/[gxemul]/trunk/src/cpus/cpu_sh.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

Contents of /trunk/src/cpus/cpu_sh.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 40 - (show annotations)
Mon Oct 8 16:22:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 39131 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1539 2007/05/01 04:03:51 debug Exp $
20070415	Landisk PCLOCK should be 33.33 MHz, not 50 MHz. (This makes
		the clock run at correct speed.)
		FINALLY found and fixed the bug which caused OpenBSD/landisk
		to randomly bug out: an &-sign was missing in the special case
		handling of FPSCR in the 'LDS.L @Rm+,FPSCR' instruction.
		Adding similar special case handling for 'LDC.L @Rm+,SR'
		(calling sh_update_sr() instead of just loading).
		Implementing the 'FCNVSD FPUL,DRn' and 'FCNVDS DRm,FPUL'
		SuperH instructions.
		The 'LDC Rm,SR' instruction now immediately breaks out of the
		dyntrans loop if an interrupt is to be triggered.
20070416	In memory_rw.c, if mapping a page as writable, make sure to
		invalidate code translations even if the data access was a
		read.
		Minor SuperH updates.
20070418	Removing the dummy M68K emulation mode.
		Minor SH update (turning unnecessary sts_mach_rn, sts_macl_rn,
		and sts_pr_rn instruction handlers into mov_rm_rn).
20070419	Beginning to add a skeleton for an M88K mode: Adding a hack to
		allow OpenBSD/m88k a.out binaries to be loaded, and disassembly
		of a few simple 88K instructions.
		Commenting out the 'LDC Rm,SR' fix from a few days ago, because
		it made Linux/dreamcast bug out.
		Adding a hack to dev_sh4.c (an extra translation cache
		invalidation), which allows OpenBSD/landisk to boot ok after
		an install. Upgrading the Landisk machine mode to stable,
		updating documentation, etc.
20070420	Experimenting with adding a PCI controller (pcic) to dev_sh4.
		Adding a dummy Realtek 8139C+ skeleton device (dev_rtl8139c).
		Implementing the first M88K instructions (br, or[.u] imm), and
		adding disassembly of some more instructions.
20070421	Continuing a little on dev_rtl8139c.
20070422	Implementing the 9346 EEPROM "read" command for dev_rtl8139c.
		Finally found and fixed an old bug in the log n symbol search
		(it sometimes missed symbols). Debug trace (-i, -t etc) should
		now show more symbols. :-)
20070423	Continuing a little on M88K disassembly.
20070428	Fixing a memset arg order bug in src/net/net.c (thanks to
		Nigel Horne for noticing the bug).
		Applying parts of a patch from Carl van Schaik to clear out
		bottom bits of MIPS addresses more correctly, when using large
		page sizes, and doing some other minor cleanup/refactoring.
		Fixing a couple of warnings given by gcc with the -W option (a
		few more warnings than just plain -Wall).
		Reducing SuperH dyntrans physical address space from 64-bit to
		32-bit (since SH5/SH64 isn't imlemented yet anyway).
		Adding address-to-symbol annotation to a few more instructions
		in the SuperH instruction trace output.
		Beginning regression testing for the next release.
		Reverting the value of SCIF_DELAYED_TX_VALUE from 1 to 2,
		because OpenBSD/landisk may otherwise hang randomly.
20070429	The ugly hack/workaround to get OpenBSD/landisk booting without
		crashing does NOT work anymore (with the April 21 snapshot
		of OpenBSD/landisk). Strangely enough, removing the hack
		completely causes OpenBSD/landisk to work (!).
		More regression testing (re-testing everything SuperH-related,
		and some other things).
		Cobalt interrupts were actually broken; fixing by commenting
		out the DEC21143s in the Cobalt machine.
20070430	More regression testing.
20070501	Updating the OpenBSD/landisk install instructions to use
		4.1 instead of the current snapshot.
		GAAAH! OpenBSD/landisk 4.1 _needs_ the ugly hack/workaround;
		reintroducing it again. (The 4.1 kernel is actually from
		2007-03-11.)
		Simplifying the NetBSD/evbarm install instructions a bit.
		More regression testing.

==============  RELEASE 0.4.5.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26