Core: Improve R4300iOp::COP1_CT

This commit is contained in:
zilmar 2023-01-02 19:49:19 +10:30
parent 3c73c06b01
commit 80aecdc5e3
5 changed files with 94 additions and 19 deletions

View File

@ -1900,14 +1900,6 @@ void R4300iOp::COP1_DMF()
void R4300iOp::COP1_CF()
{
TEST_COP1_USABLE_EXCEPTION();
if (m_Opcode.fs != 31 && m_Opcode.fs != 0)
{
if (HaveDebugger())
{
g_Notify->DisplayError("CFC1: what register are you writing to?");
}
return;
}
_GPR[m_Opcode.rt].DW = (int32_t)_FPCR[m_Opcode.fs];
}
@ -1926,17 +1918,7 @@ void R4300iOp::COP1_DMT()
void R4300iOp::COP1_CT()
{
TEST_COP1_USABLE_EXCEPTION();
if (m_Opcode.fs == 31)
{
_FPCR[m_Opcode.fs] = (_GPR[m_Opcode.rt].W[0] & 0x183FFFF);
switch ((_FPCR[m_Opcode.fs] & 3))
{
case 0: *_RoundingModel = FE_TONEAREST; break;
case 1: *_RoundingModel = FE_TOWARDZERO; break;
case 2: *_RoundingModel = FE_UPWARD; break;
case 3: *_RoundingModel = FE_DOWNWARD; break;
}
}
g_Reg->Cop1_CT(m_Opcode.fs, _GPR[m_Opcode.rt].W[0]);
}
// COP1: BC1 functions

View File

@ -246,6 +246,7 @@ protected:
static Func Jump_CoP1_L[64];
static void GenerateAddressErrorException(uint64_t VAddr, bool FromRead);
static void GenerateFloatingPointException(void);
static void GenerateOverflowException(void);
static void GenerateTLBReadException(uint64_t VAddr, const char * function);
static void GenerateTLBWriteException(uint64_t VAddr, const char * function);

View File

@ -462,6 +462,34 @@ void CRegisters::Cop0_MT(COP0Reg Reg, uint64_t Value)
}
}
void CRegisters::Cop1_CT(uint32_t Reg, uint32_t Value)
{
if (Reg == 31)
{
FPStatusReg & StatusReg = (FPStatusReg &)_FPCR[31];
StatusReg.Value = (Value & 0x183FFFF);
switch (StatusReg.RoundingMode)
{
case 0: *_RoundingModel = FE_TONEAREST; break;
case 1: *_RoundingModel = FE_TOWARDZERO; break;
case 2: *_RoundingModel = FE_UPWARD; break;
case 3: *_RoundingModel = FE_DOWNWARD; break;
}
if (((StatusReg.Cause.Inexact & StatusReg.Enable.Inexact) != 0) ||
((StatusReg.Cause.Underflow & StatusReg.Enable.Underflow) != 0) ||
((StatusReg.Cause.Overflow & StatusReg.Enable.Overflow) != 0) ||
((StatusReg.Cause.DivisionByZero & StatusReg.Enable.DivisionByZero) != 0) ||
((StatusReg.Cause.InvalidOperation & StatusReg.Enable.InvalidOperation) != 0) ||
(StatusReg.Cause.UnimplementedOperation != 0))
{
DoFloatingPointException(m_System->m_PipelineStage == PIPELINE_STAGE_JUMP);
m_System->m_PipelineStage = PIPELINE_STAGE_JUMP;
m_System->m_JumpToLocation = (*_PROGRAM_COUNTER);
}
}
}
void CRegisters::CheckInterrupts()
{
uint32_t mi_intr_reg = MI_INTR_REG, status_register;
@ -591,6 +619,22 @@ void CRegisters::DoBreakException(bool DelaySlot)
m_PROGRAM_COUNTER = 0x80000180;
}
void CRegisters::DoFloatingPointException(bool DelaySlot)
{
CAUSE_REGISTER = EXC_FPE;
if (DelaySlot)
{
EPC_REGISTER = (int64_t)((int32_t)m_PROGRAM_COUNTER - 4);
CAUSE_REGISTER |= CAUSE_BD;
}
else
{
EPC_REGISTER = (int64_t)((int32_t)m_PROGRAM_COUNTER);
}
STATUS_REGISTER |= STATUS_EXL;
m_PROGRAM_COUNTER = 0x80000180;
}
void CRegisters::DoTrapException(bool DelaySlot)
{
CAUSE_REGISTER = EXC_TRAP;

View File

@ -45,6 +45,51 @@ union COP0XContext
};
};
union FPStatusReg
{
uint32_t Value;
struct
{
unsigned RoundingMode : 2;
unsigned : 30;
};
struct
{
unsigned : 2;
unsigned Inexact : 1;
unsigned Underflow : 1;
unsigned Overflow : 1;
unsigned DivisionByZero : 1;
unsigned InvalidOperation : 1;
unsigned : 25;
} Flags;
struct
{
unsigned : 7;
unsigned Inexact : 1;
unsigned Underflow : 1;
unsigned Overflow : 1;
unsigned DivisionByZero : 1;
unsigned InvalidOperation : 1;
unsigned : 20;
} Enable;
struct
{
unsigned : 12;
unsigned Inexact : 1;
unsigned Underflow : 1;
unsigned Overflow : 1;
unsigned DivisionByZero : 1;
unsigned InvalidOperation : 1;
unsigned UnimplementedOperation : 1;
unsigned : 14;
} Cause;
};
#pragma warning(pop)
// CPO registers by name
@ -344,6 +389,7 @@ public:
void CheckInterrupts();
void DoAddressError(bool DelaySlot, uint64_t BadVaddr, bool FromRead);
void DoBreakException(bool DelaySlot);
void DoFloatingPointException(bool DelaySlot);
void DoTrapException(bool DelaySlot);
void DoCopUnusableException(bool DelaySlot, int32_t Coprocessor);
bool DoIntrException(bool DelaySlot);
@ -358,6 +404,7 @@ public:
uint64_t Cop0_MF(COP0Reg Reg);
void Cop0_MT(COP0Reg Reg, uint64_t Value);
void Cop1_CT(uint32_t Reg, uint32_t Value);
// General registers
uint32_t m_PROGRAM_COUNTER;

View File

@ -149,6 +149,7 @@ private:
friend class VideoInterfaceHandler;
friend class PifRamHandler;
friend class CRegisters;
// Used for loading and potentially executing the CPU in its own thread
static void StartEmulationThread(CThread * thread);