#ifndef MATRIX_H
#define MATRIX_H
#define reserved_ "illegal"
static const char mnemonics_PRIMARY[64][8] = {
"SPECIAL","REGIMM ","J ","JAL ","BEQ ","BNE ","BLEZ ","BGTZ ",
"ADDI ","ADDIU ","SLTI ","SLTIU ","ANDI ","ORI ","XORI ","LUI ",
"COP0 ",reserved_,"COP2 ",reserved_,reserved_,reserved_,reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,
"LB ","LH ",reserved_,"LW ","LBU ","LHU ",reserved_,reserved_,
"SB ","SH ",reserved_,"SW ",reserved_,reserved_,reserved_,reserved_,
reserved_,reserved_,"LWC2 ",reserved_,reserved_,reserved_,reserved_,reserved_,
reserved_,reserved_,"SWC2 ",reserved_,reserved_,reserved_,reserved_,reserved_
};
static const char mnemonics_SPECIAL[64][8] = {
"SLL ",reserved_,"SRL ","SRA ","SLLV ",reserved_,"SRLV ","SRAV ",
"JR ","JALR ",reserved_,reserved_,reserved_,"BREAK ",reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,
"ADD ","ADDU ","SUB ","SUBU ","AND ","OR ","XOR ","NOR ",
reserved_,reserved_,"SLT ","SLTU ",reserved_,reserved_,reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_
};
static const char mnemonics_REGIMM[32][8] = {
"BLTZ ","BGEZ ",reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,
"BLTZAL ","BGEZAL ",reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_
};
static const char mnemonics_COP0[32][8] = {
"MFC0 ",reserved_,reserved_,reserved_,"MTC0 ",reserved_,reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_
};
static const char mnemonics_COP2[32][8] = {
"MFC2 ",reserved_,"CFC2 ",reserved_,"MTC2 ",reserved_,"CTC2 ",reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,
"C2 ","C2 ","C2 ","C2 ","C2 ","C2 ","C2 ","C2 ",
"C2 ","C2 ","C2 ","C2 ","C2 ","C2 ","C2 ","C2 "
};
static const char mnemonics_LWC2[32][8] = {
"LBV ","LSV ","LLV ","LDV ","LQV ","LRV ","LPV ","LUV ",
"LHV ","LFV ",reserved_,"LTV ",reserved_,reserved_,reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_
};
static const char mnemonics_SWC2[32][8] = {
"SBV ","SSV ","SLV ","SDV ","SQV ","SRV ","SPV ","SUV ",
"SHV ","SFV ","SWV ","STV ",reserved_,reserved_,reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_
};
static const char mnemonics_C2[64][8] = {
"VMULF ","VMULU ",reserved_,reserved_,"VMUDL ","VMUDM ","VMUDN ","VMUDH ",
"VMACF ","VMACU ",reserved_,"VMACQ ","VMADL ","VMADM ","VMADN ","VMADH ",
"VADD ","VSUB ",reserved_,"VABS ","VADDC ","VSUBC ",reserved_,reserved_,
reserved_,reserved_,reserved_,reserved_,reserved_,"VSAW ",reserved_,reserved_,
"VLT ","VEQ ","VNE ","VGE ","VCL ","VCH ","VCR ","VMRG ",
"VAND ","VNAND ","VOR ","VNOR ","VXOR ","VNXOR ",reserved_,reserved_,
"VRCP ","VRCPL ","VRCPH ","VMOV ","VRSQ ","VRSQL ","VRSQH ","VNOP ",
reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_,reserved_
};
static const char tokens_CR_V[4][4] = {
"vco",
"vcc",
"vce", "vce"
};
static const char* computational_elements[16] = {
"",
"[]",
"[0q]", "[1q]",
"[0h]", "[1h]", "[2h]", "[3h]",
"[0]", "[1]", "[2]", "[3]", "[4]", "[5]", "[6]", "[7]"
};
void disassemble(char disasm[32], int IW)
{
register int ID;
unsigned short imm = (IW & 0x0000FFFF);
const signed int offset = -(IW & 0x00008000) | imm;
const unsigned int target = IW%0x04000000 << 2;
const int func = IW % 64;
const int sa = (IW >> 6) & 31;
const int rd = (IW & 0x0000FFFF) >> 11;
const int rt = (IW >> 16) & 31;
const int rs = (IW >> 21) & 31;
const int op = (IW >> 26) & 63;
if ((op & ~001) == 000)
ID = op + 1;
else if ((op & 075) == 020)
ID = (op & 002) ? 04 + ((IW & 0x02000000) ? 3 : 0) : 03;
else if ((op & 067) == 062)
ID = 05 + ((op & 010) ? 1 : 0);
else
ID = 00;
ID = (ID % 8) & 07;
switch (ID)
{
char opcode[8];
case 00:
strcpy(opcode, mnemonics_PRIMARY[op]);
if (op & 32)
sprintf(disasm, "%s $%u, %i($%u)", opcode, rt, offset, rs);
else if (op & 8)
if (op == 0xF)
sprintf(disasm, "%s $%u, 0x%04X", opcode, rt, imm);
else
sprintf(disasm, "%s $%u, $%u, 0x%04X", opcode, rt, rs, imm);
else if (op & 4)
if (op & 2)
sprintf(disasm, "%s $%u, %i", opcode, rs, offset);
else
sprintf(disasm, "%s $%u, $%u, %i", opcode, rs, rt, offset);
else if (op & 2)
sprintf(disasm, "%s 0x%07X", opcode, target);
else
sprintf(disasm, "%s:%08X", opcode, IW);
return;
case 01:
strcpy(opcode, mnemonics_SPECIAL[func]);
if (func & 040)
sprintf(disasm, "%s $%u, $%u, $%u", opcode, rd, rs, rt);
else if (func < 8)
if (func & 4)
sprintf(disasm, "%s $%u, $%u, $%u", opcode, rd, rt, rs);
else
sprintf(disasm, "%s $%u, $%u, %u", opcode, rd, rt, sa);
else if (func == 010)
sprintf(disasm, "%s $%u", opcode, rs);
else if (func == 011)
sprintf(disasm, "%s $%u, $%u", opcode, rd, rs);
else if (func == 015)
strcpy(disasm, opcode);
else
sprintf(disasm, "%s:%08X", opcode, IW);
return;
case 02:
strcpy(opcode, mnemonics_REGIMM[rt]);
if ((rt & 016) == 000)
sprintf(disasm, "%s $%u, %i", opcode, rs, offset);
else
sprintf(disasm, "%s:%08X", opcode, IW);
return;
case 03:
strcpy(opcode, mnemonics_COP0[rs]);
if ((rs & 033) != 000)
sprintf(disasm, "%s:%08X", opcode, IW);
else
sprintf(disasm, "%s $%u, $c%u", opcode, rt, rd & 0xF);
return;
case 04:
strcpy(opcode, mnemonics_COP2[rs]);
if (opcode[0] == 'M')
sprintf(disasm, "%s $%u, $v%u[0x%X]", opcode, rt, rd, sa >> 1);
else if (opcode[0] == 'C')
sprintf(disasm, "%s $%u, $%s", opcode, rt, tokens_CR_V[rd % 4]);
else
sprintf(disasm, "%s:%08X", opcode, IW);
return;
case 05:
strcpy(opcode, mnemonics_LWC2[rd]);
if (opcode[0] != 'L')
sprintf(disasm, "%s:%08X", opcode, IW);
else
sprintf(disasm, "%s $v%u[0x%X], %i($%u)", opcode, rt, sa >> 1,
-(IW & 0x00000040) | func, rs);
return;
case 06:
strcpy(opcode, mnemonics_SWC2[rd]);
if (opcode[0] != 'S')
sprintf(disasm, "%s:%08X", opcode, IW);
else
sprintf(disasm, "%s $v%u[0x%X], %i($%u)", opcode, rt, sa >> 1,
-(IW & 0x00000040) | func, rs);
return;
case 07:
strcpy(opcode, mnemonics_C2[func]);
if (opcode[0] != 'V')
sprintf(disasm, "%s:%08X", opcode, IW);
else if (func == 067)
strcpy(disasm, opcode);
else if (func >= 060)
sprintf(disasm, "%s $v%u[%u], $v%u[0x%X]", opcode, sa, rd & 07,
rt, rs & 0xF);
else
if (func == 035)
sprintf(disasm, "%s $v%u, $v%u, $v%u[%u]", opcode, sa, rd,
rt, rs & 07);
else
sprintf(disasm, "%s $v%u, $v%u, $v%u%s", opcode, sa, rd, rt,
computational_elements[rs & 0xF]);
return;
}
}
#endif