/[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 24 - (hide annotations)
Mon Oct 8 16:19:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 40668 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1256 2006/06/23 20:43:44 debug Exp $
20060219	Various minor updates. Removing the old MIPS16 skeleton code,
		because it will need to be rewritten for dyntrans anyway.
20060220-22	Removing the non-working dyntrans backend support.
		Continuing on the 64-bit dyntrans virtual memory generalization.
20060223	More work on the 64-bit vm generalization.
20060225	Beginning on MIPS dyntrans load/store instructions.
		Minor PPC updates (64-bit load/store, etc).
		Fixes for the variable-instruction-length framework, some
		minor AVR updates (a simple Hello World program works!).
		Beginning on a skeleton for automatically generating documen-
		tation (for devices etc.).
20060226	PPC updates (adding some more 64-bit instructions, etc).
		AVR updates (more instructions).
		FINALLY found and fixed the zs bug, making NetBSD/macppc
		accept the serial console.
20060301	Adding more AVR instructions.
20060304	Continuing on AVR-related stuff. Beginning on a framework for
		cycle-accurate device emulation. Adding an experimental "PAL
		TV" device (just a dummy so far).
20060305	Adding more AVR instructions.
		Adding a dummy epcom serial controller (for TS7200 emulation).
20060310	Removing the emul() command from configuration files, so only
		net() and machine() are supported.
		Minor progress on the MIPS dyntrans rewrite.
20060311	Continuing on the MIPS dyntrans rewrite (adding more
		instructions, etc).
20060315	Adding more instructions (sllv, srav, srlv, bgtz[l], blez[l],
		beql, bnel, slti[u], various loads and stores).
20060316	Removing the ALWAYS_SIGNEXTEND_32 option, since it was rarely
		used.
		Adding more MIPS dyntrans instructions, and fixing bugs.
20060318	Implementing fast loads/stores for MIPS dyntrans (big/little
		endian, 32-bit and 64-bit modes).
20060320	Making MIPS dyntrans the default configure option; use
		"--enable-oldmips" to use the old bintrans system.
		Adding MIPS dyntrans dmult[u]; minor updates.
20060322	Continuing... adding some more instructions.
		Adding a simple skeleton for demangling C++ "_ZN" symbols.
20060323	Moving src/debugger.c into a new directory (src/debugger/).
20060324	Fixing the hack used to load PPC ELFs (useful for relocated
		Linux/ppc kernels), and adding a dummy G3 machine mode.
20060325-26	Beginning to experiment with GDB remote serial protocol
		connections; adding a -G command line option for selecting
		which TCP port to listen to.
20060330	Beginning a major cleanup to replace things like "0x%016llx"
		with more correct "0x%016"PRIx64, etc.
		Continuing on the GDB remote serial protocol support.
20060331	More cleanup, and some minor GDB remote progress.
20060402	Adding a hack to the configure script, to allow compilation
		on systems that lack PRIx64 etc.
20060406	Removing the temporary FreeBSD/arm hack in dev_ns16550.c and
		replacing it with a better fix from Olivier Houchard.
20060407	A remote debugger (gdb or ddd) can now start and stop the
		emulator using the GDB remote serial protocol, and registers
		and memory can be read. MIPS only for now.
20060408	More GDB progress: single-stepping also works, and also adding
		support for ARM, PowerPC, and Alpha targets.
		Continuing on the delay-slot-across-page-boundary issue.
20060412	Minor update: beginning to add support for the SPARC target
		to the remote GDB functionality.
20060414	Various MIPS updates: adding more instructions for dyntrans
		(eret, add), and making some exceptions work. Fixing a bug
		in dmult[u].
		Implementing the first SPARC instructions (sethi, or).
20060415	Adding "magic trap" instructions so that PROM calls can be
		software emulated in MIPS dyntrans.
		Adding more MIPS dyntrans instructions (ddiv, dadd) and
		fixing another bug in dmult.
20060416	More MIPS dyntrans progress: adding [d]addi, movn, movz, dsllv,
		rfi, an ugly hack for supporting R2000/R3000 style faked caches,
		preliminary interrupt support, and various other updates and
		bugfixes.
20060417	Adding more SPARC instructions (add, sub, sll[x], sra[x],
		srl[x]), and useful SPARC header definitions.
		Adding the first (trivial) x86/AMD64 dyntrans instructions (nop,
		cli/sti, stc/clc, std/cld, simple mov, inc ax). Various other
		x86 updates related to variable instruction length stuff.
		Adding unaligned loads/stores to the MIPS dyntrans mode (but
		still using the pre-dyntrans (slow) imlementation).
20060419	Fixing a MIPS dyntrans exception-in-delay-slot bug.
		Removing the old "show opcode statistics" functionality, since
		it wasn't really useful and isn't implemented for dyntrans.
		Single-stepping (or running with instruction trace) now looks
		ok with dyntrans with delay-slot architectures.
20060420	Minor hacks (removing the -B command line option when compiled
		for non-bintrans, and some other very minor updates).
		Adding (slow) MIPS dyntrans load-linked/store-conditional.
20060422	Applying fixes for bugs discovered by Nils Weller's nwcc
		(static DEC memmap => now per machine, and adding an extern
		keyword in cpu_arm_instr.c).
		Finally found one of the MIPS dyntrans bugs that I've been
		looking for (copy/paste spelling error BIG vs LITTLE endian in
		cpu_mips_instr_loadstore.c for 16-bit fast stores).
		FINALLY found the major MIPS dyntrans bug: slti vs sltiu
		signed/unsigned code in cpu_mips_instr.c. :-)
		Adding more MIPS dyntrans instructions (lwc1, swc1, bgezal[l],
		ctc1, tlt[u], tge[u], tne, beginning on rdhwr).
		NetBSD/hpcmips can now reach userland when using dyntrans :-)
		Adding some more x86 dyntrans instructions.
		Finally removed the old Alpha-specific virtual memory code,
		and replaced it with the generic 64-bit version.
		Beginning to add disassembly support for SPECIAL3 MIPS opcodes.
20060423	Continuing on the delay-slot-across-page-boundary issue;
		adding an end_of_page2 ic slot (like I had planned before, but
		had removed for some reason).
		Adding a quick-and-dirty fallback to legacy coprocessor 1
		code (i.e. skipping dyntrans implementation for now).
		NetBSD/hpcmips and NetBSD/pmax (when running on an emulated
		R4400) can now be installed and run. :-)  (Many bugs left
		to fix, though.)
		Adding more MIPS dyntrans instructions: madd[u], msub[u].
		Cleaning up the SPECIAL2 vs R5900/TX79/C790 "MMI" opcode
		maps somewhat (disassembly and dyntrans instruction decoding).
20060424	Adding an isa_revision field to mips_cpu_types.h, and making
		sure that SPECIAL3 opcodes cause Reserved Instruction
		exceptions on MIPS32/64 revisions lower than 2.
		Adding the SPARC 'ba', 'call', 'jmpl/retl', 'and', and 'xor'
		instructions.
20060425	Removing the -m command line option ("run at most x 
		instructions") and -T ("single_step_on_bad_addr"), because
		they never worked correctly with dyntrans anyway.
		Freshening up the man page.
20060428	Adding more MIPS dyntrans instructions: bltzal[l], idle.
		Enabling MIPS dyntrans compare interrupts.
20060429	FINALLY found the weird dyntrans bug, causing NetBSD etc. to
		behave strangely: some floating point code (conditional
		coprocessor branches) could not be reused from the old
		non-dyntrans code. The "quick-and-dirty fallback" only appeared
		to work. Fixing by implementing bc1* for MIPS dyntrans.
		More MIPS instructions: [d]sub, sdc1, ldc1, dmtc1, dmfc1, cfc0.
		Freshening up MIPS floating point disassembly appearance.
20060430	Continuing on C790/R5900/TX79 disassembly; implementing 128-bit
		"por" and "pextlw".
20060504	Disabling -u (userland emulation) unless compiled as unstable
		development version.
		Beginning on freshening up the testmachine include files,
		to make it easier to reuse those files (placing them in
		src/include/testmachine/), and beginning on a set of "demos"
		or "tutorials" for the testmachine functionality.
		Minor updates to the MIPS GDB remote protocol stub.
		Refreshing doc/experiments.html and gdb_remote.html.
		Enabling Alpha emulation in the stable release configuration,
		even though no guest OSes for Alpha can run yet.
20060505	Adding a generic 'settings' object, which will contain
		references to settable variables (which will later be possible
		to access using the debugger).
20060506	Updating dev_disk and corresponding demo/documentation (and
		switching from SCSI to IDE disk types, so it actually works
		with current test machines :-).
20060510	Adding a -D_LARGEFILE_SOURCE hack for 64-bit Linux hosts,
		so that fseeko() doesn't give a warning.
		Updating the section about how dyntrans works (the "runnable
		IR") in doc/intro.html.
		Instruction updates (some x64=1 checks, some more R5900
		dyntrans stuff: better mul/mult separation from MIPS32/64,
		adding ei and di).
		Updating MIPS cpuregs.h to a newer one (from NetBSD).
		Adding more MIPS dyntrans instructions: deret, ehb.
20060514	Adding disassembly and beginning implementation of SPARC wr
		and wrpr instructions.
20060515	Adding a SUN SPARC machine mode, with dummy SS20 and Ultra1
		machines. Adding the 32-bit "rd psr" instruction.
20060517	Disassembly support for the general SPARC rd instruction.
		Partial implementation of the cmp (subcc) instruction.
		Some other minor updates (making sure that R5900 processors
		start up with the EIE bit enabled, otherwise Linux/playstation2
		receives no interrupts).
20060519	Minor MIPS updates/cleanups.
20060521	Moving the MeshCube machine into evbmips; this seems to work
		reasonably well with a snapshot of a NetBSD MeshCube kernel.
		Cleanup/fix of MIPS config0 register initialization.
20060529	Minor MIPS fixes, including a sign-extension fix to the
		unaligned load/store code, which makes NetBSD/pmax on R3000
		work better with dyntrans. (Ultrix and Linux/DECstation still
		don't work, though.)
20060530	Minor updates to the Alpha machine mode: adding an AlphaBook
		mode, an LCA bus (forwarding accesses to an ISA bus), etc.
20060531	Applying a bugfix for the MIPS dyntrans sc[d] instruction from
		Ondrej Palkovsky. (Many thanks.)
20060601	Minifix to allow ARM immediate msr instruction to not give
		an error for some valid values.
		More Alpha updates.
20060602	Some minor Alpha updates.
20060603	Adding the Alpha cmpbge instruction. NetBSD/alpha prints its
		first boot messages :-) on an emulated Alphabook 1.
20060612	Minor updates; adding a dev_ether.h include file for the
		testmachine ether device. Continuing the hunt for the dyntrans
		bug which makes Linux and Ultrix on DECstation behave
		strangely... FINALLY found it! It seems to be related to
		invalidation of the translation cache, on tlbw{r,i}. There
		also seems to be some remaining interrupt-related problems.
20060614	Correcting the implementation of ldc1/sdc1 for MIPS dyntrans
		(so that it uses 16 32-bit registers if the FR bit in the
		status register is not set).
20060616	REMOVING BINTRANS COMPLETELY!
		Removing the old MIPS interpretation mode.
		Removing the MFHILO_DELAY and instruction delay stuff, because
		they wouldn't work with dyntrans anyway.
20060617	Some documentation updates (adding "NetBSD-archive" to some
		URLs, and new Debian/DECstation installation screenshots).
		Removing the "tracenull" and "enable-caches" configure options.
		Improving MIPS dyntrans performance somewhat (only invalidate
		translations if necessary, on writes to the entryhi register,
		instead of doing it for all cop0 writes).
20060618	More cleanup after the removal of the old MIPS emulation.
		Trying to fix the MIPS dyntrans performance bugs/bottlenecks;
		only semi-successful so far (for R3000).
20060620	Minor update to allow clean compilation again on Tru64/Alpha.
20060622	MIPS cleanup and fixes (removing the pc_last stuff, which
		doesn't make sense with dyntrans anyway, and fixing a cross-
		page-delay-slot-with-exception case in end_of_page).
		Removing the old max_random_cycles_per_chunk stuff, and the
		concept of cycles vs instructions for MIPS emulation.
		FINALLY found and fixed the bug which caused NetBSD/pmax
		clocks to behave strangely (it was a load to the zero register,
		which was treated as a NOP; now it is treated as a load to a
		dummy scratch register).
20060623	Increasing the dyntrans chunk size back to
		N_SAFE_DYNTRANS_LIMIT, instead of N_SAFE_DYNTRANS_LIMIT/2.
		Preparing for a quick release, even though there are known
		bugs, and performance for non-R3000 MIPS emulation is very
		poor. :-/
		Reverting to half the dyntrans chunk size again, because
		NetBSD/cats seemed less stable with full size chunks. :(
		NetBSD/sgimips 3.0 can now run :-)  (With release 0.3.8, only
		NetBSD/sgimips 2.1 worked, not 3.0.)

==============  RELEASE 0.4.0  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26