package vue; // Instruction state and decoder public class Instruction { // Instruction fields public int bits; // Binary encoding public int cond; // Condition for Bcond public int disp; // Displacement for jumps and branches public int format; // Binary format public int id; // Library-specific identifier public int imm; // Immediate operand public int opcode; // Instruction opcode public int reg1; // Source/right register public int reg2; // Destination/left register public int size; // Number of bytes in encoding public int subopcode; // Instruction subopcode /////////////////////////////////////////////////////////////////////////// // Constants // /////////////////////////////////////////////////////////////////////////// // Intermediate instruction IDs private static final int BITSTRING = -2; private static final int FLOATENDO = -3; // Opcode lookup table private static final byte[] LOOKUP_OPCODE = { VUE.MOV_REG, 1, VUE.ADD_REG, 1, VUE.SUB , 1, VUE.CMP_REG, 1, VUE.SHL_REG, 1, VUE.SHR_REG, 1, VUE.JMP , 1, VUE.SAR_REG, 1, VUE.MUL , 1, VUE.DIV , 1, VUE.MULU , 1, VUE.DIVU , 1, VUE.OR , 1, VUE.AND , 1, VUE.XOR , 1, VUE.NOT , 1, -VUE.MOV_IMM, 2,-VUE.ADD_IMM, 2, VUE.SETF , 2,-VUE.CMP_IMM, 2, VUE.SHL_IMM, 2, VUE.SHR_IMM, 2, VUE.CLI , 2, VUE.SAR_IMM, 2, VUE.TRAP , 2, VUE.RETI , 2, VUE.HALT , 2, VUE.ILLEGAL, 0, VUE.LDSR , 2, VUE.STSR , 2, VUE.SEI , 2, BITSTRING , 2, VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3, VUE.BCOND , 3, -VUE.MOVEA , 5,-VUE.ADDI , 5, VUE.JR , 4, VUE.JAL , 4, VUE.ORI , 5, VUE.ANDI , 5, VUE.XORI , 5, VUE.MOVHI , 5, VUE.LD_B , 6, VUE.LD_H , 6, VUE.ILLEGAL, 0, VUE.LD_W , 6, VUE.ST_B , 6, VUE.ST_H , 6, VUE.ILLEGAL, 0, VUE.ST_W , 6, VUE.IN_B , 6, VUE.IN_H , 6, VUE.CAXI , 6, VUE.IN_W , 6, VUE.OUT_B , 6, VUE.OUT_H , 6, FLOATENDO , 7, VUE.OUT_W , 6 }; // Bit string lookup table private static final byte[] LOOKUP_BITSTRING = { VUE.SCH0BSU, VUE.SCH0BSD, VUE.SCH1BSU, VUE.SCH1BSD, VUE.ILLEGAL, VUE.ILLEGAL, VUE.ILLEGAL, VUE.ILLEGAL, VUE.ORBSU , VUE.ANDBSU , VUE.XORBSU , VUE.MOVBSU , VUE.ORNBSU , VUE.ANDNBSU, VUE.XORNBSU, VUE.XORNBSU }; // Floating-point and Nintendo lookup table private static final byte[] LOOKUP_FLOATENDO = { VUE.CMPF_S , VUE.ILLEGAL, VUE.CVT_WS , VUE.CVT_SW , VUE.ADDF_S , VUE.SUBF_S , VUE.MULF_S , VUE.DIVF_S , VUE.XB , VUE.XH , VUE.REV , VUE.TRNC_SW, VUE.MPYHW , VUE.ILLEGAL, VUE.ILLEGAL, VUE.ILLEGAL }; /////////////////////////////////////////////////////////////////////////// // Static Methods // /////////////////////////////////////////////////////////////////////////// // Determine the size of an instruction given its opcode public static int size(int opcode) { return LOOKUP_OPCODE[opcode << 1 | 1] < 4 ? 2 : 4; } /////////////////////////////////////////////////////////////////////////// // Constructors // /////////////////////////////////////////////////////////////////////////// // Default constructor Instruction() { } /////////////////////////////////////////////////////////////////////////// // Public Methods // /////////////////////////////////////////////////////////////////////////// // Decode an instruction from its binary encoding public void decode(int bits) { byte extend; // Sign-extend the immediate operand int x; // Working variable // Configure instance fields this.bits = bits; opcode = bits >> 26 & 63; x = opcode << 1 | 1; extend = LOOKUP_OPCODE[x]; format = LOOKUP_OPCODE[x + 1]; id = extend < 0 ? -extend : extend; size = format < 4 ? 2 : 4; // Decode by format switch (format) { case 1: reg2 = bits >> 21 & 31; reg1 = bits >> 16 & 31; break; case 2: reg2 = bits >> 21 & 31; imm = extend < 0 ? bits << 11 >> 27 : bits >> 16 & 31; if (id == BITSTRING) id = imm >= 16 ? VUE.ILLEGAL : LOOKUP_BITSTRING[imm]; break; case 3: opcode = 0x20; cond = bits >> 25 & 15; disp = bits << 7 >> 23; break; case 4: disp = bits << 6 >> 6; break; case 5: reg2 = bits >> 21 & 31; reg1 = bits >> 16 & 31; imm = extend < 0 ? bits << 16 >> 16 : bits & 0xFFFF; break; case 6: reg2 = bits >> 21 & 31; reg1 = bits >> 16 & 31; disp = bits << 16 >> 16; break; case 7: reg2 = bits >> 21 & 31; reg1 = bits >> 16 & 31; subopcode = bits >> 10 & 63; id = subopcode >= 16 ? VUE.ILLEGAL : LOOKUP_FLOATENDO[subopcode]; break; } } }