Commit e695238182aa391f5f91343c7484d9818bc66369

Authored by Filip Navara
1 parent 660f11be

ARM7TDMI emulation

While most of the ARMv5 instructions are backward compatible with ARMv4, there
are few important differences. Most notably the stack pop and load instructions
ignore the lowest bit, which is used by ARMv5 to switch to Thumb mode. A
base-updated data-abort model is used on ARM7TDMI, CP15 coprocessor is not
present and several instructions of later architectures are not implemented.

This patch introduces flags for the V5, CP15 and ABORT_BU (base-updated abort
model) features. When V5 feature is not set the bit 0 on POP, LD and LDM of PC
register is ignored and doesn't swith to/from Thumb mode and several
instructions are treated as unimplemented (BLX, PLD, BKPT, LDRD, STRD).

Based on patch by Ulrich Hecht <uli@suse.de>.

Signed-off-by: Filip Navara <filip.navara@gmail.com>
target-arm/cpu.h
@@ -330,6 +330,7 @@ enum arm_features { @@ -330,6 +330,7 @@ enum arm_features {
330 ARM_FEATURE_AUXCR, /* ARM1026 Auxiliary control register. */ 330 ARM_FEATURE_AUXCR, /* ARM1026 Auxiliary control register. */
331 ARM_FEATURE_XSCALE, /* Intel XScale extensions. */ 331 ARM_FEATURE_XSCALE, /* Intel XScale extensions. */
332 ARM_FEATURE_IWMMXT, /* Intel iwMMXt extension. */ 332 ARM_FEATURE_IWMMXT, /* Intel iwMMXt extension. */
  333 + ARM_FEATURE_V5,
333 ARM_FEATURE_V6, 334 ARM_FEATURE_V6,
334 ARM_FEATURE_V6K, 335 ARM_FEATURE_V6K,
335 ARM_FEATURE_V7, 336 ARM_FEATURE_V7,
@@ -340,7 +341,9 @@ enum arm_features { @@ -340,7 +341,9 @@ enum arm_features {
340 ARM_FEATURE_DIV, 341 ARM_FEATURE_DIV,
341 ARM_FEATURE_M, /* Microcontroller profile. */ 342 ARM_FEATURE_M, /* Microcontroller profile. */
342 ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling. */ 343 ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling. */
343 - ARM_FEATURE_THUMB2EE 344 + ARM_FEATURE_THUMB2EE,
  345 + ARM_FEATURE_CP15, /* ARM7TDMI, ARM7TDMI-S, ARM7EJ-S, and ARM9TDMI cores do not have a CP15 */
  346 + ARM_FEATURE_ABORT_BU /* base updated abort model, e.g. ARMxTDMI */
344 }; 347 };
345 348
346 static inline int arm_feature(CPUARMState *env, int feature) 349 static inline int arm_feature(CPUARMState *env, int feature)
@@ -366,6 +369,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum, @@ -366,6 +369,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
366 #define IS_M(env) arm_feature(env, ARM_FEATURE_M) 369 #define IS_M(env) arm_feature(env, ARM_FEATURE_M)
367 #define ARM_CPUID(env) (env->cp15.c0_cpuid) 370 #define ARM_CPUID(env) (env->cp15.c0_cpuid)
368 371
  372 +#define ARM_CPUID_ARM7TDMI 0x41807000 /* guess; no CP15 on ARM7TDMI */
369 #define ARM_CPUID_ARM1026 0x4106a262 373 #define ARM_CPUID_ARM1026 0x4106a262
370 #define ARM_CPUID_ARM926 0x41069265 374 #define ARM_CPUID_ARM926 0x41069265
371 #define ARM_CPUID_ARM946 0x41059461 375 #define ARM_CPUID_ARM946 0x41059461
target-arm/helper.c
@@ -37,19 +37,28 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) @@ -37,19 +37,28 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
37 { 37 {
38 env->cp15.c0_cpuid = id; 38 env->cp15.c0_cpuid = id;
39 switch (id) { 39 switch (id) {
  40 + case ARM_CPUID_ARM7TDMI:
  41 + set_feature(env, ARM_FEATURE_ABORT_BU);
  42 + break;
40 case ARM_CPUID_ARM926: 43 case ARM_CPUID_ARM926:
  44 + set_feature(env, ARM_FEATURE_V5);
41 set_feature(env, ARM_FEATURE_VFP); 45 set_feature(env, ARM_FEATURE_VFP);
  46 + set_feature(env, ARM_FEATURE_CP15);
42 env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090; 47 env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
43 env->cp15.c0_cachetype = 0x1dd20d2; 48 env->cp15.c0_cachetype = 0x1dd20d2;
44 env->cp15.c1_sys = 0x00090078; 49 env->cp15.c1_sys = 0x00090078;
45 break; 50 break;
46 case ARM_CPUID_ARM946: 51 case ARM_CPUID_ARM946:
  52 + set_feature(env, ARM_FEATURE_V5);
  53 + set_feature(env, ARM_FEATURE_CP15);
47 set_feature(env, ARM_FEATURE_MPU); 54 set_feature(env, ARM_FEATURE_MPU);
48 env->cp15.c0_cachetype = 0x0f004006; 55 env->cp15.c0_cachetype = 0x0f004006;
49 env->cp15.c1_sys = 0x00000078; 56 env->cp15.c1_sys = 0x00000078;
50 break; 57 break;
51 case ARM_CPUID_ARM1026: 58 case ARM_CPUID_ARM1026:
  59 + set_feature(env, ARM_FEATURE_V5);
52 set_feature(env, ARM_FEATURE_VFP); 60 set_feature(env, ARM_FEATURE_VFP);
  61 + set_feature(env, ARM_FEATURE_CP15);
53 set_feature(env, ARM_FEATURE_AUXCR); 62 set_feature(env, ARM_FEATURE_AUXCR);
54 env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0; 63 env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
55 env->cp15.c0_cachetype = 0x1dd20d2; 64 env->cp15.c0_cachetype = 0x1dd20d2;
@@ -57,8 +66,10 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) @@ -57,8 +66,10 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
57 break; 66 break;
58 case ARM_CPUID_ARM1136_R2: 67 case ARM_CPUID_ARM1136_R2:
59 case ARM_CPUID_ARM1136: 68 case ARM_CPUID_ARM1136:
  69 + set_feature(env, ARM_FEATURE_V5);
60 set_feature(env, ARM_FEATURE_V6); 70 set_feature(env, ARM_FEATURE_V6);
61 set_feature(env, ARM_FEATURE_VFP); 71 set_feature(env, ARM_FEATURE_VFP);
  72 + set_feature(env, ARM_FEATURE_CP15);
62 set_feature(env, ARM_FEATURE_AUXCR); 73 set_feature(env, ARM_FEATURE_AUXCR);
63 env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4; 74 env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4;
64 env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111; 75 env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111;
@@ -68,9 +79,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) @@ -68,9 +79,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
68 env->cp15.c0_cachetype = 0x1dd20d2; 79 env->cp15.c0_cachetype = 0x1dd20d2;
69 break; 80 break;
70 case ARM_CPUID_ARM11MPCORE: 81 case ARM_CPUID_ARM11MPCORE:
  82 + set_feature(env, ARM_FEATURE_V5);
71 set_feature(env, ARM_FEATURE_V6); 83 set_feature(env, ARM_FEATURE_V6);
72 set_feature(env, ARM_FEATURE_V6K); 84 set_feature(env, ARM_FEATURE_V6K);
73 set_feature(env, ARM_FEATURE_VFP); 85 set_feature(env, ARM_FEATURE_VFP);
  86 + set_feature(env, ARM_FEATURE_CP15);
74 set_feature(env, ARM_FEATURE_AUXCR); 87 set_feature(env, ARM_FEATURE_AUXCR);
75 env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4; 88 env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4;
76 env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111; 89 env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111;
@@ -80,9 +93,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) @@ -80,9 +93,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
80 env->cp15.c0_cachetype = 0x1dd20d2; 93 env->cp15.c0_cachetype = 0x1dd20d2;
81 break; 94 break;
82 case ARM_CPUID_CORTEXA8: 95 case ARM_CPUID_CORTEXA8:
  96 + set_feature(env, ARM_FEATURE_V5);
83 set_feature(env, ARM_FEATURE_V6); 97 set_feature(env, ARM_FEATURE_V6);
84 set_feature(env, ARM_FEATURE_V6K); 98 set_feature(env, ARM_FEATURE_V6K);
85 set_feature(env, ARM_FEATURE_V7); 99 set_feature(env, ARM_FEATURE_V7);
  100 + set_feature(env, ARM_FEATURE_CP15);
86 set_feature(env, ARM_FEATURE_AUXCR); 101 set_feature(env, ARM_FEATURE_AUXCR);
87 set_feature(env, ARM_FEATURE_THUMB2); 102 set_feature(env, ARM_FEATURE_THUMB2);
88 set_feature(env, ARM_FEATURE_VFP); 103 set_feature(env, ARM_FEATURE_VFP);
@@ -101,6 +116,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) @@ -101,6 +116,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
101 env->cp15.c0_ccsid[2] = 0xf0000000; /* No L2 icache. */ 116 env->cp15.c0_ccsid[2] = 0xf0000000; /* No L2 icache. */
102 break; 117 break;
103 case ARM_CPUID_CORTEXM3: 118 case ARM_CPUID_CORTEXM3:
  119 + set_feature(env, ARM_FEATURE_V5);
104 set_feature(env, ARM_FEATURE_V6); 120 set_feature(env, ARM_FEATURE_V6);
105 set_feature(env, ARM_FEATURE_THUMB2); 121 set_feature(env, ARM_FEATURE_THUMB2);
106 set_feature(env, ARM_FEATURE_V7); 122 set_feature(env, ARM_FEATURE_V7);
@@ -108,6 +124,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) @@ -108,6 +124,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
108 set_feature(env, ARM_FEATURE_DIV); 124 set_feature(env, ARM_FEATURE_DIV);
109 break; 125 break;
110 case ARM_CPUID_ANY: /* For userspace emulation. */ 126 case ARM_CPUID_ANY: /* For userspace emulation. */
  127 + set_feature(env, ARM_FEATURE_V5);
111 set_feature(env, ARM_FEATURE_V6); 128 set_feature(env, ARM_FEATURE_V6);
112 set_feature(env, ARM_FEATURE_V6K); 129 set_feature(env, ARM_FEATURE_V6K);
113 set_feature(env, ARM_FEATURE_V7); 130 set_feature(env, ARM_FEATURE_V7);
@@ -120,6 +137,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) @@ -120,6 +137,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
120 break; 137 break;
121 case ARM_CPUID_TI915T: 138 case ARM_CPUID_TI915T:
122 case ARM_CPUID_TI925T: 139 case ARM_CPUID_TI925T:
  140 + set_feature(env, ARM_FEATURE_V5);
  141 + set_feature(env, ARM_FEATURE_CP15);
123 set_feature(env, ARM_FEATURE_OMAPCP); 142 set_feature(env, ARM_FEATURE_OMAPCP);
124 env->cp15.c0_cpuid = ARM_CPUID_TI925T; /* Depends on wiring. */ 143 env->cp15.c0_cpuid = ARM_CPUID_TI925T; /* Depends on wiring. */
125 env->cp15.c0_cachetype = 0x5109149; 144 env->cp15.c0_cachetype = 0x5109149;
@@ -132,6 +151,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) @@ -132,6 +151,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
132 case ARM_CPUID_PXA260: 151 case ARM_CPUID_PXA260:
133 case ARM_CPUID_PXA261: 152 case ARM_CPUID_PXA261:
134 case ARM_CPUID_PXA262: 153 case ARM_CPUID_PXA262:
  154 + set_feature(env, ARM_FEATURE_V5);
  155 + set_feature(env, ARM_FEATURE_CP15);
135 set_feature(env, ARM_FEATURE_XSCALE); 156 set_feature(env, ARM_FEATURE_XSCALE);
136 /* JTAG_ID is ((id << 28) | 0x09265013) */ 157 /* JTAG_ID is ((id << 28) | 0x09265013) */
137 env->cp15.c0_cachetype = 0xd172172; 158 env->cp15.c0_cachetype = 0xd172172;
@@ -143,6 +164,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id) @@ -143,6 +164,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
143 case ARM_CPUID_PXA270_B1: 164 case ARM_CPUID_PXA270_B1:
144 case ARM_CPUID_PXA270_C0: 165 case ARM_CPUID_PXA270_C0:
145 case ARM_CPUID_PXA270_C5: 166 case ARM_CPUID_PXA270_C5:
  167 + set_feature(env, ARM_FEATURE_V5);
  168 + set_feature(env, ARM_FEATURE_CP15);
146 set_feature(env, ARM_FEATURE_XSCALE); 169 set_feature(env, ARM_FEATURE_XSCALE);
147 /* JTAG_ID is ((id << 28) | 0x09265013) */ 170 /* JTAG_ID is ((id << 28) | 0x09265013) */
148 set_feature(env, ARM_FEATURE_IWMMXT); 171 set_feature(env, ARM_FEATURE_IWMMXT);
@@ -277,6 +300,7 @@ struct arm_cpu_t { @@ -277,6 +300,7 @@ struct arm_cpu_t {
277 }; 300 };
278 301
279 static const struct arm_cpu_t arm_cpu_names[] = { 302 static const struct arm_cpu_t arm_cpu_names[] = {
  303 + { ARM_CPUID_ARM7TDMI, "arm7tdmi"},
280 { ARM_CPUID_ARM926, "arm926"}, 304 { ARM_CPUID_ARM926, "arm926"},
281 { ARM_CPUID_ARM946, "arm946"}, 305 { ARM_CPUID_ARM946, "arm946"},
282 { ARM_CPUID_ARM1026, "arm1026"}, 306 { ARM_CPUID_ARM1026, "arm1026"},
target-arm/translate.c
@@ -34,9 +34,10 @@ @@ -34,9 +34,10 @@
34 #define GEN_HELPER 1 34 #define GEN_HELPER 1
35 #include "helpers.h" 35 #include "helpers.h"
36 36
  37 +#define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5)
37 #define ENABLE_ARCH_5J 0 38 #define ENABLE_ARCH_5J 0
38 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6) 39 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
39 -#define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K) 40 +#define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
40 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2) 41 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
41 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7) 42 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
42 43
@@ -2587,8 +2588,10 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn) @@ -2587,8 +2588,10 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
2587 TCGv tmp; 2588 TCGv tmp;
2588 2589
2589 /* M profile cores use memory mapped registers instead of cp15. */ 2590 /* M profile cores use memory mapped registers instead of cp15. */
2590 - if (arm_feature(env, ARM_FEATURE_M))  
2591 - return 1; 2591 + if (arm_feature(env, ARM_FEATURE_M) ||
  2592 + !arm_feature(env, ARM_FEATURE_CP15)) {
  2593 + return 1;
  2594 + }
2592 2595
2593 if ((insn & (1 << 25)) == 0) { 2596 if ((insn & (1 << 25)) == 0) {
2594 if (insn & (1 << 20)) { 2597 if (insn & (1 << 20)) {
@@ -5745,9 +5748,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -5745,9 +5748,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
5745 goto illegal_op; 5748 goto illegal_op;
5746 return; 5749 return;
5747 } 5750 }
5748 - if ((insn & 0x0d70f000) == 0x0550f000) 5751 + if ((insn & 0x0d70f000) == 0x0550f000) {
  5752 + ARCH(5);
5749 return; /* PLD */ 5753 return; /* PLD */
5750 - else if ((insn & 0x0ffffdff) == 0x01010000) { 5754 + } else if ((insn & 0x0ffffdff) == 0x01010000) {
5751 ARCH(6); 5755 ARCH(6);
5752 /* setend */ 5756 /* setend */
5753 if (insn & (1 << 9)) { 5757 if (insn & (1 << 9)) {
@@ -5859,7 +5863,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -5859,7 +5863,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
5859 } else if ((insn & 0x0e000000) == 0x0a000000) { 5863 } else if ((insn & 0x0e000000) == 0x0a000000) {
5860 /* branch link and change to thumb (blx <offset>) */ 5864 /* branch link and change to thumb (blx <offset>) */
5861 int32_t offset; 5865 int32_t offset;
5862 - 5866 + ARCH(5);
5863 val = (uint32_t)s->pc; 5867 val = (uint32_t)s->pc;
5864 tmp = new_tmp(); 5868 tmp = new_tmp();
5865 tcg_gen_movi_i32(tmp, val); 5869 tcg_gen_movi_i32(tmp, val);
@@ -5881,8 +5885,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -5881,8 +5885,10 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
5881 } 5885 }
5882 } else if ((insn & 0x0fe00000) == 0x0c400000) { 5886 } else if ((insn & 0x0fe00000) == 0x0c400000) {
5883 /* Coprocessor double register transfer. */ 5887 /* Coprocessor double register transfer. */
  5888 + ARCH(5);
5884 } else if ((insn & 0x0f000010) == 0x0e000010) { 5889 } else if ((insn & 0x0f000010) == 0x0e000010) {
5885 /* Additional coprocessor register transfer. */ 5890 /* Additional coprocessor register transfer. */
  5891 + ARCH(5);
5886 } else if ((insn & 0x0ff10020) == 0x01000000) { 5892 } else if ((insn & 0x0ff10020) == 0x01000000) {
5887 uint32_t mask; 5893 uint32_t mask;
5888 uint32_t val; 5894 uint32_t val;
@@ -6008,7 +6014,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -6008,7 +6014,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
6008 case 0x3: 6014 case 0x3:
6009 if (op1 != 1) 6015 if (op1 != 1)
6010 goto illegal_op; 6016 goto illegal_op;
6011 - 6017 + ARCH(5);
6012 /* branch link/exchange thumb (blx) */ 6018 /* branch link/exchange thumb (blx) */
6013 tmp = load_reg(s, rm); 6019 tmp = load_reg(s, rm);
6014 tmp2 = new_tmp(); 6020 tmp2 = new_tmp();
@@ -6031,6 +6037,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -6031,6 +6037,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
6031 store_reg(s, rd, tmp); 6037 store_reg(s, rd, tmp);
6032 break; 6038 break;
6033 case 7: /* bkpt */ 6039 case 7: /* bkpt */
  6040 + ARCH(5);
6034 gen_set_condexec(s); 6041 gen_set_condexec(s);
6035 gen_set_pc_im(s->pc - 4); 6042 gen_set_pc_im(s->pc - 4);
6036 gen_exception(EXCP_BKPT); 6043 gen_exception(EXCP_BKPT);
@@ -6767,7 +6774,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -6767,7 +6774,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
6767 } 6774 }
6768 if (insn & (1 << 20)) { 6775 if (insn & (1 << 20)) {
6769 /* Complete the load. */ 6776 /* Complete the load. */
6770 - if (rd == 15) 6777 + if (rd == 15 && ENABLE_ARCH_5)
6771 gen_bx(s, tmp); 6778 gen_bx(s, tmp);
6772 else 6779 else
6773 store_reg(s, rd, tmp); 6780 store_reg(s, rd, tmp);
@@ -6777,6 +6784,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -6777,6 +6784,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
6777 case 0x09: 6784 case 0x09:
6778 { 6785 {
6779 int j, n, user, loaded_base; 6786 int j, n, user, loaded_base;
  6787 + int crement = 0;
6780 TCGv loaded_var; 6788 TCGv loaded_var;
6781 /* load/store multiple words */ 6789 /* load/store multiple words */
6782 /* XXX: store correct base if write back */ 6790 /* XXX: store correct base if write back */
@@ -6817,6 +6825,38 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -6817,6 +6825,38 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
6817 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4)); 6825 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
6818 } 6826 }
6819 } 6827 }
  6828 +
  6829 + if (insn & (1 << 21)) {
  6830 + /* write back */
  6831 + if (insn & (1 << 23)) {
  6832 + if (insn & (1 << 24)) {
  6833 + /* pre increment */
  6834 + } else {
  6835 + /* post increment */
  6836 + crement = 4;
  6837 + }
  6838 + } else {
  6839 + if (insn & (1 << 24)) {
  6840 + /* pre decrement */
  6841 + if (n != 1) {
  6842 + crement = -((n - 1) * 4);
  6843 + }
  6844 + } else {
  6845 + /* post decrement */
  6846 + crement = -(n * 4);
  6847 + }
  6848 + }
  6849 + if (arm_feature(env, ARM_FEATURE_ABORT_BU)) {
  6850 + /* base-updated abort model: update base register
  6851 + before an abort can happen */
  6852 + crement += (n - 1) * 4;
  6853 + tmp = new_tmp();
  6854 + tcg_gen_addi_i32(tmp, addr, crement);
  6855 + store_reg(s, rn, tmp);
  6856 + }
  6857 +
  6858 + }
  6859 +
6820 j = 0; 6860 j = 0;
6821 for(i=0;i<16;i++) { 6861 for(i=0;i<16;i++) {
6822 if (insn & (1 << i)) { 6862 if (insn & (1 << i)) {
@@ -6824,7 +6864,11 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -6824,7 +6864,11 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
6824 /* load */ 6864 /* load */
6825 tmp = gen_ld32(addr, IS_USER(s)); 6865 tmp = gen_ld32(addr, IS_USER(s));
6826 if (i == 15) { 6866 if (i == 15) {
6827 - gen_bx(s, tmp); 6867 + if (ENABLE_ARCH_5) {
  6868 + gen_bx(s, tmp);
  6869 + } else {
  6870 + store_reg(s, i, tmp);
  6871 + }
6828 } else if (user) { 6872 } else if (user) {
6829 gen_helper_set_user_reg(tcg_const_i32(i), tmp); 6873 gen_helper_set_user_reg(tcg_const_i32(i), tmp);
6830 dead_tmp(tmp); 6874 dead_tmp(tmp);
@@ -6855,25 +6899,8 @@ static void disas_arm_insn(CPUState * env, DisasContext *s) @@ -6855,25 +6899,8 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
6855 tcg_gen_addi_i32(addr, addr, 4); 6899 tcg_gen_addi_i32(addr, addr, 4);
6856 } 6900 }
6857 } 6901 }
6858 - if (insn & (1 << 21)) {  
6859 - /* write back */  
6860 - if (insn & (1 << 23)) {  
6861 - if (insn & (1 << 24)) {  
6862 - /* pre increment */  
6863 - } else {  
6864 - /* post increment */  
6865 - tcg_gen_addi_i32(addr, addr, 4);  
6866 - }  
6867 - } else {  
6868 - if (insn & (1 << 24)) {  
6869 - /* pre decrement */  
6870 - if (n != 1)  
6871 - tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));  
6872 - } else {  
6873 - /* post decrement */  
6874 - tcg_gen_addi_i32(addr, addr, -(n * 4));  
6875 - }  
6876 - } 6902 + if (!arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << 21))) {
  6903 + tcg_gen_addi_i32(addr, addr, crement);
6877 store_reg(s, rn, addr); 6904 store_reg(s, rn, addr);
6878 } else { 6905 } else {
6879 dead_tmp(addr); 6906 dead_tmp(addr);
@@ -7034,6 +7061,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) @@ -7034,6 +7061,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7034 16-bit instructions to get correct prefetch abort behavior. */ 7061 16-bit instructions to get correct prefetch abort behavior. */
7035 insn = insn_hw1; 7062 insn = insn_hw1;
7036 if ((insn & (1 << 12)) == 0) { 7063 if ((insn & (1 << 12)) == 0) {
  7064 + ARCH(5);
7037 /* Second half of blx. */ 7065 /* Second half of blx. */
7038 offset = ((insn & 0x7ff) << 1); 7066 offset = ((insn & 0x7ff) << 1);
7039 tmp = load_reg(s, 14); 7067 tmp = load_reg(s, 14);
@@ -7091,6 +7119,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) @@ -7091,6 +7119,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7091 /* Other load/store, table branch. */ 7119 /* Other load/store, table branch. */
7092 if (insn & 0x01200000) { 7120 if (insn & 0x01200000) {
7093 /* Load/store doubleword. */ 7121 /* Load/store doubleword. */
  7122 + ARCH(5);
7094 if (rn == 15) { 7123 if (rn == 15) {
7095 addr = new_tmp(); 7124 addr = new_tmp();
7096 tcg_gen_movi_i32(addr, s->pc & ~3); 7125 tcg_gen_movi_i32(addr, s->pc & ~3);
@@ -7304,7 +7333,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) @@ -7304,7 +7333,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7304 if (insn & (1 << 20)) { 7333 if (insn & (1 << 20)) {
7305 /* Load. */ 7334 /* Load. */
7306 tmp = gen_ld32(addr, IS_USER(s)); 7335 tmp = gen_ld32(addr, IS_USER(s));
7307 - if (i == 15) { 7336 + if (i == 15 && ENABLE_ARCH_5) {
7308 gen_bx(s, tmp); 7337 gen_bx(s, tmp);
7309 } else { 7338 } else {
7310 store_reg(s, i, tmp); 7339 store_reg(s, i, tmp);
@@ -7643,6 +7672,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) @@ -7643,6 +7672,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7643 gen_jmp(s, offset); 7672 gen_jmp(s, offset);
7644 } else { 7673 } else {
7645 /* blx */ 7674 /* blx */
  7675 + ARCH(5);
7646 offset &= ~(uint32_t)2; 7676 offset &= ~(uint32_t)2;
7647 gen_bx_im(s, offset); 7677 gen_bx_im(s, offset);
7648 } 7678 }
@@ -7998,7 +8028,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1) @@ -7998,7 +8028,7 @@ static int disas_thumb2_insn(CPUState *env, DisasContext *s, uint16_t insn_hw1)
7998 case 2: tmp = gen_ld32(addr, user); break; 8028 case 2: tmp = gen_ld32(addr, user); break;
7999 default: goto illegal_op; 8029 default: goto illegal_op;
8000 } 8030 }
8001 - if (rs == 15) { 8031 + if (rs == 15 && ENABLE_ARCH_5) {
8002 gen_bx(s, tmp); 8032 gen_bx(s, tmp);
8003 } else { 8033 } else {
8004 store_reg(s, rs, tmp); 8034 store_reg(s, rs, tmp);
@@ -8041,6 +8071,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) @@ -8041,6 +8071,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
8041 TCGv tmp; 8071 TCGv tmp;
8042 TCGv tmp2; 8072 TCGv tmp2;
8043 TCGv addr; 8073 TCGv addr;
  8074 + int crement;
8044 8075
8045 if (s->condexec_mask) { 8076 if (s->condexec_mask) {
8046 cond = s->condexec_cond; 8077 cond = s->condexec_cond;
@@ -8162,6 +8193,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) @@ -8162,6 +8193,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
8162 case 3:/* branch [and link] exchange thumb register */ 8193 case 3:/* branch [and link] exchange thumb register */
8163 tmp = load_reg(s, rm); 8194 tmp = load_reg(s, rm);
8164 if (insn & (1 << 7)) { 8195 if (insn & (1 << 7)) {
  8196 + ARCH(5);
8165 val = (uint32_t)s->pc | 1; 8197 val = (uint32_t)s->pc | 1;
8166 tmp2 = new_tmp(); 8198 tmp2 = new_tmp();
8167 tcg_gen_movi_i32(tmp2, val); 8199 tcg_gen_movi_i32(tmp2, val);
@@ -8514,8 +8546,13 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) @@ -8514,8 +8546,13 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
8514 /* write back the new stack pointer */ 8546 /* write back the new stack pointer */
8515 store_reg(s, 13, addr); 8547 store_reg(s, 13, addr);
8516 /* set the new PC value */ 8548 /* set the new PC value */
8517 - if ((insn & 0x0900) == 0x0900)  
8518 - gen_bx(s, tmp); 8549 + if ((insn & 0x0900) == 0x0900) {
  8550 + if (ENABLE_ARCH_5) {
  8551 + gen_bx(s, tmp);
  8552 + } else {
  8553 + store_reg(s, 15, tmp);
  8554 + }
  8555 + }
8519 break; 8556 break;
8520 8557
8521 case 1: case 3: case 9: case 11: /* czb */ 8558 case 1: case 3: case 9: case 11: /* czb */
@@ -8604,6 +8641,19 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) @@ -8604,6 +8641,19 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
8604 /* load/store multiple */ 8641 /* load/store multiple */
8605 rn = (insn >> 8) & 0x7; 8642 rn = (insn >> 8) & 0x7;
8606 addr = load_reg(s, rn); 8643 addr = load_reg(s, rn);
  8644 + if (arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << rn)) == 0) {
  8645 + /* base-updated abort model: update base register
  8646 + before an abort can happen */
  8647 + crement = 0;
  8648 + for (i = 0; i < 8; i++) {
  8649 + if (insn & (1 << i)) {
  8650 + crement += 4;
  8651 + }
  8652 + }
  8653 + tmp = new_tmp();
  8654 + tcg_gen_addi_i32(tmp, addr, crement);
  8655 + store_reg(s, rn, tmp);
  8656 + }
8607 for (i = 0; i < 8; i++) { 8657 for (i = 0; i < 8; i++) {
8608 if (insn & (1 << i)) { 8658 if (insn & (1 << i)) {
8609 if (insn & (1 << 11)) { 8659 if (insn & (1 << 11)) {
@@ -8620,7 +8670,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s) @@ -8620,7 +8670,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
8620 } 8670 }
8621 } 8671 }
8622 /* Base register writeback. */ 8672 /* Base register writeback. */
8623 - if ((insn & (1 << rn)) == 0) { 8673 + if (!arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << rn)) == 0) {
8624 store_reg(s, rn, addr); 8674 store_reg(s, rn, addr);
8625 } else { 8675 } else {
8626 dead_tmp(addr); 8676 dead_tmp(addr);