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

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


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

  ViewVC Help
Powered by ViewVC 1.1.26