25 |
* SUCH DAMAGE. |
* SUCH DAMAGE. |
26 |
* |
* |
27 |
* |
* |
28 |
* $Id: cpu_arm.c,v 1.28 2005/10/07 10:26:03 debug Exp $ |
* $Id: cpu_arm.c,v 1.35 2005/10/23 14:24:13 debug Exp $ |
29 |
* |
* |
30 |
* ARM CPU emulation. |
* ARM CPU emulation. |
31 |
* |
* |
62 |
static int arm_dpi_uses_d[16] = { 1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1 }; |
static int arm_dpi_uses_d[16] = { 1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1 }; |
63 |
static int arm_dpi_uses_n[16] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0 }; |
static int arm_dpi_uses_n[16] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0 }; |
64 |
|
|
65 |
/* Forward reference: */ |
/* For quick_pc_to_pointers(): */ |
66 |
void arm_pc_to_pointers(struct cpu *cpu); |
#include "arm_quick_pc_to_pointers.h" |
67 |
|
|
68 |
|
|
69 |
/* |
/* |
92 |
|
|
93 |
cpu->memory_rw = arm_memory_rw; |
cpu->memory_rw = arm_memory_rw; |
94 |
cpu->update_translation_table = arm_update_translation_table; |
cpu->update_translation_table = arm_update_translation_table; |
95 |
cpu->invalidate_translation_caches_paddr = |
cpu->invalidate_translation_caches = |
96 |
arm_invalidate_translation_caches_paddr; |
arm_invalidate_translation_caches; |
97 |
cpu->invalidate_code_translation = arm_invalidate_code_translation; |
cpu->invalidate_code_translation = arm_invalidate_code_translation; |
98 |
cpu->translate_address = arm_translate_address; |
cpu->translate_address = arm_translate_address; |
99 |
|
|
109 |
cpu->cd.arm.cpsr |= ARM_MODE_SVC32; |
cpu->cd.arm.cpsr |= ARM_MODE_SVC32; |
110 |
cpu->cd.arm.control |= ARM_CONTROL_S; |
cpu->cd.arm.control |= ARM_CONTROL_S; |
111 |
} else { |
} else { |
112 |
cpu->cd.arm.cpsr |= ARM_MODE_USR32; |
cpu->cd.arm.cpsr |= ARM_MODE_SVC32; |
113 |
cpu->cd.arm.control |= ARM_CONTROL_S | ARM_CONTROL_R; |
cpu->cd.arm.control |= ARM_CONTROL_R; |
114 |
} |
} |
115 |
|
|
116 |
/* Only show name and caches etc for CPU nr 0: */ |
/* Only show name and caches etc for CPU nr 0: */ |
163 |
} |
} |
164 |
|
|
165 |
cpu->cd.arm.control |= ARM_CONTROL_MMU; |
cpu->cd.arm.control |= ARM_CONTROL_MMU; |
166 |
|
cpu->translate_address = arm_translate_address_mmu; |
167 |
cpu->cd.arm.dacr |= 0x00000003; |
cpu->cd.arm.dacr |= 0x00000003; |
168 |
cpu->cd.arm.ttb = ttb_addr; |
cpu->cd.arm.ttb = ttb_addr; |
169 |
|
|
176 |
uint32_t addr = cpu->cd.arm.ttb + |
uint32_t addr = cpu->cd.arm.ttb + |
177 |
(((j << 28) + (i << 20)) >> 18); |
(((j << 28) + (i << 20)) >> 18); |
178 |
uint32_t d = (1048576*i) | 0xc02; |
uint32_t d = (1048576*i) | 0xc02; |
179 |
|
|
180 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) { |
181 |
|
descr[0] = d; descr[1] = d >> 8; |
182 |
|
descr[2] = d >> 16; descr[3] = d >> 24; |
183 |
|
} else { |
184 |
|
descr[3] = d; descr[2] = d >> 8; |
185 |
|
descr[1] = d >> 16; descr[0] = d >> 24; |
186 |
|
} |
187 |
|
cpu->memory_rw(cpu, cpu->mem, addr, &descr[0], |
188 |
|
sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS); |
189 |
|
} |
190 |
|
} |
191 |
|
|
192 |
|
|
193 |
|
/* |
194 |
|
* arm_translation_table_set_l1(): |
195 |
|
*/ |
196 |
|
void arm_translation_table_set_l1(struct cpu *cpu, uint32_t vaddr, |
197 |
|
uint32_t paddr) |
198 |
|
{ |
199 |
|
unsigned int i, j, vhigh = vaddr >> 28, phigh = paddr >> 28; |
200 |
|
|
201 |
|
for (i=0; i<256; i++) |
202 |
|
for (j=vhigh; j<=vhigh; j++) { |
203 |
|
unsigned char descr[4]; |
204 |
|
uint32_t addr = cpu->cd.arm.ttb + |
205 |
|
(((j << 28) + (i << 20)) >> 18); |
206 |
|
uint32_t d = ((phigh << 28) + 1048576*i) | 0xc02; |
207 |
|
|
208 |
|
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) { |
209 |
|
descr[0] = d; descr[1] = d >> 8; |
210 |
|
descr[2] = d >> 16; descr[3] = d >> 24; |
211 |
|
} else { |
212 |
|
descr[3] = d; descr[2] = d >> 8; |
213 |
|
descr[1] = d >> 16; descr[0] = d >> 24; |
214 |
|
} |
215 |
|
cpu->memory_rw(cpu, cpu->mem, addr, &descr[0], |
216 |
|
sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS); |
217 |
|
} |
218 |
|
} |
219 |
|
|
220 |
|
|
221 |
/* |
/* |
222 |
d = (1048576 * (i + (j==12? 10 : j)*256)) | 2; |
* arm_translation_table_set_l1_b(): |
223 |
*/ |
*/ |
224 |
|
void arm_translation_table_set_l1_b(struct cpu *cpu, uint32_t vaddr, |
225 |
|
uint32_t paddr) |
226 |
|
{ |
227 |
|
unsigned int i, j, vhigh = vaddr >> 24, phigh = paddr >> 24; |
228 |
|
|
229 |
|
for (i=0; i<16; i++) |
230 |
|
for (j=vhigh; j<=vhigh; j++) { |
231 |
|
unsigned char descr[4]; |
232 |
|
uint32_t addr = cpu->cd.arm.ttb + |
233 |
|
(((j << 24) + (i << 20)) >> 18); |
234 |
|
uint32_t d = ((phigh << 24) + 1048576*i) | 0xc02; |
235 |
|
|
236 |
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) { |
if (cpu->byte_order == EMUL_LITTLE_ENDIAN) { |
237 |
descr[0] = d; descr[1] = d >> 8; |
descr[0] = d; descr[1] = d >> 8; |
238 |
descr[2] = d >> 16; descr[3] = d >> 24; |
descr[2] = d >> 16; descr[3] = d >> 24; |
497 |
&cpu->cd.arm.r[8], sizeof(uint32_t) * 7); |
&cpu->cd.arm.r[8], sizeof(uint32_t) * 7); |
498 |
break; |
break; |
499 |
case ARM_MODE_IRQ32: |
case ARM_MODE_IRQ32: |
500 |
|
memcpy(cpu->cd.arm.default_r8_r14, |
501 |
|
&cpu->cd.arm.r[8], sizeof(uint32_t) * 5); |
502 |
cpu->cd.arm.irq_r13_r14[0] = cpu->cd.arm.r[13]; |
cpu->cd.arm.irq_r13_r14[0] = cpu->cd.arm.r[13]; |
503 |
cpu->cd.arm.irq_r13_r14[1] = cpu->cd.arm.r[14]; |
cpu->cd.arm.irq_r13_r14[1] = cpu->cd.arm.r[14]; |
504 |
break; |
break; |
505 |
case ARM_MODE_SVC32: |
case ARM_MODE_SVC32: |
506 |
if ((cpu->cd.arm.r[13] & 0xffff0000) == 0xffff0000) { |
memcpy(cpu->cd.arm.default_r8_r14, |
507 |
fatal("NEJ! pc=0x%08x\n", (int)cpu->pc); |
&cpu->cd.arm.r[8], sizeof(uint32_t) * 5); |
|
exit(1); |
|
|
} |
|
508 |
cpu->cd.arm.svc_r13_r14[0] = cpu->cd.arm.r[13]; |
cpu->cd.arm.svc_r13_r14[0] = cpu->cd.arm.r[13]; |
509 |
cpu->cd.arm.svc_r13_r14[1] = cpu->cd.arm.r[14]; |
cpu->cd.arm.svc_r13_r14[1] = cpu->cd.arm.r[14]; |
510 |
break; |
break; |
511 |
case ARM_MODE_ABT32: |
case ARM_MODE_ABT32: |
512 |
|
memcpy(cpu->cd.arm.default_r8_r14, |
513 |
|
&cpu->cd.arm.r[8], sizeof(uint32_t) * 5); |
514 |
cpu->cd.arm.abt_r13_r14[0] = cpu->cd.arm.r[13]; |
cpu->cd.arm.abt_r13_r14[0] = cpu->cd.arm.r[13]; |
515 |
cpu->cd.arm.abt_r13_r14[1] = cpu->cd.arm.r[14]; |
cpu->cd.arm.abt_r13_r14[1] = cpu->cd.arm.r[14]; |
516 |
break; |
break; |
517 |
case ARM_MODE_UND32: |
case ARM_MODE_UND32: |
518 |
|
memcpy(cpu->cd.arm.default_r8_r14, |
519 |
|
&cpu->cd.arm.r[8], sizeof(uint32_t) * 5); |
520 |
cpu->cd.arm.und_r13_r14[0] = cpu->cd.arm.r[13]; |
cpu->cd.arm.und_r13_r14[0] = cpu->cd.arm.r[13]; |
521 |
cpu->cd.arm.und_r13_r14[1] = cpu->cd.arm.r[14]; |
cpu->cd.arm.und_r13_r14[1] = cpu->cd.arm.r[14]; |
522 |
break; |
break; |
544 |
sizeof(uint32_t) * 7); |
sizeof(uint32_t) * 7); |
545 |
break; |
break; |
546 |
case ARM_MODE_IRQ32: |
case ARM_MODE_IRQ32: |
547 |
|
memcpy(&cpu->cd.arm.r[8], |
548 |
|
cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5); |
549 |
cpu->cd.arm.r[13] = cpu->cd.arm.irq_r13_r14[0]; |
cpu->cd.arm.r[13] = cpu->cd.arm.irq_r13_r14[0]; |
550 |
cpu->cd.arm.r[14] = cpu->cd.arm.irq_r13_r14[1]; |
cpu->cd.arm.r[14] = cpu->cd.arm.irq_r13_r14[1]; |
551 |
break; |
break; |
552 |
case ARM_MODE_SVC32: |
case ARM_MODE_SVC32: |
553 |
|
memcpy(&cpu->cd.arm.r[8], |
554 |
|
cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5); |
555 |
cpu->cd.arm.r[13] = cpu->cd.arm.svc_r13_r14[0]; |
cpu->cd.arm.r[13] = cpu->cd.arm.svc_r13_r14[0]; |
556 |
cpu->cd.arm.r[14] = cpu->cd.arm.svc_r13_r14[1]; |
cpu->cd.arm.r[14] = cpu->cd.arm.svc_r13_r14[1]; |
557 |
break; |
break; |
558 |
case ARM_MODE_ABT32: |
case ARM_MODE_ABT32: |
559 |
|
memcpy(&cpu->cd.arm.r[8], |
560 |
|
cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5); |
561 |
cpu->cd.arm.r[13] = cpu->cd.arm.abt_r13_r14[0]; |
cpu->cd.arm.r[13] = cpu->cd.arm.abt_r13_r14[0]; |
562 |
cpu->cd.arm.r[14] = cpu->cd.arm.abt_r13_r14[1]; |
cpu->cd.arm.r[14] = cpu->cd.arm.abt_r13_r14[1]; |
563 |
break; |
break; |
564 |
case ARM_MODE_UND32: |
case ARM_MODE_UND32: |
565 |
|
memcpy(&cpu->cd.arm.r[8], |
566 |
|
cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5); |
567 |
cpu->cd.arm.r[13] = cpu->cd.arm.und_r13_r14[0]; |
cpu->cd.arm.r[13] = cpu->cd.arm.und_r13_r14[0]; |
568 |
cpu->cd.arm.r[14] = cpu->cd.arm.und_r13_r14[1]; |
cpu->cd.arm.r[14] = cpu->cd.arm.und_r13_r14[1]; |
569 |
break; |
break; |
590 |
|
|
591 |
retaddr = cpu->pc; |
retaddr = cpu->pc; |
592 |
|
|
593 |
debug("[ arm_exception(): "); |
if (!quiet_mode) { |
594 |
|
debug("[ arm_exception(): "); |
595 |
|
switch (exception_nr) { |
596 |
|
case ARM_EXCEPTION_RESET: |
597 |
|
fatal("RESET: TODO"); |
598 |
|
break; |
599 |
|
case ARM_EXCEPTION_UND: |
600 |
|
debug("UNDEFINED"); |
601 |
|
break; |
602 |
|
case ARM_EXCEPTION_SWI: |
603 |
|
debug("SWI"); |
604 |
|
break; |
605 |
|
case ARM_EXCEPTION_PREF_ABT: |
606 |
|
debug("PREFETCH ABORT"); |
607 |
|
break; |
608 |
|
case ARM_EXCEPTION_IRQ: |
609 |
|
debug("IRQ"); |
610 |
|
break; |
611 |
|
case ARM_EXCEPTION_FIQ: |
612 |
|
debug("FIQ"); |
613 |
|
break; |
614 |
|
case ARM_EXCEPTION_DATA_ABT: |
615 |
|
debug("DATA ABORT, far=0x%08x fsr=0x%02x", |
616 |
|
cpu->cd.arm.far, cpu->cd.arm.fsr); |
617 |
|
break; |
618 |
|
} |
619 |
|
debug(" ]\n"); |
620 |
|
} |
621 |
|
|
622 |
switch (exception_nr) { |
switch (exception_nr) { |
623 |
case ARM_EXCEPTION_RESET: |
case ARM_EXCEPTION_RESET: |
624 |
cpu->running = 0; |
cpu->running = 0; |
625 |
fatal("RESET: TODO"); |
fatal("ARM RESET: TODO"); |
626 |
exit(1); |
exit(1); |
|
case ARM_EXCEPTION_UND: |
|
|
debug("UNDEFINED"); |
|
|
retaddr += 4; |
|
|
break; |
|
|
case ARM_EXCEPTION_SWI: |
|
|
debug("SWI"); |
|
|
retaddr += 4; |
|
|
break; |
|
|
case ARM_EXCEPTION_PREF_ABT: |
|
|
debug("PREFETCH ABORT"); |
|
|
retaddr += 4; |
|
|
break; |
|
|
case ARM_EXCEPTION_IRQ: |
|
|
debug("IRQ"); |
|
|
retaddr += 4; |
|
|
break; |
|
|
case ARM_EXCEPTION_FIQ: |
|
|
debug("FIQ"); |
|
|
retaddr += 4; |
|
|
break; |
|
627 |
case ARM_EXCEPTION_DATA_ABT: |
case ARM_EXCEPTION_DATA_ABT: |
628 |
debug("DATA ABORT, far=0x%08x fsr=0x%02x", |
retaddr += 4; |
|
cpu->cd.arm.far, cpu->cd.arm.fsr); |
|
|
retaddr += 8; |
|
629 |
break; |
break; |
630 |
} |
} |
631 |
|
|
632 |
debug(" ]\n"); |
retaddr += 4; |
633 |
|
|
634 |
arm_save_register_bank(cpu); |
arm_save_register_bank(cpu); |
635 |
|
|
678 |
|
|
679 |
cpu->pc = cpu->cd.arm.r[ARM_PC] = exception_nr * 4 + |
cpu->pc = cpu->cd.arm.r[ARM_PC] = exception_nr * 4 + |
680 |
((cpu->cd.arm.control & ARM_CONTROL_V)? 0xffff0000 : 0); |
((cpu->cd.arm.control & ARM_CONTROL_V)? 0xffff0000 : 0); |
681 |
arm_pc_to_pointers(cpu); |
quick_pc_to_pointers(cpu); |
682 |
} |
} |
683 |
|
|
684 |
|
|
876 |
* xxxx000P U1WLnnnn ddddHHHH 1SH1LLLL load/store rd,imm(rn) |
* xxxx000P U1WLnnnn ddddHHHH 1SH1LLLL load/store rd,imm(rn) |
877 |
*/ |
*/ |
878 |
if ((iw & 0x0e000090) == 0x00000090) { |
if ((iw & 0x0e000090) == 0x00000090) { |
879 |
|
char *op = "st"; |
880 |
int imm = ((iw >> 4) & 0xf0) | (iw & 0xf); |
int imm = ((iw >> 4) & 0xf0) | (iw & 0xf); |
881 |
int regform = !(iw & 0x00400000); |
int regform = !(iw & 0x00400000); |
882 |
p_bit = main_opcode & 1; |
p_bit = main_opcode & 1; |
889 |
break; |
break; |
890 |
} |
} |
891 |
/* Semi-generic case: */ |
/* Semi-generic case: */ |
892 |
debug("%sr%s", iw & 0x00100000? "ld" : "st", |
if (iw & 0x00100000) |
893 |
condition); |
op = "ld"; |
894 |
|
if (!l_bit && (iw & 0xd0) == 0xd0) |
895 |
|
op = iw & 0x20? "st" : "ld"; |
896 |
|
debug("%sr%s", op, condition); |
897 |
if (!l_bit && (iw & 0xd0) == 0xd0) { |
if (!l_bit && (iw & 0xd0) == 0xd0) { |
898 |
debug("d"); /* Double-register */ |
debug("d"); /* Double-register */ |
899 |
} else { |
} else { |