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

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


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

  ViewVC Help
Powered by ViewVC 1.1.26