/[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 38 - (show annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 38582 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1515 2007/04/14 05:39:46 debug Exp $
20070324	Adding a "--debug" option to the configure script, to disable
		optimizations in unstable development builds.
		Moving out SCSI-specific stuff from diskimage.c into a new
		diskimage_scsicmd.c.
		Applying Hĺvard Eidnes' patch for SCSICDROM_READ_DISKINFO and
		SCSICDROM_READ_TRACKINFO. (Not really tested yet.)
		Implementing disk image "overlays" (to allow simple roll-back
		to previous disk state). Adding a 'V' disk flag for this, and
		updating the man page and misc.html.
20070325	Stability fix to cpu_dyntrans.c, when multiple physical pages
		share the same initial table entry. (The ppp == NULL check
		should be physpage_ofs == 0.) Bug found by analysing GXemul
		against a version patched for Godson.
		Fixing a second occurance of the same problem (also in
		cpu_dyntrans.c).
		Fixing a MAJOR physical page leak in cpu_dyntrans.c; pages
		weren't _added_ to the set of translated pages, they _replaced_
		all previous pages. It's amazing that this bug has been able
		to live for this long. (Triggered when emulating >128MB RAM.)
20070326	Removing the GDB debugging stub support; it was too hackish
		and ugly.
20070328	Moving around some native code generation skeleton code.
20070329	The -lm check in the configure script now also checks for sin()
		in addition to sqrt(). (Thanks to Nigel Horne for noticing that
		sqrt was not enough on Fedora Core 6.) (Not verified yet.)
20070330	Fixing an indexing bug in dev_sh4.c, found by using gcc version
		4.3.0 20070323.
20070331	Some more experimentation with native code generation.
20070404	Attempting to fix some more SH4 SCIF interrupt bugs; rewriting
		the SH interrupt assertion/deassertion code somewhat.
20070410	Splitting src/file.c into separate files in src/file/.
		Cleanup: Removing the dummy TS7200, Walnut, PB1000, and
		Meshcube emulation modes, and dev_epcom and dev_au1x00.
		Removing the experimental CHIP8/RCA180x code; it wasn't really
		working much lately, anyway. It was fun while it lasted.
		Also removing the experimental Transputer CPU support.
20070412	Moving the section about how the dynamic translation system
		works from intro.html to a separate translation.html file.
		Minor SH fixes; attempting to get OpenBSD/landisk to run
		without randomly bugging out, but no success yet.
20070413	SH SCI (serial bit interface) should now work together with a
		(new) RS5C313 clock device (for Landisk emulation).
20070414	Moving Redhat/MIPS down from supported to experimental, in
		guestoses.html.
		Preparing for a new release; doing some regression testing etc.

==============  RELEASE 0.4.5  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26