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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 34 - (show 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 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_mips_instr.c,v 1.124 2007/02/03 10:00:52 debug Exp $
29 *
30 * MIPS instructions.
31 *
32 * Individual functions should keep track of cpu->n_translated_instrs.
33 * (If no instruction was executed, then it should be decreased. If, say, 4
34 * instructions were combined into one function and executed, then it should
35 * be increased by 3.)
36 */
37
38
39 /*
40 * COPROC_AVAILABILITY_CHECK(n) checks for the coprocessor available bit for
41 * coprocessor number n, and causes a CoProcessor Unusable exception if it
42 * is not set. (Note: For coprocessor 0 checks, use cop0_availability_check!)
43 */
44 #ifndef COPROC_AVAILABILITY_CHECK
45 #define COPROC_AVAILABILITY_CHECK(x) { \
46 const int cpnr = (x); \
47 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) \
48 / sizeof(struct mips_instr_call); \
49 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) \
50 << MIPS_INSTR_ALIGNMENT_SHIFT); \
51 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); \
52 if (!(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & \
53 ((1 << cpnr) << STATUS_CU_SHIFT)) ) { \
54 mips_cpu_exception(cpu, EXCEPTION_CPU, \
55 0, 0, cpnr, 0, 0, 0); \
56 return; \
57 } \
58 }
59 #endif
60
61
62 #ifndef COP0_AVAILABILITY_CHECK_INCLUDED
63 #define COP0_AVAILABILITY_CHECK_INCLUDED
64 /*
65 * cop0_availability_check() causes a CoProcessor Unusable exception if
66 * we are currently running in usermode, and the coprocessor available bit
67 * for coprocessor 0 is not set.
68 *
69 * Returns 1 if ok (i.e. if the coprocessor was usable), 0 on exceptions.
70 */
71 int cop0_availability_check(struct cpu *cpu, struct mips_instr_call *ic)
72 {
73 int in_usermode = 0;
74 struct mips_coproc *cp0 = cpu->cd.mips.coproc[0];
75
76 switch (cpu->cd.mips.cpu_type.exc_model) {
77 case EXC3K:
78 /*
79 * NOTE: If the KU bit is checked, Linux crashes.
80 * It is the PC that counts.
81 *
82 * TODO: Check whether this is true or not for R4000 as well.
83 */
84 /* TODO: if (cp0->reg[COP0_STATUS] & MIPS1_SR_KU_CUR) */
85 if (cpu->pc <= 0x7fffffff)
86 in_usermode = 1;
87 break;
88 default:
89 /* R4000 etc: (TODO: How about supervisor mode?) */
90 if (((cp0->reg[COP0_STATUS] &
91 STATUS_KSU_MASK) >> STATUS_KSU_SHIFT) != KSU_KERNEL)
92 in_usermode = 1;
93 if (cp0->reg[COP0_STATUS] & (STATUS_ERL | STATUS_EXL))
94 in_usermode = 0;
95 break;
96 }
97
98 if (in_usermode) {
99 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
100 / sizeof(struct mips_instr_call);
101 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
102 << MIPS_INSTR_ALIGNMENT_SHIFT);
103 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
104 if (!(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &
105 (1 << STATUS_CU_SHIFT)) ) {
106 mips_cpu_exception(cpu, EXCEPTION_CPU,
107 0, 0, /* cpnr */ 0, 0, 0, 0);
108 return 0;
109 }
110 }
111
112 return 1;
113 }
114 #endif
115
116
117 /*
118 * invalid: For catching bugs.
119 */
120 X(invalid)
121 {
122 fatal("FATAL ERROR: An internal error occured in the MIPS"
123 " dyntrans code. Please contact the author with detailed"
124 " repro steps on how to trigger this bug.\n");
125 exit(1);
126 }
127
128
129 /*
130 * reserved: Attempt to execute a reserved instruction (e.g. a 64-bit
131 * instruction on an emulated 32-bit processor).
132 */
133 X(reserved)
134 {
135 /* Synchronize the PC and cause an exception: */
136 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
137 / sizeof(struct mips_instr_call);
138 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
139 << MIPS_INSTR_ALIGNMENT_SHIFT);
140 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
141 mips_cpu_exception(cpu, EXCEPTION_RI, 0, 0, 0, 0, 0, 0);
142 }
143
144
145 /*
146 * cpu: Cause a CoProcessor Unusable exception.
147 *
148 * arg[0] = the number of the coprocessor
149 */
150 X(cpu)
151 {
152 /* Synchronize the PC and cause an exception: */
153 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
154 / sizeof(struct mips_instr_call);
155 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
156 << MIPS_INSTR_ALIGNMENT_SHIFT);
157 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
158 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, ic->arg[0], 0, 0, 0);
159 }
160
161
162 /*
163 * nop: Do nothing.
164 */
165 X(nop)
166 {
167 }
168
169
170 /*
171 * beq: Branch if equal
172 * bne: Branch if not equal
173 * b: Branch (comparing a register to itself, always true)
174 *
175 * arg[0] = pointer to rs
176 * arg[1] = pointer to rt
177 * arg[2] = (int32_t) relative offset from the next instruction
178 */
179 X(beq)
180 {
181 MODE_int_t old_pc = cpu->pc;
182 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
183 int x = rs == rt;
184 cpu->delay_slot = TO_BE_DELAYED;
185 ic[1].f(cpu, ic+1);
186 cpu->n_translated_instrs ++;
187 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
188 /* Note: Must be non-delayed when jumping to the new pc: */
189 cpu->delay_slot = NOT_DELAYED;
190 if (x) {
191 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
192 MIPS_INSTR_ALIGNMENT_SHIFT);
193 cpu->pc = old_pc + (int32_t)ic->arg[2];
194 quick_pc_to_pointers(cpu);
195 } else
196 cpu->cd.mips.next_ic ++;
197 } else
198 cpu->delay_slot = NOT_DELAYED;
199 }
200 X(beq_samepage)
201 {
202 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
203 int x = rs == rt;
204 cpu->delay_slot = TO_BE_DELAYED;
205 ic[1].f(cpu, ic+1);
206 cpu->n_translated_instrs ++;
207 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
208 if (x)
209 cpu->cd.mips.next_ic = (struct mips_instr_call *)
210 ic->arg[2];
211 else
212 cpu->cd.mips.next_ic ++;
213 }
214 cpu->delay_slot = NOT_DELAYED;
215 }
216 X(beq_samepage_addiu)
217 {
218 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
219 cpu->n_translated_instrs ++;
220 reg(ic[1].arg[1]) = (int32_t)
221 ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
222 if (rs == rt)
223 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
224 else
225 cpu->cd.mips.next_ic ++;
226 }
227 X(beq_samepage_nop)
228 {
229 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
230 cpu->n_translated_instrs ++;
231 if (rs == rt)
232 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
233 else
234 cpu->cd.mips.next_ic ++;
235 }
236 X(bne)
237 {
238 MODE_int_t old_pc = cpu->pc;
239 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
240 int x = rs != rt;
241 cpu->delay_slot = TO_BE_DELAYED;
242 ic[1].f(cpu, ic+1);
243 cpu->n_translated_instrs ++;
244 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
245 /* Note: Must be non-delayed when jumping to the new pc: */
246 cpu->delay_slot = NOT_DELAYED;
247 if (x) {
248 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
249 MIPS_INSTR_ALIGNMENT_SHIFT);
250 cpu->pc = old_pc + (int32_t)ic->arg[2];
251 quick_pc_to_pointers(cpu);
252 } else
253 cpu->cd.mips.next_ic ++;
254 } else
255 cpu->delay_slot = NOT_DELAYED;
256 }
257 X(bne_samepage)
258 {
259 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
260 int x = rs != rt;
261 cpu->delay_slot = TO_BE_DELAYED;
262 ic[1].f(cpu, ic+1);
263 cpu->n_translated_instrs ++;
264 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
265 if (x)
266 cpu->cd.mips.next_ic = (struct mips_instr_call *)
267 ic->arg[2];
268 else
269 cpu->cd.mips.next_ic ++;
270 }
271 cpu->delay_slot = NOT_DELAYED;
272 }
273 X(bne_samepage_addiu)
274 {
275 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
276 cpu->n_translated_instrs ++;
277 reg(ic[1].arg[1]) = (int32_t)
278 ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
279 if (rs != rt)
280 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
281 else
282 cpu->cd.mips.next_ic ++;
283 }
284 X(bne_samepage_nop)
285 {
286 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
287 cpu->n_translated_instrs ++;
288 if (rs != rt)
289 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
290 else
291 cpu->cd.mips.next_ic ++;
292 }
293 X(b)
294 {
295 MODE_int_t old_pc = cpu->pc;
296 cpu->delay_slot = TO_BE_DELAYED;
297 ic[1].f(cpu, ic+1);
298 cpu->n_translated_instrs ++;
299 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
300 /* Note: Must be non-delayed when jumping to the new pc: */
301 cpu->delay_slot = NOT_DELAYED;
302 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
303 MIPS_INSTR_ALIGNMENT_SHIFT);
304 cpu->pc = old_pc + (int32_t)ic->arg[2];
305 quick_pc_to_pointers(cpu);
306 } else
307 cpu->delay_slot = NOT_DELAYED;
308 }
309 X(b_samepage)
310 {
311 cpu->delay_slot = TO_BE_DELAYED;
312 ic[1].f(cpu, ic+1);
313 cpu->n_translated_instrs ++;
314 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT))
315 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
316 cpu->delay_slot = NOT_DELAYED;
317 }
318
319
320 /*
321 * beql: Branch if equal likely
322 * bnel: Branch if not equal likely
323 *
324 * arg[0] = pointer to rs
325 * arg[1] = pointer to rt
326 * arg[2] = (int32_t) relative offset from the next instruction
327 */
328 X(beql)
329 {
330 MODE_int_t old_pc = cpu->pc;
331 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
332 int x = rs == rt;
333 cpu->delay_slot = TO_BE_DELAYED;
334 if (x)
335 ic[1].f(cpu, ic+1);
336 cpu->n_translated_instrs ++;
337 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
338 /* Note: Must be non-delayed when jumping to the new pc: */
339 cpu->delay_slot = NOT_DELAYED;
340 if (x) {
341 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
342 MIPS_INSTR_ALIGNMENT_SHIFT);
343 cpu->pc = old_pc + (int32_t)ic->arg[2];
344 quick_pc_to_pointers(cpu);
345 } else
346 cpu->cd.mips.next_ic ++;
347 } else
348 cpu->delay_slot = NOT_DELAYED;
349 }
350 X(beql_samepage)
351 {
352 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
353 int x = rs == rt;
354 cpu->delay_slot = TO_BE_DELAYED;
355 if (x)
356 ic[1].f(cpu, ic+1);
357 cpu->n_translated_instrs ++;
358 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
359 if (x)
360 cpu->cd.mips.next_ic = (struct mips_instr_call *)
361 ic->arg[2];
362 else
363 cpu->cd.mips.next_ic ++;
364 }
365 cpu->delay_slot = NOT_DELAYED;
366 }
367 X(bnel)
368 {
369 MODE_int_t old_pc = cpu->pc;
370 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
371 int x = rs != rt;
372 cpu->delay_slot = TO_BE_DELAYED;
373 if (x)
374 ic[1].f(cpu, ic+1);
375 cpu->n_translated_instrs ++;
376 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
377 /* Note: Must be non-delayed when jumping to the new pc: */
378 cpu->delay_slot = NOT_DELAYED;
379 if (x) {
380 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
381 MIPS_INSTR_ALIGNMENT_SHIFT);
382 cpu->pc = old_pc + (int32_t)ic->arg[2];
383 quick_pc_to_pointers(cpu);
384 } else
385 cpu->cd.mips.next_ic ++;
386 } else
387 cpu->delay_slot = NOT_DELAYED;
388 }
389 X(bnel_samepage)
390 {
391 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
392 int x = rs != rt;
393 cpu->delay_slot = TO_BE_DELAYED;
394 if (x)
395 ic[1].f(cpu, ic+1);
396 cpu->n_translated_instrs ++;
397 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
398 if (x)
399 cpu->cd.mips.next_ic = (struct mips_instr_call *)
400 ic->arg[2];
401 else
402 cpu->cd.mips.next_ic ++;
403 }
404 cpu->delay_slot = NOT_DELAYED;
405 }
406
407
408 /*
409 * blez: Branch if less than or equal
410 * blezl: Branch if less than or equal likely
411 *
412 * arg[0] = pointer to rs
413 * arg[2] = (int32_t) relative offset from the next instruction
414 */
415 X(blez)
416 {
417 MODE_int_t old_pc = cpu->pc;
418 MODE_int_t rs = reg(ic->arg[0]);
419 int x = (rs <= 0);
420 cpu->delay_slot = TO_BE_DELAYED;
421 ic[1].f(cpu, ic+1);
422 cpu->n_translated_instrs ++;
423 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
424 /* Note: Must be non-delayed when jumping to the new pc: */
425 cpu->delay_slot = NOT_DELAYED;
426 if (x) {
427 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
428 MIPS_INSTR_ALIGNMENT_SHIFT);
429 cpu->pc = old_pc + (int32_t)ic->arg[2];
430 quick_pc_to_pointers(cpu);
431 } else
432 cpu->cd.mips.next_ic ++;
433 } else
434 cpu->delay_slot = NOT_DELAYED;
435 }
436 X(blez_samepage)
437 {
438 MODE_int_t rs = reg(ic->arg[0]);
439 int x = (rs <= 0);
440 cpu->delay_slot = TO_BE_DELAYED;
441 ic[1].f(cpu, ic+1);
442 cpu->n_translated_instrs ++;
443 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
444 if (x)
445 cpu->cd.mips.next_ic = (struct mips_instr_call *)
446 ic->arg[2];
447 else
448 cpu->cd.mips.next_ic ++;
449 }
450 cpu->delay_slot = NOT_DELAYED;
451 }
452 X(blezl)
453 {
454 MODE_int_t old_pc = cpu->pc;
455 MODE_int_t rs = reg(ic->arg[0]);
456 int x = (rs <= 0);
457 cpu->delay_slot = TO_BE_DELAYED;
458 if (x)
459 ic[1].f(cpu, ic+1);
460 cpu->n_translated_instrs ++;
461 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
462 /* Note: Must be non-delayed when jumping to the new pc: */
463 cpu->delay_slot = NOT_DELAYED;
464 if (x) {
465 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
466 MIPS_INSTR_ALIGNMENT_SHIFT);
467 cpu->pc = old_pc + (int32_t)ic->arg[2];
468 quick_pc_to_pointers(cpu);
469 } else
470 cpu->cd.mips.next_ic ++;
471 } else
472 cpu->delay_slot = NOT_DELAYED;
473 }
474 X(blezl_samepage)
475 {
476 MODE_int_t rs = reg(ic->arg[0]);
477 int x = (rs <= 0);
478 cpu->delay_slot = TO_BE_DELAYED;
479 if (x)
480 ic[1].f(cpu, ic+1);
481 cpu->n_translated_instrs ++;
482 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
483 if (x)
484 cpu->cd.mips.next_ic = (struct mips_instr_call *)
485 ic->arg[2];
486 else
487 cpu->cd.mips.next_ic ++;
488 }
489 cpu->delay_slot = NOT_DELAYED;
490 }
491
492
493 /*
494 * bltz: Branch if less than
495 * bltzl: Branch if less than likely
496 *
497 * arg[0] = pointer to rs
498 * arg[2] = (int32_t) relative offset from the next instruction
499 */
500 X(bltz)
501 {
502 MODE_int_t old_pc = cpu->pc;
503 MODE_int_t rs = reg(ic->arg[0]);
504 int x = (rs < 0);
505 cpu->delay_slot = TO_BE_DELAYED;
506 ic[1].f(cpu, ic+1);
507 cpu->n_translated_instrs ++;
508 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
509 /* Note: Must be non-delayed when jumping to the new pc: */
510 cpu->delay_slot = NOT_DELAYED;
511 if (x) {
512 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
513 MIPS_INSTR_ALIGNMENT_SHIFT);
514 cpu->pc = old_pc + (int32_t)ic->arg[2];
515 quick_pc_to_pointers(cpu);
516 } else
517 cpu->cd.mips.next_ic ++;
518 } else
519 cpu->delay_slot = NOT_DELAYED;
520 }
521 X(bltz_samepage)
522 {
523 MODE_int_t rs = reg(ic->arg[0]);
524 int x = (rs < 0);
525 cpu->delay_slot = TO_BE_DELAYED;
526 ic[1].f(cpu, ic+1);
527 cpu->n_translated_instrs ++;
528 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
529 if (x)
530 cpu->cd.mips.next_ic = (struct mips_instr_call *)
531 ic->arg[2];
532 else
533 cpu->cd.mips.next_ic ++;
534 }
535 cpu->delay_slot = NOT_DELAYED;
536 }
537 X(bltzl)
538 {
539 MODE_int_t old_pc = cpu->pc;
540 MODE_int_t rs = reg(ic->arg[0]);
541 int x = (rs < 0);
542 cpu->delay_slot = TO_BE_DELAYED;
543 if (x)
544 ic[1].f(cpu, ic+1);
545 cpu->n_translated_instrs ++;
546 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
547 /* Note: Must be non-delayed when jumping to the new pc: */
548 cpu->delay_slot = NOT_DELAYED;
549 if (x) {
550 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
551 MIPS_INSTR_ALIGNMENT_SHIFT);
552 cpu->pc = old_pc + (int32_t)ic->arg[2];
553 quick_pc_to_pointers(cpu);
554 } else
555 cpu->cd.mips.next_ic ++;
556 } else
557 cpu->delay_slot = NOT_DELAYED;
558 }
559 X(bltzl_samepage)
560 {
561 MODE_int_t rs = reg(ic->arg[0]);
562 int x = (rs < 0);
563 cpu->delay_slot = TO_BE_DELAYED;
564 if (x)
565 ic[1].f(cpu, ic+1);
566 cpu->n_translated_instrs ++;
567 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
568 if (x)
569 cpu->cd.mips.next_ic = (struct mips_instr_call *)
570 ic->arg[2];
571 else
572 cpu->cd.mips.next_ic ++;
573 }
574 cpu->delay_slot = NOT_DELAYED;
575 }
576
577
578 /*
579 * bgez: Branch if greater than or equal
580 * bgezl: Branch if greater than or equal likely
581 *
582 * arg[0] = pointer to rs
583 * arg[2] = (int32_t) relative offset from the next instruction
584 */
585 X(bgez)
586 {
587 MODE_int_t old_pc = cpu->pc;
588 MODE_int_t rs = reg(ic->arg[0]);
589 int x = (rs >= 0);
590 cpu->delay_slot = TO_BE_DELAYED;
591 ic[1].f(cpu, ic+1);
592 cpu->n_translated_instrs ++;
593 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
594 /* Note: Must be non-delayed when jumping to the new pc: */
595 cpu->delay_slot = NOT_DELAYED;
596 if (x) {
597 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
598 MIPS_INSTR_ALIGNMENT_SHIFT);
599 cpu->pc = old_pc + (int32_t)ic->arg[2];
600 quick_pc_to_pointers(cpu);
601 } else
602 cpu->cd.mips.next_ic ++;
603 } else
604 cpu->delay_slot = NOT_DELAYED;
605 }
606 X(bgez_samepage)
607 {
608 MODE_int_t rs = reg(ic->arg[0]);
609 int x = (rs >= 0);
610 cpu->delay_slot = TO_BE_DELAYED;
611 ic[1].f(cpu, ic+1);
612 cpu->n_translated_instrs ++;
613 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
614 if (x)
615 cpu->cd.mips.next_ic = (struct mips_instr_call *)
616 ic->arg[2];
617 else
618 cpu->cd.mips.next_ic ++;
619 }
620 cpu->delay_slot = NOT_DELAYED;
621 }
622 X(bgezl)
623 {
624 MODE_int_t old_pc = cpu->pc;
625 MODE_int_t rs = reg(ic->arg[0]);
626 int x = (rs >= 0);
627 cpu->delay_slot = TO_BE_DELAYED;
628 if (x)
629 ic[1].f(cpu, ic+1);
630 cpu->n_translated_instrs ++;
631 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
632 /* Note: Must be non-delayed when jumping to the new pc: */
633 cpu->delay_slot = NOT_DELAYED;
634 if (x) {
635 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
636 MIPS_INSTR_ALIGNMENT_SHIFT);
637 cpu->pc = old_pc + (int32_t)ic->arg[2];
638 quick_pc_to_pointers(cpu);
639 } else
640 cpu->cd.mips.next_ic ++;
641 } else
642 cpu->delay_slot = NOT_DELAYED;
643 }
644 X(bgezl_samepage)
645 {
646 MODE_int_t rs = reg(ic->arg[0]);
647 int x = (rs >= 0);
648 cpu->delay_slot = TO_BE_DELAYED;
649 if (x)
650 ic[1].f(cpu, ic+1);
651 cpu->n_translated_instrs ++;
652 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
653 if (x)
654 cpu->cd.mips.next_ic = (struct mips_instr_call *)
655 ic->arg[2];
656 else
657 cpu->cd.mips.next_ic ++;
658 }
659 cpu->delay_slot = NOT_DELAYED;
660 }
661
662
663 /*
664 * bgezal: Branch if greater than or equal (and link)
665 * bgezall: Branch if greater than or equal (and link) likely
666 *
667 * arg[0] = pointer to rs
668 * arg[2] = (int32_t) relative offset from the next instruction
669 */
670 X(bgezal)
671 {
672 MODE_int_t old_pc = cpu->pc;
673 MODE_int_t rs = reg(ic->arg[0]);
674 int x = (rs >= 0), low_pc;
675
676 cpu->delay_slot = TO_BE_DELAYED;
677 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
678 / sizeof(struct mips_instr_call);
679 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
680 << MIPS_INSTR_ALIGNMENT_SHIFT);
681 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
682 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
683
684 ic[1].f(cpu, ic+1);
685 cpu->n_translated_instrs ++;
686 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
687 /* Note: Must be non-delayed when jumping to the new pc: */
688 cpu->delay_slot = NOT_DELAYED;
689 if (x) {
690 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
691 MIPS_INSTR_ALIGNMENT_SHIFT);
692 cpu->pc = old_pc + (int32_t)ic->arg[2];
693 quick_pc_to_pointers(cpu);
694 } else
695 cpu->cd.mips.next_ic ++;
696 } else
697 cpu->delay_slot = NOT_DELAYED;
698 }
699 X(bgezal_samepage)
700 {
701 MODE_int_t rs = reg(ic->arg[0]);
702 int x = (rs >= 0), low_pc;
703
704 cpu->delay_slot = TO_BE_DELAYED;
705 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
706 / sizeof(struct mips_instr_call);
707 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
708 << MIPS_INSTR_ALIGNMENT_SHIFT);
709 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
710 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
711
712 ic[1].f(cpu, ic+1);
713 cpu->n_translated_instrs ++;
714 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
715 if (x)
716 cpu->cd.mips.next_ic = (struct mips_instr_call *)
717 ic->arg[2];
718 else
719 cpu->cd.mips.next_ic ++;
720 }
721 cpu->delay_slot = NOT_DELAYED;
722 }
723 X(bgezall)
724 {
725 MODE_int_t old_pc = cpu->pc;
726 MODE_int_t rs = reg(ic->arg[0]);
727 int x = (rs >= 0), low_pc;
728
729 cpu->delay_slot = TO_BE_DELAYED;
730 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
731 / sizeof(struct mips_instr_call);
732 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
733 << MIPS_INSTR_ALIGNMENT_SHIFT);
734 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
735 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
736
737 if (x)
738 ic[1].f(cpu, ic+1);
739 cpu->n_translated_instrs ++;
740 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
741 /* Note: Must be non-delayed when jumping to the new pc: */
742 cpu->delay_slot = NOT_DELAYED;
743 if (x) {
744 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
745 MIPS_INSTR_ALIGNMENT_SHIFT);
746 cpu->pc = old_pc + (int32_t)ic->arg[2];
747 quick_pc_to_pointers(cpu);
748 } else
749 cpu->cd.mips.next_ic ++;
750 } else
751 cpu->delay_slot = NOT_DELAYED;
752 }
753 X(bgezall_samepage)
754 {
755 MODE_int_t rs = reg(ic->arg[0]);
756 int x = (rs >= 0), low_pc;
757
758 cpu->delay_slot = TO_BE_DELAYED;
759 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
760 / sizeof(struct mips_instr_call);
761 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
762 << MIPS_INSTR_ALIGNMENT_SHIFT);
763 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
764 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
765
766 if (x)
767 ic[1].f(cpu, ic+1);
768 cpu->n_translated_instrs ++;
769 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
770 if (x)
771 cpu->cd.mips.next_ic = (struct mips_instr_call *)
772 ic->arg[2];
773 else
774 cpu->cd.mips.next_ic ++;
775 }
776 cpu->delay_slot = NOT_DELAYED;
777 }
778
779
780 /*
781 * bltzal: Branch if less than zero (and link)
782 * bltzall: Branch if less than zero (and link) likely
783 *
784 * arg[0] = pointer to rs
785 * arg[2] = (int32_t) relative offset from the next instruction
786 */
787 X(bltzal)
788 {
789 MODE_int_t old_pc = cpu->pc;
790 MODE_int_t rs = reg(ic->arg[0]);
791 int x = (rs < 0), low_pc;
792
793 cpu->delay_slot = TO_BE_DELAYED;
794 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
795 / sizeof(struct mips_instr_call);
796 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
797 << MIPS_INSTR_ALIGNMENT_SHIFT);
798 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
799 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
800
801 ic[1].f(cpu, ic+1);
802 cpu->n_translated_instrs ++;
803 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
804 /* Note: Must be non-delayed when jumping to the new pc: */
805 cpu->delay_slot = NOT_DELAYED;
806 if (x) {
807 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
808 MIPS_INSTR_ALIGNMENT_SHIFT);
809 cpu->pc = old_pc + (int32_t)ic->arg[2];
810 quick_pc_to_pointers(cpu);
811 } else
812 cpu->cd.mips.next_ic ++;
813 } else
814 cpu->delay_slot = NOT_DELAYED;
815 }
816 X(bltzal_samepage)
817 {
818 MODE_int_t rs = reg(ic->arg[0]);
819 int x = (rs < 0), low_pc;
820
821 cpu->delay_slot = TO_BE_DELAYED;
822 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
823 / sizeof(struct mips_instr_call);
824 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
825 << MIPS_INSTR_ALIGNMENT_SHIFT);
826 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
827 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
828
829 ic[1].f(cpu, ic+1);
830 cpu->n_translated_instrs ++;
831 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
832 if (x)
833 cpu->cd.mips.next_ic = (struct mips_instr_call *)
834 ic->arg[2];
835 else
836 cpu->cd.mips.next_ic ++;
837 }
838 cpu->delay_slot = NOT_DELAYED;
839 }
840 X(bltzall)
841 {
842 MODE_int_t old_pc = cpu->pc;
843 MODE_int_t rs = reg(ic->arg[0]);
844 int x = (rs < 0), low_pc;
845
846 cpu->delay_slot = TO_BE_DELAYED;
847 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
848 / sizeof(struct mips_instr_call);
849 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
850 << MIPS_INSTR_ALIGNMENT_SHIFT);
851 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
852 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
853
854 if (x)
855 ic[1].f(cpu, ic+1);
856 cpu->n_translated_instrs ++;
857 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
858 /* Note: Must be non-delayed when jumping to the new pc: */
859 cpu->delay_slot = NOT_DELAYED;
860 if (x) {
861 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
862 MIPS_INSTR_ALIGNMENT_SHIFT);
863 cpu->pc = old_pc + (int32_t)ic->arg[2];
864 quick_pc_to_pointers(cpu);
865 } else
866 cpu->cd.mips.next_ic ++;
867 } else
868 cpu->delay_slot = NOT_DELAYED;
869 }
870 X(bltzall_samepage)
871 {
872 MODE_int_t rs = reg(ic->arg[0]);
873 int x = (rs < 0), low_pc;
874
875 cpu->delay_slot = TO_BE_DELAYED;
876 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
877 / sizeof(struct mips_instr_call);
878 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
879 << MIPS_INSTR_ALIGNMENT_SHIFT);
880 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
881 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
882
883 if (x)
884 ic[1].f(cpu, ic+1);
885 cpu->n_translated_instrs ++;
886 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
887 if (x)
888 cpu->cd.mips.next_ic = (struct mips_instr_call *)
889 ic->arg[2];
890 else
891 cpu->cd.mips.next_ic ++;
892 }
893 cpu->delay_slot = NOT_DELAYED;
894 }
895
896
897 /*
898 * bgtz: Branch if greater than zero
899 * bgtzl: Branch if greater than zero likely
900 *
901 * arg[0] = pointer to rs
902 * arg[2] = (int32_t) relative offset from the next instruction
903 */
904 X(bgtz)
905 {
906 MODE_int_t old_pc = cpu->pc;
907 MODE_int_t rs = reg(ic->arg[0]);
908 int x = (rs > 0);
909 cpu->delay_slot = TO_BE_DELAYED;
910 ic[1].f(cpu, ic+1);
911 cpu->n_translated_instrs ++;
912 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
913 /* Note: Must be non-delayed when jumping to the new pc: */
914 cpu->delay_slot = NOT_DELAYED;
915 if (x) {
916 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
917 MIPS_INSTR_ALIGNMENT_SHIFT);
918 cpu->pc = old_pc + (int32_t)ic->arg[2];
919 quick_pc_to_pointers(cpu);
920 } else
921 cpu->cd.mips.next_ic ++;
922 } else
923 cpu->delay_slot = NOT_DELAYED;
924 }
925 X(bgtz_samepage)
926 {
927 MODE_int_t rs = reg(ic->arg[0]);
928 int x = (rs > 0);
929 cpu->delay_slot = TO_BE_DELAYED;
930 ic[1].f(cpu, ic+1);
931 cpu->n_translated_instrs ++;
932 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
933 if (x)
934 cpu->cd.mips.next_ic = (struct mips_instr_call *)
935 ic->arg[2];
936 else
937 cpu->cd.mips.next_ic ++;
938 }
939 cpu->delay_slot = NOT_DELAYED;
940 }
941 X(bgtzl)
942 {
943 MODE_int_t old_pc = cpu->pc;
944 MODE_int_t rs = reg(ic->arg[0]);
945 int x = (rs > 0);
946 cpu->delay_slot = TO_BE_DELAYED;
947 if (x)
948 ic[1].f(cpu, ic+1);
949 cpu->n_translated_instrs ++;
950 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
951 /* Note: Must be non-delayed when jumping to the new pc: */
952 cpu->delay_slot = NOT_DELAYED;
953 if (x) {
954 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
955 MIPS_INSTR_ALIGNMENT_SHIFT);
956 cpu->pc = old_pc + (int32_t)ic->arg[2];
957 quick_pc_to_pointers(cpu);
958 } else
959 cpu->cd.mips.next_ic ++;
960 } else
961 cpu->delay_slot = NOT_DELAYED;
962 }
963 X(bgtzl_samepage)
964 {
965 MODE_int_t rs = reg(ic->arg[0]);
966 int x = (rs > 0);
967 cpu->delay_slot = TO_BE_DELAYED;
968 if (x)
969 ic[1].f(cpu, ic+1);
970 cpu->n_translated_instrs ++;
971 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
972 if (x)
973 cpu->cd.mips.next_ic = (struct mips_instr_call *)
974 ic->arg[2];
975 else
976 cpu->cd.mips.next_ic ++;
977 }
978 cpu->delay_slot = NOT_DELAYED;
979 }
980
981
982 /*
983 * jr, jalr: Jump to a register [and link].
984 *
985 * arg[0] = ptr to rs
986 * arg[1] = ptr to rd (for jalr)
987 * arg[2] = (int32_t) relative offset of the next instruction
988 */
989 X(jr)
990 {
991 MODE_int_t rs = reg(ic->arg[0]);
992 cpu->delay_slot = TO_BE_DELAYED;
993 ic[1].f(cpu, ic+1);
994 cpu->n_translated_instrs ++;
995 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
996 cpu->pc = rs;
997 /* Note: Must be non-delayed when jumping to the new pc: */
998 cpu->delay_slot = NOT_DELAYED;
999 quick_pc_to_pointers(cpu);
1000 } else
1001 cpu->delay_slot = NOT_DELAYED;
1002 }
1003 X(jr_ra)
1004 {
1005 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
1006 cpu->delay_slot = TO_BE_DELAYED;
1007 ic[1].f(cpu, ic+1);
1008 cpu->n_translated_instrs ++;
1009 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1010 cpu->pc = rs;
1011 /* Note: Must be non-delayed when jumping to the new pc: */
1012 cpu->delay_slot = NOT_DELAYED;
1013 quick_pc_to_pointers(cpu);
1014 } else
1015 cpu->delay_slot = NOT_DELAYED;
1016 }
1017 X(jr_ra_addiu)
1018 {
1019 /* jr ra, followed by an addiu */
1020 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
1021 reg(ic[1].arg[1]) = (int32_t)
1022 ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
1023 cpu->pc = rs;
1024 quick_pc_to_pointers(cpu);
1025 cpu->n_translated_instrs ++;
1026 }
1027 X(jr_ra_trace)
1028 {
1029 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
1030 cpu->delay_slot = TO_BE_DELAYED;
1031 ic[1].f(cpu, ic+1);
1032 cpu->n_translated_instrs ++;
1033 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1034 cpu->pc = rs;
1035 cpu_functioncall_trace_return(cpu);
1036 /* Note: Must be non-delayed when jumping to the new pc: */
1037 cpu->delay_slot = NOT_DELAYED;
1038 quick_pc_to_pointers(cpu);
1039 } else
1040 cpu->delay_slot = NOT_DELAYED;
1041 }
1042 X(jalr)
1043 {
1044 MODE_int_t rs = reg(ic->arg[0]), rd;
1045 cpu->delay_slot = TO_BE_DELAYED;
1046 rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1047 MIPS_INSTR_ALIGNMENT_SHIFT);
1048 rd += (int32_t)ic->arg[2];
1049 reg(ic->arg[1]) = rd;
1050 ic[1].f(cpu, ic+1);
1051 cpu->n_translated_instrs ++;
1052 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1053 cpu->pc = rs;
1054 /* Note: Must be non-delayed when jumping to the new pc: */
1055 cpu->delay_slot = NOT_DELAYED;
1056 quick_pc_to_pointers(cpu);
1057 } else
1058 cpu->delay_slot = NOT_DELAYED;
1059 }
1060 X(jalr_trace)
1061 {
1062 MODE_int_t rs = reg(ic->arg[0]), rd;
1063 cpu->delay_slot = TO_BE_DELAYED;
1064 rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1065 MIPS_INSTR_ALIGNMENT_SHIFT);
1066 rd += (int32_t)ic->arg[2];
1067 reg(ic->arg[1]) = rd;
1068 ic[1].f(cpu, ic+1);
1069 cpu->n_translated_instrs ++;
1070 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1071 cpu->pc = rs;
1072 cpu_functioncall_trace(cpu, cpu->pc);
1073 /* Note: Must be non-delayed when jumping to the new pc: */
1074 cpu->delay_slot = NOT_DELAYED;
1075 quick_pc_to_pointers(cpu);
1076 } else
1077 cpu->delay_slot = NOT_DELAYED;
1078 }
1079
1080
1081 /*
1082 * j, jal: Jump [and link].
1083 *
1084 * arg[0] = lowest 28 bits of new pc.
1085 * arg[1] = offset from start of page to the jal instruction + 8
1086 */
1087 X(j)
1088 {
1089 MODE_int_t old_pc = cpu->pc;
1090 cpu->delay_slot = TO_BE_DELAYED;
1091 ic[1].f(cpu, ic+1);
1092 cpu->n_translated_instrs ++;
1093 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1094 /* Note: Must be non-delayed when jumping to the new pc: */
1095 cpu->delay_slot = NOT_DELAYED;
1096 old_pc &= ~0x03ffffff;
1097 cpu->pc = old_pc | (uint32_t)ic->arg[0];
1098 quick_pc_to_pointers(cpu);
1099 } else
1100 cpu->delay_slot = NOT_DELAYED;
1101 }
1102 X(jal)
1103 {
1104 MODE_int_t old_pc = cpu->pc;
1105 cpu->delay_slot = TO_BE_DELAYED;
1106 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1107 cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
1108 ic[1].f(cpu, ic+1);
1109 cpu->n_translated_instrs ++;
1110 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1111 /* Note: Must be non-delayed when jumping to the new pc: */
1112 cpu->delay_slot = NOT_DELAYED;
1113 old_pc &= ~0x03ffffff;
1114 cpu->pc = old_pc | (int32_t)ic->arg[0];
1115 quick_pc_to_pointers(cpu);
1116 } else
1117 cpu->delay_slot = NOT_DELAYED;
1118 }
1119 X(jal_trace)
1120 {
1121 MODE_int_t old_pc = cpu->pc;
1122 cpu->delay_slot = TO_BE_DELAYED;
1123 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1124 cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
1125 ic[1].f(cpu, ic+1);
1126 cpu->n_translated_instrs ++;
1127 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1128 /* Note: Must be non-delayed when jumping to the new pc: */
1129 cpu->delay_slot = NOT_DELAYED;
1130 old_pc &= ~0x03ffffff;
1131 cpu->pc = old_pc | (int32_t)ic->arg[0];
1132 cpu_functioncall_trace(cpu, cpu->pc);
1133 quick_pc_to_pointers(cpu);
1134 } else
1135 cpu->delay_slot = NOT_DELAYED;
1136 }
1137
1138
1139 /*
1140 * cache: Cache operation.
1141 */
1142 X(cache)
1143 {
1144 /* TODO: Implement cache operations. */
1145
1146 /* Make sure the rmw bit is cleared: */
1147 cpu->cd.mips.rmw = 0;
1148 }
1149
1150
1151 /*
1152 * ext: Extract bitfield.
1153 *
1154 * arg[0] = pointer to rt
1155 * arg[1] = pointer to rs
1156 * arg[2] = (msbd << 5) + lsb
1157 */
1158 X(ext)
1159 {
1160 fatal("ext: todo\n");
1161 exit(1);
1162 }
1163
1164
1165 /*
1166 * dsbh: Doubleword swap bytes within half-word
1167 * dshd: Doubleword swap half-words within double-word
1168 * wsbh: Word swap bytes within half-word
1169 * seb: Sign-extend byte
1170 * seh: Sign-extend half-word
1171 *
1172 * arg[0] = pointer to rt
1173 * arg[1] = pointer to rd
1174 */
1175 X(dsbh)
1176 {
1177 uint64_t x = reg(ic->arg[0]);
1178 x = ((x & 0x00ff00ff00ff00ffULL) << 8)
1179 | ((x & 0xff00ff00ff00ff00ULL) >> 8);
1180 reg(ic->arg[1]) = x;
1181 }
1182 X(dshd)
1183 {
1184 uint64_t x = reg(ic->arg[0]);
1185 x = ((x & 0x000000000000ffffULL) << 48)
1186 | ((x & 0x00000000ffff0000ULL) << 16)
1187 | ((x & 0x0000ffff00000000ULL) >> 16)
1188 | ((x & 0xffff000000000000ULL) >> 48);
1189 reg(ic->arg[1]) = x;
1190 }
1191 X(wsbh)
1192 {
1193 uint32_t x = reg(ic->arg[0]);
1194 x = ((x & 0x00ff00ff) << 8) | ((x & 0xff00ff00) >> 8);
1195 reg(ic->arg[1]) = (int32_t) x;
1196 }
1197 X(seb) { reg(ic->arg[1]) = (int8_t)reg(ic->arg[0]); }
1198 X(seh) { reg(ic->arg[1]) = (int16_t)reg(ic->arg[0]); }
1199
1200
1201 /*
1202 * 2-register + immediate:
1203 *
1204 * arg[0] = pointer to rs
1205 * arg[1] = pointer to rt
1206 * arg[2] = uint32_t immediate value
1207 */
1208 X(andi) { reg(ic->arg[1]) = reg(ic->arg[0]) & (uint32_t)ic->arg[2]; }
1209 X(ori) { reg(ic->arg[1]) = reg(ic->arg[0]) | (uint32_t)ic->arg[2]; }
1210 X(xori) { reg(ic->arg[1]) = reg(ic->arg[0]) ^ (uint32_t)ic->arg[2]; }
1211
1212
1213 /*
1214 * 2-register:
1215 *
1216 * arg[0] = ptr to rs
1217 * arg[1] = ptr to rt
1218 */
1219 X(div)
1220 {
1221 int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1222 int32_t res, rem;
1223 if (b == 0)
1224 res = 0, rem = a;
1225 else
1226 res = a / b, rem = a - b*res;
1227 cpu->cd.mips.lo = (int32_t)res;
1228 cpu->cd.mips.hi = (int32_t)rem;
1229 }
1230 X(divu)
1231 {
1232 uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1233 uint32_t res, rem;
1234 if (b == 0)
1235 res = 0, rem = a;
1236 else
1237 res = a / b, rem = a - b*res;
1238 cpu->cd.mips.lo = (int32_t)res;
1239 cpu->cd.mips.hi = (int32_t)rem;
1240 }
1241 X(ddiv)
1242 {
1243 int64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1244 int64_t res, rem;
1245 if (b == 0)
1246 res = 0;
1247 else
1248 res = a / b;
1249 rem = a - b*res;
1250 cpu->cd.mips.lo = res;
1251 cpu->cd.mips.hi = rem;
1252 }
1253 X(ddivu)
1254 {
1255 uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1256 uint64_t res, rem;
1257 if (b == 0)
1258 res = 0;
1259 else
1260 res = a / b;
1261 rem = a - b*res;
1262 cpu->cd.mips.lo = res;
1263 cpu->cd.mips.hi = rem;
1264 }
1265 X(mult)
1266 {
1267 int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1268 int64_t res = (int64_t)a * (int64_t)b;
1269 cpu->cd.mips.lo = (int32_t)res;
1270 cpu->cd.mips.hi = (int32_t)(res >> 32);
1271 }
1272 X(mult_r5900)
1273 {
1274 /* C790/TX79/R5900 multiplication, stores result in
1275 hi, lo, and a third register */
1276 int32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1277 int64_t res = (int64_t)a * (int64_t)b;
1278 cpu->cd.mips.lo = (int32_t)res;
1279 cpu->cd.mips.hi = (int32_t)(res >> 32);
1280 reg(ic->arg[2]) = (int32_t)res;
1281 }
1282 X(multu)
1283 {
1284 uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1285 uint64_t res = (uint64_t)a * (uint64_t)b;
1286 cpu->cd.mips.lo = (int32_t)res;
1287 cpu->cd.mips.hi = (int32_t)(res >> 32);
1288 }
1289 X(multu_r5900)
1290 {
1291 /* C790/TX79/R5900 multiplication, stores result in
1292 hi, lo, and a third register */
1293 uint32_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1294 uint64_t res = (uint64_t)a * (uint64_t)b;
1295 cpu->cd.mips.lo = (int32_t)res;
1296 cpu->cd.mips.hi = (int32_t)(res >> 32);
1297 reg(ic->arg[2]) = (int32_t)res;
1298 }
1299 X(dmult)
1300 {
1301 uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1302 uint64_t hi = 0, lo = 0;
1303 int neg = 0;
1304 if (a >> 63)
1305 neg = !neg, a = -a;
1306 if (b >> 63)
1307 neg = !neg, b = -b;
1308 for (; a; a >>= 1) {
1309 if (a & 1) {
1310 uint64_t old_lo = lo;
1311 hi += c;
1312 lo += b;
1313 if (lo < old_lo)
1314 hi ++;
1315 }
1316 c = (c << 1) | (b >> 63); b <<= 1;
1317 }
1318 if (neg) {
1319 if (lo == 0)
1320 hi --;
1321 lo --;
1322 hi ^= (int64_t) -1;
1323 lo ^= (int64_t) -1;
1324 }
1325 cpu->cd.mips.lo = lo;
1326 cpu->cd.mips.hi = hi;
1327 }
1328 X(dmultu)
1329 {
1330 uint64_t a = reg(ic->arg[0]), b = reg(ic->arg[1]), c = 0;
1331 uint64_t hi = 0, lo = 0;
1332 for (; a; a >>= 1) {
1333 if (a & 1) {
1334 uint64_t old_lo = lo;
1335 hi += c;
1336 lo += b;
1337 if (lo < old_lo)
1338 hi ++;
1339 }
1340 c = (c << 1) | (b >> 63); b <<= 1;
1341 }
1342 cpu->cd.mips.lo = lo;
1343 cpu->cd.mips.hi = hi;
1344 }
1345 X(tge)
1346 {
1347 MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1348 if (a >= b) {
1349 /* Synch. PC and cause an exception: */
1350 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1351 / sizeof(struct mips_instr_call);
1352 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1353 << MIPS_INSTR_ALIGNMENT_SHIFT);
1354 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1355 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1356 }
1357 }
1358 X(tgeu)
1359 {
1360 MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1361 if (a >= b) {
1362 /* Synch. PC and cause an exception: */
1363 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1364 / sizeof(struct mips_instr_call);
1365 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1366 << MIPS_INSTR_ALIGNMENT_SHIFT);
1367 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1368 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1369 }
1370 }
1371 X(tlt)
1372 {
1373 MODE_int_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1374 if (a < b) {
1375 /* Synch. PC and cause an exception: */
1376 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1377 / sizeof(struct mips_instr_call);
1378 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1379 << MIPS_INSTR_ALIGNMENT_SHIFT);
1380 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1381 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1382 }
1383 }
1384 X(tltu)
1385 {
1386 MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1387 if (a < b) {
1388 /* Synch. PC and cause an exception: */
1389 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1390 / sizeof(struct mips_instr_call);
1391 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1392 << MIPS_INSTR_ALIGNMENT_SHIFT);
1393 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1394 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1395 }
1396 }
1397 X(teq)
1398 {
1399 MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1400 if (a == b) {
1401 /* Synch. PC and cause an exception: */
1402 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1403 / sizeof(struct mips_instr_call);
1404 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1405 << MIPS_INSTR_ALIGNMENT_SHIFT);
1406 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1407 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1408 }
1409 }
1410 X(tne)
1411 {
1412 MODE_uint_t a = reg(ic->arg[0]), b = reg(ic->arg[1]);
1413 if (a != b) {
1414 /* Synch. PC and cause an exception: */
1415 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1416 / sizeof(struct mips_instr_call);
1417 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1418 << MIPS_INSTR_ALIGNMENT_SHIFT);
1419 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1420 mips_cpu_exception(cpu, EXCEPTION_TR, 0, 0, 0, 0, 0, 0);
1421 }
1422 }
1423
1424
1425 /*
1426 * 3-register arithmetic instructions:
1427 *
1428 * arg[0] = ptr to rs
1429 * arg[1] = ptr to rt
1430 * arg[2] = ptr to rd
1431 */
1432 X(addu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) + reg(ic->arg[1])); }
1433 X(add)
1434 {
1435 int32_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1436 int32_t rd = rs + rt;
1437
1438 if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1439 /* Synch. PC and cause an exception: */
1440 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1441 / sizeof(struct mips_instr_call);
1442 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1443 << MIPS_INSTR_ALIGNMENT_SHIFT);
1444 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1445 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1446 } else
1447 reg(ic->arg[2]) = rd;
1448 }
1449 X(daddu){ reg(ic->arg[2]) = reg(ic->arg[0]) + reg(ic->arg[1]); }
1450 X(dadd)
1451 {
1452 int64_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
1453 int64_t rd = rs + rt;
1454
1455 if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1456 /* Synch. PC and cause an exception: */
1457 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1458 / sizeof(struct mips_instr_call);
1459 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1460 << MIPS_INSTR_ALIGNMENT_SHIFT);
1461 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1462 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1463 } else
1464 reg(ic->arg[2]) = rd;
1465 }
1466 X(subu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) - reg(ic->arg[1])); }
1467 X(sub)
1468 {
1469 /* NOTE: Negating rt and using addition. TODO: Is this correct? */
1470 int32_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1471 int32_t rd = rs + rt;
1472
1473 if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1474 /* Synch. PC and cause an exception: */
1475 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1476 / sizeof(struct mips_instr_call);
1477 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1478 << MIPS_INSTR_ALIGNMENT_SHIFT);
1479 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1480 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1481 } else
1482 reg(ic->arg[2]) = rd;
1483 }
1484 X(dsubu){ reg(ic->arg[2]) = reg(ic->arg[0]) - reg(ic->arg[1]); }
1485 X(dsub)
1486 {
1487 /* NOTE: Negating rt and using addition. TODO: Is this correct? */
1488 int64_t rs = reg(ic->arg[0]), rt = - reg(ic->arg[1]);
1489 int64_t rd = rs + rt;
1490
1491 if ((rs >= 0 && rt >= 0 && rd < 0) || (rs < 0 && rt < 0 && rd >= 0)) {
1492 /* Synch. PC and cause an exception: */
1493 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1494 / sizeof(struct mips_instr_call);
1495 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1496 << MIPS_INSTR_ALIGNMENT_SHIFT);
1497 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1498 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1499 } else
1500 reg(ic->arg[2]) = rd;
1501 }
1502 X(slt) {
1503 reg(ic->arg[2]) =
1504 (MODE_int_t)reg(ic->arg[0]) < (MODE_int_t)reg(ic->arg[1]);
1505 }
1506 X(sltu) {
1507 reg(ic->arg[2]) =
1508 (MODE_uint_t)reg(ic->arg[0]) < (MODE_uint_t)reg(ic->arg[1]);
1509 }
1510 X(and) { reg(ic->arg[2]) = reg(ic->arg[0]) & reg(ic->arg[1]); }
1511 X(or) { reg(ic->arg[2]) = reg(ic->arg[0]) | reg(ic->arg[1]); }
1512 X(xor) { reg(ic->arg[2]) = reg(ic->arg[0]) ^ reg(ic->arg[1]); }
1513 X(nor) { reg(ic->arg[2]) = ~(reg(ic->arg[0]) | reg(ic->arg[1])); }
1514 X(sll) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << (int32_t)ic->arg[1]); }
1515 X(sllv){ int32_t sa = reg(ic->arg[1]) & 31;
1516 reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) << sa); }
1517 X(srl) { reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1518 X(srlv){ int32_t sa = reg(ic->arg[1]) & 31;
1519 reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> sa); }
1520 X(sra) { reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1521 X(srav){ int32_t sa = reg(ic->arg[1]) & 31;
1522 reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> sa); }
1523 X(dsll) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) << (int64_t)ic->arg[1]; }
1524 X(dsllv){ int64_t sa = reg(ic->arg[1]) & 63;
1525 reg(ic->arg[2]) = reg(ic->arg[0]) << sa; }
1526 X(dsrl) { reg(ic->arg[2]) = (int64_t)((uint64_t)reg(ic->arg[0]) >>
1527 (uint64_t) ic->arg[1]);}
1528 X(dsrlv){ int64_t sa = reg(ic->arg[1]) & 63;
1529 reg(ic->arg[2]) = (uint64_t)reg(ic->arg[0]) >> sa; }
1530 X(dsra) { reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> (int64_t)ic->arg[1]; }
1531 X(dsrav){ int64_t sa = reg(ic->arg[1]) & 63;
1532 reg(ic->arg[2]) = (int64_t)reg(ic->arg[0]) >> sa; }
1533 X(mul) { reg(ic->arg[2]) = (int32_t)
1534 ( (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]) ); }
1535 X(movn) { if (reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1536 X(movz) { if (!reg(ic->arg[1])) reg(ic->arg[2]) = reg(ic->arg[0]); }
1537
1538
1539 /*
1540 * p*: 128-bit C790/TX79/R5900 stuff
1541 *
1542 * arg[0] = rs (note: not a pointer)
1543 * arg[1] = rt (note: not a pointer)
1544 * arg[2] = rd (note: not a pointer)
1545 */
1546 X(por)
1547 {
1548 cpu->cd.mips.gpr[ic->arg[2]] = cpu->cd.mips.gpr[ic->arg[0]] |
1549 cpu->cd.mips.gpr[ic->arg[1]];
1550 cpu->cd.mips.gpr_quadhi[ic->arg[2]] =
1551 cpu->cd.mips.gpr_quadhi[ic->arg[0]] |
1552 cpu->cd.mips.gpr_quadhi[ic->arg[1]];
1553 }
1554 X(pextlw)
1555 {
1556 uint64_t lo, hi;
1557
1558 lo = (uint32_t)cpu->cd.mips.gpr[ic->arg[1]] |
1559 (uint64_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[0]] << 32);
1560 hi = (cpu->cd.mips.gpr[ic->arg[0]] & 0xffffffff00000000ULL) |
1561 (uint32_t)((uint64_t)cpu->cd.mips.gpr[ic->arg[1]] >> 32);
1562
1563 cpu->cd.mips.gpr[ic->arg[2]] = lo;
1564 cpu->cd.mips.gpr_quadhi[ic->arg[2]] = hi;
1565 }
1566
1567
1568 /*
1569 * madd, maddu, msub, msubu: Multiply-and-add/subtract
1570 *
1571 * arg[0] = ptr to rs
1572 * arg[1] = ptr to rt
1573 * arg[2] = ptr to rd (only used on R5900/TX79)
1574 */
1575 X(madd)
1576 {
1577 int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1578 int64_t sum = rs * rt,
1579 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1580 hilo += sum;
1581 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1582 }
1583 X(madd_rd)
1584 {
1585 int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1586 int64_t sum = rs * rt,
1587 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1588 hilo += sum;
1589 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1590 reg(ic->arg[2]) = (int32_t)hilo;
1591 }
1592 X(msub)
1593 {
1594 int64_t rs = (int32_t)reg(ic->arg[0]), rt = (int32_t)reg(ic->arg[1]);
1595 int64_t sum = rs * rt,
1596 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1597 hilo -= sum;
1598 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1599 }
1600 X(maddu)
1601 {
1602 int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1603 int64_t sum = rs * rt,
1604 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1605 hilo += sum;
1606 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1607 }
1608 X(maddu_rd)
1609 {
1610 int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1611 int64_t sum = rs * rt,
1612 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1613 hilo += sum;
1614 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1615 reg(ic->arg[2]) = (int32_t)hilo;
1616 }
1617 X(msubu)
1618 {
1619 int64_t rs = (uint32_t)reg(ic->arg[0]), rt = (uint32_t)reg(ic->arg[1]);
1620 int64_t sum = rs * rt,
1621 hilo = (cpu->cd.mips.hi << 32) | (uint32_t)(cpu->cd.mips.lo);
1622 hilo -= sum;
1623 cpu->cd.mips.hi = (int32_t)(hilo>>32); cpu->cd.mips.lo = (int32_t)hilo;
1624 }
1625
1626
1627 /*
1628 * mov: Move one register into another.
1629 *
1630 * arg[0] = pointer to source
1631 * arg[2] = pointer to destination
1632 */
1633 X(mov) { reg(ic->arg[2]) = reg(ic->arg[0]); }
1634
1635
1636 /*
1637 * clz, clo, dclz, dclo: Count leading zeroes/ones.
1638 *
1639 * arg[0] = pointer to rs
1640 * arg[1] = pointer to rd
1641 */
1642 X(clz)
1643 {
1644 uint32_t x = reg(ic->arg[0]);
1645 int count;
1646 for (count=0; count<32; count++) {
1647 if (x & 0x80000000UL)
1648 break;
1649 x <<= 1;
1650 }
1651 reg(ic->arg[1]) = count;
1652 }
1653 X(clo)
1654 {
1655 uint32_t x = reg(ic->arg[0]);
1656 int count;
1657 for (count=0; count<32; count++) {
1658 if (!(x & 0x80000000UL))
1659 break;
1660 x <<= 1;
1661 }
1662 reg(ic->arg[1]) = count;
1663 }
1664 X(dclz)
1665 {
1666 uint64_t x = reg(ic->arg[0]);
1667 int count;
1668 for (count=0; count<64; count++) {
1669 if (x & 0x8000000000000000ULL)
1670 break;
1671 x <<= 1;
1672 }
1673 reg(ic->arg[1]) = count;
1674 }
1675 X(dclo)
1676 {
1677 uint64_t x = reg(ic->arg[0]);
1678 int count;
1679 for (count=0; count<64; count++) {
1680 if (!(x & 0x8000000000000000ULL))
1681 break;
1682 x <<= 1;
1683 }
1684 reg(ic->arg[1]) = count;
1685 }
1686
1687
1688 /*
1689 * addi, daddi: Add immediate, overflow detection.
1690 * addiu, daddiu: Add immediate.
1691 * slti: Set if less than immediate (signed 32-bit)
1692 * sltiu: Set if less than immediate (signed 32-bit, but unsigned compare)
1693 *
1694 * arg[0] = pointer to rs
1695 * arg[1] = pointer to rt
1696 * arg[2] = (int32_t) immediate value
1697 */
1698 X(addi)
1699 {
1700 int32_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1701 int32_t rt = rs + imm;
1702
1703 if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1704 /* Synch. PC and cause an exception: */
1705 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1706 / sizeof(struct mips_instr_call);
1707 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1708 << MIPS_INSTR_ALIGNMENT_SHIFT);
1709 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1710 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1711 } else
1712 reg(ic->arg[1]) = rt;
1713 }
1714 X(addiu)
1715 {
1716 reg(ic->arg[1]) = (int32_t)
1717 ((int32_t)reg(ic->arg[0]) + (int32_t)ic->arg[2]);
1718 }
1719 X(daddi)
1720 {
1721 int64_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1722 int64_t rt = rs + imm;
1723
1724 if ((rs >= 0 && imm >= 0 && rt < 0) || (rs < 0 && imm < 0 && rt >= 0)) {
1725 /* Synch. PC and cause an exception: */
1726 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1727 / sizeof(struct mips_instr_call);
1728 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
1729 << MIPS_INSTR_ALIGNMENT_SHIFT);
1730 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1731 mips_cpu_exception(cpu, EXCEPTION_OV, 0, 0, 0, 0, 0, 0);
1732 } else
1733 reg(ic->arg[1]) = rt;
1734 }
1735 X(daddiu)
1736 {
1737 reg(ic->arg[1]) = reg(ic->arg[0]) + (int32_t)ic->arg[2];
1738 }
1739 X(slti)
1740 {
1741 reg(ic->arg[1]) = (MODE_int_t)reg(ic->arg[0]) < (int32_t)ic->arg[2];
1742 }
1743 X(sltiu)
1744 {
1745 reg(ic->arg[1]) = (MODE_uint_t)reg(ic->arg[0]) <
1746 ((MODE_uint_t)(int32_t)ic->arg[2]);
1747 }
1748
1749
1750 /*
1751 * set: Set a register to an immediate (signed) 32-bit value.
1752 * (This is the actual implementation of the lui instruction.)
1753 *
1754 * arg[0] = pointer to the register
1755 * arg[1] = (int32_t) immediate value
1756 */
1757 X(set)
1758 {
1759 reg(ic->arg[0]) = (int32_t)ic->arg[1];
1760 }
1761
1762
1763 /*
1764 * cfc0: Copy from Coprocessor 0.
1765 * mfc0, dmfc0: Move from Coprocessor 0.
1766 * mtc0, dmtc0: Move to Coprocessor 0.
1767 *
1768 * arg[0] = pointer to GPR (rt)
1769 * arg[1] = coprocessor 0 register number | (select << 5) (or for the
1770 * cfc0 instruction, the coprocessor control register number)
1771 * arg[2] = relative addr of this instruction within the page
1772 */
1773 X(cfc0)
1774 {
1775 int fs = ic->arg[1] & 31;
1776 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1777 cpu->pc |= ic->arg[2];
1778 /* TODO: cause exception if necessary */
1779 reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->fcr[fs];
1780 }
1781 X(mfc0)
1782 {
1783 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1784 uint64_t tmp;
1785 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1786 cpu->pc |= ic->arg[2];
1787 /* TODO: cause exception if necessary */
1788 coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd, &tmp, select);
1789 reg(ic->arg[0]) = (int32_t)tmp;
1790 }
1791 X(mfc0_select0)
1792 {
1793 /* Fast int32_t read, with no side effects: */
1794 int rd = ic->arg[1] & 31;
1795 #if 0
1796 uint64_t tmp;
1797 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1798 cpu->pc |= ic->arg[2];
1799 /* TODO: cause exception if necessary */
1800 #endif
1801 reg(ic->arg[0]) = (int32_t)cpu->cd.mips.coproc[0]->reg[rd];
1802 }
1803 X(mtc0)
1804 {
1805 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1806 uint64_t tmp = (int32_t) reg(ic->arg[0]);
1807
1808 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1809 cpu->pc |= ic->arg[2];
1810
1811 /* TODO: cause exception if necessary */
1812 coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd, &tmp, 0, select);
1813
1814 /*
1815 * Interrupts enabled, and any interrupt pending? (Note/TODO: This
1816 * code is duplicated in cpu_dyntrans.c. Fix this?)
1817 */
1818 if (rd == COP0_STATUS && !cpu->delay_slot) {
1819 uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
1820 uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1821 /* NOTE: STATUS_IE happens to match the enable bit also
1822 on R2000/R3000, so this is ok. */
1823 if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1824 if (status & (STATUS_EXL | STATUS_ERL))
1825 status &= ~STATUS_IE;
1826 }
1827 /* Ugly R5900 special case: (TODO: move this?) */
1828 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1829 !(status & R5900_STATUS_EIE))
1830 status &= ~STATUS_IE;
1831 if (status & STATUS_IE && (status & cause & STATUS_IM_MASK)) {
1832 cpu->pc += sizeof(uint32_t);
1833 mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0,0,0,0,0);
1834 }
1835 }
1836 }
1837 X(dmfc0)
1838 {
1839 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1840 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1841 cpu->pc |= ic->arg[2];
1842 /* TODO: cause exception if necessary */
1843 coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd,
1844 (uint64_t *)ic->arg[0], select);
1845 }
1846 X(dmfc0_select0)
1847 {
1848 /* Fast int64_t read, with no side effects: */
1849 int rd = ic->arg[1] & 31;
1850 #if 0
1851 uint64_t tmp;
1852 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1853 cpu->pc |= ic->arg[2];
1854 /* TODO: cause exception if necessary */
1855 #endif
1856 reg(ic->arg[0]) = cpu->cd.mips.coproc[0]->reg[rd];
1857 }
1858 X(dmtc0)
1859 {
1860 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1861 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1862 cpu->pc |= ic->arg[2];
1863 /* TODO: cause exception if necessary */
1864 coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,
1865 (uint64_t *)ic->arg[0], 1, select);
1866 }
1867
1868
1869 /*
1870 * cop1_bc: Floating point conditional branch.
1871 *
1872 * arg[0] = cc
1873 * arg[1] = nd (=2) and tf (=1) bits
1874 * arg[2] = offset (relative to start of this page)
1875 */
1876 X(cop1_bc)
1877 {
1878 MODE_int_t old_pc = cpu->pc;
1879 int x, cc = ic->arg[0];
1880
1881 COPROC_AVAILABILITY_CHECK(1);
1882
1883 /* Get the correct condition code bit: */
1884 if (cc == 0)
1885 x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1886 >> MIPS_FCSR_FCC0_SHIFT) & 1;
1887 else
1888 x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1889 >> (MIPS_FCSR_FCC1_SHIFT + cc-1)) & 1;
1890
1891 /* Branch on false? Then invert the truth value. */
1892 if (!(ic->arg[1] & 1))
1893 x ^= 1;
1894
1895 /* Execute the delay slot (except if it is nullified): */
1896 cpu->delay_slot = TO_BE_DELAYED;
1897 if (x || !(ic->arg[1] & 2))
1898 ic[1].f(cpu, ic+1);
1899 cpu->n_translated_instrs ++;
1900
1901 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1902 /* Note: Must be non-delayed when jumping to the new pc: */
1903 cpu->delay_slot = NOT_DELAYED;
1904 if (x) {
1905 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1906 MIPS_INSTR_ALIGNMENT_SHIFT);
1907 cpu->pc = old_pc + (int32_t)ic->arg[2];
1908 quick_pc_to_pointers(cpu);
1909 } else
1910 cpu->cd.mips.next_ic ++;
1911 } else
1912 cpu->delay_slot = NOT_DELAYED;
1913 }
1914
1915
1916 /*
1917 * cop1_slow: Fallback to legacy cop1 code. (Slow, but it should work.)
1918 */
1919 X(cop1_slow)
1920 {
1921 COPROC_AVAILABILITY_CHECK(1);
1922
1923 coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);
1924 }
1925
1926
1927 /*
1928 * syscall, break: Synchronize the PC and cause an exception.
1929 */
1930 X(syscall)
1931 {
1932 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1933 / sizeof(struct mips_instr_call);
1934 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1935 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1936 mips_cpu_exception(cpu, EXCEPTION_SYS, 0, 0, 0, 0, 0, 0);
1937 }
1938 X(break)
1939 {
1940 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1941 / sizeof(struct mips_instr_call);
1942 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1943 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1944 mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1945 }
1946 X(reboot)
1947 {
1948 if (!cop0_availability_check(cpu, ic))
1949 return;
1950
1951 cpu->running = 0;
1952 debugger_n_steps_left_before_interaction = 0;
1953 cpu->cd.mips.next_ic = &nothing_call;
1954 }
1955
1956
1957 /*
1958 * promemul: PROM software emulation.
1959 */
1960 X(promemul)
1961 {
1962 /* Synchronize the PC and call the correct emulation layer: */
1963 MODE_int_t old_pc;
1964 int res, low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1965 / sizeof(struct mips_instr_call);
1966 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1967 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1968 old_pc = cpu->pc;
1969
1970 switch (cpu->machine->machine_type) {
1971 case MACHINE_PMAX:
1972 res = decstation_prom_emul(cpu);
1973 break;
1974 case MACHINE_PS2:
1975 res = playstation2_sifbios_emul(cpu);
1976 break;
1977 case MACHINE_ARC:
1978 case MACHINE_SGI:
1979 res = arcbios_emul(cpu);
1980 break;
1981 case MACHINE_EVBMIPS:
1982 res = yamon_emul(cpu);
1983 break;
1984 default:fatal("TODO: Unimplemented machine type for PROM magic trap\n");
1985 exit(1);
1986 }
1987
1988 if (res) {
1989 /* Return from the PROM call: */
1990 cpu->pc = (MODE_int_t)cpu->cd.mips.gpr[MIPS_GPR_RA];
1991 cpu->delay_slot = NOT_DELAYED;
1992
1993 if (cpu->machine->show_trace_tree)
1994 cpu_functioncall_trace_return(cpu);
1995 } else {
1996 /* The PROM call blocks. */
1997 cpu->n_translated_instrs += 10;
1998 cpu->pc = old_pc;
1999 }
2000
2001 quick_pc_to_pointers(cpu);
2002 }
2003
2004
2005 /*
2006 * tlbw: TLB write indexed and random
2007 *
2008 * arg[0] = 1 for random, 0 for indexed
2009 * arg[2] = relative addr of this instruction within the page
2010 */
2011 X(tlbw)
2012 {
2013 if (!cop0_availability_check(cpu, ic))
2014 return;
2015
2016 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2017 cpu->pc |= ic->arg[2];
2018 coproc_tlbwri(cpu, ic->arg[0]);
2019 }
2020
2021
2022 /*
2023 * tlbp: TLB probe
2024 * tlbr: TLB read
2025 *
2026 * arg[2] = relative addr of this instruction within the page
2027 */
2028 X(tlbp)
2029 {
2030 if (!cop0_availability_check(cpu, ic))
2031 return;
2032
2033 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2034 cpu->pc |= ic->arg[2];
2035 coproc_tlbpr(cpu, 0);
2036 }
2037 X(tlbr)
2038 {
2039 if (!cop0_availability_check(cpu, ic))
2040 return;
2041
2042 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2043 cpu->pc |= ic->arg[2];
2044 coproc_tlbpr(cpu, 1);
2045 }
2046
2047
2048 /*
2049 * rfe: Return from exception handler (R2000/R3000)
2050 */
2051 X(rfe)
2052 {
2053 if (!cop0_availability_check(cpu, ic))
2054 return;
2055
2056 /* Just rotate the interrupt/user bits: */
2057 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
2058 (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
2059 ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
2060
2061 /*
2062 * Note: no pc to pointers conversion is necessary here. Usually the
2063 * rfe instruction resides in the delay slot of a jr k0/k1, and
2064 * it is up to that instruction to do the pointer conversion.
2065 */
2066 }
2067
2068
2069 /*
2070 * eret: Return from exception handler (non-R3000 style)
2071 */
2072 X(eret)
2073 {
2074 if (!cop0_availability_check(cpu, ic))
2075 return;
2076
2077 if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
2078 cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
2079 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
2080 } else {
2081 cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
2082 cpu->delay_slot = 0;
2083 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
2084 }
2085
2086 quick_pc_to_pointers(cpu);
2087
2088 cpu->cd.mips.rmw = 0; /* the "LL bit" */
2089 }
2090
2091
2092 /*
2093 * deret: Return from debug (EJTAG) handler
2094 */
2095 X(deret)
2096 {
2097 if (!cop0_availability_check(cpu, ic))
2098 return;
2099
2100 /*
2101 * According to the MIPS64 manual, deret loads PC from the DEPC cop0
2102 * register, and jumps there immediately. No delay slot.
2103 *
2104 * TODO: This instruction is only available if the processor is in
2105 * debug mode. (What does that mean?)
2106 *
2107 * TODO: This instruction is undefined in a delay slot.
2108 */
2109
2110 cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_DEPC];
2111 cpu->delay_slot = 0;
2112 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
2113 quick_pc_to_pointers(cpu);
2114 }
2115
2116
2117 /*
2118 * idle: Called from the implementation of wait, or netbsd_pmax_idle.
2119 */
2120 X(idle)
2121 {
2122 /*
2123 * If there is an interrupt, then just return. Otherwise
2124 * re-run the wait instruction (after a delay).
2125 */
2126 uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
2127 uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
2128
2129 if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
2130 if (status & (STATUS_EXL | STATUS_ERL))
2131 status &= ~STATUS_IE;
2132 }
2133
2134 /* Ugly R5900 special case: (TODO: move this?) */
2135 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
2136 !(status & R5900_STATUS_EIE))
2137 status &= ~STATUS_IE;
2138 if (status & STATUS_IE && (status & cause & STATUS_IM_MASK))
2139 return;
2140
2141 cpu->cd.mips.next_ic = ic;
2142 cpu->is_halted = 1;
2143 cpu->has_been_idling = 1;
2144
2145 /*
2146 * There was no interrupt. Go to sleep.
2147 *
2148 * TODO:
2149 *
2150 * Think about how to actually implement this usleep stuff,
2151 * in an SMP and/or timing accurate environment.
2152 */
2153
2154 if (cpu->machine->ncpus == 1) {
2155 static int x = 0;
2156 if ((++x) == 600) {
2157 usleep(10);
2158 x = 0;
2159 }
2160 cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
2161 }
2162 }
2163
2164
2165 /*
2166 * wait: Wait for external interrupt.
2167 */
2168 X(wait)
2169 {
2170 if (!cop0_availability_check(cpu, ic))
2171 return;
2172
2173 instr(idle)(cpu, ic);
2174 }
2175
2176
2177 /*
2178 * rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
2179 *
2180 * arg[0] = ptr to rt (destination register)
2181 */
2182 X(rdhwr_cpunum)
2183 {
2184 reg(ic->arg[0]) = cpu->cpu_id;
2185 }
2186
2187
2188 #include "tmp_mips_loadstore.c"
2189
2190
2191 /*
2192 * Load linked / store conditional:
2193 *
2194 * A Load-linked instruction initiates a RMW (read-modify-write) sequence.
2195 * COP0_LLADDR is updated for diagnostic purposes, except for CPUs in the
2196 * R10000 family.
2197 *
2198 * A Store-conditional instruction ends the sequence.
2199 *
2200 * arg[0] = ptr to rt
2201 * arg[1] = ptr to rs
2202 * arg[2] = int32_t imm
2203 */
2204 X(ll)
2205 {
2206 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2207 int low_pc;
2208 uint8_t word[sizeof(uint32_t)];
2209
2210 /* Synch. PC and load using slow memory_rw(): */
2211 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2212 / sizeof(struct mips_instr_call);
2213 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2214 << MIPS_INSTR_ALIGNMENT_SHIFT);
2215 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2216
2217 if (addr & (sizeof(word)-1)) {
2218 fatal("TODO: load linked unaligned access: exception\n");
2219 exit(1);
2220 }
2221
2222 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2223 sizeof(word), MEM_READ, CACHE_DATA)) {
2224 /* An exception occurred. */
2225 return;
2226 }
2227
2228 cpu->cd.mips.rmw = 1;
2229 cpu->cd.mips.rmw_addr = addr;
2230 cpu->cd.mips.rmw_len = sizeof(word);
2231 if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2232 cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2233 (addr >> 4) & 0xffffffffULL;
2234
2235 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2236 reg(ic->arg[0]) = (int32_t) (word[0] + (word[1] << 8)
2237 + (word[2] << 16) + (word[3] << 24));
2238 else
2239 reg(ic->arg[0]) = (int32_t) (word[3] + (word[2] << 8)
2240 + (word[1] << 16) + (word[0] << 24));
2241 }
2242 X(lld)
2243 {
2244 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2245 int low_pc;
2246 uint8_t word[sizeof(uint64_t)];
2247
2248 /* Synch. PC and load using slow memory_rw(): */
2249 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2250 / sizeof(struct mips_instr_call);
2251 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2252 << MIPS_INSTR_ALIGNMENT_SHIFT);
2253 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2254
2255 if (addr & (sizeof(word)-1)) {
2256 fatal("TODO: load linked unaligned access: exception\n");
2257 exit(1);
2258 }
2259
2260 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2261 sizeof(word), MEM_READ, CACHE_DATA)) {
2262 /* An exception occurred. */
2263 return;
2264 }
2265
2266 cpu->cd.mips.rmw = 1;
2267 cpu->cd.mips.rmw_addr = addr;
2268 cpu->cd.mips.rmw_len = sizeof(word);
2269 if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2270 cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2271 (addr >> 4) & 0xffffffffULL;
2272
2273 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2274 reg(ic->arg[0]) = word[0] + (word[1] << 8)
2275 + (word[2] << 16) + ((uint64_t)word[3] << 24) +
2276 + ((uint64_t)word[4] << 32) + ((uint64_t)word[5] << 40)
2277 + ((uint64_t)word[6] << 48) + ((uint64_t)word[7] << 56);
2278 else
2279 reg(ic->arg[0]) = word[7] + (word[6] << 8)
2280 + (word[5] << 16) + ((uint64_t)word[4] << 24) +
2281 + ((uint64_t)word[3] << 32) + ((uint64_t)word[2] << 40)
2282 + ((uint64_t)word[1] << 48) + ((uint64_t)word[0] << 56);
2283 }
2284 X(sc)
2285 {
2286 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2287 uint64_t r = reg(ic->arg[0]);
2288 int low_pc, i;
2289 uint8_t word[sizeof(uint32_t)];
2290
2291 /* Synch. PC and store using slow memory_rw(): */
2292 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2293 / sizeof(struct mips_instr_call);
2294 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2295 << MIPS_INSTR_ALIGNMENT_SHIFT);
2296 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2297
2298 if (addr & (sizeof(word)-1)) {
2299 fatal("TODO: sc unaligned access: exception\n");
2300 exit(1);
2301 }
2302
2303 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2304 word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2305 } else {
2306 word[3]=r; word[2]=r>>8; word[1]=r>>16; word[0]=r>>24;
2307 }
2308
2309 /* If rmw is 0, then the store failed. (This cache-line was written
2310 to by someone else.) */
2311 if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2312 || cpu->cd.mips.rmw_len != sizeof(word)) {
2313 reg(ic->arg[0]) = 0;
2314 cpu->cd.mips.rmw = 0;
2315 return;
2316 }
2317
2318 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2319 sizeof(word), MEM_WRITE, CACHE_DATA)) {
2320 /* An exception occurred. */
2321 return;
2322 }
2323
2324 /* We succeeded. Let's invalidate everybody else's store to this
2325 cache line: */
2326 for (i=0; i<cpu->machine->ncpus; i++) {
2327 if (cpu->machine->cpus[i]->cd.mips.rmw) {
2328 uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2329 cd.mips.rmw_addr;
2330 uint64_t mask = ~(cpu->machine->cpus[i]->
2331 cd.mips.cache_linesize[CACHE_DATA] - 1);
2332 xaddr &= mask;
2333 yaddr &= mask;
2334 if (xaddr == yaddr)
2335 cpu->machine->cpus[i]->cd.mips.rmw = 0;
2336 }
2337 }
2338
2339 reg(ic->arg[0]) = 1;
2340 cpu->cd.mips.rmw = 0;
2341 }
2342 X(scd)
2343 {
2344 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2345 uint64_t r = reg(ic->arg[0]);
2346 int low_pc, i;
2347 uint8_t word[sizeof(uint64_t)];
2348
2349 /* Synch. PC and store using slow memory_rw(): */
2350 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2351 / sizeof(struct mips_instr_call);
2352 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2353 << MIPS_INSTR_ALIGNMENT_SHIFT);
2354 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2355
2356 if (addr & (sizeof(word)-1)) {
2357 fatal("TODO: sc unaligned access: exception\n");
2358 exit(1);
2359 }
2360
2361 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2362 word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2363 word[4]=r>>32; word[5]=r>>40; word[6]=r>>48; word[7]=r>>56;
2364 } else {
2365 word[7]=r; word[6]=r>>8; word[5]=r>>16; word[4]=r>>24;
2366 word[3]=r>>32; word[2]=r>>40; word[1]=r>>48; word[0]=r>>56;
2367 }
2368
2369 /* If rmw is 0, then the store failed. (This cache-line was written
2370 to by someone else.) */
2371 if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2372 || cpu->cd.mips.rmw_len != sizeof(word)) {
2373 reg(ic->arg[0]) = 0;
2374 cpu->cd.mips.rmw = 0;
2375 return;
2376 }
2377
2378 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2379 sizeof(word), MEM_WRITE, CACHE_DATA)) {
2380 /* An exception occurred. */
2381 return;
2382 }
2383
2384 /* We succeeded. Let's invalidate everybody else's store to this
2385 cache line: */
2386 for (i=0; i<cpu->machine->ncpus; i++) {
2387 if (cpu->machine->cpus[i]->cd.mips.rmw) {
2388 uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2389 cd.mips.rmw_addr;
2390 uint64_t mask = ~(cpu->machine->cpus[i]->
2391 cd.mips.cache_linesize[CACHE_DATA] - 1);
2392 xaddr &= mask;
2393 yaddr &= mask;
2394 if (xaddr == yaddr)
2395 cpu->machine->cpus[i]->cd.mips.rmw = 0;
2396 }
2397 }
2398
2399 reg(ic->arg[0]) = 1;
2400 cpu->cd.mips.rmw = 0;
2401 }
2402
2403
2404 /*
2405 * lwc1, swc1: Coprocessor 1 load/store (32-bit)
2406 * ldc1, sdc1: Coprocessor 1 load/store (64-bit)
2407 *
2408 * arg[0] = ptr to coprocessor register
2409 * arg[1] = ptr to rs (base pointer register)
2410 * arg[2] = int32_t imm
2411 */
2412 X(lwc1)
2413 {
2414 COPROC_AVAILABILITY_CHECK(1);
2415
2416 #ifdef MODE32
2417 mips32_loadstore
2418 #else
2419 mips_loadstore
2420 #endif
2421 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 2 * 2 + 1]
2422 (cpu, ic);
2423 }
2424 X(swc1)
2425 {
2426 COPROC_AVAILABILITY_CHECK(1);
2427
2428 #ifdef MODE32
2429 mips32_loadstore
2430 #else
2431 mips_loadstore
2432 #endif
2433 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 2 * 2]
2434 (cpu, ic);
2435 }
2436 X(ldc1)
2437 {
2438 int use_fp_pairs =
2439 !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2440 uint64_t fpr, *backup_ptr;
2441
2442 COPROC_AVAILABILITY_CHECK(1);
2443
2444 backup_ptr = (uint64_t *) ic->arg[0];
2445 ic->arg[0] = (size_t) &fpr;
2446
2447 #ifdef MODE32
2448 mips32_loadstore
2449 #else
2450 mips_loadstore
2451 #endif
2452 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 3 * 2 + 1]
2453 (cpu, ic);
2454
2455 if (use_fp_pairs) {
2456 backup_ptr[0] = (int64_t)(int32_t) fpr;
2457 backup_ptr[1] = (int64_t)(int32_t) (fpr >> 32);
2458 } else {
2459 *backup_ptr = fpr;
2460 }
2461
2462 ic->arg[0] = (size_t) backup_ptr;
2463 }
2464 X(sdc1)
2465 {
2466 int use_fp_pairs =
2467 !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2468 uint64_t fpr, *backup_ptr;
2469
2470 COPROC_AVAILABILITY_CHECK(1);
2471
2472 backup_ptr = (uint64_t *) ic->arg[0];
2473 ic->arg[0] = (size_t) &fpr;
2474
2475 if (use_fp_pairs) {
2476 uint32_t lo = backup_ptr[0];
2477 uint32_t hi = backup_ptr[1];
2478 fpr = (((uint64_t)hi) << 32) | lo;
2479 } else {
2480 fpr = *backup_ptr;
2481 }
2482
2483 #ifdef MODE32
2484 mips32_loadstore
2485 #else
2486 mips_loadstore
2487 #endif
2488 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 3 * 2]
2489 (cpu, ic);
2490
2491 ic->arg[0] = (size_t) backup_ptr;
2492 }
2493
2494
2495 /*
2496 * Unaligned loads/stores:
2497 *
2498 * arg[0] = ptr to rt
2499 * arg[1] = ptr to rs
2500 * arg[2] = int32_t imm
2501 */
2502 X(lwl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 0); }
2503 X(lwr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 0); }
2504 X(ldl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 0); }
2505 X(ldr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 0); }
2506 X(swl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 1); }
2507 X(swr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 1); }
2508 X(sdl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 1); }
2509 X(sdr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 1); }
2510
2511
2512 /*
2513 * di, ei: R5900 interrupt enable/disable.
2514 *
2515 * TODO: check the R5900_STATUS_EDI bit in the status register. If it is
2516 * cleared, and we are not running in kernel mode, then both the EI and DI
2517 * instructions should be treated as NOPs!
2518 */
2519 X(di_r5900)
2520 {
2521 if (!cop0_availability_check(cpu, ic))
2522 return;
2523
2524 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2525 }
2526 X(ei_r5900)
2527 {
2528 if (!cop0_availability_check(cpu, ic))
2529 return;
2530
2531 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2532 }
2533
2534
2535 /*****************************************************************************/
2536
2537
2538 /*
2539 * sw_loop:
2540 *
2541 * s: addiu rX,rX,4 rX = arg[0] and arg[1]
2542 * bne rY,rX,s (or rX,rY,s) rt=arg[1], rs=arg[0]
2543 * sw rZ,-4(rX) rt=arg[0], rs=arg[1]
2544 */
2545 X(sw_loop)
2546 {
2547 MODE_uint_t rX = reg(ic->arg[0]), rZ = reg(ic[2].arg[0]);
2548 uint64_t *rYp = (uint64_t *) ic[1].arg[0];
2549 MODE_uint_t rY, bytes_to_write;
2550 unsigned char *page;
2551 int partial = 0;
2552
2553 page = cpu->cd.mips.host_store[rX >> 12];
2554
2555 /* Fallback: */
2556 if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {
2557 instr(addiu)(cpu, ic);
2558 return;
2559 }
2560
2561 if (rYp == (uint64_t *) ic->arg[0])
2562 rYp = (uint64_t *) ic[1].arg[1];
2563
2564 rY = reg(rYp);
2565
2566 bytes_to_write = rY - rX;
2567 if ((rX & 0xfff) + bytes_to_write > 0x1000) {
2568 bytes_to_write = 0x1000 - (rX & 0xfff);
2569 partial = 1;
2570 }
2571
2572 /* printf("rX = %08x\n", (int)rX);
2573 printf("rY = %08x\n", (int)rY);
2574 printf("rZ = %08x\n", (int)rZ);
2575 printf("%i bytes\n", (int)bytes_to_write); */
2576
2577 memset(page + (rX & 0xfff), 0, bytes_to_write);
2578
2579 reg(ic->arg[0]) = rX + bytes_to_write;
2580
2581 cpu->n_translated_instrs += bytes_to_write / 4 * 3 - 1;
2582 cpu->cd.mips.next_ic = partial?
2583 (struct mips_instr_call *) &ic[0] :
2584 (struct mips_instr_call *) &ic[3];
2585 }
2586
2587
2588 #ifdef MODE32
2589 /* multi_{l,s}w_2, _3, etc. */
2590 #include "tmp_mips_loadstore_multi.c"
2591 #endif
2592
2593
2594 /*
2595 * 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 * 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 * 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 * 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 * addiu_bne_samepage_addiu:
2768 */
2769 X(addiu_bne_samepage_addiu)
2770 {
2771 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 cpu->n_translated_instrs ++;
2827 cpu->cd.mips.next_ic ++;
2828 }
2829
2830
2831 /*
2832 * 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 * b_samepage_addiu:
2872 *
2873 * Combination of branch within the same page, followed by addiu.
2874 */
2875 X(b_samepage_addiu)
2876 {
2877 reg(ic[1].arg[1]) = (int32_t)
2878 ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
2879 cpu->n_translated_instrs ++;
2880 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2881 }
2882
2883
2884 /*
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 /*****************************************************************************/
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 /* end_of_page doesn't count as an executed instruction: */
2909 cpu->n_translated_instrs --;
2910
2911 /*
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
2919 /* Simple jump to the next page (if we are lucky): */
2920 if (cpu->delay_slot == NOT_DELAYED)
2921 return;
2922
2923 /*
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 return;
2930
2931 /*
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 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
2937
2938 instr(to_be_translated)(cpu, cpu->cd.mips.next_ic);
2939
2940 /* The instruction in the delay slot has now executed. */
2941 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
2942 cpu->delay_slot); */
2943
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 /* 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
2959 /* This doesn't count as an executed instruction. */
2960 cpu->n_translated_instrs --;
2961
2962 quick_pc_to_pointers(cpu);
2963
2964 if (cpu->delay_slot == NOT_DELAYED)
2965 return;
2966
2967 fatal("end_of_page2: fatal error, we're in a delay slot\n");
2968 exit(1);
2969 }
2970
2971
2972 /*****************************************************************************/
2973
2974
2975 /*
2976 * 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 */
2982 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 /* Only for 32-bit virtual address translation so far. */
3009 #ifdef MODE32
3010 /*
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 int low_addr)
3020 {
3021 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3022 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3023
3024 if (n_back < 3)
3025 return;
3026
3027 /* 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
3037 /* 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 return;
3075
3076 /* 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 ic[-2].arg[1] == ic[0].arg[1] &&
3091 ic[-1].arg[0] != ic[0].arg[1]) {
3092 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3093 ic[-2].f = instr(multi_lw_3_le);
3094 else
3095 ic[-2].f = instr(multi_lw_3_be);
3096 }
3097
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 }
3108 #endif
3109
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 * NetBSD/pmax' idle loop (and possibly others as well).
3154 * Linux/pmax' idle loop.
3155 */
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 if (n_back < 8)
3162 return;
3163
3164 #ifdef MODE32
3165 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 return;
3183 }
3184
3185 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 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 * 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 * [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 if (n_back < 2)
3302 return;
3303
3304 if (ic[-2].f == instr(addiu) &&
3305 ic[-1].f == instr(bne_samepage)) {
3306 ic[-2].f = instr(addiu_bne_samepage_addiu);
3307 return;
3308 }
3309
3310 if (ic[-1].f == instr(set)) {
3311 ic[-1].f = instr(lui_addiu);
3312 return;
3313 }
3314
3315 if (ic[-1].f == instr(b_samepage)) {
3316 ic[-1].f = instr(b_samepage_addiu);
3317 return;
3318 }
3319
3320 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 /* TODO: other branches that are followed by addiu should be here */
3336 }
3337
3338
3339 /*
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 /*****************************************************************************/
3360
3361
3362 /*
3363 * mips_instr_to_be_translated():
3364 *
3365 * Translate an instruction word into a mips_instr_call. ic is filled in with
3366 * 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 int main_opcode, rt, rs, rd, sa, s6, x64 = 0, s10;
3377 int in_crosspage_delayslot = 0;
3378 void (*samepage_function)(struct cpu *, struct mips_instr_call *);
3379 int store, signedness, size;
3380 #ifdef NATIVE_CODE_GENERATION
3381 int native = 0;
3382
3383 if (!cpu->currently_translating_to_native)
3384 cpu->native_code_function_pointer = (void *) &ic->f;
3385 #endif
3386
3387 /* 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 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
3393 /* fatal("[ delay-slot translation across page "
3394 "boundary ]\n"); */
3395 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 cpu->pc = (MODE_int_t)addr;
3402 addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
3403
3404 /* Read the instruction word from memory: */
3405 #ifdef MODE32
3406 page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
3407 #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
3422 if (page != NULL) {
3423 /* fatal("TRANSLATION HIT!\n"); */
3424 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
3425 } else {
3426 /* fatal("TRANSLATION MISS!\n"); */
3427 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
3428 sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
3429 fatal("to_be_translated(): read failed: TODO\n");
3430 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 * 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 */
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 s10 = (rs << 5) | sa;
3464
3465 switch (main_opcode) {
3466
3467 case HI6_SPECIAL:
3468 switch (s6) {
3469
3470 case SPECIAL_SLL:
3471 case SPECIAL_SLLV:
3472 case SPECIAL_SRL:
3473 case SPECIAL_SRLV:
3474 case SPECIAL_SRA:
3475 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 switch (s6) {
3486 case SPECIAL_SLL: ic->f = instr(sll); break;
3487 case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
3488 case SPECIAL_SRL: ic->f = instr(srl); break;
3489 case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
3490 case SPECIAL_SRA: ic->f = instr(sra); break;
3491 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 }
3508 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3509 if (sa >= 0)
3510 ic->arg[1] = sa;
3511 else
3512 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3513 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3514 if (rd == MIPS_GPR_ZERO)
3515 ic->f = instr(nop);
3516 if (ic->f == instr(sll))
3517 cpu->cd.mips.combination_check = COMBINE(sll);
3518 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
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 break;
3543
3544 case SPECIAL_ADD:
3545 case SPECIAL_ADDU:
3546 case SPECIAL_SUB:
3547 case SPECIAL_SUBU:
3548 case SPECIAL_DADD:
3549 case SPECIAL_DADDU:
3550 case SPECIAL_DSUB:
3551 case SPECIAL_DSUBU:
3552 case SPECIAL_SLT:
3553 case SPECIAL_SLTU:
3554 case SPECIAL_AND:
3555 case SPECIAL_OR:
3556 case SPECIAL_XOR:
3557 case SPECIAL_NOR:
3558 case SPECIAL_MOVN:
3559 case SPECIAL_MOVZ:
3560 case SPECIAL_MFHI:
3561 case SPECIAL_MFLO:
3562 case SPECIAL_MTHI:
3563 case SPECIAL_MTLO:
3564 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 switch (s6) {
3579 case SPECIAL_ADD: ic->f = instr(add); break;
3580 case SPECIAL_ADDU: ic->f = instr(addu); break;
3581 case SPECIAL_SUB: ic->f = instr(sub); break;
3582 case SPECIAL_SUBU: ic->f = instr(subu); break;
3583 case SPECIAL_DADD: ic->f = instr(dadd); x64=1; break;
3584 case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
3585 case SPECIAL_DSUB: ic->f = instr(dsub); x64=1; break;
3586 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 case SPECIAL_AND: ic->f = instr(and); break;
3590 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 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 }
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 /* Special cases for rd: */
3632 switch (s6) {
3633 case SPECIAL_MTHI:
3634 case SPECIAL_MTLO:
3635 case SPECIAL_DIV:
3636 case SPECIAL_DIVU:
3637 case SPECIAL_DDIV:
3638 case SPECIAL_DDIVU:
3639 case SPECIAL_MULT:
3640 case SPECIAL_MULTU:
3641 case SPECIAL_DMULT:
3642 case SPECIAL_DMULTU:
3643 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 if (rd != MIPS_GPR_ZERO) {
3665 fatal("TODO: rd NON-zero\n");
3666 goto bad;
3667 }
3668 /* These instructions don't use rd. */
3669 break;
3670 default:if (rd == MIPS_GPR_ZERO)
3671 ic->f = instr(nop);
3672 }
3673
3674 if (ic->f == instr(addu))
3675 cpu->cd.mips.combination_check = COMBINE(addu);
3676
3677 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 if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
3684 s6 = SPECIAL_JR;
3685 ic->arg[2] = (addr & 0xffc) + 8;
3686 switch (s6) {
3687 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 if (cpu->delay_slot) {
3705 fatal("TODO: branch in delay slot? (1)\n");
3706 goto bad;
3707 }
3708 break;
3709
3710 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 if (((iword >> 6) & 0xfffff) == 0x30378) {
3721 /* "Magic trap" for REBOOT: */
3722 ic->f = instr(reboot);
3723 } else {
3724 ic->f = instr(break);
3725 }
3726 break;
3727
3728 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 case HI6_BEQL:
3739 case HI6_BNEL:
3740 case HI6_BLEZ:
3741 case HI6_BLEZL:
3742 case HI6_BGTZ:
3743 case HI6_BGTZL:
3744 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 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 }
3789 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3790 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3791 ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
3792 + (addr & 0xffc) + 4 );
3793 /* 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 if (cpu->delay_slot) {
3803 fatal("TODO: branch in delay slot? (2)\n");
3804 goto bad;
3805 }
3806 break;
3807
3808 case HI6_ADDI:
3809 case HI6_ADDIU:
3810 case HI6_SLTI:
3811 case HI6_SLTIU:
3812 case HI6_DADDI:
3813 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 main_opcode == HI6_SLTI ||
3822 main_opcode == HI6_SLTIU ||
3823 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
3829 switch (main_opcode) {
3830 case HI6_ADDI: ic->f = instr(addi); break;
3831 case HI6_ADDIU: ic->f = instr(addiu); break;
3832 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 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
3841 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 if (rt == MIPS_GPR_ZERO)
3850 ic->f = instr(nop);
3851
3852 if (ic->f == instr(ori))
3853 cpu->cd.mips.combination_check = COMBINE(ori);
3854 if (ic->f == instr(addiu))
3855 cpu->cd.mips.combination_check = COMBINE(addiu);
3856 if (ic->f == instr(daddiu))
3857 cpu->cd.mips.combination_check = COMBINE(b_daddiu);
3858 break;
3859
3860 case HI6_LUI:
3861 ic->f = instr(set);
3862 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3863 ic->arg[1] = (int32_t) (imm << 16);
3864 /* NOTE: Don't use arg[2] here. It can be used with
3865 instruction combinations, to do lui + addiu, etc. */
3866 if (rt == MIPS_GPR_ZERO)
3867 ic->f = instr(nop);
3868 #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 break;
3877
3878 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 case HI6_COP0:
3902 /* 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 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 case COP0_STANDBY:
3944 /* 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 case COP0_HIBERNATE:
3959 /* TODO */
3960 goto bad;
3961 case COP0_SUSPEND:
3962 /* Used by NetBSD on HPCmips (VR41xx) to
3963 halt the machine. */
3964 ic->f = instr(reboot);
3965 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 /* rs contains the coprocessor opcode! */
3986 switch (rs) {
3987 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 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 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 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
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 break;
4023 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 default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
4033 goto bad;
4034 }
4035 break;
4036
4037 case HI6_COP1:
4038 /* 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 switch (rs) {
4049
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 case COPz_CFCz:
4083 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 break;
4091
4092 default:fatal("COP1 floating point opcode = 0x%02x\n", rs);
4093 goto bad;
4094 }
4095 break;
4096
4097 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 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 case HI6_SPECIAL2:
4129 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 switch (s6) {
4203
4204 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 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 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
4359 /* Check for multiple loads or stores in a row using the same
4360 base register: */
4361 #ifdef MODE32
4362 if (main_opcode == HI6_LW)
4363 cpu->cd.mips.combination_check = COMBINE(multi_lw);
4364 if (main_opcode == HI6_SW)
4365 cpu->cd.mips.combination_check = COMBINE(multi_sw);
4366 #endif
4367 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 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 warning = 1;
4492 }
4493 ic->f = instr(reserved);
4494 break;
4495 }
4496
4497 switch (s6) {
4498
4499 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 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 default:goto bad;
4569 }
4570
4571
4572 #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
4584 #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
4596
4597 #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