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

1 /*
2 * Copyright (C) 2005-2007 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.72 2007/06/28 13:36:46 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 #include <unistd.h>
43
44 #include "arm_cpu_types.h"
45 #include "cpu.h"
46 #include "interrupt.h"
47 #include "machine.h"
48 #include "memory.h"
49 #include "misc.h"
50 #include "of.h"
51 #include "settings.h"
52 #include "symbol.h"
53 #include "useremul.h"
54
55 #define DYNTRANS_32
56 #include "tmp_arm_head.c"
57
58
59 /* ARM symbolic register names and condition strings: */
60 static char *arm_regname[N_ARM_REGS] = ARM_REG_NAMES;
61 static char *arm_condition_string[16] = ARM_CONDITION_STRINGS;
62
63 /* Data Processing Instructions: */
64 static char *arm_dpiname[16] = ARM_DPI_NAMES;
65 static int arm_dpi_uses_d[16] = { 1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1 };
66 static int arm_dpi_uses_n[16] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0 };
67
68 static int arm_exception_to_mode[N_ARM_EXCEPTIONS] = ARM_EXCEPTION_TO_MODE;
69
70 /* For quick_pc_to_pointers(): */
71 void arm_pc_to_pointers(struct cpu *cpu);
72 #include "quick_pc_to_pointers.h"
73
74 void arm_irq_interrupt_assert(struct interrupt *interrupt);
75 void arm_irq_interrupt_deassert(struct interrupt *interrupt);
76
77
78 /*
79 * arm_cpu_new():
80 *
81 * Create a new ARM cpu object by filling the CPU struct.
82 * Return 1 on success, 0 if cpu_type_name isn't a valid ARM processor.
83 */
84 int arm_cpu_new(struct cpu *cpu, struct memory *mem,
85 struct machine *machine, int cpu_id, char *cpu_type_name)
86 {
87 int i, found;
88 struct arm_cpu_type_def cpu_type_defs[] = ARM_CPU_TYPE_DEFS;
89
90 /* Scan the list for this cpu type: */
91 i = 0; found = -1;
92 while (i >= 0 && cpu_type_defs[i].name != NULL) {
93 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
94 found = i;
95 break;
96 }
97 i++;
98 }
99 if (found == -1)
100 return 0;
101
102 cpu->run_instr = arm_run_instr;
103 cpu->memory_rw = arm_memory_rw;
104 cpu->update_translation_table = arm_update_translation_table;
105 cpu->invalidate_translation_caches =
106 arm_invalidate_translation_caches;
107 cpu->invalidate_code_translation = arm_invalidate_code_translation;
108 cpu->translate_v2p = arm_translate_v2p;
109
110 cpu->cd.arm.cpu_type = cpu_type_defs[found];
111 cpu->name = cpu->cd.arm.cpu_type.name;
112 cpu->is_32bit = 1;
113 cpu->byte_order = EMUL_LITTLE_ENDIAN;
114
115 cpu->cd.arm.cpsr = ARM_FLAG_I | ARM_FLAG_F;
116 cpu->cd.arm.control = ARM_CONTROL_PROG32 | ARM_CONTROL_DATA32
117 | ARM_CONTROL_CACHE | ARM_CONTROL_ICACHE | ARM_CONTROL_ALIGN;
118 /* TODO: default auxctrl contents */
119
120 if (cpu->machine->prom_emulation) {
121 cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
122 cpu->cd.arm.control |= ARM_CONTROL_S;
123 } else {
124 cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
125 cpu->cd.arm.control |= ARM_CONTROL_R;
126 }
127
128 /* Only show name and caches etc for CPU nr 0: */
129 if (cpu_id == 0) {
130 debug("%s", cpu->name);
131 if (cpu->cd.arm.cpu_type.icache_shift != 0 ||
132 cpu->cd.arm.cpu_type.dcache_shift != 0) {
133 int isize = cpu->cd.arm.cpu_type.icache_shift;
134 int dsize = cpu->cd.arm.cpu_type.dcache_shift;
135 if (isize != 0)
136 isize = 1 << (isize - 10);
137 if (dsize != 0)
138 dsize = 1 << (dsize - 10);
139 debug(" (I+D = %i+%i KB)", isize, dsize);
140 }
141 }
142
143 /* TODO: Some of these values (iway and dway) aren't used yet: */
144 cpu->cd.arm.cachetype =
145 (5 << ARM_CACHETYPE_CLASS_SHIFT)
146 | (1 << ARM_CACHETYPE_HARVARD_SHIFT)
147 | ((cpu->cd.arm.cpu_type.dcache_shift - 9) <<
148 ARM_CACHETYPE_DSIZE_SHIFT)
149 | (5 << ARM_CACHETYPE_DASSOC_SHIFT) /* 32-way */
150 | (2 << ARM_CACHETYPE_DLINE_SHIFT) /* 8 words/line */
151 | ((cpu->cd.arm.cpu_type.icache_shift - 9) <<
152 ARM_CACHETYPE_ISIZE_SHIFT)
153 | (5 << ARM_CACHETYPE_IASSOC_SHIFT) /* 32-way */
154 | (2 << ARM_CACHETYPE_ILINE_SHIFT); /* 8 words/line */
155
156 /* Coprocessor 15 = the system control coprocessor. */
157 cpu->cd.arm.coproc[15] = arm_coproc_15;
158
159 /* Coprocessor 14 for XScale: */
160 if (cpu->cd.arm.cpu_type.flags & ARM_XSCALE)
161 cpu->cd.arm.coproc[14] = arm_coproc_xscale_14;
162
163 /*
164 * NOTE/TODO: Ugly hack for OpenFirmware emulation:
165 */
166 if (cpu->machine->prom_emulation) {
167 cpu->cd.arm.of_emul_addr = cpu->machine->physical_ram_in_mb
168 * 1048576 - 8;
169 store_32bit_word(cpu, cpu->cd.arm.of_emul_addr, 0xef8c64be);
170 }
171
172 cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
173
174 CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
175 for (i=0; i<N_ARM_REGS - 1; i++)
176 CPU_SETTINGS_ADD_REGISTER32(arm_regname[i], cpu->cd.arm.r[i]);
177
178 /* Register the CPU's "IRQ" and "FIQ" interrupts: */
179 {
180 struct interrupt template;
181 char name[50];
182 snprintf(name, sizeof(name), "%s.irq", cpu->path);
183
184 memset(&template, 0, sizeof(template));
185 template.line = 0;
186 template.name = name;
187 template.extra = cpu;
188 template.interrupt_assert = arm_irq_interrupt_assert;
189 template.interrupt_deassert = arm_irq_interrupt_deassert;
190 interrupt_handler_register(&template);
191
192 /* FIQ: TODO */
193 }
194
195 return 1;
196 }
197
198
199 /*
200 * arm_setup_initial_translation_table():
201 *
202 * When booting kernels (such as OpenBSD or NetBSD) directly, it is assumed
203 * that the MMU is already enabled by the boot-loader. This function tries
204 * to emulate that.
205 */
206 void arm_setup_initial_translation_table(struct cpu *cpu, uint32_t ttb_addr)
207 {
208 unsigned char nothing[16384];
209 unsigned int i, j;
210
211 if (cpu->machine->userland_emul != NULL) {
212 fatal("arm_setup_initial_translation_table(): should not "
213 "be called for userland emulation!\n");
214 exit(1);
215 }
216
217 cpu->cd.arm.control |= ARM_CONTROL_MMU;
218 cpu->translate_v2p = arm_translate_v2p_mmu;
219 cpu->cd.arm.dacr |= 0x00000003;
220 cpu->cd.arm.ttb = ttb_addr;
221
222 memset(nothing, 0, sizeof(nothing));
223 cpu->memory_rw(cpu, cpu->mem, cpu->cd.arm.ttb, nothing,
224 sizeof(nothing), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
225 for (i=0; i<256; i++)
226 for (j=0x0; j<=0xf; j++) {
227 unsigned char descr[4];
228 uint32_t addr = cpu->cd.arm.ttb +
229 (((j << 28) + (i << 20)) >> 18);
230 uint32_t d = (1048576*i) | 0xc02;
231
232 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
233 descr[0] = d; descr[1] = d >> 8;
234 descr[2] = d >> 16; descr[3] = d >> 24;
235 } else {
236 descr[3] = d; descr[2] = d >> 8;
237 descr[1] = d >> 16; descr[0] = d >> 24;
238 }
239 cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
240 sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
241 }
242 }
243
244
245 /*
246 * arm_translation_table_set_l1():
247 */
248 void arm_translation_table_set_l1(struct cpu *cpu, uint32_t vaddr,
249 uint32_t paddr)
250 {
251 unsigned int i, j, vhigh = vaddr >> 28, phigh = paddr >> 28;
252
253 for (i=0; i<256; i++)
254 for (j=vhigh; j<=vhigh; j++) {
255 unsigned char descr[4];
256 uint32_t addr = cpu->cd.arm.ttb +
257 (((j << 28) + (i << 20)) >> 18);
258 uint32_t d = ((phigh << 28) + 1048576*i) | 0xc02;
259
260 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
261 descr[0] = d; descr[1] = d >> 8;
262 descr[2] = d >> 16; descr[3] = d >> 24;
263 } else {
264 descr[3] = d; descr[2] = d >> 8;
265 descr[1] = d >> 16; descr[0] = d >> 24;
266 }
267 cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
268 sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
269 }
270 }
271
272
273 /*
274 * arm_translation_table_set_l1_b():
275 */
276 void arm_translation_table_set_l1_b(struct cpu *cpu, uint32_t vaddr,
277 uint32_t paddr)
278 {
279 unsigned int i, j, vhigh = vaddr >> 24, phigh = paddr >> 24;
280
281 for (i=0; i<16; i++)
282 for (j=vhigh; j<=vhigh; j++) {
283 unsigned char descr[4];
284 uint32_t addr = cpu->cd.arm.ttb +
285 (((j << 24) + (i << 20)) >> 18);
286 uint32_t d = ((phigh << 24) + 1048576*i) | 0xc02;
287
288 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
289 descr[0] = d; descr[1] = d >> 8;
290 descr[2] = d >> 16; descr[3] = d >> 24;
291 } else {
292 descr[3] = d; descr[2] = d >> 8;
293 descr[1] = d >> 16; descr[0] = d >> 24;
294 }
295 cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
296 sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
297 }
298 }
299
300
301 /*
302 * arm_cpu_dumpinfo():
303 */
304 void arm_cpu_dumpinfo(struct cpu *cpu)
305 {
306 struct arm_cpu_type_def *ct = &cpu->cd.arm.cpu_type;
307
308 debug(" (I+D = %i+%i KB)\n",
309 (1 << ct->icache_shift) / 1024, (1 << ct->dcache_shift) / 1024);
310 }
311
312
313 /*
314 * arm_cpu_list_available_types():
315 *
316 * Print a list of available ARM CPU types.
317 */
318 void arm_cpu_list_available_types(void)
319 {
320 int i, j;
321 struct arm_cpu_type_def tdefs[] = ARM_CPU_TYPE_DEFS;
322
323 i = 0;
324 while (tdefs[i].name != NULL) {
325 debug("%s", tdefs[i].name);
326 for (j=13 - strlen(tdefs[i].name); j>0; j--)
327 debug(" ");
328 i++;
329 if ((i % 5) == 0 || tdefs[i].name == NULL)
330 debug("\n");
331 }
332 }
333
334
335 /*
336 * arm_cpu_register_dump():
337 *
338 * Dump cpu registers in a relatively readable format.
339 *
340 * gprs: set to non-zero to dump GPRs and some special-purpose registers.
341 * coprocs: set bit 0..3 to dump registers in coproc 0..3.
342 */
343 void arm_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
344 {
345 char *symbol;
346 uint64_t offset;
347 int mode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
348 int i, x = cpu->cpu_id;
349
350 cpu->cd.arm.cpsr &= 0x0fffffff;
351 cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
352
353 if (gprs) {
354 symbol = get_symbol_name(&cpu->machine->symbol_context,
355 cpu->pc, &offset);
356 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 debug(" pc = 0x%07x", (int)(cpu->pc & 0x03ffffff));
366 else
367 debug(" pc = 0x%08x", (int)cpu->pc);
368
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 debug("cpu%i: usr r8-14:", x);
405 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 debug("cpu%i: fiq r8-14:", x);
412 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 debug("cpu%i: irq r13-14:", x);
419 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 debug("cpu%i: svc r13-14:", x);
426 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 debug("cpu%i: abt r13-14:", x);
433 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 debug("cpu%i: und r13-14:", x);
440 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 /* 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 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 memcpy(cpu->cd.arm.default_r8_r14,
516 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
517 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 memcpy(cpu->cd.arm.default_r8_r14,
522 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
523 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 memcpy(cpu->cd.arm.default_r8_r14,
528 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
529 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 memcpy(cpu->cd.arm.default_r8_r14,
534 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
535 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 memcpy(&cpu->cd.arm.r[8],
563 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
564 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 memcpy(&cpu->cd.arm.r[8],
569 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
570 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 memcpy(&cpu->cd.arm.r[8],
575 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
576 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 memcpy(&cpu->cd.arm.r[8],
581 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
582 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 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
636 switch (exception_nr) {
637 case ARM_EXCEPTION_RESET:
638 cpu->running = 0;
639 fatal("ARM RESET: TODO");
640 exit(1);
641 case ARM_EXCEPTION_DATA_ABT:
642 retaddr += 4;
643 break;
644 }
645
646 retaddr += 4;
647
648 arm_save_register_bank(cpu);
649
650 cpu->cd.arm.cpsr &= 0x0fffffff;
651 cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
652
653 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 /*
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 newmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
687 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 }
692
693 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 /*
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 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 quick_pc_to_pointers(cpu);
713 }
714
715
716 /*
717 * arm_cpu_tlbdump():
718 *
719 * Called from the debugger to dump the TLB in a readable format.
720 * x is the cpu number to dump, or -1 to dump all CPUs.
721 *
722 * If rawflag is nonzero, then the TLB contents isn't formated nicely,
723 * just dumped.
724 */
725 void arm_cpu_tlbdump(struct machine *m, int x, int rawflag)
726 {
727 }
728
729
730 /*
731 * arm_irq_interrupt_assert():
732 * arm_irq_interrupt_deassert():
733 */
734 void arm_irq_interrupt_assert(struct interrupt *interrupt)
735 {
736 struct cpu *cpu = (struct cpu *) interrupt->extra;
737 cpu->cd.arm.irq_asserted = 1;
738 }
739 void arm_irq_interrupt_deassert(struct interrupt *interrupt)
740 {
741 struct cpu *cpu = (struct cpu *) interrupt->extra;
742 cpu->cd.arm.irq_asserted = 0;
743 }
744
745
746 /*
747 * arm_cpu_disassemble_instr():
748 *
749 * Convert an instruction word into human readable format, for instruction
750 * tracing.
751 *
752 * If running is 1, cpu->pc should be the address of the instruction.
753 *
754 * If running is 0, things that depend on the runtime environment (eg.
755 * register contents) will not be shown, and addr will be used instead of
756 * cpu->pc for relative addresses.
757 */
758 int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
759 int running, uint64_t dumpaddr)
760 {
761 uint32_t iw, tmp;
762 int main_opcode, secondary_opcode, s_bit, r16, r12, r8;
763 int i, n, p_bit, u_bit, b_bit, w_bit, l_bit;
764 char *symbol, *condition;
765 uint64_t offset;
766
767 if (running)
768 dumpaddr = cpu->pc;
769
770 symbol = get_symbol_name(&cpu->machine->symbol_context,
771 dumpaddr, &offset);
772 if (symbol != NULL && offset == 0)
773 debug("<%s>\n", symbol);
774
775 if (cpu->machine->ncpus > 1 && running)
776 debug("cpu%i:\t", cpu->cpu_id);
777
778 debug("%08x: ", (int)dumpaddr);
779
780 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
781 iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
782 else
783 iw = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
784 debug("%08x\t", (int)iw);
785
786 condition = arm_condition_string[iw >> 28];
787 main_opcode = (iw >> 24) & 15;
788 secondary_opcode = (iw >> 21) & 15;
789 u_bit = (iw >> 23) & 1;
790 b_bit = (iw >> 22) & 1;
791 w_bit = (iw >> 21) & 1;
792 s_bit = l_bit = (iw >> 20) & 1;
793 r16 = (iw >> 16) & 15;
794 r12 = (iw >> 12) & 15;
795 r8 = (iw >> 8) & 15;
796
797 switch (main_opcode) {
798 case 0x0:
799 case 0x1:
800 case 0x2:
801 case 0x3:
802 /*
803 * Special cases first:
804 */
805
806 /*
807 * Multiplication:
808 * xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd, Rm, Rs [,Rn])
809 */
810 if ((iw & 0x0fc000f0) == 0x00000090) {
811 int a_bit = (iw >> 21) & 1;
812 debug("%s%s%s\t", a_bit? "mla" : "mul",
813 condition, s_bit? "s" : "");
814 debug("%s,", arm_regname[r16]);
815 debug("%s,", arm_regname[iw & 15]);
816 debug("%s", arm_regname[r8]);
817 if (a_bit)
818 debug(",%s", arm_regname[r12]);
819 debug("\n");
820 break;
821 }
822
823 /*
824 * Long multiplication:
825 * xxxx0000 1UAShhhh llllssss 1001mmmm (Rl,Rh,Rm,Rs)
826 */
827 if ((iw & 0x0f8000f0) == 0x00800090) {
828 int u_bit = (iw >> 22) & 1;
829 int a_bit = (iw >> 21) & 1;
830 debug("%s%sl%s%s\t", u_bit? "s" : "u",
831 a_bit? "mla" : "mul", condition, s_bit? "s" : "");
832 debug("%s,%s,", arm_regname[r12], arm_regname[r16]);
833 debug("%s,%s\n", arm_regname[iw&15], arm_regname[r8]);
834 break;
835 }
836
837 /*
838 * xxxx0001 0000nnnn dddd0000 0101mmmm qadd Rd,Rm,Rn
839 * xxxx0001 0010nnnn dddd0000 0101mmmm qsub Rd,Rm,Rn
840 * xxxx0001 0100nnnn dddd0000 0101mmmm qdadd Rd,Rm,Rn
841 * xxxx0001 0110nnnn dddd0000 0101mmmm qdsub Rd,Rm,Rn
842 */
843 if ((iw & 0x0f900ff0) == 0x01000050) {
844 debug("q%s%s%s\t", iw & 0x400000? "d" : "",
845 iw & 0x200000? "sub" : "add", condition);
846 debug("%s,%s,%s\n", arm_regname[r12],
847 arm_regname[iw&15], arm_regname[r16]);
848 break;
849 }
850
851 /*
852 * xxxx0001 0010.... ........ 00L1mmmm bx/blx rm
853 */
854 if ((iw & 0x0ff000d0) == 0x01200010) {
855 int l_bit = iw & 0x20;
856 debug("b%sx%s\t%s\n", l_bit? "l" : "", condition,
857 arm_regname[iw & 15]);
858 break;
859 }
860
861 /*
862 * xxxx0001 0s10aaaa 11110000 0000mmmm MSR Regform
863 * xxxx0011 0s10aaaa 1111rrrr bbbbbbbb MSR Immform
864 * xxxx0001 0s001111 dddd0000 00000000 MRS
865 */
866 if ((iw & 0x0fb0fff0) == 0x0120f000 ||
867 (iw & 0x0fb0f000) == 0x0320f000) {
868 int a = (iw >> 16) & 15;
869 debug("msr%s\t%s", condition, (iw&0x400000)? "S":"C");
870 debug("PSR_");
871 switch (a) {
872 case 1: debug("ctl"); break;
873 case 8: debug("flg"); break;
874 case 9: debug("all"); break;
875 default:debug(" UNIMPLEMENTED (a=%i)", a);
876 }
877 if (iw & 0x02000000) {
878 int r = (iw >> 7) & 30;
879 uint32_t b = iw & 0xff;
880 while (r-- > 0)
881 b = (b >> 1) | ((b & 1) << 31);
882 debug(",#0x%x\n", b);
883 } else
884 debug(",%s\n", arm_regname[iw & 15]);
885 break;
886 }
887 if ((iw & 0x0fbf0fff) == 0x010f0000) {
888 debug("mrs%s\t", condition);
889 debug("%s,%sPSR\n", arm_regname[r12],
890 (iw&0x400000)? "S":"C");
891 break;
892 }
893
894 /*
895 * xxxx0001 0B00nnnn dddd0000 1001mmmm SWP Rd,Rm,[Rn]
896 */
897 if ((iw & 0x0fb00ff0) == 0x01000090) {
898 debug("swp%s%s\t", condition, (iw&0x400000)? "b":"");
899 debug("%s,%s,[%s]\n", arm_regname[r12],
900 arm_regname[iw & 15], arm_regname[r16]);
901 break;
902 }
903
904 /*
905 * xxxx0001 01101111 dddd1111 0001mmmm CLZ Rd,Rm
906 */
907 if ((iw & 0x0fff0ff0) == 0x016f0f10) {
908 debug("clz%s\t", condition);
909 debug("%s,%s\n", arm_regname[r12], arm_regname[iw&15]);
910 break;
911 }
912
913 /*
914 * xxxx0001 0000dddd nnnnssss 1yx0mmmm SMLAxy Rd,Rm,Rs,Rn
915 * xxxx0001 0100dddd DDDDssss 1yx0mmmm SMLALxy RdL,RdH,Rm,Rs
916 * xxxx0001 0010dddd nnnnssss 1y00mmmm SMLAWy Rd,Rm,Rs,Rn
917 * xxxx0001 0110dddd 0000ssss 1yx0mmmm SMULxy Rd,Rm,Rs
918 * xxxx0001 0010dddd 0000ssss 1y10mmmm SMULWy Rd,Rm,Rs
919 */
920 if ((iw & 0x0ff00090) == 0x01000080) {
921 debug("smla%s%s%s\t",
922 iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
923 condition);
924 debug("%s,%s,%s,%s\n", arm_regname[r16],
925 arm_regname[iw&15], arm_regname[r8],
926 arm_regname[r12]);
927 break;
928 }
929 if ((iw & 0x0ff00090) == 0x01400080) {
930 debug("smlal%s%s%s\t",
931 iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
932 condition);
933 debug("%s,%s,%s,%s\n", arm_regname[r12],
934 arm_regname[r16], arm_regname[iw&15],
935 arm_regname[r8]);
936 break;
937 }
938 if ((iw & 0x0ff000b0) == 0x01200080) {
939 debug("smlaw%s%s\t", iw & 0x40? "t" : "b",
940 condition);
941 debug("%s,%s,%s,%s\n", arm_regname[r16],
942 arm_regname[iw&15], arm_regname[r8],
943 arm_regname[r12]);
944 break;
945 }
946 if ((iw & 0x0ff0f090) == 0x01600080) {
947 debug("smul%s%s%s\t",
948 iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
949 condition);
950 debug("%s,%s,%s\n", arm_regname[r16],
951 arm_regname[iw&15], arm_regname[r8]);
952 break;
953 }
954 if ((iw & 0x0ff0f0b0) == 0x012000a0) {
955 debug("smulw%s%s\t", iw & 0x40? "t" : "b",
956 condition);
957 debug("%s,%s,%s\n", arm_regname[r16],
958 arm_regname[iw&15], arm_regname[r8]);
959 break;
960 }
961
962 /*
963 * xxxx000P U1WLnnnn ddddHHHH 1SH1LLLL load/store rd,imm(rn)
964 */
965 if ((iw & 0x0e000090) == 0x00000090) {
966 char *op = "st";
967 int imm = ((iw >> 4) & 0xf0) | (iw & 0xf);
968 int regform = !(iw & 0x00400000);
969 p_bit = main_opcode & 1;
970 /*
971 * TODO: detect some illegal variants:
972 * signed store, or unsigned byte load/store
973 */
974 if (!l_bit && (iw & 0xd0) == 0xd0 && (r12 & 1)) {
975 debug("TODO: r12 odd, not load/store\n");
976 break;
977 }
978 /* Semi-generic case: */
979 if (iw & 0x00100000)
980 op = "ld";
981 if (!l_bit && (iw & 0xd0) == 0xd0)
982 op = iw & 0x20? "st" : "ld";
983 debug("%sr%s", op, condition);
984 if (!l_bit && (iw & 0xd0) == 0xd0) {
985 debug("d"); /* Double-register */
986 } else {
987 if (iw & 0x40)
988 debug("s"); /* signed */
989 if (iw & 0x20)
990 debug("h"); /* half-word */
991 else
992 debug("b"); /* byte */
993 }
994 debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
995 if (p_bit) {
996 /* Pre-index: */
997 if (regform)
998 debug(",%s%s", u_bit? "" : "-",
999 arm_regname[iw & 15]);
1000 else {
1001 if (imm != 0)
1002 debug(",#%s%i", u_bit? "" : "-",
1003 imm);
1004 }
1005 debug("]%s\n", w_bit? "!" : "");
1006 } else {
1007 /* Post-index: */
1008 debug("],");
1009 if (regform)
1010 debug("%s%s\n", u_bit? "" : "-",
1011 arm_regname[iw & 15]);
1012 else
1013 debug("#%s%i\n", u_bit? "" : "-", imm);
1014 }
1015 break;
1016 }
1017
1018 /* Other special cases: */
1019 if (iw & 0x80 && !(main_opcode & 2) && iw & 0x10) {
1020 debug("UNIMPLEMENTED reg (c!=0), t odd\n");
1021 break;
1022 }
1023
1024 /*
1025 * Generic Data Processing Instructions:
1026 *
1027 * xxxx000a aaaSnnnn ddddcccc ctttmmmm Register form
1028 * xxxx001a aaaSnnnn ddddrrrr bbbbbbbb Immediate form
1029 */
1030
1031 debug("%s%s%s\t", arm_dpiname[secondary_opcode],
1032 condition, s_bit? "s" : "");
1033 if (arm_dpi_uses_d[secondary_opcode])
1034 debug("%s,", arm_regname[r12]);
1035 if (arm_dpi_uses_n[secondary_opcode])
1036 debug("%s,", arm_regname[r16]);
1037
1038 if (main_opcode & 2) {
1039 /* Immediate form: */
1040 int r = (iw >> 7) & 30;
1041 uint32_t b = iw & 0xff;
1042 while (r-- > 0)
1043 b = (b >> 1) | ((b & 1) << 31);
1044 if (b < 15)
1045 debug("#%i", b);
1046 else
1047 debug("#0x%x", b);
1048 } else {
1049 /* Register form: */
1050 int t = (iw >> 4) & 7;
1051 int c = (iw >> 7) & 31;
1052 debug("%s", arm_regname[iw & 15]);
1053 switch (t) {
1054 case 0: if (c != 0)
1055 debug(", lsl #%i", c);
1056 break;
1057 case 1: debug(", lsl %s", arm_regname[c >> 1]);
1058 break;
1059 case 2: debug(", lsr #%i", c? c : 32);
1060 break;
1061 case 3: debug(", lsr %s", arm_regname[c >> 1]);
1062 break;
1063 case 4: debug(", asr #%i", c? c : 32);
1064 break;
1065 case 5: debug(", asr %s", arm_regname[c >> 1]);
1066 break;
1067 case 6: if (c != 0)
1068 debug(", ror #%i", c);
1069 else
1070 debug(", rrx");
1071 break;
1072 case 7: debug(", ror %s", arm_regname[c >> 1]);
1073 break;
1074 }
1075
1076 /* mov pc,reg: */
1077 if (running && t == 0 && c == 0 && secondary_opcode
1078 == 0xd && r12 == ARM_PC && (iw&15)!=ARM_PC) {
1079 symbol = get_symbol_name(&cpu->machine->
1080 symbol_context, cpu->cd.arm.r[iw & 15],
1081 &offset);
1082 if (symbol != NULL)
1083 debug(" \t<%s>", symbol);
1084 }
1085 }
1086 debug("\n");
1087 break;
1088 case 0x4: /* Single Data Transfer */
1089 case 0x5:
1090 case 0x6:
1091 case 0x7:
1092 /* Special case first: */
1093 if ((iw & 0xfc70f000) == 0xf450f000) {
1094 /* Preload: */
1095 debug("pld\t[%s]\n", arm_regname[r16]);
1096 break;
1097 }
1098
1099 /*
1100 * xxxx010P UBWLnnnn ddddoooo oooooooo Immediate form
1101 * xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form
1102 */
1103 p_bit = main_opcode & 1;
1104 if (main_opcode >= 6 && iw & 0x10) {
1105 debug("TODO: single data transf. but 0x10\n");
1106 break;
1107 }
1108 debug("%s%s%s", l_bit? "ldr" : "str",
1109 condition, b_bit? "b" : "");
1110 if (!p_bit && w_bit)
1111 debug("t");
1112 debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
1113 if ((iw & 0x0e000000) == 0x04000000) {
1114 /* Immediate form: */
1115 uint32_t imm = iw & 0xfff;
1116 if (!p_bit)
1117 debug("]");
1118 if (imm != 0)
1119 debug(",#%s%i", u_bit? "" : "-", imm);
1120 if (p_bit)
1121 debug("]");
1122 } else if ((iw & 0x0e000010) == 0x06000000) {
1123 /* Register form: */
1124 if (!p_bit)
1125 debug("]");
1126 if ((iw & 0xfff) != 0)
1127 debug(",%s%s", u_bit? "" : "-",
1128 arm_regname[iw & 15]);
1129 if ((iw & 0xff0) != 0x000) {
1130 int c = (iw >> 7) & 31;
1131 int t = (iw >> 4) & 7;
1132 switch (t) {
1133 case 0: if (c != 0)
1134 debug(", lsl #%i", c);
1135 break;
1136 case 2: debug(", lsr #%i", c? c : 32);
1137 break;
1138 case 4: debug(", asr #%i", c? c : 32);
1139 break;
1140 case 6: if (c != 0)
1141 debug(", ror #%i", c);
1142 else
1143 debug(", rrx");
1144 break;
1145 }
1146 }
1147 if (p_bit)
1148 debug("]");
1149 } else {
1150 debug("UNKNOWN\n");
1151 break;
1152 }
1153 debug("%s", (p_bit && w_bit)? "!" : "");
1154 if ((iw & 0x0f000000) == 0x05000000 &&
1155 (r16 == ARM_PC || running)) {
1156 unsigned char tmpw[4];
1157 uint32_t imm = iw & 0xfff;
1158 uint32_t addr = (u_bit? imm : -imm);
1159 if (r16 == ARM_PC)
1160 addr += dumpaddr + 8;
1161 else
1162 addr += cpu->cd.arm.r[r16];
1163 symbol = get_symbol_name(&cpu->machine->symbol_context,
1164 addr, &offset);
1165 if (symbol != NULL)
1166 debug(" \t<%s", symbol);
1167 else
1168 debug(" \t<0x%08x", addr);
1169 if ((l_bit && cpu->memory_rw(cpu, cpu->mem, addr, tmpw,
1170 b_bit? 1 : sizeof(tmpw), MEM_READ, NO_EXCEPTIONS))
1171 || (!l_bit && running)) {
1172 if (l_bit) {
1173 if (cpu->byte_order ==
1174 EMUL_LITTLE_ENDIAN)
1175 addr = tmpw[0] +(tmpw[1] << 8) +
1176 (tmpw[2]<<16)+(tmpw[3]<<24);
1177 else
1178 addr = tmpw[3] + (tmpw[2]<<8) +
1179 (tmpw[1]<<16)+(tmpw[0]<<24);
1180 } else {
1181 tmpw[0] = addr = cpu->cd.arm.r[r12];
1182 if (r12 == ARM_PC)
1183 addr = cpu->pc + 8;
1184 }
1185 debug(": ");
1186 if (b_bit)
1187 debug("%i", tmpw[0]);
1188 else {
1189 symbol = get_symbol_name(&cpu->machine->
1190 symbol_context, addr, &offset);
1191 if (symbol != NULL)
1192 debug("%s", symbol);
1193 else if ((int32_t)addr > -256 &&
1194 (int32_t)addr < 256)
1195 debug("%i", addr);
1196 else
1197 debug("0x%x", addr);
1198 }
1199 }
1200 debug(">");
1201 }
1202 debug("\n");
1203 break;
1204 case 0x8: /* Block Data Transfer */
1205 case 0x9:
1206 /* xxxx100P USWLnnnn llllllll llllllll */
1207 p_bit = main_opcode & 1;
1208 s_bit = b_bit;
1209 debug("%s%s", l_bit? "ldm" : "stm", condition);
1210 switch (u_bit * 2 + p_bit) {
1211 case 0: debug("da"); break;
1212 case 1: debug("db"); break;
1213 case 2: debug("ia"); break;
1214 case 3: debug("ib"); break;
1215 }
1216 debug("\t%s", arm_regname[r16]);
1217 if (w_bit)
1218 debug("!");
1219 debug(",{");
1220 n = 0;
1221 for (i=0; i<16; i++)
1222 if ((iw >> i) & 1) {
1223 debug("%s%s", (n > 0)? ",":"", arm_regname[i]);
1224 n++;
1225 }
1226 debug("}");
1227 if (s_bit)
1228 debug("^");
1229 debug("\n");
1230 break;
1231 case 0xa: /* B: branch */
1232 case 0xb: /* BL: branch and link */
1233 debug("b%s%s\t", main_opcode == 0xa? "" : "l", condition);
1234 tmp = (iw & 0x00ffffff) << 2;
1235 if (tmp & 0x02000000)
1236 tmp |= 0xfc000000;
1237 tmp = (int32_t)(dumpaddr + tmp + 8);
1238 debug("0x%x", (int)tmp);
1239 symbol = get_symbol_name(&cpu->machine->symbol_context,
1240 tmp, &offset);
1241 if (symbol != NULL)
1242 debug(" \t<%s>", symbol);
1243 debug("\n");
1244 break;
1245 case 0xc: /* Coprocessor */
1246 case 0xd: /* LDC/STC */
1247 /*
1248 * xxxx1100 0100nnnn ddddcccc oooommmm MCRR c,op,Rd,Rn,CRm
1249 * xxxx1100 0101nnnn ddddcccc oooommmm MRRC c,op,Rd,Rn,CRm
1250 */
1251 if ((iw & 0x0fe00fff) == 0x0c400000) {
1252 debug("%s%s\t", iw & 0x100000? "mra" : "mar",
1253 condition);
1254 if (iw & 0x100000)
1255 debug("%s,%s,acc0\n",
1256 arm_regname[r12], arm_regname[r16]);
1257 else
1258 debug("acc0,%s,%s\n",
1259 arm_regname[r12], arm_regname[r16]);
1260 break;
1261 }
1262 if ((iw & 0x0fe00000) == 0x0c400000) {
1263 debug("%s%s\t", iw & 0x100000? "mrrc" : "mcrr",
1264 condition);
1265 debug("%i,%i,%s,%s,cr%i\n", r8, (iw >> 4) & 15,
1266 arm_regname[r12], arm_regname[r16], iw & 15);
1267 break;
1268 }
1269
1270 /* xxxx110P UNWLnnnn DDDDpppp oooooooo LDC/STC */
1271 debug("TODO: coprocessor LDC/STC\n");
1272 break;
1273 case 0xe: /* CDP (Coprocessor Op) */
1274 /* or MRC/MCR!
1275 * xxxx1110 oooonnnn ddddpppp qqq0mmmm CDP
1276 * xxxx1110 oooLNNNN ddddpppp qqq1MMMM MRC/MCR
1277 */
1278 if ((iw & 0x0ff00ff0) == 0x0e200010) {
1279 /* Special case: mia* DSP instructions */
1280 switch ((iw >> 16) & 0xf) {
1281 case 0: debug("mia"); break;
1282 case 8: debug("miaph"); break;
1283 case 12: debug("miaBB"); break;
1284 case 13: debug("miaTB"); break;
1285 case 14: debug("miaBT"); break;
1286 case 15: debug("miaTT"); break;
1287 default: debug("UNKNOWN mia vector instruction?");
1288 }
1289 debug("%s\t", condition);
1290 debug("acc%i,%s,%s\n", ((iw >> 5) & 7),
1291 arm_regname[iw & 15], arm_regname[r12]);
1292 break;
1293 }
1294 if (iw & 0x10) {
1295 debug("%s%s\t",
1296 (iw & 0x00100000)? "mrc" : "mcr", condition);
1297 debug("%i,%i,r%i,cr%i,cr%i,%i",
1298 (int)((iw >> 8) & 15), (int)((iw >>21) & 7),
1299 (int)((iw >>12) & 15), (int)((iw >>16) & 15),
1300 (int)((iw >> 0) & 15), (int)((iw >> 5) & 7));
1301 } else {
1302 debug("cdp%s\t", condition);
1303 debug("%i,%i,cr%i,cr%i,cr%i",
1304 (int)((iw >> 8) & 15),
1305 (int)((iw >>20) & 15),
1306 (int)((iw >>12) & 15),
1307 (int)((iw >>16) & 15),
1308 (int)((iw >> 0) & 15));
1309 if ((iw >> 5) & 7)
1310 debug(",0x%x", (int)((iw >> 5) & 7));
1311 }
1312 debug("\n");
1313 break;
1314 case 0xf: /* SWI */
1315 debug("swi%s\t", condition);
1316 debug("0x%x\n", (int)(iw & 0x00ffffff));
1317 break;
1318 default:debug("UNIMPLEMENTED\n");
1319 }
1320
1321 return sizeof(uint32_t);
1322 }
1323
1324
1325 /*****************************************************************************/
1326
1327
1328 /*
1329 * arm_mcr_mrc():
1330 *
1331 * Coprocessor register move.
1332 *
1333 * The program counter should be synched before calling this function (to
1334 * make debug output with the correct PC value possible).
1335 */
1336 void arm_mcr_mrc(struct cpu *cpu, uint32_t iword)
1337 {
1338 int opcode1 = (iword >> 21) & 7;
1339 int l_bit = (iword >> 20) & 1;
1340 int crn = (iword >> 16) & 15;
1341 int rd = (iword >> 12) & 15;
1342 int cp_num = (iword >> 8) & 15;
1343 int opcode2 = (iword >> 5) & 7;
1344 int crm = iword & 15;
1345
1346 if (cpu->cd.arm.coproc[cp_num] != NULL)
1347 cpu->cd.arm.coproc[cp_num](cpu, opcode1, opcode2, l_bit,
1348 crn, crm, rd);
1349 else {
1350 fatal("[ arm_mcr_mrc: pc=0x%08x, iword=0x%08x: "
1351 "cp_num=%i ]\n", (int)cpu->pc, iword, cp_num);
1352 arm_exception(cpu, ARM_EXCEPTION_UND);
1353 /* exit(1); */
1354 }
1355 }
1356
1357
1358 /*
1359 * arm_cdp():
1360 *
1361 * Coprocessor operations.
1362 *
1363 * The program counter should be synched before calling this function (to
1364 * make debug output with the correct PC value possible).
1365 */
1366 void arm_cdp(struct cpu *cpu, uint32_t iword)
1367 {
1368 fatal("[ arm_cdp: pc=0x%08x, iword=0x%08x ]\n", (int)cpu->pc, iword);
1369 arm_exception(cpu, ARM_EXCEPTION_UND);
1370 /* exit(1); */
1371 }
1372
1373
1374 /*****************************************************************************/
1375
1376
1377 #include "tmp_arm_tail.c"
1378

  ViewVC Help
Powered by ViewVC 1.1.26