/[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

Contents of /trunk/src/cpus/cpu_arm.c

Parent Directory Parent Directory | Revision Log Revision Log


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

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


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

  ViewVC Help
Powered by ViewVC 1.1.26