/[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 24 - (show annotations)
Mon Oct 8 16:19:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 56941 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1256 2006/06/23 20:43:44 debug Exp $
20060219	Various minor updates. Removing the old MIPS16 skeleton code,
		because it will need to be rewritten for dyntrans anyway.
20060220-22	Removing the non-working dyntrans backend support.
		Continuing on the 64-bit dyntrans virtual memory generalization.
20060223	More work on the 64-bit vm generalization.
20060225	Beginning on MIPS dyntrans load/store instructions.
		Minor PPC updates (64-bit load/store, etc).
		Fixes for the variable-instruction-length framework, some
		minor AVR updates (a simple Hello World program works!).
		Beginning on a skeleton for automatically generating documen-
		tation (for devices etc.).
20060226	PPC updates (adding some more 64-bit instructions, etc).
		AVR updates (more instructions).
		FINALLY found and fixed the zs bug, making NetBSD/macppc
		accept the serial console.
20060301	Adding more AVR instructions.
20060304	Continuing on AVR-related stuff. Beginning on a framework for
		cycle-accurate device emulation. Adding an experimental "PAL
		TV" device (just a dummy so far).
20060305	Adding more AVR instructions.
		Adding a dummy epcom serial controller (for TS7200 emulation).
20060310	Removing the emul() command from configuration files, so only
		net() and machine() are supported.
		Minor progress on the MIPS dyntrans rewrite.
20060311	Continuing on the MIPS dyntrans rewrite (adding more
		instructions, etc).
20060315	Adding more instructions (sllv, srav, srlv, bgtz[l], blez[l],
		beql, bnel, slti[u], various loads and stores).
20060316	Removing the ALWAYS_SIGNEXTEND_32 option, since it was rarely
		used.
		Adding more MIPS dyntrans instructions, and fixing bugs.
20060318	Implementing fast loads/stores for MIPS dyntrans (big/little
		endian, 32-bit and 64-bit modes).
20060320	Making MIPS dyntrans the default configure option; use
		"--enable-oldmips" to use the old bintrans system.
		Adding MIPS dyntrans dmult[u]; minor updates.
20060322	Continuing... adding some more instructions.
		Adding a simple skeleton for demangling C++ "_ZN" symbols.
20060323	Moving src/debugger.c into a new directory (src/debugger/).
20060324	Fixing the hack used to load PPC ELFs (useful for relocated
		Linux/ppc kernels), and adding a dummy G3 machine mode.
20060325-26	Beginning to experiment with GDB remote serial protocol
		connections; adding a -G command line option for selecting
		which TCP port to listen to.
20060330	Beginning a major cleanup to replace things like "0x%016llx"
		with more correct "0x%016"PRIx64, etc.
		Continuing on the GDB remote serial protocol support.
20060331	More cleanup, and some minor GDB remote progress.
20060402	Adding a hack to the configure script, to allow compilation
		on systems that lack PRIx64 etc.
20060406	Removing the temporary FreeBSD/arm hack in dev_ns16550.c and
		replacing it with a better fix from Olivier Houchard.
20060407	A remote debugger (gdb or ddd) can now start and stop the
		emulator using the GDB remote serial protocol, and registers
		and memory can be read. MIPS only for now.
20060408	More GDB progress: single-stepping also works, and also adding
		support for ARM, PowerPC, and Alpha targets.
		Continuing on the delay-slot-across-page-boundary issue.
20060412	Minor update: beginning to add support for the SPARC target
		to the remote GDB functionality.
20060414	Various MIPS updates: adding more instructions for dyntrans
		(eret, add), and making some exceptions work. Fixing a bug
		in dmult[u].
		Implementing the first SPARC instructions (sethi, or).
20060415	Adding "magic trap" instructions so that PROM calls can be
		software emulated in MIPS dyntrans.
		Adding more MIPS dyntrans instructions (ddiv, dadd) and
		fixing another bug in dmult.
20060416	More MIPS dyntrans progress: adding [d]addi, movn, movz, dsllv,
		rfi, an ugly hack for supporting R2000/R3000 style faked caches,
		preliminary interrupt support, and various other updates and
		bugfixes.
20060417	Adding more SPARC instructions (add, sub, sll[x], sra[x],
		srl[x]), and useful SPARC header definitions.
		Adding the first (trivial) x86/AMD64 dyntrans instructions (nop,
		cli/sti, stc/clc, std/cld, simple mov, inc ax). Various other
		x86 updates related to variable instruction length stuff.
		Adding unaligned loads/stores to the MIPS dyntrans mode (but
		still using the pre-dyntrans (slow) imlementation).
20060419	Fixing a MIPS dyntrans exception-in-delay-slot bug.
		Removing the old "show opcode statistics" functionality, since
		it wasn't really useful and isn't implemented for dyntrans.
		Single-stepping (or running with instruction trace) now looks
		ok with dyntrans with delay-slot architectures.
20060420	Minor hacks (removing the -B command line option when compiled
		for non-bintrans, and some other very minor updates).
		Adding (slow) MIPS dyntrans load-linked/store-conditional.
20060422	Applying fixes for bugs discovered by Nils Weller's nwcc
		(static DEC memmap => now per machine, and adding an extern
		keyword in cpu_arm_instr.c).
		Finally found one of the MIPS dyntrans bugs that I've been
		looking for (copy/paste spelling error BIG vs LITTLE endian in
		cpu_mips_instr_loadstore.c for 16-bit fast stores).
		FINALLY found the major MIPS dyntrans bug: slti vs sltiu
		signed/unsigned code in cpu_mips_instr.c. :-)
		Adding more MIPS dyntrans instructions (lwc1, swc1, bgezal[l],
		ctc1, tlt[u], tge[u], tne, beginning on rdhwr).
		NetBSD/hpcmips can now reach userland when using dyntrans :-)
		Adding some more x86 dyntrans instructions.
		Finally removed the old Alpha-specific virtual memory code,
		and replaced it with the generic 64-bit version.
		Beginning to add disassembly support for SPECIAL3 MIPS opcodes.
20060423	Continuing on the delay-slot-across-page-boundary issue;
		adding an end_of_page2 ic slot (like I had planned before, but
		had removed for some reason).
		Adding a quick-and-dirty fallback to legacy coprocessor 1
		code (i.e. skipping dyntrans implementation for now).
		NetBSD/hpcmips and NetBSD/pmax (when running on an emulated
		R4400) can now be installed and run. :-)  (Many bugs left
		to fix, though.)
		Adding more MIPS dyntrans instructions: madd[u], msub[u].
		Cleaning up the SPECIAL2 vs R5900/TX79/C790 "MMI" opcode
		maps somewhat (disassembly and dyntrans instruction decoding).
20060424	Adding an isa_revision field to mips_cpu_types.h, and making
		sure that SPECIAL3 opcodes cause Reserved Instruction
		exceptions on MIPS32/64 revisions lower than 2.
		Adding the SPARC 'ba', 'call', 'jmpl/retl', 'and', and 'xor'
		instructions.
20060425	Removing the -m command line option ("run at most x 
		instructions") and -T ("single_step_on_bad_addr"), because
		they never worked correctly with dyntrans anyway.
		Freshening up the man page.
20060428	Adding more MIPS dyntrans instructions: bltzal[l], idle.
		Enabling MIPS dyntrans compare interrupts.
20060429	FINALLY found the weird dyntrans bug, causing NetBSD etc. to
		behave strangely: some floating point code (conditional
		coprocessor branches) could not be reused from the old
		non-dyntrans code. The "quick-and-dirty fallback" only appeared
		to work. Fixing by implementing bc1* for MIPS dyntrans.
		More MIPS instructions: [d]sub, sdc1, ldc1, dmtc1, dmfc1, cfc0.
		Freshening up MIPS floating point disassembly appearance.
20060430	Continuing on C790/R5900/TX79 disassembly; implementing 128-bit
		"por" and "pextlw".
20060504	Disabling -u (userland emulation) unless compiled as unstable
		development version.
		Beginning on freshening up the testmachine include files,
		to make it easier to reuse those files (placing them in
		src/include/testmachine/), and beginning on a set of "demos"
		or "tutorials" for the testmachine functionality.
		Minor updates to the MIPS GDB remote protocol stub.
		Refreshing doc/experiments.html and gdb_remote.html.
		Enabling Alpha emulation in the stable release configuration,
		even though no guest OSes for Alpha can run yet.
20060505	Adding a generic 'settings' object, which will contain
		references to settable variables (which will later be possible
		to access using the debugger).
20060506	Updating dev_disk and corresponding demo/documentation (and
		switching from SCSI to IDE disk types, so it actually works
		with current test machines :-).
20060510	Adding a -D_LARGEFILE_SOURCE hack for 64-bit Linux hosts,
		so that fseeko() doesn't give a warning.
		Updating the section about how dyntrans works (the "runnable
		IR") in doc/intro.html.
		Instruction updates (some x64=1 checks, some more R5900
		dyntrans stuff: better mul/mult separation from MIPS32/64,
		adding ei and di).
		Updating MIPS cpuregs.h to a newer one (from NetBSD).
		Adding more MIPS dyntrans instructions: deret, ehb.
20060514	Adding disassembly and beginning implementation of SPARC wr
		and wrpr instructions.
20060515	Adding a SUN SPARC machine mode, with dummy SS20 and Ultra1
		machines. Adding the 32-bit "rd psr" instruction.
20060517	Disassembly support for the general SPARC rd instruction.
		Partial implementation of the cmp (subcc) instruction.
		Some other minor updates (making sure that R5900 processors
		start up with the EIE bit enabled, otherwise Linux/playstation2
		receives no interrupts).
20060519	Minor MIPS updates/cleanups.
20060521	Moving the MeshCube machine into evbmips; this seems to work
		reasonably well with a snapshot of a NetBSD MeshCube kernel.
		Cleanup/fix of MIPS config0 register initialization.
20060529	Minor MIPS fixes, including a sign-extension fix to the
		unaligned load/store code, which makes NetBSD/pmax on R3000
		work better with dyntrans. (Ultrix and Linux/DECstation still
		don't work, though.)
20060530	Minor updates to the Alpha machine mode: adding an AlphaBook
		mode, an LCA bus (forwarding accesses to an ISA bus), etc.
20060531	Applying a bugfix for the MIPS dyntrans sc[d] instruction from
		Ondrej Palkovsky. (Many thanks.)
20060601	Minifix to allow ARM immediate msr instruction to not give
		an error for some valid values.
		More Alpha updates.
20060602	Some minor Alpha updates.
20060603	Adding the Alpha cmpbge instruction. NetBSD/alpha prints its
		first boot messages :-) on an emulated Alphabook 1.
20060612	Minor updates; adding a dev_ether.h include file for the
		testmachine ether device. Continuing the hunt for the dyntrans
		bug which makes Linux and Ultrix on DECstation behave
		strangely... FINALLY found it! It seems to be related to
		invalidation of the translation cache, on tlbw{r,i}. There
		also seems to be some remaining interrupt-related problems.
20060614	Correcting the implementation of ldc1/sdc1 for MIPS dyntrans
		(so that it uses 16 32-bit registers if the FR bit in the
		status register is not set).
20060616	REMOVING BINTRANS COMPLETELY!
		Removing the old MIPS interpretation mode.
		Removing the MFHILO_DELAY and instruction delay stuff, because
		they wouldn't work with dyntrans anyway.
20060617	Some documentation updates (adding "NetBSD-archive" to some
		URLs, and new Debian/DECstation installation screenshots).
		Removing the "tracenull" and "enable-caches" configure options.
		Improving MIPS dyntrans performance somewhat (only invalidate
		translations if necessary, on writes to the entryhi register,
		instead of doing it for all cop0 writes).
20060618	More cleanup after the removal of the old MIPS emulation.
		Trying to fix the MIPS dyntrans performance bugs/bottlenecks;
		only semi-successful so far (for R3000).
20060620	Minor update to allow clean compilation again on Tru64/Alpha.
20060622	MIPS cleanup and fixes (removing the pc_last stuff, which
		doesn't make sense with dyntrans anyway, and fixing a cross-
		page-delay-slot-with-exception case in end_of_page).
		Removing the old max_random_cycles_per_chunk stuff, and the
		concept of cycles vs instructions for MIPS emulation.
		FINALLY found and fixed the bug which caused NetBSD/pmax
		clocks to behave strangely (it was a load to the zero register,
		which was treated as a NOP; now it is treated as a load to a
		dummy scratch register).
20060623	Increasing the dyntrans chunk size back to
		N_SAFE_DYNTRANS_LIMIT, instead of N_SAFE_DYNTRANS_LIMIT/2.
		Preparing for a quick release, even though there are known
		bugs, and performance for non-R3000 MIPS emulation is very
		poor. :-/
		Reverting to half the dyntrans chunk size again, because
		NetBSD/cats seemed less stable with full size chunks. :(
		NetBSD/sgimips 3.0 can now run :-)  (With release 0.3.8, only
		NetBSD/sgimips 2.1 worked, not 3.0.)

==============  RELEASE 0.4.0  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26