Commit 40f137e1eadbc202daf00bd6f43a997ccfb28b70

Authored by pbrook
1 parent 4081fccf

Add Arm926 core support.


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1765 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-exec.c
... ... @@ -169,6 +169,8 @@ static inline TranslationBlock *tb_find_fast(void)
169 169 | (env->vfp.vec_stride << 4);
170 170 if ((env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR)
171 171 flags |= (1 << 6);
  172 + if (env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30))
  173 + flags |= (1 << 7);
172 174 cs_base = 0;
173 175 pc = env->regs[15];
174 176 #elif defined(TARGET_SPARC)
... ...
hw/integratorcp.c
... ... @@ -1173,7 +1173,7 @@ static void set_kernel_args(uint32_t ram_size, int initrd_size,
1173 1173 static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device,
1174 1174 DisplayState *ds, const char **fd_filename, int snapshot,
1175 1175 const char *kernel_filename, const char *kernel_cmdline,
1176   - const char *initrd_filename)
  1176 + const char *initrd_filename, uint32_t cpuid)
1177 1177 {
1178 1178 CPUState *env;
1179 1179 uint32_t bios_offset;
... ... @@ -1183,6 +1183,7 @@ static void integratorcp_init(int ram_size, int vga_ram_size, int boot_device,
1183 1183 int n;
1184 1184  
1185 1185 env = cpu_init();
  1186 + cpu_arm_set_model(env, cpuid);
1186 1187 bios_offset = ram_size + vga_ram_size;
1187 1188 /* ??? On a real system the first 1Mb is mapped as SSRAM or boot flash. */
1188 1189 /* ??? 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,
1240 1241 set_kernel_args(ram_size, initrd_size, kernel_cmdline);
1241 1242 }
1242 1243  
1243   -QEMUMachine integratorcp_machine = {
1244   - "integratorcp",
1245   - "ARM Integrator/CP",
1246   - integratorcp_init,
  1244 +static void integratorcp926_init(int ram_size, int vga_ram_size,
  1245 + int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
  1246 + const char *kernel_filename, const char *kernel_cmdline,
  1247 + const char *initrd_filename)
  1248 +{
  1249 + integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
  1250 + snapshot, kernel_filename, kernel_cmdline,
  1251 + initrd_filename, ARM_CPUID_ARM926);
  1252 +}
  1253 +
  1254 +static void integratorcp1026_init(int ram_size, int vga_ram_size,
  1255 + int boot_device, DisplayState *ds, const char **fd_filename, int snapshot,
  1256 + const char *kernel_filename, const char *kernel_cmdline,
  1257 + const char *initrd_filename)
  1258 +{
  1259 + integratorcp_init(ram_size, vga_ram_size, boot_device, ds, fd_filename,
  1260 + snapshot, kernel_filename, kernel_cmdline,
  1261 + initrd_filename, ARM_CPUID_ARM1026);
  1262 +}
  1263 +
  1264 +QEMUMachine integratorcp926_machine = {
  1265 + "integratorcp926",
  1266 + "ARM Integrator/CP (ARM926EJ-S)",
  1267 + integratorcp926_init,
  1268 +};
  1269 +
  1270 +QEMUMachine integratorcp1026_machine = {
  1271 + "integratorcp1026",
  1272 + "ARM Integrator/CP (ARM1026EJ-S)",
  1273 + integratorcp1026_init,
1247 1274 };
... ...
linux-user/main.c
... ... @@ -1609,6 +1609,7 @@ int main(int argc, char **argv)
1609 1609 #elif defined(TARGET_ARM)
1610 1610 {
1611 1611 int i;
  1612 + cpu_arm_set_model(env, ARM_CPUID_ARM1026);
1612 1613 cpsr_write(env, regs->uregs[16], 0xffffffff);
1613 1614 for(i = 0; i < 16; i++) {
1614 1615 env->regs[i] = regs->uregs[i];
... ...
target-arm/cpu.h
... ... @@ -72,6 +72,7 @@ typedef struct CPUARMState {
72 72  
73 73 /* System control coprocessor (cp15) */
74 74 struct {
  75 + uint32_t c0_cpuid;
75 76 uint32_t c1_sys; /* System control register. */
76 77 uint32_t c1_coproc; /* Coprocessor access register. */
77 78 uint32_t c2; /* MMU translation table base. */
... ... @@ -85,7 +86,10 @@ typedef struct CPUARMState {
85 86 uint32_t c13_fcse; /* FCSE PID. */
86 87 uint32_t c13_context; /* Context ID. */
87 88 } cp15;
88   -
  89 +
  90 + /* Internal CPU feature flags. */
  91 + uint32_t features;
  92 +
89 93 /* exception/interrupt handling */
90 94 jmp_buf jmp_env;
91 95 int exception_index;
... ... @@ -97,12 +101,11 @@ typedef struct CPUARMState {
97 101 struct {
98 102 float64 regs[16];
99 103  
  104 + uint32_t xregs[16];
100 105 /* We store these fpcsr fields separately for convenience. */
101 106 int vec_len;
102 107 int vec_stride;
103 108  
104   - uint32_t fpscr;
105   -
106 109 /* Temporary variables if we don't have spare fp regs. */
107 110 float32 tmp0s, tmp1s;
108 111 float64 tmp0d, tmp1d;
... ... @@ -187,6 +190,29 @@ enum arm_cpu_mode {
187 190 ARM_CPU_MODE_SYS = 0x1f
188 191 };
189 192  
  193 +/* VFP system registers. */
  194 +#define ARM_VFP_FPSID 0
  195 +#define ARM_VFP_FPSCR 1
  196 +#define ARM_VFP_FPEXC 8
  197 +#define ARM_VFP_FPINST 9
  198 +#define ARM_VFP_FPINST2 10
  199 +
  200 +
  201 +enum arm_features {
  202 + ARM_FEATURE_VFP,
  203 + ARM_FEATURE_AUXCR /* ARM1026 Auxiliary control register. */
  204 +};
  205 +
  206 +static inline int arm_feature(CPUARMState *env, int feature)
  207 +{
  208 + return (env->features & (1u << feature)) != 0;
  209 +}
  210 +
  211 +void cpu_arm_set_model(CPUARMState *env, uint32_t id);
  212 +
  213 +#define ARM_CPUID_ARM1026 0x4106a262
  214 +#define ARM_CPUID_ARM926 0x41069265
  215 +
190 216 #if defined(CONFIG_USER_ONLY)
191 217 #define TARGET_PAGE_BITS 12
192 218 #else
... ...
target-arm/helper.c
... ... @@ -5,6 +5,61 @@
5 5 #include "cpu.h"
6 6 #include "exec-all.h"
7 7  
  8 +void cpu_reset(CPUARMState *env)
  9 +{
  10 +#if defined (CONFIG_USER_ONLY)
  11 + env->uncached_cpsr = ARM_CPU_MODE_USR;
  12 + env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
  13 +#else
  14 + /* SVC mode with interrupts disabled. */
  15 + env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
  16 + env->vfp.xregs[ARM_VFP_FPEXC] = 0;
  17 +#endif
  18 + env->regs[15] = 0;
  19 +}
  20 +
  21 +CPUARMState *cpu_arm_init(void)
  22 +{
  23 + CPUARMState *env;
  24 +
  25 + env = qemu_mallocz(sizeof(CPUARMState));
  26 + if (!env)
  27 + return NULL;
  28 + cpu_exec_init(env);
  29 + cpu_reset(env);
  30 + tlb_flush(env, 1);
  31 + return env;
  32 +}
  33 +
  34 +static inline void set_feature(CPUARMState *env, int feature)
  35 +{
  36 + env->features |= 1u << feature;
  37 +}
  38 +
  39 +void cpu_arm_set_model(CPUARMState *env, uint32_t id)
  40 +{
  41 + env->cp15.c0_cpuid = id;
  42 + switch (id) {
  43 + case ARM_CPUID_ARM926:
  44 + set_feature(env, ARM_FEATURE_VFP);
  45 + env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
  46 + break;
  47 + case ARM_CPUID_ARM1026:
  48 + set_feature(env, ARM_FEATURE_VFP);
  49 + set_feature(env, ARM_FEATURE_AUXCR);
  50 + env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
  51 + break;
  52 + default:
  53 + cpu_abort(env, "Bad CPU ID: %x\n", id);
  54 + break;
  55 + }
  56 +}
  57 +
  58 +void cpu_arm_close(CPUARMState *env)
  59 +{
  60 + free(env);
  61 +}
  62 +
8 63 #if defined(CONFIG_USER_ONLY)
9 64  
10 65 void do_interrupt (CPUState *env)
... ... @@ -469,7 +524,7 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
469 524 case 0: /* ID codes. */
470 525 switch (op2) {
471 526 default: /* Device ID. */
472   - return 0x4106a262;
  527 + return env->cp15.c0_cpuid;
473 528 case 1: /* Cache Type. */
474 529 return 0x1dd20d2;
475 530 case 2: /* TCM status. */
... ... @@ -480,7 +535,9 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
480 535 case 0: /* Control register. */
481 536 return env->cp15.c1_sys;
482 537 case 1: /* Auxiliary control register. */
483   - return 1;
  538 + if (arm_feature(env, ARM_FEATURE_AUXCR))
  539 + return 1;
  540 + goto bad_reg;
484 541 case 2: /* Coprocessor access register. */
485 542 return env->cp15.c1_coproc;
486 543 default:
... ... @@ -506,6 +563,8 @@ uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
506 563 case 0:
507 564 return env->cp15.c6_data;
508 565 case 1:
  566 + /* Arm9 doesn't have an IFAR, but implementing it anyway shouldn't
  567 + do any harm. */
509 568 return env->cp15.c6_insn;
510 569 default:
511 570 goto bad_reg;
... ...
target-arm/op.c
... ... @@ -1094,7 +1094,7 @@ void OPPROTO op_vfp_movl_T0_fpscr(void)
1094 1094  
1095 1095 void OPPROTO op_vfp_movl_T0_fpscr_flags(void)
1096 1096 {
1097   - T0 = env->vfp.fpscr & (0xf << 28);
  1097 + T0 = env->vfp.xregs[ARM_VFP_FPSCR] & (0xf << 28);
1098 1098 }
1099 1099  
1100 1100 void OPPROTO op_vfp_movl_fpscr_T0(void)
... ... @@ -1102,6 +1102,16 @@ void OPPROTO op_vfp_movl_fpscr_T0(void)
1102 1102 do_vfp_set_fpscr();
1103 1103 }
1104 1104  
  1105 +void OPPROTO op_vfp_movl_T0_xreg(void)
  1106 +{
  1107 + T0 = env->vfp.xregs[PARAM1];
  1108 +}
  1109 +
  1110 +void OPPROTO op_vfp_movl_xreg_T0(void)
  1111 +{
  1112 + env->vfp.xregs[PARAM1] = T0;
  1113 +}
  1114 +
1105 1115 /* Move between FT0s to T0 */
1106 1116 void OPPROTO op_vfp_mrs(void)
1107 1117 {
... ...
target-arm/op_helper.c
... ... @@ -72,7 +72,8 @@ void do_vfp_cmp##p(void) \
72 72 case 1: flags = 0x2; break;\
73 73 default: case 2: flags = 0x3; break;\
74 74 }\
75   - env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \
  75 + env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28)\
  76 + | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
76 77 FORCE_RET(); \
77 78 }\
78 79 \
... ... @@ -85,7 +86,8 @@ void do_vfp_cmpe##p(void) \
85 86 case 1: flags = 0x2; break;\
86 87 default: case 2: flags = 0x3; break;\
87 88 }\
88   - env->vfp.fpscr = (flags << 28) | (env->vfp.fpscr & 0x0fffffff); \
  89 + env->vfp.xregs[ARM_VFP_FPSCR] = (flags << 28)\
  90 + | (env->vfp.xregs[ARM_VFP_FPSCR] & 0x0fffffff); \
89 91 FORCE_RET(); \
90 92 }
91 93 DO_VFP_cmp(s, 32)
... ... @@ -133,8 +135,8 @@ void do_vfp_set_fpscr(void)
133 135 int i;
134 136 uint32_t changed;
135 137  
136   - changed = env->vfp.fpscr;
137   - env->vfp.fpscr = (T0 & 0xffc8ffff);
  138 + changed = env->vfp.xregs[ARM_VFP_FPSCR];
  139 + env->vfp.xregs[ARM_VFP_FPSCR] = (T0 & 0xffc8ffff);
138 140 env->vfp.vec_len = (T0 >> 16) & 7;
139 141 env->vfp.vec_stride = (T0 >> 20) & 3;
140 142  
... ... @@ -167,7 +169,7 @@ void do_vfp_get_fpscr(void)
167 169 {
168 170 int i;
169 171  
170   - T0 = (env->vfp.fpscr & 0xffc8ffff) | (env->vfp.vec_len << 16)
  172 + T0 = (env->vfp.xregs[ARM_VFP_FPSCR] & 0xffc8ffff) | (env->vfp.vec_len << 16)
171 173 | (env->vfp.vec_stride << 20);
172 174 i = get_float_exception_flags(&env->vfp.fp_status);
173 175 T0 |= vfp_exceptbits_from_host(i);
... ...
target-arm/translate.c
... ... @@ -526,6 +526,17 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
526 526 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
527 527 int dp, veclen;
528 528  
  529 + if (!arm_feature(env, ARM_FEATURE_VFP))
  530 + return 1;
  531 +
  532 + if ((env->vfp.xregs[ARM_VFP_FPEXC] & (1 << 30)) == 0) {
  533 + /* VFP disabled. Only allow fmxr/fmrx to/from fpexc and fpsid. */
  534 + if ((insn & 0x0fe00fff) != 0x0ee00a10)
  535 + return 1;
  536 + rn = (insn >> 16) & 0xf;
  537 + if (rn != 0 && rn != 8)
  538 + return 1;
  539 + }
529 540 dp = ((insn & 0xf00) == 0xb00);
530 541 switch ((insn >> 24) & 0xf) {
531 542 case 0xe:
... ... @@ -563,11 +574,15 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
563 574 /* vfp->arm */
564 575 if (insn & (1 << 21)) {
565 576 /* system register */
  577 + rn >>= 1;
566 578 switch (rn) {
567   - case 0: /* fpsid */
568   - n = 0x0091A0000;
  579 + case ARM_VFP_FPSID:
  580 + case ARM_VFP_FPEXC:
  581 + case ARM_VFP_FPINST:
  582 + case ARM_VFP_FPINST2:
  583 + gen_op_vfp_movl_T0_xreg(rn);
569 584 break;
570   - case 2: /* fpscr */
  585 + case ARM_VFP_FPSCR:
571 586 if (rd == 15)
572 587 gen_op_vfp_movl_T0_fpscr_flags();
573 588 else
... ... @@ -589,17 +604,24 @@ static int disas_vfp_insn(CPUState * env, DisasContext *s, uint32_t insn)
589 604 /* arm->vfp */
590 605 gen_movl_T0_reg(s, rd);
591 606 if (insn & (1 << 21)) {
  607 + rn >>= 1;
592 608 /* system register */
593 609 switch (rn) {
594   - case 0: /* fpsid */
  610 + case ARM_VFP_FPSID:
595 611 /* Writes are ignored. */
596 612 break;
597   - case 2: /* fpscr */
  613 + case ARM_VFP_FPSCR:
598 614 gen_op_vfp_movl_fpscr_T0();
599   - /* This could change vector settings, so jump to
600   - the next instuction. */
601 615 gen_lookup_tb(s);
602 616 break;
  617 + case ARM_VFP_FPEXC:
  618 + gen_op_vfp_movl_xreg_T0(rn);
  619 + gen_lookup_tb(s);
  620 + break;
  621 + case ARM_VFP_FPINST:
  622 + case ARM_VFP_FPINST2:
  623 + gen_op_vfp_movl_xreg_T0(rn);
  624 + break;
603 625 default:
604 626 return 1;
605 627 }
... ... @@ -2456,35 +2478,6 @@ int gen_intermediate_code_pc(CPUState *env, TranslationBlock *tb)
2456 2478 return gen_intermediate_code_internal(env, tb, 1);
2457 2479 }
2458 2480  
2459   -void cpu_reset(CPUARMState *env)
2460   -{
2461   -#if defined (CONFIG_USER_ONLY)
2462   - env->uncached_cpsr = ARM_CPU_MODE_USR;
2463   -#else
2464   - /* SVC mode with interrupts disabled. */
2465   - env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
2466   -#endif
2467   - env->regs[15] = 0;
2468   -}
2469   -
2470   -CPUARMState *cpu_arm_init(void)
2471   -{
2472   - CPUARMState *env;
2473   -
2474   - env = qemu_mallocz(sizeof(CPUARMState));
2475   - if (!env)
2476   - return NULL;
2477   - cpu_exec_init(env);
2478   - cpu_reset(env);
2479   - tlb_flush(env, 1);
2480   - return env;
2481   -}
2482   -
2483   -void cpu_arm_close(CPUARMState *env)
2484   -{
2485   - free(env);
2486   -}
2487   -
2488 2481 static const char *cpu_mode_names[16] = {
2489 2482 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
2490 2483 "???", "???", "???", "und", "???", "???", "???", "sys"
... ... @@ -2528,6 +2521,6 @@ void cpu_dump_state(CPUState *env, FILE *f,
2528 2521 i, (int)(uint32_t)d.l.upper, (int)(uint32_t)d.l.lower,
2529 2522 d.d);
2530 2523 }
2531   - cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.fpscr);
  2524 + cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
2532 2525 }
2533 2526  
... ...
... ... @@ -4435,7 +4435,8 @@ void register_machines(void)
4435 4435 qemu_register_machine(&sun4m_machine);
4436 4436 #endif
4437 4437 #elif defined(TARGET_ARM)
4438   - qemu_register_machine(&integratorcp_machine);
  4438 + qemu_register_machine(&integratorcp926_machine);
  4439 + qemu_register_machine(&integratorcp1026_machine);
4439 4440 #else
4440 4441 #error unsupported CPU
4441 4442 #endif
... ...
... ... @@ -960,7 +960,8 @@ void do_usb_del(const char *devname);
960 960 void usb_info(void);
961 961  
962 962 /* integratorcp.c */
963   -extern QEMUMachine integratorcp_machine;
  963 +extern QEMUMachine integratorcp926_machine;
  964 +extern QEMUMachine integratorcp1026_machine;
964 965  
965 966 /* ps2.c */
966 967 void *ps2_kbd_init(void (*update_irq)(void *, int), void *update_arg);
... ...