/[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 34 - (hide annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 57367 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1480 2007/02/19 01:34:42 debug Exp $
20061029	Changing usleep(1) calls in the debugger to usleep(10000)
20061107	Adding a new disk image option (-d o...) which sets the ISO9660
		filesystem base offset; also making some other hacks to allow
		NetBSD/dreamcast and homebrew demos/games to boot directly
		from a filesystem image.
		Moving Dreamcast-specific stuff in the documentation to its
		own page (dreamcast.html).
		Adding a border to the Dreamcast PVR framebuffer.
20061108	Adding a -T command line option (again?), for halting the
		emulator on unimplemented memory accesses.
20061109	Continuing on various SH4 and Dreamcast related things.
		The emulator should now halt on more unimplemented device
		accesses, instead of just printing a warning, forcing me to
		actually implement missing stuff :)
20061111	Continuing on SH4 and Dreamcast stuff.
		Adding a bogus Landisk (SH4) machine mode.
20061112	Implementing some parts of the Dreamcast GDROM device. With
		some ugly hacks, NetBSD can (barely) mount an ISO image.
20061113	NetBSD/dreamcast now starts booting from the Live CD image,
		but crashes randomly quite early on in the boot process.
20061122	Beginning on a skeleton interrupt.h and interrupt.c for the
		new interrupt subsystem.
20061124	Continuing on the new interrupt system; taking the first steps
		to attempt to connect CPUs (SuperH and MIPS) and devices
		(dev_cons and SH4 timer interrupts) to it. Many things will
		probably break from now on.
20061125	Converting dev_ns16550, dev_8253 to the new interrupt system.
		Attempting to begin to convert the ISA bus.
20061130	Incorporating a patch from Brian Foley for the configure
		script, which checks for X11 libs in /usr/X11R6/lib64 (which
		is used on some Linux systems).
20061227	Adding a note in the man page about booting from Dreamcast
		CDROM images (i.e. that no external kernel is needed).
20061229	Continuing on the interrupt system rewrite: beginning to
		convert more devices, adding abort() calls for legacy interrupt
		system calls so that everything now _has_ to be rewritten!
		Almost all machine modes are now completely broken.
20061230	More progress on removing old interrupt code, mostly related
		to the ISA bus + devices, the LCA bus (on AlphaBook1), and
		the Footbridge bus (for CATS). And some minor PCI stuff.
		Connecting the ARM cpu to the new interrupt system.
		The CATS, NetWinder, and QEMU_MIPS machine modes now work with
		the new interrupt system :)
20061231	Connecting PowerPC CPUs to the new interrupt system.
		Making PReP machines (IBM 6050) work again.
		Beginning to convert the GT PCI controller (for e.g. Malta
		and Cobalt emulation). Some things work, but not everything.
		Updating Copyright notices for 2007.
20070101	Converting dev_kn02 from legacy style to devinit; the 3max
		machine mode now works with the new interrupt system :-]
20070105	Beginning to convert the SGI O2 machine to the new interrupt
		system; finally converting O2 (IP32) devices to devinit, etc.
20070106	Continuing on the interrupt system redesign/rewrite; KN01
		(PMAX), KN230, and Dreamcast ASIC interrupts should work again,
		moving out stuff from machine.h and devices.h into the
		corresponding devices, beginning the rewrite of i80321
		interrupts, etc.
20070107	Beginning on the rewrite of Eagle interrupt stuff (PReP, etc).
20070117	Beginning the rewrite of Algor (V3) interrupts (finally
		changing dev_v3 into devinit style).
20070118	Removing the "bus" registry concept from machine.h, because
		it was practically meaningless.
		Continuing on the rewrite of Algor V3 ISA interrupts.
20070121	More work on Algor interrupts; they are now working again,
		well enough to run NetBSD/algor. :-)
20070122	Converting VR41xx (HPCmips) interrupts. NetBSD/hpcmips
		can be installed using the new interrupt system :-)
20070123	Making the testmips mode work with the new interrupt system.
20070127	Beginning to convert DEC5800 devices to devinit, and to the
		new interrupt system.
		Converting Playstation 2 devices to devinit, and converting
		the interrupt system. Also fixing a severe bug: the interrupt
		mask register on Playstation 2 is bitwise _toggled_ on writes.
20070128	Removing the dummy NetGear machine mode and the 8250 device
		(which was only used by the NetGear machine).
		Beginning to convert the MacPPC GC (Grand Central) interrupt
		controller to the new interrupt system.
		Converting Jazz interrupts (PICA61 etc.) to the new interrupt
		system. NetBSD/arc can be installed again :-)
		Fixing the JAZZ timer (hardcoding it at 100 Hz, works with
		NetBSD and it is better than a completely dummy timer as it
		was before).
		Converting dev_mp to the new interrupt system, although I
		haven't had time to actually test it yet.
		Completely removing src/machines/interrupts.c, cpu_interrupt
		and cpu_interrupt_ack in src/cpu.c, and
		src/include/machine_interrupts.h! Adding fatal error messages
		+ abort() in the few places that are left to fix.
		Converting dev_z8530 to the new interrupt system.
		FINALLY removing the md_int struct completely from the
		machine struct.
		SH4 fixes (adding a PADDR invalidation in the ITLB replacement
		code in memory_sh.c); the NetBSD/dreamcast LiveCD now runs
		all the way to the login prompt, and can be interacted with :-)
		Converting the CPC700 controller (PCI and interrupt controller
		for PM/PPC) to the new interrupt system.
20070129	Fixing MACE ISA interrupts (SGI IP32 emulation). Both NetBSD/
		sgimips' and OpenBSD/sgi's ramdisk kernels can now be
		interacted with again.
20070130	Moving out the MIPS multi_lw and _sw instruction combinations
		so that they are auto-generated at compile time instead.
20070131	Adding detection of amd64/x86_64 hosts in the configure script,
		for doing initial experiments (again :-) with native code
		generation.
		Adding a -k command line option to set the size of the dyntrans
		cache, and a -B command line option to disable native code
		generation, even if GXemul was compiled with support for
		native code generation for the specific host CPU architecture.
20070201	Experimenting with a skeleton for native code generation.
		Changing the default behaviour, so that native code generation
		is now disabled by default, and has to be enabled by using
		-b on the command line.
20070202	Continuing the native code generation experiments.
		Making PCI interrupts work for Footbridge again.
20070203	More native code generation experiments.
		Removing most of the native code generation experimental code,
		it does not make sense to include any quick hacks like this.
		Minor cleanup/removal of some more legacy MIPS interrupt code.
20070204	Making i80321 interrupts work again (for NetBSD/evbarm etc.),
		and fixing the timer at 100 Hz.
20070206	Experimenting with removing the wdc interrupt slowness hack.
20070207	Lowering the number of dyntrans TLB entries for MIPS from
		192 to 128, resulting in a minor speed improvement.
		Minor optimization to the code invalidation routine in
		cpu_dyntrans.c.
20070208	Increasing (experimentally) the nr of dyntrans instructions per
		loop from 60 to 120.
20070210	Commenting out (experimentally) the dyntrans_device_danger
		detection in memory_rw.c.
		Changing the testmips and baremips machines to use a revision 2
		MIPS64 CPU by default, instead of revision 1.
		Removing the dummy i960, IA64, x86, AVR32, and HP PA-RISC
		files, the PC bios emulation, and the Olivetti M700 (ARC) and
		db64360 emulation modes.
20070211	Adding an "mp" demo to the demos directory, which tests the
		SMP functionality of the testmips machine.
		Fixing PReP interrupts some more. NetBSD/prep now boots again.
20070216	Adding a "nop workaround" for booting Mach/PMAX to the
		documentation; thanks to Artur Bujdoso for the values.
		Converting more of the MacPPC interrupt stuff to the new
		system.
		Beginning to convert BeBox interrupts to the new system.
		PPC603e should NOT have the PPC_NO_DEC flag! Removing it.
		Correcting BeBox clock speed (it was set to 100 in the NetBSD
		bootinfo block, but should be 33000000/4), allowing NetBSD
		to start without using the (incorrect) PPC_NO_DEC hack.
20070217	Implementing (slow) AltiVec vector loads and stores, allowing
		NetBSD/macppc to finally boot using the GENERIC kernel :-)
		Updating the documentation with install instructions for
		NetBSD/macppc.
20070218-19	Regression testing for the release.

==============  RELEASE 0.4.4  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26