/[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 28 - (show annotations)
Mon Oct 8 16:20:26 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 106893 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1298 2006/07/22 11:27:46 debug Exp $
20060626	Continuing on SPARC emulation (beginning on the 'save'
		instruction, register windows, etc).
20060629	Planning statistics gathering (new -s command line option),
		and renaming speed_tricks to allow_instruction_combinations.
20060630	Some minor manual page updates.
		Various cleanups.
		Implementing the -s command line option.
20060701	FINALLY found the bug which prevented Linux and Ultrix from
		running without the ugly hack in the R2000/R3000 cache isol
		code; it was the phystranslation hint array which was buggy.
		Removing the phystranslation hint code completely, for now.
20060702	Minor dyntrans cleanups; invalidation of physpages now only
		invalidate those parts of a page that have actually been
		translated. (32 parts per page.)
		Some MIPS non-R3000 speed fixes.
		Experimenting with MIPS instruction combination for some
		addiu+bne+sw loops, and sw+sw+sw.
		Adding support (again) for larger-than-4KB pages in MIPS tlbw*.
		Continuing on SPARC emulation: adding load/store instructions.
20060704	Fixing a virtual vs physical page shift bug in the new tlbw*
		implementation. Problem noticed by Jakub Jermar. (Many thanks.)
		Moving rfe and eret to cpu_mips_instr.c, since that is the
		only place that uses them nowadays.
20060705	Removing the BSD license from the "testmachine" include files,
		placing them in the public domain instead; this enables the
		testmachine stuff to be used from projects which are
		incompatible with the BSD license for some reason.
20060707	Adding instruction combinations for the R2000/R3000 L1
		I-cache invalidation code used by NetBSD/pmax 3.0, lui+addiu,
		various branches followed by addiu or nop, and jr ra followed
		by addiu. The time it takes to perform a full NetBSD/pmax R3000
		install on the laptop has dropped from 573 seconds to 539. :-)
20060708	Adding a framebuffer controller device (dev_fbctrl), which so
		far can be used to change the fb resolution during runtime, but
		in the future will also be useful for accelerated block fill/
		copy, and possibly also simplified character output.
		Adding an instruction combination for NetBSD/pmax' strlen.
20060709	Minor fixes: reading raw files in src/file.c wasn't memblock
		aligned, removing buggy multi_sw MIPS instruction combination,
		etc.
20060711	Adding a machine_qemu.c, which contains a "qemu_mips" machine.
		(It mimics QEMU's MIPS machine mode, so that a test kernel
		made for QEMU_MIPS also can run in GXemul... at least to some
		extent.)  Adding a short section about how to run this mode to
		doc/guestoses.html.
20060714	Misc. minor code cleanups.
20060715	Applying a patch which adds getchar() to promemul/yamon.c
		(from Oleksandr Tymoshenko).
		Adding yamon.h from NetBSD, and rewriting yamon.c to use it
		(instead of ugly hardcoded numbers) + some cleanup.
20060716	Found and fixed the bug which broke single-stepping of 64-bit
		programs between 0.4.0 and 0.4.0.1 (caused by too quick
		refactoring and no testing). Hopefully this fix will not
		break too many other things.
20060718	Continuing on the 8253 PIT; it now works with Linux/QEMU_MIPS.
		Re-adding the sw+sw+sw instr comb (the problem was that I had
		ignored endian issues); however, it doesn't seem to give any
		big performance gain.
20060720	Adding a dummy Transputer mode (T414, T800 etc) skeleton (only
		the 'j' and 'ldc' instructions are implemented so far). :-}
20060721	Adding gtreg.h from NetBSD, updating dev_gt.c to use it, plus
		misc. other updates to get Linux 2.6 for evbmips/malta working
		(thanks to Alec Voropay for the details).
		FINALLY found and fixed the bug which made tlbw* for non-R3000
		buggy; it was a reference count problem in the dyntrans core.
20060722	Testing stuff; things seem stable enough for a new release.

==============  RELEASE 0.4.1  ==============


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

  ViewVC Help
Powered by ViewVC 1.1.26