diff mbox

[59/62] tcg-s390: Generalize load/store support.

Message ID 1274993204-30766-60-git-send-email-rth@twiddle.net
State New
Headers show

Commit Message

Richard Henderson May 27, 2010, 8:46 p.m. UTC
Rename tcg_out_ldst to tcg_out_mem and add an index parameter.  If the
index parameter is present, handle it when the offset parameter is large
and the addend must be (partially) loaded.

Rename SH{32,64}_REG_NONE to TCG_REG_NONE, as the concept of a missing
register is not unique to the shift operations.

Adjust all users of tcg_out_mem to add TCG_REG_NONE as the index.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/s390/tcg-target.c |   94 +++++++++++++++++++++++++-----------------------
 1 files changed, 49 insertions(+), 45 deletions(-)
diff mbox

Patch

diff --git a/tcg/s390/tcg-target.c b/tcg/s390/tcg-target.c
index 4e3fb8b..6101255 100644
--- a/tcg/s390/tcg-target.c
+++ b/tcg/s390/tcg-target.c
@@ -47,6 +47,7 @@ 
 #define TCG_CT_CONST_XORI  0x4000
 #define TCG_CT_CONST_CMPI  0x8000
 
+#define TCG_REG_NONE       TCG_REG_R0
 #define TCG_TMP0           TCG_REG_R14
 
 #ifdef CONFIG_USE_GUEST_BASE
@@ -204,9 +205,6 @@  typedef enum S390Opcode {
     RX_STH      = 0x40,
 } S390Opcode;
 
-#define SH32_REG_NONE  0
-#define SH64_REG_NONE  0
-
 #define LD_SIGNED      0x04
 #define LD_UINT8       0x00
 #define LD_INT8        (LD_UINT8 | LD_SIGNED)
@@ -338,7 +336,7 @@  static void patch_reloc(uint8_t *code_ptr, int type,
 
     /* ??? Not the usual definition of "addend".  */
     pcrel2 = (value - (code_ptr_tl + addend)) >> 1;
-    
+
     switch (type) {
     case R_390_PC16DBL:
         assert(pcrel2 == (int16_t)pcrel2);
@@ -597,7 +595,7 @@  static int tcg_target_const_match(tcg_target_long val,
     } else if (ct & TCG_CT_CONST_MULI) {
         /* Immediates that may be used with multiply.  If we have the
            general-instruction-extensions, then we have MULTIPLY SINGLE
-           IMMEDIATE with a signed 32-bit, otherwise we have only 
+           IMMEDIATE with a signed 32-bit, otherwise we have only
            MULTIPLY HALFWORD IMMEDIATE, with a signed 16-bit.  */
         if (facilities & FACILITY_GEN_INST_EXT) {
             return val == (int32_t)val;
@@ -799,17 +797,21 @@  static void tcg_out_movi(TCGContext *s, TCGType type,
    OPC_RX:   If the operation has an RX format opcode (e.g. STC), otherwise 0.
    OPC_RXY:  The RXY format opcode for the operation (e.g. STCY).  */
 
-static void tcg_out_ldst(TCGContext *s, S390Opcode opc_rx, S390Opcode opc_rxy,
-                         TCGReg data, TCGReg base, tcg_target_long ofs)
+static void tcg_out_mem(TCGContext *s, S390Opcode opc_rx, S390Opcode opc_rxy,
+                        TCGReg data, TCGReg base, TCGReg index,
+                        tcg_target_long ofs)
 {
-    TCGReg index = 0;
-
     if (ofs < -0x80000 || ofs >= 0x80000) {
         /* Combine the low 16 bits of the offset with the actual load insn;
            the high 48 bits must come from an immediate load.  */
-        index = TCG_TMP0;
-        tcg_out_movi(s, TCG_TYPE_PTR, index, ofs & ~0xffff);
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs & ~0xffff);
         ofs &= 0xffff;
+
+        /* If we were already given an index register, add it in.  */
+        if (index != TCG_REG_NONE) {
+            tcg_out_insn(s, RRE, AGR, TCG_TMP0, index);
+        }
+        index = TCG_TMP0;
     }
 
     if (opc_rx && ofs >= 0 && ofs < 0x1000) {
@@ -825,9 +827,9 @@  static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg data,
                               TCGReg base, tcg_target_long ofs)
 {
     if (type == TCG_TYPE_I32) {
-        tcg_out_ldst(s, RX_L, RXY_LY, data, base, ofs);
+        tcg_out_mem(s, RX_L, RXY_LY, data, base, TCG_REG_NONE, ofs);
     } else {
-        tcg_out_ldst(s, 0, RXY_LG, data, base, ofs);
+        tcg_out_mem(s, 0, RXY_LG, data, base, TCG_REG_NONE, ofs);
     }
 }
 
@@ -835,9 +837,9 @@  static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg data,
                               TCGReg base, tcg_target_long ofs)
 {
     if (type == TCG_TYPE_I32) {
-        tcg_out_ldst(s, RX_ST, RXY_STY, data, base, ofs);
+        tcg_out_mem(s, RX_ST, RXY_STY, data, base, TCG_REG_NONE, ofs);
     } else {
-        tcg_out_ldst(s, 0, RXY_STG, data, base, ofs);
+        tcg_out_mem(s, 0, RXY_STG, data, base, TCG_REG_NONE, ofs);
     }
 }
 
@@ -871,14 +873,14 @@  static void tgen_ext8s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
 
     if (type == TCG_TYPE_I32) {
         if (dest == src) {
-            tcg_out_sh32(s, RS_SLL, dest, SH32_REG_NONE, 24);
+            tcg_out_sh32(s, RS_SLL, dest, TCG_REG_NONE, 24);
         } else {
-            tcg_out_sh64(s, RSY_SLLG, dest, src, SH64_REG_NONE, 24);
+            tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 24);
         }
-        tcg_out_sh32(s, RS_SRA, dest, SH32_REG_NONE, 24);
+        tcg_out_sh32(s, RS_SRA, dest, TCG_REG_NONE, 24);
     } else {
-        tcg_out_sh64(s, RSY_SLLG, dest, src, SH64_REG_NONE, 56);
-        tcg_out_sh64(s, RSY_SRAG, dest, dest, SH64_REG_NONE, 56);
+        tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 56);
+        tcg_out_sh64(s, RSY_SRAG, dest, dest, TCG_REG_NONE, 56);
     }
 }
 
@@ -911,14 +913,14 @@  static void tgen_ext16s(TCGContext *s, TCGType type, TCGReg dest, TCGReg src)
 
     if (type == TCG_TYPE_I32) {
         if (dest == src) {
-            tcg_out_sh32(s, RS_SLL, dest, SH32_REG_NONE, 16);
+            tcg_out_sh32(s, RS_SLL, dest, TCG_REG_NONE, 16);
         } else {
-            tcg_out_sh64(s, RSY_SLLG, dest, src, SH64_REG_NONE, 16);
+            tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 16);
         }
-        tcg_out_sh32(s, RS_SRA, dest, SH32_REG_NONE, 24);
+        tcg_out_sh32(s, RS_SRA, dest, TCG_REG_NONE, 24);
     } else {
-        tcg_out_sh64(s, RSY_SLLG, dest, src, SH64_REG_NONE, 48);
-        tcg_out_sh64(s, RSY_SRAG, dest, dest, SH64_REG_NONE, 48);
+        tcg_out_sh64(s, RSY_SLLG, dest, src, TCG_REG_NONE, 48);
+        tcg_out_sh64(s, RSY_SRAG, dest, dest, TCG_REG_NONE, 48);
     }
 }
 
@@ -1427,7 +1429,7 @@  static void tcg_prepare_qemu_ldst(TCGContext* s, TCGReg data_reg,
         tcg_out_mov(s, arg0, addr_reg);
     }
 
-    tcg_out_sh64(s, RSY_SRLG, arg1, addr_reg, SH64_REG_NONE,
+    tcg_out_sh64(s, RSY_SRLG, arg1, addr_reg, TCG_REG_NONE,
                  TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
 
     tgen64_andi_tmp(s, arg0, TARGET_PAGE_MASK | ((1 << s_bits) - 1));
@@ -1615,37 +1617,37 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
     case INDEX_op_ld8u_i64:
         /* ??? LLC (RXY format) is only present with the extended-immediate
            facility, whereas LLGC is always present.  */
-        tcg_out_ldst(s, 0, RXY_LLGC, args[0], args[1], args[2]);
+        tcg_out_mem(s, 0, RXY_LLGC, args[0], args[1], TCG_REG_NONE, args[2]);
         break;
 
     case INDEX_op_ld8s_i32:
     case INDEX_op_ld8s_i64:
         /* ??? LB is no smaller than LGB, so no point to using it.  */
-        tcg_out_ldst(s, 0, RXY_LGB, args[0], args[1], args[2]);
+        tcg_out_mem(s, 0, RXY_LGB, args[0], args[1], TCG_REG_NONE, args[2]);
         break;
 
     case INDEX_op_ld16u_i32:
     case INDEX_op_ld16u_i64:
         /* ??? LLH (RXY format) is only present with the extended-immediate
            facility, whereas LLGH is always present.  */
-        tcg_out_ldst(s, 0, RXY_LLGH, args[0], args[1], args[2]);
+        tcg_out_mem(s, 0, RXY_LLGH, args[0], args[1], TCG_REG_NONE, args[2]);
         break;
 
     case INDEX_op_ld16s_i32:
-        tcg_out_ldst(s, RX_LH, RXY_LHY, args[0], args[1], args[2]);
+        tcg_out_mem(s, RX_LH, RXY_LHY, args[0], args[1], TCG_REG_NONE, args[2]);
         break;
     case INDEX_op_ld16s_i64:
-        tcg_out_ldst(s, 0, RXY_LGH, args[0], args[1], args[2]);
+        tcg_out_mem(s, 0, RXY_LGH, args[0], args[1], TCG_REG_NONE, args[2]);
         break;
 
     case INDEX_op_ld_i32:
         tcg_out_ld(s, TCG_TYPE_I32, args[0], args[1], args[2]);
         break;
     case INDEX_op_ld32u_i64:
-        tcg_out_ldst(s, 0, RXY_LLGF, args[0], args[1], args[2]);
+        tcg_out_mem(s, 0, RXY_LLGF, args[0], args[1], TCG_REG_NONE, args[2]);
         break;
     case INDEX_op_ld32s_i64:
-        tcg_out_ldst(s, 0, RXY_LGF, args[0], args[1], args[2]);
+        tcg_out_mem(s, 0, RXY_LGF, args[0], args[1], TCG_REG_NONE, args[2]);
         break;
 
     case INDEX_op_ld_i64:
@@ -1654,12 +1656,14 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
 
     case INDEX_op_st8_i32:
     case INDEX_op_st8_i64:
-        tcg_out_ldst(s, RX_STC, RXY_STCY, args[0], args[1], args[2]);
+        tcg_out_mem(s, RX_STC, RXY_STCY, args[0], args[1],
+                    TCG_REG_NONE, args[2]);
         break;
 
     case INDEX_op_st16_i32:
     case INDEX_op_st16_i64:
-        tcg_out_ldst(s, RX_STH, RXY_STHY, args[0], args[1], args[2]);
+        tcg_out_mem(s, RX_STH, RXY_STHY, args[0], args[1],
+                    TCG_REG_NONE, args[2]);
         break;
 
     case INDEX_op_st_i32:
@@ -1797,7 +1801,7 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         op = RS_SLL;
     do_shift32:
         if (const_args[2]) {
-            tcg_out_sh32(s, op, args[0], SH32_REG_NONE, args[2]);
+            tcg_out_sh32(s, op, args[0], TCG_REG_NONE, args[2]);
         } else {
             tcg_out_sh32(s, op, args[0], args[2], 0);
         }
@@ -1813,7 +1817,7 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         op = RSY_SLLG;
     do_shift64:
         if (const_args[2]) {
-            tcg_out_sh64(s, op, args[0], args[1], SH64_REG_NONE, args[2]);
+            tcg_out_sh64(s, op, args[0], args[1], TCG_REG_NONE, args[2]);
         } else {
             tcg_out_sh64(s, op, args[0], args[1], args[2], 0);
         }
@@ -1828,7 +1832,7 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
     case INDEX_op_rotl_i32:
         /* ??? Using tcg_out_sh64 here for the format; it is a 32-bit rol.  */
         if (const_args[2]) {
-            tcg_out_sh64(s, RSY_RLL, args[0], args[1], SH32_REG_NONE, args[2]);
+            tcg_out_sh64(s, RSY_RLL, args[0], args[1], TCG_REG_NONE, args[2]);
         } else {
             tcg_out_sh64(s, RSY_RLL, args[0], args[1], args[2], 0);
         }
@@ -1836,7 +1840,7 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
     case INDEX_op_rotr_i32:
         if (const_args[2]) {
             tcg_out_sh64(s, RSY_RLL, args[0], args[1],
-                         SH32_REG_NONE, (32 - args[2]) & 31);
+                         TCG_REG_NONE, (32 - args[2]) & 31);
         } else {
             tcg_out_insn(s, RR, LCR, TCG_TMP0, args[2]);
             tcg_out_sh64(s, RSY_RLL, args[0], args[1], TCG_TMP0, 0);
@@ -1846,7 +1850,7 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
     case INDEX_op_rotl_i64:
         if (const_args[2]) {
             tcg_out_sh64(s, RSY_RLLG, args[0], args[1],
-                         SH64_REG_NONE, args[2]);
+                         TCG_REG_NONE, args[2]);
         } else {
             tcg_out_sh64(s, RSY_RLLG, args[0], args[1], args[2], 0);
         }
@@ -1854,7 +1858,7 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
     case INDEX_op_rotr_i64:
         if (const_args[2]) {
             tcg_out_sh64(s, RSY_RLLG, args[0], args[1],
-                         SH64_REG_NONE, (64 - args[2]) & 63);
+                         TCG_REG_NONE, (64 - args[2]) & 63);
         } else {
             /* We can use the smaller 32-bit negate because only the
                low 6 bits are examined for the rotate.  */
@@ -1900,7 +1904,7 @@  static inline void tcg_out_op(TCGContext *s, TCGOpcode opc,
         /* The TCG bswap definition requires bits 0-47 already be zero.
            Thus we don't need the G-type insns to implement bswap16_i64.  */
         tcg_out_insn(s, RRE, LRVR, args[0], args[1]);
-        tcg_out_sh32(s, RS_SRL, args[0], SH32_REG_NONE, 16);
+        tcg_out_sh32(s, RS_SRL, args[0], TCG_REG_NONE, 16);
         break;
     case INDEX_op_bswap32_i32:
     case INDEX_op_bswap32_i64:
@@ -2113,9 +2117,9 @@  static const TCGTargetOpDef s390_op_defs[] = {
 
 /* ??? Linux kernels provide an AUXV entry AT_HWCAP that provides most of
    this information.  However, getting at that entry is not easy this far
-   away from main.  Our options are: start searching from environ, but 
+   away from main.  Our options are: start searching from environ, but
    that fails as soon as someone does a setenv in between.  Read the data
-   from /proc/self/auxv.  Or do the probing ourselves.  The only thing 
+   from /proc/self/auxv.  Or do the probing ourselves.  The only thing
    extra that AT_HWCAP gives us is HWCAP_S390_HIGH_GPRS, which indicates
    that the kernel saves all 64-bits of the registers around traps while
    in 31-bit mode.  But this is true of all "recent" kernels (ought to dig
@@ -2156,7 +2160,7 @@  static void query_facilities(void)
         /* ??? Possibly some of these are in practice never present unless
            the store-facility-extended facility is also present.  But since
            that isn't documented it's just better to probe for each.  */
-       
+
         /* Test for z/Architecture.  Required even in 31-bit mode.  */
         got_sigill = 0;
         /* agr %r0,%r0 */