[Project64] Get the rounding code to use fesetround

This commit is contained in:
zilmar 2016-01-17 17:34:05 +11:00
parent 3791525d74
commit f87c2051b5
5 changed files with 120 additions and 182 deletions

View File

@ -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];
}

View File

@ -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;

View File

@ -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];

View File

@ -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)

View File

@ -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);