Implement 32 bit MIPS16 instructions listed in m16.igen.
[deliverable/binutils-gdb.git] / sim / mips / gencode.c
index 4df7c589c4751b896420e89d8fd6058b0915abf3..44fac70846184ae1f6075dee127455a43d10f3a8 100644 (file)
 #define FEATURE_WARN_MEM    (1 << 27)   /* 0 = nothing; 1 = generate warnings when memory problems are noticed */
 #define FEATURE_WARN_R31    (1 << 28)   /* 0 = nothing; 1 = generate warnings if r31 used dangerously */
 #define FEATURE_WARN_RESULT (1 << 29)   /* 0 = nothing; 1 = generate warnings when undefined results may occur */
-
+#define FEATURE_IGEN        (1 << 20)   /* 0 = nothing; 1 = generate igen formatted output file */
+
+/* We used to enable FEATURE_WARN_ZERO, but it is perfectly legitimate to
+   have the zero register as a destination -- the zero register just doesn't
+   actually change.  */
+/* start-sanitize-r5900 */
+/* The 5900 madd instructions for example use this feature.  */
+/* end-sanitize-r5900 */
 #if 1
-#define FEATURE_WARNINGS  (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31)
+#define FEATURE_WARNINGS  (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_R31)
 #else
-#define FEATURE_WARNINGS  (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_ZERO | FEATURE_WARN_R31 | FEATURE_WARN_RESULT)
+#define FEATURE_WARNINGS  (FEATURE_WARN_STALL | FEATURE_WARN_LOHI | FEATURE_WARN_R31 | FEATURE_WARN_RESULT)
 #endif
 
 /* FEATURE_WARN_STALL */
@@ -208,6 +215,7 @@ typedef struct operand_encoding {
 #define OP_SIGNX  (1 << 1)      /* Sign-extend the operand */
 #define OP_SHIFT2 (1 << 2)      /* Shift field left by 2 */
 #define OP_BITS5  (1 << 3)      /* Only take the lo 5-bits of the operand */
+#define OP_GPR1   (1 << 4)      /* fetch from the GPR1 registers */
 
 struct operand_encoding opfields[] = {
  {'0',-1,-1,"",      "",              (OP_NONE)},  /* special case for explicit zero */
@@ -240,8 +248,11 @@ struct operand_encoding opfields[] = {
  {'x',23, 1,"int",   "to",            (OP_NONE)},  /* TRUE if move To; FALSE if move From */
  {'y', 0,16,"t_reg", "offset",        (OP_SIGNX)}, /* signed offset */
  {'z', 0,16,"ut_reg","op2",           (OP_NONE)},  /* unsigned immediate (zero extended) */
+ {'S',21, 5,"t_reg", "rs_reg",  (OP_GPR|OP_GPR1)}, /* rs field, GPR[rs] and GPR1[rs] as source */
+ {'T',16, 5,"t_reg", "rt_reg",  (OP_GPR|OP_GPR1)}, /* rt field, GPR[rt] and GPR1[rt] as source */
 };
 
+
 /* Main instruction encoding types: */
 typedef enum {
  NORMAL,
@@ -251,6 +262,12 @@ typedef enum {
  COP1X,
  COP1S, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
 
+ MMINORM,
+ MMI0,
+ MMI1,
+ MMI2,
+ MMI3,
+
  /* mips16 encoding types.  */
  I, RI, RR, RRI, RRR, RRI_A, ISHIFT, I8, I8_MOVR32, I8_MOV32R, I64, RI64
 } inst_type;
@@ -274,6 +291,7 @@ typedef enum {
  SHIFT,                 /* perform a logical or arithmetic shift */
  TRAP,                  /* system exception generation */
  BREAK,                 /* system breakpoint exception generation */
+ SDBBP,                 /* software debug breakpoint exception generation */
  SYSCALL,               /* system exception generation */
  SYNC,                  /* system cache control */
  DECODE,                /* co-processor instruction */
@@ -296,6 +314,55 @@ typedef enum {
  FPSQRT,
  FPCONVERT,
  FPCOMPARE,
+ MADD,
+ /* start-sanitize-r5900 */
+ PABS,
+ PADD,
+ PADSBH,
+ POP,
+ PCMP,
+ PCPYH,
+ PCPYLD,
+ PCPYUD,
+ PEXCH,
+ PEXCW,
+ PEXOH,
+ PEXOW,
+ PEXTLB,
+ PEXTLH,
+ PEXTLW,
+ PEXTUB,
+ PEXTUH,
+ PEXTUW,
+ PPACB,
+ PPACH,
+ PPACW,
+ PREVH,
+ PROT3W,
+ PINTH,
+ PINTOH,
+ PMXX,
+ PMFHL,
+ PMTHL,
+ PMAXMIN,
+ QFSRV,
+ MxSA,
+ MTSAB,
+ MTSAH,
+ PSHIFT,
+ PSLLVW,
+ PSRLVW,
+ PSRAVW,
+ PLZCW,
+ PHMADDH,
+ PMULTH,
+ PMULTW,
+ PDIVBW,
+ PDIVW,
+ PEXT5,
+ PPAC5,
+ /* end-sanitize-r5900 */
+ NYI,                   /* Not Yet Implemented, placeholder, errors if used */
  RSVD                   /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "Reserved Instruction" */
 } opcode_type;
 
@@ -309,9 +376,11 @@ typedef enum {
 #define DOUBLEWORD      (3)     /* 64bit */
 #define SINGLE          (4)     /* single precision FP */
 #define DOUBLE          (5)     /* double precision FP */
+/* start-sanitize-r5900 */
+#define QUADWORD        (6)     /* 128bit */
+/* end-sanitize-r5900 */
 
 /* Shorthand to get the size field from the flags value: */
-#define GETDATASIZE()   ((MIPS_DECODE[loop].flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
 #define GETDATASIZEINSN(i) (((i)->flags >> SIM_SH_SIZE) & SIM_MASK_SIZE)
 
 /* The rest are single bit flags: */
@@ -348,6 +417,28 @@ typedef enum {
    all options are applicable to all instruction types. This will free
    up more space for new flags. */
 
+/* Overloadings of above bits */
+#define PIPE1        LIKELY      /* Using pipeline 1 (DIV,MUL) */
+#define OP3          EQ          /* 3 operand version of operation  (MUL)     */
+
+#define SATURATE     OVERFLOW    /* for PADD, saturate for overflow           */
+
+#define SUBTRACT     LEFT        /* for PMULT, PMULT becomes PMSUB            */
+#define ADDITION     RIGHT       /* for PMULT, PMULT becomes PMADD            */
+
+#define FROM         LEFT        /* move from special register                */
+#define TO           RIGHT       /* move to special register                  */
+
+/* For bitwise parallel operations */ 
+#define POP_AND      0            /* for POP, op = &                           */
+#define POP_OR       LEFT         /* for POP, op = |                           */
+#define POP_NOR      LIKELY       /* for POP, op = ~(x | y)                    */
+#define POP_XOR      LEFT|LIKELY  /* for POP, op = ^                           */
+
+#define GET_OP_FROM_INSN(insn) (((insn)->flags)&(LEFT|LIKELY))
+
+
+   
 typedef struct instruction {
  char         *name;   /* ASCII mnemonic name */
  unsigned int  isa;    /* MIPS ISA number where instruction introduced */
@@ -371,8 +462,102 @@ typedef struct instruction {
    the normal instruction space. */
 #define MASK_ISA (0x000000FF) /* Start by leaving 8bits for the ISA ID */
 /* The other bits are allocated downwards, to avoid renumbering if we
-   have to extend the bits allocated to the pure ISA number. */
+   have to extend the bits allocated to the pure ISA number.
+
+   These architecture bits come in two flavors: 
+     ISA dependent - marking insns that should be included in the opcode 
+     set if that architecture is requested on the gencode command line 
+     AND the ISA of the insn is <= requested ISA; 
+   
+     ISA independent - marking insn that should be included in the opcode
+     set if that architecture is requested 
+     OR the ISA of the insn is <= requested ISA. 
+
+   Independent bits are listed in MASK_ISA_INDEP, the rest are dependent.
+ */
 #define ARCH_VR4100       ((unsigned)1 << 31) /* NEC VR4100 extension instructions */
+/* start-sanitize-r5900 */
+#define ARCH_R5900        ((unsigned)1 << 30) /* Toshiba r5900 extension instructions */
+/* end-sanitize-r5900 */
+#define ARCH_R3900        ((unsigned)1 << 29) /* Toshiba r3900 (tx39) */
+/* start-sanitize-tx49 */
+#define ARCH_R4900        ((unsigned)1 << 28) /* Toshiba r4900 (tx49) */
+/* end-sanitize-tx49 */   
+
+/* start-sanitize-tx19 */
+/* The r1900 (tx19) is a tx39 with a mips16 decoder.  For the purposes
+   of implementing the simulator we treat them as the same. */
+/* end-sanitize-tx19 */
+
+/* A list (or'ed) of extension insn sets that can be requested independant of the ISA# */
+#define MASK_ISA_INDEP  (0                                             \
+                         | ARCH_R3900                                  \
+                         /* start-sanitize-tx49 */                     \
+                         | ARCH_R4900                                  \
+                         /* end-sanitize-tx49 */                       \
+                         /* start-sanitize-r5900 */                    \
+                         | ARCH_R5900                                  \
+                         /* end-sanitize-r5900 */                      \
+                         | 0)
+
+#define MASK_ISA_DEP ~(MASK_ISA_INDEP | MASK_ISA)
+
+/* Very short names for use in the table below to keep it neet. */
+#define G1 (3 | ARCH_VR4100)
+
+#define G2 (4                                        \
+            /* start-sanitize-r5900 */               \
+            | ARCH_R5900                             \
+            /* end-sanitize-r5900 */                 \
+            | 0)
+
+#define G3 (4                                                           \
+            /* start-sanitize-r5900 */                                  \
+            /* insn that are not really 5900 insn but were left in */   \
+            /* until we can rewrite the code-gen and libs          */   \
+            | ARCH_R5900                                                \
+            /* end-sanitize-r5900 */                                    \
+            | 0)
+
+#define G4 (2 | ARCH_R3900)
+
+#define G5 (0                                         \
+            | ARCH_R3900                              \
+            /* start-sanitize-tx49 */                 \
+            | ARCH_R4900                              \
+            /* end-sanitize-tx49 */                   \
+            /* start-sanitize-r5900 */                \
+            | ARCH_R5900                              \
+            /* end-sanitize-r5900 */                  \
+            )
+
+#define G6 (3 | ARCH_R3900)
+
+#define G7 (ARCH_R3900                                \
+            /* start-sanitize-tx49 */                 \
+            | ARCH_R4900                              \
+            /* end-sanitize-tx49 */                   \
+            )
+
+#define G8 (4                                         \
+            /* start-sanitize-tx49 */                 \
+            | ARCH_R4900                              \
+            /* end-sanitize-tx49 */                   \
+            /* start-sanitize-r5900 */                \
+            | ARCH_R5900                              \
+            /* end-sanitize-r5900 */                  \
+            )
+
+#define G9 (3                                         \
+            /* start-sanitize-tx49 */                 \
+            | ARCH_R4900                              \
+            /* end-sanitize-tx49 */                   \
+            )
+
+/* start-sanitize-r5900 */
+#define T5 ARCH_R5900       
+/* end-sanitize-r5900 */
+
 
 /* The HIBERNATE, STANDBY and SUSPEND instructions are encoded in the
    COP0 space. This means that an external decoder should be added
@@ -391,21 +576,21 @@ struct instruction MIPS_DECODE[] = {
  {"ANDI",    1,"001100ssssstttttzzzzzzzzzzzzzzzz",NORMAL, AND,      (NONE)},
  {"BC1",     1,"01000101000qqqfcllllllllllllllll",COP1S,  BRANCH,   (FP)},
  {"BEQ",     1,"000100sssssgggggllllllllllllllll",NORMAL, BRANCH,   (EQ)},
- {"BEQL",    2,"010100sssssgggggllllllllllllllll",NORMAL, BRANCH,   (EQ | LIKELY)},
+ {"BEQL",   G4,"010100sssssgggggllllllllllllllll",NORMAL, BRANCH,   (EQ | LIKELY)},
  {"BGEZ",    1,"000001sssss00001llllllllllllllll",REGIMM, BRANCH,   (GT | EQ)},
  {"BGEZAL",  1,"000001sssss10001llllllllllllllll",REGIMM, BRANCH,   (GT | EQ | LINK)},
- {"BGEZALL", 2,"000001sssss10011llllllllllllllll",REGIMM, BRANCH,   (GT | EQ | LINK)},
- {"BGEZL",   2,"000001sssss00011llllllllllllllll",REGIMM, BRANCH,   (GT | EQ | LIKELY)},
+ {"BGEZALL",G4,"000001sssss10011llllllllllllllll",REGIMM, BRANCH,   (GT | EQ | LINK)},
+ {"BGEZL",  G4,"000001sssss00011llllllllllllllll",REGIMM, BRANCH,   (GT | EQ | LIKELY)},
  {"BGTZ",    1,"000111sssss00000llllllllllllllll",NORMAL, BRANCH,   (GT)},
- {"BGTZL",   2,"010111sssss00000llllllllllllllll",NORMAL, BRANCH,   (GT | LIKELY)},
+ {"BGTZL",  G4,"010111sssss00000llllllllllllllll",NORMAL, BRANCH,   (GT | LIKELY)},
  {"BLEZ",    1,"000110sssss00000llllllllllllllll",NORMAL, BRANCH,   (LT | EQ)},
- {"BLEZL",   2,"010110sssss00000llllllllllllllll",NORMAL, BRANCH,   (LT | EQ | LIKELY)},
+ {"BLEZL",  G4,"010110sssss00000llllllllllllllll",NORMAL, BRANCH,   (LT | EQ | LIKELY)},
  {"BLTZ",    1,"000001sssss00000llllllllllllllll",REGIMM, BRANCH,   (LT)},
  {"BLTZAL",  1,"000001sssss10000llllllllllllllll",REGIMM, BRANCH,   (LT | LINK)},
- {"BLTZALL", 2,"000001sssss10010llllllllllllllll",REGIMM, BRANCH,   (LT | LINK | LIKELY)},
- {"BLTZL",   2,"000001sssss00010llllllllllllllll",REGIMM, BRANCH,   (LT | LIKELY)},
+ {"BLTZALL",G4,"000001sssss10010llllllllllllllll",REGIMM, BRANCH,   (LT | LINK | LIKELY)},
+ {"BLTZL",  G4,"000001sssss00010llllllllllllllll",REGIMM, BRANCH,   (LT | LIKELY)},
  {"BNE",     1,"000101sssssgggggllllllllllllllll",NORMAL, BRANCH,   (NOT | EQ)},
- {"BNEL",    2,"010101sssssgggggllllllllllllllll",NORMAL, BRANCH,   (NOT | EQ | LIKELY)},
+ {"BNEL",   G4,"010101sssssgggggllllllllllllllll",NORMAL, BRANCH,   (NOT | EQ | LIKELY)},
  {"BREAK",   1,"000000????????????????????001101",SPECIAL,BREAK,    (NOARG)},
  {"CEIL.L",  3,"01000110mmm00000vvvvvrrrrr001010",COP1,   FPCEIL,   (FP | FIXED | DOUBLEWORD)},
  {"CEIL.W",  2,"01000110mmm00000vvvvvrrrrr001110",COP1,   FPCEIL,   (FP | FIXED | WORD)},
@@ -425,10 +610,17 @@ struct instruction MIPS_DECODE[] = {
  {"DDIVU",   3,"000000sssssggggg0000000000011111",SPECIAL,DIV,      (DOUBLEWORD | UNSIGNED | HI | LO)},
  {"DIV",     1,"000000sssssggggg0000000000011010",SPECIAL,DIV,      (WORD | WORD32 | SIGNEXTEND | HI | LO)},
  {"DIV",     1,"01000110mmmkkkkkvvvvvrrrrr000011",COP1,   FPDIV,    (FP | WORD | HI | LO)},
+ /* start-sanitize-r5900 */
+ {"DIV1",   T5,"011100sssssggggg0000000000011010",MMINORM,DIV,      (WORD | WORD32 | SIGNEXTEND | HI | LO | PIPE1)},
+ /* end-sanitize-r5900 */
  {"DIVU",    1,"000000sssssggggg0000000000011011",SPECIAL,DIV,      (WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO)},
- {"DMADD16", (ARCH_VR4100 | 3),"000000sssssggggg0000000000101001",SPECIAL,MADD16,   (DOUBLEWORD | HI | LO)},
- {"DMULT",   3,"000000sssssggggg0000000000011100",SPECIAL,MUL,      (DOUBLEWORD | HI | LO)},
- {"DMULTU",  3,"000000sssssggggg0000000000011101",SPECIAL,MUL,      (DOUBLEWORD | UNSIGNED | HI | LO)},
+ /* start-sanitize-r5900 */
+ {"DIVU1",  T5,"011100sssssggggg0000000000011011",MMINORM,DIV,      (WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO | PIPE1)},
+ /* end-sanitize-r5900 */
+ {"DMADD16",G1,"000000sssssggggg0000000000101001",SPECIAL,MADD16,   (DOUBLEWORD | HI | LO)},
+ /* See note near MULT for explanation of 3op-ness. */
+ {"DMULT",  G9,"000000sssssgggggddddd00000011100",SPECIAL,MUL,      (OP3 | DOUBLEWORD | HI | LO)},
+ {"DMULTU", G9,"000000sssssgggggddddd00000011101",SPECIAL,MUL,      (OP3 | DOUBLEWORD | UNSIGNED | HI | LO)},
  {"DMxC1",   3,"01000100x01kkkkkvvvvv00000000000",COP1S,  FPMOVEC,  (FP | DOUBLEWORD)},
  {"DSLL",    3,"00000000000gggggdddddaaaaa111000",SPECIAL,SHIFT,    (DOUBLEWORD | LEFT | LOGICAL)},
  {"DSLLV",   3,"000000sssssgggggddddd00000010100",SPECIAL,SHIFT,    (DOUBLEWORD | LEFT | LOGICAL | REG)},
@@ -455,38 +647,73 @@ struct instruction MIPS_DECODE[] = {
  {"LDC2",    2,"110110sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD,     (DOUBLEWORD | COPROC)},
  {"LDL",     3,"011010ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD,     (DOUBLEWORD | LEFT)},      /* NOTE: See "LB" comment */
  {"LDR",     3,"011011ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD,     (DOUBLEWORD | RIGHT)},     /* NOTE: See "LB" comment */
- {"LDXC1",   4,"010011sssssggggg00000rrrrr000001",COP1X,  LOAD,     (FP | DOUBLEWORD | COPROC | REG)},
+ {"LDXC1",  G3,"010011sssssggggg00000rrrrr000001",COP1X,  LOAD,     (FP | DOUBLEWORD | COPROC | REG)},
  {"LH",      1,"100001sssssttttthhhhhhhhhhhhhhhh",NORMAL, LOAD,     (HALFWORD | SIGNEXTEND)},
  {"LHU",     1,"100101sssssttttthhhhhhhhhhhhhhhh",NORMAL, LOAD,     (HALFWORD)},
  {"LL",      2,"110000ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD,     (WORD | ATOMIC | SIGNEXTEND)},
  {"LLD",     3,"110100sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD,     (DOUBLEWORD | ATOMIC)},
  {"LUI",     1,"00111100000tttttiiiiiiiiiiiiiiii",NORMAL, MOVE,     (SHIFT16)}, /* Cheat and specify sign-extension of immediate field */
+ /* start-sanitize-r5900 */
+ {"LQ",     T5,"011110sssssttttteeeeeeeeeeeeeeee",NORMAL, LOAD,     (QUADWORD)},
+ /* end-sanitize-r5900 */
  {"LW",      1,"100011ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD,     (WORD | SIGNEXTEND)},
  {"LWC1",    1,"110001ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD,     (WORD | COPROC)},
  {"LWC2",    1,"110010ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD,     (WORD | COPROC)},
  {"LWL",     1,"100010ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD,     (WORD | LEFT)},
  {"LWR",     1,"100110ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD,     (WORD | RIGHT)},
  {"LWU",     3,"100111ssssstttttwwwwwwwwwwwwwwww",NORMAL, LOAD,     (WORD)},
- {"LWXC1",   4,"010011sssssggggg00000rrrrr000000",COP1X,  LOAD,     (FP | WORD | COPROC | REG)},
- {"MADD16",  (ARCH_VR4100 | 3),"000000sssssggggg0000000000101000",SPECIAL,MADD16,   (WORD | HI | LO)},
- {"MADD.D",  4,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X,  FPADD,    (FP | MULTIPLY | DOUBLE)},
- {"MADD.S",  4,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X,  FPADD,    (FP | MULTIPLY | SINGLE)},
+ {"LWXC1",  G3,"010011sssssggggg00000rrrrr000000",COP1X,  LOAD,     (FP | WORD | COPROC | REG)},
+ {"MADD",   G5,"011100sssssgggggddddd00000000000",MMINORM,MADD,     (NONE)},
+ {"MADDU",  G5,"011100sssssgggggddddd00000000001",MMINORM,MADD,     (UNSIGNED)},
+ /* start-sanitize-r5900 */
+ {"MADD1",  T5,"011100sssssgggggddddd00000100000",MMINORM,MADD,     (PIPE1)},
+ {"MADDU1", T5,"011100sssssgggggddddd00000100001",MMINORM,MADD,     (UNSIGNED | PIPE1)},
+ /* end-sanitize-r5900 */
+ {"MADD16", G1,"000000sssssggggg0000000000101000",SPECIAL,MADD16,   (WORD | HI | LO)},
+ {"MADD.D", G3,"010011bbbbbkkkkkvvvvvrrrrr100001",COP1X,  FPADD,    (FP | MULTIPLY | DOUBLE)},
+ {"MADD.S", G3,"010011bbbbbkkkkkvvvvvrrrrr100000",COP1X,  FPADD,    (FP | MULTIPLY | SINGLE)},
  {"MFHI",    1,"0000000000000000ddddd00000010000",SPECIAL,MOVE,     (HI | LEFT)},    /* with following, from and to denoted by usage of LEFT or RIGHT */
+ /* start-sanitize-r5900 */
+ {"MFHI1",  T5,"0111000000000000ddddd00000010000",MMINORM,MOVE,     (HI | LEFT | PIPE1)},
+ /* end-sanitize-r5900 */
  {"MFLO",    1,"0000000000000000ddddd00000010010",SPECIAL,MOVE,     (LO | LEFT)},
+ /* start-sanitize-r5900 */
+ {"MFLO1",  T5,"0111000000000000ddddd00000010010",MMINORM,MOVE,     (LO | LEFT | PIPE1)},
+ {"MFSA",   T5,"0000000000000000ddddd00000101000",SPECIAL,MxSA,     (FROM)},
+ /* end-sanitize-r5900 */
  {"MTHI",    1,"000000sssss000000000000000010001",SPECIAL,MOVE,     (HI | RIGHT)},
+ /* start-sanitize-r5900 */
+ {"MTHI1",  T5,"011100sssss000000000000000010001",MMINORM,MOVE,     (HI | RIGHT | PIPE1)},
+ /* end-sanitize-r5900 */
  {"MTLO",    1,"000000sssss000000000000000010011",SPECIAL,MOVE,     (LO | RIGHT)},
+ /* start-sanitize-r5900 */
+ {"MTLO1",  T5,"011100sssss000000000000000010011",MMINORM,MOVE,     (LO | RIGHT | PIPE1)},
+ {"MTSA",   T5,"000000sssss000000000000000101001",SPECIAL,MxSA,     (TO)},
+ {"MTSAB",  T5,"000001sssss11000iiiiiiiiiiiiiiii",REGIMM, MTSAB,    (NONE)},
+ {"MTSAH",  T5,"000001sssss11001iiiiiiiiiiiiiiii",REGIMM, MTSAH,    (NONE)},
+ /* end-sanitize-r5900 */
  {"MOV",     1,"01000110mmm00000vvvvvrrrrr000110",COP1,   FPMOVE,   (FP)},
- {"MOVN",    4,"000000sssssgggggddddd00000001011",SPECIAL,MOVE,     (NOT | EQ)},
- {"MOVN",    4,"01000110mmmgggggvvvvvrrrrr010011",COP1,   FPMOVE,   (FP | NOT | EQ)},
- {"MOV%c",   4,"000000sssssqqq0cddddd00000000001",SPECIAL,FPMOVE,   (FP | CONDITIONAL | INTEGER)},
- {"MOV%c",   4,"01000110mmmqqq0cvvvvvrrrrr010001",COP1,   FPMOVE,   (FP | CONDITIONAL)},
- {"MOVZ",    4,"000000sssssgggggddddd00000001010",SPECIAL,MOVE,     (EQ)},
- {"MOVZ",    4,"01000110mmmgggggvvvvvrrrrr010010",COP1,   FPMOVE,   (FP | EQ)},
- {"MSUB.D",  4,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X,  FPSUB,    (FP | MULTIPLY | DOUBLE)},
- {"MSUB.S",  4,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X,  FPSUB,    (FP | MULTIPLY | SINGLE)},
+ {"MOVN",   G2,"000000sssssgggggddddd00000001011",SPECIAL,MOVE,     (NOT | EQ)},
+ {"MOVN",   G2,"01000110mmmgggggvvvvvrrrrr010011",COP1,   FPMOVE,   (FP | NOT | EQ)},
+ {"MOV%c",  G3,"000000sssssqqq0cddddd00000000001",SPECIAL,FPMOVE,   (FP | CONDITIONAL | INTEGER)},
+ {"MOV%c",  G3,"01000110mmmqqq0cvvvvvrrrrr010001",COP1,   FPMOVE,   (FP | CONDITIONAL)},
+ {"MOVZ",   G2,"000000sssssgggggddddd00000001010",SPECIAL,MOVE,     (EQ)},
+ {"MOVZ",   G2,"01000110mmmgggggvvvvvrrrrr010010",COP1,   FPMOVE,   (FP | EQ)},
+ {"MSUB.D", G3,"010011bbbbbkkkkkvvvvvrrrrr101001",COP1X,  FPSUB,    (FP | MULTIPLY | DOUBLE)},
+ {"MSUB.S", G3,"010011bbbbbkkkkkvvvvvrrrrr101000",COP1X,  FPSUB,    (FP | MULTIPLY | SINGLE)},
  {"MUL",     1,"01000110mmmkkkkkvvvvvrrrrr000010",COP1,   FPMUL,    (FP | HI | LO)},
- {"MULT",    1,"000000sssssggggg0000000000011000",SPECIAL,MUL,      (WORD | WORD32 | HI | LO)},
- {"MULTU",   1,"000000sssssggggg0000000000011001",SPECIAL,MUL,      (WORD | WORD32 | UNSIGNED | HI | LO)},
+ /* The 3op version of MULT and MULTU are TX39 (and related chips) specific.
+    They should be removed from other chips sets, so that using the 3op opcode
+    causes a reserved instruction exception, but gencode can't deal with
+    that currently. */
+ {"MULT",    1,"000000sssssgggggddddd00000011000",SPECIAL,MUL,      (OP3 | WORD | WORD32 | HI | LO)},
+ /* start-sanitize-r5900 */
+ {"MULT1",  T5,"011100sssssgggggddddd00000011000",MMINORM,MUL,      (OP3 | WORD | WORD32 | HI | LO | PIPE1)},
+ /* end-sanitize-r5900 */
+ {"MULTU",   1,"000000sssssgggggddddd00000011001",SPECIAL,MUL,      (OP3 | WORD | WORD32 | UNSIGNED | HI | LO)},
+ /* start-sanitize-r5900 */
+ {"MULTU1", T5,"011100sssssgggggddddd00000011001",MMINORM,MUL,      (OP3 | WORD | WORD32 | UNSIGNED | HI | LO | PIPE1)},
+ /* end-sanitize-r5900 */
  {"MxC1",    1,"01000100x00kkkkkvvvvv00000000000",COP1S,  FPMOVEC,  (FP | WORD)},
  {"NEG",     1,"01000110mmm00000vvvvvrrrrr000111",COP1,   FPNEG,    (FP)},
  {"NMADD.D", 4,"010011bbbbbkkkkkvvvvvrrrrr110001",COP1X,  FPADD,    (FP | NOT | MULTIPLY | DOUBLE)},
@@ -496,8 +723,136 @@ struct instruction MIPS_DECODE[] = {
  {"NOR",     1,"000000sssssgggggddddd00000100111",SPECIAL,OR,       (NOT)},
  {"OR",      1,"000000sssssgggggddddd00000100101",SPECIAL,OR,       (NONE)},
  {"ORI",     1,"001101ssssstttttzzzzzzzzzzzzzzzz",NORMAL, OR,       (NONE)},
- {"PREF",    4,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, PREFETCH, (NONE)},
+
+ /* start-sanitize-r5900 */
+ {"PABSH",  T5,"01110000000TTTTTddddd00101101000",MMI1,   PABS,     (HALFWORD)},
+ {"PABSW",  T5,"01110000000TTTTTddddd00001101000",MMI1,   PABS,     (WORD)},
+
+ {"PADDB",  T5,"011100SSSSSTTTTTddddd01000001000",MMI0,   PADD,     (BYTE)},
+ {"PADDH",  T5,"011100SSSSSTTTTTddddd00100001000",MMI0,   PADD,     (HALFWORD)},
+ {"PADDW",  T5,"011100SSSSSTTTTTddddd00000001000",MMI0,   PADD,     (WORD)},
+
+ {"PADDSB", T5,"011100SSSSSTTTTTddddd11000001000",MMI0,   PADD,     (BYTE | SATURATE)},
+ {"PADDSH", T5,"011100SSSSSTTTTTddddd10100001000",MMI0,   PADD,     (HALFWORD | SATURATE)},
+ {"PADDSW", T5,"011100SSSSSTTTTTddddd10000001000",MMI0,   PADD,     (WORD | SATURATE)},
+
+ {"PADDUB", T5,"011100SSSSSTTTTTddddd11000101000",MMI1,   PADD,     (BYTE | UNSIGNED)},
+ {"PADDUH", T5,"011100SSSSSTTTTTddddd10100101000",MMI1,   PADD,     (HALFWORD | UNSIGNED)},
+ {"PADDUW", T5,"011100SSSSSTTTTTddddd10000101000",MMI1,   PADD,     (WORD | UNSIGNED)},
+
+ {"PADSBH", T5,"011100SSSSSTTTTTddddd00100101000",MMI1,   PADSBH,   (NONE)},
+
+ {"PAND",   T5,"011100SSSSSTTTTTddddd10010001001",MMI2,   POP,      (POP_AND)},
+
+ {"PCEQB",  T5,"011100SSSSSTTTTTddddd01010101000",MMI1,   PCMP,     (EQ | BYTE)},
+ {"PCEQH",  T5,"011100SSSSSTTTTTddddd00110101000",MMI1,   PCMP,     (EQ | HALFWORD)},
+ {"PCEQW",  T5,"011100SSSSSTTTTTddddd00010101000",MMI1,   PCMP,     (EQ | WORD)},
+
+ {"PCGTB",  T5,"011100SSSSSTTTTTddddd01010001000",MMI0,   PCMP,     (GT | BYTE)},
+ {"PCGTH",  T5,"011100SSSSSTTTTTddddd00110001000",MMI0,   PCMP,     (GT | HALFWORD)},
+ {"PCGTW",  T5,"011100SSSSSTTTTTddddd00010001000",MMI0,   PCMP,     (GT | WORD)},
+
+ {"PCPYH",  T5,"01110000000TTTTTddddd11011101001",MMI3,   PCPYH,    (NONE)},
+ {"PCPYLD", T5,"011100SSSSSTTTTTddddd01110001001",MMI2,   PCPYLD,   (NONE)},
+ {"PCPYUD", T5,"011100SSSSSTTTTTddddd01110101001",MMI3,   PCPYUD,   (NONE)},
+
+ {"PDIVBW", T5,"011100SSSSSTTTTT0000011101001001",MMI2,   PDIVBW,   (NONE)},
+ {"PDIVUW", T5,"011100SSSSSTTTTT0000001101101001",MMI3,   PDIVW,    (UNSIGNED)},
+ {"PDIVW",  T5,"011100SSSSSTTTTT0000001101001001",MMI2,   PDIVW,    (NONE)},
+ {"PEXCH",  T5,"01110000000TTTTTddddd11010101001",MMI3,   PEXCH,    (NONE)},
+ {"PEXCW",  T5,"01110000000TTTTTddddd11110101001",MMI3,   PEXCW,    (NONE)},
+ {"PEXOH",  T5,"01110000000TTTTTddddd11010001001",MMI2,   PEXOH,    (NONE)},
+ {"PEXOW",  T5,"01110000000TTTTTddddd11110001001",MMI2,   PEXOW,    (NONE)},
+
+ {"PEXT5",  T5,"01110000000TTTTTddddd11110001000",MMI0,   PEXT5,    (NONE)},
+
+ {"PEXTLB", T5,"011100SSSSSTTTTTddddd11010001000",MMI0,   PEXTLB,   (NONE)},
+ {"PEXTLH", T5,"011100SSSSSTTTTTddddd10110001000",MMI0,   PEXTLH,   (NONE)},
+ {"PEXTLW", T5,"011100SSSSSTTTTTddddd10010001000",MMI0,   PEXTLW,   (NONE)},
+ {"PEXTUB", T5,"011100SSSSSTTTTTddddd11010101000",MMI1,   PEXTUB,   (NONE)},
+ {"PEXTUH", T5,"011100SSSSSTTTTTddddd10110101000",MMI1,   PEXTUH,   (NONE)},
+ {"PEXTUW", T5,"011100SSSSSTTTTTddddd10010101000",MMI1,   PEXTUW,   (NONE)},
+
+ {"PHMADDH",T5,"011100SSSSSTTTTTddddd10001001001",MMI2,   PHMADDH,  (NONE)},
+ {"PHMSUBH",T5,"011100SSSSSTTTTTddddd10101001001",MMI2,   PHMADDH,  (SUBTRACT)},
+
+ {"PINTH",  T5,"011100SSSSSTTTTTddddd01010001001",MMI2,   PINTH,    (NONE)},
+ {"PINTOH", T5,"011100SSSSSTTTTTddddd01010101001",MMI3,   PINTOH,   (NONE)},
+
+ {"PLZCW",  T5,"011100SSSSS00000ddddd00000000100",MMINORM,PLZCW,    (NONE)},
+
+ {"PMADDH", T5,"011100SSSSSTTTTTddddd10000001001",MMI2,   PMULTH,   (ADDITION)},
+ {"PMADDUW",T5,"011100SSSSSTTTTTddddd00000101001",MMI3,   PMULTW,   (ADDITION | UNSIGNED)},
+ {"PMADDW", T5,"011100SSSSSTTTTTddddd00000001001",MMI2,   PMULTW,   (ADDITION)},
+
+ {"PMAXH",  T5,"011100SSSSSTTTTTddddd00111001000",MMI0,   PMAXMIN,  (GT | HALFWORD)},
+ {"PMAXW",  T5,"011100SSSSSTTTTTddddd00011001000",MMI0,   PMAXMIN,  (GT | WORD)},
+
+ {"PMFHI",  T5,"0111000000000000ddddd01000001001",MMI2,   PMXX,     (HI|FROM)},
+ {"PMFLO",  T5,"0111000000000000ddddd01001001001",MMI2,   PMXX,     (LO|FROM)},
+
+ {"PMFHL",  T5,"0111000000000000dddddaaaaa110000",MMINORM,PMFHL,    (NONE)},
+
+ {"PMINH",  T5,"011100SSSSSTTTTTddddd00111101000",MMI1,   PMAXMIN,  (LT | HALFWORD)},
+ {"PMINW",  T5,"011100SSSSSTTTTTddddd00011101000",MMI1,   PMAXMIN,  (LT | WORD)},
+
+ {"PMSUBH", T5,"011100SSSSSTTTTTddddd10100001001",MMI2,   PMULTH,   (SUBTRACT)},
+ {"PMSUBW", T5,"011100SSSSSTTTTTddddd00100001001",MMI2,   PMULTW,   (SUBTRACT)},
+
+ {"PMTHI",  T5,"011100SSSSS000000000001000101001",MMI3,   PMXX,     (HI|TO)},
+ {"PMTLO",  T5,"011100SSSSS000000000001001101001",MMI3,   PMXX,     (LO|TO)},
+
+{"PMTHL.LW",T5,"011100SSSSS000000000000000110001",MMINORM,PMTHL,    (NONE)},
+
+ {"PMULTH", T5,"011100SSSSSTTTTTddddd11100001001",MMI2,   PMULTH,   (NONE)},
+ {"PMULTUW",T5,"011100SSSSSTTTTTddddd01100101001",MMI3,   PMULTW,   (UNSIGNED)},
+ {"PMULTW", T5,"011100SSSSSTTTTTddddd01100001001",MMI2,   PMULTW,   (NONE)},
+
+ {"PNOR",   T5,"011100SSSSSTTTTTddddd10011101001",MMI3,   POP,      (POP_NOR)},
+ {"POR",    T5,"011100SSSSSTTTTTddddd10010101001",MMI3,   POP,      (POP_OR)},
+
+ {"PPAC5",  T5,"01110000000TTTTTddddd11111001000",MMI0,   PPAC5,    (NONE)},
+
+ {"PPACB",  T5,"011100SSSSSTTTTTddddd11011001000",MMI0,   PPACB,    (NONE)},
+ {"PPACH",  T5,"011100SSSSSTTTTTddddd10111001000",MMI0,   PPACH,    (NONE)},
+ {"PPACW",  T5,"011100SSSSSTTTTTddddd10011001000",MMI0,   PPACW,    (NONE)},
+
+ {"PREVH",  T5,"01110000000TTTTTddddd11011001001",MMI2,   PREVH,    (NONE)},
+ {"PROT3W", T5,"01110000000TTTTTddddd11111001001",MMI2,   PROT3W,   (NONE)},
+
+ {"PSLLH",  T5,"01110000000TTTTTdddddaaaaa110100",MMINORM,PSHIFT,   (LEFT | LOGICAL | HALFWORD)},
+ {"PSLLVW", T5,"011100SSSSSTTTTTddddd00010001001",MMI2,   PSLLVW,   (NONE)},
+ {"PSLLW",  T5,"01110000000TTTTTdddddaaaaa111100",MMINORM,PSHIFT,   (LEFT | LOGICAL | WORD)},
+
+ {"PSRAH",  T5,"01110000000TTTTTdddddaaaaa110111",MMINORM,PSHIFT,   (RIGHT | ARITHMETIC | HALFWORD)},
+ {"PSRAVW", T5,"011100SSSSSTTTTTddddd00011101001",MMI3,   PSRAVW,   (NONE)},
+ {"PSRAW",  T5,"01110000000TTTTTdddddaaaaa111111",MMINORM,PSHIFT,   (RIGHT | ARITHMETIC | WORD)},
+
+ {"PSRLH",  T5,"01110000000TTTTTdddddaaaaa110110",MMINORM,PSHIFT,   (RIGHT | LOGICAL | HALFWORD)},
+ {"PSRLVW", T5,"011100SSSSSTTTTTddddd00011001001",MMI2,   PSRLVW,   (NONE)},
+ {"PSRLW",  T5,"01110000000TTTTTdddddaaaaa111110",MMINORM,PSHIFT,   (RIGHT | LOGICAL | WORD)},
+
+ {"PSUBB",  T5,"011100SSSSSTTTTTddddd01001001000",MMI0,   PADD,     (SUBTRACT | BYTE)},
+ {"PSUBH",  T5,"011100SSSSSTTTTTddddd00101001000",MMI0,   PADD,     (SUBTRACT | HALFWORD)},
+ {"PSUBSB", T5,"011100SSSSSTTTTTddddd11001001000",MMI0,   PADD,     (SUBTRACT | SATURATE | BYTE )},
+ {"PSUBSH", T5,"011100SSSSSTTTTTddddd10101001000",MMI0,   PADD,     (SUBTRACT | SATURATE | HALFWORD)},
+ {"PSUBSW", T5,"011100SSSSSTTTTTddddd10001001000",MMI0,   PADD,     (SUBTRACT | SATURATE | WORD)},
+ {"PSUBUB", T5,"011100SSSSSTTTTTddddd11001101000",MMI1,   PADD,     (SUBTRACT | UNSIGNED | BYTE)},
+ {"PSUBUH", T5,"011100SSSSSTTTTTddddd10101101000",MMI1,   PADD,     (SUBTRACT | UNSIGNED | HALFWORD)},
+ {"PSUBUW", T5,"011100SSSSSTTTTTddddd10001101000",MMI1,   PADD,     (SUBTRACT | UNSIGNED | WORD)},
+ {"PSUBW",  T5,"011100SSSSSTTTTTddddd00001001000",MMI0,   PADD,     (SUBTRACT | WORD)},
+
+ {"PXOR",   T5,"011100SSSSSTTTTTddddd10011001001",MMI2,   POP,      (POP_XOR)},
+ /* end-sanitize-r5900 */
+
+ {"PREF",   G8,"110011sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, PREFETCH, (NONE)},
  {"PREFX",   4,"010011sssssgggggvvvvv00000001111",COP1X,  FPPREFX,  (FP)},
+
+ /* start-sanitize-r5900 */
+ {"QFSRV",  T5,"011100SSSSSTTTTTddddd11011101000",MMI1,   QFSRV,    (NONE)},
+ /* end-sanitize-r5900 */
+
  {"RECIP",   4,"01000110mmm00000vvvvvrrrrr010101",COP1,   FPRECIP,  (FP)},
  {"ROUND.L", 3,"01000110mmm00000vvvvvrrrrr001000",COP1,   FPROUND,  (FP | FIXED | DOUBLEWORD)},
  {"ROUND.W", 2,"01000110mmm00000vvvvvrrrrr001100",COP1,   FPROUND,  (FP | FIXED | WORD)},
@@ -507,10 +862,11 @@ struct instruction MIPS_DECODE[] = {
  {"SCD",     3,"111100sssssgggggeeeeeeeeeeeeeeee",NORMAL, STORE,    (DOUBLEWORD | ATOMIC)},
  {"SD",      3,"111111sssssgggggeeeeeeeeeeeeeeee",NORMAL, STORE,    (DOUBLEWORD)},
  {"SDC1",    2,"111101sssssttttteeeeeeeeeeeeeeee",NORMAL, STORE,    (DOUBLEWORD | COPROC)},
+ {"SDBBP",  G7,"000000????????????????????001110",SPECIAL,SDBBP,    (NOARG)},
  {"SDC2",    2,"111110sssssttttteeeeeeeeeeeeeeee",NORMAL, STORE,    (DOUBLEWORD | COPROC)},
  {"SDL",     3,"101100sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE,    (DOUBLEWORD | LEFT)},
  {"SDR",     3,"101101sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE,    (DOUBLEWORD | RIGHT)},
- {"SDXC1",   4,"010011sssssgggggvvvvv00000001001",COP1X,  STORE,    (FP | DOUBLEWORD | COPROC | REG)},
+ {"SDXC1",  G3,"010011sssssgggggvvvvv00000001001",COP1X,  STORE,    (FP | DOUBLEWORD | COPROC | REG)},
  {"SH",      1,"101001sssssggggghhhhhhhhhhhhhhhh",NORMAL, STORE,    (HALFWORD)},
  {"SLL",     1,"00000000000gggggdddddaaaaa000000",SPECIAL,SHIFT,    (WORD | LEFT | LOGICAL)}, /* rd = rt << sa */
  {"SLLV",    1,"000000ooooogggggddddd00000000100",SPECIAL,SHIFT,    (WORD | LEFT | LOGICAL)}, /* rd = rt << rs - with "SLL" depends on "s" and "a" field values */
@@ -518,6 +874,9 @@ struct instruction MIPS_DECODE[] = {
  {"SLTI",    1,"001010ssssstttttiiiiiiiiiiiiiiii",NORMAL, SET,      (LT)},
  {"SLTU",    1,"000000sssssgggggddddd00000101011",SPECIAL,SET,      (LT | UNSIGNED)},
  {"SLTIU",   1,"001011ssssstttttiiiiiiiiiiiiiiii",NORMAL, SET,      (LT | UNSIGNED)},
+ /* start-sanitize-r5900 */
+ {"SQ",     T5,"011111sssssTTTTTeeeeeeeeeeeeeeee",NORMAL, STORE,    (QUADWORD)},
+ /* end-sanitize-r5900 */
  {"SQRT",    2,"01000110mmm00000vvvvvrrrrr000100",COP1,   FPSQRT,   (FP)},
  {"SRA",     1,"00000000000gggggdddddaaaaa000011",SPECIAL,SHIFT,    (WORD | WORD32 | RIGHT | ARITHMETIC)},
  {"SRAV",    1,"000000ooooogggggddddd00000000111",SPECIAL,SHIFT,    (WORD | WORD32 | RIGHT | ARITHMETIC)},
@@ -531,8 +890,8 @@ struct instruction MIPS_DECODE[] = {
  {"SWC2",    1,"111010ssssstttttwwwwwwwwwwwwwwww",NORMAL, STORE,    (WORD | COPROC)},
  {"SWL",     1,"101010sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE,    (WORD | LEFT)},
  {"SWR",     1,"101110sssssgggggyyyyyyyyyyyyyyyy",NORMAL, STORE,    (WORD | RIGHT)},
- {"SWXC1",   4,"010011sssssgggggvvvvv00000001000",COP1X,  STORE,    (FP | WORD | COPROC | REG)},
- {"SYNC",    2,"000000000000000000000aaaaa001111",SPECIAL,SYNC,     (NONE)}, /* z = 5bit stype field */
+ {"SWXC1",  G3,"010011sssssgggggvvvvv00000001000",COP1X,  STORE,    (FP | WORD | COPROC | REG)},
+ {"SYNC",   G4,"000000000000000000000aaaaa001111",SPECIAL,SYNC,     (NONE)}, /* z = 5bit stype field */
  {"SYSCALL", 1,"000000????????????????????001100",SPECIAL,SYSCALL,  (NOARG)},
  {"TEQ",     2,"000000sssssggggg??????????110100",SPECIAL,TRAP,     (EQ)},
  {"TEQI",    2,"000001sssss01100iiiiiiiiiiiiiiii",REGIMM, TRAP,     (EQ)},
@@ -550,7 +909,7 @@ struct instruction MIPS_DECODE[] = {
  {"TRUNC.W", 2,"01000110mmm00000vvvvvrrrrr001101",COP1,   FPTRUNC,  (FP | FIXED | WORD)},
  {"XOR",     1,"000000sssssgggggddddd00000100110",SPECIAL,XOR,      (NONE)},
  {"XORI",    1,"001110ssssstttttzzzzzzzzzzzzzzzz",NORMAL, XOR,      (NONE)},
- {"CACHE",   3,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, CACHE,    (NONE)},
+ {"CACHE",  G6,"101111sssssnnnnnyyyyyyyyyyyyyyyy",NORMAL, CACHE,    (NONE)},
  {"<INT>",   1,"111011sssssgggggyyyyyyyyyyyyyyyy",NORMAL, RSVD,     (NONE)},
 };
 
@@ -622,6 +981,7 @@ static const struct instruction MIPS16_DECODE[] = {
 {"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 },
@@ -639,10 +999,196 @@ static const struct instruction MIPS16_DECODE[] = {
 {"SUBU",    1, "11100xxxyyyddd11",  RRR,     SUB,     WORD | WORD32 },
 {"SW",      1, "11011xxxyyyWWWWW",  RRI,     STORE,   WORD },
 {"SWSP",    1, "11010yyyVVVVVVVVs", RI,      STORE,   WORD },
-{"SWRASP",  1, "01100010VVVVVVVVQs", 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
@@ -650,15 +1196,190 @@ static void build_instruction
 
 /*---------------------------------------------------------------------------*/
 
-/* We use the letter ordinal as the bit-position in our flags field: */
-#define fieldval(l)     (1 << ((l) - 'a'))
+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";
 
-unsigned int
+    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;
+  }
+
+/*---------------------------------------------------------------------------*/
+
+
+void
 convert_bitmap(bitmap,onemask,zeromask,dontmask)
      char *bitmap;
      unsigned int *onemask, *zeromask, *dontmask;
 {
-  unsigned int flags = 0x00000000;
   int loop; /* current bitmap position */
   int lastsp = -1; /* last bitmap field starting position */
   int lastoe = -1; /* last bitmap field encoding */
@@ -707,12 +1428,11 @@ convert_bitmap(bitmap,onemask,zeromask,dontmask)
          {
            if (opfields[oefield].fpos != -1) {
              /* If flag not set, then check starting position: */
-             if (!(flags & fieldval(bitmap[31 - loop]))) {
+             if (lastoe != oefield) {
                if (loop != opfields[oefield].fpos) {
                  fprintf(stderr,"Bitmap field '%c' (0x%02X) at wrong offset %d in bitmap \"%s\"\n",(((bitmap[31 - loop] < 0x20) || (bitmap[31 - loop] >= 0x7F)) ? '.' : bitmap[31 - loop]),bitmap[31 - loop],loop,bitmap);
                  exit(4);
                }
-               flags |= fieldval(bitmap[31 - loop]);
                lastsp = loop;
                lastoe = oefield;
              }
@@ -730,8 +1450,6 @@ convert_bitmap(bitmap,onemask,zeromask,dontmask)
  /* NOTE: Since we check for the position and size of fields when
     parsing the "bitmap" above, we do *NOT* need to check that invalid
     field combinations have been used. */
-
- return(flags);
 }
 
 /* Get the value of a 16 bit bitstring for a given shift count and
@@ -766,41 +1484,169 @@ bitmap_val (bitmap, shift, bits)
 /*---------------------------------------------------------------------------*/
 
 static void
-build_operands(flags)
-     unsigned int flags;
+build_operands(doisa,features,insn)
+     int doisa;
+     unsigned int features;
+     instruction* insn;
 {
-  int loop;
-  for (loop = 0; (loop < (sizeof(opfields) / sizeof(operand_encoding))); loop++)
-   if ((opfields[loop].fpos != -1) && (flags & fieldval(opfields[loop].id))) {
-     printf("  %s %s = ",opfields[loop].type,opfields[loop].name);
+  int proc64 = ((features & FEATURE_PROC32) ? 0 : -1);
+  int finish_jump_flag = 0;
+  int check_mult = 0;
+  int check_condition_code = 0;
+  int sfield_used = 0;
+  int gfield_used = 0;
+  int any_operand = 0;
 
-     if (opfields[loop].flags & OP_SIGNX)
-      printf("SIGNEXTEND((%s)",opfields[loop].type);
+  int current_field_id = -1;
+  int bitpos;
 
-     if (opfields[loop].flags & OP_GPR)
-      printf("GPR[");
+  for (bitpos=0; bitpos<32; bitpos++) {
+    if (insn->bitmap[31-bitpos] != current_field_id)
+      {
+        int opindex;
 
-     if (opfields[loop].flags & OP_SHIFT2)
-      printf("(");
+        current_field_id = insn->bitmap[31-bitpos];
 
-     printf("((instruction >> %d) & 0x%08X)",opfields[loop].fpos,((1 << opfields[loop].flen) - 1));
+        for (opindex = 0; (opindex < (sizeof(opfields) / sizeof(operand_encoding))); opindex++)
+          if ((opfields[opindex].fpos != -1) && (opfields[opindex].id == insn->bitmap[31-bitpos])) {
 
-     if (opfields[loop].flags & OP_SHIFT2)
-      printf(" << 2)");
+            any_operand = 1;
 
-     if (opfields[loop].flags & OP_GPR)
-      printf("]");
+            printf("  %s %s UNUSED = ",opfields[opindex].type,opfields[opindex].name);
 
-     if (opfields[loop].flags & OP_BITS5)
-      printf("&0x1F");
+            if (opfields[opindex].flags & OP_SIGNX)
+              printf("SIGNEXTEND((%s)",opfields[opindex].type);
 
-     if (opfields[loop].flags & OP_SIGNX)
-      printf(",%d)",(opfields[loop].flen + ((opfields[loop].flags & OP_SHIFT2) ? 2 : 0)));
+            if (opfields[opindex].flags & OP_GPR)
+              printf("GPR[");
 
-     printf(";\n");
-   }
+            if (opfields[opindex].flags & OP_SHIFT2)
+              printf("(");
 
- return;
+            printf("((instruction >> %d) & 0x%08X)",opfields[opindex].fpos,((1 << opfields[opindex].flen) - 1));
+
+            if (opfields[opindex].flags & OP_SHIFT2)
+              printf(" << 2)");
+
+            if (opfields[opindex].flags & OP_GPR)
+              printf("]");
+
+            if (opfields[opindex].flags & OP_BITS5)
+              printf("&0x1F");
+
+            if (opfields[opindex].flags & OP_SIGNX)
+              printf(",%d)",(opfields[opindex].flen + ((opfields[opindex].flags & OP_SHIFT2) ? 2 : 0)));
+
+            printf(";\n");
+
+            if (opfields[opindex].flags & OP_GPR1)
+              {
+                printf("  %s %s1 = GPR1[",opfields[opindex].type,opfields[opindex].name);
+                printf("((instruction >> %d) & 0x%08X)",
+                       opfields[opindex].fpos,
+                       ((1 << opfields[opindex].flen) - 1));
+              printf("];\n");
+              }
+
+            if (opfields[opindex].id == 'j')
+              finish_jump_flag = 1;
+
+            if (opfields[opindex].id == 'e')
+              check_mult = 8;
+            
+            if (opfields[opindex].id == 'w')
+              check_mult = 4;
+
+            if (opfields[opindex].id == 'w')
+              check_mult = 2;
+
+            if (opfields[opindex].id == 'p')
+              check_condition_code = 1;
+
+            if (opfields[opindex].id == 's')
+              sfield_used = 1;
+
+            if (opfields[opindex].id == 'g')
+              gfield_used = 1;
+          }
+      }
+  }
+
+  if ( !any_operand && !(insn->flags & NOARG)) {
+    fprintf(stderr,"Bitmap error: Instruction with no operand fields \"%s\"\n",insn->name) ;
+    exit(5) ;
+  }
+
+  /* Finish constructing the jump address if required: */
+  if (finish_jump_flag)
+    printf("  op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
+
+  /* Now perform required operand checks: */
+
+  /* The following code has been removed, since it seems perfectly
+     reasonable to have a non-aligned offset that is added to another
+     non-aligned base to create an aligned address. Some more
+     information on exactly what the MIPS IV specification requires is
+     needed before deciding on the best strategy. Experimentation with a
+     VR4300 suggests that we do not need to raise the warning. */
+#if 0
+  /* For MIPS IV (and onwards), certain instruction operand values
+     will give undefined results. For the simulator we could
+     generate explicit exceptions (i.e. ReservedInstruction) to
+     make it easier to spot invalid use. However, for the moment we
+     just raise a warning. NOTE: This is a different check to the
+     later decoding, which checks for the final address being
+     valid. */
+     
+  if (check_mult != 0 && check_mult != 1) {
+    printf("  if (instruction & 0x%1X)\n", check_mult);
+    printf("  {\n");
+    /* NOTE: If we change this to a SignalException(), we must
+       ensure that the following opcode processing is not
+       executed. i.e. the code falls straight out to the simulator
+       control loop. */
+    printf("   sim_io_eprintf(sd,\"Instruction has lo-order offset bits set in instruction\\n\");\n");
+    printf("  }\n");
+  }
+#endif
+
+  /* The extended condition codes only appeared in ISA IV */
+  if (check_condition_code && (doisa < 4)) {
+    printf("  if (condition_code != 0)\n");
+    printf("  {\n");
+    printf("   SignalException(ReservedInstruction,instruction);\n");
+    printf("  }\n");
+    printf("  else\n");
+  }
+  
+  if ((insn->flags & WORD32) && (GETDATASIZEINSN(insn) != WORD)) {
+    fprintf(stderr,"Error in opcode table: WORD32 set for non-WORD opcode\n");
+    exit(1);
+  }
+  
+#if 1
+  /* The R4000 book differs slightly from the MIPS IV ISA
+     manual. An example is the sign-extension of a 64-bit processor
+     SUBU operation, and what is meant by an Undefined Result. This
+     is now provided purely as a warning. After examining a HW
+     implementation, this is now purely a warning... and the actual
+     operation is performed, with possibly undefined results. */
+  if (((insn->flags & WORD32) && proc64) && (features & FEATURE_WARN_RESULT)) {
+    /* The compiler should optimise out an OR with zero */
+    printf("  if (%s | %s)\n",(sfield_used ? "NOTWORDVALUE(op1)" : "0"),(gfield_used ? "NOTWORDVALUE(op2)" : "0"));
+    printf("   UndefinedResult();\n") ;
+  }
+#else
+  /* Check that the source is a 32bit value */
+  if ((insn->flags & WORD32) && proc64) {
+    /* The compiler should optimise out an OR with zero */
+    printf("  if (%s | %s)\n",(sfield_used ? "NOTWORDVALUE(op1)" : "0"),(gfield_used ? "NOTWORDVALUE(op2)" : "0"));
+    printf("   UndefinedResult();\n") ;
+    printf("  else\n") ;
+  }
+#endif
+
+  return;
 }
 
 /* The mips16 operand table.  */
@@ -954,10 +1800,10 @@ build_mips16_operands (bitmap)
            {
              int j;
 
-             printf ("PC & ~ (uword64) 1");
+             printf ("((INDELAYSLOT () ? (INJALDELAYSLOT () ? cia - 4 : cia - 2) : (have_extendval ? cia - 2 : cia)) & ~ (uword64) 1)");
              for (j = 0; j < opindex; j++)
                if (ops[j]->shift != 0)
-                 printf (" & 0x%x", ~ ((1 << op->shift) - 1));
+                 printf (" & ~ (uword64) 0x%x", (1 << ops[j]->shift) - 1);
            }
          else if ((op->flags & MIPS16_ZERO) != 0)
            printf ("0");
@@ -1054,7 +1900,7 @@ build_mips16_operands (bitmap)
       if ((op->flags & MIPS16_JUMP_ADDR) != 0)
        {
          printf ("  {\n");
-         printf ("    uword64 paddr;\n");
+         printf ("    address_word paddr;\n");
          printf ("    int uncached;\n");
          printf ("    if (AddressTranslation (PC &~ (uword64) 1, isINSTRUCTION, isLOAD, &paddr, &uncached, isTARGET, isREAL))\n");
          printf ("      {\n");
@@ -1063,7 +1909,7 @@ build_mips16_operands (bitmap)
          printf ("        unsigned int bigend = (BigEndianCPU ? 3 : 0);\n");
          printf ("        unsigned int byte;\n");
          printf ("        paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (reverse << 1)));\n");
-         printf ("        memval = LoadMemory (uncached, AccessLength_HALFWORD, paddr, PC, isINSTRUCTION, isREAL);\n");
+         printf ("        LoadMemory (&memval,0,uncached, AccessLength_HALFWORD, paddr, PC, isINSTRUCTION, isREAL);\n");
          printf ("        byte = (((PC &~ (uword64) 1) & 0x7) ^ (bigend << 1));\n");
          printf ("        memval = (memval >> (8 * byte)) & 0xffff;\n");
          printf ("        %s = (((%s & 0x1f) << 23)\n", op->name, op->name);
@@ -1098,7 +1944,7 @@ build_endian_shift(proc64,datalen,endbit,direction,shift)
      e_endshift direction;
      int shift;
 {
-  if (proc64 && (datalen == 4)) {
+  if (datalen == 4) {
     printf("    if ((vaddr & (1 << %d)) ^ (BigEndianCPU << %d)) {\n",endbit,endbit);
     printf("     memval %s= %d;\n",direction == s_left ? "<<" : ">>",shift);
     printf("    }\n");
@@ -1148,99 +1994,151 @@ process_instructions(doarch,features)
   if (doisa == 0)
    doisa = maxisa;
 
-  printf("#if defined(SIM_MANIFESTS)\n");
-  printf("#define MIPSISA (%d)\n",doisa);
-  if (proc64)
-   printf("#define PROCESSOR_64BIT (1 == 1)\n");
-  else
-   printf("#define PROCESSOR_64BIT (1 == 0)\n");
+  if (!(features & FEATURE_IGEN))
+    {
+      printf("#if defined(SIM_MANIFESTS)\n");
+      printf("#define MIPSISA (%d)\n",doisa);
+      if (proc64)
+       printf("#define PROCESSOR_64BIT (1 == 1)\n");
+      else
+       printf("#define PROCESSOR_64BIT (1 == 0)\n");
 #if 1 /* cheat: We only have a 64bit LoadMemory and StoreMemory routines at the moment */
-  printf("#define LOADDRMASK (0x%08X)\n",0x7);
+      printf("#define LOADDRMASK (0x%08X)\n",0x7);
 #else
-  printf("#define LOADDRMASK (0x%08X)\n",(proc64 ? 0x7 : 0x3));
+      printf("#define LOADDRMASK (0x%08X)\n",(proc64 ? 0x7 : 0x3));
 #endif
-  /* The FP registers are the same width as the CPU registers: */
-  printf("#define GPRLEN (%d)\n",gprlen);
-  printf("typedef %s t_reg;\n",((gprlen == 64) ? "word64" : "int"));
-  printf("typedef %s ut_reg;\n",((gprlen == 64) ? "uword64" : "unsigned int"));
-  printf("typedef %s t_fpreg;\n",((gprlen == 64) ? "word64" : "int"));
-  if (dofp)
-   printf("#define HASFPU (1 == 1)\n");
-  if (features & FEATURE_FAST)
-   printf("#define FASTSIM (1 == 1)\n");
-  if (features & FEATURE_WARN_STALL)
-   printf("#define WARN_STALL (1 == 1)\n");
-  if (features & FEATURE_WARN_LOHI)
-   printf("#define WARN_LOHI (1 == 1)\n");
-  if (features & FEATURE_WARN_ZERO)
-   printf("#define WARN_ZERO (1 == 1)\n");
-  if (features & FEATURE_WARN_MEM)
-   printf("#define WARN_MEM (1 == 1)\n");
-  if (features & FEATURE_WARN_R31)
-   printf("#define WARN_R31 (1 == 1)\n");
-  if (features & FEATURE_WARN_RESULT)
-   printf("#define WARN_RESULT (1 == 1)\n");
-
-  printf("#else /* simulator engine */\n");
-
-  printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
-  printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64 ? 64 : 32),doisa,limit);
-  if (dofp)
-   printf("/* %sFP instructions included */\n",(fpsingle ? "Single precision " : ""));
-  printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
-
- if (proc64) {
-   printf("#if !defined(PROCESSOR_64BIT)\n");
-   printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
-   printf("#endif\n");
- }
-
- printf("/* Actual instruction decoding block */\n");
- printf("if ((vaddr & 1) == 0){\n");
-  {
-    int limit;
-    printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP,OP_MASK_OP);
-    limit = (OP_MASK_OP + 1);
-    printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
-    limit += (OP_MASK_SPEC + 1);
-    printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_RT,OP_MASK_RT);
-    limit += (OP_MASK_RT + 1);
-    printf("else if (num == 0x11) {\n");
-    printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM,OP_SH_COP1NORM,(OP_MASK_COP1NORM << OP_SH_COP1NORM));
-    printf("  if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP,OP_SH_COP1CMP,(OP_MASK_COP1CMP << OP_SH_COP1CMP));
-    printf("   num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,(OP_MASK_SPEC & (OP_MASK_COP1CMP << OP_SH_COP1CMP)));
-    printf("  else\n");
-    printf("   num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
-    limit += (OP_MASK_SPEC + 1);
-    printf(" else\n");
-    /* To keep this code quick, we just clear out the "to" bit
-       here. The proper (though slower) code would be to have another
-       conditional, checking whether this instruction is a branch or
-       not, before limiting the range to the bottom two bits of the
-       move operation. */
-    printf("  num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit,OP_SH_COP1SPEC,OP_MASK_COP1SPEC,OP_MASK_COP1SCLR);
-    limit += (OP_MASK_COP1SPEC + 1);
-    printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
-    limit += (OP_MASK_SPEC + 1);
-    printf("/* Total possible switch entries: %d */\n",limit) ;
-  }
- printf("switch (num)\n") ;
- printf("{\n");
-
+      /* The FP registers are the same width as the CPU registers: */
+      printf("#define GPRLEN (%d)\n",gprlen);
+      printf("typedef %s t_reg;\n",((gprlen == 64) ? "word64" : "int"));
+      printf("typedef %s ut_reg;\n",((gprlen == 64) ? "uword64" : "unsigned int"));
+      printf("typedef %s t_fpreg;\n",((gprlen == 64) ? "word64" : "int"));
+      if (dofp)
+       printf("#define HASFPU (1 == 1)\n");
+      if (features & FEATURE_FAST)
+       printf("#define FASTSIM (1 == 1)\n");
+      if (features & FEATURE_WARN_STALL)
+       printf("#define WARN_STALL (1 == 1)\n");
+      if (features & FEATURE_WARN_LOHI)
+       printf("#define WARN_LOHI (1 == 1)\n");
+      if (features & FEATURE_WARN_ZERO)
+       printf("#define WARN_ZERO (1 == 1)\n");
+      if (features & FEATURE_WARN_MEM)
+       printf("#define WARN_MEM (1 == 1)\n");
+      if (features & FEATURE_WARN_R31)
+       printf("#define WARN_R31 (1 == 1)\n");
+      if (features & FEATURE_WARN_RESULT)
+       printf("#define WARN_RESULT (1 == 1)\n");
+      
+      printf("#else /* simulator engine */\n");
+      
+      printf("/* Engine generated by \"%s\" at %s */\n","<SHOW PROGRAM ARGS>","<SHOW CURRENT DATE AND TIME>");
+      printf("/* Main instruction decode for %d-bit MIPS ISA %d (Table entry limit = %d) */\n",(proc64 ? 64 : 32),doisa,limit);
+      if (dofp)
+       printf("/* %sFP instructions included */\n",(fpsingle ? "Single precision " : ""));
+      printf("/* NOTE: \"DSPC\" is the delay slot PC address */\n");
+      
+      if (proc64) {
+       printf("#if !defined(PROCESSOR_64BIT)\n");
+       printf("#error \"Automatically constructed decoder has been built for a 64bit processor\"\n");
+       printf("#endif\n");
+      }
+      
+      printf("/* Actual instruction decoding block */\n");
+      printf("if ((vaddr & 1) == 0){\n");
+      {
+       int limit;
+       printf("int num = ((instruction >> %d) & 0x%08X);\n",OP_SH_OP,OP_MASK_OP);
+       limit = (OP_MASK_OP + 1);
+       
+       printf("#ifdef DEBUG\n");
+       printf("printf(\"DBG: instruction = 0x%%08X\\n\",instruction);\n");
+       printf("#endif\n");
+       
+       printf("if (num == 0x00) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
+       limit += (OP_MASK_SPEC + 1);
+       
+       printf("else if (num == 0x01) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_RT,OP_MASK_RT);
+       limit += (OP_MASK_RT + 1);
+       
+       printf("else if (num == 0x11) {\n");
+       printf(" if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1NORM,OP_SH_COP1NORM,(OP_MASK_COP1NORM << OP_SH_COP1NORM));
+       printf("  if ((instruction & (0x%08X << %d)) == 0x%08X)\n",OP_MASK_COP1CMP,OP_SH_COP1CMP,(OP_MASK_COP1CMP << OP_SH_COP1CMP));
+       printf("   num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,(OP_MASK_SPEC & (OP_MASK_COP1CMP << OP_SH_COP1CMP)));
+       printf("  else\n");
+       printf("   num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
+       limit += (OP_MASK_SPEC + 1);
+       
+       printf(" else\n");
+       /* To keep this code quick, we just clear out the "to" bit
+          here. The proper (though slower) code would be to have another
+          conditional, checking whether this instruction is a branch or
+          not, before limiting the range to the bottom two bits of the
+          move operation. */
+       printf("  num = (%d + (((instruction >> %d) & 0x%08X) & ~0x%08X));\n",limit,OP_SH_COP1SPEC,OP_MASK_COP1SPEC,OP_MASK_COP1SCLR);
+       limit += (OP_MASK_COP1SPEC + 1);
+       
+       printf("} else if (num == 0x13) num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_SPEC,OP_MASK_SPEC);
+       limit += (OP_MASK_SPEC + 1);
+       
+       printf("else if (num == 0x1C) {\n");
+       printf("  int mmi_func = ((instruction >> %d) & 0x%08X);\n",OP_SH_MMI,OP_MASK_MMI);
+       
+       printf("  if (mmi_func == 0x08) \n");
+       printf("    num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
+       limit += (OP_MASK_MMISUB + 1);
+       
+       printf("  else if (mmi_func == 0x28) \n");
+       printf("    num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
+       limit += (OP_MASK_MMISUB + 1);
+       
+       printf("  else if (mmi_func == 0x09) \n");
+       printf("    num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
+       limit += (OP_MASK_MMISUB + 1);
+       
+       printf("  else if (mmi_func == 0x29) \n");
+       printf("    num = (%d + ((instruction >> %d) & 0x%08X));\n",limit,OP_SH_MMISUB,OP_MASK_MMISUB);
+       limit += (OP_MASK_MMISUB + 1);
+       
+       printf("  else \n");
+       printf("    num = (%d + mmi_func);\n",limit);
+       limit += (OP_MASK_MMI + 1);
+       
+       printf("}\n");
+       
+       printf("/* Total possible switch entries: %d */\n",limit) ;
+      }
+      
+      printf("#ifdef DEBUG\n");
+      printf("printf(\"DBG: num = %%d\\n\",num);\n");
+      printf("#endif\n");
+      
+      printf("switch (num)\n") ;
+      printf("{\n");
+    }      
+      
  for (loop = 0; (loop < limit); loop++) {
-   /* First check that the ISA number we are constructing for is
-      valid, before checking if the instruction matches any of the
+   /* First check if the insn is in a requested isa# independent set,
+      then check that the ISA number we are constructing for is
+      valid, then if the instruction matches any of the
       architecture specific flags. NOTE: We allow a selected ISA of
       zero to be used to match all standard instructions. */
-   if ((((MIPS_DECODE[loop].isa & MASK_ISA) <= doisa) && (((MIPS_DECODE[loop].isa & ~MASK_ISA) == 0) || ((MIPS_DECODE[loop].isa & ~MASK_ISA) & doarch) != 0)) && (!(MIPS_DECODE[loop].flags & FP) || ((MIPS_DECODE[loop].flags & FP) && dofp))) {
+   unsigned int isa = MIPS_DECODE[loop].isa;
+   if (((isa & doarch & MASK_ISA_INDEP)
+        || (((isa & MASK_ISA) <= doisa) 
+            && (((isa & MASK_ISA_DEP) == 0) || ((isa & MASK_ISA_DEP) & doarch) != 0)))
+       && (!(MIPS_DECODE[loop].flags & FP) || ((MIPS_DECODE[loop].flags & FP) && dofp))
+       || (features & FEATURE_IGEN)) {
      unsigned int onemask;
      unsigned int zeromask;
      unsigned int dontmask;
      unsigned int mask;
      unsigned int number;
-     unsigned int flags = convert_bitmap(MIPS_DECODE[loop].bitmap,&onemask,&zeromask,&dontmask);
 
-     if (!(MIPS_DECODE[loop].flags & COPROC) && ((GETDATASIZE() == DOUBLEWORD) && !proc64)) {
+     convert_bitmap(MIPS_DECODE[loop].bitmap,&onemask,&zeromask,&dontmask);
+
+     if (!(MIPS_DECODE[loop].flags & COPROC) 
+         && ((GETDATASIZEINSN(&MIPS_DECODE[loop]) == DOUBLEWORD) && !proc64)
+         && !(features & FEATURE_IGEN)) {
        fprintf(stderr,"DOUBLEWORD width specified for non 64-bit processor for instruction \"%s\"\n",MIPS_DECODE[loop].name);
        exit(4);
      }
@@ -1282,34 +2180,93 @@ process_instructions(doarch,features)
         number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1)) + ((onemask >> OP_SH_SPEC) & OP_MASK_SPEC)) ;
         break ;
 
+       case MMI0 :
+        mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
+                | (OP_MASK_MMISUB << OP_SH_MMISUB));
+        number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) 
+           + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
+           + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
+        break ;
+
+       case MMI1 :
+        mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
+                | (OP_MASK_MMISUB << OP_SH_MMISUB));
+        number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) 
+           + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
+           + (OP_MASK_MMISUB + 1)
+           + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
+        break ;
+
+       case MMI2 :
+        mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
+                | (OP_MASK_MMISUB << OP_SH_MMISUB));
+        number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) 
+           + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
+           + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1)
+           + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
+        break ;
+
+       case MMI3 :
+        mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)
+                | (OP_MASK_MMISUB << OP_SH_MMISUB));
+        number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) 
+           + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
+           + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1)
+           + ((onemask >> OP_SH_MMISUB) & OP_MASK_MMISUB)) ;
+        break ;
+
+       case MMINORM :
+        mask = ((OP_MASK_OP << OP_SH_OP) | (OP_MASK_MMI << OP_SH_MMI)) ;
+        number = (((OP_MASK_OP + 1) + (OP_MASK_SPEC + 1) + (OP_MASK_RT + 1) 
+           + (OP_MASK_SPEC + 1) + (OP_MASK_COP1SPEC + 1) + (OP_MASK_SPEC + 1))
+           + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1) + (OP_MASK_MMISUB + 1)
+           + (OP_MASK_MMISUB + 1) 
+           + ((onemask >> OP_SH_MMI) & OP_MASK_MMI)) ;
+        break ;
+
        default :
         fprintf(stderr,"Unrecognised opcode mark %d in table slot %d \"%s\"\n",MIPS_DECODE[loop].mark,loop,MIPS_DECODE[loop].name) ;
         exit(5) ;
       }
-
-     printf("case %d : /* \"%s\" %s */\n",number,MIPS_DECODE[loop].name,MIPS_DECODE[loop].bitmap) ;
-
+     
+     if (!(features & FEATURE_IGEN))
+       {
+        printf("case %d : /* \"%s\" %s */\n",number,MIPS_DECODE[loop].name,MIPS_DECODE[loop].bitmap) ;
+        
 #if defined(DEBUG)
-     printf("/* DEBUG: mask 0x%08X */\n",mask) ;
-     printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE[loop].name);
+        printf("/* DEBUG: mask 0x%08X */\n",mask) ;
+        printf(" printf(\"\\\"%s\\\"\\n\");\n",MIPS_DECODE[loop].name);
 #endif
-
-     /* Check if there are any other explicit bits in the instruction: */
-     if ((~mask & (onemask | zeromask)) != 0x00000000) {
-       printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask | zeromask),onemask) ;
-       printf(" {\n") ;
-       printf("  SignalException(ReservedInstruction,instruction);\n") ;
-       printf(" }\n") ;
-       printf(" else\n") ;
-     }
-
-     if ((flags == 0) && !(MIPS_DECODE[loop].flags & NOARG)) {
-       fprintf(stderr,"Bitmap error: Instruction with no operand fields \"%s\"\n",MIPS_DECODE[loop].name) ;
-       exit(5) ;
-     }
-
-     printf(" {\n") ;
-
+        
+        /* Check if there are any other explicit bits in the instruction: */
+        if ((~mask & (onemask | zeromask)) != 0x00000000) {
+          printf(" if ((instruction & 0x%08X) != 0x%08X)\n",(onemask | zeromask),onemask) ;
+          printf(" {\n") ;
+          printf("  SignalException(ReservedInstruction,instruction);\n") ;
+          printf(" }\n") ;
+          printf(" else\n") ;
+        }
+        
+        printf(" {\n") ;
+       }
+     else
+       {
+        /* start-sanitize-cygnus-never */
+        /* If any sanitization occures, this line should be printed */
+        if ((MIPS_DECODE[loop].isa & ARCH_R5900))
+          printf ("// %s-%s-%s\n", "start", "sanitize", "r5900");
+        /* end-sanitize-cygnus-never */
+        printf ("\n");
+        print_igen_insn_format (MIPS_DECODE[loop].bitmap,
+                                MIPS_DECODE[loop].mark, /* format-name */
+                                GETDATASIZEINSN (&MIPS_DECODE[loop]), /* filter-flags */
+                                "", /* options */
+                                MIPS_DECODE[loop].name);
+        print_igen_insn_models (MIPS_DECODE[loop].isa);
+        printf ("{\n") ;
+        printf ("  unsigned32 instruction = instruction_0;\n");
+       }
+     
      /* Get hold of the operands */
      /* NOTE: If we wanted to make the simulator code smaller, we
       * could pull these into a common sequence before we perform
@@ -1321,93 +2278,43 @@ process_instructions(doarch,features)
       * particular operand here, since they are caught by the
       * compilation of the produced code.
       */
-     build_operands(flags);
-
-     /* Finish constructing the jump address if required: */
-     if (flags & fieldval('j'))
-      printf("  op1 |= (PC & ~0x0FFFFFFF); /* address of instruction in delay slot for the jump */\n");
-
-     /* Now perform required operand checks: */
-
-/* The following code has been removed, since it seems perfectly
-   reasonable to have a non-aligned offset that is added to another
-   non-aligned base to create an aligned address. Some more
-   information on exactly what the MIPS IV specification requires is
-   needed before deciding on the best strategy. Experimentation with a
-   VR4300 suggests that we do not need to raise the warning. */
-#if 0
-     /* For MIPS IV (and onwards), certain instruction operand values
-        will give undefined results. For the simulator we could
-        generate explicit exceptions (i.e. ReservedInstruction) to
-        make it easier to spot invalid use. However, for the moment we
-        just raise a warning. NOTE: This is a different check to the
-        later decoding, which checks for the final address being
-        valid. */
-     if ((flags & (fieldval('e') | fieldval('w') | fieldval('h'))) && (doisa >= 4)) {
-       printf("  if (instruction & 0x%1X)\n",((flags & fieldval('e')) ? 0x7 : ((flags & fieldval('w')) ? 0x3 : 0x1)));
-       printf("  {\n");
-       /* NOTE: If we change this to a SignalException(), we must
-          ensure that the following opcode processing is not
-          executed. i.e. the code falls straight out to the simulator
-          control loop. */
-       printf("   sim_warning(\"Instruction has lo-order offset bits set in instruction\");\n");
-       printf("  }\n");
-     }
-#endif
-
-     /* The extended condition codes only appeared in ISA IV */
-     if ((flags & fieldval('p')) && (doisa < 4)) {
-       printf("  if (condition_code != 0)\n");
-       printf("  {\n");
-       printf("   SignalException(ReservedInstruction,instruction);\n");
-       printf("  }\n");
-       printf("  else\n");
-     }
-
-     if ((MIPS_DECODE[loop].flags & WORD32) && (GETDATASIZE() != WORD)) {
-       fprintf(stderr,"Error in opcode table: WORD32 set for non-WORD opcode\n");
-       exit(1);
-     }
-
-#if 1
-     /* The R4000 book differs slightly from the MIPS IV ISA
-        manual. An example is the sign-extension of a 64-bit processor
-        SUBU operation, and what is meant by an Undefined Result. This
-        is now provided purely as a warning. After examining a HW
-        implementation, this is now purely a warning... and the actual
-        operation is performed, with possibly undefined results. */
-     if (((MIPS_DECODE[loop].flags & WORD32) && proc64) && (features & FEATURE_WARN_RESULT)) {
-       /* The compiler should optimise out an OR with zero */
-       printf("  if (%s | %s)\n",((flags & fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags & fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
-       printf("   UndefinedResult();\n") ;
-     }
-#else
-     /* Check that the source is a 32bit value */
-     if ((MIPS_DECODE[loop].flags & WORD32) && proc64) {
-       /* The compiler should optimise out an OR with zero */
-       printf("  if (%s | %s)\n",((flags & fieldval('s')) ? "NOTWORDVALUE(op1)" : "0"),((flags & fieldval('g')) ? "NOTWORDVALUE(op2)" : "0"));
-       printf("   UndefinedResult();\n") ;
-       printf("  else\n") ;
-     }
-#endif
-
+     build_operands(doisa, features, &MIPS_DECODE[loop]);
+     
      printf("  {\n") ;
-
+     
      build_instruction (doisa, features, 0, &MIPS_DECODE[loop]);
+     
+     printf("  }\n") ;
+     if (!(features & FEATURE_IGEN))
+       {
+        printf(" }\n") ;
+        printf(" break ;\n") ;
+       }
+     else
+       {
+        printf ("}\n");
+        printf ("\n");
+        /* start-sanitize-cygnus-never */
+        /* When sanitized, this output should never be produced */
+        if ((MIPS_DECODE[loop].isa & ARCH_R5900))
+          printf ("// %s-%s-%s\n", "end", "sanitize", "r5900");
+        /* end-sanitize-cygnus-never */
+       }
+   
+   }
+ }
 
-     printf("  }\n") ;
-     printf(" }\n") ;
+ if (!(features & FEATURE_IGEN))
+   {
+     printf("default : /* Unrecognised instruction */\n") ;
+     printf(" SignalException(ReservedInstruction,instruction);\n") ;
      printf(" break ;\n") ;
+     printf("}\n}\n") ;
    }
-  }
-
- printf("default : /* Unrecognised instruction */\n") ;
- printf(" SignalException(ReservedInstruction,instruction);\n") ;
- printf(" break ;\n") ;
- printf("}\n}\n") ;
-
  /* Handle mips16 instructions.  The switch table looks like this:
-     0 - 31: I, RI, and RRI instructions by major.
+    0 - 31: I, RI, and RRI instructions by major.
     32 - 35: ISHIFT instructions by function + 32
     36 - 37: RRI_A instructions by function + 36
     38 - 45: I8, I8_MOV32R, and I8_MOVR32 instructions by function + 38
@@ -1416,31 +2323,34 @@ process_instructions(doarch,features)
     82 - 89: I64 and RI64 instructions by funct + 82
     90 - 97: jalr (RR minor 0) by y + 90
     */
- printf ("else {\n");
- printf ("static int extendval;\n");
- printf ("static int have_extendval;\n");
- printf ("int num = ((instruction >> %d) & 0x%08X);\n",
-        MIPS16OP_SH_OP, MIPS16OP_MASK_OP);
- printf ("switch (num)\n{\n");
- printf ("case 0x6: num = 32 + (instruction & 3); break;\n");
- printf ("case 0x8: num = 36 + ((instruction & 0x10) >> 4); break;\n");
- printf ("case 0xc: num = 38 + ((instruction & 0x700) >> 8); break;\n");
- printf ("case 0x1c: num = 46 + (instruction & 3); break;\n");
- printf ("case 0x1d: num = 50 + (instruction & 0x1f);\n");
- printf ("           if (num == 50) num = 90 + ((instruction & 0xe0) >> 5);\n");
- printf ("           break;\n");
- printf ("case 0x1f: num = 82 + ((instruction & 0x700) >> 8); break;\n");
- printf ("default: break;\n}\n");
- printf ("switch (num)\n{\n");
-
+ if (!(features & FEATURE_IGEN))
+   {
+     printf ("else {\n");
+     printf ("static int extendval;\n");
+     printf ("static int have_extendval;\n");
+     printf ("int num = ((instruction >> %d) & 0x%08X);\n",
+            MIPS16OP_SH_OP, MIPS16OP_MASK_OP);
+     printf ("switch (num)\n{\n");
+     printf ("case 0x6: num = 32 + (instruction & 3); break;\n");
+     printf ("case 0x8: num = 36 + ((instruction & 0x10) >> 4); break;\n");
+     printf ("case 0xc: num = 38 + ((instruction & 0x700) >> 8); break;\n");
+     printf ("case 0x1c: num = 46 + (instruction & 3); break;\n");
+     printf ("case 0x1d: num = 50 + (instruction & 0x1f);\n");
+     printf ("           if (num == 50) num = 90 + ((instruction & 0xe0) >> 5);\n");
+     printf ("           break;\n");
+     printf ("case 0x1f: num = 82 + ((instruction & 0x700) >> 8); break;\n");
+     printf ("default: break;\n}\n");
+     printf ("switch (num)\n{\n");
+   }
  for (loop = 0; loop < sizeof MIPS16_DECODE / sizeof MIPS16_DECODE[0]; loop++)
    {
      const char *bitmap;
      int num;
-
+     
      if (! proc64 && GETDATASIZEINSN (&MIPS16_DECODE[loop]) == DOUBLEWORD)
        continue;
-
+     
      bitmap = MIPS16_DECODE[loop].bitmap;
      switch (MIPS16_DECODE[loop].mark)
        {
@@ -1466,7 +2376,7 @@ process_instructions(doarch,features)
        case RR:
         {
           int minor;
-
+          
           minor = bitmap_val (bitmap, 0, 5);
           if (minor != 0)
             num = 50 + minor;
@@ -1482,10 +2392,25 @@ process_instructions(doarch,features)
         abort ();
        }
 
-     printf ("case %d: /* \"%s\" %s */\n", num, MIPS16_DECODE[loop].name,
-            bitmap);
 
-     printf (" {\n");
+     if (!(features & FEATURE_IGEN))
+       {
+        printf ("case %d: /* \"%s\" %s */\n", num, MIPS16_DECODE[loop].name,
+                bitmap);
+        printf (" {\n");
+       }
+     else
+       {
+        printf ("\n");
+        print_igen_insn_format (bitmap,
+                                MIPS16_DECODE[loop].mark, /* format-name */
+                                -1, /* filter-flags -- -1 => MIPS16 */
+                                "", /* options */
+                                MIPS16_DECODE[loop].name);
+        printf ("*mips16:\n");
+        printf ("{\n");
+        printf ("  unsigned32 instruction = instruction_0;\n");
+       }
 
      build_mips16_operands (bitmap);
 
@@ -1501,17 +2426,28 @@ process_instructions(doarch,features)
        }
 
      printf ("  }\n");
-     printf (" }\n") ;
-     printf (" break ;\n") ;
+     if (!(features & FEATURE_IGEN))
+       {
+        printf (" }\n") ;
+        printf (" break ;\n") ;
+       }
+     else
+       {
+        printf ("}\n");
+        printf ("\n");
+       }
    }
 
- printf ("default : /* Unrecognised instruction */\n") ;
- printf (" SignalException(ReservedInstruction,instruction);\n") ;
- printf (" break ;\n") ;
- printf ("}\n}\n") ;
-
- printf("#endif /* simulator engine */\n");
-
+ if (!(features & FEATURE_IGEN))
+   {
+     printf ("default : /* Unrecognised instruction */\n") ;
+     printf (" SignalException(ReservedInstruction,instruction);\n") ;
+     printf (" break ;\n") ;
+     printf ("}\n}\n") ;
+     
+     printf("#endif /* simulator engine */\n");
+   }
+     
  return ;
 }
 
@@ -1557,10 +2493,10 @@ build_instruction (doisa, features, mips16, insn)
 
        if ((insn->type) == ADD) {
         printf("   %s temp = (%s)(op1 + op2);\n", unsigned_basetype, unsigned_basetype);
-        printf("   %s tempS = (%s)temp;\n", signed_basetype, signed_basetype);
+        printf("   %s tempS UNUSED = (%s)temp;\n", signed_basetype, signed_basetype);
         if (insn->flags & OVERFLOW) {
           printf("   if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
-          printf("    SignalException(IntegerOverflow);\n");
+          printf("    SignalExceptionIntegerOverflow ();\n");
           printf("   else\n");
         }
         if (!proc64 || (insn->flags & UNSIGNED) || (GETDATASIZEINSN(insn) == DOUBLEWORD))
@@ -1569,10 +2505,10 @@ build_instruction (doisa, features, mips16, insn)
          printf("   GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype);
        } else { /* SUB */
         printf("   %s temp = (%s)(op1 - op2);\n", unsigned_basetype, unsigned_basetype);
-        printf("   %s tempS = (%s)temp;\n", signed_basetype, signed_basetype);
+        printf("   %s tempS UNUSED = (%s)temp;\n", signed_basetype, signed_basetype);
         if (insn->flags & OVERFLOW) { /* different signs => overflow if result_sign != arg_sign */
           printf("   if (((op1 < 0) != (op2 < 0)) && ((tempS < 0) == (op1 < 0)))\n");
-          printf("    SignalException(IntegerOverflow);\n");
+          printf("    SignalExceptionIntegerOverflow ();\n");
           printf("   else\n");
         }
         /* UNSIGNED 32bit operations on a 64bit processor should
@@ -1588,6 +2524,9 @@ build_instruction (doisa, features, mips16, insn)
      break ;
 
     case MUL:
+     {
+     char* pipe = (insn->flags & PIPE1) ? "1" : "";
+
      if (features & FEATURE_WARN_LOHI) {
        printf("   CHECKHILO(\"Multiplication\");\n");
      }
@@ -1602,51 +2541,88 @@ build_instruction (doisa, features, mips16, insn)
           printf("   if (op1 < 0) { op1 = - op1; ++sign; }\n");
           printf("   if (op2 < 0) { op2 = - op2; ++sign; }\n");
         }
-       printf("   LO = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n");
-       printf("   HI = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n");
+       printf("   LO%s = ((uword64)WORD64LO(op1) * WORD64LO(op2));\n",pipe);
+       printf("   HI%s = ((uword64)WORD64HI(op1) * WORD64HI(op2));\n",pipe);
        printf("   mid = ((uword64)WORD64HI(op1) * WORD64LO(op2));\n");
        printf("   midhi = SET64HI(WORD64LO(mid));\n");
-       printf("   temp = (LO + midhi);\n");
-       printf("   if ((temp == midhi) ? (LO != 0) : (temp < midhi))\n");
-       printf("    HI += 1;\n");
-       printf("   HI += WORD64HI(mid);\n");
+       printf("   temp = (LO%s + midhi);\n",pipe);
+       printf("   if ((temp == midhi) ? (LO%s != 0) : (temp < midhi))\n",pipe);
+       printf("     HI%s += 1;\n",pipe);
+       printf("   HI%s += WORD64HI(mid);\n",pipe);
        printf("   mid = ((uword64)WORD64LO(op1) * WORD64HI(op2));\n");
        printf("   midhi = SET64HI(WORD64LO(mid));\n");
-       printf("   LO = (temp + midhi);\n");
-       printf("   if ((LO == midhi) ? (temp != 0) : (LO < midhi))\n");
-       printf("    HI += 1;\n");
-       printf("   HI += WORD64HI(mid);\n");
+       printf("   LO%s = (temp + midhi);\n",pipe);
+       printf("   if ((LO%s == midhi) ? (temp != 0) : (LO%s < midhi))\n",pipe,pipe);
+       printf("     HI%s += 1;\n",pipe);
+       printf("   HI%s += WORD64HI(mid);\n",pipe);
        if ((insn->flags & UNSIGNED) == 0)
-        printf("   if (sign & 1) { LO = - LO; HI = (LO == 0 ? 0 : -1) - HI; }\n");
+        printf("   if (sign & 1) { LO%s = - LO%s; HI%s = (LO%s == 0 ? 0 : -1) - HI%s; }\n",pipe,pipe,pipe,pipe,pipe);
      } else {
        if (insn->flags & UNSIGNED)
         printf("   uword64 temp = ((uword64)(op1 & 0xffffffff) * (uword64)(op2 & 0xffffffff));\n");
        else
-        printf("   uword64 temp = (op1 * op2);\n");
-       printf("   LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype);
-       printf("   HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype);
+        printf("   uword64 temp = ((word64) op1 * (word64) op2);\n");
+       printf("   LO%s = SIGNEXTEND((%s)WORD64LO(temp),32);\n",pipe,regtype);
+       printf("   HI%s = SIGNEXTEND((%s)WORD64HI(temp),32);\n",pipe,regtype);
      }
+     if (insn->flags & OP3)
+       {
+         printf("     if ( destreg != 0 )\n");
+         printf("         GPR[destreg] = LO%s;\n",pipe);
+       }
      printf("   }\n");
      break ;
-
+     }
     case DIV:
      {
       int boolU = (insn->flags & UNSIGNED);
+      char* pipe = (insn->flags & PIPE1) ? "1" : "";
 
       if (features & FEATURE_WARN_LOHI) {
-       printf("   CHECKHILO(\"Division\");\n");
+        printf("   CHECKHILO(\"Division\");\n");
       }
       printf("   {\n");
+
       if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
-       printf("   LO = ((%sword64)op1 / (%sword64)op2);\n",(boolU ? "u" : ""),(boolU ? "u" : ""));
-       printf("   HI = ((%sword64)op1 %c (%sword64)op2);\n",(boolU ? "u" : ""),'%',(boolU ? "u" : ""));
+        printf("   %sword64 d1 = op1;\n", (boolU ? "u" : ""));
+        printf("   %sword64 d2 = op2;\n", (boolU ? "u" : ""));
+        printf("   if (d2 == 0)\n");
+        printf("     {\n");
+        printf("     LO%s = SIGNED64 (0x8000000000000000);\n", pipe);
+        printf("     HI%s = 0;\n", pipe);
+        printf("     }\n");
+        printf("   else if (d2 == -1 && d1 == SIGNED64 (0x8000000000000000))\n");
+        printf("     {\n");
+        printf("     LO%s = SIGNED64 (0x8000000000000000);\n", pipe);
+        printf("     HI%s = 0;\n", pipe);
+        printf("     }\n");
+        printf("   else\n");
+        printf("     {\n");
+        printf("     LO%s = (d1 / d2);\n", pipe);
+        printf("     HI%s = (d1 %% d2);\n", pipe);
+        printf("     }\n");
       } else {
-       printf("   LO = SIGNEXTEND(((%sint)op1 / (%sint)op2),32);\n",(boolU ? "unsigned " : ""),(boolU ? "unsigned " : ""));
-       printf("   HI = SIGNEXTEND(((%sint)op1 %c (%sint)op2),32);\n",(boolU ? "unsigned " : ""),'%',(boolU ? "unsigned " : ""));
+        printf("   %sint d1 = op1;\n", (boolU ? "unsigned " : ""));
+        printf("   %sint d2 = op2;\n", (boolU ? "unsigned " : ""));
+        printf("   if (d2 == 0)\n");
+        printf("     {\n");
+       printf("     LO%s = SIGNEXTEND(0x80000000,32);\n",pipe);
+       printf("     HI%s = SIGNEXTEND(0,32);\n", pipe);
+        printf("     }\n");
+        printf("   else if (d2 == -1 && d1 == 0x80000000)\n");
+        printf("     {\n");
+       printf("     LO%s = SIGNEXTEND(0x80000000,32);\n",pipe);
+       printf("     HI%s = SIGNEXTEND(0,32);\n", pipe);
+        printf("     }\n");
+        printf("   else\n");
+        printf("     {\n");
+       printf("     LO%s = SIGNEXTEND((d1 / d2),32);\n", pipe);
+       printf("     HI%s = SIGNEXTEND((d1 %% d2),32);\n", pipe);
+        printf("     }\n");
       }
       printf("   }\n");
      }
-     break ;
+    break ;
 
     case SHIFT:
      {
@@ -1680,6 +2656,11 @@ build_instruction (doisa, features, mips16, insn)
        exit(9);
       }
 
+      /* Work around an MSC code generation bug by precomputing a value
+       * with the sign bit set.  */
+      if (insn->flags & ARITHMETIC)
+       printf("   %s highbit = (%s)1 << %d;\n", ltype, ltype, bits - 1);
+
       /* If register specified shift, then extract the relevant shift amount: */
       if (insn->flags & REG)
        printf("   op1 &= 0x%02X;\n",(bits - 1));
@@ -1701,7 +2682,7 @@ build_instruction (doisa, features, mips16, insn)
         since that would cause an undefined shift of the number of
         bits in the type.  */
       if (insn->flags & ARITHMETIC)
-       printf("   GPR[destreg] |= (op1 != 0 && (op2 & ((%s)1 << %d)) ? ((((%s)1 << op1) - 1) << (%d - op1)) : 0);\n",ltype,(bits - 1),ltype,bits);
+       printf("   GPR[destreg] |= (op1 != 0 && (op2 & highbit) ? ((((%s)1 << op1) - 1) << (%d - op1)) : 0);\n",ltype,bits);
 
       /* Ensure WORD values are sign-extended into 64bit registers */
       if ((bits == 32) && (gprlen == 64))
@@ -1712,17 +2693,18 @@ build_instruction (doisa, features, mips16, insn)
     case MOVE:
      if (insn->flags & (HI | LO)) {
        char *regname = ((insn->flags & LO) ? "LO" : "HI");
+       int pipe1 = (insn->flags & PIPE1);
        if (insn->flags & LEFT)
-       printf("   GPR[destreg] = %s;\n",regname);
+       printf("   GPR[destreg] = %s%s;\n",regname,(pipe1 ? "1" : ""));
        else {
         if (features & FEATURE_WARN_LOHI) {
-          printf("   if (%sACCESS != 0)\n",regname);
-          printf("     sim_warning(\"MT (move-to) over-writing %s register value\");\n",regname);
+          printf("   if (%s%sACCESS != 0)\n",regname,(pipe1 ? "1" : ""));
+          printf("     sim_io_eprintf(sd,\"MT (move-to) over-writing %s register value\\n\");\n",regname);
         }
-        printf("   %s = op1;\n",regname);
+        printf("   %s%s = op1;\n",regname,(pipe1 ? "1" : ""));
        }
        if (features & FEATURE_WARN_LOHI)
-       printf("   %sACCESS = 3; /* 3rd instruction will be safe */\n",regname);
+       printf("   %s%sACCESS = 3; /* 3rd instruction will be safe */\n",regname,(pipe1 ? "1" : ""));
      } else
       if (insn->flags & SHIFT16)
        printf("   GPR[destreg] = (op2 << 16);\n");
@@ -1749,6 +2731,10 @@ build_instruction (doisa, features, mips16, insn)
      printf("   SignalException(BreakPoint,instruction);\n");
      break ;
 
+    case SDBBP:
+     printf("   SignalException(DebugBreakPoint,instruction);\n");
+     break ;
+
     case TRAP:
      {
       int boolNOT = (insn->flags & NOT);
@@ -1795,6 +2781,11 @@ build_instruction (doisa, features, mips16, insn)
      break ;
 
     case OR:
+     /* The default mips16 nop instruction does an or to register
+        zero; catch that case, so that we don't get useless warnings
+        from the simulator.  */
+     if (mips16)
+       printf ("   if (destreg != 0)\n");
      printf("   GPR[destreg] = %s(op1 | op2);\n",((insn->flags & NOT) ? "~" : ""));
      break ;
 
@@ -1803,15 +2794,15 @@ build_instruction (doisa, features, mips16, insn)
      break ;
 
     case DECODE:
-     printf("   decode_coproc(instruction);\n");
+     printf("   DecodeCoproc(instruction);\n");
      break ;
 
     case CACHE:
      /* 16-bit offset is sign-extended and added to the base register to make a virtual address */
      /* The virtual address is translated to a physical address using the TLB */
      /* The hint specifies a cache operation for that address */
-     printf("    uword64 vaddr = (op1 + offset);\n");
-     printf("    uword64 paddr;\n");
+     printf("    address_word vaddr = (op1 + offset);\n");
+     printf("    address_word paddr;\n");
      printf("    int uncached;\n");
      /* NOTE: We are assuming that the AddressTranslation is a load: */
      printf("    if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
@@ -1828,7 +2819,7 @@ build_instruction (doisa, features, mips16, insn)
      if (features & FEATURE_WARN_RESULT) {
        /* Give user a warning if either op1 or op2 are not 16bit signed integers */
        printf("   if (NOTHALFWORDVALUE(op1) || NOTHALFWORDVALUE(op2))\n");
-       printf("     sim_warning(\"MADD16 operation with non-16bit operands\");\n");
+       printf("     sim_io_eprintf(sd,\"MADD16 operation with non-16bit operands\\n\");\n");
      }
      printf("   {\n");
      printf("    uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
@@ -1845,7 +2836,7 @@ build_instruction (doisa, features, mips16, insn)
     case RSVD: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
      if (doisa < 4) {
        printf("   if (CoProcPresent(3))\n");
-       printf("    SignalException(CoProcessorUnusable);\n");
+       printf("    SignalExceptionCoProcessorUnusable ();\n");
        printf("   else\n");
      }
      printf("   SignalException(ReservedInstruction,instruction);\n");
@@ -1867,7 +2858,11 @@ build_instruction (doisa, features, mips16, insn)
      printf("   op1 = WORD64LO(op1);\n");
      printf("   /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
      printf("   DSPC = op1;\n");
-     printf("   DELAYSLOT();\n");
+     if ((insn->flags & LINK)
+         && ! (insn->flags & REG))
+       printf("   JALDELAYSLOT();\n");
+     else
+       printf("   DELAYSLOT();\n");
      break ;
 
     case BRANCH: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
@@ -1902,7 +2897,7 @@ build_instruction (doisa, features, mips16, insn)
      if (insn->flags & LINK) {
        if (features & FEATURE_WARN_R31) {
         printf("   if (((instruction >> %d) & 0x%08X) == 31)\n",OP_SH_RS,OP_MASK_RS);
-        printf("    sim_warning(\"Branch with link using r31 as source operand\");\n");
+        printf("    sim_io_eprintf(sd,\"Branch with link using r31 as source operand\\n\");\n");
        }
        printf("   GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
      }
@@ -1958,19 +2953,26 @@ build_instruction (doisa, features, mips16, insn)
         datalen = 8;
         accesslength = "AccessLength_DOUBLEWORD";
         break ;
+        /* start-sanitize-r5900 */
+
+       case QUADWORD :
+        datalen = 16;
+        accesslength = "AccessLength_QUADWORD";
+        break ;
+        /* end-sanitize-r5900 */
       }
 
       if (insn->flags & REG)
-       printf("   uword64 vaddr = ((uword64)op1 + op2);\n");
+       printf("   address_word vaddr = ((uword64)op1 + op2);\n");
       else
-       printf("   uword64 vaddr = ((uword64)op1 + offset);\n");
-      printf("   uword64 paddr;\n");
+       printf("   address_word vaddr = ((uword64)op1 + offset);\n");
+      printf("   address_word paddr;\n");
       printf("   int uncached;\n");
 
       /* The following check should only occur on normal (non-shifted) memory loads */
       if ((datalen != 1) && !(insn->flags & (LEFT | RIGHT))) {
        printf("   if ((vaddr & %d) != 0)\n",(datalen - 1));
-       printf("    SignalException(%s);\n",(isload ? "AddressLoad" : "AddressStore"));
+       printf("    SignalException%s();\n",(isload ? "AddressLoad" : "AddressStore"));
        printf("   else\n") ;
       }
 
@@ -1981,7 +2983,8 @@ build_instruction (doisa, features, mips16, insn)
        printf("     Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
       else {
        printf("    {\n");
-       printf("     %s memval;\n",(proc64 ? "uword64" : "unsigned int"));
+       printf("     uword64 memval = 0;\n");
+        printf("     uword64 memval1 = 0;\n");
 
        if ((insn->flags & COPROC) && ((datalen != 4) && (datalen != 8))) {
          fprintf(stderr,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn->name);
@@ -1996,11 +2999,14 @@ build_instruction (doisa, features, mips16, insn)
 
          switch (datalen) {
           case 8:
-           if (!proc64) {
-             fprintf(stderr,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",insn->name);
-             exit(4);
-           }
-           /* fall through to... */
+            if (!(features & FEATURE_IGEN))
+              {
+                if (!proc64) {
+                  fprintf(stderr,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",insn->name);
+                  exit(4);
+                }
+              }
+            /* fall through to... */
           case 4:
            {
              printf("     uword64 mask = %d;\n",((datalen == 8) ? 0x7 : 0x3));
@@ -2009,14 +3015,18 @@ build_instruction (doisa, features, mips16, insn)
              printf("     int byte;\n");
              printf("     paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
              printf("     byte = ((vaddr & mask) ^ bigend);\n");
-             printf("     if (%s!ByteSwapMem)\n",((insn->flags & LEFT) ? "!" : ""));
+             printf("     if (%sBigEndianMem)\n",((insn->flags & LEFT) ? "!" : ""));
              printf("      paddr &= ~mask;\n");
 
              if (isload) {
                if (insn->flags & LEFT)
-                printf("     memval = LoadMemory(uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
+                  {
+                    printf("     LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
+                  }
                else
-                printf("     memval = LoadMemory(uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen - 1));
+                  {
+                    printf("     LoadMemory(&memval,&memval1,uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen - 1));
+                  }
              }
 
              if (insn->flags & LEFT) {
@@ -2050,7 +3060,7 @@ build_instruction (doisa, features, mips16, insn)
                    printf("    }\n");
                  }
 #endif
-                 printf("     StoreMemory(uncached,byte,memval,paddr,vaddr,isREAL);\n");
+                 printf("     StoreMemory(uncached,byte,memval,memval1,paddr,vaddr,isREAL);\n");
                }
              } else { /* RIGHT */
                if (isload) {
@@ -2078,9 +3088,9 @@ build_instruction (doisa, features, mips16, insn)
                  if (proc64 && (datalen == 4))
                   printf("     GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
                } else { /* store */
-                 printf("     memval = (op2 << (byte * 8));\n");
+                 printf("     memval = ((uword64) op2 << (byte * 8));\n");
                  build_endian_shift(proc64,datalen,2,s_left,32);
-                 printf("     StoreMemory(uncached,(%s - byte),memval,paddr,vaddr,isREAL);\n",accesslength);
+                 printf("     StoreMemory(uncached,(%s - byte),memval,memval1,paddr,vaddr,isREAL);\n",accesslength);
                }
              }
            }
@@ -2091,16 +3101,19 @@ build_instruction (doisa, features, mips16, insn)
            exit(6);
          }
        } else { /* normal memory transfer */
-         if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) {
-           fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name);
-           exit(4);
-           /* TODO: The R4000 documentation states that a LWU
-              instruction executed when in a 32bit processor mode
-              should cause a ReservedInstruction exception. This
-              will mean adding a run-time check into the code
-              sequence. */
-         }
-
+         if (!(features & FEATURE_IGEN))
+           {
+             if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) {
+               fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name);
+               exit(4);
+               /* TODO: The R4000 documentation states that a LWU
+                  instruction executed when in a 32bit processor mode
+                  should cause a ReservedInstruction exception. This
+                  will mean adding a run-time check into the code
+                  sequence. */
+             }
+           }
+         
          if (isload) {
 #if 1 /* see the comments attached to LOADDRMASK above */
            printf("     uword64 mask = 0x7;\n");
@@ -2108,19 +3121,27 @@ build_instruction (doisa, features, mips16, insn)
            printf("     uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
 #endif
            printf("     unsigned int shift = %d;\n",(datalen >> 1));
-           printf("     unsigned int reverse = (ReverseEndian ? (mask >> shift) : 0);\n");
-           printf("     unsigned int bigend = (BigEndianCPU ? (mask >> shift) : 0);\n");
-           printf("     unsigned int byte;\n");
+           printf("     unsigned int reverse UNUSED = (ReverseEndian ? (mask >> shift) : 0);\n");
+           printf("     unsigned int bigend UNUSED = (BigEndianCPU ? (mask >> shift) : 0);\n");
+           printf("     unsigned int byte UNUSED;\n");
 
 /* TODO: This should really also check for 32bit world performing 32bit access */
-           if (datalen != 8) /* not for DOUBLEWORD */
-            printf("     paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
-
-           printf("     memval = LoadMemory(uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength);
+           if (datalen < 8)
+             /* not for DOUBLEWORD */
+             /* start-sanitize-r5900 */
+             /* not for QUADWORD */
+             /* end-sanitize-r5900 */
+             printf("     paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
 
+           printf("     LoadMemory(&memval,&memval1,uncached,%s,paddr,vaddr,isDATA,isREAL);\n",accesslength);
+              
            /* The following will only make sense if the
               "LoadMemory" above returns a DOUBLEWORD entity */
-           if (datalen != 8) { /* not for DOUBLEWORD */
+           if (datalen < 8) {
+             /* not for DOUBLEWORD */
+             /* start-sanitize-r5900 */
+             /* not for QUADWORD */
+             /* end-sanitize-r5900 */
              int valmask;
              switch (datalen) {
               case 1:
@@ -2169,7 +3190,11 @@ build_instruction (doisa, features, mips16, insn)
                       ? "1"
                       : "((instruction >> 26) & 0x3)"));
              else
-              printf("     GPR[destreg] = memval;\n");
+                {
+                  printf("     GPR[destreg] = memval;\n");
+                  if (datalen > 8)
+                    printf("     GPR1[destreg] = memval1;\n");
+                }
            }
          } else { /* store operation */
            if ((datalen == 1) || (datalen == 2)) {
@@ -2186,9 +3211,9 @@ build_instruction (doisa, features, mips16, insn)
 
              printf("     paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
              printf("     byte = ((vaddr & mask) ^ (bigend << shift));\n");
-             printf("     memval = (op2 << (8 * byte));\n");
+             printf("     memval = ((uword64) op2 << (8 * byte));\n");
            } else
-            if (proc64 && (datalen == 4)) { /* proc64 SC and SW */
+            if (datalen == 4) { /* SC and SW */
 #if 1 /* see the comments attached to LOADDRMASK above */
               printf("     uword64 mask = 0x7;\n");
 #else
@@ -2204,24 +3229,37 @@ build_instruction (doisa, features, mips16, insn)
                        : "((instruction >> 26) & 0x3)"),
                       ((insn->flags & FP) ? "fs" : "destreg"));
               else
-               printf("     memval = (op2 << (8 * byte));\n");
-            } else { /* !proc64 SC and SW, plus proc64 SD and SCD */
+               printf("     memval = ((uword64) op2 << (8 * byte));\n");
+            } else if (datalen <= 8) { /* SD and SCD */
+              if (! (features & FEATURE_IGEN))
+                {
+                  if (!(insn->flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (insn->flags & UNSIGNED))) && !proc64) {
+                    fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",insn->name);
+                    exit(4);
+                  }
+                }
               if (insn->flags & COPROC)
-               printf("     memval = (uword64)COP_S%c(%s,%s);\n",
-                      ((datalen == 8) ? 'D' : 'W'),
+               printf("     memval = (uword64)COP_SD(%s,%s);\n",
                       ((insn->flags & REG)
                        ? "1"
                        : "((instruction >> 26) & 0x3)"),
                       ((insn->flags & FP) ? "fs" : "destreg"));
               else
                printf("     memval = op2;\n");
+            } else { /* wider than 8 */
+               if (insn->flags & COPROC) {
+                fprintf(stderr,"COPROC not available for 128 bit operations \"%s\"\n",insn->name);
+                exit(4);
+               }
+               printf("     memval  = rt_reg;\n");
+               printf("     memval1 = rt_reg1;\n");
             }
 
            if (insn->flags & ATOMIC)
             printf("      if (LLBIT)\n");
 
            printf("      {\n");
-           printf("       StoreMemory(uncached,%s,memval,paddr,vaddr,isREAL);\n",accesslength);
+           printf("       StoreMemory(uncached,%s,memval,memval1,paddr,vaddr,isREAL);\n",accesslength);
            printf("      }\n");
          }
 
@@ -2262,8 +3300,8 @@ build_instruction (doisa, features, mips16, insn)
 
     case FPPREFX:
      /* This code could be merged with the PREFIX generation above: */
-     printf("   uword64 vaddr = ((uword64)op1 + (uword64)op2);\n");
-     printf("   uword64 paddr;\n");
+     printf("   address_word vaddr = ((uword64)op1 + (uword64)op2);\n");
+     printf("   address_word paddr;\n");
      printf("   int uncached;\n");
      printf("   if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
      printf("    Prefetch(uncached,paddr,vaddr,isDATA,fs);\n");
@@ -2320,7 +3358,7 @@ build_instruction (doisa, features, mips16, insn)
           printf("      FGR[fs] = (SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft]));\n");
           printf("     else\n");
           printf("      FGR[fs] = WORD64LO(GPR[ft]);\n");
-          printf("     fpr_state[fs] = fmt_uninterpreted;\n");
+          printf("     FPR_STATE[fs] = fmt_uninterpreted;\n");
         }
        } else if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
         if (doisa < 4) {
@@ -2339,14 +3377,14 @@ build_instruction (doisa, features, mips16, insn)
         } else {
           printf("     if (SizeFGR() == 64) {\n");
           printf("      FGR[fs] = GPR[ft];\n");
-          printf("      fpr_state[fs] = fmt_uninterpreted;\n");
+          printf("      FPR_STATE[fs] = fmt_uninterpreted;\n");
           printf("     } else\n");
           printf("      if ((fs & 0x1) == 0)\n");
           printf("       {\n");
           printf("        FGR[fs + 1] = WORD64HI(GPR[ft]);\n");
           printf("        FGR[fs] = WORD64LO(GPR[ft]);\n");
-          printf("        fpr_state[fs + 1] = fmt_uninterpreted;\n");
-          printf("        fpr_state[fs] = fmt_uninterpreted;\n");
+          printf("        FPR_STATE[fs + 1] = fmt_uninterpreted;\n");
+          printf("        FPR_STATE[fs] = fmt_uninterpreted;\n");
           printf("       }\n");
           if (features & FEATURE_WARN_RESULT) {
             printf("      else\n");
@@ -2453,7 +3491,9 @@ build_instruction (doisa, features, mips16, insn)
      printf("  if ((format != fmt_single) && (format != fmt_double))\n");
      printf("   SignalException(ReservedInstruction,instruction);\n");
      printf("  else\n");
-     printf("   StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)));\n",((insn->flags & RECIP) ? "Recip" : ""));
+     printf("   StoreFPR(destreg,format,%s(SquareRoot(ValueFPR(fs,format),format)%s));\n",
+           ((insn->flags & RECIP) ? "Recip" : ""),
+           ((insn->flags & RECIP) ? ",format" : ""));
      break ;
 
     case FPCEIL:
@@ -2545,7 +3585,12 @@ build_instruction (doisa, features, mips16, insn)
          fprintf(stderr,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZEINSN(insn));
          exit(1);
        }
-       printf("   StoreFPR(destreg,%s,%s(Sub(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",type,((insn->flags & NOT) ? "Negate" : ""),type,type,type,type,type,type);
+       if (insn->flags & NOT)
+        printf ("   StoreFPR(destreg,%s,Negate(Sub(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",
+                type, type, type, type, type, type, type);
+       else
+        printf ("   StoreFPR(destreg,%s,Sub(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s));\n",
+                type, type, type, type, type, type);
      } else {
        printf("  if ((format != fmt_single) && (format != fmt_double))\n");
        printf("   SignalException(ReservedInstruction,instruction);\n");
@@ -2592,7 +3637,7 @@ build_instruction (doisa, features, mips16, insn)
      printf("    SignalException(ReservedInstruction,instruction);\n") ;
      printf("   else {\n");
      if (doisa < 4) {
-       printf("    if ((cmpflags & (1 << 3)) || (condition_code != 0))\n");
+       printf("    if (condition_code != 0)\n");
        printf("     SignalException(ReservedInstruction,instruction);\n") ;
        printf("    else\n");
      }
@@ -2606,7 +3651,7 @@ build_instruction (doisa, features, mips16, insn)
      printf("      if (NaN(ofs,format) || NaN(oft,format)) {\n");
      printf("      if (FCSR & FP_ENABLE(IO)) {\n");
      printf("       FCSR |= FP_CAUSE(IO);\n");
-     printf("       SignalException(FPE);\n");
+     printf("       SignalExceptionFPE ();\n");
      printf("       ignore = 1;\n");
      printf("      }\n");
      printf("     } else {\n");
@@ -2622,6 +3667,765 @@ build_instruction (doisa, features, mips16, insn)
      printf("   }\n");
      break ;
 
+    case MADD:
+     {
+       char* pipeline = (insn->flags & PIPE1) ? "1" : "";
+       int notsigned = (insn->flags & UNSIGNED);
+       char* prodtype = notsigned ? "uword64" : "word64";
+
+       printf("%s prod = (%s)WORD64(WORD64LO(HI%s),WORD64LO(LO%s)) + ((%s)%s(op1%s) * (%s)%s(op2%s));\n",
+              prodtype, prodtype, pipeline, pipeline, 
+              prodtype, (notsigned ? "WORD64LO" : "SIGNEXTEND"), (notsigned ? "" : ",32"),
+              prodtype, (notsigned ? "WORD64LO" : "SIGNEXTEND"), (notsigned ? "" : ",32")
+              );
+       printf("LO%s = SIGNEXTEND(prod,32);\n", pipeline );
+       printf("HI%s = SIGNEXTEND( WORD64HI(prod), 32);\n", pipeline );
+       printf("if( destreg != 0 ) GPR[destreg] = LO%s;\n", pipeline );
+       break;
+     }
+
+/* start-sanitize-r5900 */
+    case MxSA:
+      {
+        if (insn->flags & TO)
+          printf("SA = op1;\n");
+        else
+          printf("GPR[destreg] = SA;\n");
+        break;
+      }
+
+    case MTSAB:
+     printf("SA = ((op1 & 0xF) ^ (op2 & 0xF)) * 8;\n");
+     break;
+
+    case MTSAH:
+     printf("SA = ((op1 & 0x7) ^ (op2 & 0x7)) * 16;\n");
+     break;
+
+    case QFSRV:
+     printf("int bytes = (SA / 8) %% 16;\n");   /* mod 16 to avoid garbage */
+     printf("if (SA %% 8)\n");
+     printf("   SignalException(ReservedInstruction,instruction);\n");
+     printf("else\n");
+     printf("    {\n");
+     printf("    int i;\n");
+     printf("    for(i=0;i<(16-bytes);i++)\n");
+     printf("        GPR_SB(destreg,i) = RT_SB(bytes+i);\n");
+     printf("    for(;i<16;i++)\n");
+     printf("        GPR_SB(destreg,i) = RS_SB(i-(16-bytes));\n");
+     printf("    }\n");
+     break;
+
+    case PADD:
+     {
+       char* op = (insn->flags & SUBTRACT) ? "-" : "+";
+       char* name = name_for_data_len( insn );
+       char* letter = letter_for_data_len( insn );
+
+       char* tmptype;
+       char* maximum;
+       char* maxsat;
+       char* minimum;
+       char* signletter;
+
+       if ( insn->flags & UNSIGNED )
+         {
+           tmptype = type_for_data_len( insn, 0/*unsigned*/ );
+          signletter = "U";
+           maximum = umax_for_data_len( insn );
+          maxsat = (insn->flags & SUBTRACT) ? "0" : maximum;
+           minimum = 0;
+         }
+       else if ( insn->flags & SATURATE )
+         {
+           tmptype = type_for_data_len( insn, 1/*signed*/ );
+          signletter = "S";
+           maximum = max_for_data_len( insn );
+          maxsat = maximum;
+           minimum = min_for_data_len( insn );
+         }
+       else
+         {
+           tmptype = type_for_data_len( insn, 1/*signed*/ );
+          signletter = "S";
+           maximum = 0;
+          maxsat = 0;
+           minimum = 0;
+         }
+
+       printf("   int i;\n");
+       printf("   for (i=0; i < %sS_IN_MMI_REGS; i++)\n", name );
+       printf("    {\n");
+       printf("     %s s = RS_%s%s(i);\n", tmptype, signletter, letter);
+       printf("     %s t = RT_%s%s(i);\n", tmptype, signletter, letter);
+       printf("     %s r = s %s t;\n", tmptype, op);
+       if ( maximum )
+         {
+           printf("     if (r > %s)\n", maximum);
+           printf("      GPR_%s%s(destreg,i) = %s;\n", signletter, letter, maxsat );
+           if ( minimum )
+            {
+              printf("     else if (r < %s)\n", minimum);
+              printf("      GPR_%s%s(destreg,i) = %s;\n", signletter, letter, minimum );
+            }
+          printf("     else\n");
+          printf(" ");
+         }
+       printf("     GPR_%s%s(destreg,i) = r;\n", signletter, letter );
+       printf("    }\n");
+       break;
+     }
+
+    case PMULTH:
+     {
+       char* op;
+       if ( insn->flags & SUBTRACT )
+         op = "-";
+       else if ( insn->flags & ADDITION )
+         op = "+";
+       else
+         op = "";
+
+       printf("GPR_SW(destreg,0) = LO_SW(0) %s= (RS_SH(0) * RT_SH(0));\n", op);
+       printf("                    LO_SW(1) %s= (RS_SH(1) * RT_SH(1));\n", op);
+       printf("GPR_SW(destreg,1) = HI_SW(0) %s= (RS_SH(2) * RT_SH(2));\n", op);
+       printf("                    HI_SW(1) %s= (RS_SH(3) * RT_SH(3));\n", op);
+       printf("GPR_SW(destreg,2) = LO_SW(2) %s= (RS_SH(4) * RT_SH(4));\n", op);
+       printf("                    LO_SW(3) %s= (RS_SH(5) * RT_SH(5));\n", op);
+       printf("GPR_SW(destreg,3) = HI_SW(2) %s= (RS_SH(6) * RT_SH(6));\n", op);
+       printf("                    HI_SW(3) %s= (RS_SH(7) * RT_SH(7));\n", op);
+       break;
+     }
+
+    case PMULTW:
+     {
+       char* op;
+       char* sign  = (insn->flags & UNSIGNED) ? "U" : "S";
+       char* prodtype = (insn->flags & UNSIGNED) ? "unsigned64" : "signed64";
+       char* constructor = (insn->flags & UNSIGNED) ? "UWORD64" : "WORD64";
+
+       if ( insn->flags & SUBTRACT )
+         {
+           op = "-";
+           printf("   %s sum0 = %s( HI_SW(0), LO_SW(0) );\n", prodtype, constructor );
+           printf("   %s sum1 = %s( HI_SW(2), LO_SW(2) );\n", prodtype, constructor );
+         }
+       else if ( insn->flags & ADDITION )
+         {
+           op = "+";
+           printf("   %s sum0 = %s( HI_SW(0), LO_SW(0) );\n", prodtype, constructor );
+           printf("   %s sum1 = %s( HI_SW(2), LO_SW(2) );\n", prodtype, constructor );
+         }
+       else
+        {
+          op = "";
+          printf("   %s sum0 = 0;\n", prodtype );
+          printf("   %s sum1 = 0;\n", prodtype );
+        }
+          
+       printf("   %s prod0 = (%s)RS_%sW(0) * (%s)RT_%sW(0);\n", prodtype, prodtype, sign, prodtype, sign );
+       printf("   %s prod1 = (%s)RS_%sW(2) * (%s)RT_%sW(2);\n", prodtype, prodtype, sign, prodtype, sign );
+
+       printf("   sum0 %s= prod0;\n", op );
+       printf("   sum1 %s= prod1;\n", op );
+
+       printf("   GPR_%sD(destreg,0) = sum0;\n", sign );
+       printf("   GPR_%sD(destreg,1) = sum1;\n", sign );
+
+       printf("   LO  = SIGNEXTEND( sum0, 32 );\n");
+       printf("   HI  = SIGNEXTEND( WORD64HI(sum0), 32 );\n");
+       printf("   LO1 = SIGNEXTEND( sum1, 32 );\n");
+       printf("   HI1 = SIGNEXTEND( WORD64HI(sum1), 32 );\n");
+       break;
+     }
+
+    case PDIVW:
+     {
+       char* sign = (insn->flags & UNSIGNED) ? "U" : "S";
+       int i;
+       for (i = 0; i < 2; i ++)
+        {
+          char hi = (i == 0 ? ' ' : '1');
+          int d = i * 2;
+          if (! (insn->flags & UNSIGNED))
+            {
+              printf("if (RT_SW(%d) == -1)\n", d );
+              printf(" {\n");
+              printf("  LO%c = -RS_%sW(%d);\n", hi, sign, d );
+              printf("  HI%c = 0;\n", hi );
+              printf(" }\nelse ");
+            };
+          printf("if (RT_UW(%d) != 0)\n", d );
+          printf(" {\n");
+          printf("  LO%c = (signed32)(RS_%sW(%d) / RT_%sW(%d));\n", hi, sign, d, sign, d );
+          printf("  HI%c = (signed32)(RS_%sW(%d) %% RT_%sW(%d));\n", hi, sign, d, sign, d );
+          printf(" }\n");
+        }
+       break;
+     }
+
+    case PDIVBW:
+      printf("signed32 devisor = RT_SH(0);\n");
+      printf("if (devisor == -1)\n");
+      printf(" {\n");
+      printf("  LO_SW(0) = -RS_SW(0);\n");
+      printf("  HI_SW(0) = 0;\n");
+      printf("  LO_SW(1) = -RS_SW(1);\n");
+      printf("  HI_SW(1) = 0;\n");
+      printf("  LO_SW(2) = -RS_SW(2);\n");
+      printf("  HI_SW(2) = 0;\n");
+      printf("  LO_SW(3) = -RS_SW(3);\n");
+      printf("  HI_SW(3) = 0;\n");
+      printf(" }\n");
+      printf("else if (devisor != 0)\n");
+      printf(" {\n");
+      printf("  LO_SW(0) = RS_SW(0) / devisor;\n");
+      printf("  HI_SW(0) = SIGNEXTEND( (RS_SW(0) %% devisor), 16 );\n");
+      printf("  LO_SW(1) = RS_SW(1) / devisor;\n");
+      printf("  HI_SW(1) = SIGNEXTEND( (RS_SW(1) %% devisor), 16 );\n");
+      printf("  LO_SW(2) = RS_SW(2) / devisor;\n");
+      printf("  HI_SW(2) = SIGNEXTEND( (RS_SW(2) %% devisor), 16 );\n");
+      printf("  LO_SW(3) = RS_SW(3) / devisor;\n");
+      printf("  HI_SW(3) = SIGNEXTEND( (RS_SW(3) %% devisor), 16 );\n");
+      printf(" }\n");
+      break;
+
+    case PADSBH:
+     printf("int i;\n");
+     printf("for(i=0;i<HALFWORDS_IN_MMI_REGS/2;i++)\n");
+     printf("  GPR_SH(destreg,i) = RS_SH(i) - RT_SH(i);\n");
+     printf("for(;i<HALFWORDS_IN_MMI_REGS;i++)\n");
+     printf("  GPR_SH(destreg,i) = RS_SH(i) + RT_SH(i);\n");
+     break;
+
+    case PHMADDH:
+     {
+       char* op = (insn->flags & SUBTRACT) ? "-" : "+";
+       printf("GPR_SW(destreg,0) = LO_SW(0) = (RS_SH(1) * RT_SH(1)) %s (RS_SH(0) * RT_SH(0));\n", op );
+       printf("GPR_SW(destreg,1) = HI_SW(0) = (RS_SH(3) * RT_SH(3)) %s (RS_SH(2) * RT_SH(2));\n", op );
+       printf("GPR_SW(destreg,2) = LO_SW(2) = (RS_SH(5) * RT_SH(5)) %s (RS_SH(4) * RT_SH(4));\n", op );
+       printf("GPR_SW(destreg,3) = HI_SW(2) = (RS_SH(7) * RT_SH(7)) %s (RS_SH(6) * RT_SH(6));\n", op );
+     }
+     break;
+
+    case PSHIFT:
+     {
+       char* name = name_for_data_len( insn );
+       char* letter = letter_for_data_len( insn );
+       char* bits = bits_for_data_len( insn );
+       char* shift = (insn->flags & RIGHT) ? ">>" : "<<";
+       char* sign = (insn->flags & ARITHMETIC) ? "S" : "U";
+
+       printf("int shift_by = op1 & (%s-1);\n", bits );
+       printf("int i;\n");
+       printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
+       printf("    GPR_%s%s(destreg,i) = ", sign, letter );
+       if ( insn->flags & ARITHMETIC )
+         printf("SIGNEXTEND( ");
+       printf("(RT_%s%s(i) %s shift_by)", sign, letter, shift );
+       if ( insn->flags & ARITHMETIC )
+         printf(", (%s-shift_by) )", bits );
+       printf(";\n");
+       break;
+     }
+
+    case PSLLVW:
+     printf("int s0 = (RS_UB(0) & 0x1F);\n");
+     printf("int s1 = (RS_UB(8) & 0x1F);\n");
+     printf("signed32 temp0 = RT_UW(0) << s0;\n");
+     printf("signed32 temp1 = RT_UW(2) << s1;\n");
+     printf("GPR_SD(destreg,0) = (signed64)temp0;\n");
+     printf("GPR_SD(destreg,1) = (signed64)temp1;\n");
+     break;
+
+    case PSRLVW:
+     printf("GPR_UD(destreg,0) = SIGNEXTEND ( RT_UW(0) >> (RS_UB(0) & 0x1F), 31);\n");
+     printf("GPR_UD(destreg,1) = SIGNEXTEND ( RT_UW(2) >> (RS_UB(8) & 0x1F), 31);\n");
+     break;
+
+    case PSRAVW:
+     printf("GPR_SD(destreg,0) = SIGNEXTEND( (RT_SW (0) >> (RS_UB(0) & 0x1F)), 32-(RS_UB(0) & 0x1F) );\n");
+     printf("GPR_SD(destreg,1) = SIGNEXTEND( (RT_SW (2) >> (RS_UB(8) & 0x1F)), 32-(RS_UB(8) & 0x1F) );\n");
+     break;
+
+    case POP:
+     {
+       char* op1;
+       char* op2;
+       
+       if ( GET_OP_FROM_INSN(insn) == POP_AND )
+         {
+           op1 = "&";
+           op2 = "";
+         }
+       else if ( GET_OP_FROM_INSN(insn) == POP_OR )
+         {
+           op1 = "|";
+           op2 = "";
+         }
+       else if ( GET_OP_FROM_INSN(insn) == POP_NOR )
+         {
+           op1 = "|";
+           op2 = "~";
+         }
+       else if ( GET_OP_FROM_INSN(insn) == POP_XOR )
+         {
+           op1 = "^";
+           op2 = "";
+         }
+       
+       printf("int i;\n");
+       printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
+       printf("  GPR_UW(destreg,i) = %s(RS_UW(i) %s RT_UW(i));\n", op2, op1 );
+       break;
+     }
+
+    case PCMP:
+     {
+       char* name = name_for_data_len( insn );
+       char* letter = letter_for_data_len( insn );
+       char* maximum = umax_for_data_len( insn );
+       char* op = (insn->flags & GT) ? ">" : "==";
+
+       printf("int i;\n");
+       printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
+       printf("     {\n");
+       printf("     if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = %s;\n", 
+              letter, op, letter, letter, maximum );
+       printf("     else                        GPR_S%s(destreg,i) = 0;\n", letter );
+       printf("     }\n");
+       break;
+     }
+
+    case PMAXMIN:
+     {
+       char* name = name_for_data_len( insn );
+       char* letter = letter_for_data_len( insn );
+       char* op = (insn->flags & GT) ? ">" : "<";
+
+       printf("int i;\n");
+       printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
+       printf("     {\n");
+       printf("     if (RS_S%s(i) %s RT_S%s(i)) GPR_S%s(destreg,i) = RS_S%s(i);\n", 
+              letter, op, letter, letter, letter );
+       printf("     else                        GPR_S%s(destreg,i) = RT_S%s(i);\n", letter, letter );
+       printf("     }\n");
+       break;
+     }
+
+    case PABS:
+     {
+       char* name = name_for_data_len( insn );
+       char* letter = letter_for_data_len( insn );
+       char* min = min_for_data_len( insn );
+       char* max = max_for_data_len( insn );
+
+       printf("int i;\n");
+       printf("for(i=0;i<%sS_IN_MMI_REGS;i++)\n", name );
+       printf("  {\n");
+       printf("  if (RT_S%s(i) >= 0)\n", letter );
+       printf("    GPR_S%s(destreg,i) =  RT_S%s(i);\n", letter, letter );
+       printf("  else if (RT_S%s(i) == %s)\n", letter, min );
+       printf("    GPR_S%s(destreg,i) = %s;\n", letter, max );
+       printf("  else\n");
+       printf("    GPR_S%s(destreg,i) = -RT_S%s(i);\n", letter, letter );
+       printf("  }\n");
+       break;
+     }
+
+    case PCPYH:
+     printf("GPR_UH(destreg,7) = GPR_UH(destreg,6) = GPR_UH(destreg,5) = GPR_UH(destreg,4) = RT_UH(4);\n");
+     printf("GPR_UH(destreg,3) = GPR_UH(destreg,2) = GPR_UH(destreg,1) = GPR_UH(destreg,0) = RT_UH(0);\n");
+     break;
+
+    case PCPYLD:
+     printf("GPR_UD(destreg,0) = RT_UD(0);\n");
+     printf("GPR_UD(destreg,1) = RS_UD(0);\n");
+     break;
+
+    case PCPYUD:
+     printf("GPR_UD(destreg,0) = RS_UD(1);\n");
+     printf("GPR_UD(destreg,1) = RT_UD(1);\n");
+     break;
+
+    case PEXCH:
+     printf("GPR_UH(destreg,0) = RT_UH(0);\n");
+     printf("GPR_UH(destreg,1) = RT_UH(2);\n");
+     printf("GPR_UH(destreg,2) = RT_UH(1);\n");
+     printf("GPR_UH(destreg,3) = RT_UH(3);\n");
+     printf("GPR_UH(destreg,4) = RT_UH(4);\n");
+     printf("GPR_UH(destreg,5) = RT_UH(6);\n");
+     printf("GPR_UH(destreg,6) = RT_UH(5);\n");
+     printf("GPR_UH(destreg,7) = RT_UH(7);\n");
+     break;
+
+    case PEXCW:
+     printf("GPR_UW(destreg,0) = RT_UW(0);\n");
+     printf("GPR_UW(destreg,1) = RT_UW(2);\n");
+     printf("GPR_UW(destreg,2) = RT_UW(1);\n");
+     printf("GPR_UW(destreg,3) = RT_UW(3);\n");
+     break;
+
+    case PEXOH:
+     printf("GPR_UH(destreg,0) = RT_UH(2);\n");
+     printf("GPR_UH(destreg,1) = RT_UH(1);\n");
+     printf("GPR_UH(destreg,2) = RT_UH(0);\n");
+     printf("GPR_UH(destreg,3) = RT_UH(3);\n");
+     printf("GPR_UH(destreg,4) = RT_UH(6);\n");
+     printf("GPR_UH(destreg,5) = RT_UH(5);\n");
+     printf("GPR_UH(destreg,6) = RT_UH(4);\n");
+     printf("GPR_UH(destreg,7) = RT_UH(7);\n");
+     break;
+
+    case PEXOW:
+     printf("GPR_UW(destreg,0) = RT_UW(2);\n");
+     printf("GPR_UW(destreg,1) = RT_UW(1);\n");
+     printf("GPR_UW(destreg,2) = RT_UW(0);\n");
+     printf("GPR_UW(destreg,3) = RT_UW(3);\n");
+     break;
+
+    case PEXTLB:
+     printf("GPR_UB(destreg,0)  = RT_UB(0);\n");
+     printf("GPR_UB(destreg,1)  = RS_UB(0);\n");
+     printf("GPR_UB(destreg,2)  = RT_UB(1);\n");
+     printf("GPR_UB(destreg,3)  = RS_UB(1);\n");
+     printf("GPR_UB(destreg,4)  = RT_UB(2);\n");
+     printf("GPR_UB(destreg,5)  = RS_UB(2);\n");
+     printf("GPR_UB(destreg,6)  = RT_UB(3);\n");
+     printf("GPR_UB(destreg,7)  = RS_UB(3);\n");
+     printf("GPR_UB(destreg,8)  = RT_UB(4);\n");
+     printf("GPR_UB(destreg,9)  = RS_UB(4);\n");
+     printf("GPR_UB(destreg,10) = RT_UB(5);\n");
+     printf("GPR_UB(destreg,11) = RS_UB(5);\n");
+     printf("GPR_UB(destreg,12) = RT_UB(6);\n");
+     printf("GPR_UB(destreg,13) = RS_UB(6);\n");
+     printf("GPR_UB(destreg,14) = RT_UB(7);\n");
+     printf("GPR_UB(destreg,15) = RS_UB(7);\n");
+     break;
+
+    case PEXTLH:
+     printf("GPR_UH(destreg,0)  = RT_UH(0);\n");
+     printf("GPR_UH(destreg,1)  = RS_UH(0);\n");
+     printf("GPR_UH(destreg,2)  = RT_UH(1);\n");
+     printf("GPR_UH(destreg,3)  = RS_UH(1);\n");
+     printf("GPR_UH(destreg,4)  = RT_UH(2);\n");
+     printf("GPR_UH(destreg,5)  = RS_UH(2);\n");
+     printf("GPR_UH(destreg,6)  = RT_UH(3);\n");
+     printf("GPR_UH(destreg,7)  = RS_UH(3);\n");
+     break;
+
+    case PEXTLW:
+     printf("GPR_UW(destreg,0)  = RT_UW(0);\n");
+     printf("GPR_UW(destreg,1)  = RS_UW(0);\n");
+     printf("GPR_UW(destreg,2)  = RT_UW(1);\n");
+     printf("GPR_UW(destreg,3)  = RS_UW(1);\n");
+     break;
+
+    case PEXTUB:
+     printf("GPR_UB(destreg,0)  = RT_UB(8);\n");
+     printf("GPR_UB(destreg,1)  = RS_UB(8);\n");
+     printf("GPR_UB(destreg,2)  = RT_UB(9);\n");
+     printf("GPR_UB(destreg,3)  = RS_UB(9);\n");
+     printf("GPR_UB(destreg,4)  = RT_UB(10);\n");
+     printf("GPR_UB(destreg,5)  = RS_UB(10);\n");
+     printf("GPR_UB(destreg,6)  = RT_UB(11);\n");
+     printf("GPR_UB(destreg,7)  = RS_UB(11);\n");
+     printf("GPR_UB(destreg,8)  = RT_UB(12);\n");
+     printf("GPR_UB(destreg,9)  = RS_UB(12);\n");
+     printf("GPR_UB(destreg,10) = RT_UB(13);\n");
+     printf("GPR_UB(destreg,11) = RS_UB(13);\n");
+     printf("GPR_UB(destreg,12) = RT_UB(14);\n");
+     printf("GPR_UB(destreg,13) = RS_UB(14);\n");
+     printf("GPR_UB(destreg,14) = RT_UB(15);\n");
+     printf("GPR_UB(destreg,15) = RS_UB(15);\n");
+     break;
+
+    case PEXTUH:
+     printf("GPR_UH(destreg,0)  = RT_UH(4);\n");
+     printf("GPR_UH(destreg,1)  = RS_UH(4);\n");
+     printf("GPR_UH(destreg,2)  = RT_UH(5);\n");
+     printf("GPR_UH(destreg,3)  = RS_UH(5);\n");
+     printf("GPR_UH(destreg,4)  = RT_UH(6);\n");
+     printf("GPR_UH(destreg,5)  = RS_UH(6);\n");
+     printf("GPR_UH(destreg,6)  = RT_UH(7);\n");
+     printf("GPR_UH(destreg,7)  = RS_UH(7);\n");
+     break;
+
+    case PEXTUW:
+     printf("GPR_UW(destreg,0)  = RT_UW(2);\n");
+     printf("GPR_UW(destreg,1)  = RS_UW(2);\n");
+     printf("GPR_UW(destreg,2)  = RT_UW(3);\n");
+     printf("GPR_UW(destreg,3)  = RS_UW(3);\n");
+     break;
+
+    case PPACB:
+     printf("GPR_UB(destreg,0)  = RT_UB(0);\n");
+     printf("GPR_UB(destreg,1)  = RT_UB(2);\n");
+     printf("GPR_UB(destreg,2)  = RT_UB(4);\n");
+     printf("GPR_UB(destreg,3)  = RT_UB(6);\n");
+     printf("GPR_UB(destreg,4)  = RT_UB(8);\n");
+     printf("GPR_UB(destreg,5)  = RT_UB(10);\n");
+     printf("GPR_UB(destreg,6)  = RT_UB(12);\n");
+     printf("GPR_UB(destreg,7)  = RT_UB(14);\n");
+     printf("GPR_UB(destreg,8)  = RS_UB(0);\n");
+     printf("GPR_UB(destreg,9)  = RS_UB(2);\n");
+     printf("GPR_UB(destreg,10) = RS_UB(4);\n");
+     printf("GPR_UB(destreg,11) = RS_UB(6);\n");
+     printf("GPR_UB(destreg,12) = RS_UB(8);\n");
+     printf("GPR_UB(destreg,13) = RS_UB(10);\n");
+     printf("GPR_UB(destreg,14) = RS_UB(12);\n");
+     printf("GPR_UB(destreg,15) = RS_UB(14);\n");
+     break;
+
+    case PPACH:
+     printf("GPR_UH(destreg,0)  = RT_UH(0);\n");
+     printf("GPR_UH(destreg,1)  = RT_UH(2);\n");
+     printf("GPR_UH(destreg,2)  = RT_UH(4);\n");
+     printf("GPR_UH(destreg,3)  = RT_UH(6);\n");
+     printf("GPR_UH(destreg,4)  = RS_UH(0);\n");
+     printf("GPR_UH(destreg,5)  = RS_UH(2);\n");
+     printf("GPR_UH(destreg,6)  = RS_UH(4);\n");
+     printf("GPR_UH(destreg,7)  = RS_UH(6);\n");
+     break;
+
+    case PPACW:
+     printf("GPR_UW(destreg,0)  = RT_UW(0);\n");
+     printf("GPR_UW(destreg,1)  = RT_UW(2);\n");
+     printf("GPR_UW(destreg,2)  = RS_UW(0);\n");
+     printf("GPR_UW(destreg,3)  = RS_UW(2);\n");
+     break;
+
+    case PREVH:
+     printf("GPR_UH(destreg,0)  = RT_UH(3);\n");
+     printf("GPR_UH(destreg,1)  = RT_UH(2);\n");
+     printf("GPR_UH(destreg,2)  = RT_UH(1);\n");
+     printf("GPR_UH(destreg,3)  = RT_UH(0);\n");
+     printf("GPR_UH(destreg,4)  = RT_UH(7);\n");
+     printf("GPR_UH(destreg,5)  = RT_UH(6);\n");
+     printf("GPR_UH(destreg,6)  = RT_UH(5);\n");
+     printf("GPR_UH(destreg,7)  = RT_UH(4);\n");
+     break;
+
+    case PROT3W:
+     printf("GPR_UW(destreg,0)  = RT_UW(0);\n");
+     printf("GPR_UW(destreg,1)  = RT_UW(3);\n");
+     printf("GPR_UW(destreg,2)  = RT_UW(1);\n");
+     printf("GPR_UW(destreg,3)  = RT_UW(2);\n");
+     break;
+
+    case PINTH:
+     printf("GPR_UH(destreg,0)  = RT_UH(0);\n");
+     printf("GPR_UH(destreg,1)  = RS_UH(4);\n");
+     printf("GPR_UH(destreg,2)  = RT_UH(1);\n");
+     printf("GPR_UH(destreg,3)  = RS_UH(5);\n");
+     printf("GPR_UH(destreg,4)  = RT_UH(2);\n");
+     printf("GPR_UH(destreg,5)  = RS_UH(6);\n");
+     printf("GPR_UH(destreg,6)  = RT_UH(3);\n");
+     printf("GPR_UH(destreg,7)  = RS_UH(7);\n");
+     break;
+
+    case PINTOH:
+     printf("GPR_UH(destreg,0) = RT_UH(0);\n");
+     printf("GPR_UH(destreg,1) = RS_UH(0);\n");
+     printf("GPR_UH(destreg,2) = RT_UH(2);\n");
+     printf("GPR_UH(destreg,3) = RS_UH(2);\n");
+     printf("GPR_UH(destreg,4) = RT_UH(4);\n");
+     printf("GPR_UH(destreg,5) = RS_UH(4);\n");
+     printf("GPR_UH(destreg,6) = RT_UH(6);\n");
+     printf("GPR_UH(destreg,7) = RS_UH(6);\n");
+     break;
+
+    case PMXX:  /* Parallel move HI or LO / TO or FROM */
+     {
+       if ( (insn->flags & (HI|FROM)) == (HI|FROM) )
+         {
+           printf("GPR_SD(destreg,0) = HI;\n");
+           printf("GPR_SD(destreg,1) = HI1;\n");
+         }
+       else if ( (insn->flags & (LO|FROM)) == (LO|FROM) )
+         {
+           printf("GPR_SD(destreg,0) = LO;\n");
+           printf("GPR_SD(destreg,1) = LO1;\n");
+         }
+       else if ( (insn->flags & (HI|TO)) == (HI|TO) )
+         {
+           printf("HI  = RS_SD(0);\n");
+           printf("HI1 = RS_SD(1);\n");
+         }
+       else if ( (insn->flags & (LO|TO)) == (LO|TO) )
+         {
+           printf("LO  = RS_SD(0);\n");
+           printf("LO1 = RS_SD(1);\n");
+         }
+       break;
+     }
+
+    case PMTHL:
+     printf("LO_UW(0) = RS_UW(0);\n");
+     printf("HI_UW(0) = RS_UW(1);\n");
+     printf("LO_UW(2) = RS_UW(2);\n");
+     printf("HI_UW(2) = RS_UW(3);\n");
+     break;
+
+    case PMFHL:
+     printf("if (op1 == 0)\n");
+     printf("  {\n");
+     printf("  GPR_UW(destreg,0) = LO_UW(0);\n");
+     printf("  GPR_UW(destreg,1) = HI_UW(0);\n");
+     printf("  GPR_UW(destreg,2) = LO_UW(2);\n");
+     printf("  GPR_UW(destreg,3) = HI_UW(2);\n");
+     printf("  }\n");
+     printf("else if (op1 == 1)\n");
+     printf("  {\n");
+     printf("  GPR_UW(destreg,0) = LO_UW(1);\n");
+     printf("  GPR_UW(destreg,1) = HI_UW(1);\n");
+     printf("  GPR_UW(destreg,2) = LO_UW(3);\n");
+     printf("  GPR_UW(destreg,3) = HI_UW(3);\n");
+     printf("  }\n");
+     printf("else if (op1 == 2)\n");
+     printf("  {\n");
+     printf("  /* NOTE: This code implements a saturate according to the\n");
+     printf("           figure on page B-115 and not according to the\n");
+     printf("           definition on page B-113 */\n");
+     printf("  signed64 t = ((unsigned64)HI_UW(0) << 32) | (unsigned64)LO_UW(0);\n");
+     printf("  signed64 u = ((unsigned64)HI_UW(2) << 32) | (unsigned64)LO_UW(2);\n");
+     printf("  if ( t > SIGNED64 (0x000000007FFFFFFF) )\n");
+     printf("    GPR_SD(destreg,0) = SIGNED64 (0x000000007FFFFFFF);\n");
+     printf("  else if ( t < - SIGNED64 (0x0000000080000000) )\n");
+     printf("    GPR_SD(destreg,0) = - SIGNED64 (0x0000000080000000);\n");
+     printf("  else\n");
+     printf("    GPR_SD(destreg,0) = t;\n");
+     printf("  if ( u > SIGNED64 (0x000000007FFFFFFF) )\n");
+     printf("    GPR_SD(destreg,1) = SIGNED64 (0x000000007FFFFFFF);\n");
+     printf("  else if ( u < - SIGNED64 (0x0000000080000000) )\n");
+     printf("    GPR_SD(destreg,1) = - SIGNED64 (0x0000000080000000);\n");
+     printf("  else\n");
+     printf("    GPR_SD(destreg,1) = u;\n");
+     printf("  }\n");
+     printf("else if (op1 == 3)\n");
+     printf("  {\n");
+     printf("  GPR_UH(destreg,0) = LO_UH(0);\n");
+     printf("  GPR_UH(destreg,1) = LO_UH(2);\n");
+     printf("  GPR_UH(destreg,2) = HI_UH(0);\n");
+     printf("  GPR_UH(destreg,3) = HI_UH(2);\n");
+     printf("  GPR_UH(destreg,4) = LO_UH(4);\n");
+     printf("  GPR_UH(destreg,5) = LO_UH(6);\n");
+     printf("  GPR_UH(destreg,6) = HI_UH(4);\n");
+     printf("  GPR_UH(destreg,7) = HI_UH(6);\n");
+     printf("  }\n");
+     printf("else if (op1 == 4)\n");
+     printf("  {\n");
+     printf("  if (LO_SW(0) > 0x7FFF)\n");
+     printf("    GPR_UH(destreg,0) = 0x7FFF;\n");
+     printf("  else if (LO_SW(0) < -0x8000)\n");
+     printf("    GPR_UH(destreg,0) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,0) = LO_UH(0);\n");
+
+     printf("  if (LO_SW(1) > 0x7FFF)\n");
+     printf("    GPR_UH(destreg,1) = 0x7FFF;\n");
+     printf("  else if (LO_SW(1) < -0x8000)\n");
+     printf("    GPR_UH(destreg,1) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,1) = LO_UH(2);\n");
+
+     printf("  if (HI_SW(0) > 0x7FFF)\n");
+     printf("    GPR_UH(destreg,2) = 0x7FFF;\n");
+     printf("  else if (HI_SW(0) < -0x8000)\n");
+     printf("    GPR_UH(destreg,2) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,2) = HI_UH(0);\n");
+
+     printf("  if (HI_SW(1) > 0x7FFF)\n");
+     printf("    GPR_UH(destreg,3) = 0x7FFF;\n");
+     printf("  else if (HI_SW(1) < -0x8000)\n");
+     printf("    GPR_UH(destreg,3) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,3) = HI_UH(2);\n");
+
+     printf("  if (LO_SW(2) > 0x7FFF)\n");
+     printf("    GPR_UH(destreg,4) = 0x7FFF;\n");
+     printf("  else if (LO_SW(2) < -0x8000)\n");
+     printf("    GPR_UH(destreg,4) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,4) = LO_UH(4);\n");
+
+     printf("  if (LO_SW(3) > 0x7FFF)\n");
+     printf("    GPR_UH(destreg,5) = 0x7FFF;\n");
+     printf("  else if (LO_SW(3) < -0x8000)\n");
+     printf("    GPR_UH(destreg,5) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,5) = LO_UH(6);\n");
+
+     printf("  if (HI_SW(2) > 0x7FFF)\n");
+     printf("    GPR_UH(destreg,6) = 0x7FFF;\n");
+     printf("  else if (HI_SW(2) < -0x8000)\n");
+     printf("    GPR_UH(destreg,6) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,6) = HI_UH(4);\n");
+
+     printf("  if (HI_SW(3) > 0x7FFF)\n");
+     printf("    GPR_UH(destreg,7) = 0x7FFF;\n");
+     printf("  else if (HI_SW(3) < -0x8000)\n");
+     printf("    GPR_UH(destreg,7) = 0x8000;\n");
+     printf("  else\n");
+     printf("    GPR_UH(destreg,7) = HI_UH(6);\n");
+
+     printf("  }\n");
+     break;
+
+    case PLZCW:
+      printf("unsigned long value;\n");
+      printf("int test;\n");
+      printf("int count;\n");
+      printf("int i;\n");
+
+      printf("value = RS_UW(0);\n");
+      printf("count = 0;\n");
+      printf("test = !!(value & (1 << 31));\n");
+      printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
+      printf("  count++;\n");
+      printf("GPR_UW(destreg,0) = count;\n");
+
+      printf("value = RS_UW(1);\n");
+      printf("count = 0;\n");
+      printf("test = !!(value & (1 << 31));\n");
+      printf("for(i=30; i>=0 && (test == !!(value & (1 << i))); i--)\n");
+      printf("  count++;\n");
+      printf("GPR_UW(destreg,1) = count;\n");
+      break;
+
+    case PEXT5:
+      printf("int i;\n");
+      printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
+      printf("  {\n");
+      printf("  unsigned32 x = RT_UW(i);\n");
+      printf("  GPR_UW(destreg,i) = ((x & (1  << 15)) << (31 - 15))  \n");
+      printf("                    | ((x & (31 << 10)) << (19 - 10))  \n");
+      printf("                    | ((x & (31 << 5))  << (11 - 5))   \n");
+      printf("                    | ((x & (31 << 0))  << (3  - 0));  \n");
+      printf("  }\n");
+      break;
+
+    case PPAC5:
+      printf("int i;\n");
+      printf("for(i=0;i<WORDS_IN_MMI_REGS;i++)\n");
+      printf("  {\n");
+      printf("  unsigned32 x = RT_UW(i);\n");
+      printf("  GPR_UW(destreg,i) = ((x & (1  << 31)) >> (31 - 15))  \n");
+      printf("                    | ((x & (31 << 19)) >> (19 - 10))  \n");
+      printf("                    | ((x & (31 << 11)) >> (11 - 5))   \n");
+      printf("                    | ((x & (31 <<  3)) >> (3  - 0));  \n");
+      printf("  }\n");
+      break;
+/* end-sanitize-r5900 */
+
+    case NYI:
+     fprintf(stderr,"Warning: Unimplemented opcode: %s\n",insn->name) ;
+
+     printf("SignalException(ReservedInstruction,instruction);\n");
+     break;
+
     default:
      fprintf(stderr,"Unrecognised opcode type %d\n",insn->type) ;
      exit(6) ;
@@ -2664,6 +4468,16 @@ struct architectures {
 
 static const struct architectures available_architectures[] = {
   {"4100",ARCH_VR4100}, /* NEC MIPS VR4100 */
+  {"3900",ARCH_R3900},   /* Toshiba R3900 (TX39) */
+  /* start-sanitize-tx49 */
+  {"4900",ARCH_R4900},   /* Toshiba R4900 (TX49) */
+  /* end-sanitize-tx49  */
+  /* start-sanitize-tx19 */
+  {"1900",ARCH_R3900},   /* Toshiba R1900 (TX19) */
+  /* end-sanitize-tx19  */
+  /* start-sanitize-r5900 */
+  {"5900",ARCH_R5900},
+  /* end-sanitize-r5900 */
   {0,     0}            /* terminator */
 };
 
@@ -2751,6 +4565,7 @@ main(argc,argv)
       {"fast",    0,0,'f'},
       {"help",    0,0,'h'},
       {"warnings",0,0,'w'},
+      {"igen",    0,0,'i'},
       {0,         0,0,0}
     };
    
@@ -2767,6 +4582,10 @@ main(argc,argv)
        features |= FEATURE_FAST;
        break;
 
+      case 'i' : /* igen formatted output */
+       features |= FEATURE_IGEN;
+       break;
+
       case 'w' : /* warnings */
        features |= FEATURE_WARNINGS;
        /* TODO: Future extension: Allow better control over the warnings generated:
This page took 0.059107 seconds and 4 git commands to generate.