cpu_arm.cc Source File

Back to the index.

cpu_arm.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2014 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  *
32  * http://www.pinknoise.demon.co.uk/ARMinstrs/ARMinstrs.html
33  */
34 
35 #include <stdio.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <ctype.h>
39 #include <unistd.h>
40 
41 #include "arm_cpu_types.h"
42 #include "cpu.h"
43 #include "interrupt.h"
44 #include "machine.h"
45 #include "memory.h"
46 #include "misc.h"
47 #include "of.h"
48 #include "settings.h"
49 #include "symbol.h"
50 
51 #define DYNTRANS_32
52 #include "tmp_arm_head.cc"
53 
54 
55 /* ARM symbolic register names and condition strings: */
56 static const char *arm_regname[N_ARM_REGS] = ARM_REG_NAMES;
57 static const char *arm_condition_string[16] = ARM_CONDITION_STRINGS;
58 
59 /* Data Processing Instructions: */
60 static const char *arm_dpiname[16] = ARM_DPI_NAMES;
61 static int arm_dpi_uses_d[16] = { 1,1,1,1,1,1,1,1,0,0,0,0,1,1,1,1 };
62 static int arm_dpi_uses_n[16] = { 1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0 };
63 
64 static int arm_exception_to_mode[N_ARM_EXCEPTIONS] = ARM_EXCEPTION_TO_MODE;
65 
66 /* For quick_pc_to_pointers(): */
67 void arm_pc_to_pointers(struct cpu *cpu);
68 #include "quick_pc_to_pointers.h"
69 
71 void arm_irq_interrupt_deassert(struct interrupt *interrupt);
72 
73 
74 /*
75  * arm_cpu_new():
76  *
77  * Create a new ARM cpu object by filling the CPU struct.
78  * Return 1 on success, 0 if cpu_type_name isn't a valid ARM processor.
79  */
80 int arm_cpu_new(struct cpu *cpu, struct memory *mem,
81  struct machine *machine, int cpu_id, char *cpu_type_name)
82 {
83  int i, found;
84  struct arm_cpu_type_def cpu_type_defs[] = ARM_CPU_TYPE_DEFS;
85 
86  /* Scan the list for this cpu type: */
87  i = 0; found = -1;
88  while (i >= 0 && cpu_type_defs[i].name != NULL) {
89  if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
90  found = i;
91  break;
92  }
93  i++;
94  }
95  if (found == -1)
96  return 0;
97 
98  cpu->run_instr = arm_run_instr;
99  cpu->memory_rw = arm_memory_rw;
105 
106  cpu->cd.arm.cpu_type = cpu_type_defs[found];
107  cpu->name = strdup(cpu->cd.arm.cpu_type.name);
108  cpu->is_32bit = 1;
110 
111  cpu->cd.arm.cpsr = ARM_FLAG_I | ARM_FLAG_F;
114  /* TODO: default auxctrl contents */
115 
116  if (cpu->machine->prom_emulation) {
117  cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
118  cpu->cd.arm.control |= ARM_CONTROL_S;
119  } else {
120  cpu->cd.arm.cpsr |= ARM_MODE_SVC32;
121  cpu->cd.arm.control |= ARM_CONTROL_R;
122  }
123 
124  /* Only show name and caches etc for CPU nr 0: */
125  if (cpu_id == 0) {
126  debug("%s", cpu->name);
127  if (cpu->cd.arm.cpu_type.icache_shift != 0 ||
128  cpu->cd.arm.cpu_type.dcache_shift != 0) {
129  int isize = cpu->cd.arm.cpu_type.icache_shift;
130  int dsize = cpu->cd.arm.cpu_type.dcache_shift;
131  if (isize != 0)
132  isize = 1 << (isize - 10);
133  if (dsize != 0)
134  dsize = 1 << (dsize - 10);
135  debug(" (I+D = %i+%i KB)", isize, dsize);
136  }
137  }
138 
139  /* TODO: Some of these values (iway and dway) aren't used yet: */
140  cpu->cd.arm.cachetype =
143  | ((cpu->cd.arm.cpu_type.dcache_shift - 9) <<
145  | (5 << ARM_CACHETYPE_DASSOC_SHIFT) /* 32-way */
146  | (2 << ARM_CACHETYPE_DLINE_SHIFT) /* 8 words/line */
147  | ((cpu->cd.arm.cpu_type.icache_shift - 9) <<
149  | (5 << ARM_CACHETYPE_IASSOC_SHIFT) /* 32-way */
150  | (2 << ARM_CACHETYPE_ILINE_SHIFT); /* 8 words/line */
151 
152  /* Coprocessor 15 = the system control coprocessor. */
153  cpu->cd.arm.coproc[15] = arm_coproc_15;
154 
155  /* Coprocessor 14 for XScale: */
156  if (cpu->cd.arm.cpu_type.flags & ARM_XSCALE)
157  cpu->cd.arm.coproc[14] = arm_coproc_xscale_14;
158 
159  /*
160  * NOTE/TODO: Ugly hack for OpenFirmware emulation:
161  */
162  if (cpu->machine->prom_emulation) {
164  * 1048576 - 8;
165  store_32bit_word(cpu, cpu->cd.arm.of_emul_addr, 0xef8c64be);
166  }
167 
168  cpu->cd.arm.flags = cpu->cd.arm.cpsr >> 28;
169 
170  CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
171  for (i=0; i<N_ARM_REGS - 1; i++)
172  CPU_SETTINGS_ADD_REGISTER32(arm_regname[i], cpu->cd.arm.r[i]);
173 
174  CPU_SETTINGS_ADD_REGISTER32("cpsr", cpu->cd.arm.cpsr);
175 
176  /* Register the CPU's "IRQ" and "FIQ" interrupts: */
177  {
178  struct interrupt templ;
179  char name[50];
180  snprintf(name, sizeof(name), "%s.irq", cpu->path);
181 
182  memset(&templ, 0, sizeof(templ));
183  templ.line = 0;
184  templ.name = name;
185  templ.extra = cpu;
189 
190  /* FIQ: TODO */
191  }
192 
193  return 1;
194 }
195 
196 
197 /*
198  * arm_setup_initial_translation_table():
199  *
200  * When booting kernels (such as OpenBSD or NetBSD) directly, it is assumed
201  * that the MMU is already enabled by the boot-loader. This function tries
202  * to emulate that.
203  */
204 void arm_setup_initial_translation_table(struct cpu *cpu, uint32_t ttb_addr)
205 {
206  unsigned char nothing[16384];
207  unsigned int i, j;
208 
209  cpu->cd.arm.control |= ARM_CONTROL_MMU;
211  cpu->cd.arm.dacr |= 0x00000003;
212  cpu->cd.arm.ttb = ttb_addr;
213 
214  memset(nothing, 0, sizeof(nothing));
215  cpu->memory_rw(cpu, cpu->mem, cpu->cd.arm.ttb, nothing,
216  sizeof(nothing), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
217  for (i=0; i<256; i++)
218  for (j=0x0; j<=0xf; j++) {
219  unsigned char descr[4];
220  uint32_t addr = cpu->cd.arm.ttb +
221  (((j << 28) + (i << 20)) >> 18);
222  uint32_t d = (1048576*i) | 0xc02;
223 
224  if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
225  descr[0] = d; descr[1] = d >> 8;
226  descr[2] = d >> 16; descr[3] = d >> 24;
227  } else {
228  descr[3] = d; descr[2] = d >> 8;
229  descr[1] = d >> 16; descr[0] = d >> 24;
230  }
231  cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
232  sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
233  }
234 }
235 
236 
237 /*
238  * arm_translation_table_set_l1():
239  */
240 void arm_translation_table_set_l1(struct cpu *cpu, uint32_t vaddr,
241  uint32_t paddr)
242 {
243  unsigned int i, j, vhigh = vaddr >> 28, phigh = paddr >> 28;
244 
245  for (i=0; i<256; i++)
246  for (j=vhigh; j<=vhigh; j++) {
247  unsigned char descr[4];
248  uint32_t addr = cpu->cd.arm.ttb +
249  (((j << 28) + (i << 20)) >> 18);
250  uint32_t d = ((phigh << 28) + 1048576*i) | 0xc02;
251 
252  if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
253  descr[0] = d; descr[1] = d >> 8;
254  descr[2] = d >> 16; descr[3] = d >> 24;
255  } else {
256  descr[3] = d; descr[2] = d >> 8;
257  descr[1] = d >> 16; descr[0] = d >> 24;
258  }
259  cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
260  sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
261  }
262 }
263 
264 
265 /*
266  * arm_translation_table_set_l1_b():
267  */
268 void arm_translation_table_set_l1_b(struct cpu *cpu, uint32_t vaddr,
269  uint32_t paddr)
270 {
271  unsigned int i, j, vhigh = vaddr >> 24, phigh = paddr >> 24;
272 
273  for (i=0; i<16; i++)
274  for (j=vhigh; j<=vhigh; j++) {
275  unsigned char descr[4];
276  uint32_t addr = cpu->cd.arm.ttb +
277  (((j << 24) + (i << 20)) >> 18);
278  uint32_t d = ((phigh << 24) + 1048576*i) | 0xc02;
279 
280  if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
281  descr[0] = d; descr[1] = d >> 8;
282  descr[2] = d >> 16; descr[3] = d >> 24;
283  } else {
284  descr[3] = d; descr[2] = d >> 8;
285  descr[1] = d >> 16; descr[0] = d >> 24;
286  }
287  cpu->memory_rw(cpu, cpu->mem, addr, &descr[0],
288  sizeof(descr), MEM_WRITE, PHYSICAL | NO_EXCEPTIONS);
289  }
290 }
291 
292 
293 /*
294  * arm_cpu_dumpinfo():
295  */
296 void arm_cpu_dumpinfo(struct cpu *cpu)
297 {
298  struct arm_cpu_type_def *ct = &cpu->cd.arm.cpu_type;
299 
300  debug(" (I+D = %i+%i KB)\n",
301  (1 << ct->icache_shift) / 1024, (1 << ct->dcache_shift) / 1024);
302 }
303 
304 
305 /*
306  * arm_cpu_list_available_types():
307  *
308  * Print a list of available ARM CPU types.
309  */
311 {
312  int i, j;
313  struct arm_cpu_type_def tdefs[] = ARM_CPU_TYPE_DEFS;
314 
315  i = 0;
316  while (tdefs[i].name != NULL) {
317  debug("%s", tdefs[i].name);
318  for (j=13 - strlen(tdefs[i].name); j>0; j--)
319  debug(" ");
320  i++;
321  if ((i % 5) == 0 || tdefs[i].name == NULL)
322  debug("\n");
323  }
324 }
325 
326 
327 /*
328  * arm_cpu_register_dump():
329  *
330  * Dump cpu registers in a relatively readable format.
331  *
332  * gprs: set to non-zero to dump GPRs and some special-purpose registers.
333  * coprocs: set bit 0..3 to dump registers in coproc 0..3.
334  */
335 void arm_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
336 {
337  char *symbol;
338  uint64_t offset;
339  int mode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
340  int i, x = cpu->cpu_id;
341 
342  cpu->cd.arm.cpsr &= 0x0fffffff;
343  cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
344 
345  if (gprs) {
346  symbol = get_symbol_name(&cpu->machine->symbol_context,
347  cpu->pc, &offset);
348  debug("cpu%i: cpsr = ", x);
349  debug("%s%s%s%s%s%s%s%s",
350  (cpu->cd.arm.cpsr & ARM_FLAG_N)? "N" : "n",
351  (cpu->cd.arm.cpsr & ARM_FLAG_Z)? "Z" : "z",
352  (cpu->cd.arm.cpsr & ARM_FLAG_C)? "C" : "c",
353  (cpu->cd.arm.cpsr & ARM_FLAG_V)? "V" : "v",
354  (cpu->cd.arm.cpsr & ARM_FLAG_Q)? "Q" : "q",
355  (cpu->cd.arm.cpsr & ARM_FLAG_I)? "I" : "i",
356  (cpu->cd.arm.cpsr & ARM_FLAG_F)? "F" : "f",
357  (cpu->cd.arm.cpsr & ARM_FLAG_T)? "T" : "t");
358  if (mode < ARM_MODE_USR32)
359  debug(" pc = 0x%07x", (int)(cpu->pc & 0x03ffffff));
360  else
361  debug(" pc = 0x%08x", (int)cpu->pc);
362 
363  debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
364 
365  for (i=0; i<N_ARM_REGS; i++) {
366  if ((i % 4) == 0)
367  debug("cpu%i:", x);
368  if (i != ARM_PC)
369  debug(" %s = 0x%08x", arm_regname[i],
370  (int)cpu->cd.arm.r[i]);
371  if ((i % 4) == 3)
372  debug("\n");
373  }
374  }
375 
376  if (coprocs & 1) {
377  int m = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
378  debug("cpu%i: cpsr = 0x%08x (", x, cpu->cd.arm.cpsr);
379  switch (m) {
380  case ARM_MODE_USR32:
381  debug("USR32)\n"); break;
382  case ARM_MODE_SYS32:
383  debug("SYS32)\n"); break;
384  case ARM_MODE_FIQ32:
385  debug("FIQ32)\n"); break;
386  case ARM_MODE_IRQ32:
387  debug("IRQ32)\n"); break;
388  case ARM_MODE_SVC32:
389  debug("SVC32)\n"); break;
390  case ARM_MODE_ABT32:
391  debug("ABT32)\n"); break;
392  case ARM_MODE_UND32:
393  debug("UND32)\n"); break;
394  default:debug("unimplemented)\n");
395  }
396 
397  if (m != ARM_MODE_USR32 && m != ARM_MODE_SYS32) {
398  debug("cpu%i: usr r8-14:", x);
399  for (i=0; i<7; i++)
400  debug(" %08x", cpu->cd.arm.default_r8_r14[i]);
401  debug("\n");
402  }
403 
404  if (m != ARM_MODE_FIQ32) {
405  debug("cpu%i: fiq r8-14:", x);
406  for (i=0; i<7; i++)
407  debug(" %08x", cpu->cd.arm.fiq_r8_r14[i]);
408  debug("\n");
409  }
410 
411  if (m != ARM_MODE_IRQ32) {
412  debug("cpu%i: irq r13-14:", x);
413  for (i=0; i<2; i++)
414  debug(" %08x", cpu->cd.arm.irq_r13_r14[i]);
415  debug("\n");
416  }
417 
418  if (m != ARM_MODE_SVC32) {
419  debug("cpu%i: svc r13-14:", x);
420  for (i=0; i<2; i++)
421  debug(" %08x", cpu->cd.arm.svc_r13_r14[i]);
422  debug("\n");
423  }
424 
425  if (m != ARM_MODE_ABT32) {
426  debug("cpu%i: abt r13-14:", x);
427  for (i=0; i<2; i++)
428  debug(" %08x", cpu->cd.arm.abt_r13_r14[i]);
429  debug("\n");
430  }
431 
432  if (m != ARM_MODE_UND32) {
433  debug("cpu%i: und r13-14:", x);
434  for (i=0; i<2; i++)
435  debug(" %08x", cpu->cd.arm.und_r13_r14[i]);
436  debug("\n");
437  }
438  }
439 
440  if (coprocs & 2) {
441  debug("cpu%i: control = 0x%08x\n", x, cpu->cd.arm.control);
442  debug("cpu%i: MMU: %s\n", x,
443  cpu->cd.arm.control &
444  ARM_CONTROL_MMU? "enabled" : "disabled");
445  debug("cpu%i: alignment checks: %s\n", x,
446  cpu->cd.arm.control &
447  ARM_CONTROL_ALIGN? "enabled" : "disabled");
448  debug("cpu%i: [data] cache: %s\n", x,
449  cpu->cd.arm.control &
450  ARM_CONTROL_CACHE? "enabled" : "disabled");
451  debug("cpu%i: instruction cache: %s\n", x,
452  cpu->cd.arm.control &
453  ARM_CONTROL_ICACHE? "enabled" : "disabled");
454  debug("cpu%i: write buffer: %s\n", x,
455  cpu->cd.arm.control &
456  ARM_CONTROL_WBUFFER? "enabled" : "disabled");
457  debug("cpu%i: prog32: %s\n", x,
458  cpu->cd.arm.control &
459  ARM_CONTROL_PROG32? "yes" : "no (using prog26)");
460  debug("cpu%i: data32: %s\n", x,
461  cpu->cd.arm.control &
462  ARM_CONTROL_DATA32? "yes" : "no (using data26)");
463  debug("cpu%i: endianness: %s\n", x,
464  cpu->cd.arm.control &
465  ARM_CONTROL_BIG? "big endian" : "little endian");
466  debug("cpu%i: high vectors: %s\n", x,
467  cpu->cd.arm.control &
468  ARM_CONTROL_V? "yes (0xffff0000)" : "no");
469 
470  /* TODO: auxctrl on which CPU types? */
471  if (cpu->cd.arm.cpu_type.flags & ARM_XSCALE) {
472  debug("cpu%i: auxctrl = 0x%08x\n", x,
473  cpu->cd.arm.auxctrl);
474  debug("cpu%i: minidata cache attr = 0x%x\n", x,
475  (cpu->cd.arm.auxctrl & ARM_AUXCTRL_MD)
477  debug("cpu%i: page table memory attr: %i\n", x,
478  (cpu->cd.arm.auxctrl & ARM_AUXCTRL_P)? 1 : 0);
479  debug("cpu%i: write buffer coalescing: %s\n", x,
480  (cpu->cd.arm.auxctrl & ARM_AUXCTRL_K)?
481  "disabled" : "enabled");
482  }
483 
484  debug("cpu%i: ttb = 0x%08x dacr = 0x%08x\n", x,
485  cpu->cd.arm.ttb, cpu->cd.arm.dacr);
486  debug("cpu%i: fsr = 0x%08x far = 0x%08x\n", x,
487  cpu->cd.arm.fsr, cpu->cd.arm.far);
488  }
489 }
490 
491 
492 /*
493  * arm_save_register_bank():
494  */
495 void arm_save_register_bank(struct cpu *cpu)
496 {
497  /* Save away current registers: */
498  switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
499  case ARM_MODE_USR32:
500  case ARM_MODE_SYS32:
501  memcpy(cpu->cd.arm.default_r8_r14,
502  &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
503  break;
504  case ARM_MODE_FIQ32:
505  memcpy(cpu->cd.arm.fiq_r8_r14,
506  &cpu->cd.arm.r[8], sizeof(uint32_t) * 7);
507  break;
508  case ARM_MODE_IRQ32:
509  memcpy(cpu->cd.arm.default_r8_r14,
510  &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
511  cpu->cd.arm.irq_r13_r14[0] = cpu->cd.arm.r[13];
512  cpu->cd.arm.irq_r13_r14[1] = cpu->cd.arm.r[14];
513  break;
514  case ARM_MODE_SVC32:
515  memcpy(cpu->cd.arm.default_r8_r14,
516  &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
517  cpu->cd.arm.svc_r13_r14[0] = cpu->cd.arm.r[13];
518  cpu->cd.arm.svc_r13_r14[1] = cpu->cd.arm.r[14];
519  break;
520  case ARM_MODE_ABT32:
521  memcpy(cpu->cd.arm.default_r8_r14,
522  &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
523  cpu->cd.arm.abt_r13_r14[0] = cpu->cd.arm.r[13];
524  cpu->cd.arm.abt_r13_r14[1] = cpu->cd.arm.r[14];
525  break;
526  case ARM_MODE_UND32:
527  memcpy(cpu->cd.arm.default_r8_r14,
528  &cpu->cd.arm.r[8], sizeof(uint32_t) * 5);
529  cpu->cd.arm.und_r13_r14[0] = cpu->cd.arm.r[13];
530  cpu->cd.arm.und_r13_r14[1] = cpu->cd.arm.r[14];
531  break;
532  default:fatal("arm_save_register_bank: unimplemented mode %i\n",
533  cpu->cd.arm.cpsr & ARM_FLAG_MODE);
534  exit(1);
535  }
536 }
537 
538 
539 /*
540  * arm_load_register_bank():
541  */
542 void arm_load_register_bank(struct cpu *cpu)
543 {
544  /* Load new registers: */
545  switch (cpu->cd.arm.cpsr & ARM_FLAG_MODE) {
546  case ARM_MODE_USR32:
547  case ARM_MODE_SYS32:
548  memcpy(&cpu->cd.arm.r[8],
549  cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 7);
550  break;
551  case ARM_MODE_FIQ32:
552  memcpy(&cpu->cd.arm.r[8], cpu->cd.arm.fiq_r8_r14,
553  sizeof(uint32_t) * 7);
554  break;
555  case ARM_MODE_IRQ32:
556  memcpy(&cpu->cd.arm.r[8],
557  cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
558  cpu->cd.arm.r[13] = cpu->cd.arm.irq_r13_r14[0];
559  cpu->cd.arm.r[14] = cpu->cd.arm.irq_r13_r14[1];
560  break;
561  case ARM_MODE_SVC32:
562  memcpy(&cpu->cd.arm.r[8],
563  cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
564  cpu->cd.arm.r[13] = cpu->cd.arm.svc_r13_r14[0];
565  cpu->cd.arm.r[14] = cpu->cd.arm.svc_r13_r14[1];
566  break;
567  case ARM_MODE_ABT32:
568  memcpy(&cpu->cd.arm.r[8],
569  cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
570  cpu->cd.arm.r[13] = cpu->cd.arm.abt_r13_r14[0];
571  cpu->cd.arm.r[14] = cpu->cd.arm.abt_r13_r14[1];
572  break;
573  case ARM_MODE_UND32:
574  memcpy(&cpu->cd.arm.r[8],
575  cpu->cd.arm.default_r8_r14, sizeof(uint32_t) * 5);
576  cpu->cd.arm.r[13] = cpu->cd.arm.und_r13_r14[0];
577  cpu->cd.arm.r[14] = cpu->cd.arm.und_r13_r14[1];
578  break;
579  default:fatal("arm_load_register_bank: unimplemented mode %i\n",
580  cpu->cd.arm.cpsr & ARM_FLAG_MODE);
581  exit(1);
582  }
583 }
584 
585 
586 /*
587  * arm_exception():
588  */
589 void arm_exception(struct cpu *cpu, int exception_nr)
590 {
591  int oldmode, newmode;
592  uint32_t retaddr;
593 
594  if (exception_nr < 0 || exception_nr >= N_ARM_EXCEPTIONS) {
595  fatal("arm_exception(): exception_nr = %i\n", exception_nr);
596  exit(1);
597  }
598 
599  retaddr = cpu->pc;
600 
601  if (!quiet_mode) {
602  debug("[ arm_exception(): ");
603  switch (exception_nr) {
604  case ARM_EXCEPTION_RESET:
605  fatal("RESET: TODO");
606  break;
607  case ARM_EXCEPTION_UND:
608  debug("UNDEFINED");
609  break;
610  case ARM_EXCEPTION_SWI:
611  debug("SWI");
612  break;
614  debug("PREFETCH ABORT");
615  break;
616  case ARM_EXCEPTION_IRQ:
617  debug("IRQ");
618  break;
619  case ARM_EXCEPTION_FIQ:
620  debug("FIQ");
621  break;
623  debug("DATA ABORT, far=0x%08x fsr=0x%02x",
624  cpu->cd.arm.far, cpu->cd.arm.fsr);
625  break;
626  }
627  debug(" ]\n");
628  }
629 
630  switch (exception_nr) {
631  case ARM_EXCEPTION_RESET:
632  cpu->running = 0;
633  fatal("ARM RESET: TODO");
634  exit(1);
636  retaddr += 4;
637  break;
638  }
639 
640  retaddr += 4;
641 
643 
644  cpu->cd.arm.cpsr &= 0x0fffffff;
645  cpu->cd.arm.cpsr |= (cpu->cd.arm.flags << 28);
646 
647  switch (arm_exception_to_mode[exception_nr]) {
648  case ARM_MODE_SVC32:
649  cpu->cd.arm.spsr_svc = cpu->cd.arm.cpsr; break;
650  case ARM_MODE_ABT32:
651  cpu->cd.arm.spsr_abt = cpu->cd.arm.cpsr; break;
652  case ARM_MODE_UND32:
653  cpu->cd.arm.spsr_und = cpu->cd.arm.cpsr; break;
654  case ARM_MODE_IRQ32:
655  cpu->cd.arm.spsr_irq = cpu->cd.arm.cpsr; break;
656  case ARM_MODE_FIQ32:
657  cpu->cd.arm.spsr_fiq = cpu->cd.arm.cpsr; break;
658  default:fatal("arm_exception(): unimplemented exception nr\n");
659  exit(1);
660  }
661 
662  /*
663  * Disable Thumb mode (because exception handlers always execute
664  * in ARM mode), set the exception mode, and disable interrupts:
665  */
666  cpu->cd.arm.cpsr &= ~ARM_FLAG_T;
667 
668  oldmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
669 
670  cpu->cd.arm.cpsr &= ~ARM_FLAG_MODE;
671  cpu->cd.arm.cpsr |= arm_exception_to_mode[exception_nr];
672 
673  /*
674  * Usually, an exception should change modes (so that saved status
675  * bits don't get lost). However, Linux on ARM seems to use floating
676  * point instructions in the kernel (!), and it emulates those using
677  * its own fp emulation code. This leads to a situation where we
678  * sometimes change from SVC32 to SVC32.
679  */
680  newmode = cpu->cd.arm.cpsr & ARM_FLAG_MODE;
681  if (oldmode == newmode && oldmode != ARM_MODE_SVC32) {
682  fatal("[ WARNING! Exception caused no mode change? "
683  "mode 0x%02x (pc=0x%x) ]\n", newmode, (int)cpu->pc);
684  /* exit(1); */
685  }
686 
687  cpu->cd.arm.cpsr |= ARM_FLAG_I;
688  if (exception_nr == ARM_EXCEPTION_RESET ||
689  exception_nr == ARM_EXCEPTION_FIQ)
690  cpu->cd.arm.cpsr |= ARM_FLAG_F;
691 
692  /* Load the new register bank, if we switched: */
694 
695  /*
696  * Set the return address and new PC.
697  *
698  * NOTE: r[ARM_PC] is also set; see cpu_arm_instr_loadstore.c for
699  * details. (If an exception occurs during a load into the pc
700  * register, the code in that file assumes that the r[ARM_PC]
701  * was changed to the address of the exception handler.)
702  */
703  cpu->cd.arm.r[ARM_LR] = retaddr;
704  cpu->pc = cpu->cd.arm.r[ARM_PC] = exception_nr * 4 +
705  ((cpu->cd.arm.control & ARM_CONTROL_V)? 0xffff0000 : 0);
707 }
708 
709 
710 /*
711  * arm_cpu_tlbdump():
712  *
713  * Called from the debugger to dump the TLB in a readable format.
714  * x is the cpu number to dump, or -1 to dump all CPUs.
715  *
716  * If rawflag is nonzero, then the TLB contents isn't formated nicely,
717  * just dumped.
718  */
719 void arm_cpu_tlbdump(struct machine *m, int x, int rawflag)
720 {
721 }
722 
723 
724 /*
725  * arm_irq_interrupt_assert():
726  * arm_irq_interrupt_deassert():
727  */
728 void arm_irq_interrupt_assert(struct interrupt *interrupt)
729 {
730  struct cpu *cpu = (struct cpu *) interrupt->extra;
731  cpu->cd.arm.irq_asserted = 1;
732 }
733 void arm_irq_interrupt_deassert(struct interrupt *interrupt)
734 {
735  struct cpu *cpu = (struct cpu *) interrupt->extra;
736  cpu->cd.arm.irq_asserted = 0;
737 }
738 
739 
740 /*
741  * arm_cpu_disassemble_instr_thumb():
742  *
743  * Like arm_cpu_disassemble_instr below, but for THUMB encodings.
744  * Note that the disassbmly uses regular ARM mnemonics, not "THUMB
745  * assembly language".
746  */
747 int arm_cpu_disassemble_instr_thumb(struct cpu *cpu, unsigned char *ib,
748  int running, uint64_t dumpaddr)
749 {
750  uint16_t iw;
751  if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
752  iw = ib[0] + (ib[1]<<8);
753  else
754  iw = ib[1] + (ib[0]<<8);
755  debug("%04x \t", (int)iw);
756 
757  int main_opcode = (iw >> 12) & 15;
758  int rn = (iw >> 6) & 7;
759  int rs_rb = (iw >> 3) & 7;
760  int rd = iw & 7;
761  int offset5 = (iw >> 6) & 0x1f;
762  int b_bit = (iw >> 12) & 1;
763  int l_bit = (iw >> 11) & 1;
764  int addsub_op = (iw >> 9) & 1;
765  int addsub_immediate = (iw >> 10) & 1;
766  int op11 = (iw >> 11) & 3;
767  int op10 = (iw >> 10) & 3;
768  int op8 = (iw >> 8) & 3;
769  int h1 = (iw >> 7) & 1;
770  int h2 = (iw >> 6) & 1;
771  int condition_code = (iw >> 8) & 15;
772  const char* condition = arm_condition_string[condition_code];
773  const char* symbol;
774  uint64_t offset;
775  int tmp;
776 
777  switch (main_opcode)
778  {
779  case 0x0:
780  case 0x1:
781  if (op11 < 3) {
782  // Move shifted register.
783  debug("movs\tr%i,r%i, %s #%i\n",
784  rd,
785  rs_rb,
786  op11 & 1 ? "lsr" : (op11 & 2 ? "asr" : "lsl"),
787  offset5);
788  } else {
789  // Add/subtract.
790  debug("%s\tr%i,r%i,%s%i\n",
791  addsub_op ? "subs" : "adds",
792  rd,
793  rs_rb,
794  addsub_immediate ? "#" : "r",
795  rn);
796  }
797  break;
798 
799  case 0x2:
800  case 0x3:
801  // Move/compare/add/subtract immediate.
802  rd = (iw >> 8) & 7;
803  if (op11 & 2) {
804  debug("%s\tr%i,r%i,#%i\n",
805  op11 & 1 ? "subs" : "adds",
806  rd, rd,
807  iw & 0xff);
808  } else {
809  debug("%s\tr%i,#%i\n",
810  op11 & 1 ? "cmp" : "movs",
811  rd,
812  iw & 0xff);
813  }
814  break;
815 
816  case 0x4:
817  switch (op10) {
818  case 0:
819  // ALU operations.
820  debug("TODO main_opcode = %i, op10 = %i\n", main_opcode, op10);
821  break;
822 
823  case 1:
824  // Hi register operations / branch exchange.
825  if (h1)
826  rd += 8;
827  if (h2)
828  rs_rb += 8;
829  switch (op8) {
830  case 0:
831  case 1:
832  case 2:
833  if (h1 == 0 && h2 == 0) {
834  debug("TODO main_opcode = %i, op10 = %i, h1 AND h2 are zero?!\n", main_opcode, op10);
835  } else {
836  if (op8 == 0)
837  debug("add\tr%i,r%i,r%i\n", rd, rd, rs_rb);
838  else
839  debug("%s\tr%i,r%i\n",
840  op8 == 1 ? "cmp" : "mov", rd, rs_rb);
841  }
842  break;
843  case 3:
844  if (h1 == 1) {
845  debug("TODO main_opcode = %i, op10 = %i, h1 set for BX?!\n", main_opcode, op10);
846  } else {
847  debug("bx\tr%i\n", rs_rb);
848  }
849  break;
850  }
851  break;
852 
853  case 2:
854  case 3:
855  // PC-relative load.
856  debug("TODO main_opcode = %i, op10 = %i\n", main_opcode, op10);
857  break;
858  }
859  break;
860 
861  case 0x6:
862  case 0x7:
863  // Load/Store with immediate offset.
864  debug("%s%s\tr%i,[r%i,#%i]\n",
865  l_bit ? "ldr" : "str",
866  b_bit ? "b" : "",
867  rd,
868  rs_rb,
869  offset5 * (b_bit ? sizeof(uint8_t) : sizeof(uint32_t)));
870  break;
871 
872  case 0x8:
873  // Load/Store halfword.
874  debug("%sh\tr%i,[r%i,#%i]\n",
875  l_bit ? "ldr" : "str",
876  rd,
877  rs_rb,
878  offset5 * sizeof(uint16_t));
879  break;
880 
881  case 0xd:
882  if (condition_code < 0xe) {
883  // Conditional branch.
884  debug("b%s\t", condition);
885  tmp = (iw & 0xff) << 1;
886  if (tmp & 0x100)
887  tmp |= 0xfffffe00;
888  tmp = (int32_t)(dumpaddr + 4 + tmp);
889  debug("0x%x", (int)tmp);
890  symbol = get_symbol_name(&cpu->machine->symbol_context,
891  tmp, &offset);
892  if (symbol != NULL)
893  debug(" \t<%s>", symbol);
894  debug("\n");
895  } else {
896  // ? (0xe).
897  // Software interrupt (0xf).
898  debug("UNIMPLEMENTED\n");
899  }
900  break;
901 
902  case 0xe:
903  // Unconditional branch.
904  if (iw & 0x0800) {
905  debug("UNKNOWN encoding?\n");
906  } else {
907  tmp = (iw & 0x7ff) << 1;
908  if (tmp & 0x800)
909  tmp |= 0xfffff000;
910  tmp = (int32_t)(dumpaddr + 4 + tmp);
911  debug("bal\t0x%x", (int)tmp);
912  symbol = get_symbol_name(&cpu->machine->symbol_context,
913  tmp, &offset);
914  if (symbol != NULL)
915  debug(" \t<%s>", symbol);
916  debug("\n");
917  }
918  break;
919 
920  default:
921  debug("TODO: unimplemented opcode %i\n", main_opcode);
922  }
923 
924  return sizeof(uint16_t);
925 }
926 
927 
928 /*
929  * arm_cpu_disassemble_instr():
930  *
931  * Convert an instruction word into human readable format, for instruction
932  * tracing.
933  *
934  * If running is 1, cpu->pc should be the address of the instruction.
935  *
936  * If running is 0, things that depend on the runtime environment (eg.
937  * register contents) will not be shown, and addr will be used instead of
938  * cpu->pc for relative addresses.
939  */
940 int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib,
941  int running, uint64_t dumpaddr)
942 {
943  uint32_t iw, tmp;
944  int main_opcode, secondary_opcode, s_bit, r16, r12, r8;
945  int i, n, p_bit, u_bit, b_bit, w_bit, l_bit;
946  const char *symbol, *condition;
947  uint64_t offset;
948 
949  if (running)
950  dumpaddr = cpu->pc;
951 
952  symbol = get_symbol_name(&cpu->machine->symbol_context,
953  dumpaddr, &offset);
954  if (symbol != NULL && offset == 0)
955  debug("<%s>\n", symbol);
956 
957  if (cpu->machine->ncpus > 1 && running)
958  debug("cpu%i:\t", cpu->cpu_id);
959 
960  debug("%08x: ", (int)dumpaddr);
961 
962  if (cpu->cd.arm.cpsr & ARM_FLAG_T)
963  return arm_cpu_disassemble_instr_thumb(cpu, ib, running, dumpaddr);
964 
965  if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
966  iw = ib[0] + (ib[1]<<8) + (ib[2]<<16) + (ib[3]<<24);
967  else
968  iw = ib[3] + (ib[2]<<8) + (ib[1]<<16) + (ib[0]<<24);
969  debug("%08x\t", (int)iw);
970 
971  condition = arm_condition_string[iw >> 28];
972  main_opcode = (iw >> 24) & 15;
973  secondary_opcode = (iw >> 21) & 15;
974  u_bit = (iw >> 23) & 1;
975  b_bit = (iw >> 22) & 1;
976  w_bit = (iw >> 21) & 1;
977  s_bit = l_bit = (iw >> 20) & 1;
978  r16 = (iw >> 16) & 15;
979  r12 = (iw >> 12) & 15;
980  r8 = (iw >> 8) & 15;
981 
982  switch (main_opcode) {
983  case 0x0:
984  case 0x1:
985  case 0x2:
986  case 0x3:
987  /*
988  * Special cases first:
989  */
990 
991  /*
992  * Multiplication:
993  * xxxx0000 00ASdddd nnnnssss 1001mmmm (Rd, Rm, Rs [,Rn])
994  */
995  if ((iw & 0x0fc000f0) == 0x00000090) {
996  int a_bit = (iw >> 21) & 1;
997  debug("%s%s%s\t", a_bit? "mla" : "mul",
998  condition, s_bit? "s" : "");
999  debug("%s,", arm_regname[r16]);
1000  debug("%s,", arm_regname[iw & 15]);
1001  debug("%s", arm_regname[r8]);
1002  if (a_bit)
1003  debug(",%s", arm_regname[r12]);
1004  debug("\n");
1005  break;
1006  }
1007 
1008  /*
1009  * Long multiplication:
1010  * xxxx0000 1UAShhhh llllssss 1001mmmm (Rl,Rh,Rm,Rs)
1011  */
1012  if ((iw & 0x0f8000f0) == 0x00800090) {
1013  int a_bit = (iw >> 21) & 1;
1014  u_bit = (iw >> 22) & 1;
1015  debug("%s%sl%s%s\t", u_bit? "s" : "u",
1016  a_bit? "mla" : "mul", condition, s_bit? "s" : "");
1017  debug("%s,%s,", arm_regname[r12], arm_regname[r16]);
1018  debug("%s,%s\n", arm_regname[iw&15], arm_regname[r8]);
1019  break;
1020  }
1021 
1022  /*
1023  * xxxx0001 0000nnnn dddd0000 0101mmmm qadd Rd,Rm,Rn
1024  * xxxx0001 0010nnnn dddd0000 0101mmmm qsub Rd,Rm,Rn
1025  * xxxx0001 0100nnnn dddd0000 0101mmmm qdadd Rd,Rm,Rn
1026  * xxxx0001 0110nnnn dddd0000 0101mmmm qdsub Rd,Rm,Rn
1027  */
1028  if ((iw & 0x0f900ff0) == 0x01000050) {
1029  debug("q%s%s%s\t", iw & 0x400000? "d" : "",
1030  iw & 0x200000? "sub" : "add", condition);
1031  debug("%s,%s,%s\n", arm_regname[r12],
1032  arm_regname[iw&15], arm_regname[r16]);
1033  break;
1034  }
1035 
1036  /*
1037  * xxxx0001 0010.... ........ 00L1mmmm bx/blx rm
1038  */
1039  if ((iw & 0x0ff000d0) == 0x01200010) {
1040  l_bit = iw & 0x20;
1041  debug("b%sx%s\t%s\n", l_bit? "l" : "", condition,
1042  arm_regname[iw & 15]);
1043  break;
1044  }
1045 
1046  /*
1047  * xxxx0001 0s10aaaa 11110000 0000mmmm MSR Regform
1048  * xxxx0011 0s10aaaa 1111rrrr bbbbbbbb MSR Immform
1049  * xxxx0001 0s001111 dddd0000 00000000 MRS
1050  */
1051  if ((iw & 0x0fb0fff0) == 0x0120f000 ||
1052  (iw & 0x0fb0f000) == 0x0320f000) {
1053  debug("msr%s\t%s", condition, (iw&0x400000)? "S":"C");
1054  debug("PSR_");
1055  if (iw & (1<<19)) debug("f");
1056  if (iw & (1<<18)) debug("s");
1057  if (iw & (1<<17)) debug("x");
1058  if (iw & (1<<16)) debug("c");
1059  if (iw & 0x02000000) {
1060  int r = (iw >> 7) & 30;
1061  uint32_t b = iw & 0xff;
1062  while (r-- > 0)
1063  b = (b >> 1) | ((b & 1) << 31);
1064  debug(",#0x%x\n", b);
1065  } else
1066  debug(",%s\n", arm_regname[iw & 15]);
1067  break;
1068  }
1069  if ((iw & 0x0fbf0fff) == 0x010f0000) {
1070  debug("mrs%s\t", condition);
1071  debug("%s,%sPSR\n", arm_regname[r12],
1072  (iw&0x400000)? "S":"C");
1073  break;
1074  }
1075 
1076  /*
1077  * xxxx0001 0B00nnnn dddd0000 1001mmmm SWP Rd,Rm,[Rn]
1078  */
1079  if ((iw & 0x0fb00ff0) == 0x01000090) {
1080  debug("swp%s%s\t", condition, (iw&0x400000)? "b":"");
1081  debug("%s,%s,[%s]\n", arm_regname[r12],
1082  arm_regname[iw & 15], arm_regname[r16]);
1083  break;
1084  }
1085 
1086  /*
1087  * xxxx0001 0010iiii iiiiiiii 0111iiii BKPT immed16
1088  */
1089  if ((iw & 0x0ff000f0) == 0x01200070) {
1090  debug("bkpt%s\t0x%04x\n", condition,
1091  ((iw & 0x000fff00) >> 4) + (iw & 0xf));
1092  break;
1093  }
1094 
1095  /*
1096  * xxxx0001 01101111 dddd1111 0001mmmm CLZ Rd,Rm
1097  */
1098  if ((iw & 0x0fff0ff0) == 0x016f0f10) {
1099  debug("clz%s\t", condition);
1100  debug("%s,%s\n", arm_regname[r12], arm_regname[iw&15]);
1101  break;
1102  }
1103 
1104  /*
1105  * xxxx0001 0000dddd nnnnssss 1yx0mmmm SMLAxy Rd,Rm,Rs,Rn
1106  * xxxx0001 0100dddd DDDDssss 1yx0mmmm SMLALxy RdL,RdH,Rm,Rs
1107  * xxxx0001 0010dddd nnnnssss 1y00mmmm SMLAWy Rd,Rm,Rs,Rn
1108  * xxxx0001 0110dddd 0000ssss 1yx0mmmm SMULxy Rd,Rm,Rs
1109  * xxxx0001 0010dddd 0000ssss 1y10mmmm SMULWy Rd,Rm,Rs
1110  */
1111  if ((iw & 0x0ff00090) == 0x01000080) {
1112  debug("smla%s%s%s\t",
1113  iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
1114  condition);
1115  debug("%s,%s,%s,%s\n", arm_regname[r16],
1116  arm_regname[iw&15], arm_regname[r8],
1117  arm_regname[r12]);
1118  break;
1119  }
1120  if ((iw & 0x0ff00090) == 0x01400080) {
1121  debug("smlal%s%s%s\t",
1122  iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
1123  condition);
1124  debug("%s,%s,%s,%s\n", arm_regname[r12],
1125  arm_regname[r16], arm_regname[iw&15],
1126  arm_regname[r8]);
1127  break;
1128  }
1129  if ((iw & 0x0ff000b0) == 0x01200080) {
1130  debug("smlaw%s%s\t", iw & 0x40? "t" : "b",
1131  condition);
1132  debug("%s,%s,%s,%s\n", arm_regname[r16],
1133  arm_regname[iw&15], arm_regname[r8],
1134  arm_regname[r12]);
1135  break;
1136  }
1137  if ((iw & 0x0ff0f090) == 0x01600080) {
1138  debug("smul%s%s%s\t",
1139  iw & 0x20? "t" : "b", iw & 0x40? "t" : "b",
1140  condition);
1141  debug("%s,%s,%s\n", arm_regname[r16],
1142  arm_regname[iw&15], arm_regname[r8]);
1143  break;
1144  }
1145  if ((iw & 0x0ff0f0b0) == 0x012000a0) {
1146  debug("smulw%s%s\t", iw & 0x40? "t" : "b",
1147  condition);
1148  debug("%s,%s,%s\n", arm_regname[r16],
1149  arm_regname[iw&15], arm_regname[r8]);
1150  break;
1151  }
1152 
1153  /*
1154  * xxxx000P U1WLnnnn ddddHHHH 1SH1LLLL load/store rd,imm(rn)
1155  */
1156  if ((iw & 0x0e000090) == 0x00000090) {
1157  const char *op = "st";
1158  int imm = ((iw >> 4) & 0xf0) | (iw & 0xf);
1159  int regform = !(iw & 0x00400000);
1160  p_bit = main_opcode & 1;
1161  /*
1162  * TODO: detect some illegal variants:
1163  * signed store, or unsigned byte load/store
1164  */
1165  if (!l_bit && (iw & 0xd0) == 0xd0 && (r12 & 1)) {
1166  debug("TODO: r12 odd, not load/store\n");
1167  break;
1168  }
1169  /* Semi-generic case: */
1170  if (iw & 0x00100000)
1171  op = "ld";
1172  if (!l_bit && (iw & 0xd0) == 0xd0) {
1173  if (iw & 0x20)
1174  op = "st";
1175  else
1176  op = "ld";
1177  }
1178  debug("%sr%s", op, condition);
1179  if (!l_bit && (iw & 0xd0) == 0xd0) {
1180  debug("d"); /* Double-register */
1181  } else {
1182  if (iw & 0x40)
1183  debug("s"); /* signed */
1184  if (iw & 0x20)
1185  debug("h"); /* half-word */
1186  else
1187  debug("b"); /* byte */
1188  }
1189  debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
1190  if (p_bit) {
1191  /* Pre-index: */
1192  if (regform)
1193  debug(",%s%s", u_bit? "" : "-",
1194  arm_regname[iw & 15]);
1195  else {
1196  if (imm != 0)
1197  debug(",#%s%i", u_bit? "" : "-",
1198  imm);
1199  }
1200  debug("]%s\n", w_bit? "!" : "");
1201  } else {
1202  /* Post-index: */
1203  debug("],");
1204  if (regform)
1205  debug("%s%s\n", u_bit? "" : "-",
1206  arm_regname[iw & 15]);
1207  else
1208  debug("#%s%i\n", u_bit? "" : "-", imm);
1209  }
1210  break;
1211  }
1212 
1213  /* Other special cases: */
1214  if (iw & 0x80 && !(main_opcode & 2) && iw & 0x10) {
1215  debug("UNIMPLEMENTED reg (c!=0), t odd\n");
1216  break;
1217  }
1218 
1219  /*
1220  * Generic Data Processing Instructions:
1221  *
1222  * xxxx000a aaaSnnnn ddddcccc ctttmmmm Register form
1223  * xxxx001a aaaSnnnn ddddrrrr bbbbbbbb Immediate form
1224  */
1225 
1226  debug("%s%s%s\t", arm_dpiname[secondary_opcode],
1227  condition, s_bit? "s" : "");
1228  if (arm_dpi_uses_d[secondary_opcode])
1229  debug("%s,", arm_regname[r12]);
1230  if (arm_dpi_uses_n[secondary_opcode])
1231  debug("%s,", arm_regname[r16]);
1232 
1233  if (main_opcode & 2) {
1234  /* Immediate form: */
1235  int r = (iw >> 7) & 30;
1236  uint32_t b = iw & 0xff;
1237  while (r-- > 0)
1238  b = (b >> 1) | ((b & 1) << 31);
1239  if (b < 15)
1240  debug("#%i", b);
1241  else
1242  debug("#0x%x", b);
1243  } else {
1244  /* Register form: */
1245  int t = (iw >> 4) & 7;
1246  int c = (iw >> 7) & 31;
1247  debug("%s", arm_regname[iw & 15]);
1248  switch (t) {
1249  case 0: if (c != 0)
1250  debug(", lsl #%i", c);
1251  break;
1252  case 1: debug(", lsl %s", arm_regname[c >> 1]);
1253  break;
1254  case 2: debug(", lsr #%i", c? c : 32);
1255  break;
1256  case 3: debug(", lsr %s", arm_regname[c >> 1]);
1257  break;
1258  case 4: debug(", asr #%i", c? c : 32);
1259  break;
1260  case 5: debug(", asr %s", arm_regname[c >> 1]);
1261  break;
1262  case 6: if (c != 0)
1263  debug(", ror #%i", c);
1264  else
1265  debug(", rrx");
1266  break;
1267  case 7: debug(", ror %s", arm_regname[c >> 1]);
1268  break;
1269  }
1270 
1271  /* mov pc,reg: */
1272  if (running && t == 0 && c == 0 && secondary_opcode
1273  == 0xd && r12 == ARM_PC && (iw&15)!=ARM_PC) {
1274  symbol = get_symbol_name(&cpu->machine->
1275  symbol_context, cpu->cd.arm.r[iw & 15],
1276  &offset);
1277  if (symbol != NULL)
1278  debug(" \t<%s>", symbol);
1279  }
1280  }
1281  debug("\n");
1282  break;
1283  case 0x4: /* Single Data Transfer */
1284  case 0x5:
1285  case 0x6:
1286  case 0x7:
1287  /* Special case first: */
1288  if ((iw & 0xfc70f000) == 0xf450f000) {
1289  /* Preload: */
1290  debug("pld\t[%s]\n", arm_regname[r16]);
1291  break;
1292  }
1293 
1294  /*
1295  * xxxx010P UBWLnnnn ddddoooo oooooooo Immediate form
1296  * xxxx011P UBWLnnnn ddddcccc ctt0mmmm Register form
1297  */
1298  p_bit = main_opcode & 1;
1299  if (main_opcode >= 6 && iw & 0x10) {
1300  debug("TODO: single data transf. but 0x10\n");
1301  break;
1302  }
1303  debug("%s%s%s", l_bit? "ldr" : "str",
1304  condition, b_bit? "b" : "");
1305  if (!p_bit && w_bit)
1306  debug("t");
1307  debug("\t%s,[%s", arm_regname[r12], arm_regname[r16]);
1308  if ((iw & 0x0e000000) == 0x04000000) {
1309  /* Immediate form: */
1310  uint32_t imm = iw & 0xfff;
1311  if (!p_bit)
1312  debug("]");
1313  if (imm != 0)
1314  debug(",#%s%i", u_bit? "" : "-", imm);
1315  if (p_bit)
1316  debug("]");
1317  } else if ((iw & 0x0e000010) == 0x06000000) {
1318  /* Register form: */
1319  if (!p_bit)
1320  debug("]");
1321  if ((iw & 0xfff) != 0)
1322  debug(",%s%s", u_bit? "" : "-",
1323  arm_regname[iw & 15]);
1324  if ((iw & 0xff0) != 0x000) {
1325  int c = (iw >> 7) & 31;
1326  int t = (iw >> 4) & 7;
1327  switch (t) {
1328  case 0: if (c != 0)
1329  debug(", lsl #%i", c);
1330  break;
1331  case 2: debug(", lsr #%i", c? c : 32);
1332  break;
1333  case 4: debug(", asr #%i", c? c : 32);
1334  break;
1335  case 6: if (c != 0)
1336  debug(", ror #%i", c);
1337  else
1338  debug(", rrx");
1339  break;
1340  }
1341  }
1342  if (p_bit)
1343  debug("]");
1344  } else {
1345  debug("UNKNOWN\n");
1346  break;
1347  }
1348  debug("%s", (p_bit && w_bit)? "!" : "");
1349  if ((iw & 0x0f000000) == 0x05000000 &&
1350  (r16 == ARM_PC || running)) {
1351  unsigned char tmpw[4];
1352  uint32_t imm = iw & 0xfff;
1353  uint32_t addr = (u_bit? imm : -imm);
1354  if (r16 == ARM_PC)
1355  addr += dumpaddr + 8;
1356  else
1357  addr += cpu->cd.arm.r[r16];
1358  symbol = get_symbol_name(&cpu->machine->symbol_context,
1359  addr, &offset);
1360  if (symbol != NULL)
1361  debug(" \t<%s", symbol);
1362  else
1363  debug(" \t<0x%08x", addr);
1364  if ((l_bit && cpu->memory_rw(cpu, cpu->mem, addr, tmpw,
1365  b_bit? 1 : sizeof(tmpw), MEM_READ, NO_EXCEPTIONS))
1366  || (!l_bit && running)) {
1367  if (l_bit) {
1368  if (cpu->byte_order ==
1370  addr = tmpw[0] +(tmpw[1] << 8) +
1371  (tmpw[2]<<16)+(tmpw[3]<<24);
1372  else
1373  addr = tmpw[3] + (tmpw[2]<<8) +
1374  (tmpw[1]<<16)+(tmpw[0]<<24);
1375  } else {
1376  tmpw[0] = addr = cpu->cd.arm.r[r12];
1377  if (r12 == ARM_PC)
1378  addr = cpu->pc + 8;
1379  }
1380  debug(": ");
1381  if (b_bit)
1382  debug("%i", tmpw[0]);
1383  else {
1384  symbol = get_symbol_name(&cpu->machine->
1385  symbol_context, addr, &offset);
1386  if (symbol != NULL)
1387  debug("%s", symbol);
1388  else if ((int32_t)addr > -256 &&
1389  (int32_t)addr < 256)
1390  debug("%i", addr);
1391  else
1392  debug("0x%x", addr);
1393  }
1394  }
1395  debug(">");
1396  }
1397  debug("\n");
1398  break;
1399  case 0x8: /* Block Data Transfer */
1400  case 0x9:
1401  /* xxxx100P USWLnnnn llllllll llllllll */
1402  p_bit = main_opcode & 1;
1403  s_bit = b_bit;
1404  debug("%s%s", l_bit? "ldm" : "stm", condition);
1405  switch (u_bit * 2 + p_bit) {
1406  case 0: debug("da"); break;
1407  case 1: debug("db"); break;
1408  case 2: debug("ia"); break;
1409  case 3: debug("ib"); break;
1410  }
1411  debug("\t%s", arm_regname[r16]);
1412  if (w_bit)
1413  debug("!");
1414  debug(",{");
1415  n = 0;
1416  for (i=0; i<16; i++)
1417  if ((iw >> i) & 1) {
1418  debug("%s%s", (n > 0)? ",":"", arm_regname[i]);
1419  n++;
1420  }
1421  debug("}");
1422  if (s_bit)
1423  debug("^");
1424  debug("\n");
1425  break;
1426  case 0xa: /* B: branch */
1427  case 0xb: /* BL: branch and link */
1428  debug("b%s%s\t", main_opcode == 0xa? "" : "l", condition);
1429  tmp = (iw & 0x00ffffff) << 2;
1430  if (tmp & 0x02000000)
1431  tmp |= 0xfc000000;
1432  tmp = (int32_t)(dumpaddr + tmp + 8);
1433  debug("0x%x", (int)tmp);
1434  symbol = get_symbol_name(&cpu->machine->symbol_context,
1435  tmp, &offset);
1436  if (symbol != NULL)
1437  debug(" \t<%s>", symbol);
1438  debug("\n");
1439  break;
1440  case 0xc: /* Coprocessor */
1441  case 0xd: /* LDC/STC */
1442  /*
1443  * xxxx1100 0100nnnn ddddcccc oooommmm MCRR c,op,Rd,Rn,CRm
1444  * xxxx1100 0101nnnn ddddcccc oooommmm MRRC c,op,Rd,Rn,CRm
1445  */
1446  if ((iw & 0x0fe00fff) == 0x0c400000) {
1447  debug("%s%s\t", iw & 0x100000? "mra" : "mar",
1448  condition);
1449  if (iw & 0x100000)
1450  debug("%s,%s,acc0\n",
1451  arm_regname[r12], arm_regname[r16]);
1452  else
1453  debug("acc0,%s,%s\n",
1454  arm_regname[r12], arm_regname[r16]);
1455  break;
1456  }
1457  if ((iw & 0x0fe00000) == 0x0c400000) {
1458  debug("%s%s\t", iw & 0x100000? "mrrc" : "mcrr",
1459  condition);
1460  debug("%i,%i,%s,%s,cr%i\n", r8, (iw >> 4) & 15,
1461  arm_regname[r12], arm_regname[r16], iw & 15);
1462  break;
1463  }
1464 
1465  /* xxxx110P UNWLnnnn DDDDpppp oooooooo LDC/STC */
1466  debug("TODO: coprocessor LDC/STC\n");
1467  break;
1468  case 0xe: /* CDP (Coprocessor Op) */
1469  /* or MRC/MCR!
1470  * xxxx1110 oooonnnn ddddpppp qqq0mmmm CDP
1471  * xxxx1110 oooLNNNN ddddpppp qqq1MMMM MRC/MCR
1472  */
1473  if ((iw & 0x0ff00ff0) == 0x0e200010) {
1474  /* Special case: mia* DSP instructions */
1475  switch ((iw >> 16) & 0xf) {
1476  case 0: debug("mia"); break;
1477  case 8: debug("miaph"); break;
1478  case 12: debug("miaBB"); break;
1479  case 13: debug("miaTB"); break;
1480  case 14: debug("miaBT"); break;
1481  case 15: debug("miaTT"); break;
1482  default: debug("UNKNOWN mia vector instruction?");
1483  }
1484  debug("%s\t", condition);
1485  debug("acc%i,%s,%s\n", ((iw >> 5) & 7),
1486  arm_regname[iw & 15], arm_regname[r12]);
1487  break;
1488  }
1489  if (iw & 0x10) {
1490  debug("%s%s\t",
1491  (iw & 0x00100000)? "mrc" : "mcr", condition);
1492  debug("%i,%i,r%i,cr%i,cr%i,%i",
1493  (int)((iw >> 8) & 15), (int)((iw >>21) & 7),
1494  (int)((iw >>12) & 15), (int)((iw >>16) & 15),
1495  (int)((iw >> 0) & 15), (int)((iw >> 5) & 7));
1496  } else {
1497  debug("cdp%s\t", condition);
1498  debug("%i,%i,cr%i,cr%i,cr%i",
1499  (int)((iw >> 8) & 15),
1500  (int)((iw >>20) & 15),
1501  (int)((iw >>12) & 15),
1502  (int)((iw >>16) & 15),
1503  (int)((iw >> 0) & 15));
1504  if ((iw >> 5) & 7)
1505  debug(",0x%x", (int)((iw >> 5) & 7));
1506  }
1507  debug("\n");
1508  break;
1509  case 0xf: /* SWI */
1510  debug("swi%s\t", condition);
1511  debug("0x%x\n", (int)(iw & 0x00ffffff));
1512  break;
1513  default:debug("UNIMPLEMENTED\n");
1514  }
1515 
1516  return sizeof(uint32_t);
1517 }
1518 
1519 
1520 /*****************************************************************************/
1521 
1522 
1523 /*
1524  * arm_mcr_mrc():
1525  *
1526  * Coprocessor register move.
1527  *
1528  * The program counter should be synched before calling this function (to
1529  * make debug output with the correct PC value possible).
1530  */
1531 void arm_mcr_mrc(struct cpu *cpu, uint32_t iword)
1532 {
1533  int opcode1 = (iword >> 21) & 7;
1534  int l_bit = (iword >> 20) & 1;
1535  int crn = (iword >> 16) & 15;
1536  int rd = (iword >> 12) & 15;
1537  int cp_num = (iword >> 8) & 15;
1538  int opcode2 = (iword >> 5) & 7;
1539  int crm = iword & 15;
1540 
1541  if (cpu->cd.arm.coproc[cp_num] != NULL)
1542  cpu->cd.arm.coproc[cp_num](cpu, opcode1, opcode2, l_bit,
1543  crn, crm, rd);
1544  else {
1545  fatal("[ arm_mcr_mrc: pc=0x%08x, iword=0x%08x: "
1546  "cp_num=%i ]\n", (int)cpu->pc, iword, cp_num);
1548  /* exit(1); */
1549  }
1550 }
1551 
1552 
1553 /*
1554  * arm_cdp():
1555  *
1556  * Coprocessor operations.
1557  *
1558  * The program counter should be synched before calling this function (to
1559  * make debug output with the correct PC value possible).
1560  */
1561 void arm_cdp(struct cpu *cpu, uint32_t iword)
1562 {
1563  fatal("[ arm_cdp: pc=0x%08x, iword=0x%08x ]\n", (int)cpu->pc, iword);
1565  /* exit(1); */
1566 }
1567 
1568 
1569 /*****************************************************************************/
1570 
1571 
1572 #include "tmp_arm_tail.cc"
1573 
#define N_ARM_REGS
Definition: cpu_arm.h:57
const char * name
Definition: cpu_arm.h:41
uint32_t spsr_irq
Definition: cpu_arm.h:171
#define ARM_CONTROL_ALIGN
Definition: cpu_arm.h:245
void fatal(const char *fmt,...)
Definition: main.cc:152
char * name
Definition: cpu.h:334
#define ARM_FLAG_F
Definition: cpu_arm.h:93
#define ARM_FLAG_Z
Definition: cpu_arm.h:88
void arm_save_register_bank(struct cpu *cpu)
Definition: cpu_arm.cc:495
void(* interrupt_assert)(struct interrupt *)
Definition: interrupt.h:38
#define ARM_MODE_IRQ32
Definition: cpu_arm.h:103
int(* translate_v2p)(struct cpu *, uint64_t vaddr, uint64_t *return_paddr, int flags)
Definition: cpu.h:369
int prom_emulation
Definition: machine.h:149
int arm_memory_rw(struct cpu *cpu, struct memory *mem, uint64_t vaddr, unsigned char *data, size_t len, int writeflag, int cache_flags)
#define ARM_FLAG_Q
Definition: cpu_arm.h:91
#define ARM_EXCEPTION_TO_MODE
Definition: cpu_arm.h:109
uint32_t ttb
Definition: cpu_arm.h:181
int arm_translate_v2p_mmu(struct cpu *cpu, uint64_t vaddr64, uint64_t *return_paddr, int flags)
Definition: memory_arm.cc:112
int store_32bit_word(struct cpu *cpu, uint64_t addr, uint64_t data32)
Definition: memory.cc:783
#define ARM_FLAG_N
Definition: cpu_arm.h:87
uint32_t irq_r13_r14[2]
Definition: cpu_arm.h:152
#define ARM_CONTROL_R
Definition: cpu_arm.h:252
void arm_cpu_list_available_types(void)
Definition: cpu_arm.cc:310
struct arm_cpu_type_def cpu_type
Definition: cpu_arm.h:133
#define ARM_PC
Definition: cpu_arm.h:56
uint8_t is_32bit
Definition: cpu.h:350
#define ARM_CACHETYPE_IASSOC_SHIFT
Definition: cpu_arm.h:280
void arm_invalidate_code_translation(struct cpu *cpu, uint64_t, int)
#define ARM_AUXCTRL_MD_SHIFT
Definition: cpu_arm.h:262
#define ARM_FLAG_C
Definition: cpu_arm.h:89
int icache_shift
Definition: cpu_arm.h:44
uint32_t far
Definition: cpu_arm.h:184
uint32_t auxctrl
Definition: cpu_arm.h:180
union cpu::@1 cd
struct memory * mem
Definition: cpu.h:362
int dcache_shift
Definition: cpu_arm.h:46
#define ARM_MODE_FIQ32
Definition: cpu_arm.h:102
#define ARM_MODE_SVC32
Definition: cpu_arm.h:104
void arm_update_translation_table(struct cpu *cpu, uint64_t vaddr_page, unsigned char *host_page, int writeflag, uint64_t paddr_page)
#define ARM_EXCEPTION_DATA_ABT
Definition: cpu_arm.h:119
struct machine * machine
Definition: cpu.h:328
void interrupt_handler_register(struct interrupt *templ)
Definition: interrupt.cc:81
#define MEM_READ
Definition: memory.h:116
void(* interrupt_deassert)(struct interrupt *)
Definition: interrupt.h:39
uint32_t spsr_fiq
Definition: cpu_arm.h:172
void arm_coproc_15(struct cpu *cpu, int opcode1, int opcode2, int l_bit, int crn, int crm, int rd)
#define ARM_CONTROL_BIG
Definition: cpu_arm.h:250
void arm_load_register_bank(struct cpu *cpu)
Definition: cpu_arm.cc:542
#define ARM_FLAG_I
Definition: cpu_arm.h:92
void arm_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
Definition: cpu_arm.cc:335
struct arm_cpu arm
Definition: cpu.h:441
uint32_t control
Definition: cpu_arm.h:179
void arm_translation_table_set_l1_b(struct cpu *cpu, uint32_t vaddr, uint32_t paddr)
Definition: cpu_arm.cc:268
int(* run_instr)(struct cpu *cpu)
Definition: cpu.h:364
uint32_t fsr
Definition: cpu_arm.h:183
char * get_symbol_name(struct symbol_context *, uint64_t addr, uint64_t *offset)
Definition: symbol.cc:188
uint32_t default_r8_r14[7]
Definition: cpu_arm.h:150
#define ARM_FLAG_V
Definition: cpu_arm.h:90
#define N_ARM_EXCEPTIONS
Definition: cpu_arm.h:113
int physical_ram_in_mb
Definition: machine.h:147
#define ARM_MODE_UND32
Definition: cpu_arm.h:106
#define ARM_CACHETYPE_DLINE_SHIFT
Definition: cpu_arm.h:276
int ncpus
Definition: machine.h:139
#define EMUL_LITTLE_ENDIAN
Definition: misc.h:164
uint64_t pc
Definition: cpu.h:383
uint32_t fiq_r8_r14[7]
Definition: cpu_arm.h:151
#define quick_pc_to_pointers(cpu)
#define ARM_CACHETYPE_HARVARD_SHIFT
Definition: cpu_arm.h:270
void arm_exception(struct cpu *cpu, int exception_nr)
Definition: cpu_arm.cc:589
int arm_run_instr(struct cpu *cpu)
#define ARM_EXCEPTION_IRQ
Definition: cpu_arm.h:121
#define ARM_CONTROL_ICACHE
Definition: cpu_arm.h:255
#define PHYSICAL
Definition: memory.h:126
#define ARM_CACHETYPE_CLASS_SHIFT
Definition: cpu_arm.h:268
#define ARM_CACHETYPE_DSIZE_SHIFT
Definition: cpu_arm.h:272
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
#define ARM_EXCEPTION_SWI
Definition: cpu_arm.h:117
char * path
Definition: cpu.h:337
int arm_translate_v2p(struct cpu *cpu, uint64_t vaddr64, uint64_t *return_paddr, int flags)
Definition: memory_arm.cc:52
#define ARM_CONTROL_S
Definition: cpu_arm.h:251
#define ARM_CONTROL_DATA32
Definition: cpu_arm.h:249
#define ARM_CACHETYPE_ILINE_SHIFT
Definition: cpu_arm.h:282
#define ARM_AUXCTRL_MD
Definition: cpu_arm.h:261
#define ARM_EXCEPTION_RESET
Definition: cpu_arm.h:115
#define ARM_CONTROL_MMU
Definition: cpu_arm.h:244
#define ARM_CONTROL_WBUFFER
Definition: cpu_arm.h:247
#define ARM_CACHETYPE_ISIZE_SHIFT
Definition: cpu_arm.h:278
uint8_t running
Definition: cpu.h:353
#define ARM_CACHETYPE_DASSOC_SHIFT
Definition: cpu_arm.h:274
uint32_t spsr_und
Definition: cpu_arm.h:170
#define MEM_WRITE
Definition: memory.h:117
void arm_pc_to_pointers(struct cpu *cpu)
uint32_t und_r13_r14[2]
Definition: cpu_arm.h:155
int arm_cpu_disassemble_instr_thumb(struct cpu *cpu, unsigned char *ib, int running, uint64_t dumpaddr)
Definition: cpu_arm.cc:747
int irq_asserted
Definition: cpu_arm.h:227
uint32_t addr
#define CPU_SETTINGS_ADD_REGISTER32(name, var)
Definition: cpu.h:490
#define ARM_EXCEPTION_PREF_ABT
Definition: cpu_arm.h:118
#define debug
Definition: dev_adb.cc:57
#define ARM_XSCALE
Definition: arm_cpu_types.h:42
void arm_cpu_tlbdump(struct machine *m, int x, int rawflag)
Definition: cpu_arm.cc:719
int quiet_mode
Definition: emul.cc:68
int cpu_id
Definition: cpu.h:359
uint32_t dacr
Definition: cpu_arm.h:182
#define ARM_MODE_USR32
Definition: cpu_arm.h:101
uint32_t line
Definition: interrupt.h:51
Definition: cpu.h:326
#define ARM_REG_NAMES
Definition: cpu_arm.h:59
#define NO_EXCEPTIONS
Definition: memory.h:125
uint32_t spsr_abt
Definition: cpu_arm.h:169
char * name
Definition: interrupt.h:66
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
#define ARM_MODE_ABT32
Definition: cpu_arm.h:105
int arm_cpu_disassemble_instr(struct cpu *cpu, unsigned char *ib, int running, uint64_t dumpaddr)
Definition: cpu_arm.cc:940
#define ARM_MODE_SYS32
Definition: cpu_arm.h:107
uint32_t spsr_svc
Definition: cpu_arm.h:168
struct symbol_context symbol_context
Definition: machine.h:144
#define ARM_CONDITION_STRINGS
Definition: cpu_arm.h:63
int arm_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine, int cpu_id, char *cpu_type_name)
Definition: cpu_arm.cc:80
void(* coproc[16])(struct cpu *, int opcode1, int opcode2, int l_bit, int crn, int crm, int rd)
Definition: cpu_arm.h:136
size_t flags
Definition: cpu_arm.h:166
#define ARM_AUXCTRL_K
Definition: cpu_arm.h:264
uint8_t byte_order
Definition: cpu.h:347
#define ARM_FLAG_T
Definition: cpu_arm.h:94
void(* update_translation_table)(struct cpu *, uint64_t vaddr_page, unsigned char *host_page, int writeflag, uint64_t paddr_page)
Definition: cpu.h:371
void arm_irq_interrupt_assert(struct interrupt *interrupt)
Definition: cpu_arm.cc:728
void arm_irq_interrupt_deassert(struct interrupt *interrupt)
Definition: cpu_arm.cc:733
Definition: memory.h:75
uint32_t svc_r13_r14[2]
Definition: cpu_arm.h:153
uint32_t of_emul_addr
Definition: cpu_arm.h:134
#define ARM_FLAG_MODE
Definition: cpu_arm.h:96
uint32_t cpsr
Definition: cpu_arm.h:167
#define ARM_CPU_TYPE_DEFS
Definition: arm_cpu_types.h:50
#define ARM_CONTROL_CACHE
Definition: cpu_arm.h:246
#define ARM_EXCEPTION_FIQ
Definition: cpu_arm.h:122
Definition: symbol.h:37
#define ARM_CONTROL_V
Definition: cpu_arm.h:256
uint32_t cachetype
Definition: cpu_arm.h:178
void * extra
Definition: interrupt.h:59
void arm_coproc_xscale_14(struct cpu *cpu, int opcode1, int opcode2, int l_bit, int crn, int crm, int rd)
void(* invalidate_code_translation)(struct cpu *, uint64_t paddr, int flags)
Definition: cpu.h:376
void arm_invalidate_translation_caches(struct cpu *cpu, uint64_t, int)
uint32_t r[N_ARM_REGS]
Definition: cpu_arm.h:148
void arm_mcr_mrc(struct cpu *cpu, uint32_t iword)
Definition: cpu_arm.cc:1531
#define CPU_SETTINGS_ADD_REGISTER64(name, var)
Definition: cpu.h:486
char * op[16]
void arm_translation_table_set_l1(struct cpu *cpu, uint32_t vaddr, uint32_t paddr)
Definition: cpu_arm.cc:240
void arm_cpu_dumpinfo(struct cpu *cpu)
Definition: cpu_arm.cc:296
#define ARM_CONTROL_PROG32
Definition: cpu_arm.h:248
void arm_setup_initial_translation_table(struct cpu *cpu, uint32_t ttb_addr)
Definition: cpu_arm.cc:204
#define ARM_AUXCTRL_P
Definition: cpu_arm.h:263
uint32_t abt_r13_r14[2]
Definition: cpu_arm.h:154
void arm_cdp(struct cpu *cpu, uint32_t iword)
Definition: cpu_arm.cc:1561
#define ARM_DPI_NAMES
Definition: cpu_arm.h:68
#define ARM_EXCEPTION_UND
Definition: cpu_arm.h:116
void(* invalidate_translation_caches)(struct cpu *, uint64_t paddr, int flags)
Definition: cpu.h:374
#define ARM_LR
Definition: cpu_arm.h:55

Generated on Sun Sep 30 2018 16:05:18 for GXemul by doxygen 1.8.13