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

Annotation of /trunk/src/cpu_mips.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 6 - (hide annotations)
Mon Oct 8 16:18:11 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 119531 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.772 2005/06/04 12:02:16 debug Exp $
20050428	Disabling the "-fmove-all-movables" option in the configure
		script, because it causes the compile to fail on OpenBSD/sgi.
20050502	Minor updates.
20050503	Removing the WRT54G mode (it was bogus anyway), and adding a
		comment about Windows NT for MIPS in doc/experiments.html.
		Minor updates to the x86 instruction decoding.
20050504	Adding some more x86 instructions.
		Adding support for reading files from ISO9660 CDROMs (including
		gzipped files). It's an ugly hack, but it seems to work.
		Various other minor updates (dev_vga.c, pc_bios.c etc).
20050505	Some more x86-related updates.
		Beginning (what I hope will be) a major code cleanup phase.
		"bootris" (an x86 bootsector) runs :-)
20050506	Adding some more x86 instructions.
20050507	tmpnam => mkstemp.
		Working on a hack to allow VGA charcells to be shown even when
		not running with X11.
		Adding more x86 instructions.
20050508	x86 32-bit SIB addressing fix, and more instructions.
20050509	Adding more x86 instructions.
20050510	Minor documentation updates, and other updates (x86 stuff etc.)
20050511	More x86-related updates.
20050513	Various updates, mostly x86-related. (Trying to fix flag 
		calculation, factoring out the ugly shift/rotate code, and
		some other things.)
20050514	Adding support for loading some old i386 a.out executables.
		Finally beginning the cleanup of machine/PROM/bios dependant
		info.
		Some minor documentation updates.
		Trying to clean up ARCBIOS stuff a little.
20050515	Trying to make it possible to actually use more than one disk
		type per machine (floppy, ide, scsi).
		Trying to clean up the kbd vs PROM console stuff. (For PC and
		ARC emulation modes, mostly.)
		Beginning to add an 8259 interrupt controller, and connecting
		it to the x86 emulation.
20050516	The first x86 interrupts seem to work (keyboard stuff).
		Adding a 8253/8254 programmable interval timer skeleton.
		FreeDOS now reaches a command prompt and can be interacted
		with.
20050517	After some bugfixes, MS-DOS also (sometimes) reaches a
		command prompt now.
		Trying to fix the pckbc to work with MS-DOS' keyb.com, but no
		success yet.
20050518	Adding a simple 32-bit x86 MMU skeleton.
20050519	Some more work on the x86 stuff. (Beginning the work on paging,
		and various other fixes).
20050520	More updates. Working on dev_vga (4-bit graphics modes), adding
		40 columns support to the PC bios emulation.
		Trying to add support for resizing windows when switching
		between graphics modes.
20050521	Many more x86-related updates.
20050522	Correcting the initial stack pointer's sign-extension for
		ARCBIOS emulation (thanks to Alec Voropay for noticing the
		error).
		Continuing on the cleanup (ARCBIOS etc).
		dev_vga updates.
20050523	More x86 updates: trying to add some support for protected mode
		interrupts (via gate descriptors) and many other fixes.
		More ARCBIOS cleanup.
		Adding a device flag which indicates that reads cause no
		side-effects. (Useful for the "dump" command in the debugger,
		and other things.)
		Adding support for directly starting up x86 ELFs, skipping the
		bootloader stage. (Most ELFs, however, are not suitable for
		this.)
20050524	Adding simple 32-bit x86 TSS task switching, but no privilege
		level support yet.
		More work on dev_vga. A small "Copper bars" demo works. :-)
		Adding support for Trap Flag (single-step exceptions), at least
		in real mode, and various other x86-related fixes.
20050525	Adding a new disk image prefix (gH;S;) which can be used to
		override the default nr of heads and sectors per track.
20050527	Various bug fixes, more work on the x86 mode (stack change on
		interrupts between different priv.levels), and some minor
		documentation updates.
20050528	Various fixes (x86 stuff).
20050529	More x86 fixes. An OpenBSD/i386 bootfloppy reaches userland
		and can be interacted with (although there are problems with
		key repetition). NetBSD/i386 triggers a serious CISC-related
		problem: instruction fetches across page boundaries, where
		the later part isn't actually part of the instruction.
20050530	Various minor updates. (Documentation updates, etc.)
20050531	Adding some experimental code (experiments/new_test_*) which
		could be useful for dynamic (but not binary) translation in
		the future.
20050602	Adding a dummy ARM skeleton.
		Fixing the pckbc key repetition problem (by adding release
		scancodes for all keypresses).
20050603	Minor updates for the next release.
20050604	Release testing. Minor updates.

==============  RELEASE 0.3.3  ==============

20050604	There'll probably be a 0.3.3.1 release soon, with some very
		very tiny updates.


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

  ViewVC Help
Powered by ViewVC 1.1.26