VEX-side changes to fix bug #271776.
Patch provided by Divya Vyas <divyvyas@linux.vnet.ibm.com>
git-svn-id: svn://svn.valgrind.org/vex/trunk@2171
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, HWord addr);
/* The various ways to compute the condition code. */
enum {
#include "libvex_guest_s390x.h"
#include "libvex_ir.h"
#include "libvex.h"
+#include "libvex_s390x_common.h"
#include "main_util.h"
#include "guest_generic_bb_to_IR.h"
ULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;}
#endif /* VGA_s390x */
+/*------------------------------------------------------------*/
+/*--- Dirty helper for Store Facility instruction ---*/
+/*------------------------------------------------------------*/
+#if defined(VGA_s390x)
+ULong
+s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, HWord addr)
+{
+ ULong hoststfle[S390_NUM_FACILITY_DW], cc, num_dw, i;
+ register ULong reg0 asm("0") = guest_state->guest_r0 & 0xF; /* r0[56:63] */
+
+ /* We cannot store more than S390_NUM_FACILITY_DW
+ (and it makes not much sense to do so anyhow) */
+ if (reg0 > S390_NUM_FACILITY_DW - 1)
+ reg0 = S390_NUM_FACILITY_DW - 1;
+
+ num_dw = reg0 + 1; /* number of double words written */
+
+ asm volatile(" .insn s,0xb2b00000,%0\n" /* stfle */
+ "ipm %2\n"
+ "srl %2,28\n"
+ : "=m" (hoststfle), "+d"(reg0), "=d"(cc) : : "cc", "memory");
+
+ /* Update guest register 0 with what STFLE set r0 to */
+ guest_state->guest_r0 = reg0;
+
+ for (i = 0; i < num_dw; ++i)
+ ((ULong *)addr)[i] = hoststfle[i];
+
+ return cc;
+}
+
+#else
+
+ULong
+s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, HWord addr)
+{
+ return 3;
+}
+#endif /* VGA_s390x */
+
/*------------------------------------------------------------*/
/*--- Helper for condition code. ---*/
/*------------------------------------------------------------*/
#include "libvex_guest_s390x.h" /* VexGuestS390XState */
#include "libvex.h" /* needed for bb_to_IR.h */
#include "libvex_guest_offsets.h" /* OFFSET_s390x_SYSNO */
-
+#include "libvex_s390x_common.h"
#include "main_util.h" /* vassert */
#include "main_globals.h" /* vex_traceflags */
#include "guest_generic_bb_to_IR.h" /* DisResult */
return "stcke";
}
+static HChar *
+s390_irgen_STFLE(IRTemp op2addr)
+{
+ IRDirty *d;
+ IRTemp cc = newTemp(Ity_I64);
+
+ d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_STFLE",
+ &s390x_dirtyhelper_STFLE,
+ mkIRExprVec_1(mkexpr(op2addr)));
+
+ d->needsBBP = 1; /* Need to pass pointer to guest state to helper */
+
+ 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->nFxState = 1;
+
+ 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_thunk_fill(mkU64(S390_CC_OP_SET), mkexpr(cc), mkU64(0), mkU64(0));
+
+ return "stfle";
+}
+
/*------------------------------------------------------------*/
/*--- Build IR for special instructions ---*/
/*------------------------------------------------------------*/
case 0xb2a5: /* TRE */ goto unimplemented;
case 0xb2a6: /* CU21 */ goto unimplemented;
case 0xb2a7: /* CU12 */ goto unimplemented;
- case 0xb2b0: /* STFLE */ goto unimplemented;
+ case 0xb2b0: s390_format_S_RD(s390_irgen_STFLE, ovl.fmt.S.b2, ovl.fmt.S.d2);
+ goto ok;
case 0xb2b1: /* STFL */ goto unimplemented;
case 0xb2b2: /* LPSWE */ goto unimplemented;
case 0xb2b8: /* SRNMB */ goto unimplemented;
/* Number of arguments that can be passed in registers */
#define S390_NUM_GPRPARMS 5
+/* Number of double words needed to store all facility bits. */
+#define S390_NUM_FACILITY_DW 2
+
#endif /* __LIBVEX_PUB_S390X_H */
/*--------------------------------------------------------------------*/