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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 24 - (hide annotations)
Mon Oct 8 16:19:56 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 93793 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1256 2006/06/23 20:43:44 debug Exp $
20060219	Various minor updates. Removing the old MIPS16 skeleton code,
		because it will need to be rewritten for dyntrans anyway.
20060220-22	Removing the non-working dyntrans backend support.
		Continuing on the 64-bit dyntrans virtual memory generalization.
20060223	More work on the 64-bit vm generalization.
20060225	Beginning on MIPS dyntrans load/store instructions.
		Minor PPC updates (64-bit load/store, etc).
		Fixes for the variable-instruction-length framework, some
		minor AVR updates (a simple Hello World program works!).
		Beginning on a skeleton for automatically generating documen-
		tation (for devices etc.).
20060226	PPC updates (adding some more 64-bit instructions, etc).
		AVR updates (more instructions).
		FINALLY found and fixed the zs bug, making NetBSD/macppc
		accept the serial console.
20060301	Adding more AVR instructions.
20060304	Continuing on AVR-related stuff. Beginning on a framework for
		cycle-accurate device emulation. Adding an experimental "PAL
		TV" device (just a dummy so far).
20060305	Adding more AVR instructions.
		Adding a dummy epcom serial controller (for TS7200 emulation).
20060310	Removing the emul() command from configuration files, so only
		net() and machine() are supported.
		Minor progress on the MIPS dyntrans rewrite.
20060311	Continuing on the MIPS dyntrans rewrite (adding more
		instructions, etc).
20060315	Adding more instructions (sllv, srav, srlv, bgtz[l], blez[l],
		beql, bnel, slti[u], various loads and stores).
20060316	Removing the ALWAYS_SIGNEXTEND_32 option, since it was rarely
		used.
		Adding more MIPS dyntrans instructions, and fixing bugs.
20060318	Implementing fast loads/stores for MIPS dyntrans (big/little
		endian, 32-bit and 64-bit modes).
20060320	Making MIPS dyntrans the default configure option; use
		"--enable-oldmips" to use the old bintrans system.
		Adding MIPS dyntrans dmult[u]; minor updates.
20060322	Continuing... adding some more instructions.
		Adding a simple skeleton for demangling C++ "_ZN" symbols.
20060323	Moving src/debugger.c into a new directory (src/debugger/).
20060324	Fixing the hack used to load PPC ELFs (useful for relocated
		Linux/ppc kernels), and adding a dummy G3 machine mode.
20060325-26	Beginning to experiment with GDB remote serial protocol
		connections; adding a -G command line option for selecting
		which TCP port to listen to.
20060330	Beginning a major cleanup to replace things like "0x%016llx"
		with more correct "0x%016"PRIx64, etc.
		Continuing on the GDB remote serial protocol support.
20060331	More cleanup, and some minor GDB remote progress.
20060402	Adding a hack to the configure script, to allow compilation
		on systems that lack PRIx64 etc.
20060406	Removing the temporary FreeBSD/arm hack in dev_ns16550.c and
		replacing it with a better fix from Olivier Houchard.
20060407	A remote debugger (gdb or ddd) can now start and stop the
		emulator using the GDB remote serial protocol, and registers
		and memory can be read. MIPS only for now.
20060408	More GDB progress: single-stepping also works, and also adding
		support for ARM, PowerPC, and Alpha targets.
		Continuing on the delay-slot-across-page-boundary issue.
20060412	Minor update: beginning to add support for the SPARC target
		to the remote GDB functionality.
20060414	Various MIPS updates: adding more instructions for dyntrans
		(eret, add), and making some exceptions work. Fixing a bug
		in dmult[u].
		Implementing the first SPARC instructions (sethi, or).
20060415	Adding "magic trap" instructions so that PROM calls can be
		software emulated in MIPS dyntrans.
		Adding more MIPS dyntrans instructions (ddiv, dadd) and
		fixing another bug in dmult.
20060416	More MIPS dyntrans progress: adding [d]addi, movn, movz, dsllv,
		rfi, an ugly hack for supporting R2000/R3000 style faked caches,
		preliminary interrupt support, and various other updates and
		bugfixes.
20060417	Adding more SPARC instructions (add, sub, sll[x], sra[x],
		srl[x]), and useful SPARC header definitions.
		Adding the first (trivial) x86/AMD64 dyntrans instructions (nop,
		cli/sti, stc/clc, std/cld, simple mov, inc ax). Various other
		x86 updates related to variable instruction length stuff.
		Adding unaligned loads/stores to the MIPS dyntrans mode (but
		still using the pre-dyntrans (slow) imlementation).
20060419	Fixing a MIPS dyntrans exception-in-delay-slot bug.
		Removing the old "show opcode statistics" functionality, since
		it wasn't really useful and isn't implemented for dyntrans.
		Single-stepping (or running with instruction trace) now looks
		ok with dyntrans with delay-slot architectures.
20060420	Minor hacks (removing the -B command line option when compiled
		for non-bintrans, and some other very minor updates).
		Adding (slow) MIPS dyntrans load-linked/store-conditional.
20060422	Applying fixes for bugs discovered by Nils Weller's nwcc
		(static DEC memmap => now per machine, and adding an extern
		keyword in cpu_arm_instr.c).
		Finally found one of the MIPS dyntrans bugs that I've been
		looking for (copy/paste spelling error BIG vs LITTLE endian in
		cpu_mips_instr_loadstore.c for 16-bit fast stores).
		FINALLY found the major MIPS dyntrans bug: slti vs sltiu
		signed/unsigned code in cpu_mips_instr.c. :-)
		Adding more MIPS dyntrans instructions (lwc1, swc1, bgezal[l],
		ctc1, tlt[u], tge[u], tne, beginning on rdhwr).
		NetBSD/hpcmips can now reach userland when using dyntrans :-)
		Adding some more x86 dyntrans instructions.
		Finally removed the old Alpha-specific virtual memory code,
		and replaced it with the generic 64-bit version.
		Beginning to add disassembly support for SPECIAL3 MIPS opcodes.
20060423	Continuing on the delay-slot-across-page-boundary issue;
		adding an end_of_page2 ic slot (like I had planned before, but
		had removed for some reason).
		Adding a quick-and-dirty fallback to legacy coprocessor 1
		code (i.e. skipping dyntrans implementation for now).
		NetBSD/hpcmips and NetBSD/pmax (when running on an emulated
		R4400) can now be installed and run. :-)  (Many bugs left
		to fix, though.)
		Adding more MIPS dyntrans instructions: madd[u], msub[u].
		Cleaning up the SPECIAL2 vs R5900/TX79/C790 "MMI" opcode
		maps somewhat (disassembly and dyntrans instruction decoding).
20060424	Adding an isa_revision field to mips_cpu_types.h, and making
		sure that SPECIAL3 opcodes cause Reserved Instruction
		exceptions on MIPS32/64 revisions lower than 2.
		Adding the SPARC 'ba', 'call', 'jmpl/retl', 'and', and 'xor'
		instructions.
20060425	Removing the -m command line option ("run at most x 
		instructions") and -T ("single_step_on_bad_addr"), because
		they never worked correctly with dyntrans anyway.
		Freshening up the man page.
20060428	Adding more MIPS dyntrans instructions: bltzal[l], idle.
		Enabling MIPS dyntrans compare interrupts.
20060429	FINALLY found the weird dyntrans bug, causing NetBSD etc. to
		behave strangely: some floating point code (conditional
		coprocessor branches) could not be reused from the old
		non-dyntrans code. The "quick-and-dirty fallback" only appeared
		to work. Fixing by implementing bc1* for MIPS dyntrans.
		More MIPS instructions: [d]sub, sdc1, ldc1, dmtc1, dmfc1, cfc0.
		Freshening up MIPS floating point disassembly appearance.
20060430	Continuing on C790/R5900/TX79 disassembly; implementing 128-bit
		"por" and "pextlw".
20060504	Disabling -u (userland emulation) unless compiled as unstable
		development version.
		Beginning on freshening up the testmachine include files,
		to make it easier to reuse those files (placing them in
		src/include/testmachine/), and beginning on a set of "demos"
		or "tutorials" for the testmachine functionality.
		Minor updates to the MIPS GDB remote protocol stub.
		Refreshing doc/experiments.html and gdb_remote.html.
		Enabling Alpha emulation in the stable release configuration,
		even though no guest OSes for Alpha can run yet.
20060505	Adding a generic 'settings' object, which will contain
		references to settable variables (which will later be possible
		to access using the debugger).
20060506	Updating dev_disk and corresponding demo/documentation (and
		switching from SCSI to IDE disk types, so it actually works
		with current test machines :-).
20060510	Adding a -D_LARGEFILE_SOURCE hack for 64-bit Linux hosts,
		so that fseeko() doesn't give a warning.
		Updating the section about how dyntrans works (the "runnable
		IR") in doc/intro.html.
		Instruction updates (some x64=1 checks, some more R5900
		dyntrans stuff: better mul/mult separation from MIPS32/64,
		adding ei and di).
		Updating MIPS cpuregs.h to a newer one (from NetBSD).
		Adding more MIPS dyntrans instructions: deret, ehb.
20060514	Adding disassembly and beginning implementation of SPARC wr
		and wrpr instructions.
20060515	Adding a SUN SPARC machine mode, with dummy SS20 and Ultra1
		machines. Adding the 32-bit "rd psr" instruction.
20060517	Disassembly support for the general SPARC rd instruction.
		Partial implementation of the cmp (subcc) instruction.
		Some other minor updates (making sure that R5900 processors
		start up with the EIE bit enabled, otherwise Linux/playstation2
		receives no interrupts).
20060519	Minor MIPS updates/cleanups.
20060521	Moving the MeshCube machine into evbmips; this seems to work
		reasonably well with a snapshot of a NetBSD MeshCube kernel.
		Cleanup/fix of MIPS config0 register initialization.
20060529	Minor MIPS fixes, including a sign-extension fix to the
		unaligned load/store code, which makes NetBSD/pmax on R3000
		work better with dyntrans. (Ultrix and Linux/DECstation still
		don't work, though.)
20060530	Minor updates to the Alpha machine mode: adding an AlphaBook
		mode, an LCA bus (forwarding accesses to an ISA bus), etc.
20060531	Applying a bugfix for the MIPS dyntrans sc[d] instruction from
		Ondrej Palkovsky. (Many thanks.)
20060601	Minifix to allow ARM immediate msr instruction to not give
		an error for some valid values.
		More Alpha updates.
20060602	Some minor Alpha updates.
20060603	Adding the Alpha cmpbge instruction. NetBSD/alpha prints its
		first boot messages :-) on an emulated Alphabook 1.
20060612	Minor updates; adding a dev_ether.h include file for the
		testmachine ether device. Continuing the hunt for the dyntrans
		bug which makes Linux and Ultrix on DECstation behave
		strangely... FINALLY found it! It seems to be related to
		invalidation of the translation cache, on tlbw{r,i}. There
		also seems to be some remaining interrupt-related problems.
20060614	Correcting the implementation of ldc1/sdc1 for MIPS dyntrans
		(so that it uses 16 32-bit registers if the FR bit in the
		status register is not set).
20060616	REMOVING BINTRANS COMPLETELY!
		Removing the old MIPS interpretation mode.
		Removing the MFHILO_DELAY and instruction delay stuff, because
		they wouldn't work with dyntrans anyway.
20060617	Some documentation updates (adding "NetBSD-archive" to some
		URLs, and new Debian/DECstation installation screenshots).
		Removing the "tracenull" and "enable-caches" configure options.
		Improving MIPS dyntrans performance somewhat (only invalidate
		translations if necessary, on writes to the entryhi register,
		instead of doing it for all cop0 writes).
20060618	More cleanup after the removal of the old MIPS emulation.
		Trying to fix the MIPS dyntrans performance bugs/bottlenecks;
		only semi-successful so far (for R3000).
20060620	Minor update to allow clean compilation again on Tru64/Alpha.
20060622	MIPS cleanup and fixes (removing the pc_last stuff, which
		doesn't make sense with dyntrans anyway, and fixing a cross-
		page-delay-slot-with-exception case in end_of_page).
		Removing the old max_random_cycles_per_chunk stuff, and the
		concept of cycles vs instructions for MIPS emulation.
		FINALLY found and fixed the bug which caused NetBSD/pmax
		clocks to behave strangely (it was a load to the zero register,
		which was treated as a NOP; now it is treated as a load to a
		dummy scratch register).
20060623	Increasing the dyntrans chunk size back to
		N_SAFE_DYNTRANS_LIMIT, instead of N_SAFE_DYNTRANS_LIMIT/2.
		Preparing for a quick release, even though there are known
		bugs, and performance for non-R3000 MIPS emulation is very
		poor. :-/
		Reverting to half the dyntrans chunk size again, because
		NetBSD/cats seemed less stable with full size chunks. :(
		NetBSD/sgimips 3.0 can now run :-)  (With release 0.3.8, only
		NetBSD/sgimips 2.1 worked, not 3.0.)

==============  RELEASE 0.4.0  ==============


1 dpavlin 22 /*
2     * Copyright (C) 2005-2006 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 24 * $Id: cpu_mips_instr.c,v 1.85 2006/06/22 13:22:41 debug Exp $
29 dpavlin 22 *
30     * MIPS instructions.
31     *
32     * Individual functions should keep track of cpu->n_translated_instrs.
33     * (If no instruction was executed, then it should be decreased. If, say, 4
34     * instructions were combined into one function and executed, then it should
35     * be increased by 3.)
36     */
37    
38    
39     /*
40 dpavlin 24 * invalid: For catching bugs.
41 dpavlin 22 */
42 dpavlin 24 X(invalid)
43 dpavlin 22 {
44 dpavlin 24 fatal("FATAL ERROR: An internal error occured in the MIPS"
45     " dyntrans code. Please contact the author with detailed"
46     " repro steps on how to trigger this bug.\n");
47     exit(1);
48 dpavlin 22 }
49    
50    
51     /*
52 dpavlin 24 * reserved: Attempt to execute a reserved instruction (e.g. a 64-bit
53     * instruction on an emulated 32-bit processor).
54 dpavlin 22 */
55 dpavlin 24 X(reserved)
56 dpavlin 22 {
57 dpavlin 24 /* Synchronize the PC and cause an exception: */
58     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
59     / sizeof(struct mips_instr_call);
60     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
61     << MIPS_INSTR_ALIGNMENT_SHIFT);
62     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
63     mips_cpu_exception(cpu, EXCEPTION_RI, 0, 0, 0, 0, 0, 0);
64 dpavlin 22 }
65    
66    
67     /*
68 dpavlin 24 * cpu: Cause a CoProcessor Unusable exception.
69     *
70     * arg[0] = the number of the coprocessor
71     */
72     X(cpu)
73     {
74     /* Synchronize the PC and cause an exception: */
75     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
76     / sizeof(struct mips_instr_call);
77     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
78     << MIPS_INSTR_ALIGNMENT_SHIFT);
79     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
80     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, ic->arg[0], 0, 0, 0);
81     }
82    
83    
84     /*
85     * nop: Do nothing.
86     */
87     X(nop)
88     {
89     }
90    
91    
92     /*
93 dpavlin 22 * beq: Branch if equal
94     * bne: Branch if not equal
95     * b: Branch (comparing a register to itself, always true)
96     *
97     * arg[0] = pointer to rs
98     * arg[1] = pointer to rt
99     * arg[2] = (int32_t) relative offset from the next instruction
100     */
101     X(beq)
102     {
103 dpavlin 24 MODE_int_t old_pc = cpu->pc;
104 dpavlin 22 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
105     int x = rs == rt;
106 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
107 dpavlin 22 ic[1].f(cpu, ic+1);
108     cpu->n_translated_instrs ++;
109 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
110     /* Note: Must be non-delayed when jumping to the new pc: */
111     cpu->delay_slot = NOT_DELAYED;
112 dpavlin 22 if (x) {
113     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
114     MIPS_INSTR_ALIGNMENT_SHIFT);
115     cpu->pc = old_pc + (int32_t)ic->arg[2];
116     quick_pc_to_pointers(cpu);
117     } else
118     cpu->cd.mips.next_ic ++;
119 dpavlin 24 } else
120     cpu->delay_slot = NOT_DELAYED;
121 dpavlin 22 }
122     X(beq_samepage)
123     {
124     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
125     int x = rs == rt;
126 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
127 dpavlin 22 ic[1].f(cpu, ic+1);
128     cpu->n_translated_instrs ++;
129 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
130 dpavlin 22 if (x)
131     cpu->cd.mips.next_ic = (struct mips_instr_call *)
132     ic->arg[2];
133     else
134     cpu->cd.mips.next_ic ++;
135     }
136 dpavlin 24 cpu->delay_slot = NOT_DELAYED;
137 dpavlin 22 }
138     X(bne)
139     {
140 dpavlin 24 MODE_int_t old_pc = cpu->pc;
141 dpavlin 22 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
142     int x = rs != rt;
143 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
144 dpavlin 22 ic[1].f(cpu, ic+1);
145     cpu->n_translated_instrs ++;
146 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
147     /* Note: Must be non-delayed when jumping to the new pc: */
148     cpu->delay_slot = NOT_DELAYED;
149 dpavlin 22 if (x) {
150     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
151     MIPS_INSTR_ALIGNMENT_SHIFT);
152     cpu->pc = old_pc + (int32_t)ic->arg[2];
153     quick_pc_to_pointers(cpu);
154     } else
155     cpu->cd.mips.next_ic ++;
156 dpavlin 24 } else
157     cpu->delay_slot = NOT_DELAYED;
158 dpavlin 22 }
159     X(bne_samepage)
160     {
161     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
162     int x = rs != rt;
163 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
164 dpavlin 22 ic[1].f(cpu, ic+1);
165     cpu->n_translated_instrs ++;
166 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
167 dpavlin 22 if (x)
168     cpu->cd.mips.next_ic = (struct mips_instr_call *)
169     ic->arg[2];
170     else
171     cpu->cd.mips.next_ic ++;
172     }
173 dpavlin 24 cpu->delay_slot = NOT_DELAYED;
174 dpavlin 22 }
175     X(b)
176     {
177 dpavlin 24 MODE_int_t old_pc = cpu->pc;
178     cpu->delay_slot = TO_BE_DELAYED;
179 dpavlin 22 ic[1].f(cpu, ic+1);
180     cpu->n_translated_instrs ++;
181 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
182     /* Note: Must be non-delayed when jumping to the new pc: */
183     cpu->delay_slot = NOT_DELAYED;
184 dpavlin 22 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
185     MIPS_INSTR_ALIGNMENT_SHIFT);
186     cpu->pc = old_pc + (int32_t)ic->arg[2];
187     quick_pc_to_pointers(cpu);
188 dpavlin 24 } else
189     cpu->delay_slot = NOT_DELAYED;
190 dpavlin 22 }
191     X(b_samepage)
192     {
193 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
194 dpavlin 22 ic[1].f(cpu, ic+1);
195     cpu->n_translated_instrs ++;
196 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT))
197 dpavlin 22 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
198 dpavlin 24 cpu->delay_slot = NOT_DELAYED;
199 dpavlin 22 }
200    
201    
202     /*
203 dpavlin 24 * beql: Branch if equal likely
204     * bnel: Branch if not equal likely
205     *
206     * arg[0] = pointer to rs
207     * arg[1] = pointer to rt
208     * arg[2] = (int32_t) relative offset from the next instruction
209     */
210     X(beql)
211     {
212     MODE_int_t old_pc = cpu->pc;
213     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
214     int x = rs == rt;
215     cpu->delay_slot = TO_BE_DELAYED;
216     if (x)
217     ic[1].f(cpu, ic+1);
218     cpu->n_translated_instrs ++;
219     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
220     /* Note: Must be non-delayed when jumping to the new pc: */
221     cpu->delay_slot = NOT_DELAYED;
222     if (x) {
223     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
224     MIPS_INSTR_ALIGNMENT_SHIFT);
225     cpu->pc = old_pc + (int32_t)ic->arg[2];
226     quick_pc_to_pointers(cpu);
227     } else
228     cpu->cd.mips.next_ic ++;
229     } else
230     cpu->delay_slot = NOT_DELAYED;
231     }
232     X(beql_samepage)
233     {
234     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
235     int x = rs == rt;
236     cpu->delay_slot = TO_BE_DELAYED;
237     if (x)
238     ic[1].f(cpu, ic+1);
239     cpu->n_translated_instrs ++;
240     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
241     if (x)
242     cpu->cd.mips.next_ic = (struct mips_instr_call *)
243     ic->arg[2];
244     else
245     cpu->cd.mips.next_ic ++;
246     }
247     cpu->delay_slot = NOT_DELAYED;
248     }
249     X(bnel)
250     {
251     MODE_int_t old_pc = cpu->pc;
252     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
253     int x = rs != rt;
254     cpu->delay_slot = TO_BE_DELAYED;
255     if (x)
256     ic[1].f(cpu, ic+1);
257     cpu->n_translated_instrs ++;
258     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
259     /* Note: Must be non-delayed when jumping to the new pc: */
260     cpu->delay_slot = NOT_DELAYED;
261     if (x) {
262     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
263     MIPS_INSTR_ALIGNMENT_SHIFT);
264     cpu->pc = old_pc + (int32_t)ic->arg[2];
265     quick_pc_to_pointers(cpu);
266     } else
267     cpu->cd.mips.next_ic ++;
268     } else
269     cpu->delay_slot = NOT_DELAYED;
270     }
271     X(bnel_samepage)
272     {
273     MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
274     int x = rs != rt;
275     cpu->delay_slot = TO_BE_DELAYED;
276     if (x)
277     ic[1].f(cpu, ic+1);
278     cpu->n_translated_instrs ++;
279     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
280     if (x)
281     cpu->cd.mips.next_ic = (struct mips_instr_call *)
282     ic->arg[2];
283     else
284     cpu->cd.mips.next_ic ++;
285     }
286     cpu->delay_slot = NOT_DELAYED;
287     }
288    
289    
290     /*
291     * blez: Branch if less than or equal
292     * blezl: Branch if less than or equal likely
293     *
294     * arg[0] = pointer to rs
295     * arg[2] = (int32_t) relative offset from the next instruction
296     */
297     X(blez)
298     {
299     MODE_int_t old_pc = cpu->pc;
300     MODE_int_t rs = reg(ic->arg[0]);
301     int x = (rs <= 0);
302     cpu->delay_slot = TO_BE_DELAYED;
303     ic[1].f(cpu, ic+1);
304     cpu->n_translated_instrs ++;
305     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
306     /* Note: Must be non-delayed when jumping to the new pc: */
307     cpu->delay_slot = NOT_DELAYED;
308     if (x) {
309     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
310     MIPS_INSTR_ALIGNMENT_SHIFT);
311     cpu->pc = old_pc + (int32_t)ic->arg[2];
312     quick_pc_to_pointers(cpu);
313     } else
314     cpu->cd.mips.next_ic ++;
315     } else
316     cpu->delay_slot = NOT_DELAYED;
317     }
318     X(blez_samepage)
319     {
320     MODE_int_t rs = reg(ic->arg[0]);
321     int x = (rs <= 0);
322     cpu->delay_slot = TO_BE_DELAYED;
323     ic[1].f(cpu, ic+1);
324     cpu->n_translated_instrs ++;
325     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
326     if (x)
327     cpu->cd.mips.next_ic = (struct mips_instr_call *)
328     ic->arg[2];
329     else
330     cpu->cd.mips.next_ic ++;
331     }
332     cpu->delay_slot = NOT_DELAYED;
333     }
334     X(blezl)
335     {
336     MODE_int_t old_pc = cpu->pc;
337     MODE_int_t rs = reg(ic->arg[0]);
338     int x = (rs <= 0);
339     cpu->delay_slot = TO_BE_DELAYED;
340     if (x)
341     ic[1].f(cpu, ic+1);
342     cpu->n_translated_instrs ++;
343     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
344     /* Note: Must be non-delayed when jumping to the new pc: */
345     cpu->delay_slot = NOT_DELAYED;
346     if (x) {
347     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
348     MIPS_INSTR_ALIGNMENT_SHIFT);
349     cpu->pc = old_pc + (int32_t)ic->arg[2];
350     quick_pc_to_pointers(cpu);
351     } else
352     cpu->cd.mips.next_ic ++;
353     } else
354     cpu->delay_slot = NOT_DELAYED;
355     }
356     X(blezl_samepage)
357     {
358     MODE_int_t rs = reg(ic->arg[0]);
359     int x = (rs <= 0);
360     cpu->delay_slot = TO_BE_DELAYED;
361     if (x)
362     ic[1].f(cpu, ic+1);
363     cpu->n_translated_instrs ++;
364     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
365     if (x)
366     cpu->cd.mips.next_ic = (struct mips_instr_call *)
367     ic->arg[2];
368     else
369     cpu->cd.mips.next_ic ++;
370     }
371     cpu->delay_slot = NOT_DELAYED;
372     }
373    
374    
375     /*
376     * bltz: Branch if less than
377     * bltzl: Branch if less than likely
378     *
379     * arg[0] = pointer to rs
380     * arg[2] = (int32_t) relative offset from the next instruction
381     */
382     X(bltz)
383     {
384     MODE_int_t old_pc = cpu->pc;
385     MODE_int_t rs = reg(ic->arg[0]);
386     int x = (rs < 0);
387     cpu->delay_slot = TO_BE_DELAYED;
388     ic[1].f(cpu, ic+1);
389     cpu->n_translated_instrs ++;
390     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
391     /* Note: Must be non-delayed when jumping to the new pc: */
392     cpu->delay_slot = NOT_DELAYED;
393     if (x) {
394     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
395     MIPS_INSTR_ALIGNMENT_SHIFT);
396     cpu->pc = old_pc + (int32_t)ic->arg[2];
397     quick_pc_to_pointers(cpu);
398     } else
399     cpu->cd.mips.next_ic ++;
400     } else
401     cpu->delay_slot = NOT_DELAYED;
402     }
403     X(bltz_samepage)
404     {
405     MODE_int_t rs = reg(ic->arg[0]);
406     int x = (rs < 0);
407     cpu->delay_slot = TO_BE_DELAYED;
408     ic[1].f(cpu, ic+1);
409     cpu->n_translated_instrs ++;
410     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
411     if (x)
412     cpu->cd.mips.next_ic = (struct mips_instr_call *)
413     ic->arg[2];
414     else
415     cpu->cd.mips.next_ic ++;
416     }
417     cpu->delay_slot = NOT_DELAYED;
418     }
419     X(bltzl)
420     {
421     MODE_int_t old_pc = cpu->pc;
422     MODE_int_t rs = reg(ic->arg[0]);
423     int x = (rs < 0);
424     cpu->delay_slot = TO_BE_DELAYED;
425     if (x)
426     ic[1].f(cpu, ic+1);
427     cpu->n_translated_instrs ++;
428     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
429     /* Note: Must be non-delayed when jumping to the new pc: */
430     cpu->delay_slot = NOT_DELAYED;
431     if (x) {
432     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
433     MIPS_INSTR_ALIGNMENT_SHIFT);
434     cpu->pc = old_pc + (int32_t)ic->arg[2];
435     quick_pc_to_pointers(cpu);
436     } else
437     cpu->cd.mips.next_ic ++;
438     } else
439     cpu->delay_slot = NOT_DELAYED;
440     }
441     X(bltzl_samepage)
442     {
443     MODE_int_t rs = reg(ic->arg[0]);
444     int x = (rs < 0);
445     cpu->delay_slot = TO_BE_DELAYED;
446     if (x)
447     ic[1].f(cpu, ic+1);
448     cpu->n_translated_instrs ++;
449     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
450     if (x)
451     cpu->cd.mips.next_ic = (struct mips_instr_call *)
452     ic->arg[2];
453     else
454     cpu->cd.mips.next_ic ++;
455     }
456     cpu->delay_slot = NOT_DELAYED;
457     }
458    
459    
460     /*
461     * bgez: Branch if greater than or equal
462     * bgezl: Branch if greater than or equal likely
463     *
464     * arg[0] = pointer to rs
465     * arg[2] = (int32_t) relative offset from the next instruction
466     */
467     X(bgez)
468     {
469     MODE_int_t old_pc = cpu->pc;
470     MODE_int_t rs = reg(ic->arg[0]);
471     int x = (rs >= 0);
472     cpu->delay_slot = TO_BE_DELAYED;
473     ic[1].f(cpu, ic+1);
474     cpu->n_translated_instrs ++;
475     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
476     /* Note: Must be non-delayed when jumping to the new pc: */
477     cpu->delay_slot = NOT_DELAYED;
478     if (x) {
479     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
480     MIPS_INSTR_ALIGNMENT_SHIFT);
481     cpu->pc = old_pc + (int32_t)ic->arg[2];
482     quick_pc_to_pointers(cpu);
483     } else
484     cpu->cd.mips.next_ic ++;
485     } else
486     cpu->delay_slot = NOT_DELAYED;
487     }
488     X(bgez_samepage)
489     {
490     MODE_int_t rs = reg(ic->arg[0]);
491     int x = (rs >= 0);
492     cpu->delay_slot = TO_BE_DELAYED;
493     ic[1].f(cpu, ic+1);
494     cpu->n_translated_instrs ++;
495     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
496     if (x)
497     cpu->cd.mips.next_ic = (struct mips_instr_call *)
498     ic->arg[2];
499     else
500     cpu->cd.mips.next_ic ++;
501     }
502     cpu->delay_slot = NOT_DELAYED;
503     }
504     X(bgezl)
505     {
506     MODE_int_t old_pc = cpu->pc;
507     MODE_int_t rs = reg(ic->arg[0]);
508     int x = (rs >= 0);
509     cpu->delay_slot = TO_BE_DELAYED;
510     if (x)
511     ic[1].f(cpu, ic+1);
512     cpu->n_translated_instrs ++;
513     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
514     /* Note: Must be non-delayed when jumping to the new pc: */
515     cpu->delay_slot = NOT_DELAYED;
516     if (x) {
517     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
518     MIPS_INSTR_ALIGNMENT_SHIFT);
519     cpu->pc = old_pc + (int32_t)ic->arg[2];
520     quick_pc_to_pointers(cpu);
521     } else
522     cpu->cd.mips.next_ic ++;
523     } else
524     cpu->delay_slot = NOT_DELAYED;
525     }
526     X(bgezl_samepage)
527     {
528     MODE_int_t rs = reg(ic->arg[0]);
529     int x = (rs >= 0);
530     cpu->delay_slot = TO_BE_DELAYED;
531     if (x)
532     ic[1].f(cpu, ic+1);
533     cpu->n_translated_instrs ++;
534     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
535     if (x)
536     cpu->cd.mips.next_ic = (struct mips_instr_call *)
537     ic->arg[2];
538     else
539     cpu->cd.mips.next_ic ++;
540     }
541     cpu->delay_slot = NOT_DELAYED;
542     }
543    
544    
545     /*
546     * bgezal: Branch if greater than or equal (and link)
547     * bgezall: Branch if greater than or equal (and link) likely
548     *
549     * arg[0] = pointer to rs
550     * arg[2] = (int32_t) relative offset from the next instruction
551     */
552     X(bgezal)
553     {
554     MODE_int_t old_pc = cpu->pc;
555     MODE_int_t rs = reg(ic->arg[0]);
556     int x = (rs >= 0), low_pc;
557    
558     cpu->delay_slot = TO_BE_DELAYED;
559     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
560     / sizeof(struct mips_instr_call);
561     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
562     << MIPS_INSTR_ALIGNMENT_SHIFT);
563     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
564     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
565    
566     ic[1].f(cpu, ic+1);
567     cpu->n_translated_instrs ++;
568     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
569     /* Note: Must be non-delayed when jumping to the new pc: */
570     cpu->delay_slot = NOT_DELAYED;
571     if (x) {
572     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
573     MIPS_INSTR_ALIGNMENT_SHIFT);
574     cpu->pc = old_pc + (int32_t)ic->arg[2];
575     quick_pc_to_pointers(cpu);
576     } else
577     cpu->cd.mips.next_ic ++;
578     } else
579     cpu->delay_slot = NOT_DELAYED;
580     }
581     X(bgezal_samepage)
582     {
583     MODE_int_t rs = reg(ic->arg[0]);
584     int x = (rs >= 0), low_pc;
585    
586     cpu->delay_slot = TO_BE_DELAYED;
587     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
588     / sizeof(struct mips_instr_call);
589     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
590     << MIPS_INSTR_ALIGNMENT_SHIFT);
591     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
592     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
593    
594     ic[1].f(cpu, ic+1);
595     cpu->n_translated_instrs ++;
596     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
597     if (x)
598     cpu->cd.mips.next_ic = (struct mips_instr_call *)
599     ic->arg[2];
600     else
601     cpu->cd.mips.next_ic ++;
602     }
603     cpu->delay_slot = NOT_DELAYED;
604     }
605     X(bgezall)
606     {
607     MODE_int_t old_pc = cpu->pc;
608     MODE_int_t rs = reg(ic->arg[0]);
609     int x = (rs >= 0), low_pc;
610    
611     cpu->delay_slot = TO_BE_DELAYED;
612     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
613     / sizeof(struct mips_instr_call);
614     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
615     << MIPS_INSTR_ALIGNMENT_SHIFT);
616     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
617     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
618    
619     if (x)
620     ic[1].f(cpu, ic+1);
621     cpu->n_translated_instrs ++;
622     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
623     /* Note: Must be non-delayed when jumping to the new pc: */
624     cpu->delay_slot = NOT_DELAYED;
625     if (x) {
626     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
627     MIPS_INSTR_ALIGNMENT_SHIFT);
628     cpu->pc = old_pc + (int32_t)ic->arg[2];
629     quick_pc_to_pointers(cpu);
630     } else
631     cpu->cd.mips.next_ic ++;
632     } else
633     cpu->delay_slot = NOT_DELAYED;
634     }
635     X(bgezall_samepage)
636     {
637     MODE_int_t rs = reg(ic->arg[0]);
638     int x = (rs >= 0), low_pc;
639    
640     cpu->delay_slot = TO_BE_DELAYED;
641     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
642     / sizeof(struct mips_instr_call);
643     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
644     << MIPS_INSTR_ALIGNMENT_SHIFT);
645     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
646     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
647    
648     if (x)
649     ic[1].f(cpu, ic+1);
650     cpu->n_translated_instrs ++;
651     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
652     if (x)
653     cpu->cd.mips.next_ic = (struct mips_instr_call *)
654     ic->arg[2];
655     else
656     cpu->cd.mips.next_ic ++;
657     }
658     cpu->delay_slot = NOT_DELAYED;
659     }
660    
661    
662     /*
663     * bltzal: Branch if less than zero (and link)
664     * bltzall: Branch if less than zero (and link) likely
665     *
666     * arg[0] = pointer to rs
667     * arg[2] = (int32_t) relative offset from the next instruction
668     */
669     X(bltzal)
670     {
671     MODE_int_t old_pc = cpu->pc;
672     MODE_int_t rs = reg(ic->arg[0]);
673     int x = (rs < 0), low_pc;
674    
675     cpu->delay_slot = TO_BE_DELAYED;
676     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
677     / sizeof(struct mips_instr_call);
678     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
679     << MIPS_INSTR_ALIGNMENT_SHIFT);
680     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
681     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
682    
683     ic[1].f(cpu, ic+1);
684     cpu->n_translated_instrs ++;
685     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
686     /* Note: Must be non-delayed when jumping to the new pc: */
687     cpu->delay_slot = NOT_DELAYED;
688     if (x) {
689     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
690     MIPS_INSTR_ALIGNMENT_SHIFT);
691     cpu->pc = old_pc + (int32_t)ic->arg[2];
692     quick_pc_to_pointers(cpu);
693     } else
694     cpu->cd.mips.next_ic ++;
695     } else
696     cpu->delay_slot = NOT_DELAYED;
697     }
698     X(bltzal_samepage)
699     {
700     MODE_int_t rs = reg(ic->arg[0]);
701     int x = (rs < 0), low_pc;
702    
703     cpu->delay_slot = TO_BE_DELAYED;
704     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
705     / sizeof(struct mips_instr_call);
706     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
707     << MIPS_INSTR_ALIGNMENT_SHIFT);
708     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
709     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
710    
711     ic[1].f(cpu, ic+1);
712     cpu->n_translated_instrs ++;
713     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
714     if (x)
715     cpu->cd.mips.next_ic = (struct mips_instr_call *)
716     ic->arg[2];
717     else
718     cpu->cd.mips.next_ic ++;
719     }
720     cpu->delay_slot = NOT_DELAYED;
721     }
722     X(bltzall)
723     {
724     MODE_int_t old_pc = cpu->pc;
725     MODE_int_t rs = reg(ic->arg[0]);
726     int x = (rs < 0), low_pc;
727    
728     cpu->delay_slot = TO_BE_DELAYED;
729     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
730     / sizeof(struct mips_instr_call);
731     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
732     << MIPS_INSTR_ALIGNMENT_SHIFT);
733     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
734     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
735    
736     if (x)
737     ic[1].f(cpu, ic+1);
738     cpu->n_translated_instrs ++;
739     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
740     /* Note: Must be non-delayed when jumping to the new pc: */
741     cpu->delay_slot = NOT_DELAYED;
742     if (x) {
743     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
744     MIPS_INSTR_ALIGNMENT_SHIFT);
745     cpu->pc = old_pc + (int32_t)ic->arg[2];
746     quick_pc_to_pointers(cpu);
747     } else
748     cpu->cd.mips.next_ic ++;
749     } else
750     cpu->delay_slot = NOT_DELAYED;
751     }
752     X(bltzall_samepage)
753     {
754     MODE_int_t rs = reg(ic->arg[0]);
755     int x = (rs < 0), low_pc;
756    
757     cpu->delay_slot = TO_BE_DELAYED;
758     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
759     / sizeof(struct mips_instr_call);
760     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
761     << MIPS_INSTR_ALIGNMENT_SHIFT);
762     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
763     cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
764    
765     if (x)
766     ic[1].f(cpu, ic+1);
767     cpu->n_translated_instrs ++;
768     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
769     if (x)
770     cpu->cd.mips.next_ic = (struct mips_instr_call *)
771     ic->arg[2];
772     else
773     cpu->cd.mips.next_ic ++;
774     }
775     cpu->delay_slot = NOT_DELAYED;
776     }
777    
778    
779     /*
780     * bgtz: Branch if greater than zero
781     * bgtzl: Branch if greater than zero likely
782     *
783     * arg[0] = pointer to rs
784     * arg[2] = (int32_t) relative offset from the next instruction
785     */
786     X(bgtz)
787     {
788     MODE_int_t old_pc = cpu->pc;
789     MODE_int_t rs = reg(ic->arg[0]);
790     int x = (rs > 0);
791     cpu->delay_slot = TO_BE_DELAYED;
792     ic[1].f(cpu, ic+1);
793     cpu->n_translated_instrs ++;
794     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
795     /* Note: Must be non-delayed when jumping to the new pc: */
796     cpu->delay_slot = NOT_DELAYED;
797     if (x) {
798     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
799     MIPS_INSTR_ALIGNMENT_SHIFT);
800     cpu->pc = old_pc + (int32_t)ic->arg[2];
801     quick_pc_to_pointers(cpu);
802     } else
803     cpu->cd.mips.next_ic ++;
804     } else
805     cpu->delay_slot = NOT_DELAYED;
806     }
807     X(bgtz_samepage)
808     {
809     MODE_int_t rs = reg(ic->arg[0]);
810     int x = (rs > 0);
811     cpu->delay_slot = TO_BE_DELAYED;
812     ic[1].f(cpu, ic+1);
813     cpu->n_translated_instrs ++;
814     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
815     if (x)
816     cpu->cd.mips.next_ic = (struct mips_instr_call *)
817     ic->arg[2];
818     else
819     cpu->cd.mips.next_ic ++;
820     }
821     cpu->delay_slot = NOT_DELAYED;
822     }
823     X(bgtzl)
824     {
825     MODE_int_t old_pc = cpu->pc;
826     MODE_int_t rs = reg(ic->arg[0]);
827     int x = (rs > 0);
828     cpu->delay_slot = TO_BE_DELAYED;
829     if (x)
830     ic[1].f(cpu, ic+1);
831     cpu->n_translated_instrs ++;
832     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
833     /* Note: Must be non-delayed when jumping to the new pc: */
834     cpu->delay_slot = NOT_DELAYED;
835     if (x) {
836     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
837     MIPS_INSTR_ALIGNMENT_SHIFT);
838     cpu->pc = old_pc + (int32_t)ic->arg[2];
839     quick_pc_to_pointers(cpu);
840     } else
841     cpu->cd.mips.next_ic ++;
842     } else
843     cpu->delay_slot = NOT_DELAYED;
844     }
845     X(bgtzl_samepage)
846     {
847     MODE_int_t rs = reg(ic->arg[0]);
848     int x = (rs > 0);
849     cpu->delay_slot = TO_BE_DELAYED;
850     if (x)
851     ic[1].f(cpu, ic+1);
852     cpu->n_translated_instrs ++;
853     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
854     if (x)
855     cpu->cd.mips.next_ic = (struct mips_instr_call *)
856     ic->arg[2];
857     else
858     cpu->cd.mips.next_ic ++;
859     }
860     cpu->delay_slot = NOT_DELAYED;
861     }
862    
863    
864     /*
865 dpavlin 22 * jr, jalr: Jump to a register [and link].
866     *
867     * arg[0] = ptr to rs
868     * arg[1] = ptr to rd (for jalr)
869     * arg[2] = (int32_t) relative offset of the next instruction
870     */
871     X(jr)
872     {
873 dpavlin 24 MODE_int_t rs = reg(ic->arg[0]);
874     cpu->delay_slot = TO_BE_DELAYED;
875 dpavlin 22 ic[1].f(cpu, ic+1);
876     cpu->n_translated_instrs ++;
877 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
878 dpavlin 22 cpu->pc = rs;
879 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
880     cpu->delay_slot = NOT_DELAYED;
881 dpavlin 22 quick_pc_to_pointers(cpu);
882 dpavlin 24 } else
883     cpu->delay_slot = NOT_DELAYED;
884 dpavlin 22 }
885     X(jr_ra)
886     {
887 dpavlin 24 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
888     cpu->delay_slot = TO_BE_DELAYED;
889 dpavlin 22 ic[1].f(cpu, ic+1);
890     cpu->n_translated_instrs ++;
891 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
892 dpavlin 22 cpu->pc = rs;
893 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
894     cpu->delay_slot = NOT_DELAYED;
895 dpavlin 22 quick_pc_to_pointers(cpu);
896 dpavlin 24 } else
897     cpu->delay_slot = NOT_DELAYED;
898 dpavlin 22 }
899     X(jr_ra_trace)
900     {
901 dpavlin 24 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
902     cpu->delay_slot = TO_BE_DELAYED;
903 dpavlin 22 ic[1].f(cpu, ic+1);
904     cpu->n_translated_instrs ++;
905 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
906 dpavlin 22 cpu->pc = rs;
907     cpu_functioncall_trace_return(cpu);
908 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
909     cpu->delay_slot = NOT_DELAYED;
910 dpavlin 22 quick_pc_to_pointers(cpu);
911 dpavlin 24 } else
912     cpu->delay_slot = NOT_DELAYED;
913 dpavlin 22 }
914     X(jalr)
915     {
916 dpavlin 24 MODE_int_t rs = reg(ic->arg[0]), rd;
917     cpu->delay_slot = TO_BE_DELAYED;
918 dpavlin 22 rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
919     MIPS_INSTR_ALIGNMENT_SHIFT);
920     rd += (int32_t)ic->arg[2];
921     reg(ic->arg[1]) = rd;
922     ic[1].f(cpu, ic+1);
923     cpu->n_translated_instrs ++;
924 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
925 dpavlin 22 cpu->pc = rs;
926 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
927     cpu->delay_slot = NOT_DELAYED;
928 dpavlin 22 quick_pc_to_pointers(cpu);
929 dpavlin 24 } else
930     cpu->delay_slot = NOT_DELAYED;
931 dpavlin 22 }
932     X(jalr_trace)
933     {
934 dpavlin 24 MODE_int_t rs = reg(ic->arg[0]), rd;
935     cpu->delay_slot = TO_BE_DELAYED;
936 dpavlin 22 rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
937     MIPS_INSTR_ALIGNMENT_SHIFT);
938     rd += (int32_t)ic->arg[2];
939     reg(ic->arg[1]) = rd;
940     ic[1].f(cpu, ic+1);
941     cpu->n_translated_instrs ++;
942 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
943 dpavlin 22 cpu->pc = rs;
944     cpu_functioncall_trace(cpu, cpu->pc);
945 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
946     cpu->delay_slot = NOT_DELAYED;
947 dpavlin 22 quick_pc_to_pointers(cpu);
948 dpavlin 24 } else
949     cpu->delay_slot = NOT_DELAYED;
950 dpavlin 22 }
951    
952    
953     /*
954 dpavlin 24 * j, jal: Jump [and link].
955     *
956     * arg[0] = lowest 28 bits of new pc.
957     * arg[1] = offset from start of page to the jal instruction + 8
958     */
959     X(j)
960     {
961     MODE_int_t old_pc = cpu->pc;
962     cpu->delay_slot = TO_BE_DELAYED;
963     ic[1].f(cpu, ic+1);
964     cpu->n_translated_instrs ++;
965     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
966     /* Note: Must be non-delayed when jumping to the new pc: */
967     cpu->delay_slot = NOT_DELAYED;
968     old_pc &= ~0x03ffffff;
969     cpu->pc = old_pc | (uint32_t)ic->arg[0];
970     quick_pc_to_pointers(cpu);
971     } else
972     cpu->delay_slot = NOT_DELAYED;
973     }
974     X(jal)
975     {
976     MODE_int_t old_pc = cpu->pc;
977     cpu->delay_slot = TO_BE_DELAYED;
978     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
979     cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
980     ic[1].f(cpu, ic+1);
981     cpu->n_translated_instrs ++;
982     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
983     /* Note: Must be non-delayed when jumping to the new pc: */
984     cpu->delay_slot = NOT_DELAYED;
985     old_pc &= ~0x03ffffff;
986     cpu->pc = old_pc | (int32_t)ic->arg[0];
987     quick_pc_to_pointers(cpu);
988     } else
989     cpu->delay_slot = NOT_DELAYED;
990     }
991     X(jal_trace)
992     {
993     MODE_int_t old_pc = cpu->pc;
994     cpu->delay_slot = TO_BE_DELAYED;
995     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
996     cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
997     ic[1].f(cpu, ic+1);
998     cpu->n_translated_instrs ++;
999     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1000     /* Note: Must be non-delayed when jumping to the new pc: */
1001     cpu->delay_slot = NOT_DELAYED;
1002     old_pc &= ~0x03ffffff;
1003     cpu->pc = old_pc | (int32_t)ic->arg[0];
1004     cpu_functioncall_trace(cpu, cpu->pc);
1005     quick_pc_to_pointers(cpu);
1006     } else
1007     cpu->delay_slot = NOT_DELAYED;
1008     }
1009    
1010    
1011     /*
1012     * cache: Cache operation.
1013     */
1014     X(cache)
1015     {
1016     /* TODO. For now, just clear the rmw bit: */
1017     cpu->cd.mips.rmw = 0;
1018    
1019     /* TODO: fix */
1020     cpu->invalidate_code_translation(cpu, 0, INVALIDATE_ALL);
1021     cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
1022     /* cpu_create_or_reset_tc(cpu); */
1023     }
1024    
1025    
1026     /*
1027 dpavlin 22 * 2-register + immediate:
1028     *
1029     * arg[0] = pointer to rs
1030     * arg[1] = pointer to rt
1031     * arg[2] = uint32_t immediate value
1032     */
1033 dpavlin 24 X(andi) { reg(ic->arg[1]) = reg(ic->arg[0]) & (uint32_t)ic->arg[2]; }
1034     X(ori) { reg(ic->arg[1]) = reg(ic->arg[0]) | (uint32_t)ic->arg[2]; }
1035     X(xori) { reg(ic->arg[1]) = reg(ic->arg[0]) ^ (uint32_t)ic->arg[2]; }
1036 dpavlin 22
1037    
1038     /*
1039     * 2-register:
1040 dpavlin 24 *
1041     * arg[0] = ptr to rs
1042     * arg[1] = ptr to rt
1043 dpavlin 22 */
1044 dpavlin 24 X(div)
1045     {
1046     int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1047     int32_t res, rem;
1048     if (b == 0)
1049     res = 0, rem = a;
1050     else
1051     res = a / b, rem = a - b*res;
1052     reg(&cpu->cd.mips.lo) = (int32_t)res;
1053     reg(&cpu->cd.mips.hi) = (int32_t)rem;
1054     }
1055     X(divu)
1056     {
1057     uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1058     uint32_t res, rem;
1059     if (b == 0)
1060     res = 0, rem = a;
1061     else
1062     res = a / b, rem = a - b*res;
1063     reg(&cpu->cd.mips.lo) = (int32_t)res;
1064     reg(&cpu->cd.mips.hi) = (int32_t)rem;
1065     }
1066     X(ddiv)
1067     {
1068     int64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1069     int64_t res, rem;
1070     if (b == 0)
1071     res = 0;
1072     else
1073     res = a / b;
1074     rem = a - b*res;
1075     reg(&cpu->cd.mips.lo) = res;
1076     reg(&cpu->cd.mips.hi) = rem;
1077     }
1078     X(ddivu)
1079     {
1080     uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1081     uint64_t res, rem;
1082     if (b == 0)
1083     res = 0;
1084     else
1085     res = a / b;
1086     rem = a - b*res;
1087     reg(&cpu->cd.mips.lo) = res;
1088     reg(&cpu->cd.mips.hi) = rem;
1089     }
1090 dpavlin 22 X(mult)
1091     {
1092     int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1093     int64_t res = (int64_t)a * (int64_t)b;
1094     reg(&cpu->cd.mips.lo) = (int32_t)res;
1095     reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1096     }
1097 dpavlin 24 X(mult_r5900)
1098     {
1099     /* C790/TX79/R5900 multiplication, stores result in
1100     hi, lo, and a third register */
1101     int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1102     int64_t res = (int64_t)a * (int64_t)b;
1103     reg(&cpu->cd.mips.lo) = (int32_t)res;
1104     reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1105     reg(ic->arg[2]) = (int32_t)res;
1106     }
1107 dpavlin 22 X(multu)
1108     {
1109     uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1110     uint64_t res = (uint64_t)a * (uint64_t)b;
1111     reg(&cpu->cd.mips.lo) = (int32_t)res;
1112     reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1113     }
1114 dpavlin 24 X(multu_r5900)
1115     {
1116     /* C790/TX79/R5900 multiplication, stores result in
1117     hi, lo, and a third register */
1118     uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1119     uint64_t res = (uint64_t)a * (uint64_t)b;
1120     reg(&cpu->cd.mips.lo) = (int32_t)res;
1121     reg(&cpu->cd.mips.hi) = (int32_t)(res >> 32);
1122     reg(ic->arg[2]) = (int32_t)res;
1123     }
1124     X(dmult)
1125     {
1126     uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1127     uint64_t hi = 0, lo = 0;
1128     int neg = 0;
1129     if (a >> 63)
1130     neg = !neg, a = -a;
1131     if (b >> 63)
1132     neg = !neg, b = -b;
1133     for (; a; a >>= 1) {
1134     if (a & 1) {
1135     uint64_t old_lo = lo;
1136     hi += c;
1137     lo += b;
1138     if (lo < old_lo)
1139     hi ++;
1140     }
1141     c = (c << 1) | (b >> 63); b <<= 1;
1142     }
1143     if (neg) {
1144     if (lo == 0)
1145     hi --;
1146     lo --;
1147     hi ^= (int64_t) -1;
1148     lo ^= (int64_t) -1;
1149     }
1150     reg(&cpu->cd.mips.lo) = lo;
1151     reg(&cpu->cd.mips.hi) = hi;
1152     }
1153     X(dmultu)
1154     {
1155     uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1156     uint64_t hi = 0, lo = 0;
1157     for (; a; a >>= 1) {
1158     if (a & 1) {
1159     uint64_t old_lo = lo;
1160     hi += c;
1161     lo += b;
1162     if (lo < old_lo)
1163     hi ++;
1164     }
1165     c = (c << 1) | (b >> 63); b <<= 1;
1166     }
1167     reg(&cpu->cd.mips.lo) = lo;
1168     reg(&cpu->cd.mips.hi) = hi;
1169     }
1170     X(tge)
1171     {
1172     MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1173     if (a >= b) {
1174     /* Synch. PC and cause an exception: */
1175     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1176     / sizeof(struct mips_instr_call);
1177     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1178     << MIPS_INSTR_ALIGNMENT_SHIFT);
1179     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1180     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1181     }
1182     }
1183     X(tgeu)
1184     {
1185     MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1186     if (a >= b) {
1187     /* Synch. PC and cause an exception: */
1188     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1189     / sizeof(struct mips_instr_call);
1190     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1191     << MIPS_INSTR_ALIGNMENT_SHIFT);
1192     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1193     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1194     }
1195     }
1196     X(tlt)
1197     {
1198     MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1199     if (a < b) {
1200     /* Synch. PC and cause an exception: */
1201     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1202     / sizeof(struct mips_instr_call);
1203     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1204     << MIPS_INSTR_ALIGNMENT_SHIFT);
1205     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1206     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1207     }
1208     }
1209     X(tltu)
1210     {
1211     MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1212     if (a < b) {
1213     /* Synch. PC and cause an exception: */
1214     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1215     / sizeof(struct mips_instr_call);
1216     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1217     << MIPS_INSTR_ALIGNMENT_SHIFT);
1218     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1219     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1220     }
1221     }
1222     X(teq)
1223     {
1224     MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1225     if (a == b) {
1226     /* Synch. PC and cause an exception: */
1227     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1228     / sizeof(struct mips_instr_call);
1229     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1230     << MIPS_INSTR_ALIGNMENT_SHIFT);
1231     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1232     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1233     }
1234     }
1235     X(tne)
1236     {
1237     MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1238     if (a != b) {
1239     /* Synch. PC and cause an exception: */
1240     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1241     / sizeof(struct mips_instr_call);
1242     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1243     << MIPS_INSTR_ALIGNMENT_SHIFT);
1244     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1245     mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1246     }
1247     }
1248 dpavlin 22
1249    
1250     /*
1251 dpavlin 24 * 3-register arithmetic instructions:
1252     *
1253     * arg[0] = ptr to rs
1254     * arg[1] = ptr to rt
1255     * arg[2] = ptr to rd
1256 dpavlin 22 */
1257     X(addu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) + reg(ic->arg[1])); }
1258 dpavlin 24 X(add)
1259     {
1260     int32_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1261     int32_t rd = rs + rt;
1262    
1263     if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1264     /* Synch. PC and cause an exception: */
1265     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1266     / sizeof(struct mips_instr_call);
1267     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1268     << MIPS_INSTR_ALIGNMENT_SHIFT);
1269     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1270     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1271     } else
1272     reg(ic->arg[2]) = rd;
1273     }
1274     X(daddu){ reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]); }
1275     X(dadd)
1276     {
1277     int64_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1278     int64_t rd = rs + rt;
1279    
1280     if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1281     /* Synch. PC and cause an exception: */
1282     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1283     / sizeof(struct mips_instr_call);
1284     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1285     << MIPS_INSTR_ALIGNMENT_SHIFT);
1286     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1287     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1288     } else
1289     reg(ic->arg[2]) = rd;
1290     }
1291 dpavlin 22 X(subu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) - reg(ic->arg[1])); }
1292 dpavlin 24 X(sub)
1293     {
1294     /* NOTE: Negating rt and using addition. TODO: Is this correct? */
1295     int32_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1296     int32_t rd = rs + rt;
1297    
1298     if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1299     /* Synch. PC and cause an exception: */
1300     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1301     / sizeof(struct mips_instr_call);
1302     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1303     << MIPS_INSTR_ALIGNMENT_SHIFT);
1304     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1305     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1306     } else
1307     reg(ic->arg[2]) = rd;
1308     }
1309     X(dsubu){ reg(ic->arg[2]) = reg(ic->arg[0]) - reg(ic->arg[1]); }
1310     X(dsub)
1311     {
1312     /* NOTE: Negating rt and using addition. TODO: Is this correct? */
1313     int64_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1314     int64_t rd = rs + rt;
1315    
1316     if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1317     /* Synch. PC and cause an exception: */
1318     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1319     / sizeof(struct mips_instr_call);
1320     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1321     << MIPS_INSTR_ALIGNMENT_SHIFT);
1322     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1323     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1324     } else
1325     reg(ic->arg[2]) = rd;
1326     }
1327 dpavlin 22 X(slt) {
1328 dpavlin 24 reg(ic->arg[2]) =
1329     (MODE_int_t)reg(ic->arg[0]) < (MODE_int_t)reg(ic->arg[1]);
1330 dpavlin 22 }
1331     X(sltu) {
1332 dpavlin 24 reg(ic->arg[2]) =
1333     (MODE_uint_t)reg(ic->arg[0]) < (MODE_uint_t)reg(ic->arg[1]);
1334 dpavlin 22 }
1335 dpavlin 24 X(and) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
1336     X(or) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
1337 dpavlin 22 X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
1338     X(nor) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1])); }
1339 dpavlin 24 X(sll) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << (int32_t)ic->arg[1]); }
1340     X(sllv){ int32_t sa = reg(ic->arg[1]) & 31;
1341     reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << sa); }
1342 dpavlin 22 X(srl) { reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1343 dpavlin 24 X(srlv){ int32_t sa = reg(ic->arg[1]) & 31;
1344     reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> sa); }
1345 dpavlin 22 X(sra) { reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1346 dpavlin 24 X(srav){ int32_t sa = reg(ic->arg[1]) & 31;
1347     reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> sa); }
1348     X(dsll) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) << (int64_t)ic->arg[1]; }
1349     X(dsllv){ int64_t sa = reg(ic->arg[1]) & 63;
1350     reg(ic->arg[2]) = reg(ic->arg[0]) << sa; }
1351     X(dsrl) { reg(ic->arg[2]) = (int64_t)((uint64_t)reg(ic->arg[0]) >>
1352     (uint64_t) ic->arg[1]);}
1353     X(dsrlv){ int64_t sa = reg(ic->arg[1]) & 63;
1354     reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) >> sa; }
1355     X(dsra) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> (int64_t)ic->arg[1]; }
1356     X(dsrav){ int64_t sa = reg(ic->arg[1]) & 63;
1357     reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> sa; }
1358 dpavlin 22 X(mul) { reg(ic->arg[2]) = (int32_t)
1359     ( (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]) ); }
1360 dpavlin 24 X(movn) { if (reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1361     X(movz) { if (!reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1362 dpavlin 22
1363    
1364     /*
1365 dpavlin 24 * p*: 128-bit C790/TX79/R5900 stuff
1366     *
1367     * arg[0] = rs (note: not a pointer)
1368     * arg[1] = rt (note: not a pointer)
1369     * arg[2] = rd (note: not a pointer)
1370     */
1371     X(por)
1372     {
1373     cpu->cd.mips.gpr[ic->arg[2]] = cpu->cd.mips.gpr[ic->arg[0]] |
1374     cpu->cd.mips.gpr[ic->arg[1]];
1375     cpu->cd.mips.gpr_quadhi[ic->arg[2]] =
1376     cpu->cd.mips.gpr_quadhi[ic->arg[0]] |
1377     cpu->cd.mips.gpr_quadhi[ic->arg[1]];
1378     }
1379     X(pextlw)
1380     {
1381     uint64_t lo, hi;
1382    
1383     lo = (uint32_t)cpu->cd.mips.gpr[ic->arg[1]] |
1384     (uint64_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[0]] << 32);
1385     hi = (cpu->cd.mips.gpr[ic->arg[0]] & 0xffffffff00000000ULL) |
1386     (uint32_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[1]] >> 32);
1387    
1388     cpu->cd.mips.gpr[ic->arg[2]] = lo;
1389     cpu->cd.mips.gpr_quadhi[ic->arg[2]] = hi;
1390     }
1391    
1392    
1393     /*
1394     * madd, maddu, msub, msubu: Multiply-and-add/subtract
1395     *
1396     * arg[0] = ptr to rs
1397     * arg[1] = ptr to rt
1398     * arg[2] = ptr to rd (only used on R5900/TX79)
1399     */
1400     X(madd)
1401     {
1402     int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1403     int64_t sum = rs * rt,
1404     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1405     hilo += sum;
1406     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1407     }
1408     X(madd_rd)
1409     {
1410     int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1411     int64_t sum = rs * rt,
1412     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1413     hilo += sum;
1414     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1415     reg(ic->arg[2]) = (int32_t)hilo;
1416     }
1417     X(msub)
1418     {
1419     int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1420     int64_t sum = rs * rt,
1421     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1422     hilo -= sum;
1423     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1424     }
1425     X(maddu)
1426     {
1427     int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1428     int64_t sum = rs * rt,
1429     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1430     hilo += sum;
1431     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1432     }
1433     X(maddu_rd)
1434     {
1435     int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1436     int64_t sum = rs * rt,
1437     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1438     hilo += sum;
1439     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1440     reg(ic->arg[2]) = (int32_t)hilo;
1441     }
1442     X(msubu)
1443     {
1444     int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1445     int64_t sum = rs * rt,
1446     hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1447     hilo -= sum;
1448     cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1449     }
1450    
1451    
1452     /*
1453 dpavlin 22 * mov: Move one register into another.
1454     *
1455     * arg[0] = pointer to source
1456     * arg[2] = pointer to destination
1457     */
1458     X(mov) { reg(ic->arg[2]) = reg(ic->arg[0]); }
1459    
1460    
1461     /*
1462     * clz, clo, dclz, dclo: Count leading zeroes/ones.
1463     *
1464     * arg[0] = pointer to rs
1465     * arg[1] = pointer to rd
1466     */
1467     X(clz)
1468     {
1469     uint32_t x = reg(ic->arg[0]);
1470     int count;
1471     for (count=0; count<32; count++) {
1472     if (x & 0x80000000UL)
1473     break;
1474     x <<= 1;
1475     }
1476     reg(ic->arg[1]) = count;
1477     }
1478     X(clo)
1479     {
1480     uint32_t x = reg(ic->arg[0]);
1481     int count;
1482     for (count=0; count<32; count++) {
1483     if (!(x & 0x80000000UL))
1484     break;
1485     x <<= 1;
1486     }
1487     reg(ic->arg[1]) = count;
1488     }
1489     X(dclz)
1490     {
1491     uint64_t x = reg(ic->arg[0]);
1492     int count;
1493     for (count=0; count<64; count++) {
1494     if (x & 0x8000000000000000ULL)
1495     break;
1496     x <<= 1;
1497     }
1498     reg(ic->arg[1]) = count;
1499     }
1500     X(dclo)
1501     {
1502     uint64_t x = reg(ic->arg[0]);
1503     int count;
1504     for (count=0; count<64; count++) {
1505     if (!(x & 0x8000000000000000ULL))
1506     break;
1507     x <<= 1;
1508     }
1509     reg(ic->arg[1]) = count;
1510     }
1511    
1512    
1513     /*
1514 dpavlin 24 * addi, daddi: Add immediate, overflow detection.
1515     * addiu, daddiu: Add immediate.
1516     * slti: Set if less than immediate (signed 32-bit)
1517     * sltiu: Set if less than immediate (signed 32-bit, but unsigned compare)
1518 dpavlin 22 *
1519     * arg[0] = pointer to rs
1520     * arg[1] = pointer to rt
1521     * arg[2] = (int32_t) immediate value
1522     */
1523 dpavlin 24 X(addi)
1524     {
1525     int32_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1526     int32_t rt = rs + imm;
1527    
1528     if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1529     /* Synch. PC and cause an exception: */
1530     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1531     / sizeof(struct mips_instr_call);
1532     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1533     << MIPS_INSTR_ALIGNMENT_SHIFT);
1534     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1535     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1536     } else
1537     reg(ic->arg[1]) = rt;
1538     }
1539 dpavlin 22 X(addiu)
1540     {
1541     reg(ic->arg[1]) = (int32_t)
1542     ((int32_t)reg(ic->arg[0]) + (int32_t)ic->arg[2]);
1543     }
1544 dpavlin 24 X(daddi)
1545     {
1546     int64_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1547     int64_t rt = rs + imm;
1548 dpavlin 22
1549 dpavlin 24 if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1550     /* Synch. PC and cause an exception: */
1551     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1552     / sizeof(struct mips_instr_call);
1553     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1554     << MIPS_INSTR_ALIGNMENT_SHIFT);
1555     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1556     mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1557     } else
1558     reg(ic->arg[1]) = rt;
1559     }
1560 dpavlin 22 X(daddiu)
1561     {
1562     reg(ic->arg[1]) = reg(ic->arg[0]) + (int32_t)ic->arg[2];
1563     }
1564 dpavlin 24 X(slti)
1565     {
1566     reg(ic->arg[1]) = (MODE_int_t)reg(ic->arg[0]) < (int32_t)ic->arg[2];
1567     }
1568     X(sltiu)
1569     {
1570     reg(ic->arg[1]) = (MODE_uint_t)reg(ic->arg[0]) <
1571     ((MODE_uint_t)(int32_t)ic->arg[2]);
1572     }
1573 dpavlin 22
1574    
1575     /*
1576     * set: Set a register to an immediate (signed) 32-bit value.
1577     *
1578     * arg[0] = pointer to the register
1579     * arg[1] = (int32_t) immediate value
1580     */
1581     X(set)
1582     {
1583     reg(ic->arg[0]) = (int32_t)ic->arg[1];
1584     }
1585    
1586    
1587     /*
1588 dpavlin 24 * cfc0: Copy from Coprocessor 0.
1589 dpavlin 22 * mfc0, dmfc0: Move from Coprocessor 0.
1590     * mtc0, dmtc0: Move to Coprocessor 0.
1591     *
1592     * arg[0] = pointer to GPR (rt)
1593 dpavlin 24 * arg[1] = coprocessor 0 register number | (select << 5) (or for the
1594     * cfc0 instruction, the coprocessor control register number)
1595 dpavlin 22 * arg[2] = relative addr of this instruction within the page
1596     */
1597 dpavlin 24 X(cfc0)
1598     {
1599     int fs = ic->arg[1] & 31;
1600     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1601     cpu->pc |= ic->arg[2];
1602     /* TODO: cause exception if necessary */
1603     reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->fcr[fs];
1604     }
1605 dpavlin 22 X(mfc0)
1606     {
1607     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1608     uint64_t tmp;
1609     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1610     cpu->pc |= ic->arg[2];
1611     /* TODO: cause exception if necessary */
1612     coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, &tmp, select);
1613     reg(ic->arg[0]) = (int32_t)tmp;
1614     }
1615     X(mtc0)
1616     {
1617     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1618 dpavlin 24 uint64_t tmp = (int32_t) reg(ic->arg[0]);
1619     #if 0
1620     uint32_t oldstatus = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
1621     #endif
1622 dpavlin 22 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1623     cpu->pc |= ic->arg[2];
1624 dpavlin 24
1625 dpavlin 22 /* TODO: cause exception if necessary */
1626 dpavlin 24 coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd, &tmp, 0, select);
1627    
1628     #if 0
1629     /* Interrupts enabled, and any interrupt pending? */
1630     if (rd == COP0_STATUS && !(oldstatus & STATUS_IE)) {
1631     uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
1632     uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1633     /* NOTE: STATUS_IE happens to match the enable bit also
1634     on R2000/R3000, so this is ok. */
1635     if (status & STATUS_IE && (status & cause & STATUS_IM_MASK))
1636     cpu->running_translated = 0;
1637     }
1638     #endif
1639 dpavlin 22 }
1640     X(dmfc0)
1641     {
1642     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1643     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1644     cpu->pc |= ic->arg[2];
1645     /* TODO: cause exception if necessary */
1646     coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd,
1647     (uint64_t *)ic->arg[0], select);
1648     }
1649     X(dmtc0)
1650     {
1651     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1652     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1653     cpu->pc |= ic->arg[2];
1654     /* TODO: cause exception if necessary */
1655     coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,
1656     (uint64_t *)ic->arg[0], 1, select);
1657 dpavlin 24
1658     /* TODO: fix/remove these! */
1659     cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
1660 dpavlin 22 }
1661 dpavlin 24
1662    
1663     /*
1664     * cop1_bc: Floating point conditional branch.
1665     *
1666     * arg[0] = cc
1667     * arg[1] = nd (=2) and tf (=1) bits
1668     * arg[2] = offset (relative to start of this page)
1669     */
1670     X(cop1_bc)
1671 dpavlin 22 {
1672 dpavlin 24 MODE_int_t old_pc = cpu->pc;
1673     const int cpnr = 1;
1674     int x, low_pc, cc = ic->arg[0];
1675    
1676     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1677     / sizeof(struct mips_instr_call);
1678     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1679     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1680     if (!(cpu->cd.mips.coproc[0]->
1681     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1682     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1683     return;
1684     }
1685    
1686     /* Get the correct condition code bit: */
1687     if (cc == 0)
1688     x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1689     >> MIPS_FCSR_FCC0_SHIFT) & 1;
1690     else
1691     x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1692     >> (MIPS_FCSR_FCC1_SHIFT + cc-1)) & 1;
1693    
1694     /* Branch on false? Then invert the truth value. */
1695     if (!(ic->arg[1] & 1))
1696     x ^= 1;
1697    
1698     /* Execute the delay slot (except if it is nullified): */
1699     cpu->delay_slot = TO_BE_DELAYED;
1700     if (x || !(ic->arg[1] & 2))
1701     ic[1].f(cpu, ic+1);
1702     cpu->n_translated_instrs ++;
1703    
1704     if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1705     /* Note: Must be non-delayed when jumping to the new pc: */
1706     cpu->delay_slot = NOT_DELAYED;
1707     if (x) {
1708     old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1709     MIPS_INSTR_ALIGNMENT_SHIFT);
1710     cpu->pc = old_pc + (int32_t)ic->arg[2];
1711     quick_pc_to_pointers(cpu);
1712     } else
1713     cpu->cd.mips.next_ic ++;
1714     } else
1715     cpu->delay_slot = NOT_DELAYED;
1716     }
1717    
1718    
1719     /*
1720     * cop1_slow: Fallback to legacy cop1 code. (Slow, but it should work.)
1721     */
1722     X(cop1_slow)
1723     {
1724     const int cpnr = 1;
1725     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1726     / sizeof(struct mips_instr_call);
1727     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1728     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1729    
1730     if (!(cpu->cd.mips.coproc[0]->
1731     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1732     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1733     return;
1734     }
1735    
1736     coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);
1737     }
1738    
1739    
1740     /*
1741     * syscall, break: Synchronize the PC and cause an exception.
1742     */
1743     X(syscall)
1744     {
1745     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1746     / sizeof(struct mips_instr_call);
1747     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1748     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1749     mips_cpu_exception(cpu, EXCEPTION_SYS, 0, 0, 0, 0, 0, 0);
1750     }
1751     X(break)
1752     {
1753     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1754     / sizeof(struct mips_instr_call);
1755     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1756     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1757     mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1758     }
1759    
1760    
1761     /*
1762     * promemul: PROM software emulation.
1763     */
1764     X(promemul)
1765     {
1766     /* Synchronize the PC and call the correct emulation layer: */
1767     MODE_int_t old_pc;
1768     int res, low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1769     / sizeof(struct mips_instr_call);
1770     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1771     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1772     old_pc = cpu->pc;
1773    
1774     switch (cpu->machine->machine_type) {
1775     case MACHINE_PMAX:
1776     res = decstation_prom_emul(cpu);
1777     break;
1778     case MACHINE_PS2:
1779     res = playstation2_sifbios_emul(cpu);
1780     break;
1781     case MACHINE_ARC:
1782     case MACHINE_SGI:
1783     res = arcbios_emul(cpu);
1784     break;
1785     case MACHINE_EVBMIPS:
1786     res = yamon_emul(cpu);
1787     break;
1788     default:fatal("TODO: Unimplemented machine type for PROM magic trap\n");
1789     exit(1);
1790     }
1791    
1792     if (res) {
1793     /* Return from the PROM call: */
1794     cpu->pc = (MODE_int_t)cpu->cd.mips.gpr[MIPS_GPR_RA];
1795     cpu->delay_slot = NOT_DELAYED;
1796    
1797     if (cpu->machine->show_trace_tree)
1798     cpu_functioncall_trace_return(cpu);
1799     } else {
1800     /* The PROM call blocks. */
1801     cpu->n_translated_instrs += 10;
1802     cpu->pc = old_pc;
1803     }
1804    
1805     quick_pc_to_pointers(cpu);
1806     }
1807    
1808    
1809     /*
1810     * tlbw: TLB write indexed and random
1811     *
1812     * arg[0] = 1 for random, 0 for indexed
1813     * arg[2] = relative addr of this instruction within the page
1814     */
1815     X(tlbw)
1816     {
1817 dpavlin 22 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1818     cpu->pc |= ic->arg[2];
1819 dpavlin 24 coproc_tlbwri(cpu, ic->arg[0]);
1820 dpavlin 22 }
1821    
1822    
1823 dpavlin 24 /*
1824     * tlbp: TLB probe
1825     * tlbr: TLB read
1826     *
1827     * arg[2] = relative addr of this instruction within the page
1828     */
1829     X(tlbp)
1830     {
1831     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1832     cpu->pc |= ic->arg[2];
1833     coproc_tlbpr(cpu, 0);
1834     }
1835     X(tlbr)
1836     {
1837     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1838     cpu->pc |= ic->arg[2];
1839     coproc_tlbpr(cpu, 1);
1840     }
1841    
1842    
1843     /*
1844     * rfe: Return from exception handler (R2000/R3000)
1845     */
1846     X(rfe)
1847     {
1848     coproc_rfe(cpu);
1849    
1850     /* Note: no pc to pointers conversion is necessary here. */
1851     }
1852    
1853    
1854     /*
1855     * eret: Return from exception handler
1856     */
1857     X(eret)
1858     {
1859     coproc_eret(cpu);
1860     quick_pc_to_pointers(cpu);
1861     }
1862    
1863    
1864     /*
1865     * deret: Return from debug (EJTAG) handler
1866     */
1867     X(deret)
1868     {
1869     /*
1870     * According to the MIPS64 manual, deret loads PC from the DEPC cop0
1871     * register, and jumps there immediately. No delay slot.
1872     *
1873     * TODO: This instruction is only available if the processor is in
1874     * debug mode. (What does that mean?)
1875     *
1876     * TODO: This instruction is undefined in a delay slot.
1877     */
1878    
1879     cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_DEPC];
1880     cpu->delay_slot = 0;
1881     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1882     quick_pc_to_pointers(cpu);
1883     }
1884    
1885    
1886     /*
1887     * rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
1888     *
1889     * arg[0] = ptr to rt (destination register)
1890     */
1891     X(rdhwr_cpunum)
1892     {
1893     reg(ic->arg[0]) = cpu->cpu_id;
1894     }
1895    
1896    
1897     #include "tmp_mips_loadstore.c"
1898    
1899    
1900     /*
1901     * Load linked / store conditional:
1902     *
1903     * A Load-linked instruction initiates a RMW (read-modify-write) sequence.
1904     * COP0_LLADDR is updated for diagnostic purposes, except for CPUs in the
1905     * R10000 family.
1906     *
1907     * A Store-conditional instruction ends the sequence.
1908     *
1909     * arg[0] = ptr to rt
1910     * arg[1] = ptr to rs
1911     * arg[2] = int32_t imm
1912     */
1913     X(ll)
1914     {
1915     MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1916     int low_pc;
1917     uint8_t word[sizeof(uint32_t)];
1918    
1919     /* Synch. PC and load using slow memory_rw(): */
1920     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1921     / sizeof(struct mips_instr_call);
1922     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1923     << MIPS_INSTR_ALIGNMENT_SHIFT);
1924     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1925    
1926     if (addr & (sizeof(word)-1)) {
1927     fatal("TODO: load linked unaligned access: exception\n");
1928     exit(1);
1929     }
1930    
1931     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
1932     sizeof(word), MEM_READ, CACHE_DATA)) {
1933     /* An exception occurred. */
1934     return;
1935     }
1936    
1937     cpu->cd.mips.rmw = 1;
1938     cpu->cd.mips.rmw_addr = addr;
1939     cpu->cd.mips.rmw_len = sizeof(word);
1940     if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
1941     cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
1942     (addr >> 4) & 0xffffffffULL;
1943    
1944     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1945     reg(ic->arg[0]) = (int32_t) (word[0] + (word[1] << 8)
1946     + (word[2] << 16) + (word[3] << 24));
1947     else
1948     reg(ic->arg[0]) = (int32_t) (word[3] + (word[2] << 8)
1949     + (word[1] << 16) + (word[0] << 24));
1950     }
1951     X(lld)
1952     {
1953     MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1954     int low_pc;
1955     uint8_t word[sizeof(uint64_t)];
1956    
1957     /* Synch. PC and load using slow memory_rw(): */
1958     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1959     / sizeof(struct mips_instr_call);
1960     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1961     << MIPS_INSTR_ALIGNMENT_SHIFT);
1962     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1963    
1964     if (addr & (sizeof(word)-1)) {
1965     fatal("TODO: load linked unaligned access: exception\n");
1966     exit(1);
1967     }
1968    
1969     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
1970     sizeof(word), MEM_READ, CACHE_DATA)) {
1971     /* An exception occurred. */
1972     return;
1973     }
1974    
1975     cpu->cd.mips.rmw = 1;
1976     cpu->cd.mips.rmw_addr = addr;
1977     cpu->cd.mips.rmw_len = sizeof(word);
1978     if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
1979     cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
1980     (addr >> 4) & 0xffffffffULL;
1981    
1982     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
1983     reg(ic->arg[0]) = word[0] + (word[1] << 8)
1984     + (word[2] << 16) + ((uint64_t)word[3] << 24) +
1985     + ((uint64_t)word[4] << 32) + ((uint64_t)word[5] << 40)
1986     + ((uint64_t)word[6] << 48) + ((uint64_t)word[7] << 56);
1987     else
1988     reg(ic->arg[0]) = word[7] + (word[6] << 8)
1989     + (word[5] << 16) + ((uint64_t)word[4] << 24) +
1990     + ((uint64_t)word[3] << 32) + ((uint64_t)word[2] << 40)
1991     + ((uint64_t)word[1] << 48) + ((uint64_t)word[0] << 56);
1992     }
1993     X(sc)
1994     {
1995     MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
1996     uint64_t r = reg(ic->arg[0]);
1997     int low_pc, i;
1998     uint8_t word[sizeof(uint32_t)];
1999    
2000     /* Synch. PC and store using slow memory_rw(): */
2001     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2002     / sizeof(struct mips_instr_call);
2003     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2004     << MIPS_INSTR_ALIGNMENT_SHIFT);
2005     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2006    
2007     if (addr & (sizeof(word)-1)) {
2008     fatal("TODO: sc unaligned access: exception\n");
2009     exit(1);
2010     }
2011    
2012     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2013     word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2014     } else {
2015     word[3]=r; word[2]=r>>8; word[1]=r>>16; word[0]=r>>24;
2016     }
2017    
2018     /* If rmw is 0, then the store failed. (This cache-line was written
2019     to by someone else.) */
2020     if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2021     || cpu->cd.mips.rmw_len != sizeof(word)) {
2022     reg(ic->arg[0]) = 0;
2023     cpu->cd.mips.rmw = 0;
2024     return;
2025     }
2026    
2027     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2028     sizeof(word), MEM_WRITE, CACHE_DATA)) {
2029     /* An exception occurred. */
2030     return;
2031     }
2032    
2033     /* We succeeded. Let's invalidate everybody else's store to this
2034     cache line: */
2035     for (i=0; i<cpu->machine->ncpus; i++) {
2036     if (cpu->machine->cpus[i]->cd.mips.rmw) {
2037     uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2038     cd.mips.rmw_addr;
2039     uint64_t mask = ~(cpu->machine->cpus[i]->
2040     cd.mips.cache_linesize[CACHE_DATA] - 1);
2041     xaddr &= mask;
2042     yaddr &= mask;
2043     if (xaddr == yaddr)
2044     cpu->machine->cpus[i]->cd.mips.rmw = 0;
2045     }
2046     }
2047    
2048     reg(ic->arg[0]) = 1;
2049     cpu->cd.mips.rmw = 0;
2050     }
2051     X(scd)
2052     {
2053     MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2054     uint64_t r = reg(ic->arg[0]);
2055     int low_pc, i;
2056     uint8_t word[sizeof(uint64_t)];
2057    
2058     /* Synch. PC and store using slow memory_rw(): */
2059     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2060     / sizeof(struct mips_instr_call);
2061     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2062     << MIPS_INSTR_ALIGNMENT_SHIFT);
2063     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2064    
2065     if (addr & (sizeof(word)-1)) {
2066     fatal("TODO: sc unaligned access: exception\n");
2067     exit(1);
2068     }
2069    
2070     if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2071     word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2072     word[4]=r>>32; word[5]=r>>40; word[6]=r>>48; word[7]=r>>56;
2073     } else {
2074     word[7]=r; word[6]=r>>8; word[5]=r>>16; word[4]=r>>24;
2075     word[3]=r>>32; word[2]=r>>40; word[1]=r>>48; word[0]=r>>56;
2076     }
2077    
2078     /* If rmw is 0, then the store failed. (This cache-line was written
2079     to by someone else.) */
2080     if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2081     || cpu->cd.mips.rmw_len != sizeof(word)) {
2082     reg(ic->arg[0]) = 0;
2083     cpu->cd.mips.rmw = 0;
2084     return;
2085     }
2086    
2087     if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2088     sizeof(word), MEM_WRITE, CACHE_DATA)) {
2089     /* An exception occurred. */
2090     return;
2091     }
2092    
2093     /* We succeeded. Let's invalidate everybody else's store to this
2094     cache line: */
2095     for (i=0; i<cpu->machine->ncpus; i++) {
2096     if (cpu->machine->cpus[i]->cd.mips.rmw) {
2097     uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2098     cd.mips.rmw_addr;
2099     uint64_t mask = ~(cpu->machine->cpus[i]->
2100     cd.mips.cache_linesize[CACHE_DATA] - 1);
2101     xaddr &= mask;
2102     yaddr &= mask;
2103     if (xaddr == yaddr)
2104     cpu->machine->cpus[i]->cd.mips.rmw = 0;
2105     }
2106     }
2107    
2108     reg(ic->arg[0]) = 1;
2109     cpu->cd.mips.rmw = 0;
2110     }
2111    
2112    
2113     /*
2114     * lwc1, swc1: Coprocessor 1 load/store (32-bit)
2115     * ldc1, sdc1: Coprocessor 1 load/store (64-bit)
2116     *
2117     * arg[0] = ptr to coprocessor register
2118     * arg[1] = ptr to rs (base pointer register)
2119     * arg[2] = int32_t imm
2120     */
2121     X(lwc1)
2122     {
2123     const int cpnr = 1;
2124    
2125     /* Synch. PC and call the generic load/store function: */
2126     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2127     / sizeof(struct mips_instr_call);
2128     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2129     << MIPS_INSTR_ALIGNMENT_SHIFT);
2130     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2131    
2132     /* ... but first, let's see if the coprocessor is available: */
2133     if (!(cpu->cd.mips.coproc[0]->
2134     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2135     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2136     return;
2137     }
2138    
2139     #ifdef MODE32
2140     mips32_loadstore
2141     #else
2142     mips_loadstore
2143     #endif
2144     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 2 * 2 + 1]
2145     (cpu, ic);
2146     }
2147     X(swc1)
2148     {
2149     const int cpnr = 1;
2150    
2151     /* Synch. PC and call the generic load/store function: */
2152     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2153     / sizeof(struct mips_instr_call);
2154     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2155     << MIPS_INSTR_ALIGNMENT_SHIFT);
2156     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2157    
2158     /* ... but first, let's see if the coprocessor is available: */
2159     if (!(cpu->cd.mips.coproc[0]->
2160     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2161     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2162     return;
2163     }
2164    
2165     #ifdef MODE32
2166     mips32_loadstore
2167     #else
2168     mips_loadstore
2169     #endif
2170     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 2 * 2]
2171     (cpu, ic);
2172     }
2173     X(ldc1)
2174     {
2175     const int cpnr = 1;
2176     int use_fp_pairs =
2177     !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2178     uint64_t fpr, *backup_ptr;
2179    
2180     /* Synch. PC and call the generic load/store function: */
2181     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2182     / sizeof(struct mips_instr_call);
2183     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2184     << MIPS_INSTR_ALIGNMENT_SHIFT);
2185     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2186    
2187     /* ... but first, let's see if the coprocessor is available: */
2188     if (!(cpu->cd.mips.coproc[0]->
2189     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2190     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2191     return;
2192     }
2193    
2194     backup_ptr = (uint64_t *) ic->arg[0];
2195     ic->arg[0] = (size_t) &fpr;
2196    
2197     #ifdef MODE32
2198     mips32_loadstore
2199     #else
2200     mips_loadstore
2201     #endif
2202     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 3 * 2 + 1]
2203     (cpu, ic);
2204    
2205     if (use_fp_pairs) {
2206     backup_ptr[0] = (int64_t)(int32_t) fpr;
2207     backup_ptr[1] = (int64_t)(int32_t) (fpr >> 32);
2208     } else {
2209     *backup_ptr = fpr;
2210     }
2211    
2212     ic->arg[0] = (size_t) backup_ptr;
2213     }
2214     X(sdc1)
2215     {
2216     const int cpnr = 1;
2217     int use_fp_pairs =
2218     !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2219     uint64_t fpr, *backup_ptr;
2220    
2221     /* Synch. PC and call the generic load/store function: */
2222     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2223     / sizeof(struct mips_instr_call);
2224     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2225     << MIPS_INSTR_ALIGNMENT_SHIFT);
2226     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2227    
2228     /* ... but first, let's see if the coprocessor is available: */
2229     if (!(cpu->cd.mips.coproc[0]->
2230     reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2231     mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2232     return;
2233     }
2234    
2235     backup_ptr = (uint64_t *) ic->arg[0];
2236     ic->arg[0] = (size_t) &fpr;
2237    
2238     if (use_fp_pairs) {
2239     uint32_t lo = backup_ptr[0];
2240     uint32_t hi = backup_ptr[1];
2241     fpr = (((uint64_t)hi) << 32) | lo;
2242     } else {
2243     fpr = *backup_ptr;
2244     }
2245    
2246     #ifdef MODE32
2247     mips32_loadstore
2248     #else
2249     mips_loadstore
2250     #endif
2251     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 3 * 2]
2252     (cpu, ic);
2253    
2254     ic->arg[0] = (size_t) backup_ptr;
2255     }
2256    
2257    
2258     /*
2259     * Unaligned loads/stores:
2260     *
2261     * arg[0] = ptr to rt
2262     * arg[1] = ptr to rs
2263     * arg[2] = int32_t imm
2264     */
2265     X(lwl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 0); }
2266     X(lwr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 0); }
2267     X(ldl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 0); }
2268     X(ldr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 0); }
2269     X(swl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 1); }
2270     X(swr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 1); }
2271     X(sdl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 1); }
2272     X(sdr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 1); }
2273    
2274    
2275     /*
2276     * di, ei: R5900 interrupt enable/disable.
2277     *
2278     * TODO: check the R5900_STATUS_EDI bit in the status register. If it is
2279     * cleared, and we are not running in kernel mode, then both the EI and DI
2280     * instructions should be treated as NOPs!
2281     */
2282     X(di_r5900)
2283     {
2284     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2285     }
2286     X(ei_r5900)
2287     {
2288     cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2289     }
2290    
2291    
2292 dpavlin 22 /*****************************************************************************/
2293    
2294    
2295     /*
2296     * b_samepage_addiu:
2297     *
2298     * Combination of branch within the same page, followed by addiu.
2299     */
2300     X(b_samepage_addiu)
2301     {
2302 dpavlin 24 reg(ic[1].arg[1]) = (int32_t)
2303     ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
2304 dpavlin 22 cpu->n_translated_instrs ++;
2305     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2306     }
2307    
2308    
2309 dpavlin 24 /*
2310     * b_samepage_daddiu:
2311     *
2312     * Combination of branch within the same page, followed by daddiu.
2313     */
2314     X(b_samepage_daddiu)
2315     {
2316     *(uint64_t *)ic[1].arg[1] = *(uint64_t *)ic[1].arg[0] +
2317     (int32_t)ic[1].arg[2];
2318     cpu->n_translated_instrs ++;
2319     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2320     }
2321    
2322    
2323 dpavlin 22 /*****************************************************************************/
2324    
2325    
2326     X(end_of_page)
2327     {
2328     /* Update the PC: (offset 0, but on the next page) */
2329     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
2330     MIPS_INSTR_ALIGNMENT_SHIFT);
2331     cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);
2332    
2333 dpavlin 24 /* end_of_page doesn't count as an executed instruction: */
2334     cpu->n_translated_instrs --;
2335 dpavlin 22
2336 dpavlin 24 /*
2337     * Find the new physpage and update translation pointers.
2338     *
2339     * Note: This may cause an exception, if e.g. the new page is
2340     * not accessible.
2341     */
2342     quick_pc_to_pointers(cpu);
2343 dpavlin 22
2344 dpavlin 24 /* Simple jump to the next page (if we are lucky): */
2345     if (cpu->delay_slot == NOT_DELAYED)
2346     return;
2347 dpavlin 22
2348 dpavlin 24 /*
2349     * If we were in a delay slot, and we got an exception while doing
2350     * quick_pc_to_pointers, then return. The function which called
2351     * end_of_page should handle this case.
2352     */
2353     if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
2354 dpavlin 22 return;
2355    
2356 dpavlin 24 /*
2357     * Tricky situation; the delay slot is on the next virtual page.
2358     * Calling to_be_translated will translate one instruction manually,
2359     * execute it, and then discard it.
2360     */
2361 dpavlin 22 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
2362    
2363 dpavlin 24 instr(to_be_translated)(cpu, cpu->cd.mips.next_ic);
2364 dpavlin 22
2365     /* The instruction in the delay slot has now executed. */
2366 dpavlin 24 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
2367     cpu->delay_slot); */
2368 dpavlin 22
2369     /* Find the physpage etc of the instruction in the delay slot
2370     (or, if there was an exception, the exception handler): */
2371     quick_pc_to_pointers(cpu);
2372     }
2373    
2374    
2375     X(end_of_page2)
2376     {
2377 dpavlin 24 /* Synchronize PC on the _second_ instruction on the next page: */
2378     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2379     / sizeof(struct mips_instr_call);
2380     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2381     << MIPS_INSTR_ALIGNMENT_SHIFT);
2382     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2383 dpavlin 22
2384 dpavlin 24 /* This doesn't count as an executed instruction. */
2385     cpu->n_translated_instrs --;
2386 dpavlin 22
2387 dpavlin 24 quick_pc_to_pointers(cpu);
2388 dpavlin 22
2389 dpavlin 24 if (cpu->delay_slot == NOT_DELAYED)
2390 dpavlin 22 return;
2391    
2392 dpavlin 24 fatal("end_of_page2: fatal error, we're in a delay slot\n");
2393 dpavlin 22 exit(1);
2394     }
2395    
2396    
2397     /*****************************************************************************/
2398    
2399    
2400     /*
2401     * Combine: [Conditional] branch, followed by addiu.
2402     */
2403     void COMBINE(b_addiu)(struct cpu *cpu, struct mips_instr_call *ic,
2404     int low_addr)
2405     {
2406     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2407     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2408    
2409     if (n_back < 1)
2410     return;
2411    
2412     if (ic[-1].f == instr(b_samepage)) {
2413     ic[-1].f = instr(b_samepage_addiu);
2414     combined;
2415     }
2416    
2417     /* TODO: other branches that are followed by addiu should be here */
2418     }
2419    
2420    
2421 dpavlin 24 /*
2422     * Combine: [Conditional] branch, followed by daddiu.
2423     */
2424     void COMBINE(b_daddiu)(struct cpu *cpu, struct mips_instr_call *ic,
2425     int low_addr)
2426     {
2427     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2428     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2429    
2430     if (n_back < 1)
2431     return;
2432    
2433     if (ic[-1].f == instr(b_samepage)) {
2434     ic[-1].f = instr(b_samepage_daddiu);
2435     combined;
2436     }
2437    
2438     /* TODO: other branches that are followed by daddiu should be here */
2439     }
2440    
2441    
2442 dpavlin 22 /*****************************************************************************/
2443    
2444    
2445     /*
2446     * mips_instr_to_be_translated():
2447     *
2448 dpavlin 24 * Translate an instruction word into a mips_instr_call. ic is filled in with
2449 dpavlin 22 * valid data for the translated instruction, or a "nothing" instruction if
2450     * there was a translation failure. The newly translated instruction is then
2451     * executed.
2452     */
2453     X(to_be_translated)
2454     {
2455     uint64_t addr, low_pc;
2456     uint32_t iword, imm;
2457     unsigned char *page;
2458     unsigned char ib[4];
2459     int main_opcode, rt, rs, rd, sa, s6, x64 = 0;
2460     int in_crosspage_delayslot = 0;
2461     void (*samepage_function)(struct cpu *, struct mips_instr_call *);
2462 dpavlin 24 int store, signedness, size;
2463 dpavlin 22
2464     /* Figure out the (virtual) address of the instruction: */
2465     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2466     / sizeof(struct mips_instr_call);
2467    
2468     /* Special case for branch with delayslot on the next page: */
2469 dpavlin 24 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
2470     /* fatal("[ delay-slot translation across page "
2471     "boundary ]\n"); */
2472 dpavlin 22 in_crosspage_delayslot = 1;
2473     }
2474    
2475     addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2476     << MIPS_INSTR_ALIGNMENT_SHIFT);
2477     addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2478 dpavlin 24 cpu->pc = (MODE_int_t)addr;
2479 dpavlin 22 addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
2480    
2481     /* Read the instruction word from memory: */
2482 dpavlin 24 #ifdef MODE32
2483 dpavlin 22 page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
2484 dpavlin 24 #else
2485     {
2486     const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
2487     const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
2488     const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
2489     uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
2490     uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
2491     uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
2492     DYNTRANS_L3N)) & mask3;
2493     struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.mips.l1_64[x1];
2494     struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
2495     page = l3->host_load[x3];
2496     }
2497     #endif
2498 dpavlin 22
2499     if (page != NULL) {
2500     /* fatal("TRANSLATION HIT!\n"); */
2501 dpavlin 24 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
2502 dpavlin 22 } else {
2503     /* fatal("TRANSLATION MISS!\n"); */
2504     if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2505     sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
2506 dpavlin 24 fatal("to_be_translated(): read failed: TODO\n");
2507 dpavlin 22 goto bad;
2508     }
2509     }
2510    
2511     iword = *((uint32_t *)&ib[0]);
2512    
2513     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2514     iword = LE32_TO_HOST(iword);
2515     else
2516     iword = BE32_TO_HOST(iword);
2517    
2518    
2519     #define DYNTRANS_TO_BE_TRANSLATED_HEAD
2520     #include "cpu_dyntrans.c"
2521     #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
2522    
2523    
2524     /*
2525     * Translate the instruction:
2526     *
2527 dpavlin 24 * NOTE: _NEVER_ allow writes to the zero register; all instructions
2528     * that use the zero register as their destination should be treated
2529     * as NOPs, except those that access memory (they should use the
2530     * scratch register instead).
2531 dpavlin 22 */
2532    
2533     main_opcode = iword >> 26;
2534     rs = (iword >> 21) & 31;
2535     rt = (iword >> 16) & 31;
2536     rd = (iword >> 11) & 31;
2537     sa = (iword >> 6) & 31;
2538     imm = (int16_t)iword;
2539     s6 = iword & 63;
2540    
2541     switch (main_opcode) {
2542    
2543     case HI6_SPECIAL:
2544     switch (s6) {
2545    
2546     case SPECIAL_SLL:
2547 dpavlin 24 case SPECIAL_SLLV:
2548 dpavlin 22 case SPECIAL_SRL:
2549 dpavlin 24 case SPECIAL_SRLV:
2550 dpavlin 22 case SPECIAL_SRA:
2551 dpavlin 24 case SPECIAL_SRAV:
2552     case SPECIAL_DSRL:
2553     case SPECIAL_DSRLV:
2554     case SPECIAL_DSRL32:
2555     case SPECIAL_DSLL:
2556     case SPECIAL_DSLLV:
2557     case SPECIAL_DSLL32:
2558     case SPECIAL_DSRA:
2559     case SPECIAL_DSRAV:
2560     case SPECIAL_DSRA32:
2561 dpavlin 22 switch (s6) {
2562     case SPECIAL_SLL: ic->f = instr(sll); break;
2563 dpavlin 24 case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
2564 dpavlin 22 case SPECIAL_SRL: ic->f = instr(srl); break;
2565 dpavlin 24 case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
2566 dpavlin 22 case SPECIAL_SRA: ic->f = instr(sra); break;
2567 dpavlin 24 case SPECIAL_SRAV: ic->f = instr(srav); sa = -1; break;
2568     case SPECIAL_DSRL: ic->f = instr(dsrl); x64=1; break;
2569     case SPECIAL_DSRLV:ic->f = instr(dsrlv);
2570     x64 = 1; sa = -1; break;
2571     case SPECIAL_DSRL32:ic->f= instr(dsrl); x64=1;
2572     sa += 32; break;
2573     case SPECIAL_DSLL: ic->f = instr(dsll); x64=1; break;
2574     case SPECIAL_DSLLV:ic->f = instr(dsllv);
2575     x64 = 1; sa = -1; break;
2576     case SPECIAL_DSLL32:ic->f= instr(dsll); x64=1;
2577     sa += 32; break;
2578     case SPECIAL_DSRA: ic->f = instr(dsra); x64=1; break;
2579     case SPECIAL_DSRAV:ic->f = instr(dsrav);
2580     x64 = 1; sa = -1; break;
2581     case SPECIAL_DSRA32:ic->f = instr(dsra); x64=1;
2582     sa += 32; break;
2583 dpavlin 22 }
2584     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2585 dpavlin 24 if (sa >= 0)
2586     ic->arg[1] = sa;
2587     else
2588     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
2589 dpavlin 22 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
2590     if (rd == MIPS_GPR_ZERO)
2591     ic->f = instr(nop);
2592     break;
2593    
2594 dpavlin 24 case SPECIAL_ADD:
2595 dpavlin 22 case SPECIAL_ADDU:
2596 dpavlin 24 case SPECIAL_SUB:
2597 dpavlin 22 case SPECIAL_SUBU:
2598 dpavlin 24 case SPECIAL_DADD:
2599 dpavlin 22 case SPECIAL_DADDU:
2600 dpavlin 24 case SPECIAL_DSUB:
2601 dpavlin 22 case SPECIAL_DSUBU:
2602     case SPECIAL_SLT:
2603     case SPECIAL_SLTU:
2604 dpavlin 24 case SPECIAL_AND:
2605 dpavlin 22 case SPECIAL_OR:
2606     case SPECIAL_XOR:
2607     case SPECIAL_NOR:
2608 dpavlin 24 case SPECIAL_MOVN:
2609     case SPECIAL_MOVZ:
2610 dpavlin 22 case SPECIAL_MFHI:
2611     case SPECIAL_MFLO:
2612     case SPECIAL_MTHI:
2613     case SPECIAL_MTLO:
2614 dpavlin 24 case SPECIAL_DIV:
2615     case SPECIAL_DIVU:
2616     case SPECIAL_DDIV:
2617     case SPECIAL_DDIVU:
2618     case SPECIAL_MULT:
2619     case SPECIAL_MULTU:
2620     case SPECIAL_DMULT:
2621     case SPECIAL_DMULTU:
2622     case SPECIAL_TGE:
2623     case SPECIAL_TGEU:
2624     case SPECIAL_TLT:
2625     case SPECIAL_TLTU:
2626     case SPECIAL_TEQ:
2627     case SPECIAL_TNE:
2628 dpavlin 22 switch (s6) {
2629 dpavlin 24 case SPECIAL_ADD: ic->f = instr(add); break;
2630 dpavlin 22 case SPECIAL_ADDU: ic->f = instr(addu); break;
2631 dpavlin 24 case SPECIAL_SUB: ic->f = instr(sub); break;
2632 dpavlin 22 case SPECIAL_SUBU: ic->f = instr(subu); break;
2633 dpavlin 24 case SPECIAL_DADD: ic->f = instr(dadd); x64=1; break;
2634 dpavlin 22 case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
2635 dpavlin 24 case SPECIAL_DSUB: ic->f = instr(dsub); x64=1; break;
2636 dpavlin 22 case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;
2637     case SPECIAL_SLT: ic->f = instr(slt); break;
2638     case SPECIAL_SLTU: ic->f = instr(sltu); break;
2639 dpavlin 24 case SPECIAL_AND: ic->f = instr(and); break;
2640 dpavlin 22 case SPECIAL_OR: ic->f = instr(or); break;
2641     case SPECIAL_XOR: ic->f = instr(xor); break;
2642     case SPECIAL_NOR: ic->f = instr(nor); break;
2643     case SPECIAL_MFHI: ic->f = instr(mov); break;
2644     case SPECIAL_MFLO: ic->f = instr(mov); break;
2645     case SPECIAL_MTHI: ic->f = instr(mov); break;
2646     case SPECIAL_MTLO: ic->f = instr(mov); break;
2647 dpavlin 24 case SPECIAL_DIV: ic->f = instr(div); break;
2648     case SPECIAL_DIVU: ic->f = instr(divu); break;
2649     case SPECIAL_DDIV: ic->f = instr(ddiv); x64=1; break;
2650     case SPECIAL_DDIVU: ic->f = instr(ddivu); x64=1; break;
2651     case SPECIAL_MULT : ic->f = instr(mult); break;
2652     case SPECIAL_MULTU: ic->f = instr(multu); break;
2653     case SPECIAL_DMULT: ic->f = instr(dmult); x64=1; break;
2654     case SPECIAL_DMULTU:ic->f = instr(dmultu); x64=1; break;
2655     case SPECIAL_TGE: ic->f = instr(tge); break;
2656     case SPECIAL_TGEU: ic->f = instr(tgeu); break;
2657     case SPECIAL_TLT: ic->f = instr(tlt); break;
2658     case SPECIAL_TLTU: ic->f = instr(tltu); break;
2659     case SPECIAL_TEQ: ic->f = instr(teq); break;
2660     case SPECIAL_TNE: ic->f = instr(tne); break;
2661     case SPECIAL_MOVN: ic->f = instr(movn); break;
2662     case SPECIAL_MOVZ: ic->f = instr(movz); break;
2663 dpavlin 22 }
2664     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2665     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
2666     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
2667     switch (s6) {
2668     case SPECIAL_MFHI:
2669     ic->arg[0] = (size_t)&cpu->cd.mips.hi;
2670     break;
2671     case SPECIAL_MFLO:
2672     ic->arg[0] = (size_t)&cpu->cd.mips.lo;
2673     break;
2674     case SPECIAL_MTHI:
2675     ic->arg[2] = (size_t)&cpu->cd.mips.hi;
2676     break;
2677     case SPECIAL_MTLO:
2678     ic->arg[2] = (size_t)&cpu->cd.mips.lo;
2679     break;
2680     }
2681 dpavlin 24 /* Special cases for rd: */
2682 dpavlin 22 switch (s6) {
2683     case SPECIAL_MTHI:
2684     case SPECIAL_MTLO:
2685 dpavlin 24 case SPECIAL_DIV:
2686     case SPECIAL_DIVU:
2687     case SPECIAL_DDIV:
2688     case SPECIAL_DDIVU:
2689 dpavlin 22 case SPECIAL_MULT:
2690     case SPECIAL_MULTU:
2691     case SPECIAL_DMULT:
2692     case SPECIAL_DMULTU:
2693 dpavlin 24 case SPECIAL_TGE:
2694     case SPECIAL_TGEU:
2695     case SPECIAL_TLT:
2696     case SPECIAL_TLTU:
2697     case SPECIAL_TEQ:
2698     case SPECIAL_TNE:
2699     if (s6 == SPECIAL_MULT && rd != MIPS_GPR_ZERO) {
2700     if (cpu->cd.mips.cpu_type.rev ==
2701     MIPS_R5900) {
2702     ic->f = instr(mult_r5900);
2703     break;
2704     }
2705     break;
2706     }
2707     if (s6 == SPECIAL_MULTU && rd!=MIPS_GPR_ZERO) {
2708     if (cpu->cd.mips.cpu_type.rev ==
2709     MIPS_R5900) {
2710     ic->f = instr(multu_r5900);
2711     break;
2712     }
2713     }
2714 dpavlin 22 if (rd != MIPS_GPR_ZERO) {
2715 dpavlin 24 fatal("TODO: rd NON-zero\n");
2716 dpavlin 22 goto bad;
2717     }
2718 dpavlin 24 /* These instructions don't use rd. */
2719 dpavlin 22 break;
2720 dpavlin 24 default:if (rd == MIPS_GPR_ZERO)
2721     ic->f = instr(nop);
2722 dpavlin 22 }
2723     break;
2724    
2725     case SPECIAL_JR:
2726     case SPECIAL_JALR:
2727     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2728     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
2729 dpavlin 24 if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
2730     s6 = SPECIAL_JR;
2731     ic->arg[2] = (addr & 0xffc) + 8;
2732     switch (s6) {
2733 dpavlin 22 case SPECIAL_JR:
2734     if (rs == MIPS_GPR_RA) {
2735     if (cpu->machine->show_trace_tree)
2736     ic->f = instr(jr_ra_trace);
2737     else
2738     ic->f = instr(jr_ra);
2739     } else {
2740     ic->f = instr(jr);
2741     }
2742     break;
2743     case SPECIAL_JALR:
2744     if (cpu->machine->show_trace_tree)
2745     ic->f = instr(jalr_trace);
2746     else
2747     ic->f = instr(jalr);
2748     break;
2749     }
2750 dpavlin 24 if (cpu->delay_slot) {
2751     fatal("TODO: branch in delay slot? (1)\n");
2752     goto bad;
2753 dpavlin 22 }
2754     break;
2755    
2756 dpavlin 24 case SPECIAL_SYSCALL:
2757     if (((iword >> 6) & 0xfffff) == 0x30378) {
2758     /* "Magic trap" for PROM emulation: */
2759     ic->f = instr(promemul);
2760     } else {
2761     ic->f = instr(syscall);
2762     }
2763     break;
2764    
2765     case SPECIAL_BREAK:
2766     ic->f = instr(break);
2767     break;
2768    
2769 dpavlin 22 case SPECIAL_SYNC:
2770     ic->f = instr(nop);
2771     break;
2772    
2773     default:goto bad;
2774     }
2775     break;
2776    
2777     case HI6_BEQ:
2778     case HI6_BNE:
2779 dpavlin 24 case HI6_BEQL:
2780     case HI6_BNEL:
2781     case HI6_BLEZ:
2782     case HI6_BLEZL:
2783     case HI6_BGTZ:
2784     case HI6_BGTZL:
2785 dpavlin 22 samepage_function = NULL; /* get rid of a compiler warning */
2786     switch (main_opcode) {
2787     case HI6_BEQ:
2788     ic->f = instr(beq);
2789     samepage_function = instr(beq_samepage);
2790     /* Special case: comparing a register with itself: */
2791     if (rs == rt) {
2792     ic->f = instr(b);
2793     samepage_function = instr(b_samepage);
2794     }
2795     break;
2796     case HI6_BNE:
2797     ic->f = instr(bne);
2798     samepage_function = instr(bne_samepage);
2799 dpavlin 24 break;
2800     case HI6_BEQL:
2801     ic->f = instr(beql);
2802     samepage_function = instr(beql_samepage);
2803     /* Special case: comparing a register with itself: */
2804     if (rs == rt) {
2805     ic->f = instr(b);
2806     samepage_function = instr(b_samepage);
2807     }
2808     break;
2809     case HI6_BNEL:
2810     ic->f = instr(bnel);
2811     samepage_function = instr(bnel_samepage);
2812     break;
2813     case HI6_BLEZ:
2814     ic->f = instr(blez);
2815     samepage_function = instr(blez_samepage);
2816     break;
2817     case HI6_BLEZL:
2818     ic->f = instr(blezl);
2819     samepage_function = instr(blezl_samepage);
2820     break;
2821     case HI6_BGTZ:
2822     ic->f = instr(bgtz);
2823     samepage_function = instr(bgtz_samepage);
2824     break;
2825     case HI6_BGTZL:
2826     ic->f = instr(bgtzl);
2827     samepage_function = instr(bgtzl_samepage);
2828     break;
2829 dpavlin 22 }
2830     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2831     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
2832 dpavlin 24 ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
2833     + (addr & 0xffc) + 4 );
2834 dpavlin 22 /* Is the offset from the start of the current page still
2835     within the same page? Then use the samepage_function: */
2836     if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE - 1)
2837     << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc) < 0xffc) {
2838     ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page +
2839     ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
2840     & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
2841     ic->f = samepage_function;
2842     }
2843 dpavlin 24 if (cpu->delay_slot) {
2844     fatal("TODO: branch in delay slot? (2)\n");
2845     goto bad;
2846 dpavlin 22 }
2847     break;
2848    
2849 dpavlin 24 case HI6_ADDI:
2850 dpavlin 22 case HI6_ADDIU:
2851 dpavlin 24 case HI6_SLTI:
2852     case HI6_SLTIU:
2853     case HI6_DADDI:
2854 dpavlin 22 case HI6_DADDIU:
2855     case HI6_ANDI:
2856     case HI6_ORI:
2857     case HI6_XORI:
2858     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2859     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
2860     if (main_opcode == HI6_ADDI ||
2861     main_opcode == HI6_ADDIU ||
2862 dpavlin 24 main_opcode == HI6_SLTI ||
2863     main_opcode == HI6_SLTIU ||
2864 dpavlin 22 main_opcode == HI6_DADDI ||
2865     main_opcode == HI6_DADDIU)
2866     ic->arg[2] = (int16_t)iword;
2867     else
2868     ic->arg[2] = (uint16_t)iword;
2869 dpavlin 24
2870 dpavlin 22 switch (main_opcode) {
2871 dpavlin 24 case HI6_ADDI: ic->f = instr(addi); break;
2872 dpavlin 22 case HI6_ADDIU: ic->f = instr(addiu); break;
2873 dpavlin 24 case HI6_SLTI: ic->f = instr(slti); break;
2874     case HI6_SLTIU: ic->f = instr(sltiu); break;
2875     case HI6_DADDI: ic->f = instr(daddi); x64 = 1; break;
2876 dpavlin 22 case HI6_DADDIU: ic->f = instr(daddiu); x64 = 1; break;
2877     case HI6_ANDI: ic->f = instr(andi); break;
2878     case HI6_ORI: ic->f = instr(ori); break;
2879     case HI6_XORI: ic->f = instr(xori); break;
2880     }
2881 dpavlin 24
2882 dpavlin 22 if (rt == MIPS_GPR_ZERO)
2883     ic->f = instr(nop);
2884    
2885     if (ic->f == instr(addiu))
2886     cpu->cd.mips.combination_check = COMBINE(b_addiu);
2887 dpavlin 24 if (ic->f == instr(daddiu))
2888     cpu->cd.mips.combination_check = COMBINE(b_daddiu);
2889 dpavlin 22 break;
2890    
2891     case HI6_LUI:
2892     ic->f = instr(set);
2893     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2894 dpavlin 24 ic->arg[1] = (int32_t) (imm << 16);
2895 dpavlin 22 if (rt == MIPS_GPR_ZERO)
2896     ic->f = instr(nop);
2897     break;
2898    
2899 dpavlin 24 case HI6_J:
2900     case HI6_JAL:
2901     switch (main_opcode) {
2902     case HI6_J:
2903     ic->f = instr(j);
2904     break;
2905     case HI6_JAL:
2906     if (cpu->machine->show_trace_tree)
2907     ic->f = instr(jal_trace);
2908     else
2909     ic->f = instr(jal);
2910     break;
2911     }
2912     ic->arg[0] = (iword & 0x03ffffff) << 2;
2913     ic->arg[1] = (addr & 0xffc) + 8;
2914     if (cpu->delay_slot) {
2915     fatal("TODO: branch in delay slot (=%i)? (3); addr=%016"
2916     PRIx64" iword=%08"PRIx32"\n", cpu->delay_slot,
2917     (uint64_t)addr, iword);
2918     goto bad;
2919     }
2920     break;
2921    
2922 dpavlin 22 case HI6_COP0:
2923 dpavlin 24 /* TODO: Is checking bit 25 enough, or perhaps all bits
2924     25..21 must be checked? */
2925     if ((iword >> 25) & 1) {
2926     ic->arg[2] = addr & 0xffc;
2927     switch (iword & 0xff) {
2928     case COP0_TLBR:
2929     ic->f = instr(tlbr);
2930     break;
2931     case COP0_TLBWI:
2932     case COP0_TLBWR:
2933     ic->f = instr(tlbw);
2934     ic->arg[0] = (iword & 0xff) == COP0_TLBWR;
2935     break;
2936     case COP0_TLBP:
2937     ic->f = instr(tlbp);
2938     break;
2939     case COP0_RFE:
2940     ic->f = instr(rfe);
2941     break;
2942     case COP0_ERET:
2943     ic->f = instr(eret);
2944     break;
2945     case COP0_DERET:
2946     ic->f = instr(deret);
2947     break;
2948     case COP0_IDLE:
2949     case COP0_STANDBY:
2950     case COP0_SUSPEND:
2951     case COP0_HIBERNATE:
2952     /* TODO */
2953     ic->f = instr(nop);
2954     break;
2955     case COP0_EI:
2956     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
2957     ic->f = instr(ei_r5900);
2958     } else
2959     goto bad;
2960     break;
2961     case COP0_DI:
2962     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
2963     ic->f = instr(di_r5900);
2964     } else
2965     goto bad;
2966     break;
2967     default:fatal("UNIMPLEMENTED cop0 (func 0x%02x)\n",
2968     iword & 0xff);
2969     goto bad;
2970     }
2971     break;
2972     }
2973    
2974 dpavlin 22 /* rs contains the coprocessor opcode! */
2975     switch (rs) {
2976 dpavlin 24 case COPz_CFCz:
2977     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2978     ic->arg[1] = rd + ((iword & 7) << 5);
2979     ic->arg[2] = addr & 0xffc;
2980     ic->f = instr(cfc0);
2981     if (rt == MIPS_GPR_ZERO)
2982     ic->f = instr(nop);
2983     break;
2984 dpavlin 22 case COPz_MFCz:
2985     case COPz_DMFCz:
2986     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2987     ic->arg[1] = rd + ((iword & 7) << 5);
2988     ic->arg[2] = addr & 0xffc;
2989     ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0);
2990     if (rt == MIPS_GPR_ZERO)
2991     ic->f = instr(nop);
2992     break;
2993     case COPz_MTCz:
2994     case COPz_DMTCz:
2995     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2996     ic->arg[1] = rd + ((iword & 7) << 5);
2997     ic->arg[2] = addr & 0xffc;
2998     ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
2999     break;
3000 dpavlin 24 case 8: if (iword == 0x4100ffff) {
3001     /* R2020 DECstation write-loop thingy. */
3002     ic->f = instr(nop);
3003     } else {
3004     fatal("Unimplemented blah blah zzzz...\n");
3005     goto bad;
3006     }
3007     break;
3008    
3009 dpavlin 22 default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
3010     goto bad;
3011     }
3012     break;
3013    
3014     case HI6_COP1:
3015 dpavlin 24 /* Always cause a coprocessor unusable exception if
3016     there is no floating point coprocessor: */
3017     if (cpu->cd.mips.cpu_type.flags & NOFPU ||
3018     cpu->cd.mips.coproc[1] == NULL) {
3019     ic->f = instr(cpu);
3020     ic->arg[0] = 1;
3021     break;
3022     }
3023    
3024     /* Bits 25..21 are floating point main opcode: */
3025 dpavlin 22 switch (rs) {
3026 dpavlin 24
3027     case COPz_BCzc:
3028     /* Conditional branch: */
3029     /* TODO: Reimplement this in a faster way. */
3030     ic->f = instr(cop1_bc);
3031     ic->arg[0] = (iword >> 18) & 7; /* cc */
3032     ic->arg[1] = (iword >> 16) & 3; /* nd, tf bits */
3033     ic->arg[2] = (int32_t) ((imm <<
3034     MIPS_INSTR_ALIGNMENT_SHIFT) + (addr & 0xffc) + 4);
3035     if (cpu->delay_slot) {
3036     fatal("TODO: branch in delay slot? (4)\n");
3037     goto bad;
3038     }
3039     if (cpu->cd.mips.cpu_type.isa_level <= 3 &&
3040     ic->arg[0] != 0) {
3041     fatal("Attempt to execute a non-cc-0 BC*"
3042     " instruction on an isa level %i cpu. "
3043     "TODO: How should this be handled?\n",
3044     cpu->cd.mips.cpu_type.isa_level);
3045     goto bad;
3046     }
3047    
3048     break;
3049    
3050     case COPz_DMFCz:
3051     case COPz_DMTCz:
3052     x64 = 1;
3053     /* FALL-THROUGH */
3054     case COP1_FMT_S:
3055     case COP1_FMT_D:
3056     case COP1_FMT_W:
3057     case COP1_FMT_L:
3058     case COP1_FMT_PS:
3059 dpavlin 22 case COPz_CFCz:
3060 dpavlin 24 case COPz_CTCz:
3061     case COPz_MFCz:
3062     case COPz_MTCz:
3063     /* Fallback to slow pre-dyntrans code, for now. */
3064     /* TODO: Fix/optimize/rewrite. */
3065     ic->f = instr(cop1_slow);
3066     ic->arg[0] = (uint32_t)iword & ((1 << 26) - 1);
3067 dpavlin 22 break;
3068 dpavlin 24
3069     default:fatal("COP1 floating point opcode = 0x%02x\n", rs);
3070 dpavlin 22 goto bad;
3071     }
3072     break;
3073    
3074 dpavlin 24 case HI6_COP2:
3075     /* Always cause a coprocessor unusable exception if
3076     there is no coprocessor 2: */
3077     if (cpu->cd.mips.coproc[2] == NULL) {
3078     ic->f = instr(cpu);
3079     ic->arg[0] = 2;
3080     break;
3081     }
3082     fatal("COP2 functionality not yet implemented\n");
3083     goto bad;
3084     break;
3085    
3086 dpavlin 22 case HI6_SPECIAL2:
3087 dpavlin 24 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3088     /* R5900, TX79/C790, have MMI instead of SPECIAL2: */
3089     int mmi_subopcode = (iword >> 6) & 0x1f;
3090    
3091     switch (s6) {
3092    
3093     case MMI_MADD:
3094     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3095     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3096     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3097     if (rd == MIPS_GPR_ZERO)
3098     ic->f = instr(madd);
3099     else
3100     ic->f = instr(madd_rd);
3101     break;
3102    
3103     case MMI_MADDU:
3104     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3105     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3106     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3107     if (rd == MIPS_GPR_ZERO)
3108     ic->f = instr(maddu);
3109     else
3110     ic->f = instr(maddu_rd);
3111     break;
3112    
3113     case MMI_MMI0:
3114     switch (mmi_subopcode) {
3115    
3116     case MMI0_PEXTLW:
3117     ic->arg[0] = rs;
3118     ic->arg[1] = rt;
3119     ic->arg[2] = rd;
3120     if (rd == MIPS_GPR_ZERO)
3121     ic->f = instr(nop);
3122     else
3123     ic->f = instr(pextlw);
3124     break;
3125    
3126     default:goto bad;
3127     }
3128     break;
3129    
3130     case MMI_MMI3:
3131     switch (mmi_subopcode) {
3132    
3133     case MMI3_POR:
3134     ic->arg[0] = rs;
3135     ic->arg[1] = rt;
3136     ic->arg[2] = rd;
3137     if (rd == MIPS_GPR_ZERO)
3138     ic->f = instr(nop);
3139     else
3140     ic->f = instr(por);
3141     break;
3142    
3143     default:goto bad;
3144     }
3145     break;
3146    
3147     default:goto bad;
3148     }
3149     break;
3150     }
3151    
3152     /* TODO: is this correct? Or are there other non-MIPS32/64
3153     MIPS processors that have support for SPECIAL2 opcodes? */
3154     if (cpu->cd.mips.cpu_type.isa_level < 32) {
3155     ic->f = instr(reserved);
3156     break;
3157     }
3158    
3159     /* SPECIAL2: */
3160 dpavlin 22 switch (s6) {
3161    
3162 dpavlin 24 case SPECIAL2_MADD:
3163     case SPECIAL2_MADDU:
3164     case SPECIAL2_MSUB:
3165     case SPECIAL2_MSUBU:
3166     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3167     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3168     switch (s6) {
3169     case SPECIAL2_MADD: ic->f = instr(madd); break;
3170     case SPECIAL2_MADDU:ic->f = instr(maddu); break;
3171     case SPECIAL2_MSUB: ic->f = instr(msub); break;
3172     case SPECIAL2_MSUBU:ic->f = instr(msubu); break;
3173     }
3174     break;
3175    
3176 dpavlin 22 case SPECIAL2_MUL:
3177     ic->f = instr(mul);
3178     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3179     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3180     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3181     if (rd == MIPS_GPR_ZERO)
3182     ic->f = instr(nop);
3183     break;
3184    
3185     case SPECIAL2_CLZ:
3186     case SPECIAL2_CLO:
3187     case SPECIAL2_DCLZ:
3188     case SPECIAL2_DCLO:
3189     switch (s6) {
3190     case SPECIAL2_CLZ: ic->f = instr(clz); break;
3191     case SPECIAL2_CLO: ic->f = instr(clo); break;
3192     case SPECIAL2_DCLZ: ic->f = instr(dclz); break;
3193     case SPECIAL2_DCLO: ic->f = instr(dclo); break;
3194     }
3195     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3196     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
3197     if (rd == MIPS_GPR_ZERO)
3198     ic->f = instr(nop);
3199     break;
3200    
3201     default:goto bad;
3202     }
3203     break;
3204    
3205 dpavlin 24 case HI6_REGIMM:
3206     switch (rt) {
3207     case REGIMM_BGEZ:
3208     case REGIMM_BGEZL:
3209     case REGIMM_BLTZ:
3210     case REGIMM_BLTZL:
3211     case REGIMM_BGEZAL:
3212     case REGIMM_BGEZALL:
3213     case REGIMM_BLTZAL:
3214     case REGIMM_BLTZALL:
3215     samepage_function = NULL;
3216     switch (rt) {
3217     case REGIMM_BGEZ:
3218     ic->f = instr(bgez);
3219     samepage_function = instr(bgez_samepage);
3220     break;
3221     case REGIMM_BGEZL:
3222     ic->f = instr(bgezl);
3223     samepage_function = instr(bgezl_samepage);
3224     break;
3225     case REGIMM_BLTZ:
3226     ic->f = instr(bltz);
3227     samepage_function = instr(bltz_samepage);
3228     break;
3229     case REGIMM_BLTZL:
3230     ic->f = instr(bltzl);
3231     samepage_function = instr(bltzl_samepage);
3232     break;
3233     case REGIMM_BGEZAL:
3234     ic->f = instr(bgezal);
3235     samepage_function = instr(bgezal_samepage);
3236     break;
3237     case REGIMM_BGEZALL:
3238     ic->f = instr(bgezall);
3239     samepage_function = instr(bgezall_samepage);
3240     break;
3241     case REGIMM_BLTZAL:
3242     ic->f = instr(bltzal);
3243     samepage_function = instr(bltzal_samepage);
3244     break;
3245     case REGIMM_BLTZALL:
3246     ic->f = instr(bltzall);
3247     samepage_function = instr(bltzall_samepage);
3248     break;
3249     }
3250     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3251     ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
3252     + (addr & 0xffc) + 4;
3253     /* Is the offset from the start of the current page
3254     still within the same page? Then use the
3255     samepage_function: */
3256     if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE-1)
3257     << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc)
3258     < 0xffc) {
3259     ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page+
3260     ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
3261     & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
3262     ic->f = samepage_function;
3263     }
3264     if (cpu->delay_slot) {
3265     fatal("TODO: branch in delay slot? (5)\n");
3266     goto bad;
3267     }
3268     break;
3269     default:fatal("UNIMPLEMENTED regimm rt=%i\n", rt);
3270     goto bad;
3271     }
3272     break;
3273    
3274     case HI6_LB:
3275     case HI6_LBU:
3276     case HI6_SB:
3277     case HI6_LH:
3278     case HI6_LHU:
3279     case HI6_SH:
3280     case HI6_LW:
3281     case HI6_LWU:
3282     case HI6_SW:
3283     case HI6_LD:
3284     case HI6_SD:
3285     /* TODO: LWU should probably also be x64=1? */
3286     size = 2; signedness = 0; store = 0;
3287     switch (main_opcode) {
3288     case HI6_LB: size = 0; signedness = 1; break;
3289     case HI6_LBU: size = 0; break;
3290     case HI6_LH: size = 1; signedness = 1; break;
3291     case HI6_LHU: size = 1; break;
3292     case HI6_LW: signedness = 1; break;
3293     case HI6_LWU: break;
3294     case HI6_LD: size = 3; x64 = 1; break;
3295     case HI6_SB: store = 1; size = 0; break;
3296     case HI6_SH: store = 1; size = 1; break;
3297     case HI6_SW: store = 1; break;
3298     case HI6_SD: store = 1; size = 3; x64 = 1; break;
3299     }
3300    
3301     ic->f =
3302     #ifdef MODE32
3303     mips32_loadstore
3304     #else
3305     mips_loadstore
3306     #endif
3307     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16)
3308     + store * 8 + size * 2 + signedness];
3309     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3310     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3311     ic->arg[2] = (int32_t)imm;
3312    
3313     /* Load into the dummy scratch register, if rt = zero */
3314     if (!store && rt == MIPS_GPR_ZERO)
3315     ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
3316     break;
3317    
3318     case HI6_LL:
3319     case HI6_LLD:
3320     case HI6_SC:
3321     case HI6_SCD:
3322     /* 32-bit load-linked/store-condition for ISA II and up: */
3323     /* (64-bit load-linked/store-condition for ISA III...) */
3324     if (cpu->cd.mips.cpu_type.isa_level < 2) {
3325     ic->f = instr(reserved);
3326     break;
3327     }
3328    
3329     store = 0;
3330     switch (main_opcode) {
3331     case HI6_LL: ic->f = instr(ll); break;
3332     case HI6_LLD: ic->f = instr(lld); x64 = 1; break;
3333     case HI6_SC: ic->f = instr(sc); store = 1; break;
3334     case HI6_SCD: ic->f = instr(scd); store = 1; x64 = 1; break;
3335     }
3336     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3337     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3338     ic->arg[2] = (int32_t)imm;
3339     if (!store && rt == MIPS_GPR_ZERO) {
3340     fatal("HM... unusual load linked\n");
3341     goto bad;
3342     }
3343     break;
3344    
3345     case HI6_LWL:
3346     case HI6_LWR:
3347     case HI6_LDL:
3348     case HI6_LDR:
3349     case HI6_SWL:
3350     case HI6_SWR:
3351     case HI6_SDL:
3352     case HI6_SDR:
3353     /* TODO: replace these with faster versions... */
3354     store = 0;
3355     switch (main_opcode) {
3356     case HI6_LWL: ic->f = instr(lwl); break;
3357     case HI6_LWR: ic->f = instr(lwr); break;
3358     case HI6_LDL: ic->f = instr(ldl); x64 = 1; break;
3359     case HI6_LDR: ic->f = instr(ldr); x64 = 1; break;
3360     case HI6_SWL: ic->f = instr(swl); store = 1; break;
3361     case HI6_SWR: ic->f = instr(swr); store = 1; break;
3362     case HI6_SDL: ic->f = instr(sdl); store = 1; x64 = 1; break;
3363     case HI6_SDR: ic->f = instr(sdr); store = 1; x64 = 1; break;
3364     }
3365     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3366     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3367     ic->arg[2] = (int32_t)imm;
3368    
3369     /* Load into the dummy scratch register, if rt = zero */
3370     if (!store && rt == MIPS_GPR_ZERO)
3371     ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
3372     break;
3373    
3374     case HI6_LWC1:
3375     case HI6_SWC1:
3376     case HI6_LDC1:
3377     case HI6_SDC1:
3378     /* 64-bit floating-point load/store for ISA II and up... */
3379     if ((main_opcode == HI6_LDC1 || main_opcode == HI6_SDC1)
3380     && cpu->cd.mips.cpu_type.isa_level < 2) {
3381     ic->f = instr(reserved);
3382     break;
3383     }
3384    
3385     ic->arg[0] = (size_t)&cpu->cd.mips.coproc[1]->reg[rt];
3386     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3387     ic->arg[2] = (int32_t)imm;
3388     switch (main_opcode) {
3389     case HI6_LWC1: ic->f = instr(lwc1); break;
3390     case HI6_LDC1: ic->f = instr(ldc1); break;
3391     case HI6_SWC1: ic->f = instr(swc1); break;
3392     case HI6_SDC1: ic->f = instr(sdc1); break;
3393     }
3394    
3395     /* Cause a coprocessor unusable exception if
3396     there is no floating point coprocessor: */
3397     if (cpu->cd.mips.cpu_type.flags & NOFPU ||
3398     cpu->cd.mips.coproc[1] == NULL) {
3399     ic->f = instr(cpu);
3400     ic->arg[0] = 1;
3401     }
3402     break;
3403    
3404     case HI6_LWC3:
3405     /* PREF (prefetch) on ISA IV and MIPS32/64: */
3406     if (cpu->cd.mips.cpu_type.isa_level >= 4) {
3407     /* Treat as nop for now: */
3408     ic->f = instr(nop);
3409     } else {
3410     fatal("TODO: lwc3 not implemented yet\n");
3411     goto bad;
3412     }
3413     break;
3414    
3415     case HI6_LQ_MDMX:
3416     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3417     fatal("TODO: R5900 128-bit loads\n");
3418     goto bad;
3419     }
3420    
3421     fatal("TODO: MDMX\n");
3422     goto bad;
3423     /* break */
3424    
3425     case HI6_SQ_SPECIAL3:
3426     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3427     fatal("TODO: R5900 128-bit stores\n");
3428     goto bad;
3429     }
3430    
3431     if (cpu->cd.mips.cpu_type.isa_level < 32 ||
3432     cpu->cd.mips.cpu_type.isa_revision < 2) {
3433     static int warning = 0;
3434     if (!warning) {
3435     fatal("[ WARNING! SPECIAL3 opcode used on a"
3436     " cpu which doesn't implement it ]\n");
3437     warning = 1;
3438     }
3439     ic->f = instr(reserved);
3440     break;
3441     }
3442    
3443     switch (s6) {
3444    
3445     case SPECIAL3_RDHWR:
3446     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3447    
3448     switch (rd) {
3449    
3450     case 0: ic->f = instr(rdhwr_cpunum);
3451     if (rt == MIPS_GPR_ZERO)
3452     ic->f = instr(nop);
3453     break;
3454    
3455     default:fatal("unimplemented rdhwr register rd=%i\n",
3456     rd);
3457     goto bad;
3458     }
3459     break;
3460    
3461     default:goto bad;
3462     }
3463     break;
3464    
3465     case HI6_CACHE:
3466     /* TODO: rt and op etc... */
3467     ic->f = instr(cache);
3468     break;
3469    
3470 dpavlin 22 default:goto bad;
3471     }
3472    
3473 dpavlin 24 #ifdef MODE32
3474     if (x64) {
3475     static int has_warned = 0;
3476     if (!has_warned)
3477     fatal("[ WARNING/NOTE: attempt to execute a 64-bit"
3478     " instruction on an emulated 32-bit processor; "
3479     "pc=0x%08"PRIx32" ]\n", (uint32_t)cpu->pc);
3480     has_warned = 1;
3481     ic->f = instr(reserved);
3482     }
3483     #endif
3484 dpavlin 22
3485    
3486     #define DYNTRANS_TO_BE_TRANSLATED_TAIL
3487     #include "cpu_dyntrans.c"
3488     #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
3489     }
3490    

  ViewVC Help
Powered by ViewVC 1.1.26