Add Arm926 core support.
authorpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 20 Feb 2006 00:33:36 +0000 (00:33 +0000)
committerpbrook <pbrook@c046a42c-6fe2-441c-8c8c-71466251a162>
Mon, 20 Feb 2006 00:33:36 +0000 (00:33 +0000)
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1765 c046a42c-6fe2-441c-8c8c-71466251a162

cpu-exec.c
hw/integratorcp.c
linux-user/main.c
target-arm/cpu.h
target-arm/helper.c
target-arm/op.c
target-arm/op_helper.c
target-arm/translate.c
vl.c
vl.h

index 3bf4b37..3a537fc 100644 (file)
@@ -169,6 +169,8 @@ static inline TranslationBlock *tb_find_fast(void)
             | (env->vfp.vec_stride << 4);
     if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
         flags |= (1 << 6);
+    if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
+        flags |= (1 << 7);
     cs_base = 0;
     pc = env->regs[15];
 #elif defined(TARGET_SPARC)
index 8f91b58..db73efd 100644 (file)
@@ -1173,7 +1173,7 @@ static void set_kernel_args(uint32_t ram_size, int initrd_size,
 static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device,
                      DisplayState *ds, const char **fd_filename, int snapshot,
                      const char *kernel_filename, const char *kernel_cmdline,
-                     const char *initrd_filename)
+                     const char *initrd_filename, uint32_t cpuid)
 {
     CPUState *env;
     uint32_t bios_offset;
@@ -1183,6 +1183,7 @@ static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device,
     int n;
 
     env = cpu_init();
+    cpu_arm_set_model(env, cpuid);
     bios_offset = ram_size + vga_ram_size;
     /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash.  */
     /* ??? RAM shoud repeat to fill physical memory space.  */
@@ -1240,8 +1241,34 @@ static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device,
     set_kernel_args(ram_size, initrd_size, kernel_cmdline);
 }
 
-QEMUMachine integratorcp_machine = {
-    "integratorcp",
-    "ARM Integrator/CP",
-    integratorcp_init,
+static void integratorcp926_init(int ram_size, int vga_ram_size,
+    int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
+    const char *kernel_filename, const char *kernel_cmdline,
+    const char *initrd_filename)
+{
+    integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
+                      snapshot, kernel_filename, kernel_cmdline,
+                      initrd_filename, ARM_CPUID_ARM926);
+}
+
+static void integratorcp1026_init(int ram_size, int vga_ram_size,
+    int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
+    const char *kernel_filename, const char *kernel_cmdline,
+    const char *initrd_filename)
+{
+    integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
+                      snapshot, kernel_filename, kernel_cmdline,
+                      initrd_filename, ARM_CPUID_ARM1026);
+}
+
+QEMUMachine integratorcp926_machine = {
+    "integratorcp926",
+    "ARM Integrator/CP (ARM926EJ-S)",
+    integratorcp926_init,
+};
+
+QEMUMachine integratorcp1026_machine = {
+    "integratorcp1026",
+    "ARM Integrator/CP (ARM1026EJ-S)",
+    integratorcp1026_init,
 };
index afcf4f4..1402fd9 100644 (file)
@@ -1609,6 +1609,7 @@ int main(int argc, char **argv)
 #elif defined(TARGET_ARM)
     {
         int i;
+        cpu_arm_set_model(env, ARM_CPUID_ARM1026);
         cpsr_write(env, regs->uregs[16], 0xffffffff);
         for(i = 0; i < 16; i++) {
             env->regs[i] = regs->uregs[i];
index 052634c..75a1f13 100644 (file)
@@ -72,6 +72,7 @@ typedef struct CPUARMState {
 
     /* System control coprocessor (cp15) */
     struct {
+        uint32_t c0_cpuid;
         uint32_t c1_sys; /* System control register.  */
         uint32_t c1_coproc; /* Coprocessor access register.  */
         uint32_t c2; /* MMU translation table base.  */
@@ -85,7 +86,10 @@ typedef struct CPUARMState {
         uint32_t c13_fcse; /* FCSE PID.  */
         uint32_t c13_context; /* Context ID.  */
     } cp15;
-    
+
+    /* Internal CPU feature flags.  */
+    uint32_t features;
+
     /* exception/interrupt handling */
     jmp_buf jmp_env;
     int exception_index;
@@ -97,12 +101,11 @@ typedef struct CPUARMState {
     struct {
         float64 regs[16];
 
+        uint32_t xregs[16];
         /* We store these fpcsr fields separately for convenience.  */
         int vec_len;
         int vec_stride;
 
-        uint32_t fpscr;
-
         /* Temporary variables if we don't have spare fp regs.  */
         float32 tmp0s, tmp1s;
         float64 tmp0d, tmp1d;
@@ -187,6 +190,29 @@ enum arm_cpu_mode {
   ARM_CPU_MODE_SYS = 0x1f
 };
 
+/* VFP system registers.  */
+#define ARM_VFP_FPSID   0
+#define ARM_VFP_FPSCR   1
+#define ARM_VFP_FPEXC   8
+#define ARM_VFP_FPINST  9
+#define ARM_VFP_FPINST2 10
+
+
+enum arm_features {
+    ARM_FEATURE_VFP,
+    ARM_FEATURE_AUXCR /* ARM1026 Auxiliary control register.  */
+};
+
+static inline int arm_feature(CPUARMState *env, int feature)
+{
+    return (env->features & (1u << feature)) != 0;
+}
+
+void cpu_arm_set_model(CPUARMState *env, uint32_t id);
+
+#define ARM_CPUID_ARM1026 0x4106a262
+#define ARM_CPUID_ARM926  0x41069265
+
 #if defined(CONFIG_USER_ONLY)
 #define TARGET_PAGE_BITS 12
 #else
index 5804df8..d0cd6d8 100644 (file)
@@ -5,6 +5,61 @@
 #include "cpu.h"
 #include "exec-all.h"
 
+void cpu_reset(CPUARMState *env)
+{
+#if defined (CONFIG_USER_ONLY)
+    env->uncached_cpsr = ARM_CPU_MODE_USR;
+    env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
+#else
+    /* SVC mode with interrupts disabled.  */
+    env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
+    env->vfp.xregs[ARM_VFP_FPEXC] = 0;
+#endif
+    env->regs[15] = 0;
+}
+
+CPUARMState *cpu_arm_init(void)
+{
+    CPUARMState *env;
+
+    env = qemu_mallocz(sizeof(CPUARMState));
+    if (!env)
+        return NULL;
+    cpu_exec_init(env);
+    cpu_reset(env);
+    tlb_flush(env, 1);
+    return env;
+}
+
+static inline void set_feature(CPUARMState *env, int feature)
+{
+    env->features |= 1u << feature;
+}
+
+void cpu_arm_set_model(CPUARMState *env, uint32_t id)
+{
+    env->cp15.c0_cpuid = id;
+    switch (id) {
+    case ARM_CPUID_ARM926:
+        set_feature(env, ARM_FEATURE_VFP);
+        env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
+        break;
+    case ARM_CPUID_ARM1026:
+        set_feature(env, ARM_FEATURE_VFP);
+        set_feature(env, ARM_FEATURE_AUXCR);
+        env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
+        break;
+    default:
+        cpu_abort(env, "Bad CPU ID: %x\n", id);
+        break;
+    }
+}
+
+void cpu_arm_close(CPUARMState *env)
+{
+    free(env);
+}
+
 #if defined(CONFIG_USER_ONLY) 
 
 void do_interrupt (CPUState *env)
@@ -469,7 +524,7 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
     case 0: /* ID codes.  */
         switch (op2) {
         default: /* Device ID.  */
-            return 0x4106a262;
+            return env->cp15.c0_cpuid;
         case 1: /* Cache Type.  */
             return 0x1dd20d2;
         case 2: /* TCM status.  */
@@ -480,7 +535,9 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
         case 0: /* Control register.  */
             return env->cp15.c1_sys;
         case 1: /* Auxiliary control register.  */
-            return 1;
+            if (arm_feature(env, ARM_FEATURE_AUXCR))
+                return 1;
+            goto bad_reg;
         case 2: /* Coprocessor access register.  */
             return env->cp15.c1_coproc;
         default:
@@ -506,6 +563,8 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
         case 0:
             return env->cp15.c6_data;
         case 1:
+            /* Arm9 doesn't have an IFAR, but implementing it anyway shouldn't
+               do any harm.  */
             return env->cp15.c6_insn;
         default:
             goto bad_reg;
index f06b06b..619066d 100644 (file)
@@ -1094,7 +1094,7 @@ void OPPROTO op_vfp_movl_T0_fpscr(void)
 
 void OPPROTO op_vfp_movl_T0_fpscr_flags(void)
 {
-    T0 = env->vfp.fpscr & (0xf << 28);
+    T0 = env->vfp.xregs[ARM_VFP_FPSCR] & (0xf << 28);
 }
 
 void OPPROTO op_vfp_movl_fpscr_T0(void)
@@ -1102,6 +1102,16 @@ void OPPROTO op_vfp_movl_fpscr_T0(void)
     do_vfp_set_fpscr();
 }
 
+void OPPROTO op_vfp_movl_T0_xreg(void)
+{
+    T0 = env->vfp.xregs[PARAM1];
+}
+
+void OPPROTO op_vfp_movl_xreg_T0(void)
+{
+    env->vfp.xregs[PARAM1] = T0;
+}
+
 /* Move between FT0s to T0  */
 void OPPROTO op_vfp_mrs(void)
 {
index c075b53..af5c61d 100644 (file)
@@ -72,7 +72,8 @@ void do_vfp_cmp##p(void)                  \
     case 1: flags = 0x2; break;\
     default: case 2: flags = 0x3; break;\
     }\
-    env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \
+    env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28)\
+        | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
     FORCE_RET();                          \
 }\
 \
@@ -85,7 +86,8 @@ void do_vfp_cmpe##p(void)                   \
     case 1: flags = 0x2; break;\
     default: case 2: flags = 0x3; break;\
     }\
-    env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \
+    env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28)\
+        | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
     FORCE_RET();                          \
 }
 DO_VFP_cmp(s, 32)
@@ -133,8 +135,8 @@ void do_vfp_set_fpscr(void)
     int i;
     uint32_t changed;
 
-    changed = env->vfp.fpscr;
-    env->vfp.fpscr = (T0 & 0xffc8ffff);
+    changed = env->vfp.xregs[ARM_VFP_FPSCR];
+    env->vfp.xregs[ARM_VFP_FPSCR] = (T0 & 0xffc8ffff);
     env->vfp.vec_len = (T0 >> 16) & 7;
     env->vfp.vec_stride = (T0 >> 20) & 3;
 
@@ -167,7 +169,7 @@ void do_vfp_get_fpscr(void)
 {
     int i;
 
-    T0 = (env->vfp.fpscr & 0xffc8ffff) | (env->vfp.vec_len << 16)
+    T0 = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff) | (env->vfp.vec_len << 16)
           | (env->vfp.vec_stride << 20);
     i = get_float_exception_flags(&env->vfp.fp_status);
     T0 |= vfp_exceptbits_from_host(i);
index 9390579..1f8a485 100644 (file)
@@ -526,6 +526,17 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
     uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
     int dp, veclen;
 
+    if (!arm_feature(env, ARM_FEATURE_VFP))
+        return 1;
+
+    if ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) == 0) {
+        /* VFP disabled.  Only allow fmxr/fmrx to/from fpexc and fpsid.  */
+        if ((insn & 0x0fe00fff) != 0x0ee00a10)
+            return 1;
+        rn = (insn >> 16) & 0xf;
+        if (rn != 0 && rn != 8)
+            return 1;
+    }
     dp = ((insn & 0xf00) == 0xb00);
     switch ((insn >> 24) & 0xf) {
     case 0xe:
@@ -563,11 +574,15 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     /* vfp->arm */
                     if (insn & (1 << 21)) {
                         /* system register */
+                        rn >>= 1;
                         switch (rn) {
-                        case 0: /* fpsid */
-                            n = 0x0091A0000;
+                        case ARM_VFP_FPSID:
+                        case ARM_VFP_FPEXC:
+                        case ARM_VFP_FPINST:
+                        case ARM_VFP_FPINST2:
+                            gen_op_vfp_movl_T0_xreg(rn);
                             break;
-                        case 2: /* fpscr */
+                        case ARM_VFP_FPSCR:
                            if (rd == 15)
                                gen_op_vfp_movl_T0_fpscr_flags();
                            else
@@ -589,17 +604,24 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
                     /* arm->vfp */
                     gen_movl_T0_reg(s, rd);
                     if (insn & (1 << 21)) {
+                        rn >>= 1;
                         /* system register */
                         switch (rn) {
-                        case 0: /* fpsid */
+                        case ARM_VFP_FPSID:
                             /* Writes are ignored.  */
                             break;
-                        case 2: /* fpscr */
+                        case ARM_VFP_FPSCR:
                             gen_op_vfp_movl_fpscr_T0();
-                            /* This could change vector settings, so jump to
-                               the next instuction.  */
                             gen_lookup_tb(s);
                             break;
+                        case ARM_VFP_FPEXC:
+                            gen_op_vfp_movl_xreg_T0(rn);
+                            gen_lookup_tb(s);
+                            break;
+                        case ARM_VFP_FPINST:
+                        case ARM_VFP_FPINST2:
+                            gen_op_vfp_movl_xreg_T0(rn);
+                            break;
                         default:
                             return 1;
                         }
@@ -2456,35 +2478,6 @@ int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
     return gen_intermediate_code_internal(env, tb, 1);
 }
 
-void cpu_reset(CPUARMState *env)
-{
-#if defined (CONFIG_USER_ONLY)
-    env->uncached_cpsr = ARM_CPU_MODE_USR;
-#else
-    /* SVC mode with interrupts disabled.  */
-    env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
-#endif
-    env->regs[15] = 0;
-}
-
-CPUARMState *cpu_arm_init(void)
-{
-    CPUARMState *env;
-
-    env = qemu_mallocz(sizeof(CPUARMState));
-    if (!env)
-        return NULL;
-    cpu_exec_init(env);
-    cpu_reset(env);
-    tlb_flush(env, 1);
-    return env;
-}
-
-void cpu_arm_close(CPUARMState *env)
-{
-    free(env);
-}
-
 static const char *cpu_mode_names[16] = {
   "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
   "???", "???", "???", "und", "???", "???", "???", "sys"
@@ -2528,6 +2521,6 @@ void cpu_dump_state(CPUState *env, FILE *f,
                     i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
                     d.d);
     }
-    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.fpscr);
+    cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
 }
 
diff --git a/vl.c b/vl.c
index 8d1fa37..e0406ea 100644 (file)
--- a/vl.c
+++ b/vl.c
@@ -4435,7 +4435,8 @@ void register_machines(void)
     qemu_register_machine(&sun4m_machine);
 #endif
 #elif defined(TARGET_ARM)
-    qemu_register_machine(&integratorcp_machine);
+    qemu_register_machine(&integratorcp926_machine);
+    qemu_register_machine(&integratorcp1026_machine);
 #else
 #error unsupported CPU
 #endif
diff --git a/vl.h b/vl.h
index 4d215e7..ada0788 100644 (file)
--- a/vl.h
+++ b/vl.h
@@ -960,7 +960,8 @@ void do_usb_del(const char *devname);
 void usb_info(void);
 
 /* integratorcp.c */
-extern QEMUMachine integratorcp_machine;
+extern QEMUMachine integratorcp926_machine;
+extern QEMUMachine integratorcp1026_machine;
 
 /* ps2.c */
 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg);