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