diff options
author | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-03-31 03:47:03 +0000 |
---|---|---|
committer | pbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162> | 2008-03-31 03:47:03 +0000 |
commit | b010980544b543d421b3f514bba3cafc59b3a3db (patch) | |
tree | 695a66970b73a639ef7baf4b820364f04ed81a49 | |
parent | d9ba48308d50ae08e87dc4ea24cb9783b0568c08 (diff) |
ARM TCG conversion 9/16.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4146 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r-- | target-arm/exec.h | 2 | ||||
-rw-r--r-- | target-arm/helper.c | 8 | ||||
-rw-r--r-- | target-arm/helpers.h | 14 | ||||
-rw-r--r-- | target-arm/op.c | 42 | ||||
-rw-r--r-- | target-arm/op_helper.c | 33 | ||||
-rw-r--r-- | target-arm/op_mem.h | 31 | ||||
-rw-r--r-- | target-arm/translate.c | 754 | ||||
-rw-r--r-- | tcg/tcg-op.h | 12 |
8 files changed, 487 insertions, 409 deletions
diff --git a/target-arm/exec.h b/target-arm/exec.h index cb202062d5..9b284f2872 100644 --- a/target-arm/exec.h +++ b/target-arm/exec.h @@ -72,8 +72,6 @@ void helper_set_cp(CPUState *, uint32_t, uint32_t); uint32_t helper_get_cp(CPUState *, uint32_t); void helper_set_cp15(CPUState *, uint32_t, uint32_t); uint32_t helper_get_cp15(CPUState *, uint32_t); -void helper_set_r13_banked(CPUState *env, int mode, uint32_t val); -uint32_t helper_get_r13_banked(CPUState *env, int mode); uint32_t helper_v7m_mrs(CPUState *env, int reg); void helper_v7m_msr(CPUState *env, int reg, uint32_t val); diff --git a/target-arm/helper.c b/target-arm/helper.c index ee6cd598fd..8985c8855a 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -513,12 +513,12 @@ void switch_mode(CPUState *env, int mode) cpu_abort(env, "Tried to switch out of user mode\n"); } -void helper_set_r13_banked(CPUState *env, int mode, uint32_t val) +void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val) { cpu_abort(env, "banked r13 write\n"); } -uint32_t helper_get_r13_banked(CPUState *env, int mode) +uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode) { cpu_abort(env, "banked r13 read\n"); return 0; @@ -1793,12 +1793,12 @@ bad_reg: return 0; } -void helper_set_r13_banked(CPUState *env, int mode, uint32_t val) +void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val) { env->banked_r13[bank_number(mode)] = val; } -uint32_t helper_get_r13_banked(CPUState *env, int mode) +uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode) { return env->banked_r13[bank_number(mode)]; } diff --git a/target-arm/helpers.h b/target-arm/helpers.h index bd9962ef1f..12c9343f98 100644 --- a/target-arm/helpers.h +++ b/target-arm/helpers.h @@ -19,6 +19,13 @@ static inline void gen_helper_##name(TCGv arg1, TCGv arg2) \ { \ tcg_gen_helper_0_2(helper_##name, arg1, arg2); \ } +#define DEF_HELPER_0_3(name, ret, args) \ +DEF_HELPER(name, ret, args) \ +static inline void gen_helper_##name( \ + TCGv arg1, TCGv arg2, TCGv arg3) \ +{ \ + tcg_gen_helper_0_3(helper_##name, arg1, arg2, arg3); \ +} #define DEF_HELPER_1_0(name, ret, args) \ DEF_HELPER(name, ret, args) \ static inline void gen_helper_##name(TCGv ret) \ @@ -48,6 +55,7 @@ static inline void gen_helper_##name(TCGv ret, \ #define DEF_HELPER_0_0 DEF_HELPER #define DEF_HELPER_0_1 DEF_HELPER #define DEF_HELPER_0_2 DEF_HELPER +#define DEF_HELPER_0_3 DEF_HELPER #define DEF_HELPER_1_0 DEF_HELPER #define DEF_HELPER_1_1 DEF_HELPER #define DEF_HELPER_1_2 DEF_HELPER @@ -108,6 +116,12 @@ DEF_HELPER_0_0(wfi, void, (void)) DEF_HELPER_0_2(cpsr_write, void, (uint32_t, uint32_t)) DEF_HELPER_1_0(cpsr_read, uint32_t, (void)) +DEF_HELPER_1_2(get_r13_banked, uint32_t, (CPUState *, uint32_t)) +DEF_HELPER_0_3(set_r13_banked, void, (CPUState *, uint32_t, uint32_t)) + +DEF_HELPER_1_1(get_user_reg, uint32_t, (uint32_t)) +DEF_HELPER_0_2(set_user_reg, void, (uint32_t, uint32_t)) + #undef DEF_HELPER #undef DEF_HELPER_0_0 #undef DEF_HELPER_0_1 diff --git a/target-arm/op.c b/target-arm/op.c index 057a08bfc2..74bf62b723 100644 --- a/target-arm/op.c +++ b/target-arm/op.c @@ -589,48 +589,6 @@ void OPPROTO op_movl_T0_cp15(void) FORCE_RET(); } -/* Access to user mode registers from privileged modes. */ -void OPPROTO op_movl_T0_user(void) -{ - int regno = PARAM1; - if (regno == 13) { - T0 = env->banked_r13[0]; - } else if (regno == 14) { - T0 = env->banked_r14[0]; - } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { - T0 = env->usr_regs[regno - 8]; - } else { - T0 = env->regs[regno]; - } - FORCE_RET(); -} - - -void OPPROTO op_movl_user_T0(void) -{ - int regno = PARAM1; - if (regno == 13) { - env->banked_r13[0] = T0; - } else if (regno == 14) { - env->banked_r14[0] = T0; - } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { - env->usr_regs[regno - 8] = T0; - } else { - env->regs[regno] = T0; - } - FORCE_RET(); -} - -void OPPROTO op_movl_T1_r13_banked(void) -{ - T1 = helper_get_r13_banked(env, PARAM1); -} - -void OPPROTO op_movl_r13_T1_banked(void) -{ - helper_set_r13_banked(env, PARAM1, T1); -} - void OPPROTO op_v7m_mrs_T0(void) { T0 = helper_v7m_mrs(env, PARAM1); diff --git a/target-arm/op_helper.c b/target-arm/op_helper.c index d7541d6a65..939aebfe6c 100644 --- a/target-arm/op_helper.c +++ b/target-arm/op_helper.c @@ -459,3 +459,36 @@ void HELPER(cpsr_write)(uint32_t val, uint32_t mask) { cpsr_write(env, val, mask); } + +/* Access to user mode registers from privileged modes. */ +uint32_t HELPER(get_user_reg)(uint32_t regno) +{ + uint32_t val; + + if (regno == 13) { + val = env->banked_r13[0]; + } else if (regno == 14) { + val = env->banked_r14[0]; + } else if (regno >= 8 + && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { + val = env->usr_regs[regno - 8]; + } else { + val = env->regs[regno]; + } + return val; +} + +void HELPER(set_user_reg)(uint32_t regno, uint32_t val) +{ + if (regno == 13) { + env->banked_r13[0] = val; + } else if (regno == 14) { + env->banked_r14[0] = val; + } else if (regno >= 8 + && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { + env->usr_regs[regno - 8] = val; + } else { + env->regs[regno] = val; + } +} + diff --git a/target-arm/op_mem.h b/target-arm/op_mem.h index b12b63c5f1..f11c498213 100644 --- a/target-arm/op_mem.h +++ b/target-arm/op_mem.h @@ -1,36 +1,5 @@ /* ARM memory operations. */ -void helper_ld(uint32_t); -/* Load from address T1 into T0. */ -#define MEM_LD_OP(name) \ -void OPPROTO glue(op_ld##name,MEMSUFFIX)(void) \ -{ \ - T0 = glue(ld##name,MEMSUFFIX)(T1); \ - FORCE_RET(); \ -} - -MEM_LD_OP(ub) -MEM_LD_OP(sb) -MEM_LD_OP(uw) -MEM_LD_OP(sw) -MEM_LD_OP(l) - -#undef MEM_LD_OP - -/* Store T0 to address T1. */ -#define MEM_ST_OP(name) \ -void OPPROTO glue(op_st##name,MEMSUFFIX)(void) \ -{ \ - glue(st##name,MEMSUFFIX)(T1, T0); \ - FORCE_RET(); \ -} - -MEM_ST_OP(b) -MEM_ST_OP(w) -MEM_ST_OP(l) - -#undef MEM_ST_OP - /* Swap T0 with memory at address T1. */ /* ??? Is this exception safe? */ #define MEM_SWP_OP(name, lname) \ diff --git a/target-arm/translate.c b/target-arm/translate.c index dc3fc9ad09..89515cc819 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -222,7 +222,6 @@ static void store_reg(DisasContext *s, int reg, TCGv var) #define gen_sxtb16(var) gen_helper_sxtb16(var, var) #define gen_uxtb16(var) gen_helper_uxtb16(var, var) -#define gen_op_rev_T0() tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]) #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1]) @@ -804,6 +803,51 @@ static inline void gen_bx_T0(DisasContext *s) gen_op_##name##_kernel(); \ } while (0) #endif +static inline TCGv gen_ld8s(TCGv addr, int index) +{ + TCGv tmp = new_tmp(); + tcg_gen_qemu_ld8s(tmp, addr, index); + return tmp; +} +static inline TCGv gen_ld8u(TCGv addr, int index) +{ + TCGv tmp = new_tmp(); + tcg_gen_qemu_ld8u(tmp, addr, index); + return tmp; +} +static inline TCGv gen_ld16s(TCGv addr, int index) +{ + TCGv tmp = new_tmp(); + tcg_gen_qemu_ld16s(tmp, addr, index); + return tmp; +} +static inline TCGv gen_ld16u(TCGv addr, int index) +{ + TCGv tmp = new_tmp(); + tcg_gen_qemu_ld16u(tmp, addr, index); + return tmp; +} +static inline TCGv gen_ld32(TCGv addr, int index) +{ + TCGv tmp = new_tmp(); + tcg_gen_qemu_ld32u(tmp, addr, index); + return tmp; +} +static inline void gen_st8(TCGv val, TCGv addr, int index) +{ + tcg_gen_qemu_st8(val, addr, index); + dead_tmp(val); +} +static inline void gen_st16(TCGv val, TCGv addr, int index) +{ + tcg_gen_qemu_st16(val, addr, index); + dead_tmp(val); +} +static inline void gen_st32(TCGv val, TCGv addr, int index) +{ + tcg_gen_qemu_st32(val, addr, index); + dead_tmp(val); +} static inline void gen_movl_T0_reg(DisasContext *s, int reg) { @@ -859,7 +903,8 @@ static inline void gen_lookup_tb(DisasContext *s) s->is_jmp = DISAS_UPDATE; } -static inline void gen_add_data_offset(DisasContext *s, unsigned int insn) +static inline void gen_add_data_offset(DisasContext *s, unsigned int insn, + TCGv var) { int val, rm, shift, shiftop; TCGv offset; @@ -870,7 +915,7 @@ static inline void gen_add_data_offset(DisasContext *s, unsigned int insn) if (!(insn & (1 << 23))) val = -val; if (val != 0) - gen_op_addl_T1_im(val); + tcg_gen_addi_i32(var, var, val); } else { /* shift/register */ rm = (insn) & 0xf; @@ -879,15 +924,15 @@ static inline void gen_add_data_offset(DisasContext *s, unsigned int insn) offset = load_reg(s, rm); gen_arm_shift_im(offset, shiftop, shift, 0); if (!(insn & (1 << 23))) - tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset); + tcg_gen_sub_i32(var, var, offset); else - tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset); + tcg_gen_add_i32(var, var, offset); dead_tmp(offset); } } static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, - int extra) + int extra, TCGv var) { int val, rm; TCGv offset; @@ -899,17 +944,17 @@ static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, val = -val; val += extra; if (val != 0) - gen_op_addl_T1_im(val); + tcg_gen_addi_i32(var, var, val); } else { /* register */ if (extra) - gen_op_addl_T1_im(extra); + tcg_gen_addi_i32(var, var, extra); rm = (insn) & 0xf; offset = load_reg(s, rm); if (!(insn & (1 << 23))) - tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset); + tcg_gen_sub_i32(var, var, offset); else - tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset); + tcg_gen_add_i32(var, var, offset); dead_tmp(offset); } } @@ -1090,6 +1135,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) { int rd, wrd; int rdhi, rdlo, rd0, rd1, i; + TCGv tmp; if ((insn & 0x0e000e00) == 0x0c000000) { if ((insn & 0x0fe00ff0) == 0x0c400000) { @@ -1114,7 +1160,9 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) return 1; if (insn & ARM_CP_RW_BIT) { if ((insn >> 28) == 0xf) { /* WLDRW wCx */ - gen_ldst(ldl, s); + tmp = gen_ld32(cpu_T[1], IS_USER(s)); + tcg_gen_mov_i32(cpu_T[0], tmp); + dead_tmp(tmp); gen_op_iwmmxt_movl_wCx_T0(wrd); } else { if (insn & (1 << 8)) @@ -1132,7 +1180,9 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) } else { if ((insn >> 28) == 0xf) { /* WSTRW wCx */ gen_op_iwmmxt_movl_T0_wCx(wrd); - gen_ldst(stl, s); + tmp = new_tmp(); + tcg_gen_mov_i32(tmp, cpu_T[0]); + gen_st32(tmp, cpu_T[1], IS_USER(s)); } else { gen_op_iwmmxt_movq_M0_wRn(wrd); if (insn & (1 << 8)) @@ -2970,12 +3020,12 @@ static void gen_exception_return(DisasContext *s) s->is_jmp = DISAS_UPDATE; } -/* Generate a v6 exception return. */ -static void gen_rfe(DisasContext *s) +/* Generate a v6 exception return. Marks both values as dead. */ +static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr) { - gen_set_cpsr(cpu_T[0], 0xffffffff); - gen_op_movl_T0_T2(); - gen_set_pc_T0(); + gen_set_cpsr(cpsr, 0xffffffff); + dead_tmp(cpsr); + store_reg(s, 15, pc); s->is_jmp = DISAS_UPDATE; } @@ -3288,6 +3338,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) int shift; uint32_t mask; int n; + TCGv tmp; if (!vfp_enabled(env)) return 1; @@ -3316,36 +3367,50 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) for (pass = 0; pass < 2; pass++) { if (size == 2) { if (load) { - gen_ldst(ldl, s); + tmp = gen_ld32(cpu_T[1], IS_USER(s)); + tcg_gen_mov_i32(cpu_T[0], tmp); + dead_tmp(tmp); NEON_SET_REG(T0, rd, pass); } else { NEON_GET_REG(T0, rd, pass); - gen_ldst(stl, s); + tmp = new_tmp(); + tcg_gen_mov_i32(tmp, cpu_T[0]); + gen_st32(tmp, cpu_T[1], IS_USER(s)); } gen_op_addl_T1_im(stride); } else if (size == 1) { if (load) { - gen_ldst(lduw, s); + tmp = gen_ld16u(cpu_T[1], IS_USER(s)); + tcg_gen_mov_i32(cpu_T[0], tmp); + dead_tmp(tmp); gen_op_addl_T1_im(stride); gen_op_movl_T2_T0(); - gen_ldst(lduw, s); + tmp = gen_ld16u(cpu_T[1], IS_USER(s)); + tcg_gen_mov_i32(cpu_T[0], tmp); + dead_tmp(tmp); gen_op_addl_T1_im(stride); gen_op_neon_insert_elt(16, 0xffff); NEON_SET_REG(T2, rd, pass); } else { NEON_GET_REG(T2, rd, pass); gen_op_movl_T0_T2(); - gen_ldst(stw, s); + tmp = new_tmp(); + tcg_gen_mov_i32(tmp, cpu_T[0]); + gen_st16(tmp, cpu_T[1], IS_USER(s)); gen_op_addl_T1_im(stride); gen_op_neon_extract_elt(16, 0xffff0000); - gen_ldst(stw, s); + tmp = new_tmp(); + tcg_gen_mov_i32(tmp, cpu_T[0]); + gen_st16(tmp, cpu_T[1], IS_USER(s)); gen_op_addl_T1_im(stride); } } else /* size == 0 */ { if (load) { mask = 0xff; for (n = 0; n < 4; n++) { - gen_ldst(ldub, s); + tmp = gen_ld8u(cpu_T[1], IS_USER(s)); + tcg_gen_mov_i32(cpu_T[0], tmp); + dead_tmp(tmp); gen_op_addl_T1_im(stride); if (n == 0) { gen_op_movl_T2_T0(); @@ -3364,7 +3429,9 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) } else { gen_op_neon_extract_elt(n * 8, mask); } - gen_ldst(stb, s); + tmp = new_tmp(); + tcg_gen_mov_i32(tmp, cpu_T[0]); + gen_st8(tmp, cpu_T[1], IS_USER(s)); gen_op_addl_T1_im(stride); mask <<= 8; } @@ -3387,15 +3454,21 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) for (reg = 0; reg < nregs; reg++) { switch (size) { case 0: - gen_ldst(ldub, s); + tmp = gen_ld8u(cpu_T[1], IS_USER(s)); + tcg_gen_mov_i32(cpu_T[0], tmp); + dead_tmp(tmp); gen_op_neon_dup_u8(0); break; case 1: - gen_ldst(lduw, s); + tmp = gen_ld16u(cpu_T[1], IS_USER(s)); + tcg_gen_mov_i32(cpu_T[0], tmp); + dead_tmp(tmp); gen_op_neon_dup_low16(); break; case 2: - gen_ldst(ldl, s); + tmp = gen_ld32(cpu_T[0], IS_USER(s)); + tcg_gen_mov_i32(cpu_T[0], tmp); + dead_tmp(tmp); break; case 3: return 1; @@ -3437,19 +3510,22 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) } switch (size) { case 0: - gen_ldst(ldub, s); + tmp = gen_ld8u(cpu_T[1], IS_USER(s)); break; case 1: - gen_ldst(lduw, s); + tmp = gen_ld16u(cpu_T[1], IS_USER(s)); break; case 2: - gen_ldst(ldl, s); - NEON_SET_REG(T0, rd, pass); + tmp = gen_ld32(cpu_T[1], IS_USER(s)); break; } + tcg_gen_mov_i32(cpu_T[0], tmp); + dead_tmp(tmp); if (size != 2) { gen_op_neon_insert_elt(shift, ~mask); NEON_SET_REG(T0, rd, pass); + } else { + NEON_SET_REG(T0, rd, pass); } } else { /* Store */ if (size == 2) { @@ -3458,15 +3534,17 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) NEON_GET_REG(T2, rd, pass); gen_op_neon_extract_elt(shift, mask); } + tmp = new_tmp(); + tcg_gen_mov_i32(tmp, cpu_T[0]); switch (size) { case 0: - gen_ldst(stb, s); + gen_st8(tmp, cpu_T[1], IS_USER(s)); break; case 1: - gen_ldst(stw, s); + gen_st16(tmp, cpu_T[1], IS_USER(s)); break; case 2: - gen_ldst(stl, s); + gen_st32(tmp, cpu_T[1], IS_USER(s)); break; } } @@ -4647,7 +4725,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) NEON_GET_REG(T0, rm, pass * 2); NEON_GET_REG(T1, rm, pass * 2 + 1); switch (size) { - case 0: gen_op_rev_T0(); break; + case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break; case 1: gen_swap_half(cpu_T[0]); break; case 2: /* no-op */ break; default: abort(); @@ -4658,7 +4736,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) } else { gen_op_movl_T0_T1(); switch (size) { - case 0: gen_op_rev_T0(); break; + case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break; case 1: gen_swap_half(cpu_T[0]); break; default: abort(); } @@ -4827,7 +4905,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) switch (op) { case 1: /* VREV32 */ switch (size) { - case 0: gen_op_rev_T0(); break; + case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break; case 1: gen_swap_half(cpu_T[0]); break; default: return 1; } @@ -5099,6 +5177,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) TCGv tmp; TCGv tmp2; TCGv tmp3; + TCGv addr; insn = ldl_code(s->pc); s->pc += 4; @@ -5160,9 +5239,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) ARCH(6); op1 = (insn & 0x1f); if (op1 == (env->uncached_cpsr & CPSR_M)) { - gen_movl_T1_reg(s, 13); + addr = load_reg(s, 13); } else { - gen_op_movl_T1_r13_banked(op1); + addr = new_tmp(); + gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1)); } i = (insn >> 23) & 3; switch (i) { @@ -5173,12 +5253,13 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) default: abort(); } if (offset) - gen_op_addl_T1_im(offset); - gen_movl_T0_reg(s, 14); - gen_ldst(stl, s); - gen_helper_cpsr_read(cpu_T[0]); - gen_op_addl_T1_im(4); - gen_ldst(stl, s); + tcg_gen_addi_i32(addr, addr, offset); + tmp = load_reg(s, 14); + gen_st32(tmp, addr, 0); + tmp = new_tmp(); + gen_helper_cpsr_read(tmp); + tcg_gen_addi_i32(addr, addr, 4); + gen_st32(tmp, addr, 0); if (insn & (1 << 21)) { /* Base writeback. */ switch (i) { @@ -5189,12 +5270,14 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) default: abort(); } if (offset) - gen_op_addl_T1_im(offset); + tcg_gen_addi_i32(addr, tmp, offset); if (op1 == (env->uncached_cpsr & CPSR_M)) { gen_movl_reg_T1(s, 13); } else { - gen_op_movl_r13_T1_banked(op1); + gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), cpu_T[1]); } + } else { + dead_tmp(addr); } } else if ((insn & 0x0e5fffe0) == 0x081d0a00) { /* rfe */ @@ -5203,36 +5286,37 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) goto illegal_op; ARCH(6); rn = (insn >> 16) & 0xf; - gen_movl_T1_reg(s, rn); + addr = load_reg(s, rn); i = (insn >> 23) & 3; switch (i) { - case 0: offset = 0; break; /* DA */ - case 1: offset = -4; break; /* DB */ - case 2: offset = 4; break; /* IA */ - case 3: offset = 8; break; /* IB */ + case 0: offset = -4; break; /* DA */ + case 1: offset = -8; break; /* DB */ + case 2: offset = 0; break; /* IA */ + case 3: offset = 4; break; /* IB */ default: abort(); } if (offset) - gen_op_addl_T1_im(offset); - /* Load CPSR into T2 and PC into T0. */ - gen_ldst(ldl, s); - gen_op_movl_T2_T0(); - gen_op_addl_T1_im(-4); - gen_ldst(ldl, s); + tcg_gen_addi_i32(addr, addr, offset); + /* Load PC into tmp and CPSR into tmp2. */ + tmp = gen_ld32(addr, 0); + tcg_gen_addi_i32(addr, addr, 4); + tmp2 = gen_ld32(addr, 0); if (insn & (1 << 21)) { /* Base writeback. */ switch (i) { - case 0: offset = -4; break; - case 1: offset = 0; break; - case 2: offset = 8; break; - case 3: offset = 4; break; + case 0: offset = -8; break; + case 1: offset = -4; break; + case 2: offset = 4; break; + case 3: offset = 0; break; default: abort(); } if (offset) - gen_op_addl_T1_im(offset); - gen_movl_reg_T1(s, rn); + tcg_gen_addi_i32(addr, addr, offset); + store_reg(s, rn, addr); + } else { + dead_tmp(addr); } - gen_rfe(s); + gen_rfe(s, tmp, tmp2); } else if ((insn & 0x0e000000) == 0x0a000000) { /* branch link and change to thumb (blx <offset>) */ int32_t offset; @@ -5707,22 +5791,22 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) /* Misc load/store */ rn = (insn >> 16) & 0xf; rd = (insn >> 12) & 0xf; - gen_movl_T1_reg(s, rn); + addr = load_reg(s, rn); if (insn & (1 << 24)) - gen_add_datah_offset(s, insn, 0); + gen_add_datah_offset(s, insn, 0, addr); address_offset = 0; if (insn & (1 << 20)) { /* load */ switch(sh) { case 1: - gen_ldst(lduw, s); + tmp = gen_ld16u(addr, IS_USER(s)); break; case 2: - gen_ldst(ldsb, s); + tmp = gen_ld8s(addr, IS_USER(s)); break; default: case 3: - gen_ldst(ldsw, s); + tmp = gen_ld16s(addr, IS_USER(s)); break; } load = 1; @@ -5730,26 +5814,26 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) /* doubleword */ if (sh & 1) { /* store */ - gen_movl_T0_reg(s, rd); - gen_ldst(stl, s); - gen_op_addl_T1_im(4); - gen_movl_T0_reg(s, rd + 1); - gen_ldst(stl, s); + tmp = load_reg(s, rd); + gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_addi_i32(addr, addr, 4); + tmp = load_reg(s, rd + 1); + gen_st32(tmp, addr, IS_USER(s)); load = 0; } else { /* load */ - gen_ldst(ldl, s); - gen_movl_reg_T0(s, rd); - gen_op_addl_T1_im(4); - gen_ldst(ldl, s); + tmp = gen_ld32(addr, IS_USER(s)); + store_reg(s, rd, tmp); + tcg_gen_addi_i32(addr, addr, 4); + tmp = gen_ld32(addr, IS_USER(s)); rd++; load = 1; } address_offset = -4; } else { /* store */ - gen_movl_T0_reg(s, rd); - gen_ldst(stw, s); + tmp = load_reg(s, rd); + gen_st16(tmp, addr, IS_USER(s)); load = 0; } /* Perform base writeback before the loaded value to @@ -5757,16 +5841,18 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) ldrd with base writeback is is undefined if the destination and index registers overlap. */ if (!(insn & (1 << 24))) { - gen_add_datah_offset(s, insn, address_offset); - gen_movl_reg_T1(s, rn); + gen_add_datah_offset(s, insn, address_offset, addr); + store_reg(s, rn, addr); } else if (insn & (1 << 21)) { if (address_offset) - gen_op_addl_T1_im(address_offset); - gen_movl_reg_T1(s, rn); + tcg_gen_addi_i32(addr, addr, address_offset); + store_reg(s, rn, addr); + } else { + dead_tmp(addr); } if (load) { /* Complete the load. */ - gen_movl_reg_T0(s, rd); + store_reg(s, rd, tmp); } } break; @@ -5882,21 +5968,21 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) gen_movl_reg_T1(s, rd); } else if ((insn & 0x003f0f60) == 0x003f0f20) { /* rev */ - gen_movl_T0_reg(s, rm); + tmp = load_reg(s, rm); if (insn & (1 << 22)) { if (insn & (1 << 7)) { - gen_revsh(cpu_T[0]); + gen_revsh(tmp); } else { ARCH(6T2); - gen_helper_rbit(cpu_T[0], cpu_T[0]); + gen_helper_rbit(tmp, tmp); } } else { if (insn & (1 << 7)) - gen_rev16(cpu_T[0]); + gen_rev16(tmp); else - gen_op_rev_T0(); + tcg_gen_bswap_i32(tmp, tmp); } - gen_movl_reg_T0(s, rd); + store_reg(s, rd, tmp); } else { goto illegal_op; } @@ -6020,71 +6106,47 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) /* load/store byte/word */ rn = (insn >> 16) & 0xf; rd = (insn >> 12) & 0xf; - gen_movl_T1_reg(s, rn); + tmp2 = load_reg(s, rn); i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000); if (insn & (1 << 24)) - gen_add_data_offset(s, insn); + gen_add_data_offset(s, insn, tmp2); if (insn & (1 << 20)) { /* load */ s->is_mem = 1; -#if defined(CONFIG_USER_ONLY) - if (insn & (1 << 22)) - gen_op_ldub_raw(); - else - gen_op_ldl_raw(); -#else if (insn & (1 << 22)) { - if (i) - gen_op_ldub_user(); - else - gen_op_ldub_kernel(); + tmp = gen_ld8u(tmp2, i); } else { - if (i) - gen_op_ldl_user(); - else - gen_op_ldl_kernel(); + tmp = gen_ld32(tmp2, i); } -#endif } else { /* store */ - gen_movl_T0_reg(s, rd); -#if defined(CONFIG_USER_ONLY) + tmp = load_reg(s, rd); if (insn & (1 << 22)) - gen_op_stb_raw(); + gen_st8(tmp, tmp2, i); else - gen_op_stl_raw(); -#else - if (insn & (1 << 22)) { - if (i) - gen_op_stb_user(); - else - gen_op_stb_kernel(); - } else { - if (i) - gen_op_stl_user(); - else - gen_op_stl_kernel(); - } -#endif + gen_st32(tmp, tmp2, i); } if (!(insn & (1 << 24))) { - gen_add_data_offset(s, insn); - gen_movl_reg_T1(s, rn); - } else if (insn & (1 << 21)) - gen_movl_reg_T1(s, rn); { + gen_add_data_offset(s, insn, tmp2); + store_reg(s, rn, tmp2); + } else if (insn & (1 << 21)) { + store_reg(s, rn, tmp2); + } else { + dead_tmp(tmp2); } if (insn & (1 << 20)) { /* Complete the load. */ if (rd == 15) - gen_bx_T0(s); + gen_bx(s, tmp); else - gen_movl_reg_T0(s, rd); + store_reg(s, rd, tmp); } break; case 0x08: case 0x09: { int j, n, user, loaded_base; + TCGv loaded_var; /* load/store multiple words */ /* XXX: store correct base if write back */ user = 0; @@ -6096,7 +6158,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) user = 1; } rn = (insn >> 16) & 0xf; - gen_movl_T1_reg(s, rn); + addr = load_reg(s, rn); /* compute total size */ loaded_base = 0; @@ -6109,18 +6171,18 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) if (insn & (1 << 23)) { if (insn & (1 << 24)) { /* pre increment */ - gen_op_addl_T1_im(4); + tcg_gen_addi_i32(addr, addr, 4); } else { /* post increment */ } } else { if (insn & (1 << 24)) { /* pre decrement */ - gen_op_addl_T1_im(-(n * 4)); + tcg_gen_addi_i32(addr, addr, -(n * 4)); } else { /* post decrement */ if (n != 1) - gen_op_addl_T1_im(-((n - 1) * 4)); + tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); } } j = 0; @@ -6128,34 +6190,37 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) if (insn & (1 << i)) { if (insn & (1 << 20)) { /* load */ - gen_ldst(ldl, s); + tmp = gen_ld32(addr, IS_USER(s)); if (i == 15) { - gen_bx_T0(s); + gen_bx(s, tmp); } else if (user) { - gen_op_movl_user_T0(i); + gen_helper_set_user_reg(tcg_const_i32(i), tmp); + dead_tmp(tmp); } else if (i == rn) { - gen_op_movl_T2_T0(); + loaded_var = tmp; loaded_base = 1; } else { - gen_movl_reg_T0(s, i); + store_reg(s, i, tmp); } } else { /* store */ if (i == 15) { /* special case: r15 = PC + 8 */ val = (long)s->pc + 4; - gen_op_movl_T0_im(val); + tmp = new_tmp(); + tcg_gen_movi_i32(tmp, val); } else if (user) { - gen_op_movl_T0_user(i); + tmp = new_tmp(); + gen_helper_get_user_reg(tmp, tcg_const_i32(i)); } else { - gen_movl_T0_reg(s, i); + tmp = load_reg(s, i); } - gen_ldst(stl, s); + gen_st32(tmp, addr, IS_USER(s)); } j++; /* no need to add after the last transfer */ if (j != n) - gen_op_addl_T1_im(4); + tcg_gen_addi_i32(addr, addr, 4); } } if (insn & (1 << 21)) { @@ -6165,23 +6230,24 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) /* pre increment */ } else { /* post increment */ - gen_op_addl_T1_im(4); + tcg_gen_addi_i32(addr, addr, 4); } } else { if (insn & (1 << 24)) { /* pre decrement */ if (n != 1) - gen_op_addl_T1_im(-((n - 1) * 4)); + tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); } else { /* post decrement */ - gen_op_addl_T1_im(-(n * 4)); + tcg_gen_addi_i32(addr, addr, -(n * 4)); } } - gen_movl_reg_T1(s, rn); + store_reg(s, rn, addr); + } else { + dead_tmp(addr); } if (loaded_base) { - gen_op_movl_T0_T2(); - gen_movl_reg_T0(s, rn); + store_reg(s, rn, loaded_var); } if ((insn & (1 << 22)) && !user) { /* Restore CPSR from SPSR. */ @@ -6319,11 +6385,12 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out) is not legal. */ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) { - uint32_t insn, imm, shift, offset, addr; + uint32_t insn, imm, shift, offset; uint32_t rd, rn, rm, rs; TCGv tmp; TCGv tmp2; TCGv tmp3; + TCGv addr; int op; int shiftop; int conds; @@ -6341,9 +6408,8 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) tcg_gen_addi_i32(tmp, tmp, offset); tcg_gen_andi_i32(tmp, tmp, 0xfffffffc); - addr = (uint32_t)s->pc; tmp2 = new_tmp(); - tcg_gen_movi_i32(tmp2, addr | 1); + tcg_gen_movi_i32(tmp2, s->pc | 1); store_reg(s, 14, tmp2); gen_bx(s, tmp); return 0; @@ -6354,9 +6420,8 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) tmp = load_reg(s, 14); tcg_gen_addi_i32(tmp, tmp, 14); - addr = (uint32_t)s->pc; tmp2 = new_tmp(); - tcg_gen_movi_i32(tmp2, addr | 1); + tcg_gen_movi_i32(tmp2, s->pc | 1); store_reg(s, 14, tmp2); gen_bx(s, tmp); return 0; @@ -6366,8 +6431,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) 16-bit instructions in case the second half causes an prefetch abort. */ offset = ((int32_t)insn << 21) >> 9; - addr = s->pc + 2 + offset; - gen_op_movl_T0_im(addr); + gen_op_movl_T0_im(s->pc + 2 + offset); gen_movl_reg_T0(s, 14); return 0; } @@ -6396,38 +6460,41 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) if (insn & 0x01200000) { /* Load/store doubleword. */ if (rn == 15) { - gen_op_movl_T1_im(s->pc & ~3); + addr = new_tmp(); + tcg_gen_movi_i32(addr, s->pc & ~3); } else { - gen_movl_T1_reg(s, rn); + addr = load_reg(s, rn); } offset = (insn & 0xff) * 4; if ((insn & (1 << 23)) == 0) offset = -offset; if (insn & (1 << 24)) { - gen_op_addl_T1_im(offset); + tcg_gen_addi_i32(addr, addr, offset); offset = 0; } if (insn & (1 << 20)) { /* ldrd */ - gen_ldst(ldl, s); - gen_movl_reg_T0(s, rs); - gen_op_addl_T1_im(4); - gen_ldst(ldl, s); - gen_movl_reg_T0(s, rd); + tmp = gen_ld32(addr, IS_USER(s)); + store_reg(s, rs, tmp); + tcg_gen_addi_i32(addr, addr, 4); + tmp = gen_ld32(addr, IS_USER(s)); + store_reg(s, rd, tmp); } else { /* strd */ - gen_movl_T0_reg(s, rs); - gen_ldst(stl, s); - gen_op_addl_T1_im(4); - gen_movl_T0_reg(s, rd); - gen_ldst(stl, s); + tmp = load_reg(s, rs); + gen_st32(tmp, addr, IS_USER(s)); + tcg_gen_addi_i32(addr, addr, 4); + tmp = load_reg(s, rd); + gen_st32(tmp, addr, IS_USER(s)); } if (insn & (1 << 21)) { /* Base writeback. */ if (rn == 15) goto illegal_op; - gen_op_addl_T1_im(offset - 4); - gen_movl_reg_T1(s, rn); + tcg_gen_addi_i32(addr, addr, offset - 4); + store_reg(s, rn, addr); + } else { + dead_tmp(addr); } } else if ((insn & (1 << 23)) == 0) { /* Load/store exclusive word. */ @@ -6442,24 +6509,26 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) } else if ((insn & (1 << 6)) == 0) { /* Table Branch. */ if (rn == 15) { - gen_op_movl_T1_im(s->pc); + addr = new_tmp(); + tcg_gen_movi_i32(addr, s->pc); } else { - gen_movl_T1_reg(s, rn); + addr = load_reg(s, rn); } tmp = load_reg(s, rm); - tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp); + tcg_gen_add_i32(addr, addr, tmp); if (insn & (1 << 4)) { /* tbh */ - tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp); + tcg_gen_add_i32(addr, addr, tmp); dead_tmp(tmp); - gen_ldst(lduw, s); + tmp = gen_ld16u(addr, IS_USER(s)); } else { /* tbb */ dead_tmp(tmp); - gen_ldst(ldub, s); + tmp = gen_ld8u(addr, IS_USER(s)); } - tcg_gen_shli_i32(cpu_T[0], cpu_T[0], 1); - tcg_gen_addi_i32(cpu_T[0], cpu_T[0], s->pc); - gen_movl_reg_T0(s, 15); + dead_tmp(addr); + tcg_gen_shli_i32(tmp, tmp, 1); + tcg_gen_addi_i32(tmp, tmp, s->pc); + store_reg(s, 15, tmp); } else { /* Load/store exclusive byte/halfword/doubleword. */ op = (insn >> 4) & 0x3; @@ -6503,68 +6572,74 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) /* Load/store multiple, RFE, SRS. */ if (((insn >> 23) & 1) == ((insn >> 24) & 1)) { /* Not available in user mode. */ - if (!IS_USER(s)) + if (IS_USER(s)) goto illegal_op; if (insn & (1 << 20)) { /* rfe */ - gen_movl_T1_reg(s, rn); - if (insn & (1 << 24)) { - gen_op_addl_T1_im(4); - } else { - gen_op_addl_T1_im(-4); - } - /* Load CPSR into T2 and PC into T0. */ - gen_ldst(ldl, s); - gen_op_movl_T2_T0(); - gen_op_addl_T1_im(-4); - gen_ldst(ldl, s); + addr = load_reg(s, rn); + if ((insn & (1 << 24)) == 0) + tcg_gen_addi_i32(addr, addr, -8); + /* Load PC into tmp and CPSR into tmp2. */ + tmp = gen_ld32(addr, 0); + tcg_gen_addi_i32(addr, addr, 4); + tmp2 = gen_ld32(addr, 0); if (insn & (1 << 21)) { /* Base writeback. */ - if (insn & (1 << 24)) - gen_op_addl_T1_im(8); - gen_movl_reg_T1(s, rn); + if (insn & (1 << 24)) { + tcg_gen_addi_i32(addr, addr, 4); + } else { + tcg_gen_addi_i32(addr, addr, -4); + } + store_reg(s, rn, addr); + } else { + dead_tmp(addr); } - gen_rfe(s); + gen_rfe(s, tmp, tmp2); } else { /* srs */ op = (insn & 0x1f); if (op == (env->uncached_cpsr & CPSR_M)) { - gen_movl_T1_reg(s, 13); + addr = load_reg(s, 13); } else { - gen_op_movl_T1_r13_banked(op); + addr = new_tmp(); + gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op)); } if ((insn & (1 << 24)) == 0) { - gen_op_addl_T1_im(-8); + tcg_gen_addi_i32(addr, addr, -8); } - gen_movl_T0_reg(s, 14); - gen_ldst(stl, s); - gen_helper_cpsr_read(cpu_T[0]); - gen_op_addl_T1_im(4); - gen_ldst(stl, s); + tmp = load_reg(s, 14); + gen_st32(tmp, addr, 0); + tcg_gen_addi_i32(addr, addr, 4); + tmp = new_tmp(); + gen_helper_cpsr_read(tmp); + gen_st32(tmp, addr, 0); if (insn & (1 << 21)) { if ((insn & (1 << 24)) == 0) { - gen_op_addl_T1_im(-4); + tcg_gen_addi_i32(addr, addr, -4); } else { - gen_op_addl_T1_im(4); + tcg_gen_addi_i32(addr, addr, 4); } if (op == (env->uncached_cpsr & CPSR_M)) { - gen_movl_reg_T1(s, 13); + store_reg(s, 13, addr); } else { - gen_op_movl_r13_T1_banked(op); + gen_helper_set_r13_banked(cpu_env, + tcg_const_i32(op), addr); } + } else { + dead_tmp(addr); } } } else { int i; /* Load/store multiple. */ - gen_movl_T1_reg(s, rn); + addr = load_reg(s, rn); offset = 0; for (i = 0; i < 16; i++) { if (insn & (1 << i)) offset += 4; } if (insn & (1 << 24)) { - gen_op_addl_T1_im(-offset); + tcg_gen_addi_i32(addr, addr, -offset); } for (i = 0; i < 16; i++) { @@ -6572,28 +6647,30 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) continue; if (insn & (1 << 20)) { /* Load. */ - gen_ldst(ldl, s); + tmp = gen_ld32(addr, IS_USER(s)); if (i == 15) { - gen_bx_T0(s); + gen_bx(s, tmp); } else { - gen_movl_reg_T0(s, i); + store_reg(s, i, tmp); } } else { /* Store. */ - gen_movl_T0_reg(s, i); - gen_ldst(stl, s); + tmp = load_reg(s, i); + gen_st32(tmp, addr, IS_USER(s)); } - gen_op_addl_T1_im(4); + tcg_gen_addi_i32(addr, addr, 4); } if (insn & (1 << 21)) { /* Base register writeback. */ if (insn & (1 << 24)) { - gen_op_addl_T1_im(-offset); + tcg_gen_addi_i32(addr, addr, -offset); } /* Fault if writeback register is in register list. */ if (insn & (1 << rn)) goto illegal_op; - gen_movl_reg_T1(s, rn); + store_reg(s, rn, addr); + } else { + dead_tmp(addr); } } } @@ -6892,21 +6969,20 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) offset ^= ((~insn) & (1 << 13)) << 10; offset ^= ((~insn) & (1 << 11)) << 11; - addr = s->pc; if (insn & (1 << 14)) { /* Branch and link. */ - gen_op_movl_T1_im(addr | 1); + gen_op_movl_T1_im(s->pc | 1); gen_movl_reg_T1(s, 14); } - addr += offset; + offset += s->pc; if (insn & (1 << 12)) { /* b/bl */ - gen_jmp(s, addr); + gen_jmp(s, offset); } else { /* blx */ - addr &= ~(uint32_t)2; - gen_bx_im(s, addr); + offset &= ~(uint32_t)2; + gen_bx_im(s, offset); } } else if (((insn >> 23) & 7) == 7) { /* Misc control */ @@ -7025,8 +7101,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) offset |= (insn & (1 << 11)) << 8; /* jump to the offset */ - addr = s->pc + offset; - gen_jmp(s, addr); + gen_jmp(s, s->pc + offset); } } else { /* Data processing immediate. */ @@ -7114,12 +7189,12 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) } else { /* Add/sub 12-bit immediate. */ if (rn == 15) { - addr = s->pc & ~(uint32_t)3; + offset = s->pc & ~(uint32_t)3; if (insn & (1 << 23)) - addr -= imm; + offset -= imm; else - addr += imm; - gen_op_movl_T0_im(addr); + offset += imm; + gen_op_movl_T0_im(offset); } else { gen_movl_T0_reg(s, rn); gen_op_movl_T1_im(imm); @@ -7179,12 +7254,15 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) { int postinc = 0; int writeback = 0; + int user; if ((insn & 0x01100000) == 0x01000000) { if (disas_neon_ls_insn(env, s, insn)) goto illegal_op; break; } + user = IS_USER(s); if (rn == 15) { + addr = new_tmp(); /* PC relative. */ /* s->pc has already been incremented by 4. */ imm = s->pc & 0xfffffffc; @@ -7192,13 +7270,13 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) imm += insn & 0xfff; else imm -= insn & 0xfff; - gen_op_movl_T1_im(imm); + tcg_gen_movi_i32(addr, imm); } else { - gen_movl_T1_reg(s, rn); + addr = load_reg(s, rn); if (insn & (1 << 23)) { /* Positive offset. */ imm = insn & 0xfff; - gen_op_addl_T1_im(imm); + tcg_gen_addi_i32(addr, addr, imm); } else { op = (insn >> 8) & 7; imm = insn & 0xff; @@ -7210,14 +7288,15 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) tmp = load_reg(s, rm); if (shift) tcg_gen_shli_i32(tmp, tmp, shift); - tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp); + tcg_gen_add_i32(addr, addr, tmp); dead_tmp(tmp); break; case 4: /* Negative offset. */ - gen_op_addl_T1_im(-imm); + tcg_gen_addi_i32(addr, addr, -imm); break; case 6: /* User privilege. */ - gen_op_addl_T1_im(imm); + tcg_gen_addi_i32(addr, addr, imm); + user = 1; break; case 1: /* Post-decrement. */ imm = -imm; @@ -7230,7 +7309,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) imm = -imm; /* Fall through. */ case 7: /* Pre-increment. */ - gen_op_addl_T1_im(imm); + tcg_gen_addi_i32(addr, addr, imm); writeback = 1; break; default: @@ -7247,35 +7326,38 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) /* Memory hint. Implemented as NOP. */ } else { switch (op) { - case 0: gen_ldst(ldub, s); break; - case 4: gen_ldst(ldsb, s); break; - case 1: gen_ldst(lduw, s); break; - case 5: gen_ldst(ldsw, s); break; - case 2: gen_ldst(ldl, s); break; + case 0: tmp = gen_ld8u(addr, user); break; + case 4: tmp = gen_ld8s(addr, user); break; + case 1: tmp = gen_ld16u(addr, user); break; + case 5: tmp = gen_ld16s(addr, user); break; + case 2: tmp = gen_ld32(addr, user); break; default: goto illegal_op; } if (rs == 15) { - gen_bx_T0(s); + gen_bx(s, tmp); } else { - gen_movl_reg_T0(s, rs); + store_reg(s, rs, tmp); } } } else { /* Store. */ if (rs == 15) goto illegal_op; - gen_movl_T0_reg(s, rs); + tmp = load_reg(s, rs); switch (op) { - case 0: gen_ldst(stb, s); break; - case 1: gen_ldst(stw, s); break; - case 2: gen_ldst(stl, s); break; + case 0: gen_st8(tmp, addr, user); break; + case 1: gen_st16(tmp, addr, user); break; + case 2: gen_st32(tmp, addr, user); break; default: goto illegal_op; } } if (postinc) - gen_op_addl_T1_im(imm); - if (writeback) - gen_movl_reg_T1(s, rn); + tcg_gen_addi_i32(addr, addr, imm); + if (writeback) { + store_reg(s, rn, addr); + } else { + dead_tmp(addr); + } } break; default: @@ -7293,6 +7375,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) int i; TCGv tmp; TCGv tmp2; + TCGv addr; if (s->condexec_mask) { cond = s->condexec_cond; @@ -7383,9 +7466,11 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) /* load pc-relative. Bit 1 of PC is ignored. */ val = s->pc + 2 + ((insn & 0xff) * 4); val &= ~(uint32_t)2; - gen_op_movl_T1_im(val); - gen_ldst(ldl, s); - gen_movl_reg_T0(s, rd); + addr = new_tmp(); + tcg_gen_movi_i32(addr, val); + tmp = gen_ld32(addr, IS_USER(s)); + dead_tmp(addr); + store_reg(s, rd, tmp); break; } if (insn & (1 << 10)) { @@ -7410,12 +7495,13 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) gen_movl_reg_T0(s, rd); break; case 3:/* branch [and link] exchange thumb register */ + tmp = load_reg(s, rm); if (insn & (1 << 7)) { val = (uint32_t)s->pc | 1; - gen_op_movl_T1_im(val); - gen_movl_reg_T1(s, 14); + tmp2 = new_tmp(); + tcg_gen_movi_i32(tmp2, val); + store_reg(s, 14, tmp2); } - tmp = load_reg(s, rm); gen_bx(s, tmp); break; } @@ -7553,117 +7639,122 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) rn = (insn >> 3) & 7; rm = (insn >> 6) & 7; op = (insn >> 9) & 7; - gen_movl_T1_reg(s, rn); + addr = load_reg(s, rn); tmp = load_reg(s, rm); - tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp); + tcg_gen_add_i32(addr, addr, tmp); dead_tmp(tmp); if (op < 3) /* store */ - gen_movl_T0_reg(s, rd); + tmp = load_reg(s, rd); switch (op) { case 0: /* str */ - gen_ldst(stl, s); + gen_st32(tmp, addr, IS_USER(s)); break; case 1: /* strh */ - gen_ldst(stw, s); + gen_st16(tmp, addr, IS_USER(s)); break; case 2: /* strb */ - gen_ldst(stb, s); + gen_st8(tmp, addr, IS_USER(s)); break; case 3: /* ldrsb */ - gen_ldst(ldsb, s); + tmp = gen_ld8s(addr, IS_USER(s)); break; case 4: /* ldr */ - gen_ldst(ldl, s); + tmp = gen_ld32(addr, IS_USER(s)); break; case 5: /* ldrh */ - gen_ldst(lduw, s); + tmp = gen_ld16u(addr, IS_USER(s)); break; case 6: /* ldrb */ - gen_ldst(ldub, s); + tmp = gen_ld8u(addr, IS_USER(s)); break; case 7: /* ldrsh */ - gen_ldst(ldsw, s); + tmp = gen_ld16s(addr, IS_USER(s)); break; } if (op >= 3) /* load */ - gen_movl_reg_T0(s, rd); + store_reg(s, rd, tmp); + dead_tmp(addr); break; case 6: /* load/store word immediate offset */ rd = insn & 7; rn = (insn >> 3) & 7; - gen_movl_T1_reg(s, rn); + addr = load_reg(s, rn); val = (insn >> 4) & 0x7c; - tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val); + tcg_gen_addi_i32(addr, addr, val); if (insn & (1 << 11)) { /* load */ - gen_ldst(ldl, s); - gen_movl_reg_T0(s, rd); + tmp = gen_ld32(addr, IS_USER(s)); + store_reg(s, rd, tmp); } else { /* store */ - gen_movl_T0_reg(s, rd); - gen_ldst(stl, s); + tmp = load_reg(s, rd); + gen_st32(tmp, addr, IS_USER(s)); } + dead_tmp(addr); break; case 7: /* load/store byte immediate offset */ rd = insn & 7; rn = (insn >> 3) & 7; - gen_movl_T1_reg(s, rn); + addr = load_reg(s, rn); val = (insn >> 6) & 0x1f; - tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val); + tcg_gen_addi_i32(addr, addr, val); if (insn & (1 << 11)) { /* load */ - gen_ldst(ldub, s); - gen_movl_reg_T0(s, rd); + tmp = gen_ld8u(addr, IS_USER(s)); + store_reg(s, rd, tmp); } else { /* store */ - gen_movl_T0_reg(s, rd); - gen_ldst(stb, s); + tmp = load_reg(s, rd); + gen_st8(tmp, addr, IS_USER(s)); } + dead_tmp(addr); break; case 8: /* load/store halfword immediate offset */ rd = insn & 7; rn = (insn >> 3) & 7; - gen_movl_T1_reg(s, rn); + addr = load_reg(s, rn); val = (insn >> 5) & 0x3e; - tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val); + tcg_gen_addi_i32(addr, addr, val); if (insn & (1 << 11)) { /* load */ - gen_ldst(lduw, s); - gen_movl_reg_T0(s, rd); + tmp = gen_ld16u(addr, IS_USER(s)); + store_reg(s, rd, tmp); } else { /* store */ - gen_movl_T0_reg(s, rd); - gen_ldst(stw, s); + tmp = load_reg(s, rd); + gen_st16(tmp, addr, IS_USER(s)); } + dead_tmp(addr); break; case 9: /* load/store from stack */ rd = (insn >> 8) & 7; - gen_movl_T1_reg(s, 13); + addr = load_reg(s, 13); val = (insn & 0xff) * 4; - tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val); + tcg_gen_addi_i32(addr, addr, val); if (insn & (1 << 11)) { /* load */ - gen_ldst(ldl, s); - gen_movl_reg_T0(s, rd); + tmp = gen_ld32(addr, IS_USER(s)); + store_reg(s, rd, tmp); } else { /* store */ - gen_movl_T0_reg(s, rd); - gen_ldst(stl, s); + tmp = load_reg(s, rd); + gen_st32(tmp, addr, IS_USER(s)); } + dead_tmp(addr); break; case 10: @@ -7700,18 +7791,18 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) ARCH(6); rd = insn & 7; rm = (insn >> 3) & 7; - gen_movl_T1_reg(s, rm); + tmp = load_reg(s, rm); switch ((insn >> 6) & 3) { - case 0: gen_sxth(cpu_T[1]); break; - case 1: gen_sxtb(cpu_T[1]); break; - case 2: gen_uxth(cpu_T[1]); break; - case 3: gen_uxtb(cpu_T[1]); break; + case 0: gen_sxth(tmp); break; + case 1: gen_sxtb(tmp); break; + case 2: gen_uxth(tmp); break; + case 3: gen_uxtb(tmp); break; } - gen_movl_reg_T1(s, rd); + store_reg(s, rd, tmp); break; case 4: case 5: case 0xc: case 0xd: /* push/pop */ - gen_movl_T1_reg(s, 13); + addr = load_reg(s, 13); if (insn & (1 << 8)) offset = 4; else @@ -7721,44 +7812,44 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) offset += 4; } if ((insn & (1 << 11)) == 0) { - gen_op_addl_T1_im(-offset); + tcg_gen_addi_i32(addr, addr, -offset); } for (i = 0; i < 8; i++) { if (insn & (1 << i)) { if (insn & (1 << 11)) { /* pop */ - gen_ldst(ldl, s); - gen_movl_reg_T0(s, i); + tmp = gen_ld32(addr, IS_USER(s)); + store_reg(s, i, tmp); } else { /* push */ - gen_movl_T0_reg(s, i); - gen_ldst(stl, s); + tmp = load_reg(s, i); + gen_st32(tmp, addr, IS_USER(s)); } /* advance to the next address. */ - gen_op_addl_T1_im(4); + tcg_gen_addi_i32(addr, addr, 4); } } if (insn & (1 << 8)) { if (insn & (1 << 11)) { /* pop pc */ - gen_ldst(ldl, s); + tmp = gen_ld32(addr, IS_USER(s)); /* don't set the pc until the rest of the instruction has completed */ } else { /* push lr */ - gen_movl_T0_reg(s, 14); - gen_ldst(stl, s); + tmp = load_reg(s, 14); + gen_st32(tmp, addr, IS_USER(s)); } - gen_op_addl_T1_im(4); + tcg_gen_addi_i32(addr, addr, 4); } if ((insn & (1 << 11)) == 0) { - gen_op_addl_T1_im(-offset); + tcg_gen_addi_i32(addr, addr, -offset); } /* write back the new stack pointer */ - gen_movl_reg_T1(s, 13); + store_reg(s, 13, addr); /* set the new PC value */ if ((insn & 0x0900) == 0x0900) - gen_bx_T0(s); + gen_bx(s, tmp); break; case 1: case 3: case 9: case 11: /* czb */ @@ -7801,14 +7892,14 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) ARCH(6); rn = (insn >> 3) & 0x7; rd = insn & 0x7; - gen_movl_T0_reg(s, rn); + tmp = load_reg(s, rn); switch ((insn >> 6) & 3) { - case 0: gen_op_rev_T0(); break; - case 1: gen_rev16(cpu_T[0]); break; - case 3: gen_revsh(cpu_T[0]); break; + case 0: tcg_gen_bswap_i32(tmp, tmp); break; + case 1: gen_rev16(tmp); break; + case 3: gen_revsh(tmp); break; default: goto illegal_op; } - gen_movl_reg_T0(s, rd); + store_reg(s, rd, tmp); break; case 6: /* cps */ @@ -7846,25 +7937,28 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) case 12: /* load/store multiple */ rn = (insn >> 8) & 0x7; - gen_movl_T1_reg(s, rn); + addr = load_reg(s, rn); for (i = 0; i < 8; i++) { if (insn & (1 << i)) { if (insn & (1 << 11)) { /* load */ - gen_ldst(ldl, s); - gen_movl_reg_T0(s, i); + tmp = gen_ld32(addr, IS_USER(s)); + store_reg(s, i, tmp); } else { /* store */ - gen_movl_T0_reg(s, i); - gen_ldst(stl, s); + tmp = load_reg(s, i); + gen_st32(tmp, addr, IS_USER(s)); } /* advance to the next address */ - gen_op_addl_T1_im(4); + tcg_gen_addi_i32(addr, addr, 4); } } /* Base register writeback. */ - if ((insn & (1 << rn)) == 0) - gen_movl_reg_T1(s, rn); + if ((insn & (1 << rn)) == 0) { + store_reg(s, rn, addr); + } else { + dead_tmp(addr); + } break; case 13: diff --git a/tcg/tcg-op.h b/tcg/tcg-op.h index 27f83b5b23..5f66d7f969 100644 --- a/tcg/tcg-op.h +++ b/tcg/tcg-op.h @@ -199,6 +199,18 @@ static inline void tcg_gen_helper_0_2(void *func, TCGv arg1, TCGv arg2) 0, NULL, 2, args); } +static inline void tcg_gen_helper_0_3(void *func, + TCGv arg1, TCGv arg2, TCGv arg3) +{ + TCGv args[3]; + args[0] = arg1; + args[1] = arg2; + args[2] = arg3; + tcg_gen_call(&tcg_ctx, + tcg_const_ptr((tcg_target_long)func), TCG_HELPER_CALL_FLAGS, + 0, NULL, 3, args); +} + static inline void tcg_gen_helper_0_4(void *func, TCGv arg1, TCGv arg2, TCGv arg3, TCGv arg4) { |