/[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 44 - (hide annotations)
Mon Oct 8 16:22:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 38623 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1632 2007/09/11 21:46:35 debug Exp $
20070616	Implementing the MIPS32/64 revision 2 "ror" instruction.
20070617	Adding a struct for each physpage which keeps track of which
		ranges within that page (base offset, length) that are
		continuously translatable. When running with native code
		generation enabled (-b), a range is added after each read-
		ahead loop.
		Experimenting with using the physical program counter sample
		data (implemented 20070608) together with the "translatable
		range" information, to figure out which physical address ranges
		would be worth translating to native code (if the number of
		samples falling within a range is above a certain threshold).
20070618	Adding automagic building of .index comment files for
		src/file/, src/promemul/, src src/useremul/ as well.
		Adding a "has been translated" bit to the ranges, so that only
		not-yet-translated ranges will be sampled.
20070619	Moving src/cpu.c and src/memory_rw.c into src/cpus/,
		src/device.c into src/devices/, and src/machine.c into
		src/machines/.
		Creating a skeleton cc/ld native backend module; beginning on
		the function which will detect cc command line, etc.
20070620	Continuing on the native code generation infrastructure.
20070621	Moving src/x11.c and src/console.c into a new src/console/
		subdir (for everything that is console or framebuffer related).
		Moving src/symbol*.c into a new src/symbol/, which should
		contain anything that is symbol handling related.
20070624	Making the program counter sampling threshold a "settings
		variable" (sampling_threshold), i.e. it can now be changed
		during runtime.
		Switching the RELEASE notes format from plain text to HTML.
		If the TMPDIR environment variable is set, it is used instead
		of "/tmp" for temporary files.
		Continuing on the cc/ld backend: simple .c code is generated,
		the compiler and linker are called, etc.
		Adding detection of host architecture to the configure script
		(again), and adding icache invalidation support (only
		implemented for Alpha hosts so far).
20070625	Simplifying the program counter sampling mechanism.
20070626	Removing the cc/ld native code generation stuff, program
		counter sampling, etc; it would not have worked well in the
		general case.
20070627	Removing everything related to native code generation.
20070629	Removing the (practically unusable) support for multiple
		emulations. (The single emulation allowed now still supports
		multiple simultaneous machines, as before.)
		Beginning on PCCTWO and M88K interrupts.
20070723	Adding a dummy skeleton for emulation of M32R processors.
20070901	Fixing a warning found by "gcc version 4.3.0 20070817
		(experimental)" on amd64.
20070905	Removing some more traces of the old "multiple emulations"
		code.
		Also looking in /usr/local/include and /usr/local/lib for
		X11 libs, when running configure.
20070909	Minor updates to the guest OS install instructions, in
		preparation for the NetBSD 4.0 release.
20070918	More testing of NetBSD 4.0 RC1.

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

  ViewVC Help
Powered by ViewVC 1.1.26