Support conditional load and store for s390x (VEX side).
Fixes #269209.  (Christian Borntraeger, borntraeger@de.ibm.com)


git-svn-id: svn://svn.valgrind.org/vex/trunk@2121 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest_s390_toIR.c b/priv/guest_s390_toIR.c
index fdd2cf4..4537fc5 100644
--- a/priv/guest_s390_toIR.c
+++ b/priv/guest_s390_toIR.c
@@ -1564,6 +1564,16 @@
 }
 
 static void
+s390_format_RRF_U0RR(HChar *(*irgen)(UChar m3, UChar r1, UChar r2),
+                     UChar m3, UChar r1, UChar r2, Int xmnm_kind)
+{
+   irgen(m3, r1, r2);
+
+   if (unlikely(vex_traceflags & VEX_TRACE_FE))
+      s390_disasm(ENC3(XMNM, GPR, GPR), xmnm_kind, m3, r1, r2);
+}
+
+static void
 s390_format_RRF_U0RF(HChar *(*irgen)(UChar r3, UChar r1, UChar r2),
                      UChar r3, UChar r1, UChar r2)
 {
@@ -1739,6 +1749,26 @@
 }
 
 static void
+s390_format_RSY_RDRM(HChar *(*irgen)(UChar r1, IRTemp op2addr),
+                     UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2,
+                     Int xmnm_kind)
+{
+   IRTemp op2addr = newTemp(Ity_I64);
+   IRTemp d2 = newTemp(Ity_I64);
+
+   if_condition_goto(binop(Iop_CmpEQ32, s390_call_calculate_cond(m3), mkU32(0)),
+                     guest_IA_next_instr);
+   assign(d2, mkU64(((ULong)(Long)(Char)dh2 << 12) | ((ULong)dl2)));
+   assign(op2addr, binop(Iop_Add64, mkexpr(d2), b2 != 0 ? get_gpr_dw0(b2) :
+          mkU64(0)));
+
+   irgen(r1, op2addr);
+
+   if (unlikely(vex_traceflags & VEX_TRACE_FE))
+      s390_disasm(ENC3(XMNM, GPR, SDXB), xmnm_kind, m3, r1, dh2, dl2, 0, b2);
+}
+
+static void
 s390_format_RX(HChar *(*irgen)(UChar r1, UChar x2, UChar b2, UShort d2,
                IRTemp op2addr),
                UChar r1, UChar x2, UChar b2, UShort d2)
@@ -5755,6 +5785,44 @@
 }
 
 static HChar *
+s390_irgen_LOCR(UChar m3, UChar r1, UChar r2)
+{
+   if_condition_goto(binop(Iop_CmpEQ32, s390_call_calculate_cond(m3), mkU32(0)),
+                     guest_IA_next_instr);
+   put_gpr_w1(r1, get_gpr_w1(r2));
+
+   return "locr";
+}
+
+static HChar *
+s390_irgen_LOCGR(UChar m3, UChar r1, UChar r2)
+{
+   if_condition_goto(binop(Iop_CmpEQ32, s390_call_calculate_cond(m3), mkU32(0)),
+                     guest_IA_next_instr);
+   put_gpr_dw0(r1, get_gpr_dw0(r2));
+
+   return "locgr";
+}
+
+static HChar *
+s390_irgen_LOC(UChar r1, IRTemp op2addr)
+{
+   /* condition is checked in format handler */
+   put_gpr_w1(r1, load(Ity_I32, mkexpr(op2addr)));
+
+   return "loc";
+}
+
+static HChar *
+s390_irgen_LOCG(UChar r1, IRTemp op2addr)
+{
+   /* condition is checked in format handler */
+   put_gpr_dw0(r1, load(Ity_I64, mkexpr(op2addr)));
+
+   return "locg";
+}
+
+static HChar *
 s390_irgen_LPQ(UChar r1, IRTemp op2addr)
 {
    put_gpr_dw0(r1, load(Ity_I64, mkexpr(op2addr)));
@@ -7164,6 +7232,24 @@
 }
 
 static HChar *
+s390_irgen_STOC(UChar r1, IRTemp op2addr)
+{
+   /* condition is checked in format handler */
+   store(mkexpr(op2addr), get_gpr_w1(r1));
+
+   return "stoc";
+}
+
+static HChar *
+s390_irgen_STOCG(UChar r1, IRTemp op2addr)
+{
+   /* condition is checked in format handler */
+   store(mkexpr(op2addr), get_gpr_dw0(r1));
+
+   return "stocg";
+}
+
+static HChar *
 s390_irgen_STPQ(UChar r1, IRTemp op2addr)
 {
    store(mkexpr(op2addr), get_gpr_dw0(r1));
@@ -11276,7 +11362,9 @@
    case 0xb9df: s390_format_RRE_RR(s390_irgen_CLHLR, ovl.fmt.RRE.r1,
                                    ovl.fmt.RRE.r2);  goto ok;
    case 0xb9e1: /* POPCNT */ goto unimplemented;
-   case 0xb9e2: /* LOCGR */ goto unimplemented;
+   case 0xb9e2: s390_format_RRF_U0RR(s390_irgen_LOCGR, ovl.fmt.RRF3.r3,
+                                     ovl.fmt.RRF3.r1, ovl.fmt.RRF3.r2,
+                                     S390_XMNM_LOCGR);  goto ok;
    case 0xb9e4: s390_format_RRF_R0RR2(s390_irgen_NGRK, ovl.fmt.RRF4.r3,
                                       ovl.fmt.RRF4.r1, ovl.fmt.RRF4.r2);
                                       goto ok;
@@ -11298,7 +11386,9 @@
    case 0xb9eb: s390_format_RRF_R0RR2(s390_irgen_SLGRK, ovl.fmt.RRF4.r3,
                                       ovl.fmt.RRF4.r1, ovl.fmt.RRF4.r2);
                                       goto ok;
-   case 0xb9f2: /* LOCR */ goto unimplemented;
+   case 0xb9f2: s390_format_RRF_U0RR(s390_irgen_LOCR, ovl.fmt.RRF3.r3,
+                                     ovl.fmt.RRF3.r1, ovl.fmt.RRF3.r2,
+                                     S390_XMNM_LOCR);  goto ok;
    case 0xb9f4: s390_format_RRF_R0RR2(s390_irgen_NRK, ovl.fmt.RRF4.r3,
                                       ovl.fmt.RRF4.r1, ovl.fmt.RRF4.r2);
                                       goto ok;
@@ -12185,8 +12275,16 @@
                                                 ovl.fmt.RSY.r3, ovl.fmt.RSY.b2,
                                                 ovl.fmt.RSY.dl2,
                                                 ovl.fmt.RSY.dh2);  goto ok;
-   case 0xeb00000000e2ULL: /* LOCG */ goto unimplemented;
-   case 0xeb00000000e3ULL: /* STOCG */ goto unimplemented;
+   case 0xeb00000000e2ULL: s390_format_RSY_RDRM(s390_irgen_LOCG, ovl.fmt.RSY.r1,
+                                                ovl.fmt.RSY.r3, ovl.fmt.RSY.b2,
+                                                ovl.fmt.RSY.dl2,
+                                                ovl.fmt.RSY.dh2,
+                                                S390_XMNM_LOCG);  goto ok;
+   case 0xeb00000000e3ULL: s390_format_RSY_RDRM(s390_irgen_STOCG,
+                                                ovl.fmt.RSY.r1, ovl.fmt.RSY.r3,
+                                                ovl.fmt.RSY.b2, ovl.fmt.RSY.dl2,
+                                                ovl.fmt.RSY.dh2,
+                                                S390_XMNM_STOCG);  goto ok;
    case 0xeb00000000e4ULL: s390_format_RSY_RRRD(s390_irgen_LANG, ovl.fmt.RSY.r1,
                                                 ovl.fmt.RSY.r3, ovl.fmt.RSY.b2,
                                                 ovl.fmt.RSY.dl2,
@@ -12207,8 +12305,16 @@
                                                 ovl.fmt.RSY.r1, ovl.fmt.RSY.r3,
                                                 ovl.fmt.RSY.b2, ovl.fmt.RSY.dl2,
                                                 ovl.fmt.RSY.dh2);  goto ok;
-   case 0xeb00000000f2ULL: /* LOC */ goto unimplemented;
-   case 0xeb00000000f3ULL: /* STOC */ goto unimplemented;
+   case 0xeb00000000f2ULL: s390_format_RSY_RDRM(s390_irgen_LOC, ovl.fmt.RSY.r1,
+                                                ovl.fmt.RSY.r3, ovl.fmt.RSY.b2,
+                                                ovl.fmt.RSY.dl2,
+                                                ovl.fmt.RSY.dh2, S390_XMNM_LOC);
+                                                goto ok;
+   case 0xeb00000000f3ULL: s390_format_RSY_RDRM(s390_irgen_STOC, ovl.fmt.RSY.r1,
+                                                ovl.fmt.RSY.r3, ovl.fmt.RSY.b2,
+                                                ovl.fmt.RSY.dl2,
+                                                ovl.fmt.RSY.dh2,
+                                                S390_XMNM_STOC);  goto ok;
    case 0xeb00000000f4ULL: s390_format_RSY_RRRD(s390_irgen_LAN, ovl.fmt.RSY.r1,
                                                 ovl.fmt.RSY.r3, ovl.fmt.RSY.b2,
                                                 ovl.fmt.RSY.dl2,