/[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 26 - (hide annotations)
Mon Oct 8 16:20:10 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 40652 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1264 2006/06/25 11:08:04 debug Exp $
20060624	Replacing the error-prone machine type initialization stuff
		with something more reasonable.
		Finally removing the old "cpu_run" kludge; moving around stuff
		in machine.c and emul.c to better suit the dyntrans system.
		Various minor dyntrans cleanups (renaming translate_address to
		translate_v2p, and experimenting with template physpages).
20060625	Removing the speed hack which separated the vph entries into
		two halves (code vs data); things seem a lot more stable now.
		Minor performance hack: R2000/R3000 cache isolation now only
		clears address translations when going into isolation, not
		when going out of it.
		Fixing the MIPS interrupt problems by letting mtc0 immediately
		cause interrupts.

==============  RELEASE 0.4.0.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26