diff options
Diffstat (limited to 'libgcc/config/libbid/bid64_to_bid128.c')
-rw-r--r-- | libgcc/config/libbid/bid64_to_bid128.c | 145 |
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 - } - } } + + } } |