/[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 34 - (hide annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 36100 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1480 2007/02/19 01:34:42 debug Exp $
20061029	Changing usleep(1) calls in the debugger to usleep(10000)
20061107	Adding a new disk image option (-d o...) which sets the ISO9660
		filesystem base offset; also making some other hacks to allow
		NetBSD/dreamcast and homebrew demos/games to boot directly
		from a filesystem image.
		Moving Dreamcast-specific stuff in the documentation to its
		own page (dreamcast.html).
		Adding a border to the Dreamcast PVR framebuffer.
20061108	Adding a -T command line option (again?), for halting the
		emulator on unimplemented memory accesses.
20061109	Continuing on various SH4 and Dreamcast related things.
		The emulator should now halt on more unimplemented device
		accesses, instead of just printing a warning, forcing me to
		actually implement missing stuff :)
20061111	Continuing on SH4 and Dreamcast stuff.
		Adding a bogus Landisk (SH4) machine mode.
20061112	Implementing some parts of the Dreamcast GDROM device. With
		some ugly hacks, NetBSD can (barely) mount an ISO image.
20061113	NetBSD/dreamcast now starts booting from the Live CD image,
		but crashes randomly quite early on in the boot process.
20061122	Beginning on a skeleton interrupt.h and interrupt.c for the
		new interrupt subsystem.
20061124	Continuing on the new interrupt system; taking the first steps
		to attempt to connect CPUs (SuperH and MIPS) and devices
		(dev_cons and SH4 timer interrupts) to it. Many things will
		probably break from now on.
20061125	Converting dev_ns16550, dev_8253 to the new interrupt system.
		Attempting to begin to convert the ISA bus.
20061130	Incorporating a patch from Brian Foley for the configure
		script, which checks for X11 libs in /usr/X11R6/lib64 (which
		is used on some Linux systems).
20061227	Adding a note in the man page about booting from Dreamcast
		CDROM images (i.e. that no external kernel is needed).
20061229	Continuing on the interrupt system rewrite: beginning to
		convert more devices, adding abort() calls for legacy interrupt
		system calls so that everything now _has_ to be rewritten!
		Almost all machine modes are now completely broken.
20061230	More progress on removing old interrupt code, mostly related
		to the ISA bus + devices, the LCA bus (on AlphaBook1), and
		the Footbridge bus (for CATS). And some minor PCI stuff.
		Connecting the ARM cpu to the new interrupt system.
		The CATS, NetWinder, and QEMU_MIPS machine modes now work with
		the new interrupt system :)
20061231	Connecting PowerPC CPUs to the new interrupt system.
		Making PReP machines (IBM 6050) work again.
		Beginning to convert the GT PCI controller (for e.g. Malta
		and Cobalt emulation). Some things work, but not everything.
		Updating Copyright notices for 2007.
20070101	Converting dev_kn02 from legacy style to devinit; the 3max
		machine mode now works with the new interrupt system :-]
20070105	Beginning to convert the SGI O2 machine to the new interrupt
		system; finally converting O2 (IP32) devices to devinit, etc.
20070106	Continuing on the interrupt system redesign/rewrite; KN01
		(PMAX), KN230, and Dreamcast ASIC interrupts should work again,
		moving out stuff from machine.h and devices.h into the
		corresponding devices, beginning the rewrite of i80321
		interrupts, etc.
20070107	Beginning on the rewrite of Eagle interrupt stuff (PReP, etc).
20070117	Beginning the rewrite of Algor (V3) interrupts (finally
		changing dev_v3 into devinit style).
20070118	Removing the "bus" registry concept from machine.h, because
		it was practically meaningless.
		Continuing on the rewrite of Algor V3 ISA interrupts.
20070121	More work on Algor interrupts; they are now working again,
		well enough to run NetBSD/algor. :-)
20070122	Converting VR41xx (HPCmips) interrupts. NetBSD/hpcmips
		can be installed using the new interrupt system :-)
20070123	Making the testmips mode work with the new interrupt system.
20070127	Beginning to convert DEC5800 devices to devinit, and to the
		new interrupt system.
		Converting Playstation 2 devices to devinit, and converting
		the interrupt system. Also fixing a severe bug: the interrupt
		mask register on Playstation 2 is bitwise _toggled_ on writes.
20070128	Removing the dummy NetGear machine mode and the 8250 device
		(which was only used by the NetGear machine).
		Beginning to convert the MacPPC GC (Grand Central) interrupt
		controller to the new interrupt system.
		Converting Jazz interrupts (PICA61 etc.) to the new interrupt
		system. NetBSD/arc can be installed again :-)
		Fixing the JAZZ timer (hardcoding it at 100 Hz, works with
		NetBSD and it is better than a completely dummy timer as it
		was before).
		Converting dev_mp to the new interrupt system, although I
		haven't had time to actually test it yet.
		Completely removing src/machines/interrupts.c, cpu_interrupt
		and cpu_interrupt_ack in src/cpu.c, and
		src/include/machine_interrupts.h! Adding fatal error messages
		+ abort() in the few places that are left to fix.
		Converting dev_z8530 to the new interrupt system.
		FINALLY removing the md_int struct completely from the
		machine struct.
		SH4 fixes (adding a PADDR invalidation in the ITLB replacement
		code in memory_sh.c); the NetBSD/dreamcast LiveCD now runs
		all the way to the login prompt, and can be interacted with :-)
		Converting the CPC700 controller (PCI and interrupt controller
		for PM/PPC) to the new interrupt system.
20070129	Fixing MACE ISA interrupts (SGI IP32 emulation). Both NetBSD/
		sgimips' and OpenBSD/sgi's ramdisk kernels can now be
		interacted with again.
20070130	Moving out the MIPS multi_lw and _sw instruction combinations
		so that they are auto-generated at compile time instead.
20070131	Adding detection of amd64/x86_64 hosts in the configure script,
		for doing initial experiments (again :-) with native code
		generation.
		Adding a -k command line option to set the size of the dyntrans
		cache, and a -B command line option to disable native code
		generation, even if GXemul was compiled with support for
		native code generation for the specific host CPU architecture.
20070201	Experimenting with a skeleton for native code generation.
		Changing the default behaviour, so that native code generation
		is now disabled by default, and has to be enabled by using
		-b on the command line.
20070202	Continuing the native code generation experiments.
		Making PCI interrupts work for Footbridge again.
20070203	More native code generation experiments.
		Removing most of the native code generation experimental code,
		it does not make sense to include any quick hacks like this.
		Minor cleanup/removal of some more legacy MIPS interrupt code.
20070204	Making i80321 interrupts work again (for NetBSD/evbarm etc.),
		and fixing the timer at 100 Hz.
20070206	Experimenting with removing the wdc interrupt slowness hack.
20070207	Lowering the number of dyntrans TLB entries for MIPS from
		192 to 128, resulting in a minor speed improvement.
		Minor optimization to the code invalidation routine in
		cpu_dyntrans.c.
20070208	Increasing (experimentally) the nr of dyntrans instructions per
		loop from 60 to 120.
20070210	Commenting out (experimentally) the dyntrans_device_danger
		detection in memory_rw.c.
		Changing the testmips and baremips machines to use a revision 2
		MIPS64 CPU by default, instead of revision 1.
		Removing the dummy i960, IA64, x86, AVR32, and HP PA-RISC
		files, the PC bios emulation, and the Olivetti M700 (ARC) and
		db64360 emulation modes.
20070211	Adding an "mp" demo to the demos directory, which tests the
		SMP functionality of the testmips machine.
		Fixing PReP interrupts some more. NetBSD/prep now boots again.
20070216	Adding a "nop workaround" for booting Mach/PMAX to the
		documentation; thanks to Artur Bujdoso for the values.
		Converting more of the MacPPC interrupt stuff to the new
		system.
		Beginning to convert BeBox interrupts to the new system.
		PPC603e should NOT have the PPC_NO_DEC flag! Removing it.
		Correcting BeBox clock speed (it was set to 100 in the NetBSD
		bootinfo block, but should be 33000000/4), allowing NetBSD
		to start without using the (incorrect) PPC_NO_DEC hack.
20070217	Implementing (slow) AltiVec vector loads and stores, allowing
		NetBSD/macppc to finally boot using the GENERIC kernel :-)
		Updating the documentation with install instructions for
		NetBSD/macppc.
20070218-19	Regression testing for the release.

==============  RELEASE 0.4.4  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26