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

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


1 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 12 * $Id: cpu_mips.c,v 1.61 2005/08/07 19:12:12 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     #include "cpu_mips16.c"
99    
100    
101     /*
102     * regname():
103     *
104     * Convert a register number into either 'r0', 'r31' etc, or a symbolic
105     * name, depending on machine->show_symbolic_register_names.
106     *
107     * NOTE: _NOT_ reentrant.
108     */
109     static char *regname(struct machine *machine, int r)
110     {
111     static char ch[4];
112     ch[3] = ch[2] = '\0';
113    
114     if (r<0 || r>=32)
115 dpavlin 10 strlcpy(ch, "xx", sizeof(ch));
116 dpavlin 2 else if (machine->show_symbolic_register_names)
117 dpavlin 10 strlcpy(ch, regnames[r], sizeof(ch));
118 dpavlin 2 else
119 dpavlin 10 snprintf(ch, sizeof(ch), "r%i", r);
120 dpavlin 2
121     return ch;
122     }
123    
124    
125     /*
126     * mips_cpu_new():
127     *
128     * Create a new MIPS cpu object.
129 dpavlin 10 *
130     * Returns 1 on success, 0 if there was no valid MIPS processor with
131     * a matching name.
132 dpavlin 2 */
133 dpavlin 10 int mips_cpu_new(struct cpu *cpu, struct memory *mem, struct machine *machine,
134 dpavlin 2 int cpu_id, char *cpu_type_name)
135     {
136     int i, found, j, tags_size, n_cache_lines, size_per_cache_line;
137     struct mips_cpu_type_def cpu_type_defs[] = MIPS_CPU_TYPE_DEFS;
138     int64_t secondary_cache_size;
139     int x, linesize;
140    
141     /* Scan the cpu_type_defs list for this cpu type: */
142     i = 0;
143     found = -1;
144     while (i >= 0 && cpu_type_defs[i].name != NULL) {
145     if (strcasecmp(cpu_type_defs[i].name, cpu_type_name) == 0) {
146     found = i;
147     break;
148     }
149     i++;
150     }
151    
152     if (found == -1)
153 dpavlin 10 return 0;
154 dpavlin 2
155     cpu->memory_rw = mips_memory_rw;
156     cpu->cd.mips.cpu_type = cpu_type_defs[found];
157     cpu->name = cpu->cd.mips.cpu_type.name;
158     cpu->byte_order = EMUL_LITTLE_ENDIAN;
159 dpavlin 12 cpu->cd.mips.gpr[MIPS_GPR_SP] = INITIAL_STACK_POINTER;
160     cpu->update_translation_table = mips_update_translation_table;
161     cpu->invalidate_translation_caches_paddr =
162     mips_invalidate_translation_caches_paddr;
163 dpavlin 2
164 dpavlin 12 if (cpu->cd.mips.cpu_type.isa_level <= 2 ||
165     cpu->cd.mips.cpu_type.isa_level == 32)
166     cpu->is_32bit = 1;
167    
168 dpavlin 2 if (cpu_id == 0)
169     debug("%s", cpu->cd.mips.cpu_type.name);
170    
171     /*
172     * CACHES:
173     *
174     * 1) Use DEFAULT_PCACHE_SIZE and DEFAULT_PCACHE_LINESIZE etc.
175     * 2) If there are specific values defined for this type of cpu,
176     * in its cpu_type substruct, then let's use those.
177     * 3) Values in the emul struct override both of the above.
178     *
179     * Once we've decided which values to use, they are stored in
180     * the emul struct so they can be used from src/machine.c etc.
181     */
182    
183     x = DEFAULT_PCACHE_SIZE;
184 dpavlin 12 if (cpu->cd.mips.cpu_type.pdcache)
185     x = cpu->cd.mips.cpu_type.pdcache;
186 dpavlin 2 if (machine->cache_pdcache == 0)
187     machine->cache_pdcache = x;
188    
189     x = DEFAULT_PCACHE_SIZE;
190 dpavlin 12 if (cpu->cd.mips.cpu_type.picache)
191     x = cpu->cd.mips.cpu_type.picache;
192 dpavlin 2 if (machine->cache_picache == 0)
193     machine->cache_picache = x;
194    
195     if (machine->cache_secondary == 0)
196 dpavlin 12 machine->cache_secondary = cpu->cd.mips.cpu_type.scache;
197 dpavlin 2
198     linesize = DEFAULT_PCACHE_LINESIZE;
199 dpavlin 12 if (cpu->cd.mips.cpu_type.pdlinesize)
200     linesize = cpu->cd.mips.cpu_type.pdlinesize;
201 dpavlin 2 if (machine->cache_pdcache_linesize == 0)
202     machine->cache_pdcache_linesize = linesize;
203    
204     linesize = DEFAULT_PCACHE_LINESIZE;
205 dpavlin 12 if (cpu->cd.mips.cpu_type.pilinesize)
206     linesize = cpu->cd.mips.cpu_type.pilinesize;
207 dpavlin 2 if (machine->cache_picache_linesize == 0)
208     machine->cache_picache_linesize = linesize;
209    
210     linesize = 0;
211 dpavlin 12 if (cpu->cd.mips.cpu_type.slinesize)
212     linesize = cpu->cd.mips.cpu_type.slinesize;
213 dpavlin 2 if (machine->cache_secondary_linesize == 0)
214     machine->cache_secondary_linesize = linesize;
215    
216    
217     /*
218     * Primary Data and Instruction caches:
219     */
220     for (i=CACHE_DATA; i<=CACHE_INSTRUCTION; i++) {
221     switch (i) {
222     case CACHE_DATA:
223     x = 1 << machine->cache_pdcache;
224     linesize = 1 << machine->cache_pdcache_linesize;
225     break;
226     case CACHE_INSTRUCTION:
227     x = 1 << machine->cache_picache;
228     linesize = 1 << machine->cache_picache_linesize;
229     break;
230     }
231    
232     /* Primary cache size and linesize: */
233     cpu->cd.mips.cache_size[i] = x;
234     cpu->cd.mips.cache_linesize[i] = linesize;
235    
236     switch (cpu->cd.mips.cpu_type.rev) {
237     case MIPS_R2000:
238     case MIPS_R3000:
239     size_per_cache_line = sizeof(struct r3000_cache_line);
240     break;
241     default:
242     size_per_cache_line = sizeof(struct r4000_cache_line);
243     }
244    
245     cpu->cd.mips.cache_mask[i] = cpu->cd.mips.cache_size[i] - 1;
246     cpu->cd.mips.cache_miss_penalty[i] = 10; /* TODO ? */
247    
248     cpu->cd.mips.cache[i] = malloc(cpu->cd.mips.cache_size[i]);
249     if (cpu->cd.mips.cache[i] == NULL) {
250     fprintf(stderr, "out of memory\n");
251     }
252    
253     n_cache_lines = cpu->cd.mips.cache_size[i] /
254     cpu->cd.mips.cache_linesize[i];
255     tags_size = n_cache_lines * size_per_cache_line;
256    
257     cpu->cd.mips.cache_tags[i] = malloc(tags_size);
258     if (cpu->cd.mips.cache_tags[i] == NULL) {
259     fprintf(stderr, "out of memory\n");
260     }
261    
262     /* Initialize the cache tags: */
263     switch (cpu->cd.mips.cpu_type.rev) {
264     case MIPS_R2000:
265     case MIPS_R3000:
266     for (j=0; j<n_cache_lines; j++) {
267     struct r3000_cache_line *rp;
268     rp = (struct r3000_cache_line *)
269     cpu->cd.mips.cache_tags[i];
270     rp[j].tag_paddr = 0;
271     rp[j].tag_valid = 0;
272     }
273     break;
274     default:
275     ;
276     }
277    
278     /* Set cache_last_paddr to something "impossible": */
279     cpu->cd.mips.cache_last_paddr[i] = IMPOSSIBLE_PADDR;
280     }
281    
282     /*
283     * Secondary cache:
284     */
285     secondary_cache_size = 0;
286     if (machine->cache_secondary)
287     secondary_cache_size = 1 << machine->cache_secondary;
288     /* TODO: linesize... */
289    
290     if (cpu_id == 0) {
291     debug(" (I+D = %i+%i KB",
292     (int)(cpu->cd.mips.cache_size[CACHE_INSTRUCTION] / 1024),
293     (int)(cpu->cd.mips.cache_size[CACHE_DATA] / 1024));
294    
295     if (secondary_cache_size != 0) {
296     debug(", L2 = ");
297     if (secondary_cache_size >= 1048576)
298     debug("%i MB", (int)
299     (secondary_cache_size / 1048576));
300     else
301     debug("%i KB", (int)
302     (secondary_cache_size / 1024));
303     }
304    
305     debug(")");
306     }
307    
308     /* System coprocessor (0), and FPU (1): */
309     cpu->cd.mips.coproc[0] = mips_coproc_new(cpu, 0);
310     cpu->cd.mips.coproc[1] = mips_coproc_new(cpu, 1);
311    
312     /*
313     * Initialize the cpu->cd.mips.pc_last_* cache (a 1-entry cache of the
314     * last program counter value). For pc_last_virtual_page, any
315     * "impossible" value will do. The pc should never ever get this
316     * value. (The other pc_last* variables do not need initialization,
317     * as they are not used before pc_last_virtual_page.)
318     */
319     cpu->cd.mips.pc_last_virtual_page = PC_LAST_PAGE_IMPOSSIBLE_VALUE;
320    
321     switch (cpu->cd.mips.cpu_type.mmu_model) {
322     case MMU3K:
323     cpu->translate_address = translate_address_mmu3k;
324     break;
325     case MMU8K:
326     cpu->translate_address = translate_address_mmu8k;
327     break;
328     case MMU10K:
329     cpu->translate_address = translate_address_mmu10k;
330     break;
331     default:
332     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100)
333     cpu->translate_address = translate_address_mmu4100;
334     else
335     cpu->translate_address = translate_address_generic;
336     }
337    
338 dpavlin 12 /* Testing: */
339     cpu->cd.mips.host_load = zeroed_alloc(1048576 *
340     sizeof(unsigned char *));
341     cpu->cd.mips.host_store = zeroed_alloc(1048576 *
342     sizeof(unsigned char *));
343     cpu->cd.mips.host_load_orig = cpu->cd.mips.host_load;
344     cpu->cd.mips.host_store_orig = cpu->cd.mips.host_store;
345    
346 dpavlin 10 return 1;
347 dpavlin 2 }
348    
349    
350     /*
351     * mips_cpu_show_full_statistics():
352     *
353     * Show detailed statistics on opcode usage on each cpu.
354     */
355     void mips_cpu_show_full_statistics(struct machine *m)
356     {
357     int i, s1, s2, iadd = 4;
358    
359     if (m->bintrans_enable)
360     fatal("NOTE: Dynamic binary translation is used; this list"
361     " of opcode usage\n only includes instructions that"
362     " were interpreted manually!\n");
363    
364     for (i=0; i<m->ncpus; i++) {
365     fatal("cpu%i opcode statistics:\n", i);
366     debug_indentation(iadd);
367    
368     for (s1=0; s1<N_HI6; s1++) {
369     if (m->cpus[i]->cd.mips.stats_opcode[s1] > 0)
370     fatal("opcode %02x (%7s): %li\n", s1,
371     hi6_names[s1],
372     m->cpus[i]->cd.mips.stats_opcode[s1]);
373    
374     debug_indentation(iadd);
375     if (s1 == HI6_SPECIAL)
376     for (s2=0; s2<N_SPECIAL; s2++)
377     if (m->cpus[i]->cd.mips.stats__special[
378     s2] > 0)
379     fatal("special %02x (%7s): "
380     "%li\n", s2, special_names[
381     s2], m->cpus[i]->cd.mips.
382     stats__special[s2]);
383     if (s1 == HI6_REGIMM)
384     for (s2=0; s2<N_REGIMM; s2++)
385     if (m->cpus[i]->cd.mips.stats__regimm[
386     s2] > 0)
387     fatal("regimm %02x (%7s): "
388     "%li\n", s2, regimm_names[
389     s2], m->cpus[i]->cd.mips.
390     stats__regimm[s2]);
391     if (s1 == HI6_SPECIAL2)
392     for (s2=0; s2<N_SPECIAL; s2++)
393     if (m->cpus[i]->cd.mips.stats__special2
394     [s2] > 0)
395     fatal("special2 %02x (%7s): "
396     "%li\n", s2,
397     special2_names[s2], m->
398     cpus[i]->cd.mips.
399     stats__special2[s2]);
400     debug_indentation(-iadd);
401     }
402    
403     debug_indentation(-iadd);
404     }
405     }
406    
407    
408     /*
409     * mips_cpu_tlbdump():
410     *
411     * Called from the debugger to dump the TLB in a readable format.
412     * x is the cpu number to dump, or -1 to dump all CPUs.
413     *
414     * If rawflag is nonzero, then the TLB contents isn't formated nicely,
415     * just dumped.
416     */
417     void mips_cpu_tlbdump(struct machine *m, int x, int rawflag)
418     {
419     int i, j;
420    
421     /* Nicely formatted output: */
422     if (!rawflag) {
423     for (i=0; i<m->ncpus; i++) {
424     int pageshift = 12;
425    
426     if (x >= 0 && i != x)
427     continue;
428    
429     if (m->cpus[i]->cd.mips.cpu_type.rev == MIPS_R4100)
430     pageshift = 10;
431    
432     /* Print index, random, and wired: */
433     printf("cpu%i: (", i);
434     switch (m->cpus[i]->cd.mips.cpu_type.isa_level) {
435     case 1:
436     case 2:
437     printf("index=0x%x random=0x%x",
438     (int) ((m->cpus[i]->cd.mips.coproc[0]->
439     reg[COP0_INDEX] & R2K3K_INDEX_MASK)
440     >> R2K3K_INDEX_SHIFT),
441     (int) ((m->cpus[i]->cd.mips.coproc[0]->
442     reg[COP0_RANDOM] & R2K3K_RANDOM_MASK)
443     >> R2K3K_RANDOM_SHIFT));
444     break;
445     default:
446     printf("index=0x%x random=0x%x",
447     (int) (m->cpus[i]->cd.mips.coproc[0]->
448     reg[COP0_INDEX] & INDEX_MASK),
449     (int) (m->cpus[i]->cd.mips.coproc[0]->
450     reg[COP0_RANDOM] & RANDOM_MASK));
451     printf(" wired=0x%llx", (long long)
452     m->cpus[i]->cd.mips.coproc[0]->
453     reg[COP0_WIRED]);
454     }
455    
456     printf(")\n");
457    
458     for (j=0; j<m->cpus[i]->cd.mips.cpu_type.
459     nr_of_tlb_entries; j++) {
460     uint64_t hi,lo0,lo1,mask;
461     hi = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi;
462     lo0 = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0;
463     lo1 = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1;
464     mask = m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask;
465    
466     printf("%3i: ", j);
467     switch (m->cpus[i]->cd.mips.cpu_type.mmu_model) {
468     case MMU3K:
469     if (!(lo0 & R2K3K_ENTRYLO_V)) {
470     printf("(invalid)\n");
471     continue;
472     }
473     printf("vaddr=0x%08x ",
474     (int) (hi&R2K3K_ENTRYHI_VPN_MASK));
475     if (lo0 & R2K3K_ENTRYLO_G)
476     printf("(global), ");
477     else
478     printf("(asid %02x),",
479     (int) ((hi & R2K3K_ENTRYHI_ASID_MASK)
480     >> R2K3K_ENTRYHI_ASID_SHIFT));
481     printf(" paddr=0x%08x ",
482     (int) (lo0&R2K3K_ENTRYLO_PFN_MASK));
483     if (lo0 & R2K3K_ENTRYLO_N)
484     printf("N");
485     if (lo0 & R2K3K_ENTRYLO_D)
486     printf("D");
487     printf("\n");
488     break;
489     default:
490 dpavlin 12 switch (m->cpus[i]->cd.mips.cpu_type.mmu_model) {
491     case MMU10K:
492 dpavlin 2 printf("vaddr=0x%1x..%011llx ",
493     (int) (hi >> 60),
494     (long long) (hi&ENTRYHI_VPN2_MASK_R10K));
495 dpavlin 12 break;
496     case MMU32:
497     printf("vaddr=0x%08x ", (int)(hi&ENTRYHI_VPN2_MASK));
498     break;
499     default:/* R4000 etc. */
500 dpavlin 2 printf("vaddr=0x%1x..%010llx ",
501     (int) (hi >> 60),
502     (long long) (hi&ENTRYHI_VPN2_MASK));
503 dpavlin 12 }
504 dpavlin 2 if (hi & TLB_G)
505     printf("(global): ");
506     else
507     printf("(asid %02x):",
508     (int) (hi & ENTRYHI_ASID));
509    
510     /* TODO: Coherency bits */
511    
512     if (!(lo0 & ENTRYLO_V))
513     printf(" p0=(invalid) ");
514     else
515     printf(" p0=0x%09llx ", (long long)
516     (((lo0&ENTRYLO_PFN_MASK) >> ENTRYLO_PFN_SHIFT) << pageshift));
517     printf(lo0 & ENTRYLO_D? "D" : " ");
518    
519     if (!(lo1 & ENTRYLO_V))
520     printf(" p1=(invalid) ");
521     else
522     printf(" p1=0x%09llx ", (long long)
523     (((lo1&ENTRYLO_PFN_MASK) >> ENTRYLO_PFN_SHIFT) << pageshift));
524     printf(lo1 & ENTRYLO_D? "D" : " ");
525     mask |= (1 << (pageshift+1)) - 1;
526     switch (mask) {
527     case 0x7ff: printf(" (1KB)"); break;
528     case 0x1fff: printf(" (4KB)"); break;
529     case 0x7fff: printf(" (16KB)"); break;
530     case 0x1ffff: printf(" (64KB)"); break;
531     case 0x7ffff: printf(" (256KB)"); break;
532     case 0x1fffff: printf(" (1MB)"); break;
533     case 0x7fffff: printf(" (4MB)"); break;
534     case 0x1ffffff: printf(" (16MB)"); break;
535     case 0x7ffffff: printf(" (64MB)"); break;
536     default:
537     printf(" (mask=%08x?)", (int)mask);
538     }
539     printf("\n");
540     }
541     }
542     }
543    
544     return;
545     }
546    
547     /* Raw output: */
548     for (i=0; i<m->ncpus; i++) {
549     if (x >= 0 && i != x)
550     continue;
551    
552     /* Print index, random, and wired: */
553     printf("cpu%i: (", i);
554    
555 dpavlin 12 if (m->cpus[i]->is_32bit)
556 dpavlin 2 printf("index=0x%08x random=0x%08x",
557     (int)m->cpus[i]->cd.mips.coproc[0]->reg[COP0_INDEX],
558     (int)m->cpus[i]->cd.mips.coproc[0]->reg[COP0_RANDOM]);
559     else
560     printf("index=0x%016llx random=0x%016llx", (long long)
561     m->cpus[i]->cd.mips.coproc[0]->reg[COP0_INDEX],
562     (long long)m->cpus[i]->cd.mips.coproc[0]->reg
563     [COP0_RANDOM]);
564    
565     if (m->cpus[i]->cd.mips.cpu_type.isa_level >= 3)
566     printf(" wired=0x%llx", (long long)
567     m->cpus[i]->cd.mips.coproc[0]->reg[COP0_WIRED]);
568    
569     printf(")\n");
570    
571     for (j=0; j<m->cpus[i]->cd.mips.cpu_type.nr_of_tlb_entries; j++) {
572     if (m->cpus[i]->cd.mips.cpu_type.mmu_model == MMU3K)
573     printf("%3i: hi=0x%08x lo=0x%08x\n",
574     j,
575     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
576     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0);
577 dpavlin 12 else if (m->cpus[i]->is_32bit)
578 dpavlin 2 printf("%3i: hi=0x%08x mask=0x%08x "
579     "lo0=0x%08x lo1=0x%08x\n", j,
580     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
581     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask,
582     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0,
583     (int)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1);
584     else
585     printf("%3i: hi=0x%016llx mask=0x%016llx "
586     "lo0=0x%016llx lo1=0x%016llx\n", j,
587     (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].hi,
588     (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].mask,
589     (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo0,
590     (long long)m->cpus[i]->cd.mips.coproc[0]->tlbs[j].lo1);
591     }
592     }
593     }
594    
595    
596     /*
597     * mips_cpu_register_match():
598     */
599     void mips_cpu_register_match(struct machine *m, char *name,
600     int writeflag, uint64_t *valuep, int *match_register)
601     {
602     int cpunr = 0;
603    
604     /* CPU number: */
605    
606     /* TODO */
607    
608     /* Register name: */
609     if (strcasecmp(name, "pc") == 0) {
610     if (writeflag) {
611     m->cpus[cpunr]->pc = *valuep;
612     if (m->cpus[cpunr]->cd.mips.delay_slot) {
613     printf("NOTE: Clearing the delay slot"
614     " flag! (It was set before.)\n");
615     m->cpus[cpunr]->cd.mips.delay_slot = 0;
616     }
617     if (m->cpus[cpunr]->cd.mips.nullify_next) {
618     printf("NOTE: Clearing the nullify-ne"
619     "xt flag! (It was set before.)\n");
620     m->cpus[cpunr]->cd.mips.nullify_next = 0;
621     }
622     } else
623     *valuep = m->cpus[cpunr]->pc;
624     *match_register = 1;
625     } else if (strcasecmp(name, "hi") == 0) {
626     if (writeflag)
627     m->cpus[cpunr]->cd.mips.hi = *valuep;
628     else
629     *valuep = m->cpus[cpunr]->cd.mips.hi;
630     *match_register = 1;
631     } else if (strcasecmp(name, "lo") == 0) {
632     if (writeflag)
633     m->cpus[cpunr]->cd.mips.lo = *valuep;
634     else
635     *valuep = m->cpus[cpunr]->cd.mips.lo;
636     *match_register = 1;
637     } else if (name[0] == 'r' && isdigit((int)name[1])) {
638     int nr = atoi(name + 1);
639     if (nr >= 0 && nr < N_MIPS_GPRS) {
640     if (writeflag) {
641     if (nr != 0)
642     m->cpus[cpunr]->cd.mips.gpr[nr] = *valuep;
643     else
644     printf("WARNING: Attempt to modify r0.\n");
645     } else
646     *valuep = m->cpus[cpunr]->cd.mips.gpr[nr];
647     *match_register = 1;
648     }
649     } else {
650     /* Check for a symbolic name such as "t6" or "at": */
651     int nr;
652     for (nr=0; nr<N_MIPS_GPRS; nr++)
653     if (strcmp(name, regnames[nr]) == 0) {
654     if (writeflag) {
655     if (nr != 0)
656     m->cpus[cpunr]->cd.mips.gpr[nr] = *valuep;
657     else
658     printf("WARNING: Attempt to modify r0.\n");
659     } else
660     *valuep = m->cpus[cpunr]->cd.mips.gpr[nr];
661     *match_register = 1;
662     }
663     }
664    
665     if (!(*match_register)) {
666     /* Check for a symbolic coproc0 name: */
667     int nr;
668     for (nr=0; nr<32; nr++)
669     if (strcmp(name, cop0_names[nr]) == 0) {
670     if (writeflag) {
671     coproc_register_write(m->cpus[cpunr],
672     m->cpus[cpunr]->cd.mips.coproc[0], nr,
673 dpavlin 10 valuep, 1, 0);
674 dpavlin 2 } else {
675     /* TODO: Use coproc_register_read instead? */
676     *valuep = m->cpus[cpunr]->cd.mips.coproc[0]->reg[nr];
677     }
678     *match_register = 1;
679     }
680     }
681    
682     /* TODO: Coprocessor 1,2,3 registers. */
683     }
684    
685    
686     /*
687     * cpu_flags():
688     *
689     * Returns a pointer to a string containing "(d)" "(j)" "(dj)" or "",
690     * depending on the cpu's current delay_slot and last_was_jumptoself
691     * flags.
692     */
693     static const char *cpu_flags(struct cpu *cpu)
694     {
695     if (cpu->cd.mips.delay_slot) {
696     if (cpu->cd.mips.last_was_jumptoself)
697     return " (dj)";
698     else
699     return " (d)";
700     } else {
701     if (cpu->cd.mips.last_was_jumptoself)
702     return " (j)";
703     else
704     return "";
705     }
706     }
707    
708    
709     /*
710     * mips_cpu_disassemble_instr():
711     *
712     * Convert an instruction word into human readable format, for instruction
713     * tracing.
714     *
715     * If running is 1, cpu->pc should be the address of the instruction.
716     *
717     * If running is 0, things that depend on the runtime environment (eg.
718     * register contents) will not be shown, and addr will be used instead of
719     * cpu->pc for relative addresses.
720     *
721     * NOTE 2: coprocessor instructions are not decoded nicely yet (TODO)
722     */
723     int mips_cpu_disassemble_instr(struct cpu *cpu, unsigned char *originstr,
724     int running, uint64_t dumpaddr, int bintrans)
725     {
726     int hi6, special6, regimm5;
727     int rt, rd, rs, sa, imm, copz, cache_op, which_cache, showtag;
728     uint64_t addr, offset;
729     uint32_t instrword;
730     unsigned char instr[4];
731     char *symbol;
732    
733     if (running)
734     dumpaddr = cpu->pc;
735    
736 dpavlin 4 if ((dumpaddr & 3) != 0)
737     printf("WARNING: Unaligned address!\n");
738    
739 dpavlin 2 symbol = get_symbol_name(&cpu->machine->symbol_context,
740     dumpaddr, &offset);
741     if (symbol != NULL && offset==0)
742     debug("<%s>\n", symbol);
743    
744     if (cpu->machine->ncpus > 1 && running)
745     debug("cpu%i: ", cpu->cpu_id);
746    
747 dpavlin 12 if (cpu->is_32bit)
748 dpavlin 2 debug("%08x", (int)dumpaddr);
749     else
750     debug("%016llx", (long long)dumpaddr);
751    
752     *((uint32_t *)&instr[0]) = *((uint32_t *)&originstr[0]);
753    
754     /*
755     * The rest of the code is written for little endian,
756     * so swap if necessary:
757     */
758     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
759     int tmp = instr[0]; instr[0] = instr[3];
760     instr[3] = tmp;
761     tmp = instr[1]; instr[1] = instr[2];
762     instr[2] = tmp;
763     }
764    
765     debug(": %02x%02x%02x%02x",
766     instr[3], instr[2], instr[1], instr[0]);
767    
768     if (running)
769     debug("%s", cpu_flags(cpu));
770    
771     debug("\t");
772    
773     if (bintrans && running) {
774     debug("(bintrans)");
775     goto disasm_ret;
776     }
777    
778     /*
779     * Decode the instruction:
780     */
781    
782     if (cpu->cd.mips.nullify_next && running) {
783     debug("(nullified)");
784     goto disasm_ret;
785     }
786    
787     hi6 = (instr[3] >> 2) & 0x3f;
788    
789     switch (hi6) {
790     case HI6_SPECIAL:
791     special6 = instr[0] & 0x3f;
792     switch (special6) {
793     case SPECIAL_SLL:
794     case SPECIAL_SRL:
795     case SPECIAL_SRA:
796     case SPECIAL_DSLL:
797     case SPECIAL_DSRL:
798     case SPECIAL_DSRA:
799     case SPECIAL_DSLL32:
800     case SPECIAL_DSRL32:
801     case SPECIAL_DSRA32:
802     rt = instr[2] & 31;
803     rd = (instr[1] >> 3) & 31;
804     sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
805    
806     if (rd == 0 && special6 == SPECIAL_SLL) {
807     if (sa == 0)
808     debug("nop");
809     else if (sa == 1)
810     debug("ssnop");
811     else
812     debug("nop (weird, sa=%i)", sa);
813     goto disasm_ret;
814     } else
815     debug("%s\t%s,",
816     special_names[special6],
817     regname(cpu->machine, rd));
818     debug("%s,%i", regname(cpu->machine, rt), sa);
819     break;
820     case SPECIAL_DSRLV:
821     case SPECIAL_DSRAV:
822     case SPECIAL_DSLLV:
823     case SPECIAL_SLLV:
824     case SPECIAL_SRAV:
825     case SPECIAL_SRLV:
826     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
827     rt = instr[2] & 31;
828     rd = (instr[1] >> 3) & 31;
829     debug("%s\t%s",
830     special_names[special6], regname(cpu->machine, rd));
831     debug(",%s", regname(cpu->machine, rt));
832     debug(",%s", regname(cpu->machine, rs));
833     break;
834     case SPECIAL_JR:
835     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
836     symbol = get_symbol_name(&cpu->machine->symbol_context,
837     cpu->cd.mips.gpr[rs], &offset);
838     debug("jr\t%s", regname(cpu->machine, rs));
839     if (running && symbol != NULL)
840     debug("\t<%s>", symbol);
841     break;
842     case SPECIAL_JALR:
843     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
844     rd = (instr[1] >> 3) & 31;
845     symbol = get_symbol_name(&cpu->machine->symbol_context,
846     cpu->cd.mips.gpr[rs], &offset);
847     debug("jalr\t%s", regname(cpu->machine, rd));
848     debug(",%s", regname(cpu->machine, rs));
849     if (running && symbol != NULL)
850     debug("\t<%s>", symbol);
851     break;
852     case SPECIAL_MFHI:
853     case SPECIAL_MFLO:
854     rd = (instr[1] >> 3) & 31;
855     debug("%s\t%s", special_names[special6],
856     regname(cpu->machine, rd));
857     break;
858     case SPECIAL_MTLO:
859     case SPECIAL_MTHI:
860     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
861     debug("%s\t%s", special_names[special6],
862     regname(cpu->machine, rs));
863     break;
864     case SPECIAL_ADD:
865     case SPECIAL_ADDU:
866     case SPECIAL_SUB:
867     case SPECIAL_SUBU:
868     case SPECIAL_AND:
869     case SPECIAL_OR:
870     case SPECIAL_XOR:
871     case SPECIAL_NOR:
872     case SPECIAL_SLT:
873     case SPECIAL_SLTU:
874     case SPECIAL_DADD:
875     case SPECIAL_DADDU:
876     case SPECIAL_DSUB:
877     case SPECIAL_DSUBU:
878     case SPECIAL_MOVZ:
879     case SPECIAL_MOVN:
880     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
881     rt = instr[2] & 31;
882     rd = (instr[1] >> 3) & 31;
883     if ((special6 == SPECIAL_ADDU ||
884     special6 == SPECIAL_DADDU ||
885     special6 == SPECIAL_SUBU ||
886     special6 == SPECIAL_DSUBU) && rt == 0) {
887     /* Special case 1: addu/daddu/subu/dsubu with
888     rt = the zero register ==> move */
889     debug("move\t%s", regname(cpu->machine, rd));
890     debug(",%s", regname(cpu->machine, rs));
891     } else if ((special6 == SPECIAL_ADDU ||
892     special6 == SPECIAL_DADDU) && rs == 0) {
893     /* Special case 2: addu/daddu with
894     rs = the zero register ==> move */
895     debug("move\t%s", regname(cpu->machine, rd));
896     debug(",%s", regname(cpu->machine, rt));
897     } else {
898     debug("%s\t%s", special_names[special6],
899     regname(cpu->machine, rd));
900     debug(",%s", regname(cpu->machine, rs));
901     debug(",%s", regname(cpu->machine, rt));
902     }
903     break;
904     case SPECIAL_MULT:
905     case SPECIAL_MULTU:
906     case SPECIAL_DMULT:
907     case SPECIAL_DMULTU:
908     case SPECIAL_DIV:
909     case SPECIAL_DIVU:
910     case SPECIAL_DDIV:
911     case SPECIAL_DDIVU:
912     case SPECIAL_TGE:
913     case SPECIAL_TGEU:
914     case SPECIAL_TLT:
915     case SPECIAL_TLTU:
916     case SPECIAL_TEQ:
917     case SPECIAL_TNE:
918     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
919     rt = instr[2] & 31;
920     rd = (instr[1] >> 3) & 31;
921     if (special6 == SPECIAL_MULT) {
922     if (rd != 0) {
923     debug("mult_xx\t%s",
924     regname(cpu->machine, rd));
925     debug(",%s", regname(cpu->machine, rs));
926     debug(",%s", regname(cpu->machine, rt));
927     goto disasm_ret;
928     }
929     }
930     debug("%s\t%s", special_names[special6],
931     regname(cpu->machine, rs));
932     debug(",%s", regname(cpu->machine, rt));
933     break;
934     case SPECIAL_SYNC:
935     imm = ((instr[1] & 7) << 2) + (instr[0] >> 6);
936     debug("sync\t0x%02x", imm);
937     break;
938     case SPECIAL_SYSCALL:
939     imm = (((instr[3] << 24) + (instr[2] << 16) +
940     (instr[1] << 8) + instr[0]) >> 6) & 0xfffff;
941     if (imm != 0)
942     debug("syscall\t0x%05x", imm);
943     else
944     debug("syscall");
945     break;
946     case SPECIAL_BREAK:
947 dpavlin 12 imm = (((instr[3] << 24) + (instr[2] << 16) +
948     (instr[1] << 8) + instr[0]) >> 6) & 0xfffff;
949     if (imm != 0)
950     debug("break\t0x%05x", imm);
951     else
952     debug("break");
953 dpavlin 2 break;
954     case SPECIAL_MFSA:
955     rd = (instr[1] >> 3) & 31;
956     debug("mfsa\t%s", regname(cpu->machine, rd));
957     break;
958     case SPECIAL_MTSA:
959     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
960     debug("mtsa\t%s", regname(cpu->machine, rs));
961     break;
962     default:
963     debug("unimplemented special6 = 0x%02x", special6);
964     }
965     break;
966     case HI6_BEQ:
967     case HI6_BEQL:
968     case HI6_BNE:
969     case HI6_BNEL:
970     case HI6_BGTZ:
971     case HI6_BGTZL:
972     case HI6_BLEZ:
973     case HI6_BLEZL:
974     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
975     rt = instr[2] & 31;
976     imm = (instr[1] << 8) + instr[0];
977     if (imm >= 32768)
978     imm -= 65536;
979     addr = (dumpaddr + 4) + (imm << 2);
980     debug("%s\t", hi6_names[hi6]);
981    
982     switch (hi6) {
983     case HI6_BEQ:
984     case HI6_BEQL:
985     case HI6_BNE:
986     case HI6_BNEL:
987     debug("%s,", regname(cpu->machine, rt));
988     }
989    
990     debug("%s,", regname(cpu->machine, rs));
991    
992 dpavlin 12 if (cpu->is_32bit)
993 dpavlin 2 debug("0x%08x", (int)addr);
994     else
995     debug("0x%016llx", (long long)addr);
996    
997     symbol = get_symbol_name(&cpu->machine->symbol_context,
998     addr, &offset);
999     if (symbol != NULL && offset != addr)
1000     debug("\t<%s>", symbol);
1001     break;
1002     case HI6_ADDI:
1003     case HI6_ADDIU:
1004     case HI6_DADDI:
1005     case HI6_DADDIU:
1006     case HI6_SLTI:
1007     case HI6_SLTIU:
1008     case HI6_ANDI:
1009     case HI6_ORI:
1010     case HI6_XORI:
1011     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1012     rt = instr[2] & 31;
1013     imm = (instr[1] << 8) + instr[0];
1014     if (imm >= 32768)
1015     imm -= 65536;
1016     debug("%s\t%s,", hi6_names[hi6], regname(cpu->machine, rt));
1017     debug("%s,", regname(cpu->machine, rs));
1018     if (hi6 == HI6_ANDI || hi6 == HI6_ORI || hi6 == HI6_XORI)
1019     debug("0x%04x", imm & 0xffff);
1020     else
1021     debug("%i", imm);
1022     break;
1023     case HI6_LUI:
1024     rt = instr[2] & 31;
1025     imm = (instr[1] << 8) + instr[0];
1026     debug("lui\t%s,0x%x", regname(cpu->machine, rt), imm);
1027     break;
1028     case HI6_LB:
1029     case HI6_LBU:
1030     case HI6_LH:
1031     case HI6_LHU:
1032     case HI6_LW:
1033     case HI6_LWU:
1034     case HI6_LD:
1035     case HI6_LQ_MDMX:
1036     case HI6_LWC1:
1037     case HI6_LWC2:
1038     case HI6_LWC3:
1039     case HI6_LDC1:
1040     case HI6_LDC2:
1041     case HI6_LL:
1042     case HI6_LLD:
1043     case HI6_SB:
1044     case HI6_SH:
1045     case HI6_SW:
1046     case HI6_SD:
1047     case HI6_SQ:
1048     case HI6_SC:
1049     case HI6_SCD:
1050     case HI6_SWC1:
1051     case HI6_SWC2:
1052     case HI6_SWC3:
1053     case HI6_SDC1:
1054     case HI6_SDC2:
1055     case HI6_LWL:
1056     case HI6_LWR:
1057     case HI6_LDL:
1058     case HI6_LDR:
1059     case HI6_SWL:
1060     case HI6_SWR:
1061     case HI6_SDL:
1062     case HI6_SDR:
1063     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1064     rt = instr[2] & 31;
1065     imm = (instr[1] << 8) + instr[0];
1066     if (imm >= 32768)
1067     imm -= 65536;
1068     symbol = get_symbol_name(&cpu->machine->symbol_context,
1069     cpu->cd.mips.gpr[rs] + imm, &offset);
1070    
1071     /* LWC3 is PREF in the newer ISA levels: */
1072 dpavlin 12 /* TODO: Which ISAs? IV? V? 32? 64? */
1073     if (cpu->cd.mips.cpu_type.isa_level >= 4 && hi6 == HI6_LWC3) {
1074 dpavlin 2 debug("pref\t0x%x,%i(%s)",
1075     rt, imm, regname(cpu->machine, rs));
1076    
1077     if (running) {
1078     debug("\t[0x%016llx = %s]",
1079     (long long)(cpu->cd.mips.gpr[rs] + imm));
1080     if (symbol != NULL)
1081     debug(" = %s", symbol);
1082     debug("]");
1083     }
1084     goto disasm_ret;
1085     }
1086    
1087     debug("%s\t", hi6_names[hi6]);
1088    
1089     if (hi6 == HI6_SWC1 || hi6 == HI6_SWC2 || hi6 == HI6_SWC3 ||
1090     hi6 == HI6_SDC1 || hi6 == HI6_SDC2 ||
1091     hi6 == HI6_LWC1 || hi6 == HI6_LWC2 || hi6 == HI6_LWC3 ||
1092     hi6 == HI6_LDC1 || hi6 == HI6_LDC2)
1093     debug("r%i", rt);
1094     else
1095     debug("%s", regname(cpu->machine, rt));
1096    
1097     debug(",%i(%s)", imm, regname(cpu->machine, rs));
1098    
1099     if (running) {
1100     debug("\t[");
1101    
1102 dpavlin 12 if (cpu->is_32bit)
1103 dpavlin 2 debug("0x%08x", (int)(cpu->cd.mips.gpr[rs] + imm));
1104     else
1105     debug("0x%016llx",
1106     (long long)(cpu->cd.mips.gpr[rs] + imm));
1107    
1108     if (symbol != NULL)
1109     debug(" = %s", symbol);
1110    
1111     debug(", data=");
1112     } else
1113     break;
1114     /* NOTE: No break here (if we are running) as it is up
1115     to the caller to print 'data'. */
1116     return sizeof(instrword);
1117     case HI6_J:
1118     case HI6_JAL:
1119     imm = (((instr[3] & 3) << 24) + (instr[2] << 16) +
1120     (instr[1] << 8) + instr[0]) << 2;
1121     addr = (dumpaddr + 4) & ~((1 << 28) - 1);
1122     addr |= imm;
1123     symbol = get_symbol_name(&cpu->machine->symbol_context,
1124     addr, &offset);
1125     debug("%s\t0x", hi6_names[hi6]);
1126 dpavlin 12 if (cpu->is_32bit)
1127 dpavlin 2 debug("%08x", (int)addr);
1128     else
1129     debug("%016llx", (long long)addr);
1130     if (symbol != NULL)
1131     debug("\t<%s>", symbol);
1132     break;
1133     case HI6_COP0:
1134     case HI6_COP1:
1135     case HI6_COP2:
1136     case HI6_COP3:
1137     imm = (instr[3] << 24) + (instr[2] << 16) +
1138     (instr[1] << 8) + instr[0];
1139     imm &= ((1 << 26) - 1);
1140    
1141     /* Call coproc_function(), but ONLY disassembly, no exec: */
1142     coproc_function(cpu, cpu->cd.mips.coproc[hi6 - HI6_COP0],
1143     hi6 - HI6_COP0, imm, 1, running);
1144     return sizeof(instrword);
1145     case HI6_CACHE:
1146     rt = ((instr[3] & 3) << 3) + (instr[2] >> 5); /* base */
1147     copz = instr[2] & 31;
1148     imm = (instr[1] << 8) + instr[0];
1149     cache_op = copz >> 2;
1150     which_cache = copz & 3;
1151     showtag = 0;
1152     debug("cache\t0x%02x,0x%04x(%s)", copz, imm,
1153     regname(cpu->machine, rt));
1154     if (which_cache==0) debug(" [ primary I-cache");
1155     if (which_cache==1) debug(" [ primary D-cache");
1156     if (which_cache==2) debug(" [ secondary I-cache");
1157     if (which_cache==3) debug(" [ secondary D-cache");
1158     debug(", ");
1159     if (cache_op==0) debug("index invalidate");
1160     if (cache_op==1) debug("index load tag");
1161     if (cache_op==2) debug("index store tag"), showtag=1;
1162     if (cache_op==3) debug("create dirty exclusive");
1163     if (cache_op==4) debug("hit invalidate");
1164     if (cache_op==5) debug("fill OR hit writeback invalidate");
1165     if (cache_op==6) debug("hit writeback");
1166     if (cache_op==7) debug("hit set virtual");
1167     if (running)
1168     debug(", addr 0x%016llx",
1169     (long long)(cpu->cd.mips.gpr[rt] + imm));
1170     if (showtag)
1171     debug(", taghi=%08lx lo=%08lx",
1172     (long)cpu->cd.mips.coproc[0]->reg[COP0_TAGDATA_HI],
1173     (long)cpu->cd.mips.coproc[0]->reg[COP0_TAGDATA_LO]);
1174     debug(" ]");
1175     break;
1176     case HI6_SPECIAL2:
1177     special6 = instr[0] & 0x3f;
1178     instrword = (instr[3] << 24) + (instr[2] << 16) +
1179     (instr[1] << 8) + instr[0];
1180     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1181     rt = instr[2] & 31;
1182     rd = (instr[1] >> 3) & 31;
1183     if ((instrword & 0xfc0007ffULL) == 0x70000000) {
1184     debug("madd\t%s", regname(cpu->machine, rd));
1185     debug(",%s", regname(cpu->machine, rs));
1186     debug(",%s", regname(cpu->machine, rt));
1187     } else if (special6 == SPECIAL2_MUL) {
1188     /* TODO: this is just a guess, I don't have the
1189     docs in front of me */
1190     debug("mul\t%s", regname(cpu->machine, rd));
1191     debug(",%s", regname(cpu->machine, rs));
1192     debug(",%s", regname(cpu->machine, rt));
1193     } else if (special6 == SPECIAL2_CLZ) {
1194     debug("clz\t%s", regname(cpu->machine, rd));
1195     debug(",%s", regname(cpu->machine, rs));
1196     } else if (special6 == SPECIAL2_CLO) {
1197     debug("clo\t%s", regname(cpu->machine, rd));
1198     debug(",%s", regname(cpu->machine, rs));
1199     } else if (special6 == SPECIAL2_DCLZ) {
1200     debug("dclz\t%s", regname(cpu->machine, rd));
1201     debug(",%s", regname(cpu->machine, rs));
1202     } else if (special6 == SPECIAL2_DCLO) {
1203     debug("dclo\t%s", regname(cpu->machine, rd));
1204     debug(",%s", regname(cpu->machine, rs));
1205     } else if ((instrword & 0xffff07ffULL) == 0x70000209
1206     || (instrword & 0xffff07ffULL) == 0x70000249) {
1207     if (instr[0] == 0x49) {
1208     debug("pmflo\t%s", regname(cpu->machine, rd));
1209     debug(" (rs=%s)", regname(cpu->machine, rs));
1210     } else {
1211     debug("pmfhi\t%s", regname(cpu->machine, rd));
1212     debug(" (rs=%s)", regname(cpu->machine, rs));
1213     }
1214     } else if ((instrword & 0xfc1fffff) == 0x70000269
1215     || (instrword & 0xfc1fffff) == 0x70000229) {
1216     if (instr[0] == 0x69) {
1217     debug("pmtlo\t%s", regname(cpu->machine, rs));
1218     } else {
1219     debug("pmthi\t%s", regname(cpu->machine, rs));
1220     }
1221     } else if ((instrword & 0xfc0007ff) == 0x700004a9) {
1222     debug("por\t%s", regname(cpu->machine, rd));
1223     debug(",%s", regname(cpu->machine, rs));
1224     debug(",%s", regname(cpu->machine, rt));
1225     } else if ((instrword & 0xfc0007ff) == 0x70000488) {
1226     debug("pextlw\t%s", regname(cpu->machine, rd));
1227     debug(",%s", regname(cpu->machine, rs));
1228     debug(",%s", regname(cpu->machine, rt));
1229     } else {
1230     debug("unimplemented special2 = 0x%02x", special6);
1231     }
1232     break;
1233     case HI6_REGIMM:
1234     regimm5 = instr[2] & 0x1f;
1235     switch (regimm5) {
1236     case REGIMM_BLTZ:
1237     case REGIMM_BGEZ:
1238     case REGIMM_BLTZL:
1239     case REGIMM_BGEZL:
1240     case REGIMM_BLTZAL:
1241     case REGIMM_BLTZALL:
1242     case REGIMM_BGEZAL:
1243     case REGIMM_BGEZALL:
1244     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
1245     imm = (instr[1] << 8) + instr[0];
1246     if (imm >= 32768)
1247     imm -= 65536;
1248    
1249     debug("%s\t%s,", regimm_names[regimm5],
1250     regname(cpu->machine, rs));
1251    
1252     addr = (dumpaddr + 4) + (imm << 2);
1253    
1254 dpavlin 12 if (cpu->is_32bit)
1255 dpavlin 2 debug("0x%08x", (int)addr);
1256     else
1257     debug("0x%016llx", (long long)addr);
1258     break;
1259     default:
1260     debug("unimplemented regimm5 = 0x%02x", regimm5);
1261     }
1262     break;
1263     default:
1264     debug("unimplemented hi6 = 0x%02x", hi6);
1265     }
1266    
1267     disasm_ret:
1268     debug("\n");
1269     return sizeof(instrword);
1270     }
1271    
1272    
1273     /*
1274     * mips_cpu_register_dump():
1275     *
1276     * Dump cpu registers in a relatively readable format.
1277     *
1278     * gprs: set to non-zero to dump GPRs and hi/lo/pc
1279     * coprocs: set bit 0..3 to dump registers in coproc 0..3.
1280     */
1281     void mips_cpu_register_dump(struct cpu *cpu, int gprs, int coprocs)
1282     {
1283     int coprocnr, i, bits32;
1284     uint64_t offset;
1285     char *symbol;
1286    
1287 dpavlin 12 bits32 = cpu->is_32bit;
1288 dpavlin 2
1289     if (gprs) {
1290     /* Special registers (pc, hi/lo) first: */
1291     symbol = get_symbol_name(&cpu->machine->symbol_context,
1292     cpu->pc, &offset);
1293    
1294     if (bits32)
1295     debug("cpu%i: pc = %08x", cpu->cpu_id, (int)cpu->pc);
1296     else
1297 dpavlin 12 debug("cpu%i: pc = 0x%016llx",
1298 dpavlin 2 cpu->cpu_id, (long long)cpu->pc);
1299    
1300     debug(" <%s>\n", symbol != NULL? symbol :
1301     " no symbol ");
1302    
1303     if (bits32)
1304     debug("cpu%i: hi = %08x lo = %08x\n",
1305     cpu->cpu_id, (int)cpu->cd.mips.hi, (int)cpu->cd.mips.lo);
1306     else
1307 dpavlin 12 debug("cpu%i: hi = 0x%016llx lo = 0x%016llx\n",
1308 dpavlin 2 cpu->cpu_id, (long long)cpu->cd.mips.hi,
1309     (long long)cpu->cd.mips.lo);
1310    
1311     /* General registers: */
1312     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
1313     /* 128-bit: */
1314     for (i=0; i<32; i++) {
1315     if ((i & 1) == 0)
1316     debug("cpu%i:", cpu->cpu_id);
1317     debug(" %3s=%016llx%016llx",
1318     regname(cpu->machine, i),
1319     (long long)cpu->cd.mips.gpr_quadhi[i],
1320     (long long)cpu->cd.mips.gpr[i]);
1321     if ((i & 1) == 1)
1322     debug("\n");
1323     }
1324     } else if (bits32) {
1325     /* 32-bit: */
1326     for (i=0; i<32; i++) {
1327     if ((i & 3) == 0)
1328     debug("cpu%i:", cpu->cpu_id);
1329 dpavlin 12 if (i == MIPS_GPR_ZERO)
1330     debug(" ");
1331     else
1332     debug(" %3s = %08x", regname(cpu->machine, i), (int)cpu->cd.mips.gpr[i]);
1333 dpavlin 2 if ((i & 3) == 3)
1334     debug("\n");
1335     }
1336     } else {
1337     /* 64-bit: */
1338     for (i=0; i<32; i++) {
1339 dpavlin 12 int r = (i >> 1) + ((i & 1) << 4);
1340 dpavlin 2 if ((i & 1) == 0)
1341     debug("cpu%i:", cpu->cpu_id);
1342 dpavlin 12 if (r == MIPS_GPR_ZERO)
1343     debug(" ");
1344     else
1345     debug(" %3s = 0x%016llx", regname(cpu->machine, r), (long long)cpu->cd.mips.gpr[r]);
1346 dpavlin 2 if ((i & 1) == 1)
1347     debug("\n");
1348     }
1349     }
1350     }
1351    
1352     for (coprocnr=0; coprocnr<4; coprocnr++) {
1353     int nm1 = 1;
1354    
1355     if (bits32)
1356     nm1 = 3;
1357    
1358     if (!(coprocs & (1<<coprocnr)))
1359     continue;
1360     if (cpu->cd.mips.coproc[coprocnr] == NULL) {
1361     debug("cpu%i: no coprocessor %i\n",
1362     cpu->cpu_id, coprocnr);
1363     continue;
1364     }
1365    
1366     /* Coprocessor registers: */
1367     /* TODO: multiple selections per register? */
1368     for (i=0; i<32; i++) {
1369     /* 32-bit: */
1370     if ((i & nm1) == 0)
1371     debug("cpu%i:", cpu->cpu_id);
1372    
1373     if (cpu->machine->show_symbolic_register_names &&
1374     coprocnr == 0)
1375     debug(" %8s", cop0_names[i]);
1376     else
1377     debug(" c%i,%02i", coprocnr, i);
1378    
1379     if (bits32)
1380     debug("=%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]);
1381 dpavlin 12 else {
1382     if (coprocnr == 0 && (i == COP0_COUNT
1383     || i == COP0_COMPARE || i == COP0_INDEX
1384     || i == COP0_RANDOM || i == COP0_WIRED))
1385     debug(" = 0x%08x", (int)cpu->cd.mips.coproc[coprocnr]->reg[i]);
1386     else
1387     debug(" = 0x%016llx", (long long)
1388     cpu->cd.mips.coproc[coprocnr]->reg[i]);
1389     }
1390 dpavlin 2
1391     if ((i & nm1) == nm1)
1392     debug("\n");
1393    
1394     /* Skip the last 16 cop0 registers on R3000 etc. */
1395     if (coprocnr == 0 && cpu->cd.mips.cpu_type.isa_level < 3
1396     && i == 15)
1397     i = 31;
1398     }
1399    
1400 dpavlin 12 if (coprocnr == 0 && cpu->cd.mips.cpu_type.isa_level >= 32) {
1401     debug("cpu%i: ", cpu->cpu_id);
1402     debug("config_select1 = 0x");
1403     if (cpu->is_32bit)
1404     debug("%08x", (int)cpu->cd.mips.cop0_config_select1);
1405     else
1406     debug("%016llx", (long long)cpu->cd.mips.cop0_config_select1);
1407     debug("\n");
1408     }
1409    
1410 dpavlin 2 /* Floating point control registers: */
1411     if (coprocnr == 1) {
1412     for (i=0; i<32; i++)
1413     switch (i) {
1414     case 0: printf("cpu%i: fcr0 (fcir) = 0x%08x\n",
1415     cpu->cpu_id, (int)cpu->cd.mips.coproc[coprocnr]->fcr[i]);
1416     break;
1417     case 25:printf("cpu%i: fcr25 (fccr) = 0x%08x\n",
1418     cpu->cpu_id, (int)cpu->cd.mips.coproc[coprocnr]->fcr[i]);
1419     break;
1420     case 31:printf("cpu%i: fcr31 (fcsr) = 0x%08x\n",
1421     cpu->cpu_id, (int)cpu->cd.mips.coproc[coprocnr]->fcr[i]);
1422     break;
1423     }
1424     }
1425     }
1426     }
1427    
1428    
1429 dpavlin 12 #define DYNTRANS_FUNCTION_TRACE mips_cpu_functioncall_trace
1430     #define DYNTRANS_MIPS
1431     #define DYNTRANS_ARCH mips
1432     #include "cpu_dyntrans.c"
1433     #undef DYNTRANS_MIPS
1434     #undef DYNTRANS_ARCH
1435     #undef DYNTRANS_FUNCTION_TRACE
1436 dpavlin 2
1437    
1438     /*
1439     * mips_cpu_interrupt():
1440     *
1441     * Cause an interrupt. If irq_nr is 2..7, then it is a MIPS hardware
1442     * interrupt. 0 and 1 are ignored (software interrupts).
1443     *
1444     * If irq_nr is >= 8, then this function calls md_interrupt().
1445     */
1446     int mips_cpu_interrupt(struct cpu *cpu, uint64_t irq_nr)
1447     {
1448     if (irq_nr >= 8) {
1449     if (cpu->machine->md_interrupt != NULL)
1450     cpu->machine->md_interrupt(cpu->machine, cpu, irq_nr, 1);
1451     else
1452     fatal("mips_cpu_interrupt(): irq_nr = %i, but md_interrupt = NULL ?\n", irq_nr);
1453     return 1;
1454     }
1455    
1456     if (irq_nr < 2)
1457     return 0;
1458    
1459     cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] |= ((1 << irq_nr) << STATUS_IM_SHIFT);
1460     cpu->cd.mips.cached_interrupt_is_possible = 1;
1461     return 1;
1462     }
1463    
1464    
1465     /*
1466     * mips_cpu_interrupt_ack():
1467     *
1468     * Acknowledge an interrupt. If irq_nr is 2..7, then it is a MIPS hardware
1469     * interrupt. Interrupts 0..1 are ignored (software interrupts).
1470     *
1471     * If irq_nr is >= 8, then it is machine dependant, and md_interrupt() is
1472     * called.
1473     */
1474     int mips_cpu_interrupt_ack(struct cpu *cpu, uint64_t irq_nr)
1475     {
1476     if (irq_nr >= 8) {
1477     if (cpu->machine->md_interrupt != NULL)
1478     cpu->machine->md_interrupt(cpu->machine, cpu, irq_nr, 0);
1479     else
1480     fatal("mips_cpu_interrupt_ack(): irq_nr = %i, but md_interrupt = NULL ?\n", irq_nr);
1481     return 1;
1482     }
1483    
1484     if (irq_nr < 2)
1485     return 0;
1486    
1487     cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] &= ~((1 << irq_nr) << STATUS_IM_SHIFT);
1488     if (!(cpu->cd.mips.coproc[0]->reg[COP0_CAUSE] & STATUS_IM_MASK))
1489     cpu->cd.mips.cached_interrupt_is_possible = 0;
1490    
1491     return 1;
1492     }
1493    
1494    
1495     /*
1496     * mips_cpu_exception():
1497     *
1498     * Cause an exception in a CPU. This sets a couple of coprocessor 0
1499     * registers, and the program counter.
1500     *
1501     * exccode the exception code
1502     * tlb set to non-zero if the exception handler at
1503     * 0x80000000 should be used. (normal = 0x80000180)
1504     * vaddr virtual address (for some exceptions)
1505     * coproc_nr coprocessor number (for some exceptions)
1506     * vaddr_vpn2 vpn2 (for some exceptions)
1507     * vaddr_asid asid (for some exceptions)
1508     * x_64 non-zero for 64-bit mode for R4000-style tlb misses
1509     */
1510     void mips_cpu_exception(struct cpu *cpu, int exccode, int tlb, uint64_t vaddr,
1511     int coproc_nr, uint64_t vaddr_vpn2, int vaddr_asid, int x_64)
1512     {
1513     uint64_t base;
1514     uint64_t *reg = &cpu->cd.mips.coproc[0]->reg[0];
1515     int exc_model = cpu->cd.mips.cpu_type.exc_model;
1516    
1517     if (!quiet_mode) {
1518     uint64_t offset;
1519     int x;
1520 dpavlin 12 char *symbol = get_symbol_name(&cpu->machine->symbol_context,
1521     cpu->cd.mips.pc_last, &offset);
1522 dpavlin 2
1523     debug("[ ");
1524     if (cpu->machine->ncpus > 1)
1525     debug("cpu%i: ", cpu->cpu_id);
1526    
1527     debug("exception %s%s",
1528     exception_names[exccode], tlb? " <tlb>" : "");
1529    
1530     switch (exccode) {
1531     case EXCEPTION_INT:
1532     debug(" cause_im=0x%02x", (int)((reg[COP0_CAUSE] & CAUSE_IP_MASK) >> CAUSE_IP_SHIFT));
1533     break;
1534     case EXCEPTION_SYS:
1535     debug(" v0=%i", (int)cpu->cd.mips.gpr[MIPS_GPR_V0]);
1536     for (x=0; x<4; x++) {
1537     int64_t d = cpu->cd.mips.gpr[MIPS_GPR_A0 + x];
1538     char strbuf[30];
1539    
1540     if (d > -256 && d < 256)
1541     debug(" a%i=%i", x, (int)d);
1542     else if (memory_points_to_string(cpu, cpu->mem, d, 1))
1543     debug(" a%i=\"%s\"", x, memory_conv_to_string(cpu, cpu->mem, d, strbuf, sizeof(strbuf)));
1544     else
1545     debug(" a%i=0x%llx", x, (long long)d);
1546     }
1547     break;
1548     default:
1549 dpavlin 12 if (cpu->is_32bit)
1550     debug(" vaddr=0x%08x", (int)vaddr);
1551     else
1552     debug(" vaddr=0x%016llx", (long long)vaddr);
1553 dpavlin 2 }
1554    
1555 dpavlin 12 if (cpu->is_32bit)
1556     debug(" pc=0x%08x ", (int)cpu->cd.mips.pc_last);
1557     else
1558     debug(" pc=0x%016llx ", (long long)cpu->cd.mips.pc_last);
1559 dpavlin 2
1560     if (symbol != NULL)
1561     debug("<%s> ]\n", symbol);
1562     else
1563     debug("]\n");
1564     }
1565    
1566     if (tlb && vaddr < 0x1000) {
1567     uint64_t offset;
1568 dpavlin 4 char *symbol = get_symbol_name(&cpu->machine->symbol_context,
1569     cpu->cd.mips.pc_last, &offset);
1570 dpavlin 6 fatal("[ ");
1571     if (cpu->machine->ncpus > 1)
1572     fatal("cpu%i: ", cpu->cpu_id);
1573 dpavlin 12 fatal("warning: LOW reference: vaddr=");
1574     if (cpu->is_32bit)
1575     fatal("0x%08x", (int)vaddr);
1576     else
1577     fatal("0x%016llx", (long long)vaddr);
1578     fatal(", exception %s, pc=", exception_names[exccode]);
1579     if (cpu->is_32bit)
1580     fatal("0x%08x", (int)cpu->cd.mips.pc_last);
1581     else
1582     fatal("0x%016llx", (long long)cpu->cd.mips.pc_last);
1583     fatal(" <%s> ]\n", symbol? symbol : "(no symbol)");
1584 dpavlin 8
1585     #ifdef TRACE_NULL_CRASHES
1586     /* This can be useful for debugging kernel bugs: */
1587     {
1588     int i = cpu->trace_null_index;
1589     do {
1590     fatal("TRACE: 0x%016llx\n",
1591     cpu->trace_null_addr[i]);
1592     i ++;
1593     i %= TRACE_NULL_N_ENTRIES;
1594     } while (i != cpu->trace_null_index);
1595     }
1596     cpu->running = 0;
1597     cpu->dead = 1;
1598     #endif
1599 dpavlin 2 }
1600    
1601     /* Clear the exception code bits of the cause register... */
1602 dpavlin 12 if (exc_model == EXC3K)
1603 dpavlin 2 reg[COP0_CAUSE] &= ~R2K3K_CAUSE_EXCCODE_MASK;
1604 dpavlin 12 else
1605 dpavlin 2 reg[COP0_CAUSE] &= ~CAUSE_EXCCODE_MASK;
1606    
1607     /* ... and OR in the exception code: */
1608     reg[COP0_CAUSE] |= (exccode << CAUSE_EXCCODE_SHIFT);
1609    
1610     /* Always set CE (according to the R5000 manual): */
1611     reg[COP0_CAUSE] &= ~CAUSE_CE_MASK;
1612     reg[COP0_CAUSE] |= (coproc_nr << CAUSE_CE_SHIFT);
1613    
1614     if (tlb || (exccode >= EXCEPTION_MOD && exccode <= EXCEPTION_ADES) ||
1615     exccode == EXCEPTION_VCEI || exccode == EXCEPTION_VCED) {
1616     reg[COP0_BADVADDR] = vaddr;
1617     #if 1
1618     /* TODO: This should be removed. */
1619     /* sign-extend vaddr, if it is 32-bit */
1620     if ((vaddr >> 32) == 0 && (vaddr & 0x80000000ULL))
1621     reg[COP0_BADVADDR] |=
1622     0xffffffff00000000ULL;
1623     #endif
1624     if (exc_model == EXC3K) {
1625     reg[COP0_CONTEXT] &= ~R2K3K_CONTEXT_BADVPN_MASK;
1626     reg[COP0_CONTEXT] |= ((vaddr_vpn2 << R2K3K_CONTEXT_BADVPN_SHIFT) & R2K3K_CONTEXT_BADVPN_MASK);
1627    
1628     reg[COP0_ENTRYHI] = (vaddr & R2K3K_ENTRYHI_VPN_MASK)
1629     | (vaddr_asid << R2K3K_ENTRYHI_ASID_SHIFT);
1630    
1631     /* Sign-extend: */
1632     reg[COP0_CONTEXT] = (int64_t)(int32_t)reg[COP0_CONTEXT];
1633     reg[COP0_ENTRYHI] = (int64_t)(int32_t)reg[COP0_ENTRYHI];
1634     } else {
1635     if (cpu->cd.mips.cpu_type.rev == MIPS_R4100) {
1636     reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK_R4100;
1637     reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK_R4100);
1638    
1639     /* TODO: fix these */
1640     reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
1641     reg[COP0_XCONTEXT] &= ~XCONTEXT_BADVPN2_MASK;
1642     reg[COP0_XCONTEXT] |= (vaddr_vpn2 << XCONTEXT_BADVPN2_SHIFT) & XCONTEXT_BADVPN2_MASK;
1643     reg[COP0_XCONTEXT] |= ((vaddr >> 62) & 0x3) << XCONTEXT_R_SHIFT;
1644    
1645     /* reg[COP0_PAGEMASK] = cpu->cd.mips.coproc[0]->tlbs[0].mask & PAGEMASK_MASK; */
1646    
1647     reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK | 0x1800)) | vaddr_asid;
1648     } else {
1649     reg[COP0_CONTEXT] &= ~CONTEXT_BADVPN2_MASK;
1650     reg[COP0_CONTEXT] |= ((vaddr_vpn2 << CONTEXT_BADVPN2_SHIFT) & CONTEXT_BADVPN2_MASK);
1651    
1652     reg[COP0_XCONTEXT] &= ~XCONTEXT_R_MASK;
1653     reg[COP0_XCONTEXT] &= ~XCONTEXT_BADVPN2_MASK;
1654     reg[COP0_XCONTEXT] |= (vaddr_vpn2 << XCONTEXT_BADVPN2_SHIFT) & XCONTEXT_BADVPN2_MASK;
1655     reg[COP0_XCONTEXT] |= ((vaddr >> 62) & 0x3) << XCONTEXT_R_SHIFT;
1656    
1657     /* reg[COP0_PAGEMASK] = cpu->cd.mips.coproc[0]->tlbs[0].mask & PAGEMASK_MASK; */
1658    
1659     if (cpu->cd.mips.cpu_type.mmu_model == MMU10K)
1660     reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK_R10K)) | vaddr_asid;
1661     else
1662     reg[COP0_ENTRYHI] = (vaddr & (ENTRYHI_R_MASK | ENTRYHI_VPN2_MASK)) | vaddr_asid;
1663     }
1664     }
1665     }
1666    
1667     if (exc_model == EXC4K && reg[COP0_STATUS] & STATUS_EXL) {
1668     /*
1669     * Don't set EPC if STATUS_EXL is set, for R4000 and up.
1670     * This actually happens when running IRIX and Ultrix, when
1671     * they handle interrupts and/or tlb updates, I think, so
1672     * printing this with debug() looks better than with fatal().
1673     */
1674     /* debug("[ warning: cpu%i exception while EXL is set, not setting EPC ]\n", cpu->cpu_id); */
1675     } else {
1676     if (cpu->cd.mips.delay_slot || cpu->cd.mips.nullify_next) {
1677     reg[COP0_EPC] = cpu->cd.mips.pc_last - 4;
1678     reg[COP0_CAUSE] |= CAUSE_BD;
1679    
1680     /* TODO: Should the BD flag actually be set
1681     on nullified slots? */
1682     } else {
1683     reg[COP0_EPC] = cpu->cd.mips.pc_last;
1684     reg[COP0_CAUSE] &= ~CAUSE_BD;
1685     }
1686     }
1687    
1688     cpu->cd.mips.delay_slot = NOT_DELAYED;
1689     cpu->cd.mips.nullify_next = 0;
1690    
1691     /* TODO: This is true for MIPS64, but how about others? */
1692     if (reg[COP0_STATUS] & STATUS_BEV)
1693     base = 0xffffffffbfc00200ULL;
1694     else
1695     base = 0xffffffff80000000ULL;
1696    
1697     switch (exc_model) {
1698     case EXC3K:
1699     /* Userspace tlb, vs others: */
1700     if (tlb && !(vaddr & 0x80000000ULL) &&
1701     (exccode == EXCEPTION_TLBL || exccode == EXCEPTION_TLBS) )
1702     cpu->pc = base + 0x000;
1703     else
1704     cpu->pc = base + 0x080;
1705     break;
1706     default:
1707     /*
1708     * These offsets are according to the MIPS64 manual, but
1709     * should work with R4000 and the rest too (I hope).
1710     *
1711     * 0x000 TLB refill, if EXL=0
1712     * 0x080 64-bit XTLB refill, if EXL=0
1713     * 0x100 cache error (not implemented yet)
1714     * 0x180 general exception
1715     * 0x200 interrupt (if CAUSE_IV is set)
1716     */
1717     if (tlb && (exccode == EXCEPTION_TLBL ||
1718     exccode == EXCEPTION_TLBS) &&
1719     !(reg[COP0_STATUS] & STATUS_EXL)) {
1720     if (x_64)
1721     cpu->pc = base + 0x080;
1722     else
1723     cpu->pc = base + 0x000;
1724     } else {
1725     if (exccode == EXCEPTION_INT &&
1726     (reg[COP0_CAUSE] & CAUSE_IV))
1727     cpu->pc = base + 0x200;
1728     else
1729     cpu->pc = base + 0x180;
1730     }
1731     }
1732    
1733     if (exc_model == EXC3K) {
1734     /* R2000/R3000: Shift the lowest 6 bits to the left two steps: */
1735     reg[COP0_STATUS] =
1736     (reg[COP0_STATUS] & ~0x3f) +
1737     ((reg[COP0_STATUS] & 0xf) << 2);
1738     } else {
1739     /* R4000: */
1740     reg[COP0_STATUS] |= STATUS_EXL;
1741     }
1742    
1743     /* Sign-extend: */
1744     reg[COP0_CAUSE] = (int64_t)(int32_t)reg[COP0_CAUSE];
1745     reg[COP0_STATUS] = (int64_t)(int32_t)reg[COP0_STATUS];
1746     }
1747    
1748    
1749     #ifdef BINTRANS
1750     /*
1751     * mips_cpu_cause_simple_exception():
1752     *
1753     * Useful for causing raw exceptions from bintrans, for example
1754     * SYSCALL or BREAK.
1755     */
1756     void mips_cpu_cause_simple_exception(struct cpu *cpu, int exc_code)
1757     {
1758     mips_cpu_exception(cpu, exc_code, 0, 0, 0, 0, 0, 0);
1759     }
1760     #endif
1761    
1762    
1763     /* Included here for better cache characteristics: */
1764     #include "memory_mips.c"
1765    
1766    
1767     /*
1768     * mips_cpu_run_instr():
1769     *
1770     * Execute one instruction on a cpu.
1771     *
1772     * If we are in a delay slot, set cpu->pc to cpu->cd.mips.delay_jmpaddr
1773     * after the instruction is executed.
1774     *
1775     * Return value is the number of instructions executed during this call,
1776     * 0 if no instruction was executed.
1777     */
1778     int mips_cpu_run_instr(struct emul *emul, struct cpu *cpu)
1779     {
1780     int quiet_mode_cached = quiet_mode;
1781     int instruction_trace_cached = cpu->machine->instruction_trace;
1782     struct mips_coproc *cp0 = cpu->cd.mips.coproc[0];
1783     int i, tmp, ninstrs_executed;
1784     unsigned char instr[4];
1785     uint32_t instrword;
1786     uint64_t cached_pc;
1787     int hi6, special6, regimm5, rd, rs, rt, sa, imm;
1788     int copz, which_cache, cache_op;
1789    
1790     int cond, likely, and_link;
1791    
1792     /* for unaligned load/store */
1793     uint64_t dir, is_left, reg_ofs, reg_dir;
1794    
1795     uint64_t tmpvalue, tmpaddr;
1796    
1797     int cpnr; /* coprocessor nr */
1798    
1799     /* for load/store */
1800     uint64_t addr, value, value_hi, result_value;
1801     int wlen, st, signd, linked;
1802     unsigned char d[16]; /* room for at most 128 bits */
1803    
1804    
1805     /*
1806     * Update Coprocessor 0 registers:
1807     *
1808     * The COUNT register needs to be updated on every [other] instruction.
1809     * The RANDOM register should decrease for every instruction.
1810     */
1811    
1812     if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
1813     int r = (cp0->reg[COP0_RANDOM] & R2K3K_RANDOM_MASK) >> R2K3K_RANDOM_SHIFT;
1814     r --;
1815     if (r >= cp0->nr_of_tlbs || r < 8)
1816     r = cp0->nr_of_tlbs-1;
1817     cp0->reg[COP0_RANDOM] = r << R2K3K_RANDOM_SHIFT;
1818     } else {
1819     cp0->reg[COP0_RANDOM] --;
1820     if ((int64_t)cp0->reg[COP0_RANDOM] >= cp0->nr_of_tlbs ||
1821     (int64_t)cp0->reg[COP0_RANDOM] < (int64_t) cp0->reg[COP0_WIRED])
1822     cp0->reg[COP0_RANDOM] = cp0->nr_of_tlbs-1;
1823    
1824     /*
1825     * TODO: only increase count every other instruction,
1826     * according to the R4000 manual. But according to the
1827     * R5000 manual: increment every other clock cycle.
1828     * Which one is it? :-)
1829     */
1830     cp0->reg[COP0_COUNT] = (int64_t)(int32_t)(cp0->reg[COP0_COUNT] + 1);
1831    
1832     if (cpu->cd.mips.compare_register_set &&
1833     cp0->reg[COP0_COUNT] == cp0->reg[COP0_COMPARE]) {
1834     mips_cpu_interrupt(cpu, 7);
1835     cpu->cd.mips.compare_register_set = 0;
1836     }
1837     }
1838    
1839    
1840     #ifdef ENABLE_INSTRUCTION_DELAYS
1841     if (cpu->cd.mips.instruction_delay > 0) {
1842     cpu->cd.mips.instruction_delay --;
1843     return 1;
1844     }
1845     #endif
1846    
1847     /* Cache the program counter in a local variable: */
1848     cached_pc = cpu->pc;
1849    
1850 dpavlin 8 #ifdef TRACE_NULL_CRASHES
1851     cpu->trace_null_addr[cpu->trace_null_index] = cached_pc;
1852     cpu->trace_null_index ++;
1853     cpu->trace_null_index %= TRACE_NULL_N_ENTRIES;
1854     #endif
1855    
1856 dpavlin 2 /* Hardwire the zero register to 0: */
1857     cpu->cd.mips.gpr[MIPS_GPR_ZERO] = 0;
1858    
1859     if (cpu->cd.mips.delay_slot) {
1860     if (cpu->cd.mips.delay_slot == DELAYED) {
1861     cached_pc = cpu->pc = cpu->cd.mips.delay_jmpaddr;
1862     cpu->cd.mips.delay_slot = NOT_DELAYED;
1863     } else /* if (cpu->cd.mips.delay_slot == TO_BE_DELAYED) */ {
1864     /* next instruction will be delayed */
1865     cpu->cd.mips.delay_slot = DELAYED;
1866     }
1867     }
1868    
1869     if (cpu->cd.mips.last_was_jumptoself > 0)
1870     cpu->cd.mips.last_was_jumptoself --;
1871    
1872     /* Check PC against breakpoints: */
1873     if (!single_step)
1874     for (i=0; i<cpu->machine->n_breakpoints; i++)
1875     if (cached_pc == cpu->machine->breakpoint_addr[i]) {
1876     fatal("Breakpoint reached, pc=0x");
1877 dpavlin 12 if (cpu->is_32bit)
1878 dpavlin 2 fatal("%08x", (int)cached_pc);
1879     else
1880     fatal("%016llx", (long long)cached_pc);
1881     fatal("\n");
1882     single_step = 1;
1883     return 0;
1884     }
1885    
1886    
1887     /* Remember where we are, in case of interrupt or exception: */
1888     cpu->cd.mips.pc_last = cached_pc;
1889    
1890     /*
1891     * Any pending interrupts?
1892     *
1893     * If interrupts are enabled, and any interrupt has arrived (ie its
1894     * bit in the cause register is set) and corresponding enable bits
1895     * in the status register are set, then cause an interrupt exception
1896     * instead of executing the current instruction.
1897     *
1898     * NOTE: cached_interrupt_is_possible is set to 1 whenever an
1899     * interrupt bit in the cause register is set to one (in
1900     * mips_cpu_interrupt()) and set to 0 whenever all interrupt bits are
1901     * cleared (in mips_cpu_interrupt_ack()), so we don't need to do a
1902     * full check each time.
1903     */
1904     if (cpu->cd.mips.cached_interrupt_is_possible && !cpu->cd.mips.nullify_next) {
1905     if (cpu->cd.mips.cpu_type.exc_model == EXC3K) {
1906     /* R3000: */
1907     int enabled, mask;
1908     int status = cp0->reg[COP0_STATUS];
1909    
1910     enabled = status & MIPS_SR_INT_IE;
1911     mask = status & cp0->reg[COP0_CAUSE] & STATUS_IM_MASK;
1912     if (enabled && mask) {
1913     mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0, 0);
1914     return 0;
1915     }
1916     } else {
1917     /* R4000 and others: */
1918     int enabled, mask;
1919     int status = cp0->reg[COP0_STATUS];
1920    
1921     enabled = (status & STATUS_IE)
1922     && !(status & STATUS_EXL)
1923     && !(status & STATUS_ERL);
1924    
1925     mask = status & cp0->reg[COP0_CAUSE] & STATUS_IM_MASK;
1926     if (enabled && mask) {
1927     mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0, 0, 0, 0, 0);
1928     return 0;
1929     }
1930     }
1931     }
1932    
1933    
1934     /*
1935 dpavlin 10 * ROM emulation: (0xbfcXXXXX or 0x9fcXXXXX)
1936 dpavlin 2 *
1937     * This assumes that a jal was made to a ROM address,
1938     * and we should return via gpr ra.
1939     */
1940 dpavlin 10 if ((cached_pc & 0xdff00000) == 0x9fc00000 &&
1941 dpavlin 2 cpu->machine->prom_emulation) {
1942 dpavlin 10 int rom_jal = 1, res = 1;
1943 dpavlin 2 switch (cpu->machine->machine_type) {
1944     case MACHINE_DEC:
1945     res = decstation_prom_emul(cpu);
1946     break;
1947     case MACHINE_PS2:
1948     res = playstation2_sifbios_emul(cpu);
1949     break;
1950     case MACHINE_ARC:
1951     case MACHINE_SGI:
1952     res = arcbios_emul(cpu);
1953     break;
1954 dpavlin 10 case MACHINE_EVBMIPS:
1955     res = yamon_emul(cpu);
1956     break;
1957 dpavlin 2 default:
1958     rom_jal = 0;
1959     }
1960    
1961     if (rom_jal) {
1962     /*
1963     * Special hack: If the PROM emulation layer needs
1964     * to loop (for example when emulating blocking
1965     * console input) then we should simply return, so
1966     * that the same PROM routine is called on the next
1967     * round as well.
1968     *
1969     * This still has to count as one or more
1970     * instructions, so 1000 is returned. (Ugly.)
1971     */
1972     if (!res)
1973     return 1000;
1974    
1975     cpu->pc = cpu->cd.mips.gpr[MIPS_GPR_RA];
1976     /* no need to update cached_pc, as we're returning */
1977     cpu->cd.mips.delay_slot = NOT_DELAYED;
1978    
1979 dpavlin 12 if (cpu->machine->show_trace_tree)
1980     cpu_functioncall_trace_return(cpu);
1981 dpavlin 2
1982     /* TODO: how many instrs should this count as? */
1983     return 10;
1984     }
1985     }
1986    
1987     #ifdef ALWAYS_SIGNEXTEND_32
1988     /*
1989     * An extra check for 32-bit mode to make sure that all
1990     * registers are sign-extended: (Slow, but might be useful
1991     * to detect bugs that have to do with sign-extension.)
1992     */
1993 dpavlin 12 if (cpu->is_32bit)
1994 dpavlin 2 int warning = 0;
1995     uint64_t x;
1996    
1997     if (cpu->cd.mips.gpr[0] != 0) {
1998     fatal("\nWARNING: r0 was not zero! (%016llx)\n\n",
1999     (long long)cpu->cd.mips.gpr[0]);
2000     cpu->cd.mips.gpr[0] = 0;
2001     warning = 1;
2002     }
2003    
2004     if (cpu->pc != (int64_t)(int32_t)cpu->pc) {
2005     fatal("\nWARNING: pc was not sign-extended correctly"
2006     " (%016llx)\n\n", (long long)cpu->pc);
2007     cpu->pc = (int64_t)(int32_t)cpu->pc;
2008     warning = 1;
2009     }
2010    
2011     if (cpu->cd.mips.pc_last != (int64_t)(int32_t)cpu->cd.mips.pc_last) {
2012     fatal("\nWARNING: pc_last was not sign-extended correc"
2013     "tly (%016llx)\n\n", (long long)cpu->cd.mips.pc_last);
2014     cpu->cd.mips.pc_last = (int64_t)(int32_t)cpu->cd.mips.pc_last;
2015     warning = 1;
2016     }
2017    
2018     /* Sign-extend ALL registers, including coprocessor registers and tlbs: */
2019     for (i=1; i<32; i++) {
2020     x = cpu->cd.mips.gpr[i];
2021     cpu->cd.mips.gpr[i] &= 0xffffffff;
2022     if (cpu->cd.mips.gpr[i] & 0x80000000ULL)
2023     cpu->cd.mips.gpr[i] |= 0xffffffff00000000ULL;
2024     if (x != cpu->cd.mips.gpr[i]) {
2025     fatal("\nWARNING: r%i (%s) was not sign-"
2026     "extended correctly (%016llx != "
2027     "%016llx)\n\n", i, regname(cpu->machine, i),
2028     (long long)x, (long long)cpu->cd.mips.gpr[i]);
2029     warning = 1;
2030     }
2031     }
2032     for (i=0; i<32; i++) {
2033     x = cpu->cd.mips.coproc[0]->reg[i];
2034     cpu->cd.mips.coproc[0]->reg[i] &= 0xffffffffULL;
2035     if (cpu->cd.mips.coproc[0]->reg[i] & 0x80000000ULL)
2036     cpu->cd.mips.coproc[0]->reg[i] |=
2037     0xffffffff00000000ULL;
2038     if (x != cpu->cd.mips.coproc[0]->reg[i]) {
2039     fatal("\nWARNING: cop0,r%i was not sign-extended correctly (%016llx != %016llx)\n\n",
2040     i, (long long)x, (long long)cpu->cd.mips.coproc[0]->reg[i]);
2041     warning = 1;
2042     }
2043     }
2044     for (i=0; i<cpu->cd.mips.coproc[0]->nr_of_tlbs; i++) {
2045     x = cpu->cd.mips.coproc[0]->tlbs[i].hi;
2046     cpu->cd.mips.coproc[0]->tlbs[i].hi &= 0xffffffffULL;
2047     if (cpu->cd.mips.coproc[0]->tlbs[i].hi & 0x80000000ULL)
2048     cpu->cd.mips.coproc[0]->tlbs[i].hi |=
2049     0xffffffff00000000ULL;
2050     if (x != cpu->cd.mips.coproc[0]->tlbs[i].hi) {
2051     fatal("\nWARNING: tlb[%i].hi was not sign-extended correctly (%016llx != %016llx)\n\n",
2052     i, (long long)x, (long long)cpu->cd.mips.coproc[0]->tlbs[i].hi);
2053     warning = 1;
2054     }
2055    
2056     x = cpu->cd.mips.coproc[0]->tlbs[i].lo0;
2057     cpu->cd.mips.coproc[0]->tlbs[i].lo0 &= 0xffffffffULL;
2058     if (cpu->cd.mips.coproc[0]->tlbs[i].lo0 & 0x80000000ULL)
2059     cpu->cd.mips.coproc[0]->tlbs[i].lo0 |=
2060     0xffffffff00000000ULL;
2061     if (x != cpu->cd.mips.coproc[0]->tlbs[i].lo0) {
2062     fatal("\nWARNING: tlb[%i].lo0 was not sign-extended correctly (%016llx != %016llx)\n\n",
2063     i, (long long)x, (long long)cpu->cd.mips.coproc[0]->tlbs[i].lo0);
2064     warning = 1;
2065     }
2066     }
2067    
2068     if (warning) {
2069     fatal("Halting. pc = %016llx\n", (long long)cpu->pc);
2070     cpu->running = 0;
2071     }
2072     }
2073     #endif
2074    
2075     PREFETCH(cpu->cd.mips.pc_last_host_4k_page + (cached_pc & 0xfff));
2076    
2077     #ifdef HALT_IF_PC_ZERO
2078     /* Halt if PC = 0: */
2079     if (cached_pc == 0) {
2080     debug("cpu%i: pc=0, halting\n", cpu->cpu_id);
2081     cpu->running = 0;
2082     return 0;
2083     }
2084     #endif
2085    
2086     #ifdef BINTRANS
2087 dpavlin 4 if ((single_step || instruction_trace_cached)
2088 dpavlin 2 && cpu->machine->bintrans_enable)
2089     cpu->cd.mips.dont_run_next_bintrans = 1;
2090     #endif
2091    
2092     if (!quiet_mode_cached) {
2093     /* Dump CPU registers for debugging: */
2094     if (cpu->machine->register_dump) {
2095     debug("\n");
2096     mips_cpu_register_dump(cpu, 1, 0x1);
2097     }
2098 dpavlin 12 }
2099 dpavlin 2
2100 dpavlin 12 /* Trace tree: */
2101     if (cpu->machine->show_trace_tree && cpu->cd.mips.show_trace_delay > 0) {
2102     cpu->cd.mips.show_trace_delay --;
2103     if (cpu->cd.mips.show_trace_delay == 0)
2104     cpu_functioncall_trace(cpu, cpu->cd.mips.show_trace_addr);
2105 dpavlin 2 }
2106    
2107     #ifdef MFHILO_DELAY
2108     /* Decrease the MFHI/MFLO delays: */
2109     if (cpu->mfhi_delay > 0)
2110     cpu->mfhi_delay--;
2111     if (cpu->mflo_delay > 0)
2112     cpu->mflo_delay--;
2113     #endif
2114    
2115     /* Read an instruction from memory: */
2116     #ifdef ENABLE_MIPS16
2117     if (cpu->cd.mips.mips16 && (cached_pc & 1)) {
2118     /* 16-bit instruction word: */
2119     unsigned char instr16[2];
2120     int mips16_offset = 0;
2121    
2122     if (!cpu->memory_rw(cpu, cpu->mem, cached_pc ^ 1, &instr16[0],
2123     sizeof(instr16), MEM_READ, CACHE_INSTRUCTION))
2124     return 0;
2125    
2126     /* TODO: If Reverse-endian is set in the status cop0 register, and
2127     we are in usermode, then reverse endianness! */
2128    
2129     /* The rest of the code is written for little endian, so swap if necessary: */
2130     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2131     int tmp;
2132     tmp = instr16[0]; instr16[0] = instr16[1]; instr16[1] = tmp;
2133     }
2134    
2135     cpu->cd.mips.mips16_extend = 0;
2136    
2137     /*
2138     * Translate into 32-bit instruction, little endian (instr[3..0]):
2139     *
2140     * This ugly loop is necessary because if we would get an exception between
2141     * reading an extend instruction and the next instruction, and execution
2142     * continues on the second instruction, the extend data would be lost. So the
2143     * entire instruction (the two parts) need to be read in. If an exception is
2144     * caused, it will appear as if it was caused when reading the extend instruction.
2145     */
2146     while (mips16_to_32(cpu, instr16, instr) == 0) {
2147     if (instruction_trace_cached)
2148     debug("cpu%i @ %016llx: %02x%02x\t\t\textend\n",
2149     cpu->cpu_id, (cpu->cd.mips.pc_last ^ 1) + mips16_offset,
2150     instr16[1], instr16[0]);
2151    
2152     /* instruction with extend: */
2153     mips16_offset += 2;
2154     if (!cpu->memory_rw(cpu, cpu->mem, (cached_pc ^ 1) +
2155     mips16_offset, &instr16[0], sizeof(instr16),
2156     MEM_READ, CACHE_INSTRUCTION))
2157     return 0;
2158    
2159     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2160     int tmp;
2161     tmp = instr16[0]; instr16[0] = instr16[1]; instr16[1] = tmp;
2162     }
2163     }
2164    
2165     /* TODO: bintrans like in 32-bit mode? */
2166    
2167     /* Advance the program counter: */
2168     cpu->pc += sizeof(instr16) + mips16_offset;
2169     cached_pc = cpu->pc;
2170    
2171     if (instruction_trace_cached) {
2172     uint64_t offset;
2173     char *symbol = get_symbol_name(&cpu->machine->
2174     symbol_context, cpu->cd.mips.pc_last ^ 1, &offset);
2175     if (symbol != NULL && offset==0)
2176     debug("<%s>\n", symbol);
2177    
2178     debug("cpu%i @ %016llx: %02x%02x => %02x%02x%02x%02x%s\t",
2179     cpu->cpu_id, (cpu->cd.mips.pc_last ^ 1) + mips16_offset,
2180     instr16[1], instr16[0],
2181     instr[3], instr[2], instr[1], instr[0],
2182     cpu_flags(cpu));
2183     }
2184     } else
2185     #endif
2186     {
2187     /*
2188     * Fetch a 32-bit instruction word from memory:
2189     *
2190     * 1) The special case of reading an instruction from the
2191     * same host RAM page as the last one is handled here,
2192     * to gain a little bit performance.
2193     *
2194     * 2) Fallback to reading from memory the usual way.
2195     */
2196     if (cpu->cd.mips.pc_last_host_4k_page != NULL &&
2197     (cached_pc & ~0xfff) == cpu->cd.mips.pc_last_virtual_page) {
2198     /* NOTE: This only works on the host if offset is
2199     aligned correctly! (TODO) */
2200     *(uint32_t *)instr = *(uint32_t *)
2201 dpavlin 12 (cpu->cd.mips.pc_last_host_4k_page + (cached_pc & 0xffc));
2202 dpavlin 2 #ifdef BINTRANS
2203     cpu->cd.mips.pc_bintrans_paddr_valid = 1;
2204     cpu->cd.mips.pc_bintrans_paddr =
2205     cpu->cd.mips.pc_last_physical_page | (cached_pc & 0xfff);
2206     cpu->cd.mips.pc_bintrans_host_4kpage = cpu->cd.mips.pc_last_host_4k_page;
2207     #endif
2208     } else {
2209     if (!cpu->memory_rw(cpu, cpu->mem, cached_pc, &instr[0],
2210     sizeof(instr), MEM_READ, CACHE_INSTRUCTION))
2211     return 0;
2212     }
2213    
2214     #ifdef BINTRANS
2215     if (cpu->cd.mips.dont_run_next_bintrans) {
2216     cpu->cd.mips.dont_run_next_bintrans = 0;
2217     } else if (cpu->machine->bintrans_enable &&
2218     cpu->cd.mips.pc_bintrans_paddr_valid) {
2219     int res;
2220     cpu->cd.mips.bintrans_instructions_executed = 0;
2221    
2222     res = bintrans_attempt_translate(cpu,
2223     cpu->cd.mips.pc_bintrans_paddr);
2224    
2225     if (res >= 0) {
2226     /* debug("BINTRANS translation + hit,"
2227     " pc = %016llx\n", (long long)cached_pc); */
2228     if (res > 0 || cpu->pc != cached_pc) {
2229     if (instruction_trace_cached)
2230     mips_cpu_disassemble_instr(cpu, instr, 1, 0, 1);
2231     if (res & BINTRANS_DONT_RUN_NEXT)
2232     cpu->cd.mips.dont_run_next_bintrans = 1;
2233     res &= BINTRANS_N_MASK;
2234    
2235     if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
2236     int x = cp0->reg[COP0_COUNT], y = cp0->reg[COP0_COMPARE];
2237     int diff = x - y;
2238     if (diff < 0 && diff + (res-1) >= 0
2239     && cpu->cd.mips.compare_register_set) {
2240     mips_cpu_interrupt(cpu, 7);
2241     cpu->cd.mips.compare_register_set = 0;
2242     }
2243    
2244     cp0->reg[COP0_COUNT] = (int64_t)
2245     (int32_t)(cp0->reg[COP0_COUNT] + res-1);
2246     }
2247    
2248     return res;
2249     }
2250     }
2251     }
2252     #endif
2253    
2254     if (instruction_trace_cached)
2255     mips_cpu_disassemble_instr(cpu, instr, 1, 0, 0);
2256    
2257     /* Advance the program counter: */
2258     cpu->pc += sizeof(instr);
2259     cached_pc = cpu->pc;
2260    
2261     /*
2262     * TODO: If Reverse-endian is set in the status cop0 register
2263     * and we are in usermode, then reverse endianness!
2264     */
2265    
2266     /*
2267     * The rest of the code is written for little endian, so
2268     * swap if necessary:
2269     */
2270     if (cpu->byte_order == EMUL_BIG_ENDIAN) {
2271 dpavlin 12 int tmp = instr[0]; instr[0] = instr[3]; instr[3] = tmp;
2272     tmp = instr[1]; instr[1] = instr[2]; instr[2] = tmp;
2273 dpavlin 2 }
2274     }
2275    
2276    
2277     /*
2278     * Nullify this instruction? (Set by a previous branch-likely
2279     * instruction.)
2280     *
2281     * Note: The return value is 1, even if no instruction was actually
2282     * executed.
2283     */
2284     if (cpu->cd.mips.nullify_next) {
2285     cpu->cd.mips.nullify_next = 0;
2286     return 1;
2287     }
2288    
2289    
2290     /*
2291     * Execute the instruction:
2292     */
2293    
2294     /* Get the top 6 bits of the instruction: */
2295     hi6 = instr[3] >> 2; /* & 0x3f */
2296    
2297     if (show_opcode_statistics)
2298     cpu->cd.mips.stats_opcode[hi6] ++;
2299    
2300     switch (hi6) {
2301     case HI6_SPECIAL:
2302     special6 = instr[0] & 0x3f;
2303    
2304     if (show_opcode_statistics)
2305     cpu->cd.mips.stats__special[special6] ++;
2306    
2307     switch (special6) {
2308     case SPECIAL_SLL:
2309     case SPECIAL_SRL:
2310     case SPECIAL_SRA:
2311     case SPECIAL_DSLL:
2312     case SPECIAL_DSRL:
2313     case SPECIAL_DSRA:
2314     case SPECIAL_DSLL32:
2315     case SPECIAL_DSRL32:
2316     case SPECIAL_DSRA32:
2317     rt = instr[2] & 31;
2318     rd = (instr[1] >> 3) & 31;
2319     sa = ((instr[1] & 7) << 2) + ((instr[0] >> 6) & 3);
2320    
2321     /*
2322     * Check for NOP:
2323     *
2324     * The R4000 manual says that a shift amount of zero
2325     * is treated as a nop by some assemblers. Checking
2326     * for sa == 0 here would not be correct, though,
2327     * because instructions such as sll r3,r4,0 are
2328     * possible, and are definitely not a nop.
2329     * Instead, check if the destination register is r0.
2330     *
2331     * TODO: ssnop should wait until the _next_
2332     * cycle boundary, or something like that. The
2333     * code here is incorrect.
2334     */
2335     if (rd == 0 && special6 == SPECIAL_SLL) {
2336     if (sa == 1) {
2337     /* ssnop */
2338     #ifdef ENABLE_INSTRUCTION_DELAYS
2339     cpu->cd.mips.instruction_delay +=
2340     cpu->cd.mips.cpu_type.
2341     instrs_per_cycle - 1;
2342     #endif
2343     }
2344     return 1;
2345     }
2346    
2347     if (special6 == SPECIAL_SLL) {
2348     switch (sa) {
2349     case 8: cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << 8; break;
2350     case 16:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << 16; break;
2351     default:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << sa;
2352     }
2353     /* Sign-extend rd: */
2354     cpu->cd.mips.gpr[rd] = (int64_t) (int32_t) cpu->cd.mips.gpr[rd];
2355     }
2356     if (special6 == SPECIAL_DSLL) {
2357     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << sa;
2358     }
2359     if (special6 == SPECIAL_DSRL) {
2360     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2361     }
2362     if (special6 == SPECIAL_DSLL32) {
2363     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] << (sa + 32);
2364     }
2365     if (special6 == SPECIAL_SRL) {
2366     /*
2367     * Three cases:
2368     * shift amount = zero: just copy
2369     * high bit of rt zero: plain shift right (of all bits)
2370     * high bit of rt one: plain shift right (of lowest 32 bits)
2371     */
2372     if (sa == 0)
2373     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2374     else if (!(cpu->cd.mips.gpr[rt] & 0x80000000ULL)) {
2375     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2376     } else
2377     cpu->cd.mips.gpr[rd] = (cpu->cd.mips.gpr[rt] & 0xffffffffULL) >> sa;
2378     }
2379     if (special6 == SPECIAL_SRA) {
2380     int topbit = cpu->cd.mips.gpr[rt] & 0x80000000ULL;
2381     switch (sa) {
2382     case 8: cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> 8; break;
2383     case 16:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> 16; break;
2384     default:cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2385     }
2386     if (topbit)
2387     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2388     }
2389     if (special6 == SPECIAL_DSRL32) {
2390     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> (sa + 32);
2391     }
2392     if (special6 == SPECIAL_DSRA32 || special6 == SPECIAL_DSRA) {
2393     if (special6 == SPECIAL_DSRA32)
2394     sa += 32;
2395     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2396     while (sa > 0) {
2397     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2398     sa--;
2399     if (cpu->cd.mips.gpr[rd] & ((uint64_t)1 << 62)) /* old signbit */
2400     cpu->cd.mips.gpr[rd] |= ((uint64_t)1 << 63);
2401     }
2402     }
2403     return 1;
2404     case SPECIAL_DSRLV:
2405     case SPECIAL_DSRAV:
2406     case SPECIAL_DSLLV:
2407     case SPECIAL_SLLV:
2408     case SPECIAL_SRAV:
2409     case SPECIAL_SRLV:
2410     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2411     rt = instr[2] & 31;
2412     rd = (instr[1] >> 3) & 31;
2413    
2414     if (special6 == SPECIAL_DSRLV) {
2415     sa = cpu->cd.mips.gpr[rs] & 63;
2416     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt] >> sa;
2417     }
2418     if (special6 == SPECIAL_DSRAV) {
2419     sa = cpu->cd.mips.gpr[rs] & 63;
2420     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2421     while (sa > 0) {
2422     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2423     sa--;
2424     if (cpu->cd.mips.gpr[rd] & ((uint64_t)1 << 62)) /* old sign-bit */
2425     cpu->cd.mips.gpr[rd] |= ((uint64_t)1 << 63);
2426     }
2427     }
2428     if (special6 == SPECIAL_DSLLV) {
2429     sa = cpu->cd.mips.gpr[rs] & 63;
2430     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2431     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] << sa;
2432     }
2433     if (special6 == SPECIAL_SLLV) {
2434     sa = cpu->cd.mips.gpr[rs] & 31;
2435     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2436     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] << sa;
2437     /* Sign-extend rd: */
2438     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2439     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2440     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2441     }
2442     if (special6 == SPECIAL_SRAV) {
2443     sa = cpu->cd.mips.gpr[rs] & 31;
2444     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2445     /* Sign-extend rd: */
2446     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2447     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2448     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2449     while (sa > 0) {
2450     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> 1;
2451     sa--;
2452     }
2453     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2454     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2455     }
2456     if (special6 == SPECIAL_SRLV) {
2457     sa = cpu->cd.mips.gpr[rs] & 31;
2458     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rt];
2459     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2460     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rd] >> sa;
2461     /* And finally sign-extend rd: */
2462     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2463     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2464     }
2465     return 1;
2466     case SPECIAL_JR:
2467     if (cpu->cd.mips.delay_slot) {
2468     fatal("jr: jump inside a jump's delay slot, or similar. TODO\n");
2469     cpu->running = 0;
2470     return 1;
2471     }
2472    
2473     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2474    
2475     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
2476     cpu->cd.mips.delay_jmpaddr = cpu->cd.mips.gpr[rs];
2477    
2478 dpavlin 12 if (cpu->machine->show_trace_tree && rs == 31)
2479     cpu_functioncall_trace_return(cpu);
2480 dpavlin 2
2481     return 1;
2482     case SPECIAL_JALR:
2483     if (cpu->cd.mips.delay_slot) {
2484     fatal("jalr: jump inside a jump's delay slot, or similar. TODO\n");
2485     cpu->running = 0;
2486     return 1;
2487     }
2488    
2489     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2490     rd = (instr[1] >> 3) & 31;
2491    
2492     tmpvalue = cpu->cd.mips.gpr[rs];
2493     cpu->cd.mips.gpr[rd] = cached_pc + 4;
2494     /* already increased by 4 earlier */
2495    
2496 dpavlin 12 if (cpu->machine->show_trace_tree && rd == 31) {
2497 dpavlin 2 cpu->cd.mips.show_trace_delay = 2;
2498     cpu->cd.mips.show_trace_addr = tmpvalue;
2499     }
2500    
2501     cpu->cd.mips.delay_slot = TO_BE_DELAYED;
2502     cpu->cd.mips.delay_jmpaddr = tmpvalue;
2503     return 1;
2504     case SPECIAL_MFHI:
2505     case SPECIAL_MFLO:
2506     rd = (instr[1] >> 3) & 31;
2507    
2508     if (special6 == SPECIAL_MFHI) {
2509     cpu->cd.mips.gpr[rd] = cpu->cd.mips.hi;
2510     #ifdef MFHILO_DELAY
2511     cpu->mfhi_delay = 3;
2512     #endif
2513     }
2514     if (special6 == SPECIAL_MFLO) {
2515     cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
2516     #ifdef MFHILO_DELAY
2517     cpu->mflo_delay = 3;
2518     #endif
2519     }
2520     return 1;
2521     case SPECIAL_ADD:
2522     case SPECIAL_ADDU:
2523     case SPECIAL_SUB:
2524     case SPECIAL_SUBU:
2525     case SPECIAL_AND:
2526     case SPECIAL_OR:
2527     case SPECIAL_XOR:
2528     case SPECIAL_NOR:
2529     case SPECIAL_SLT:
2530     case SPECIAL_SLTU:
2531     case SPECIAL_MTLO:
2532     case SPECIAL_MTHI:
2533     case SPECIAL_MULT:
2534     case SPECIAL_MULTU:
2535     case SPECIAL_DMULT:
2536     case SPECIAL_DMULTU:
2537     case SPECIAL_DIV:
2538     case SPECIAL_DIVU:
2539     case SPECIAL_DDIV:
2540     case SPECIAL_DDIVU:
2541     case SPECIAL_TGE:
2542     case SPECIAL_TGEU:
2543     case SPECIAL_TLT:
2544     case SPECIAL_TLTU:
2545     case SPECIAL_TEQ:
2546     case SPECIAL_TNE:
2547     case SPECIAL_DADD:
2548     case SPECIAL_DADDU:
2549     case SPECIAL_DSUB:
2550     case SPECIAL_DSUBU:
2551     case SPECIAL_MOVZ:
2552     case SPECIAL_MOVN:
2553     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
2554     rt = instr[2] & 31;
2555     rd = (instr[1] >> 3) & 31;
2556    
2557     #ifdef MFHILO_DELAY
2558     if (cpu->mflo_delay > 0 && (
2559     special6 == SPECIAL_DDIV || special6 == SPECIAL_DDIVU ||
2560     special6 == SPECIAL_DIV || special6 == SPECIAL_DIVU ||
2561     special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU ||
2562     special6 == SPECIAL_MTLO || special6 == SPECIAL_MULT
2563     || special6 == SPECIAL_MULTU
2564     ) )
2565     debug("warning: instruction modifying LO too early after mflo!\n");
2566    
2567     if (cpu->mfhi_delay > 0 && (
2568     special6 == SPECIAL_DDIV || special6 == SPECIAL_DDIVU ||
2569     special6 == SPECIAL_DIV || special6 == SPECIAL_DIVU ||
2570     special6 == SPECIAL_DMULT || special6 == SPECIAL_DMULTU ||
2571     special6 == SPECIAL_MTHI || special6 == SPECIAL_MULT
2572     || special6 == SPECIAL_MULTU
2573     ) )
2574     debug("warning: instruction modifying HI too early after mfhi!\n");
2575     #endif
2576    
2577     if (special6 == SPECIAL_ADDU) {
2578     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] + cpu->cd.mips.gpr[rt];
2579     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2580     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2581     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2582     break;
2583     }
2584     if (special6 == SPECIAL_ADD) {
2585     /* According to the MIPS64 manual: */
2586     uint64_t temp, temp1, temp2;
2587     temp1 = cpu->cd.mips.gpr[rs] + ((cpu->cd.mips.gpr[rs] & 0x80000000ULL) << 1);
2588     temp2 = cpu->cd.mips.gpr[rt] + ((cpu->cd.mips.gpr[rt] & 0x80000000ULL) << 1);
2589     temp = temp1 + temp2;
2590     #if 0
2591     /* TODO: apparently this doesn't work (an example of
2592     something that breaks is NetBSD/sgimips' mips3_TBIA() */
2593     /* If bits 32 and 31 of temp differ, then it's an overflow */
2594     temp1 = temp & 0x100000000ULL;
2595     temp2 = temp & 0x80000000ULL;
2596     if ((temp1 && !temp2) || (!temp1 && temp2)) {
2597     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
2598     break;
2599     }
2600     #endif
2601     cpu->cd.mips.gpr[rd] = temp & 0xffffffffULL;
2602     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2603     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2604     break;
2605     }
2606     if (special6 == SPECIAL_SUBU) {
2607     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] - cpu->cd.mips.gpr[rt];
2608     cpu->cd.mips.gpr[rd] &= 0xffffffffULL;
2609     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2610     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2611     break;
2612     }
2613     if (special6 == SPECIAL_SUB) {
2614     /* According to the MIPS64 manual: */
2615     uint64_t temp, temp1, temp2;
2616     temp1 = cpu->cd.mips.gpr[rs] + ((cpu->cd.mips.gpr[rs] & 0x80000000ULL) << 1);
2617     temp2 = cpu->cd.mips.gpr[rt] + ((cpu->cd.mips.gpr[rt] & 0x80000000ULL) << 1);
2618     temp = temp1 - temp2;
2619     #if 0
2620     /* If bits 32 and 31 of temp differ, then it's an overflow */
2621     temp1 = temp & 0x100000000ULL;
2622     temp2 = temp & 0x80000000ULL;
2623     if ((temp1 && !temp2) || (!temp1 && temp2)) {
2624     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
2625     break;
2626     }
2627     #endif
2628     cpu->cd.mips.gpr[rd] = temp & 0xffffffffULL;
2629     if (cpu->cd.mips.gpr[rd] & 0x80000000ULL)
2630     cpu->cd.mips.gpr[rd] |= 0xffffffff00000000ULL;
2631     break;
2632     }
2633    
2634     if (special6 == SPECIAL_AND) {
2635     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] & cpu->cd.mips.gpr[rt];
2636     break;
2637     }
2638     if (special6 == SPECIAL_OR) {
2639     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt];
2640     break;
2641     }
2642     if (special6 == SPECIAL_XOR) {
2643     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] ^ cpu->cd.mips.gpr[rt];
2644     break;
2645     }
2646     if (special6 == SPECIAL_NOR) {
2647     cpu->cd.mips.gpr[rd] = ~(cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt]);
2648     break;
2649     }
2650     if (special6 == SPECIAL_SLT) {
2651     cpu->cd.mips.gpr[rd] = (int64_t)cpu->cd.mips.gpr[rs] < (int64_t)cpu->cd.mips.gpr[rt];
2652     break;
2653     }
2654     if (special6 == SPECIAL_SLTU) {
2655     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] < cpu->cd.mips.gpr[rt];
2656     break;
2657     }
2658     if (special6 == SPECIAL_MTLO) {
2659     cpu->cd.mips.lo = cpu->cd.mips.gpr[rs];
2660     break;
2661     }
2662     if (special6 == SPECIAL_MTHI) {
2663     cpu->cd.mips.hi = cpu->cd.mips.gpr[rs];
2664     break;
2665     }
2666     if (special6 == SPECIAL_MULT) {
2667     int64_t f1, f2, sum;
2668     f1 = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2669     /* sign extend f1 */
2670     if (f1 & 0x80000000ULL)
2671     f1 |= 0xffffffff00000000ULL;
2672     f2 = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2673     /* sign extend f2 */
2674     if (f2 & 0x80000000ULL)
2675     f2 |= 0xffffffff00000000ULL;
2676     sum = f1 * f2;
2677    
2678     cpu->cd.mips.lo = sum & 0xffffffffULL;
2679     cpu->cd.mips.hi = ((uint64_t)sum >> 32) & 0xffffffffULL;
2680    
2681     /* sign-extend: */
2682     if (cpu->cd.mips.lo & 0x80000000ULL)
2683     cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2684     if (cpu->cd.mips.hi & 0x80000000ULL)
2685     cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2686    
2687     /*
2688     * NOTE: The stuff about rd!=0 is just a
2689     * guess, judging from how some NetBSD code
2690     * seems to execute. It is not documented in
2691     * the MIPS64 ISA docs :-/
2692     */
2693    
2694     if (rd != 0) {
2695     if (cpu->cd.mips.cpu_type.rev != MIPS_R5900)
2696     debug("WARNING! mult_xx is an undocumented instruction!");
2697     cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
2698     }
2699     break;
2700     }
2701     if (special6 == SPECIAL_MULTU) {
2702     uint64_t f1, f2, sum;
2703     /* zero extend f1 and f2 */
2704     f1 = cpu->cd.mips.gpr[rs] & 0xffffffffULL;
2705     f2 = cpu->cd.mips.gpr[rt] & 0xffffffffULL;
2706     sum = f1 * f2;
2707     cpu->cd.mips.lo = sum & 0xffffffffULL;
2708     cpu->cd.mips.hi = (sum >> 32) & 0xffffffffULL;
2709    
2710     /* sign-extend: */
2711     if (cpu->cd.mips.lo & 0x80000000ULL)
2712     cpu->cd.mips.lo |= 0xffffffff00000000ULL;
2713     if (cpu->cd.mips.hi & 0x80000000ULL)
2714     cpu->cd.mips.hi |= 0xffffffff00000000ULL;
2715     break;
2716     }
2717 dpavlin 12 if (special6 == SPECIAL_DMULT) {
2718     /* 64x64 = 128 bit multiplication, signed. */
2719     uint64_t s1 = cpu->cd.mips.gpr[rt];
2720     uint64_t s2 = cpu->cd.mips.gpr[rs];
2721     int n_negative = 0;
2722     int i;
2723 dpavlin 2
2724 dpavlin 12 if ((int64_t)s1 < 0) {
2725     s1 = -(int64_t)s1;
2726     n_negative ++;
2727     }
2728     if ((int64_t)s2 < 0) {
2729     s2 = -(int64_t)s2;
2730     n_negative ++;
2731     }
2732    
2733 dpavlin 2 cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2734 dpavlin 12
2735 dpavlin 2 for (i=0; i<64; i++) {
2736 dpavlin 12 int bit = (s1 & 0x8000000000000000ULL)? 1 : 0;
2737     s1 <<= 1;
2738     /* If bit in s1 set, then add s2 to hi/lo: */
2739 dpavlin 2 if (bit) {
2740 dpavlin 12 uint64_t old_lo = cpu->cd.mips.lo;
2741     cpu->cd.mips.lo += s2;
2742     if (cpu->cd.mips.lo < old_lo)
2743 dpavlin 2 cpu->cd.mips.hi ++;
2744     }
2745 dpavlin 12 if (i != 63) {
2746     cpu->cd.mips.hi <<= 1;
2747     cpu->cd.mips.hi +=
2748     (cpu->cd.mips.lo & 0x8000000000000000ULL) ? 1 : 0;
2749     cpu->cd.mips.lo <<= 1;
2750     }
2751 dpavlin 2 }
2752 dpavlin 12
2753     if (n_negative == 1) {
2754     cpu->cd.mips.hi = -(int64_t)cpu->cd.mips.hi;
2755     cpu->cd.mips.lo = -(int64_t)cpu->cd.mips.lo;
2756     if ((int64_t)cpu->cd.mips.lo < 0)
2757     cpu->cd.mips.hi --;
2758     }
2759 dpavlin 2 break;
2760     }
2761 dpavlin 12 if (special6 == SPECIAL_DMULTU) {
2762     /* 64x64 = 128 bit multiplication, unsigned. */
2763     uint64_t s1 = cpu->cd.mips.gpr[rt];
2764     uint64_t s2 = cpu->cd.mips.gpr[rs];
2765     int i;
2766    
2767     cpu->cd.mips.lo = cpu->cd.mips.hi = 0;
2768    
2769     for (i=0; i<64; i++) {
2770     int bit = (s1 & 0x8000000000000000ULL)? 1 : 0;
2771     s1 <<= 1;
2772     /* If bit in s1 set, then add s2 to hi/lo: */
2773     if (bit) {
2774     uint64_t old_lo = cpu->cd.mips.lo;
2775     cpu->cd.mips.lo += s2;
2776     if (cpu->cd.mips.lo < old_lo)
2777     cpu->cd.mips.hi ++;
2778     }
2779     if (i != 63) {
2780     cpu->cd.mips.hi <<= 1;
2781     cpu->cd.mips.hi +=
2782     (cpu->cd.mips.lo & 0x8000000000000000ULL) ? 1 : 0;
2783     cpu->cd.mips.lo <<= 1;
2784     }
2785     }
2786     break;
2787     }
2788 dpavlin 2 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 dpavlin 12 /* imm = ((instr[1] & 7) << 2) + (instr[0] >> 6); */
2914 dpavlin 2 /* 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 dpavlin 12 /* R5900? Move from shift amount register? */
2935     /* rd = (instr[1] >> 3) & 31; */
2936 dpavlin 2 /* TODO */
2937     return 1;
2938     case SPECIAL_MTSA:
2939 dpavlin 12 /* R5900? Move to shift amount register? */
2940     /* rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7); */
2941 dpavlin 2 /* TODO */
2942     return 1;
2943     default:
2944     if (!instruction_trace_cached) {
2945     fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
2946 dpavlin 12 cpu->cpu_id, (long long)cpu->cd.mips.pc_last,
2947 dpavlin 2 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 dpavlin 10 cpu->cd.mips.coproc[cpnr], rt, &a, 0);
3363 dpavlin 2 coproc_register_read(cpu,
3364 dpavlin 10 cpu->cd.mips.coproc[cpnr], rt^1, &b, 0);
3365 dpavlin 2 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 dpavlin 10 coproc_register_read(cpu, cpu->cd.mips.coproc[cpnr], rt, &value, 0);
3371 dpavlin 2 }
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 dpavlin 10 hi6==HI6_LDC1 || hi6==HI6_LDC2, 0);
3508 dpavlin 2 coproc_register_write(cpu,
3509     cpu->cd.mips.coproc[cpnr], rt ^ 1, &b,
3510 dpavlin 10 hi6==HI6_LDC1 || hi6==HI6_LDC2, 0);
3511 dpavlin 2 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 dpavlin 10 hi6==HI6_LDC1 || hi6==HI6_LDC2, 0);
3517 dpavlin 2 }
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 dpavlin 12 cpu->cpu_id, (long long)cpu->cd.mips.pc_last,
3770 dpavlin 2 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 dpavlin 12 if (cpu->machine->show_trace_tree && hi6 == HI6_JAL) {
3797 dpavlin 2 cpu->cd.mips.show_trace_delay = 2;
3798     cpu->cd.mips.show_trace_addr = addr;
3799     }
3800    
3801     return 1;
3802     case HI6_COP0:
3803     case HI6_COP1:
3804     case HI6_COP2:
3805     case HI6_COP3:
3806     imm = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3807     imm &= ((1 << 26) - 1);
3808    
3809     cpnr = 0;
3810     if (hi6 == HI6_COP0) cpnr = 0;
3811     if (hi6 == HI6_COP1) cpnr = 1;
3812     if (hi6 == HI6_COP2) cpnr = 2;
3813     if (hi6 == HI6_COP3) cpnr = 3;
3814    
3815     /*
3816     * If there is no coprocessor nr cpnr, or we are running in
3817     * userland and the coprocessor is not marked as Useable in
3818     * the status register of CP0, then we get an exception.
3819     *
3820     * An exception (hehe) to this rule is that the kernel should
3821     * always be able to access CP0.
3822     */
3823     /* Set tmp = 1 if we're in user mode. */
3824     tmp = 0;
3825     switch (cpu->cd.mips.cpu_type.exc_model) {
3826     case EXC3K:
3827     /*
3828     * NOTE: If the KU bit is checked, Linux crashes.
3829     * It is the PC that counts. TODO: Check whether
3830     * this is true or not for R4000 as well.
3831     */
3832     if (cached_pc <= 0x7fffffff) /* if (cp0->reg[COP0_STATUS] & MIPS1_SR_KU_CUR) */
3833     tmp = 1;
3834     break;
3835     default:
3836     /* R4000 etc: (TODO: How about supervisor mode?) */
3837     if (((cp0->reg[COP0_STATUS] & STATUS_KSU_MASK) >> STATUS_KSU_SHIFT) != KSU_KERNEL)
3838     tmp = 1;
3839     if (cp0->reg[COP0_STATUS] & STATUS_ERL)
3840     tmp = 0;
3841     if (cp0->reg[COP0_STATUS] & STATUS_EXL)
3842     tmp = 0;
3843     break;
3844     }
3845     if (cpu->cd.mips.coproc[cpnr] == NULL ||
3846     (tmp && !(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT))) ||
3847     (!tmp && cpnr >= 1 && !(cp0->reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)))
3848     ) {
3849     if (instruction_trace_cached)
3850     debug("cop%i\t0x%08x => coprocessor unusable\n", cpnr, (int)imm);
3851    
3852     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
3853     } else {
3854     /*
3855     * Execute the coprocessor function. The
3856     * coproc_function code outputs instruction
3857     * trace, if necessary.
3858     */
3859     coproc_function(cpu, cpu->cd.mips.coproc[cpnr],
3860     cpnr, imm, 0, 1);
3861     }
3862     return 1;
3863     case HI6_CACHE:
3864     rt = ((instr[3] & 3) << 3) + (instr[2] >> 5); /* base */
3865     copz = instr[2] & 31;
3866     imm = (instr[1] << 8) + instr[0];
3867    
3868     cache_op = copz >> 2;
3869     which_cache = copz & 3;
3870    
3871     /*
3872     * TODO: The cache instruction is implementation dependant.
3873     */
3874    
3875     /*
3876     * Clear the LLbit (at least on R10000):
3877     * TODO: How about R4000?
3878     */
3879     cpu->cd.mips.rmw = 0;
3880    
3881     return 1;
3882     case HI6_SPECIAL2:
3883     special6 = instr[0] & 0x3f;
3884    
3885     if (show_opcode_statistics)
3886     cpu->cd.mips.stats__special2[special6] ++;
3887    
3888     instrword = (instr[3] << 24) + (instr[2] << 16) + (instr[1] << 8) + instr[0];
3889    
3890     rs = ((instr[3] & 3) << 3) + ((instr[2] >> 5) & 7);
3891     rt = instr[2] & 31;
3892     rd = (instr[1] >> 3) & 31;
3893    
3894     /* printf("special2 %08x rs=0x%02x rt=0x%02x rd=0x%02x\n", instrword, rs,rt,rd); */
3895    
3896     /*
3897     * Many of these can be found in the R5000 docs, or figured out
3898     * by studying binutils source code for MIPS instructions.
3899     */
3900    
3901     if ((instrword & 0xfc0007ffULL) == 0x70000000) {
3902     {
3903     int32_t a, b;
3904     int64_t c;
3905     a = (int32_t)cpu->cd.mips.gpr[rs];
3906     b = (int32_t)cpu->cd.mips.gpr[rt];
3907     c = a * b;
3908     c += (cpu->cd.mips.lo & 0xffffffffULL)
3909     + (cpu->cd.mips.hi << 32);
3910     cpu->cd.mips.lo = (int64_t)((int32_t)c);
3911     cpu->cd.mips.hi = (int64_t)((int32_t)(c >> 32));
3912    
3913     /*
3914     * The R5000 manual says that rd should be all zeros,
3915     * but it isn't on R5900. I'm just guessing here that
3916     * it stores the value in register rd, in addition to hi/lo.
3917     * TODO
3918     */
3919     if (rd != 0)
3920     cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
3921     }
3922     } else if ((instrword & 0xffff07ffULL) == 0x70000209
3923     || (instrword & 0xffff07ffULL) == 0x70000249) {
3924     /*
3925     * This is just a guess for R5900, I've not found any docs on this one yet.
3926     *
3927     * pmfhi/pmflo rd
3928     *
3929     * If the lowest 8 bits of the instruction word are 0x09, it's a pmfhi.
3930     * If the lowest bits are 0x49, it's a pmflo.
3931     *
3932     * A wild guess is that this is a 128-bit version of mfhi/mflo.
3933     * For now, this is implemented as 64-bit only. (TODO)
3934     */
3935     if (instr[0] == 0x49) {
3936     cpu->cd.mips.gpr[rd] = cpu->cd.mips.lo;
3937     } else {
3938     cpu->cd.mips.gpr[rd] = cpu->cd.mips.hi;
3939     }
3940     } else if ((instrword & 0xfc1fffff) == 0x70000269 || (instrword & 0xfc1fffff) == 0x70000229) {
3941     /*
3942     * This is just a guess for R5900, I've not found any docs on this one yet.
3943     *
3944     * pmthi/pmtlo rs (pmtlo = 269, pmthi = 229)
3945     *
3946     * A wild guess is that this is a 128-bit version of mthi/mtlo.
3947     * For now, this is implemented as 64-bit only. (TODO)
3948     */
3949     if (instr[0] == 0x69) {
3950     cpu->cd.mips.lo = cpu->cd.mips.gpr[rs];
3951     } else {
3952     cpu->cd.mips.hi = cpu->cd.mips.gpr[rs];
3953     }
3954     } else if ((instrword & 0xfc0007ff) == 0x700004a9) {
3955     /*
3956     * This is just a guess for R5900, I've not found any docs on this one yet.
3957     *
3958     * por dst,src,src2 ==> rs=src rt=src2 rd=dst
3959     *
3960     * A wild guess is that this is a 128-bit "or" between two registers.
3961     * For now, let's just or using 64-bits. (TODO)
3962     */
3963     cpu->cd.mips.gpr[rd] = cpu->cd.mips.gpr[rs] | cpu->cd.mips.gpr[rt];
3964     } else if ((instrword & 0xfc0007ff) == 0x70000488) {
3965     /*
3966     * R5900 "undocumented" pextlw. TODO: find out if this is correct.
3967     * It seems that this instruction is used to combine two 32-bit
3968     * words into a 64-bit dword, typically before a sd (store dword).
3969     */
3970     cpu->cd.mips.gpr[rd] =
3971     ((cpu->cd.mips.gpr[rs] & 0xffffffffULL) << 32) /* TODO: switch rt and rs? */
3972     | (cpu->cd.mips.gpr[rt] & 0xffffffffULL);
3973     } else if (special6 == SPECIAL2_MUL) {
3974     cpu->cd.mips.gpr[rd] = (int64_t)cpu->cd.mips.gpr[rt] *
3975     (int64_t)cpu->cd.mips.gpr[rs];
3976     } else if (special6 == SPECIAL2_CLZ) {
3977     /* clz: count leading zeroes */
3978     int i, n=0;
3979     for (i=31; i>=0; i--) {
3980     if (cpu->cd.mips.gpr[rs] & ((uint32_t)1 << i))
3981     break;
3982     else
3983     n++;
3984     }
3985     cpu->cd.mips.gpr[rd] = n;
3986     } else if (special6 == SPECIAL2_CLO) {
3987     /* clo: count leading ones */
3988     int i, n=0;
3989     for (i=31; i>=0; i--) {
3990     if (cpu->cd.mips.gpr[rs] & ((uint32_t)1 << i))
3991     n++;
3992     else
3993     break;
3994     }
3995     cpu->cd.mips.gpr[rd] = n;
3996     } else if (special6 == SPECIAL2_DCLZ) {
3997     /* dclz: count leading zeroes */
3998     int i, n=0;
3999     for (i=63; i>=0; i--) {
4000     if (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << i))
4001     break;
4002     else
4003     n++;
4004     }
4005     cpu->cd.mips.gpr[rd] = n;
4006     } else if (special6 == SPECIAL2_DCLO) {
4007     /* dclo: count leading ones */
4008     int i, n=0;
4009     for (i=63; i>=0; i--) {
4010     if (cpu->cd.mips.gpr[rs] & ((uint64_t)1 << i))
4011     n++;
4012     else
4013     break;
4014     }
4015     cpu->cd.mips.gpr[rd] = n;
4016     } else {
4017     if (!instruction_trace_cached) {
4018     fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
4019 dpavlin 12 cpu->cpu_id, (long long)cpu->cd.mips.pc_last,
4020 dpavlin 2 instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
4021     }
4022     fatal("unimplemented special_2 = 0x%02x, rs=0x%02x rt=0x%02x rd=0x%02x\n",
4023     special6, rs, rt, rd);
4024     cpu->running = 0;
4025     return 1;
4026     }
4027     return 1;
4028     default:
4029     if (!instruction_trace_cached) {
4030     fatal("cpu%i @ %016llx: %02x%02x%02x%02x%s\t",
4031 dpavlin 12 cpu->cpu_id, (long long)cpu->cd.mips.pc_last,
4032 dpavlin 2 instr[3], instr[2], instr[1], instr[0], cpu_flags(cpu));
4033     }
4034     fatal("unimplemented hi6 = 0x%02x\n", hi6);
4035     cpu->running = 0;
4036     return 1;
4037     }
4038    
4039     /* NOTREACHED */
4040     }
4041    
4042    
4043     #define CPU_RUN mips_cpu_run
4044     #define CPU_RUN_MIPS
4045     #define CPU_RINSTR mips_cpu_run_instr
4046     #include "cpu_run.c"
4047     #undef CPU_RINSTR
4048     #undef CPU_RUN_MIPS
4049     #undef CPU_RUN
4050    
4051    
4052     /*
4053     * mips_cpu_dumpinfo():
4054     *
4055     * Debug dump of MIPS-specific CPU data for specific CPU.
4056     */
4057     void mips_cpu_dumpinfo(struct cpu *cpu)
4058     {
4059 dpavlin 12 int iadd = 4;
4060 dpavlin 2 struct mips_cpu_type_def *ct = &cpu->cd.mips.cpu_type;
4061    
4062 dpavlin 12 debug_indentation(iadd);
4063 dpavlin 2
4064 dpavlin 12 debug("\n%i-bit %s (MIPS",
4065     cpu->is_32bit? 32 : 64,
4066     cpu->byte_order == EMUL_BIG_ENDIAN? "BE" : "LE");
4067 dpavlin 2
4068 dpavlin 12 switch (ct->isa_level) {
4069     case 1: debug(" ISA I"); break;
4070     case 2: debug(" ISA II"); break;
4071     case 3: debug(" ISA III"); break;
4072     case 4: debug(" ISA IV"); break;
4073     case 5: debug(" ISA V"); break;
4074     case 32:
4075     case 64:debug("%i", ct->isa_level); break;
4076     default:debug(" ISA level %i", ct->isa_level);
4077     }
4078 dpavlin 2
4079 dpavlin 12 debug("), ");
4080     if (ct->nr_of_tlb_entries)
4081     debug("%i TLB entries", ct->nr_of_tlb_entries);
4082     else
4083     debug("no TLB");
4084     debug("\n");
4085 dpavlin 2
4086 dpavlin 12 if (ct->picache) {
4087     debug("L1 I-cache: %i KB", (1 << ct->picache) / 1024);
4088     if (ct->pilinesize)
4089     debug(", %i bytes per line", 1 << ct->pilinesize);
4090     if (ct->piways > 1)
4091     debug(", %i-way", ct->piways);
4092     else
4093     debug(", direct-mapped");
4094     debug("\n");
4095 dpavlin 2 }
4096    
4097 dpavlin 12 if (ct->pdcache) {
4098     debug("L1 D-cache: %i KB", (1 << ct->pdcache) / 1024);
4099     if (ct->pdlinesize)
4100     debug(", %i bytes per line", 1 << ct->pdlinesize);
4101     if (ct->pdways > 1)
4102     debug(", %i-way", ct->pdways);
4103     else
4104     debug(", direct-mapped");
4105     debug("\n");
4106     }
4107    
4108     if (ct->scache) {
4109     int kb = (1 << ct->scache) / 1024;
4110     debug("L2 cache: %i %s",
4111     kb >= 1024? kb / 1024 : kb, kb >= 1024? "MB":"KB");
4112     if (ct->slinesize)
4113     debug(", %i bytes per line", 1 << ct->slinesize);
4114     if (ct->sways > 1)
4115     debug(", %i-way", ct->sways);
4116     else
4117     debug(", direct-mapped");
4118     debug("\n");
4119     }
4120    
4121     debug_indentation(-iadd);
4122 dpavlin 2 }
4123    
4124    
4125     /*
4126     * mips_cpu_list_available_types():
4127     *
4128     * Print a list of available MIPS CPU types.
4129     */
4130     void mips_cpu_list_available_types(void)
4131     {
4132     int i, j;
4133     struct mips_cpu_type_def cpu_type_defs[] = MIPS_CPU_TYPE_DEFS;
4134    
4135     i = 0;
4136     while (cpu_type_defs[i].name != NULL) {
4137     debug("%s", cpu_type_defs[i].name);
4138     for (j=10 - strlen(cpu_type_defs[i].name); j>0; j--)
4139     debug(" ");
4140     i++;
4141     if ((i % 6) == 0 || cpu_type_defs[i].name == NULL)
4142     debug("\n");
4143     }
4144     }
4145    
4146    
4147 dpavlin 12 CPU_FAMILY_INIT(mips,"MIPS")
4148 dpavlin 2
4149    
4150     #endif /* ENABLE_MIPS */

  ViewVC Help
Powered by ViewVC 1.1.26