added cpu_model parameter to cpu_init()
[qemu] / target-arm / helper.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4
5 #include "cpu.h"
6 #include "exec-all.h"
7
8 static uint32_t cpu_arm_find_by_name(const char *name);
9
10 static inline void set_feature(CPUARMState *env, int feature)
11 {
12     env->features |= 1u << feature;
13 }
14
15 static void cpu_reset_model_id(CPUARMState *env, uint32_t id)
16 {
17     env->cp15.c0_cpuid = id;
18     switch (id) {
19     case ARM_CPUID_ARM926:
20         set_feature(env, ARM_FEATURE_VFP);
21         env->vfp.xregs[ARM_VFP_FPSID] = 0x41011090;
22         env->cp15.c0_cachetype = 0x1dd20d2;
23         env->cp15.c1_sys = 0x00090078;
24         break;
25     case ARM_CPUID_ARM946:
26         set_feature(env, ARM_FEATURE_MPU);
27         env->cp15.c0_cachetype = 0x0f004006;
28         env->cp15.c1_sys = 0x00000078;
29         break;
30     case ARM_CPUID_ARM1026:
31         set_feature(env, ARM_FEATURE_VFP);
32         set_feature(env, ARM_FEATURE_AUXCR);
33         env->vfp.xregs[ARM_VFP_FPSID] = 0x410110a0;
34         env->cp15.c0_cachetype = 0x1dd20d2;
35         env->cp15.c1_sys = 0x00090078;
36         break;
37     case ARM_CPUID_TI915T:
38     case ARM_CPUID_TI925T:
39         set_feature(env, ARM_FEATURE_OMAPCP);
40         env->cp15.c0_cpuid = ARM_CPUID_TI925T; /* Depends on wiring.  */
41         env->cp15.c0_cachetype = 0x5109149;
42         env->cp15.c1_sys = 0x00000070;
43         env->cp15.c15_i_max = 0x000;
44         env->cp15.c15_i_min = 0xff0;
45         break;
46     case ARM_CPUID_PXA250:
47     case ARM_CPUID_PXA255:
48     case ARM_CPUID_PXA260:
49     case ARM_CPUID_PXA261:
50     case ARM_CPUID_PXA262:
51         set_feature(env, ARM_FEATURE_XSCALE);
52         /* JTAG_ID is ((id << 28) | 0x09265013) */
53         env->cp15.c0_cachetype = 0xd172172;
54         env->cp15.c1_sys = 0x00000078;
55         break;
56     case ARM_CPUID_PXA270_A0:
57     case ARM_CPUID_PXA270_A1:
58     case ARM_CPUID_PXA270_B0:
59     case ARM_CPUID_PXA270_B1:
60     case ARM_CPUID_PXA270_C0:
61     case ARM_CPUID_PXA270_C5:
62         set_feature(env, ARM_FEATURE_XSCALE);
63         /* JTAG_ID is ((id << 28) | 0x09265013) */
64         set_feature(env, ARM_FEATURE_IWMMXT);
65         env->iwmmxt.cregs[ARM_IWMMXT_wCID] = 0x69051000 | 'Q';
66         env->cp15.c0_cachetype = 0xd172172;
67         env->cp15.c1_sys = 0x00000078;
68         break;
69     default:
70         cpu_abort(env, "Bad CPU ID: %x\n", id);
71         break;
72     }
73 }
74
75 void cpu_reset(CPUARMState *env)
76 {
77     uint32_t id;
78     id = env->cp15.c0_cpuid;
79     memset(env, 0, offsetof(CPUARMState, breakpoints));
80     if (id)
81         cpu_reset_model_id(env, id);
82 #if defined (CONFIG_USER_ONLY)
83     env->uncached_cpsr = ARM_CPU_MODE_USR;
84     env->vfp.xregs[ARM_VFP_FPEXC] = 1 << 30;
85 #else
86     /* SVC mode with interrupts disabled.  */
87     env->uncached_cpsr = ARM_CPU_MODE_SVC | CPSR_A | CPSR_F | CPSR_I;
88     env->vfp.xregs[ARM_VFP_FPEXC] = 0;
89 #endif
90     env->regs[15] = 0;
91     tlb_flush(env, 1);
92 }
93
94 CPUARMState *cpu_arm_init(const char *cpu_model)
95 {
96     CPUARMState *env;
97     uint32_t id;
98
99     id = cpu_arm_find_by_name(cpu_model);
100     if (id == 0)
101         return NULL;
102     env = qemu_mallocz(sizeof(CPUARMState));
103     if (!env)
104         return NULL;
105     cpu_exec_init(env);
106     env->cp15.c0_cpuid = id;
107     cpu_reset(env);
108     return env;
109 }
110
111 struct arm_cpu_t {
112     uint32_t id;
113     const char *name;
114 };
115
116 static const struct arm_cpu_t arm_cpu_names[] = {
117     { ARM_CPUID_ARM926, "arm926"},
118     { ARM_CPUID_ARM946, "arm946"},
119     { ARM_CPUID_ARM1026, "arm1026"},
120     { ARM_CPUID_TI925T, "ti925t" },
121     { ARM_CPUID_PXA250, "pxa250" },
122     { ARM_CPUID_PXA255, "pxa255" },
123     { ARM_CPUID_PXA260, "pxa260" },
124     { ARM_CPUID_PXA261, "pxa261" },
125     { ARM_CPUID_PXA262, "pxa262" },
126     { ARM_CPUID_PXA270, "pxa270" },
127     { ARM_CPUID_PXA270_A0, "pxa270-a0" },
128     { ARM_CPUID_PXA270_A1, "pxa270-a1" },
129     { ARM_CPUID_PXA270_B0, "pxa270-b0" },
130     { ARM_CPUID_PXA270_B1, "pxa270-b1" },
131     { ARM_CPUID_PXA270_C0, "pxa270-c0" },
132     { ARM_CPUID_PXA270_C5, "pxa270-c5" },
133     { 0, NULL}
134 };
135
136 void arm_cpu_list(FILE *f, int (*cpu_fprintf)(FILE *f, const char *fmt, ...))
137 {
138     int i;
139
140     (*cpu_fprintf)(f, "Available CPUs:\n");
141     for (i = 0; arm_cpu_names[i].name; i++) {
142         (*cpu_fprintf)(f, "  %s\n", arm_cpu_names[i].name);
143     }
144 }
145
146 /* return 0 if not found */
147 static uint32_t cpu_arm_find_by_name(const char *name)
148 {
149     int i;
150     uint32_t id;
151
152     id = 0;
153     for (i = 0; arm_cpu_names[i].name; i++) {
154         if (strcmp(name, arm_cpu_names[i].name) == 0) {
155             id = arm_cpu_names[i].id;
156             break;
157         }
158     }
159     return id;
160 }
161
162 void cpu_arm_close(CPUARMState *env)
163 {
164     free(env);
165 }
166
167 #if defined(CONFIG_USER_ONLY)
168
169 void do_interrupt (CPUState *env)
170 {
171     env->exception_index = -1;
172 }
173
174 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address, int rw,
175                               int mmu_idx, int is_softmmu)
176 {
177     if (rw == 2) {
178         env->exception_index = EXCP_PREFETCH_ABORT;
179         env->cp15.c6_insn = address;
180     } else {
181         env->exception_index = EXCP_DATA_ABORT;
182         env->cp15.c6_data = address;
183     }
184     return 1;
185 }
186
187 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
188 {
189     return addr;
190 }
191
192 /* These should probably raise undefined insn exceptions.  */
193 void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
194 {
195     int op1 = (insn >> 8) & 0xf;
196     cpu_abort(env, "cp%i insn %08x\n", op1, insn);
197     return;
198 }
199
200 uint32_t helper_get_cp(CPUState *env, uint32_t insn)
201 {
202     int op1 = (insn >> 8) & 0xf;
203     cpu_abort(env, "cp%i insn %08x\n", op1, insn);
204     return 0;
205 }
206
207 void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
208 {
209     cpu_abort(env, "cp15 insn %08x\n", insn);
210 }
211
212 uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
213 {
214     cpu_abort(env, "cp15 insn %08x\n", insn);
215     return 0;
216 }
217
218 void switch_mode(CPUState *env, int mode)
219 {
220     if (mode != ARM_CPU_MODE_USR)
221         cpu_abort(env, "Tried to switch out of user mode\n");
222 }
223
224 #else
225
226 extern int semihosting_enabled;
227
228 /* Map CPU modes onto saved register banks.  */
229 static inline int bank_number (int mode)
230 {
231     switch (mode) {
232     case ARM_CPU_MODE_USR:
233     case ARM_CPU_MODE_SYS:
234         return 0;
235     case ARM_CPU_MODE_SVC:
236         return 1;
237     case ARM_CPU_MODE_ABT:
238         return 2;
239     case ARM_CPU_MODE_UND:
240         return 3;
241     case ARM_CPU_MODE_IRQ:
242         return 4;
243     case ARM_CPU_MODE_FIQ:
244         return 5;
245     }
246     cpu_abort(cpu_single_env, "Bad mode %x\n", mode);
247     return -1;
248 }
249
250 void switch_mode(CPUState *env, int mode)
251 {
252     int old_mode;
253     int i;
254
255     old_mode = env->uncached_cpsr & CPSR_M;
256     if (mode == old_mode)
257         return;
258
259     if (old_mode == ARM_CPU_MODE_FIQ) {
260         memcpy (env->fiq_regs, env->regs + 8, 5 * sizeof(uint32_t));
261         memcpy (env->regs + 8, env->usr_regs, 5 * sizeof(uint32_t));
262     } else if (mode == ARM_CPU_MODE_FIQ) {
263         memcpy (env->usr_regs, env->regs + 8, 5 * sizeof(uint32_t));
264         memcpy (env->regs + 8, env->fiq_regs, 5 * sizeof(uint32_t));
265     }
266
267     i = bank_number(old_mode);
268     env->banked_r13[i] = env->regs[13];
269     env->banked_r14[i] = env->regs[14];
270     env->banked_spsr[i] = env->spsr;
271
272     i = bank_number(mode);
273     env->regs[13] = env->banked_r13[i];
274     env->regs[14] = env->banked_r14[i];
275     env->spsr = env->banked_spsr[i];
276 }
277
278 /* Handle a CPU exception.  */
279 void do_interrupt(CPUARMState *env)
280 {
281     uint32_t addr;
282     uint32_t mask;
283     int new_mode;
284     uint32_t offset;
285
286     /* TODO: Vectored interrupt controller.  */
287     switch (env->exception_index) {
288     case EXCP_UDEF:
289         new_mode = ARM_CPU_MODE_UND;
290         addr = 0x04;
291         mask = CPSR_I;
292         if (env->thumb)
293             offset = 2;
294         else
295             offset = 4;
296         break;
297     case EXCP_SWI:
298         if (semihosting_enabled) {
299             /* Check for semihosting interrupt.  */
300             if (env->thumb) {
301                 mask = lduw_code(env->regs[15] - 2) & 0xff;
302             } else {
303                 mask = ldl_code(env->regs[15] - 4) & 0xffffff;
304             }
305             /* Only intercept calls from privileged modes, to provide some
306                semblance of security.  */
307             if (((mask == 0x123456 && !env->thumb)
308                     || (mask == 0xab && env->thumb))
309                   && (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
310                 env->regs[0] = do_arm_semihosting(env);
311                 return;
312             }
313         }
314         new_mode = ARM_CPU_MODE_SVC;
315         addr = 0x08;
316         mask = CPSR_I;
317         /* The PC already points to the next instructon.  */
318         offset = 0;
319         break;
320     case EXCP_PREFETCH_ABORT:
321     case EXCP_BKPT:
322         new_mode = ARM_CPU_MODE_ABT;
323         addr = 0x0c;
324         mask = CPSR_A | CPSR_I;
325         offset = 4;
326         break;
327     case EXCP_DATA_ABORT:
328         new_mode = ARM_CPU_MODE_ABT;
329         addr = 0x10;
330         mask = CPSR_A | CPSR_I;
331         offset = 8;
332         break;
333     case EXCP_IRQ:
334         new_mode = ARM_CPU_MODE_IRQ;
335         addr = 0x18;
336         /* Disable IRQ and imprecise data aborts.  */
337         mask = CPSR_A | CPSR_I;
338         offset = 4;
339         break;
340     case EXCP_FIQ:
341         new_mode = ARM_CPU_MODE_FIQ;
342         addr = 0x1c;
343         /* Disable FIQ, IRQ and imprecise data aborts.  */
344         mask = CPSR_A | CPSR_I | CPSR_F;
345         offset = 4;
346         break;
347     default:
348         cpu_abort(env, "Unhandled exception 0x%x\n", env->exception_index);
349         return; /* Never happens.  Keep compiler happy.  */
350     }
351     /* High vectors.  */
352     if (env->cp15.c1_sys & (1 << 13)) {
353         addr += 0xffff0000;
354     }
355     switch_mode (env, new_mode);
356     env->spsr = cpsr_read(env);
357     /* Switch to the new mode, and switch to Arm mode.  */
358     /* ??? Thumb interrupt handlers not implemented.  */
359     env->uncached_cpsr = (env->uncached_cpsr & ~CPSR_M) | new_mode;
360     env->uncached_cpsr |= mask;
361     env->thumb = 0;
362     env->regs[14] = env->regs[15] + offset;
363     env->regs[15] = addr;
364     env->interrupt_request |= CPU_INTERRUPT_EXITTB;
365 }
366
367 /* Check section/page access permissions.
368    Returns the page protection flags, or zero if the access is not
369    permitted.  */
370 static inline int check_ap(CPUState *env, int ap, int domain, int access_type,
371                            int is_user)
372 {
373   if (domain == 3)
374     return PAGE_READ | PAGE_WRITE;
375
376   switch (ap) {
377   case 0:
378       if (access_type == 1)
379           return 0;
380       switch ((env->cp15.c1_sys >> 8) & 3) {
381       case 1:
382           return is_user ? 0 : PAGE_READ;
383       case 2:
384           return PAGE_READ;
385       default:
386           return 0;
387       }
388   case 1:
389       return is_user ? 0 : PAGE_READ | PAGE_WRITE;
390   case 2:
391       if (is_user)
392           return (access_type == 1) ? 0 : PAGE_READ;
393       else
394           return PAGE_READ | PAGE_WRITE;
395   case 3:
396       return PAGE_READ | PAGE_WRITE;
397   default:
398       abort();
399   }
400 }
401
402 static int get_phys_addr(CPUState *env, uint32_t address, int access_type,
403                          int is_user, uint32_t *phys_ptr, int *prot)
404 {
405     int code;
406     uint32_t table;
407     uint32_t desc;
408     int type;
409     int ap;
410     int domain;
411     uint32_t phys_addr;
412
413     /* Fast Context Switch Extension.  */
414     if (address < 0x02000000)
415         address += env->cp15.c13_fcse;
416
417     if ((env->cp15.c1_sys & 1) == 0) {
418         /* MMU/MPU disabled.  */
419         *phys_ptr = address;
420         *prot = PAGE_READ | PAGE_WRITE;
421     } else if (arm_feature(env, ARM_FEATURE_MPU)) {
422         int n;
423         uint32_t mask;
424         uint32_t base;
425
426         *phys_ptr = address;
427         for (n = 7; n >= 0; n--) {
428             base = env->cp15.c6_region[n];
429             if ((base & 1) == 0)
430                 continue;
431             mask = 1 << ((base >> 1) & 0x1f);
432             /* Keep this shift separate from the above to avoid an
433                (undefined) << 32.  */
434             mask = (mask << 1) - 1;
435             if (((base ^ address) & ~mask) == 0)
436                 break;
437         }
438         if (n < 0)
439             return 2;
440
441         if (access_type == 2) {
442             mask = env->cp15.c5_insn;
443         } else {
444             mask = env->cp15.c5_data;
445         }
446         mask = (mask >> (n * 4)) & 0xf;
447         switch (mask) {
448         case 0:
449             return 1;
450         case 1:
451             if (is_user)
452               return 1;
453             *prot = PAGE_READ | PAGE_WRITE;
454             break;
455         case 2:
456             *prot = PAGE_READ;
457             if (!is_user)
458                 *prot |= PAGE_WRITE;
459             break;
460         case 3:
461             *prot = PAGE_READ | PAGE_WRITE;
462             break;
463         case 5:
464             if (is_user)
465                 return 1;
466             *prot = PAGE_READ;
467             break;
468         case 6:
469             *prot = PAGE_READ;
470             break;
471         default:
472             /* Bad permission.  */
473             return 1;
474         }
475     } else {
476         /* Pagetable walk.  */
477         /* Lookup l1 descriptor.  */
478         table = (env->cp15.c2_base & 0xffffc000) | ((address >> 18) & 0x3ffc);
479         desc = ldl_phys(table);
480         type = (desc & 3);
481         domain = (env->cp15.c3 >> ((desc >> 4) & 0x1e)) & 3;
482         if (type == 0) {
483             /* Secton translation fault.  */
484             code = 5;
485             goto do_fault;
486         }
487         if (domain == 0 || domain == 2) {
488             if (type == 2)
489                 code = 9; /* Section domain fault.  */
490             else
491                 code = 11; /* Page domain fault.  */
492             goto do_fault;
493         }
494         if (type == 2) {
495             /* 1Mb section.  */
496             phys_addr = (desc & 0xfff00000) | (address & 0x000fffff);
497             ap = (desc >> 10) & 3;
498             code = 13;
499         } else {
500             /* Lookup l2 entry.  */
501             if (type == 1) {
502                 /* Coarse pagetable.  */
503                 table = (desc & 0xfffffc00) | ((address >> 10) & 0x3fc);
504             } else {
505                 /* Fine pagetable.  */
506                 table = (desc & 0xfffff000) | ((address >> 8) & 0xffc);
507             }
508             desc = ldl_phys(table);
509             switch (desc & 3) {
510             case 0: /* Page translation fault.  */
511                 code = 7;
512                 goto do_fault;
513             case 1: /* 64k page.  */
514                 phys_addr = (desc & 0xffff0000) | (address & 0xffff);
515                 ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
516                 break;
517             case 2: /* 4k page.  */
518                 phys_addr = (desc & 0xfffff000) | (address & 0xfff);
519                 ap = (desc >> (4 + ((address >> 13) & 6))) & 3;
520                 break;
521             case 3: /* 1k page.  */
522                 if (type == 1) {
523                     if (arm_feature(env, ARM_FEATURE_XSCALE))
524                         phys_addr = (desc & 0xfffff000) | (address & 0xfff);
525                     else {
526                         /* Page translation fault.  */
527                         code = 7;
528                         goto do_fault;
529                     }
530                 } else
531                     phys_addr = (desc & 0xfffffc00) | (address & 0x3ff);
532                 ap = (desc >> 4) & 3;
533                 break;
534             default:
535                 /* Never happens, but compiler isn't smart enough to tell.  */
536                 abort();
537             }
538             code = 15;
539         }
540         *prot = check_ap(env, ap, domain, access_type, is_user);
541         if (!*prot) {
542             /* Access permission fault.  */
543             goto do_fault;
544         }
545         *phys_ptr = phys_addr;
546     }
547     return 0;
548 do_fault:
549     return code | (domain << 4);
550 }
551
552 int cpu_arm_handle_mmu_fault (CPUState *env, target_ulong address,
553                               int access_type, int mmu_idx, int is_softmmu)
554 {
555     uint32_t phys_addr;
556     int prot;
557     int ret, is_user;
558
559     is_user = mmu_idx == MMU_USER_IDX;
560     ret = get_phys_addr(env, address, access_type, is_user, &phys_addr, &prot);
561     if (ret == 0) {
562         /* Map a single [sub]page.  */
563         phys_addr &= ~(uint32_t)0x3ff;
564         address &= ~(uint32_t)0x3ff;
565         return tlb_set_page (env, address, phys_addr, prot, mmu_idx,
566                              is_softmmu);
567     }
568
569     if (access_type == 2) {
570         env->cp15.c5_insn = ret;
571         env->cp15.c6_insn = address;
572         env->exception_index = EXCP_PREFETCH_ABORT;
573     } else {
574         env->cp15.c5_data = ret;
575         env->cp15.c6_data = address;
576         env->exception_index = EXCP_DATA_ABORT;
577     }
578     return 1;
579 }
580
581 target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
582 {
583     uint32_t phys_addr;
584     int prot;
585     int ret;
586
587     ret = get_phys_addr(env, addr, 0, 0, &phys_addr, &prot);
588
589     if (ret != 0)
590         return -1;
591
592     return phys_addr;
593 }
594
595 void helper_set_cp(CPUState *env, uint32_t insn, uint32_t val)
596 {
597     int cp_num = (insn >> 8) & 0xf;
598     int cp_info = (insn >> 5) & 7;
599     int src = (insn >> 16) & 0xf;
600     int operand = insn & 0xf;
601
602     if (env->cp[cp_num].cp_write)
603         env->cp[cp_num].cp_write(env->cp[cp_num].opaque,
604                                  cp_info, src, operand, val);
605 }
606
607 uint32_t helper_get_cp(CPUState *env, uint32_t insn)
608 {
609     int cp_num = (insn >> 8) & 0xf;
610     int cp_info = (insn >> 5) & 7;
611     int dest = (insn >> 16) & 0xf;
612     int operand = insn & 0xf;
613
614     if (env->cp[cp_num].cp_read)
615         return env->cp[cp_num].cp_read(env->cp[cp_num].opaque,
616                                        cp_info, dest, operand);
617     return 0;
618 }
619
620 /* Return basic MPU access permission bits.  */
621 static uint32_t simple_mpu_ap_bits(uint32_t val)
622 {
623     uint32_t ret;
624     uint32_t mask;
625     int i;
626     ret = 0;
627     mask = 3;
628     for (i = 0; i < 16; i += 2) {
629         ret |= (val >> i) & mask;
630         mask <<= 2;
631     }
632     return ret;
633 }
634
635 /* Pad basic MPU access permission bits to extended format.  */
636 static uint32_t extended_mpu_ap_bits(uint32_t val)
637 {
638     uint32_t ret;
639     uint32_t mask;
640     int i;
641     ret = 0;
642     mask = 3;
643     for (i = 0; i < 16; i += 2) {
644         ret |= (val & mask) << i;
645         mask <<= 2;
646     }
647     return ret;
648 }
649
650 void helper_set_cp15(CPUState *env, uint32_t insn, uint32_t val)
651 {
652     uint32_t op2;
653     uint32_t crm;
654
655     op2 = (insn >> 5) & 7;
656     crm = insn & 0xf;
657     switch ((insn >> 16) & 0xf) {
658     case 0: /* ID codes.  */
659         if (arm_feature(env, ARM_FEATURE_XSCALE))
660             break;
661         if (arm_feature(env, ARM_FEATURE_OMAPCP))
662             break;
663         goto bad_reg;
664     case 1: /* System configuration.  */
665         if (arm_feature(env, ARM_FEATURE_OMAPCP))
666             op2 = 0;
667         switch (op2) {
668         case 0:
669             if (!arm_feature(env, ARM_FEATURE_XSCALE) || crm == 0)
670                 env->cp15.c1_sys = val;
671             /* ??? Lots of these bits are not implemented.  */
672             /* This may enable/disable the MMU, so do a TLB flush.  */
673             tlb_flush(env, 1);
674             break;
675         case 1:
676             if (arm_feature(env, ARM_FEATURE_XSCALE)) {
677                 env->cp15.c1_xscaleauxcr = val;
678                 break;
679             }
680             goto bad_reg;
681         case 2:
682             if (arm_feature(env, ARM_FEATURE_XSCALE))
683                 goto bad_reg;
684             env->cp15.c1_coproc = val;
685             /* ??? Is this safe when called from within a TB?  */
686             tb_flush(env);
687             break;
688         default:
689             goto bad_reg;
690         }
691         break;
692     case 2: /* MMU Page table control / MPU cache control.  */
693         if (arm_feature(env, ARM_FEATURE_MPU)) {
694             switch (op2) {
695             case 0:
696                 env->cp15.c2_data = val;
697                 break;
698             case 1:
699                 env->cp15.c2_insn = val;
700                 break;
701             default:
702                 goto bad_reg;
703             }
704         } else {
705             env->cp15.c2_base = val;
706         }
707         break;
708     case 3: /* MMU Domain access control / MPU write buffer control.  */
709         env->cp15.c3 = val;
710         tlb_flush(env, 1); /* Flush TLB as domain not tracked in TLB */
711         break;
712     case 4: /* Reserved.  */
713         goto bad_reg;
714     case 5: /* MMU Fault status / MPU access permission.  */
715         if (arm_feature(env, ARM_FEATURE_OMAPCP))
716             op2 = 0;
717         switch (op2) {
718         case 0:
719             if (arm_feature(env, ARM_FEATURE_MPU))
720                 val = extended_mpu_ap_bits(val);
721             env->cp15.c5_data = val;
722             break;
723         case 1:
724             if (arm_feature(env, ARM_FEATURE_MPU))
725                 val = extended_mpu_ap_bits(val);
726             env->cp15.c5_insn = val;
727             break;
728         case 2:
729             if (!arm_feature(env, ARM_FEATURE_MPU))
730                 goto bad_reg;
731             env->cp15.c5_data = val;
732             break;
733         case 3:
734             if (!arm_feature(env, ARM_FEATURE_MPU))
735                 goto bad_reg;
736             env->cp15.c5_insn = val;
737             break;
738         default:
739             goto bad_reg;
740         }
741         break;
742     case 6: /* MMU Fault address / MPU base/size.  */
743         if (arm_feature(env, ARM_FEATURE_MPU)) {
744             if (crm >= 8)
745                 goto bad_reg;
746             env->cp15.c6_region[crm] = val;
747         } else {
748             if (arm_feature(env, ARM_FEATURE_OMAPCP))
749                 op2 = 0;
750             switch (op2) {
751             case 0:
752                 env->cp15.c6_data = val;
753                 break;
754             case 1:
755                 env->cp15.c6_insn = val;
756                 break;
757             default:
758                 goto bad_reg;
759             }
760         }
761         break;
762     case 7: /* Cache control.  */
763         env->cp15.c15_i_max = 0x000;
764         env->cp15.c15_i_min = 0xff0;
765         /* No cache, so nothing to do.  */
766         break;
767     case 8: /* MMU TLB control.  */
768         switch (op2) {
769         case 0: /* Invalidate all.  */
770             tlb_flush(env, 0);
771             break;
772         case 1: /* Invalidate single TLB entry.  */
773 #if 0
774             /* ??? This is wrong for large pages and sections.  */
775             /* As an ugly hack to make linux work we always flush a 4K
776                pages.  */
777             val &= 0xfffff000;
778             tlb_flush_page(env, val);
779             tlb_flush_page(env, val + 0x400);
780             tlb_flush_page(env, val + 0x800);
781             tlb_flush_page(env, val + 0xc00);
782 #else
783             tlb_flush(env, 1);
784 #endif
785             break;
786         default:
787             goto bad_reg;
788         }
789         break;
790     case 9:
791         if (arm_feature(env, ARM_FEATURE_OMAPCP))
792             break;
793         switch (crm) {
794         case 0: /* Cache lockdown.  */
795             switch (op2) {
796             case 0:
797                 env->cp15.c9_data = val;
798                 break;
799             case 1:
800                 env->cp15.c9_insn = val;
801                 break;
802             default:
803                 goto bad_reg;
804             }
805             break;
806         case 1: /* TCM memory region registers.  */
807             /* Not implemented.  */
808             goto bad_reg;
809         default:
810             goto bad_reg;
811         }
812         break;
813     case 10: /* MMU TLB lockdown.  */
814         /* ??? TLB lockdown not implemented.  */
815         break;
816     case 12: /* Reserved.  */
817         goto bad_reg;
818     case 13: /* Process ID.  */
819         switch (op2) {
820         case 0:
821             /* Unlike real hardware the qemu TLB uses virtual addresses,
822                not modified virtual addresses, so this causes a TLB flush.
823              */
824             if (env->cp15.c13_fcse != val)
825               tlb_flush(env, 1);
826             env->cp15.c13_fcse = val;
827             break;
828         case 1:
829             /* This changes the ASID, so do a TLB flush.  */
830             if (env->cp15.c13_context != val
831                 && !arm_feature(env, ARM_FEATURE_MPU))
832               tlb_flush(env, 0);
833             env->cp15.c13_context = val;
834             break;
835         default:
836             goto bad_reg;
837         }
838         break;
839     case 14: /* Reserved.  */
840         goto bad_reg;
841     case 15: /* Implementation specific.  */
842         if (arm_feature(env, ARM_FEATURE_XSCALE)) {
843             if (op2 == 0 && crm == 1) {
844                 if (env->cp15.c15_cpar != (val & 0x3fff)) {
845                     /* Changes cp0 to cp13 behavior, so needs a TB flush.  */
846                     tb_flush(env);
847                     env->cp15.c15_cpar = val & 0x3fff;
848                 }
849                 break;
850             }
851             goto bad_reg;
852         }
853         if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
854             switch (crm) {
855             case 0:
856                 break;
857             case 1: /* Set TI925T configuration.  */
858                 env->cp15.c15_ticonfig = val & 0xe7;
859                 env->cp15.c0_cpuid = (val & (1 << 5)) ? /* OS_TYPE bit */
860                         ARM_CPUID_TI915T : ARM_CPUID_TI925T;
861                 break;
862             case 2: /* Set I_max.  */
863                 env->cp15.c15_i_max = val;
864                 break;
865             case 3: /* Set I_min.  */
866                 env->cp15.c15_i_min = val;
867                 break;
868             case 4: /* Set thread-ID.  */
869                 env->cp15.c15_threadid = val & 0xffff;
870                 break;
871             case 8: /* Wait-for-interrupt (deprecated).  */
872                 cpu_interrupt(env, CPU_INTERRUPT_HALT);
873                 break;
874             default:
875                 goto bad_reg;
876             }
877         }
878         break;
879     }
880     return;
881 bad_reg:
882     /* ??? For debugging only.  Should raise illegal instruction exception.  */
883     cpu_abort(env, "Unimplemented cp15 register write\n");
884 }
885
886 uint32_t helper_get_cp15(CPUState *env, uint32_t insn)
887 {
888     uint32_t op2;
889     uint32_t crm;
890
891     op2 = (insn >> 5) & 7;
892     crm = insn & 0xf;
893     switch ((insn >> 16) & 0xf) {
894     case 0: /* ID codes.  */
895         switch (op2) {
896         default: /* Device ID.  */
897             return env->cp15.c0_cpuid;
898         case 1: /* Cache Type.  */
899             return env->cp15.c0_cachetype;
900         case 2: /* TCM status.  */
901             if (arm_feature(env, ARM_FEATURE_XSCALE))
902                 goto bad_reg;
903             return 0;
904         }
905     case 1: /* System configuration.  */
906         if (arm_feature(env, ARM_FEATURE_OMAPCP))
907             op2 = 0;
908         switch (op2) {
909         case 0: /* Control register.  */
910             return env->cp15.c1_sys;
911         case 1: /* Auxiliary control register.  */
912             if (arm_feature(env, ARM_FEATURE_AUXCR))
913                 return 1;
914             if (arm_feature(env, ARM_FEATURE_XSCALE))
915                 return env->cp15.c1_xscaleauxcr;
916             goto bad_reg;
917         case 2: /* Coprocessor access register.  */
918             if (arm_feature(env, ARM_FEATURE_XSCALE))
919                 goto bad_reg;
920             return env->cp15.c1_coproc;
921         default:
922             goto bad_reg;
923         }
924     case 2: /* MMU Page table control / MPU cache control.  */
925         if (arm_feature(env, ARM_FEATURE_MPU)) {
926             switch (op2) {
927             case 0:
928                 return env->cp15.c2_data;
929                 break;
930             case 1:
931                 return env->cp15.c2_insn;
932                 break;
933             default:
934                 goto bad_reg;
935             }
936         } else {
937             return env->cp15.c2_base;
938         }
939     case 3: /* MMU Domain access control / MPU write buffer control.  */
940         return env->cp15.c3;
941     case 4: /* Reserved.  */
942         goto bad_reg;
943     case 5: /* MMU Fault status / MPU access permission.  */
944         if (arm_feature(env, ARM_FEATURE_OMAPCP))
945             op2 = 0;
946         switch (op2) {
947         case 0:
948             if (arm_feature(env, ARM_FEATURE_MPU))
949                 return simple_mpu_ap_bits(env->cp15.c5_data);
950             return env->cp15.c5_data;
951         case 1:
952             if (arm_feature(env, ARM_FEATURE_MPU))
953                 return simple_mpu_ap_bits(env->cp15.c5_data);
954             return env->cp15.c5_insn;
955         case 2:
956             if (!arm_feature(env, ARM_FEATURE_MPU))
957                 goto bad_reg;
958             return env->cp15.c5_data;
959         case 3:
960             if (!arm_feature(env, ARM_FEATURE_MPU))
961                 goto bad_reg;
962             return env->cp15.c5_insn;
963         default:
964             goto bad_reg;
965         }
966     case 6: /* MMU Fault address / MPU base/size.  */
967         if (arm_feature(env, ARM_FEATURE_MPU)) {
968             int n;
969             n = (insn & 0xf);
970             if (n >= 8)
971                 goto bad_reg;
972             return env->cp15.c6_region[n];
973         } else {
974             if (arm_feature(env, ARM_FEATURE_OMAPCP))
975                 op2 = 0;
976             switch (op2) {
977             case 0:
978                 return env->cp15.c6_data;
979             case 1:
980                 /* Arm9 doesn't have an IFAR, but implementing it anyway
981                    shouldn't do any harm.  */
982                 return env->cp15.c6_insn;
983             default:
984                 goto bad_reg;
985             }
986         }
987     case 7: /* Cache control.  */
988         /* ??? This is for test, clean and invaidate operations that set the
989            Z flag.  We can't represent N = Z = 1, so it also clears
990            the N flag.  Oh well.  */
991         env->NZF = 0;
992         return 0;
993     case 8: /* MMU TLB control.  */
994         goto bad_reg;
995     case 9: /* Cache lockdown.  */
996         if (arm_feature(env, ARM_FEATURE_OMAPCP))
997             return 0;
998         switch (op2) {
999         case 0:
1000             return env->cp15.c9_data;
1001         case 1:
1002             return env->cp15.c9_insn;
1003         default:
1004             goto bad_reg;
1005         }
1006     case 10: /* MMU TLB lockdown.  */
1007         /* ??? TLB lockdown not implemented.  */
1008         return 0;
1009     case 11: /* TCM DMA control.  */
1010     case 12: /* Reserved.  */
1011         goto bad_reg;
1012     case 13: /* Process ID.  */
1013         switch (op2) {
1014         case 0:
1015             return env->cp15.c13_fcse;
1016         case 1:
1017             return env->cp15.c13_context;
1018         default:
1019             goto bad_reg;
1020         }
1021     case 14: /* Reserved.  */
1022         goto bad_reg;
1023     case 15: /* Implementation specific.  */
1024         if (arm_feature(env, ARM_FEATURE_XSCALE)) {
1025             if (op2 == 0 && crm == 1)
1026                 return env->cp15.c15_cpar;
1027
1028             goto bad_reg;
1029         }
1030         if (arm_feature(env, ARM_FEATURE_OMAPCP)) {
1031             switch (crm) {
1032             case 0:
1033                 return 0;
1034             case 1: /* Read TI925T configuration.  */
1035                 return env->cp15.c15_ticonfig;
1036             case 2: /* Read I_max.  */
1037                 return env->cp15.c15_i_max;
1038             case 3: /* Read I_min.  */
1039                 return env->cp15.c15_i_min;
1040             case 4: /* Read thread-ID.  */
1041                 return env->cp15.c15_threadid;
1042             case 8: /* TI925T_status */
1043                 return 0;
1044             }
1045             goto bad_reg;
1046         }
1047         return 0;
1048     }
1049 bad_reg:
1050     /* ??? For debugging only.  Should raise illegal instruction exception.  */
1051     cpu_abort(env, "Unimplemented cp15 register read\n");
1052     return 0;
1053 }
1054
1055 void cpu_arm_set_cp_io(CPUARMState *env, int cpnum,
1056                 ARMReadCPFunc *cp_read, ARMWriteCPFunc *cp_write,
1057                 void *opaque)
1058 {
1059     if (cpnum < 0 || cpnum > 14) {
1060         cpu_abort(env, "Bad coprocessor number: %i\n", cpnum);
1061         return;
1062     }
1063
1064     env->cp[cpnum].cp_read = cp_read;
1065     env->cp[cpnum].cp_write = cp_write;
1066     env->cp[cpnum].opaque = opaque;
1067 }
1068
1069 #endif