cpu_sh.cc Source File

Back to the index.

cpu_sh.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2005-2011 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  * Hitachi SuperH ("SH") CPU emulation.
29  *
30  * TODO: It would be nice if this could encompass both 64-bit SH5, and
31  * 32-bit SH encodings. Right now, it only really supports 32-bit mode.
32  *
33  * TODO: This actually only works or SH4 so far, not SH3.
34  */
35 
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include <unistd.h>
41 
42 #include "cpu.h"
43 #include "device.h"
44 #include "float_emul.h"
45 #include "interrupt.h"
46 #include "machine.h"
47 #include "memory.h"
48 #include "misc.h"
49 #include "settings.h"
50 #include "symbol.h"
51 
53 #include "thirdparty/sh4_mmu.h"
54 
55 
56 #define DYNTRANS_32
57 #define DYNTRANS_DELAYSLOT
58 #include "tmp_sh_head.cc"
59 
60 
61 extern int quiet_mode;
62 
63 void sh_pc_to_pointers(struct cpu *);
64 
67 
68 
69 /*
70  * sh_cpu_new():
71  *
72  * Create a new SH cpu object.
73  *
74  * Returns 1 on success, 0 if there was no matching SH processor with
75  * this cpu_type_name.
76  */
77 int sh_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
78  int cpu_id, char *cpu_type_name)
79 {
80  int i = 0;
81  struct sh_cpu_type_def cpu_type_defs[] = SH_CPU_TYPE_DEFS;
82 
83  /* Scan the cpu_type_defs list for this cpu type: */
84  while (cpu_type_defs[i].name != NULL) {
85  if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
86  break;
87  }
88  i++;
89  }
90  if (cpu_type_defs[i].name == NULL)
91  return 0;
92 
93  cpu->memory_rw = sh_memory_rw;
94 
95  cpu->cd.sh.cpu_type = cpu_type_defs[i];
97  cpu->is_32bit = cpu->cd.sh.cpu_type.bits == 32;
98 
99  if (!cpu->is_32bit) {
100  fatal("SH64 emulation not implemented. Sorry.\n");
101  exit(1);
102  }
103 
105 
107 
108  cpu->run_instr = sh_run_instr;
114 
115  /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
116  if (cpu_id == 0) {
117  debug("%s", cpu->name);
118  }
119 
120  /* Initial value of FPSCR (according to the SH4 manual): */
121  cpu->cd.sh.fpscr = 0x00040001;
122 
123  /* (Initial value of the program counter on reboot is 0xA0000000.) */
124 
125  /* Start in Privileged Mode: */
126  cpu->cd.sh.sr = SH_SR_MD | SH_SR_IMASK;
127 
128  /* Stack pointer at end of physical RAM: */
129  cpu->cd.sh.r[15] = cpu->machine->physical_ram_in_mb * 1048576 - 64;
130 
131  CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
132  CPU_SETTINGS_ADD_REGISTER32("sr", cpu->cd.sh.sr);
133  CPU_SETTINGS_ADD_REGISTER32("pr", cpu->cd.sh.pr);
134  CPU_SETTINGS_ADD_REGISTER32("vbr", cpu->cd.sh.vbr);
135  CPU_SETTINGS_ADD_REGISTER32("sgr", cpu->cd.sh.sgr);
136  CPU_SETTINGS_ADD_REGISTER32("gbr", cpu->cd.sh.gbr);
137  CPU_SETTINGS_ADD_REGISTER32("dbr", cpu->cd.sh.dbr);
138  CPU_SETTINGS_ADD_REGISTER32("macl", cpu->cd.sh.macl);
139  CPU_SETTINGS_ADD_REGISTER32("mach", cpu->cd.sh.mach);
140  CPU_SETTINGS_ADD_REGISTER32("expevt", cpu->cd.sh.expevt);
141  CPU_SETTINGS_ADD_REGISTER32("intevt", cpu->cd.sh.intevt);
142  CPU_SETTINGS_ADD_REGISTER32("tra", cpu->cd.sh.tra);
143  CPU_SETTINGS_ADD_REGISTER32("fpscr", cpu->cd.sh.fpscr);
144  CPU_SETTINGS_ADD_REGISTER32("fpul", cpu->cd.sh.fpul);
145  for (i=0; i<SH_N_GPRS; i++) {
146  char tmpstr[5];
147  snprintf(tmpstr, sizeof(tmpstr), "r%i", i);
148  CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.r[i]);
149  }
150  for (i=0; i<SH_N_GPRS_BANKED; i++) {
151  char tmpstr[15];
152  snprintf(tmpstr, sizeof(tmpstr), "r%i_bank", i);
153  CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.r_bank[i]);
154  }
155  for (i=0; i<SH_N_FPRS; i++) {
156  char tmpstr[6];
157  snprintf(tmpstr, sizeof(tmpstr), "fr%i", i);
158  CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.fr[i]);
159  snprintf(tmpstr, sizeof(tmpstr), "xf%i", i);
160  CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.xf[i]);
161  }
162  for (i=0; i<SH_N_ITLB_ENTRIES; i++) {
163  char tmpstr[15];
164  snprintf(tmpstr, sizeof(tmpstr), "itlb_hi_%i", i);
165  CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.itlb_hi[i]);
166  snprintf(tmpstr, sizeof(tmpstr), "itlb_lo_%i", i);
167  CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.itlb_lo[i]);
168  }
169  for (i=0; i<SH_N_UTLB_ENTRIES; i++) {
170  char tmpstr[15];
171  snprintf(tmpstr, sizeof(tmpstr), "utlb_hi_%i", i);
172  CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.utlb_hi[i]);
173  snprintf(tmpstr, sizeof(tmpstr), "utlb_lo_%i", i);
174  CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.utlb_lo[i]);
175  }
176 
177  /* Register the CPU's interrupts: */
178  if (cpu->cd.sh.cpu_type.arch == 4) {
179  for (i=SH_INTEVT_NMI; i<0x1000; i+=0x20) {
180  struct interrupt templ;
181  char name[100];
182  snprintf(name, sizeof(name), "%s.irq[0x%x]",
183  cpu->path, i);
184  memset(&templ, 0, sizeof(templ));
185  templ.line = i;
186  templ.name = name;
187  templ.extra = cpu;
191  }
192  } else {
193  struct interrupt templ;
194  memset(&templ, 0, sizeof(templ));
195  templ.line = i;
196  templ.name = cpu->path;
197  templ.extra = cpu;
201  }
202 
203  /* SH4-specific memory mapped registers, TLBs, caches, etc: */
204  if (cpu->cd.sh.cpu_type.arch == 4) {
205  cpu->cd.sh.pcic_pcibus = (struct pci_data *) device_add(machine, "sh4");
206 
207  /*
208  * Interrupt Controller initial values, according to the
209  * SH7760 manual:
210  */
211  cpu->cd.sh.intc_iprd = 0xda74;
212  cpu->cd.sh.intc_intmsk00 = 0xf3ff7fff;
213  cpu->cd.sh.intc_intmsk04 = 0x00ffffff;
214  /* All others are zero. */
215 
216  /* TODO: Initial priorities? */
217  cpu->cd.sh.intc_intpri00 = 0x33333333;
218  cpu->cd.sh.intc_intpri04 = 0x33333333;
219  cpu->cd.sh.intc_intpri08 = 0x33333333;
220  cpu->cd.sh.intc_intpri0c = 0x33333333;
221  }
222 
224 
225  return 1;
226 }
227 
228 
229 /*
230  * sh_update_interrupt_priorities():
231  *
232  * SH interrupts are a bit complicated; there are several intc registers
233  * controlling priorities for various peripherals:
234  *
235  * Register: Bits 15..12 11..8 7..4 3..0
236  * --------- ----------- ----- ---- ----
237  * ipra TMU0 TMU1 TMU2 Reserved
238  * iprb WDT REF Reserved Reserved
239  * iprc GPIO DMAC Reserved H-UDI
240  * iprd IRL0 IRL1 IRL2 IRL3
241  *
242  * Register: 31..28 27..24 23..20 19..16 15..12 11..8 7..4 3..0
243  * --------- ------ ------ ------ ------ ------ ----- ---- ----
244  * intpri00 IRQ4 IRQ5 IRQ6 IRQ7 Rsrvd. Rsrvd. Rsrvd. Reserved
245  * intpri04 HCAN2,0 HCAN2,1 SSI(0) SSI(1) HAC(0) HAC(1) I2C(0) I2C(1)
246  * intpri08 USB LCDC DMABRG SCIF(0) SCIF(1) SCIF(2) SIM HSPI
247  * intpri0c Reserv. Reserv. MMCIF Reserv. MFI Rsrvd. ADC CMT
248  */
250 {
251  int i;
252 
253  /*
254  * Set priorities of known interrupts, without affecting the
255  * SH_INT_ASSERTED bit:
256  */
257 
258  for (i=SH4_INTEVT_IRQ0; i<=SH4_INTEVT_IRQ14; i+=0x20) {
259  cpu->cd.sh.int_prio_and_pending[i/0x20] &= ~SH_INT_PRIO_MASK;
260  cpu->cd.sh.int_prio_and_pending[i/0x20] |= (15 - ((i -
261  SH4_INTEVT_IRQ0) / 0x20));
262  }
263 
267  (cpu->cd.sh.intc_ipra >> 12) & 0xf;
268 
272  (cpu->cd.sh.intc_ipra >> 8) & 0xf;
273 
277  (cpu->cd.sh.intc_ipra >> 4) & 0xf;
278 
279  for (i=SH4_INTEVT_SCIF_ERI; i<=SH4_INTEVT_SCIF_TXI; i+=0x20) {
280  cpu->cd.sh.int_prio_and_pending[i/0x20] &= ~SH_INT_PRIO_MASK;
281  cpu->cd.sh.int_prio_and_pending[i/0x20] |=
282  ((cpu->cd.sh.intc_intpri08 >> 16) & 0xf);
283  }
284 }
285 
286 
287 /*
288  * sh3_cpu_interrupt_assert():
289  * sh3_cpu_interrupt_deassert():
290  */
292 {
293  /* TODO */
294 }
296 {
297  /* TODO */
298 }
299 
300 
301 /*
302  * sh_cpu_interrupt_assert():
303  */
305 {
306  struct cpu *cpu = (struct cpu *) interrupt->extra;
307  unsigned int irq_nr = interrupt->line;
308  unsigned int index = irq_nr / 0x20;
309  unsigned int prio;
310 
311  /* Assert the interrupt, and check its priority level: */
312  cpu->cd.sh.int_prio_and_pending[index] |= SH_INT_ASSERTED;
313  prio = cpu->cd.sh.int_prio_and_pending[index] & SH_INT_PRIO_MASK;
314 
315  if (prio == 0) {
316  /* Interrupt not implemented? Hm. */
317  fatal("[ SH interrupt 0x%x, prio 0 (?), aborting ]\n", irq_nr);
318  exit(1);
319  }
320 
321  if (cpu->cd.sh.int_to_assert == 0 || prio > cpu->cd.sh.int_level) {
322  cpu->cd.sh.int_to_assert = irq_nr;
323  cpu->cd.sh.int_level = prio;
324  }
325 }
326 
327 
328 /*
329  * sh_cpu_interrupt_deassert():
330  */
332 {
333  struct cpu *cpu = (struct cpu *) interrupt->extra;
334  int irq_nr = interrupt->line;
335  int index = irq_nr / 0x20;
336 
337  /* Deassert the interrupt: */
338  if (cpu->cd.sh.int_prio_and_pending[index] & SH_INT_ASSERTED) {
339  cpu->cd.sh.int_prio_and_pending[index] &= ~SH_INT_ASSERTED;
340 
341  /* Calculate new interrupt assertion: */
342  cpu->cd.sh.int_to_assert = 0;
343  cpu->cd.sh.int_level = 0;
344 
345  /* NOTE/TODO: This is slow, but should hopefully work: */
346  for (index=0; index<0x1000/0x20; index++) {
347  uint8_t x = cpu->cd.sh.int_prio_and_pending[index];
348  uint8_t prio = x & SH_INT_PRIO_MASK;
349  if (x & SH_INT_ASSERTED &&
350  prio > cpu->cd.sh.int_level) {
351  cpu->cd.sh.int_to_assert = index * 0x20;
352  cpu->cd.sh.int_level = prio;
353  }
354  }
355  }
356 }
357 
358 
359 /*
360  * sh_cpu_list_available_types():
361  *
362  * Print a list of available SH CPU types.
363  */
365 {
366  int i = 0, j;
367  struct sh_cpu_type_def tdefs[] = SH_CPU_TYPE_DEFS;
368 
369  while (tdefs[i].name != NULL) {
370  debug("%s", tdefs[i].name);
371  for (j=10 - strlen(tdefs[i].name); j>0; j--)
372  debug(" ");
373  i ++;
374  if ((i % 6) == 0 || tdefs[i].name == NULL)
375  debug("\n");
376  }
377 }
378 
379 
380 /*
381  * sh_cpu_dumpinfo():
382  */
383 void sh_cpu_dumpinfo(struct cpu *cpu)
384 {
385  debug(" (%s-endian)\n",
386  cpu->byte_order == EMUL_BIG_ENDIAN? "Big" : "Little");
387 }
388 
389 
390 /*
391  * sh_cpu_instruction_has_delayslot():
392  *
393  * Return 1 if an opcode is a branch, 0 otherwise.
394  */
395 int sh_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib)
396 {
397  uint16_t iword = *((uint16_t *)&ib[0]);
398  int hi4, lo8; // , lo4
399 
400  if (!cpu->is_32bit)
401  return 0;
402 
403  if (cpu->byte_order == EMUL_BIG_ENDIAN)
404  iword = BE16_TO_HOST(iword);
405  else
406  iword = LE16_TO_HOST(iword);
407 
408  hi4 = iword >> 12;
409  lo8 = iword & 255;
410  // lo4 = iword & 15;
411 
412  switch (hi4) {
413  case 0x0:
414  if (iword == 0x000b) /* rts */
415  return 1;
416  if (iword == 0x002b) /* rte */
417  return 1;
418  if (lo8 == 0x03) /* bsrf */
419  return 1;
420  if (lo8 == 0x23) /* braf */
421  return 1;
422  break;
423  case 0x4:
424  switch (lo8) {
425  case 0x0b: /* jsr */
426  case 0x2b: /* jmp */
427  return 1;
428  }
429  break;
430  case 0x8:
431  switch ((iword >> 8) & 0xf) {
432  case 0xd: /* bt/s */
433  case 0xf: /* bf/s */
434  return 1;
435  }
436  break;
437  case 0xa: /* bra */
438  case 0xb: /* bsr */
439  return 1;
440  }
441 
442  return 0;
443 }
444 
445 
446 /*
447  * sh_cpu_register_dump():
448  *
449  * Dump cpu registers in a relatively readable format.
450  *
451  * gprs: set to non-zero to dump GPRs and some special-purpose registers.
452  * coprocs: set bit 0..3 to dump registers in coproc 0..3.
453  */
454 void sh_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
455 {
456  char *symbol;
457  uint64_t offset;
458  int i, x = cpu->cpu_id;
459 
460  if (gprs) {
461  /* Special registers (pc, ...) first: */
462  symbol = get_symbol_name(&cpu->machine->symbol_context,
463  cpu->pc, &offset);
464 
465  debug("cpu%i: pc = 0x%08" PRIx32, x, (uint32_t)cpu->pc);
466  debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
467 
468  debug("cpu%i: sr = 0x%08" PRIx32" (%s, %s, %s, %s, %s, %s,"
469  " imask=0x%x, %s, %s)\n", x, (int32_t)cpu->cd.sh.sr,
470  (cpu->cd.sh.sr & SH_SR_MD)? "MD" : "!md",
471  (cpu->cd.sh.sr & SH_SR_RB)? "RB" : "!rb",
472  (cpu->cd.sh.sr & SH_SR_BL)? "BL" : "!bl",
473  (cpu->cd.sh.sr & SH_SR_FD)? "FD" : "!fd",
474  (cpu->cd.sh.sr & SH_SR_M)? "M" : "!m",
475  (cpu->cd.sh.sr & SH_SR_Q)? "Q" : "!q",
476  (cpu->cd.sh.sr & SH_SR_IMASK) >> SH_SR_IMASK_SHIFT,
477  (cpu->cd.sh.sr & SH_SR_S)? "S" : "!s",
478  (cpu->cd.sh.sr & SH_SR_T)? "T" : "!t");
479 
480  symbol = get_symbol_name(&cpu->machine->symbol_context,
481  cpu->cd.sh.pr, &offset);
482  debug("cpu%i: pr = 0x%08" PRIx32, x, (uint32_t)cpu->cd.sh.pr);
483  debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
484 
485  debug("cpu%i: mach = 0x%08" PRIx32" macl = 0x%08" PRIx32
486  " gbr = 0x%08" PRIx32"\n", x, (uint32_t)cpu->cd.sh.mach,
487  (uint32_t)cpu->cd.sh.macl, (uint32_t)cpu->cd.sh.gbr);
488 
489  for (i=0; i<SH_N_GPRS; i++) {
490  if ((i % 4) == 0)
491  debug("cpu%i:", x);
492  debug(" r%-2i = 0x%08x ", i, (int)cpu->cd.sh.r[i]);
493  if ((i % 4) == 3)
494  debug("\n");
495  }
496  }
497 
498  if (coprocs & 1) {
499  /* Floating point: */
500  debug("cpu%i: fpscr = 0x%08" PRIx32" (%s,%s,%s) fpul = 0x%08"
501  PRIx32"\n", x, cpu->cd.sh.fpscr,
502  cpu->cd.sh.fpscr & SH_FPSCR_PR? "PR" : "!pr",
503  cpu->cd.sh.fpscr & SH_FPSCR_SZ? "SZ" : "!sz",
504  cpu->cd.sh.fpscr & SH_FPSCR_FR? "FR" : "!fr",
505  cpu->cd.sh.fpul);
506 
507  for (i=0; i<SH_N_FPRS; i++) {
508  if ((i % 4) == 0)
509  debug("cpu%i:", x);
510  debug(" fr%-2i=0x%08x ", i, (int)cpu->cd.sh.fr[i]);
511  if ((i % 4) == 3)
512  debug("\n");
513  }
514 
515  for (i=0; i<SH_N_FPRS; i++) {
516  if ((i % 4) == 0)
517  debug("cpu%i:", x);
518  debug(" xf%-2i=0x%08x ", i, (int)cpu->cd.sh.xf[i]);
519  if ((i % 4) == 3)
520  debug("\n");
521  }
522  }
523 
524  if (coprocs & 2) {
525  /* System registers, etc: */
526  debug("cpu%i: vbr = 0x%08" PRIx32" sgr = 0x%08" PRIx32
527  " dbr = 0x%08" PRIx32"\n", x, cpu->cd.sh.vbr, cpu->cd.sh.sgr,
528  cpu->cd.sh.dbr);
529  debug("cpu%i: spc = 0x%08" PRIx32" ssr = 0x%08" PRIx32"\n",
530  x, cpu->cd.sh.spc, cpu->cd.sh.ssr);
531  debug("cpu%i: expevt = 0x%" PRIx32" intevt = 0x%" PRIx32
532  " tra = 0x%" PRIx32"\n", x, cpu->cd.sh.expevt,
533  cpu->cd.sh.intevt, cpu->cd.sh.tra);
534 
535  for (i=0; i<SH_N_GPRS_BANKED; i++) {
536  if ((i % 2) == 0)
537  debug("cpu%i:", x);
538  debug(" r%i_bank = 0x%08x ", i,
539  (int)cpu->cd.sh.r_bank[i]);
540  if ((i % 2) == 1)
541  debug("\n");
542  }
543  }
544 }
545 
546 
547 /*
548  * sh_cpu_tlbdump():
549  *
550  * Called from the debugger to dump the TLB in a readable format.
551  * x is the cpu number to dump, or -1 to dump all CPUs.
552  *
553  * If rawflag is nonzero, then the TLB contents isn't formated nicely,
554  * just dumped.
555  */
556 void sh_cpu_tlbdump(struct machine *m, int x, int rawflag)
557 {
558  int i, j;
559 
560  for (j=0; j<m->ncpus; j++) {
561  struct cpu *cpu = m->cpus[j];
562 
563  if (x >= 0 && j != x)
564  continue;
565 
566  for (i=0; i<SH_N_ITLB_ENTRIES; i++)
567  printf("cpu%i: itlb_hi_%-2i = 0x%08" PRIx32" "
568  "itlb_lo_%-2i = 0x%08" PRIx32"\n", j, i,
569  (uint32_t) cpu->cd.sh.itlb_hi[i], i,
570  (uint32_t) cpu->cd.sh.itlb_lo[i]);
571  for (i=0; i<SH_N_UTLB_ENTRIES; i++)
572  printf("cpu%i: utlb_hi_%-2i = 0x%08" PRIx32" "
573  "utlb_lo_%-2i = 0x%08" PRIx32"\n", j, i,
574  (uint32_t) cpu->cd.sh.utlb_hi[i], i,
575  (uint32_t) cpu->cd.sh.utlb_lo[i]);
576  }
577 }
578 
579 
580 /*
581  * sh_update_sr():
582  *
583  * Writes a new value to the status register.
584  */
585 void sh_update_sr(struct cpu *cpu, uint32_t new_sr)
586 {
587  uint32_t old_sr = cpu->cd.sh.sr;
588 
589  if ((new_sr & SH_SR_RB) != (old_sr & SH_SR_RB)) {
590  int i;
591  for (i=0; i<SH_N_GPRS_BANKED; i++) {
592  uint32_t tmp = cpu->cd.sh.r[i];
593  cpu->cd.sh.r[i] = cpu->cd.sh.r_bank[i];
594  cpu->cd.sh.r_bank[i] = tmp;
595  }
596  }
597 
598  cpu->cd.sh.sr = new_sr;
599 }
600 
601 
602 /*
603  * sh_update_fpscr():
604  *
605  * Writes a new value to the floating-point status/control register.
606  */
607 void sh_update_fpscr(struct cpu *cpu, uint32_t new_fpscr)
608 {
609  uint32_t old_fpscr = cpu->cd.sh.fpscr;
610 
611  if ((new_fpscr & SH_FPSCR_FR) != (old_fpscr & SH_FPSCR_FR)) {
612  int i;
613  for (i=0; i<SH_N_FPRS; i++) {
614  uint32_t tmp = cpu->cd.sh.fr[i];
615  cpu->cd.sh.fr[i] = cpu->cd.sh.xf[i];
616  cpu->cd.sh.xf[i] = tmp;
617  }
618  }
619 
620  cpu->cd.sh.fpscr = new_fpscr;
621 }
622 
623 
624 /*
625  * sh_exception():
626  *
627  * Causes a transfer of control to an exception or interrupt handler.
628  * If intevt > 0, then it is an interrupt, otherwise an exception.
629  *
630  * vaddr contains the faulting address, on TLB exceptions.
631  */
632 void sh_exception(struct cpu *cpu, int expevt, int intevt, uint32_t vaddr)
633 {
634  uint32_t vbr = cpu->cd.sh.vbr;
635 
636  if (!quiet_mode) {
637  if (intevt > 0)
638  debug("[ interrupt 0x%03x", intevt);
639  else
640  debug("[ exception 0x%03x", expevt);
641 
642  debug(", pc=0x%08" PRIx32" ", (uint32_t)cpu->pc);
643  if (intevt == 0)
644  debug("vaddr=0x%08" PRIx32" ", vaddr);
645 
646  debug(" ]\n");
647  }
648 
649  if (cpu->cd.sh.sr & SH_SR_BL) {
650  fatal("[ sh_exception(): BL bit already set. ]\n");
651 
652  /* This is actually OK in two cases: a User Break,
653  or on NMI interrupts if a special flag is set? */
654  /* TODO */
655 
656  expevt = EXPEVT_RESET_POWER;
657  }
658 
659  if (cpu->is_halted) {
660  /*
661  * If the exception occurred on a 'sleep' instruction, then let
662  * the instruction following the sleep instruction be the one
663  * where execution resumes when the interrupt service routine
664  * returns.
665  */
666  cpu->is_halted = 0;
667  cpu->pc += sizeof(uint16_t);
668  }
669 
670  if (cpu->delay_slot) {
672  cpu->pc -= sizeof(uint16_t);
673  }
674 
675 
676  /*
677  * Stuff common to all exceptions:
678  */
679 
680  cpu->cd.sh.spc = cpu->pc;
681  cpu->cd.sh.ssr = cpu->cd.sh.sr;
682  cpu->cd.sh.sgr = cpu->cd.sh.r[15];
683 
684  if (intevt > 0) {
685  cpu->cd.sh.intevt = intevt;
686  expevt = -1;
687  } else {
688  cpu->cd.sh.expevt = expevt;
689  }
690 
691  sh_update_sr(cpu, cpu->cd.sh.sr | SH_SR_MD | SH_SR_RB | SH_SR_BL);
692 
693  /* Most exceptions set PC to VBR + 0x100. */
694  cpu->pc = vbr + 0x100;
695 
696 
697  /* Specific cases: */
698  switch (expevt) {
699 
700  case -1: /* Interrupt */
701  cpu->pc = vbr + 0x600;
702  break;
703 
704  case EXPEVT_RESET_POWER:
705  case EXPEVT_RESET_MANUAL:
706  cpu->pc = 0xa0000000;
707  cpu->cd.sh.vbr = 0x00000000;
708  sh_update_sr(cpu, (cpu->cd.sh.sr | SH_SR_IMASK) & ~SH_SR_FD);
709  break;
710 
711  case EXPEVT_TLB_MISS_LD:
712  case EXPEVT_TLB_MISS_ST:
713  cpu->pc = vbr + 0x400;
714  case EXPEVT_TLB_PROT_LD:
715  case EXPEVT_TLB_PROT_ST:
716  case EXPEVT_TLB_MOD:
717  cpu->cd.sh.tea = vaddr;
718  cpu->cd.sh.pteh &= ~SH4_PTEH_VPN_MASK;
719  cpu->cd.sh.pteh |= (vaddr & SH4_PTEH_VPN_MASK);
720  break;
721 
722  case EXPEVT_TRAPA:
723  /*
724  * Note: The TRA register is already set by the implementation
725  * of the trapa instruction. See cpu_sh_instr.c for details.
726  * Here, spc is incremented, so that a return from the trap
727  * handler transfers control to the instruction _following_
728  * the trapa.
729  */
730  cpu->cd.sh.spc += sizeof(uint16_t);
731  break;
732 
733  case EXPEVT_RES_INST:
734  /*
735  * Note: Having this code here makes it possible to catch
736  * reserved instructions; during normal instruction execution,
737  * these are not very common.
738  */
739 #if 1
740  printf("\nRESERVED SuperH instruction at spc=%08" PRIx32"\n",
741  cpu->cd.sh.spc);
742  exit(1);
743 #else
744  break;
745 #endif
746 
747  case EXPEVT_FPU_DISABLE:
748  break;
749 
750  default:fatal("sh_exception(): exception 0x%x is not yet "
751  "implemented.\n", expevt);
752  exit(1);
753  }
754 
755  sh_pc_to_pointers(cpu);
756 }
757 
758 
759 /*
760  * sh_cpu_disassemble_instr():
761  *
762  * SHcompact instruction disassembly. The top 4 bits of each 16-bit
763  * instruction word is used as the main opcode. For most instructions, the
764  * lowest 4 or 8 bits then select sub-opcode.
765  *
766  * This function convert an instruction word into human readable format,
767  * for instruction tracing.
768  *
769  * If running is 1, cpu->pc should be the address of the instruction.
770  *
771  * If running is 0, things that depend on the runtime environment (eg.
772  * register contents) will not be shown, and addr will be used instead of
773  * cpu->pc for relative addresses.
774  */
775 int sh_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
776  int running, uint64_t dumpaddr)
777 {
778  char *symbol;
779  uint64_t offset, addr;
780  uint16_t iword;
781 
782  if (running)
783  dumpaddr = cpu->pc;
784 
785  symbol = get_symbol_name(&cpu->machine->symbol_context,
786  dumpaddr, &offset);
787  if (symbol != NULL && offset==0)
788  debug("<%s>\n", symbol);
789 
790  if (cpu->machine->ncpus > 1 && running)
791  debug("cpu%i: ", cpu->cpu_id);
792 
793  debug("%08" PRIx32, (uint32_t) dumpaddr);
794 
795  if (cpu->byte_order == EMUL_BIG_ENDIAN)
796  iword = (instr[0] << 8) + instr[1];
797  else
798  iword = (instr[1] << 8) + instr[0];
799 
800  debug(": %04x %s\t", iword, cpu->delay_slot? "(d)" : "");
801  const int hi4 = iword >> 12, lo4 = iword & 15, lo8 = iword & 255;
802  int r8 = (iword >> 8) & 15, r4 = (iword >> 4) & 15;
803 
804 
805  /*
806  * Decode the instruction:
807  */
808 
809  switch (hi4) {
810  case 0x0:
811  if (lo8 == 0x02)
812  debug("stc\tsr,r%i\n", r8);
813  else if (lo8 == 0x03)
814  debug("bsrf\tr%i\n", r8);
815  else if (lo4 >= 4 && lo4 <= 6) {
816  if (lo4 == 0x4)
817  debug("mov.b\tr%i,@(r0,r%i)", r4, r8);
818  else if (lo4 == 0x5)
819  debug("mov.w\tr%i,@(r0,r%i)", r4, r8);
820  else if (lo4 == 0x6)
821  debug("mov.l\tr%i,@(r0,r%i)", r4, r8);
822  if (running) {
823  addr = cpu->cd.sh.r[0] + cpu->cd.sh.r[r8];
824  debug("\t; r0+r%i = ", r8);
825  symbol = get_symbol_name(
826  &cpu->machine->symbol_context,
827  addr, &offset);
828  if (symbol != NULL)
829  debug("<%s>", symbol);
830  else
831  debug("0x%08" PRIx32, addr);
832  }
833  debug("\n");
834  } else if (lo4 == 0x7)
835  debug("mul.l\tr%i,r%i\n", r4, r8);
836  else if (iword == 0x0008)
837  debug("clrt\n");
838  else if (iword == 0x0009)
839  debug("nop\n");
840  else if (lo8 == 0x0a)
841  debug("sts\tmach,r%i\n", r8);
842  else if (iword == 0x000b)
843  debug("rts\n");
844  else if (lo4 >= 0xc && lo4 <= 0xe) {
845  if (lo4 == 0xc)
846  debug("mov.b\t@(r0,r%i),r%i", r4, r8);
847  else if (lo4 == 0xd)
848  debug("mov.w\t@(r0,r%i),r%i", r4, r8);
849  else if (lo4 == 0xe)
850  debug("mov.l\t@(r0,r%i),r%i", r4, r8);
851  if (running) {
852  addr = cpu->cd.sh.r[0] + cpu->cd.sh.r[r4];
853  debug("\t; r0+r%i = ", r4);
854  symbol = get_symbol_name(
855  &cpu->machine->symbol_context,
856  addr, &offset);
857  if (symbol != NULL)
858  debug("<%s>", symbol);
859  else
860  debug("0x%08" PRIx32, addr);
861  }
862  debug("\n");
863  } else if (lo8 == 0x12)
864  debug("stc\tgbr,r%i\n", r8);
865  else if (iword == 0x0018)
866  debug("sett\n");
867  else if (iword == 0x0019)
868  debug("div0u\n");
869  else if (lo8 == 0x1a)
870  debug("sts\tmacl,r%i\n", r8);
871  else if (iword == 0x001b)
872  debug("sleep\n");
873  else if (lo8 == 0x22)
874  debug("stc\tvbr,r%i\n", r8);
875  else if (lo8 == 0x23)
876  debug("braf\tr%i\n", r8);
877  else if (iword == 0x0028)
878  debug("clrmac\n");
879  else if (lo8 == 0x29)
880  debug("movt\tr%i\n", r8);
881  else if (lo8 == 0x2a)
882  debug("sts\tpr,r%i\n", r8);
883  else if (iword == 0x002b)
884  debug("rte\n");
885  else if (lo8 == 0x32)
886  debug("stc\tssr,r%i\n", r8);
887  else if (iword == 0x0038)
888  debug("ldtlb\n");
889  else if (iword == 0x003b)
890  debug("brk\n");
891  else if (lo8 == 0x42)
892  debug("stc\tspc,r%i\n", r8);
893  else if (iword == 0x0048)
894  debug("clrs\n");
895  else if (iword == 0x0058)
896  debug("sets\n");
897  else if (lo8 == 0x5a)
898  debug("sts\tfpul,r%i\n", r8);
899  else if (lo8 == 0x6a)
900  debug("sts\tfpscr,r%i\n", r8);
901  else if ((lo8 & 0x8f) == 0x82)
902  debug("stc\tr%i_bank,r%i\n", (lo8 >> 4) & 7, r8);
903  else if (lo8 == 0x83)
904  debug("pref\t@r%i\n", r8);
905  else if (lo8 == 0x93)
906  debug("ocbi\t@r%i\n", r8);
907  else if (lo8 == 0xa3)
908  debug("ocbp\t@r%i\n", r8);
909  else if (lo8 == 0xb3)
910  debug("ocbwb\t@r%i\n", r8);
911  else if (lo8 == 0xc3)
912  debug("movca.l\tr0,@r%i\n", r8);
913  else if (lo8 == 0xfa)
914  debug("stc\tdbr,r%i\n", r8);
915  else if (iword == SH_INVALID_INSTR)
916  debug("gxemul_dreamcast_prom_emul\n");
917  else
918  debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
919  break;
920  case 0x1:
921  debug("mov.l\tr%i,@(%i,r%i)", r4, lo4 * 4, r8);
922  if (running) {
923  addr = cpu->cd.sh.r[r8] + lo4 * 4;
924  debug("\t; r%i+%i = ", r8, lo4 * 4);
925  symbol = get_symbol_name(&cpu->machine->symbol_context,
926  addr, &offset);
927  if (symbol != NULL)
928  debug("<%s>", symbol);
929  else
930  debug("0x%08" PRIx32, addr);
931  }
932  debug("\n");
933  break;
934  case 0x2:
935  if (lo4 == 0x0)
936  debug("mov.b\tr%i,@r%i", r4, r8);
937  else if (lo4 == 0x1)
938  debug("mov.w\tr%i,@r%i", r4, r8);
939  else if (lo4 == 0x2)
940  debug("mov.l\tr%i,@r%i", r4, r8);
941  else if (lo4 == 0x4)
942  debug("mov.b\tr%i,@-r%i", r4, r8);
943  else if (lo4 == 0x5)
944  debug("mov.w\tr%i,@-r%i", r4, r8);
945  else if (lo4 == 0x6)
946  debug("mov.l\tr%i,@-r%i", r4, r8);
947  else if (lo4 == 0x7)
948  debug("div0s\tr%i,r%i", r4, r8);
949  else if (lo4 == 0x8)
950  debug("tst\tr%i,r%i", r4, r8);
951  else if (lo4 == 0x9)
952  debug("and\tr%i,r%i", r4, r8);
953  else if (lo4 == 0xa)
954  debug("xor\tr%i,r%i", r4, r8);
955  else if (lo4 == 0xb)
956  debug("or\tr%i,r%i", r4, r8);
957  else if (lo4 == 0xc)
958  debug("cmp/str\tr%i,r%i", r4, r8);
959  else if (lo4 == 0xd)
960  debug("xtrct\tr%i,r%i", r4, r8);
961  else if (lo4 == 0xe)
962  debug("mulu.w\tr%i,r%i", r4, r8);
963  else if (lo4 == 0xf)
964  debug("muls.w\tr%i,r%i", r4, r8);
965  else
966  debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x", hi4, lo8);
967  if (running && lo4 <= 6) {
968  debug("\t; r%i = 0x%08" PRIx32, r8, cpu->cd.sh.r[r8]);
969  }
970  debug("\n");
971  break;
972  case 0x3:
973  if (lo4 == 0x0)
974  debug("cmp/eq\tr%i,r%i\n", r4, r8);
975  else if (lo4 == 0x2)
976  debug("cmp/hs\tr%i,r%i\n", r4, r8);
977  else if (lo4 == 0x3)
978  debug("cmp/ge\tr%i,r%i\n", r4, r8);
979  else if (lo4 == 0x4)
980  debug("div1\tr%i,r%i\n", r4, r8);
981  else if (lo4 == 0x5)
982  debug("dmulu.l\tr%i,r%i\n", r4, r8);
983  else if (lo4 == 0x6)
984  debug("cmp/hi\tr%i,r%i\n", r4, r8);
985  else if (lo4 == 0x7)
986  debug("cmp/gt\tr%i,r%i\n", r4, r8);
987  else if (lo4 == 0x8)
988  debug("sub\tr%i,r%i\n", r4, r8);
989  else if (lo4 == 0xa)
990  debug("subc\tr%i,r%i\n", r4, r8);
991  else if (lo4 == 0xb)
992  debug("subv\tr%i,r%i\n", r4, r8);
993  else if (lo4 == 0xc)
994  debug("add\tr%i,r%i\n", r4, r8);
995  else if (lo4 == 0xd)
996  debug("dmuls.l\tr%i,r%i\n", r4, r8);
997  else if (lo4 == 0xe)
998  debug("addc\tr%i,r%i\n", r4, r8);
999  else if (lo4 == 0xf)
1000  debug("addv\tr%i,r%i\n", r4, r8);
1001  else
1002  debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
1003  break;
1004  case 0x4:
1005  if (lo8 == 0x00)
1006  debug("shll\tr%i\n", r8);
1007  else if (lo8 == 0x01)
1008  debug("shlr\tr%i\n", r8);
1009  else if (lo8 == 0x02)
1010  debug("sts.l\tmach,@-r%i\n", r8);
1011  else if (lo8 == 0x03)
1012  debug("stc.l\tsr,@-r%i\n", r8);
1013  else if (lo8 == 0x04)
1014  debug("rotl\tr%i\n", r8);
1015  else if (lo8 == 0x05)
1016  debug("rotr\tr%i\n", r8);
1017  else if (lo8 == 0x06)
1018  debug("lds.l\t@r%i+,mach\n", r8);
1019  else if (lo8 == 0x07)
1020  debug("ldc.l\t@r%i+,sr\n", r8);
1021  else if (lo8 == 0x08)
1022  debug("shll2\tr%i\n", r8);
1023  else if (lo8 == 0x09)
1024  debug("shlr2\tr%i\n", r8);
1025  else if (lo8 == 0x0a)
1026  debug("lds\tr%i,mach\n", r8);
1027  else if (lo8 == 0x0b)
1028  debug("jsr\t@r%i\n", r8);
1029  else if (lo4 == 0xc)
1030  debug("shad\tr%i,r%i\n", r4, r8);
1031  else if (lo4 == 0xd)
1032  debug("shld\tr%i,r%i\n", r4, r8);
1033  else if (lo8 == 0x0e)
1034  debug("ldc\tr%i,sr\n", r8);
1035  else if (lo8 == 0x10)
1036  debug("dt\tr%i\n", r8);
1037  else if (lo8 == 0x11)
1038  debug("cmp/pz\tr%i\n", r8);
1039  else if (lo8 == 0x12)
1040  debug("sts.l\tmacl,@-r%i\n", r8);
1041  else if (lo8 == 0x13)
1042  debug("stc.l\tgbr,@-r%i\n", r8);
1043  else if (lo8 == 0x15)
1044  debug("cmp/pl\tr%i\n", r8);
1045  else if (lo8 == 0x16)
1046  debug("lds.l\t@r%i+,macl\n", r8);
1047  else if (lo8 == 0x17)
1048  debug("ldc.l\t@r%i+,gbr\n", r8);
1049  else if (lo8 == 0x18)
1050  debug("shll8\tr%i\n", r8);
1051  else if (lo8 == 0x19)
1052  debug("shlr8\tr%i\n", r8);
1053  else if (lo8 == 0x1a)
1054  debug("lds\tr%i,macl\n", r8);
1055  else if (lo8 == 0x1b)
1056  debug("tas.b\t@r%i\n", r8);
1057  else if (lo8 == 0x1e)
1058  debug("ldc\tr%i,gbr\n", r8);
1059  else if (lo8 == 0x20)
1060  debug("shal\tr%i\n", r8);
1061  else if (lo8 == 0x21)
1062  debug("shar\tr%i\n", r8);
1063  else if (lo8 == 0x22)
1064  debug("sts.l\tpr,@-r%i\n", r8);
1065  else if (lo8 == 0x23)
1066  debug("stc.l\tvbr,@-r%i\n", r8);
1067  else if (lo8 == 0x24)
1068  debug("rotcl\tr%i\n", r8);
1069  else if (lo8 == 0x25)
1070  debug("rotcr\tr%i\n", r8);
1071  else if (lo8 == 0x26)
1072  debug("lds.l\t@r%i+,pr\n", r8);
1073  else if (lo8 == 0x27)
1074  debug("ldc.l\t@r%i+,vbr\n", r8);
1075  else if (lo8 == 0x28)
1076  debug("shll16\tr%i\n", r8);
1077  else if (lo8 == 0x29)
1078  debug("shlr16\tr%i\n", r8);
1079  else if (lo8 == 0x2a)
1080  debug("lds\tr%i,pr\n", r8);
1081  else if (lo8 == 0x2b) {
1082  debug("jmp\t@r%i", r8);
1083  if (running) {
1084  symbol = get_symbol_name(
1085  &cpu->machine->symbol_context,
1086  cpu->cd.sh.r[r8], &offset);
1087  if (symbol != NULL)
1088  debug("\t\t; <%s>", symbol);
1089  }
1090  debug("\n");
1091  } else if (lo8 == 0x2e)
1092  debug("ldc\tr%i,vbr\n", r8);
1093  else if (lo8 == 0x33)
1094  debug("stc.l\tssr,@-r%i\n", r8);
1095  else if (lo8 == 0x37)
1096  debug("ldc.l\t@r%i+,ssr\n", r8);
1097  else if (lo8 == 0x3e)
1098  debug("ldc\tr%i,ssr\n", r8);
1099  else if (lo8 == 0x43)
1100  debug("stc.l\tspc,@-r%i\n", r8);
1101  else if (lo8 == 0x47)
1102  debug("ldc.l\t@r%i+,spc\n", r8);
1103  else if (lo8 == 0x4e)
1104  debug("ldc\tr%i,spc\n", r8);
1105  else if (lo8 == 0x52)
1106  debug("sts.l\tfpul,@-r%i\n", r8);
1107  else if (lo8 == 0x56)
1108  debug("lds.l\t@r%i+,fpul\n", r8);
1109  else if (lo8 == 0x5a)
1110  debug("lds\tr%i,fpul\n", r8);
1111  else if (lo8 == 0x62)
1112  debug("sts.l\tfpscr,@-r%i\n", r8);
1113  else if (lo8 == 0x66)
1114  debug("lds.l\t@r%i+,fpscr\n", r8);
1115  else if (lo8 == 0x6a)
1116  debug("lds\tr%i,fpscr\n", r8);
1117  else if ((lo8 & 0x8f) == 0x83)
1118  debug("stc.l\tr%i_bank,@-r%i\n", (lo8 >> 4) & 7, r8);
1119  else if ((lo8 & 0x8f) == 0x87)
1120  debug("ldc.l\t@r%i,r%i_bank\n", r8, (lo8 >> 4) & 7, r8);
1121  else if ((lo8 & 0x8f) == 0x8e)
1122  debug("ldc\tr%i,r%i_bank\n", r8, (lo8 >> 4) & 7);
1123  else if (lo8 == 0xfa)
1124  debug("ldc\tr%i,dbr\n", r8);
1125  else
1126  debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
1127  break;
1128  case 0x5:
1129  debug("mov.l\t@(%i,r%i),r%i", lo4 * 4, r4, r8);
1130  if (running) {
1131  addr = cpu->cd.sh.r[r4] + lo4 * 4;
1132  symbol = get_symbol_name(&cpu->machine->symbol_context, addr, &offset);
1133  if (symbol != NULL)
1134  debug("\t; r%i+%i <%s>", r4, lo4 * 4, symbol);
1135  else
1136  debug("\t; r%i+%i = 0x%08" PRIx32, r4, lo4 * 4, (int)addr);
1137  }
1138  debug("\n");
1139  break;
1140  case 0x6:
1141  if (lo4 == 0x0)
1142  debug("mov.b\t@r%i,r%i", r4, r8);
1143  else if (lo4 == 0x1)
1144  debug("mov.w\t@r%i,r%i", r4, r8);
1145  else if (lo4 == 0x2)
1146  debug("mov.l\t@r%i,r%i", r4, r8);
1147  else if (lo4 == 0x3)
1148  debug("mov\tr%i,r%i", r4, r8);
1149  else if (lo4 == 0x4)
1150  debug("mov.b\t@r%i+,r%i", r4, r8);
1151  else if (lo4 == 0x5)
1152  debug("mov.w\t@r%i+,r%i", r4, r8);
1153  else if (lo4 == 0x6)
1154  debug("mov.l\t@r%i+,r%i", r4, r8);
1155  else if (lo4 == 0x7)
1156  debug("not\tr%i,r%i", r4, r8);
1157  else if (lo4 == 0x8)
1158  debug("swap.b\tr%i,r%i", r4, r8);
1159  else if (lo4 == 0x9)
1160  debug("swap.w\tr%i,r%i", r4, r8);
1161  else if (lo4 == 0xa)
1162  debug("negc\tr%i,r%i", r4, r8);
1163  else if (lo4 == 0xb)
1164  debug("neg\tr%i,r%i", r4, r8);
1165  else if (lo4 == 0xc)
1166  debug("extu.b\tr%i,r%i", r4, r8);
1167  else if (lo4 == 0xd)
1168  debug("extu.w\tr%i,r%i", r4, r8);
1169  else if (lo4 == 0xe)
1170  debug("exts.b\tr%i,r%i", r4, r8);
1171  else if (lo4 == 0xf)
1172  debug("exts.w\tr%i,r%i", r4, r8);
1173  else
1174  debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x", hi4, lo8);
1175  if (running && lo4 < 8 && (lo4 & 3) < 3) {
1176  debug("\t; r%i = 0x%08" PRIx32, r4, cpu->cd.sh.r[r4]);
1177  }
1178  debug("\n");
1179  break;
1180  case 0x7:
1181  debug("add\t#%i,r%i\n", (int8_t)lo8, r8);
1182  break;
1183  case 0x8:
1184  if (r8 == 0 || r8 == 4) {
1185  if (r8 == 0x0)
1186  debug("mov.b\tr0,@(%i,r%i)", lo4, r4);
1187  else if (r8 == 0x4)
1188  debug("mov.b\t@(%i,r%i),r0", lo4, r4);
1189  if (running) {
1190  debug("\t; r%i+%i = 0x%08" PRIx32, r4, lo4,
1191  cpu->cd.sh.r[r4] + lo4);
1192  }
1193  debug("\n");
1194  } else if (r8 == 1 || r8 == 5) {
1195  if (r8 == 0x1)
1196  debug("mov.w\tr0,@(%i,r%i)", lo4 * 2, r4);
1197  else if (r8 == 0x5)
1198  debug("mov.w\t@(%i,r%i),r0", lo4 * 2, r4);
1199  if (running) {
1200  debug("\t; r%i+%i = 0x%08" PRIx32, r4, lo4 * 2,
1201  cpu->cd.sh.r[r4] + lo4 * 2);
1202  }
1203  debug("\n");
1204  } else if (r8 == 0x8) {
1205  debug("cmp/eq\t#%i,r0\n", (int8_t)lo8);
1206  } else if (r8 == 0x9 || r8 == 0xb || r8 == 0xd || r8 == 0xf) {
1207  addr = (int8_t)lo8;
1208  addr = dumpaddr + 4 + (addr << 1);
1209  debug("b%s%s\t0x%x",
1210  (r8 == 0x9 || r8 == 0xd)? "t" : "f",
1211  (r8 == 0x9 || r8 == 0xb)? "" : "/s", (int)addr);
1212  symbol = get_symbol_name(&cpu->machine->symbol_context,
1213  addr, &offset);
1214  if (symbol != NULL)
1215  debug("\t; <%s>", symbol);
1216  debug("\n");
1217  } else
1218  debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);
1219  break;
1220  case 0x9:
1221  case 0xd:
1222  addr = lo8 * (hi4==9? 2 : 4);
1223  addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4;
1224  debug("mov.%s\t0x%x,r%i", hi4==9? "w":"l", (int)addr, r8);
1225  symbol = get_symbol_name(&cpu->machine->symbol_context,
1226  addr, &offset);
1227  if (symbol != NULL)
1228  debug("\t; <%s>", symbol);
1229  debug("\n");
1230  break;
1231  case 0xa:
1232  case 0xb:
1233  addr = (int32_t)(int16_t)((iword & 0xfff) << 4);
1234  addr = ((int32_t)addr >> 3);
1235  addr += dumpaddr + 4;
1236  debug("%s\t0x%x", hi4==0xa? "bra":"bsr", (int)addr);
1237 
1238  symbol = get_symbol_name(&cpu->machine->symbol_context,
1239  addr, &offset);
1240  if (symbol != NULL)
1241  debug("\t; <%s>", symbol);
1242  debug("\n");
1243  break;
1244  case 0xc:
1245  if (r8 == 0x0)
1246  debug("mov.b\tr0,@(%i,gbr)\n", lo8);
1247  else if (r8 == 0x1)
1248  debug("mov.w\tr0,@(%i,gbr)\n", lo8 * 2);
1249  else if (r8 == 0x2)
1250  debug("mov.l\tr0,@(%i,gbr)\n", lo8 * 4);
1251  else if (r8 == 0x3)
1252  debug("trapa\t#%i\n", (uint8_t)lo8);
1253  else if (r8 == 0x4)
1254  debug("mov.b\t(%i,gbr),r0\n", lo8);
1255  else if (r8 == 0x5)
1256  debug("mov.w\t(%i,gbr),r0\n", lo8 * 2);
1257  else if (r8 == 0x6)
1258  debug("mov.l\t(%i,gbr),r0\n", lo8 * 4);
1259  else if (r8 == 0x7) {
1260  addr = lo8 * 4 + (dumpaddr & ~3) + 4;
1261  debug("mova\t0x%x,r0\n", (int)addr);
1262  } else if (r8 == 0x8)
1263  debug("tst\t#%i,r0\n", (uint8_t)lo8);
1264  else if (r8 == 0x9)
1265  debug("and\t#%i,r0\n", (uint8_t)lo8);
1266  else if (r8 == 0xa)
1267  debug("xor\t#%i,r0\n", (uint8_t)lo8);
1268  else if (r8 == 0xb)
1269  debug("or\t#%i,r0\n", (uint8_t)lo8);
1270  else if (r8 == 0xc)
1271  debug("tst.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1272  else if (r8 == 0xd)
1273  debug("and.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1274  else if (r8 == 0xe)
1275  debug("xor.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1276  else if (r8 == 0xf)
1277  debug("or.b\t#%i,@(r0,gbr)\n", (uint8_t)lo8);
1278  else
1279  debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);
1280  break;
1281  case 0xe:
1282  debug("mov\t#%i,r%i\n", (int8_t)lo8, r8);
1283  break;
1284  case 0xf:
1285  if (lo4 == 0x0)
1286  debug("fadd\t%sr%i,%sr%i\n",
1287  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1288  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1289  else if (lo4 == 0x1)
1290  debug("fsub\t%sr%i,%sr%i\n",
1291  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1292  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1293  else if (lo4 == 0x2)
1294  debug("fmul\t%sr%i,%sr%i\n",
1295  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1296  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1297  else if (lo4 == 0x3)
1298  debug("fdiv\t%sr%i,%sr%i\n",
1299  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1300  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1301  else if (lo4 == 0x4)
1302  debug("fcmp/eq\t%sr%i,%sr%i\n",
1303  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1304  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1305  else if (lo4 == 0x5)
1306  debug("fcmp/gt\t%sr%i,%sr%i\n",
1307  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r4,
1308  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1309  else if (lo4 == 0x6) {
1310  const char *n = "fr";
1311  if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1312  n = (r8 & 1)? "xd" : "dr";
1313  r8 &= ~1;
1314  }
1315  debug("fmov\t@(r0,r%i),%s%i\n", r4, n, r8);
1316  } else if (lo4 == 0x7) {
1317  const char *n = "fr";
1318  if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1319  n = (r4 & 1)? "xd" : "dr";
1320  r4 &= ~1;
1321  }
1322  debug("fmov\t%s%i,@(r0,r%i)\n", n, r4, r8);
1323  } else if (lo4 == 0x8) {
1324  const char *n = "fr";
1325  if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1326  n = (r8 & 1)? "xd" : "dr";
1327  r8 &= ~1;
1328  }
1329  debug("fmov\t@r%i,%s%i\n", r4, n, r8);
1330  } else if (lo4 == 0x9) {
1331  const char *n = "fr";
1332  if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1333  n = (r8 & 1)? "xd" : "dr";
1334  r8 &= ~1;
1335  }
1336  debug("fmov\t@r%i+,%s%i\n", r4, n, r8);
1337  } else if (lo4 == 0xa) {
1338  const char *n = "fr";
1339  if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1340  n = (r4 & 1)? "xd" : "dr";
1341  r4 &= ~1;
1342  }
1343  debug("fmov\t%s%i,@r%i\n", n, r4, r8);
1344  } else if (lo4 == 0xb) {
1345  const char *n = "fr";
1346  if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1347  n = (r4 & 1)? "xd" : "dr";
1348  r4 &= ~1;
1349  }
1350  debug("fmov\t%s%i,@-r%i\n", n, r4, r8);
1351  } else if (lo4 == 0xc) {
1352  const char *n1 = "fr", *n2 = "fr";
1353  if (cpu->cd.sh.fpscr & SH_FPSCR_SZ) {
1354  n1 = (r4 & 1)? "xd" : "dr";
1355  n2 = (r8 & 1)? "xd" : "dr";
1356  r4 &= ~1; r8 &= ~1;
1357  }
1358  debug("fmov\t%s%i,%s%i\n", n1, r4, n2, r8);
1359  } else if (lo8 == 0x0d)
1360  debug("fsts\tfpul,fr%i\n", r8);
1361  else if (lo8 == 0x1d)
1362  debug("flds\tfr%i,fpul\n", r8);
1363  else if (lo8 == 0x2d)
1364  debug("float\tfpul,%sr%i\n",
1365  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1366  else if (lo8 == 0x3d)
1367  debug("ftrc\t%sr%i,fpul\n",
1368  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1369  else if (lo8 == 0x4d)
1370  debug("fneg\t%sr%i\n",
1371  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1372  else if (lo8 == 0x5d)
1373  debug("fabs\t%sr%i\n",
1374  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1375  else if (lo8 == 0x6d)
1376  debug("fsqrt\t%sr%i\n",
1377  cpu->cd.sh.fpscr & SH_FPSCR_PR? "d" : "f", r8);
1378  else if (lo8 == 0x7d)
1379  debug("fsrra\tfr%i\n", r8);
1380  else if (lo8 == 0x8d)
1381  debug("fldi0\tfr%i\n", r8);
1382  else if (lo8 == 0x9d)
1383  debug("fldi1\tfr%i\n", r8);
1384  else if (lo8 == 0xad)
1385  debug("fcnvsd\tfpul,dr%i\n", r8);
1386  else if (lo8 == 0xbd)
1387  debug("fcnvds\tdr%i,fpul\n", r8);
1388  else if (lo8 == 0xed)
1389  debug("fipr\tfv%i,fv%i\n", (r8 & 3) << 2, r8 & 0xc);
1390  else if ((iword & 0x01ff) == 0x00fd)
1391  debug("fsca\tfpul,dr%i\n", r8);
1392  else if (iword == 0xf3fd)
1393  debug("fschg\n");
1394  else if (iword == 0xfbfd)
1395  debug("frchg\n");
1396  else if ((iword & 0xf3ff) == 0xf1fd)
1397  debug("ftrv\txmtrx,fv%i\n", r8 & 0xc);
1398  else if (lo4 == 0xe)
1399  debug("fmac\tfr0,fr%i,fr%i\n", r4, r8);
1400  else
1401  debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, lo8);
1402  break;
1403  default:debug("UNIMPLEMENTED hi4=0x%x\n", hi4);
1404  }
1405 
1406  return sizeof(iword);
1407 }
1408 
1409 
1410 #include "tmp_sh_tail.cc"
1411 
uint16_t intc_iprd
Definition: cpu_sh.h:146
#define EXPEVT_TLB_MISS_LD
Definition: sh4_exception.h:62
uint32_t r_bank[SH_N_GPRS_BANKED]
Definition: cpu_sh.h:101
void fatal(const char *fmt,...)
Definition: main.cc:152
uint32_t r[SH_N_GPRS]
Definition: cpu_sh.h:100
char * name
Definition: cpu.h:334
void(* interrupt_assert)(struct interrupt *)
Definition: interrupt.h:38
#define SH_N_GPRS_BANKED
Definition: cpu_sh.h:85
#define LE16_TO_HOST(x)
Definition: misc.h:172
int(* translate_v2p)(struct cpu *, uint64_t vaddr, uint64_t *return_paddr, int flags)
Definition: cpu.h:369
#define EXPEVT_FPU_DISABLE
Definition: sh4_exception.h:74
uint32_t expevt
Definition: cpu_sh.h:139
uint32_t vbr
Definition: cpu_sh.h:116
uint32_t spc
Definition: cpu_sh.h:114
#define SH_N_UTLB_ENTRIES
Definition: cpu_sh.h:89
uint32_t sr
Definition: cpu_sh.h:112
#define EXPEVT_RES_INST
Definition: sh4_exception.h:71
uint8_t delay_slot
Definition: cpu.h:356
#define SH_SR_T
Definition: cpu_sh.h:185
uint8_t is_32bit
Definition: cpu.h:350
int sh_memory_rw(struct cpu *cpu, struct memory *mem, uint64_t vaddr, unsigned char *data, size_t len, int writeflag, int cache_flags)
#define EXPEVT_RESET_POWER
Definition: sh4_exception.h:57
#define SH4_PTEH_VPN_MASK
Definition: sh4_mmu.h:46
#define EXPEVT_RESET_MANUAL
Definition: sh4_exception.h:58
#define SH_SR_MD
Definition: cpu_sh.h:194
union cpu::@1 cd
#define SH_SR_FD
Definition: cpu_sh.h:191
#define SH4_INTEVT_SCIF_TXI
uint32_t fpul
Definition: cpu_sh.h:111
struct machine * machine
Definition: cpu.h:328
void interrupt_handler_register(struct interrupt *templ)
Definition: interrupt.cc:81
void sh_update_interrupt_priorities(struct cpu *cpu)
Definition: cpu_sh.cc:249
void(* interrupt_deassert)(struct interrupt *)
Definition: interrupt.h:39
struct pci_data * pcic_pcibus
Definition: cpu_sh.h:171
#define instr(n)
#define SH_CPU_TYPE_DEFS
Definition: cpu_sh.h:61
char is_halted
Definition: cpu.h:397
uint32_t macl
Definition: cpu_sh.h:108
int16_t int_to_assert
Definition: cpu_sh.h:157
uint32_t intc_intpri00
Definition: cpu_sh.h:147
#define EXPEVT_TLB_MOD
Definition: sh4_exception.h:64
void sh_update_fpscr(struct cpu *cpu, uint32_t new_fpscr)
Definition: cpu_sh.cc:607
void sh_exception(struct cpu *cpu, int expevt, int intevt, uint32_t vaddr)
Definition: cpu_sh.cc:632
int(* run_instr)(struct cpu *cpu)
Definition: cpu.h:364
uint32_t tra
Definition: cpu_sh.h:138
void sh_cpu_dumpinfo(struct cpu *cpu)
Definition: cpu_sh.cc:383
#define SH4_INTEVT_SCIF_ERI
char * get_symbol_name(struct symbol_context *, uint64_t addr, uint64_t *offset)
Definition: symbol.cc:188
void * device_add(struct machine *machine, const char *name_and_params)
Definition: device.cc:252
struct cpu ** cpus
Definition: machine.h:140
uint32_t fpscr
Definition: cpu_sh.h:110
uint32_t intc_intpri0c
Definition: cpu_sh.h:150
int physical_ram_in_mb
Definition: machine.h:147
uint32_t intc_intmsk04
Definition: cpu_sh.h:154
void sh_cpu_interrupt_assert(struct interrupt *interrupt)
Definition: cpu_sh.cc:304
void sh_pc_to_pointers(struct cpu *)
void sh_cpu_list_available_types(void)
Definition: cpu_sh.cc:364
#define SH_FPSCR_PR
Definition: cpu_sh.h:217
int ncpus
Definition: machine.h:139
unsigned int int_level
Definition: cpu_sh.h:158
#define EMUL_LITTLE_ENDIAN
Definition: misc.h:164
const char * name
Definition: cpu_sh.h:54
uint64_t pc
Definition: cpu.h:383
void sh_cpu_interrupt_deassert(struct interrupt *interrupt)
Definition: cpu_sh.cc:331
#define SH_SR_Q
Definition: cpu_sh.h:189
uint32_t dbr
Definition: cpu_sh.h:118
uint32_t fr[SH_N_FPRS]
Definition: cpu_sh.h:104
#define SH_SR_S
Definition: cpu_sh.h:186
#define SH_N_ITLB_ENTRIES
Definition: cpu_sh.h:88
uint32_t itlb_lo[SH_N_ITLB_ENTRIES]
Definition: cpu_sh.h:133
void sh_update_translation_table(struct cpu *cpu, uint64_t vaddr_page, unsigned char *host_page, int writeflag, uint64_t paddr_page)
#define SH_FPSCR_SZ
Definition: cpu_sh.h:218
int sh_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib)
Definition: cpu_sh.cc:395
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 SH_INT_PRIO_MASK
Definition: cpu_sh.h:224
#define SH_INTEVT_TMU0_TUNI0
Definition: sh4_exception.h:88
char * path
Definition: cpu.h:337
uint32_t xf[SH_N_FPRS]
Definition: cpu_sh.h:105
uint32_t intevt
Definition: cpu_sh.h:140
uint32_t utlb_hi[SH_N_UTLB_ENTRIES]
Definition: cpu_sh.h:134
#define BE16_TO_HOST(x)
Definition: misc.h:173
#define SH_INTEVT_TMU2_TUNI2
Definition: sh4_exception.h:90
uint32_t pr
Definition: cpu_sh.h:109
uint32_t pteh
Definition: cpu_sh.h:126
uint8_t running
Definition: cpu.h:353
uint32_t intc_intpri08
Definition: cpu_sh.h:149
#define SH_SR_IMASK_SHIFT
Definition: cpu_sh.h:188
void sh_invalidate_code_translation(struct cpu *cpu, uint64_t, int)
struct sh_cpu_type_def cpu_type
Definition: cpu_sh.h:97
uint32_t ssr
Definition: cpu_sh.h:113
#define SH_SR_IMASK
Definition: cpu_sh.h:187
#define SH_SR_RB
Definition: cpu_sh.h:193
uint16_t intc_ipra
Definition: cpu_sh.h:143
#define SH_INTEVT_NMI
Definition: sh4_exception.h:86
uint32_t addr
#define SH_SR_BL
Definition: cpu_sh.h:192
#define CPU_SETTINGS_ADD_REGISTER32(name, var)
Definition: cpu.h:490
#define SH_N_GPRS
Definition: cpu_sh.h:84
#define debug
Definition: dev_adb.cc:57
#define EXPEVT_TLB_MISS_ST
Definition: sh4_exception.h:63
int cpu_id
Definition: cpu.h:359
int quiet_mode
Definition: emul.cc:68
int sh_translate_v2p(struct cpu *cpu, uint64_t vaddr64, uint64_t *return_paddr, int flags)
Definition: memory_sh.cc:248
uint32_t intc_intpri04
Definition: cpu_sh.h:148
uint32_t line
Definition: interrupt.h:51
Definition: cpu.h:326
#define SH_SR_M
Definition: cpu_sh.h:190
int(* instruction_has_delayslot)(struct cpu *cpu, unsigned char *ib)
Definition: cpu.h:379
char * name
Definition: interrupt.h:66
void COMBINE() strlen(struct cpu *cpu, struct arm_instr_call *ic, int low_addr)
#define SH_N_FPRS
Definition: cpu_sh.h:86
#define EXPEVT_TLB_PROT_LD
Definition: sh4_exception.h:65
void sh_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
Definition: cpu_sh.cc:454
#define SH4_INTEVT_IRQ14
struct symbol_context symbol_context
Definition: machine.h:144
int sh_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr, int running, uint64_t dumpaddr)
Definition: cpu_sh.cc:775
void sh_update_sr(struct cpu *cpu, uint32_t new_sr)
Definition: cpu_sh.cc:585
#define SH4_INTEVT_IRQ0
int sh_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine, int cpu_id, char *cpu_type_name)
Definition: cpu_sh.cc:77
uint32_t itlb_hi[SH_N_ITLB_ENTRIES]
Definition: cpu_sh.h:132
uint8_t byte_order
Definition: cpu.h:347
uint32_t tea
Definition: cpu_sh.h:130
#define EXCEPTION_IN_DELAY_SLOT
Definition: cpu.h:308
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 sh3_cpu_interrupt_assert(struct interrupt *interrupt)
Definition: cpu_sh.cc:291
Definition: memory.h:75
addr & if(addr >=0x24 &&page !=NULL)
int sh_run_instr(struct cpu *cpu)
uint8_t int_prio_and_pending[0x1000/0x20]
Definition: cpu_sh.h:156
Definition: symbol.h:37
uint32_t gbr
Definition: cpu_sh.h:115
void * extra
Definition: interrupt.h:59
uint32_t sgr
Definition: cpu_sh.h:117
void(* invalidate_code_translation)(struct cpu *, uint64_t paddr, int flags)
Definition: cpu.h:376
void sh_invalidate_translation_caches(struct cpu *cpu, uint64_t, int)
uint32_t mach
Definition: cpu_sh.h:107
void sh3_cpu_interrupt_deassert(struct interrupt *interrupt)
Definition: cpu_sh.cc:295
#define CPU_SETTINGS_ADD_REGISTER64(name, var)
Definition: cpu.h:486
#define EXPEVT_TRAPA
Definition: sh4_exception.h:70
#define SH_INVALID_INSTR
Definition: cpu_sh.h:93
uint32_t utlb_lo[SH_N_UTLB_ENTRIES]
Definition: cpu_sh.h:135
#define SH_FPSCR_FR
Definition: cpu_sh.h:219
uint32_t intc_intmsk00
Definition: cpu_sh.h:153
struct sh_cpu sh
Definition: cpu.h:445
#define SH_INTEVT_TMU1_TUNI1
Definition: sh4_exception.h:89
void sh_cpu_tlbdump(struct machine *m, int x, int rawflag)
Definition: cpu_sh.cc:556
void(* invalidate_translation_caches)(struct cpu *, uint64_t paddr, int flags)
Definition: cpu.h:374
#define SH_INT_ASSERTED
Definition: cpu_sh.h:223
#define EMUL_BIG_ENDIAN
Definition: misc.h:165
#define EXPEVT_TLB_PROT_ST
Definition: sh4_exception.h:66

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