Revision d9ba4830 target-arm/translate.c
b/target-arm/translate.c | ||
---|---|---|
130 | 130 |
temps[i] = tmp; |
131 | 131 |
} |
132 | 132 |
|
133 |
static inline TCGv load_cpu_offset(int offset) |
|
134 |
{ |
|
135 |
TCGv tmp = new_tmp(); |
|
136 |
tcg_gen_ld_i32(tmp, cpu_env, offset); |
|
137 |
return tmp; |
|
138 |
} |
|
139 |
|
|
140 |
#define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name)) |
|
141 |
|
|
142 |
static inline void store_cpu_offset(TCGv var, int offset) |
|
143 |
{ |
|
144 |
tcg_gen_st_i32(var, cpu_env, offset); |
|
145 |
dead_tmp(var); |
|
146 |
} |
|
147 |
|
|
148 |
#define store_cpu_field(var, name) \ |
|
149 |
store_cpu_offset(var, offsetof(CPUState, name)) |
|
150 |
|
|
133 | 151 |
/* Set a variable to the value of a CPU register. */ |
134 | 152 |
static void load_reg_var(DisasContext *s, TCGv var, int reg) |
135 | 153 |
{ |
... | ... | |
222 | 240 |
/* Copy the most significant bit of T0 to all bits of T1. */ |
223 | 241 |
#define gen_op_signbit_T1_T0() tcg_gen_sari_i32(cpu_T[1], cpu_T[0], 31) |
224 | 242 |
|
243 |
#define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask)) |
|
244 |
/* Set NZCV flags from the high 4 bits of var. */ |
|
245 |
#define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV) |
|
246 |
|
|
247 |
static void gen_exception(int excp) |
|
248 |
{ |
|
249 |
TCGv tmp = new_tmp(); |
|
250 |
tcg_gen_movi_i32(tmp, excp); |
|
251 |
gen_helper_exception(tmp); |
|
252 |
dead_tmp(tmp); |
|
253 |
} |
|
254 |
|
|
225 | 255 |
static void gen_smul_dual(TCGv a, TCGv b) |
226 | 256 |
{ |
227 | 257 |
TCGv tmp1 = new_tmp(); |
... | ... | |
293 | 323 |
tcg_gen_or_i32(dest, base, val); |
294 | 324 |
} |
295 | 325 |
|
296 |
static void gen_op_roundqd_T0_T1(void) |
|
326 |
/* Round the top 32 bits of a 64-bit value. */ |
|
327 |
static void gen_roundqd(TCGv a, TCGv b) |
|
297 | 328 |
{ |
298 |
tcg_gen_shri_i32(cpu_T[0], cpu_T[0], 31);
|
|
299 |
tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1]);
|
|
329 |
tcg_gen_shri_i32(a, a, 31);
|
|
330 |
tcg_gen_add_i32(a, a, b);
|
|
300 | 331 |
} |
301 | 332 |
|
302 | 333 |
/* FIXME: Most targets have native widening multiplication. |
... | ... | |
316 | 347 |
} |
317 | 348 |
|
318 | 349 |
/* Signed 32x32->64 multiply. */ |
319 |
static void gen_op_imull_T0_T1(void)
|
|
350 |
static void gen_imull(TCGv a, TCGv b)
|
|
320 | 351 |
{ |
321 | 352 |
TCGv tmp1 = tcg_temp_new(TCG_TYPE_I64); |
322 | 353 |
TCGv tmp2 = tcg_temp_new(TCG_TYPE_I64); |
323 | 354 |
|
324 |
tcg_gen_ext_i32_i64(tmp1, cpu_T[0]);
|
|
325 |
tcg_gen_ext_i32_i64(tmp2, cpu_T[1]);
|
|
355 |
tcg_gen_ext_i32_i64(tmp1, a);
|
|
356 |
tcg_gen_ext_i32_i64(tmp2, b);
|
|
326 | 357 |
tcg_gen_mul_i64(tmp1, tmp1, tmp2); |
327 |
tcg_gen_trunc_i64_i32(cpu_T[0], tmp1);
|
|
358 |
tcg_gen_trunc_i64_i32(a, tmp1);
|
|
328 | 359 |
tcg_gen_shri_i64(tmp1, tmp1, 32); |
329 |
tcg_gen_trunc_i64_i32(cpu_T[1], tmp1); |
|
360 |
tcg_gen_trunc_i64_i32(b, tmp1); |
|
361 |
} |
|
362 |
#define gen_op_imull_T0_T1() gen_imull(cpu_T[0], cpu_T[1]) |
|
363 |
|
|
364 |
/* Signed 32x16 multiply, top 32 bits. */ |
|
365 |
static void gen_imulw(TCGv a, TCGv b) |
|
366 |
{ |
|
367 |
gen_imull(a, b); |
|
368 |
tcg_gen_shri_i32(a, a, 16); |
|
369 |
tcg_gen_shli_i32(b, b, 16); |
|
370 |
tcg_gen_or_i32(a, a, b); |
|
330 | 371 |
} |
331 | 372 |
|
332 | 373 |
/* Swap low and high halfwords. */ |
... | ... | |
379 | 420 |
/* T0 += T1 + CF. */ |
380 | 421 |
static void gen_adc_T0_T1(void) |
381 | 422 |
{ |
382 |
TCGv tmp = new_tmp();
|
|
423 |
TCGv tmp; |
|
383 | 424 |
gen_op_addl_T0_T1(); |
384 |
tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF));
|
|
425 |
tmp = load_cpu_field(CF);
|
|
385 | 426 |
tcg_gen_add_i32(cpu_T[0], cpu_T[0], tmp); |
386 | 427 |
dead_tmp(tmp); |
387 | 428 |
} |
... | ... | |
389 | 430 |
/* dest = T0 - T1 + CF - 1. */ |
390 | 431 |
static void gen_sub_carry(TCGv dest, TCGv t0, TCGv t1) |
391 | 432 |
{ |
392 |
TCGv tmp = new_tmp();
|
|
433 |
TCGv tmp; |
|
393 | 434 |
tcg_gen_sub_i32(dest, t0, t1); |
394 |
tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF));
|
|
435 |
tmp = load_cpu_field(CF);
|
|
395 | 436 |
tcg_gen_add_i32(dest, dest, tmp); |
396 | 437 |
tcg_gen_subi_i32(dest, dest, 1); |
397 | 438 |
dead_tmp(tmp); |
... | ... | |
482 | 523 |
shifter_out_im(var, shift - 1); |
483 | 524 |
tcg_gen_rori_i32(var, var, shift); break; |
484 | 525 |
} else { |
485 |
TCGv tmp = new_tmp(); |
|
486 |
tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUState, CF)); |
|
526 |
TCGv tmp = load_cpu_field(CF); |
|
487 | 527 |
if (flags) |
488 | 528 |
shifter_out_im(var, 0); |
489 | 529 |
tcg_gen_shri_i32(var, var, 1); |
... | ... | |
503 | 543 |
case 4: gen_pas_helper(glue(pfx,add8)); break; \ |
504 | 544 |
case 7: gen_pas_helper(glue(pfx,sub8)); break; \ |
505 | 545 |
} |
506 |
void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b) |
|
546 |
static void gen_arm_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
|
|
507 | 547 |
{ |
508 | 548 |
TCGv tmp; |
509 | 549 |
|
... | ... | |
548 | 588 |
case 5: gen_pas_helper(glue(pfx,sub16)); break; \ |
549 | 589 |
case 6: gen_pas_helper(glue(pfx,subaddx)); break; \ |
550 | 590 |
} |
551 |
void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b) |
|
591 |
static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv a, TCGv b)
|
|
552 | 592 |
{ |
553 | 593 |
TCGv tmp; |
554 | 594 |
|
... | ... | |
583 | 623 |
} |
584 | 624 |
#undef PAS_OP |
585 | 625 |
|
586 |
static GenOpFunc1 *gen_test_cc[14] = { |
|
587 |
gen_op_test_eq, |
|
588 |
gen_op_test_ne, |
|
589 |
gen_op_test_cs, |
|
590 |
gen_op_test_cc, |
|
591 |
gen_op_test_mi, |
|
592 |
gen_op_test_pl, |
|
593 |
gen_op_test_vs, |
|
594 |
gen_op_test_vc, |
|
595 |
gen_op_test_hi, |
|
596 |
gen_op_test_ls, |
|
597 |
gen_op_test_ge, |
|
598 |
gen_op_test_lt, |
|
599 |
gen_op_test_gt, |
|
600 |
gen_op_test_le, |
|
601 |
}; |
|
626 |
static void gen_test_cc(int cc, int label) |
|
627 |
{ |
|
628 |
TCGv tmp; |
|
629 |
TCGv tmp2; |
|
630 |
TCGv zero; |
|
631 |
int inv; |
|
632 |
|
|
633 |
zero = tcg_const_i32(0); |
|
634 |
switch (cc) { |
|
635 |
case 0: /* eq: Z */ |
|
636 |
tmp = load_cpu_field(NZF); |
|
637 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
|
638 |
break; |
|
639 |
case 1: /* ne: !Z */ |
|
640 |
tmp = load_cpu_field(NZF); |
|
641 |
tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label); |
|
642 |
break; |
|
643 |
case 2: /* cs: C */ |
|
644 |
tmp = load_cpu_field(CF); |
|
645 |
tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label); |
|
646 |
break; |
|
647 |
case 3: /* cc: !C */ |
|
648 |
tmp = load_cpu_field(CF); |
|
649 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
|
650 |
break; |
|
651 |
case 4: /* mi: N */ |
|
652 |
tmp = load_cpu_field(NZF); |
|
653 |
tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); |
|
654 |
break; |
|
655 |
case 5: /* pl: !N */ |
|
656 |
tmp = load_cpu_field(NZF); |
|
657 |
tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); |
|
658 |
break; |
|
659 |
case 6: /* vs: V */ |
|
660 |
tmp = load_cpu_field(VF); |
|
661 |
tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); |
|
662 |
break; |
|
663 |
case 7: /* vc: !V */ |
|
664 |
tmp = load_cpu_field(VF); |
|
665 |
tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); |
|
666 |
break; |
|
667 |
case 8: /* hi: C && !Z */ |
|
668 |
inv = gen_new_label(); |
|
669 |
tmp = load_cpu_field(CF); |
|
670 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv); |
|
671 |
dead_tmp(tmp); |
|
672 |
tmp = load_cpu_field(NZF); |
|
673 |
tcg_gen_brcond_i32(TCG_COND_NE, tmp, zero, label); |
|
674 |
gen_set_label(inv); |
|
675 |
break; |
|
676 |
case 9: /* ls: !C || Z */ |
|
677 |
tmp = load_cpu_field(CF); |
|
678 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
|
679 |
dead_tmp(tmp); |
|
680 |
tmp = load_cpu_field(NZF); |
|
681 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
|
682 |
break; |
|
683 |
case 10: /* ge: N == V -> N ^ V == 0 */ |
|
684 |
tmp = load_cpu_field(VF); |
|
685 |
tmp2 = load_cpu_field(NZF); |
|
686 |
tcg_gen_xor_i32(tmp, tmp, tmp2); |
|
687 |
dead_tmp(tmp2); |
|
688 |
tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); |
|
689 |
break; |
|
690 |
case 11: /* lt: N != V -> N ^ V != 0 */ |
|
691 |
tmp = load_cpu_field(VF); |
|
692 |
tmp2 = load_cpu_field(NZF); |
|
693 |
tcg_gen_xor_i32(tmp, tmp, tmp2); |
|
694 |
dead_tmp(tmp2); |
|
695 |
tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); |
|
696 |
break; |
|
697 |
case 12: /* gt: !Z && N == V */ |
|
698 |
inv = gen_new_label(); |
|
699 |
tmp = load_cpu_field(NZF); |
|
700 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, inv); |
|
701 |
dead_tmp(tmp); |
|
702 |
tmp = load_cpu_field(VF); |
|
703 |
tmp2 = load_cpu_field(NZF); |
|
704 |
tcg_gen_xor_i32(tmp, tmp, tmp2); |
|
705 |
dead_tmp(tmp2); |
|
706 |
tcg_gen_brcond_i32(TCG_COND_GE, tmp, zero, label); |
|
707 |
gen_set_label(inv); |
|
708 |
break; |
|
709 |
case 13: /* le: Z || N != V */ |
|
710 |
tmp = load_cpu_field(NZF); |
|
711 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, zero, label); |
|
712 |
dead_tmp(tmp); |
|
713 |
tmp = load_cpu_field(VF); |
|
714 |
tmp2 = load_cpu_field(NZF); |
|
715 |
tcg_gen_xor_i32(tmp, tmp, tmp2); |
|
716 |
dead_tmp(tmp2); |
|
717 |
tcg_gen_brcond_i32(TCG_COND_LT, tmp, zero, label); |
|
718 |
break; |
|
719 |
default: |
|
720 |
fprintf(stderr, "Bad condition code 0x%x\n", cc); |
|
721 |
abort(); |
|
722 |
} |
|
723 |
dead_tmp(tmp); |
|
724 |
} |
|
602 | 725 |
|
603 | 726 |
const uint8_t table_logic_cc[16] = { |
604 | 727 |
1, /* and */ |
... | ... | |
633 | 756 |
gen_op_rorl_T1_T0_cc, |
634 | 757 |
}; |
635 | 758 |
|
636 |
/* Set PC and thumb state from T0. Clobbers T0. */
|
|
637 |
static inline void gen_bx(DisasContext *s)
|
|
759 |
/* Set PC and Thumb state from an immediate address. */
|
|
760 |
static inline void gen_bx_im(DisasContext *s, uint32_t addr)
|
|
638 | 761 |
{ |
639 | 762 |
TCGv tmp; |
640 | 763 |
|
641 | 764 |
s->is_jmp = DISAS_UPDATE; |
642 | 765 |
tmp = new_tmp(); |
643 |
tcg_gen_andi_i32(tmp, cpu_T[0], 1); |
|
644 |
tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb)); |
|
766 |
if (s->thumb != (addr & 1)) { |
|
767 |
tcg_gen_movi_i32(tmp, addr & 1); |
|
768 |
tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, thumb)); |
|
769 |
} |
|
770 |
tcg_gen_movi_i32(tmp, addr & ~1); |
|
771 |
tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, regs[15])); |
|
645 | 772 |
dead_tmp(tmp); |
646 |
tcg_gen_andi_i32(cpu_T[0], cpu_T[0], ~1); |
|
647 |
tcg_gen_st_i32(cpu_T[0], cpu_env, offsetof(CPUState, regs[15])); |
|
773 |
} |
|
774 |
|
|
775 |
/* Set PC and Thumb state from var. var is marked as dead. */ |
|
776 |
static inline void gen_bx(DisasContext *s, TCGv var) |
|
777 |
{ |
|
778 |
TCGv tmp; |
|
779 |
|
|
780 |
s->is_jmp = DISAS_UPDATE; |
|
781 |
tmp = new_tmp(); |
|
782 |
tcg_gen_andi_i32(tmp, var, 1); |
|
783 |
store_cpu_field(tmp, thumb); |
|
784 |
tcg_gen_andi_i32(var, var, ~1); |
|
785 |
store_cpu_field(var, regs[15]); |
|
786 |
} |
|
787 |
|
|
788 |
/* TODO: This should be removed. Use gen_bx instead. */ |
|
789 |
static inline void gen_bx_T0(DisasContext *s) |
|
790 |
{ |
|
791 |
TCGv tmp = new_tmp(); |
|
792 |
tcg_gen_mov_i32(tmp, cpu_T[0]); |
|
793 |
gen_bx(s, tmp); |
|
648 | 794 |
} |
649 | 795 |
|
650 | 796 |
#if defined(CONFIG_USER_ONLY) |
... | ... | |
1312 | 1458 |
return 1; |
1313 | 1459 |
} |
1314 | 1460 |
gen_op_shll_T1_im(28); |
1315 |
gen_op_movl_T0_T1(); |
|
1316 |
gen_op_movl_cpsr_T0(0xf0000000); |
|
1461 |
gen_set_nzcv(cpu_T[1]); |
|
1317 | 1462 |
break; |
1318 | 1463 |
case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */ |
1319 | 1464 |
rd = (insn >> 12) & 0xf; |
... | ... | |
1359 | 1504 |
case 3: |
1360 | 1505 |
return 1; |
1361 | 1506 |
} |
1362 |
gen_op_movl_cpsr_T0(0xf0000000);
|
|
1507 |
gen_set_nzcv(cpu_T[0]);
|
|
1363 | 1508 |
break; |
1364 | 1509 |
case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */ |
1365 | 1510 |
wrd = (insn >> 12) & 0xf; |
... | ... | |
1405 | 1550 |
case 3: |
1406 | 1551 |
return 1; |
1407 | 1552 |
} |
1408 |
gen_op_movl_T1_im(0xf0000000); |
|
1409 |
gen_op_andl_T0_T1(); |
|
1410 |
gen_op_movl_cpsr_T0(0xf0000000); |
|
1553 |
gen_set_nzcv(cpu_T[0]); |
|
1411 | 1554 |
break; |
1412 | 1555 |
case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */ |
1413 | 1556 |
rd = (insn >> 12) & 0xf; |
... | ... | |
2246 | 2389 |
} |
2247 | 2390 |
if (rd == 15) { |
2248 | 2391 |
/* Set the 4 flag bits in the CPSR. */ |
2249 |
gen_op_movl_cpsr_T0(0xf0000000);
|
|
2392 |
gen_set_nzcv(cpu_T[0]);
|
|
2250 | 2393 |
} else |
2251 | 2394 |
gen_movl_reg_T0(s, rd); |
2252 | 2395 |
} else { |
... | ... | |
2745 | 2888 |
if (__builtin_expect(s->singlestep_enabled, 0)) { |
2746 | 2889 |
/* An indirect jump so that we still trigger the debug exception. */ |
2747 | 2890 |
if (s->thumb) |
2748 |
dest |= 1; |
|
2749 |
gen_op_movl_T0_im(dest); |
|
2750 |
gen_bx(s); |
|
2891 |
dest |= 1; |
|
2892 |
gen_bx_im(s, dest); |
|
2751 | 2893 |
} else { |
2752 | 2894 |
gen_goto_tb(s, 0, dest); |
2753 | 2895 |
s->is_jmp = DISAS_TB_JUMP; |
2754 | 2896 |
} |
2755 | 2897 |
} |
2756 | 2898 |
|
2757 |
static inline void gen_mulxy(int x, int y) |
|
2899 |
static inline void gen_mulxy(TCGv t0, TCGv t1, int x, int y)
|
|
2758 | 2900 |
{ |
2759 | 2901 |
if (x) |
2760 |
tcg_gen_sari_i32(cpu_T[0], cpu_T[0], 16);
|
|
2902 |
tcg_gen_sari_i32(t0, t0, 16);
|
|
2761 | 2903 |
else |
2762 |
gen_sxth(cpu_T[0]);
|
|
2904 |
gen_sxth(t0);
|
|
2763 | 2905 |
if (y) |
2764 |
gen_op_sarl_T1_im(16);
|
|
2906 |
tcg_gen_sari_i32(t1, t1, 16);
|
|
2765 | 2907 |
else |
2766 |
gen_sxth(cpu_T[1]);
|
|
2767 |
gen_op_mul_T0_T1();
|
|
2908 |
gen_sxth(t1);
|
|
2909 |
tcg_gen_mul_i32(t0, t0, t1);
|
|
2768 | 2910 |
} |
2769 | 2911 |
|
2770 | 2912 |
/* Return the mask of PSR bits set by a MSR instruction. */ |
... | ... | |
2799 | 2941 |
/* Returns nonzero if access to the PSR is not permitted. */ |
2800 | 2942 |
static int gen_set_psr_T0(DisasContext *s, uint32_t mask, int spsr) |
2801 | 2943 |
{ |
2944 |
TCGv tmp; |
|
2802 | 2945 |
if (spsr) { |
2803 | 2946 |
/* ??? This is also undefined in system mode. */ |
2804 | 2947 |
if (IS_USER(s)) |
2805 | 2948 |
return 1; |
2806 |
gen_op_movl_spsr_T0(mask); |
|
2949 |
|
|
2950 |
tmp = load_cpu_field(spsr); |
|
2951 |
tcg_gen_andi_i32(tmp, tmp, ~mask); |
|
2952 |
tcg_gen_andi_i32(cpu_T[0], cpu_T[0], mask); |
|
2953 |
tcg_gen_or_i32(tmp, tmp, cpu_T[0]); |
|
2954 |
store_cpu_field(tmp, spsr); |
|
2807 | 2955 |
} else { |
2808 |
gen_op_movl_cpsr_T0(mask);
|
|
2956 |
gen_set_cpsr(cpu_T[0], mask);
|
|
2809 | 2957 |
} |
2810 | 2958 |
gen_lookup_tb(s); |
2811 | 2959 |
return 0; |
... | ... | |
2814 | 2962 |
/* Generate an old-style exception return. */ |
2815 | 2963 |
static void gen_exception_return(DisasContext *s) |
2816 | 2964 |
{ |
2965 |
TCGv tmp; |
|
2817 | 2966 |
gen_set_pc_T0(); |
2818 |
gen_op_movl_T0_spsr(); |
|
2819 |
gen_op_movl_cpsr_T0(0xffffffff); |
|
2967 |
tmp = load_cpu_field(spsr); |
|
2968 |
gen_set_cpsr(tmp, 0xffffffff); |
|
2969 |
dead_tmp(tmp); |
|
2820 | 2970 |
s->is_jmp = DISAS_UPDATE; |
2821 | 2971 |
} |
2822 | 2972 |
|
2823 | 2973 |
/* Generate a v6 exception return. */ |
2824 | 2974 |
static void gen_rfe(DisasContext *s) |
2825 | 2975 |
{ |
2826 |
gen_op_movl_cpsr_T0(0xffffffff);
|
|
2976 |
gen_set_cpsr(cpu_T[0], 0xffffffff);
|
|
2827 | 2977 |
gen_op_movl_T0_T2(); |
2828 | 2978 |
gen_set_pc_T0(); |
2829 | 2979 |
s->is_jmp = DISAS_UPDATE; |
... | ... | |
2836 | 2986 |
uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1); |
2837 | 2987 |
TCGv tmp = new_tmp(); |
2838 | 2988 |
tcg_gen_movi_i32(tmp, val); |
2839 |
tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, condexec_bits)); |
|
2840 |
dead_tmp(tmp); |
|
2989 |
store_cpu_field(tmp, condexec_bits); |
|
2841 | 2990 |
} |
2842 | 2991 |
} |
2843 | 2992 |
|
... | ... | |
5027 | 5176 |
gen_op_addl_T1_im(offset); |
5028 | 5177 |
gen_movl_T0_reg(s, 14); |
5029 | 5178 |
gen_ldst(stl, s); |
5030 |
gen_op_movl_T0_cpsr();
|
|
5179 |
gen_helper_cpsr_read(cpu_T[0]);
|
|
5031 | 5180 |
gen_op_addl_T1_im(4); |
5032 | 5181 |
gen_ldst(stl, s); |
5033 | 5182 |
if (insn & (1 << 21)) { |
... | ... | |
5089 | 5238 |
int32_t offset; |
5090 | 5239 |
|
5091 | 5240 |
val = (uint32_t)s->pc; |
5092 |
gen_op_movl_T0_im(val); |
|
5093 |
gen_movl_reg_T0(s, 14); |
|
5241 |
tmp = new_tmp(); |
|
5242 |
tcg_gen_movi_i32(tmp, val); |
|
5243 |
store_reg(s, 14, tmp); |
|
5094 | 5244 |
/* Sign-extend the 24-bit offset */ |
5095 | 5245 |
offset = (((int32_t)insn) << 8) >> 8; |
5096 | 5246 |
/* offset * 4 + bit24 * 2 + (thumb bit) */ |
5097 | 5247 |
val += (offset << 2) | ((insn >> 23) & 2) | 1; |
5098 | 5248 |
/* pipeline offset */ |
5099 | 5249 |
val += 4; |
5100 |
gen_op_movl_T0_im(val); |
|
5101 |
gen_bx(s); |
|
5250 |
gen_bx_im(s, val); |
|
5102 | 5251 |
return; |
5103 | 5252 |
} else if ((insn & 0x0e000f00) == 0x0c000100) { |
5104 | 5253 |
if (arm_feature(env, ARM_FEATURE_IWMMXT)) { |
... | ... | |
5144 | 5293 |
/* if not always execute, we generate a conditional jump to |
5145 | 5294 |
next instruction */ |
5146 | 5295 |
s->condlabel = gen_new_label(); |
5147 |
gen_test_cc[cond ^ 1](s->condlabel);
|
|
5296 |
gen_test_cc(cond ^ 1, s->condlabel);
|
|
5148 | 5297 |
s->condjmp = 1; |
5149 | 5298 |
} |
5150 | 5299 |
if ((insn & 0x0f900000) == 0x03000000) { |
... | ... | |
5201 | 5350 |
if (op1 & 2) { |
5202 | 5351 |
if (IS_USER(s)) |
5203 | 5352 |
goto illegal_op; |
5204 |
gen_op_movl_T0_spsr();
|
|
5353 |
tmp = load_cpu_field(spsr);
|
|
5205 | 5354 |
} else { |
5206 |
gen_op_movl_T0_cpsr(); |
|
5355 |
tmp = new_tmp(); |
|
5356 |
gen_helper_cpsr_read(tmp); |
|
5207 | 5357 |
} |
5208 |
gen_movl_reg_T0(s, rd);
|
|
5358 |
store_reg(s, rd, tmp);
|
|
5209 | 5359 |
} |
5210 | 5360 |
break; |
5211 | 5361 |
case 0x1: |
5212 | 5362 |
if (op1 == 1) { |
5213 | 5363 |
/* branch/exchange thumb (bx). */ |
5214 |
gen_movl_T0_reg(s, rm);
|
|
5215 |
gen_bx(s); |
|
5364 |
tmp = load_reg(s, rm);
|
|
5365 |
gen_bx(s, tmp);
|
|
5216 | 5366 |
} else if (op1 == 3) { |
5217 | 5367 |
/* clz */ |
5218 | 5368 |
rd = (insn >> 12) & 0xf; |
... | ... | |
5227 | 5377 |
if (op1 == 1) { |
5228 | 5378 |
ARCH(5J); /* bxj */ |
5229 | 5379 |
/* Trivial implementation equivalent to bx. */ |
5230 |
gen_movl_T0_reg(s, rm);
|
|
5231 |
gen_bx(s); |
|
5380 |
tmp = load_reg(s, rm);
|
|
5381 |
gen_bx(s, tmp);
|
|
5232 | 5382 |
} else { |
5233 | 5383 |
goto illegal_op; |
5234 | 5384 |
} |
... | ... | |
5238 | 5388 |
goto illegal_op; |
5239 | 5389 |
|
5240 | 5390 |
/* branch link/exchange thumb (blx) */ |
5241 |
val = (uint32_t)s->pc;
|
|
5242 |
gen_op_movl_T1_im(val);
|
|
5243 |
gen_movl_T0_reg(s, rm);
|
|
5244 |
gen_movl_reg_T1(s, 14);
|
|
5245 |
gen_bx(s); |
|
5391 |
tmp = load_reg(s, rm);
|
|
5392 |
tmp2 = new_tmp();
|
|
5393 |
tcg_gen_movi_i32(tmp2, s->pc);
|
|
5394 |
store_reg(s, 14, tmp2);
|
|
5395 |
gen_bx(s, tmp);
|
|
5246 | 5396 |
break; |
5247 | 5397 |
case 0x5: /* saturating add/subtract */ |
5248 | 5398 |
rd = (insn >> 12) & 0xf; |
... | ... | |
5261 | 5411 |
gen_set_condexec(s); |
5262 | 5412 |
gen_op_movl_T0_im((long)s->pc - 4); |
5263 | 5413 |
gen_set_pc_T0(); |
5264 |
gen_op_bkpt();
|
|
5414 |
gen_exception(EXCP_BKPT);
|
|
5265 | 5415 |
s->is_jmp = DISAS_JUMP; |
5266 | 5416 |
break; |
5267 | 5417 |
case 0x8: /* signed multiply */ |
... | ... | |
5279 | 5429 |
gen_op_sarl_T1_im(16); |
5280 | 5430 |
else |
5281 | 5431 |
gen_sxth(cpu_T[1]); |
5282 |
gen_op_imulw_T0_T1();
|
|
5432 |
gen_imulw(cpu_T[0], cpu_T[1]);
|
|
5283 | 5433 |
if ((sh & 2) == 0) { |
5284 | 5434 |
gen_movl_T1_reg(s, rn); |
5285 | 5435 |
gen_op_addl_T0_T1_setq(); |
... | ... | |
5289 | 5439 |
/* 16 * 16 */ |
5290 | 5440 |
gen_movl_T0_reg(s, rm); |
5291 | 5441 |
gen_movl_T1_reg(s, rs); |
5292 |
gen_mulxy(sh & 2, sh & 4); |
|
5442 |
gen_mulxy(cpu_T[0], cpu_T[1], sh & 2, sh & 4);
|
|
5293 | 5443 |
if (op1 == 2) { |
5294 | 5444 |
gen_op_signbit_T1_T0(); |
5295 | 5445 |
gen_op_addq_T0_T1(rn, rd); |
... | ... | |
5758 | 5908 |
/* Signed multiply most significant [accumulate]. */ |
5759 | 5909 |
gen_op_imull_T0_T1(); |
5760 | 5910 |
if (insn & (1 << 5)) |
5761 |
gen_op_roundqd_T0_T1();
|
|
5911 |
gen_roundqd(cpu_T[0], cpu_T[1]);
|
|
5762 | 5912 |
else |
5763 | 5913 |
gen_op_movl_T0_T1(); |
5764 | 5914 |
if (rn != 15) { |
... | ... | |
5926 | 6076 |
if (insn & (1 << 20)) { |
5927 | 6077 |
/* Complete the load. */ |
5928 | 6078 |
if (rd == 15) |
5929 |
gen_bx(s); |
|
6079 |
gen_bx_T0(s);
|
|
5930 | 6080 |
else |
5931 | 6081 |
gen_movl_reg_T0(s, rd); |
5932 | 6082 |
} |
... | ... | |
5980 | 6130 |
/* load */ |
5981 | 6131 |
gen_ldst(ldl, s); |
5982 | 6132 |
if (i == 15) { |
5983 |
gen_bx(s); |
|
6133 |
gen_bx_T0(s);
|
|
5984 | 6134 |
} else if (user) { |
5985 | 6135 |
gen_op_movl_user_T0(i); |
5986 | 6136 |
} else if (i == rn) { |
... | ... | |
6035 | 6185 |
} |
6036 | 6186 |
if ((insn & (1 << 22)) && !user) { |
6037 | 6187 |
/* Restore CPSR from SPSR. */ |
6038 |
gen_op_movl_T0_spsr(); |
|
6039 |
gen_op_movl_cpsr_T0(0xffffffff); |
|
6188 |
tmp = load_cpu_field(spsr); |
|
6189 |
gen_set_cpsr(tmp, 0xffffffff); |
|
6190 |
dead_tmp(tmp); |
|
6040 | 6191 |
s->is_jmp = DISAS_UPDATE; |
6041 | 6192 |
} |
6042 | 6193 |
} |
... | ... | |
6075 | 6226 |
gen_set_condexec(s); |
6076 | 6227 |
gen_op_movl_T0_im((long)s->pc - 4); |
6077 | 6228 |
gen_set_pc_T0(); |
6078 |
gen_op_undef_insn();
|
|
6229 |
gen_exception(EXCP_UDEF);
|
|
6079 | 6230 |
s->is_jmp = DISAS_JUMP; |
6080 | 6231 |
break; |
6081 | 6232 |
} |
... | ... | |
6186 | 6337 |
if ((insn & (1 << 12)) == 0) { |
6187 | 6338 |
/* Second half of blx. */ |
6188 | 6339 |
offset = ((insn & 0x7ff) << 1); |
6189 |
gen_movl_T0_reg(s, 14); |
|
6190 |
gen_op_movl_T1_im(offset); |
|
6191 |
gen_op_addl_T0_T1(); |
|
6192 |
gen_op_movl_T1_im(0xfffffffc); |
|
6193 |
gen_op_andl_T0_T1(); |
|
6340 |
tmp = load_reg(s, 14); |
|
6341 |
tcg_gen_addi_i32(tmp, tmp, offset); |
|
6342 |
tcg_gen_andi_i32(tmp, tmp, 0xfffffffc); |
|
6194 | 6343 |
|
6195 | 6344 |
addr = (uint32_t)s->pc; |
6196 |
gen_op_movl_T1_im(addr | 1); |
|
6197 |
gen_movl_reg_T1(s, 14); |
|
6198 |
gen_bx(s); |
|
6345 |
tmp2 = new_tmp(); |
|
6346 |
tcg_gen_movi_i32(tmp2, addr | 1); |
|
6347 |
store_reg(s, 14, tmp2); |
|
6348 |
gen_bx(s, tmp); |
|
6199 | 6349 |
return 0; |
6200 | 6350 |
} |
6201 | 6351 |
if (insn & (1 << 11)) { |
6202 | 6352 |
/* Second half of bl. */ |
6203 | 6353 |
offset = ((insn & 0x7ff) << 1) | 1; |
6204 |
gen_movl_T0_reg(s, 14); |
|
6205 |
gen_op_movl_T1_im(offset); |
|
6206 |
gen_op_addl_T0_T1(); |
|
6354 |
tmp = load_reg(s, 14); |
|
6355 |
tcg_gen_addi_i32(tmp, tmp, 14); |
|
6207 | 6356 |
|
6208 | 6357 |
addr = (uint32_t)s->pc; |
6209 |
gen_op_movl_T1_im(addr | 1); |
|
6210 |
gen_movl_reg_T1(s, 14); |
|
6211 |
gen_bx(s); |
|
6358 |
tmp2 = new_tmp(); |
|
6359 |
tcg_gen_movi_i32(tmp2, addr | 1); |
|
6360 |
store_reg(s, 14, tmp2); |
|
6361 |
gen_bx(s, tmp); |
|
6212 | 6362 |
return 0; |
6213 | 6363 |
} |
6214 | 6364 |
if ((s->pc & ~TARGET_PAGE_MASK) == 0) { |
... | ... | |
6388 | 6538 |
} |
6389 | 6539 |
gen_movl_T0_reg(s, 14); |
6390 | 6540 |
gen_ldst(stl, s); |
6391 |
gen_op_movl_T0_cpsr();
|
|
6541 |
gen_helper_cpsr_read(cpu_T[0]);
|
|
6392 | 6542 |
gen_op_addl_T1_im(4); |
6393 | 6543 |
gen_ldst(stl, s); |
6394 | 6544 |
if (insn & (1 << 21)) { |
... | ... | |
6424 | 6574 |
/* Load. */ |
6425 | 6575 |
gen_ldst(ldl, s); |
6426 | 6576 |
if (i == 15) { |
6427 |
gen_bx(s); |
|
6577 |
gen_bx_T0(s);
|
|
6428 | 6578 |
} else { |
6429 | 6579 |
gen_movl_reg_T0(s, i); |
6430 | 6580 |
} |
... | ... | |
6527 | 6677 |
op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7); |
6528 | 6678 |
if (op < 4) { |
6529 | 6679 |
/* Saturating add/subtract. */ |
6530 |
gen_movl_T0_reg(s, rm);
|
|
6531 |
gen_movl_T1_reg(s, rn);
|
|
6680 |
tmp = load_reg(s, rn);
|
|
6681 |
tmp2 = load_reg(s, rm);
|
|
6532 | 6682 |
if (op & 2) |
6533 |
gen_helper_double_saturate(cpu_T[1], cpu_T[1]);
|
|
6683 |
gen_helper_double_saturate(tmp, tmp);
|
|
6534 | 6684 |
if (op & 1) |
6535 |
gen_op_subl_T0_T1_saturate();
|
|
6685 |
gen_helper_sub_saturate(tmp, tmp2, tmp);
|
|
6536 | 6686 |
else |
6537 |
gen_op_addl_T0_T1_saturate(); |
|
6687 |
gen_helper_add_saturate(tmp, tmp, tmp2); |
|
6688 |
dead_tmp(tmp2); |
|
6538 | 6689 |
} else { |
6539 |
gen_movl_T0_reg(s, rn);
|
|
6690 |
tmp = load_reg(s, rn);
|
|
6540 | 6691 |
switch (op) { |
6541 | 6692 |
case 0x0a: /* rbit */ |
6542 |
gen_helper_rbit(cpu_T[0], cpu_T[0]);
|
|
6693 |
gen_helper_rbit(tmp, tmp);
|
|
6543 | 6694 |
break; |
6544 | 6695 |
case 0x08: /* rev */ |
6545 |
gen_op_rev_T0();
|
|
6696 |
tcg_gen_bswap_i32(tmp, tmp);
|
|
6546 | 6697 |
break; |
6547 | 6698 |
case 0x09: /* rev16 */ |
6548 |
gen_rev16(cpu_T[0]);
|
|
6699 |
gen_rev16(tmp);
|
|
6549 | 6700 |
break; |
6550 | 6701 |
case 0x0b: /* revsh */ |
6551 |
gen_revsh(cpu_T[0]);
|
|
6702 |
gen_revsh(tmp);
|
|
6552 | 6703 |
break; |
6553 | 6704 |
case 0x10: /* sel */ |
6554 |
gen_movl_T1_reg(s, rm);
|
|
6705 |
tmp2 = load_reg(s, rm);
|
|
6555 | 6706 |
tmp3 = new_tmp(); |
6556 | 6707 |
tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUState, GE)); |
6557 |
gen_helper_sel_flags(cpu_T[0], tmp3, cpu_T[0], cpu_T[1]);
|
|
6708 |
gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
|
|
6558 | 6709 |
dead_tmp(tmp3); |
6710 |
dead_tmp(tmp2); |
|
6559 | 6711 |
break; |
6560 | 6712 |
case 0x18: /* clz */ |
6561 |
gen_helper_clz(cpu_T[0], cpu_T[0]);
|
|
6713 |
gen_helper_clz(tmp, tmp);
|
|
6562 | 6714 |
break; |
6563 | 6715 |
default: |
6564 | 6716 |
goto illegal_op; |
6565 | 6717 |
} |
6566 | 6718 |
} |
6567 |
gen_movl_reg_T0(s, rd);
|
|
6719 |
store_reg(s, rd, tmp);
|
|
6568 | 6720 |
break; |
6569 | 6721 |
case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */ |
6570 | 6722 |
op = (insn >> 4) & 0xf; |
6571 |
gen_movl_T0_reg(s, rn);
|
|
6572 |
gen_movl_T1_reg(s, rm);
|
|
6723 |
tmp = load_reg(s, rn);
|
|
6724 |
tmp2 = load_reg(s, rm);
|
|
6573 | 6725 |
switch ((insn >> 20) & 7) { |
6574 | 6726 |
case 0: /* 32 x 32 -> 32 */ |
6575 |
gen_op_mul_T0_T1(); |
|
6727 |
tcg_gen_mul_i32(tmp, tmp, tmp2); |
|
6728 |
dead_tmp(tmp2); |
|
6576 | 6729 |
if (rs != 15) { |
6577 |
gen_movl_T1_reg(s, rs);
|
|
6730 |
tmp2 = load_reg(s, rs);
|
|
6578 | 6731 |
if (op) |
6579 |
gen_op_rsbl_T0_T1();
|
|
6732 |
tcg_gen_sub_i32(tmp, tmp2, tmp);
|
|
6580 | 6733 |
else |
6581 |
gen_op_addl_T0_T1(); |
|
6734 |
tcg_gen_add_i32(tmp, tmp, tmp2); |
|
6735 |
dead_tmp(tmp2); |
|
6582 | 6736 |
} |
6583 |
gen_movl_reg_T0(s, rd); |
|
6584 | 6737 |
break; |
6585 | 6738 |
case 1: /* 16 x 16 -> 32 */ |
6586 |
gen_mulxy(op & 2, op & 1); |
|
6739 |
gen_mulxy(tmp, tmp2, op & 2, op & 1); |
|
6740 |
dead_tmp(tmp2); |
|
6587 | 6741 |
if (rs != 15) { |
6588 |
gen_movl_T1_reg(s, rs); |
|
6589 |
gen_op_addl_T0_T1_setq(); |
|
6742 |
tmp2 = load_reg(s, rs); |
|
6743 |
gen_helper_add_setq(tmp, tmp, tmp2); |
|
6744 |
dead_tmp(tmp2); |
|
6590 | 6745 |
} |
6591 |
gen_movl_reg_T0(s, rd); |
|
6592 | 6746 |
break; |
6593 | 6747 |
case 2: /* Dual multiply add. */ |
6594 | 6748 |
case 4: /* Dual multiply subtract. */ |
6595 | 6749 |
if (op) |
6596 |
gen_swap_half(cpu_T[1]);
|
|
6597 |
gen_smul_dual(cpu_T[0], cpu_T[1]);
|
|
6750 |
gen_swap_half(tmp2);
|
|
6751 |
gen_smul_dual(tmp, tmp2);
|
|
6598 | 6752 |
/* This addition cannot overflow. */ |
6599 | 6753 |
if (insn & (1 << 22)) { |
6600 |
gen_op_subl_T0_T1();
|
|
6754 |
tcg_gen_sub_i32(tmp, tmp, tmp2);
|
|
6601 | 6755 |
} else { |
6602 |
gen_op_addl_T0_T1();
|
|
6756 |
tcg_gen_add_i32(tmp, tmp, tmp2);
|
|
6603 | 6757 |
} |
6758 |
dead_tmp(tmp2); |
|
6604 | 6759 |
if (rs != 15) |
6605 | 6760 |
{ |
6606 |
gen_movl_T1_reg(s, rs); |
|
6607 |
gen_op_addl_T0_T1_setq(); |
|
6761 |
tmp2 = load_reg(s, rs); |
|
6762 |
gen_helper_add_setq(tmp, tmp, tmp2); |
|
6763 |
dead_tmp(tmp2); |
|
6608 | 6764 |
} |
6609 |
gen_movl_reg_T0(s, rd); |
|
6610 | 6765 |
break; |
6611 | 6766 |
case 3: /* 32 * 16 -> 32msb */ |
6612 | 6767 |
if (op) |
6613 |
gen_op_sarl_T1_im(16);
|
|
6768 |
tcg_gen_sari_i32(tmp2, tmp2, 16);
|
|
6614 | 6769 |
else |
6615 |
gen_sxth(cpu_T[1]); |
|
6616 |
gen_op_imulw_T0_T1(); |
|
6770 |
gen_sxth(tmp2); |
|
6771 |
gen_imulw(tmp, tmp2); |
|
6772 |
dead_tmp(tmp2); |
|
6617 | 6773 |
if (rs != 15) |
6618 | 6774 |
{ |
6619 |
gen_movl_T1_reg(s, rs); |
|
6620 |
gen_op_addl_T0_T1_setq(); |
|
6775 |
tmp2 = load_reg(s, rs); |
|
6776 |
gen_helper_add_setq(tmp, tmp, tmp2); |
|
6777 |
dead_tmp(tmp2); |
|
6621 | 6778 |
} |
6622 |
gen_movl_reg_T0(s, rd); |
|
6623 | 6779 |
break; |
6624 | 6780 |
case 5: case 6: /* 32 * 32 -> 32msb */ |
6625 |
gen_op_imull_T0_T1(); |
|
6626 |
if (insn & (1 << 5)) |
|
6627 |
gen_op_roundqd_T0_T1(); |
|
6628 |
else |
|
6629 |
gen_op_movl_T0_T1(); |
|
6781 |
gen_imull(tmp, tmp2); |
|
6782 |
if (insn & (1 << 5)) { |
|
6783 |
gen_roundqd(tmp, tmp2); |
|
6784 |
dead_tmp(tmp2); |
|
6785 |
} else { |
|
6786 |
dead_tmp(tmp); |
|
6787 |
tmp = tmp2; |
|
6788 |
} |
|
6630 | 6789 |
if (rs != 15) { |
6631 |
gen_movl_T1_reg(s, rs);
|
|
6790 |
tmp2 = load_reg(s, rs);
|
|
6632 | 6791 |
if (insn & (1 << 21)) { |
6633 |
gen_op_addl_T0_T1();
|
|
6792 |
tcg_gen_add_i32(tmp, tmp, tmp2);
|
|
6634 | 6793 |
} else { |
6635 |
gen_op_rsbl_T0_T1();
|
|
6794 |
tcg_gen_sub_i32(tmp, tmp2, tmp);
|
|
6636 | 6795 |
} |
6796 |
dead_tmp(tmp2); |
|
6637 | 6797 |
} |
6638 |
gen_movl_reg_T0(s, rd); |
|
6639 | 6798 |
break; |
6640 | 6799 |
case 7: /* Unsigned sum of absolute differences. */ |
6641 |
gen_helper_usad8(cpu_T[0], cpu_T[0], cpu_T[1]); |
|
6800 |
gen_helper_usad8(tmp, tmp, tmp2); |
|
6801 |
dead_tmp(tmp2); |
|
6642 | 6802 |
if (rs != 15) { |
6643 |
gen_movl_T1_reg(s, rs); |
|
6644 |
gen_op_addl_T0_T1(); |
|
6803 |
tmp2 = load_reg(s, rs); |
|
6804 |
tcg_gen_add_i32(tmp, tmp, tmp2); |
|
6805 |
dead_tmp(tmp2); |
|
6645 | 6806 |
} |
6646 |
gen_movl_reg_T0(s, rd); |
|
6647 | 6807 |
break; |
6648 | 6808 |
} |
6809 |
store_reg(s, rd, tmp); |
|
6649 | 6810 |
break; |
6650 | 6811 |
case 6: case 7: /* 64-bit multiply, Divide. */ |
6651 | 6812 |
op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70); |
... | ... | |
6681 | 6842 |
} else { |
6682 | 6843 |
if (op & 8) { |
6683 | 6844 |
/* smlalxy */ |
6684 |
gen_mulxy(op & 2, op & 1); |
|
6845 |
gen_mulxy(cpu_T[0], cpu_T[1], op & 2, op & 1);
|
|
6685 | 6846 |
gen_op_signbit_T1_T0(); |
6686 | 6847 |
} else { |
6687 | 6848 |
/* Signed 64-bit multiply */ |
... | ... | |
6745 | 6906 |
} else { |
6746 | 6907 |
/* blx */ |
6747 | 6908 |
addr &= ~(uint32_t)2; |
6748 |
gen_op_movl_T0_im(addr); |
|
6749 |
gen_bx(s); |
|
6909 |
gen_bx_im(s, addr); |
|
6750 | 6910 |
} |
6751 | 6911 |
} else if (((insn >> 23) & 7) == 7) { |
6752 | 6912 |
/* Misc control */ |
... | ... | |
6822 | 6982 |
break; |
6823 | 6983 |
case 4: /* bxj */ |
6824 | 6984 |
/* Trivial implementation equivalent to bx. */ |
6825 |
gen_movl_T0_reg(s, rn);
|
|
6826 |
gen_bx(s); |
|
6985 |
tmp = load_reg(s, rn);
|
|
6986 |
gen_bx(s, tmp);
|
|
6827 | 6987 |
break; |
6828 | 6988 |
case 5: /* Exception return. */ |
6829 | 6989 |
/* Unpredictable in user mode. */ |
... | ... | |
6832 | 6992 |
if (IS_M(env)) { |
6833 | 6993 |
gen_op_v7m_mrs_T0(insn & 0xff); |
6834 | 6994 |
} else { |
6835 |
gen_op_movl_T0_cpsr();
|
|
6995 |
gen_helper_cpsr_read(cpu_T[0]);
|
|
6836 | 6996 |
} |
6837 | 6997 |
gen_movl_reg_T0(s, rd); |
6838 | 6998 |
break; |
... | ... | |
6840 | 7000 |
/* Not accessible in user mode. */ |
6841 | 7001 |
if (IS_USER(s) || IS_M(env)) |
6842 | 7002 |
goto illegal_op; |
6843 |
gen_op_movl_T0_spsr();
|
|
6844 |
gen_movl_reg_T0(s, rd);
|
|
7003 |
tmp = load_cpu_field(spsr);
|
|
7004 |
store_reg(s, rd, tmp);
|
|
6845 | 7005 |
break; |
6846 | 7006 |
} |
6847 | 7007 |
} |
... | ... | |
6850 | 7010 |
op = (insn >> 22) & 0xf; |
6851 | 7011 |
/* Generate a conditional jump to next instruction. */ |
6852 | 7012 |
s->condlabel = gen_new_label(); |
6853 |
gen_test_cc[op ^ 1](s->condlabel);
|
|
7013 |
gen_test_cc(op ^ 1, s->condlabel);
|
|
6854 | 7014 |
s->condjmp = 1; |
6855 | 7015 |
|
6856 | 7016 |
/* offset[11:1] = insn[10:0] */ |
... | ... | |
7095 | 7255 |
default: goto illegal_op; |
7096 | 7256 |
} |
7097 | 7257 |
if (rs == 15) { |
7098 |
gen_bx(s); |
|
7258 |
gen_bx_T0(s);
|
|
7099 | 7259 |
} else { |
7100 | 7260 |
gen_movl_reg_T0(s, rs); |
7101 | 7261 |
} |
... | ... | |
7132 | 7292 |
int32_t offset; |
7133 | 7293 |
int i; |
7134 | 7294 |
TCGv tmp; |
7295 |
TCGv tmp2; |
|
7135 | 7296 |
|
7136 | 7297 |
if (s->condexec_mask) { |
7137 | 7298 |
cond = s->condexec_cond; |
7138 | 7299 |
s->condlabel = gen_new_label(); |
7139 |
gen_test_cc[cond ^ 1](s->condlabel);
|
|
7300 |
gen_test_cc(cond ^ 1, s->condlabel);
|
|
7140 | 7301 |
s->condjmp = 1; |
7141 | 7302 |
} |
7142 | 7303 |
|
... | ... | |
7254 | 7415 |
gen_op_movl_T1_im(val); |
7255 | 7416 |
gen_movl_reg_T1(s, 14); |
7256 | 7417 |
} |
7257 |
gen_movl_T0_reg(s, rm);
|
|
7258 |
gen_bx(s); |
|
7418 |
tmp = load_reg(s, rm);
|
|
7419 |
gen_bx(s, tmp);
|
|
7259 | 7420 |
break; |
7260 | 7421 |
} |
7261 | 7422 |
break; |
... | ... | |
7597 | 7758 |
gen_movl_reg_T1(s, 13); |
7598 | 7759 |
/* set the new PC value */ |
7599 | 7760 |
if ((insn & 0x0900) == 0x0900) |
7600 |
gen_bx(s); |
|
7761 |
gen_bx_T0(s);
|
|
7601 | 7762 |
break; |
7602 | 7763 |
|
7603 | 7764 |
case 1: case 3: case 9: case 11: /* czb */ |
7604 | 7765 |
rm = insn & 7; |
7605 |
gen_movl_T0_reg(s, rm); |
|
7766 |
tmp = load_reg(s, rm); |
|
7767 |
tmp2 = tcg_const_i32(0); |
|
7606 | 7768 |
s->condlabel = gen_new_label(); |
7607 | 7769 |
s->condjmp = 1; |
7608 | 7770 |
if (insn & (1 << 11)) |
7609 |
gen_op_testn_T0(s->condlabel);
|
|
7771 |
tcg_gen_brcond_i32(TCG_COND_EQ, tmp, tmp2, s->condlabel);
|
|
7610 | 7772 |
else |
7611 |
gen_op_test_T0(s->condlabel);
|
|
7612 |
|
|
7773 |
tcg_gen_brcond_i32(TCG_COND_NE, tmp, tmp2, s->condlabel);
|
|
7774 |
dead_tmp(tmp); |
|
7613 | 7775 |
offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3; |
7614 | 7776 |
val = (uint32_t)s->pc + 2; |
7615 | 7777 |
val += offset; |
... | ... | |
7631 | 7793 |
gen_set_condexec(s); |
7632 | 7794 |
gen_op_movl_T0_im((long)s->pc - 2); |
7633 | 7795 |
gen_set_pc_T0(); |
7634 |
gen_op_bkpt();
|
|
7796 |
gen_exception(EXCP_BKPT);
|
|
7635 | 7797 |
s->is_jmp = DISAS_JUMP; |
7636 | 7798 |
break; |
7637 | 7799 |
|
... | ... | |
7722 | 7884 |
} |
7723 | 7885 |
/* generate a conditional jump to next instruction */ |
7724 | 7886 |
s->condlabel = gen_new_label(); |
7725 |
gen_test_cc[cond ^ 1](s->condlabel);
|
|
7887 |
gen_test_cc(cond ^ 1, s->condlabel);
|
|
7726 | 7888 |
s->condjmp = 1; |
7727 | 7889 |
gen_movl_T1_reg(s, 15); |
7728 | 7890 |
|
... | ... | |
7756 | 7918 |
gen_set_condexec(s); |
7757 | 7919 |
gen_op_movl_T0_im((long)s->pc - 4); |
7758 | 7920 |
gen_set_pc_T0(); |
7759 |
gen_op_undef_insn();
|
|
7921 |
gen_exception(EXCP_UDEF);
|
|
7760 | 7922 |
s->is_jmp = DISAS_JUMP; |
7761 | 7923 |
return; |
7762 | 7924 |
illegal_op: |
... | ... | |
7764 | 7926 |
gen_set_condexec(s); |
7765 | 7927 |
gen_op_movl_T0_im((long)s->pc - 2); |
7766 | 7928 |
gen_set_pc_T0(); |
7767 |
gen_op_undef_insn();
|
|
7929 |
gen_exception(EXCP_UDEF);
|
|
7768 | 7930 |
s->is_jmp = DISAS_JUMP; |
7769 | 7931 |
} |
7770 | 7932 |
|
... | ... | |
7814 | 7976 |
{ |
7815 | 7977 |
TCGv tmp = new_tmp(); |
7816 | 7978 |
tcg_gen_movi_i32(tmp, 0); |
7817 |
tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUState, condexec_bits)); |
|
7818 |
dead_tmp(tmp); |
|
7979 |
store_cpu_field(tmp, condexec_bits); |
|
7819 | 7980 |
} |
7820 | 7981 |
do { |
7821 | 7982 |
#ifndef CONFIG_USER_ONLY |
7822 | 7983 |
if (dc->pc >= 0xfffffff0 && IS_M(env)) { |
7823 | 7984 |
/* We always get here via a jump, so know we are not in a |
7824 | 7985 |
conditional execution block. */ |
7825 |
gen_op_exception_exit();
|
|
7986 |
gen_exception(EXCP_EXCEPTION_EXIT);
|
|
7826 | 7987 |
} |
7827 | 7988 |
#endif |
7828 | 7989 |
|
... | ... | |
7832 | 7993 |
gen_set_condexec(dc); |
7833 | 7994 |
gen_op_movl_T0_im((long)dc->pc); |
7834 | 7995 |
gen_set_pc_T0(); |
7835 |
gen_op_debug();
|
|
7996 |
gen_exception(EXCP_DEBUG);
|
|
7836 | 7997 |
dc->is_jmp = DISAS_JUMP; |
7837 | 7998 |
/* Advance PC so that clearing the breakpoint will |
7838 | 7999 |
invalidate this TB. */ |
... | ... | |
7897 | 8058 |
if (dc->condjmp) { |
7898 | 8059 |
gen_set_condexec(dc); |
7899 | 8060 |
if (dc->is_jmp == DISAS_SWI) { |
7900 |
gen_op_swi();
|
|
8061 |
gen_exception(EXCP_SWI);
|
|
7901 | 8062 |
} else { |
7902 |
gen_op_debug();
|
|
8063 |
gen_exception(EXCP_DEBUG);
|
|
7903 | 8064 |
} |
7904 | 8065 |
gen_set_label(dc->condlabel); |
7905 | 8066 |
} |
... | ... | |
7910 | 8071 |
} |
7911 | 8072 |
gen_set_condexec(dc); |
7912 | 8073 |
if (dc->is_jmp == DISAS_SWI && !dc->condjmp) { |
7913 |
gen_op_swi();
|
|
8074 |
gen_exception(EXCP_SWI);
|
|
7914 | 8075 |
} else { |
7915 | 8076 |
/* FIXME: Single stepping a WFI insn will not halt |
7916 | 8077 |
the CPU. */ |
7917 |
gen_op_debug();
|
|
8078 |
gen_exception(EXCP_DEBUG);
|
|
7918 | 8079 |
} |
7919 | 8080 |
} else { |
7920 | 8081 |
/* While branches must always occur at the end of an IT block, |
... | ... | |
7940 | 8101 |
/* nothing more to generate */ |
7941 | 8102 |
break; |
7942 | 8103 |
case DISAS_WFI: |
7943 |
gen_op_wfi();
|
|
8104 |
gen_helper_wfi();
|
|
7944 | 8105 |
break; |
7945 | 8106 |
case DISAS_SWI: |
7946 |
gen_op_swi();
|
|
8107 |
gen_exception(EXCP_SWI);
|
|
7947 | 8108 |
break; |
7948 | 8109 |
} |
7949 | 8110 |
if (dc->condjmp) { |
Also available in: Unified diff