PS2SDK
PS2 Homebrew Libraries
mipsdis.c
1 /*
2 # _____ ___ ____ ___ ____
3 # ____| | ____| | | |____|
4 # | ___| |____ ___| ____| | \ PS2DEV Open Source Project.
5 #-----------------------------------------------------------------------
6 # Copyright ps2dev - http://www.ps2dev.org
7 # Licenced under Academic Free License version 2.0
8 # Review ps2sdk README & LICENSE files for further details.
9 */
10 
11 #include "srxfixup_internal.h"
12 #include <stdint.h>
13 #include <stdio.h>
14 #include <stdlib.h>
15 #include <string.h>
16 
17 static void getrs(unsigned int data, Operand *opr);
18 static void getrt(unsigned int data, Operand *opr);
19 static void getrd(unsigned int data, Operand *opr);
20 static void getc0rd_iop(unsigned int data, Operand *opr);
21 static void getc0rd_ee(unsigned int data, Operand *opr);
22 static void getczrd(unsigned int data, Operand *opr);
23 static void getshamt(unsigned int data, Operand *opr);
24 static void getfs(unsigned int data, Operand *opr);
25 static void getft(unsigned int data, Operand *opr);
26 static void getfd(unsigned int data, Operand *opr);
27 static void getczfs(unsigned int data, Operand *opr);
28 static void getbroff(unsigned int addr, unsigned int data, Operand *opr);
29 static void Rs(Disasm_result *result);
30 static void Rd(Disasm_result *result);
31 static void Rdrs(Disasm_result *result);
32 static void Rsrt(Disasm_result *result);
33 static void Rtc0rd_iop(Disasm_result *result);
34 static void Rtc0rd_ee(Disasm_result *result);
35 static void Rtczrd(Disasm_result *result);
36 static void Rdrsrt(Disasm_result *result);
37 static void Rdrtrs(Disasm_result *result);
38 static void Rdrtshamt(Disasm_result *result);
39 static void Rsseimm(Disasm_result *result);
40 static void Rtrsseimm(Disasm_result *result);
41 static void Rtrsimm(Disasm_result *result);
42 #if 0
43 static void Rdimm(Disasm_result *result);
44 static void Rsimm(Disasm_result *result);
45 #endif
46 static void Rtimm(Disasm_result *result);
47 static void Rsrtbroff(Disasm_result *result);
48 static void Rsbroff(Disasm_result *result);
49 static void Rtoffbase(Disasm_result *result);
50 static void Fdfs(Disasm_result *result);
51 static void Fsft(Disasm_result *result);
52 static void Fdfsft(Disasm_result *result);
53 static void Rtczfs(Disasm_result *result);
54 static void Code20(Disasm_result *result);
55 static void Jtarget(Disasm_result *result);
56 static void Cofun(Disasm_result *result);
57 static void Bcft(Disasm_result *result);
58 
59 // clang-format off
60 static int regnmsw[5] = { 1, 1, 0, 1, 0 };
61 static const char * const REGNAME[2][32] =
62 {
63  {
64  "$0",
65  "$at",
66  "$2",
67  "$3",
68  "$4",
69  "$5",
70  "$6",
71  "$7",
72  "$8",
73  "$9",
74  "$10",
75  "$11",
76  "$12",
77  "$13",
78  "$14",
79  "$15",
80  "$16",
81  "$17",
82  "$18",
83  "$19",
84  "$20",
85  "$21",
86  "$22",
87  "$23",
88  "$24",
89  "$25",
90  "$26",
91  "$27",
92  "$gp",
93  "$sp",
94  "$30",
95  "$31"
96  },
97  {
98  "zero",
99  "at",
100  "v0",
101  "v1",
102  "a0",
103  "a1",
104  "a2",
105  "a3",
106  "t0",
107  "t1",
108  "t2",
109  "t3",
110  "t4",
111  "t5",
112  "t6",
113  "t7",
114  "s0",
115  "s1",
116  "s2",
117  "s3",
118  "s4",
119  "s5",
120  "s6",
121  "s7",
122  "t8",
123  "t9",
124  "k0",
125  "k1",
126  "gp",
127  "sp",
128  "fp",
129  "ra"
130  }
131 };
132 static const char * const REGC0_iop[2][32] =
133 {
134  {
135  "$0",
136  "$1",
137  "$2",
138  "$3",
139  "$4",
140  "$5",
141  "$6",
142  "$7",
143  "$8",
144  "$9",
145  "$10",
146  "$11",
147  "$12",
148  "$13",
149  "$14",
150  "$15",
151  "$16",
152  "$17",
153  "$18",
154  "$19",
155  "$20",
156  "$21",
157  "$22",
158  "$23",
159  "$24",
160  "$25",
161  "$26",
162  "$27",
163  "$28",
164  "$29",
165  "$30",
166  "$31"
167  },
168  {
169  "$0",
170  "$1",
171  "$2",
172  "$bpc",
173  "$4",
174  "$bda",
175  "$tar",
176  "$dcic",
177  "$bada",
178  "$bdam",
179  "$10",
180  "$bpcm",
181  "$sr",
182  "$cause",
183  "$epc",
184  "$prid",
185  "$16",
186  "$17",
187  "$18",
188  "$19",
189  "$20",
190  "$21",
191  "$22",
192  "$23",
193  "$24",
194  "$25",
195  "$26",
196  "$27",
197  "$28",
198  "$29",
199  "$30",
200  "$31"
201  }
202 };
203 static const char * const REGC0_ee[2][32] =
204 {
205  {
206  "$0",
207  "$1",
208  "$2",
209  "$3",
210  "$4",
211  "$5",
212  "$6",
213  "$7",
214  "$8",
215  "$9",
216  "$10",
217  "$11",
218  "$12",
219  "$13",
220  "$14",
221  "$15",
222  "$16",
223  "$17",
224  "$18",
225  "$19",
226  "$20",
227  "$21",
228  "$22",
229  "$23",
230  "$24",
231  "$25",
232  "$26",
233  "$27",
234  "$28",
235  "$29",
236  "$30",
237  "$31"
238  },
239  {
240  "$index",
241  "$random",
242  "$entrylo0",
243  "$entrylo1",
244  "$context",
245  "$pagemask",
246  "$wired",
247  "$7",
248  "$badvaddr",
249  "$count",
250  "$entryhi",
251  "$compare",
252  "$status",
253  "$cause",
254  "$epc",
255  "$prid",
256  "$config",
257  "$17",
258  "$18",
259  "$19",
260  "$20",
261  "$21",
262  "$22",
263  "$badpaddr",
264  "$hwbk",
265  "$pccr",
266  "$26",
267  "$27",
268  "$taglo",
269  "$taghi",
270  "$errorepc",
271  "$31"
272  }
273 };
274 static const char * const REGC1[2][32] =
275 {
276  {
277  "$f0",
278  "$f1",
279  "$f2",
280  "$f3",
281  "$f4",
282  "$f5",
283  "$f6",
284  "$f7",
285  "$f8",
286  "$f9",
287  "$f10",
288  "$f11",
289  "$f12",
290  "$f13",
291  "$f14",
292  "$f15",
293  "$f16",
294  "$f17",
295  "$f18",
296  "$f19",
297  "$f20",
298  "$f21",
299  "$f22",
300  "$f23",
301  "$f24",
302  "$f25",
303  "$f26",
304  "$f27",
305  "$f28",
306  "$f29",
307  "$f30",
308  "$f31"
309  },
310  {
311  "$fv0",
312  "$fv1",
313  "$ft0",
314  "$ft1",
315  "$ft2",
316  "$ft3",
317  "$ft4",
318  "$ft5",
319  "$ft6",
320  "$ft7",
321  "$ft8",
322  "$ft9",
323  "$fa0",
324  "$fa1",
325  "$fa2",
326  "$fa3",
327  "$fa4",
328  "$fa5",
329  "$fa6",
330  "$fa7",
331  "$fs0",
332  "$fs1",
333  "$fs2",
334  "$fs3",
335  "$fs4",
336  "$fs5",
337  "$fs6",
338  "$fs7",
339  "$fs8",
340  "$fs9",
341  "$fs10",
342  "$fs11"
343  }
344 };
345 // clang-format on
346 
347 typedef void (*Operand_func)(Disasm_result *result);
348 typedef struct opcode_table_entry_
349 {
350  const char *mnemonic;
351  const struct opcode_table_ *subtable;
352  Operand_func opfunc;
354 typedef struct opcode_table_
355 {
356  int bit_pos;
357  unsigned int bit_mask;
358  const Opcode_table_entry *entries;
359 } Opcode_table;
360 
361 static void getrs(unsigned int data, Operand *opr)
362 {
363  opr->tag = OprTag_reg;
364  opr->reg = (data >> 21) & 0x1F;
365 }
366 
367 static void getrt(unsigned int data, Operand *opr)
368 {
369  opr->tag = OprTag_reg;
370  opr->reg = (data >> 16) & 0x1F;
371 }
372 
373 static void getrd(unsigned int data, Operand *opr)
374 {
375  opr->tag = OprTag_reg;
376  opr->reg = (data >> 11) & 0x1F;
377 }
378 
379 static void getc0rd_iop(unsigned int data, Operand *opr)
380 {
381  opr->tag = OprTag_c0reg_iop;
382  opr->reg = (data >> 11) & 0x1F;
383 }
384 
385 static void getc0rd_ee(unsigned int data, Operand *opr)
386 {
387  opr->tag = OprTag_c0reg_ee;
388  opr->reg = (data >> 11) & 0x1F;
389 }
390 
391 static void getczrd(unsigned int data, Operand *opr)
392 {
393  opr->tag = OprTag_czreg;
394  opr->reg = (data >> 11) & 0x1F;
395 }
396 
397 static void getshamt(unsigned int data, Operand *opr)
398 {
399  opr->tag = OprTag_shamt;
400  opr->data = (data >> 6) & 0x1F;
401 }
402 
403 static void getfs(unsigned int data, Operand *opr)
404 {
405  opr->tag = OprTag_c1reg;
406  opr->reg = (data >> 11) & 0x1F;
407 }
408 
409 static void getft(unsigned int data, Operand *opr)
410 {
411  opr->tag = OprTag_c1reg;
412  opr->reg = (data >> 16) & 0x1F;
413 }
414 
415 static void getfd(unsigned int data, Operand *opr)
416 {
417  opr->tag = OprTag_c1reg;
418  opr->reg = (data >> 6) & 0x1F;
419 }
420 
421 static void getczfs(unsigned int data, Operand *opr)
422 {
423  opr->tag = OprTag_c1reg;
424  opr->reg = (data >> 11) & 0x1F;
425 }
426 
427 static void getbroff(unsigned int addr, unsigned int data, Operand *opr)
428 {
429  opr->tag = OprTag_jtarget;
430  if ( (data & 0x8000) != 0 )
431  {
432  opr->data = 4 * (uint16_t)data - 0x40000;
433  }
434  else
435  {
436  opr->data = 4 * (uint16_t)data;
437  }
438  opr->data += 4 + addr;
439 }
440 
441 static void Rs(Disasm_result *result)
442 {
443  getrs(result->data, result->operands);
444 }
445 
446 static void Rd(Disasm_result *result)
447 {
448  getrd(result->data, result->operands);
449 }
450 
451 static void Rdrs(Disasm_result *result)
452 {
453  getrd(result->data, result->operands);
454  getrs(result->data, &result->operands[1]);
455 }
456 
457 static void Rsrt(Disasm_result *result)
458 {
459  getrs(result->data, result->operands);
460  getrt(result->data, &result->operands[1]);
461 }
462 
463 static void Rtc0rd_iop(Disasm_result *result)
464 {
465  getrt(result->data, result->operands);
466  getc0rd_iop(result->data, &result->operands[1]);
467 }
468 
469 static void Rtc0rd_ee(Disasm_result *result)
470 {
471  getrt(result->data, result->operands);
472  getc0rd_ee(result->data, &result->operands[1]);
473 }
474 
475 static void Rtczrd(Disasm_result *result)
476 {
477  getrt(result->data, result->operands);
478  getczrd(result->data, &result->operands[1]);
479 }
480 
481 static void Rdrsrt(Disasm_result *result)
482 {
483  getrd(result->data, result->operands);
484  getrs(result->data, &result->operands[1]);
485  getrt(result->data, &result->operands[2]);
486 }
487 
488 static void Rdrtrs(Disasm_result *result)
489 {
490  getrd(result->data, result->operands);
491  getrt(result->data, &result->operands[1]);
492  getrs(result->data, &result->operands[2]);
493 }
494 
495 static void Rdrtshamt(Disasm_result *result)
496 {
497  getrd(result->data, result->operands);
498  getrt(result->data, &result->operands[1]);
499  getshamt(result->data, &result->operands[2]);
500 }
501 
502 static void Rsseimm(Disasm_result *result)
503 {
504  unsigned int imm;
505 
506  getrs(result->data, result->operands);
507  if ( (int16_t)(result->data & 0xFFFF) < 0 )
508  {
509  imm = (result->data & 0xFFFF) - 0x10000;
510  }
511  else
512  {
513  imm = (result->data & 0xFFFF);
514  }
515  result->operands[1].tag = OprTag_imm;
516  result->operands[1].data = imm;
517 }
518 
519 static void Rtrsseimm(Disasm_result *result)
520 {
521  unsigned int imm;
522 
523  getrt(result->data, result->operands);
524  getrs(result->data, &result->operands[1]);
525  if ( (int16_t)(result->data & 0xFFFF) < 0 )
526  {
527  imm = (result->data & 0xFFFF) - 0x10000;
528  }
529  else
530  {
531  imm = (result->data & 0xFFFF);
532  }
533  result->operands[2].tag = OprTag_imm;
534  result->operands[2].data = imm;
535 }
536 
537 static void Rtrsimm(Disasm_result *result)
538 {
539  getrt(result->data, result->operands);
540  getrs(result->data, &result->operands[1]);
541  result->operands[2].tag = OprTag_imm;
542  result->operands[2].data = (result->data & 0xFFFF);
543 }
544 
545 #if 0
546 static void Rdimm(Disasm_result *result)
547 {
548  getrd(result->data, result->operands);
549  result->operands[1].tag = OprTag_imm;
550  result->operands[1].data = (result->data & 0xFFFF);
551 }
552 
553 static void Rsimm(Disasm_result *result)
554 {
555  getrs(result->data, result->operands);
556  result->operands[1].tag = OprTag_imm;
557  result->operands[1].data = (result->data & 0xFFFF);
558 }
559 #endif
560 
561 static void Rtimm(Disasm_result *result)
562 {
563  getrt(result->data, result->operands);
564  result->operands[1].tag = OprTag_imm;
565  result->operands[1].data = (result->data & 0xFFFF);
566 }
567 
568 static void Rsrtbroff(Disasm_result *result)
569 {
570  getrs(result->data, result->operands);
571  getrt(result->data, &result->operands[1]);
572  getbroff(result->addr, result->data, &result->operands[2]);
573 }
574 
575 static void Rsbroff(Disasm_result *result)
576 {
577  getrs(result->data, result->operands);
578  getbroff(result->addr, result->data, &result->operands[1]);
579 }
580 
581 static void Rtoffbase(Disasm_result *result)
582 {
583  unsigned int off;
584 
585  if ( (int16_t)(result->data & 0xFFFF) < 0 )
586  {
587  off = (result->data & 0xFFFF) - 0x10000;
588  }
589  else
590  {
591  off = (result->data & 0xFFFF);
592  }
593  getrt(result->data, result->operands);
594  result->operands[1].tag = OprTag_regoffset;
595  result->operands[1].data = off;
596  result->operands[1].reg = (result->data >> 21) & 0x1F;
597 }
598 
599 static void Fdfs(Disasm_result *result)
600 {
601  getfd(result->data, result->operands);
602  getfs(result->data, &result->operands[1]);
603 }
604 
605 static void Fsft(Disasm_result *result)
606 {
607  getfs(result->data, result->operands);
608  getft(result->data, &result->operands[1]);
609 }
610 
611 static void Fdfsft(Disasm_result *result)
612 {
613  getfd(result->data, result->operands);
614  getfs(result->data, &result->operands[1]);
615  getft(result->data, &result->operands[2]);
616 }
617 
618 static void Rtczfs(Disasm_result *result)
619 {
620  getrt(result->data, result->operands);
621  getczfs(result->data, &result->operands[1]);
622 }
623 
624 static void Code20(Disasm_result *result)
625 {
626  result->operands[0].tag = OprTag_code20;
627  result->operands[0].data = (result->data >> 6) & 0xFFFFF;
628 }
629 
630 static void Jtarget(Disasm_result *result)
631 {
632  result->operands[0].tag = OprTag_jtarget;
633  result->operands[0].data = (4 * (result->data & 0x3FFFFFF)) | (result->addr & 0xF0000000);
634 }
635 
636 static void Cofun(Disasm_result *result)
637 {
638  result->operands[0].tag = OprTag_code25;
639  result->operands[0].data = result->data & 0x1FFFFFF;
640 }
641 
642 static void Bcft(Disasm_result *result)
643 {
644  result->mnemonic[0] = 'b';
645  result->mnemonic[1] = 'c';
646  result->mnemonic[2] = result->mnemonic[3];
647  if ( (result->data & 0x10000) != 0 )
648  {
649  result->mnemonic[3] = 't';
650  }
651  else
652  {
653  result->mnemonic[3] = 'f';
654  }
655  if ( (result->data & 0x20000) != 0 )
656  {
657  result->mnemonic[4] = 'l';
658  }
659  else
660  {
661  result->mnemonic[4] = '\x00';
662  }
663  result->mnemonic[5] = '\x00';
664  getbroff(result->addr, result->data, result->operands);
665 }
666 
667 // clang-format off
668 static const Opcode_table_entry iop_SPECIAL_entries[] =
669 {
670  { "sll", NULL, &Rdrtshamt },
671  { NULL, NULL, NULL },
672  { "srl", NULL, &Rdrtshamt },
673  { "sra", NULL, &Rdrtshamt },
674  { "sllv", NULL, &Rdrtrs },
675  { NULL, NULL, NULL },
676  { "srlv", NULL, &Rdrtrs },
677  { "srav", NULL, &Rdrtrs },
678  { "jr", NULL, &Rs },
679  { "jalr", NULL, &Rdrs },
680  { NULL, NULL, NULL },
681  { NULL, NULL, NULL },
682  { "syscall", NULL, &Code20 },
683  { "break", NULL, &Code20 },
684  { NULL, NULL, NULL },
685  { NULL, NULL, NULL },
686  { "mfhi", NULL, &Rd },
687  { "mthi", NULL, &Rs },
688  { "mflo", NULL, &Rd },
689  { "mtlo", NULL, &Rs },
690  { NULL, NULL, NULL },
691  { NULL, NULL, NULL },
692  { NULL, NULL, NULL },
693  { NULL, NULL, NULL },
694  { "mult", NULL, &Rsrt },
695  { "multu", NULL, &Rsrt },
696  { "div", NULL, &Rsrt },
697  { "divu", NULL, &Rsrt },
698  { NULL, NULL, NULL },
699  { NULL, NULL, NULL },
700  { NULL, NULL, NULL },
701  { NULL, NULL, NULL },
702  { "add", NULL, &Rdrsrt },
703  { "addu", NULL, &Rdrsrt },
704  { "sub", NULL, &Rdrsrt },
705  { "subu", NULL, &Rdrsrt },
706  { "and", NULL, &Rdrsrt },
707  { "or", NULL, &Rdrsrt },
708  { "xor", NULL, &Rdrsrt },
709  { "nor", NULL, &Rdrsrt },
710  { NULL, NULL, NULL },
711  { NULL, NULL, NULL },
712  { "slt", NULL, &Rdrsrt },
713  { "sltu", NULL, &Rdrsrt },
714  { NULL, NULL, NULL },
715  { NULL, NULL, NULL },
716  { NULL, NULL, NULL },
717  { NULL, NULL, NULL },
718  { NULL, NULL, NULL },
719  { NULL, NULL, NULL },
720  { NULL, NULL, NULL },
721  { NULL, NULL, NULL },
722  { NULL, NULL, NULL },
723  { NULL, NULL, NULL },
724  { NULL, NULL, NULL },
725  { NULL, NULL, NULL },
726  { NULL, NULL, NULL },
727  { NULL, NULL, NULL },
728  { NULL, NULL, NULL },
729  { NULL, NULL, NULL },
730  { NULL, NULL, NULL },
731  { NULL, NULL, NULL },
732  { NULL, NULL, NULL },
733  { NULL, NULL, NULL }
734 };
735 static const Opcode_table iop_SPECIAL = { 0, 63, iop_SPECIAL_entries };
736 static const Opcode_table_entry ee_SPECIAL_entries[] =
737 {
738  { "sll", NULL, &Rdrtshamt },
739  { NULL, NULL, NULL },
740  { "srl", NULL, &Rdrtshamt },
741  { "sra", NULL, &Rdrtshamt },
742  { "sllv", NULL, &Rdrtrs },
743  { NULL, NULL, NULL },
744  { "srlv", NULL, &Rdrtrs },
745  { "srav", NULL, &Rdrtrs },
746  { "jr", NULL, &Rs },
747  { "jalr", NULL, &Rdrs },
748  { "movz", NULL, &Rdrtrs },
749  { "movn", NULL, &Rdrtrs },
750  { "syscall", NULL, &Code20 },
751  { "break", NULL, &Code20 },
752  { NULL, NULL, NULL },
753  { "sync", NULL, NULL },
754  { "mfhi", NULL, &Rd },
755  { "mthi", NULL, &Rs },
756  { "mflo", NULL, &Rd },
757  { "mtlo", NULL, &Rs },
758  { "dsllv", NULL, &Rdrtrs },
759  { NULL, NULL, NULL },
760  { "dsrlv", NULL, &Rdrtrs },
761  { "dsrav", NULL, &Rdrtrs },
762  { "mult", NULL, &Rsrt },
763  { "multu", NULL, &Rsrt },
764  { "div", NULL, &Rsrt },
765  { "divu", NULL, &Rsrt },
766  { NULL, NULL, NULL },
767  { NULL, NULL, NULL },
768  { NULL, NULL, NULL },
769  { NULL, NULL, NULL },
770  { "add", NULL, &Rdrsrt },
771  { "addu", NULL, &Rdrsrt },
772  { "sub", NULL, &Rdrsrt },
773  { "subu", NULL, &Rdrsrt },
774  { "and", NULL, &Rdrsrt },
775  { "or", NULL, &Rdrsrt },
776  { "xor", NULL, &Rdrsrt },
777  { "nor", NULL, &Rdrsrt },
778  { "mfsa", NULL, &Rd },
779  { "mtsa", NULL, &Rs },
780  { "slt", NULL, &Rdrsrt },
781  { "sltu", NULL, &Rdrsrt },
782  { "dadd", NULL, &Rdrsrt },
783  { "daddu", NULL, &Rdrsrt },
784  { "dsub", NULL, &Rdrsrt },
785  { "dsubu", NULL, &Rdrsrt },
786  { "tge", NULL, &Rsrt },
787  { "tgeu", NULL, &Rsrt },
788  { "tlt", NULL, &Rsrt },
789  { "tltu", NULL, &Rsrt },
790  { "teq", NULL, &Rsrt },
791  { NULL, NULL, NULL },
792  { "tne", NULL, &Rsrt },
793  { NULL, NULL, NULL },
794  { "dsll", NULL, &Rdrtshamt },
795  { NULL, NULL, NULL },
796  { "dsrl", NULL, &Rdrtshamt },
797  { "dsra", NULL, &Rdrtshamt },
798  { "dsll32", NULL, &Rdrtshamt },
799  { NULL, NULL, NULL },
800  { "dsrl32", NULL, &Rdrtshamt },
801  { "dsra32", NULL, &Rdrtshamt }
802 };
803 static const Opcode_table ee_SPECIAL = { 0, 63, ee_SPECIAL_entries };
804 static const Opcode_table_entry BCOND_entries[] =
805 {
806  { "bltz", NULL, &Rsbroff },
807  { "bgez", NULL, &Rsbroff },
808  { NULL, NULL, NULL },
809  { NULL, NULL, NULL },
810  { NULL, NULL, NULL },
811  { NULL, NULL, NULL },
812  { NULL, NULL, NULL },
813  { NULL, NULL, NULL },
814  { NULL, NULL, NULL },
815  { NULL, NULL, NULL },
816  { NULL, NULL, NULL },
817  { NULL, NULL, NULL },
818  { NULL, NULL, NULL },
819  { NULL, NULL, NULL },
820  { NULL, NULL, NULL },
821  { NULL, NULL, NULL },
822  { "bltzal", NULL, &Rsbroff },
823  { "bgezal", NULL, &Rsbroff },
824  { NULL, NULL, NULL },
825  { NULL, NULL, NULL },
826  { NULL, NULL, NULL },
827  { NULL, NULL, NULL },
828  { NULL, NULL, NULL },
829  { NULL, NULL, NULL },
830  { NULL, NULL, NULL },
831  { NULL, NULL, NULL },
832  { NULL, NULL, NULL },
833  { NULL, NULL, NULL },
834  { NULL, NULL, NULL },
835  { NULL, NULL, NULL },
836  { NULL, NULL, NULL },
837  { NULL, NULL, NULL }
838 };
839 static const Opcode_table BCOND = { 16, 31, BCOND_entries };
840 static const Opcode_table_entry ee_REGIMM_entries[] =
841 {
842  { "bltz", NULL, &Rsbroff },
843  { "bgez", NULL, &Rsbroff },
844  { "bltzl", NULL, &Rsbroff },
845  { "bgezl", NULL, &Rsbroff },
846  { NULL, NULL, NULL },
847  { NULL, NULL, NULL },
848  { NULL, NULL, NULL },
849  { NULL, NULL, NULL },
850  { "tgei", NULL, &Rsseimm },
851  { "tgeiu", NULL, &Rsseimm },
852  { "tlti", NULL, &Rsseimm },
853  { "tltiu", NULL, &Rsseimm },
854  { "teqi", NULL, &Rsseimm },
855  { NULL, NULL, NULL },
856  { "tnei", NULL, &Rsseimm },
857  { NULL, NULL, NULL },
858  { "bltzal", NULL, &Rsbroff },
859  { "bgezal", NULL, &Rsbroff },
860  { "bltzall", NULL, &Rsbroff },
861  { "bgezall", NULL, &Rsbroff },
862  { NULL, NULL, NULL },
863  { NULL, NULL, NULL },
864  { NULL, NULL, NULL },
865  { NULL, NULL, NULL },
866  { "mtsab", NULL, &Rsseimm },
867  { "mtsah", NULL, &Rsseimm },
868  { NULL, NULL, NULL },
869  { NULL, NULL, NULL },
870  { NULL, NULL, NULL },
871  { NULL, NULL, NULL },
872  { NULL, NULL, NULL },
873  { NULL, NULL, NULL }
874 };
875 static const Opcode_table ee_REGIMM = { 16, 31, ee_REGIMM_entries };
876 static const Opcode_table_entry iop_COP0CO_entries[] =
877 {
878  { NULL, NULL, NULL },
879  { "tlbr", NULL, NULL },
880  { "tlbwi", NULL, NULL },
881  { NULL, NULL, NULL },
882  { NULL, NULL, NULL },
883  { NULL, NULL, NULL },
884  { "tlbwr", NULL, NULL },
885  { NULL, NULL, NULL },
886  { "tlbp", NULL, NULL },
887  { NULL, NULL, NULL },
888  { NULL, NULL, NULL },
889  { NULL, NULL, NULL },
890  { NULL, NULL, NULL },
891  { NULL, NULL, NULL },
892  { NULL, NULL, NULL },
893  { NULL, NULL, NULL },
894  { "rfe", NULL, NULL },
895  { NULL, NULL, NULL },
896  { NULL, NULL, NULL },
897  { NULL, NULL, NULL },
898  { NULL, NULL, NULL },
899  { NULL, NULL, NULL },
900  { NULL, NULL, NULL },
901  { NULL, NULL, NULL },
902  { NULL, NULL, NULL },
903  { NULL, NULL, NULL },
904  { NULL, NULL, NULL },
905  { NULL, NULL, NULL },
906  { NULL, NULL, NULL },
907  { NULL, NULL, NULL },
908  { NULL, NULL, NULL },
909  { NULL, NULL, NULL },
910  { NULL, NULL, NULL },
911  { NULL, NULL, NULL },
912  { NULL, NULL, NULL },
913  { NULL, NULL, NULL },
914  { NULL, NULL, NULL },
915  { NULL, NULL, NULL },
916  { NULL, NULL, NULL },
917  { NULL, NULL, NULL },
918  { NULL, NULL, NULL },
919  { NULL, NULL, NULL },
920  { NULL, NULL, NULL },
921  { NULL, NULL, NULL },
922  { NULL, NULL, NULL },
923  { NULL, NULL, NULL },
924  { NULL, NULL, NULL },
925  { NULL, NULL, NULL },
926  { NULL, NULL, NULL },
927  { NULL, NULL, NULL },
928  { NULL, NULL, NULL },
929  { NULL, NULL, NULL },
930  { NULL, NULL, NULL },
931  { NULL, NULL, NULL },
932  { NULL, NULL, NULL },
933  { NULL, NULL, NULL },
934  { NULL, NULL, NULL },
935  { NULL, NULL, NULL },
936  { NULL, NULL, NULL },
937  { NULL, NULL, NULL },
938  { NULL, NULL, NULL },
939  { NULL, NULL, NULL },
940  { NULL, NULL, NULL },
941  { NULL, NULL, NULL }
942 };
943 static const Opcode_table iop_COP0CO = { 0, 63, iop_COP0CO_entries };
944 static const Opcode_table_entry ee_COP0CO_entries[] =
945 {
946  { NULL, NULL, NULL },
947  { "tlbr", NULL, NULL },
948  { "tlbwi", NULL, NULL },
949  { NULL, NULL, NULL },
950  { NULL, NULL, NULL },
951  { NULL, NULL, NULL },
952  { "tlbwr", NULL, NULL },
953  { NULL, NULL, NULL },
954  { "tlbp", NULL, NULL },
955  { NULL, NULL, NULL },
956  { NULL, NULL, NULL },
957  { NULL, NULL, NULL },
958  { NULL, NULL, NULL },
959  { NULL, NULL, NULL },
960  { NULL, NULL, NULL },
961  { NULL, NULL, NULL },
962  { NULL, NULL, NULL },
963  { NULL, NULL, NULL },
964  { NULL, NULL, NULL },
965  { NULL, NULL, NULL },
966  { NULL, NULL, NULL },
967  { NULL, NULL, NULL },
968  { NULL, NULL, NULL },
969  { NULL, NULL, NULL },
970  { "eret", NULL, NULL },
971  { NULL, NULL, NULL },
972  { NULL, NULL, NULL },
973  { NULL, NULL, NULL },
974  { NULL, NULL, NULL },
975  { NULL, NULL, NULL },
976  { NULL, NULL, NULL },
977  { NULL, NULL, NULL },
978  { NULL, NULL, NULL },
979  { NULL, NULL, NULL },
980  { NULL, NULL, NULL },
981  { NULL, NULL, NULL },
982  { NULL, NULL, NULL },
983  { NULL, NULL, NULL },
984  { NULL, NULL, NULL },
985  { NULL, NULL, NULL },
986  { NULL, NULL, NULL },
987  { NULL, NULL, NULL },
988  { NULL, NULL, NULL },
989  { NULL, NULL, NULL },
990  { NULL, NULL, NULL },
991  { NULL, NULL, NULL },
992  { NULL, NULL, NULL },
993  { NULL, NULL, NULL },
994  { NULL, NULL, NULL },
995  { NULL, NULL, NULL },
996  { NULL, NULL, NULL },
997  { NULL, NULL, NULL },
998  { NULL, NULL, NULL },
999  { NULL, NULL, NULL },
1000  { NULL, NULL, NULL },
1001  { NULL, NULL, NULL },
1002  { "ei", NULL, NULL },
1003  { "di", NULL, NULL },
1004  { NULL, NULL, NULL },
1005  { NULL, NULL, NULL },
1006  { NULL, NULL, NULL },
1007  { NULL, NULL, NULL },
1008  { NULL, NULL, NULL },
1009  { NULL, NULL, NULL }
1010 };
1011 static const Opcode_table ee_COP0CO = { 0, 63, ee_COP0CO_entries };
1012 static const Opcode_table_entry iop_COP0_entries[] =
1013 {
1014  { "mfc0", NULL, &Rtc0rd_iop },
1015  { NULL, NULL, NULL },
1016  { "cfc0", NULL, &Rtc0rd_iop },
1017  { NULL, NULL, NULL },
1018  { "mtc0", NULL, &Rtc0rd_iop },
1019  { NULL, NULL, NULL },
1020  { "ctc0", NULL, &Rtc0rd_iop },
1021  { NULL, NULL, NULL },
1022  { "cop0", NULL, &Bcft },
1023  { NULL, NULL, NULL },
1024  { NULL, NULL, NULL },
1025  { NULL, NULL, NULL },
1026  { "cop0", NULL, &Bcft },
1027  { NULL, NULL, NULL },
1028  { NULL, NULL, NULL },
1029  { NULL, NULL, NULL },
1030  { NULL, &iop_COP0CO, NULL },
1031  { NULL, &iop_COP0CO, NULL },
1032  { NULL, &iop_COP0CO, NULL },
1033  { NULL, &iop_COP0CO, NULL },
1034  { NULL, &iop_COP0CO, NULL },
1035  { NULL, &iop_COP0CO, NULL },
1036  { NULL, &iop_COP0CO, NULL },
1037  { NULL, &iop_COP0CO, NULL },
1038  { NULL, &iop_COP0CO, NULL },
1039  { NULL, &iop_COP0CO, NULL },
1040  { NULL, &iop_COP0CO, NULL },
1041  { NULL, &iop_COP0CO, NULL },
1042  { NULL, &iop_COP0CO, NULL },
1043  { NULL, &iop_COP0CO, NULL },
1044  { NULL, &iop_COP0CO, NULL },
1045  { NULL, &iop_COP0CO, NULL }
1046 };
1047 static const Opcode_table iop_COP0 = { 21, 31, iop_COP0_entries };
1048 static const Opcode_table_entry ee_COP0_entries[] =
1049 {
1050  { "mfc0", NULL, &Rtc0rd_ee },
1051  { NULL, NULL, NULL },
1052  { "cfc0", NULL, &Rtc0rd_ee },
1053  { NULL, NULL, NULL },
1054  { "mtc0", NULL, &Rtc0rd_ee },
1055  { NULL, NULL, NULL },
1056  { "ctc0", NULL, &Rtc0rd_ee },
1057  { NULL, NULL, NULL },
1058  { "cop0", NULL, &Bcft },
1059  { NULL, NULL, NULL },
1060  { NULL, NULL, NULL },
1061  { NULL, NULL, NULL },
1062  { "cop0", NULL, &Bcft },
1063  { NULL, NULL, NULL },
1064  { NULL, NULL, NULL },
1065  { NULL, NULL, NULL },
1066  { NULL, &ee_COP0CO, NULL },
1067  { NULL, &ee_COP0CO, NULL },
1068  { NULL, &ee_COP0CO, NULL },
1069  { NULL, &ee_COP0CO, NULL },
1070  { NULL, &ee_COP0CO, NULL },
1071  { NULL, &ee_COP0CO, NULL },
1072  { NULL, &ee_COP0CO, NULL },
1073  { NULL, &ee_COP0CO, NULL },
1074  { NULL, &ee_COP0CO, NULL },
1075  { NULL, &ee_COP0CO, NULL },
1076  { NULL, &ee_COP0CO, NULL },
1077  { NULL, &ee_COP0CO, NULL },
1078  { NULL, &ee_COP0CO, NULL },
1079  { NULL, &ee_COP0CO, NULL },
1080  { NULL, &ee_COP0CO, NULL },
1081  { NULL, &ee_COP0CO, NULL }
1082 };
1083 static const Opcode_table ee_COP0 = { 21, 31, ee_COP0_entries };
1084 static const Opcode_table_entry ee_COP1CO_entries[] =
1085 {
1086  { "add.s", NULL, &Fdfsft },
1087  { "sub.s", NULL, &Fdfsft },
1088  { "mul.s", NULL, &Fdfsft },
1089  { "div.s", NULL, &Fdfsft },
1090  { "sqrt.s", NULL, &Fdfs },
1091  { "abs.s", NULL, &Fdfs },
1092  { "mov.s", NULL, &Fdfs },
1093  { "neg.s", NULL, &Fdfs },
1094  { NULL, NULL, NULL },
1095  { NULL, NULL, NULL },
1096  { NULL, NULL, NULL },
1097  { NULL, NULL, NULL },
1098  { NULL, NULL, NULL },
1099  { NULL, NULL, NULL },
1100  { NULL, NULL, NULL },
1101  { NULL, NULL, NULL },
1102  { NULL, NULL, NULL },
1103  { NULL, NULL, NULL },
1104  { NULL, NULL, NULL },
1105  { NULL, NULL, NULL },
1106  { NULL, NULL, NULL },
1107  { NULL, NULL, NULL },
1108  { "rsqrt.s", NULL, &Fdfs },
1109  { NULL, NULL, NULL },
1110  { "adda.s", NULL, &Fsft },
1111  { "suba.s", NULL, &Fsft },
1112  { "mula.s", NULL, &Fsft },
1113  { NULL, NULL, NULL },
1114  { "madd.s", NULL, &Fdfsft },
1115  { "msub.s", NULL, &Fdfsft },
1116  { "madda.s", NULL, &Fsft },
1117  { "msuba.s", NULL, &Fsft },
1118  { "cvt", NULL, &Fdfs },
1119  { NULL, NULL, NULL },
1120  { NULL, NULL, NULL },
1121  { NULL, NULL, NULL },
1122  { "cvt", NULL, &Fdfs },
1123  { NULL, NULL, NULL },
1124  { NULL, NULL, NULL },
1125  { NULL, NULL, NULL },
1126  { "max.s", NULL, &Fdfs },
1127  { "min.s", NULL, &Fdfs },
1128  { NULL, NULL, NULL },
1129  { NULL, NULL, NULL },
1130  { NULL, NULL, NULL },
1131  { NULL, NULL, NULL },
1132  { NULL, NULL, NULL },
1133  { NULL, NULL, NULL },
1134  { "c.f.s", NULL, &Fsft },
1135  { NULL, NULL, NULL },
1136  { "c.eq.s", NULL, &Fsft },
1137  { NULL, NULL, NULL },
1138  { "c.lt.s", NULL, &Fsft },
1139  { NULL, NULL, NULL },
1140  { "c.le.s", NULL, &Fsft },
1141  { NULL, NULL, NULL },
1142  { NULL, NULL, NULL },
1143  { NULL, NULL, NULL },
1144  { NULL, NULL, NULL },
1145  { NULL, NULL, NULL },
1146  { NULL, NULL, NULL },
1147  { NULL, NULL, NULL },
1148  { NULL, NULL, NULL },
1149  { NULL, NULL, NULL }
1150 };
1151 static const Opcode_table ee_COP1CO = { 0, 63, ee_COP1CO_entries };
1152 static const Opcode_table_entry iop_COP1_entries[] =
1153 {
1154  { "mfc1", NULL, &Rtczrd },
1155  { NULL, NULL, NULL },
1156  { "cfc1", NULL, &Rtczrd },
1157  { NULL, NULL, NULL },
1158  { "mtc1", NULL, &Rtczrd },
1159  { NULL, NULL, NULL },
1160  { "ctc1", NULL, &Rtczrd },
1161  { NULL, NULL, NULL },
1162  { "cop1", NULL, &Bcft },
1163  { NULL, NULL, NULL },
1164  { NULL, NULL, NULL },
1165  { NULL, NULL, NULL },
1166  { "cop1", NULL, &Bcft },
1167  { NULL, NULL, NULL },
1168  { NULL, NULL, NULL },
1169  { NULL, NULL, NULL },
1170  { "cop1", NULL, &Cofun },
1171  { "cop1", NULL, &Cofun },
1172  { "cop1", NULL, &Cofun },
1173  { "cop1", NULL, &Cofun },
1174  { "cop1", NULL, &Cofun },
1175  { "cop1", NULL, &Cofun },
1176  { "cop1", NULL, &Cofun },
1177  { "cop1", NULL, &Cofun },
1178  { "cop1", NULL, &Cofun },
1179  { "cop1", NULL, &Cofun },
1180  { "cop1", NULL, &Cofun },
1181  { "cop1", NULL, &Cofun },
1182  { "cop1", NULL, &Cofun },
1183  { "cop1", NULL, &Cofun },
1184  { "cop1", NULL, &Cofun },
1185  { "cop1", NULL, &Cofun }
1186 };
1187 static const Opcode_table iop_COP1 = { 21, 31, iop_COP1_entries };
1188 static const Opcode_table_entry ee_COP1_entries[] =
1189 {
1190  { "mfc1", NULL, &Rtczfs },
1191  { NULL, NULL, NULL },
1192  { "cfc1", NULL, &Rtczfs },
1193  { NULL, NULL, NULL },
1194  { "mtc1", NULL, &Rtczfs },
1195  { NULL, NULL, NULL },
1196  { "ctc1", NULL, &Rtczfs },
1197  { NULL, NULL, NULL },
1198  { "cop1", NULL, &Bcft },
1199  { NULL, NULL, NULL },
1200  { NULL, NULL, NULL },
1201  { NULL, NULL, NULL },
1202  { "cop1", NULL, &Bcft },
1203  { NULL, NULL, NULL },
1204  { NULL, NULL, NULL },
1205  { NULL, NULL, NULL },
1206  { NULL, &ee_COP1CO, NULL },
1207  { NULL, &ee_COP1CO, NULL },
1208  { NULL, &ee_COP1CO, NULL },
1209  { NULL, &ee_COP1CO, NULL },
1210  { NULL, &ee_COP1CO, NULL },
1211  { NULL, &ee_COP1CO, NULL },
1212  { NULL, &ee_COP1CO, NULL },
1213  { NULL, &ee_COP1CO, NULL },
1214  { NULL, &ee_COP1CO, NULL },
1215  { NULL, &ee_COP1CO, NULL },
1216  { NULL, &ee_COP1CO, NULL },
1217  { NULL, &ee_COP1CO, NULL },
1218  { NULL, &ee_COP1CO, NULL },
1219  { NULL, &ee_COP1CO, NULL },
1220  { NULL, &ee_COP1CO, NULL },
1221  { NULL, &ee_COP1CO, NULL }
1222 };
1223 static const Opcode_table ee_COP1 = { 21, 31, ee_COP1_entries };
1224 static const Opcode_table_entry iop_COP2_entries[] =
1225 {
1226  { "mfc2", NULL, &Rtczrd },
1227  { NULL, NULL, NULL },
1228  { "cfc2", NULL, &Rtczrd },
1229  { NULL, NULL, NULL },
1230  { "mtc2", NULL, &Rtczrd },
1231  { NULL, NULL, NULL },
1232  { "ctc2", NULL, &Rtczrd },
1233  { NULL, NULL, NULL },
1234  { "cop2", NULL, &Bcft },
1235  { NULL, NULL, NULL },
1236  { NULL, NULL, NULL },
1237  { NULL, NULL, NULL },
1238  { "cop2", NULL, &Bcft },
1239  { NULL, NULL, NULL },
1240  { NULL, NULL, NULL },
1241  { NULL, NULL, NULL },
1242  { "cop2", NULL, &Cofun },
1243  { "cop2", NULL, &Cofun },
1244  { "cop2", NULL, &Cofun },
1245  { "cop2", NULL, &Cofun },
1246  { "cop2", NULL, &Cofun },
1247  { "cop2", NULL, &Cofun },
1248  { "cop2", NULL, &Cofun },
1249  { "cop2", NULL, &Cofun },
1250  { "cop2", NULL, &Cofun },
1251  { "cop2", NULL, &Cofun },
1252  { "cop2", NULL, &Cofun },
1253  { "cop2", NULL, &Cofun },
1254  { "cop2", NULL, &Cofun },
1255  { "cop2", NULL, &Cofun },
1256  { "cop2", NULL, &Cofun },
1257  { "cop2", NULL, &Cofun }
1258 };
1259 static const Opcode_table iop_COP2 = { 21, 31, iop_COP2_entries };
1260 static const Opcode_table_entry ee_COP2_entries[] =
1261 {
1262  { "mfc2", NULL, &Rtczrd },
1263  { "qmfc2", NULL, &Rtczrd },
1264  { "cfc2", NULL, &Rtczrd },
1265  { NULL, NULL, NULL },
1266  { "mtc2", NULL, &Rtczrd },
1267  { "qmtc2", NULL, &Rtczrd },
1268  { "ctc2", NULL, &Rtczrd },
1269  { NULL, NULL, NULL },
1270  { "cop2", NULL, &Bcft },
1271  { NULL, NULL, NULL },
1272  { NULL, NULL, NULL },
1273  { NULL, NULL, NULL },
1274  { "cop2", NULL, &Bcft },
1275  { NULL, NULL, NULL },
1276  { NULL, NULL, NULL },
1277  { NULL, NULL, NULL },
1278  { "cop2", NULL, &Cofun },
1279  { "cop2", NULL, &Cofun },
1280  { "cop2", NULL, &Cofun },
1281  { "cop2", NULL, &Cofun },
1282  { "cop2", NULL, &Cofun },
1283  { "cop2", NULL, &Cofun },
1284  { "cop2", NULL, &Cofun },
1285  { "cop2", NULL, &Cofun },
1286  { "cop2", NULL, &Cofun },
1287  { "cop2", NULL, &Cofun },
1288  { "cop2", NULL, &Cofun },
1289  { "cop2", NULL, &Cofun },
1290  { "cop2", NULL, &Cofun },
1291  { "cop2", NULL, &Cofun },
1292  { "cop2", NULL, &Cofun },
1293  { "cop2", NULL, &Cofun }
1294 };
1295 static const Opcode_table ee_COP2 = { 21, 31, ee_COP2_entries };
1296 static const Opcode_table_entry COP3_entries[] =
1297 {
1298  { "mfc3", NULL, &Rtczrd },
1299  { NULL, NULL, NULL },
1300  { "cfc3", NULL, &Rtczrd },
1301  { NULL, NULL, NULL },
1302  { "mtc3", NULL, &Rtczrd },
1303  { NULL, NULL, NULL },
1304  { "ctc3", NULL, &Rtczrd },
1305  { NULL, NULL, NULL },
1306  { "cop3", NULL, &Bcft },
1307  { NULL, NULL, NULL },
1308  { NULL, NULL, NULL },
1309  { NULL, NULL, NULL },
1310  { "cop3", NULL, &Bcft },
1311  { NULL, NULL, NULL },
1312  { NULL, NULL, NULL },
1313  { NULL, NULL, NULL },
1314  { "cop3", NULL, &Cofun },
1315  { "cop3", NULL, &Cofun },
1316  { "cop3", NULL, &Cofun },
1317  { "cop3", NULL, &Cofun },
1318  { "cop3", NULL, &Cofun },
1319  { "cop3", NULL, &Cofun },
1320  { "cop3", NULL, &Cofun },
1321  { "cop3", NULL, &Cofun },
1322  { "cop3", NULL, &Cofun },
1323  { "cop3", NULL, &Cofun },
1324  { "cop3", NULL, &Cofun },
1325  { "cop3", NULL, &Cofun },
1326  { "cop3", NULL, &Cofun },
1327  { "cop3", NULL, &Cofun },
1328  { "cop3", NULL, &Cofun },
1329  { "cop3", NULL, &Cofun }
1330 };
1331 static const Opcode_table COP3 = { 21, 31, COP3_entries };
1332 static const Opcode_table_entry iop_opcode_root_table_entries[] =
1333 {
1334  { NULL, &iop_SPECIAL, NULL },
1335  { NULL, &BCOND, NULL },
1336  { "j", NULL, &Jtarget },
1337  { "jal", NULL, &Jtarget },
1338  { "beq", NULL, &Rsrtbroff },
1339  { "bne", NULL, &Rsrtbroff },
1340  { "blez", NULL, &Rsbroff },
1341  { "bgtz", NULL, &Rsbroff },
1342  { "addi", NULL, &Rtrsseimm },
1343  { "addiu", NULL, &Rtrsseimm },
1344  { "slti", NULL, &Rtrsseimm },
1345  { "sltiu", NULL, &Rtrsseimm },
1346  { "andi", NULL, &Rtrsimm },
1347  { "ori", NULL, &Rtrsimm },
1348  { "xori", NULL, &Rtrsimm },
1349  { "lui", NULL, &Rtimm },
1350  { NULL, &iop_COP0, NULL },
1351  { NULL, &iop_COP1, NULL },
1352  { NULL, &iop_COP2, NULL },
1353  { NULL, &COP3, NULL },
1354  { NULL, NULL, NULL },
1355  { NULL, NULL, NULL },
1356  { NULL, NULL, NULL },
1357  { NULL, NULL, NULL },
1358  { NULL, NULL, NULL },
1359  { NULL, NULL, NULL },
1360  { NULL, NULL, NULL },
1361  { NULL, NULL, NULL },
1362  { NULL, NULL, NULL },
1363  { NULL, NULL, NULL },
1364  { NULL, NULL, NULL },
1365  { NULL, NULL, NULL },
1366  { "lb", NULL, &Rtoffbase },
1367  { "lh", NULL, &Rtoffbase },
1368  { "lwl", NULL, &Rtoffbase },
1369  { "lw", NULL, &Rtoffbase },
1370  { "lbu", NULL, &Rtoffbase },
1371  { "lhu", NULL, &Rtoffbase },
1372  { "lwr", NULL, &Rtoffbase },
1373  { NULL, NULL, NULL },
1374  { "sb", NULL, &Rtoffbase },
1375  { "sh", NULL, &Rtoffbase },
1376  { "swl", NULL, &Rtoffbase },
1377  { "sw", NULL, &Rtoffbase },
1378  { NULL, NULL, NULL },
1379  { NULL, NULL, NULL },
1380  { "swr", NULL, &Rtoffbase },
1381  { NULL, NULL, NULL },
1382  { "lwc0", NULL, &Rtoffbase },
1383  { "lwc1", NULL, &Rtoffbase },
1384  { "lwc2", NULL, &Rtoffbase },
1385  { "lwc3", NULL, &Rtoffbase },
1386  { NULL, NULL, NULL },
1387  { NULL, NULL, NULL },
1388  { NULL, NULL, NULL },
1389  { NULL, NULL, NULL },
1390  { "swc0", NULL, &Rtoffbase },
1391  { "swc1", NULL, &Rtoffbase },
1392  { "swc2", NULL, &Rtoffbase },
1393  { "swc3", NULL, &Rtoffbase },
1394  { NULL, NULL, NULL },
1395  { NULL, NULL, NULL },
1396  { NULL, NULL, NULL },
1397  { NULL, NULL, NULL }
1398 };
1399 static const Opcode_table_entry ee_opcode_root_table_entries[] =
1400 {
1401  { NULL, &ee_SPECIAL, NULL },
1402  { NULL, &ee_REGIMM, NULL },
1403  { "j", NULL, &Jtarget },
1404  { "jal", NULL, &Jtarget },
1405  { "beq", NULL, &Rsrtbroff },
1406  { "bne", NULL, &Rsrtbroff },
1407  { "blez", NULL, &Rsbroff },
1408  { "bgtz", NULL, &Rsbroff },
1409  { "addi", NULL, &Rtrsseimm },
1410  { "addiu", NULL, &Rtrsseimm },
1411  { "slti", NULL, &Rtrsseimm },
1412  { "sltiu", NULL, &Rtrsseimm },
1413  { "andi", NULL, &Rtrsimm },
1414  { "ori", NULL, &Rtrsimm },
1415  { "xori", NULL, &Rtrsimm },
1416  { "lui", NULL, &Rtimm },
1417  { NULL, &ee_COP0, NULL },
1418  { NULL, &ee_COP1, NULL },
1419  { NULL, &ee_COP2, NULL },
1420  { NULL, &COP3, NULL },
1421  { "beql", NULL, &Rsrtbroff },
1422  { "bnel", NULL, &Rsrtbroff },
1423  { "blezl", NULL, &Rsbroff },
1424  { "bgtzl", NULL, &Rsbroff },
1425  { "daddi", NULL, &Rtrsseimm },
1426  { "daddiu", NULL, &Rtrsseimm },
1427  { "ldl", NULL, &Rtoffbase },
1428  { "ldr", NULL, &Rtoffbase },
1429  { "mmi", NULL, NULL },
1430  { NULL, NULL, NULL },
1431  { "lq", NULL, &Rtoffbase },
1432  { "sq", NULL, &Rtoffbase },
1433  { "lb", NULL, &Rtoffbase },
1434  { "lh", NULL, &Rtoffbase },
1435  { "lwl", NULL, &Rtoffbase },
1436  { "lw", NULL, &Rtoffbase },
1437  { "lbu", NULL, &Rtoffbase },
1438  { "lhu", NULL, &Rtoffbase },
1439  { "lwr", NULL, &Rtoffbase },
1440  { NULL, NULL, NULL },
1441  { "sb", NULL, &Rtoffbase },
1442  { "sh", NULL, &Rtoffbase },
1443  { "swl", NULL, &Rtoffbase },
1444  { "sw", NULL, &Rtoffbase },
1445  { "sdl", NULL, &Rtoffbase },
1446  { "sdr", NULL, &Rtoffbase },
1447  { "swr", NULL, &Rtoffbase },
1448  { "cache", NULL, NULL },
1449  { "lwc0", NULL, &Rtoffbase },
1450  { "lwc1", NULL, &Rtoffbase },
1451  { "lwc2", NULL, &Rtoffbase },
1452  { "pref", NULL, &Rtoffbase },
1453  { NULL, NULL, NULL },
1454  { NULL, NULL, NULL },
1455  { "lqc2", NULL, &Rtoffbase },
1456  { "ld", NULL, &Rtoffbase },
1457  { "swc0", NULL, &Rtoffbase },
1458  { "swc1", NULL, &Rtoffbase },
1459  { "swc2", NULL, &Rtoffbase },
1460  { "swc3", NULL, &Rtoffbase },
1461  { NULL, NULL, NULL },
1462  { NULL, NULL, NULL },
1463  { "sqc2", NULL, &Rtoffbase },
1464  { "sd", NULL, &Rtoffbase }
1465 };
1466 static const Opcode_table iop_opcode_root_table = { 26, 63, iop_opcode_root_table_entries };
1467 static const Opcode_table ee_opcode_root_table = { 26, 63, ee_opcode_root_table_entries };
1468 static const Opcode_table * opcode_root_table = &iop_opcode_root_table;
1469 // clang-format on
1470 
1471 void gen_asmmacro(Disasm_result *result)
1472 {
1473  if ( result->data )
1474  {
1475  if (
1476  !strcmp("beq", result->mnemonic) && result->operands[0].tag == OprTag_reg && result->operands[1].tag == OprTag_reg
1477  && result->operands[1].reg == result->operands[0].reg )
1478  {
1479  strcpy(result->mnemonic, "b");
1480  result->operands[0] = result->operands[2];
1481  result->operands[1].tag = OprTag_none;
1482  }
1483  else if ( !strcmp("bgezal", result->mnemonic) && result->operands[0].tag == OprTag_reg && !result->operands[0].reg )
1484  {
1485  strcpy(result->mnemonic, "bal");
1486  result->operands[0] = result->operands[1];
1487  result->operands[1].tag = OprTag_none;
1488  }
1489  else if ( !strcmp("cvt", result->mnemonic) )
1490  {
1491  if ( ((result->data >> 21) & 0x1F) == 20 )
1492  {
1493  strcpy(result->mnemonic, "cvt.s.w");
1494  }
1495  else if ( ((result->data >> 21) & 0x1F) == 16 )
1496  {
1497  strcpy(result->mnemonic, "cvt.w.s");
1498  }
1499  }
1500  }
1501  else
1502  {
1503  strcpy(result->mnemonic, "nop");
1504  result->operands[0].tag = OprTag_none;
1505  }
1506 }
1507 
1508 void initdisasm(int arch, int regform0, int regform1, int regform2, int regform3)
1509 {
1510  switch ( arch )
1511  {
1512  case 1:
1513  opcode_root_table = &iop_opcode_root_table;
1514  break;
1515  case 2:
1516  opcode_root_table = &ee_opcode_root_table;
1517  break;
1518  default:
1519  break;
1520  }
1521  if ( regform0 != -1 )
1522  {
1523  if ( !regform0 || regform0 == 1 )
1524  {
1525  regnmsw[0] = regform0;
1526  }
1527  if ( !regform1 || regform1 == 1 )
1528  {
1529  regnmsw[1] = regform0;
1530  }
1531  if ( !regform2 || regform2 == 1 )
1532  {
1533  regnmsw[2] = regform0;
1534  }
1535  if ( !regform3 || regform3 == 1 )
1536  {
1537  regnmsw[3] = regform3;
1538  }
1539  }
1540 }
1541 
1542 Disasm_result *disassemble(unsigned int addr, unsigned int data)
1543 {
1544  Disasm_result *v3;
1545  const Opcode_table_entry *op;
1546  const Opcode_table *optable;
1547 
1548  optable = opcode_root_table;
1549  v3 = (Disasm_result *)calloc(1, sizeof(Disasm_result));
1550  for ( ;; )
1551  {
1552  op = &optable->entries[(data >> optable->bit_pos) & optable->bit_mask];
1553  if ( !op->subtable )
1554  {
1555  break;
1556  }
1557  optable = op->subtable;
1558  }
1559  v3->addr = addr;
1560  v3->data = data;
1561  if ( op->mnemonic )
1562  {
1563  strcpy(v3->mnemonic, op->mnemonic);
1564  if ( op->opfunc )
1565  {
1566  op->opfunc(v3);
1567  }
1568  }
1569  return v3;
1570 }
1571 
1572 void shex(char *buf, unsigned int data)
1573 {
1574  if ( (data & 0x80000000) != 0 )
1575  {
1576  sprintf(buf, "-0x%x", -data);
1577  }
1578  else
1579  {
1580  sprintf(buf, "0x%x", data);
1581  }
1582 }
1583 
1584 void format_operand(const Operand *opr, char *buf)
1585 {
1586  switch ( opr->tag )
1587  {
1588  case OprTag_reg:
1589  strcpy(buf, REGNAME[regnmsw[0]][opr->reg]);
1590  break;
1591  case OprTag_c0reg_iop:
1592  strcpy(buf, REGC0_iop[regnmsw[0]][opr->reg]);
1593  break;
1594  case OprTag_c0reg_ee:
1595  strcpy(buf, REGC0_ee[regnmsw[0]][opr->reg]);
1596  break;
1597  case OprTag_czreg:
1598  sprintf(buf, "$%d", opr->reg);
1599  break;
1600  case OprTag_c1reg:
1601  strcpy(buf, REGC1[regnmsw[1]][opr->reg]);
1602  break;
1603  case OprTag_imm:
1604  case OprTag_jtarget:
1605  shex(buf, opr->data);
1606  break;
1607  case OprTag_shamt:
1608  sprintf(buf, "%d", (int)(opr->data));
1609  break;
1610  case OprTag_regoffset:
1611  shex(buf, opr->data);
1612  sprintf(&buf[strlen(buf)], "(%s)", REGNAME[regnmsw[0]][opr->reg]);
1613  break;
1614  case OprTag_code20:
1615  case OprTag_code25:
1616  sprintf(buf, "0x%x", opr->data);
1617  break;
1618  default:
1619  sprintf(buf, "?type?(0x%x)", opr->tag);
1620  fprintf(stderr, "Panic unknown oprand type 0x%x\n", opr->tag);
1621  break;
1622  }
1623 }
1624 
1625 void format_disasm(Disasm_result *dis, char *buf)
1626 {
1627  char *s;
1628 
1629  sprintf(buf, "%08x: %08x", dis->addr, dis->data);
1630  s = &buf[strlen(buf)];
1631  if ( dis->mnemonic[0] )
1632  {
1633  int i;
1634  char *sa;
1635 
1636  sprintf(s, " %-8s", dis->mnemonic);
1637  sa = &s[strlen(s)];
1638  for ( i = 0; dis->operands[i].tag; i += 1 )
1639  {
1640  format_operand(&dis->operands[i], sa);
1641  if ( dis->operands[i + 1].tag )
1642  {
1643  strcat(sa, ", ");
1644  }
1645  sa += strlen(sa);
1646  }
1647  }
1648 }
opcode_table_
Definition: mipsdis.c:354
operand
Definition: srxfixup_internal.h:399
stdio.h
opcode_table_entry_
Definition: mipsdis.c:348
stdlib.h
disasm_result
Definition: srxfixup_internal.h:405