/[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 20 - (show annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 36382 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26