rewrite fprem.cc using functions from softfloat3e
preparing to eliminate softfloat2 completely
This commit is contained in:
parent
8757c36e1c
commit
c70bcbf5e9
@ -130,14 +130,14 @@ floatx80 f2xm1(floatx80 a, float_status_t &status)
|
||||
int aSign = extF80_sign(a);
|
||||
|
||||
if (aExp == 0x7FFF) {
|
||||
if ((Bit64u) (aSig<<1))
|
||||
if (aSig << 1)
|
||||
return propagateFloatx80NaN(a, status);
|
||||
|
||||
return (aSign) ? floatx80_negone : a;
|
||||
}
|
||||
|
||||
if (aExp == 0) {
|
||||
if (aSig == 0) return a;
|
||||
if (! aExp) {
|
||||
if (! aSig) return a;
|
||||
softfloat_raiseFlags(&status, softfloat_flag_denormal | softfloat_flag_inexact);
|
||||
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
|
||||
|
||||
|
@ -159,19 +159,17 @@ floatx80 fpatan(floatx80 a, floatx80 b, float_status_t &status)
|
||||
if (aSig<<1)
|
||||
return propagateFloatx80NaN(a, b, status);
|
||||
|
||||
if (aSign) { /* return 3PI/4 */
|
||||
return roundAndPackFloatx80(80, bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, status);
|
||||
}
|
||||
else { /* return PI/4 */
|
||||
return roundAndPackFloatx80(80, bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
|
||||
}
|
||||
if (aSign) /* return 3PI/4 */
|
||||
return softfloat_roundPackToExtF80(bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, 80, &status);
|
||||
else /* return PI/4 */
|
||||
return softfloat_roundPackToExtF80(bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status);
|
||||
}
|
||||
|
||||
if (aSig && ! aExp)
|
||||
softfloat_raiseFlags(&status, softfloat_flag_denormal);
|
||||
|
||||
/* return PI/2 */
|
||||
return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
|
||||
return softfloat_roundPackToExtF80(bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status);
|
||||
}
|
||||
if (aExp == 0x7FFF)
|
||||
{
|
||||
@ -183,11 +181,10 @@ floatx80 fpatan(floatx80 a, floatx80 b, float_status_t &status)
|
||||
|
||||
return_PI_or_ZERO:
|
||||
|
||||
if (aSign) { /* return PI */
|
||||
return roundAndPackFloatx80(80, bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
|
||||
} else { /* return 0 */
|
||||
return packFloatx80(bSign, 0, 0);
|
||||
}
|
||||
if (aSign) /* return PI */
|
||||
return softfloat_roundPackToExtF80(bSign, FLOATX80_PI_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status);
|
||||
else /* return 0 */
|
||||
return packToExtF80(bSign, 0, 0);
|
||||
}
|
||||
if (! bExp)
|
||||
{
|
||||
@ -202,7 +199,7 @@ return_PI_or_ZERO:
|
||||
if (! aExp)
|
||||
{
|
||||
if (! aSig) /* return PI/2 */
|
||||
return roundAndPackFloatx80(80, bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
|
||||
return softfloat_roundPackToExtF80(bSign, FLOATX80_PI2_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status);
|
||||
|
||||
softfloat_raiseFlags(&status, softfloat_flag_denormal);
|
||||
normalizeFloatx80Subnormal(aSig, &aExp, &aSig);
|
||||
@ -213,9 +210,9 @@ return_PI_or_ZERO:
|
||||
/* |a| = |b| ==> return PI/4 */
|
||||
if (aSig == bSig && aExp == bExp) {
|
||||
if (aSign)
|
||||
return roundAndPackFloatx80(80, bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, status);
|
||||
return softfloat_roundPackToExtF80(bSign, FLOATX80_3PI4_EXP, FLOAT_3PI4_HI, FLOAT_3PI4_LO, 80, &status);
|
||||
else
|
||||
return roundAndPackFloatx80(80, bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, status);
|
||||
return softfloat_roundPackToExtF80(bSign, FLOATX80_PI4_EXP, FLOAT_PI_HI, FLOAT_PI_LO, 80, &status);
|
||||
}
|
||||
|
||||
/* ******************************** */
|
||||
|
@ -24,92 +24,101 @@ these four paragraphs for those parts of this code that are retained.
|
||||
* ==========================================================================*/
|
||||
|
||||
#include "softfloatx80.h"
|
||||
#include "softfloat-round-pack.h"
|
||||
#define USE_estimateDiv128To64
|
||||
#include "softfloat-macros.h"
|
||||
#include "softfloat-helpers.h"
|
||||
|
||||
#include "../softfloat3e/include/specialize.h" // for softfloat_propagateNaNExtF80UI
|
||||
|
||||
/* executes single exponent reduction cycle */
|
||||
static Bit64u remainder_kernel(Bit64u aSig0, Bit64u bSig, int expDiff, Bit64u *zSig0, Bit64u *zSig1)
|
||||
{
|
||||
Bit64u term0, term1;
|
||||
uint128 term, z;
|
||||
Bit64u aSig1 = 0;
|
||||
|
||||
shortShift128Left(aSig1, aSig0, expDiff, &aSig1, &aSig0);
|
||||
Bit64u q = estimateDiv128To64(aSig1, aSig0, bSig);
|
||||
mul64To128(bSig, q, &term0, &term1);
|
||||
sub128(aSig1, aSig0, term0, term1, zSig1, zSig0);
|
||||
while ((Bit64s)(*zSig1) < 0) {
|
||||
term = softfloat_mul64To128(bSig, q);
|
||||
z = softfloat_sub128(aSig1, aSig0, term.v64, term.v0);
|
||||
while ((int64_t) z.v64 < 0) {
|
||||
--q;
|
||||
add128(*zSig1, *zSig0, 0, bSig, zSig1, zSig0);
|
||||
z = softfloat_add128(z.v64, z.v0, 0, bSig);
|
||||
}
|
||||
*zSig0 = z.v0;
|
||||
*zSig1 = z.v64;
|
||||
return q;
|
||||
}
|
||||
|
||||
static int do_fprem(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, int rounding_mode, float_status_t &status)
|
||||
static int do_fprem(extFloat80_t a, extFloat80_t b, extFloat80_t &r, Bit64u &q, int rounding_mode, struct softfloat_status_t *status)
|
||||
{
|
||||
Bit32s aExp, bExp, zExp, expDiff;
|
||||
Bit64u aSig0, aSig1, bSig;
|
||||
Bit64u aSig0, aSig1 = 0, bSig;
|
||||
int aSign;
|
||||
struct exp32_sig64 normExpSig;
|
||||
uint128 term;
|
||||
|
||||
q = 0;
|
||||
|
||||
// handle unsupported extended double-precision floating encodings
|
||||
if (extF80_isUnsupported(a) || extF80_isUnsupported(b)) {
|
||||
softfloat_raiseFlags(&status, softfloat_flag_invalid);
|
||||
softfloat_raiseFlags(status, softfloat_flag_invalid);
|
||||
r = floatx80_default_nan;
|
||||
return -1;
|
||||
}
|
||||
|
||||
aSig0 = extractFloatx80Frac(a);
|
||||
aExp = extractFloatx80Exp(a);
|
||||
aSign = extractFloatx80Sign(a);
|
||||
bSig = extractFloatx80Frac(b);
|
||||
bExp = extractFloatx80Exp(b);
|
||||
aSig0 = extF80_fraction(a);
|
||||
aExp = extF80_exp(a);
|
||||
aSign = extF80_sign(a);
|
||||
bSig = extF80_fraction(b);
|
||||
bExp = extF80_exp(b);
|
||||
|
||||
if (aExp == 0x7FFF) {
|
||||
if ((Bit64u) (aSig0<<1) || ((bExp == 0x7FFF) && (Bit64u) (bSig<<1))) {
|
||||
r = propagateFloatx80NaN(a, b, status);
|
||||
if ((aSig0<<1) || ((bExp == 0x7FFF) && (bSig<<1))) {
|
||||
r = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, b.signExp, b.signif, status);
|
||||
return -1;
|
||||
}
|
||||
softfloat_raiseFlags(&status, softfloat_flag_invalid);
|
||||
softfloat_raiseFlags(status, softfloat_flag_invalid);
|
||||
r = floatx80_default_nan;
|
||||
return -1;
|
||||
}
|
||||
if (bExp == 0x7FFF) {
|
||||
if ((Bit64u) (bSig<<1)) {
|
||||
r = propagateFloatx80NaN(a, b, status);
|
||||
if (bSig << 1) {
|
||||
r = softfloat_propagateNaNExtF80UI(a.signExp, a.signif, b.signExp, b.signif, status);
|
||||
return -1;
|
||||
}
|
||||
if (aExp == 0 && aSig0) {
|
||||
softfloat_raiseFlags(&status, softfloat_flag_denormal);
|
||||
normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
|
||||
r = (a.fraction & BX_CONST64(0x8000000000000000)) ? packFloatx80(aSign, aExp, aSig0) : a;
|
||||
if (! aExp && aSig0) {
|
||||
softfloat_raiseFlags(status, softfloat_flag_denormal);
|
||||
normExpSig = softfloat_normSubnormalExtF80Sig(aSig0);
|
||||
aExp = normExpSig.exp + 1;
|
||||
aSig0 = normExpSig.sig;
|
||||
r = (a.signif & BX_CONST64(0x8000000000000000)) ? packToExtF80(aSign, aExp, aSig0) : a;
|
||||
return 0;
|
||||
}
|
||||
r = a;
|
||||
return 0;
|
||||
|
||||
}
|
||||
if (bExp == 0) {
|
||||
if (bSig == 0) {
|
||||
softfloat_raiseFlags(&status, softfloat_flag_invalid);
|
||||
if (! bExp) {
|
||||
if (! bSig) {
|
||||
softfloat_raiseFlags(status, softfloat_flag_invalid);
|
||||
r = floatx80_default_nan;
|
||||
return -1;
|
||||
}
|
||||
softfloat_raiseFlags(&status, softfloat_flag_denormal);
|
||||
normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
|
||||
softfloat_raiseFlags(status, softfloat_flag_denormal);
|
||||
normExpSig = softfloat_normSubnormalExtF80Sig(bSig);
|
||||
bExp = normExpSig.exp + 1;
|
||||
bSig = normExpSig.sig;
|
||||
}
|
||||
if (aExp == 0) {
|
||||
if (aSig0 == 0) {
|
||||
if (! aExp) {
|
||||
if (! aSig0) {
|
||||
r = a;
|
||||
return 0;
|
||||
}
|
||||
softfloat_raiseFlags(&status, softfloat_flag_denormal);
|
||||
normalizeFloatx80Subnormal(aSig0, &aExp, &aSig0);
|
||||
softfloat_raiseFlags(status, softfloat_flag_denormal);
|
||||
normExpSig = softfloat_normSubnormalExtF80Sig(aSig0);
|
||||
aExp = normExpSig.exp + 1;
|
||||
aSig0 = normExpSig.sig;
|
||||
}
|
||||
expDiff = aExp - bExp;
|
||||
aSig1 = 0;
|
||||
|
||||
expDiff = aExp - bExp;
|
||||
int overflow = 0;
|
||||
|
||||
if (expDiff >= 64) {
|
||||
@ -123,8 +132,7 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, int rounding
|
||||
|
||||
if (expDiff < 0) {
|
||||
if (expDiff < -1) {
|
||||
r = (a.fraction & BX_CONST64(0x8000000000000000)) ?
|
||||
packFloatx80(aSign, aExp, aSig0) : a;
|
||||
r = (a.signif & BX_CONST64(0x8000000000000000)) ? packToExtF80(aSign, aExp, aSig0) : a;
|
||||
return 0;
|
||||
}
|
||||
shortShift128Right(aSig0, 0, 1, &aSig0, &aSig1);
|
||||
@ -141,26 +149,28 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, int rounding
|
||||
}
|
||||
}
|
||||
|
||||
if (rounding_mode == softfloat_round_near_even)
|
||||
{
|
||||
if (rounding_mode == softfloat_round_near_even) {
|
||||
Bit64u term0, term1;
|
||||
shortShift128Right(bSig, 0, 1, &term0, &term1);
|
||||
|
||||
if (! lt128(aSig0, aSig1, term0, term1))
|
||||
{
|
||||
int lt = lt128(term0, term1, aSig0, aSig1);
|
||||
int eq = eq128(aSig0, aSig1, term0, term1);
|
||||
if (! softfloat_lt128(aSig0, aSig1, term0, term1)) {
|
||||
int lt = softfloat_lt128(term0, term1, aSig0, aSig1);
|
||||
int eq = softfloat_eq128(aSig0, aSig1, term0, term1);
|
||||
|
||||
if ((eq && (q & 1)) || lt) {
|
||||
aSign = !aSign;
|
||||
++q;
|
||||
}
|
||||
if (lt) sub128(bSig, 0, aSig0, aSig1, &aSig0, &aSig1);
|
||||
if ((eq && (q & 1)) || lt) {
|
||||
aSign = !aSign;
|
||||
++q;
|
||||
}
|
||||
if (lt) {
|
||||
term = softfloat_sub128(bSig, 0, aSig0, aSig1);
|
||||
aSig0 = term.v64;
|
||||
aSig1 = term.v0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
r = normalizeRoundAndPackFloatx80(80, aSign, zExp, aSig0, aSig1, status);
|
||||
r = softfloat_normRoundPackToExtF80(aSign, zExp, aSig0, aSig1, 80, status);
|
||||
return overflow;
|
||||
}
|
||||
|
||||
@ -170,7 +180,7 @@ static int do_fprem(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, int rounding
|
||||
| according to the IEC/IEEE Standard for Binary Floating-Point Arithmetic.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, float_status_t &status)
|
||||
int floatx80_ieee754_remainder(extFloat80_t a, extFloat80_t b, extFloat80_t &r, Bit64u &q, struct softfloat_status_t *status)
|
||||
{
|
||||
return do_fprem(a, b, r, q, softfloat_round_near_even, status);
|
||||
}
|
||||
@ -184,7 +194,7 @@ int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, f
|
||||
| quotient of 'a' divided by 'b' to an integer.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
int floatx80_remainder(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, float_status_t &status)
|
||||
int floatx80_remainder(extFloat80_t a, extFloat80_t b, extFloat80_t &r, Bit64u &q, struct softfloat_status_t *status)
|
||||
{
|
||||
return do_fprem(a, b, r, q, softfloat_round_to_zero, status);
|
||||
}
|
||||
|
@ -233,11 +233,11 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FPREM1(bxInstruction_c *i)
|
||||
|
||||
Bit64u quotient;
|
||||
|
||||
floatx80 a = BX_READ_FPU_REG(0);
|
||||
floatx80 b = BX_READ_FPU_REG(1);
|
||||
floatx80 result;
|
||||
extFloat80_t a = BX_READ_FPU_REG(0);
|
||||
extFloat80_t b = BX_READ_FPU_REG(1);
|
||||
extFloat80_t result;
|
||||
|
||||
int flags = floatx80_ieee754_remainder(a, b, result, quotient, status);
|
||||
int flags = floatx80_ieee754_remainder(a, b, result, quotient, &status);
|
||||
|
||||
if (! FPU_exception(i, status.float_exception_flags)) {
|
||||
if (flags >= 0) {
|
||||
@ -276,11 +276,11 @@ void BX_CPP_AttrRegparmN(1) BX_CPU_C::FPREM(bxInstruction_c *i)
|
||||
|
||||
Bit64u quotient;
|
||||
|
||||
floatx80 a = BX_READ_FPU_REG(0);
|
||||
floatx80 b = BX_READ_FPU_REG(1);
|
||||
floatx80 result;
|
||||
extFloat80_t a = BX_READ_FPU_REG(0);
|
||||
extFloat80_t b = BX_READ_FPU_REG(1);
|
||||
extFloat80_t result;
|
||||
|
||||
int flags = floatx80_remainder(a, b, result, quotient, status);
|
||||
int flags = floatx80_remainder(a, b, result, quotient, &status);
|
||||
|
||||
if (! FPU_exception(i, status.float_exception_flags)) {
|
||||
if (flags >= 0) {
|
||||
|
@ -154,9 +154,7 @@ invalid:
|
||||
int zSign = bSign ^ 1;
|
||||
|
||||
if (aExp == 0x7FFF) {
|
||||
if ((Bit64u) (aSig<<1)
|
||||
|| ((bExp == 0x7FFF) && (Bit64u) (bSig<<1)))
|
||||
{
|
||||
if ((aSig<<1) || ((bExp == 0x7FFF) && (bSig<<1))) {
|
||||
return propagateFloatx80NaN(a, b, status);
|
||||
}
|
||||
if (aSign) goto invalid;
|
||||
@ -168,16 +166,15 @@ invalid:
|
||||
return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000));
|
||||
}
|
||||
}
|
||||
if (bExp == 0x7FFF)
|
||||
{
|
||||
if (bSig<<1) return propagateFloatx80NaN(a, b, status);
|
||||
if (bExp == 0x7FFF) {
|
||||
if (bSig << 1) return propagateFloatx80NaN(a, b, status);
|
||||
if (aSign && (Bit64u)(aExp | aSig)) goto invalid;
|
||||
if (aSig && ! aExp)
|
||||
softfloat_raiseFlags(&status, softfloat_flag_denormal);
|
||||
if (aExp < 0x3FFF) {
|
||||
return packFloatx80(zSign, 0x7FFF, BX_CONST64(0x8000000000000000));
|
||||
}
|
||||
if (aExp == 0x3FFF && ((Bit64u) (aSig<<1) == 0)) goto invalid;
|
||||
if (aExp == 0x3FFF && ! (aSig<<1)) goto invalid;
|
||||
return packFloatx80(bSign, 0x7FFF, BX_CONST64(0x8000000000000000));
|
||||
}
|
||||
if (! aExp) {
|
||||
@ -199,7 +196,7 @@ invalid:
|
||||
softfloat_raiseFlags(&status, softfloat_flag_denormal);
|
||||
normalizeFloatx80Subnormal(bSig, &bExp, &bSig);
|
||||
}
|
||||
if (aExp == 0x3FFF && ((aSig<<1) == 0))
|
||||
if (aExp == 0x3FFF && ! (aSig<<1))
|
||||
return packFloatx80(bSign, 0, 0);
|
||||
|
||||
softfloat_raiseFlags(&status, softfloat_flag_inexact);
|
||||
@ -339,8 +336,7 @@ invalid:
|
||||
--zExp;
|
||||
}
|
||||
|
||||
return
|
||||
roundAndPackFloatx80(80, aSign ^ bSign, zExp, zSig0, zSig1, status);
|
||||
return softfloat_roundPackToExtF80(aSign ^ bSign, zExp, zSig0, zSig1, 80, &status);
|
||||
}
|
||||
|
||||
/* ******************************** */
|
||||
|
@ -81,4 +81,35 @@ BX_CPP_INLINE void shortShift128Right(Bit64u a0, Bit64u a1, int count, Bit64u *z
|
||||
*z0Ptr = z0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns an approximation to the 64-bit integer quotient obtained by dividing
|
||||
| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The
|
||||
| divisor `b' must be at least 2^63. If q is the exact quotient truncated
|
||||
| toward zero, the approximation returned lies between q and q + 2 inclusive.
|
||||
| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
|
||||
| unsigned integer is returned.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef USE_estimateDiv128To64
|
||||
static Bit64u estimateDiv128To64(Bit64u a0, Bit64u a1, Bit64u b)
|
||||
{
|
||||
uint128 term, rem;
|
||||
Bit64u b0, b1;
|
||||
Bit64u z;
|
||||
if (b <= a0) return BX_CONST64(0xFFFFFFFFFFFFFFFF);
|
||||
b0 = b>>32;
|
||||
z = (b0<<32 <= a0) ? BX_CONST64(0xFFFFFFFF00000000) : (a0 / b0)<<32;
|
||||
term = softfloat_mul64To128(b, z);
|
||||
rem = softfloat_sub128(a0, a1, term.v64, term.v0);
|
||||
while (((int64_t) rem.v64) < 0) {
|
||||
z -= UINT64_C(0x100000000);
|
||||
b1 = b<<32;
|
||||
rem = softfloat_add128(rem.v64, rem.v0, b0, b1);
|
||||
}
|
||||
rem.v64 = (rem.v64<<32) | (rem.v0>>32);
|
||||
z |= (b0<<32 <= rem.v64) ? 0xFFFFFFFF : rem.v64 / b0;
|
||||
return z;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
@ -103,20 +103,6 @@ BX_CPP_INLINE void shift64ExtraRightJamming(Bit64u a0, Bit64u a1, int count, Bit
|
||||
*z0Ptr = z0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Adds the 128-bit value formed by concatenating `a0' and `a1' to the 128-bit
|
||||
| value formed by concatenating `b0' and `b1'. Addition is modulo 2^128, so
|
||||
| any carry out is lost. The result is broken into two 64-bit pieces which
|
||||
| are stored at the locations pointed to by `z0Ptr' and `z1Ptr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
BX_CPP_INLINE void add128(Bit64u a0, Bit64u a1, Bit64u b0, Bit64u b1, Bit64u *z0Ptr, Bit64u *z1Ptr)
|
||||
{
|
||||
Bit64u z1 = a1 + b1;
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = a0 + b0 + (z1 < a1);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Subtracts the 128-bit value formed by concatenating `b0' and `b1' from the
|
||||
| 128-bit value formed by concatenating `a0' and `a1'. Subtraction is modulo
|
||||
@ -132,66 +118,6 @@ BX_CPP_INLINE void
|
||||
*z0Ptr = a0 - b0 - (a1 < b1);
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Multiplies `a' by `b' to obtain a 128-bit product. The product is broken
|
||||
| into two 64-bit pieces which are stored at the locations pointed to by
|
||||
| `z0Ptr' and `z1Ptr'.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
BX_CPP_INLINE void mul64To128(Bit64u a, Bit64u b, Bit64u *z0Ptr, Bit64u *z1Ptr)
|
||||
{
|
||||
Bit32u aHigh, aLow, bHigh, bLow;
|
||||
Bit64u z0, zMiddleA, zMiddleB, z1;
|
||||
|
||||
aLow = (Bit32u) a;
|
||||
aHigh = (Bit32u)(a>>32);
|
||||
bLow = (Bit32u) b;
|
||||
bHigh = (Bit32u)(b>>32);
|
||||
z1 = ((Bit64u) aLow) * bLow;
|
||||
zMiddleA = ((Bit64u) aLow) * bHigh;
|
||||
zMiddleB = ((Bit64u) aHigh) * bLow;
|
||||
z0 = ((Bit64u) aHigh) * bHigh;
|
||||
zMiddleA += zMiddleB;
|
||||
z0 += (((Bit64u) (zMiddleA < zMiddleB))<<32) + (zMiddleA>>32);
|
||||
zMiddleA <<= 32;
|
||||
z1 += zMiddleA;
|
||||
z0 += (z1 < zMiddleA);
|
||||
*z1Ptr = z1;
|
||||
*z0Ptr = z0;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Returns an approximation to the 64-bit integer quotient obtained by dividing
|
||||
| `b' into the 128-bit value formed by concatenating `a0' and `a1'. The
|
||||
| divisor `b' must be at least 2^63. If q is the exact quotient truncated
|
||||
| toward zero, the approximation returned lies between q and q + 2 inclusive.
|
||||
| If the exact quotient q is larger than 64 bits, the maximum positive 64-bit
|
||||
| unsigned integer is returned.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
#ifdef USE_estimateDiv128To64
|
||||
static Bit64u estimateDiv128To64(Bit64u a0, Bit64u a1, Bit64u b)
|
||||
{
|
||||
Bit64u b0, b1;
|
||||
Bit64u rem0, rem1, term0, term1;
|
||||
Bit64u z;
|
||||
|
||||
if (b <= a0) return BX_CONST64(0xFFFFFFFFFFFFFFFF);
|
||||
b0 = b>>32;
|
||||
z = (b0<<32 <= a0) ? BX_CONST64(0xFFFFFFFF00000000) : (a0 / b0)<<32;
|
||||
mul64To128(b, z, &term0, &term1);
|
||||
sub128(a0, a1, term0, term1, &rem0, &rem1);
|
||||
while (((Bit64s) rem0) < 0) {
|
||||
z -= BX_CONST64(0x100000000);
|
||||
b1 = b<<32;
|
||||
add128(rem0, rem1, b0, b1, &rem0, &rem1);
|
||||
}
|
||||
rem0 = (rem0<<32) | (rem1>>32);
|
||||
z |= (b0<<32 <= rem0) ? 0xFFFFFFFF : rem0 / b0;
|
||||
return z;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const int countLeadingZeros8[] = {
|
||||
8, 7, 6, 6, 5, 5, 5, 5, 4, 4, 4, 4, 4, 4, 4, 4,
|
||||
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3,
|
||||
|
@ -270,30 +270,6 @@ floatx80 roundAndPackFloatx80(int roundingPrecision,
|
||||
return result;
|
||||
}
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes an abstract floating-point value having sign `zSign', exponent
|
||||
| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
|
||||
| and returns the proper extended double-precision floating-point value
|
||||
| corresponding to the abstract input. This routine is just like
|
||||
| `roundAndPackFloatx80' except that the input significand does not have to be
|
||||
| normalized.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
floatx80 normalizeRoundAndPackFloatx80(int roundingPrecision,
|
||||
int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, float_status_t &status)
|
||||
{
|
||||
if (zSig0 == 0) {
|
||||
zSig0 = zSig1;
|
||||
zSig1 = 0;
|
||||
zExp -= 64;
|
||||
}
|
||||
int shiftCount = countLeadingZeros64(zSig0);
|
||||
shortShift128Left(zSig0, zSig1, shiftCount, &zSig0, &zSig1);
|
||||
zExp -= shiftCount;
|
||||
return
|
||||
roundAndPackFloatx80(roundingPrecision, zSign, zExp, zSig0, zSig1, status);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef FLOAT128
|
||||
|
@ -75,18 +75,6 @@ void normalizeFloatx80Subnormal(Bit64u aSig, Bit32s *zExpPtr, Bit64u *zSigPtr);
|
||||
floatx80 roundAndPackFloatx80(int roundingPrecision,
|
||||
int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, float_status_t &status);
|
||||
|
||||
/*----------------------------------------------------------------------------
|
||||
| Takes an abstract floating-point value having sign `zSign', exponent
|
||||
| `zExp', and significand formed by the concatenation of `zSig0' and `zSig1',
|
||||
| and returns the proper extended double-precision floating-point value
|
||||
| corresponding to the abstract input. This routine is just like
|
||||
| `roundAndPackFloatx80' except that the input significand does not have to be
|
||||
| normalized.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
floatx80 normalizeRoundAndPackFloatx80(int roundingPrecision,
|
||||
int zSign, Bit32s zExp, Bit64u zSig0, Bit64u zSig1, float_status_t &status);
|
||||
|
||||
#endif // FLOATX80
|
||||
|
||||
#ifdef FLOAT128
|
||||
|
@ -33,8 +33,9 @@ these four paragraphs for those parts of this code that are retained.
|
||||
| Software IEC/IEEE extended double-precision operations.
|
||||
*----------------------------------------------------------------------------*/
|
||||
|
||||
int floatx80_remainder(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, float_status_t &status);
|
||||
int floatx80_ieee754_remainder(floatx80 a, floatx80 b, floatx80 &r, Bit64u &q, float_status_t &status);
|
||||
int floatx80_remainder(extFloat80_t a, extFloat80_t b, extFloat80_t &r, Bit64u &q, struct softfloat_status_t *status);
|
||||
int floatx80_ieee754_remainder(extFloat80_t a, extFloat80_t b, extFloat80_t &r, Bit64u &q, struct softfloat_status_t *status);
|
||||
|
||||
floatx80 f2xm1(floatx80 a, float_status_t &status);
|
||||
floatx80 fyl2x(floatx80 a, floatx80 b, float_status_t &status);
|
||||
floatx80 fyl2xp1(floatx80 a, floatx80 b, float_status_t &status);
|
||||
|
@ -197,6 +197,9 @@ extFloat80_t
|
||||
if (sig > sigExact)
|
||||
softfloat_setRoundingUp(status);
|
||||
}
|
||||
else {
|
||||
if (! sig) exp = 0;
|
||||
}
|
||||
return packToExtF80(sign, exp, sig);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user