+static const struct instruction MIPS16_DECODE[] = {
+{"ADDIU", 1, "01000xxxddd04444", RRI_A, ADD, WORD | WORD32 },
+{"ADDIU8", 1, "01001wwwkkkkkkkk", RI, ADD, WORD | WORD32 },
+{"ADJSP", 1, "01100011KKKKKKKKS", I8, ADD, WORD | WORD32 },
+{"ADDIUPC", 1, "00001dddAAAAAAAAP", RI, ADD, WORD | WORD32 },
+{"ADDIUSP", 1, "00000dddAAAAAAAAs", RI, ADD, WORD | WORD32 },
+{"ADDU", 1, "11100xxxyyyddd01", RRR, ADD, WORD | WORD32 },
+{"AND", 1, "11101wwwyyy01100", RR, AND, NONE },
+{"B", 1, "00010qqqqqqqqqqqzZ", I, BRANCH, EQ },
+{"BEQZ", 1, "00100xxxppppppppz", RI, BRANCH, EQ },
+{"BNEZ", 1, "00101xxxppppppppz", RI, BRANCH, NOT | EQ },
+{"BREAK", 1, "01100??????00101", RR, BREAK, NOARG },
+{"BTEQZ", 1, "01100000pppppppptz", I8, BRANCH, EQ },
+{"BTNEZ", 1, "01100001pppppppptz", I8, BRANCH, NOT | EQ },
+{"CMP", 1, "11101xxxyyy01010T", RR, XOR, NONE },
+{"CMPI", 1, "01110xxxUUUUUUUUT", RI, XOR, NONE },
+{"DADDIU", 3, "01000xxxddd14444", RRI_A, ADD, DOUBLEWORD },
+{"DADDIU5", 3, "11111101wwwjjjjj", RI64, ADD, DOUBLEWORD },
+{"DADJSP", 3, "11111011KKKKKKKKS", I64, ADD, DOUBLEWORD },
+{"DADIUPC", 3, "11111110dddEEEEEP", RI64, ADD, DOUBLEWORD },
+{"DADIUSP", 3, "11111111dddEEEEEs", RI64, ADD, DOUBLEWORD },
+{"DADDU", 3, "11100xxxyyyddd00", RRR, ADD, DOUBLEWORD },
+{"DDIV", 3, "11101xxxyyy11110", RR, DIV, DOUBLEWORD | HI | LO },
+{"DDIVU", 3, "11101xxxyyy11111", RR, DIV, DOUBLEWORD | UNSIGNED | HI | LO },
+{"DIV", 1, "11101xxxyyy11010", RR, DIV, WORD | WORD32 | SIGNEXTEND | HI | LO },
+{"DIVU", 1, "11101xxxyyy11011", RR, DIV, WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO },
+{"DMULT", 3, "11101xxxyyy11100", RR, MUL, DOUBLEWORD | HI | LO },
+{"DMULTU", 3, "11101xxxyyy11101", RR, MUL, DOUBLEWORD | UNSIGNED | HI | LO },
+{"DSLL", 3, "00110dddyyy[[[01", ISHIFT, SHIFT, DOUBLEWORD | LEFT | LOGICAL },
+{"DSLLV", 3, "11101xxxvvv10100", RR, SHIFT, DOUBLEWORD | LEFT | LOGICAL | REG },
+{"DSRA", 3, "11101]]]vvv10011", RR, SHIFT, DOUBLEWORD | RIGHT | ARITHMETIC },
+{"DSRAV", 3, "11101xxxvvv10111", RR, SHIFT, DOUBLEWORD | RIGHT | ARITHMETIC | REG},
+{"DSRL", 3, "11101]]]vvv01000", RR, SHIFT, DOUBLEWORD | RIGHT | LOGICAL },
+{"DSRLV", 3, "11101xxxvvv10110", RR, SHIFT, DOUBLEWORD | RIGHT | LOGICAL | REG},
+{"DSUBU", 3, "11100xxxyyyddd10", RRR, SUB, DOUBLEWORD | UNSIGNED},
+#if 0
+ /* FIXME: Should we handle these ourselves, or should we require an
+ emulation routine? */
+{"EXIT", 1, "1110111100001000", RR, BREAK, EXIT },
+{"ENTRY", 1, "11101??????01000", RR, BREAK, ENTRY },
+#endif
+{"EXTEND", 1, "11110eeeeeeeeeee", I, RSVD, NOARG },
+{"JALR", 1, "11101xxx01000000R", RR, JUMP, LINK | REG },
+{"JAL", 1, "00011aaaaaaaaaaa", I, JUMP, LINK },
+{"JR", 1, "11101xxx00000000", RR, JUMP, NONE },
+{"JRRA", 1, "1110100000100000r", RR, JUMP, NONE },
+{"LB", 1, "10000xxxddd55555", RRI, LOAD, BYTE | SIGNEXTEND },
+{"LBU", 1, "10100xxxddd55555", RRI, LOAD, BYTE },
+{"LD", 3, "00111xxxdddDDDDD", RRI, LOAD, DOUBLEWORD },
+{"LDPC", 3, "11111100dddDDDDDP", RI64, LOAD, DOUBLEWORD },
+{"LDSP", 3, "11111000dddDDDDDs", RI64, LOAD, DOUBLEWORD },
+{"LH", 1, "10001xxxdddHHHHH", RRI, LOAD, HALFWORD | SIGNEXTEND },
+{"LHU", 1, "10101xxxdddHHHHH", RRI, LOAD, HALFWORD },
+{"LI", 1, "01101dddUUUUUUUUZ", RI, OR, NONE },
+{"LW", 1, "10011xxxdddWWWWW", RRI, LOAD, WORD | SIGNEXTEND },
+{"LWPC", 1, "10110dddVVVVVVVVP", RI, LOAD, WORD | SIGNEXTEND },
+{"LWSP", 1, "10010dddVVVVVVVVs", RI, LOAD, WORD | SIGNEXTEND },
+{"LWU", 1, "10111xxxdddWWWWW", RRI, LOAD, WORD },
+{"MFHI", 1, "11101ddd00010000", RR, MOVE, HI | LEFT },
+{"MFLO", 1, "11101ddd00010010", RR, MOVE, LO | LEFT },
+{"MOVR32", 1, "01100111dddXXXXXz", I8_MOVR32, OR, NONE },
+{"MOV32R", 1, "01100101YYYYYxxxz", I8_MOV32R, OR, NONE },
+{"MULT", 1, "11101xxxyyy11000", RR, MUL, WORD | WORD32 | HI | LO},
+{"MULTU", 1, "11101xxxyyy11001", RR, MUL, WORD | WORD32 | UNSIGNED | HI | LO },
+{"NEG", 1, "11101dddyyy01011Z", RR, SUB, WORD },
+{"NOT", 1, "11101dddyyy01111Z", RR, OR, NOT },
+{"OR", 1, "11101wwwyyy01101", RR, OR, NONE },
+{"SB", 1, "11000xxxyyy55555", RRI, STORE, BYTE },
+{"SDBBP", G7, "11100??????00001", RR, SDBBP, NOARG },
+{"SD", 3, "01111xxxyyyDDDDD", RRI, STORE, DOUBLEWORD },
+{"SDSP", 3, "11111001yyyDDDDDs", RI64, STORE, DOUBLEWORD },
+{"SDRASP", 3, "11111010CCCCCCCCsQ", I64, STORE, DOUBLEWORD },
+{"SH", 1, "11001xxxyyyHHHHH", RRI, STORE, HALFWORD },
+{"SLL", 1, "00110dddyyy<<<00", ISHIFT, SHIFT, WORD | LEFT | LOGICAL },
+{"SLLV", 1, "11101xxxvvv00100", RR, SHIFT, WORD | LEFT | LOGICAL | REG},
+{"SLT", 1, "11101xxxyyy00010T", RR, SET, LT },
+{"SLTI", 1, "01010xxx88888888T", RI, SET, LT },
+{"SLTU", 1, "11101xxxyyy00011T", RR, SET, LT | UNSIGNED },
+{"SLTIU", 1, "01011xxx88888888T", RI, SET, LT | UNSIGNED },
+{"SRA", 1, "00110dddyyy<<<11", ISHIFT, SHIFT, WORD | WORD32 | RIGHT | ARITHMETIC },
+{"SRAV", 1, "11101xxxvvv00111", RR, SHIFT, WORD | WORD32 | RIGHT | ARITHMETIC | REG },
+{"SRL", 1, "00110dddyyy<<<10", ISHIFT, SHIFT, WORD | WORD32 | RIGHT | LOGICAL },
+{"SRLV", 1, "11101xxxvvv00110", RR, SHIFT, WORD | WORD32 | RIGHT | LOGICAL | REG },
+{"SUBU", 1, "11100xxxyyyddd11", RRR, SUB, WORD | WORD32 },
+{"SW", 1, "11011xxxyyyWWWWW", RRI, STORE, WORD },
+{"SWSP", 1, "11010yyyVVVVVVVVs", RI, STORE, WORD },
+{"SWRASP", 1, "01100010VVVVVVVVQs", I8, STORE, WORD },
+{"XOR", 1, "11101wwwyyy01110", RR, XOR, NONE }
+};
+
+/*---------------------------------------------------------------------------*/
+
+static void print_igen_insn_format PARAMS ((const char *bitmap,
+ inst_type mark,
+ int data_size,
+ const char *options,
+ const char *name));
+
+static void
+print_igen_insn_format (bitmap, mark, data_size, options, name)
+ const char *bitmap;
+ inst_type mark;
+ int data_size;
+ const char *options;
+ const char *name;
+{
+ const char *chp;
+ char lch = *bitmap;
+ for (chp = bitmap; *chp != '\0'; chp++)
+ {
+ if ((isdigit (lch) && !isdigit (*chp))
+ || (!isdigit (lch) && isdigit (*chp))
+ || (!isdigit (lch) && !isdigit (*chp) && lch != *chp))
+ {
+ lch = *chp;
+ printf (",");
+ }
+ switch (*chp)
+ {
+ case '?':
+ printf ("*");
+ break;
+ case '<':
+ printf ("s"); /* good guess */
+ break;
+ default:
+ printf ("%c", *chp);
+ break;
+ }
+ }
+ printf (":");
+ switch (mark)
+ {
+ case NORMAL:
+ printf ("NORMAL");
+ break;
+ case SPECIAL:
+ printf ("SPECIAL");
+ break;
+ case REGIMM:
+ printf ("REGIMM");
+ break;
+ case COP1:
+ printf ("COP1");
+ break;
+ case COP1X:
+ printf ("COP1X");
+ break;
+ case COP1S: /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
+ printf ("COP1S");
+ break;
+
+ case MMINORM:
+ printf ("MMINORM");
+ break;
+ case MMI0:
+ printf ("MMI0");
+ break;
+ case MMI1:
+ printf ("MMI1");
+ break;
+ case MMI2:
+ printf ("MMI2");
+ break;
+ case MMI3:
+ printf ("MMI3");
+ break;
+
+ /* mips16 encoding types. */
+ case I:
+ printf ("I");
+ break;
+ case RI:
+ printf ("RI");
+ break;
+ case RR:
+ printf ("RR");
+ break;
+ case RRI:
+ printf ("RRI");
+ break;
+ case RRR:
+ printf ("RRR");
+ break;
+ case RRI_A:
+ printf ("RRI_A");
+ break;
+ case ISHIFT:
+ printf ("ISHIFT");
+ break;
+ case I8:
+ printf ("I8");
+ break;
+ case I8_MOVR32:
+ printf ("I8_MOVR32");
+ break;
+ case I8_MOV32R:
+ printf ("I8_MOV32R");
+ break;
+ case I64:
+ printf ("I64");
+ break;
+ case RI64:
+ printf ("RI64");
+ break;
+ }
+ printf (":");
+ switch (data_size)
+ {
+ case DOUBLEWORD:
+ printf ("64");
+ break;
+ /* start-sanitize-r5900 */
+ case QUADWORD:
+ printf ("128");
+ break;
+ /* end-sanitize-r5900 */
+ case -1:
+ printf ("16");
+ break;
+ default:
+ printf ("32");
+ }
+ printf (":%s:%s\n", options, name);
+}
+
+static void print_igen_insn_models PARAMS ((unsigned int isa));
+
+static void
+print_igen_insn_models (isa)
+ unsigned int isa;
+{
+ /* common mips ISAs */
+ switch ((isa & MASK_ISA))
+ {
+ case 1:
+ printf ("*mipsI:\n");
+ case 2:
+ printf ("*mipsII:\n");
+ case 3:
+ printf ("*mipsIII:\n");
+ /* start-sanitize-cygnus-never */
+ printf ("// %s-%s-%s\n", "start", "sanitize", "r5900");
+ /* end-sanitize-cygnus-never */
+ /* start-sanitize-r5900 */
+ printf ("*r5900:\n");
+ /* end-sanitize-r5900 */
+ /* start-sanitize-cygnus-never */
+ printf ("// %s-%s-%s\n", "end", "sanitize", "r5900");
+ /* end-sanitize-cygnus-never */
+ printf ("*r3900:\n");
+ /* start-sanitize-cygnus-never */
+ printf ("// %s-%s-%s\n", "start", "sanitize", "tx19");
+ /* end-sanitize-cygnus-never */
+ /* start-sanitize-tx19 */
+ printf ("*tx19:\n");
+ /* end-sanitize-tx19 */
+ /* start-sanitize-cygnus-never */
+ printf ("// %s-%s-%s\n", "end", "sanitize", "tx19");
+ /* end-sanitize-cygnus-never */
+ break;
+ default:
+ /* processor specific ISAs */
+ if ((isa & ARCH_VR4100))
+ printf ("*vr4100:\n");
+ /* start-sanitize-r5900 */
+ if ((isa & ARCH_R5900))
+ printf ("*r5900:\n");
+ /* end-sanitize-r5900 */
+ if ((isa & ARCH_R3900))
+ printf ("*r3900:\n");
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+
+static int bitmap_val PARAMS ((const char *, int, int));
+static void build_mips16_operands PARAMS ((const char *));
+static void build_instruction
+ PARAMS ((int, unsigned int, int, const struct instruction *));
+
+/*---------------------------------------------------------------------------*/
+
+static char*
+name_for_data_len( insn )
+ struct instruction* insn;
+ {
+ if (GETDATASIZEINSN(insn) == BYTE)
+ return "BYTE";
+
+ else if (GETDATASIZEINSN(insn) == HALFWORD)
+ return "HALFWORD";
+
+ else if (GETDATASIZEINSN(insn) == WORD)
+ return "WORD";
+
+ else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+ return "DOUBLEWORD";
+
+ /* start-sanitize-r5900 */
+ else if (GETDATASIZEINSN(insn) == QUADWORD)
+ return "QUADWORD";
+
+ /* end-sanitize-r5900 */
+ else
+ return 0;
+ }
+
+static char*
+letter_for_data_len( insn )
+ struct instruction* insn;
+ {
+ if (GETDATASIZEINSN(insn) == BYTE)
+ return "B";
+
+ else if (GETDATASIZEINSN(insn) == HALFWORD)
+ return "H";
+
+ else if (GETDATASIZEINSN(insn) == WORD)
+ return "W";
+
+ else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+ return "D";
+
+ /* start-sanitize-r5900 */
+ else if (GETDATASIZEINSN(insn) == QUADWORD)
+ return "Q";
+
+ /* end-sanitize-r5900 */
+ else
+ return 0;
+ }
+
+static char*
+type_for_data_len( insn , is_signed )
+ struct instruction* insn;
+ int is_signed;
+ {
+ if (GETDATASIZEINSN(insn) == BYTE)
+ return is_signed ? "int" : "unsigned int";
+
+ else if (GETDATASIZEINSN(insn) == HALFWORD)
+ return is_signed ? "int" : "unsigned int";
+
+ else if (GETDATASIZEINSN(insn) == WORD)
+ return is_signed ? "signed64" : "unsigned64";
+
+ else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+ return 0;
+
+ /* start-sanitize-r5900 */
+ else if (GETDATASIZEINSN(insn) == QUADWORD)
+ return 0;
+
+ /* end-sanitize-r5900 */
+ else
+ return 0;
+ }
+
+static char*
+max_for_data_len( insn )
+ struct instruction* insn;
+ {
+ if (GETDATASIZEINSN(insn) == BYTE)
+ return "127";
+
+ else if (GETDATASIZEINSN(insn) == HALFWORD)
+ return "32767";
+
+ else if (GETDATASIZEINSN(insn) == WORD)
+ return "(int)0x7FFFFFFF";
+
+ else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+ return 0;
+
+ /* start-sanitize-r5900 */
+ else if (GETDATASIZEINSN(insn) == QUADWORD)
+ return 0;
+
+ /* end-sanitize-r5900 */
+ else
+ return 0;
+ }
+
+static char*
+min_for_data_len( insn )
+ struct instruction* insn;
+ {
+ if (GETDATASIZEINSN(insn) == BYTE)
+ return "-128";
+
+ else if (GETDATASIZEINSN(insn) == HALFWORD)
+ return "-32768";
+
+ else if (GETDATASIZEINSN(insn) == WORD)
+ return "(int)0x80000000";
+
+ else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+ return 0;
+
+ /* start-sanitize-r5900 */
+ else if (GETDATASIZEINSN(insn) == QUADWORD)
+ return 0;
+
+ /* end-sanitize-r5900 */
+ else
+ return 0;
+ }
+
+static char*
+umax_for_data_len( insn )
+ struct instruction* insn;
+ {
+ if (GETDATASIZEINSN(insn) == BYTE)
+ return "0xFF";
+
+ else if (GETDATASIZEINSN(insn) == HALFWORD)
+ return "0xFFFF";
+
+ else if (GETDATASIZEINSN(insn) == WORD)
+ return "0xFFFFFFFF";
+
+ else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+ return 0;
+
+ /* start-sanitize-r5900 */
+ else if (GETDATASIZEINSN(insn) == QUADWORD)
+ return 0;
+
+ /* end-sanitize-r5900 */
+ else
+ return 0;
+ }
+
+static char*
+bits_for_data_len( insn )
+ struct instruction* insn;
+ {
+ if (GETDATASIZEINSN(insn) == BYTE)
+ return "8";
+
+ else if (GETDATASIZEINSN(insn) == HALFWORD)
+ return "16";
+
+ else if (GETDATASIZEINSN(insn) == WORD)
+ return "32";
+
+ else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+ return "64";
+
+ /* start-sanitize-r5900 */
+ else if (GETDATASIZEINSN(insn) == QUADWORD)
+ return "128";
+
+ /* end-sanitize-r5900 */
+ else
+ return 0;
+ }
+