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