/[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 34 - (hide annotations)
Mon Oct 8 16:21:17 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 119157 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1480 2007/02/19 01:34:42 debug Exp $
20061029	Changing usleep(1) calls in the debugger to usleep(10000)
20061107	Adding a new disk image option (-d o...) which sets the ISO9660
		filesystem base offset; also making some other hacks to allow
		NetBSD/dreamcast and homebrew demos/games to boot directly
		from a filesystem image.
		Moving Dreamcast-specific stuff in the documentation to its
		own page (dreamcast.html).
		Adding a border to the Dreamcast PVR framebuffer.
20061108	Adding a -T command line option (again?), for halting the
		emulator on unimplemented memory accesses.
20061109	Continuing on various SH4 and Dreamcast related things.
		The emulator should now halt on more unimplemented device
		accesses, instead of just printing a warning, forcing me to
		actually implement missing stuff :)
20061111	Continuing on SH4 and Dreamcast stuff.
		Adding a bogus Landisk (SH4) machine mode.
20061112	Implementing some parts of the Dreamcast GDROM device. With
		some ugly hacks, NetBSD can (barely) mount an ISO image.
20061113	NetBSD/dreamcast now starts booting from the Live CD image,
		but crashes randomly quite early on in the boot process.
20061122	Beginning on a skeleton interrupt.h and interrupt.c for the
		new interrupt subsystem.
20061124	Continuing on the new interrupt system; taking the first steps
		to attempt to connect CPUs (SuperH and MIPS) and devices
		(dev_cons and SH4 timer interrupts) to it. Many things will
		probably break from now on.
20061125	Converting dev_ns16550, dev_8253 to the new interrupt system.
		Attempting to begin to convert the ISA bus.
20061130	Incorporating a patch from Brian Foley for the configure
		script, which checks for X11 libs in /usr/X11R6/lib64 (which
		is used on some Linux systems).
20061227	Adding a note in the man page about booting from Dreamcast
		CDROM images (i.e. that no external kernel is needed).
20061229	Continuing on the interrupt system rewrite: beginning to
		convert more devices, adding abort() calls for legacy interrupt
		system calls so that everything now _has_ to be rewritten!
		Almost all machine modes are now completely broken.
20061230	More progress on removing old interrupt code, mostly related
		to the ISA bus + devices, the LCA bus (on AlphaBook1), and
		the Footbridge bus (for CATS). And some minor PCI stuff.
		Connecting the ARM cpu to the new interrupt system.
		The CATS, NetWinder, and QEMU_MIPS machine modes now work with
		the new interrupt system :)
20061231	Connecting PowerPC CPUs to the new interrupt system.
		Making PReP machines (IBM 6050) work again.
		Beginning to convert the GT PCI controller (for e.g. Malta
		and Cobalt emulation). Some things work, but not everything.
		Updating Copyright notices for 2007.
20070101	Converting dev_kn02 from legacy style to devinit; the 3max
		machine mode now works with the new interrupt system :-]
20070105	Beginning to convert the SGI O2 machine to the new interrupt
		system; finally converting O2 (IP32) devices to devinit, etc.
20070106	Continuing on the interrupt system redesign/rewrite; KN01
		(PMAX), KN230, and Dreamcast ASIC interrupts should work again,
		moving out stuff from machine.h and devices.h into the
		corresponding devices, beginning the rewrite of i80321
		interrupts, etc.
20070107	Beginning on the rewrite of Eagle interrupt stuff (PReP, etc).
20070117	Beginning the rewrite of Algor (V3) interrupts (finally
		changing dev_v3 into devinit style).
20070118	Removing the "bus" registry concept from machine.h, because
		it was practically meaningless.
		Continuing on the rewrite of Algor V3 ISA interrupts.
20070121	More work on Algor interrupts; they are now working again,
		well enough to run NetBSD/algor. :-)
20070122	Converting VR41xx (HPCmips) interrupts. NetBSD/hpcmips
		can be installed using the new interrupt system :-)
20070123	Making the testmips mode work with the new interrupt system.
20070127	Beginning to convert DEC5800 devices to devinit, and to the
		new interrupt system.
		Converting Playstation 2 devices to devinit, and converting
		the interrupt system. Also fixing a severe bug: the interrupt
		mask register on Playstation 2 is bitwise _toggled_ on writes.
20070128	Removing the dummy NetGear machine mode and the 8250 device
		(which was only used by the NetGear machine).
		Beginning to convert the MacPPC GC (Grand Central) interrupt
		controller to the new interrupt system.
		Converting Jazz interrupts (PICA61 etc.) to the new interrupt
		system. NetBSD/arc can be installed again :-)
		Fixing the JAZZ timer (hardcoding it at 100 Hz, works with
		NetBSD and it is better than a completely dummy timer as it
		was before).
		Converting dev_mp to the new interrupt system, although I
		haven't had time to actually test it yet.
		Completely removing src/machines/interrupts.c, cpu_interrupt
		and cpu_interrupt_ack in src/cpu.c, and
		src/include/machine_interrupts.h! Adding fatal error messages
		+ abort() in the few places that are left to fix.
		Converting dev_z8530 to the new interrupt system.
		FINALLY removing the md_int struct completely from the
		machine struct.
		SH4 fixes (adding a PADDR invalidation in the ITLB replacement
		code in memory_sh.c); the NetBSD/dreamcast LiveCD now runs
		all the way to the login prompt, and can be interacted with :-)
		Converting the CPC700 controller (PCI and interrupt controller
		for PM/PPC) to the new interrupt system.
20070129	Fixing MACE ISA interrupts (SGI IP32 emulation). Both NetBSD/
		sgimips' and OpenBSD/sgi's ramdisk kernels can now be
		interacted with again.
20070130	Moving out the MIPS multi_lw and _sw instruction combinations
		so that they are auto-generated at compile time instead.
20070131	Adding detection of amd64/x86_64 hosts in the configure script,
		for doing initial experiments (again :-) with native code
		generation.
		Adding a -k command line option to set the size of the dyntrans
		cache, and a -B command line option to disable native code
		generation, even if GXemul was compiled with support for
		native code generation for the specific host CPU architecture.
20070201	Experimenting with a skeleton for native code generation.
		Changing the default behaviour, so that native code generation
		is now disabled by default, and has to be enabled by using
		-b on the command line.
20070202	Continuing the native code generation experiments.
		Making PCI interrupts work for Footbridge again.
20070203	More native code generation experiments.
		Removing most of the native code generation experimental code,
		it does not make sense to include any quick hacks like this.
		Minor cleanup/removal of some more legacy MIPS interrupt code.
20070204	Making i80321 interrupts work again (for NetBSD/evbarm etc.),
		and fixing the timer at 100 Hz.
20070206	Experimenting with removing the wdc interrupt slowness hack.
20070207	Lowering the number of dyntrans TLB entries for MIPS from
		192 to 128, resulting in a minor speed improvement.
		Minor optimization to the code invalidation routine in
		cpu_dyntrans.c.
20070208	Increasing (experimentally) the nr of dyntrans instructions per
		loop from 60 to 120.
20070210	Commenting out (experimentally) the dyntrans_device_danger
		detection in memory_rw.c.
		Changing the testmips and baremips machines to use a revision 2
		MIPS64 CPU by default, instead of revision 1.
		Removing the dummy i960, IA64, x86, AVR32, and HP PA-RISC
		files, the PC bios emulation, and the Olivetti M700 (ARC) and
		db64360 emulation modes.
20070211	Adding an "mp" demo to the demos directory, which tests the
		SMP functionality of the testmips machine.
		Fixing PReP interrupts some more. NetBSD/prep now boots again.
20070216	Adding a "nop workaround" for booting Mach/PMAX to the
		documentation; thanks to Artur Bujdoso for the values.
		Converting more of the MacPPC interrupt stuff to the new
		system.
		Beginning to convert BeBox interrupts to the new system.
		PPC603e should NOT have the PPC_NO_DEC flag! Removing it.
		Correcting BeBox clock speed (it was set to 100 in the NetBSD
		bootinfo block, but should be 33000000/4), allowing NetBSD
		to start without using the (incorrect) PPC_NO_DEC hack.
20070217	Implementing (slow) AltiVec vector loads and stores, allowing
		NetBSD/macppc to finally boot using the GENERIC kernel :-)
		Updating the documentation with install instructions for
		NetBSD/macppc.
20070218-19	Regression testing for the release.

==============  RELEASE 0.4.4  ==============


1 dpavlin 22 /*
2 dpavlin 34 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 dpavlin 22 *
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 34 * $Id: cpu_mips_instr.c,v 1.124 2007/02/03 10:00:52 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 34 /* multi_{l,s}w_2, _3, etc. */
2590     #include "tmp_mips_loadstore_multi.c"
2591 dpavlin 30 #endif
2592    
2593    
2594 dpavlin 28 /*
2595 dpavlin 30 * multi_addu_3:
2596     */
2597     X(multi_addu_3)
2598     {
2599     /* Fallback: */
2600     if (cpu->delay_slot) {
2601     instr(addu)(cpu, ic);
2602     return;
2603     }
2604    
2605     reg(ic[0].arg[2]) = (int32_t)(reg(ic[0].arg[0]) + reg(ic[0].arg[1]));
2606     reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0]) + reg(ic[1].arg[1]));
2607     reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0]) + reg(ic[2].arg[1]));
2608     cpu->n_translated_instrs += 2;
2609     cpu->cd.mips.next_ic += 2;
2610     }
2611    
2612    
2613     /*
2614 dpavlin 28 * netbsd_r3k_picache_do_inv:
2615     *
2616     * ic[0] mtc0 rV,status
2617     * 1 nop
2618     * 2 nop
2619     * 3 s: addiu rX,rX,4
2620     * 4 bne rY,rX,s
2621     * 5 sb zr,-4(rX)
2622     * 6 nop
2623     * 7 nop
2624     * 8 mtc0 rT,status
2625     */
2626     X(netbsd_r3k_picache_do_inv)
2627     {
2628     MODE_uint_t rx = reg(ic[3].arg[0]), ry = reg(ic[4].arg[1]);
2629    
2630     /* Fallback if the environment isn't exactly right: */
2631     if (!(reg(ic[0].arg[0]) & MIPS1_ISOL_CACHES) ||
2632     (rx & 3) || (ry & 3) || cpu->delay_slot) {
2633     instr(mtc0)(cpu, ic);
2634     return;
2635     }
2636    
2637     reg(ic[3].arg[0]) = ry;
2638     cpu->n_translated_instrs += (ry - rx + 4) / 4 * 3 + 4;
2639    
2640     /* Run the last mtc0 instruction: */
2641     cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[8];
2642     }
2643    
2644    
2645     #ifdef MODE32
2646     /*
2647 dpavlin 32 * netbsd_pmax_idle():
2648     *
2649     * s: lui rX, hi
2650     * lw rY, lo(rX)
2651     * nop
2652     * beq zr, rY, s
2653     * nop
2654     */
2655     X(netbsd_pmax_idle)
2656     {
2657     uint32_t addr, pageindex, i;
2658     int32_t *page;
2659    
2660     reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2661    
2662     addr = reg(ic[0].arg[0]) + (int32_t)ic[1].arg[2];
2663     pageindex = addr >> 12;
2664     i = (addr & 0xfff) >> 2;
2665     page = (int32_t *) cpu->cd.mips.host_load[pageindex];
2666    
2667     /* Fallback: */
2668     if (cpu->delay_slot || page == NULL || page[i] != 0)
2669     return;
2670    
2671     instr(idle)(cpu, ic);
2672     }
2673    
2674    
2675     /*
2676     * linux_pmax_idle():
2677     *
2678     * s: lui rX, hi
2679     * lw rX, lo(rX)
2680     * nop
2681     * bne zr, rX, ...
2682     * nop
2683     * lw rX, ofs(gp)
2684     * nop
2685     * beq zr, rX, s
2686     * nop
2687     */
2688     X(linux_pmax_idle)
2689     {
2690     uint32_t addr, addr2, pageindex, pageindex2, i, i2;
2691     int32_t *page, *page2;
2692    
2693     reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2694    
2695     addr = reg(ic[0].arg[0]) + (int32_t)ic[1].arg[2];
2696     pageindex = addr >> 12;
2697     i = (addr & 0xfff) >> 2;
2698     page = (int32_t *) cpu->cd.mips.host_load[pageindex];
2699    
2700     addr2 = reg(ic[5].arg[1]) + (int32_t)ic[5].arg[2];
2701     pageindex2 = addr2 >> 12;
2702     i2 = (addr2 & 0xfff) >> 2;
2703     page2 = (int32_t *) cpu->cd.mips.host_load[pageindex2];
2704    
2705     /* Fallback: */
2706     if (cpu->delay_slot || page == NULL || page[i] != 0 || page2[i2] != 0)
2707     return;
2708    
2709     instr(idle)(cpu, ic);
2710     }
2711    
2712    
2713     /*
2714 dpavlin 28 * netbsd_strlen():
2715     *
2716     * lb rV,0(rX)
2717     * s: addiu rX,rX,1
2718     * bne zr,rV,s
2719     * nop
2720     */
2721     X(netbsd_strlen)
2722     {
2723     MODE_uint_t rx = reg(ic[0].arg[1]);
2724     MODE_int_t rv;
2725     signed char *page;
2726     uint32_t pageindex = rx >> 12;
2727     int i;
2728    
2729     page = (signed char *) cpu->cd.mips.host_load[pageindex];
2730    
2731     /* Fallback: */
2732     if (cpu->delay_slot || page == NULL) {
2733     /*
2734     * Normal lb: NOTE: It doesn't matter whether [1] or
2735     * [16+1] is called here, because endianness for 8-bit
2736     * loads is irrelevant. :-)
2737     */
2738     mips32_loadstore[1](cpu, ic);
2739     return;
2740     }
2741    
2742     i = rx & 0xfff;
2743    
2744     /*
2745     * TODO: This loop can be optimized further for optimal
2746     * performance on the host, e.g. by reading full words...
2747     */
2748     do {
2749     rv = page[i ++];
2750     } while (i < 0x1000 && rv != 0);
2751    
2752     cpu->n_translated_instrs += (i - (rx & 0xfff)) * 4 - 1;
2753    
2754     reg(ic[0].arg[1]) = (rx & ~0xfff) + i;
2755     reg(ic[2].arg[0]) = rv;
2756    
2757     /* Done with the loop? Or continue on the next rx page? */
2758     if (rv == 0)
2759     cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[4];
2760     else
2761     cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[0];
2762     }
2763     #endif
2764    
2765    
2766     /*
2767 dpavlin 30 * addiu_bne_samepage_addiu:
2768 dpavlin 28 */
2769 dpavlin 30 X(addiu_bne_samepage_addiu)
2770 dpavlin 28 {
2771 dpavlin 30 MODE_uint_t rs, rt;
2772    
2773     if (cpu->delay_slot) {
2774     instr(addiu)(cpu, ic);
2775     return;
2776     }
2777    
2778     cpu->n_translated_instrs += 2;
2779     reg(ic[0].arg[1]) = (int32_t)
2780     ((int32_t)reg(ic[0].arg[0]) + (int32_t)ic[0].arg[2]);
2781     rs = reg(ic[1].arg[0]);
2782     rt = reg(ic[1].arg[1]);
2783     reg(ic[2].arg[1]) = (int32_t)
2784     ((int32_t)reg(ic[2].arg[0]) + (int32_t)ic[2].arg[2]);
2785     if (rs != rt)
2786     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic[1].arg[2];
2787     else
2788     cpu->cd.mips.next_ic += 2;
2789     }
2790    
2791    
2792     /*
2793     * xor_andi_sll:
2794     */
2795     X(xor_andi_sll)
2796     {
2797     /* Fallback: */
2798     if (cpu->delay_slot) {
2799     instr(xor)(cpu, ic);
2800     return;
2801     }
2802    
2803     reg(ic[0].arg[2]) = reg(ic[0].arg[0]) ^ reg(ic[0].arg[1]);
2804     reg(ic[1].arg[1]) = reg(ic[1].arg[0]) & (uint32_t)ic[1].arg[2];
2805     reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0])<<(int32_t)ic[2].arg[1]);
2806    
2807     cpu->n_translated_instrs += 2;
2808     cpu->cd.mips.next_ic += 2;
2809     }
2810    
2811    
2812     /*
2813     * andi_sll:
2814     */
2815     X(andi_sll)
2816     {
2817     /* Fallback: */
2818     if (cpu->delay_slot) {
2819     instr(andi)(cpu, ic);
2820     return;
2821     }
2822    
2823     reg(ic[0].arg[1]) = reg(ic[0].arg[0]) & (uint32_t)ic[0].arg[2];
2824     reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0])<<(int32_t)ic[1].arg[1]);
2825    
2826 dpavlin 28 cpu->n_translated_instrs ++;
2827     cpu->cd.mips.next_ic ++;
2828     }
2829    
2830    
2831     /*
2832 dpavlin 30 * lui_ori:
2833     */
2834     X(lui_ori)
2835     {
2836     /* Fallback: */
2837     if (cpu->delay_slot) {
2838     instr(set)(cpu, ic);
2839     return;
2840     }
2841    
2842     reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2843     reg(ic[1].arg[1]) = reg(ic[1].arg[0]) | (uint32_t)ic[1].arg[2];
2844    
2845     cpu->n_translated_instrs ++;
2846     cpu->cd.mips.next_ic ++;
2847     }
2848    
2849    
2850     /*
2851     * lui_addiu:
2852     */
2853     X(lui_addiu)
2854     {
2855     /* Fallback: */
2856     if (cpu->delay_slot) {
2857     instr(set)(cpu, ic);
2858     return;
2859     }
2860    
2861     reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
2862     reg(ic[1].arg[1]) = (int32_t)
2863     ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
2864    
2865     cpu->n_translated_instrs ++;
2866     cpu->cd.mips.next_ic ++;
2867     }
2868    
2869    
2870     /*
2871 dpavlin 22 * b_samepage_addiu:
2872     *
2873     * Combination of branch within the same page, followed by addiu.
2874     */
2875     X(b_samepage_addiu)
2876     {
2877 dpavlin 24 reg(ic[1].arg[1]) = (int32_t)
2878     ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
2879 dpavlin 22 cpu->n_translated_instrs ++;
2880     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2881     }
2882    
2883    
2884 dpavlin 24 /*
2885     * b_samepage_daddiu:
2886     *
2887     * Combination of branch within the same page, followed by daddiu.
2888     */
2889     X(b_samepage_daddiu)
2890     {
2891     *(uint64_t *)ic[1].arg[1] = *(uint64_t *)ic[1].arg[0] +
2892     (int32_t)ic[1].arg[2];
2893     cpu->n_translated_instrs ++;
2894     cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2895     }
2896    
2897    
2898 dpavlin 22 /*****************************************************************************/
2899    
2900    
2901     X(end_of_page)
2902     {
2903     /* Update the PC: (offset 0, but on the next page) */
2904     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
2905     MIPS_INSTR_ALIGNMENT_SHIFT);
2906     cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);
2907    
2908 dpavlin 24 /* end_of_page doesn't count as an executed instruction: */
2909     cpu->n_translated_instrs --;
2910 dpavlin 22
2911 dpavlin 24 /*
2912     * Find the new physpage and update translation pointers.
2913     *
2914     * Note: This may cause an exception, if e.g. the new page is
2915     * not accessible.
2916     */
2917     quick_pc_to_pointers(cpu);
2918 dpavlin 22
2919 dpavlin 24 /* Simple jump to the next page (if we are lucky): */
2920     if (cpu->delay_slot == NOT_DELAYED)
2921     return;
2922 dpavlin 22
2923 dpavlin 24 /*
2924     * If we were in a delay slot, and we got an exception while doing
2925     * quick_pc_to_pointers, then return. The function which called
2926     * end_of_page should handle this case.
2927     */
2928     if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
2929 dpavlin 22 return;
2930    
2931 dpavlin 24 /*
2932     * Tricky situation; the delay slot is on the next virtual page.
2933     * Calling to_be_translated will translate one instruction manually,
2934     * execute it, and then discard it.
2935     */
2936 dpavlin 22 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
2937    
2938 dpavlin 24 instr(to_be_translated)(cpu, cpu->cd.mips.next_ic);
2939 dpavlin 22
2940     /* The instruction in the delay slot has now executed. */
2941 dpavlin 24 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
2942     cpu->delay_slot); */
2943 dpavlin 22
2944     /* Find the physpage etc of the instruction in the delay slot
2945     (or, if there was an exception, the exception handler): */
2946     quick_pc_to_pointers(cpu);
2947     }
2948    
2949    
2950     X(end_of_page2)
2951     {
2952 dpavlin 24 /* Synchronize PC on the _second_ instruction on the next page: */
2953     int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2954     / sizeof(struct mips_instr_call);
2955     cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2956     << MIPS_INSTR_ALIGNMENT_SHIFT);
2957     cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2958 dpavlin 22
2959 dpavlin 24 /* This doesn't count as an executed instruction. */
2960     cpu->n_translated_instrs --;
2961 dpavlin 22
2962 dpavlin 24 quick_pc_to_pointers(cpu);
2963 dpavlin 22
2964 dpavlin 24 if (cpu->delay_slot == NOT_DELAYED)
2965 dpavlin 22 return;
2966    
2967 dpavlin 24 fatal("end_of_page2: fatal error, we're in a delay slot\n");
2968 dpavlin 22 exit(1);
2969     }
2970    
2971    
2972     /*****************************************************************************/
2973    
2974    
2975     /*
2976 dpavlin 28 * Combine: Memory fill loop (addiu, bne, sw)
2977     *
2978     * s: addiu rX,rX,4
2979     * bne rY,rX,s
2980     * sw rZ,-4(rX)
2981 dpavlin 22 */
2982 dpavlin 28 void COMBINE(sw_loop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
2983     {
2984     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
2985     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
2986    
2987     /* Only for 32-bit virtual address translation so far. */
2988     if (!cpu->is_32bit)
2989     return;
2990    
2991     if (n_back < 2)
2992     return;
2993    
2994     if (ic[-2].f == instr(addiu) && ic[-2].arg[0] == ic[-2].arg[1] &&
2995     (int32_t)ic[-2].arg[2] == 4 &&
2996     ic[-1].f == instr(bne_samepage) &&
2997     (ic[-1].arg[0] == ic[-2].arg[0] ||
2998     ic[-1].arg[1] == ic[-2].arg[0]) &&
2999     ic[-1].arg[0] != ic[-1].arg[1] &&
3000     ic[-1].arg[2] == (size_t) &ic[-2] &&
3001     ic[0].arg[0] != ic[0].arg[1] &&
3002     ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) {
3003     ic[-2].f = instr(sw_loop);
3004     }
3005     }
3006    
3007    
3008 dpavlin 30 /* Only for 32-bit virtual address translation so far. */
3009     #ifdef MODE32
3010 dpavlin 28 /*
3011     * Combine: Multiple SW in a row using the same base register
3012     *
3013     * sw r?,???(rX)
3014     * sw r?,???(rX)
3015     * sw r?,???(rX)
3016     * ...
3017     */
3018     void COMBINE(multi_sw)(struct cpu *cpu, struct mips_instr_call *ic,
3019 dpavlin 22 int low_addr)
3020     {
3021     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3022     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3023    
3024 dpavlin 30 if (n_back < 3)
3025 dpavlin 28 return;
3026    
3027 dpavlin 30 /* Convert a multi_sw_3 to a multi_sw_4: */
3028     if ((ic[-3].f == instr(multi_sw_3_be) ||
3029     ic[-3].f == instr(multi_sw_3_le)) &&
3030     ic[-3].arg[1] == ic[0].arg[1]) {
3031     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3032     ic[-3].f = instr(multi_sw_4_le);
3033     else
3034     ic[-3].f = instr(multi_sw_4_be);
3035     }
3036 dpavlin 28
3037 dpavlin 30 /* Convert a multi_sw_2 to a multi_sw_3: */
3038     if ((ic[-2].f == instr(multi_sw_2_be) ||
3039     ic[-2].f == instr(multi_sw_2_le)) &&
3040     ic[-2].arg[1] == ic[0].arg[1]) {
3041     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3042     ic[-2].f = instr(multi_sw_3_le);
3043     else
3044     ic[-2].f = instr(multi_sw_3_be);
3045     }
3046    
3047     if (ic[-1].f == ic[0].f && ic[-1].arg[1] == ic[0].arg[1]) {
3048     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3049     ic[-1].f = instr(multi_sw_2_le);
3050     else
3051     ic[-1].f = instr(multi_sw_2_be);
3052     }
3053     }
3054     #endif
3055    
3056    
3057     /* Only for 32-bit virtual address translation so far. */
3058     #ifdef MODE32
3059     /*
3060     * Combine: Multiple LW in a row using the same base register
3061     *
3062     * lw r?,???(rX)
3063     * lw r?,???(rX)
3064     * lw r?,???(rX)
3065     * ...
3066     */
3067     void COMBINE(multi_lw)(struct cpu *cpu, struct mips_instr_call *ic,
3068     int low_addr)
3069     {
3070     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3071     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3072    
3073     if (n_back < 3)
3074 dpavlin 28 return;
3075    
3076 dpavlin 30 /* Convert a multi_lw_3 to a multi_lw_4: */
3077     if ((ic[-3].f == instr(multi_lw_3_be) ||
3078     ic[-3].f == instr(multi_lw_3_le)) &&
3079     ic[-3].arg[1] == ic[0].arg[1] &&
3080     ic[-1].arg[0] != ic[0].arg[1]) {
3081     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3082     ic[-3].f = instr(multi_lw_4_le);
3083     else
3084     ic[-3].f = instr(multi_lw_4_be);
3085     }
3086    
3087     /* Convert a multi_lw_2 to a multi_lw_3: */
3088     if ((ic[-2].f == instr(multi_lw_2_be) ||
3089     ic[-2].f == instr(multi_lw_2_le)) &&
3090 dpavlin 28 ic[-2].arg[1] == ic[0].arg[1] &&
3091 dpavlin 30 ic[-1].arg[0] != ic[0].arg[1]) {
3092 dpavlin 28 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3093 dpavlin 30 ic[-2].f = instr(multi_lw_3_le);
3094 dpavlin 28 else
3095 dpavlin 30 ic[-2].f = instr(multi_lw_3_be);
3096 dpavlin 28 }
3097 dpavlin 30
3098     /* Note: Loads to the base register are not allowed in slot -1. */
3099     if (ic[-1].f == ic[0].f &&
3100     ic[-1].arg[1] == ic[0].arg[1] &&
3101     ic[-1].arg[0] != ic[0].arg[1]) {
3102     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3103     ic[-1].f = instr(multi_lw_2_le);
3104     else
3105     ic[-1].f = instr(multi_lw_2_be);
3106     }
3107 dpavlin 28 }
3108 dpavlin 30 #endif
3109 dpavlin 28
3110    
3111     /*
3112     * Combine: NetBSD/pmax 3.0 R2000/R3000 physical cache invalidation loop
3113     *
3114     * Instruction cache loop:
3115     *
3116     * ic[-8] mtc0 rV,status
3117     * -7 nop
3118     * -6 nop
3119     * -5 s: addiu rX,rX,4
3120     * -4 bne rY,rX,s
3121     * -3 sb zr,-4(rX)
3122     * -2 nop
3123     * -1 nop
3124     * 0 mtc0 rT,status
3125     */
3126     void COMBINE(netbsd_r3k_cache_inv)(struct cpu *cpu,
3127     struct mips_instr_call *ic, int low_addr)
3128     {
3129     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3130     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3131    
3132     if (n_back < 8)
3133     return;
3134    
3135     if (ic[-8].f == instr(mtc0) && ic[-8].arg[1] == COP0_STATUS &&
3136     ic[-7].f == instr(nop) && ic[-6].f == instr(nop) &&
3137     ic[-5].f == instr(addiu) && ic[-5].arg[0] == ic[-5].arg[1] &&
3138     (int32_t)ic[-5].arg[2] == 4 && ic[-4].f == instr(bne_samepage) &&
3139     ic[-4].arg[0] == ic[-5].arg[0] && ic[-4].arg[0] != ic[-4].arg[1] &&
3140     ic[-4].arg[2] == (size_t) &ic[-5] &&
3141     ic[-3].arg[1] == ic[-5].arg[0] &&
3142     ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {
3143     ic[-8].f = instr(netbsd_r3k_picache_do_inv);
3144     }
3145     }
3146    
3147    
3148     /*
3149     * Combine: something ending with a nop.
3150     *
3151     * NetBSD's strlen core.
3152     * [Conditional] branch, followed by nop.
3153 dpavlin 32 * NetBSD/pmax' idle loop (and possibly others as well).
3154     * Linux/pmax' idle loop.
3155 dpavlin 28 */
3156     void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3157     {
3158     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3159     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3160    
3161 dpavlin 32 if (n_back < 8)
3162     return;
3163    
3164 dpavlin 28 #ifdef MODE32
3165 dpavlin 32 if (ic[-8].f == instr(set) &&
3166     ic[-7].f == mips32_loadstore[4 + 1] &&
3167     ic[-7].arg[0] == ic[-1].arg[0] &&
3168     ic[-7].arg[0] == ic[-3].arg[0] &&
3169     ic[-7].arg[0] == ic[-5].arg[0] &&
3170     ic[-7].arg[0] == ic[-7].arg[1] &&
3171     ic[-7].arg[0] == ic[-8].arg[0] &&
3172     ic[-6].f == instr(nop) &&
3173     ic[-5].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3174     ic[-5].f == instr(bne_samepage_nop) &&
3175     ic[-4].f == instr(nop) &&
3176     ic[-3].f == mips32_loadstore[4 + 1] &&
3177     ic[-2].f == instr(nop) &&
3178     ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3179     ic[-1].arg[2] == (size_t) &ic[-8] &&
3180     ic[-1].f == instr(beq_samepage)) {
3181     ic[-8].f = instr(linux_pmax_idle);
3182 dpavlin 28 return;
3183 dpavlin 32 }
3184 dpavlin 28
3185 dpavlin 32 if (ic[-4].f == instr(set) &&
3186     ic[-3].f == mips32_loadstore[4 + 1] &&
3187     ic[-3].arg[0] == ic[-1].arg[0] &&
3188     ic[-3].arg[1] == ic[-4].arg[0] &&
3189     ic[-2].f == instr(nop) &&
3190     ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3191     ic[-1].arg[2] == (size_t) &ic[-4] &&
3192     ic[-1].f == instr(beq_samepage)) {
3193     ic[-4].f = instr(netbsd_pmax_idle);
3194     return;
3195     }
3196    
3197 dpavlin 28 if ((ic[-3].f == mips32_loadstore[1] ||
3198     ic[-3].f == mips32_loadstore[16 + 1]) &&
3199     ic[-3].arg[2] == 0 &&
3200     ic[-3].arg[0] == ic[-1].arg[0] && ic[-3].arg[1] == ic[-2].arg[0] &&
3201     ic[-2].arg[0] == ic[-2].arg[1] && ic[-2].arg[2] == 1 &&
3202     ic[-2].f == instr(addiu) && ic[-1].arg[2] == (size_t) &ic[-3] &&
3203     ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3204     ic[-1].f == instr(bne_samepage)) {
3205     ic[-3].f = instr(netbsd_strlen);
3206     return;
3207     }
3208     #endif
3209    
3210     if (ic[-1].f == instr(bne_samepage)) {
3211     ic[-1].f = instr(bne_samepage_nop);
3212     return;
3213     }
3214    
3215     if (ic[-1].f == instr(beq_samepage)) {
3216     ic[-1].f = instr(beq_samepage_nop);
3217     return;
3218     }
3219    
3220     /* TODO: other branches that are followed by nop should be here */
3221     }
3222    
3223    
3224     /*
3225     * Combine:
3226     *
3227 dpavlin 30 * xor + andi + sll
3228     * andi + sll
3229     */
3230     void COMBINE(sll)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3231     {
3232     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3233     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3234    
3235     if (n_back < 2)
3236     return;
3237    
3238     if (ic[-2].f == instr(xor) && ic[-1].f == instr(andi)) {
3239     ic[-2].f = instr(xor_andi_sll);
3240     return;
3241     }
3242    
3243     if (ic[-1].f == instr(andi)) {
3244     ic[-1].f = instr(andi_sll);
3245     return;
3246     }
3247     }
3248    
3249    
3250     /*
3251     * lui + ori
3252     */
3253     void COMBINE(ori)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3254     {
3255     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3256     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3257    
3258     if (n_back < 1)
3259     return;
3260    
3261     if (ic[-1].f == instr(set)) {
3262     ic[-1].f = instr(lui_ori);
3263     return;
3264     }
3265     }
3266    
3267    
3268     /*
3269     * addu + addu + addu
3270     */
3271     void COMBINE(addu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3272     {
3273     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3274     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3275    
3276     if (n_back < 4)
3277     return;
3278    
3279     /* Avoid "overlapping" instruction combinations: */
3280     if (ic[-4].f == instr(multi_addu_3) ||
3281     ic[-3].f == instr(multi_addu_3))
3282     return;
3283    
3284     if (ic[-2].f == instr(addu) && ic[-1].f == instr(addu)) {
3285     ic[-2].f = instr(multi_addu_3);
3286     return;
3287     }
3288     }
3289    
3290    
3291     /*
3292     * Combine:
3293     *
3294 dpavlin 28 * [Conditional] branch, followed by addiu.
3295     */
3296     void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3297     {
3298     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3299     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3300    
3301 dpavlin 30 if (n_back < 2)
3302 dpavlin 28 return;
3303    
3304 dpavlin 30 if (ic[-2].f == instr(addiu) &&
3305     ic[-1].f == instr(bne_samepage)) {
3306     ic[-2].f = instr(addiu_bne_samepage_addiu);
3307 dpavlin 28 return;
3308     }
3309    
3310 dpavlin 30 if (ic[-1].f == instr(set)) {
3311     ic[-1].f = instr(lui_addiu);
3312     return;
3313     }
3314    
3315 dpavlin 22 if (ic[-1].f == instr(b_samepage)) {
3316     ic[-1].f = instr(b_samepage_addiu);
3317 dpavlin 28 return;
3318 dpavlin 22 }
3319    
3320 dpavlin 28 if (ic[-1].f == instr(beq_samepage)) {
3321     ic[-1].f = instr(beq_samepage_addiu);
3322     return;
3323     }
3324    
3325     if (ic[-1].f == instr(bne_samepage)) {
3326     ic[-1].f = instr(bne_samepage_addiu);
3327     return;
3328     }
3329    
3330     if (ic[-1].f == instr(jr_ra)) {
3331     ic[-1].f = instr(jr_ra_addiu);
3332     return;
3333     }
3334    
3335 dpavlin 22 /* TODO: other branches that are followed by addiu should be here */
3336     }
3337    
3338    
3339 dpavlin 24 /*
3340     * Combine: [Conditional] branch, followed by daddiu.
3341     */
3342     void COMBINE(b_daddiu)(struct cpu *cpu, struct mips_instr_call *ic,
3343     int low_addr)
3344     {
3345     int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3346     & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3347    
3348     if (n_back < 1)
3349     return;
3350    
3351     if (ic[-1].f == instr(b_samepage)) {
3352     ic[-1].f = instr(b_samepage_daddiu);
3353     }
3354    
3355     /* TODO: other branches that are followed by daddiu should be here */
3356     }
3357    
3358    
3359 dpavlin 22 /*****************************************************************************/
3360    
3361    
3362     /*
3363     * mips_instr_to_be_translated():
3364     *
3365 dpavlin 24 * Translate an instruction word into a mips_instr_call. ic is filled in with
3366 dpavlin 22 * valid data for the translated instruction, or a "nothing" instruction if
3367     * there was a translation failure. The newly translated instruction is then
3368     * executed.
3369     */
3370     X(to_be_translated)
3371     {
3372     uint64_t addr, low_pc;
3373     uint32_t iword, imm;
3374     unsigned char *page;
3375     unsigned char ib[4];
3376 dpavlin 32 int main_opcode, rt, rs, rd, sa, s6, x64 = 0, s10;
3377 dpavlin 22 int in_crosspage_delayslot = 0;
3378     void (*samepage_function)(struct cpu *, struct mips_instr_call *);
3379 dpavlin 24 int store, signedness, size;
3380 dpavlin 34 #ifdef NATIVE_CODE_GENERATION
3381     int native = 0;
3382 dpavlin 22
3383 dpavlin 34 if (!cpu->currently_translating_to_native)
3384     cpu->native_code_function_pointer = (void *) &ic->f;
3385     #endif
3386    
3387 dpavlin 22 /* Figure out the (virtual) address of the instruction: */
3388     low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
3389     / sizeof(struct mips_instr_call);
3390    
3391     /* Special case for branch with delayslot on the next page: */
3392 dpavlin 24 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
3393     /* fatal("[ delay-slot translation across page "
3394     "boundary ]\n"); */
3395 dpavlin 22 in_crosspage_delayslot = 1;
3396     }
3397    
3398     addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)
3399     << MIPS_INSTR_ALIGNMENT_SHIFT);
3400     addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
3401 dpavlin 24 cpu->pc = (MODE_int_t)addr;
3402 dpavlin 22 addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
3403    
3404     /* Read the instruction word from memory: */
3405 dpavlin 24 #ifdef MODE32
3406 dpavlin 22 page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
3407 dpavlin 24 #else
3408     {
3409     const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
3410     const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
3411     const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
3412     uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
3413     uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
3414     uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
3415     DYNTRANS_L3N)) & mask3;
3416     struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.mips.l1_64[x1];
3417     struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
3418     page = l3->host_load[x3];
3419     }
3420     #endif
3421 dpavlin 22
3422     if (page != NULL) {
3423     /* fatal("TRANSLATION HIT!\n"); */
3424 dpavlin 24 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
3425 dpavlin 22 } else {
3426     /* fatal("TRANSLATION MISS!\n"); */
3427     if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
3428     sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
3429 dpavlin 24 fatal("to_be_translated(): read failed: TODO\n");
3430 dpavlin 22 goto bad;
3431     }
3432     }
3433    
3434     iword = *((uint32_t *)&ib[0]);
3435    
3436     if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3437     iword = LE32_TO_HOST(iword);
3438     else
3439     iword = BE32_TO_HOST(iword);
3440    
3441    
3442     #define DYNTRANS_TO_BE_TRANSLATED_HEAD
3443     #include "cpu_dyntrans.c"
3444     #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
3445    
3446    
3447     /*
3448     * Translate the instruction:
3449     *
3450 dpavlin 24 * NOTE: _NEVER_ allow writes to the zero register; all instructions
3451     * that use the zero register as their destination should be treated
3452     * as NOPs, except those that access memory (they should use the
3453     * scratch register instead).
3454 dpavlin 22 */
3455    
3456     main_opcode = iword >> 26;
3457     rs = (iword >> 21) & 31;
3458     rt = (iword >> 16) & 31;
3459     rd = (iword >> 11) & 31;
3460     sa = (iword >> 6) & 31;
3461     imm = (int16_t)iword;
3462     s6 = iword & 63;
3463 dpavlin 32 s10 = (rs << 5) | sa;
3464 dpavlin 22
3465     switch (main_opcode) {
3466    
3467     case HI6_SPECIAL:
3468     switch (s6) {
3469    
3470     case SPECIAL_SLL:
3471 dpavlin 24 case SPECIAL_SLLV:
3472 dpavlin 22 case SPECIAL_SRL:
3473 dpavlin 24 case SPECIAL_SRLV:
3474 dpavlin 22 case SPECIAL_SRA:
3475 dpavlin 24 case SPECIAL_SRAV:
3476     case SPECIAL_DSRL:
3477     case SPECIAL_DSRLV:
3478     case SPECIAL_DSRL32:
3479     case SPECIAL_DSLL:
3480     case SPECIAL_DSLLV:
3481     case SPECIAL_DSLL32:
3482     case SPECIAL_DSRA:
3483     case SPECIAL_DSRAV:
3484     case SPECIAL_DSRA32:
3485 dpavlin 22 switch (s6) {
3486     case SPECIAL_SLL: ic->f = instr(sll); break;
3487 dpavlin 24 case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
3488 dpavlin 22 case SPECIAL_SRL: ic->f = instr(srl); break;
3489 dpavlin 24 case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
3490 dpavlin 22 case SPECIAL_SRA: ic->f = instr(sra); break;
3491 dpavlin 24 case SPECIAL_SRAV: ic->f = instr(srav); sa = -1; break;
3492     case SPECIAL_DSRL: ic->f = instr(dsrl); x64=1; break;
3493     case SPECIAL_DSRLV:ic->f = instr(dsrlv);
3494     x64 = 1; sa = -1; break;
3495     case SPECIAL_DSRL32:ic->f= instr(dsrl); x64=1;
3496     sa += 32; break;
3497     case SPECIAL_DSLL: ic->f = instr(dsll); x64=1; break;
3498     case SPECIAL_DSLLV:ic->f = instr(dsllv);
3499     x64 = 1; sa = -1; break;
3500     case SPECIAL_DSLL32:ic->f= instr(dsll); x64=1;
3501     sa += 32; break;
3502     case SPECIAL_DSRA: ic->f = instr(dsra); x64=1; break;
3503     case SPECIAL_DSRAV:ic->f = instr(dsrav);
3504     x64 = 1; sa = -1; break;
3505     case SPECIAL_DSRA32:ic->f = instr(dsra); x64=1;
3506     sa += 32; break;
3507 dpavlin 22 }
3508     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3509 dpavlin 24 if (sa >= 0)
3510     ic->arg[1] = sa;
3511     else
3512     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3513 dpavlin 22 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3514     if (rd == MIPS_GPR_ZERO)
3515     ic->f = instr(nop);
3516 dpavlin 30 if (ic->f == instr(sll))
3517     cpu->cd.mips.combination_check = COMBINE(sll);
3518 dpavlin 32 if (ic->f == instr(nop))
3519     cpu->cd.mips.combination_check = COMBINE(nop);
3520    
3521     /* Special checks for MIPS32/64 revision 2 opcodes,
3522     such as rotation instructions: */
3523     if (sa >= 0 && rs != 0x00) {
3524     switch (rs) {
3525     /* TODO: [d]ror, etc. */
3526     default:goto bad;
3527     }
3528     }
3529     if (sa < 0 && (s10 & 0x1f) != 0) {
3530     switch (s10 & 0x1f) {
3531     /* TODO: [d]rorv, etc. */
3532     default:goto bad;
3533     }
3534     }
3535 dpavlin 34
3536     #ifdef NATIVE_CODE_GENERATION
3537     if (native_code_translation_enabled &&
3538     !cpu->delay_slot && ic->f == instr(nop))
3539     native = native_nop(cpu);
3540     #endif
3541    
3542 dpavlin 22 break;
3543    
3544 dpavlin 24 case SPECIAL_ADD:
3545 dpavlin 22 case SPECIAL_ADDU:
3546 dpavlin 24 case SPECIAL_SUB:
3547 dpavlin 22 case SPECIAL_SUBU:
3548 dpavlin 24 case SPECIAL_DADD:
3549 dpavlin 22 case SPECIAL_DADDU:
3550 dpavlin 24 case SPECIAL_DSUB:
3551 dpavlin 22 case SPECIAL_DSUBU:
3552     case SPECIAL_SLT:
3553     case SPECIAL_SLTU:
3554 dpavlin 24 case SPECIAL_AND:
3555 dpavlin 22 case SPECIAL_OR:
3556     case SPECIAL_XOR:
3557     case SPECIAL_NOR:
3558 dpavlin 24 case SPECIAL_MOVN:
3559     case SPECIAL_MOVZ:
3560 dpavlin 22 case SPECIAL_MFHI:
3561     case SPECIAL_MFLO:
3562     case SPECIAL_MTHI:
3563     case SPECIAL_MTLO:
3564 dpavlin 24 case SPECIAL_DIV:
3565     case SPECIAL_DIVU:
3566     case SPECIAL_DDIV:
3567     case SPECIAL_DDIVU:
3568     case SPECIAL_MULT:
3569     case SPECIAL_MULTU:
3570     case SPECIAL_DMULT:
3571     case SPECIAL_DMULTU:
3572     case SPECIAL_TGE:
3573     case SPECIAL_TGEU:
3574     case SPECIAL_TLT:
3575     case SPECIAL_TLTU:
3576     case SPECIAL_TEQ:
3577     case SPECIAL_TNE:
3578 dpavlin 22 switch (s6) {
3579 dpavlin 24 case SPECIAL_ADD: ic->f = instr(add); break;
3580 dpavlin 22 case SPECIAL_ADDU: ic->f = instr(addu); break;
3581 dpavlin 24 case SPECIAL_SUB: ic->f = instr(sub); break;
3582 dpavlin 22 case SPECIAL_SUBU: ic->f = instr(subu); break;
3583 dpavlin 24 case SPECIAL_DADD: ic->f = instr(dadd); x64=1; break;
3584 dpavlin 22 case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
3585 dpavlin 24 case SPECIAL_DSUB: ic->f = instr(dsub); x64=1; break;
3586 dpavlin 22 case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;
3587     case SPECIAL_SLT: ic->f = instr(slt); break;
3588     case SPECIAL_SLTU: ic->f = instr(sltu); break;
3589 dpavlin 24 case SPECIAL_AND: ic->f = instr(and); break;
3590 dpavlin 22 case SPECIAL_OR: ic->f = instr(or); break;
3591     case SPECIAL_XOR: ic->f = instr(xor); break;
3592     case SPECIAL_NOR: ic->f = instr(nor); break;
3593     case SPECIAL_MFHI: ic->f = instr(mov); break;
3594     case SPECIAL_MFLO: ic->f = instr(mov); break;
3595     case SPECIAL_MTHI: ic->f = instr(mov); break;
3596     case SPECIAL_MTLO: ic->f = instr(mov); break;
3597 dpavlin 24 case SPECIAL_DIV: ic->f = instr(div); break;
3598     case SPECIAL_DIVU: ic->f = instr(divu); break;
3599     case SPECIAL_DDIV: ic->f = instr(ddiv); x64=1; break;
3600     case SPECIAL_DDIVU: ic->f = instr(ddivu); x64=1; break;
3601     case SPECIAL_MULT : ic->f = instr(mult); break;
3602     case SPECIAL_MULTU: ic->f = instr(multu); break;
3603     case SPECIAL_DMULT: ic->f = instr(dmult); x64=1; break;
3604     case SPECIAL_DMULTU:ic->f = instr(dmultu); x64=1; break;
3605     case SPECIAL_TGE: ic->f = instr(tge); break;
3606     case SPECIAL_TGEU: ic->f = instr(tgeu); break;
3607     case SPECIAL_TLT: ic->f = instr(tlt); break;
3608     case SPECIAL_TLTU: ic->f = instr(tltu); break;
3609     case SPECIAL_TEQ: ic->f = instr(teq); break;
3610     case SPECIAL_TNE: ic->f = instr(tne); break;
3611     case SPECIAL_MOVN: ic->f = instr(movn); break;
3612     case SPECIAL_MOVZ: ic->f = instr(movz); break;
3613 dpavlin 22 }
3614     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3615     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3616     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3617     switch (s6) {
3618     case SPECIAL_MFHI:
3619     ic->arg[0] = (size_t)&cpu->cd.mips.hi;
3620     break;
3621     case SPECIAL_MFLO:
3622     ic->arg[0] = (size_t)&cpu->cd.mips.lo;
3623     break;
3624     case SPECIAL_MTHI:
3625     ic->arg[2] = (size_t)&cpu->cd.mips.hi;
3626     break;
3627     case SPECIAL_MTLO:
3628     ic->arg[2] = (size_t)&cpu->cd.mips.lo;
3629     break;
3630     }
3631 dpavlin 24 /* Special cases for rd: */
3632 dpavlin 22 switch (s6) {
3633     case SPECIAL_MTHI:
3634     case SPECIAL_MTLO:
3635 dpavlin 24 case SPECIAL_DIV:
3636     case SPECIAL_DIVU:
3637     case SPECIAL_DDIV:
3638     case SPECIAL_DDIVU:
3639 dpavlin 22 case SPECIAL_MULT:
3640     case SPECIAL_MULTU:
3641     case SPECIAL_DMULT:
3642     case SPECIAL_DMULTU:
3643 dpavlin 24 case SPECIAL_TGE:
3644     case SPECIAL_TGEU:
3645     case SPECIAL_TLT:
3646     case SPECIAL_TLTU:
3647     case SPECIAL_TEQ:
3648     case SPECIAL_TNE:
3649     if (s6 == SPECIAL_MULT && rd != MIPS_GPR_ZERO) {
3650     if (cpu->cd.mips.cpu_type.rev ==
3651     MIPS_R5900) {
3652     ic->f = instr(mult_r5900);
3653     break;
3654     }
3655     break;
3656     }
3657     if (s6 == SPECIAL_MULTU && rd!=MIPS_GPR_ZERO) {
3658     if (cpu->cd.mips.cpu_type.rev ==
3659     MIPS_R5900) {
3660     ic->f = instr(multu_r5900);
3661     break;
3662     }
3663     }
3664 dpavlin 22 if (rd != MIPS_GPR_ZERO) {
3665 dpavlin 24 fatal("TODO: rd NON-zero\n");
3666 dpavlin 22 goto bad;
3667     }
3668 dpavlin 24 /* These instructions don't use rd. */
3669 dpavlin 22 break;
3670 dpavlin 24 default:if (rd == MIPS_GPR_ZERO)
3671     ic->f = instr(nop);
3672 dpavlin 22 }
3673 dpavlin 30
3674     if (ic->f == instr(addu))
3675     cpu->cd.mips.combination_check = COMBINE(addu);
3676 dpavlin 34
3677 dpavlin 22 break;
3678    
3679     case SPECIAL_JR:
3680     case SPECIAL_JALR:
3681     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3682     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
3683 dpavlin 24 if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
3684     s6 = SPECIAL_JR;
3685     ic->arg[2] = (addr & 0xffc) + 8;
3686     switch (s6) {
3687 dpavlin 22 case SPECIAL_JR:
3688     if (rs == MIPS_GPR_RA) {
3689     if (cpu->machine->show_trace_tree)
3690     ic->f = instr(jr_ra_trace);
3691     else
3692     ic->f = instr(jr_ra);
3693     } else {
3694     ic->f = instr(jr);
3695     }
3696     break;
3697     case SPECIAL_JALR:
3698     if (cpu->machine->show_trace_tree)
3699     ic->f = instr(jalr_trace);
3700     else
3701     ic->f = instr(jalr);
3702     break;
3703     }
3704 dpavlin 24 if (cpu->delay_slot) {
3705     fatal("TODO: branch in delay slot? (1)\n");
3706     goto bad;
3707 dpavlin 22 }
3708     break;
3709    
3710 dpavlin 24 case SPECIAL_SYSCALL:
3711     if (((iword >> 6) & 0xfffff) == 0x30378) {
3712     /* "Magic trap" for PROM emulation: */
3713     ic->f = instr(promemul);
3714     } else {
3715     ic->f = instr(syscall);
3716     }
3717     break;
3718    
3719     case SPECIAL_BREAK:
3720 dpavlin 30 if (((iword >> 6) & 0xfffff) == 0x30378) {
3721     /* "Magic trap" for REBOOT: */
3722     ic->f = instr(reboot);
3723     } else {
3724     ic->f = instr(break);
3725     }
3726 dpavlin 24 break;
3727    
3728 dpavlin 22 case SPECIAL_SYNC:
3729     ic->f = instr(nop);
3730     break;
3731    
3732     default:goto bad;
3733     }
3734     break;
3735    
3736     case HI6_BEQ:
3737     case HI6_BNE:
3738 dpavlin 24 case HI6_BEQL:
3739     case HI6_BNEL:
3740     case HI6_BLEZ:
3741     case HI6_BLEZL:
3742     case HI6_BGTZ:
3743     case HI6_BGTZL:
3744 dpavlin 22 samepage_function = NULL; /* get rid of a compiler warning */
3745     switch (main_opcode) {
3746     case HI6_BEQ:
3747     ic->f = instr(beq);
3748     samepage_function = instr(beq_samepage);
3749     /* Special case: comparing a register with itself: */
3750     if (rs == rt) {
3751     ic->f = instr(b);
3752     samepage_function = instr(b_samepage);
3753     }
3754     break;
3755     case HI6_BNE:
3756     ic->f = instr(bne);
3757     samepage_function = instr(bne_samepage);
3758 dpavlin 24 break;
3759     case HI6_BEQL:
3760     ic->f = instr(beql);
3761     samepage_function = instr(beql_samepage);
3762     /* Special case: comparing a register with itself: */
3763     if (rs == rt) {
3764     ic->f = instr(b);
3765     samepage_function = instr(b_samepage);
3766     }
3767     break;
3768     case HI6_BNEL:
3769     ic->f = instr(bnel);
3770     samepage_function = instr(bnel_samepage);
3771     break;
3772     case HI6_BLEZ:
3773     ic->f = instr(blez);
3774     samepage_function = instr(blez_samepage);
3775     break;
3776     case HI6_BLEZL:
3777     ic->f = instr(blezl);
3778     samepage_function = instr(blezl_samepage);
3779     break;
3780     case HI6_BGTZ:
3781     ic->f = instr(bgtz);
3782     samepage_function = instr(bgtz_samepage);
3783     break;
3784     case HI6_BGTZL:
3785     ic->f = instr(bgtzl);
3786     samepage_function = instr(bgtzl_samepage);
3787     break;
3788 dpavlin 22 }
3789     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3790     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3791 dpavlin 24 ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
3792     + (addr & 0xffc) + 4 );
3793 dpavlin 22 /* Is the offset from the start of the current page still
3794     within the same page? Then use the samepage_function: */
3795     if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE - 1)
3796     << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc) < 0xffc) {
3797     ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page +
3798     ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
3799     & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
3800     ic->f = samepage_function;
3801     }
3802 dpavlin 24 if (cpu->delay_slot) {
3803     fatal("TODO: branch in delay slot? (2)\n");
3804     goto bad;
3805 dpavlin 22 }
3806     break;
3807    
3808 dpavlin 24 case HI6_ADDI:
3809 dpavlin 22 case HI6_ADDIU:
3810 dpavlin 24 case HI6_SLTI:
3811     case HI6_SLTIU:
3812     case HI6_DADDI:
3813 dpavlin 22 case HI6_DADDIU:
3814     case HI6_ANDI:
3815     case HI6_ORI:
3816     case HI6_XORI:
3817     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3818     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3819     if (main_opcode == HI6_ADDI ||
3820     main_opcode == HI6_ADDIU ||
3821 dpavlin 24 main_opcode == HI6_SLTI ||
3822     main_opcode == HI6_SLTIU ||
3823 dpavlin 22 main_opcode == HI6_DADDI ||
3824     main_opcode == HI6_DADDIU)
3825     ic->arg[2] = (int16_t)iword;
3826     else
3827     ic->arg[2] = (uint16_t)iword;
3828 dpavlin 24
3829 dpavlin 22 switch (main_opcode) {
3830 dpavlin 24 case HI6_ADDI: ic->f = instr(addi); break;
3831 dpavlin 22 case HI6_ADDIU: ic->f = instr(addiu); break;
3832 dpavlin 24 case HI6_SLTI: ic->f = instr(slti); break;
3833     case HI6_SLTIU: ic->f = instr(sltiu); break;
3834     case HI6_DADDI: ic->f = instr(daddi); x64 = 1; break;
3835 dpavlin 22 case HI6_DADDIU: ic->f = instr(daddiu); x64 = 1; break;
3836     case HI6_ANDI: ic->f = instr(andi); break;
3837     case HI6_ORI: ic->f = instr(ori); break;
3838     case HI6_XORI: ic->f = instr(xori); break;
3839     }
3840 dpavlin 24
3841 dpavlin 28 if (ic->arg[2] == 0) {
3842     if ((cpu->is_32bit && ic->f == instr(addiu)) ||
3843     (!cpu->is_32bit && ic->f == instr(daddiu))) {
3844     ic->f = instr(mov);
3845     ic->arg[2] = ic->arg[1];
3846     }
3847     }
3848    
3849 dpavlin 22 if (rt == MIPS_GPR_ZERO)
3850     ic->f = instr(nop);
3851    
3852 dpavlin 30 if (ic->f == instr(ori))
3853     cpu->cd.mips.combination_check = COMBINE(ori);
3854 dpavlin 22 if (ic->f == instr(addiu))
3855 dpavlin 28 cpu->cd.mips.combination_check = COMBINE(addiu);
3856 dpavlin 24 if (ic->f == instr(daddiu))
3857     cpu->cd.mips.combination_check = COMBINE(b_daddiu);
3858 dpavlin 22 break;
3859    
3860     case HI6_LUI:
3861     ic->f = instr(set);
3862     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3863 dpavlin 24 ic->arg[1] = (int32_t) (imm << 16);
3864 dpavlin 28 /* NOTE: Don't use arg[2] here. It can be used with
3865     instruction combinations, to do lui + addiu, etc. */
3866 dpavlin 22 if (rt == MIPS_GPR_ZERO)
3867     ic->f = instr(nop);
3868 dpavlin 34 #ifdef NATIVE_CODE_GENERATION
3869     #ifdef MODE32
3870     if (native_code_translation_enabled && !cpu->delay_slot
3871     && (addr & 0xffc) >= 4)
3872     native = native_set_u32_p32(cpu,
3873     ic->arg[1], &reg(&cpu->cd.mips.gpr[rt]));
3874     #endif
3875     #endif
3876 dpavlin 22 break;
3877    
3878 dpavlin 24 case HI6_J:
3879     case HI6_JAL:
3880     switch (main_opcode) {
3881     case HI6_J:
3882     ic->f = instr(j);
3883     break;
3884     case HI6_JAL:
3885     if (cpu->machine->show_trace_tree)
3886     ic->f = instr(jal_trace);
3887     else
3888     ic->f = instr(jal);
3889     break;
3890     }
3891     ic->arg[0] = (iword & 0x03ffffff) << 2;
3892     ic->arg[1] = (addr & 0xffc) + 8;
3893     if (cpu->delay_slot) {
3894     fatal("TODO: branch in delay slot (=%i)? (3); addr=%016"
3895     PRIx64" iword=%08"PRIx32"\n", cpu->delay_slot,
3896     (uint64_t)addr, iword);
3897     goto bad;
3898     }
3899     break;
3900    
3901 dpavlin 22 case HI6_COP0:
3902 dpavlin 24 /* TODO: Is checking bit 25 enough, or perhaps all bits
3903     25..21 must be checked? */
3904     if ((iword >> 25) & 1) {
3905     ic->arg[2] = addr & 0xffc;
3906     switch (iword & 0xff) {
3907     case COP0_TLBR:
3908     ic->f = instr(tlbr);
3909     break;
3910     case COP0_TLBWI:
3911     case COP0_TLBWR:
3912     ic->f = instr(tlbw);
3913     ic->arg[0] = (iword & 0xff) == COP0_TLBWR;
3914     break;
3915     case COP0_TLBP:
3916     ic->f = instr(tlbp);
3917     break;
3918     case COP0_RFE:
3919     ic->f = instr(rfe);
3920     break;
3921     case COP0_ERET:
3922     ic->f = instr(eret);
3923     break;
3924     case COP0_DERET:
3925     ic->f = instr(deret);
3926     break;
3927 dpavlin 30 case COP0_WAIT:
3928     ic->f = instr(wait);
3929     if (cpu->cd.mips.cpu_type.rev != MIPS_RM5200 &&
3930     cpu->cd.mips.cpu_type.isa_level < 32) {
3931     static int warned = 0;
3932     ic->f = instr(reserved);
3933     if (!warned) {
3934     fatal("{ WARNING: Attempt to "
3935     "execute the WAIT instruct"
3936     "ion, but the emulated CPU "
3937     "is neither RM52xx, nor "
3938     "MIPS32/64! }\n");
3939     warned = 1;
3940     }
3941     }
3942     break;
3943 dpavlin 24 case COP0_STANDBY:
3944 dpavlin 32 /* NOTE: Reusing the 'wait' instruction: */
3945     ic->f = instr(wait);
3946     if (cpu->cd.mips.cpu_type.rev != MIPS_R4100) {
3947     static int warned = 0;
3948     ic->f = instr(reserved);
3949     if (!warned) {
3950     fatal("{ WARNING: Attempt to "
3951     "execute a R41xx instruct"
3952     "ion, but the emulated CPU "
3953     "doesn't support it! }\n");
3954     warned = 1;
3955     }
3956     }
3957     break;
3958 dpavlin 24 case COP0_HIBERNATE:
3959     /* TODO */
3960 dpavlin 32 goto bad;
3961     case COP0_SUSPEND:
3962     /* Used by NetBSD on HPCmips (VR41xx) to
3963     halt the machine. */
3964     ic->f = instr(reboot);
3965 dpavlin 24 break;
3966     case COP0_EI:
3967     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3968     ic->f = instr(ei_r5900);
3969     } else
3970     goto bad;
3971     break;
3972     case COP0_DI:
3973     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
3974     ic->f = instr(di_r5900);
3975     } else
3976     goto bad;
3977     break;
3978     default:fatal("UNIMPLEMENTED cop0 (func 0x%02x)\n",
3979     iword & 0xff);
3980     goto bad;
3981     }
3982     break;
3983     }
3984    
3985 dpavlin 22 /* rs contains the coprocessor opcode! */
3986     switch (rs) {
3987 dpavlin 24 case COPz_CFCz:
3988     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3989     ic->arg[1] = rd + ((iword & 7) << 5);
3990     ic->arg[2] = addr & 0xffc;
3991     ic->f = instr(cfc0);
3992     if (rt == MIPS_GPR_ZERO)
3993     ic->f = instr(nop);
3994     break;
3995 dpavlin 22 case COPz_MFCz:
3996     case COPz_DMFCz:
3997     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3998     ic->arg[1] = rd + ((iword & 7) << 5);
3999     ic->arg[2] = addr & 0xffc;
4000     ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0);
4001 dpavlin 32 if (rs == COPz_MFCz && (iword & 7) == 0 &&
4002     rd != COP0_COUNT)
4003     ic->f = instr(mfc0_select0);
4004     if (rs == COPz_DMFCz && (iword & 7) == 0 &&
4005     rd != COP0_COUNT)
4006     ic->f = instr(dmfc0_select0);
4007 dpavlin 22 if (rt == MIPS_GPR_ZERO)
4008     ic->f = instr(nop);
4009     break;
4010     case COPz_MTCz:
4011     case COPz_DMTCz:
4012     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4013     ic->arg[1] = rd + ((iword & 7) << 5);
4014     ic->arg[2] = addr & 0xffc;
4015     ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
4016 dpavlin 28
4017     if (cpu->cd.mips.cpu_type.exc_model == EXC3K &&
4018     rs == COPz_MTCz && rd == COP0_STATUS)
4019     cpu->cd.mips.combination_check =
4020     COMBINE(netbsd_r3k_cache_inv);
4021    
4022 dpavlin 22 break;
4023 dpavlin 24 case 8: if (iword == 0x4100ffff) {
4024     /* R2020 DECstation write-loop thingy. */
4025     ic->f = instr(nop);
4026     } else {
4027     fatal("Unimplemented blah blah zzzz...\n");
4028     goto bad;
4029     }
4030     break;
4031    
4032 dpavlin 22 default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
4033     goto bad;
4034     }
4035     break;
4036    
4037     case HI6_COP1:
4038 dpavlin 24 /* Always cause a coprocessor unusable exception if
4039     there is no floating point coprocessor: */
4040     if (cpu->cd.mips.cpu_type.flags & NOFPU ||
4041     cpu->cd.mips.coproc[1] == NULL) {
4042     ic->f = instr(cpu);
4043     ic->arg[0] = 1;
4044     break;
4045     }
4046    
4047     /* Bits 25..21 are floating point main opcode: */
4048 dpavlin 22 switch (rs) {
4049 dpavlin 24
4050     case COPz_BCzc:
4051     /* Conditional branch: */
4052     /* TODO: Reimplement this in a faster way. */
4053     ic->f = instr(cop1_bc);
4054     ic->arg[0] = (iword >> 18) & 7; /* cc */
4055     ic->arg[1] = (iword >> 16) & 3; /* nd, tf bits */
4056     ic->arg[2] = (int32_t) ((imm <<
4057     MIPS_INSTR_ALIGNMENT_SHIFT) + (addr & 0xffc) + 4);
4058     if (cpu->delay_slot) {
4059     fatal("TODO: branch in delay slot? (4)\n");
4060     goto bad;
4061     }
4062     if (cpu->cd.mips.cpu_type.isa_level <= 3 &&
4063     ic->arg[0] != 0) {
4064     fatal("Attempt to execute a non-cc-0 BC*"
4065     " instruction on an isa level %i cpu. "
4066     "TODO: How should this be handled?\n",
4067     cpu->cd.mips.cpu_type.isa_level);
4068     goto bad;
4069     }
4070    
4071     break;
4072    
4073     case COPz_DMFCz:
4074     case COPz_DMTCz:
4075     x64 = 1;
4076     /* FALL-THROUGH */
4077     case COP1_FMT_S:
4078     case COP1_FMT_D:
4079     case COP1_FMT_W:
4080     case COP1_FMT_L:
4081     case COP1_FMT_PS:
4082 dpavlin 22 case COPz_CFCz:
4083 dpavlin 24 case COPz_CTCz:
4084     case COPz_MFCz:
4085     case COPz_MTCz:
4086     /* Fallback to slow pre-dyntrans code, for now. */
4087     /* TODO: Fix/optimize/rewrite. */
4088     ic->f = instr(cop1_slow);
4089     ic->arg[0] = (uint32_t)iword & ((1 << 26) - 1);
4090 dpavlin 22 break;
4091 dpavlin 24
4092     default:fatal("COP1 floating point opcode = 0x%02x\n", rs);
4093 dpavlin 22 goto bad;
4094     }
4095     break;
4096    
4097 dpavlin 24 case HI6_COP2:
4098     /* Always cause a coprocessor unusable exception if
4099     there is no coprocessor 2: */
4100     if (cpu->cd.mips.coproc[2] == NULL) {
4101     ic->f = instr(cpu);
4102     ic->arg[0] = 2;
4103     break;
4104     }
4105     fatal("COP2 functionality not yet implemented\n");
4106     goto bad;
4107     break;
4108    
4109 dpavlin 34 case HI6_COP3:
4110     /* Always cause a coprocessor unusable exception if
4111     there is no coprocessor 3: */
4112     if (cpu->cd.mips.coproc[3] == NULL) {
4113     ic->f = instr(cpu);
4114     ic->arg[0] = 3;
4115     break;
4116     }
4117    
4118     if (iword == 0x4d00ffff) {
4119     /* R2020 writeback thing, used by e.g. NetBSD/pmax
4120     on MIPSMATE. */
4121     ic->f = instr(nop);
4122     } else {
4123     fatal("COP3 iword=0x%08x\n", iword);
4124     goto bad;
4125     }
4126     break;
4127    
4128 dpavlin 22 case HI6_SPECIAL2:
4129 dpavlin 24 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4130     /* R5900, TX79/C790, have MMI instead of SPECIAL2: */
4131     int mmi_subopcode = (iword >> 6) & 0x1f;
4132    
4133     switch (s6) {
4134    
4135     case MMI_MADD:
4136     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4137     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4138     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4139     if (rd == MIPS_GPR_ZERO)
4140     ic->f = instr(madd);
4141     else
4142     ic->f = instr(madd_rd);
4143     break;
4144    
4145     case MMI_MADDU:
4146     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4147     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4148     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4149     if (rd == MIPS_GPR_ZERO)
4150     ic->f = instr(maddu);
4151     else
4152     ic->f = instr(maddu_rd);
4153     break;
4154    
4155     case MMI_MMI0:
4156     switch (mmi_subopcode) {
4157    
4158     case MMI0_PEXTLW:
4159     ic->arg[0] = rs;
4160     ic->arg[1] = rt;
4161     ic->arg[2] = rd;
4162     if (rd == MIPS_GPR_ZERO)
4163     ic->f = instr(nop);
4164     else
4165     ic->f = instr(pextlw);
4166     break;
4167    
4168     default:goto bad;
4169     }
4170     break;
4171    
4172     case MMI_MMI3:
4173     switch (mmi_subopcode) {
4174    
4175     case MMI3_POR:
4176     ic->arg[0] = rs;
4177     ic->arg[1] = rt;
4178     ic->arg[2] = rd;
4179     if (rd == MIPS_GPR_ZERO)
4180     ic->f = instr(nop);
4181     else
4182     ic->f = instr(por);
4183     break;
4184    
4185     default:goto bad;
4186     }
4187     break;
4188    
4189     default:goto bad;
4190     }
4191     break;
4192     }
4193    
4194     /* TODO: is this correct? Or are there other non-MIPS32/64
4195     MIPS processors that have support for SPECIAL2 opcodes? */
4196     if (cpu->cd.mips.cpu_type.isa_level < 32) {
4197     ic->f = instr(reserved);
4198     break;
4199     }
4200    
4201     /* SPECIAL2: */
4202 dpavlin 22 switch (s6) {
4203    
4204 dpavlin 24 case SPECIAL2_MADD:
4205     case SPECIAL2_MADDU:
4206     case SPECIAL2_MSUB:
4207     case SPECIAL2_MSUBU:
4208     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4209     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4210     switch (s6) {
4211     case SPECIAL2_MADD: ic->f = instr(madd); break;
4212     case SPECIAL2_MADDU:ic->f = instr(maddu); break;
4213     case SPECIAL2_MSUB: ic->f = instr(msub); break;
4214     case SPECIAL2_MSUBU:ic->f = instr(msubu); break;
4215     }
4216     break;
4217    
4218 dpavlin 22 case SPECIAL2_MUL:
4219     ic->f = instr(mul);
4220     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4221     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4222     ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4223     if (rd == MIPS_GPR_ZERO)
4224     ic->f = instr(nop);
4225     break;
4226    
4227     case SPECIAL2_CLZ:
4228     case SPECIAL2_CLO:
4229     case SPECIAL2_DCLZ:
4230     case SPECIAL2_DCLO:
4231     switch (s6) {
4232     case SPECIAL2_CLZ: ic->f = instr(clz); break;
4233     case SPECIAL2_CLO: ic->f = instr(clo); break;
4234     case SPECIAL2_DCLZ: ic->f = instr(dclz); break;
4235     case SPECIAL2_DCLO: ic->f = instr(dclo); break;
4236     }
4237     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4238     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4239     if (rd == MIPS_GPR_ZERO)
4240     ic->f = instr(nop);
4241     break;
4242    
4243     default:goto bad;
4244     }
4245     break;
4246    
4247 dpavlin 24 case HI6_REGIMM:
4248     switch (rt) {
4249     case REGIMM_BGEZ:
4250     case REGIMM_BGEZL:
4251     case REGIMM_BLTZ:
4252     case REGIMM_BLTZL:
4253     case REGIMM_BGEZAL:
4254     case REGIMM_BGEZALL:
4255     case REGIMM_BLTZAL:
4256     case REGIMM_BLTZALL:
4257     samepage_function = NULL;
4258     switch (rt) {
4259     case REGIMM_BGEZ:
4260     ic->f = instr(bgez);
4261     samepage_function = instr(bgez_samepage);
4262     break;
4263     case REGIMM_BGEZL:
4264     ic->f = instr(bgezl);
4265     samepage_function = instr(bgezl_samepage);
4266     break;
4267     case REGIMM_BLTZ:
4268     ic->f = instr(bltz);
4269     samepage_function = instr(bltz_samepage);
4270     break;
4271     case REGIMM_BLTZL:
4272     ic->f = instr(bltzl);
4273     samepage_function = instr(bltzl_samepage);
4274     break;
4275     case REGIMM_BGEZAL:
4276     ic->f = instr(bgezal);
4277     samepage_function = instr(bgezal_samepage);
4278     break;
4279     case REGIMM_BGEZALL:
4280     ic->f = instr(bgezall);
4281     samepage_function = instr(bgezall_samepage);
4282     break;
4283     case REGIMM_BLTZAL:
4284     ic->f = instr(bltzal);
4285     samepage_function = instr(bltzal_samepage);
4286     break;
4287     case REGIMM_BLTZALL:
4288     ic->f = instr(bltzall);
4289     samepage_function = instr(bltzall_samepage);
4290     break;
4291     }
4292     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4293     ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
4294     + (addr & 0xffc) + 4;
4295     /* Is the offset from the start of the current page
4296     still within the same page? Then use the
4297     samepage_function: */
4298     if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE-1)
4299     << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc)
4300     < 0xffc) {
4301     ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page+
4302     ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
4303     & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
4304     ic->f = samepage_function;
4305     }
4306     if (cpu->delay_slot) {
4307     fatal("TODO: branch in delay slot? (5)\n");
4308     goto bad;
4309     }
4310     break;
4311     default:fatal("UNIMPLEMENTED regimm rt=%i\n", rt);
4312     goto bad;
4313     }
4314     break;
4315    
4316     case HI6_LB:
4317     case HI6_LBU:
4318     case HI6_SB:
4319     case HI6_LH:
4320     case HI6_LHU:
4321     case HI6_SH:
4322     case HI6_LW:
4323     case HI6_LWU:
4324     case HI6_SW:
4325     case HI6_LD:
4326     case HI6_SD:
4327     /* TODO: LWU should probably also be x64=1? */
4328     size = 2; signedness = 0; store = 0;
4329     switch (main_opcode) {
4330     case HI6_LB: size = 0; signedness = 1; break;
4331     case HI6_LBU: size = 0; break;
4332     case HI6_LH: size = 1; signedness = 1; break;
4333     case HI6_LHU: size = 1; break;
4334     case HI6_LW: signedness = 1; break;
4335     case HI6_LWU: break;
4336     case HI6_LD: size = 3; x64 = 1; break;
4337     case HI6_SB: store = 1; size = 0; break;
4338     case HI6_SH: store = 1; size = 1; break;
4339     case HI6_SW: store = 1; break;
4340     case HI6_SD: store = 1; size = 3; x64 = 1; break;
4341     }
4342    
4343     ic->f =
4344     #ifdef MODE32
4345     mips32_loadstore
4346     #else
4347     mips_loadstore
4348     #endif
4349     [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16)
4350     + store * 8 + size * 2 + signedness];
4351     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4352     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4353     ic->arg[2] = (int32_t)imm;
4354    
4355     /* Load into the dummy scratch register, if rt = zero */
4356     if (!store && rt == MIPS_GPR_ZERO)
4357     ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4358 dpavlin 28
4359 dpavlin 30 /* Check for multiple loads or stores in a row using the same
4360 dpavlin 28 base register: */
4361 dpavlin 30 #ifdef MODE32
4362     if (main_opcode == HI6_LW)
4363     cpu->cd.mips.combination_check = COMBINE(multi_lw);
4364     if (main_opcode == HI6_SW)
4365 dpavlin 28 cpu->cd.mips.combination_check = COMBINE(multi_sw);
4366 dpavlin 30 #endif
4367 dpavlin 24 break;
4368    
4369     case HI6_LL:
4370     case HI6_LLD:
4371     case HI6_SC:
4372     case HI6_SCD:
4373     /* 32-bit load-linked/store-condition for ISA II and up: */
4374     /* (64-bit load-linked/store-condition for ISA III...) */
4375     if (cpu->cd.mips.cpu_type.isa_level < 2) {
4376     ic->f = instr(reserved);
4377     break;
4378     }
4379    
4380     store = 0;
4381     switch (main_opcode) {
4382     case HI6_LL: ic->f = instr(ll); break;
4383     case HI6_LLD: ic->f = instr(lld); x64 = 1; break;
4384     case HI6_SC: ic->f = instr(sc); store = 1; break;
4385     case HI6_SCD: ic->f = instr(scd); store = 1; x64 = 1; break;
4386     }
4387     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4388     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4389     ic->arg[2] = (int32_t)imm;
4390     if (!store && rt == MIPS_GPR_ZERO) {
4391     fatal("HM... unusual load linked\n");
4392     goto bad;
4393     }
4394     break;
4395    
4396     case HI6_LWL:
4397     case HI6_LWR:
4398     case HI6_LDL:
4399     case HI6_LDR:
4400     case HI6_SWL:
4401     case HI6_SWR:
4402     case HI6_SDL:
4403     case HI6_SDR:
4404     /* TODO: replace these with faster versions... */
4405     store = 0;
4406     switch (main_opcode) {
4407     case HI6_LWL: ic->f = instr(lwl); break;
4408     case HI6_LWR: ic->f = instr(lwr); break;
4409     case HI6_LDL: ic->f = instr(ldl); x64 = 1; break;
4410     case HI6_LDR: ic->f = instr(ldr); x64 = 1; break;
4411     case HI6_SWL: ic->f = instr(swl); store = 1; break;
4412     case HI6_SWR: ic->f = instr(swr); store = 1; break;
4413     case HI6_SDL: ic->f = instr(sdl); store = 1; x64 = 1; break;
4414     case HI6_SDR: ic->f = instr(sdr); store = 1; x64 = 1; break;
4415     }
4416     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4417     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4418     ic->arg[2] = (int32_t)imm;
4419    
4420     /* Load into the dummy scratch register, if rt = zero */
4421     if (!store && rt == MIPS_GPR_ZERO)
4422     ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4423     break;
4424    
4425     case HI6_LWC1:
4426     case HI6_SWC1:
4427     case HI6_LDC1:
4428     case HI6_SDC1:
4429     /* 64-bit floating-point load/store for ISA II and up... */
4430     if ((main_opcode == HI6_LDC1 || main_opcode == HI6_SDC1)
4431     && cpu->cd.mips.cpu_type.isa_level < 2) {
4432     ic->f = instr(reserved);
4433     break;
4434     }
4435    
4436     ic->arg[0] = (size_t)&cpu->cd.mips.coproc[1]->reg[rt];
4437     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4438     ic->arg[2] = (int32_t)imm;
4439     switch (main_opcode) {
4440     case HI6_LWC1: ic->f = instr(lwc1); break;
4441     case HI6_LDC1: ic->f = instr(ldc1); break;
4442     case HI6_SWC1: ic->f = instr(swc1); break;
4443     case HI6_SDC1: ic->f = instr(sdc1); break;
4444     }
4445    
4446     /* Cause a coprocessor unusable exception if
4447     there is no floating point coprocessor: */
4448     if (cpu->cd.mips.cpu_type.flags & NOFPU ||
4449     cpu->cd.mips.coproc[1] == NULL) {
4450     ic->f = instr(cpu);
4451     ic->arg[0] = 1;
4452     }
4453     break;
4454    
4455     case HI6_LWC3:
4456     /* PREF (prefetch) on ISA IV and MIPS32/64: */
4457     if (cpu->cd.mips.cpu_type.isa_level >= 4) {
4458     /* Treat as nop for now: */
4459     ic->f = instr(nop);
4460     } else {
4461     fatal("TODO: lwc3 not implemented yet\n");
4462     goto bad;
4463     }
4464     break;
4465    
4466     case HI6_LQ_MDMX:
4467     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4468     fatal("TODO: R5900 128-bit loads\n");
4469     goto bad;
4470     }
4471    
4472     fatal("TODO: MDMX\n");
4473     goto bad;
4474     /* break */
4475    
4476     case HI6_SQ_SPECIAL3:
4477     if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4478     fatal("TODO: R5900 128-bit stores\n");
4479     goto bad;
4480     }
4481    
4482     if (cpu->cd.mips.cpu_type.isa_level < 32 ||
4483     cpu->cd.mips.cpu_type.isa_revision < 2) {
4484     static int warning = 0;
4485     if (!warning) {
4486 dpavlin 28 fatal("[ WARNING! SPECIAL3 opcode used, but"
4487     " the %s processor does not implement "
4488     "such instructions. Only printing this "
4489     "warning once. ]\n",
4490     cpu->cd.mips.cpu_type.name);
4491 dpavlin 24 warning = 1;
4492     }
4493     ic->f = instr(reserved);
4494     break;
4495     }
4496    
4497     switch (s6) {
4498    
4499 dpavlin 32 case SPECIAL3_EXT:
4500     /* TODO: Cleanup and extend to DEXT... etc */
4501     {
4502     int msbd = rd, lsb = (iword >> 6) & 0x1f;
4503     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4504     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4505     ic->arg[2] = (msbd << 5) + lsb;
4506     ic->f = instr(ext);
4507     if (rt == MIPS_GPR_ZERO)
4508     ic->f = instr(nop);
4509     }
4510     break;
4511    
4512     case SPECIAL3_BSHFL:
4513     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4514     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4515     switch (s10) {
4516     case BSHFL_WSBH:
4517     ic->f = instr(wsbh);
4518     break;
4519     case BSHFL_SEB:
4520     ic->f = instr(seb);
4521     break;
4522     case BSHFL_SEH:
4523     ic->f = instr(seh);
4524     break;
4525     default:goto bad;
4526     }
4527     break;
4528    
4529     case SPECIAL3_DBSHFL:
4530     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4531     ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4532     switch (s10) {
4533     case BSHFL_DSBH:
4534     ic->f = instr(dsbh);
4535     break;
4536     case BSHFL_DSHD:
4537     ic->f = instr(dshd);
4538     break;
4539     default:goto bad;
4540     }
4541     break;
4542    
4543 dpavlin 24 case SPECIAL3_RDHWR:
4544     ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4545    
4546     switch (rd) {
4547    
4548     case 0: ic->f = instr(rdhwr_cpunum);
4549     if (rt == MIPS_GPR_ZERO)
4550     ic->f = instr(nop);
4551     break;
4552    
4553     default:fatal("unimplemented rdhwr register rd=%i\n",
4554     rd);
4555     goto bad;
4556     }
4557     break;
4558    
4559     default:goto bad;
4560     }
4561     break;
4562    
4563     case HI6_CACHE:
4564     /* TODO: rt and op etc... */
4565     ic->f = instr(cache);
4566     break;
4567    
4568 dpavlin 22 default:goto bad;
4569     }
4570    
4571 dpavlin 34
4572 dpavlin 24 #ifdef MODE32
4573     if (x64) {
4574     static int has_warned = 0;
4575     if (!has_warned)
4576     fatal("[ WARNING/NOTE: attempt to execute a 64-bit"
4577     " instruction on an emulated 32-bit processor; "
4578     "pc=0x%08"PRIx32" ]\n", (uint32_t)cpu->pc);
4579     has_warned = 1;
4580     ic->f = instr(reserved);
4581     }
4582     #endif
4583 dpavlin 22
4584 dpavlin 34 #ifdef NATIVE_CODE_GENERATION
4585     /*
4586     * End the native code generation when an instruction is translated
4587     * (or found in the following slow) which is not translatable.
4588     */
4589     if (cpu->currently_translating_to_native && (!native ||
4590     (addr & 0xffc) == 0xffc ||
4591     cpu->cd.mips.next_ic->f != instr(to_be_translated))) {
4592     native_commit(cpu);
4593     }
4594     #endif
4595 dpavlin 22
4596 dpavlin 34
4597 dpavlin 22 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
4598     #include "cpu_dyntrans.c"
4599     #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
4600     }
4601    

  ViewVC Help
Powered by ViewVC 1.1.26