mirror of
https://github.com/stenzek/duckstation.git
synced 2024-11-23 05:49:43 +00:00
CPU: Fix incorrect exception vector for break
This commit is contained in:
parent
5babc076f5
commit
540f282213
@ -33,6 +33,7 @@ void Core::Reset()
|
||||
m_cop0_regs.BDAM = 0;
|
||||
m_cop0_regs.BPCM = 0;
|
||||
m_cop0_regs.EPC = 0;
|
||||
m_cop0_regs.sr.bits = 0;
|
||||
|
||||
SetPC(RESET_VECTOR);
|
||||
}
|
||||
@ -165,17 +166,31 @@ void Core::Branch(u32 target)
|
||||
m_branched = true;
|
||||
}
|
||||
|
||||
void Core::RaiseException(Exception excode)
|
||||
u32 Core::GetExceptionVector(Exception excode) const
|
||||
{
|
||||
const u32 base = m_cop0_regs.sr.BEV ? UINT32_C(0xbfc00100) : UINT32_C(0x80000000);
|
||||
switch (excode)
|
||||
{
|
||||
case Exception::BP:
|
||||
return base | UINT32_C(0x00000040);
|
||||
|
||||
default:
|
||||
return base | UINT32_C(0x00000080);
|
||||
}
|
||||
}
|
||||
|
||||
void Core::RaiseException(Exception excode, u8 coprocessor /* = 0 */)
|
||||
{
|
||||
m_cop0_regs.EPC = m_in_branch_delay_slot ? (m_current_instruction_pc - UINT32_C(4)) : m_current_instruction_pc;
|
||||
m_cop0_regs.cause.Excode = excode;
|
||||
m_cop0_regs.cause.BD = m_in_branch_delay_slot;
|
||||
m_cop0_regs.cause.CE = coprocessor;
|
||||
|
||||
// current -> previous
|
||||
// current -> previous, switch to kernel mode and disable interrupts
|
||||
m_cop0_regs.sr.mode_bits <<= 2;
|
||||
|
||||
// flush the pipeline - we don't want to execute the previously fetched instruction
|
||||
m_regs.npc = m_cop0_regs.sr.BEV ? UINT32_C(0xbfc00180) : UINT32_C(0x80000080);
|
||||
m_regs.npc = GetExceptionVector(excode);
|
||||
FlushPipeline();
|
||||
}
|
||||
|
||||
@ -830,7 +845,7 @@ void Core::ExecuteInstruction(Instruction inst)
|
||||
if (!m_cop0_regs.sr.CU0 && InUserMode())
|
||||
{
|
||||
Log_WarningPrintf("Coprocessor 0 not present in user mode");
|
||||
RaiseException(Exception::CpU);
|
||||
RaiseException(Exception::CpU, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -842,7 +857,7 @@ void Core::ExecuteInstruction(Instruction inst)
|
||||
case InstructionOp::cop1:
|
||||
case InstructionOp::cop2:
|
||||
{
|
||||
RaiseException(Exception::CpU);
|
||||
RaiseException(Exception::CpU, inst.cop.cop_n);
|
||||
}
|
||||
break;
|
||||
|
||||
|
@ -69,7 +69,10 @@ private:
|
||||
void ExecuteInstruction(Instruction inst);
|
||||
void ExecuteCop0Instruction(Instruction inst);
|
||||
void Branch(u32 target);
|
||||
void RaiseException(Exception excode);
|
||||
|
||||
// exceptions
|
||||
u32 GetExceptionVector(Exception excode) const;
|
||||
void RaiseException(Exception excode, u8 coprocessor = 0);
|
||||
|
||||
// flushes any load delays if present
|
||||
void FlushLoadDelay();
|
||||
|
@ -267,11 +267,11 @@ struct Cop0Registers
|
||||
{
|
||||
u32 bits;
|
||||
BitField<u32, bool, 0, 1> IEc; // current interrupt enable
|
||||
BitField<u32, bool, 1, 1> KUc; // current kernel/user mode, kernel = 1
|
||||
BitField<u32, bool, 1, 1> KUc; // current kernel/user mode, user = 1
|
||||
BitField<u32, bool, 2, 1> IEp; // previous interrupt enable
|
||||
BitField<u32, bool, 3, 1> KUp; // previous kernel/user mode, kernel = 1
|
||||
BitField<u32, bool, 3, 1> KUp; // previous kernel/user mode, user = 1
|
||||
BitField<u32, bool, 4, 1> IEo; // old interrupt enable
|
||||
BitField<u32, bool, 5, 1> KUo; // old kernel/user mode, kernel = 1
|
||||
BitField<u32, bool, 5, 1> KUo; // old kernel/user mode, user = 1
|
||||
BitField<u32, u8, 8, 8> Im; // interrupt mask, set to 1 = allowed to trigger
|
||||
BitField<u32, bool, 16, 1> Isc; // isolate cache, no writes to memory occur
|
||||
BitField<u32, bool, 17, 1> Swc; // swap data and instruction caches
|
||||
|
Loading…
Reference in New Issue
Block a user