/[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 26 - (show annotations)
Mon Oct 8 16:20:10 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 40652 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1264 2006/06/25 11:08:04 debug Exp $
20060624	Replacing the error-prone machine type initialization stuff
		with something more reasonable.
		Finally removing the old "cpu_run" kludge; moving around stuff
		in machine.c and emul.c to better suit the dyntrans system.
		Various minor dyntrans cleanups (renaming translate_address to
		translate_v2p, and experimenting with template physpages).
20060625	Removing the speed hack which separated the vph entries into
		two halves (code vs data); things seem a lot more stable now.
		Minor performance hack: R2000/R3000 cache isolation now only
		clears address translations when going into isolation, not
		when going out of it.
		Fixing the MIPS interrupt problems by letting mtc0 immediately
		cause interrupts.

==============  RELEASE 0.4.0.1  ==============


1 /*
2 * Copyright (C) 2005-2006 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.60 2006/06/24 21:47:23 debug Exp $
29 *
30 * ARM CPU emulation.
31 *
32 *
33 * A good source of quick info on ARM instruction encoding:
34 *
35 * http://www.pinknoise.demon.co.uk/ARMinstrs/ARMinstrs.html
36 */
37
38 #include <stdio.h>
39 #include <stdlib.h>
40 #include <string.h>
41 #include <ctype.h>
42
43 #include "arm_cpu_types.h"
44 #include "cpu.h"
45 #include "machine.h"
46 #include "memory.h"
47 #include "misc.h"
48 #include "of.h"
49 #include "symbol.h"
50
51 #define DYNTRANS_32
52 #include "tmp_arm_head.c"
53
54
55 /* ARM symbolic register names and condition strings: */
56 static char *arm_regname[N_ARM_REGS] = ARM_REG_NAMES;
57 static char *arm_condition_string[16] = ARM_CONDITION_STRINGS;
58
59 /* Data Processing Instructions: */
60 static char *arm_dpiname[16] = ARM_DPI_NAMES;
61 static int arm_dpi_uses_d[16] = { 1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1 };
62 static int arm_dpi_uses_n[16] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0 };
63
64 static int arm_exception_to_mode[N_ARM_EXCEPTIONS] = ARM_EXCEPTION_TO_MODE;
65
66 /* For quick_pc_to_pointers(): */
67 void arm_pc_to_pointers(struct cpu *cpu);
68 #include "quick_pc_to_pointers.h"
69
70
71 /*
72 * arm_cpu_new():
73 *
74 * Create a new ARM cpu object by filling the CPU struct.
75 * Return 1 on success, 0 if cpu_type_name isn't a valid ARM processor.
76 */
77 int arm_cpu_new(struct cpu *cpu, struct memory *mem,
78 struct machine *machine, int cpu_id, char *cpu_type_name)
79 {
80 int any_cache = 0, i, found;
81 struct arm_cpu_type_def cpu_type_defs[] = ARM_CPU_TYPE_DEFS;
82
83 /* Scan the list for this cpu type: */
84 i = 0; found = -1;
85 while (i >= 0 && cpu_type_defs[i].name != NULL) {
86 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
87 found = i;
88 break;
89 }
90 i++;
91 }
92 if (found == -1)
93 return 0;
94
95 cpu->memory_rw = arm_memory_rw;
96 cpu->update_translation_table = arm_update_translation_table;
97 cpu->invalidate_translation_caches =
98 arm_invalidate_translation_caches;
99 cpu->invalidate_code_translation = arm_invalidate_code_translation;
100 cpu->translate_v2p = arm_translate_v2p;
101
102 cpu->cd.arm.cpu_type = cpu_type_defs[found];
103 cpu->name = cpu->cd.arm.cpu_type.name;
104 cpu->is_32bit = 1;
105
106 cpu->cd.arm.cpsr = ARM_FLAG_I | ARM_FLAG_F;
107 cpu->cd.arm.control = ARM_CONTROL_PROG32 | ARM_CONTROL_DATA32
108 | ARM_CONTROL_CACHE | ARM_CONTROL_ICACHE | ARM_CONTROL_ALIGN;
109 /* TODO: default auxctrl contents */
110
111 if (cpu->machine->prom_emulation) {
112 cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
113 cpu->cd.arm.control |= ARM_CONTROL_S;
114 } else {
115 cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
116 cpu->cd.arm.control |= ARM_CONTROL_R;
117 }
118
119 /* Only show name and caches etc for CPU nr 0: */
120 if (cpu_id == 0) {
121 debug("%s", cpu->name);
122 if (cpu->cd.arm.cpu_type.icache_shift != 0)
123 any_cache = 1;
124 if (cpu->cd.arm.cpu_type.dcache_shift != 0)
125 any_cache = 1;
126 if (any_cache) {
127 debug(" (I+D = %i+%i KB",
128 (int)(1 << (cpu->cd.arm.cpu_type.icache_shift-10)),
129 (int)(1 << (cpu->cd.arm.cpu_type.dcache_shift-10)));
130 debug(")");
131 }
132 }
133
134 /* TODO: Some of these values (iway and dway) aren't used yet: */
135 cpu->cd.arm.cachetype =
136 (5 << ARM_CACHETYPE_CLASS_SHIFT)
137 | (1 << ARM_CACHETYPE_HARVARD_SHIFT)
138 | ((cpu->cd.arm.cpu_type.dcache_shift - 9) <<
139 ARM_CACHETYPE_DSIZE_SHIFT)
140 | (5 << ARM_CACHETYPE_DASSOC_SHIFT) /* 32-way */
141 | (2 << ARM_CACHETYPE_DLINE_SHIFT) /* 8 words/line */
142 | ((cpu->cd.arm.cpu_type.icache_shift - 9) <<
143 ARM_CACHETYPE_ISIZE_SHIFT)
144 | (5 << ARM_CACHETYPE_IASSOC_SHIFT) /* 32-way */
145 | (2 << ARM_CACHETYPE_ILINE_SHIFT); /* 8 words/line */
146
147 /* Coprocessor 15 = the system control coprocessor. */
148 cpu->cd.arm.coproc[15] = arm_coproc_15;
149
150 /* Coprocessor 14 for XScale: */
151 if (cpu->cd.arm.cpu_type.flags & ARM_XSCALE)
152 cpu->cd.arm.coproc[14] = arm_coproc_xscale_14;
153
154 /*
155 * NOTE/TODO: Ugly hack for OpenFirmware emulation:
156 */
157 if (cpu->machine->prom_emulation) {
158 cpu->cd.arm.of_emul_addr = cpu->machine->physical_ram_in_mb
159 * 1048576 - 8;
160 store_32bit_word(cpu, cpu->cd.arm.of_emul_addr, 0xef8c64be);
161 }
162
163 cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
164
165 return 1;
166 }
167
168
169 /*
170 * arm_setup_initial_translation_table():
171 *
172 * When booting kernels (such as OpenBSD or NetBSD) directly, it is assumed
173 * that the MMU is already enabled by the boot-loader. This function tries
174 * to emulate that.
175 */
176 void arm_setup_initial_translation_table(struct cpu *cpu, uint32_t ttb_addr)
177 {
178 unsigned char nothing[16384];
179 unsigned int i, j;
180
181 if (cpu->machine->userland_emul != NULL) {
182 fatal("arm_setup_initial_translation_table(): should not "
183 "be called for userland emulation!\n");
184 exit(1);
185 }
186
187 cpu->cd.arm.control |= ARM_CONTROL_MMU;
188 cpu->translate_v2p = arm_translate_v2p_mmu;
189 cpu->cd.arm.dacr |= 0x00000003;
190 cpu->cd.arm.ttb = ttb_addr;
191
192 memset(nothing, 0, sizeof(nothing));
193 cpu->memory_rw(cpu, cpu->mem, cpu->cd.arm.ttb, nothing,
194 sizeof(nothing), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
195 for (i=0; i<256; i++)
196 for (j=0x0; j<=0xf; j++) {
197 unsigned char descr[4];
198 uint32_t addr = cpu->cd.arm.ttb +
199 (((j << 28) + (i << 20)) >> 18);
200 uint32_t d = (1048576*i) | 0xc02;
201
202 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
203 descr[0] = d; descr[1] = d >> 8;
204 descr[2] = d >> 16; descr[3] = d >> 24;
205 } else {
206 descr[3] = d; descr[2] = d >> 8;
207 descr[1] = d >> 16; descr[0] = d >> 24;
208 }
209 cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
210 sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
211 }
212 }
213
214
215 /*
216 * arm_translation_table_set_l1():
217 */
218 void arm_translation_table_set_l1(struct cpu *cpu, uint32_t vaddr,
219 uint32_t paddr)
220 {
221 unsigned int i, j, vhigh = vaddr >> 28, phigh = paddr >> 28;
222
223 for (i=0; i<256; i++)
224 for (j=vhigh; j<=vhigh; j++) {
225 unsigned char descr[4];
226 uint32_t addr = cpu->cd.arm.ttb +
227 (((j << 28) + (i << 20)) >> 18);
228 uint32_t d = ((phigh << 28) + 1048576*i) | 0xc02;
229
230 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
231 descr[0] = d; descr[1] = d >> 8;
232 descr[2] = d >> 16; descr[3] = d >> 24;
233 } else {
234 descr[3] = d; descr[2] = d >> 8;
235 descr[1] = d >> 16; descr[0] = d >> 24;
236 }
237 cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
238 sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
239 }
240 }
241
242
243 /*
244 * arm_translation_table_set_l1_b():
245 */
246 void arm_translation_table_set_l1_b(struct cpu *cpu, uint32_t vaddr,
247 uint32_t paddr)
248 {
249 unsigned int i, j, vhigh = vaddr >> 24, phigh = paddr >> 24;
250
251 for (i=0; i<16; i++)
252 for (j=vhigh; j<=vhigh; j++) {
253 unsigned char descr[4];
254 uint32_t addr = cpu->cd.arm.ttb +
255 (((j << 24) + (i << 20)) >> 18);
256 uint32_t d = ((phigh << 24) + 1048576*i) | 0xc02;
257
258 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
259 descr[0] = d; descr[1] = d >> 8;
260 descr[2] = d >> 16; descr[3] = d >> 24;
261 } else {
262 descr[3] = d; descr[2] = d >> 8;
263 descr[1] = d >> 16; descr[0] = d >> 24;
264 }
265 cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
266 sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
267 }
268 }
269
270
271 /*
272 * arm_cpu_dumpinfo():
273 */
274 void arm_cpu_dumpinfo(struct cpu *cpu)
275 {
276 struct arm_cpu_type_def *ct = &cpu->cd.arm.cpu_type;
277
278 debug(" (I+D = %i+%i KB)\n",
279 (1 << ct->icache_shift) / 1024, (1 << ct->dcache_shift) / 1024);
280 }
281
282
283 /*
284 * arm_cpu_list_available_types():
285 *
286 * Print a list of available ARM CPU types.
287 */
288 void arm_cpu_list_available_types(void)
289 {
290 int i, j;
291 struct arm_cpu_type_def tdefs[] = ARM_CPU_TYPE_DEFS;
292
293 i = 0;
294 while (tdefs[i].name != NULL) {
295 debug("%s", tdefs[i].name);
296 for (j=13 - strlen(tdefs[i].name); j>0; j--)
297 debug(" ");
298 i++;
299 if ((i % 5) == 0 || tdefs[i].name == NULL)
300 debug("\n");
301 }
302 }
303
304
305 /*
306 * arm_cpu_register_match():
307 */
308 void arm_cpu_register_match(struct machine *m, char *name,
309 int writeflag, uint64_t *valuep, int *match_register)
310 {
311 int i, cpunr = 0;
312
313 /* CPU number: */
314
315 /* TODO */
316
317 /* Register names: */
318 for (i=0; i<N_ARM_REGS; i++) {
319 if (strcasecmp(name, arm_regname[i]) == 0) {
320 if (writeflag) {
321 m->cpus[cpunr]->cd.arm.r[i] = *valuep;
322 if (i == ARM_PC)
323 m->cpus[cpunr]->pc = *valuep;
324 } else {
325 *valuep = m->cpus[cpunr]->cd.arm.r[i];
326 if (i == ARM_PC)
327 *valuep = m->cpus[cpunr]->pc;
328 }
329 *match_register = 1;
330 }
331 }
332 }
333
334
335 /*
336 * arm_cpu_register_dump():
337 *
338 * Dump cpu registers in a relatively readable format.
339 *
340 * gprs: set to non-zero to dump GPRs and some special-purpose registers.
341 * coprocs: set bit 0..3 to dump registers in coproc 0..3.
342 */
343 void arm_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
344 {
345 char *symbol;
346 uint64_t offset;
347 int mode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
348 int i, x = cpu->cpu_id;
349
350 cpu->cd.arm.cpsr &= 0x0fffffff;
351 cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
352
353 if (gprs) {
354 symbol = get_symbol_name(&cpu->machine->symbol_context,
355 cpu->pc, &offset);
356 debug("cpu%i: cpsr = ", x);
357 debug("%s%s%s%s%s%s",
358 (cpu->cd.arm.cpsr & ARM_FLAG_N)? "N" : "n",
359 (cpu->cd.arm.cpsr & ARM_FLAG_Z)? "Z" : "z",
360 (cpu->cd.arm.cpsr & ARM_FLAG_C)? "C" : "c",
361 (cpu->cd.arm.cpsr & ARM_FLAG_V)? "V" : "v",
362 (cpu->cd.arm.cpsr & ARM_FLAG_I)? "I" : "i",
363 (cpu->cd.arm.cpsr & ARM_FLAG_F)? "F" : "f");
364 if (mode < ARM_MODE_USR32)
365 debug(" pc = 0x%07x", (int)(cpu->pc & 0x03ffffff));
366 else
367 debug(" pc = 0x%08x", (int)cpu->pc);
368
369 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
370
371 for (i=0; i<N_ARM_REGS; i++) {
372 if ((i % 4) == 0)
373 debug("cpu%i:", x);
374 if (i != ARM_PC)
375 debug(" %s = 0x%08x", arm_regname[i],
376 (int)cpu->cd.arm.r[i]);
377 if ((i % 4) == 3)
378 debug("\n");
379 }
380 }
381
382 if (coprocs & 1) {
383 int m = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
384 debug("cpu%i: cpsr = 0x%08x (", x, cpu->cd.arm.cpsr);
385 switch (m) {
386 case ARM_MODE_USR32:
387 debug("USR32)\n"); break;
388 case ARM_MODE_SYS32:
389 debug("SYS32)\n"); break;
390 case ARM_MODE_FIQ32:
391 debug("FIQ32)\n"); break;
392 case ARM_MODE_IRQ32:
393 debug("IRQ32)\n"); break;
394 case ARM_MODE_SVC32:
395 debug("SVC32)\n"); break;
396 case ARM_MODE_ABT32:
397 debug("ABT32)\n"); break;
398 case ARM_MODE_UND32:
399 debug("UND32)\n"); break;
400 default:debug("unimplemented)\n");
401 }
402
403 if (m != ARM_MODE_USR32 && m != ARM_MODE_SYS32) {
404 debug("cpu%i: usr r8-14:", x);
405 for (i=0; i<7; i++)
406 debug(" %08x", cpu->cd.arm.default_r8_r14[i]);
407 debug("\n");
408 }
409
410 if (m != ARM_MODE_FIQ32) {
411 debug("cpu%i: fiq r8-14:", x);
412 for (i=0; i<7; i++)
413 debug(" %08x", cpu->cd.arm.fiq_r8_r14[i]);
414 debug("\n");
415 }
416
417 if (m != ARM_MODE_IRQ32) {
418 debug("cpu%i: irq r13-14:", x);
419 for (i=0; i<2; i++)
420 debug(" %08x", cpu->cd.arm.irq_r13_r14[i]);
421 debug("\n");
422 }
423
424 if (m != ARM_MODE_SVC32) {
425 debug("cpu%i: svc r13-14:", x);
426 for (i=0; i<2; i++)
427 debug(" %08x", cpu->cd.arm.svc_r13_r14[i]);
428 debug("\n");
429 }
430
431 if (m != ARM_MODE_ABT32) {
432 debug("cpu%i: abt r13-14:", x);
433 for (i=0; i<2; i++)
434 debug(" %08x", cpu->cd.arm.abt_r13_r14[i]);
435 debug("\n");
436 }
437
438 if (m != ARM_MODE_UND32) {
439 debug("cpu%i: und r13-14:", x);
440 for (i=0; i<2; i++)
441 debug(" %08x", cpu->cd.arm.und_r13_r14[i]);
442 debug("\n");
443 }
444 }
445
446 if (coprocs & 2) {
447 debug("cpu%i: control = 0x%08x\n", x, cpu->cd.arm.control);
448 debug("cpu%i: MMU: %s\n", x,
449 cpu->cd.arm.control &
450 ARM_CONTROL_MMU? "enabled" : "disabled");
451 debug("cpu%i: alignment checks: %s\n", x,
452 cpu->cd.arm.control &
453 ARM_CONTROL_ALIGN? "enabled" : "disabled");
454 debug("cpu%i: [data] cache: %s\n", x,
455 cpu->cd.arm.control &
456 ARM_CONTROL_CACHE? "enabled" : "disabled");
457 debug("cpu%i: instruction cache: %s\n", x,
458 cpu->cd.arm.control &
459 ARM_CONTROL_ICACHE? "enabled" : "disabled");
460 debug("cpu%i: write buffer: %s\n", x,
461 cpu->cd.arm.control &
462 ARM_CONTROL_WBUFFER? "enabled" : "disabled");
463 debug("cpu%i: prog32: %s\n", x,
464 cpu->cd.arm.control &
465 ARM_CONTROL_PROG32? "yes" : "no (using prog26)");
466 debug("cpu%i: data32: %s\n", x,
467 cpu->cd.arm.control &
468 ARM_CONTROL_DATA32? "yes" : "no (using data26)");
469 debug("cpu%i: endianness: %s\n", x,
470 cpu->cd.arm.control &
471 ARM_CONTROL_BIG? "big endian" : "little endian");
472 debug("cpu%i: high vectors: %s\n", x,
473 cpu->cd.arm.control &
474 ARM_CONTROL_V? "yes (0xffff0000)" : "no");
475
476 /* TODO: auxctrl on which CPU types? */
477 if (cpu->cd.arm.cpu_type.flags & ARM_XSCALE) {
478 debug("cpu%i: auxctrl = 0x%08x\n", x,
479 cpu->cd.arm.auxctrl);
480 debug("cpu%i: minidata cache attr = 0x%x\n", x,
481 (cpu->cd.arm.auxctrl & ARM_AUXCTRL_MD)
482 >> ARM_AUXCTRL_MD_SHIFT);
483 debug("cpu%i: page table memory attr: %i\n", x,
484 (cpu->cd.arm.auxctrl & ARM_AUXCTRL_P)? 1 : 0);
485 debug("cpu%i: write buffer coalescing: %s\n", x,
486 (cpu->cd.arm.auxctrl & ARM_AUXCTRL_K)?
487 "disabled" : "enabled");
488 }
489
490 debug("cpu%i: ttb = 0x%08x dacr = 0x%08x\n", x,
491 cpu->cd.arm.ttb, cpu->cd.arm.dacr);
492 debug("cpu%i: fsr = 0x%08x far = 0x%08x\n", x,
493 cpu->cd.arm.fsr, cpu->cd.arm.far);
494 }
495 }
496
497
498 /*
499 * arm_save_register_bank():
500 */
501 void arm_save_register_bank(struct cpu *cpu)
502 {
503 /* Save away current registers: */
504 switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
505 case ARM_MODE_USR32:
506 case ARM_MODE_SYS32:
507 memcpy(cpu->cd.arm.default_r8_r14,
508 &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
509 break;
510 case ARM_MODE_FIQ32:
511 memcpy(cpu->cd.arm.fiq_r8_r14,
512 &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
513 break;
514 case ARM_MODE_IRQ32:
515 memcpy(cpu->cd.arm.default_r8_r14,
516 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
517 cpu->cd.arm.irq_r13_r14[0] = cpu->cd.arm.r[13];
518 cpu->cd.arm.irq_r13_r14[1] = cpu->cd.arm.r[14];
519 break;
520 case ARM_MODE_SVC32:
521 memcpy(cpu->cd.arm.default_r8_r14,
522 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
523 cpu->cd.arm.svc_r13_r14[0] = cpu->cd.arm.r[13];
524 cpu->cd.arm.svc_r13_r14[1] = cpu->cd.arm.r[14];
525 break;
526 case ARM_MODE_ABT32:
527 memcpy(cpu->cd.arm.default_r8_r14,
528 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
529 cpu->cd.arm.abt_r13_r14[0] = cpu->cd.arm.r[13];
530 cpu->cd.arm.abt_r13_r14[1] = cpu->cd.arm.r[14];
531 break;
532 case ARM_MODE_UND32:
533 memcpy(cpu->cd.arm.default_r8_r14,
534 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
535 cpu->cd.arm.und_r13_r14[0] = cpu->cd.arm.r[13];
536 cpu->cd.arm.und_r13_r14[1] = cpu->cd.arm.r[14];
537 break;
538 default:fatal("arm_save_register_bank: unimplemented mode %i\n",
539 cpu->cd.arm.cpsr & ARM_FLAG_MODE);
540 exit(1);
541 }
542 }
543
544
545 /*
546 * arm_load_register_bank():
547 */
548 void arm_load_register_bank(struct cpu *cpu)
549 {
550 /* Load new registers: */
551 switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
552 case ARM_MODE_USR32:
553 case ARM_MODE_SYS32:
554 memcpy(&cpu->cd.arm.r[8],
555 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 7);
556 break;
557 case ARM_MODE_FIQ32:
558 memcpy(&cpu->cd.arm.r[8], cpu->cd.arm.fiq_r8_r14,
559 sizeof(uint32_t) * 7);
560 break;
561 case ARM_MODE_IRQ32:
562 memcpy(&cpu->cd.arm.r[8],
563 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
564 cpu->cd.arm.r[13] = cpu->cd.arm.irq_r13_r14[0];
565 cpu->cd.arm.r[14] = cpu->cd.arm.irq_r13_r14[1];
566 break;
567 case ARM_MODE_SVC32:
568 memcpy(&cpu->cd.arm.r[8],
569 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
570 cpu->cd.arm.r[13] = cpu->cd.arm.svc_r13_r14[0];
571 cpu->cd.arm.r[14] = cpu->cd.arm.svc_r13_r14[1];
572 break;
573 case ARM_MODE_ABT32:
574 memcpy(&cpu->cd.arm.r[8],
575 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
576 cpu->cd.arm.r[13] = cpu->cd.arm.abt_r13_r14[0];
577 cpu->cd.arm.r[14] = cpu->cd.arm.abt_r13_r14[1];
578 break;
579 case ARM_MODE_UND32:
580 memcpy(&cpu->cd.arm.r[8],
581 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
582 cpu->cd.arm.r[13] = cpu->cd.arm.und_r13_r14[0];
583 cpu->cd.arm.r[14] = cpu->cd.arm.und_r13_r14[1];
584 break;
585 default:fatal("arm_load_register_bank: unimplemented mode %i\n",
586 cpu->cd.arm.cpsr & ARM_FLAG_MODE);
587 exit(1);
588 }
589 }
590
591
592 /*
593 * arm_exception():
594 */
595 void arm_exception(struct cpu *cpu, int exception_nr)
596 {
597 int oldmode, newmode;
598 uint32_t retaddr;
599
600 if (exception_nr < 0 || exception_nr >= N_ARM_EXCEPTIONS) {
601 fatal("arm_exception(): exception_nr = %i\n", exception_nr);
602 exit(1);
603 }
604
605 retaddr = cpu->pc;
606
607 if (!quiet_mode) {
608 debug("[ arm_exception(): ");
609 switch (exception_nr) {
610 case ARM_EXCEPTION_RESET:
611 fatal("RESET: TODO");
612 break;
613 case ARM_EXCEPTION_UND:
614 debug("UNDEFINED");
615 break;
616 case ARM_EXCEPTION_SWI:
617 debug("SWI");
618 break;
619 case ARM_EXCEPTION_PREF_ABT:
620 debug("PREFETCH ABORT");
621 break;
622 case ARM_EXCEPTION_IRQ:
623 debug("IRQ");
624 break;
625 case ARM_EXCEPTION_FIQ:
626 debug("FIQ");
627 break;
628 case ARM_EXCEPTION_DATA_ABT:
629 debug("DATA ABORT, far=0x%08x fsr=0x%02x",
630 cpu->cd.arm.far, cpu->cd.arm.fsr);
631 break;
632 }
633 debug(" ]\n");
634 }
635
636 switch (exception_nr) {
637 case ARM_EXCEPTION_RESET:
638 cpu->running = 0;
639 fatal("ARM RESET: TODO");
640 exit(1);
641 case ARM_EXCEPTION_DATA_ABT:
642 retaddr += 4;
643 break;
644 }
645
646 retaddr += 4;
647
648 arm_save_register_bank(cpu);
649
650 cpu->cd.arm.cpsr &= 0x0fffffff;
651 cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
652
653 switch (arm_exception_to_mode[exception_nr]) {
654 case ARM_MODE_SVC32:
655 cpu->cd.arm.spsr_svc = cpu->cd.arm.cpsr; break;
656 case ARM_MODE_ABT32:
657 cpu->cd.arm.spsr_abt = cpu->cd.arm.cpsr; break;
658 case ARM_MODE_UND32:
659 cpu->cd.arm.spsr_und = cpu->cd.arm.cpsr; break;
660 case ARM_MODE_IRQ32:
661 cpu->cd.arm.spsr_irq = cpu->cd.arm.cpsr; break;
662 case ARM_MODE_FIQ32:
663 cpu->cd.arm.spsr_fiq = cpu->cd.arm.cpsr; break;
664 default:fatal("arm_exception(): unimplemented exception nr\n");
665 exit(1);
666 }
667
668 /*
669 * Disable Thumb mode (because exception handlers always execute
670 * in ARM mode), set the exception mode, and disable interrupts:
671 */
672 cpu->cd.arm.cpsr &= ~ARM_FLAG_T;
673
674 oldmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
675
676 cpu->cd.arm.cpsr &= ~ARM_FLAG_MODE;
677 cpu->cd.arm.cpsr |= arm_exception_to_mode[exception_nr];
678
679 /*
680 * Usually, an exception should change modes (so that saved status
681 * bits don't get lost). However, Linux on ARM seems to use floating
682 * point instructions in the kernel (!), and it emulates those using
683 * its own fp emulation code. This leads to a situation where we
684 * sometimes change from SVC32 to SVC32.
685 */
686 newmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
687 if (oldmode == newmode && oldmode != ARM_MODE_SVC32) {
688 fatal("[ WARNING! Exception caused no mode change? "
689 "mode 0x%02x (pc=0x%x) ]\n", newmode, (int)cpu->pc);
690 /* exit(1); */
691 }
692
693 cpu->cd.arm.cpsr |= ARM_FLAG_I;
694 if (exception_nr == ARM_EXCEPTION_RESET ||
695 exception_nr == ARM_EXCEPTION_FIQ)
696 cpu->cd.arm.cpsr |= ARM_FLAG_F;
697
698 /* Load the new register bank, if we switched: */
699 arm_load_register_bank(cpu);
700
701 /*
702 * Set the return address and new PC.
703 *
704 * NOTE: r[ARM_PC] is also set; see cpu_arm_instr_loadstore.c for
705 * details. (If an exception occurs during a load into the pc
706 * register, the code in that file assumes that the r[ARM_PC]
707 * was changed to the address of the exception handler.)
708 */
709 cpu->cd.arm.r[ARM_LR] = retaddr;
710 cpu->pc = cpu->cd.arm.r[ARM_PC] = exception_nr * 4 +
711 ((cpu->cd.arm.control & ARM_CONTROL_V)? 0xffff0000 : 0);
712 quick_pc_to_pointers(cpu);
713 }
714
715
716 /*
717 * arm_cpu_tlbdump():
718 *
719 * Called from the debugger to dump the TLB in a readable format.
720 * x is the cpu number to dump, or -1 to dump all CPUs.
721 *
722 * If rawflag is nonzero, then the TLB contents isn't formated nicely,
723 * just dumped.
724 */
725 void arm_cpu_tlbdump(struct machine *m, int x, int rawflag)
726 {
727 }
728
729
730 static void add_response_word(struct cpu *cpu, char *r, uint32_t value,
731 size_t maxlen)
732 {
733 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
734 value = ((value & 0xff) << 24) +
735 ((value & 0xff00) << 8) +
736 ((value & 0xff0000) >> 8) +
737 ((value & 0xff000000) >> 24);
738 }
739 snprintf(r + strlen(r), maxlen - strlen(r), "%08"PRIx32, value);
740 }
741
742
743 /*
744 * arm_cpu_gdb_stub():
745 *
746 * Execute a "remote GDB" command. Returns a newly allocated response string
747 * on success, NULL on failure.
748 */
749 char *arm_cpu_gdb_stub(struct cpu *cpu, char *cmd)
750 {
751 if (strcmp(cmd, "g") == 0) {
752 /* 15 gprs, pc, 8 fprs, fps, cpsr. */
753 int i;
754 char *r;
755 size_t len = 1 + 18 * sizeof(uint32_t);
756 r = malloc(len);
757 if (r == NULL) {
758 fprintf(stderr, "out of memory\n");
759 exit(1);
760 }
761 r[0] = '\0';
762 for (i=0; i<15; i++)
763 add_response_word(cpu, r, cpu->cd.arm.r[i], len);
764 add_response_word(cpu, r, cpu->pc, len);
765 /* TODO: fprs: */
766 for (i=0; i<8; i++)
767 add_response_word(cpu, r, 0, len);
768 /* TODO: fps */
769 add_response_word(cpu, r, 0, len);
770 add_response_word(cpu, r, cpu->cd.arm.cpsr, len);
771 return r;
772 }
773
774 if (cmd[0] == 'p') {
775 int regnr = strtol(cmd + 1, NULL, 16);
776 size_t len = 2 * sizeof(uint32_t) + 1;
777 char *r = malloc(len);
778 r[0] = '\0';
779 if (regnr == ARM_PC) {
780 add_response_word(cpu, r, cpu->pc, len);
781 } else if (regnr >= 0 && regnr < ARM_PC) {
782 add_response_word(cpu, r, cpu->cd.arm.r[regnr], len);
783 } else if (regnr >= 0x10 && regnr <= 0x17) {
784 /* TODO: fprs */
785 add_response_word(cpu, r, 0, len);
786 add_response_word(cpu, r, 0, len);
787 add_response_word(cpu, r, 0, len);
788 } else if (regnr == 0x18) {
789 /* TODO: fps */
790 add_response_word(cpu, r, 0, len);
791 } else if (regnr == 0x19) {
792 add_response_word(cpu, r, cpu->cd.arm.cpsr, len);
793 }
794 return r;
795 }
796
797 fatal("arm_cpu_gdb_stub(): TODO\n");
798 return NULL;
799 }
800
801
802 /*
803 * arm_cpu_interrupt():
804 *
805 * 0..31 are used as footbridge interrupt numbers, 32..47 = ISA,
806 * 64 is used as a "re-assert" signal to cpu->machine->md_interrupt().
807 *
808 * TODO: don't hardcode to footbridge!
809 */
810 int arm_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
811 {
812 /* fatal("arm_cpu_interrupt(): 0x%x\n", (int)irq_nr); */
813 if (irq_nr <= 64) {
814 if (cpu->machine->md_interrupt != NULL)
815 cpu->machine->md_interrupt(cpu->machine,
816 cpu, irq_nr, 1);
817 else
818 fatal("arm_cpu_interrupt(): irq_nr=%i md_interrupt =="
819 " NULL\n", (int)irq_nr);
820 } else {
821 /* Assert ARM IRQs: */
822 cpu->cd.arm.irq_asserted = 1;
823 }
824
825 return 1;
826 }
827
828
829 /*
830 * arm_cpu_interrupt_ack():
831 */
832 int arm_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
833 {
834 if (irq_nr <= 64) {
835 if (cpu->machine->md_interrupt != NULL)
836 cpu->machine->md_interrupt(cpu->machine,
837 cpu, irq_nr, 0);
838 } else {
839 /* De-assert ARM IRQs: */
840 cpu->cd.arm.irq_asserted = 0;
841 }
842
843 return 1;
844 }
845
846
847 /*
848 * arm_cpu_disassemble_instr():
849 *
850 * Convert an instruction word into human readable format, for instruction
851 * tracing.
852 *
853 * If running is 1, cpu->pc should be the address of the instruction.
854 *
855 * If running is 0, things that depend on the runtime environment (eg.
856 * register contents) will not be shown, and addr will be used instead of
857 * cpu->pc for relative addresses.
858 */
859 int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
860 int running, uint64_t dumpaddr)
861 {
862 uint32_t iw, tmp;
863 int main_opcode, secondary_opcode, s_bit, r16, r12, r8;
864 int i, n, p_bit, u_bit, b_bit, w_bit, l_bit;
865 char *symbol, *condition;
866 uint64_t offset;
867
868 if (running)
869 dumpaddr = cpu->pc;
870
871 symbol = get_symbol_name(&cpu->machine->symbol_context,
872 dumpaddr, &offset);
873 if (symbol != NULL && offset == 0)
874 debug("<%s>\n", symbol);
875
876 if (cpu->machine->ncpus > 1 && running)
877 debug("cpu%i:\t", cpu->cpu_id);
878
879 debug("%08x: ", (int)dumpaddr);
880
881 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
882 iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
883 else
884 iw = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
885 debug("%08x\t", (int)iw);
886
887 condition = arm_condition_string[iw >> 28];
888 main_opcode = (iw >> 24) & 15;
889 secondary_opcode = (iw >> 21) & 15;
890 u_bit = (iw >> 23) & 1;
891 b_bit = (iw >> 22) & 1;
892 w_bit = (iw >> 21) & 1;
893 s_bit = l_bit = (iw >> 20) & 1;
894 r16 = (iw >> 16) & 15;
895 r12 = (iw >> 12) & 15;
896 r8 = (iw >> 8) & 15;
897
898 switch (main_opcode) {
899 case 0x0:
900 case 0x1:
901 case 0x2:
902 case 0x3:
903 /*
904 * Special cases first:
905 */
906
907 /*
908 * Multiplication:
909 * xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd, Rm, Rs [,Rn])
910 */
911 if ((iw & 0x0fc000f0) == 0x00000090) {
912 int a_bit = (iw >> 21) & 1;
913 debug("%s%s%s\t", a_bit? "mla" : "mul",
914 condition, s_bit? "s" : "");
915 debug("%s,", arm_regname[r16]);
916 debug("%s,", arm_regname[iw & 15]);
917 debug("%s", arm_regname[r8]);
918 if (a_bit)
919 debug(",%s", arm_regname[r12]);
920 debug("\n");
921 break;
922 }
923
924 /*
925 * Long multiplication:
926 * xxxx0000 1UAShhhh llllssss 1001mmmm (Rl,Rh,Rm,Rs)
927 */
928 if ((iw & 0x0f8000f0) == 0x00800090) {
929 int u_bit = (iw >> 22) & 1;
930 int a_bit = (iw >> 21) & 1;
931 debug("%s%sl%s%s\t", u_bit? "s" : "u",
932 a_bit? "mla" : "mul", condition, s_bit? "s" : "");
933 debug("%s,%s,", arm_regname[r12], arm_regname[r16]);
934 debug("%s,%s\n", arm_regname[iw&15], arm_regname[r8]);
935 break;
936 }
937
938 /*
939 * xxxx0001 0000nnnn dddd0000 0101mmmm qadd Rd,Rm,Rn
940 * xxxx0001 0010nnnn dddd0000 0101mmmm qsub Rd,Rm,Rn
941 * xxxx0001 0100nnnn dddd0000 0101mmmm qdadd Rd,Rm,Rn
942 * xxxx0001 0110nnnn dddd0000 0101mmmm qdsub Rd,Rm,Rn
943 */
944 if ((iw & 0x0f900ff0) == 0x01000050) {
945 debug("q%s%s%s\t", iw & 0x400000? "d" : "",
946 iw & 0x200000? "sub" : "add", condition);
947 debug("%s,%s,%s\n", arm_regname[r12],
948 arm_regname[iw&15], arm_regname[r16]);
949 break;
950 }
951
952 /*
953 * xxxx0001 0010.... ........ 00L1mmmm bx/blx rm
954 */
955 if ((iw & 0x0ff000d0) == 0x01200010) {
956 int l_bit = iw & 0x20;
957 debug("b%sx%s\t%s\n", l_bit? "l" : "", condition,
958 arm_regname[iw & 15]);
959 break;
960 }
961
962 /*
963 * xxxx0001 0s10aaaa 11110000 0000mmmm MSR Regform
964 * xxxx0011 0s10aaaa 1111rrrr bbbbbbbb MSR Immform
965 * xxxx0001 0s001111 dddd0000 00000000 MRS
966 */
967 if ((iw & 0x0fb0fff0) == 0x0120f000 ||
968 (iw & 0x0fb0f000) == 0x0320f000) {
969 int a = (iw >> 16) & 15;
970 debug("msr%s\t%s", condition, (iw&0x400000)? "S":"C");
971 debug("PSR_");
972 switch (a) {
973 case 1: debug("ctl"); break;
974 case 8: debug("flg"); break;
975 case 9: debug("all"); break;
976 default:debug(" UNIMPLEMENTED (a=%i)", a);
977 }
978 if (iw & 0x02000000) {
979 int r = (iw >> 7) & 30;
980 uint32_t b = iw & 0xff;
981 while (r-- > 0)
982 b = (b >> 1) | ((b & 1) << 31);
983 debug(",#0x%x\n", b);
984 } else
985 debug(",%s\n", arm_regname[iw & 15]);
986 break;
987 }
988 if ((iw & 0x0fbf0fff) == 0x010f0000) {
989 debug("mrs%s\t", condition);
990 debug("%s,%sPSR\n", arm_regname[r12],
991 (iw&0x400000)? "S":"C");
992 break;
993 }
994
995 /*
996 * xxxx0001 0B00nnnn dddd0000 1001mmmm SWP Rd,Rm,[Rn]
997 */
998 if ((iw & 0x0fb00ff0) == 0x01000090) {
999 debug("swp%s%s\t", condition, (iw&0x400000)? "b":"");
1000 debug("%s,%s,[%s]\n", arm_regname[r12],
1001 arm_regname[iw & 15], arm_regname[r16]);
1002 break;
1003 }
1004
1005 /*
1006 * xxxx0001 01101111 dddd1111 0001mmmm CLZ Rd,Rm
1007 */
1008 if ((iw & 0x0fff0ff0) == 0x016f0f10) {
1009 debug("clz%s\t", condition);
1010 debug("%s,%s\n", arm_regname[r12], arm_regname[iw&15]);
1011 break;
1012 }
1013
1014 /*
1015 * xxxx0001 0000dddd nnnnssss 1yx0mmmm SMLAxy Rd,Rm,Rs,Rn
1016 * xxxx0001 0100dddd DDDDssss 1yx0mmmm SMLALxy RdL,RdH,Rm,Rs
1017 * xxxx0001 0010dddd nnnnssss 1y00mmmm SMLAWy Rd,Rm,Rs,Rn
1018 * xxxx0001 0110dddd 0000ssss 1yx0mmmm SMULxy Rd,Rm,Rs
1019 * xxxx0001 0010dddd 0000ssss 1y10mmmm SMULWy Rd,Rm,Rs
1020 */
1021 if ((iw & 0x0ff00090) == 0x01000080) {
1022 debug("smla%s%s%s\t",
1023 iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
1024 condition);
1025 debug("%s,%s,%s,%s\n", arm_regname[r16],
1026 arm_regname[iw&15], arm_regname[r8],
1027 arm_regname[r12]);
1028 break;
1029 }
1030 if ((iw & 0x0ff00090) == 0x01400080) {
1031 debug("smlal%s%s%s\t",
1032 iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
1033 condition);
1034 debug("%s,%s,%s,%s\n", arm_regname[r12],
1035 arm_regname[r16], arm_regname[iw&15],
1036 arm_regname[r8]);
1037 break;
1038 }
1039 if ((iw & 0x0ff000b0) == 0x01200080) {
1040 debug("smlaw%s%s\t", iw & 0x40? "t" : "b",
1041 condition);
1042 debug("%s,%s,%s,%s\n", arm_regname[r16],
1043 arm_regname[iw&15], arm_regname[r8],
1044 arm_regname[r12]);
1045 break;
1046 }
1047 if ((iw & 0x0ff0f090) == 0x01600080) {
1048 debug("smul%s%s%s\t",
1049 iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
1050 condition);
1051 debug("%s,%s,%s\n", arm_regname[r16],
1052 arm_regname[iw&15], arm_regname[r8]);
1053 break;
1054 }
1055 if ((iw & 0x0ff0f0b0) == 0x012000a0) {
1056 debug("smulw%s%s\t", iw & 0x40? "t" : "b",
1057 condition);
1058 debug("%s,%s,%s\n", arm_regname[r16],
1059 arm_regname[iw&15], arm_regname[r8]);
1060 break;
1061 }
1062
1063 /*
1064 * xxxx000P U1WLnnnn ddddHHHH 1SH1LLLL load/store rd,imm(rn)
1065 */
1066 if ((iw & 0x0e000090) == 0x00000090) {
1067 char *op = "st";
1068 int imm = ((iw >> 4) & 0xf0) | (iw & 0xf);
1069 int regform = !(iw & 0x00400000);
1070 p_bit = main_opcode & 1;
1071 /*
1072 * TODO: detect some illegal variants:
1073 * signed store, or unsigned byte load/store
1074 */
1075 if (!l_bit && (iw & 0xd0) == 0xd0 && (r12 & 1)) {
1076 debug("TODO: r12 odd, not load/store\n");
1077 break;
1078 }
1079 /* Semi-generic case: */
1080 if (iw & 0x00100000)
1081 op = "ld";
1082 if (!l_bit && (iw & 0xd0) == 0xd0)
1083 op = iw & 0x20? "st" : "ld";
1084 debug("%sr%s", op, condition);
1085 if (!l_bit && (iw & 0xd0) == 0xd0) {
1086 debug("d"); /* Double-register */
1087 } else {
1088 if (iw & 0x40)
1089 debug("s"); /* signed */
1090 if (iw & 0x20)
1091 debug("h"); /* half-word */
1092 else
1093 debug("b"); /* byte */
1094 }
1095 debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
1096 if (p_bit) {
1097 /* Pre-index: */
1098 if (regform)
1099 debug(",%s%s", u_bit? "" : "-",
1100 arm_regname[iw & 15]);
1101 else {
1102 if (imm != 0)
1103 debug(",#%s%i", u_bit? "" : "-",
1104 imm);
1105 }
1106 debug("]%s\n", w_bit? "!" : "");
1107 } else {
1108 /* Post-index: */
1109 debug("],");
1110 if (regform)
1111 debug("%s%s\n", u_bit? "" : "-",
1112 arm_regname[iw & 15]);
1113 else
1114 debug("#%s%i\n", u_bit? "" : "-", imm);
1115 }
1116 break;
1117 }
1118
1119 /* Other special cases: */
1120 if (iw & 0x80 && !(main_opcode & 2) && iw & 0x10) {
1121 debug("UNIMPLEMENTED reg (c!=0), t odd\n");
1122 break;
1123 }
1124
1125 /*
1126 * Generic Data Processing Instructions:
1127 *
1128 * xxxx000a aaaSnnnn ddddcccc ctttmmmm Register form
1129 * xxxx001a aaaSnnnn ddddrrrr bbbbbbbb Immediate form
1130 */
1131
1132 debug("%s%s%s\t", arm_dpiname[secondary_opcode],
1133 condition, s_bit? "s" : "");
1134 if (arm_dpi_uses_d[secondary_opcode])
1135 debug("%s,", arm_regname[r12]);
1136 if (arm_dpi_uses_n[secondary_opcode])
1137 debug("%s,", arm_regname[r16]);
1138
1139 if (main_opcode & 2) {
1140 /* Immediate form: */
1141 int r = (iw >> 7) & 30;
1142 uint32_t b = iw & 0xff;
1143 while (r-- > 0)
1144 b = (b >> 1) | ((b & 1) << 31);
1145 if (b < 15)
1146 debug("#%i", b);
1147 else
1148 debug("#0x%x", b);
1149 } else {
1150 /* Register form: */
1151 int t = (iw >> 4) & 7;
1152 int c = (iw >> 7) & 31;
1153 debug("%s", arm_regname[iw & 15]);
1154 switch (t) {
1155 case 0: if (c != 0)
1156 debug(", lsl #%i", c);
1157 break;
1158 case 1: debug(", lsl %s", arm_regname[c >> 1]);
1159 break;
1160 case 2: debug(", lsr #%i", c? c : 32);
1161 break;
1162 case 3: debug(", lsr %s", arm_regname[c >> 1]);
1163 break;
1164 case 4: debug(", asr #%i", c? c : 32);
1165 break;
1166 case 5: debug(", asr %s", arm_regname[c >> 1]);
1167 break;
1168 case 6: if (c != 0)
1169 debug(", ror #%i", c);
1170 else
1171 debug(", rrx");
1172 break;
1173 case 7: debug(", ror %s", arm_regname[c >> 1]);
1174 break;
1175 }
1176
1177 /* mov pc,reg: */
1178 if (running && t == 0 && c == 0 && secondary_opcode
1179 == 0xd && r12 == ARM_PC && (iw&15)!=ARM_PC) {
1180 symbol = get_symbol_name(&cpu->machine->
1181 symbol_context, cpu->cd.arm.r[iw & 15],
1182 &offset);
1183 if (symbol != NULL)
1184 debug(" \t<%s>", symbol);
1185 }
1186 }
1187 debug("\n");
1188 break;
1189 case 0x4: /* Single Data Transfer */
1190 case 0x5:
1191 case 0x6:
1192 case 0x7:
1193 /* Special case first: */
1194 if ((iw & 0xfc70f000) == 0xf450f000) {
1195 /* Preload: */
1196 debug("pld\t[%s]\n", arm_regname[r16]);
1197 break;
1198 }
1199
1200 /*
1201 * xxxx010P UBWLnnnn ddddoooo oooooooo Immediate form
1202 * xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form
1203 */
1204 p_bit = main_opcode & 1;
1205 if (main_opcode >= 6 && iw & 0x10) {
1206 debug("TODO: single data transf. but 0x10\n");
1207 break;
1208 }
1209 debug("%s%s%s", l_bit? "ldr" : "str",
1210 condition, b_bit? "b" : "");
1211 if (!p_bit && w_bit)
1212 debug("t");
1213 debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
1214 if ((iw & 0x0e000000) == 0x04000000) {
1215 /* Immediate form: */
1216 uint32_t imm = iw & 0xfff;
1217 if (!p_bit)
1218 debug("]");
1219 if (imm != 0)
1220 debug(",#%s%i", u_bit? "" : "-", imm);
1221 if (p_bit)
1222 debug("]");
1223 } else if ((iw & 0x0e000010) == 0x06000000) {
1224 /* Register form: */
1225 if (!p_bit)
1226 debug("]");
1227 if ((iw & 0xfff) != 0)
1228 debug(",%s%s", u_bit? "" : "-",
1229 arm_regname[iw & 15]);
1230 if ((iw & 0xff0) != 0x000) {
1231 int c = (iw >> 7) & 31;
1232 int t = (iw >> 4) & 7;
1233 switch (t) {
1234 case 0: if (c != 0)
1235 debug(", lsl #%i", c);
1236 break;
1237 case 2: debug(", lsr #%i", c? c : 32);
1238 break;
1239 case 4: debug(", asr #%i", c? c : 32);
1240 break;
1241 case 6: if (c != 0)
1242 debug(", ror #%i", c);
1243 else
1244 debug(", rrx");
1245 break;
1246 }
1247 }
1248 if (p_bit)
1249 debug("]");
1250 } else {
1251 debug("UNKNOWN\n");
1252 break;
1253 }
1254 debug("%s", (p_bit && w_bit)? "!" : "");
1255 if ((iw & 0x0f000000) == 0x05000000 &&
1256 (r16 == ARM_PC || running)) {
1257 unsigned char tmpw[4];
1258 uint32_t imm = iw & 0xfff;
1259 uint32_t addr = (u_bit? imm : -imm);
1260 if (r16 == ARM_PC)
1261 addr += dumpaddr + 8;
1262 else
1263 addr += cpu->cd.arm.r[r16];
1264 symbol = get_symbol_name(&cpu->machine->symbol_context,
1265 addr, &offset);
1266 if (symbol != NULL)
1267 debug(" \t<%s", symbol);
1268 else
1269 debug(" \t<0x%08x", addr);
1270 if ((l_bit && cpu->memory_rw(cpu, cpu->mem, addr, tmpw,
1271 b_bit? 1 : sizeof(tmpw), MEM_READ, NO_EXCEPTIONS))
1272 || (!l_bit && running)) {
1273 if (l_bit) {
1274 if (cpu->byte_order ==
1275 EMUL_LITTLE_ENDIAN)
1276 addr = tmpw[0] +(tmpw[1] << 8) +
1277 (tmpw[2]<<16)+(tmpw[3]<<24);
1278 else
1279 addr = tmpw[3] + (tmpw[2]<<8) +
1280 (tmpw[1]<<16)+(tmpw[0]<<24);
1281 } else {
1282 tmpw[0] = addr = cpu->cd.arm.r[r12];
1283 if (r12 == ARM_PC)
1284 addr = cpu->pc + 8;
1285 }
1286 debug(": ");
1287 if (b_bit)
1288 debug("%i", tmpw[0]);
1289 else {
1290 symbol = get_symbol_name(&cpu->machine->
1291 symbol_context, addr, &offset);
1292 if (symbol != NULL)
1293 debug("%s", symbol);
1294 else if ((int32_t)addr > -256 &&
1295 (int32_t)addr < 256)
1296 debug("%i", addr);
1297 else
1298 debug("0x%x", addr);
1299 }
1300 }
1301 debug(">");
1302 }
1303 debug("\n");
1304 break;
1305 case 0x8: /* Block Data Transfer */
1306 case 0x9:
1307 /* xxxx100P USWLnnnn llllllll llllllll */
1308 p_bit = main_opcode & 1;
1309 s_bit = b_bit;
1310 debug("%s%s", l_bit? "ldm" : "stm", condition);
1311 switch (u_bit * 2 + p_bit) {
1312 case 0: debug("da"); break;
1313 case 1: debug("db"); break;
1314 case 2: debug("ia"); break;
1315 case 3: debug("ib"); break;
1316 }
1317 debug("\t%s", arm_regname[r16]);
1318 if (w_bit)
1319 debug("!");
1320 debug(",{");
1321 n = 0;
1322 for (i=0; i<16; i++)
1323 if ((iw >> i) & 1) {
1324 debug("%s%s", (n > 0)? ",":"", arm_regname[i]);
1325 n++;
1326 }
1327 debug("}");
1328 if (s_bit)
1329 debug("^");
1330 debug("\n");
1331 break;
1332 case 0xa: /* B: branch */
1333 case 0xb: /* BL: branch and link */
1334 debug("b%s%s\t", main_opcode == 0xa? "" : "l", condition);
1335 tmp = (iw & 0x00ffffff) << 2;
1336 if (tmp & 0x02000000)
1337 tmp |= 0xfc000000;
1338 tmp = (int32_t)(dumpaddr + tmp + 8);
1339 debug("0x%x", (int)tmp);
1340 symbol = get_symbol_name(&cpu->machine->symbol_context,
1341 tmp, &offset);
1342 if (symbol != NULL)
1343 debug(" \t<%s>", symbol);
1344 debug("\n");
1345 break;
1346 case 0xc: /* Coprocessor */
1347 case 0xd: /* LDC/STC */
1348 /*
1349 * xxxx1100 0100nnnn ddddcccc oooommmm MCRR c,op,Rd,Rn,CRm
1350 * xxxx1100 0101nnnn ddddcccc oooommmm MRRC c,op,Rd,Rn,CRm
1351 */
1352 if ((iw & 0x0fe00fff) == 0x0c400000) {
1353 debug("%s%s\t", iw & 0x100000? "mra" : "mar",
1354 condition);
1355 if (iw & 0x100000)
1356 debug("%s,%s,acc0\n",
1357 arm_regname[r12], arm_regname[r16]);
1358 else
1359 debug("acc0,%s,%s\n",
1360 arm_regname[r12], arm_regname[r16]);
1361 break;
1362 }
1363 if ((iw & 0x0fe00000) == 0x0c400000) {
1364 debug("%s%s\t", iw & 0x100000? "mrrc" : "mcrr",
1365 condition);
1366 debug("%i,%i,%s,%s,cr%i\n", r8, (iw >> 4) & 15,
1367 arm_regname[r12], arm_regname[r16], iw & 15);
1368 break;
1369 }
1370
1371 /* xxxx110P UNWLnnnn DDDDpppp oooooooo LDC/STC */
1372 debug("TODO: coprocessor LDC/STC\n");
1373 break;
1374 case 0xe: /* CDP (Coprocessor Op) */
1375 /* or MRC/MCR!
1376 * xxxx1110 oooonnnn ddddpppp qqq0mmmm CDP
1377 * xxxx1110 oooLNNNN ddddpppp qqq1MMMM MRC/MCR
1378 */
1379 if ((iw & 0x0ff00ff0) == 0x0e200010) {
1380 /* Special case: mia* DSP instructions */
1381 switch ((iw >> 16) & 0xf) {
1382 case 0: debug("mia"); break;
1383 case 8: debug("miaph"); break;
1384 case 12: debug("miaBB"); break;
1385 case 13: debug("miaTB"); break;
1386 case 14: debug("miaBT"); break;
1387 case 15: debug("miaTT"); break;
1388 default: debug("UNKNOWN mia vector instruction?");
1389 }
1390 debug("%s\t", condition);
1391 debug("acc%i,%s,%s\n", ((iw >> 5) & 7),
1392 arm_regname[iw & 15], arm_regname[r12]);
1393 break;
1394 }
1395 if (iw & 0x10) {
1396 debug("%s%s\t",
1397 (iw & 0x00100000)? "mrc" : "mcr", condition);
1398 debug("%i,%i,r%i,cr%i,cr%i,%i",
1399 (int)((iw >> 8) & 15), (int)((iw >>21) & 7),
1400 (int)((iw >>12) & 15), (int)((iw >>16) & 15),
1401 (int)((iw >> 0) & 15), (int)((iw >> 5) & 7));
1402 } else {
1403 debug("cdp%s\t", condition);
1404 debug("%i,%i,cr%i,cr%i,cr%i",
1405 (int)((iw >> 8) & 15),
1406 (int)((iw >>20) & 15),
1407 (int)((iw >>12) & 15),
1408 (int)((iw >>16) & 15),
1409 (int)((iw >> 0) & 15));
1410 if ((iw >> 5) & 7)
1411 debug(",0x%x", (int)((iw >> 5) & 7));
1412 }
1413 debug("\n");
1414 break;
1415 case 0xf: /* SWI */
1416 debug("swi%s\t", condition);
1417 debug("0x%x\n", (int)(iw & 0x00ffffff));
1418 break;
1419 default:debug("UNIMPLEMENTED\n");
1420 }
1421
1422 return sizeof(uint32_t);
1423 }
1424
1425
1426 /*****************************************************************************/
1427
1428
1429 /*
1430 * arm_mcr_mrc():
1431 *
1432 * Coprocessor register move.
1433 *
1434 * The program counter should be synched before calling this function (to
1435 * make debug output with the correct PC value possible).
1436 */
1437 void arm_mcr_mrc(struct cpu *cpu, uint32_t iword)
1438 {
1439 int opcode1 = (iword >> 21) & 7;
1440 int l_bit = (iword >> 20) & 1;
1441 int crn = (iword >> 16) & 15;
1442 int rd = (iword >> 12) & 15;
1443 int cp_num = (iword >> 8) & 15;
1444 int opcode2 = (iword >> 5) & 7;
1445 int crm = iword & 15;
1446
1447 if (cpu->cd.arm.coproc[cp_num] != NULL)
1448 cpu->cd.arm.coproc[cp_num](cpu, opcode1, opcode2, l_bit,
1449 crn, crm, rd);
1450 else {
1451 fatal("[ arm_mcr_mrc: pc=0x%08x, iword=0x%08x: "
1452 "cp_num=%i ]\n", (int)cpu->pc, iword, cp_num);
1453 arm_exception(cpu, ARM_EXCEPTION_UND);
1454 /* exit(1); */
1455 }
1456 }
1457
1458
1459 /*
1460 * arm_cdp():
1461 *
1462 * Coprocessor operations.
1463 *
1464 * The program counter should be synched before calling this function (to
1465 * make debug output with the correct PC value possible).
1466 */
1467 void arm_cdp(struct cpu *cpu, uint32_t iword)
1468 {
1469 fatal("[ arm_cdp: pc=0x%08x, iword=0x%08x ]\n", (int)cpu->pc, iword);
1470 arm_exception(cpu, ARM_EXCEPTION_UND);
1471 /* exit(1); */
1472 }
1473
1474
1475 /*****************************************************************************/
1476
1477
1478 #include "tmp_arm_tail.c"
1479

  ViewVC Help
Powered by ViewVC 1.1.26