qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Filip Navara <filip.navara@gmail.com>
To: qemu-devel@nongnu.org
Cc: paul@codesourcery.com
Subject: Re: [Qemu-devel] [PATCH] ARM7TDMI emulation
Date: Mon, 15 Jun 2009 21:11:37 +0200	[thread overview]
Message-ID: <5b31733c0906151211o1c95245ay38f2d09c123ea0c9@mail.gmail.com> (raw)
In-Reply-To: <200707031645.51832.uli@suse.de>


[-- Attachment #1.1: Type: text/plain, Size: 731 bytes --]

On Tue, Jul 3, 2007 at 4:45 PM, Ulrich Hecht <uli@suse.de> wrote:

> 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)
>

Hello,

this is a rewritten version of the original patch to work on the latest qemu
git. Anything that needs to be done to get this merged?

ARM7TDMI emulation (ignore bit 0 on POP PC, no BLX, no CP15, base-updated
data aborts).
Based on patch by Ulrich Hecht <uli@suse.de>.

Best regards,
Filip Navara

[-- Attachment #1.2: Type: text/html, Size: 1232 bytes --]

[-- Attachment #2: 0001-ARM7TDMI-emulation-ignore-bit-0-on-POP-PC-no-BLX-no-.patch --]
[-- Type: application/octet-stream, Size: 13064 bytes --]

From b49a01d876d65d9ef456ebbcd8ac219e6d49ab0a Mon Sep 17 00:00:00 2001
From: Filip Navara <filip.navara@gmail.com>
Date: Mon, 15 Jun 2009 21:05:19 +0200
Subject: [PATCH] ARM7TDMI emulation (ignore bit 0 on POP PC, no BLX, no CP15, base-updated data aborts).
 Based on patch by Ulrich Hecht <uli@suse.de>.

---
 target-arm/cpu.h       |    6 +++-
 target-arm/helper.c    |   24 +++++++++++++
 target-arm/translate.c |   87 ++++++++++++++++++++++++++++++++++-------------
 3 files changed, 92 insertions(+), 25 deletions(-)

diff --git a/target-arm/cpu.h b/target-arm/cpu.h
index f98655f..d004777 100644
--- a/target-arm/cpu.h
+++ b/target-arm/cpu.h
@@ -331,6 +331,7 @@ enum arm_features {
     ARM_FEATURE_AUXCR,  /* ARM1026 Auxiliary control register.  */
     ARM_FEATURE_XSCALE, /* Intel XScale extensions.  */
     ARM_FEATURE_IWMMXT, /* Intel iwMMXt extension.  */
+    ARM_FEATURE_V5,
     ARM_FEATURE_V6,
     ARM_FEATURE_V6K,
     ARM_FEATURE_V7,
@@ -341,7 +342,9 @@ enum arm_features {
     ARM_FEATURE_DIV,
     ARM_FEATURE_M, /* Microcontroller profile.  */
     ARM_FEATURE_OMAPCP, /* OMAP specific CP15 ops handling.  */
-    ARM_FEATURE_THUMB2EE
+    ARM_FEATURE_THUMB2EE,
+    ARM_FEATURE_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)
@@ -367,6 +370,7 @@ void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
 #define IS_M(env) arm_feature(env, ARM_FEATURE_M)
 #define ARM_CPUID(env) (env->cp15.c0_cpuid)
 
+#define ARM_CPUID_ARM7TDMI    0x41807000 /* guess; no CP15 on ARM7TDMI */
 #define ARM_CPUID_ARM1026     0x4106a262
 #define ARM_CPUID_ARM926      0x41069265
 #define ARM_CPUID_ARM946      0x41059461
diff --git a/target-arm/helper.c b/target-arm/helper.c
index 701629a..38875d4 100644
--- a/target-arm/helper.c
+++ b/target-arm/helper.c
@@ -37,19 +37,28 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
 {
     env->cp15.c0_cpuid = id;
     switch (id) {
+    case ARM_CPUID_ARM7TDMI:
+        set_feature(env, ARM_FEATURE_ABORT_BU);
+        break;
     case ARM_CPUID_ARM926:
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_VFP);
+        set_feature(env, ARM_FEATURE_CP15);
         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_V5);
+        set_feature(env, ARM_FEATURE_CP15);
         set_feature(env, ARM_FEATURE_MPU);
         env->cp15.c0_cachetype = 0x0f004006;
         env->cp15.c1_sys = 0x00000078;
         break;
     case ARM_CPUID_ARM1026:
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_VFP);
+        set_feature(env, ARM_FEATURE_CP15);
         set_feature(env, ARM_FEATURE_AUXCR);
         env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
         env->cp15.c0_cachetype = 0x1dd20d2;
@@ -57,8 +66,10 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         break;
     case ARM_CPUID_ARM1136_R2:
     case ARM_CPUID_ARM1136:
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_VFP);
+        set_feature(env, ARM_FEATURE_CP15);
         set_feature(env, ARM_FEATURE_AUXCR);
         env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4;
         env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111;
@@ -68,9 +79,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c0_cachetype = 0x1dd20d2;
         break;
     case ARM_CPUID_ARM11MPCORE:
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_VFP);
+        set_feature(env, ARM_FEATURE_CP15);
         set_feature(env, ARM_FEATURE_AUXCR);
         env->vfp.xregs[ARM_VFP_FPSID] = 0x410120b4;
         env->vfp.xregs[ARM_VFP_MVFR0] = 0x11111111;
@@ -80,9 +93,11 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c0_cachetype = 0x1dd20d2;
         break;
     case ARM_CPUID_CORTEXA8:
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_V7);
+        set_feature(env, ARM_FEATURE_CP15);
         set_feature(env, ARM_FEATURE_AUXCR);
         set_feature(env, ARM_FEATURE_THUMB2);
         set_feature(env, ARM_FEATURE_VFP);
@@ -101,6 +116,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         env->cp15.c0_ccsid[2] = 0xf0000000; /* No L2 icache. */
         break;
     case ARM_CPUID_CORTEXM3:
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_THUMB2);
         set_feature(env, ARM_FEATURE_V7);
@@ -108,6 +124,7 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         set_feature(env, ARM_FEATURE_DIV);
         break;
     case ARM_CPUID_ANY: /* For userspace emulation.  */
+        set_feature(env, ARM_FEATURE_V5);
         set_feature(env, ARM_FEATURE_V6);
         set_feature(env, ARM_FEATURE_V6K);
         set_feature(env, ARM_FEATURE_V7);
@@ -120,6 +137,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
         break;
     case ARM_CPUID_TI915T:
     case ARM_CPUID_TI925T:
+        set_feature(env, ARM_FEATURE_V5);
+        set_feature(env, ARM_FEATURE_CP15);
         set_feature(env, ARM_FEATURE_OMAPCP);
         env->cp15.c0_cpuid = ARM_CPUID_TI925T; /* Depends on wiring.  */
         env->cp15.c0_cachetype = 0x5109149;
@@ -132,6 +151,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     case ARM_CPUID_PXA260:
     case ARM_CPUID_PXA261:
     case ARM_CPUID_PXA262:
+        set_feature(env, ARM_FEATURE_V5);
+        set_feature(env, ARM_FEATURE_CP15);
         set_feature(env, ARM_FEATURE_XSCALE);
         /* JTAG_ID is ((id << 28) | 0x09265013) */
         env->cp15.c0_cachetype = 0xd172172;
@@ -143,6 +164,8 @@ static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
     case ARM_CPUID_PXA270_B1:
     case ARM_CPUID_PXA270_C0:
     case ARM_CPUID_PXA270_C5:
+        set_feature(env, ARM_FEATURE_V5);
+        set_feature(env, ARM_FEATURE_CP15);
         set_feature(env, ARM_FEATURE_XSCALE);
         /* JTAG_ID is ((id << 28) | 0x09265013) */
         set_feature(env, ARM_FEATURE_IWMMXT);
@@ -277,6 +300,7 @@ struct arm_cpu_t {
 };
 
 static const struct arm_cpu_t arm_cpu_names[] = {
+    { ARM_CPUID_ARM7TDMI, "arm7tdmi"},
     { ARM_CPUID_ARM926, "arm926"},
     { ARM_CPUID_ARM946, "arm946"},
     { ARM_CPUID_ARM1026, "arm1026"},
diff --git a/target-arm/translate.c b/target-arm/translate.c
index adac19a..c1d908c 100644
--- a/target-arm/translate.c
+++ b/target-arm/translate.c
@@ -2596,8 +2596,10 @@ static int disas_cp15_insn(CPUState *env, DisasContext *s, uint32_t insn)
     TCGv tmp;
 
     /* M profile cores use memory mapped registers instead of cp15.  */
-    if (arm_feature(env, ARM_FEATURE_M))
-	return 1;
+    if (arm_feature(env, ARM_FEATURE_M) ||
+        !arm_feature(env, ARM_FEATURE_CP15)) {
+	    return 1;
+    }
 
     if ((insn & (1 << 25)) == 0) {
         if (insn & (1 << 20)) {
@@ -6786,6 +6788,7 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
         case 0x09:
             {
                 int j, n, user, loaded_base;
+                int crement = 0;
                 TCGv loaded_var;
                 /* load/store multiple words */
                 /* XXX: store correct base if write back */
@@ -6826,6 +6829,37 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                         tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
                     }
                 }
+
+                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;
+                        tmp = new_tmp();
+                        tcg_gen_addi_i32(tmp, addr, crement);
+                        store_reg(s, rn, tmp);
+                    }
+                }
+
                 j = 0;
                 for(i=0;i<16;i++) {
                     if (insn & (1 << i)) {
@@ -6864,25 +6898,8 @@ static void disas_arm_insn(CPUState * env, DisasContext *s)
                             tcg_gen_addi_i32(addr, addr, 4);
                     }
                 }
-                if (insn & (1 << 21)) {
-                    /* write back */
-                    if (insn & (1 << 23)) {
-                        if (insn & (1 << 24)) {
-                            /* pre increment */
-                        } else {
-                            /* post increment */
-                            tcg_gen_addi_i32(addr, addr, 4);
-                        }
-                    } else {
-                        if (insn & (1 << 24)) {
-                            /* pre decrement */
-                            if (n != 1)
-                                tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
-                        } else {
-                            /* post decrement */
-                            tcg_gen_addi_i32(addr, addr, -(n * 4));
-                        }
-                    }
+                if (!arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << 21))) {
+                    tcg_gen_addi_i32(addr, addr, crement);
                     store_reg(s, rn, addr);
                 } else {
                     dead_tmp(addr);
@@ -8050,6 +8067,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
     TCGv tmp;
     TCGv tmp2;
     TCGv addr;
+    int crement;
 
     if (s->condexec_mask) {
         cond = s->condexec_cond;
@@ -8171,6 +8189,9 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
             case 3:/* branch [and link] exchange thumb register */
                 tmp = load_reg(s, rm);
                 if (insn & (1 << 7)) {
+                    if (!arm_feature(env, ARM_FEATURE_V5)) {
+                        goto undef;
+                    }
                     val = (uint32_t)s->pc | 1;
                     tmp2 = new_tmp();
                     tcg_gen_movi_i32(tmp2, val);
@@ -8523,8 +8544,13 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
             /* write back the new stack pointer */
             store_reg(s, 13, addr);
             /* set the new PC value */
-            if ((insn & 0x0900) == 0x0900)
-                gen_bx(s, tmp);
+            if ((insn & 0x0900) == 0x0900) {
+                if (!arm_feature(env, ARM_FEATURE_V5)) {
+                    store_cpu_field(tmp, regs[15]);
+                } else {
+                    gen_bx(s, tmp);
+                }
+            }
             break;
 
         case 1: case 3: case 9: case 11: /* czb */
@@ -8613,6 +8639,19 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
         /* load/store multiple */
         rn = (insn >> 8) & 0x7;
         addr = load_reg(s, rn);
+        if (arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << rn)) == 0) {
+            /* base-updated abort model: update base register
+               before an abort can happen */
+            crement = 0;
+            for (i = 0; i < 8; i++) {
+                if (insn & (1 << i)) {
+                    crement += 4;
+                }
+            }
+            tmp = new_tmp();
+            tcg_gen_addi_i32(tmp, addr, crement);
+            store_reg(s, rn, tmp);
+        }
         for (i = 0; i < 8; i++) {
             if (insn & (1 << i)) {
                 if (insn & (1 << 11)) {
@@ -8629,7 +8668,7 @@ static void disas_thumb_insn(CPUState *env, DisasContext *s)
             }
         }
         /* Base register writeback.  */
-        if ((insn & (1 << rn)) == 0) {
+        if (!arm_feature(env, ARM_FEATURE_ABORT_BU) && (insn & (1 << rn)) == 0) {
             store_reg(s, rn, addr);
         } else {
             dead_tmp(addr);
-- 
1.6.3.msysgit.0


  reply	other threads:[~2009-06-15 19:11 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2007-07-02 13:27 [Qemu-devel] [PATCH] ARM7TDMI emulation Ulrich Hecht
2007-07-02 13:40 ` Paul Brook
2007-07-02 16:14   ` Ulrich Hecht
2007-07-03 14:45     ` Ulrich Hecht
2009-06-15 19:11       ` Filip Navara [this message]
2009-06-16 17:25         ` Paul Brook
2009-06-16 19:02           ` Jamie Lokier
2009-06-16 19:05             ` Paul Brook
2009-06-16 20:49             ` Filip Navara
2009-06-16 21:47               ` Filip Navara
2009-06-17  9:55               ` Filip Navara
2009-06-17 10:24                 ` Filip Navara
  -- strict thread matches above, loose matches on Subject: below --
2009-07-15 12:08 Filip Navara

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5b31733c0906151211o1c95245ay38f2d09c123ea0c9@mail.gmail.com \
    --to=filip.navara@gmail.com \
    --cc=paul@codesourcery.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).