/[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 38 - (hide annotations)
Mon Oct 8 16:21:53 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 38582 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1515 2007/04/14 05:39:46 debug Exp $
20070324	Adding a "--debug" option to the configure script, to disable
		optimizations in unstable development builds.
		Moving out SCSI-specific stuff from diskimage.c into a new
		diskimage_scsicmd.c.
		Applying Hĺvard Eidnes' patch for SCSICDROM_READ_DISKINFO and
		SCSICDROM_READ_TRACKINFO. (Not really tested yet.)
		Implementing disk image "overlays" (to allow simple roll-back
		to previous disk state). Adding a 'V' disk flag for this, and
		updating the man page and misc.html.
20070325	Stability fix to cpu_dyntrans.c, when multiple physical pages
		share the same initial table entry. (The ppp == NULL check
		should be physpage_ofs == 0.) Bug found by analysing GXemul
		against a version patched for Godson.
		Fixing a second occurance of the same problem (also in
		cpu_dyntrans.c).
		Fixing a MAJOR physical page leak in cpu_dyntrans.c; pages
		weren't _added_ to the set of translated pages, they _replaced_
		all previous pages. It's amazing that this bug has been able
		to live for this long. (Triggered when emulating >128MB RAM.)
20070326	Removing the GDB debugging stub support; it was too hackish
		and ugly.
20070328	Moving around some native code generation skeleton code.
20070329	The -lm check in the configure script now also checks for sin()
		in addition to sqrt(). (Thanks to Nigel Horne for noticing that
		sqrt was not enough on Fedora Core 6.) (Not verified yet.)
20070330	Fixing an indexing bug in dev_sh4.c, found by using gcc version
		4.3.0 20070323.
20070331	Some more experimentation with native code generation.
20070404	Attempting to fix some more SH4 SCIF interrupt bugs; rewriting
		the SH interrupt assertion/deassertion code somewhat.
20070410	Splitting src/file.c into separate files in src/file/.
		Cleanup: Removing the dummy TS7200, Walnut, PB1000, and
		Meshcube emulation modes, and dev_epcom and dev_au1x00.
		Removing the experimental CHIP8/RCA180x code; it wasn't really
		working much lately, anyway. It was fun while it lasted.
		Also removing the experimental Transputer CPU support.
20070412	Moving the section about how the dynamic translation system
		works from intro.html to a separate translation.html file.
		Minor SH fixes; attempting to get OpenBSD/landisk to run
		without randomly bugging out, but no success yet.
20070413	SH SCI (serial bit interface) should now work together with a
		(new) RS5C313 clock device (for Landisk emulation).
20070414	Moving Redhat/MIPS down from supported to experimental, in
		guestoses.html.
		Preparing for a new release; doing some regression testing etc.

==============  RELEASE 0.4.5  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26