1/* Copyright (C) 2007-2020 Free Software Foundation, Inc. 2 3This file is part of GCC. 4 5GCC is free software; you can redistribute it and/or modify it under 6the terms of the GNU General Public License as published by the Free 7Software Foundation; either version 3, or (at your option) any later 8version. 9 10GCC is distributed in the hope that it will be useful, but WITHOUT ANY 11WARRANTY; without even the implied warranty of MERCHANTABILITY or 12FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 13for more details. 14 15Under Section 7 of GPL version 3, you are granted additional 16permissions described in the GCC Runtime Library Exception, version 173.1, as published by the Free Software Foundation. 18 19You should have received a copy of the GNU General Public License and 20a copy of the GCC Runtime Library Exception along with this program; 21see the files COPYING3 and COPYING.RUNTIME respectively. If not, see 22<http://www.gnu.org/licenses/>. */ 23 24#include "bid_internal.h" 25 26/* 27 * Takes a BID32 as input and converts it to a BID64 and returns it. 28 */ 29TYPE0_FUNCTION_ARGTYPE1_NORND (UINT64, bid32_to_bid64, UINT32, x) 30 31 UINT64 res; 32 UINT32 sign_x; 33 int exponent_x; 34 UINT32 coefficient_x; 35 36if (!unpack_BID32 (&sign_x, &exponent_x, &coefficient_x, x)) { 37 // Inf, NaN, 0 38if (((x) & 0x78000000) == 0x78000000) { 39 if (((x) & 0x7e000000) == 0x7e000000) { // sNaN 40#ifdef SET_STATUS_FLAGS 41 __set_status_flags (pfpsf, INVALID_EXCEPTION); 42#endif 43 } 44 res = (coefficient_x & 0x000fffff); 45 res *= 1000000000; 46 res |= ((((UINT64) coefficient_x) << 32) & 0xfc00000000000000ull); 47 48 BID_RETURN (res); 49} 50} 51 52res = 53very_fast_get_BID64_small_mantissa (((UINT64) sign_x) << 32, 54 exponent_x + 55 DECIMAL_EXPONENT_BIAS - 56 DECIMAL_EXPONENT_BIAS_32, 57 (UINT64) coefficient_x); 58BID_RETURN (res); 59} // convert_bid32_to_bid64 60 61 62/* 63 * Takes a BID64 as input and converts it to a BID32 and returns it. 64 */ 65#if DECIMAL_CALL_BY_REFERENCE 66 67void 68bid64_to_bid32 (UINT32 * pres, 69 UINT64 * 70 px _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM 71 _EXC_INFO_PARAM) { 72 UINT64 x; 73#else 74 75UINT32 76bid64_to_bid32 (UINT64 x _RND_MODE_PARAM _EXC_FLAGS_PARAM 77 _EXC_MASKS_PARAM _EXC_INFO_PARAM) { 78#endif 79 UINT128 Q; 80 UINT64 sign_x, coefficient_x, remainder_h, carry, Stemp; 81 UINT32 res; 82 int_float tempx; 83 int exponent_x, bin_expon_cx, extra_digits, rmode = 0, amount; 84 unsigned status = 0; 85 86#if DECIMAL_CALL_BY_REFERENCE 87#if !DECIMAL_GLOBAL_ROUNDING 88 _IDEC_round rnd_mode = *prnd_mode; 89#endif 90 x = *px; 91#endif 92 93 // unpack arguments, check for NaN or Infinity, 0 94 if (!unpack_BID64 (&sign_x, &exponent_x, &coefficient_x, x)) { 95 if (((x) & 0x7800000000000000ull) == 0x7800000000000000ull) { 96 res = (coefficient_x & 0x0003ffffffffffffull); 97 res /= 1000000000ull; 98 res |= ((coefficient_x >> 32) & 0xfc000000); 99#ifdef SET_STATUS_FLAGS 100 if ((x & SNAN_MASK64) == SNAN_MASK64) // sNaN 101 __set_status_flags (pfpsf, INVALID_EXCEPTION); 102#endif 103 BID_RETURN (res); 104 } 105 exponent_x = 106 exponent_x - DECIMAL_EXPONENT_BIAS + DECIMAL_EXPONENT_BIAS_32; 107 if (exponent_x < 0) 108 exponent_x = 0; 109 if (exponent_x > DECIMAL_MAX_EXPON_32) 110 exponent_x = DECIMAL_MAX_EXPON_32; 111 res = (sign_x >> 32) | (exponent_x << 23); 112 BID_RETURN (res); 113 } 114 115 exponent_x = 116 exponent_x - DECIMAL_EXPONENT_BIAS + DECIMAL_EXPONENT_BIAS_32; 117 118 // check number of digits 119 if (coefficient_x >= 10000000) { 120 tempx.d = (float) coefficient_x; 121 bin_expon_cx = ((tempx.i >> 23) & 0xff) - 0x7f; 122 extra_digits = estimate_decimal_digits[bin_expon_cx] - 7; 123 // add test for range 124 if (coefficient_x >= power10_index_binexp[bin_expon_cx]) 125 extra_digits++; 126 127#ifndef IEEE_ROUND_NEAREST_TIES_AWAY 128#ifndef IEEE_ROUND_NEAREST 129 rmode = rnd_mode; 130 if (sign_x && (unsigned) (rmode - 1) < 2) 131 rmode = 3 - rmode; 132#else 133 rmode = 0; 134#endif 135#else 136 rmode = 0; 137#endif 138 139 exponent_x += extra_digits; 140 if ((exponent_x < 0) && (exponent_x + MAX_FORMAT_DIGITS_32 >= 0)) { 141 status = UNDERFLOW_EXCEPTION; 142 if (exponent_x == -1) 143 if (coefficient_x + round_const_table[rmode][extra_digits] >= 144 power10_table_128[extra_digits + 7].w[0]) 145 status = 0; 146 extra_digits -= exponent_x; 147 exponent_x = 0; 148 } 149 coefficient_x += round_const_table[rmode][extra_digits]; 150 __mul_64x64_to_128 (Q, coefficient_x, 151 reciprocals10_64[extra_digits]); 152 153 // now get P/10^extra_digits: shift Q_high right by M[extra_digits]-128 154 amount = short_recip_scale[extra_digits]; 155 156 coefficient_x = Q.w[1] >> amount; 157 158#ifndef IEEE_ROUND_NEAREST_TIES_AWAY 159#ifndef IEEE_ROUND_NEAREST 160 if (rmode == 0) //ROUNDING_TO_NEAREST 161#endif 162 if (coefficient_x & 1) { 163 // check whether fractional part of initial_P/10^extra_digits 164 // is exactly .5 165 166 // get remainder 167 remainder_h = Q.w[1] << (64 - amount); 168 169 if (!remainder_h && (Q.w[0] < reciprocals10_64[extra_digits])) 170 coefficient_x--; 171 } 172#endif 173 174#ifdef SET_STATUS_FLAGS 175 176 { 177 status |= INEXACT_EXCEPTION; 178 // get remainder 179 remainder_h = Q.w[1] << (64 - amount); 180 181 switch (rmode) { 182 case ROUNDING_TO_NEAREST: 183 case ROUNDING_TIES_AWAY: 184 // test whether fractional part is 0 185 if (remainder_h == 0x8000000000000000ull 186 && (Q.w[0] < reciprocals10_64[extra_digits])) 187 status = EXACT_STATUS; 188 break; 189 case ROUNDING_DOWN: 190 case ROUNDING_TO_ZERO: 191 if (!remainder_h && (Q.w[0] < reciprocals10_64[extra_digits])) 192 status = EXACT_STATUS; 193 break; 194 default: 195 // round up 196 __add_carry_out (Stemp, carry, Q.w[0], 197 reciprocals10_64[extra_digits]); 198 if ((remainder_h >> (64 - amount)) + carry >= 199 (((UINT64) 1) << amount)) 200 status = EXACT_STATUS; 201 } 202 203 if (status != EXACT_STATUS) 204 __set_status_flags (pfpsf, status); 205 } 206 207#endif 208 209 } 210 211 res = 212 get_BID32 ((UINT32) (sign_x >> 32), 213 exponent_x, coefficient_x, rnd_mode, pfpsf); 214 BID_RETURN (res); 215 216} 217