Generalise S390_INSN_GZERO which only worked on the guest
state to S390_INSN_MZERO which works for any memory location
addressable with base reg + 12-bit displacement.


git-svn-id: svn://svn.valgrind.org/vex/trunk@2587 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/host_s390_defs.c b/priv/host_s390_defs.c
index ef79095..91a201f 100644
--- a/priv/host_s390_defs.c
+++ b/priv/host_s390_defs.c
@@ -714,8 +714,11 @@
       }
       break;
 
+   case S390_INSN_MZERO:
+      s390_amode_get_reg_usage(u, insn->variant.mzero.dst);
+      break;
+
    case S390_INSN_MFENCE:
-   case S390_INSN_GZERO:
    case S390_INSN_GADD:
       break;
 
@@ -963,8 +966,11 @@
       }
       break;
 
+   case S390_INSN_MZERO:
+      s390_amode_map_regs(m, insn->variant.mzero.dst);
+      break;
+
    case S390_INSN_MFENCE:
-   case S390_INSN_GZERO:
    case S390_INSN_GADD:
       break;
 
@@ -5078,13 +5084,17 @@
 
 
 s390_insn *
-s390_insn_gzero(UChar size, UInt offset)
+s390_insn_mzero(UChar size, s390_amode *dst)
 {
    s390_insn *insn = LibVEX_Alloc(sizeof(s390_insn));
 
-   insn->tag  = S390_INSN_GZERO;
+   /* This insn will be mapped to an XC so we can only allow base register
+      plus 12-bit displacement */
+   vassert(dst->tag == S390_AMODE_B12);
+
+   insn->tag  = S390_INSN_MZERO;
    insn->size = size;
-   insn->variant.gzero.offset = offset;
+   insn->variant.mzero.dst = dst;
 
    return insn;
 }
@@ -5643,8 +5653,8 @@
       s390_sprintf(buf, "%M", "v-mfence");
       return buf;   /* avoid printing "size = ..." which is meaningless */
 
-   case S390_INSN_GZERO:
-      s390_sprintf(buf, "%M %G", "v-gzero", insn->variant.gzero.offset);
+   case S390_INSN_MZERO:
+      s390_sprintf(buf, "%M %A", "v-mzero", insn->variant.mzero.dst);
       break;
 
    case S390_INSN_GADD:
@@ -7788,11 +7798,11 @@
 
 
 static UChar *
-s390_insn_gzero_emit(UChar *buf, const s390_insn *insn)
+s390_insn_mzero_emit(UChar *buf, const s390_insn *insn)
 {
-   return s390_emit_XC(buf, insn->size - 1,
-                       S390_REGNO_GUEST_STATE_POINTER, insn->variant.gzero.offset,
-                       S390_REGNO_GUEST_STATE_POINTER, insn->variant.gzero.offset);
+   s390_amode *am = insn->variant.mzero.dst;
+
+   return s390_emit_XC(buf, insn->size - 1, am->b, am->d, am->b, am->d);
 }
 
 
@@ -8377,8 +8387,8 @@
       end = s390_insn_mfence_emit(buf, insn);
       break;
 
-   case S390_INSN_GZERO:
-      end = s390_insn_gzero_emit(buf, insn);
+   case S390_INSN_MZERO:
+      end = s390_insn_mzero_emit(buf, insn);
       break;
 
    case S390_INSN_GADD:
diff --git a/priv/host_s390_defs.h b/priv/host_s390_defs.h
index 2a24d5c..2e93b2f 100644
--- a/priv/host_s390_defs.h
+++ b/priv/host_s390_defs.h
@@ -139,7 +139,7 @@
    S390_INSN_BFP_CONVERT,
    S390_INSN_DFP_BINOP, /* Decimal floating point */
    S390_INSN_MFENCE,
-   S390_INSN_GZERO,   /* Assign zero to a guest register */
+   S390_INSN_MZERO,   /* Assign zero to a memory location */
    S390_INSN_GADD,    /* Add a value to a guest register */
    S390_INSN_SET_FPC_BFPRM, /* Set the bfp rounding mode in the FPC */
    S390_INSN_SET_FPC_DFPRM, /* Set the dfp rounding mode in the FPC */
@@ -510,8 +510,8 @@
 
       /* Miscellaneous */
       struct {
-         UInt             offset;
-      } gzero;
+         s390_amode      *dst;
+      } mzero;
       struct {
          UInt             offset;
          UChar            delta;
@@ -616,7 +616,7 @@
                                HReg op2, HReg op3,
                                s390_dfp_round_t rounding_mode);
 s390_insn *s390_insn_mfence(void);
-s390_insn *s390_insn_gzero(UChar size, UInt offset);
+s390_insn *s390_insn_mzero(UChar size, s390_amode *dst);
 s390_insn *s390_insn_gadd(UChar size, UInt offset, UChar delta, ULong value);
 s390_insn *s390_insn_set_fpc_bfprm(UChar size, HReg mode);
 s390_insn *s390_insn_set_fpc_dfprm(UChar size, HReg mode);
diff --git a/priv/host_s390_isel.c b/priv/host_s390_isel.c
index f5010a4..0289baf 100644
--- a/priv/host_s390_isel.c
+++ b/priv/host_s390_isel.c
@@ -2564,6 +2564,11 @@
       case Ity_I16:
       case Ity_I32:
       case Ity_I64:
+         if (am->tag == S390_AMODE_B12 &&
+             s390_expr_is_const_zero(stmt->Ist.Store.data)) {
+            addInstr(env, s390_insn_mzero(sizeofIRType(tyd), am));
+            return;
+         }
          src = s390_isel_int_expr(env, stmt->Ist.Store.data);
          break;
 
@@ -2649,7 +2654,8 @@
 
       /* guest register = 0 */
       if (new_value == 0) {
-         addInstr(env, s390_insn_gzero(sizeofIRType(tyd), offset));
+         am = s390_amode_for_guest_state(offset);
+         addInstr(env, s390_insn_mzero(sizeofIRType(tyd), am));
          return;
       }
 
@@ -2689,6 +2695,11 @@
       case Ity_I16:
       case Ity_I32:
       case Ity_I64:
+         if (am->tag == S390_AMODE_B12 &&
+             s390_expr_is_const_zero(stmt->Ist.Put.data)) {
+            addInstr(env, s390_insn_mzero(sizeofIRType(tyd), am));
+            return;
+         }
          src = s390_isel_int_expr(env, stmt->Ist.Put.data);
          break;