Core: Improve R4300iOp::COP1_CT
This commit is contained in:
parent
3c73c06b01
commit
80aecdc5e3
|
@ -1900,14 +1900,6 @@ void R4300iOp::COP1_DMF()
|
||||||
void R4300iOp::COP1_CF()
|
void R4300iOp::COP1_CF()
|
||||||
{
|
{
|
||||||
TEST_COP1_USABLE_EXCEPTION();
|
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];
|
_GPR[m_Opcode.rt].DW = (int32_t)_FPCR[m_Opcode.fs];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1926,17 +1918,7 @@ void R4300iOp::COP1_DMT()
|
||||||
void R4300iOp::COP1_CT()
|
void R4300iOp::COP1_CT()
|
||||||
{
|
{
|
||||||
TEST_COP1_USABLE_EXCEPTION();
|
TEST_COP1_USABLE_EXCEPTION();
|
||||||
if (m_Opcode.fs == 31)
|
g_Reg->Cop1_CT(m_Opcode.fs, _GPR[m_Opcode.rt].W[0]);
|
||||||
{
|
|
||||||
_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;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// COP1: BC1 functions
|
// COP1: BC1 functions
|
||||||
|
|
|
@ -246,6 +246,7 @@ protected:
|
||||||
static Func Jump_CoP1_L[64];
|
static Func Jump_CoP1_L[64];
|
||||||
|
|
||||||
static void GenerateAddressErrorException(uint64_t VAddr, bool FromRead);
|
static void GenerateAddressErrorException(uint64_t VAddr, bool FromRead);
|
||||||
|
static void GenerateFloatingPointException(void);
|
||||||
static void GenerateOverflowException(void);
|
static void GenerateOverflowException(void);
|
||||||
static void GenerateTLBReadException(uint64_t VAddr, const char * function);
|
static void GenerateTLBReadException(uint64_t VAddr, const char * function);
|
||||||
static void GenerateTLBWriteException(uint64_t VAddr, const char * function);
|
static void GenerateTLBWriteException(uint64_t VAddr, const char * function);
|
||||||
|
|
|
@ -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()
|
void CRegisters::CheckInterrupts()
|
||||||
{
|
{
|
||||||
uint32_t mi_intr_reg = MI_INTR_REG, status_register;
|
uint32_t mi_intr_reg = MI_INTR_REG, status_register;
|
||||||
|
@ -591,6 +619,22 @@ void CRegisters::DoBreakException(bool DelaySlot)
|
||||||
m_PROGRAM_COUNTER = 0x80000180;
|
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)
|
void CRegisters::DoTrapException(bool DelaySlot)
|
||||||
{
|
{
|
||||||
CAUSE_REGISTER = EXC_TRAP;
|
CAUSE_REGISTER = EXC_TRAP;
|
||||||
|
|
|
@ -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)
|
#pragma warning(pop)
|
||||||
|
|
||||||
// CPO registers by name
|
// CPO registers by name
|
||||||
|
@ -344,6 +389,7 @@ public:
|
||||||
void CheckInterrupts();
|
void CheckInterrupts();
|
||||||
void DoAddressError(bool DelaySlot, uint64_t BadVaddr, bool FromRead);
|
void DoAddressError(bool DelaySlot, uint64_t BadVaddr, bool FromRead);
|
||||||
void DoBreakException(bool DelaySlot);
|
void DoBreakException(bool DelaySlot);
|
||||||
|
void DoFloatingPointException(bool DelaySlot);
|
||||||
void DoTrapException(bool DelaySlot);
|
void DoTrapException(bool DelaySlot);
|
||||||
void DoCopUnusableException(bool DelaySlot, int32_t Coprocessor);
|
void DoCopUnusableException(bool DelaySlot, int32_t Coprocessor);
|
||||||
bool DoIntrException(bool DelaySlot);
|
bool DoIntrException(bool DelaySlot);
|
||||||
|
@ -358,6 +404,7 @@ public:
|
||||||
|
|
||||||
uint64_t Cop0_MF(COP0Reg Reg);
|
uint64_t Cop0_MF(COP0Reg Reg);
|
||||||
void Cop0_MT(COP0Reg Reg, uint64_t Value);
|
void Cop0_MT(COP0Reg Reg, uint64_t Value);
|
||||||
|
void Cop1_CT(uint32_t Reg, uint32_t Value);
|
||||||
|
|
||||||
// General registers
|
// General registers
|
||||||
uint32_t m_PROGRAM_COUNTER;
|
uint32_t m_PROGRAM_COUNTER;
|
||||||
|
|
|
@ -149,6 +149,7 @@ private:
|
||||||
|
|
||||||
friend class VideoInterfaceHandler;
|
friend class VideoInterfaceHandler;
|
||||||
friend class PifRamHandler;
|
friend class PifRamHandler;
|
||||||
|
friend class CRegisters;
|
||||||
|
|
||||||
// Used for loading and potentially executing the CPU in its own thread
|
// Used for loading and potentially executing the CPU in its own thread
|
||||||
static void StartEmulationThread(CThread * thread);
|
static void StartEmulationThread(CThread * thread);
|
||||||
|
|
Loading…
Reference in New Issue