cpu_mips_instr.cc Source File

Back to the index.

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

Generated on Fri Dec 7 2018 19:52:23 for GXemul by doxygen 1.8.13