182 lines
6.4 KiB
Java
182 lines
6.4 KiB
Java
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) {
|
|
|
|
// Configure instance fields
|
|
this.bits = bits;
|
|
opcode = bits >> 26 & 63;
|
|
id = opcode << 1 | 1;
|
|
format = LOOKUP_OPCODE[id + 1];
|
|
id = LOOKUP_OPCODE[id];
|
|
|
|
// Determine whether to sign-extend the immediate operand
|
|
boolean extend = format < 0;
|
|
if (extend)
|
|
format = -format;
|
|
|
|
// Determine the size in bytes of the instruction
|
|
size = format < 4 ? 2 : 4;
|
|
if (size == 2)
|
|
this.bits &= 0xFFFF0000;
|
|
|
|
// Decode by format
|
|
switch (format) {
|
|
case 0: return; // Nothing to do
|
|
case 1: formatI ( ); break;
|
|
case 2: formatII (extend); break;
|
|
case 3: formatIII( ); break;
|
|
case 4: formatIV ( ); break;
|
|
case 5: formatV (extend); break;
|
|
case 6: formatVI ( ); break;
|
|
case 7: formatVII( ); break;
|
|
}
|
|
|
|
// Resolve final instruction ID by subopcode
|
|
if (id == FLOATENDO)
|
|
id = subopcode >= 16 ? VUE.ILLEGAL : LOOKUP_FLOATENDO[subopcode];
|
|
else if (id == BITSTRING)
|
|
id = imm >= 16 ? VUE.ILLEGAL : LOOKUP_BITSTRING[imm ];
|
|
}
|
|
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////////
|
|
// Private Methods //
|
|
///////////////////////////////////////////////////////////////////////////
|
|
|
|
// Decoder for Format I
|
|
private void formatI() {
|
|
reg2 = bits >> 21 & 31;
|
|
reg1 = bits >> 16 & 31;
|
|
}
|
|
|
|
// Decoder for Format II
|
|
private void formatII(boolean extend) {
|
|
reg2 = bits >> 21 & 31;
|
|
imm = extend ? bits << 11 >> 27 : bits >> 16 & 31;
|
|
}
|
|
|
|
// Decoder for Format III
|
|
private void formatIII() {
|
|
opcode = 0x20;
|
|
cond = bits >> 25 & 15;
|
|
disp = bits << 7 >> 25;
|
|
}
|
|
|
|
// Decoder for Format IV
|
|
private void formatIV() {
|
|
disp = bits << 6 >> 6;
|
|
}
|
|
|
|
// Decoder for Format V
|
|
private void formatV(boolean extend) {
|
|
reg2 = bits >> 21 & 31;
|
|
reg1 = bits >> 16 & 31;
|
|
imm = extend ? bits << 16 >> 16 : bits & 0x0000FFFF;
|
|
}
|
|
|
|
// Decoder for Format VI
|
|
private void formatVI() {
|
|
reg2 = bits >> 21 & 31;
|
|
reg1 = bits >> 16 & 31;
|
|
disp = bits << 16 >> 16;
|
|
}
|
|
|
|
// Decoder for Format VII
|
|
private void formatVII() {
|
|
reg2 = bits >> 21 & 31;
|
|
reg1 = bits >> 16 & 31;
|
|
subopcode = bits >> 10 & 63;
|
|
}
|
|
|
|
}
|