From: Jin Guojie <jinguo...@loongson.cn>

This patch implements TCG mips64r2(little-endian) translation backend.
Tested on Loongson 3A2000(a MIPS64-compatible CPU) with Fedora Linux 21 Remix.
linux-0.2.img.bz2 runs well.
The performance is nearly 10 times higher than tci mode.

https://en.wikipedia.org/wiki/Loongson
http://www.loongnix.org/index.php/Loongnix

Cc: Aurelien Jarno <aurel...@aurel32.net>
Signed-off-by: Jin Guojie <jinguo...@loongson.cn>
---
 tcg/mips/tcg-target.h     |  59 +++++++++++++
 tcg/mips/tcg-target.inc.c | 215 +++++++++++++++++++++++++++++++++++++++++++---
 2 files changed, 264 insertions(+), 10 deletions(-)

diff --git a/tcg/mips/tcg-target.h b/tcg/mips/tcg-target.h
index 3aeac87..4665e0b 100644
--- a/tcg/mips/tcg-target.h
+++ b/tcg/mips/tcg-target.h
@@ -31,6 +31,12 @@
 #define TCG_TARGET_TLB_DISPLACEMENT_BITS 16
 #define TCG_TARGET_NB_REGS 32
 
+#if UINTPTR_MAX == UINT32_MAX
+# define TCG_TARGET_REG_BITS 32
+#elif UINTPTR_MAX == UINT64_MAX
+# define TCG_TARGET_REG_BITS 64
+#endif
+
 typedef enum {
     TCG_REG_ZERO = 0,
     TCG_REG_AT,
@@ -40,6 +46,7 @@ typedef enum {
     TCG_REG_A1,
     TCG_REG_A2,
     TCG_REG_A3,
+#if TCG_TARGET_REG_BITS == 32
     TCG_REG_T0,
     TCG_REG_T1,
     TCG_REG_T2,
@@ -48,6 +55,16 @@ typedef enum {
     TCG_REG_T5,
     TCG_REG_T6,
     TCG_REG_T7,
+#else
+    TCG_REG_A4,
+    TCG_REG_A5,
+    TCG_REG_A6,
+    TCG_REG_A7,
+    TCG_REG_T0,
+    TCG_REG_T1,
+    TCG_REG_T2,
+    TCG_REG_T3,
+#endif
     TCG_REG_S0,
     TCG_REG_S1,
     TCG_REG_S2,
@@ -132,6 +149,48 @@ extern bool use_mips32r2_instructions;
 #define TCG_TARGET_HAS_ext8u_i32        0 /* andi rt, rs, 0xff   */
 #define TCG_TARGET_HAS_ext16u_i32       0 /* andi rt, rs, 0xffff */
 
+#if TCG_TARGET_REG_BITS == 64
+#define TCG_TARGET_HAS_extrl_i64_i32    0
+#define TCG_TARGET_HAS_extrh_i64_i32    0
+#define TCG_TARGET_HAS_bswap16_i64      1
+#define TCG_TARGET_HAS_bswap32_i64      1
+#define TCG_TARGET_HAS_bswap64_i64      1
+#define TCG_TARGET_HAS_deposit_i64      1
+#define TCG_TARGET_HAS_div_i64          0
+#define TCG_TARGET_HAS_rem_i64          0
+#define TCG_TARGET_HAS_ext8s_i64        1
+#define TCG_TARGET_HAS_ext16s_i64       1
+#define TCG_TARGET_HAS_ext32s_i64       1
+#define TCG_TARGET_HAS_ext8u_i64        1
+#define TCG_TARGET_HAS_ext16u_i64       1
+#define TCG_TARGET_HAS_ext32u_i64       1
+#define TCG_TARGET_HAS_andc_i64         0
+#define TCG_TARGET_HAS_eqv_i64          0
+#define TCG_TARGET_HAS_nand_i64         0
+#define TCG_TARGET_HAS_nor_i64          0
+#define TCG_TARGET_HAS_neg_i64          1
+#define TCG_TARGET_HAS_not_i64          1
+#define TCG_TARGET_HAS_orc_i64          0
+#define TCG_TARGET_HAS_rot_i64          1
+#define TCG_TARGET_HAS_movcond_i64      0
+#define TCG_TARGET_HAS_muls2_i64        0
+#define TCG_TARGET_HAS_add2_i32         0
+#define TCG_TARGET_HAS_sub2_i32         0
+#define TCG_TARGET_HAS_add2_i64         0
+#define TCG_TARGET_HAS_sub2_i64         0
+#define TCG_TARGET_HAS_mulu2_i64        0
+#define TCG_TARGET_HAS_muluh_i64        0
+#define TCG_TARGET_HAS_mulsh_i64        0
+
+#undef use_movnz_instructions
+#undef use_mips32_instructions
+#undef use_mips32r6_instructions
+
+#define use_movnz_instructions  0
+#define use_mips32_instructions  0
+#define use_mips32r6_instructions  0
+#endif /* TCG_TARGET_REG_BITS == 64 */
+
 #ifdef __OpenBSD__
 #include <machine/sysarch.h>
 #else
diff --git a/tcg/mips/tcg-target.inc.c b/tcg/mips/tcg-target.inc.c
index abce602..153a49a 100644
--- a/tcg/mips/tcg-target.inc.c
+++ b/tcg/mips/tcg-target.inc.c
@@ -93,33 +93,53 @@ static const int tcg_target_reg_alloc_order[] = {
     TCG_REG_T1,
     TCG_REG_T2,
     TCG_REG_T3,
+#if TCG_TARGET_REG_BITS == 32
     TCG_REG_T4,
     TCG_REG_T5,
     TCG_REG_T6,
     TCG_REG_T7,
+#endif
     TCG_REG_T8,
     TCG_REG_T9,
     TCG_REG_V1,
     TCG_REG_V0,
 
     /* Argument registers, opposite order of allocation.  */
+#if TCG_TARGET_REG_BITS == 64
+    TCG_REG_A7,
+    TCG_REG_A6,
+    TCG_REG_A5,
+    TCG_REG_A4,
+#endif
     TCG_REG_A3,
     TCG_REG_A2,
     TCG_REG_A1,
     TCG_REG_A0,
 };
 
-static const TCGReg tcg_target_call_iarg_regs[4] = {
+static const TCGReg tcg_target_call_iarg_regs[] = {
     TCG_REG_A0,
     TCG_REG_A1,
     TCG_REG_A2,
-    TCG_REG_A3
+    TCG_REG_A3,
+#if TCG_TARGET_REG_BITS == 64
+    TCG_REG_A4,
+    TCG_REG_A5,
+    TCG_REG_A6,
+    TCG_REG_A7,
+#endif
 };
 
+#if TCG_TARGET_REG_BITS == 64
+static const TCGReg tcg_target_call_oarg_regs[1] = {
+    TCG_REG_V0,
+};
+#else
 static const TCGReg tcg_target_call_oarg_regs[2] = {
     TCG_REG_V0,
     TCG_REG_V1
 };
+#endif
 
 static tcg_insn_unit *tb_ret_addr;
 
@@ -348,6 +368,14 @@ typedef enum {
     OPC_SYNC_ACQUIRE = OPC_SYNC | 0x11 << 5,
     OPC_SYNC_RELEASE = OPC_SYNC | 0x12 << 5,
     OPC_SYNC_RMB     = OPC_SYNC | 0x13 << 5,
+
+#if TCG_TARGET_REG_BITS == 64
+    OPC_DADDIU   = 0x19 << 26,
+    OPC_DADDU    = OPC_SPECIAL | 0x2D,
+    OPC_DSLL     = OPC_SPECIAL | 0x38,
+    OPC_LD       = 0x37 << 26,
+    OPC_SD       = 0x3F << 26,
+#endif
 } MIPSInsn;
 
 /*
@@ -380,6 +408,21 @@ static inline void tcg_out_opc_imm(TCGContext *s, MIPSInsn 
opc,
     tcg_out32(s, inst);
 }
 
+#if TCG_TARGET_REG_BITS == 64
+static inline void tcg_out_opc_imm_64(TCGContext *s, int opc,
+                                      int rd, int rt, int sa)
+{
+    int32_t inst;
+
+    inst = opc;
+    inst |= (rt & 0x1F) << 16;
+    inst |= (rd & 0x1F) << 11;
+    inst |= (sa & 0x1F) << 6;
+    tcg_out32(s, inst);
+}
+#endif
+
+
 /*
  * Type bitfield
  */
@@ -459,7 +502,15 @@ static inline void tcg_out_mov(TCGContext *s, TCGType type,
 {
     /* Simple reg-reg move, optimising out the 'do nothing' case */
     if (ret != arg) {
+#if TCG_TARGET_REG_BITS == 64
+        if (type == TCG_TYPE_I32) {
+            tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
+        } else {
+            tcg_out_opc_reg(s, OPC_DADDU, ret, arg, TCG_REG_ZERO);
+        }
+#else
         tcg_out_opc_reg(s, OPC_ADDU, ret, arg, TCG_REG_ZERO);
+#endif
     }
 }
 
@@ -470,12 +521,21 @@ static inline void tcg_out_movi(TCGContext *s, TCGType 
type,
         tcg_out_opc_imm(s, OPC_ADDIU, reg, TCG_REG_ZERO, arg);
     } else if (arg == (uint16_t)arg) {
         tcg_out_opc_imm(s, OPC_ORI, reg, TCG_REG_ZERO, arg);
-    } else {
+    } else if (arg == (int32_t)arg) {
         tcg_out_opc_imm(s, OPC_LUI, reg, TCG_REG_ZERO, arg >> 16);
         if (arg & 0xffff) {
             tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
         }
     }
+#if TCG_TARGET_REG_BITS == 64
+    /* 64-bit imm */
+    else {
+        tcg_out_opc_imm(s, OPC_LUI, reg, 0, (arg >> 32) & 0xffff);
+        tcg_out_opc_imm(s, OPC_ORI, reg, reg, (arg >> 16) & 0xffff);
+        tcg_out_opc_imm_64(s, OPC_DSLL, reg, reg, 16);
+        tcg_out_opc_imm(s, OPC_ORI, reg, reg, arg & 0xffff);
+    }
+#endif
 }
 
 static inline void tcg_out_bswap16(TCGContext *s, TCGReg ret, TCGReg arg)
@@ -566,7 +626,11 @@ static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, 
TCGReg data,
     if (ofs != lo) {
         tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, ofs - lo);
         if (addr != TCG_REG_ZERO) {
+#if TCG_TARGET_REG_BITS == 64
+            tcg_out_opc_reg(s, OPC_DADDU, TCG_TMP0, TCG_TMP0, addr);
+#else
             tcg_out_opc_reg(s, OPC_ADDU, TCG_TMP0, TCG_TMP0, addr);
+#endif
         }
         addr = TCG_TMP0;
     }
@@ -576,13 +640,29 @@ static void tcg_out_ldst(TCGContext *s, MIPSInsn opc, 
TCGReg data,
 static inline void tcg_out_ld(TCGContext *s, TCGType type, TCGReg arg,
                               TCGReg arg1, intptr_t arg2)
 {
+#if TCG_TARGET_REG_BITS == 64
+    if (type == TCG_TYPE_I32) {
+        tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
+    } else if (type == TCG_TYPE_I64) {
+        tcg_out_ldst(s, OPC_LD, arg, arg1, arg2);
+    }
+#else
     tcg_out_ldst(s, OPC_LW, arg, arg1, arg2);
+#endif
 }
 
 static inline void tcg_out_st(TCGContext *s, TCGType type, TCGReg arg,
                               TCGReg arg1, intptr_t arg2)
 {
+#if TCG_TARGET_REG_BITS == 64
+    if (type == TCG_TYPE_I32) {
+        tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
+    } else if (type == TCG_TYPE_I64) {
+        tcg_out_ldst(s, OPC_SD, arg, arg1, arg2);
+    }
+#else
     tcg_out_ldst(s, OPC_SW, arg, arg1, arg2);
+#endif
 }
 
 static inline bool tcg_out_sti(TCGContext *s, TCGType type, TCGArg val,
@@ -605,6 +685,18 @@ static inline void tcg_out_addi(TCGContext *s, TCGReg reg, 
TCGArg val)
     }
 }
 
+#if TCG_TARGET_REG_BITS == 64
+static inline void tcg_out_daddi(TCGContext *s, int reg, tcg_target_long val)
+{
+    if (val == (int16_t)val) {
+        tcg_out_opc_imm(s, OPC_DADDIU, reg, reg, val);
+    } else {
+        tcg_out_movi(s, TCG_TYPE_PTR, TCG_TMP0, val);
+        tcg_out_opc_reg(s, OPC_DADDU, reg, reg, TCG_REG_AT);
+    }
+}
+#endif
+
 static void tcg_out_addsub2(TCGContext *s, TCGReg rl, TCGReg rh, TCGReg al,
                             TCGReg ah, TCGArg bl, TCGArg bh, bool cbl,
                             bool cbh, bool is_sub)
@@ -1063,7 +1155,11 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, 
TCGReg addrl,
                    TARGET_PAGE_BITS - CPU_TLB_ENTRY_BITS);
     tcg_out_opc_imm(s, OPC_ANDI, TCG_REG_A0, TCG_REG_A0,
                     (CPU_TLB_SIZE - 1) << CPU_TLB_ENTRY_BITS);
+#if TCG_TARGET_REG_BITS == 64
+    tcg_out_opc_reg(s, OPC_DADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
+#else
     tcg_out_opc_reg(s, OPC_ADDU, TCG_REG_A0, TCG_REG_A0, TCG_AREG0);
+#endif
 
     /* Compensate for very large offsets.  */
     if (add_off >= 0x8000) {
@@ -1073,14 +1169,23 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg 
base, TCGReg addrl,
         QEMU_BUILD_BUG_ON(offsetof(CPUArchState,
                                    tlb_table[NB_MMU_MODES - 1][1])
                           > 0x7ff0 + 0x7fff);
+#if TCG_TARGET_REG_BITS == 64
+        tcg_out_opc_imm(s, OPC_DADDIU, TCG_REG_A0, TCG_REG_A0, 0x7ff0);
+#else
         tcg_out_opc_imm(s, OPC_ADDIU, TCG_REG_A0, TCG_REG_A0, 0x7ff0);
+#endif
         cmp_off -= 0x7ff0;
         add_off -= 0x7ff0;
     }
 
     /* Load the (low half) tlb comparator.  */
+#if TCG_TARGET_REG_BITS == 64
+    tcg_out_opc_imm(s, OPC_LWU, TCG_TMP0, TCG_REG_A0,
+                    cmp_off + (TARGET_LONG_BITS == 64 ? LO_OFF : 0));
+#else
     tcg_out_opc_imm(s, OPC_LW, TCG_TMP0, TCG_REG_A0,
                     cmp_off + (TARGET_LONG_BITS == 64 ? LO_OFF : 0));
+#endif
 
     /* We don't currently support unaligned accesses.
        We could do so with mips32r6.  */
@@ -1092,7 +1197,11 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, 
TCGReg addrl,
     tcg_out_movi(s, TCG_TYPE_I32, TCG_TMP1,
                  TARGET_PAGE_MASK | ((1 << a_bits) - 1));
     if (TARGET_LONG_BITS == 32) {
+#if TCG_TARGET_REG_BITS == 64
+        tcg_out_opc_imm(s, OPC_LD, TCG_REG_A0, TCG_REG_A0, add_off);
+#else
         tcg_out_opc_imm(s, OPC_LW, TCG_REG_A0, TCG_REG_A0, add_off);
+#endif
     }
     tcg_out_opc_reg(s, OPC_AND, TCG_TMP1, TCG_TMP1, addrl);
 
@@ -1114,7 +1223,11 @@ static void tcg_out_tlb_load(TCGContext *s, TCGReg base, 
TCGReg addrl,
     }
 
     /* delay slot */
+#if TCG_TARGET_REG_BITS == 64
+    tcg_out_opc_reg(s, OPC_DADDU, base, TCG_REG_A0, addrl);
+#else
     tcg_out_opc_reg(s, OPC_ADDU, base, TCG_REG_A0, addrl);
+#endif
 }
 
 static void add_qemu_ldst_label(TCGContext *s, int is_ld, TCGMemOpIdx oi,
@@ -1163,6 +1276,7 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
     tcg_out_mov(s, TCG_TYPE_PTR, tcg_target_call_iarg_regs[0], TCG_AREG0);
 
     v0 = l->datalo_reg;
+#if TCG_TARGET_REG_BITS == 32
     if ((opc & MO_SIZE) == MO_64) {
         /* We eliminated V0 from the possible output registers, so it
            cannot be clobbered here.  So we must move V1 first.  */
@@ -1173,11 +1287,21 @@ static void tcg_out_qemu_ld_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
             tcg_out_mov(s, TCG_TYPE_I32, l->datahi_reg, TCG_REG_V1);
         }
     }
+#endif
 
     reloc_pc16(s->code_ptr, l->raddr);
     tcg_out_opc_br(s, OPC_BEQ, TCG_REG_ZERO, TCG_REG_ZERO);
     /* delay slot */
+#if TCG_TARGET_REG_BITS == 32
     tcg_out_mov(s, TCG_TYPE_REG, v0, TCG_REG_V0);
+#else
+    /* ext unsigned long(32) -> 64-bit */
+    if ((opc & MO_SIZE) == MO_32) {
+        tcg_out_mov(s, TCG_TYPE_I32, v0, TCG_REG_V0);
+    } else {
+        tcg_out_mov(s, TCG_TYPE_REG, v0, TCG_REG_V0);
+    }
+#endif
 }
 
 static void tcg_out_qemu_st_slow_path(TCGContext *s, TCGLabelQemuLdst *l)
@@ -1210,7 +1334,11 @@ static void tcg_out_qemu_st_slow_path(TCGContext *s, 
TCGLabelQemuLdst *l)
         i = tcg_out_call_iarg_reg(s, i, l->datalo_reg);
         break;
     case MO_64:
+#if TCG_TARGET_REG_BITS == 64
+        i = tcg_out_call_iarg_reg(s, i, l->datalo_reg);
+#else
         i = tcg_out_call_iarg_reg2(s, i, l->datalo_reg, l->datahi_reg);
+#endif
         break;
     default:
         tcg_abort();
@@ -1265,8 +1393,12 @@ static void tcg_out_qemu_ld_direct(TCGContext *s, TCGReg 
datalo, TCGReg datahi,
         tcg_out_bswap32(s, datahi, TCG_TMP1);
         break;
     case MO_Q:
+#if TCG_TARGET_REG_BITS == 64
+        tcg_out_opc_imm(s, OPC_LD, datalo, base, 0);
+#else
         tcg_out_opc_imm(s, OPC_LW, datalo, base, LO_OFF);
         tcg_out_opc_imm(s, OPC_LW, datahi, base, HI_OFF);
+#endif
         break;
     default:
         tcg_abort();
@@ -1287,7 +1419,11 @@ static void tcg_out_qemu_ld(TCGContext *s, const TCGArg 
*args, bool is_64)
     TCGReg base = TCG_REG_V0;
 
     data_regl = *args++;
+#if TCG_TARGET_REG_BITS == 64
+    data_regh = 0;
+#else
     data_regh = (is_64 ? *args++ : 0);
+#endif
     addr_regl = *args++;
     addr_regh = (TARGET_LONG_BITS == 64 ? *args++ : 0);
     oi = *args++;
@@ -1343,8 +1479,12 @@ static void tcg_out_qemu_st_direct(TCGContext *s, TCGReg 
datalo, TCGReg datahi,
         tcg_out_opc_imm(s, OPC_SW, TCG_TMP1, base, LO_OFF);
         break;
     case MO_64:
+#if TCG_TARGET_REG_BITS == 64
+        tcg_out_opc_imm(s, OPC_SD, datalo, base, 0);
+#else
         tcg_out_opc_imm(s, OPC_SW, datalo, base, LO_OFF);
         tcg_out_opc_imm(s, OPC_SW, datahi, base, HI_OFF);
+#endif
         break;
 
     default:
@@ -1363,7 +1503,11 @@ static void tcg_out_qemu_st(TCGContext *s, const TCGArg 
*args, bool is_64)
 #endif
 
     data_regl = *args++;
+#if TCG_TARGET_REG_BITS == 64
+    data_regh = 0;
+#else
     data_regh = (is_64 ? *args++ : 0);
+#endif
     addr_regl = *args++;
     addr_regh = (TARGET_LONG_BITS == 64 ? *args++ : 0);
     oi = *args++;
@@ -1481,6 +1625,15 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
         goto do_ldst;
     case INDEX_op_st_i32:
         i1 = OPC_SW;
+        goto do_ldst;
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_ld_i64:
+        i1 = OPC_LD;
+        goto do_ldst;
+    case INDEX_op_st_i64:
+        i1 = OPC_SD;
+        goto do_ldst;
+#endif
     do_ldst:
         tcg_out_ldst(s, i1, a0, a1, a2);
         break;
@@ -1488,6 +1641,11 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
     case INDEX_op_add_i32:
         i1 = OPC_ADDU, i2 = OPC_ADDIU;
         goto do_binary;
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_add_i64:
+        i1 = OPC_DADDU, i2 = OPC_DADDIU;
+        goto do_binary;
+#endif
     case INDEX_op_or_i32:
         i1 = OPC_OR, i2 = OPC_ORI;
         goto do_binary;
@@ -1683,6 +1841,9 @@ static inline void tcg_out_op(TCGContext *s, TCGOpcode 
opc,
         break;
     case INDEX_op_mov_i32:  /* Always emitted via tcg_out_mov.  */
     case INDEX_op_movi_i32: /* Always emitted via tcg_out_movi.  */
+#if TCG_TARGET_REG_BITS == 64
+    case INDEX_op_movi_i64:
+#endif
     case INDEX_op_call:     /* Always emitted via tcg_out_call.  */
     default:
         tcg_abort();
@@ -1702,8 +1863,14 @@ static const TCGTargetOpDef mips_op_defs[] = {
     { INDEX_op_st8_i32, { "rZ", "r" } },
     { INDEX_op_st16_i32, { "rZ", "r" } },
     { INDEX_op_st_i32, { "rZ", "r" } },
-
+#if TCG_TARGET_REG_BITS == 64
+    { INDEX_op_ld_i64, { "r", "r" } },
+    { INDEX_op_st_i64, { "rZ", "r" } },
+#endif
     { INDEX_op_add_i32, { "r", "rZ", "rJ" } },
+#if TCG_TARGET_REG_BITS == 64
+    { INDEX_op_add_i64, { "r", "rZ", "rJ" } },
+#endif
     { INDEX_op_mul_i32, { "r", "rZ", "rZ" } },
 #if !use_mips32r6_instructions
     { INDEX_op_muls2_i32, { "r", "r", "rZ", "rZ" } },
@@ -1753,8 +1920,13 @@ static const TCGTargetOpDef mips_op_defs[] = {
 #if TARGET_LONG_BITS == 32
     { INDEX_op_qemu_ld_i32, { "L", "lZ" } },
     { INDEX_op_qemu_st_i32, { "SZ", "SZ" } },
+  #if TCG_TARGET_REG_BITS == 64
+    { INDEX_op_qemu_ld_i64, { "L", "lZ" } },
+    { INDEX_op_qemu_st_i64, { "SZ", "SZ" } },
+  #else
     { INDEX_op_qemu_ld_i64, { "L", "L", "lZ" } },
     { INDEX_op_qemu_st_i64, { "SZ", "SZ", "SZ" } },
+  #endif
 #else
     { INDEX_op_qemu_ld_i32, { "L", "lZ", "lZ" } },
     { INDEX_op_qemu_st_i32, { "SZ", "SZ", "SZ" } },
@@ -1862,22 +2034,34 @@ static void tcg_target_detect_isa(void)
 static void tcg_target_qemu_prologue(TCGContext *s)
 {
     int i, frame_size;
+#if TCG_TARGET_REG_BITS == 64
+  #define SAVE_REG_SIZE 8
+  #define SAVE_REG_TYPE TCG_TYPE_I64
+#else
+  #define SAVE_REG_SIZE 4
+  #define SAVE_REG_TYPE TCG_TYPE_I32
+#endif
 
     /* reserve some stack space, also for TCG temps. */
-    frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * 4
+    frame_size = ARRAY_SIZE(tcg_target_callee_save_regs) * SAVE_REG_SIZE
                  + TCG_STATIC_CALL_ARGS_SIZE
                  + CPU_TEMP_BUF_NLONGS * sizeof(long);
     frame_size = (frame_size + TCG_TARGET_STACK_ALIGN - 1) &
                  ~(TCG_TARGET_STACK_ALIGN - 1);
-    tcg_set_frame(s, TCG_REG_SP, ARRAY_SIZE(tcg_target_callee_save_regs) * 4
+    tcg_set_frame(s, TCG_REG_SP,
+                  ARRAY_SIZE(tcg_target_callee_save_regs) * SAVE_REG_SIZE
                   + TCG_STATIC_CALL_ARGS_SIZE,
                   CPU_TEMP_BUF_NLONGS * sizeof(long));
 
     /* TB prologue */
+#if TCG_TARGET_REG_BITS == 64
+    tcg_out_daddi(s, TCG_REG_SP, -frame_size);
+#else
     tcg_out_addi(s, TCG_REG_SP, -frame_size);
+#endif
     for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
-        tcg_out_st(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
-                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
+        tcg_out_st(s, SAVE_REG_TYPE, tcg_target_callee_save_regs[i],
+                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * SAVE_REG_SIZE);
     }
 
     /* Call generated code */
@@ -1887,12 +2071,16 @@ static void tcg_target_qemu_prologue(TCGContext *s)
 
     /* TB epilogue */
     for(i = 0 ; i < ARRAY_SIZE(tcg_target_callee_save_regs) ; i++) {
-        tcg_out_ld(s, TCG_TYPE_I32, tcg_target_callee_save_regs[i],
-                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * 4);
+        tcg_out_ld(s, SAVE_REG_TYPE, tcg_target_callee_save_regs[i],
+                   TCG_REG_SP, TCG_STATIC_CALL_ARGS_SIZE + i * SAVE_REG_SIZE);
     }
 
     tcg_out_opc_reg(s, OPC_JR, 0, TCG_REG_RA, 0);
+#if TCG_TARGET_REG_BITS == 64
+    tcg_out_daddi(s, TCG_REG_SP, frame_size);
+#else
     tcg_out_addi(s, TCG_REG_SP, frame_size);
+#endif
 }
 
 static void tcg_target_init(TCGContext *s)
@@ -1910,10 +2098,17 @@ static void tcg_target_init(TCGContext *s)
                    (1 << TCG_REG_T1) |
                    (1 << TCG_REG_T2) |
                    (1 << TCG_REG_T3) |
+#if TCG_TARGET_REG_BITS == 32
                    (1 << TCG_REG_T4) |
                    (1 << TCG_REG_T5) |
                    (1 << TCG_REG_T6) |
                    (1 << TCG_REG_T7) |
+#else
+                   (1 << TCG_REG_A4) |
+                   (1 << TCG_REG_A5) |
+                   (1 << TCG_REG_A6) |
+                   (1 << TCG_REG_A7) |
+#endif
                    (1 << TCG_REG_T8) |
                    (1 << TCG_REG_T9));
 
-- 
2.1.0



Reply via email to