/[gxemul]/upstream/0.3.6.2/src/cpus/cpu_arm.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /upstream/0.3.6.2/src/cpus/cpu_arm.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 19 - (show annotations)
Mon Oct 8 16:19:16 2007 UTC (16 years, 8 months ago) by dpavlin
File MIME type: text/plain
File size: 33418 byte(s)
0.3.6.2
1 /*
2 * Copyright (C) 2005 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_arm.c,v 1.35 2005/10/23 14:24:13 debug Exp $
29 *
30 * ARM CPU emulation.
31 *
32 * A good source of quick info on ARM instruction encoding:
33 *
34 * http://www.pinknoise.demon.co.uk/ARMinstrs/ARMinstrs.html
35 *
36 * (Most "xxxx0101..." and similar strings in this file are from that URL,
37 * or from the ARM manual.)
38 */
39
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <string.h>
43 #include <ctype.h>
44
45 #include "arm_cpu_types.h"
46 #include "cpu.h"
47 #include "machine.h"
48 #include "memory.h"
49 #include "misc.h"
50 #include "symbol.h"
51
52 #define DYNTRANS_32
53 #include "tmp_arm_head.c"
54
55
56 /* ARM symbolic register names and condition strings: */
57 static char *arm_regname[N_ARM_REGS] = ARM_REG_NAMES;
58 static char *arm_condition_string[16] = ARM_CONDITION_STRINGS;
59
60 /* Data Processing Instructions: */
61 static char *arm_dpiname[16] = ARM_DPI_NAMES;
62 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 };
64
65 /* For quick_pc_to_pointers(): */
66 #include "arm_quick_pc_to_pointers.h"
67
68
69 /*
70 * arm_cpu_new():
71 *
72 * Create a new ARM cpu object by filling the CPU struct.
73 * Return 1 on success, 0 if cpu_type_name isn't a valid ARM processor.
74 */
75 int arm_cpu_new(struct cpu *cpu, struct memory *mem,
76 struct machine *machine, int cpu_id, char *cpu_type_name)
77 {
78 int any_cache = 0, i, found;
79 struct arm_cpu_type_def cpu_type_defs[] = ARM_CPU_TYPE_DEFS;
80
81 /* Scan the list for this cpu type: */
82 i = 0; found = -1;
83 while (i >= 0 && cpu_type_defs[i].name != NULL) {
84 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
85 found = i;
86 break;
87 }
88 i++;
89 }
90 if (found == -1)
91 return 0;
92
93 cpu->memory_rw = arm_memory_rw;
94 cpu->update_translation_table = arm_update_translation_table;
95 cpu->invalidate_translation_caches =
96 arm_invalidate_translation_caches;
97 cpu->invalidate_code_translation = arm_invalidate_code_translation;
98 cpu->translate_address = arm_translate_address;
99
100 cpu->cd.arm.cpu_type = cpu_type_defs[found];
101 cpu->name = cpu->cd.arm.cpu_type.name;
102 cpu->is_32bit = 1;
103
104 cpu->cd.arm.cpsr = ARM_FLAG_I | ARM_FLAG_F;
105 cpu->cd.arm.control = ARM_CONTROL_PROG32 | ARM_CONTROL_DATA32
106 | ARM_CONTROL_CACHE | ARM_CONTROL_ICACHE | ARM_CONTROL_ALIGN;
107
108 if (cpu->machine->prom_emulation) {
109 cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
110 cpu->cd.arm.control |= ARM_CONTROL_S;
111 } else {
112 cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
113 cpu->cd.arm.control |= ARM_CONTROL_R;
114 }
115
116 /* Only show name and caches etc for CPU nr 0: */
117 if (cpu_id == 0) {
118 debug("%s", cpu->name);
119 if (cpu->cd.arm.cpu_type.icache_shift != 0)
120 any_cache = 1;
121 if (cpu->cd.arm.cpu_type.dcache_shift != 0)
122 any_cache = 1;
123 if (any_cache) {
124 debug(" (I+D = %i+%i KB",
125 (int)(1 << (cpu->cd.arm.cpu_type.icache_shift-10)),
126 (int)(1 << (cpu->cd.arm.cpu_type.dcache_shift-10)));
127 debug(")");
128 }
129 }
130
131 /* Coprocessor 15 = the system control coprocessor. */
132 cpu->cd.arm.coproc[15] = arm_coproc_15;
133
134 /*
135 * NOTE/TODO: Ugly hack for OpenFirmware emulation:
136 */
137 if (cpu->machine->prom_emulation) {
138 cpu->cd.arm.of_emul_addr = cpu->machine->physical_ram_in_mb
139 * 1048576 - 8;
140 store_32bit_word(cpu, cpu->cd.arm.of_emul_addr, 0xef8c64be);
141 }
142
143 return 1;
144 }
145
146
147 /*
148 * arm_setup_initial_translation_table():
149 *
150 * When booting kernels (such as OpenBSD or NetBSD) directly, it is assumed
151 * that the MMU is already enabled by the boot-loader. This function tries
152 * to emulate that.
153 */
154 void arm_setup_initial_translation_table(struct cpu *cpu, uint32_t ttb_addr)
155 {
156 unsigned char nothing[16384];
157 unsigned int i, j;
158
159 if (cpu->machine->userland_emul != NULL) {
160 fatal("arm_setup_initial_translation_table(): should not "
161 "be called for userland emulation!\n");
162 exit(1);
163 }
164
165 cpu->cd.arm.control |= ARM_CONTROL_MMU;
166 cpu->translate_address = arm_translate_address_mmu;
167 cpu->cd.arm.dacr |= 0x00000003;
168 cpu->cd.arm.ttb = ttb_addr;
169
170 memset(nothing, 0, sizeof(nothing));
171 cpu->memory_rw(cpu, cpu->mem, cpu->cd.arm.ttb, nothing,
172 sizeof(nothing), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
173 for (i=0; i<256; i++)
174 for (j=0x0; j<=0xf; j++) {
175 unsigned char descr[4];
176 uint32_t addr = cpu->cd.arm.ttb +
177 (((j << 28) + (i << 20)) >> 18);
178 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 * 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) {
237 descr[0] = d; descr[1] = d >> 8;
238 descr[2] = d >> 16; descr[3] = d >> 24;
239 } else {
240 descr[3] = d; descr[2] = d >> 8;
241 descr[1] = d >> 16; descr[0] = d >> 24;
242 }
243 cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
244 sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
245 }
246 }
247
248
249 /*
250 * arm_cpu_dumpinfo():
251 */
252 void arm_cpu_dumpinfo(struct cpu *cpu)
253 {
254 struct arm_cpu_type_def *ct = &cpu->cd.arm.cpu_type;
255
256 debug(" (I+D = %i+%i KB)\n",
257 (1 << ct->icache_shift) / 1024, (1 << ct->dcache_shift) / 1024);
258 }
259
260
261 /*
262 * arm_cpu_list_available_types():
263 *
264 * Print a list of available ARM CPU types.
265 */
266 void arm_cpu_list_available_types(void)
267 {
268 int i, j;
269 struct arm_cpu_type_def tdefs[] = ARM_CPU_TYPE_DEFS;
270
271 i = 0;
272 while (tdefs[i].name != NULL) {
273 debug("%s", tdefs[i].name);
274 for (j=13 - strlen(tdefs[i].name); j>0; j--)
275 debug(" ");
276 i++;
277 if ((i % 5) == 0 || tdefs[i].name == NULL)
278 debug("\n");
279 }
280 }
281
282
283 /*
284 * arm_cpu_register_match():
285 */
286 void arm_cpu_register_match(struct machine *m, char *name,
287 int writeflag, uint64_t *valuep, int *match_register)
288 {
289 int i, cpunr = 0;
290
291 /* CPU number: */
292
293 /* TODO */
294
295 /* Register names: */
296 for (i=0; i<N_ARM_REGS; i++) {
297 if (strcasecmp(name, arm_regname[i]) == 0) {
298 if (writeflag) {
299 m->cpus[cpunr]->cd.arm.r[i] = *valuep;
300 if (i == ARM_PC)
301 m->cpus[cpunr]->pc = *valuep;
302 } else
303 *valuep = m->cpus[cpunr]->cd.arm.r[i];
304 *match_register = 1;
305 }
306 }
307 }
308
309
310 /*
311 * arm_cpu_register_dump():
312 *
313 * Dump cpu registers in a relatively readable format.
314 *
315 * gprs: set to non-zero to dump GPRs and some special-purpose registers.
316 * coprocs: set bit 0..3 to dump registers in coproc 0..3.
317 */
318 void arm_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
319 {
320 char *symbol;
321 uint64_t offset;
322 int mode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
323 int i, x = cpu->cpu_id;
324
325 if (gprs) {
326 symbol = get_symbol_name(&cpu->machine->symbol_context,
327 cpu->cd.arm.r[ARM_PC], &offset);
328 debug("cpu%i: cpsr = ", x);
329 debug("%s%s%s%s%s%s",
330 (cpu->cd.arm.cpsr & ARM_FLAG_N)? "N" : "n",
331 (cpu->cd.arm.cpsr & ARM_FLAG_Z)? "Z" : "z",
332 (cpu->cd.arm.cpsr & ARM_FLAG_C)? "C" : "c",
333 (cpu->cd.arm.cpsr & ARM_FLAG_V)? "V" : "v",
334 (cpu->cd.arm.cpsr & ARM_FLAG_I)? "I" : "i",
335 (cpu->cd.arm.cpsr & ARM_FLAG_F)? "F" : "f");
336 if (mode < ARM_MODE_USR32)
337 debug(" pc = 0x%07x",
338 (int)(cpu->cd.arm.r[ARM_PC] & 0x03ffffff));
339 else
340 debug(" pc = 0x%08x", (int)cpu->cd.arm.r[ARM_PC]);
341
342 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
343
344 for (i=0; i<N_ARM_REGS; i++) {
345 if ((i % 4) == 0)
346 debug("cpu%i:", x);
347 if (i != ARM_PC)
348 debug(" %s = 0x%08x", arm_regname[i],
349 (int)cpu->cd.arm.r[i]);
350 if ((i % 4) == 3)
351 debug("\n");
352 }
353 }
354
355 if (coprocs & 1) {
356 int m = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
357 debug("cpu%i: cpsr = 0x%08x (", x, cpu->cd.arm.cpsr);
358 switch (m) {
359 case ARM_MODE_USR32:
360 debug("USR32)\n"); break;
361 case ARM_MODE_SYS32:
362 debug("SYS32)\n"); break;
363 case ARM_MODE_FIQ32:
364 debug("FIQ32)\n"); break;
365 case ARM_MODE_IRQ32:
366 debug("IRQ32)\n"); break;
367 case ARM_MODE_SVC32:
368 debug("SVC32)\n"); break;
369 case ARM_MODE_ABT32:
370 debug("ABT32)\n"); break;
371 case ARM_MODE_UND32:
372 debug("UND32)\n"); break;
373 default:debug("unimplemented)\n");
374 }
375
376 if (m != ARM_MODE_USR32 && m != ARM_MODE_SYS32) {
377 debug("cpu%i: usr r8..r14 =", x);
378 for (i=0; i<7; i++)
379 debug(" %08x", cpu->cd.arm.default_r8_r14[i]);
380 debug("\n");
381 }
382
383 if (m != ARM_MODE_FIQ32) {
384 debug("cpu%i: fiq r8..r14 =", x);
385 for (i=0; i<7; i++)
386 debug(" %08x", cpu->cd.arm.fiq_r8_r14[i]);
387 debug("\n");
388 }
389
390 if (m != ARM_MODE_IRQ32) {
391 debug("cpu%i: irq r13..r14 =", x);
392 for (i=0; i<2; i++)
393 debug(" %08x", cpu->cd.arm.irq_r13_r14[i]);
394 debug("\n");
395 }
396
397 if (m != ARM_MODE_SVC32) {
398 debug("cpu%i: svc r13..r14 =", x);
399 for (i=0; i<2; i++)
400 debug(" %08x", cpu->cd.arm.svc_r13_r14[i]);
401 debug("\n");
402 }
403
404 if (m != ARM_MODE_ABT32) {
405 debug("cpu%i: abt r13..r14 =", x);
406 for (i=0; i<2; i++)
407 debug(" %08x", cpu->cd.arm.abt_r13_r14[i]);
408 debug("\n");
409 }
410
411 if (m != ARM_MODE_UND32) {
412 debug("cpu%i: und r13..r14 =", x);
413 for (i=0; i<2; i++)
414 debug(" %08x", cpu->cd.arm.und_r13_r14[i]);
415 debug("\n");
416 }
417 }
418
419 if (coprocs & 2) {
420 debug("cpu%i: control = 0x%08x\n", x, cpu->cd.arm.control);
421 debug("cpu%i: MMU: %s\n", x,
422 cpu->cd.arm.control &
423 ARM_CONTROL_MMU? "enabled" : "disabled");
424 debug("cpu%i: alignment checks: %s\n", x,
425 cpu->cd.arm.control &
426 ARM_CONTROL_ALIGN? "enabled" : "disabled");
427 debug("cpu%i: [data] cache: %s\n", x,
428 cpu->cd.arm.control &
429 ARM_CONTROL_CACHE? "enabled" : "disabled");
430 debug("cpu%i: instruction cache: %s\n", x,
431 cpu->cd.arm.control &
432 ARM_CONTROL_ICACHE? "enabled" : "disabled");
433 debug("cpu%i: write buffer: %s\n", x,
434 cpu->cd.arm.control &
435 ARM_CONTROL_WBUFFER? "enabled" : "disabled");
436 debug("cpu%i: prog32: %s\n", x,
437 cpu->cd.arm.control &
438 ARM_CONTROL_PROG32? "yes" : "no (using prog26)");
439 debug("cpu%i: data32: %s\n", x,
440 cpu->cd.arm.control &
441 ARM_CONTROL_DATA32? "yes" : "no (using data26)");
442 debug("cpu%i: endianness: %s\n", x,
443 cpu->cd.arm.control &
444 ARM_CONTROL_BIG? "big endian" : "little endian");
445 debug("cpu%i: high vectors: %s\n", x,
446 cpu->cd.arm.control &
447 ARM_CONTROL_V? "yes (0xffff0000)" : "no");
448
449 debug("cpu%i: ttb = 0x%08x dacr = 0x%08x\n", x,
450 cpu->cd.arm.ttb, cpu->cd.arm.dacr);
451 debug("cpu%i: fsr = 0x%08x far = 0x%08x\n", x,
452 cpu->cd.arm.fsr, cpu->cd.arm.far);
453 }
454 }
455
456
457 /*
458 * arm_cpu_show_full_statistics():
459 *
460 * Show detailed statistics on opcode usage on each cpu.
461 */
462 void arm_cpu_show_full_statistics(struct machine *m)
463 {
464 fatal("arm_cpu_show_full_statistics(): TODO\n");
465 }
466
467
468 /*
469 * arm_cpu_tlbdump():
470 *
471 * Called from the debugger to dump the TLB in a readable format.
472 * x is the cpu number to dump, or -1 to dump all CPUs.
473 *
474 * If rawflag is nonzero, then the TLB contents isn't formated nicely,
475 * just dumped.
476 */
477 void arm_cpu_tlbdump(struct machine *m, int x, int rawflag)
478 {
479 fatal("arm_cpu_tlbdump(): TODO\n");
480 }
481
482
483 /*
484 * arm_save_register_bank():
485 */
486 void arm_save_register_bank(struct cpu *cpu)
487 {
488 /* Save away current registers: */
489 switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
490 case ARM_MODE_USR32:
491 case ARM_MODE_SYS32:
492 memcpy(cpu->cd.arm.default_r8_r14,
493 &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
494 break;
495 case ARM_MODE_FIQ32:
496 memcpy(cpu->cd.arm.fiq_r8_r14,
497 &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
498 break;
499 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];
503 cpu->cd.arm.irq_r13_r14[1] = cpu->cd.arm.r[14];
504 break;
505 case ARM_MODE_SVC32:
506 memcpy(cpu->cd.arm.default_r8_r14,
507 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
508 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];
510 break;
511 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];
515 cpu->cd.arm.abt_r13_r14[1] = cpu->cd.arm.r[14];
516 break;
517 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];
521 cpu->cd.arm.und_r13_r14[1] = cpu->cd.arm.r[14];
522 break;
523 default:fatal("arm_save_register_bank: unimplemented mode %i\n",
524 cpu->cd.arm.cpsr & ARM_FLAG_MODE);
525 exit(1);
526 }
527 }
528
529
530 /*
531 * arm_load_register_bank():
532 */
533 void arm_load_register_bank(struct cpu *cpu)
534 {
535 /* Load new registers: */
536 switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
537 case ARM_MODE_USR32:
538 case ARM_MODE_SYS32:
539 memcpy(&cpu->cd.arm.r[8],
540 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 7);
541 break;
542 case ARM_MODE_FIQ32:
543 memcpy(&cpu->cd.arm.r[8], cpu->cd.arm.fiq_r8_r14,
544 sizeof(uint32_t) * 7);
545 break;
546 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];
550 cpu->cd.arm.r[14] = cpu->cd.arm.irq_r13_r14[1];
551 break;
552 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];
556 cpu->cd.arm.r[14] = cpu->cd.arm.svc_r13_r14[1];
557 break;
558 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];
562 cpu->cd.arm.r[14] = cpu->cd.arm.abt_r13_r14[1];
563 break;
564 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];
568 cpu->cd.arm.r[14] = cpu->cd.arm.und_r13_r14[1];
569 break;
570 default:fatal("arm_load_register_bank: unimplemented mode %i\n",
571 cpu->cd.arm.cpsr & ARM_FLAG_MODE);
572 exit(1);
573 }
574 }
575
576
577 /*
578 * arm_exception():
579 */
580 void arm_exception(struct cpu *cpu, int exception_nr)
581 {
582 int arm_exception_to_mode[N_ARM_EXCEPTIONS] = ARM_EXCEPTION_TO_MODE;
583 int oldmode, newmode;
584 uint32_t retaddr;
585
586 if (exception_nr < 0 || exception_nr >= N_ARM_EXCEPTIONS) {
587 fatal("arm_exception(): exception_nr = %i\n", exception_nr);
588 exit(1);
589 }
590
591 retaddr = cpu->pc;
592
593 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) {
623 case ARM_EXCEPTION_RESET:
624 cpu->running = 0;
625 fatal("ARM RESET: TODO");
626 exit(1);
627 case ARM_EXCEPTION_DATA_ABT:
628 retaddr += 4;
629 break;
630 }
631
632 retaddr += 4;
633
634 arm_save_register_bank(cpu);
635
636 switch (arm_exception_to_mode[exception_nr]) {
637 case ARM_MODE_SVC32:
638 cpu->cd.arm.spsr_svc = cpu->cd.arm.cpsr; break;
639 case ARM_MODE_ABT32:
640 cpu->cd.arm.spsr_abt = cpu->cd.arm.cpsr; break;
641 case ARM_MODE_UND32:
642 cpu->cd.arm.spsr_und = cpu->cd.arm.cpsr; break;
643 case ARM_MODE_IRQ32:
644 cpu->cd.arm.spsr_irq = cpu->cd.arm.cpsr; break;
645 case ARM_MODE_FIQ32:
646 cpu->cd.arm.spsr_fiq = cpu->cd.arm.cpsr; break;
647 default:fatal("arm_exception(): unimplemented exception nr\n");
648 exit(1);
649 }
650
651 /*
652 * Disable Thumb mode (because exception handlers always execute
653 * in ARM mode), set the exception mode, and disable interrupts:
654 */
655 cpu->cd.arm.cpsr &= ~ARM_FLAG_T;
656
657 oldmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
658
659 cpu->cd.arm.cpsr &= ~ARM_FLAG_MODE;
660 cpu->cd.arm.cpsr |= arm_exception_to_mode[exception_nr];
661
662 newmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
663 if (oldmode == newmode) {
664 fatal("Exception caused no mode change? TODO\n");
665 exit(1);
666 }
667
668 cpu->cd.arm.cpsr |= ARM_FLAG_I;
669 if (exception_nr == ARM_EXCEPTION_RESET ||
670 exception_nr == ARM_EXCEPTION_FIQ)
671 cpu->cd.arm.cpsr |= ARM_FLAG_F;
672
673 /* Load the new register bank, if we switched: */
674 arm_load_register_bank(cpu);
675
676 /* Set the return address and new PC: */
677 cpu->cd.arm.r[ARM_LR] = retaddr;
678
679 cpu->pc = cpu->cd.arm.r[ARM_PC] = exception_nr * 4 +
680 ((cpu->cd.arm.control & ARM_CONTROL_V)? 0xffff0000 : 0);
681 quick_pc_to_pointers(cpu);
682 }
683
684
685 /*
686 * arm_cpu_interrupt():
687 *
688 * 0..31 are used as footbridge interrupt numbers, 32..47 = ISA,
689 * 64 is used as a "re-assert" signal to cpu->machine->md_interrupt().
690 *
691 * TODO: don't hardcode to footbridge!
692 */
693 int arm_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
694 {
695 /* fatal("arm_cpu_interrupt(): 0x%llx\n", (int)irq_nr); */
696 if (irq_nr <= 64) {
697 if (cpu->machine->md_interrupt != NULL)
698 cpu->machine->md_interrupt(cpu->machine,
699 cpu, irq_nr, 1);
700 else
701 fatal("arm_cpu_interrupt(): md_interrupt == NULL\n");
702 } else {
703 /* Assert ARM IRQs: */
704 cpu->cd.arm.irq_asserted = 1;
705 }
706
707 return 1;
708 }
709
710
711 /*
712 * arm_cpu_interrupt_ack():
713 */
714 int arm_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
715 {
716 if (irq_nr <= 64) {
717 if (cpu->machine->md_interrupt != NULL)
718 cpu->machine->md_interrupt(cpu->machine,
719 cpu, irq_nr, 0);
720 } else {
721 /* De-assert ARM IRQs: */
722 cpu->cd.arm.irq_asserted = 0;
723 }
724
725 return 1;
726 }
727
728
729 /*
730 * arm_cpu_disassemble_instr():
731 *
732 * Convert an instruction word into human readable format, for instruction
733 * tracing.
734 *
735 * If running is 1, cpu->pc should be the address of the instruction.
736 *
737 * If running is 0, things that depend on the runtime environment (eg.
738 * register contents) will not be shown, and addr will be used instead of
739 * cpu->pc for relative addresses.
740 */
741 int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
742 int running, uint64_t dumpaddr, int bintrans)
743 {
744 uint32_t iw, tmp;
745 int main_opcode, secondary_opcode, s_bit, r16, r12, r8;
746 int i, n, p_bit, u_bit, b_bit, w_bit, l_bit;
747 char *symbol, *condition;
748 uint64_t offset;
749
750 if (running)
751 dumpaddr = cpu->pc;
752
753 symbol = get_symbol_name(&cpu->machine->symbol_context,
754 dumpaddr, &offset);
755 if (symbol != NULL && offset == 0)
756 debug("<%s>\n", symbol);
757
758 if (cpu->machine->ncpus > 1 && running)
759 debug("cpu%i:\t", cpu->cpu_id);
760
761 debug("%08x: ", (int)dumpaddr);
762
763 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
764 iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
765 else
766 iw = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
767 debug("%08x\t", (int)iw);
768
769 condition = arm_condition_string[iw >> 28];
770 main_opcode = (iw >> 24) & 15;
771 secondary_opcode = (iw >> 21) & 15;
772 u_bit = (iw >> 23) & 1;
773 b_bit = (iw >> 22) & 1;
774 w_bit = (iw >> 21) & 1;
775 s_bit = l_bit = (iw >> 20) & 1;
776 r16 = (iw >> 16) & 15;
777 r12 = (iw >> 12) & 15;
778 r8 = (iw >> 8) & 15;
779
780 switch (main_opcode) {
781 case 0x0:
782 case 0x1:
783 case 0x2:
784 case 0x3:
785 /*
786 * Special cases first:
787 */
788
789 /*
790 * Multiplication:
791 * xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd, Rm, Rs [,Rn])
792 */
793 if ((iw & 0x0fc000f0) == 0x00000090) {
794 int a_bit = (iw >> 21) & 1;
795 debug("%s%s%s\t", a_bit? "mla" : "mul",
796 condition, s_bit? "s" : "");
797 debug("%s,", arm_regname[r16]);
798 debug("%s,", arm_regname[iw & 15]);
799 debug("%s", arm_regname[r8]);
800 if (a_bit)
801 debug(",%s", arm_regname[r12]);
802 debug("\n");
803 break;
804 }
805
806 /*
807 * Long multiplication:
808 * xxxx0000 1UAShhhh llllssss 1001mmmm (Rl,Rh,Rm,Rs)
809 */
810 if ((iw & 0x0f8000f0) == 0x00800090) {
811 int u_bit = (iw >> 22) & 1;
812 int a_bit = (iw >> 21) & 1;
813 debug("%s%sl%s%s\t", u_bit? "s" : "u",
814 a_bit? "mla" : "mul", condition, s_bit? "s" : "");
815 debug("%s,", arm_regname[r12]);
816 debug("%s,", arm_regname[r16]);
817 debug("%s,", arm_regname[iw & 15]);
818 debug("%s\n", arm_regname[r8]);
819 break;
820 }
821
822 /*
823 * xxxx0001 0010.... ........ 00L1mmmm bx/blx rm
824 */
825 if ((iw & 0x0ff000d0) == 0x01200010) {
826 int l_bit = iw & 0x20;
827 debug("b%sx%s\t%s\n", l_bit? "l" : "", condition,
828 arm_regname[iw & 15]);
829 break;
830 }
831
832 /*
833 * xxxx0001 0s10aaaa 11110000 0000mmmm MSR Regform
834 * xxxx0011 0s10aaaa 1111rrrr bbbbbbbb MSR Immform
835 * xxxx0001 0s001111 dddd0000 00000000 MRS
836 */
837 if ((iw & 0x0fb0fff0) == 0x0120f000 ||
838 (iw & 0x0fb0f000) == 0x0320f000) {
839 int a = (iw >> 16) & 15;
840 debug("msr%s\t%s", condition, (iw&0x400000)? "S":"C");
841 debug("PSR_");
842 switch (a) {
843 case 1: debug("ctl"); break;
844 case 8: debug("flg"); break;
845 case 9: debug("all"); break;
846 default:debug(" UNIMPLEMENTED (a=%i)", a);
847 }
848 if (iw & 0x02000000) {
849 int r = (iw >> 7) & 30;
850 uint32_t b = iw & 0xff;
851 while (r-- > 0)
852 b = (b >> 1) | ((b & 1) << 31);
853 debug(",#0x%x\n", b);
854 } else
855 debug(",%s\n", arm_regname[iw & 15]);
856 break;
857 }
858 if ((iw & 0x0fbf0fff) == 0x010f0000) {
859 debug("mrs%s\t", condition);
860 debug("%s,%sPSR\n", arm_regname[r12],
861 (iw&0x400000)? "S":"C");
862 break;
863 }
864
865 /*
866 * xxxx0001 0B00nnnn dddd0000 1001mmmm SWP Rd,Rm,[Rn]
867 */
868 if ((iw & 0x0fb00ff0) == 0x01000090) {
869 debug("swp%s%s\t", condition, (iw&0x400000)? "b":"");
870 debug("%s,%s,[%s]\n", arm_regname[r12],
871 arm_regname[iw & 15], arm_regname[r16]);
872 break;
873 }
874
875 /*
876 * xxxx000P U1WLnnnn ddddHHHH 1SH1LLLL load/store rd,imm(rn)
877 */
878 if ((iw & 0x0e000090) == 0x00000090) {
879 char *op = "st";
880 int imm = ((iw >> 4) & 0xf0) | (iw & 0xf);
881 int regform = !(iw & 0x00400000);
882 p_bit = main_opcode & 1;
883 /*
884 * TODO: detect some illegal variants:
885 * signed store, or unsigned byte load/store
886 */
887 if (!l_bit && (iw & 0xd0) == 0xd0 && (r12 & 1)) {
888 debug("TODO: r12 odd, not load/store\n");
889 break;
890 }
891 /* Semi-generic case: */
892 if (iw & 0x00100000)
893 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) {
898 debug("d"); /* Double-register */
899 } else {
900 if (iw & 0x40)
901 debug("s"); /* signed */
902 if (iw & 0x20)
903 debug("h"); /* half-word */
904 else
905 debug("b"); /* byte */
906 }
907 debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
908 if (p_bit) {
909 /* Pre-index: */
910 if (regform)
911 debug(",%s%s", u_bit? "" : "-",
912 arm_regname[iw & 15]);
913 else {
914 if (imm != 0)
915 debug(",#%s%i", u_bit? "" : "-",
916 imm);
917 }
918 debug("]%s\n", w_bit? "!" : "");
919 } else {
920 /* Post-index: */
921 debug("],");
922 if (regform)
923 debug("%s%s\n", u_bit? "" : "-",
924 arm_regname[iw & 15]);
925 else
926 debug("#%s%i\n", u_bit? "" : "-", imm);
927 }
928 break;
929 }
930
931 /* Other special cases: */
932 if (iw & 0x80 && !(main_opcode & 2) && iw & 0x10) {
933 debug("UNIMPLEMENTED reg (c!=0), t odd\n");
934 break;
935 }
936
937 /*
938 * Generic Data Processing Instructions:
939 *
940 * xxxx000a aaaSnnnn ddddcccc ctttmmmm Register form
941 * xxxx001a aaaSnnnn ddddrrrr bbbbbbbb Immediate form
942 */
943
944 debug("%s%s%s\t", arm_dpiname[secondary_opcode],
945 condition, s_bit? "s" : "");
946 if (arm_dpi_uses_d[secondary_opcode])
947 debug("%s,", arm_regname[r12]);
948 if (arm_dpi_uses_n[secondary_opcode])
949 debug("%s,", arm_regname[r16]);
950
951 if (main_opcode & 2) {
952 /* Immediate form: */
953 int r = (iw >> 7) & 30;
954 uint32_t b = iw & 0xff;
955 while (r-- > 0)
956 b = (b >> 1) | ((b & 1) << 31);
957 if (b < 15)
958 debug("#%i", b);
959 else
960 debug("#0x%x", b);
961 } else {
962 /* Register form: */
963 int t = (iw >> 4) & 7;
964 int c = (iw >> 7) & 31;
965 debug("%s", arm_regname[iw & 15]);
966 switch (t) {
967 case 0: if (c != 0)
968 debug(", lsl #%i", c);
969 break;
970 case 1: debug(", lsl %s", arm_regname[c >> 1]);
971 break;
972 case 2: debug(", lsr #%i", c? c : 32);
973 break;
974 case 3: debug(", lsr %s", arm_regname[c >> 1]);
975 break;
976 case 4: debug(", asr #%i", c? c : 32);
977 break;
978 case 5: debug(", asr %s", arm_regname[c >> 1]);
979 break;
980 case 6: if (c != 0)
981 debug(", ror #%i", c);
982 else
983 debug(", rrx");
984 break;
985 case 7: debug(", ror %s", arm_regname[c >> 1]);
986 break;
987 }
988
989 /* mov pc,reg: */
990 if (running && t == 0 && c == 0 && secondary_opcode
991 == 0xd && r12 == ARM_PC && (iw&15)!=ARM_PC) {
992 symbol = get_symbol_name(&cpu->machine->
993 symbol_context, cpu->cd.arm.r[iw & 15],
994 &offset);
995 if (symbol != NULL)
996 debug(" \t<%s>", symbol);
997 }
998 }
999 debug("\n");
1000 break;
1001 case 0x4: /* Single Data Transfer */
1002 case 0x5:
1003 case 0x6:
1004 case 0x7:
1005 /* Special case first: */
1006 if ((iw & 0xfc70f000) == 0xf450f000) {
1007 /* Preload: */
1008 debug("pld\t[%s]\n", arm_regname[r16]);
1009 break;
1010 }
1011
1012 /*
1013 * xxxx010P UBWLnnnn ddddoooo oooooooo Immediate form
1014 * xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form
1015 */
1016 p_bit = main_opcode & 1;
1017 if (main_opcode >= 6 && iw & 0x10) {
1018 debug("TODO: single data transf. but 0x10\n");
1019 break;
1020 }
1021 debug("%s%s%s", l_bit? "ldr" : "str",
1022 condition, b_bit? "b" : "");
1023 if (!p_bit && w_bit)
1024 debug("t");
1025 debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
1026 if ((iw & 0x0e000000) == 0x04000000) {
1027 /* Immediate form: */
1028 uint32_t imm = iw & 0xfff;
1029 if (!p_bit)
1030 debug("]");
1031 if (imm != 0)
1032 debug(",#%s%i", u_bit? "" : "-", imm);
1033 if (p_bit)
1034 debug("]");
1035 } else if ((iw & 0x0e000010) == 0x06000000) {
1036 /* Register form: */
1037 if (!p_bit)
1038 debug("]");
1039 if ((iw & 0xfff) != 0)
1040 debug(",%s%s", u_bit? "" : "-",
1041 arm_regname[iw & 15]);
1042 if ((iw & 0xff0) != 0x000) {
1043 int c = (iw >> 7) & 31;
1044 int t = (iw >> 4) & 7;
1045 switch (t) {
1046 case 0: if (c != 0)
1047 debug(", lsl #%i", c);
1048 break;
1049 case 2: debug(", lsr #%i", c? c : 32);
1050 break;
1051 case 4: debug(", asr #%i", c? c : 32);
1052 break;
1053 case 6: if (c != 0)
1054 debug(", ror #%i", c);
1055 else
1056 debug(", rrx");
1057 break;
1058 }
1059 }
1060 if (p_bit)
1061 debug("]");
1062 } else {
1063 debug("UNKNOWN\n");
1064 break;
1065 }
1066 debug("%s", (p_bit && w_bit)? "!" : "");
1067 if ((iw & 0x0f000000) == 0x05000000 &&
1068 (r16 == ARM_PC || running)) {
1069 unsigned char tmpw[4];
1070 uint32_t imm = iw & 0xfff;
1071 uint32_t addr = (u_bit? imm : -imm);
1072 if (r16 == ARM_PC)
1073 addr += dumpaddr + 8;
1074 else
1075 addr += cpu->cd.arm.r[r16];
1076 symbol = get_symbol_name(&cpu->machine->symbol_context,
1077 addr, &offset);
1078 if (symbol != NULL)
1079 debug(" \t<%s", symbol);
1080 else
1081 debug(" \t<0x%08x", addr);
1082 if ((l_bit && cpu->memory_rw(cpu, cpu->mem, addr, tmpw,
1083 b_bit? 1 : sizeof(tmpw), MEM_READ, NO_EXCEPTIONS))
1084 || (!l_bit && running)) {
1085 if (l_bit) {
1086 if (cpu->byte_order ==
1087 EMUL_LITTLE_ENDIAN)
1088 addr = tmpw[0] +(tmpw[1] << 8) +
1089 (tmpw[2]<<16)+(tmpw[3]<<24);
1090 else
1091 addr = tmpw[3] + (tmpw[2]<<8) +
1092 (tmpw[1]<<16)+(tmpw[0]<<24);
1093 } else {
1094 tmpw[0] = addr = cpu->cd.arm.r[r12];
1095 if (r12 == ARM_PC)
1096 addr += 8;
1097 }
1098 debug(": ");
1099 if (b_bit)
1100 debug("%i", tmpw[0]);
1101 else {
1102 symbol = get_symbol_name(&cpu->machine->
1103 symbol_context, addr, &offset);
1104 if (symbol != NULL)
1105 debug("%s", symbol);
1106 else if ((int32_t)addr > -256 &&
1107 (int32_t)addr < 256)
1108 debug("%i", addr);
1109 else
1110 debug("0x%x", addr);
1111 }
1112 }
1113 debug(">");
1114 }
1115 debug("\n");
1116 break;
1117 case 0x8: /* Block Data Transfer */
1118 case 0x9:
1119 /* xxxx100P USWLnnnn llllllll llllllll */
1120 p_bit = main_opcode & 1;
1121 s_bit = b_bit;
1122 debug("%s%s", l_bit? "ldm" : "stm", condition);
1123 switch (u_bit * 2 + p_bit) {
1124 case 0: debug("da"); break;
1125 case 1: debug("db"); break;
1126 case 2: debug("ia"); break;
1127 case 3: debug("ib"); break;
1128 }
1129 debug("\t%s", arm_regname[r16]);
1130 if (w_bit)
1131 debug("!");
1132 debug(",{");
1133 n = 0;
1134 for (i=0; i<16; i++)
1135 if ((iw >> i) & 1) {
1136 debug("%s%s", (n > 0)? ",":"", arm_regname[i]);
1137 n++;
1138 }
1139 debug("}");
1140 if (s_bit)
1141 debug("^");
1142 debug("\n");
1143 break;
1144 case 0xa: /* B: branch */
1145 case 0xb: /* BL: branch and link */
1146 debug("b%s%s\t", main_opcode == 0xa? "" : "l", condition);
1147 tmp = (iw & 0x00ffffff) << 2;
1148 if (tmp & 0x02000000)
1149 tmp |= 0xfc000000;
1150 tmp = (int32_t)(dumpaddr + tmp + 8);
1151 debug("0x%x", (int)tmp);
1152 symbol = get_symbol_name(&cpu->machine->symbol_context,
1153 tmp, &offset);
1154 if (symbol != NULL)
1155 debug(" \t<%s>", symbol);
1156 debug("\n");
1157 break;
1158 case 0xc: /* Coprocessor */
1159 case 0xd: /* LDC/STC */
1160 /* xxxx110P UNWLnnnn DDDDpppp oooooooo LDC/STC */
1161 debug("TODO: coprocessor LDC/STC\n");
1162 break;
1163 case 0xe: /* CDP (Coprocessor Op) */
1164 /* or MRC/MCR!
1165 * xxxx1110 oooonnnn ddddpppp qqq0mmmm CDP
1166 * xxxx1110 oooLNNNN ddddpppp qqq1MMMM MRC/MCR
1167 */
1168 if (iw & 0x10) {
1169 debug("%s%s\t",
1170 (iw & 0x00100000)? "mrc" : "mcr", condition);
1171 debug("%i,%i,r%i,cr%i,cr%i,%i",
1172 (int)((iw >> 8) & 15), (int)((iw >>21) & 7),
1173 (int)((iw >>12) & 15), (int)((iw >>16) & 15),
1174 (int)((iw >> 0) & 15), (int)((iw >> 5) & 7));
1175 } else {
1176 debug("cdp%s\t", condition);
1177 debug("%i,%i,cr%i,cr%i,cr%i",
1178 (int)((iw >> 8) & 15),
1179 (int)((iw >>20) & 15),
1180 (int)((iw >>12) & 15),
1181 (int)((iw >>16) & 15),
1182 (int)((iw >> 0) & 15));
1183 if ((iw >> 5) & 7)
1184 debug(",0x%x", (int)((iw >> 5) & 7));
1185 }
1186 debug("\n");
1187 break;
1188 case 0xf: /* SWI */
1189 debug("swi%s\t", condition);
1190 debug("0x%x\n", (int)(iw & 0x00ffffff));
1191 break;
1192 default:debug("UNIMPLEMENTED\n");
1193 }
1194
1195 return sizeof(uint32_t);
1196 }
1197
1198
1199 /*****************************************************************************/
1200
1201
1202 /*
1203 * arm_mcr_mrc():
1204 *
1205 * Coprocessor register move.
1206 *
1207 * The program counter should be synched before calling this function (to
1208 * make debug output with the correct PC value possible).
1209 */
1210 void arm_mcr_mrc(struct cpu *cpu, uint32_t iword)
1211 {
1212 int opcode1 = (iword >> 21) & 7;
1213 int l_bit = (iword >> 20) & 1;
1214 int crn = (iword >> 16) & 15;
1215 int rd = (iword >> 12) & 15;
1216 int cp_num = (iword >> 8) & 15;
1217 int opcode2 = (iword >> 5) & 7;
1218 int crm = iword & 15;
1219
1220 if (cpu->cd.arm.coproc[cp_num] != NULL)
1221 cpu->cd.arm.coproc[cp_num](cpu, opcode1, opcode2, l_bit,
1222 crn, crm, rd);
1223 else {
1224 fatal("arm_mcr_mrc: pc=0x%08x, iword=0x%08x: "
1225 "cp_num=%i\n", (int)cpu->pc, iword, cp_num);
1226 exit(1);
1227 }
1228 }
1229
1230
1231 /*
1232 * arm_cdp():
1233 *
1234 * Coprocessor operations.
1235 *
1236 * The program counter should be synched before calling this function (to
1237 * make debug output with the correct PC value possible).
1238 */
1239 void arm_cdp(struct cpu *cpu, uint32_t iword)
1240 {
1241 fatal("arm_cdp: pc=0x%08x, iword=0x%08x\n", (int)cpu->pc, iword);
1242 exit(1);
1243 }
1244
1245
1246 /*****************************************************************************/
1247
1248
1249 #include "tmp_arm_tail.c"
1250

  ViewVC Help
Powered by ViewVC 1.1.26