/[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 22 - (show annotations)
Mon Oct 8 16:19:37 2007 UTC (13 years, 1 month ago) by dpavlin
File MIME type: text/plain
File size: 38518 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1121 2006/02/18 21:03:08 debug Exp $
20051126	Cobalt and PReP now work with the 21143 NIC.
		Continuing on Alpha dyntrans things.
		Fixing some more left-shift-by-24 to unsigned.
20051127	Working on OpenFirmware emulation; major cleanup/redesign.
		Progress on MacPPC emulation: NetBSD detects two CPUs (when
		running with -n 2), framebuffer output (for text) works.
		Adding quick-hack Bandit PCI controller and "gc" interrupt
		controller for MacPPC.
20051128	Changing from a Bandit to a Uni-North controller for macppc.
		Continuing on OpenFirmware and MacPPC emulation in general
		(obio controller, and wdc attached to the obio seems to work).
20051129	More work on MacPPC emulation (adding a dummy ADB controller).
		Continuing the PCI bus cleanup (endianness and tag composition)
		and rewriting all PCI controllers' access functions.
20051130	Various minor PPC dyntrans optimizations.
		Manually inlining some parts of the framebuffer redraw routine.
		Slowly beginning the conversion of the old MIPS emulation into
		dyntrans (but this will take quite some time to get right).
		Generalizing quick_pc_to_pointers.
20051201	Documentation update (David Muse has made available a kernel
		which simplifies Debian/DECstation installation).
		Continuing on the ADB bus controller.
20051202	Beginning a rewrite of the Zilog serial controller (dev_zs).
20051203	Continuing on the zs rewrite (now called dev_z8530); conversion
		to devinit style.
		Reworking some of the input-only vs output-only vs input-output
		details of src/console.c, better warning messages, and adding
		a debug dump.
		Removing the concept of "device state"; it wasn't really used.
		Changing some debug output (-vv should now be used to show all
		details about devices and busses; not shown during normal
		startup anymore).
		Beginning on some SPARC instruction disassembly support.
20051204	Minor PPC updates (WALNUT skeleton stuff).
		Continuing on the MIPS dyntrans rewrite.
		More progress on the ADB controller (a keyboard is "detected"
		by NetBSD and OpenBSD).
		Downgrading OpenBSD/arc as a guest OS from "working" to
		"almost working" in the documentation.
		Progress on Algor emulation ("v3" PCI controller).
20051205	Minor updates.
20051207	Sorting devices according to address; this reduces complexity
		of device lookups from O(n) to O(log n) in memory_rw (but no
		real performance increase (yet) in experiments).
20051210	Beginning the work on native dyntrans backends (by making a
		simple skeleton; so far only for Alpha hosts).
20051211	Some very minor SPARC updates.
20051215	Fixing a bug in the MIPS mul (note: not mult) instruction,
		so it also works with non-64-bit emulation. (Thanks to Alec
		Voropay for noticing the problem.)
20051216	More work on the fake/empty/simple/skeleton/whatever backend;
		performance doesn't increase, so this isn't really worth it,
		but it was probably worth it to prepare for a real backend
		later.
20051219	More instr call statistics gathering and analysis stuff.
20051220	Another fix for MIPS 'mul'. Also converting mul and {d,}cl{o,z}
		to dyntrans.
		memory_ppc.c syntax error fix (noticed by Peter Valchev).
		Beginning to move out machines from src/machine.c into
		individual files in src/machines (in a way similar to the
		autodev system for devices).
20051222	Updating the documentation regarding NetBSD/pmax 3.0.
20051223	- " - NetBSD/cats 3.0.
20051225	- " - NetBSD/hpcmips 3.0.
20051226	Continuing on the machine registry redesign.
		Adding support for ARM rrx (33-bit rotate).
		Fixing some signed/unsigned issues (exposed by gcc -W).
20051227	Fixing the bug which prevented a NetBSD/prep 3.0 install kernel
		from starting (triggered when an mtmsr was the last instruction
		on a page). Unfortunately not enough to get the kernel to run
		as well as the 2.1 kernels did.
20051230	Some dyntrans refactoring.
20051231	Continuing on the machine registry redesign.
20060101-10	Continuing... moving more machines. Moving MD interrupt stuff
		from machine.c into a new src/machines/interrupts.c.
20060114	Adding various mvmeppc machine skeletons.
20060115	Continuing on mvme* stuff. NetBSD/mvmeppc prints boot messages
		(for MVME1600) and reaches the root device prompt, but no
		specific hardware devices are emulated yet.
20060116	Minor updates to the mvme1600 emulation mode; the Eagle PCI bus
		seems to work without much modification, and a 21143 can be
		detected, interrupts might work (but untested so far).
		Adding a fake MK48Txx (mkclock) device, for NetBSD/mvmeppc.
20060121	Adding an aux control register for ARM. (A BIG thank you to
		Olivier Houchard for tracking down this bug.)
20060122	Adding more ARM instructions (smulXY), and dev_iq80321_7seg.
20060124	Adding disassembly of more ARM instructions (mia*, mra/mar),
		and some semi-bogus XScale and i80321 registers.
20060201-02	Various minor updates. Moving the last machines out of
		machine.c.
20060204	Adding a -c command line option, for running debugger commands
		before the simulation starts, but after all files have been
		loaded.
		Minor iq80321-related updates.
20060209	Minor hacks (DEVINIT macro, etc).
		Preparing for the generalization of the 64-bit dyntrans address
		translation subsystem.
20060216	Adding ARM ldrd (double-register load).
20060217	Continuing on various ARM-related stuff.
20060218	More progress on the ATA/wdc emulation for NetBSD/iq80321.
		NetBSD/evbarm can now be installed :-)  Updating the docs, etc.
		Continuing on Algor emulation.

==============  RELEASE 0.3.8  ==============


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.54 2006/02/09 20:02:58 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_address = arm_translate_address;
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_address = arm_translate_address_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_interrupt():
718 *
719 * 0..31 are used as footbridge interrupt numbers, 32..47 = ISA,
720 * 64 is used as a "re-assert" signal to cpu->machine->md_interrupt().
721 *
722 * TODO: don't hardcode to footbridge!
723 */
724 int arm_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
725 {
726 /* fatal("arm_cpu_interrupt(): 0x%x\n", (int)irq_nr); */
727 if (irq_nr <= 64) {
728 if (cpu->machine->md_interrupt != NULL)
729 cpu->machine->md_interrupt(cpu->machine,
730 cpu, irq_nr, 1);
731 else
732 fatal("arm_cpu_interrupt(): irq_nr=%i md_interrupt =="
733 " NULL\n", (int)irq_nr);
734 } else {
735 /* Assert ARM IRQs: */
736 cpu->cd.arm.irq_asserted = 1;
737 }
738
739 return 1;
740 }
741
742
743 /*
744 * arm_cpu_interrupt_ack():
745 */
746 int arm_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
747 {
748 if (irq_nr <= 64) {
749 if (cpu->machine->md_interrupt != NULL)
750 cpu->machine->md_interrupt(cpu->machine,
751 cpu, irq_nr, 0);
752 } else {
753 /* De-assert ARM IRQs: */
754 cpu->cd.arm.irq_asserted = 0;
755 }
756
757 return 1;
758 }
759
760
761 /*
762 * arm_cpu_disassemble_instr():
763 *
764 * Convert an instruction word into human readable format, for instruction
765 * tracing.
766 *
767 * If running is 1, cpu->pc should be the address of the instruction.
768 *
769 * If running is 0, things that depend on the runtime environment (eg.
770 * register contents) will not be shown, and addr will be used instead of
771 * cpu->pc for relative addresses.
772 */
773 int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
774 int running, uint64_t dumpaddr, int bintrans)
775 {
776 uint32_t iw, tmp;
777 int main_opcode, secondary_opcode, s_bit, r16, r12, r8;
778 int i, n, p_bit, u_bit, b_bit, w_bit, l_bit;
779 char *symbol, *condition;
780 uint64_t offset;
781
782 if (running)
783 dumpaddr = cpu->pc;
784
785 symbol = get_symbol_name(&cpu->machine->symbol_context,
786 dumpaddr, &offset);
787 if (symbol != NULL && offset == 0)
788 debug("<%s>\n", symbol);
789
790 if (cpu->machine->ncpus > 1 && running)
791 debug("cpu%i:\t", cpu->cpu_id);
792
793 debug("%08x: ", (int)dumpaddr);
794
795 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
796 iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
797 else
798 iw = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
799 debug("%08x\t", (int)iw);
800
801 condition = arm_condition_string[iw >> 28];
802 main_opcode = (iw >> 24) & 15;
803 secondary_opcode = (iw >> 21) & 15;
804 u_bit = (iw >> 23) & 1;
805 b_bit = (iw >> 22) & 1;
806 w_bit = (iw >> 21) & 1;
807 s_bit = l_bit = (iw >> 20) & 1;
808 r16 = (iw >> 16) & 15;
809 r12 = (iw >> 12) & 15;
810 r8 = (iw >> 8) & 15;
811
812 switch (main_opcode) {
813 case 0x0:
814 case 0x1:
815 case 0x2:
816 case 0x3:
817 /*
818 * Special cases first:
819 */
820
821 /*
822 * Multiplication:
823 * xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd, Rm, Rs [,Rn])
824 */
825 if ((iw & 0x0fc000f0) == 0x00000090) {
826 int a_bit = (iw >> 21) & 1;
827 debug("%s%s%s\t", a_bit? "mla" : "mul",
828 condition, s_bit? "s" : "");
829 debug("%s,", arm_regname[r16]);
830 debug("%s,", arm_regname[iw & 15]);
831 debug("%s", arm_regname[r8]);
832 if (a_bit)
833 debug(",%s", arm_regname[r12]);
834 debug("\n");
835 break;
836 }
837
838 /*
839 * Long multiplication:
840 * xxxx0000 1UAShhhh llllssss 1001mmmm (Rl,Rh,Rm,Rs)
841 */
842 if ((iw & 0x0f8000f0) == 0x00800090) {
843 int u_bit = (iw >> 22) & 1;
844 int a_bit = (iw >> 21) & 1;
845 debug("%s%sl%s%s\t", u_bit? "s" : "u",
846 a_bit? "mla" : "mul", condition, s_bit? "s" : "");
847 debug("%s,%s,", arm_regname[r12], arm_regname[r16]);
848 debug("%s,%s\n", arm_regname[iw&15], arm_regname[r8]);
849 break;
850 }
851
852 /*
853 * xxxx0001 0000nnnn dddd0000 0101mmmm qadd Rd,Rm,Rn
854 * xxxx0001 0010nnnn dddd0000 0101mmmm qsub Rd,Rm,Rn
855 * xxxx0001 0100nnnn dddd0000 0101mmmm qdadd Rd,Rm,Rn
856 * xxxx0001 0110nnnn dddd0000 0101mmmm qdsub Rd,Rm,Rn
857 */
858 if ((iw & 0x0f900ff0) == 0x01000050) {
859 debug("q%s%s%s\t", iw & 0x400000? "d" : "",
860 iw & 0x200000? "sub" : "add", condition);
861 debug("%s,%s,%s\n", arm_regname[r12],
862 arm_regname[iw&15], arm_regname[r16]);
863 break;
864 }
865
866 /*
867 * xxxx0001 0010.... ........ 00L1mmmm bx/blx rm
868 */
869 if ((iw & 0x0ff000d0) == 0x01200010) {
870 int l_bit = iw & 0x20;
871 debug("b%sx%s\t%s\n", l_bit? "l" : "", condition,
872 arm_regname[iw & 15]);
873 break;
874 }
875
876 /*
877 * xxxx0001 0s10aaaa 11110000 0000mmmm MSR Regform
878 * xxxx0011 0s10aaaa 1111rrrr bbbbbbbb MSR Immform
879 * xxxx0001 0s001111 dddd0000 00000000 MRS
880 */
881 if ((iw & 0x0fb0fff0) == 0x0120f000 ||
882 (iw & 0x0fb0f000) == 0x0320f000) {
883 int a = (iw >> 16) & 15;
884 debug("msr%s\t%s", condition, (iw&0x400000)? "S":"C");
885 debug("PSR_");
886 switch (a) {
887 case 1: debug("ctl"); break;
888 case 8: debug("flg"); break;
889 case 9: debug("all"); break;
890 default:debug(" UNIMPLEMENTED (a=%i)", a);
891 }
892 if (iw & 0x02000000) {
893 int r = (iw >> 7) & 30;
894 uint32_t b = iw & 0xff;
895 while (r-- > 0)
896 b = (b >> 1) | ((b & 1) << 31);
897 debug(",#0x%x\n", b);
898 } else
899 debug(",%s\n", arm_regname[iw & 15]);
900 break;
901 }
902 if ((iw & 0x0fbf0fff) == 0x010f0000) {
903 debug("mrs%s\t", condition);
904 debug("%s,%sPSR\n", arm_regname[r12],
905 (iw&0x400000)? "S":"C");
906 break;
907 }
908
909 /*
910 * xxxx0001 0B00nnnn dddd0000 1001mmmm SWP Rd,Rm,[Rn]
911 */
912 if ((iw & 0x0fb00ff0) == 0x01000090) {
913 debug("swp%s%s\t", condition, (iw&0x400000)? "b":"");
914 debug("%s,%s,[%s]\n", arm_regname[r12],
915 arm_regname[iw & 15], arm_regname[r16]);
916 break;
917 }
918
919 /*
920 * xxxx0001 01101111 dddd1111 0001mmmm CLZ Rd,Rm
921 */
922 if ((iw & 0x0fff0ff0) == 0x016f0f10) {
923 debug("clz%s\t", condition);
924 debug("%s,%s\n", arm_regname[r12], arm_regname[iw&15]);
925 break;
926 }
927
928 /*
929 * xxxx0001 0000dddd nnnnssss 1yx0mmmm SMLAxy Rd,Rm,Rs,Rn
930 * xxxx0001 0100dddd DDDDssss 1yx0mmmm SMLALxy RdL,RdH,Rm,Rs
931 * xxxx0001 0010dddd nnnnssss 1y00mmmm SMLAWy Rd,Rm,Rs,Rn
932 * xxxx0001 0110dddd 0000ssss 1yx0mmmm SMULxy Rd,Rm,Rs
933 * xxxx0001 0010dddd 0000ssss 1y10mmmm SMULWy Rd,Rm,Rs
934 */
935 if ((iw & 0x0ff00090) == 0x01000080) {
936 debug("smla%s%s%s\t",
937 iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
938 condition);
939 debug("%s,%s,%s,%s\n", arm_regname[r16],
940 arm_regname[iw&15], arm_regname[r8],
941 arm_regname[r12]);
942 break;
943 }
944 if ((iw & 0x0ff00090) == 0x01400080) {
945 debug("smlal%s%s%s\t",
946 iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
947 condition);
948 debug("%s,%s,%s,%s\n", arm_regname[r12],
949 arm_regname[r16], arm_regname[iw&15],
950 arm_regname[r8]);
951 break;
952 }
953 if ((iw & 0x0ff000b0) == 0x01200080) {
954 debug("smlaw%s%s\t", iw & 0x40? "t" : "b",
955 condition);
956 debug("%s,%s,%s,%s\n", arm_regname[r16],
957 arm_regname[iw&15], arm_regname[r8],
958 arm_regname[r12]);
959 break;
960 }
961 if ((iw & 0x0ff0f090) == 0x01600080) {
962 debug("smul%s%s%s\t",
963 iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
964 condition);
965 debug("%s,%s,%s\n", arm_regname[r16],
966 arm_regname[iw&15], arm_regname[r8]);
967 break;
968 }
969 if ((iw & 0x0ff0f0b0) == 0x012000a0) {
970 debug("smulw%s%s\t", iw & 0x40? "t" : "b",
971 condition);
972 debug("%s,%s,%s\n", arm_regname[r16],
973 arm_regname[iw&15], arm_regname[r8]);
974 break;
975 }
976
977 /*
978 * xxxx000P U1WLnnnn ddddHHHH 1SH1LLLL load/store rd,imm(rn)
979 */
980 if ((iw & 0x0e000090) == 0x00000090) {
981 char *op = "st";
982 int imm = ((iw >> 4) & 0xf0) | (iw & 0xf);
983 int regform = !(iw & 0x00400000);
984 p_bit = main_opcode & 1;
985 /*
986 * TODO: detect some illegal variants:
987 * signed store, or unsigned byte load/store
988 */
989 if (!l_bit && (iw & 0xd0) == 0xd0 && (r12 & 1)) {
990 debug("TODO: r12 odd, not load/store\n");
991 break;
992 }
993 /* Semi-generic case: */
994 if (iw & 0x00100000)
995 op = "ld";
996 if (!l_bit && (iw & 0xd0) == 0xd0)
997 op = iw & 0x20? "st" : "ld";
998 debug("%sr%s", op, condition);
999 if (!l_bit && (iw & 0xd0) == 0xd0) {
1000 debug("d"); /* Double-register */
1001 } else {
1002 if (iw & 0x40)
1003 debug("s"); /* signed */
1004 if (iw & 0x20)
1005 debug("h"); /* half-word */
1006 else
1007 debug("b"); /* byte */
1008 }
1009 debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
1010 if (p_bit) {
1011 /* Pre-index: */
1012 if (regform)
1013 debug(",%s%s", u_bit? "" : "-",
1014 arm_regname[iw & 15]);
1015 else {
1016 if (imm != 0)
1017 debug(",#%s%i", u_bit? "" : "-",
1018 imm);
1019 }
1020 debug("]%s\n", w_bit? "!" : "");
1021 } else {
1022 /* Post-index: */
1023 debug("],");
1024 if (regform)
1025 debug("%s%s\n", u_bit? "" : "-",
1026 arm_regname[iw & 15]);
1027 else
1028 debug("#%s%i\n", u_bit? "" : "-", imm);
1029 }
1030 break;
1031 }
1032
1033 /* Other special cases: */
1034 if (iw & 0x80 && !(main_opcode & 2) && iw & 0x10) {
1035 debug("UNIMPLEMENTED reg (c!=0), t odd\n");
1036 break;
1037 }
1038
1039 /*
1040 * Generic Data Processing Instructions:
1041 *
1042 * xxxx000a aaaSnnnn ddddcccc ctttmmmm Register form
1043 * xxxx001a aaaSnnnn ddddrrrr bbbbbbbb Immediate form
1044 */
1045
1046 debug("%s%s%s\t", arm_dpiname[secondary_opcode],
1047 condition, s_bit? "s" : "");
1048 if (arm_dpi_uses_d[secondary_opcode])
1049 debug("%s,", arm_regname[r12]);
1050 if (arm_dpi_uses_n[secondary_opcode])
1051 debug("%s,", arm_regname[r16]);
1052
1053 if (main_opcode & 2) {
1054 /* Immediate form: */
1055 int r = (iw >> 7) & 30;
1056 uint32_t b = iw & 0xff;
1057 while (r-- > 0)
1058 b = (b >> 1) | ((b & 1) << 31);
1059 if (b < 15)
1060 debug("#%i", b);
1061 else
1062 debug("#0x%x", b);
1063 } else {
1064 /* Register form: */
1065 int t = (iw >> 4) & 7;
1066 int c = (iw >> 7) & 31;
1067 debug("%s", arm_regname[iw & 15]);
1068 switch (t) {
1069 case 0: if (c != 0)
1070 debug(", lsl #%i", c);
1071 break;
1072 case 1: debug(", lsl %s", arm_regname[c >> 1]);
1073 break;
1074 case 2: debug(", lsr #%i", c? c : 32);
1075 break;
1076 case 3: debug(", lsr %s", arm_regname[c >> 1]);
1077 break;
1078 case 4: debug(", asr #%i", c? c : 32);
1079 break;
1080 case 5: debug(", asr %s", arm_regname[c >> 1]);
1081 break;
1082 case 6: if (c != 0)
1083 debug(", ror #%i", c);
1084 else
1085 debug(", rrx");
1086 break;
1087 case 7: debug(", ror %s", arm_regname[c >> 1]);
1088 break;
1089 }
1090
1091 /* mov pc,reg: */
1092 if (running && t == 0 && c == 0 && secondary_opcode
1093 == 0xd && r12 == ARM_PC && (iw&15)!=ARM_PC) {
1094 symbol = get_symbol_name(&cpu->machine->
1095 symbol_context, cpu->cd.arm.r[iw & 15],
1096 &offset);
1097 if (symbol != NULL)
1098 debug(" \t<%s>", symbol);
1099 }
1100 }
1101 debug("\n");
1102 break;
1103 case 0x4: /* Single Data Transfer */
1104 case 0x5:
1105 case 0x6:
1106 case 0x7:
1107 /* Special case first: */
1108 if ((iw & 0xfc70f000) == 0xf450f000) {
1109 /* Preload: */
1110 debug("pld\t[%s]\n", arm_regname[r16]);
1111 break;
1112 }
1113
1114 /*
1115 * xxxx010P UBWLnnnn ddddoooo oooooooo Immediate form
1116 * xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form
1117 */
1118 p_bit = main_opcode & 1;
1119 if (main_opcode >= 6 && iw & 0x10) {
1120 debug("TODO: single data transf. but 0x10\n");
1121 break;
1122 }
1123 debug("%s%s%s", l_bit? "ldr" : "str",
1124 condition, b_bit? "b" : "");
1125 if (!p_bit && w_bit)
1126 debug("t");
1127 debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
1128 if ((iw & 0x0e000000) == 0x04000000) {
1129 /* Immediate form: */
1130 uint32_t imm = iw & 0xfff;
1131 if (!p_bit)
1132 debug("]");
1133 if (imm != 0)
1134 debug(",#%s%i", u_bit? "" : "-", imm);
1135 if (p_bit)
1136 debug("]");
1137 } else if ((iw & 0x0e000010) == 0x06000000) {
1138 /* Register form: */
1139 if (!p_bit)
1140 debug("]");
1141 if ((iw & 0xfff) != 0)
1142 debug(",%s%s", u_bit? "" : "-",
1143 arm_regname[iw & 15]);
1144 if ((iw & 0xff0) != 0x000) {
1145 int c = (iw >> 7) & 31;
1146 int t = (iw >> 4) & 7;
1147 switch (t) {
1148 case 0: if (c != 0)
1149 debug(", lsl #%i", c);
1150 break;
1151 case 2: debug(", lsr #%i", c? c : 32);
1152 break;
1153 case 4: debug(", asr #%i", c? c : 32);
1154 break;
1155 case 6: if (c != 0)
1156 debug(", ror #%i", c);
1157 else
1158 debug(", rrx");
1159 break;
1160 }
1161 }
1162 if (p_bit)
1163 debug("]");
1164 } else {
1165 debug("UNKNOWN\n");
1166 break;
1167 }
1168 debug("%s", (p_bit && w_bit)? "!" : "");
1169 if ((iw & 0x0f000000) == 0x05000000 &&
1170 (r16 == ARM_PC || running)) {
1171 unsigned char tmpw[4];
1172 uint32_t imm = iw & 0xfff;
1173 uint32_t addr = (u_bit? imm : -imm);
1174 if (r16 == ARM_PC)
1175 addr += dumpaddr + 8;
1176 else
1177 addr += cpu->cd.arm.r[r16];
1178 symbol = get_symbol_name(&cpu->machine->symbol_context,
1179 addr, &offset);
1180 if (symbol != NULL)
1181 debug(" \t<%s", symbol);
1182 else
1183 debug(" \t<0x%08x", addr);
1184 if ((l_bit && cpu->memory_rw(cpu, cpu->mem, addr, tmpw,
1185 b_bit? 1 : sizeof(tmpw), MEM_READ, NO_EXCEPTIONS))
1186 || (!l_bit && running)) {
1187 if (l_bit) {
1188 if (cpu->byte_order ==
1189 EMUL_LITTLE_ENDIAN)
1190 addr = tmpw[0] +(tmpw[1] << 8) +
1191 (tmpw[2]<<16)+(tmpw[3]<<24);
1192 else
1193 addr = tmpw[3] + (tmpw[2]<<8) +
1194 (tmpw[1]<<16)+(tmpw[0]<<24);
1195 } else {
1196 tmpw[0] = addr = cpu->cd.arm.r[r12];
1197 if (r12 == ARM_PC)
1198 addr = cpu->pc + 8;
1199 }
1200 debug(": ");
1201 if (b_bit)
1202 debug("%i", tmpw[0]);
1203 else {
1204 symbol = get_symbol_name(&cpu->machine->
1205 symbol_context, addr, &offset);
1206 if (symbol != NULL)
1207 debug("%s", symbol);
1208 else if ((int32_t)addr > -256 &&
1209 (int32_t)addr < 256)
1210 debug("%i", addr);
1211 else
1212 debug("0x%x", addr);
1213 }
1214 }
1215 debug(">");
1216 }
1217 debug("\n");
1218 break;
1219 case 0x8: /* Block Data Transfer */
1220 case 0x9:
1221 /* xxxx100P USWLnnnn llllllll llllllll */
1222 p_bit = main_opcode & 1;
1223 s_bit = b_bit;
1224 debug("%s%s", l_bit? "ldm" : "stm", condition);
1225 switch (u_bit * 2 + p_bit) {
1226 case 0: debug("da"); break;
1227 case 1: debug("db"); break;
1228 case 2: debug("ia"); break;
1229 case 3: debug("ib"); break;
1230 }
1231 debug("\t%s", arm_regname[r16]);
1232 if (w_bit)
1233 debug("!");
1234 debug(",{");
1235 n = 0;
1236 for (i=0; i<16; i++)
1237 if ((iw >> i) & 1) {
1238 debug("%s%s", (n > 0)? ",":"", arm_regname[i]);
1239 n++;
1240 }
1241 debug("}");
1242 if (s_bit)
1243 debug("^");
1244 debug("\n");
1245 break;
1246 case 0xa: /* B: branch */
1247 case 0xb: /* BL: branch and link */
1248 debug("b%s%s\t", main_opcode == 0xa? "" : "l", condition);
1249 tmp = (iw & 0x00ffffff) << 2;
1250 if (tmp & 0x02000000)
1251 tmp |= 0xfc000000;
1252 tmp = (int32_t)(dumpaddr + tmp + 8);
1253 debug("0x%x", (int)tmp);
1254 symbol = get_symbol_name(&cpu->machine->symbol_context,
1255 tmp, &offset);
1256 if (symbol != NULL)
1257 debug(" \t<%s>", symbol);
1258 debug("\n");
1259 break;
1260 case 0xc: /* Coprocessor */
1261 case 0xd: /* LDC/STC */
1262 /*
1263 * xxxx1100 0100nnnn ddddcccc oooommmm MCRR c,op,Rd,Rn,CRm
1264 * xxxx1100 0101nnnn ddddcccc oooommmm MRRC c,op,Rd,Rn,CRm
1265 */
1266 if ((iw & 0x0fe00fff) == 0x0c400000) {
1267 debug("%s%s\t", iw & 0x100000? "mra" : "mar",
1268 condition);
1269 if (iw & 0x100000)
1270 debug("%s,%s,acc0\n",
1271 arm_regname[r12], arm_regname[r16]);
1272 else
1273 debug("acc0,%s,%s\n",
1274 arm_regname[r12], arm_regname[r16]);
1275 break;
1276 }
1277 if ((iw & 0x0fe00000) == 0x0c400000) {
1278 debug("%s%s\t", iw & 0x100000? "mrrc" : "mcrr",
1279 condition);
1280 debug("%i,%i,%s,%s,cr%i\n", r8, (iw >> 4) & 15,
1281 arm_regname[r12], arm_regname[r16], iw & 15);
1282 break;
1283 }
1284
1285 /* xxxx110P UNWLnnnn DDDDpppp oooooooo LDC/STC */
1286 debug("TODO: coprocessor LDC/STC\n");
1287 break;
1288 case 0xe: /* CDP (Coprocessor Op) */
1289 /* or MRC/MCR!
1290 * xxxx1110 oooonnnn ddddpppp qqq0mmmm CDP
1291 * xxxx1110 oooLNNNN ddddpppp qqq1MMMM MRC/MCR
1292 */
1293 if ((iw & 0x0ff00ff0) == 0x0e200010) {
1294 /* Special case: mia* DSP instructions */
1295 switch ((iw >> 16) & 0xf) {
1296 case 0: debug("mia"); break;
1297 case 8: debug("miaph"); break;
1298 case 12: debug("miaBB"); break;
1299 case 13: debug("miaTB"); break;
1300 case 14: debug("miaBT"); break;
1301 case 15: debug("miaTT"); break;
1302 default: debug("UNKNOWN mia vector instruction?");
1303 }
1304 debug("%s\t", condition);
1305 debug("acc%i,%s,%s\n", ((iw >> 5) & 7),
1306 arm_regname[iw & 15], arm_regname[r12]);
1307 break;
1308 }
1309 if (iw & 0x10) {
1310 debug("%s%s\t",
1311 (iw & 0x00100000)? "mrc" : "mcr", condition);
1312 debug("%i,%i,r%i,cr%i,cr%i,%i",
1313 (int)((iw >> 8) & 15), (int)((iw >>21) & 7),
1314 (int)((iw >>12) & 15), (int)((iw >>16) & 15),
1315 (int)((iw >> 0) & 15), (int)((iw >> 5) & 7));
1316 } else {
1317 debug("cdp%s\t", condition);
1318 debug("%i,%i,cr%i,cr%i,cr%i",
1319 (int)((iw >> 8) & 15),
1320 (int)((iw >>20) & 15),
1321 (int)((iw >>12) & 15),
1322 (int)((iw >>16) & 15),
1323 (int)((iw >> 0) & 15));
1324 if ((iw >> 5) & 7)
1325 debug(",0x%x", (int)((iw >> 5) & 7));
1326 }
1327 debug("\n");
1328 break;
1329 case 0xf: /* SWI */
1330 debug("swi%s\t", condition);
1331 debug("0x%x\n", (int)(iw & 0x00ffffff));
1332 break;
1333 default:debug("UNIMPLEMENTED\n");
1334 }
1335
1336 return sizeof(uint32_t);
1337 }
1338
1339
1340 /*****************************************************************************/
1341
1342
1343 /*
1344 * arm_mcr_mrc():
1345 *
1346 * Coprocessor register move.
1347 *
1348 * The program counter should be synched before calling this function (to
1349 * make debug output with the correct PC value possible).
1350 */
1351 void arm_mcr_mrc(struct cpu *cpu, uint32_t iword)
1352 {
1353 int opcode1 = (iword >> 21) & 7;
1354 int l_bit = (iword >> 20) & 1;
1355 int crn = (iword >> 16) & 15;
1356 int rd = (iword >> 12) & 15;
1357 int cp_num = (iword >> 8) & 15;
1358 int opcode2 = (iword >> 5) & 7;
1359 int crm = iword & 15;
1360
1361 if (cpu->cd.arm.coproc[cp_num] != NULL)
1362 cpu->cd.arm.coproc[cp_num](cpu, opcode1, opcode2, l_bit,
1363 crn, crm, rd);
1364 else {
1365 fatal("[ arm_mcr_mrc: pc=0x%08x, iword=0x%08x: "
1366 "cp_num=%i ]\n", (int)cpu->pc, iword, cp_num);
1367 arm_exception(cpu, ARM_EXCEPTION_UND);
1368 /* exit(1); */
1369 }
1370 }
1371
1372
1373 /*
1374 * arm_cdp():
1375 *
1376 * Coprocessor operations.
1377 *
1378 * The program counter should be synched before calling this function (to
1379 * make debug output with the correct PC value possible).
1380 */
1381 void arm_cdp(struct cpu *cpu, uint32_t iword)
1382 {
1383 fatal("[ arm_cdp: pc=0x%08x, iword=0x%08x ]\n", (int)cpu->pc, iword);
1384 arm_exception(cpu, ARM_EXCEPTION_UND);
1385 /* exit(1); */
1386 }
1387
1388
1389 /*****************************************************************************/
1390
1391
1392 #include "tmp_arm_tail.c"
1393

  ViewVC Help
Powered by ViewVC 1.1.26