mirror of
https://github.com/WinampDesktop/winamp.git
synced 2025-04-27 19:45:41 -04:00
CPU: Handle reserved instructions/bus errors
This commit is contained in:
parent
01ad2fa5b6
commit
92ec5a0a14
@ -229,6 +229,15 @@ u32 Core::GetExceptionVector(Exception excode) const
|
|||||||
|
|
||||||
void Core::RaiseException(Exception excode)
|
void Core::RaiseException(Exception excode)
|
||||||
{
|
{
|
||||||
|
#ifdef Y_BUILD_CONFIG_RELEASE
|
||||||
|
if (excode == Exception::RI)
|
||||||
|
{
|
||||||
|
// Invalid op.
|
||||||
|
Log_DevPrintf("Invalid instruction at 0x%08X", m_current_instruction_pc);
|
||||||
|
DisassembleAndPrint(m_current_instruction_pc, 4, 0);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
RaiseException(excode, m_current_instruction_pc, m_current_instruction_in_branch_delay_slot,
|
RaiseException(excode, m_current_instruction_pc, m_current_instruction_in_branch_delay_slot,
|
||||||
m_current_instruction_was_branch_taken, m_current_instruction.cop.cop_n);
|
m_current_instruction_was_branch_taken, m_current_instruction.cop.cop_n);
|
||||||
}
|
}
|
||||||
@ -334,7 +343,7 @@ 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)
|
std::optional<u32> Core::ReadCop0Reg(Cop0Reg reg)
|
||||||
{
|
{
|
||||||
switch (reg)
|
switch (reg)
|
||||||
{
|
{
|
||||||
@ -372,8 +381,8 @@ u32 Core::ReadCop0Reg(Cop0Reg reg)
|
|||||||
return m_cop0_regs.PRID;
|
return m_cop0_regs.PRID;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Panic("Unknown COP0 reg");
|
Log_DevPrintf("Unknown COP0 reg %u", ZeroExtend32(static_cast<u8>(reg)));
|
||||||
return 0;
|
return std::nullopt;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -440,7 +449,7 @@ void Core::WriteCop0Reg(Cop0Reg reg, u32 value)
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Panic("Unknown COP0 reg");
|
Log_DevPrintf("Unknown COP0 reg %u", ZeroExtend32(static_cast<u8>(reg)));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -820,10 +829,12 @@ void Core::ExecuteInstruction()
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
UnreachableCode();
|
{
|
||||||
|
RaiseException(Exception::RI);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case InstructionOp::lui:
|
case InstructionOp::lui:
|
||||||
@ -1149,20 +1160,24 @@ void Core::ExecuteInstruction()
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// COP1/COP3 are not present
|
// swc0/lwc0/cop1/cop3 are essentially no-ops
|
||||||
case InstructionOp::cop1:
|
case InstructionOp::cop1:
|
||||||
case InstructionOp::cop3:
|
case InstructionOp::cop3:
|
||||||
|
case InstructionOp::lwc0:
|
||||||
case InstructionOp::lwc1:
|
case InstructionOp::lwc1:
|
||||||
case InstructionOp::swc1:
|
|
||||||
case InstructionOp::lwc3:
|
case InstructionOp::lwc3:
|
||||||
|
case InstructionOp::swc0:
|
||||||
|
case InstructionOp::swc1:
|
||||||
case InstructionOp::swc3:
|
case InstructionOp::swc3:
|
||||||
{
|
{
|
||||||
RaiseException(Exception::CpU);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
// everything else is reserved/invalid
|
||||||
default:
|
default:
|
||||||
UnreachableCode();
|
{
|
||||||
|
RaiseException(Exception::RI);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1176,11 +1191,19 @@ void Core::ExecuteCop0Instruction()
|
|||||||
switch (inst.cop.CommonOp())
|
switch (inst.cop.CommonOp())
|
||||||
{
|
{
|
||||||
case CopCommonInstruction::mfcn:
|
case CopCommonInstruction::mfcn:
|
||||||
WriteRegDelayed(inst.r.rt, ReadCop0Reg(static_cast<Cop0Reg>(inst.r.rd.GetValue())));
|
{
|
||||||
|
const std::optional<u32> value = ReadCop0Reg(static_cast<Cop0Reg>(inst.r.rd.GetValue()));
|
||||||
|
if (value)
|
||||||
|
WriteRegDelayed(inst.r.rt, value.value());
|
||||||
|
else
|
||||||
|
RaiseException(Exception::RI);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CopCommonInstruction::mtcn:
|
case CopCommonInstruction::mtcn:
|
||||||
|
{
|
||||||
WriteCop0Reg(static_cast<Cop0Reg>(inst.r.rd.GetValue()), ReadReg(inst.r.rt));
|
WriteCop0Reg(static_cast<Cop0Reg>(inst.r.rd.GetValue()), ReadReg(inst.r.rt));
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include "gte.h"
|
#include "gte.h"
|
||||||
#include "types.h"
|
#include "types.h"
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <optional>
|
||||||
|
|
||||||
class StateWrapper;
|
class StateWrapper;
|
||||||
|
|
||||||
@ -107,7 +108,7 @@ private:
|
|||||||
void WriteCacheControl(u32 value);
|
void WriteCacheControl(u32 value);
|
||||||
|
|
||||||
// read/write cop0 regs
|
// read/write cop0 regs
|
||||||
u32 ReadCop0Reg(Cop0Reg reg);
|
std::optional<u32> ReadCop0Reg(Cop0Reg reg);
|
||||||
void WriteCop0Reg(Cop0Reg reg, u32 value);
|
void WriteCop0Reg(Cop0Reg reg, u32 value);
|
||||||
|
|
||||||
Bus* m_bus = nullptr;
|
Bus* m_bus = nullptr;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user