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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 20 - (show annotations)
Mon Oct 8 16:19:23 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 119367 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1055 2005/11/25 22:48:36 debug Exp $
20051031	Adding disassembly support for more ARM instructions (clz,
		smul* etc), and adding a hack to support "new tiny" pages
		for StrongARM.
20051101	Minor documentation updates (NetBSD 2.0.2 -> 2.1, and OpenBSD
		3.7 -> 3.8, and lots of testing).
		Changing from 1-sector PIO mode 0 transfers to 128-sector PIO
		mode 3 (in dev_wdc).
		Various minor ARM dyntrans updates (pc-relative loads from
		within the same page as the instruction are now treated as
		constant "mov").
20051102	Re-enabling instruction combinations (they were accidentally
		disabled).
		Dyntrans TLB entries are now overwritten using a round-robin
		scheme instead of randomly. This increases performance.
		Fixing a typo in file.c (thanks to Chuan-Hua Chang for
		noticing it).
		Experimenting with adding ATAPI support to dev_wdc (to make
		emulated *BSD detect cdroms as cdroms, not harddisks).
20051104	Various minor updates.
20051105	Continuing on the ATAPI emulation. Seems to work well enough
		for a NetBSD/cats installation, but not OpenBSD/cats.
		Various other updates.
20051106	Modifying the -Y command line option to allow scaleup with
		certain graphic controllers (only dev_vga so far), not just
		scaledown.
		Some minor dyntrans cleanups.
20051107	Beginning a cleanup up the PCI subsystem (removing the
		read_register hack, etc).
20051108	Continuing the cleanup; splitting up some pci devices into a
		normal autodev device and some separate pci glue code.
20051109	Continuing on the PCI bus stuff; all old pci_*.c have been
		incorporated into normal devices and/or rewritten as glue code
		only, adding a dummy Intel 82371AB PIIX4 for Malta (not really
		tested yet).
		Minor pckbc fix so that Linux doesn't complain.
		Working on the DEC 21143 NIC (ethernet mac rom stuff mostly).
		Various other minor fixes.
20051110	Some more ARM dyntrans fine-tuning (e.g. some instruction
		combinations (cmps followed by conditional branch within the
		same page) and special cases for DPIs with regform when the
		shifter isn't used).
20051111	ARM dyntrans updates: O(n)->O(1) for just-mark-as-non-
		writable in the generic pc_to_pointers function, and some other
		minor hacks.
		Merging Cobalt and evbmips (Malta) ISA interrupt handling,
		and some minor fixes to allow Linux to accept harddisk irqs.
20051112	Minor device updates (pckbc, dec21143, lpt, ...), most
		importantly fixing the ALI M1543/M5229 so that harddisk irqs
		work with Linux/CATS.
20051113	Some more generalizations of the PCI subsystem.
		Finally took the time to add a hack for SCSI CDROM TOCs; this
		enables OpenBSD to use partition 'a' (as needed by the OpenBSD
		installer), and Windows NT's installer to get a bit further.
		Also fixing dev_wdc to allow Linux to detect ATAPI CDROMs.
		Continuing on the DEC 21143.
20051114	Minor ARM dyntrans tweaks; ARM cmps+branch optimization when
		comparing with 0, and generalizing the xchg instr. comb.
		Adding disassembly of ARM mrrc/mcrr and q{,d}{add,sub}.
20051115	Continuing on various PPC things (BATs, other address trans-
		lation things, various loads/stores, BeBox emulation, etc.).
		Beginning to work on PPC interrupt/exception support.
20051116	Factoring out some code which initializes legacy ISA devices
		from those machines that use them (bus_isa).
		Continuing on PPC interrupt/exception support.
20051117	Minor Malta fixes: RTC year offset = 80, disabling a speed hack
		which caused NetBSD to detect a too fast cpu, and adding a new
		hack to make Linux detect a faster cpu.
		Continuing on the Artesyn PM/PPC emulation mode.
		Adding an Algor emulation skeleton (P4032 and P5064);
		implementing some of the basics.
		Continuing on PPC emulation in general; usage of unimplemented
		SPRs is now easier to track, continuing on memory/exception
		related issues, etc.
20051118	More work on PPC emulation (tgpr0..3, exception handling,
		memory stuff, syscalls, etc.).
20051119	Changing the ARM dyntrans code to mostly use cpu->pc, and not
		necessarily use arm reg 15. Seems to work.
		Various PPC updates; continuing on the PReP emulation mode.
20051120	Adding a workaround/hack to dev_mc146818 to allow NetBSD/prep
		to detect the clock.
20051121	More cleanup of the PCI bus (memory and I/O bases, etc).
		Continuing on various PPC things (decrementer and timebase,
		WDCs on obio (on PReP) use irq 13, not 14/15).
20051122	Continuing on the CPC700 controller (interrupts etc) for PMPPC,
		and on PPC stuff in general.
		Finally! After some bug fixes to the virtual to physical addr
		translation, NetBSD/{prep,pmppc} 2.1 reach userland and are
		stable enough to be interacted with.
		More PCI updates; reverse-endian device access for PowerPC etc.
20051123	Generalizing the IEEE floating point subsystem (moving it out
		from src/cpus/cpu_mips_coproc.c into a new src/float_emul.c).
		Input via slave xterms was sometimes not really working; fixing
		this for ns16550, and a warning message is now displayed if
		multiple non-xterm consoles are active.
		Adding some PPC floating point support, etc.
		Various interrupt related updates (dev_wdc, _ns16550, _8259,
		and the isa32 common code in machine.c).
		NetBSD/prep can now be installed! :-) (Well, with some manual
		commands necessary before running sysinst.) Updating the
		documentation and various other things to reflect this.
20051124	Various minor documentation updates.
		Continuing the work on the DEC 21143 NIC.
20051125	LOTS of work on the 21143. Both OpenBSD and NetBSD work fine
		with it now, except that OpenBSD sometimes gives a time-out
		warning.
		Minor documentation updates.

==============  RELEASE 0.3.7  ==============


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.8 2005/11/13 00:14:07 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 =
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 dependent, 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 * ROM emulation: (0xbfcXXXXX or 0x9fcXXXXX)
1935 *
1936 * This assumes that a jal was made to a ROM address,
1937 * and we should return via gpr ra.
1938 */
1939 if ((cached_pc & 0xdff00000) == 0x9fc00000 &&
1940 cpu->machine->prom_emulation) {
1941 int rom_jal = 1, res = 1;
1942 switch (cpu->machine->machine_type) {
1943 case MACHINE_DEC:
1944 res = decstation_prom_emul(cpu);
1945 break;
1946 case MACHINE_PS2:
1947 res = playstation2_sifbios_emul(cpu);
1948 break;
1949 case MACHINE_ARC:
1950 case MACHINE_SGI:
1951 res = arcbios_emul(cpu);
1952 break;
1953 case MACHINE_EVBMIPS:
1954 res = yamon_emul(cpu);
1955 break;
1956 default:
1957 rom_jal = 0;
1958 }
1959
1960 if (rom_jal) {
1961 /*
1962 * Special hack: If the PROM emulation layer needs
1963 * to loop (for example when emulating blocking
1964 * console input) then we should simply return, so
1965 * that the same PROM routine is called on the next
1966 * round as well.
1967 *
1968 * This still has to count as one or more
1969 * instructions, so 1000 is returned. (Ugly.)
1970 */
1971 if (!res)
1972 return 1000;
1973
1974 cpu->pc = cpu->cd.mips.gpr[MIPS_GPR_RA];
1975 /* no need to update cached_pc, as we're returning */
1976 cpu->cd.mips.delay_slot = NOT_DELAYED;
1977
1978 if (cpu->machine->show_trace_tree)
1979 cpu_functioncall_trace_return(cpu);
1980
1981 /* TODO: how many instrs should this count as? */
1982 return 10;
1983 }
1984 }
1985
1986 #ifdef ALWAYS_SIGNEXTEND_32
1987 /*
1988 * An extra check for 32-bit mode to make sure that all
1989 * registers are sign-extended: (Slow, but might be useful
1990 * to detect bugs that have to do with sign-extension.)
1991 */
1992 if (cpu->is_32bit) {
1993 int warning = 0;
1994 uint64_t x;
1995
1996 if (cpu->cd.mips.gpr[0] != 0) {
1997 fatal("\nWARNING: r0 was not zero! (%016llx)\n\n",
1998 (long long)cpu->cd.mips.gpr[0]);
1999 cpu->cd.mips.gpr[0] = 0;
2000 warning = 1;
2001 }
2002
2003 if (cpu->pc != (int64_t)(int32_t)cpu->pc) {
2004 fatal("\nWARNING: pc was not sign-extended correctly"
2005 " (%016llx)\n\n", (long long)cpu->pc);
2006 cpu->pc = (int64_t)(int32_t)cpu->pc;
2007 warning = 1;
2008 }
2009
2010 if (cpu->cd.mips.pc_last != (int64_t)(int32_t)cpu->cd.mips.pc_last) {
2011 fatal("\nWARNING: pc_last was not sign-extended correc"
2012 "tly (%016llx)\n\n", (long long)cpu->cd.mips.pc_last);
2013 cpu->cd.mips.pc_last = (int64_t)(int32_t)cpu->cd.mips.pc_last;
2014 warning = 1;
2015 }
2016
2017 /* Sign-extend ALL registers, including coprocessor registers and tlbs: */
2018 for (i=1; i<32; i++) {
2019 x = cpu->cd.mips.gpr[i];
2020 cpu->cd.mips.gpr[i] &= 0xffffffff;
2021 if (cpu->cd.mips.gpr[i] & 0x80000000ULL)
2022 cpu->cd.mips.gpr[i] |= 0xffffffff00000000ULL;
2023 if (x != cpu->cd.mips.gpr[i]) {
2024 fatal("\nWARNING: r%i (%s) was not sign-"
2025 "extended correctly (%016llx != "
2026 "%016llx)\n\n", i, regname(cpu->machine, i),
2027 (long long)x, (long long)cpu->cd.mips.gpr[i]);
2028 warning = 1;
2029 }
2030 }
2031 for (i=0; i<32; i++) {
2032 x = cpu->cd.mips.coproc[0]->reg[i];
2033 cpu->cd.mips.coproc[0]->reg[i] &= 0xffffffffULL;
2034 if (cpu->cd.mips.coproc[0]->reg[i] & 0x80000000ULL)
2035 cpu->cd.mips.coproc[0]->reg[i] |=
2036 0xffffffff00000000ULL;
2037 if (x != cpu->cd.mips.coproc[0]->reg[i]) {
2038 fatal("\nWARNING: cop0,r%i was not sign-extended correctly (%016llx != %016llx)\n\n",
2039 i, (long long)x, (long long)cpu->cd.mips.coproc[0]->reg[i]);
2040 warning = 1;
2041 }
2042 }
2043 for (i=0; i<cpu->cd.mips.coproc[0]->nr_of_tlbs; i++) {
2044 x = cpu->cd.mips.coproc[0]->tlbs[i].hi;
2045 cpu->cd.mips.coproc[0]->tlbs[i].hi &= 0xffffffffULL;
2046 if (cpu->cd.mips.coproc[0]->tlbs[i].hi & 0x80000000ULL)
2047 cpu->cd.mips.coproc[0]->tlbs[i].hi |=
2048 0xffffffff00000000ULL;
2049 if (x != cpu->cd.mips.coproc[0]->tlbs[i].hi) {
2050 fatal("\nWARNING: tlb[%i].hi was not sign-extended correctly (%016llx != %016llx)\n\n",
2051 i, (long long)x, (long long)cpu->cd.mips.coproc[0]->tlbs[i].hi);
2052 warning = 1;
2053 }
2054
2055 x = cpu->cd.mips.coproc[0]->tlbs[i].lo0;
2056 cpu->cd.mips.coproc[0]->tlbs[i].lo0 &= 0xffffffffULL;
2057 if (cpu->cd.mips.coproc[0]->tlbs[i].lo0 & 0x80000000ULL)
2058 cpu->cd.mips.coproc[0]->tlbs[i].lo0 |=
2059 0xffffffff00000000ULL;
2060 if (x != cpu->cd.mips.coproc[0]->tlbs[i].lo0) {
2061 fatal("\nWARNING: tlb[%i].lo0 was not sign-extended correctly (%016llx != %016llx)\n\n",
2062 i, (long long)x, (long long)cpu->cd.mips.coproc[0]->tlbs[i].lo0);
2063 warning = 1;
2064 }
2065 }
2066
2067 if (warning) {
2068 fatal("Halting. pc = %016llx\n", (long long)cpu->pc);
2069 cpu->running = 0;
2070 }
2071 }
2072 #endif
2073
2074 PREFETCH(cpu->cd.mips.pc_last_host_4k_page + (cached_pc & 0xfff));
2075
2076 #ifdef HALT_IF_PC_ZERO
2077 /* Halt if PC = 0: */
2078 if (cached_pc == 0) {
2079 debug("cpu%i: pc=0, halting\n", cpu->cpu_id);
2080 cpu->running = 0;
2081 return 0;
2082 }
2083 #endif
2084
2085 #ifdef BINTRANS
2086 if ((single_step || instruction_trace_cached)
2087 && cpu->machine->bintrans_enable)
2088 cpu->cd.mips.dont_run_next_bintrans = 1;
2089 #endif
2090
2091 if (!quiet_mode_cached) {
2092 /* Dump CPU registers for debugging: */
2093 if (cpu->machine->register_dump) {
2094 debug("\n");
2095 mips_cpu_register_dump(cpu, 1, 0x1);
2096 }
2097 }
2098
2099 /* Trace tree: */
2100 if (cpu->machine->show_trace_tree && cpu->cd.mips.show_trace_delay > 0) {
2101 cpu->cd.mips.show_trace_delay --;
2102 if (cpu->cd.mips.show_trace_delay == 0)
2103 cpu_functioncall_trace(cpu, cpu->cd.mips.show_trace_addr);
2104 }
2105
2106 #ifdef MFHILO_DELAY
2107 /* Decrease the MFHI/MFLO delays: */
2108 if (cpu->mfhi_delay > 0)
2109 cpu->mfhi_delay--;
2110 if (cpu->mflo_delay > 0)
2111 cpu->mflo_delay--;
2112 #endif
2113
2114 /* Read an instruction from memory: */
2115 #ifdef ENABLE_MIPS16
2116 if (cpu->cd.mips.mips16 && (cached_pc & 1)) {
2117 /* 16-bit instruction word: */
2118 unsigned char instr16[2];
2119 int mips16_offset = 0;
2120
2121 if (!cpu->memory_rw(cpu, cpu->mem, cached_pc ^ 1, &instr16[0],
2122 sizeof(instr16), MEM_READ, CACHE_INSTRUCTION))
2123 return 0;
2124
2125 /* TODO: If Reverse-endian is set in the status cop0 register, and
2126 we are in usermode, then reverse endianness! */
2127
2128 /* The rest of the code is written for little endian, so swap if necessary: */
2129 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2130 int tmp;
2131 tmp = instr16[0]; instr16[0] = instr16[1]; instr16[1] = tmp;
2132 }
2133
2134 cpu->cd.mips.mips16_extend = 0;
2135
2136 /*
2137 * Translate into 32-bit instruction, little endian (instr[3..0]):
2138 *
2139 * This ugly loop is necessary because if we would get an exception between
2140 * reading an extend instruction and the next instruction, and execution
2141 * continues on the second instruction, the extend data would be lost. So the
2142 * entire instruction (the two parts) need to be read in. If an exception is
2143 * caused, it will appear as if it was caused when reading the extend instruction.
2144 */
2145 while (mips16_to_32(cpu, instr16, instr) == 0) {
2146 if (instruction_trace_cached)
2147 debug("cpu%i @ %016llx: %02x%02x\t\t\textend\n",
2148 cpu->cpu_id, (cpu->cd.mips.pc_last ^ 1) + mips16_offset,
2149 instr16[1], instr16[0]);
2150
2151 /* instruction with extend: */
2152 mips16_offset += 2;
2153 if (!cpu->memory_rw(cpu, cpu->mem, (cached_pc ^ 1) +
2154 mips16_offset, &instr16[0], sizeof(instr16),
2155 MEM_READ, CACHE_INSTRUCTION))
2156 return 0;
2157
2158 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2159 int tmp;
2160 tmp = instr16[0]; instr16[0] = instr16[1]; instr16[1] = tmp;
2161 }
2162 }
2163
2164 /* TODO: bintrans like in 32-bit mode? */
2165
2166 /* Advance the program counter: */
2167 cpu->pc += sizeof(instr16) + mips16_offset;
2168 cached_pc = cpu->pc;
2169
2170 if (instruction_trace_cached) {
2171 uint64_t offset;
2172 char *symbol = get_symbol_name(&cpu->machine->
2173 symbol_context, cpu->cd.mips.pc_last ^ 1, &offset);
2174 if (symbol != NULL && offset==0)
2175 debug("<%s>\n", symbol);
2176
2177 debug("cpu%i @ %016llx: %02x%02x => %02x%02x%02x%02x%s\t",
2178 cpu->cpu_id, (cpu->cd.mips.pc_last ^ 1) + mips16_offset,
2179 instr16[1], instr16[0],
2180 instr[3], instr[2], instr[1], instr[0],
2181 cpu_flags(cpu));
2182 }
2183 } else
2184 #endif
2185 {
2186 /*
2187 * Fetch a 32-bit instruction word from memory:
2188 *
2189 * 1) The special case of reading an instruction from the
2190 * same host RAM page as the last one is handled here,
2191 * to gain a little bit performance.
2192 *
2193 * 2) Fallback to reading from memory the usual way.
2194 */
2195 if (cached_pc & 3) {
2196 mips_cpu_exception(cpu, EXCEPTION_ADEL,
2197 0, cached_pc, 0, 0, 0, 0);
2198 return 0;
2199 }
2200 if (cpu->cd.mips.pc_last_host_4k_page != NULL &&
2201 (cached_pc & ~0xfff) == cpu->cd.mips.pc_last_virtual_page) {
2202 /* NOTE: This only works on the host if offset is
2203 aligned correctly! (TODO) */
2204 *(uint32_t *)instr = *(uint32_t *)
2205 (cpu->cd.mips.pc_last_host_4k_page + (cached_pc & 0xffc));
2206 #ifdef BINTRANS
2207 cpu->cd.mips.pc_bintrans_paddr_valid = 1;
2208 cpu->cd.mips.pc_bintrans_paddr =
2209 cpu->cd.mips.pc_last_physical_page | (cached_pc & 0xfff);
2210 cpu->cd.mips.pc_bintrans_host_4kpage = cpu->cd.mips.pc_last_host_4k_page;
2211 #endif
2212 } else {
2213 if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
2214 sizeof(instr), MEM_READ, CACHE_INSTRUCTION))
2215 return 0;
2216 }
2217
2218 #ifdef BINTRANS
2219 if (cpu->cd.mips.dont_run_next_bintrans) {
2220 cpu->cd.mips.dont_run_next_bintrans = 0;
2221 } else if (cpu->machine->bintrans_enable &&
2222 cpu->cd.mips.pc_bintrans_paddr_valid) {
2223 int res;
2224 cpu->cd.mips.bintrans_instructions_executed = 0;
2225
2226 res = bintrans_attempt_translate(cpu,
2227 cpu->cd.mips.pc_bintrans_paddr);
2228
2229 if (res >= 0) {
2230 /* debug("BINTRANS translation + hit,"
2231 " pc = %016llx\n", (long long)cached_pc); */
2232 if (res > 0 || cpu->pc != cached_pc) {
2233 if (instruction_trace_cached)
2234 mips_cpu_disassemble_instr(cpu, instr, 1, 0, 1);
2235 if (res & BINTRANS_DONT_RUN_NEXT)
2236 cpu->cd.mips.dont_run_next_bintrans = 1;
2237 res &= BINTRANS_N_MASK;
2238
2239 if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
2240 int x = cp0->reg[COP0_COUNT], y = cp0->reg[COP0_COMPARE];
2241 int diff = x - y;
2242 if (diff < 0 && diff + (res-1) >= 0
2243 && cpu->cd.mips.compare_register_set) {
2244 mips_cpu_interrupt(cpu, 7);
2245 cpu->cd.mips.compare_register_set = 0;
2246 }
2247
2248 cp0->reg[COP0_COUNT] = (int64_t)
2249 (int32_t)(cp0->reg[COP0_COUNT] + res-1);
2250 }
2251
2252 return res;
2253 }
2254 }
2255 }
2256 #endif
2257
2258 if (instruction_trace_cached)
2259 mips_cpu_disassemble_instr(cpu, instr, 1, 0, 0);
2260
2261 /* Advance the program counter: */
2262 cpu->pc += sizeof(instr);
2263 cached_pc = cpu->pc;
2264
2265 /*
2266 * TODO: If Reverse-endian is set in the status cop0 register
2267 * and we are in usermode, then reverse endianness!
2268 */
2269
2270 /*
2271 * The rest of the code is written for little endian, so
2272 * swap if necessary:
2273 */
2274 if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2275 int tmp = instr[0]; instr[0] = instr[3]; instr[3] = tmp;
2276 tmp = instr[1]; instr[1] = instr[2]; instr[2] = tmp;
2277 }
2278 }
2279
2280
2281 /*
2282 * Nullify this instruction? (Set by a previous branch-likely
2283 * instruction.)
2284 *
2285 * Note: The return value is 1, even if no instruction was actually
2286 * executed.
2287 */
2288 if (cpu->cd.mips.nullify_next) {
2289 cpu->cd.mips.nullify_next = 0;
2290 return 1;
2291 }
2292
2293
2294 /*
2295 * Execute the instruction:
2296 */
2297
2298 /* Get the top 6 bits of the instruction: */
2299 hi6 = instr[3] >> 2; /* & 0x3f */
2300
2301 if (show_opcode_statistics)
2302 cpu->cd.mips.stats_opcode[hi6] ++;
2303
2304 switch (hi6) {
2305 case HI6_SPECIAL:
2306 special6 = instr[0] & 0x3f;
2307
2308 if (show_opcode_statistics)
2309 cpu->cd.mips.stats__special[special6] ++;
2310
2311 switch (special6) {
2312 case SPECIAL_SLL:
2313 case SPECIAL_SRL:
2314 case SPECIAL_SRA:
2315 case SPECIAL_DSLL:
2316 case SPECIAL_DSRL:
2317 case SPECIAL_DSRA:
2318 case SPECIAL_DSLL32:
2319 case SPECIAL_DSRL32:
2320 case SPECIAL_DSRA32:
2321 rt = instr[2] & 31;
2322 rd = (instr[1] >> 3) & 31;
2323 sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
2324
2325 /*
2326 * Check for NOP:
2327 *
2328 * The R4000 manual says that a shift amount of zero
2329 * is treated as a nop by some assemblers. Checking
2330 * for sa == 0 here would not be correct, though,
2331 * because instructions such as sll r3,r4,0 are
2332 * possible, and are definitely not a nop.
2333 * Instead, check if the destination register is r0.
2334 *
2335 * TODO: ssnop should wait until the _next_
2336 * cycle boundary, or something like that. The
2337 * code here is incorrect.
2338 */
2339 if (rd == 0 && special6 == SPECIAL_SLL) {
2340 if (sa == 1) {
2341 /* ssnop */
2342 #ifdef ENABLE_INSTRUCTION_DELAYS
2343 cpu->cd.mips.instruction_delay +=
2344 cpu->cd.mips.cpu_type.
2345 instrs_per_cycle - 1;
2346 #endif
2347 }
2348 return 1;
2349 }
2350
2351 if (special6 == SPECIAL_SLL) {
2352 switch (sa) {
2353 case 8: cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << 8; break;
2354 case 16:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << 16; break;
2355 default:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << sa;
2356 }
2357 /* Sign-extend rd: */
2358 cpu->cd.mips.gpr[rd] = (int64_t) (int32_t) cpu->cd.mips.gpr[rd];
2359 }
2360 if (special6 == SPECIAL_DSLL) {
2361 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << sa;
2362 }
2363 if (special6 == SPECIAL_DSRL) {
2364 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2365 }
2366 if (special6 == SPECIAL_DSLL32) {
2367 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << (sa + 32);
2368 }
2369 if (special6 == SPECIAL_SRL) {
2370 /*
2371 * Three cases:
2372 * shift amount = zero: just copy
2373 * high bit of rt zero: plain shift right (of all bits)
2374 * high bit of rt one: plain shift right (of lowest 32 bits)
2375 */
2376 if (sa == 0)
2377 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2378 else if (!(cpu->cd.mips.gpr[rt] & 0x80000000ULL)) {
2379 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2380 } else
2381 cpu->cd.mips.gpr[rd] = (cpu->cd.mips.gpr[rt] & 0xffffffffULL) >> sa;
2382 }
2383 if (special6 == SPECIAL_SRA) {
2384 int topbit = cpu->cd.mips.gpr[rt] & 0x80000000ULL;
2385 switch (sa) {
2386 case 8: cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> 8; break;
2387 case 16:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> 16; break;
2388 default:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2389 }
2390 if (topbit)
2391 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2392 }
2393 if (special6 == SPECIAL_DSRL32) {
2394 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> (sa + 32);
2395 }
2396 if (special6 == SPECIAL_DSRA32 || special6 == SPECIAL_DSRA) {
2397 if (special6 == SPECIAL_DSRA32)
2398 sa += 32;
2399 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2400 while (sa > 0) {
2401 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2402 sa--;
2403 if (cpu->cd.mips.gpr[rd] & ((uint64_t)1 << 62)) /* old signbit */
2404 cpu->cd.mips.gpr[rd] |= ((uint64_t)1 << 63);
2405 }
2406 }
2407 return 1;
2408 case SPECIAL_DSRLV:
2409 case SPECIAL_DSRAV:
2410 case SPECIAL_DSLLV:
2411 case SPECIAL_SLLV:
2412 case SPECIAL_SRAV:
2413 case SPECIAL_SRLV:
2414 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2415 rt = instr[2] & 31;
2416 rd = (instr[1] >> 3) & 31;
2417
2418 if (special6 == SPECIAL_DSRLV) {
2419 sa = cpu->cd.mips.gpr[rs] & 63;
2420 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2421 }
2422 if (special6 == SPECIAL_DSRAV) {
2423 sa = cpu->cd.mips.gpr[rs] & 63;
2424 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2425 while (sa > 0) {
2426 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2427 sa--;
2428 if (cpu->cd.mips.gpr[rd] & ((uint64_t)1 << 62)) /* old sign-bit */
2429 cpu->cd.mips.gpr[rd] |= ((uint64_t)1 << 63);
2430 }
2431 }
2432 if (special6 == SPECIAL_DSLLV) {
2433 sa = cpu->cd.mips.gpr[rs] & 63;
2434 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2435 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] << sa;
2436 }
2437 if (special6 == SPECIAL_SLLV) {
2438 sa = cpu->cd.mips.gpr[rs] & 31;
2439 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2440 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] << sa;
2441 /* Sign-extend rd: */
2442 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2443 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2444 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2445 }
2446 if (special6 == SPECIAL_SRAV) {
2447 sa = cpu->cd.mips.gpr[rs] & 31;
2448 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2449 /* Sign-extend rd: */
2450 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2451 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2452 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2453 while (sa > 0) {
2454 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2455 sa--;
2456 }
2457 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2458 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2459 }
2460 if (special6 == SPECIAL_SRLV) {
2461 sa = cpu->cd.mips.gpr[rs] & 31;
2462 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2463 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2464 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> sa;
2465 /* And finally sign-extend rd: */
2466 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2467 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2468 }
2469 return 1;
2470 case SPECIAL_JR:
2471 if (cpu->cd.mips.delay_slot) {
2472 fatal("jr: jump inside a jump's delay slot, or similar. TODO\n");
2473 cpu->running = 0;
2474 return 1;
2475 }
2476
2477 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2478
2479 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
2480 cpu->cd.mips.delay_jmpaddr = cpu->cd.mips.gpr[rs];
2481
2482 if (cpu->machine->show_trace_tree && rs == 31)
2483 cpu_functioncall_trace_return(cpu);
2484
2485 return 1;
2486 case SPECIAL_JALR:
2487 if (cpu->cd.mips.delay_slot) {
2488 fatal("jalr: jump inside a jump's delay slot, or similar. TODO\n");
2489 cpu->running = 0;
2490 return 1;
2491 }
2492
2493 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2494 rd = (instr[1] >> 3) & 31;
2495
2496 tmpvalue = cpu->cd.mips.gpr[rs];
2497 cpu->cd.mips.gpr[rd] = cached_pc + 4;
2498 /* already increased by 4 earlier */
2499
2500 if (cpu->machine->show_trace_tree && rd == 31) {
2501 cpu->cd.mips.show_trace_delay = 2;
2502 cpu->cd.mips.show_trace_addr = tmpvalue;
2503 }
2504
2505 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
2506 cpu->cd.mips.delay_jmpaddr = tmpvalue;
2507 return 1;
2508 case SPECIAL_MFHI:
2509 case SPECIAL_MFLO:
2510 rd = (instr[1] >> 3) & 31;
2511
2512 if (special6 == SPECIAL_MFHI) {
2513 cpu->cd.mips.gpr[rd] = cpu->cd.mips.hi;
2514 #ifdef MFHILO_DELAY
2515 cpu->mfhi_delay = 3;
2516 #endif
2517 }
2518 if (special6 == SPECIAL_MFLO) {
2519 cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
2520 #ifdef MFHILO_DELAY
2521 cpu->mflo_delay = 3;
2522 #endif
2523 }
2524 return 1;
2525 case SPECIAL_ADD:
2526 case SPECIAL_ADDU:
2527 case SPECIAL_SUB:
2528 case SPECIAL_SUBU:
2529 case SPECIAL_AND:
2530 case SPECIAL_OR:
2531 case SPECIAL_XOR:
2532 case SPECIAL_NOR:
2533 case SPECIAL_SLT:
2534 case SPECIAL_SLTU:
2535 case SPECIAL_MTLO:
2536 case SPECIAL_MTHI:
2537 case SPECIAL_MULT:
2538 case SPECIAL_MULTU:
2539 case SPECIAL_DMULT:
2540 case SPECIAL_DMULTU:
2541 case SPECIAL_DIV:
2542 case SPECIAL_DIVU:
2543 case SPECIAL_DDIV:
2544 case SPECIAL_DDIVU:
2545 case SPECIAL_TGE:
2546 case SPECIAL_TGEU:
2547 case SPECIAL_TLT:
2548 case SPECIAL_TLTU:
2549 case SPECIAL_TEQ:
2550 case SPECIAL_TNE:
2551 case SPECIAL_DADD:
2552 case SPECIAL_DADDU:
2553 case SPECIAL_DSUB:
2554 case SPECIAL_DSUBU:
2555 case SPECIAL_MOVZ:
2556 case SPECIAL_MOVN:
2557 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2558 rt = instr[2] & 31;
2559 rd = (instr[1] >> 3) & 31;
2560
2561 #ifdef MFHILO_DELAY
2562 if (cpu->mflo_delay > 0 && (
2563 special6 == SPECIAL_DDIV || special6 == SPECIAL_DDIVU ||
2564 special6 == SPECIAL_DIV || special6 == SPECIAL_DIVU ||
2565 special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU ||
2566 special6 == SPECIAL_MTLO || special6 == SPECIAL_MULT
2567 || special6 == SPECIAL_MULTU
2568 ) )
2569 debug("warning: instruction modifying LO too early after mflo!\n");
2570
2571 if (cpu->mfhi_delay > 0 && (
2572 special6 == SPECIAL_DDIV || special6 == SPECIAL_DDIVU ||
2573 special6 == SPECIAL_DIV || special6 == SPECIAL_DIVU ||
2574 special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU ||
2575 special6 == SPECIAL_MTHI || special6 == SPECIAL_MULT
2576 || special6 == SPECIAL_MULTU
2577 ) )
2578 debug("warning: instruction modifying HI too early after mfhi!\n");
2579 #endif
2580
2581 if (special6 == SPECIAL_ADDU) {
2582 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2583 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2584 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2585 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2586 break;
2587 }
2588 if (special6 == SPECIAL_ADD) {
2589 /* According to the MIPS64 manual: */
2590 uint64_t temp, temp1, temp2;
2591 temp1 = cpu->cd.mips.gpr[rs] + ((cpu->cd.mips.gpr[rs] & 0x80000000ULL) << 1);
2592 temp2 = cpu->cd.mips.gpr[rt] + ((cpu->cd.mips.gpr[rt] & 0x80000000ULL) << 1);
2593 temp = temp1 + temp2;
2594 #if 0
2595 /* TODO: apparently this doesn't work (an example of
2596 something that breaks is NetBSD/sgimips' mips3_TBIA() */
2597 /* If bits 32 and 31 of temp differ, then it's an overflow */
2598 temp1 = temp & 0x100000000ULL;
2599 temp2 = temp & 0x80000000ULL;
2600 if ((temp1 && !temp2) || (!temp1 && temp2)) {
2601 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
2602 break;
2603 }
2604 #endif
2605 cpu->cd.mips.gpr[rd] = temp & 0xffffffffULL;
2606 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2607 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2608 break;
2609 }
2610 if (special6 == SPECIAL_SUBU) {
2611 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2612 cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2613 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2614 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2615 break;
2616 }
2617 if (special6 == SPECIAL_SUB) {
2618 /* According to the MIPS64 manual: */
2619 uint64_t temp, temp1, temp2;
2620 temp1 = cpu->cd.mips.gpr[rs] + ((cpu->cd.mips.gpr[rs] & 0x80000000ULL) << 1);
2621 temp2 = cpu->cd.mips.gpr[rt] + ((cpu->cd.mips.gpr[rt] & 0x80000000ULL) << 1);
2622 temp = temp1 - temp2;
2623 #if 0
2624 /* If bits 32 and 31 of temp differ, then it's an overflow */
2625 temp1 = temp & 0x100000000ULL;
2626 temp2 = temp & 0x80000000ULL;
2627 if ((temp1 && !temp2) || (!temp1 && temp2)) {
2628 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
2629 break;
2630 }
2631 #endif
2632 cpu->cd.mips.gpr[rd] = temp & 0xffffffffULL;
2633 if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2634 cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2635 break;
2636 }
2637
2638 if (special6 == SPECIAL_AND) {
2639 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] & cpu->cd.mips.gpr[rt];
2640 break;
2641 }
2642 if (special6 == SPECIAL_OR) {
2643 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt];
2644 break;
2645 }
2646 if (special6 == SPECIAL_XOR) {
2647 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] ^ cpu->cd.mips.gpr[rt];
2648 break;
2649 }
2650 if (special6 == SPECIAL_NOR) {
2651 cpu->cd.mips.gpr[rd] = ~(cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt]);
2652 break;
2653 }
2654 if (special6 == SPECIAL_SLT) {
2655 cpu->cd.mips.gpr[rd] = (int64_t)cpu->cd.mips.gpr[rs] < (int64_t)cpu->cd.mips.gpr[rt];
2656 break;
2657 }
2658 if (special6 == SPECIAL_SLTU) {
2659 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] < cpu->cd.mips.gpr[rt];
2660 break;
2661 }
2662 if (special6 == SPECIAL_MTLO) {
2663 cpu->cd.mips.lo = cpu->cd.mips.gpr[rs];
2664 break;
2665 }
2666 if (special6 == SPECIAL_MTHI) {
2667 cpu->cd.mips.hi = cpu->cd.mips.gpr[rs];
2668 break;
2669 }
2670 if (special6 == SPECIAL_MULT) {
2671 int64_t f1, f2, sum;
2672 f1 = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2673 /* sign extend f1 */
2674 if (f1 & 0x80000000ULL)
2675 f1 |= 0xffffffff00000000ULL;
2676 f2 = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2677 /* sign extend f2 */
2678 if (f2 & 0x80000000ULL)
2679 f2 |= 0xffffffff00000000ULL;
2680 sum = f1 * f2;
2681
2682 cpu->cd.mips.lo = sum & 0xffffffffULL;
2683 cpu->cd.mips.hi = ((uint64_t)sum >> 32) & 0xffffffffULL;
2684
2685 /* sign-extend: */
2686 if (cpu->cd.mips.lo & 0x80000000ULL)
2687 cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2688 if (cpu->cd.mips.hi & 0x80000000ULL)
2689 cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2690
2691 /*
2692 * NOTE: The stuff about rd!=0 is just a
2693 * guess, judging from how some NetBSD code
2694 * seems to execute. It is not documented in
2695 * the MIPS64 ISA docs :-/
2696 */
2697
2698 if (rd != 0) {
2699 if (cpu->cd.mips.cpu_type.rev != MIPS_R5900)
2700 debug("WARNING! mult_xx is an undocumented instruction!");
2701 cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
2702 }
2703 break;
2704 }
2705 if (special6 == SPECIAL_MULTU) {
2706 uint64_t f1, f2, sum;
2707 /* zero extend f1 and f2 */
2708 f1 = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2709 f2 = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2710 sum = f1 * f2;
2711 cpu->cd.mips.lo = sum & 0xffffffffULL;
2712 cpu->cd.mips.hi = (sum >> 32) & 0xffffffffULL;
2713
2714 /* sign-extend: */
2715 if (cpu->cd.mips.lo & 0x80000000ULL)
2716 cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2717 if (cpu->cd.mips.hi & 0x80000000ULL)
2718 cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2719 break;
2720 }
2721 if (special6 == SPECIAL_DMULT) {
2722 /* 64x64 = 128 bit multiplication, signed. */
2723 uint64_t s1 = cpu->cd.mips.gpr[rt];
2724 uint64_t s2 = cpu->cd.mips.gpr[rs];
2725 int n_negative = 0;
2726 int i;
2727
2728 if ((int64_t)s1 < 0) {
2729 s1 = -(int64_t)s1;
2730 n_negative ++;
2731 }
2732 if ((int64_t)s2 < 0) {
2733 s2 = -(int64_t)s2;
2734 n_negative ++;
2735 }
2736
2737 cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2738
2739 for (i=0; i<64; i++) {
2740 int bit = (s1 & 0x8000000000000000ULL)? 1 : 0;
2741 s1 <<= 1;
2742 /* If bit in s1 set, then add s2 to hi/lo: */
2743 if (bit) {
2744 uint64_t old_lo = cpu->cd.mips.lo;
2745 cpu->cd.mips.lo += s2;
2746 if (cpu->cd.mips.lo < old_lo)
2747 cpu->cd.mips.hi ++;
2748 }
2749 if (i != 63) {
2750 cpu->cd.mips.hi <<= 1;
2751 cpu->cd.mips.hi +=
2752 (cpu->cd.mips.lo & 0x8000000000000000ULL) ? 1 : 0;
2753 cpu->cd.mips.lo <<= 1;
2754 }
2755 }
2756
2757 if (n_negative == 1) {
2758 cpu->cd.mips.hi = -(int64_t)cpu->cd.mips.hi;
2759 cpu->cd.mips.lo = -(int64_t)cpu->cd.mips.lo;
2760 if ((int64_t)cpu->cd.mips.lo < 0)
2761 cpu->cd.mips.hi --;
2762 }
2763 break;
2764 }
2765 if (special6 == SPECIAL_DMULTU) {
2766 /* 64x64 = 128 bit multiplication, unsigned. */
2767 uint64_t s1 = cpu->cd.mips.gpr[rt];
2768 uint64_t s2 = cpu->cd.mips.gpr[rs];
2769 int i;
2770
2771 cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2772
2773 for (i=0; i<64; i++) {
2774 int bit = (s1 & 0x8000000000000000ULL)? 1 : 0;
2775 s1 <<= 1;
2776 /* If bit in s1 set, then add s2 to hi/lo: */
2777 if (bit) {
2778 uint64_t old_lo = cpu->cd.mips.lo;
2779 cpu->cd.mips.lo += s2;
2780 if (cpu->cd.mips.lo < old_lo)
2781 cpu->cd.mips.hi ++;
2782 }
2783 if (i != 63) {
2784 cpu->cd.mips.hi <<= 1;
2785 cpu->cd.mips.hi +=
2786 (cpu->cd.mips.lo & 0x8000000000000000ULL) ? 1 : 0;
2787 cpu->cd.mips.lo <<= 1;
2788 }
2789 }
2790 break;
2791 }
2792 if (special6 == SPECIAL_DIV) {
2793 int64_t a, b;
2794 /* Signextend rs and rt: */
2795 a = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2796 if (a & 0x80000000ULL)
2797 a |= 0xffffffff00000000ULL;
2798 b = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2799 if (b & 0x80000000ULL)
2800 b |= 0xffffffff00000000ULL;
2801
2802 if (b == 0) {
2803 /* undefined */
2804 cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2805 } else {
2806 cpu->cd.mips.lo = a / b;
2807 cpu->cd.mips.hi = a % b;
2808 }
2809 /* Sign-extend lo and hi: */
2810 cpu->cd.mips.lo &= 0xffffffffULL;
2811 if (cpu->cd.mips.lo & 0x80000000ULL)
2812 cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2813 cpu->cd.mips.hi &= 0xffffffffULL;
2814 if (cpu->cd.mips.hi & 0x80000000ULL)
2815 cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2816 break;
2817 }
2818 if (special6 == SPECIAL_DIVU) {
2819 int64_t a, b;
2820 /* Zero-extend rs and rt: */
2821 a = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2822 b = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2823 if (b == 0) {
2824 /* undefined */
2825 cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2826 } else {
2827 cpu->cd.mips.lo = a / b;
2828 cpu->cd.mips.hi = a % b;
2829 }
2830 /* Sign-extend lo and hi: */
2831 cpu->cd.mips.lo &= 0xffffffffULL;
2832 if (cpu->cd.mips.lo & 0x80000000ULL)
2833 cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2834 cpu->cd.mips.hi &= 0xffffffffULL;
2835 if (cpu->cd.mips.hi & 0x80000000ULL)
2836 cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2837 break;
2838 }
2839 if (special6 == SPECIAL_DDIV) {
2840 if (cpu->cd.mips.gpr[rt] == 0) {
2841 cpu->cd.mips.lo = cpu->cd.mips.hi = 0; /* undefined */
2842 } else {
2843 cpu->cd.mips.lo = (int64_t)cpu->cd.mips.gpr[rs] / (int64_t)cpu->cd.mips.gpr[rt];
2844 cpu->cd.mips.hi = (int64_t)cpu->cd.mips.gpr[rs] % (int64_t)cpu->cd.mips.gpr[rt];
2845 }
2846 break;
2847 }
2848 if (special6 == SPECIAL_DDIVU) {
2849 if (cpu->cd.mips.gpr[rt] == 0) {
2850 cpu->cd.mips.lo = cpu->cd.mips.hi = 0; /* undefined */
2851 } else {
2852 cpu->cd.mips.lo = cpu->cd.mips.gpr[rs] / cpu->cd.mips.gpr[rt];
2853 cpu->cd.mips.hi = cpu->cd.mips.gpr[rs] % cpu->cd.mips.gpr[rt];
2854 }
2855 break;
2856 }
2857 if (special6 == SPECIAL_TGE) {
2858 if ((int64_t)cpu->cd.mips.gpr[rs] >= (int64_t)cpu->cd.mips.gpr[rt])
2859 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2860 break;
2861 }
2862 if (special6 == SPECIAL_TGEU) {
2863 if (cpu->cd.mips.gpr[rs] >= cpu->cd.mips.gpr[rt])
2864 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2865 break;
2866 }
2867 if (special6 == SPECIAL_TLT) {
2868 if ((int64_t)cpu->cd.mips.gpr[rs] < (int64_t)cpu->cd.mips.gpr[rt])
2869 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2870 break;
2871 }
2872 if (special6 == SPECIAL_TLTU) {
2873 if (cpu->cd.mips.gpr[rs] < cpu->cd.mips.gpr[rt])
2874 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2875 break;
2876 }
2877 if (special6 == SPECIAL_TEQ) {
2878 if (cpu->cd.mips.gpr[rs] == cpu->cd.mips.gpr[rt])
2879 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2880 break;
2881 }
2882 if (special6 == SPECIAL_TNE) {
2883 if (cpu->cd.mips.gpr[rs] != cpu->cd.mips.gpr[rt])
2884 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
2885 break;
2886 }
2887 if (special6 == SPECIAL_DADD) {
2888 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2889 /* TODO: exception on overflow */
2890 break;
2891 }
2892 if (special6 == SPECIAL_DADDU) {
2893 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2894 break;
2895 }
2896 if (special6 == SPECIAL_DSUB) {
2897 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2898 /* TODO: exception on overflow */
2899 break;
2900 }
2901 if (special6 == SPECIAL_DSUBU) {
2902 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2903 break;
2904 }
2905 if (special6 == SPECIAL_MOVZ) {
2906 if (cpu->cd.mips.gpr[rt] == 0)
2907 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs];
2908 break;
2909 }
2910 if (special6 == SPECIAL_MOVN) {
2911 if (cpu->cd.mips.gpr[rt] != 0)
2912 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs];
2913 return 1;
2914 }
2915 return 1;
2916 case SPECIAL_SYNC:
2917 /* imm = ((instr[1] & 7) << 2) + (instr[0] >> 6); */
2918 /* TODO: actually sync */
2919
2920 /* Clear the LLbit (at least on R10000): */
2921 cpu->cd.mips.rmw = 0;
2922 return 1;
2923 case SPECIAL_SYSCALL:
2924 imm = ((instr[3] << 24) + (instr[2] << 16) +
2925 (instr[1] << 8) + instr[0]) >> 6;
2926 imm &= 0xfffff;
2927
2928 if (cpu->machine->userland_emul != NULL)
2929 useremul_syscall(cpu, imm);
2930 else
2931 mips_cpu_exception(cpu, EXCEPTION_SYS,
2932 0, 0, 0, 0, 0, 0);
2933 return 1;
2934 case SPECIAL_BREAK:
2935 mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
2936 return 1;
2937 case SPECIAL_MFSA:
2938 /* R5900? Move from shift amount register? */
2939 /* rd = (instr[1] >> 3) & 31; */
2940 /* TODO */
2941 return 1;
2942 case SPECIAL_MTSA:
2943 /* R5900? Move to shift amount register? */
2944 /* rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7); */
2945 /* TODO */
2946 return 1;
2947 default:
2948 if (!instruction_trace_cached) {
2949 fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
2950 cpu->cpu_id, (long long)cpu->cd.mips.pc_last,
2951 instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
2952 }
2953 fatal("unimplemented special6 = 0x%02x\n", special6);
2954 cpu->running = 0;
2955 return 1;
2956 }
2957 return 1;
2958 case HI6_BEQ:
2959 case HI6_BEQL:
2960 case HI6_BNE:
2961 case HI6_BGTZ:
2962 case HI6_BGTZL:
2963 case HI6_BLEZ:
2964 case HI6_BLEZL:
2965 case HI6_BNEL:
2966 case HI6_ADDI:
2967 case HI6_ADDIU:
2968 case HI6_DADDI:
2969 case HI6_DADDIU:
2970 case HI6_SLTI:
2971 case HI6_SLTIU:
2972 case HI6_ANDI:
2973 case HI6_ORI:
2974 case HI6_XORI:
2975 case HI6_LUI:
2976 case HI6_LB:
2977 case HI6_LBU:
2978 case HI6_LH:
2979 case HI6_LHU:
2980 case HI6_LW:
2981 case HI6_LWU:
2982 case HI6_LD:
2983 case HI6_LQ_MDMX:
2984 case HI6_LWC1:
2985 case HI6_LWC2:
2986 case HI6_LWC3:
2987 case HI6_LDC1:
2988 case HI6_LDC2:
2989 case HI6_LL:
2990 case HI6_LLD:
2991 case HI6_SB:
2992 case HI6_SH:
2993 case HI6_SW:
2994 case HI6_SD:
2995 case HI6_SQ:
2996 case HI6_SC:
2997 case HI6_SCD:
2998 case HI6_SWC1:
2999 case HI6_SWC2:
3000 case HI6_SWC3:
3001 case HI6_SDC1:
3002 case HI6_SDC2:
3003 case HI6_LWL: /* Unaligned load/store */
3004 case HI6_LWR:
3005 case HI6_LDL:
3006 case HI6_LDR:
3007 case HI6_SWL:
3008 case HI6_SWR:
3009 case HI6_SDL:
3010 case HI6_SDR:
3011 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3012 rt = instr[2] & 31;
3013 imm = (instr[1] << 8) + instr[0];
3014 if (imm >= 32768) /* signed 16-bit */
3015 imm -= 65536;
3016
3017 tmpvalue = imm; /* used later in several cases */
3018
3019 switch (hi6) {
3020 case HI6_ADDI:
3021 case HI6_ADDIU:
3022 case HI6_DADDI:
3023 case HI6_DADDIU:
3024 tmpvalue = cpu->cd.mips.gpr[rs];
3025 result_value = cpu->cd.mips.gpr[rs] + imm;
3026
3027 if (hi6 == HI6_ADDI || hi6 == HI6_DADDI) {
3028 /*
3029 * addi and daddi should trap on overflow:
3030 *
3031 * TODO: This is incorrect? The R4000 manual
3032 * says that overflow occurs if the carry bits
3033 * out of bit 62 and 63 differ. The
3034 * destination register should not be modified
3035 * on overflow.
3036 */
3037 if (imm >= 0) {
3038 /* Turn around from 0x7fff.. to 0x800 ? Then overflow. */
3039 if ( ((hi6 == HI6_ADDI && (result_value &
3040 0x80000000ULL) && (tmpvalue &
3041 0x80000000ULL)==0))
3042 || ((hi6 == HI6_DADDI && (result_value &
3043 0x8000000000000000ULL) && (tmpvalue &
3044 0x8000000000000000ULL)==0)) ) {
3045 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
3046 break;
3047 }
3048 } else {
3049 /* Turn around from 0x8000.. to 0x7fff.. ? Then overflow. */
3050 if ( ((hi6 == HI6_ADDI && (result_value &
3051 0x80000000ULL)==0 && (tmpvalue &
3052 0x80000000ULL)))
3053 || ((hi6 == HI6_DADDI && (result_value &
3054 0x8000000000000000ULL)==0 && (tmpvalue &
3055 0x8000000000000000ULL))) ) {
3056 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
3057 break;
3058 }
3059 }
3060 }
3061
3062 cpu->cd.mips.gpr[rt] = result_value;
3063
3064 /*
3065 * Super-ugly speed-hack: (only if speed_tricks != 0)
3066 * NOTE: This makes the emulation less correct.
3067 *
3068 * If we encounter a loop such as:
3069 *
3070 * 8012f5f4: 1c40ffff bgtz r0,r2,ffffffff8012f5f4
3071 * 8012f5f8: 2442ffff (d) addiu r2,r2,-1
3072 *
3073 * then it is a small loop which simply waits for r2
3074 * to become zero.
3075 *
3076 * TODO: increaste the count register, and cause
3077 * interrupts!!! For now: return as if we just
3078 * executed 1 instruction.
3079 */
3080 ninstrs_executed = 1;
3081 if (cpu->machine->speed_tricks && cpu->cd.mips.delay_slot &&
3082 cpu->cd.mips.last_was_jumptoself &&
3083 cpu->cd.mips.jump_to_self_reg == rt &&
3084 cpu->cd.mips.jump_to_self_reg == rs) {
3085 if ((int64_t)cpu->cd.mips.gpr[rt] > 1 && (int64_t)cpu->cd.mips.gpr[rt] < 0x70000000
3086 && (imm >= -30000 && imm <= -1)) {
3087 if (instruction_trace_cached)
3088 debug("changing r%i from %016llx to", rt, (long long)cpu->cd.mips.gpr[rt]);
3089
3090 while ((int64_t)cpu->cd.mips.gpr[rt] > 0 && ninstrs_executed < 1000
3091 && ((int64_t)cpu->cd.mips.gpr[rt] + (int64_t)imm) > 0) {
3092 cpu->cd.mips.gpr[rt] += (int64_t)imm;
3093 ninstrs_executed += 2;
3094 }
3095
3096 if (instruction_trace_cached)
3097 debug(" %016llx\n", (long long)cpu->cd.mips.gpr[rt]);
3098
3099 /* TODO: return value, cpu->cd.mips.gpr[rt] * 2; */
3100 }
3101 if ((int64_t)cpu->cd.mips.gpr[rt] > -0x70000000 && (int64_t)cpu->cd.mips.gpr[rt] < -1
3102 && (imm >= 1 && imm <= 30000)) {
3103 if (instruction_trace_cached)
3104 debug("changing r%i from %016llx to", rt, (long long)cpu->cd.mips.gpr[rt]);
3105
3106 while ((int64_t)cpu->cd.mips.gpr[rt] < 0 && ninstrs_executed < 1000
3107 && ((int64_t)cpu->cd.mips.gpr[rt] + (int64_t)imm) < 0) {
3108 cpu->cd.mips.gpr[rt] += (int64_t)imm;
3109 ninstrs_executed += 2;
3110 }
3111
3112 if (instruction_trace_cached)
3113 debug(" %016llx\n", (long long)cpu->cd.mips.gpr[rt]);
3114 }
3115 }
3116
3117 if (hi6 == HI6_ADDI || hi6 == HI6_ADDIU) {
3118 /* Sign-extend: */
3119 cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
3120 if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
3121 cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
3122 }
3123 return ninstrs_executed;
3124 case HI6_BEQ:
3125 case HI6_BNE:
3126 case HI6_BGTZ:
3127 case HI6_BGTZL:
3128 case HI6_BLEZ:
3129 case HI6_BLEZL:
3130 case HI6_BEQL:
3131 case HI6_BNEL:
3132 if (cpu->cd.mips.delay_slot) {
3133 fatal("b*: jump inside a jump's delay slot, or similar. TODO\n");
3134 cpu->running = 0;
3135 return 1;
3136 }
3137 likely = cond = 0;
3138 switch (hi6) {
3139 case HI6_BNEL: likely = 1;
3140 case HI6_BNE: cond = (cpu->cd.mips.gpr[rt] != cpu->cd.mips.gpr[rs]);
3141 break;
3142 case HI6_BEQL: likely = 1;
3143 case HI6_BEQ: cond = (cpu->cd.mips.gpr[rt] == cpu->cd.mips.gpr[rs]);
3144 break;
3145 case HI6_BLEZL: likely = 1;
3146 case HI6_BLEZ: cond = ((int64_t)cpu->cd.mips.gpr[rs] <= 0);
3147 break;
3148 case HI6_BGTZL: likely = 1;
3149 case HI6_BGTZ: cond = ((int64_t)cpu->cd.mips.gpr[rs] > 0);
3150 break;
3151 }
3152
3153 if (cond) {
3154 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3155 cpu->cd.mips.delay_jmpaddr = cached_pc + (imm << 2);
3156 } else {
3157 if (likely)
3158 cpu->cd.mips.nullify_next = 1; /* nullify delay slot */
3159 }
3160
3161 if (imm==-1 && (hi6 == HI6_BGTZ || hi6 == HI6_BLEZ ||
3162 (hi6 == HI6_BGTZL && cond) ||
3163 (hi6 == HI6_BLEZL && cond) ||
3164 (hi6 == HI6_BNE && (rt==0 || rs==0)) ||
3165 (hi6 == HI6_BEQ && (rt==0 || rs==0)))) {
3166 cpu->cd.mips.last_was_jumptoself = 2;
3167 if (rs == 0)
3168 cpu->cd.mips.jump_to_self_reg = rt;
3169 else
3170 cpu->cd.mips.jump_to_self_reg = rs;
3171 }
3172 return 1;
3173 case HI6_LUI:
3174 cpu->cd.mips.gpr[rt] = (imm << 16);
3175 /* No sign-extending necessary, as imm already
3176 was sign-extended if it was negative. */
3177 break;
3178 case HI6_SLTI:
3179 cpu->cd.mips.gpr[rt] = (int64_t)cpu->cd.mips.gpr[rs] < (int64_t)tmpvalue;
3180 break;
3181 case HI6_SLTIU:
3182 cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] < (uint64_t)imm;
3183 break;
3184 case HI6_ANDI:
3185 cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] & (tmpvalue & 0xffff);
3186 break;
3187 case HI6_ORI:
3188 cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] | (tmpvalue & 0xffff);
3189 break;
3190 case HI6_XORI:
3191 cpu->cd.mips.gpr[rt] = cpu->cd.mips.gpr[rs] ^ (tmpvalue & 0xffff);
3192 break;
3193 case HI6_LB:
3194 case HI6_LBU:
3195 case HI6_LH:
3196 case HI6_LHU:
3197 case HI6_LW:
3198 case HI6_LWU:
3199 case HI6_LD:
3200 case HI6_LQ_MDMX:
3201 case HI6_LWC1:
3202 case HI6_LWC2:
3203 case HI6_LWC3: /* pref */
3204 case HI6_LDC1:
3205 case HI6_LDC2:
3206 case HI6_LL:
3207 case HI6_LLD:
3208 case HI6_SB:
3209 case HI6_SH:
3210 case HI6_SW:
3211 case HI6_SD:
3212 case HI6_SQ:
3213 case HI6_SC:
3214 case HI6_SCD:
3215 case HI6_SWC1:
3216 case HI6_SWC2:
3217 case HI6_SWC3:
3218 case HI6_SDC1:
3219 case HI6_SDC2:
3220 /* These are the default "assumptions". */
3221 linked = 0;
3222 st = 1;
3223 signd = 1;
3224 wlen = 4;
3225
3226 switch (hi6) {
3227 /* The most common ones: */
3228 case HI6_LW: { st = 0; } break;
3229 case HI6_SW: { signd = 0; } break;
3230
3231 case HI6_LB: { wlen = 1; st = 0; } break;
3232 case HI6_LBU: { wlen = 1; st = 0; signd = 0; } break;
3233 case HI6_SB: { wlen = 1; signd = 0; } break;
3234
3235 case HI6_LD: { wlen = 8; st = 0; signd = 0; } break;
3236 case HI6_SD: { wlen = 8; signd = 0; } break;
3237
3238 case HI6_LQ_MDMX: { wlen = 16; st = 0; signd = 0; } break; /* R5900, otherwise MDMX (TODO) */
3239 case HI6_SQ: { wlen = 16; signd = 0; } break; /* R5900 ? */
3240
3241 /* The rest: */
3242 case HI6_LH: { wlen = 2; st = 0; } break;
3243 case HI6_LHU: { wlen = 2; st = 0; signd = 0; } break;
3244 case HI6_LWU: { st = 0; signd = 0; } break;
3245 case HI6_LWC1: { st = 0; } break;
3246 case HI6_LWC2: { st = 0; } break;
3247 case HI6_LWC3: { st = 0; } break;
3248 case HI6_LDC1: { wlen = 8; st = 0; signd = 0; } break;
3249 case HI6_LDC2: { wlen = 8; st = 0; signd = 0; } break;
3250
3251 case HI6_SH: { wlen = 2; signd = 0; } break;
3252 case HI6_SDC1:
3253 case HI6_SDC2: wlen = 8;
3254 case HI6_SWC1:
3255 case HI6_SWC2:
3256 case HI6_SWC3: { signd = 0; } break;
3257
3258 case HI6_LL: { st = 0; signd = 1; linked = 1; } break;
3259 case HI6_LLD: { wlen = 8; st = 0; signd = 0; linked = 1; } break;
3260
3261 case HI6_SC: { signd = 1; linked = 1; } break;
3262 case HI6_SCD: { wlen = 8; signd = 0; linked = 1; } break;
3263
3264 default:
3265 fatal("cannot be here\n");
3266 wlen = 4; st = 0; signd = 0;
3267 }
3268
3269 /*
3270 * In the MIPS IV ISA, the 'lwc3' instruction is changed into 'pref'.
3271 * The pref instruction is emulated by not doing anything. :-) TODO
3272 */
3273 if (hi6 == HI6_LWC3 && cpu->cd.mips.cpu_type.isa_level >= 4) {
3274 /* Clear the LLbit (at least on R10000): */
3275 cpu->cd.mips.rmw = 0;
3276 break;
3277 }
3278
3279 addr = cpu->cd.mips.gpr[rs] + imm;
3280
3281 /* Check for natural alignment: */
3282 if ((addr & (wlen - 1)) != 0) {
3283 mips_cpu_exception(cpu, st? EXCEPTION_ADES : EXCEPTION_ADEL,
3284 0, addr, 0, 0, 0, 0);
3285 break;
3286 }
3287
3288 #if 0
3289 if (cpu->cd.mips.cpu_type.isa_level == 4 && (imm & (wlen - 1)) != 0)
3290 debug("WARNING: low bits of imm value not zero! (MIPS IV) "
3291 "pc=%016llx", (long long)cpu->cd.mips.pc_last);
3292 #endif
3293
3294 /*
3295 * Load Linked: This initiates a Read-Modify-Write
3296 * sequence.
3297 */
3298 if (linked) {
3299 if (st==0) {
3300 /* st == 0: Load */
3301 cpu->cd.mips.rmw = 1;
3302 cpu->cd.mips.rmw_addr = addr;
3303 cpu->cd.mips.rmw_len = wlen;
3304
3305 /*
3306 * COP0_LLADDR is updated for
3307 * diagnostic purposes, except for
3308 * CPUs in the R10000 family.
3309 */
3310 if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
3311 cp0->reg[COP0_LLADDR] =
3312 (addr >> 4) & 0xffffffffULL;
3313 } else {
3314 /*
3315 * st == 1: Store
3316 * If rmw is 0, then the store failed.
3317 * (This cache-line was written to by
3318 * someone else.)
3319 */
3320 if (cpu->cd.mips.rmw == 0 ||
3321 cpu->cd.mips.rmw_addr != addr ||
3322 cpu->cd.mips.rmw_len != wlen) {
3323 /* The store failed: */
3324 cpu->cd.mips.gpr[rt] = 0;
3325 if (instruction_trace_cached)
3326 debug(" [COLLISION] ");
3327 break;
3328 }
3329 }
3330 } else {
3331 /*
3332 * If any kind of load or store occurs between
3333 * an ll and an sc, then the ll-sc sequence
3334 * should fail. (This is local to each cpu.)
3335 */
3336 cpu->cd.mips.rmw = 0;
3337 }
3338
3339 value_hi = 0;
3340
3341 if (st) {
3342 /* store: */
3343 int cpnr, success;
3344
3345 if (hi6 == HI6_SWC3 || hi6 == HI6_SWC2 ||
3346 hi6 == HI6_SDC1 || hi6 == HI6_SWC1) {
3347 cpnr = 1;
3348 switch (hi6) {
3349 case HI6_SWC3: cpnr++; /* fallthrough */
3350 case HI6_SWC2: cpnr++;
3351 case HI6_SDC1:
3352 case HI6_SWC1: if (cpu->cd.mips.coproc[cpnr] == NULL ||
3353 (!(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ) {
3354 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3355 cpnr = -1;
3356 break;
3357 } else {
3358 /* Special handling of 64-bit stores
3359 on 32-bit CPUs, and on newer CPUs
3360 in 32-bit compatiblity mode: */
3361 if ((hi6==HI6_SDC1 || hi6==HI6_SDC2) &&
3362 (cpu->cd.mips.cpu_type.isa_level <= 2 ||
3363 !(cp0->reg[COP0_STATUS] & STATUS_FR))) {
3364 uint64_t a, b;
3365 coproc_register_read(cpu,
3366 cpu->cd.mips.coproc[cpnr], rt, &a, 0);
3367 coproc_register_read(cpu,
3368 cpu->cd.mips.coproc[cpnr], rt^1, &b, 0);
3369 if (rt & 1)
3370 fatal("WARNING: SDCx in 32-bit mode from odd register!\n");
3371 value = (a & 0xffffffffULL)
3372 | (b << 32);
3373 } else
3374 coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr], rt, &value, 0);
3375 }
3376 break;
3377 default:
3378 ;
3379 }
3380 if (cpnr < 0)
3381 break;
3382 } else
3383 value = cpu->cd.mips.gpr[rt];
3384
3385 if (wlen == 4) {
3386 /* Special case for 32-bit stores... (perhaps not worth it) */
3387 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3388 d[0] = value & 0xff; d[1] = (value >> 8) & 0xff;
3389 d[2] = (value >> 16) & 0xff; d[3] = (value >> 24) & 0xff;
3390 } else {
3391 d[3] = value & 0xff; d[2] = (value >> 8) & 0xff;
3392 d[1] = (value >> 16) & 0xff; d[0] = (value >> 24) & 0xff;
3393 }
3394 } else if (wlen == 16) {
3395 value_hi = cpu->cd.mips.gpr_quadhi[rt];
3396 /* Special case for R5900 128-bit stores: */
3397 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3398 for (i=0; i<8; i++) {
3399 d[i] = (value >> (i*8)) & 255;
3400 d[i+8] = (value_hi >> (i*8)) & 255;
3401 }
3402 else
3403 for (i=0; i<8; i++) {
3404 d[i] = (value >> ((wlen-1-i)*8)) & 255;
3405 d[i + 8] = (value_hi >> ((wlen-1-i)*8)) & 255;
3406 }
3407 } else if (wlen == 1) {
3408 d[0] = value & 0xff;
3409 } else {
3410 /* General case: */
3411 uint64_t v = value;
3412 if (cpu->byte_order ==
3413 EMUL_LITTLE_ENDIAN)
3414 for (i=0; i<wlen; i++) {
3415 d[i] = v & 255;
3416 v >>= 8;
3417 }
3418 else
3419 for (i=0; i<wlen; i++) {
3420 d[wlen-1-i] = v & 255;
3421 v >>= 8;
3422 }
3423 }
3424
3425 success = cpu->memory_rw(cpu, cpu->mem, addr,
3426 d, wlen, MEM_WRITE, CACHE_DATA);
3427 if (!success) {
3428 /* The store failed, and might have caused an exception. */
3429 if (instruction_trace_cached)
3430 debug("(failed)]\n");
3431 break;
3432 }
3433 } else {
3434 /* load: */
3435 int cpnr = 1;
3436 int success;
3437
3438 success = cpu->memory_rw(cpu, cpu->mem, addr,
3439 d, wlen, MEM_READ, CACHE_DATA);
3440 if (!success) {
3441 /* The load failed, and might have caused an exception. */
3442 if (instruction_trace_cached)
3443 debug("(failed)]\n");
3444 break;
3445 }
3446
3447 if (wlen == 1)
3448 value = d[0] | (signd && (d[0]&128)? (-1 << 8) : 0);
3449 else if (wlen != 16) {
3450 /* General case (except for 128-bit): */
3451 int i;
3452 value = 0;
3453 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3454 if (signd && (d[wlen-1] & 128)!=0) /* sign extend */
3455 value = -1;
3456 for (i=wlen-1; i>=0; i--) {
3457 value <<= 8;
3458 value += d[i];
3459 }
3460 } else {
3461 if (signd && (d[0] & 128)!=0) /* sign extend */
3462 value = -1;
3463 for (i=0; i<wlen; i++) {
3464 value <<= 8;
3465 value += d[i];
3466 }
3467 }
3468 } else {
3469 /* R5900 128-bit quadword: */
3470 int i;
3471 value_hi = 0;
3472 value = 0;
3473 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
3474 for (i=wlen-1; i>=0; i--) {
3475 value_hi <<= 8;
3476 value_hi += (value >> 56) & 255;
3477 value <<= 8;
3478 value += d[i];
3479 }
3480 } else {
3481 for (i=0; i<wlen; i++) {
3482 value_hi <<= 8;
3483 value_hi += (value >> 56) & 255;
3484 value <<= 8;
3485 value += d[i];
3486 }
3487 }
3488 cpu->cd.mips.gpr_quadhi[rt] = value_hi;
3489 }
3490
3491 switch (hi6) {
3492 case HI6_LWC3: cpnr++; /* fallthrough */
3493 case HI6_LDC2:
3494 case HI6_LWC2: cpnr++;
3495 case HI6_LDC1:
3496 case HI6_LWC1: if (cpu->cd.mips.coproc[cpnr] == NULL ||
3497 (!(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ) {
3498 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3499 } else {
3500 /* Special handling of 64-bit loads
3501 on 32-bit CPUs, and on newer CPUs
3502 in 32-bit compatiblity mode: */
3503 if ((hi6==HI6_LDC1 || hi6==HI6_LDC2) &&
3504 (cpu->cd.mips.cpu_type.isa_level <= 2 ||
3505 !(cp0->reg[COP0_STATUS] & STATUS_FR))) {
3506 uint64_t a, b;
3507 a = (int64_t)(int32_t) (value & 0xffffffffULL);
3508 b = (int64_t)(int32_t) (value >> 32);
3509 coproc_register_write(cpu,
3510 cpu->cd.mips.coproc[cpnr], rt, &a,
3511 hi6==HI6_LDC1 || hi6==HI6_LDC2, 0);
3512 coproc_register_write(cpu,
3513 cpu->cd.mips.coproc[cpnr], rt ^ 1, &b,
3514 hi6==HI6_LDC1 || hi6==HI6_LDC2, 0);
3515 if (rt & 1)
3516 fatal("WARNING: LDCx in 32-bit mode to odd register!\n");
3517 } else {
3518 coproc_register_write(cpu,
3519 cpu->cd.mips.coproc[cpnr], rt, &value,
3520 hi6==HI6_LDC1 || hi6==HI6_LDC2, 0);
3521 }
3522 }
3523 break;
3524 default: if (rt != 0)
3525 cpu->cd.mips.gpr[rt] = value;
3526 }
3527 }
3528
3529 if (linked && st==1) {
3530 /*
3531 * The store succeeded. Invalidate any other
3532 * cpu's store to this cache line, and then
3533 * return 1 in gpr rt:
3534 *
3535 * (this is a semi-ugly hack using global
3536 * 'cpus')
3537 *
3538 * TODO: How about invalidating other CPUs
3539 * stores to this cache line, even if this
3540 * was _NOT_ a linked store?
3541 */
3542 for (i=0; i<cpu->machine->ncpus; i++) {
3543 if (cpu->machine->cpus[i]->cd.mips.rmw) {
3544 uint64_t yaddr = addr;
3545 uint64_t xaddr =
3546 cpu->machine->cpus[i]->cd.mips.rmw_addr;
3547 uint64_t mask;
3548 mask = ~(cpu->machine->cpus[i]->
3549 cd.mips.cache_linesize[CACHE_DATA]
3550 - 1);
3551 xaddr &= mask;
3552 yaddr &= mask;
3553 if (xaddr == yaddr) {
3554 cpu->machine->cpus[i]->cd.mips.rmw = 0;
3555 cpu->machine->cpus[i]->cd.mips.rmw_addr = 0;
3556 }
3557 }
3558 }
3559
3560 if (rt != 0)
3561 cpu->cd.mips.gpr[rt] = 1;
3562
3563 if (instruction_trace_cached)
3564 debug(" [no collision] ");
3565 cpu->cd.mips.rmw = 0;
3566 }
3567
3568 if (instruction_trace_cached) {
3569 switch (wlen) {
3570 case 2: debug("0x%04x", (int)value); break;
3571 case 4: debug("0x%08x", (int)value); break;
3572 case 8: debug("0x%016llx", (long long)value);
3573 break;
3574 case 16:debug("0x%016llx", (long long)value_hi);
3575 debug("%016llx", (long long)value);
3576 break;
3577 default:debug("0x%02x", (int)value);
3578 }
3579 debug("]\n");
3580 }
3581 return 1;
3582 case HI6_LWL: /* Unaligned load/store */
3583 case HI6_LWR:
3584 case HI6_LDL:
3585 case HI6_LDR:
3586 case HI6_SWL:
3587 case HI6_SWR:
3588 case HI6_SDL:
3589 case HI6_SDR:
3590 /* For L (Left): address is the most significant byte */
3591 /* For R (Right): address is the least significant byte */
3592 addr = cpu->cd.mips.gpr[rs] + imm;
3593
3594 is_left = 0;
3595 if (hi6 == HI6_SWL || hi6 == HI6_LWL ||
3596 hi6 == HI6_SDL || hi6 == HI6_LDL)
3597 is_left = 1;
3598
3599 wlen = 0; st = 0;
3600 signd = 0;
3601 if (hi6 == HI6_LWL || hi6 == HI6_LWR)
3602 signd = 1;
3603
3604 if (hi6 == HI6_LWL || hi6 == HI6_LWR) { wlen = 4; st = 0; }
3605 if (hi6 == HI6_SWL || hi6 == HI6_SWR) { wlen = 4; st = 1; }
3606 if (hi6 == HI6_LDL || hi6 == HI6_LDR) { wlen = 8; st = 0; }
3607 if (hi6 == HI6_SDL || hi6 == HI6_SDR) { wlen = 8; st = 1; }
3608
3609 dir = 1; /* big endian, Left */
3610 reg_dir = -1;
3611 reg_ofs = wlen - 1; /* byte offset in the register */
3612 if (!is_left) {
3613 dir = -dir;
3614 reg_ofs = 0;
3615 reg_dir = 1;
3616 }
3617 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3618 dir = -dir;
3619
3620 result_value = cpu->cd.mips.gpr[rt];
3621
3622 if (st) {
3623 /* Store: */
3624 uint64_t aligned_addr = addr & ~(wlen-1);
3625 unsigned char aligned_word[8];
3626 uint64_t oldpc = cpu->pc;
3627 /*
3628 * NOTE (this is ugly): The memory_rw()
3629 * call generates a TLBL exception, if there
3630 * is a tlb refill exception. However, since
3631 * this is a Store, the exception is converted
3632 * to a TLBS:
3633 */
3634 int ok = cpu->memory_rw(cpu, cpu->mem,
3635 aligned_addr, &aligned_word[0], wlen,
3636 MEM_READ, CACHE_DATA);
3637 if (!ok) {
3638 if (cpu->pc != oldpc) {
3639 cp0->reg[COP0_CAUSE] &= ~CAUSE_EXCCODE_MASK;
3640 cp0->reg[COP0_CAUSE] |= (EXCEPTION_TLBS << CAUSE_EXCCODE_SHIFT);
3641 }
3642 return 1;
3643 }
3644
3645 for (i=0; i<wlen; i++) {
3646 tmpaddr = addr + i*dir;
3647 /* Have we moved into another word/dword? Then stop: */
3648 if ( (tmpaddr & ~(wlen-1)) != (addr & ~(wlen-1)) )
3649 break;
3650
3651 /* debug("unaligned byte at %016llx, reg_ofs=%i reg=0x%016llx\n",
3652 tmpaddr, reg_ofs, (long long)result_value); */
3653
3654 /* Store one byte: */
3655 aligned_word[tmpaddr & (wlen-1)] = (result_value >> (reg_ofs * 8)) & 255;
3656
3657 reg_ofs += reg_dir;
3658 }
3659
3660 ok = cpu->memory_rw(cpu, cpu->mem,
3661 aligned_addr, &aligned_word[0], wlen,
3662 MEM_WRITE, CACHE_DATA);
3663 if (!ok)
3664 return 1;
3665 } else {
3666 /* Load: */
3667 uint64_t aligned_addr = addr & ~(wlen-1);
3668 unsigned char aligned_word[8], databyte;
3669 int ok = cpu->memory_rw(cpu, cpu->mem,
3670 aligned_addr, &aligned_word[0], wlen,
3671 MEM_READ, CACHE_DATA);
3672 if (!ok)
3673 return 1;
3674
3675 for (i=0; i<wlen; i++) {
3676 tmpaddr = addr + i*dir;
3677 /* Have we moved into another word/dword? Then stop: */
3678 if ( (tmpaddr & ~(wlen-1)) != (addr & ~(wlen-1)) )
3679 break;
3680
3681 /* debug("unaligned byte at %016llx, reg_ofs=%i reg=0x%016llx\n",
3682 tmpaddr, reg_ofs, (long long)result_value); */
3683
3684 /* Load one byte: */
3685 databyte = aligned_word[tmpaddr & (wlen-1)];
3686 result_value &= ~((uint64_t)0xff << (reg_ofs * 8));
3687 result_value |= (uint64_t)databyte << (reg_ofs * 8);
3688
3689 reg_ofs += reg_dir;
3690 }
3691
3692 if (rt != 0)
3693 cpu->cd.mips.gpr[rt] = result_value;
3694 }
3695
3696 /* Sign extend for 32-bit load lefts: */
3697 if (!st && signd && wlen == 4) {
3698 cpu->cd.mips.gpr[rt] &= 0xffffffffULL;
3699 if (cpu->cd.mips.gpr[rt] & 0x80000000ULL)
3700 cpu->cd.mips.gpr[rt] |= 0xffffffff00000000ULL;
3701 }
3702
3703 if (instruction_trace_cached) {
3704 char *t;
3705 switch (wlen) {
3706 case 2: t = "0x%04llx"; break;
3707 case 4: t = "0x%08llx"; break;
3708 case 8: t = "0x%016llx"; break;
3709 default: t = "0x%02llx";
3710 }
3711 debug(t, (long long)cpu->cd.mips.gpr[rt]);
3712 debug("]\n");
3713 }
3714
3715 return 1;
3716 }
3717 return 1;
3718 case HI6_REGIMM:
3719 regimm5 = instr[2] & 0x1f;
3720
3721 if (show_opcode_statistics)
3722 cpu->cd.mips.stats__regimm[regimm5] ++;
3723
3724 switch (regimm5) {
3725 case REGIMM_BLTZ:
3726 case REGIMM_BGEZ:
3727 case REGIMM_BLTZL:
3728 case REGIMM_BGEZL:
3729 case REGIMM_BLTZAL:
3730 case REGIMM_BLTZALL:
3731 case REGIMM_BGEZAL:
3732 case REGIMM_BGEZALL:
3733 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3734 imm = (instr[1] << 8) + instr[0];
3735 if (imm >= 32768) /* signed 16-bit */
3736 imm -= 65536;
3737
3738 cond = and_link = likely = 0;
3739
3740 switch (regimm5) {
3741 case REGIMM_BLTZL: likely = 1;
3742 case REGIMM_BLTZ: cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) != 0;
3743 break;
3744 case REGIMM_BGEZL: likely = 1;
3745 case REGIMM_BGEZ: cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) == 0;
3746 break;
3747
3748 case REGIMM_BLTZALL: likely = 1;
3749 case REGIMM_BLTZAL: and_link = 1;
3750 cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) != 0;
3751 break;
3752 case REGIMM_BGEZALL: likely = 1;
3753 case REGIMM_BGEZAL: and_link = 1;
3754 cond = (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << 63)) == 0;
3755 break;
3756 }
3757
3758 if (and_link)
3759 cpu->cd.mips.gpr[31] = cached_pc + 4;
3760
3761 if (cond) {
3762 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3763 cpu->cd.mips.delay_jmpaddr = cached_pc + (imm << 2);
3764 } else {
3765 if (likely)
3766 cpu->cd.mips.nullify_next = 1; /* nullify delay slot */
3767 }
3768
3769 return 1;
3770 default:
3771 if (!instruction_trace_cached) {
3772 fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
3773 cpu->cpu_id, (long long)cpu->cd.mips.pc_last,
3774 instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
3775 }
3776 fatal("unimplemented regimm5 = 0x%02x\n", regimm5);
3777 cpu->running = 0;
3778 return 1;
3779 }
3780 /* NOT REACHED */
3781 case HI6_J:
3782 case HI6_JAL:
3783 if (cpu->cd.mips.delay_slot) {
3784 fatal("j/jal: jump inside a jump's delay slot, or similar. TODO\n");
3785 cpu->running = 0;
3786 return 1;
3787 }
3788 imm = ((instr[3] & 3) << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3789 imm <<= 2;
3790
3791 if (hi6 == HI6_JAL)
3792 cpu->cd.mips.gpr[31] = cached_pc + 4; /* pc already increased by 4 earlier */
3793
3794 addr = cached_pc & ~((1 << 28) - 1);
3795 addr |= imm;
3796
3797 cpu->cd.mips.delay_slot = TO_BE_DELAYED;
3798 cpu->cd.mips.delay_jmpaddr = addr;
3799
3800 if (cpu->machine->show_trace_tree && hi6 == HI6_JAL) {
3801 cpu->cd.mips.show_trace_delay = 2;
3802 cpu->cd.mips.show_trace_addr = addr;
3803 }
3804
3805 return 1;
3806 case HI6_COP0:
3807 case HI6_COP1:
3808 case HI6_COP2:
3809 case HI6_COP3:
3810 imm = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3811 imm &= ((1 << 26) - 1);
3812
3813 cpnr = 0;
3814 if (hi6 == HI6_COP0) cpnr = 0;
3815 if (hi6 == HI6_COP1) cpnr = 1;
3816 if (hi6 == HI6_COP2) cpnr = 2;
3817 if (hi6 == HI6_COP3) cpnr = 3;
3818
3819 /*
3820 * If there is no coprocessor nr cpnr, or we are running in
3821 * userland and the coprocessor is not marked as Useable in
3822 * the status register of CP0, then we get an exception.
3823 *
3824 * An exception (hehe) to this rule is that the kernel should
3825 * always be able to access CP0.
3826 */
3827 /* Set tmp = 1 if we're in user mode. */
3828 tmp = 0;
3829 switch (cpu->cd.mips.cpu_type.exc_model) {
3830 case EXC3K:
3831 /*
3832 * NOTE: If the KU bit is checked, Linux crashes.
3833 * It is the PC that counts. TODO: Check whether
3834 * this is true or not for R4000 as well.
3835 */
3836 if (cached_pc <= 0x7fffffff) /* if (cp0->reg[COP0_STATUS] & MIPS1_SR_KU_CUR) */
3837 tmp = 1;
3838 break;
3839 default:
3840 /* R4000 etc: (TODO: How about supervisor mode?) */
3841 if (((cp0->reg[COP0_STATUS] & STATUS_KSU_MASK) >> STATUS_KSU_SHIFT) != KSU_KERNEL)
3842 tmp = 1;
3843 if (cp0->reg[COP0_STATUS] & STATUS_ERL)
3844 tmp = 0;
3845 if (cp0->reg[COP0_STATUS] & STATUS_EXL)
3846 tmp = 0;
3847 break;
3848 }
3849 if (cpu->cd.mips.coproc[cpnr] == NULL ||
3850 (tmp && !(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ||
3851 (!tmp && cpnr >= 1 && !(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)))
3852 ) {
3853 if (instruction_trace_cached)
3854 debug("cop%i\t0x%08x => coprocessor unusable\n", cpnr, (int)imm);
3855 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3856 } else {
3857 /*
3858 * Execute the coprocessor function. The
3859 * coproc_function code outputs instruction
3860 * trace, if necessary.
3861 */
3862 coproc_function(cpu, cpu->cd.mips.coproc[cpnr],
3863 cpnr, imm, 0, 1);
3864 }
3865 return 1;
3866 case HI6_CACHE:
3867 rt = ((instr[3] & 3) << 3) + (instr[2] >> 5); /* base */
3868 copz = instr[2] & 31;
3869 imm = (instr[1] << 8) + instr[0];
3870
3871 cache_op = copz >> 2;
3872 which_cache = copz & 3;
3873
3874 /*
3875 * TODO: The cache instruction is implementation dependant.
3876 */
3877
3878 /*
3879 * Clear the LLbit (at least on R10000):
3880 * TODO: How about R4000?
3881 */
3882 cpu->cd.mips.rmw = 0;
3883
3884 return 1;
3885 case HI6_SPECIAL2:
3886 special6 = instr[0] & 0x3f;
3887
3888 if (show_opcode_statistics)
3889 cpu->cd.mips.stats__special2[special6] ++;
3890
3891 instrword = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3892
3893 rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3894 rt = instr[2] & 31;
3895 rd = (instr[1] >> 3) & 31;
3896
3897 /* printf("special2 %08x rs=0x%02x rt=0x%02x rd=0x%02x\n", instrword, rs,rt,rd); */
3898
3899 /*
3900 * Many of these can be found in the R5000 docs, or figured out
3901 * by studying binutils source code for MIPS instructions.
3902 */
3903
3904 if ((instrword & 0xfc0007ffULL) == 0x70000000) {
3905 {
3906 int32_t a, b;
3907 int64_t c;
3908 a = (int32_t)cpu->cd.mips.gpr[rs];
3909 b = (int32_t)cpu->cd.mips.gpr[rt];
3910 c = a * b;
3911 c += (cpu->cd.mips.lo & 0xffffffffULL)
3912 + (cpu->cd.mips.hi << 32);
3913 cpu->cd.mips.lo = (int64_t)((int32_t)c);
3914 cpu->cd.mips.hi = (int64_t)((int32_t)(c >> 32));
3915
3916 /*
3917 * The R5000 manual says that rd should be all zeros,
3918 * but it isn't on R5900. I'm just guessing here that
3919 * it stores the value in register rd, in addition to hi/lo.
3920 * TODO
3921 */
3922 if (rd != 0)
3923 cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
3924 }
3925 } else if ((instrword & 0xffff07ffULL) == 0x70000209
3926 || (instrword & 0xffff07ffULL) == 0x70000249) {
3927 /*
3928 * This is just a guess for R5900, I've not found any docs on this one yet.
3929 *
3930 * pmfhi/pmflo rd
3931 *
3932 * If the lowest 8 bits of the instruction word are 0x09, it's a pmfhi.
3933 * If the lowest bits are 0x49, it's a pmflo.
3934 *
3935 * A wild guess is that this is a 128-bit version of mfhi/mflo.
3936 * For now, this is implemented as 64-bit only. (TODO)
3937 */
3938 if (instr[0] == 0x49) {
3939 cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
3940 } else {
3941 cpu->cd.mips.gpr[rd] = cpu->cd.mips.hi;
3942 }
3943 } else if ((instrword & 0xfc1fffff) == 0x70000269 || (instrword & 0xfc1fffff) == 0x70000229) {
3944 /*
3945 * This is just a guess for R5900, I've not found any docs on this one yet.
3946 *
3947 * pmthi/pmtlo rs (pmtlo = 269, pmthi = 229)
3948 *
3949 * A wild guess is that this is a 128-bit version of mthi/mtlo.
3950 * For now, this is implemented as 64-bit only. (TODO)
3951 */
3952 if (instr[0] == 0x69) {
3953 cpu->cd.mips.lo = cpu->cd.mips.gpr[rs];
3954 } else {
3955 cpu->cd.mips.hi = cpu->cd.mips.gpr[rs];
3956 }
3957 } else if ((instrword & 0xfc0007ff) == 0x700004a9) {
3958 /*
3959 * This is just a guess for R5900, I've not found any docs on this one yet.
3960 *
3961 * por dst,src,src2 ==> rs=src rt=src2 rd=dst
3962 *
3963 * A wild guess is that this is a 128-bit "or" between two registers.
3964 * For now, let's just or using 64-bits. (TODO)
3965 */
3966 cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt];
3967 } else if ((instrword & 0xfc0007ff) == 0x70000488) {
3968 /*
3969 * R5900 "undocumented" pextlw. TODO: find out if this is correct.
3970 * It seems that this instruction is used to combine two 32-bit
3971 * words into a 64-bit dword, typically before a sd (store dword).
3972 */
3973 cpu->cd.mips.gpr[rd] =
3974 ((cpu->cd.mips.gpr[rs] & 0xffffffffULL) << 32) /* TODO: switch rt and rs? */
3975 | (cpu->cd.mips.gpr[rt] & 0xffffffffULL);
3976 } else if (special6 == SPECIAL2_MUL) {
3977 cpu->cd.mips.gpr[rd] = (int64_t)cpu->cd.mips.gpr[rt] *
3978 (int64_t)cpu->cd.mips.gpr[rs];
3979 } else if (special6 == SPECIAL2_CLZ) {
3980 /* clz: count leading zeroes */
3981 int i, n=0;
3982 for (i=31; i>=0; i--) {
3983 if (cpu->cd.mips.gpr[rs] & ((uint32_t)1 << i))
3984 break;
3985 else
3986 n++;
3987 }
3988 cpu->cd.mips.gpr[rd] = n;
3989 } else if (special6 == SPECIAL2_CLO) {
3990 /* clo: count leading ones */
3991 int i, n=0;
3992 for (i=31; i>=0; i--) {
3993 if (cpu->cd.mips.gpr[rs] & ((uint32_t)1 << i))
3994 n++;
3995 else
3996 break;
3997 }
3998 cpu->cd.mips.gpr[rd] = n;
3999 } else if (special6 == SPECIAL2_DCLZ) {
4000 /* dclz: count leading zeroes */
4001 int i, n=0;
4002 for (i=63; i>=0; i--) {
4003 if (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << i))
4004 break;
4005 else
4006 n++;
4007 }
4008 cpu->cd.mips.gpr[rd] = n;
4009 } else if (special6 == SPECIAL2_DCLO) {
4010 /* dclo: count leading ones */
4011 int i, n=0;
4012 for (i=63; i>=0; i--) {
4013 if (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << i))
4014 n++;
4015 else
4016 break;
4017 }
4018 cpu->cd.mips.gpr[rd] = n;
4019 } else {
4020 if (!instruction_trace_cached) {
4021 fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
4022 cpu->cpu_id, (long long)cpu->cd.mips.pc_last,
4023 instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
4024 }
4025 fatal("unimplemented special_2 = 0x%02x, rs=0x%02x rt=0x%02x rd=0x%02x\n",
4026 special6, rs, rt, rd);
4027 cpu->running = 0;
4028 return 1;
4029 }
4030 return 1;
4031 default:
4032 if (!instruction_trace_cached) {
4033 fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
4034 cpu->cpu_id, (long long)cpu->cd.mips.pc_last,
4035 instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
4036 }
4037 fatal("unimplemented hi6 = 0x%02x\n", hi6);
4038 cpu->running = 0;
4039 return 1;
4040 }
4041
4042 /* NOTREACHED */
4043 }
4044
4045
4046 #define CPU_RUN mips_cpu_run
4047 #define CPU_RUN_MIPS
4048 #define CPU_RINSTR mips_cpu_run_instr
4049 #include "cpu_run.c"
4050 #undef CPU_RINSTR
4051 #undef CPU_RUN_MIPS
4052 #undef CPU_RUN
4053
4054
4055 /*
4056 * mips_cpu_dumpinfo():
4057 *
4058 * Debug dump of MIPS-specific CPU data for specific CPU.
4059 */
4060 void mips_cpu_dumpinfo(struct cpu *cpu)
4061 {
4062 int iadd = 4;
4063 struct mips_cpu_type_def *ct = &cpu->cd.mips.cpu_type;
4064
4065 debug_indentation(iadd);
4066
4067 debug("\n%i-bit %s (MIPS",
4068 cpu->is_32bit? 32 : 64,
4069 cpu->byte_order == EMUL_BIG_ENDIAN? "BE" : "LE");
4070
4071 switch (ct->isa_level) {
4072 case 1: debug(" ISA I"); break;
4073 case 2: debug(" ISA II"); break;
4074 case 3: debug(" ISA III"); break;
4075 case 4: debug(" ISA IV"); break;
4076 case 5: debug(" ISA V"); break;
4077 case 32:
4078 case 64:debug("%i", ct->isa_level); break;
4079 default:debug(" ISA level %i", ct->isa_level);
4080 }
4081
4082 debug("), ");
4083 if (ct->nr_of_tlb_entries)
4084 debug("%i TLB entries", ct->nr_of_tlb_entries);
4085 else
4086 debug("no TLB");
4087 debug("\n");
4088
4089 if (ct->picache) {
4090 debug("L1 I-cache: %i KB", (1 << ct->picache) / 1024);
4091 if (ct->pilinesize)
4092 debug(", %i bytes per line", 1 << ct->pilinesize);
4093 if (ct->piways > 1)
4094 debug(", %i-way", ct->piways);
4095 else
4096 debug(", direct-mapped");
4097 debug("\n");
4098 }
4099
4100 if (ct->pdcache) {
4101 debug("L1 D-cache: %i KB", (1 << ct->pdcache) / 1024);
4102 if (ct->pdlinesize)
4103 debug(", %i bytes per line", 1 << ct->pdlinesize);
4104 if (ct->pdways > 1)
4105 debug(", %i-way", ct->pdways);
4106 else
4107 debug(", direct-mapped");
4108 debug("\n");
4109 }
4110
4111 if (ct->scache) {
4112 int kb = (1 << ct->scache) / 1024;
4113 debug("L2 cache: %i %s",
4114 kb >= 1024? kb / 1024 : kb, kb >= 1024? "MB":"KB");
4115 if (ct->slinesize)
4116 debug(", %i bytes per line", 1 << ct->slinesize);
4117 if (ct->sways > 1)
4118 debug(", %i-way", ct->sways);
4119 else
4120 debug(", direct-mapped");
4121 debug("\n");
4122 }
4123
4124 debug_indentation(-iadd);
4125 }
4126
4127
4128 /*
4129 * mips_cpu_list_available_types():
4130 *
4131 * Print a list of available MIPS CPU types.
4132 */
4133 void mips_cpu_list_available_types(void)
4134 {
4135 int i, j;
4136 struct mips_cpu_type_def cpu_type_defs[] = MIPS_CPU_TYPE_DEFS;
4137
4138 i = 0;
4139 while (cpu_type_defs[i].name != NULL) {
4140 debug("%s", cpu_type_defs[i].name);
4141 for (j=10 - strlen(cpu_type_defs[i].name); j>0; j--)
4142 debug(" ");
4143 i++;
4144 if ((i % 6) == 0 || cpu_type_defs[i].name == NULL)
4145 debug("\n");
4146 }
4147 }
4148
4149
4150 /* NOTE: _OLD_ family init. TODO: remove all this */
4151
4152 CPU_OLD_FAMILY_INIT(mips,"MIPS")
4153
4154
4155 #endif /* ENABLE_MIPS */

  ViewVC Help
Powered by ViewVC 1.1.26