/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (hide 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 dpavlin 14 /*
2 dpavlin 34 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 dpavlin 14 *
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 dpavlin 42 * $Id: cpu_sh.c,v 1.75 2007/06/07 15:36:24 debug Exp $
29 dpavlin 14 *
30     * Hitachi SuperH ("SH") CPU emulation.
31     *
32 dpavlin 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 dpavlin 42 *
35     * TODO: This actually only works or SH4 so far, not SH3.
36 dpavlin 14 */
37    
38     #include <stdio.h>
39     #include <stdlib.h>
40     #include <string.h>
41     #include <ctype.h>
42 dpavlin 32 #include <unistd.h>
43 dpavlin 14
44     #include "cpu.h"
45 dpavlin 32 #include "device.h"
46     #include "float_emul.h"
47 dpavlin 34 #include "interrupt.h"
48 dpavlin 14 #include "machine.h"
49     #include "memory.h"
50     #include "misc.h"
51 dpavlin 32 #include "settings.h"
52 dpavlin 14 #include "symbol.h"
53 dpavlin 42 #include "timer.h"
54 dpavlin 14
55 dpavlin 32 #include "sh4_exception.h"
56     #include "sh4_mmu.h"
57 dpavlin 14
58 dpavlin 32
59     #define DYNTRANS_32
60     #define DYNTRANS_DELAYSLOT
61 dpavlin 14 #include "tmp_sh_head.c"
62    
63    
64 dpavlin 32 extern int quiet_mode;
65 dpavlin 42 extern int native_code_translation_enabled;
66 dpavlin 32
67     void sh_pc_to_pointers(struct cpu *);
68    
69 dpavlin 42 void sh3_cpu_interrupt_assert(struct interrupt *interrupt);
70     void sh3_cpu_interrupt_deassert(struct interrupt *interrupt);
71 dpavlin 32
72 dpavlin 42
73 dpavlin 14 /*
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 dpavlin 30 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 dpavlin 14 return 0;
96    
97     cpu->memory_rw = sh_memory_rw;
98    
99 dpavlin 30 cpu->cd.sh.cpu_type = cpu_type_defs[i];
100 dpavlin 14 cpu->byte_order = EMUL_LITTLE_ENDIAN;
101 dpavlin 30 cpu->is_32bit = cpu->cd.sh.cpu_type.bits == 32;
102 dpavlin 14
103 dpavlin 32 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 dpavlin 30 cpu->translate_v2p = sh_translate_v2p;
111    
112 dpavlin 32 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 dpavlin 14
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 dpavlin 30 /* Initial value of FPSCR (according to the SH4 manual): */
125     cpu->cd.sh.fpscr = 0x00040001;
126    
127 dpavlin 32 /* (Initial value of the program counter on reboot is 0xA0000000.) */
128    
129 dpavlin 30 /* Start in Privileged Mode: */
130 dpavlin 32 cpu->cd.sh.sr = SH_SR_MD | SH_SR_IMASK;
131 dpavlin 30
132 dpavlin 32 /* 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 dpavlin 34 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 dpavlin 32 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 dpavlin 34 /* Register the CPU's interrupts: */
180 dpavlin 42 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 dpavlin 34 struct interrupt template;
196     memset(&template, 0, sizeof(template));
197     template.line = i;
198 dpavlin 42 template.name = cpu->path;
199 dpavlin 34 template.extra = cpu;
200 dpavlin 42 template.interrupt_assert = sh3_cpu_interrupt_assert;
201     template.interrupt_deassert = sh3_cpu_interrupt_deassert;
202 dpavlin 34 interrupt_handler_register(&template);
203     }
204    
205 dpavlin 32 /* SH4-specific memory mapped registers, TLBs, caches, etc: */
206 dpavlin 38 if (cpu->cd.sh.cpu_type.arch == 4) {
207 dpavlin 40 cpu->cd.sh.pcic_pcibus = device_add(machine, "sh4");
208 dpavlin 32
209 dpavlin 38 /*
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 dpavlin 42 if (native_code_translation_enabled)
228     cpu->sampling_timer = timer_add(CPU_SAMPLE_TIMER_HZ,
229     sh_timer_sample_tick, cpu);
230    
231 dpavlin 14 return 1;
232     }
233    
234    
235     /*
236 dpavlin 38 * 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 dpavlin 34 */
255 dpavlin 38 void sh_update_interrupt_priorities(struct cpu *cpu)
256 dpavlin 34 {
257 dpavlin 38 int i;
258 dpavlin 34
259     /*
260 dpavlin 38 * Set priorities of known interrupts, without affecting the
261     * SH_INT_ASSERTED bit:
262 dpavlin 34 */
263    
264 dpavlin 38 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 dpavlin 34
270 dpavlin 38 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 dpavlin 34
275 dpavlin 38 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 dpavlin 34
280 dpavlin 38 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 dpavlin 34 }
291    
292    
293     /*
294 dpavlin 42 * 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 dpavlin 38 * sh_cpu_interrupt_assert():
309 dpavlin 34 */
310 dpavlin 38 void sh_cpu_interrupt_assert(struct interrupt *interrupt)
311 dpavlin 34 {
312     struct cpu *cpu = interrupt->extra;
313 dpavlin 40 unsigned int irq_nr = interrupt->line;
314     unsigned int index = irq_nr / 0x20;
315     unsigned int prio;
316 dpavlin 34
317 dpavlin 38 /* 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 dpavlin 34
321 dpavlin 38 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 dpavlin 34
327 dpavlin 38 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 dpavlin 34
333    
334 dpavlin 38 /*
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 dpavlin 34
343 dpavlin 38 /* 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 dpavlin 34
347 dpavlin 38 /* 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 dpavlin 34 }
360     }
361     }
362     }
363    
364    
365     /*
366 dpavlin 14 * 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 dpavlin 30 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 dpavlin 14 }
384    
385    
386     /*
387     * sh_cpu_dumpinfo():
388     */
389     void sh_cpu_dumpinfo(struct cpu *cpu)
390     {
391 dpavlin 32 debug(" (%s-endian)\n",
392     cpu->byte_order == EMUL_BIG_ENDIAN? "Big" : "Little");
393 dpavlin 14 }
394    
395    
396     /*
397 dpavlin 32 * 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 dpavlin 14 * 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 dpavlin 22 uint64_t offset;
462 dpavlin 42 int i, x = cpu->cpu_id;
463 dpavlin 14
464     if (gprs) {
465     /* Special registers (pc, ...) first: */
466     symbol = get_symbol_name(&cpu->machine->symbol_context,
467     cpu->pc, &offset);
468    
469 dpavlin 32 debug("cpu%i: pc = 0x%08"PRIx32, x, (uint32_t)cpu->pc);
470 dpavlin 14 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
471    
472 dpavlin 32 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 dpavlin 30 (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 dpavlin 32 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 dpavlin 42 for (i=0; i<SH_N_GPRS; i++) {
494 dpavlin 32 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 dpavlin 14 }
500     }
501    
502 dpavlin 32 if (coprocs & 1) {
503     /* Floating point: */
504 dpavlin 40 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 dpavlin 14
511 dpavlin 32 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 dpavlin 14
519 dpavlin 32 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 dpavlin 14
528 dpavlin 32 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 dpavlin 14
538 dpavlin 32 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 dpavlin 30 }
546 dpavlin 14 }
547     }
548    
549    
550     /*
551 dpavlin 24 * 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 dpavlin 32 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 dpavlin 24 }
581    
582    
583     /*
584 dpavlin 30 * sh_update_sr():
585 dpavlin 32 *
586     * Writes a new value to the status register.
587 dpavlin 30 */
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 dpavlin 32 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 dpavlin 30 }
600    
601     cpu->cd.sh.sr = new_sr;
602     }
603    
604    
605     /*
606 dpavlin 32 * 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 dpavlin 38 *
633     * vaddr contains the faulting address, on TLB exceptions.
634 dpavlin 32 */
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 dpavlin 38 debug(", pc=0x%08"PRIx32" ", (uint32_t)cpu->pc);
646 dpavlin 32 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 dpavlin 38 fatal("[ sh_exception(): BL bit already set. ]\n");
654 dpavlin 32
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 dpavlin 38
679     /*
680     * Stuff common to all exceptions:
681     */
682    
683 dpavlin 32 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 dpavlin 38
687 dpavlin 32 if (intevt > 0) {
688     cpu->cd.sh.intevt = intevt;
689     expevt = -1;
690 dpavlin 38 } else {
691 dpavlin 32 cpu->cd.sh.expevt = expevt;
692 dpavlin 38 }
693    
694 dpavlin 32 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 dpavlin 38
700 dpavlin 32 /* 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 dpavlin 38 /*
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 dpavlin 32 cpu->cd.sh.spc += sizeof(uint16_t);
734     break;
735    
736 dpavlin 34 case EXPEVT_RES_INST:
737 dpavlin 36 /*
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 dpavlin 34 break;
748     #endif
749    
750     case EXPEVT_FPU_DISABLE:
751     break;
752    
753 dpavlin 32 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 dpavlin 42 * sh_cpu_disassemble_instr():
764 dpavlin 14 *
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 dpavlin 42 *
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 dpavlin 14 */
778 dpavlin 42 int sh_cpu_disassemble_instr(struct cpu *cpu, unsigned char *instr,
779 dpavlin 24 int running, uint64_t dumpaddr)
780 dpavlin 14 {
781 dpavlin 40 char *symbol;
782     uint64_t offset, addr;
783 dpavlin 14 uint16_t iword;
784     int hi4, lo4, lo8, r8, r4;
785    
786 dpavlin 42 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 dpavlin 14 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 dpavlin 32 debug(": %04x %s\t", iword, cpu->delay_slot? "(d)" : "");
805 dpavlin 14 hi4 = iword >> 12; lo4 = iword & 15; lo8 = iword & 255;
806     r8 = (iword >> 8) & 15; r4 = (iword >> 4) & 15;
807    
808 dpavlin 42
809 dpavlin 14 /*
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 dpavlin 34 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 dpavlin 40 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 dpavlin 34 }
838     debug("\n");
839     } else if (lo4 == 0x7)
840 dpavlin 14 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 dpavlin 34 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 dpavlin 40 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 dpavlin 34 }
868     debug("\n");
869     } else if (lo8 == 0x12)
870 dpavlin 14 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 dpavlin 32 else if (iword == 0x001b)
878     debug("sleep\n");
879     else if (lo8 == 0x22)
880     debug("stc\tvbr,r%i\n", r8);
881 dpavlin 14 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 dpavlin 32 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 dpavlin 14 else if (iword == 0x003b)
896     debug("brk\n");
897 dpavlin 32 else if (lo8 == 0x42)
898     debug("stc\tspc,r%i\n", r8);
899 dpavlin 14 else if (iword == 0x0048)
900     debug("clrs\n");
901     else if (iword == 0x0058)
902     debug("sets\n");
903 dpavlin 32 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 dpavlin 14 else if (lo8 == 0x83)
910     debug("pref\t@r%i\n", r8);
911 dpavlin 32 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 dpavlin 34 else if (iword == SH_INVALID_INSTR)
922 dpavlin 32 debug("gxemul_dreamcast_prom_emul\n");
923 dpavlin 14 else
924     debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
925     break;
926     case 0x1:
927 dpavlin 34 debug("mov.l\tr%i,@(%i,r%i)", r4, lo4 * 4, r8);
928     if (running) {
929 dpavlin 40 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 dpavlin 34 }
938     debug("\n");
939 dpavlin 14 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 dpavlin 32 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 dpavlin 14 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 dpavlin 32 else if (lo8 == 0x07)
1022     debug("ldc.l\t@r%i+,sr\n", r8);
1023 dpavlin 14 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 dpavlin 32 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 dpavlin 14 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 dpavlin 32 else if (lo8 == 0x17)
1050     debug("ldc.l\t@r%i+,gbr\n", r8);
1051 dpavlin 14 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 dpavlin 32 else if (lo8 == 0x23)
1068     debug("stc.l\tvbr,@-r%i\n", r8);
1069 dpavlin 14 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 dpavlin 32 else if (lo8 == 0x27)
1076     debug("ldc.l\t@r%i+,vbr\n", r8);
1077 dpavlin 14 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 dpavlin 40 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 dpavlin 32 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 dpavlin 14 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 dpavlin 32 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 dpavlin 14 else if (lo8 == 0x6a)
1118     debug("lds\tr%i,fpscr\n", r8);
1119 dpavlin 32 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 dpavlin 14 else
1128     debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
1129     break;
1130     case 0x5:
1131 dpavlin 34 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 dpavlin 14 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 dpavlin 32 else if (lo4 == 0x5)
1150     debug("mov.w\t@r%i+,r%i\n", r4, r8);
1151 dpavlin 14 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 dpavlin 34 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 dpavlin 32 } else if (r8 == 0x8) {
1199 dpavlin 14 debug("cmp/eq\t#%i,r0\n", (int8_t)lo8);
1200 dpavlin 32 } else if (r8 == 0x9 || r8 == 0xb || r8 == 0xd || r8 == 0xf) {
1201 dpavlin 14 addr = (int8_t)lo8;
1202     addr = dumpaddr + 4 + (addr << 1);
1203 dpavlin 40 debug("b%s%s\t0x%x",
1204 dpavlin 14 (r8 == 0x9 || r8 == 0xd)? "t" : "f",
1205     (r8 == 0x9 || r8 == 0xb)? "" : "/s", (int)addr);
1206 dpavlin 40 symbol = get_symbol_name(&cpu->machine->symbol_context,
1207     addr, &offset);
1208     if (symbol != NULL)
1209     debug("\t; <%s>", symbol);
1210     debug("\n");
1211 dpavlin 14 } else
1212     debug("UNIMPLEMENTED hi4=0x%x,0x%x\n", hi4, r8);
1213     break;
1214     case 0x9:
1215     case 0xd:
1216 dpavlin 30 addr = lo8 * (hi4==9? 2 : 4);
1217 dpavlin 14 addr += (dumpaddr & ~(hi4==9? 1 : 3)) + 4;
1218 dpavlin 40 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 dpavlin 14 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 dpavlin 40 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 dpavlin 14 break;
1238     case 0xc:
1239 dpavlin 32 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 dpavlin 14 debug("trapa\t#%i\n", (uint8_t)lo8);
1247 dpavlin 32 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 dpavlin 14 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 dpavlin 32 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 dpavlin 40 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 dpavlin 32 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 dpavlin 14 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