/[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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 24 - (show 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 /*
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 * $Id: cpu_mips_instr.c,v 1.85 2006/06/22 13:22:41 debug Exp $
29 *
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 * invalid: For catching bugs.
41 */
42 X(invalid)
43 {
44 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 }
49
50
51 /*
52 * reserved: Attempt to execute a reserved instruction (e.g. a 64-bit
53 * instruction on an emulated 32-bit processor).
54 */
55 X(reserved)
56 {
57 /* 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 }
65
66
67 /*
68 * 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 * 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 MODE_int_t old_pc = cpu->pc;
104 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
105 int x = rs == rt;
106 cpu->delay_slot = TO_BE_DELAYED;
107 ic[1].f(cpu, ic+1);
108 cpu->n_translated_instrs ++;
109 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 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 } else
120 cpu->delay_slot = NOT_DELAYED;
121 }
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 cpu->delay_slot = TO_BE_DELAYED;
127 ic[1].f(cpu, ic+1);
128 cpu->n_translated_instrs ++;
129 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
130 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 cpu->delay_slot = NOT_DELAYED;
137 }
138 X(bne)
139 {
140 MODE_int_t old_pc = cpu->pc;
141 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
142 int x = rs != rt;
143 cpu->delay_slot = TO_BE_DELAYED;
144 ic[1].f(cpu, ic+1);
145 cpu->n_translated_instrs ++;
146 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 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 } else
157 cpu->delay_slot = NOT_DELAYED;
158 }
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 cpu->delay_slot = TO_BE_DELAYED;
164 ic[1].f(cpu, ic+1);
165 cpu->n_translated_instrs ++;
166 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
167 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 cpu->delay_slot = NOT_DELAYED;
174 }
175 X(b)
176 {
177 MODE_int_t old_pc = cpu->pc;
178 cpu->delay_slot = TO_BE_DELAYED;
179 ic[1].f(cpu, ic+1);
180 cpu->n_translated_instrs ++;
181 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 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 } else
189 cpu->delay_slot = NOT_DELAYED;
190 }
191 X(b_samepage)
192 {
193 cpu->delay_slot = TO_BE_DELAYED;
194 ic[1].f(cpu, ic+1);
195 cpu->n_translated_instrs ++;
196 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT))
197 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
198 cpu->delay_slot = NOT_DELAYED;
199 }
200
201
202 /*
203 * 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 * 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 MODE_int_t rs = reg(ic->arg[0]);
874 cpu->delay_slot = TO_BE_DELAYED;
875 ic[1].f(cpu, ic+1);
876 cpu->n_translated_instrs ++;
877 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
878 cpu->pc = rs;
879 /* Note: Must be non-delayed when jumping to the new pc: */
880 cpu->delay_slot = NOT_DELAYED;
881 quick_pc_to_pointers(cpu);
882 } else
883 cpu->delay_slot = NOT_DELAYED;
884 }
885 X(jr_ra)
886 {
887 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
888 cpu->delay_slot = TO_BE_DELAYED;
889 ic[1].f(cpu, ic+1);
890 cpu->n_translated_instrs ++;
891 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
892 cpu->pc = rs;
893 /* Note: Must be non-delayed when jumping to the new pc: */
894 cpu->delay_slot = NOT_DELAYED;
895 quick_pc_to_pointers(cpu);
896 } else
897 cpu->delay_slot = NOT_DELAYED;
898 }
899 X(jr_ra_trace)
900 {
901 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
902 cpu->delay_slot = TO_BE_DELAYED;
903 ic[1].f(cpu, ic+1);
904 cpu->n_translated_instrs ++;
905 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
906 cpu->pc = rs;
907 cpu_functioncall_trace_return(cpu);
908 /* Note: Must be non-delayed when jumping to the new pc: */
909 cpu->delay_slot = NOT_DELAYED;
910 quick_pc_to_pointers(cpu);
911 } else
912 cpu->delay_slot = NOT_DELAYED;
913 }
914 X(jalr)
915 {
916 MODE_int_t rs = reg(ic->arg[0]), rd;
917 cpu->delay_slot = TO_BE_DELAYED;
918 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 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
925 cpu->pc = rs;
926 /* Note: Must be non-delayed when jumping to the new pc: */
927 cpu->delay_slot = NOT_DELAYED;
928 quick_pc_to_pointers(cpu);
929 } else
930 cpu->delay_slot = NOT_DELAYED;
931 }
932 X(jalr_trace)
933 {
934 MODE_int_t rs = reg(ic->arg[0]), rd;
935 cpu->delay_slot = TO_BE_DELAYED;
936 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 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
943 cpu->pc = rs;
944 cpu_functioncall_trace(cpu, cpu->pc);
945 /* Note: Must be non-delayed when jumping to the new pc: */
946 cpu->delay_slot = NOT_DELAYED;
947 quick_pc_to_pointers(cpu);
948 } else
949 cpu->delay_slot = NOT_DELAYED;
950 }
951
952
953 /*
954 * 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 * 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 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
1037
1038 /*
1039 * 2-register:
1040 *
1041 * arg[0] = ptr to rs
1042 * arg[1] = ptr to rt
1043 */
1044 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 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 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 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 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
1249
1250 /*
1251 * 3-register arithmetic instructions:
1252 *
1253 * arg[0] = ptr to rs
1254 * arg[1] = ptr to rt
1255 * arg[2] = ptr to rd
1256 */
1257 X(addu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) + reg(ic->arg[1])); }
1258 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 X(subu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) - reg(ic->arg[1])); }
1292 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 X(slt) {
1328 reg(ic->arg[2]) =
1329 (MODE_int_t)reg(ic->arg[0]) < (MODE_int_t)reg(ic->arg[1]);
1330 }
1331 X(sltu) {
1332 reg(ic->arg[2]) =
1333 (MODE_uint_t)reg(ic->arg[0]) < (MODE_uint_t)reg(ic->arg[1]);
1334 }
1335 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 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 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 X(srl) { reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1343 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 X(sra) { reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1346 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 X(mul) { reg(ic->arg[2]) = (int32_t)
1359 ( (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]) ); }
1360 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
1363
1364 /*
1365 * 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 * 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 * 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 *
1519 * arg[0] = pointer to rs
1520 * arg[1] = pointer to rt
1521 * arg[2] = (int32_t) immediate value
1522 */
1523 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 X(addiu)
1540 {
1541 reg(ic->arg[1]) = (int32_t)
1542 ((int32_t)reg(ic->arg[0]) + (int32_t)ic->arg[2]);
1543 }
1544 X(daddi)
1545 {
1546 int64_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1547 int64_t rt = rs + imm;
1548
1549 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 X(daddiu)
1561 {
1562 reg(ic->arg[1]) = reg(ic->arg[0]) + (int32_t)ic->arg[2];
1563 }
1564 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
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 * cfc0: Copy from Coprocessor 0.
1589 * mfc0, dmfc0: Move from Coprocessor 0.
1590 * mtc0, dmtc0: Move to Coprocessor 0.
1591 *
1592 * arg[0] = pointer to GPR (rt)
1593 * arg[1] = coprocessor 0 register number | (select << 5) (or for the
1594 * cfc0 instruction, the coprocessor control register number)
1595 * arg[2] = relative addr of this instruction within the page
1596 */
1597 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 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 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 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1623 cpu->pc |= ic->arg[2];
1624
1625 /* TODO: cause exception if necessary */
1626 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 }
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
1658 /* TODO: fix/remove these! */
1659 cpu->invalidate_translation_caches(cpu, 0, INVALIDATE_ALL);
1660 }
1661
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 {
1672 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 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1818 cpu->pc |= ic->arg[2];
1819 coproc_tlbwri(cpu, ic->arg[0]);
1820 }
1821
1822
1823 /*
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 /*****************************************************************************/
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 reg(ic[1].arg[1]) = (int32_t)
2303 ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
2304 cpu->n_translated_instrs ++;
2305 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2306 }
2307
2308
2309 /*
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 /*****************************************************************************/
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 /* end_of_page doesn't count as an executed instruction: */
2334 cpu->n_translated_instrs --;
2335
2336 /*
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
2344 /* Simple jump to the next page (if we are lucky): */
2345 if (cpu->delay_slot == NOT_DELAYED)
2346 return;
2347
2348 /*
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 return;
2355
2356 /*
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 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
2362
2363 instr(to_be_translated)(cpu, cpu->cd.mips.next_ic);
2364
2365 /* The instruction in the delay slot has now executed. */
2366 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
2367 cpu->delay_slot); */
2368
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 /* 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
2384 /* This doesn't count as an executed instruction. */
2385 cpu->n_translated_instrs --;
2386
2387 quick_pc_to_pointers(cpu);
2388
2389 if (cpu->delay_slot == NOT_DELAYED)
2390 return;
2391
2392 fatal("end_of_page2: fatal error, we're in a delay slot\n");
2393 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 /*
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 /*****************************************************************************/
2443
2444
2445 /*
2446 * mips_instr_to_be_translated():
2447 *
2448 * Translate an instruction word into a mips_instr_call. ic is filled in with
2449 * 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 int store, signedness, size;
2463
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 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
2470 /* fatal("[ delay-slot translation across page "
2471 "boundary ]\n"); */
2472 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 cpu->pc = (MODE_int_t)addr;
2479 addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
2480
2481 /* Read the instruction word from memory: */
2482 #ifdef MODE32
2483 page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
2484 #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
2499 if (page != NULL) {
2500 /* fatal("TRANSLATION HIT!\n"); */
2501 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
2502 } else {
2503 /* fatal("TRANSLATION MISS!\n"); */
2504 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
2505 sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
2506 fatal("to_be_translated(): read failed: TODO\n");
2507 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 * 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 */
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 case SPECIAL_SLLV:
2548 case SPECIAL_SRL:
2549 case SPECIAL_SRLV:
2550 case SPECIAL_SRA:
2551 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 switch (s6) {
2562 case SPECIAL_SLL: ic->f = instr(sll); break;
2563 case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
2564 case SPECIAL_SRL: ic->f = instr(srl); break;
2565 case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
2566 case SPECIAL_SRA: ic->f = instr(sra); break;
2567 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 }
2584 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2585 if (sa >= 0)
2586 ic->arg[1] = sa;
2587 else
2588 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
2589 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 case SPECIAL_ADD:
2595 case SPECIAL_ADDU:
2596 case SPECIAL_SUB:
2597 case SPECIAL_SUBU:
2598 case SPECIAL_DADD:
2599 case SPECIAL_DADDU:
2600 case SPECIAL_DSUB:
2601 case SPECIAL_DSUBU:
2602 case SPECIAL_SLT:
2603 case SPECIAL_SLTU:
2604 case SPECIAL_AND:
2605 case SPECIAL_OR:
2606 case SPECIAL_XOR:
2607 case SPECIAL_NOR:
2608 case SPECIAL_MOVN:
2609 case SPECIAL_MOVZ:
2610 case SPECIAL_MFHI:
2611 case SPECIAL_MFLO:
2612 case SPECIAL_MTHI:
2613 case SPECIAL_MTLO:
2614 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 switch (s6) {
2629 case SPECIAL_ADD: ic->f = instr(add); break;
2630 case SPECIAL_ADDU: ic->f = instr(addu); break;
2631 case SPECIAL_SUB: ic->f = instr(sub); break;
2632 case SPECIAL_SUBU: ic->f = instr(subu); break;
2633 case SPECIAL_DADD: ic->f = instr(dadd); x64=1; break;
2634 case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
2635 case SPECIAL_DSUB: ic->f = instr(dsub); x64=1; break;
2636 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 case SPECIAL_AND: ic->f = instr(and); break;
2640 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 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 }
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 /* Special cases for rd: */
2682 switch (s6) {
2683 case SPECIAL_MTHI:
2684 case SPECIAL_MTLO:
2685 case SPECIAL_DIV:
2686 case SPECIAL_DIVU:
2687 case SPECIAL_DDIV:
2688 case SPECIAL_DDIVU:
2689 case SPECIAL_MULT:
2690 case SPECIAL_MULTU:
2691 case SPECIAL_DMULT:
2692 case SPECIAL_DMULTU:
2693 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 if (rd != MIPS_GPR_ZERO) {
2715 fatal("TODO: rd NON-zero\n");
2716 goto bad;
2717 }
2718 /* These instructions don't use rd. */
2719 break;
2720 default:if (rd == MIPS_GPR_ZERO)
2721 ic->f = instr(nop);
2722 }
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 if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
2730 s6 = SPECIAL_JR;
2731 ic->arg[2] = (addr & 0xffc) + 8;
2732 switch (s6) {
2733 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 if (cpu->delay_slot) {
2751 fatal("TODO: branch in delay slot? (1)\n");
2752 goto bad;
2753 }
2754 break;
2755
2756 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 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 case HI6_BEQL:
2780 case HI6_BNEL:
2781 case HI6_BLEZ:
2782 case HI6_BLEZL:
2783 case HI6_BGTZ:
2784 case HI6_BGTZL:
2785 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 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 }
2830 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
2831 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
2832 ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
2833 + (addr & 0xffc) + 4 );
2834 /* 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 if (cpu->delay_slot) {
2844 fatal("TODO: branch in delay slot? (2)\n");
2845 goto bad;
2846 }
2847 break;
2848
2849 case HI6_ADDI:
2850 case HI6_ADDIU:
2851 case HI6_SLTI:
2852 case HI6_SLTIU:
2853 case HI6_DADDI:
2854 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 main_opcode == HI6_SLTI ||
2863 main_opcode == HI6_SLTIU ||
2864 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
2870 switch (main_opcode) {
2871 case HI6_ADDI: ic->f = instr(addi); break;
2872 case HI6_ADDIU: ic->f = instr(addiu); break;
2873 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 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
2882 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 if (ic->f == instr(daddiu))
2888 cpu->cd.mips.combination_check = COMBINE(b_daddiu);
2889 break;
2890
2891 case HI6_LUI:
2892 ic->f = instr(set);
2893 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
2894 ic->arg[1] = (int32_t) (imm << 16);
2895 if (rt == MIPS_GPR_ZERO)
2896 ic->f = instr(nop);
2897 break;
2898
2899 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 case HI6_COP0:
2923 /* 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 /* rs contains the coprocessor opcode! */
2975 switch (rs) {
2976 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 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 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 default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
3010 goto bad;
3011 }
3012 break;
3013
3014 case HI6_COP1:
3015 /* 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 switch (rs) {
3026
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 case COPz_CFCz:
3060 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 break;
3068
3069 default:fatal("COP1 floating point opcode = 0x%02x\n", rs);
3070 goto bad;
3071 }
3072 break;
3073
3074 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 case HI6_SPECIAL2:
3087 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 switch (s6) {
3161
3162 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 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 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 default:goto bad;
3471 }
3472
3473 #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
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