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