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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (show 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 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_sh.c,v 1.60 2007/01/05 17:42:23 debug Exp $
29 *
30 * Hitachi SuperH ("SH") CPU emulation.
31 *
32 * TODO: It would be nice if this could encompass both 64-bit SH5, and
33 * 32-bit SH encodings. Right now, it only really supports 32-bit mode.
34 */
35
36 #include <stdio.h>
37 #include <stdlib.h>
38 #include <string.h>
39 #include <ctype.h>
40 #include <unistd.h>
41
42 #include "cpu.h"
43 #include "device.h"
44 #include "float_emul.h"
45 #include "interrupt.h"
46 #include "machine.h"
47 #include "memory.h"
48 #include "misc.h"
49 #include "settings.h"
50 #include "symbol.h"
51
52 #include "sh4_exception.h"
53 #include "sh4_mmu.h"
54
55
56 #define DYNTRANS_32
57 #define DYNTRANS_DELAYSLOT
58 #include "tmp_sh_head.c"
59
60
61 extern int quiet_mode;
62
63 void sh_pc_to_pointers(struct cpu *);
64
65
66 /*
67 * sh_cpu_new():
68 *
69 * Create a new SH cpu object.
70 *
71 * Returns 1 on success, 0 if there was no matching SH processor with
72 * this cpu_type_name.
73 */
74 int sh_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
75 int cpu_id, char *cpu_type_name)
76 {
77 int i = 0;
78 struct sh_cpu_type_def cpu_type_defs[] = SH_CPU_TYPE_DEFS;
79
80 /* Scan the cpu_type_defs list for this cpu type: */
81 while (cpu_type_defs[i].name != NULL) {
82 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
83 break;
84 }
85 i++;
86 }
87 if (cpu_type_defs[i].name == NULL)
88 return 0;
89
90 cpu->memory_rw = sh_memory_rw;
91
92 cpu->cd.sh.cpu_type = cpu_type_defs[i];
93 cpu->byte_order = EMUL_LITTLE_ENDIAN;
94 cpu->is_32bit = cpu->cd.sh.cpu_type.bits == 32;
95 cpu->cd.sh.compact = 1; /* Default to 16-bit opcode mode */
96
97 if (!cpu->is_32bit) {
98 fatal("SH64 emulation not implemented. Sorry.\n");
99 exit(1);
100 }
101
102 cpu->instruction_has_delayslot = sh_cpu_instruction_has_delayslot;
103
104 cpu->translate_v2p = sh_translate_v2p;
105
106 cpu->run_instr = sh_run_instr;
107 cpu->update_translation_table = sh_update_translation_table;
108 cpu->invalidate_translation_caches =
109 sh_invalidate_translation_caches;
110 cpu->invalidate_code_translation =
111 sh_invalidate_code_translation;
112
113 /* Only show name and caches etc for CPU nr 0 (in SMP machines): */
114 if (cpu_id == 0) {
115 debug("%s", cpu->name);
116 }
117
118 /* Initial value of FPSCR (according to the SH4 manual): */
119 cpu->cd.sh.fpscr = 0x00040001;
120
121 /* (Initial value of the program counter on reboot is 0xA0000000.) */
122
123 /* Start in Privileged Mode: */
124 cpu->cd.sh.sr = SH_SR_MD | SH_SR_IMASK;
125
126 /* Stack pointer at end of physical RAM: */
127 cpu->cd.sh.r[15] = cpu->machine->physical_ram_in_mb * 1048576 - 64;
128
129 CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
130 CPU_SETTINGS_ADD_REGISTER32("sr", cpu->cd.sh.sr);
131 CPU_SETTINGS_ADD_REGISTER32("pr", cpu->cd.sh.pr);
132 CPU_SETTINGS_ADD_REGISTER32("vbr", cpu->cd.sh.vbr);
133 CPU_SETTINGS_ADD_REGISTER32("gbr", cpu->cd.sh.gbr);
134 CPU_SETTINGS_ADD_REGISTER32("macl", cpu->cd.sh.macl);
135 CPU_SETTINGS_ADD_REGISTER32("mach", cpu->cd.sh.mach);
136 CPU_SETTINGS_ADD_REGISTER32("expevt", cpu->cd.sh.expevt);
137 CPU_SETTINGS_ADD_REGISTER32("intevt", cpu->cd.sh.intevt);
138 CPU_SETTINGS_ADD_REGISTER32("tra", cpu->cd.sh.tra);
139 CPU_SETTINGS_ADD_REGISTER32("fpscr", cpu->cd.sh.fpscr);
140 CPU_SETTINGS_ADD_REGISTER32("fpul", cpu->cd.sh.fpul);
141 for (i=0; i<SH_N_GPRS; i++) {
142 char tmpstr[5];
143 snprintf(tmpstr, sizeof(tmpstr), "r%i", i);
144 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.r[i]);
145 }
146 for (i=0; i<SH_N_GPRS_BANKED; i++) {
147 char tmpstr[15];
148 snprintf(tmpstr, sizeof(tmpstr), "r%i_bank", i);
149 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.r_bank[i]);
150 }
151 for (i=0; i<SH_N_FPRS; i++) {
152 char tmpstr[6];
153 snprintf(tmpstr, sizeof(tmpstr), "fr%i", i);
154 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.fr[i]);
155 snprintf(tmpstr, sizeof(tmpstr), "xf%i", i);
156 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.xf[i]);
157 }
158 for (i=0; i<SH_N_ITLB_ENTRIES; i++) {
159 char tmpstr[15];
160 snprintf(tmpstr, sizeof(tmpstr), "itlb_hi_%i", i);
161 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.itlb_hi[i]);
162 snprintf(tmpstr, sizeof(tmpstr), "itlb_lo_%i", i);
163 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.itlb_lo[i]);
164 }
165 for (i=0; i<SH_N_UTLB_ENTRIES; i++) {
166 char tmpstr[15];
167 snprintf(tmpstr, sizeof(tmpstr), "utlb_hi_%i", i);
168 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.utlb_hi[i]);
169 snprintf(tmpstr, sizeof(tmpstr), "utlb_lo_%i", i);
170 CPU_SETTINGS_ADD_REGISTER32(tmpstr, cpu->cd.sh.utlb_lo[i]);
171 }
172
173 /* Register the CPU's interrupts: */
174 for (i=SH_INTEVT_NMI; i<0x1000; i+=0x20) {
175 struct interrupt template;
176 char name[100];
177 snprintf(name, sizeof(name), "%s.irq[0x%x]", cpu->path, i);
178 memset(&template, 0, sizeof(template));
179 template.line = i;
180 template.name = name;
181 template.extra = cpu;
182 template.interrupt_assert = sh_cpu_interrupt_assert;
183 template.interrupt_deassert = sh_cpu_interrupt_deassert;
184 interrupt_handler_register(&template);
185 }
186
187 /* SH4-specific memory mapped registers, TLBs, caches, etc: */
188 if (cpu->cd.sh.cpu_type.arch == 4)
189 device_add(machine, "sh4");
190
191 return 1;
192 }
193
194
195 /*
196 * 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 * 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 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 }
315
316
317 /*
318 * sh_cpu_dumpinfo():
319 */
320 void sh_cpu_dumpinfo(struct cpu *cpu)
321 {
322 debug(" (%s-endian)\n",
323 cpu->byte_order == EMUL_BIG_ENDIAN? "Big" : "Little");
324 }
325
326
327 /*
328 * 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 * 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 uint64_t offset;
393 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 debug("cpu%i: pc = 0x%08"PRIx32, x, (uint32_t)cpu->pc);
401 debug(" <%s>\n", symbol != NULL? symbol : " no symbol ");
402
403 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 (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 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 }
431 }
432
433 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
438 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
446 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
455 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
465 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 }
473 }
474 }
475
476
477 /*
478 * 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 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 }
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 * sh_update_sr():
525 *
526 * Writes a new value to the status register.
527 */
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 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 }
540
541 cpu->cd.sh.sr = new_sr;
542 }
543
544
545 /*
546 * 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 #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 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 * 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 int running, uint64_t dumpaddr)
691 {
692 uint64_t addr;
693 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 debug(": %04x %s\t", iword, cpu->delay_slot? "(d)" : "");
702 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 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 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 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 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 else if (iword == 0x001b)
758 debug("sleep\n");
759 else if (lo8 == 0x22)
760 debug("stc\tvbr,r%i\n", r8);
761 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 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 else if (iword == 0x003b)
776 debug("brk\n");
777 else if (lo8 == 0x42)
778 debug("stc\tspc,r%i\n", r8);
779 else if (iword == 0x0048)
780 debug("clrs\n");
781 else if (iword == 0x0058)
782 debug("sets\n");
783 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 else if (lo8 == 0x83)
790 debug("pref\t@r%i\n", r8);
791 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 else if (iword == SH_INVALID_INSTR)
802 debug("gxemul_dreamcast_prom_emul\n");
803 else
804 debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
805 break;
806 case 0x1:
807 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 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 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 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 else if (lo8 == 0x07)
896 debug("ldc.l\t@r%i+,sr\n", r8);
897 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 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 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 else if (lo8 == 0x17)
924 debug("ldc.l\t@r%i+,gbr\n", r8);
925 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 else if (lo8 == 0x23)
942 debug("stc.l\tvbr,@-r%i\n", r8);
943 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 else if (lo8 == 0x27)
950 debug("ldc.l\t@r%i+,vbr\n", r8);
951 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 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 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 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 else if (lo8 == 0x6a)
984 debug("lds\tr%i,fpscr\n", r8);
985 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 else
994 debug("UNIMPLEMENTED hi4=0x%x, lo8=0x%02x\n", hi4, lo8);
995 break;
996 case 0x5:
997 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 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 else if (lo4 == 0x5)
1016 debug("mov.w\t@r%i+,r%i\n", r4, r8);
1017 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 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 } else if (r8 == 0x8) {
1065 debug("cmp/eq\t#%i,r0\n", (int8_t)lo8);
1066 } else if (r8 == 0x9 || r8 == 0xb || r8 == 0xd || r8 == 0xf) {
1067 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 addr = lo8 * (hi4==9? 2 : 4);
1078 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 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 debug("trapa\t#%i\n", (uint8_t)lo8);
1097 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 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 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 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 int running, uint64_t dumpaddr)
1260 {
1261 uint64_t offset;
1262 uint32_t iword;
1263 char *symbol;
1264
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 if (cpu->cd.sh.cpu_type.bits == 32)
1277 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 running, dumpaddr);
1284
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