#define DEBUG (1) /* Just for testing */
#endif
-/* The Makefile currently defines "INSIDE_SIMULATOR" as part of the
- build. It is not currently used by the MIPS simulator world
- though. */
-
/* All output sent to stdout is for the simulator engine. All program
related warnings and errors should be sent to stderr. */
#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 */
access Rn in an instruction immediately following an Rn update
"WARNING : Invalid value read". The simulator engine is designed
that the previous value is read in such cases, to allow programs
- that make use of this feature to execute. *
+ that make use of this feature to execute. */
/* If MIPS II or later, attempting to read a register before the
update has completed will generate a "WARNING : Processor stall"
message (since the processor will lock the pipeline until the value
#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 */
{'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,
COP1,
COP1X,
COP1S, /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
- UNKNOWN
+
+ 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;
/* Main instruction families: */
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 */
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;
#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: */
#define MULTIPLY (1 << 3) /* actually FP multiply ADD/SUB modifier */
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 */
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
{"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 | LIKELY)},
+ {"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)},
{"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)},
+ {"DSLLV", 3,"000000sssssgggggddddd00000010100",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL | REG)},
{"DSLL32", 3,"00000000000gggggdddddaaaaa111100",SPECIAL,SHIFT, (DOUBLEWORD | LEFT | LOGICAL | HI32)}, /* rd = rt << (sa + 32) */
{"DSRA", 3,"00000000000gggggdddddaaaaa111011",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC)},
- {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC)},
+ {"DSRAV", 3,"000000sssssgggggddddd00000010111",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC | REG)},
{"DSRA32", 3,"00000000000gggggdddddaaaaa111111",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | ARITHMETIC | HI32)}, /* rd = rt >> (sa + 32) */
{"DSRL", 3,"00000000000gggggdddddaaaaa111010",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL)},
- {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL)},
+ {"DSRLV", 3,"000000sssssgggggddddd00000010110",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL | REG)},
{"DSRL32", 3,"00000000000gggggdddddaaaaa111110",SPECIAL,SHIFT, (DOUBLEWORD | RIGHT | LOGICAL | HI32)},
{"DSUB", 3,"000000sssssgggggddddd00000101110",SPECIAL,SUB, (DOUBLEWORD)},
{"DSUBU", 3,"000000sssssgggggddddd00000101111",SPECIAL,SUB, (DOUBLEWORD | UNSIGNED)},
{"J", 1,"000010jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (NONE)}, /* NOTE: boundary case due to delay slot address being used */
{"JAL", 1,"000011jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (LINK)}, /* NOTE: boundary case due to delay slot address being used */
{"JALR", 1,"000000sssss00000ddddd00000001001",SPECIAL,JUMP, (LINK | REG)},
+ {"JALX", 1,"011101jjjjjjjjjjjjjjjjjjjjjjjjjj",NORMAL, JUMP, (LINK | NOT)},
{"JR", 1,"000000sssss000000000000000001000",SPECIAL,JUMP, (NONE)}, /* need to check PC as part of instruction fetch */
{"LB", 1,"100000ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (BYTE | SIGNEXTEND)}, /* NOTE: "i" rather than "o" because BYTE addressing is allowed */
{"LBU", 1,"100100ssssstttttyyyyyyyyyyyyyyyy",NORMAL, LOAD, (BYTE)}, /* NOTE: See "LB" comment */
{"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)},
- {"MFHI", 1,"0000000000000000ddddd00000010000",SPECIAL,MOVE, (HI)}, /* with following, from and to denoted by usage of "s" or "d" */
- {"MFLO", 1,"0000000000000000ddddd00000010010",SPECIAL,MOVE, (LO)},
- {"MTHI", 1,"000000sssss000000000000000010001",SPECIAL,MOVE, (HI)},
- {"MTLO", 1,"000000sssss000000000000000010011",SPECIAL,MOVE, (LO)},
+ {"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)},
{"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)},
{"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 */
{"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)},
{"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)},
{"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)},
};
+static const struct instruction MIPS16_DECODE[] = {
+{"ADDIU", 1, "01000xxxddd04444", RRI_A, ADD, WORD | WORD32 },
+{"ADDIU8", 1, "01001wwwkkkkkkkk", RI, ADD, WORD | WORD32 },
+{"ADJSP", 1, "01100011KKKKKKKKS", I8, ADD, WORD | WORD32 },
+{"ADDIUPC", 1, "00001dddAAAAAAAAP", RI, ADD, WORD | WORD32 },
+{"ADDIUSP", 1, "00000dddAAAAAAAAs", RI, ADD, WORD | WORD32 },
+{"ADDU", 1, "11100xxxyyyddd01", RRR, ADD, WORD | WORD32 },
+{"AND", 1, "11101wwwyyy01100", RR, AND, NONE },
+{"B", 1, "00010qqqqqqqqqqqzZ", I, BRANCH, EQ },
+{"BEQZ", 1, "00100xxxppppppppz", RI, BRANCH, EQ },
+{"BNEZ", 1, "00101xxxppppppppz", RI, BRANCH, NOT | EQ },
+{"BREAK", 1, "01100??????00101", RR, BREAK, NOARG },
+{"BTEQZ", 1, "01100000pppppppptz", I8, BRANCH, EQ },
+{"BTNEZ", 1, "01100001pppppppptz", I8, BRANCH, NOT | EQ },
+{"CMP", 1, "11101xxxyyy01010T", RR, XOR, NONE },
+{"CMPI", 1, "01110xxxUUUUUUUUT", RI, XOR, NONE },
+{"DADDIU", 3, "01000xxxddd14444", RRI_A, ADD, DOUBLEWORD },
+{"DADDIU5", 3, "11111101wwwjjjjj", RI64, ADD, DOUBLEWORD },
+{"DADJSP", 3, "11111011KKKKKKKKS", I64, ADD, DOUBLEWORD },
+{"DADIUPC", 3, "11111110dddEEEEEP", RI64, ADD, DOUBLEWORD },
+{"DADIUSP", 3, "11111111dddEEEEEs", RI64, ADD, DOUBLEWORD },
+{"DADDU", 3, "11100xxxyyyddd00", RRR, ADD, DOUBLEWORD },
+{"DDIV", 3, "11101xxxyyy11110", RR, DIV, DOUBLEWORD | HI | LO },
+{"DDIVU", 3, "11101xxxyyy11111", RR, DIV, DOUBLEWORD | UNSIGNED | HI | LO },
+{"DIV", 1, "11101xxxyyy11010", RR, DIV, WORD | WORD32 | SIGNEXTEND | HI | LO },
+{"DIVU", 1, "11101xxxyyy11011", RR, DIV, WORD | WORD32 | UNSIGNED | SIGNEXTEND | HI | LO },
+{"DMULT", 3, "11101xxxyyy11100", RR, MUL, DOUBLEWORD | HI | LO },
+{"DMULTU", 3, "11101xxxyyy11101", RR, MUL, DOUBLEWORD | UNSIGNED | HI | LO },
+{"DSLL", 3, "00110dddyyy[[[01", ISHIFT, SHIFT, DOUBLEWORD | LEFT | LOGICAL },
+{"DSLLV", 3, "11101xxxvvv10100", RR, SHIFT, DOUBLEWORD | LEFT | LOGICAL | REG },
+{"DSRA", 3, "11101]]]vvv10011", RR, SHIFT, DOUBLEWORD | RIGHT | ARITHMETIC },
+{"DSRAV", 3, "11101xxxvvv10111", RR, SHIFT, DOUBLEWORD | RIGHT | ARITHMETIC | REG},
+{"DSRL", 3, "11101]]]vvv01000", RR, SHIFT, DOUBLEWORD | RIGHT | LOGICAL },
+{"DSRLV", 3, "11101xxxvvv10110", RR, SHIFT, DOUBLEWORD | RIGHT | LOGICAL | REG},
+{"DSUBU", 3, "11100xxxyyyddd10", RRR, SUB, DOUBLEWORD | UNSIGNED},
+#if 0
+ /* FIXME: Should we handle these ourselves, or should we require an
+ emulation routine? */
+{"EXIT", 1, "1110111100001000", RR, BREAK, EXIT },
+{"ENTRY", 1, "11101??????01000", RR, BREAK, ENTRY },
+#endif
+{"EXTEND", 1, "11110eeeeeeeeeee", I, RSVD, NOARG },
+{"JALR", 1, "11101xxx01000000R", RR, JUMP, LINK | REG },
+{"JAL", 1, "00011aaaaaaaaaaa", I, JUMP, LINK },
+{"JR", 1, "11101xxx00000000", RR, JUMP, NONE },
+{"JRRA", 1, "1110100000100000r", RR, JUMP, NONE },
+{"LB", 1, "10000xxxddd55555", RRI, LOAD, BYTE | SIGNEXTEND },
+{"LBU", 1, "10100xxxddd55555", RRI, LOAD, BYTE },
+{"LD", 3, "00111xxxdddDDDDD", RRI, LOAD, DOUBLEWORD },
+{"LDPC", 3, "11111100dddDDDDDP", RI64, LOAD, DOUBLEWORD },
+{"LDSP", 3, "11111000dddDDDDDs", RI64, LOAD, DOUBLEWORD },
+{"LH", 1, "10001xxxdddHHHHH", RRI, LOAD, HALFWORD | SIGNEXTEND },
+{"LHU", 1, "10101xxxdddHHHHH", RRI, LOAD, HALFWORD },
+{"LI", 1, "01101dddUUUUUUUUZ", RI, OR, NONE },
+{"LW", 1, "10011xxxdddWWWWW", RRI, LOAD, WORD | SIGNEXTEND },
+{"LWPC", 1, "10110dddVVVVVVVVP", RI, LOAD, WORD | SIGNEXTEND },
+{"LWSP", 1, "10010dddVVVVVVVVs", RI, LOAD, WORD | SIGNEXTEND },
+{"LWU", 1, "10111xxxdddWWWWW", RRI, LOAD, WORD },
+{"MFHI", 1, "11101ddd00010000", RR, MOVE, HI | LEFT },
+{"MFLO", 1, "11101ddd00010010", RR, MOVE, LO | LEFT },
+{"MOVR32", 1, "01100111dddXXXXXz", I8_MOVR32, OR, NONE },
+{"MOV32R", 1, "01100101YYYYYxxxz", I8_MOV32R, OR, NONE },
+{"MULT", 1, "11101xxxyyy11000", RR, MUL, WORD | WORD32 | HI | LO},
+{"MULTU", 1, "11101xxxyyy11001", RR, MUL, WORD | WORD32 | UNSIGNED | HI | LO },
+{"NEG", 1, "11101dddyyy01011Z", RR, SUB, WORD },
+{"NOT", 1, "11101dddyyy01111Z", RR, OR, NOT },
+{"OR", 1, "11101wwwyyy01101", RR, OR, NONE },
+{"SB", 1, "11000xxxyyy55555", RRI, STORE, BYTE },
+{"SDBBP", G7, "11100??????00001", RR, SDBBP, NOARG },
+{"SD", 3, "01111xxxyyyDDDDD", RRI, STORE, DOUBLEWORD },
+{"SDSP", 3, "11111001yyyDDDDDs", RI64, STORE, DOUBLEWORD },
+{"SDRASP", 3, "11111010CCCCCCCCsQ", I64, STORE, DOUBLEWORD },
+{"SH", 1, "11001xxxyyyHHHHH", RRI, STORE, HALFWORD },
+{"SLL", 1, "00110dddyyy<<<00", ISHIFT, SHIFT, WORD | LEFT | LOGICAL },
+{"SLLV", 1, "11101xxxvvv00100", RR, SHIFT, WORD | LEFT | LOGICAL | REG},
+{"SLT", 1, "11101xxxyyy00010T", RR, SET, LT },
+{"SLTI", 1, "01010xxx88888888T", RI, SET, LT },
+{"SLTU", 1, "11101xxxyyy00011T", RR, SET, LT | UNSIGNED },
+{"SLTIU", 1, "01011xxx88888888T", RI, SET, LT | UNSIGNED },
+{"SRA", 1, "00110dddyyy<<<11", ISHIFT, SHIFT, WORD | WORD32 | RIGHT | ARITHMETIC },
+{"SRAV", 1, "11101xxxvvv00111", RR, SHIFT, WORD | WORD32 | RIGHT | ARITHMETIC | REG },
+{"SRL", 1, "00110dddyyy<<<10", ISHIFT, SHIFT, WORD | WORD32 | RIGHT | LOGICAL },
+{"SRLV", 1, "11101xxxvvv00110", RR, SHIFT, WORD | WORD32 | RIGHT | LOGICAL | REG },
+{"SUBU", 1, "11100xxxyyyddd11", RRR, SUB, WORD | WORD32 },
+{"SW", 1, "11011xxxyyyWWWWW", RRI, STORE, WORD },
+{"SWSP", 1, "11010yyyVVVVVVVVs", RI, STORE, WORD },
+{"SWRASP", 1, "01100010VVVVVVVVQs", I8, STORE, WORD },
+{"XOR", 1, "11101wwwyyy01110", RR, XOR, NONE }
+};
+
+/*---------------------------------------------------------------------------*/
+
+static void print_igen_insn_format PARAMS ((const char *bitmap,
+ inst_type mark,
+ int data_size,
+ const char *options,
+ const char *name));
+
+static void
+print_igen_insn_format (bitmap, mark, data_size, options, name)
+ const char *bitmap;
+ inst_type mark;
+ int data_size;
+ const char *options;
+ const char *name;
+{
+ const char *chp;
+ char lch = *bitmap;
+ for (chp = bitmap; *chp != '\0'; chp++)
+ {
+ if ((isdigit (lch) && !isdigit (*chp))
+ || (!isdigit (lch) && isdigit (*chp))
+ || (!isdigit (lch) && !isdigit (*chp) && lch != *chp))
+ {
+ lch = *chp;
+ printf (",");
+ }
+ switch (*chp)
+ {
+ case '?':
+ printf ("*");
+ break;
+ case '<':
+ printf ("s"); /* good guess */
+ break;
+ default:
+ printf ("%c", *chp);
+ break;
+ }
+ }
+ printf (":");
+ switch (mark)
+ {
+ case NORMAL:
+ printf ("NORMAL");
+ break;
+ case SPECIAL:
+ printf ("SPECIAL");
+ break;
+ case REGIMM:
+ printf ("REGIMM");
+ break;
+ case COP1:
+ printf ("COP1");
+ break;
+ case COP1X:
+ printf ("COP1X");
+ break;
+ case COP1S: /* These instructions live in the reserved FP format values: 0..15,18-19,22-31 */
+ printf ("COP1S");
+ break;
+
+ case MMINORM:
+ printf ("MMINORM");
+ break;
+ case MMI0:
+ printf ("MMI0");
+ break;
+ case MMI1:
+ printf ("MMI1");
+ break;
+ case MMI2:
+ printf ("MMI2");
+ break;
+ case MMI3:
+ printf ("MMI3");
+ break;
+
+ /* mips16 encoding types. */
+ case I:
+ printf ("I");
+ break;
+ case RI:
+ printf ("RI");
+ break;
+ case RR:
+ printf ("RR");
+ break;
+ case RRI:
+ printf ("RRI");
+ break;
+ case RRR:
+ printf ("RRR");
+ break;
+ case RRI_A:
+ printf ("RRI_A");
+ break;
+ case ISHIFT:
+ printf ("ISHIFT");
+ break;
+ case I8:
+ printf ("I8");
+ break;
+ case I8_MOVR32:
+ printf ("I8_MOVR32");
+ break;
+ case I8_MOV32R:
+ printf ("I8_MOV32R");
+ break;
+ case I64:
+ printf ("I64");
+ break;
+ case RI64:
+ printf ("RI64");
+ break;
+ }
+ printf (":");
+ switch (data_size)
+ {
+ case DOUBLEWORD:
+ printf ("64");
+ break;
+ /* start-sanitize-r5900 */
+ case QUADWORD:
+ printf ("128");
+ break;
+ /* end-sanitize-r5900 */
+ case -1:
+ printf ("16");
+ break;
+ default:
+ printf ("32");
+ }
+ printf (":%s:%s\n", options, name);
+}
+
+static void print_igen_insn_models PARAMS ((unsigned int isa));
+
+static void
+print_igen_insn_models (isa)
+ unsigned int isa;
+{
+ /* common mips ISAs */
+ switch ((isa & MASK_ISA))
+ {
+ case 1:
+ printf ("*mipsI:\n");
+ case 2:
+ printf ("*mipsII:\n");
+ case 3:
+ printf ("*mipsIII:\n");
+ /* start-sanitize-cygnus-never */
+ printf ("// %s-%s-%s\n", "start", "sanitize", "r5900");
+ /* end-sanitize-cygnus-never */
+ /* start-sanitize-r5900 */
+ printf ("*r5900:\n");
+ /* end-sanitize-r5900 */
+ /* start-sanitize-cygnus-never */
+ printf ("// %s-%s-%s\n", "end", "sanitize", "r5900");
+ /* end-sanitize-cygnus-never */
+ printf ("*r3900:\n");
+ /* start-sanitize-cygnus-never */
+ printf ("// %s-%s-%s\n", "start", "sanitize", "tx19");
+ /* end-sanitize-cygnus-never */
+ /* start-sanitize-tx19 */
+ printf ("*tx19:\n");
+ /* end-sanitize-tx19 */
+ /* start-sanitize-cygnus-never */
+ printf ("// %s-%s-%s\n", "end", "sanitize", "tx19");
+ /* end-sanitize-cygnus-never */
+ break;
+ default:
+ /* processor specific ISAs */
+ if ((isa & ARCH_VR4100))
+ printf ("*vr4100:\n");
+ /* start-sanitize-r5900 */
+ if ((isa & ARCH_R5900))
+ printf ("*r5900:\n");
+ /* end-sanitize-r5900 */
+ if ((isa & ARCH_R3900))
+ printf ("*r3900:\n");
+ }
+}
+
+/*---------------------------------------------------------------------------*/
+
+static int bitmap_val PARAMS ((const char *, int, int));
+static void build_mips16_operands PARAMS ((const char *));
+static void build_instruction
+ PARAMS ((int, unsigned int, int, const struct instruction *));
+
+/*---------------------------------------------------------------------------*/
+
+static char*
+name_for_data_len( insn )
+ struct instruction* insn;
+ {
+ if (GETDATASIZEINSN(insn) == BYTE)
+ return "BYTE";
+
+ else if (GETDATASIZEINSN(insn) == HALFWORD)
+ return "HALFWORD";
+
+ else if (GETDATASIZEINSN(insn) == WORD)
+ return "WORD";
+
+ else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+ return "DOUBLEWORD";
+
+ /* start-sanitize-r5900 */
+ else if (GETDATASIZEINSN(insn) == QUADWORD)
+ return "QUADWORD";
+
+ /* end-sanitize-r5900 */
+ else
+ return 0;
+ }
+
+static char*
+letter_for_data_len( insn )
+ struct instruction* insn;
+ {
+ if (GETDATASIZEINSN(insn) == BYTE)
+ return "B";
+
+ else if (GETDATASIZEINSN(insn) == HALFWORD)
+ return "H";
+
+ else if (GETDATASIZEINSN(insn) == WORD)
+ return "W";
+
+ else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+ return "D";
+
+ /* start-sanitize-r5900 */
+ else if (GETDATASIZEINSN(insn) == QUADWORD)
+ return "Q";
+
+ /* end-sanitize-r5900 */
+ else
+ return 0;
+ }
+
+static char*
+type_for_data_len( insn , is_signed )
+ struct instruction* insn;
+ int is_signed;
+ {
+ if (GETDATASIZEINSN(insn) == BYTE)
+ return is_signed ? "int" : "unsigned int";
+
+ else if (GETDATASIZEINSN(insn) == HALFWORD)
+ return is_signed ? "int" : "unsigned int";
+
+ else if (GETDATASIZEINSN(insn) == WORD)
+ return is_signed ? "signed64" : "unsigned64";
+
+ else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+ return 0;
+
+ /* start-sanitize-r5900 */
+ else if (GETDATASIZEINSN(insn) == QUADWORD)
+ return 0;
+
+ /* end-sanitize-r5900 */
+ else
+ return 0;
+ }
+
+static char*
+max_for_data_len( insn )
+ struct instruction* insn;
+ {
+ if (GETDATASIZEINSN(insn) == BYTE)
+ return "127";
+
+ else if (GETDATASIZEINSN(insn) == HALFWORD)
+ return "32767";
+
+ else if (GETDATASIZEINSN(insn) == WORD)
+ return "(int)0x7FFFFFFF";
+
+ else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+ return 0;
+
+ /* start-sanitize-r5900 */
+ else if (GETDATASIZEINSN(insn) == QUADWORD)
+ return 0;
+
+ /* end-sanitize-r5900 */
+ else
+ return 0;
+ }
+
+static char*
+min_for_data_len( insn )
+ struct instruction* insn;
+ {
+ if (GETDATASIZEINSN(insn) == BYTE)
+ return "-128";
+
+ else if (GETDATASIZEINSN(insn) == HALFWORD)
+ return "-32768";
+
+ else if (GETDATASIZEINSN(insn) == WORD)
+ return "(int)0x80000000";
+
+ else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+ return 0;
+
+ /* start-sanitize-r5900 */
+ else if (GETDATASIZEINSN(insn) == QUADWORD)
+ return 0;
+
+ /* end-sanitize-r5900 */
+ else
+ return 0;
+ }
+
+static char*
+umax_for_data_len( insn )
+ struct instruction* insn;
+ {
+ if (GETDATASIZEINSN(insn) == BYTE)
+ return "0xFF";
+
+ else if (GETDATASIZEINSN(insn) == HALFWORD)
+ return "0xFFFF";
+
+ else if (GETDATASIZEINSN(insn) == WORD)
+ return "0xFFFFFFFF";
+
+ else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+ return 0;
+
+ /* start-sanitize-r5900 */
+ else if (GETDATASIZEINSN(insn) == QUADWORD)
+ return 0;
+
+ /* end-sanitize-r5900 */
+ else
+ return 0;
+ }
+
+static char*
+bits_for_data_len( insn )
+ struct instruction* insn;
+ {
+ if (GETDATASIZEINSN(insn) == BYTE)
+ return "8";
+
+ else if (GETDATASIZEINSN(insn) == HALFWORD)
+ return "16";
+
+ else if (GETDATASIZEINSN(insn) == WORD)
+ return "32";
+
+ else if (GETDATASIZEINSN(insn) == DOUBLEWORD)
+ return "64";
+
+ /* start-sanitize-r5900 */
+ else if (GETDATASIZEINSN(insn) == QUADWORD)
+ return "128";
+
+ /* end-sanitize-r5900 */
+ else
+ return 0;
+ }
+
/*---------------------------------------------------------------------------*/
-/* We use the letter ordinal as the bit-position in our flags field: */
-#define fieldval(l) (1 << ((l) - 'a'))
-unsigned int
+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 */
{
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;
}
/* 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
+ number of bits. */
+
+static int
+bitmap_val (bitmap, shift, bits)
+ const char *bitmap;
+ int shift;
+ int bits;
+{
+ const char *s;
+ int ret;
+
+ ret = 0;
+ s = bitmap + 16 - shift - bits;
+ for (; bits > 0; --bits)
+ {
+ ret <<= 1;
+ if (*s == '0')
+ ;
+ else if (*s == '1')
+ ret |= 1;
+ else
+ abort ();
+ ++s;
+ }
+
+ return ret;
}
/*---------------------------------------------------------------------------*/
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. */
+
+struct mips16_op
+{
+ /* The character which appears in the bitmap string. */
+ int type;
+ /* The type of the variable in the simulator. */
+ const char *vartype;
+ /* The name of the variable in the simulator. */
+ const char *name;
+ /* The number of bits. */
+ int nbits;
+ /* The number of bits when extended (zero if can not be extended). */
+ int extbits;
+ /* The amount by which the short form is shifted when it is used;
+ for example, the sw instruction has a shift count of 2. */
+ int shift;
+ /* Flags. */
+ int flags;
+};
+
+/* Flags which appears in the mips16 operand table. */
+
+/* Whether this is a mips16 register index. */
+#define MIPS16_REG16 (0x1)
+/* Whether this is a register value. */
+#define MIPS16_REGVAL (0x2)
+/* Whether this is a swapped mips32 register index (MOV32R) */
+#define MIPS16_REG32_SWAPPED (0x4)
+/* Whether this index is also the destination register. */
+#define MIPS16_DESTREG (0x8)
+/* Whether the short form is unsigned. */
+#define MIPS16_UNSP (0x10)
+/* Whether the extended form is unsigned. */
+#define MIPS16_EXTU (0x20)
+/* Implicit stack pointer. */
+#define MIPS16_SP (0x40)
+/* Implicit program counter. */
+#define MIPS16_PC (0x80)
+/* Implicit $0. */
+#define MIPS16_ZERO (0x100)
+/* Implicit $24. */
+#define MIPS16_TREG (0x200)
+/* Implicit $31. */
+#define MIPS16_RA (0x400)
+/* Jump address. */
+#define MIPS16_JUMP_ADDR (0x800)
+/* Branch offset. */
+#define MIPS16_BRANCH (0x1000)
+
+/* The mips16 operand table. */
+
+static const struct mips16_op mips16_op_table[] =
+{
+ { 'd', "int", "destreg", 3, 0, 0, MIPS16_REG16 },
+ { 'x', "t_reg", "op1", 3, 0, 0, MIPS16_REG16 | MIPS16_REGVAL },
+ { 'w', "t_reg", "op1", 3, 0, 0, MIPS16_REG16|MIPS16_REGVAL|MIPS16_DESTREG},
+ { 'y', "t_reg", "op2", 3, 0, 0, MIPS16_REG16 | MIPS16_REGVAL },
+ { 'v', "t_reg", "op2", 3, 0, 0, MIPS16_REG16|MIPS16_REGVAL|MIPS16_DESTREG },
+ { 'X', "t_reg", "op1", 5, 0, 0, MIPS16_REGVAL },
+ { 'Y', "int", "destreg", 5, 0, 0, MIPS16_REG32_SWAPPED },
+ { 'a', "ut_reg", "op1", 11, 0, 0, MIPS16_JUMP_ADDR },
+ { 'e', "int", "ext", 11, 0, 0, 0 },
+ { '<', "int", "op1", 3, 5, 0, MIPS16_UNSP | MIPS16_EXTU },
+ { '>', "int", "op1", 3, 5, 0, MIPS16_UNSP | MIPS16_EXTU },
+ { '[', "int", "op1", 3, 6, 0, MIPS16_UNSP | MIPS16_EXTU },
+ { ']', "int", "op1", 3, 6, 0, MIPS16_UNSP | MIPS16_EXTU },
+ { '4', "int", "op2", 4, 15, 0, 0 },
+ { '5', "int", "offset", 5, 16, 0, MIPS16_UNSP },
+ { 'H', "int", "offset", 5, 16, 1, MIPS16_UNSP },
+ { 'W', "int", "offset", 5, 16, 2, MIPS16_UNSP },
+ { 'D', "int", "offset", 5, 16, 3, MIPS16_UNSP },
+ { 'j', "int", "op2", 5, 16, 0, 0 },
+ { '8', "int", "op2", 8, 16, 0, MIPS16_UNSP },
+ { 'V', "int", "offset", 8, 16, 2, MIPS16_UNSP },
+ { 'C', "int", "offset", 8, 16, 3, MIPS16_UNSP },
+ { 'U', "int", "op2", 8, 16, 0, MIPS16_UNSP | MIPS16_EXTU },
+ { 'k', "int", "op2", 8, 16, 0, 0 },
+ { 'K', "int", "op2", 8, 16, 3, 0 },
+ { 'p', "int", "offset", 8, 16, 0, MIPS16_BRANCH },
+ { 'q', "int", "offset", 11, 16, 0, MIPS16_BRANCH },
+ { 'A', "int", "op2", 8, 16, 2, MIPS16_UNSP },
+ { 'B', "int", "op2", 5, 16, 3, MIPS16_UNSP },
+ { 'E', "int", "op2", 5, 16, 2, MIPS16_UNSP },
+
+ /* The remaining operands are special operands which encode implied
+ arguments. These only appear at the end of a bitmap string, and
+ do not represent actual bits. */
+ { 's', "t_reg", "op1", 0, 0, 0, MIPS16_SP | MIPS16_REGVAL },
+ { 'S', "t_reg", "op1", 0, 0, 0, MIPS16_SP|MIPS16_REGVAL|MIPS16_DESTREG },
+ { 'P', "t_reg", "op1", 0, 0, 0, MIPS16_PC },
+ { 'z', "t_reg", "op2", 0, 0, 0, MIPS16_ZERO },
+ { 'Z', "t_reg", "op1", 0, 0, 0, MIPS16_ZERO },
+ { 't', "t_reg", "op1", 0, 0, 0, MIPS16_TREG | MIPS16_REGVAL },
+ { 'T', "int", "destreg", 0, 0, 0, MIPS16_TREG },
+ { 'r', "t_reg", "op1", 0, 0, 0, MIPS16_RA | MIPS16_REGVAL },
+ { 'R', "int", "destreg", 0, 0, 0, MIPS16_RA },
+ { 'Q', "t_reg", "op2", 0, 0, 0, MIPS16_RA | MIPS16_REGVAL },
+
+ { '\0', NULL, NULL, 0, 0, 0, 0 }
+};
+
+/* Build mips16 operands. */
+
+static void
+build_mips16_operands (bitmap)
+ const char *bitmap;
+{
+ const char *s;
+ int start = -1;
+ const struct mips16_op *op = NULL;
+ const struct mips16_op *ops[3];
+ int opindex = 0;
+ int i;
+
+ for (s = bitmap; *s != '\0'; s++)
+ {
+ if (op != NULL)
+ {
+ if (op->type == *s)
+ continue;
+
+ /* Make sure we saw the right number of bits for that
+ operand. */
+ if (op->nbits != 0 && (s - bitmap) - op->nbits != start)
+ abort ();
+ op = NULL;
+ }
+
+ if (*s == '0' || *s == '1' || *s == '?')
+ continue;
+
+ start = s - bitmap;
+
+ for (op = mips16_op_table; op->type != *s; ++op)
+ if (op->type == '\0')
+ abort ();
+
+ printf (" %s %s = ", op->vartype, op->name);
+ if (op->nbits != 0)
+ printf ("(instruction >> %d) & 0x%x",
+ 16 - (s - bitmap) - op->nbits,
+ (1 << op->nbits) - 1);
+ else
+ {
+ if ((op->flags & MIPS16_SP) != 0)
+ printf ("29");
+ else if ((op->flags & MIPS16_PC) != 0)
+ {
+ int j;
+
+ 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 (" & ~ (uword64) 0x%x", (1 << ops[j]->shift) - 1);
+ }
+ else if ((op->flags & MIPS16_ZERO) != 0)
+ printf ("0");
+ else if ((op->flags & MIPS16_TREG) != 0)
+ printf ("24");
+ else if ((op->flags & MIPS16_RA) != 0)
+ printf ("31");
+ else
+ abort ();
+ }
+ printf (";\n");
+
+ if ((op->flags & MIPS16_DESTREG) != 0)
+ printf (" int destreg;\n");
+
+ if (opindex > 2)
+ abort ();
+ ops[opindex] = op;
+ ++opindex;
+ }
+
+ if (op != NULL)
+ {
+ /* Make sure we saw the right number of bits for that
+ operand. */
+ if (op->nbits != 0 && 16 - op->nbits != start)
+ abort ();
+ }
+
+ for (i = 0; i < opindex; i++)
+ {
+ op = ops[i];
+ if ((op->flags & MIPS16_REG16) != 0)
+ {
+ printf (" if (%s < 2)\n", op->name);
+ printf (" %s += 16;\n", op->name);
+ }
+ if ((op->flags & MIPS16_REG32_SWAPPED) != 0)
+ printf (" %s = (%s >> 2) | ((%s & 3) << 3);\n",
+ op->name, op->name, op->name);
+ if ((op->flags & MIPS16_DESTREG) != 0)
+ printf (" destreg = %s;\n", op->name);
+ if ((op->flags & MIPS16_REGVAL) != 0)
+ printf (" %s = GPR[%s];\n", op->name, op->name);
+
+ if (op->extbits != 0)
+ {
+ printf (" if (have_extendval)\n");
+ printf (" {\n");
+ if (op->extbits == 16)
+ printf (" %s |= ((extendval & 0x1f) << 11) | (extendval & 0x7e0);\n",
+ op->name);
+ else if (op->extbits == 15)
+ printf (" %s |= ((extendval & 0xf) << 11) | (extendval & 0x7f0);\n",
+ op->name);
+ else if (op->extbits == 6)
+ printf (" %s = ((extendval >> 6) & 0x1f) | (extendval & 0x20);\n",
+ op->name);
+ else
+ printf (" %s = (extendval >> 6) & 0x1f;\n",
+ op->name);
+ if ((op->flags & MIPS16_EXTU) == 0)
+ {
+ printf (" if (%s >= 0x%x)\n",
+ op->name, 1 << (op->extbits - 1));
+ printf (" %s -= 0x%x;\n",
+ op->name, 1 << op->extbits);
+ }
+ printf (" have_extendval = 0;\n");
+ printf (" }\n");
+ printf (" else\n");
+ printf (" {\n");
+ if ((op->flags & MIPS16_UNSP) == 0)
+ {
+ printf (" if (%s >= 0x%x)\n",
+ op->name, 1 << (op->nbits - 1));
+ printf (" %s -= 0x%x;\n",
+ op->name, 1 << op->nbits);
+ }
+ if (op->shift != 0)
+ printf (" %s <<= %d;\n", op->name, op->shift);
+ if (op->type == '<' || op->type == '>'
+ || op->type == '[' || op->type == ']')
+ {
+ printf (" if (%s == 0)\n", op->name);
+ printf (" %s = 8;\n", op->name);
+ }
+ printf (" }\n");
+ }
+
+ if ((op->flags & MIPS16_BRANCH) != 0)
+ printf (" %s *= 2;\n", op->name);
+
+ if ((op->flags & MIPS16_JUMP_ADDR) != 0)
+ {
+ printf (" {\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");
+ printf (" uword64 memval;\n");
+ printf (" unsigned int reverse = (ReverseEndian ? 3 : 0);\n");
+ printf (" unsigned int bigend = (BigEndianCPU ? 3 : 0);\n");
+ printf (" unsigned int byte;\n");
+ printf (" paddr = ((paddr & ~0x7) | ((paddr & 0x7) ^ (reverse << 1)));\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);
+ printf (" | ((%s & 0x3e0) << 13)\n", op->name);
+ printf (" | (memval << 2));\n");
+ printf (" if ((instruction & 0x400) == 0)\n");
+ printf (" %s |= 1;\n", op->name);
+ printf (" PC += 2;\n");
+ printf (" }\n");
+ printf (" }\n");
+ printf (" %s |= PC & ~ (uword64) 0x0fffffff;\n", op->name);
+ }
+ }
+
+ /* FIXME: Is this the way to detect an unused extend opcode? */
+ printf (" if (have_extendval)\n");
+ printf (" SignalException (ReservedInstruction, instruction);\n");
}
/*---------------------------------------------------------------------------*/
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");
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("{\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);
- char *regtype = ((gprlen == 64) ? "uword64" : "unsigned int");
- 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);
}
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
* 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 */
+ }
+
+ }
+ }
- switch (MIPS_DECODE[loop].type) {
- /* TODO: To make these easier to edit and maintain, they should
- actually be provided as source macros (or inline functions)
- OUTSIDE this main switch statement. The PPC simulator has a
- neater scheme for describing the instruction sequences. */
-
- case ADD:
- case SUB:
- {
- char *signed_basetype = "unknown";
- char *unsigned_basetype = "unknown";
-
- switch (GETDATASIZE()) {
- case WORD :
- signed_basetype = "signed int";
- unsigned_basetype = "unsigned int";
- break;
- case DOUBLEWORD :
- signed_basetype = "word64";
- unsigned_basetype = "uword64";
- break;
- default :
- fprintf(stderr,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZE());
- exit(1);
- }
-
- if ((MIPS_DECODE[loop].type) == ADD) {
- printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype, unsigned_basetype);
- printf(" %s tempS = (%s)temp;\n", signed_basetype, signed_basetype);
- if (MIPS_DECODE[loop].flags & OVERFLOW) {
- printf(" if (((op1 < 0) == (op2 < 0)) && ((tempS < 0) != (op1 < 0)))\n");
- printf(" SignalException(IntegerOverflow);\n");
- printf(" else\n");
- }
- if (!proc64 || (MIPS_DECODE[loop].flags & UNSIGNED) || (GETDATASIZE() == DOUBLEWORD))
- printf(" GPR[destreg] = (%s)temp;\n",regtype);
- else /* only sign-extend when placing 32bit result in 64bit processor */
- 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);
- if (MIPS_DECODE[loop].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(" else\n");
- }
- /* UNSIGNED 32bit operations on a 64bit processor should
- *STILL* be sign-extended. We have cheated in the
- data-structure, by not marking it with UNSIGNED, and not
- setting OVERFLOW. */
- if (!proc64 || (MIPS_DECODE[loop].flags & UNSIGNED) || (GETDATASIZE() == DOUBLEWORD))
- printf(" GPR[destreg] = (%s)temp;\n",regtype);
- else /* only sign-extend when placing 32bit result in 64bit processor */
- printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype);
- }
- }
- break ;
-
- case MUL:
- if (features & FEATURE_WARN_LOHI) {
- printf(" CHECKHILO(\"Multiplication\");\n");
- }
- printf(" {\n");
- if (GETDATASIZE() == DOUBLEWORD) {
- printf(" uword64 mid;\n");
- printf(" uword64 midhi;\n");
- printf(" uword64 temp;\n");
- if ((MIPS_DECODE[loop].flags & UNSIGNED) == 0)
- {
- printf(" int sign = 0;\n");
- 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(" 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(" 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");
- if ((MIPS_DECODE[loop].flags & UNSIGNED) == 0)
- printf(" if (sign & 1) { LO = - LO; HI = (LO == 0 ? 0 : -1) - HI; }\n");
- } else {
- if (MIPS_DECODE[loop].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(" }\n");
- break ;
-
- case DIV:
- {
- int boolU = (MIPS_DECODE[loop].flags & UNSIGNED);
-
- if (features & FEATURE_WARN_LOHI) {
- printf(" CHECKHILO(\"Division\");\n");
- }
- printf(" {\n");
- if (GETDATASIZE() == DOUBLEWORD) {
- printf(" LO = ((%sword64)op1 / (%sword64)op2);\n",(boolU ? "u" : ""),(boolU ? "u" : ""));
- printf(" HI = ((%sword64)op1 %c (%sword64)op2);\n",(boolU ? "u" : ""),'%',(boolU ? "u" : ""));
- } 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(" }\n");
- }
- break ;
+
+ if (!(features & FEATURE_IGEN))
+ {
+ 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.
+ 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
+ 46 - 49: RRR instructions by function + 46
+ 50 - 81: RR instructions by minor + 50 (except for minor == 0)
+ 82 - 89: I64 and RI64 instructions by funct + 82
+ 90 - 97: jalr (RR minor 0) by y + 90
+ */
+ 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)
+ {
+ case I:
+ case RI:
+ case RRI:
+ num = bitmap_val (bitmap, 11, 5);
+ break;
+ case ISHIFT:
+ num = 32 + bitmap_val (bitmap, 0, 2);
+ break;
+ case RRI_A:
+ num = 36 + bitmap_val (bitmap, 4, 1);
+ break;
+ case I8:
+ case I8_MOV32R:
+ case I8_MOVR32:
+ num = 38 + bitmap_val (bitmap, 8, 3);
+ break;
+ case RRR:
+ num = 46 + bitmap_val (bitmap, 0, 2);
+ break;
+ case RR:
+ {
+ int minor;
+
+ minor = bitmap_val (bitmap, 0, 5);
+ if (minor != 0)
+ num = 50 + minor;
+ else
+ num = 90 + bitmap_val (bitmap, 5, 3);
+ }
+ break;
+ case I64:
+ case RI64:
+ num = 82 + bitmap_val (bitmap, 8, 3);
+ break;
+ default:
+ abort ();
+ }
- case SHIFT:
- {
- int datalen = GETDATASIZE();
- int bits = ((datalen == WORD) ? 32 : 64);
- char *ltype = ((datalen == WORD) ? "unsigned int" : "uword64");
- /* Check that the specified SHIFT is valid: */
- if ((datalen == BYTE) || (datalen == HALFWORD)) {
- fprintf(stderr,"Shift \"%s\" specified with BYTE or HALFWORD\n",MIPS_DECODE[loop].name);
- exit(9);
- }
- if ((MIPS_DECODE[loop].flags & LEFT) && (MIPS_DECODE[loop].flags & RIGHT)) {
- fprintf(stderr,"Shift \"%s\" specified with both LEFT and RIGHT\n",MIPS_DECODE[loop].name);
- exit(9);
- }
- if (!(MIPS_DECODE[loop].flags & LEFT) && !(MIPS_DECODE[loop].flags & RIGHT)) {
- fprintf(stderr,"Shift \"%s\" specified with neither LEFT or RIGHT\n",MIPS_DECODE[loop].name);
- exit(9);
- }
- if ((MIPS_DECODE[loop].flags & LOGICAL) && (MIPS_DECODE[loop].flags & ARITHMETIC)) {
- fprintf(stderr,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",MIPS_DECODE[loop].name);
- exit(9);
- }
- if (!(MIPS_DECODE[loop].flags & LOGICAL) && !(MIPS_DECODE[loop].flags & ARITHMETIC)) {
- fprintf(stderr,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",MIPS_DECODE[loop].name);
- exit(9);
- }
- if ((MIPS_DECODE[loop].flags & LEFT) && (MIPS_DECODE[loop].flags & ARITHMETIC)) {
- fprintf(stderr,"Arithmetic LEFT shift \"%s\" specified\n",MIPS_DECODE[loop].name);
- exit(9);
- }
-
- /* If register specified shift, then extract the relevant shift amount: */
- if (flags & fieldval('s'))
- printf(" op1 &= 0x%02X;\n",(bits - 1));
-
- /* If HI32 specified, then shift range is 32..63 */
- if (MIPS_DECODE[loop].flags & HI32)
- printf(" op1 |= (1 << 5);\n");
-
- /* We do not need to perform pre-masking with 0xFFFFFFFF when
- dealing with 32bit shift lefts, since the sign-extension
- code will replace any remaining hi-bits: */
- if (MIPS_DECODE[loop].flags & LEFT)
- printf(" GPR[destreg] = ((uword64)op2 << op1);\n");
- else
- printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits == 32) ? " & 0xFFFFFFFF" : ""));
-
- /* For ARITHMETIC shifts, we must duplicate the sign-bit. We
- don't do this if op1 is zero, since it is not needed and
- since that would cause an undefined shift of the number of
- bits in the type. */
- if (MIPS_DECODE[loop].flags & ARITHMETIC)
- printf(" GPR[destreg] |= (op1 != 0 && (op2 & ((%s)1 << %d)) ? ((((%s)1 << op1) - 1) << (%d - op1)) : 0);\n",ltype,(bits - 1),ltype,bits);
-
- /* Ensure WORD values are sign-extended into 64bit registers */
- if ((bits == 32) && (gprlen == 64))
- printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits);
- }
- break ;
+ 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");
+ }
- case MOVE:
- if (MIPS_DECODE[loop].flags & (HI | LO)) {
- char *regname = ((MIPS_DECODE[loop].flags & LO) ? "LO" : "HI");
- if (flags & fieldval('d'))
- printf(" GPR[destreg] = %s;\n",regname);
- 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(" %s = op1;\n",regname);
- }
- if (features & FEATURE_WARN_LOHI)
- printf(" %sACCESS = 3; /* 3rd instruction will be safe */\n",regname);
- } else
- if (MIPS_DECODE[loop].flags & SHIFT16)
- printf(" GPR[destreg] = (op2 << 16);\n");
- else {
- /* perform conditional move */
- if (!(MIPS_DECODE[loop].flags & EQ)) {
- fprintf(stderr,"Standard conditional %s does not have the equality flag\n",MIPS_DECODE[loop].name);
- exit(8);
- }
- printf(" if (op2 %c= 0)\n",((MIPS_DECODE[loop].flags & NOT) ? '!' : '='));
- printf(" GPR[destreg] = op1;\n");
- }
- break ;
+ build_mips16_operands (bitmap);
- case SYNC:
- printf(" SyncOperation(op1);\n");
- break ;
+ printf (" {\n") ;
- case SYSCALL:
- printf(" SignalException(SystemCall);\n");
- break ;
+ /* build_instruction doesn't know about extend. */
+ if (num != 30)
+ build_instruction (doisa, features, 1, &MIPS16_DECODE[loop]);
+ else
+ {
+ printf (" extendval = ext;\n");
+ printf (" have_extendval = 1;\n");
+ }
- case BREAK:
- printf(" SignalException(BreakPoint);\n");
- break ;
+ printf (" }\n");
+ if (!(features & FEATURE_IGEN))
+ {
+ printf (" }\n") ;
+ printf (" break ;\n") ;
+ }
+ else
+ {
+ printf ("}\n");
+ printf ("\n");
+ }
+ }
- case TRAP:
- {
- int boolNOT = (MIPS_DECODE[loop].flags & NOT);
- int boolEQ = (MIPS_DECODE[loop].flags & EQ);
- int boolGT = (MIPS_DECODE[loop].flags & GT);
- int boolLT = (MIPS_DECODE[loop].flags & LT);
- int boolU = (MIPS_DECODE[loop].flags & UNSIGNED);
-
- if (boolGT && boolLT) {
- fprintf(stderr,"GT and LT specified for \"%s\"\n",MIPS_DECODE[loop].name);
- exit(8);
- }
+ 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 ;
+}
- if (boolNOT && (boolGT || boolLT)) {
- fprintf(stderr,"NOT specified with GT or LT specified for \"%s\"\n",MIPS_DECODE[loop].name);
- exit(8);
- }
+/* Output the code to execute an instruction, assuming the operands
+ have already been extracted. */
- printf(" if ((%sword64)op1 ",(boolU ? "u" : ""));
- printf("%c%s",(boolNOT ? '!' : (boolLT ? '<' : (boolGT ? '>' : '='))),(boolEQ ? "=" : ""));
- printf(" (%sword64)op2)\n",(boolU ? "u" : ""));
- printf(" SignalException(Trap);\n");
- }
- break ;
+static void
+build_instruction (doisa, features, mips16, insn)
+ int doisa;
+ unsigned int features;
+ int mips16;
+ const struct instruction *insn;
+{
+ int gprlen=((features & FEATURE_GP64) ? 64 : 32);
+ int proc64 = ((features & FEATURE_PROC32) ? 0 : -1);
+ char *regtype = ((gprlen == 64) ? "uword64" : "unsigned int");
+
+ switch (insn->type) {
+ /* TODO: To make these easier to edit and maintain, they should
+ actually be provided as source macros (or inline functions)
+ OUTSIDE this main switch statement. The PPC simulator has a
+ neater scheme for describing the instruction sequences. */
+
+ case ADD:
+ case SUB:
+ {
+ char *signed_basetype = "unknown";
+ char *unsigned_basetype = "unknown";
+
+ switch (GETDATASIZEINSN(insn)) {
+ case WORD :
+ signed_basetype = "signed int";
+ unsigned_basetype = "unsigned int";
+ break;
+ case DOUBLEWORD :
+ signed_basetype = "word64";
+ unsigned_basetype = "uword64";
+ break;
+ default :
+ fprintf(stderr,"Opcode table error: size of ADD/SUB operands not known (%d)\n",GETDATASIZEINSN(insn));
+ exit(1);
+ }
- case SET:
- {
- int boolU = (MIPS_DECODE[loop].flags & UNSIGNED);
+ if ((insn->type) == ADD) {
+ printf(" %s temp = (%s)(op1 + op2);\n", unsigned_basetype, unsigned_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(" SignalExceptionIntegerOverflow ();\n");
+ printf(" else\n");
+ }
+ if (!proc64 || (insn->flags & UNSIGNED) || (GETDATASIZEINSN(insn) == DOUBLEWORD))
+ printf(" GPR[destreg] = (%s)temp;\n",regtype);
+ else /* only sign-extend when placing 32bit result in 64bit processor */
+ 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 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(" SignalExceptionIntegerOverflow ();\n");
+ printf(" else\n");
+ }
+ /* UNSIGNED 32bit operations on a 64bit processor should
+ *STILL* be sign-extended. We have cheated in the
+ data-structure, by not marking it with UNSIGNED, and not
+ setting OVERFLOW. */
+ if (!proc64 || (insn->flags & UNSIGNED) || (GETDATASIZEINSN(insn) == DOUBLEWORD))
+ printf(" GPR[destreg] = (%s)temp;\n",regtype);
+ else /* only sign-extend when placing 32bit result in 64bit processor */
+ printf(" GPR[destreg] = SIGNEXTEND(((%s)temp),32);\n",regtype);
+ }
+ }
+ break ;
+
+ case MUL:
+ {
+ char* pipe = (insn->flags & PIPE1) ? "1" : "";
+
+ printf(" {\n");
+ if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
+ printf(" uword64 mid;\n");
+ printf(" uword64 midhi;\n");
+ printf(" uword64 temp;\n");
+ if ((insn->flags & UNSIGNED) == 0)
+ {
+ printf(" int sign = 0;\n");
+ printf(" if (op1 < 0) { op1 = - op1; ++sign; }\n");
+ printf(" if (op2 < 0) { op2 = - op2; ++sign; }\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%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%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%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 = ((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 (!(MIPS_DECODE[loop].flags & LT)) {
- fprintf(stderr,"Set instruction without LT specified \"%s\"\n",MIPS_DECODE[loop].name);
- exit(8);
- }
+ printf(" {\n");
- printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU ? "u" : ""),(boolU ? "u" : ""));
- printf(" GPR[destreg] = 1;\n");
- printf(" else\n");
- printf(" GPR[destreg] = 0;\n");
- }
- break ;
+ if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
+ 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(" %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 ;
+
+ case SHIFT:
+ {
+ int datalen = GETDATASIZEINSN(insn);
+ int bits = ((datalen == WORD) ? 32 : 64);
+ char *ltype = ((datalen == WORD) ? "unsigned int" : "uword64");
+
+ /* Check that the specified SHIFT is valid: */
+ if ((datalen == BYTE) || (datalen == HALFWORD)) {
+ fprintf(stderr,"Shift \"%s\" specified with BYTE or HALFWORD\n",insn->name);
+ exit(9);
+ }
+ if ((insn->flags & LEFT) && (insn->flags & RIGHT)) {
+ fprintf(stderr,"Shift \"%s\" specified with both LEFT and RIGHT\n",insn->name);
+ exit(9);
+ }
+ if (!(insn->flags & LEFT) && !(insn->flags & RIGHT)) {
+ fprintf(stderr,"Shift \"%s\" specified with neither LEFT or RIGHT\n",insn->name);
+ exit(9);
+ }
+ if ((insn->flags & LOGICAL) && (insn->flags & ARITHMETIC)) {
+ fprintf(stderr,"Shift \"%s\" specified with both LOGICAL and ARITHMETIC\n",insn->name);
+ exit(9);
+ }
+ if (!(insn->flags & LOGICAL) && !(insn->flags & ARITHMETIC)) {
+ fprintf(stderr,"Shift \"%s\" specified with neither LOGICAL or ARITHMETIC\n",insn->name);
+ exit(9);
+ }
+ if ((insn->flags & LEFT) && (insn->flags & ARITHMETIC)) {
+ fprintf(stderr,"Arithmetic LEFT shift \"%s\" specified\n",insn->name);
+ exit(9);
+ }
- case AND:
- printf(" GPR[destreg] = (op1 & op2);\n");
- break ;
+ /* 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));
+
+ /* If HI32 specified, then shift range is 32..63 */
+ if (insn->flags & HI32)
+ printf(" op1 |= (1 << 5);\n");
+
+ /* We do not need to perform pre-masking with 0xFFFFFFFF when
+ dealing with 32bit shift lefts, since the sign-extension
+ code will replace any remaining hi-bits: */
+ if (insn->flags & LEFT)
+ printf(" GPR[destreg] = ((uword64)op2 << op1);\n");
+ else
+ printf(" GPR[destreg] = ((uword64)(op2%s) >> op1);\n",((bits == 32) ? " & 0xFFFFFFFF" : ""));
+
+ /* For ARITHMETIC shifts, we must duplicate the sign-bit. We
+ don't do this if op1 is zero, since it is not needed and
+ 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 & 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))
+ printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],%d);\n",bits);
+ }
+ break ;
+
+ 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%s;\n",regname,(pipe1 ? "1" : ""));
+ else {
+ printf(" %s%s = op1;\n",regname,(pipe1 ? "1" : ""));
+ }
+ } else
+ if (insn->flags & SHIFT16)
+ printf(" GPR[destreg] = (op2 << 16);\n");
+ else {
+ /* perform conditional move */
+ if (!(insn->flags & EQ)) {
+ fprintf(stderr,"Standard conditional %s does not have the equality flag\n",insn->name);
+ exit(8);
+ }
+ printf(" if (op2 %c= 0)\n",((insn->flags & NOT) ? '!' : '='));
+ printf(" GPR[destreg] = op1;\n");
+ }
+ break ;
+
+ case SYNC:
+ printf(" SyncOperation(op1);\n");
+ break ;
+
+ case SYSCALL:
+ printf(" SignalException(SystemCall,instruction);\n");
+ break ;
+
+ case BREAK:
+ printf(" SignalException(BreakPoint,instruction);\n");
+ break ;
+
+ case SDBBP:
+ printf(" SignalException(DebugBreakPoint,instruction);\n");
+ break ;
+
+ case TRAP:
+ {
+ int boolNOT = (insn->flags & NOT);
+ int boolEQ = (insn->flags & EQ);
+ int boolGT = (insn->flags & GT);
+ int boolLT = (insn->flags & LT);
+ int boolU = (insn->flags & UNSIGNED);
+
+ if (boolGT && boolLT) {
+ fprintf(stderr,"GT and LT specified for \"%s\"\n",insn->name);
+ exit(8);
+ }
- case OR:
- printf(" GPR[destreg] = %s(op1 | op2);\n",((MIPS_DECODE[loop].flags & NOT) ? "~" : ""));
- break ;
+ if (boolNOT && (boolGT || boolLT)) {
+ fprintf(stderr,"NOT specified with GT or LT specified for \"%s\"\n",insn->name);
+ exit(8);
+ }
- case XOR:
- printf(" GPR[destreg] = (op1 ^ op2);\n");
- break ;
+ printf(" if ((%sword64)op1 ",(boolU ? "u" : ""));
+ printf("%c%s",(boolNOT ? '!' : (boolLT ? '<' : (boolGT ? '>' : '='))),(boolEQ ? "=" : ""));
+ printf(" (%sword64)op2)\n",(boolU ? "u" : ""));
+ printf(" SignalException(Trap,instruction);\n");
+ }
+ break ;
- case DECODE:
- printf(" decode_coproc(instruction);\n");
- break ;
+ case SET:
+ {
+ int boolU = (insn->flags & UNSIGNED);
- 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(" int uncached;\n");
- /* NOTE: We are assuming that the AddressTranslation is a load: */
- printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
- printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
- break;
+ if (!(insn->flags & LT)) {
+ fprintf(stderr,"Set instruction without LT specified \"%s\"\n",insn->name);
+ exit(8);
+ }
- case MADD16: /* VR4100 specific multiply-add instructions */
- /* Some of this code is shared with the standard multiply
- routines, so an effort should be made to merge where
- possible. */
- if (features & FEATURE_WARN_LOHI) {
- printf(" CHECKHILO(\"Multiply-Add\");\n");
- }
- 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(" {\n");
- printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
- if (GETDATASIZE() == DOUBLEWORD) {
- printf(" LO = LO + temp;\n");
- } else { /* WORD */
- printf(" temp += (SET64HI(WORD64LO(HI)) | WORD64LO(LO));\n");
- printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype);
- printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype);
- }
- printf(" }\n");
- break;
+ printf(" if ((%sword64)op1 < (%sword64)op2)\n",(boolU ? "u" : ""),(boolU ? "u" : ""));
+ printf(" GPR[destreg] = 1;\n");
+ printf(" else\n");
+ printf(" GPR[destreg] = 0;\n");
+ }
+ break ;
+
+ case AND:
+ printf(" GPR[destreg] = (op1 & op2);\n");
+ 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 ;
+
+ case XOR:
+ printf(" GPR[destreg] = (op1 ^ op2);\n");
+ break ;
+
+ case DECODE:
+ 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(" 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");
+ printf(" CacheOp(hint,vaddr,paddr,instruction);\n");
+ break;
+
+ case MADD16: /* VR4100 specific multiply-add instructions */
+ /* Some of this code is shared with the standard multiply
+ routines, so an effort should be made to merge where
+ possible. */
+ 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_io_eprintf(sd,\"MADD16 operation with non-16bit operands\\n\");\n");
+ }
+ printf(" {\n");
+ printf(" uword64 temp = (op1 * op2);\n"); /* 16x16 multiply */
+ if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
+ printf(" LO = LO + temp;\n");
+ } else { /* WORD */
+ printf(" temp += (SET64HI(WORD64LO(HI)) | WORD64LO(LO));\n");
+ printf(" LO = SIGNEXTEND((%s)WORD64LO(temp),32);\n",regtype);
+ printf(" HI = SIGNEXTEND((%s)WORD64HI(temp),32);\n",regtype);
+ }
+ printf(" }\n");
+ break;
+
+ case RSVD: /* "Reserved Instruction" on MIPS IV, or if co-proc 3 absent. Otherwise "CoProcessorUnusable" */
+ if (doisa < 4) {
+ printf(" if (CoProcPresent(3))\n");
+ printf(" SignalExceptionCoProcessorUnusable ();\n");
+ printf(" else\n");
+ }
+ printf(" SignalException(ReservedInstruction,instruction);\n");
+ break ;
+
+ case JUMP:
+ if (insn->flags & LINK) {
+ if (!(insn->flags & REG))
+ printf(" int destreg = 31;\n");
+ printf(" GPR[destreg] = (PC + %d); /* NOTE: The PC is already %d ahead within the simulator */\n",
+ mips16 ? 2 : 4, mips16 ? 2 : 4);
+ }
- 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(" else\n");
- }
- printf(" SignalException(ReservedInstruction,instruction);\n");
- break ;
-
- case JUMP:
- if (MIPS_DECODE[loop].flags & LINK) {
- if (!(MIPS_DECODE[loop].flags & REG))
- printf(" int destreg = 31;\n");
- printf(" GPR[destreg] = (PC + 4); /* NOTE: The PC is already 4 ahead within the simulator */\n");
- }
-
- printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
- printf(" DSPC = op1;\n");
- printf(" DELAYSLOT();\n");
- break ;
-
- case BRANCH: /* execute delay slot instruction before branch unless (LIKELY && branch_not_taken) */
- if (MIPS_DECODE[loop].flags & FP) {
- if (doisa < 4) {
- printf(" if (condition_code != 0)\n");
- printf(" SignalException(ReservedInstruction,instruction);\n");
- printf(" else {\n");
- }
- /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */
- printf(" int condition = (%s == boolean);\n",((doisa < 4) ? "PREVCOC1()" : "GETFCC(condition_code)"));
- } else {
- if ((MIPS_DECODE[loop].flags & NOT) && !(MIPS_DECODE[loop].flags & EQ)) {
- fprintf(stderr,"NOT specified when not EQ in \"%s\"\n",MIPS_DECODE[loop].name);
- exit(7);
- }
- if ((MIPS_DECODE[loop].flags & NOT) && (MIPS_DECODE[loop].flags & (GT | LT))) {
- fprintf(stderr,"NOT specified with GT or LT in \"%s\"\n",MIPS_DECODE[loop].name);
- exit(7);
- }
- /* GT LT */
- if (MIPS_DECODE[loop].flags & GT)
- printf(" int condition = (op1 >%s 0);\n",((MIPS_DECODE[loop].flags & EQ) ? "=" : ""));
- else
- if (MIPS_DECODE[loop].flags & LT)
- printf(" int condition = (op1 <%s 0);\n",((MIPS_DECODE[loop].flags & EQ) ? "=" : ""));
- else
- if (MIPS_DECODE[loop].flags & EQ)
- printf(" int condition = (op1 %c= op2);\n",((MIPS_DECODE[loop].flags & NOT) ? '!' : '='));
- }
-
- if (MIPS_DECODE[loop].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(" GPR[31] = (PC + 4); /* NOTE: PC is already 8 ahead */\n");
- }
-
- printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
- printf(" if (condition) {\n");
- printf(" DSPC = (PC + offset);\n");
- printf(" DELAYSLOT();\n");
- printf(" }\n");
- if ((MIPS_DECODE[loop].flags & FP) && (doisa != 1)) {
- printf(" else if (likely) {\n");
- printf(" NULLIFY();\n");
- printf(" }\n");
- } else if (MIPS_DECODE[loop].flags & LIKELY) {
- printf(" else\n");
- printf(" NULLIFY();\n");
- }
- if ((MIPS_DECODE[loop].flags & FP) && (doisa < 4))
- printf(" }\n");
- break ;
-
- case PREFETCH: /* The beginning is shared with normal load operations */
- case LOAD:
- case STORE:
- {
- int isload = ((MIPS_DECODE[loop].type == LOAD) || (MIPS_DECODE[loop].type == PREFETCH));
- int datalen;
- char *accesslength = "<UNKNOWN>";
-
- switch (GETDATASIZE()) {
- case BYTE :
- datalen = 1;
- accesslength = "AccessLength_BYTE";
- break ;
-
- case HALFWORD :
- datalen = 2;
- accesslength = "AccessLength_HALFWORD";
- break ;
-
- case WORD :
- datalen = 4;
- accesslength = "AccessLength_WORD";
- break ;
-
- case DOUBLEWORD :
- datalen = 8;
- accesslength = "AccessLength_DOUBLEWORD";
- break ;
- }
+ if (insn->flags & NOT)
+ printf(" op1 ^= 1;\n");
+
+ printf(" /* NOTE: ??? Gdb gets confused if the PC is sign-extended,\n");
+ printf(" so we just truncate it to 32 bits here. */\n");
+ printf(" op1 = WORD64LO(op1);\n");
+ printf(" /* NOTE: The jump occurs AFTER the next instruction has been executed */\n");
+ printf(" DSPC = op1;\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) */
+ if (insn->flags & FP) {
+ if (doisa < 4) {
+ printf(" if (condition_code != 0)\n");
+ printf(" SignalException(ReservedInstruction,instruction);\n");
+ printf(" else {\n");
+ }
+ /* "PREVCOC1()" should be the COC1 value at the start of the preceding instruction */
+ printf(" int condition = (%s == boolean);\n",((doisa < 4) ? "PREVCOC1()" : "GETFCC(condition_code)"));
+ } else {
+ if ((insn->flags & NOT) && !(insn->flags & EQ)) {
+ fprintf(stderr,"NOT specified when not EQ in \"%s\"\n",insn->name);
+ exit(7);
+ }
+ if ((insn->flags & NOT) && (insn->flags & (GT | LT))) {
+ fprintf(stderr,"NOT specified with GT or LT in \"%s\"\n",insn->name);
+ exit(7);
+ }
+ /* GT LT */
+ if (insn->flags & GT)
+ printf(" int condition = (op1 >%s 0);\n",((insn->flags & EQ) ? "=" : ""));
+ else
+ if (insn->flags & LT)
+ printf(" int condition = (op1 <%s 0);\n",((insn->flags & EQ) ? "=" : ""));
+ else
+ if (insn->flags & EQ)
+ printf(" int condition = (op1 %c= op2);\n",((insn->flags & NOT) ? '!' : '='));
+ }
- if (MIPS_DECODE[loop].flags & REG)
- printf(" uword64 vaddr = ((uword64)op1 + op2);\n");
- else
- printf(" uword64 vaddr = ((uword64)op1 + offset);\n");
- printf(" uword64 paddr;\n");
- printf(" int uncached;\n");
-
- /* The following check should only occur on normal (non-shifted) memory loads */
- if ((datalen != 1) && !(MIPS_DECODE[loop].flags & (LEFT | RIGHT))) {
- printf(" if ((vaddr & %d) != 0)\n",(datalen - 1));
- printf(" SignalException(%s);\n",(isload ? "AddressLoad" : "AddressStore"));
- printf(" else\n") ;
- }
+ 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_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");
+ }
- printf(" {\n");
- printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload ? "isLOAD" : "isSTORE"));
+ if (! mips16) {
+ printf(" /* NOTE: The branch occurs AFTER the next instruction has been executed */\n");
+ printf(" if (condition) {\n");
+ printf(" DSPC = (PC + offset);\n");
+ printf(" DELAYSLOT();\n");
+ printf(" }\n");
+ } else {
+ /* No delayed slots for mips16 branches. */
+ printf(" if (condition)\n");
+ printf(" PC = PC + offset;\n");
+ }
+ if ((insn->flags & FP) && (doisa != 1)) {
+ printf(" else if (likely) {\n");
+ printf(" NULLIFY();\n");
+ printf(" }\n");
+ } else if (insn->flags & LIKELY) {
+ printf(" else\n");
+ printf(" NULLIFY();\n");
+ }
+ if ((insn->flags & FP) && (doisa < 4))
+ printf(" }\n");
+ break ;
+
+ case PREFETCH: /* The beginning is shared with normal load operations */
+ case LOAD:
+ case STORE:
+ {
+ int isload = ((insn->type == LOAD) || (insn->type == PREFETCH));
+ int datalen;
+ char *accesslength = "<UNKNOWN>";
+
+ switch (GETDATASIZEINSN(insn)) {
+ case BYTE :
+ datalen = 1;
+ accesslength = "AccessLength_BYTE";
+ break ;
+
+ case HALFWORD :
+ datalen = 2;
+ accesslength = "AccessLength_HALFWORD";
+ break ;
+
+ case WORD :
+ datalen = 4;
+ accesslength = "AccessLength_WORD";
+ break ;
+
+ case DOUBLEWORD :
+ datalen = 8;
+ accesslength = "AccessLength_DOUBLEWORD";
+ break ;
+ /* start-sanitize-r5900 */
+
+ case QUADWORD :
+ datalen = 16;
+ accesslength = "AccessLength_QUADWORD";
+ break ;
+ /* end-sanitize-r5900 */
+ }
- if (MIPS_DECODE[loop].type == PREFETCH)
- printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
- else {
- printf(" {\n");
- printf(" %s memval;\n",(proc64 ? "uword64" : "unsigned int"));
+ if (insn->flags & REG)
+ printf(" address_word vaddr = ((uword64)op1 + op2);\n");
+ else
+ 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(" else\n") ;
+ }
- if ((MIPS_DECODE[loop].flags & COPROC) && ((datalen != 4) && (datalen != 8))) {
- fprintf(stderr,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",MIPS_DECODE[loop].name);
- exit(6);
- }
+ printf(" {\n");
+ printf(" if (AddressTranslation(vaddr,isDATA,%s,&paddr,&uncached,isTARGET,isREAL))\n",(isload ? "isLOAD" : "isSTORE"));
- if (MIPS_DECODE[loop].flags & (LEFT | RIGHT)) {
- if ((MIPS_DECODE[loop].flags & LEFT) && (MIPS_DECODE[loop].flags & RIGHT)) {
- fprintf(stderr,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",MIPS_DECODE[loop].name);
- exit(4);
- }
+ if (insn->type == PREFETCH)
+ printf(" Prefetch(uncached,paddr,vaddr,isDATA,hint);\n");
+ else {
+ printf(" {\n");
+ printf(" uword64 memval = 0;\n");
+ printf(" uword64 memval1 = 0;\n");
- switch (datalen) {
- case 8:
- if (!proc64) {
- fprintf(stderr,"DOUBLEWORD shifted memory transfers only valid for 64-bit processors \"%s\"\n",MIPS_DECODE[loop].name);
- exit(4);
- }
- /* fall through to... */
- case 4:
- {
- char *maskstr = ((datalen == 8) ? "((uword64)-1)" : "0xFFFFFFFF");
-
- printf(" uword64 mask = %d;\n",((datalen == 8) ? 0x7 : 0x3));
- printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
- printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
- printf(" int byte;\n");
- printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
- printf(" byte = ((vaddr & mask) ^ bigend);\n");
- printf(" if (%sBigEndianMem)\n",((MIPS_DECODE[loop].flags & LEFT) ? "!" : ""));
- printf(" paddr &= ~mask;\n");
-
- if (isload) {
- if (MIPS_DECODE[loop].flags & LEFT)
- printf(" memval = LoadMemory(uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
- else
- printf(" memval = LoadMemory(uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen - 1));
- }
+ if ((insn->flags & COPROC) && ((datalen != 4) && (datalen != 8))) {
+ fprintf(stderr,"Co-processor transfer operation not WORD or DOUBLEWORD in length \"%s\"\n",insn->name);
+ exit(6);
+ }
- if (MIPS_DECODE[loop].flags & LEFT) {
- if (isload) {
- /* For WORD transfers work out if the value will
- be in the top or bottom of the DOUBLEWORD
- returned: */
+ if (insn->flags & (LEFT | RIGHT)) {
+ if ((insn->flags & LEFT) && (insn->flags & RIGHT)) {
+ fprintf(stderr,"Memory transfer with both LEFT and RIGHT specified \"%s\"\n",insn->name);
+ exit(4);
+ }
+
+ switch (datalen) {
+ case 8:
+ 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));
+ printf(" unsigned int reverse = (ReverseEndian ? mask : 0);\n");
+ printf(" unsigned int bigend = (BigEndianCPU ? mask : 0);\n");
+ printf(" int byte;\n");
+ printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ reverse));\n");
+ printf(" byte = ((vaddr & mask) ^ bigend);\n");
+ printf(" if (%sBigEndianMem)\n",((insn->flags & LEFT) ? "!" : ""));
+ printf(" paddr &= ~mask;\n");
+
+ if (isload) {
+ if (insn->flags & LEFT)
+ {
+ printf(" LoadMemory(&memval,&memval1,uncached,byte,paddr,vaddr,isDATA,isREAL);\n");
+ }
+ else
+ {
+ printf(" LoadMemory(&memval,&memval1,uncached,(%d - byte),paddr,vaddr,isDATA,isREAL);\n",(datalen - 1));
+ }
+ }
+
+ if (insn->flags & LEFT) {
+ if (isload) {
+ /* For WORD transfers work out if the value will
+ be in the top or bottom of the DOUBLEWORD
+ returned: */
#if 1
- build_endian_shift(proc64,datalen,2,s_right,32);
+ build_endian_shift(proc64,datalen,2,s_right,32);
#else
- if (proc64 && (datalen == 4)) {
- printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
- printf(" memval >>= 32;\n");
- printf(" }\n");
- }
+ if (proc64 && (datalen == 4)) {
+ printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
+ printf(" memval >>= 32;\n");
+ printf(" }\n");
+ }
#endif
- printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen - 1),(datalen - 1));
- if (proc64 && (datalen == 4))
- printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
- } else { /* store */
- printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen - 1));
+ printf(" GPR[destreg] = ((memval << ((%d - byte) * 8)) | (GPR[destreg] & (((uword64)1 << ((%d - byte) * 8)) - 1)));\n",(datalen - 1),(datalen - 1));
+ if (proc64 && (datalen == 4))
+ printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
+ } else { /* store */
+ printf(" memval = (op2 >> (8 * (%d - byte)));\n",(datalen - 1));
#if 1
- build_endian_shift(proc64,datalen,2,s_left,32);
+ build_endian_shift(proc64,datalen,2,s_left,32);
#else
- /* TODO: This is duplicated in the LOAD code
- above - and the RIGHT LOAD and STORE code
- below. It should be merged if possible. */
- if (proc64 && (datalen == 4)) {
- printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
- printf(" memval <<= 32;\n");
- printf(" }\n");
- }
+ /* TODO: This is duplicated in the LOAD code
+ above - and the RIGHT LOAD and STORE code
+ below. It should be merged if possible. */
+ if (proc64 && (datalen == 4)) {
+ printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
+ printf(" memval <<= 32;\n");
+ printf(" }\n");
+ }
#endif
- printf(" StoreMemory(uncached,byte,memval,paddr,vaddr,isREAL);\n");
- }
- } else { /* RIGHT */
- if (isload) {
+ printf(" StoreMemory(uncached,byte,memval,memval1,paddr,vaddr,isREAL);\n");
+ }
+ } else { /* RIGHT */
+ if (isload) {
#if 1
- build_endian_shift(proc64,datalen,2,s_right,32);
+ build_endian_shift(proc64,datalen,2,s_right,32);
#else
- if (proc64 && (datalen == 4)) {
- printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
- printf(" memval >>= 32;\n");
- printf(" }\n");
- }
+ if (proc64 && (datalen == 4)) {
+ printf(" if ((vaddr & (1 << 2)) ^ (BigEndianCPU << 2)) {\n");
+ printf(" memval >>= 32;\n");
+ printf(" }\n");
+ }
#endif
- printf(" {\n");
- printf(" uword64 srcmask;\n");
- /* All of this extra code is just a bodge
- required because some hosts don't allow
- ((v) << 64). The SPARC just leaves the (v)
- value un-touched. */
- printf(" if (byte == 0)\n");
- printf(" srcmask = 0;\n");
- printf(" else\n");
- printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen);
- printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n",datalen);
- printf(" }\n");
- if (proc64 && (datalen == 4))
- printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
- } else { /* store */
- printf(" memval = (op2 << (byte * 8));\n");
- build_endian_shift(proc64,datalen,2,s_left,32);
- printf(" StoreMemory(uncached,(%s - byte),memval,paddr,vaddr,isREAL);\n",accesslength);
- }
- }
- }
- break;
-
- default:
- fprintf(stderr,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",MIPS_DECODE[loop].name);
- exit(6);
- }
- } else { /* normal memory transfer */
- if (!(MIPS_DECODE[loop].flags & COPROC) && ((datalen == 8) || ((datalen == 4) & (MIPS_DECODE[loop].flags & UNSIGNED))) && !proc64) {
- fprintf(stderr,"Operation not available with 32bit wide memory access \"%s\"\n",MIPS_DECODE[loop].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) {
+ printf(" {\n");
+ printf(" uword64 srcmask;\n");
+ /* All of this extra code is just a bodge
+ required because some hosts don't allow
+ ((v) << 64). The SPARC just leaves the (v)
+ value un-touched. */
+ printf(" if (byte == 0)\n");
+ printf(" srcmask = 0;\n");
+ printf(" else\n");
+ printf(" srcmask = ((uword64)-1 << (8 * (%d - byte)));\n",datalen);
+ printf(" GPR[destreg] = ((GPR[destreg] & srcmask) | (memval >> (8 * byte)));\n");
+ printf(" }\n");
+ if (proc64 && (datalen == 4))
+ printf(" GPR[destreg] = SIGNEXTEND(GPR[destreg],32);\n");
+ } else { /* store */
+ printf(" memval = ((uword64) op2 << (byte * 8));\n");
+ build_endian_shift(proc64,datalen,2,s_left,32);
+ printf(" StoreMemory(uncached,(%s - byte),memval,memval1,paddr,vaddr,isREAL);\n",accesslength);
+ }
+ }
+ }
+ break;
+
+ default:
+ fprintf(stderr,"Shifted memory transfer not WORD or DOUBLEWORD in length \"%s\"\n",insn->name);
+ exit(6);
+ }
+ } else { /* normal memory transfer */
+ 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");
+ printf(" uword64 mask = 0x7;\n");
#else
- printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
+ 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 shift = %d;\n",(datalen >> 1));
+ 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);
-
- /* The following will only make sense if the
- "LoadMemory" above returns a DOUBLEWORD entity */
- if (datalen != 8) { /* not for DOUBLEWORD */
- int valmask;
- switch (datalen) {
- case 1:
- valmask = 0xFF;
- break;
-
- case 2:
- valmask = 0xFFFF;
- break;
-
- case 4:
- valmask = 0xFFFFFFFF;
- break;
-
- default:
- fprintf(stderr,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen,MIPS_DECODE[loop].name);
- exit(4);
- }
- printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
- /* NOTE: The R4000 user manual has the COP_LW
- occuring in the same cycle as the rest of the
- instruction, yet the MIPS IV shows the operation
- happening on the next cycle. To keep the simulator
- simple, this code follows the R4000
- manual. Experimentation with a silicon
- implementation will be needed to ascertain the
- correct operation. */
- if (MIPS_DECODE[loop].flags & COPROC)
- printf(" COP_LW(%s,destreg,(unsigned int)",
- ((MIPS_DECODE[loop].flags & REG)
- ? "1"
- : "((instruction >> 26) & 0x3)"));
- else
- printf(" GPR[destreg] = (");
-
- if (MIPS_DECODE[loop].flags & SIGNEXTEND)
- printf("SIGNEXTEND(");
- printf("((memval >> (8 * byte)) & 0x%08X)",valmask);
- if (MIPS_DECODE[loop].flags & SIGNEXTEND)
- printf(",%d)",(datalen * 8));
- printf(");\n");
- } else {
- if (MIPS_DECODE[loop].flags & COPROC)
- printf(" COP_LD(%s,destreg,memval);;\n",
- ((MIPS_DECODE[loop].flags & REG)
- ? "1"
- : "((instruction >> 26) & 0x3)"));
- else
+ 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 */
+ /* start-sanitize-r5900 */
+ /* not for QUADWORD */
+ /* end-sanitize-r5900 */
+ int valmask;
+ switch (datalen) {
+ case 1:
+ valmask = 0xFF;
+ break;
+
+ case 2:
+ valmask = 0xFFFF;
+ break;
+
+ case 4:
+ valmask = 0xFFFFFFFF;
+ break;
+
+ default:
+ fprintf(stderr,"Unrecognised datalen (%d) when processing \"%s\"\n",datalen,insn->name);
+ exit(4);
+ }
+ printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
+ /* NOTE: The R4000 user manual has the COP_LW
+ occuring in the same cycle as the rest of the
+ instruction, yet the MIPS IV shows the operation
+ happening on the next cycle. To keep the simulator
+ simple, this code follows the R4000
+ manual. Experimentation with a silicon
+ implementation will be needed to ascertain the
+ correct operation. */
+ if (insn->flags & COPROC)
+ printf(" COP_LW(%s,destreg,(unsigned int)",
+ ((insn->flags & REG)
+ ? "1"
+ : "((instruction >> 26) & 0x3)"));
+ else
+ printf(" GPR[destreg] = (");
+
+ if (insn->flags & SIGNEXTEND)
+ printf("SIGNEXTEND(");
+ printf("((memval >> (8 * byte)) & 0x%08X)",valmask);
+ if (insn->flags & SIGNEXTEND)
+ printf(",%d)",(datalen * 8));
+ printf(");\n");
+ } else {
+ if (insn->flags & COPROC)
+ printf(" COP_LD(%s,destreg,memval);;\n",
+ ((insn->flags & REG)
+ ? "1"
+ : "((instruction >> 26) & 0x3)"));
+ else
+ {
printf(" GPR[destreg] = memval;\n");
- }
- } else { /* store operation */
- if ((datalen == 1) || (datalen == 2)) {
- /* SH and SB */
+ if (datalen > 8)
+ printf(" GPR1[destreg] = memval1;\n");
+ }
+ }
+ } else { /* store operation */
+ if ((datalen == 1) || (datalen == 2)) {
+ /* SH and SB */
#if 1 /* see the comments attached to LOADDRMASK above */
- printf(" uword64 mask = 0x7;\n");
+ printf(" uword64 mask = 0x7;\n");
#else
- printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
+ 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(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
- printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
- printf(" memval = (op2 << (8 * byte));\n");
- } else
- if (proc64 && (datalen == 4)) { /* proc64 SC and SW */
+ 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(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (reverse << shift)));\n");
+ printf(" byte = ((vaddr & mask) ^ (bigend << shift));\n");
+ printf(" memval = ((uword64) op2 << (8 * byte));\n");
+ } else
+ if (datalen == 4) { /* SC and SW */
#if 1 /* see the comments attached to LOADDRMASK above */
- printf(" uword64 mask = 0x7;\n");
+ printf(" uword64 mask = 0x7;\n");
#else
- printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
+ printf(" uword64 mask = %d;\n",(proc64 ? 0x7 : 0x3));
#endif
- printf(" unsigned int byte;\n");
- printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n");
- printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n");
- if (MIPS_DECODE[loop].flags & COPROC)
- printf(" memval = (((uword64)COP_SW(%s,%s)) << (8 * byte));\n",
- ((MIPS_DECODE[loop].flags & REG)
- ? "1"
- : "((instruction >> 26) & 0x3)"),
- ((MIPS_DECODE[loop].flags & FP) ? "fs" : "destreg"));
- else
- printf(" memval = (op2 << (8 * byte));\n");
- } else { /* !proc64 SC and SW, plus proc64 SD and SCD */
- if (MIPS_DECODE[loop].flags & COPROC)
- printf(" memval = (uword64)COP_S%c(%s,%s);\n",
- ((datalen == 8) ? 'D' : 'W'),
- ((MIPS_DECODE[loop].flags & REG)
- ? "1"
- : "((instruction >> 26) & 0x3)"),
- ((MIPS_DECODE[loop].flags & FP) ? "fs" : "destreg"));
- else
- printf(" memval = op2;\n");
- }
+ printf(" unsigned int byte;\n");
+ printf(" paddr = ((paddr & ~mask) | ((paddr & mask) ^ (ReverseEndian << 2)));\n");
+ printf(" byte = ((vaddr & mask) ^ (BigEndianCPU << 2));\n");
+ if (insn->flags & COPROC)
+ printf(" memval = (((uword64)COP_SW(%s,%s)) << (8 * byte));\n",
+ ((insn->flags & REG)
+ ? "1"
+ : "((instruction >> 26) & 0x3)"),
+ ((insn->flags & FP) ? "fs" : "destreg"));
+ else
+ 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_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,memval1,paddr,vaddr,isREAL);\n",accesslength);
+ printf(" }\n");
+ }
+
+ if (insn->flags & ATOMIC) {
+ if ((datalen != 4) && (datalen != 8)) {
+ fprintf(stderr,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",insn->name);
+ exit(4);
+ } else
+ if (isload)
+ printf(" LLBIT = 1;\n");
+ else {
+ /* The documentation states that:
+
+ SC *WILL* fail if coherent store into the same
+ block occurs, or if an exception occurs between
+ the LL and SC instructions.
+
+ SC *MAY* fail if a load, store or prefetch is
+ executed on the processor (VR4300 doesn't seem
+ to), or if the instructions between the LL and
+ SC are not in a 2048byte contiguous VM range.
+
+ SC *MUST* have been preceded by an LL
+ (i.e. LLBIT will be set), and it must use the
+ same Vaddr, Paddr and cache-coherence algorithm
+ as the LL (which means we should store this
+ information from the load-conditional).
+ */
+ printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT,OP_MASK_RT);
+ }
+ }
+ }
+ printf(" }\n");
+ }
+ printf(" }\n");
+ }
+ break ;
+
+ case FPPREFX:
+ /* This code could be merged with the PREFIX generation above: */
+ 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");
+ break ;
+
+ case FPMOVEC:
+ if (insn->flags & CONTROL) {
+ /* The following "magic" of interpreting the FP
+ control-register number would not be needed if we were not
+ trying to match our internal register numbers with those
+ used by GDB. */
+ printf(" if (to) {\n");
+ if (doisa < 4) {
+ printf(" if (fs == 0) {\n");
+ printf(" PENDING_FILL((fs + FCR0IDX),WORD64LO(GPR[ft]));\n");
+ printf(" } else if (fs == 31) {\n");
+ printf(" PENDING_FILL((fs + FCR31IDX),WORD64LO(GPR[ft]));\n");
+ printf(" } /* else NOP */\n");
+ printf(" PENDING_FILL(COCIDX,0); /* special case */\n");
+ } else {
+ printf(" if (fs == 0) {\n");
+ printf(" FCR0 = WORD64LO(GPR[ft]);\n");
+ printf(" } else if (fs == 31) {\n");
+ printf(" FCR31 = WORD64LO(GPR[ft]);\n");
+ printf(" } /* else NOP */\n");
+ printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n");
+ }
+ printf(" } else { /* control from */\n");
+ if (doisa < 4) {
+ printf(" if (fs == 0) {\n");
+ printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n");
+ printf(" } else if (fs == 31) {\n");
+ printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n");
+ printf(" } /* else NOP */\n");
+ } else {
+ printf(" if (fs == 0) {\n");
+ printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n");
+ printf(" } else if (fs == 31) {\n");
+ printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n");
+ printf(" } /* else NOP */\n");
+ }
+ printf(" }\n");
+ } else {
+ printf(" if (to) {\n");
+ if (GETDATASIZEINSN(insn) == WORD) {
+ if (doisa < 4) {
+ printf(" if (SizeFGR() == 64) {\n");
+ printf(" PENDING_FILL((fs + FGRIDX),(SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft])));\n");
+ printf(" } else { \n");
+ printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
+ printf(" }\n");
+ } else {
+ printf(" if (SizeFGR() == 64)\n");
+ 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");
+ }
+ } else if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
+ if (doisa < 4) {
+ printf(" if (SizeFGR() == 64) {\n");
+ printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n");
+ printf(" } else\n");
+ printf(" if ((fs & 0x1) == 0)\n");
+ printf(" {\n");
+ printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n");
+ printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
+ printf(" }\n");
+ if (features & FEATURE_WARN_RESULT) {
+ printf(" else\n");
+ printf(" UndefinedResult();\n");
+ }
+ } else {
+ printf(" if (SizeFGR() == 64) {\n");
+ printf(" FGR[fs] = GPR[ft];\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(" }\n");
+ if (features & FEATURE_WARN_RESULT) {
+ printf(" else\n");
+ printf(" UndefinedResult();\n");
+ }
+ }
+ } else {
+ fprintf(stderr,"Invalid data width specified in FPU Move operation\n");
+ exit(1);
+ }
+ printf(" } else {\n");
+ if (GETDATASIZEINSN(insn) == WORD) {
+ if (doisa < 4) /* write-back occurs in next cycle */
+ printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n");
+ else /* in this cycle */
+ printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n");
+ } else if (GETDATASIZEINSN(insn) == DOUBLEWORD) {
+ if (doisa < 4) {
+ printf(" if (SizeFGR() == 64) {\n");
+ printf(" PENDING_FILL(ft,FGR[fs]);\n");
+ printf(" } else\n");
+ printf(" if ((fs & 0x1) == 0) {\n");
+ printf(" PENDING_FILL(ft,(SET64HI(FGR[fs+1]) | FGR[fs]));\n");
+ printf(" } else {\n");
+ printf(" PENDING_FILL(ft,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
+ if (features & FEATURE_WARN_RESULT)
+ printf(" UndefinedResult();\n");
+ printf(" }\n");
+ } else {
+ printf(" if (SizeFGR() == 64)\n");
+ printf(" GPR[ft] = FGR[fs];\n");
+ printf(" else\n");
+ printf(" if ((fs & 0x1) == 0)\n");
+ printf(" GPR[ft] = (SET64HI(FGR[fs + 1]) | FGR[fs]);\n");
+ printf(" else {\n");
+ printf(" GPR[ft] = (SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
+ if (features & FEATURE_WARN_RESULT)
+ printf(" UndefinedResult();\n");
+ printf(" }\n");
+ }
+ } else {
+ fprintf(stderr,"Invalid data width specified in FPU Move operation\n");
+ exit(1);
+ }
+ printf(" }\n");
+ }
+ break ;
+
+ case FPMOVE:
+ if (insn->flags & CONDITIONAL) {
+ if (insn->flags & INTEGER) { /* moving GPR - testing FGR */
+ printf(" if (GETFCC(condition_code) == boolean)\n");
+ printf(" GPR[destreg] = op1;\n");
+ } else {
+ if (insn->flags & EQ) /* moving FGR - testing GPR */
+ printf(" if (op2 %c= 0)\n",((insn->flags & NOT) ? '!' : '='));
+ else
+ printf(" if (GETFCC(condition_code) == boolean)\n");
+ printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
+ printf(" else\n");
+ printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
+ }
+ } else { /* simple MOVE */
+ printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
+ }
+ break ;
+
+ case FPNEG:
+ printf(" if ((format != fmt_single) && (format != fmt_double))\n");
+ printf(" SignalException(ReservedInstruction,instruction);\n");
+ printf(" else\n");
+ printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
+ break ;
+
+ case FPABS:
+ printf(" if ((format != fmt_single) && (format != fmt_double))\n");
+ printf(" SignalException(ReservedInstruction,instruction);\n");
+ printf(" else\n");
+ printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n");
+ break ;
+
+ case FPDIV:
+ printf(" if ((format != fmt_single) && (format != fmt_double))\n");
+ printf(" SignalException(ReservedInstruction,instruction);\n");
+ printf(" else\n");
+ printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
+ break ;
+
+ case FPMUL:
+ printf(" if ((format != fmt_single) && (format != fmt_double))\n");
+ printf(" SignalException(ReservedInstruction,instruction);\n");
+ printf(" else\n");
+ printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
+ break ;
+
+ case FPRECIP:
+ printf(" if ((format != fmt_single) && (format != fmt_double))\n");
+ printf(" SignalException(ReservedInstruction,instruction);\n");
+ printf(" else\n");
+ printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\n");
+ break ;
+
+ case FPSQRT:
+ 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)%s));\n",
+ ((insn->flags & RECIP) ? "Recip" : ""),
+ ((insn->flags & RECIP) ? ",format" : ""));
+ break ;
+
+ case FPCEIL:
+ case FPFLOOR:
+ case FPTRUNC:
+ case FPROUND:
+ {
+ char *op = "";
+ char *type = "";
+
+ switch (insn->type) {
+ case FPCEIL:
+ op = "FP_RM_TOPINF";
+ break;
+ case FPFLOOR:
+ op = "FP_RM_TOMINF";
+ break;
+ case FPTRUNC:
+ op = "FP_RM_TOZERO";
+ break;
+ case FPROUND:
+ op = "FP_RM_NEAREST";
+ break;
+ default:
+ fprintf(stderr,"Error: Handled missing for FP reason code %d\n",insn->type);
+ exit(1);
+ }
- if (MIPS_DECODE[loop].flags & ATOMIC)
- printf(" if (LLBIT)\n");
+ switch (GETDATASIZEINSN(insn)) {
+ case WORD :
+ type = "fmt_word";
+ break;
+ case DOUBLEWORD :
+ type = "fmt_long";
+ break;
+ default:
+ fprintf(stderr,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op);
+ exit(1);
+ }
+ printf(" if ((format != fmt_single) && (format != fmt_double))\n");
+ printf(" SignalException(ReservedInstruction,instruction);\n");
+ printf(" else\n");
+ printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type,op,type);
+ }
+ break ;
+
+ case FPCONVERT:
+ {
+ char *type = "";
+ switch (GETDATASIZEINSN(insn)) {
+ case SINGLE:
+ type = "fmt_single";
+ break;
+ case DOUBLE:
+ type = "fmt_double";
+ break;
+ case WORD:
+ type = "fmt_word";
+ break;
+ case DOUBLEWORD:
+ type = "fmt_long";
+ break;
+ default :
+ fprintf(stderr,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZEINSN(insn));
+ exit(1);
+ }
- printf(" {\n");
- printf(" StoreMemory(uncached,%s,memval,paddr,vaddr,isREAL);\n",accesslength);
- printf(" }\n");
- }
+ /* Not all combinations of conversion are valid at the
+ moment: When converting to a fixed-point format, only
+ floating-point sources are allowed. */
+ printf(" if ((format == %s) | %s)\n",type,((insn->flags & FIXED) ? "((format == fmt_long) || (format == fmt_word))": "0"));
+ printf(" SignalException(ReservedInstruction,instruction);\n");
+ printf(" else\n");
+ printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type,type);
+ }
+ break ;
+
+ case FPSUB:
+ if (insn->flags & MULTIPLY) {
+ char *type = "";
+ switch (GETDATASIZEINSN(insn)) {
+ case SINGLE:
+ type = "fmt_single";
+ break;
+ case DOUBLE:
+ type = "fmt_double";
+ break;
+ default:
+ fprintf(stderr,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZEINSN(insn));
+ exit(1);
+ }
+ 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");
+ printf(" else\n");
+ printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
+ }
+ break ;
+
+ case FPADD:
+ if (insn->flags & MULTIPLY) {
+ char *type = "";
+ switch (GETDATASIZEINSN(insn)) {
+ case SINGLE:
+ type = "fmt_single";
+ break;
+ case DOUBLE:
+ type = "fmt_double";
+ break;
+ default:
+ fprintf(stderr,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZEINSN(insn));
+ exit(1);
+ }
+ if (insn->flags & NOT)
+ printf (" StoreFPR(destreg,%s,Negate(Add(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,Add(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");
+ printf(" else\n");
+ printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\n");
+ }
+ break ;
+
+ case FPCOMPARE:
+ /* For the MIPS I,II or III there *MUST* be at least one
+ instruction between the compare that sets a condition code
+ and the branch that tests it. NOTE: However the hardware
+ does not detect this condition. */
+ /* Explicitly limit the operation to S and D formats: */
+ printf(" if ((format != fmt_single) && (format != fmt_double))\n");
+ printf(" SignalException(ReservedInstruction,instruction);\n") ;
+ printf(" else {\n");
+ if (doisa < 4) {
+ printf(" if (condition_code != 0)\n");
+ printf(" SignalException(ReservedInstruction,instruction);\n") ;
+ printf(" else\n");
+ }
+ printf(" {\n");
+ printf(" int ignore = 0;\n");
+ printf(" int less = 0;\n");
+ printf(" int equal = 0;\n");
+ printf(" int unordered = 1;\n");
+ printf(" uword64 ofs = ValueFPR(fs,format);\n");
+ printf(" uword64 oft = ValueFPR(ft,format);\n");
+ printf(" if (NaN(ofs,format) || NaN(oft,format)) {\n");
+ printf(" if (FCSR & FP_ENABLE(IO)) {\n");
+ printf(" FCSR |= FP_CAUSE(IO);\n");
+ printf(" SignalExceptionFPE ();\n");
+ printf(" ignore = 1;\n");
+ printf(" }\n");
+ printf(" } else {\n");
+ printf(" less = Less(ofs,oft,format);\n");
+ printf(" equal = Equal(ofs,oft,format);\n");
+ printf(" unordered = 0;\n");
+ printf(" }\n");
+ printf(" if (!ignore) {\n");
+ printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
+ printf(" SETFCC(condition_code,condition);\n");
+ printf(" }\n");
+ printf(" }\n");
+ 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;
+ }
- if (MIPS_DECODE[loop].flags & ATOMIC) {
- if ((datalen != 4) && (datalen != 8)) {
- fprintf(stderr,"ATOMIC can only be applied to WORD and DOUBLEWORD instructions \"%s\"\n",MIPS_DECODE[loop].name);
- exit(4);
- } else
- if (isload)
- printf(" LLBIT = 1;\n");
- else {
- /* The documentation states that:
-
- SC *WILL* fail if coherent store into the same
- block occurs, or if an exception occurs between
- the LL and SC instructions.
-
- SC *MAY* fail if a load, store or prefetch is
- executed on the processor (VR4300 doesn't seem
- to), or if the instructions between the LL and
- SC are not in a 2048byte contiguous VM range.
-
- SC *MUST* have been preceded by an LL
- (i.e. LLBIT will be set), and it must use the
- same Vaddr, Paddr and cache-coherence algorithm
- as the LL (which means we should store this
- information from the load-conditional).
- */
- printf(" GPR[(instruction >> %d) & 0x%08X] = LLBIT;\n",OP_SH_RT,OP_MASK_RT);
- }
- }
- }
- printf(" }\n");
+/* 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(" }\n");
- }
- break ;
-
- 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(" int uncached;\n");
- printf(" if (AddressTranslation(vaddr,isDATA,isLOAD,&paddr,&uncached,isTARGET,isREAL))\n");
- printf(" Prefetch(uncached,paddr,vaddr,isDATA,fs);\n");
- break ;
- case FPMOVEC:
- if (MIPS_DECODE[loop].flags & CONTROL) {
- /* The following "magic" of interpreting the FP
- control-register number would not be needed if we were not
- trying to match our internal register numbers with those
- used by GDB. */
- printf(" if (to) {\n");
- if (doisa < 4) {
- printf(" if (fs == 0) {\n");
- printf(" PENDING_FILL((fs + FCR0IDX),WORD64LO(GPR[ft]));\n");
- printf(" } else if (fs == 31) {\n");
- printf(" PENDING_FILL((fs + FCR31IDX),WORD64LO(GPR[ft]));\n");
- printf(" } /* else NOP */\n");
- printf(" PENDING_FILL(COCIDX,0); /* special case */\n");
- } else {
- printf(" if (fs == 0) {\n");
- printf(" FCR0 = WORD64LO(GPR[ft]);\n");
- printf(" } else if (fs == 31) {\n");
- printf(" FCR31 = WORD64LO(GPR[ft]);\n");
- printf(" } /* else NOP */\n");
- printf(" SETFCC(0,((FCR31 & (1 << 23)) ? 1 : 0)); /* COC[1] */\n");
- }
- printf(" } else { /* control from */\n");
- if (doisa < 4) {
- printf(" if (fs == 0) {\n");
- printf(" PENDING_FILL(ft,SIGNEXTEND(FCR0,32));\n");
- printf(" } else if (fs == 31) {\n");
- printf(" PENDING_FILL(ft,SIGNEXTEND(FCR31,32));\n");
- printf(" } /* else NOP */\n");
- } else {
- printf(" if (fs == 0) {\n");
- printf(" GPR[ft] = SIGNEXTEND(FCR0,32);\n");
- printf(" } else if (fs == 31) {\n");
- printf(" GPR[ft] = SIGNEXTEND(FCR31,32);\n");
- printf(" } /* else NOP */\n");
- }
- printf(" }\n");
- } else {
- printf(" if (to) {\n");
- if (GETDATASIZE() == WORD) {
- if (doisa < 4) {
- printf(" if (SizeFGR() == 64) {\n");
- printf(" PENDING_FILL((fs + FGRIDX),(SET64HI(0xDEADC0DE) | WORD64LO(GPR[ft])));\n");
- printf(" } else { \n");
- printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
- printf(" }\n");
- } else {
- printf(" if (SizeFGR() == 64)\n");
- 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");
- }
- } else if (GETDATASIZE() == DOUBLEWORD) {
- if (doisa < 4) {
- printf(" if (SizeFGR() == 64) {\n");
- printf(" PENDING_FILL((fs + FGRIDX),GPR[ft]);\n");
- printf(" } else\n");
- printf(" if ((fs & 0x1) == 0)\n");
- printf(" {\n");
- printf(" PENDING_FILL(((fs + 1) + FGRIDX),WORD64HI(GPR[ft]));\n");
- printf(" PENDING_FILL((fs + FGRIDX),WORD64LO(GPR[ft]));\n");
- printf(" }\n");
- if (features & FEATURE_WARN_RESULT) {
- printf(" else\n");
- printf(" UndefinedResult();\n");
- }
- } else {
- printf(" if (SizeFGR() == 64) {\n");
- printf(" FGR[fs] = GPR[ft];\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(" }\n");
- if (features & FEATURE_WARN_RESULT) {
- printf(" else\n");
- printf(" UndefinedResult();\n");
- }
- }
- } else {
- fprintf(stderr,"Invalid data width specified in FPU Move operation\n");
- exit(1);
- }
- printf(" } else {\n");
- if (GETDATASIZE() == WORD) {
- if (doisa < 4) /* write-back occurs in next cycle */
- printf(" PENDING_FILL(ft,SIGNEXTEND(FGR[fs],32));\n");
- else /* in this cycle */
- printf(" GPR[ft] = SIGNEXTEND(FGR[fs],32);\n");
- } else if (GETDATASIZE() == DOUBLEWORD) {
- if (doisa < 4) {
- printf(" if (SizeFGR() == 64) {\n");
- printf(" PENDING_FILL(ft,FGR[fs]);\n");
- printf(" } else\n");
- printf(" if ((fs & 0x1) == 0) {\n");
- printf(" PENDING_FILL(ft,(SET64HI(FGR[fs+1]) | FGR[fs]));\n");
- printf(" } else {\n");
- printf(" PENDING_FILL(ft,SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
- if (features & FEATURE_WARN_RESULT)
- printf(" UndefinedResult();\n");
- printf(" }\n");
- } else {
- printf(" if (SizeFGR() == 64)\n");
- printf(" GPR[ft] = FGR[fs];\n");
- printf(" else\n");
- printf(" if ((fs & 0x1) == 0)\n");
- printf(" GPR[ft] = (SET64HI(FGR[fs + 1]) | FGR[fs]);\n");
- printf(" else {\n");
- printf(" GPR[ft] = (SET64HI(0xDEADC0DE) | 0xBAD0BAD0);\n");
- if (features & FEATURE_WARN_RESULT)
- printf(" UndefinedResult();\n");
- printf(" }\n");
- }
- } else {
- fprintf(stderr,"Invalid data width specified in FPU Move operation\n");
- exit(1);
- }
- printf(" }\n");
- }
- break ;
+ 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 FPMOVE:
- if (MIPS_DECODE[loop].flags & CONDITIONAL) {
- if (MIPS_DECODE[loop].flags & INTEGER) { /* moving GPR - testing FGR */
- printf(" if (GETFCC(condition_code) == boolean)\n");
- printf(" GPR[destreg] = op1;\n");
- } else {
- if (MIPS_DECODE[loop].flags & EQ) /* moving FGR - testing GPR */
- printf(" if (op2 %c= 0)\n",((MIPS_DECODE[loop].flags & NOT) ? '!' : '='));
- else
- printf(" if (GETFCC(condition_code) == boolean)\n");
- printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\n");
- printf(" else\n");
- printf(" StoreFPR(destreg,format,ValueFPR(destreg,format));\n");
- }
- } else { /* simple MOVE */
- printf(" StoreFPR(destreg,format,ValueFPR(fs,format));\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 FPNEG:
- printf(" if ((format != fmt_single) && (format != fmt_double))\n");
- printf(" SignalException(ReservedInstruction,instruction);\n");
- printf(" else\n");
- printf(" StoreFPR(destreg,format,Negate(ValueFPR(fs,format),format));\n");
- 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";
- case FPABS:
- printf(" if ((format != fmt_single) && (format != fmt_double))\n");
- printf(" SignalException(ReservedInstruction,instruction);\n");
- printf(" else\n");
- printf(" StoreFPR(destreg,format,AbsoluteValue(ValueFPR(fs,format),format));\n");
- break ;
+ 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 FPDIV:
- printf(" if ((format != fmt_single) && (format != fmt_double))\n");
- printf(" SignalException(ReservedInstruction,instruction);\n");
- printf(" else\n");
- printf(" StoreFPR(destreg,format,Divide(ValueFPR(fs,format),ValueFPR(ft,format),format));\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 FPMUL:
- printf(" if ((format != fmt_single) && (format != fmt_double))\n");
- printf(" SignalException(ReservedInstruction,instruction);\n");
- printf(" else\n");
- printf(" StoreFPR(destreg,format,Multiply(ValueFPR(fs,format),ValueFPR(ft,format),format));\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 FPRECIP:
- printf(" if ((format != fmt_single) && (format != fmt_double))\n");
- printf(" SignalException(ReservedInstruction,instruction);\n");
- printf(" else\n");
- printf(" StoreFPR(destreg,format,Recip(ValueFPR(fs,format),format));\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 FPSQRT:
- 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",((MIPS_DECODE[loop].flags & RECIP) ? "Recip" : ""));
- 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 FPCEIL:
- case FPFLOOR:
- case FPTRUNC:
- case FPROUND:
- {
- char *op = "";
- char *type = "";
-
- switch (MIPS_DECODE[loop].type) {
- case FPCEIL:
- op = "FP_RM_TOPINF";
- break;
- case FPFLOOR:
- op = "FP_RM_TOMINF";
- break;
- case FPTRUNC:
- op = "FP_RM_TOZERO";
- break;
- case FPROUND:
- op = "FP_RM_NEAREST";
- break;
- default:
- fprintf(stderr,"Error: Handled missing for FP reason code %d\n",MIPS_DECODE[loop].type);
- exit(1);
- }
+ 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;
+ }
- switch (GETDATASIZE()) {
- case WORD :
- type = "fmt_word";
- break;
- case DOUBLEWORD :
- type = "fmt_long";
- break;
- default:
- fprintf(stderr,"Error in instruction encoding table for FP %s operation (not WORD or DOUBLEWORD)\n",op);
- exit(1);
- }
- printf(" if ((format != fmt_single) && (format != fmt_double))\n");
- printf(" SignalException(ReservedInstruction,instruction);\n");
- printf(" else\n");
- printf(" StoreFPR(destreg,%s,Convert(%s,ValueFPR(fs,format),format,%s));\n",type,op,type);
- }
- 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 FPCONVERT:
- {
- char *type = "";
- switch (GETDATASIZE()) {
- case SINGLE:
- type = "fmt_single";
- break;
- case DOUBLE:
- type = "fmt_double";
- break;
- case WORD:
- type = "fmt_word";
- break;
- case DOUBLEWORD:
- type = "fmt_long";
- break;
- default :
- fprintf(stderr,"Error: Unknown data size %d in FPCONVERT instruction\n",GETDATASIZE());
- exit(1);
- }
+ 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 );
- /* Not all combinations of conversion are valid at the
- moment: When converting to a fixed-point format, only
- floating-point sources are allowed. */
- printf(" if ((format == %s) | %s)\n",type,((MIPS_DECODE[loop].flags & FIXED) ? "((format == fmt_long) || (format == fmt_word))": "0"));
- printf(" SignalException(ReservedInstruction,instruction);\n");
- printf(" else\n");
- printf(" StoreFPR(destreg,%s,Convert(GETRM(),ValueFPR(fs,format),format,%s));\n",type,type);
- }
- break ;
+ 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 FPSUB:
- if (MIPS_DECODE[loop].flags & MULTIPLY) {
- char *type = "";
- switch (GETDATASIZE()) {
- case SINGLE:
- type = "fmt_single";
- break;
- case DOUBLE:
- type = "fmt_double";
- break;
- default:
- fprintf(stderr,"Error: Invalid data size %d for FPSUB operation\n",GETDATASIZE());
- exit(1);
- }
- printf(" StoreFPR(destreg,%s,%s(Sub(Multiply(ValueFPR(fs,%s),ValueFPR(ft,%s),%s),ValueFPR(fr,%s),%s),%s));\n",type,((MIPS_DECODE[loop].flags & NOT) ? "Negate" : ""),type,type,type,type,type,type);
- } else {
- printf(" if ((format != fmt_single) && (format != fmt_double))\n");
- printf(" SignalException(ReservedInstruction,instruction);\n");
- printf(" else\n");
- printf(" StoreFPR(destreg,format,Sub(ValueFPR(fs,format),ValueFPR(ft,format),format));\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 FPADD:
- if (MIPS_DECODE[loop].flags & MULTIPLY) {
- char *type = "";
- switch (GETDATASIZE()) {
- case SINGLE:
- type = "fmt_single";
- break;
- case DOUBLE:
- type = "fmt_double";
- break;
- default:
- fprintf(stderr,"Error: Invalid data size %d for FPADD operation in instruction table\n",GETDATASIZE());
- exit(1);
- }
- if (MIPS_DECODE[loop].flags & NOT)
- printf (" StoreFPR(destreg,%s,Negate(Add(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,Add(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");
- printf(" else\n");
- printf(" StoreFPR(destreg,format,Add(ValueFPR(fs,format),ValueFPR(ft,format),format));\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 FPCOMPARE:
- /* For the MIPS I,II or III there *MUST* be at least one
- instruction between the compare that sets a condition code
- and the branch that tests it. NOTE: However the hardware
- does not detect this condition. */
- /* Explicitly limit the operation to S and D formats: */
- printf(" if ((format != fmt_single) && (format != fmt_double))\n");
- printf(" SignalException(ReservedInstruction,instruction);\n") ;
- printf(" else {\n");
- if (doisa < 4) {
- printf(" if ((cmpflags & (1 << 3)) || (condition_code != 0))\n");
- printf(" SignalException(ReservedInstruction,instruction);\n") ;
- printf(" else\n");
- }
- printf(" {\n");
- printf(" int ignore = 0;\n");
- printf(" int less = 0;\n");
- printf(" int equal = 0;\n");
- printf(" int unordered = 1;\n");
- printf(" uword64 ofs = ValueFPR(fs,format);\n");
- printf(" uword64 oft = ValueFPR(ft,format);\n");
- 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(" ignore = 1;\n");
- printf(" }\n");
- printf(" } else {\n");
- printf(" less = Less(ofs,oft,format);\n");
- printf(" equal = Equal(ofs,oft,format);\n");
- printf(" unordered = 0;\n");
- printf(" }\n");
- printf(" if (!ignore) {\n");
- printf(" int condition = (((cmpflags & (1 << 2)) && less) || ((cmpflags & (1 << 1)) && equal) || ((cmpflags & (1 << 0)) && unordered));\n");
- printf(" SETFCC(condition_code,condition);\n");
- printf(" }\n");
- printf(" }\n");
- printf(" }\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;
- default:
- fprintf(stderr,"Unrecognised opcode type %d\n",MIPS_DECODE[loop].type) ;
- exit(6) ;
- }
- printf(" }\n") ;
- printf(" }\n") ;
- printf(" break ;\n") ;
- }
- }
+ 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 */
- printf("default : /* Unrecognised instruction */\n") ;
- printf(" SignalException(ReservedInstruction,instruction);\n") ;
- printf(" break ;\n") ;
- printf("}\n}\n") ;
- printf("#endif /* simulator engine */\n");
+ case NYI:
+ fprintf(stderr,"Warning: Unimplemented opcode: %s\n",insn->name) ;
- return ;
+ printf("SignalException(ReservedInstruction,instruction);\n");
+ break;
+
+ default:
+ fprintf(stderr,"Unrecognised opcode type %d\n",insn->type) ;
+ exit(6) ;
+ }
}
/*---------------------------------------------------------------------------*/
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 */
};
break;
default :
- fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",machine_options[loop].type);
+ fprintf(stderr,"%s: FATAL error: unrecognised machine option type ID %d\n",name,machine_options[loop].type);
exit(1);
}
fprintf(stderr,"%s\n",machine_options[loop].desc);
features |= FEATURE_GP64;
while (1) {
- int this_option_optind = (optind ? optind : 1);
int option_index = 0;
static struct option cmdline[] = {
{"fast", 0,0,'f'},
{"help", 0,0,'h'},
{"warnings",0,0,'w'},
+ {"igen", 0,0,'i'},
{0, 0,0,0}
};
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:
for (archloop = 0; (available_architectures[archloop].name != 0); archloop++) {
if ((*loptarg == 'v') || (*loptarg == 'V'))
- *loptarg++;
+ loptarg++;
- if (*loptarg && (*loptarg == 'r') || (*loptarg == 'R'))
- *loptarg++;
+ if ((*loptarg == 'r') || (*loptarg == 'R'))
+ loptarg++;
if (strcmp(available_architectures[archloop].name,loptarg) == 0) {
doarch |= available_architectures[archloop].idflag;
break;
if (c >= base)
break;
- if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
+ if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;