ULong s390x_dirtyhelper_STCK(ULong *addr);
ULong s390x_dirtyhelper_STCKF(ULong *addr);
ULong s390x_dirtyhelper_STCKE(ULong *addr);
-ULong s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr);
void s390x_dirtyhelper_CUxy(UChar *addr, ULong data, ULong num_bytes);
ULong s390x_dirtyhelper_vec_op(VexGuestS390XState *guest_state,
ULong details);
ULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;}
#endif /* VGA_s390x */
-/*------------------------------------------------------------*/
-/*--- Dirty helper for Store Facility instruction ---*/
-/*------------------------------------------------------------*/
-#if defined(VGA_s390x)
-
-static ULong
-s390_stfle_range(UInt lo, UInt hi)
-{
- return ((1UL << (hi + 1 - lo)) - 1) << (63 - (hi % 64));
-}
-
-ULong
-s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
-{
- ULong hoststfle[S390_NUM_FACILITY_DW], cc, last_dw, i;
- register ULong reg0 asm("0") = guest_state->guest_r0;
- last_dw = reg0 & 0xf;
-
- /* Restrict to facilities that we know about and that we assume to be
- compatible with Valgrind. Of course, in this way we may reject features
- that Valgrind is not really involved in (and thus would be compatible
- with), but quering for such features doesn't seem like a typical use
- case. */
- ULong accepted_facility[S390_NUM_FACILITY_DW] = {
- /* === 0 .. 63 === */
- (s390_stfle_range(0, 16)
- /* 17: message-security-assist, not supported */
- | s390_stfle_range(18, 19)
- /* 20: HFP-multiply-and-add/subtract, not supported */
- | s390_stfle_range(21, 22)
- /* 23: HFP-unnormalized-extension, not supported */
- | s390_stfle_range(24, 25)
- /* 26: parsing-enhancement, not supported */
- | s390_stfle_range(27, 28)
- /* 29: unassigned */
- | s390_stfle_range(30, 30)
- /* 31: extract-CPU-time, not supported */
- | s390_stfle_range(32, 41)
- /* 42-43: DFP, not fully supported */
- /* 44: PFPO, not fully supported */
- | s390_stfle_range(45, 47)
- /* 48: DFP zoned-conversion, not supported */
- /* 49: includes PPA, not supported */
- /* 50: constrained transactional-execution, not supported */
- | s390_stfle_range(51, 55)
- /* 56: unassigned */
- /* 57: MSA5, not supported */
- | s390_stfle_range(58, 63)),
-
- /* === 64 .. 127 === */
- (s390_stfle_range(64, 72)
- /* 73: transactional-execution, not supported */
- | s390_stfle_range(74, 75)
- /* 76: MSA3, not supported */
- /* 77: MSA4, not supported */
- | s390_stfle_range(78, 78)
- /* 80: DFP packed-conversion, not supported */
- /* 81: PPA-in-order, not supported */
- | s390_stfle_range(82, 82)
- /* 83-127: unassigned */ ),
-
- /* === 128 .. 191 === */
- (s390_stfle_range(128, 131)
- /* 132: unassigned */
- /* 133: guarded-storage, not supported */
- /* 134: vector packed decimal, not supported */
- | s390_stfle_range(135, 135)
- /* 136: unassigned */
- /* 137: unassigned */
- | s390_stfle_range(138, 142)
- /* 143: unassigned */
- | s390_stfle_range(144, 145)
- /* 146: MSA8, not supported */
- | s390_stfle_range(147, 149)
- /* 150: unassigned */
- | s390_stfle_range(151, 151)
- /* 152: vector packed decimal enhancement, not supported */
- /* 153: unassigned */
- /* 154: unassigned */
- /* 155: MSA9, not supported */
- | s390_stfle_range(156, 156)
- /* 157-164: unassigned */
- | s390_stfle_range(165, 165)
- /* 166-167: unassigned */
- | s390_stfle_range(168, 168)
- /* 168-191: unassigned */ ),
-
- /* === 192 .. 255 === */
- /* 192: vector-packed-decimal, not supported */
- (s390_stfle_range(193, 194)
- /* 195: unassigned */
- | s390_stfle_range(196, 197)),
- };
-
- asm(".insn s,0xb2b00000,%0\n" /* stfle */
- "ipm %2\n"
- "srl %2,28\n"
- : "=Q"(hoststfle), "+d"(reg0), "=d"(cc)
- :
- : "cc");
-
- /* Update guest register 0 with what STFLE set r0 to */
- guest_state->guest_r0 = reg0;
-
- /* VM facilities = host facilities, filtered by acceptance */
- for (i = 0; i <= last_dw; ++i) {
- if (i < S390_NUM_FACILITY_DW)
- addr[i] = hoststfle[i] & accepted_facility[i];
- else
- addr[i] = 0; /* mask out any excess doublewords */
- }
-
- return cc;
-}
-
-#else
-
-ULong
-s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
-{
- return 3;
-}
-#endif /* VGA_s390x */
/*------------------------------------------------------------*/
/*--- Dirty helper for the "convert unicode" insn family. ---*/
s390_disasm(ENC2(MNM, UDXB), mnm, d2, 0, b2);
}
+static void
+s390_format_S_RD_raw(const HChar *(*irgen)(UChar b2, UShort d2),
+ UChar b2, UShort d2)
+{
+ const HChar *mnm;
+
+ mnm = irgen(b2, d2);
+
+ if (UNLIKELY(vex_traceflags & VEX_TRACE_FE))
+ s390_disasm(ENC2(MNM, UDXB), mnm, d2, 0, b2);
+}
+
static void
s390_format_SI_URD(const HChar *(*irgen)(UChar i2, IRTemp op1addr),
UChar i2, UChar b1, UShort d1)
}
static const HChar *
-s390_irgen_STFLE(IRTemp op2addr)
+s390_irgen_STFLE(UChar b2, UShort d2)
{
if (! s390_host_has_stfle) {
emulation_failure(EmFail_S390X_stfle);
return "stfle";
}
-
- IRDirty *d;
- IRTemp cc = newTemp(Ity_I64);
-
- /* IRExpr_GSPTR() => Need to pass pointer to guest state to helper */
- d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_STFLE",
- &s390x_dirtyhelper_STFLE,
- mkIRExprVec_2(IRExpr_GSPTR(), mkexpr(op2addr)));
-
- d->nFxState = 1;
- vex_bzero(&d->fxState, sizeof(d->fxState));
-
- d->fxState[0].fx = Ifx_Modify; /* read then write */
- d->fxState[0].offset = S390X_GUEST_OFFSET(guest_r0);
- d->fxState[0].size = sizeof(ULong);
-
- d->mAddr = mkexpr(op2addr);
- /* Pretend all double words are written */
- d->mSize = S390_NUM_FACILITY_DW * sizeof(ULong);
- d->mFx = Ifx_Write;
-
- stmt(IRStmt_Dirty(d));
-
- s390_cc_set(cc);
-
+ extension(S390_EXT_STFLE, b2 | (d2 << 8));
return "stfle";
}
case 0xb2a7: s390_format_RRF_M0RERE(s390_irgen_CU12, RRF3_r3(ovl),
RRF3_r1(ovl), RRF3_r2(ovl));
goto ok;
- case 0xb2b0: s390_format_S_RD(s390_irgen_STFLE, S_b2(ovl), S_d2(ovl));
+ case 0xb2b0: s390_format_S_RD_raw(s390_irgen_STFLE, S_b2(ovl), S_d2(ovl));
goto ok;
case 0xb2b1: /* STFL */ goto unimplemented;
case 0xb2b2: /* LPSWE */ goto unimplemented;
#define S390_EXT_PRNO 1
#define S390_EXT_NNPA 2
#define S390_EXT_DFLT 3
+#define S390_EXT_STFLE 4
/*--------------------------------------------------------------*/
/*--- Miscellaneous ---*/
unsigned __int128 pair;
};
-#define S390_SETBIT(x) (1UL << (63 - (x % 64)))
+#define S390_SETBIT(x) (1UL << (63 - (x % 64)))
+#define S390_SETBITS(lo, hi) (((1UL << (hi + 1 - lo)) - 1) << (63 - (hi % 64)))
/* Helper routine for query functions: Filter the bit vector `fc' using a given
`filter' vector */
return ExtErr_OK;
}
+/*---------------------------------------------------------------*/
+/*--- STFLE (store facility list extended) ---*/
+/*---------------------------------------------------------------*/
+
+static enum ExtensionError do_extension_STFLE(ThreadState* tst, ULong variant)
+{
+ Int cc = 0;
+ UChar b2 = variant & 0xf;
+ UShort d2 = (variant >> 8) & 0xfff;
+ ULong gpr0 = READ_GPR(tst, "STFLE(r0)", 0);
+ ULong last_dw = gpr0 & 0xff;
+ ULong addr = READ_GPR(tst, "STFLE(b2)", b2) + d2;
+
+ PRE_MEM_WRITE(tst, "STFLE(bits)", addr, (last_dw + 1) * sizeof(ULong));
+ static const ULong accepted_facility[] = {
+ /* === 0 .. 63 === */
+ (S390_SETBITS(0, 16)
+ /* 17: message-security-assist, not supported */
+ | S390_SETBITS(18, 19)
+ /* 20: HFP-multiply-and-add/subtract, not supported */
+ | S390_SETBITS(21, 22)
+ /* 23: HFP-unnormalized-extension, not supported */
+ | S390_SETBITS(24, 25)
+ /* 26: parsing-enhancement, not supported */
+ | S390_SETBITS(27, 28)
+ /* 29: unassigned */
+ | S390_SETBITS(30, 30)
+ /* 31: extract-CPU-time, not supported */
+ | S390_SETBITS(32, 41)
+ /* 42-43: DFP, not fully supported */
+ /* 44: PFPO, not fully supported */
+ | S390_SETBITS(45, 47)
+ /* 48: DFP zoned-conversion, not supported */
+ /* 49: includes PPA, not supported */
+ /* 50: constrained transactional-execution, not supported */
+ | S390_SETBITS(51, 55)
+ /* 56: unassigned */
+ /* 57: MSA5, not supported */
+ | S390_SETBITS(58, 63)),
+
+ /* === 64 .. 127 === */
+ (S390_SETBITS(64, 72)
+ /* 73: transactional-execution, not supported */
+ | S390_SETBITS(74, 75)
+ /* 76: MSA3, not supported */
+ /* 77: MSA4, not supported */
+ | S390_SETBITS(78, 78)
+ /* 80: DFP packed-conversion, not supported */
+ /* 81: PPA-in-order, not supported */
+ | S390_SETBITS(82, 82)
+ /* 83-127: unassigned */),
+
+ /* === 128 .. 191 === */
+ (S390_SETBITS(128, 131)
+ /* 132: unassigned */
+ /* 133: guarded-storage, not supported */
+ /* 134: vector packed decimal, not supported */
+ | S390_SETBITS(135, 135)
+ /* 136: unassigned */
+ /* 137: unassigned */
+ | S390_SETBITS(138, 142)
+ /* 143: unassigned */
+ | S390_SETBITS(144, 145)
+ /* 146: MSA8, not supported */
+ | S390_SETBITS(147, 149)
+ /* 150: unassigned */
+ | S390_SETBITS(151, 151)
+ /* 152: vector packed decimal enhancement, not supported */
+ /* 153: unassigned */
+ /* 154: unassigned */
+ /* 155: MSA9, not supported */
+ | S390_SETBITS(156, 156)
+ /* 157-164: unassigned */
+ | S390_SETBITS(165, 165)
+ /* 166-167: unassigned */
+ | S390_SETBITS(168, 168)
+ /* 168-191: unassigned */),
+
+ /* === 192 .. 255 === */
+ /* 192: vector-packed-decimal, not supported */
+ (S390_SETBITS(193, 194)
+ /* 195: unassigned */
+ | S390_SETBITS(196, 197)),
+ };
+ asm("lgr 0,%[r0]\n"
+ ".insn s,0xb2b00000,%[out]\n" /* stfle */
+ "lgr %[r0],0\n"
+ "ipm %[cc]\n"
+ "srl %[cc],28\n"
+ : [out] "=Q"(*(ULong(*)[last_dw + 1])(void*)addr), [r0] "+d"(gpr0),
+ [cc] "=d"(cc)
+ :
+ : "cc");
+
+ WRITE_GPR(tst, 0, gpr0);
+ if (last_dw > (gpr0 & 0xff))
+ last_dw = gpr0 & 0xff;
+ s390_filter_functions((ULong*)addr, (last_dw + 1) * sizeof(ULong),
+ accepted_facility, sizeof(accepted_facility));
+ POST_MEM_WRITE(tst, addr, (last_dw + 1) * sizeof(ULong));
+
+ WRITE_CC(tst, cc);
+ return ExtErr_OK;
+}
+
/*---------------------------------------------------------------*/
/*--- Main function: select and call appropriate extension ---*/
/*---------------------------------------------------------------*/
return do_extension_NNPA(tst, variant);
case S390_EXT_DFLT:
return do_extension_DFLTCC(tst, variant);
+ case S390_EXT_STFLE:
+ return do_extension_STFLE(tst, variant);
default:
VG_(core_panic)("unknown extension ID");
}