cpu_arm.cc Source File

Back to the index.

cpu_arm.cc
Go to the documentation of this file.
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 
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  */
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 
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;
124 
125  cpu->vaddr_mask = 0x00000000ffffffffULL;
126 
130  /* TODO: default auxctrl contents */
131 
132  if (cpu->machine->prom_emulation) {
135  } else {
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 =
159  | ((cpu->cd.arm.cpu_type.dcache_shift - 9) <<
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) <<
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: */
174 
175  /*
176  * NOTE/TODO: Ugly hack for OpenFirmware emulation:
177  */
178  if (cpu->machine->prom_emulation) {
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 
187  for (i=0; i<N_ARM_REGS - 1; i++)
188  CPU_SETTINGS_ADD_REGISTER32(arm_regname[i], cpu->cd.arm.r[i]);
189 
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;
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  */
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 
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 
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  */
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 
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  */
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 
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  */
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  */
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  */
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) {
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,
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,
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  */
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",
553  exit(1);
554  }
555 }
556 
557 
558 /*
559  * arm_load_register_bank():
560  */
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",
600  exit(1);
601  }
602 }
603 
604 
605 /*
606  * arm_exception():
607  */
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;
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;
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);
655  retaddr += 4;
656  break;
657  }
658 
659  retaddr += (cpu->cd.arm.cpsr & ARM_FLAG_T ? 2 : 4);
660 
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: */
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);
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  */
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  */
748 {
749  struct cpu *cpu = (struct cpu *) interrupt->extra;
750  cpu->cd.arm.irq_asserted = 1;
751 }
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  */
766 int arm_cpu_disassemble_instr_thumb(struct cpu *cpu, unsigned char *ib,
767  int running, uint64_t dumpaddr)
768 {
769  uint16_t iw;
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);
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);
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);
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);
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  */
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;
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);
1130  }
1131 
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)
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 
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 
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) {
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)
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)
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  */
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 
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 
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);
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) {
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];
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 ==
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 {
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);
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  */
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  */
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);
2564  /* exit(1); */
2565 }
2566 
2567 
2568 /*****************************************************************************/
2569 
2570 
2571 #include "tmp_arm_tail.cc"
2572 
ARM_MODE_SVC32
#define ARM_MODE_SVC32
Definition: cpu_arm.h:111
arm_translate_v2p
int arm_translate_v2p(struct cpu *cpu, uint64_t vaddr64, uint64_t *return_paddr, int flags)
Definition: memory_arm.cc:54
cpu::ninstrs
int64_t ninstrs
Definition: cpu.h:340
ARM_FLAG_I
#define ARM_FLAG_I
Definition: cpu_arm.h:99
ARM_EXCEPTION_DATA_ABT
#define ARM_EXCEPTION_DATA_ABT
Definition: cpu_arm.h:126
ARM_THUMB_DPI_NAMES
#define ARM_THUMB_DPI_NAMES
Definition: cpu_arm.h:72
ARM_CONTROL_CACHE
#define ARM_CONTROL_CACHE
Definition: cpu_arm.h:259
ARM_EXCEPTION_PREF_ABT
#define ARM_EXCEPTION_PREF_ABT
Definition: cpu_arm.h:125
condition_hi
uint8_t condition_hi[16]
Definition: cpu_arm_instr.cc:128
cpu::cpu_id
int cpu_id
Definition: cpu.h:359
ARM_CONTROL_V
#define ARM_CONTROL_V
Definition: cpu_arm.h:269
ARM_CACHETYPE_ISIZE_SHIFT
#define ARM_CACHETYPE_ISIZE_SHIFT
Definition: cpu_arm.h:291
cpu::running
uint8_t running
Definition: cpu.h:353
tmp_arm_tail.cc
interrupt::interrupt_deassert
void(* interrupt_deassert)(struct interrupt *)
Definition: interrupt.h:39
arm_cpu_disassemble_instr_thumb
int arm_cpu_disassemble_instr_thumb(struct cpu *cpu, unsigned char *ib, int running, uint64_t dumpaddr)
Definition: cpu_arm.cc:766
machine::symbol_context
struct symbol_context symbol_context
Definition: machine.h:144
CPU_SETTINGS_ADD_REGISTER32
#define CPU_SETTINGS_ADD_REGISTER32(name, var)
Definition: cpu.h:493
settings.h
ARM_FLAG_V
#define ARM_FLAG_V
Definition: cpu_arm.h:94
memory
Definition: memory.h:75
N_ARM_EXCEPTIONS
#define N_ARM_EXCEPTIONS
Definition: cpu_arm.h:120
debug
#define debug
Definition: dev_adb.cc:57
condition_ge
uint8_t condition_ge[16]
Definition: cpu_arm_instr.cc:129
get_symbol_name
char * get_symbol_name(struct symbol_context *, uint64_t addr, uint64_t *offset)
Definition: symbol.cc:188
cpu_functioncall_trace_return
void cpu_functioncall_trace_return(struct cpu *cpu)
Definition: cpu.cc:284
symbol_context
Definition: symbol.h:49
arm_cpu::default_r8_r14
uint32_t default_r8_r14[7]
Definition: cpu_arm.h:157
ARM_CONTROL_ALIGN
#define ARM_CONTROL_ALIGN
Definition: cpu_arm.h:258
arm_cpu::auxctrl
uint32_t auxctrl
Definition: cpu_arm.h:188
machine::show_trace_tree
int show_trace_tree
Definition: machine.h:164
ARM_MODE_SYS32
#define ARM_MODE_SYS32
Definition: cpu_arm.h:114
arm_cpu_dumpinfo
void arm_cpu_dumpinfo(struct cpu *cpu)
Definition: cpu_arm.cc:312
ARM_DPI_NAMES
#define ARM_DPI_NAMES
Definition: cpu_arm.h:68
if
addr & if(addr >=0x24 &&page !=NULL)
Definition: tmp_arm_multi.cc:56
arm_cpu::coproc
void(* coproc[16])(struct cpu *, int opcode1, int opcode2, int l_bit, int crn, int crm, int rd)
Definition: cpu_arm.h:143
arm_cdp
void arm_cdp(struct cpu *cpu, uint32_t iword)
Definition: cpu_arm.cc:2560
N_ARM_REGS
#define N_ARM_REGS
Definition: cpu_arm.h:57
arm_cpu::dacr
uint32_t dacr
Definition: cpu_arm.h:190
MEM_READ
#define MEM_READ
Definition: memory.h:116
ARM_REG_NAMES
#define ARM_REG_NAMES
Definition: cpu_arm.h:59
arm_pop
void arm_pop(struct cpu *cpu, uint32_t *np, int p_bit, int u_bit, int s_bit, int w_bit, uint32_t iw)
Definition: cpu_arm_instr.cc:1352
t
vmrs t
Definition: armreg.h:750
cpu::byte_order
uint8_t byte_order
Definition: cpu.h:347
arm_cpu::of_emul_addr
uint32_t of_emul_addr
Definition: cpu_arm.h:141
cpu_functioncall_trace
void cpu_functioncall_trace(struct cpu *cpu, uint64_t f)
Definition: cpu.cc:228
cpu::update_translation_table
void(* update_translation_table)(struct cpu *, uint64_t vaddr_page, unsigned char *host_page, int writeflag, uint64_t paddr_page)
Definition: cpu.h:374
arm_cpu::cpsr
uint32_t cpsr
Definition: cpu_arm.h:175
interrupt::extra
void * extra
Definition: interrupt.h:59
ARM_MODE_ABT32
#define ARM_MODE_ABT32
Definition: cpu_arm.h:112
arm_setup_initial_translation_table
void arm_setup_initial_translation_table(struct cpu *cpu, uint32_t ttb_addr)
Definition: cpu_arm.cc:220
addr
uint32_t addr
Definition: tmp_arm_multi.cc:52
arm_cpu::far
uint32_t far
Definition: cpu_arm.h:192
machine::prom_emulation
int prom_emulation
Definition: machine.h:149
ARM_CONTROL_R
#define ARM_CONTROL_R
Definition: cpu_arm.h:265
ARM_CONTROL_MMU
#define ARM_CONTROL_MMU
Definition: cpu_arm.h:257
CPU_SETTINGS_ADD_REGISTER64
#define CPU_SETTINGS_ADD_REGISTER64(name, var)
Definition: cpu.h:489
ARM_AUXCTRL_MD_SHIFT
#define ARM_AUXCTRL_MD_SHIFT
Definition: cpu_arm.h:275
arm_cpu_register_dump
void arm_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
Definition: cpu_arm.cc:351
arm_cpu::control
uint32_t control
Definition: cpu_arm.h:187
ARM_CONTROL_S
#define ARM_CONTROL_S
Definition: cpu_arm.h:264
ARM_CACHETYPE_DASSOC_SHIFT
#define ARM_CACHETYPE_DASSOC_SHIFT
Definition: cpu_arm.h:287
MEM_WRITE
#define MEM_WRITE
Definition: memory.h:117
cpu::invalidate_code_translation
void(* invalidate_code_translation)(struct cpu *, uint64_t paddr, int flags)
Definition: cpu.h:379
arm_cpu::fsr
uint32_t fsr
Definition: cpu_arm.h:191
ARM_AUXCTRL_K
#define ARM_AUXCTRL_K
Definition: cpu_arm.h:277
condition_gt
uint8_t condition_gt[16]
Definition: cpu_arm_instr.cc:130
ARM_MODE_FIQ32
#define ARM_MODE_FIQ32
Definition: cpu_arm.h:109
machine::instruction_trace
int instruction_trace
Definition: machine.h:162
arm_cpu::flags
size_t flags
Definition: cpu_arm.h:174
arm_push
void arm_push(struct cpu *cpu, uint32_t *np, int p_bit, int u_bit, int s_bit, int w_bit, uint16_t regs)
Definition: cpu_arm_instr.cc:1518
ARM_FLAG_E
#define ARM_FLAG_E
Definition: cpu_arm.h:97
arm_cpu::tmp_branch
uint32_t tmp_branch
Definition: cpu_arm.h:165
ARM_CONTROL_PROG32
#define ARM_CONTROL_PROG32
Definition: cpu_arm.h:261
arm_cpu_interpret_thumb_SLOW
int arm_cpu_interpret_thumb_SLOW(struct cpu *cpu)
Definition: cpu_arm.cc:1097
arm_cpu::spsr_und
uint32_t spsr_und
Definition: cpu_arm.h:178
arm_cpu_disassemble_instr
int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib, int running, uint64_t dumpaddr)
Definition: cpu_arm.cc:1720
arm_cpu_types.h
op
char * op[16]
Definition: generate_arm_dpi.c:34
strlen
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
Definition: cpu_arm_instr.cc:2686
interrupt.h
PHYSICAL
#define PHYSICAL
Definition: memory.h:126
fatal
void fatal(const char *fmt,...)
Definition: main.cc:152
arm_cpu::und_r13_r14
uint32_t und_r13_r14[2]
Definition: cpu_arm.h:162
arm_cpu::spsr_irq
uint32_t spsr_irq
Definition: cpu_arm.h:179
misc.h
ARM_AUXCTRL_P
#define ARM_AUXCTRL_P
Definition: cpu_arm.h:276
ARM_FLAG_Z
#define ARM_FLAG_Z
Definition: cpu_arm.h:92
arm_cpu::cachetype
uint32_t cachetype
Definition: cpu_arm.h:186
arm_cpu::irq_asserted
int irq_asserted
Definition: cpu_arm.h:235
cpu::cd
union cpu::@1 cd
arm_load_register_bank
void arm_load_register_bank(struct cpu *cpu)
Definition: cpu_arm.cc:561
machine.h
machine
Definition: machine.h:97
cpu::vaddr_mask
uint64_t vaddr_mask
Definition: cpu.h:365
cpu::name
char * name
Definition: cpu.h:334
arm_cpu_list_available_types
void arm_cpu_list_available_types(void)
Definition: cpu_arm.cc:326
quiet_mode
int quiet_mode
Definition: emul.cc:68
CACHE_INSTRUCTION
#define CACHE_INSTRUCTION
Definition: memory.h:122
of.h
ARM_EXCEPTION_UND
#define ARM_EXCEPTION_UND
Definition: cpu_arm.h:123
ARM_MODE_UND32
#define ARM_MODE_UND32
Definition: cpu_arm.h:113
ARM_MODE_USR32
#define ARM_MODE_USR32
Definition: cpu_arm.h:108
ARM_LR
#define ARM_LR
Definition: cpu_arm.h:55
ARM_FLAG_F
#define ARM_FLAG_F
Definition: cpu_arm.h:100
arm_mcr_mrc
void arm_mcr_mrc(struct cpu *cpu, uint32_t iword)
Definition: cpu_arm.cc:2529
arm_cpu::spsr_abt
uint32_t spsr_abt
Definition: cpu_arm.h:177
CACHE_DATA
#define CACHE_DATA
Definition: memory.h:121
arm_cpu::r
uint32_t r[N_ARM_REGS]
Definition: cpu_arm.h:155
arm_save_register_bank
void arm_save_register_bank(struct cpu *cpu)
Definition: cpu_arm.cc:514
ARM_CACHETYPE_IASSOC_SHIFT
#define ARM_CACHETYPE_IASSOC_SHIFT
Definition: cpu_arm.h:293
ARM_FLAG_Q
#define ARM_FLAG_Q
Definition: cpu_arm.h:95
ARM_CONDITION_STRINGS
#define ARM_CONDITION_STRINGS
Definition: cpu_arm.h:63
arm_cpu_type_def::name
const char * name
Definition: cpu_arm.h:41
cpu::invalidate_translation_caches
void(* invalidate_translation_caches)(struct cpu *, uint64_t paddr, int flags)
Definition: cpu.h:377
ARM_EXCEPTION_TO_MODE
#define ARM_EXCEPTION_TO_MODE
Definition: cpu_arm.h:116
arm_cpu_new
int arm_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine, int cpu_id, char *cpu_type_name)
Definition: cpu_arm.cc:94
cpu::is_32bit
uint8_t is_32bit
Definition: cpu.h:350
symbol.h
cpu.h
arm_invalidate_code_translation
void arm_invalidate_code_translation(struct cpu *cpu, uint64_t, int)
arm_run_instr
int arm_run_instr(struct cpu *cpu)
ARM_EXCEPTION_IRQ
#define ARM_EXCEPTION_IRQ
Definition: cpu_arm.h:128
arm_cpu_type_def::flags
int flags
Definition: cpu_arm.h:43
cpu::translate_v2p
int(* translate_v2p)(struct cpu *, uint64_t vaddr, uint64_t *return_paddr, int flags)
Definition: cpu.h:372
arm_irq_interrupt_deassert
void arm_irq_interrupt_deassert(struct interrupt *interrupt)
Definition: cpu_arm.cc:752
ARM_FLAG_T
#define ARM_FLAG_T
Definition: cpu_arm.h:101
ARM_FLAG_N
#define ARM_FLAG_N
Definition: cpu_arm.h:91
ARM_FLAG_C
#define ARM_FLAG_C
Definition: cpu_arm.h:93
ARM_CACHETYPE_CLASS_SHIFT
#define ARM_CACHETYPE_CLASS_SHIFT
Definition: cpu_arm.h:281
arm_cpu::spsr_fiq
uint32_t spsr_fiq
Definition: cpu_arm.h:180
ARM_MODE_IRQ32
#define ARM_MODE_IRQ32
Definition: cpu_arm.h:110
ARM_PC
#define ARM_PC
Definition: cpu_arm.h:56
cpu::mem
struct memory * mem
Definition: cpu.h:362
ARM_F_N
#define ARM_F_N
Definition: cpu_arm.h:86
ARM_CACHETYPE_HARVARD_SHIFT
#define ARM_CACHETYPE_HARVARD_SHIFT
Definition: cpu_arm.h:283
arm_translation_table_set_l1
void arm_translation_table_set_l1(struct cpu *cpu, uint32_t vaddr, uint32_t paddr)
Definition: cpu_arm.cc:256
arm_cpu_type_def
Definition: cpu_arm.h:40
machine::physical_ram_in_mb
uint32_t physical_ram_in_mb
Definition: machine.h:147
EMUL_LITTLE_ENDIAN
#define EMUL_LITTLE_ENDIAN
Definition: misc.h:164
arm_coproc_xscale_14
void arm_coproc_xscale_14(struct cpu *cpu, int opcode1, int opcode2, int l_bit, int crn, int crm, int rd)
Definition: cpu_arm_coproc.cc:416
cpu::machine
struct machine * machine
Definition: cpu.h:328
arm_cpu_type_def::cpu_id
uint32_t cpu_id
Definition: cpu_arm.h:42
arm_update_translation_table
void arm_update_translation_table(struct cpu *cpu, uint64_t vaddr_page, unsigned char *host_page, int writeflag, uint64_t paddr_page)
arm_cpu::irq_r13_r14
uint32_t irq_r13_r14[2]
Definition: cpu_arm.h:159
arm_cpu_type_def::icache_shift
int icache_shift
Definition: cpu_arm.h:44
ARM_CONTROL_WBUFFER
#define ARM_CONTROL_WBUFFER
Definition: cpu_arm.h:260
ARM_FLAG_MODE
#define ARM_FLAG_MODE
Definition: cpu_arm.h:103
arm_cpu::ttb
uint32_t ttb
Definition: cpu_arm.h:189
ARM_CONTROL_DATA32
#define ARM_CONTROL_DATA32
Definition: cpu_arm.h:262
ARM_EXCEPTION_FIQ
#define ARM_EXCEPTION_FIQ
Definition: cpu_arm.h:129
NO_EXCEPTIONS
#define NO_EXCEPTIONS
Definition: memory.h:125
ARM_F_Z
#define ARM_F_Z
Definition: cpu_arm.h:87
arm_cpu::cpu_type
struct arm_cpu_type_def cpu_type
Definition: cpu_arm.h:140
cpu::arm
struct arm_cpu arm
Definition: cpu.h:444
ARM_CACHETYPE_ILINE_SHIFT
#define ARM_CACHETYPE_ILINE_SHIFT
Definition: cpu_arm.h:295
symbol
Definition: symbol.h:37
arm_translate_v2p_mmu
int arm_translate_v2p_mmu(struct cpu *cpu, uint64_t vaddr64, uint64_t *return_paddr, int flags)
Definition: memory_arm.cc:114
store_32bit_word
int store_32bit_word(struct cpu *cpu, uint64_t addr, uint64_t data32)
Definition: memory.cc:783
arm_exception
void arm_exception(struct cpu *cpu, int exception_nr)
Definition: cpu_arm.cc:608
ARM_FLAG_A
#define ARM_FLAG_A
Definition: cpu_arm.h:98
arm_invalidate_translation_caches
void arm_invalidate_translation_caches(struct cpu *cpu, uint64_t, int)
cpu::run_instr
int(* run_instr)(struct cpu *cpu)
Definition: cpu.h:367
arm_cpu_type_def::dcache_shift
int dcache_shift
Definition: cpu_arm.h:46
arm_irq_interrupt_assert
void arm_irq_interrupt_assert(struct interrupt *interrupt)
Definition: cpu_arm.cc:747
arm_cpu_tlbdump
void arm_cpu_tlbdump(struct machine *m, int x, int rawflag)
Definition: cpu_arm.cc:738
interrupt::line
uint32_t line
Definition: interrupt.h:51
arm_coproc_15
void arm_coproc_15(struct cpu *cpu, int opcode1, int opcode2, int l_bit, int crn, int crm, int rd)
Definition: cpu_arm_coproc.cc:50
ARM_CPU_TYPE_DEFS
#define ARM_CPU_TYPE_DEFS
Definition: arm_cpu_types.h:50
ARM_CACHETYPE_DLINE_SHIFT
#define ARM_CACHETYPE_DLINE_SHIFT
Definition: cpu_arm.h:289
ARM_FLAG_J
#define ARM_FLAG_J
Definition: cpu_arm.h:96
interrupt::interrupt_assert
void(* interrupt_assert)(struct interrupt *)
Definition: interrupt.h:38
ARM_CONTROL_BIG
#define ARM_CONTROL_BIG
Definition: cpu_arm.h:263
arm_translation_table_set_l1_b
void arm_translation_table_set_l1_b(struct cpu *cpu, uint32_t vaddr, uint32_t paddr)
Definition: cpu_arm.cc:284
interrupt_handler_register
void interrupt_handler_register(struct interrupt *templ)
Definition: interrupt.cc:81
quick_pc_to_pointers
#define quick_pc_to_pointers(cpu)
Definition: quick_pc_to_pointers.h:29
interrupt::name
char * name
Definition: interrupt.h:66
arm_cpu::abt_r13_r14
uint32_t abt_r13_r14[2]
Definition: cpu_arm.h:161
interrupt
Definition: interrupt.h:36
arm_memory_rw
int arm_memory_rw(struct cpu *cpu, struct memory *mem, uint64_t vaddr, unsigned char *data, size_t len, int writeflag, int cache_flags)
arm_cpu::svc_r13_r14
uint32_t svc_r13_r14[2]
Definition: cpu_arm.h:160
ARM_CONTROL_ICACHE
#define ARM_CONTROL_ICACHE
Definition: cpu_arm.h:268
cpu
Definition: cpu.h:326
arm_cpu::spsr_svc
uint32_t spsr_svc
Definition: cpu_arm.h:176
ARM_F_V
#define ARM_F_V
Definition: cpu_arm.h:89
cpu::memory_rw
int(* memory_rw)(struct cpu *cpu, struct memory *mem, uint64_t vaddr, unsigned char *data, size_t len, int writeflag, int cache_flags)
Definition: cpu.h:368
ARM_SP
#define ARM_SP
Definition: cpu_arm.h:54
ARM_CACHETYPE_DSIZE_SHIFT
#define ARM_CACHETYPE_DSIZE_SHIFT
Definition: cpu_arm.h:285
cpu::path
char * path
Definition: cpu.h:337
ARM_XSCALE
#define ARM_XSCALE
Definition: arm_cpu_types.h:42
cpu::pc
uint64_t pc
Definition: cpu.h:386
memory.h
tmp_arm_head.cc
quick_pc_to_pointers.h
arm_pc_to_pointers
void arm_pc_to_pointers(struct cpu *cpu)
ARM_AUXCTRL_MD
#define ARM_AUXCTRL_MD
Definition: cpu_arm.h:274
ARM_F_C
#define ARM_F_C
Definition: cpu_arm.h:88
machine::ncpus
int ncpus
Definition: machine.h:139
ARM_EXCEPTION_SWI
#define ARM_EXCEPTION_SWI
Definition: cpu_arm.h:124
ARM_EXCEPTION_RESET
#define ARM_EXCEPTION_RESET
Definition: cpu_arm.h:122
arm_cpu::fiq_r8_r14
uint32_t fiq_r8_r14[7]
Definition: cpu_arm.h:158

Generated on Tue Aug 25 2020 19:25:06 for GXemul by doxygen 1.8.18