cpu_arm.cc Source File

Back to the index.

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