/[gxemul]/trunk/src/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/cpu_mips.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 12 - (show annotations)
Mon Oct 8 16:18:38 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 119194 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.905 2005/08/16 09:16:24 debug Exp $
20050628	Continuing the work on the ARM translation engine. end_of_page
		works. Experimenting with load/store translation caches
		(virtual -> physical -> host).
20050629	More ARM stuff (memory access translation cache, mostly). This
		might break a lot of stuff elsewhere, probably some MIPS-
		related translation things.
20050630	Many load/stores are now automatically generated and included
		into cpu_arm_instr.c; 1024 functions in total (!).
		Fixes based on feedback from Alec Voropay: only print 8 hex
		digits instead of 16 in some cases when emulating 32-bit
		machines; similar 8 vs 16 digit fix for breakpoint addresses;
		4Kc has 16 TLB entries, not 48; the MIPS config select1
		register is now printed with "reg ,0".
		Also changing many other occurances of 16 vs 8 digit output.
		Adding cache associativity fields to mips_cpu_types.h; updating
		some other cache fields; making the output of
		mips_cpu_dumpinfo() look nicer.
		Generalizing the bintrans stuff for device accesses to also
		work with the new translation system. (This might also break
		some MIPS things.)
		Adding multi-load/store instructions to the ARM disassembler
		and the translator, and some optimizations of various kinds.
20050701	Adding a simple dev_disk (it can read/write sectors from
		disk images).
20050712	Adding dev_ether (a simple ethernet send/receive device).
		Debugger command "ninstrs" for toggling show_nr_of_instructions
		during runtime.
		Removing the framebuffer logo.
20050713	Continuing on dev_ether.
		Adding a dummy cpu_alpha (again).
20050714	More work on cpu_alpha.
20050715	More work on cpu_alpha. Many instructions work, enough to run
		a simple framebuffer fill test (similar to the ARM test).
20050716	More Alpha stuff.
20050717	Minor updates (Alpha stuff).
20050718	Minor updates (Alpha stuff).
20050719	Generalizing some Alpha instructions.
20050720	More Alpha-related updates.
20050721	Continuing on cpu_alpha. Importing rpb.h from NetBSD/alpha.
20050722	Alpha-related updates: userland stuff (Hello World using
		write() compiled statically for FreeBSD/Alpha runs fine), and
		more instructions are now implemented.
20050723	Fixing ldq_u and stq_u.
		Adding more instructions (conditional moves, masks, extracts,
		shifts).
20050724	More FreeBSD/Alpha userland stuff, and adding some more
		instructions (inserts).
20050725	Continuing on the Alpha stuff. (Adding dummy ldt/stt.)
		Adding a -A command line option to turn off alignment checks
		in some cases (for translated code).
		Trying to remove the old bintrans code which updated the pc
		and nr_of_executed_instructions for every instruction.
20050726	Making another attempt att removing the pc/nr of instructions
		code. This time it worked, huge performance increase for
		artificial test code, but performance loss for real-world
		code :-( so I'm scrapping that code for now.
		Tiny performance increase on Alpha (by using ret instead of
		jmp, to play nice with the Alpha's branch prediction) for the
		old MIPS bintrans backend.
20050727	Various minor fixes and cleanups.
20050728	Switching from a 2-level virtual to host/physical translation
		system for ARM emulation, to a 1-level translation.
		Trying to switch from 2-level to 1-level for the MIPS bintrans
		system as well (Alpha only, so far), but there is at least one
		problem: caches and/or how they work with device mappings.
20050730	Doing the 2-level to 1-level conversion for the i386 backend.
		The cache/device bug is still there for R2K/3K :(
		Various other minor updates (Malta etc).
		The mc146818 clock now updates the UIP bit in a way which works
		better with Linux for at least sgimips and Malta emulation.
		Beginning the work on refactoring the dyntrans system.
20050731	Continuing the dyntrans refactoring.
		Fixing a small but serious host alignment bug in memory_rw.
		Adding support for big-endian load/stores to the i386 bintrans
		backend.
		Another minor i386 bintrans backend update: stores from the
		zero register are now one (or two) loads shorter.
		The slt and sltu instructions were incorrectly implemented for
		the i386 backend; only using them for 32-bit mode for now.
20050801	Continuing the dyntrans refactoring.
		Cleanup of the ns16550 serial controller (removing unnecessary
		code).
		Bugfix (memory corruption bug) in dev_gt, and a patch/hack from
		Alec Voropay for Linux/Malta.
20050802	More cleanup/refactoring of the dyntrans subsystem: adding
		phys_page pointers to the lookup tables, for quick jumps
		between translated pages.
		Better fix for the ns16550 device (but still no real FIFO
		functionality).
		Converting cpu_ppc to the new dyntrans system. This means that
		I will have to start from scratch with implementing each
		instruction, and figure out how to implement dual 64/32-bit
		modes etc.
		Removing the URISC CPU family, because it was useless.
20050803	When selecting a machine type, the main type can now be omitted
		if the subtype name is unique. (I.e. -E can be omitted.)
		Fixing a dyntrans/device update bug. (Writes to offset 0 of
		a device could sometimes go unnoticed.)
		Adding an experimental "instruction combination" hack for
		ARM for memset-like byte fill loops.
20050804	Minor progress on cpu_alpha and related things.
		Finally fixing the MIPS dmult/dmultu bugs.
		Fixing some minor TODOs.
20050805	Generalizing the 8259 PIC. It now also works with Cobalt
		and evbmips emulation, in addition to the x86 hack.
		Finally converting the ns16550 device to use devinit.
		Continuing the work on the dyntrans system. Thinking about
		how to add breakpoints.
20050806	More dyntrans updates. Breakpoints seem to work now.
20050807	Minor updates: cpu_alpha and related things; removing
		dev_malta (as it isn't used any more).
		Dyntrans: working on general "show trace tree" support.
		The trace tree stuff now works with both the old MIPS code and
		with newer dyntrans modes. :)
		Continuing on Alpha-related stuff (trying to get *BSD to boot
		a bit further, adding more instructions, etc).
20050808	Adding a dummy IA64 cpu family, and continuing the refactoring
		of the dyntrans system.
		Removing the regression test stuff, because it was more or
		less useless.
		Adding loadlinked/storeconditional type instructions to the
		Alpha emulation. (Needed for Linux/alpha. Not very well tested
		yet.)
20050809	The function call trace tree now prints a per-function nr of
		arguments. (Semi-meaningless, since that data isn't read yet
		from the ELFs; some hardcoded symbols such as memcpy() and
		strlen() work fine, though.)
		More dyntrans refactoring; taking out more of the things that
		are common to all cpu families.
20050810	Working on adding support for "dual mode" for PPC dyntrans
		(i.e. both 64-bit and 32-bit modes).
		(Re)adding some simple PPC instructions.
20050811	Adding a dummy M68K cpu family. The dyntrans system isn't ready
		for variable-length ISAs yet, so it's completely bogus so far.
		Re-adding more PPC instructions.
		Adding a hack to src/file.c which allows OpenBSD/mac68k a.out
		kernels to be loaded.
		Beginning to add PPC loads/stores. So far they only work in
		32-bit mode.
20050812	The configure file option "add_remote" now accepts symbolic
		host names, in addition to numeric IPv4 addresses.
		Re-adding more PPC instructions.
20050814	Continuing to port back more PPC instructions.
		Found and fixed the cache/device write-update bug for 32-bit
		MIPS bintrans. :-)
		Triggered a really weird and annoying bug in Compaq's C
		compiler; ccc sometimes outputs code which loads from an
		address _before_ checking whether the pointer was NULL or not.
		(I'm not sure how to handle this problem.)
20050815	Removing all of the old x86 instruction execution code; adding
		a new (dummy) dyntrans module for x86.
		Taking the first steps to extend the dyntrans system to support
		variable-length instructions.
		Slowly preparing for the next release.
20050816	Adding a dummy SPARC cpu module.
		Minor updates (documentation etc) for the release.

==============  RELEASE 0.3.5  ==============


1 /*
2 * Copyright (C) 2003-2005 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.61 2005/08/07 19:12:12 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
39 #include "../config.h"
40
41
42 #ifndef ENABLE_MIPS
43
44
45 #include "cpu_mips.h"
46
47 /*
48 * mips_cpu_family_init():
49 *
50 * Bogus function.
51 */
52 int mips_cpu_family_init(struct cpu_family *fp)
53 {
54 return 0;
55 }
56
57
58 /* TODO: Maybe it isn't very nice to have these global like this... */
59 void mips_cpu_exception(struct cpu *cpu, int exccode, int tlb, uint64_t vaddr,
60 int coproc_nr, uint64_t vaddr_vpn2, int vaddr_asid, int x_64) { }
61
62
63 #else /* ENABLE_MIPS */
64
65
66 #include "arcbios.h"
67 #include "bintrans.h"
68 #include "cop0.h"
69 #include "cpu.h"
70 #include "cpu_mips.h"
71 #include "debugger.h"
72 #include "devices.h"
73 #include "emul.h"
74 #include "machine.h"
75 #include "memory.h"
76 #include "mips_cpu_types.h"
77 #include "opcodes_mips.h"
78 #include "symbol.h"
79
80
81 extern volatile int single_step;
82 extern int show_opcode_statistics;
83 extern int old_show_trace_tree;
84 extern int old_instruction_trace;
85 extern int old_quiet_mode;
86 extern int quiet_mode;
87
88 static char *exception_names[] = EXCEPTION_NAMES;
89
90 static char *hi6_names[] = HI6_NAMES;
91 static char *regimm_names[] = REGIMM_NAMES;
92 static char *special_names[] = SPECIAL_NAMES;
93 static char *special2_names[] = SPECIAL2_NAMES;
94
95 static char *regnames[] = MIPS_REGISTER_NAMES;
96 static char *cop0_names[] = COP0_NAMES;
97
98 #include "cpu_mips16.c"
99
100
101 /*
102 * regname():
103 *
104 * Convert a register number into either 'r0', 'r31' etc, or a symbolic
105 * name, depending on machine->show_symbolic_register_names.
106 *
107 * NOTE: _NOT_ reentrant.
108 */
109 static char *regname(struct machine *machine, int r)
110 {
111 static char ch[4];
112 ch[3] = ch[2] = '\0';
113
114 if (r<0 || r>=32)
115 strlcpy(ch, "xx", sizeof(ch));
116 else if (machine->show_symbolic_register_names)
117 strlcpy(ch, regnames[r], sizeof(ch));
118 else
119 snprintf(ch, sizeof(ch), "r%i", r);
120
121 return ch;
122 }
123
124
125 /*
126 * mips_cpu_new():
127 *
128 * Create a new MIPS cpu object.
129 *
130 * Returns 1 on success, 0 if there was no valid MIPS processor with
131 * a matching name.
132 */
133 int mips_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
134 int cpu_id, char *cpu_type_name)
135 {
136 int i, found, j, tags_size, n_cache_lines, size_per_cache_line;
137 struct mips_cpu_type_def cpu_type_defs[] = MIPS_CPU_TYPE_DEFS;
138 int64_t secondary_cache_size;
139 int x, linesize;
140
141 /* Scan the cpu_type_defs list for this cpu type: */
142 i = 0;
143 found = -1;
144 while (i >= 0 && cpu_type_defs[i].name != NULL) {
145 if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
146 found = i;
147 break;
148 }
149 i++;
150 }
151
152 if (found == -1)
153 return 0;
154
155 cpu->memory_rw = mips_memory_rw;
156 cpu->cd.mips.cpu_type = cpu_type_defs[found];
157 cpu->name = cpu->cd.mips.cpu_type.name;
158 cpu->byte_order = EMUL_LITTLE_ENDIAN;
159 cpu->cd.mips.gpr[MIPS_GPR_SP] = INITIAL_STACK_POINTER;
160 cpu->update_translation_table = mips_update_translation_table;
161 cpu->invalidate_translation_caches_paddr =
162 mips_invalidate_translation_caches_paddr;
163
164 if (cpu->cd.mips.cpu_type.isa_level <= 2 ||
165 cpu->cd.mips.cpu_type.isa_level == 32)
166 cpu->is_32bit = 1;
167
168 if (cpu_id == 0)
169 debug("%s", cpu->cd.mips.cpu_type.name);
170
171 /*
172 * CACHES:
173 *
174 * 1) Use DEFAULT_PCACHE_SIZE and DEFAULT_PCACHE_LINESIZE etc.
175 * 2) If there are specific values defined for this type of cpu,
176 * in its cpu_type substruct, then let's use those.
177 * 3) Values in the emul struct override both of the above.
178 *
179 * Once we've decided which values to use, they are stored in
180 * the emul struct so they can be used from src/machine.c etc.
181 */
182
183 x = DEFAULT_PCACHE_SIZE;
184 if (cpu->cd.mips.cpu_type.pdcache)
185 x = cpu->cd.mips.cpu_type.pdcache;
186 if (machine->cache_pdcache == 0)
187 machine->cache_pdcache = x;
188
189 x = DEFAULT_PCACHE_SIZE;
190 if (cpu->cd.mips.cpu_type.picache)
191 x = cpu->cd.mips.cpu_type.picache;
192 if (machine->cache_picache == 0)
193 machine->cache_picache = x;
194
195 if (machine->cache_secondary == 0)
196 machine->cache_secondary = cpu->cd.mips.cpu_type.scache;
197
198 linesize = DEFAULT_PCACHE_LINESIZE;
199 if (cpu->cd.mips.cpu_type.pdlinesize)
200 linesize = cpu->cd.mips.cpu_type.pdlinesize;
201 if (machine->cache_pdcache_linesize == 0)
202 machine->cache_pdcache_linesize = linesize;
203
204 linesize = DEFAULT_PCACHE_LINESIZE;
205 if (cpu->cd.mips.cpu_type.pilinesize)
206 linesize = cpu->cd.mips.cpu_type.pilinesize;
207 if (machine->cache_picache_linesize == 0)
208 machine->cache_picache_linesize = linesize;
209
210 linesize = 0;
211 if (cpu->cd.mips.cpu_type.slinesize)
212 linesize = cpu->cd.mips.cpu_type.slinesize;
213 if (machine->cache_secondary_linesize == 0)
214 machine->cache_secondary_linesize = linesize;
215
216
217 /*
218 * Primary Data and Instruction caches:
219 */
220 for (i=CACHE_DATA; i<=CACHE_INSTRUCTION; i++) {
221 switch (i) {
222 case CACHE_DATA:
223 x = 1 << machine->cache_pdcache;
224 linesize = 1 << machine->cache_pdcache_linesize;
225 break;
226 case CACHE_INSTRUCTION:
227 x = 1 << machine->cache_picache;
228 linesize = 1 << machine->cache_picache_linesize;
229 break;
230 }
231
232 /* Primary cache size and linesize: */
233 cpu->cd.mips.cache_size[i] = x;
234 cpu->cd.mips.cache_linesize[i] = linesize;
235
236 switch (cpu->cd.mips.cpu_type.rev) {
237 case MIPS_R2000:
238 case MIPS_R3000:
239 size_per_cache_line = sizeof(struct r3000_cache_line);
240 break;
241 default:
242 size_per_cache_line = sizeof(struct r4000_cache_line);
243 }
244
245 cpu->cd.mips.cache_mask[i] = cpu->cd.mips.cache_size[i] - 1;
246 cpu->cd.mips.cache_miss_penalty[i] = 10; /* TODO ? */
247
248 cpu->cd.mips.cache[i] = malloc(cpu->cd.mips.cache_size[i]);
249 if (cpu->cd.mips.cache[i] == NULL) {
250 fprintf(stderr, "out of memory\n");
251 }
252
253 n_cache_lines = cpu->cd.mips.cache_size[i] /
254 cpu->cd.mips.cache_linesize[i];
255 tags_size = n_cache_lines * size_per_cache_line;
256
257 cpu->cd.mips.cache_tags[i] = malloc(tags_size);
258 if (cpu->cd.mips.cache_tags[i] == NULL) {
259 fprintf(stderr, "out of memory\n");
260 }
261
262 /* Initialize the cache tags: */
263 switch (cpu->cd.mips.cpu_type.rev) {
264 case MIPS_R2000:
265 case MIPS_R3000:
266 for (j=0; j<n_cache_lines; j++) {
267 struct r3000_cache_line *rp;
268 rp = (struct r3000_cache_line *)
269 cpu->cd.mips.cache_tags[i];
270 rp[j].tag_paddr = 0;
271 rp[j].tag_valid = 0;
272 }
273 break;
274 default:
275 ;
276 }
277
278 /* Set cache_last_paddr to something "impossible": */
279 cpu->cd.mips.cache_last_paddr[i] = IMPOSSIBLE_PADDR;
280 }
281
282 /*
283 * Secondary cache:
284 */
285 secondary_cache_size = 0;
286 if (machine->cache_secondary)
287 secondary_cache_size = 1 << machine->cache_secondary;
288 /* TODO: linesize... */
289
290 if (cpu_id == 0) {
291 debug(" (I+D = %i+%i KB",
292 (int)(cpu->cd.mips.cache_size[CACHE_INSTRUCTION] / 1024),
293 (int)(cpu->cd.mips.cache_size[CACHE_DATA] / 1024));
294
295 if (secondary_cache_size != 0) {
296 debug(", L2 = ");
297 if (secondary_cache_size >= 1048576)
298 debug("%i MB", (int)
299 (secondary_cache_size / 1048576));
300 else
301 debug("%i KB", (int)
302 (secondary_cache_size / 1024));
303 }
304
305 debug(")");
306 }
307
308 /* System coprocessor (0), and FPU (1): */
309 cpu->cd.mips.coproc[0] = mips_coproc_new(cpu, 0);
310 cpu->cd.mips.coproc[1] = mips_coproc_new(cpu, 1);
311
312 /*
313 * Initialize the cpu->cd.mips.pc_last_* cache (a 1-entry cache of the
314 * last program counter value). For pc_last_virtual_page, any
315 * "impossible" value will do. The pc should never ever get this
316 * value. (The other pc_last* variables do not need initialization,
317 * as they are not used before pc_last_virtual_page.)
318 */
319 cpu->cd.mips.pc_last_virtual_page = PC_LAST_PAGE_IMPOSSIBLE_VALUE;
320
321 switch (cpu->cd.mips.cpu_type.mmu_model) {
322 case MMU3K:
323 cpu->translate_address = translate_address_mmu3k;
324 break;
325 case MMU8K:
326 cpu->translate_address = translate_address_mmu8k;
327 break;
328 case MMU10K:
329 cpu->translate_address = translate_address_mmu10k;
330 break;
331 default:
332 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
333 cpu->translate_address = translate_address_mmu4100;
334 else
335 cpu->translate_address = translate_address_generic;
336 }
337
338 /* Testing: */
339 cpu->cd.mips.host_load = zeroed_alloc(1048576 *
340 sizeof(unsigned char *));
341 cpu->cd.mips.host_store = zeroed_alloc(1048576 *
342 sizeof(unsigned char *));
343 cpu->cd.mips.host_load_orig = cpu->cd.mips.host_load;
344 cpu->cd.mips.host_store_orig = cpu->cd.mips.host_store;
345
346 return 1;
347 }
348
349
350 /*
351 * mips_cpu_show_full_statistics():
352 *
353 * Show detailed statistics on opcode usage on each cpu.
354 */
355 void mips_cpu_show_full_statistics(struct machine *m)
356 {
357 int i, s1, s2, iadd = 4;
358
359 if (m->bintrans_enable)
360 fatal("NOTE: Dynamic binary translation is used; this list"
361 " of opcode usage\n only includes instructions that"
362 " were interpreted manually!\n");
363
364 for (i=0; i<m->ncpus; i++) {
365 fatal("cpu%i opcode statistics:\n", i);
366 debug_indentation(iadd);
367
368 for (s1=0; s1<N_HI6; s1++) {
369 if (m->cpus[i]->cd.mips.stats_opcode[s1] > 0)
370 fatal("opcode %02x (%7s): %li\n", s1,
371 hi6_names[s1],
372 m->cpus[i]->cd.mips.stats_opcode[s1]);
373
374 debug_indentation(iadd);
375 if (s1 == HI6_SPECIAL)
376 for (s2=0; s2<N_SPECIAL; s2++)
377 if (m->cpus[i]->cd.mips.stats__special[
378 s2] > 0)
379 fatal("special %02x (%7s): "
380 "%li\n", s2, special_names[
381 s2], m->cpus[i]->cd.mips.
382 stats__special[s2]);
383 if (s1 == HI6_REGIMM)
384 for (s2=0; s2<N_REGIMM; s2++)
385 if (m->cpus[i]->cd.mips.stats__regimm[
386 s2] > 0)
387 fatal("regimm %02x (%7s): "
388 "%li\n", s2, regimm_names[
389 s2], m->cpus[i]->cd.mips.
390 stats__regimm[s2]);
391 if (s1 == HI6_SPECIAL2)
392 for (s2=0; s2<N_SPECIAL; s2++)
393 if (m->cpus[i]->cd.mips.stats__special2
394 [s2] > 0)
395 fatal("special2 %02x (%7s): "
396 "%li\n", s2,
397 special2_names[s2], m->
398 cpus[i]->cd.mips.
399 stats__special2[s2]);
400 debug_indentation(-iadd);
401 }
402
403 debug_indentation(-iadd);
404 }
405 }
406
407
408 /*
409 * mips_cpu_tlbdump():
410 *
411 * Called from the debugger to dump the TLB in a readable format.
412 * x is the cpu number to dump, or -1 to dump all CPUs.
413 *
414 * If rawflag is nonzero, then the TLB contents isn't formated nicely,
415 * just dumped.
416 */
417 void mips_cpu_tlbdump(struct machine *m, int x, int rawflag)
418 {
419 int i, j;
420
421 /* Nicely formatted output: */
422 if (!rawflag) {
423 for (i=0; i<m->ncpus; i++) {
424 int pageshift = 12;
425
426 if (x >= 0 && i != x)
427 continue;
428
429 if (m->cpus[i]->cd.mips.cpu_type.rev == MIPS_R4100)
430 pageshift = 10;
431
432 /* Print index, random, and wired: */
433 printf("cpu%i: (", i);
434 switch (m->cpus[i]->cd.mips.cpu_type.isa_level) {
435 case 1:
436 case 2:
437 printf("index=0x%x random=0x%x",
438 (int) ((m->cpus[i]->cd.mips.coproc[0]->
439 reg[COP0_INDEX] & R2K3K_INDEX_MASK)
440 >> R2K3K_INDEX_SHIFT),
441 (int) ((m->cpus[i]->cd.mips.coproc[0]->
442 reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
443 >> R2K3K_RANDOM_SHIFT));
444 break;
445 default:
446 printf("index=0x%x random=0x%x",
447 (int) (m->cpus[i]->cd.mips.coproc[0]->
448 reg[COP0_INDEX] & INDEX_MASK),
449 (int) (m->cpus[i]->cd.mips.coproc[0]->
450 reg[COP0_RANDOM] & RANDOM_MASK));
451 printf(" wired=0x%llx", (long long)
452 m->cpus[i]->cd.mips.coproc[0]->
453 reg[COP0_WIRED]);
454 }
455
456 printf(")\n");
457
458 for (j=0; j<m->cpus[i]->cd.mips.cpu_type.
459 nr_of_tlb_entries; j++) {
460 uint64_t hi,lo0,lo1,mask;
461 hi = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi;
462 lo0 = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0;
463 lo1 = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1;
464 mask = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask;
465
466 printf("%3i: ", j);
467 switch (m->cpus[i]->cd.mips.cpu_type.mmu_model) {
468 case MMU3K:
469 if (!(lo0 & R2K3K_ENTRYLO_V)) {
470 printf("(invalid)\n");
471 continue;
472 }
473 printf("vaddr=0x%08x ",
474 (int) (hi&R2K3K_ENTRYHI_VPN_MASK));
475 if (lo0 & R2K3K_ENTRYLO_G)
476 printf("(global), ");
477 else
478 printf("(asid %02x),",
479 (int) ((hi & R2K3K_ENTRYHI_ASID_MASK)
480 >> R2K3K_ENTRYHI_ASID_SHIFT));
481 printf(" paddr=0x%08x ",
482 (int) (lo0&R2K3K_ENTRYLO_PFN_MASK));
483 if (lo0 & R2K3K_ENTRYLO_N)
484 printf("N");
485 if (lo0 & R2K3K_ENTRYLO_D)
486 printf("D");
487 printf("\n");
488 break;
489 default:
490 switch (m->cpus[i]->cd.mips.cpu_type.mmu_model) {
491 case MMU10K:
492 printf("vaddr=0x%1x..%011llx ",
493 (int) (hi >> 60),
494 (long long) (hi&ENTRYHI_VPN2_MASK_R10K));
495 break;
496 case MMU32:
497 printf("vaddr=0x%08x ", (int)(hi&ENTRYHI_VPN2_MASK));
498 break;
499 default:/* R4000 etc. */
500 printf("vaddr=0x%1x..%010llx ",
501 (int) (hi >> 60),
502 (long long) (hi&ENTRYHI_VPN2_MASK));
503 }
504 if (hi & TLB_G)
505 printf("(global): ");
506 else
507 printf("(asid %02x):",
508 (int) (hi & ENTRYHI_ASID));
509
510 /* TODO: Coherency bits */
511
512 if (!(lo0 & ENTRYLO_V))
513 printf(" p0=(invalid) ");
514 else
515 printf(" p0=0x%09llx ", (long long)
516 (((lo0&ENTRYLO_PFN_MASK) >> ENTRYLO_PFN_SHIFT) << pageshift));
517 printf(lo0 & ENTRYLO_D? "D" : " ");
518
519 if (!(lo1 & ENTRYLO_V))
520 printf(" p1=(invalid) ");
521 else
522 printf(" p1=0x%09llx ", (long long)
523 (((lo1&ENTRYLO_PFN_MASK) >> ENTRYLO_PFN_SHIFT) << pageshift));
524 printf(lo1 & ENTRYLO_D? "D" : " ");
525 mask |= (1 << (pageshift+1)) - 1;
526 switch (mask) {
527 case 0x7ff: printf(" (1KB)"); break;
528 case 0x1fff: printf(" (4KB)"); break;
529 case 0x7fff: printf(" (16KB)"); break;
530 case 0x1ffff: printf(" (64KB)"); break;
531 case 0x7ffff: printf(" (256KB)"); break;
532 case 0x1fffff: printf(" (1MB)"); break;
533 case 0x7fffff: printf(" (4MB)"); break;
534 case 0x1ffffff: printf(" (16MB)"); break;
535 case 0x7ffffff: printf(" (64MB)"); break;
536 default:
537 printf(" (mask=%08x?)", (int)mask);
538 }
539 printf("\n");
540 }
541 }
542 }
543
544 return;
545 }
546
547 /* Raw output: */
548 for (i=0; i<m->ncpus; i++) {
549 if (x >= 0 && i != x)
550 continue;
551
552 /* Print index, random, and wired: */
553 printf("cpu%i: (", i);
554
555 if (m->cpus[i]->is_32bit)
556 printf("index=0x%08x random=0x%08x",
557 (int)m->cpus[i]->cd.mips.coproc[0]->reg[COP0_INDEX],
558 (int)m->cpus[i]->cd.mips.coproc[0]->reg[COP0_RANDOM]);
559 else
560 printf("index=0x%016llx random=0x%016llx", (long long)
561 m->cpus[i]->cd.mips.coproc[0]->reg[COP0_INDEX],
562 (long long)m->cpus[i]->cd.mips.coproc[0]->reg
563 [COP0_RANDOM]);
564
565 if (m->cpus[i]->cd.mips.cpu_type.isa_level >= 3)
566 printf(" wired=0x%llx", (long long)
567 m->cpus[i]->cd.mips.coproc[0]->reg[COP0_WIRED]);
568
569 printf(")\n");
570
571 for (j=0; j<m->cpus[i]->cd.mips.cpu_type.nr_of_tlb_entries; j++) {
572 if (m->cpus[i]->cd.mips.cpu_type.mmu_model == MMU3K)
573 printf("%3i: hi=0x%08x lo=0x%08x\n",
574 j,
575 (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
576 (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0);
577 else if (m->cpus[i]->is_32bit)
578 printf("%3i: hi=0x%08x mask=0x%08x "
579 "lo0=0x%08x lo1=0x%08x\n", j,
580 (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
581 (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask,
582 (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0,
583 (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1);
584 else
585 printf("%3i: hi=0x%016llx mask=0x%016llx "
586 "lo0=0x%016llx lo1=0x%016llx\n", j,
587 (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
588 (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask,
589 (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0,
590 (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1);
591 }
592 }
593 }
594
595
596 /*
597 * mips_cpu_register_match():
598 */
599 void mips_cpu_register_match(struct machine *m, char *name,
600 int writeflag, uint64_t *valuep, int *match_register)
601 {
602 int cpunr = 0;
603
604 /* CPU number: */
605
606 /* TODO */
607
608 /* Register name: */
609 if (strcasecmp(name, "pc") == 0) {
610 if (writeflag) {
611 m->cpus[cpunr]->pc = *valuep;
612 if (m->cpus[cpunr]->cd.mips.delay_slot) {
613 printf("NOTE: Clearing the delay slot"
614 " flag! (It was set before.)\n");
615 m->cpus[cpunr]->cd.mips.delay_slot = 0;
616 }
617 if (m->cpus[cpunr]->cd.mips.nullify_next) {
618 printf("NOTE: Clearing the nullify-ne"
619 "xt flag! (It was set before.)\n");
620 m->cpus[cpunr]->cd.mips.nullify_next = 0;
621 }
622 } else
623 *valuep = m->cpus[cpunr]->pc;
624 *match_register = 1;
625 } else if (strcasecmp(name, "hi") == 0) {
626 if (writeflag)
627 m->cpus[cpunr]->cd.mips.hi = *valuep;
628 else
629 *valuep = m->cpus[cpunr]->cd.mips.hi;
630 *match_register = 1;
631 } else if (strcasecmp(name, "lo") == 0) {
632 if (writeflag)
633 m->cpus[cpunr]->cd.mips.lo = *valuep;
634 else
635 *valuep = m->cpus[cpunr]->cd.mips.lo;
636 *match_register = 1;
637 } else if (name[0] == 'r' && isdigit((int)name[1])) {
638 int nr = atoi(name + 1);
639 if (nr >= 0 && nr < N_MIPS_GPRS) {
640 if (writeflag) {
641 if (nr != 0)
642 m->cpus[cpunr]->cd.mips.gpr[nr] = *valuep;
643 else
644 printf("WARNING: Attempt to modify r0.\n");
645 } else
646 *valuep = m->cpus[cpunr]->cd.mips.gpr[nr];
647 *match_register = 1;
648 }
649 } else {
650 /* Check for a symbolic name such as "t6" or "at": */
651 int nr;
652 for (nr=0; nr<N_MIPS_GPRS; nr++)
653 if (strcmp(name, regnames[nr]) == 0) {
654 if (writeflag) {
655 if (nr != 0)
656 m->cpus[cpunr]->cd.mips.gpr[nr] = *valuep;
657 else
658 printf("WARNING: Attempt to modify r0.\n");
659 } else
660 *valuep = m->cpus[cpunr]->cd.mips.gpr[nr];
661 *match_register = 1;
662 }
663 }
664
665 if (!(*match_register)) {
666 /* Check for a symbolic coproc0 name: */
667 int nr;
668 for (nr=0; nr<32; nr++)
669 if (strcmp(name, cop0_names[nr]) == 0) {
670 if (writeflag) {
671 coproc_register_write(m->cpus[cpunr],
672 m->cpus[cpunr]->cd.mips.coproc[0], nr,
673 valuep, 1, 0);
674 } else {
675 /* TODO: Use coproc_register_read instead? */
676 *valuep = m->cpus[cpunr]->cd.mips.coproc[0]->reg[nr];
677 }
678 *match_register = 1;
679 }
680 }
681
682 /* TODO: Coprocessor 1,2,3 registers. */
683 }
684
685
686 /*
687 * cpu_flags():
688 *
689 * Returns a pointer to a string containing "(d)" "(j)" "(dj)" or "",
690 * depending on the cpu's current delay_slot and last_was_jumptoself
691 * flags.
692 */
693 static const char *cpu_flags(struct cpu *cpu)
694 {
695 if (cpu->cd.mips.delay_slot) {
696 if (cpu->cd.mips.last_was_jumptoself)
697 return " (dj)";
698 else
699 return " (d)";
700 } else {
701 if (cpu->cd.mips.last_was_jumptoself)
702 return " (j)";
703 else
704 return "";
705 }
706 }
707
708
709 /*
710 * mips_cpu_disassemble_instr():
711 *
712 * Convert an instruction word into human readable format, for instruction
713 * tracing.
714 *
715 * If running is 1, cpu->pc should be the address of the instruction.
716 *
717 * If running is 0, things that depend on the runtime environment (eg.
718 * register contents) will not be shown, and addr will be used instead of
719 * cpu->pc for relative addresses.
720 *
721 * NOTE 2: coprocessor instructions are not decoded nicely yet (TODO)
722 */
723 int mips_cpu_disassemble_instr(struct cpu *cpu, unsigned char *originstr,
724 int running, uint64_t dumpaddr, int bintrans)
725 {
726 int hi6, special6, regimm5;
727 int rt, rd, rs, sa, imm, copz, cache_op, which_cache, showtag;
728 uint64_t addr, offset;
729 uint32_t instrword;
730 unsigned char instr[4];
731 char *symbol;
732
733 if (running)
734 dumpaddr = cpu->pc;
735
736 if ((dumpaddr & 3) != 0)
737 printf("WARNING: Unaligned address!\n");
738
739 symbol = get_symbol_name(&cpu->machine->symbol_context,
740 dumpaddr, &offset);
741 if (symbol != NULL && offset==0)
742 debug("<%s>\n", symbol);
743
744 if (cpu->machine->ncpus > 1 && running)
745 debug("cpu%i: ", cpu->cpu_id);
746
747 if (cpu->is_32bit)
748 debug("%08x", (int)dumpaddr);
749 else
750 debug("%016llx", (long long)dumpaddr);
751
752 *((uint32_t *)&instr[0]) = *((uint32_t *)&originstr[0]);
753
754 /*
755 * The rest of the code is written for little endian,
756 * so swap if necessary:
757 */
758 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
759 int tmp = instr[0]; instr[0] = instr[3];
760 instr[3] = tmp;
761 tmp = instr[1]; instr[1] = instr[2];
762 instr[2] = tmp;
763 }
764
765 debug(": %02x%02x%02x%02x",
766 instr[3], instr[2], instr[1], instr[0]);
767
768 if (running)
769 debug("%s", cpu_flags(cpu));
770
771 debug("\t");
772
773 if (bintrans && running) {
774 debug("(bintrans)");
775 goto disasm_ret;
776 }
777
778 /*
779 * Decode the instruction:
780 */
781
782 if (cpu->cd.mips.nullify_next && running) {
783 debug("(nullified)");
784 goto disasm_ret;
785 }
786
787 hi6 = (instr[3] >> 2) & 0x3f;
788
789 switch (hi6) {
790 case HI6_SPECIAL:
791 special6 = instr[0] & 0x3f;
792 switch (special6) {
793 case SPECIAL_SLL:
794 case SPECIAL_SRL:
795 case SPECIAL_SRA:
796 case SPECIAL_DSLL:
797 case SPECIAL_DSRL:
798 case SPECIAL_DSRA:
799 case SPECIAL_DSLL32:
800 case SPECIAL_DSRL32:
801 case SPECIAL_DSRA32:
802 rt = instr[2] & 31;
803 rd = (instr[1] >> 3) & 31;
804 sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
805
806 if (rd == 0 && special6 == SPECIAL_SLL) {
807 if (sa == 0)
808 debug("nop");
809 else if (sa == 1)
810 debug("ssnop");
811 else
812 debug("nop (weird, sa=%i)", sa);
813 goto disasm_ret;
814 } else
815 debug("%s\t%s,",
816 special_names[special6],
817 regname(cpu->machine, rd));
818 debug("%s,%i", regname(cpu->machine, rt), sa);
819 break;
820 case SPECIAL_DSRLV:
821 case SPECIAL_DSRAV:
822 case SPECIAL_DSLLV:
823 case SPECIAL_SLLV:
824 case SPECIAL_SRAV:
825 case SPECIAL_SRLV:
826 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
827 rt = instr[2] & 31;
828 rd = (instr[1] >> 3) & 31;
829 debug("%s\t%s",
830 special_names[special6], regname(cpu->machine, rd));
831 debug(",%s", regname(cpu->machine, rt));
832 debug(",%s", regname(cpu->machine, rs));
833 break;
834 case SPECIAL_JR:
835 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
836 symbol = get_symbol_name(&cpu->machine->symbol_context,
837 cpu->cd.mips.gpr[rs], &offset);
838 debug("jr\t%s", regname(cpu->machine, rs));
839 if (running && symbol != NULL)
840 debug("\t<%s>", symbol);
841 break;
842 case SPECIAL_JALR:
843 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
844 rd = (instr[1] >> 3) & 31;
845 symbol = get_symbol_name(&cpu->machine->symbol_context,
846 cpu->cd.mips.gpr[rs], &offset);
847 debug("jalr\t%s", regname(cpu->machine, rd));
848 debug(",%s", regname(cpu->machine, rs));
849 if (running && symbol != NULL)
850 debug("\t<%s>", symbol);
851 break;
852 case SPECIAL_MFHI:
853 case SPECIAL_MFLO:
854 rd = (instr[1] >> 3) & 31;
855 debug("%s\t%s", special_names[special6],
856 regname(cpu->machine, rd));
857 break;
858 case SPECIAL_MTLO:
859 case SPECIAL_MTHI:
860 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
861 debug("%s\t%s", special_names[special6],
862 regname(cpu->machine, rs));
863 break;
864 case SPECIAL_ADD:
865 case SPECIAL_ADDU:
866 case SPECIAL_SUB:
867 case SPECIAL_SUBU:
868 case SPECIAL_AND:
869 case SPECIAL_OR:
870 case SPECIAL_XOR:
871 case SPECIAL_NOR:
872 case SPECIAL_SLT:
873 case SPECIAL_SLTU:
874 case SPECIAL_DADD:
875 case SPECIAL_DADDU:
876 case SPECIAL_DSUB:
877 case SPECIAL_DSUBU:
878 case SPECIAL_MOVZ:
879 case SPECIAL_MOVN:
880 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
881 rt = instr[2] & 31;
882 rd = (instr[1] >> 3) & 31;
883 if ((special6 == SPECIAL_ADDU ||
884 special6 == SPECIAL_DADDU ||
885 special6 == SPECIAL_SUBU ||
886 special6 == SPECIAL_DSUBU) && rt == 0) {
887 /* Special case 1: addu/daddu/subu/dsubu with
888 rt = the zero register ==> move */
889 debug("move\t%s", regname(cpu->machine, rd));
890 debug(",%s", regname(cpu->machine, rs));
891 } else if ((special6 == SPECIAL_ADDU ||
892 special6 == SPECIAL_DADDU) && rs == 0) {
893 /* Special case 2: addu/daddu with
894 rs = the zero register ==> move */
895 debug("move\t%s", regname(cpu->machine, rd));
896 debug(",%s", regname(cpu->machine, rt));
897 } else {
898 debug("%s\t%s", special_names[special6],
899 regname(cpu->machine, rd));
900 debug(",%s", regname(cpu->machine, rs));
901 debug(",%s", regname(cpu->machine, rt));
902 }
903 break;
904 case SPECIAL_MULT:
905 case SPECIAL_MULTU:
906 case SPECIAL_DMULT:
907 case SPECIAL_DMULTU:
908 case SPECIAL_DIV:
909 case SPECIAL_DIVU:
910 case SPECIAL_DDIV:
911 case SPECIAL_DDIVU:
912 case SPECIAL_TGE:
913 case SPECIAL_TGEU:
914 case SPECIAL_TLT:
915 case SPECIAL_TLTU:
916 case SPECIAL_TEQ:
917 case SPECIAL_TNE:
918 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
919 rt = instr[2] & 31;
920 rd = (instr[1] >> 3) & 31;
921 if (special6 == SPECIAL_MULT) {
922 if (rd != 0) {
923 debug("mult_xx\t%s",
924 regname(cpu->machine, rd));
925 debug(",%s", regname(cpu->machine, rs));
926 debug(",%s", regname(cpu->machine, rt));
927 goto disasm_ret;
928 }
929 }
930 debug("%s\t%s", special_names[special6],
931 regname(cpu->machine, rs));
932 debug(",%s", regname(cpu->machine, rt));
933 break;
934 case SPECIAL_SYNC:
935 imm = ((instr[1] & 7) << 2) + (instr[0] >> 6);
936 debug("sync\t0x%02x", imm);
937 break;
938 case SPECIAL_SYSCALL:
939 imm = (((instr[3] << 24) + (instr[2] << 16) +
940 (instr[1] << 8) + instr[0]) >> 6) & 0xfffff;
941 if (imm != 0)
942 debug("syscall\t0x%05x", imm);
943 else
944 debug("syscall");
945 break;
946 case SPECIAL_BREAK:
947 imm = (((instr[3] << 24) + (instr[2] << 16) +
948 (instr[1] << 8) + instr[0]) >> 6) & 0xfffff;
949 if (imm != 0)
950 debug("break\t0x%05x", imm);
951 else
952 debug("break");
953 break;
954 case SPECIAL_MFSA:
955 rd = (instr[1] >> 3) & 31;
956 debug("mfsa\t%s", regname(cpu->machine, rd));
957 break;
958 case SPECIAL_MTSA:
959 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
960 debug("mtsa\t%s", regname(cpu->machine, rs));
961 break;
962 default:
963 debug("unimplemented special6 = 0x%02x", special6);
964 }
965 break;
966 case HI6_BEQ:
967 case HI6_BEQL:
968 case HI6_BNE:
969 case HI6_BNEL:
970 case HI6_BGTZ:
971 case HI6_BGTZL:
972 case HI6_BLEZ:
973 case HI6_BLEZL:
974 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
975 rt = instr[2] & 31;
976 imm = (instr[1] << 8) + instr[0];
977 if (imm >= 32768)
978 imm -= 65536;
979 addr = (dumpaddr + 4) + (imm << 2);
980 debug("%s\t", hi6_names[hi6]);
981
982 switch (hi6) {
983 case HI6_BEQ:
984 case HI6_BEQL:
985 case HI6_BNE:
986 case HI6_BNEL:
987 debug("%s,", regname(cpu->machine, rt));
988 }
989
990 debug("%s,", regname(cpu->machine, rs));
991
992 if (cpu->is_32bit)
993 debug("0x%08x", (int)addr);
994 else
995 debug("0x%016llx", (long long)addr);
996
997 symbol = get_symbol_name(&cpu->machine->symbol_context,
998 addr, &offset);
999 if (symbol != NULL && offset != addr)
1000 debug("\t<%s>", symbol);
1001 break;
1002 case HI6_ADDI:
1003 case HI6_ADDIU:
1004 case HI6_DADDI:
1005 case HI6_DADDIU:
1006 case HI6_SLTI:
1007 case HI6_SLTIU:
1008 case HI6_ANDI:
1009 case HI6_ORI:
1010 case HI6_XORI:
1011 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1012 rt = instr[2] & 31;
1013 imm = (instr[1] << 8) + instr[0];
1014 if (imm >= 32768)
1015 imm -= 65536;
1016 debug("%s\t%s,", hi6_names[hi6], regname(cpu->machine, rt));
1017 debug("%s,", regname(cpu->machine, rs));
1018 if (hi6 == HI6_ANDI || hi6 == HI6_ORI || hi6 == HI6_XORI)
1019 debug("0x%04x", imm & 0xffff);
1020 else
1021 debug("%i", imm);
1022 break;
1023 case HI6_LUI:
1024 rt = instr[2] & 31;
1025 imm = (instr[1] << 8) + instr[0];
1026 debug("lui\t%s,0x%x", regname(cpu->machine, rt), imm);
1027 break;
1028 case HI6_LB:
1029 case HI6_LBU:
1030 case HI6_LH:
1031 case HI6_LHU:
1032 case HI6_LW:
1033 case HI6_LWU:
1034 case HI6_LD:
1035 case HI6_LQ_MDMX:
1036 case HI6_LWC1:
1037 case HI6_LWC2:
1038 case HI6_LWC3:
1039 case HI6_LDC1:
1040 case HI6_LDC2:
1041 case HI6_LL:
1042 case HI6_LLD:
1043 case HI6_SB:
1044 case HI6_SH:
1045 case HI6_SW:
1046 case HI6_SD:
1047 case HI6_SQ:
1048 case HI6_SC:
1049 case HI6_SCD:
1050 case HI6_SWC1:
1051 case HI6_SWC2:
1052 case HI6_SWC3:
1053 case HI6_SDC1:
1054 case HI6_SDC2:
1055 case HI6_LWL:
1056 case HI6_LWR:
1057 case HI6_LDL:
1058 case HI6_LDR:
1059 case HI6_SWL:
1060 case HI6_SWR:
1061 case HI6_SDL:
1062 case HI6_SDR:
1063 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1064 rt = instr[2] & 31;
1065 imm = (instr[1] << 8) + instr[0];
1066 if (imm >= 32768)
1067 imm -= 65536;
1068 symbol = get_symbol_name(&cpu->machine->symbol_context,
1069 cpu->cd.mips.gpr[rs] + imm, &offset);
1070
1071 /* LWC3 is PREF in the newer ISA levels: */
1072 /* TODO: Which ISAs? IV? V? 32? 64? */
1073 if (cpu->cd.mips.cpu_type.isa_level >= 4 && hi6 == HI6_LWC3) {
1074 debug("pref\t0x%x,%i(%s)",
1075 rt, imm, regname(cpu->machine, rs));
1076
1077 if (running) {
1078 debug("\t[0x%016llx = %s]",
1079 (long long)(cpu->cd.mips.gpr[rs] + imm));
1080 if (symbol != NULL)
1081 debug(" = %s", symbol);
1082 debug("]");
1083 }
1084 goto disasm_ret;
1085 }
1086
1087 debug("%s\t", hi6_names[hi6]);
1088
1089 if (hi6 == HI6_SWC1 || hi6 == HI6_SWC2 || hi6 == HI6_SWC3 ||
1090 hi6 == HI6_SDC1 || hi6 == HI6_SDC2 ||
1091 hi6 == HI6_LWC1 || hi6 == HI6_LWC2 || hi6 == HI6_LWC3 ||
1092 hi6 == HI6_LDC1 || hi6 == HI6_LDC2)
1093 debug("r%i", rt);
1094 else
1095 debug("%s", regname(cpu->machine, rt));
1096
1097 debug(",%i(%s)", imm, regname(cpu->machine, rs));
1098
1099 if (running) {
1100 debug("\t[");
1101
1102 if (cpu->is_32bit)
1103 debug("0x%08x", (int)(cpu->cd.mips.gpr[rs] + imm));
1104 else
1105 debug("0x%016llx",
1106 (long long)(cpu->cd.mips.gpr[rs] + imm));
1107
1108 if (symbol != NULL)
1109 debug(" = %s", symbol);
1110
1111 debug(", data=");
1112 } else
1113 break;
1114 /* NOTE: No break here (if we are running) as it is up
1115 to the caller to print 'data'. */
1116 return sizeof(instrword);
1117 case HI6_J:
1118 case HI6_JAL:
1119 imm = (((instr[3] & 3) << 24) + (instr[2] << 16) +
1120 (instr[1] << 8) + instr[0]) << 2;
1121 addr = (dumpaddr + 4) & ~((1 << 28) - 1);
1122 addr |= imm;
1123 symbol = get_symbol_name(&cpu->machine->symbol_context,
1124 addr, &offset);
1125 debug("%s\t0x", hi6_names[hi6]);
1126 if (cpu->is_32bit)
1127 debug("%08x", (int)addr);
1128 else
1129 debug("%016llx", (long long)addr);
1130 if (symbol != NULL)
1131 debug("\t<%s>", symbol);
1132 break;
1133 case HI6_COP0:
1134 case HI6_COP1:
1135 case HI6_COP2:
1136 case HI6_COP3:
1137 imm = (instr[3] << 24) + (instr[2] << 16) +
1138 (instr[1] << 8) + instr[0];
1139 imm &= ((1 << 26) - 1);
1140
1141 /* Call coproc_function(), but ONLY disassembly, no exec: */
1142 coproc_function(cpu, cpu->cd.mips.coproc[hi6 - HI6_COP0],
1143 hi6 - HI6_COP0, imm, 1, running);
1144 return sizeof(instrword);
1145 case HI6_CACHE:
1146 rt = ((instr[3] & 3) << 3) + (instr[2] >> 5); /* base */
1147 copz = instr[2] & 31;
1148 imm = (instr[1] << 8) + instr[0];
1149 cache_op = copz >> 2;
1150 which_cache = copz & 3;
1151 showtag = 0;
1152 debug("cache\t0x%02x,0x%04x(%s)", copz, imm,
1153 regname(cpu->machine, rt));
1154 if (which_cache==0) debug(" [ primary I-cache");
1155 if (which_cache==1) debug(" [ primary D-cache");
1156 if (which_cache==2) debug(" [ secondary I-cache");
1157 if (which_cache==3) debug(" [ secondary D-cache");
1158 debug(", ");
1159 if (cache_op==0) debug("index invalidate");
1160 if (cache_op==1) debug("index load tag");
1161 if (cache_op==2) debug("index store tag"), showtag=1;
1162 if (cache_op==3) debug("create dirty exclusive");
1163 if (cache_op==4) debug("hit invalidate");
1164 if (cache_op==5) debug("fill OR hit writeback invalidate");
1165 if (cache_op==6) debug("hit writeback");
1166 if (cache_op==7) debug("hit set virtual");
1167 if (running)
1168 debug(", addr 0x%016llx",
1169 (long long)(cpu->cd.mips.gpr[rt] + imm));
1170 if (showtag)
1171 debug(", taghi=%08lx lo=%08lx",
1172 (long)cpu->cd.mips.coproc[0]->reg[COP0_TAGDATA_HI],
1173 (long)cpu->cd.mips.coproc[0]->reg[COP0_TAGDATA_LO]);
1174 debug(" ]");
1175 break;
1176 case HI6_SPECIAL2:
1177 special6 = instr[0] & 0x3f;
1178 instrword = (instr[3] << 24) + (instr[2] << 16) +
1179 (instr[1] << 8) + instr[0];
1180 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1181 rt = instr[2] & 31;
1182 rd = (instr[1] >> 3) & 31;
1183 if ((instrword & 0xfc0007ffULL) == 0x70000000) {
1184 debug("madd\t%s", regname(cpu->machine, rd));
1185 debug(",%s", regname(cpu->machine, rs));
1186 debug(",%s", regname(cpu->machine, rt));
1187 } else if (special6 == SPECIAL2_MUL) {
1188 /* TODO: this is just a guess, I don't have the
1189 docs in front of me */
1190 debug("mul\t%s", regname(cpu->machine, rd));
1191 debug(",%s", regname(cpu->machine, rs));
1192 debug(",%s", regname(cpu->machine, rt));
1193 } else if (special6 == SPECIAL2_CLZ) {
1194 debug("clz\t%s", regname(cpu->machine, rd));
1195 debug(",%s", regname(cpu->machine, rs));
1196 } else if (special6 == SPECIAL2_CLO) {
1197 debug("clo\t%s", regname(cpu->machine, rd));
1198 debug(",%s", regname(cpu->machine, rs));
1199 } else if (special6 == SPECIAL2_DCLZ) {
1200 debug("dclz\t%s", regname(cpu->machine, rd));
1201 debug(",%s", regname(cpu->machine, rs));
1202 } else if (special6 == SPECIAL2_DCLO) {
1203 debug("dclo\t%s", regname(cpu->machine, rd));
1204 debug(",%s", regname(cpu->machine, rs));
1205 } else if ((instrword & 0xffff07ffULL) == 0x70000209
1206 || (instrword & 0xffff07ffULL) == 0x70000249) {
1207 if (instr[0] == 0x49) {
1208 debug("pmflo\t%s", regname(cpu->machine, rd));
1209 debug(" (rs=%s)", regname(cpu->machine, rs));
1210 } else {
1211 debug("pmfhi\t%s", regname(cpu->machine, rd));
1212 debug(" (rs=%s)", regname(cpu->machine, rs));
1213 }
1214 } else if ((instrword & 0xfc1fffff) == 0x70000269
1215 || (instrword & 0xfc1fffff) == 0x70000229) {
1216 if (instr[0] == 0x69) {
1217 debug("pmtlo\t%s", regname(cpu->machine, rs));
1218 } else {
1219 debug("pmthi\t%s", regname(cpu->machine, rs));
1220 }
1221 } else if ((instrword & 0xfc0007ff) == 0x700004a9) {
1222 debug("por\t%s", regname(cpu->machine, rd));
1223 debug(",%s", regname(cpu->machine, rs));
1224 debug(",%s", regname(cpu->machine, rt));
1225 } else if ((instrword & 0xfc0007ff) == 0x70000488) {
1226 debug("pextlw\t%s", regname(cpu->machine, rd));
1227 debug(",%s", regname(cpu->machine, rs));
1228 debug(",%s", regname(cpu->machine, rt));
1229 } else {
1230 debug("unimplemented special2 = 0x%02x", special6);
1231 }
1232 break;
1233 case HI6_REGIMM:
1234 regimm5 = instr[2] & 0x1f;
1235 switch (regimm5) {
1236 case REGIMM_BLTZ:
1237 case REGIMM_BGEZ:
1238 case REGIMM_BLTZL:
1239 case REGIMM_BGEZL:
1240 case REGIMM_BLTZAL:
1241 case REGIMM_BLTZALL:
1242 case REGIMM_BGEZAL:
1243 case REGIMM_BGEZALL:
1244 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1245 imm = (instr[1] << 8) + instr[0];
1246 if (imm >= 32768)
1247 imm -= 65536;
1248
1249 debug("%s\t%s,", regimm_names[regimm5],
1250 regname(cpu->machine, rs));
1251
1252 addr = (dumpaddr + 4) + (imm << 2);
1253
1254 if (cpu->is_32bit)
1255 debug("0x%08x", (int)addr);
1256 else
1257 debug("0x%016llx", (long long)addr);
1258 break;
1259 default:
1260 debug("unimplemented regimm5 = 0x%02x", regimm5);
1261 }
1262 break;
1263 default:
1264 debug("unimplemented hi6 = 0x%02x", hi6);
1265 }
1266
1267 disasm_ret:
1268 debug("\n");
1269 return sizeof(instrword);
1270 }
1271
1272
1273 /*
1274 * mips_cpu_register_dump():
1275 *
1276 * Dump cpu registers in a relatively readable format.
1277 *
1278 * gprs: set to non-zero to dump GPRs and hi/lo/pc
1279 * coprocs: set bit 0..3 to dump registers in coproc 0..3.
1280 */
1281 void mips_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
1282 {
1283 int coprocnr, i, bits32;
1284 uint64_t offset;
1285 char *symbol;
1286
1287 bits32 = cpu->is_32bit;
1288
1289 if (gprs) {
1290 /* Special registers (pc, hi/lo) first: */
1291 symbol = get_symbol_name(&cpu->machine->symbol_context,
1292 cpu->pc, &offset);
1293
1294 if (bits32)
1295 debug("cpu%i: pc = %08x", cpu->cpu_id, (int)cpu->pc);
1296 else
1297 debug("cpu%i: pc = 0x%016llx",
1298 cpu->cpu_id, (long long)cpu->pc);
1299
1300 debug(" <%s>\n", symbol != NULL? symbol :
1301 " no symbol ");
1302
1303 if (bits32)
1304 debug("cpu%i: hi = %08x lo = %08x\n",
1305 cpu->cpu_id, (int)cpu->cd.mips.hi, (int)cpu->cd.mips.lo);
1306 else
1307 debug("cpu%i: hi = 0x%016llx lo = 0x%016llx\n",
1308 cpu->cpu_id, (long long)cpu->cd.mips.hi,
1309 (long long)cpu->cd.mips.lo);
1310
1311 /* General registers: */
1312 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
1313 /* 128-bit: */
1314 for (i=0; i<32; i++) {
1315 if ((i & 1) == 0)
1316 debug("cpu%i:", cpu->cpu_id);
1317 debug(" %3s=%016llx%016llx",
1318 regname(cpu->machine, i),
1319 (long long)cpu->cd.mips.gpr_quadhi[i],
1320 (long long)cpu->cd.mips.gpr[i]);
1321 if ((i & 1) == 1)
1322 debug("\n");
1323 }
1324 } else if (bits32) {
1325 /* 32-bit: */
1326 for (i=0; i<32; i++) {
1327 if ((i & 3) == 0)
1328 debug("cpu%i:", cpu->cpu_id);
1329 if (i == MIPS_GPR_ZERO)
1330 debug(" ");
1331 else
1332 debug(" %3s = %08x", regname(cpu->machine, i), (int)cpu->cd.mips.gpr[i]);
1333 if ((i & 3) == 3)
1334 debug("\n");
1335 }
1336 } else {
1337 /* 64-bit: */
1338 for (i=0; i<32; i++) {
1339 int r = (i >> 1) + ((i & 1) << 4);
1340 if ((i & 1) == 0)
1341 debug("cpu%i:", cpu->cpu_id);
1342 if (r == MIPS_GPR_ZERO)
1343 debug(" ");
1344 else
1345 debug(" %3s = 0x%016llx", regname(cpu->machine, r), (long long)cpu->cd.mips.gpr[r]);
1346 if ((i & 1) == 1)
1347 debug("\n");
1348 }
1349 }
1350 }
1351
1352 for (coprocnr=0; coprocnr<4; coprocnr++) {
1353 int nm1 = 1;
1354
1355 if (bits32)
1356 nm1 = 3;
1357
1358 if (!(coprocs & (1<<coprocnr)))
1359 continue;
1360 if (cpu->cd.mips.coproc[coprocnr] == NULL) {
1361 debug("cpu%i: no coprocessor %i\n",
1362 cpu->cpu_id, coprocnr);
1363 continue;
1364 }
1365
1366 /* Coprocessor registers: */
1367 /* TODO: multiple selections per register? */
1368 for (i=0; i<32; i++) {
1369 /* 32-bit: */
1370 if ((i & nm1) == 0)
1371 debug("cpu%i:", cpu->cpu_id);
1372
1373 if (cpu->machine->show_symbolic_register_names &&
1374 coprocnr == 0)
1375 debug(" %8s", cop0_names[i]);
1376 else
1377 debug(" c%i,%02i", coprocnr, i);
1378
1379 if (bits32)
1380 debug("=%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]);
1381 else {
1382 if (coprocnr == 0 && (i == COP0_COUNT
1383 || i == COP0_COMPARE || i == COP0_INDEX
1384 || i == COP0_RANDOM || i == COP0_WIRED))
1385 debug(" = 0x%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]);
1386 else
1387 debug(" = 0x%016llx", (long long)
1388 cpu->cd.mips.coproc[coprocnr]->reg[i]);
1389 }
1390
1391 if ((i & nm1) == nm1)
1392 debug("\n");
1393
1394 /* Skip the last 16 cop0 registers on R3000 etc. */
1395 if (coprocnr == 0 && cpu->cd.mips.cpu_type.isa_level < 3
1396 && i == 15)
1397 i = 31;
1398 }
1399
1400 if (coprocnr == 0 && cpu->cd.mips.cpu_type.isa_level >= 32) {
1401 debug("cpu%i: ", cpu->cpu_id);
1402 debug("config_select1 = 0x");
1403 if (cpu->is_32bit)
1404 debug("%08x", (int)cpu->cd.mips.cop0_config_select1);
1405 else
1406 debug("%016llx", (long long)cpu->cd.mips.cop0_config_select1);
1407 debug("\n");
1408 }
1409
1410 /* Floating point control registers: */
1411 if (coprocnr == 1) {
1412 for (i=0; i<32; i++)
1413 switch (i) {
1414 case 0: printf("cpu%i: fcr0 (fcir) = 0x%08x\n",
1415 cpu->cpu_id, (int)cpu->cd.mips.coproc[coprocnr]->fcr[i]);
1416 break;
1417 case 25:printf("cpu%i: fcr25 (fccr) = 0x%08x\n",
1418 cpu->cpu_id, (int)cpu->cd.mips.coproc[coprocnr]->fcr[i]);
1419 break;
1420 case 31:printf("cpu%i: fcr31 (fcsr) = 0x%08x\n",
1421 cpu->cpu_id, (int)cpu->cd.mips.coproc[coprocnr]->fcr[i]);
1422 break;
1423 }
1424 }
1425 }
1426 }
1427
1428
1429 #define DYNTRANS_FUNCTION_TRACE mips_cpu_functioncall_trace
1430 #define DYNTRANS_MIPS
1431 #define DYNTRANS_ARCH mips
1432 #include "cpu_dyntrans.c"
1433 #undef DYNTRANS_MIPS
1434 #undef DYNTRANS_ARCH
1435 #undef DYNTRANS_FUNCTION_TRACE
1436
1437
1438 /*
1439 * mips_cpu_interrupt():
1440 *
1441 * Cause an interrupt. If irq_nr is 2..7, then it is a MIPS hardware
1442 * interrupt. 0 and 1 are ignored (software interrupts).
1443 *
1444 * If irq_nr is >= 8, then this function calls md_interrupt().
1445 */
1446 int mips_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
1447 {
1448 if (irq_nr >= 8) {
1449 if (cpu->machine->md_interrupt != NULL)
1450 cpu->machine->md_interrupt(cpu->machine, cpu, irq_nr, 1);
1451 else
1452 fatal("mips_cpu_interrupt(): irq_nr = %i, but md_interrupt = NULL ?\n", irq_nr);
1453 return 1;
1454 }
1455
1456 if (irq_nr < 2)
1457 return 0;
1458
1459 cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] |= ((1 << irq_nr) << STATUS_IM_SHIFT);
1460 cpu->cd.mips.cached_interrupt_is_possible = 1;
1461 return 1;
1462 }
1463
1464
1465 /*
1466 * mips_cpu_interrupt_ack():
1467 *
1468 * Acknowledge an interrupt. If irq_nr is 2..7, then it is a MIPS hardware
1469 * interrupt. Interrupts 0..1 are ignored (software interrupts).
1470 *
1471 * If irq_nr is >= 8, then it is machine dependant, and md_interrupt() is
1472 * called.
1473 */
1474 int mips_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
1475 {
1476 if (irq_nr >= 8) {
1477 if (cpu->machine->md_interrupt != NULL)
1478 cpu->machine->md_interrupt(cpu->machine, cpu, irq_nr, 0);
1479 else
1480 fatal("mips_cpu_interrupt_ack(): irq_nr = %i, but md_interrupt = NULL ?\n", irq_nr);
1481 return 1;
1482 }
1483
1484 if (irq_nr < 2)
1485 return 0;
1486
1487 cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] &= ~((1 << irq_nr) << STATUS_IM_SHIFT);
1488 if (!(cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] & STATUS_IM_MASK))
1489 cpu->cd.mips.cached_interrupt_is_possible = 0;
1490
1491 return 1;
1492 }
1493
1494
1495 /*
1496 * mips_cpu_exception():
1497 *
1498 * Cause an exception in a CPU. This sets a couple of coprocessor 0
1499 * registers, and the program counter.
1500 *
1501 * exccode the exception code
1502 * tlb set to non-zero if the exception handler at
1503 * 0x80000000 should be used. (normal = 0x80000180)
1504 * vaddr virtual address (for some exceptions)
1505 * coproc_nr coprocessor number (for some exceptions)
1506 * vaddr_vpn2 vpn2 (for some exceptions)
1507 * vaddr_asid asid (for some exceptions)
1508 * x_64 non-zero for 64-bit mode for R4000-style tlb misses
1509 */
1510 void mips_cpu_exception(struct cpu *cpu, int exccode, int tlb, uint64_t vaddr,
1511 int coproc_nr, uint64_t vaddr_vpn2, int vaddr_asid, int x_64)
1512 {
1513 uint64_t base;
1514 uint64_t *reg = &cpu->cd.mips.coproc[0]->reg[0];
1515 int exc_model = cpu->cd.mips.cpu_type.exc_model;
1516
1517 if (!quiet_mode) {
1518 uint64_t offset;
1519 int x;
1520 char *symbol = get_symbol_name(&cpu->machine->symbol_context,
1521 cpu->cd.mips.pc_last, &offset);
1522
1523 debug("[ ");
1524 if (cpu->machine->ncpus > 1)
1525 debug("cpu%i: ", cpu->cpu_id);
1526
1527 debug("exception %s%s",
1528 exception_names[exccode], tlb? " <tlb>" : "");
1529
1530 switch (exccode) {
1531 case EXCEPTION_INT:
1532 debug(" cause_im=0x%02x", (int)((reg[COP0_CAUSE] & CAUSE_IP_MASK) >> CAUSE_IP_SHIFT));
1533 break;
1534 case EXCEPTION_SYS:
1535 debug(" v0=%i", (int)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1536 for (x=0; x<4; x++) {
1537 int64_t d = cpu->cd.mips.gpr[MIPS_GPR_A0 + x];
1538 char strbuf[30];
1539
1540 if (d > -256 && d < 256)
1541 debug(" a%i=%i", x, (int)d);
1542 else if (memory_points_to_string(cpu, cpu->mem, d, 1))
1543 debug(" a%i=\"%s\"", x, memory_conv_to_string(cpu, cpu->mem, d, strbuf, sizeof(strbuf)));
1544 else
1545 debug(" a%i=0x%llx", x, (long long)d);
1546 }
1547 break;
1548 default:
1549 if (cpu->is_32bit)
1550 debug(" vaddr=0x%08x", (int)vaddr);
1551 else
1552 debug(" vaddr=0x%016llx", (long long)vaddr);
1553 }
1554
1555 if (cpu->is_32bit)
1556 debug(" pc=0x%08x ", (int)cpu->cd.mips.pc_last);
1557 else
1558 debug(" pc=0x%016llx ", (long long)cpu->cd.mips.pc_last);
1559
1560 if (symbol != NULL)
1561 debug("<%s> ]\n", symbol);
1562 else
1563 debug("]\n");
1564 }
1565
1566 if (tlb && vaddr < 0x1000) {
1567 uint64_t offset;
1568 char *symbol = get_symbol_name(&cpu->machine->symbol_context,
1569 cpu->cd.mips.pc_last, &offset);
1570 fatal("[ ");
1571 if (cpu->machine->ncpus > 1)
1572 fatal("cpu%i: ", cpu->cpu_id);
1573 fatal("warning: LOW reference: vaddr=");
1574 if (cpu->is_32bit)
1575 fatal("0x%08x", (int)vaddr);
1576 else
1577 fatal("0x%016llx", (long long)vaddr);
1578 fatal(", exception %s, pc=", exception_names[exccode]);
1579 if (cpu->is_32bit)
1580 fatal("0x%08x", (int)cpu->cd.mips.pc_last);
1581 else
1582 fatal("0x%016llx", (long long)cpu->cd.mips.pc_last);
1583 fatal(" <%s> ]\n", symbol? symbol : "(no symbol)");
1584
1585 #ifdef TRACE_NULL_CRASHES
1586 /* This can be useful for debugging kernel bugs: */
1587 {
1588 int i = cpu->trace_null_index;
1589 do {
1590 fatal("TRACE: 0x%016llx\n",
1591 cpu->trace_null_addr[i]);
1592 i ++;
1593 i %= TRACE_NULL_N_ENTRIES;
1594 } while (i != cpu->trace_null_index);
1595 }
1596 cpu->running = 0;
1597 cpu->dead = 1;
1598 #endif
1599 }
1600
1601 /* Clear the exception code bits of the cause register... */
1602 if (exc_model == EXC3K)
1603 reg[COP0_CAUSE] &= ~R2K3K_CAUSE_EXCCODE_MASK;
1604 else
1605 reg[COP0_CAUSE] &= ~CAUSE_EXCCODE_MASK;
1606
1607 /* ... and OR in the exception code: */
1608 reg[COP0_CAUSE] |= (exccode << CAUSE_EXCCODE_SHIFT);
1609
1610 /* Always set CE (according to the R5000 manual): */
1611 reg[COP0_CAUSE] &= ~CAUSE_CE_MASK;
1612 reg[COP0_CAUSE] |= (coproc_nr << CAUSE_CE_SHIFT);
1613
1614 if (tlb || (exccode >= EXCEPTION_MOD && exccode <= EXCEPTION_ADES) ||
1615 exccode == EXCEPTION_VCEI || exccode == EXCEPTION_VCED) {
1616 reg[COP0_BADVADDR] = vaddr;
1617 #if 1
1618 /* TODO: This should be removed. */
1619 /* sign-extend vaddr, if it is 32-bit */
1620 if ((vaddr >> 32) == 0 && (vaddr & 0x80000000ULL))
1621 reg[COP0_BADVADDR] |=
1622 0xffffffff00000000ULL;
1623 #endif
1624 if (exc_model == EXC3K) {
1625 reg[COP0_CONTEXT] &= ~R2K3K_CONTEXT_BADVPN_MASK;
1626 reg[COP0_CONTEXT] |= ((vaddr_vpn2 << R2K3K_CONTEXT_BADVPN_SHIFT) & R2K3K_CONTEXT_BADVPN_MASK);
1627
1628 reg[COP0_ENTRYHI] = (vaddr & R2K3K_ENTRYHI_VPN_MASK)
1629 | (vaddr_asid << R2K3K_ENTRYHI_ASID_SHIFT);
1630
1631 /* Sign-extend: */
1632 reg[COP0_CONTEXT] = (int64_t)(int32_t)reg[COP0_CONTEXT];
1633 reg[COP0_ENTRYHI] = (int64_t)(int32_t)reg[COP0_ENTRYHI];
1634 } else {
1635 if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1636 reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK_R4100;
1637 reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK_R4100);
1638
1639 /* TODO: fix these */
1640 reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
1641 reg[COP0_XCONTEXT] &= ~XCONTEXT_BADVPN2_MASK;
1642 reg[COP0_XCONTEXT] |= (vaddr_vpn2 << XCONTEXT_BADVPN2_SHIFT) & XCONTEXT_BADVPN2_MASK;
1643 reg[COP0_XCONTEXT] |= ((vaddr >> 62) & 0x3) << XCONTEXT_R_SHIFT;
1644
1645 /* reg[COP0_PAGEMASK] = cpu->cd.mips.coproc[0]->tlbs[0].mask & PAGEMASK_MASK; */
1646
1647 reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK | 0x1800)) | vaddr_asid;
1648 } else {
1649 reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK;
1650 reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK);
1651
1652 reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
1653 reg[COP0_XCONTEXT] &= ~XCONTEXT_BADVPN2_MASK;
1654 reg[COP0_XCONTEXT] |= (vaddr_vpn2 << XCONTEXT_BADVPN2_SHIFT) & XCONTEXT_BADVPN2_MASK;
1655 reg[COP0_XCONTEXT] |= ((vaddr >> 62) & 0x3) << XCONTEXT_R_SHIFT;
1656
1657 /* reg[COP0_PAGEMASK] = cpu->cd.mips.coproc[0]->tlbs[0].mask & PAGEMASK_MASK; */
1658
1659 if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
1660 reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K)) | vaddr_asid;
1661 else
1662 reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK)) | vaddr_asid;
1663 }
1664 }
1665 }
1666
1667 if (exc_model == EXC4K && reg[COP0_STATUS] & STATUS_EXL) {
1668 /*
1669 * Don't set EPC if STATUS_EXL is set, for R4000 and up.
1670 * This actually happens when running IRIX and Ultrix, when
1671 * they handle interrupts and/or tlb updates, I think, so
1672 * printing this with debug() looks better than with fatal().
1673 */
1674 /* debug("[ warning: cpu%i exception while EXL is set, not setting EPC ]\n", cpu->cpu_id); */
1675 } else {
1676 if (cpu->cd.mips.delay_slot || cpu->cd.mips.nullify_next) {
1677 reg[COP0_EPC] = cpu->cd.mips.pc_last - 4;
1678 reg[COP0_CAUSE] |= CAUSE_BD;
1679
1680 /* TODO: Should the BD flag actually be set
1681 on nullified slots? */
1682 } else {
1683 reg[COP0_EPC] = cpu->cd.mips.pc_last;
1684 reg[COP0_CAUSE] &= ~CAUSE_BD;
1685 }
1686 }
1687
1688 cpu->cd.mips.delay_slot = NOT_DELAYED;
1689 cpu->cd.mips.nullify_next = 0;
1690
1691 /* TODO: This is true for MIPS64, but how about others? */
1692 if (reg[COP0_STATUS] & STATUS_BEV)
1693 base = 0xffffffffbfc00200ULL;
1694 else
1695 base = 0xffffffff80000000ULL;
1696
1697 switch (exc_model) {
1698 case EXC3K:
1699 /* Userspace tlb, vs others: */
1700 if (tlb && !(vaddr & 0x80000000ULL) &&
1701 (exccode == EXCEPTION_TLBL || exccode == EXCEPTION_TLBS) )
1702 cpu->pc = base + 0x000;
1703 else
1704 cpu->pc = base + 0x080;
1705 break;
1706 default:
1707 /*
1708 * These offsets are according to the MIPS64 manual, but
1709 * should work with R4000 and the rest too (I hope).
1710 *
1711 * 0x000 TLB refill, if EXL=0
1712 * 0x080 64-bit XTLB refill, if EXL=0
1713 * 0x100 cache error (not implemented yet)
1714 * 0x180 general exception
1715 * 0x200 interrupt (if CAUSE_IV is set)
1716 */
1717 if (tlb && (exccode == EXCEPTION_TLBL ||
1718 exccode == EXCEPTION_TLBS) &&
1719 !(reg[COP0_STATUS] & STATUS_EXL)) {
1720 if (x_64)
1721 cpu->pc = base + 0x080;
1722 else
1723 cpu->pc = base + 0x000;
1724 } else {
1725 if (exccode == EXCEPTION_INT &&
1726 (reg[COP0_CAUSE] & CAUSE_IV))
1727 cpu->pc = base + 0x200;
1728 else
1729 cpu->pc = base + 0x180;
1730 }
1731 }
1732
1733 if (exc_model == EXC3K) {
1734 /* R2000/R3000: Shift the lowest 6 bits to the left two steps: */
1735 reg[COP0_STATUS] =
1736 (reg[COP0_STATUS] & ~0x3f) +
1737 ((reg[COP0_STATUS] & 0xf) << 2);
1738 } else {
1739 /* R4000: */
1740 reg[COP0_STATUS] |= STATUS_EXL;
1741 }
1742
1743 /* Sign-extend: */
1744 reg[COP0_CAUSE] = (int64_t)(int32_t)reg[COP0_CAUSE];
1745 reg[COP0_STATUS] = (int64_t)(int32_t)reg[COP0_STATUS];
1746 }
1747
1748
1749 #ifdef BINTRANS
1750 /*
1751 * mips_cpu_cause_simple_exception():
1752 *
1753 * Useful for causing raw exceptions from bintrans, for example
1754 * SYSCALL or BREAK.
1755 */
1756 void mips_cpu_cause_simple_exception(struct cpu *cpu, int exc_code)
1757 {
1758 mips_cpu_exception(cpu, exc_code, 0, 0, 0, 0, 0, 0);
1759 }
1760 #endif
1761
1762
1763 /* Included here for better cache characteristics: */
1764 #include "memory_mips.c"
1765
1766
1767 /*
1768 * mips_cpu_run_instr():
1769 *
1770 * Execute one instruction on a cpu.
1771 *
1772 * If we are in a delay slot, set cpu->pc to cpu->cd.mips.delay_jmpaddr
1773 * after the instruction is executed.
1774 *
1775 * Return value is the number of instructions executed during this call,
1776 * 0 if no instruction was executed.
1777 */
1778 int mips_cpu_run_instr(struct emul *emul, struct cpu *cpu)
1779 {
1780 int quiet_mode_cached = quiet_mode;
1781 int instruction_trace_cached = cpu->machine->instruction_trace;
1782 struct mips_coproc *cp0 = cpu->cd.mips.coproc[0];
1783 int i, tmp, ninstrs_executed;
1784 unsigned char instr[4];
1785 uint32_t instrword;
1786 uint64_t cached_pc;
1787 int hi6, special6, regimm5, rd, rs, rt, sa, imm;
1788 int copz, which_cache, cache_op;
1789
1790 int cond, likely, and_link;
1791
1792 /* for unaligned load/store */
1793 uint64_t dir, is_left, reg_ofs, reg_dir;
1794
1795 uint64_t tmpvalue, tmpaddr;
1796
1797 int cpnr; /* coprocessor nr */
1798
1799 /* for load/store */
1800 uint64_t addr, value, value_hi, result_value;
1801 int wlen, st, signd, linked;
1802 unsigned char d[16]; /* room for at most 128 bits */
1803
1804
1805 /*
1806 * Update Coprocessor 0 registers:
1807 *
1808 * The COUNT register needs to be updated on every [other] instruction.
1809 * The RANDOM register should decrease for every instruction.
1810 */
1811
1812 if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
1813 int r = (cp0->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK) >> R2K3K_RANDOM_SHIFT;
1814 r --;
1815 if (r >= cp0->nr_of_tlbs || r < 8)
1816 r = cp0->nr_of_tlbs-1;
1817 cp0->reg[COP0_RANDOM] = r << R2K3K_RANDOM_SHIFT;
1818 } else {
1819 cp0->reg[COP0_RANDOM] --;
1820 if ((int64_t)cp0->reg[COP0_RANDOM] >= cp0->nr_of_tlbs ||
1821 (int64_t)cp0->reg[COP0_RANDOM] < (int64_t) cp0->reg[COP0_WIRED])
1822 cp0->reg[COP0_RANDOM] = cp0->nr_of_tlbs-1;
1823
1824 /*
1825 * TODO: only increase count every other instruction,
1826 * according to the R4000 manual. But according to the
1827 * R5000 manual: increment every other clock cycle.
1828 * Which one is it? :-)
1829 */
1830 cp0->reg[COP0_COUNT] = (int64_t)(int32_t)(cp0->reg[COP0_COUNT] + 1);
1831
1832 if (cpu->cd.mips.compare_register_set &&
1833 cp0->reg[COP0_COUNT] == cp0->reg[COP0_COMPARE]) {
1834 mips_cpu_interrupt(cpu, 7);
1835 cpu->cd.mips.compare_register_set = 0;
1836 }
1837 }
1838
1839
1840 #ifdef ENABLE_INSTRUCTION_DELAYS
1841 if (cpu->cd.mips.instruction_delay > 0) {
1842 cpu->cd.mips.instruction_delay --;
1843 return 1;
1844 }
1845 #endif
1846
1847 /* Cache the program counter in a local variable: */
1848 cached_pc = cpu->pc;
1849
1850 #ifdef TRACE_NULL_CRASHES
1851 cpu->trace_null_addr[cpu->trace_null_index] = cached_pc;
1852 cpu->trace_null_index ++;
1853 cpu->trace_null_index %= TRACE_NULL_N_ENTRIES;
1854 #endif
1855
1856 /* Hardwire the zero register to 0: */
1857 cpu->cd.mips.gpr[MIPS_GPR_ZERO] = 0;
1858
1859 if (cpu->cd.mips.delay_slot) {
1860 if (cpu->cd.mips.delay_slot == DELAYED) {
1861 cached_pc = cpu->pc = cpu->cd.mips.delay_jmpaddr;
1862 cpu->cd.mips.delay_slot = NOT_DELAYED;
1863 } else /* if (cpu->cd.mips.delay_slot == TO_BE_DELAYED) */ {
1864 /* next instruction will be delayed */
1865 cpu->cd.mips.delay_slot = DELAYED;
1866 }
1867 }
1868
1869 if (cpu->cd.mips.last_was_jumptoself > 0)
1870 cpu->cd.mips.last_was_jumptoself --;
1871
1872 /* Check PC against breakpoints: */
1873 if (!single_step)
1874 for (i=0; i<cpu->machine->n_breakpoints; i++)
1875 if (cached_pc == cpu->machine->breakpoint_addr[i]) {
1876 fatal("Breakpoint reached, pc=0x");
1877 if (cpu->is_32bit)
1878 fatal("%08x", (int)cached_pc);
1879 else
1880 fatal("%016llx", (long long)cached_pc);
1881 fatal("\n");
1882 single_step = 1;
1883 return 0;
1884 }
1885
1886
1887 /* Remember where we are, in case of interrupt or exception: */
1888 cpu->cd.mips.pc_last = cached_pc;
1889
1890 /*
1891 * Any pending interrupts?
1892 *
1893 * If interrupts are enabled, and any interrupt has arrived (ie its
1894 * bit in the cause register is set) and corresponding enable bits
1895 * in the status register are set, then cause an interrupt exception
1896 * instead of executing the current instruction.
1897 *
1898 * NOTE: cached_interrupt_is_possible is set to 1 whenever an
1899 * interrupt bit in the cause register is set to one (in
1900 * mips_cpu_interrupt()) and set to 0 whenever all interrupt bits are
1901 * cleared (in mips_cpu_interrupt_ack()), so we don't need to do a
1902 * full check each time.
1903 */
1904 if (cpu->cd.mips.cached_interrupt_is_possible && !cpu->cd.mips.nullify_next) {
1905 if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
1906 /* R3000: */
1907 int enabled, mask;
1908 int status = cp0->reg[COP0_STATUS];
1909
1910 enabled = status & MIPS_SR_INT_IE;
1911 mask = status & cp0->reg[COP0_CAUSE] & STATUS_IM_MASK;
1912 if (enabled && mask) {
1913 mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0, 0);
1914 return 0;
1915 }
1916 } else {
1917 /* R4000 and others: */
1918 int enabled, mask;
1919 int status = cp0->reg[COP0_STATUS];
1920
1921 enabled = (status & STATUS_IE)
1922 && !(status & STATUS_EXL)
1923 && !(status & STATUS_ERL);
1924
1925 mask = status & cp0->reg[COP0_CAUSE] & STATUS_IM_MASK;
1926 if (enabled && mask) {
1927 mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0, 0);
1928 return 0;
1929 }
1930 }
1931 }
1932
1933
1934 /*
1935 * ROM emulation: (0xbfcXXXXX or 0x9fcXXXXX)
1936 *
1937 * This assumes that a jal was made to a ROM address,
1938 * and we should return via gpr ra.
1939 */
1940 if ((cached_pc & 0xdff00000) == 0x9fc00000 &&
1941 cpu->machine->prom_emulation) {
1942 int rom_jal = 1, res = 1;
1943 switch (cpu->machine->machine_type) {
1944 case MACHINE_DEC:
1945 res = decstation_prom_emul(cpu);
1946 break;
1947 case MACHINE_PS2:
1948 res = playstation2_sifbios_emul(cpu);
1949 break;
1950 case MACHINE_ARC:
1951 case MACHINE_SGI:
1952 res = arcbios_emul(cpu);
1953 break;
1954 case MACHINE_EVBMIPS:
1955 res = yamon_emul(cpu);
1956 break;
1957 default:
1958 rom_jal = 0;
1959 }
1960
1961 if (rom_jal) {
1962 /*
1963 * Special hack: If the PROM emulation layer needs
1964 * to loop (for example when emulating blocking
1965 * console input) then we should simply return, so
1966 * that the same PROM routine is called on the next
1967 * round as well.
1968 *
1969 * This still has to count as one or more
1970 * instructions, so 1000 is returned. (Ugly.)
1971 */
1972 if (!res)
1973 return 1000;
1974
1975 cpu->pc = cpu->cd.mips.gpr[MIPS_GPR_RA];
1976 /* no need to update cached_pc, as we're returning */
1977 cpu->cd.mips.delay_slot = NOT_DELAYED;
1978
1979 if (cpu->machine->show_trace_tree)
1980 cpu_functioncall_trace_return(cpu);
1981
1982 /* TODO: how many instrs should this count as? */
1983 return 10;
1984 }
1985 }
1986
1987 #ifdef ALWAYS_SIGNEXTEND_32
1988 /*
1989 * An extra check for 32-bit mode to make sure that all
1990 * registers are sign-extended: (Slow, but might be useful
1991 * to detect bugs that have to do with sign-extension.)
1992 */
1993 if (cpu->is_32bit)
1994 int warning = 0;
1995 uint64_t x;
1996
1997 if (cpu->cd.mips.gpr[0] != 0) {
1998 fatal("\nWARNING: r0 was not zero! (%016llx)\n\n",
1999 (long long)cpu->cd.mips.gpr[0]);
2000 cpu->cd.mips.gpr[0] = 0;
2001 warning = 1;
2002 }
2003
2004 if (cpu->pc != (int64_t)(int32_t)cpu->pc) {
2005 fatal("\nWARNING: pc was not sign-extended correctly"
2006 " (%016llx)\n\n", (long long)cpu->pc);
2007 cpu->pc = (int64_t)(int32_t)cpu->pc;
2008 warning = 1;
2009 }
2010
2011 if (cpu->cd.mips.pc_last != (int64_t)(int32_t)cpu->cd.mips.pc_last) {
2012 fatal("\nWARNING: pc_last was not sign-extended correc"
2013 "tly (%016llx)\n\n", (long long)cpu->cd.mips.pc_last);
2014 cpu->cd.mips.pc_last = (int64_t)(int32_t)cpu->cd.mips.pc_last;
2015 warning = 1;
2016 }
2017
2018 /* Sign-extend ALL registers, including coprocessor registers and tlbs: */
2019 for (i=1; i<32; i++) {
2020 x = cpu->cd.mips.gpr[i];
2021 cpu->cd.mips.gpr[i] &= 0xffffffff;
2022 if (cpu->cd.mips.gpr[i] & 0x80000000ULL)
2023 cpu->cd.mips.gpr[i] |= 0xffffffff00000000ULL;
2024 if (x != cpu->cd.mips.gpr[i]) {
2025 fatal("\nWARNING: r%i (%s) was not sign-"
2026 "extended correctly (%016llx != "
2027 "%016llx)\n\n", i, regname(cpu->machine, i),
2028 (long long)x, (long long)cpu->cd.mips.gpr[i]);
2029 warning = 1;
2030 }
2031 }
2032 for (i=0; i<32; i++) {
2033 x = cpu->cd.mips.coproc[0]->reg[i];
2034 cpu->cd.mips.coproc[0]->reg[i] &= 0xffffffffULL;
2035 if (cpu->cd.mips.coproc[0]->reg[i] & 0x80000000ULL)
2036 cpu->cd.mips.coproc[0]->reg[i] |=
2037 0xffffffff00000000ULL;
2038 if (x != cpu->cd.mips.coproc[0]->reg[i]) {
2039 fatal("\nWARNING: cop0,r%i was not sign-extended correctly (%016llx != %016llx)\n\n",
2040 i, (long long)x, (long long)cpu->cd.mips.coproc[0]->reg[i]);
2041 warning = 1;
2042 }
2043 }
2044 for (i=0; i<cpu->cd.mips.coproc[0]->nr_of_tlbs; i++) {
2045 x = cpu->cd.mips.coproc[0]->tlbs[i].hi;
2046 cpu->cd.mips.coproc[0]->tlbs[i].hi &= 0xffffffffULL;
2047 if (cpu->cd.mips.coproc[0]->tlbs[i].hi & 0x80000000ULL)
2048 cpu->cd.mips.coproc[0]->tlbs[i].hi |=
2049 0xffffffff00000000ULL;
2050 if (x != cpu->cd.mips.coproc[0]->tlbs[i].hi) {
2051 fatal("\nWARNING: tlb[%i].hi was not sign-extended correctly (%016llx != %016llx)\n\n",
2052 i, (long long)x, (long long)cpu->cd.mips.coproc[0]->tlbs[i].hi);
2053 warning = 1;
2054 }
2055
2056 x = cpu->cd.mips.coproc[0]->tlbs[i].lo0;
2057 cpu->cd.mips.coproc[0]->tlbs[i].lo0 &= 0xffffffffULL;
2058 if (cpu->cd.mips.coproc[0]->tlbs[i].lo0 & 0x80000000ULL)
2059 cpu->cd.mips.coproc[0]->tlbs[i].lo0 |=
2060 0xffffffff00000000ULL;
2061 if (x != cpu->cd.mips.coproc[0]->tlbs[i].lo0) {
2062 fatal("\nWARNING: tlb[%i].lo0 was not sign-extended correctly (%016llx != %016llx)\n\n",
2063 i, (long long)x, (long long)cpu->cd.mips.coproc[0]->tlbs[i].lo0);
2064 warning = 1;
2065 }
2066 }
2067
2068 if (warning) {
2069 fatal("Halting. pc = %016llx\n", (long long)cpu->pc);
2070 cpu->running = 0;
2071 }
2072 }
2073 #endif
2074
2075 PREFETCH(cpu->cd.mips.pc_last_host_4k_page + (cached_pc & 0xfff));
2076
2077 #ifdef HALT_IF_PC_ZERO
2078 /* Halt if PC = 0: */
2079 if (cached_pc == 0) {
2080 debug("cpu%i: pc=0, halting\n", cpu->cpu_id);
2081 cpu->running = 0;
2082 return 0;
2083 }
2084 #endif
2085
2086 #ifdef BINTRANS
2087 if ((single_step || instruction_trace_cached)
2088 && cpu->machine->bintrans_enable)
2089 cpu->cd.mips.dont_run_next_bintrans = 1;
2090 #endif
2091
2092 if (!quiet_mode_cached) {
2093 /* Dump CPU registers for debugging: */
2094 if (cpu->machine->register_dump) {
2095 debug("\n");
2096 mips_cpu_register_dump(cpu, 1, 0x1);
2097 }
2098 }
2099
2100 /* Trace tree: */
2101 if (cpu->machine->show_trace_tree && cpu->cd.mips.show_trace_delay > 0) {
2102 cpu->cd.mips.show_trace_delay --;
2103 if (cpu->cd.mips.show_trace_delay == 0)
2104 cpu_functioncall_trace(cpu, cpu->cd.mips.show_trace_addr);
2105 }
2106
2107 #ifdef MFHILO_DELAY
2108 /* Decrease the MFHI/MFLO delays: */
2109 if (cpu->mfhi_delay > 0)
2110 cpu->mfhi_delay--;
2111 if (cpu->mflo_delay > 0)
2112 cpu->mflo_delay--;
2113 #endif
2114
2115 /* Read an instruction from memory: */
2116 #ifdef ENABLE_MIPS16
2117 if (cpu->cd.mips.mips16 && (cached_pc & 1)) {
2118 /* 16-bit instruction word: */
2119 unsigned char instr16[2];
2120 int mips16_offset = 0;
2121
2122 if (!cpu->memory_rw(cpu, cpu->mem, cached_pc ^ 1, &instr16[0],
2123 sizeof(instr16), MEM_READ, CACHE_INSTRUCTION))
2124 return 0;
2125
2126 /* TODO: If Reverse-endian is set in the status cop0 register, and
2127 we are in usermode, then reverse endianness! */
2128
2129 /* The rest of the code is written for little endian, so swap if necessary: */
2130 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2131 int tmp;
2132 tmp = instr16[0]; instr16[0] = instr16[1]; instr16[1] = tmp;
2133 }
2134
2135 cpu->cd.mips.mips16_extend = 0;
2136
2137 /*
2138 * Translate into 32-bit instruction, little endian (instr[3..0]):
2139 *
2140 * This ugly loop is necessary because if we would get an exception between
2141 * reading an extend instruction and the next instruction, and execution
2142 * continues on the second instruction, the extend data would be lost. So the
2143 * entire instruction (the two parts) need to be read in. If an exception is
2144 * caused, it will appear as if it was caused when reading the extend instruction.
2145 */
2146 while (mips16_to_32(cpu, instr16, instr) == 0) {
2147 if (instruction_trace_cached)
2148 debug("cpu%i @ %016llx: %02x%02x\t\t\textend\n",
2149 cpu->cpu_id, (cpu->cd.mips.pc_last ^ 1) + mips16_offset,
2150 instr16[1], instr16[0]);
2151
2152 /* instruction with extend: */
2153 mips16_offset += 2;
2154 if (!cpu->memory_rw(cpu, cpu->mem, (cached_pc ^ 1) +
2155 mips16_offset, &instr16[0], sizeof(instr16),
2156 MEM_READ, CACHE_INSTRUCTION))
2157 return 0;
2158
2159 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2160 int tmp;
2161 tmp = instr16[0]; instr16[0] = instr16[1]; instr16[1] = tmp;
2162 }
2163 }
2164
2165 /* TODO: bintrans like in 32-bit mode? */
2166
2167 /* Advance the program counter: */
2168 cpu->pc += sizeof(instr16) + mips16_offset;
2169 cached_pc = cpu->pc;
2170
2171 if (instruction_trace_cached) {
2172 uint64_t offset;
2173 char *symbol = get_symbol_name(&cpu->machine->
2174 symbol_context, cpu->cd.mips.pc_last ^ 1, &offset);
2175 if (symbol != NULL && offset==0)
2176 debug("<%s>\n", symbol);
2177
2178 debug("cpu%i @ %016llx: %02x%02x => %02x%02x%02x%02x%s\t",
2179 cpu->cpu_id, (cpu->cd.mips.pc_last ^ 1) + mips16_offset,
2180 instr16[1], instr16[0],
2181 instr[3], instr[2], instr[1], instr[0],
2182 cpu_flags(cpu));
2183 }
2184 } else
2185 #endif
2186 {
2187 /*
2188 * Fetch a 32-bit instruction word from memory:
2189 *
2190 * 1) The special case of reading an instruction from the
2191 * same host RAM page as the last one is handled here,
2192 * to gain a little bit performance.
2193 *
2194 * 2) Fallback to reading from memory the usual way.
2195 */
2196 if (cpu->cd.mips.pc_last_host_4k_page != NULL &&
2197 (cached_pc & ~0xfff) == cpu->cd.mips.pc_last_virtual_page) {
2198 /* NOTE: This only works on the host if offset is
2199 aligned correctly! (TODO) */
2200 *(uint32_t *)instr = *(uint32_t *)
2201 (cpu->cd.mips.pc_last_host_4k_page + (cached_pc & 0xffc));
2202 #ifdef BINTRANS
2203 cpu->cd.mips.pc_bintrans_paddr_valid = 1;
2204 cpu->cd.mips.pc_bintrans_paddr =
2205 cpu->cd.mips.pc_last_physical_page | (cached_pc & 0xfff);
2206 cpu->cd.mips.pc_bintrans_host_4kpage = cpu->cd.mips.pc_last_host_4k_page;
2207 #endif
2208 } else {
2209 if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
2210 sizeof(instr), MEM_READ, CACHE_INSTRUCTION))
2211 return 0;
2212 }
2213
2214 #ifdef BINTRANS
2215 if (cpu->cd.mips.dont_run_next_bintrans) {
2216 cpu->cd.mips.dont_run_next_bintrans = 0;
2217 } else if (cpu->machine->bintrans_enable &&
2218 cpu->cd.mips.pc_bintrans_paddr_valid) {
2219 int res;
2220 cpu->cd.mips.bintrans_instructions_executed = 0;
2221
2222 res = bintrans_attempt_translate(cpu,
2223 cpu->cd.mips.pc_bintrans_paddr);
2224
2225 if (res >= 0) {
2226 /* debug("BINTRANS translation + hit,"
2227 " pc = %016llx\n", (long long)cached_pc); */
2228 if (res > 0 || cpu->pc != cached_pc) {
2229 if (instruction_trace_cached)
2230 mips_cpu_disassemble_instr(cpu, instr, 1, 0, 1);
2231 if (res & BINTRANS_DONT_RUN_NEXT)
2232 cpu->cd.mips.dont_run_next_bintrans = 1;
2233 res &= BINTRANS_N_MASK;
2234
2235 if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
2236 int x = cp0->reg[COP0_COUNT], y = cp0->reg[COP0_COMPARE];
2237 int diff = x - y;
2238 if (diff < 0 && diff + (res-1) >= 0
2239 && cpu->cd.mips.compare_register_set) {
2240 mips_cpu_interrupt(cpu, 7);
2241 cpu->cd.mips.compare_register_set = 0;
2242 }
2243
2244 cp0->reg[COP0_COUNT] = (int64_t)
2245 (int32_t)(cp0->reg[COP0_COUNT] + res-1);
2246 }
2247
2248 return res;
2249 }
2250 }
2251 }
2252 #endif
2253
2254 if (instruction_trace_cached)
2255 mips_cpu_disassemble_instr(cpu, instr, 1, 0, 0);
2256
2257 /* Advance the program counter: */
2258 cpu->pc += sizeof(instr);
2259 cached_pc = cpu->pc;
2260
2261 /*
2262 * TODO: If Reverse-endian is set in the status cop0 register
2263 * and we are in usermode, then reverse endianness!
2264 */
2265
2266 /*
2267 * The rest of the code is written for little endian, so
2268 * swap if necessary:
2269 */
2270 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2271 int tmp = instr[0]; instr[0] = instr[3]; instr[3] = tmp;
2272 tmp = instr[1]; instr[1] = instr[2]; instr[2] = tmp;
2273 }
2274 }
2275
2276
2277 /*
2278 * Nullify this instruction? (Set by a previous branch-likely
2279 * instruction.)
2280 *
2281 * Note: The return value is 1, even if no instruction was actually
2282 * executed.
2283 */
2284 if (cpu->cd.mips.nullify_next) {
2285 cpu->cd.mips.nullify_next = 0;
2286 return 1;
2287 }
2288
2289
2290 /*
2291 * Execute the instruction:
2292 */
2293
2294 /* Get the top 6 bits of the instruction: */
2295 hi6 = instr[3] >> 2; /* & 0x3f */
2296
2297 if (show_opcode_statistics)
2298 cpu->cd.mips.stats_opcode[hi6] ++;
2299
2300 switch (hi6) {
2301 case HI6_SPECIAL:
2302 special6 = instr[0] & 0x3f;
2303
2304 if (show_opcode_statistics)
2305 cpu->cd.mips.stats__special[special6] ++;
2306
2307 switch (special6) {
2308 case SPECIAL_SLL:
2309 case SPECIAL_SRL:
2310 case SPECIAL_SRA:
2311 case SPECIAL_DSLL:
2312 case SPECIAL_DSRL:
2313 case SPECIAL_DSRA:
2314 case SPECIAL_DSLL32:
2315 case SPECIAL_DSRL32:
2316 case SPECIAL_DSRA32:
2317 rt = instr[2] & 31;
2318 rd = (instr[1] >> 3) & 31;
2319 sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
2320
2321 /*
2322 * Check for NOP:
2323 *
2324 * The R4000 manual says that a shift amount of zero
2325 * is treated as a nop by some assemblers. Checking
2326 * for sa == 0 here would not be correct, though,
2327 * because instructions such as sll r3,r4,0 are
2328 * possible, and are definitely not a nop.
2329 * Instead, check if the destination register is r0.
2330 *
2331 * TODO: ssnop should wait until the _next_
2332 * cycle boundary, or something like that. The
2333 * code here is incorrect.
2334 */
2335 if (rd == 0 && special6 == SPECIAL_SLL) {
2336 if (sa == 1) {
2337 /* ssnop */
2338 #ifdef ENABLE_INSTRUCTION_DELAYS
2339 cpu->cd.mips.instruction_delay +=
2340 cpu->cd.mips.cpu_type.
2341 instrs_per_cycle - 1;
2342 #endif
2343 }
2344 return 1;
2345 }
2346
2347 if (special6 == SPECIAL_SLL) {
2348 switch (sa) {
2349 case 8: cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << 8; break;
2350 case 16:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << 16; break;
2351 default:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << sa;
2352 }
2353 /* Sign-extend rd: */
2354 cpu->cd.mips.gpr[rd] = (int64_t) (int32_t) cpu->cd.mips.gpr[rd];
2355 }
2356 if (special6 == SPECIAL_DSLL) {
2357 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << sa;
2358 }
2359 if (special6 == SPECIAL_DSRL) {
2360 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2361 }
2362 if (special6 == SPECIAL_DSLL32) {
2363 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << (sa + 32);
2364 }
2365 if (special6 == SPECIAL_SRL) {
2366 /*
2367 * Three cases:
2368 * shift amount = zero: just copy
2369 * high bit of rt zero: plain shift right (of all bits)
2370 * high bit of rt one: plain shift right (of lowest 32 bits)
2371 */
2372 if (sa == 0)
2373 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2374 else if (!(cpu->cd.mips.gpr[rt] & 0x80000000ULL)) {
2375 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2376 } else
2377 cpu->cd.mips.gpr[rd] = (cpu->cd.mips.gpr[rt] & 0xffffffffULL) >> sa;
2378 }
2379 if (special6 == SPECIAL_SRA) {
2380 int topbit = cpu->cd.mips.gpr[rt] & 0x80000000ULL;
2381 switch (sa) {
2382 case 8: cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> 8; break;
2383 case 16:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> 16; break;
2384 default:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2385 }
2386 if (topbit)
2387 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2388 }
2389 if (special6 == SPECIAL_DSRL32) {
2390 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> (sa + 32);
2391 }
2392 if (special6 == SPECIAL_DSRA32 || special6 == SPECIAL_DSRA) {
2393 if (special6 == SPECIAL_DSRA32)
2394 sa += 32;
2395 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2396 while (sa > 0) {
2397 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2398 sa--;
2399 if (cpu->cd.mips.gpr[rd] & ((uint64_t)1 << 62)) /* old signbit */
2400 cpu->cd.mips.gpr[rd] |= ((uint64_t)1 << 63);
2401 }
2402 }
2403 return 1;
2404 case SPECIAL_DSRLV:
2405 case SPECIAL_DSRAV:
2406 case SPECIAL_DSLLV:
2407 case SPECIAL_SLLV:
2408 case SPECIAL_SRAV:
2409 case SPECIAL_SRLV:
2410 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2411 rt = instr[2] & 31;
2412 rd = (instr[1] >> 3) & 31;
2413
2414 if (special6 == SPECIAL_DSRLV) {
2415 sa = cpu->cd.mips.gpr[rs] & 63;
2416 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2417 }
2418 if (special6 == SPECIAL_DSRAV) {
2419 sa = cpu->cd.mips.gpr[rs] & 63;
2420 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2421 while (sa > 0) {
2422 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2423 sa--;
2424 if (cpu->cd.mips.gpr[rd] & ((uint64_t)1 << 62)) /* old sign-bit */
2425 cpu->cd.mips.gpr[rd] |= ((uint64_t)1 << 63);
2426 }
2427 }
2428 if (special6 == SPECIAL_DSLLV) {
2429 sa = cpu->cd.mips.gpr[rs] & 63;
2430 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2431 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] << sa;
2432 }
2433 if (special6 == SPECIAL_SLLV) {
2434 sa = cpu->cd.mips.gpr[rs] & 31;
2435 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2436 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] << sa;
2437 /* Sign-extend rd: */
2438 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2439 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2440 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2441 }
2442 if (special6 == SPECIAL_SRAV) {
2443 sa = cpu->cd.mips.gpr[rs] & 31;
2444 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2445 /* Sign-extend rd: */
2446 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2447 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2448 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2449 while (sa > 0) {
2450 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2451 sa--;
2452 }
2453 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2454 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2455 }
2456 if (special6 == SPECIAL_SRLV) {
2457 sa = cpu->cd.mips.gpr[rs] & 31;
2458 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2459 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2460 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> sa;
2461 /* And finally sign-extend rd: */
2462 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2463 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2464 }
2465 return 1;
2466 case SPECIAL_JR:
2467 if (cpu->cd.mips.delay_slot) {
2468 fatal("jr: jump inside a jump's delay slot, or similar. TODO\n");
2469 cpu->running = 0;
2470 return 1;
2471 }
2472
2473 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2474
2475 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
2476 cpu->cd.mips.delay_jmpaddr = cpu->cd.mips.gpr[rs];
2477
2478 if (cpu->machine->show_trace_tree && rs == 31)
2479 cpu_functioncall_trace_return(cpu);
2480
2481 return 1;
2482 case SPECIAL_JALR:
2483 if (cpu->cd.mips.delay_slot) {
2484 fatal("jalr: jump inside a jump's delay slot, or similar. TODO\n");
2485 cpu->running = 0;
2486 return 1;
2487 }
2488
2489 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2490 rd = (instr[1] >> 3) & 31;
2491
2492 tmpvalue = cpu->cd.mips.gpr[rs];
2493 cpu->cd.mips.gpr[rd] = cached_pc + 4;
2494 /* already increased by 4 earlier */
2495
2496 if (cpu->machine->show_trace_tree && rd == 31) {
2497 cpu->cd.mips.show_trace_delay = 2;
2498 cpu->cd.mips.show_trace_addr = tmpvalue;
2499 }
2500
2501 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
2502 cpu->cd.mips.delay_jmpaddr = tmpvalue;
2503 return 1;
2504 case SPECIAL_MFHI:
2505 case SPECIAL_MFLO:
2506 rd = (instr[1] >> 3) & 31;
2507
2508 if (special6 == SPECIAL_MFHI) {
2509 cpu->cd.mips.gpr[rd] = cpu->cd.mips.hi;
2510 #ifdef MFHILO_DELAY
2511 cpu->mfhi_delay = 3;
2512 #endif
2513 }
2514 if (special6 == SPECIAL_MFLO) {
2515 cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
2516 #ifdef MFHILO_DELAY
2517 cpu->mflo_delay = 3;
2518 #endif
2519 }
2520 return 1;
2521 case SPECIAL_ADD:
2522 case SPECIAL_ADDU:
2523 case SPECIAL_SUB:
2524 case SPECIAL_SUBU:
2525 case SPECIAL_AND:
2526 case SPECIAL_OR:
2527 case SPECIAL_XOR:
2528 case SPECIAL_NOR:
2529 case SPECIAL_SLT:
2530 case SPECIAL_SLTU:
2531 case SPECIAL_MTLO:
2532 case SPECIAL_MTHI:
2533 case SPECIAL_MULT:
2534 case SPECIAL_MULTU:
2535 case SPECIAL_DMULT:
2536 case SPECIAL_DMULTU:
2537 case SPECIAL_DIV:
2538 case SPECIAL_DIVU:
2539 case SPECIAL_DDIV:
2540 case SPECIAL_DDIVU:
2541 case SPECIAL_TGE:
2542 case SPECIAL_TGEU:
2543 case SPECIAL_TLT:
2544 case SPECIAL_TLTU:
2545 case SPECIAL_TEQ:
2546 case SPECIAL_TNE:
2547 case SPECIAL_DADD:
2548 case SPECIAL_DADDU:
2549 case SPECIAL_DSUB:
2550 case SPECIAL_DSUBU:
2551 case SPECIAL_MOVZ:
2552 case SPECIAL_MOVN:
2553 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2554 rt = instr[2] & 31;
2555 rd = (instr[1] >> 3) & 31;
2556
2557 #ifdef MFHILO_DELAY
2558 if (cpu->mflo_delay > 0 && (
2559 special6 == SPECIAL_DDIV || special6 == SPECIAL_DDIVU ||
2560 special6 == SPECIAL_DIV || special6 == SPECIAL_DIVU ||
2561 special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU ||
2562 special6 == SPECIAL_MTLO || special6 == SPECIAL_MULT
2563 || special6 == SPECIAL_MULTU
2564 ) )
2565 debug("warning: instruction modifying LO too early after mflo!\n");
2566
2567 if (cpu->mfhi_delay > 0 && (
2568 special6 == SPECIAL_DDIV || special6 == SPECIAL_DDIVU ||
2569 special6 == SPECIAL_DIV || special6 == SPECIAL_DIVU ||
2570 special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU ||
2571 special6 == SPECIAL_MTHI || special6 == SPECIAL_MULT
2572 || special6 == SPECIAL_MULTU
2573 ) )
2574 debug("warning: instruction modifying HI too early after mfhi!\n");
2575 #endif
2576
2577 if (special6 == SPECIAL_ADDU) {
2578 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2579 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2580 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2581 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2582 break;
2583 }
2584 if (special6 == SPECIAL_ADD) {
2585 /* According to the MIPS64 manual: */
2586 uint64_t temp, temp1, temp2;
2587 temp1 = cpu->cd.mips.gpr[rs] + ((cpu->cd.mips.gpr[rs] & 0x80000000ULL) << 1);
2588 temp2 = cpu->cd.mips.gpr[rt] + ((cpu->cd.mips.gpr[rt] & 0x80000000ULL) << 1);
2589 temp = temp1 + temp2;
2590 #if 0
2591 /* TODO: apparently this doesn't work (an example of
2592 something that breaks is NetBSD/sgimips' mips3_TBIA() */
2593 /* If bits 32 and 31 of temp differ, then it's an overflow */
2594 temp1 = temp & 0x100000000ULL;
2595 temp2 = temp & 0x80000000ULL;
2596 if ((temp1 && !temp2) || (!temp1 && temp2)) {
2597 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
2598 break;
2599 }
2600 #endif
2601 cpu->cd.mips.gpr[rd] = temp & 0xffffffffULL;
2602 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2603 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2604 break;
2605 }
2606 if (special6 == SPECIAL_SUBU) {
2607 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2608 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2609 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2610 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2611 break;
2612 }
2613 if (special6 == SPECIAL_SUB) {
2614 /* According to the MIPS64 manual: */
2615 uint64_t temp, temp1, temp2;
2616 temp1 = cpu->cd.mips.gpr[rs] + ((cpu->cd.mips.gpr[rs] & 0x80000000ULL) << 1);
2617 temp2 = cpu->cd.mips.gpr[rt] + ((cpu->cd.mips.gpr[rt] & 0x80000000ULL) << 1);
2618 temp = temp1 - temp2;
2619 #if 0
2620 /* If bits 32 and 31 of temp differ, then it's an overflow */
2621 temp1 = temp & 0x100000000ULL;
2622 temp2 = temp & 0x80000000ULL;
2623 if ((temp1 && !temp2) || (!temp1 && temp2)) {
2624 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
2625 break;
2626 }
2627 #endif
2628 cpu->cd.mips.gpr[rd] = temp & 0xffffffffULL;
2629 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2630 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2631 break;
2632 }
2633
2634 if (special6 == SPECIAL_AND) {
2635 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] & cpu->cd.mips.gpr[rt];
2636 break;
2637 }
2638 if (special6 == SPECIAL_OR) {
2639 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt];
2640 break;
2641 }
2642 if (special6 == SPECIAL_XOR) {
2643 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] ^ cpu->cd.mips.gpr[rt];
2644 break;
2645 }
2646 if (special6 == SPECIAL_NOR) {
2647 cpu->cd.mips.gpr[rd] = ~(cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt]);
2648 break;
2649 }
2650 if (special6 == SPECIAL_SLT) {
2651 cpu->cd.mips.gpr[rd] = (int64_t)cpu->cd.mips.gpr[rs] < (int64_t)cpu->cd.mips.gpr[rt];
2652 break;
2653 }
2654 if (special6 == SPECIAL_SLTU) {
2655 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] < cpu->cd.mips.gpr[rt];
2656 break;
2657 }
2658 if (special6 == SPECIAL_MTLO) {
2659 cpu->cd.mips.lo = cpu->cd.mips.gpr[rs];
2660 break;
2661 }
2662 if (special6 == SPECIAL_MTHI) {
2663 cpu->cd.mips.hi = cpu->cd.mips.gpr[rs];
2664 break;
2665 }
2666 if (special6 == SPECIAL_MULT) {
2667 int64_t f1, f2, sum;
2668 f1 = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2669 /* sign extend f1 */
2670 if (f1 & 0x80000000ULL)
2671 f1 |= 0xffffffff00000000ULL;
2672 f2 = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2673 /* sign extend f2 */
2674 if (f2 & 0x80000000ULL)
2675 f2 |= 0xffffffff00000000ULL;
2676 sum = f1 * f2;
2677
2678 cpu->cd.mips.lo = sum & 0xffffffffULL;
2679 cpu->cd.mips.hi = ((uint64_t)sum >> 32) & 0xffffffffULL;
2680
2681 /* sign-extend: */
2682 if (cpu->cd.mips.lo & 0x80000000ULL)
2683 cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2684 if (cpu->cd.mips.hi & 0x80000000ULL)
2685 cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2686
2687 /*
2688 * NOTE: The stuff about rd!=0 is just a
2689 * guess, judging from how some NetBSD code
2690 * seems to execute. It is not documented in
2691 * the MIPS64 ISA docs :-/
2692 */
2693
2694 if (rd != 0) {
2695 if (cpu->cd.mips.cpu_type.rev != MIPS_R5900)
2696 debug("WARNING! mult_xx is an undocumented instruction!");
2697 cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
2698 }
2699 break;
2700 }
2701 if (special6 == SPECIAL_MULTU) {
2702 uint64_t f1, f2, sum;
2703 /* zero extend f1 and f2 */
2704 f1 = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2705 f2 = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2706 sum = f1 * f2;
2707 cpu->cd.mips.lo = sum & 0xffffffffULL;
2708 cpu->cd.mips.hi = (sum >> 32) & 0xffffffffULL;
2709
2710 /* sign-extend: */
2711 if (cpu->cd.mips.lo & 0x80000000ULL)
2712 cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2713 if (cpu->cd.mips.hi & 0x80000000ULL)
2714 cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2715 break;
2716 }
2717 if (special6 == SPECIAL_DMULT) {
2718 /* 64x64 = 128 bit multiplication, signed. */
2719 uint64_t s1 = cpu->cd.mips.gpr[rt];
2720 uint64_t s2 = cpu->cd.mips.gpr[rs];
2721 int n_negative = 0;
2722 int i;
2723
2724 if ((int64_t)s1 < 0) {
2725 s1 = -(int64_t)s1;
2726 n_negative ++;
2727 }
2728 if ((int64_t)s2 < 0) {
2729 s2 = -(int64_t)s2;
2730 n_negative ++;
2731 }
2732
2733 cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2734
2735 for (i=0; i<64; i++) {
2736 int bit = (s1 & 0x8000000000000000ULL)? 1 : 0;
2737 s1 <<= 1;
2738 /* If bit in s1 set, then add s2 to hi/lo: */
2739 if (bit) {
2740 uint64_t old_lo = cpu->cd.mips.lo;
2741 cpu->cd.mips.lo += s2;
2742 if (cpu->cd.mips.lo < old_lo)
2743 cpu->cd.mips.hi ++;
2744 }
2745 if (i != 63) {
2746 cpu->cd.mips.hi <<= 1;
2747 cpu->cd.mips.hi +=
2748 (cpu->cd.mips.lo & 0x8000000000000000ULL) ? 1 : 0;
2749 cpu->cd.mips.lo <<= 1;
2750 }
2751 }
2752
2753 if (n_negative == 1) {
2754 cpu->cd.mips.hi = -(int64_t)cpu->cd.mips.hi;
2755 cpu->cd.mips.lo = -(int64_t)cpu->cd.mips.lo;
2756 if ((int64_t)cpu->cd.mips.lo < 0)
2757 cpu->cd.mips.hi --;
2758 }
2759 break;
2760 }
2761 if (special6 == SPECIAL_DMULTU) {
2762 /* 64x64 = 128 bit multiplication, unsigned. */
2763 uint64_t s1 = cpu->cd.mips.gpr[rt];
2764 uint64_t s2 = cpu->cd.mips.gpr[rs];
2765 int i;
2766
2767 cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2768
2769 for (i=0; i<64; i++) {
2770 int bit = (s1 & 0x8000000000000000ULL)? 1 : 0;
2771 s1 <<= 1;
2772 /* If bit in s1 set, then add s2 to hi/lo: */
2773 if (bit) {
2774 uint64_t old_lo = cpu->cd.mips.lo;
2775 cpu->cd.mips.lo += s2;
2776 if (cpu->cd.mips.lo < old_lo)
2777 cpu->cd.mips.hi ++;
2778 }
2779 if (i != 63) {
2780 cpu->cd.mips.hi <<= 1;
2781 cpu->cd.mips.hi +=
2782 (cpu->cd.mips.lo & 0x8000000000000000ULL) ? 1 : 0;
2783 cpu->cd.mips.lo <<= 1;
2784 }
2785 }
2786 break;
2787 }
2788 if (special6 == SPECIAL_DIV) {
2789 int64_t a, b;
2790 /* Signextend rs and rt: */
2791 a = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2792 if (a & 0x80000000ULL)
2793 a |= 0xffffffff00000000ULL;
2794 b = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2795 if (b & 0x80000000ULL)
2796 b |= 0xffffffff00000000ULL;
2797
2798 if (b == 0) {
2799 /* undefined */
2800 cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2801 } else {
2802 cpu->cd.mips.lo = a / b;
2803 cpu->cd.mips.hi = a % b;
2804 }
2805 /* Sign-extend lo and hi: */
2806 cpu->cd.mips.lo &= 0xffffffffULL;
2807 if (cpu->cd.mips.lo & 0x80000000ULL)
2808 cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2809 cpu->cd.mips.hi &= 0xffffffffULL;
2810 if (cpu->cd.mips.hi & 0x80000000ULL)
2811 cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2812 break;
2813 }
2814 if (special6 == SPECIAL_DIVU) {
2815 int64_t a, b;
2816 /* Zero-extend rs and rt: */
2817 a = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2818 b = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2819 if (b == 0) {
2820 /* undefined */
2821 cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2822 } else {
2823 cpu->cd.mips.lo = a / b;
2824 cpu->cd.mips.hi = a % b;
2825 }
2826 /* Sign-extend lo and hi: */
2827 cpu->cd.mips.lo &= 0xffffffffULL;
2828 if (cpu->cd.mips.lo & 0x80000000ULL)
2829 cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2830 cpu->cd.mips.hi &= 0xffffffffULL;
2831 if (cpu->cd.mips.hi & 0x80000000ULL)
2832 cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2833 break;
2834 }
2835 if (special6 == SPECIAL_DDIV) {
2836 if (cpu->cd.mips.gpr[rt] == 0) {
2837 cpu->cd.mips.lo = cpu->cd.mips.hi = 0; /* undefined */
2838 } else {
2839 cpu->cd.mips.lo = (int64_t)cpu->cd.mips.gpr[rs] / (int64_t)cpu->cd.mips.gpr[rt];
2840 cpu->cd.mips.hi = (int64_t)cpu->cd.mips.gpr[rs] % (int64_t)cpu->cd.mips.gpr[rt];
2841 }
2842 break;
2843 }
2844 if (special6 == SPECIAL_DDIVU) {
2845 if (cpu->cd.mips.gpr[rt] == 0) {
2846 cpu->cd.mips.lo = cpu->cd.mips.hi = 0; /* undefined */
2847 } else {
2848 cpu->cd.mips.lo = cpu->cd.mips.gpr[rs] / cpu->cd.mips.gpr[rt];
2849 cpu->cd.mips.hi = cpu->cd.mips.gpr[rs] % cpu->cd.mips.gpr[rt];
2850 }
2851 break;
2852 }
2853 if (special6 == SPECIAL_TGE) {
2854 if ((int64_t)cpu->cd.mips.gpr[rs] >= (int64_t)cpu->cd.mips.gpr[rt])
2855 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2856 break;
2857 }
2858 if (special6 == SPECIAL_TGEU) {
2859 if (cpu->cd.mips.gpr[rs] >= cpu->cd.mips.gpr[rt])
2860 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2861 break;
2862 }
2863 if (special6 == SPECIAL_TLT) {
2864 if ((int64_t)cpu->cd.mips.gpr[rs] < (int64_t)cpu->cd.mips.gpr[rt])
2865 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2866 break;
2867 }
2868 if (special6 == SPECIAL_TLTU) {
2869 if (cpu->cd.mips.gpr[rs] < cpu->cd.mips.gpr[rt])
2870 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2871 break;
2872 }
2873 if (special6 == SPECIAL_TEQ) {
2874 if (cpu->cd.mips.gpr[rs] == cpu->cd.mips.gpr[rt])
2875 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2876 break;
2877 }
2878 if (special6 == SPECIAL_TNE) {
2879 if (cpu->cd.mips.gpr[rs] != cpu->cd.mips.gpr[rt])
2880 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2881 break;
2882 }
2883 if (special6 == SPECIAL_DADD) {
2884 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2885 /* TODO: exception on overflow */
2886 break;
2887 }
2888 if (special6 == SPECIAL_DADDU) {
2889 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2890 break;
2891 }
2892 if (special6 == SPECIAL_DSUB) {
2893 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2894 /* TODO: exception on overflow */
2895 break;
2896 }
2897 if (special6 == SPECIAL_DSUBU) {
2898 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2899 break;
2900 }
2901 if (special6 == SPECIAL_MOVZ) {
2902 if (cpu->cd.mips.gpr[rt] == 0)
2903 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs];
2904 break;
2905 }
2906 if (special6 == SPECIAL_MOVN) {
2907 if (cpu->cd.mips.gpr[rt] != 0)
2908 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs];
2909 return 1;
2910 }
2911 return 1;
2912 case SPECIAL_SYNC:
2913 /* imm = ((instr[1] & 7) << 2) + (instr[0] >> 6); */
2914 /* TODO: actually sync */
2915
2916 /* Clear the LLbit (at least on R10000): */
2917 cpu->cd.mips.rmw = 0;
2918 return 1;
2919 case SPECIAL_SYSCALL:
2920 imm = ((instr[3] << 24) + (instr[2] << 16) +
2921 (instr[1] << 8) + instr[0]) >> 6;
2922 imm &= 0xfffff;
2923
2924 if (cpu->machine->userland_emul != NULL)
2925 useremul_syscall(cpu, imm);
2926 else
2927 mips_cpu_exception(cpu, EXCEPTION_SYS,
2928 0, 0, 0, 0, 0, 0);
2929 return 1;
2930 case SPECIAL_BREAK:
2931 mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
2932 return 1;
2933 case SPECIAL_MFSA:
2934 /* R5900? Move from shift amount register? */
2935 /* rd = (instr[1] >> 3) & 31; */
2936 /* TODO */
2937 return 1;
2938 case SPECIAL_MTSA:
2939 /* R5900? Move to shift amount register? */
2940 /* rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7); */
2941 /* TODO */
2942 return 1;
2943 default:
2944 if (!instruction_trace_cached) {
2945 fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
2946 cpu->cpu_id, (long long)cpu->cd.mips.pc_last,
2947 instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
2948 }
2949 fatal("unimplemented special6 = 0x%02x\n", special6);
2950 cpu->running = 0;
2951 return 1;
2952 }
2953 return 1;
2954 case HI6_BEQ:
2955 case HI6_BEQL:
2956 case HI6_BNE:
2957 case HI6_BGTZ:
2958 case HI6_BGTZL:
2959 case HI6_BLEZ:
2960 case HI6_BLEZL:
2961 case HI6_BNEL:
2962 case HI6_ADDI:
2963 case HI6_ADDIU:
2964 case HI6_DADDI:
2965 case HI6_DADDIU:
2966 case HI6_SLTI:
2967 case HI6_SLTIU:
2968 case HI6_ANDI:
2969 case HI6_ORI:
2970 case HI6_XORI:
2971 case HI6_LUI:
2972 case HI6_LB:
2973 case HI6_LBU:
2974 case HI6_LH:
2975 case HI6_LHU:
2976 case HI6_LW:
2977 case HI6_LWU:
2978 case HI6_LD:
2979 case HI6_LQ_MDMX:
2980 case HI6_LWC1:
2981 case HI6_LWC2:
2982 case HI6_LWC3:
2983 case HI6_LDC1:
2984 case HI6_LDC2:
2985 case HI6_LL:
2986 case HI6_LLD:
2987 case HI6_SB:
2988 case HI6_SH:
2989 case HI6_SW:
2990 case HI6_SD:
2991 case HI6_SQ:
2992 case HI6_SC:
2993 case HI6_SCD:
2994 case HI6_SWC1:
2995 case HI6_SWC2:
2996 case HI6_SWC3:
2997 case HI6_SDC1:
2998 case HI6_SDC2:
2999 case HI6_LWL: /* Unaligned load/store */
3000 case HI6_LWR:
3001 case HI6_LDL:
3002 case HI6_LDR:
3003 case HI6_SWL:
3004 case HI6_SWR:
3005 case HI6_SDL:
3006 case HI6_SDR:
3007 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3008 rt = instr[2] & 31;
3009 imm = (instr[1] << 8) + instr[0];
3010 if (imm >= 32768) /* signed 16-bit */
3011 imm -= 65536;
3012
3013 tmpvalue = imm; /* used later in several cases */
3014
3015 switch (hi6) {
3016 case HI6_ADDI:
3017 case HI6_ADDIU:
3018 case HI6_DADDI:
3019 case HI6_DADDIU:
3020 tmpvalue = cpu->cd.mips.gpr[rs];
3021 result_value = cpu->cd.mips.gpr[rs] + imm;
3022
3023 if (hi6 == HI6_ADDI || hi6 == HI6_DADDI) {
3024 /*
3025 * addi and daddi should trap on overflow:
3026 *
3027 * TODO: This is incorrect? The R4000 manual
3028 * says that overflow occurs if the carry bits
3029 * out of bit 62 and 63 differ. The
3030 * destination register should not be modified
3031 * on overflow.
3032 */
3033 if (imm >= 0) {
3034 /* Turn around from 0x7fff.. to 0x800 ? Then overflow. */
3035 if ( ((hi6 == HI6_ADDI && (result_value &
3036 0x80000000ULL) && (tmpvalue &
3037 0x80000000ULL)==0))
3038 || ((hi6 == HI6_DADDI && (result_value &
3039 0x8000000000000000ULL) && (tmpvalue &
3040 0x8000000000000000ULL)==0)) ) {
3041 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
3042 break;
3043 }
3044 } else {
3045 /* Turn around from 0x8000.. to 0x7fff.. ? Then overflow. */
3046 if ( ((hi6 == HI6_ADDI && (result_value &
3047 0x80000000ULL)==0 && (tmpvalue &
3048 0x80000000ULL)))
3049 || ((hi6 == HI6_DADDI && (result_value &
3050 0x8000000000000000ULL)==0 && (tmpvalue &
3051 0x8000000000000000ULL))) ) {
3052 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
3053 break;
3054 }
3055 }
3056 }
3057
3058 cpu->cd.mips.gpr[rt] = result_value;
3059
3060 /*
3061 * Super-ugly speed-hack: (only if speed_tricks != 0)
3062 * NOTE: This makes the emulation less correct.
3063 *
3064 * If we encounter a loop such as:
3065 *
3066 * 8012f5f4: 1c40ffff bgtz r0,r2,ffffffff8012f5f4
3067 * 8012f5f8: 2442ffff (d) addiu r2,r2,-1
3068 *
3069 * then it is a small loop which simply waits for r2
3070 * to become zero.
3071 *
3072 * TODO: increaste the count register, and cause
3073 * interrupts!!! For now: return as if we just
3074 * executed 1 instruction.
3075 */
3076 ninstrs_executed = 1;
3077 if (cpu->machine->speed_tricks && cpu->cd.mips.delay_slot &&
3078 cpu->cd.mips.last_was_jumptoself &&
3079 cpu->cd.mips.jump_to_self_reg == rt &&
3080 cpu->cd.mips.jump_to_self_reg == rs) {
3081 if ((int64_t)cpu->cd.mips.gpr[rt] > 1 && (int64_t)cpu->cd.mips.gpr[rt] < 0x70000000
3082 && (imm >= -30000 && imm <= -1)) {
3083 if (instruction_trace_cached)
3084 debug("changing r%i from %016llx to", rt, (long long)cpu->cd.mips.gpr[rt]);
3085
3086 while ((int64_t)cpu->cd.mips.gpr[rt] > 0 && ninstrs_executed < 1000
3087 && ((int64_t)cpu->cd.mips.gpr[rt] + (int64_t)imm) > 0) {
3088 cpu->cd.mips.gpr[rt] += (int64_t)imm;
3089 ninstrs_executed += 2;
3090 }
3091
3092 if (instruction_trace_cached)
3093 debug(" %016llx\n", (long long)cpu->cd.mips.gpr[rt]);
3094
3095 /* TODO: return value, cpu->cd.mips.gpr[rt] * 2; */
3096 }
3097 if ((int64_t)cpu->cd.mips.gpr[rt] > -0x70000000 && (int64_t)cpu->cd.mips.gpr[rt] < -1
3098 && (imm >= 1 && imm <= 30000)) {
3099 if (instruction_trace_cached)
3100 debug("changing r%i from %016llx to", rt, (long long)cpu->cd.mips.gpr[rt]);
3101
3102 while ((int64_t)cpu->cd.mips.gpr[rt] < 0 && ninstrs_executed < 1000
3103 && ((int64_t)cpu->cd.mips.gpr[rt] + (int64_t)imm) < 0) {
3104 cpu->cd.mips.gpr[rt] += (int64_t)imm;
3105 ninstrs_executed += 2;
3106 }
3107
3108 if (instruction_trace_cached)
3109 debug(" %016llx\n", (long long)cpu->cd.mips.gpr[rt]);
3110 }
3111 }
3112
3113 if (hi6 == HI6_ADDI || hi6 == HI6_ADDIU) {
3114 /* Sign-extend: */
3115 cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
3116 if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
3117 cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
3118 }
3119 return ninstrs_executed;
3120 case HI6_BEQ:
3121 case HI6_BNE:
3122 case HI6_BGTZ:
3123 case HI6_BGTZL:
3124 case HI6_BLEZ:
3125 case HI6_BLEZL:
3126 case HI6_BEQL:
3127 case HI6_BNEL:
3128 if (cpu->cd.mips.delay_slot) {
3129 fatal("b*: jump inside a jump's delay slot, or similar. TODO\n");
3130 cpu->running = 0;
3131 return 1;
3132 }
3133 likely = cond = 0;
3134 switch (hi6) {
3135 case HI6_BNEL: likely = 1;
3136 case HI6_BNE: cond = (cpu->cd.mips.gpr[rt] != cpu->cd.mips.gpr[rs]);
3137 break;
3138 case HI6_BEQL: likely = 1;
3139 case HI6_BEQ: cond = (cpu->cd.mips.gpr[rt] == cpu->cd.mips.gpr[rs]);
3140 break;
3141 case HI6_BLEZL: likely = 1;
3142 case HI6_BLEZ: cond = ((int64_t)cpu->cd.mips.gpr[rs] <= 0);
3143 break;
3144 case HI6_BGTZL: likely = 1;
3145 case HI6_BGTZ: cond = ((int64_t)cpu->cd.mips.gpr[rs] > 0);
3146 break;
3147 }
3148
3149 if (cond) {
3150 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3151 cpu->cd.mips.delay_jmpaddr = cached_pc + (imm << 2);
3152 } else {
3153 if (likely)
3154 cpu->cd.mips.nullify_next = 1; /* nullify delay slot */
3155 }
3156
3157 if (imm==-1 && (hi6 == HI6_BGTZ || hi6 == HI6_BLEZ ||
3158 (hi6 == HI6_BGTZL && cond) ||
3159 (hi6 == HI6_BLEZL && cond) ||
3160 (hi6 == HI6_BNE && (rt==0 || rs==0)) ||
3161 (hi6 == HI6_BEQ && (rt==0 || rs==0)))) {
3162 cpu->cd.mips.last_was_jumptoself = 2;
3163 if (rs == 0)
3164 cpu->cd.mips.jump_to_self_reg = rt;
3165 else
3166 cpu->cd.mips.jump_to_self_reg = rs;
3167 }
3168 return 1;
3169 case HI6_LUI:
3170 cpu->cd.mips.gpr[rt] = (imm << 16);
3171 /* No sign-extending necessary, as imm already
3172 was sign-extended if it was negative. */
3173 break;
3174 case HI6_SLTI:
3175 cpu->cd.mips.gpr[rt] = (int64_t)cpu->cd.mips.gpr[rs] < (int64_t)tmpvalue;
3176 break;
3177 case HI6_SLTIU:
3178 cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] < (uint64_t)imm;
3179 break;
3180 case HI6_ANDI:
3181 cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] & (tmpvalue & 0xffff);
3182 break;
3183 case HI6_ORI:
3184 cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] | (tmpvalue & 0xffff);
3185 break;
3186 case HI6_XORI:
3187 cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] ^ (tmpvalue & 0xffff);
3188 break;
3189 case HI6_LB:
3190 case HI6_LBU:
3191 case HI6_LH:
3192 case HI6_LHU:
3193 case HI6_LW:
3194 case HI6_LWU:
3195 case HI6_LD:
3196 case HI6_LQ_MDMX:
3197 case HI6_LWC1:
3198 case HI6_LWC2:
3199 case HI6_LWC3: /* pref */
3200 case HI6_LDC1:
3201 case HI6_LDC2:
3202 case HI6_LL:
3203 case HI6_LLD:
3204 case HI6_SB:
3205 case HI6_SH:
3206 case HI6_SW:
3207 case HI6_SD:
3208 case HI6_SQ:
3209 case HI6_SC:
3210 case HI6_SCD:
3211 case HI6_SWC1:
3212 case HI6_SWC2:
3213 case HI6_SWC3:
3214 case HI6_SDC1:
3215 case HI6_SDC2:
3216 /* These are the default "assumptions". */
3217 linked = 0;
3218 st = 1;
3219 signd = 1;
3220 wlen = 4;
3221
3222 switch (hi6) {
3223 /* The most common ones: */
3224 case HI6_LW: { st = 0; } break;
3225 case HI6_SW: { signd = 0; } break;
3226
3227 case HI6_LB: { wlen = 1; st = 0; } break;
3228 case HI6_LBU: { wlen = 1; st = 0; signd = 0; } break;
3229 case HI6_SB: { wlen = 1; signd = 0; } break;
3230
3231 case HI6_LD: { wlen = 8; st = 0; signd = 0; } break;
3232 case HI6_SD: { wlen = 8; signd = 0; } break;
3233
3234 case HI6_LQ_MDMX: { wlen = 16; st = 0; signd = 0; } break; /* R5900, otherwise MDMX (TODO) */
3235 case HI6_SQ: { wlen = 16; signd = 0; } break; /* R5900 ? */
3236
3237 /* The rest: */
3238 case HI6_LH: { wlen = 2; st = 0; } break;
3239 case HI6_LHU: { wlen = 2; st = 0; signd = 0; } break;
3240 case HI6_LWU: { st = 0; signd = 0; } break;
3241 case HI6_LWC1: { st = 0; } break;
3242 case HI6_LWC2: { st = 0; } break;
3243 case HI6_LWC3: { st = 0; } break;
3244 case HI6_LDC1: { wlen = 8; st = 0; signd = 0; } break;
3245 case HI6_LDC2: { wlen = 8; st = 0; signd = 0; } break;
3246
3247 case HI6_SH: { wlen = 2; signd = 0; } break;
3248 case HI6_SDC1:
3249 case HI6_SDC2: wlen = 8;
3250 case HI6_SWC1:
3251 case HI6_SWC2:
3252 case HI6_SWC3: { signd = 0; } break;
3253
3254 case HI6_LL: { st = 0; signd = 1; linked = 1; } break;
3255 case HI6_LLD: { wlen = 8; st = 0; signd = 0; linked = 1; } break;
3256
3257 case HI6_SC: { signd = 1; linked = 1; } break;
3258 case HI6_SCD: { wlen = 8; signd = 0; linked = 1; } break;
3259
3260 default:
3261 fatal("cannot be here\n");
3262 wlen = 4; st = 0; signd = 0;
3263 }
3264
3265 /*
3266 * In the MIPS IV ISA, the 'lwc3' instruction is changed into 'pref'.
3267 * The pref instruction is emulated by not doing anything. :-) TODO
3268 */
3269 if (hi6 == HI6_LWC3 && cpu->cd.mips.cpu_type.isa_level >= 4) {
3270 /* Clear the LLbit (at least on R10000): */
3271 cpu->cd.mips.rmw = 0;
3272 break;
3273 }
3274
3275 addr = cpu->cd.mips.gpr[rs] + imm;
3276
3277 /* Check for natural alignment: */
3278 if ((addr & (wlen - 1)) != 0) {
3279 mips_cpu_exception(cpu, st? EXCEPTION_ADES : EXCEPTION_ADEL,
3280 0, addr, 0, 0, 0, 0);
3281 break;
3282 }
3283
3284 #if 0
3285 if (cpu->cd.mips.cpu_type.isa_level == 4 && (imm & (wlen - 1)) != 0)
3286 debug("WARNING: low bits of imm value not zero! (MIPS IV) "
3287 "pc=%016llx", (long long)cpu->cd.mips.pc_last);
3288 #endif
3289
3290 /*
3291 * Load Linked: This initiates a Read-Modify-Write
3292 * sequence.
3293 */
3294 if (linked) {
3295 if (st==0) {
3296 /* st == 0: Load */
3297 cpu->cd.mips.rmw = 1;
3298 cpu->cd.mips.rmw_addr = addr;
3299 cpu->cd.mips.rmw_len = wlen;
3300
3301 /*
3302 * COP0_LLADDR is updated for
3303 * diagnostic purposes, except for
3304 * CPUs in the R10000 family.
3305 */
3306 if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
3307 cp0->reg[COP0_LLADDR] =
3308 (addr >> 4) & 0xffffffffULL;
3309 } else {
3310 /*
3311 * st == 1: Store
3312 * If rmw is 0, then the store failed.
3313 * (This cache-line was written to by
3314 * someone else.)
3315 */
3316 if (cpu->cd.mips.rmw == 0 ||
3317 cpu->cd.mips.rmw_addr != addr ||
3318 cpu->cd.mips.rmw_len != wlen) {
3319 /* The store failed: */
3320 cpu->cd.mips.gpr[rt] = 0;
3321 if (instruction_trace_cached)
3322 debug(" [COLLISION] ");
3323 break;
3324 }
3325 }
3326 } else {
3327 /*
3328 * If any kind of load or store occurs between
3329 * an ll and an sc, then the ll-sc sequence
3330 * should fail. (This is local to each cpu.)
3331 */
3332 cpu->cd.mips.rmw = 0;
3333 }
3334
3335 value_hi = 0;
3336
3337 if (st) {
3338 /* store: */
3339 int cpnr, success;
3340
3341 if (hi6 == HI6_SWC3 || hi6 == HI6_SWC2 ||
3342 hi6 == HI6_SDC1 || hi6 == HI6_SWC1) {
3343 cpnr = 1;
3344 switch (hi6) {
3345 case HI6_SWC3: cpnr++; /* fallthrough */
3346 case HI6_SWC2: cpnr++;
3347 case HI6_SDC1:
3348 case HI6_SWC1: if (cpu->cd.mips.coproc[cpnr] == NULL ||
3349 (!(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ) {
3350 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3351 cpnr = -1;
3352 break;
3353 } else {
3354 /* Special handling of 64-bit stores
3355 on 32-bit CPUs, and on newer CPUs
3356 in 32-bit compatiblity mode: */
3357 if ((hi6==HI6_SDC1 || hi6==HI6_SDC2) &&
3358 (cpu->cd.mips.cpu_type.isa_level <= 2 ||
3359 !(cp0->reg[COP0_STATUS] & STATUS_FR))) {
3360 uint64_t a, b;
3361 coproc_register_read(cpu,
3362 cpu->cd.mips.coproc[cpnr], rt, &a, 0);
3363 coproc_register_read(cpu,
3364 cpu->cd.mips.coproc[cpnr], rt^1, &b, 0);
3365 if (rt & 1)
3366 fatal("WARNING: SDCx in 32-bit mode from odd register!\n");
3367 value = (a & 0xffffffffULL)
3368 | (b << 32);
3369 } else
3370 coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr], rt, &value, 0);
3371 }
3372 break;
3373 default:
3374 ;
3375 }
3376 if (cpnr < 0)
3377 break;
3378 } else
3379 value = cpu->cd.mips.gpr[rt];
3380
3381 if (wlen == 4) {
3382 /* Special case for 32-bit stores... (perhaps not worth it) */
3383 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3384 d[0] = value & 0xff; d[1] = (value >> 8) & 0xff;
3385 d[2] = (value >> 16) & 0xff; d[3] = (value >> 24) & 0xff;
3386 } else {
3387 d[3] = value & 0xff; d[2] = (value >> 8) & 0xff;
3388 d[1] = (value >> 16) & 0xff; d[0] = (value >> 24) & 0xff;
3389 }
3390 } else if (wlen == 16) {
3391 value_hi = cpu->cd.mips.gpr_quadhi[rt];
3392 /* Special case for R5900 128-bit stores: */
3393 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3394 for (i=0; i<8; i++) {
3395 d[i] = (value >> (i*8)) & 255;
3396 d[i+8] = (value_hi >> (i*8)) & 255;
3397 }
3398 else
3399 for (i=0; i<8; i++) {
3400 d[i] = (value >> ((wlen-1-i)*8)) & 255;
3401 d[i + 8] = (value_hi >> ((wlen-1-i)*8)) & 255;
3402 }
3403 } else if (wlen == 1) {
3404 d[0] = value & 0xff;
3405 } else {
3406 /* General case: */
3407 uint64_t v = value;
3408 if (cpu->byte_order ==
3409 EMUL_LITTLE_ENDIAN)
3410 for (i=0; i<wlen; i++) {
3411 d[i] = v & 255;
3412 v >>= 8;
3413 }
3414 else
3415 for (i=0; i<wlen; i++) {
3416 d[wlen-1-i] = v & 255;
3417 v >>= 8;
3418 }
3419 }
3420
3421 success = cpu->memory_rw(cpu, cpu->mem, addr,
3422 d, wlen, MEM_WRITE, CACHE_DATA);
3423 if (!success) {
3424 /* The store failed, and might have caused an exception. */
3425 if (instruction_trace_cached)
3426 debug("(failed)]\n");
3427 break;
3428 }
3429 } else {
3430 /* load: */
3431 int cpnr = 1;
3432 int success;
3433
3434 success = cpu->memory_rw(cpu, cpu->mem, addr,
3435 d, wlen, MEM_READ, CACHE_DATA);
3436 if (!success) {
3437 /* The load failed, and might have caused an exception. */
3438 if (instruction_trace_cached)
3439 debug("(failed)]\n");
3440 break;
3441 }
3442
3443 if (wlen == 1)
3444 value = d[0] | (signd && (d[0]&128)? (-1 << 8) : 0);
3445 else if (wlen != 16) {
3446 /* General case (except for 128-bit): */
3447 int i;
3448 value = 0;
3449 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3450 if (signd && (d[wlen-1] & 128)!=0) /* sign extend */
3451 value = -1;
3452 for (i=wlen-1; i>=0; i--) {
3453 value <<= 8;
3454 value += d[i];
3455 }
3456 } else {
3457 if (signd && (d[0] & 128)!=0) /* sign extend */
3458 value = -1;
3459 for (i=0; i<wlen; i++) {
3460 value <<= 8;
3461 value += d[i];
3462 }
3463 }
3464 } else {
3465 /* R5900 128-bit quadword: */
3466 int i;
3467 value_hi = 0;
3468 value = 0;
3469 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3470 for (i=wlen-1; i>=0; i--) {
3471 value_hi <<= 8;
3472 value_hi += (value >> 56) & 255;
3473 value <<= 8;
3474 value += d[i];
3475 }
3476 } else {
3477 for (i=0; i<wlen; i++) {
3478 value_hi <<= 8;
3479 value_hi += (value >> 56) & 255;
3480 value <<= 8;
3481 value += d[i];
3482 }
3483 }
3484 cpu->cd.mips.gpr_quadhi[rt] = value_hi;
3485 }
3486
3487 switch (hi6) {
3488 case HI6_LWC3: cpnr++; /* fallthrough */
3489 case HI6_LDC2:
3490 case HI6_LWC2: cpnr++;
3491 case HI6_LDC1:
3492 case HI6_LWC1: if (cpu->cd.mips.coproc[cpnr] == NULL ||
3493 (!(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ) {
3494 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3495 } else {
3496 /* Special handling of 64-bit loads
3497 on 32-bit CPUs, and on newer CPUs
3498 in 32-bit compatiblity mode: */
3499 if ((hi6==HI6_LDC1 || hi6==HI6_LDC2) &&
3500 (cpu->cd.mips.cpu_type.isa_level <= 2 ||
3501 !(cp0->reg[COP0_STATUS] & STATUS_FR))) {
3502 uint64_t a, b;
3503 a = (int64_t)(int32_t) (value & 0xffffffffULL);
3504 b = (int64_t)(int32_t) (value >> 32);
3505 coproc_register_write(cpu,
3506 cpu->cd.mips.coproc[cpnr], rt, &a,
3507 hi6==HI6_LDC1 || hi6==HI6_LDC2, 0);
3508 coproc_register_write(cpu,
3509 cpu->cd.mips.coproc[cpnr], rt ^ 1, &b,
3510 hi6==HI6_LDC1 || hi6==HI6_LDC2, 0);
3511 if (rt & 1)
3512 fatal("WARNING: LDCx in 32-bit mode to odd register!\n");
3513 } else {
3514 coproc_register_write(cpu,
3515 cpu->cd.mips.coproc[cpnr], rt, &value,
3516 hi6==HI6_LDC1 || hi6==HI6_LDC2, 0);
3517 }
3518 }
3519 break;
3520 default: if (rt != 0)
3521 cpu->cd.mips.gpr[rt] = value;
3522 }
3523 }
3524
3525 if (linked && st==1) {
3526 /*
3527 * The store succeeded. Invalidate any other
3528 * cpu's store to this cache line, and then
3529 * return 1 in gpr rt:
3530 *
3531 * (this is a semi-ugly hack using global
3532 * 'cpus')
3533 *
3534 * TODO: How about invalidating other CPUs
3535 * stores to this cache line, even if this
3536 * was _NOT_ a linked store?
3537 */
3538 for (i=0; i<cpu->machine->ncpus; i++) {
3539 if (cpu->machine->cpus[i]->cd.mips.rmw) {
3540 uint64_t yaddr = addr;
3541 uint64_t xaddr =
3542 cpu->machine->cpus[i]->cd.mips.rmw_addr;
3543 uint64_t mask;
3544 mask = ~(cpu->machine->cpus[i]->
3545 cd.mips.cache_linesize[CACHE_DATA]
3546 - 1);
3547 xaddr &= mask;
3548 yaddr &= mask;
3549 if (xaddr == yaddr) {
3550 cpu->machine->cpus[i]->cd.mips.rmw = 0;
3551 cpu->machine->cpus[i]->cd.mips.rmw_addr = 0;
3552 }
3553 }
3554 }
3555
3556 if (rt != 0)
3557 cpu->cd.mips.gpr[rt] = 1;
3558
3559 if (instruction_trace_cached)
3560 debug(" [no collision] ");
3561 cpu->cd.mips.rmw = 0;
3562 }
3563
3564 if (instruction_trace_cached) {
3565 switch (wlen) {
3566 case 2: debug("0x%04x", (int)value); break;
3567 case 4: debug("0x%08x", (int)value); break;
3568 case 8: debug("0x%016llx", (long long)value);
3569 break;
3570 case 16:debug("0x%016llx", (long long)value_hi);
3571 debug("%016llx", (long long)value);
3572 break;
3573 default:debug("0x%02x", (int)value);
3574 }
3575 debug("]\n");
3576 }
3577 return 1;
3578 case HI6_LWL: /* Unaligned load/store */
3579 case HI6_LWR:
3580 case HI6_LDL:
3581 case HI6_LDR:
3582 case HI6_SWL:
3583 case HI6_SWR:
3584 case HI6_SDL:
3585 case HI6_SDR:
3586 /* For L (Left): address is the most significant byte */
3587 /* For R (Right): address is the least significant byte */
3588 addr = cpu->cd.mips.gpr[rs] + imm;
3589
3590 is_left = 0;
3591 if (hi6 == HI6_SWL || hi6 == HI6_LWL ||
3592 hi6 == HI6_SDL || hi6 == HI6_LDL)
3593 is_left = 1;
3594
3595 wlen = 0; st = 0;
3596 signd = 0;
3597 if (hi6 == HI6_LWL || hi6 == HI6_LWR)
3598 signd = 1;
3599
3600 if (hi6 == HI6_LWL || hi6 == HI6_LWR) { wlen = 4; st = 0; }
3601 if (hi6 == HI6_SWL || hi6 == HI6_SWR) { wlen = 4; st = 1; }
3602 if (hi6 == HI6_LDL || hi6 == HI6_LDR) { wlen = 8; st = 0; }
3603 if (hi6 == HI6_SDL || hi6 == HI6_SDR) { wlen = 8; st = 1; }
3604
3605 dir = 1; /* big endian, Left */
3606 reg_dir = -1;
3607 reg_ofs = wlen - 1; /* byte offset in the register */
3608 if (!is_left) {
3609 dir = -dir;
3610 reg_ofs = 0;
3611 reg_dir = 1;
3612 }
3613 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3614 dir = -dir;
3615
3616 result_value = cpu->cd.mips.gpr[rt];
3617
3618 if (st) {
3619 /* Store: */
3620 uint64_t aligned_addr = addr & ~(wlen-1);
3621 unsigned char aligned_word[8];
3622 uint64_t oldpc = cpu->pc;
3623 /*
3624 * NOTE (this is ugly): The memory_rw()
3625 * call generates a TLBL exception, if there
3626 * is a tlb refill exception. However, since
3627 * this is a Store, the exception is converted
3628 * to a TLBS:
3629 */
3630 int ok = cpu->memory_rw(cpu, cpu->mem,
3631 aligned_addr, &aligned_word[0], wlen,
3632 MEM_READ, CACHE_DATA);
3633 if (!ok) {
3634 if (cpu->pc != oldpc) {
3635 cp0->reg[COP0_CAUSE] &= ~CAUSE_EXCCODE_MASK;
3636 cp0->reg[COP0_CAUSE] |= (EXCEPTION_TLBS << CAUSE_EXCCODE_SHIFT);
3637 }
3638 return 1;
3639 }
3640
3641 for (i=0; i<wlen; i++) {
3642 tmpaddr = addr + i*dir;
3643 /* Have we moved into another word/dword? Then stop: */
3644 if ( (tmpaddr & ~(wlen-1)) != (addr & ~(wlen-1)) )
3645 break;
3646
3647 /* debug("unaligned byte at %016llx, reg_ofs=%i reg=0x%016llx\n",
3648 tmpaddr, reg_ofs, (long long)result_value); */
3649
3650 /* Store one byte: */
3651 aligned_word[tmpaddr & (wlen-1)] = (result_value >> (reg_ofs * 8)) & 255;
3652
3653 reg_ofs += reg_dir;
3654 }
3655
3656 ok = cpu->memory_rw(cpu, cpu->mem,
3657 aligned_addr, &aligned_word[0], wlen,
3658 MEM_WRITE, CACHE_DATA);
3659 if (!ok)
3660 return 1;
3661 } else {
3662 /* Load: */
3663 uint64_t aligned_addr = addr & ~(wlen-1);
3664 unsigned char aligned_word[8], databyte;
3665 int ok = cpu->memory_rw(cpu, cpu->mem,
3666 aligned_addr, &aligned_word[0], wlen,
3667 MEM_READ, CACHE_DATA);
3668 if (!ok)
3669 return 1;
3670
3671 for (i=0; i<wlen; i++) {
3672 tmpaddr = addr + i*dir;
3673 /* Have we moved into another word/dword? Then stop: */
3674 if ( (tmpaddr & ~(wlen-1)) != (addr & ~(wlen-1)) )
3675 break;
3676
3677 /* debug("unaligned byte at %016llx, reg_ofs=%i reg=0x%016llx\n",
3678 tmpaddr, reg_ofs, (long long)result_value); */
3679
3680 /* Load one byte: */
3681 databyte = aligned_word[tmpaddr & (wlen-1)];
3682 result_value &= ~((uint64_t)0xff << (reg_ofs * 8));
3683 result_value |= (uint64_t)databyte << (reg_ofs * 8);
3684
3685 reg_ofs += reg_dir;
3686 }
3687
3688 if (rt != 0)
3689 cpu->cd.mips.gpr[rt] = result_value;
3690 }
3691
3692 /* Sign extend for 32-bit load lefts: */
3693 if (!st && signd && wlen == 4) {
3694 cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
3695 if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
3696 cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
3697 }
3698
3699 if (instruction_trace_cached) {
3700 char *t;
3701 switch (wlen) {
3702 case 2: t = "0x%04llx"; break;
3703 case 4: t = "0x%08llx"; break;
3704 case 8: t = "0x%016llx"; break;
3705 default: t = "0x%02llx";
3706 }
3707 debug(t, (long long)cpu->cd.mips.gpr[rt]);
3708 debug("]\n");
3709 }
3710
3711 return 1;
3712 }
3713 return 1;
3714 case HI6_REGIMM:
3715 regimm5 = instr[2] & 0x1f;
3716
3717 if (show_opcode_statistics)
3718 cpu->cd.mips.stats__regimm[regimm5] ++;
3719
3720 switch (regimm5) {
3721 case REGIMM_BLTZ:
3722 case REGIMM_BGEZ:
3723 case REGIMM_BLTZL:
3724 case REGIMM_BGEZL:
3725 case REGIMM_BLTZAL:
3726 case REGIMM_BLTZALL:
3727 case REGIMM_BGEZAL:
3728 case REGIMM_BGEZALL:
3729 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3730 imm = (instr[1] << 8) + instr[0];
3731 if (imm >= 32768) /* signed 16-bit */
3732 imm -= 65536;
3733
3734 cond = and_link = likely = 0;
3735
3736 switch (regimm5) {
3737 case REGIMM_BLTZL: likely = 1;
3738 case REGIMM_BLTZ: cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) != 0;
3739 break;
3740 case REGIMM_BGEZL: likely = 1;
3741 case REGIMM_BGEZ: cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) == 0;
3742 break;
3743
3744 case REGIMM_BLTZALL: likely = 1;
3745 case REGIMM_BLTZAL: and_link = 1;
3746 cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) != 0;
3747 break;
3748 case REGIMM_BGEZALL: likely = 1;
3749 case REGIMM_BGEZAL: and_link = 1;
3750 cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) == 0;
3751 break;
3752 }
3753
3754 if (and_link)
3755 cpu->cd.mips.gpr[31] = cached_pc + 4;
3756
3757 if (cond) {
3758 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3759 cpu->cd.mips.delay_jmpaddr = cached_pc + (imm << 2);
3760 } else {
3761 if (likely)
3762 cpu->cd.mips.nullify_next = 1; /* nullify delay slot */
3763 }
3764
3765 return 1;
3766 default:
3767 if (!instruction_trace_cached) {
3768 fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
3769 cpu->cpu_id, (long long)cpu->cd.mips.pc_last,
3770 instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
3771 }
3772 fatal("unimplemented regimm5 = 0x%02x\n", regimm5);
3773 cpu->running = 0;
3774 return 1;
3775 }
3776 /* NOT REACHED */
3777 case HI6_J:
3778 case HI6_JAL:
3779 if (cpu->cd.mips.delay_slot) {
3780 fatal("j/jal: jump inside a jump's delay slot, or similar. TODO\n");
3781 cpu->running = 0;
3782 return 1;
3783 }
3784 imm = ((instr[3] & 3) << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3785 imm <<= 2;
3786
3787 if (hi6 == HI6_JAL)
3788 cpu->cd.mips.gpr[31] = cached_pc + 4; /* pc already increased by 4 earlier */
3789
3790 addr = cached_pc & ~((1 << 28) - 1);
3791 addr |= imm;
3792
3793 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3794 cpu->cd.mips.delay_jmpaddr = addr;
3795
3796 if (cpu->machine->show_trace_tree && hi6 == HI6_JAL) {
3797 cpu->cd.mips.show_trace_delay = 2;
3798 cpu->cd.mips.show_trace_addr = addr;
3799 }
3800
3801 return 1;
3802 case HI6_COP0:
3803 case HI6_COP1:
3804 case HI6_COP2:
3805 case HI6_COP3:
3806 imm = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3807 imm &= ((1 << 26) - 1);
3808
3809 cpnr = 0;
3810 if (hi6 == HI6_COP0) cpnr = 0;
3811 if (hi6 == HI6_COP1) cpnr = 1;
3812 if (hi6 == HI6_COP2) cpnr = 2;
3813 if (hi6 == HI6_COP3) cpnr = 3;
3814
3815 /*
3816 * If there is no coprocessor nr cpnr, or we are running in
3817 * userland and the coprocessor is not marked as Useable in
3818 * the status register of CP0, then we get an exception.
3819 *
3820 * An exception (hehe) to this rule is that the kernel should
3821 * always be able to access CP0.
3822 */
3823 /* Set tmp = 1 if we're in user mode. */
3824 tmp = 0;
3825 switch (cpu->cd.mips.cpu_type.exc_model) {
3826 case EXC3K:
3827 /*
3828 * NOTE: If the KU bit is checked, Linux crashes.
3829 * It is the PC that counts. TODO: Check whether
3830 * this is true or not for R4000 as well.
3831 */
3832 if (cached_pc <= 0x7fffffff) /* if (cp0->reg[COP0_STATUS] & MIPS1_SR_KU_CUR) */
3833 tmp = 1;
3834 break;
3835 default:
3836 /* R4000 etc: (TODO: How about supervisor mode?) */
3837 if (((cp0->reg[COP0_STATUS] & STATUS_KSU_MASK) >> STATUS_KSU_SHIFT) != KSU_KERNEL)
3838 tmp = 1;
3839 if (cp0->reg[COP0_STATUS] & STATUS_ERL)
3840 tmp = 0;
3841 if (cp0->reg[COP0_STATUS] & STATUS_EXL)
3842 tmp = 0;
3843 break;
3844 }
3845 if (cpu->cd.mips.coproc[cpnr] == NULL ||
3846 (tmp && !(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ||
3847 (!tmp && cpnr >= 1 && !(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)))
3848 ) {
3849 if (instruction_trace_cached)
3850 debug("cop%i\t0x%08x => coprocessor unusable\n", cpnr, (int)imm);
3851
3852 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3853 } else {
3854 /*
3855 * Execute the coprocessor function. The
3856 * coproc_function code outputs instruction
3857 * trace, if necessary.
3858 */
3859 coproc_function(cpu, cpu->cd.mips.coproc[cpnr],
3860 cpnr, imm, 0, 1);
3861 }
3862 return 1;
3863 case HI6_CACHE:
3864 rt = ((instr[3] & 3) << 3) + (instr[2] >> 5); /* base */
3865 copz = instr[2] & 31;
3866 imm = (instr[1] << 8) + instr[0];
3867
3868 cache_op = copz >> 2;
3869 which_cache = copz & 3;
3870
3871 /*
3872 * TODO: The cache instruction is implementation dependant.
3873 */
3874
3875 /*
3876 * Clear the LLbit (at least on R10000):
3877 * TODO: How about R4000?
3878 */
3879 cpu->cd.mips.rmw = 0;
3880
3881 return 1;
3882 case HI6_SPECIAL2:
3883 special6 = instr[0] & 0x3f;
3884
3885 if (show_opcode_statistics)
3886 cpu->cd.mips.stats__special2[special6] ++;
3887
3888 instrword = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3889
3890 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3891 rt = instr[2] & 31;
3892 rd = (instr[1] >> 3) & 31;
3893
3894 /* printf("special2 %08x rs=0x%02x rt=0x%02x rd=0x%02x\n", instrword, rs,rt,rd); */
3895
3896 /*
3897 * Many of these can be found in the R5000 docs, or figured out
3898 * by studying binutils source code for MIPS instructions.
3899 */
3900
3901 if ((instrword & 0xfc0007ffULL) == 0x70000000) {
3902 {
3903 int32_t a, b;
3904 int64_t c;
3905 a = (int32_t)cpu->cd.mips.gpr[rs];
3906 b = (int32_t)cpu->cd.mips.gpr[rt];
3907 c = a * b;
3908 c += (cpu->cd.mips.lo & 0xffffffffULL)
3909 + (cpu->cd.mips.hi << 32);
3910 cpu->cd.mips.lo = (int64_t)((int32_t)c);
3911 cpu->cd.mips.hi = (int64_t)((int32_t)(c >> 32));
3912
3913 /*
3914 * The R5000 manual says that rd should be all zeros,
3915 * but it isn't on R5900. I'm just guessing here that
3916 * it stores the value in register rd, in addition to hi/lo.
3917 * TODO
3918 */
3919 if (rd != 0)
3920 cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
3921 }
3922 } else if ((instrword & 0xffff07ffULL) == 0x70000209
3923 || (instrword & 0xffff07ffULL) == 0x70000249) {
3924 /*
3925 * This is just a guess for R5900, I've not found any docs on this one yet.
3926 *
3927 * pmfhi/pmflo rd
3928 *
3929 * If the lowest 8 bits of the instruction word are 0x09, it's a pmfhi.
3930 * If the lowest bits are 0x49, it's a pmflo.
3931 *
3932 * A wild guess is that this is a 128-bit version of mfhi/mflo.
3933 * For now, this is implemented as 64-bit only. (TODO)
3934 */
3935 if (instr[0] == 0x49) {
3936 cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
3937 } else {
3938 cpu->cd.mips.gpr[rd] = cpu->cd.mips.hi;
3939 }
3940 } else if ((instrword & 0xfc1fffff) == 0x70000269 || (instrword & 0xfc1fffff) == 0x70000229) {
3941 /*
3942 * This is just a guess for R5900, I've not found any docs on this one yet.
3943 *
3944 * pmthi/pmtlo rs (pmtlo = 269, pmthi = 229)
3945 *
3946 * A wild guess is that this is a 128-bit version of mthi/mtlo.
3947 * For now, this is implemented as 64-bit only. (TODO)
3948 */
3949 if (instr[0] == 0x69) {
3950 cpu->cd.mips.lo = cpu->cd.mips.gpr[rs];
3951 } else {
3952 cpu->cd.mips.hi = cpu->cd.mips.gpr[rs];
3953 }
3954 } else if ((instrword & 0xfc0007ff) == 0x700004a9) {
3955 /*
3956 * This is just a guess for R5900, I've not found any docs on this one yet.
3957 *
3958 * por dst,src,src2 ==> rs=src rt=src2 rd=dst
3959 *
3960 * A wild guess is that this is a 128-bit "or" between two registers.
3961 * For now, let's just or using 64-bits. (TODO)
3962 */
3963 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt];
3964 } else if ((instrword & 0xfc0007ff) == 0x70000488) {
3965 /*
3966 * R5900 "undocumented" pextlw. TODO: find out if this is correct.
3967 * It seems that this instruction is used to combine two 32-bit
3968 * words into a 64-bit dword, typically before a sd (store dword).
3969 */
3970 cpu->cd.mips.gpr[rd] =
3971 ((cpu->cd.mips.gpr[rs] & 0xffffffffULL) << 32) /* TODO: switch rt and rs? */
3972 | (cpu->cd.mips.gpr[rt] & 0xffffffffULL);
3973 } else if (special6 == SPECIAL2_MUL) {
3974 cpu->cd.mips.gpr[rd] = (int64_t)cpu->cd.mips.gpr[rt] *
3975 (int64_t)cpu->cd.mips.gpr[rs];
3976 } else if (special6 == SPECIAL2_CLZ) {
3977 /* clz: count leading zeroes */
3978 int i, n=0;
3979 for (i=31; i>=0; i--) {
3980 if (cpu->cd.mips.gpr[rs] & ((uint32_t)1 << i))
3981 break;
3982 else
3983 n++;
3984 }
3985 cpu->cd.mips.gpr[rd] = n;
3986 } else if (special6 == SPECIAL2_CLO) {
3987 /* clo: count leading ones */
3988 int i, n=0;
3989 for (i=31; i>=0; i--) {
3990 if (cpu->cd.mips.gpr[rs] & ((uint32_t)1 << i))
3991 n++;
3992 else
3993 break;
3994 }
3995 cpu->cd.mips.gpr[rd] = n;
3996 } else if (special6 == SPECIAL2_DCLZ) {
3997 /* dclz: count leading zeroes */
3998 int i, n=0;
3999 for (i=63; i>=0; i--) {
4000 if (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << i))
4001 break;
4002 else
4003 n++;
4004 }
4005 cpu->cd.mips.gpr[rd] = n;
4006 } else if (special6 == SPECIAL2_DCLO) {
4007 /* dclo: count leading ones */
4008 int i, n=0;
4009 for (i=63; i>=0; i--) {
4010 if (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << i))
4011 n++;
4012 else
4013 break;
4014 }
4015 cpu->cd.mips.gpr[rd] = n;
4016 } else {
4017 if (!instruction_trace_cached) {
4018 fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
4019 cpu->cpu_id, (long long)cpu->cd.mips.pc_last,
4020 instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
4021 }
4022 fatal("unimplemented special_2 = 0x%02x, rs=0x%02x rt=0x%02x rd=0x%02x\n",
4023 special6, rs, rt, rd);
4024 cpu->running = 0;
4025 return 1;
4026 }
4027 return 1;
4028 default:
4029 if (!instruction_trace_cached) {
4030 fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
4031 cpu->cpu_id, (long long)cpu->cd.mips.pc_last,
4032 instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
4033 }
4034 fatal("unimplemented hi6 = 0x%02x\n", hi6);
4035 cpu->running = 0;
4036 return 1;
4037 }
4038
4039 /* NOTREACHED */
4040 }
4041
4042
4043 #define CPU_RUN mips_cpu_run
4044 #define CPU_RUN_MIPS
4045 #define CPU_RINSTR mips_cpu_run_instr
4046 #include "cpu_run.c"
4047 #undef CPU_RINSTR
4048 #undef CPU_RUN_MIPS
4049 #undef CPU_RUN
4050
4051
4052 /*
4053 * mips_cpu_dumpinfo():
4054 *
4055 * Debug dump of MIPS-specific CPU data for specific CPU.
4056 */
4057 void mips_cpu_dumpinfo(struct cpu *cpu)
4058 {
4059 int iadd = 4;
4060 struct mips_cpu_type_def *ct = &cpu->cd.mips.cpu_type;
4061
4062 debug_indentation(iadd);
4063
4064 debug("\n%i-bit %s (MIPS",
4065 cpu->is_32bit? 32 : 64,
4066 cpu->byte_order == EMUL_BIG_ENDIAN? "BE" : "LE");
4067
4068 switch (ct->isa_level) {
4069 case 1: debug(" ISA I"); break;
4070 case 2: debug(" ISA II"); break;
4071 case 3: debug(" ISA III"); break;
4072 case 4: debug(" ISA IV"); break;
4073 case 5: debug(" ISA V"); break;
4074 case 32:
4075 case 64:debug("%i", ct->isa_level); break;
4076 default:debug(" ISA level %i", ct->isa_level);
4077 }
4078
4079 debug("), ");
4080 if (ct->nr_of_tlb_entries)
4081 debug("%i TLB entries", ct->nr_of_tlb_entries);
4082 else
4083 debug("no TLB");
4084 debug("\n");
4085
4086 if (ct->picache) {
4087 debug("L1 I-cache: %i KB", (1 << ct->picache) / 1024);
4088 if (ct->pilinesize)
4089 debug(", %i bytes per line", 1 << ct->pilinesize);
4090 if (ct->piways > 1)
4091 debug(", %i-way", ct->piways);
4092 else
4093 debug(", direct-mapped");
4094 debug("\n");
4095 }
4096
4097 if (ct->pdcache) {
4098 debug("L1 D-cache: %i KB", (1 << ct->pdcache) / 1024);
4099 if (ct->pdlinesize)
4100 debug(", %i bytes per line", 1 << ct->pdlinesize);
4101 if (ct->pdways > 1)
4102 debug(", %i-way", ct->pdways);
4103 else
4104 debug(", direct-mapped");
4105 debug("\n");
4106 }
4107
4108 if (ct->scache) {
4109 int kb = (1 << ct->scache) / 1024;
4110 debug("L2 cache: %i %s",
4111 kb >= 1024? kb / 1024 : kb, kb >= 1024? "MB":"KB");
4112 if (ct->slinesize)
4113 debug(", %i bytes per line", 1 << ct->slinesize);
4114 if (ct->sways > 1)
4115 debug(", %i-way", ct->sways);
4116 else
4117 debug(", direct-mapped");
4118 debug("\n");
4119 }
4120
4121 debug_indentation(-iadd);
4122 }
4123
4124
4125 /*
4126 * mips_cpu_list_available_types():
4127 *
4128 * Print a list of available MIPS CPU types.
4129 */
4130 void mips_cpu_list_available_types(void)
4131 {
4132 int i, j;
4133 struct mips_cpu_type_def cpu_type_defs[] = MIPS_CPU_TYPE_DEFS;
4134
4135 i = 0;
4136 while (cpu_type_defs[i].name != NULL) {
4137 debug("%s", cpu_type_defs[i].name);
4138 for (j=10 - strlen(cpu_type_defs[i].name); j>0; j--)
4139 debug(" ");
4140 i++;
4141 if ((i % 6) == 0 || cpu_type_defs[i].name == NULL)
4142 debug("\n");
4143 }
4144 }
4145
4146
4147 CPU_FAMILY_INIT(mips,"MIPS")
4148
4149
4150 #endif /* ENABLE_MIPS */

  ViewVC Help
Powered by ViewVC 1.1.26