CPU: Refactoring, implement LWC/SWC
This commit is contained in:
parent
2875a22987
commit
948ac50020
|
@ -283,6 +283,117 @@ void Core::WriteRegDelayed(Reg rd, u32 value)
|
||||||
m_regs.r[static_cast<u8>(rd)] = value;
|
m_regs.r[static_cast<u8>(rd)] = value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 Core::ReadCop0Reg(Cop0Reg reg)
|
||||||
|
{
|
||||||
|
switch (reg)
|
||||||
|
{
|
||||||
|
case Cop0Reg::BPC:
|
||||||
|
return m_cop0_regs.BPC;
|
||||||
|
|
||||||
|
case Cop0Reg::BPCM:
|
||||||
|
return m_cop0_regs.BPCM;
|
||||||
|
|
||||||
|
case Cop0Reg::BDA:
|
||||||
|
return m_cop0_regs.BDA;
|
||||||
|
|
||||||
|
case Cop0Reg::BDAM:
|
||||||
|
return m_cop0_regs.BDAM;
|
||||||
|
|
||||||
|
case Cop0Reg::DCIC:
|
||||||
|
return m_cop0_regs.dcic.bits;
|
||||||
|
|
||||||
|
case Cop0Reg::JUMPDEST:
|
||||||
|
return m_cop0_regs.JUMPDEST;
|
||||||
|
|
||||||
|
case Cop0Reg::BadVaddr:
|
||||||
|
return m_cop0_regs.BadVaddr;
|
||||||
|
|
||||||
|
case Cop0Reg::SR:
|
||||||
|
return m_cop0_regs.sr.bits;
|
||||||
|
|
||||||
|
case Cop0Reg::CAUSE:
|
||||||
|
return m_cop0_regs.cause.bits;
|
||||||
|
|
||||||
|
case Cop0Reg::EPC:
|
||||||
|
return m_cop0_regs.EPC;
|
||||||
|
|
||||||
|
case Cop0Reg::PRID:
|
||||||
|
return m_cop0_regs.PRID;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Panic("Unknown COP0 reg");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Core::WriteCop0Reg(Cop0Reg reg, u32 value)
|
||||||
|
{
|
||||||
|
switch (reg)
|
||||||
|
{
|
||||||
|
case Cop0Reg::BPC:
|
||||||
|
{
|
||||||
|
m_cop0_regs.BPC = value;
|
||||||
|
Log_WarningPrintf("COP0 BPC <- %08X", value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Cop0Reg::BPCM:
|
||||||
|
{
|
||||||
|
m_cop0_regs.BPCM = value;
|
||||||
|
Log_WarningPrintf("COP0 BPCM <- %08X", value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Cop0Reg::BDA:
|
||||||
|
{
|
||||||
|
m_cop0_regs.BDA = value;
|
||||||
|
Log_WarningPrintf("COP0 BDA <- %08X", value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Cop0Reg::BDAM:
|
||||||
|
{
|
||||||
|
m_cop0_regs.BDAM = value;
|
||||||
|
Log_WarningPrintf("COP0 BDAM <- %08X", value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Cop0Reg::JUMPDEST:
|
||||||
|
{
|
||||||
|
Log_WarningPrintf("Ignoring write to Cop0 JUMPDEST");
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Cop0Reg::DCIC:
|
||||||
|
{
|
||||||
|
m_cop0_regs.dcic.bits =
|
||||||
|
(m_cop0_regs.dcic.bits & ~Cop0Registers::DCIC::WRITE_MASK) | (value & Cop0Registers::DCIC::WRITE_MASK);
|
||||||
|
Log_WarningPrintf("COP0 DCIC <- %08X (now %08X)", value, m_cop0_regs.dcic.bits);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Cop0Reg::SR:
|
||||||
|
{
|
||||||
|
m_cop0_regs.sr.bits =
|
||||||
|
(m_cop0_regs.sr.bits & ~Cop0Registers::SR::WRITE_MASK) | (value & Cop0Registers::SR::WRITE_MASK);
|
||||||
|
Log_WarningPrintf("COP0 SR <- %08X (now %08X)", value, m_cop0_regs.sr.bits);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case Cop0Reg::CAUSE:
|
||||||
|
{
|
||||||
|
m_cop0_regs.cause.bits =
|
||||||
|
(m_cop0_regs.cause.bits & ~Cop0Registers::CAUSE::WRITE_MASK) | (value & Cop0Registers::CAUSE::WRITE_MASK);
|
||||||
|
Log_WarningPrintf("COP0 CAUSE <- %08X (now %08X)", value, m_cop0_regs.cause.bits);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
Panic("Unknown COP0 reg");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Core::WriteCacheControl(u32 value)
|
void Core::WriteCacheControl(u32 value)
|
||||||
{
|
{
|
||||||
Log_WarningPrintf("Cache control <- 0x%08X", value);
|
Log_WarningPrintf("Cache control <- 0x%08X", value);
|
||||||
|
@ -895,7 +1006,7 @@ void Core::ExecuteInstruction(Instruction inst)
|
||||||
|
|
||||||
case InstructionOp::cop0:
|
case InstructionOp::cop0:
|
||||||
{
|
{
|
||||||
if (!m_cop0_regs.sr.CU0 && InUserMode())
|
if (InUserMode() && !m_cop0_regs.sr.CU0)
|
||||||
{
|
{
|
||||||
Log_WarningPrintf("Coprocessor 0 not present in user mode");
|
Log_WarningPrintf("Coprocessor 0 not present in user mode");
|
||||||
RaiseException(Exception::CpU, 0);
|
RaiseException(Exception::CpU, 0);
|
||||||
|
@ -908,7 +1019,7 @@ void Core::ExecuteInstruction(Instruction inst)
|
||||||
|
|
||||||
case InstructionOp::cop2:
|
case InstructionOp::cop2:
|
||||||
{
|
{
|
||||||
if (!m_cop0_regs.sr.CU0 && InUserMode())
|
if (InUserMode() && !m_cop0_regs.sr.CU2)
|
||||||
{
|
{
|
||||||
Log_WarningPrintf("Coprocessor 2 not present in user mode");
|
Log_WarningPrintf("Coprocessor 2 not present in user mode");
|
||||||
RaiseException(Exception::CpU, 2);
|
RaiseException(Exception::CpU, 2);
|
||||||
|
@ -919,9 +1030,46 @@ void Core::ExecuteInstruction(Instruction inst)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case InstructionOp::lwc2:
|
||||||
|
{
|
||||||
|
if (InUserMode() && !m_cop0_regs.sr.CU2)
|
||||||
|
{
|
||||||
|
Log_WarningPrintf("Coprocessor 2 not present in user mode");
|
||||||
|
RaiseException(Exception::CpU, 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VirtualMemoryAddress addr = ReadReg(inst.i.rs) + inst.i.imm_sext32();
|
||||||
|
u32 value;
|
||||||
|
if (!ReadMemoryWord(addr, &value))
|
||||||
|
return;
|
||||||
|
|
||||||
|
m_cop2.WriteDataRegister(ZeroExtend32(static_cast<u8>(inst.i.rt.GetValue())), value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case InstructionOp::swc2:
|
||||||
|
{
|
||||||
|
if (InUserMode() && !m_cop0_regs.sr.CU2)
|
||||||
|
{
|
||||||
|
Log_WarningPrintf("Coprocessor 2 not present in user mode");
|
||||||
|
RaiseException(Exception::CpU, 2);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const VirtualMemoryAddress addr = ReadReg(inst.i.rs) + inst.i.imm_sext32();
|
||||||
|
const u32 value = m_cop2.ReadDataRegister(ZeroExtend32(static_cast<u8>(inst.i.rt.GetValue())));
|
||||||
|
WriteMemoryWord(addr, value);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
// COP1/COP3 are not present
|
// COP1/COP3 are not present
|
||||||
case InstructionOp::cop1:
|
case InstructionOp::cop1:
|
||||||
case InstructionOp::cop3:
|
case InstructionOp::cop3:
|
||||||
|
case InstructionOp::lwc1:
|
||||||
|
case InstructionOp::swc1:
|
||||||
|
case InstructionOp::lwc3:
|
||||||
|
case InstructionOp::swc3:
|
||||||
{
|
{
|
||||||
RaiseException(Exception::CpU, inst.cop.cop_n);
|
RaiseException(Exception::CpU, inst.cop.cop_n);
|
||||||
}
|
}
|
||||||
|
@ -935,137 +1083,27 @@ void Core::ExecuteInstruction(Instruction inst)
|
||||||
|
|
||||||
void Core::ExecuteCop0Instruction(Instruction inst)
|
void Core::ExecuteCop0Instruction(Instruction inst)
|
||||||
{
|
{
|
||||||
switch (inst.cop.cop0_op())
|
if (inst.cop.IsCommonInstruction())
|
||||||
{
|
{
|
||||||
case Cop0Instruction::mtc0:
|
switch (inst.cop.CommonOp())
|
||||||
{
|
{
|
||||||
const u32 value = ReadReg(inst.r.rt);
|
case CopCommonInstruction::mfcn:
|
||||||
switch (static_cast<Cop0Reg>(inst.r.rd.GetValue()))
|
WriteRegDelayed(inst.r.rt, ReadCop0Reg(static_cast<Cop0Reg>(inst.r.rd.GetValue())));
|
||||||
{
|
|
||||||
case Cop0Reg::BPC:
|
|
||||||
{
|
|
||||||
m_cop0_regs.BPC = value;
|
|
||||||
Log_WarningPrintf("COP0 BPC <- %08X", value);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Cop0Reg::BPCM:
|
case CopCommonInstruction::mtcn:
|
||||||
{
|
WriteCop0Reg(static_cast<Cop0Reg>(inst.r.rd.GetValue()), ReadReg(inst.r.rt));
|
||||||
m_cop0_regs.BPCM = value;
|
|
||||||
Log_WarningPrintf("COP0 BPCM <- %08X", value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::BDA:
|
|
||||||
{
|
|
||||||
m_cop0_regs.BDA = value;
|
|
||||||
Log_WarningPrintf("COP0 BDA <- %08X", value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::BDAM:
|
|
||||||
{
|
|
||||||
m_cop0_regs.BDAM = value;
|
|
||||||
Log_WarningPrintf("COP0 BDAM <- %08X", value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::JUMPDEST:
|
|
||||||
{
|
|
||||||
Log_WarningPrintf("Ignoring write to Cop0 JUMPDEST");
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::DCIC:
|
|
||||||
{
|
|
||||||
m_cop0_regs.dcic.bits =
|
|
||||||
(m_cop0_regs.dcic.bits & ~Cop0Registers::DCIC::WRITE_MASK) | (value & Cop0Registers::DCIC::WRITE_MASK);
|
|
||||||
Log_WarningPrintf("COP0 DCIC <- %08X (now %08X)", value, m_cop0_regs.dcic.bits);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::SR:
|
|
||||||
{
|
|
||||||
m_cop0_regs.sr.bits =
|
|
||||||
(m_cop0_regs.sr.bits & ~Cop0Registers::SR::WRITE_MASK) | (value & Cop0Registers::SR::WRITE_MASK);
|
|
||||||
Log_WarningPrintf("COP0 SR <- %08X (now %08X)", value, m_cop0_regs.sr.bits);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::CAUSE:
|
|
||||||
{
|
|
||||||
m_cop0_regs.cause.bits =
|
|
||||||
(m_cop0_regs.cause.bits & ~Cop0Registers::CAUSE::WRITE_MASK) | (value & Cop0Registers::CAUSE::WRITE_MASK);
|
|
||||||
Log_WarningPrintf("COP0 CAUSE <- %08X (now %08X)", value, m_cop0_regs.cause.bits);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Panic("Unknown COP0 reg");
|
Panic("Missing implementation");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
else
|
||||||
|
|
||||||
case Cop0Instruction::mfc0:
|
|
||||||
{
|
{
|
||||||
u32 value;
|
switch (inst.cop.Cop0Op())
|
||||||
switch (static_cast<Cop0Reg>(inst.r.rd.GetValue()))
|
|
||||||
{
|
{
|
||||||
case Cop0Reg::BPC:
|
|
||||||
value = m_cop0_regs.BPC;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::BPCM:
|
|
||||||
value = m_cop0_regs.BPCM;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::BDA:
|
|
||||||
value = m_cop0_regs.BDA;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::BDAM:
|
|
||||||
value = m_cop0_regs.BDAM;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::DCIC:
|
|
||||||
value = m_cop0_regs.dcic.bits;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::JUMPDEST:
|
|
||||||
value = m_cop0_regs.JUMPDEST;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::BadVaddr:
|
|
||||||
value = m_cop0_regs.BadVaddr;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::SR:
|
|
||||||
value = m_cop0_regs.sr.bits;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::CAUSE:
|
|
||||||
value = m_cop0_regs.cause.bits;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::EPC:
|
|
||||||
value = m_cop0_regs.EPC;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Reg::PRID:
|
|
||||||
value = m_cop0_regs.PRID;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
Panic("Unknown COP0 reg");
|
|
||||||
value = 0;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
WriteRegDelayed(inst.r.rt, value);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case Cop0Instruction::rfe:
|
case Cop0Instruction::rfe:
|
||||||
{
|
{
|
||||||
// restore mode
|
// restore mode
|
||||||
|
@ -1074,30 +1112,36 @@ void Core::ExecuteCop0Instruction(Instruction inst)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Panic("Unhandled instruction");
|
Panic("Missing implementation");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void Core::ExecuteCop2Instruction(Instruction inst)
|
void Core::ExecuteCop2Instruction(Instruction inst)
|
||||||
{
|
{
|
||||||
if (inst.cop.IsCommonInstruction())
|
if (inst.cop.IsCommonInstruction())
|
||||||
{
|
{
|
||||||
// TODO: Combine with cop0.
|
// TODO: Combine with cop0.
|
||||||
switch (inst.cop.cop2_op())
|
switch (inst.cop.CommonOp())
|
||||||
{
|
{
|
||||||
case Cop2Instruction::mfc2:
|
case CopCommonInstruction::cfcn:
|
||||||
case Cop2Instruction::cfc2:
|
WriteRegDelayed(inst.r.rt, m_cop2.ReadControlRegister(static_cast<u32>(inst.r.rd.GetValue())));
|
||||||
case Cop2Instruction::mtc2:
|
|
||||||
case Cop2Instruction::ctc2:
|
|
||||||
{
|
|
||||||
const u32 index = static_cast<u32>(inst.r.rd.GetValue());
|
|
||||||
const u32 value = ReadReg(inst.r.rt);
|
|
||||||
m_cop2.WriteControlRegister(index, value);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Cop2Instruction::bc2c:
|
case CopCommonInstruction::ctcn:
|
||||||
|
m_cop2.WriteControlRegister(static_cast<u32>(inst.r.rd.GetValue()), ReadReg(inst.r.rt));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CopCommonInstruction::mfcn:
|
||||||
|
WriteRegDelayed(inst.r.rt, m_cop2.ReadDataRegister(static_cast<u32>(inst.r.rd.GetValue())));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CopCommonInstruction::mtcn:
|
||||||
|
m_cop2.WriteDataRegister(static_cast<u32>(inst.r.rd.GetValue()), ReadReg(inst.r.rt));
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CopCommonInstruction::bcnc:
|
||||||
default:
|
default:
|
||||||
Panic("Missing implementation");
|
Panic("Missing implementation");
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -103,6 +103,10 @@ private:
|
||||||
// write to cache control register
|
// write to cache control register
|
||||||
void WriteCacheControl(u32 value);
|
void WriteCacheControl(u32 value);
|
||||||
|
|
||||||
|
// read/write cop0 regs
|
||||||
|
u32 ReadCop0Reg(Cop0Reg reg);
|
||||||
|
void WriteCop0Reg(Cop0Reg reg, u32 value);
|
||||||
|
|
||||||
Bus* m_bus = nullptr;
|
Bus* m_bus = nullptr;
|
||||||
|
|
||||||
// ticks the CPU has executed
|
// ticks the CPU has executed
|
||||||
|
|
|
@ -160,20 +160,14 @@ static const std::array<const char*, 64> s_special_table = {{
|
||||||
"UNKNOWN" // 63
|
"UNKNOWN" // 63
|
||||||
}};
|
}};
|
||||||
|
|
||||||
static const std::array<std::pair<Cop0Instruction, const char*>, 6> s_cop0_table = {
|
static const std::array<std::pair<CopCommonInstruction, const char*>, 5> s_cop_common_table = {
|
||||||
{{Cop0Instruction::mfc0, "mfc0 $rt, $coprd"},
|
{{CopCommonInstruction::mfcn, "mfc$cop $rt, $coprd"},
|
||||||
{Cop0Instruction::cfc0, "cfc0 $rt, $copcr"},
|
{CopCommonInstruction::cfcn, "cfc$cop $rt, $copcr"},
|
||||||
{Cop0Instruction::mtc0, "mtc0 $rt, $coprd"},
|
{CopCommonInstruction::mtcn, "mtc$cop $rt, $coprd"},
|
||||||
{Cop0Instruction::ctc0, "ctc0 $rt, $copcr"},
|
{CopCommonInstruction::ctcn, "ctc$cop $rt, $copcr"},
|
||||||
{Cop0Instruction::bc0c, "bc0$copcc $rel"},
|
{CopCommonInstruction::bcnc, "bc$cop$copcc $rel"}}};
|
||||||
{Cop0Instruction::rfe, "rfe"}}};
|
|
||||||
|
|
||||||
static const std::array<std::pair<Cop2Instruction, const char*>, 6> s_cop2_common_table = {
|
static const std::array<std::pair<Cop0Instruction, const char*>, 1> s_cop0_table = {{{Cop0Instruction::rfe, "rfe"}}};
|
||||||
{{Cop2Instruction::mfc2, "mfc2 $rt, $coprd"},
|
|
||||||
{Cop2Instruction::cfc2, "cfc2 $rt, $copcr"},
|
|
||||||
{Cop2Instruction::mtc2, "mtc2 $rt, $coprd"},
|
|
||||||
{Cop2Instruction::ctc2, "ctc2 $rt, $copcr"},
|
|
||||||
{Cop2Instruction::bc2c, "bc2$copcc $rel"}}};
|
|
||||||
|
|
||||||
static void FormatInstruction(String* dest, const Instruction inst, u32 pc, const char* format)
|
static void FormatInstruction(String* dest, const Instruction inst, u32 pc, const char* format)
|
||||||
{
|
{
|
||||||
|
@ -286,26 +280,35 @@ void DisassembleInstruction(String* dest, u32 pc, u32 bits)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
case InstructionOp::cop0:
|
case InstructionOp::cop0:
|
||||||
FormatCopInstruction(dest, pc, inst, s_cop0_table.data(), s_cop0_table.size(), inst.cop.cop0_op());
|
case InstructionOp::cop1:
|
||||||
return;
|
|
||||||
|
|
||||||
case InstructionOp::cop2:
|
case InstructionOp::cop2:
|
||||||
|
case InstructionOp::cop3:
|
||||||
{
|
{
|
||||||
if (inst.cop.IsCommonInstruction())
|
if (inst.cop.IsCommonInstruction())
|
||||||
{
|
{
|
||||||
FormatCopInstruction(dest, pc, inst, s_cop2_common_table.data(), s_cop2_common_table.size(),
|
FormatCopInstruction(dest, pc, inst, s_cop_common_table.data(), s_cop_common_table.size(), inst.cop.CommonOp());
|
||||||
inst.cop.cop2_op());
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
dest->Format("<cop%u 0x%08X>", ZeroExtend32(inst.cop.cop_n.GetValue()), inst.cop.imm25.GetValue());
|
switch (inst.op)
|
||||||
}
|
{
|
||||||
|
case InstructionOp::cop0:
|
||||||
|
{
|
||||||
|
FormatCopInstruction(dest, pc, inst, s_cop0_table.data(), s_cop0_table.size(), inst.cop.Cop0Op());
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InstructionOp::cop1:
|
case InstructionOp::cop1:
|
||||||
|
case InstructionOp::cop2:
|
||||||
case InstructionOp::cop3:
|
case InstructionOp::cop3:
|
||||||
|
default:
|
||||||
|
{
|
||||||
dest->Format("<cop%u 0x%08X>", ZeroExtend32(inst.cop.cop_n.GetValue()), inst.cop.imm25.GetValue());
|
dest->Format("<cop%u 0x%08X>", ZeroExtend32(inst.cop.cop_n.GetValue()), inst.cop.imm25.GetValue());
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// special case for bltz/bgez{al}
|
// special case for bltz/bgez{al}
|
||||||
|
|
|
@ -74,7 +74,15 @@ enum class InstructionOp : u8
|
||||||
sh = 41,
|
sh = 41,
|
||||||
swl = 42,
|
swl = 42,
|
||||||
sw = 43,
|
sw = 43,
|
||||||
swr = 46
|
swr = 46,
|
||||||
|
lwc0 = 48,
|
||||||
|
lwc1 = 49,
|
||||||
|
lwc2 = 50,
|
||||||
|
lwc3 = 51,
|
||||||
|
swc0 = 56,
|
||||||
|
swc1 = 57,
|
||||||
|
swc2 = 58,
|
||||||
|
swc3 = 59,
|
||||||
};
|
};
|
||||||
constexpr u8 INSTRUCTION_COP_BITS = 0x10;
|
constexpr u8 INSTRUCTION_COP_BITS = 0x10;
|
||||||
constexpr u8 INSTRUCTION_COP_MASK = 0x3C;
|
constexpr u8 INSTRUCTION_COP_MASK = 0x3C;
|
||||||
|
@ -113,27 +121,22 @@ enum class InstructionFunct : u8
|
||||||
sltu = 43
|
sltu = 43
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Cop0Instruction : u32 // 25:21 | 0:5
|
enum class CopCommonInstruction : u32
|
||||||
{
|
{
|
||||||
mfc0 = 0b00000'000000,
|
mfcn = 0b0000,
|
||||||
cfc0 = 0b00010'000000,
|
cfcn = 0b0010,
|
||||||
mtc0 = 0b00100'000000,
|
mtcn = 0b0100,
|
||||||
ctc0 = 0b00110'000000,
|
ctcn = 0b0110,
|
||||||
bc0c = 0b01000'000000,
|
bcnc = 0b1000,
|
||||||
tlbr = 0b10000'000001,
|
|
||||||
tlbwi = 0b10000'000010,
|
|
||||||
tlbwr = 0b10000'000100,
|
|
||||||
tlbp = 0b10000'001000,
|
|
||||||
rfe = 0b10000'010000,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class Cop2Instruction : u32 // 25:21
|
enum class Cop0Instruction : u32
|
||||||
{
|
{
|
||||||
mfc2 = 0b0000,
|
tlbr = 0x01,
|
||||||
cfc2 = 0b0010,
|
tlbwi = 0x02,
|
||||||
mtc2 = 0b0100,
|
tlbwr = 0x04,
|
||||||
ctc2 = 0b0110,
|
tlbp = 0x08,
|
||||||
bc2c = 0b1000,
|
rfe = 0x10,
|
||||||
};
|
};
|
||||||
|
|
||||||
union Instruction
|
union Instruction
|
||||||
|
@ -175,15 +178,9 @@ union Instruction
|
||||||
|
|
||||||
bool IsCommonInstruction() const { return (bits & (UINT32_C(1) << 25)) == 0; }
|
bool IsCommonInstruction() const { return (bits & (UINT32_C(1) << 25)) == 0; }
|
||||||
|
|
||||||
Cop0Instruction cop0_op() const
|
CopCommonInstruction CommonOp() const { return static_cast<CopCommonInstruction>((bits >> 21) & UINT32_C(0b1111)); }
|
||||||
{
|
|
||||||
return static_cast<Cop0Instruction>(((bits >> 15) & UINT32_C(0b11111000000)) | (bits & UINT32_C(0b111111)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Cop2Instruction cop2_op() const
|
Cop0Instruction Cop0Op() const { return static_cast<Cop0Instruction>(bits & UINT32_C(0x3F)); }
|
||||||
{
|
|
||||||
return static_cast<Cop2Instruction>((bits >> 21) & UINT32_C(0b1111));
|
|
||||||
}
|
|
||||||
} cop;
|
} cop;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue