/none/tests/s390x/ecag
/none/tests/s390x/bfp-306054
/none/tests/s390x/bfp-arith
+/none/tests/s390x/bfp-diint
/none/tests/s390x/bfp-load
/none/tests/s390x/bfp-fpc
/none/tests/s390x/bfp-tdc
void s390x_dirtyhelper_CUxy(UChar *addr, ULong data, ULong num_bytes);
ULong s390x_dirtyhelper_vec_op(VexGuestS390XState *guest_state,
ULong details);
+ULong s390x_dirtyhelper_DIxBR(VexGuestS390XState *guest_state, ULong packed);
ULong s390_do_cu12_cu14_helper1(UInt byte1, UInt etf3_and_m3_is_1);
ULong s390_do_cu12_helper2(UInt byte1, UInt byte2, UInt byte3, UInt byte4,
ULong stuff);
#endif
+/*------------------------------------------------------------*/
+/*--- Dirty helper for DIEBR/DIDBR instructions ---*/
+/*------------------------------------------------------------*/
+
+#if defined(VGA_s390x)
+
+ULong
+s390x_dirtyhelper_DIxBR(VexGuestS390XState *guest_state, ULong args)
+{
+ UInt r1 = (args >> 0) & 0xf;
+ UInt r2 = (args >> 4) & 0xf;
+ UInt r3 = (args >> 8) & 0xf;
+ UInt m4 = (args >> 12) & 0xf;
+ UInt op = (args >> 16) & 0xffff;
+ UInt cc;
+
+ V128* gv = &guest_state->guest_v0;
+
+ /* DIEBR/DIDBR instruction to be targeted by EX */
+ UInt insn = (op << 16) | (4u << 12) | ((UInt)m4 << 8) | (0u << 4) | 2u;
+
+ __asm__("ld %%f0, %[op1]\n\t"
+ "ld %%f2, %[op2]\n\t"
+ "ld %%f4, %[op3]\n\t"
+ "ex %%r0, %[insn]\n\t"
+ "std %%f0, %[op1]\n\t"
+ "std %%f4, %[op3]\n\t"
+ "ipm %[cc]\n\t"
+ : [op1] "+R"(gv[r1]), [op3] "=R"(gv[r3]), [cc] "=d"(cc)
+ : [op2] "R"(gv[r2]), [insn] "R"(insn)
+ : "cc", "f0", "f2", "f4");
+
+ return cc >> 28;
+}
+
+#else
+
+ULong
+s390x_dirtyhelper_DIxBR(VexGuestS390XState *guest_state, ULong packed)
+{ return 0; }
+
+#endif
+
/*---------------------------------------------------------------*/
/*--- end guest_s390_helpers.c ---*/
/*---------------------------------------------------------------*/
put_fpr_pair(r1, unop(Iop_F32toF128, mkexpr(op)));
}
+
+static void
+s390_irgen_DIxBR(UChar r1, UChar r3, UChar r2, UChar m4, ULong op)
+{
+ s390_insn_assert(is_valid_rounding_mode(m4));
+ IRTemp cc = newTemp(Ity_I64);
+ ULong args = (op << 16) | ((ULong)m4 << 12) | ((ULong)r3 << 8) |
+ ((ULong)r2 << 4) | (ULong)r1;
+ IRDirty* d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_DIxBR",
+ &s390x_dirtyhelper_DIxBR,
+ mkIRExprVec_2(IRExpr_GSPTR(), mkU64(args)));
+ d->nFxState = 3;
+ vex_bzero(&d->fxState, sizeof(d->fxState));
+ d->fxState[0].fx = Ifx_Read;
+ d->fxState[0].offset = fpr_w0_offset(r2);
+ d->fxState[0].size = sizeof(UInt);
+ d->fxState[1].fx = Ifx_Modify;
+ d->fxState[1].offset = fpr_w0_offset(r1);
+ d->fxState[1].size = sizeof(UInt);
+ d->fxState[2].fx = Ifx_Write;
+ d->fxState[2].offset = fpr_w0_offset(r3);
+ d->fxState[2].size = sizeof(UInt);
+ stmt(IRStmt_Dirty(d));
+ s390_cc_set(cc);
+}
+
+static void
+s390_irgen_DIEBR(UChar r1, UChar r3, UChar r2, UChar m4)
+{
+ s390_irgen_DIxBR(r1, r3, r2, m4, 0xb353);
+}
+
+static void
+s390_irgen_DIDBR(UChar r1, UChar r3, UChar r2, UChar m4)
+{
+ s390_irgen_DIxBR(r1, r3, r2, m4, 0xb35b);
+}
+
static void
s390_irgen_FIEBRA(UChar m3, UChar m4, UChar r1, UChar r2)
{
goto ok;
case 0xb350: /* TBEDR */ goto unimplemented;
case 0xb351: /* TBDR */ goto unimplemented;
- case 0xb353: /* DIEBR */ goto unimplemented;
+ case 0xb353: s390_irgen_DIEBR(RRFb_r1(ovl), RRFb_r3(ovl), RRFb_r2(ovl),
+ RRFb_m4(ovl));
+ goto ok;
case 0xb357: s390_irgen_FIEBRA(RRFe_m3(ovl), RRFe_m4(ovl), RRFe_r1(ovl),
RRFe_r2(ovl));
goto ok;
case 0xb358: /* THDER */ goto unimplemented;
case 0xb359: /* THDR */ goto unimplemented;
- case 0xb35b: /* DIDBR */ goto unimplemented;
+ case 0xb35b: s390_irgen_DIDBR(RRFb_r1(ovl), RRFb_r3(ovl), RRFb_r2(ovl),
+ RRFb_m4(ovl));
+ goto ok;
case 0xb35f: s390_irgen_FIDBRA(RRFe_m3(ovl), RRFe_m4(ovl), RRFe_r1(ovl),
RRFe_r2(ovl));
goto ok;
ddb,"divide long bfp",implemented,
debr,"divide short bfp",implemented,
deb,"divide short bfp",implemented,
-didbr,"divide to integer long bfp","not implemented",
-diebr,"divide to integer short bfp","not implemented",
+didbr,"divide to integer long bfp",implemented,
+diebr,"divide to integer short bfp",implemented,
efpc,"extract fpc",implemented,
ltxbr,"load and test extended bfp",implemented,
ltdbr,"load and test long bfp",implemented,
cs csg cds cdsg cu21 cu21_1 cu24 cu24_1 cu42 cu12 cu12_1 \
ex_sig ex_clone cu14 cu14_1 cu41 ecag \
bfp-fpc bfp-306054 \
- bfp-muldiv comp-1 comp-2 exrl tmll tm stmg \
+ bfp-muldiv bfp-diint comp-1 comp-2 exrl tmll tm stmg \
ex clst mvc test_fork test_sig rxsbg popcnt popcnt-mi3 \
high-word traps \
spechelper-alr spechelper-algr \
--- /dev/null
+/* Test "divide to integer" instructions. */
+
+#include <math.h>
+#include <stdio.h>
+
+#define GEN_DIXBR(insn, type, m4) \
+ static void insn##_##m4(type dividend, type divisor) \
+ { \
+ type op1 = dividend; \
+ type op2 = divisor; \
+ type op3; \
+ unsigned cc; \
+ \
+ __asm__(#insn " %[r1],%[r3],%[r2]," #m4 "\n\t" \
+ "ipm %[cc]\n\t" \
+ "srl %[cc],28\n\t" \
+ : [r1] "+&f"(op1), [r3] "=&f"(op3), [cc] "=d"(cc) \
+ : [r2] "f"(op2) \
+ : "cc"); \
+ printf("\t%g / %g = %g rem=%g cc=%u\n", dividend, divisor, op3, op1, \
+ cc); \
+ }
+
+GEN_DIXBR(diebr, float, 5);
+GEN_DIXBR(didbr, double, 1);
+GEN_DIXBR(didbr, double, 4);
+GEN_DIXBR(didbr, double, 5);
+GEN_DIXBR(didbr, double, 6);
+
+static const double data[][2] = {{7, 2}, {-6, 2}, {-5, INFINITY},
+ {INFINITY, 3}, {5, 0}, {NAN, 3},
+ {3, NAN}, {1.5e-45, 1}, {5, 1e-40}};
+
+enum { n_data = sizeof(data) / sizeof(data[0]) };
+
+int main(void)
+{
+ puts("diebr (m4=5)");
+ for (int i = 0; i < n_data; i++)
+ diebr_5(data[i][0], data[i][1]);
+
+ puts("didbr (m4=5)");
+ for (int i = 0; i < n_data; i++)
+ didbr_5(data[i][0], data[i][1]);
+
+ puts("didbr (m4=1)"); /* ties away from zero */
+ didbr_1(5, 2);
+ didbr_1(-5, 2);
+ puts("didbr (m4=4)"); /* ties to even */
+ didbr_4(7, 4);
+ didbr_4(5, 2);
+ puts("didbr (m4=6)"); /* toward +inf */
+ didbr_6(5, 2);
+ didbr_6(5, -2);
+
+ return 0;
+}
--- /dev/null
+diebr (m4=5)
+ 7 / 2 = 3 rem=1 cc=0
+ -6 / 2 = -3 rem=-0 cc=0
+ -5 / inf = -0 rem=-5 cc=0
+ inf / 3 = nan rem=nan cc=1
+ 5 / 0 = nan rem=nan cc=1
+ nan / 3 = nan rem=nan cc=1
+ 3 / nan = nan rem=nan cc=1
+ 1.4013e-45 / 1 = 0 rem=1.4013e-45 cc=0
+ 5 / 9.99995e-41 = 7.9655e-18 rem=3.24493e-07 cc=3
+didbr (m4=5)
+ 7 / 2 = 3 rem=1 cc=0
+ -6 / 2 = -3 rem=-0 cc=0
+ -5 / inf = -0 rem=-5 cc=0
+ inf / 3 = nan rem=nan cc=1
+ 5 / 0 = nan rem=nan cc=1
+ nan / 3 = nan rem=nan cc=1
+ 3 / nan = nan rem=nan cc=1
+ 1.5e-45 / 1 = 0 rem=1.5e-45 cc=0
+ 5 / 1e-40 = 5e+40 rem=3.22535e-16 cc=2
+didbr (m4=1)
+ 5 / 2 = 3 rem=-1 cc=0
+ -5 / 2 = -3 rem=1 cc=0
+didbr (m4=4)
+ 7 / 4 = 2 rem=-1 cc=0
+ 5 / 2 = 2 rem=1 cc=0
+didbr (m4=6)
+ 5 / 2 = 3 rem=-1 cc=0
+ 5 / -2 = -2 rem=1 cc=0
--- /dev/null
+prog: bfp-diint
+vgopts: -q
test_insn("ddbr %f0,%f1");
test_insn("dxbr %f0,%f1");
- # echo "DIVIDE TO INTEGER" not implemented
+ # echo "DIVIDE TO INTEGER" implemented via dirty helper
# echo "LOAD AND TEST" insn not mapped one-to-one
header("LOAD COMPLEMENT");
Looking for missed specification exceptions
-Total: 43957 tests generated
-Total: 43957 specification exceptions
+Total: 43975 tests generated
+Total: 43975 specification exceptions
Looking for unexpected specification exceptions
-Total: 154451 tests generated
+Total: 154465 tests generated
Total: 0 specification exceptions
"dxbr f1:{0,1,4,5,8,9,12,13},f2:{0,1,4,5,8,9,12,13}",
"deb f1,d12(x2,b2)",
"ddb f1,d12(x2,b2)",
- // diebr not implemented
- // didbr not implemented
+ "diebr f1,f3,f2,m4:{0,1,3,4,5,6,7}",
+ "didbr f1,f3,f2,m4:{0,1,3,4,5,6,7}",
"ltebr f1,f2",
"ltdbr f1,f2",
"ltxbr f1:{0,1,4,5,8,9,12,13},f2:{0,1,4,5,8,9,12,13}",