Commit 40f137e1eadbc202daf00bd6f43a997ccfb28b70
1 parent
4081fccf
Add Arm926 core support.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1765 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
10 changed files
with
177 additions
and
55 deletions
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 | ... | ... |
vl.c
... | ... | @@ -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 | ... | ... |
vl.h
... | ... | @@ -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); | ... | ... |