diff --git a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp index e297097a2..ad3b51589 100644 --- a/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp +++ b/Source/Project64-core/N64System/Interpreter/InterpreterOps.cpp @@ -57,14 +57,12 @@ const int32_t R4300iOp::LWR_SHIFT[4] = { 24, 16, 8, 0 }; m_JumpToLocation = (*_PROGRAM_COUNTER);\ return; -//#define TEST_COP1_USABLE_EXCEPTION #define TEST_COP1_USABLE_EXCEPTION() \ if ((g_Reg->STATUS_REGISTER & STATUS_CU1) == 0) {\ g_Reg->DoCopUnusableException(m_NextInstruction == JUMP,1);\ m_NextInstruction = JUMP;\ m_JumpToLocation = (*_PROGRAM_COUNTER);\ - return;\ - } + return;}\ #define TLB_READ_EXCEPTION(Address) \ g_Reg->DoTLBReadMiss(m_NextInstruction == JUMP,Address);\ @@ -104,13 +102,13 @@ void R4300iOp::COP1_BC() void R4300iOp::COP1_S() { - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); Jump_CoP1_S[m_Opcode.funct](); } void R4300iOp::COP1_D() { - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); Jump_CoP1_D[m_Opcode.funct](); } @@ -2255,15 +2253,15 @@ void R4300iOp::COP1_DMF() void R4300iOp::COP1_CF() { TEST_COP1_USABLE_EXCEPTION(); - if (m_Opcode.fs != 31 && m_Opcode.fs != 0) - { - if (bHaveDebugger()) - { - g_Notify->DisplayError("CFC1 what register are you writing to ?"); - } - return; - } - _GPR[m_Opcode.rt].DW = (int32_t)_FPCR[m_Opcode.fs]; + if (m_Opcode.fs != 31 && m_Opcode.fs != 0) + { + if (bHaveDebugger()) + { + g_Notify->DisplayError("CFC1 what register are you writing to ?"); + } + return; + } + _GPR[m_Opcode.rt].DW = (int32_t)_FPCR[m_Opcode.fs]; } void R4300iOp::COP1_MT() @@ -2281,15 +2279,15 @@ void R4300iOp::COP1_DMT() void R4300iOp::COP1_CT() { TEST_COP1_USABLE_EXCEPTION(); - if (m_Opcode.fs == 31) - { + if (m_Opcode.fs == 31) + { _FPCR[m_Opcode.fs] = _GPR[m_Opcode.rt].W[0]; switch ((_FPCR[m_Opcode.fs] & 3)) { - case 0: *_RoundingModel = ROUND_NEAR; break; - case 1: *_RoundingModel = ROUND_CHOP; break; - case 2: *_RoundingModel = ROUND_UP; break; - case 3: *_RoundingModel = ROUND_DOWN; break; + case 0: *_RoundingModel = FE_TONEAREST; break; + case 1: *_RoundingModel = FE_TOWARDZERO; break; + case 2: *_RoundingModel = FE_UPWARD; break; + case 3: *_RoundingModel = FE_DOWNWARD; break; } return; } @@ -2358,186 +2356,148 @@ void R4300iOp::COP1_BCTL() } } /************************** COP1: S functions ************************/ -__inline void Float_RoundToInteger32(int32_t * Dest, float * Source) +__inline void Float_RoundToInteger32(int32_t * Dest, const float * Source, int RoundType) { -#ifdef _M_IX86 - _asm - { - mov esi, [Source] - mov edi, [Dest] - fld dword ptr[esi] - fistp dword ptr[edi] - } -#else - __m128 xmm; +#pragma warning(push) +#pragma warning(disable:4244) //warning C4244: disabe conversion from 'float' to 'int32_t', possible loss of data - xmm = _mm_load_ss(Source); - *(Dest) = _mm_cvt_ss2si(xmm); -#endif + if (RoundType == FE_TONEAREST) { *Dest = roundf(*Source); } + if (RoundType == FE_TOWARDZERO) { *Dest = truncf(*Source); } + if (RoundType == FE_UPWARD) { *Dest = ceilf(*Source); } + if (RoundType == FE_DOWNWARD) { *Dest = floorf(*Source); } + +#pragma warning(pop) } -__inline void Float_RoundToInteger64(int64_t * Dest, float * Source) +__inline void Float_RoundToInteger64(int64_t * Dest, const float * Source, int RoundType) { -#ifdef _M_IX86 - _asm - { - mov esi, [Source] - mov edi, [Dest] - fld dword ptr[esi] - fistp qword ptr[edi] - } -#else - __m128 xmm; +#pragma warning(push) +#pragma warning(disable:4244) //warning C4244: disabe conversion from 'float' to 'int64_t', possible loss of data - xmm = _mm_load_ss(Source); - *(Dest) = _mm_cvtss_si64(xmm); -#endif + if (RoundType == FE_TONEAREST) { *Dest = roundf(*Source); } + if (RoundType == FE_TOWARDZERO) { *Dest = truncf(*Source); } + if (RoundType == FE_UPWARD) { *Dest = ceilf(*Source); } + if (RoundType == FE_DOWNWARD) { *Dest = floorf(*Source); } + +#pragma warning(pop) } void R4300iOp::COP1_S_ADD() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(float *)_FPR_S[m_Opcode.fd] = (*(float *)_FPR_S[m_Opcode.fs] + *(float *)_FPR_S[m_Opcode.ft]); } void R4300iOp::COP1_S_SUB() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(float *)_FPR_S[m_Opcode.fd] = (*(float *)_FPR_S[m_Opcode.fs] - *(float *)_FPR_S[m_Opcode.ft]); } void R4300iOp::COP1_S_MUL() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(float *)_FPR_S[m_Opcode.fd] = (*(float *)_FPR_S[m_Opcode.fs] * *(float *)_FPR_S[m_Opcode.ft]); } void R4300iOp::COP1_S_DIV() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(float *)_FPR_S[m_Opcode.fd] = (*(float *)_FPR_S[m_Opcode.fs] / *(float *)_FPR_S[m_Opcode.ft]); } void R4300iOp::COP1_S_SQRT() { - float * Dest = (float *)(_FPR_S[m_Opcode.fd]); - float * Source = (float *)(_FPR_S[m_Opcode.fs]); - TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); -#ifdef _M_IX86 - _asm - { - push esi - mov esi, dword ptr[Source] - fld dword ptr[esi] - fsqrt - mov esi, dword ptr[Dest] - fstp dword ptr[esi] - pop esi - } -#else - __m128 xmm; + fesetround(*_RoundingModel); - xmm = _mm_load_ss(Source); - xmm = _mm_sqrt_ss(xmm); - *(Dest) = _mm_cvtss_f32(xmm); -#endif + *(float *)(_FPR_S[m_Opcode.fd]) = sqrtf(*(float *)(_FPR_S[m_Opcode.fs])); } void R4300iOp::COP1_S_ABS() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(float *)_FPR_S[m_Opcode.fd] = (float)fabs(*(float *)_FPR_S[m_Opcode.fs]); } void R4300iOp::COP1_S_MOV() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(float *)_FPR_S[m_Opcode.fd] = *(float *)_FPR_S[m_Opcode.fs]; } void R4300iOp::COP1_S_NEG() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(float *)_FPR_S[m_Opcode.fd] = (*(float *)_FPR_S[m_Opcode.fs] * -1.0f); } void R4300iOp::COP1_S_TRUNC_L() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(_RC_CHOP, _MCW_RC); - Float_RoundToInteger64(&*(int64_t *)_FPR_D[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs]); + Float_RoundToInteger64(&*(int64_t *)_FPR_D[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs], FE_TOWARDZERO); } void R4300iOp::COP1_S_CEIL_L() { //added by Witten TEST_COP1_USABLE_EXCEPTION(); - _controlfp(_RC_UP, _MCW_RC); - Float_RoundToInteger64(&*(int64_t *)_FPR_D[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs]); + Float_RoundToInteger64(&*(int64_t *)_FPR_D[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs], FE_UPWARD); } void R4300iOp::COP1_S_FLOOR_L() { //added by Witten TEST_COP1_USABLE_EXCEPTION(); - _controlfp(_RC_DOWN, _MCW_RC); - Float_RoundToInteger64(&*(int64_t *)_FPR_D[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs]); + Float_RoundToInteger64(&*(int64_t *)_FPR_D[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs], FE_DOWNWARD); } void R4300iOp::COP1_S_ROUND_W() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(_RC_NEAR, _MCW_RC); - Float_RoundToInteger32(&*(int32_t *)_FPR_S[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs]); + Float_RoundToInteger32(&*(int32_t *)_FPR_S[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs], FE_TONEAREST); } void R4300iOp::COP1_S_TRUNC_W() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(_RC_CHOP, _MCW_RC); - Float_RoundToInteger32(&*(int32_t *)_FPR_S[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs]); + Float_RoundToInteger32(&*(int32_t *)_FPR_S[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs], FE_TOWARDZERO); } void R4300iOp::COP1_S_CEIL_W() { //added by Witten TEST_COP1_USABLE_EXCEPTION(); - _controlfp(_RC_UP, _MCW_RC); - Float_RoundToInteger32(&*(int32_t *)_FPR_S[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs]); + Float_RoundToInteger32(&*(int32_t *)_FPR_S[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs], FE_UPWARD); } void R4300iOp::COP1_S_FLOOR_W() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(_RC_DOWN, _MCW_RC); - Float_RoundToInteger32(&*(int32_t *)_FPR_S[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs]); + Float_RoundToInteger32(&*(int32_t *)_FPR_S[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs], FE_DOWNWARD); } void R4300iOp::COP1_S_CVT_D() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(double *)_FPR_D[m_Opcode.fd] = (double)(*(float *)_FPR_S[m_Opcode.fs]); } void R4300iOp::COP1_S_CVT_W() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); - Float_RoundToInteger32(&*(int32_t *)_FPR_S[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs]); + Float_RoundToInteger32(&*(int32_t *)_FPR_S[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs], *_RoundingModel); } void R4300iOp::COP1_S_CVT_L() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); - Float_RoundToInteger64(&*(int64_t *)_FPR_D[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs]); + Float_RoundToInteger64(&*(int64_t *)_FPR_D[m_Opcode.fd], &*(float *)_FPR_S[m_Opcode.fs], *_RoundingModel); } void R4300iOp::COP1_S_CMP() @@ -2554,7 +2514,7 @@ void R4300iOp::COP1_S_CMP() { if (bHaveDebugger()) { - g_Notify->DisplayError(stdstr_f("%s: Nan ?",__FUNCTION__).c_str()); + g_Notify->DisplayError(stdstr_f("%s: Nan ?", __FUNCTION__).c_str()); } less = false; equal = false; @@ -2588,166 +2548,147 @@ void R4300iOp::COP1_S_CMP() } /************************** COP1: D functions ************************/ -__inline void Double_RoundToInteger32(uint32_t * Dest, double * Source) +__inline void Double_RoundToInteger32(uint32_t * Dest, const double * Source, int RoundType) { -#ifdef _M_IX86 - _asm - { - mov esi, [Source] - mov edi, [Dest] - fld qword ptr [esi] - fistp dword ptr [edi] - } -#else - __m128d xmm; +#pragma warning(push) +#pragma warning(disable:4244) //warning C4244: disabe conversion from 'double' to 'uint32_t', possible loss of data - xmm = _mm_load_sd(Source); - *(Dest) = _mm_cvtsd_si32(xmm); -#endif + if (RoundType == FE_TONEAREST) { *Dest = round(*Source); } + if (RoundType == FE_TOWARDZERO) { *Dest = trunc(*Source); } + if (RoundType == FE_UPWARD) { *Dest = ceil(*Source); } + if (RoundType == FE_DOWNWARD) { *Dest = floor(*Source); } + +#pragma warning(pop) } -__inline void Double_RoundToInteger64(uint64_t * Dest, double * Source) +__inline void Double_RoundToInteger64(uint64_t * Dest, const double * Source, int RoundType) { -#ifdef _M_IX86 - _asm - { - mov esi, [Source] - mov edi, [Dest] - fld qword ptr [esi] - fistp qword ptr [edi] - } -#else - __m128d xmm; +#pragma warning(push) +#pragma warning(disable:4244) //warning C4244: disabe conversion from 'double' to 'uint64_t', possible loss of data - xmm = _mm_load_sd(Source); - *(Dest) = _mm_cvtsd_si64(xmm); -#endif + if (RoundType == FE_TONEAREST) { *Dest = round(*Source); } + if (RoundType == FE_TOWARDZERO) { *Dest = trunc(*Source); } + if (RoundType == FE_UPWARD) { *Dest = ceil(*Source); } + if (RoundType == FE_DOWNWARD) { *Dest = floor(*Source); } + +#pragma warning(pop) } void R4300iOp::COP1_D_ADD() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(double *)_FPR_D[m_Opcode.fd] = *(double *)_FPR_D[m_Opcode.fs] + *(double *)_FPR_D[m_Opcode.ft]; } void R4300iOp::COP1_D_SUB() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(double *)_FPR_D[m_Opcode.fd] = *(double *)_FPR_D[m_Opcode.fs] - *(double *)_FPR_D[m_Opcode.ft]; } void R4300iOp::COP1_D_MUL() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(double *)_FPR_D[m_Opcode.fd] = *(double *)_FPR_D[m_Opcode.fs] * *(double *)_FPR_D[m_Opcode.ft]; } void R4300iOp::COP1_D_DIV() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(double *)_FPR_D[m_Opcode.fd] = *(double *)_FPR_D[m_Opcode.fs] / *(double *)_FPR_D[m_Opcode.ft]; } void R4300iOp::COP1_D_SQRT() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(double *)_FPR_D[m_Opcode.fd] = (double)sqrt(*(double *)_FPR_D[m_Opcode.fs]); } void R4300iOp::COP1_D_ABS() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(double *)_FPR_D[m_Opcode.fd] = fabs(*(double *)_FPR_D[m_Opcode.fs]); } void R4300iOp::COP1_D_MOV() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(int64_t *)_FPR_D[m_Opcode.fd] = *(int64_t *)_FPR_D[m_Opcode.fs]; } void R4300iOp::COP1_D_NEG() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(double *)_FPR_D[m_Opcode.fd] = (*(double *)_FPR_D[m_Opcode.fs] * -1.0); } void R4300iOp::COP1_D_TRUNC_L() { //added by Witten TEST_COP1_USABLE_EXCEPTION(); - _controlfp(RC_CHOP, _MCW_RC); - Double_RoundToInteger64(&*(uint64_t *)_FPR_S[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs]); + Double_RoundToInteger64(&*(uint64_t *)_FPR_S[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs], FE_TOWARDZERO); } void R4300iOp::COP1_D_CEIL_L() { //added by Witten TEST_COP1_USABLE_EXCEPTION(); - _controlfp(RC_UP, _MCW_RC); - Double_RoundToInteger64(&*(uint64_t *)_FPR_S[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs]); + Double_RoundToInteger64(&*(uint64_t *)_FPR_S[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs], FE_UPWARD); } void R4300iOp::COP1_D_FLOOR_L() { //added by Witten TEST_COP1_USABLE_EXCEPTION(); - _controlfp(_RC_DOWN, _MCW_RC); - Double_RoundToInteger64(&*(uint64_t *)_FPR_D[m_Opcode.fd], &*(double *)_FPR_S[m_Opcode.fs]); + Double_RoundToInteger64(&*(uint64_t *)_FPR_D[m_Opcode.fd], &*(double *)_FPR_S[m_Opcode.fs], FE_DOWNWARD); } void R4300iOp::COP1_D_ROUND_W() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(_RC_NEAR, _MCW_RC); - Double_RoundToInteger32(&*(uint32_t *)_FPR_S[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs]); + Double_RoundToInteger32(&*(uint32_t *)_FPR_S[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs], FE_TONEAREST); } void R4300iOp::COP1_D_TRUNC_W() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(RC_CHOP, _MCW_RC); - Double_RoundToInteger32(&*(uint32_t *)_FPR_S[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs]); + Double_RoundToInteger32(&*(uint32_t *)_FPR_S[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs], FE_TOWARDZERO); } void R4300iOp::COP1_D_CEIL_W() { //added by Witten TEST_COP1_USABLE_EXCEPTION(); - _controlfp(RC_UP, _MCW_RC); - Double_RoundToInteger32(&*(uint32_t *)_FPR_S[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs]); + Double_RoundToInteger32(&*(uint32_t *)_FPR_S[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs], FE_UPWARD); } void R4300iOp::COP1_D_FLOOR_W() { //added by Witten TEST_COP1_USABLE_EXCEPTION(); - _controlfp(_RC_DOWN, _MCW_RC); - Double_RoundToInteger32(&*(uint32_t *)_FPR_D[m_Opcode.fd], &*(double *)_FPR_S[m_Opcode.fs]); + Double_RoundToInteger32(&*(uint32_t *)_FPR_D[m_Opcode.fd], &*(double *)_FPR_S[m_Opcode.fs], FE_DOWNWARD); } void R4300iOp::COP1_D_CVT_S() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(float *)_FPR_S[m_Opcode.fd] = (float)*(double *)_FPR_D[m_Opcode.fs]; } void R4300iOp::COP1_D_CVT_W() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); - Double_RoundToInteger32(&*(uint32_t *)_FPR_S[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs]); + Double_RoundToInteger32(&*(uint32_t *)_FPR_S[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs], *_RoundingModel); } void R4300iOp::COP1_D_CVT_L() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); - Double_RoundToInteger64(&*(uint64_t *)_FPR_D[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs]); + Double_RoundToInteger64(&*(uint64_t *)_FPR_D[m_Opcode.fd], &*(double *)_FPR_D[m_Opcode.fs], *_RoundingModel); } void R4300iOp::COP1_D_CMP() @@ -2765,7 +2706,7 @@ void R4300iOp::COP1_D_CMP() { if (bHaveDebugger()) { - g_Notify->DisplayError(stdstr_f("%s: Nan ?",__FUNCTION__).c_str()); + g_Notify->DisplayError(stdstr_f("%s: Nan ?", __FUNCTION__).c_str()); } less = false; equal = false; @@ -2802,14 +2743,14 @@ void R4300iOp::COP1_D_CMP() void R4300iOp::COP1_W_CVT_S() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(float *)_FPR_S[m_Opcode.fd] = (float)*(int32_t *)_FPR_S[m_Opcode.fs]; } void R4300iOp::COP1_W_CVT_D() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(double *)_FPR_D[m_Opcode.fd] = (double)*(int32_t *)_FPR_S[m_Opcode.fs]; } @@ -2817,14 +2758,14 @@ void R4300iOp::COP1_W_CVT_D() void R4300iOp::COP1_L_CVT_S() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(float *)_FPR_S[m_Opcode.fd] = (float)*(int64_t *)_FPR_D[m_Opcode.fs]; } void R4300iOp::COP1_L_CVT_D() { TEST_COP1_USABLE_EXCEPTION(); - _controlfp(*_RoundingModel, _MCW_RC); + fesetround(*_RoundingModel); *(double *)_FPR_D[m_Opcode.fd] = (double)*(int64_t *)_FPR_D[m_Opcode.fs]; } diff --git a/Source/Project64-core/N64System/Mips/RegisterClass.cpp b/Source/Project64-core/N64System/Mips/RegisterClass.cpp index 18657b827..574b3df60 100644 --- a/Source/Project64-core/N64System/Mips/RegisterClass.cpp +++ b/Source/Project64-core/N64System/Mips/RegisterClass.cpp @@ -60,7 +60,7 @@ float ** CSystemRegisters::_FPR_S; double ** CSystemRegisters::_FPR_D; uint32_t * CSystemRegisters::_FPCR = NULL; uint32_t * CSystemRegisters::_LLBit = NULL; -ROUNDING_MODE * CSystemRegisters::_RoundingModel = NULL; +int32_t * CSystemRegisters::_RoundingModel = NULL; CP0registers::CP0registers(uint32_t * _CP0) : INDEX_REGISTER(_CP0[0]), @@ -240,7 +240,7 @@ void CRegisters::Reset() memset(m_FPCR, 0, sizeof(m_FPCR)); m_HI.DW = 0; m_LO.DW = 0; - m_RoundingModel = ROUND_NEAR; + m_RoundingModel = FE_TONEAREST; m_LLBit = 0; diff --git a/Source/Project64-core/N64System/Mips/RegisterClass.h b/Source/Project64-core/N64System/Mips/RegisterClass.h index 9f6a4befa..01b2f9f1a 100644 --- a/Source/Project64-core/N64System/Mips/RegisterClass.h +++ b/Source/Project64-core/N64System/Mips/RegisterClass.h @@ -482,14 +482,6 @@ enum SI_STATUS_INTERRUPT = 0x1000, }; -enum ROUNDING_MODE -{ - ROUND_NEAR = 0x00000000, // _RC_NEAR - ROUND_DOWN = 0x00000100, // _RC_DOWN - ROUND_UP = 0x00000200, // _RC_UP - ROUND_CHOP = 0x00000300, // _RC_CHOP -}; - class CRegName { public: @@ -514,7 +506,7 @@ protected: static double ** _FPR_D; static uint32_t * _FPCR; static uint32_t * _LLBit; - static ROUNDING_MODE * _RoundingModel; + static int32_t * _RoundingModel; }; class CN64System; @@ -549,7 +541,7 @@ public: //Floating point registers/information uint32_t m_FPCR[32]; - ROUNDING_MODE m_RoundingModel; + int32_t m_RoundingModel; MIPS_DWORD m_FPR[32]; float * m_FPR_S[32]; double * m_FPR_D[32]; diff --git a/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp index 57f704e5d..000133433 100644 --- a/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/RecompilerOps.cpp @@ -2300,7 +2300,7 @@ void CRecompilerOps::DADDIU() BeforeCallDirect(m_RegWorkingSet); MoveConstToVariable(m_Opcode.Hex, &R4300iOp::m_Opcode.Hex, "R4300iOp::m_Opcode.Hex"); - Call_Direct(R4300iOp::DADDIU, "R4300iOp::DADDIU"); + Call_Direct((void *)R4300iOp::DADDIU, "R4300iOp::DADDIU"); AfterCallDirect(m_RegWorkingSet); } @@ -3191,7 +3191,7 @@ void CRecompilerOps::SPECIAL_DMULT() BeforeCallDirect(m_RegWorkingSet); MoveConstToVariable(m_Opcode.Hex, &R4300iOp::m_Opcode.Hex, "R4300iOp::m_Opcode.Hex"); - Call_Direct(R4300iOp::SPECIAL_DMULT, "R4300iOp::SPECIAL_DMULT"); + Call_Direct((void *)R4300iOp::SPECIAL_DMULT, "R4300iOp::SPECIAL_DMULT"); AfterCallDirect(m_RegWorkingSet); } @@ -3203,7 +3203,7 @@ void CRecompilerOps::SPECIAL_DMULTU() UnMap_GPR(m_Opcode.rt, true); BeforeCallDirect(m_RegWorkingSet); MoveConstToVariable(m_Opcode.Hex, &R4300iOp::m_Opcode.Hex, "R4300iOp::m_Opcode.Hex"); - Call_Direct(R4300iOp::SPECIAL_DMULTU, "R4300iOp::SPECIAL_DMULTU"); + Call_Direct((void *)R4300iOp::SPECIAL_DMULTU, "R4300iOp::SPECIAL_DMULTU"); AfterCallDirect(m_RegWorkingSet); #ifdef toremove @@ -3282,7 +3282,7 @@ void CRecompilerOps::SPECIAL_DDIV() UnMap_GPR(m_Opcode.rt, true); BeforeCallDirect(m_RegWorkingSet); MoveConstToVariable(m_Opcode.Hex, &R4300iOp::m_Opcode.Hex, "R4300iOp::m_Opcode.Hex"); - Call_Direct(R4300iOp::SPECIAL_DDIV, "R4300iOp::SPECIAL_DDIV"); + Call_Direct((void *)R4300iOp::SPECIAL_DDIV, "R4300iOp::SPECIAL_DDIV"); AfterCallDirect(m_RegWorkingSet); } @@ -3294,7 +3294,7 @@ void CRecompilerOps::SPECIAL_DDIVU() UnMap_GPR(m_Opcode.rt, true); BeforeCallDirect(m_RegWorkingSet); MoveConstToVariable(m_Opcode.Hex, &R4300iOp::m_Opcode.Hex, "R4300iOp::m_Opcode.Hex"); - Call_Direct(R4300iOp::SPECIAL_DDIVU, "R4300iOp::SPECIAL_DDIVU"); + Call_Direct((void *)R4300iOp::SPECIAL_DDIVU, "R4300iOp::SPECIAL_DDIVU"); AfterCallDirect(m_RegWorkingSet); } @@ -5563,7 +5563,7 @@ void CRecompilerOps::COP0_CO_ERET(void) CPU_Message(" %X %s", m_CompilePC, R4300iOpcodeName(m_Opcode.Hex, m_CompilePC)); m_RegWorkingSet.WriteBackRegisters(); - Call_Direct(compiler_COP0_CO_ERET, "compiler_COP0_CO_ERET"); + Call_Direct((void *)compiler_COP0_CO_ERET, "compiler_COP0_CO_ERET"); UpdateCounters(m_RegWorkingSet, true, true); m_Section->CompileExit(m_CompilePC, (uint32_t)-1, m_RegWorkingSet, CExitInfo::Normal, true, NULL); @@ -5573,11 +5573,12 @@ void CRecompilerOps::COP0_CO_ERET(void) /************************** FPU Options **************************/ void CRecompilerOps::ChangeDefaultRoundingModel() { - switch ((_FPCR[31] & 3)) { - case 0: *_RoundingModel = ROUND_NEAR; break; - case 1: *_RoundingModel = ROUND_CHOP; break; - case 2: *_RoundingModel = ROUND_UP; break; - case 3: *_RoundingModel = ROUND_DOWN; break; + switch ((_FPCR[31] & 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; } } @@ -5746,7 +5747,7 @@ void CRecompilerOps::COP1_CT() MoveX86regToVariable(Map_TempReg(x86_Any, m_Opcode.rt, false), &_FPCR[m_Opcode.fs], CRegName::FPR_Ctrl[m_Opcode.fs]); } BeforeCallDirect(m_RegWorkingSet); - Call_Direct(ChangeDefaultRoundingModel, "ChangeDefaultRoundingModel"); + Call_Direct((void *)ChangeDefaultRoundingModel, "ChangeDefaultRoundingModel"); AfterCallDirect(m_RegWorkingSet); m_RegWorkingSet.SetRoundingModel(CRegInfo::RoundUnknown); } @@ -6578,7 +6579,7 @@ void CRecompilerOps::UnknownOpcode() m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() - g_System->CountPerOp()); MoveConstToVariable(m_Opcode.Hex, &R4300iOp::m_Opcode.Hex, "R4300iOp::m_Opcode.Hex"); - Call_Direct(R4300iOp::UnknownOpcode, "R4300iOp::UnknownOpcode"); + Call_Direct((void *)R4300iOp::UnknownOpcode, "R4300iOp::UnknownOpcode"); Ret(); if (m_NextInstruction == NORMAL) { m_NextInstruction = END_BLOCK; } } @@ -6712,7 +6713,7 @@ void CRecompilerOps::OverflowDelaySlot(bool TestTimer) } PushImm32("g_System->CountPerOp()", g_System->CountPerOp()); - Call_Direct(CInterpreterCPU::ExecuteOps, "CInterpreterCPU::ExecuteOps"); + Call_Direct((void *)CInterpreterCPU::ExecuteOps, "CInterpreterCPU::ExecuteOps"); AddConstToX86Reg(x86_ESP, 4); if (g_System->bFastSP() && g_Recompiler) diff --git a/Source/Project64-core/N64System/Recompiler/RegInfo.cpp b/Source/Project64-core/N64System/Recompiler/RegInfo.cpp index 1d3b705b8..fec38842c 100644 --- a/Source/Project64-core/N64System/Recompiler/RegInfo.cpp +++ b/Source/Project64-core/N64System/Recompiler/RegInfo.cpp @@ -160,8 +160,12 @@ void CRegInfo::FixRoundModel(FPU_ROUND RoundMethod) if (RoundMethod == RoundDefault) { + static const unsigned int msRound[4] = { _RC_NEAR, _RC_CHOP, _RC_UP, _RC_DOWN }; + x86Reg RoundReg = Map_TempReg(x86_Any, -1, false); MoveVariableToX86reg(&g_Reg->m_RoundingModel, "m_RoundingModel", RoundReg); + MoveVariableDispToX86Reg((void *)&msRound[0], "msRound", RoundReg, RoundReg, Multip_x4); + ShiftLeftSignImmed(RoundReg, 2); OrX86RegToX86Reg(reg, RoundReg); SetX86Protected(RoundReg, false);