/[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 18 - (hide annotations)
Mon Oct 8 16:19:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 33418 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1004 2005/10/27 14:01:10 debug Exp $
20051011        Passing -A as the default boot arg for CATS (works fine with
                OpenBSD/cats).
20051012	Fixing the VGA cursor offset bug, and speeding up framebuffer
		redraws if character cells contain the same thing as during
		the last redraw.
20051013	Adding a slow strd ARM instruction hack.
20051017	Minor updates: Adding a dummy i80321 Verde controller (for
		XScale emulation), fixing the disassembly of the ARM "ldrd"
		instruction, adding "support" for less-than-4KB pages for ARM
		(by not adding them to translation tables).
20051020	Continuing on some HPCarm stuff. A NetBSD/hpcarm kernel prints
		some boot messages on an emulated Jornada 720.
		Making dev_ram work better with dyntrans (speeds up some things
		quite a bit).
20051021	Automatically generating some of the most common ARM load/store
		multiple instructions.
20051022	Better statistics gathering for the ARM load/store multiple.
		Various other dyntrans and device updates.
20051023	Various minor updates.
20051024	Continuing; minor device and dyntrans fine-tuning. Adding the
		first "reasonable" instruction combination hacks for ARM (the
		cores of NetBSD/cats' memset and memcpy).
20051025	Fixing a dyntrans-related bug in dev_vga. Also changing the
		dyntrans low/high access notification to only be updated on
		writes, not reads. Hopefully it will be enough. (dev_vga in
		charcell mode now seems to work correctly with both reads and
		writes.)
		Experimenting with gathering dyntrans statistics (which parts
		of emulated RAM that are actually executed), and adding
		instruction combination hacks for cache cleaning and a part of
		NetBSD's scanc() function.
20051026	Adding a bitmap for ARM emulation which indicates if a page is
		(specifically) user accessible; loads and stores with the t-
		flag set can now use the translation arrays, which results in
		a measurable speedup.
20051027	Dyntrans updates; adding an extra bitmap array for 32-bit
		emulation modes, speeding up the check whether a physical page
		has any code translations or not (O(n) -> O(1)). Doing a
		similar reduction of O(n) to O(1) by avoiding the scan through
		the translation entries on a translation update (32-bit mode
		only).
		Various other minor hacks.
20051029	Quick release, without any testing at all.

==============  RELEASE 0.3.6.2  ==============


1 dpavlin 14 /*
2     * Copyright (C) 2005 Anders Gavare. All rights reserved.
3     *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 18 * $Id: cpu_arm.c,v 1.35 2005/10/23 14:24:13 debug Exp $
29 dpavlin 14 *
30     * ARM CPU emulation.
31     *
32     * A good source of quick info on ARM instruction encoding:
33     *
34     * http://www.pinknoise.demon.co.uk/ARMinstrs/ARMinstrs.html
35     *
36     * (Most "xxxx0101..." and similar strings in this file are from that URL,
37     * or from the ARM manual.)
38     */
39    
40     #include <stdio.h>
41     #include <stdlib.h>
42     #include <string.h>
43     #include <ctype.h>
44    
45     #include "arm_cpu_types.h"
46     #include "cpu.h"
47     #include "machine.h"
48     #include "memory.h"
49     #include "misc.h"
50     #include "symbol.h"
51    
52     #define DYNTRANS_32
53     #include "tmp_arm_head.c"
54    
55    
56     /* ARM symbolic register names and condition strings: */
57     static char *arm_regname[N_ARM_REGS] = ARM_REG_NAMES;
58     static char *arm_condition_string[16] = ARM_CONDITION_STRINGS;
59    
60     /* Data Processing Instructions: */
61     static char *arm_dpiname[16] = ARM_DPI_NAMES;
62     static int arm_dpi_uses_d[16] = { 1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1 };
63     static int arm_dpi_uses_n[16] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0 };
64    
65 dpavlin 18 /* For quick_pc_to_pointers(): */
66     #include "arm_quick_pc_to_pointers.h"
67 dpavlin 14
68    
69     /*
70     * arm_cpu_new():
71     *
72     * Create a new ARM cpu object by filling the CPU struct.
73     * Return 1 on success, 0 if cpu_type_name isn't a valid ARM processor.
74     */
75     int arm_cpu_new(struct cpu *cpu, struct memory *mem,
76     struct machine *machine, int cpu_id, char *cpu_type_name)
77     {
78     int any_cache = 0, i, found;
79     struct arm_cpu_type_def cpu_type_defs[] = ARM_CPU_TYPE_DEFS;
80    
81     /* Scan the list for this cpu type: */
82     i = 0; found = -1;
83     while (i >= 0 && cpu_type_defs[i].name != NULL) {
84     if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
85     found = i;
86     break;
87     }
88     i++;
89     }
90     if (found == -1)
91     return 0;
92    
93     cpu->memory_rw = arm_memory_rw;
94     cpu->update_translation_table = arm_update_translation_table;
95 dpavlin 18 cpu->invalidate_translation_caches =
96     arm_invalidate_translation_caches;
97 dpavlin 14 cpu->invalidate_code_translation = arm_invalidate_code_translation;
98     cpu->translate_address = arm_translate_address;
99    
100     cpu->cd.arm.cpu_type = cpu_type_defs[found];
101     cpu->name = cpu->cd.arm.cpu_type.name;
102     cpu->is_32bit = 1;
103    
104     cpu->cd.arm.cpsr = ARM_FLAG_I | ARM_FLAG_F;
105     cpu->cd.arm.control = ARM_CONTROL_PROG32 | ARM_CONTROL_DATA32
106     | ARM_CONTROL_CACHE | ARM_CONTROL_ICACHE | ARM_CONTROL_ALIGN;
107    
108     if (cpu->machine->prom_emulation) {
109     cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
110     cpu->cd.arm.control |= ARM_CONTROL_S;
111     } else {
112 dpavlin 18 cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
113     cpu->cd.arm.control |= ARM_CONTROL_R;
114 dpavlin 14 }
115    
116     /* Only show name and caches etc for CPU nr 0: */
117     if (cpu_id == 0) {
118     debug("%s", cpu->name);
119     if (cpu->cd.arm.cpu_type.icache_shift != 0)
120     any_cache = 1;
121     if (cpu->cd.arm.cpu_type.dcache_shift != 0)
122     any_cache = 1;
123     if (any_cache) {
124     debug(" (I+D = %i+%i KB",
125     (int)(1 << (cpu->cd.arm.cpu_type.icache_shift-10)),
126     (int)(1 << (cpu->cd.arm.cpu_type.dcache_shift-10)));
127     debug(")");
128     }
129     }
130    
131     /* Coprocessor 15 = the system control coprocessor. */
132     cpu->cd.arm.coproc[15] = arm_coproc_15;
133    
134     /*
135     * NOTE/TODO: Ugly hack for OpenFirmware emulation:
136     */
137     if (cpu->machine->prom_emulation) {
138     cpu->cd.arm.of_emul_addr = cpu->machine->physical_ram_in_mb
139     * 1048576 - 8;
140     store_32bit_word(cpu, cpu->cd.arm.of_emul_addr, 0xef8c64be);
141     }
142    
143     return 1;
144     }
145    
146    
147     /*
148     * arm_setup_initial_translation_table():
149     *
150     * When booting kernels (such as OpenBSD or NetBSD) directly, it is assumed
151     * that the MMU is already enabled by the boot-loader. This function tries
152     * to emulate that.
153     */
154     void arm_setup_initial_translation_table(struct cpu *cpu, uint32_t ttb_addr)
155     {
156     unsigned char nothing[16384];
157     unsigned int i, j;
158    
159     if (cpu->machine->userland_emul != NULL) {
160     fatal("arm_setup_initial_translation_table(): should not "
161     "be called for userland emulation!\n");
162     exit(1);
163     }
164    
165     cpu->cd.arm.control |= ARM_CONTROL_MMU;
166 dpavlin 18 cpu->translate_address = arm_translate_address_mmu;
167 dpavlin 14 cpu->cd.arm.dacr |= 0x00000003;
168     cpu->cd.arm.ttb = ttb_addr;
169    
170     memset(nothing, 0, sizeof(nothing));
171     cpu->memory_rw(cpu, cpu->mem, cpu->cd.arm.ttb, nothing,
172     sizeof(nothing), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
173     for (i=0; i<256; i++)
174     for (j=0x0; j<=0xf; j++) {
175     unsigned char descr[4];
176     uint32_t addr = cpu->cd.arm.ttb +
177     (((j << 28) + (i << 20)) >> 18);
178     uint32_t d = (1048576*i) | 0xc02;
179 dpavlin 18
180     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
181     descr[0] = d; descr[1] = d >> 8;
182     descr[2] = d >> 16; descr[3] = d >> 24;
183     } else {
184     descr[3] = d; descr[2] = d >> 8;
185     descr[1] = d >> 16; descr[0] = d >> 24;
186     }
187     cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
188     sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
189     }
190     }
191    
192    
193 dpavlin 14 /*
194 dpavlin 18 * arm_translation_table_set_l1():
195     */
196     void arm_translation_table_set_l1(struct cpu *cpu, uint32_t vaddr,
197     uint32_t paddr)
198     {
199     unsigned int i, j, vhigh = vaddr >> 28, phigh = paddr >> 28;
200    
201     for (i=0; i<256; i++)
202     for (j=vhigh; j<=vhigh; j++) {
203     unsigned char descr[4];
204     uint32_t addr = cpu->cd.arm.ttb +
205     (((j << 28) + (i << 20)) >> 18);
206     uint32_t d = ((phigh << 28) + 1048576*i) | 0xc02;
207    
208 dpavlin 14 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
209     descr[0] = d; descr[1] = d >> 8;
210     descr[2] = d >> 16; descr[3] = d >> 24;
211     } else {
212     descr[3] = d; descr[2] = d >> 8;
213     descr[1] = d >> 16; descr[0] = d >> 24;
214     }
215     cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
216     sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
217     }
218     }
219    
220    
221     /*
222 dpavlin 18 * arm_translation_table_set_l1_b():
223     */
224     void arm_translation_table_set_l1_b(struct cpu *cpu, uint32_t vaddr,
225     uint32_t paddr)
226     {
227     unsigned int i, j, vhigh = vaddr >> 24, phigh = paddr >> 24;
228    
229     for (i=0; i<16; i++)
230     for (j=vhigh; j<=vhigh; j++) {
231     unsigned char descr[4];
232     uint32_t addr = cpu->cd.arm.ttb +
233     (((j << 24) + (i << 20)) >> 18);
234     uint32_t d = ((phigh << 24) + 1048576*i) | 0xc02;
235    
236     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
237     descr[0] = d; descr[1] = d >> 8;
238     descr[2] = d >> 16; descr[3] = d >> 24;
239     } else {
240     descr[3] = d; descr[2] = d >> 8;
241     descr[1] = d >> 16; descr[0] = d >> 24;
242     }
243     cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
244     sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
245     }
246     }
247    
248    
249     /*
250 dpavlin 14 * arm_cpu_dumpinfo():
251     */
252     void arm_cpu_dumpinfo(struct cpu *cpu)
253     {
254     struct arm_cpu_type_def *ct = &cpu->cd.arm.cpu_type;
255    
256     debug(" (I+D = %i+%i KB)\n",
257     (1 << ct->icache_shift) / 1024, (1 << ct->dcache_shift) / 1024);
258     }
259    
260    
261     /*
262     * arm_cpu_list_available_types():
263     *
264     * Print a list of available ARM CPU types.
265     */
266     void arm_cpu_list_available_types(void)
267     {
268     int i, j;
269     struct arm_cpu_type_def tdefs[] = ARM_CPU_TYPE_DEFS;
270    
271     i = 0;
272     while (tdefs[i].name != NULL) {
273     debug("%s", tdefs[i].name);
274     for (j=13 - strlen(tdefs[i].name); j>0; j--)
275     debug(" ");
276     i++;
277     if ((i % 5) == 0 || tdefs[i].name == NULL)
278     debug("\n");
279     }
280     }
281    
282    
283     /*
284     * arm_cpu_register_match():
285     */
286     void arm_cpu_register_match(struct machine *m, char *name,
287     int writeflag, uint64_t *valuep, int *match_register)
288     {
289     int i, cpunr = 0;
290    
291     /* CPU number: */
292    
293     /* TODO */
294    
295     /* Register names: */
296     for (i=0; i<N_ARM_REGS; i++) {
297     if (strcasecmp(name, arm_regname[i]) == 0) {
298     if (writeflag) {
299     m->cpus[cpunr]->cd.arm.r[i] = *valuep;
300     if (i == ARM_PC)
301     m->cpus[cpunr]->pc = *valuep;
302     } else
303     *valuep = m->cpus[cpunr]->cd.arm.r[i];
304     *match_register = 1;
305     }
306     }
307     }
308    
309    
310     /*
311     * arm_cpu_register_dump():
312     *
313     * Dump cpu registers in a relatively readable format.
314     *
315     * gprs: set to non-zero to dump GPRs and some special-purpose registers.
316     * coprocs: set bit 0..3 to dump registers in coproc 0..3.
317     */
318     void arm_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
319     {
320     char *symbol;
321     uint64_t offset;
322     int mode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
323     int i, x = cpu->cpu_id;
324    
325     if (gprs) {
326     symbol = get_symbol_name(&cpu->machine->symbol_context,
327     cpu->cd.arm.r[ARM_PC], &offset);
328     debug("cpu%i: cpsr = ", x);
329     debug("%s%s%s%s%s%s",
330     (cpu->cd.arm.cpsr & ARM_FLAG_N)? "N" : "n",
331     (cpu->cd.arm.cpsr & ARM_FLAG_Z)? "Z" : "z",
332     (cpu->cd.arm.cpsr & ARM_FLAG_C)? "C" : "c",
333     (cpu->cd.arm.cpsr & ARM_FLAG_V)? "V" : "v",
334     (cpu->cd.arm.cpsr & ARM_FLAG_I)? "I" : "i",
335     (cpu->cd.arm.cpsr & ARM_FLAG_F)? "F" : "f");
336     if (mode < ARM_MODE_USR32)
337     debug(" pc = 0x%07x",
338     (int)(cpu->cd.arm.r[ARM_PC] & 0x03ffffff));
339     else
340     debug(" pc = 0x%08x", (int)cpu->cd.arm.r[ARM_PC]);
341    
342     debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
343    
344     for (i=0; i<N_ARM_REGS; i++) {
345     if ((i % 4) == 0)
346     debug("cpu%i:", x);
347     if (i != ARM_PC)
348     debug(" %s = 0x%08x", arm_regname[i],
349     (int)cpu->cd.arm.r[i]);
350     if ((i % 4) == 3)
351     debug("\n");
352     }
353     }
354    
355     if (coprocs & 1) {
356     int m = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
357     debug("cpu%i: cpsr = 0x%08x (", x, cpu->cd.arm.cpsr);
358     switch (m) {
359     case ARM_MODE_USR32:
360     debug("USR32)\n"); break;
361     case ARM_MODE_SYS32:
362     debug("SYS32)\n"); break;
363     case ARM_MODE_FIQ32:
364     debug("FIQ32)\n"); break;
365     case ARM_MODE_IRQ32:
366     debug("IRQ32)\n"); break;
367     case ARM_MODE_SVC32:
368     debug("SVC32)\n"); break;
369     case ARM_MODE_ABT32:
370     debug("ABT32)\n"); break;
371     case ARM_MODE_UND32:
372     debug("UND32)\n"); break;
373     default:debug("unimplemented)\n");
374     }
375    
376     if (m != ARM_MODE_USR32 && m != ARM_MODE_SYS32) {
377     debug("cpu%i: usr r8..r14 =", x);
378     for (i=0; i<7; i++)
379     debug(" %08x", cpu->cd.arm.default_r8_r14[i]);
380     debug("\n");
381     }
382    
383     if (m != ARM_MODE_FIQ32) {
384     debug("cpu%i: fiq r8..r14 =", x);
385     for (i=0; i<7; i++)
386     debug(" %08x", cpu->cd.arm.fiq_r8_r14[i]);
387     debug("\n");
388     }
389    
390     if (m != ARM_MODE_IRQ32) {
391     debug("cpu%i: irq r13..r14 =", x);
392     for (i=0; i<2; i++)
393     debug(" %08x", cpu->cd.arm.irq_r13_r14[i]);
394     debug("\n");
395     }
396    
397     if (m != ARM_MODE_SVC32) {
398     debug("cpu%i: svc r13..r14 =", x);
399     for (i=0; i<2; i++)
400     debug(" %08x", cpu->cd.arm.svc_r13_r14[i]);
401     debug("\n");
402     }
403    
404     if (m != ARM_MODE_ABT32) {
405     debug("cpu%i: abt r13..r14 =", x);
406     for (i=0; i<2; i++)
407     debug(" %08x", cpu->cd.arm.abt_r13_r14[i]);
408     debug("\n");
409     }
410    
411     if (m != ARM_MODE_UND32) {
412     debug("cpu%i: und r13..r14 =", x);
413     for (i=0; i<2; i++)
414     debug(" %08x", cpu->cd.arm.und_r13_r14[i]);
415     debug("\n");
416     }
417     }
418    
419     if (coprocs & 2) {
420     debug("cpu%i: control = 0x%08x\n", x, cpu->cd.arm.control);
421     debug("cpu%i: MMU: %s\n", x,
422     cpu->cd.arm.control &
423     ARM_CONTROL_MMU? "enabled" : "disabled");
424     debug("cpu%i: alignment checks: %s\n", x,
425     cpu->cd.arm.control &
426     ARM_CONTROL_ALIGN? "enabled" : "disabled");
427     debug("cpu%i: [data] cache: %s\n", x,
428     cpu->cd.arm.control &
429     ARM_CONTROL_CACHE? "enabled" : "disabled");
430     debug("cpu%i: instruction cache: %s\n", x,
431     cpu->cd.arm.control &
432     ARM_CONTROL_ICACHE? "enabled" : "disabled");
433     debug("cpu%i: write buffer: %s\n", x,
434     cpu->cd.arm.control &
435     ARM_CONTROL_WBUFFER? "enabled" : "disabled");
436     debug("cpu%i: prog32: %s\n", x,
437     cpu->cd.arm.control &
438     ARM_CONTROL_PROG32? "yes" : "no (using prog26)");
439     debug("cpu%i: data32: %s\n", x,
440     cpu->cd.arm.control &
441     ARM_CONTROL_DATA32? "yes" : "no (using data26)");
442     debug("cpu%i: endianness: %s\n", x,
443     cpu->cd.arm.control &
444     ARM_CONTROL_BIG? "big endian" : "little endian");
445     debug("cpu%i: high vectors: %s\n", x,
446     cpu->cd.arm.control &
447     ARM_CONTROL_V? "yes (0xffff0000)" : "no");
448    
449     debug("cpu%i: ttb = 0x%08x dacr = 0x%08x\n", x,
450     cpu->cd.arm.ttb, cpu->cd.arm.dacr);
451     debug("cpu%i: fsr = 0x%08x far = 0x%08x\n", x,
452     cpu->cd.arm.fsr, cpu->cd.arm.far);
453     }
454     }
455    
456    
457     /*
458     * arm_cpu_show_full_statistics():
459     *
460     * Show detailed statistics on opcode usage on each cpu.
461     */
462     void arm_cpu_show_full_statistics(struct machine *m)
463     {
464     fatal("arm_cpu_show_full_statistics(): TODO\n");
465     }
466    
467    
468     /*
469     * arm_cpu_tlbdump():
470     *
471     * Called from the debugger to dump the TLB in a readable format.
472     * x is the cpu number to dump, or -1 to dump all CPUs.
473     *
474     * If rawflag is nonzero, then the TLB contents isn't formated nicely,
475     * just dumped.
476     */
477     void arm_cpu_tlbdump(struct machine *m, int x, int rawflag)
478     {
479     fatal("arm_cpu_tlbdump(): TODO\n");
480     }
481    
482    
483     /*
484     * arm_save_register_bank():
485     */
486     void arm_save_register_bank(struct cpu *cpu)
487     {
488     /* Save away current registers: */
489     switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
490     case ARM_MODE_USR32:
491     case ARM_MODE_SYS32:
492     memcpy(cpu->cd.arm.default_r8_r14,
493     &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
494     break;
495     case ARM_MODE_FIQ32:
496     memcpy(cpu->cd.arm.fiq_r8_r14,
497     &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
498     break;
499     case ARM_MODE_IRQ32:
500 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
501     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
502 dpavlin 14 cpu->cd.arm.irq_r13_r14[0] = cpu->cd.arm.r[13];
503     cpu->cd.arm.irq_r13_r14[1] = cpu->cd.arm.r[14];
504     break;
505     case ARM_MODE_SVC32:
506 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
507     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
508 dpavlin 14 cpu->cd.arm.svc_r13_r14[0] = cpu->cd.arm.r[13];
509     cpu->cd.arm.svc_r13_r14[1] = cpu->cd.arm.r[14];
510     break;
511     case ARM_MODE_ABT32:
512 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
513     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
514 dpavlin 14 cpu->cd.arm.abt_r13_r14[0] = cpu->cd.arm.r[13];
515     cpu->cd.arm.abt_r13_r14[1] = cpu->cd.arm.r[14];
516     break;
517     case ARM_MODE_UND32:
518 dpavlin 16 memcpy(cpu->cd.arm.default_r8_r14,
519     &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
520 dpavlin 14 cpu->cd.arm.und_r13_r14[0] = cpu->cd.arm.r[13];
521     cpu->cd.arm.und_r13_r14[1] = cpu->cd.arm.r[14];
522     break;
523     default:fatal("arm_save_register_bank: unimplemented mode %i\n",
524     cpu->cd.arm.cpsr & ARM_FLAG_MODE);
525     exit(1);
526     }
527     }
528    
529    
530     /*
531     * arm_load_register_bank():
532     */
533     void arm_load_register_bank(struct cpu *cpu)
534     {
535     /* Load new registers: */
536     switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
537     case ARM_MODE_USR32:
538     case ARM_MODE_SYS32:
539     memcpy(&cpu->cd.arm.r[8],
540     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 7);
541     break;
542     case ARM_MODE_FIQ32:
543     memcpy(&cpu->cd.arm.r[8], cpu->cd.arm.fiq_r8_r14,
544     sizeof(uint32_t) * 7);
545     break;
546     case ARM_MODE_IRQ32:
547 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
548     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
549 dpavlin 14 cpu->cd.arm.r[13] = cpu->cd.arm.irq_r13_r14[0];
550     cpu->cd.arm.r[14] = cpu->cd.arm.irq_r13_r14[1];
551     break;
552     case ARM_MODE_SVC32:
553 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
554     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
555 dpavlin 14 cpu->cd.arm.r[13] = cpu->cd.arm.svc_r13_r14[0];
556     cpu->cd.arm.r[14] = cpu->cd.arm.svc_r13_r14[1];
557     break;
558     case ARM_MODE_ABT32:
559 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
560     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
561 dpavlin 14 cpu->cd.arm.r[13] = cpu->cd.arm.abt_r13_r14[0];
562     cpu->cd.arm.r[14] = cpu->cd.arm.abt_r13_r14[1];
563     break;
564     case ARM_MODE_UND32:
565 dpavlin 16 memcpy(&cpu->cd.arm.r[8],
566     cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
567 dpavlin 14 cpu->cd.arm.r[13] = cpu->cd.arm.und_r13_r14[0];
568     cpu->cd.arm.r[14] = cpu->cd.arm.und_r13_r14[1];
569     break;
570     default:fatal("arm_load_register_bank: unimplemented mode %i\n",
571     cpu->cd.arm.cpsr & ARM_FLAG_MODE);
572     exit(1);
573     }
574     }
575    
576    
577     /*
578     * arm_exception():
579     */
580     void arm_exception(struct cpu *cpu, int exception_nr)
581     {
582     int arm_exception_to_mode[N_ARM_EXCEPTIONS] = ARM_EXCEPTION_TO_MODE;
583     int oldmode, newmode;
584     uint32_t retaddr;
585    
586     if (exception_nr < 0 || exception_nr >= N_ARM_EXCEPTIONS) {
587     fatal("arm_exception(): exception_nr = %i\n", exception_nr);
588     exit(1);
589     }
590    
591     retaddr = cpu->pc;
592    
593 dpavlin 18 if (!quiet_mode) {
594     debug("[ arm_exception(): ");
595     switch (exception_nr) {
596     case ARM_EXCEPTION_RESET:
597     fatal("RESET: TODO");
598     break;
599     case ARM_EXCEPTION_UND:
600     debug("UNDEFINED");
601     break;
602     case ARM_EXCEPTION_SWI:
603     debug("SWI");
604     break;
605     case ARM_EXCEPTION_PREF_ABT:
606     debug("PREFETCH ABORT");
607     break;
608     case ARM_EXCEPTION_IRQ:
609     debug("IRQ");
610     break;
611     case ARM_EXCEPTION_FIQ:
612     debug("FIQ");
613     break;
614     case ARM_EXCEPTION_DATA_ABT:
615     debug("DATA ABORT, far=0x%08x fsr=0x%02x",
616     cpu->cd.arm.far, cpu->cd.arm.fsr);
617     break;
618     }
619     debug(" ]\n");
620     }
621 dpavlin 14
622     switch (exception_nr) {
623     case ARM_EXCEPTION_RESET:
624     cpu->running = 0;
625 dpavlin 18 fatal("ARM RESET: TODO");
626 dpavlin 14 exit(1);
627 dpavlin 18 case ARM_EXCEPTION_DATA_ABT:
628 dpavlin 14 retaddr += 4;
629     break;
630     }
631    
632 dpavlin 18 retaddr += 4;
633 dpavlin 14
634     arm_save_register_bank(cpu);
635    
636     switch (arm_exception_to_mode[exception_nr]) {
637     case ARM_MODE_SVC32:
638     cpu->cd.arm.spsr_svc = cpu->cd.arm.cpsr; break;
639     case ARM_MODE_ABT32:
640     cpu->cd.arm.spsr_abt = cpu->cd.arm.cpsr; break;
641     case ARM_MODE_UND32:
642     cpu->cd.arm.spsr_und = cpu->cd.arm.cpsr; break;
643     case ARM_MODE_IRQ32:
644     cpu->cd.arm.spsr_irq = cpu->cd.arm.cpsr; break;
645     case ARM_MODE_FIQ32:
646     cpu->cd.arm.spsr_fiq = cpu->cd.arm.cpsr; break;
647     default:fatal("arm_exception(): unimplemented exception nr\n");
648     exit(1);
649     }
650    
651     /*
652     * Disable Thumb mode (because exception handlers always execute
653     * in ARM mode), set the exception mode, and disable interrupts:
654     */
655     cpu->cd.arm.cpsr &= ~ARM_FLAG_T;
656    
657     oldmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
658    
659     cpu->cd.arm.cpsr &= ~ARM_FLAG_MODE;
660     cpu->cd.arm.cpsr |= arm_exception_to_mode[exception_nr];
661    
662     newmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
663     if (oldmode == newmode) {
664     fatal("Exception caused no mode change? TODO\n");
665     exit(1);
666     }
667    
668     cpu->cd.arm.cpsr |= ARM_FLAG_I;
669     if (exception_nr == ARM_EXCEPTION_RESET ||
670     exception_nr == ARM_EXCEPTION_FIQ)
671     cpu->cd.arm.cpsr |= ARM_FLAG_F;
672    
673     /* Load the new register bank, if we switched: */
674     arm_load_register_bank(cpu);
675    
676     /* Set the return address and new PC: */
677     cpu->cd.arm.r[ARM_LR] = retaddr;
678    
679     cpu->pc = cpu->cd.arm.r[ARM_PC] = exception_nr * 4 +
680     ((cpu->cd.arm.control & ARM_CONTROL_V)? 0xffff0000 : 0);
681 dpavlin 18 quick_pc_to_pointers(cpu);
682 dpavlin 14 }
683    
684    
685     /*
686     * arm_cpu_interrupt():
687     *
688     * 0..31 are used as footbridge interrupt numbers, 32..47 = ISA,
689     * 64 is used as a "re-assert" signal to cpu->machine->md_interrupt().
690     *
691     * TODO: don't hardcode to footbridge!
692     */
693     int arm_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
694     {
695     /* fatal("arm_cpu_interrupt(): 0x%llx\n", (int)irq_nr); */
696     if (irq_nr <= 64) {
697     if (cpu->machine->md_interrupt != NULL)
698     cpu->machine->md_interrupt(cpu->machine,
699     cpu, irq_nr, 1);
700     else
701     fatal("arm_cpu_interrupt(): md_interrupt == NULL\n");
702     } else {
703     /* Assert ARM IRQs: */
704     cpu->cd.arm.irq_asserted = 1;
705     }
706    
707     return 1;
708     }
709    
710    
711     /*
712     * arm_cpu_interrupt_ack():
713     */
714     int arm_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
715     {
716     if (irq_nr <= 64) {
717     if (cpu->machine->md_interrupt != NULL)
718     cpu->machine->md_interrupt(cpu->machine,
719     cpu, irq_nr, 0);
720     } else {
721     /* De-assert ARM IRQs: */
722     cpu->cd.arm.irq_asserted = 0;
723     }
724    
725     return 1;
726     }
727    
728    
729     /*
730     * arm_cpu_disassemble_instr():
731     *
732     * Convert an instruction word into human readable format, for instruction
733     * tracing.
734     *
735     * If running is 1, cpu->pc should be the address of the instruction.
736     *
737     * If running is 0, things that depend on the runtime environment (eg.
738     * register contents) will not be shown, and addr will be used instead of
739     * cpu->pc for relative addresses.
740     */
741     int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
742     int running, uint64_t dumpaddr, int bintrans)
743     {
744     uint32_t iw, tmp;
745     int main_opcode, secondary_opcode, s_bit, r16, r12, r8;
746     int i, n, p_bit, u_bit, b_bit, w_bit, l_bit;
747     char *symbol, *condition;
748     uint64_t offset;
749    
750     if (running)
751     dumpaddr = cpu->pc;
752    
753     symbol = get_symbol_name(&cpu->machine->symbol_context,
754     dumpaddr, &offset);
755     if (symbol != NULL && offset == 0)
756     debug("<%s>\n", symbol);
757    
758     if (cpu->machine->ncpus > 1 && running)
759     debug("cpu%i:\t", cpu->cpu_id);
760    
761     debug("%08x: ", (int)dumpaddr);
762    
763     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
764     iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
765     else
766     iw = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
767     debug("%08x\t", (int)iw);
768    
769     condition = arm_condition_string[iw >> 28];
770     main_opcode = (iw >> 24) & 15;
771     secondary_opcode = (iw >> 21) & 15;
772     u_bit = (iw >> 23) & 1;
773     b_bit = (iw >> 22) & 1;
774     w_bit = (iw >> 21) & 1;
775     s_bit = l_bit = (iw >> 20) & 1;
776     r16 = (iw >> 16) & 15;
777     r12 = (iw >> 12) & 15;
778     r8 = (iw >> 8) & 15;
779    
780     switch (main_opcode) {
781     case 0x0:
782     case 0x1:
783     case 0x2:
784     case 0x3:
785     /*
786     * Special cases first:
787     */
788    
789     /*
790     * Multiplication:
791     * xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd, Rm, Rs [,Rn])
792     */
793     if ((iw & 0x0fc000f0) == 0x00000090) {
794     int a_bit = (iw >> 21) & 1;
795     debug("%s%s%s\t", a_bit? "mla" : "mul",
796     condition, s_bit? "s" : "");
797     debug("%s,", arm_regname[r16]);
798     debug("%s,", arm_regname[iw & 15]);
799     debug("%s", arm_regname[r8]);
800     if (a_bit)
801     debug(",%s", arm_regname[r12]);
802     debug("\n");
803     break;
804     }
805    
806     /*
807     * Long multiplication:
808     * xxxx0000 1UAShhhh llllssss 1001mmmm (Rl,Rh,Rm,Rs)
809     */
810     if ((iw & 0x0f8000f0) == 0x00800090) {
811     int u_bit = (iw >> 22) & 1;
812     int a_bit = (iw >> 21) & 1;
813     debug("%s%sl%s%s\t", u_bit? "s" : "u",
814     a_bit? "mla" : "mul", condition, s_bit? "s" : "");
815     debug("%s,", arm_regname[r12]);
816     debug("%s,", arm_regname[r16]);
817     debug("%s,", arm_regname[iw & 15]);
818     debug("%s\n", arm_regname[r8]);
819     break;
820     }
821    
822     /*
823     * xxxx0001 0010.... ........ 00L1mmmm bx/blx rm
824     */
825     if ((iw & 0x0ff000d0) == 0x01200010) {
826     int l_bit = iw & 0x20;
827     debug("b%sx%s\t%s\n", l_bit? "l" : "", condition,
828     arm_regname[iw & 15]);
829     break;
830     }
831    
832     /*
833     * xxxx0001 0s10aaaa 11110000 0000mmmm MSR Regform
834     * xxxx0011 0s10aaaa 1111rrrr bbbbbbbb MSR Immform
835     * xxxx0001 0s001111 dddd0000 00000000 MRS
836     */
837     if ((iw & 0x0fb0fff0) == 0x0120f000 ||
838     (iw & 0x0fb0f000) == 0x0320f000) {
839     int a = (iw >> 16) & 15;
840     debug("msr%s\t%s", condition, (iw&0x400000)? "S":"C");
841     debug("PSR_");
842     switch (a) {
843     case 1: debug("ctl"); break;
844     case 8: debug("flg"); break;
845     case 9: debug("all"); break;
846     default:debug(" UNIMPLEMENTED (a=%i)", a);
847     }
848     if (iw & 0x02000000) {
849     int r = (iw >> 7) & 30;
850     uint32_t b = iw & 0xff;
851     while (r-- > 0)
852     b = (b >> 1) | ((b & 1) << 31);
853     debug(",#0x%x\n", b);
854     } else
855     debug(",%s\n", arm_regname[iw & 15]);
856     break;
857     }
858     if ((iw & 0x0fbf0fff) == 0x010f0000) {
859     debug("mrs%s\t", condition);
860     debug("%s,%sPSR\n", arm_regname[r12],
861     (iw&0x400000)? "S":"C");
862     break;
863     }
864    
865     /*
866     * xxxx0001 0B00nnnn dddd0000 1001mmmm SWP Rd,Rm,[Rn]
867     */
868     if ((iw & 0x0fb00ff0) == 0x01000090) {
869     debug("swp%s%s\t", condition, (iw&0x400000)? "b":"");
870     debug("%s,%s,[%s]\n", arm_regname[r12],
871     arm_regname[iw & 15], arm_regname[r16]);
872     break;
873     }
874    
875     /*
876     * xxxx000P U1WLnnnn ddddHHHH 1SH1LLLL load/store rd,imm(rn)
877     */
878     if ((iw & 0x0e000090) == 0x00000090) {
879 dpavlin 18 char *op = "st";
880 dpavlin 14 int imm = ((iw >> 4) & 0xf0) | (iw & 0xf);
881     int regform = !(iw & 0x00400000);
882     p_bit = main_opcode & 1;
883     /*
884     * TODO: detect some illegal variants:
885     * signed store, or unsigned byte load/store
886     */
887     if (!l_bit && (iw & 0xd0) == 0xd0 && (r12 & 1)) {
888     debug("TODO: r12 odd, not load/store\n");
889     break;
890     }
891     /* Semi-generic case: */
892 dpavlin 18 if (iw & 0x00100000)
893     op = "ld";
894     if (!l_bit && (iw & 0xd0) == 0xd0)
895     op = iw & 0x20? "st" : "ld";
896     debug("%sr%s", op, condition);
897 dpavlin 14 if (!l_bit && (iw & 0xd0) == 0xd0) {
898     debug("d"); /* Double-register */
899     } else {
900     if (iw & 0x40)
901     debug("s"); /* signed */
902     if (iw & 0x20)
903     debug("h"); /* half-word */
904     else
905     debug("b"); /* byte */
906     }
907     debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
908     if (p_bit) {
909     /* Pre-index: */
910     if (regform)
911     debug(",%s%s", u_bit? "" : "-",
912     arm_regname[iw & 15]);
913     else {
914     if (imm != 0)
915     debug(",#%s%i", u_bit? "" : "-",
916     imm);
917     }
918     debug("]%s\n", w_bit? "!" : "");
919     } else {
920     /* Post-index: */
921     debug("],");
922     if (regform)
923     debug("%s%s\n", u_bit? "" : "-",
924     arm_regname[iw & 15]);
925     else
926     debug("#%s%i\n", u_bit? "" : "-", imm);
927     }
928     break;
929     }
930    
931     /* Other special cases: */
932     if (iw & 0x80 && !(main_opcode & 2) && iw & 0x10) {
933     debug("UNIMPLEMENTED reg (c!=0), t odd\n");
934     break;
935     }
936    
937     /*
938     * Generic Data Processing Instructions:
939     *
940     * xxxx000a aaaSnnnn ddddcccc ctttmmmm Register form
941     * xxxx001a aaaSnnnn ddddrrrr bbbbbbbb Immediate form
942     */
943    
944     debug("%s%s%s\t", arm_dpiname[secondary_opcode],
945     condition, s_bit? "s" : "");
946     if (arm_dpi_uses_d[secondary_opcode])
947     debug("%s,", arm_regname[r12]);
948     if (arm_dpi_uses_n[secondary_opcode])
949     debug("%s,", arm_regname[r16]);
950    
951     if (main_opcode & 2) {
952     /* Immediate form: */
953     int r = (iw >> 7) & 30;
954     uint32_t b = iw & 0xff;
955     while (r-- > 0)
956     b = (b >> 1) | ((b & 1) << 31);
957     if (b < 15)
958     debug("#%i", b);
959     else
960     debug("#0x%x", b);
961     } else {
962     /* Register form: */
963     int t = (iw >> 4) & 7;
964     int c = (iw >> 7) & 31;
965     debug("%s", arm_regname[iw & 15]);
966     switch (t) {
967     case 0: if (c != 0)
968     debug(", lsl #%i", c);
969     break;
970     case 1: debug(", lsl %s", arm_regname[c >> 1]);
971     break;
972     case 2: debug(", lsr #%i", c? c : 32);
973     break;
974     case 3: debug(", lsr %s", arm_regname[c >> 1]);
975     break;
976     case 4: debug(", asr #%i", c? c : 32);
977     break;
978     case 5: debug(", asr %s", arm_regname[c >> 1]);
979     break;
980     case 6: if (c != 0)
981     debug(", ror #%i", c);
982     else
983     debug(", rrx");
984     break;
985     case 7: debug(", ror %s", arm_regname[c >> 1]);
986     break;
987     }
988    
989     /* mov pc,reg: */
990     if (running && t == 0 && c == 0 && secondary_opcode
991     == 0xd && r12 == ARM_PC && (iw&15)!=ARM_PC) {
992     symbol = get_symbol_name(&cpu->machine->
993     symbol_context, cpu->cd.arm.r[iw & 15],
994     &offset);
995     if (symbol != NULL)
996     debug(" \t<%s>", symbol);
997     }
998     }
999     debug("\n");
1000     break;
1001     case 0x4: /* Single Data Transfer */
1002     case 0x5:
1003     case 0x6:
1004     case 0x7:
1005     /* Special case first: */
1006     if ((iw & 0xfc70f000) == 0xf450f000) {
1007     /* Preload: */
1008     debug("pld\t[%s]\n", arm_regname[r16]);
1009     break;
1010     }
1011    
1012     /*
1013     * xxxx010P UBWLnnnn ddddoooo oooooooo Immediate form
1014     * xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form
1015     */
1016     p_bit = main_opcode & 1;
1017     if (main_opcode >= 6 && iw & 0x10) {
1018     debug("TODO: single data transf. but 0x10\n");
1019     break;
1020     }
1021     debug("%s%s%s", l_bit? "ldr" : "str",
1022     condition, b_bit? "b" : "");
1023     if (!p_bit && w_bit)
1024     debug("t");
1025     debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
1026     if ((iw & 0x0e000000) == 0x04000000) {
1027     /* Immediate form: */
1028     uint32_t imm = iw & 0xfff;
1029     if (!p_bit)
1030     debug("]");
1031     if (imm != 0)
1032     debug(",#%s%i", u_bit? "" : "-", imm);
1033     if (p_bit)
1034     debug("]");
1035     } else if ((iw & 0x0e000010) == 0x06000000) {
1036     /* Register form: */
1037     if (!p_bit)
1038     debug("]");
1039     if ((iw & 0xfff) != 0)
1040     debug(",%s%s", u_bit? "" : "-",
1041     arm_regname[iw & 15]);
1042     if ((iw & 0xff0) != 0x000) {
1043     int c = (iw >> 7) & 31;
1044     int t = (iw >> 4) & 7;
1045     switch (t) {
1046     case 0: if (c != 0)
1047     debug(", lsl #%i", c);
1048     break;
1049     case 2: debug(", lsr #%i", c? c : 32);
1050     break;
1051     case 4: debug(", asr #%i", c? c : 32);
1052     break;
1053     case 6: if (c != 0)
1054     debug(", ror #%i", c);
1055     else
1056     debug(", rrx");
1057     break;
1058     }
1059     }
1060     if (p_bit)
1061     debug("]");
1062     } else {
1063     debug("UNKNOWN\n");
1064     break;
1065     }
1066     debug("%s", (p_bit && w_bit)? "!" : "");
1067     if ((iw & 0x0f000000) == 0x05000000 &&
1068     (r16 == ARM_PC || running)) {
1069     unsigned char tmpw[4];
1070     uint32_t imm = iw & 0xfff;
1071     uint32_t addr = (u_bit? imm : -imm);
1072     if (r16 == ARM_PC)
1073     addr += dumpaddr + 8;
1074     else
1075     addr += cpu->cd.arm.r[r16];
1076     symbol = get_symbol_name(&cpu->machine->symbol_context,
1077     addr, &offset);
1078     if (symbol != NULL)
1079     debug(" \t<%s", symbol);
1080     else
1081     debug(" \t<0x%08x", addr);
1082     if ((l_bit && cpu->memory_rw(cpu, cpu->mem, addr, tmpw,
1083     b_bit? 1 : sizeof(tmpw), MEM_READ, NO_EXCEPTIONS))
1084     || (!l_bit && running)) {
1085     if (l_bit) {
1086     if (cpu->byte_order ==
1087     EMUL_LITTLE_ENDIAN)
1088     addr = tmpw[0] +(tmpw[1] << 8) +
1089     (tmpw[2]<<16)+(tmpw[3]<<24);
1090     else
1091     addr = tmpw[3] + (tmpw[2]<<8) +
1092     (tmpw[1]<<16)+(tmpw[0]<<24);
1093     } else {
1094     tmpw[0] = addr = cpu->cd.arm.r[r12];
1095     if (r12 == ARM_PC)
1096     addr += 8;
1097     }
1098     debug(": ");
1099     if (b_bit)
1100     debug("%i", tmpw[0]);
1101     else {
1102     symbol = get_symbol_name(&cpu->machine->
1103     symbol_context, addr, &offset);
1104     if (symbol != NULL)
1105     debug("%s", symbol);
1106     else if ((int32_t)addr > -256 &&
1107     (int32_t)addr < 256)
1108     debug("%i", addr);
1109     else
1110     debug("0x%x", addr);
1111     }
1112     }
1113     debug(">");
1114     }
1115     debug("\n");
1116     break;
1117     case 0x8: /* Block Data Transfer */
1118     case 0x9:
1119     /* xxxx100P USWLnnnn llllllll llllllll */
1120     p_bit = main_opcode & 1;
1121     s_bit = b_bit;
1122     debug("%s%s", l_bit? "ldm" : "stm", condition);
1123     switch (u_bit * 2 + p_bit) {
1124     case 0: debug("da"); break;
1125     case 1: debug("db"); break;
1126     case 2: debug("ia"); break;
1127     case 3: debug("ib"); break;
1128     }
1129     debug("\t%s", arm_regname[r16]);
1130     if (w_bit)
1131     debug("!");
1132     debug(",{");
1133     n = 0;
1134     for (i=0; i<16; i++)
1135     if ((iw >> i) & 1) {
1136     debug("%s%s", (n > 0)? ",":"", arm_regname[i]);
1137     n++;
1138     }
1139     debug("}");
1140     if (s_bit)
1141     debug("^");
1142     debug("\n");
1143     break;
1144     case 0xa: /* B: branch */
1145     case 0xb: /* BL: branch and link */
1146     debug("b%s%s\t", main_opcode == 0xa? "" : "l", condition);
1147     tmp = (iw & 0x00ffffff) << 2;
1148     if (tmp & 0x02000000)
1149     tmp |= 0xfc000000;
1150     tmp = (int32_t)(dumpaddr + tmp + 8);
1151     debug("0x%x", (int)tmp);
1152     symbol = get_symbol_name(&cpu->machine->symbol_context,
1153     tmp, &offset);
1154     if (symbol != NULL)
1155     debug(" \t<%s>", symbol);
1156     debug("\n");
1157     break;
1158     case 0xc: /* Coprocessor */
1159     case 0xd: /* LDC/STC */
1160     /* xxxx110P UNWLnnnn DDDDpppp oooooooo LDC/STC */
1161     debug("TODO: coprocessor LDC/STC\n");
1162     break;
1163     case 0xe: /* CDP (Coprocessor Op) */
1164     /* or MRC/MCR!
1165     * xxxx1110 oooonnnn ddddpppp qqq0mmmm CDP
1166     * xxxx1110 oooLNNNN ddddpppp qqq1MMMM MRC/MCR
1167     */
1168     if (iw & 0x10) {
1169     debug("%s%s\t",
1170     (iw & 0x00100000)? "mrc" : "mcr", condition);
1171     debug("%i,%i,r%i,cr%i,cr%i,%i",
1172     (int)((iw >> 8) & 15), (int)((iw >>21) & 7),
1173     (int)((iw >>12) & 15), (int)((iw >>16) & 15),
1174     (int)((iw >> 0) & 15), (int)((iw >> 5) & 7));
1175     } else {
1176     debug("cdp%s\t", condition);
1177     debug("%i,%i,cr%i,cr%i,cr%i",
1178     (int)((iw >> 8) & 15),
1179     (int)((iw >>20) & 15),
1180     (int)((iw >>12) & 15),
1181     (int)((iw >>16) & 15),
1182     (int)((iw >> 0) & 15));
1183     if ((iw >> 5) & 7)
1184     debug(",0x%x", (int)((iw >> 5) & 7));
1185     }
1186     debug("\n");
1187     break;
1188     case 0xf: /* SWI */
1189     debug("swi%s\t", condition);
1190     debug("0x%x\n", (int)(iw & 0x00ffffff));
1191     break;
1192     default:debug("UNIMPLEMENTED\n");
1193     }
1194    
1195     return sizeof(uint32_t);
1196     }
1197    
1198    
1199     /*****************************************************************************/
1200    
1201    
1202     /*
1203     * arm_mcr_mrc():
1204     *
1205     * Coprocessor register move.
1206     *
1207     * The program counter should be synched before calling this function (to
1208     * make debug output with the correct PC value possible).
1209     */
1210     void arm_mcr_mrc(struct cpu *cpu, uint32_t iword)
1211     {
1212     int opcode1 = (iword >> 21) & 7;
1213     int l_bit = (iword >> 20) & 1;
1214     int crn = (iword >> 16) & 15;
1215     int rd = (iword >> 12) & 15;
1216     int cp_num = (iword >> 8) & 15;
1217     int opcode2 = (iword >> 5) & 7;
1218     int crm = iword & 15;
1219    
1220     if (cpu->cd.arm.coproc[cp_num] != NULL)
1221     cpu->cd.arm.coproc[cp_num](cpu, opcode1, opcode2, l_bit,
1222     crn, crm, rd);
1223     else {
1224     fatal("arm_mcr_mrc: pc=0x%08x, iword=0x%08x: "
1225     "cp_num=%i\n", (int)cpu->pc, iword, cp_num);
1226     exit(1);
1227     }
1228     }
1229    
1230    
1231     /*
1232     * arm_cdp():
1233     *
1234     * Coprocessor operations.
1235     *
1236     * The program counter should be synched before calling this function (to
1237     * make debug output with the correct PC value possible).
1238     */
1239     void arm_cdp(struct cpu *cpu, uint32_t iword)
1240     {
1241     fatal("arm_cdp: pc=0x%08x, iword=0x%08x\n", (int)cpu->pc, iword);
1242     exit(1);
1243     }
1244    
1245    
1246     /*****************************************************************************/
1247    
1248    
1249     #include "tmp_arm_tail.c"
1250    

  ViewVC Help
Powered by ViewVC 1.1.26