/[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 42 - (hide annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 51695 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1613 2007/06/15 20:11:26 debug Exp $
20070501	Continuing a little on m88k disassembly (control registers,
		more instructions).
		Adding a dummy mvme88k machine mode.
20070502	Re-adding MIPS load/store alignment exceptions.
20070503	Implementing more of the M88K disassembly code.
20070504	Adding disassembly of some more M88K load/store instructions.
		Implementing some relatively simple M88K instructions (br.n,
		xor[.u] imm, and[.u] imm).
20070505	Implementing M88K three-register and, or, xor, and jmp[.n],
		bsr[.n] including function call trace stuff.
		Applying a patch from Bruce M. Simpson which implements the
		SYSCON_BOARD_CPU_CLOCK_FREQ_ID object of the syscon call in
		the yamon PROM emulation.
20070506	Implementing M88K bb0[.n] and bb1[.n], and skeletons for
		ldcr and stcr (although no control regs are implemented yet).
20070509	Found and fixed the bug which caused Linux for QEMU_MIPS to
		stop working in 0.4.5.1: It was a faulty change to the MIPS
		'sc' and 'scd' instructions I made while going through gcc -W
		warnings on 20070428.
20070510	Updating the Linux/QEMU_MIPS section in guestoses.html to
		use mips-test-0.2.tar.gz instead of 0.1.
		A big thank you to Miod Vallat for sending me M88K manuals.
		Implementing more M88K instructions (addu, subu, div[u], mulu,
		ext[u], clr, set, cmp).
20070511	Fixing bugs in the M88K "and" and "and.u" instructions (found
		by comparing against the manual).
		Implementing more M88K instructions (mask[.u], mak, bcnd (auto-
		generated)) and some more control register details.
		Cleanup: Removing the experimental AVR emulation mode and
		corresponding devices; AVR emulation wasn't really meaningful.
		Implementing autogeneration of most M88K loads/stores. The
		rectangle drawing demo (with -O0) for M88K runs :-)
		Beginning on M88K exception handling.
		More M88K instructions: tb0, tb1, rte, sub, jsr[.n].
		Adding some skeleton MVME PROM ("BUG") emulation.
20070512	Fixing a bug in the M88K cmp instruction.
		Adding the M88K lda (scaled register) instruction.
		Fixing bugs in 64-bit (32-bit pairs) M88K loads/stores.
		Removing the unused tick_hz stuff from the machine struct.
		Implementing the M88K xmem instruction. OpenBSD/mvme88k gets
		far enough to display the Copyright banner :-)
		Implementing subu.co (guess), addu.co, addu.ci, ff0, and ff1.
		Adding a dev_mvme187, for MVME187-specific devices/registers.
		OpenBSD/mvme88k prints more boot messages. :)
20070515	Continuing on MVME187 emulation (adding more devices, beginning
		on the CMMUs, etc).
		Adding the M88K and.c, xor.c, and or.c instructions, and making
		sure that mul, div, etc cause exceptions if executed when SFD1
		is disabled.
20070517	Continuing on M88K and MVME187 emulation in general; moving
		the CMMU registers to the CPU struct, separating dev_pcc2 from
		dev_mvme187, and beginning on memory_m88k.c (BATC and PATC).
		Fixing a bug in 64-bit (32-bit pairs) M88K fast stores.
		Implementing the clock part of dev_mk48txx.
		Implementing the M88K fstcr and xcr instructions.
		Implementing m88k_cpu_tlbdump().
		Beginning on the implementation of a separate address space
		for M88K .usr loads/stores.
20070520	Removing the non-working (skeleton) Sandpoint, SonyNEWS, SHARK
		Dnard, and Zaurus machine modes.
		Experimenting with dyntrans to_be_translated read-ahead. It
		seems to give a very small performance increase for MIPS
		emulation, but a large performance degradation for SuperH. Hm.
20070522	Disabling correct SuperH ITLB emulation; it does not seem to be
		necessary in order to let SH4 guest OSes run, and it slows down
		userspace code.
		Implementing "samepage" branches for SuperH emulation, and some
		other minor speed hacks.
20070525	Continuing on M88K memory-related stuff: exceptions, memory
		transaction register contents, etc.
		Implementing the M88K subu.ci instruction.
		Removing the non-working (skeleton) Iyonix machine mode.
		OpenBSD/mvme88k reaches userland :-), starts executing
		/sbin/init's instructions, and issues a few syscalls, before
		crashing.
20070526	Fixing bugs in dev_mk48txx, so that OpenBSD/mvme88k detects
		the correct time-of-day.
		Implementing a generic IRQ controller for the test machines
		(dev_irqc), similar to a proposed patch from Petr Stepan.
		Experimenting some more with translation read-ahead.
		Adding an "expect" script for automated OpenBSD/landisk
		install regression/performance tests.
20070527	Adding a dummy mmEye (SH3) machine mode skeleton.
		FINALLY found the strange M88K bug I have been hunting: I had
		not emulated the SNIP value for exceptions occurring in
		branch delay slots correctly.
		Implementing correct exceptions for 64-bit M88K loads/stores.
		Address to symbol lookups are now disabled when M88K is
		running in usermode (because usermode addresses don't have
		anything to do with supervisor addresses).
20070531	Removing the mmEye machine mode skeleton.
20070604	Some minor code cleanup.
20070605	Moving src/useremul.c into a subdir (src/useremul/), and
		cleaning up some more legacy constructs.
		Adding -Wstrict-aliasing and -fstrict-aliasing detection to
		the configure script.
20070606	Adding a check for broken GCC on Solaris to the configure
		script. (GCC 3.4.3 on Solaris cannot handle static variables
		which are initialized to 0 or NULL. :-/)
		Removing the old (non-working) ARC emulation modes: NEC RD94,
		R94, R96, and R98, and the last traces of Olivetti M700 and
		Deskstation Tyne.
		Removing the non-working skeleton WDSC device (dev_wdsc).
20070607	Thinking about how to use the host's cc + ld at runtime to
		generate native code. (See experiments/native_cc_ld_test.i
		for an example.)
20070608	Adding a program counter sampling timer, which could be useful
		for native code generation experiments.
		The KN02_CSR_NRMMOD bit in the DECstation 5000/200 (KN02) CSR
		should always be set, to allow a 5000/200 PROM to boot.
20070609	Moving out breakpoint details from the machine struct into
		a helper struct, and removing the limit on max nr of
		breakpoints.
20070610	Moving out tick functions into a helper struct as well (which
		also gets rid of the max limit).
20070612	FINALLY figured out why Debian/DECstation stopped working when
		translation read-ahead was enabled: in src/memory_rw.c, the
		call to invalidate_code_translation was made also if the
		memory access was an instruction load (if the page was mapped
		as writable); it shouldn't be called in that case.
20070613	Implementing some more MIPS32/64 revision 2 instructions: di,
		ei, ext, dext, dextm, dextu, and ins.
20070614	Implementing an instruction combination for the NetBSD/arm
		idle loop (making the host not use any cpu if NetBSD/arm
		inside the emulator is not using any cpu).
		Increasing the nr of ARM VPH entries from 128 to 384.
20070615	Removing the ENABLE_arch stuff from the configure script, so
		that all included architectures are included in both release
		and development builds.
		Moving memory related helper functions from misc.c to memory.c.
		Adding preliminary instructions for netbooting NetBSD/pmppc to
		guestoses.html; it doesn't work yet, there are weird timeouts.
		Beginning a total rewrite of the userland emulation modes
		(removing all emulation modes, beginning from scratch with
		NetBSD/MIPS and FreeBSD/Alpha only).
20070616	After fixing a bug in the DEC21143 NIC (the TDSTAT_OWN bit was
		only cleared for the last segment when transmitting, not all
		segments), NetBSD/pmppc boots with root-on-nfs without the
		timeouts. Updating guestoses.html.
		Removing the skeleton PSP (Playstation Portable) mode.
		Moving X11-related stuff in the machine struct into a helper
		struct.
		Cleanup of out-of-memory checks, to use a new CHECK_ALLOCATION
		macro (which prints a meaningful error message).
		Adding a COMMENT to each machine and device (for automagic
		.index comment generation).
		Doing regression testing for the next release.

==============  RELEASE 0.4.6  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26