Skip to content

Commit

Permalink
Softfloat update (from Previous)
Browse files Browse the repository at this point in the history
  • Loading branch information
tonioni committed Apr 10, 2021
1 parent 3323eb1 commit 2337abe
Show file tree
Hide file tree
Showing 6 changed files with 379 additions and 119 deletions.
5 changes: 2 additions & 3 deletions fpp.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,7 @@ FPP_AB fpp_cosh;
FPP_ABP fpp_neg;
FPP_AB fpp_acos;
FPP_AB fpp_cos;
FPP_ABC fpp_sincos;
FPP_AB fpp_getexp;
FPP_AB fpp_getman;
FPP_ABP fpp_div;
Expand Down Expand Up @@ -3109,9 +3110,7 @@ static bool fp_arithmetic(fpdata *src, fpdata *dst, int extra)
case 0x35: /* FSINCOS */
case 0x36: /* FSINCOS */
case 0x37: /* FSINCOS */
fpp_cos(dst, src);
regs.fp[extra & 7] = *dst;
fpp_sin(dst, src);
fpp_sincos(dst, src, &regs.fp[extra & 7]);
break;
case 0x38: /* FCMP */
case 0x39:
Expand Down
5 changes: 5 additions & 0 deletions fpp_softfloat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -511,6 +511,10 @@ static void fp_cos(fpdata *a, fpdata *b)
{
a->fpx = floatx80_cos(b->fpx, &fs);
}
static void fp_sincos(fpdata * a, fpdata * b, fpdata * c)
{
a->fpx = floatx80_sincos(b->fpx, &c->fpx, &fs);
}

/* Functions for converting between float formats */
static const fptype twoto32 = 4294967296.0;
Expand Down Expand Up @@ -814,6 +818,7 @@ void fp_init_softfloat(int fpu_model)
fpp_neg = fp_neg;
fpp_acos = fp_acos;
fpp_cos = fp_cos;
fpp_sincos = fp_sincos;
fpp_getexp = fp_getexp;
fpp_getman = fp_getman;
fpp_div = fp_div;
Expand Down
2 changes: 2 additions & 0 deletions include/fpp.h
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ typedef void (*FPP_ABQS)(fpdata*, fpdata*, uae_u64*, uae_u8*);
typedef void (*FPP_AB)(fpdata*, fpdata*);
typedef void (*FPP_ABP)(fpdata*, fpdata*, int);
typedef void (*FPP_A)(fpdata*);
typedef void (*FPP_ABC)(fpdata*, fpdata*, fpdata*);

typedef bool (*FPP_IS)(fpdata*);
typedef void (*FPP_SET_MODE)(uae_u32);
Expand Down Expand Up @@ -151,6 +152,7 @@ extern FPP_AB fpp_cosh;
extern FPP_ABP fpp_neg;
extern FPP_AB fpp_acos;
extern FPP_AB fpp_cos;
extern FPP_ABC fpp_sincos;
extern FPP_AB fpp_getexp;
extern FPP_AB fpp_getman;
extern FPP_ABP fpp_div;
Expand Down
224 changes: 108 additions & 116 deletions softfloat/softfloat.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2879,206 +2879,198 @@ floatx80 floatx80_rem(floatx80 a, floatx80 b, float_status *status)

}
#else // 09-01-2017: Modified version for Previous
floatx80 floatx80_rem( floatx80 a, floatx80 b, uint64_t *q, flag *s, float_status *status )
floatx80 floatx80_rem(floatx80 a, floatx80 b, uint64_t* q, flag* s, float_status* status)
{
flag aSign, bSign, zSign;
int32_t aExp, bExp, expDiff;
uint64_t aSig0, aSig1, bSig;
uint64_t qTemp, term0, term1, alternateASig0, alternateASig1;

aSig0 = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
bSig = extractFloatx80Frac( b );
bExp = extractFloatx80Exp( b );
bSign = extractFloatx80Sign( b );

if ( aExp == 0x7FFF ) {
if ( (uint64_t) ( aSig0<<1 )
|| ( ( bExp == 0x7FFF ) && (uint64_t) ( bSig<<1 ) ) ) {
return propagateFloatx80NaN( a, b, status );
aSig0 = extractFloatx80Frac(a);
aExp = extractFloatx80Exp(a);
aSign = extractFloatx80Sign(a);
bSig = extractFloatx80Frac(b);
bExp = extractFloatx80Exp(b);
bSign = extractFloatx80Sign(b);

*s = 0;
*q = 0;

if (aExp == 0x7FFF) {
if ((uint64_t)(aSig0 << 1)
|| ((bExp == 0x7FFF) && (uint64_t)(bSig << 1))) {
return propagateFloatx80NaN(a, b, status);
}
goto invalid;
}
if ( bExp == 0x7FFF ) {
if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b, status );
if (bExp == 0x7FFF) {
if ((uint64_t)(bSig << 1)) return propagateFloatx80NaN(a, b, status);
*s = (aSign != bSign);
*q = 0;
return a;
return normalizeRoundAndPackFloatx80(status->floatx80_rounding_precision, aSign, aExp, aSig0, 0, status);;
}
if ( bExp == 0 ) {
if ( bSig == 0 ) {
if (bExp == 0) {
if (bSig == 0) {
invalid:
float_raise( float_flag_invalid, status );
return floatx80_default_nan(status);
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
}
normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
}
if ( aExp == 0 ) {
#ifdef SOFTFLOAT_68K
if ( aSig0 == 0 ) {
if (aExp == 0) {
if (aSig0 == 0) {
*s = (aSign != bSign);
*q = 0;
return a;
}
#else
if ( (uint64_t) ( aSig0<<1 ) == 0 ) return a;
#endif
normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
}
bSig |= LIT64( 0x8000000000000000 );
bSig |= LIT64(0x8000000000000000);
zSign = aSign;
expDiff = aExp - bExp;
*s = (aSign != bSign);
aSig1 = 0;
if ( expDiff < 0 ) {
if ( expDiff < -1 ) return a;
shift128Right( aSig0, 0, 1, &aSig0, &aSig1 );
if (expDiff < 0) {
if (expDiff < -1) return a;
shift128Right(aSig0, 0, 1, &aSig0, &aSig1);
expDiff = 0;
}
qTemp = ( bSig <= aSig0 );
if ( qTemp ) aSig0 -= bSig;
*q = ( expDiff > 63 ) ? 0 : ( qTemp<<expDiff );
qTemp = (bSig <= aSig0);
if (qTemp) aSig0 -= bSig;
*q = (expDiff > 63) ? 0 : (qTemp << expDiff);
expDiff -= 64;
while ( 0 < expDiff ) {
qTemp = estimateDiv128To64( aSig0, aSig1, bSig );
qTemp = ( 2 < qTemp ) ? qTemp - 2 : 0;
mul64To128( bSig, qTemp, &term0, &term1 );
sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 );
*q = ( expDiff > 63 ) ? 0 : ( qTemp<<expDiff );
while (0 < expDiff) {
qTemp = estimateDiv128To64(aSig0, aSig1, bSig);
qTemp = (2 < qTemp) ? qTemp - 2 : 0;
mul64To128(bSig, qTemp, &term0, &term1);
sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
shortShift128Left(aSig0, aSig1, 62, &aSig0, &aSig1);
*q = (expDiff > 63) ? 0 : (qTemp << expDiff);
expDiff -= 62;
}
expDiff += 64;
if ( 0 < expDiff ) {
qTemp = estimateDiv128To64( aSig0, aSig1, bSig );
qTemp = ( 2 < qTemp ) ? qTemp - 2 : 0;
if (0 < expDiff) {
qTemp = estimateDiv128To64(aSig0, aSig1, bSig);
qTemp = (2 < qTemp) ? qTemp - 2 : 0;
qTemp >>= 64 - expDiff;
mul64To128( bSig, qTemp<<( 64 - expDiff ), &term0, &term1 );
sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 );
while ( le128( term0, term1, aSig0, aSig1 ) ) {
mul64To128(bSig, qTemp << (64 - expDiff), &term0, &term1);
sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
shortShift128Left(0, bSig, 64 - expDiff, &term0, &term1);
while (le128(term0, term1, aSig0, aSig1)) {
++qTemp;
sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
}
*q += qTemp;
}
else {
term1 = 0;
term0 = bSig;
}
sub128( term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1 );
if ( lt128( alternateASig0, alternateASig1, aSig0, aSig1 )
|| ( eq128( alternateASig0, alternateASig1, aSig0, aSig1 )
&& ( qTemp & 1 ) )
sub128(term0, term1, aSig0, aSig1, &alternateASig0, &alternateASig1);
if (lt128(alternateASig0, alternateASig1, aSig0, aSig1)
|| (eq128(alternateASig0, alternateASig1, aSig0, aSig1)
&& (qTemp & 1))
) {
aSig0 = alternateASig0;
aSig1 = alternateASig1;
zSign = ! zSign;
++*q;
zSign = !zSign;
++* q;
}
return
normalizeRoundAndPackFloatx80(status->floatx80_rounding_precision,
zSign, bExp + expDiff, aSig0, aSig1, status );
normalizeRoundAndPackFloatx80(status->floatx80_rounding_precision,
zSign, bExp + expDiff, aSig0, aSig1, status);

}
#endif // End of modification


#ifdef SOFTFLOAT_68K // 08-01-2017: Added for Previous
/*----------------------------------------------------------------------------
| Returns the modulo remainder of the extended double-precision floating-point
| value `a' with respect to the corresponding value `b'.
*----------------------------------------------------------------------------*/

floatx80 floatx80_mod( floatx80 a, floatx80 b, uint64_t *q, flag *s, float_status *status )
floatx80 floatx80_mod(floatx80 a, floatx80 b, uint64_t* q, flag* s, float_status* status)
{
flag aSign, bSign, zSign;
int32_t aExp, bExp, expDiff;
uint64_t aSig0, aSig1, bSig;
uint64_t qTemp, term0, term1;

aSig0 = extractFloatx80Frac( a );
aExp = extractFloatx80Exp( a );
aSign = extractFloatx80Sign( a );
bSig = extractFloatx80Frac( b );
bExp = extractFloatx80Exp( b );
bSign = extractFloatx80Sign( b );

if ( aExp == 0x7FFF ) {
if ( (uint64_t) ( aSig0<<1 )
|| ( ( bExp == 0x7FFF ) && (uint64_t) ( bSig<<1 ) ) ) {
return propagateFloatx80NaN( a, b, status );
aSig0 = extractFloatx80Frac(a);
aExp = extractFloatx80Exp(a);
aSign = extractFloatx80Sign(a);
bSig = extractFloatx80Frac(b);
bExp = extractFloatx80Exp(b);
bSign = extractFloatx80Sign(b);

*s = 0;
*q = 0;

if (aExp == 0x7FFF) {
if ((uint64_t)(aSig0 << 1)
|| ((bExp == 0x7FFF) && (uint64_t)(bSig << 1))) {
return propagateFloatx80NaN(a, b, status);
}
goto invalid;
}
if ( bExp == 0x7FFF ) {
if ( (uint64_t) ( bSig<<1 ) ) return propagateFloatx80NaN( a, b, status );
if (bExp == 0x7FFF) {
if ((uint64_t)(bSig << 1)) return propagateFloatx80NaN(a, b, status);
*s = (aSign != bSign);
*q = 0;
return a;
return normalizeRoundAndPackFloatx80(status->floatx80_rounding_precision, aSign, aExp, aSig0, 0, status);
}
if ( bExp == 0 ) {
if ( bSig == 0 ) {
if (bExp == 0) {
if (bSig == 0) {
invalid:
float_raise( float_flag_invalid, status );
return floatx80_default_nan(status);
}
normalizeFloatx80Subnormal( bSig, &bExp, &bSig );
float_raise(float_flag_invalid, status);
return floatx80_default_nan(status);
}
normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
}
if ( aExp == 0 ) {
#ifdef SOFTFLOAT_68K
if ( aSig0 == 0 ) {
if (aExp == 0) {
if (aSig0 == 0) {
*s = (aSign != bSign);
*q = 0;
return a;
}
#else
if ( (uint64_t) ( aSig0<<1 ) == 0 ) return a;
#endif
normalizeFloatx80Subnormal( aSig0, &aExp, &aSig0 );
normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
}
bSig |= LIT64( 0x8000000000000000 );
bSig |= LIT64(0x8000000000000000);
zSign = aSign;
expDiff = aExp - bExp;
*s = (aSign != bSign);
aSig1 = 0;
if ( expDiff < 0 ) return a;
qTemp = ( bSig <= aSig0 );
if ( qTemp ) aSig0 -= bSig;
*q = ( expDiff > 63 ) ? 0 : ( qTemp<<expDiff );
if (expDiff < 0) return roundAndPackFloatx80(status->floatx80_rounding_precision, aSign, aExp, aSig0, 0, status);
qTemp = (bSig <= aSig0);
if (qTemp) aSig0 -= bSig;
*q = (expDiff > 63) ? 0 : (qTemp << expDiff);
expDiff -= 64;
while ( 0 < expDiff ) {
qTemp = estimateDiv128To64( aSig0, aSig1, bSig );
qTemp = ( 2 < qTemp ) ? qTemp - 2 : 0;
mul64To128( bSig, qTemp, &term0, &term1 );
sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
shortShift128Left( aSig0, aSig1, 62, &aSig0, &aSig1 );
*q = ( expDiff > 63 ) ? 0 : ( qTemp<<expDiff );
expDiff -= 62;
while (0 < expDiff) {
qTemp = estimateDiv128To64(aSig0, aSig1, bSig);
qTemp = (2 < qTemp) ? qTemp - 2 : 0;
mul64To128(bSig, qTemp, &term0, &term1);
sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
shortShift128Left(aSig0, aSig1, 62, &aSig0, &aSig1);
*q = (expDiff > 63) ? 0 : (qTemp << expDiff);
expDiff -= 62;
}
expDiff += 64;
if ( 0 < expDiff ) {
qTemp = estimateDiv128To64( aSig0, aSig1, bSig );
qTemp = ( 2 < qTemp ) ? qTemp - 2 : 0;
if (0 < expDiff) {
qTemp = estimateDiv128To64(aSig0, aSig1, bSig);
qTemp = (2 < qTemp) ? qTemp - 2 : 0;
qTemp >>= 64 - expDiff;
mul64To128( bSig, qTemp<<( 64 - expDiff ), &term0, &term1 );
sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
shortShift128Left( 0, bSig, 64 - expDiff, &term0, &term1 );
while ( le128( term0, term1, aSig0, aSig1 ) ) {
mul64To128(bSig, qTemp << (64 - expDiff), &term0, &term1);
sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
shortShift128Left(0, bSig, 64 - expDiff, &term0, &term1);
while (le128(term0, term1, aSig0, aSig1)) {
++qTemp;
sub128( aSig0, aSig1, term0, term1, &aSig0, &aSig1 );
sub128(aSig0, aSig1, term0, term1, &aSig0, &aSig1);
}
*q += qTemp;
}
return
normalizeRoundAndPackFloatx80(status->floatx80_rounding_precision,
zSign, bExp + expDiff, aSig0, aSig1, status );
zSign, bExp + expDiff, aSig0, aSig1, status);

}
#endif // end of addition for Previous


/*----------------------------------------------------------------------------
| Returns the square root of the extended double-precision floating-point
| value `a'. The operation is performed according to the IEC/IEEE Standard
Expand Down Expand Up @@ -3244,7 +3236,7 @@ floatx80 floatx80_scale(floatx80 a, floatx80 b, float_status *status)
}
if ( aExp == 0 ) {
if ( aSig == 0 ) return packFloatx80( aSign, 0, 0);
if ( bExp < 0x3FFF ) return a;
if (bExp < 0x3FFF) return normalizeRoundAndPackFloatx80(status->floatx80_rounding_precision, aSign, aExp, aSig, 0, status);
normalizeFloatx80Subnormal( aSig, &aExp, &aSig );
}

Expand Down
1 change: 1 addition & 0 deletions softfloat/softfloat.h
Original file line number Diff line number Diff line change
Expand Up @@ -459,6 +459,7 @@ floatx80 floatx80_tan(floatx80 a, float_status *status);
floatx80 floatx80_tanh(floatx80 a, float_status *status);
floatx80 floatx80_tentox(floatx80 a, float_status *status);
floatx80 floatx80_twotox(floatx80 a, float_status *status);
floatx80 floatx80_sincos(floatx80 a, floatx80 *c, float_status *status);
#endif

// functions originally internal to softfloat.c
Expand Down
Loading

0 comments on commit 2337abe

Please sign in to comment.