/[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 28 - (hide annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 40685 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26