1 /*
2 * Copyright (C) 2005-2019 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 * ARM CPU emulation.
29 *
30 * A good source of quick info on ARM instruction encoding:
31 * http://www.pinknoise.demon.co.uk/ARMinstrs/ARMinstrs.html
32 *
33 * Another one, with details about THUMB:
34 * http://engold.ui.ac.ir/~nikmehr/Appendix_B2.pdf
35 *
36 * and yet another one, with descriptions about THUMB semantics:
37 * https://web.eecs.umich.edu/~prabal/teaching/eecs373-f10/readings/ARM_QRC0006_UAL16.pdf
38 *
39 * And one with the newer ARM v7 instructions:
40 * http://vision.gel.ulaval.ca/~jflalonde/cours/1001/h17/docs/ARM_v7.pdf
41 */
42
43 #include <stdio.h>
44 #include <stdlib.h>
45 #include <string.h>
46 #include <ctype.h>
47 #include <unistd.h>
48
49 #include "arm_cpu_types.h"
50 #include "cpu.h"
51 #include "interrupt.h"
52 #include "machine.h"
53 #include "memory.h"
54 #include "misc.h"
55 #include "of.h"
56 #include "settings.h"
57 #include "symbol.h"
58
59 #define DYNTRANS_32
60 #include "tmp_arm_head.cc"
61
62
63 /* ARM symbolic register names and condition strings: */
64 static const char *arm_regname[N_ARM_REGS] = ARM_REG_NAMES;
65 static const char *arm_condition_string[16] = ARM_CONDITION_STRINGS;
66
67 /* Data Processing Instructions: */
68 static const char *arm_dpiname[16] = ARM_DPI_NAMES;
69 static int arm_dpi_uses_d[16] = { 1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1 };
70 static int arm_dpi_uses_n[16] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0 };
71
72 static const char *arm_thumb_dpiname[16] = ARM_THUMB_DPI_NAMES;
73
74 static int arm_exception_to_mode[N_ARM_EXCEPTIONS] = ARM_EXCEPTION_TO_MODE;
75
76 extern uint8_t condition_hi[16];
77 extern uint8_t condition_ge[16];
78 extern uint8_t condition_gt[16];
79
80 /* For quick_pc_to_pointers(): */
81 void arm_pc_to_pointers(struct cpu *cpu);
82 #include "quick_pc_to_pointers.h"
83
84 void arm_irq_interrupt_assert(struct interrupt *interrupt);
85 void arm_irq_interrupt_deassert(struct interrupt *interrupt);
86
87
88 /*
89 * arm_cpu_new():
90 *
91 * Create a new ARM cpu object by filling the CPU struct.
92 * Return 1 on success, 0 if cpu_type_name isn't a valid ARM processor.
93 */
arm_cpu_new(struct cpu * cpu,struct memory * mem,struct machine * machine,int cpu_id,char * cpu_type_name)94 int arm_cpu_new(struct cpu *cpu, struct memory *mem,
95 struct machine *machine, int cpu_id, char *cpu_type_name)
96 {
97 int i, found;
98 struct arm_cpu_type_def cpu_type_defs[] = ARM_CPU_TYPE_DEFS;
99
100 /* Scan the list for this cpu type: */
101 i = 0; found = -1;
102 while (i >= 0 && cpu_type_defs[i].name != NULL) {
103 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
104 found = i;
105 break;
106 }
107 i++;
108 }
109 if (found == -1)
110 return 0;
111
112 cpu->run_instr = arm_run_instr;
113 cpu->memory_rw = arm_memory_rw;
114 cpu->update_translation_table = arm_update_translation_table;
115 cpu->invalidate_translation_caches =
116 arm_invalidate_translation_caches;
117 cpu->invalidate_code_translation = arm_invalidate_code_translation;
118 cpu->translate_v2p = arm_translate_v2p;
119
120 cpu->cd.arm.cpu_type = cpu_type_defs[found];
121 cpu->name = strdup(cpu->cd.arm.cpu_type.name);
122 cpu->is_32bit = 1;
123 cpu->byte_order = EMUL_LITTLE_ENDIAN;
124
125 cpu->vaddr_mask = 0x00000000ffffffffULL;
126
127 cpu->cd.arm.cpsr = ARM_FLAG_I | ARM_FLAG_F;
128 cpu->cd.arm.control = ARM_CONTROL_PROG32 | ARM_CONTROL_DATA32
129 | ARM_CONTROL_CACHE | ARM_CONTROL_ICACHE | ARM_CONTROL_ALIGN;
130 /* TODO: default auxctrl contents */
131
132 if (cpu->machine->prom_emulation) {
133 cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
134 cpu->cd.arm.control |= ARM_CONTROL_S;
135 } else {
136 cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
137 cpu->cd.arm.control |= ARM_CONTROL_R;
138 }
139
140 /* Only show name and caches etc for CPU nr 0: */
141 if (cpu_id == 0) {
142 debug("%s", cpu->name);
143 if (cpu->cd.arm.cpu_type.icache_shift != 0 ||
144 cpu->cd.arm.cpu_type.dcache_shift != 0) {
145 int isize = cpu->cd.arm.cpu_type.icache_shift;
146 int dsize = cpu->cd.arm.cpu_type.dcache_shift;
147 if (isize != 0)
148 isize = 1 << (isize - 10);
149 if (dsize != 0)
150 dsize = 1 << (dsize - 10);
151 debug(" (I+D = %i+%i KB)", isize, dsize);
152 }
153 }
154
155 /* TODO: Some of these values (iway and dway) aren't used yet: */
156 cpu->cd.arm.cachetype =
157 (5 << ARM_CACHETYPE_CLASS_SHIFT)
158 | (1 << ARM_CACHETYPE_HARVARD_SHIFT)
159 | ((cpu->cd.arm.cpu_type.dcache_shift - 9) <<
160 ARM_CACHETYPE_DSIZE_SHIFT)
161 | (5 << ARM_CACHETYPE_DASSOC_SHIFT) /* 32-way */
162 | (2 << ARM_CACHETYPE_DLINE_SHIFT) /* 8 words/line */
163 | ((cpu->cd.arm.cpu_type.icache_shift - 9) <<
164 ARM_CACHETYPE_ISIZE_SHIFT)
165 | (5 << ARM_CACHETYPE_IASSOC_SHIFT) /* 32-way */
166 | (2 << ARM_CACHETYPE_ILINE_SHIFT); /* 8 words/line */
167
168 /* Coprocessor 15 = the system control coprocessor. */
169 cpu->cd.arm.coproc[15] = arm_coproc_15;
170
171 /* Coprocessor 14 for XScale: */
172 if (cpu->cd.arm.cpu_type.flags & ARM_XSCALE)
173 cpu->cd.arm.coproc[14] = arm_coproc_xscale_14;
174
175 /*
176 * NOTE/TODO: Ugly hack for OpenFirmware emulation:
177 */
178 if (cpu->machine->prom_emulation) {
179 cpu->cd.arm.of_emul_addr = cpu->machine->physical_ram_in_mb
180 * 1048576 - 8;
181 store_32bit_word(cpu, cpu->cd.arm.of_emul_addr, 0xef8c64be);
182 }
183
184 cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
185
186 CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
187 for (i=0; i<N_ARM_REGS - 1; i++)
188 CPU_SETTINGS_ADD_REGISTER32(arm_regname[i], cpu->cd.arm.r[i]);
189
190 CPU_SETTINGS_ADD_REGISTER32("cpsr", cpu->cd.arm.cpsr);
191
192 /* Register the CPU's "IRQ" and "FIQ" interrupts: */
193 {
194 struct interrupt templ;
195 char name[50];
196 snprintf(name, sizeof(name), "%s.irq", cpu->path);
197
198 memset(&templ, 0, sizeof(templ));
199 templ.line = 0;
200 templ.name = name;
201 templ.extra = cpu;
202 templ.interrupt_assert = arm_irq_interrupt_assert;
203 templ.interrupt_deassert = arm_irq_interrupt_deassert;
204 interrupt_handler_register(&templ);
205
206 /* FIQ: TODO */
207 }
208
209 return 1;
210 }
211
212
213 /*
214 * arm_setup_initial_translation_table():
215 *
216 * When booting kernels (such as OpenBSD or NetBSD) directly, it is assumed
217 * that the MMU is already enabled by the boot-loader. This function tries
218 * to emulate that.
219 */
arm_setup_initial_translation_table(struct cpu * cpu,uint32_t ttb_addr)220 void arm_setup_initial_translation_table(struct cpu *cpu, uint32_t ttb_addr)
221 {
222 unsigned char nothing[16384];
223 unsigned int i, j;
224
225 cpu->cd.arm.control |= ARM_CONTROL_MMU;
226 cpu->translate_v2p = arm_translate_v2p_mmu;
227 cpu->cd.arm.dacr |= 0x00000003;
228 cpu->cd.arm.ttb = ttb_addr;
229
230 memset(nothing, 0, sizeof(nothing));
231 cpu->memory_rw(cpu, cpu->mem, cpu->cd.arm.ttb, nothing,
232 sizeof(nothing), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
233 for (i=0; i<256; i++)
234 for (j=0x0; j<=0xf; j++) {
235 unsigned char descr[4];
236 uint32_t addr = cpu->cd.arm.ttb +
237 (((j << 28) + (i << 20)) >> 18);
238 uint32_t d = (1048576*i) | 0xc02;
239
240 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
241 descr[0] = d; descr[1] = d >> 8;
242 descr[2] = d >> 16; descr[3] = d >> 24;
243 } else {
244 descr[3] = d; descr[2] = d >> 8;
245 descr[1] = d >> 16; descr[0] = d >> 24;
246 }
247 cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
248 sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
249 }
250 }
251
252
253 /*
254 * arm_translation_table_set_l1():
255 */
arm_translation_table_set_l1(struct cpu * cpu,uint32_t vaddr,uint32_t paddr)256 void arm_translation_table_set_l1(struct cpu *cpu, uint32_t vaddr,
257 uint32_t paddr)
258 {
259 unsigned int i, j, vhigh = vaddr >> 28, phigh = paddr >> 28;
260
261 for (i=0; i<256; i++)
262 for (j=vhigh; j<=vhigh; j++) {
263 unsigned char descr[4];
264 uint32_t addr = cpu->cd.arm.ttb +
265 (((j << 28) + (i << 20)) >> 18);
266 uint32_t d = ((phigh << 28) + 1048576*i) | 0xc02;
267
268 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
269 descr[0] = d; descr[1] = d >> 8;
270 descr[2] = d >> 16; descr[3] = d >> 24;
271 } else {
272 descr[3] = d; descr[2] = d >> 8;
273 descr[1] = d >> 16; descr[0] = d >> 24;
274 }
275 cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
276 sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
277 }
278 }
279
280
281 /*
282 * arm_translation_table_set_l1_b():
283 */
arm_translation_table_set_l1_b(struct cpu * cpu,uint32_t vaddr,uint32_t paddr)284 void arm_translation_table_set_l1_b(struct cpu *cpu, uint32_t vaddr,
285 uint32_t paddr)
286 {
287 unsigned int i, j, vhigh = vaddr >> 24, phigh = paddr >> 24;
288
289 for (i=0; i<16; i++)
290 for (j=vhigh; j<=vhigh; j++) {
291 unsigned char descr[4];
292 uint32_t addr = cpu->cd.arm.ttb +
293 (((j << 24) + (i << 20)) >> 18);
294 uint32_t d = ((phigh << 24) + 1048576*i) | 0xc02;
295
296 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
297 descr[0] = d; descr[1] = d >> 8;
298 descr[2] = d >> 16; descr[3] = d >> 24;
299 } else {
300 descr[3] = d; descr[2] = d >> 8;
301 descr[1] = d >> 16; descr[0] = d >> 24;
302 }
303 cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
304 sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
305 }
306 }
307
308
309 /*
310 * arm_cpu_dumpinfo():
311 */
arm_cpu_dumpinfo(struct cpu * cpu)312 void arm_cpu_dumpinfo(struct cpu *cpu)
313 {
314 struct arm_cpu_type_def *ct = &cpu->cd.arm.cpu_type;
315
316 debug(" (I+D = %i+%i KB)\n",
317 (1 << ct->icache_shift) / 1024, (1 << ct->dcache_shift) / 1024);
318 }
319
320
321 /*
322 * arm_cpu_list_available_types():
323 *
324 * Print a list of available ARM CPU types.
325 */
arm_cpu_list_available_types(void)326 void arm_cpu_list_available_types(void)
327 {
328 int i, j;
329 struct arm_cpu_type_def tdefs[] = ARM_CPU_TYPE_DEFS;
330
331 i = 0;
332 while (tdefs[i].name != NULL) {
333 debug("%s", tdefs[i].name);
334 for (j=13 - strlen(tdefs[i].name); j>0; j--)
335 debug(" ");
336 i++;
337 if ((i % 5) == 0 || tdefs[i].name == NULL)
338 debug("\n");
339 }
340 }
341
342
343 /*
344 * arm_cpu_register_dump():
345 *
346 * Dump cpu registers in a relatively readable format.
347 *
348 * gprs: set to non-zero to dump GPRs and some special-purpose registers.
349 * coprocs: set bit 0..3 to dump registers in coproc 0..3.
350 */
arm_cpu_register_dump(struct cpu * cpu,int gprs,int coprocs)351 void arm_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
352 {
353 char *symbol;
354 uint64_t offset;
355 int mode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
356 int i, x = cpu->cpu_id;
357
358 cpu->cd.arm.cpsr &= 0x0fffffff;
359 cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
360
361 if (gprs) {
362 symbol = get_symbol_name(&cpu->machine->symbol_context,
363 cpu->pc, &offset);
364 debug("cpu%i: cpsr = ", x);
365 debug("%s%s%s%s%s%s%s%s%s%s%s",
366 (cpu->cd.arm.cpsr & ARM_FLAG_N)? "N" : "n",
367 (cpu->cd.arm.cpsr & ARM_FLAG_Z)? "Z" : "z",
368 (cpu->cd.arm.cpsr & ARM_FLAG_C)? "C" : "c",
369 (cpu->cd.arm.cpsr & ARM_FLAG_V)? "V" : "v",
370 (cpu->cd.arm.cpsr & ARM_FLAG_Q)? "Q" : "q",
371 (cpu->cd.arm.cpsr & ARM_FLAG_J)? "J" : "j",
372 (cpu->cd.arm.cpsr & ARM_FLAG_E)? "E" : "e",
373 (cpu->cd.arm.cpsr & ARM_FLAG_A)? "A" : "a",
374 (cpu->cd.arm.cpsr & ARM_FLAG_I)? "I" : "i",
375 (cpu->cd.arm.cpsr & ARM_FLAG_F)? "F" : "f",
376 (cpu->cd.arm.cpsr & ARM_FLAG_T)? "T" : "t");
377 if (mode < ARM_MODE_USR32)
378 debug(" pc = 0x%07x", (int)(cpu->pc & 0x03ffffff));
379 else
380 debug(" pc = 0x%08x", (int)cpu->pc);
381
382 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
383
384 for (i=0; i<N_ARM_REGS; i++) {
385 if ((i % 4) == 0)
386 debug("cpu%i:", x);
387 if (i != ARM_PC)
388 debug(" %s = 0x%08x", arm_regname[i],
389 (int)cpu->cd.arm.r[i]);
390 if ((i % 4) == 3)
391 debug("\n");
392 }
393 }
394
395 if (coprocs & 1) {
396 int m = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
397 debug("cpu%i: cpsr = 0x%08x (", x, cpu->cd.arm.cpsr);
398 switch (m) {
399 case ARM_MODE_USR32:
400 debug("USR32)\n"); break;
401 case ARM_MODE_SYS32:
402 debug("SYS32)\n"); break;
403 case ARM_MODE_FIQ32:
404 debug("FIQ32)\n"); break;
405 case ARM_MODE_IRQ32:
406 debug("IRQ32)\n"); break;
407 case ARM_MODE_SVC32:
408 debug("SVC32)\n"); break;
409 case ARM_MODE_ABT32:
410 debug("ABT32)\n"); break;
411 case ARM_MODE_UND32:
412 debug("UND32)\n"); break;
413 default:debug("unimplemented)\n");
414 }
415
416 if (m != ARM_MODE_USR32 && m != ARM_MODE_SYS32) {
417 debug("cpu%i: usr r8-14:", x);
418 for (i=0; i<7; i++)
419 debug(" %08x", cpu->cd.arm.default_r8_r14[i]);
420 debug("\n");
421 }
422
423 if (m != ARM_MODE_FIQ32) {
424 debug("cpu%i: fiq r8-14:", x);
425 for (i=0; i<7; i++)
426 debug(" %08x", cpu->cd.arm.fiq_r8_r14[i]);
427 debug("\n");
428 }
429
430 if (m != ARM_MODE_IRQ32) {
431 debug("cpu%i: irq r13-14:", x);
432 for (i=0; i<2; i++)
433 debug(" %08x", cpu->cd.arm.irq_r13_r14[i]);
434 debug("\n");
435 }
436
437 if (m != ARM_MODE_SVC32) {
438 debug("cpu%i: svc r13-14:", x);
439 for (i=0; i<2; i++)
440 debug(" %08x", cpu->cd.arm.svc_r13_r14[i]);
441 debug("\n");
442 }
443
444 if (m != ARM_MODE_ABT32) {
445 debug("cpu%i: abt r13-14:", x);
446 for (i=0; i<2; i++)
447 debug(" %08x", cpu->cd.arm.abt_r13_r14[i]);
448 debug("\n");
449 }
450
451 if (m != ARM_MODE_UND32) {
452 debug("cpu%i: und r13-14:", x);
453 for (i=0; i<2; i++)
454 debug(" %08x", cpu->cd.arm.und_r13_r14[i]);
455 debug("\n");
456 }
457 }
458
459 if (coprocs & 2) {
460 debug("cpu%i: control = 0x%08x\n", x, cpu->cd.arm.control);
461 debug("cpu%i: MMU: %s\n", x,
462 cpu->cd.arm.control &
463 ARM_CONTROL_MMU? "enabled" : "disabled");
464 debug("cpu%i: alignment checks: %s\n", x,
465 cpu->cd.arm.control &
466 ARM_CONTROL_ALIGN? "enabled" : "disabled");
467 debug("cpu%i: [data] cache: %s\n", x,
468 cpu->cd.arm.control &
469 ARM_CONTROL_CACHE? "enabled" : "disabled");
470 debug("cpu%i: instruction cache: %s\n", x,
471 cpu->cd.arm.control &
472 ARM_CONTROL_ICACHE? "enabled" : "disabled");
473 debug("cpu%i: write buffer: %s\n", x,
474 cpu->cd.arm.control &
475 ARM_CONTROL_WBUFFER? "enabled" : "disabled");
476 debug("cpu%i: prog32: %s\n", x,
477 cpu->cd.arm.control &
478 ARM_CONTROL_PROG32? "yes" : "no (using prog26)");
479 debug("cpu%i: data32: %s\n", x,
480 cpu->cd.arm.control &
481 ARM_CONTROL_DATA32? "yes" : "no (using data26)");
482 debug("cpu%i: endianness: %s\n", x,
483 cpu->cd.arm.control &
484 ARM_CONTROL_BIG? "big endian" : "little endian");
485 debug("cpu%i: high vectors: %s\n", x,
486 cpu->cd.arm.control &
487 ARM_CONTROL_V? "yes (0xffff0000)" : "no");
488
489 /* TODO: auxctrl on which CPU types? */
490 if (cpu->cd.arm.cpu_type.flags & ARM_XSCALE) {
491 debug("cpu%i: auxctrl = 0x%08x\n", x,
492 cpu->cd.arm.auxctrl);
493 debug("cpu%i: minidata cache attr = 0x%x\n", x,
494 (cpu->cd.arm.auxctrl & ARM_AUXCTRL_MD)
495 >> ARM_AUXCTRL_MD_SHIFT);
496 debug("cpu%i: page table memory attr: %i\n", x,
497 (cpu->cd.arm.auxctrl & ARM_AUXCTRL_P)? 1 : 0);
498 debug("cpu%i: write buffer coalescing: %s\n", x,
499 (cpu->cd.arm.auxctrl & ARM_AUXCTRL_K)?
500 "disabled" : "enabled");
501 }
502
503 debug("cpu%i: ttb = 0x%08x dacr = 0x%08x\n", x,
504 cpu->cd.arm.ttb, cpu->cd.arm.dacr);
505 debug("cpu%i: fsr = 0x%08x far = 0x%08x\n", x,
506 cpu->cd.arm.fsr, cpu->cd.arm.far);
507 }
508 }
509
510
511 /*
512 * arm_save_register_bank():
513 */
arm_save_register_bank(struct cpu * cpu)514 void arm_save_register_bank(struct cpu *cpu)
515 {
516 /* Save away current registers: */
517 switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
518 case ARM_MODE_USR32:
519 case ARM_MODE_SYS32:
520 memcpy(cpu->cd.arm.default_r8_r14,
521 &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
522 break;
523 case ARM_MODE_FIQ32:
524 memcpy(cpu->cd.arm.fiq_r8_r14,
525 &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
526 break;
527 case ARM_MODE_IRQ32:
528 memcpy(cpu->cd.arm.default_r8_r14,
529 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
530 cpu->cd.arm.irq_r13_r14[0] = cpu->cd.arm.r[13];
531 cpu->cd.arm.irq_r13_r14[1] = cpu->cd.arm.r[14];
532 break;
533 case ARM_MODE_SVC32:
534 memcpy(cpu->cd.arm.default_r8_r14,
535 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
536 cpu->cd.arm.svc_r13_r14[0] = cpu->cd.arm.r[13];
537 cpu->cd.arm.svc_r13_r14[1] = cpu->cd.arm.r[14];
538 break;
539 case ARM_MODE_ABT32:
540 memcpy(cpu->cd.arm.default_r8_r14,
541 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
542 cpu->cd.arm.abt_r13_r14[0] = cpu->cd.arm.r[13];
543 cpu->cd.arm.abt_r13_r14[1] = cpu->cd.arm.r[14];
544 break;
545 case ARM_MODE_UND32:
546 memcpy(cpu->cd.arm.default_r8_r14,
547 &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
548 cpu->cd.arm.und_r13_r14[0] = cpu->cd.arm.r[13];
549 cpu->cd.arm.und_r13_r14[1] = cpu->cd.arm.r[14];
550 break;
551 default:fatal("arm_save_register_bank: unimplemented mode %i\n",
552 cpu->cd.arm.cpsr & ARM_FLAG_MODE);
553 exit(1);
554 }
555 }
556
557
558 /*
559 * arm_load_register_bank():
560 */
arm_load_register_bank(struct cpu * cpu)561 void arm_load_register_bank(struct cpu *cpu)
562 {
563 /* Load new registers: */
564 switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
565 case ARM_MODE_USR32:
566 case ARM_MODE_SYS32:
567 memcpy(&cpu->cd.arm.r[8],
568 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 7);
569 break;
570 case ARM_MODE_FIQ32:
571 memcpy(&cpu->cd.arm.r[8], cpu->cd.arm.fiq_r8_r14,
572 sizeof(uint32_t) * 7);
573 break;
574 case ARM_MODE_IRQ32:
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.irq_r13_r14[0];
578 cpu->cd.arm.r[14] = cpu->cd.arm.irq_r13_r14[1];
579 break;
580 case ARM_MODE_SVC32:
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.svc_r13_r14[0];
584 cpu->cd.arm.r[14] = cpu->cd.arm.svc_r13_r14[1];
585 break;
586 case ARM_MODE_ABT32:
587 memcpy(&cpu->cd.arm.r[8],
588 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
589 cpu->cd.arm.r[13] = cpu->cd.arm.abt_r13_r14[0];
590 cpu->cd.arm.r[14] = cpu->cd.arm.abt_r13_r14[1];
591 break;
592 case ARM_MODE_UND32:
593 memcpy(&cpu->cd.arm.r[8],
594 cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
595 cpu->cd.arm.r[13] = cpu->cd.arm.und_r13_r14[0];
596 cpu->cd.arm.r[14] = cpu->cd.arm.und_r13_r14[1];
597 break;
598 default:fatal("arm_load_register_bank: unimplemented mode %i\n",
599 cpu->cd.arm.cpsr & ARM_FLAG_MODE);
600 exit(1);
601 }
602 }
603
604
605 /*
606 * arm_exception():
607 */
arm_exception(struct cpu * cpu,int exception_nr)608 void arm_exception(struct cpu *cpu, int exception_nr)
609 {
610 int oldmode, newmode;
611 uint32_t retaddr;
612
613 if (exception_nr < 0 || exception_nr >= N_ARM_EXCEPTIONS) {
614 fatal("arm_exception(): exception_nr = %i\n", exception_nr);
615 exit(1);
616 }
617
618 retaddr = cpu->pc;
619
620 if (!quiet_mode) {
621 debug("[ arm_exception(): ");
622 switch (exception_nr) {
623 case ARM_EXCEPTION_RESET:
624 fatal("RESET: TODO");
625 break;
626 case ARM_EXCEPTION_UND:
627 debug("UNDEFINED");
628 break;
629 case ARM_EXCEPTION_SWI:
630 debug("SWI");
631 break;
632 case ARM_EXCEPTION_PREF_ABT:
633 debug("PREFETCH ABORT");
634 break;
635 case ARM_EXCEPTION_IRQ:
636 debug("IRQ");
637 break;
638 case ARM_EXCEPTION_FIQ:
639 debug("FIQ");
640 break;
641 case ARM_EXCEPTION_DATA_ABT:
642 debug("DATA ABORT, far=0x%08x fsr=0x%02x",
643 cpu->cd.arm.far, cpu->cd.arm.fsr);
644 break;
645 }
646 debug(" ]\n");
647 }
648
649 switch (exception_nr) {
650 case ARM_EXCEPTION_RESET:
651 cpu->running = 0;
652 fatal("ARM RESET: TODO");
653 exit(1);
654 case ARM_EXCEPTION_DATA_ABT:
655 retaddr += 4;
656 break;
657 }
658
659 retaddr += (cpu->cd.arm.cpsr & ARM_FLAG_T ? 2 : 4);
660
661 arm_save_register_bank(cpu);
662
663 cpu->cd.arm.cpsr &= 0x0fffffff;
664 cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
665
666 switch (arm_exception_to_mode[exception_nr]) {
667 case ARM_MODE_SVC32:
668 cpu->cd.arm.spsr_svc = cpu->cd.arm.cpsr; break;
669 case ARM_MODE_ABT32:
670 cpu->cd.arm.spsr_abt = cpu->cd.arm.cpsr; break;
671 case ARM_MODE_UND32:
672 cpu->cd.arm.spsr_und = cpu->cd.arm.cpsr; break;
673 case ARM_MODE_IRQ32:
674 cpu->cd.arm.spsr_irq = cpu->cd.arm.cpsr; break;
675 case ARM_MODE_FIQ32:
676 cpu->cd.arm.spsr_fiq = cpu->cd.arm.cpsr; break;
677 default:fatal("arm_exception(): unimplemented exception nr\n");
678 exit(1);
679 }
680
681 /*
682 * Disable Thumb mode (because exception handlers always execute
683 * in ARM mode), set the exception mode, and disable interrupts:
684 */
685 cpu->cd.arm.cpsr &= ~ARM_FLAG_T;
686
687 oldmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
688
689 cpu->cd.arm.cpsr &= ~ARM_FLAG_MODE;
690 cpu->cd.arm.cpsr |= arm_exception_to_mode[exception_nr];
691
692 /*
693 * Usually, an exception should change modes (so that saved status
694 * bits don't get lost). However, Linux on ARM seems to use floating
695 * point instructions in the kernel (!), and it emulates those using
696 * its own fp emulation code. This leads to a situation where we
697 * sometimes change from SVC32 to SVC32.
698 */
699 newmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
700 if (oldmode == newmode && oldmode != ARM_MODE_SVC32) {
701 fatal("[ WARNING! Exception caused no mode change? "
702 "mode 0x%02x (pc=0x%x) ]\n", newmode, (int)cpu->pc);
703 /* exit(1); */
704 }
705
706 cpu->cd.arm.cpsr |= ARM_FLAG_I;
707 if (exception_nr == ARM_EXCEPTION_RESET ||
708 exception_nr == ARM_EXCEPTION_FIQ)
709 cpu->cd.arm.cpsr |= ARM_FLAG_F;
710
711 /* Load the new register bank, if we switched: */
712 arm_load_register_bank(cpu);
713
714 /*
715 * Set the return address and new PC.
716 *
717 * NOTE: r[ARM_PC] is also set; see cpu_arm_instr_loadstore.c for
718 * details. (If an exception occurs during a load into the pc
719 * register, the code in that file assumes that the r[ARM_PC]
720 * was changed to the address of the exception handler.)
721 */
722 cpu->cd.arm.r[ARM_LR] = retaddr;
723 cpu->pc = cpu->cd.arm.r[ARM_PC] = exception_nr * 4 +
724 ((cpu->cd.arm.control & ARM_CONTROL_V)? 0xffff0000 : 0);
725 quick_pc_to_pointers(cpu);
726 }
727
728
729 /*
730 * arm_cpu_tlbdump():
731 *
732 * Called from the debugger to dump the TLB in a readable format.
733 * x is the cpu number to dump, or -1 to dump all CPUs.
734 *
735 * If rawflag is nonzero, then the TLB contents isn't formated nicely,
736 * just dumped.
737 */
arm_cpu_tlbdump(struct machine * m,int x,int rawflag)738 void arm_cpu_tlbdump(struct machine *m, int x, int rawflag)
739 {
740 }
741
742
743 /*
744 * arm_irq_interrupt_assert():
745 * arm_irq_interrupt_deassert():
746 */
arm_irq_interrupt_assert(struct interrupt * interrupt)747 void arm_irq_interrupt_assert(struct interrupt *interrupt)
748 {
749 struct cpu *cpu = (struct cpu *) interrupt->extra;
750 cpu->cd.arm.irq_asserted = 1;
751 }
arm_irq_interrupt_deassert(struct interrupt * interrupt)752 void arm_irq_interrupt_deassert(struct interrupt *interrupt)
753 {
754 struct cpu *cpu = (struct cpu *) interrupt->extra;
755 cpu->cd.arm.irq_asserted = 0;
756 }
757
758
759 /*
760 * arm_cpu_disassemble_instr_thumb():
761 *
762 * Like arm_cpu_disassemble_instr below, but for THUMB encodings.
763 * Note that the disassbmly uses regular ARM mnemonics, not "THUMB
764 * assembly language".
765 */
arm_cpu_disassemble_instr_thumb(struct cpu * cpu,unsigned char * ib,int running,uint64_t dumpaddr)766 int arm_cpu_disassemble_instr_thumb(struct cpu *cpu, unsigned char *ib,
767 int running, uint64_t dumpaddr)
768 {
769 uint16_t iw;
770 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
771 iw = ib[0] + (ib[1]<<8);
772 else
773 iw = ib[1] + (ib[0]<<8);
774 debug("%04x \t", (int)iw);
775
776 int main_opcode = (iw >> 12) & 15;
777 int r6 = (iw >> 6) & 7;
778 int rs_rb = (iw >> 3) & 7;
779 int rd = iw & 7;
780 int offset5 = (iw >> 6) & 0x1f;
781 int b_bit = (iw >> 12) & 1;
782 int l_bit = (iw >> 11) & 1;
783 int addsub_op = (iw >> 9) & 1;
784 int addsub_immediate = (iw >> 10) & 1;
785 int op11 = (iw >> 11) & 3;
786 int op10 = (iw >> 10) & 3;
787 int rd8 = (iw >> 8) & 7;
788 int op8 = (iw >> 8) & 3;
789 int h1 = (iw >> 7) & 1;
790 int h2 = (iw >> 6) & 1;
791 int condition_code = (iw >> 8) & 15;
792 const char* condition = arm_condition_string[condition_code];
793 const char* symbol;
794 uint64_t offset;
795 int tmp;
796 uint32_t tmp32;
797
798 switch (main_opcode)
799 {
800 case 0x0:
801 case 0x1:
802 if (op11 <= 2) {
803 // Move shifted register.
804 debug("%ss\tr%i,r%i,#%i\n",
805 op11 & 1 ? "lsr" : (op11 & 2 ? "asr" : "lsl"),
806 rd,
807 rs_rb,
808 offset5);
809 } else {
810 // Add/subtract.
811 debug("%s\tr%i,r%i,%s%i\n",
812 addsub_op ? "subs" : "adds",
813 rd,
814 rs_rb,
815 addsub_immediate ? "#" : "r",
816 r6);
817 }
818 break;
819
820 case 0x2:
821 case 0x3:
822 // Move/compare/add/subtract immediate.
823 rd = (iw >> 8) & 7;
824 if (op11 & 2) {
825 debug("%s\tr%i,r%i,#%i\n",
826 op11 & 1 ? "subs" : "adds",
827 rd, rd,
828 iw & 0xff);
829 } else {
830 debug("%s\tr%i,#%i\n",
831 op11 & 1 ? "cmp" : "movs",
832 rd,
833 iw & 0xff);
834 }
835 break;
836
837 case 0x4:
838 switch (op10) {
839 case 0:
840 // ALU operations.
841 debug("%s\t%s,%s",
842 arm_thumb_dpiname[(iw >> 6) & 15],
843 arm_regname[rd],
844 arm_regname[rs_rb]);
845
846 if (running) {
847 debug("\t\t; %s = 0x%x", arm_regname[rd], cpu->cd.arm.r[rd]);
848 debug(", %s = 0x%x", arm_regname[rs_rb], cpu->cd.arm.r[rs_rb]);
849 }
850
851 debug("\n");
852 break;
853
854 case 1:
855 // Hi register operations / branch exchange.
856 if (h1)
857 rd += 8;
858 if (h2)
859 rs_rb += 8;
860 switch (op8) {
861 case 0:
862 case 1:
863 case 2:
864 if (h1 == 0 && h2 == 0) {
865 debug("TODO main_opcode = %i, op10 = %i, h1 AND h2 are zero?!\n", main_opcode, op10);
866 } else {
867 if (op8 == 0)
868 debug("add\tr%i,r%i,r%i\n", rd, rd, rs_rb);
869 else {
870 if (op8 == 2 && rd == rs_rb)
871 debug("nop\n"); // mov rX,rX
872 else {
873 debug("%s\t%s,%s",
874 op8 == 1 ? "cmp" : "mov",
875 arm_regname[rd],
876 arm_regname[rs_rb]);
877 if (running) {
878 debug("\t\t; %s = 0x%x", arm_regname[rd], cpu->cd.arm.r[rd]);
879 debug(", %s = 0x%x", arm_regname[rs_rb], cpu->cd.arm.r[rs_rb]);
880 }
881 debug("\n");
882 }
883 }
884 }
885 break;
886 case 3:
887 if (h1 == 1) {
888 debug("TODO main_opcode = %i, op10 = %i, h1 set for BX?!\n", main_opcode, op10);
889 } else {
890 debug("bx\t%s\n", arm_regname[rs_rb]);
891
892 // Extra newline when returning from function.
893 // if (running && rs_rb == ARM_LR)
894 // debug("\n");
895 }
896 break;
897 }
898 break;
899
900 case 2:
901 case 3:
902 // PC-relative load.
903 debug("ldr\t%s,[pc,#%i]\t; ",
904 arm_regname[rd8],
905 (iw & 0xff) * 4);
906
907 // Is this address calculation correct?
908 // It works with real code, but is not the same as that of
909 // http://engold.ui.ac.ir/~nikmehr/Appendix_B2.pdf
910 tmp = (dumpaddr & ~3) + 4 + (iw & 0xff) * 4;
911 debug("0x%x", (int)tmp);
912 symbol = get_symbol_name(&cpu->machine->symbol_context,
913 tmp, &offset);
914 if (symbol != NULL)
915 debug(" <%s>", symbol);
916 debug("\n");
917 break;
918 }
919 break;
920
921 case 0x5:
922 // Load/Store with register offset.
923 switch ((iw >> 9) & 7) {
924 case 0: debug("str"); break;
925 case 1: debug("strh"); break;
926 case 2: debug("strb"); break;
927 case 3: debug("ldrsb"); break;
928 case 4: debug("ldr"); break;
929 case 5: debug("ldrh"); break;
930 case 6: debug("ldrb"); break;
931 case 7: debug("ldrsh"); break;
932 }
933 debug("\t%s,[%s,%s]\n",
934 arm_regname[rd],
935 arm_regname[rs_rb],
936 arm_regname[r6]);
937 break;
938
939 case 0x6:
940 case 0x7:
941 // Load/Store with immediate offset.
942 debug("%s%s\tr%i,[r%i,#%i]\n",
943 l_bit ? "ldr" : "str",
944 b_bit ? "b" : "",
945 rd,
946 rs_rb,
947 offset5 * (b_bit ? sizeof(uint8_t) : sizeof(uint32_t)));
948 break;
949
950 case 0x8:
951 // Load/Store halfword.
952 debug("%sh\tr%i,[r%i,#%i]\n",
953 l_bit ? "ldr" : "str",
954 rd,
955 rs_rb,
956 offset5 * sizeof(uint16_t));
957 break;
958
959 case 0x9:
960 // Load/Store stack pointer relative.
961 debug("%s\t%s,[sp,#%i]\n",
962 l_bit ? "ldr" : "str",
963 arm_regname[rd8],
964 4 * (iw & 0xff));
965 break;
966
967 case 0xa:
968 // add rx, sp or pc plus imm
969 debug("add\t%s,%s,#%i\n",
970 arm_regname[rd8],
971 iw & 0x0800 ? "sp" : "pc",
972 4 * (iw & 0xff));
973 break;
974
975 case 0xb:
976 /* Bits 11..8: */
977 switch (condition_code) {
978 case 0x0:
979 tmp = (iw & 0x7f) << 2;
980 debug(iw & 0x80 ? "sub" : "add");
981 debug("\tsp,#%i\n", tmp);
982 break;
983 case 0x4:
984 case 0x5:
985 case 0xc:
986 case 0xd:
987 debug(condition_code & 8 ? "pop" : "push");
988 debug("\t{");
989 for (tmp=0; tmp<8; ++tmp) {
990 if (iw & (1 << tmp))
991 debug("%s,", arm_regname[tmp]);
992 }
993 if (condition_code & 1) {
994 if (condition_code & 8)
995 debug("pc");
996 else
997 debug("lr");
998 }
999 debug("}\n");
1000
1001 // Extra newline when returning from function.
1002 // if (running && (condition_code & 8) && (condition_code & 1))
1003 // debug("\n");
1004 break;
1005 default:
1006 debug("TODO: unimplemented opcode 0x%x,0x%x\n", main_opcode, condition_code);
1007 }
1008 break;
1009
1010 case 0xd:
1011 if (condition_code < 0xe) {
1012 // Conditional branch.
1013 debug("b%s\t", condition);
1014 tmp = (iw & 0xff) << 1;
1015 if (tmp & 0x100)
1016 tmp |= 0xfffffe00;
1017 tmp = (int32_t)(dumpaddr + 4 + tmp);
1018 debug("0x%x", (int)tmp);
1019 symbol = get_symbol_name(&cpu->machine->symbol_context,
1020 tmp, &offset);
1021 if (symbol != NULL)
1022 debug(" \t<%s>", symbol);
1023 debug("\n");
1024 } else if (condition_code == 0xf) {
1025 debug("swi\t#0x%x\n", iw & 0xff);
1026 } else {
1027 debug("UNIMPLEMENTED\n");
1028 }
1029 break;
1030
1031 case 0xe:
1032 // Unconditional branch.
1033 if (iw & 0x0800) {
1034 uint32_t addr = (dumpaddr + 4 + (cpu->cd.arm.tmp_branch + (((iw >> 1) & 0x3ff) << 2))) & ~3;
1035
1036 debug("blx\t");
1037 if (running) {
1038 debug("0x%x", addr);
1039 symbol = get_symbol_name(&cpu->machine->symbol_context, addr, &offset);
1040 if (symbol != NULL)
1041 debug(" \t<%s>", symbol);
1042 debug("\n");
1043 } else
1044 debug("offset depending on prefix at runtime\n");
1045 } else {
1046 tmp = (iw & 0x7ff) << 1;
1047 if (tmp & 0x800)
1048 tmp |= 0xfffff000;
1049 tmp = (int32_t)(dumpaddr + 4 + tmp);
1050 debug("b\t0x%x", (int)tmp);
1051 symbol = get_symbol_name(&cpu->machine->symbol_context, tmp, &offset);
1052 if (symbol != NULL)
1053 debug(" \t<%s>", symbol);
1054 debug("\n");
1055 }
1056 break;
1057
1058 case 0xf:
1059 if (iw & 0x0800) {
1060 uint32_t addr = (dumpaddr + 2 + (cpu->cd.arm.tmp_branch + ((iw & 0x7ff) << 1)));
1061
1062 debug("bl\t");
1063 if (running) {
1064 debug("0x%x", addr);
1065 symbol = get_symbol_name(&cpu->machine->symbol_context, addr, &offset);
1066 if (symbol != NULL)
1067 debug(" \t<%s>", symbol);
1068 debug("\n");
1069 } else
1070 debug("offset depending on prefix at runtime\n");
1071 } else {
1072 tmp32 = iw & 0x07ff;
1073 if (tmp32 & 0x0400)
1074 tmp32 |= 0xfffff800;
1075 tmp32 <<= 12;
1076 debug("bprefix\t0x%x\n", tmp32);
1077 }
1078 break;
1079
1080 default:
1081 debug("TODO: unimplemented opcode 0x%x\n", main_opcode);
1082 }
1083
1084 return sizeof(uint16_t);
1085 }
1086
1087
1088 /*
1089 * arm_cpu_interpret_thumb_SLOW():
1090 *
1091 * Slow interpretation of THUMB instructions.
1092 *
1093 * TODO: Either replace this with dyntrans in the old framework, or
1094 * implement ARM (including THUMB) in the new framework. :-)
1095 * For now, this is better than nothing.
1096 */
arm_cpu_interpret_thumb_SLOW(struct cpu * cpu)1097 int arm_cpu_interpret_thumb_SLOW(struct cpu *cpu)
1098 {
1099 uint16_t iw;
1100 uint8_t ib[sizeof(uint16_t)];
1101 uint32_t addr = cpu->pc & ~1;
1102
1103 if (!(cpu->pc & 1) || !(cpu->cd.arm.cpsr & ARM_FLAG_T)) {
1104 fatal("arm_cpu_interpret_thumb_SLOW called when not in "
1105 "THUMB mode?\n");
1106 cpu->running = 0;
1107 return 0;
1108 }
1109
1110 if (!cpu->memory_rw(cpu, cpu->mem, addr, &ib[0],
1111 sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
1112 fatal("arm_cpu_interpret_thumb_SLOW(): could not read "
1113 "the instruction\n");
1114 cpu->running = 0;
1115 return 0;
1116 }
1117
1118 if (cpu->machine->instruction_trace) {
1119 uint64_t offset;
1120 char* symbol = get_symbol_name(&cpu->machine->symbol_context,
1121 addr, &offset);
1122 if (symbol != NULL && offset == 0)
1123 debug("<%s>\n", symbol);
1124
1125 if (cpu->machine->ncpus > 1)
1126 debug("cpu%i:\t", cpu->cpu_id);
1127
1128 debug("%08x: ", (int)addr & ~1);
1129 arm_cpu_disassemble_instr_thumb(cpu, ib, 1, cpu->pc);
1130 }
1131
1132 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1133 iw = ib[0] + (ib[1]<<8);
1134 else
1135 iw = ib[1] + (ib[0]<<8);
1136
1137 cpu->ninstrs ++;
1138
1139 int main_opcode = (iw >> 12) & 15;
1140 int condition_code = (iw >> 8) & 15;
1141 int op10 = (iw >> 10) & 3;
1142 int op11_8 = (iw >> 8) & 15;
1143 int rd8 = (iw >> 8) & 7;
1144 int r6 = (iw >> 6) & 7;
1145 int r3 = (iw >> 3) & 7;
1146 int rd = (iw >> 0) & 7;
1147 int hd = (iw >> 7) & 1;
1148 int hm = (iw >> 6) & 1;
1149 int imm6 = (iw >> 6) & 31;
1150 uint8_t word[sizeof(uint32_t)];
1151 uint32_t tmp;
1152 int t, len, isLoad;
1153
1154 switch (main_opcode)
1155 {
1156 case 0x0:
1157 if (iw & 0x0800) {
1158 // lsr
1159 tmp = cpu->cd.arm.r[r3];
1160 if (imm6 > 1)
1161 tmp >>= (imm6 - 1);
1162 cpu->cd.arm.r[rd] = cpu->cd.arm.r[r3] >> imm6;
1163 tmp &= 1;
1164 } else {
1165 // lsl
1166 tmp = cpu->cd.arm.r[r3];
1167 if (imm6 > 1)
1168 tmp <<= (imm6 - 1);
1169 cpu->cd.arm.r[rd] = cpu->cd.arm.r[r3] << imm6;
1170 tmp >>= 31;
1171 }
1172 cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1173 if (cpu->cd.arm.r[rd] == 0)
1174 cpu->cd.arm.flags |= ARM_F_Z;
1175 if ((int32_t)cpu->cd.arm.r[rd] < 0)
1176 cpu->cd.arm.flags |= ARM_F_N;
1177 if (imm6 != 0) {
1178 // tmp is "last bit shifted out"
1179 cpu->cd.arm.flags &= ~ARM_F_C;
1180 if (tmp)
1181 cpu->cd.arm.flags |= ARM_F_C;
1182 }
1183 break;
1184
1185 case 0x1:
1186 if (!(iw & 0x0800)) {
1187 // asr
1188 tmp = cpu->cd.arm.r[r3];
1189 if (imm6 > 1)
1190 tmp = (int32_t)tmp >> (imm6 - 1);
1191 cpu->cd.arm.r[rd] = (int32_t)cpu->cd.arm.r[r3] >> imm6;
1192 tmp &= 1;
1193 cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1194 if (cpu->cd.arm.r[rd8] == 0)
1195 cpu->cd.arm.flags |= ARM_F_Z;
1196 if ((int32_t)cpu->cd.arm.r[rd8] < 0)
1197 cpu->cd.arm.flags |= ARM_F_N;
1198 if (imm6 != 0) {
1199 // tmp is "last bit shifted out"
1200 cpu->cd.arm.flags &= ~ARM_F_C;
1201 if (tmp)
1202 cpu->cd.arm.flags |= ARM_F_C;
1203 }
1204 } else {
1205 // add or sub
1206 int isSub = iw & 0x0200;
1207 int isImm3 = iw & 0x0400;
1208 uint64_t old = cpu->cd.arm.r[r3];
1209 uint64_t tmp64 = isImm3 ? r6 : cpu->cd.arm.r[r6];
1210 tmp64 = (uint32_t)(isSub ? -tmp64 : tmp64);
1211 uint64_t result = old + tmp64;
1212 cpu->cd.arm.r[rd] = result;
1213 cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N | ARM_F_C | ARM_F_V);
1214 if (result == 0)
1215 cpu->cd.arm.flags |= ARM_F_Z;
1216 if ((int32_t)result < 0)
1217 cpu->cd.arm.flags |= ARM_F_N;
1218 if (result & 0x100000000ULL)
1219 cpu->cd.arm.flags |= ARM_F_C;
1220 if (result & 0x80000000) {
1221 if ((tmp64 & 0x80000000) == 0 && (old & 0x80000000) == 0)
1222 cpu->cd.arm.flags |= ARM_F_V;
1223 } else {
1224 if ((tmp64 & 0x80000000) != 0 && (old & 0x80000000) != 0)
1225 cpu->cd.arm.flags |= ARM_F_V;
1226 }
1227 }
1228 break;
1229
1230 case 0x2:
1231 // movs or cmp
1232 if (iw & 0x0800) {
1233 uint64_t old = cpu->cd.arm.r[rd8];
1234 uint64_t tmp64 = (uint32_t)(-(iw & 0xff));
1235 uint64_t result = old + tmp64;
1236 cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N | ARM_F_C | ARM_F_V);
1237 if (result == 0)
1238 cpu->cd.arm.flags |= ARM_F_Z;
1239 if ((int32_t)result < 0)
1240 cpu->cd.arm.flags |= ARM_F_N;
1241 if (result & 0x100000000ULL)
1242 cpu->cd.arm.flags |= ARM_F_C;
1243 if (result & 0x80000000) {
1244 if ((tmp64 & 0x80000000) == 0 && (old & 0x80000000) == 0)
1245 cpu->cd.arm.flags |= ARM_F_V;
1246 } else {
1247 if ((tmp64 & 0x80000000) != 0 && (old & 0x80000000) != 0)
1248 cpu->cd.arm.flags |= ARM_F_V;
1249 }
1250 } else {
1251 cpu->cd.arm.r[rd8] = iw & 0xff;
1252 cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1253 if (cpu->cd.arm.r[rd8] == 0)
1254 cpu->cd.arm.flags |= ARM_F_Z;
1255 }
1256 break;
1257
1258 case 0x3:
1259 // adds or sub
1260 {
1261 uint64_t old = cpu->cd.arm.r[rd8];
1262 uint64_t tmp64 = iw & 0xff;
1263
1264 if (iw & 0x0800)
1265 tmp64 = (uint32_t)(-tmp64);
1266
1267 uint64_t result = old + tmp64;
1268 cpu->cd.arm.r[rd8] = result;
1269
1270 cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N | ARM_F_C | ARM_F_V);
1271 if (result == 0)
1272 cpu->cd.arm.flags |= ARM_F_Z;
1273 if ((int32_t)result < 0)
1274 cpu->cd.arm.flags |= ARM_F_N;
1275 if (result & 0x100000000ULL)
1276 cpu->cd.arm.flags |= ARM_F_C;
1277 if (result & 0x80000000) {
1278 if ((tmp64 & 0x80000000) == 0 && (old & 0x80000000) == 0)
1279 cpu->cd.arm.flags |= ARM_F_V;
1280 } else {
1281 if ((tmp64 & 0x80000000) != 0 && (old & 0x80000000) != 0)
1282 cpu->cd.arm.flags |= ARM_F_V;
1283 }
1284 }
1285 break;
1286
1287 case 0x4:
1288 switch (op10) {
1289 case 0:
1290 // "DPIs":
1291 switch ((iw >> 6) & 15) {
1292 case 0:// ands
1293 cpu->cd.arm.r[rd] &= cpu->cd.arm.r[r3];
1294 cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1295 if (cpu->cd.arm.r[rd] == 0)
1296 cpu->cd.arm.flags |= ARM_F_Z;
1297 if ((int32_t)cpu->cd.arm.r[rd] < 0)
1298 cpu->cd.arm.flags |= ARM_F_N;
1299 break;
1300 case 1:// eors
1301 cpu->cd.arm.r[rd] ^= cpu->cd.arm.r[r3];
1302 cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1303 if (cpu->cd.arm.r[rd] == 0)
1304 cpu->cd.arm.flags |= ARM_F_Z;
1305 if ((int32_t)cpu->cd.arm.r[rd] < 0)
1306 cpu->cd.arm.flags |= ARM_F_N;
1307 break;
1308 case 7:// rors
1309 {
1310 int amount = cpu->cd.arm.r[r3] & 0xff;
1311 for (int i = 0; i < (amount & 31); ++i) {
1312 int c = cpu->cd.arm.r[rd] & 1;
1313 cpu->cd.arm.r[rd] >>= 1;
1314 cpu->cd.arm.flags &= ~ARM_F_C;
1315 if (c) {
1316 cpu->cd.arm.flags |= ARM_F_C;
1317 cpu->cd.arm.r[rd] |= 0x80000000;
1318 }
1319 }
1320
1321 // Rotating right by e.g. 32 means that the C flag
1322 // should be updated, but the register isn't
1323 // really rotated.
1324 if (amount != 0 && (amount & 31) == 0) {
1325 cpu->cd.arm.flags &= ~ARM_F_C;
1326 if (cpu->cd.arm.r[rd] & 0x80000000)
1327 cpu->cd.arm.flags |= ARM_F_C;
1328 }
1329
1330 if (cpu->cd.arm.r[rd] == 0)
1331 cpu->cd.arm.flags |= ARM_F_Z;
1332 if ((int32_t)cpu->cd.arm.r[rd] < 0)
1333 cpu->cd.arm.flags |= ARM_F_N;
1334 }
1335 break;
1336 case 8:// tst
1337 tmp = cpu->cd.arm.r[rd] & cpu->cd.arm.r[r3];
1338 cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1339 if (tmp == 0)
1340 cpu->cd.arm.flags |= ARM_F_Z;
1341 if ((int32_t)tmp < 0)
1342 cpu->cd.arm.flags |= ARM_F_N;
1343 break;
1344 case 10: // cmp
1345 {
1346 uint64_t old = cpu->cd.arm.r[rd];
1347 uint64_t tmp64 = (uint32_t) (-cpu->cd.arm.r[r3]);
1348 uint64_t result = old + tmp64;
1349 cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N | ARM_F_C | ARM_F_V);
1350 if (result == 0)
1351 cpu->cd.arm.flags |= ARM_F_Z;
1352 if ((int32_t)result < 0)
1353 cpu->cd.arm.flags |= ARM_F_N;
1354 if (result & 0x100000000ULL)
1355 cpu->cd.arm.flags |= ARM_F_C;
1356 if (result & 0x80000000) {
1357 if ((tmp64 & 0x80000000) == 0 && (old & 0x80000000) == 0)
1358 cpu->cd.arm.flags |= ARM_F_V;
1359 } else {
1360 if ((tmp64 & 0x80000000) != 0 && (old & 0x80000000) != 0)
1361 cpu->cd.arm.flags |= ARM_F_V;
1362 }
1363 }
1364 break;
1365 case 12:// orrs
1366 cpu->cd.arm.r[rd] |= cpu->cd.arm.r[r3];
1367 cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1368 if (cpu->cd.arm.r[rd] == 0)
1369 cpu->cd.arm.flags |= ARM_F_Z;
1370 if ((int32_t)cpu->cd.arm.r[rd] < 0)
1371 cpu->cd.arm.flags |= ARM_F_N;
1372 break;
1373 case 13:// muls
1374 cpu->cd.arm.r[rd] *= cpu->cd.arm.r[r3];
1375 cpu->cd.arm.flags &= ~(ARM_F_Z | ARM_F_N);
1376 if (cpu->cd.arm.r[rd] == 0)
1377 cpu->cd.arm.flags |= ARM_F_Z;
1378 if ((int32_t)cpu->cd.arm.r[rd] < 0)
1379 cpu->cd.arm.flags |= ARM_F_N;
1380 break;
1381 default:
1382 debug("TODO: unimplemented DPI %i at pc 0x%08x\n", (iw >> 6) & 15, (int)cpu->pc);
1383 cpu->running = 0;
1384 return 0;
1385 }
1386 break;
1387 case 1:
1388 switch (op11_8) {
1389 case 6:
1390 if (hd)
1391 rd += 8;
1392 if (hm)
1393 r3 += 8;
1394 cpu->cd.arm.r[rd] = cpu->cd.arm.r[r3];
1395 if (r3 == ARM_PC) {
1396 if (cpu->pc & 1) {
1397 debug("TODO: double check with manual whether it is correct to use old pc + 8 here; at pc 0x%08x\n", (int)cpu->pc);
1398 cpu->running = 0;
1399 return 0;
1400 }
1401 cpu->cd.arm.r[rd] = cpu->pc + 8;
1402 }
1403 if (rd == ARM_PC) {
1404 cpu->pc = cpu->cd.arm.r[rd];
1405 cpu->cd.arm.cpsr |= ARM_FLAG_T;
1406 if (!(cpu->pc & 1))
1407 cpu->cd.arm.cpsr &= ~ARM_FLAG_T;
1408 cpu->pc = addr - sizeof(uint16_t);
1409 }
1410 break;
1411 case 7:
1412 if ((iw & 0xff87) == 0x4700) {
1413 // bx
1414 int rm = (iw >> 3) & 15;
1415 // Note: pc will be increased by 2 further down!
1416 cpu->pc = cpu->cd.arm.r[rm] - sizeof(uint16_t);
1417 if (!(cpu->pc & 1))
1418 cpu->cd.arm.cpsr &= ~ARM_FLAG_T;
1419 if (rm == ARM_LR && cpu->machine->show_trace_tree)
1420 cpu_functioncall_trace_return(cpu);
1421 } else {
1422 debug("TODO: unimplemented opcode 0x%x,%i at pc 0x%08x\n", main_opcode, op11_8, (int)cpu->pc);
1423 cpu->running = 0;
1424 return 0;
1425 }
1426 break;
1427 default:
1428 debug("TODO: unimplemented opcode 0x%x,%i at pc 0x%08x\n", main_opcode, op11_8, (int)cpu->pc);
1429 cpu->running = 0;
1430 return 0;
1431 }
1432 break;
1433
1434 case 2:
1435 case 3:
1436 // PC-relative load.
1437 // Is this address calculation correct?
1438 // It works with real code, but is not the same as that of
1439 // http://engold.ui.ac.ir/~nikmehr/Appendix_B2.pdf
1440 tmp = (addr & ~3) + 4 + (iw & 0xff) * 4;
1441
1442 if (!cpu->memory_rw(cpu, cpu->mem, tmp, &word[0],
1443 sizeof(word), MEM_READ, CACHE_INSTRUCTION)) {
1444 fatal("arm_cpu_interpret_thumb_SLOW(): could not load pc-relative word\n");
1445 cpu->running = 0;
1446 return 0;
1447 }
1448
1449 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1450 tmp = word[0] + (word[1]<<8) + (word[2]<<16) + (word[3]<<24);
1451 else
1452 tmp = word[3] + (word[2]<<8) + (word[1]<<16) + (word[0]<<24);
1453
1454 cpu->cd.arm.r[rd8] = tmp;
1455 break;
1456
1457 default:
1458 debug("TODO: unimplemented opcode 0x%x,%i at pc 0x%08x\n", main_opcode, op10, (int)cpu->pc);
1459 cpu->running = 0;
1460 return 0;
1461 }
1462 break;
1463
1464 case 0x6:
1465 case 0x7:
1466 case 0x8:
1467 // Load/Store with immediate offset.
1468 len = main_opcode == 6 ? 4 : (main_opcode == 7 ? 1 : 2);
1469 isLoad = iw & 0x0800;
1470 addr = (cpu->cd.arm.r[r3] + imm6 * len) & ~(len - 1);
1471 tmp = 0;
1472
1473 if (!isLoad) {
1474 tmp = cpu->cd.arm.r[rd];
1475
1476 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
1477 for (int i = 0; i < len; ++i)
1478 word[i] = (tmp >> (8*i));
1479 } else {
1480 for (int i = 0; i < len; ++i)
1481 word[len - 1 - i] = (tmp >> (8*i));
1482 }
1483 }
1484
1485 if (!cpu->memory_rw(cpu, cpu->mem, addr, &word[0],
1486 len, isLoad ? MEM_READ : MEM_WRITE, CACHE_DATA)) {
1487 fatal("arm_cpu_interpret_thumb_SLOW(): could not load with immediate offset\n");
1488 cpu->running = 0;
1489 return 0;
1490 }
1491
1492 if (isLoad) {
1493 tmp = 0;
1494 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
1495 for (int i = 0; i < len; ++i) {
1496 tmp <<= 8;
1497 tmp |= word[len - 1 - i];
1498 }
1499 } else {
1500 for (int i = 0; i < len; ++i) {
1501 tmp <<= 8;
1502 tmp |= word[i];
1503 }
1504 }
1505
1506 cpu->cd.arm.r[rd] = tmp;
1507 }
1508 break;
1509
1510 case 0x9:
1511 // sp-relative load or store
1512 if (iw & 0x0800) {
1513 addr = (cpu->cd.arm.r[ARM_SP] + (iw & 0xff) * 4) & ~3;
1514 if (!cpu->memory_rw(cpu, cpu->mem, addr, &word[0],
1515 sizeof(word), MEM_READ, CACHE_DATA)) {
1516 fatal("arm_cpu_interpret_thumb_SLOW(): could not load sp-relative word\n");
1517 cpu->running = 0;
1518 return 0;
1519 }
1520
1521 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1522 tmp = word[0] + (word[1]<<8) + (word[2]<<16) + (word[3]<<24);
1523 else
1524 tmp = word[3] + (word[2]<<8) + (word[1]<<16) + (word[0]<<24);
1525
1526 cpu->cd.arm.r[rd8] = tmp;
1527 } else {
1528 tmp = cpu->cd.arm.r[rd8];
1529 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
1530 for (size_t i = 0; i < sizeof(word); ++i)
1531 word[i] = (tmp >> (8*i));
1532 } else {
1533 for (size_t i = 0; i < sizeof(word); ++i)
1534 word[sizeof(word) - 1 - i] = (tmp >> (8*i));
1535 }
1536
1537 addr = (cpu->cd.arm.r[ARM_SP] + (iw & 0xff) * 4) & ~3;
1538 if (!cpu->memory_rw(cpu, cpu->mem, addr, &word[0],
1539 sizeof(word), MEM_WRITE, CACHE_DATA)) {
1540 fatal("arm_cpu_interpret_thumb_SLOW(): could not store sp-relative word\n");
1541 cpu->running = 0;
1542 return 0;
1543 }
1544 }
1545 break;
1546
1547 case 0xb:
1548 switch (op11_8) {
1549 case 0:
1550 if (iw & 0x0080)
1551 cpu->cd.arm.r[ARM_SP] -= ((iw & 0x7f) << 2);
1552 else
1553 cpu->cd.arm.r[ARM_SP] += ((iw & 0x7f) << 2);
1554 break;
1555 case 4:
1556 case 5:
1557 /* push, i.e. stmdb sp!, reglist */
1558 arm_push(cpu, &cpu->cd.arm.r[ARM_SP], 1, 0, 0, 1, (iw & 0xff) |
1559 (iw & 0x100 ? (1 << ARM_LR) : 0));
1560 break;
1561 case 12:
1562 case 13:
1563 /* pop, i.e. ldmia sp!, reglist */
1564 cpu->cd.arm.r[ARM_PC] = cpu->pc;
1565 arm_pop(cpu, &cpu->cd.arm.r[ARM_SP], 0, 1, 0, 1, (iw & 0xff) |
1566 (iw & 0x100 ? (1 << ARM_PC) : 0));
1567 cpu->pc = cpu->cd.arm.r[ARM_PC];
1568 if (cpu->pc & 1)
1569 cpu->cd.arm.cpsr |= ARM_FLAG_T;
1570 else
1571 cpu->cd.arm.cpsr &= ~ARM_FLAG_T;
1572 // If not popping pc, make sure to move to the next instruction:
1573 if (!(iw & 0x100))
1574 cpu->pc += sizeof(uint16_t);
1575 return 1;
1576 default:
1577 debug("TODO: unimplemented opcode 0x%x,%i at pc 0x%08x\n", main_opcode, op11_8, (int)cpu->pc);
1578 cpu->running = 0;
1579 return 0;
1580 }
1581 break;
1582
1583 case 0xd:
1584 if (condition_code < 0xe) {
1585 // Conditional branch.
1586 tmp = (iw & 0xff) << 1;
1587 if (tmp & 0x100)
1588 tmp |= 0xfffffe00;
1589 tmp = (int32_t)(cpu->pc + 4 + tmp);
1590
1591 switch (condition_code) {
1592 case 0x0: // eq:
1593 t = cpu->cd.arm.flags & ARM_F_Z;
1594 break;
1595 case 0x1: // ne:
1596 t = !(cpu->cd.arm.flags & ARM_F_Z);
1597 break;
1598 case 0x2: // cs:
1599 t = cpu->cd.arm.flags & ARM_F_C;
1600 break;
1601 case 0x3: // cc:
1602 t = !(cpu->cd.arm.flags & ARM_F_C);
1603 break;
1604 case 0x4: // mi:
1605 t = cpu->cd.arm.flags & ARM_F_N;
1606 break;
1607 case 0x5: // pl:
1608 t = !(cpu->cd.arm.flags & ARM_F_N);
1609 break;
1610 case 0x6: // vs:
1611 t = cpu->cd.arm.flags & ARM_F_V;
1612 break;
1613 case 0x7: // vc:
1614 t = !(cpu->cd.arm.flags & ARM_F_V);
1615 break;
1616 case 0x8: // hi:
1617 t = condition_hi[cpu->cd.arm.flags];
1618 break;
1619 case 0x9: // ls:
1620 t = !condition_hi[cpu->cd.arm.flags];
1621 break;
1622 case 0xa: // ge:
1623 t = condition_ge[cpu->cd.arm.flags];
1624 break;
1625 case 0xb: // lt:
1626 t = !condition_ge[cpu->cd.arm.flags];
1627 break;
1628 case 0xc: // gt:
1629 t = condition_gt[cpu->cd.arm.flags];
1630 break;
1631 case 0xd: // le:
1632 t = !condition_gt[cpu->cd.arm.flags];
1633 break;
1634 }
1635
1636 if (t) {
1637 cpu->pc = tmp;
1638 return 1;
1639 }
1640 } else if (condition_code == 0xf) {
1641 arm_exception(cpu, ARM_EXCEPTION_SWI);
1642 return 1;
1643 } else {
1644 debug("TODO: unimplemented opcode 0x%x, non-branch, at pc 0x%08x\n", main_opcode, (int)cpu->pc);
1645 cpu->running = 0;
1646 return 0;
1647 }
1648 break;
1649
1650 case 0xe:
1651 if (iw & 0x0800) {
1652 // blx
1653 addr = (cpu->pc + 4 + (cpu->cd.arm.tmp_branch + (((iw >> 1) & 0x3ff) << 2))) & ~3;
1654
1655 if (iw & 1) {
1656 fatal("lowest bit set in thumb blx instruction?\n");
1657 cpu->running = 0;
1658 return 0;
1659 }
1660
1661 cpu->cd.arm.r[ARM_LR] = cpu->pc + 2;
1662 cpu->pc = addr;
1663 if (cpu->machine->show_trace_tree)
1664 cpu_functioncall_trace(cpu, cpu->pc);
1665 cpu->cd.arm.cpsr &= ~ARM_FLAG_T;
1666 return 1;
1667 } else {
1668 // b
1669 tmp = (iw & 0x7ff) << 1;
1670 if (tmp & 0x800)
1671 tmp |= 0xfffff000;
1672 cpu->pc = (int32_t)(cpu->pc + 4 + tmp);
1673 return 1;
1674 }
1675 break;
1676
1677 case 0xf:
1678 if (iw & 0x0800) {
1679 // bl
1680 addr = (cpu->pc + 2 + (cpu->cd.arm.tmp_branch + ((iw & 0x7ff) << 1)));
1681 cpu->cd.arm.r[ARM_LR] = cpu->pc + 2;
1682 cpu->pc = addr;
1683 if (cpu->machine->show_trace_tree)
1684 cpu_functioncall_trace(cpu, cpu->pc);
1685 return 1;
1686 } else {
1687 // "branch prefix".
1688 uint32_t tmp32 = iw & 0x07ff;
1689 if (tmp32 & 0x0400)
1690 tmp32 |= 0xfffff800;
1691 tmp32 <<= 12;
1692 cpu->cd.arm.tmp_branch = tmp32;
1693 }
1694 break;
1695
1696 default:
1697 debug("TODO: unimplemented opcode 0x%x at pc 0x%08x\n", main_opcode, (int)cpu->pc);
1698 cpu->running = 0;
1699 return 0;
1700 }
1701
1702 cpu->pc += sizeof(uint16_t);
1703
1704 return 1;
1705 }
1706
1707
1708 /*
1709 * arm_cpu_disassemble_instr():
1710 *
1711 * Convert an instruction word into human readable format, for instruction
1712 * tracing.
1713 *
1714 * If running is 1, cpu->pc should be the address of the instruction.
1715 *
1716 * If running is 0, things that depend on the runtime environment (eg.
1717 * register contents) will not be shown, and addr will be used instead of
1718 * cpu->pc for relative addresses.
1719 */
arm_cpu_disassemble_instr(struct cpu * cpu,unsigned char * ib,int running,uint64_t dumpaddr)1720 int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
1721 int running, uint64_t dumpaddr)
1722 {
1723 uint32_t iw, tmp;
1724 int main_opcode, secondary_opcode, s_bit, r16, r12, r8;
1725 int i, n, p_bit, u_bit, b_bit, w_bit, l_bit;
1726 const char *symbol, *condition;
1727 uint64_t offset;
1728
1729 if (running)
1730 dumpaddr = cpu->pc;
1731
1732 symbol = get_symbol_name(&cpu->machine->symbol_context,
1733 dumpaddr, &offset);
1734 if (symbol != NULL && offset == 0)
1735 debug("<%s>\n", symbol);
1736
1737 if (cpu->machine->ncpus > 1 && running)
1738 debug("cpu%i:\t", cpu->cpu_id);
1739
1740 debug("%08x: ", (int)dumpaddr & ~1);
1741
1742 if (dumpaddr & 1)
1743 return arm_cpu_disassemble_instr_thumb(cpu, ib, running, dumpaddr);
1744
1745 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1746 iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
1747 else
1748 iw = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
1749 debug("%08x\t", (int)iw);
1750
1751 condition = arm_condition_string[iw >> 28];
1752 main_opcode = (iw >> 24) & 15;
1753 secondary_opcode = (iw >> 21) & 15;
1754 u_bit = (iw >> 23) & 1;
1755 b_bit = (iw >> 22) & 1;
1756 w_bit = (iw >> 21) & 1;
1757 s_bit = l_bit = (iw >> 20) & 1;
1758 r16 = (iw >> 16) & 15;
1759 r12 = (iw >> 12) & 15;
1760 r8 = (iw >> 8) & 15;
1761
1762 if (iw == 0xf10c0040) {
1763 debug("cpsid\tf\n");
1764 return sizeof(uint32_t);
1765 } else if (iw == 0xf10c0080) {
1766 debug("cpsid\ti\n");
1767 return sizeof(uint32_t);
1768 } else if (iw == 0xf57ff04f) {
1769 debug("dsb\tsy\n");
1770 return sizeof(uint32_t);
1771 } else if (iw == 0xf57ff05f) {
1772 debug("dmb\tsy\n");
1773 return sizeof(uint32_t);
1774 } else if (iw == 0xf57ff06f) {
1775 debug("isb\tsy\n");
1776 return sizeof(uint32_t);
1777 } else if ((iw >> 28) == 0xf) {
1778 switch (main_opcode) {
1779 case 0xa:
1780 case 0xb:
1781 tmp = (iw & 0xffffff);
1782 if (tmp & 0x800000)
1783 tmp |= 0xff000000;
1784 tmp = (int32_t)(dumpaddr + 8 + 4*tmp + (main_opcode == 0xb? 2 : 0)) + 1;
1785 debug("blx\t0x%x", (int)tmp);
1786 symbol = get_symbol_name(&cpu->machine->symbol_context,
1787 tmp, &offset);
1788 if (symbol != NULL)
1789 debug(" \t<%s>", symbol);
1790 debug("\n");
1791 break;
1792 default:debug("UNIMPLEMENTED\n");
1793 }
1794 return sizeof(uint32_t);
1795 }
1796
1797 switch (main_opcode) {
1798 case 0x0:
1799 case 0x1:
1800 case 0x2:
1801 case 0x3:
1802 /*
1803 * Special cases first:
1804 */
1805
1806 /*
1807 * ldrex: Load Register Exclusive
1808 * strex: Store Register Exclusive
1809 */
1810 if ((iw & 0x0ff00fff) == 0x01900f9f) {
1811 /* ldrex rt[,rn]: */
1812 debug("ldrex%s\t%s,%s",
1813 condition,
1814 arm_regname[r12],
1815 arm_regname[r16]);
1816 debug("\n");
1817 break;
1818 }
1819 if ((iw & 0x0ff00ff0) == 0x01800f90) {
1820 /* strex rd,rt[,rn]: */
1821 debug("strex%s\t%s,%s,%s",
1822 condition,
1823 arm_regname[r12],
1824 arm_regname[iw & 15],
1825 arm_regname[r16]);
1826 debug("\n");
1827 break;
1828 }
1829
1830 /*
1831 * Multiplication:
1832 * xxxx0000 0110dddd aaaammmm 1001nnnn mls rd,rn,rm,ra
1833 */
1834 if ((iw & 0x0ff000f0) == 0x00600090) {
1835 debug("mls%s\t", condition);
1836 debug("%s,", arm_regname[r16]);
1837 debug("%s,", arm_regname[iw & 15]);
1838 debug("%s,", arm_regname[r8]);
1839 debug("%s", arm_regname[r12]);
1840 debug("\n");
1841 break;
1842 }
1843
1844 /*
1845 * Multiplication:
1846 * xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd, Rm, Rs [,Rn])
1847 */
1848 if ((iw & 0x0fc000f0) == 0x00000090) {
1849 int a_bit = (iw >> 21) & 1;
1850 debug("%s%s%s\t", a_bit? "mla" : "mul",
1851 condition, s_bit? "s" : "");
1852 debug("%s,", arm_regname[r16]);
1853 debug("%s,", arm_regname[iw & 15]);
1854 debug("%s", arm_regname[r8]);
1855 if (a_bit)
1856 debug(",%s", arm_regname[r12]);
1857 debug("\n");
1858 break;
1859 }
1860
1861 /*
1862 * Long multiplication:
1863 * xxxx0000 1UAShhhh llllssss 1001mmmm (Rl,Rh,Rm,Rs)
1864 */
1865 if ((iw & 0x0f8000f0) == 0x00800090) {
1866 int a_bit = (iw >> 21) & 1;
1867 u_bit = (iw >> 22) & 1;
1868 debug("%s%sl%s%s\t", u_bit? "s" : "u",
1869 a_bit? "mla" : "mul", condition, s_bit? "s" : "");
1870 debug("%s,%s,", arm_regname[r12], arm_regname[r16]);
1871 debug("%s,%s\n", arm_regname[iw&15], arm_regname[r8]);
1872 break;
1873 }
1874
1875 /*
1876 * xxxx0001 0000nnnn dddd0000 0101mmmm qadd Rd,Rm,Rn
1877 * xxxx0001 0010nnnn dddd0000 0101mmmm qsub Rd,Rm,Rn
1878 * xxxx0001 0100nnnn dddd0000 0101mmmm qdadd Rd,Rm,Rn
1879 * xxxx0001 0110nnnn dddd0000 0101mmmm qdsub Rd,Rm,Rn
1880 */
1881 if ((iw & 0x0f900ff0) == 0x01000050) {
1882 debug("q%s%s%s\t", iw & 0x400000? "d" : "",
1883 iw & 0x200000? "sub" : "add", condition);
1884 debug("%s,%s,%s\n", arm_regname[r12],
1885 arm_regname[iw&15], arm_regname[r16]);
1886 break;
1887 }
1888
1889 /*
1890 * xxxx0001 0010.... ........ 00L1mmmm bx/blx rm
1891 */
1892 if ((iw & 0x0ff000d0) == 0x01200010) {
1893 l_bit = iw & 0x20;
1894 debug("b%sx%s\t%s\n", l_bit? "l" : "", condition,
1895 arm_regname[iw & 15]);
1896 break;
1897 }
1898
1899 /*
1900 * xxxx0001 0s10aaaa 11110000 0000mmmm MSR Regform
1901 * xxxx0011 0s10aaaa 1111rrrr bbbbbbbb MSR Immform
1902 * xxxx0001 0s001111 dddd0000 00000000 MRS
1903 */
1904 if ((iw & 0x0fb0fff0) == 0x0120f000 ||
1905 (iw & 0x0fb0f000) == 0x0320f000) {
1906 debug("msr%s\t%s", condition, (iw&0x400000)? "S":"C");
1907 debug("PSR_");
1908 if (iw & (1<<19)) debug("f");
1909 if (iw & (1<<18)) debug("s");
1910 if (iw & (1<<17)) debug("x");
1911 if (iw & (1<<16)) debug("c");
1912 if (iw & 0x02000000) {
1913 int r = (iw >> 7) & 30;
1914 uint32_t b = iw & 0xff;
1915 while (r-- > 0)
1916 b = (b >> 1) | ((b & 1) << 31);
1917 debug(",#0x%x\n", b);
1918 } else
1919 debug(",%s\n", arm_regname[iw & 15]);
1920 break;
1921 }
1922 if ((iw & 0x0fbf0fff) == 0x010f0000) {
1923 debug("mrs%s\t", condition);
1924 debug("%s,%sPSR\n", arm_regname[r12],
1925 (iw&0x400000)? "S":"C");
1926 break;
1927 }
1928
1929 /*
1930 * xxxx0001 0B00nnnn dddd0000 1001mmmm SWP Rd,Rm,[Rn]
1931 */
1932 if ((iw & 0x0fb00ff0) == 0x01000090) {
1933 debug("swp%s%s\t", condition, (iw&0x400000)? "b":"");
1934 debug("%s,%s,[%s]\n", arm_regname[r12],
1935 arm_regname[iw & 15], arm_regname[r16]);
1936 break;
1937 }
1938
1939 /*
1940 * xxxx0001 0010iiii iiiiiiii 0111iiii BKPT immed16
1941 */
1942 if ((iw & 0x0ff000f0) == 0x01200070) {
1943 debug("bkpt%s\t0x%04x\n", condition,
1944 ((iw & 0x000fff00) >> 4) + (iw & 0xf));
1945 break;
1946 }
1947
1948 /*
1949 * xxxx0001 01101111 dddd1111 0001mmmm CLZ Rd,Rm
1950 */
1951 if ((iw & 0x0fff0ff0) == 0x016f0f10) {
1952 debug("clz%s\t", condition);
1953 debug("%s,%s\n", arm_regname[r12], arm_regname[iw&15]);
1954 break;
1955 }
1956
1957 /*
1958 * xxxx0011 0000mmm ddddmmm mmmmmmm MOVW Rd,imm
1959 */
1960 if ((iw & 0x0ff00000) == 0x03000000) {
1961 debug("movw%s\t", condition);
1962 debug("%s,#%i\n", arm_regname[r12],
1963 ((iw & 0xf0000) >> 4) | (iw & 0xfff));
1964 break;
1965 }
1966
1967 /*
1968 * xxxx0011 0100mmm ddddmmm mmmmmmm MOVT Rd,imm
1969 */
1970 if ((iw & 0x0ff00000) == 0x03400000) {
1971 debug("movt%s\t", condition);
1972 debug("%s,#%i\n", arm_regname[r12],
1973 ((iw & 0xf0000) >> 4) | (iw & 0xfff));
1974 break;
1975 }
1976
1977 /*
1978 * xxxx0001 0000dddd nnnnssss 1yx0mmmm SMLAxy Rd,Rm,Rs,Rn
1979 * xxxx0001 0100dddd DDDDssss 1yx0mmmm SMLALxy RdL,RdH,Rm,Rs
1980 * xxxx0001 0010dddd nnnnssss 1y00mmmm SMLAWy Rd,Rm,Rs,Rn
1981 * xxxx0001 0110dddd 0000ssss 1yx0mmmm SMULxy Rd,Rm,Rs
1982 * xxxx0001 0010dddd 0000ssss 1y10mmmm SMULWy Rd,Rm,Rs
1983 */
1984 if ((iw & 0x0ff00090) == 0x01000080) {
1985 debug("smla%s%s%s\t",
1986 iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
1987 condition);
1988 debug("%s,%s,%s,%s\n", arm_regname[r16],
1989 arm_regname[iw&15], arm_regname[r8],
1990 arm_regname[r12]);
1991 break;
1992 }
1993 if ((iw & 0x0ff00090) == 0x01400080) {
1994 debug("smlal%s%s%s\t",
1995 iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
1996 condition);
1997 debug("%s,%s,%s,%s\n", arm_regname[r12],
1998 arm_regname[r16], arm_regname[iw&15],
1999 arm_regname[r8]);
2000 break;
2001 }
2002 if ((iw & 0x0ff000b0) == 0x01200080) {
2003 debug("smlaw%s%s\t", iw & 0x40? "t" : "b",
2004 condition);
2005 debug("%s,%s,%s,%s\n", arm_regname[r16],
2006 arm_regname[iw&15], arm_regname[r8],
2007 arm_regname[r12]);
2008 break;
2009 }
2010 if ((iw & 0x0ff0f090) == 0x01600080) {
2011 debug("smul%s%s%s\t",
2012 iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
2013 condition);
2014 debug("%s,%s,%s\n", arm_regname[r16],
2015 arm_regname[iw&15], arm_regname[r8]);
2016 break;
2017 }
2018 if ((iw & 0x0ff0f0b0) == 0x012000a0) {
2019 debug("smulw%s%s\t", iw & 0x40? "t" : "b",
2020 condition);
2021 debug("%s,%s,%s\n", arm_regname[r16],
2022 arm_regname[iw&15], arm_regname[r8]);
2023 break;
2024 }
2025
2026 /*
2027 * xxxx000P U1WLnnnn ddddHHHH 1SH1LLLL load/store rd,imm(rn)
2028 */
2029 if ((iw & 0x0e000090) == 0x00000090) {
2030 const char *op = "st";
2031 int imm = ((iw >> 4) & 0xf0) | (iw & 0xf);
2032 int regform = !(iw & 0x00400000);
2033 p_bit = main_opcode & 1;
2034 /*
2035 * TODO: detect some illegal variants:
2036 * signed store, or unsigned byte load/store
2037 */
2038 if (!l_bit && (iw & 0xd0) == 0xd0 && (r12 & 1)) {
2039 debug("TODO: r12 odd, not load/store\n");
2040 break;
2041 }
2042 /* Semi-generic case: */
2043 if (iw & 0x00100000)
2044 op = "ld";
2045 if (!l_bit && (iw & 0xd0) == 0xd0) {
2046 if (iw & 0x20)
2047 op = "st";
2048 else
2049 op = "ld";
2050 }
2051 debug("%sr%s", op, condition);
2052 if (!l_bit && (iw & 0xd0) == 0xd0) {
2053 debug("d"); /* Double-register */
2054 } else {
2055 if (iw & 0x40)
2056 debug("s"); /* signed */
2057 if (iw & 0x20)
2058 debug("h"); /* half-word */
2059 else
2060 debug("b"); /* byte */
2061 }
2062 debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
2063 if (p_bit) {
2064 /* Pre-index: */
2065 if (regform)
2066 debug(",%s%s", u_bit? "" : "-",
2067 arm_regname[iw & 15]);
2068 else {
2069 if (imm != 0)
2070 debug(",#%s%i", u_bit? "" : "-",
2071 imm);
2072 }
2073 debug("]%s\n", w_bit? "!" : "");
2074 } else {
2075 /* Post-index: */
2076 debug("],");
2077 if (regform)
2078 debug("%s%s\n", u_bit? "" : "-",
2079 arm_regname[iw & 15]);
2080 else
2081 debug("#%s%i\n", u_bit? "" : "-", imm);
2082 }
2083 break;
2084 }
2085
2086 /* Other special cases: */
2087 if (iw & 0x80 && !(main_opcode & 2) && iw & 0x10) {
2088 debug("UNIMPLEMENTED reg (c!=0), t odd\n");
2089 break;
2090 }
2091
2092 /*
2093 * Generic Data Processing Instructions:
2094 *
2095 * xxxx000a aaaSnnnn ddddcccc ctttmmmm Register form
2096 * xxxx001a aaaSnnnn ddddrrrr bbbbbbbb Immediate form
2097 */
2098
2099 debug("%s%s%s\t", arm_dpiname[secondary_opcode],
2100 condition, s_bit? "s" : "");
2101 if (arm_dpi_uses_d[secondary_opcode])
2102 debug("%s,", arm_regname[r12]);
2103 if (arm_dpi_uses_n[secondary_opcode])
2104 debug("%s,", arm_regname[r16]);
2105
2106 if (main_opcode & 2) {
2107 /* Immediate form: */
2108 int r = (iw >> 7) & 30;
2109 uint32_t b = iw & 0xff;
2110 while (r-- > 0)
2111 b = (b >> 1) | ((b & 1) << 31);
2112 if (b < 15)
2113 debug("#%i", b);
2114 else
2115 debug("#0x%x", b);
2116 } else {
2117 /* Register form: */
2118 int t = (iw >> 4) & 7;
2119 int c = (iw >> 7) & 31;
2120 debug("%s", arm_regname[iw & 15]);
2121 switch (t) {
2122 case 0: if (c != 0)
2123 debug(", lsl #%i", c);
2124 break;
2125 case 1: debug(", lsl %s", arm_regname[c >> 1]);
2126 break;
2127 case 2: debug(", lsr #%i", c? c : 32);
2128 break;
2129 case 3: debug(", lsr %s", arm_regname[c >> 1]);
2130 break;
2131 case 4: debug(", asr #%i", c? c : 32);
2132 break;
2133 case 5: debug(", asr %s", arm_regname[c >> 1]);
2134 break;
2135 case 6: if (c != 0)
2136 debug(", ror #%i", c);
2137 else
2138 debug(", rrx");
2139 break;
2140 case 7: debug(", ror %s", arm_regname[c >> 1]);
2141 break;
2142 }
2143
2144 /* mov pc,reg: */
2145 if (running && t == 0 && c == 0 && secondary_opcode
2146 == 0xd && r12 == ARM_PC && (iw&15)!=ARM_PC) {
2147 symbol = get_symbol_name(&cpu->machine->
2148 symbol_context, cpu->cd.arm.r[iw & 15],
2149 &offset);
2150 if (symbol != NULL)
2151 debug(" \t<%s>", symbol);
2152 }
2153 }
2154 debug("\n");
2155 break;
2156 case 0x4: /* Single Data Transfer */
2157 case 0x5:
2158 case 0x6:
2159 case 0x7:
2160 /* Special cases first: */
2161 if ((iw & 0xfc70f000) == 0xf450f000) {
2162 /* Preload: */
2163 debug("pld\t[%s]\n", arm_regname[r16]);
2164 break;
2165 }
2166
2167 if ((iw & 0x0fff0ff0) == 0x06bf0f30) {
2168 /* rev rd,rm: */
2169 debug("rev%s\t%s,%s",
2170 condition,
2171 arm_regname[r12],
2172 arm_regname[iw & 15]);
2173 debug("\n");
2174 break;
2175 }
2176
2177 if ((iw & 0x0fff03f0) == 0x06bf0070) {
2178 /* sxth rd,rm[,rot]: */
2179 debug("sxth%s\t%s,%s",
2180 condition,
2181 arm_regname[r12],
2182 arm_regname[iw & 15]);
2183 int rot = ((iw & 0xc00) >> 10) << 3;
2184 if (rot != 0)
2185 debug(",%i", rot);
2186 debug("\n");
2187 break;
2188 }
2189
2190 if ((iw & 0x0fff03f0) == 0x06ef0070) {
2191 /* uxtb rd,rm[,rot]: */
2192 debug("uxtb%s\t%s,%s",
2193 condition,
2194 arm_regname[r12],
2195 arm_regname[iw & 15]);
2196 int rot = ((iw & 0xc00) >> 10) << 3;
2197 if (rot != 0)
2198 debug(",%i", rot);
2199 debug("\n");
2200 break;
2201 }
2202
2203 // Note: uxtab is decoded AFTER uxtb.
2204 if ((iw & 0x0ff003f0) == 0x06e00070) {
2205 /* uxtab rd,rn,rm[,rot]: */
2206 debug("uxtab%s\t%s,%s,%s",
2207 condition,
2208 arm_regname[r12],
2209 arm_regname[r16],
2210 arm_regname[iw & 15]);
2211 int rot = ((iw & 0xc00) >> 10) << 3;
2212 if (rot != 0)
2213 debug(",%i", rot);
2214 debug("\n");
2215 break;
2216 }
2217
2218 if ((iw & 0x0fff03f0) == 0x06ff0070) {
2219 /* uxth rd,rm[,rot]: */
2220 debug("uxth%s\t%s,%s",
2221 condition,
2222 arm_regname[r12],
2223 arm_regname[iw & 15]);
2224 int rot = ((iw & 0xc00) >> 10) << 3;
2225 if (rot != 0)
2226 debug(",%i", rot);
2227 debug("\n");
2228 break;
2229 }
2230
2231 // Note: uxtah is decoded AFTER uxth.
2232 if ((iw & 0x0ff003f0) == 0x06f00070) {
2233 /* uxtah rd,rn,rm[,rot]: */
2234 debug("uxtah%s\t%s,%s,%s",
2235 condition,
2236 arm_regname[r12],
2237 arm_regname[r16],
2238 arm_regname[iw & 15]);
2239 int rot = ((iw & 0xc00) >> 10) << 3;
2240 if (rot != 0)
2241 debug(",%i", rot);
2242 debug("\n");
2243 break;
2244 }
2245
2246 if ((iw & 0x0fe00070) == 0x07c00010) {
2247 /* bfi rd,rn,#lsb,#width: */
2248 debug("bfi%s\t%s,%s",
2249 condition,
2250 arm_regname[r12],
2251 arm_regname[iw & 15]);
2252 int lsb = (iw >> 7) & 31;
2253 int msb = (iw >> 16) & 31;
2254 int width = msb - lsb + 1;
2255 debug(",%i", lsb);
2256 debug(",%i", width);
2257 debug("\n");
2258 break;
2259 }
2260
2261 if ((iw & 0x0fe00070) == 0x07e00050) {
2262 /* ubfx rd,rn,#lsb,#width: */
2263 debug("ubfx%s\t%s,%s",
2264 condition,
2265 arm_regname[r12],
2266 arm_regname[iw & 15]);
2267 debug(",%i", (iw >> 7) & 31);
2268 debug(",%i", 1 + ((iw >> 16) & 31));
2269 debug("\n");
2270 break;
2271 }
2272
2273 if ((iw & 0x0fe00070) == 0x07a00050) {
2274 /* sbfx rd,rn,#lsb,#width: */
2275 debug("sbfx%s\t%s,%s",
2276 condition,
2277 arm_regname[r12],
2278 arm_regname[iw & 15]);
2279 debug(",%i", (iw >> 7) & 31);
2280 debug(",%i", 1 + ((iw >> 16) & 31));
2281 debug("\n");
2282 break;
2283 }
2284
2285 if ((iw & 0x0fffffff) == 0x07f001f2) {
2286 debug("linux_bug%s\t; see https://github.com/torvalds/linux/blob/master/arch/arm/include/asm/bug.h\n",
2287 condition);
2288 break;
2289 }
2290
2291
2292 /*
2293 * xxxx010P UBWLnnnn ddddoooo oooooooo Immediate form
2294 * xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form
2295 */
2296 p_bit = main_opcode & 1;
2297 if (main_opcode >= 6 && iw & 0x10) {
2298 debug("TODO: single data transf. but 0x10\n");
2299 break;
2300 }
2301 debug("%s%s%s", l_bit? "ldr" : "str",
2302 condition, b_bit? "b" : "");
2303 if (!p_bit && w_bit)
2304 debug("t");
2305 debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
2306 if ((iw & 0x0e000000) == 0x04000000) {
2307 /* Immediate form: */
2308 uint32_t imm = iw & 0xfff;
2309 if (!p_bit)
2310 debug("]");
2311 if (imm != 0)
2312 debug(",#%s%i", u_bit? "" : "-", imm);
2313 if (p_bit)
2314 debug("]");
2315 } else if ((iw & 0x0e000010) == 0x06000000) {
2316 /* Register form: */
2317 if (!p_bit)
2318 debug("]");
2319 if ((iw & 0xfff) != 0)
2320 debug(",%s%s", u_bit? "" : "-",
2321 arm_regname[iw & 15]);
2322 if ((iw & 0xff0) != 0x000) {
2323 int c = (iw >> 7) & 31;
2324 int t = (iw >> 4) & 7;
2325 switch (t) {
2326 case 0: if (c != 0)
2327 debug(", lsl #%i", c);
2328 break;
2329 case 2: debug(", lsr #%i", c? c : 32);
2330 break;
2331 case 4: debug(", asr #%i", c? c : 32);
2332 break;
2333 case 6: if (c != 0)
2334 debug(", ror #%i", c);
2335 else
2336 debug(", rrx");
2337 break;
2338 }
2339 }
2340 if (p_bit)
2341 debug("]");
2342 } else {
2343 debug("UNKNOWN\n");
2344 break;
2345 }
2346 debug("%s", (p_bit && w_bit)? "!" : "");
2347 if ((iw & 0x0f000000) == 0x05000000 &&
2348 (r16 == ARM_PC || running)) {
2349 unsigned char tmpw[4];
2350 uint32_t imm = iw & 0xfff;
2351 uint32_t addr = (u_bit? imm : -imm);
2352 if (r16 == ARM_PC)
2353 addr += dumpaddr + 8;
2354 else
2355 addr += cpu->cd.arm.r[r16];
2356 symbol = get_symbol_name(&cpu->machine->symbol_context,
2357 addr, &offset);
2358 if (symbol != NULL)
2359 debug(" \t<%s", symbol);
2360 else
2361 debug(" \t<0x%08x", addr);
2362 if ((l_bit && cpu->memory_rw(cpu, cpu->mem, addr, tmpw,
2363 b_bit? 1 : sizeof(tmpw), MEM_READ, NO_EXCEPTIONS))
2364 || (!l_bit && running)) {
2365 if (l_bit) {
2366 if (cpu->byte_order ==
2367 EMUL_LITTLE_ENDIAN)
2368 addr = tmpw[0] +(tmpw[1] << 8) +
2369 (tmpw[2]<<16)+(tmpw[3]<<24);
2370 else
2371 addr = tmpw[3] + (tmpw[2]<<8) +
2372 (tmpw[1]<<16)+(tmpw[0]<<24);
2373 } else {
2374 tmpw[0] = addr = cpu->cd.arm.r[r12];
2375 if (r12 == ARM_PC)
2376 addr = cpu->pc + 8;
2377 }
2378 debug(": ");
2379 if (b_bit)
2380 debug("%i", tmpw[0]);
2381 else {
2382 symbol = get_symbol_name(&cpu->machine->
2383 symbol_context, addr, &offset);
2384 if (symbol != NULL)
2385 debug("%s", symbol);
2386 else if ((int32_t)addr > -256 &&
2387 (int32_t)addr < 256)
2388 debug("%i", addr);
2389 else
2390 debug("0x%x", addr);
2391 }
2392 }
2393 debug(">");
2394 }
2395 debug("\n");
2396 break;
2397 case 0x8: /* Block Data Transfer */
2398 case 0x9:
2399 /* xxxx100P USWLnnnn llllllll llllllll */
2400 p_bit = main_opcode & 1;
2401 s_bit = b_bit;
2402 debug("%s%s", l_bit? "ldm" : "stm", condition);
2403 switch (u_bit * 2 + p_bit) {
2404 case 0: debug("da"); break;
2405 case 1: debug("db"); break;
2406 case 2: debug("ia"); break;
2407 case 3: debug("ib"); break;
2408 }
2409 debug("\t%s", arm_regname[r16]);
2410 if (w_bit)
2411 debug("!");
2412 debug(",{");
2413 n = 0;
2414 for (i=0; i<16; i++)
2415 if ((iw >> i) & 1) {
2416 debug("%s%s", (n > 0)? ",":"", arm_regname[i]);
2417 n++;
2418 }
2419 debug("}");
2420 if (s_bit)
2421 debug("^");
2422 debug("\n");
2423 break;
2424 case 0xa: /* B: branch */
2425 case 0xb: /* BL: branch and link */
2426 debug("b%s%s\t", main_opcode == 0xa? "" : "l", condition);
2427 tmp = (iw & 0x00ffffff) << 2;
2428 if (tmp & 0x02000000)
2429 tmp |= 0xfc000000;
2430 tmp = (int32_t)(dumpaddr + tmp + 8);
2431 debug("0x%x", (int)tmp);
2432 symbol = get_symbol_name(&cpu->machine->symbol_context,
2433 tmp, &offset);
2434 if (symbol != NULL)
2435 debug(" \t<%s>", symbol);
2436 debug("\n");
2437 break;
2438 case 0xc: /* Coprocessor */
2439 case 0xd: /* LDC/STC */
2440 /*
2441 * xxxx1100 0100nnnn ddddcccc oooommmm MCRR c,op,Rd,Rn,CRm
2442 * xxxx1100 0101nnnn ddddcccc oooommmm MRRC c,op,Rd,Rn,CRm
2443 */
2444 if ((iw & 0x0fe00fff) == 0x0c400000) {
2445 debug("%s%s\t", iw & 0x100000? "mra" : "mar",
2446 condition);
2447 if (iw & 0x100000)
2448 debug("%s,%s,acc0\n",
2449 arm_regname[r12], arm_regname[r16]);
2450 else
2451 debug("acc0,%s,%s\n",
2452 arm_regname[r12], arm_regname[r16]);
2453 break;
2454 }
2455 if ((iw & 0x0fe00000) == 0x0c400000) {
2456 debug("%s%s\t", iw & 0x100000? "mrrc" : "mcrr",
2457 condition);
2458 debug("%i,%i,%s,%s,cr%i\n", r8, (iw >> 4) & 15,
2459 arm_regname[r12], arm_regname[r16], iw & 15);
2460 break;
2461 }
2462
2463 /* xxxx110P UNWLnnnn DDDDpppp oooooooo LDC/STC */
2464 debug("TODO: coprocessor LDC/STC\n");
2465 break;
2466 case 0xe: /* CDP (Coprocessor Op) */
2467 /* or MRC/MCR!
2468 * xxxx1110 oooonnnn ddddpppp qqq0mmmm CDP
2469 * xxxx1110 oooLNNNN ddddpppp qqq1MMMM MRC/MCR
2470 */
2471 if ((iw & 0x0ff00ff0) == 0x0e200010) {
2472 /* Special case: mia* DSP instructions */
2473 switch ((iw >> 16) & 0xf) {
2474 case 0: debug("mia"); break;
2475 case 8: debug("miaph"); break;
2476 case 12: debug("miaBB"); break;
2477 case 13: debug("miaTB"); break;
2478 case 14: debug("miaBT"); break;
2479 case 15: debug("miaTT"); break;
2480 default: debug("UNKNOWN mia vector instruction?");
2481 }
2482 debug("%s\t", condition);
2483 debug("acc%i,%s,%s\n", ((iw >> 5) & 7),
2484 arm_regname[iw & 15], arm_regname[r12]);
2485 break;
2486 }
2487 if (iw & 0x10) {
2488 debug("%s%s\t",
2489 (iw & 0x00100000)? "mrc" : "mcr", condition);
2490 debug("%i,%i,r%i,cr%i,cr%i,%i",
2491 (int)((iw >> 8) & 15), (int)((iw >>21) & 7),
2492 (int)((iw >>12) & 15), (int)((iw >>16) & 15),
2493 (int)((iw >> 0) & 15), (int)((iw >> 5) & 7));
2494 } else {
2495 debug("cdp%s\t", condition);
2496 debug("%i,%i,cr%i,cr%i,cr%i",
2497 (int)((iw >> 8) & 15),
2498 (int)((iw >>20) & 15),
2499 (int)((iw >>12) & 15),
2500 (int)((iw >>16) & 15),
2501 (int)((iw >> 0) & 15));
2502 if ((iw >> 5) & 7)
2503 debug(",0x%x", (int)((iw >> 5) & 7));
2504 }
2505 debug("\n");
2506 break;
2507 case 0xf: /* SWI */
2508 debug("swi%s\t", condition);
2509 debug("0x%x\n", (int)(iw & 0x00ffffff));
2510 break;
2511 default:debug("UNIMPLEMENTED\n");
2512 }
2513
2514 return sizeof(uint32_t);
2515 }
2516
2517
2518 /*****************************************************************************/
2519
2520
2521 /*
2522 * arm_mcr_mrc():
2523 *
2524 * Coprocessor register move.
2525 *
2526 * The program counter should be synched before calling this function (to
2527 * make debug output with the correct PC value possible).
2528 */
arm_mcr_mrc(struct cpu * cpu,uint32_t iword)2529 void arm_mcr_mrc(struct cpu *cpu, uint32_t iword)
2530 {
2531 int opcode1 = (iword >> 21) & 7;
2532 int l_bit = (iword >> 20) & 1;
2533 int crn = (iword >> 16) & 15;
2534 int rd = (iword >> 12) & 15;
2535 int cp_num = (iword >> 8) & 15;
2536 int opcode2 = (iword >> 5) & 7;
2537 int crm = iword & 15;
2538
2539 if (cpu->cd.arm.coproc[cp_num] != NULL)
2540 cpu->cd.arm.coproc[cp_num](cpu, opcode1, opcode2, l_bit,
2541 crn, crm, rd);
2542 else {
2543 fatal("[ TODO: arm_mcr_mrc: pc=0x%08x, iword=0x%08x: "
2544 "cp_num=%i ]\n", (int)cpu->pc, iword, cp_num);
2545
2546 // arm_exception(cpu, ARM_EXCEPTION_UND);
2547 /* exit(1); */
2548 }
2549 }
2550
2551
2552 /*
2553 * arm_cdp():
2554 *
2555 * Coprocessor operations.
2556 *
2557 * The program counter should be synched before calling this function (to
2558 * make debug output with the correct PC value possible).
2559 */
arm_cdp(struct cpu * cpu,uint32_t iword)2560 void arm_cdp(struct cpu *cpu, uint32_t iword)
2561 {
2562 fatal("[ arm_cdp: pc=0x%08x, iword=0x%08x ]\n", (int)cpu->pc, iword);
2563 arm_exception(cpu, ARM_EXCEPTION_UND);
2564 /* exit(1); */
2565 }
2566
2567
2568 /*****************************************************************************/
2569
2570
2571 #include "tmp_arm_tail.cc"
2572
2573