/[gxemul]/trunk/src/cpus/cpu_mips.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_mips.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (show annotations)
Mon Oct 8 16:20:58 2007 UTC (13 years ago) by dpavlin
File MIME type: text/plain
File size: 57681 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) 2003-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_mips.c,v 1.69 2006/10/07 02:05:21 debug Exp $
29 *
30 * MIPS core CPU emulation.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <ctype.h>
38 #include <unistd.h>
39
40 #include "../../config.h"
41
42 #include "arcbios.h"
43 #include "cop0.h"
44 #include "cpu.h"
45 #include "cpu_mips.h"
46 #include "debugger.h"
47 #include "devices.h"
48 #include "emul.h"
49 #include "machine.h"
50 #include "memory.h"
51 #include "mips_cpu_types.h"
52 #include "opcodes_mips.h"
53 #include "settings.h"
54 #include "symbol.h"
55
56
57 extern volatile int single_step;
58
59 static char *exception_names[] = EXCEPTION_NAMES;
60
61 static char *hi6_names[] = HI6_NAMES;
62 static char *regimm_names[] = REGIMM_NAMES;
63 static char *special_names[] = SPECIAL_NAMES;
64 static char *special_rot_names[] = SPECIAL_ROT_NAMES;
65 static char *special2_names[] = SPECIAL2_NAMES;
66 static char *mmi_names[] = MMI_NAMES;
67 static char *mmi0_names[] = MMI0_NAMES;
68 static char *mmi1_names[] = MMI1_NAMES;
69 static char *mmi2_names[] = MMI2_NAMES;
70 static char *mmi3_names[] = MMI3_NAMES;
71 static char *special3_names[] = SPECIAL3_NAMES;
72
73 static char *regnames[] = MIPS_REGISTER_NAMES;
74 static char *cop0_names[] = COP0_NAMES;
75
76
77 #define DYNTRANS_DUALMODE_32
78 #define DYNTRANS_DELAYSLOT
79 #include "tmp_mips_head.c"
80
81 void mips_pc_to_pointers(struct cpu *);
82 void mips32_pc_to_pointers(struct cpu *);
83
84
85 /*
86 * regname():
87 *
88 * Convert a register number into either 'r0', 'r31' etc, or a symbolic
89 * name, depending on machine->show_symbolic_register_names.
90 *
91 * NOTE: _NOT_ reentrant.
92 */
93 static char *regname(struct machine *machine, int r)
94 {
95 static char ch[4];
96 ch[3] = ch[2] = '\0';
97
98 if (r<0 || r>=32)
99 strlcpy(ch, "xx", sizeof(ch));
100 else if (machine->show_symbolic_register_names)
101 strlcpy(ch, regnames[r], sizeof(ch));
102 else
103 snprintf(ch, sizeof(ch), "r%i", r);
104
105 return ch;
106 }
107
108
109 /*
110 * mips_cpu_new():
111 *
112 * Create a new MIPS cpu object.
113 *
114 * Returns 1 on success, 0 if there was no valid MIPS processor with
115 * a matching name.
116 */
117 int mips_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
118 int cpu_id, char *cpu_type_name)
119 {
120 int i, found, j, tags_size, n_cache_lines, size_per_cache_line;
121 struct mips_cpu_type_def cpu_type_defs[] = MIPS_CPU_TYPE_DEFS;
122 int64_t secondary_cache_size;
123 int x, linesize;
124
125 /* Scan the cpu_type_defs list for this cpu type: */
126 i = 0;
127 found = -1;
128 while (i >= 0 && cpu_type_defs[i].name != NULL) {
129 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
130 found = i;
131 break;
132 }
133 i++;
134 }
135
136 if (found == -1)
137 return 0;
138
139 cpu->memory_rw = mips_memory_rw;
140 cpu->cd.mips.cpu_type = cpu_type_defs[found];
141 cpu->name = cpu->cd.mips.cpu_type.name;
142 cpu->byte_order = EMUL_LITTLE_ENDIAN;
143 cpu->cd.mips.gpr[MIPS_GPR_SP] = INITIAL_STACK_POINTER;
144
145 if (cpu->cd.mips.cpu_type.isa_level <= 2 ||
146 cpu->cd.mips.cpu_type.isa_level == 32)
147 cpu->is_32bit = 1;
148
149 if (cpu->is_32bit) {
150 cpu->run_instr = mips32_run_instr;
151 cpu->update_translation_table = mips32_update_translation_table;
152 cpu->invalidate_translation_caches =
153 mips32_invalidate_translation_caches;
154 cpu->invalidate_code_translation =
155 mips32_invalidate_code_translation;
156 } else {
157 cpu->run_instr = mips_run_instr;
158 cpu->update_translation_table = mips_update_translation_table;
159 cpu->invalidate_translation_caches =
160 mips_invalidate_translation_caches;
161 cpu->invalidate_code_translation =
162 mips_invalidate_code_translation;
163 }
164
165 cpu->instruction_has_delayslot = mips_cpu_instruction_has_delayslot;
166
167 if (cpu_id == 0)
168 debug("%s", cpu->cd.mips.cpu_type.name);
169
170 /*
171 * CACHES:
172 *
173 * 1) Use DEFAULT_PCACHE_SIZE and DEFAULT_PCACHE_LINESIZE etc.
174 * 2) If there are specific values defined for this type of cpu,
175 * in its cpu_type substruct, then let's use those.
176 * 3) Values in the emul struct override both of the above.
177 *
178 * Once we've decided which values to use, they are stored in
179 * the emul struct so they can be used from src/machine.c etc.
180 */
181
182 x = DEFAULT_PCACHE_SIZE;
183 if (cpu->cd.mips.cpu_type.pdcache)
184 x = cpu->cd.mips.cpu_type.pdcache;
185 if (machine->cache_pdcache == 0)
186 machine->cache_pdcache = x;
187
188 x = DEFAULT_PCACHE_SIZE;
189 if (cpu->cd.mips.cpu_type.picache)
190 x = cpu->cd.mips.cpu_type.picache;
191 if (machine->cache_picache == 0)
192 machine->cache_picache = x;
193
194 if (machine->cache_secondary == 0)
195 machine->cache_secondary = cpu->cd.mips.cpu_type.scache;
196
197 linesize = DEFAULT_PCACHE_LINESIZE;
198 if (cpu->cd.mips.cpu_type.pdlinesize)
199 linesize = cpu->cd.mips.cpu_type.pdlinesize;
200 if (machine->cache_pdcache_linesize == 0)
201 machine->cache_pdcache_linesize = linesize;
202
203 linesize = DEFAULT_PCACHE_LINESIZE;
204 if (cpu->cd.mips.cpu_type.pilinesize)
205 linesize = cpu->cd.mips.cpu_type.pilinesize;
206 if (machine->cache_picache_linesize == 0)
207 machine->cache_picache_linesize = linesize;
208
209 linesize = 0;
210 if (cpu->cd.mips.cpu_type.slinesize)
211 linesize = cpu->cd.mips.cpu_type.slinesize;
212 if (machine->cache_secondary_linesize == 0)
213 machine->cache_secondary_linesize = linesize;
214
215
216 /*
217 * Primary Data and Instruction caches:
218 */
219 for (i=CACHE_DATA; i<=CACHE_INSTRUCTION; i++) {
220 switch (i) {
221 case CACHE_DATA:
222 x = 1 << machine->cache_pdcache;
223 linesize = 1 << machine->cache_pdcache_linesize;
224 break;
225 case CACHE_INSTRUCTION:
226 x = 1 << machine->cache_picache;
227 linesize = 1 << machine->cache_picache_linesize;
228 break;
229 }
230
231 /* Primary cache size and linesize: */
232 cpu->cd.mips.cache_size[i] = x;
233 cpu->cd.mips.cache_linesize[i] = linesize;
234
235 switch (cpu->cd.mips.cpu_type.rev) {
236 case MIPS_R2000:
237 case MIPS_R3000:
238 size_per_cache_line = sizeof(struct r3000_cache_line);
239 break;
240 default:
241 size_per_cache_line = sizeof(struct r4000_cache_line);
242 }
243
244 cpu->cd.mips.cache_mask[i] = cpu->cd.mips.cache_size[i] - 1;
245 cpu->cd.mips.cache_miss_penalty[i] = 10; /* TODO ? */
246
247 cpu->cd.mips.cache[i] = malloc(cpu->cd.mips.cache_size[i]);
248 if (cpu->cd.mips.cache[i] == NULL) {
249 fprintf(stderr, "out of memory\n");
250 }
251
252 n_cache_lines = cpu->cd.mips.cache_size[i] /
253 cpu->cd.mips.cache_linesize[i];
254 tags_size = n_cache_lines * size_per_cache_line;
255
256 cpu->cd.mips.cache_tags[i] = malloc(tags_size);
257 if (cpu->cd.mips.cache_tags[i] == NULL) {
258 fprintf(stderr, "out of memory\n");
259 }
260
261 /* Initialize the cache tags: */
262 switch (cpu->cd.mips.cpu_type.rev) {
263 case MIPS_R2000:
264 case MIPS_R3000:
265 for (j=0; j<n_cache_lines; j++) {
266 struct r3000_cache_line *rp;
267 rp = (struct r3000_cache_line *)
268 cpu->cd.mips.cache_tags[i];
269 rp[j].tag_paddr = 0;
270 rp[j].tag_valid = 0;
271 }
272 break;
273 default:
274 ;
275 }
276
277 /* Set cache_last_paddr to something "impossible": */
278 cpu->cd.mips.cache_last_paddr[i] = IMPOSSIBLE_PADDR;
279 }
280
281 /*
282 * Secondary cache:
283 */
284 secondary_cache_size = 0;
285 if (machine->cache_secondary)
286 secondary_cache_size = 1 << machine->cache_secondary;
287 /* TODO: linesize... */
288
289 if (cpu_id == 0) {
290 debug(" (I+D = %i+%i KB",
291 (int)(cpu->cd.mips.cache_size[CACHE_INSTRUCTION] / 1024),
292 (int)(cpu->cd.mips.cache_size[CACHE_DATA] / 1024));
293
294 if (secondary_cache_size != 0) {
295 debug(", L2 = ");
296 if (secondary_cache_size >= 1048576)
297 debug("%i MB", (int)
298 (secondary_cache_size / 1048576));
299 else
300 debug("%i KB", (int)
301 (secondary_cache_size / 1024));
302 }
303
304 debug(")");
305 }
306
307 /* System coprocessor (0), and FPU (1): */
308 cpu->cd.mips.coproc[0] = mips_coproc_new(cpu, 0);
309 cpu->cd.mips.coproc[1] = mips_coproc_new(cpu, 1);
310
311 switch (cpu->cd.mips.cpu_type.mmu_model) {
312 case MMU3K:
313 cpu->translate_v2p = translate_v2p_mmu3k;
314 break;
315 case MMU8K:
316 cpu->translate_v2p = translate_v2p_mmu8k;
317 break;
318 case MMU10K:
319 cpu->translate_v2p = translate_v2p_mmu10k;
320 break;
321 default:
322 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
323 cpu->translate_v2p = translate_v2p_mmu4100;
324 else
325 cpu->translate_v2p = translate_v2p_generic;
326 }
327
328 if (cpu->machine->prom_emulation) {
329 /*
330 * Default behaviour of jumping to 0xbfc00000 should be
331 * a reboot, unless machine-specific initialization code
332 * overrides this.
333 *
334 * Note: Specifically big-endian machines should override
335 * this, since the default MIPS CPU is little-endian!
336 */
337 store_32bit_word(cpu, 0xffffffff9fc00000ULL, 0x00c0de0d);
338 }
339
340 /* Add all register names to the settings: */
341 CPU_SETTINGS_ADD_REGISTER64("pc", cpu->pc);
342 CPU_SETTINGS_ADD_REGISTER64("hi", cpu->cd.mips.hi);
343 CPU_SETTINGS_ADD_REGISTER64("lo", cpu->cd.mips.lo);
344 for (i=0; i<N_MIPS_GPRS; i++)
345 CPU_SETTINGS_ADD_REGISTER64(regnames[i], cpu->cd.mips.gpr[i]);
346 /* TODO: Write via special handler function! */
347 for (i=0; i<N_MIPS_COPROC_REGS; i++)
348 CPU_SETTINGS_ADD_REGISTER64(cop0_names[i],
349 cpu->cd.mips.coproc[0]->reg[i]);
350
351 return 1;
352 }
353
354
355 /*
356 * mips_cpu_dumpinfo():
357 *
358 * Debug dump of MIPS-specific CPU data for specific CPU.
359 */
360 void mips_cpu_dumpinfo(struct cpu *cpu)
361 {
362 int iadd = DEBUG_INDENTATION;
363 struct mips_cpu_type_def *ct = &cpu->cd.mips.cpu_type;
364
365 debug_indentation(iadd);
366
367 debug("\n%i-bit %s-endian (MIPS",
368 cpu->is_32bit? 32 : 64,
369 cpu->byte_order == EMUL_BIG_ENDIAN? "Big" : "Little");
370
371 switch (ct->isa_level) {
372 case 1: debug(" ISA I"); break;
373 case 2: debug(" ISA II"); break;
374 case 3: debug(" ISA III"); break;
375 case 4: debug(" ISA IV"); break;
376 case 5: debug(" ISA V"); break;
377 case 32:
378 case 64:debug("%i, revision %i", ct->isa_level, ct->isa_revision);
379 break;
380 default:debug(" ISA level %i", ct->isa_level);
381 }
382
383 debug("), ");
384 if (ct->nr_of_tlb_entries)
385 debug("%i TLB entries", ct->nr_of_tlb_entries);
386 else
387 debug("no TLB");
388 debug("\n");
389
390 if (ct->picache) {
391 debug("L1 I-cache: %i KB", (1 << ct->picache) / 1024);
392 if (ct->pilinesize)
393 debug(", %i bytes per line", 1 << ct->pilinesize);
394 if (ct->piways > 1)
395 debug(", %i-way", ct->piways);
396 else
397 debug(", direct-mapped");
398 debug("\n");
399 }
400
401 if (ct->pdcache) {
402 debug("L1 D-cache: %i KB", (1 << ct->pdcache) / 1024);
403 if (ct->pdlinesize)
404 debug(", %i bytes per line", 1 << ct->pdlinesize);
405 if (ct->pdways > 1)
406 debug(", %i-way", ct->pdways);
407 else
408 debug(", direct-mapped");
409 debug("\n");
410 }
411
412 if (ct->scache) {
413 int kb = (1 << ct->scache) / 1024;
414 debug("L2 cache: %i %s",
415 kb >= 1024? kb / 1024 : kb, kb >= 1024? "MB":"KB");
416 if (ct->slinesize)
417 debug(", %i bytes per line", 1 << ct->slinesize);
418 if (ct->sways > 1)
419 debug(", %i-way", ct->sways);
420 else
421 debug(", direct-mapped");
422 debug("\n");
423 }
424
425 debug_indentation(-iadd);
426 }
427
428
429 /*
430 * mips_cpu_list_available_types():
431 *
432 * Print a list of available MIPS CPU types.
433 */
434 void mips_cpu_list_available_types(void)
435 {
436 int i, j;
437 struct mips_cpu_type_def cpu_type_defs[] = MIPS_CPU_TYPE_DEFS;
438
439 i = 0;
440 while (cpu_type_defs[i].name != NULL) {
441 debug("%s", cpu_type_defs[i].name);
442 for (j=10 - strlen(cpu_type_defs[i].name); j>0; j--)
443 debug(" ");
444 i++;
445 if ((i % 6) == 0 || cpu_type_defs[i].name == NULL)
446 debug("\n");
447 }
448 }
449
450
451 /*
452 * mips_cpu_instruction_has_delayslot():
453 *
454 * Return 1 if an opcode is a branch, 0 otherwise.
455 */
456 int mips_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib)
457 {
458 uint32_t iword = *((uint32_t *)&ib[0]);
459
460 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
461 iword = LE32_TO_HOST(iword);
462 else
463 iword = BE32_TO_HOST(iword);
464
465 switch (iword >> 26) {
466 case HI6_SPECIAL:
467 switch (iword & 0x3f) {
468 case SPECIAL_JR:
469 case SPECIAL_JALR:
470 return 1;
471 }
472 break;
473 case HI6_REGIMM:
474 switch ((iword >> 16) & 0x1f) {
475 case REGIMM_BLTZ:
476 case REGIMM_BGEZ:
477 case REGIMM_BLTZL:
478 case REGIMM_BGEZL:
479 case REGIMM_BLTZAL:
480 case REGIMM_BLTZALL:
481 case REGIMM_BGEZAL:
482 case REGIMM_BGEZALL:
483 return 1;
484 }
485 break;
486 case HI6_BEQ:
487 case HI6_BEQL:
488 case HI6_BNE:
489 case HI6_BNEL:
490 case HI6_BGTZ:
491 case HI6_BGTZL:
492 case HI6_BLEZ:
493 case HI6_BLEZL:
494 case HI6_J:
495 case HI6_JAL:
496 return 1;
497 }
498
499 return 0;
500 }
501
502
503 /*
504 * mips_cpu_tlbdump():
505 *
506 * Called from the debugger to dump the TLB in a readable format.
507 * x is the cpu number to dump, or -1 to dump all CPUs.
508 *
509 * If rawflag is nonzero, then the TLB contents isn't formated nicely,
510 * just dumped.
511 */
512 void mips_cpu_tlbdump(struct machine *m, int x, int rawflag)
513 {
514 int i, j;
515
516 /* Raw output: */
517 if (rawflag) {
518 for (i=0; i<m->ncpus; i++) {
519 if (x >= 0 && i != x)
520 continue;
521
522 /* Print index, random, and wired: */
523 printf("cpu%i: (", i);
524
525 if (m->cpus[i]->is_32bit)
526 printf("index=0x%08x random=0x%08x", (int)m->
527 cpus[i]->cd.mips.coproc[0]->reg[COP0_INDEX],
528 (int)m->cpus[i]->cd.mips.coproc[0]->reg
529 [COP0_RANDOM]);
530 else
531 printf("index=0x%016"PRIx64
532 " random=0x%016"PRIx64,
533 (uint64_t)m->cpus[i]->cd.mips.coproc[0]->
534 reg[COP0_INDEX], (uint64_t)m->cpus[i]->
535 cd.mips.coproc[0]->reg[COP0_RANDOM]);
536
537 if (m->cpus[i]->cd.mips.cpu_type.isa_level >= 3)
538 printf(" wired=0x%"PRIx64, (uint64_t) m->cpus
539 [i]->cd.mips.coproc[0]->reg[COP0_WIRED]);
540
541 printf(")\n");
542
543 for (j=0; j<m->cpus[i]->cd.mips.cpu_type.
544 nr_of_tlb_entries; j++) {
545 if (m->cpus[i]->cd.mips.cpu_type.mmu_model ==
546 MMU3K)
547 printf("%3i: hi=0x%08x lo=0x%08x\n", j,
548 (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
549 (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0);
550 else if (m->cpus[i]->is_32bit)
551 printf("%3i: hi=0x%08x mask=0x%08x "
552 "lo0=0x%08x lo1=0x%08x\n", j,
553 (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
554 (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask,
555 (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0,
556 (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1);
557 else
558 printf("%3i: hi=0x%016"PRIx64" mask=0x%016"PRIx64" "
559 "lo0=0x%016"PRIx64" lo1=0x%016"PRIx64"\n", j,
560 (uint64_t)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
561 (uint64_t)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask,
562 (uint64_t)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0,
563 (uint64_t)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1);
564 }
565 }
566 return;
567 }
568
569 /* Nicely formatted output: */
570 for (i=0; i<m->ncpus; i++) {
571 int pageshift = 12;
572
573 if (x >= 0 && i != x)
574 continue;
575
576 if (m->cpus[i]->cd.mips.cpu_type.rev == MIPS_R4100)
577 pageshift = 10;
578
579 /* Print index, random, and wired: */
580 printf("cpu%i: (", i);
581 switch (m->cpus[i]->cd.mips.cpu_type.isa_level) {
582 case 1:
583 case 2: printf("index=0x%x random=0x%x",
584 (int) ((m->cpus[i]->cd.mips.coproc[0]->
585 reg[COP0_INDEX] & R2K3K_INDEX_MASK)
586 >> R2K3K_INDEX_SHIFT),
587 (int) ((m->cpus[i]->cd.mips.coproc[0]->
588 reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
589 >> R2K3K_RANDOM_SHIFT));
590 break;
591 default:printf("index=0x%x random=0x%x",
592 (int) (m->cpus[i]->cd.mips.coproc[0]->
593 reg[COP0_INDEX] & INDEX_MASK),
594 (int) (m->cpus[i]->cd.mips.coproc[0]->
595 reg[COP0_RANDOM] & RANDOM_MASK));
596 printf(" wired=0x%"PRIx64, (uint64_t)
597 m->cpus[i]->cd.mips.coproc[0]->reg[COP0_WIRED]);
598 }
599
600 printf(")\n");
601
602 for (j=0; j<m->cpus[i]->cd.mips.cpu_type.
603 nr_of_tlb_entries; j++) {
604 uint64_t hi,lo0,lo1,mask;
605 hi = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi;
606 lo0 = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0;
607 lo1 = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1;
608 mask = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask;
609
610 printf("%3i: ", j);
611 switch (m->cpus[i]->cd.mips.cpu_type.mmu_model) {
612 case MMU3K:
613 if (!(lo0 & R2K3K_ENTRYLO_V)) {
614 printf("(invalid)\n");
615 continue;
616 }
617 printf("vaddr=0x%08x ",
618 (int) (hi&R2K3K_ENTRYHI_VPN_MASK));
619 if (lo0 & R2K3K_ENTRYLO_G)
620 printf("(global), ");
621 else
622 printf("(asid %02x),", (int) ((hi &
623 R2K3K_ENTRYHI_ASID_MASK)
624 >> R2K3K_ENTRYHI_ASID_SHIFT));
625 printf(" paddr=0x%08x ",
626 (int) (lo0&R2K3K_ENTRYLO_PFN_MASK));
627 if (lo0 & R2K3K_ENTRYLO_N)
628 printf("N");
629 if (lo0 & R2K3K_ENTRYLO_D)
630 printf("D");
631 printf("\n");
632 break;
633 default:switch (m->cpus[i]->cd.mips.cpu_type.mmu_model){
634 case MMU32:
635 printf("vaddr=0x%08"PRIx32" ",
636 (uint32_t) hi);
637 break;
638 case MMU10K:
639 default:/* R4000 etc. */
640 printf("vaddr=%016"PRIx64" ",
641 (uint64_t) hi);
642 }
643 if (hi & TLB_G)
644 printf("(global): ");
645 else
646 printf("(asid %02x):",
647 (int) (hi & ENTRYHI_ASID));
648
649 /* TODO: Coherency bits */
650
651 if (!(lo0 & ENTRYLO_V))
652 printf(" p0=(invalid) ");
653 else
654 printf(" p0=0x%09"PRIx64" ", (uint64_t)
655 (((lo0&ENTRYLO_PFN_MASK) >>
656 ENTRYLO_PFN_SHIFT) << pageshift));
657 printf(lo0 & ENTRYLO_D? "D" : " ");
658
659 if (!(lo1 & ENTRYLO_V))
660 printf(" p1=(invalid) ");
661 else
662 printf(" p1=0x%09"PRIx64" ", (uint64_t)
663 (((lo1&ENTRYLO_PFN_MASK) >>
664 ENTRYLO_PFN_SHIFT) << pageshift));
665 printf(lo1 & ENTRYLO_D? "D" : " ");
666 mask |= (1 << (pageshift+1)) - 1;
667 switch (mask) {
668 case 0x7ff: printf(" (1KB)"); break;
669 case 0x1fff: printf(" (4KB)"); break;
670 case 0x7fff: printf(" (16KB)"); break;
671 case 0x1ffff: printf(" (64KB)"); break;
672 case 0x7ffff: printf(" (256KB)"); break;
673 case 0x1fffff: printf(" (1MB)"); break;
674 case 0x7fffff: printf(" (4MB)"); break;
675 case 0x1ffffff: printf(" (16MB)"); break;
676 case 0x7ffffff: printf(" (64MB)"); break;
677 default:printf(" (mask=%08x?)", (int)mask);
678 }
679 printf("\n");
680 }
681 }
682 }
683 }
684
685
686 /*
687 * mips_cpu_disassemble_instr():
688 *
689 * Convert an instruction word into human readable format, for instruction
690 * tracing.
691 *
692 * If running is 1, cpu->pc should be the address of the instruction.
693 *
694 * If running is 0, things that depend on the runtime environment (eg.
695 * register contents) will not be shown, and addr will be used instead of
696 * cpu->pc for relative addresses.
697 *
698 * NOTE 2: coprocessor instructions are not decoded nicely yet (TODO)
699 */
700 int mips_cpu_disassemble_instr(struct cpu *cpu, unsigned char *originstr,
701 int running, uint64_t dumpaddr)
702 {
703 int hi6, special6, regimm5, sub;
704 int rt, rd, rs, sa, imm, copz, cache_op, which_cache, showtag;
705 uint64_t addr, offset;
706 uint32_t instrword;
707 unsigned char instr[4];
708 char *symbol;
709
710 if (running)
711 dumpaddr = cpu->pc;
712
713 if ((dumpaddr & 3) != 0)
714 printf("WARNING: Unaligned address!\n");
715
716 symbol = get_symbol_name(&cpu->machine->symbol_context,
717 dumpaddr, &offset);
718 if (symbol != NULL && offset==0)
719 debug("<%s>\n", symbol);
720
721 if (cpu->machine->ncpus > 1 && running)
722 debug("cpu%i: ", cpu->cpu_id);
723
724 if (cpu->is_32bit)
725 debug("%08"PRIx32, (uint32_t)dumpaddr);
726 else
727 debug("%016"PRIx64, (uint64_t)dumpaddr);
728
729 *((uint32_t *)&instr[0]) = *((uint32_t *)&originstr[0]);
730
731 /*
732 * The rest of the code is written for little endian,
733 * so swap if necessary:
734 */
735 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
736 int tmp = instr[0]; instr[0] = instr[3];
737 instr[3] = tmp;
738 tmp = instr[1]; instr[1] = instr[2];
739 instr[2] = tmp;
740 }
741
742 debug(": %02x%02x%02x%02x",
743 instr[3], instr[2], instr[1], instr[0]);
744
745 if (running && cpu->delay_slot)
746 debug(" (d)");
747
748 debug("\t");
749
750 /*
751 * Decode the instruction:
752 */
753
754 hi6 = (instr[3] >> 2) & 0x3f;
755
756 switch (hi6) {
757 case HI6_SPECIAL:
758 special6 = instr[0] & 0x3f;
759 switch (special6) {
760 case SPECIAL_SLL:
761 case SPECIAL_SRL:
762 case SPECIAL_SRA:
763 case SPECIAL_DSLL:
764 case SPECIAL_DSRL:
765 case SPECIAL_DSRA:
766 case SPECIAL_DSLL32:
767 case SPECIAL_DSRL32:
768 case SPECIAL_DSRA32:
769 sub = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
770 rt = instr[2] & 31;
771 rd = (instr[1] >> 3) & 31;
772 sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
773
774 if (rd == 0 && special6 == SPECIAL_SLL) {
775 if (sa == 0)
776 debug("nop");
777 else if (sa == 1)
778 debug("ssnop");
779 else if (sa == 3)
780 debug("ehb");
781 else
782 debug("nop (weird, sa=%i)", sa);
783 break;
784 }
785
786 switch (sub) {
787 case 0x00:
788 debug("%s\t%s,",
789 special_names[special6],
790 regname(cpu->machine, rd));
791 debug("%s,%i", regname(cpu->machine, rt), sa);
792 break;
793 case 0x01:
794 debug("%s\t%s,",
795 special_rot_names[special6],
796 regname(cpu->machine, rd));
797 debug("%s,%i", regname(cpu->machine, rt), sa);
798 break;
799 default:debug("UNIMPLEMENTED special, sub=0x%02x\n",
800 sub);
801 }
802 break;
803 case SPECIAL_DSRLV:
804 case SPECIAL_DSRAV:
805 case SPECIAL_DSLLV:
806 case SPECIAL_SLLV:
807 case SPECIAL_SRAV:
808 case SPECIAL_SRLV:
809 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
810 rt = instr[2] & 31;
811 rd = (instr[1] >> 3) & 31;
812 sub = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
813
814 switch (sub) {
815 case 0x00:
816 debug("%s\t%s", special_names[special6],
817 regname(cpu->machine, rd));
818 debug(",%s", regname(cpu->machine, rt));
819 debug(",%s", regname(cpu->machine, rs));
820 break;
821 case 0x01:
822 debug("%s\t%s", special_rot_names[special6],
823 regname(cpu->machine, rd));
824 debug(",%s", regname(cpu->machine, rt));
825 debug(",%s", regname(cpu->machine, rs));
826 break;
827 default:debug("UNIMPLEMENTED special, sub=0x%02x\n",
828 sub);
829 }
830 break;
831 case SPECIAL_JR:
832 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
833 symbol = get_symbol_name(&cpu->machine->symbol_context,
834 cpu->cd.mips.gpr[rs], &offset);
835 /* .hb = hazard barrier hint on MIPS32/64 rev 2 */
836 debug("jr%s\t%s",
837 (instr[1] & 0x04) ? ".hb" : "",
838 regname(cpu->machine, rs));
839 if (running && symbol != NULL)
840 debug("\t<%s>", symbol);
841 break;
842 case SPECIAL_JALR:
843 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
844 rd = (instr[1] >> 3) & 31;
845 symbol = get_symbol_name(&cpu->machine->symbol_context,
846 cpu->cd.mips.gpr[rs], &offset);
847 /* .hb = hazard barrier hint on MIPS32/64 rev 2 */
848 debug("jalr%s\t%s",
849 (instr[1] & 0x04) ? ".hb" : "",
850 regname(cpu->machine, rd));
851 debug(",%s", regname(cpu->machine, rs));
852 if (running && symbol != NULL)
853 debug("\t<%s>", symbol);
854 break;
855 case SPECIAL_MFHI:
856 case SPECIAL_MFLO:
857 rd = (instr[1] >> 3) & 31;
858 debug("%s\t%s", special_names[special6],
859 regname(cpu->machine, rd));
860 break;
861 case SPECIAL_MTLO:
862 case SPECIAL_MTHI:
863 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
864 debug("%s\t%s", special_names[special6],
865 regname(cpu->machine, rs));
866 break;
867 case SPECIAL_ADD:
868 case SPECIAL_ADDU:
869 case SPECIAL_SUB:
870 case SPECIAL_SUBU:
871 case SPECIAL_AND:
872 case SPECIAL_OR:
873 case SPECIAL_XOR:
874 case SPECIAL_NOR:
875 case SPECIAL_SLT:
876 case SPECIAL_SLTU:
877 case SPECIAL_DADD:
878 case SPECIAL_DADDU:
879 case SPECIAL_DSUB:
880 case SPECIAL_DSUBU:
881 case SPECIAL_MOVZ:
882 case SPECIAL_MOVN:
883 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
884 rt = instr[2] & 31;
885 rd = (instr[1] >> 3) & 31;
886 if (cpu->is_32bit && (special6 == SPECIAL_ADDU ||
887 special6 == SPECIAL_SUBU) && rt == 0) {
888 /* Special case 1: addu/subu with
889 rt = the zero register ==> move */
890 debug("move\t%s", regname(cpu->machine, rd));
891 debug(",%s", regname(cpu->machine, rs));
892 } else if (special6 == SPECIAL_ADDU && cpu->is_32bit
893 && rs == 0) {
894 /* Special case 2: addu with
895 rs = the zero register ==> move */
896 debug("move\t%s", regname(cpu->machine, rd));
897 debug(",%s", regname(cpu->machine, rt));
898 } else {
899 debug("%s\t%s", special_names[special6],
900 regname(cpu->machine, rd));
901 debug(",%s", regname(cpu->machine, rs));
902 debug(",%s", regname(cpu->machine, rt));
903 }
904 break;
905 case SPECIAL_MULT:
906 case SPECIAL_MULTU:
907 case SPECIAL_DMULT:
908 case SPECIAL_DMULTU:
909 case SPECIAL_DIV:
910 case SPECIAL_DIVU:
911 case SPECIAL_DDIV:
912 case SPECIAL_DDIVU:
913 case SPECIAL_TGE:
914 case SPECIAL_TGEU:
915 case SPECIAL_TLT:
916 case SPECIAL_TLTU:
917 case SPECIAL_TEQ:
918 case SPECIAL_TNE:
919 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
920 rt = instr[2] & 31;
921 rd = (instr[1] >> 3) & 31;
922 debug("%s\t", special_names[special6]);
923 if (rd != 0) {
924 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
925 if (special6 == SPECIAL_MULT ||
926 special6 == SPECIAL_MULTU)
927 debug("%s,",
928 regname(cpu->machine, rd));
929 else
930 debug("WEIRD_R5900_RD,");
931 } else {
932 debug("WEIRD_RD_NONZERO,");
933 }
934 }
935 debug("%s", regname(cpu->machine, rs));
936 debug(",%s", regname(cpu->machine, rt));
937 break;
938 case SPECIAL_SYNC:
939 imm = ((instr[1] & 7) << 2) + (instr[0] >> 6);
940 debug("sync\t0x%02x", imm);
941 break;
942 case SPECIAL_SYSCALL:
943 imm = (((instr[3] << 24) + (instr[2] << 16) +
944 (instr[1] << 8) + instr[0]) >> 6) & 0xfffff;
945 if (imm != 0)
946 debug("syscall\t0x%05x", imm);
947 else
948 debug("syscall");
949 break;
950 case SPECIAL_BREAK:
951 imm = (((instr[3] << 24) + (instr[2] << 16) +
952 (instr[1] << 8) + instr[0]) >> 6) & 0xfffff;
953 if (imm != 0)
954 debug("break\t0x%05x", imm);
955 else
956 debug("break");
957 break;
958 case SPECIAL_MFSA:
959 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
960 rd = (instr[1] >> 3) & 31;
961 debug("mfsa\t%s", regname(cpu->machine, rd));
962 } else {
963 debug("unimplemented special 0x28");
964 }
965 break;
966 case SPECIAL_MTSA:
967 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
968 rs = ((instr[3] & 3) << 3) +
969 ((instr[2] >> 5) & 7);
970 debug("mtsa\t%s", regname(cpu->machine, rs));
971 } else {
972 debug("unimplemented special 0x29");
973 }
974 break;
975 default:
976 debug("%s\t= UNIMPLEMENTED", special_names[special6]);
977 }
978 break;
979 case HI6_BEQ:
980 case HI6_BEQL:
981 case HI6_BNE:
982 case HI6_BNEL:
983 case HI6_BGTZ:
984 case HI6_BGTZL:
985 case HI6_BLEZ:
986 case HI6_BLEZL:
987 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
988 rt = instr[2] & 31;
989 imm = (instr[1] << 8) + instr[0];
990 if (imm >= 32768)
991 imm -= 65536;
992 addr = (dumpaddr + 4) + (imm << 2);
993
994 if (hi6 == HI6_BEQ && rt == MIPS_GPR_ZERO &&
995 rs == MIPS_GPR_ZERO)
996 debug("b\t");
997 else {
998 debug("%s\t", hi6_names[hi6]);
999 switch (hi6) {
1000 case HI6_BEQ:
1001 case HI6_BEQL:
1002 case HI6_BNE:
1003 case HI6_BNEL:
1004 debug("%s,", regname(cpu->machine, rt));
1005 }
1006 debug("%s,", regname(cpu->machine, rs));
1007 }
1008
1009 if (cpu->is_32bit)
1010 debug("0x%08"PRIx32, (uint32_t)addr);
1011 else
1012 debug("0x%016"PRIx64, (uint64_t)addr);
1013
1014 symbol = get_symbol_name(&cpu->machine->symbol_context,
1015 addr, &offset);
1016 if (symbol != NULL && offset != addr)
1017 debug("\t<%s>", symbol);
1018 break;
1019 case HI6_ADDI:
1020 case HI6_ADDIU:
1021 case HI6_DADDI:
1022 case HI6_DADDIU:
1023 case HI6_SLTI:
1024 case HI6_SLTIU:
1025 case HI6_ANDI:
1026 case HI6_ORI:
1027 case HI6_XORI:
1028 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1029 rt = instr[2] & 31;
1030 imm = (instr[1] << 8) + instr[0];
1031 if (imm >= 32768)
1032 imm -= 65536;
1033 debug("%s\t%s,", hi6_names[hi6], regname(cpu->machine, rt));
1034 debug("%s,", regname(cpu->machine, rs));
1035 if (hi6 == HI6_ANDI || hi6 == HI6_ORI || hi6 == HI6_XORI)
1036 debug("0x%04x", imm & 0xffff);
1037 else
1038 debug("%i", imm);
1039 break;
1040 case HI6_LUI:
1041 rt = instr[2] & 31;
1042 imm = (instr[1] << 8) + instr[0];
1043 debug("lui\t%s,0x%x", regname(cpu->machine, rt), imm);
1044 break;
1045 case HI6_LB:
1046 case HI6_LBU:
1047 case HI6_LH:
1048 case HI6_LHU:
1049 case HI6_LW:
1050 case HI6_LWU:
1051 case HI6_LD:
1052 case HI6_LQ_MDMX:
1053 case HI6_LWC1:
1054 case HI6_LWC2:
1055 case HI6_LWC3:
1056 case HI6_LDC1:
1057 case HI6_LDC2:
1058 case HI6_LL:
1059 case HI6_LLD:
1060 case HI6_SB:
1061 case HI6_SH:
1062 case HI6_SW:
1063 case HI6_SD:
1064 case HI6_SQ_SPECIAL3:
1065 case HI6_SC:
1066 case HI6_SCD:
1067 case HI6_SWC1:
1068 case HI6_SWC2:
1069 case HI6_SWC3:
1070 case HI6_SDC1:
1071 case HI6_SDC2:
1072 case HI6_LWL:
1073 case HI6_LWR:
1074 case HI6_LDL:
1075 case HI6_LDR:
1076 case HI6_SWL:
1077 case HI6_SWR:
1078 case HI6_SDL:
1079 case HI6_SDR:
1080 if (hi6 == HI6_LQ_MDMX &&
1081 cpu->cd.mips.cpu_type.rev != MIPS_R5900) {
1082 debug("mdmx\t(UNIMPLEMENTED)");
1083 break;
1084 }
1085 if (hi6 == HI6_SQ_SPECIAL3 &&
1086 cpu->cd.mips.cpu_type.rev != MIPS_R5900) {
1087 int msbd, lsb, sub10;
1088 special6 = instr[0] & 0x3f;
1089 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1090 rt = instr[2] & 31;
1091 rd = msbd = (instr[1] >> 3) & 31;
1092 lsb = ((instr[1] & 7) << 2) | (instr[0] >> 6);
1093 sub10 = (rs << 5) | lsb;
1094
1095 switch (special6) {
1096
1097 case SPECIAL3_EXT:
1098 case SPECIAL3_DEXT:
1099 case SPECIAL3_DEXTM:
1100 case SPECIAL3_DEXTU:
1101 debug("%s", special3_names[special6]);
1102 if (special6 == SPECIAL3_DEXTM)
1103 msbd += 32;
1104 if (special6 == SPECIAL3_DEXTU)
1105 lsb += 32;
1106 debug("\t%s", regname(cpu->machine, rt));
1107 debug(",%s", regname(cpu->machine, rs));
1108 debug(",%i,%i", lsb, msbd + 1);
1109 break;
1110
1111 case SPECIAL3_INS:
1112 case SPECIAL3_DINS:
1113 case SPECIAL3_DINSM:
1114 case SPECIAL3_DINSU:
1115 debug("%s", special3_names[special6]);
1116 if (special6 == SPECIAL3_DINSM)
1117 msbd += 32;
1118 if (special6 == SPECIAL3_DINSU) {
1119 lsb += 32;
1120 msbd += 32;
1121 }
1122 msbd -= lsb;
1123 debug("\t%s", regname(cpu->machine, rt));
1124 debug(",%s", regname(cpu->machine, rs));
1125 debug(",%i,%i", lsb, msbd + 1);
1126 break;
1127
1128 case SPECIAL3_BSHFL:
1129 switch (sub10) {
1130 case BSHFL_WSBH:
1131 case BSHFL_SEB:
1132 case BSHFL_SEH:
1133 switch (sub10) {
1134 case BSHFL_WSBH: debug("wsbh"); break;
1135 case BSHFL_SEB: debug("seb"); break;
1136 case BSHFL_SEH: debug("seh"); break;
1137 }
1138 debug("\t%s", regname(cpu->machine,rd));
1139 debug(",%s", regname(cpu->machine,rt));
1140 break;
1141 default:debug("%s", special3_names[special6]);
1142 debug("\t(UNIMPLEMENTED)");
1143 }
1144 break;
1145
1146 case SPECIAL3_DBSHFL:
1147 switch (sub10) {
1148 case BSHFL_DSBH:
1149 case BSHFL_DSHD:
1150 switch (sub10) {
1151 case BSHFL_DSBH: debug("dsbh"); break;
1152 case BSHFL_DSHD: debug("dshd"); break;
1153 }
1154 debug("\t%s", regname(cpu->machine,rd));
1155 debug(",%s", regname(cpu->machine,rt));
1156 break;
1157 default:debug("%s", special3_names[special6]);
1158 debug("\t(UNIMPLEMENTED)");
1159 }
1160 break;
1161
1162 case SPECIAL3_RDHWR:
1163 debug("%s", special3_names[special6]);
1164 debug("\t%s", regname(cpu->machine, rt));
1165 debug(",hwr%i", rd);
1166 break;
1167
1168 default:debug("%s", special3_names[special6]);
1169 debug("\t(UNIMPLEMENTED)");
1170 }
1171 break;
1172 }
1173
1174 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1175 rt = instr[2] & 31;
1176 imm = (instr[1] << 8) + instr[0];
1177 if (imm >= 32768)
1178 imm -= 65536;
1179 symbol = get_symbol_name(&cpu->machine->symbol_context,
1180 cpu->cd.mips.gpr[rs] + imm, &offset);
1181
1182 /* LWC3 is PREF in the newer ISA levels: */
1183 /* TODO: Which ISAs? IV? V? 32? 64? */
1184 if (cpu->cd.mips.cpu_type.isa_level >= 4 && hi6 == HI6_LWC3) {
1185 debug("pref\t0x%x,%i(%s)",
1186 rt, imm, regname(cpu->machine, rs));
1187
1188 if (running) {
1189 debug("\t[0x%016"PRIx64" = %s]",
1190 (uint64_t)(cpu->cd.mips.gpr[rs] + imm));
1191 if (symbol != NULL)
1192 debug(" = %s", symbol);
1193 debug("]");
1194 }
1195 goto disasm_ret;
1196 }
1197
1198 debug("%s\t", hi6_names[hi6]);
1199
1200 if (hi6 == HI6_SWC1 || hi6 == HI6_SWC2 || hi6 == HI6_SWC3 ||
1201 hi6 == HI6_SDC1 || hi6 == HI6_SDC2 ||
1202 hi6 == HI6_LWC1 || hi6 == HI6_LWC2 || hi6 == HI6_LWC3 ||
1203 hi6 == HI6_LDC1 || hi6 == HI6_LDC2)
1204 debug("r%i", rt);
1205 else
1206 debug("%s", regname(cpu->machine, rt));
1207
1208 debug(",%i(%s)", imm, regname(cpu->machine, rs));
1209
1210 if (running) {
1211 debug("\t[");
1212
1213 if (cpu->is_32bit)
1214 debug("0x%08"PRIx32,
1215 (uint32_t) (cpu->cd.mips.gpr[rs] + imm));
1216 else
1217 debug("0x%016"PRIx64,
1218 (uint64_t) (cpu->cd.mips.gpr[rs] + imm));
1219
1220 if (symbol != NULL)
1221 debug(" = %s", symbol);
1222
1223 /* TODO: In some cases, it is possible to peek into
1224 memory, and display that data here, like for the
1225 other emulation modes. */
1226
1227 debug("]");
1228 }
1229 break;
1230
1231 case HI6_J:
1232 case HI6_JAL:
1233 imm = (((instr[3] & 3) << 24) + (instr[2] << 16) +
1234 (instr[1] << 8) + instr[0]) << 2;
1235 addr = (dumpaddr + 4) & ~((1 << 28) - 1);
1236 addr |= imm;
1237 symbol = get_symbol_name(&cpu->machine->symbol_context,
1238 addr, &offset);
1239 debug("%s\t0x", hi6_names[hi6]);
1240 if (cpu->is_32bit)
1241 debug("%08"PRIx32, (uint32_t) addr);
1242 else
1243 debug("%016"PRIx64, (uint64_t) addr);
1244 if (symbol != NULL)
1245 debug("\t<%s>", symbol);
1246 break;
1247
1248 case HI6_COP0:
1249 case HI6_COP1:
1250 case HI6_COP2:
1251 case HI6_COP3:
1252 imm = (instr[3] << 24) + (instr[2] << 16) +
1253 (instr[1] << 8) + instr[0];
1254 imm &= ((1 << 26) - 1);
1255
1256 /* Call coproc_function(), but ONLY disassembly, no exec: */
1257 coproc_function(cpu, cpu->cd.mips.coproc[hi6 - HI6_COP0],
1258 hi6 - HI6_COP0, imm, 1, running);
1259 return sizeof(instrword);
1260
1261 case HI6_CACHE:
1262 rt = ((instr[3] & 3) << 3) + (instr[2] >> 5); /* base */
1263 copz = instr[2] & 31;
1264 imm = (instr[1] << 8) + instr[0];
1265 cache_op = copz >> 2;
1266 which_cache = copz & 3;
1267 showtag = 0;
1268 debug("cache\t0x%02x,0x%04x(%s)", copz, imm,
1269 regname(cpu->machine, rt));
1270 if (which_cache==0) debug(" [ primary I-cache");
1271 if (which_cache==1) debug(" [ primary D-cache");
1272 if (which_cache==2) debug(" [ secondary I-cache");
1273 if (which_cache==3) debug(" [ secondary D-cache");
1274 debug(", ");
1275 if (cache_op==0) debug("index invalidate");
1276 if (cache_op==1) debug("index load tag");
1277 if (cache_op==2) debug("index store tag"), showtag=1;
1278 if (cache_op==3) debug("create dirty exclusive");
1279 if (cache_op==4) debug("hit invalidate");
1280 if (cache_op==5) debug("fill OR hit writeback invalidate");
1281 if (cache_op==6) debug("hit writeback");
1282 if (cache_op==7) debug("hit set virtual");
1283 if (running)
1284 debug(", addr 0x%016"PRIx64,
1285 (uint64_t)(cpu->cd.mips.gpr[rt] + imm));
1286 if (showtag)
1287 debug(", taghi=%08lx lo=%08lx",
1288 (long)cpu->cd.mips.coproc[0]->reg[COP0_TAGDATA_HI],
1289 (long)cpu->cd.mips.coproc[0]->reg[COP0_TAGDATA_LO]);
1290 debug(" ]");
1291 break;
1292
1293 case HI6_SPECIAL2:
1294 special6 = instr[0] & 0x3f;
1295 instrword = (instr[3] << 24) + (instr[2] << 16) +
1296 (instr[1] << 8) + instr[0];
1297 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1298 rt = instr[2] & 31;
1299 rd = (instr[1] >> 3) & 31;
1300
1301 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
1302 int c790mmifunc = (instrword >> 6) & 0x1f;
1303 if (special6 != MMI_MMI0 && special6 != MMI_MMI1 &&
1304 special6 != MMI_MMI2 && special6 != MMI_MMI3)
1305 debug("%s\t", mmi_names[special6]);
1306
1307 switch (special6) {
1308
1309 case MMI_MADD:
1310 case MMI_MADDU:
1311 if (rd != MIPS_GPR_ZERO) {
1312 debug("%s,", regname(cpu->machine, rd));
1313 }
1314 debug("%s", regname(cpu->machine, rs));
1315 debug(",%s", regname(cpu->machine, rt));
1316 break;
1317
1318 case MMI_MMI0:
1319 debug("%s\t", mmi0_names[c790mmifunc]);
1320 switch (c790mmifunc) {
1321
1322 case MMI0_PEXTLB:
1323 case MMI0_PEXTLH:
1324 case MMI0_PEXTLW:
1325 case MMI0_PMAXH:
1326 case MMI0_PMAXW:
1327 case MMI0_PPACB:
1328 case MMI0_PPACH:
1329 case MMI0_PPACW:
1330 debug("%s", regname(cpu->machine, rd));
1331 debug(",%s", regname(cpu->machine, rs));
1332 debug(",%s", regname(cpu->machine, rt));
1333 break;
1334
1335 default:debug("(UNIMPLEMENTED)");
1336 }
1337 break;
1338
1339 case MMI_MMI1:
1340 debug("%s\t", mmi1_names[c790mmifunc]);
1341 switch (c790mmifunc) {
1342
1343 case MMI1_PEXTUB:
1344 case MMI1_PEXTUH:
1345 case MMI1_PEXTUW:
1346 case MMI1_PMINH:
1347 case MMI1_PMINW:
1348 debug("%s", regname(cpu->machine, rd));
1349 debug(",%s", regname(cpu->machine, rs));
1350 debug(",%s", regname(cpu->machine, rt));
1351 break;
1352
1353 default:debug("(UNIMPLEMENTED)");
1354 }
1355 break;
1356
1357 case MMI_MMI2:
1358 debug("%s\t", mmi2_names[c790mmifunc]);
1359 switch (c790mmifunc) {
1360
1361 case MMI2_PMFHI:
1362 case MMI2_PMFLO:
1363 debug("%s", regname(cpu->machine, rd));
1364 break;
1365
1366 case MMI2_PHMADH:
1367 case MMI2_PHMSBH:
1368 case MMI2_PINTH:
1369 case MMI2_PMADDH:
1370 case MMI2_PMADDW:
1371 case MMI2_PMSUBH:
1372 case MMI2_PMSUBW:
1373 case MMI2_PMULTH:
1374 case MMI2_PMULTW:
1375 case MMI2_PSLLVW:
1376 debug("%s", regname(cpu->machine, rd));
1377 debug(",%s", regname(cpu->machine, rs));
1378 debug(",%s", regname(cpu->machine, rt));
1379 break;
1380
1381 default:debug("(UNIMPLEMENTED)");
1382 }
1383 break;
1384
1385 case MMI_MMI3:
1386 debug("%s\t", mmi3_names[c790mmifunc]);
1387 switch (c790mmifunc) {
1388
1389 case MMI3_PMTHI:
1390 case MMI3_PMTLO:
1391 debug("%s", regname(cpu->machine, rs));
1392 break;
1393
1394 case MMI3_PINTEH:
1395 case MMI3_PMADDUW:
1396 case MMI3_PMULTUW:
1397 case MMI3_PNOR:
1398 case MMI3_POR:
1399 case MMI3_PSRAVW:
1400 debug("%s", regname(cpu->machine, rd));
1401 debug(",%s", regname(cpu->machine, rs));
1402 debug(",%s", regname(cpu->machine, rt));
1403 break;
1404
1405 default:debug("(UNIMPLEMENTED)");
1406 }
1407 break;
1408
1409 default:debug("(UNIMPLEMENTED)");
1410 }
1411 break;
1412 }
1413
1414 /* SPECIAL2: */
1415 debug("%s\t", special2_names[special6]);
1416
1417 switch (special6) {
1418
1419 case SPECIAL2_MADD:
1420 case SPECIAL2_MADDU:
1421 case SPECIAL2_MSUB:
1422 case SPECIAL2_MSUBU:
1423 if (rd != MIPS_GPR_ZERO) {
1424 debug("WEIRD_NONZERO_RD(%s),",
1425 regname(cpu->machine, rd));
1426 }
1427 debug("%s", regname(cpu->machine, rs));
1428 debug(",%s", regname(cpu->machine, rt));
1429 break;
1430
1431 case SPECIAL2_MUL:
1432 /* Apparently used both on R5900 and MIPS32: */
1433 debug("%s", regname(cpu->machine, rd));
1434 debug(",%s", regname(cpu->machine, rs));
1435 debug(",%s", regname(cpu->machine, rt));
1436 break;
1437
1438 case SPECIAL2_CLZ:
1439 case SPECIAL2_CLO:
1440 case SPECIAL2_DCLZ:
1441 case SPECIAL2_DCLO:
1442 debug("%s", regname(cpu->machine, rd));
1443 debug(",%s", regname(cpu->machine, rs));
1444 break;
1445
1446 default:
1447 debug("(UNIMPLEMENTED)");
1448 }
1449 break;
1450
1451 case HI6_REGIMM:
1452 regimm5 = instr[2] & 0x1f;
1453 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1454 imm = (instr[1] << 8) + instr[0];
1455 if (imm >= 32768)
1456 imm -= 65536;
1457
1458 switch (regimm5) {
1459
1460 case REGIMM_BLTZ:
1461 case REGIMM_BGEZ:
1462 case REGIMM_BLTZL:
1463 case REGIMM_BGEZL:
1464 case REGIMM_BLTZAL:
1465 case REGIMM_BLTZALL:
1466 case REGIMM_BGEZAL:
1467 case REGIMM_BGEZALL:
1468 debug("%s\t%s,", regimm_names[regimm5],
1469 regname(cpu->machine, rs));
1470
1471 addr = (dumpaddr + 4) + (imm << 2);
1472
1473 if (cpu->is_32bit)
1474 debug("0x%08"PRIx32, (uint32_t) addr);
1475 else
1476 debug("0x%016"PRIx64, (uint64_t) addr);
1477 break;
1478
1479 case REGIMM_SYNCI:
1480 debug("%s\t%i(%s)", regimm_names[regimm5],
1481 imm, regname(cpu->machine, rs));
1482 break;
1483
1484 default:
1485 debug("unimplemented regimm5 = 0x%02x", regimm5);
1486 }
1487 break;
1488 default:
1489 debug("unimplemented hi6 = 0x%02x", hi6);
1490 }
1491
1492 disasm_ret:
1493 debug("\n");
1494 return sizeof(instrword);
1495 }
1496
1497
1498 /*
1499 * mips_cpu_register_dump():
1500 *
1501 * Dump cpu registers in a relatively readable format.
1502 *
1503 * gprs: set to non-zero to dump GPRs and hi/lo/pc
1504 * coprocs: set bit 0..3 to dump registers in coproc 0..3.
1505 */
1506 void mips_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
1507 {
1508 int coprocnr, i, bits32;
1509 uint64_t offset;
1510 char *symbol;
1511 int bits128 = cpu->cd.mips.cpu_type.rev == MIPS_R5900;
1512
1513 bits32 = cpu->is_32bit;
1514
1515 if (gprs) {
1516 /* Special registers (pc, hi/lo) first: */
1517 symbol = get_symbol_name(&cpu->machine->symbol_context,
1518 cpu->pc, &offset);
1519
1520 if (bits32)
1521 debug("cpu%i: pc = %08"PRIx32,
1522 cpu->cpu_id, (uint32_t) cpu->pc);
1523 else if (bits128)
1524 debug("cpu%i: pc=%016"PRIx64,
1525 cpu->cpu_id, (uint64_t) cpu->pc);
1526 else
1527 debug("cpu%i: pc = 0x%016"PRIx64,
1528 cpu->cpu_id, (uint64_t) cpu->pc);
1529
1530 debug(" <%s>\n", symbol != NULL? symbol :
1531 " no symbol ");
1532
1533 if (bits32)
1534 debug("cpu%i: hi = %08"PRIx32" lo = %08"PRIx32"\n",
1535 cpu->cpu_id, (uint32_t) cpu->cd.mips.hi,
1536 (uint32_t) cpu->cd.mips.lo);
1537 else if (bits128) {
1538 debug("cpu%i: hi=%016"PRIx64"%016"PRIx64" lo="
1539 "%016"PRIx64"%016"PRIx64"\n", cpu->cpu_id,
1540 cpu->cd.mips.hi1, cpu->cd.mips.hi,
1541 cpu->cd.mips.lo1, cpu->cd.mips.lo);
1542 } else {
1543 debug("cpu%i: hi = 0x%016"PRIx64" lo = 0x%016"
1544 PRIx64"\n", cpu->cpu_id,
1545 (uint64_t) cpu->cd.mips.hi,
1546 (uint64_t) cpu->cd.mips.lo);
1547 }
1548
1549 /* General registers: */
1550 if (bits128) {
1551 /* 128-bit: */
1552 for (i=0; i<32; i++) {
1553 int r = (i >> 1) + ((i & 1) << 4);
1554 if ((i & 1) == 0)
1555 debug("cpu%i:", cpu->cpu_id);
1556 if (r == MIPS_GPR_ZERO)
1557 debug(" "
1558 " ");
1559 else
1560 debug(" %3s=%016"PRIx64"%016"PRIx64,
1561 regname(cpu->machine, r),
1562 (uint64_t)cpu->cd.mips.gpr_quadhi[r],
1563 (uint64_t)cpu->cd.mips.gpr[r]);
1564 if ((i & 1) == 1)
1565 debug("\n");
1566 }
1567 } else if (bits32) {
1568 /* 32-bit: */
1569 for (i=0; i<32; i++) {
1570 if ((i & 3) == 0)
1571 debug("cpu%i:", cpu->cpu_id);
1572 if (i == MIPS_GPR_ZERO)
1573 debug(" ");
1574 else
1575 debug(" %3s = %08"PRIx32,
1576 regname(cpu->machine, i),
1577 (uint32_t)cpu->cd.mips.gpr[i]);
1578 if ((i & 3) == 3)
1579 debug("\n");
1580 }
1581 } else {
1582 /* 64-bit: */
1583 for (i=0; i<32; i++) {
1584 int r = (i >> 1) + ((i & 1) << 4);
1585 if ((i & 1) == 0)
1586 debug("cpu%i:", cpu->cpu_id);
1587 if (r == MIPS_GPR_ZERO)
1588 debug(" ");
1589 else
1590 debug(" %3s = 0x%016"PRIx64,
1591 regname(cpu->machine, r),
1592 (uint64_t)cpu->cd.mips.gpr[r]);
1593 if ((i & 1) == 1)
1594 debug("\n");
1595 }
1596 }
1597 }
1598
1599 for (coprocnr=0; coprocnr<4; coprocnr++) {
1600 int nm1 = 1;
1601
1602 if (bits32)
1603 nm1 = 3;
1604
1605 if (!(coprocs & (1<<coprocnr)))
1606 continue;
1607 if (cpu->cd.mips.coproc[coprocnr] == NULL) {
1608 debug("cpu%i: no coprocessor %i\n",
1609 cpu->cpu_id, coprocnr);
1610 continue;
1611 }
1612
1613 /* Coprocessor registers: */
1614 for (i=0; i<32; i++) {
1615 /* 32-bit: */
1616 if ((i & nm1) == 0)
1617 debug("cpu%i:", cpu->cpu_id);
1618
1619 if (cpu->machine->show_symbolic_register_names &&
1620 coprocnr == 0)
1621 debug(" %8s", cop0_names[i]);
1622 else
1623 debug(" c%i,%02i", coprocnr, i);
1624
1625 if (bits32)
1626 debug("=%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]);
1627 else {
1628 if (coprocnr == 0 && (i == COP0_COUNT
1629 || i == COP0_COMPARE || i == COP0_INDEX
1630 || i == COP0_RANDOM || i == COP0_WIRED))
1631 debug(" = 0x%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]);
1632 else
1633 debug(" = 0x%016"PRIx64, (uint64_t)
1634 cpu->cd.mips.coproc[coprocnr]->reg[i]);
1635 }
1636
1637 if ((i & nm1) == nm1)
1638 debug("\n");
1639
1640 /* Skip the last 16 cop0 registers on R3000 etc. */
1641 if (coprocnr == 0 && cpu->cd.mips.cpu_type.isa_level < 3
1642 && i == 15)
1643 i = 31;
1644 }
1645
1646 if (coprocnr == 0 && cpu->cd.mips.cpu_type.isa_level >= 32) {
1647 debug("cpu%i: ", cpu->cpu_id);
1648 debug("config_select1 = 0x");
1649 if (cpu->is_32bit)
1650 debug("%08"PRIx32, (uint32_t)cpu->cd.mips.cop0_config_select1);
1651 else
1652 debug("%016"PRIx64, (uint64_t)cpu->cd.mips.cop0_config_select1);
1653 debug("\n");
1654 }
1655
1656 /* Floating point control registers: */
1657 if (coprocnr == 1) {
1658 for (i=0; i<32; i++)
1659 switch (i) {
1660 case MIPS_FPU_FCIR:
1661 printf("cpu%i: fcr0 (fcir) = 0x%08x\n",
1662 cpu->cpu_id, (int)cpu->cd.mips.
1663 coproc[coprocnr]->fcr[i]);
1664 break;
1665 case MIPS_FPU_FCCR:
1666 printf("cpu%i: fcr25 (fccr) = 0x%08x\n",
1667 cpu->cpu_id, (int)cpu->cd.mips.
1668 coproc[coprocnr]->fcr[i]);
1669 break;
1670 case MIPS_FPU_FCSR:
1671 printf("cpu%i: fcr31 (fcsr) = 0x%08x\n",
1672 cpu->cpu_id, (int)cpu->cd.mips.
1673 coproc[coprocnr]->fcr[i]);
1674 break;
1675 }
1676 }
1677 }
1678
1679 if (cpu->cd.mips.rmw) {
1680 printf("cpu%i: Read-Modify-Write in progress, address "
1681 "0x%016"PRIx64"\n", cpu->cpu_id, cpu->cd.mips.rmw_addr);
1682 }
1683 }
1684
1685
1686 static void add_response_word(struct cpu *cpu, char *r, uint64_t value,
1687 size_t maxlen, int len)
1688 {
1689 char *format = (len == 4)? "%08"PRIx64 : "%016"PRIx64;
1690 if (len == 4)
1691 value &= 0xffffffffULL;
1692 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
1693 if (len == 4) {
1694 value = ((value & 0xff) << 24) +
1695 ((value & 0xff00) << 8) +
1696 ((value & 0xff0000) >> 8) +
1697 ((value & 0xff000000) >> 24);
1698 } else {
1699 value = ((value & 0xff) << 56) +
1700 ((value & 0xff00) << 40) +
1701 ((value & 0xff0000) << 24) +
1702 ((value & 0xff000000ULL) << 8) +
1703 ((value & 0xff00000000ULL) >> 8) +
1704 ((value & 0xff0000000000ULL) >> 24) +
1705 ((value & 0xff000000000000ULL) >> 40) +
1706 ((value & 0xff00000000000000ULL) >> 56);
1707 }
1708 }
1709 snprintf(r + strlen(r), maxlen - strlen(r), format, (uint64_t)value);
1710 }
1711
1712
1713 /*
1714 * mips_cpu_gdb_stub():
1715 *
1716 * Execute a "remote GDB" command. Returns 1 on success, 0 on error.
1717 */
1718 char *mips_cpu_gdb_stub(struct cpu *cpu, char *cmd)
1719 {
1720 if (strcmp(cmd, "g") == 0) {
1721 /* 76 registers: gprs, sr, lo, hi, badvaddr, cause, pc,
1722 fprs, fsr, fir, fp. */
1723 int i;
1724 char *r;
1725 size_t wlen = cpu->is_32bit?
1726 sizeof(uint32_t) : sizeof(uint64_t);
1727 size_t len = 1 + 76 * wlen;
1728 r = malloc(len);
1729 if (r == NULL) {
1730 fprintf(stderr, "out of memory\n");
1731 exit(1);
1732 }
1733 r[0] = '\0';
1734 for (i=0; i<32; i++)
1735 add_response_word(cpu, r, cpu->cd.mips.gpr[i],
1736 len, wlen);
1737 add_response_word(cpu, r,
1738 cpu->cd.mips.coproc[0]->reg[COP0_STATUS], len, wlen);
1739 add_response_word(cpu, r, cpu->cd.mips.lo, len, wlen);
1740 add_response_word(cpu, r, cpu->cd.mips.hi, len, wlen);
1741 add_response_word(cpu, r,
1742 cpu->cd.mips.coproc[0]->reg[COP0_BADVADDR], len, wlen);
1743 add_response_word(cpu, r,
1744 cpu->cd.mips.coproc[0]->reg[COP0_CAUSE], len, wlen);
1745 add_response_word(cpu, r, cpu->pc, len, wlen);
1746 for (i=0; i<32; i++)
1747 add_response_word(cpu, r,
1748 cpu->cd.mips.coproc[1]->reg[i], len, wlen);
1749 add_response_word(cpu, r,
1750 cpu->cd.mips.coproc[1]->reg[31] /* fcsr */, len, wlen);
1751 add_response_word(cpu, r,
1752 cpu->cd.mips.coproc[1]->reg[0] /* fcir */, len, wlen);
1753
1754 /* TODO: fp = gpr 30? */
1755 add_response_word(cpu, r, cpu->cd.mips.gpr[30], len, wlen);
1756
1757 return r;
1758 }
1759
1760 if (cmd[0] == 'p') {
1761 int regnr = strtol(cmd + 1, NULL, 16);
1762 size_t wlen = cpu->is_32bit? sizeof(uint32_t):sizeof(uint64_t);
1763 size_t len = 2 * wlen + 1;
1764 char *r = malloc(len);
1765 r[0] = '\0';
1766 if (regnr >= 0 && regnr <= 31) {
1767 add_response_word(cpu, r,
1768 cpu->cd.mips.gpr[regnr], len, wlen);
1769 } else if (regnr == 0x20) {
1770 add_response_word(cpu, r, cpu->cd.mips.coproc[0]->
1771 reg[COP0_STATUS], len, wlen);
1772 } else if (regnr == 0x21) {
1773 add_response_word(cpu, r, cpu->cd.mips.lo, len, wlen);
1774 } else if (regnr == 0x22) {
1775 add_response_word(cpu, r, cpu->cd.mips.hi, len, wlen);
1776 } else if (regnr == 0x23) {
1777 add_response_word(cpu, r, cpu->cd.mips.coproc[0]->
1778 reg[COP0_BADVADDR], len, wlen);
1779 } else if (regnr == 0x24) {
1780 add_response_word(cpu, r, cpu->cd.mips.coproc[0]->
1781 reg[COP0_CAUSE], len, wlen);
1782 } else if (regnr == 0x25) {
1783 add_response_word(cpu, r, cpu->pc, len, wlen);
1784 } else if (regnr >= 0x26 && regnr <= 0x45 &&
1785 cpu->cd.mips.coproc[1] != NULL) {
1786 add_response_word(cpu, r, cpu->cd.mips.coproc[1]->
1787 reg[regnr - 0x26], len, wlen);
1788 } else if (regnr == 0x46) {
1789 add_response_word(cpu, r, cpu->cd.mips.coproc[1]->
1790 fcr[MIPS_FPU_FCSR], len, wlen);
1791 } else if (regnr == 0x47) {
1792 add_response_word(cpu, r, cpu->cd.mips.coproc[1]->
1793 fcr[MIPS_FPU_FCIR], len, wlen);
1794 } else {
1795 /* Unimplemented: */
1796 add_response_word(cpu, r, 0xcc000 + regnr, len, wlen);
1797 }
1798 return r;
1799 }
1800
1801 fatal("mips_cpu_gdb_stub(): cmd='%s' TODO\n", cmd);
1802 return NULL;
1803 }
1804
1805
1806 /*
1807 * mips_cpu_interrupt():
1808 *
1809 * Cause an interrupt. If irq_nr is 2..7, then it is a MIPS hardware
1810 * interrupt. 0 and 1 are ignored (software interrupts).
1811 *
1812 * If irq_nr is >= 8, then this function calls md_interrupt().
1813 */
1814 int mips_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
1815 {
1816 if (irq_nr >= 8) {
1817 if (cpu->machine->md_interrupt != NULL)
1818 cpu->machine->md_interrupt(cpu->machine,
1819 cpu, irq_nr, 1);
1820 else
1821 fatal("mips_cpu_interrupt(): irq_nr = %i, "
1822 "but md_interrupt = NULL ?\n", irq_nr);
1823 return 1;
1824 }
1825
1826 if (irq_nr < 2)
1827 return 0;
1828
1829 cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] |=
1830 ((1 << irq_nr) << STATUS_IM_SHIFT);
1831
1832 return 1;
1833 }
1834
1835
1836 /*
1837 * mips_cpu_interrupt_ack():
1838 *
1839 * Acknowledge an interrupt. If irq_nr is 2..7, then it is a MIPS hardware
1840 * interrupt. Interrupts 0..1 are ignored (software interrupts).
1841 *
1842 * If irq_nr is >= 8, then it is machine dependent, and md_interrupt() is
1843 * called.
1844 */
1845 int mips_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
1846 {
1847 if (irq_nr >= 8) {
1848 if (cpu->machine->md_interrupt != NULL)
1849 cpu->machine->md_interrupt(cpu->machine, cpu,
1850 irq_nr, 0);
1851 else
1852 fatal("mips_cpu_interrupt_ack(): irq_nr = %i, "
1853 "but md_interrupt = NULL ?\n", irq_nr);
1854 return 1;
1855 }
1856
1857 if (irq_nr < 2)
1858 return 0;
1859
1860 cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] &=
1861 ~((1 << irq_nr) << STATUS_IM_SHIFT);
1862
1863 return 1;
1864 }
1865
1866
1867 /*
1868 * mips_cpu_exception():
1869 *
1870 * Cause an exception in a CPU. This sets a couple of coprocessor 0
1871 * registers, and the program counter.
1872 *
1873 * exccode the exception code
1874 * tlb set to non-zero if the exception handler at
1875 * 0x80000000 should be used. (normal = 0x80000180)
1876 * vaddr virtual address (for some exceptions)
1877 * coproc_nr coprocessor number (for some exceptions)
1878 * vaddr_vpn2 vpn2 (for some exceptions)
1879 * vaddr_asid asid (for some exceptions)
1880 * x_64 non-zero for 64-bit mode for R4000-style tlb misses
1881 */
1882 void mips_cpu_exception(struct cpu *cpu, int exccode, int tlb, uint64_t vaddr,
1883 int coproc_nr, uint64_t vaddr_vpn2, int vaddr_asid, int x_64)
1884 {
1885 uint64_t base;
1886 uint64_t *reg = &cpu->cd.mips.coproc[0]->reg[0];
1887 int exc_model = cpu->cd.mips.cpu_type.exc_model;
1888
1889 if (cpu->is_halted) {
1890 /*
1891 * If the exception occurred on a 'wait' instruction, then let
1892 * the instruction following the wait instruction be the one
1893 * we continue at when the interrupt service routine returns.
1894 */
1895 cpu->is_halted = 0;
1896 cpu->pc += sizeof(uint32_t);
1897 }
1898
1899 if (!quiet_mode) {
1900 uint64_t offset;
1901 int x;
1902 char *symbol = get_symbol_name(&cpu->machine->symbol_context,
1903 cpu->pc, &offset);
1904
1905 debug("[ ");
1906 if (cpu->machine->ncpus > 1)
1907 debug("cpu%i: ", cpu->cpu_id);
1908
1909 debug("exception %s%s",
1910 exception_names[exccode], tlb? " <tlb>" : "");
1911
1912 switch (exccode) {
1913
1914 case EXCEPTION_INT:
1915 debug(" cause_im=0x%02x", (int)((reg[COP0_CAUSE] & CAUSE_IP_MASK) >> CAUSE_IP_SHIFT));
1916 break;
1917
1918 case EXCEPTION_SYS:
1919 debug(" v0=%i", (int)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1920 for (x=0; x<4; x++) {
1921 int64_t d = cpu->cd.mips.gpr[MIPS_GPR_A0 + x];
1922 char strbuf[30];
1923
1924 if (d > -256 && d < 256) {
1925 debug(" a%i=%i", x, (int)d);
1926 } else if (memory_points_to_string(cpu,
1927 cpu->mem, d, 1)) {
1928 debug(" a%i=\"%s\"", x,
1929 memory_conv_to_string(cpu, cpu->mem,
1930 d, strbuf, sizeof(strbuf)));
1931 } else {
1932 if (cpu->is_32bit)
1933 debug(" a%i=0x%"PRIx32, x,
1934 (uint32_t)d);
1935 else
1936 debug(" a%i=0x%"PRIx64, x,
1937 (uint64_t)d);
1938 }
1939 }
1940 break;
1941
1942 case EXCEPTION_CPU:
1943 debug(" coproc_nr=%i", coproc_nr);
1944 break;
1945
1946 default:
1947 if (cpu->is_32bit)
1948 debug(" vaddr=0x%08x", (int)vaddr);
1949 else
1950 debug(" vaddr=0x%016"PRIx64, (uint64_t)vaddr);
1951 }
1952
1953 if (cpu->is_32bit)
1954 debug(" pc=0x%08"PRIx32" ", (uint32_t)cpu->pc);
1955 else
1956 debug(" pc=0x%016"PRIx64" ", (uint64_t)cpu->pc);
1957
1958 if (symbol != NULL)
1959 debug("<%s> ]\n", symbol);
1960 else
1961 debug("]\n");
1962 }
1963
1964 if (tlb && vaddr < 0x1000) {
1965 uint64_t offset;
1966 char *symbol = get_symbol_name(&cpu->machine->symbol_context,
1967 cpu->pc, &offset);
1968 fatal("[ ");
1969 if (cpu->machine->ncpus > 1)
1970 fatal("cpu%i: ", cpu->cpu_id);
1971 fatal("warning: LOW reference: vaddr=");
1972 if (cpu->is_32bit)
1973 fatal("0x%08"PRIx32, (uint32_t) vaddr);
1974 else
1975 fatal("0x%016"PRIx64, (uint64_t) vaddr);
1976 fatal(", exception %s, pc=", exception_names[exccode]);
1977 if (cpu->is_32bit)
1978 fatal("0x%08"PRIx32, (uint32_t) cpu->pc);
1979 else
1980 fatal("0x%016"PRIx64, (uint64_t)cpu->pc);
1981 fatal(" <%s> ]\n", symbol? symbol : "(no symbol)");
1982 }
1983
1984 /* Clear the exception code bits of the cause register... */
1985 if (exc_model == EXC3K)
1986 reg[COP0_CAUSE] &= ~R2K3K_CAUSE_EXCCODE_MASK;
1987 else
1988 reg[COP0_CAUSE] &= ~CAUSE_EXCCODE_MASK;
1989
1990 /* ... and OR in the exception code: */
1991 reg[COP0_CAUSE] |= (exccode << CAUSE_EXCCODE_SHIFT);
1992
1993 /* Always set CE (according to the R5000 manual): */
1994 reg[COP0_CAUSE] &= ~CAUSE_CE_MASK;
1995 reg[COP0_CAUSE] |= (coproc_nr << CAUSE_CE_SHIFT);
1996
1997 if (tlb || (exccode >= EXCEPTION_MOD && exccode <= EXCEPTION_ADES) ||
1998 exccode == EXCEPTION_VCEI || exccode == EXCEPTION_VCED) {
1999 reg[COP0_BADVADDR] = vaddr;
2000 if (cpu->is_32bit)
2001 reg[COP0_BADVADDR] = (int32_t)reg[COP0_BADVADDR];
2002
2003 if (exc_model == EXC3K) {
2004 reg[COP0_CONTEXT] &= ~R2K3K_CONTEXT_BADVPN_MASK;
2005 reg[COP0_CONTEXT] |= ((vaddr_vpn2 << R2K3K_CONTEXT_BADVPN_SHIFT) & R2K3K_CONTEXT_BADVPN_MASK);
2006
2007 reg[COP0_ENTRYHI] = (vaddr & R2K3K_ENTRYHI_VPN_MASK)
2008 | (vaddr_asid << R2K3K_ENTRYHI_ASID_SHIFT);
2009
2010 /* Sign-extend: */
2011 reg[COP0_CONTEXT] = (int64_t)(int32_t)reg[COP0_CONTEXT];
2012 reg[COP0_ENTRYHI] = (int64_t)(int32_t)reg[COP0_ENTRYHI];
2013 } else {
2014 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
2015 reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK_R4100;
2016 reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK_R4100);
2017
2018 /* TODO: fix these */
2019 reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
2020 reg[COP0_XCONTEXT] &= ~XCONTEXT_BADVPN2_MASK;
2021 reg[COP0_XCONTEXT] |= (vaddr_vpn2 << XCONTEXT_BADVPN2_SHIFT) & XCONTEXT_BADVPN2_MASK;
2022 reg[COP0_XCONTEXT] |= ((vaddr >> 62) & 0x3) << XCONTEXT_R_SHIFT;
2023
2024 /* reg[COP0_PAGEMASK] = cpu->cd.mips.coproc[0]->tlbs[0].mask & PAGEMASK_MASK; */
2025
2026 reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK | 0x1800)) | vaddr_asid;
2027 } else {
2028 reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK;
2029 reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK);
2030
2031 reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
2032 reg[COP0_XCONTEXT] &= ~XCONTEXT_BADVPN2_MASK;
2033 reg[COP0_XCONTEXT] |= (vaddr_vpn2 << XCONTEXT_BADVPN2_SHIFT) & XCONTEXT_BADVPN2_MASK;
2034 reg[COP0_XCONTEXT] |= ((vaddr >> 62) & 0x3) << XCONTEXT_R_SHIFT;
2035
2036 /* reg[COP0_PAGEMASK] = cpu->cd.mips.coproc[0]->tlbs[0].mask & PAGEMASK_MASK; */
2037
2038 if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
2039 reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K)) | vaddr_asid;
2040 else
2041 reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK)) | vaddr_asid;
2042 }
2043 }
2044 }
2045
2046 if (exc_model != EXC3K && reg[COP0_STATUS] & STATUS_EXL) {
2047 /*
2048 * Don't set EPC if STATUS_EXL is set, for R4000 and up.
2049 * This actually happens when running IRIX and Ultrix, when
2050 * they handle interrupts and/or tlb updates, I think, so
2051 * printing this with debug() looks better than with fatal().
2052 */
2053 /* debug("[ warning: cpu%i exception while EXL is set,"
2054 " not setting EPC ]\n", cpu->cpu_id); */
2055 } else {
2056 if (cpu->delay_slot) {
2057 reg[COP0_EPC] = cpu->pc - 4;
2058 reg[COP0_CAUSE] |= CAUSE_BD;
2059 } else {
2060 reg[COP0_EPC] = cpu->pc;
2061 reg[COP0_CAUSE] &= ~CAUSE_BD;
2062 }
2063 }
2064
2065 if (cpu->delay_slot)
2066 cpu->delay_slot = EXCEPTION_IN_DELAY_SLOT;
2067 else
2068 cpu->delay_slot = NOT_DELAYED;
2069
2070 /* TODO: This is true for MIPS64, but how about others? */
2071 if (reg[COP0_STATUS] & STATUS_BEV)
2072 base = 0xffffffffbfc00200ULL;
2073 else
2074 base = 0xffffffff80000000ULL;
2075
2076 switch (exc_model) {
2077 case EXC3K:
2078 /* Userspace tlb, vs others: */
2079 if (tlb && !(vaddr & 0x80000000ULL) &&
2080 (exccode == EXCEPTION_TLBL || exccode == EXCEPTION_TLBS) )
2081 cpu->pc = base + 0x000;
2082 else
2083 cpu->pc = base + 0x080;
2084 break;
2085 default:
2086 /*
2087 * These offsets are according to the MIPS64 manual, but
2088 * should work with R4000 and the rest too (I hope).
2089 *
2090 * 0x000 TLB refill, if EXL=0
2091 * 0x080 64-bit XTLB refill, if EXL=0
2092 * 0x100 cache error (not implemented yet)
2093 * 0x180 general exception
2094 * 0x200 interrupt (if CAUSE_IV is set)
2095 */
2096 if (tlb && (exccode == EXCEPTION_TLBL ||
2097 exccode == EXCEPTION_TLBS) &&
2098 !(reg[COP0_STATUS] & STATUS_EXL)) {
2099 if (x_64)
2100 cpu->pc = base + 0x080;
2101 else
2102 cpu->pc = base + 0x000;
2103 } else {
2104 if (exccode == EXCEPTION_INT &&
2105 (reg[COP0_CAUSE] & CAUSE_IV))
2106 cpu->pc = base + 0x200;
2107 else
2108 cpu->pc = base + 0x180;
2109 }
2110 }
2111
2112 if (exc_model == EXC3K) {
2113 /* R{2,3}000: Shift the lowest 6 bits to the left two steps:*/
2114 reg[COP0_STATUS] = (reg[COP0_STATUS] & ~0x3f) +
2115 ((reg[COP0_STATUS] & 0xf) << 2);
2116 } else {
2117 /* R4000: */
2118 reg[COP0_STATUS] |= STATUS_EXL;
2119 }
2120
2121 /* Sign-extend: */
2122 reg[COP0_CAUSE] = (int64_t)(int32_t)reg[COP0_CAUSE];
2123 reg[COP0_STATUS] = (int64_t)(int32_t)reg[COP0_STATUS];
2124
2125 if (cpu->is_32bit) {
2126 reg[COP0_EPC] = (int64_t)(int32_t)reg[COP0_EPC];
2127 mips32_pc_to_pointers(cpu);
2128 } else {
2129 mips_pc_to_pointers(cpu);
2130 }
2131 }
2132
2133
2134 #include "memory_mips.c"
2135
2136
2137 #include "tmp_mips_tail.c"
2138

  ViewVC Help
Powered by ViewVC 1.1.26