On Monday 02 July 2007 18:14, Ulrich Hecht wrote:
> Anyway, here's the 920T version. The magic numbers may or may not be
> correct.

And here's an even better version that implements both 920T and 7TDMI 
(with base-updated aborts).

CU
Uli

-- 
SUSE LINUX Products GmbH, GF: Markus Rex, HRB 16746 (AG Nürnberg)
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);
 

Reply via email to