611 lines
26 KiB
C++
611 lines
26 KiB
C++
#include "RSPInstruction.h"
|
|
#include "../RSP Registers.h"
|
|
#include <Common/StdString.h>
|
|
|
|
RSPInstruction::RSPInstruction(uint32_t Address, uint32_t Instruction) :
|
|
m_Address(Address)
|
|
{
|
|
m_Name[0] = '\0';
|
|
m_Param[0] = '\0';
|
|
m_Instruction.Value = Instruction;
|
|
}
|
|
|
|
const char * RSPInstruction::Name()
|
|
{
|
|
if (m_Name[0] == '\0')
|
|
{
|
|
DecodeName();
|
|
}
|
|
return m_Name;
|
|
}
|
|
|
|
const char * RSPInstruction::Param()
|
|
{
|
|
if (m_Param[0] == '\0')
|
|
{
|
|
DecodeName();
|
|
}
|
|
return m_Param;
|
|
}
|
|
|
|
std::string RSPInstruction::NameAndParam()
|
|
{
|
|
return stdstr_f("%s %s", Name(), Param());
|
|
}
|
|
|
|
void RSPInstruction::DecodeName(void)
|
|
{
|
|
switch (m_Instruction.op)
|
|
{
|
|
case RSP_SPECIAL:
|
|
DecodeSpecialName();
|
|
break;
|
|
case RSP_REGIMM:
|
|
DecodeRegImmName();
|
|
break;
|
|
case RSP_J:
|
|
strcpy(m_Name, "J");
|
|
sprintf(m_Param, "0x%04X", (m_Instruction.target << 2) & 0x1FFC);
|
|
break;
|
|
case RSP_JAL:
|
|
strcpy(m_Name, "JAL");
|
|
sprintf(m_Param, "0x%04X", (m_Instruction.target << 2) & 0x1FFC);
|
|
break;
|
|
case RSP_BEQ:
|
|
if (m_Instruction.rs == 0 && m_Instruction.rt == 0)
|
|
{
|
|
strcpy(m_Name, "B");
|
|
sprintf(m_Param, "0x%08X", (m_Address + ((short)m_Instruction.offset << 2) + 4) & 0x1FFC);
|
|
}
|
|
else if (m_Instruction.rs == 0 || m_Instruction.rt == 0)
|
|
{
|
|
strcpy(m_Name, "BEQZ");
|
|
sprintf(m_Param, "%s, 0x%08X", GPR_Name(m_Instruction.rs == 0 ? m_Instruction.rt : m_Instruction.rs), (m_Address + ((short)m_Instruction.offset << 2) + 4) & 0x1FFC);
|
|
}
|
|
else
|
|
{
|
|
strcpy(m_Name, "BEQ");
|
|
sprintf(m_Param, "%s, %s, 0x%08X", GPR_Name(m_Instruction.rs), GPR_Name(m_Instruction.rt), (m_Address + ((short)m_Instruction.offset << 2) + 4) & 0x1FFC);
|
|
}
|
|
break;
|
|
case RSP_BNE:
|
|
if ((m_Instruction.rs == 0) ^ (m_Instruction.rt == 0))
|
|
{
|
|
strcpy(m_Name, "BNEZ");
|
|
sprintf(m_Param, "%s, 0x%08X", GPR_Name(m_Instruction.rs == 0 ? m_Instruction.rt : m_Instruction.rs), (m_Address + ((short)m_Instruction.offset << 2) + 4) & 0x1FFC);
|
|
}
|
|
else
|
|
{
|
|
strcpy(m_Name, "BNE");
|
|
sprintf(m_Param, "%s, %s, 0x%08X", GPR_Name(m_Instruction.rs), GPR_Name(m_Instruction.rt), (m_Address + ((short)m_Instruction.offset << 2) + 4) & 0x1FFC);
|
|
}
|
|
break;
|
|
case RSP_BLEZ:
|
|
strcpy(m_Name, "BLEZ");
|
|
sprintf(m_Param, "%s, 0x%08X", GPR_Name(m_Instruction.rs), (m_Address + ((short)m_Instruction.offset << 2) + 4) & 0x1FFC);
|
|
break;
|
|
case RSP_BGTZ:
|
|
strcpy(m_Name, "BGTZ");
|
|
sprintf(m_Param, "%s, 0x%08X", GPR_Name(m_Instruction.rs), (m_Address + ((short)m_Instruction.offset << 2) + 4) & 0x1FFC);
|
|
break;
|
|
case RSP_ADDI:
|
|
strcpy(m_Name, "ADDI");
|
|
sprintf(m_Param, "%s, %s, 0x%04X", GPR_Name(m_Instruction.rt), GPR_Name(m_Instruction.rs), m_Instruction.immediate);
|
|
break;
|
|
case RSP_ADDIU:
|
|
strcpy(m_Name, "ADDIU");
|
|
sprintf(m_Param, "%s, %s, 0x%04X", GPR_Name(m_Instruction.rt), GPR_Name(m_Instruction.rs), m_Instruction.immediate);
|
|
break;
|
|
case RSP_SLTI:
|
|
strcpy(m_Name, "SLTI");
|
|
sprintf(m_Param, "%s, %s, 0x%04X", GPR_Name(m_Instruction.rt), GPR_Name(m_Instruction.rs), m_Instruction.immediate);
|
|
break;
|
|
case RSP_SLTIU:
|
|
strcpy(m_Name, "SLTIU");
|
|
sprintf(m_Param, "%s, %s, 0x%04X", GPR_Name(m_Instruction.rt), GPR_Name(m_Instruction.rs), m_Instruction.immediate);
|
|
break;
|
|
case RSP_ANDI:
|
|
strcpy(m_Name, "ANDI");
|
|
sprintf(m_Param, "%s, %s, 0x%04X", GPR_Name(m_Instruction.rt), GPR_Name(m_Instruction.rs), m_Instruction.immediate);
|
|
break;
|
|
case RSP_ORI:
|
|
strcpy(m_Name, "ORI");
|
|
sprintf(m_Param, "%s, %s, 0x%04X", GPR_Name(m_Instruction.rt), GPR_Name(m_Instruction.rs), m_Instruction.immediate);
|
|
break;
|
|
case RSP_XORI:
|
|
strcpy(m_Name, "XORI");
|
|
sprintf(m_Param, "%s, %s, 0x%04X", GPR_Name(m_Instruction.rt), GPR_Name(m_Instruction.rs), m_Instruction.immediate);
|
|
break;
|
|
case RSP_LUI:
|
|
strcpy(m_Name, "LUI");
|
|
sprintf(m_Param, "%s, 0x%04X", GPR_Name(m_Instruction.rt), m_Instruction.immediate);
|
|
break;
|
|
case RSP_CP0:
|
|
DecodeCop0Name();
|
|
break;
|
|
case RSP_CP2:
|
|
DecodeCop2Name();
|
|
break;
|
|
case RSP_LB:
|
|
strcpy(m_Name, "LB");
|
|
sprintf(m_Param, "%s, 0x%04X (%s)", GPR_Name(m_Instruction.rt), m_Instruction.offset, GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LH:
|
|
strcpy(m_Name, "LH");
|
|
sprintf(m_Param, "%s, 0x%04X (%s)", GPR_Name(m_Instruction.rt), m_Instruction.offset, GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LW:
|
|
strcpy(m_Name, "LW");
|
|
sprintf(m_Param, "%s, 0x%04X (%s)", GPR_Name(m_Instruction.rt), m_Instruction.offset, GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LBU:
|
|
strcpy(m_Name, "LBU");
|
|
sprintf(m_Param, "%s, 0x%04X (%s)", GPR_Name(m_Instruction.rt), m_Instruction.offset, GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LHU:
|
|
strcpy(m_Name, "LHU");
|
|
sprintf(m_Param, "%s, 0x%04X (%s)", GPR_Name(m_Instruction.rt), m_Instruction.offset, GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LWU:
|
|
strcpy(m_Name, "LWU");
|
|
sprintf(m_Param, "%s, 0x%04X (%s)", GPR_Name(m_Instruction.rt), m_Instruction.offset, GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_SB:
|
|
strcpy(m_Name, "SB");
|
|
sprintf(m_Param, "%s, 0x%04X (%s)", GPR_Name(m_Instruction.rt), m_Instruction.offset, GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_SH:
|
|
strcpy(m_Name, "SH");
|
|
sprintf(m_Param, "%s, 0x%04X (%s)", GPR_Name(m_Instruction.rt), m_Instruction.offset, GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_SW:
|
|
strcpy(m_Name, "SW");
|
|
sprintf(m_Param, "%s, 0x%04X (%s)", GPR_Name(m_Instruction.rt), m_Instruction.offset, GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LC2:
|
|
DecodeLSC2Name('L');
|
|
break;
|
|
case RSP_SC2:
|
|
DecodeLSC2Name('S');
|
|
break;
|
|
default:
|
|
strcpy(m_Name, "UNKNOWN");
|
|
sprintf(m_Param, "0x%08X", m_Instruction.Value);
|
|
}
|
|
}
|
|
|
|
void RSPInstruction::DecodeSpecialName(void)
|
|
{
|
|
switch (m_Instruction.funct)
|
|
{
|
|
case RSP_SPECIAL_SLL:
|
|
if (m_Instruction.Value != 0)
|
|
{
|
|
strcpy(m_Name, "SLL");
|
|
sprintf(m_Param, "%s, %s, 0x%X", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rt), m_Instruction.sa);
|
|
}
|
|
else
|
|
{
|
|
strcpy(m_Name, "NOP");
|
|
}
|
|
break;
|
|
case RSP_SPECIAL_SRL:
|
|
strcpy(m_Name, "SRL");
|
|
sprintf(m_Param, "%s, %s, 0x%X", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rt), m_Instruction.sa);
|
|
break;
|
|
case RSP_SPECIAL_SRA:
|
|
strcpy(m_Name, "SRA");
|
|
sprintf(m_Param, "%s, %s, 0x%X", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rt), m_Instruction.sa);
|
|
break;
|
|
case RSP_SPECIAL_SLLV:
|
|
strcpy(m_Name, "SLLV");
|
|
sprintf(m_Param, "%s, %s, %s", GPR_Name(m_Instruction.rd),GPR_Name(m_Instruction.rt), GPR_Name(m_Instruction.rs));
|
|
break;
|
|
case RSP_SPECIAL_SRLV:
|
|
strcpy(m_Name, "SRLV");
|
|
sprintf(m_Param, "%s, %s, %s", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rt), GPR_Name(m_Instruction.rs));
|
|
break;
|
|
case RSP_SPECIAL_SRAV:
|
|
strcpy(m_Name, "SRAV");
|
|
sprintf(m_Param, "%s, %s, %s", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rt), GPR_Name(m_Instruction.rs));
|
|
break;
|
|
case RSP_SPECIAL_JR:
|
|
strcpy(m_Name, "JR");
|
|
sprintf(m_Param, "%s", GPR_Name(m_Instruction.rs));
|
|
break;
|
|
case RSP_SPECIAL_JALR:
|
|
strcpy(m_Name, "JALR");
|
|
sprintf(m_Param, "%s, %s", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rs));
|
|
break;
|
|
case RSP_SPECIAL_BREAK:
|
|
strcpy(m_Name, "BREAK");
|
|
break;
|
|
case RSP_SPECIAL_ADD:
|
|
strcpy(m_Name, "ADD");
|
|
sprintf(m_Param, "%s, %s, %s", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rs), GPR_Name(m_Instruction.rt));
|
|
break;
|
|
case RSP_SPECIAL_ADDU:
|
|
strcpy(m_Name, "ADDU");
|
|
sprintf(m_Param, "%s, %s, %s", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rs), GPR_Name(m_Instruction.rt));
|
|
break;
|
|
case RSP_SPECIAL_SUB:
|
|
strcpy(m_Name, "SUB");
|
|
sprintf(m_Param, "%s, %s, %s", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rs), GPR_Name(m_Instruction.rt));
|
|
break;
|
|
case RSP_SPECIAL_SUBU:
|
|
strcpy(m_Name, "SUBU");
|
|
sprintf(m_Param, "%s, %s, %s", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rs), GPR_Name(m_Instruction.rt));
|
|
break;
|
|
case RSP_SPECIAL_AND:
|
|
strcpy(m_Name, "AND");
|
|
sprintf(m_Param, "%s, %s, %s", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rs), GPR_Name(m_Instruction.rt));
|
|
break;
|
|
case RSP_SPECIAL_OR:
|
|
strcpy(m_Name, "OR");
|
|
sprintf(m_Param, "%s, %s, %s", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rs), GPR_Name(m_Instruction.rt));
|
|
break;
|
|
case RSP_SPECIAL_XOR:
|
|
strcpy(m_Name, "XOR");
|
|
sprintf(m_Param, "%s, %s, %s", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rs), GPR_Name(m_Instruction.rt));
|
|
break;
|
|
case RSP_SPECIAL_NOR:
|
|
strcpy(m_Name, "NOR");
|
|
sprintf(m_Param, "%s, %s, %s", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rs), GPR_Name(m_Instruction.rt));
|
|
break;
|
|
case RSP_SPECIAL_SLT:
|
|
strcpy(m_Name, "SLT");
|
|
sprintf(m_Param, "%s, %s, %s", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rs), GPR_Name(m_Instruction.rt));
|
|
break;
|
|
case RSP_SPECIAL_SLTU:
|
|
strcpy(m_Name, "SLTU");
|
|
sprintf(m_Param, "%s, %s, %s", GPR_Name(m_Instruction.rd), GPR_Name(m_Instruction.rs), GPR_Name(m_Instruction.rt));
|
|
break;
|
|
default:
|
|
strcpy(m_Name, "UNKNOWN");
|
|
sprintf(m_Param, "0x%08X", m_Instruction.Value);
|
|
}
|
|
}
|
|
|
|
void RSPInstruction::DecodeRegImmName(void)
|
|
{
|
|
switch (m_Instruction.rt)
|
|
{
|
|
case RSP_REGIMM_BLTZ:
|
|
strcpy(m_Name, "BLTZ");
|
|
sprintf(m_Param, "%s, 0x%04X", GPR_Name(m_Instruction.rs), (m_Address + ((short)m_Instruction.offset << 2) + 4) & 0x1FFC);
|
|
break;
|
|
case RSP_REGIMM_BGEZ:
|
|
if (m_Instruction.rs == 0)
|
|
{
|
|
strcpy(m_Name, "B");
|
|
sprintf(m_Param, "0x%04X", (m_Address + ((short)m_Instruction.offset << 2) + 4) & 0x1FFC);
|
|
}
|
|
else
|
|
{
|
|
strcpy(m_Name, "BGEZ");
|
|
sprintf(m_Param, "%s, 0x%04X", GPR_Name(m_Instruction.rs), (m_Address + ((short)m_Instruction.offset << 2) + 4) & 0x1FFC);
|
|
}
|
|
break;
|
|
case RSP_REGIMM_BLTZAL:
|
|
strcpy(m_Name, "BLTZAL");
|
|
sprintf(m_Param, "%s, 0x%04X", GPR_Name(m_Instruction.rs), (m_Address + ((short)m_Instruction.offset << 2) + 4) & 0x1FFC);
|
|
break;
|
|
case RSP_REGIMM_BGEZAL:
|
|
if (m_Instruction.rs == 0)
|
|
{
|
|
strcpy(m_Name, "BAL");
|
|
sprintf(m_Param, "0x%04X", (m_Address + ((short)m_Instruction.offset << 2) + 4) & 0x1FFC);
|
|
}
|
|
else
|
|
{
|
|
strcpy(m_Name, "BGEZAL");
|
|
sprintf(m_Param, "%s, 0x%04X", GPR_Name(m_Instruction.rs), (m_Address + ((short)m_Instruction.offset << 2) + 4) & 0x1FFC);
|
|
}
|
|
break;
|
|
default:
|
|
strcpy(m_Name, "UNKNOWN");
|
|
sprintf(m_Param, "0x%08X", m_Instruction.Value);
|
|
}
|
|
}
|
|
|
|
void RSPInstruction::DecodeCop0Name(void)
|
|
{
|
|
switch (m_Instruction.rs)
|
|
{
|
|
case RSP_COP0_MF:
|
|
strcpy(m_Name, "MFC0");
|
|
sprintf(m_Param, "%s, %s", GPR_Name(m_Instruction.rt), COP0_Name(m_Instruction.rd));
|
|
break;
|
|
case RSP_COP0_MT:
|
|
strcpy(m_Name, "MTC0");
|
|
sprintf(m_Param, "%s, %s", GPR_Name(m_Instruction.rt), COP0_Name(m_Instruction.rd));
|
|
break;
|
|
default:
|
|
strcpy(m_Name, "UNKNOWN");
|
|
sprintf(m_Param, "0x%08X", m_Instruction.Value);
|
|
}
|
|
}
|
|
|
|
void RSPInstruction::DecodeCop2Name(void)
|
|
{
|
|
if ((m_Instruction.rs & 0x10) == 0)
|
|
{
|
|
switch (m_Instruction.rs)
|
|
{
|
|
case RSP_COP2_MF:
|
|
strcpy(m_Name, "MFC2");
|
|
sprintf(m_Param, "%s, $v%d[%d]", GPR_Name(m_Instruction.rt), m_Instruction.rd, m_Instruction.sa >> 1);
|
|
break;
|
|
case RSP_COP2_CF:
|
|
strcpy(m_Name, "CFC2");
|
|
sprintf(m_Param, "%s, %d", GPR_Name(m_Instruction.rt), m_Instruction.rd % 4);
|
|
break;
|
|
case RSP_COP2_MT:
|
|
strcpy(m_Name, "MTC2");
|
|
sprintf(m_Param, "%s, $v%d[%d]", GPR_Name(m_Instruction.rt), m_Instruction.rd, m_Instruction.sa >> 1);
|
|
break;
|
|
case RSP_COP2_CT:
|
|
strcpy(m_Name, "CTC2");
|
|
sprintf(m_Param, "%s, %d", GPR_Name(m_Instruction.rt), m_Instruction.rd % 4);
|
|
break;
|
|
default:
|
|
strcpy(m_Name, "UNKNOWN");
|
|
sprintf(m_Param, "0x%08X", m_Instruction.Value);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (m_Instruction.funct)
|
|
{
|
|
case RSP_VECTOR_VMULF:
|
|
strcpy(m_Name, "VMULF");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VMULU:
|
|
strcpy(m_Name, "VMULU");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VMUDL:
|
|
strcpy(m_Name, "VMUDL");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VMUDM:
|
|
strcpy(m_Name, "VMUDM");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VMUDN:
|
|
strcpy(m_Name, "VMUDN");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VMUDH:
|
|
strcpy(m_Name, "VMUDH");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VMACF:
|
|
strcpy(m_Name, "VMACF");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VMACU:
|
|
strcpy(m_Name, "VMACU");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VMACQ:
|
|
strcpy(m_Name, "VMACQ");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VMADL:
|
|
strcpy(m_Name, "VMADL");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VMADM:
|
|
strcpy(m_Name, "VMADM");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VMADN:
|
|
strcpy(m_Name, "VMADN");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VMADH:
|
|
strcpy(m_Name, "VMADH");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VADD:
|
|
strcpy(m_Name, "VADD");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VSUB:
|
|
strcpy(m_Name, "VSUB");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VABS:
|
|
strcpy(m_Name, "VABS");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VADDC:
|
|
strcpy(m_Name, "VADDC");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VSUBC:
|
|
strcpy(m_Name, "VSUBC");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VSAW:
|
|
strcpy(m_Name, "VSAW");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VLT:
|
|
strcpy(m_Name, "VLT");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VEQ:
|
|
strcpy(m_Name, "VEQ");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VNE:
|
|
strcpy(m_Name, "VNE");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VGE:
|
|
strcpy(m_Name, "VGE");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VCL:
|
|
strcpy(m_Name, "VCL");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VCH:
|
|
strcpy(m_Name, "VCH");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VCR:
|
|
strcpy(m_Name, "VCR");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VMRG:
|
|
strcpy(m_Name, "VMRG");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VAND:
|
|
strcpy(m_Name, "VAND");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VNAND:
|
|
strcpy(m_Name, "VNAND");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VOR:
|
|
strcpy(m_Name, "VOR");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VNOR:
|
|
strcpy(m_Name, "VNOR");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VXOR:
|
|
strcpy(m_Name, "VXOR");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VNXOR:
|
|
strcpy(m_Name, "VNXOR");
|
|
sprintf(m_Param, "$v%d, $v%d, $v%d%s", m_Instruction.vd, m_Instruction.vs, m_Instruction.vt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VRCP:
|
|
strcpy(m_Name, "VRCP");
|
|
sprintf(m_Param, "$v%d[%d], $v%d%s", m_Instruction.sa, m_Instruction.rd & 0x7, m_Instruction.rt, ElementSpecifier(m_Instruction.e));
|
|
case RSP_VECTOR_VRCPL:
|
|
strcpy(m_Name, "VRCPL");
|
|
sprintf(m_Param, "$v%d[%d], $v%d%s", m_Instruction.sa, m_Instruction.rd & 0x7, m_Instruction.rt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VRCPH:
|
|
strcpy(m_Name, "VRCPH");
|
|
sprintf(m_Param, "$v%d[%d], $v%d%s", m_Instruction.sa, m_Instruction.rd & 0x7, m_Instruction.rt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VMOV:
|
|
strcpy(m_Name, "VMOV");
|
|
sprintf(m_Param, "$v%d[%d], $v%d[%d]", m_Instruction.vd, m_Instruction.de & 0x7, m_Instruction.rt, m_Instruction.de & 0x7);
|
|
break;
|
|
case RSP_VECTOR_VRSQ:
|
|
strcpy(m_Name, "VRSQ");
|
|
sprintf(m_Param, "$v%d[%d], $v%d%s", m_Instruction.sa, m_Instruction.rd & 0x7, m_Instruction.rt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VRSQL:
|
|
strcpy(m_Name, "VRSQL");
|
|
sprintf(m_Param, "$v%d[%d], $v%d%s", m_Instruction.sa, m_Instruction.rd & 0x7, m_Instruction.rt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VRSQH:
|
|
strcpy(m_Name, "VRSQH");
|
|
sprintf(m_Param, "$v%d[%d], $v%d%s", m_Instruction.sa, m_Instruction.rd & 0x7, m_Instruction.rt, ElementSpecifier(m_Instruction.e));
|
|
break;
|
|
case RSP_VECTOR_VNOP:
|
|
strcpy(m_Name, "VNOP");
|
|
strcpy(m_Param, "");
|
|
break;
|
|
default:
|
|
strcpy(m_Name, "UNKNOWN");
|
|
sprintf(m_Param, "0x%08X", m_Instruction.Value);
|
|
}
|
|
}
|
|
}
|
|
|
|
void RSPInstruction::DecodeLSC2Name(const char LoadStoreIdent)
|
|
{
|
|
switch (m_Instruction.rd)
|
|
{
|
|
case RSP_LSC2_BV:
|
|
sprintf(m_Name, "%cBV", LoadStoreIdent);
|
|
sprintf(m_Param, "$v%d[%d], %s0x%03X(%s)", m_Instruction.rt, m_Instruction.del, (m_Instruction.voffset < 0) ? "-" : "", abs(m_Instruction.voffset << 0), GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LSC2_SV:
|
|
sprintf(m_Name, "%cSV", LoadStoreIdent);
|
|
sprintf(m_Param, "$v%d[%d], %s0x%03X(%s)", m_Instruction.rt, m_Instruction.del, (m_Instruction.voffset < 0) ? "-" : "", abs(m_Instruction.voffset << 1), GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LSC2_LV:
|
|
sprintf(m_Name, "%cLV", LoadStoreIdent);
|
|
sprintf(m_Param, "$v%d[%d], %s0x%03X(%s)", m_Instruction.rt, m_Instruction.del, (m_Instruction.voffset < 0) ? "-" : "", abs(m_Instruction.voffset << 2), GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LSC2_DV:
|
|
sprintf(m_Name, "%cDV", LoadStoreIdent);
|
|
sprintf(m_Param, "$v%d[%d], %s0x%03X(%s)", m_Instruction.rt, m_Instruction.del, (m_Instruction.voffset < 0) ? "-" : "", abs(m_Instruction.voffset << 3), GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LSC2_QV:
|
|
sprintf(m_Name, "%cQV", LoadStoreIdent);
|
|
sprintf(m_Param, "$v%d[%d], %s0x%03X(%s)", m_Instruction.rt, m_Instruction.del, (m_Instruction.voffset < 0) ? "-" : "", abs(m_Instruction.voffset << 4), GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LSC2_RV:
|
|
sprintf(m_Name, "%cRV", LoadStoreIdent);
|
|
sprintf(m_Param, "$v%d[%d], %s0x%03X(%s)", m_Instruction.rt, m_Instruction.del, (m_Instruction.voffset < 0) ? "-" : "", abs(m_Instruction.voffset << 4), GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LSC2_PV:
|
|
sprintf(m_Name, "%cPV", LoadStoreIdent);
|
|
sprintf(m_Param, "$v%d[%d], %s0x%03X(%s)", m_Instruction.rt, m_Instruction.del, (m_Instruction.voffset < 0) ? "-" : "", abs(m_Instruction.voffset << 3), GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LSC2_UV:
|
|
sprintf(m_Name, "%cUV", LoadStoreIdent);
|
|
sprintf(m_Param, "$v%d[%d], %s0x%03X(%s)", m_Instruction.rt, m_Instruction.del, (m_Instruction.voffset < 0) ? "-" : "", abs(m_Instruction.voffset << 3), GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LSC2_HV:
|
|
sprintf(m_Name, "%cHV", LoadStoreIdent);
|
|
sprintf(m_Param, "$v%d[%d], %s0x%03X(%s)", m_Instruction.rt, m_Instruction.del, (m_Instruction.voffset < 0) ? "-" : "", abs(m_Instruction.voffset << 4), GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LSC2_FV:
|
|
sprintf(m_Name, "%cFV", LoadStoreIdent);
|
|
sprintf(m_Param, "$v%d[%d], %s0x%03X(%s)", m_Instruction.rt, m_Instruction.del, (m_Instruction.voffset < 0) ? "-" : "", abs(m_Instruction.voffset << 4), GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LSC2_WV:
|
|
sprintf(m_Name, "%cWV", LoadStoreIdent);
|
|
sprintf(m_Param, "$v%d[%d], %s0x%03X(%s)", m_Instruction.rt, m_Instruction.del, (m_Instruction.voffset < 0) ? "-" : "", abs(m_Instruction.voffset << 4), GPR_Name(m_Instruction.base));
|
|
break;
|
|
case RSP_LSC2_TV:
|
|
sprintf(m_Name, "%cTV", LoadStoreIdent);
|
|
sprintf(m_Param, "$v%d[%d], %s0x%03X(%s)", m_Instruction.rt, m_Instruction.del, (m_Instruction.voffset < 0) ? "-" : "", abs(m_Instruction.voffset << 4), GPR_Name(m_Instruction.base));
|
|
break;
|
|
default:
|
|
strcpy(m_Name, "UNKNOWN");
|
|
sprintf(m_Param, "0x%08X", m_Instruction.Value);
|
|
}
|
|
}
|
|
|
|
const char * RSPInstruction::ElementSpecifier(uint32_t Element)
|
|
{
|
|
switch (Element)
|
|
{
|
|
case 0: return "";
|
|
case 1: return "";
|
|
case 2: return " [0q]";
|
|
case 3: return " [1q]";
|
|
case 4: return " [0h]";
|
|
case 5: return " [1h]";
|
|
case 6: return " [2h]";
|
|
case 7: return " [3h]";
|
|
case 8: return " [0]";
|
|
case 9: return " [1]";
|
|
case 10: return " [2]";
|
|
case 11: return " [3]";
|
|
case 12: return " [4]";
|
|
case 13: return " [5]";
|
|
case 14: return " [6]";
|
|
case 15: return " [7]";
|
|
}
|
|
return "Unknown Element";
|
|
}
|