/[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 30 - (show annotations)
Mon Oct 8 16:20:40 2007 UTC (16 years, 6 months ago) by dpavlin
File MIME type: text/plain
File size: 123928 byte(s)
++ trunk/HISTORY	(local)
$Id: HISTORY,v 1.1325 2006/08/15 15:38:37 debug Exp $
20060723	More Transputer instructions (pfix, nfix, opr, mint, ldl, ldlp,
		eqc, rev, ajw, stl, stlf, sthf, sub, ldnl, ldnlp, ldpi, move,
		wcnt, add, bcnt).
		Adding more SPARC instructions (andcc, addcc, bl, rdpr).
		Progress on the igsfb framebuffer used by NetBSD/netwinder.
		Enabling 8-bit fills in dev_fb.
		NetBSD/netwinder 3.0.1 can now run from a disk image :-)
20060724	Cleanup/performance fix for 64-bit virtual translation table
		updates (by removing the "timestamp" stuff). A full NetBSD/pmax
		3.0.1 install for R4400 has dropped from 667 seconds to 584 :)
		Fixing the igsfb "almost vga" color (it is 24-bit, not 18-bit).
		Adding some MIPS instruction combinations (3*lw, and 3*addu).
		The 8048 keyboard now turns off interrupt enable between the
		KBR_ACK and the KBR_RSTDONE, to work better with Linux 2.6.
		Not causing PPC DEC interrupts if PPC_NO_DEC is set for a
		specific CPU; NetBSD/bebox gets slightly further than before.
		Adding some more SPARC instructions: branches, udiv.
20060725	Refreshing dev_pckbc.c a little.
		Cleanups for the SH emulation mode, and adding the first
		"compact" (16-bit) instructions: various simple movs, nop,
		shll, stc, or, ldc.
20060726	Adding dummy "pcn" (AMD PCnet NIC) PCI glue.
20060727	Various cleanups; removing stuff from cpu.h, such as
		running_translated (not really meaningful anymore), and
		page flags (breaking into the debugger clears all translations
		anyway).
		Minor MIPS instruction combination updates.
20060807	Expanding the 3*sw and 3*lw MIPS instruction combinations to
		work with 2* and 4* too, resulting in a minor performance gain.
		Implementing a usleep hack for the RM52xx/MIPS32/MIPS64 "wait"
		instruction (when emulating 1 cpu).
20060808	Experimenting with some more MIPS instruction combinations.
		Implementing support for showing a (hardcoded 12x22) text
		cursor in igsfb.
20060809	Simplifying the NetBSD/evbmips (Malta) install instructions
		somewhat (by using a NetBSD/pmax ramdisk install kernel).
20060812	Experimenting more with the MIPS 'wait' instruction.
		PCI configuration register writes can now be handled, which
		allow PCI IDE controllers to work with NetBSD/Malta 3.0.1 and
		NetBSD/cobalt 3.0.1. (Previously only NetBSD 2.1 worked.)
20060813	Updating dev_gt.c based on numbers from Alec Voropay, to enable
		Linux 2.6 to use PCI on Malta.
		Continuing on Algor interrupt stuff.
20060814	Adding support for routing ISA interrupts to two different
		interrupts, making it possible to run NetBSD/algor :-)
20060814-15	Testing for the release.

==============  RELEASE 0.4.2  ==============


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.104 2006/08/14 17:45:47 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 (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1683 if (status & (STATUS_EXL | STATUS_ERL))
1684 status &= ~STATUS_IE;
1685 }
1686 /* Ugly R5900 special case: (TODO: move this?) */
1687 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1688 !(status & R5900_STATUS_EIE))
1689 status &= ~STATUS_IE;
1690 if (status & STATUS_IE && (status & cause & STATUS_IM_MASK)) {
1691 cpu->pc += sizeof(uint32_t);
1692 mips_cpu_exception(cpu, EXCEPTION_INT, 0, 0,0,0,0,0);
1693 }
1694 }
1695 }
1696 X(dmfc0)
1697 {
1698 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1699 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1700 cpu->pc |= ic->arg[2];
1701 /* TODO: cause exception if necessary */
1702 coproc_register_read(cpu, cpu->cd.mips.coproc[0], rd,
1703 (uint64_t *)ic->arg[0], select);
1704 }
1705 X(dmtc0)
1706 {
1707 int rd = ic->arg[1] & 31, select = ic->arg[1] >> 5;
1708 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1709 cpu->pc |= ic->arg[2];
1710 /* TODO: cause exception if necessary */
1711 coproc_register_write(cpu, cpu->cd.mips.coproc[0], rd,
1712 (uint64_t *)ic->arg[0], 1, select);
1713 }
1714
1715
1716 /*
1717 * cop1_bc: Floating point conditional branch.
1718 *
1719 * arg[0] = cc
1720 * arg[1] = nd (=2) and tf (=1) bits
1721 * arg[2] = offset (relative to start of this page)
1722 */
1723 X(cop1_bc)
1724 {
1725 MODE_int_t old_pc = cpu->pc;
1726 const int cpnr = 1;
1727 int x, low_pc, cc = ic->arg[0];
1728
1729 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1730 / sizeof(struct mips_instr_call);
1731 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1732 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1733 if (!(cpu->cd.mips.coproc[0]->
1734 reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1735 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1736 return;
1737 }
1738
1739 /* Get the correct condition code bit: */
1740 if (cc == 0)
1741 x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1742 >> MIPS_FCSR_FCC0_SHIFT) & 1;
1743 else
1744 x = (cpu->cd.mips.coproc[1]->fcr[MIPS_FPU_FCSR]
1745 >> (MIPS_FCSR_FCC1_SHIFT + cc-1)) & 1;
1746
1747 /* Branch on false? Then invert the truth value. */
1748 if (!(ic->arg[1] & 1))
1749 x ^= 1;
1750
1751 /* Execute the delay slot (except if it is nullified): */
1752 cpu->delay_slot = TO_BE_DELAYED;
1753 if (x || !(ic->arg[1] & 2))
1754 ic[1].f(cpu, ic+1);
1755 cpu->n_translated_instrs ++;
1756
1757 if (!(cpu->delay_slot & EXCEPTION_IN_DELAY_SLOT)) {
1758 /* Note: Must be non-delayed when jumping to the new pc: */
1759 cpu->delay_slot = NOT_DELAYED;
1760 if (x) {
1761 old_pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
1762 MIPS_INSTR_ALIGNMENT_SHIFT);
1763 cpu->pc = old_pc + (int32_t)ic->arg[2];
1764 quick_pc_to_pointers(cpu);
1765 } else
1766 cpu->cd.mips.next_ic ++;
1767 } else
1768 cpu->delay_slot = NOT_DELAYED;
1769 }
1770
1771
1772 /*
1773 * cop1_slow: Fallback to legacy cop1 code. (Slow, but it should work.)
1774 */
1775 X(cop1_slow)
1776 {
1777 const int cpnr = 1;
1778 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1779 / sizeof(struct mips_instr_call);
1780 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1781 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1782
1783 if (!(cpu->cd.mips.coproc[0]->
1784 reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
1785 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
1786 return;
1787 }
1788
1789 coproc_function(cpu, cpu->cd.mips.coproc[1], 1, ic->arg[0], 0, 1);
1790 }
1791
1792
1793 /*
1794 * syscall, break: Synchronize the PC and cause an exception.
1795 */
1796 X(syscall)
1797 {
1798 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1799 / sizeof(struct mips_instr_call);
1800 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1801 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1802 mips_cpu_exception(cpu, EXCEPTION_SYS, 0, 0, 0, 0, 0, 0);
1803 }
1804 X(break)
1805 {
1806 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1807 / sizeof(struct mips_instr_call);
1808 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1809 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1810 mips_cpu_exception(cpu, EXCEPTION_BP, 0, 0, 0, 0, 0, 0);
1811 }
1812 X(reboot)
1813 {
1814 cpu->running = 0;
1815 debugger_n_steps_left_before_interaction = 0;
1816 cpu->cd.mips.next_ic = &nothing_call;
1817 }
1818
1819
1820 /*
1821 * promemul: PROM software emulation.
1822 */
1823 X(promemul)
1824 {
1825 /* Synchronize the PC and call the correct emulation layer: */
1826 MODE_int_t old_pc;
1827 int res, low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
1828 / sizeof(struct mips_instr_call);
1829 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<< MIPS_INSTR_ALIGNMENT_SHIFT);
1830 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
1831 old_pc = cpu->pc;
1832
1833 switch (cpu->machine->machine_type) {
1834 case MACHINE_PMAX:
1835 res = decstation_prom_emul(cpu);
1836 break;
1837 case MACHINE_PS2:
1838 res = playstation2_sifbios_emul(cpu);
1839 break;
1840 case MACHINE_ARC:
1841 case MACHINE_SGI:
1842 res = arcbios_emul(cpu);
1843 break;
1844 case MACHINE_EVBMIPS:
1845 res = yamon_emul(cpu);
1846 break;
1847 default:fatal("TODO: Unimplemented machine type for PROM magic trap\n");
1848 exit(1);
1849 }
1850
1851 if (res) {
1852 /* Return from the PROM call: */
1853 cpu->pc = (MODE_int_t)cpu->cd.mips.gpr[MIPS_GPR_RA];
1854 cpu->delay_slot = NOT_DELAYED;
1855
1856 if (cpu->machine->show_trace_tree)
1857 cpu_functioncall_trace_return(cpu);
1858 } else {
1859 /* The PROM call blocks. */
1860 cpu->n_translated_instrs += 10;
1861 cpu->pc = old_pc;
1862 }
1863
1864 quick_pc_to_pointers(cpu);
1865 }
1866
1867
1868 /*
1869 * tlbw: TLB write indexed and random
1870 *
1871 * arg[0] = 1 for random, 0 for indexed
1872 * arg[2] = relative addr of this instruction within the page
1873 */
1874 X(tlbw)
1875 {
1876 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1877 cpu->pc |= ic->arg[2];
1878 coproc_tlbwri(cpu, ic->arg[0]);
1879 }
1880
1881
1882 /*
1883 * tlbp: TLB probe
1884 * tlbr: TLB read
1885 *
1886 * arg[2] = relative addr of this instruction within the page
1887 */
1888 X(tlbp)
1889 {
1890 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1891 cpu->pc |= ic->arg[2];
1892 coproc_tlbpr(cpu, 0);
1893 }
1894 X(tlbr)
1895 {
1896 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)<<MIPS_INSTR_ALIGNMENT_SHIFT);
1897 cpu->pc |= ic->arg[2];
1898 coproc_tlbpr(cpu, 1);
1899 }
1900
1901
1902 /*
1903 * rfe: Return from exception handler (R2000/R3000)
1904 */
1905 X(rfe)
1906 {
1907 /* Just rotate the interrupt/user bits: */
1908 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] =
1909 (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & ~0x3f) |
1910 ((cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & 0x3c) >> 2);
1911
1912 /*
1913 * Note: no pc to pointers conversion is necessary here. Usually the
1914 * rfe instruction resides in the delay slot of a jr k0/k1, and
1915 * it is up to that instruction to do the pointer conversion.
1916 */
1917 }
1918
1919
1920 /*
1921 * eret: Return from exception handler (non-R3000 style)
1922 */
1923 X(eret)
1924 {
1925 if (cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_ERL) {
1926 cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_ERROREPC];
1927 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_ERL;
1928 } else {
1929 cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_EPC];
1930 cpu->delay_slot = 0;
1931 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1932 }
1933
1934 quick_pc_to_pointers(cpu);
1935
1936 cpu->cd.mips.rmw = 0; /* the "LL bit" */
1937 }
1938
1939
1940 /*
1941 * deret: Return from debug (EJTAG) handler
1942 */
1943 X(deret)
1944 {
1945 /*
1946 * According to the MIPS64 manual, deret loads PC from the DEPC cop0
1947 * register, and jumps there immediately. No delay slot.
1948 *
1949 * TODO: This instruction is only available if the processor is in
1950 * debug mode. (What does that mean?)
1951 *
1952 * TODO: This instruction is undefined in a delay slot.
1953 */
1954
1955 cpu->pc = cpu->cd.mips.coproc[0]->reg[COP0_DEPC];
1956 cpu->delay_slot = 0;
1957 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~STATUS_EXL;
1958 quick_pc_to_pointers(cpu);
1959 }
1960
1961
1962 /*
1963 * wait: Wait for external interrupt.
1964 */
1965 X(wait)
1966 {
1967 /*
1968 * If there is an interrupt, then just return. Otherwise
1969 * re-run the wait instruction (after a delay).
1970 */
1971 uint32_t status = cpu->cd.mips.coproc[0]->reg[COP0_STATUS];
1972 uint32_t cause = cpu->cd.mips.coproc[0]->reg[COP0_CAUSE];
1973
1974 /* NOTE: STATUS_IE happens to match the enable bit also
1975 on R2000/R3000, so this is ok. */
1976 if (cpu->cd.mips.cpu_type.exc_model != EXC3K) {
1977 if (status & (STATUS_EXL | STATUS_ERL))
1978 status &= ~STATUS_IE;
1979 }
1980 /* Ugly R5900 special case: (TODO: move this?) */
1981 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900 &&
1982 !(status & R5900_STATUS_EIE))
1983 status &= ~STATUS_IE;
1984 if (status & STATUS_IE && (status & cause & STATUS_IM_MASK))
1985 return;
1986
1987 cpu->cd.mips.next_ic = ic;
1988 cpu->is_halted = 1;
1989
1990 /*
1991 * There was no interrupt. Go to sleep.
1992 *
1993 * TODO:
1994 *
1995 * Think about how to actually implement this usleep stuff,
1996 * in an SMP and/or timing accurate environment.
1997 */
1998
1999 if (cpu->machine->ncpus == 1) {
2000 static int x = 0;
2001 if ((++x) == 600) {
2002 usleep(1);
2003 x = 0;
2004 }
2005 cpu->n_translated_instrs += N_SAFE_DYNTRANS_LIMIT / 6;
2006 }
2007 }
2008
2009
2010 /*
2011 * rdhwr: Read hardware register into gpr (MIPS32/64 rev 2).
2012 *
2013 * arg[0] = ptr to rt (destination register)
2014 */
2015 X(rdhwr_cpunum)
2016 {
2017 reg(ic->arg[0]) = cpu->cpu_id;
2018 }
2019
2020
2021 #include "tmp_mips_loadstore.c"
2022
2023
2024 /*
2025 * Load linked / store conditional:
2026 *
2027 * A Load-linked instruction initiates a RMW (read-modify-write) sequence.
2028 * COP0_LLADDR is updated for diagnostic purposes, except for CPUs in the
2029 * R10000 family.
2030 *
2031 * A Store-conditional instruction ends the sequence.
2032 *
2033 * arg[0] = ptr to rt
2034 * arg[1] = ptr to rs
2035 * arg[2] = int32_t imm
2036 */
2037 X(ll)
2038 {
2039 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2040 int low_pc;
2041 uint8_t word[sizeof(uint32_t)];
2042
2043 /* Synch. PC and load using slow memory_rw(): */
2044 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2045 / sizeof(struct mips_instr_call);
2046 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2047 << MIPS_INSTR_ALIGNMENT_SHIFT);
2048 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2049
2050 if (addr & (sizeof(word)-1)) {
2051 fatal("TODO: load linked unaligned access: exception\n");
2052 exit(1);
2053 }
2054
2055 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2056 sizeof(word), MEM_READ, CACHE_DATA)) {
2057 /* An exception occurred. */
2058 return;
2059 }
2060
2061 cpu->cd.mips.rmw = 1;
2062 cpu->cd.mips.rmw_addr = addr;
2063 cpu->cd.mips.rmw_len = sizeof(word);
2064 if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2065 cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2066 (addr >> 4) & 0xffffffffULL;
2067
2068 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2069 reg(ic->arg[0]) = (int32_t) (word[0] + (word[1] << 8)
2070 + (word[2] << 16) + (word[3] << 24));
2071 else
2072 reg(ic->arg[0]) = (int32_t) (word[3] + (word[2] << 8)
2073 + (word[1] << 16) + (word[0] << 24));
2074 }
2075 X(lld)
2076 {
2077 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2078 int low_pc;
2079 uint8_t word[sizeof(uint64_t)];
2080
2081 /* Synch. PC and load using slow memory_rw(): */
2082 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2083 / sizeof(struct mips_instr_call);
2084 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2085 << MIPS_INSTR_ALIGNMENT_SHIFT);
2086 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2087
2088 if (addr & (sizeof(word)-1)) {
2089 fatal("TODO: load linked unaligned access: exception\n");
2090 exit(1);
2091 }
2092
2093 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2094 sizeof(word), MEM_READ, CACHE_DATA)) {
2095 /* An exception occurred. */
2096 return;
2097 }
2098
2099 cpu->cd.mips.rmw = 1;
2100 cpu->cd.mips.rmw_addr = addr;
2101 cpu->cd.mips.rmw_len = sizeof(word);
2102 if (cpu->cd.mips.cpu_type.exc_model != MMU10K)
2103 cpu->cd.mips.coproc[0]->reg[COP0_LLADDR] =
2104 (addr >> 4) & 0xffffffffULL;
2105
2106 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
2107 reg(ic->arg[0]) = word[0] + (word[1] << 8)
2108 + (word[2] << 16) + ((uint64_t)word[3] << 24) +
2109 + ((uint64_t)word[4] << 32) + ((uint64_t)word[5] << 40)
2110 + ((uint64_t)word[6] << 48) + ((uint64_t)word[7] << 56);
2111 else
2112 reg(ic->arg[0]) = word[7] + (word[6] << 8)
2113 + (word[5] << 16) + ((uint64_t)word[4] << 24) +
2114 + ((uint64_t)word[3] << 32) + ((uint64_t)word[2] << 40)
2115 + ((uint64_t)word[1] << 48) + ((uint64_t)word[0] << 56);
2116 }
2117 X(sc)
2118 {
2119 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2120 uint64_t r = reg(ic->arg[0]);
2121 int low_pc, i;
2122 uint8_t word[sizeof(uint32_t)];
2123
2124 /* Synch. PC and store using slow memory_rw(): */
2125 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2126 / sizeof(struct mips_instr_call);
2127 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2128 << MIPS_INSTR_ALIGNMENT_SHIFT);
2129 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2130
2131 if (addr & (sizeof(word)-1)) {
2132 fatal("TODO: sc unaligned access: exception\n");
2133 exit(1);
2134 }
2135
2136 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2137 word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2138 } else {
2139 word[3]=r; word[2]=r>>8; word[1]=r>>16; word[0]=r>>24;
2140 }
2141
2142 /* If rmw is 0, then the store failed. (This cache-line was written
2143 to by someone else.) */
2144 if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2145 || cpu->cd.mips.rmw_len != sizeof(word)) {
2146 reg(ic->arg[0]) = 0;
2147 cpu->cd.mips.rmw = 0;
2148 return;
2149 }
2150
2151 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2152 sizeof(word), MEM_WRITE, CACHE_DATA)) {
2153 /* An exception occurred. */
2154 return;
2155 }
2156
2157 /* We succeeded. Let's invalidate everybody else's store to this
2158 cache line: */
2159 for (i=0; i<cpu->machine->ncpus; i++) {
2160 if (cpu->machine->cpus[i]->cd.mips.rmw) {
2161 uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2162 cd.mips.rmw_addr;
2163 uint64_t mask = ~(cpu->machine->cpus[i]->
2164 cd.mips.cache_linesize[CACHE_DATA] - 1);
2165 xaddr &= mask;
2166 yaddr &= mask;
2167 if (xaddr == yaddr)
2168 cpu->machine->cpus[i]->cd.mips.rmw = 0;
2169 }
2170 }
2171
2172 reg(ic->arg[0]) = 1;
2173 cpu->cd.mips.rmw = 0;
2174 }
2175 X(scd)
2176 {
2177 MODE_int_t addr = reg(ic->arg[1]) + (int32_t)ic->arg[2];
2178 uint64_t r = reg(ic->arg[0]);
2179 int low_pc, i;
2180 uint8_t word[sizeof(uint64_t)];
2181
2182 /* Synch. PC and store using slow memory_rw(): */
2183 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2184 / sizeof(struct mips_instr_call);
2185 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2186 << MIPS_INSTR_ALIGNMENT_SHIFT);
2187 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2188
2189 if (addr & (sizeof(word)-1)) {
2190 fatal("TODO: sc unaligned access: exception\n");
2191 exit(1);
2192 }
2193
2194 if (cpu->byte_order == EMUL_LITTLE_ENDIAN) {
2195 word[0]=r; word[1]=r>>8; word[2]=r>>16; word[3]=r>>24;
2196 word[4]=r>>32; word[5]=r>>40; word[6]=r>>48; word[7]=r>>56;
2197 } else {
2198 word[7]=r; word[6]=r>>8; word[5]=r>>16; word[4]=r>>24;
2199 word[3]=r>>32; word[2]=r>>40; word[1]=r>>48; word[0]=r>>56;
2200 }
2201
2202 /* If rmw is 0, then the store failed. (This cache-line was written
2203 to by someone else.) */
2204 if (cpu->cd.mips.rmw == 0 || cpu->cd.mips.rmw_addr != addr
2205 || cpu->cd.mips.rmw_len != sizeof(word)) {
2206 reg(ic->arg[0]) = 0;
2207 cpu->cd.mips.rmw = 0;
2208 return;
2209 }
2210
2211 if (!cpu->memory_rw(cpu, cpu->mem, addr, word,
2212 sizeof(word), MEM_WRITE, CACHE_DATA)) {
2213 /* An exception occurred. */
2214 return;
2215 }
2216
2217 /* We succeeded. Let's invalidate everybody else's store to this
2218 cache line: */
2219 for (i=0; i<cpu->machine->ncpus; i++) {
2220 if (cpu->machine->cpus[i]->cd.mips.rmw) {
2221 uint64_t yaddr = addr, xaddr = cpu->machine->cpus[i]->
2222 cd.mips.rmw_addr;
2223 uint64_t mask = ~(cpu->machine->cpus[i]->
2224 cd.mips.cache_linesize[CACHE_DATA] - 1);
2225 xaddr &= mask;
2226 yaddr &= mask;
2227 if (xaddr == yaddr)
2228 cpu->machine->cpus[i]->cd.mips.rmw = 0;
2229 }
2230 }
2231
2232 reg(ic->arg[0]) = 1;
2233 cpu->cd.mips.rmw = 0;
2234 }
2235
2236
2237 /*
2238 * lwc1, swc1: Coprocessor 1 load/store (32-bit)
2239 * ldc1, sdc1: Coprocessor 1 load/store (64-bit)
2240 *
2241 * arg[0] = ptr to coprocessor register
2242 * arg[1] = ptr to rs (base pointer register)
2243 * arg[2] = int32_t imm
2244 */
2245 X(lwc1)
2246 {
2247 const int cpnr = 1;
2248
2249 /* Synch. PC and call the generic load/store function: */
2250 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2251 / sizeof(struct mips_instr_call);
2252 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2253 << MIPS_INSTR_ALIGNMENT_SHIFT);
2254 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2255
2256 /* ... but first, let's see if the coprocessor is available: */
2257 if (!(cpu->cd.mips.coproc[0]->
2258 reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2259 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2260 return;
2261 }
2262
2263 #ifdef MODE32
2264 mips32_loadstore
2265 #else
2266 mips_loadstore
2267 #endif
2268 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 2 * 2 + 1]
2269 (cpu, ic);
2270 }
2271 X(swc1)
2272 {
2273 const int cpnr = 1;
2274
2275 /* Synch. PC and call the generic load/store function: */
2276 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2277 / sizeof(struct mips_instr_call);
2278 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2279 << MIPS_INSTR_ALIGNMENT_SHIFT);
2280 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2281
2282 /* ... but first, let's see if the coprocessor is available: */
2283 if (!(cpu->cd.mips.coproc[0]->
2284 reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2285 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2286 return;
2287 }
2288
2289 #ifdef MODE32
2290 mips32_loadstore
2291 #else
2292 mips_loadstore
2293 #endif
2294 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 2 * 2]
2295 (cpu, ic);
2296 }
2297 X(ldc1)
2298 {
2299 const int cpnr = 1;
2300 int use_fp_pairs =
2301 !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2302 uint64_t fpr, *backup_ptr;
2303
2304 /* Synch. PC and call the generic load/store function: */
2305 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2306 / sizeof(struct mips_instr_call);
2307 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2308 << MIPS_INSTR_ALIGNMENT_SHIFT);
2309 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2310
2311 /* ... but first, let's see if the coprocessor is available: */
2312 if (!(cpu->cd.mips.coproc[0]->
2313 reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2314 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2315 return;
2316 }
2317
2318 backup_ptr = (uint64_t *) ic->arg[0];
2319 ic->arg[0] = (size_t) &fpr;
2320
2321 #ifdef MODE32
2322 mips32_loadstore
2323 #else
2324 mips_loadstore
2325 #endif
2326 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 3 * 2 + 1]
2327 (cpu, ic);
2328
2329 if (use_fp_pairs) {
2330 backup_ptr[0] = (int64_t)(int32_t) fpr;
2331 backup_ptr[1] = (int64_t)(int32_t) (fpr >> 32);
2332 } else {
2333 *backup_ptr = fpr;
2334 }
2335
2336 ic->arg[0] = (size_t) backup_ptr;
2337 }
2338 X(sdc1)
2339 {
2340 const int cpnr = 1;
2341 int use_fp_pairs =
2342 !(cpu->cd.mips.coproc[0]->reg[COP0_STATUS] & STATUS_FR);
2343 uint64_t fpr, *backup_ptr;
2344
2345 /* Synch. PC and call the generic load/store function: */
2346 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
2347 / sizeof(struct mips_instr_call);
2348 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
2349 << MIPS_INSTR_ALIGNMENT_SHIFT);
2350 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
2351
2352 /* ... but first, let's see if the coprocessor is available: */
2353 if (!(cpu->cd.mips.coproc[0]->
2354 reg[COP0_STATUS] & ((1 << cpnr) << STATUS_CU_SHIFT)) ) {
2355 mips_cpu_exception(cpu, EXCEPTION_CPU, 0, 0, cpnr, 0, 0, 0);
2356 return;
2357 }
2358
2359 backup_ptr = (uint64_t *) ic->arg[0];
2360 ic->arg[0] = (size_t) &fpr;
2361
2362 if (use_fp_pairs) {
2363 uint32_t lo = backup_ptr[0];
2364 uint32_t hi = backup_ptr[1];
2365 fpr = (((uint64_t)hi) << 32) | lo;
2366 } else {
2367 fpr = *backup_ptr;
2368 }
2369
2370 #ifdef MODE32
2371 mips32_loadstore
2372 #else
2373 mips_loadstore
2374 #endif
2375 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16) + 8 + 3 * 2]
2376 (cpu, ic);
2377
2378 ic->arg[0] = (size_t) backup_ptr;
2379 }
2380
2381
2382 /*
2383 * Unaligned loads/stores:
2384 *
2385 * arg[0] = ptr to rt
2386 * arg[1] = ptr to rs
2387 * arg[2] = int32_t imm
2388 */
2389 X(lwl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 0); }
2390 X(lwr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 0); }
2391 X(ldl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 0); }
2392 X(ldr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 0); }
2393 X(swl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint32_t), 1); }
2394 X(swr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint32_t), 1); }
2395 X(sdl) { mips_unaligned_loadstore(cpu, ic, 1, sizeof(uint64_t), 1); }
2396 X(sdr) { mips_unaligned_loadstore(cpu, ic, 0, sizeof(uint64_t), 1); }
2397
2398
2399 /*
2400 * di, ei: R5900 interrupt enable/disable.
2401 *
2402 * TODO: check the R5900_STATUS_EDI bit in the status register. If it is
2403 * cleared, and we are not running in kernel mode, then both the EI and DI
2404 * instructions should be treated as NOPs!
2405 */
2406 X(di_r5900)
2407 {
2408 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] &= ~R5900_STATUS_EIE;
2409 }
2410 X(ei_r5900)
2411 {
2412 cpu->cd.mips.coproc[0]->reg[COP0_STATUS] |= R5900_STATUS_EIE;
2413 }
2414
2415
2416 /*****************************************************************************/
2417
2418
2419 /*
2420 * sw_loop:
2421 *
2422 * s: addiu rX,rX,4 rX = arg[0] and arg[1]
2423 * bne rY,rX,s (or rX,rY,s) rt=arg[1], rs=arg[0]
2424 * sw rZ,-4(rX) rt=arg[0], rs=arg[1]
2425 */
2426 X(sw_loop)
2427 {
2428 MODE_uint_t rX = reg(ic->arg[0]), rZ = reg(ic[2].arg[0]);
2429 uint64_t *rYp = (uint64_t *) ic[1].arg[0];
2430 MODE_uint_t rY, bytes_to_write;
2431 unsigned char *page;
2432 int partial = 0;
2433
2434 page = cpu->cd.mips.host_store[rX >> 12];
2435
2436 /* Fallback: */
2437 if (cpu->delay_slot || page == NULL || (rX & 3) != 0 || rZ != 0) {
2438 instr(addiu)(cpu, ic);
2439 return;
2440 }
2441
2442 if (rYp == (uint64_t *) ic->arg[0])
2443 rYp = (uint64_t *) ic[1].arg[1];
2444
2445 rY = reg(rYp);
2446
2447 bytes_to_write = rY - rX;
2448 if ((rX & 0xfff) + bytes_to_write > 0x1000) {
2449 bytes_to_write = 0x1000 - (rX & 0xfff);
2450 partial = 1;
2451 }
2452
2453 /* printf("rX = %08x\n", (int)rX);
2454 printf("rY = %08x\n", (int)rY);
2455 printf("rZ = %08x\n", (int)rZ);
2456 printf("%i bytes\n", (int)bytes_to_write); */
2457
2458 memset(page + (rX & 0xfff), 0, bytes_to_write);
2459
2460 reg(ic->arg[0]) = rX + bytes_to_write;
2461
2462 cpu->n_translated_instrs += bytes_to_write / 4 * 3 - 1;
2463 cpu->cd.mips.next_ic = partial?
2464 (struct mips_instr_call *) &ic[0] :
2465 (struct mips_instr_call *) &ic[3];
2466 }
2467
2468
2469 #ifdef MODE32
2470 /*
2471 * multi_sw_2, _3, _4:
2472 *
2473 * sw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2]
2474 */
2475 X(multi_sw_2_le)
2476 {
2477 uint32_t *page;
2478 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2479 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2480 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2481 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2482
2483 page = (uint32_t *) cpu->cd.mips.host_store[index0];
2484
2485 /* Fallback: */
2486 if (cpu->delay_slot ||
2487 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2488 index0 != index1) {
2489 /* Normal safe sw: */
2490 mips32_loadstore[8 + 2 * 2](cpu, ic);
2491 return;
2492 }
2493
2494 addr0 = (addr0 >> 2) & 0x3ff;
2495 addr1 = (addr1 >> 2) & 0x3ff;
2496
2497 r1 = reg(ic[0].arg[0]);
2498 r2 = reg(ic[1].arg[0]);
2499
2500 r1 = LE32_TO_HOST(r1);
2501 r2 = LE32_TO_HOST(r2);
2502
2503 page[addr0] = r1;
2504 page[addr1] = r2;
2505
2506 cpu->n_translated_instrs ++;
2507 cpu->cd.mips.next_ic ++;
2508 }
2509 X(multi_sw_2_be)
2510 {
2511 uint32_t *page;
2512 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2513 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2514 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2515 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2516
2517 page = (uint32_t *) cpu->cd.mips.host_store[index0];
2518
2519 /* Fallback: */
2520 if (cpu->delay_slot ||
2521 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2522 index0 != index1) {
2523 /* Normal safe sw: */
2524 mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2525 return;
2526 }
2527
2528 addr0 = (addr0 >> 2) & 0x3ff;
2529 addr1 = (addr1 >> 2) & 0x3ff;
2530
2531 r1 = reg(ic[0].arg[0]);
2532 r2 = reg(ic[1].arg[0]);
2533
2534 r1 = BE32_TO_HOST(r1);
2535 r2 = BE32_TO_HOST(r2);
2536
2537 page[addr0] = r1;
2538 page[addr1] = r2;
2539
2540 cpu->n_translated_instrs ++;
2541 cpu->cd.mips.next_ic ++;
2542 }
2543 X(multi_sw_3_le)
2544 {
2545 uint32_t *page;
2546 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2547 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2548 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2549 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2550 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2551 index2 = addr2 >> 12;
2552
2553 page = (uint32_t *) cpu->cd.mips.host_store[index0];
2554
2555 /* Fallback: */
2556 if (cpu->delay_slot ||
2557 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2558 (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2559 /* Normal safe sw: */
2560 mips32_loadstore[8 + 2 * 2](cpu, ic);
2561 return;
2562 }
2563
2564 addr0 = (addr0 >> 2) & 0x3ff;
2565 addr1 = (addr1 >> 2) & 0x3ff;
2566 addr2 = (addr2 >> 2) & 0x3ff;
2567
2568 /* printf("addr0=%x 1=%x 2=%x\n",
2569 (int)addr0, (int)addr1, (int)addr2); */
2570
2571 r1 = reg(ic[0].arg[0]);
2572 r2 = reg(ic[1].arg[0]);
2573 r3 = reg(ic[2].arg[0]);
2574
2575 r1 = LE32_TO_HOST(r1);
2576 r2 = LE32_TO_HOST(r2);
2577 r3 = LE32_TO_HOST(r3);
2578
2579 page[addr0] = r1;
2580 page[addr1] = r2;
2581 page[addr2] = r3;
2582
2583 cpu->n_translated_instrs += 2;
2584 cpu->cd.mips.next_ic += 2;
2585 }
2586 X(multi_sw_3_be)
2587 {
2588 uint32_t *page;
2589 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2590 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2591 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2592 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2593 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2594 index2 = addr2 >> 12;
2595
2596 page = (uint32_t *) cpu->cd.mips.host_store[index0];
2597
2598 /* Fallback: */
2599 if (cpu->delay_slot ||
2600 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2601 (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2602 /* Normal safe sw: */
2603 mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2604 return;
2605 }
2606
2607 addr0 = (addr0 >> 2) & 0x3ff;
2608 addr1 = (addr1 >> 2) & 0x3ff;
2609 addr2 = (addr2 >> 2) & 0x3ff;
2610
2611 /* printf("addr0=%x 1=%x 2=%x\n",
2612 (int)addr0, (int)addr1, (int)addr2); */
2613
2614 r1 = reg(ic[0].arg[0]);
2615 r2 = reg(ic[1].arg[0]);
2616 r3 = reg(ic[2].arg[0]);
2617
2618 r1 = BE32_TO_HOST(r1);
2619 r2 = BE32_TO_HOST(r2);
2620 r3 = BE32_TO_HOST(r3);
2621
2622 page[addr0] = r1;
2623 page[addr1] = r2;
2624 page[addr2] = r3;
2625
2626 cpu->n_translated_instrs += 2;
2627 cpu->cd.mips.next_ic += 2;
2628 }
2629 X(multi_sw_4_le)
2630 {
2631 uint32_t *page;
2632 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2633 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2634 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2635 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2636 MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2637 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2638 index2 = addr2 >> 12, index3 = addr3 >> 12;
2639
2640 page = (uint32_t *) cpu->cd.mips.host_store[index0];
2641
2642 /* Fallback: */
2643 if (cpu->delay_slot ||
2644 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2645 (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 ||
2646 index0 != index2 || index0 != index3) {
2647 /* Normal safe sw: */
2648 mips32_loadstore[8 + 2 * 2](cpu, ic);
2649 return;
2650 }
2651
2652 addr0 = (addr0 >> 2) & 0x3ff;
2653 addr1 = (addr1 >> 2) & 0x3ff;
2654 addr2 = (addr2 >> 2) & 0x3ff;
2655 addr3 = (addr3 >> 2) & 0x3ff;
2656
2657 r1 = reg(ic[0].arg[0]);
2658 r2 = reg(ic[1].arg[0]);
2659 r3 = reg(ic[2].arg[0]);
2660 r4 = reg(ic[3].arg[0]);
2661
2662 r1 = LE32_TO_HOST(r1);
2663 r2 = LE32_TO_HOST(r2);
2664 r3 = LE32_TO_HOST(r3);
2665 r4 = LE32_TO_HOST(r4);
2666
2667 page[addr0] = r1;
2668 page[addr1] = r2;
2669 page[addr2] = r3;
2670 page[addr3] = r4;
2671
2672 cpu->n_translated_instrs += 3;
2673 cpu->cd.mips.next_ic += 3;
2674 }
2675 X(multi_sw_4_be)
2676 {
2677 uint32_t *page;
2678 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2679 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2680 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2681 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2682 MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2683 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2684 index2 = addr2 >> 12, index3 = addr3 >> 12;
2685
2686 page = (uint32_t *) cpu->cd.mips.host_store[index0];
2687
2688 /* Fallback: */
2689 if (cpu->delay_slot ||
2690 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2691 (addr2 & 3) != 0 || (addr3 & 3) != 0 || index0 != index1 ||
2692 index0 != index2 || index0 != index3) {
2693 /* Normal safe sw: */
2694 mips32_loadstore[16 + 8 + 2 * 2](cpu, ic);
2695 return;
2696 }
2697
2698 addr0 = (addr0 >> 2) & 0x3ff;
2699 addr1 = (addr1 >> 2) & 0x3ff;
2700 addr2 = (addr2 >> 2) & 0x3ff;
2701 addr3 = (addr3 >> 2) & 0x3ff;
2702
2703 r1 = reg(ic[0].arg[0]);
2704 r2 = reg(ic[1].arg[0]);
2705 r3 = reg(ic[2].arg[0]);
2706 r4 = reg(ic[3].arg[0]);
2707
2708 r1 = BE32_TO_HOST(r1);
2709 r2 = BE32_TO_HOST(r2);
2710 r3 = BE32_TO_HOST(r3);
2711 r4 = BE32_TO_HOST(r4);
2712
2713 page[addr0] = r1;
2714 page[addr1] = r2;
2715 page[addr2] = r3;
2716 page[addr3] = r4;
2717
2718 cpu->n_translated_instrs += 3;
2719 cpu->cd.mips.next_ic += 3;
2720 }
2721 #endif
2722
2723
2724 #ifdef MODE32
2725 /*
2726 * multi_lw_2, _3, _4:
2727 *
2728 * lw r?,ofs(rX) r?=arg[0], rX=arg[1], ofs=arg[2]
2729 */
2730 X(multi_lw_2_le)
2731 {
2732 uint32_t *page;
2733 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2734 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2735 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2736 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2737
2738 page = (uint32_t *) cpu->cd.mips.host_load[index0];
2739
2740 /* Fallback: */
2741 if (cpu->delay_slot ||
2742 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2743 index0 != index1) {
2744 /* Normal safe lw: */
2745 mips32_loadstore[2 * 2 + 1](cpu, ic);
2746 return;
2747 }
2748
2749 addr0 = (addr0 >> 2) & 0x3ff;
2750 addr1 = (addr1 >> 2) & 0x3ff;
2751
2752 r1 = page[addr0];
2753 r2 = page[addr1];
2754
2755 r1 = LE32_TO_HOST(r1);
2756 r2 = LE32_TO_HOST(r2);
2757
2758 reg(ic[0].arg[0]) = r1;
2759 reg(ic[1].arg[0]) = r2;
2760
2761 cpu->n_translated_instrs ++;
2762 cpu->cd.mips.next_ic ++;
2763 }
2764 X(multi_lw_2_be)
2765 {
2766 uint32_t *page;
2767 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2;
2768 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2769 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2770 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12;
2771
2772 page = (uint32_t *) cpu->cd.mips.host_load[index0];
2773
2774 /* Fallback: */
2775 if (cpu->delay_slot ||
2776 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2777 index0 != index1) {
2778 /* Normal safe lw: */
2779 mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2780 return;
2781 }
2782
2783 addr0 = (addr0 >> 2) & 0x3ff;
2784 addr1 = (addr1 >> 2) & 0x3ff;
2785
2786 r1 = page[addr0];
2787 r2 = page[addr1];
2788
2789 r1 = BE32_TO_HOST(r1);
2790 r2 = BE32_TO_HOST(r2);
2791
2792 reg(ic[0].arg[0]) = r1;
2793 reg(ic[1].arg[0]) = r2;
2794
2795 cpu->n_translated_instrs ++;
2796 cpu->cd.mips.next_ic ++;
2797 }
2798 X(multi_lw_3_le)
2799 {
2800 uint32_t *page;
2801 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2802 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2803 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2804 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2805 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2806 index2 = addr2 >> 12;
2807
2808 page = (uint32_t *) cpu->cd.mips.host_load[index0];
2809
2810 /* Fallback: */
2811 if (cpu->delay_slot ||
2812 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2813 (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2814 /* Normal safe lw: */
2815 mips32_loadstore[2 * 2 + 1](cpu, ic);
2816 return;
2817 }
2818
2819 addr0 = (addr0 >> 2) & 0x3ff;
2820 addr1 = (addr1 >> 2) & 0x3ff;
2821 addr2 = (addr2 >> 2) & 0x3ff;
2822
2823 /* printf("addr0=%x 1=%x 2=%x\n",
2824 (int)addr0, (int)addr1, (int)addr2); */
2825
2826 r1 = page[addr0];
2827 r2 = page[addr1];
2828 r3 = page[addr2];
2829
2830 r1 = LE32_TO_HOST(r1);
2831 r2 = LE32_TO_HOST(r2);
2832 r3 = LE32_TO_HOST(r3);
2833
2834 reg(ic[0].arg[0]) = r1;
2835 reg(ic[1].arg[0]) = r2;
2836 reg(ic[2].arg[0]) = r3;
2837
2838 cpu->n_translated_instrs += 2;
2839 cpu->cd.mips.next_ic += 2;
2840 }
2841 X(multi_lw_3_be)
2842 {
2843 uint32_t *page;
2844 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3;
2845 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2846 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2847 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2848 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2849 index2 = addr2 >> 12;
2850
2851 page = (uint32_t *) cpu->cd.mips.host_load[index0];
2852
2853 /* Fallback: */
2854 if (cpu->delay_slot ||
2855 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2856 (addr2 & 3) != 0 || index0 != index1 || index0 != index2) {
2857 /* Normal safe lw: */
2858 mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2859 return;
2860 }
2861
2862 addr0 = (addr0 >> 2) & 0x3ff;
2863 addr1 = (addr1 >> 2) & 0x3ff;
2864 addr2 = (addr2 >> 2) & 0x3ff;
2865
2866 /* printf("addr0=%x 1=%x 2=%x\n",
2867 (int)addr0, (int)addr1, (int)addr2); */
2868
2869 r1 = page[addr0];
2870 r2 = page[addr1];
2871 r3 = page[addr2];
2872
2873 r1 = BE32_TO_HOST(r1);
2874 r2 = BE32_TO_HOST(r2);
2875 r3 = BE32_TO_HOST(r3);
2876
2877 reg(ic[0].arg[0]) = r1;
2878 reg(ic[1].arg[0]) = r2;
2879 reg(ic[2].arg[0]) = r3;
2880
2881 cpu->n_translated_instrs += 2;
2882 cpu->cd.mips.next_ic += 2;
2883 }
2884 X(multi_lw_4_le)
2885 {
2886 uint32_t *page;
2887 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2888 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2889 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2890 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2891 MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2892 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2893 index2 = addr2 >> 12, index3 = addr3 >> 12;
2894
2895 page = (uint32_t *) cpu->cd.mips.host_load[index0];
2896
2897 /* Fallback: */
2898 if (cpu->delay_slot ||
2899 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2900 (addr2 & 3) != 0 || (addr3 & 3) != 0 ||
2901 index0 != index1 || index0 != index2 || index0 != index3) {
2902 /* Normal safe lw: */
2903 mips32_loadstore[2 * 2 + 1](cpu, ic);
2904 return;
2905 }
2906
2907 addr0 = (addr0 >> 2) & 0x3ff;
2908 addr1 = (addr1 >> 2) & 0x3ff;
2909 addr2 = (addr2 >> 2) & 0x3ff;
2910 addr3 = (addr3 >> 2) & 0x3ff;
2911
2912 r1 = page[addr0];
2913 r2 = page[addr1];
2914 r3 = page[addr2];
2915 r4 = page[addr3];
2916
2917 r1 = LE32_TO_HOST(r1);
2918 r2 = LE32_TO_HOST(r2);
2919 r3 = LE32_TO_HOST(r3);
2920 r4 = LE32_TO_HOST(r4);
2921
2922 reg(ic[0].arg[0]) = r1;
2923 reg(ic[1].arg[0]) = r2;
2924 reg(ic[2].arg[0]) = r3;
2925 reg(ic[3].arg[0]) = r4;
2926
2927 cpu->n_translated_instrs += 3;
2928 cpu->cd.mips.next_ic += 3;
2929 }
2930 X(multi_lw_4_be)
2931 {
2932 uint32_t *page;
2933 MODE_uint_t rX = reg(ic[0].arg[1]), r1, r2, r3, r4;
2934 MODE_uint_t addr0 = rX + (int32_t)ic[0].arg[2];
2935 MODE_uint_t addr1 = rX + (int32_t)ic[1].arg[2];
2936 MODE_uint_t addr2 = rX + (int32_t)ic[2].arg[2];
2937 MODE_uint_t addr3 = rX + (int32_t)ic[3].arg[2];
2938 uint32_t index0 = addr0 >> 12, index1 = addr1 >> 12,
2939 index2 = addr2 >> 12, index3 = addr3 >> 12;
2940
2941 page = (uint32_t *) cpu->cd.mips.host_load[index0];
2942
2943 /* Fallback: */
2944 if (cpu->delay_slot ||
2945 page == NULL || (addr0 & 3) != 0 || (addr1 & 3) != 0 ||
2946 (addr2 & 3) != 0 || (addr3 & 3) != 0 ||
2947 index0 != index1 || index0 != index2 || index0 != index3) {
2948 /* Normal safe lw: */
2949 mips32_loadstore[16 + 2 * 2 + 1](cpu, ic);
2950 return;
2951 }
2952
2953 addr0 = (addr0 >> 2) & 0x3ff;
2954 addr1 = (addr1 >> 2) & 0x3ff;
2955 addr2 = (addr2 >> 2) & 0x3ff;
2956 addr3 = (addr3 >> 2) & 0x3ff;
2957
2958 r1 = page[addr0];
2959 r2 = page[addr1];
2960 r3 = page[addr2];
2961 r4 = page[addr3];
2962
2963 r1 = BE32_TO_HOST(r1);
2964 r2 = BE32_TO_HOST(r2);
2965 r3 = BE32_TO_HOST(r3);
2966 r4 = BE32_TO_HOST(r4);
2967
2968 reg(ic[0].arg[0]) = r1;
2969 reg(ic[1].arg[0]) = r2;
2970 reg(ic[2].arg[0]) = r3;
2971 reg(ic[3].arg[0]) = r4;
2972
2973 cpu->n_translated_instrs += 3;
2974 cpu->cd.mips.next_ic += 3;
2975 }
2976 #endif
2977
2978
2979 /*
2980 * multi_addu_3:
2981 */
2982 X(multi_addu_3)
2983 {
2984 /* Fallback: */
2985 if (cpu->delay_slot) {
2986 instr(addu)(cpu, ic);
2987 return;
2988 }
2989
2990 reg(ic[0].arg[2]) = (int32_t)(reg(ic[0].arg[0]) + reg(ic[0].arg[1]));
2991 reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0]) + reg(ic[1].arg[1]));
2992 reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0]) + reg(ic[2].arg[1]));
2993 cpu->n_translated_instrs += 2;
2994 cpu->cd.mips.next_ic += 2;
2995 }
2996
2997
2998 /*
2999 * netbsd_r3k_picache_do_inv:
3000 *
3001 * ic[0] mtc0 rV,status
3002 * 1 nop
3003 * 2 nop
3004 * 3 s: addiu rX,rX,4
3005 * 4 bne rY,rX,s
3006 * 5 sb zr,-4(rX)
3007 * 6 nop
3008 * 7 nop
3009 * 8 mtc0 rT,status
3010 */
3011 X(netbsd_r3k_picache_do_inv)
3012 {
3013 MODE_uint_t rx = reg(ic[3].arg[0]), ry = reg(ic[4].arg[1]);
3014
3015 /* Fallback if the environment isn't exactly right: */
3016 if (!(reg(ic[0].arg[0]) & MIPS1_ISOL_CACHES) ||
3017 (rx & 3) || (ry & 3) || cpu->delay_slot) {
3018 instr(mtc0)(cpu, ic);
3019 return;
3020 }
3021
3022 reg(ic[3].arg[0]) = ry;
3023 cpu->n_translated_instrs += (ry - rx + 4) / 4 * 3 + 4;
3024
3025 /* Run the last mtc0 instruction: */
3026 cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[8];
3027 }
3028
3029
3030 #ifdef MODE32
3031 /*
3032 * netbsd_strlen():
3033 *
3034 * lb rV,0(rX)
3035 * s: addiu rX,rX,1
3036 * bne zr,rV,s
3037 * nop
3038 */
3039 X(netbsd_strlen)
3040 {
3041 MODE_uint_t rx = reg(ic[0].arg[1]);
3042 MODE_int_t rv;
3043 signed char *page;
3044 uint32_t pageindex = rx >> 12;
3045 int i;
3046
3047 page = (signed char *) cpu->cd.mips.host_load[pageindex];
3048
3049 /* Fallback: */
3050 if (cpu->delay_slot || page == NULL) {
3051 /*
3052 * Normal lb: NOTE: It doesn't matter whether [1] or
3053 * [16+1] is called here, because endianness for 8-bit
3054 * loads is irrelevant. :-)
3055 */
3056 mips32_loadstore[1](cpu, ic);
3057 return;
3058 }
3059
3060 i = rx & 0xfff;
3061
3062 /*
3063 * TODO: This loop can be optimized further for optimal
3064 * performance on the host, e.g. by reading full words...
3065 */
3066 do {
3067 rv = page[i ++];
3068 } while (i < 0x1000 && rv != 0);
3069
3070 cpu->n_translated_instrs += (i - (rx & 0xfff)) * 4 - 1;
3071
3072 reg(ic[0].arg[1]) = (rx & ~0xfff) + i;
3073 reg(ic[2].arg[0]) = rv;
3074
3075 /* Done with the loop? Or continue on the next rx page? */
3076 if (rv == 0)
3077 cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[4];
3078 else
3079 cpu->cd.mips.next_ic = (struct mips_instr_call *) &ic[0];
3080 }
3081 #endif
3082
3083
3084 /*
3085 * addiu_bne_samepage_addiu:
3086 */
3087 X(addiu_bne_samepage_addiu)
3088 {
3089 MODE_uint_t rs, rt;
3090
3091 if (cpu->delay_slot) {
3092 instr(addiu)(cpu, ic);
3093 return;
3094 }
3095
3096 cpu->n_translated_instrs += 2;
3097 reg(ic[0].arg[1]) = (int32_t)
3098 ((int32_t)reg(ic[0].arg[0]) + (int32_t)ic[0].arg[2]);
3099 rs = reg(ic[1].arg[0]);
3100 rt = reg(ic[1].arg[1]);
3101 reg(ic[2].arg[1]) = (int32_t)
3102 ((int32_t)reg(ic[2].arg[0]) + (int32_t)ic[2].arg[2]);
3103 if (rs != rt)
3104 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic[1].arg[2];
3105 else
3106 cpu->cd.mips.next_ic += 2;
3107 }
3108
3109
3110 /*
3111 * xor_andi_sll:
3112 */
3113 X(xor_andi_sll)
3114 {
3115 /* Fallback: */
3116 if (cpu->delay_slot) {
3117 instr(xor)(cpu, ic);
3118 return;
3119 }
3120
3121 reg(ic[0].arg[2]) = reg(ic[0].arg[0]) ^ reg(ic[0].arg[1]);
3122 reg(ic[1].arg[1]) = reg(ic[1].arg[0]) & (uint32_t)ic[1].arg[2];
3123 reg(ic[2].arg[2]) = (int32_t)(reg(ic[2].arg[0])<<(int32_t)ic[2].arg[1]);
3124
3125 cpu->n_translated_instrs += 2;
3126 cpu->cd.mips.next_ic += 2;
3127 }
3128
3129
3130 /*
3131 * andi_sll:
3132 */
3133 X(andi_sll)
3134 {
3135 /* Fallback: */
3136 if (cpu->delay_slot) {
3137 instr(andi)(cpu, ic);
3138 return;
3139 }
3140
3141 reg(ic[0].arg[1]) = reg(ic[0].arg[0]) & (uint32_t)ic[0].arg[2];
3142 reg(ic[1].arg[2]) = (int32_t)(reg(ic[1].arg[0])<<(int32_t)ic[1].arg[1]);
3143
3144 cpu->n_translated_instrs ++;
3145 cpu->cd.mips.next_ic ++;
3146 }
3147
3148
3149 /*
3150 * lui_ori:
3151 */
3152 X(lui_ori)
3153 {
3154 /* Fallback: */
3155 if (cpu->delay_slot) {
3156 instr(set)(cpu, ic);
3157 return;
3158 }
3159
3160 reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3161 reg(ic[1].arg[1]) = reg(ic[1].arg[0]) | (uint32_t)ic[1].arg[2];
3162
3163 cpu->n_translated_instrs ++;
3164 cpu->cd.mips.next_ic ++;
3165 }
3166
3167
3168 /*
3169 * lui_addiu:
3170 */
3171 X(lui_addiu)
3172 {
3173 /* Fallback: */
3174 if (cpu->delay_slot) {
3175 instr(set)(cpu, ic);
3176 return;
3177 }
3178
3179 reg(ic[0].arg[0]) = (int32_t)ic[0].arg[1];
3180 reg(ic[1].arg[1]) = (int32_t)
3181 ((int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2]);
3182
3183 cpu->n_translated_instrs ++;
3184 cpu->cd.mips.next_ic ++;
3185 }
3186
3187
3188 /*
3189 * b_samepage_addiu:
3190 *
3191 * Combination of branch within the same page, followed by addiu.
3192 */
3193 X(b_samepage_addiu)
3194 {
3195 reg(ic[1].arg[1]) = (int32_t)
3196 ( (int32_t)reg(ic[1].arg[0]) + (int32_t)ic[1].arg[2] );
3197 cpu->n_translated_instrs ++;
3198 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
3199 }
3200
3201
3202 /*
3203 * b_samepage_daddiu:
3204 *
3205 * Combination of branch within the same page, followed by daddiu.
3206 */
3207 X(b_samepage_daddiu)
3208 {
3209 *(uint64_t *)ic[1].arg[1] = *(uint64_t *)ic[1].arg[0] +
3210 (int32_t)ic[1].arg[2];
3211 cpu->n_translated_instrs ++;
3212 cpu->cd.mips.next_ic = (struct mips_instr_call *) ic->arg[2];
3213 }
3214
3215
3216 /*****************************************************************************/
3217
3218
3219 X(end_of_page)
3220 {
3221 /* Update the PC: (offset 0, but on the next page) */
3222 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1) <<
3223 MIPS_INSTR_ALIGNMENT_SHIFT);
3224 cpu->pc += (MIPS_IC_ENTRIES_PER_PAGE << MIPS_INSTR_ALIGNMENT_SHIFT);
3225
3226 /* end_of_page doesn't count as an executed instruction: */
3227 cpu->n_translated_instrs --;
3228
3229 /*
3230 * Find the new physpage and update translation pointers.
3231 *
3232 * Note: This may cause an exception, if e.g. the new page is
3233 * not accessible.
3234 */
3235 quick_pc_to_pointers(cpu);
3236
3237 /* Simple jump to the next page (if we are lucky): */
3238 if (cpu->delay_slot == NOT_DELAYED)
3239 return;
3240
3241 /*
3242 * If we were in a delay slot, and we got an exception while doing
3243 * quick_pc_to_pointers, then return. The function which called
3244 * end_of_page should handle this case.
3245 */
3246 if (cpu->delay_slot == EXCEPTION_IN_DELAY_SLOT)
3247 return;
3248
3249 /*
3250 * Tricky situation; the delay slot is on the next virtual page.
3251 * Calling to_be_translated will translate one instruction manually,
3252 * execute it, and then discard it.
3253 */
3254 /* fatal("[ end_of_page: delay slot across page boundary! ]\n"); */
3255
3256 instr(to_be_translated)(cpu, cpu->cd.mips.next_ic);
3257
3258 /* The instruction in the delay slot has now executed. */
3259 /* fatal("[ end_of_page: back from executing the delay slot, %i ]\n",
3260 cpu->delay_slot); */
3261
3262 /* Find the physpage etc of the instruction in the delay slot
3263 (or, if there was an exception, the exception handler): */
3264 quick_pc_to_pointers(cpu);
3265 }
3266
3267
3268 X(end_of_page2)
3269 {
3270 /* Synchronize PC on the _second_ instruction on the next page: */
3271 int low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
3272 / sizeof(struct mips_instr_call);
3273 cpu->pc &= ~((MIPS_IC_ENTRIES_PER_PAGE-1)
3274 << MIPS_INSTR_ALIGNMENT_SHIFT);
3275 cpu->pc += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
3276
3277 /* This doesn't count as an executed instruction. */
3278 cpu->n_translated_instrs --;
3279
3280 quick_pc_to_pointers(cpu);
3281
3282 if (cpu->delay_slot == NOT_DELAYED)
3283 return;
3284
3285 fatal("end_of_page2: fatal error, we're in a delay slot\n");
3286 exit(1);
3287 }
3288
3289
3290 /*****************************************************************************/
3291
3292
3293 /*
3294 * Combine: Memory fill loop (addiu, bne, sw)
3295 *
3296 * s: addiu rX,rX,4
3297 * bne rY,rX,s
3298 * sw rZ,-4(rX)
3299 */
3300 void COMBINE(sw_loop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3301 {
3302 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3303 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3304
3305 /* Only for 32-bit virtual address translation so far. */
3306 if (!cpu->is_32bit)
3307 return;
3308
3309 if (n_back < 2)
3310 return;
3311
3312 if (ic[-2].f == instr(addiu) && ic[-2].arg[0] == ic[-2].arg[1] &&
3313 (int32_t)ic[-2].arg[2] == 4 &&
3314 ic[-1].f == instr(bne_samepage) &&
3315 (ic[-1].arg[0] == ic[-2].arg[0] ||
3316 ic[-1].arg[1] == ic[-2].arg[0]) &&
3317 ic[-1].arg[0] != ic[-1].arg[1] &&
3318 ic[-1].arg[2] == (size_t) &ic[-2] &&
3319 ic[0].arg[0] != ic[0].arg[1] &&
3320 ic[0].arg[1] == ic[-2].arg[0] && (int32_t)ic[0].arg[2] == -4) {
3321 ic[-2].f = instr(sw_loop);
3322 }
3323 }
3324
3325
3326 /* Only for 32-bit virtual address translation so far. */
3327 #ifdef MODE32
3328 /*
3329 * Combine: Multiple SW in a row using the same base register
3330 *
3331 * sw r?,???(rX)
3332 * sw r?,???(rX)
3333 * sw r?,???(rX)
3334 * ...
3335 */
3336 void COMBINE(multi_sw)(struct cpu *cpu, struct mips_instr_call *ic,
3337 int low_addr)
3338 {
3339 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3340 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3341
3342 if (n_back < 3)
3343 return;
3344
3345 /* Convert a multi_sw_3 to a multi_sw_4: */
3346 if ((ic[-3].f == instr(multi_sw_3_be) ||
3347 ic[-3].f == instr(multi_sw_3_le)) &&
3348 ic[-3].arg[1] == ic[0].arg[1]) {
3349 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3350 ic[-3].f = instr(multi_sw_4_le);
3351 else
3352 ic[-3].f = instr(multi_sw_4_be);
3353 }
3354
3355 /* Convert a multi_sw_2 to a multi_sw_3: */
3356 if ((ic[-2].f == instr(multi_sw_2_be) ||
3357 ic[-2].f == instr(multi_sw_2_le)) &&
3358 ic[-2].arg[1] == ic[0].arg[1]) {
3359 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3360 ic[-2].f = instr(multi_sw_3_le);
3361 else
3362 ic[-2].f = instr(multi_sw_3_be);
3363 }
3364
3365 if (ic[-1].f == ic[0].f && ic[-1].arg[1] == ic[0].arg[1]) {
3366 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3367 ic[-1].f = instr(multi_sw_2_le);
3368 else
3369 ic[-1].f = instr(multi_sw_2_be);
3370 }
3371 }
3372 #endif
3373
3374
3375 /* Only for 32-bit virtual address translation so far. */
3376 #ifdef MODE32
3377 /*
3378 * Combine: Multiple LW in a row using the same base register
3379 *
3380 * lw r?,???(rX)
3381 * lw r?,???(rX)
3382 * lw r?,???(rX)
3383 * ...
3384 */
3385 void COMBINE(multi_lw)(struct cpu *cpu, struct mips_instr_call *ic,
3386 int low_addr)
3387 {
3388 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3389 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3390
3391 if (n_back < 3)
3392 return;
3393
3394 /* Convert a multi_lw_3 to a multi_lw_4: */
3395 if ((ic[-3].f == instr(multi_lw_3_be) ||
3396 ic[-3].f == instr(multi_lw_3_le)) &&
3397 ic[-3].arg[1] == ic[0].arg[1] &&
3398 ic[-1].arg[0] != ic[0].arg[1]) {
3399 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3400 ic[-3].f = instr(multi_lw_4_le);
3401 else
3402 ic[-3].f = instr(multi_lw_4_be);
3403 }
3404
3405 /* Convert a multi_lw_2 to a multi_lw_3: */
3406 if ((ic[-2].f == instr(multi_lw_2_be) ||
3407 ic[-2].f == instr(multi_lw_2_le)) &&
3408 ic[-2].arg[1] == ic[0].arg[1] &&
3409 ic[-1].arg[0] != ic[0].arg[1]) {
3410 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3411 ic[-2].f = instr(multi_lw_3_le);
3412 else
3413 ic[-2].f = instr(multi_lw_3_be);
3414 }
3415
3416 /* Note: Loads to the base register are not allowed in slot -1. */
3417 if (ic[-1].f == ic[0].f &&
3418 ic[-1].arg[1] == ic[0].arg[1] &&
3419 ic[-1].arg[0] != ic[0].arg[1]) {
3420 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3421 ic[-1].f = instr(multi_lw_2_le);
3422 else
3423 ic[-1].f = instr(multi_lw_2_be);
3424 }
3425 }
3426 #endif
3427
3428
3429 /*
3430 * Combine: NetBSD/pmax 3.0 R2000/R3000 physical cache invalidation loop
3431 *
3432 * Instruction cache loop:
3433 *
3434 * ic[-8] mtc0 rV,status
3435 * -7 nop
3436 * -6 nop
3437 * -5 s: addiu rX,rX,4
3438 * -4 bne rY,rX,s
3439 * -3 sb zr,-4(rX)
3440 * -2 nop
3441 * -1 nop
3442 * 0 mtc0 rT,status
3443 */
3444 void COMBINE(netbsd_r3k_cache_inv)(struct cpu *cpu,
3445 struct mips_instr_call *ic, int low_addr)
3446 {
3447 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3448 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3449
3450 if (n_back < 8)
3451 return;
3452
3453 if (ic[-8].f == instr(mtc0) && ic[-8].arg[1] == COP0_STATUS &&
3454 ic[-7].f == instr(nop) && ic[-6].f == instr(nop) &&
3455 ic[-5].f == instr(addiu) && ic[-5].arg[0] == ic[-5].arg[1] &&
3456 (int32_t)ic[-5].arg[2] == 4 && ic[-4].f == instr(bne_samepage) &&
3457 ic[-4].arg[0] == ic[-5].arg[0] && ic[-4].arg[0] != ic[-4].arg[1] &&
3458 ic[-4].arg[2] == (size_t) &ic[-5] &&
3459 ic[-3].arg[1] == ic[-5].arg[0] &&
3460 ic[-2].f == instr(nop) && ic[-1].f == instr(nop)) {
3461 ic[-8].f = instr(netbsd_r3k_picache_do_inv);
3462 }
3463 }
3464
3465
3466 /*
3467 * Combine: something ending with a nop.
3468 *
3469 * NetBSD's strlen core.
3470 * [Conditional] branch, followed by nop.
3471 */
3472 void COMBINE(nop)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3473 {
3474 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3475 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3476
3477 #ifdef MODE32
3478 if (n_back < 3)
3479 return;
3480
3481 if ((ic[-3].f == mips32_loadstore[1] ||
3482 ic[-3].f == mips32_loadstore[16 + 1]) &&
3483 ic[-3].arg[2] == 0 &&
3484 ic[-3].arg[0] == ic[-1].arg[0] && ic[-3].arg[1] == ic[-2].arg[0] &&
3485 ic[-2].arg[0] == ic[-2].arg[1] && ic[-2].arg[2] == 1 &&
3486 ic[-2].f == instr(addiu) && ic[-1].arg[2] == (size_t) &ic[-3] &&
3487 ic[-1].arg[1] == (size_t) &cpu->cd.mips.gpr[MIPS_GPR_ZERO] &&
3488 ic[-1].f == instr(bne_samepage)) {
3489 ic[-3].f = instr(netbsd_strlen);
3490 return;
3491 }
3492 #endif
3493
3494 if (n_back < 1)
3495 return;
3496
3497 if (ic[-1].f == instr(bne_samepage)) {
3498 ic[-1].f = instr(bne_samepage_nop);
3499 return;
3500 }
3501
3502 if (ic[-1].f == instr(beq_samepage)) {
3503 ic[-1].f = instr(beq_samepage_nop);
3504 return;
3505 }
3506
3507 /* TODO: other branches that are followed by nop should be here */
3508 }
3509
3510
3511 /*
3512 * Combine:
3513 *
3514 * xor + andi + sll
3515 * andi + sll
3516 */
3517 void COMBINE(sll)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3518 {
3519 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3520 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3521
3522 if (n_back < 2)
3523 return;
3524
3525 if (ic[-2].f == instr(xor) && ic[-1].f == instr(andi)) {
3526 ic[-2].f = instr(xor_andi_sll);
3527 return;
3528 }
3529
3530 if (ic[-1].f == instr(andi)) {
3531 ic[-1].f = instr(andi_sll);
3532 return;
3533 }
3534 }
3535
3536
3537 /*
3538 * lui + ori
3539 */
3540 void COMBINE(ori)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3541 {
3542 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3543 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3544
3545 if (n_back < 1)
3546 return;
3547
3548 if (ic[-1].f == instr(set)) {
3549 ic[-1].f = instr(lui_ori);
3550 return;
3551 }
3552 }
3553
3554
3555 /*
3556 * addu + addu + addu
3557 */
3558 void COMBINE(addu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3559 {
3560 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3561 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3562
3563 if (n_back < 4)
3564 return;
3565
3566 /* Avoid "overlapping" instruction combinations: */
3567 if (ic[-4].f == instr(multi_addu_3) ||
3568 ic[-3].f == instr(multi_addu_3))
3569 return;
3570
3571 if (ic[-2].f == instr(addu) && ic[-1].f == instr(addu)) {
3572 ic[-2].f = instr(multi_addu_3);
3573 return;
3574 }
3575 }
3576
3577
3578 /*
3579 * Combine:
3580 *
3581 * [Conditional] branch, followed by addiu.
3582 */
3583 void COMBINE(addiu)(struct cpu *cpu, struct mips_instr_call *ic, int low_addr)
3584 {
3585 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3586 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3587
3588 if (n_back < 2)
3589 return;
3590
3591 if (ic[-2].f == instr(addiu) &&
3592 ic[-1].f == instr(bne_samepage)) {
3593 ic[-2].f = instr(addiu_bne_samepage_addiu);
3594 return;
3595 }
3596
3597 if (ic[-1].f == instr(set)) {
3598 ic[-1].f = instr(lui_addiu);
3599 return;
3600 }
3601
3602 if (ic[-1].f == instr(b_samepage)) {
3603 ic[-1].f = instr(b_samepage_addiu);
3604 return;
3605 }
3606
3607 if (ic[-1].f == instr(beq_samepage)) {
3608 ic[-1].f = instr(beq_samepage_addiu);
3609 return;
3610 }
3611
3612 if (ic[-1].f == instr(bne_samepage)) {
3613 ic[-1].f = instr(bne_samepage_addiu);
3614 return;
3615 }
3616
3617 if (ic[-1].f == instr(jr_ra)) {
3618 ic[-1].f = instr(jr_ra_addiu);
3619 return;
3620 }
3621
3622 /* TODO: other branches that are followed by addiu should be here */
3623 }
3624
3625
3626 /*
3627 * Combine: [Conditional] branch, followed by daddiu.
3628 */
3629 void COMBINE(b_daddiu)(struct cpu *cpu, struct mips_instr_call *ic,
3630 int low_addr)
3631 {
3632 int n_back = (low_addr >> MIPS_INSTR_ALIGNMENT_SHIFT)
3633 & (MIPS_IC_ENTRIES_PER_PAGE - 1);
3634
3635 if (n_back < 1)
3636 return;
3637
3638 if (ic[-1].f == instr(b_samepage)) {
3639 ic[-1].f = instr(b_samepage_daddiu);
3640 }
3641
3642 /* TODO: other branches that are followed by daddiu should be here */
3643 }
3644
3645
3646 /*****************************************************************************/
3647
3648
3649 /*
3650 * mips_instr_to_be_translated():
3651 *
3652 * Translate an instruction word into a mips_instr_call. ic is filled in with
3653 * valid data for the translated instruction, or a "nothing" instruction if
3654 * there was a translation failure. The newly translated instruction is then
3655 * executed.
3656 */
3657 X(to_be_translated)
3658 {
3659 uint64_t addr, low_pc;
3660 uint32_t iword, imm;
3661 unsigned char *page;
3662 unsigned char ib[4];
3663 int main_opcode, rt, rs, rd, sa, s6, x64 = 0;
3664 int in_crosspage_delayslot = 0;
3665 void (*samepage_function)(struct cpu *, struct mips_instr_call *);
3666 int store, signedness, size;
3667
3668 /* Figure out the (virtual) address of the instruction: */
3669 low_pc = ((size_t)ic - (size_t)cpu->cd.mips.cur_ic_page)
3670 / sizeof(struct mips_instr_call);
3671
3672 /* Special case for branch with delayslot on the next page: */
3673 if (cpu->delay_slot == TO_BE_DELAYED && low_pc == 0) {
3674 /* fatal("[ delay-slot translation across page "
3675 "boundary ]\n"); */
3676 in_crosspage_delayslot = 1;
3677 }
3678
3679 addr = cpu->pc & ~((MIPS_IC_ENTRIES_PER_PAGE-1)
3680 << MIPS_INSTR_ALIGNMENT_SHIFT);
3681 addr += (low_pc << MIPS_INSTR_ALIGNMENT_SHIFT);
3682 cpu->pc = (MODE_int_t)addr;
3683 addr &= ~((1 << MIPS_INSTR_ALIGNMENT_SHIFT) - 1);
3684
3685 /* Read the instruction word from memory: */
3686 #ifdef MODE32
3687 page = cpu->cd.mips.host_load[(uint32_t)addr >> 12];
3688 #else
3689 {
3690 const uint32_t mask1 = (1 << DYNTRANS_L1N) - 1;
3691 const uint32_t mask2 = (1 << DYNTRANS_L2N) - 1;
3692 const uint32_t mask3 = (1 << DYNTRANS_L3N) - 1;
3693 uint32_t x1 = (addr >> (64-DYNTRANS_L1N)) & mask1;
3694 uint32_t x2 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N)) & mask2;
3695 uint32_t x3 = (addr >> (64-DYNTRANS_L1N-DYNTRANS_L2N-
3696 DYNTRANS_L3N)) & mask3;
3697 struct DYNTRANS_L2_64_TABLE *l2 = cpu->cd.mips.l1_64[x1];
3698 struct DYNTRANS_L3_64_TABLE *l3 = l2->l3[x2];
3699 page = l3->host_load[x3];
3700 }
3701 #endif
3702
3703 if (page != NULL) {
3704 /* fatal("TRANSLATION HIT!\n"); */
3705 memcpy(ib, page + (addr & 0xffc), sizeof(ib));
3706 } else {
3707 /* fatal("TRANSLATION MISS!\n"); */
3708 if (!cpu->memory_rw(cpu, cpu->mem, addr, ib,
3709 sizeof(ib), MEM_READ, CACHE_INSTRUCTION)) {
3710 fatal("to_be_translated(): read failed: TODO\n");
3711 goto bad;
3712 }
3713 }
3714
3715 iword = *((uint32_t *)&ib[0]);
3716
3717 if (cpu->byte_order == EMUL_LITTLE_ENDIAN)
3718 iword = LE32_TO_HOST(iword);
3719 else
3720 iword = BE32_TO_HOST(iword);
3721
3722
3723 #define DYNTRANS_TO_BE_TRANSLATED_HEAD
3724 #include "cpu_dyntrans.c"
3725 #undef DYNTRANS_TO_BE_TRANSLATED_HEAD
3726
3727
3728 /*
3729 * Translate the instruction:
3730 *
3731 * NOTE: _NEVER_ allow writes to the zero register; all instructions
3732 * that use the zero register as their destination should be treated
3733 * as NOPs, except those that access memory (they should use the
3734 * scratch register instead).
3735 */
3736
3737 main_opcode = iword >> 26;
3738 rs = (iword >> 21) & 31;
3739 rt = (iword >> 16) & 31;
3740 rd = (iword >> 11) & 31;
3741 sa = (iword >> 6) & 31;
3742 imm = (int16_t)iword;
3743 s6 = iword & 63;
3744
3745 switch (main_opcode) {
3746
3747 case HI6_SPECIAL:
3748 switch (s6) {
3749
3750 case SPECIAL_SLL:
3751 case SPECIAL_SLLV:
3752 case SPECIAL_SRL:
3753 case SPECIAL_SRLV:
3754 case SPECIAL_SRA:
3755 case SPECIAL_SRAV:
3756 case SPECIAL_DSRL:
3757 case SPECIAL_DSRLV:
3758 case SPECIAL_DSRL32:
3759 case SPECIAL_DSLL:
3760 case SPECIAL_DSLLV:
3761 case SPECIAL_DSLL32:
3762 case SPECIAL_DSRA:
3763 case SPECIAL_DSRAV:
3764 case SPECIAL_DSRA32:
3765 switch (s6) {
3766 case SPECIAL_SLL: ic->f = instr(sll); break;
3767 case SPECIAL_SLLV: ic->f = instr(sllv); sa = -1; break;
3768 case SPECIAL_SRL: ic->f = instr(srl); break;
3769 case SPECIAL_SRLV: ic->f = instr(srlv); sa = -1; break;
3770 case SPECIAL_SRA: ic->f = instr(sra); break;
3771 case SPECIAL_SRAV: ic->f = instr(srav); sa = -1; break;
3772 case SPECIAL_DSRL: ic->f = instr(dsrl); x64=1; break;
3773 case SPECIAL_DSRLV:ic->f = instr(dsrlv);
3774 x64 = 1; sa = -1; break;
3775 case SPECIAL_DSRL32:ic->f= instr(dsrl); x64=1;
3776 sa += 32; break;
3777 case SPECIAL_DSLL: ic->f = instr(dsll); x64=1; break;
3778 case SPECIAL_DSLLV:ic->f = instr(dsllv);
3779 x64 = 1; sa = -1; break;
3780 case SPECIAL_DSLL32:ic->f= instr(dsll); x64=1;
3781 sa += 32; break;
3782 case SPECIAL_DSRA: ic->f = instr(dsra); x64=1; break;
3783 case SPECIAL_DSRAV:ic->f = instr(dsrav);
3784 x64 = 1; sa = -1; break;
3785 case SPECIAL_DSRA32:ic->f = instr(dsra); x64=1;
3786 sa += 32; break;
3787 }
3788 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
3789 if (sa >= 0)
3790 ic->arg[1] = sa;
3791 else
3792 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
3793 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3794 if (rd == MIPS_GPR_ZERO)
3795 ic->f = instr(nop);
3796 if (ic->f == instr(sll))
3797 cpu->cd.mips.combination_check = COMBINE(sll);
3798 break;
3799
3800 case SPECIAL_ADD:
3801 case SPECIAL_ADDU:
3802 case SPECIAL_SUB:
3803 case SPECIAL_SUBU:
3804 case SPECIAL_DADD:
3805 case SPECIAL_DADDU:
3806 case SPECIAL_DSUB:
3807 case SPECIAL_DSUBU:
3808 case SPECIAL_SLT:
3809 case SPECIAL_SLTU:
3810 case SPECIAL_AND:
3811 case SPECIAL_OR:
3812 case SPECIAL_XOR:
3813 case SPECIAL_NOR:
3814 case SPECIAL_MOVN:
3815 case SPECIAL_MOVZ:
3816 case SPECIAL_MFHI:
3817 case SPECIAL_MFLO:
3818 case SPECIAL_MTHI:
3819 case SPECIAL_MTLO:
3820 case SPECIAL_DIV:
3821 case SPECIAL_DIVU:
3822 case SPECIAL_DDIV:
3823 case SPECIAL_DDIVU:
3824 case SPECIAL_MULT:
3825 case SPECIAL_MULTU:
3826 case SPECIAL_DMULT:
3827 case SPECIAL_DMULTU:
3828 case SPECIAL_TGE:
3829 case SPECIAL_TGEU:
3830 case SPECIAL_TLT:
3831 case SPECIAL_TLTU:
3832 case SPECIAL_TEQ:
3833 case SPECIAL_TNE:
3834 switch (s6) {
3835 case SPECIAL_ADD: ic->f = instr(add); break;
3836 case SPECIAL_ADDU: ic->f = instr(addu); break;
3837 case SPECIAL_SUB: ic->f = instr(sub); break;
3838 case SPECIAL_SUBU: ic->f = instr(subu); break;
3839 case SPECIAL_DADD: ic->f = instr(dadd); x64=1; break;
3840 case SPECIAL_DADDU: ic->f = instr(daddu); x64=1; break;
3841 case SPECIAL_DSUB: ic->f = instr(dsub); x64=1; break;
3842 case SPECIAL_DSUBU: ic->f = instr(dsubu); x64=1; break;
3843 case SPECIAL_SLT: ic->f = instr(slt); break;
3844 case SPECIAL_SLTU: ic->f = instr(sltu); break;
3845 case SPECIAL_AND: ic->f = instr(and); break;
3846 case SPECIAL_OR: ic->f = instr(or); break;
3847 case SPECIAL_XOR: ic->f = instr(xor); break;
3848 case SPECIAL_NOR: ic->f = instr(nor); break;
3849 case SPECIAL_MFHI: ic->f = instr(mov); break;
3850 case SPECIAL_MFLO: ic->f = instr(mov); break;
3851 case SPECIAL_MTHI: ic->f = instr(mov); break;
3852 case SPECIAL_MTLO: ic->f = instr(mov); break;
3853 case SPECIAL_DIV: ic->f = instr(div); break;
3854 case SPECIAL_DIVU: ic->f = instr(divu); break;
3855 case SPECIAL_DDIV: ic->f = instr(ddiv); x64=1; break;
3856 case SPECIAL_DDIVU: ic->f = instr(ddivu); x64=1; break;
3857 case SPECIAL_MULT : ic->f = instr(mult); break;
3858 case SPECIAL_MULTU: ic->f = instr(multu); break;
3859 case SPECIAL_DMULT: ic->f = instr(dmult); x64=1; break;
3860 case SPECIAL_DMULTU:ic->f = instr(dmultu); x64=1; break;
3861 case SPECIAL_TGE: ic->f = instr(tge); break;
3862 case SPECIAL_TGEU: ic->f = instr(tgeu); break;
3863 case SPECIAL_TLT: ic->f = instr(tlt); break;
3864 case SPECIAL_TLTU: ic->f = instr(tltu); break;
3865 case SPECIAL_TEQ: ic->f = instr(teq); break;
3866 case SPECIAL_TNE: ic->f = instr(tne); break;
3867 case SPECIAL_MOVN: ic->f = instr(movn); break;
3868 case SPECIAL_MOVZ: ic->f = instr(movz); break;
3869 }
3870 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3871 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
3872 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
3873 switch (s6) {
3874 case SPECIAL_MFHI:
3875 ic->arg[0] = (size_t)&cpu->cd.mips.hi;
3876 break;
3877 case SPECIAL_MFLO:
3878 ic->arg[0] = (size_t)&cpu->cd.mips.lo;
3879 break;
3880 case SPECIAL_MTHI:
3881 ic->arg[2] = (size_t)&cpu->cd.mips.hi;
3882 break;
3883 case SPECIAL_MTLO:
3884 ic->arg[2] = (size_t)&cpu->cd.mips.lo;
3885 break;
3886 }
3887 /* Special cases for rd: */
3888 switch (s6) {
3889 case SPECIAL_MTHI:
3890 case SPECIAL_MTLO:
3891 case SPECIAL_DIV:
3892 case SPECIAL_DIVU:
3893 case SPECIAL_DDIV:
3894 case SPECIAL_DDIVU:
3895 case SPECIAL_MULT:
3896 case SPECIAL_MULTU:
3897 case SPECIAL_DMULT:
3898 case SPECIAL_DMULTU:
3899 case SPECIAL_TGE:
3900 case SPECIAL_TGEU:
3901 case SPECIAL_TLT:
3902 case SPECIAL_TLTU:
3903 case SPECIAL_TEQ:
3904 case SPECIAL_TNE:
3905 if (s6 == SPECIAL_MULT && rd != MIPS_GPR_ZERO) {
3906 if (cpu->cd.mips.cpu_type.rev ==
3907 MIPS_R5900) {
3908 ic->f = instr(mult_r5900);
3909 break;
3910 }
3911 break;
3912 }
3913 if (s6 == SPECIAL_MULTU && rd!=MIPS_GPR_ZERO) {
3914 if (cpu->cd.mips.cpu_type.rev ==
3915 MIPS_R5900) {
3916 ic->f = instr(multu_r5900);
3917 break;
3918 }
3919 }
3920 if (rd != MIPS_GPR_ZERO) {
3921 fatal("TODO: rd NON-zero\n");
3922 goto bad;
3923 }
3924 /* These instructions don't use rd. */
3925 break;
3926 default:if (rd == MIPS_GPR_ZERO)
3927 ic->f = instr(nop);
3928 }
3929
3930 if (ic->f == instr(addu))
3931 cpu->cd.mips.combination_check = COMBINE(addu);
3932 break;
3933
3934 case SPECIAL_JR:
3935 case SPECIAL_JALR:
3936 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
3937 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
3938 if (s6 == SPECIAL_JALR && rd == MIPS_GPR_ZERO)
3939 s6 = SPECIAL_JR;
3940 ic->arg[2] = (addr & 0xffc) + 8;
3941 switch (s6) {
3942 case SPECIAL_JR:
3943 if (rs == MIPS_GPR_RA) {
3944 if (cpu->machine->show_trace_tree)
3945 ic->f = instr(jr_ra_trace);
3946 else
3947 ic->f = instr(jr_ra);
3948 } else {
3949 ic->f = instr(jr);
3950 }
3951 break;
3952 case SPECIAL_JALR:
3953 if (cpu->machine->show_trace_tree)
3954 ic->f = instr(jalr_trace);
3955 else
3956 ic->f = instr(jalr);
3957 break;
3958 }
3959 if (cpu->delay_slot) {
3960 fatal("TODO: branch in delay slot? (1)\n");
3961 goto bad;
3962 }
3963 break;
3964
3965 case SPECIAL_SYSCALL:
3966 if (((iword >> 6) & 0xfffff) == 0x30378) {
3967 /* "Magic trap" for PROM emulation: */
3968 ic->f = instr(promemul);
3969 } else {
3970 ic->f = instr(syscall);
3971 }
3972 break;
3973
3974 case SPECIAL_BREAK:
3975 if (((iword >> 6) & 0xfffff) == 0x30378) {
3976 /* "Magic trap" for REBOOT: */
3977 ic->f = instr(reboot);
3978 } else {
3979 ic->f = instr(break);
3980 }
3981 break;
3982
3983 case SPECIAL_SYNC:
3984 ic->f = instr(nop);
3985 break;
3986
3987 default:goto bad;
3988 }
3989 break;
3990
3991 case HI6_BEQ:
3992 case HI6_BNE:
3993 case HI6_BEQL:
3994 case HI6_BNEL:
3995 case HI6_BLEZ:
3996 case HI6_BLEZL:
3997 case HI6_BGTZ:
3998 case HI6_BGTZL:
3999 samepage_function = NULL; /* get rid of a compiler warning */
4000 switch (main_opcode) {
4001 case HI6_BEQ:
4002 ic->f = instr(beq);
4003 samepage_function = instr(beq_samepage);
4004 /* Special case: comparing a register with itself: */
4005 if (rs == rt) {
4006 ic->f = instr(b);
4007 samepage_function = instr(b_samepage);
4008 }
4009 break;
4010 case HI6_BNE:
4011 ic->f = instr(bne);
4012 samepage_function = instr(bne_samepage);
4013 break;
4014 case HI6_BEQL:
4015 ic->f = instr(beql);
4016 samepage_function = instr(beql_samepage);
4017 /* Special case: comparing a register with itself: */
4018 if (rs == rt) {
4019 ic->f = instr(b);
4020 samepage_function = instr(b_samepage);
4021 }
4022 break;
4023 case HI6_BNEL:
4024 ic->f = instr(bnel);
4025 samepage_function = instr(bnel_samepage);
4026 break;
4027 case HI6_BLEZ:
4028 ic->f = instr(blez);
4029 samepage_function = instr(blez_samepage);
4030 break;
4031 case HI6_BLEZL:
4032 ic->f = instr(blezl);
4033 samepage_function = instr(blezl_samepage);
4034 break;
4035 case HI6_BGTZ:
4036 ic->f = instr(bgtz);
4037 samepage_function = instr(bgtz_samepage);
4038 break;
4039 case HI6_BGTZL:
4040 ic->f = instr(bgtzl);
4041 samepage_function = instr(bgtzl_samepage);
4042 break;
4043 }
4044 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4045 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4046 ic->arg[2] = (int32_t) ( (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
4047 + (addr & 0xffc) + 4 );
4048 /* Is the offset from the start of the current page still
4049 within the same page? Then use the samepage_function: */
4050 if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE - 1)
4051 << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc) < 0xffc) {
4052 ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page +
4053 ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
4054 & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
4055 ic->f = samepage_function;
4056 }
4057 if (cpu->delay_slot) {
4058 fatal("TODO: branch in delay slot? (2)\n");
4059 goto bad;
4060 }
4061 break;
4062
4063 case HI6_ADDI:
4064 case HI6_ADDIU:
4065 case HI6_SLTI:
4066 case HI6_SLTIU:
4067 case HI6_DADDI:
4068 case HI6_DADDIU:
4069 case HI6_ANDI:
4070 case HI6_ORI:
4071 case HI6_XORI:
4072 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4073 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4074 if (main_opcode == HI6_ADDI ||
4075 main_opcode == HI6_ADDIU ||
4076 main_opcode == HI6_SLTI ||
4077 main_opcode == HI6_SLTIU ||
4078 main_opcode == HI6_DADDI ||
4079 main_opcode == HI6_DADDIU)
4080 ic->arg[2] = (int16_t)iword;
4081 else
4082 ic->arg[2] = (uint16_t)iword;
4083
4084 switch (main_opcode) {
4085 case HI6_ADDI: ic->f = instr(addi); break;
4086 case HI6_ADDIU: ic->f = instr(addiu); break;
4087 case HI6_SLTI: ic->f = instr(slti); break;
4088 case HI6_SLTIU: ic->f = instr(sltiu); break;
4089 case HI6_DADDI: ic->f = instr(daddi); x64 = 1; break;
4090 case HI6_DADDIU: ic->f = instr(daddiu); x64 = 1; break;
4091 case HI6_ANDI: ic->f = instr(andi); break;
4092 case HI6_ORI: ic->f = instr(ori); break;
4093 case HI6_XORI: ic->f = instr(xori); break;
4094 }
4095
4096 if (ic->arg[2] == 0) {
4097 if ((cpu->is_32bit && ic->f == instr(addiu)) ||
4098 (!cpu->is_32bit && ic->f == instr(daddiu))) {
4099 ic->f = instr(mov);
4100 ic->arg[2] = ic->arg[1];
4101 }
4102 }
4103
4104 if (rt == MIPS_GPR_ZERO)
4105 ic->f = instr(nop);
4106
4107 if (ic->f == instr(ori))
4108 cpu->cd.mips.combination_check = COMBINE(ori);
4109 if (ic->f == instr(addiu))
4110 cpu->cd.mips.combination_check = COMBINE(addiu);
4111 if (ic->f == instr(daddiu))
4112 cpu->cd.mips.combination_check = COMBINE(b_daddiu);
4113 break;
4114
4115 case HI6_LUI:
4116 ic->f = instr(set);
4117 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4118 ic->arg[1] = (int32_t) (imm << 16);
4119 /* NOTE: Don't use arg[2] here. It can be used with
4120 instruction combinations, to do lui + addiu, etc. */
4121 if (rt == MIPS_GPR_ZERO)
4122 ic->f = instr(nop);
4123 break;
4124
4125 case HI6_J:
4126 case HI6_JAL:
4127 switch (main_opcode) {
4128 case HI6_J:
4129 ic->f = instr(j);
4130 break;
4131 case HI6_JAL:
4132 if (cpu->machine->show_trace_tree)
4133 ic->f = instr(jal_trace);
4134 else
4135 ic->f = instr(jal);
4136 break;
4137 }
4138 ic->arg[0] = (iword & 0x03ffffff) << 2;
4139 ic->arg[1] = (addr & 0xffc) + 8;
4140 if (cpu->delay_slot) {
4141 fatal("TODO: branch in delay slot (=%i)? (3); addr=%016"
4142 PRIx64" iword=%08"PRIx32"\n", cpu->delay_slot,
4143 (uint64_t)addr, iword);
4144 goto bad;
4145 }
4146 break;
4147
4148 case HI6_COP0:
4149 /* TODO: Is checking bit 25 enough, or perhaps all bits
4150 25..21 must be checked? */
4151 if ((iword >> 25) & 1) {
4152 ic->arg[2] = addr & 0xffc;
4153 switch (iword & 0xff) {
4154 case COP0_TLBR:
4155 ic->f = instr(tlbr);
4156 break;
4157 case COP0_TLBWI:
4158 case COP0_TLBWR:
4159 ic->f = instr(tlbw);
4160 ic->arg[0] = (iword & 0xff) == COP0_TLBWR;
4161 break;
4162 case COP0_TLBP:
4163 ic->f = instr(tlbp);
4164 break;
4165 case COP0_RFE:
4166 ic->f = instr(rfe);
4167 break;
4168 case COP0_ERET:
4169 ic->f = instr(eret);
4170 break;
4171 case COP0_DERET:
4172 ic->f = instr(deret);
4173 break;
4174 case COP0_WAIT:
4175 ic->f = instr(wait);
4176 if (cpu->cd.mips.cpu_type.rev != MIPS_RM5200 &&
4177 cpu->cd.mips.cpu_type.isa_level < 32) {
4178 static int warned = 0;
4179 ic->f = instr(reserved);
4180 if (!warned) {
4181 fatal("{ WARNING: Attempt to "
4182 "execute the WAIT instruct"
4183 "ion, but the emulated CPU "
4184 "is neither RM52xx, nor "
4185 "MIPS32/64! }\n");
4186 warned = 1;
4187 }
4188 }
4189 break;
4190 case COP0_STANDBY:
4191 case COP0_SUSPEND:
4192 case COP0_HIBERNATE:
4193 /* TODO */
4194 ic->f = instr(nop);
4195 break;
4196 case COP0_EI:
4197 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4198 ic->f = instr(ei_r5900);
4199 } else
4200 goto bad;
4201 break;
4202 case COP0_DI:
4203 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4204 ic->f = instr(di_r5900);
4205 } else
4206 goto bad;
4207 break;
4208 default:fatal("UNIMPLEMENTED cop0 (func 0x%02x)\n",
4209 iword & 0xff);
4210 goto bad;
4211 }
4212 break;
4213 }
4214
4215 /* rs contains the coprocessor opcode! */
4216 switch (rs) {
4217 case COPz_CFCz:
4218 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4219 ic->arg[1] = rd + ((iword & 7) << 5);
4220 ic->arg[2] = addr & 0xffc;
4221 ic->f = instr(cfc0);
4222 if (rt == MIPS_GPR_ZERO)
4223 ic->f = instr(nop);
4224 break;
4225 case COPz_MFCz:
4226 case COPz_DMFCz:
4227 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4228 ic->arg[1] = rd + ((iword & 7) << 5);
4229 ic->arg[2] = addr & 0xffc;
4230 ic->f = rs == COPz_MFCz? instr(mfc0) : instr(dmfc0);
4231 if (rt == MIPS_GPR_ZERO)
4232 ic->f = instr(nop);
4233 break;
4234 case COPz_MTCz:
4235 case COPz_DMTCz:
4236 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4237 ic->arg[1] = rd + ((iword & 7) << 5);
4238 ic->arg[2] = addr & 0xffc;
4239 ic->f = rs == COPz_MTCz? instr(mtc0) : instr(dmtc0);
4240
4241 if (cpu->cd.mips.cpu_type.exc_model == EXC3K &&
4242 rs == COPz_MTCz && rd == COP0_STATUS)
4243 cpu->cd.mips.combination_check =
4244 COMBINE(netbsd_r3k_cache_inv);
4245
4246 break;
4247 case 8: if (iword == 0x4100ffff) {
4248 /* R2020 DECstation write-loop thingy. */
4249 ic->f = instr(nop);
4250 } else {
4251 fatal("Unimplemented blah blah zzzz...\n");
4252 goto bad;
4253 }
4254 break;
4255
4256 default:fatal("UNIMPLEMENTED cop0 (rs = %i)\n", rs);
4257 goto bad;
4258 }
4259 break;
4260
4261 case HI6_COP1:
4262 /* Always cause a coprocessor unusable exception if
4263 there is no floating point coprocessor: */
4264 if (cpu->cd.mips.cpu_type.flags & NOFPU ||
4265 cpu->cd.mips.coproc[1] == NULL) {
4266 ic->f = instr(cpu);
4267 ic->arg[0] = 1;
4268 break;
4269 }
4270
4271 /* Bits 25..21 are floating point main opcode: */
4272 switch (rs) {
4273
4274 case COPz_BCzc:
4275 /* Conditional branch: */
4276 /* TODO: Reimplement this in a faster way. */
4277 ic->f = instr(cop1_bc);
4278 ic->arg[0] = (iword >> 18) & 7; /* cc */
4279 ic->arg[1] = (iword >> 16) & 3; /* nd, tf bits */
4280 ic->arg[2] = (int32_t) ((imm <<
4281 MIPS_INSTR_ALIGNMENT_SHIFT) + (addr & 0xffc) + 4);
4282 if (cpu->delay_slot) {
4283 fatal("TODO: branch in delay slot? (4)\n");
4284 goto bad;
4285 }
4286 if (cpu->cd.mips.cpu_type.isa_level <= 3 &&
4287 ic->arg[0] != 0) {
4288 fatal("Attempt to execute a non-cc-0 BC*"
4289 " instruction on an isa level %i cpu. "
4290 "TODO: How should this be handled?\n",
4291 cpu->cd.mips.cpu_type.isa_level);
4292 goto bad;
4293 }
4294
4295 break;
4296
4297 case COPz_DMFCz:
4298 case COPz_DMTCz:
4299 x64 = 1;
4300 /* FALL-THROUGH */
4301 case COP1_FMT_S:
4302 case COP1_FMT_D:
4303 case COP1_FMT_W:
4304 case COP1_FMT_L:
4305 case COP1_FMT_PS:
4306 case COPz_CFCz:
4307 case COPz_CTCz:
4308 case COPz_MFCz:
4309 case COPz_MTCz:
4310 /* Fallback to slow pre-dyntrans code, for now. */
4311 /* TODO: Fix/optimize/rewrite. */
4312 ic->f = instr(cop1_slow);
4313 ic->arg[0] = (uint32_t)iword & ((1 << 26) - 1);
4314 break;
4315
4316 default:fatal("COP1 floating point opcode = 0x%02x\n", rs);
4317 goto bad;
4318 }
4319 break;
4320
4321 case HI6_COP2:
4322 /* Always cause a coprocessor unusable exception if
4323 there is no coprocessor 2: */
4324 if (cpu->cd.mips.coproc[2] == NULL) {
4325 ic->f = instr(cpu);
4326 ic->arg[0] = 2;
4327 break;
4328 }
4329 fatal("COP2 functionality not yet implemented\n");
4330 goto bad;
4331 break;
4332
4333 case HI6_SPECIAL2:
4334 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4335 /* R5900, TX79/C790, have MMI instead of SPECIAL2: */
4336 int mmi_subopcode = (iword >> 6) & 0x1f;
4337
4338 switch (s6) {
4339
4340 case MMI_MADD:
4341 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4342 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4343 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4344 if (rd == MIPS_GPR_ZERO)
4345 ic->f = instr(madd);
4346 else
4347 ic->f = instr(madd_rd);
4348 break;
4349
4350 case MMI_MADDU:
4351 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4352 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4353 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4354 if (rd == MIPS_GPR_ZERO)
4355 ic->f = instr(maddu);
4356 else
4357 ic->f = instr(maddu_rd);
4358 break;
4359
4360 case MMI_MMI0:
4361 switch (mmi_subopcode) {
4362
4363 case MMI0_PEXTLW:
4364 ic->arg[0] = rs;
4365 ic->arg[1] = rt;
4366 ic->arg[2] = rd;
4367 if (rd == MIPS_GPR_ZERO)
4368 ic->f = instr(nop);
4369 else
4370 ic->f = instr(pextlw);
4371 break;
4372
4373 default:goto bad;
4374 }
4375 break;
4376
4377 case MMI_MMI3:
4378 switch (mmi_subopcode) {
4379
4380 case MMI3_POR:
4381 ic->arg[0] = rs;
4382 ic->arg[1] = rt;
4383 ic->arg[2] = rd;
4384 if (rd == MIPS_GPR_ZERO)
4385 ic->f = instr(nop);
4386 else
4387 ic->f = instr(por);
4388 break;
4389
4390 default:goto bad;
4391 }
4392 break;
4393
4394 default:goto bad;
4395 }
4396 break;
4397 }
4398
4399 /* TODO: is this correct? Or are there other non-MIPS32/64
4400 MIPS processors that have support for SPECIAL2 opcodes? */
4401 if (cpu->cd.mips.cpu_type.isa_level < 32) {
4402 ic->f = instr(reserved);
4403 break;
4404 }
4405
4406 /* SPECIAL2: */
4407 switch (s6) {
4408
4409 case SPECIAL2_MADD:
4410 case SPECIAL2_MADDU:
4411 case SPECIAL2_MSUB:
4412 case SPECIAL2_MSUBU:
4413 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4414 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4415 switch (s6) {
4416 case SPECIAL2_MADD: ic->f = instr(madd); break;
4417 case SPECIAL2_MADDU:ic->f = instr(maddu); break;
4418 case SPECIAL2_MSUB: ic->f = instr(msub); break;
4419 case SPECIAL2_MSUBU:ic->f = instr(msubu); break;
4420 }
4421 break;
4422
4423 case SPECIAL2_MUL:
4424 ic->f = instr(mul);
4425 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4426 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rt];
4427 ic->arg[2] = (size_t)&cpu->cd.mips.gpr[rd];
4428 if (rd == MIPS_GPR_ZERO)
4429 ic->f = instr(nop);
4430 break;
4431
4432 case SPECIAL2_CLZ:
4433 case SPECIAL2_CLO:
4434 case SPECIAL2_DCLZ:
4435 case SPECIAL2_DCLO:
4436 switch (s6) {
4437 case SPECIAL2_CLZ: ic->f = instr(clz); break;
4438 case SPECIAL2_CLO: ic->f = instr(clo); break;
4439 case SPECIAL2_DCLZ: ic->f = instr(dclz); break;
4440 case SPECIAL2_DCLO: ic->f = instr(dclo); break;
4441 }
4442 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4443 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rd];
4444 if (rd == MIPS_GPR_ZERO)
4445 ic->f = instr(nop);
4446 break;
4447
4448 default:goto bad;
4449 }
4450 break;
4451
4452 case HI6_REGIMM:
4453 switch (rt) {
4454 case REGIMM_BGEZ:
4455 case REGIMM_BGEZL:
4456 case REGIMM_BLTZ:
4457 case REGIMM_BLTZL:
4458 case REGIMM_BGEZAL:
4459 case REGIMM_BGEZALL:
4460 case REGIMM_BLTZAL:
4461 case REGIMM_BLTZALL:
4462 samepage_function = NULL;
4463 switch (rt) {
4464 case REGIMM_BGEZ:
4465 ic->f = instr(bgez);
4466 samepage_function = instr(bgez_samepage);
4467 break;
4468 case REGIMM_BGEZL:
4469 ic->f = instr(bgezl);
4470 samepage_function = instr(bgezl_samepage);
4471 break;
4472 case REGIMM_BLTZ:
4473 ic->f = instr(bltz);
4474 samepage_function = instr(bltz_samepage);
4475 break;
4476 case REGIMM_BLTZL:
4477 ic->f = instr(bltzl);
4478 samepage_function = instr(bltzl_samepage);
4479 break;
4480 case REGIMM_BGEZAL:
4481 ic->f = instr(bgezal);
4482 samepage_function = instr(bgezal_samepage);
4483 break;
4484 case REGIMM_BGEZALL:
4485 ic->f = instr(bgezall);
4486 samepage_function = instr(bgezall_samepage);
4487 break;
4488 case REGIMM_BLTZAL:
4489 ic->f = instr(bltzal);
4490 samepage_function = instr(bltzal_samepage);
4491 break;
4492 case REGIMM_BLTZALL:
4493 ic->f = instr(bltzall);
4494 samepage_function = instr(bltzall_samepage);
4495 break;
4496 }
4497 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rs];
4498 ic->arg[2] = (imm << MIPS_INSTR_ALIGNMENT_SHIFT)
4499 + (addr & 0xffc) + 4;
4500 /* Is the offset from the start of the current page
4501 still within the same page? Then use the
4502 samepage_function: */
4503 if ((uint32_t)ic->arg[2] < ((MIPS_IC_ENTRIES_PER_PAGE-1)
4504 << MIPS_INSTR_ALIGNMENT_SHIFT) && (addr & 0xffc)
4505 < 0xffc) {
4506 ic->arg[2] = (size_t) (cpu->cd.mips.cur_ic_page+
4507 ((ic->arg[2] >> MIPS_INSTR_ALIGNMENT_SHIFT)
4508 & (MIPS_IC_ENTRIES_PER_PAGE - 1)));
4509 ic->f = samepage_function;
4510 }
4511 if (cpu->delay_slot) {
4512 fatal("TODO: branch in delay slot? (5)\n");
4513 goto bad;
4514 }
4515 break;
4516 default:fatal("UNIMPLEMENTED regimm rt=%i\n", rt);
4517 goto bad;
4518 }
4519 break;
4520
4521 case HI6_LB:
4522 case HI6_LBU:
4523 case HI6_SB:
4524 case HI6_LH:
4525 case HI6_LHU:
4526 case HI6_SH:
4527 case HI6_LW:
4528 case HI6_LWU:
4529 case HI6_SW:
4530 case HI6_LD:
4531 case HI6_SD:
4532 /* TODO: LWU should probably also be x64=1? */
4533 size = 2; signedness = 0; store = 0;
4534 switch (main_opcode) {
4535 case HI6_LB: size = 0; signedness = 1; break;
4536 case HI6_LBU: size = 0; break;
4537 case HI6_LH: size = 1; signedness = 1; break;
4538 case HI6_LHU: size = 1; break;
4539 case HI6_LW: signedness = 1; break;
4540 case HI6_LWU: break;
4541 case HI6_LD: size = 3; x64 = 1; break;
4542 case HI6_SB: store = 1; size = 0; break;
4543 case HI6_SH: store = 1; size = 1; break;
4544 case HI6_SW: store = 1; break;
4545 case HI6_SD: store = 1; size = 3; x64 = 1; break;
4546 }
4547
4548 ic->f =
4549 #ifdef MODE32
4550 mips32_loadstore
4551 #else
4552 mips_loadstore
4553 #endif
4554 [ (cpu->byte_order == EMUL_LITTLE_ENDIAN? 0 : 16)
4555 + store * 8 + size * 2 + signedness];
4556 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4557 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4558 ic->arg[2] = (int32_t)imm;
4559
4560 /* Load into the dummy scratch register, if rt = zero */
4561 if (!store && rt == MIPS_GPR_ZERO)
4562 ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4563
4564 /* Check for multiple loads or stores in a row using the same
4565 base register: */
4566 #ifdef MODE32
4567 if (main_opcode == HI6_LW)
4568 cpu->cd.mips.combination_check = COMBINE(multi_lw);
4569 if (main_opcode == HI6_SW)
4570 cpu->cd.mips.combination_check = COMBINE(multi_sw);
4571 #endif
4572 break;
4573
4574 case HI6_LL:
4575 case HI6_LLD:
4576 case HI6_SC:
4577 case HI6_SCD:
4578 /* 32-bit load-linked/store-condition for ISA II and up: */
4579 /* (64-bit load-linked/store-condition for ISA III...) */
4580 if (cpu->cd.mips.cpu_type.isa_level < 2) {
4581 ic->f = instr(reserved);
4582 break;
4583 }
4584
4585 store = 0;
4586 switch (main_opcode) {
4587 case HI6_LL: ic->f = instr(ll); break;
4588 case HI6_LLD: ic->f = instr(lld); x64 = 1; break;
4589 case HI6_SC: ic->f = instr(sc); store = 1; break;
4590 case HI6_SCD: ic->f = instr(scd); store = 1; x64 = 1; break;
4591 }
4592 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4593 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4594 ic->arg[2] = (int32_t)imm;
4595 if (!store && rt == MIPS_GPR_ZERO) {
4596 fatal("HM... unusual load linked\n");
4597 goto bad;
4598 }
4599 break;
4600
4601 case HI6_LWL:
4602 case HI6_LWR:
4603 case HI6_LDL:
4604 case HI6_LDR:
4605 case HI6_SWL:
4606 case HI6_SWR:
4607 case HI6_SDL:
4608 case HI6_SDR:
4609 /* TODO: replace these with faster versions... */
4610 store = 0;
4611 switch (main_opcode) {
4612 case HI6_LWL: ic->f = instr(lwl); break;
4613 case HI6_LWR: ic->f = instr(lwr); break;
4614 case HI6_LDL: ic->f = instr(ldl); x64 = 1; break;
4615 case HI6_LDR: ic->f = instr(ldr); x64 = 1; break;
4616 case HI6_SWL: ic->f = instr(swl); store = 1; break;
4617 case HI6_SWR: ic->f = instr(swr); store = 1; break;
4618 case HI6_SDL: ic->f = instr(sdl); store = 1; x64 = 1; break;
4619 case HI6_SDR: ic->f = instr(sdr); store = 1; x64 = 1; break;
4620 }
4621 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4622 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4623 ic->arg[2] = (int32_t)imm;
4624
4625 /* Load into the dummy scratch register, if rt = zero */
4626 if (!store && rt == MIPS_GPR_ZERO)
4627 ic->arg[0] = (size_t)&cpu->cd.mips.scratch;
4628 break;
4629
4630 case HI6_LWC1:
4631 case HI6_SWC1:
4632 case HI6_LDC1:
4633 case HI6_SDC1:
4634 /* 64-bit floating-point load/store for ISA II and up... */
4635 if ((main_opcode == HI6_LDC1 || main_opcode == HI6_SDC1)
4636 && cpu->cd.mips.cpu_type.isa_level < 2) {
4637 ic->f = instr(reserved);
4638 break;
4639 }
4640
4641 ic->arg[0] = (size_t)&cpu->cd.mips.coproc[1]->reg[rt];
4642 ic->arg[1] = (size_t)&cpu->cd.mips.gpr[rs];
4643 ic->arg[2] = (int32_t)imm;
4644 switch (main_opcode) {
4645 case HI6_LWC1: ic->f = instr(lwc1); break;
4646 case HI6_LDC1: ic->f = instr(ldc1); break;
4647 case HI6_SWC1: ic->f = instr(swc1); break;
4648 case HI6_SDC1: ic->f = instr(sdc1); break;
4649 }
4650
4651 /* Cause a coprocessor unusable exception if
4652 there is no floating point coprocessor: */
4653 if (cpu->cd.mips.cpu_type.flags & NOFPU ||
4654 cpu->cd.mips.coproc[1] == NULL) {
4655 ic->f = instr(cpu);
4656 ic->arg[0] = 1;
4657 }
4658 break;
4659
4660 case HI6_LWC3:
4661 /* PREF (prefetch) on ISA IV and MIPS32/64: */
4662 if (cpu->cd.mips.cpu_type.isa_level >= 4) {
4663 /* Treat as nop for now: */
4664 ic->f = instr(nop);
4665 } else {
4666 fatal("TODO: lwc3 not implemented yet\n");
4667 goto bad;
4668 }
4669 break;
4670
4671 case HI6_LQ_MDMX:
4672 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4673 fatal("TODO: R5900 128-bit loads\n");
4674 goto bad;
4675 }
4676
4677 fatal("TODO: MDMX\n");
4678 goto bad;
4679 /* break */
4680
4681 case HI6_SQ_SPECIAL3:
4682 if (cpu->cd.mips.cpu_type.rev == MIPS_R5900) {
4683 fatal("TODO: R5900 128-bit stores\n");
4684 goto bad;
4685 }
4686
4687 if (cpu->cd.mips.cpu_type.isa_level < 32 ||
4688 cpu->cd.mips.cpu_type.isa_revision < 2) {
4689 static int warning = 0;
4690 if (!warning) {
4691 fatal("[ WARNING! SPECIAL3 opcode used, but"
4692 " the %s processor does not implement "
4693 "such instructions. Only printing this "
4694 "warning once. ]\n",
4695 cpu->cd.mips.cpu_type.name);
4696 warning = 1;
4697 }
4698 ic->f = instr(reserved);
4699 break;
4700 }
4701
4702 switch (s6) {
4703
4704 case SPECIAL3_RDHWR:
4705 ic->arg[0] = (size_t)&cpu->cd.mips.gpr[rt];
4706
4707 switch (rd) {
4708
4709 case 0: ic->f = instr(rdhwr_cpunum);
4710 if (rt == MIPS_GPR_ZERO)
4711 ic->f = instr(nop);
4712 break;
4713
4714 default:fatal("unimplemented rdhwr register rd=%i\n",
4715 rd);
4716 goto bad;
4717 }
4718 break;
4719
4720 default:goto bad;
4721 }
4722 break;
4723
4724 case HI6_CACHE:
4725 /* TODO: rt and op etc... */
4726 ic->f = instr(cache);
4727 break;
4728
4729 default:goto bad;
4730 }
4731
4732 #ifdef MODE32
4733 if (x64) {
4734 static int has_warned = 0;
4735 if (!has_warned)
4736 fatal("[ WARNING/NOTE: attempt to execute a 64-bit"
4737 " instruction on an emulated 32-bit processor; "
4738 "pc=0x%08"PRIx32" ]\n", (uint32_t)cpu->pc);
4739 has_warned = 1;
4740 ic->f = instr(reserved);
4741 }
4742 #endif
4743
4744 if (ic->f == instr(nop) && cpu->cd.mips.combination_check == NULL)
4745 cpu->cd.mips.combination_check = COMBINE(nop);
4746
4747
4748 #define DYNTRANS_TO_BE_TRANSLATED_TAIL
4749 #include "cpu_dyntrans.c"
4750 #undef DYNTRANS_TO_BE_TRANSLATED_TAIL
4751 }
4752

  ViewVC Help
Powered by ViewVC 1.1.26