/[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

Annotation of /trunk/src/cpus/cpu_arm.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 20 - (hide 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 dpavlin 14 /*
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 dpavlin 20 * $Id: cpu_arm.c,v 1.44 2005/11/19 18:53:07 debug Exp $
29 dpavlin 14 *
30     * ARM CPU emulation.
31     *
32 dpavlin 20 *
33 dpavlin 14 * 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 dpavlin 20 static int arm_exception_to_mode[N_ARM_EXCEPTIONS] = ARM_EXCEPTION_TO_MODE;
64    
65 dpavlin 18 /* For quick_pc_to_pointers(): */
66     #include "arm_quick_pc_to_pointers.h"
67 dpavlin 14
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 dpavlin 18 cpu->invalidate_translation_caches =
96     arm_invalidate_translation_caches;
97 dpavlin 14 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 dpavlin 18 cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
113     cpu->cd.arm.control |= ARM_CONTROL_R;
114 dpavlin 14 }
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 dpavlin 20 cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
144    
145 dpavlin 14 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 dpavlin 18 cpu->translate_address = arm_translate_address_mmu;
169 dpavlin 14 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 dpavlin 18
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 dpavlin 14 /*
196 dpavlin 18 * 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 dpavlin 14 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 dpavlin 18 * 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 dpavlin 14 * 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 dpavlin 20 cpu->cd.arm.cpsr &= 0x0fffffff;
328     cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
329    
330 dpavlin 14 if (gprs) {
331     symbol = get_symbol_name(&cpu->machine->symbol_context,
332 dpavlin 20 cpu->pc, &offset);
333 dpavlin 14 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 dpavlin 20 debug(" pc = 0x%07x", (int)(cpu->pc & 0x03ffffff));
343 dpavlin 14 else
344 dpavlin 20 debug(" pc = 0x%08x", (int)cpu->pc);
345 dpavlin 14
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 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
479     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
480 dpavlin 14 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 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
485     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
486 dpavlin 14 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 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
491     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
492 dpavlin 14 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 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
497     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
498 dpavlin 14 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 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
526     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
527 dpavlin 14 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 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
532     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
533 dpavlin 14 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 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
538     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
539 dpavlin 14 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 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
544     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
545 dpavlin 14 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 dpavlin 18 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 dpavlin 14
599     switch (exception_nr) {
600     case ARM_EXCEPTION_RESET:
601     cpu->running = 0;
602 dpavlin 18 fatal("ARM RESET: TODO");
603 dpavlin 14 exit(1);
604 dpavlin 18 case ARM_EXCEPTION_DATA_ABT:
605 dpavlin 14 retaddr += 4;
606     break;
607     }
608    
609 dpavlin 18 retaddr += 4;
610 dpavlin 14
611     arm_save_register_bank(cpu);
612    
613 dpavlin 20 cpu->cd.arm.cpsr &= 0x0fffffff;
614     cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
615    
616 dpavlin 14 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 dpavlin 20 /*
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 dpavlin 14 newmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
650 dpavlin 20 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 dpavlin 14 }
655 dpavlin 20 #if 0
656     if (oldmode==0x10 && newmode ==0x17 && cpu->pc == 0x1644f0)
657     single_step = 1;
658     /* 00008554 */
659     #endif
660 dpavlin 14 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 dpavlin 20 /*
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 dpavlin 14 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 dpavlin 18 quick_pc_to_pointers(cpu);
680 dpavlin 14 }
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 dpavlin 20 /* fatal("arm_cpu_interrupt(): 0x%x\n", (int)irq_nr); */
694 dpavlin 14 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 dpavlin 20 debug("%s,%s,", arm_regname[r12], arm_regname[r16]);
814     debug("%s,%s\n", arm_regname[iw&15], arm_regname[r8]);
815 dpavlin 14 break;
816     }
817    
818     /*
819 dpavlin 20 * 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 dpavlin 14 * 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 dpavlin 20 * 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 dpavlin 14 * xxxx000P U1WLnnnn ddddHHHH 1SH1LLLL load/store rd,imm(rn)
945     */
946     if ((iw & 0x0e000090) == 0x00000090) {
947 dpavlin 18 char *op = "st";
948 dpavlin 14 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 dpavlin 18 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 dpavlin 14 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 dpavlin 20 addr = cpu->pc + 8;
1165 dpavlin 14 }
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 dpavlin 20 /*
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 dpavlin 14 /* 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 dpavlin 20 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 dpavlin 14 }
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 dpavlin 20 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 dpavlin 14 }
1326    
1327    
1328     /*****************************************************************************/
1329    
1330    
1331     #include "tmp_arm_tail.c"
1332    

  ViewVC Help
Powered by ViewVC 1.1.26