]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Support the STFLE instruction via a dirty helper.
authorFlorian Krohm <florian@eich-krohm.de>
Mon, 11 Jul 2011 01:48:02 +0000 (01:48 +0000)
committerFlorian Krohm <florian@eich-krohm.de>
Mon, 11 Jul 2011 01:48:02 +0000 (01:48 +0000)
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

VEX/priv/guest_s390_defs.h
VEX/priv/guest_s390_helpers.c
VEX/priv/guest_s390_toIR.c
VEX/pub/libvex_s390x_common.h

index ddcccd8eddb51e61bb99a1837d68ce0e1e480e02..733902481c845623eff6a9989a55c2da17137e23 100644 (file)
@@ -78,7 +78,7 @@ void s390x_dirtyhelper_EX(ULong torun);
 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 {
index e01d978feb1ead6799aa54d4d8c8db78b6fe6760..ff48771d2d2934d01ffdf03694ff7df3d1edebb6 100644 (file)
@@ -35,6 +35,7 @@
 #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"
@@ -277,6 +278,46 @@ ULong s390x_dirtyhelper_STCKF(ULong *addr) {return 3;}
 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.                           ---*/
 /*------------------------------------------------------------*/
index 75b38e96f2aadaecd0cfd1e6bee35f69a52cdc23..2849665a4d523e4dc2c6a14fcfd9cc99b957ffba 100644 (file)
@@ -37,7 +37,7 @@
 #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 */
@@ -10558,6 +10558,35 @@ s390_irgen_STCKE(IRTemp op2addr)
    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                    ---*/
 /*------------------------------------------------------------*/
@@ -10994,7 +11023,8 @@ s390_decode_4byte_and_irgen(UChar *bytes)
    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;
index 7aa598883843b8ae2987298ae803253547d13fa9..f23bc9c5b23e89833716cd2ef6bd0257992e9142 100644 (file)
@@ -82,6 +82,9 @@
 /* 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 */
 
 /*--------------------------------------------------------------------*/