aboutsummaryrefslogtreecommitdiff
path: root/libgcc/config/libbid/bid64_to_bid128.c
diff options
context:
space:
mode:
Diffstat (limited to 'libgcc/config/libbid/bid64_to_bid128.c')
-rw-r--r--libgcc/config/libbid/bid64_to_bid128.c145
1 files changed, 78 insertions, 67 deletions
diff --git a/libgcc/config/libbid/bid64_to_bid128.c b/libgcc/config/libbid/bid64_to_bid128.c
index 1fc0b59591c..ac0cf781f05 100644
--- a/libgcc/config/libbid/bid64_to_bid128.c
+++ b/libgcc/config/libbid/bid64_to_bid128.c
@@ -30,29 +30,34 @@ Software Foundation, 51 Franklin Street, Fifth Floor, Boston, MA
#include "bid_internal.h"
/*
- * Takes a BID64 as input and converts it to a BID128 and returns it.
+ * Takes a BID64 as input and converts it to a BID128 and returns it.
*/
-TYPE0_FUNCTION_ARGTYPE1_NORND(UINT128, __bid64_to_bid128, UINT64, x)
-
- UINT128 new_coeff, res;
- UINT64 sign_x;
- int exponent_x = 0;
- UINT64 coefficient_x;
-
- if (!unpack_BID64 (&sign_x, &exponent_x, &coefficient_x, x)) {
- if (((x) << 1) >= 0xf000000000000000ull) {
- res.w[0] = 0;
- res.w[1] = (x) & 0xfe03ffffffffffffull;
- BID_RETURN (res);
- }
- }
+TYPE0_FUNCTION_ARGTYPE1_NORND (UINT128, bid64_to_bid128, UINT64, x)
- new_coeff.w[0] = coefficient_x;
- new_coeff.w[1] = 0;
- get_BID128_very_fast (&res, sign_x,
- exponent_x + DECIMAL_EXPONENT_BIAS_128 -
- DECIMAL_EXPONENT_BIAS, new_coeff);
+ UINT128 new_coeff, res;
+ UINT64 sign_x;
+ int exponent_x;
+ UINT64 coefficient_x;
+
+if (!unpack_BID64 (&sign_x, &exponent_x, &coefficient_x, x)) {
+if (((x) << 1) >= 0xf000000000000000ull) {
+#ifdef SET_STATUS_FLAGS
+ if (((x) & SNAN_MASK64) == SNAN_MASK64) // sNaN
+ __set_status_flags (pfpsf, INVALID_EXCEPTION);
+#endif
+ res.w[0] = (coefficient_x & 0x0003ffffffffffffull);
+ __mul_64x64_to_128 (res, res.w[0], power10_table_128[18].w[0]);
+ res.w[1] |= ((coefficient_x) & 0xfc00000000000000ull);
BID_RETURN (res);
+}
+}
+
+new_coeff.w[0] = coefficient_x;
+new_coeff.w[1] = 0;
+get_BID128_very_fast (&res, sign_x,
+ exponent_x + DECIMAL_EXPONENT_BIAS_128 -
+ DECIMAL_EXPONENT_BIAS, new_coeff);
+BID_RETURN (res);
} // convert_bid64_to_bid128
@@ -63,7 +68,7 @@ TYPE0_FUNCTION_ARGTYPE1_NORND(UINT128, __bid64_to_bid128, UINT64, x)
#if DECIMAL_CALL_BY_REFERENCE
void
-__bid128_to_bid64 (UINT64 * pres,
+bid128_to_bid64 (UINT64 * pres,
UINT128 *
px _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
_EXC_INFO_PARAM) {
@@ -71,14 +76,14 @@ __bid128_to_bid64 (UINT64 * pres,
#else
UINT64
-__bid128_to_bid64 (UINT128 x _RND_MODE_PARAM _EXC_FLAGS_PARAM
+bid128_to_bid64 (UINT128 x _RND_MODE_PARAM _EXC_FLAGS_PARAM
_EXC_MASKS_PARAM _EXC_INFO_PARAM) {
#endif
- UINT128 CX, T128, TP128, Qh, Ql, Qh1, Stemp, Tmp, Tmp1;
+ UINT128 CX, T128, TP128, Qh, Ql, Qh1, Stemp, Tmp, Tmp1, CX1;
UINT64 sign_x, carry, cy, res;
SINT64 D;
int_float f64, fx;
- int exponent_x = 0, extra_digits, amount, bin_expon_cx;
+ int exponent_x, extra_digits, amount, bin_expon_cx;
unsigned rmode, status, uf_check = 0;
#if DECIMAL_CALL_BY_REFERENCE
@@ -87,12 +92,21 @@ __bid128_to_bid64 (UINT128 x _RND_MODE_PARAM _EXC_FLAGS_PARAM
#endif
#endif
- BID_SWAP128(x);
+ BID_SWAP128 (x);
// unpack arguments, check for NaN or Infinity or 0
- if (!unpack_BID128 (&sign_x, &exponent_x, &CX, &x)) {
+ if (!unpack_BID128_value (&sign_x, &exponent_x, &CX, x)) {
if ((x.w[1] << 1) >= 0xf000000000000000ull) {
- cy = ((x.w[1] & 0x00003fffffffffffull)<<4) | (x.w[0] >> 60);
- res = (x.w[1] & 0xfe00000000000000ull) | cy;
+ Tmp.w[1] = (CX.w[1] & 0x00003fffffffffffull);
+ Tmp.w[0] = CX.w[0];
+ TP128 = reciprocals10_128[18];
+ __mul_128x128_full (Qh, Ql, Tmp, TP128);
+ amount = recip_scale[18];
+ __shr_128 (Tmp, Qh, amount);
+ res = (CX.w[1] & 0xfc00000000000000ull) | Tmp.w[0];
+#ifdef SET_STATUS_FLAGS
+ if ((x.w[1] & SNAN_MASK64) == SNAN_MASK64) // sNaN
+ __set_status_flags (pfpsf, INVALID_EXCEPTION);
+#endif
BID_RETURN_VAL (res);
}
exponent_x =
@@ -114,12 +128,12 @@ __bid128_to_bid64 (UINT128 x _RND_MODE_PARAM _EXC_FLAGS_PARAM
// fx ~ CX
fx.d = (float) CX.w[1] * f64.d + (float) CX.w[0];
bin_expon_cx = ((fx.i >> 23) & 0xff) - 0x7f;
- extra_digits = __bid_estimate_decimal_digits[bin_expon_cx] - 16;
- // scale = 38-__bid_estimate_decimal_digits[bin_expon_cx];
- D = CX.w[1] - __bid_power10_index_binexp_128[bin_expon_cx].w[1];
+ extra_digits = estimate_decimal_digits[bin_expon_cx] - 16;
+ // scale = 38-estimate_decimal_digits[bin_expon_cx];
+ D = CX.w[1] - power10_index_binexp_128[bin_expon_cx].w[1];
if (D > 0
|| (!D
- && CX.w[0] >= __bid_power10_index_binexp_128[bin_expon_cx].w[0]))
+ && CX.w[0] >= power10_index_binexp_128[bin_expon_cx].w[0]))
extra_digits++;
exponent_x += extra_digits;
@@ -137,25 +151,33 @@ __bid128_to_bid64 (UINT128 x _RND_MODE_PARAM _EXC_FLAGS_PARAM
#endif
if (exponent_x < DECIMAL_EXPONENT_BIAS_128 - DECIMAL_EXPONENT_BIAS) {
uf_check = 1;
- if (extra_digits == 1
- && (exponent_x - DECIMAL_EXPONENT_BIAS_128 +
- DECIMAL_EXPONENT_BIAS + 16 >= 0)) {
+ if (-extra_digits + exponent_x - DECIMAL_EXPONENT_BIAS_128 +
+ DECIMAL_EXPONENT_BIAS + 35 >= 0) {
+ if (exponent_x ==
+ DECIMAL_EXPONENT_BIAS_128 - DECIMAL_EXPONENT_BIAS - 1) {
+ T128 = round_const_table_128[rmode][extra_digits];
+ __add_carry_out (CX1.w[0], carry, T128.w[0], CX.w[0]);
+ CX1.w[1] = CX.w[1] + T128.w[1] + carry;
+ if (__unsigned_compare_ge_128
+ (CX1, power10_table_128[extra_digits + 16]))
+ uf_check = 0;
+ }
extra_digits =
- 1 + DECIMAL_EXPONENT_BIAS_128 - DECIMAL_EXPONENT_BIAS -
- exponent_x;
+ extra_digits + DECIMAL_EXPONENT_BIAS_128 -
+ DECIMAL_EXPONENT_BIAS - exponent_x;
exponent_x = DECIMAL_EXPONENT_BIAS_128 - DECIMAL_EXPONENT_BIAS;
- uf_check = 2;
+ //uf_check = 2;
} else
rmode = ROUNDING_TO_ZERO;
}
- T128 = __bid_round_const_table_128[rmode][extra_digits];
+ T128 = round_const_table_128[rmode][extra_digits];
__add_carry_out (CX.w[0], carry, T128.w[0], CX.w[0]);
CX.w[1] = CX.w[1] + T128.w[1] + carry;
- TP128 = __bid_reciprocals10_128[extra_digits];
+ TP128 = reciprocals10_128[extra_digits];
__mul_128x128_full (Qh, Ql, CX, TP128);
- amount = __bid_recip_scale[extra_digits];
+ amount = recip_scale[extra_digits];
if (amount >= 64) {
CX.w[0] = Qh.w[1] >> (amount - 64);
@@ -175,9 +197,9 @@ __bid128_to_bid64 (UINT128 x _RND_MODE_PARAM _EXC_FLAGS_PARAM
__shl_128_long (Qh1, Qh, (128 - amount));
if (!Qh1.w[1] && !Qh1.w[0]
- && (Ql.w[1] < __bid_reciprocals10_128[extra_digits].w[1]
- || (Ql.w[1] == __bid_reciprocals10_128[extra_digits].w[1]
- && Ql.w[0] < __bid_reciprocals10_128[extra_digits].w[0]))) {
+ && (Ql.w[1] < reciprocals10_128[extra_digits].w[1]
+ || (Ql.w[1] == reciprocals10_128[extra_digits].w[1]
+ && Ql.w[0] < reciprocals10_128[extra_digits].w[0]))) {
CX.w[0]--;
}
}
@@ -193,25 +215,25 @@ __bid128_to_bid64 (UINT128 x _RND_MODE_PARAM _EXC_FLAGS_PARAM
case ROUNDING_TIES_AWAY:
// test whether fractional part is 0
if (Qh1.w[1] == 0x8000000000000000ull && (!Qh1.w[0])
- && (Ql.w[1] < __bid_reciprocals10_128[extra_digits].w[1]
- || (Ql.w[1] == __bid_reciprocals10_128[extra_digits].w[1]
- && Ql.w[0] < __bid_reciprocals10_128[extra_digits].w[0])))
+ && (Ql.w[1] < reciprocals10_128[extra_digits].w[1]
+ || (Ql.w[1] == reciprocals10_128[extra_digits].w[1]
+ && Ql.w[0] < reciprocals10_128[extra_digits].w[0])))
status = EXACT_STATUS;
break;
case ROUNDING_DOWN:
case ROUNDING_TO_ZERO:
if ((!Qh1.w[1]) && (!Qh1.w[0])
- && (Ql.w[1] < __bid_reciprocals10_128[extra_digits].w[1]
- || (Ql.w[1] == __bid_reciprocals10_128[extra_digits].w[1]
- && Ql.w[0] < __bid_reciprocals10_128[extra_digits].w[0])))
+ && (Ql.w[1] < reciprocals10_128[extra_digits].w[1]
+ || (Ql.w[1] == reciprocals10_128[extra_digits].w[1]
+ && Ql.w[0] < reciprocals10_128[extra_digits].w[0])))
status = EXACT_STATUS;
break;
default:
// round up
__add_carry_out (Stemp.w[0], cy, Ql.w[0],
- __bid_reciprocals10_128[extra_digits].w[0]);
+ reciprocals10_128[extra_digits].w[0]);
__add_carry_in_out (Stemp.w[1], carry, Ql.w[1],
- __bid_reciprocals10_128[extra_digits].w[1], cy);
+ reciprocals10_128[extra_digits].w[1], cy);
__shr_128_long (Qh, Qh1, (128 - amount));
Tmp.w[0] = 1;
Tmp.w[1] = 0;
@@ -224,25 +246,14 @@ __bid128_to_bid64 (UINT128 x _RND_MODE_PARAM _EXC_FLAGS_PARAM
}
if (status != EXACT_STATUS) {
+ if (uf_check)
+ status |= UNDERFLOW_EXCEPTION;
#ifdef SET_STATUS_FLAGS
__set_status_flags (pfpsf, status);
#endif
- if (uf_check) {
- if (uf_check == 1) // result has not already been computed
- {
- res =
- get_BID64_UF (sign_x,
- exponent_x - DECIMAL_EXPONENT_BIAS_128 +
- DECIMAL_EXPONENT_BIAS, CX.w[0], 1, rnd_mode,
- pfpsf);
- BID_RETURN_VAL (res);
- } else {
-#ifdef SET_STATUS_FLAGS
- __set_status_flags (pfpsf, UNDERFLOW_EXCEPTION);
-#endif
- }
- }
}
+
+
}
}