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

Contents of /upstream/0.4.5/src/cpus/cpu_mips_instr.c

Parent Directory Parent Directory | Revision Log Revision Log


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

  ViewVC Help
Powered by ViewVC 1.1.26