/[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 32 - (show annotations)
Mon Oct 8 16:20:58 2007 UTC (16 years, 5 months ago) by dpavlin
File MIME type: text/plain
File size: 130162 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1421 2006/11/06 05:32:37 debug Exp $
20060816	Adding a framework for emulated/virtual timers (src/timer.c),
		using only setitimer().
		Rewriting the mc146818 to use the new timer framework.
20060817	Adding a call to gettimeofday() every now and then (once every
		second, at the moment) to resynch the timer if it drifts.
		Beginning to convert the ISA timer interrupt mechanism (8253
		and 8259) to use the new timer framework.
		Removing the -I command line option.
20060819	Adding the -I command line option again, with new semantics.
		Working on Footbridge timer interrupts; NetBSD/NetWinder and
		NetBSD/CATS now run at correct speed, but unfortunately with
		HUGE delays during bootup.
20060821	Some minor m68k updates. Adding the first instruction: nop. :)
		Minor Alpha emulation updates.
20060822	Adding a FreeBSD development specific YAMON environment
		variable ("khz") (as suggested by Bruce M. Simpson).
		Moving YAMON environment variable initialization from
		machine_evbmips.c into promemul/yamon.c, and adding some more
		variables.
		Continuing on the LCA PCI bus controller (for Alpha machines).
20060823	Continuing on the timer stuff: experimenting with MIPS count/
		compare interrupts connected to the timer framework.
20060825	Adding bogus SCSI commands 0x51 (SCSICDROM_READ_DISCINFO) and
		0x52 (SCSICDROM_READ_TRACKINFO) to the SCSI emulation layer,
		to allow NetBSD/pmax 4.0_BETA to be installed from CDROM.
		Minor updates to the LCA PCI controller.
20060827	Implementing a CHIP8 cpu mode, and a corresponding CHIP8
		machine, for fun. Disassembly support for all instructions,
		and most of the common instructions have been implemented: mvi,
		mov_imm, add_imm, jmp, rand, cls, sprite, skeq_imm, jsr,
		skne_imm, bcd, rts, ldr, str, mov, or, and, xor, add, sub,
		font, ssound, sdelay, gdelay, bogus skup/skpr, skeq, skne.
20060828	Beginning to convert the CHIP8 cpu in the CHIP8 machine to a
		(more correct) RCA 180x cpu. (Disassembly for all 1802
		instructions has been implemented, but no execution yet, and
		no 1805 extended instructions.)
20060829	Minor Alpha emulation updates.
20060830	Beginning to experiment a little with PCI IDE for SGI O2.
		Fixing the cursor key mappings for MobilePro 770 emulation.
		Fixing the LK201 warning caused by recent NetBSD/pmax.
		The MIPS R41xx standby, suspend, and hibernate instructions now
		behave like the RM52xx/MIPS32/MIPS64 wait instruction.
		Fixing dev_wdc so it calculates correct (64-bit) offsets before
		giving them to diskimage_access().
20060831	Continuing on Alpha emulation (OSF1 PALcode).
20060901	Minor Alpha updates; beginning on virtual memory pagetables.
		Removed the limit for max nr of devices (in preparation for
		allowing devices' base addresses to be changed during runtime).
		Adding a hack for MIPS [d]mfc0 select 0 (except the count
		register), so that the coproc register is simply copied.
		The MIPS suspend instruction now exits the emulator, instead
		of being treated as a wait instruction (this causes NetBSD/
		hpcmips to get correct 'halt' behavior).
		The VR41xx RTC now returns correct time.
		Connecting the VR41xx timer to the timer framework (fixed at
		128 Hz, for now).
		Continuing on SPARC emulation, adding more instructions:
		restore, ba_xcc, ble. The rectangle drawing demo works :)
		Removing the last traces of the old ENABLE_CACHE_EMULATION
		MIPS stuff (not usable with dyntrans anyway).
20060902	Splitting up src/net.c into several smaller files in its own
		subdirectory (src/net/).
20060903	Cleanup of the files in src/net/, to make them less ugly.
20060904	Continuing on the 'settings' subsystem.
		Minor progress on the SPARC emulation mode.
20060905	Cleanup of various things, and connecting the settings
		infrastructure to various subsystems (emul, machine, cpu, etc).
		Changing the lk201 mouse update routine to not rely on any
		emulated hardware framebuffer cursor coordinates, but instead
		always do (semi-usable) relative movements.
20060906	Continuing on the lk201 mouse stuff. Mouse behaviour with
		multiple framebuffers (which was working in Ultrix) is now
		semi-broken (but it still works, in a way).
		Moving the documentation about networking into its own file
		(networking.html), and refreshing it a bit. Adding an example
		of how to use ethernet frame direct-access (udp_snoop).
20060907	Continuing on the settings infrastructure.
20060908	Minor updates to SH emulation: for 32-bit emulation: delay
		slots and the 'jsr @Rn' instruction. I'm putting 64-bit SH5 on
		ice, for now.
20060909-10	Implementing some more 32-bit SH instructions. Removing the
		64-bit mode completely. Enough has now been implemented to run
		the rectangle drawing demo. :-)
20060912	Adding more SH instructions.
20060916	Continuing on SH emulation (some more instructions: div0u,
		div1, rotcl/rotcr, more mov instructions, dt, braf, sets, sett,
		tst_imm, dmuls.l, subc, ldc_rm_vbr, movt, clrt, clrs, clrmac).
		Continuing on the settings subsystem (beginning on reading/
		writing settings, removing bugs, and connecting more cpus to
		the framework).
20060919	More work on SH emulation; adding an ldc banked instruction,
		and attaching a 640x480 framebuffer to the Dreamcast machine
		mode (NetBSD/dreamcast prints the NetBSD copyright banner :-),
		and then panics).
20060920	Continuing on the settings subsystem.
20060921	Fixing the Footbridge timer stuff so that NetBSD/cats and
		NetBSD/netwinder boot up without the delays.
20060922	Temporarily hardcoding MIPS timer interrupt to 100 Hz. With
		'wait' support disabled, NetBSD/malta and Linux/malta run at
		correct speed.
20060923	Connecting dev_gt to the timer framework, so that NetBSD/cobalt
		runs at correct speed.
		Moving SH4-specific memory mapped registers into its own
		device (dev_sh4.c).
		Running with -N now prints "idling" instead of bogus nr of
		instrs/second (which isn't valid anyway) while idling.
20060924	Algor emulation should now run at correct speed.
		Adding disassembly support for some MIPS64 revision 2
		instructions: ext, dext, dextm, dextu.
20060926	The timer framework now works also when the MIPS wait
		instruction is used.
20060928	Re-implementing checks for coprocessor availability for MIPS
		cop0 instructions. (Thanks to Carl van Schaik for noticing the
		lack of cop0 availability checks.)
20060929	Implementing an instruction combination hack which treats
		NetBSD/pmax' idle loop as a wait-like instruction.
20060930	The ENTRYHI_R_MASK was missing in (at least) memory_mips_v2p.c,
		causing TLB lookups to sometimes succeed when they should have
		failed. (A big thank you to Juli Mallett for noticing the
		problem.)
		Adding disassembly support for more MIPS64 revision 2 opcodes
		(seb, seh, wsbh, jalr.hb, jr.hb, synci, ins, dins, dinsu,
		dinsm, dsbh, dshd, ror, dror, rorv, drorv, dror32). Also
		implementing seb, seh, dsbh, dshd, and wsbh.
		Implementing an instruction combination hack for Linux/pmax'
		idle loop, similar to the NetBSD/pmax case.
20061001	Changing the NetBSD/sgimips install instructions to extract
		files from an iso image, instead of downloading them via ftp.
20061002	More-than-31-bit userland addresses in memory_mips_v2p.c were
		not actually working; applying a fix from Carl van Schaik to
		enable them to work + making some other updates (adding kuseg
		support).
		Fixing hpcmips (vr41xx) timer initialization.
		Experimenting with O(n)->O(1) reduction in the MIPS TLB lookup
		loop. Seems to work both for R3000 and non-R3000.
20061003	Continuing a little on SH emulation (adding more control
		registers; mini-cleanup of memory_sh.c).
20061004	Beginning on a dev_rtc, a clock/timer device for the test
		machines; also adding a demo, and some documentation.
		Fixing a bug in SH "mov.w @(disp,pc),Rn" (the result wasn't
		sign-extended), and adding the addc and ldtlb instructions.
20061005	Contining on SH emulation: virtual to physical address
		translation, and a skeleton exception mechanism.
20061006	Adding more SH instructions (various loads and stores, rte,
		negc, muls.w, various privileged register-move instructions).
20061007	More SH instructions: various move instructions, trapa, div0s,
		float, fdiv, ftrc.
		Continuing on dev_rtc; removing the rtc demo.
20061008	Adding a dummy Dreamcast PROM module. (Homebrew Dreamcast
		programs using KOS libs need this.)
		Adding more SH instructions: "stc vbr,rn", rotl, rotr, fsca,
		fmul, fadd, various floating-point moves, etc. A 256-byte
		demo for Dreamcast runs :-)
20061012	Adding the SH "lds Rm,pr" and bsr instructions.
20061013	More SH instructions: "sts fpscr,rn", tas.b, and some more
		floating point instructions, cmp/str, and more moves.
		Adding a dummy dev_pvr (Dreamcast graphics controller).
20061014	Generalizing the expression evaluator (used in the built-in
		debugger) to support parentheses and +-*/%^&|.
20061015	Removing the experimental tlb index hint code in
		mips_memory_v2p.c, since it didn't really have any effect.
20061017	Minor SH updates; adding the "sts pr,Rn", fcmp/gt, fneg,
		frchg, and some other instructions. Fixing missing sign-
		extension in an 8-bit load instruction.
20061019	Adding a simple dev_dreamcast_rtc.
		Implementing memory-mapped access to the SH ITLB/UTLB arrays.
20061021	Continuing on various SH and Dreamcast things: sh4 timers,
		debug messages for dev_pvr, fixing some virtual address
		translation bugs, adding the bsrf instruction.
		The NetBSD/dreamcast GENERIC_MD kernel now reaches userland :)
		Adding a dummy dev_dreamcast_asic.c (not really useful yet).
		Implementing simple support for Store Queues.
		Beginning on the PVR Tile Accelerator.
20061022	Generalizing the PVR framebuffer to support off-screen drawing,
		multiple bit-depths, etc. (A small speed penalty, but most
		likely worth it.)
		Adding more SH instructions (mulu.w, fcmp/eq, fsub, fmac,
		fschg, and some more); correcting bugs in "fsca" and "float".
20061024	Adding the SH ftrv (matrix * vector) instruction. Marcus
		Comstedt's "tatest" example runs :) (wireframe only).
		Correcting disassembly for SH floating point instructions that
		use the xd* registers.
		Adding the SH fsts instruction.
		In memory_device_dyntrans_access(), only the currently used
		range is now invalidated, and not the entire device range.
20061025	Adding a dummy AVR32 cpu mode skeleton.
20061026	Various Dreamcast updates; beginning on a Maple bus controller.
20061027	Continuing on the Maple bus. A bogus Controller, Keyboard, and
		Mouse can now be detected by NetBSD and KOS homebrew programs.
		Cleaning up the SH4 Timer Management Unit, and beginning on
		SH4 interrupts.
		Implementing the Dreamcast SYSASIC.
20061028	Continuing on the SYSASIC.
		Adding the SH fsqrt instruction.
		memory_sh.c now actually scans the ITLB.
		Fixing a bug in dev_sh4.c, related to associative writes into
		the memory-mapped UTLB array. NetBSD/dreamcast now reaches
		userland stably, and prints the "Terminal type?" message :-]
		Implementing enough of the Dreamcast keyboard to make NetBSD
		accept it for input.
		Enabling SuperH for stable (non-development) builds.
		Adding NetBSD/dreamcast to the documentation, although it
		doesn't support root-on-nfs yet.
20061029	Changing usleep(1) calls in the debugger to to usleep(10000)
		(according to Brian Foley, this makes GXemul run better on
		MacOS X).
		Making the Maple "Controller" do something (enough to barely
		interact with dcircus.elf).
20061030-31	Some progress on the PVR. More test programs start running (but
		with strange output).
		Various other SH4-related updates.
20061102	Various Dreamcast and SH4 updates; more KOS demos run now.
20061104	Adding a skeleton dev_mb8696x.c (the Dreamcast's LAN adapter).
20061105	Continuing on the MB8696x; NetBSD/dreamcast detects it as mbe0.
		Testing for the release.

==============  RELEASE 0.4.3  ==============


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.118 2006/10/29 05:10:27 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 * COPROC_AVAILABILITY_CHECK(n) checks for the coprocessor available bit for
41 * coprocessor number n, and causes a CoProcessor Unusable exception if it
42 * is not set. (Note: For coprocessor 0 checks, use cop0_availability_check!)
43 */
44 #ifndef COPROC_AVAILABILITY_CHECK
45 #define COPROC_AVAILABILITY_CHECK(x) { \
46 const int cpnr = (x); \
47 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) \
48 / sizeof(struct mips_instr_call); \
49 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) \
50 << MIPS_INSTR_ALIGNMENT_SHIFT); \
51 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); \
52 if (!(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & \
53 ((1 << cpnr) << STATUS_CU_SHIFT)) ) { \
54 mips_cpu_exception(cpu, EXCEPTION_CPU, \
55 0, 0, cpnr, 0, 0, 0); \
56 return; \
57 } \
58 }
59 #endif
60
61
62 #ifndef COP0_AVAILABILITY_CHECK_INCLUDED
63 #define COP0_AVAILABILITY_CHECK_INCLUDED
64 /*
65 * cop0_availability_check() causes a CoProcessor Unusable exception if
66 * we are currently running in usermode, and the coprocessor available bit
67 * for coprocessor 0 is not set.
68 *
69 * Returns 1 if ok (i.e. if the coprocessor was usable), 0 on exceptions.
70 */
71 int cop0_availability_check(struct cpu *cpu, struct mips_instr_call *ic)
72 {
73 int in_usermode = 0;
74 struct mips_coproc *cp0 = cpu->cd.mips.coproc[0];
75
76 switch (cpu->cd.mips.cpu_type.exc_model) {
77 case EXC3K:
78 /*
79 * NOTE: If the KU bit is checked, Linux crashes.
80 * It is the PC that counts.
81 *
82 * TODO: Check whether this is true or not for R4000 as well.
83 */
84 /* TODO: if (cp0->reg[COP0_STATUS] & MIPS1_SR_KU_CUR) */
85 if (cpu->pc <= 0x7fffffff)
86 in_usermode = 1;
87 break;
88 default:
89 /* R4000 etc: (TODO: How about supervisor mode?) */
90 if (((cp0->reg[COP0_STATUS] &
91 STATUS_KSU_MASK) >> STATUS_KSU_SHIFT) != KSU_KERNEL)
92 in_usermode = 1;
93 if (cp0->reg[COP0_STATUS] & (STATUS_ERL | STATUS_EXL))
94 in_usermode = 0;
95 break;
96 }
97
98 if (in_usermode) {
99 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
100 / sizeof(struct mips_instr_call);
101 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
102 << MIPS_INSTR_ALIGNMENT_SHIFT);
103 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
104 if (!(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &
105 (1 << STATUS_CU_SHIFT)) ) {
106 mips_cpu_exception(cpu, EXCEPTION_CPU,
107 0, 0, /* cpnr */ 0, 0, 0, 0);
108 return 0;
109 }
110 }
111
112 return 1;
113 }
114 #endif
115
116
117 /*
118 * invalid: For catching bugs.
119 */
120 X(invalid)
121 {
122 fatal("FATAL ERROR: An internal error occured in the MIPS"
123 " dyntrans code. Please contact the author with detailed"
124 " repro steps on how to trigger this bug.\n");
125 exit(1);
126 }
127
128
129 /*
130 * reserved: Attempt to execute a reserved instruction (e.g. a 64-bit
131 * instruction on an emulated 32-bit processor).
132 */
133 X(reserved)
134 {
135 /* Synchronize the PC and cause an exception: */
136 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
137 / sizeof(struct mips_instr_call);
138 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
139 << MIPS_INSTR_ALIGNMENT_SHIFT);
140 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
141 mips_cpu_exception(cpu, EXCEPTION_RI, 0, 0, 0, 0, 0, 0);
142 }
143
144
145 /*
146 * cpu: Cause a CoProcessor Unusable exception.
147 *
148 * arg[0] = the number of the coprocessor
149 */
150 X(cpu)
151 {
152 /* Synchronize the PC and cause an exception: */
153 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
154 / sizeof(struct mips_instr_call);
155 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
156 << MIPS_INSTR_ALIGNMENT_SHIFT);
157 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
158 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, ic->arg[0], 0, 0, 0);
159 }
160
161
162 /*
163 * nop: Do nothing.
164 */
165 X(nop)
166 {
167 }
168
169
170 /*
171 * beq: Branch if equal
172 * bne: Branch if not equal
173 * b: Branch (comparing a register to itself, always true)
174 *
175 * arg[0] = pointer to rs
176 * arg[1] = pointer to rt
177 * arg[2] = (int32_t) relative offset from the next instruction
178 */
179 X(beq)
180 {
181 MODE_int_t old_pc = cpu->pc;
182 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
183 int x = rs == rt;
184 cpu->delay_slot = TO_BE_DELAYED;
185 ic[1].f(cpu, ic+1);
186 cpu->n_translated_instrs ++;
187 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
188 /* Note: Must be non-delayed when jumping to the new pc: */
189 cpu->delay_slot = NOT_DELAYED;
190 if (x) {
191 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
192 MIPS_INSTR_ALIGNMENT_SHIFT);
193 cpu->pc = old_pc + (int32_t)ic->arg[2];
194 quick_pc_to_pointers(cpu);
195 } else
196 cpu->cd.mips.next_ic ++;
197 } else
198 cpu->delay_slot = NOT_DELAYED;
199 }
200 X(beq_samepage)
201 {
202 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
203 int x = rs == rt;
204 cpu->delay_slot = TO_BE_DELAYED;
205 ic[1].f(cpu, ic+1);
206 cpu->n_translated_instrs ++;
207 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
208 if (x)
209 cpu->cd.mips.next_ic = (struct mips_instr_call *)
210 ic->arg[2];
211 else
212 cpu->cd.mips.next_ic ++;
213 }
214 cpu->delay_slot = NOT_DELAYED;
215 }
216 X(beq_samepage_addiu)
217 {
218 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
219 cpu->n_translated_instrs ++;
220 reg(ic[1].arg[1]) = (int32_t)
221 ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
222 if (rs == rt)
223 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
224 else
225 cpu->cd.mips.next_ic ++;
226 }
227 X(beq_samepage_nop)
228 {
229 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
230 cpu->n_translated_instrs ++;
231 if (rs == rt)
232 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
233 else
234 cpu->cd.mips.next_ic ++;
235 }
236 X(bne)
237 {
238 MODE_int_t old_pc = cpu->pc;
239 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
240 int x = rs != rt;
241 cpu->delay_slot = TO_BE_DELAYED;
242 ic[1].f(cpu, ic+1);
243 cpu->n_translated_instrs ++;
244 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
245 /* Note: Must be non-delayed when jumping to the new pc: */
246 cpu->delay_slot = NOT_DELAYED;
247 if (x) {
248 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
249 MIPS_INSTR_ALIGNMENT_SHIFT);
250 cpu->pc = old_pc + (int32_t)ic->arg[2];
251 quick_pc_to_pointers(cpu);
252 } else
253 cpu->cd.mips.next_ic ++;
254 } else
255 cpu->delay_slot = NOT_DELAYED;
256 }
257 X(bne_samepage)
258 {
259 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
260 int x = rs != rt;
261 cpu->delay_slot = TO_BE_DELAYED;
262 ic[1].f(cpu, ic+1);
263 cpu->n_translated_instrs ++;
264 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
265 if (x)
266 cpu->cd.mips.next_ic = (struct mips_instr_call *)
267 ic->arg[2];
268 else
269 cpu->cd.mips.next_ic ++;
270 }
271 cpu->delay_slot = NOT_DELAYED;
272 }
273 X(bne_samepage_addiu)
274 {
275 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
276 cpu->n_translated_instrs ++;
277 reg(ic[1].arg[1]) = (int32_t)
278 ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
279 if (rs != rt)
280 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
281 else
282 cpu->cd.mips.next_ic ++;
283 }
284 X(bne_samepage_nop)
285 {
286 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
287 cpu->n_translated_instrs ++;
288 if (rs != rt)
289 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
290 else
291 cpu->cd.mips.next_ic ++;
292 }
293 X(b)
294 {
295 MODE_int_t old_pc = cpu->pc;
296 cpu->delay_slot = TO_BE_DELAYED;
297 ic[1].f(cpu, ic+1);
298 cpu->n_translated_instrs ++;
299 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
300 /* Note: Must be non-delayed when jumping to the new pc: */
301 cpu->delay_slot = NOT_DELAYED;
302 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
303 MIPS_INSTR_ALIGNMENT_SHIFT);
304 cpu->pc = old_pc + (int32_t)ic->arg[2];
305 quick_pc_to_pointers(cpu);
306 } else
307 cpu->delay_slot = NOT_DELAYED;
308 }
309 X(b_samepage)
310 {
311 cpu->delay_slot = TO_BE_DELAYED;
312 ic[1].f(cpu, ic+1);
313 cpu->n_translated_instrs ++;
314 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT))
315 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
316 cpu->delay_slot = NOT_DELAYED;
317 }
318
319
320 /*
321 * beql: Branch if equal likely
322 * bnel: Branch if not equal likely
323 *
324 * arg[0] = pointer to rs
325 * arg[1] = pointer to rt
326 * arg[2] = (int32_t) relative offset from the next instruction
327 */
328 X(beql)
329 {
330 MODE_int_t old_pc = cpu->pc;
331 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
332 int x = rs == rt;
333 cpu->delay_slot = TO_BE_DELAYED;
334 if (x)
335 ic[1].f(cpu, ic+1);
336 cpu->n_translated_instrs ++;
337 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
338 /* Note: Must be non-delayed when jumping to the new pc: */
339 cpu->delay_slot = NOT_DELAYED;
340 if (x) {
341 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
342 MIPS_INSTR_ALIGNMENT_SHIFT);
343 cpu->pc = old_pc + (int32_t)ic->arg[2];
344 quick_pc_to_pointers(cpu);
345 } else
346 cpu->cd.mips.next_ic ++;
347 } else
348 cpu->delay_slot = NOT_DELAYED;
349 }
350 X(beql_samepage)
351 {
352 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
353 int x = rs == rt;
354 cpu->delay_slot = TO_BE_DELAYED;
355 if (x)
356 ic[1].f(cpu, ic+1);
357 cpu->n_translated_instrs ++;
358 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
359 if (x)
360 cpu->cd.mips.next_ic = (struct mips_instr_call *)
361 ic->arg[2];
362 else
363 cpu->cd.mips.next_ic ++;
364 }
365 cpu->delay_slot = NOT_DELAYED;
366 }
367 X(bnel)
368 {
369 MODE_int_t old_pc = cpu->pc;
370 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
371 int x = rs != rt;
372 cpu->delay_slot = TO_BE_DELAYED;
373 if (x)
374 ic[1].f(cpu, ic+1);
375 cpu->n_translated_instrs ++;
376 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
377 /* Note: Must be non-delayed when jumping to the new pc: */
378 cpu->delay_slot = NOT_DELAYED;
379 if (x) {
380 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
381 MIPS_INSTR_ALIGNMENT_SHIFT);
382 cpu->pc = old_pc + (int32_t)ic->arg[2];
383 quick_pc_to_pointers(cpu);
384 } else
385 cpu->cd.mips.next_ic ++;
386 } else
387 cpu->delay_slot = NOT_DELAYED;
388 }
389 X(bnel_samepage)
390 {
391 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
392 int x = rs != rt;
393 cpu->delay_slot = TO_BE_DELAYED;
394 if (x)
395 ic[1].f(cpu, ic+1);
396 cpu->n_translated_instrs ++;
397 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
398 if (x)
399 cpu->cd.mips.next_ic = (struct mips_instr_call *)
400 ic->arg[2];
401 else
402 cpu->cd.mips.next_ic ++;
403 }
404 cpu->delay_slot = NOT_DELAYED;
405 }
406
407
408 /*
409 * blez: Branch if less than or equal
410 * blezl: Branch if less than or equal likely
411 *
412 * arg[0] = pointer to rs
413 * arg[2] = (int32_t) relative offset from the next instruction
414 */
415 X(blez)
416 {
417 MODE_int_t old_pc = cpu->pc;
418 MODE_int_t rs = reg(ic->arg[0]);
419 int x = (rs <= 0);
420 cpu->delay_slot = TO_BE_DELAYED;
421 ic[1].f(cpu, ic+1);
422 cpu->n_translated_instrs ++;
423 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
424 /* Note: Must be non-delayed when jumping to the new pc: */
425 cpu->delay_slot = NOT_DELAYED;
426 if (x) {
427 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
428 MIPS_INSTR_ALIGNMENT_SHIFT);
429 cpu->pc = old_pc + (int32_t)ic->arg[2];
430 quick_pc_to_pointers(cpu);
431 } else
432 cpu->cd.mips.next_ic ++;
433 } else
434 cpu->delay_slot = NOT_DELAYED;
435 }
436 X(blez_samepage)
437 {
438 MODE_int_t rs = reg(ic->arg[0]);
439 int x = (rs <= 0);
440 cpu->delay_slot = TO_BE_DELAYED;
441 ic[1].f(cpu, ic+1);
442 cpu->n_translated_instrs ++;
443 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
444 if (x)
445 cpu->cd.mips.next_ic = (struct mips_instr_call *)
446 ic->arg[2];
447 else
448 cpu->cd.mips.next_ic ++;
449 }
450 cpu->delay_slot = NOT_DELAYED;
451 }
452 X(blezl)
453 {
454 MODE_int_t old_pc = cpu->pc;
455 MODE_int_t rs = reg(ic->arg[0]);
456 int x = (rs <= 0);
457 cpu->delay_slot = TO_BE_DELAYED;
458 if (x)
459 ic[1].f(cpu, ic+1);
460 cpu->n_translated_instrs ++;
461 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
462 /* Note: Must be non-delayed when jumping to the new pc: */
463 cpu->delay_slot = NOT_DELAYED;
464 if (x) {
465 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
466 MIPS_INSTR_ALIGNMENT_SHIFT);
467 cpu->pc = old_pc + (int32_t)ic->arg[2];
468 quick_pc_to_pointers(cpu);
469 } else
470 cpu->cd.mips.next_ic ++;
471 } else
472 cpu->delay_slot = NOT_DELAYED;
473 }
474 X(blezl_samepage)
475 {
476 MODE_int_t rs = reg(ic->arg[0]);
477 int x = (rs <= 0);
478 cpu->delay_slot = TO_BE_DELAYED;
479 if (x)
480 ic[1].f(cpu, ic+1);
481 cpu->n_translated_instrs ++;
482 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
483 if (x)
484 cpu->cd.mips.next_ic = (struct mips_instr_call *)
485 ic->arg[2];
486 else
487 cpu->cd.mips.next_ic ++;
488 }
489 cpu->delay_slot = NOT_DELAYED;
490 }
491
492
493 /*
494 * bltz: Branch if less than
495 * bltzl: Branch if less than likely
496 *
497 * arg[0] = pointer to rs
498 * arg[2] = (int32_t) relative offset from the next instruction
499 */
500 X(bltz)
501 {
502 MODE_int_t old_pc = cpu->pc;
503 MODE_int_t rs = reg(ic->arg[0]);
504 int x = (rs < 0);
505 cpu->delay_slot = TO_BE_DELAYED;
506 ic[1].f(cpu, ic+1);
507 cpu->n_translated_instrs ++;
508 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
509 /* Note: Must be non-delayed when jumping to the new pc: */
510 cpu->delay_slot = NOT_DELAYED;
511 if (x) {
512 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
513 MIPS_INSTR_ALIGNMENT_SHIFT);
514 cpu->pc = old_pc + (int32_t)ic->arg[2];
515 quick_pc_to_pointers(cpu);
516 } else
517 cpu->cd.mips.next_ic ++;
518 } else
519 cpu->delay_slot = NOT_DELAYED;
520 }
521 X(bltz_samepage)
522 {
523 MODE_int_t rs = reg(ic->arg[0]);
524 int x = (rs < 0);
525 cpu->delay_slot = TO_BE_DELAYED;
526 ic[1].f(cpu, ic+1);
527 cpu->n_translated_instrs ++;
528 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
529 if (x)
530 cpu->cd.mips.next_ic = (struct mips_instr_call *)
531 ic->arg[2];
532 else
533 cpu->cd.mips.next_ic ++;
534 }
535 cpu->delay_slot = NOT_DELAYED;
536 }
537 X(bltzl)
538 {
539 MODE_int_t old_pc = cpu->pc;
540 MODE_int_t rs = reg(ic->arg[0]);
541 int x = (rs < 0);
542 cpu->delay_slot = TO_BE_DELAYED;
543 if (x)
544 ic[1].f(cpu, ic+1);
545 cpu->n_translated_instrs ++;
546 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
547 /* Note: Must be non-delayed when jumping to the new pc: */
548 cpu->delay_slot = NOT_DELAYED;
549 if (x) {
550 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
551 MIPS_INSTR_ALIGNMENT_SHIFT);
552 cpu->pc = old_pc + (int32_t)ic->arg[2];
553 quick_pc_to_pointers(cpu);
554 } else
555 cpu->cd.mips.next_ic ++;
556 } else
557 cpu->delay_slot = NOT_DELAYED;
558 }
559 X(bltzl_samepage)
560 {
561 MODE_int_t rs = reg(ic->arg[0]);
562 int x = (rs < 0);
563 cpu->delay_slot = TO_BE_DELAYED;
564 if (x)
565 ic[1].f(cpu, ic+1);
566 cpu->n_translated_instrs ++;
567 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
568 if (x)
569 cpu->cd.mips.next_ic = (struct mips_instr_call *)
570 ic->arg[2];
571 else
572 cpu->cd.mips.next_ic ++;
573 }
574 cpu->delay_slot = NOT_DELAYED;
575 }
576
577
578 /*
579 * bgez: Branch if greater than or equal
580 * bgezl: Branch if greater than or equal likely
581 *
582 * arg[0] = pointer to rs
583 * arg[2] = (int32_t) relative offset from the next instruction
584 */
585 X(bgez)
586 {
587 MODE_int_t old_pc = cpu->pc;
588 MODE_int_t rs = reg(ic->arg[0]);
589 int x = (rs >= 0);
590 cpu->delay_slot = TO_BE_DELAYED;
591 ic[1].f(cpu, ic+1);
592 cpu->n_translated_instrs ++;
593 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
594 /* Note: Must be non-delayed when jumping to the new pc: */
595 cpu->delay_slot = NOT_DELAYED;
596 if (x) {
597 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
598 MIPS_INSTR_ALIGNMENT_SHIFT);
599 cpu->pc = old_pc + (int32_t)ic->arg[2];
600 quick_pc_to_pointers(cpu);
601 } else
602 cpu->cd.mips.next_ic ++;
603 } else
604 cpu->delay_slot = NOT_DELAYED;
605 }
606 X(bgez_samepage)
607 {
608 MODE_int_t rs = reg(ic->arg[0]);
609 int x = (rs >= 0);
610 cpu->delay_slot = TO_BE_DELAYED;
611 ic[1].f(cpu, ic+1);
612 cpu->n_translated_instrs ++;
613 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
614 if (x)
615 cpu->cd.mips.next_ic = (struct mips_instr_call *)
616 ic->arg[2];
617 else
618 cpu->cd.mips.next_ic ++;
619 }
620 cpu->delay_slot = NOT_DELAYED;
621 }
622 X(bgezl)
623 {
624 MODE_int_t old_pc = cpu->pc;
625 MODE_int_t rs = reg(ic->arg[0]);
626 int x = (rs >= 0);
627 cpu->delay_slot = TO_BE_DELAYED;
628 if (x)
629 ic[1].f(cpu, ic+1);
630 cpu->n_translated_instrs ++;
631 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
632 /* Note: Must be non-delayed when jumping to the new pc: */
633 cpu->delay_slot = NOT_DELAYED;
634 if (x) {
635 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
636 MIPS_INSTR_ALIGNMENT_SHIFT);
637 cpu->pc = old_pc + (int32_t)ic->arg[2];
638 quick_pc_to_pointers(cpu);
639 } else
640 cpu->cd.mips.next_ic ++;
641 } else
642 cpu->delay_slot = NOT_DELAYED;
643 }
644 X(bgezl_samepage)
645 {
646 MODE_int_t rs = reg(ic->arg[0]);
647 int x = (rs >= 0);
648 cpu->delay_slot = TO_BE_DELAYED;
649 if (x)
650 ic[1].f(cpu, ic+1);
651 cpu->n_translated_instrs ++;
652 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
653 if (x)
654 cpu->cd.mips.next_ic = (struct mips_instr_call *)
655 ic->arg[2];
656 else
657 cpu->cd.mips.next_ic ++;
658 }
659 cpu->delay_slot = NOT_DELAYED;
660 }
661
662
663 /*
664 * bgezal: Branch if greater than or equal (and link)
665 * bgezall: Branch if greater than or equal (and link) likely
666 *
667 * arg[0] = pointer to rs
668 * arg[2] = (int32_t) relative offset from the next instruction
669 */
670 X(bgezal)
671 {
672 MODE_int_t old_pc = cpu->pc;
673 MODE_int_t rs = reg(ic->arg[0]);
674 int x = (rs >= 0), low_pc;
675
676 cpu->delay_slot = TO_BE_DELAYED;
677 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
678 / sizeof(struct mips_instr_call);
679 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
680 << MIPS_INSTR_ALIGNMENT_SHIFT);
681 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
682 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
683
684 ic[1].f(cpu, ic+1);
685 cpu->n_translated_instrs ++;
686 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
687 /* Note: Must be non-delayed when jumping to the new pc: */
688 cpu->delay_slot = NOT_DELAYED;
689 if (x) {
690 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
691 MIPS_INSTR_ALIGNMENT_SHIFT);
692 cpu->pc = old_pc + (int32_t)ic->arg[2];
693 quick_pc_to_pointers(cpu);
694 } else
695 cpu->cd.mips.next_ic ++;
696 } else
697 cpu->delay_slot = NOT_DELAYED;
698 }
699 X(bgezal_samepage)
700 {
701 MODE_int_t rs = reg(ic->arg[0]);
702 int x = (rs >= 0), low_pc;
703
704 cpu->delay_slot = TO_BE_DELAYED;
705 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
706 / sizeof(struct mips_instr_call);
707 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
708 << MIPS_INSTR_ALIGNMENT_SHIFT);
709 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
710 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
711
712 ic[1].f(cpu, ic+1);
713 cpu->n_translated_instrs ++;
714 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
715 if (x)
716 cpu->cd.mips.next_ic = (struct mips_instr_call *)
717 ic->arg[2];
718 else
719 cpu->cd.mips.next_ic ++;
720 }
721 cpu->delay_slot = NOT_DELAYED;
722 }
723 X(bgezall)
724 {
725 MODE_int_t old_pc = cpu->pc;
726 MODE_int_t rs = reg(ic->arg[0]);
727 int x = (rs >= 0), low_pc;
728
729 cpu->delay_slot = TO_BE_DELAYED;
730 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
731 / sizeof(struct mips_instr_call);
732 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
733 << MIPS_INSTR_ALIGNMENT_SHIFT);
734 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
735 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
736
737 if (x)
738 ic[1].f(cpu, ic+1);
739 cpu->n_translated_instrs ++;
740 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
741 /* Note: Must be non-delayed when jumping to the new pc: */
742 cpu->delay_slot = NOT_DELAYED;
743 if (x) {
744 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
745 MIPS_INSTR_ALIGNMENT_SHIFT);
746 cpu->pc = old_pc + (int32_t)ic->arg[2];
747 quick_pc_to_pointers(cpu);
748 } else
749 cpu->cd.mips.next_ic ++;
750 } else
751 cpu->delay_slot = NOT_DELAYED;
752 }
753 X(bgezall_samepage)
754 {
755 MODE_int_t rs = reg(ic->arg[0]);
756 int x = (rs >= 0), low_pc;
757
758 cpu->delay_slot = TO_BE_DELAYED;
759 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
760 / sizeof(struct mips_instr_call);
761 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
762 << MIPS_INSTR_ALIGNMENT_SHIFT);
763 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
764 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
765
766 if (x)
767 ic[1].f(cpu, ic+1);
768 cpu->n_translated_instrs ++;
769 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
770 if (x)
771 cpu->cd.mips.next_ic = (struct mips_instr_call *)
772 ic->arg[2];
773 else
774 cpu->cd.mips.next_ic ++;
775 }
776 cpu->delay_slot = NOT_DELAYED;
777 }
778
779
780 /*
781 * bltzal: Branch if less than zero (and link)
782 * bltzall: Branch if less than zero (and link) likely
783 *
784 * arg[0] = pointer to rs
785 * arg[2] = (int32_t) relative offset from the next instruction
786 */
787 X(bltzal)
788 {
789 MODE_int_t old_pc = cpu->pc;
790 MODE_int_t rs = reg(ic->arg[0]);
791 int x = (rs < 0), low_pc;
792
793 cpu->delay_slot = TO_BE_DELAYED;
794 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
795 / sizeof(struct mips_instr_call);
796 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
797 << MIPS_INSTR_ALIGNMENT_SHIFT);
798 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
799 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
800
801 ic[1].f(cpu, ic+1);
802 cpu->n_translated_instrs ++;
803 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
804 /* Note: Must be non-delayed when jumping to the new pc: */
805 cpu->delay_slot = NOT_DELAYED;
806 if (x) {
807 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
808 MIPS_INSTR_ALIGNMENT_SHIFT);
809 cpu->pc = old_pc + (int32_t)ic->arg[2];
810 quick_pc_to_pointers(cpu);
811 } else
812 cpu->cd.mips.next_ic ++;
813 } else
814 cpu->delay_slot = NOT_DELAYED;
815 }
816 X(bltzal_samepage)
817 {
818 MODE_int_t rs = reg(ic->arg[0]);
819 int x = (rs < 0), low_pc;
820
821 cpu->delay_slot = TO_BE_DELAYED;
822 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
823 / sizeof(struct mips_instr_call);
824 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
825 << MIPS_INSTR_ALIGNMENT_SHIFT);
826 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
827 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
828
829 ic[1].f(cpu, ic+1);
830 cpu->n_translated_instrs ++;
831 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
832 if (x)
833 cpu->cd.mips.next_ic = (struct mips_instr_call *)
834 ic->arg[2];
835 else
836 cpu->cd.mips.next_ic ++;
837 }
838 cpu->delay_slot = NOT_DELAYED;
839 }
840 X(bltzall)
841 {
842 MODE_int_t old_pc = cpu->pc;
843 MODE_int_t rs = reg(ic->arg[0]);
844 int x = (rs < 0), low_pc;
845
846 cpu->delay_slot = TO_BE_DELAYED;
847 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
848 / sizeof(struct mips_instr_call);
849 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
850 << MIPS_INSTR_ALIGNMENT_SHIFT);
851 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
852 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
853
854 if (x)
855 ic[1].f(cpu, ic+1);
856 cpu->n_translated_instrs ++;
857 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
858 /* Note: Must be non-delayed when jumping to the new pc: */
859 cpu->delay_slot = NOT_DELAYED;
860 if (x) {
861 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
862 MIPS_INSTR_ALIGNMENT_SHIFT);
863 cpu->pc = old_pc + (int32_t)ic->arg[2];
864 quick_pc_to_pointers(cpu);
865 } else
866 cpu->cd.mips.next_ic ++;
867 } else
868 cpu->delay_slot = NOT_DELAYED;
869 }
870 X(bltzall_samepage)
871 {
872 MODE_int_t rs = reg(ic->arg[0]);
873 int x = (rs < 0), low_pc;
874
875 cpu->delay_slot = TO_BE_DELAYED;
876 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
877 / sizeof(struct mips_instr_call);
878 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
879 << MIPS_INSTR_ALIGNMENT_SHIFT);
880 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
881 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
882
883 if (x)
884 ic[1].f(cpu, ic+1);
885 cpu->n_translated_instrs ++;
886 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
887 if (x)
888 cpu->cd.mips.next_ic = (struct mips_instr_call *)
889 ic->arg[2];
890 else
891 cpu->cd.mips.next_ic ++;
892 }
893 cpu->delay_slot = NOT_DELAYED;
894 }
895
896
897 /*
898 * bgtz: Branch if greater than zero
899 * bgtzl: Branch if greater than zero likely
900 *
901 * arg[0] = pointer to rs
902 * arg[2] = (int32_t) relative offset from the next instruction
903 */
904 X(bgtz)
905 {
906 MODE_int_t old_pc = cpu->pc;
907 MODE_int_t rs = reg(ic->arg[0]);
908 int x = (rs > 0);
909 cpu->delay_slot = TO_BE_DELAYED;
910 ic[1].f(cpu, ic+1);
911 cpu->n_translated_instrs ++;
912 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
913 /* Note: Must be non-delayed when jumping to the new pc: */
914 cpu->delay_slot = NOT_DELAYED;
915 if (x) {
916 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
917 MIPS_INSTR_ALIGNMENT_SHIFT);
918 cpu->pc = old_pc + (int32_t)ic->arg[2];
919 quick_pc_to_pointers(cpu);
920 } else
921 cpu->cd.mips.next_ic ++;
922 } else
923 cpu->delay_slot = NOT_DELAYED;
924 }
925 X(bgtz_samepage)
926 {
927 MODE_int_t rs = reg(ic->arg[0]);
928 int x = (rs > 0);
929 cpu->delay_slot = TO_BE_DELAYED;
930 ic[1].f(cpu, ic+1);
931 cpu->n_translated_instrs ++;
932 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
933 if (x)
934 cpu->cd.mips.next_ic = (struct mips_instr_call *)
935 ic->arg[2];
936 else
937 cpu->cd.mips.next_ic ++;
938 }
939 cpu->delay_slot = NOT_DELAYED;
940 }
941 X(bgtzl)
942 {
943 MODE_int_t old_pc = cpu->pc;
944 MODE_int_t rs = reg(ic->arg[0]);
945 int x = (rs > 0);
946 cpu->delay_slot = TO_BE_DELAYED;
947 if (x)
948 ic[1].f(cpu, ic+1);
949 cpu->n_translated_instrs ++;
950 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
951 /* Note: Must be non-delayed when jumping to the new pc: */
952 cpu->delay_slot = NOT_DELAYED;
953 if (x) {
954 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
955 MIPS_INSTR_ALIGNMENT_SHIFT);
956 cpu->pc = old_pc + (int32_t)ic->arg[2];
957 quick_pc_to_pointers(cpu);
958 } else
959 cpu->cd.mips.next_ic ++;
960 } else
961 cpu->delay_slot = NOT_DELAYED;
962 }
963 X(bgtzl_samepage)
964 {
965 MODE_int_t rs = reg(ic->arg[0]);
966 int x = (rs > 0);
967 cpu->delay_slot = TO_BE_DELAYED;
968 if (x)
969 ic[1].f(cpu, ic+1);
970 cpu->n_translated_instrs ++;
971 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
972 if (x)
973 cpu->cd.mips.next_ic = (struct mips_instr_call *)
974 ic->arg[2];
975 else
976 cpu->cd.mips.next_ic ++;
977 }
978 cpu->delay_slot = NOT_DELAYED;
979 }
980
981
982 /*
983 * jr, jalr: Jump to a register [and link].
984 *
985 * arg[0] = ptr to rs
986 * arg[1] = ptr to rd (for jalr)
987 * arg[2] = (int32_t) relative offset of the next instruction
988 */
989 X(jr)
990 {
991 MODE_int_t rs = reg(ic->arg[0]);
992 cpu->delay_slot = TO_BE_DELAYED;
993 ic[1].f(cpu, ic+1);
994 cpu->n_translated_instrs ++;
995 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
996 cpu->pc = rs;
997 /* Note: Must be non-delayed when jumping to the new pc: */
998 cpu->delay_slot = NOT_DELAYED;
999 quick_pc_to_pointers(cpu);
1000 } else
1001 cpu->delay_slot = NOT_DELAYED;
1002 }
1003 X(jr_ra)
1004 {
1005 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
1006 cpu->delay_slot = TO_BE_DELAYED;
1007 ic[1].f(cpu, ic+1);
1008 cpu->n_translated_instrs ++;
1009 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1010 cpu->pc = rs;
1011 /* Note: Must be non-delayed when jumping to the new pc: */
1012 cpu->delay_slot = NOT_DELAYED;
1013 quick_pc_to_pointers(cpu);
1014 } else
1015 cpu->delay_slot = NOT_DELAYED;
1016 }
1017 X(jr_ra_addiu)
1018 {
1019 /* jr ra, followed by an addiu */
1020 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
1021 reg(ic[1].arg[1]) = (int32_t)
1022 ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
1023 cpu->pc = rs;
1024 quick_pc_to_pointers(cpu);
1025 cpu->n_translated_instrs ++;
1026 }
1027 X(jr_ra_trace)
1028 {
1029 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
1030 cpu->delay_slot = TO_BE_DELAYED;
1031 ic[1].f(cpu, ic+1);
1032 cpu->n_translated_instrs ++;
1033 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1034 cpu->pc = rs;
1035 cpu_functioncall_trace_return(cpu);
1036 /* Note: Must be non-delayed when jumping to the new pc: */
1037 cpu->delay_slot = NOT_DELAYED;
1038 quick_pc_to_pointers(cpu);
1039 } else
1040 cpu->delay_slot = NOT_DELAYED;
1041 }
1042 X(jalr)
1043 {
1044 MODE_int_t rs = reg(ic->arg[0]), rd;
1045 cpu->delay_slot = TO_BE_DELAYED;
1046 rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1047 MIPS_INSTR_ALIGNMENT_SHIFT);
1048 rd += (int32_t)ic->arg[2];
1049 reg(ic->arg[1]) = rd;
1050 ic[1].f(cpu, ic+1);
1051 cpu->n_translated_instrs ++;
1052 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1053 cpu->pc = rs;
1054 /* Note: Must be non-delayed when jumping to the new pc: */
1055 cpu->delay_slot = NOT_DELAYED;
1056 quick_pc_to_pointers(cpu);
1057 } else
1058 cpu->delay_slot = NOT_DELAYED;
1059 }
1060 X(jalr_trace)
1061 {
1062 MODE_int_t rs = reg(ic->arg[0]), rd;
1063 cpu->delay_slot = TO_BE_DELAYED;
1064 rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1065 MIPS_INSTR_ALIGNMENT_SHIFT);
1066 rd += (int32_t)ic->arg[2];
1067 reg(ic->arg[1]) = rd;
1068 ic[1].f(cpu, ic+1);
1069 cpu->n_translated_instrs ++;
1070 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1071 cpu->pc = rs;
1072 cpu_functioncall_trace(cpu, cpu->pc);
1073 /* Note: Must be non-delayed when jumping to the new pc: */
1074 cpu->delay_slot = NOT_DELAYED;
1075 quick_pc_to_pointers(cpu);
1076 } else
1077 cpu->delay_slot = NOT_DELAYED;
1078 }
1079
1080
1081 /*
1082 * j, jal: Jump [and link].
1083 *
1084 * arg[0] = lowest 28 bits of new pc.
1085 * arg[1] = offset from start of page to the jal instruction + 8
1086 */
1087 X(j)
1088 {
1089 MODE_int_t old_pc = cpu->pc;
1090 cpu->delay_slot = TO_BE_DELAYED;
1091 ic[1].f(cpu, ic+1);
1092 cpu->n_translated_instrs ++;
1093 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1094 /* Note: Must be non-delayed when jumping to the new pc: */
1095 cpu->delay_slot = NOT_DELAYED;
1096 old_pc &= ~0x03ffffff;
1097 cpu->pc = old_pc | (uint32_t)ic->arg[0];
1098 quick_pc_to_pointers(cpu);
1099 } else
1100 cpu->delay_slot = NOT_DELAYED;
1101 }
1102 X(jal)
1103 {
1104 MODE_int_t old_pc = cpu->pc;
1105 cpu->delay_slot = TO_BE_DELAYED;
1106 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1107 cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
1108 ic[1].f(cpu, ic+1);
1109 cpu->n_translated_instrs ++;
1110 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1111 /* Note: Must be non-delayed when jumping to the new pc: */
1112 cpu->delay_slot = NOT_DELAYED;
1113 old_pc &= ~0x03ffffff;
1114 cpu->pc = old_pc | (int32_t)ic->arg[0];
1115 quick_pc_to_pointers(cpu);
1116 } else
1117 cpu->delay_slot = NOT_DELAYED;
1118 }
1119 X(jal_trace)
1120 {
1121 MODE_int_t old_pc = cpu->pc;
1122 cpu->delay_slot = TO_BE_DELAYED;
1123 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1124 cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
1125 ic[1].f(cpu, ic+1);
1126 cpu->n_translated_instrs ++;
1127 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1128 /* Note: Must be non-delayed when jumping to the new pc: */
1129 cpu->delay_slot = NOT_DELAYED;
1130 old_pc &= ~0x03ffffff;
1131 cpu->pc = old_pc | (int32_t)ic->arg[0];
1132 cpu_functioncall_trace(cpu, cpu->pc);
1133 quick_pc_to_pointers(cpu);
1134 } else
1135 cpu->delay_slot = NOT_DELAYED;
1136 }
1137
1138
1139 /*
1140 * cache: Cache operation.
1141 */
1142 X(cache)
1143 {
1144 /* TODO: Implement cache operations. */
1145
1146 /* Make sure the rmw bit is cleared: */
1147 cpu->cd.mips.rmw = 0;
1148 }
1149
1150
1151 /*
1152 * ext: Extract bitfield.
1153 *
1154 * arg[0] = pointer to rt
1155 * arg[1] = pointer to rs
1156 * arg[2] = (msbd << 5) + lsb
1157 */
1158 X(ext)
1159 {
1160 fatal("ext: todo\n");
1161 exit(1);
1162 }
1163
1164
1165 /*
1166 * dsbh: Doubleword swap bytes within half-word
1167 * dshd: Doubleword swap half-words within double-word
1168 * wsbh: Word swap bytes within half-word
1169 * seb: Sign-extend byte
1170 * seh: Sign-extend half-word
1171 *
1172 * arg[0] = pointer to rt
1173 * arg[1] = pointer to rd
1174 */
1175 X(dsbh)
1176 {
1177 uint64_t x = reg(ic->arg[0]);
1178 x = ((x & 0x00ff00ff00ff00ffULL) << 8)
1179 | ((x & 0xff00ff00ff00ff00ULL) >> 8);
1180 reg(ic->arg[1]) = x;
1181 }
1182 X(dshd)
1183 {
1184 uint64_t x = reg(ic->arg[0]);
1185 x = ((x & 0x000000000000ffffULL) << 48)
1186 | ((x & 0x00000000ffff0000ULL) << 16)
1187 | ((x & 0x0000ffff00000000ULL) >> 16)
1188 | ((x & 0xffff000000000000ULL) >> 48);
1189 reg(ic->arg[1]) = x;
1190 }
1191 X(wsbh)
1192 {
1193 uint32_t x = reg(ic->arg[0]);
1194 x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8);
1195 reg(ic->arg[1]) = (int32_t) x;
1196 }
1197 X(seb) { reg(ic->arg[1]) = (int8_t)reg(ic->arg[0]); }
1198 X(seh) { reg(ic->arg[1]) = (int16_t)reg(ic->arg[0]); }
1199
1200
1201 /*
1202 * 2-register + immediate:
1203 *
1204 * arg[0] = pointer to rs
1205 * arg[1] = pointer to rt
1206 * arg[2] = uint32_t immediate value
1207 */
1208 X(andi) { reg(ic->arg[1]) = reg(ic->arg[0]) & (uint32_t)ic->arg[2]; }
1209 X(ori) { reg(ic->arg[1]) = reg(ic->arg[0]) | (uint32_t)ic->arg[2]; }
1210 X(xori) { reg(ic->arg[1]) = reg(ic->arg[0]) ^ (uint32_t)ic->arg[2]; }
1211
1212
1213 /*
1214 * 2-register:
1215 *
1216 * arg[0] = ptr to rs
1217 * arg[1] = ptr to rt
1218 */
1219 X(div)
1220 {
1221 int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1222 int32_t res, rem;
1223 if (b == 0)
1224 res = 0, rem = a;
1225 else
1226 res = a / b, rem = a - b*res;
1227 cpu->cd.mips.lo = (int32_t)res;
1228 cpu->cd.mips.hi = (int32_t)rem;
1229 }
1230 X(divu)
1231 {
1232 uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1233 uint32_t res, rem;
1234 if (b == 0)
1235 res = 0, rem = a;
1236 else
1237 res = a / b, rem = a - b*res;
1238 cpu->cd.mips.lo = (int32_t)res;
1239 cpu->cd.mips.hi = (int32_t)rem;
1240 }
1241 X(ddiv)
1242 {
1243 int64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1244 int64_t res, rem;
1245 if (b == 0)
1246 res = 0;
1247 else
1248 res = a / b;
1249 rem = a - b*res;
1250 cpu->cd.mips.lo = res;
1251 cpu->cd.mips.hi = rem;
1252 }
1253 X(ddivu)
1254 {
1255 uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1256 uint64_t res, rem;
1257 if (b == 0)
1258 res = 0;
1259 else
1260 res = a / b;
1261 rem = a - b*res;
1262 cpu->cd.mips.lo = res;
1263 cpu->cd.mips.hi = rem;
1264 }
1265 X(mult)
1266 {
1267 int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1268 int64_t res = (int64_t)a * (int64_t)b;
1269 cpu->cd.mips.lo = (int32_t)res;
1270 cpu->cd.mips.hi = (int32_t)(res >> 32);
1271 }
1272 X(mult_r5900)
1273 {
1274 /* C790/TX79/R5900 multiplication, stores result in
1275 hi, lo, and a third register */
1276 int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1277 int64_t res = (int64_t)a * (int64_t)b;
1278 cpu->cd.mips.lo = (int32_t)res;
1279 cpu->cd.mips.hi = (int32_t)(res >> 32);
1280 reg(ic->arg[2]) = (int32_t)res;
1281 }
1282 X(multu)
1283 {
1284 uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1285 uint64_t res = (uint64_t)a * (uint64_t)b;
1286 cpu->cd.mips.lo = (int32_t)res;
1287 cpu->cd.mips.hi = (int32_t)(res >> 32);
1288 }
1289 X(multu_r5900)
1290 {
1291 /* C790/TX79/R5900 multiplication, stores result in
1292 hi, lo, and a third register */
1293 uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1294 uint64_t res = (uint64_t)a * (uint64_t)b;
1295 cpu->cd.mips.lo = (int32_t)res;
1296 cpu->cd.mips.hi = (int32_t)(res >> 32);
1297 reg(ic->arg[2]) = (int32_t)res;
1298 }
1299 X(dmult)
1300 {
1301 uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1302 uint64_t hi = 0, lo = 0;
1303 int neg = 0;
1304 if (a >> 63)
1305 neg = !neg, a = -a;
1306 if (b >> 63)
1307 neg = !neg, b = -b;
1308 for (; a; a >>= 1) {
1309 if (a & 1) {
1310 uint64_t old_lo = lo;
1311 hi += c;
1312 lo += b;
1313 if (lo < old_lo)
1314 hi ++;
1315 }
1316 c = (c << 1) | (b >> 63); b <<= 1;
1317 }
1318 if (neg) {
1319 if (lo == 0)
1320 hi --;
1321 lo --;
1322 hi ^= (int64_t) -1;
1323 lo ^= (int64_t) -1;
1324 }
1325 cpu->cd.mips.lo = lo;
1326 cpu->cd.mips.hi = hi;
1327 }
1328 X(dmultu)
1329 {
1330 uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1331 uint64_t hi = 0, lo = 0;
1332 for (; a; a >>= 1) {
1333 if (a & 1) {
1334 uint64_t old_lo = lo;
1335 hi += c;
1336 lo += b;
1337 if (lo < old_lo)
1338 hi ++;
1339 }
1340 c = (c << 1) | (b >> 63); b <<= 1;
1341 }
1342 cpu->cd.mips.lo = lo;
1343 cpu->cd.mips.hi = hi;
1344 }
1345 X(tge)
1346 {
1347 MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1348 if (a >= b) {
1349 /* Synch. PC and cause an exception: */
1350 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1351 / sizeof(struct mips_instr_call);
1352 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1353 << MIPS_INSTR_ALIGNMENT_SHIFT);
1354 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1355 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1356 }
1357 }
1358 X(tgeu)
1359 {
1360 MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1361 if (a >= b) {
1362 /* Synch. PC and cause an exception: */
1363 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1364 / sizeof(struct mips_instr_call);
1365 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1366 << MIPS_INSTR_ALIGNMENT_SHIFT);
1367 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1368 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1369 }
1370 }
1371 X(tlt)
1372 {
1373 MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1374 if (a < b) {
1375 /* Synch. PC and cause an exception: */
1376 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1377 / sizeof(struct mips_instr_call);
1378 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1379 << MIPS_INSTR_ALIGNMENT_SHIFT);
1380 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1381 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1382 }
1383 }
1384 X(tltu)
1385 {
1386 MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1387 if (a < b) {
1388 /* Synch. PC and cause an exception: */
1389 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1390 / sizeof(struct mips_instr_call);
1391 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1392 << MIPS_INSTR_ALIGNMENT_SHIFT);
1393 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1394 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1395 }
1396 }
1397 X(teq)
1398 {
1399 MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1400 if (a == b) {
1401 /* Synch. PC and cause an exception: */
1402 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1403 / sizeof(struct mips_instr_call);
1404 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1405 << MIPS_INSTR_ALIGNMENT_SHIFT);
1406 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1407 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1408 }
1409 }
1410 X(tne)
1411 {
1412 MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1413 if (a != b) {
1414 /* Synch. PC and cause an exception: */
1415 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1416 / sizeof(struct mips_instr_call);
1417 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1418 << MIPS_INSTR_ALIGNMENT_SHIFT);
1419 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1420 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1421 }
1422 }
1423
1424
1425 /*
1426 * 3-register arithmetic instructions:
1427 *
1428 * arg[0] = ptr to rs
1429 * arg[1] = ptr to rt
1430 * arg[2] = ptr to rd
1431 */
1432 X(addu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) + reg(ic->arg[1])); }
1433 X(add)
1434 {
1435 int32_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1436 int32_t rd = rs + rt;
1437
1438 if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1439 /* Synch. PC and cause an exception: */
1440 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1441 / sizeof(struct mips_instr_call);
1442 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1443 << MIPS_INSTR_ALIGNMENT_SHIFT);
1444 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1445 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1446 } else
1447 reg(ic->arg[2]) = rd;
1448 }
1449 X(daddu){ reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]); }
1450 X(dadd)
1451 {
1452 int64_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1453 int64_t rd = rs + rt;
1454
1455 if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1456 /* Synch. PC and cause an exception: */
1457 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1458 / sizeof(struct mips_instr_call);
1459 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1460 << MIPS_INSTR_ALIGNMENT_SHIFT);
1461 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1462 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1463 } else
1464 reg(ic->arg[2]) = rd;
1465 }
1466 X(subu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) - reg(ic->arg[1])); }
1467 X(sub)
1468 {
1469 /* NOTE: Negating rt and using addition. TODO: Is this correct? */
1470 int32_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1471 int32_t rd = rs + rt;
1472
1473 if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1474 /* Synch. PC and cause an exception: */
1475 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1476 / sizeof(struct mips_instr_call);
1477 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1478 << MIPS_INSTR_ALIGNMENT_SHIFT);
1479 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1480 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1481 } else
1482 reg(ic->arg[2]) = rd;
1483 }
1484 X(dsubu){ reg(ic->arg[2]) = reg(ic->arg[0]) - reg(ic->arg[1]); }
1485 X(dsub)
1486 {
1487 /* NOTE: Negating rt and using addition. TODO: Is this correct? */
1488 int64_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1489 int64_t rd = rs + rt;
1490
1491 if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1492 /* Synch. PC and cause an exception: */
1493 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1494 / sizeof(struct mips_instr_call);
1495 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1496 << MIPS_INSTR_ALIGNMENT_SHIFT);
1497 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1498 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1499 } else
1500 reg(ic->arg[2]) = rd;
1501 }
1502 X(slt) {
1503 reg(ic->arg[2]) =
1504 (MODE_int_t)reg(ic->arg[0]) < (MODE_int_t)reg(ic->arg[1]);
1505 }
1506 X(sltu) {
1507 reg(ic->arg[2]) =
1508 (MODE_uint_t)reg(ic->arg[0]) < (MODE_uint_t)reg(ic->arg[1]);
1509 }
1510 X(and) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
1511 X(or) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
1512 X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
1513 X(nor) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1])); }
1514 X(sll) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << (int32_t)ic->arg[1]); }
1515 X(sllv){ int32_t sa = reg(ic->arg[1]) & 31;
1516 reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << sa); }
1517 X(srl) { reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1518 X(srlv){ int32_t sa = reg(ic->arg[1]) & 31;
1519 reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> sa); }
1520 X(sra) { reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1521 X(srav){ int32_t sa = reg(ic->arg[1]) & 31;
1522 reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> sa); }
1523 X(dsll) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) << (int64_t)ic->arg[1]; }
1524 X(dsllv){ int64_t sa = reg(ic->arg[1]) & 63;
1525 reg(ic->arg[2]) = reg(ic->arg[0]) << sa; }
1526 X(dsrl) { reg(ic->arg[2]) = (int64_t)((uint64_t)reg(ic->arg[0]) >>
1527 (uint64_t) ic->arg[1]);}
1528 X(dsrlv){ int64_t sa = reg(ic->arg[1]) & 63;
1529 reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) >> sa; }
1530 X(dsra) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> (int64_t)ic->arg[1]; }
1531 X(dsrav){ int64_t sa = reg(ic->arg[1]) & 63;
1532 reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> sa; }
1533 X(mul) { reg(ic->arg[2]) = (int32_t)
1534 ( (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]) ); }
1535 X(movn) { if (reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1536 X(movz) { if (!reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1537
1538
1539 /*
1540 * p*: 128-bit C790/TX79/R5900 stuff
1541 *
1542 * arg[0] = rs (note: not a pointer)
1543 * arg[1] = rt (note: not a pointer)
1544 * arg[2] = rd (note: not a pointer)
1545 */
1546 X(por)
1547 {
1548 cpu->cd.mips.gpr[ic->arg[2]] = cpu->cd.mips.gpr[ic->arg[0]] |
1549 cpu->cd.mips.gpr[ic->arg[1]];
1550 cpu->cd.mips.gpr_quadhi[ic->arg[2]] =
1551 cpu->cd.mips.gpr_quadhi[ic->arg[0]] |
1552 cpu->cd.mips.gpr_quadhi[ic->arg[1]];
1553 }
1554 X(pextlw)
1555 {
1556 uint64_t lo, hi;
1557
1558 lo = (uint32_t)cpu->cd.mips.gpr[ic->arg[1]] |
1559 (uint64_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[0]] << 32);
1560 hi = (cpu->cd.mips.gpr[ic->arg[0]] & 0xffffffff00000000ULL) |
1561 (uint32_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[1]] >> 32);
1562
1563 cpu->cd.mips.gpr[ic->arg[2]] = lo;
1564 cpu->cd.mips.gpr_quadhi[ic->arg[2]] = hi;
1565 }
1566
1567
1568 /*
1569 * madd, maddu, msub, msubu: Multiply-and-add/subtract
1570 *
1571 * arg[0] = ptr to rs
1572 * arg[1] = ptr to rt
1573 * arg[2] = ptr to rd (only used on R5900/TX79)
1574 */
1575 X(madd)
1576 {
1577 int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1578 int64_t sum = rs * rt,
1579 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1580 hilo += sum;
1581 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1582 }
1583 X(madd_rd)
1584 {
1585 int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1586 int64_t sum = rs * rt,
1587 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1588 hilo += sum;
1589 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1590 reg(ic->arg[2]) = (int32_t)hilo;
1591 }
1592 X(msub)
1593 {
1594 int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1595 int64_t sum = rs * rt,
1596 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1597 hilo -= sum;
1598 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1599 }
1600 X(maddu)
1601 {
1602 int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1603 int64_t sum = rs * rt,
1604 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1605 hilo += sum;
1606 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1607 }
1608 X(maddu_rd)
1609 {
1610 int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1611 int64_t sum = rs * rt,
1612 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1613 hilo += sum;
1614 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1615 reg(ic->arg[2]) = (int32_t)hilo;
1616 }
1617 X(msubu)
1618 {
1619 int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1620 int64_t sum = rs * rt,
1621 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1622 hilo -= sum;
1623 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1624 }
1625
1626
1627 /*
1628 * mov: Move one register into another.
1629 *
1630 * arg[0] = pointer to source
1631 * arg[2] = pointer to destination
1632 */
1633 X(mov) { reg(ic->arg[2]) = reg(ic->arg[0]); }
1634
1635
1636 /*
1637 * clz, clo, dclz, dclo: Count leading zeroes/ones.
1638 *
1639 * arg[0] = pointer to rs
1640 * arg[1] = pointer to rd
1641 */
1642 X(clz)
1643 {
1644 uint32_t x = reg(ic->arg[0]);
1645 int count;
1646 for (count=0; count<32; count++) {
1647 if (x & 0x80000000UL)
1648 break;
1649 x <<= 1;
1650 }
1651 reg(ic->arg[1]) = count;
1652 }
1653 X(clo)
1654 {
1655 uint32_t x = reg(ic->arg[0]);
1656 int count;
1657 for (count=0; count<32; count++) {
1658 if (!(x & 0x80000000UL))
1659 break;
1660 x <<= 1;
1661 }
1662 reg(ic->arg[1]) = count;
1663 }
1664 X(dclz)
1665 {
1666 uint64_t x = reg(ic->arg[0]);
1667 int count;
1668 for (count=0; count<64; count++) {
1669 if (x & 0x8000000000000000ULL)
1670 break;
1671 x <<= 1;
1672 }
1673 reg(ic->arg[1]) = count;
1674 }
1675 X(dclo)
1676 {
1677 uint64_t x = reg(ic->arg[0]);
1678 int count;
1679 for (count=0; count<64; count++) {
1680 if (!(x & 0x8000000000000000ULL))
1681 break;
1682 x <<= 1;
1683 }
1684 reg(ic->arg[1]) = count;
1685 }
1686
1687
1688 /*
1689 * addi, daddi: Add immediate, overflow detection.
1690 * addiu, daddiu: Add immediate.
1691 * slti: Set if less than immediate (signed 32-bit)
1692 * sltiu: Set if less than immediate (signed 32-bit, but unsigned compare)
1693 *
1694 * arg[0] = pointer to rs
1695 * arg[1] = pointer to rt
1696 * arg[2] = (int32_t) immediate value
1697 */
1698 X(addi)
1699 {
1700 int32_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1701 int32_t rt = rs + imm;
1702
1703 if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1704 /* Synch. PC and cause an exception: */
1705 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1706 / sizeof(struct mips_instr_call);
1707 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1708 << MIPS_INSTR_ALIGNMENT_SHIFT);
1709 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1710 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1711 } else
1712 reg(ic->arg[1]) = rt;
1713 }
1714 X(addiu)
1715 {
1716 reg(ic->arg[1]) = (int32_t)
1717 ((int32_t)reg(ic->arg[0]) + (int32_t)ic->arg[2]);
1718 }
1719 X(daddi)
1720 {
1721 int64_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1722 int64_t rt = rs + imm;
1723
1724 if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1725 /* Synch. PC and cause an exception: */
1726 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1727 / sizeof(struct mips_instr_call);
1728 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1729 << MIPS_INSTR_ALIGNMENT_SHIFT);
1730 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1731 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1732 } else
1733 reg(ic->arg[1]) = rt;
1734 }
1735 X(daddiu)
1736 {
1737 reg(ic->arg[1]) = reg(ic->arg[0]) + (int32_t)ic->arg[2];
1738 }
1739 X(slti)
1740 {
1741 reg(ic->arg[1]) = (MODE_int_t)reg(ic->arg[0]) < (int32_t)ic->arg[2];
1742 }
1743 X(sltiu)
1744 {
1745 reg(ic->arg[1]) = (MODE_uint_t)reg(ic->arg[0]) <
1746 ((MODE_uint_t)(int32_t)ic->arg[2]);
1747 }
1748
1749
1750 /*
1751 * set: Set a register to an immediate (signed) 32-bit value.
1752 * (This is the actual implementation of the lui instruction.)
1753 *
1754 * arg[0] = pointer to the register
1755 * arg[1] = (int32_t) immediate value
1756 */
1757 X(set)
1758 {
1759 reg(ic->arg[0]) = (int32_t)ic->arg[1];
1760 }
1761
1762
1763 /*
1764 * cfc0: Copy from Coprocessor 0.
1765 * mfc0, dmfc0: Move from Coprocessor 0.
1766 * mtc0, dmtc0: Move to Coprocessor 0.
1767 *
1768 * arg[0] = pointer to GPR (rt)
1769 * arg[1] = coprocessor 0 register number | (select << 5) (or for the
1770 * cfc0 instruction, the coprocessor control register number)
1771 * arg[2] = relative addr of this instruction within the page
1772 */
1773 X(cfc0)
1774 {
1775 int fs = ic->arg[1] & 31;
1776 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1777 cpu->pc |= ic->arg[2];
1778 /* TODO: cause exception if necessary */
1779 reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->fcr[fs];
1780 }
1781 X(mfc0)
1782 {
1783 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1784 uint64_t tmp;
1785 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1786 cpu->pc |= ic->arg[2];
1787 /* TODO: cause exception if necessary */
1788 coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, &tmp, select);
1789 reg(ic->arg[0]) = (int32_t)tmp;
1790 }
1791 X(mfc0_select0)
1792 {
1793 /* Fast int32_t read, with no side effects: */
1794 int rd = ic->arg[1] & 31;
1795 #if 0
1796 uint64_t tmp;
1797 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1798 cpu->pc |= ic->arg[2];
1799 /* TODO: cause exception if necessary */
1800 #endif
1801 reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->reg[rd];
1802 }
1803 X(mtc0)
1804 {
1805 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1806 uint64_t tmp = (int32_t) reg(ic->arg[0]);
1807
1808 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1809 cpu->pc |= ic->arg[2];
1810
1811 /* TODO: cause exception if necessary */
1812 coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd, &tmp, 0, select);
1813
1814 /*
1815 * Interrupts enabled, and any interrupt pending? (Note/TODO: This
1816 * code is duplicated in cpu_dyntrans.c. Fix this?)
1817 */
1818 if (rd == COP0_STATUS && !cpu->delay_slot) {
1819 uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
1820 uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1821 /* NOTE: STATUS_IE happens to match the enable bit also
1822 on R2000/R3000, so this is ok. */
1823 if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1824 if (status & (STATUS_EXL | STATUS_ERL))
1825 status &= ~STATUS_IE;
1826 }
1827 /* Ugly R5900 special case: (TODO: move this?) */
1828 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1829 !(status & R5900_STATUS_EIE))
1830 status &= ~STATUS_IE;
1831 if (status & STATUS_IE && (status & cause & STATUS_IM_MASK)) {
1832 cpu->pc += sizeof(uint32_t);
1833 mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0,0,0,0,0);
1834 }
1835 }
1836 }
1837 X(dmfc0)
1838 {
1839 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1840 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1841 cpu->pc |= ic->arg[2];
1842 /* TODO: cause exception if necessary */
1843 coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd,
1844 (uint64_t *)ic->arg[0], select);
1845 }
1846 X(dmfc0_select0)
1847 {
1848 /* Fast int64_t read, with no side effects: */
1849 int rd = ic->arg[1] & 31;
1850 #if 0
1851 uint64_t tmp;
1852 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1853 cpu->pc |= ic->arg[2];
1854 /* TODO: cause exception if necessary */
1855 #endif
1856 reg(ic->arg[0]) = cpu->cd.mips.coproc[0]->reg[rd];
1857 }
1858 X(dmtc0)
1859 {
1860 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1861 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1862 cpu->pc |= ic->arg[2];
1863 /* TODO: cause exception if necessary */
1864 coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,
1865 (uint64_t *)ic->arg[0], 1, select);
1866 }
1867
1868
1869 /*
1870 * cop1_bc: Floating point conditional branch.
1871 *
1872 * arg[0] = cc
1873 * arg[1] = nd (=2) and tf (=1) bits
1874 * arg[2] = offset (relative to start of this page)
1875 */
1876 X(cop1_bc)
1877 {
1878 MODE_int_t old_pc = cpu->pc;
1879 int x, cc = ic->arg[0];
1880
1881 COPROC_AVAILABILITY_CHECK(1);
1882
1883 /* Get the correct condition code bit: */
1884 if (cc == 0)
1885 x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1886 >> MIPS_FCSR_FCC0_SHIFT) & 1;
1887 else
1888 x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1889 >> (MIPS_FCSR_FCC1_SHIFT + cc-1)) & 1;
1890
1891 /* Branch on false? Then invert the truth value. */
1892 if (!(ic->arg[1] & 1))
1893 x ^= 1;
1894
1895 /* Execute the delay slot (except if it is nullified): */
1896 cpu->delay_slot = TO_BE_DELAYED;
1897 if (x || !(ic->arg[1] & 2))
1898 ic[1].f(cpu, ic+1);
1899 cpu->n_translated_instrs ++;
1900
1901 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1902 /* Note: Must be non-delayed when jumping to the new pc: */
1903 cpu->delay_slot = NOT_DELAYED;
1904 if (x) {
1905 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1906 MIPS_INSTR_ALIGNMENT_SHIFT);
1907 cpu->pc = old_pc + (int32_t)ic->arg[2];
1908 quick_pc_to_pointers(cpu);
1909 } else
1910 cpu->cd.mips.next_ic ++;
1911 } else
1912 cpu->delay_slot = NOT_DELAYED;
1913 }
1914
1915
1916 /*
1917 * cop1_slow: Fallback to legacy cop1 code. (Slow, but it should work.)
1918 */
1919 X(cop1_slow)
1920 {
1921 COPROC_AVAILABILITY_CHECK(1);
1922
1923 coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);
1924 }
1925
1926
1927 /*
1928 * syscall, break: Synchronize the PC and cause an exception.
1929 */
1930 X(syscall)
1931 {
1932 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1933 / sizeof(struct mips_instr_call);
1934 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1935 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1936 mips_cpu_exception(cpu, EXCEPTION_SYS, 0, 0, 0, 0, 0, 0);
1937 }
1938 X(break)
1939 {
1940 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1941 / sizeof(struct mips_instr_call);
1942 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1943 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1944 mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1945 }
1946 X(reboot)
1947 {
1948 if (!cop0_availability_check(cpu, ic))
1949 return;
1950
1951 cpu->running = 0;
1952 debugger_n_steps_left_before_interaction = 0;
1953 cpu->cd.mips.next_ic = &nothing_call;
1954 }
1955
1956
1957 /*
1958 * promemul: PROM software emulation.
1959 */
1960 X(promemul)
1961 {
1962 /* Synchronize the PC and call the correct emulation layer: */
1963 MODE_int_t old_pc;
1964 int res, low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1965 / sizeof(struct mips_instr_call);
1966 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1967 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1968 old_pc = cpu->pc;
1969
1970 switch (cpu->machine->machine_type) {
1971 case MACHINE_PMAX:
1972 res = decstation_prom_emul(cpu);
1973 break;
1974 case MACHINE_PS2:
1975 res = playstation2_sifbios_emul(cpu);
1976 break;
1977 case MACHINE_ARC:
1978 case MACHINE_SGI:
1979 res = arcbios_emul(cpu);
1980 break;
1981 case MACHINE_EVBMIPS:
1982 res = yamon_emul(cpu);
1983 break;
1984 default:fatal("TODO: Unimplemented machine type for PROM magic trap\n");
1985 exit(1);
1986 }
1987
1988 if (res) {
1989 /* Return from the PROM call: */
1990 cpu->pc = (MODE_int_t)cpu->cd.mips.gpr[MIPS_GPR_RA];
1991 cpu->delay_slot = NOT_DELAYED;
1992
1993 if (cpu->machine->show_trace_tree)
1994 cpu_functioncall_trace_return(cpu);
1995 } else {
1996 /* The PROM call blocks. */
1997 cpu->n_translated_instrs += 10;
1998 cpu->pc = old_pc;
1999 }
2000
2001 quick_pc_to_pointers(cpu);
2002 }
2003
2004
2005 /*
2006 * tlbw: TLB write indexed and random
2007 *
2008 * arg[0] = 1 for random, 0 for indexed
2009 * arg[2] = relative addr of this instruction within the page
2010 */
2011 X(tlbw)
2012 {
2013 if (!cop0_availability_check(cpu, ic))
2014 return;
2015
2016 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2017 cpu->pc |= ic->arg[2];
2018 coproc_tlbwri(cpu, ic->arg[0]);
2019 }
2020
2021
2022 /*
2023 * tlbp: TLB probe
2024 * tlbr: TLB read
2025 *
2026 * arg[2] = relative addr of this instruction within the page
2027 */
2028 X(tlbp)
2029 {
2030 if (!cop0_availability_check(cpu, ic))
2031 return;
2032
2033 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2034 cpu->pc |= ic->arg[2];
2035 coproc_tlbpr(cpu, 0);
2036 }
2037 X(tlbr)
2038 {
2039 if (!cop0_availability_check(cpu, ic))
2040 return;
2041
2042 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2043 cpu->pc |= ic->arg[2];
2044 coproc_tlbpr(cpu, 1);
2045 }
2046
2047
2048 /*
2049 * rfe: Return from exception handler (R2000/R3000)
2050 */
2051 X(rfe)
2052 {
2053 if (!cop0_availability_check(cpu, ic))
2054 return;
2055
2056 /* Just rotate the interrupt/user bits: */
2057 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
2058 (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
2059 ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
2060
2061 /*
2062 * Note: no pc to pointers conversion is necessary here. Usually the
2063 * rfe instruction resides in the delay slot of a jr k0/k1, and
2064 * it is up to that instruction to do the pointer conversion.
2065 */
2066 }
2067
2068
2069 /*
2070 * eret: Return from exception handler (non-R3000 style)
2071 */
2072 X(eret)
2073 {
2074 if (!cop0_availability_check(cpu, ic))
2075 return;
2076
2077 if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
2078 cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
2079 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
2080 } else {
2081 cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
2082 cpu->delay_slot = 0;
2083 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
2084 }
2085
2086 quick_pc_to_pointers(cpu);
2087
2088 cpu->cd.mips.rmw = 0; /* the "LL bit" */
2089 }
2090
2091
2092 /*
2093 * deret: Return from debug (EJTAG) handler
2094 */
2095 X(deret)
2096 {
2097 if (!cop0_availability_check(cpu, ic))
2098 return;
2099
2100 /*
2101 * According to the MIPS64 manual, deret loads PC from the DEPC cop0
2102 * register, and jumps there immediately. No delay slot.
2103 *
2104 * TODO: This instruction is only available if the processor is in
2105 * debug mode. (What does that mean?)
2106 *
2107 * TODO: This instruction is undefined in a delay slot.
2108 */
2109
2110 cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_DEPC];
2111 cpu->delay_slot = 0;
2112 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
2113 quick_pc_to_pointers(cpu);
2114 }
2115
2116
2117 /*
2118 * idle: Called from the implementation of wait, or netbsd_pmax_idle.
2119 */
2120 X(idle)
2121 {
2122 /*
2123 * If there is an interrupt, then just return. Otherwise
2124 * re-run the wait instruction (after a delay).
2125 */
2126 uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
2127 uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
2128
2129 if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
2130 if (status & (STATUS_EXL | STATUS_ERL))
2131 status &= ~STATUS_IE;
2132 }
2133
2134 /* Ugly R5900 special case: (TODO: move this?) */
2135 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
2136 !(status & R5900_STATUS_EIE))
2137 status &= ~STATUS_IE;
2138 if (status & STATUS_IE && (status & cause & STATUS_IM_MASK))
2139 return;
2140
2141 cpu->cd.mips.next_ic = ic;
2142 cpu->is_halted = 1;
2143 cpu->has_been_idling = 1;
2144
2145 /*
2146 * There was no interrupt. Go to sleep.
2147 *
2148 * TODO:
2149 *
2150 * Think about how to actually implement this usleep stuff,
2151 * in an SMP and/or timing accurate environment.
2152 */
2153
2154 if (cpu->machine->ncpus == 1) {
2155 static int x = 0;
2156 if ((++x) == 600) {
2157 usleep(10);
2158 x = 0;
2159 }
2160 cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
2161 }
2162 }
2163
2164
2165 /*
2166 * wait: Wait for external interrupt.
2167 */
2168 X(wait)
2169 {
2170 if (!cop0_availability_check(cpu, ic))
2171 return;
2172
2173 instr(idle)(cpu, ic);
2174 }
2175
2176
2177 /*
2178 * rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
2179 *
2180 * arg[0] = ptr to rt (destination register)
2181 */
2182 X(rdhwr_cpunum)
2183 {
2184 reg(ic->arg[0]) = cpu->cpu_id;
2185 }
2186
2187
2188 #include "tmp_mips_loadstore.c"
2189
2190
2191 /*
2192 * Load linked / store conditional:
2193 *
2194 * A Load-linked instruction initiates a RMW (read-modify-write) sequence.
2195 * COP0_LLADDR is updated for diagnostic purposes, except for CPUs in the
2196 * R10000 family.
2197 *
2198 * A Store-conditional instruction ends the sequence.
2199 *
2200 * arg[0] = ptr to rt
2201 * arg[1] = ptr to rs
2202 * arg[2] = int32_t imm
2203 */
2204 X(ll)
2205 {
2206 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2207 int low_pc;
2208 uint8_t word[sizeof(uint32_t)];
2209
2210 /* Synch. PC and load using slow memory_rw(): */
2211 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2212 / sizeof(struct mips_instr_call);
2213 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2214 << MIPS_INSTR_ALIGNMENT_SHIFT);
2215 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2216
2217 if (addr & (sizeof(word)-1)) {
2218 fatal("TODO: load linked unaligned access: exception\n");
2219 exit(1);
2220 }
2221
2222 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2223 sizeof(word), MEM_READ, CACHE_DATA)) {
2224 /* An exception occurred. */
2225 return;
2226 }
2227
2228 cpu->cd.mips.rmw = 1;
2229 cpu->cd.mips.rmw_addr = addr;
2230 cpu->cd.mips.rmw_len = sizeof(word);
2231 if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2232 cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2233 (addr >> 4) & 0xffffffffULL;
2234
2235 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2236 reg(ic->arg[0]) = (int32_t) (word[0] + (word[1] << 8)
2237 + (word[2] << 16) + (word[3] << 24));
2238 else
2239 reg(ic->arg[0]) = (int32_t) (word[3] + (word[2] << 8)
2240 + (word[1] << 16) + (word[0] << 24));
2241 }
2242 X(lld)
2243 {
2244 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2245 int low_pc;
2246 uint8_t word[sizeof(uint64_t)];
2247
2248 /* Synch. PC and load using slow memory_rw(): */
2249 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2250 / sizeof(struct mips_instr_call);
2251 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2252 << MIPS_INSTR_ALIGNMENT_SHIFT);
2253 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2254
2255 if (addr & (sizeof(word)-1)) {
2256 fatal("TODO: load linked unaligned access: exception\n");
2257 exit(1);
2258 }
2259
2260 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2261 sizeof(word), MEM_READ, CACHE_DATA)) {
2262 /* An exception occurred. */
2263 return;
2264 }
2265
2266 cpu->cd.mips.rmw = 1;
2267 cpu->cd.mips.rmw_addr = addr;
2268 cpu->cd.mips.rmw_len = sizeof(word);
2269 if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2270 cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2271 (addr >> 4) & 0xffffffffULL;
2272
2273 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2274 reg(ic->arg[0]) = word[0] + (word[1] << 8)
2275 + (word[2] << 16) + ((uint64_t)word[3] << 24) +
2276 + ((uint64_t)word[4] << 32) + ((uint64_t)word[5] << 40)
2277 + ((uint64_t)word[6] << 48) + ((uint64_t)word[7] << 56);
2278 else
2279 reg(ic->arg[0]) = word[7] + (word[6] << 8)
2280 + (word[5] << 16) + ((uint64_t)word[4] << 24) +
2281 + ((uint64_t)word[3] << 32) + ((uint64_t)word[2] << 40)
2282 + ((uint64_t)word[1] << 48) + ((uint64_t)word[0] << 56);
2283 }
2284 X(sc)
2285 {
2286 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2287 uint64_t r = reg(ic->arg[0]);
2288 int low_pc, i;
2289 uint8_t word[sizeof(uint32_t)];
2290
2291 /* Synch. PC and store using slow memory_rw(): */
2292 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2293 / sizeof(struct mips_instr_call);
2294 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2295 << MIPS_INSTR_ALIGNMENT_SHIFT);
2296 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2297
2298 if (addr & (sizeof(word)-1)) {
2299 fatal("TODO: sc unaligned access: exception\n");
2300 exit(1);
2301 }
2302
2303 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2304 word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2305 } else {
2306 word[3]=r; word[2]=r>>8; word[1]=r>>16; word[0]=r>>24;
2307 }
2308
2309 /* If rmw is 0, then the store failed. (This cache-line was written
2310 to by someone else.) */
2311 if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2312 || cpu->cd.mips.rmw_len != sizeof(word)) {
2313 reg(ic->arg[0]) = 0;
2314 cpu->cd.mips.rmw = 0;
2315 return;
2316 }
2317
2318 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2319 sizeof(word), MEM_WRITE, CACHE_DATA)) {
2320 /* An exception occurred. */
2321 return;
2322 }
2323
2324 /* We succeeded. Let's invalidate everybody else's store to this
2325 cache line: */
2326 for (i=0; i<cpu->machine->ncpus; i++) {
2327 if (cpu->machine->cpus[i]->cd.mips.rmw) {
2328 uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2329 cd.mips.rmw_addr;
2330 uint64_t mask = ~(cpu->machine->cpus[i]->
2331 cd.mips.cache_linesize[CACHE_DATA] - 1);
2332 xaddr &= mask;
2333 yaddr &= mask;
2334 if (xaddr == yaddr)
2335 cpu->machine->cpus[i]->cd.mips.rmw = 0;
2336 }
2337 }
2338
2339 reg(ic->arg[0]) = 1;
2340 cpu->cd.mips.rmw = 0;
2341 }
2342 X(scd)
2343 {
2344 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2345 uint64_t r = reg(ic->arg[0]);
2346 int low_pc, i;
2347 uint8_t word[sizeof(uint64_t)];
2348
2349 /* Synch. PC and store using slow memory_rw(): */
2350 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2351 / sizeof(struct mips_instr_call);
2352 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2353 << MIPS_INSTR_ALIGNMENT_SHIFT);
2354 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2355
2356 if (addr & (sizeof(word)-1)) {
2357 fatal("TODO: sc unaligned access: exception\n");
2358 exit(1);
2359 }
2360
2361 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2362 word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2363 word[4]=r>>32; word[5]=r>>40; word[6]=r>>48; word[7]=r>>56;
2364 } else {
2365 word[7]=r; word[6]=r>>8; word[5]=r>>16; word[4]=r>>24;
2366 word[3]=r>>32; word[2]=r>>40; word[1]=r>>48; word[0]=r>>56;
2367 }
2368
2369 /* If rmw is 0, then the store failed. (This cache-line was written
2370 to by someone else.) */
2371 if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2372 || cpu->cd.mips.rmw_len != sizeof(word)) {
2373 reg(ic->arg[0]) = 0;
2374 cpu->cd.mips.rmw = 0;
2375 return;
2376 }
2377
2378 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2379 sizeof(word), MEM_WRITE, CACHE_DATA)) {
2380 /* An exception occurred. */
2381 return;
2382 }
2383
2384 /* We succeeded. Let's invalidate everybody else's store to this
2385 cache line: */
2386 for (i=0; i<cpu->machine->ncpus; i++) {
2387 if (cpu->machine->cpus[i]->cd.mips.rmw) {
2388 uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2389 cd.mips.rmw_addr;
2390 uint64_t mask = ~(cpu->machine->cpus[i]->
2391 cd.mips.cache_linesize[CACHE_DATA] - 1);
2392 xaddr &= mask;
2393 yaddr &= mask;
2394 if (xaddr == yaddr)
2395 cpu->machine->cpus[i]->cd.mips.rmw = 0;
2396 }
2397 }
2398
2399 reg(ic->arg[0]) = 1;
2400 cpu->cd.mips.rmw = 0;
2401 }
2402
2403
2404 /*
2405 * lwc1, swc1: Coprocessor 1 load/store (32-bit)
2406 * ldc1, sdc1: Coprocessor 1 load/store (64-bit)
2407 *
2408 * arg[0] = ptr to coprocessor register
2409 * arg[1] = ptr to rs (base pointer register)
2410 * arg[2] = int32_t imm
2411 */
2412 X(lwc1)
2413 {
2414 COPROC_AVAILABILITY_CHECK(1);
2415
2416 #ifdef MODE32
2417 mips32_loadstore
2418 #else
2419 mips_loadstore
2420 #endif
2421 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 2 * 2 + 1]
2422 (cpu, ic);
2423 }
2424 X(swc1)
2425 {
2426 COPROC_AVAILABILITY_CHECK(1);
2427
2428 #ifdef MODE32
2429 mips32_loadstore
2430 #else
2431 mips_loadstore
2432 #endif
2433 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 2 * 2]
2434 (cpu, ic);
2435 }
2436 X(ldc1)
2437 {
2438 int use_fp_pairs =
2439 !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2440 uint64_t fpr, *backup_ptr;
2441
2442 COPROC_AVAILABILITY_CHECK(1);
2443
2444 backup_ptr = (uint64_t *) ic->arg[0];
2445 ic->arg[0] = (size_t) &fpr;
2446
2447 #ifdef MODE32
2448 mips32_loadstore
2449 #else
2450 mips_loadstore
2451 #endif
2452 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 3 * 2 + 1]
2453 (cpu, ic);
2454
2455 if (use_fp_pairs) {
2456 backup_ptr[0] = (int64_t)(int32_t) fpr;
2457 backup_ptr[1] = (int64_t)(int32_t) (fpr >> 32);
2458 } else {
2459 *backup_ptr = fpr;
2460 }
2461
2462 ic->arg[0] = (size_t) backup_ptr;
2463 }
2464 X(sdc1)
2465 {
2466 int use_fp_pairs =
2467 !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2468 uint64_t fpr, *backup_ptr;
2469
2470 COPROC_AVAILABILITY_CHECK(1);
2471
2472 backup_ptr = (uint64_t *) ic->arg[0];
2473 ic->arg[0] = (size_t) &fpr;
2474
2475 if (use_fp_pairs) {
2476 uint32_t lo = backup_ptr[0];
2477 uint32_t hi = backup_ptr[1];
2478 fpr = (((uint64_t)hi) << 32) | lo;
2479 } else {
2480 fpr = *backup_ptr;
2481 }
2482
2483 #ifdef MODE32
2484 mips32_loadstore
2485 #else
2486 mips_loadstore
2487 #endif
2488 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 3 * 2]
2489 (cpu, ic);
2490
2491 ic->arg[0] = (size_t) backup_ptr;
2492 }
2493
2494
2495 /*
2496 * Unaligned loads/stores:
2497 *
2498 * arg[0] = ptr to rt
2499 * arg[1] = ptr to rs
2500 * arg[2] = int32_t imm
2501 */
2502 X(lwl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 0); }
2503 X(lwr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 0); }
2504 X(ldl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 0); }
2505 X(ldr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 0); }
2506 X(swl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 1); }
2507 X(swr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 1); }
2508 X(sdl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 1); }
2509 X(sdr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 1); }
2510
2511
2512 /*
2513 * di, ei: R5900 interrupt enable/disable.
2514 *
2515 * TODO: check the R5900_STATUS_EDI bit in the status register. If it is
2516 * cleared, and we are not running in kernel mode, then both the EI and DI
2517 * instructions should be treated as NOPs!
2518 */
2519 X(di_r5900)
2520 {
2521 if (!cop0_availability_check(cpu, ic))
2522 return;
2523
2524 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2525 }
2526 X(ei_r5900)
2527 {
2528 if (!cop0_availability_check(cpu, ic))
2529 return;
2530
2531 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2532 }
2533
2534
2535 /*****************************************************************************/
2536
2537
2538 /*
2539 * sw_loop:
2540 *
2541 * s: addiu rX,rX,4 rX = arg[0] and arg[1]
2542 * bne rY,rX,s (or rX,rY,s) rt=arg[1], rs=arg[0]
2543 * sw rZ,-4(rX) rt=arg[0], rs=arg[1]
2544 */
2545 X(sw_loop)
2546 {
2547 MODE_uint_t rX = reg(ic->arg[0]), rZ = reg(ic[2].arg[0]);
2548 uint64_t *rYp = (uint64_t *) ic[1].arg[0];
2549 MODE_uint_t rY, bytes_to_write;
2550 unsigned char *page;
2551 int partial = 0;
2552
2553 page = cpu->cd.mips.host_store[rX >> 12];
2554
2555 /* Fallback: */
2556 if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {
2557 instr(addiu)(cpu, ic);
2558 return;
2559 }
2560
2561 if (rYp == (uint64_t *) ic->arg[0])
2562 rYp = (uint64_t *) ic[1].arg[1];
2563
2564 rY = reg(rYp);
2565
2566 bytes_to_write = rY - rX;
2567 if ((rX & 0xfff) + bytes_to_write > 0x1000) {
2568 bytes_to_write = 0x1000 - (rX & 0xfff);
2569 partial = 1;
2570 }
2571
2572 /* printf("rX = %08x\n", (int)rX);
2573 printf("rY = %08x\n", (int)rY);
2574 printf("rZ = %08x\n", (int)rZ);
2575 printf("%i bytes\n", (int)bytes_to_write); */
2576
2577 memset(page + (rX & 0xfff), 0, bytes_to_write);
2578
2579 reg(ic->arg[0]) = rX + bytes_to_write;
2580
2581 cpu->n_translated_instrs += bytes_to_write / 4 * 3 - 1;
2582 cpu->cd.mips.next_ic = partial?
2583 (struct mips_instr_call *) &ic[0] :
2584 (struct mips_instr_call *) &ic[3];
2585 }
2586
2587
2588 #ifdef MODE32
2589 /*
2590 * multi_sw_2, _3, _4:
2591 *
2592 * sw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2]
2593 */
2594 X(multi_sw_2_le)
2595 {
2596 uint32_t *page;
2597 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2598 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2599 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2600 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2601
2602 page = (uint32_t *) cpu->cd.mips.host_store[index0];
2603
2604 /* Fallback: */
2605 if (cpu->delay_slot ||
2606 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2607 index0 != index1) {
2608 /* Normal safe sw: */
2609 mips32_loadstore[8 + 2 * 2](cpu, ic);
2610 return;
2611 }
2612
2613 addr0 = (addr0 >> 2) & 0x3ff;
2614 addr1 = (addr1 >> 2) & 0x3ff;
2615
2616 r1 = reg(ic[0].arg[0]);
2617 r2 = reg(ic[1].arg[0]);
2618
2619 r1 = LE32_TO_HOST(r1);
2620 r2 = LE32_TO_HOST(r2);
2621
2622 page[addr0] = r1;
2623 page[addr1] = r2;
2624
2625 cpu->n_translated_instrs ++;
2626 cpu->cd.mips.next_ic ++;
2627 }
2628 X(multi_sw_2_be)
2629 {
2630 uint32_t *page;
2631 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2632 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2633 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2634 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2635
2636 page = (uint32_t *) cpu->cd.mips.host_store[index0];
2637
2638 /* Fallback: */
2639 if (cpu->delay_slot ||
2640 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2641 index0 != index1) {
2642 /* Normal safe sw: */
2643 mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2644 return;
2645 }
2646
2647 addr0 = (addr0 >> 2) & 0x3ff;
2648 addr1 = (addr1 >> 2) & 0x3ff;
2649
2650 r1 = reg(ic[0].arg[0]);
2651 r2 = reg(ic[1].arg[0]);
2652
2653 r1 = BE32_TO_HOST(r1);
2654 r2 = BE32_TO_HOST(r2);
2655
2656 page[addr0] = r1;
2657 page[addr1] = r2;
2658
2659 cpu->n_translated_instrs ++;
2660 cpu->cd.mips.next_ic ++;
2661 }
2662 X(multi_sw_3_le)
2663 {
2664 uint32_t *page;
2665 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2666 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2667 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2668 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2669 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2670 index2 = addr2 >> 12;
2671
2672 page = (uint32_t *) cpu->cd.mips.host_store[index0];
2673
2674 /* Fallback: */
2675 if (cpu->delay_slot ||
2676 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2677 (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2678 /* Normal safe sw: */
2679 mips32_loadstore[8 + 2 * 2](cpu, ic);
2680 return;
2681 }
2682
2683 addr0 = (addr0 >> 2) & 0x3ff;
2684 addr1 = (addr1 >> 2) & 0x3ff;
2685 addr2 = (addr2 >> 2) & 0x3ff;
2686
2687 /* printf("addr0=%x 1=%x 2=%x\n",
2688 (int)addr0, (int)addr1, (int)addr2); */
2689
2690 r1 = reg(ic[0].arg[0]);
2691 r2 = reg(ic[1].arg[0]);
2692 r3 = reg(ic[2].arg[0]);
2693
2694 r1 = LE32_TO_HOST(r1);
2695 r2 = LE32_TO_HOST(r2);
2696 r3 = LE32_TO_HOST(r3);
2697
2698 page[addr0] = r1;
2699 page[addr1] = r2;
2700 page[addr2] = r3;
2701
2702 cpu->n_translated_instrs += 2;
2703 cpu->cd.mips.next_ic += 2;
2704 }
2705 X(multi_sw_3_be)
2706 {
2707 uint32_t *page;
2708 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2709 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2710 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2711 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2712 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2713 index2 = addr2 >> 12;
2714
2715 page = (uint32_t *) cpu->cd.mips.host_store[index0];
2716
2717 /* Fallback: */
2718 if (cpu->delay_slot ||
2719 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2720 (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2721 /* Normal safe sw: */
2722 mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2723 return;
2724 }
2725
2726 addr0 = (addr0 >> 2) & 0x3ff;
2727 addr1 = (addr1 >> 2) & 0x3ff;
2728 addr2 = (addr2 >> 2) & 0x3ff;
2729
2730 /* printf("addr0=%x 1=%x 2=%x\n",
2731 (int)addr0, (int)addr1, (int)addr2); */
2732
2733 r1 = reg(ic[0].arg[0]);
2734 r2 = reg(ic[1].arg[0]);
2735 r3 = reg(ic[2].arg[0]);
2736
2737 r1 = BE32_TO_HOST(r1);
2738 r2 = BE32_TO_HOST(r2);
2739 r3 = BE32_TO_HOST(r3);
2740
2741 page[addr0] = r1;
2742 page[addr1] = r2;
2743 page[addr2] = r3;
2744
2745 cpu->n_translated_instrs += 2;
2746 cpu->cd.mips.next_ic += 2;
2747 }
2748 X(multi_sw_4_le)
2749 {
2750 uint32_t *page;
2751 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2752 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2753 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2754 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2755 MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2756 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2757 index2 = addr2 >> 12, index3 = addr3 >> 12;
2758
2759 page = (uint32_t *) cpu->cd.mips.host_store[index0];
2760
2761 /* Fallback: */
2762 if (cpu->delay_slot ||
2763 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2764 (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 ||
2765 index0 != index2 || index0 != index3) {
2766 /* Normal safe sw: */
2767 mips32_loadstore[8 + 2 * 2](cpu, ic);
2768 return;
2769 }
2770
2771 addr0 = (addr0 >> 2) & 0x3ff;
2772 addr1 = (addr1 >> 2) & 0x3ff;
2773 addr2 = (addr2 >> 2) & 0x3ff;
2774 addr3 = (addr3 >> 2) & 0x3ff;
2775
2776 r1 = reg(ic[0].arg[0]);
2777 r2 = reg(ic[1].arg[0]);
2778 r3 = reg(ic[2].arg[0]);
2779 r4 = reg(ic[3].arg[0]);
2780
2781 r1 = LE32_TO_HOST(r1);
2782 r2 = LE32_TO_HOST(r2);
2783 r3 = LE32_TO_HOST(r3);
2784 r4 = LE32_TO_HOST(r4);
2785
2786 page[addr0] = r1;
2787 page[addr1] = r2;
2788 page[addr2] = r3;
2789 page[addr3] = r4;
2790
2791 cpu->n_translated_instrs += 3;
2792 cpu->cd.mips.next_ic += 3;
2793 }
2794 X(multi_sw_4_be)
2795 {
2796 uint32_t *page;
2797 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2798 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2799 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2800 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2801 MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2802 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2803 index2 = addr2 >> 12, index3 = addr3 >> 12;
2804
2805 page = (uint32_t *) cpu->cd.mips.host_store[index0];
2806
2807 /* Fallback: */
2808 if (cpu->delay_slot ||
2809 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2810 (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 ||
2811 index0 != index2 || index0 != index3) {
2812 /* Normal safe sw: */
2813 mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2814 return;
2815 }
2816
2817 addr0 = (addr0 >> 2) & 0x3ff;
2818 addr1 = (addr1 >> 2) & 0x3ff;
2819 addr2 = (addr2 >> 2) & 0x3ff;
2820 addr3 = (addr3 >> 2) & 0x3ff;
2821
2822 r1 = reg(ic[0].arg[0]);
2823 r2 = reg(ic[1].arg[0]);
2824 r3 = reg(ic[2].arg[0]);
2825 r4 = reg(ic[3].arg[0]);
2826
2827 r1 = BE32_TO_HOST(r1);
2828 r2 = BE32_TO_HOST(r2);
2829 r3 = BE32_TO_HOST(r3);
2830 r4 = BE32_TO_HOST(r4);
2831
2832 page[addr0] = r1;
2833 page[addr1] = r2;
2834 page[addr2] = r3;
2835 page[addr3] = r4;
2836
2837 cpu->n_translated_instrs += 3;
2838 cpu->cd.mips.next_ic += 3;
2839 }
2840 #endif
2841
2842
2843 #ifdef MODE32
2844 /*
2845 * multi_lw_2, _3, _4:
2846 *
2847 * lw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2]
2848 */
2849 X(multi_lw_2_le)
2850 {
2851 uint32_t *page;
2852 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2853 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2854 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2855 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2856
2857 page = (uint32_t *) cpu->cd.mips.host_load[index0];
2858
2859 /* Fallback: */
2860 if (cpu->delay_slot ||
2861 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2862 index0 != index1) {
2863 /* Normal safe lw: */
2864 mips32_loadstore[2 * 2 + 1](cpu, ic);
2865 return;
2866 }
2867
2868 addr0 = (addr0 >> 2) & 0x3ff;
2869 addr1 = (addr1 >> 2) & 0x3ff;
2870
2871 r1 = page[addr0];
2872 r2 = page[addr1];
2873
2874 r1 = LE32_TO_HOST(r1);
2875 r2 = LE32_TO_HOST(r2);
2876
2877 reg(ic[0].arg[0]) = r1;
2878 reg(ic[1].arg[0]) = r2;
2879
2880 cpu->n_translated_instrs ++;
2881 cpu->cd.mips.next_ic ++;
2882 }
2883 X(multi_lw_2_be)
2884 {
2885 uint32_t *page;
2886 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2887 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2888 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2889 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2890
2891 page = (uint32_t *) cpu->cd.mips.host_load[index0];
2892
2893 /* Fallback: */
2894 if (cpu->delay_slot ||
2895 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2896 index0 != index1) {
2897 /* Normal safe lw: */
2898 mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2899 return;
2900 }
2901
2902 addr0 = (addr0 >> 2) & 0x3ff;
2903 addr1 = (addr1 >> 2) & 0x3ff;
2904
2905 r1 = page[addr0];
2906 r2 = page[addr1];
2907
2908 r1 = BE32_TO_HOST(r1);
2909 r2 = BE32_TO_HOST(r2);
2910
2911 reg(ic[0].arg[0]) = r1;
2912 reg(ic[1].arg[0]) = r2;
2913
2914 cpu->n_translated_instrs ++;
2915 cpu->cd.mips.next_ic ++;
2916 }
2917 X(multi_lw_3_le)
2918 {
2919 uint32_t *page;
2920 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2921 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2922 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2923 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2924 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2925 index2 = addr2 >> 12;
2926
2927 page = (uint32_t *) cpu->cd.mips.host_load[index0];
2928
2929 /* Fallback: */
2930 if (cpu->delay_slot ||
2931 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2932 (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2933 /* Normal safe lw: */
2934 mips32_loadstore[2 * 2 + 1](cpu, ic);
2935 return;
2936 }
2937
2938 addr0 = (addr0 >> 2) & 0x3ff;
2939 addr1 = (addr1 >> 2) & 0x3ff;
2940 addr2 = (addr2 >> 2) & 0x3ff;
2941
2942 /* printf("addr0=%x 1=%x 2=%x\n",
2943 (int)addr0, (int)addr1, (int)addr2); */
2944
2945 r1 = page[addr0];
2946 r2 = page[addr1];
2947 r3 = page[addr2];
2948
2949 r1 = LE32_TO_HOST(r1);
2950 r2 = LE32_TO_HOST(r2);
2951 r3 = LE32_TO_HOST(r3);
2952
2953 reg(ic[0].arg[0]) = r1;
2954 reg(ic[1].arg[0]) = r2;
2955 reg(ic[2].arg[0]) = r3;
2956
2957 cpu->n_translated_instrs += 2;
2958 cpu->cd.mips.next_ic += 2;
2959 }
2960 X(multi_lw_3_be)
2961 {
2962 uint32_t *page;
2963 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2964 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2965 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2966 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2967 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2968 index2 = addr2 >> 12;
2969
2970 page = (uint32_t *) cpu->cd.mips.host_load[index0];
2971
2972 /* Fallback: */
2973 if (cpu->delay_slot ||
2974 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2975 (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2976 /* Normal safe lw: */
2977 mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2978 return;
2979 }
2980
2981 addr0 = (addr0 >> 2) & 0x3ff;
2982 addr1 = (addr1 >> 2) & 0x3ff;
2983 addr2 = (addr2 >> 2) & 0x3ff;
2984
2985 /* printf("addr0=%x 1=%x 2=%x\n",
2986 (int)addr0, (int)addr1, (int)addr2); */
2987
2988 r1 = page[addr0];
2989 r2 = page[addr1];
2990 r3 = page[addr2];
2991
2992 r1 = BE32_TO_HOST(r1);
2993 r2 = BE32_TO_HOST(r2);
2994 r3 = BE32_TO_HOST(r3);
2995
2996 reg(ic[0].arg[0]) = r1;
2997 reg(ic[1].arg[0]) = r2;
2998 reg(ic[2].arg[0]) = r3;
2999
3000 cpu->n_translated_instrs += 2;
3001 cpu->cd.mips.next_ic += 2;
3002 }
3003 X(multi_lw_4_le)
3004 {
3005 uint32_t *page;
3006 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
3007 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
3008 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
3009 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
3010 MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
3011 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
3012 index2 = addr2 >> 12, index3 = addr3 >> 12;
3013
3014 page = (uint32_t *) cpu->cd.mips.host_load[index0];
3015
3016 /* Fallback: */
3017 if (cpu->delay_slot ||
3018 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
3019 (addr2 & 3) != 0 || (addr3 & 3) != 0 ||
3020 index0 != index1 || index0 != index2 || index0 != index3) {
3021 /* Normal safe lw: */
3022 mips32_loadstore[2 * 2 + 1](cpu, ic);
3023 return;
3024 }
3025
3026 addr0 = (addr0 >> 2) & 0x3ff;
3027 addr1 = (addr1 >> 2) & 0x3ff;
3028 addr2 = (addr2 >> 2) & 0x3ff;
3029 addr3 = (addr3 >> 2) & 0x3ff;
3030
3031 r1 = page[addr0];
3032 r2 = page[addr1];
3033 r3 = page[addr2];
3034 r4 = page[addr3];
3035
3036 r1 = LE32_TO_HOST(r1);
3037 r2 = LE32_TO_HOST(r2);
3038 r3 = LE32_TO_HOST(r3);
3039 r4 = LE32_TO_HOST(r4);
3040
3041 reg(ic[0].arg[0]) = r1;
3042 reg(ic[1].arg[0]) = r2;
3043 reg(ic[2].arg[0]) = r3;
3044 reg(ic[3].arg[0]) = r4;
3045
3046 cpu->n_translated_instrs += 3;
3047 cpu->cd.mips.next_ic += 3;
3048 }
3049 X(multi_lw_4_be)
3050 {
3051 uint32_t *page;
3052 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
3053 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
3054 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
3055 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
3056 MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
3057 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
3058 index2 = addr2 >> 12, index3 = addr3 >> 12;
3059
3060 page = (uint32_t *) cpu->cd.mips.host_load[index0];
3061
3062 /* Fallback: */
3063 if (cpu->delay_slot ||
3064 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
3065 (addr2 & 3) != 0 || (addr3 & 3) != 0 ||
3066 index0 != index1 || index0 != index2 || index0 != index3) {
3067 /* Normal safe lw: */
3068 mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
3069 return;
3070 }
3071
3072 addr0 = (addr0 >> 2) & 0x3ff;
3073 addr1 = (addr1 >> 2) & 0x3ff;
3074 addr2 = (addr2 >> 2) & 0x3ff;
3075 addr3 = (addr3 >> 2) & 0x3ff;
3076
3077 r1 = page[addr0];
3078 r2 = page[addr1];
3079 r3 = page[addr2];
3080 r4 = page[addr3];
3081
3082 r1 = BE32_TO_HOST(r1);
3083 r2 = BE32_TO_HOST(r2);
3084 r3 = BE32_TO_HOST(r3);
3085 r4 = BE32_TO_HOST(r4);
3086
3087 reg(ic[0].arg[0]) = r1;
3088 reg(ic[1].arg[0]) = r2;
3089 reg(ic[2].arg[0]) = r3;
3090 reg(ic[3].arg[0]) = r4;
3091
3092 cpu->n_translated_instrs += 3;
3093 cpu->cd.mips.next_ic += 3;
3094 }
3095 #endif
3096
3097
3098 /*
3099 * multi_addu_3:
3100 */
3101 X(multi_addu_3)
3102 {
3103 /* Fallback: */
3104 if (cpu->delay_slot) {
3105 instr(addu)(cpu, ic);
3106 return;
3107 }
3108
3109 reg(ic[0].arg[2]) = (int32_t)(reg(ic[0].arg[0]) + reg(ic[0].arg[1]));
3110 reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0]) + reg(ic[1].arg[1]));
3111 reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0]) + reg(ic[2].arg[1]));
3112 cpu->n_translated_instrs += 2;
3113 cpu->cd.mips.next_ic += 2;
3114 }
3115
3116
3117 /*
3118 * netbsd_r3k_picache_do_inv:
3119 *
3120 * ic[0] mtc0 rV,status
3121 * 1 nop
3122 * 2 nop
3123 * 3 s: addiu rX,rX,4
3124 * 4 bne rY,rX,s
3125 * 5 sb zr,-4(rX)
3126 * 6 nop
3127 * 7 nop
3128 * 8 mtc0 rT,status
3129 */
3130 X(netbsd_r3k_picache_do_inv)
3131 {
3132 MODE_uint_t rx = reg(ic[3].arg[0]), ry = reg(ic[4].arg[1]);
3133
3134 /* Fallback if the environment isn't exactly right: */
3135 if (!(reg(ic[0].arg[0]) & MIPS1_ISOL_CACHES) ||
3136 (rx & 3) || (ry & 3) || cpu->delay_slot) {
3137 instr(mtc0)(cpu, ic);
3138 return;
3139 }
3140
3141 reg(ic[3].arg[0]) = ry;
3142 cpu->n_translated_instrs += (ry - rx + 4) / 4 * 3 + 4;
3143
3144 /* Run the last mtc0 instruction: */
3145 cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[8];
3146 }
3147
3148
3149 #ifdef MODE32
3150 /*
3151 * netbsd_pmax_idle():
3152 *
3153 * s: lui rX, hi
3154 * lw rY, lo(rX)
3155 * nop
3156 * beq zr, rY, s
3157 * nop
3158 */
3159 X(netbsd_pmax_idle)
3160 {
3161 uint32_t addr, pageindex, i;
3162 int32_t *page;
3163
3164 reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3165
3166 addr = reg(ic[0].arg[0]) + (int32_t)ic[1].arg[2];
3167 pageindex = addr >> 12;
3168 i = (addr & 0xfff) >> 2;
3169 page = (int32_t *) cpu->cd.mips.host_load[pageindex];
3170
3171 /* Fallback: */
3172 if (cpu->delay_slot || page == NULL || page[i] != 0)
3173 return;
3174
3175 instr(idle)(cpu, ic);
3176 }
3177
3178
3179 /*
3180 * linux_pmax_idle():
3181 *
3182 * s: lui rX, hi
3183 * lw rX, lo(rX)
3184 * nop
3185 * bne zr, rX, ...
3186 * nop
3187 * lw rX, ofs(gp)
3188 * nop
3189 * beq zr, rX, s
3190 * nop
3191 */
3192 X(linux_pmax_idle)
3193 {
3194 uint32_t addr, addr2, pageindex, pageindex2, i, i2;
3195 int32_t *page, *page2;
3196
3197 reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3198
3199 addr = reg(ic[0].arg[0]) + (int32_t)ic[1].arg[2];
3200 pageindex = addr >> 12;
3201 i = (addr & 0xfff) >> 2;
3202 page = (int32_t *) cpu->cd.mips.host_load[pageindex];
3203
3204 addr2 = reg(ic[5].arg[1]) + (int32_t)ic[5].arg[2];
3205 pageindex2 = addr2 >> 12;
3206 i2 = (addr2 & 0xfff) >> 2;
3207 page2 = (int32_t *) cpu->cd.mips.host_load[pageindex2];
3208
3209 /* Fallback: */
3210 if (cpu->delay_slot || page == NULL || page[i] != 0 || page2[i2] != 0)
3211 return;
3212
3213 instr(idle)(cpu, ic);
3214 }
3215
3216
3217 /*
3218 * netbsd_strlen():
3219 *
3220 * lb rV,0(rX)
3221 * s: addiu rX,rX,1
3222 * bne zr,rV,s
3223 * nop
3224 */
3225 X(netbsd_strlen)
3226 {
3227 MODE_uint_t rx = reg(ic[0].arg[1]);
3228 MODE_int_t rv;
3229 signed char *page;
3230 uint32_t pageindex = rx >> 12;
3231 int i;
3232
3233 page = (signed char *) cpu->cd.mips.host_load[pageindex];
3234
3235 /* Fallback: */
3236 if (cpu->delay_slot || page == NULL) {
3237 /*
3238 * Normal lb: NOTE: It doesn't matter whether [1] or
3239 * [16+1] is called here, because endianness for 8-bit
3240 * loads is irrelevant. :-)
3241 */
3242 mips32_loadstore[1](cpu, ic);
3243 return;
3244 }
3245
3246 i = rx & 0xfff;
3247
3248 /*
3249 * TODO: This loop can be optimized further for optimal
3250 * performance on the host, e.g. by reading full words...
3251 */
3252 do {
3253 rv = page[i ++];
3254 } while (i < 0x1000 && rv != 0);
3255
3256 cpu->n_translated_instrs += (i - (rx & 0xfff)) * 4 - 1;
3257
3258 reg(ic[0].arg[1]) = (rx & ~0xfff) + i;
3259 reg(ic[2].arg[0]) = rv;
3260
3261 /* Done with the loop? Or continue on the next rx page? */
3262 if (rv == 0)
3263 cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[4];
3264 else
3265 cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[0];
3266 }
3267 #endif
3268
3269
3270 /*
3271 * addiu_bne_samepage_addiu:
3272 */
3273 X(addiu_bne_samepage_addiu)
3274 {
3275 MODE_uint_t rs, rt;
3276
3277 if (cpu->delay_slot) {
3278 instr(addiu)(cpu, ic);
3279 return;
3280 }
3281
3282 cpu->n_translated_instrs += 2;
3283 reg(ic[0].arg[1]) = (int32_t)
3284 ((int32_t)reg(ic[0].arg[0]) + (int32_t)ic[0].arg[2]);
3285 rs = reg(ic[1].arg[0]);
3286 rt = reg(ic[1].arg[1]);
3287 reg(ic[2].arg[1]) = (int32_t)
3288 ((int32_t)reg(ic[2].arg[0]) + (int32_t)ic[2].arg[2]);
3289 if (rs != rt)
3290 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic[1].arg[2];
3291 else
3292 cpu->cd.mips.next_ic += 2;
3293 }
3294
3295
3296 /*
3297 * xor_andi_sll:
3298 */
3299 X(xor_andi_sll)
3300 {
3301 /* Fallback: */
3302 if (cpu->delay_slot) {
3303 instr(xor)(cpu, ic);
3304 return;
3305 }
3306
3307 reg(ic[0].arg[2]) = reg(ic[0].arg[0]) ^ reg(ic[0].arg[1]);
3308 reg(ic[1].arg[1]) = reg(ic[1].arg[0]) & (uint32_t)ic[1].arg[2];
3309 reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0])<<(int32_t)ic[2].arg[1]);
3310
3311 cpu->n_translated_instrs += 2;
3312 cpu->cd.mips.next_ic += 2;
3313 }
3314
3315
3316 /*
3317 * andi_sll:
3318 */
3319 X(andi_sll)
3320 {
3321 /* Fallback: */
3322 if (cpu->delay_slot) {
3323 instr(andi)(cpu, ic);
3324 return;
3325 }
3326
3327 reg(ic[0].arg[1]) = reg(ic[0].arg[0]) & (uint32_t)ic[0].arg[2];
3328 reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0])<<(int32_t)ic[1].arg[1]);
3329
3330 cpu->n_translated_instrs ++;
3331 cpu->cd.mips.next_ic ++;
3332 }
3333
3334
3335 /*
3336 * lui_ori:
3337 */
3338 X(lui_ori)
3339 {
3340 /* Fallback: */
3341 if (cpu->delay_slot) {
3342 instr(set)(cpu, ic);
3343 return;
3344 }
3345
3346 reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3347 reg(ic[1].arg[1]) = reg(ic[1].arg[0]) | (uint32_t)ic[1].arg[2];
3348
3349 cpu->n_translated_instrs ++;
3350 cpu->cd.mips.next_ic ++;
3351 }
3352
3353
3354 /*
3355 * lui_addiu:
3356 */
3357 X(lui_addiu)
3358 {
3359 /* Fallback: */
3360 if (cpu->delay_slot) {
3361 instr(set)(cpu, ic);
3362 return;
3363 }
3364
3365 reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3366 reg(ic[1].arg[1]) = (int32_t)
3367 ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
3368
3369 cpu->n_translated_instrs ++;
3370 cpu->cd.mips.next_ic ++;
3371 }
3372
3373
3374 /*
3375 * b_samepage_addiu:
3376 *
3377 * Combination of branch within the same page, followed by addiu.
3378 */
3379 X(b_samepage_addiu)
3380 {
3381 reg(ic[1].arg[1]) = (int32_t)
3382 ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
3383 cpu->n_translated_instrs ++;
3384 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
3385 }
3386
3387
3388 /*
3389 * b_samepage_daddiu:
3390 *
3391 * Combination of branch within the same page, followed by daddiu.
3392 */
3393 X(b_samepage_daddiu)
3394 {
3395 *(uint64_t *)ic[1].arg[1] = *(uint64_t *)ic[1].arg[0] +
3396 (int32_t)ic[1].arg[2];
3397 cpu->n_translated_instrs ++;
3398 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
3399 }
3400
3401
3402 /*****************************************************************************/
3403
3404
3405 X(end_of_page)
3406 {
3407 /* Update the PC: (offset 0, but on the next page) */
3408 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
3409 MIPS_INSTR_ALIGNMENT_SHIFT);
3410 cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);
3411
3412 /* end_of_page doesn't count as an executed instruction: */
3413 cpu->n_translated_instrs --;
3414
3415 /*
3416 * Find the new physpage and update translation pointers.
3417 *
3418 * Note: This may cause an exception, if e.g. the new page is
3419 * not accessible.
3420 */
3421 quick_pc_to_pointers(cpu);
3422
3423 /* Simple jump to the next page (if we are lucky): */
3424 if (cpu->delay_slot == NOT_DELAYED)
3425 return;
3426
3427 /*
3428 * If we were in a delay slot, and we got an exception while doing
3429 * quick_pc_to_pointers, then return. The function which called
3430 * end_of_page should handle this case.
3431 */
3432 if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
3433 return;
3434
3435 /*
3436 * Tricky situation; the delay slot is on the next virtual page.
3437 * Calling to_be_translated will translate one instruction manually,
3438 * execute it, and then discard it.
3439 */
3440 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
3441
3442 instr(to_be_translated)(cpu, cpu->cd.mips.next_ic);
3443
3444 /* The instruction in the delay slot has now executed. */
3445 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
3446 cpu->delay_slot); */
3447
3448 /* Find the physpage etc of the instruction in the delay slot
3449 (or, if there was an exception, the exception handler): */
3450 quick_pc_to_pointers(cpu);
3451 }
3452
3453
3454 X(end_of_page2)
3455 {
3456 /* Synchronize PC on the _second_ instruction on the next page: */
3457 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
3458 / sizeof(struct mips_instr_call);
3459 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
3460 << MIPS_INSTR_ALIGNMENT_SHIFT);
3461 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
3462
3463 /* This doesn't count as an executed instruction. */
3464 cpu->n_translated_instrs --;
3465
3466 quick_pc_to_pointers(cpu);
3467
3468 if (cpu->delay_slot == NOT_DELAYED)
3469 return;
3470
3471 fatal("end_of_page2: fatal error, we're in a delay slot\n");
3472 exit(1);
3473 }
3474
3475
3476 /*****************************************************************************/
3477
3478
3479 /*
3480 * Combine: Memory fill loop (addiu, bne, sw)
3481 *
3482 * s: addiu rX,rX,4
3483 * bne rY,rX,s
3484 * sw rZ,-4(rX)
3485 */
3486 void COMBINE(sw_loop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3487 {
3488 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3489 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3490
3491 /* Only for 32-bit virtual address translation so far. */
3492 if (!cpu->is_32bit)
3493 return;
3494
3495 if (n_back < 2)
3496 return;
3497
3498 if (ic[-2].f == instr(addiu) && ic[-2].arg[0] == ic[-2].arg[1] &&
3499 (int32_t)ic[-2].arg[2] == 4 &&
3500 ic[-1].f == instr(bne_samepage) &&
3501 (ic[-1].arg[0] == ic[-2].arg[0] ||
3502 ic[-1].arg[1] == ic[-2].arg[0]) &&
3503 ic[-1].arg[0] != ic[-1].arg[1] &&
3504 ic[-1].arg[2] == (size_t) &ic[-2] &&
3505 ic[0].arg[0] != ic[0].arg[1] &&
3506 ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) {
3507 ic[-2].f = instr(sw_loop);
3508 }
3509 }
3510
3511
3512 /* Only for 32-bit virtual address translation so far. */
3513 #ifdef MODE32
3514 /*
3515 * Combine: Multiple SW in a row using the same base register
3516 *
3517 * sw r?,???(rX)
3518 * sw r?,???(rX)
3519 * sw r?,???(rX)
3520 * ...
3521 */
3522 void COMBINE(multi_sw)(struct cpu *cpu, struct mips_instr_call *ic,
3523 int low_addr)
3524 {
3525 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3526 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3527
3528 if (n_back < 3)
3529 return;
3530
3531 /* Convert a multi_sw_3 to a multi_sw_4: */
3532 if ((ic[-3].f == instr(multi_sw_3_be) ||
3533 ic[-3].f == instr(multi_sw_3_le)) &&
3534 ic[-3].arg[1] == ic[0].arg[1]) {
3535 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3536 ic[-3].f = instr(multi_sw_4_le);
3537 else
3538 ic[-3].f = instr(multi_sw_4_be);
3539 }
3540
3541 /* Convert a multi_sw_2 to a multi_sw_3: */
3542 if ((ic[-2].f == instr(multi_sw_2_be) ||
3543 ic[-2].f == instr(multi_sw_2_le)) &&
3544 ic[-2].arg[1] == ic[0].arg[1]) {
3545 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3546 ic[-2].f = instr(multi_sw_3_le);
3547 else
3548 ic[-2].f = instr(multi_sw_3_be);
3549 }
3550
3551 if (ic[-1].f == ic[0].f && ic[-1].arg[1] == ic[0].arg[1]) {
3552 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3553 ic[-1].f = instr(multi_sw_2_le);
3554 else
3555 ic[-1].f = instr(multi_sw_2_be);
3556 }
3557 }
3558 #endif
3559
3560
3561 /* Only for 32-bit virtual address translation so far. */
3562 #ifdef MODE32
3563 /*
3564 * Combine: Multiple LW in a row using the same base register
3565 *
3566 * lw r?,???(rX)
3567 * lw r?,???(rX)
3568 * lw r?,???(rX)
3569 * ...
3570 */
3571 void COMBINE(multi_lw)(struct cpu *cpu, struct mips_instr_call *ic,
3572 int low_addr)
3573 {
3574 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3575 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3576
3577 if (n_back < 3)
3578 return;
3579
3580 /* Convert a multi_lw_3 to a multi_lw_4: */
3581 if ((ic[-3].f == instr(multi_lw_3_be) ||
3582 ic[-3].f == instr(multi_lw_3_le)) &&
3583 ic[-3].arg[1] == ic[0].arg[1] &&
3584 ic[-1].arg[0] != ic[0].arg[1]) {
3585 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3586 ic[-3].f = instr(multi_lw_4_le);
3587 else
3588 ic[-3].f = instr(multi_lw_4_be);
3589 }
3590
3591 /* Convert a multi_lw_2 to a multi_lw_3: */
3592 if ((ic[-2].f == instr(multi_lw_2_be) ||
3593 ic[-2].f == instr(multi_lw_2_le)) &&
3594 ic[-2].arg[1] == ic[0].arg[1] &&
3595 ic[-1].arg[0] != ic[0].arg[1]) {
3596 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3597 ic[-2].f = instr(multi_lw_3_le);
3598 else
3599 ic[-2].f = instr(multi_lw_3_be);
3600 }
3601
3602 /* Note: Loads to the base register are not allowed in slot -1. */
3603 if (ic[-1].f == ic[0].f &&
3604 ic[-1].arg[1] == ic[0].arg[1] &&
3605 ic[-1].arg[0] != ic[0].arg[1]) {
3606 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3607 ic[-1].f = instr(multi_lw_2_le);
3608 else
3609 ic[-1].f = instr(multi_lw_2_be);
3610 }
3611 }
3612 #endif
3613
3614
3615 /*
3616 * Combine: NetBSD/pmax 3.0 R2000/R3000 physical cache invalidation loop
3617 *
3618 * Instruction cache loop:
3619 *
3620 * ic[-8] mtc0 rV,status
3621 * -7 nop
3622 * -6 nop
3623 * -5 s: addiu rX,rX,4
3624 * -4 bne rY,rX,s
3625 * -3 sb zr,-4(rX)
3626 * -2 nop
3627 * -1 nop
3628 * 0 mtc0 rT,status
3629 */
3630 void COMBINE(netbsd_r3k_cache_inv)(struct cpu *cpu,
3631 struct mips_instr_call *ic, int low_addr)
3632 {
3633 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3634 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3635
3636 if (n_back < 8)
3637 return;
3638
3639 if (ic[-8].f == instr(mtc0) && ic[-8].arg[1] == COP0_STATUS &&
3640 ic[-7].f == instr(nop) && ic[-6].f == instr(nop) &&
3641 ic[-5].f == instr(addiu) && ic[-5].arg[0] == ic[-5].arg[1] &&
3642 (int32_t)ic[-5].arg[2] == 4 && ic[-4].f == instr(bne_samepage) &&
3643 ic[-4].arg[0] == ic[-5].arg[0] && ic[-4].arg[0] != ic[-4].arg[1] &&
3644 ic[-4].arg[2] == (size_t) &ic[-5] &&
3645 ic[-3].arg[1] == ic[-5].arg[0] &&
3646 ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {
3647 ic[-8].f = instr(netbsd_r3k_picache_do_inv);
3648 }
3649 }
3650
3651
3652 /*
3653 * Combine: something ending with a nop.
3654 *
3655 * NetBSD's strlen core.
3656 * [Conditional] branch, followed by nop.
3657 * NetBSD/pmax' idle loop (and possibly others as well).
3658 * Linux/pmax' idle loop.
3659 */
3660 void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3661 {
3662 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3663 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3664
3665 if (n_back < 8)
3666 return;
3667
3668 #ifdef MODE32
3669 if (ic[-8].f == instr(set) &&
3670 ic[-7].f == mips32_loadstore[4 + 1] &&
3671 ic[-7].arg[0] == ic[-1].arg[0] &&
3672 ic[-7].arg[0] == ic[-3].arg[0] &&
3673 ic[-7].arg[0] == ic[-5].arg[0] &&
3674 ic[-7].arg[0] == ic[-7].arg[1] &&
3675 ic[-7].arg[0] == ic[-8].arg[0] &&
3676 ic[-6].f == instr(nop) &&
3677 ic[-5].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3678 ic[-5].f == instr(bne_samepage_nop) &&
3679 ic[-4].f == instr(nop) &&
3680 ic[-3].f == mips32_loadstore[4 + 1] &&
3681 ic[-2].f == instr(nop) &&
3682 ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3683 ic[-1].arg[2] == (size_t) &ic[-8] &&
3684 ic[-1].f == instr(beq_samepage)) {
3685 ic[-8].f = instr(linux_pmax_idle);
3686 return;
3687 }
3688
3689 if (ic[-4].f == instr(set) &&
3690 ic[-3].f == mips32_loadstore[4 + 1] &&
3691 ic[-3].arg[0] == ic[-1].arg[0] &&
3692 ic[-3].arg[1] == ic[-4].arg[0] &&
3693 ic[-2].f == instr(nop) &&
3694 ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3695 ic[-1].arg[2] == (size_t) &ic[-4] &&
3696 ic[-1].f == instr(beq_samepage)) {
3697 ic[-4].f = instr(netbsd_pmax_idle);
3698 return;
3699 }
3700
3701 if ((ic[-3].f == mips32_loadstore[1] ||
3702 ic[-3].f == mips32_loadstore[16 + 1]) &&
3703 ic[-3].arg[2] == 0 &&
3704 ic[-3].arg[0] == ic[-1].arg[0] && ic[-3].arg[1] == ic[-2].arg[0] &&
3705 ic[-2].arg[0] == ic[-2].arg[1] && ic[-2].arg[2] == 1 &&
3706 ic[-2].f == instr(addiu) && ic[-1].arg[2] == (size_t) &ic[-3] &&
3707 ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3708 ic[-1].f == instr(bne_samepage)) {
3709 ic[-3].f = instr(netbsd_strlen);
3710 return;
3711 }
3712 #endif
3713
3714 if (ic[-1].f == instr(bne_samepage)) {
3715 ic[-1].f = instr(bne_samepage_nop);
3716 return;
3717 }
3718
3719 if (ic[-1].f == instr(beq_samepage)) {
3720 ic[-1].f = instr(beq_samepage_nop);
3721 return;
3722 }
3723
3724 /* TODO: other branches that are followed by nop should be here */
3725 }
3726
3727
3728 /*
3729 * Combine:
3730 *
3731 * xor + andi + sll
3732 * andi + sll
3733 */
3734 void COMBINE(sll)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3735 {
3736 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3737 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3738
3739 if (n_back < 2)
3740 return;
3741
3742 if (ic[-2].f == instr(xor) && ic[-1].f == instr(andi)) {
3743 ic[-2].f = instr(xor_andi_sll);
3744 return;
3745 }
3746
3747 if (ic[-1].f == instr(andi)) {
3748 ic[-1].f = instr(andi_sll);
3749 return;
3750 }
3751 }
3752
3753
3754 /*
3755 * lui + ori
3756 */
3757 void COMBINE(ori)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3758 {
3759 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3760 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3761
3762 if (n_back < 1)
3763 return;
3764
3765 if (ic[-1].f == instr(set)) {
3766 ic[-1].f = instr(lui_ori);
3767 return;
3768 }
3769 }
3770
3771
3772 /*
3773 * addu + addu + addu
3774 */
3775 void COMBINE(addu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3776 {
3777 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3778 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3779
3780 if (n_back < 4)
3781 return;
3782
3783 /* Avoid "overlapping" instruction combinations: */
3784 if (ic[-4].f == instr(multi_addu_3) ||
3785 ic[-3].f == instr(multi_addu_3))
3786 return;
3787
3788 if (ic[-2].f == instr(addu) && ic[-1].f == instr(addu)) {
3789 ic[-2].f = instr(multi_addu_3);
3790 return;
3791 }
3792 }
3793
3794
3795 /*
3796 * Combine:
3797 *
3798 * [Conditional] branch, followed by addiu.
3799 */
3800 void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3801 {
3802 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3803 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3804
3805 if (n_back < 2)
3806 return;
3807
3808 if (ic[-2].f == instr(addiu) &&
3809 ic[-1].f == instr(bne_samepage)) {
3810 ic[-2].f = instr(addiu_bne_samepage_addiu);
3811 return;
3812 }
3813
3814 if (ic[-1].f == instr(set)) {
3815 ic[-1].f = instr(lui_addiu);
3816 return;
3817 }
3818
3819 if (ic[-1].f == instr(b_samepage)) {
3820 ic[-1].f = instr(b_samepage_addiu);
3821 return;
3822 }
3823
3824 if (ic[-1].f == instr(beq_samepage)) {
3825 ic[-1].f = instr(beq_samepage_addiu);
3826 return;
3827 }
3828
3829 if (ic[-1].f == instr(bne_samepage)) {
3830 ic[-1].f = instr(bne_samepage_addiu);
3831 return;
3832 }
3833
3834 if (ic[-1].f == instr(jr_ra)) {
3835 ic[-1].f = instr(jr_ra_addiu);
3836 return;
3837 }
3838
3839 /* TODO: other branches that are followed by addiu should be here */
3840 }
3841
3842
3843 /*
3844 * Combine: [Conditional] branch, followed by daddiu.
3845 */
3846 void COMBINE(b_daddiu)(struct cpu *cpu, struct mips_instr_call *ic,
3847 int low_addr)
3848 {
3849 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3850 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3851
3852 if (n_back < 1)
3853 return;
3854
3855 if (ic[-1].f == instr(b_samepage)) {
3856 ic[-1].f = instr(b_samepage_daddiu);
3857 }
3858
3859 /* TODO: other branches that are followed by daddiu should be here */
3860 }
3861
3862
3863 /*****************************************************************************/
3864
3865
3866 /*
3867 * mips_instr_to_be_translated():
3868 *
3869 * Translate an instruction word into a mips_instr_call. ic is filled in with
3870 * valid data for the translated instruction, or a "nothing" instruction if
3871 * there was a translation failure. The newly translated instruction is then
3872 * executed.
3873 */
3874 X(to_be_translated)
3875 {
3876 uint64_t addr, low_pc;
3877 uint32_t iword, imm;
3878 unsigned char *page;
3879 unsigned char ib[4];
3880 int main_opcode, rt, rs, rd, sa, s6, x64 = 0, s10;
3881 int in_crosspage_delayslot = 0;
3882 void (*samepage_function)(struct cpu *, struct mips_instr_call *);
3883 int store, signedness, size;
3884
3885 /* Figure out the (virtual) address of the instruction: */
3886 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
3887 / sizeof(struct mips_instr_call);
3888
3889 /* Special case for branch with delayslot on the next page: */
3890 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
3891 /* fatal("[ delay-slot translation across page "
3892 "boundary ]\n"); */
3893 in_crosspage_delayslot = 1;
3894 }
3895
3896 addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)
3897 << MIPS_INSTR_ALIGNMENT_SHIFT);
3898 addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
3899 cpu->pc = (MODE_int_t)addr;
3900 addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
3901
3902 /* Read the instruction word from memory: */
3903 #ifdef MODE32
3904 page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
3905 #else
3906 {
3907 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
3908 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
3909 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
3910 uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
3911 uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
3912 uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
3913 DYNTRANS_L3N)) & mask3;
3914 struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.mips.l1_64[x1];
3915 struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
3916 page = l3->host_load[x3];
3917 }
3918 #endif
3919
3920 if (page != NULL) {
3921 /* fatal("TRANSLATION HIT!\n"); */
3922 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
3923 } else {
3924 /* fatal("TRANSLATION MISS!\n"); */
3925 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
3926 sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
3927 fatal("to_be_translated(): read failed: TODO\n");
3928 goto bad;
3929 }
3930 }
3931
3932 iword = *((uint32_t *)&ib[0]);
3933
3934 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3935 iword = LE32_TO_HOST(iword);
3936 else
3937 iword = BE32_TO_HOST(iword);
3938
3939
3940 #define DYNTRANS_TO_BE_TRANSLATED_HEAD
3941 #include "cpu_dyntrans.c"
3942 #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
3943
3944
3945 /*
3946 * Translate the instruction:
3947 *
3948 * NOTE: _NEVER_ allow writes to the zero register; all instructions
3949 * that use the zero register as their destination should be treated
3950 * as NOPs, except those that access memory (they should use the
3951 * scratch register instead).
3952 */
3953
3954 main_opcode = iword >> 26;
3955 rs = (iword >> 21) & 31;
3956 rt = (iword >> 16) & 31;
3957 rd = (iword >> 11) & 31;
3958 sa = (iword >> 6) & 31;
3959 imm = (int16_t)iword;
3960 s6 = iword & 63;
3961 s10 = (rs << 5) | sa;
3962
3963 switch (main_opcode) {
3964
3965 case HI6_SPECIAL:
3966 switch (s6) {
3967
3968 case SPECIAL_SLL:
3969 case SPECIAL_SLLV:
3970 case SPECIAL_SRL:
3971 case SPECIAL_SRLV:
3972 case SPECIAL_SRA:
3973 case SPECIAL_SRAV:
3974 case SPECIAL_DSRL:
3975 case SPECIAL_DSRLV:
3976 case SPECIAL_DSRL32:
3977 case SPECIAL_DSLL:
3978 case SPECIAL_DSLLV:
3979 case SPECIAL_DSLL32:
3980 case SPECIAL_DSRA:
3981 case SPECIAL_DSRAV:
3982 case SPECIAL_DSRA32:
3983 switch (s6) {
3984 case SPECIAL_SLL: ic->f = instr(sll); break;
3985 case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
3986 case SPECIAL_SRL: ic->f = instr(srl); break;
3987 case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
3988 case SPECIAL_SRA: ic->f = instr(sra); break;
3989 case SPECIAL_SRAV: ic->f = instr(srav); sa = -1; break;
3990 case SPECIAL_DSRL: ic->f = instr(dsrl); x64=1; break;
3991 case SPECIAL_DSRLV:ic->f = instr(dsrlv);
3992 x64 = 1; sa = -1; break;
3993 case SPECIAL_DSRL32:ic->f= instr(dsrl); x64=1;
3994 sa += 32; break;
3995 case SPECIAL_DSLL: ic->f = instr(dsll); x64=1; break;
3996 case SPECIAL_DSLLV:ic->f = instr(dsllv);
3997 x64 = 1; sa = -1; break;
3998 case SPECIAL_DSLL32:ic->f= instr(dsll); x64=1;
3999 sa += 32; break;
4000 case SPECIAL_DSRA: ic->f = instr(dsra); x64=1; break;
4001 case SPECIAL_DSRAV:ic->f = instr(dsrav);
4002 x64 = 1; sa = -1; break;
4003 case SPECIAL_DSRA32:ic->f = instr(dsra); x64=1;
4004 sa += 32; break;
4005 }
4006 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4007 if (sa >= 0)
4008 ic->arg[1] = sa;
4009 else
4010 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4011 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4012 if (rd == MIPS_GPR_ZERO)
4013 ic->f = instr(nop);
4014 if (ic->f == instr(sll))
4015 cpu->cd.mips.combination_check = COMBINE(sll);
4016 if (ic->f == instr(nop))
4017 cpu->cd.mips.combination_check = COMBINE(nop);
4018
4019 /* Special checks for MIPS32/64 revision 2 opcodes,
4020 such as rotation instructions: */
4021 if (sa >= 0 && rs != 0x00) {
4022 switch (rs) {
4023 /* TODO: [d]ror, etc. */
4024 default:goto bad;
4025 }
4026 }
4027 if (sa < 0 && (s10 & 0x1f) != 0) {
4028 switch (s10 & 0x1f) {
4029 /* TODO: [d]rorv, etc. */
4030 default:goto bad;
4031 }
4032 }
4033 break;
4034
4035 case SPECIAL_ADD:
4036 case SPECIAL_ADDU:
4037 case SPECIAL_SUB:
4038 case SPECIAL_SUBU:
4039 case SPECIAL_DADD:
4040 case SPECIAL_DADDU:
4041 case SPECIAL_DSUB:
4042 case SPECIAL_DSUBU:
4043 case SPECIAL_SLT:
4044 case SPECIAL_SLTU:
4045 case SPECIAL_AND:
4046 case SPECIAL_OR:
4047 case SPECIAL_XOR:
4048 case SPECIAL_NOR:
4049 case SPECIAL_MOVN:
4050 case SPECIAL_MOVZ:
4051 case SPECIAL_MFHI:
4052 case SPECIAL_MFLO:
4053 case SPECIAL_MTHI:
4054 case SPECIAL_MTLO:
4055 case SPECIAL_DIV:
4056 case SPECIAL_DIVU:
4057 case SPECIAL_DDIV:
4058 case SPECIAL_DDIVU:
4059 case SPECIAL_MULT:
4060 case SPECIAL_MULTU:
4061 case SPECIAL_DMULT:
4062 case SPECIAL_DMULTU:
4063 case SPECIAL_TGE:
4064 case SPECIAL_TGEU:
4065 case SPECIAL_TLT:
4066 case SPECIAL_TLTU:
4067 case SPECIAL_TEQ:
4068 case SPECIAL_TNE:
4069 switch (s6) {
4070 case SPECIAL_ADD: ic->f = instr(add); break;
4071 case SPECIAL_ADDU: ic->f = instr(addu); break;
4072 case SPECIAL_SUB: ic->f = instr(sub); break;
4073 case SPECIAL_SUBU: ic->f = instr(subu); break;
4074 case SPECIAL_DADD: ic->f = instr(dadd); x64=1; break;
4075 case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
4076 case SPECIAL_DSUB: ic->f = instr(dsub); x64=1; break;
4077 case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;
4078 case SPECIAL_SLT: ic->f = instr(slt); break;
4079 case SPECIAL_SLTU: ic->f = instr(sltu); break;
4080 case SPECIAL_AND: ic->f = instr(and); break;
4081 case SPECIAL_OR: ic->f = instr(or); break;
4082 case SPECIAL_XOR: ic->f = instr(xor); break;
4083 case SPECIAL_NOR: ic->f = instr(nor); break;
4084 case SPECIAL_MFHI: ic->f = instr(mov); break;
4085 case SPECIAL_MFLO: ic->f = instr(mov); break;
4086 case SPECIAL_MTHI: ic->f = instr(mov); break;
4087 case SPECIAL_MTLO: ic->f = instr(mov); break;
4088 case SPECIAL_DIV: ic->f = instr(div); break;
4089 case SPECIAL_DIVU: ic->f = instr(divu); break;
4090 case SPECIAL_DDIV: ic->f = instr(ddiv); x64=1; break;
4091 case SPECIAL_DDIVU: ic->f = instr(ddivu); x64=1; break;
4092 case SPECIAL_MULT : ic->f = instr(mult); break;
4093 case SPECIAL_MULTU: ic->f = instr(multu); break;
4094 case SPECIAL_DMULT: ic->f = instr(dmult); x64=1; break;
4095 case SPECIAL_DMULTU:ic->f = instr(dmultu); x64=1; break;
4096 case SPECIAL_TGE: ic->f = instr(tge); break;
4097 case SPECIAL_TGEU: ic->f = instr(tgeu); break;
4098 case SPECIAL_TLT: ic->f = instr(tlt); break;
4099 case SPECIAL_TLTU: ic->f = instr(tltu); break;
4100 case SPECIAL_TEQ: ic->f = instr(teq); break;
4101 case SPECIAL_TNE: ic->f = instr(tne); break;
4102 case SPECIAL_MOVN: ic->f = instr(movn); break;
4103 case SPECIAL_MOVZ: ic->f = instr(movz); break;
4104 }
4105 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4106 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4107 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4108 switch (s6) {
4109 case SPECIAL_MFHI:
4110 ic->arg[0] = (size_t)&cpu->cd.mips.hi;
4111 break;
4112 case SPECIAL_MFLO:
4113 ic->arg[0] = (size_t)&cpu->cd.mips.lo;
4114 break;
4115 case SPECIAL_MTHI:
4116 ic->arg[2] = (size_t)&cpu->cd.mips.hi;
4117 break;
4118 case SPECIAL_MTLO:
4119 ic->arg[2] = (size_t)&cpu->cd.mips.lo;
4120 break;
4121 }
4122 /* Special cases for rd: */
4123 switch (s6) {
4124 case SPECIAL_MTHI:
4125 case SPECIAL_MTLO:
4126 case SPECIAL_DIV:
4127 case SPECIAL_DIVU:
4128 case SPECIAL_DDIV:
4129 case SPECIAL_DDIVU:
4130 case SPECIAL_MULT:
4131 case SPECIAL_MULTU:
4132 case SPECIAL_DMULT:
4133 case SPECIAL_DMULTU:
4134 case SPECIAL_TGE:
4135 case SPECIAL_TGEU:
4136 case SPECIAL_TLT:
4137 case SPECIAL_TLTU:
4138 case SPECIAL_TEQ:
4139 case SPECIAL_TNE:
4140 if (s6 == SPECIAL_MULT && rd != MIPS_GPR_ZERO) {
4141 if (cpu->cd.mips.cpu_type.rev ==
4142 MIPS_R5900) {
4143 ic->f = instr(mult_r5900);
4144 break;
4145 }
4146 break;
4147 }
4148 if (s6 == SPECIAL_MULTU && rd!=MIPS_GPR_ZERO) {
4149 if (cpu->cd.mips.cpu_type.rev ==
4150 MIPS_R5900) {
4151 ic->f = instr(multu_r5900);
4152 break;
4153 }
4154 }
4155 if (rd != MIPS_GPR_ZERO) {
4156 fatal("TODO: rd NON-zero\n");
4157 goto bad;
4158 }
4159 /* These instructions don't use rd. */
4160 break;
4161 default:if (rd == MIPS_GPR_ZERO)
4162 ic->f = instr(nop);
4163 }
4164
4165 if (ic->f == instr(addu))
4166 cpu->cd.mips.combination_check = COMBINE(addu);
4167 break;
4168
4169 case SPECIAL_JR:
4170 case SPECIAL_JALR:
4171 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4172 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4173 if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
4174 s6 = SPECIAL_JR;
4175 ic->arg[2] = (addr & 0xffc) + 8;
4176 switch (s6) {
4177 case SPECIAL_JR:
4178 if (rs == MIPS_GPR_RA) {
4179 if (cpu->machine->show_trace_tree)
4180 ic->f = instr(jr_ra_trace);
4181 else
4182 ic->f = instr(jr_ra);
4183 } else {
4184 ic->f = instr(jr);
4185 }
4186 break;
4187 case SPECIAL_JALR:
4188 if (cpu->machine->show_trace_tree)
4189 ic->f = instr(jalr_trace);
4190 else
4191 ic->f = instr(jalr);
4192 break;
4193 }
4194 if (cpu->delay_slot) {
4195 fatal("TODO: branch in delay slot? (1)\n");
4196 goto bad;
4197 }
4198 break;
4199
4200 case SPECIAL_SYSCALL:
4201 if (((iword >> 6) & 0xfffff) == 0x30378) {
4202 /* "Magic trap" for PROM emulation: */
4203 ic->f = instr(promemul);
4204 } else {
4205 ic->f = instr(syscall);
4206 }
4207 break;
4208
4209 case SPECIAL_BREAK:
4210 if (((iword >> 6) & 0xfffff) == 0x30378) {
4211 /* "Magic trap" for REBOOT: */
4212 ic->f = instr(reboot);
4213 } else {
4214 ic->f = instr(break);
4215 }
4216 break;
4217
4218 case SPECIAL_SYNC:
4219 ic->f = instr(nop);
4220 break;
4221
4222 default:goto bad;
4223 }
4224 break;
4225
4226 case HI6_BEQ:
4227 case HI6_BNE:
4228 case HI6_BEQL:
4229 case HI6_BNEL:
4230 case HI6_BLEZ:
4231 case HI6_BLEZL:
4232 case HI6_BGTZ:
4233 case HI6_BGTZL:
4234 samepage_function = NULL; /* get rid of a compiler warning */
4235 switch (main_opcode) {
4236 case HI6_BEQ:
4237 ic->f = instr(beq);
4238 samepage_function = instr(beq_samepage);
4239 /* Special case: comparing a register with itself: */
4240 if (rs == rt) {
4241 ic->f = instr(b);
4242 samepage_function = instr(b_samepage);
4243 }
4244 break;
4245 case HI6_BNE:
4246 ic->f = instr(bne);
4247 samepage_function = instr(bne_samepage);
4248 break;
4249 case HI6_BEQL:
4250 ic->f = instr(beql);
4251 samepage_function = instr(beql_samepage);
4252 /* Special case: comparing a register with itself: */
4253 if (rs == rt) {
4254 ic->f = instr(b);
4255 samepage_function = instr(b_samepage);
4256 }
4257 break;
4258 case HI6_BNEL:
4259 ic->f = instr(bnel);
4260 samepage_function = instr(bnel_samepage);
4261 break;
4262 case HI6_BLEZ:
4263 ic->f = instr(blez);
4264 samepage_function = instr(blez_samepage);
4265 break;
4266 case HI6_BLEZL:
4267 ic->f = instr(blezl);
4268 samepage_function = instr(blezl_samepage);
4269 break;
4270 case HI6_BGTZ:
4271 ic->f = instr(bgtz);
4272 samepage_function = instr(bgtz_samepage);
4273 break;
4274 case HI6_BGTZL:
4275 ic->f = instr(bgtzl);
4276 samepage_function = instr(bgtzl_samepage);
4277 break;
4278 }
4279 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4280 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4281 ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
4282 + (addr & 0xffc) + 4 );
4283 /* Is the offset from the start of the current page still
4284 within the same page? Then use the samepage_function: */
4285 if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE - 1)
4286 << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc) < 0xffc) {
4287 ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page +
4288 ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
4289 & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
4290 ic->f = samepage_function;
4291 }
4292 if (cpu->delay_slot) {
4293 fatal("TODO: branch in delay slot? (2)\n");
4294 goto bad;
4295 }
4296 break;
4297
4298 case HI6_ADDI:
4299 case HI6_ADDIU:
4300 case HI6_SLTI:
4301 case HI6_SLTIU:
4302 case HI6_DADDI:
4303 case HI6_DADDIU:
4304 case HI6_ANDI:
4305 case HI6_ORI:
4306 case HI6_XORI:
4307 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4308 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4309 if (main_opcode == HI6_ADDI ||
4310 main_opcode == HI6_ADDIU ||
4311 main_opcode == HI6_SLTI ||
4312 main_opcode == HI6_SLTIU ||
4313 main_opcode == HI6_DADDI ||
4314 main_opcode == HI6_DADDIU)
4315 ic->arg[2] = (int16_t)iword;
4316 else
4317 ic->arg[2] = (uint16_t)iword;
4318
4319 switch (main_opcode) {
4320 case HI6_ADDI: ic->f = instr(addi); break;
4321 case HI6_ADDIU: ic->f = instr(addiu); break;
4322 case HI6_SLTI: ic->f = instr(slti); break;
4323 case HI6_SLTIU: ic->f = instr(sltiu); break;
4324 case HI6_DADDI: ic->f = instr(daddi); x64 = 1; break;
4325 case HI6_DADDIU: ic->f = instr(daddiu); x64 = 1; break;
4326 case HI6_ANDI: ic->f = instr(andi); break;
4327 case HI6_ORI: ic->f = instr(ori); break;
4328 case HI6_XORI: ic->f = instr(xori); break;
4329 }
4330
4331 if (ic->arg[2] == 0) {
4332 if ((cpu->is_32bit && ic->f == instr(addiu)) ||
4333 (!cpu->is_32bit && ic->f == instr(daddiu))) {
4334 ic->f = instr(mov);
4335 ic->arg[2] = ic->arg[1];
4336 }
4337 }
4338
4339 if (rt == MIPS_GPR_ZERO)
4340 ic->f = instr(nop);
4341
4342 if (ic->f == instr(ori))
4343 cpu->cd.mips.combination_check = COMBINE(ori);
4344 if (ic->f == instr(addiu))
4345 cpu->cd.mips.combination_check = COMBINE(addiu);
4346 if (ic->f == instr(daddiu))
4347 cpu->cd.mips.combination_check = COMBINE(b_daddiu);
4348 break;
4349
4350 case HI6_LUI:
4351 ic->f = instr(set);
4352 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4353 ic->arg[1] = (int32_t) (imm << 16);
4354 /* NOTE: Don't use arg[2] here. It can be used with
4355 instruction combinations, to do lui + addiu, etc. */
4356 if (rt == MIPS_GPR_ZERO)
4357 ic->f = instr(nop);
4358 break;
4359
4360 case HI6_J:
4361 case HI6_JAL:
4362 switch (main_opcode) {
4363 case HI6_J:
4364 ic->f = instr(j);
4365 break;
4366 case HI6_JAL:
4367 if (cpu->machine->show_trace_tree)
4368 ic->f = instr(jal_trace);
4369 else
4370 ic->f = instr(jal);
4371 break;
4372 }
4373 ic->arg[0] = (iword & 0x03ffffff) << 2;
4374 ic->arg[1] = (addr & 0xffc) + 8;
4375 if (cpu->delay_slot) {
4376 fatal("TODO: branch in delay slot (=%i)? (3); addr=%016"
4377 PRIx64" iword=%08"PRIx32"\n", cpu->delay_slot,
4378 (uint64_t)addr, iword);
4379 goto bad;
4380 }
4381 break;
4382
4383 case HI6_COP0:
4384 /* TODO: Is checking bit 25 enough, or perhaps all bits
4385 25..21 must be checked? */
4386 if ((iword >> 25) & 1) {
4387 ic->arg[2] = addr & 0xffc;
4388 switch (iword & 0xff) {
4389 case COP0_TLBR:
4390 ic->f = instr(tlbr);
4391 break;
4392 case COP0_TLBWI:
4393 case COP0_TLBWR:
4394 ic->f = instr(tlbw);
4395 ic->arg[0] = (iword & 0xff) == COP0_TLBWR;
4396 break;
4397 case COP0_TLBP:
4398 ic->f = instr(tlbp);
4399 break;
4400 case COP0_RFE:
4401 ic->f = instr(rfe);
4402 break;
4403 case COP0_ERET:
4404 ic->f = instr(eret);
4405 break;
4406 case COP0_DERET:
4407 ic->f = instr(deret);
4408 break;
4409 case COP0_WAIT:
4410 ic->f = instr(wait);
4411 if (cpu->cd.mips.cpu_type.rev != MIPS_RM5200 &&
4412 cpu->cd.mips.cpu_type.isa_level < 32) {
4413 static int warned = 0;
4414 ic->f = instr(reserved);
4415 if (!warned) {
4416 fatal("{ WARNING: Attempt to "
4417 "execute the WAIT instruct"
4418 "ion, but the emulated CPU "
4419 "is neither RM52xx, nor "
4420 "MIPS32/64! }\n");
4421 warned = 1;
4422 }
4423 }
4424 break;
4425 case COP0_STANDBY:
4426 /* NOTE: Reusing the 'wait' instruction: */
4427 ic->f = instr(wait);
4428 if (cpu->cd.mips.cpu_type.rev != MIPS_R4100) {
4429 static int warned = 0;
4430 ic->f = instr(reserved);
4431 if (!warned) {
4432 fatal("{ WARNING: Attempt to "
4433 "execute a R41xx instruct"
4434 "ion, but the emulated CPU "
4435 "doesn't support it! }\n");
4436 warned = 1;
4437 }
4438 }
4439 break;
4440 case COP0_HIBERNATE:
4441 /* TODO */
4442 goto bad;
4443 case COP0_SUSPEND:
4444 /* Used by NetBSD on HPCmips (VR41xx) to
4445 halt the machine. */
4446 ic->f = instr(reboot);
4447 break;
4448 case COP0_EI:
4449 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4450 ic->f = instr(ei_r5900);
4451 } else
4452 goto bad;
4453 break;
4454 case COP0_DI:
4455 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4456 ic->f = instr(di_r5900);
4457 } else
4458 goto bad;
4459 break;
4460 default:fatal("UNIMPLEMENTED cop0 (func 0x%02x)\n",
4461 iword & 0xff);
4462 goto bad;
4463 }
4464 break;
4465 }
4466
4467 /* rs contains the coprocessor opcode! */
4468 switch (rs) {
4469 case COPz_CFCz:
4470 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4471 ic->arg[1] = rd + ((iword & 7) << 5);
4472 ic->arg[2] = addr & 0xffc;
4473 ic->f = instr(cfc0);
4474 if (rt == MIPS_GPR_ZERO)
4475 ic->f = instr(nop);
4476 break;
4477 case COPz_MFCz:
4478 case COPz_DMFCz:
4479 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4480 ic->arg[1] = rd + ((iword & 7) << 5);
4481 ic->arg[2] = addr & 0xffc;
4482 ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0);
4483 if (rs == COPz_MFCz && (iword & 7) == 0 &&
4484 rd != COP0_COUNT)
4485 ic->f = instr(mfc0_select0);
4486 if (rs == COPz_DMFCz && (iword & 7) == 0 &&
4487 rd != COP0_COUNT)
4488 ic->f = instr(dmfc0_select0);
4489 if (rt == MIPS_GPR_ZERO)
4490 ic->f = instr(nop);
4491 break;
4492 case COPz_MTCz:
4493 case COPz_DMTCz:
4494 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4495 ic->arg[1] = rd + ((iword & 7) << 5);
4496 ic->arg[2] = addr & 0xffc;
4497 ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
4498
4499 if (cpu->cd.mips.cpu_type.exc_model == EXC3K &&
4500 rs == COPz_MTCz && rd == COP0_STATUS)
4501 cpu->cd.mips.combination_check =
4502 COMBINE(netbsd_r3k_cache_inv);
4503
4504 break;
4505 case 8: if (iword == 0x4100ffff) {
4506 /* R2020 DECstation write-loop thingy. */
4507 ic->f = instr(nop);
4508 } else {
4509 fatal("Unimplemented blah blah zzzz...\n");
4510 goto bad;
4511 }
4512 break;
4513
4514 default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
4515 goto bad;
4516 }
4517 break;
4518
4519 case HI6_COP1:
4520 /* Always cause a coprocessor unusable exception if
4521 there is no floating point coprocessor: */
4522 if (cpu->cd.mips.cpu_type.flags & NOFPU ||
4523 cpu->cd.mips.coproc[1] == NULL) {
4524 ic->f = instr(cpu);
4525 ic->arg[0] = 1;
4526 break;
4527 }
4528
4529 /* Bits 25..21 are floating point main opcode: */
4530 switch (rs) {
4531
4532 case COPz_BCzc:
4533 /* Conditional branch: */
4534 /* TODO: Reimplement this in a faster way. */
4535 ic->f = instr(cop1_bc);
4536 ic->arg[0] = (iword >> 18) & 7; /* cc */
4537 ic->arg[1] = (iword >> 16) & 3; /* nd, tf bits */
4538 ic->arg[2] = (int32_t) ((imm <<
4539 MIPS_INSTR_ALIGNMENT_SHIFT) + (addr & 0xffc) + 4);
4540 if (cpu->delay_slot) {
4541 fatal("TODO: branch in delay slot? (4)\n");
4542 goto bad;
4543 }
4544 if (cpu->cd.mips.cpu_type.isa_level <= 3 &&
4545 ic->arg[0] != 0) {
4546 fatal("Attempt to execute a non-cc-0 BC*"
4547 " instruction on an isa level %i cpu. "
4548 "TODO: How should this be handled?\n",
4549 cpu->cd.mips.cpu_type.isa_level);
4550 goto bad;
4551 }
4552
4553 break;
4554
4555 case COPz_DMFCz:
4556 case COPz_DMTCz:
4557 x64 = 1;
4558 /* FALL-THROUGH */
4559 case COP1_FMT_S:
4560 case COP1_FMT_D:
4561 case COP1_FMT_W:
4562 case COP1_FMT_L:
4563 case COP1_FMT_PS:
4564 case COPz_CFCz:
4565 case COPz_CTCz:
4566 case COPz_MFCz:
4567 case COPz_MTCz:
4568 /* Fallback to slow pre-dyntrans code, for now. */
4569 /* TODO: Fix/optimize/rewrite. */
4570 ic->f = instr(cop1_slow);
4571 ic->arg[0] = (uint32_t)iword & ((1 << 26) - 1);
4572 break;
4573
4574 default:fatal("COP1 floating point opcode = 0x%02x\n", rs);
4575 goto bad;
4576 }
4577 break;
4578
4579 case HI6_COP2:
4580 /* Always cause a coprocessor unusable exception if
4581 there is no coprocessor 2: */
4582 if (cpu->cd.mips.coproc[2] == NULL) {
4583 ic->f = instr(cpu);
4584 ic->arg[0] = 2;
4585 break;
4586 }
4587 fatal("COP2 functionality not yet implemented\n");
4588 goto bad;
4589 break;
4590
4591 case HI6_SPECIAL2:
4592 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4593 /* R5900, TX79/C790, have MMI instead of SPECIAL2: */
4594 int mmi_subopcode = (iword >> 6) & 0x1f;
4595
4596 switch (s6) {
4597
4598 case MMI_MADD:
4599 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4600 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4601 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4602 if (rd == MIPS_GPR_ZERO)
4603 ic->f = instr(madd);
4604 else
4605 ic->f = instr(madd_rd);
4606 break;
4607
4608 case MMI_MADDU:
4609 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4610 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4611 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4612 if (rd == MIPS_GPR_ZERO)
4613 ic->f = instr(maddu);
4614 else
4615 ic->f = instr(maddu_rd);
4616 break;
4617
4618 case MMI_MMI0:
4619 switch (mmi_subopcode) {
4620
4621 case MMI0_PEXTLW:
4622 ic->arg[0] = rs;
4623 ic->arg[1] = rt;
4624 ic->arg[2] = rd;
4625 if (rd == MIPS_GPR_ZERO)
4626 ic->f = instr(nop);
4627 else
4628 ic->f = instr(pextlw);
4629 break;
4630
4631 default:goto bad;
4632 }
4633 break;
4634
4635 case MMI_MMI3:
4636 switch (mmi_subopcode) {
4637
4638 case MMI3_POR:
4639 ic->arg[0] = rs;
4640 ic->arg[1] = rt;
4641 ic->arg[2] = rd;
4642 if (rd == MIPS_GPR_ZERO)
4643 ic->f = instr(nop);
4644 else
4645 ic->f = instr(por);
4646 break;
4647
4648 default:goto bad;
4649 }
4650 break;
4651
4652 default:goto bad;
4653 }
4654 break;
4655 }
4656
4657 /* TODO: is this correct? Or are there other non-MIPS32/64
4658 MIPS processors that have support for SPECIAL2 opcodes? */
4659 if (cpu->cd.mips.cpu_type.isa_level < 32) {
4660 ic->f = instr(reserved);
4661 break;
4662 }
4663
4664 /* SPECIAL2: */
4665 switch (s6) {
4666
4667 case SPECIAL2_MADD:
4668 case SPECIAL2_MADDU:
4669 case SPECIAL2_MSUB:
4670 case SPECIAL2_MSUBU:
4671 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4672 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4673 switch (s6) {
4674 case SPECIAL2_MADD: ic->f = instr(madd); break;
4675 case SPECIAL2_MADDU:ic->f = instr(maddu); break;
4676 case SPECIAL2_MSUB: ic->f = instr(msub); break;
4677 case SPECIAL2_MSUBU:ic->f = instr(msubu); break;
4678 }
4679 break;
4680
4681 case SPECIAL2_MUL:
4682 ic->f = instr(mul);
4683 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4684 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4685 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4686 if (rd == MIPS_GPR_ZERO)
4687 ic->f = instr(nop);
4688 break;
4689
4690 case SPECIAL2_CLZ:
4691 case SPECIAL2_CLO:
4692 case SPECIAL2_DCLZ:
4693 case SPECIAL2_DCLO:
4694 switch (s6) {
4695 case SPECIAL2_CLZ: ic->f = instr(clz); break;
4696 case SPECIAL2_CLO: ic->f = instr(clo); break;
4697 case SPECIAL2_DCLZ: ic->f = instr(dclz); break;
4698 case SPECIAL2_DCLO: ic->f = instr(dclo); break;
4699 }
4700 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4701 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4702 if (rd == MIPS_GPR_ZERO)
4703 ic->f = instr(nop);
4704 break;
4705
4706 default:goto bad;
4707 }
4708 break;
4709
4710 case HI6_REGIMM:
4711 switch (rt) {
4712 case REGIMM_BGEZ:
4713 case REGIMM_BGEZL:
4714 case REGIMM_BLTZ:
4715 case REGIMM_BLTZL:
4716 case REGIMM_BGEZAL:
4717 case REGIMM_BGEZALL:
4718 case REGIMM_BLTZAL:
4719 case REGIMM_BLTZALL:
4720 samepage_function = NULL;
4721 switch (rt) {
4722 case REGIMM_BGEZ:
4723 ic->f = instr(bgez);
4724 samepage_function = instr(bgez_samepage);
4725 break;
4726 case REGIMM_BGEZL:
4727 ic->f = instr(bgezl);
4728 samepage_function = instr(bgezl_samepage);
4729 break;
4730 case REGIMM_BLTZ:
4731 ic->f = instr(bltz);
4732 samepage_function = instr(bltz_samepage);
4733 break;
4734 case REGIMM_BLTZL:
4735 ic->f = instr(bltzl);
4736 samepage_function = instr(bltzl_samepage);
4737 break;
4738 case REGIMM_BGEZAL:
4739 ic->f = instr(bgezal);
4740 samepage_function = instr(bgezal_samepage);
4741 break;
4742 case REGIMM_BGEZALL:
4743 ic->f = instr(bgezall);
4744 samepage_function = instr(bgezall_samepage);
4745 break;
4746 case REGIMM_BLTZAL:
4747 ic->f = instr(bltzal);
4748 samepage_function = instr(bltzal_samepage);
4749 break;
4750 case REGIMM_BLTZALL:
4751 ic->f = instr(bltzall);
4752 samepage_function = instr(bltzall_samepage);
4753 break;
4754 }
4755 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4756 ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
4757 + (addr & 0xffc) + 4;
4758 /* Is the offset from the start of the current page
4759 still within the same page? Then use the
4760 samepage_function: */
4761 if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE-1)
4762 << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc)
4763 < 0xffc) {
4764 ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page+
4765 ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
4766 & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
4767 ic->f = samepage_function;
4768 }
4769 if (cpu->delay_slot) {
4770 fatal("TODO: branch in delay slot? (5)\n");
4771 goto bad;
4772 }
4773 break;
4774 default:fatal("UNIMPLEMENTED regimm rt=%i\n", rt);
4775 goto bad;
4776 }
4777 break;
4778
4779 case HI6_LB:
4780 case HI6_LBU:
4781 case HI6_SB:
4782 case HI6_LH:
4783 case HI6_LHU:
4784 case HI6_SH:
4785 case HI6_LW:
4786 case HI6_LWU:
4787 case HI6_SW:
4788 case HI6_LD:
4789 case HI6_SD:
4790 /* TODO: LWU should probably also be x64=1? */
4791 size = 2; signedness = 0; store = 0;
4792 switch (main_opcode) {
4793 case HI6_LB: size = 0; signedness = 1; break;
4794 case HI6_LBU: size = 0; break;
4795 case HI6_LH: size = 1; signedness = 1; break;
4796 case HI6_LHU: size = 1; break;
4797 case HI6_LW: signedness = 1; break;
4798 case HI6_LWU: break;
4799 case HI6_LD: size = 3; x64 = 1; break;
4800 case HI6_SB: store = 1; size = 0; break;
4801 case HI6_SH: store = 1; size = 1; break;
4802 case HI6_SW: store = 1; break;
4803 case HI6_SD: store = 1; size = 3; x64 = 1; break;
4804 }
4805
4806 ic->f =
4807 #ifdef MODE32
4808 mips32_loadstore
4809 #else
4810 mips_loadstore
4811 #endif
4812 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16)
4813 + store * 8 + size * 2 + signedness];
4814 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4815 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4816 ic->arg[2] = (int32_t)imm;
4817
4818 /* Load into the dummy scratch register, if rt = zero */
4819 if (!store && rt == MIPS_GPR_ZERO)
4820 ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4821
4822 /* Check for multiple loads or stores in a row using the same
4823 base register: */
4824 #ifdef MODE32
4825 if (main_opcode == HI6_LW)
4826 cpu->cd.mips.combination_check = COMBINE(multi_lw);
4827 if (main_opcode == HI6_SW)
4828 cpu->cd.mips.combination_check = COMBINE(multi_sw);
4829 #endif
4830 break;
4831
4832 case HI6_LL:
4833 case HI6_LLD:
4834 case HI6_SC:
4835 case HI6_SCD:
4836 /* 32-bit load-linked/store-condition for ISA II and up: */
4837 /* (64-bit load-linked/store-condition for ISA III...) */
4838 if (cpu->cd.mips.cpu_type.isa_level < 2) {
4839 ic->f = instr(reserved);
4840 break;
4841 }
4842
4843 store = 0;
4844 switch (main_opcode) {
4845 case HI6_LL: ic->f = instr(ll); break;
4846 case HI6_LLD: ic->f = instr(lld); x64 = 1; break;
4847 case HI6_SC: ic->f = instr(sc); store = 1; break;
4848 case HI6_SCD: ic->f = instr(scd); store = 1; x64 = 1; break;
4849 }
4850 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4851 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4852 ic->arg[2] = (int32_t)imm;
4853 if (!store && rt == MIPS_GPR_ZERO) {
4854 fatal("HM... unusual load linked\n");
4855 goto bad;
4856 }
4857 break;
4858
4859 case HI6_LWL:
4860 case HI6_LWR:
4861 case HI6_LDL:
4862 case HI6_LDR:
4863 case HI6_SWL:
4864 case HI6_SWR:
4865 case HI6_SDL:
4866 case HI6_SDR:
4867 /* TODO: replace these with faster versions... */
4868 store = 0;
4869 switch (main_opcode) {
4870 case HI6_LWL: ic->f = instr(lwl); break;
4871 case HI6_LWR: ic->f = instr(lwr); break;
4872 case HI6_LDL: ic->f = instr(ldl); x64 = 1; break;
4873 case HI6_LDR: ic->f = instr(ldr); x64 = 1; break;
4874 case HI6_SWL: ic->f = instr(swl); store = 1; break;
4875 case HI6_SWR: ic->f = instr(swr); store = 1; break;
4876 case HI6_SDL: ic->f = instr(sdl); store = 1; x64 = 1; break;
4877 case HI6_SDR: ic->f = instr(sdr); store = 1; x64 = 1; break;
4878 }
4879 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4880 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4881 ic->arg[2] = (int32_t)imm;
4882
4883 /* Load into the dummy scratch register, if rt = zero */
4884 if (!store && rt == MIPS_GPR_ZERO)
4885 ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4886 break;
4887
4888 case HI6_LWC1:
4889 case HI6_SWC1:
4890 case HI6_LDC1:
4891 case HI6_SDC1:
4892 /* 64-bit floating-point load/store for ISA II and up... */
4893 if ((main_opcode == HI6_LDC1 || main_opcode == HI6_SDC1)
4894 && cpu->cd.mips.cpu_type.isa_level < 2) {
4895 ic->f = instr(reserved);
4896 break;
4897 }
4898
4899 ic->arg[0] = (size_t)&cpu->cd.mips.coproc[1]->reg[rt];
4900 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4901 ic->arg[2] = (int32_t)imm;
4902 switch (main_opcode) {
4903 case HI6_LWC1: ic->f = instr(lwc1); break;
4904 case HI6_LDC1: ic->f = instr(ldc1); break;
4905 case HI6_SWC1: ic->f = instr(swc1); break;
4906 case HI6_SDC1: ic->f = instr(sdc1); break;
4907 }
4908
4909 /* Cause a coprocessor unusable exception if
4910 there is no floating point coprocessor: */
4911 if (cpu->cd.mips.cpu_type.flags & NOFPU ||
4912 cpu->cd.mips.coproc[1] == NULL) {
4913 ic->f = instr(cpu);
4914 ic->arg[0] = 1;
4915 }
4916 break;
4917
4918 case HI6_LWC3:
4919 /* PREF (prefetch) on ISA IV and MIPS32/64: */
4920 if (cpu->cd.mips.cpu_type.isa_level >= 4) {
4921 /* Treat as nop for now: */
4922 ic->f = instr(nop);
4923 } else {
4924 fatal("TODO: lwc3 not implemented yet\n");
4925 goto bad;
4926 }
4927 break;
4928
4929 case HI6_LQ_MDMX:
4930 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4931 fatal("TODO: R5900 128-bit loads\n");
4932 goto bad;
4933 }
4934
4935 fatal("TODO: MDMX\n");
4936 goto bad;
4937 /* break */
4938
4939 case HI6_SQ_SPECIAL3:
4940 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4941 fatal("TODO: R5900 128-bit stores\n");
4942 goto bad;
4943 }
4944
4945 if (cpu->cd.mips.cpu_type.isa_level < 32 ||
4946 cpu->cd.mips.cpu_type.isa_revision < 2) {
4947 static int warning = 0;
4948 if (!warning) {
4949 fatal("[ WARNING! SPECIAL3 opcode used, but"
4950 " the %s processor does not implement "
4951 "such instructions. Only printing this "
4952 "warning once. ]\n",
4953 cpu->cd.mips.cpu_type.name);
4954 warning = 1;
4955 }
4956 ic->f = instr(reserved);
4957 break;
4958 }
4959
4960 switch (s6) {
4961
4962 case SPECIAL3_EXT:
4963 /* TODO: Cleanup and extend to DEXT... etc */
4964 {
4965 int msbd = rd, lsb = (iword >> 6) & 0x1f;
4966 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4967 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4968 ic->arg[2] = (msbd << 5) + lsb;
4969 ic->f = instr(ext);
4970 if (rt == MIPS_GPR_ZERO)
4971 ic->f = instr(nop);
4972 }
4973 break;
4974
4975 case SPECIAL3_BSHFL:
4976 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4977 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4978 switch (s10) {
4979 case BSHFL_WSBH:
4980 ic->f = instr(wsbh);
4981 break;
4982 case BSHFL_SEB:
4983 ic->f = instr(seb);
4984 break;
4985 case BSHFL_SEH:
4986 ic->f = instr(seh);
4987 break;
4988 default:goto bad;
4989 }
4990 break;
4991
4992 case SPECIAL3_DBSHFL:
4993 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4994 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4995 switch (s10) {
4996 case BSHFL_DSBH:
4997 ic->f = instr(dsbh);
4998 break;
4999 case BSHFL_DSHD:
5000 ic->f = instr(dshd);
5001 break;
5002 default:goto bad;
5003 }
5004 break;
5005
5006 case SPECIAL3_RDHWR:
5007 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
5008
5009 switch (rd) {
5010
5011 case 0: ic->f = instr(rdhwr_cpunum);
5012 if (rt == MIPS_GPR_ZERO)
5013 ic->f = instr(nop);
5014 break;
5015
5016 default:fatal("unimplemented rdhwr register rd=%i\n",
5017 rd);
5018 goto bad;
5019 }
5020 break;
5021
5022 default:goto bad;
5023 }
5024 break;
5025
5026 case HI6_CACHE:
5027 /* TODO: rt and op etc... */
5028 ic->f = instr(cache);
5029 break;
5030
5031 default:goto bad;
5032 }
5033
5034 #ifdef MODE32
5035 if (x64) {
5036 static int has_warned = 0;
5037 if (!has_warned)
5038 fatal("[ WARNING/NOTE: attempt to execute a 64-bit"
5039 " instruction on an emulated 32-bit processor; "
5040 "pc=0x%08"PRIx32" ]\n", (uint32_t)cpu->pc);
5041 has_warned = 1;
5042 ic->f = instr(reserved);
5043 }
5044 #endif
5045
5046
5047 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
5048 #include "cpu_dyntrans.c"
5049 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
5050 }
5051

  ViewVC Help
Powered by ViewVC 1.1.26