Revision b0109805 target-arm/translate.c
b/target-arm/translate.c | ||
---|---|---|
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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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 | 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); |
Also available in: Unified diff