/[gxemul]/trunk/src/cpus/cpu_mips.c
This is repository of my old source code which isn't updated any more. Go to git.rot13.org for current projects!
ViewVC logotype

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (show annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 5 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 /*
2 * Copyright (C) 2003-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_mips.c,v 1.83 2007/06/15 18:07:08 debug Exp $
29 *
30 * MIPS core CPU emulation.
31 */
32
33 #include <stdio.h>
34 #include <stdlib.h>
35 #include <string.h>
36 #include <sys/types.h>
37 #include <ctype.h>
38 #include <unistd.h>
39
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 #include "settings.h"
54 #include "symbol.h"
55 #include "timer.h"
56
57
58 extern int native_code_translation_enabled;
59
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 static char *special_rot_names[] = SPECIAL_ROT_NAMES;
66 static char *special2_names[] = SPECIAL2_NAMES;
67 static char *mmi_names[] = MMI_NAMES;
68 static char *mmi0_names[] = MMI0_NAMES;
69 static char *mmi1_names[] = MMI1_NAMES;
70 static char *mmi2_names[] = MMI2_NAMES;
71 static char *mmi3_names[] = MMI3_NAMES;
72 static char *special3_names[] = SPECIAL3_NAMES;
73
74 static char *regnames[] = MIPS_REGISTER_NAMES;
75 static char *cop0_names[] = COP0_NAMES;
76
77
78 #define DYNTRANS_DUALMODE_32
79 #define DYNTRANS_DELAYSLOT
80 #include "tmp_mips_head.c"
81
82 void mips_pc_to_pointers(struct cpu *);
83 void mips32_pc_to_pointers(struct cpu *);
84
85
86 /*
87 * 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 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 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 if (cpu->is_32bit) {
127 cpu->run_instr = mips32_run_instr;
128 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 cpu->run_instr = mips_run_instr;
135 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 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 if (cpu->cd.mips.cache_pdcache == 0)
163 cpu->cd.mips.cache_pdcache = x;
164
165 x = DEFAULT_PCACHE_SIZE;
166 if (cpu->cd.mips.cpu_type.picache)
167 x = cpu->cd.mips.cpu_type.picache;
168 if (cpu->cd.mips.cache_picache == 0)
169 cpu->cd.mips.cache_picache = x;
170
171 if (cpu->cd.mips.cache_secondary == 0)
172 cpu->cd.mips.cache_secondary = cpu->cd.mips.cpu_type.scache;
173
174 linesize = DEFAULT_PCACHE_LINESIZE;
175 if (cpu->cd.mips.cpu_type.pdlinesize)
176 linesize = cpu->cd.mips.cpu_type.pdlinesize;
177 if (cpu->cd.mips.cache_pdcache_linesize == 0)
178 cpu->cd.mips.cache_pdcache_linesize = linesize;
179
180 linesize = DEFAULT_PCACHE_LINESIZE;
181 if (cpu->cd.mips.cpu_type.pilinesize)
182 linesize = cpu->cd.mips.cpu_type.pilinesize;
183 if (cpu->cd.mips.cache_picache_linesize == 0)
184 cpu->cd.mips.cache_picache_linesize = linesize;
185
186 linesize = 0;
187 if (cpu->cd.mips.cpu_type.slinesize)
188 linesize = cpu->cd.mips.cpu_type.slinesize;
189 if (cpu->cd.mips.cache_secondary_linesize == 0)
190 cpu->cd.mips.cache_secondary_linesize = linesize;
191
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 x = 1 << cpu->cd.mips.cache_pdcache;
200 linesize = 1 << cpu->cd.mips.cache_pdcache_linesize;
201 break;
202 case CACHE_INSTRUCTION:
203 x = 1 << cpu->cd.mips.cache_picache;
204 linesize = 1 << cpu->cd.mips.cache_picache_linesize;
205 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 size_per_cache_line = 32; /* TODO */
219 }
220
221 cpu->cd.mips.cache_mask[i] = cpu->cd.mips.cache_size[i] - 1;
222
223 CHECK_ALLOCATION(cpu->cd.mips.cache[i] =
224 malloc(cpu->cd.mips.cache_size[i]));
225
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 CHECK_ALLOCATION(cpu->cd.mips.cache_tags[i] =
231 malloc(tags_size));
232
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 if (cpu->cd.mips.cache_secondary)
258 secondary_cache_size = 1 << cpu->cd.mips.cache_secondary;
259 /* 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 /* 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 /* 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 cpu->translate_v2p = translate_v2p_mmu3k;
303 break;
304 case MMU8K:
305 cpu->translate_v2p = translate_v2p_mmu8k;
306 break;
307 case MMU10K:
308 cpu->translate_v2p = translate_v2p_mmu10k;
309 break;
310 default:
311 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
312 cpu->translate_v2p = translate_v2p_mmu4100;
313 else
314 cpu->translate_v2p = translate_v2p_generic;
315 }
316
317 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 if (native_code_translation_enabled)
341 cpu->sampling_timer = timer_add(CPU_SAMPLE_TIMER_HZ,
342 mips_timer_sample_tick, cpu);
343
344 return 1;
345 }
346
347
348 /*
349 * 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 debug("\n%i-bit %s-endian (MIPS",
361 cpu->is_32bit? 32 : 64,
362 cpu->byte_order == EMUL_BIG_ENDIAN? "Big" : "Little");
363
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 case 64:debug("%i, revision %i", ct->isa_level, ct->isa_revision);
372 break;
373 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 * mips_cpu_instruction_has_delayslot():
446 *
447 * Return 1 if an opcode is a branch, 0 otherwise.
448 */
449 int mips_cpu_instruction_has_delayslot(struct cpu *cpu, unsigned char *ib)
450 {
451 uint32_t iword = *((uint32_t *)&ib[0]);
452
453 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
454 iword = LE32_TO_HOST(iword);
455 else
456 iword = BE32_TO_HOST(iword);
457
458 switch (iword >> 26) {
459 case HI6_SPECIAL:
460 switch (iword & 0x3f) {
461 case SPECIAL_JR:
462 case SPECIAL_JALR:
463 return 1;
464 }
465 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
492 return 0;
493 }
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 /* Raw output: */
510 if (rawflag) {
511 for (i=0; i<m->ncpus; i++) {
512 struct mips_coproc *cop0 =
513 m->cpus[i]->cd.mips.coproc[0];
514
515 if (x >= 0 && i != x)
516 continue;
517
518 /* Print index, random, and wired: */
519 printf("cpu%i: (", i);
520
521 if (m->cpus[i]->is_32bit)
522 printf("index=0x%08x random=0x%08x",
523 (int) cop0->reg[COP0_INDEX],
524 (int) cop0->reg[COP0_RANDOM]);
525 else
526 printf("index=0x%016"PRIx64
527 " random=0x%016"PRIx64,
528 (uint64_t) cop0->reg[COP0_INDEX],
529 (uint64_t) cop0->reg[COP0_RANDOM]);
530
531 if (m->cpus[i]->cd.mips.cpu_type.isa_level >= 3)
532 printf(" wired=0x%"PRIx64,
533 (uint64_t) cop0->reg[COP0_WIRED]);
534
535 printf(")\n");
536
537 for (j=0; j<m->cpus[i]->cd.mips.cpu_type.
538 nr_of_tlb_entries; j++) {
539 if (m->cpus[i]->cd.mips.cpu_type.mmu_model ==
540 MMU3K)
541 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 else if (m->cpus[i]->is_32bit)
546 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 else
554 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 }
562 }
563
564 return;
565 }
566
567 /* Nicely formatted output: */
568 for (i=0; i<m->ncpus; i++) {
569 int pageshift = 12;
570 struct mips_coproc *cop0 = m->cpus[i]->cd.mips.coproc[0];
571
572 if (x >= 0 && i != x)
573 continue;
574
575 if (m->cpus[i]->cd.mips.cpu_type.rev == MIPS_R4100)
576 pageshift = 10;
577
578 /* Print index, random, and wired: */
579 printf("cpu%i: (", i);
580 switch (m->cpus[i]->cd.mips.cpu_type.isa_level) {
581 case 1:
582 case 2: printf("index=0x%x random=0x%x",
583 (int) ((cop0->reg[COP0_INDEX] & R2K3K_INDEX_MASK)
584 >> R2K3K_INDEX_SHIFT),
585 (int) ((cop0->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
586 >> R2K3K_RANDOM_SHIFT));
587 break;
588 default:printf("index=0x%x random=0x%x",
589 (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 }
594
595 printf(")\n");
596
597 for (j=0; j<m->cpus[i]->cd.mips.cpu_type.
598 nr_of_tlb_entries; j++) {
599 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 uint64_t psize;
604
605 mask |= (1 << (pageshift+1)) - 1;
606 /* here mask = e.g. 0x1fff for 4KB pages */
607
608 printf("%3i: ", j);
609
610 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 printf("vaddr=0x%08"PRIx32" ",
635 (uint32_t) (hi & ~mask));
636 break;
637 default:/* R4x00, R1x000, MIPS64, etc. */
638 printf("vaddr=%016"PRIx64" ",
639 (uint64_t) (hi & ~mask));
640 }
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 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 printf(lo0 & ENTRYLO_D? "D" : " ");
660
661 if (!(lo1 & ENTRYLO_V))
662 printf(" p1=(invalid) ");
663 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 else
682 printf(" (?)");
683
684 printf("\n");
685 }
686 }
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 int running, uint64_t dumpaddr)
707 {
708 int hi6, special6, regimm5, sub;
709 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 debug("%08"PRIx32, (uint32_t)dumpaddr);
731 else
732 debug("%016"PRIx64, (uint64_t)dumpaddr);
733
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 if (running && cpu->delay_slot)
751 debug(" (d)");
752
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 sub = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
775 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 else if (sa == 3)
785 debug("ehb");
786 else
787 debug("nop (weird, sa=%i)", sa);
788 break;
789 }
790
791 switch (sub) {
792 case 0x00:
793 debug("%s\t%s,", special_names[special6],
794 regnames[rd]);
795 debug("%s,%i", regnames[rt], sa);
796 break;
797 case 0x01:
798 debug("%s\t%s,",
799 special_rot_names[special6],
800 regnames[rd]);
801 debug("%s,%i", regnames[rt], sa);
802 break;
803 default:debug("UNIMPLEMENTED special, sub=0x%02x\n",
804 sub);
805 }
806 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 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 regnames[rd]);
822 debug(",%s", regnames[rt]);
823 debug(",%s", regnames[rs]);
824 break;
825 case 0x01:
826 debug("%s\t%s", special_rot_names[special6],
827 regnames[rd]);
828 debug(",%s", regnames[rt]);
829 debug(",%s", regnames[rs]);
830 break;
831 default:debug("UNIMPLEMENTED special, sub=0x%02x\n",
832 sub);
833 }
834 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 /* .hb = hazard barrier hint on MIPS32/64 rev 2 */
840 debug("jr%s\t%s",
841 (instr[1] & 0x04) ? ".hb" : "",
842 regnames[rs]);
843 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 /* .hb = hazard barrier hint on MIPS32/64 rev 2 */
852 debug("jalr%s\t%s",
853 (instr[1] & 0x04) ? ".hb" : "",
854 regnames[rd]);
855 debug(",%s", regnames[rs]);
856 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 debug("%s\t%s", special_names[special6], regnames[rd]);
863 break;
864 case SPECIAL_MTLO:
865 case SPECIAL_MTHI:
866 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
867 debug("%s\t%s", special_names[special6], regnames[rs]);
868 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 if (cpu->is_32bit && (special6 == SPECIAL_ADDU ||
889 special6 == SPECIAL_SUBU) && rt == 0) {
890 /* Special case 1: addu/subu with
891 rt = the zero register ==> move */
892 debug("move\t%s", regnames[rd]);
893 debug(",%s", regnames[rs]);
894 } else if (special6 == SPECIAL_ADDU && cpu->is_32bit
895 && rs == 0) {
896 /* Special case 2: addu with
897 rs = the zero register ==> move */
898 debug("move\t%s", regnames[rd]);
899 debug(",%s", regnames[rt]);
900 } else {
901 debug("%s\t%s", special_names[special6],
902 regnames[rd]);
903 debug(",%s", regnames[rs]);
904 debug(",%s", regnames[rt]);
905 }
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 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 debug("%s,", regnames[rd]);
930 else
931 debug("WEIRD_R5900_RD,");
932 } else {
933 debug("WEIRD_RD_NONZERO,");
934 }
935 }
936 debug("%s", regnames[rs]);
937 debug(",%s", regnames[rt]);
938 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 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
961 rd = (instr[1] >> 3) & 31;
962 debug("mfsa\t%s", regnames[rd]);
963 } else {
964 debug("unimplemented special 0x28");
965 }
966 break;
967 case SPECIAL_MTSA:
968 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
969 rs = ((instr[3] & 3) << 3) +
970 ((instr[2] >> 5) & 7);
971 debug("mtsa\t%s", regnames[rs]);
972 } else {
973 debug("unimplemented special 0x29");
974 }
975 break;
976 default:
977 debug("%s\t= UNIMPLEMENTED", special_names[special6]);
978 }
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 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 debug("%s,", regnames[rt]);
1006 }
1007 debug("%s,", regnames[rs]);
1008 }
1009
1010 if (cpu->is_32bit)
1011 debug("0x%08"PRIx32, (uint32_t)addr);
1012 else
1013 debug("0x%016"PRIx64, (uint64_t)addr);
1014
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 debug("%s\t%s,", hi6_names[hi6], regnames[rt]);
1035 debug("%s,", regnames[rs]);
1036 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 debug("lui\t%s,0x%x", regnames[rt], imm);
1045 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 case HI6_SQ_SPECIAL3:
1066 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 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 int msbd, lsb, sub10;
1089 special6 = instr[0] & 0x3f;
1090 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1091 rt = instr[2] & 31;
1092 rd = msbd = (instr[1] >> 3) & 31;
1093 lsb = ((instr[1] & 7) << 2) | (instr[0] >> 6);
1094 sub10 = (rs << 5) | lsb;
1095
1096 switch (special6) {
1097
1098 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 debug("\t%s", regnames[rt]);
1108 debug(",%s", regnames[rs]);
1109 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 debug("\t%s", regnames[rt]);
1125 debug(",%s", regnames[rs]);
1126 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 debug("\t%s", regnames[rd]);
1140 debug(",%s", regnames[rt]);
1141 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 debug("\t%s", regnames[rd]);
1156 debug(",%s", regnames[rt]);
1157 break;
1158 default:debug("%s", special3_names[special6]);
1159 debug("\t(UNIMPLEMENTED)");
1160 }
1161 break;
1162
1163 case SPECIAL3_RDHWR:
1164 debug("%s", special3_names[special6]);
1165 debug("\t%s", regnames[rt]);
1166 debug(",hwr%i", rd);
1167 break;
1168
1169 default:debug("%s", special3_names[special6]);
1170 debug("\t(UNIMPLEMENTED)");
1171 }
1172 break;
1173 }
1174
1175 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 rt, imm, regnames[rs]);
1188
1189 if (running) {
1190 debug("\t[0x%016"PRIx64" = %s]",
1191 (uint64_t)(cpu->cd.mips.gpr[rs] + imm));
1192 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 debug("%s", regnames[rt]);
1208
1209 debug(",%i(%s)", imm, regnames[rs]);
1210
1211 if (running) {
1212 debug("\t[");
1213
1214 if (cpu->is_32bit)
1215 debug("0x%08"PRIx32,
1216 (uint32_t) (cpu->cd.mips.gpr[rs] + imm));
1217 else
1218 debug("0x%016"PRIx64,
1219 (uint64_t) (cpu->cd.mips.gpr[rs] + imm));
1220
1221 if (symbol != NULL)
1222 debug(" = %s", symbol);
1223
1224 /* 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 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 debug("%08"PRIx32, (uint32_t) addr);
1243 else
1244 debug("%016"PRIx64, (uint64_t) addr);
1245 if (symbol != NULL)
1246 debug("\t<%s>", symbol);
1247 break;
1248
1249 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
1262 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 debug("cache\t0x%02x,0x%04x(%s)", copz, imm, regnames[rt]);
1270 if (which_cache==0) debug(" [ primary I-cache");
1271 if (which_cache==1) debug(" [ primary D-cache");
1272 if (which_cache==2) debug(" [ secondary I-cache");
1273 if (which_cache==3) debug(" [ secondary D-cache");
1274 debug(", ");
1275 if (cache_op==0) debug("index invalidate");
1276 if (cache_op==1) debug("index load tag");
1277 if (cache_op==2) debug("index store tag"), showtag=1;
1278 if (cache_op==3) debug("create dirty exclusive");
1279 if (cache_op==4) debug("hit invalidate");
1280 if (cache_op==5) debug("fill OR hit writeback invalidate");
1281 if (cache_op==6) debug("hit writeback");
1282 if (cache_op==7) debug("hit set virtual");
1283 if (running)
1284 debug(", addr 0x%016"PRIx64,
1285 (uint64_t)(cpu->cd.mips.gpr[rt] + imm));
1286 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
1293 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
1301 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
1302 int c790mmifunc = (instrword >> 6) & 0x1f;
1303 if (special6 != MMI_MMI0 && special6 != MMI_MMI1 &&
1304 special6 != MMI_MMI2 && special6 != MMI_MMI3)
1305 debug("%s\t", mmi_names[special6]);
1306
1307 switch (special6) {
1308
1309 case MMI_MADD:
1310 case MMI_MADDU:
1311 if (rd != MIPS_GPR_ZERO) {
1312 debug("%s,", regnames[rd]);
1313 }
1314 debug("%s,%s", regnames[rs], regnames[rt]);
1315 break;
1316
1317 case MMI_MMI0:
1318 debug("%s\t", mmi0_names[c790mmifunc]);
1319 switch (c790mmifunc) {
1320
1321 case MMI0_PEXTLB:
1322 case MMI0_PEXTLH:
1323 case MMI0_PEXTLW:
1324 case MMI0_PMAXH:
1325 case MMI0_PMAXW:
1326 case MMI0_PPACB:
1327 case MMI0_PPACH:
1328 case MMI0_PPACW:
1329 debug("%s,%s,%s", regnames[rd],
1330 regnames[rs], regnames[rt]);
1331 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 debug("%s,%s,%s", regnames[rd],
1347 regnames[rs], regnames[rt]);
1348 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 debug("%s", regnames[rd]);
1361 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 debug("%s,%s,%s", regnames[rd],
1374 regnames[rs], regnames[rt]);
1375 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 debug("%s", regnames[rs]);
1388 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 debug("%s,%s,%s", regnames[rd],
1397 regnames[rs], regnames[rt]);
1398 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 regnames[rd]);
1421 }
1422 debug("%s,%s", regnames[rs], regnames[rt]);
1423 break;
1424
1425 case SPECIAL2_MUL:
1426 /* Apparently used both on R5900 and MIPS32: */
1427 debug("%s,%s,%s", regnames[rd],
1428 regnames[rs], regnames[rt]);
1429 break;
1430
1431 case SPECIAL2_CLZ:
1432 case SPECIAL2_CLO:
1433 case SPECIAL2_DCLZ:
1434 case SPECIAL2_DCLO:
1435 debug("%s,%s", regnames[rd], regnames[rs]);
1436 break;
1437
1438 default:
1439 debug("(UNIMPLEMENTED)");
1440 }
1441 break;
1442
1443 case HI6_REGIMM:
1444 regimm5 = instr[2] & 0x1f;
1445 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 switch (regimm5) {
1451
1452 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 debug("%s\t%s,", regimm_names[regimm5], regnames[rs]);
1461
1462 addr = (dumpaddr + 4) + (imm << 2);
1463
1464 if (cpu->is_32bit)
1465 debug("0x%08"PRIx32, (uint32_t) addr);
1466 else
1467 debug("0x%016"PRIx64, (uint64_t) addr);
1468 break;
1469
1470 case REGIMM_SYNCI:
1471 debug("%s\t%i(%s)", regimm_names[regimm5],
1472 imm, regnames[rs]);
1473 break;
1474
1475 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 int bits128 = cpu->cd.mips.cpu_type.rev == MIPS_R5900;
1503
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 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 else
1518 debug("cpu%i: pc = 0x%016"PRIx64,
1519 cpu->cpu_id, (uint64_t) cpu->pc);
1520
1521 debug(" <%s>\n", symbol != NULL? symbol :
1522 " no symbol ");
1523
1524 if (bits32)
1525 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
1540 /* General registers: */
1541 if (bits128) {
1542 /* 128-bit: */
1543 for (i=0; i<32; i++) {
1544 int r = (i >> 1) + ((i & 1) << 4);
1545 if ((i & 1) == 0)
1546 debug("cpu%i:", cpu->cpu_id);
1547 if (r == MIPS_GPR_ZERO)
1548 debug(" "
1549 " ");
1550 else
1551 debug(" %3s=%016"PRIx64"%016"PRIx64,
1552 regnames[r], (uint64_t)
1553 cpu->cd.mips.gpr_quadhi[r],
1554 (uint64_t)cpu->cd.mips.gpr[r]);
1555 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 debug(" %3s = %08"PRIx32, regnames[i],
1567 (uint32_t)cpu->cd.mips.gpr[i]);
1568 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 debug(" %3s = 0x%016"PRIx64,
1581 regnames[r],
1582 (uint64_t)cpu->cd.mips.gpr[r]);
1583 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 if (coprocnr == 0)
1610 debug(" %8s", cop0_names[i]);
1611 else
1612 debug(" c%i,%02i", coprocnr, i);
1613
1614 if (bits32)
1615 debug("=%08x", (int)cpu->cd.mips.
1616 coproc[coprocnr]->reg[i]);
1617 else {
1618 if (coprocnr == 0 && (i == COP0_COUNT
1619 || i == COP0_COMPARE || i == COP0_INDEX
1620 || i == COP0_RANDOM || i == COP0_WIRED))
1621 debug(" = 0x%08x",
1622 (int) cpu->cd.mips.coproc[
1623 coprocnr]->reg[i]);
1624 else
1625 debug(" = 0x%016"PRIx64, (uint64_t)
1626 cpu->cd.mips.coproc[
1627 coprocnr]->reg[i]);
1628 }
1629
1630 if ((i & nm1) == nm1)
1631 debug("\n");
1632
1633 /* Skip the last 16 cop0 registers on R3000 etc. */
1634 if (coprocnr == 0 && cpu->cd.mips.cpu_type.isa_level < 3
1635 && i == 15)
1636 i = 31;
1637 }
1638
1639 if (coprocnr == 0 && cpu->cd.mips.cpu_type.isa_level >= 32) {
1640 debug("cpu%i: ", cpu->cpu_id);
1641 debug("config_select1 = 0x");
1642 if (cpu->is_32bit)
1643 debug("%08"PRIx32,
1644 (uint32_t)cpu->cd.mips.cop0_config_select1);
1645 else
1646 debug("%016"PRIx64,
1647 (uint64_t)cpu->cd.mips.cop0_config_select1);
1648 debug("\n");
1649 }
1650
1651 /* Floating point control registers: */
1652 if (coprocnr == 1) {
1653 for (i=0; i<32; i++)
1654 switch (i) {
1655 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 break;
1660 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 break;
1665 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 break;
1670 }
1671 }
1672 }
1673
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 }
1679
1680
1681 /*
1682 * mips_cpu_interrupt_assert(), mips_cpu_interrupt_deassert():
1683 *
1684 * Assert or deassert a MIPS CPU interrupt by masking in or out bits
1685 * in the CAUSE register of coprocessor 0.
1686 */
1687 void mips_cpu_interrupt_assert(struct interrupt *interrupt)
1688 {
1689 struct cpu *cpu = interrupt->extra;
1690 cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] |= interrupt->line;
1691 }
1692 void mips_cpu_interrupt_deassert(struct interrupt *interrupt)
1693 {
1694 struct cpu *cpu = interrupt->extra;
1695 cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] &= ~interrupt->line;
1696 }
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 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 if (!quiet_mode) {
1732 uint64_t offset;
1733 int x;
1734 char *symbol = get_symbol_name(&cpu->machine->symbol_context,
1735 cpu->pc, &offset);
1736
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
1746 case EXCEPTION_INT:
1747 debug(" cause_im=0x%02x", (int)
1748 ((reg[COP0_CAUSE] & CAUSE_IP_MASK)
1749 >> CAUSE_IP_SHIFT));
1750 break;
1751
1752 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 if (d > -256 && d < 256) {
1759 debug(" a%i=%i", x, (int)d);
1760 } 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 }
1774 break;
1775
1776 case EXCEPTION_CPU:
1777 debug(" coproc_nr=%i", coproc_nr);
1778 break;
1779
1780 default:
1781 if (cpu->is_32bit)
1782 debug(" vaddr=0x%08x", (int)vaddr);
1783 else
1784 debug(" vaddr=0x%016"PRIx64, (uint64_t)vaddr);
1785 }
1786
1787 if (cpu->is_32bit)
1788 debug(" pc=0x%08"PRIx32" ", (uint32_t)cpu->pc);
1789 else
1790 debug(" pc=0x%016"PRIx64" ", (uint64_t)cpu->pc);
1791
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 cpu->pc, &offset);
1802 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 fatal("0x%08"PRIx32, (uint32_t) vaddr);
1808 else
1809 fatal("0x%016"PRIx64, (uint64_t) vaddr);
1810 fatal(", exception %s, pc=", exception_names[exccode]);
1811 if (cpu->is_32bit)
1812 fatal("0x%08"PRIx32, (uint32_t) cpu->pc);
1813 else
1814 fatal("0x%016"PRIx64, (uint64_t)cpu->pc);
1815 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 if (cpu->is_32bit)
1835 reg[COP0_BADVADDR] = (int32_t)reg[COP0_BADVADDR];
1836
1837 if (exc_model == EXC3K) {
1838 reg[COP0_CONTEXT] &= ~R2K3K_CONTEXT_BADVPN_MASK;
1839 reg[COP0_CONTEXT] |= ((vaddr_vpn2 <<
1840 R2K3K_CONTEXT_BADVPN_SHIFT) &
1841 R2K3K_CONTEXT_BADVPN_MASK);
1842
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 reg[COP0_CONTEXT] &=
1852 ~CONTEXT_BADVPN2_MASK_R4100;
1853 reg[COP0_CONTEXT] |= ((vaddr_vpn2 <<
1854 CONTEXT_BADVPN2_SHIFT) &
1855 CONTEXT_BADVPN2_MASK_R4100);
1856
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 if (exc_model != EXC3K && reg[COP0_STATUS] & STATUS_EXL) {
1886 /*
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 /* debug("[ warning: cpu%i exception while EXL is set,"
1893 " not setting EPC ]\n", cpu->cpu_id); */
1894 } else {
1895 if (cpu->delay_slot) {
1896 reg[COP0_EPC] = cpu->pc - 4;
1897 reg[COP0_CAUSE] |= CAUSE_BD;
1898 } else {
1899 reg[COP0_EPC] = cpu->pc;
1900 reg[COP0_CAUSE] &= ~CAUSE_BD;
1901 }
1902 }
1903
1904 if (cpu->delay_slot)
1905 cpu->delay_slot = EXCEPTION_IN_DELAY_SLOT;
1906 else
1907 cpu->delay_slot = NOT_DELAYED;
1908
1909 /* 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 /* R{2,3}000: Shift the lowest 6 bits to the left two steps:*/
1953 reg[COP0_STATUS] = (reg[COP0_STATUS] & ~0x3f) +
1954 ((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 if (cpu->is_32bit) {
1965 reg[COP0_EPC] = (int64_t)(int32_t)reg[COP0_EPC];
1966 mips32_pc_to_pointers(cpu);
1967 } else {
1968 mips_pc_to_pointers(cpu);
1969 }
1970 }
1971
1972
1973 #include "memory_mips.c"
1974
1975
1976 #include "tmp_mips_tail.c"
1977

  ViewVC Help
Powered by ViewVC 1.1.26