/[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 32 - (show annotations)
Mon Oct 8 16:20:58 2007 UTC (11 years, 11 months ago) by dpavlin
File MIME type: text/plain
File size: 33762 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1421 2006/11/06 05:32:37 debug Exp $
20060816	Adding a framework for emulated/virtual timers (src/timer.c),
		using only setitimer().
		Rewriting the mc146818 to use the new timer framework.
20060817	Adding a call to gettimeofday() every now and then (once every
		second, at the moment) to resynch the timer if it drifts.
		Beginning to convert the ISA timer interrupt mechanism (8253
		and 8259) to use the new timer framework.
		Removing the -I command line option.
20060819	Adding the -I command line option again, with new semantics.
		Working on Footbridge timer interrupts; NetBSD/NetWinder and
		NetBSD/CATS now run at correct speed, but unfortunately with
		HUGE delays during bootup.
20060821	Some minor m68k updates. Adding the first instruction: nop. :)
		Minor Alpha emulation updates.
20060822	Adding a FreeBSD development specific YAMON environment
		variable ("khz") (as suggested by Bruce M. Simpson).
		Moving YAMON environment variable initialization from
		machine_evbmips.c into promemul/yamon.c, and adding some more
		variables.
		Continuing on the LCA PCI bus controller (for Alpha machines).
20060823	Continuing on the timer stuff: experimenting with MIPS count/
		compare interrupts connected to the timer framework.
20060825	Adding bogus SCSI commands 0x51 (SCSICDROM_READ_DISCINFO) and
		0x52 (SCSICDROM_READ_TRACKINFO) to the SCSI emulation layer,
		to allow NetBSD/pmax 4.0_BETA to be installed from CDROM.
		Minor updates to the LCA PCI controller.
20060827	Implementing a CHIP8 cpu mode, and a corresponding CHIP8
		machine, for fun. Disassembly support for all instructions,
		and most of the common instructions have been implemented: mvi,
		mov_imm, add_imm, jmp, rand, cls, sprite, skeq_imm, jsr,
		skne_imm, bcd, rts, ldr, str, mov, or, and, xor, add, sub,
		font, ssound, sdelay, gdelay, bogus skup/skpr, skeq, skne.
20060828	Beginning to convert the CHIP8 cpu in the CHIP8 machine to a
		(more correct) RCA 180x cpu. (Disassembly for all 1802
		instructions has been implemented, but no execution yet, and
		no 1805 extended instructions.)
20060829	Minor Alpha emulation updates.
20060830	Beginning to experiment a little with PCI IDE for SGI O2.
		Fixing the cursor key mappings for MobilePro 770 emulation.
		Fixing the LK201 warning caused by recent NetBSD/pmax.
		The MIPS R41xx standby, suspend, and hibernate instructions now
		behave like the RM52xx/MIPS32/MIPS64 wait instruction.
		Fixing dev_wdc so it calculates correct (64-bit) offsets before
		giving them to diskimage_access().
20060831	Continuing on Alpha emulation (OSF1 PALcode).
20060901	Minor Alpha updates; beginning on virtual memory pagetables.
		Removed the limit for max nr of devices (in preparation for
		allowing devices' base addresses to be changed during runtime).
		Adding a hack for MIPS [d]mfc0 select 0 (except the count
		register), so that the coproc register is simply copied.
		The MIPS suspend instruction now exits the emulator, instead
		of being treated as a wait instruction (this causes NetBSD/
		hpcmips to get correct 'halt' behavior).
		The VR41xx RTC now returns correct time.
		Connecting the VR41xx timer to the timer framework (fixed at
		128 Hz, for now).
		Continuing on SPARC emulation, adding more instructions:
		restore, ba_xcc, ble. The rectangle drawing demo works :)
		Removing the last traces of the old ENABLE_CACHE_EMULATION
		MIPS stuff (not usable with dyntrans anyway).
20060902	Splitting up src/net.c into several smaller files in its own
		subdirectory (src/net/).
20060903	Cleanup of the files in src/net/, to make them less ugly.
20060904	Continuing on the 'settings' subsystem.
		Minor progress on the SPARC emulation mode.
20060905	Cleanup of various things, and connecting the settings
		infrastructure to various subsystems (emul, machine, cpu, etc).
		Changing the lk201 mouse update routine to not rely on any
		emulated hardware framebuffer cursor coordinates, but instead
		always do (semi-usable) relative movements.
20060906	Continuing on the lk201 mouse stuff. Mouse behaviour with
		multiple framebuffers (which was working in Ultrix) is now
		semi-broken (but it still works, in a way).
		Moving the documentation about networking into its own file
		(networking.html), and refreshing it a bit. Adding an example
		of how to use ethernet frame direct-access (udp_snoop).
20060907	Continuing on the settings infrastructure.
20060908	Minor updates to SH emulation: for 32-bit emulation: delay
		slots and the 'jsr @Rn' instruction. I'm putting 64-bit SH5 on
		ice, for now.
20060909-10	Implementing some more 32-bit SH instructions. Removing the
		64-bit mode completely. Enough has now been implemented to run
		the rectangle drawing demo. :-)
20060912	Adding more SH instructions.
20060916	Continuing on SH emulation (some more instructions: div0u,
		div1, rotcl/rotcr, more mov instructions, dt, braf, sets, sett,
		tst_imm, dmuls.l, subc, ldc_rm_vbr, movt, clrt, clrs, clrmac).
		Continuing on the settings subsystem (beginning on reading/
		writing settings, removing bugs, and connecting more cpus to
		the framework).
20060919	More work on SH emulation; adding an ldc banked instruction,
		and attaching a 640x480 framebuffer to the Dreamcast machine
		mode (NetBSD/dreamcast prints the NetBSD copyright banner :-),
		and then panics).
20060920	Continuing on the settings subsystem.
20060921	Fixing the Footbridge timer stuff so that NetBSD/cats and
		NetBSD/netwinder boot up without the delays.
20060922	Temporarily hardcoding MIPS timer interrupt to 100 Hz. With
		'wait' support disabled, NetBSD/malta and Linux/malta run at
		correct speed.
20060923	Connecting dev_gt to the timer framework, so that NetBSD/cobalt
		runs at correct speed.
		Moving SH4-specific memory mapped registers into its own
		device (dev_sh4.c).
		Running with -N now prints "idling" instead of bogus nr of
		instrs/second (which isn't valid anyway) while idling.
20060924	Algor emulation should now run at correct speed.
		Adding disassembly support for some MIPS64 revision 2
		instructions: ext, dext, dextm, dextu.
20060926	The timer framework now works also when the MIPS wait
		instruction is used.
20060928	Re-implementing checks for coprocessor availability for MIPS
		cop0 instructions. (Thanks to Carl van Schaik for noticing the
		lack of cop0 availability checks.)
20060929	Implementing an instruction combination hack which treats
		NetBSD/pmax' idle loop as a wait-like instruction.
20060930	The ENTRYHI_R_MASK was missing in (at least) memory_mips_v2p.c,
		causing TLB lookups to sometimes succeed when they should have
		failed. (A big thank you to Juli Mallett for noticing the
		problem.)
		Adding disassembly support for more MIPS64 revision 2 opcodes
		(seb, seh, wsbh, jalr.hb, jr.hb, synci, ins, dins, dinsu,
		dinsm, dsbh, dshd, ror, dror, rorv, drorv, dror32). Also
		implementing seb, seh, dsbh, dshd, and wsbh.
		Implementing an instruction combination hack for Linux/pmax'
		idle loop, similar to the NetBSD/pmax case.
20061001	Changing the NetBSD/sgimips install instructions to extract
		files from an iso image, instead of downloading them via ftp.
20061002	More-than-31-bit userland addresses in memory_mips_v2p.c were
		not actually working; applying a fix from Carl van Schaik to
		enable them to work + making some other updates (adding kuseg
		support).
		Fixing hpcmips (vr41xx) timer initialization.
		Experimenting with O(n)->O(1) reduction in the MIPS TLB lookup
		loop. Seems to work both for R3000 and non-R3000.
20061003	Continuing a little on SH emulation (adding more control
		registers; mini-cleanup of memory_sh.c).
20061004	Beginning on a dev_rtc, a clock/timer device for the test
		machines; also adding a demo, and some documentation.
		Fixing a bug in SH "mov.w @(disp,pc),Rn" (the result wasn't
		sign-extended), and adding the addc and ldtlb instructions.
20061005	Contining on SH emulation: virtual to physical address
		translation, and a skeleton exception mechanism.
20061006	Adding more SH instructions (various loads and stores, rte,
		negc, muls.w, various privileged register-move instructions).
20061007	More SH instructions: various move instructions, trapa, div0s,
		float, fdiv, ftrc.
		Continuing on dev_rtc; removing the rtc demo.
20061008	Adding a dummy Dreamcast PROM module. (Homebrew Dreamcast
		programs using KOS libs need this.)
		Adding more SH instructions: "stc vbr,rn", rotl, rotr, fsca,
		fmul, fadd, various floating-point moves, etc. A 256-byte
		demo for Dreamcast runs :-)
20061012	Adding the SH "lds Rm,pr" and bsr instructions.
20061013	More SH instructions: "sts fpscr,rn", tas.b, and some more
		floating point instructions, cmp/str, and more moves.
		Adding a dummy dev_pvr (Dreamcast graphics controller).
20061014	Generalizing the expression evaluator (used in the built-in
		debugger) to support parentheses and +-*/%^&|.
20061015	Removing the experimental tlb index hint code in
		mips_memory_v2p.c, since it didn't really have any effect.
20061017	Minor SH updates; adding the "sts pr,Rn", fcmp/gt, fneg,
		frchg, and some other instructions. Fixing missing sign-
		extension in an 8-bit load instruction.
20061019	Adding a simple dev_dreamcast_rtc.
		Implementing memory-mapped access to the SH ITLB/UTLB arrays.
20061021	Continuing on various SH and Dreamcast things: sh4 timers,
		debug messages for dev_pvr, fixing some virtual address
		translation bugs, adding the bsrf instruction.
		The NetBSD/dreamcast GENERIC_MD kernel now reaches userland :)
		Adding a dummy dev_dreamcast_asic.c (not really useful yet).
		Implementing simple support for Store Queues.
		Beginning on the PVR Tile Accelerator.
20061022	Generalizing the PVR framebuffer to support off-screen drawing,
		multiple bit-depths, etc. (A small speed penalty, but most
		likely worth it.)
		Adding more SH instructions (mulu.w, fcmp/eq, fsub, fmac,
		fschg, and some more); correcting bugs in "fsca" and "float".
20061024	Adding the SH ftrv (matrix * vector) instruction. Marcus
		Comstedt's "tatest" example runs :) (wireframe only).
		Correcting disassembly for SH floating point instructions that
		use the xd* registers.
		Adding the SH fsts instruction.
		In memory_device_dyntrans_access(), only the currently used
		range is now invalidated, and not the entire device range.
20061025	Adding a dummy AVR32 cpu mode skeleton.
20061026	Various Dreamcast updates; beginning on a Maple bus controller.
20061027	Continuing on the Maple bus. A bogus Controller, Keyboard, and
		Mouse can now be detected by NetBSD and KOS homebrew programs.
		Cleaning up the SH4 Timer Management Unit, and beginning on
		SH4 interrupts.
		Implementing the Dreamcast SYSASIC.
20061028	Continuing on the SYSASIC.
		Adding the SH fsqrt instruction.
		memory_sh.c now actually scans the ITLB.
		Fixing a bug in dev_sh4.c, related to associative writes into
		the memory-mapped UTLB array. NetBSD/dreamcast now reaches
		userland stably, and prints the "Terminal type?" message :-]
		Implementing enough of the Dreamcast keyboard to make NetBSD
		accept it for input.
		Enabling SuperH for stable (non-development) builds.
		Adding NetBSD/dreamcast to the documentation, although it
		doesn't support root-on-nfs yet.
20061029	Changing usleep(1) calls in the debugger to to usleep(10000)
		(according to Brian Foley, this makes GXemul run better on
		MacOS X).
		Making the Maple "Controller" do something (enough to barely
		interact with dcircus.elf).
20061030-31	Some progress on the PVR. More test programs start running (but
		with strange output).
		Various other SH4-related updates.
20061102	Various Dreamcast and SH4 updates; more KOS demos run now.
20061104	Adding a skeleton dev_mb8696x.c (the Dreamcast's LAN adapter).
20061105	Continuing on the MB8696x; NetBSD/dreamcast detects it as mbe0.
		Testing for the release.

==============  RELEASE 0.4.3  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26