/[gxemul]/trunk/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 /trunk/src/cpus/cpu_arm.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 18 - (show annotations)
Mon Oct 8 16:19:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 33418 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1004 2005/10/27 14:01:10 debug Exp $
20051011        Passing -A as the default boot arg for CATS (works fine with
                OpenBSD/cats).
20051012	Fixing the VGA cursor offset bug, and speeding up framebuffer
		redraws if character cells contain the same thing as during
		the last redraw.
20051013	Adding a slow strd ARM instruction hack.
20051017	Minor updates: Adding a dummy i80321 Verde controller (for
		XScale emulation), fixing the disassembly of the ARM "ldrd"
		instruction, adding "support" for less-than-4KB pages for ARM
		(by not adding them to translation tables).
20051020	Continuing on some HPCarm stuff. A NetBSD/hpcarm kernel prints
		some boot messages on an emulated Jornada 720.
		Making dev_ram work better with dyntrans (speeds up some things
		quite a bit).
20051021	Automatically generating some of the most common ARM load/store
		multiple instructions.
20051022	Better statistics gathering for the ARM load/store multiple.
		Various other dyntrans and device updates.
20051023	Various minor updates.
20051024	Continuing; minor device and dyntrans fine-tuning. Adding the
		first "reasonable" instruction combination hacks for ARM (the
		cores of NetBSD/cats' memset and memcpy).
20051025	Fixing a dyntrans-related bug in dev_vga. Also changing the
		dyntrans low/high access notification to only be updated on
		writes, not reads. Hopefully it will be enough. (dev_vga in
		charcell mode now seems to work correctly with both reads and
		writes.)
		Experimenting with gathering dyntrans statistics (which parts
		of emulated RAM that are actually executed), and adding
		instruction combination hacks for cache cleaning and a part of
		NetBSD's scanc() function.
20051026	Adding a bitmap for ARM emulation which indicates if a page is
		(specifically) user accessible; loads and stores with the t-
		flag set can now use the translation arrays, which results in
		a measurable speedup.
20051027	Dyntrans updates; adding an extra bitmap array for 32-bit
		emulation modes, speeding up the check whether a physical page
		has any code translations or not (O(n) -> O(1)). Doing a
		similar reduction of O(n) to O(1) by avoiding the scan through
		the translation entries on a translation update (32-bit mode
		only).
		Various other minor hacks.
20051029	Quick release, without any testing at all.

==============  RELEASE 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