/[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

Annotation of /trunk/src/cpus/cpu_mips.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 24 - (hide 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 dpavlin 14 /*
2 dpavlin 22 * Copyright (C) 2003-2006 Anders Gavare. All rights reserved.
3 dpavlin 14 *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 24 * $Id: cpu_mips.c,v 1.56 2006/06/22 13:22:41 debug Exp $
29 dpavlin 14 *
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 dpavlin 24 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 dpavlin 14
74     static char *regnames[] = MIPS_REGISTER_NAMES;
75     static char *cop0_names[] = COP0_NAMES;
76    
77    
78 dpavlin 22 #define DYNTRANS_DUALMODE_32
79     #define DYNTRANS_DELAYSLOT
80     #include "tmp_mips_head.c"
81    
82 dpavlin 24 void mips_pc_to_pointers(struct cpu *);
83     void mips32_pc_to_pointers(struct cpu *);
84 dpavlin 22
85 dpavlin 24
86 dpavlin 14 /*
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 dpavlin 24 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 dpavlin 14 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 dpavlin 24 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 dpavlin 14 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 dpavlin 24 mips_init_64bit_dummy_tables(cpu);
328 dpavlin 14
329     return 1;
330     }
331    
332    
333     /*
334 dpavlin 22 * 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 dpavlin 24 debug("\n%i-bit %s-endian (MIPS",
346 dpavlin 22 cpu->is_32bit? 32 : 64,
347 dpavlin 24 cpu->byte_order == EMUL_BIG_ENDIAN? "Big" : "Little");
348 dpavlin 22
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 dpavlin 24 case 64:debug("%i, revision %i", ct->isa_level, ct->isa_revision);
357     break;
358 dpavlin 22 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 dpavlin 24 * mips_cpu_instruction_has_delayslot():
431 dpavlin 14 *
432 dpavlin 24 * Return 1 if an opcode is a branch, 0 otherwise.
433 dpavlin 14 */
434 dpavlin 24 int mips_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib)
435 dpavlin 14 {
436 dpavlin 24 uint32_t iword = *((uint32_t *)&ib[0]);
437 dpavlin 14
438 dpavlin 24 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
439     iword = LE32_TO_HOST(iword);
440     else
441     iword = BE32_TO_HOST(iword);
442 dpavlin 14
443 dpavlin 24 switch (iword >> 26) {
444     case HI6_SPECIAL:
445     switch (iword & 0x3f) {
446     case SPECIAL_JR:
447     case SPECIAL_JALR:
448     return 1;
449 dpavlin 14 }
450 dpavlin 24 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 dpavlin 14
477 dpavlin 24 return 0;
478 dpavlin 14 }
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 dpavlin 22 /* Raw output: */
495     if (rawflag) {
496 dpavlin 14 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 dpavlin 22 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 dpavlin 24 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 dpavlin 22 cd.mips.coproc[0]->reg[COP0_RANDOM]);
514    
515     if (m->cpus[i]->cd.mips.cpu_type.isa_level >= 3)
516 dpavlin 24 printf(" wired=0x%"PRIx64, (uint64_t) m->cpus
517 dpavlin 22 [i]->cd.mips.coproc[0]->reg[COP0_WIRED]);
518    
519 dpavlin 14 printf(")\n");
520    
521     for (j=0; j<m->cpus[i]->cd.mips.cpu_type.
522     nr_of_tlb_entries; j++) {
523 dpavlin 22 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 dpavlin 24 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 dpavlin 14 }
543     }
544     return;
545     }
546    
547 dpavlin 22 /* Nicely formatted output: */
548 dpavlin 14 for (i=0; i<m->ncpus; i++) {
549 dpavlin 22 int pageshift = 12;
550    
551 dpavlin 14 if (x >= 0 && i != x)
552     continue;
553    
554 dpavlin 22 if (m->cpus[i]->cd.mips.cpu_type.rev == MIPS_R4100)
555     pageshift = 10;
556    
557 dpavlin 14 /* Print index, random, and wired: */
558     printf("cpu%i: (", i);
559 dpavlin 22 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 dpavlin 24 printf(" wired=0x%"PRIx64, (uint64_t)
575     m->cpus[i]->cd.mips.coproc[0]->reg[COP0_WIRED]);
576 dpavlin 22 }
577 dpavlin 14
578     printf(")\n");
579    
580 dpavlin 22 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 dpavlin 24 printf("vaddr=0x%1x..%011"PRIx64" ",
614     (int) (hi >> 60), (uint64_t)
615 dpavlin 22 (hi&ENTRYHI_VPN2_MASK_R10K));
616     break;
617     case MMU32:
618 dpavlin 24 printf("vaddr=0x%08"PRIx32" ",
619     (uint32_t)(hi&ENTRYHI_VPN2_MASK));
620 dpavlin 22 break;
621     default:/* R4000 etc. */
622 dpavlin 24 printf("vaddr=0x%1x..%010"PRIx64" ",
623 dpavlin 22 (int) (hi >> 60),
624 dpavlin 24 (uint64_t) (hi&ENTRYHI_VPN2_MASK));
625 dpavlin 22 }
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 dpavlin 24 printf(" p0=0x%09"PRIx64" ", (uint64_t)
638 dpavlin 22 (((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 dpavlin 24 printf(" p1=0x%09"PRIx64" ", (uint64_t)
646 dpavlin 22 (((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 dpavlin 14 }
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 dpavlin 24 if (m->cpus[cpunr]->delay_slot) {
686 dpavlin 14 printf("NOTE: Clearing the delay slot"
687     " flag! (It was set before.)\n");
688 dpavlin 24 m->cpus[cpunr]->delay_slot = 0;
689 dpavlin 14 }
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 dpavlin 24 if (cpu->delay_slot) {
769 dpavlin 14 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 dpavlin 24 int running, uint64_t dumpaddr)
798 dpavlin 14 {
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 dpavlin 24 debug("%08"PRIx32, (uint32_t)dumpaddr);
822 dpavlin 14 else
823 dpavlin 24 debug("%016"PRIx64, (uint64_t)dumpaddr);
824 dpavlin 14
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 dpavlin 24 else if (sa == 3)
880     debug("ehb");
881 dpavlin 14 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 dpavlin 24 if (cpu->is_32bit && (special6 == SPECIAL_ADDU ||
954     special6 == SPECIAL_SUBU) && rt == 0) {
955     /* Special case 1: addu/subu with
956 dpavlin 14 rt = the zero register ==> move */
957     debug("move\t%s", regname(cpu->machine, rd));
958     debug(",%s", regname(cpu->machine, rs));
959 dpavlin 24 } else if (special6 == SPECIAL_ADDU && cpu->is_32bit
960     && rs == 0) {
961     /* Special case 2: addu with
962 dpavlin 14 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 dpavlin 24 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 dpavlin 14 }
1001     }
1002 dpavlin 24 debug("%s", regname(cpu->machine, rs));
1003 dpavlin 14 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 dpavlin 24 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 dpavlin 14 break;
1033     case SPECIAL_MTSA:
1034 dpavlin 24 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 dpavlin 14 break;
1042     default:
1043 dpavlin 24 debug("%s\t= UNIMPLEMENTED", special_names[special6]);
1044 dpavlin 14 }
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 dpavlin 22 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 dpavlin 14 }
1075    
1076     if (cpu->is_32bit)
1077 dpavlin 24 debug("0x%08"PRIx32, (uint32_t)addr);
1078 dpavlin 14 else
1079 dpavlin 24 debug("0x%016"PRIx64, (uint64_t)addr);
1080 dpavlin 14
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 dpavlin 24 case HI6_SQ_SPECIAL3:
1132 dpavlin 14 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 dpavlin 24 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 dpavlin 14 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 dpavlin 24 debug("\t[0x%016"PRIx64" = %s]",
1189     (uint64_t)(cpu->cd.mips.gpr[rs] + imm));
1190 dpavlin 14 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 dpavlin 24 debug("0x%08"PRIx32,
1214     (uint32_t) (cpu->cd.mips.gpr[rs] + imm));
1215 dpavlin 14 else
1216 dpavlin 24 debug("0x%016"PRIx64,
1217     (uint64_t) (cpu->cd.mips.gpr[rs] + imm));
1218 dpavlin 14
1219     if (symbol != NULL)
1220     debug(" = %s", symbol);
1221    
1222 dpavlin 24 /* 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 dpavlin 14 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 dpavlin 24 debug("%08"PRIx32, (uint32_t) addr);
1241 dpavlin 14 else
1242 dpavlin 24 debug("%016"PRIx64, (uint64_t) addr);
1243 dpavlin 14 if (symbol != NULL)
1244     debug("\t<%s>", symbol);
1245     break;
1246 dpavlin 24
1247 dpavlin 14 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 dpavlin 24
1260 dpavlin 14 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 dpavlin 24 debug(", addr 0x%016"PRIx64,
1284     (uint64_t)(cpu->cd.mips.gpr[rt] + imm));
1285 dpavlin 14 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 dpavlin 24
1292 dpavlin 14 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 dpavlin 24
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 dpavlin 14 debug(",%s", regname(cpu->machine, rt));
1428 dpavlin 24 break;
1429    
1430     case SPECIAL2_MUL:
1431 dpavlin 22 /* Apparently used both on R5900 and MIPS32: */
1432 dpavlin 24 debug("%s", regname(cpu->machine, rd));
1433 dpavlin 14 debug(",%s", regname(cpu->machine, rs));
1434     debug(",%s", regname(cpu->machine, rt));
1435 dpavlin 24 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 dpavlin 14 debug(",%s", regname(cpu->machine, rs));
1443 dpavlin 24 break;
1444    
1445     default:
1446     debug("(UNIMPLEMENTED)");
1447 dpavlin 14 }
1448     break;
1449 dpavlin 24
1450 dpavlin 14 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 dpavlin 24 debug("0x%08"PRIx32, (uint32_t) addr);
1473 dpavlin 14 else
1474 dpavlin 24 debug("0x%016"PRIx64, (uint64_t) addr);
1475 dpavlin 14 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 dpavlin 24 int bits128 = cpu->cd.mips.cpu_type.rev == MIPS_R5900;
1504 dpavlin 14
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 dpavlin 24 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 dpavlin 14 else
1519 dpavlin 24 debug("cpu%i: pc = 0x%016"PRIx64,
1520     cpu->cpu_id, (uint64_t) cpu->pc);
1521 dpavlin 14
1522     debug(" <%s>\n", symbol != NULL? symbol :
1523     " no symbol ");
1524    
1525     if (bits32)
1526 dpavlin 24 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 dpavlin 14
1541     /* General registers: */
1542 dpavlin 24 if (bits128) {
1543 dpavlin 14 /* 128-bit: */
1544     for (i=0; i<32; i++) {
1545 dpavlin 24 int r = (i >> 1) + ((i & 1) << 4);
1546 dpavlin 14 if ((i & 1) == 0)
1547     debug("cpu%i:", cpu->cpu_id);
1548 dpavlin 24 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 dpavlin 14 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 dpavlin 24 debug(" %3s = %08"PRIx32,
1568     regname(cpu->machine, i),
1569     (uint32_t)cpu->cd.mips.gpr[i]);
1570 dpavlin 14 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 dpavlin 24 debug(" %3s = 0x%016"PRIx64,
1583     regname(cpu->machine, r),
1584     (uint64_t)cpu->cd.mips.gpr[r]);
1585 dpavlin 14 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 dpavlin 24 debug(" = 0x%016"PRIx64, (uint64_t)
1627 dpavlin 14 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 dpavlin 24 debug("%08"PRIx32, (uint32_t)cpu->cd.mips.cop0_config_select1);
1644 dpavlin 14 else
1645 dpavlin 24 debug("%016"PRIx64, (uint64_t)cpu->cd.mips.cop0_config_select1);
1646 dpavlin 14 debug("\n");
1647     }
1648    
1649     /* Floating point control registers: */
1650     if (coprocnr == 1) {
1651     for (i=0; i<32; i++)
1652     switch (i) {
1653 dpavlin 24 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 dpavlin 14 break;
1658 dpavlin 24 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 dpavlin 14 break;
1663 dpavlin 24 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 dpavlin 14 break;
1668     }
1669     }
1670     }
1671 dpavlin 24
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 dpavlin 14 }
1677    
1678    
1679 dpavlin 24 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 dpavlin 22
1705 dpavlin 14
1706 dpavlin 24 /*
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 dpavlin 14
1747 dpavlin 24 /* TODO: fp = gpr 30? */
1748     add_response_word(cpu, r, cpu->cd.mips.gpr[30], len, wlen);
1749 dpavlin 22
1750 dpavlin 24 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 dpavlin 14 /*
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 dpavlin 24 cpu->machine->md_interrupt(cpu->machine,
1812     cpu, irq_nr, 1);
1813 dpavlin 14 else
1814 dpavlin 24 fatal("mips_cpu_interrupt(): irq_nr = %i, "
1815     "but md_interrupt = NULL ?\n", irq_nr);
1816 dpavlin 14 return 1;
1817     }
1818    
1819     if (irq_nr < 2)
1820     return 0;
1821    
1822 dpavlin 24 cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] |=
1823     ((1 << irq_nr) << STATUS_IM_SHIFT);
1824    
1825 dpavlin 14 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 dpavlin 18 * If irq_nr is >= 8, then it is machine dependent, and md_interrupt() is
1836 dpavlin 14 * 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 dpavlin 24 cpu->machine->md_interrupt(cpu->machine, cpu,
1843     irq_nr, 0);
1844 dpavlin 14 else
1845 dpavlin 24 fatal("mips_cpu_interrupt_ack(): irq_nr = %i, "
1846     "but md_interrupt = NULL ?\n", irq_nr);
1847 dpavlin 14 return 1;
1848     }
1849    
1850     if (irq_nr < 2)
1851     return 0;
1852    
1853 dpavlin 24 cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] &=
1854     ~((1 << irq_nr) << STATUS_IM_SHIFT);
1855 dpavlin 14
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 dpavlin 24 cpu->pc, &offset);
1887 dpavlin 14
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 dpavlin 24
1897 dpavlin 14 case EXCEPTION_INT:
1898     debug(" cause_im=0x%02x", (int)((reg[COP0_CAUSE] & CAUSE_IP_MASK) >> CAUSE_IP_SHIFT));
1899     break;
1900 dpavlin 24
1901 dpavlin 14 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 dpavlin 24 if (d > -256 && d < 256) {
1908 dpavlin 14 debug(" a%i=%i", x, (int)d);
1909 dpavlin 24 } 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 dpavlin 14 }
1923     break;
1924 dpavlin 24
1925     case EXCEPTION_CPU:
1926     debug(" coproc_nr=%i", coproc_nr);
1927     break;
1928    
1929 dpavlin 14 default:
1930     if (cpu->is_32bit)
1931     debug(" vaddr=0x%08x", (int)vaddr);
1932     else
1933 dpavlin 24 debug(" vaddr=0x%016"PRIx64, (uint64_t)vaddr);
1934 dpavlin 14 }
1935    
1936     if (cpu->is_32bit)
1937 dpavlin 24 debug(" pc=0x%08"PRIx32" ", (uint32_t)cpu->pc);
1938 dpavlin 14 else
1939 dpavlin 24 debug(" pc=0x%016"PRIx64" ", (uint64_t)cpu->pc);
1940 dpavlin 14
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 dpavlin 24 cpu->pc, &offset);
1951 dpavlin 14 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 dpavlin 24 fatal("0x%08"PRIx32, (uint32_t) vaddr);
1957 dpavlin 14 else
1958 dpavlin 24 fatal("0x%016"PRIx64, (uint64_t) vaddr);
1959 dpavlin 14 fatal(", exception %s, pc=", exception_names[exccode]);
1960     if (cpu->is_32bit)
1961 dpavlin 24 fatal("0x%08"PRIx32, (uint32_t) cpu->pc);
1962 dpavlin 14 else
1963 dpavlin 24 fatal("0x%016"PRIx64, (uint64_t)cpu->pc);
1964 dpavlin 14 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 dpavlin 24 if (cpu->is_32bit)
1984     reg[COP0_BADVADDR] = (int32_t)reg[COP0_BADVADDR];
1985    
1986 dpavlin 14 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 dpavlin 24 if (exc_model != EXC3K && reg[COP0_STATUS] & STATUS_EXL) {
2030 dpavlin 14 /*
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 dpavlin 24 /* debug("[ warning: cpu%i exception while EXL is set,"
2037     " not setting EPC ]\n", cpu->cpu_id); */
2038 dpavlin 14 } else {
2039 dpavlin 24 if (cpu->delay_slot || cpu->cd.mips.nullify_next) {
2040     reg[COP0_EPC] = cpu->pc - 4;
2041 dpavlin 14 reg[COP0_CAUSE] |= CAUSE_BD;
2042    
2043     /* TODO: Should the BD flag actually be set
2044     on nullified slots? */
2045     } else {
2046 dpavlin 24 reg[COP0_EPC] = cpu->pc;
2047 dpavlin 14 reg[COP0_CAUSE] &= ~CAUSE_BD;
2048     }
2049     }
2050    
2051 dpavlin 24 if (cpu->delay_slot)
2052     cpu->delay_slot = EXCEPTION_IN_DELAY_SLOT;
2053     else
2054     cpu->delay_slot = NOT_DELAYED;
2055    
2056 dpavlin 14 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 dpavlin 24 /* R{2,3}000: Shift the lowest 6 bits to the left two steps:*/
2102     reg[COP0_STATUS] = (reg[COP0_STATUS] & ~0x3f) +
2103 dpavlin 14 ((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 dpavlin 24 if (cpu->is_32bit) {
2114     reg[COP0_EPC] = (int64_t)(int32_t)reg[COP0_EPC];
2115     mips32_pc_to_pointers(cpu);
2116 dpavlin 14 } else {
2117 dpavlin 24 mips_pc_to_pointers(cpu);
2118 dpavlin 14 }
2119     }
2120    
2121    
2122 dpavlin 24 #include "memory_mips.c"
2123 dpavlin 22
2124    
2125     #include "tmp_mips_tail.c"
2126    

  ViewVC Help
Powered by ViewVC 1.1.26