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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (hide annotations)
Mon Oct 8 16:22:32 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 122381 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1613 2007/06/15 20:11:26 debug Exp $
20070501	Continuing a little on m88k disassembly (control registers,
		more instructions).
		Adding a dummy mvme88k machine mode.
20070502	Re-adding MIPS load/store alignment exceptions.
20070503	Implementing more of the M88K disassembly code.
20070504	Adding disassembly of some more M88K load/store instructions.
		Implementing some relatively simple M88K instructions (br.n,
		xor[.u] imm, and[.u] imm).
20070505	Implementing M88K three-register and, or, xor, and jmp[.n],
		bsr[.n] including function call trace stuff.
		Applying a patch from Bruce M. Simpson which implements the
		SYSCON_BOARD_CPU_CLOCK_FREQ_ID object of the syscon call in
		the yamon PROM emulation.
20070506	Implementing M88K bb0[.n] and bb1[.n], and skeletons for
		ldcr and stcr (although no control regs are implemented yet).
20070509	Found and fixed the bug which caused Linux for QEMU_MIPS to
		stop working in 0.4.5.1: It was a faulty change to the MIPS
		'sc' and 'scd' instructions I made while going through gcc -W
		warnings on 20070428.
20070510	Updating the Linux/QEMU_MIPS section in guestoses.html to
		use mips-test-0.2.tar.gz instead of 0.1.
		A big thank you to Miod Vallat for sending me M88K manuals.
		Implementing more M88K instructions (addu, subu, div[u], mulu,
		ext[u], clr, set, cmp).
20070511	Fixing bugs in the M88K "and" and "and.u" instructions (found
		by comparing against the manual).
		Implementing more M88K instructions (mask[.u], mak, bcnd (auto-
		generated)) and some more control register details.
		Cleanup: Removing the experimental AVR emulation mode and
		corresponding devices; AVR emulation wasn't really meaningful.
		Implementing autogeneration of most M88K loads/stores. The
		rectangle drawing demo (with -O0) for M88K runs :-)
		Beginning on M88K exception handling.
		More M88K instructions: tb0, tb1, rte, sub, jsr[.n].
		Adding some skeleton MVME PROM ("BUG") emulation.
20070512	Fixing a bug in the M88K cmp instruction.
		Adding the M88K lda (scaled register) instruction.
		Fixing bugs in 64-bit (32-bit pairs) M88K loads/stores.
		Removing the unused tick_hz stuff from the machine struct.
		Implementing the M88K xmem instruction. OpenBSD/mvme88k gets
		far enough to display the Copyright banner :-)
		Implementing subu.co (guess), addu.co, addu.ci, ff0, and ff1.
		Adding a dev_mvme187, for MVME187-specific devices/registers.
		OpenBSD/mvme88k prints more boot messages. :)
20070515	Continuing on MVME187 emulation (adding more devices, beginning
		on the CMMUs, etc).
		Adding the M88K and.c, xor.c, and or.c instructions, and making
		sure that mul, div, etc cause exceptions if executed when SFD1
		is disabled.
20070517	Continuing on M88K and MVME187 emulation in general; moving
		the CMMU registers to the CPU struct, separating dev_pcc2 from
		dev_mvme187, and beginning on memory_m88k.c (BATC and PATC).
		Fixing a bug in 64-bit (32-bit pairs) M88K fast stores.
		Implementing the clock part of dev_mk48txx.
		Implementing the M88K fstcr and xcr instructions.
		Implementing m88k_cpu_tlbdump().
		Beginning on the implementation of a separate address space
		for M88K .usr loads/stores.
20070520	Removing the non-working (skeleton) Sandpoint, SonyNEWS, SHARK
		Dnard, and Zaurus machine modes.
		Experimenting with dyntrans to_be_translated read-ahead. It
		seems to give a very small performance increase for MIPS
		emulation, but a large performance degradation for SuperH. Hm.
20070522	Disabling correct SuperH ITLB emulation; it does not seem to be
		necessary in order to let SH4 guest OSes run, and it slows down
		userspace code.
		Implementing "samepage" branches for SuperH emulation, and some
		other minor speed hacks.
20070525	Continuing on M88K memory-related stuff: exceptions, memory
		transaction register contents, etc.
		Implementing the M88K subu.ci instruction.
		Removing the non-working (skeleton) Iyonix machine mode.
		OpenBSD/mvme88k reaches userland :-), starts executing
		/sbin/init's instructions, and issues a few syscalls, before
		crashing.
20070526	Fixing bugs in dev_mk48txx, so that OpenBSD/mvme88k detects
		the correct time-of-day.
		Implementing a generic IRQ controller for the test machines
		(dev_irqc), similar to a proposed patch from Petr Stepan.
		Experimenting some more with translation read-ahead.
		Adding an "expect" script for automated OpenBSD/landisk
		install regression/performance tests.
20070527	Adding a dummy mmEye (SH3) machine mode skeleton.
		FINALLY found the strange M88K bug I have been hunting: I had
		not emulated the SNIP value for exceptions occurring in
		branch delay slots correctly.
		Implementing correct exceptions for 64-bit M88K loads/stores.
		Address to symbol lookups are now disabled when M88K is
		running in usermode (because usermode addresses don't have
		anything to do with supervisor addresses).
20070531	Removing the mmEye machine mode skeleton.
20070604	Some minor code cleanup.
20070605	Moving src/useremul.c into a subdir (src/useremul/), and
		cleaning up some more legacy constructs.
		Adding -Wstrict-aliasing and -fstrict-aliasing detection to
		the configure script.
20070606	Adding a check for broken GCC on Solaris to the configure
		script. (GCC 3.4.3 on Solaris cannot handle static variables
		which are initialized to 0 or NULL. :-/)
		Removing the old (non-working) ARC emulation modes: NEC RD94,
		R94, R96, and R98, and the last traces of Olivetti M700 and
		Deskstation Tyne.
		Removing the non-working skeleton WDSC device (dev_wdsc).
20070607	Thinking about how to use the host's cc + ld at runtime to
		generate native code. (See experiments/native_cc_ld_test.i
		for an example.)
20070608	Adding a program counter sampling timer, which could be useful
		for native code generation experiments.
		The KN02_CSR_NRMMOD bit in the DECstation 5000/200 (KN02) CSR
		should always be set, to allow a 5000/200 PROM to boot.
20070609	Moving out breakpoint details from the machine struct into
		a helper struct, and removing the limit on max nr of
		breakpoints.
20070610	Moving out tick functions into a helper struct as well (which
		also gets rid of the max limit).
20070612	FINALLY figured out why Debian/DECstation stopped working when
		translation read-ahead was enabled: in src/memory_rw.c, the
		call to invalidate_code_translation was made also if the
		memory access was an instruction load (if the page was mapped
		as writable); it shouldn't be called in that case.
20070613	Implementing some more MIPS32/64 revision 2 instructions: di,
		ei, ext, dext, dextm, dextu, and ins.
20070614	Implementing an instruction combination for the NetBSD/arm
		idle loop (making the host not use any cpu if NetBSD/arm
		inside the emulator is not using any cpu).
		Increasing the nr of ARM VPH entries from 128 to 384.
20070615	Removing the ENABLE_arch stuff from the configure script, so
		that all included architectures are included in both release
		and development builds.
		Moving memory related helper functions from misc.c to memory.c.
		Adding preliminary instructions for netbooting NetBSD/pmppc to
		guestoses.html; it doesn't work yet, there are weird timeouts.
		Beginning a total rewrite of the userland emulation modes
		(removing all emulation modes, beginning from scratch with
		NetBSD/MIPS and FreeBSD/Alpha only).
20070616	After fixing a bug in the DEC21143 NIC (the TDSTAT_OWN bit was
		only cleared for the last segment when transmitting, not all
		segments), NetBSD/pmppc boots with root-on-nfs without the
		timeouts. Updating guestoses.html.
		Removing the skeleton PSP (Playstation Portable) mode.
		Moving X11-related stuff in the machine struct into a helper
		struct.
		Cleanup of out-of-memory checks, to use a new CHECK_ALLOCATION
		macro (which prints a meaningful error message).
		Adding a COMMENT to each machine and device (for automagic
		.index comment generation).
		Doing regression testing for the next release.

==============  RELEASE 0.4.6  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26