FPU: replace check* macros by functions

v2: remove useless return after function call
This commit is contained in:
Gregory Hainaut 2016-09-07 19:12:34 +02:00
parent 9648e25018
commit d39f17bda3
1 changed files with 53 additions and 45 deletions

View File

@ -74,23 +74,28 @@
//****************************************************************
// If we have an infinity value, then Overflow has occured.
#define checkOverflow(xReg, cFlagsToSet, shouldReturn) { \
if ( ( xReg & ~0x80000000 ) == PosInfinity ) { \
/*Console.Warning( "FPU OVERFLOW!: Changing to +/-Fmax!!!!!!!!!!!!\n" );*/ \
xReg = ( xReg & 0x80000000 ) | posFmax; \
_ContVal_ |= cFlagsToSet; \
if ( shouldReturn ) { return; } \
} \
bool checkOverflow(u32& xReg, u32 cFlagsToSet)
{
if ( (xReg & ~0x80000000) == PosInfinity ) {
/*Console.Warning( "FPU OVERFLOW!: Changing to +/-Fmax!!!!!!!!!!!!\n" );*/
xReg = (xReg & 0x80000000) | posFmax;
_ContVal_ |= (cFlagsToSet);
return true;
}
return false;
}
// If we have a denormal value, then Underflow has occured.
#define checkUnderflow(xReg, cFlagsToSet, shouldReturn) { \
if ( ( ( xReg & 0x7F800000 ) == 0 ) && ( ( xReg & 0x007FFFFF ) != 0 ) ) { \
/*Console.Warning( "FPU UNDERFLOW!: Changing to +/-0!!!!!!!!!!!!\n" );*/ \
xReg &= 0x80000000; \
_ContVal_ |= cFlagsToSet; \
if ( shouldReturn ) { return; } \
} \
bool checkUnderflow(u32& xReg, u32 cFlagsToSet) {
if ( ( (xReg & 0x7F800000) == 0 ) && ( (xReg & 0x007FFFFF) != 0 ) ) {
/*Console.Warning( "FPU UNDERFLOW!: Changing to +/-0!!!!!!!!!!!!\n" );*/
xReg &= 0x80000000;
_ContVal_ |= (cFlagsToSet);
return true;
}
return false;
}
/* Checks if Divide by Zero will occur. (z/y = x)
@ -98,12 +103,15 @@
cFlagsToSet2 = Flags to set if (z == 0)
( Denormals are counted as "0" )
*/
#define checkDivideByZero(xReg, yDivisorReg, zDividendReg, cFlagsToSet1, cFlagsToSet2, shouldReturn) { \
if ( ( yDivisorReg & 0x7F800000 ) == 0 ) { \
_ContVal_ |= ( ( zDividendReg & 0x7F800000 ) == 0 ) ? cFlagsToSet2 : cFlagsToSet1; \
xReg = ( ( yDivisorReg ^ zDividendReg ) & 0x80000000 ) | posFmax; \
if ( shouldReturn ) { return; } \
} \
bool checkDivideByZero(u32& xReg, u32 yDivisorReg, u32 zDividendReg, u32 cFlagsToSet1, u32 cFlagsToSet2) {
if ( (yDivisorReg & 0x7F800000) == 0 ) {
_ContVal_ |= ( (zDividendReg & 0x7F800000) == 0 ) ? cFlagsToSet2 : cFlagsToSet1;
xReg = ( (yDivisorReg ^ zDividendReg) & 0x80000000 ) | posFmax;
return true;
}
return false;
}
/* Clears the "Cause Flags" of the Control/Status Reg
@ -180,14 +188,14 @@ void ABS_S() {
void ADD_S() {
_FdValf_ = fpuDouble( _FsValUl_ ) + fpuDouble( _FtValUl_ );
checkOverflow( _FdValUl_, FPUflagO | FPUflagSO, 1 );
checkUnderflow( _FdValUl_, FPUflagU | FPUflagSU, 1 );
if (checkOverflow( _FdValUl_, FPUflagO | FPUflagSO)) return;
checkUnderflow( _FdValUl_, FPUflagU | FPUflagSU);
}
void ADDA_S() {
_FAValf_ = fpuDouble( _FsValUl_ ) + fpuDouble( _FtValUl_ );
checkOverflow( _FAValUl_, FPUflagO | FPUflagSO, 1 );
checkUnderflow( _FAValUl_, FPUflagU | FPUflagSU, 1 );
if (checkOverflow( _FAValUl_, FPUflagO | FPUflagSO)) return;
checkUnderflow( _FAValUl_, FPUflagU | FPUflagSU);
}
void BC1F() {
@ -248,10 +256,10 @@ void CVT_W() {
}
void DIV_S() {
checkDivideByZero( _FdValUl_, _FtValUl_, _FsValUl_, FPUflagD | FPUflagSD, FPUflagI | FPUflagSI, 1 );
if (checkDivideByZero( _FdValUl_, _FtValUl_, _FsValUl_, FPUflagD | FPUflagSD, FPUflagI | FPUflagSI)) return;
_FdValf_ = fpuDouble( _FsValUl_ ) / fpuDouble( _FtValUl_ );
checkOverflow( _FdValUl_, 0, 1);
checkUnderflow( _FdValUl_, 0, 1 );
if (checkOverflow( _FdValUl_, 0)) return;
checkUnderflow( _FdValUl_, 0);
}
/* The Instruction Set manual has an overly complicated way of
@ -262,14 +270,14 @@ void MADD_S() {
FPRreg temp;
temp.f = fpuDouble( _FsValUl_ ) * fpuDouble( _FtValUl_ );
_FdValf_ = fpuDouble( _FAValUl_ ) + fpuDouble( temp.UL );
checkOverflow( _FdValUl_, FPUflagO | FPUflagSO, 1 );
checkUnderflow( _FdValUl_, FPUflagU | FPUflagSU, 1 );
if (checkOverflow( _FdValUl_, FPUflagO | FPUflagSO)) return;
checkUnderflow( _FdValUl_, FPUflagU | FPUflagSU);
}
void MADDA_S() {
_FAValf_ += fpuDouble( _FsValUl_ ) * fpuDouble( _FtValUl_ );
checkOverflow( _FAValUl_, FPUflagO | FPUflagSO, 1 );
checkUnderflow( _FAValUl_, FPUflagU | FPUflagSU, 1 );
if (checkOverflow( _FAValUl_, FPUflagO | FPUflagSO)) return;
checkUnderflow( _FAValUl_, FPUflagU | FPUflagSU);
}
void MAX_S() {
@ -295,14 +303,14 @@ void MSUB_S() {
FPRreg temp;
temp.f = fpuDouble( _FsValUl_ ) * fpuDouble( _FtValUl_ );
_FdValf_ = fpuDouble( _FAValUl_ ) - fpuDouble( temp.UL );
checkOverflow( _FdValUl_, FPUflagO | FPUflagSO, 1 );
checkUnderflow( _FdValUl_, FPUflagU | FPUflagSU, 1 );
if (checkOverflow( _FdValUl_, FPUflagO | FPUflagSO)) return;
checkUnderflow( _FdValUl_, FPUflagU | FPUflagSU);
}
void MSUBA_S() {
_FAValf_ -= fpuDouble( _FsValUl_ ) * fpuDouble( _FtValUl_ );
checkOverflow( _FAValUl_, FPUflagO | FPUflagSO, 1 );
checkUnderflow( _FAValUl_, FPUflagU | FPUflagSU, 1 );
if (checkOverflow( _FAValUl_, FPUflagO | FPUflagSO)) return;
checkUnderflow( _FAValUl_, FPUflagU | FPUflagSU);
}
void MTC1() {
@ -311,14 +319,14 @@ void MTC1() {
void MUL_S() {
_FdValf_ = fpuDouble( _FsValUl_ ) * fpuDouble( _FtValUl_ );
checkOverflow( _FdValUl_, FPUflagO | FPUflagSO, 1 );
checkUnderflow( _FdValUl_, FPUflagU | FPUflagSU, 1 );
if (checkOverflow( _FdValUl_, FPUflagO | FPUflagSO)) return;
checkUnderflow( _FdValUl_, FPUflagU | FPUflagSU);
}
void MULA_S() {
_FAValf_ = fpuDouble( _FsValUl_ ) * fpuDouble( _FtValUl_ );
checkOverflow( _FAValUl_, FPUflagO | FPUflagSO, 1 );
checkUnderflow( _FAValUl_, FPUflagU | FPUflagSU, 1 );
if (checkOverflow( _FAValUl_, FPUflagO | FPUflagSO)) return;
checkUnderflow( _FAValUl_, FPUflagU | FPUflagSU);
}
void NEG_S() {
@ -340,8 +348,8 @@ void RSQRT_S() {
}
else { _FdValf_ = fpuDouble( _FsValUl_ ) / sqrt( fpuDouble( _FtValUl_ ) ); } // Ft is positive and not zero
checkOverflow( _FdValUl_, 0, 1 );
checkUnderflow( _FdValUl_, 0, 1 );
if (checkOverflow( _FdValUl_, 0)) return;
checkUnderflow( _FdValUl_, 0);
}
void SQRT_S() {
@ -357,14 +365,14 @@ void SQRT_S() {
void SUB_S() {
_FdValf_ = fpuDouble( _FsValUl_ ) - fpuDouble( _FtValUl_ );
checkOverflow( _FdValUl_, FPUflagO | FPUflagSO, 1 );
checkUnderflow( _FdValUl_, FPUflagU | FPUflagSU, 1 );
if (checkOverflow( _FdValUl_, FPUflagO | FPUflagSO)) return;
checkUnderflow( _FdValUl_, FPUflagU | FPUflagSU);
}
void SUBA_S() {
_FAValf_ = fpuDouble( _FsValUl_ ) - fpuDouble( _FtValUl_ );
checkOverflow( _FAValUl_, FPUflagO | FPUflagSO, 1 );
checkUnderflow( _FAValUl_, FPUflagU | FPUflagSU, 1 );
if (checkOverflow( _FAValUl_, FPUflagO | FPUflagSO)) return;
checkUnderflow( _FAValUl_, FPUflagU | FPUflagSU);
}
} // End Namespace COP1