Commit b010980544b543d421b3f514bba3cafc59b3a3db
1 parent
d9ba4830
ARM TCG conversion 9/16.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@4146 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
8 changed files
with
487 additions
and
409 deletions
target-arm/exec.h
| ... | ... | @@ -72,8 +72,6 @@ void helper_set_cp(CPUState *, uint32_t, uint32_t); |
| 72 | 72 | uint32_t helper_get_cp(CPUState *, uint32_t); |
| 73 | 73 | void helper_set_cp15(CPUState *, uint32_t, uint32_t); |
| 74 | 74 | uint32_t helper_get_cp15(CPUState *, uint32_t); |
| 75 | -void helper_set_r13_banked(CPUState *env, int mode, uint32_t val); | |
| 76 | -uint32_t helper_get_r13_banked(CPUState *env, int mode); | |
| 77 | 75 | uint32_t helper_v7m_mrs(CPUState *env, int reg); |
| 78 | 76 | void helper_v7m_msr(CPUState *env, int reg, uint32_t val); |
| 79 | 77 | ... | ... |
target-arm/helper.c
| ... | ... | @@ -513,12 +513,12 @@ void switch_mode(CPUState *env, int mode) |
| 513 | 513 | cpu_abort(env, "Tried to switch out of user mode\n"); |
| 514 | 514 | } |
| 515 | 515 | |
| 516 | -void helper_set_r13_banked(CPUState *env, int mode, uint32_t val) | |
| 516 | +void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val) | |
| 517 | 517 | { |
| 518 | 518 | cpu_abort(env, "banked r13 write\n"); |
| 519 | 519 | } |
| 520 | 520 | |
| 521 | -uint32_t helper_get_r13_banked(CPUState *env, int mode) | |
| 521 | +uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode) | |
| 522 | 522 | { |
| 523 | 523 | cpu_abort(env, "banked r13 read\n"); |
| 524 | 524 | return 0; |
| ... | ... | @@ -1793,12 +1793,12 @@ bad_reg: |
| 1793 | 1793 | return 0; |
| 1794 | 1794 | } |
| 1795 | 1795 | |
| 1796 | -void helper_set_r13_banked(CPUState *env, int mode, uint32_t val) | |
| 1796 | +void HELPER(set_r13_banked)(CPUState *env, uint32_t mode, uint32_t val) | |
| 1797 | 1797 | { |
| 1798 | 1798 | env->banked_r13[bank_number(mode)] = val; |
| 1799 | 1799 | } |
| 1800 | 1800 | |
| 1801 | -uint32_t helper_get_r13_banked(CPUState *env, int mode) | |
| 1801 | +uint32_t HELPER(get_r13_banked)(CPUState *env, uint32_t mode) | |
| 1802 | 1802 | { |
| 1803 | 1803 | return env->banked_r13[bank_number(mode)]; |
| 1804 | 1804 | } | ... | ... |
target-arm/helpers.h
| ... | ... | @@ -19,6 +19,13 @@ static inline void gen_helper_##name(TCGv arg1, TCGv arg2) \ |
| 19 | 19 | { \ |
| 20 | 20 | tcg_gen_helper_0_2(helper_##name, arg1, arg2); \ |
| 21 | 21 | } |
| 22 | +#define DEF_HELPER_0_3(name, ret, args) \ | |
| 23 | +DEF_HELPER(name, ret, args) \ | |
| 24 | +static inline void gen_helper_##name( \ | |
| 25 | + TCGv arg1, TCGv arg2, TCGv arg3) \ | |
| 26 | +{ \ | |
| 27 | + tcg_gen_helper_0_3(helper_##name, arg1, arg2, arg3); \ | |
| 28 | +} | |
| 22 | 29 | #define DEF_HELPER_1_0(name, ret, args) \ |
| 23 | 30 | DEF_HELPER(name, ret, args) \ |
| 24 | 31 | static inline void gen_helper_##name(TCGv ret) \ |
| ... | ... | @@ -48,6 +55,7 @@ static inline void gen_helper_##name(TCGv ret, \ |
| 48 | 55 | #define DEF_HELPER_0_0 DEF_HELPER |
| 49 | 56 | #define DEF_HELPER_0_1 DEF_HELPER |
| 50 | 57 | #define DEF_HELPER_0_2 DEF_HELPER |
| 58 | +#define DEF_HELPER_0_3 DEF_HELPER | |
| 51 | 59 | #define DEF_HELPER_1_0 DEF_HELPER |
| 52 | 60 | #define DEF_HELPER_1_1 DEF_HELPER |
| 53 | 61 | #define DEF_HELPER_1_2 DEF_HELPER |
| ... | ... | @@ -108,6 +116,12 @@ DEF_HELPER_0_0(wfi, void, (void)) |
| 108 | 116 | DEF_HELPER_0_2(cpsr_write, void, (uint32_t, uint32_t)) |
| 109 | 117 | DEF_HELPER_1_0(cpsr_read, uint32_t, (void)) |
| 110 | 118 | |
| 119 | +DEF_HELPER_1_2(get_r13_banked, uint32_t, (CPUState *, uint32_t)) | |
| 120 | +DEF_HELPER_0_3(set_r13_banked, void, (CPUState *, uint32_t, uint32_t)) | |
| 121 | + | |
| 122 | +DEF_HELPER_1_1(get_user_reg, uint32_t, (uint32_t)) | |
| 123 | +DEF_HELPER_0_2(set_user_reg, void, (uint32_t, uint32_t)) | |
| 124 | + | |
| 111 | 125 | #undef DEF_HELPER |
| 112 | 126 | #undef DEF_HELPER_0_0 |
| 113 | 127 | #undef DEF_HELPER_0_1 | ... | ... |
target-arm/op.c
| ... | ... | @@ -589,48 +589,6 @@ void OPPROTO op_movl_T0_cp15(void) |
| 589 | 589 | FORCE_RET(); |
| 590 | 590 | } |
| 591 | 591 | |
| 592 | -/* Access to user mode registers from privileged modes. */ | |
| 593 | -void OPPROTO op_movl_T0_user(void) | |
| 594 | -{ | |
| 595 | - int regno = PARAM1; | |
| 596 | - if (regno == 13) { | |
| 597 | - T0 = env->banked_r13[0]; | |
| 598 | - } else if (regno == 14) { | |
| 599 | - T0 = env->banked_r14[0]; | |
| 600 | - } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { | |
| 601 | - T0 = env->usr_regs[regno - 8]; | |
| 602 | - } else { | |
| 603 | - T0 = env->regs[regno]; | |
| 604 | - } | |
| 605 | - FORCE_RET(); | |
| 606 | -} | |
| 607 | - | |
| 608 | - | |
| 609 | -void OPPROTO op_movl_user_T0(void) | |
| 610 | -{ | |
| 611 | - int regno = PARAM1; | |
| 612 | - if (regno == 13) { | |
| 613 | - env->banked_r13[0] = T0; | |
| 614 | - } else if (regno == 14) { | |
| 615 | - env->banked_r14[0] = T0; | |
| 616 | - } else if ((env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { | |
| 617 | - env->usr_regs[regno - 8] = T0; | |
| 618 | - } else { | |
| 619 | - env->regs[regno] = T0; | |
| 620 | - } | |
| 621 | - FORCE_RET(); | |
| 622 | -} | |
| 623 | - | |
| 624 | -void OPPROTO op_movl_T1_r13_banked(void) | |
| 625 | -{ | |
| 626 | - T1 = helper_get_r13_banked(env, PARAM1); | |
| 627 | -} | |
| 628 | - | |
| 629 | -void OPPROTO op_movl_r13_T1_banked(void) | |
| 630 | -{ | |
| 631 | - helper_set_r13_banked(env, PARAM1, T1); | |
| 632 | -} | |
| 633 | - | |
| 634 | 592 | void OPPROTO op_v7m_mrs_T0(void) |
| 635 | 593 | { |
| 636 | 594 | T0 = helper_v7m_mrs(env, PARAM1); | ... | ... |
target-arm/op_helper.c
| ... | ... | @@ -459,3 +459,36 @@ void HELPER(cpsr_write)(uint32_t val, uint32_t mask) |
| 459 | 459 | { |
| 460 | 460 | cpsr_write(env, val, mask); |
| 461 | 461 | } |
| 462 | + | |
| 463 | +/* Access to user mode registers from privileged modes. */ | |
| 464 | +uint32_t HELPER(get_user_reg)(uint32_t regno) | |
| 465 | +{ | |
| 466 | + uint32_t val; | |
| 467 | + | |
| 468 | + if (regno == 13) { | |
| 469 | + val = env->banked_r13[0]; | |
| 470 | + } else if (regno == 14) { | |
| 471 | + val = env->banked_r14[0]; | |
| 472 | + } else if (regno >= 8 | |
| 473 | + && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { | |
| 474 | + val = env->usr_regs[regno - 8]; | |
| 475 | + } else { | |
| 476 | + val = env->regs[regno]; | |
| 477 | + } | |
| 478 | + return val; | |
| 479 | +} | |
| 480 | + | |
| 481 | +void HELPER(set_user_reg)(uint32_t regno, uint32_t val) | |
| 482 | +{ | |
| 483 | + if (regno == 13) { | |
| 484 | + env->banked_r13[0] = val; | |
| 485 | + } else if (regno == 14) { | |
| 486 | + env->banked_r14[0] = val; | |
| 487 | + } else if (regno >= 8 | |
| 488 | + && (env->uncached_cpsr & 0x1f) == ARM_CPU_MODE_FIQ) { | |
| 489 | + env->usr_regs[regno - 8] = val; | |
| 490 | + } else { | |
| 491 | + env->regs[regno] = val; | |
| 492 | + } | |
| 493 | +} | |
| 494 | + | ... | ... |
target-arm/op_mem.h
| 1 | 1 | /* ARM memory operations. */ |
| 2 | 2 | |
| 3 | -void helper_ld(uint32_t); | |
| 4 | -/* Load from address T1 into T0. */ | |
| 5 | -#define MEM_LD_OP(name) \ | |
| 6 | -void OPPROTO glue(op_ld##name,MEMSUFFIX)(void) \ | |
| 7 | -{ \ | |
| 8 | - T0 = glue(ld##name,MEMSUFFIX)(T1); \ | |
| 9 | - FORCE_RET(); \ | |
| 10 | -} | |
| 11 | - | |
| 12 | -MEM_LD_OP(ub) | |
| 13 | -MEM_LD_OP(sb) | |
| 14 | -MEM_LD_OP(uw) | |
| 15 | -MEM_LD_OP(sw) | |
| 16 | -MEM_LD_OP(l) | |
| 17 | - | |
| 18 | -#undef MEM_LD_OP | |
| 19 | - | |
| 20 | -/* Store T0 to address T1. */ | |
| 21 | -#define MEM_ST_OP(name) \ | |
| 22 | -void OPPROTO glue(op_st##name,MEMSUFFIX)(void) \ | |
| 23 | -{ \ | |
| 24 | - glue(st##name,MEMSUFFIX)(T1, T0); \ | |
| 25 | - FORCE_RET(); \ | |
| 26 | -} | |
| 27 | - | |
| 28 | -MEM_ST_OP(b) | |
| 29 | -MEM_ST_OP(w) | |
| 30 | -MEM_ST_OP(l) | |
| 31 | - | |
| 32 | -#undef MEM_ST_OP | |
| 33 | - | |
| 34 | 3 | /* Swap T0 with memory at address T1. */ |
| 35 | 4 | /* ??? Is this exception safe? */ |
| 36 | 5 | #define MEM_SWP_OP(name, lname) \ | ... | ... |
target-arm/translate.c
| ... | ... | @@ -222,7 +222,6 @@ static void store_reg(DisasContext *s, int reg, TCGv var) |
| 222 | 222 | |
| 223 | 223 | #define gen_sxtb16(var) gen_helper_sxtb16(var, var) |
| 224 | 224 | #define gen_uxtb16(var) gen_helper_uxtb16(var, var) |
| 225 | -#define gen_op_rev_T0() tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]) | |
| 226 | 225 | |
| 227 | 226 | #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1]) |
| 228 | 227 | |
| ... | ... | @@ -804,6 +803,51 @@ static inline void gen_bx_T0(DisasContext *s) |
| 804 | 803 | gen_op_##name##_kernel(); \ |
| 805 | 804 | } while (0) |
| 806 | 805 | #endif |
| 806 | +static inline TCGv gen_ld8s(TCGv addr, int index) | |
| 807 | +{ | |
| 808 | + TCGv tmp = new_tmp(); | |
| 809 | + tcg_gen_qemu_ld8s(tmp, addr, index); | |
| 810 | + return tmp; | |
| 811 | +} | |
| 812 | +static inline TCGv gen_ld8u(TCGv addr, int index) | |
| 813 | +{ | |
| 814 | + TCGv tmp = new_tmp(); | |
| 815 | + tcg_gen_qemu_ld8u(tmp, addr, index); | |
| 816 | + return tmp; | |
| 817 | +} | |
| 818 | +static inline TCGv gen_ld16s(TCGv addr, int index) | |
| 819 | +{ | |
| 820 | + TCGv tmp = new_tmp(); | |
| 821 | + tcg_gen_qemu_ld16s(tmp, addr, index); | |
| 822 | + return tmp; | |
| 823 | +} | |
| 824 | +static inline TCGv gen_ld16u(TCGv addr, int index) | |
| 825 | +{ | |
| 826 | + TCGv tmp = new_tmp(); | |
| 827 | + tcg_gen_qemu_ld16u(tmp, addr, index); | |
| 828 | + return tmp; | |
| 829 | +} | |
| 830 | +static inline TCGv gen_ld32(TCGv addr, int index) | |
| 831 | +{ | |
| 832 | + TCGv tmp = new_tmp(); | |
| 833 | + tcg_gen_qemu_ld32u(tmp, addr, index); | |
| 834 | + return tmp; | |
| 835 | +} | |
| 836 | +static inline void gen_st8(TCGv val, TCGv addr, int index) | |
| 837 | +{ | |
| 838 | + tcg_gen_qemu_st8(val, addr, index); | |
| 839 | + dead_tmp(val); | |
| 840 | +} | |
| 841 | +static inline void gen_st16(TCGv val, TCGv addr, int index) | |
| 842 | +{ | |
| 843 | + tcg_gen_qemu_st16(val, addr, index); | |
| 844 | + dead_tmp(val); | |
| 845 | +} | |
| 846 | +static inline void gen_st32(TCGv val, TCGv addr, int index) | |
| 847 | +{ | |
| 848 | + tcg_gen_qemu_st32(val, addr, index); | |
| 849 | + dead_tmp(val); | |
| 850 | +} | |
| 807 | 851 | |
| 808 | 852 | static inline void gen_movl_T0_reg(DisasContext *s, int reg) |
| 809 | 853 | { |
| ... | ... | @@ -859,7 +903,8 @@ static inline void gen_lookup_tb(DisasContext *s) |
| 859 | 903 | s->is_jmp = DISAS_UPDATE; |
| 860 | 904 | } |
| 861 | 905 | |
| 862 | -static inline void gen_add_data_offset(DisasContext *s, unsigned int insn) | |
| 906 | +static inline void gen_add_data_offset(DisasContext *s, unsigned int insn, | |
| 907 | + TCGv var) | |
| 863 | 908 | { |
| 864 | 909 | int val, rm, shift, shiftop; |
| 865 | 910 | TCGv offset; |
| ... | ... | @@ -870,7 +915,7 @@ static inline void gen_add_data_offset(DisasContext *s, unsigned int insn) |
| 870 | 915 | if (!(insn & (1 << 23))) |
| 871 | 916 | val = -val; |
| 872 | 917 | if (val != 0) |
| 873 | - gen_op_addl_T1_im(val); | |
| 918 | + tcg_gen_addi_i32(var, var, val); | |
| 874 | 919 | } else { |
| 875 | 920 | /* shift/register */ |
| 876 | 921 | rm = (insn) & 0xf; |
| ... | ... | @@ -879,15 +924,15 @@ static inline void gen_add_data_offset(DisasContext *s, unsigned int insn) |
| 879 | 924 | offset = load_reg(s, rm); |
| 880 | 925 | gen_arm_shift_im(offset, shiftop, shift, 0); |
| 881 | 926 | if (!(insn & (1 << 23))) |
| 882 | - tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset); | |
| 927 | + tcg_gen_sub_i32(var, var, offset); | |
| 883 | 928 | else |
| 884 | - tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset); | |
| 929 | + tcg_gen_add_i32(var, var, offset); | |
| 885 | 930 | dead_tmp(offset); |
| 886 | 931 | } |
| 887 | 932 | } |
| 888 | 933 | |
| 889 | 934 | static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, |
| 890 | - int extra) | |
| 935 | + int extra, TCGv var) | |
| 891 | 936 | { |
| 892 | 937 | int val, rm; |
| 893 | 938 | TCGv offset; |
| ... | ... | @@ -899,17 +944,17 @@ static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn, |
| 899 | 944 | val = -val; |
| 900 | 945 | val += extra; |
| 901 | 946 | if (val != 0) |
| 902 | - gen_op_addl_T1_im(val); | |
| 947 | + tcg_gen_addi_i32(var, var, val); | |
| 903 | 948 | } else { |
| 904 | 949 | /* register */ |
| 905 | 950 | if (extra) |
| 906 | - gen_op_addl_T1_im(extra); | |
| 951 | + tcg_gen_addi_i32(var, var, extra); | |
| 907 | 952 | rm = (insn) & 0xf; |
| 908 | 953 | offset = load_reg(s, rm); |
| 909 | 954 | if (!(insn & (1 << 23))) |
| 910 | - tcg_gen_sub_i32(cpu_T[1], cpu_T[1], offset); | |
| 955 | + tcg_gen_sub_i32(var, var, offset); | |
| 911 | 956 | else |
| 912 | - tcg_gen_add_i32(cpu_T[1], cpu_T[1], offset); | |
| 957 | + tcg_gen_add_i32(var, var, offset); | |
| 913 | 958 | dead_tmp(offset); |
| 914 | 959 | } |
| 915 | 960 | } |
| ... | ... | @@ -1090,6 +1135,7 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) |
| 1090 | 1135 | { |
| 1091 | 1136 | int rd, wrd; |
| 1092 | 1137 | int rdhi, rdlo, rd0, rd1, i; |
| 1138 | + TCGv tmp; | |
| 1093 | 1139 | |
| 1094 | 1140 | if ((insn & 0x0e000e00) == 0x0c000000) { |
| 1095 | 1141 | if ((insn & 0x0fe00ff0) == 0x0c400000) { |
| ... | ... | @@ -1114,7 +1160,9 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) |
| 1114 | 1160 | return 1; |
| 1115 | 1161 | if (insn & ARM_CP_RW_BIT) { |
| 1116 | 1162 | if ((insn >> 28) == 0xf) { /* WLDRW wCx */ |
| 1117 | - gen_ldst(ldl, s); | |
| 1163 | + tmp = gen_ld32(cpu_T[1], IS_USER(s)); | |
| 1164 | + tcg_gen_mov_i32(cpu_T[0], tmp); | |
| 1165 | + dead_tmp(tmp); | |
| 1118 | 1166 | gen_op_iwmmxt_movl_wCx_T0(wrd); |
| 1119 | 1167 | } else { |
| 1120 | 1168 | if (insn & (1 << 8)) |
| ... | ... | @@ -1132,7 +1180,9 @@ static int disas_iwmmxt_insn(CPUState *env, DisasContext *s, uint32_t insn) |
| 1132 | 1180 | } else { |
| 1133 | 1181 | if ((insn >> 28) == 0xf) { /* WSTRW wCx */ |
| 1134 | 1182 | gen_op_iwmmxt_movl_T0_wCx(wrd); |
| 1135 | - gen_ldst(stl, s); | |
| 1183 | + tmp = new_tmp(); | |
| 1184 | + tcg_gen_mov_i32(tmp, cpu_T[0]); | |
| 1185 | + gen_st32(tmp, cpu_T[1], IS_USER(s)); | |
| 1136 | 1186 | } else { |
| 1137 | 1187 | gen_op_iwmmxt_movq_M0_wRn(wrd); |
| 1138 | 1188 | if (insn & (1 << 8)) |
| ... | ... | @@ -2970,12 +3020,12 @@ static void gen_exception_return(DisasContext *s) |
| 2970 | 3020 | s->is_jmp = DISAS_UPDATE; |
| 2971 | 3021 | } |
| 2972 | 3022 | |
| 2973 | -/* Generate a v6 exception return. */ | |
| 2974 | -static void gen_rfe(DisasContext *s) | |
| 3023 | +/* Generate a v6 exception return. Marks both values as dead. */ | |
| 3024 | +static void gen_rfe(DisasContext *s, TCGv pc, TCGv cpsr) | |
| 2975 | 3025 | { |
| 2976 | - gen_set_cpsr(cpu_T[0], 0xffffffff); | |
| 2977 | - gen_op_movl_T0_T2(); | |
| 2978 | - gen_set_pc_T0(); | |
| 3026 | + gen_set_cpsr(cpsr, 0xffffffff); | |
| 3027 | + dead_tmp(cpsr); | |
| 3028 | + store_reg(s, 15, pc); | |
| 2979 | 3029 | s->is_jmp = DISAS_UPDATE; |
| 2980 | 3030 | } |
| 2981 | 3031 | |
| ... | ... | @@ -3288,6 +3338,7 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) |
| 3288 | 3338 | int shift; |
| 3289 | 3339 | uint32_t mask; |
| 3290 | 3340 | int n; |
| 3341 | + TCGv tmp; | |
| 3291 | 3342 | |
| 3292 | 3343 | if (!vfp_enabled(env)) |
| 3293 | 3344 | return 1; |
| ... | ... | @@ -3316,36 +3367,50 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) |
| 3316 | 3367 | for (pass = 0; pass < 2; pass++) { |
| 3317 | 3368 | if (size == 2) { |
| 3318 | 3369 | if (load) { |
| 3319 | - gen_ldst(ldl, s); | |
| 3370 | + tmp = gen_ld32(cpu_T[1], IS_USER(s)); | |
| 3371 | + tcg_gen_mov_i32(cpu_T[0], tmp); | |
| 3372 | + dead_tmp(tmp); | |
| 3320 | 3373 | NEON_SET_REG(T0, rd, pass); |
| 3321 | 3374 | } else { |
| 3322 | 3375 | NEON_GET_REG(T0, rd, pass); |
| 3323 | - gen_ldst(stl, s); | |
| 3376 | + tmp = new_tmp(); | |
| 3377 | + tcg_gen_mov_i32(tmp, cpu_T[0]); | |
| 3378 | + gen_st32(tmp, cpu_T[1], IS_USER(s)); | |
| 3324 | 3379 | } |
| 3325 | 3380 | gen_op_addl_T1_im(stride); |
| 3326 | 3381 | } else if (size == 1) { |
| 3327 | 3382 | if (load) { |
| 3328 | - gen_ldst(lduw, s); | |
| 3383 | + tmp = gen_ld16u(cpu_T[1], IS_USER(s)); | |
| 3384 | + tcg_gen_mov_i32(cpu_T[0], tmp); | |
| 3385 | + dead_tmp(tmp); | |
| 3329 | 3386 | gen_op_addl_T1_im(stride); |
| 3330 | 3387 | gen_op_movl_T2_T0(); |
| 3331 | - gen_ldst(lduw, s); | |
| 3388 | + tmp = gen_ld16u(cpu_T[1], IS_USER(s)); | |
| 3389 | + tcg_gen_mov_i32(cpu_T[0], tmp); | |
| 3390 | + dead_tmp(tmp); | |
| 3332 | 3391 | gen_op_addl_T1_im(stride); |
| 3333 | 3392 | gen_op_neon_insert_elt(16, 0xffff); |
| 3334 | 3393 | NEON_SET_REG(T2, rd, pass); |
| 3335 | 3394 | } else { |
| 3336 | 3395 | NEON_GET_REG(T2, rd, pass); |
| 3337 | 3396 | gen_op_movl_T0_T2(); |
| 3338 | - gen_ldst(stw, s); | |
| 3397 | + tmp = new_tmp(); | |
| 3398 | + tcg_gen_mov_i32(tmp, cpu_T[0]); | |
| 3399 | + gen_st16(tmp, cpu_T[1], IS_USER(s)); | |
| 3339 | 3400 | gen_op_addl_T1_im(stride); |
| 3340 | 3401 | gen_op_neon_extract_elt(16, 0xffff0000); |
| 3341 | - gen_ldst(stw, s); | |
| 3402 | + tmp = new_tmp(); | |
| 3403 | + tcg_gen_mov_i32(tmp, cpu_T[0]); | |
| 3404 | + gen_st16(tmp, cpu_T[1], IS_USER(s)); | |
| 3342 | 3405 | gen_op_addl_T1_im(stride); |
| 3343 | 3406 | } |
| 3344 | 3407 | } else /* size == 0 */ { |
| 3345 | 3408 | if (load) { |
| 3346 | 3409 | mask = 0xff; |
| 3347 | 3410 | for (n = 0; n < 4; n++) { |
| 3348 | - gen_ldst(ldub, s); | |
| 3411 | + tmp = gen_ld8u(cpu_T[1], IS_USER(s)); | |
| 3412 | + tcg_gen_mov_i32(cpu_T[0], tmp); | |
| 3413 | + dead_tmp(tmp); | |
| 3349 | 3414 | gen_op_addl_T1_im(stride); |
| 3350 | 3415 | if (n == 0) { |
| 3351 | 3416 | gen_op_movl_T2_T0(); |
| ... | ... | @@ -3364,7 +3429,9 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) |
| 3364 | 3429 | } else { |
| 3365 | 3430 | gen_op_neon_extract_elt(n * 8, mask); |
| 3366 | 3431 | } |
| 3367 | - gen_ldst(stb, s); | |
| 3432 | + tmp = new_tmp(); | |
| 3433 | + tcg_gen_mov_i32(tmp, cpu_T[0]); | |
| 3434 | + gen_st8(tmp, cpu_T[1], IS_USER(s)); | |
| 3368 | 3435 | gen_op_addl_T1_im(stride); |
| 3369 | 3436 | mask <<= 8; |
| 3370 | 3437 | } |
| ... | ... | @@ -3387,15 +3454,21 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) |
| 3387 | 3454 | for (reg = 0; reg < nregs; reg++) { |
| 3388 | 3455 | switch (size) { |
| 3389 | 3456 | case 0: |
| 3390 | - gen_ldst(ldub, s); | |
| 3457 | + tmp = gen_ld8u(cpu_T[1], IS_USER(s)); | |
| 3458 | + tcg_gen_mov_i32(cpu_T[0], tmp); | |
| 3459 | + dead_tmp(tmp); | |
| 3391 | 3460 | gen_op_neon_dup_u8(0); |
| 3392 | 3461 | break; |
| 3393 | 3462 | case 1: |
| 3394 | - gen_ldst(lduw, s); | |
| 3463 | + tmp = gen_ld16u(cpu_T[1], IS_USER(s)); | |
| 3464 | + tcg_gen_mov_i32(cpu_T[0], tmp); | |
| 3465 | + dead_tmp(tmp); | |
| 3395 | 3466 | gen_op_neon_dup_low16(); |
| 3396 | 3467 | break; |
| 3397 | 3468 | case 2: |
| 3398 | - gen_ldst(ldl, s); | |
| 3469 | + tmp = gen_ld32(cpu_T[0], IS_USER(s)); | |
| 3470 | + tcg_gen_mov_i32(cpu_T[0], tmp); | |
| 3471 | + dead_tmp(tmp); | |
| 3399 | 3472 | break; |
| 3400 | 3473 | case 3: |
| 3401 | 3474 | return 1; |
| ... | ... | @@ -3437,19 +3510,22 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) |
| 3437 | 3510 | } |
| 3438 | 3511 | switch (size) { |
| 3439 | 3512 | case 0: |
| 3440 | - gen_ldst(ldub, s); | |
| 3513 | + tmp = gen_ld8u(cpu_T[1], IS_USER(s)); | |
| 3441 | 3514 | break; |
| 3442 | 3515 | case 1: |
| 3443 | - gen_ldst(lduw, s); | |
| 3516 | + tmp = gen_ld16u(cpu_T[1], IS_USER(s)); | |
| 3444 | 3517 | break; |
| 3445 | 3518 | case 2: |
| 3446 | - gen_ldst(ldl, s); | |
| 3447 | - NEON_SET_REG(T0, rd, pass); | |
| 3519 | + tmp = gen_ld32(cpu_T[1], IS_USER(s)); | |
| 3448 | 3520 | break; |
| 3449 | 3521 | } |
| 3522 | + tcg_gen_mov_i32(cpu_T[0], tmp); | |
| 3523 | + dead_tmp(tmp); | |
| 3450 | 3524 | if (size != 2) { |
| 3451 | 3525 | gen_op_neon_insert_elt(shift, ~mask); |
| 3452 | 3526 | NEON_SET_REG(T0, rd, pass); |
| 3527 | + } else { | |
| 3528 | + NEON_SET_REG(T0, rd, pass); | |
| 3453 | 3529 | } |
| 3454 | 3530 | } else { /* Store */ |
| 3455 | 3531 | if (size == 2) { |
| ... | ... | @@ -3458,15 +3534,17 @@ static int disas_neon_ls_insn(CPUState * env, DisasContext *s, uint32_t insn) |
| 3458 | 3534 | NEON_GET_REG(T2, rd, pass); |
| 3459 | 3535 | gen_op_neon_extract_elt(shift, mask); |
| 3460 | 3536 | } |
| 3537 | + tmp = new_tmp(); | |
| 3538 | + tcg_gen_mov_i32(tmp, cpu_T[0]); | |
| 3461 | 3539 | switch (size) { |
| 3462 | 3540 | case 0: |
| 3463 | - gen_ldst(stb, s); | |
| 3541 | + gen_st8(tmp, cpu_T[1], IS_USER(s)); | |
| 3464 | 3542 | break; |
| 3465 | 3543 | case 1: |
| 3466 | - gen_ldst(stw, s); | |
| 3544 | + gen_st16(tmp, cpu_T[1], IS_USER(s)); | |
| 3467 | 3545 | break; |
| 3468 | 3546 | case 2: |
| 3469 | - gen_ldst(stl, s); | |
| 3547 | + gen_st32(tmp, cpu_T[1], IS_USER(s)); | |
| 3470 | 3548 | break; |
| 3471 | 3549 | } |
| 3472 | 3550 | } |
| ... | ... | @@ -4647,7 +4725,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) |
| 4647 | 4725 | NEON_GET_REG(T0, rm, pass * 2); |
| 4648 | 4726 | NEON_GET_REG(T1, rm, pass * 2 + 1); |
| 4649 | 4727 | switch (size) { |
| 4650 | - case 0: gen_op_rev_T0(); break; | |
| 4728 | + case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break; | |
| 4651 | 4729 | case 1: gen_swap_half(cpu_T[0]); break; |
| 4652 | 4730 | case 2: /* no-op */ break; |
| 4653 | 4731 | default: abort(); |
| ... | ... | @@ -4658,7 +4736,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) |
| 4658 | 4736 | } else { |
| 4659 | 4737 | gen_op_movl_T0_T1(); |
| 4660 | 4738 | switch (size) { |
| 4661 | - case 0: gen_op_rev_T0(); break; | |
| 4739 | + case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break; | |
| 4662 | 4740 | case 1: gen_swap_half(cpu_T[0]); break; |
| 4663 | 4741 | default: abort(); |
| 4664 | 4742 | } |
| ... | ... | @@ -4827,7 +4905,7 @@ static int disas_neon_data_insn(CPUState * env, DisasContext *s, uint32_t insn) |
| 4827 | 4905 | switch (op) { |
| 4828 | 4906 | case 1: /* VREV32 */ |
| 4829 | 4907 | switch (size) { |
| 4830 | - case 0: gen_op_rev_T0(); break; | |
| 4908 | + case 0: tcg_gen_bswap_i32(cpu_T[0], cpu_T[0]); break; | |
| 4831 | 4909 | case 1: gen_swap_half(cpu_T[0]); break; |
| 4832 | 4910 | default: return 1; |
| 4833 | 4911 | } |
| ... | ... | @@ -5099,6 +5177,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 5099 | 5177 | TCGv tmp; |
| 5100 | 5178 | TCGv tmp2; |
| 5101 | 5179 | TCGv tmp3; |
| 5180 | + TCGv addr; | |
| 5102 | 5181 | |
| 5103 | 5182 | insn = ldl_code(s->pc); |
| 5104 | 5183 | s->pc += 4; |
| ... | ... | @@ -5160,9 +5239,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 5160 | 5239 | ARCH(6); |
| 5161 | 5240 | op1 = (insn & 0x1f); |
| 5162 | 5241 | if (op1 == (env->uncached_cpsr & CPSR_M)) { |
| 5163 | - gen_movl_T1_reg(s, 13); | |
| 5242 | + addr = load_reg(s, 13); | |
| 5164 | 5243 | } else { |
| 5165 | - gen_op_movl_T1_r13_banked(op1); | |
| 5244 | + addr = new_tmp(); | |
| 5245 | + gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op1)); | |
| 5166 | 5246 | } |
| 5167 | 5247 | i = (insn >> 23) & 3; |
| 5168 | 5248 | switch (i) { |
| ... | ... | @@ -5173,12 +5253,13 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 5173 | 5253 | default: abort(); |
| 5174 | 5254 | } |
| 5175 | 5255 | if (offset) |
| 5176 | - gen_op_addl_T1_im(offset); | |
| 5177 | - gen_movl_T0_reg(s, 14); | |
| 5178 | - gen_ldst(stl, s); | |
| 5179 | - gen_helper_cpsr_read(cpu_T[0]); | |
| 5180 | - gen_op_addl_T1_im(4); | |
| 5181 | - gen_ldst(stl, s); | |
| 5256 | + tcg_gen_addi_i32(addr, addr, offset); | |
| 5257 | + tmp = load_reg(s, 14); | |
| 5258 | + gen_st32(tmp, addr, 0); | |
| 5259 | + tmp = new_tmp(); | |
| 5260 | + gen_helper_cpsr_read(tmp); | |
| 5261 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 5262 | + gen_st32(tmp, addr, 0); | |
| 5182 | 5263 | if (insn & (1 << 21)) { |
| 5183 | 5264 | /* Base writeback. */ |
| 5184 | 5265 | switch (i) { |
| ... | ... | @@ -5189,12 +5270,14 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 5189 | 5270 | default: abort(); |
| 5190 | 5271 | } |
| 5191 | 5272 | if (offset) |
| 5192 | - gen_op_addl_T1_im(offset); | |
| 5273 | + tcg_gen_addi_i32(addr, tmp, offset); | |
| 5193 | 5274 | if (op1 == (env->uncached_cpsr & CPSR_M)) { |
| 5194 | 5275 | gen_movl_reg_T1(s, 13); |
| 5195 | 5276 | } else { |
| 5196 | - gen_op_movl_r13_T1_banked(op1); | |
| 5277 | + gen_helper_set_r13_banked(cpu_env, tcg_const_i32(op1), cpu_T[1]); | |
| 5197 | 5278 | } |
| 5279 | + } else { | |
| 5280 | + dead_tmp(addr); | |
| 5198 | 5281 | } |
| 5199 | 5282 | } else if ((insn & 0x0e5fffe0) == 0x081d0a00) { |
| 5200 | 5283 | /* rfe */ |
| ... | ... | @@ -5203,36 +5286,37 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 5203 | 5286 | goto illegal_op; |
| 5204 | 5287 | ARCH(6); |
| 5205 | 5288 | rn = (insn >> 16) & 0xf; |
| 5206 | - gen_movl_T1_reg(s, rn); | |
| 5289 | + addr = load_reg(s, rn); | |
| 5207 | 5290 | i = (insn >> 23) & 3; |
| 5208 | 5291 | switch (i) { |
| 5209 | - case 0: offset = 0; break; /* DA */ | |
| 5210 | - case 1: offset = -4; break; /* DB */ | |
| 5211 | - case 2: offset = 4; break; /* IA */ | |
| 5212 | - case 3: offset = 8; break; /* IB */ | |
| 5292 | + case 0: offset = -4; break; /* DA */ | |
| 5293 | + case 1: offset = -8; break; /* DB */ | |
| 5294 | + case 2: offset = 0; break; /* IA */ | |
| 5295 | + case 3: offset = 4; break; /* IB */ | |
| 5213 | 5296 | default: abort(); |
| 5214 | 5297 | } |
| 5215 | 5298 | if (offset) |
| 5216 | - gen_op_addl_T1_im(offset); | |
| 5217 | - /* Load CPSR into T2 and PC into T0. */ | |
| 5218 | - gen_ldst(ldl, s); | |
| 5219 | - gen_op_movl_T2_T0(); | |
| 5220 | - gen_op_addl_T1_im(-4); | |
| 5221 | - gen_ldst(ldl, s); | |
| 5299 | + tcg_gen_addi_i32(addr, addr, offset); | |
| 5300 | + /* Load PC into tmp and CPSR into tmp2. */ | |
| 5301 | + tmp = gen_ld32(addr, 0); | |
| 5302 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 5303 | + tmp2 = gen_ld32(addr, 0); | |
| 5222 | 5304 | if (insn & (1 << 21)) { |
| 5223 | 5305 | /* Base writeback. */ |
| 5224 | 5306 | switch (i) { |
| 5225 | - case 0: offset = -4; break; | |
| 5226 | - case 1: offset = 0; break; | |
| 5227 | - case 2: offset = 8; break; | |
| 5228 | - case 3: offset = 4; break; | |
| 5307 | + case 0: offset = -8; break; | |
| 5308 | + case 1: offset = -4; break; | |
| 5309 | + case 2: offset = 4; break; | |
| 5310 | + case 3: offset = 0; break; | |
| 5229 | 5311 | default: abort(); |
| 5230 | 5312 | } |
| 5231 | 5313 | if (offset) |
| 5232 | - gen_op_addl_T1_im(offset); | |
| 5233 | - gen_movl_reg_T1(s, rn); | |
| 5314 | + tcg_gen_addi_i32(addr, addr, offset); | |
| 5315 | + store_reg(s, rn, addr); | |
| 5316 | + } else { | |
| 5317 | + dead_tmp(addr); | |
| 5234 | 5318 | } |
| 5235 | - gen_rfe(s); | |
| 5319 | + gen_rfe(s, tmp, tmp2); | |
| 5236 | 5320 | } else if ((insn & 0x0e000000) == 0x0a000000) { |
| 5237 | 5321 | /* branch link and change to thumb (blx <offset>) */ |
| 5238 | 5322 | int32_t offset; |
| ... | ... | @@ -5707,22 +5791,22 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 5707 | 5791 | /* Misc load/store */ |
| 5708 | 5792 | rn = (insn >> 16) & 0xf; |
| 5709 | 5793 | rd = (insn >> 12) & 0xf; |
| 5710 | - gen_movl_T1_reg(s, rn); | |
| 5794 | + addr = load_reg(s, rn); | |
| 5711 | 5795 | if (insn & (1 << 24)) |
| 5712 | - gen_add_datah_offset(s, insn, 0); | |
| 5796 | + gen_add_datah_offset(s, insn, 0, addr); | |
| 5713 | 5797 | address_offset = 0; |
| 5714 | 5798 | if (insn & (1 << 20)) { |
| 5715 | 5799 | /* load */ |
| 5716 | 5800 | switch(sh) { |
| 5717 | 5801 | case 1: |
| 5718 | - gen_ldst(lduw, s); | |
| 5802 | + tmp = gen_ld16u(addr, IS_USER(s)); | |
| 5719 | 5803 | break; |
| 5720 | 5804 | case 2: |
| 5721 | - gen_ldst(ldsb, s); | |
| 5805 | + tmp = gen_ld8s(addr, IS_USER(s)); | |
| 5722 | 5806 | break; |
| 5723 | 5807 | default: |
| 5724 | 5808 | case 3: |
| 5725 | - gen_ldst(ldsw, s); | |
| 5809 | + tmp = gen_ld16s(addr, IS_USER(s)); | |
| 5726 | 5810 | break; |
| 5727 | 5811 | } |
| 5728 | 5812 | load = 1; |
| ... | ... | @@ -5730,26 +5814,26 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 5730 | 5814 | /* doubleword */ |
| 5731 | 5815 | if (sh & 1) { |
| 5732 | 5816 | /* store */ |
| 5733 | - gen_movl_T0_reg(s, rd); | |
| 5734 | - gen_ldst(stl, s); | |
| 5735 | - gen_op_addl_T1_im(4); | |
| 5736 | - gen_movl_T0_reg(s, rd + 1); | |
| 5737 | - gen_ldst(stl, s); | |
| 5817 | + tmp = load_reg(s, rd); | |
| 5818 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 5819 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 5820 | + tmp = load_reg(s, rd + 1); | |
| 5821 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 5738 | 5822 | load = 0; |
| 5739 | 5823 | } else { |
| 5740 | 5824 | /* load */ |
| 5741 | - gen_ldst(ldl, s); | |
| 5742 | - gen_movl_reg_T0(s, rd); | |
| 5743 | - gen_op_addl_T1_im(4); | |
| 5744 | - gen_ldst(ldl, s); | |
| 5825 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 5826 | + store_reg(s, rd, tmp); | |
| 5827 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 5828 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 5745 | 5829 | rd++; |
| 5746 | 5830 | load = 1; |
| 5747 | 5831 | } |
| 5748 | 5832 | address_offset = -4; |
| 5749 | 5833 | } else { |
| 5750 | 5834 | /* store */ |
| 5751 | - gen_movl_T0_reg(s, rd); | |
| 5752 | - gen_ldst(stw, s); | |
| 5835 | + tmp = load_reg(s, rd); | |
| 5836 | + gen_st16(tmp, addr, IS_USER(s)); | |
| 5753 | 5837 | load = 0; |
| 5754 | 5838 | } |
| 5755 | 5839 | /* Perform base writeback before the loaded value to |
| ... | ... | @@ -5757,16 +5841,18 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 5757 | 5841 | ldrd with base writeback is is undefined if the |
| 5758 | 5842 | destination and index registers overlap. */ |
| 5759 | 5843 | if (!(insn & (1 << 24))) { |
| 5760 | - gen_add_datah_offset(s, insn, address_offset); | |
| 5761 | - gen_movl_reg_T1(s, rn); | |
| 5844 | + gen_add_datah_offset(s, insn, address_offset, addr); | |
| 5845 | + store_reg(s, rn, addr); | |
| 5762 | 5846 | } else if (insn & (1 << 21)) { |
| 5763 | 5847 | if (address_offset) |
| 5764 | - gen_op_addl_T1_im(address_offset); | |
| 5765 | - gen_movl_reg_T1(s, rn); | |
| 5848 | + tcg_gen_addi_i32(addr, addr, address_offset); | |
| 5849 | + store_reg(s, rn, addr); | |
| 5850 | + } else { | |
| 5851 | + dead_tmp(addr); | |
| 5766 | 5852 | } |
| 5767 | 5853 | if (load) { |
| 5768 | 5854 | /* Complete the load. */ |
| 5769 | - gen_movl_reg_T0(s, rd); | |
| 5855 | + store_reg(s, rd, tmp); | |
| 5770 | 5856 | } |
| 5771 | 5857 | } |
| 5772 | 5858 | break; |
| ... | ... | @@ -5882,21 +5968,21 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 5882 | 5968 | gen_movl_reg_T1(s, rd); |
| 5883 | 5969 | } else if ((insn & 0x003f0f60) == 0x003f0f20) { |
| 5884 | 5970 | /* rev */ |
| 5885 | - gen_movl_T0_reg(s, rm); | |
| 5971 | + tmp = load_reg(s, rm); | |
| 5886 | 5972 | if (insn & (1 << 22)) { |
| 5887 | 5973 | if (insn & (1 << 7)) { |
| 5888 | - gen_revsh(cpu_T[0]); | |
| 5974 | + gen_revsh(tmp); | |
| 5889 | 5975 | } else { |
| 5890 | 5976 | ARCH(6T2); |
| 5891 | - gen_helper_rbit(cpu_T[0], cpu_T[0]); | |
| 5977 | + gen_helper_rbit(tmp, tmp); | |
| 5892 | 5978 | } |
| 5893 | 5979 | } else { |
| 5894 | 5980 | if (insn & (1 << 7)) |
| 5895 | - gen_rev16(cpu_T[0]); | |
| 5981 | + gen_rev16(tmp); | |
| 5896 | 5982 | else |
| 5897 | - gen_op_rev_T0(); | |
| 5983 | + tcg_gen_bswap_i32(tmp, tmp); | |
| 5898 | 5984 | } |
| 5899 | - gen_movl_reg_T0(s, rd); | |
| 5985 | + store_reg(s, rd, tmp); | |
| 5900 | 5986 | } else { |
| 5901 | 5987 | goto illegal_op; |
| 5902 | 5988 | } |
| ... | ... | @@ -6020,71 +6106,47 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 6020 | 6106 | /* load/store byte/word */ |
| 6021 | 6107 | rn = (insn >> 16) & 0xf; |
| 6022 | 6108 | rd = (insn >> 12) & 0xf; |
| 6023 | - gen_movl_T1_reg(s, rn); | |
| 6109 | + tmp2 = load_reg(s, rn); | |
| 6024 | 6110 | i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000); |
| 6025 | 6111 | if (insn & (1 << 24)) |
| 6026 | - gen_add_data_offset(s, insn); | |
| 6112 | + gen_add_data_offset(s, insn, tmp2); | |
| 6027 | 6113 | if (insn & (1 << 20)) { |
| 6028 | 6114 | /* load */ |
| 6029 | 6115 | s->is_mem = 1; |
| 6030 | -#if defined(CONFIG_USER_ONLY) | |
| 6031 | - if (insn & (1 << 22)) | |
| 6032 | - gen_op_ldub_raw(); | |
| 6033 | - else | |
| 6034 | - gen_op_ldl_raw(); | |
| 6035 | -#else | |
| 6036 | 6116 | if (insn & (1 << 22)) { |
| 6037 | - if (i) | |
| 6038 | - gen_op_ldub_user(); | |
| 6039 | - else | |
| 6040 | - gen_op_ldub_kernel(); | |
| 6117 | + tmp = gen_ld8u(tmp2, i); | |
| 6041 | 6118 | } else { |
| 6042 | - if (i) | |
| 6043 | - gen_op_ldl_user(); | |
| 6044 | - else | |
| 6045 | - gen_op_ldl_kernel(); | |
| 6119 | + tmp = gen_ld32(tmp2, i); | |
| 6046 | 6120 | } |
| 6047 | -#endif | |
| 6048 | 6121 | } else { |
| 6049 | 6122 | /* store */ |
| 6050 | - gen_movl_T0_reg(s, rd); | |
| 6051 | -#if defined(CONFIG_USER_ONLY) | |
| 6123 | + tmp = load_reg(s, rd); | |
| 6052 | 6124 | if (insn & (1 << 22)) |
| 6053 | - gen_op_stb_raw(); | |
| 6125 | + gen_st8(tmp, tmp2, i); | |
| 6054 | 6126 | else |
| 6055 | - gen_op_stl_raw(); | |
| 6056 | -#else | |
| 6057 | - if (insn & (1 << 22)) { | |
| 6058 | - if (i) | |
| 6059 | - gen_op_stb_user(); | |
| 6060 | - else | |
| 6061 | - gen_op_stb_kernel(); | |
| 6062 | - } else { | |
| 6063 | - if (i) | |
| 6064 | - gen_op_stl_user(); | |
| 6065 | - else | |
| 6066 | - gen_op_stl_kernel(); | |
| 6067 | - } | |
| 6068 | -#endif | |
| 6127 | + gen_st32(tmp, tmp2, i); | |
| 6069 | 6128 | } |
| 6070 | 6129 | if (!(insn & (1 << 24))) { |
| 6071 | - gen_add_data_offset(s, insn); | |
| 6072 | - gen_movl_reg_T1(s, rn); | |
| 6073 | - } else if (insn & (1 << 21)) | |
| 6074 | - gen_movl_reg_T1(s, rn); { | |
| 6130 | + gen_add_data_offset(s, insn, tmp2); | |
| 6131 | + store_reg(s, rn, tmp2); | |
| 6132 | + } else if (insn & (1 << 21)) { | |
| 6133 | + store_reg(s, rn, tmp2); | |
| 6134 | + } else { | |
| 6135 | + dead_tmp(tmp2); | |
| 6075 | 6136 | } |
| 6076 | 6137 | if (insn & (1 << 20)) { |
| 6077 | 6138 | /* Complete the load. */ |
| 6078 | 6139 | if (rd == 15) |
| 6079 | - gen_bx_T0(s); | |
| 6140 | + gen_bx(s, tmp); | |
| 6080 | 6141 | else |
| 6081 | - gen_movl_reg_T0(s, rd); | |
| 6142 | + store_reg(s, rd, tmp); | |
| 6082 | 6143 | } |
| 6083 | 6144 | break; |
| 6084 | 6145 | case 0x08: |
| 6085 | 6146 | case 0x09: |
| 6086 | 6147 | { |
| 6087 | 6148 | int j, n, user, loaded_base; |
| 6149 | + TCGv loaded_var; | |
| 6088 | 6150 | /* load/store multiple words */ |
| 6089 | 6151 | /* XXX: store correct base if write back */ |
| 6090 | 6152 | user = 0; |
| ... | ... | @@ -6096,7 +6158,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 6096 | 6158 | user = 1; |
| 6097 | 6159 | } |
| 6098 | 6160 | rn = (insn >> 16) & 0xf; |
| 6099 | - gen_movl_T1_reg(s, rn); | |
| 6161 | + addr = load_reg(s, rn); | |
| 6100 | 6162 | |
| 6101 | 6163 | /* compute total size */ |
| 6102 | 6164 | loaded_base = 0; |
| ... | ... | @@ -6109,18 +6171,18 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 6109 | 6171 | if (insn & (1 << 23)) { |
| 6110 | 6172 | if (insn & (1 << 24)) { |
| 6111 | 6173 | /* pre increment */ |
| 6112 | - gen_op_addl_T1_im(4); | |
| 6174 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 6113 | 6175 | } else { |
| 6114 | 6176 | /* post increment */ |
| 6115 | 6177 | } |
| 6116 | 6178 | } else { |
| 6117 | 6179 | if (insn & (1 << 24)) { |
| 6118 | 6180 | /* pre decrement */ |
| 6119 | - gen_op_addl_T1_im(-(n * 4)); | |
| 6181 | + tcg_gen_addi_i32(addr, addr, -(n * 4)); | |
| 6120 | 6182 | } else { |
| 6121 | 6183 | /* post decrement */ |
| 6122 | 6184 | if (n != 1) |
| 6123 | - gen_op_addl_T1_im(-((n - 1) * 4)); | |
| 6185 | + tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); | |
| 6124 | 6186 | } |
| 6125 | 6187 | } |
| 6126 | 6188 | j = 0; |
| ... | ... | @@ -6128,34 +6190,37 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 6128 | 6190 | if (insn & (1 << i)) { |
| 6129 | 6191 | if (insn & (1 << 20)) { |
| 6130 | 6192 | /* load */ |
| 6131 | - gen_ldst(ldl, s); | |
| 6193 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 6132 | 6194 | if (i == 15) { |
| 6133 | - gen_bx_T0(s); | |
| 6195 | + gen_bx(s, tmp); | |
| 6134 | 6196 | } else if (user) { |
| 6135 | - gen_op_movl_user_T0(i); | |
| 6197 | + gen_helper_set_user_reg(tcg_const_i32(i), tmp); | |
| 6198 | + dead_tmp(tmp); | |
| 6136 | 6199 | } else if (i == rn) { |
| 6137 | - gen_op_movl_T2_T0(); | |
| 6200 | + loaded_var = tmp; | |
| 6138 | 6201 | loaded_base = 1; |
| 6139 | 6202 | } else { |
| 6140 | - gen_movl_reg_T0(s, i); | |
| 6203 | + store_reg(s, i, tmp); | |
| 6141 | 6204 | } |
| 6142 | 6205 | } else { |
| 6143 | 6206 | /* store */ |
| 6144 | 6207 | if (i == 15) { |
| 6145 | 6208 | /* special case: r15 = PC + 8 */ |
| 6146 | 6209 | val = (long)s->pc + 4; |
| 6147 | - gen_op_movl_T0_im(val); | |
| 6210 | + tmp = new_tmp(); | |
| 6211 | + tcg_gen_movi_i32(tmp, val); | |
| 6148 | 6212 | } else if (user) { |
| 6149 | - gen_op_movl_T0_user(i); | |
| 6213 | + tmp = new_tmp(); | |
| 6214 | + gen_helper_get_user_reg(tmp, tcg_const_i32(i)); | |
| 6150 | 6215 | } else { |
| 6151 | - gen_movl_T0_reg(s, i); | |
| 6216 | + tmp = load_reg(s, i); | |
| 6152 | 6217 | } |
| 6153 | - gen_ldst(stl, s); | |
| 6218 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 6154 | 6219 | } |
| 6155 | 6220 | j++; |
| 6156 | 6221 | /* no need to add after the last transfer */ |
| 6157 | 6222 | if (j != n) |
| 6158 | - gen_op_addl_T1_im(4); | |
| 6223 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 6159 | 6224 | } |
| 6160 | 6225 | } |
| 6161 | 6226 | if (insn & (1 << 21)) { |
| ... | ... | @@ -6165,23 +6230,24 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) |
| 6165 | 6230 | /* pre increment */ |
| 6166 | 6231 | } else { |
| 6167 | 6232 | /* post increment */ |
| 6168 | - gen_op_addl_T1_im(4); | |
| 6233 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 6169 | 6234 | } |
| 6170 | 6235 | } else { |
| 6171 | 6236 | if (insn & (1 << 24)) { |
| 6172 | 6237 | /* pre decrement */ |
| 6173 | 6238 | if (n != 1) |
| 6174 | - gen_op_addl_T1_im(-((n - 1) * 4)); | |
| 6239 | + tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); | |
| 6175 | 6240 | } else { |
| 6176 | 6241 | /* post decrement */ |
| 6177 | - gen_op_addl_T1_im(-(n * 4)); | |
| 6242 | + tcg_gen_addi_i32(addr, addr, -(n * 4)); | |
| 6178 | 6243 | } |
| 6179 | 6244 | } |
| 6180 | - gen_movl_reg_T1(s, rn); | |
| 6245 | + store_reg(s, rn, addr); | |
| 6246 | + } else { | |
| 6247 | + dead_tmp(addr); | |
| 6181 | 6248 | } |
| 6182 | 6249 | if (loaded_base) { |
| 6183 | - gen_op_movl_T0_T2(); | |
| 6184 | - gen_movl_reg_T0(s, rn); | |
| 6250 | + store_reg(s, rn, loaded_var); | |
| 6185 | 6251 | } |
| 6186 | 6252 | if ((insn & (1 << 22)) && !user) { |
| 6187 | 6253 | /* Restore CPSR from SPSR. */ |
| ... | ... | @@ -6319,11 +6385,12 @@ gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out) |
| 6319 | 6385 | is not legal. */ |
| 6320 | 6386 | static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6321 | 6387 | { |
| 6322 | - uint32_t insn, imm, shift, offset, addr; | |
| 6388 | + uint32_t insn, imm, shift, offset; | |
| 6323 | 6389 | uint32_t rd, rn, rm, rs; |
| 6324 | 6390 | TCGv tmp; |
| 6325 | 6391 | TCGv tmp2; |
| 6326 | 6392 | TCGv tmp3; |
| 6393 | + TCGv addr; | |
| 6327 | 6394 | int op; |
| 6328 | 6395 | int shiftop; |
| 6329 | 6396 | int conds; |
| ... | ... | @@ -6341,9 +6408,8 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6341 | 6408 | tcg_gen_addi_i32(tmp, tmp, offset); |
| 6342 | 6409 | tcg_gen_andi_i32(tmp, tmp, 0xfffffffc); |
| 6343 | 6410 | |
| 6344 | - addr = (uint32_t)s->pc; | |
| 6345 | 6411 | tmp2 = new_tmp(); |
| 6346 | - tcg_gen_movi_i32(tmp2, addr | 1); | |
| 6412 | + tcg_gen_movi_i32(tmp2, s->pc | 1); | |
| 6347 | 6413 | store_reg(s, 14, tmp2); |
| 6348 | 6414 | gen_bx(s, tmp); |
| 6349 | 6415 | return 0; |
| ... | ... | @@ -6354,9 +6420,8 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6354 | 6420 | tmp = load_reg(s, 14); |
| 6355 | 6421 | tcg_gen_addi_i32(tmp, tmp, 14); |
| 6356 | 6422 | |
| 6357 | - addr = (uint32_t)s->pc; | |
| 6358 | 6423 | tmp2 = new_tmp(); |
| 6359 | - tcg_gen_movi_i32(tmp2, addr | 1); | |
| 6424 | + tcg_gen_movi_i32(tmp2, s->pc | 1); | |
| 6360 | 6425 | store_reg(s, 14, tmp2); |
| 6361 | 6426 | gen_bx(s, tmp); |
| 6362 | 6427 | return 0; |
| ... | ... | @@ -6366,8 +6431,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6366 | 6431 | 16-bit instructions in case the second half causes an |
| 6367 | 6432 | prefetch abort. */ |
| 6368 | 6433 | offset = ((int32_t)insn << 21) >> 9; |
| 6369 | - addr = s->pc + 2 + offset; | |
| 6370 | - gen_op_movl_T0_im(addr); | |
| 6434 | + gen_op_movl_T0_im(s->pc + 2 + offset); | |
| 6371 | 6435 | gen_movl_reg_T0(s, 14); |
| 6372 | 6436 | return 0; |
| 6373 | 6437 | } |
| ... | ... | @@ -6396,38 +6460,41 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6396 | 6460 | if (insn & 0x01200000) { |
| 6397 | 6461 | /* Load/store doubleword. */ |
| 6398 | 6462 | if (rn == 15) { |
| 6399 | - gen_op_movl_T1_im(s->pc & ~3); | |
| 6463 | + addr = new_tmp(); | |
| 6464 | + tcg_gen_movi_i32(addr, s->pc & ~3); | |
| 6400 | 6465 | } else { |
| 6401 | - gen_movl_T1_reg(s, rn); | |
| 6466 | + addr = load_reg(s, rn); | |
| 6402 | 6467 | } |
| 6403 | 6468 | offset = (insn & 0xff) * 4; |
| 6404 | 6469 | if ((insn & (1 << 23)) == 0) |
| 6405 | 6470 | offset = -offset; |
| 6406 | 6471 | if (insn & (1 << 24)) { |
| 6407 | - gen_op_addl_T1_im(offset); | |
| 6472 | + tcg_gen_addi_i32(addr, addr, offset); | |
| 6408 | 6473 | offset = 0; |
| 6409 | 6474 | } |
| 6410 | 6475 | if (insn & (1 << 20)) { |
| 6411 | 6476 | /* ldrd */ |
| 6412 | - gen_ldst(ldl, s); | |
| 6413 | - gen_movl_reg_T0(s, rs); | |
| 6414 | - gen_op_addl_T1_im(4); | |
| 6415 | - gen_ldst(ldl, s); | |
| 6416 | - gen_movl_reg_T0(s, rd); | |
| 6477 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 6478 | + store_reg(s, rs, tmp); | |
| 6479 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 6480 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 6481 | + store_reg(s, rd, tmp); | |
| 6417 | 6482 | } else { |
| 6418 | 6483 | /* strd */ |
| 6419 | - gen_movl_T0_reg(s, rs); | |
| 6420 | - gen_ldst(stl, s); | |
| 6421 | - gen_op_addl_T1_im(4); | |
| 6422 | - gen_movl_T0_reg(s, rd); | |
| 6423 | - gen_ldst(stl, s); | |
| 6484 | + tmp = load_reg(s, rs); | |
| 6485 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 6486 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 6487 | + tmp = load_reg(s, rd); | |
| 6488 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 6424 | 6489 | } |
| 6425 | 6490 | if (insn & (1 << 21)) { |
| 6426 | 6491 | /* Base writeback. */ |
| 6427 | 6492 | if (rn == 15) |
| 6428 | 6493 | goto illegal_op; |
| 6429 | - gen_op_addl_T1_im(offset - 4); | |
| 6430 | - gen_movl_reg_T1(s, rn); | |
| 6494 | + tcg_gen_addi_i32(addr, addr, offset - 4); | |
| 6495 | + store_reg(s, rn, addr); | |
| 6496 | + } else { | |
| 6497 | + dead_tmp(addr); | |
| 6431 | 6498 | } |
| 6432 | 6499 | } else if ((insn & (1 << 23)) == 0) { |
| 6433 | 6500 | /* Load/store exclusive word. */ |
| ... | ... | @@ -6442,24 +6509,26 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6442 | 6509 | } else if ((insn & (1 << 6)) == 0) { |
| 6443 | 6510 | /* Table Branch. */ |
| 6444 | 6511 | if (rn == 15) { |
| 6445 | - gen_op_movl_T1_im(s->pc); | |
| 6512 | + addr = new_tmp(); | |
| 6513 | + tcg_gen_movi_i32(addr, s->pc); | |
| 6446 | 6514 | } else { |
| 6447 | - gen_movl_T1_reg(s, rn); | |
| 6515 | + addr = load_reg(s, rn); | |
| 6448 | 6516 | } |
| 6449 | 6517 | tmp = load_reg(s, rm); |
| 6450 | - tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp); | |
| 6518 | + tcg_gen_add_i32(addr, addr, tmp); | |
| 6451 | 6519 | if (insn & (1 << 4)) { |
| 6452 | 6520 | /* tbh */ |
| 6453 | - tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp); | |
| 6521 | + tcg_gen_add_i32(addr, addr, tmp); | |
| 6454 | 6522 | dead_tmp(tmp); |
| 6455 | - gen_ldst(lduw, s); | |
| 6523 | + tmp = gen_ld16u(addr, IS_USER(s)); | |
| 6456 | 6524 | } else { /* tbb */ |
| 6457 | 6525 | dead_tmp(tmp); |
| 6458 | - gen_ldst(ldub, s); | |
| 6526 | + tmp = gen_ld8u(addr, IS_USER(s)); | |
| 6459 | 6527 | } |
| 6460 | - tcg_gen_shli_i32(cpu_T[0], cpu_T[0], 1); | |
| 6461 | - tcg_gen_addi_i32(cpu_T[0], cpu_T[0], s->pc); | |
| 6462 | - gen_movl_reg_T0(s, 15); | |
| 6528 | + dead_tmp(addr); | |
| 6529 | + tcg_gen_shli_i32(tmp, tmp, 1); | |
| 6530 | + tcg_gen_addi_i32(tmp, tmp, s->pc); | |
| 6531 | + store_reg(s, 15, tmp); | |
| 6463 | 6532 | } else { |
| 6464 | 6533 | /* Load/store exclusive byte/halfword/doubleword. */ |
| 6465 | 6534 | op = (insn >> 4) & 0x3; |
| ... | ... | @@ -6503,68 +6572,74 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6503 | 6572 | /* Load/store multiple, RFE, SRS. */ |
| 6504 | 6573 | if (((insn >> 23) & 1) == ((insn >> 24) & 1)) { |
| 6505 | 6574 | /* Not available in user mode. */ |
| 6506 | - if (!IS_USER(s)) | |
| 6575 | + if (IS_USER(s)) | |
| 6507 | 6576 | goto illegal_op; |
| 6508 | 6577 | if (insn & (1 << 20)) { |
| 6509 | 6578 | /* rfe */ |
| 6510 | - gen_movl_T1_reg(s, rn); | |
| 6511 | - if (insn & (1 << 24)) { | |
| 6512 | - gen_op_addl_T1_im(4); | |
| 6513 | - } else { | |
| 6514 | - gen_op_addl_T1_im(-4); | |
| 6515 | - } | |
| 6516 | - /* Load CPSR into T2 and PC into T0. */ | |
| 6517 | - gen_ldst(ldl, s); | |
| 6518 | - gen_op_movl_T2_T0(); | |
| 6519 | - gen_op_addl_T1_im(-4); | |
| 6520 | - gen_ldst(ldl, s); | |
| 6579 | + addr = load_reg(s, rn); | |
| 6580 | + if ((insn & (1 << 24)) == 0) | |
| 6581 | + tcg_gen_addi_i32(addr, addr, -8); | |
| 6582 | + /* Load PC into tmp and CPSR into tmp2. */ | |
| 6583 | + tmp = gen_ld32(addr, 0); | |
| 6584 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 6585 | + tmp2 = gen_ld32(addr, 0); | |
| 6521 | 6586 | if (insn & (1 << 21)) { |
| 6522 | 6587 | /* Base writeback. */ |
| 6523 | - if (insn & (1 << 24)) | |
| 6524 | - gen_op_addl_T1_im(8); | |
| 6525 | - gen_movl_reg_T1(s, rn); | |
| 6588 | + if (insn & (1 << 24)) { | |
| 6589 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 6590 | + } else { | |
| 6591 | + tcg_gen_addi_i32(addr, addr, -4); | |
| 6592 | + } | |
| 6593 | + store_reg(s, rn, addr); | |
| 6594 | + } else { | |
| 6595 | + dead_tmp(addr); | |
| 6526 | 6596 | } |
| 6527 | - gen_rfe(s); | |
| 6597 | + gen_rfe(s, tmp, tmp2); | |
| 6528 | 6598 | } else { |
| 6529 | 6599 | /* srs */ |
| 6530 | 6600 | op = (insn & 0x1f); |
| 6531 | 6601 | if (op == (env->uncached_cpsr & CPSR_M)) { |
| 6532 | - gen_movl_T1_reg(s, 13); | |
| 6602 | + addr = load_reg(s, 13); | |
| 6533 | 6603 | } else { |
| 6534 | - gen_op_movl_T1_r13_banked(op); | |
| 6604 | + addr = new_tmp(); | |
| 6605 | + gen_helper_get_r13_banked(addr, cpu_env, tcg_const_i32(op)); | |
| 6535 | 6606 | } |
| 6536 | 6607 | if ((insn & (1 << 24)) == 0) { |
| 6537 | - gen_op_addl_T1_im(-8); | |
| 6608 | + tcg_gen_addi_i32(addr, addr, -8); | |
| 6538 | 6609 | } |
| 6539 | - gen_movl_T0_reg(s, 14); | |
| 6540 | - gen_ldst(stl, s); | |
| 6541 | - gen_helper_cpsr_read(cpu_T[0]); | |
| 6542 | - gen_op_addl_T1_im(4); | |
| 6543 | - gen_ldst(stl, s); | |
| 6610 | + tmp = load_reg(s, 14); | |
| 6611 | + gen_st32(tmp, addr, 0); | |
| 6612 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 6613 | + tmp = new_tmp(); | |
| 6614 | + gen_helper_cpsr_read(tmp); | |
| 6615 | + gen_st32(tmp, addr, 0); | |
| 6544 | 6616 | if (insn & (1 << 21)) { |
| 6545 | 6617 | if ((insn & (1 << 24)) == 0) { |
| 6546 | - gen_op_addl_T1_im(-4); | |
| 6618 | + tcg_gen_addi_i32(addr, addr, -4); | |
| 6547 | 6619 | } else { |
| 6548 | - gen_op_addl_T1_im(4); | |
| 6620 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 6549 | 6621 | } |
| 6550 | 6622 | if (op == (env->uncached_cpsr & CPSR_M)) { |
| 6551 | - gen_movl_reg_T1(s, 13); | |
| 6623 | + store_reg(s, 13, addr); | |
| 6552 | 6624 | } else { |
| 6553 | - gen_op_movl_r13_T1_banked(op); | |
| 6625 | + gen_helper_set_r13_banked(cpu_env, | |
| 6626 | + tcg_const_i32(op), addr); | |
| 6554 | 6627 | } |
| 6628 | + } else { | |
| 6629 | + dead_tmp(addr); | |
| 6555 | 6630 | } |
| 6556 | 6631 | } |
| 6557 | 6632 | } else { |
| 6558 | 6633 | int i; |
| 6559 | 6634 | /* Load/store multiple. */ |
| 6560 | - gen_movl_T1_reg(s, rn); | |
| 6635 | + addr = load_reg(s, rn); | |
| 6561 | 6636 | offset = 0; |
| 6562 | 6637 | for (i = 0; i < 16; i++) { |
| 6563 | 6638 | if (insn & (1 << i)) |
| 6564 | 6639 | offset += 4; |
| 6565 | 6640 | } |
| 6566 | 6641 | if (insn & (1 << 24)) { |
| 6567 | - gen_op_addl_T1_im(-offset); | |
| 6642 | + tcg_gen_addi_i32(addr, addr, -offset); | |
| 6568 | 6643 | } |
| 6569 | 6644 | |
| 6570 | 6645 | for (i = 0; i < 16; i++) { |
| ... | ... | @@ -6572,28 +6647,30 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6572 | 6647 | continue; |
| 6573 | 6648 | if (insn & (1 << 20)) { |
| 6574 | 6649 | /* Load. */ |
| 6575 | - gen_ldst(ldl, s); | |
| 6650 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 6576 | 6651 | if (i == 15) { |
| 6577 | - gen_bx_T0(s); | |
| 6652 | + gen_bx(s, tmp); | |
| 6578 | 6653 | } else { |
| 6579 | - gen_movl_reg_T0(s, i); | |
| 6654 | + store_reg(s, i, tmp); | |
| 6580 | 6655 | } |
| 6581 | 6656 | } else { |
| 6582 | 6657 | /* Store. */ |
| 6583 | - gen_movl_T0_reg(s, i); | |
| 6584 | - gen_ldst(stl, s); | |
| 6658 | + tmp = load_reg(s, i); | |
| 6659 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 6585 | 6660 | } |
| 6586 | - gen_op_addl_T1_im(4); | |
| 6661 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 6587 | 6662 | } |
| 6588 | 6663 | if (insn & (1 << 21)) { |
| 6589 | 6664 | /* Base register writeback. */ |
| 6590 | 6665 | if (insn & (1 << 24)) { |
| 6591 | - gen_op_addl_T1_im(-offset); | |
| 6666 | + tcg_gen_addi_i32(addr, addr, -offset); | |
| 6592 | 6667 | } |
| 6593 | 6668 | /* Fault if writeback register is in register list. */ |
| 6594 | 6669 | if (insn & (1 << rn)) |
| 6595 | 6670 | goto illegal_op; |
| 6596 | - gen_movl_reg_T1(s, rn); | |
| 6671 | + store_reg(s, rn, addr); | |
| 6672 | + } else { | |
| 6673 | + dead_tmp(addr); | |
| 6597 | 6674 | } |
| 6598 | 6675 | } |
| 6599 | 6676 | } |
| ... | ... | @@ -6892,21 +6969,20 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 6892 | 6969 | offset ^= ((~insn) & (1 << 13)) << 10; |
| 6893 | 6970 | offset ^= ((~insn) & (1 << 11)) << 11; |
| 6894 | 6971 | |
| 6895 | - addr = s->pc; | |
| 6896 | 6972 | if (insn & (1 << 14)) { |
| 6897 | 6973 | /* Branch and link. */ |
| 6898 | - gen_op_movl_T1_im(addr | 1); | |
| 6974 | + gen_op_movl_T1_im(s->pc | 1); | |
| 6899 | 6975 | gen_movl_reg_T1(s, 14); |
| 6900 | 6976 | } |
| 6901 | 6977 | |
| 6902 | - addr += offset; | |
| 6978 | + offset += s->pc; | |
| 6903 | 6979 | if (insn & (1 << 12)) { |
| 6904 | 6980 | /* b/bl */ |
| 6905 | - gen_jmp(s, addr); | |
| 6981 | + gen_jmp(s, offset); | |
| 6906 | 6982 | } else { |
| 6907 | 6983 | /* blx */ |
| 6908 | - addr &= ~(uint32_t)2; | |
| 6909 | - gen_bx_im(s, addr); | |
| 6984 | + offset &= ~(uint32_t)2; | |
| 6985 | + gen_bx_im(s, offset); | |
| 6910 | 6986 | } |
| 6911 | 6987 | } else if (((insn >> 23) & 7) == 7) { |
| 6912 | 6988 | /* Misc control */ |
| ... | ... | @@ -7025,8 +7101,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 7025 | 7101 | offset |= (insn & (1 << 11)) << 8; |
| 7026 | 7102 | |
| 7027 | 7103 | /* jump to the offset */ |
| 7028 | - addr = s->pc + offset; | |
| 7029 | - gen_jmp(s, addr); | |
| 7104 | + gen_jmp(s, s->pc + offset); | |
| 7030 | 7105 | } |
| 7031 | 7106 | } else { |
| 7032 | 7107 | /* Data processing immediate. */ |
| ... | ... | @@ -7114,12 +7189,12 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 7114 | 7189 | } else { |
| 7115 | 7190 | /* Add/sub 12-bit immediate. */ |
| 7116 | 7191 | if (rn == 15) { |
| 7117 | - addr = s->pc & ~(uint32_t)3; | |
| 7192 | + offset = s->pc & ~(uint32_t)3; | |
| 7118 | 7193 | if (insn & (1 << 23)) |
| 7119 | - addr -= imm; | |
| 7194 | + offset -= imm; | |
| 7120 | 7195 | else |
| 7121 | - addr += imm; | |
| 7122 | - gen_op_movl_T0_im(addr); | |
| 7196 | + offset += imm; | |
| 7197 | + gen_op_movl_T0_im(offset); | |
| 7123 | 7198 | } else { |
| 7124 | 7199 | gen_movl_T0_reg(s, rn); |
| 7125 | 7200 | gen_op_movl_T1_im(imm); |
| ... | ... | @@ -7179,12 +7254,15 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 7179 | 7254 | { |
| 7180 | 7255 | int postinc = 0; |
| 7181 | 7256 | int writeback = 0; |
| 7257 | + int user; | |
| 7182 | 7258 | if ((insn & 0x01100000) == 0x01000000) { |
| 7183 | 7259 | if (disas_neon_ls_insn(env, s, insn)) |
| 7184 | 7260 | goto illegal_op; |
| 7185 | 7261 | break; |
| 7186 | 7262 | } |
| 7263 | + user = IS_USER(s); | |
| 7187 | 7264 | if (rn == 15) { |
| 7265 | + addr = new_tmp(); | |
| 7188 | 7266 | /* PC relative. */ |
| 7189 | 7267 | /* s->pc has already been incremented by 4. */ |
| 7190 | 7268 | imm = s->pc & 0xfffffffc; |
| ... | ... | @@ -7192,13 +7270,13 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 7192 | 7270 | imm += insn & 0xfff; |
| 7193 | 7271 | else |
| 7194 | 7272 | imm -= insn & 0xfff; |
| 7195 | - gen_op_movl_T1_im(imm); | |
| 7273 | + tcg_gen_movi_i32(addr, imm); | |
| 7196 | 7274 | } else { |
| 7197 | - gen_movl_T1_reg(s, rn); | |
| 7275 | + addr = load_reg(s, rn); | |
| 7198 | 7276 | if (insn & (1 << 23)) { |
| 7199 | 7277 | /* Positive offset. */ |
| 7200 | 7278 | imm = insn & 0xfff; |
| 7201 | - gen_op_addl_T1_im(imm); | |
| 7279 | + tcg_gen_addi_i32(addr, addr, imm); | |
| 7202 | 7280 | } else { |
| 7203 | 7281 | op = (insn >> 8) & 7; |
| 7204 | 7282 | imm = insn & 0xff; |
| ... | ... | @@ -7210,14 +7288,15 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 7210 | 7288 | tmp = load_reg(s, rm); |
| 7211 | 7289 | if (shift) |
| 7212 | 7290 | tcg_gen_shli_i32(tmp, tmp, shift); |
| 7213 | - tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp); | |
| 7291 | + tcg_gen_add_i32(addr, addr, tmp); | |
| 7214 | 7292 | dead_tmp(tmp); |
| 7215 | 7293 | break; |
| 7216 | 7294 | case 4: /* Negative offset. */ |
| 7217 | - gen_op_addl_T1_im(-imm); | |
| 7295 | + tcg_gen_addi_i32(addr, addr, -imm); | |
| 7218 | 7296 | break; |
| 7219 | 7297 | case 6: /* User privilege. */ |
| 7220 | - gen_op_addl_T1_im(imm); | |
| 7298 | + tcg_gen_addi_i32(addr, addr, imm); | |
| 7299 | + user = 1; | |
| 7221 | 7300 | break; |
| 7222 | 7301 | case 1: /* Post-decrement. */ |
| 7223 | 7302 | imm = -imm; |
| ... | ... | @@ -7230,7 +7309,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 7230 | 7309 | imm = -imm; |
| 7231 | 7310 | /* Fall through. */ |
| 7232 | 7311 | case 7: /* Pre-increment. */ |
| 7233 | - gen_op_addl_T1_im(imm); | |
| 7312 | + tcg_gen_addi_i32(addr, addr, imm); | |
| 7234 | 7313 | writeback = 1; |
| 7235 | 7314 | break; |
| 7236 | 7315 | default: |
| ... | ... | @@ -7247,35 +7326,38 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) |
| 7247 | 7326 | /* Memory hint. Implemented as NOP. */ |
| 7248 | 7327 | } else { |
| 7249 | 7328 | switch (op) { |
| 7250 | - case 0: gen_ldst(ldub, s); break; | |
| 7251 | - case 4: gen_ldst(ldsb, s); break; | |
| 7252 | - case 1: gen_ldst(lduw, s); break; | |
| 7253 | - case 5: gen_ldst(ldsw, s); break; | |
| 7254 | - case 2: gen_ldst(ldl, s); break; | |
| 7329 | + case 0: tmp = gen_ld8u(addr, user); break; | |
| 7330 | + case 4: tmp = gen_ld8s(addr, user); break; | |
| 7331 | + case 1: tmp = gen_ld16u(addr, user); break; | |
| 7332 | + case 5: tmp = gen_ld16s(addr, user); break; | |
| 7333 | + case 2: tmp = gen_ld32(addr, user); break; | |
| 7255 | 7334 | default: goto illegal_op; |
| 7256 | 7335 | } |
| 7257 | 7336 | if (rs == 15) { |
| 7258 | - gen_bx_T0(s); | |
| 7337 | + gen_bx(s, tmp); | |
| 7259 | 7338 | } else { |
| 7260 | - gen_movl_reg_T0(s, rs); | |
| 7339 | + store_reg(s, rs, tmp); | |
| 7261 | 7340 | } |
| 7262 | 7341 | } |
| 7263 | 7342 | } else { |
| 7264 | 7343 | /* Store. */ |
| 7265 | 7344 | if (rs == 15) |
| 7266 | 7345 | goto illegal_op; |
| 7267 | - gen_movl_T0_reg(s, rs); | |
| 7346 | + tmp = load_reg(s, rs); | |
| 7268 | 7347 | switch (op) { |
| 7269 | - case 0: gen_ldst(stb, s); break; | |
| 7270 | - case 1: gen_ldst(stw, s); break; | |
| 7271 | - case 2: gen_ldst(stl, s); break; | |
| 7348 | + case 0: gen_st8(tmp, addr, user); break; | |
| 7349 | + case 1: gen_st16(tmp, addr, user); break; | |
| 7350 | + case 2: gen_st32(tmp, addr, user); break; | |
| 7272 | 7351 | default: goto illegal_op; |
| 7273 | 7352 | } |
| 7274 | 7353 | } |
| 7275 | 7354 | if (postinc) |
| 7276 | - gen_op_addl_T1_im(imm); | |
| 7277 | - if (writeback) | |
| 7278 | - gen_movl_reg_T1(s, rn); | |
| 7355 | + tcg_gen_addi_i32(addr, addr, imm); | |
| 7356 | + if (writeback) { | |
| 7357 | + store_reg(s, rn, addr); | |
| 7358 | + } else { | |
| 7359 | + dead_tmp(addr); | |
| 7360 | + } | |
| 7279 | 7361 | } |
| 7280 | 7362 | break; |
| 7281 | 7363 | default: |
| ... | ... | @@ -7293,6 +7375,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) |
| 7293 | 7375 | int i; |
| 7294 | 7376 | TCGv tmp; |
| 7295 | 7377 | TCGv tmp2; |
| 7378 | + TCGv addr; | |
| 7296 | 7379 | |
| 7297 | 7380 | if (s->condexec_mask) { |
| 7298 | 7381 | cond = s->condexec_cond; |
| ... | ... | @@ -7383,9 +7466,11 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) |
| 7383 | 7466 | /* load pc-relative. Bit 1 of PC is ignored. */ |
| 7384 | 7467 | val = s->pc + 2 + ((insn & 0xff) * 4); |
| 7385 | 7468 | val &= ~(uint32_t)2; |
| 7386 | - gen_op_movl_T1_im(val); | |
| 7387 | - gen_ldst(ldl, s); | |
| 7388 | - gen_movl_reg_T0(s, rd); | |
| 7469 | + addr = new_tmp(); | |
| 7470 | + tcg_gen_movi_i32(addr, val); | |
| 7471 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 7472 | + dead_tmp(addr); | |
| 7473 | + store_reg(s, rd, tmp); | |
| 7389 | 7474 | break; |
| 7390 | 7475 | } |
| 7391 | 7476 | if (insn & (1 << 10)) { |
| ... | ... | @@ -7410,12 +7495,13 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) |
| 7410 | 7495 | gen_movl_reg_T0(s, rd); |
| 7411 | 7496 | break; |
| 7412 | 7497 | case 3:/* branch [and link] exchange thumb register */ |
| 7498 | + tmp = load_reg(s, rm); | |
| 7413 | 7499 | if (insn & (1 << 7)) { |
| 7414 | 7500 | val = (uint32_t)s->pc | 1; |
| 7415 | - gen_op_movl_T1_im(val); | |
| 7416 | - gen_movl_reg_T1(s, 14); | |
| 7501 | + tmp2 = new_tmp(); | |
| 7502 | + tcg_gen_movi_i32(tmp2, val); | |
| 7503 | + store_reg(s, 14, tmp2); | |
| 7417 | 7504 | } |
| 7418 | - tmp = load_reg(s, rm); | |
| 7419 | 7505 | gen_bx(s, tmp); |
| 7420 | 7506 | break; |
| 7421 | 7507 | } |
| ... | ... | @@ -7553,117 +7639,122 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) |
| 7553 | 7639 | rn = (insn >> 3) & 7; |
| 7554 | 7640 | rm = (insn >> 6) & 7; |
| 7555 | 7641 | op = (insn >> 9) & 7; |
| 7556 | - gen_movl_T1_reg(s, rn); | |
| 7642 | + addr = load_reg(s, rn); | |
| 7557 | 7643 | tmp = load_reg(s, rm); |
| 7558 | - tcg_gen_add_i32(cpu_T[1], cpu_T[1], tmp); | |
| 7644 | + tcg_gen_add_i32(addr, addr, tmp); | |
| 7559 | 7645 | dead_tmp(tmp); |
| 7560 | 7646 | |
| 7561 | 7647 | if (op < 3) /* store */ |
| 7562 | - gen_movl_T0_reg(s, rd); | |
| 7648 | + tmp = load_reg(s, rd); | |
| 7563 | 7649 | |
| 7564 | 7650 | switch (op) { |
| 7565 | 7651 | case 0: /* str */ |
| 7566 | - gen_ldst(stl, s); | |
| 7652 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 7567 | 7653 | break; |
| 7568 | 7654 | case 1: /* strh */ |
| 7569 | - gen_ldst(stw, s); | |
| 7655 | + gen_st16(tmp, addr, IS_USER(s)); | |
| 7570 | 7656 | break; |
| 7571 | 7657 | case 2: /* strb */ |
| 7572 | - gen_ldst(stb, s); | |
| 7658 | + gen_st8(tmp, addr, IS_USER(s)); | |
| 7573 | 7659 | break; |
| 7574 | 7660 | case 3: /* ldrsb */ |
| 7575 | - gen_ldst(ldsb, s); | |
| 7661 | + tmp = gen_ld8s(addr, IS_USER(s)); | |
| 7576 | 7662 | break; |
| 7577 | 7663 | case 4: /* ldr */ |
| 7578 | - gen_ldst(ldl, s); | |
| 7664 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 7579 | 7665 | break; |
| 7580 | 7666 | case 5: /* ldrh */ |
| 7581 | - gen_ldst(lduw, s); | |
| 7667 | + tmp = gen_ld16u(addr, IS_USER(s)); | |
| 7582 | 7668 | break; |
| 7583 | 7669 | case 6: /* ldrb */ |
| 7584 | - gen_ldst(ldub, s); | |
| 7670 | + tmp = gen_ld8u(addr, IS_USER(s)); | |
| 7585 | 7671 | break; |
| 7586 | 7672 | case 7: /* ldrsh */ |
| 7587 | - gen_ldst(ldsw, s); | |
| 7673 | + tmp = gen_ld16s(addr, IS_USER(s)); | |
| 7588 | 7674 | break; |
| 7589 | 7675 | } |
| 7590 | 7676 | if (op >= 3) /* load */ |
| 7591 | - gen_movl_reg_T0(s, rd); | |
| 7677 | + store_reg(s, rd, tmp); | |
| 7678 | + dead_tmp(addr); | |
| 7592 | 7679 | break; |
| 7593 | 7680 | |
| 7594 | 7681 | case 6: |
| 7595 | 7682 | /* load/store word immediate offset */ |
| 7596 | 7683 | rd = insn & 7; |
| 7597 | 7684 | rn = (insn >> 3) & 7; |
| 7598 | - gen_movl_T1_reg(s, rn); | |
| 7685 | + addr = load_reg(s, rn); | |
| 7599 | 7686 | val = (insn >> 4) & 0x7c; |
| 7600 | - tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val); | |
| 7687 | + tcg_gen_addi_i32(addr, addr, val); | |
| 7601 | 7688 | |
| 7602 | 7689 | if (insn & (1 << 11)) { |
| 7603 | 7690 | /* load */ |
| 7604 | - gen_ldst(ldl, s); | |
| 7605 | - gen_movl_reg_T0(s, rd); | |
| 7691 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 7692 | + store_reg(s, rd, tmp); | |
| 7606 | 7693 | } else { |
| 7607 | 7694 | /* store */ |
| 7608 | - gen_movl_T0_reg(s, rd); | |
| 7609 | - gen_ldst(stl, s); | |
| 7695 | + tmp = load_reg(s, rd); | |
| 7696 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 7610 | 7697 | } |
| 7698 | + dead_tmp(addr); | |
| 7611 | 7699 | break; |
| 7612 | 7700 | |
| 7613 | 7701 | case 7: |
| 7614 | 7702 | /* load/store byte immediate offset */ |
| 7615 | 7703 | rd = insn & 7; |
| 7616 | 7704 | rn = (insn >> 3) & 7; |
| 7617 | - gen_movl_T1_reg(s, rn); | |
| 7705 | + addr = load_reg(s, rn); | |
| 7618 | 7706 | val = (insn >> 6) & 0x1f; |
| 7619 | - tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val); | |
| 7707 | + tcg_gen_addi_i32(addr, addr, val); | |
| 7620 | 7708 | |
| 7621 | 7709 | if (insn & (1 << 11)) { |
| 7622 | 7710 | /* load */ |
| 7623 | - gen_ldst(ldub, s); | |
| 7624 | - gen_movl_reg_T0(s, rd); | |
| 7711 | + tmp = gen_ld8u(addr, IS_USER(s)); | |
| 7712 | + store_reg(s, rd, tmp); | |
| 7625 | 7713 | } else { |
| 7626 | 7714 | /* store */ |
| 7627 | - gen_movl_T0_reg(s, rd); | |
| 7628 | - gen_ldst(stb, s); | |
| 7715 | + tmp = load_reg(s, rd); | |
| 7716 | + gen_st8(tmp, addr, IS_USER(s)); | |
| 7629 | 7717 | } |
| 7718 | + dead_tmp(addr); | |
| 7630 | 7719 | break; |
| 7631 | 7720 | |
| 7632 | 7721 | case 8: |
| 7633 | 7722 | /* load/store halfword immediate offset */ |
| 7634 | 7723 | rd = insn & 7; |
| 7635 | 7724 | rn = (insn >> 3) & 7; |
| 7636 | - gen_movl_T1_reg(s, rn); | |
| 7725 | + addr = load_reg(s, rn); | |
| 7637 | 7726 | val = (insn >> 5) & 0x3e; |
| 7638 | - tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val); | |
| 7727 | + tcg_gen_addi_i32(addr, addr, val); | |
| 7639 | 7728 | |
| 7640 | 7729 | if (insn & (1 << 11)) { |
| 7641 | 7730 | /* load */ |
| 7642 | - gen_ldst(lduw, s); | |
| 7643 | - gen_movl_reg_T0(s, rd); | |
| 7731 | + tmp = gen_ld16u(addr, IS_USER(s)); | |
| 7732 | + store_reg(s, rd, tmp); | |
| 7644 | 7733 | } else { |
| 7645 | 7734 | /* store */ |
| 7646 | - gen_movl_T0_reg(s, rd); | |
| 7647 | - gen_ldst(stw, s); | |
| 7735 | + tmp = load_reg(s, rd); | |
| 7736 | + gen_st16(tmp, addr, IS_USER(s)); | |
| 7648 | 7737 | } |
| 7738 | + dead_tmp(addr); | |
| 7649 | 7739 | break; |
| 7650 | 7740 | |
| 7651 | 7741 | case 9: |
| 7652 | 7742 | /* load/store from stack */ |
| 7653 | 7743 | rd = (insn >> 8) & 7; |
| 7654 | - gen_movl_T1_reg(s, 13); | |
| 7744 | + addr = load_reg(s, 13); | |
| 7655 | 7745 | val = (insn & 0xff) * 4; |
| 7656 | - tcg_gen_addi_i32(cpu_T[1], cpu_T[1], val); | |
| 7746 | + tcg_gen_addi_i32(addr, addr, val); | |
| 7657 | 7747 | |
| 7658 | 7748 | if (insn & (1 << 11)) { |
| 7659 | 7749 | /* load */ |
| 7660 | - gen_ldst(ldl, s); | |
| 7661 | - gen_movl_reg_T0(s, rd); | |
| 7750 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 7751 | + store_reg(s, rd, tmp); | |
| 7662 | 7752 | } else { |
| 7663 | 7753 | /* store */ |
| 7664 | - gen_movl_T0_reg(s, rd); | |
| 7665 | - gen_ldst(stl, s); | |
| 7754 | + tmp = load_reg(s, rd); | |
| 7755 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 7666 | 7756 | } |
| 7757 | + dead_tmp(addr); | |
| 7667 | 7758 | break; |
| 7668 | 7759 | |
| 7669 | 7760 | case 10: |
| ... | ... | @@ -7700,18 +7791,18 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) |
| 7700 | 7791 | ARCH(6); |
| 7701 | 7792 | rd = insn & 7; |
| 7702 | 7793 | rm = (insn >> 3) & 7; |
| 7703 | - gen_movl_T1_reg(s, rm); | |
| 7794 | + tmp = load_reg(s, rm); | |
| 7704 | 7795 | switch ((insn >> 6) & 3) { |
| 7705 | - case 0: gen_sxth(cpu_T[1]); break; | |
| 7706 | - case 1: gen_sxtb(cpu_T[1]); break; | |
| 7707 | - case 2: gen_uxth(cpu_T[1]); break; | |
| 7708 | - case 3: gen_uxtb(cpu_T[1]); break; | |
| 7796 | + case 0: gen_sxth(tmp); break; | |
| 7797 | + case 1: gen_sxtb(tmp); break; | |
| 7798 | + case 2: gen_uxth(tmp); break; | |
| 7799 | + case 3: gen_uxtb(tmp); break; | |
| 7709 | 7800 | } |
| 7710 | - gen_movl_reg_T1(s, rd); | |
| 7801 | + store_reg(s, rd, tmp); | |
| 7711 | 7802 | break; |
| 7712 | 7803 | case 4: case 5: case 0xc: case 0xd: |
| 7713 | 7804 | /* push/pop */ |
| 7714 | - gen_movl_T1_reg(s, 13); | |
| 7805 | + addr = load_reg(s, 13); | |
| 7715 | 7806 | if (insn & (1 << 8)) |
| 7716 | 7807 | offset = 4; |
| 7717 | 7808 | else |
| ... | ... | @@ -7721,44 +7812,44 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) |
| 7721 | 7812 | offset += 4; |
| 7722 | 7813 | } |
| 7723 | 7814 | if ((insn & (1 << 11)) == 0) { |
| 7724 | - gen_op_addl_T1_im(-offset); | |
| 7815 | + tcg_gen_addi_i32(addr, addr, -offset); | |
| 7725 | 7816 | } |
| 7726 | 7817 | for (i = 0; i < 8; i++) { |
| 7727 | 7818 | if (insn & (1 << i)) { |
| 7728 | 7819 | if (insn & (1 << 11)) { |
| 7729 | 7820 | /* pop */ |
| 7730 | - gen_ldst(ldl, s); | |
| 7731 | - gen_movl_reg_T0(s, i); | |
| 7821 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 7822 | + store_reg(s, i, tmp); | |
| 7732 | 7823 | } else { |
| 7733 | 7824 | /* push */ |
| 7734 | - gen_movl_T0_reg(s, i); | |
| 7735 | - gen_ldst(stl, s); | |
| 7825 | + tmp = load_reg(s, i); | |
| 7826 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 7736 | 7827 | } |
| 7737 | 7828 | /* advance to the next address. */ |
| 7738 | - gen_op_addl_T1_im(4); | |
| 7829 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 7739 | 7830 | } |
| 7740 | 7831 | } |
| 7741 | 7832 | if (insn & (1 << 8)) { |
| 7742 | 7833 | if (insn & (1 << 11)) { |
| 7743 | 7834 | /* pop pc */ |
| 7744 | - gen_ldst(ldl, s); | |
| 7835 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 7745 | 7836 | /* don't set the pc until the rest of the instruction |
| 7746 | 7837 | has completed */ |
| 7747 | 7838 | } else { |
| 7748 | 7839 | /* push lr */ |
| 7749 | - gen_movl_T0_reg(s, 14); | |
| 7750 | - gen_ldst(stl, s); | |
| 7840 | + tmp = load_reg(s, 14); | |
| 7841 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 7751 | 7842 | } |
| 7752 | - gen_op_addl_T1_im(4); | |
| 7843 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 7753 | 7844 | } |
| 7754 | 7845 | if ((insn & (1 << 11)) == 0) { |
| 7755 | - gen_op_addl_T1_im(-offset); | |
| 7846 | + tcg_gen_addi_i32(addr, addr, -offset); | |
| 7756 | 7847 | } |
| 7757 | 7848 | /* write back the new stack pointer */ |
| 7758 | - gen_movl_reg_T1(s, 13); | |
| 7849 | + store_reg(s, 13, addr); | |
| 7759 | 7850 | /* set the new PC value */ |
| 7760 | 7851 | if ((insn & 0x0900) == 0x0900) |
| 7761 | - gen_bx_T0(s); | |
| 7852 | + gen_bx(s, tmp); | |
| 7762 | 7853 | break; |
| 7763 | 7854 | |
| 7764 | 7855 | case 1: case 3: case 9: case 11: /* czb */ |
| ... | ... | @@ -7801,14 +7892,14 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) |
| 7801 | 7892 | ARCH(6); |
| 7802 | 7893 | rn = (insn >> 3) & 0x7; |
| 7803 | 7894 | rd = insn & 0x7; |
| 7804 | - gen_movl_T0_reg(s, rn); | |
| 7895 | + tmp = load_reg(s, rn); | |
| 7805 | 7896 | switch ((insn >> 6) & 3) { |
| 7806 | - case 0: gen_op_rev_T0(); break; | |
| 7807 | - case 1: gen_rev16(cpu_T[0]); break; | |
| 7808 | - case 3: gen_revsh(cpu_T[0]); break; | |
| 7897 | + case 0: tcg_gen_bswap_i32(tmp, tmp); break; | |
| 7898 | + case 1: gen_rev16(tmp); break; | |
| 7899 | + case 3: gen_revsh(tmp); break; | |
| 7809 | 7900 | default: goto illegal_op; |
| 7810 | 7901 | } |
| 7811 | - gen_movl_reg_T0(s, rd); | |
| 7902 | + store_reg(s, rd, tmp); | |
| 7812 | 7903 | break; |
| 7813 | 7904 | |
| 7814 | 7905 | case 6: /* cps */ |
| ... | ... | @@ -7846,25 +7937,28 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) |
| 7846 | 7937 | case 12: |
| 7847 | 7938 | /* load/store multiple */ |
| 7848 | 7939 | rn = (insn >> 8) & 0x7; |
| 7849 | - gen_movl_T1_reg(s, rn); | |
| 7940 | + addr = load_reg(s, rn); | |
| 7850 | 7941 | for (i = 0; i < 8; i++) { |
| 7851 | 7942 | if (insn & (1 << i)) { |
| 7852 | 7943 | if (insn & (1 << 11)) { |
| 7853 | 7944 | /* load */ |
| 7854 | - gen_ldst(ldl, s); | |
| 7855 | - gen_movl_reg_T0(s, i); | |
| 7945 | + tmp = gen_ld32(addr, IS_USER(s)); | |
| 7946 | + store_reg(s, i, tmp); | |
| 7856 | 7947 | } else { |
| 7857 | 7948 | /* store */ |
| 7858 | - gen_movl_T0_reg(s, i); | |
| 7859 | - gen_ldst(stl, s); | |
| 7949 | + tmp = load_reg(s, i); | |
| 7950 | + gen_st32(tmp, addr, IS_USER(s)); | |
| 7860 | 7951 | } |
| 7861 | 7952 | /* advance to the next address */ |
| 7862 | - gen_op_addl_T1_im(4); | |
| 7953 | + tcg_gen_addi_i32(addr, addr, 4); | |
| 7863 | 7954 | } |
| 7864 | 7955 | } |
| 7865 | 7956 | /* Base register writeback. */ |
| 7866 | - if ((insn & (1 << rn)) == 0) | |
| 7867 | - gen_movl_reg_T1(s, rn); | |
| 7957 | + if ((insn & (1 << rn)) == 0) { | |
| 7958 | + store_reg(s, rn, addr); | |
| 7959 | + } else { | |
| 7960 | + dead_tmp(addr); | |
| 7961 | + } | |
| 7868 | 7962 | break; |
| 7869 | 7963 | |
| 7870 | 7964 | case 13: | ... | ... |
tcg/tcg-op.h
| ... | ... | @@ -199,6 +199,18 @@ static inline void tcg_gen_helper_0_2(void *func, TCGv arg1, TCGv arg2) |
| 199 | 199 | 0, NULL, 2, args); |
| 200 | 200 | } |
| 201 | 201 | |
| 202 | +static inline void tcg_gen_helper_0_3(void *func, | |
| 203 | + TCGv arg1, TCGv arg2, TCGv arg3) | |
| 204 | +{ | |
| 205 | + TCGv args[3]; | |
| 206 | + args[0] = arg1; | |
| 207 | + args[1] = arg2; | |
| 208 | + args[2] = arg3; | |
| 209 | + tcg_gen_call(&tcg_ctx, | |
| 210 | + tcg_const_ptr((tcg_target_long)func), TCG_HELPER_CALL_FLAGS, | |
| 211 | + 0, NULL, 3, args); | |
| 212 | +} | |
| 213 | + | |
| 202 | 214 | static inline void tcg_gen_helper_0_4(void *func, TCGv arg1, TCGv arg2, |
| 203 | 215 | TCGv arg3, TCGv arg4) |
| 204 | 216 | { | ... | ... |