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()
|
||||
{
|
||||
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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue