diff mbox series

[07/10] tcg/s390x: Support SELGR instruction in MOVCOND

Message ID 20220224154333.125185-8-richard.henderson@linaro.org
State New
Headers show
Series tcg/s390x: updates for mie2 and mie3 | expand

Commit Message

Richard Henderson Feb. 24, 2022, 3:43 p.m. UTC
The new select instruction provides two separate register inputs,
whereas the old load-on-condition instruction overlaps one of the
register inputs with the destination.

Generalize movcond to support pre-computed conditions, and the same
set of arguments at all times.  This allows, but does not require,
MIE3 and LOC2 facilities at the same time.  It will also be assumed
by a following patch, which needs to reuse tgen_movcond_int.

Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
 tcg/s390x/tcg-target-con-set.h |  3 +-
 tcg/s390x/tcg-target.c.inc     | 99 +++++++++++++++++++++++++++-------
 2 files changed, 82 insertions(+), 20 deletions(-)
diff mbox series

Patch

diff --git a/tcg/s390x/tcg-target-con-set.h b/tcg/s390x/tcg-target-con-set.h
index 37801983f1..38ebce3594 100644
--- a/tcg/s390x/tcg-target-con-set.h
+++ b/tcg/s390x/tcg-target-con-set.h
@@ -29,8 +29,7 @@  C_O1_I2(r, rZ, r)
 C_O1_I2(v, v, r)
 C_O1_I2(v, v, v)
 C_O1_I3(v, v, v, v)
-C_O1_I4(r, r, ri, r, 0)
-C_O1_I4(r, r, ri, rI, 0)
+C_O1_I4(r, r, ri, rI, r)
 C_O2_I2(b, a, 0, r)
 C_O2_I2(b, a, r, r)
 C_O2_I3(b, a, 0, 1, r)
diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
index 18b8ca3132..8edad2c390 100644
--- a/tcg/s390x/tcg-target.c.inc
+++ b/tcg/s390x/tcg-target.c.inc
@@ -210,6 +210,8 @@  typedef enum S390Opcode {
     RRFa_XRK    = 0xb9f7,
     RRFa_XGRK   = 0xb9e7,
 
+    RRFa4_SELGR  = 0xb9e3,  /* RRF-a with the m4 field */
+
     RRFc_LOCR   = 0xb9f2,
     RRFc_LOCGR  = 0xb9e2,
 
@@ -564,12 +566,20 @@  static void tcg_out_insn_RRE(TCGContext *s, S390Opcode op,
     tcg_out32(s, (op << 16) | (r1 << 4) | r2);
 }
 
+/* RRF-a without the m4 field */
 static void tcg_out_insn_RRFa(TCGContext *s, S390Opcode op,
                               TCGReg r1, TCGReg r2, TCGReg r3)
 {
     tcg_out32(s, (op << 16) | (r3 << 12) | (r1 << 4) | r2);
 }
 
+/* RRF-a with the m4 field */
+static void tcg_out_insn_RRFa4(TCGContext *s, S390Opcode op,
+                               TCGReg r1, TCGReg r2, TCGReg r3, int m4)
+{
+    tcg_out32(s, (op << 16) | (r3 << 12) | (m4 << 8) | (r1 << 4) | r2);
+}
+
 static void tcg_out_insn_RRFc(TCGContext *s, S390Opcode op,
                               TCGReg r1, TCGReg r2, int m3)
 {
@@ -1562,25 +1572,80 @@  static void tgen_setcond(TCGContext *s, TCGType type, TCGCond cond,
     }
 }
 
+static void tgen_movcond_int(TCGContext *s, TCGType type, TCGReg dest,
+                             TCGArg v3, int v3const, TCGReg v4,
+                             int cc, int inv_cc)
+{
+    TCGReg src;
+
+    if (v3const && HAVE_FACILITY(LOAD_ON_COND2)) {
+        tcg_out_mov(s, type, dest, v4);
+        /* Emit: if (cc) dest = v3. */
+        tcg_out_insn(s, RIEg, LOCGHI, dest, v3, cc);
+        return;
+    }
+
+    /* Note that while MIE3 implies LOC, it does not imply LOC2. */
+    if (HAVE_FACILITY(MISC_INSN_EXT3)) {
+        if (v3const) {
+            tcg_out_insn(s, RI, LGHI, TCG_TMP0, v3);
+            v3 = TCG_TMP0;
+        }
+        /* Emit: dest = cc ? v3 : v4. */
+        tcg_out_insn(s, RRFa4, SELGR, dest, v3, v4, cc);
+        return;
+    }
+
+    if (HAVE_FACILITY(LOAD_ON_COND)) {
+        if (v3const) {
+            if (dest == v4) {
+                tcg_out_insn(s, RI, LGHI, TCG_TMP0, v3);
+                src = TCG_TMP0;
+            } else {
+                tcg_out_insn(s, RI, LGHI, dest, v3);
+                cc = inv_cc;
+                src = v4;
+            }
+        } else if (dest == v3) {
+            cc = inv_cc;
+            src = v4;
+        } else {
+            tcg_out_mov(s, type, dest, v4);
+            src = v3;
+        }
+        /* Emit: if (cc) dest = v3. */
+        tcg_out_insn(s, RRFc, LOCGR, dest, src, cc);
+        return;
+    }
+
+    if (v3const) {
+        tcg_out_mov(s, type, dest, v4);
+        /* Emit: if (!cc) goto over; dest = r3; over:  */
+        tcg_out_insn(s, RI, BRC, inv_cc, (4 + 4) >> 1);
+        tcg_out_insn(s, RI, LGHI, dest, v3);
+        return;
+    }
+
+    if (dest == v3) {
+        src = v4;
+        inv_cc = cc;
+    } else {
+        tcg_out_mov(s, type, dest, v4);
+        src = v3;
+    }
+    /* Emit: if (!cc) goto over; dest = r3; over:  */
+    tcg_out_insn(s, RI, BRC, inv_cc, (4 + 4) >> 1);
+    tcg_out_insn(s, RRE, LGR, dest, src);
+}
+
 static void tgen_movcond(TCGContext *s, TCGType type, TCGCond c, TCGReg dest,
                          TCGReg c1, TCGArg c2, int c2const,
-                         TCGArg v3, int v3const)
+                         TCGArg v3, int v3const, TCGReg v4)
 {
     int cc, inv_cc;
 
     cc = tgen_cmp2(s, type, c, c1, c2, c2const, false, &inv_cc);
-
-    if (HAVE_FACILITY(LOAD_ON_COND)) {
-        if (v3const) {
-            tcg_out_insn(s, RIEg, LOCGHI, dest, v3, cc);
-        } else {
-            tcg_out_insn(s, RRFc, LOCGR, dest, v3, cc);
-        }
-    } else {
-        /* Emit: if (cc) goto over; dest = r3; over:  */
-        tcg_out_insn(s, RI, BRC, inv_cc, (4 + 4) >> 1);
-        tcg_out_insn(s, RRE, LGR, dest, v3);
-    }
+    tgen_movcond_int(s, type, dest, v3, v3const, v4, cc, inv_cc);
 }
 
 static void tgen_clz(TCGContext *s, TCGReg dest, TCGReg a1,
@@ -2460,7 +2525,7 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
     case INDEX_op_movcond_i32:
         tgen_movcond(s, TCG_TYPE_I32, args[5], args[0], args[1],
-                     args[2], const_args[2], args[3], const_args[3]);
+                     args[2], const_args[2], args[3], const_args[3], args[4]);
         break;
 
     case INDEX_op_qemu_ld_i32:
@@ -2737,7 +2802,7 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         break;
     case INDEX_op_movcond_i64:
         tgen_movcond(s, TCG_TYPE_I64, args[5], args[0], args[1],
-                     args[2], const_args[2], args[3], const_args[3]);
+                     args[2], const_args[2], args[3], const_args[3], args[4]);
         break;
 
     OP_32_64(deposit):
@@ -3336,9 +3401,7 @@  static TCGConstraintSetIndex tcg_target_op_def(TCGOpcode op)
 
     case INDEX_op_movcond_i32:
     case INDEX_op_movcond_i64:
-        return (HAVE_FACILITY(LOAD_ON_COND2)
-                ? C_O1_I4(r, r, ri, rI, 0)
-                : C_O1_I4(r, r, ri, r, 0));
+        return C_O1_I4(r, r, ri, rI, r);
 
     case INDEX_op_div2_i32:
     case INDEX_op_div2_i64: