Index: target-arm/cpu.h =================================================================== RCS file: /sources/qemu/qemu/target-arm/cpu.h,v retrieving revision 1.28 diff -u -r1.28 cpu.h --- target-arm/cpu.h 24 Jun 2007 12:09:48 -0000 1.28 +++ target-arm/cpu.h 3 Jul 2007 14:36:00 -0000 @@ -247,7 +247,10 @@ ARM_FEATURE_AUXCR, /* ARM1026 Auxiliary control register. */ ARM_FEATURE_XSCALE, /* Intel XScale extensions. */ ARM_FEATURE_IWMMXT, /* Intel iwMMXt extension. */ - ARM_FEATURE_MPU /* Only has Memory Protection Unit, not full MMU. */ + ARM_FEATURE_MPU, /* Only has Memory Protection Unit, not full MMU. */ + ARM_FEATURE_V5, /* ARM v5 instruction set */ + ARM_FEATURE_NO_CP15, /* ARM7TDMI, ARM7TDMI-S, ARM7EJ-S, and ARM9TDMI cores do not have a CP15 */ + ARM_FEATURE_ABORT_BU /* base updated abort model, e.g. ARMxTDMI */ }; static inline int arm_feature(CPUARMState *env, int feature) @@ -262,7 +265,9 @@ ARMReadCPFunc *cp_read, ARMWriteCPFunc *cp_write, void *opaque); +#define ARM_CPUID_ARM7TDMI 0x41807000 /* guess; no CP15 on ARM7TDMI */ #define ARM_CPUID_ARM1026 0x4106a262 +#define ARM_CPUID_ARM920T 0x41129200 #define ARM_CPUID_ARM926 0x41069265 #define ARM_CPUID_ARM946 0x41059461 #define ARM_CPUID_PXA250 0x69052100 Index: target-arm/helper.c =================================================================== RCS file: /sources/qemu/qemu/target-arm/helper.c,v retrieving revision 1.17 diff -u -r1.17 helper.c --- target-arm/helper.c 24 Jun 2007 12:09:48 -0000 1.17 +++ target-arm/helper.c 3 Jul 2007 14:36:00 -0000 @@ -14,20 +14,31 @@ { env->cp15.c0_cpuid = id; switch (id) { + case ARM_CPUID_ARM7TDMI: + set_feature(env, ARM_FEATURE_ABORT_BU); + set_feature(env, ARM_FEATURE_NO_CP15); + break; + case ARM_CPUID_ARM920T: + env->cp15.c0_cachetype = 0x0d172172; + env->cp15.c1_sys = 0x00000078; + break; case ARM_CPUID_ARM926: set_feature(env, ARM_FEATURE_VFP); + set_feature(env, ARM_FEATURE_V5); env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090; env->cp15.c0_cachetype = 0x1dd20d2; env->cp15.c1_sys = 0x00090078; break; case ARM_CPUID_ARM946: set_feature(env, ARM_FEATURE_MPU); + set_feature(env, ARM_FEATURE_V5); env->cp15.c0_cachetype = 0x0f004006; env->cp15.c1_sys = 0x00000078; break; case ARM_CPUID_ARM1026: set_feature(env, ARM_FEATURE_VFP); set_feature(env, ARM_FEATURE_AUXCR); + set_feature(env, ARM_FEATURE_V5); env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0; env->cp15.c0_cachetype = 0x1dd20d2; env->cp15.c1_sys = 0x00090078; @@ -38,6 +49,7 @@ case ARM_CPUID_PXA261: case ARM_CPUID_PXA262: set_feature(env, ARM_FEATURE_XSCALE); + set_feature(env, ARM_FEATURE_V5); /* JTAG_ID is ((id << 28) | 0x09265013) */ env->cp15.c0_cachetype = 0xd172172; env->cp15.c1_sys = 0x00000078; @@ -49,6 +61,7 @@ case ARM_CPUID_PXA270_C0: case ARM_CPUID_PXA270_C5: set_feature(env, ARM_FEATURE_XSCALE); + set_feature(env, ARM_FEATURE_V5); /* JTAG_ID is ((id << 28) | 0x09265013) */ set_feature(env, ARM_FEATURE_IWMMXT); env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q'; @@ -98,6 +111,8 @@ }; static const struct arm_cpu_t arm_cpu_names[] = { + { ARM_CPUID_ARM7TDMI, "arm7tdmi"}, + { ARM_CPUID_ARM920T, "arm920t"}, { ARM_CPUID_ARM926, "arm926"}, { ARM_CPUID_ARM946, "arm946"}, { ARM_CPUID_ARM1026, "arm1026"}, Index: target-arm/translate.c =================================================================== RCS file: /sources/qemu/qemu/target-arm/translate.c,v retrieving revision 1.53 diff -u -r1.53 translate.c --- target-arm/translate.c 11 Jun 2007 18:59:35 -0000 1.53 +++ target-arm/translate.c 3 Jul 2007 14:36:00 -0000 @@ -1589,7 +1589,7 @@ uint32_t rd; /* ??? Some cp15 registers are accessible from userspace. */ - if (IS_USER(s)) { + if (IS_USER(s) || arm_feature(env, ARM_FEATURE_NO_CP15)) { return 1; } if ((insn & 0x0fff0fff) == 0x0e070f90 @@ -2780,6 +2780,7 @@ case 0x09: { int j, n, user, loaded_base; + int crement; /* load/store multiple words */ /* XXX: store correct base if write back */ user = 0; @@ -2819,6 +2820,36 @@ } } j = 0; + + crement = 0; + if(insn & (1 << 21)) { + /* write back */ + if(insn & (1 << 23)) { + if(insn & (1 << 24)) { + /* pre increment */ + } else { + /* post increment */ + crement += 4; + } + } else { + if(insn & (1 << 24)) { + /* pre decrement */ + if(n!=1) crement -= (n-1)*4; + } else { + /* post decrement */ + crement -= n*4; + } + } + if(arm_feature(env, ARM_FEATURE_ABORT_BU)) { + /* base-updated abort model: update base register + before an abort can happen */ + crement += (n - 1) * 4; + gen_op_addl_T1_im(crement); + gen_movl_reg_T1(s, rn); + gen_op_addl_T1_im(-crement); + } + } + for(i=0;i<16;i++) { if (insn & (1 << i)) { if (insn & (1 << 20)) { @@ -2853,25 +2884,10 @@ gen_op_addl_T1_im(4); } } - if (insn & (1 << 21)) { - /* write back */ - if (insn & (1 << 23)) { - if (insn & (1 << 24)) { - /* pre increment */ - } else { - /* post increment */ - gen_op_addl_T1_im(4); - } - } else { - if (insn & (1 << 24)) { - /* pre decrement */ - if (n != 1) - gen_op_addl_T1_im(-((n - 1) * 4)); - } else { - /* post decrement */ - gen_op_addl_T1_im(-(n * 4)); - } - } + if(!loaded_base && (insn & (1 << 21)) && !arm_feature(env, ARM_FEATURE_ABORT_BU)) { + /* base-restored abort model: only update base register + after all memory accesses went through */ + gen_op_addl_T1_im(crement); gen_movl_reg_T1(s, rn); } if (loaded_base) { @@ -2958,11 +2974,12 @@ } } -static void disas_thumb_insn(DisasContext *s) +static void disas_thumb_insn(CPUState *env, DisasContext *s) { uint32_t val, insn, op, rm, rn, rd, shift, cond; int32_t offset; int i; + int crement; insn = lduw_code(s->pc); s->pc += 2; @@ -3058,6 +3075,7 @@ break; case 3:/* branch [and link] exchange thumb register */ if (insn & (1 << 7)) { + if(!arm_feature(env, ARM_FEATURE_V5)) goto undef; val = (uint32_t)s->pc | 1; gen_op_movl_T1_im(val); gen_movl_reg_T1(s, 14); @@ -3367,11 +3385,16 @@ /* write back the new stack pointer */ gen_movl_reg_T1(s, 13); /* set the new PC value */ - if ((insn & 0x0900) == 0x0900) - gen_bx(s); + if ((insn & 0x0900) == 0x0900) { + if(!arm_feature(env, ARM_FEATURE_V5)) + gen_movl_reg_T0(s, 15); + else + gen_bx(s); + } break; case 0xe: /* bkpt */ + if(!arm_feature(env, ARM_FEATURE_V5)) goto undef; gen_op_movl_T0_im((long)s->pc - 2); gen_op_movl_reg_TN[0][15](); gen_op_bkpt(); @@ -3387,6 +3410,17 @@ /* load/store multiple */ rn = (insn >> 8) & 0x7; gen_movl_T1_reg(s, rn); + crement = 0; + for (i = 0; i < 8; i++) { + if (insn & (1 << i)) crement += 4; + } + if(arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << rn)) == 0) { + /* base-updated abort model: update base register + before an abort can happen */ + gen_op_addl_T1_im(crement); + gen_movl_reg_T1(s, rn); + gen_op_addl_T1_im(-crement); + } gen_op_movl_T2_im(4); for (i = 0; i < 8; i++) { if (insn & (1 << i)) { @@ -3403,8 +3437,8 @@ gen_op_addl_T1_T2(); } } - /* Base register writeback. */ - if ((insn & (1 << rn)) == 0) + /* Base register writeback, base-restored abort model */ + if (!arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << rn)) == 0) gen_movl_reg_T1(s, rn); break; @@ -3442,6 +3476,7 @@ /* unconditional branch */ if (insn & (1 << 11)) { /* Second half of blx. */ + if(!arm_feature(env, ARM_FEATURE_V5)) goto undef; offset = ((insn & 0x7ff) << 1); gen_movl_T0_reg(s, 14); gen_op_movl_T1_im(offset); @@ -3571,7 +3606,7 @@ } if (env->thumb) - disas_thumb_insn(dc); + disas_thumb_insn(env, dc); else disas_arm_insn(env, dc);