Patchwork [05/15] tcg-sparc: Simplify qemu_ld/st direct memory paths.

login
register
mail settings
Submitter Richard Henderson
Date March 25, 2012, 10:27 p.m.
Message ID <1332714477-30079-6-git-send-email-rth@twiddle.net>
Download mbox | patch
Permalink /patch/148606/
State New
Headers show

Comments

Richard Henderson - March 25, 2012, 10:27 p.m.
Given that we have an opcode for all sizes, all endianness,
turn the functions into a simple table lookup.

Signed-off-by: Richard Henderson <rth@twiddle.net>
---
 tcg/sparc/tcg-target.c |  209 +++++++++++++-----------------------------------
 1 files changed, 56 insertions(+), 153 deletions(-)

Patch

diff --git a/tcg/sparc/tcg-target.c b/tcg/sparc/tcg-target.c
index 8763b03..1b27626 100644
--- a/tcg/sparc/tcg-target.c
+++ b/tcg/sparc/tcg-target.c
@@ -294,6 +294,16 @@  static inline int tcg_target_const_match(tcg_target_long val,
 #define ASI_PRIMARY_LITTLE 0x88
 #endif
 
+#define LDUH_LE    (LDUHA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define LDSH_LE    (LDSHA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define LDUW_LE    (LDUWA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define LDSW_LE    (LDSWA | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define LDX_LE     (LDXA  | INSN_ASI(ASI_PRIMARY_LITTLE))
+
+#define STH_LE     (STHA  | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define STW_LE     (STWA  | INSN_ASI(ASI_PRIMARY_LITTLE))
+#define STX_LE     (STXA  | INSN_ASI(ASI_PRIMARY_LITTLE))
+
 static inline void tcg_out_arith(TCGContext *s, int rd, int rs1, int rs2,
                                  int op)
 {
@@ -366,66 +376,46 @@  static inline void tcg_out_movi(TCGContext *s, TCGType type,
     }
 }
 
-static inline void tcg_out_ld_raw(TCGContext *s, int ret,
-                                  tcg_target_long arg)
+static inline void tcg_out_ldst_rr(TCGContext *s, int data, int a1,
+                                   int a2, int op)
 {
-    tcg_out_sethi(s, ret, arg);
-    tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) |
-              INSN_IMM13(arg & 0x3ff));
+    tcg_out32(s, op | INSN_RD(data) | INSN_RS1(a1) | INSN_RS2(a2));
 }
 
-static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
-                                  tcg_target_long arg)
+static inline void tcg_out_ldst(TCGContext *s, int ret, int addr,
+                                int offset, int op)
 {
-    if (!check_fit_tl(arg, 10))
-        tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ffULL);
-    if (TCG_TARGET_REG_BITS == 64) {
-        tcg_out32(s, LDX | INSN_RD(ret) | INSN_RS1(ret) |
-                  INSN_IMM13(arg & 0x3ff));
-    } else {
-        tcg_out32(s, LDUW | INSN_RD(ret) | INSN_RS1(ret) |
-                  INSN_IMM13(arg & 0x3ff));
-    }
-}
-
-static inline void tcg_out_ldst(TCGContext *s, int ret, int addr, int offset, int op)
-{
-    if (check_fit_tl(offset, 13))
+    if (check_fit_tl(offset, 13)) {
         tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(addr) |
                   INSN_IMM13(offset));
-    else {
+    } else {
         tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset);
-        tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(TCG_REG_I5) |
-                  INSN_RS2(addr));
+        tcg_out_ldst_rr(s, ret, addr, TCG_REG_I5, op);
     }
 }
 
-static inline void tcg_out_ldst_asi(TCGContext *s, int ret, int addr,
-                                    int offset, int op, int asi)
-{
-    tcg_out_movi(s, TCG_TYPE_PTR, TCG_REG_I5, offset);
-    tcg_out32(s, op | INSN_RD(ret) | INSN_RS1(TCG_REG_I5) |
-              INSN_ASI(asi) | INSN_RS2(addr));
-}
-
 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg ret,
                               TCGReg arg1, tcg_target_long arg2)
 {
-    if (type == TCG_TYPE_I32)
-        tcg_out_ldst(s, ret, arg1, arg2, LDUW);
-    else
-        tcg_out_ldst(s, ret, arg1, arg2, LDX);
+    tcg_out_ldst(s, ret, arg1, arg2, (type == TCG_TYPE_I32 ? LDUW : LDX));
 }
 
 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
                               TCGReg arg1, tcg_target_long arg2)
 {
-    if (type == TCG_TYPE_I32)
-        tcg_out_ldst(s, arg, arg1, arg2, STW);
-    else
-        tcg_out_ldst(s, arg, arg1, arg2, STX);
+    tcg_out_ldst(s, arg, arg1, arg2, (type == TCG_TYPE_I32 ? STW : STX));
 }
 
+static inline void tcg_out_ld_ptr(TCGContext *s, int ret,
+                                  tcg_target_long arg)
+{
+    if (!check_fit_tl(arg, 10)) {
+        tcg_out_movi(s, TCG_TYPE_PTR, ret, arg & ~0x3ff);
+    }
+    tcg_out_ld(s, TCG_TYPE_PTR, ret, ret, arg & 0x3ff);
+}
+
+
 static inline void tcg_out_sety(TCGContext *s, int rs)
 {
     tcg_out32(s, WRY | INSN_RS1(TCG_REG_G0) | INSN_RS2(rs));
@@ -833,76 +823,26 @@  static void tcg_out_qemu_ld_direct(TCGContext *s, int addr, int datalo,
                                    int datahi, int sizeop)
 {
 #ifdef TARGET_WORDS_BIGENDIAN
-    const int bigendian = 1;
+    static const int ld_opc[8] = {
+        LDUB, LDUH, LDUW, LDX, LDSB, LDSH, LDSW, LDX
+    };
 #else
-    const int bigendian = 0;
+    static const int ld_opc[8] = {
+        LDUB, LDUH_LE, LDUW_LE, LDX_LE, LDSB, LDSH_LE, LDSW_LE, LDX_LE
+    };
 #endif
-    switch (sizeop) {
-    case 0:
-        /* ldub [addr], datalo */
-        tcg_out_ldst(s, datalo, addr, 0, LDUB);
-        break;
-    case 0 | 4:
-        /* ldsb [addr], datalo */
-        tcg_out_ldst(s, datalo, addr, 0, LDSB);
-        break;
-    case 1:
-        if (bigendian) {
-            /* lduh [addr], datalo */
-            tcg_out_ldst(s, datalo, addr, 0, LDUH);
-        } else {
-            /* lduha [addr] ASI_PRIMARY_LITTLE, datalo */
-            tcg_out_ldst_asi(s, datalo, addr, 0, LDUHA, ASI_PRIMARY_LITTLE);
-        }
-        break;
-    case 1 | 4:
-        if (bigendian) {
-            /* ldsh [addr], datalo */
-            tcg_out_ldst(s, datalo, addr, 0, LDSH);
-        } else {
-            /* ldsha [addr] ASI_PRIMARY_LITTLE, datalo */
-            tcg_out_ldst_asi(s, datalo, addr, 0, LDSHA, ASI_PRIMARY_LITTLE);
-        }
-        break;
-    case 2:
-        if (bigendian) {
-            /* lduw [addr], datalo */
-            tcg_out_ldst(s, datalo, addr, 0, LDUW);
-        } else {
-            /* lduwa [addr] ASI_PRIMARY_LITTLE, datalo */
-            tcg_out_ldst_asi(s, datalo, addr, 0, LDUWA, ASI_PRIMARY_LITTLE);
-        }
-        break;
-    case 2 | 4:
-        if (bigendian) {
-            /* ldsw [addr], datalo */
-            tcg_out_ldst(s, datalo, addr, 0, LDSW);
-        } else {
-            /* ldswa [addr] ASI_PRIMARY_LITTLE, datalo */
-            tcg_out_ldst_asi(s, datalo, addr, 0, LDSWA, ASI_PRIMARY_LITTLE);
-        }
-        break;
-    case 3:
-        if (TCG_TARGET_REG_BITS == 64) {
-            if (bigendian) {
-                /* ldx [addr], datalo */
-                tcg_out_ldst(s, datalo, addr, 0, LDX);
-            } else {
-                /* ldxa [addr] ASI_PRIMARY_LITTLE, datalo */
-                tcg_out_ldst_asi(s, datalo, addr, 0, LDXA, ASI_PRIMARY_LITTLE);
-            }
-        } else {
-            if (bigendian) {
-                tcg_out_ldst(s, datahi, addr, 0, LDUW);
-                tcg_out_ldst(s, datalo, addr, 4, LDUW);
-            } else {
-                tcg_out_ldst_asi(s, datalo, addr, 0, LDUWA, ASI_PRIMARY_LITTLE);
-                tcg_out_ldst_asi(s, datahi, addr, 4, LDUWA, ASI_PRIMARY_LITTLE);
-            }
+
+    if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
+        /* Load all 64-bits into an O/G register.  */
+        int reg64 = (datalo < 16 ? datalo : TCG_REG_O0);
+        tcg_out_ldst_rr(s, reg64, addr, TCG_REG_G0, ld_opc[sizeop]);
+        /* Move the two 32-bit pieces into the destination registers.  */
+        tcg_out_arithi(s, datahi, reg64, 32, SHIFT_SRLX);
+        if (reg64 != datalo) {
+            tcg_out_mov(s, TCG_TYPE_I32, datalo, reg64);
         }
-        break;
-    default:
-        tcg_abort();
+    } else {
+        tcg_out_ldst_rr(s, datalo, addr, TCG_REG_G0, ld_opc[sizeop]);
     }
 }
 
@@ -1016,55 +956,18 @@  static void tcg_out_qemu_st_direct(TCGContext *s, int addr, int datalo,
                                    int datahi, int sizeop)
 {
 #ifdef TARGET_WORDS_BIGENDIAN
-    const int bigendian = 1;
+    static const int st_opc[4] = { STB, STH, STW, STX };
 #else
-    const int bigendian = 0;
+    static const int st_opc[4] = { STB, STH_LE, STW_LE, STX_LE };
 #endif
-    switch (sizeop) {
-    case 0:
-        /* stb datalo, [addr] */
-        tcg_out_ldst(s, datalo, addr, 0, STB);
-        break;
-    case 1:
-        if (bigendian) {
-            /* sth datalo, [addr] */
-            tcg_out_ldst(s, datalo, addr, 0, STH);
-        } else {
-            /* stha datalo, [addr] ASI_PRIMARY_LITTLE */
-            tcg_out_ldst_asi(s, datalo, addr, 0, STHA, ASI_PRIMARY_LITTLE);
-        }
-        break;
-    case 2:
-        if (bigendian) {
-            /* stw datalo, [addr] */
-            tcg_out_ldst(s, datalo, addr, 0, STW);
-        } else {
-            /* stwa datalo, [addr] ASI_PRIMARY_LITTLE */
-            tcg_out_ldst_asi(s, datalo, addr, 0, STWA, ASI_PRIMARY_LITTLE);
-        }
-        break;
-    case 3:
-        if (TCG_TARGET_REG_BITS == 64) {
-            if (bigendian) {
-                /* stx datalo, [addr] */
-                tcg_out_ldst(s, datalo, addr, 0, STX);
-            } else {
-                /* stxa datalo, [addr] ASI_PRIMARY_LITTLE */
-                tcg_out_ldst_asi(s, datalo, addr, 0, STXA, ASI_PRIMARY_LITTLE);
-            }
-        } else {
-            if (bigendian) {
-                tcg_out_ldst(s, datahi, addr, 0, STW);
-                tcg_out_ldst(s, datalo, addr, 4, STW);
-            } else {
-                tcg_out_ldst_asi(s, datalo, addr, 0, STWA, ASI_PRIMARY_LITTLE);
-                tcg_out_ldst_asi(s, datahi, addr, 4, STWA, ASI_PRIMARY_LITTLE);
-            }
-        }
-        break;
-    default:
-        tcg_abort();
+
+    if (TCG_TARGET_REG_BITS == 32 && sizeop == 3) {
+        tcg_out_arithi(s, TCG_REG_O0, datalo, 0, SHIFT_SRL);
+        tcg_out_arithi(s, TCG_REG_O2, datahi, 32, SHIFT_SLLX);
+        tcg_out_arith(s, TCG_REG_O0, TCG_REG_O0, TCG_REG_O2, ARITH_OR);
+        datalo = TCG_REG_O0;
     }
+    tcg_out_ldst_rr(s, datalo, addr, TCG_REG_G0, st_opc[sizeop]);
 }
 
 static void tcg_out_qemu_st(TCGContext *s, const TCGArg *args, int opc)