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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 32 - (hide annotations)
Mon Oct 8 16:20:58 2007 UTC (16 years, 6 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 dpavlin 22 /*
2     * Copyright (C) 2005-2006 Anders Gavare. All rights reserved.
3     *
4     * Redistribution and use in source and binary forms, with or without
5     * modification, are permitted provided that the following conditions are met:
6     *
7     * 1. Redistributions of source code must retain the above copyright
8     * notice, this list of conditions and the following disclaimer.
9     * 2. Redistributions in binary form must reproduce the above copyright
10     * notice, this list of conditions and the following disclaimer in the
11     * documentation and/or other materials provided with the distribution.
12     * 3. The name of the author may not be used to endorse or promote products
13     * derived from this software without specific prior written permission.
14     *
15     * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16     * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17     * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18     * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19     * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20     * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21     * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24     * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25     * SUCH DAMAGE.
26     *
27     *
28 dpavlin 32 * $Id: cpu_mips_instr.c,v 1.118 2006/10/29 05:10:27 debug Exp $
29 dpavlin 22 *
30     * MIPS instructions.
31     *
32     * Individual functions should keep track of cpu->n_translated_instrs.
33     * (If no instruction was executed, then it should be decreased. If, say, 4
34     * instructions were combined into one function and executed, then it should
35     * be increased by 3.)
36     */
37    
38    
39     /*
40 dpavlin 32 * 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 dpavlin 24 * invalid: For catching bugs.
119 dpavlin 22 */
120 dpavlin 24 X(invalid)
121 dpavlin 22 {
122 dpavlin 24 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 dpavlin 22 }
127    
128    
129     /*
130 dpavlin 24 * reserved: Attempt to execute a reserved instruction (e.g. a 64-bit
131     * instruction on an emulated 32-bit processor).
132 dpavlin 22 */
133 dpavlin 24 X(reserved)
134 dpavlin 22 {
135 dpavlin 24 /* 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 dpavlin 22 }
143    
144    
145     /*
146 dpavlin 24 * 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 dpavlin 22 * 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 dpavlin 24 MODE_int_t old_pc = cpu->pc;
182 dpavlin 22 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
183     int x = rs == rt;
184 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
185 dpavlin 22 ic[1].f(cpu, ic+1);
186     cpu->n_translated_instrs ++;
187 dpavlin 24 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 dpavlin 22 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 dpavlin 24 } else
198     cpu->delay_slot = NOT_DELAYED;
199 dpavlin 22 }
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 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
205 dpavlin 22 ic[1].f(cpu, ic+1);
206     cpu->n_translated_instrs ++;
207 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
208 dpavlin 22 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 dpavlin 24 cpu->delay_slot = NOT_DELAYED;
215 dpavlin 22 }
216 dpavlin 28 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 dpavlin 22 X(bne)
237     {
238 dpavlin 24 MODE_int_t old_pc = cpu->pc;
239 dpavlin 22 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
240     int x = rs != rt;
241 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
242 dpavlin 22 ic[1].f(cpu, ic+1);
243     cpu->n_translated_instrs ++;
244 dpavlin 24 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 dpavlin 22 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 dpavlin 24 } else
255     cpu->delay_slot = NOT_DELAYED;
256 dpavlin 22 }
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 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
262 dpavlin 22 ic[1].f(cpu, ic+1);
263     cpu->n_translated_instrs ++;
264 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
265 dpavlin 22 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 dpavlin 24 cpu->delay_slot = NOT_DELAYED;
272 dpavlin 22 }
273 dpavlin 28 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 dpavlin 22 X(b)
294     {
295 dpavlin 24 MODE_int_t old_pc = cpu->pc;
296     cpu->delay_slot = TO_BE_DELAYED;
297 dpavlin 22 ic[1].f(cpu, ic+1);
298     cpu->n_translated_instrs ++;
299 dpavlin 24 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 dpavlin 22 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 dpavlin 24 } else
307     cpu->delay_slot = NOT_DELAYED;
308 dpavlin 22 }
309     X(b_samepage)
310     {
311 dpavlin 24 cpu->delay_slot = TO_BE_DELAYED;
312 dpavlin 22 ic[1].f(cpu, ic+1);
313     cpu->n_translated_instrs ++;
314 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT))
315 dpavlin 22 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
316 dpavlin 24 cpu->delay_slot = NOT_DELAYED;
317 dpavlin 22 }
318    
319    
320     /*
321 dpavlin 24 * 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 dpavlin 22 * 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 dpavlin 24 MODE_int_t rs = reg(ic->arg[0]);
992     cpu->delay_slot = TO_BE_DELAYED;
993 dpavlin 22 ic[1].f(cpu, ic+1);
994     cpu->n_translated_instrs ++;
995 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
996 dpavlin 22 cpu->pc = rs;
997 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
998     cpu->delay_slot = NOT_DELAYED;
999 dpavlin 22 quick_pc_to_pointers(cpu);
1000 dpavlin 24 } else
1001     cpu->delay_slot = NOT_DELAYED;
1002 dpavlin 22 }
1003     X(jr_ra)
1004     {
1005 dpavlin 24 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
1006     cpu->delay_slot = TO_BE_DELAYED;
1007 dpavlin 22 ic[1].f(cpu, ic+1);
1008     cpu->n_translated_instrs ++;
1009 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1010 dpavlin 22 cpu->pc = rs;
1011 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
1012     cpu->delay_slot = NOT_DELAYED;
1013 dpavlin 22 quick_pc_to_pointers(cpu);
1014 dpavlin 24 } else
1015     cpu->delay_slot = NOT_DELAYED;
1016 dpavlin 22 }
1017 dpavlin 28 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 dpavlin 22 X(jr_ra_trace)
1028     {
1029 dpavlin 24 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
1030     cpu->delay_slot = TO_BE_DELAYED;
1031 dpavlin 22 ic[1].f(cpu, ic+1);
1032     cpu->n_translated_instrs ++;
1033 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1034 dpavlin 22 cpu->pc = rs;
1035     cpu_functioncall_trace_return(cpu);
1036 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
1037     cpu->delay_slot = NOT_DELAYED;
1038 dpavlin 22 quick_pc_to_pointers(cpu);
1039 dpavlin 24 } else
1040     cpu->delay_slot = NOT_DELAYED;
1041 dpavlin 22 }
1042     X(jalr)
1043     {
1044 dpavlin 24 MODE_int_t rs = reg(ic->arg[0]), rd;
1045     cpu->delay_slot = TO_BE_DELAYED;
1046 dpavlin 22 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 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1053 dpavlin 22 cpu->pc = rs;
1054 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
1055     cpu->delay_slot = NOT_DELAYED;
1056 dpavlin 22 quick_pc_to_pointers(cpu);
1057 dpavlin 24 } else
1058     cpu->delay_slot = NOT_DELAYED;
1059 dpavlin 22 }
1060     X(jalr_trace)
1061     {
1062 dpavlin 24 MODE_int_t rs = reg(ic->arg[0]), rd;
1063     cpu->delay_slot = TO_BE_DELAYED;
1064 dpavlin 22 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 dpavlin 24 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1071 dpavlin 22 cpu->pc = rs;
1072     cpu_functioncall_trace(cpu, cpu->pc);
1073 dpavlin 24 /* Note: Must be non-delayed when jumping to the new pc: */
1074     cpu->delay_slot = NOT_DELAYED;
1075 dpavlin 22 quick_pc_to_pointers(cpu);
1076 dpavlin 24 } else
1077     cpu->delay_slot = NOT_DELAYED;
1078 dpavlin 22 }
1079    
1080    
1081     /*
1082 dpavlin 24 * 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 dpavlin 28 /* TODO: Implement cache operations. */
1145    
1146     /* Make sure the rmw bit is cleared: */
1147 dpavlin 24 cpu->cd.mips.rmw = 0;
1148     }
1149    
1150    
1151     /*
1152 dpavlin 32 * 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 dpavlin 22 * 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 dpavlin 24 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 dpavlin 22
1212    
1213     /*
1214     * 2-register:
1215 dpavlin 24 *
1216     * arg[0] = ptr to rs
1217     * arg[1] = ptr to rt
1218 dpavlin 22 */
1219 dpavlin 24 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 dpavlin 32 cpu->cd.mips.lo = (int32_t)res;
1228     cpu->cd.mips.hi = (int32_t)rem;
1229 dpavlin 24 }
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 dpavlin 32 cpu->cd.mips.lo = (int32_t)res;
1239     cpu->cd.mips.hi = (int32_t)rem;
1240 dpavlin 24 }
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 dpavlin 32 cpu->cd.mips.lo = res;
1251     cpu->cd.mips.hi = rem;
1252 dpavlin 24 }
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 dpavlin 32 cpu->cd.mips.lo = res;
1263     cpu->cd.mips.hi = rem;
1264 dpavlin 24 }
1265 dpavlin 22 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 dpavlin 32 cpu->cd.mips.lo = (int32_t)res;
1270     cpu->cd.mips.hi = (int32_t)(res >> 32);
1271 dpavlin 22 }
1272 dpavlin 24 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 dpavlin 32 cpu->cd.mips.lo = (int32_t)res;
1279     cpu->cd.mips.hi = (int32_t)(res >> 32);
1280 dpavlin 24 reg(ic->arg[2]) = (int32_t)res;
1281     }
1282 dpavlin 22 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 dpavlin 32 cpu->cd.mips.lo = (int32_t)res;
1287     cpu->cd.mips.hi = (int32_t)(res >> 32);
1288 dpavlin 22 }
1289 dpavlin 24 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 dpavlin 32 cpu->cd.mips.lo = (int32_t)res;
1296     cpu->cd.mips.hi = (int32_t)(res >> 32);
1297 dpavlin 24 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 dpavlin 32 cpu->cd.mips.lo = lo;
1326     cpu->cd.mips.hi = hi;
1327 dpavlin 24 }
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 dpavlin 32 cpu->cd.mips.lo = lo;
1343     cpu->cd.mips.hi = hi;
1344 dpavlin 24 }
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 dpavlin 22
1424    
1425     /*
1426 dpavlin 24 * 3-register arithmetic instructions:
1427     *
1428     * arg[0] = ptr to rs
1429     * arg[1] = ptr to rt
1430     * arg[2] = ptr to rd
1431 dpavlin 22 */
1432     X(addu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) + reg(ic->arg[1])); }
1433 dpavlin 24 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 dpavlin 22 X(subu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) - reg(ic->arg[1])); }
1467 dpavlin 24 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 dpavlin 22 X(slt) {
1503 dpavlin 24 reg(ic->arg[2]) =
1504     (MODE_int_t)reg(ic->arg[0]) < (MODE_int_t)reg(ic->arg[1]);
1505 dpavlin 22 }
1506     X(sltu) {
1507 dpavlin 24 reg(ic->arg[2]) =
1508     (MODE_uint_t)reg(ic->arg[0]) < (MODE_uint_t)reg(ic->arg[1]);
1509 dpavlin 22 }
1510 dpavlin 24 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 dpavlin 22 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 dpavlin 24 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 dpavlin 22 X(srl) { reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1518 dpavlin 24 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 dpavlin 22 X(sra) { reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1521 dpavlin 24 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 dpavlin 22 X(mul) { reg(ic->arg[2]) = (int32_t)
1534     ( (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]) ); }
1535 dpavlin 24 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 dpavlin 22
1538    
1539     /*
1540 dpavlin 24 * 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 dpavlin 22 * 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 dpavlin 24 * 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 dpavlin 22 *
1694     * arg[0] = pointer to rs
1695     * arg[1] = pointer to rt
1696     * arg[2] = (int32_t) immediate value
1697     */
1698 dpavlin 24 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 dpavlin 22 X(addiu)
1715     {
1716     reg(ic->arg[1]) = (int32_t)
1717     ((int32_t)reg(ic->arg[0]) + (int32_t)ic->arg[2]);
1718     }
1719 dpavlin 24 X(daddi)
1720     {
1721     int64_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1722     int64_t rt = rs + imm;
1723 dpavlin 22
1724 dpavlin 24 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 dpavlin 22 X(daddiu)
1736     {
1737     reg(ic->arg[1]) = reg(ic->arg[0]) + (int32_t)ic->arg[2];
1738     }
1739 dpavlin 24 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 dpavlin 22
1749    
1750     /*
1751     * set: Set a register to an immediate (signed) 32-bit value.
1752 dpavlin 32 * (This is the actual implementation of the lui instruction.)
1753 dpavlin 22 *
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 dpavlin 24 * cfc0: Copy from Coprocessor 0.
1765 dpavlin 22 * mfc0, dmfc0: Move from Coprocessor 0.
1766     * mtc0, dmtc0: Move to Coprocessor 0.
1767     *
1768     * arg[0] = pointer to GPR (rt)
1769 dpavlin 24 * arg[1] = coprocessor 0 register number | (select << 5) (or for the
1770     * cfc0 instruction, the coprocessor control register number)
1771 dpavlin 22 * arg[2] = relative addr of this instruction within the page
1772     */
1773 dpavlin 24 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 dpavlin 22 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 dpavlin 32 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 dpavlin 22 X(mtc0)
1804     {
1805     int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1806 dpavlin 24 uint64_t tmp = (int32_t) reg(ic->arg[0]);
1807 dpavlin 26
1808 dpavlin 22 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1809     cpu->pc |= ic->arg[2];
1810 dpavlin 24
1811 dpavlin 22 /* TODO: cause exception if necessary */
1812 dpavlin 24 coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd, &tmp, 0, select);
1813    
1814 dpavlin 26 /*
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 dpavlin 24 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 dpavlin 30 if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1824     if (status & (STATUS_EXL | STATUS_ERL))
1825     status &= ~STATUS_IE;
1826     }
1827 dpavlin 26 /* 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 dpavlin 24 }
1836 dpavlin 22 }
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 dpavlin 32 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 dpavlin 22 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 dpavlin 24
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 dpavlin 22 {
1878 dpavlin 24 MODE_int_t old_pc = cpu->pc;
1879 dpavlin 32 int x, cc = ic->arg[0];
1880 dpavlin 24
1881 dpavlin 32 COPROC_AVAILABILITY_CHECK(1);
1882 dpavlin 24
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 dpavlin 32 COPROC_AVAILABILITY_CHECK(1);
1922 dpavlin 24
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 dpavlin 30 X(reboot)
1947     {
1948 dpavlin 32 if (!cop0_availability_check(cpu, ic))
1949     return;
1950    
1951 dpavlin 30 cpu->running = 0;
1952     debugger_n_steps_left_before_interaction = 0;
1953     cpu->cd.mips.next_ic = &nothing_call;
1954     }
1955 dpavlin 24
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 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2014     return;
2015    
2016 dpavlin 22 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2017     cpu->pc |= ic->arg[2];
2018 dpavlin 24 coproc_tlbwri(cpu, ic->arg[0]);
2019 dpavlin 22 }
2020    
2021    
2022 dpavlin 24 /*
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 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2031     return;
2032    
2033 dpavlin 24 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 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2040     return;
2041    
2042 dpavlin 24 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 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2054     return;
2055    
2056 dpavlin 28 /* 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 dpavlin 24
2061 dpavlin 28 /*
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 dpavlin 24 }
2067    
2068    
2069     /*
2070 dpavlin 28 * eret: Return from exception handler (non-R3000 style)
2071 dpavlin 24 */
2072     X(eret)
2073     {
2074 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2075     return;
2076    
2077 dpavlin 28 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 dpavlin 24 quick_pc_to_pointers(cpu);
2087 dpavlin 28
2088     cpu->cd.mips.rmw = 0; /* the "LL bit" */
2089 dpavlin 24 }
2090    
2091    
2092     /*
2093     * deret: Return from debug (EJTAG) handler
2094     */
2095     X(deret)
2096     {
2097 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2098     return;
2099    
2100 dpavlin 24 /*
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 dpavlin 32 * idle: Called from the implementation of wait, or netbsd_pmax_idle.
2119 dpavlin 30 */
2120 dpavlin 32 X(idle)
2121 dpavlin 30 {
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 dpavlin 32
2134 dpavlin 30 /* 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 dpavlin 32 cpu->has_been_idling = 1;
2144 dpavlin 30
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 dpavlin 32 usleep(10);
2158 dpavlin 30 x = 0;
2159     }
2160     cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
2161     }
2162     }
2163    
2164    
2165     /*
2166 dpavlin 32 * 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 dpavlin 24 * 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 dpavlin 32 COPROC_AVAILABILITY_CHECK(1);
2415 dpavlin 24
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 dpavlin 32 COPROC_AVAILABILITY_CHECK(1);
2427 dpavlin 24
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 dpavlin 32 COPROC_AVAILABILITY_CHECK(1);
2443 dpavlin 24
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 dpavlin 32 COPROC_AVAILABILITY_CHECK(1);
2471 dpavlin 24
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 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2522     return;
2523    
2524 dpavlin 24 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2525     }
2526     X(ei_r5900)
2527     {
2528 dpavlin 32 if (!cop0_availability_check(cpu, ic))
2529     return;
2530    
2531 dpavlin 24 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2532     }
2533    
2534    
2535 dpavlin 22 /*****************************************************************************/
2536    
2537    
2538     /*
2539 dpavlin 28 * 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 dpavlin 30 }
2560 dpavlin 28
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 dpavlin 30 #ifdef MODE32
2589 dpavlin 28 /*
2590 dpavlin 30 * multi_sw_2, _3, _4:
2591 dpavlin 28 *
2592     * sw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2]
2593     */
2594 dpavlin 30 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 dpavlin 28 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 dpavlin 30 mips32_loadstore[8 + 2 * 2](cpu, ic);
2680 dpavlin 28 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 dpavlin 30 cpu->cd.mips.next_ic += 2;
2704 dpavlin 28 }
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 dpavlin 30 mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2723 dpavlin 28 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 dpavlin 30 cpu->cd.mips.next_ic += 2;
2747 dpavlin 28 }
2748 dpavlin 30 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 dpavlin 28
2759 dpavlin 30 page = (uint32_t *) cpu->cd.mips.host_store[index0];
2760 dpavlin 28
2761 dpavlin 30 /* 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 dpavlin 28 /*
2845 dpavlin 30 * 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 dpavlin 28 * 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 dpavlin 32 * 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 dpavlin 28 * 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 dpavlin 30 * addiu_bne_samepage_addiu:
3272 dpavlin 28 */
3273 dpavlin 30 X(addiu_bne_samepage_addiu)
3274 dpavlin 28 {
3275 dpavlin 30 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 dpavlin 28 cpu->n_translated_instrs ++;
3331     cpu->cd.mips.next_ic ++;
3332     }
3333    
3334    
3335     /*
3336 dpavlin 30 * 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 dpavlin 22 * b_samepage_addiu:
3376     *
3377     * Combination of branch within the same page, followed by addiu.
3378     */
3379     X(b_samepage_addiu)
3380     {
3381 dpavlin 24 reg(ic[1].arg[1]) = (int32_t)
3382     ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
3383 dpavlin 22 cpu->n_translated_instrs ++;
3384     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
3385     }
3386    
3387    
3388 dpavlin 24 /*
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 dpavlin 22 /*****************************************************************************/
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 dpavlin 24 /* end_of_page doesn't count as an executed instruction: */
3413     cpu->n_translated_instrs --;
3414 dpavlin 22
3415 dpavlin 24 /*
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 dpavlin 22
3423 dpavlin 24 /* Simple jump to the next page (if we are lucky): */
3424     if (cpu->delay_slot == NOT_DELAYED)
3425     return;
3426 dpavlin 22
3427 dpavlin 24 /*
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 dpavlin 22 return;
3434    
3435 dpavlin 24 /*
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 dpavlin 22 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
3441    
3442 dpavlin 24 instr(to_be_translated)(cpu, cpu->cd.mips.next_ic);
3443 dpavlin 22
3444     /* The instruction in the delay slot has now executed. */
3445 dpavlin 24 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
3446     cpu->delay_slot); */
3447 dpavlin 22
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 dpavlin 24 /* 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 dpavlin 22
3463 dpavlin 24 /* This doesn't count as an executed instruction. */
3464     cpu->n_translated_instrs --;
3465 dpavlin 22
3466 dpavlin 24 quick_pc_to_pointers(cpu);
3467 dpavlin 22
3468 dpavlin 24 if (cpu->delay_slot == NOT_DELAYED)
3469 dpavlin 22 return;
3470    
3471 dpavlin 24 fatal("end_of_page2: fatal error, we're in a delay slot\n");
3472 dpavlin 22 exit(1);
3473     }
3474    
3475    
3476     /*****************************************************************************/
3477    
3478    
3479     /*
3480 dpavlin 28 * 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 dpavlin 22 */
3486 dpavlin 28 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 dpavlin 30 /* Only for 32-bit virtual address translation so far. */
3513     #ifdef MODE32
3514 dpavlin 28 /*
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 dpavlin 22 int low_addr)
3524     {
3525     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3526     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3527    
3528 dpavlin 30 if (n_back < 3)
3529 dpavlin 28 return;
3530    
3531 dpavlin 30 /* 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 dpavlin 28
3541 dpavlin 30 /* 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 dpavlin 28 return;
3579    
3580 dpavlin 30 /* 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 dpavlin 28 ic[-2].arg[1] == ic[0].arg[1] &&
3595 dpavlin 30 ic[-1].arg[0] != ic[0].arg[1]) {
3596 dpavlin 28 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3597 dpavlin 30 ic[-2].f = instr(multi_lw_3_le);
3598 dpavlin 28 else
3599 dpavlin 30 ic[-2].f = instr(multi_lw_3_be);
3600 dpavlin 28 }
3601 dpavlin 30
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 dpavlin 28 }
3612 dpavlin 30 #endif
3613 dpavlin 28
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 dpavlin 32 * NetBSD/pmax' idle loop (and possibly others as well).
3658     * Linux/pmax' idle loop.
3659 dpavlin 28 */
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 dpavlin 32 if (n_back < 8)
3666     return;
3667    
3668 dpavlin 28 #ifdef MODE32
3669 dpavlin 32 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 dpavlin 28 return;
3687 dpavlin 32 }
3688 dpavlin 28
3689 dpavlin 32 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 dpavlin 28 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 dpavlin 30 * 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 dpavlin 28 * [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 dpavlin 30 if (n_back < 2)
3806 dpavlin 28 return;
3807    
3808 dpavlin 30 if (ic[-2].f == instr(addiu) &&
3809     ic[-1].f == instr(bne_samepage)) {
3810     ic[-2].f = instr(addiu_bne_samepage_addiu);
3811 dpavlin 28 return;
3812     }
3813    
3814 dpavlin 30 if (ic[-1].f == instr(set)) {
3815     ic[-1].f = instr(lui_addiu);
3816     return;
3817     }
3818    
3819 dpavlin 22 if (ic[-1].f == instr(b_samepage)) {
3820     ic[-1].f = instr(b_samepage_addiu);
3821 dpavlin 28 return;
3822 dpavlin 22 }
3823    
3824 dpavlin 28 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 dpavlin 22 /* TODO: other branches that are followed by addiu should be here */
3840     }
3841    
3842    
3843 dpavlin 24 /*
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 dpavlin 22 /*****************************************************************************/
3864    
3865    
3866     /*
3867     * mips_instr_to_be_translated():
3868     *
3869 dpavlin 24 * Translate an instruction word into a mips_instr_call. ic is filled in with
3870 dpavlin 22 * 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 dpavlin 32 int main_opcode, rt, rs, rd, sa, s6, x64 = 0, s10;
3881 dpavlin 22 int in_crosspage_delayslot = 0;
3882     void (*samepage_function)(struct cpu *, struct mips_instr_call *);
3883 dpavlin 24 int store, signedness, size;
3884 dpavlin 22
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 dpavlin 24 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
3891     /* fatal("[ delay-slot translation across page "
3892     "boundary ]\n"); */
3893 dpavlin 22 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 dpavlin 24 cpu->pc = (MODE_int_t)addr;
3900 dpavlin 22 addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
3901    
3902     /* Read the instruction word from memory: */
3903 dpavlin 24 #ifdef MODE32
3904 dpavlin 22 page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
3905 dpavlin 24 #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 dpavlin 22
3920     if (page != NULL) {
3921     /* fatal("TRANSLATION HIT!\n"); */
3922 dpavlin 24 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
3923 dpavlin 22 } else {
3924     /* fatal("TRANSLATION MISS!\n"); */
3925     if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
3926     sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
3927 dpavlin 24 fatal("to_be_translated(): read failed: TODO\n");
3928 dpavlin 22 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 dpavlin 24 * 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 dpavlin 22 */
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 dpavlin 32 s10 = (rs << 5) | sa;
3962 dpavlin 22
3963     switch (main_opcode) {
3964    
3965     case HI6_SPECIAL:
3966     switch (s6) {
3967    
3968     case SPECIAL_SLL:
3969 dpavlin 24 case SPECIAL_SLLV:
3970 dpavlin 22 case SPECIAL_SRL:
3971 dpavlin 24 case SPECIAL_SRLV:
3972 dpavlin 22 case SPECIAL_SRA:
3973 dpavlin 24 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 dpavlin 22 switch (s6) {
3984     case SPECIAL_SLL: ic->f = instr(sll); break;
3985 dpavlin 24 case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
3986 dpavlin 22 case SPECIAL_SRL: ic->f = instr(srl); break;
3987 dpavlin 24 case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
3988 dpavlin 22 case SPECIAL_SRA: ic->f = instr(sra); break;
3989 dpavlin 24 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 dpavlin 22 }
4006     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4007 dpavlin 24 if (sa >= 0)
4008     ic->arg[1] = sa;
4009     else
4010     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4011 dpavlin 22 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4012     if (rd == MIPS_GPR_ZERO)
4013     ic->f = instr(nop);
4014 dpavlin 30 if (ic->f == instr(sll))
4015     cpu->cd.mips.combination_check = COMBINE(sll);
4016 dpavlin 32 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 dpavlin 22 break;
4034    
4035 dpavlin 24 case SPECIAL_ADD:
4036 dpavlin 22 case SPECIAL_ADDU:
4037 dpavlin 24 case SPECIAL_SUB:
4038 dpavlin 22 case SPECIAL_SUBU:
4039 dpavlin 24 case SPECIAL_DADD:
4040 dpavlin 22 case SPECIAL_DADDU:
4041 dpavlin 24 case SPECIAL_DSUB:
4042 dpavlin 22 case SPECIAL_DSUBU:
4043     case SPECIAL_SLT:
4044     case SPECIAL_SLTU:
4045 dpavlin 24 case SPECIAL_AND:
4046 dpavlin 22 case SPECIAL_OR:
4047     case SPECIAL_XOR:
4048     case SPECIAL_NOR:
4049 dpavlin 24 case SPECIAL_MOVN:
4050     case SPECIAL_MOVZ:
4051 dpavlin 22 case SPECIAL_MFHI:
4052     case SPECIAL_MFLO:
4053     case SPECIAL_MTHI:
4054     case SPECIAL_MTLO:
4055 dpavlin 24 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 dpavlin 22 switch (s6) {
4070 dpavlin 24 case SPECIAL_ADD: ic->f = instr(add); break;
4071 dpavlin 22 case SPECIAL_ADDU: ic->f = instr(addu); break;
4072 dpavlin 24 case SPECIAL_SUB: ic->f = instr(sub); break;
4073 dpavlin 22 case SPECIAL_SUBU: ic->f = instr(subu); break;
4074 dpavlin 24 case SPECIAL_DADD: ic->f = instr(dadd); x64=1; break;
4075 dpavlin 22 case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
4076 dpavlin 24 case SPECIAL_DSUB: ic->f = instr(dsub); x64=1; break;
4077 dpavlin 22 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 dpavlin 24 case SPECIAL_AND: ic->f = instr(and); break;
4081 dpavlin 22 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 dpavlin 24 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 dpavlin 22 }
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 dpavlin 24 /* Special cases for rd: */
4123 dpavlin 22 switch (s6) {
4124     case SPECIAL_MTHI:
4125     case SPECIAL_MTLO:
4126 dpavlin 24 case SPECIAL_DIV:
4127     case SPECIAL_DIVU:
4128     case SPECIAL_DDIV:
4129     case SPECIAL_DDIVU:
4130 dpavlin 22 case SPECIAL_MULT:
4131     case SPECIAL_MULTU:
4132     case SPECIAL_DMULT:
4133     case SPECIAL_DMULTU:
4134 dpavlin 24 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 dpavlin 22 if (rd != MIPS_GPR_ZERO) {
4156 dpavlin 24 fatal("TODO: rd NON-zero\n");
4157 dpavlin 22 goto bad;
4158     }
4159 dpavlin 24 /* These instructions don't use rd. */
4160 dpavlin 22 break;
4161 dpavlin 24 default:if (rd == MIPS_GPR_ZERO)
4162     ic->f = instr(nop);
4163 dpavlin 22 }
4164 dpavlin 30
4165     if (ic->f == instr(addu))
4166     cpu->cd.mips.combination_check = COMBINE(addu);
4167 dpavlin 22 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 dpavlin 24 if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
4174     s6 = SPECIAL_JR;
4175     ic->arg[2] = (addr & 0xffc) + 8;
4176     switch (s6) {
4177 dpavlin 22 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 dpavlin 24 if (cpu->delay_slot) {
4195     fatal("TODO: branch in delay slot? (1)\n");
4196     goto bad;
4197 dpavlin 22 }
4198     break;
4199    
4200 dpavlin 24 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 dpavlin 30 if (((iword >> 6) & 0xfffff) == 0x30378) {
4211     /* "Magic trap" for REBOOT: */
4212     ic->f = instr(reboot);
4213     } else {
4214     ic->f = instr(break);
4215     }
4216 dpavlin 24 break;
4217    
4218 dpavlin 22 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 dpavlin 24 case HI6_BEQL:
4229     case HI6_BNEL:
4230     case HI6_BLEZ:
4231     case HI6_BLEZL:
4232     case HI6_BGTZ:
4233     case HI6_BGTZL:
4234 dpavlin 22 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 dpavlin 24 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 dpavlin 22 }
4279     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4280     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4281 dpavlin 24 ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
4282     + (addr & 0xffc) + 4 );
4283 dpavlin 22 /* 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 dpavlin 24 if (cpu->delay_slot) {
4293     fatal("TODO: branch in delay slot? (2)\n");
4294     goto bad;
4295 dpavlin 22 }
4296     break;
4297    
4298 dpavlin 24 case HI6_ADDI:
4299 dpavlin 22 case HI6_ADDIU:
4300 dpavlin 24 case HI6_SLTI:
4301     case HI6_SLTIU:
4302     case HI6_DADDI:
4303 dpavlin 22 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 dpavlin 24 main_opcode == HI6_SLTI ||
4312     main_opcode == HI6_SLTIU ||
4313 dpavlin 22 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 dpavlin 24
4319 dpavlin 22 switch (main_opcode) {
4320 dpavlin 24 case HI6_ADDI: ic->f = instr(addi); break;
4321 dpavlin 22 case HI6_ADDIU: ic->f = instr(addiu); break;
4322 dpavlin 24 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 dpavlin 22 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 dpavlin 24
4331 dpavlin 28 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 dpavlin 22 if (rt == MIPS_GPR_ZERO)
4340     ic->f = instr(nop);
4341    
4342 dpavlin 30 if (ic->f == instr(ori))
4343     cpu->cd.mips.combination_check = COMBINE(ori);
4344 dpavlin 22 if (ic->f == instr(addiu))
4345 dpavlin 28 cpu->cd.mips.combination_check = COMBINE(addiu);
4346 dpavlin 24 if (ic->f == instr(daddiu))
4347     cpu->cd.mips.combination_check = COMBINE(b_daddiu);
4348 dpavlin 22 break;
4349    
4350     case HI6_LUI:
4351     ic->f = instr(set);
4352     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4353 dpavlin 24 ic->arg[1] = (int32_t) (imm << 16);
4354 dpavlin 28 /* NOTE: Don't use arg[2] here. It can be used with
4355     instruction combinations, to do lui + addiu, etc. */
4356 dpavlin 22 if (rt == MIPS_GPR_ZERO)
4357     ic->f = instr(nop);
4358     break;
4359    
4360 dpavlin 24 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 dpavlin 22 case HI6_COP0:
4384 dpavlin 24 /* 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 dpavlin 30 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 dpavlin 24 case COP0_STANDBY:
4426 dpavlin 32 /* 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 dpavlin 24 case COP0_HIBERNATE:
4441     /* TODO */
4442 dpavlin 32 goto bad;
4443     case COP0_SUSPEND:
4444     /* Used by NetBSD on HPCmips (VR41xx) to
4445     halt the machine. */
4446     ic->f = instr(reboot);
4447 dpavlin 24 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 dpavlin 22 /* rs contains the coprocessor opcode! */
4468     switch (rs) {
4469 dpavlin 24 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 dpavlin 22 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 dpavlin 32 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 dpavlin 22 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 dpavlin 28
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 dpavlin 22 break;
4505 dpavlin 24 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 dpavlin 22 default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
4515     goto bad;
4516     }
4517     break;
4518    
4519     case HI6_COP1:
4520 dpavlin 24 /* 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 dpavlin 22 switch (rs) {
4531 dpavlin 24
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 dpavlin 22 case COPz_CFCz:
4565 dpavlin 24 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 dpavlin 22 break;
4573 dpavlin 24
4574     default:fatal("COP1 floating point opcode = 0x%02x\n", rs);
4575 dpavlin 22 goto bad;
4576     }
4577     break;
4578    
4579 dpavlin 24 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 dpavlin 22 case HI6_SPECIAL2:
4592 dpavlin 24 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 dpavlin 22 switch (s6) {
4666    
4667 dpavlin 24 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 dpavlin 22 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 dpavlin 24 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 dpavlin 28
4822 dpavlin 30 /* Check for multiple loads or stores in a row using the same
4823 dpavlin 28 base register: */
4824 dpavlin 30 #ifdef MODE32
4825     if (main_opcode == HI6_LW)
4826     cpu->cd.mips.combination_check = COMBINE(multi_lw);
4827     if (main_opcode == HI6_SW)
4828 dpavlin 28 cpu->cd.mips.combination_check = COMBINE(multi_sw);
4829 dpavlin 30 #endif
4830 dpavlin 24 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 dpavlin 28 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 dpavlin 24 warning = 1;
4955     }
4956     ic->f = instr(reserved);
4957     break;
4958     }
4959    
4960     switch (s6) {
4961    
4962 dpavlin 32 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 dpavlin 24 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 dpavlin 22 default:goto bad;
5032     }
5033    
5034 dpavlin 24 #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 dpavlin 22
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