From 49a385e7439b723abe69e27e21d1e0df33c04b8a Mon Sep 17 00:00:00 2001 From: zilmar Date: Tue, 9 May 2023 08:06:15 +0930 Subject: [PATCH] Core: Split CheckFPUException into CheckFPUException and CheckFPUInvalidException --- .../N64System/Interpreter/InterpreterOps.cpp | 169 +++++++++--------- .../N64System/Interpreter/InterpreterOps.h | 1 + 2 files changed, 83 insertions(+), 87 deletions(-) diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp index 5fc2df9d6..6fe8f7fe1 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp @@ -3161,10 +3161,6 @@ bool R4300iOp::CheckFPUInput32Conv(const float & Value) { FPStatusReg & StatusReg = (FPStatusReg &)_FPCR[31]; StatusReg.Cause.UnimplementedOperation = 1; - Exception = true; - } - if (Exception) - { g_Reg->DoFloatingPointException(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP); g_System->m_PipelineStage = PIPELINE_STAGE_JUMP; g_System->m_JumpToLocation = (*_PROGRAM_COUNTER); @@ -3319,92 +3315,14 @@ bool R4300iOp::CheckFPUResult64(double & Result) bool R4300iOp::CheckFPUException(void) { int Except = fetestexcept(FE_ALL_EXCEPT); - if (Except == 0) + if (Except == 0 || !SetFPUException()) { return false; } - - bool Res = false; - FPStatusReg & StatusReg = (FPStatusReg &)_FPCR[31]; - if ((Except & FE_UNDERFLOW) != 0) - { - if (StatusReg.FlushSubnormals == 0 || StatusReg.Enable.Underflow || StatusReg.Enable.Inexact) - { - StatusReg.Cause.UnimplementedOperation = 1; - Res = true; - } - } - - if (!Res) - { - if ((Except & FE_INEXACT) != 0) - { - StatusReg.Cause.Inexact = 1; - if (StatusReg.Enable.Inexact) - { - Res = true; - } - else - { - StatusReg.Flags.Inexact = 1; - } - } - if ((Except & FE_UNDERFLOW) != 0) - { - StatusReg.Cause.Underflow = 1; - if (StatusReg.Enable.Underflow) - { - Res = true; - } - else - { - StatusReg.Flags.Underflow = 1; - } - } - if ((Except & FE_OVERFLOW) != 0) - { - StatusReg.Cause.Overflow = 1; - if (StatusReg.Enable.Overflow) - { - Res = true; - } - else - { - StatusReg.Flags.Overflow = 1; - } - } - if ((Except & FE_DIVBYZERO) != 0) - { - StatusReg.Cause.DivisionByZero = 1; - if (StatusReg.Enable.DivisionByZero) - { - Res = true; - } - else - { - StatusReg.Flags.DivisionByZero = 1; - } - } - if ((Except & FE_INVALID) != 0) - { - StatusReg.Cause.InvalidOperation = 1; - if (StatusReg.Enable.InvalidOperation) - { - Res = true; - } - else - { - StatusReg.Flags.InvalidOperation = 1; - } - } - } - if (Res) - { - g_Reg->DoFloatingPointException(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP); - g_System->m_PipelineStage = PIPELINE_STAGE_JUMP; - g_System->m_JumpToLocation = (*_PROGRAM_COUNTER); - } - return Res; + g_Reg->DoFloatingPointException(g_System->m_PipelineStage == PIPELINE_STAGE_JUMP); + g_System->m_PipelineStage = PIPELINE_STAGE_JUMP; + g_System->m_JumpToLocation = (*_PROGRAM_COUNTER); + return true; } bool R4300iOp::CheckFPUInvalidException(void) @@ -3444,3 +3362,80 @@ bool R4300iOp::CheckFPUInvalidException(void) } return false; } + +bool R4300iOp::SetFPUException(void) +{ + FPStatusReg & StatusReg = (FPStatusReg &)_FPCR[31]; + int Except = fetestexcept(FE_ALL_EXCEPT); + if ((Except & FE_UNDERFLOW) != 0) + { + if (StatusReg.FlushSubnormals == 0 || StatusReg.Enable.Underflow || StatusReg.Enable.Inexact) + { + StatusReg.Cause.UnimplementedOperation = 1; + return true; + } + } + + bool Res = false; + if ((Except & FE_INEXACT) != 0) + { + StatusReg.Cause.Inexact = 1; + if (StatusReg.Enable.Inexact) + { + Res = true; + } + else + { + StatusReg.Flags.Inexact = 1; + } + } + if ((Except & FE_UNDERFLOW) != 0) + { + StatusReg.Cause.Underflow = 1; + if (StatusReg.Enable.Underflow) + { + Res = true; + } + else + { + StatusReg.Flags.Underflow = 1; + } + } + if ((Except & FE_OVERFLOW) != 0) + { + StatusReg.Cause.Overflow = 1; + if (StatusReg.Enable.Overflow) + { + Res = true; + } + else + { + StatusReg.Flags.Overflow = 1; + } + } + if ((Except & FE_DIVBYZERO) != 0) + { + StatusReg.Cause.DivisionByZero = 1; + if (StatusReg.Enable.DivisionByZero) + { + Res = true; + } + else + { + StatusReg.Flags.DivisionByZero = 1; + } + } + if ((Except & FE_INVALID) != 0) + { + StatusReg.Cause.InvalidOperation = 1; + if (StatusReg.Enable.InvalidOperation) + { + Res = true; + } + else + { + StatusReg.Flags.InvalidOperation = 1; + } + } + return Res; +} diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.h b/Source/Project64-core/N64System/Interpreter/InterpreterOps.h index 2ae7289d7..5ac01c015 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.h +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.h @@ -264,6 +264,7 @@ protected: static bool CheckFPUResult64(double & Result); static bool CheckFPUException(void); static bool CheckFPUInvalidException(void); + static bool SetFPUException(void); static const uint32_t SWL_MASK[4], SWR_MASK[4], LWL_MASK[4], LWR_MASK[4]; static const int32_t SWL_SHIFT[4], SWR_SHIFT[4], LWL_SHIFT[4], LWR_SHIFT[4];