]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
s390x: Enable 1- and 2-byte operands for v-test
authorAndreas Arnez <arnez@linux.ibm.com>
Mon, 9 Mar 2020 14:14:16 +0000 (15:14 +0100)
committerAndreas Arnez <arnez@linux.ibm.com>
Fri, 13 Mar 2020 19:08:29 +0000 (20:08 +0100)
The v-test operation tests its operand against zero and sets the condition
code accordingly.  So far the operation was only supported for 4- and
8-byte operands.

Lift this restriction and enable 1- and 2-byte operands for v-test, using
the z/Architecture "test under mask" instructions TM, TMY, and TMLL.
Exploit this in the instruction selector, getting rid of the conversion to
a 4-byte operand.  This slightly reduces the generated code on s390x.

VEX/priv/host_s390_defs.c
VEX/priv/host_s390_isel.c

index 1cd469637e418c00d501f173fc0412ae7a7fe040..04da842ee234f00b8bb090f5fb8e8ab358d387e6 100644 (file)
@@ -2081,6 +2081,36 @@ s390_emit_NILL(UChar *p, UChar r1, UShort i2)
 }
 
 
+static UChar *
+s390_emit_TM(UChar *p, UChar i2, UChar b1, UShort d1)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC3(MNM, UDXB, INT), "tm", d1, 0, b1, i2);
+
+   return emit_SI(p, 0x91000000, i2, b1, d1);
+}
+
+
+static UChar *
+s390_emit_TMY(UChar *p, UChar i2, UChar b1, UShort dl1, UChar dh1)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC3(MNM, SDXB, INT), "tmy", dh1, dl1, 0, b1, (Int)(Char)i2);
+
+   return emit_SIY(p, 0xeb0000000051ULL, i2, b1, dl1, dh1);
+}
+
+
+static UChar *
+s390_emit_TMLL(UChar *p, UChar r1, UShort i2)
+{
+   if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM))
+      s390_disasm(ENC3(MNM, GPR, UINT), "tmll", r1, i2);
+
+   return emit_RI(p, 0xa7010000, r1, i2);
+}
+
+
 static UChar *
 s390_emit_BASR(UChar *p, UChar r1, UChar r2)
 {
@@ -6490,7 +6520,7 @@ s390_insn_test(UChar size, s390_opnd_RMI src)
 {
    s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn));
 
-   vassert(size == 4 || size == 8);
+   vassert(size == 1 || size == 2 || size == 4 || size == 8);
 
    insn->tag  = S390_INSN_TEST;
    insn->size = size;
@@ -9300,9 +9330,7 @@ s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
 }
 
 
-/* Only 4-byte and 8-byte operands are handled. 1-byte and 2-byte
-   comparisons will have been converted to 4-byte comparisons in
-   s390_isel_cc and should not occur here. */
+/* Test operand for zero. */
 static UChar *
 s390_insn_test_emit(UChar *buf, const s390_insn *insn)
 {
@@ -9315,6 +9343,12 @@ s390_insn_test_emit(UChar *buf, const s390_insn *insn)
       UInt reg = hregNumber(opnd.variant.reg);
 
       switch (insn->size) {
+      case 1:
+         return s390_emit_TMLL(buf, reg, 0xff);
+
+      case 2:
+         return s390_emit_TMLL(buf, reg, 0xffff);
+
       case 4:
          return s390_emit_LTR(buf, reg, reg);
 
@@ -9333,6 +9367,27 @@ s390_insn_test_emit(UChar *buf, const s390_insn *insn)
       Int   d = am->d;
 
       switch (insn->size) {
+      case 1:
+         switch (am->tag) {
+         case S390_AMODE_B12:
+            return s390_emit_TM(buf, 0xff, b, d);
+         case S390_AMODE_B20:
+            return s390_emit_TMY(buf, 0xff, b, DISP20(d));
+         default:
+            buf = s390_emit_LB(buf, R0, x, b, DISP20(d));
+            return s390_emit_TMLL(buf, R0, 0xff);
+         }
+
+      case 2:
+         switch (am->tag) {
+         case S390_AMODE_B12:
+            buf = s390_emit_LH(buf, R0, x, b, d);
+            return s390_emit_TMLL(buf, R0, 0xffff);
+         default:
+            buf = s390_emit_LHY(buf, R0, x, b, DISP20(d));
+            return s390_emit_TMLL(buf, R0, 0xffff);
+         }
+
       case 4:
          return s390_emit_LTw(buf, R0, x, b, DISP20(d));
 
@@ -9345,20 +9400,10 @@ s390_insn_test_emit(UChar *buf, const s390_insn *insn)
    }
 
    case S390_OPND_IMMEDIATE: {
-      ULong value = opnd.variant.imm;
-
-      switch (insn->size) {
-      case 4:
-         buf = s390_emit_load_32imm(buf, R0, value);
-         return s390_emit_LTR(buf, R0, R0);
-
-      case 8:
-         buf = s390_emit_load_64imm(buf, R0, value);
-         return s390_emit_LTGR(buf, R0, R0);
-
-      default:
-         goto fail;
-      }
+      if (opnd.variant.imm == 0)
+         return s390_emit_CR(buf, R0, R0);
+      else
+         return s390_emit_OILL(buf, R0, 1);
    }
 
    default:
index 4d0cf1721b7f969a8f7b68d879af9fabcf7561f5..b374024c8ce8d7720ca32e6b9dc5cbc04418175b 100644 (file)
@@ -3514,20 +3514,7 @@ s390_isel_cc(ISelEnv *env, IRExpr *cond)
       }
 
       case Iop_CmpNEZ8:
-      case Iop_CmpNEZ16: {
-         s390_opnd_RMI src;
-         s390_unop_t   op;
-         HReg dst;
-
-         op  = (cond->Iex.Unop.op == Iop_CmpNEZ8) ? S390_ZERO_EXTEND_8
-            : S390_ZERO_EXTEND_16;
-         dst = newVRegI(env);
-         src = s390_isel_int_expr_RMI(env, arg);
-         addInstr(env, s390_insn_unop(4, op, dst, src));
-         addInstr(env, s390_insn_test(4, s390_opnd_reg(dst)));
-         return S390_CC_NE;
-      }
-
+      case Iop_CmpNEZ16:
       case Iop_CmpNEZ32:
       case Iop_CmpNEZ64: {
          s390_opnd_RMI src;