📄 softfloat.c
字号:
return float32_default_nan;
}
return packFloat32( zSign, 0xFF, 0 );
}
if ( bExp == 0xFF ) {
if ( bSig ) return propagateFloat32NaN( a, b );
return packFloat32( zSign, 0, 0 );
}
if ( bExp == 0 ) {
if ( bSig == 0 ) {
if ( ( aExp | aSig ) == 0 ) {
float_raise( float_flag_invalid );
return float32_default_nan;
}
float_raise( float_flag_divbyzero );
return packFloat32( zSign, 0xFF, 0 );
}
normalizeFloat32Subnormal( bSig, &bExp, &bSig );
}
if ( aExp == 0 ) {
if ( aSig == 0 ) return packFloat32( zSign, 0, 0 );
normalizeFloat32Subnormal( aSig, &aExp, &aSig );
}
zExp = aExp - bExp + 0x7D;
aSig = ( aSig | 0x00800000 )<<7;
bSig = ( bSig | 0x00800000 )<<8;
if ( bSig <= ( aSig + aSig ) ) {
aSig >>= 1;
++zExp;
}
zSig = estimateDiv64To32( aSig, 0, bSig );
if ( ( zSig & 0x3F ) <= 2 ) {
mul32To64( bSig, zSig, &term0, &term1 );
sub64( aSig, 0, term0, term1, &rem0, &rem1 );
while ( (sbits32) rem0 < 0 ) {
--zSig;
add64( rem0, rem1, 0, bSig, &rem0, &rem1 );
}
zSig |= ( rem1 != 0 );
}
return roundAndPackFloat32( zSign, zExp, zSig );
}
// for FPU testbench
float32 float32_div( float32 a, float32 b ){
float32 output = float32_div2( a, b );
/*printf("\t\t\twait for CLK_PERIOD; start_i <= '1';\n");
printf("\t\t\topa_i <= X\"%x\";\n",a);
printf("\t\t\topb_i <= X\"%x\";\n",b);
printf("\t\t\tfpu_op_i <= \"011\";\n");
printf("\t\t\trmode_i <= \""); print_roundmode(); printf("\";\n");
printf("\t\t\twait for CLK_PERIOD; start_i <= '0'; wait until ready_o='1';\n");
printf("\t\t\tassert output_o=x\"%x\"\n" ,output);
printf("\t\t\treport \"Error!!!\"\n");
printf("\t\t\tseverity failure;\n\n");*/
printf("%x \n",a);
printf("%x \n",b);
printf("011\n");
print_roundmode(); printf("\n");
printf("%x \n\n", output);
return output;
}
/*----------------------------------------------------------------------------
| Returns the remainder of the single-precision floating-point value `a'
| with respect to the corresponding value `b'. The operation is performed
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
float32 float32_rem( float32 a, float32 b )
{
flag aSign, bSign, zSign;
int16 aExp, bExp, expDiff;
bits32 aSig, bSig, q, allZero, alternateASig;
sbits32 sigMean;
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
bSig = extractFloat32Frac( b );
bExp = extractFloat32Exp( b );
bSign = extractFloat32Sign( b );
if ( aExp == 0xFF ) {
if ( aSig || ( ( bExp == 0xFF ) && bSig ) ) {
return propagateFloat32NaN( a, b );
}
float_raise( float_flag_invalid );
return float32_default_nan;
}
if ( bExp == 0xFF ) {
if ( bSig ) return propagateFloat32NaN( a, b );
return a;
}
if ( bExp == 0 ) {
if ( bSig == 0 ) {
float_raise( float_flag_invalid );
return float32_default_nan;
}
normalizeFloat32Subnormal( bSig, &bExp, &bSig );
}
if ( aExp == 0 ) {
if ( aSig == 0 ) return a;
normalizeFloat32Subnormal( aSig, &aExp, &aSig );
}
expDiff = aExp - bExp;
aSig = ( aSig | 0x00800000 )<<8;
bSig = ( bSig | 0x00800000 )<<8;
if ( expDiff < 0 ) {
if ( expDiff < -1 ) return a;
aSig >>= 1;
}
q = ( bSig <= aSig );
if ( q ) aSig -= bSig;
expDiff -= 32;
while ( 0 < expDiff ) {
q = estimateDiv64To32( aSig, 0, bSig );
q = ( 2 < q ) ? q - 2 : 0;
aSig = - ( ( bSig>>2 ) * q );
expDiff -= 30;
}
expDiff += 32;
if ( 0 < expDiff ) {
q = estimateDiv64To32( aSig, 0, bSig );
q = ( 2 < q ) ? q - 2 : 0;
q >>= 32 - expDiff;
bSig >>= 2;
aSig = ( ( aSig>>1 )<<( expDiff - 1 ) ) - bSig * q;
}
else {
aSig >>= 2;
bSig >>= 2;
}
do {
alternateASig = aSig;
++q;
aSig -= bSig;
} while ( 0 <= (sbits32) aSig );
sigMean = aSig + alternateASig;
if ( ( sigMean < 0 ) || ( ( sigMean == 0 ) && ( q & 1 ) ) ) {
aSig = alternateASig;
}
zSign = ( (sbits32) aSig < 0 );
if ( zSign ) aSig = - aSig;
return normalizeRoundAndPackFloat32( aSign ^ zSign, bExp, aSig );
}
/*----------------------------------------------------------------------------
| Returns the square root of the single-precision floating-point value `a'.
| The operation is performed according to the IEC/IEEE Standard for Binary
| Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
float32 float32_sqrt2( float32 a )
{
flag aSign;
int16 aExp, zExp;
bits32 aSig, zSig, rem0, rem1, term0, term1;
aSig = extractFloat32Frac( a );
aExp = extractFloat32Exp( a );
aSign = extractFloat32Sign( a );
if ( aExp == 0xFF ) {
if ( aSig ) return propagateFloat32NaN( a, 0 );
if ( ! aSign ) return a;
float_raise( float_flag_invalid );
return float32_default_nan;
}
if ( aSign ) {
if ( ( aExp | aSig ) == 0 ) return a;
float_raise( float_flag_invalid );
return float32_default_nan;
}
if ( aExp == 0 ) {
if ( aSig == 0 ) return 0;
normalizeFloat32Subnormal( aSig, &aExp, &aSig );
}
zExp = ( ( aExp - 0x7F )>>1 ) + 0x7E;
aSig = ( aSig | 0x00800000 )<<8;
zSig = estimateSqrt32( aExp, aSig ) + 2;
if ( ( zSig & 0x7F ) <= 5 ) {
if ( zSig < 2 ) {
zSig = 0x7FFFFFFF;
goto roundAndPack;
}
else {
aSig >>= aExp & 1;
mul32To64( zSig, zSig, &term0, &term1 );
sub64( aSig, 0, term0, term1, &rem0, &rem1 );
while ( (sbits32) rem0 < 0 ) {
--zSig;
shortShift64Left( 0, zSig, 1, &term0, &term1 );
term1 |= 1;
add64( rem0, rem1, term0, term1, &rem0, &rem1 );
}
zSig |= ( ( rem0 | rem1 ) != 0 );
}
}
shift32RightJamming( zSig, 1, &zSig );
roundAndPack:
return roundAndPackFloat32( 0, zExp, zSig );
}
// for FPU testbench
float32 float32_sqrt( float32 a ){
float32 output = float32_sqrt2( a );
/*printf("\t\t\twait for CLK_PERIOD; start_i <= '1';\n");
if(a==0) printf("\t\t\topa_i <= X\"00000000\";\n"); else printf("\t\t\topa_i <= X\"%x\";\n",a);
//printf("\t\t\topb_i <= X\"%x\";\n",b);
printf("\t\t\tfpu_op_i <= \"100\";\n");
printf("\t\t\trmode_i <= \""); print_roundmode(); printf("\";\n");
printf("\t\t\twait for CLK_PERIOD; start_i <= '0'; wait until ready_o='1';\n");
printf("\t\t\tassert output_o=x\"%x\"\n" ,output);
printf("\t\t\treport \"Error!!!\"\n");
printf("\t\t\tseverity failure;\n\n");*/
printf("%x \n",a);
printf("00000000 \n");
printf("100\n");
print_roundmode(); printf("\n");
printf("%x \n\n", output);
return output;
}
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is equal to
| the corresponding value `b', and 0 otherwise. The comparison is performed
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float32_eq( float32 a, float32 b )
{
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
) {
if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
float_raise( float_flag_invalid );
}
return 0;
}
return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
}
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is less than
| or equal to the corresponding value `b', and 0 otherwise. The comparison
| is performed according to the IEC/IEEE Standard for Binary Floating-Point
| Arithmetic.
*----------------------------------------------------------------------------*/
flag float32_le( float32 a, float32 b )
{
flag aSign, bSign;
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
) {
float_raise( float_flag_invalid );
return 0;
}
aSign = extractFloat32Sign( a );
bSign = extractFloat32Sign( b );
if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
return ( a == b ) || ( aSign ^ ( a < b ) );
}
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is less than
| the corresponding value `b', and 0 otherwise. The comparison is performed
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float32_lt( float32 a, float32 b )
{
flag aSign, bSign;
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
) {
float_raise( float_flag_invalid );
return 0;
}
aSign = extractFloat32Sign( a );
bSign = extractFloat32Sign( b );
if ( aSign != bSign ) return aSign && ( (bits32) ( ( a | b )<<1 ) != 0 );
return ( a != b ) && ( aSign ^ ( a < b ) );
}
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is equal to
| the corresponding value `b', and 0 otherwise. The invalid exception is
| raised if either operand is a NaN. Otherwise, the comparison is performed
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float32_eq_signaling( float32 a, float32 b )
{
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
) {
float_raise( float_flag_invalid );
return 0;
}
return ( a == b ) || ( (bits32) ( ( a | b )<<1 ) == 0 );
}
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is less than or
| equal to the corresponding value `b', and 0 otherwise. Quiet NaNs do not
| cause an exception. Otherwise, the comparison is performed according to the
| IEC/IEEE Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float32_le_quiet( float32 a, float32 b )
{
flag aSign, bSign;
int16 aExp, bExp;
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
) {
if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
float_raise( float_flag_invalid );
}
return 0;
}
aSign = extractFloat32Sign( a );
bSign = extractFloat32Sign( b );
if ( aSign != bSign ) return aSign || ( (bits32) ( ( a | b )<<1 ) == 0 );
return ( a == b ) || ( aSign ^ ( a < b ) );
}
/*----------------------------------------------------------------------------
| Returns 1 if the single-precision floating-point value `a' is less than
| the corresponding value `b', and 0 otherwise. Quiet NaNs do not cause an
| exception. Otherwise, the comparison is performed according to the IEC/IEEE
| Standard for Binary Floating-Point Arithmetic.
*----------------------------------------------------------------------------*/
flag float32_lt_quiet( float32 a, float32 b )
{
flag aSign, bSign;
if ( ( ( extractFloat32Exp( a ) == 0xFF ) && extractFloat32Frac( a ) )
|| ( ( extractFloat32Exp( b ) == 0xFF ) && extractFloat32Frac( b ) )
) {
if ( float32_is_signaling_nan( a ) || float32_is_signaling_nan( b ) ) {
float_raise( float_flag_invalid );
}
return 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -