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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 42 - (show 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 /*
2 * Copyright (C) 2005-2007 Anders Gavare. All rights reserved.
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are met:
6 *
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * 3. The name of the author may not be used to endorse or promote products
13 * derived from this software without specific prior written permission.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25 * SUCH DAMAGE.
26 *
27 *
28 * $Id: cpu_mips_instr.c,v 1.133 2007/06/13 02:08:03 debug Exp $
29 *
30 * MIPS instructions.
31 *
32 * Individual functions should keep track of cpu->n_translated_instrs.
33 * (If no instruction was executed, then it should be decreased. If, say, 4
34 * instructions were combined into one function and executed, then it should
35 * be increased by 3.)
36 */
37
38
39 /*
40 * COPROC_AVAILABILITY_CHECK(n) checks for the coprocessor available bit for
41 * coprocessor number n, and causes a CoProcessor Unusable exception if it
42 * is not set. (Note: For coprocessor 0 checks, use cop0_availability_check!)
43 */
44 #ifndef COPROC_AVAILABILITY_CHECK
45 #define COPROC_AVAILABILITY_CHECK(x) { \
46 const int cpnr = (x); \
47 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page) \
48 / sizeof(struct mips_instr_call); \
49 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) \
50 << MIPS_INSTR_ALIGNMENT_SHIFT); \
51 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT); \
52 if (!(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & \
53 ((1 << cpnr) << STATUS_CU_SHIFT)) ) { \
54 mips_cpu_exception(cpu, EXCEPTION_CPU, \
55 0, 0, cpnr, 0, 0, 0); \
56 return; \
57 } \
58 }
59 #endif
60
61
62 #ifndef COP0_AVAILABILITY_CHECK_INCLUDED
63 #define COP0_AVAILABILITY_CHECK_INCLUDED
64 /*
65 * cop0_availability_check() causes a CoProcessor Unusable exception if
66 * we are currently running in usermode, and the coprocessor available bit
67 * for coprocessor 0 is not set.
68 *
69 * Returns 1 if ok (i.e. if the coprocessor was usable), 0 on exceptions.
70 */
71 int cop0_availability_check(struct cpu *cpu, struct mips_instr_call *ic)
72 {
73 int in_usermode = 0;
74 struct mips_coproc *cp0 = cpu->cd.mips.coproc[0];
75
76 switch (cpu->cd.mips.cpu_type.exc_model) {
77 case EXC3K:
78 /*
79 * NOTE: If the KU bit is checked, Linux crashes.
80 * It is the PC that counts.
81 *
82 * TODO: Check whether this is true or not for R4000 as well.
83 */
84 /* TODO: if (cp0->reg[COP0_STATUS] & MIPS1_SR_KU_CUR) */
85 if (cpu->pc <= 0x7fffffff)
86 in_usermode = 1;
87 break;
88 default:
89 /* R4000 etc: (TODO: How about supervisor mode?) */
90 if (((cp0->reg[COP0_STATUS] &
91 STATUS_KSU_MASK) >> STATUS_KSU_SHIFT) != KSU_KERNEL)
92 in_usermode = 1;
93 if (cp0->reg[COP0_STATUS] & (STATUS_ERL | STATUS_EXL))
94 in_usermode = 0;
95 break;
96 }
97
98 if (in_usermode) {
99 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
100 / sizeof(struct mips_instr_call);
101 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
102 << MIPS_INSTR_ALIGNMENT_SHIFT);
103 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
104 if (!(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &
105 (1 << STATUS_CU_SHIFT)) ) {
106 mips_cpu_exception(cpu, EXCEPTION_CPU,
107 0, 0, /* cpnr */ 0, 0, 0, 0);
108 return 0;
109 }
110 }
111
112 return 1;
113 }
114 #endif
115
116
117 /*
118 * invalid: For catching bugs.
119 */
120 X(invalid)
121 {
122 fatal("FATAL ERROR: An internal error occured in the MIPS"
123 " dyntrans code. Please contact the author with detailed"
124 " repro steps on how to trigger this bug.\n");
125 exit(1);
126 }
127
128
129 /*
130 * reserved: Attempt to execute a reserved instruction (e.g. a 64-bit
131 * instruction on an emulated 32-bit processor).
132 */
133 X(reserved)
134 {
135 /* Synchronize the PC and cause an exception: */
136 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
137 / sizeof(struct mips_instr_call);
138 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
139 << MIPS_INSTR_ALIGNMENT_SHIFT);
140 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
141 mips_cpu_exception(cpu, EXCEPTION_RI, 0, 0, 0, 0, 0, 0);
142 }
143
144
145 /*
146 * cpu: Cause a CoProcessor Unusable exception.
147 *
148 * arg[0] = the number of the coprocessor
149 */
150 X(cpu)
151 {
152 /* Synchronize the PC and cause an exception: */
153 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
154 / sizeof(struct mips_instr_call);
155 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
156 << MIPS_INSTR_ALIGNMENT_SHIFT);
157 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
158 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, ic->arg[0], 0, 0, 0);
159 }
160
161
162 /*
163 * nop: Do nothing.
164 */
165 X(nop)
166 {
167 }
168
169
170 /*
171 * beq: Branch if equal
172 * bne: Branch if not equal
173 * b: Branch (comparing a register to itself, always true)
174 *
175 * arg[0] = pointer to rs
176 * arg[1] = pointer to rt
177 * arg[2] = (int32_t) relative offset from the next instruction
178 */
179 X(beq)
180 {
181 MODE_int_t old_pc = cpu->pc;
182 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
183 int x = rs == rt;
184 cpu->delay_slot = TO_BE_DELAYED;
185 ic[1].f(cpu, ic+1);
186 cpu->n_translated_instrs ++;
187 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
188 /* Note: Must be non-delayed when jumping to the new pc: */
189 cpu->delay_slot = NOT_DELAYED;
190 if (x) {
191 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
192 MIPS_INSTR_ALIGNMENT_SHIFT);
193 cpu->pc = old_pc + (int32_t)ic->arg[2];
194 quick_pc_to_pointers(cpu);
195 } else
196 cpu->cd.mips.next_ic ++;
197 } else
198 cpu->delay_slot = NOT_DELAYED;
199 }
200 X(beq_samepage)
201 {
202 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
203 int x = rs == rt;
204 cpu->delay_slot = TO_BE_DELAYED;
205 ic[1].f(cpu, ic+1);
206 cpu->n_translated_instrs ++;
207 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
208 if (x)
209 cpu->cd.mips.next_ic = (struct mips_instr_call *)
210 ic->arg[2];
211 else
212 cpu->cd.mips.next_ic ++;
213 }
214 cpu->delay_slot = NOT_DELAYED;
215 }
216 X(beq_samepage_addiu)
217 {
218 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
219 cpu->n_translated_instrs ++;
220 reg(ic[1].arg[1]) = (int32_t)
221 ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
222 if (rs == rt)
223 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
224 else
225 cpu->cd.mips.next_ic ++;
226 }
227 X(beq_samepage_nop)
228 {
229 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
230 cpu->n_translated_instrs ++;
231 if (rs == rt)
232 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
233 else
234 cpu->cd.mips.next_ic ++;
235 }
236 X(bne)
237 {
238 MODE_int_t old_pc = cpu->pc;
239 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
240 int x = rs != rt;
241 cpu->delay_slot = TO_BE_DELAYED;
242 ic[1].f(cpu, ic+1);
243 cpu->n_translated_instrs ++;
244 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
245 /* Note: Must be non-delayed when jumping to the new pc: */
246 cpu->delay_slot = NOT_DELAYED;
247 if (x) {
248 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
249 MIPS_INSTR_ALIGNMENT_SHIFT);
250 cpu->pc = old_pc + (int32_t)ic->arg[2];
251 quick_pc_to_pointers(cpu);
252 } else
253 cpu->cd.mips.next_ic ++;
254 } else
255 cpu->delay_slot = NOT_DELAYED;
256 }
257 X(bne_samepage)
258 {
259 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
260 int x = rs != rt;
261 cpu->delay_slot = TO_BE_DELAYED;
262 ic[1].f(cpu, ic+1);
263 cpu->n_translated_instrs ++;
264 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
265 if (x)
266 cpu->cd.mips.next_ic = (struct mips_instr_call *)
267 ic->arg[2];
268 else
269 cpu->cd.mips.next_ic ++;
270 }
271 cpu->delay_slot = NOT_DELAYED;
272 }
273 X(bne_samepage_addiu)
274 {
275 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
276 cpu->n_translated_instrs ++;
277 reg(ic[1].arg[1]) = (int32_t)
278 ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
279 if (rs != rt)
280 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
281 else
282 cpu->cd.mips.next_ic ++;
283 }
284 X(bne_samepage_nop)
285 {
286 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
287 cpu->n_translated_instrs ++;
288 if (rs != rt)
289 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
290 else
291 cpu->cd.mips.next_ic ++;
292 }
293 X(b)
294 {
295 MODE_int_t old_pc = cpu->pc;
296 cpu->delay_slot = TO_BE_DELAYED;
297 ic[1].f(cpu, ic+1);
298 cpu->n_translated_instrs ++;
299 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
300 /* Note: Must be non-delayed when jumping to the new pc: */
301 cpu->delay_slot = NOT_DELAYED;
302 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
303 MIPS_INSTR_ALIGNMENT_SHIFT);
304 cpu->pc = old_pc + (int32_t)ic->arg[2];
305 quick_pc_to_pointers(cpu);
306 } else
307 cpu->delay_slot = NOT_DELAYED;
308 }
309 X(b_samepage)
310 {
311 cpu->delay_slot = TO_BE_DELAYED;
312 ic[1].f(cpu, ic+1);
313 cpu->n_translated_instrs ++;
314 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT))
315 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
316 cpu->delay_slot = NOT_DELAYED;
317 }
318
319
320 /*
321 * beql: Branch if equal likely
322 * bnel: Branch if not equal likely
323 *
324 * arg[0] = pointer to rs
325 * arg[1] = pointer to rt
326 * arg[2] = (int32_t) relative offset from the next instruction
327 */
328 X(beql)
329 {
330 MODE_int_t old_pc = cpu->pc;
331 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
332 int x = rs == rt;
333 cpu->delay_slot = TO_BE_DELAYED;
334 if (x)
335 ic[1].f(cpu, ic+1);
336 cpu->n_translated_instrs ++;
337 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
338 /* Note: Must be non-delayed when jumping to the new pc: */
339 cpu->delay_slot = NOT_DELAYED;
340 if (x) {
341 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
342 MIPS_INSTR_ALIGNMENT_SHIFT);
343 cpu->pc = old_pc + (int32_t)ic->arg[2];
344 quick_pc_to_pointers(cpu);
345 } else
346 cpu->cd.mips.next_ic ++;
347 } else
348 cpu->delay_slot = NOT_DELAYED;
349 }
350 X(beql_samepage)
351 {
352 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
353 int x = rs == rt;
354 cpu->delay_slot = TO_BE_DELAYED;
355 if (x)
356 ic[1].f(cpu, ic+1);
357 cpu->n_translated_instrs ++;
358 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
359 if (x)
360 cpu->cd.mips.next_ic = (struct mips_instr_call *)
361 ic->arg[2];
362 else
363 cpu->cd.mips.next_ic ++;
364 }
365 cpu->delay_slot = NOT_DELAYED;
366 }
367 X(bnel)
368 {
369 MODE_int_t old_pc = cpu->pc;
370 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
371 int x = rs != rt;
372 cpu->delay_slot = TO_BE_DELAYED;
373 if (x)
374 ic[1].f(cpu, ic+1);
375 cpu->n_translated_instrs ++;
376 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
377 /* Note: Must be non-delayed when jumping to the new pc: */
378 cpu->delay_slot = NOT_DELAYED;
379 if (x) {
380 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
381 MIPS_INSTR_ALIGNMENT_SHIFT);
382 cpu->pc = old_pc + (int32_t)ic->arg[2];
383 quick_pc_to_pointers(cpu);
384 } else
385 cpu->cd.mips.next_ic ++;
386 } else
387 cpu->delay_slot = NOT_DELAYED;
388 }
389 X(bnel_samepage)
390 {
391 MODE_uint_t rs = reg(ic->arg[0]), rt = reg(ic->arg[1]);
392 int x = rs != rt;
393 cpu->delay_slot = TO_BE_DELAYED;
394 if (x)
395 ic[1].f(cpu, ic+1);
396 cpu->n_translated_instrs ++;
397 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
398 if (x)
399 cpu->cd.mips.next_ic = (struct mips_instr_call *)
400 ic->arg[2];
401 else
402 cpu->cd.mips.next_ic ++;
403 }
404 cpu->delay_slot = NOT_DELAYED;
405 }
406
407
408 /*
409 * blez: Branch if less than or equal
410 * blezl: Branch if less than or equal likely
411 *
412 * arg[0] = pointer to rs
413 * arg[2] = (int32_t) relative offset from the next instruction
414 */
415 X(blez)
416 {
417 MODE_int_t old_pc = cpu->pc;
418 MODE_int_t rs = reg(ic->arg[0]);
419 int x = (rs <= 0);
420 cpu->delay_slot = TO_BE_DELAYED;
421 ic[1].f(cpu, ic+1);
422 cpu->n_translated_instrs ++;
423 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
424 /* Note: Must be non-delayed when jumping to the new pc: */
425 cpu->delay_slot = NOT_DELAYED;
426 if (x) {
427 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
428 MIPS_INSTR_ALIGNMENT_SHIFT);
429 cpu->pc = old_pc + (int32_t)ic->arg[2];
430 quick_pc_to_pointers(cpu);
431 } else
432 cpu->cd.mips.next_ic ++;
433 } else
434 cpu->delay_slot = NOT_DELAYED;
435 }
436 X(blez_samepage)
437 {
438 MODE_int_t rs = reg(ic->arg[0]);
439 int x = (rs <= 0);
440 cpu->delay_slot = TO_BE_DELAYED;
441 ic[1].f(cpu, ic+1);
442 cpu->n_translated_instrs ++;
443 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
444 if (x)
445 cpu->cd.mips.next_ic = (struct mips_instr_call *)
446 ic->arg[2];
447 else
448 cpu->cd.mips.next_ic ++;
449 }
450 cpu->delay_slot = NOT_DELAYED;
451 }
452 X(blezl)
453 {
454 MODE_int_t old_pc = cpu->pc;
455 MODE_int_t rs = reg(ic->arg[0]);
456 int x = (rs <= 0);
457 cpu->delay_slot = TO_BE_DELAYED;
458 if (x)
459 ic[1].f(cpu, ic+1);
460 cpu->n_translated_instrs ++;
461 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
462 /* Note: Must be non-delayed when jumping to the new pc: */
463 cpu->delay_slot = NOT_DELAYED;
464 if (x) {
465 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
466 MIPS_INSTR_ALIGNMENT_SHIFT);
467 cpu->pc = old_pc + (int32_t)ic->arg[2];
468 quick_pc_to_pointers(cpu);
469 } else
470 cpu->cd.mips.next_ic ++;
471 } else
472 cpu->delay_slot = NOT_DELAYED;
473 }
474 X(blezl_samepage)
475 {
476 MODE_int_t rs = reg(ic->arg[0]);
477 int x = (rs <= 0);
478 cpu->delay_slot = TO_BE_DELAYED;
479 if (x)
480 ic[1].f(cpu, ic+1);
481 cpu->n_translated_instrs ++;
482 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
483 if (x)
484 cpu->cd.mips.next_ic = (struct mips_instr_call *)
485 ic->arg[2];
486 else
487 cpu->cd.mips.next_ic ++;
488 }
489 cpu->delay_slot = NOT_DELAYED;
490 }
491
492
493 /*
494 * bltz: Branch if less than
495 * bltzl: Branch if less than likely
496 *
497 * arg[0] = pointer to rs
498 * arg[2] = (int32_t) relative offset from the next instruction
499 */
500 X(bltz)
501 {
502 MODE_int_t old_pc = cpu->pc;
503 MODE_int_t rs = reg(ic->arg[0]);
504 int x = (rs < 0);
505 cpu->delay_slot = TO_BE_DELAYED;
506 ic[1].f(cpu, ic+1);
507 cpu->n_translated_instrs ++;
508 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
509 /* Note: Must be non-delayed when jumping to the new pc: */
510 cpu->delay_slot = NOT_DELAYED;
511 if (x) {
512 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
513 MIPS_INSTR_ALIGNMENT_SHIFT);
514 cpu->pc = old_pc + (int32_t)ic->arg[2];
515 quick_pc_to_pointers(cpu);
516 } else
517 cpu->cd.mips.next_ic ++;
518 } else
519 cpu->delay_slot = NOT_DELAYED;
520 }
521 X(bltz_samepage)
522 {
523 MODE_int_t rs = reg(ic->arg[0]);
524 int x = (rs < 0);
525 cpu->delay_slot = TO_BE_DELAYED;
526 ic[1].f(cpu, ic+1);
527 cpu->n_translated_instrs ++;
528 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
529 if (x)
530 cpu->cd.mips.next_ic = (struct mips_instr_call *)
531 ic->arg[2];
532 else
533 cpu->cd.mips.next_ic ++;
534 }
535 cpu->delay_slot = NOT_DELAYED;
536 }
537 X(bltzl)
538 {
539 MODE_int_t old_pc = cpu->pc;
540 MODE_int_t rs = reg(ic->arg[0]);
541 int x = (rs < 0);
542 cpu->delay_slot = TO_BE_DELAYED;
543 if (x)
544 ic[1].f(cpu, ic+1);
545 cpu->n_translated_instrs ++;
546 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
547 /* Note: Must be non-delayed when jumping to the new pc: */
548 cpu->delay_slot = NOT_DELAYED;
549 if (x) {
550 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
551 MIPS_INSTR_ALIGNMENT_SHIFT);
552 cpu->pc = old_pc + (int32_t)ic->arg[2];
553 quick_pc_to_pointers(cpu);
554 } else
555 cpu->cd.mips.next_ic ++;
556 } else
557 cpu->delay_slot = NOT_DELAYED;
558 }
559 X(bltzl_samepage)
560 {
561 MODE_int_t rs = reg(ic->arg[0]);
562 int x = (rs < 0);
563 cpu->delay_slot = TO_BE_DELAYED;
564 if (x)
565 ic[1].f(cpu, ic+1);
566 cpu->n_translated_instrs ++;
567 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
568 if (x)
569 cpu->cd.mips.next_ic = (struct mips_instr_call *)
570 ic->arg[2];
571 else
572 cpu->cd.mips.next_ic ++;
573 }
574 cpu->delay_slot = NOT_DELAYED;
575 }
576
577
578 /*
579 * bgez: Branch if greater than or equal
580 * bgezl: Branch if greater than or equal likely
581 *
582 * arg[0] = pointer to rs
583 * arg[2] = (int32_t) relative offset from the next instruction
584 */
585 X(bgez)
586 {
587 MODE_int_t old_pc = cpu->pc;
588 MODE_int_t rs = reg(ic->arg[0]);
589 int x = (rs >= 0);
590 cpu->delay_slot = TO_BE_DELAYED;
591 ic[1].f(cpu, ic+1);
592 cpu->n_translated_instrs ++;
593 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
594 /* Note: Must be non-delayed when jumping to the new pc: */
595 cpu->delay_slot = NOT_DELAYED;
596 if (x) {
597 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
598 MIPS_INSTR_ALIGNMENT_SHIFT);
599 cpu->pc = old_pc + (int32_t)ic->arg[2];
600 quick_pc_to_pointers(cpu);
601 } else
602 cpu->cd.mips.next_ic ++;
603 } else
604 cpu->delay_slot = NOT_DELAYED;
605 }
606 X(bgez_samepage)
607 {
608 MODE_int_t rs = reg(ic->arg[0]);
609 int x = (rs >= 0);
610 cpu->delay_slot = TO_BE_DELAYED;
611 ic[1].f(cpu, ic+1);
612 cpu->n_translated_instrs ++;
613 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
614 if (x)
615 cpu->cd.mips.next_ic = (struct mips_instr_call *)
616 ic->arg[2];
617 else
618 cpu->cd.mips.next_ic ++;
619 }
620 cpu->delay_slot = NOT_DELAYED;
621 }
622 X(bgezl)
623 {
624 MODE_int_t old_pc = cpu->pc;
625 MODE_int_t rs = reg(ic->arg[0]);
626 int x = (rs >= 0);
627 cpu->delay_slot = TO_BE_DELAYED;
628 if (x)
629 ic[1].f(cpu, ic+1);
630 cpu->n_translated_instrs ++;
631 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
632 /* Note: Must be non-delayed when jumping to the new pc: */
633 cpu->delay_slot = NOT_DELAYED;
634 if (x) {
635 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
636 MIPS_INSTR_ALIGNMENT_SHIFT);
637 cpu->pc = old_pc + (int32_t)ic->arg[2];
638 quick_pc_to_pointers(cpu);
639 } else
640 cpu->cd.mips.next_ic ++;
641 } else
642 cpu->delay_slot = NOT_DELAYED;
643 }
644 X(bgezl_samepage)
645 {
646 MODE_int_t rs = reg(ic->arg[0]);
647 int x = (rs >= 0);
648 cpu->delay_slot = TO_BE_DELAYED;
649 if (x)
650 ic[1].f(cpu, ic+1);
651 cpu->n_translated_instrs ++;
652 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
653 if (x)
654 cpu->cd.mips.next_ic = (struct mips_instr_call *)
655 ic->arg[2];
656 else
657 cpu->cd.mips.next_ic ++;
658 }
659 cpu->delay_slot = NOT_DELAYED;
660 }
661
662
663 /*
664 * bgezal: Branch if greater than or equal (and link)
665 * bgezall: Branch if greater than or equal (and link) likely
666 *
667 * arg[0] = pointer to rs
668 * arg[2] = (int32_t) relative offset from the next instruction
669 */
670 X(bgezal)
671 {
672 MODE_int_t old_pc = cpu->pc;
673 MODE_int_t rs = reg(ic->arg[0]);
674 int x = (rs >= 0), low_pc;
675
676 cpu->delay_slot = TO_BE_DELAYED;
677 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
678 / sizeof(struct mips_instr_call);
679 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
680 << MIPS_INSTR_ALIGNMENT_SHIFT);
681 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
682 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
683
684 ic[1].f(cpu, ic+1);
685 cpu->n_translated_instrs ++;
686 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
687 /* Note: Must be non-delayed when jumping to the new pc: */
688 cpu->delay_slot = NOT_DELAYED;
689 if (x) {
690 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
691 MIPS_INSTR_ALIGNMENT_SHIFT);
692 cpu->pc = old_pc + (int32_t)ic->arg[2];
693 quick_pc_to_pointers(cpu);
694 } else
695 cpu->cd.mips.next_ic ++;
696 } else
697 cpu->delay_slot = NOT_DELAYED;
698 }
699 X(bgezal_samepage)
700 {
701 MODE_int_t rs = reg(ic->arg[0]);
702 int x = (rs >= 0), low_pc;
703
704 cpu->delay_slot = TO_BE_DELAYED;
705 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
706 / sizeof(struct mips_instr_call);
707 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
708 << MIPS_INSTR_ALIGNMENT_SHIFT);
709 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
710 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
711
712 ic[1].f(cpu, ic+1);
713 cpu->n_translated_instrs ++;
714 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
715 if (x)
716 cpu->cd.mips.next_ic = (struct mips_instr_call *)
717 ic->arg[2];
718 else
719 cpu->cd.mips.next_ic ++;
720 }
721 cpu->delay_slot = NOT_DELAYED;
722 }
723 X(bgezall)
724 {
725 MODE_int_t old_pc = cpu->pc;
726 MODE_int_t rs = reg(ic->arg[0]);
727 int x = (rs >= 0), low_pc;
728
729 cpu->delay_slot = TO_BE_DELAYED;
730 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
731 / sizeof(struct mips_instr_call);
732 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
733 << MIPS_INSTR_ALIGNMENT_SHIFT);
734 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
735 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
736
737 if (x)
738 ic[1].f(cpu, ic+1);
739 cpu->n_translated_instrs ++;
740 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
741 /* Note: Must be non-delayed when jumping to the new pc: */
742 cpu->delay_slot = NOT_DELAYED;
743 if (x) {
744 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
745 MIPS_INSTR_ALIGNMENT_SHIFT);
746 cpu->pc = old_pc + (int32_t)ic->arg[2];
747 quick_pc_to_pointers(cpu);
748 } else
749 cpu->cd.mips.next_ic ++;
750 } else
751 cpu->delay_slot = NOT_DELAYED;
752 }
753 X(bgezall_samepage)
754 {
755 MODE_int_t rs = reg(ic->arg[0]);
756 int x = (rs >= 0), low_pc;
757
758 cpu->delay_slot = TO_BE_DELAYED;
759 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
760 / sizeof(struct mips_instr_call);
761 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
762 << MIPS_INSTR_ALIGNMENT_SHIFT);
763 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
764 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
765
766 if (x)
767 ic[1].f(cpu, ic+1);
768 cpu->n_translated_instrs ++;
769 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
770 if (x)
771 cpu->cd.mips.next_ic = (struct mips_instr_call *)
772 ic->arg[2];
773 else
774 cpu->cd.mips.next_ic ++;
775 }
776 cpu->delay_slot = NOT_DELAYED;
777 }
778
779
780 /*
781 * bltzal: Branch if less than zero (and link)
782 * bltzall: Branch if less than zero (and link) likely
783 *
784 * arg[0] = pointer to rs
785 * arg[2] = (int32_t) relative offset from the next instruction
786 */
787 X(bltzal)
788 {
789 MODE_int_t old_pc = cpu->pc;
790 MODE_int_t rs = reg(ic->arg[0]);
791 int x = (rs < 0), low_pc;
792
793 cpu->delay_slot = TO_BE_DELAYED;
794 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
795 / sizeof(struct mips_instr_call);
796 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
797 << MIPS_INSTR_ALIGNMENT_SHIFT);
798 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
799 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
800
801 ic[1].f(cpu, ic+1);
802 cpu->n_translated_instrs ++;
803 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
804 /* Note: Must be non-delayed when jumping to the new pc: */
805 cpu->delay_slot = NOT_DELAYED;
806 if (x) {
807 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
808 MIPS_INSTR_ALIGNMENT_SHIFT);
809 cpu->pc = old_pc + (int32_t)ic->arg[2];
810 quick_pc_to_pointers(cpu);
811 } else
812 cpu->cd.mips.next_ic ++;
813 } else
814 cpu->delay_slot = NOT_DELAYED;
815 }
816 X(bltzal_samepage)
817 {
818 MODE_int_t rs = reg(ic->arg[0]);
819 int x = (rs < 0), low_pc;
820
821 cpu->delay_slot = TO_BE_DELAYED;
822 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
823 / sizeof(struct mips_instr_call);
824 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
825 << MIPS_INSTR_ALIGNMENT_SHIFT);
826 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
827 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
828
829 ic[1].f(cpu, ic+1);
830 cpu->n_translated_instrs ++;
831 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
832 if (x)
833 cpu->cd.mips.next_ic = (struct mips_instr_call *)
834 ic->arg[2];
835 else
836 cpu->cd.mips.next_ic ++;
837 }
838 cpu->delay_slot = NOT_DELAYED;
839 }
840 X(bltzall)
841 {
842 MODE_int_t old_pc = cpu->pc;
843 MODE_int_t rs = reg(ic->arg[0]);
844 int x = (rs < 0), low_pc;
845
846 cpu->delay_slot = TO_BE_DELAYED;
847 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
848 / sizeof(struct mips_instr_call);
849 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
850 << MIPS_INSTR_ALIGNMENT_SHIFT);
851 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
852 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
853
854 if (x)
855 ic[1].f(cpu, ic+1);
856 cpu->n_translated_instrs ++;
857 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
858 /* Note: Must be non-delayed when jumping to the new pc: */
859 cpu->delay_slot = NOT_DELAYED;
860 if (x) {
861 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
862 MIPS_INSTR_ALIGNMENT_SHIFT);
863 cpu->pc = old_pc + (int32_t)ic->arg[2];
864 quick_pc_to_pointers(cpu);
865 } else
866 cpu->cd.mips.next_ic ++;
867 } else
868 cpu->delay_slot = NOT_DELAYED;
869 }
870 X(bltzall_samepage)
871 {
872 MODE_int_t rs = reg(ic->arg[0]);
873 int x = (rs < 0), low_pc;
874
875 cpu->delay_slot = TO_BE_DELAYED;
876 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
877 / sizeof(struct mips_instr_call);
878 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
879 << MIPS_INSTR_ALIGNMENT_SHIFT);
880 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
881 cpu->cd.mips.gpr[MIPS_GPR_RA] = cpu->pc + 8;
882
883 if (x)
884 ic[1].f(cpu, ic+1);
885 cpu->n_translated_instrs ++;
886 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
887 if (x)
888 cpu->cd.mips.next_ic = (struct mips_instr_call *)
889 ic->arg[2];
890 else
891 cpu->cd.mips.next_ic ++;
892 }
893 cpu->delay_slot = NOT_DELAYED;
894 }
895
896
897 /*
898 * bgtz: Branch if greater than zero
899 * bgtzl: Branch if greater than zero likely
900 *
901 * arg[0] = pointer to rs
902 * arg[2] = (int32_t) relative offset from the next instruction
903 */
904 X(bgtz)
905 {
906 MODE_int_t old_pc = cpu->pc;
907 MODE_int_t rs = reg(ic->arg[0]);
908 int x = (rs > 0);
909 cpu->delay_slot = TO_BE_DELAYED;
910 ic[1].f(cpu, ic+1);
911 cpu->n_translated_instrs ++;
912 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
913 /* Note: Must be non-delayed when jumping to the new pc: */
914 cpu->delay_slot = NOT_DELAYED;
915 if (x) {
916 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
917 MIPS_INSTR_ALIGNMENT_SHIFT);
918 cpu->pc = old_pc + (int32_t)ic->arg[2];
919 quick_pc_to_pointers(cpu);
920 } else
921 cpu->cd.mips.next_ic ++;
922 } else
923 cpu->delay_slot = NOT_DELAYED;
924 }
925 X(bgtz_samepage)
926 {
927 MODE_int_t rs = reg(ic->arg[0]);
928 int x = (rs > 0);
929 cpu->delay_slot = TO_BE_DELAYED;
930 ic[1].f(cpu, ic+1);
931 cpu->n_translated_instrs ++;
932 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
933 if (x)
934 cpu->cd.mips.next_ic = (struct mips_instr_call *)
935 ic->arg[2];
936 else
937 cpu->cd.mips.next_ic ++;
938 }
939 cpu->delay_slot = NOT_DELAYED;
940 }
941 X(bgtzl)
942 {
943 MODE_int_t old_pc = cpu->pc;
944 MODE_int_t rs = reg(ic->arg[0]);
945 int x = (rs > 0);
946 cpu->delay_slot = TO_BE_DELAYED;
947 if (x)
948 ic[1].f(cpu, ic+1);
949 cpu->n_translated_instrs ++;
950 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
951 /* Note: Must be non-delayed when jumping to the new pc: */
952 cpu->delay_slot = NOT_DELAYED;
953 if (x) {
954 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
955 MIPS_INSTR_ALIGNMENT_SHIFT);
956 cpu->pc = old_pc + (int32_t)ic->arg[2];
957 quick_pc_to_pointers(cpu);
958 } else
959 cpu->cd.mips.next_ic ++;
960 } else
961 cpu->delay_slot = NOT_DELAYED;
962 }
963 X(bgtzl_samepage)
964 {
965 MODE_int_t rs = reg(ic->arg[0]);
966 int x = (rs > 0);
967 cpu->delay_slot = TO_BE_DELAYED;
968 if (x)
969 ic[1].f(cpu, ic+1);
970 cpu->n_translated_instrs ++;
971 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
972 if (x)
973 cpu->cd.mips.next_ic = (struct mips_instr_call *)
974 ic->arg[2];
975 else
976 cpu->cd.mips.next_ic ++;
977 }
978 cpu->delay_slot = NOT_DELAYED;
979 }
980
981
982 /*
983 * jr, jalr: Jump to a register [and link].
984 *
985 * arg[0] = ptr to rs
986 * arg[1] = ptr to rd (for jalr)
987 * arg[2] = (int32_t) relative offset of the next instruction
988 */
989 X(jr)
990 {
991 MODE_int_t rs = reg(ic->arg[0]);
992 cpu->delay_slot = TO_BE_DELAYED;
993 ic[1].f(cpu, ic+1);
994 cpu->n_translated_instrs ++;
995 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
996 cpu->pc = rs;
997 /* Note: Must be non-delayed when jumping to the new pc: */
998 cpu->delay_slot = NOT_DELAYED;
999 quick_pc_to_pointers(cpu);
1000 } else
1001 cpu->delay_slot = NOT_DELAYED;
1002 }
1003 X(jr_ra)
1004 {
1005 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
1006 cpu->delay_slot = TO_BE_DELAYED;
1007 ic[1].f(cpu, ic+1);
1008 cpu->n_translated_instrs ++;
1009 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1010 cpu->pc = rs;
1011 /* Note: Must be non-delayed when jumping to the new pc: */
1012 cpu->delay_slot = NOT_DELAYED;
1013 quick_pc_to_pointers(cpu);
1014 } else
1015 cpu->delay_slot = NOT_DELAYED;
1016 }
1017 X(jr_ra_addiu)
1018 {
1019 /* jr ra, followed by an addiu */
1020 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
1021 reg(ic[1].arg[1]) = (int32_t)
1022 ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
1023 cpu->pc = rs;
1024 quick_pc_to_pointers(cpu);
1025 cpu->n_translated_instrs ++;
1026 }
1027 X(jr_ra_trace)
1028 {
1029 MODE_int_t rs = cpu->cd.mips.gpr[MIPS_GPR_RA];
1030 cpu->delay_slot = TO_BE_DELAYED;
1031 ic[1].f(cpu, ic+1);
1032 cpu->n_translated_instrs ++;
1033 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1034 cpu->pc = rs;
1035 cpu_functioncall_trace_return(cpu);
1036 /* Note: Must be non-delayed when jumping to the new pc: */
1037 cpu->delay_slot = NOT_DELAYED;
1038 quick_pc_to_pointers(cpu);
1039 } else
1040 cpu->delay_slot = NOT_DELAYED;
1041 }
1042 X(jalr)
1043 {
1044 MODE_int_t rs = reg(ic->arg[0]), rd;
1045 cpu->delay_slot = TO_BE_DELAYED;
1046 rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1047 MIPS_INSTR_ALIGNMENT_SHIFT);
1048 rd += (int32_t)ic->arg[2];
1049 reg(ic->arg[1]) = rd;
1050 ic[1].f(cpu, ic+1);
1051 cpu->n_translated_instrs ++;
1052 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1053 cpu->pc = rs;
1054 /* Note: Must be non-delayed when jumping to the new pc: */
1055 cpu->delay_slot = NOT_DELAYED;
1056 quick_pc_to_pointers(cpu);
1057 } else
1058 cpu->delay_slot = NOT_DELAYED;
1059 }
1060 X(jalr_trace)
1061 {
1062 MODE_int_t rs = reg(ic->arg[0]), rd;
1063 cpu->delay_slot = TO_BE_DELAYED;
1064 rd = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1065 MIPS_INSTR_ALIGNMENT_SHIFT);
1066 rd += (int32_t)ic->arg[2];
1067 reg(ic->arg[1]) = rd;
1068 ic[1].f(cpu, ic+1);
1069 cpu->n_translated_instrs ++;
1070 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1071 cpu->pc = rs;
1072 cpu_functioncall_trace(cpu, cpu->pc);
1073 /* Note: Must be non-delayed when jumping to the new pc: */
1074 cpu->delay_slot = NOT_DELAYED;
1075 quick_pc_to_pointers(cpu);
1076 } else
1077 cpu->delay_slot = NOT_DELAYED;
1078 }
1079
1080
1081 /*
1082 * j, jal: Jump [and link].
1083 *
1084 * arg[0] = lowest 28 bits of new pc.
1085 * arg[1] = offset from start of page to the jal instruction + 8
1086 */
1087 X(j)
1088 {
1089 MODE_int_t old_pc = cpu->pc;
1090 cpu->delay_slot = TO_BE_DELAYED;
1091 ic[1].f(cpu, ic+1);
1092 cpu->n_translated_instrs ++;
1093 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1094 /* Note: Must be non-delayed when jumping to the new pc: */
1095 cpu->delay_slot = NOT_DELAYED;
1096 old_pc &= ~0x03ffffff;
1097 cpu->pc = old_pc | (uint32_t)ic->arg[0];
1098 quick_pc_to_pointers(cpu);
1099 } else
1100 cpu->delay_slot = NOT_DELAYED;
1101 }
1102 X(jal)
1103 {
1104 MODE_int_t old_pc = cpu->pc;
1105 cpu->delay_slot = TO_BE_DELAYED;
1106 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1107 cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
1108 ic[1].f(cpu, ic+1);
1109 cpu->n_translated_instrs ++;
1110 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1111 /* Note: Must be non-delayed when jumping to the new pc: */
1112 cpu->delay_slot = NOT_DELAYED;
1113 old_pc &= ~0x03ffffff;
1114 cpu->pc = old_pc | (int32_t)ic->arg[0];
1115 quick_pc_to_pointers(cpu);
1116 } else
1117 cpu->delay_slot = NOT_DELAYED;
1118 }
1119 X(jal_trace)
1120 {
1121 MODE_int_t old_pc = cpu->pc;
1122 cpu->delay_slot = TO_BE_DELAYED;
1123 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1124 cpu->cd.mips.gpr[31] = (MODE_int_t)cpu->pc + (int32_t)ic->arg[1];
1125 ic[1].f(cpu, ic+1);
1126 cpu->n_translated_instrs ++;
1127 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1128 /* Note: Must be non-delayed when jumping to the new pc: */
1129 cpu->delay_slot = NOT_DELAYED;
1130 old_pc &= ~0x03ffffff;
1131 cpu->pc = old_pc | (int32_t)ic->arg[0];
1132 cpu_functioncall_trace(cpu, cpu->pc);
1133 quick_pc_to_pointers(cpu);
1134 } else
1135 cpu->delay_slot = NOT_DELAYED;
1136 }
1137
1138
1139 /*
1140 * cache: Cache operation.
1141 */
1142 X(cache)
1143 {
1144 /* TODO: Implement cache operations. */
1145
1146 /* Make sure the rmw bit is cleared: */
1147 cpu->cd.mips.rmw = 0;
1148 }
1149
1150
1151 /*
1152 * 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 * 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 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 }
1188
1189
1190 /*
1191 * 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 * 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 * 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 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
1254
1255 /*
1256 * 2-register:
1257 *
1258 * arg[0] = ptr to rs
1259 * arg[1] = ptr to rt
1260 */
1261 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 cpu->cd.mips.lo = (int32_t)res;
1270 cpu->cd.mips.hi = (int32_t)rem;
1271 }
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 cpu->cd.mips.lo = (int32_t)res;
1281 cpu->cd.mips.hi = (int32_t)rem;
1282 }
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 cpu->cd.mips.lo = res;
1293 cpu->cd.mips.hi = rem;
1294 }
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 cpu->cd.mips.lo = res;
1305 cpu->cd.mips.hi = rem;
1306 }
1307 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 cpu->cd.mips.lo = (int32_t)res;
1312 cpu->cd.mips.hi = (int32_t)(res >> 32);
1313 }
1314 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 cpu->cd.mips.lo = (int32_t)res;
1321 cpu->cd.mips.hi = (int32_t)(res >> 32);
1322 reg(ic->arg[2]) = (int32_t)res;
1323 }
1324 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 cpu->cd.mips.lo = (int32_t)res;
1329 cpu->cd.mips.hi = (int32_t)(res >> 32);
1330 }
1331 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 cpu->cd.mips.lo = (int32_t)res;
1338 cpu->cd.mips.hi = (int32_t)(res >> 32);
1339 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 cpu->cd.mips.lo = lo;
1368 cpu->cd.mips.hi = hi;
1369 }
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 cpu->cd.mips.lo = lo;
1385 cpu->cd.mips.hi = hi;
1386 }
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
1466
1467 /*
1468 * 3-register arithmetic instructions:
1469 *
1470 * arg[0] = ptr to rs
1471 * arg[1] = ptr to rt
1472 * arg[2] = ptr to rd
1473 */
1474 X(addu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) + reg(ic->arg[1])); }
1475 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 X(subu) { reg(ic->arg[2]) = (int32_t)(reg(ic->arg[0]) - reg(ic->arg[1])); }
1509 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 X(slt) {
1545 reg(ic->arg[2]) =
1546 (MODE_int_t)reg(ic->arg[0]) < (MODE_int_t)reg(ic->arg[1]);
1547 }
1548 X(sltu) {
1549 reg(ic->arg[2]) =
1550 (MODE_uint_t)reg(ic->arg[0]) < (MODE_uint_t)reg(ic->arg[1]);
1551 }
1552 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 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 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 X(srl) { reg(ic->arg[2]) = (int32_t)((uint32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1560 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 X(sra) { reg(ic->arg[2]) = (int32_t)((int32_t)reg(ic->arg[0]) >> ic->arg[1]); }
1563 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 X(mul) { reg(ic->arg[2]) = (int32_t)
1576 ( (int32_t)reg(ic->arg[0]) * (int32_t)reg(ic->arg[1]) ); }
1577 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
1580
1581 /*
1582 * 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 * 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 * 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 *
1736 * arg[0] = pointer to rs
1737 * arg[1] = pointer to rt
1738 * arg[2] = (int32_t) immediate value
1739 */
1740 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 X(addiu)
1757 {
1758 reg(ic->arg[1]) = (int32_t)
1759 ((int32_t)reg(ic->arg[0]) + (int32_t)ic->arg[2]);
1760 }
1761 X(daddi)
1762 {
1763 int64_t rs = reg(ic->arg[0]), imm = (int32_t)ic->arg[2];
1764 int64_t rt = rs + imm;
1765
1766 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 X(daddiu)
1778 {
1779 reg(ic->arg[1]) = reg(ic->arg[0]) + (int32_t)ic->arg[2];
1780 }
1781 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
1791
1792 /*
1793 * set: Set a register to an immediate (signed) 32-bit value.
1794 * (This is the actual implementation of the lui instruction.)
1795 *
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 * cfc0: Copy from Coprocessor 0.
1807 * mfc0, dmfc0: Move from Coprocessor 0.
1808 * mtc0, dmtc0: Move to Coprocessor 0.
1809 *
1810 * arg[0] = pointer to GPR (rt)
1811 * arg[1] = coprocessor 0 register number | (select << 5) (or for the
1812 * cfc0 instruction, the coprocessor control register number)
1813 * arg[2] = relative addr of this instruction within the page
1814 */
1815 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 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 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 X(mtc0)
1846 {
1847 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1848 uint64_t tmp = (int32_t) reg(ic->arg[0]);
1849
1850 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1851 cpu->pc |= ic->arg[2];
1852
1853 /* TODO: cause exception if necessary */
1854 coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd, &tmp, 0, select);
1855
1856 /*
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 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 if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1866 if (status & (STATUS_EXL | STATUS_ERL))
1867 status &= ~STATUS_IE;
1868 }
1869 /* 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 }
1878 }
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 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 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
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 {
1920 MODE_int_t old_pc = cpu->pc;
1921 int x, cc = ic->arg[0];
1922
1923 COPROC_AVAILABILITY_CHECK(1);
1924
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 COPROC_AVAILABILITY_CHECK(1);
1964
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 X(reboot)
1989 {
1990 if (!cop0_availability_check(cpu, ic))
1991 return;
1992
1993 cpu->running = 0;
1994 debugger_n_steps_left_before_interaction = 0;
1995 cpu->cd.mips.next_ic = &nothing_call;
1996 }
1997
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 if (!cop0_availability_check(cpu, ic))
2056 return;
2057
2058 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
2059 cpu->pc |= ic->arg[2];
2060 coproc_tlbwri(cpu, ic->arg[0]);
2061 }
2062
2063
2064 /*
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 if (!cop0_availability_check(cpu, ic))
2073 return;
2074
2075 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 if (!cop0_availability_check(cpu, ic))
2082 return;
2083
2084 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 * 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 * rfe: Return from exception handler (R2000/R3000)
2108 */
2109 X(rfe)
2110 {
2111 if (!cop0_availability_check(cpu, ic))
2112 return;
2113
2114 /* 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
2119 /*
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 }
2125
2126
2127 /*
2128 * eret: Return from exception handler (non-R3000 style)
2129 */
2130 X(eret)
2131 {
2132 if (!cop0_availability_check(cpu, ic))
2133 return;
2134
2135 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 quick_pc_to_pointers(cpu);
2145
2146 cpu->cd.mips.rmw = 0; /* the "LL bit" */
2147 }
2148
2149
2150 /*
2151 * deret: Return from debug (EJTAG) handler
2152 */
2153 X(deret)
2154 {
2155 if (!cop0_availability_check(cpu, ic))
2156 return;
2157
2158 /*
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 * idle: Called from the implementation of wait, or netbsd_pmax_idle.
2177 */
2178 X(idle)
2179 {
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
2192 /* 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 cpu->has_been_idling = 1;
2202
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 usleep(10);
2216 x = 0;
2217 }
2218 cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
2219 }
2220 }
2221
2222
2223 /*
2224 * 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 * 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 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2345 uint64_t r = reg(ic->arg[0]);
2346 int low_pc, i;
2347 uint8_t word[sizeof(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 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2403 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 COPROC_AVAILABILITY_CHECK(1);
2473
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 COPROC_AVAILABILITY_CHECK(1);
2485
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 COPROC_AVAILABILITY_CHECK(1);
2501
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 COPROC_AVAILABILITY_CHECK(1);
2529
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 if (!cop0_availability_check(cpu, ic))
2580 return;
2581
2582 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2583 }
2584 X(ei_r5900)
2585 {
2586 if (!cop0_availability_check(cpu, ic))
2587 return;
2588
2589 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2590 }
2591
2592
2593 /*****************************************************************************/
2594
2595
2596 /*
2597 * 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 }
2618
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 #ifdef MODE32
2647 /* multi_{l,s}w_2, _3, etc. */
2648 #include "tmp_mips_loadstore_multi.c"
2649 #endif
2650
2651
2652 /*
2653 * 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 * 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 * 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 * 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 * addiu_bne_samepage_addiu:
2826 */
2827 X(addiu_bne_samepage_addiu)
2828 {
2829 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 cpu->n_translated_instrs ++;
2885 cpu->cd.mips.next_ic ++;
2886 }
2887
2888
2889 /*
2890 * 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 * b_samepage_addiu:
2930 *
2931 * Combination of branch within the same page, followed by addiu.
2932 */
2933 X(b_samepage_addiu)
2934 {
2935 reg(ic[1].arg[1]) = (int32_t)
2936 ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
2937 cpu->n_translated_instrs ++;
2938 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
2939 }
2940
2941
2942 /*
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 /*****************************************************************************/
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 /* end_of_page doesn't count as an executed instruction: */
2967 cpu->n_translated_instrs --;
2968
2969 /*
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
2977 /* Simple jump to the next page (if we are lucky): */
2978 if (cpu->delay_slot == NOT_DELAYED)
2979 return;
2980
2981 /*
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 return;
2988
2989 /*
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 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
2995
2996 instr(to_be_translated)(cpu, cpu->cd.mips.next_ic);
2997
2998 /* The instruction in the delay slot has now executed. */
2999 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
3000 cpu->delay_slot); */
3001
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 /* 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
3017 /* This doesn't count as an executed instruction. */
3018 cpu->n_translated_instrs --;
3019
3020 quick_pc_to_pointers(cpu);
3021
3022 if (cpu->delay_slot == NOT_DELAYED)
3023 return;
3024
3025 fatal("end_of_page2: fatal error, we're in a delay slot\n");
3026 exit(1);
3027 }
3028
3029
3030 /*****************************************************************************/
3031
3032
3033 /*
3034 * 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 */
3040 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 /* Only for 32-bit virtual address translation so far. */
3067 #ifdef MODE32
3068 /*
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 int low_addr)
3078 {
3079 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3080 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3081
3082 if (n_back < 3)
3083 return;
3084
3085 /* 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
3095 /* 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 return;
3133
3134 /* 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 ic[-2].arg[1] == ic[0].arg[1] &&
3149 ic[-1].arg[0] != ic[0].arg[1]) {
3150 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3151 ic[-2].f = instr(multi_lw_3_le);
3152 else
3153 ic[-2].f = instr(multi_lw_3_be);
3154 }
3155
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 }
3166 #endif
3167
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 * NetBSD/pmax' idle loop (and possibly others as well).
3212 * Linux/pmax' idle loop.
3213 */
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 if (n_back < 8)
3220 return;
3221
3222 #ifdef MODE32
3223 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 return;
3241 }
3242
3243 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 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 * 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 * [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 if (n_back < 2)
3360 return;
3361
3362 if (ic[-2].f == instr(addiu) &&
3363 ic[-1].f == instr(bne_samepage)) {
3364 ic[-2].f = instr(addiu_bne_samepage_addiu);
3365 return;
3366 }
3367
3368 if (ic[-1].f == instr(set)) {
3369 ic[-1].f = instr(lui_addiu);
3370 return;
3371 }
3372
3373 if (ic[-1].f == instr(b_samepage)) {
3374 ic[-1].f = instr(b_samepage_addiu);
3375 return;
3376 }
3377
3378 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 /* TODO: other branches that are followed by addiu should be here */
3394 }
3395
3396
3397 /*
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 /*****************************************************************************/
3418
3419
3420 /*
3421 * mips_instr_to_be_translated():
3422 *
3423 * Translate an instruction word into a mips_instr_call. ic is filled in with
3424 * 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 int main_opcode, rt, rs, rd, sa, s6, x64 = 0, s10;
3435 int in_crosspage_delayslot = 0;
3436 void (*samepage_function)(struct cpu *, struct mips_instr_call *);
3437 int store, signedness, size;
3438
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 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
3445 /* fatal("[ delay-slot translation across page "
3446 "boundary ]\n"); */
3447 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 cpu->pc = (MODE_int_t)addr;
3454 addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
3455
3456 /* Read the instruction word from memory: */
3457 #ifdef MODE32
3458 page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
3459 #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
3474 if (page != NULL) {
3475 /* fatal("TRANSLATION HIT!\n"); */
3476 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
3477 } else {
3478 /* fatal("TRANSLATION MISS!\n"); */
3479 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
3480 sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
3481 fatal("to_be_translated(): read failed: TODO\n");
3482 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 * 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 */
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 s10 = (rs << 5) | sa;
3516
3517 switch (main_opcode) {
3518
3519 case HI6_SPECIAL:
3520 switch (s6) {
3521
3522 case SPECIAL_SLL:
3523 case SPECIAL_SLLV:
3524 case SPECIAL_SRL:
3525 case SPECIAL_SRLV:
3526 case SPECIAL_SRA:
3527 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 switch (s6) {
3538 case SPECIAL_SLL: ic->f = instr(sll); break;
3539 case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
3540 case SPECIAL_SRL: ic->f = instr(srl); break;
3541 case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
3542 case SPECIAL_SRA: ic->f = instr(sra); break;
3543 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 }
3560 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3561 if (sa >= 0)
3562 ic->arg[1] = sa;
3563 else
3564 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3565 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3566 if (rd == MIPS_GPR_ZERO)
3567 ic->f = instr(nop);
3568 if (ic->f == instr(sll))
3569 cpu->cd.mips.combination_check = COMBINE(sll);
3570 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 break;
3588
3589 case SPECIAL_ADD:
3590 case SPECIAL_ADDU:
3591 case SPECIAL_SUB:
3592 case SPECIAL_SUBU:
3593 case SPECIAL_DADD:
3594 case SPECIAL_DADDU:
3595 case SPECIAL_DSUB:
3596 case SPECIAL_DSUBU:
3597 case SPECIAL_SLT:
3598 case SPECIAL_SLTU:
3599 case SPECIAL_AND:
3600 case SPECIAL_OR:
3601 case SPECIAL_XOR:
3602 case SPECIAL_NOR:
3603 case SPECIAL_MOVN:
3604 case SPECIAL_MOVZ:
3605 case SPECIAL_MFHI:
3606 case SPECIAL_MFLO:
3607 case SPECIAL_MTHI:
3608 case SPECIAL_MTLO:
3609 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 switch (s6) {
3624 case SPECIAL_ADD: ic->f = instr(add); break;
3625 case SPECIAL_ADDU: ic->f = instr(addu); break;
3626 case SPECIAL_SUB: ic->f = instr(sub); break;
3627 case SPECIAL_SUBU: ic->f = instr(subu); break;
3628 case SPECIAL_DADD: ic->f = instr(dadd); x64=1; break;
3629 case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
3630 case SPECIAL_DSUB: ic->f = instr(dsub); x64=1; break;
3631 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 case SPECIAL_AND: ic->f = instr(and); break;
3635 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 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 }
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 /* Special cases for rd: */
3677 switch (s6) {
3678 case SPECIAL_MTHI:
3679 case SPECIAL_MTLO:
3680 case SPECIAL_DIV:
3681 case SPECIAL_DIVU:
3682 case SPECIAL_DDIV:
3683 case SPECIAL_DDIVU:
3684 case SPECIAL_MULT:
3685 case SPECIAL_MULTU:
3686 case SPECIAL_DMULT:
3687 case SPECIAL_DMULTU:
3688 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 if (rd != MIPS_GPR_ZERO) {
3710 if (!cpu->translation_readahead)
3711 fatal("TODO: rd NON-zero\n");
3712 goto bad;
3713 }
3714 /* These instructions don't use rd. */
3715 break;
3716 default:if (rd == MIPS_GPR_ZERO)
3717 ic->f = instr(nop);
3718 }
3719
3720 if (ic->f == instr(addu))
3721 cpu->cd.mips.combination_check = COMBINE(addu);
3722
3723 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 if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
3730 s6 = SPECIAL_JR;
3731 ic->arg[2] = (addr & 0xffc) + 8;
3732 switch (s6) {
3733 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 if (cpu->translation_readahead > 2)
3743 cpu->translation_readahead = 2;
3744 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 if (cpu->delay_slot) {
3753 if (!cpu->translation_readahead)
3754 fatal("TODO: branch in delay "
3755 "slot? (1)\n");
3756 goto bad;
3757 }
3758 break;
3759
3760 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 if (((iword >> 6) & 0xfffff) == 0x30378) {
3771 /* "Magic trap" for REBOOT: */
3772 ic->f = instr(reboot);
3773 } else {
3774 ic->f = instr(break);
3775 }
3776 break;
3777
3778 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 case HI6_BEQL:
3789 case HI6_BNEL:
3790 case HI6_BLEZ:
3791 case HI6_BLEZL:
3792 case HI6_BGTZ:
3793 case HI6_BGTZL:
3794 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 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 }
3839 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3840 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3841 ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
3842 + (addr & 0xffc) + 4 );
3843 /* 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 if (cpu->delay_slot) {
3853 if (!cpu->translation_readahead)
3854 fatal("TODO: branch in delay slot? (2)\n");
3855 goto bad;
3856 }
3857 break;
3858
3859 case HI6_ADDI:
3860 case HI6_ADDIU:
3861 case HI6_SLTI:
3862 case HI6_SLTIU:
3863 case HI6_DADDI:
3864 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 main_opcode == HI6_SLTI ||
3873 main_opcode == HI6_SLTIU ||
3874 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
3880 switch (main_opcode) {
3881 case HI6_ADDI: ic->f = instr(addi); break;
3882 case HI6_ADDIU: ic->f = instr(addiu); break;
3883 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 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
3892 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 if (rt == MIPS_GPR_ZERO)
3901 ic->f = instr(nop);
3902
3903 if (ic->f == instr(ori))
3904 cpu->cd.mips.combination_check = COMBINE(ori);
3905 if (ic->f == instr(addiu))
3906 cpu->cd.mips.combination_check = COMBINE(addiu);
3907 if (ic->f == instr(daddiu))
3908 cpu->cd.mips.combination_check = COMBINE(b_daddiu);
3909 break;
3910
3911 case HI6_LUI:
3912 ic->f = instr(set);
3913 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3914 ic->arg[1] = (int32_t) (imm << 16);
3915 /* NOTE: Don't use arg[2] here. It can be used with
3916 instruction combinations, to do lui + addiu, etc. */
3917 if (rt == MIPS_GPR_ZERO)
3918 ic->f = instr(nop);
3919 break;
3920
3921 case HI6_J:
3922 case HI6_JAL:
3923 switch (main_opcode) {
3924 case HI6_J:
3925 ic->f = instr(j);
3926 if (cpu->translation_readahead > 2)
3927 cpu->translation_readahead = 2;
3928 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 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 goto bad;
3944 }
3945 break;
3946
3947 case HI6_COP0:
3948 /* 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 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 if (!warned &&
3980 !cpu->translation_readahead) {
3981 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 case COP0_STANDBY:
3991 /* 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 if (!warned &&
3997 !cpu->translation_readahead) {
3998 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 case COP0_HIBERNATE:
4007 /* TODO */
4008 goto bad;
4009 case COP0_SUSPEND:
4010 /* Used by NetBSD on HPCmips (VR41xx) to
4011 halt the machine. */
4012 ic->f = instr(reboot);
4013 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 default:if (!cpu->translation_readahead)
4027 fatal("UNIMPLEMENTED cop0 (func "
4028 "0x%02x)\n", iword & 0xff);
4029 goto bad;
4030 }
4031 break;
4032 }
4033
4034 /* rs contains the coprocessor opcode! */
4035 switch (rs) {
4036 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 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 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 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
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 break;
4072 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 /* R2020 DECstation write-loop thingy. */
4108 ic->f = instr(nop);
4109 } else {
4110 if (!cpu->translation_readahead)
4111 fatal("Unimplemented COP0_BCzc\n");
4112 goto bad;
4113 }
4114 break;
4115
4116 default:if (!cpu->translation_readahead)
4117 fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
4118 goto bad;
4119 }
4120 break;
4121
4122 case HI6_COP1:
4123 /* 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 switch (rs) {
4134
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 if (!cpu->translation_readahead)
4145 fatal("TODO: branch in delay slot 4\n");
4146 goto bad;
4147 }
4148 if (cpu->cd.mips.cpu_type.isa_level <= 3 &&
4149 ic->arg[0] != 0) {
4150 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 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 case COPz_CFCz:
4171 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 break;
4179
4180 default:if (!cpu->translation_readahead)
4181 fatal("COP1 floating point opcode = 0x%02x\n", rs);
4182 goto bad;
4183 }
4184 break;
4185
4186 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 if (!cpu->translation_readahead)
4195 fatal("COP2 functionality not yet implemented\n");
4196 goto bad;
4197 break;
4198
4199 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 if (!cpu->translation_readahead)
4214 fatal("COP3 iword=0x%08x\n", iword);
4215 goto bad;
4216 }
4217 break;
4218
4219 case HI6_SPECIAL2:
4220 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 switch (s6) {
4294
4295 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 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 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 if (!cpu->translation_readahead)
4399 fatal("TODO: branch in delay slot:5\n");
4400 goto bad;
4401 }
4402 break;
4403
4404 default:if (!cpu->translation_readahead)
4405 fatal("UNIMPLEMENTED regimm rt=%i\n", rt);
4406 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
4453 /* Check for multiple loads or stores in a row using the same
4454 base register: */
4455 #ifdef MODE32
4456 if (main_opcode == HI6_LW)
4457 cpu->cd.mips.combination_check = COMBINE(multi_lw);
4458 if (main_opcode == HI6_SW)
4459 cpu->cd.mips.combination_check = COMBINE(multi_sw);
4460 #endif
4461 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 if (!cpu->translation_readahead)
4486 fatal("HM... unusual load linked\n");
4487 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 if (!cpu->translation_readahead)
4557 fatal("TODO: lwc3 not implemented yet\n");
4558 goto bad;
4559 }
4560 break;
4561
4562 case HI6_LQ_MDMX:
4563 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4564 if (!cpu->translation_readahead)
4565 fatal("TODO: R5900 128-bit loads\n");
4566 goto bad;
4567 }
4568
4569 if (!cpu->translation_readahead)
4570 fatal("TODO: MDMX\n");
4571
4572 goto bad;
4573 /* break */
4574
4575 case HI6_SQ_SPECIAL3:
4576 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4577 if (!cpu->translation_readahead)
4578 fatal("TODO: R5900 128-bit stores\n");
4579 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 if (!warning && !cpu->translation_readahead) {
4586 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 warning = 1;
4592 }
4593 ic->f = instr(reserved);
4594 break;
4595 }
4596
4597 switch (s6) {
4598
4599 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 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 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 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 default:if (!cpu->translation_readahead)
4683 fatal("unimplemented rdhwr "
4684 "register rd=%i\n", rd);
4685 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 default:goto bad;
4699 }
4700
4701
4702 #ifdef MODE32
4703 if (x64) {
4704 static int has_warned = 0;
4705 if (!has_warned && !cpu->translation_readahead) {
4706 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 has_warned = 1;
4710 }
4711 if (cpu->translation_readahead)
4712 goto bad;
4713 else
4714 ic->f = instr(reserved);
4715 }
4716 #endif
4717
4718
4719 #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