/[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 42 - (show annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 39321 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1613 2007/06/15 20:11:26 debug Exp $
20070501	Continuing a little on m88k disassembly (control registers,
		more instructions).
		Adding a dummy mvme88k machine mode.
20070502	Re-adding MIPS load/store alignment exceptions.
20070503	Implementing more of the M88K disassembly code.
20070504	Adding disassembly of some more M88K load/store instructions.
		Implementing some relatively simple M88K instructions (br.n,
		xor[.u] imm, and[.u] imm).
20070505	Implementing M88K three-register and, or, xor, and jmp[.n],
		bsr[.n] including function call trace stuff.
		Applying a patch from Bruce M. Simpson which implements the
		SYSCON_BOARD_CPU_CLOCK_FREQ_ID object of the syscon call in
		the yamon PROM emulation.
20070506	Implementing M88K bb0[.n] and bb1[.n], and skeletons for
		ldcr and stcr (although no control regs are implemented yet).
20070509	Found and fixed the bug which caused Linux for QEMU_MIPS to
		stop working in 0.4.5.1: It was a faulty change to the MIPS
		'sc' and 'scd' instructions I made while going through gcc -W
		warnings on 20070428.
20070510	Updating the Linux/QEMU_MIPS section in guestoses.html to
		use mips-test-0.2.tar.gz instead of 0.1.
		A big thank you to Miod Vallat for sending me M88K manuals.
		Implementing more M88K instructions (addu, subu, div[u], mulu,
		ext[u], clr, set, cmp).
20070511	Fixing bugs in the M88K "and" and "and.u" instructions (found
		by comparing against the manual).
		Implementing more M88K instructions (mask[.u], mak, bcnd (auto-
		generated)) and some more control register details.
		Cleanup: Removing the experimental AVR emulation mode and
		corresponding devices; AVR emulation wasn't really meaningful.
		Implementing autogeneration of most M88K loads/stores. The
		rectangle drawing demo (with -O0) for M88K runs :-)
		Beginning on M88K exception handling.
		More M88K instructions: tb0, tb1, rte, sub, jsr[.n].
		Adding some skeleton MVME PROM ("BUG") emulation.
20070512	Fixing a bug in the M88K cmp instruction.
		Adding the M88K lda (scaled register) instruction.
		Fixing bugs in 64-bit (32-bit pairs) M88K loads/stores.
		Removing the unused tick_hz stuff from the machine struct.
		Implementing the M88K xmem instruction. OpenBSD/mvme88k gets
		far enough to display the Copyright banner :-)
		Implementing subu.co (guess), addu.co, addu.ci, ff0, and ff1.
		Adding a dev_mvme187, for MVME187-specific devices/registers.
		OpenBSD/mvme88k prints more boot messages. :)
20070515	Continuing on MVME187 emulation (adding more devices, beginning
		on the CMMUs, etc).
		Adding the M88K and.c, xor.c, and or.c instructions, and making
		sure that mul, div, etc cause exceptions if executed when SFD1
		is disabled.
20070517	Continuing on M88K and MVME187 emulation in general; moving
		the CMMU registers to the CPU struct, separating dev_pcc2 from
		dev_mvme187, and beginning on memory_m88k.c (BATC and PATC).
		Fixing a bug in 64-bit (32-bit pairs) M88K fast stores.
		Implementing the clock part of dev_mk48txx.
		Implementing the M88K fstcr and xcr instructions.
		Implementing m88k_cpu_tlbdump().
		Beginning on the implementation of a separate address space
		for M88K .usr loads/stores.
20070520	Removing the non-working (skeleton) Sandpoint, SonyNEWS, SHARK
		Dnard, and Zaurus machine modes.
		Experimenting with dyntrans to_be_translated read-ahead. It
		seems to give a very small performance increase for MIPS
		emulation, but a large performance degradation for SuperH. Hm.
20070522	Disabling correct SuperH ITLB emulation; it does not seem to be
		necessary in order to let SH4 guest OSes run, and it slows down
		userspace code.
		Implementing "samepage" branches for SuperH emulation, and some
		other minor speed hacks.
20070525	Continuing on M88K memory-related stuff: exceptions, memory
		transaction register contents, etc.
		Implementing the M88K subu.ci instruction.
		Removing the non-working (skeleton) Iyonix machine mode.
		OpenBSD/mvme88k reaches userland :-), starts executing
		/sbin/init's instructions, and issues a few syscalls, before
		crashing.
20070526	Fixing bugs in dev_mk48txx, so that OpenBSD/mvme88k detects
		the correct time-of-day.
		Implementing a generic IRQ controller for the test machines
		(dev_irqc), similar to a proposed patch from Petr Stepan.
		Experimenting some more with translation read-ahead.
		Adding an "expect" script for automated OpenBSD/landisk
		install regression/performance tests.
20070527	Adding a dummy mmEye (SH3) machine mode skeleton.
		FINALLY found the strange M88K bug I have been hunting: I had
		not emulated the SNIP value for exceptions occurring in
		branch delay slots correctly.
		Implementing correct exceptions for 64-bit M88K loads/stores.
		Address to symbol lookups are now disabled when M88K is
		running in usermode (because usermode addresses don't have
		anything to do with supervisor addresses).
20070531	Removing the mmEye machine mode skeleton.
20070604	Some minor code cleanup.
20070605	Moving src/useremul.c into a subdir (src/useremul/), and
		cleaning up some more legacy constructs.
		Adding -Wstrict-aliasing and -fstrict-aliasing detection to
		the configure script.
20070606	Adding a check for broken GCC on Solaris to the configure
		script. (GCC 3.4.3 on Solaris cannot handle static variables
		which are initialized to 0 or NULL. :-/)
		Removing the old (non-working) ARC emulation modes: NEC RD94,
		R94, R96, and R98, and the last traces of Olivetti M700 and
		Deskstation Tyne.
		Removing the non-working skeleton WDSC device (dev_wdsc).
20070607	Thinking about how to use the host's cc + ld at runtime to
		generate native code. (See experiments/native_cc_ld_test.i
		for an example.)
20070608	Adding a program counter sampling timer, which could be useful
		for native code generation experiments.
		The KN02_CSR_NRMMOD bit in the DECstation 5000/200 (KN02) CSR
		should always be set, to allow a 5000/200 PROM to boot.
20070609	Moving out breakpoint details from the machine struct into
		a helper struct, and removing the limit on max nr of
		breakpoints.
20070610	Moving out tick functions into a helper struct as well (which
		also gets rid of the max limit).
20070612	FINALLY figured out why Debian/DECstation stopped working when
		translation read-ahead was enabled: in src/memory_rw.c, the
		call to invalidate_code_translation was made also if the
		memory access was an instruction load (if the page was mapped
		as writable); it shouldn't be called in that case.
20070613	Implementing some more MIPS32/64 revision 2 instructions: di,
		ei, ext, dext, dextm, dextu, and ins.
20070614	Implementing an instruction combination for the NetBSD/arm
		idle loop (making the host not use any cpu if NetBSD/arm
		inside the emulator is not using any cpu).
		Increasing the nr of ARM VPH entries from 128 to 384.
20070615	Removing the ENABLE_arch stuff from the configure script, so
		that all included architectures are included in both release
		and development builds.
		Moving memory related helper functions from misc.c to memory.c.
		Adding preliminary instructions for netbooting NetBSD/pmppc to
		guestoses.html; it doesn't work yet, there are weird timeouts.
		Beginning a total rewrite of the userland emulation modes
		(removing all emulation modes, beginning from scratch with
		NetBSD/MIPS and FreeBSD/Alpha only).
20070616	After fixing a bug in the DEC21143 NIC (the TDSTAT_OWN bit was
		only cleared for the last segment when transmitting, not all
		segments), NetBSD/pmppc boots with root-on-nfs without the
		timeouts. Updating guestoses.html.
		Removing the skeleton PSP (Playstation Portable) mode.
		Moving X11-related stuff in the machine struct into a helper
		struct.
		Cleanup of out-of-memory checks, to use a new CHECK_ALLOCATION
		macro (which prints a meaningful error message).
		Adding a COMMENT to each machine and device (for automagic
		.index comment generation).
		Doing regression testing for the next release.

==============  RELEASE 0.4.6  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26