]> git.ipfire.org Git - thirdparty/gcc.git/blame - libgcc/config/libbid/bid32_to_bid64.c
Update copyright years.
[thirdparty/gcc.git] / libgcc / config / libbid / bid32_to_bid64.c
CommitLineData
a945c346 1/* Copyright (C) 2007-2024 Free Software Foundation, Inc.
200359e8
L
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
748086b7 7Software Foundation; either version 3, or (at your option) any later
200359e8
L
8version.
9
200359e8
L
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
748086b7
JJ
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/>. */
200359e8
L
23
24#include "bid_internal.h"
25
26/*
27 * Takes a BID32 as input and converts it to a BID64 and returns it.
28 */
b2a00c89 29TYPE0_FUNCTION_ARGTYPE1_NORND (UINT64, bid32_to_bid64, UINT32, x)
200359e8 30
b2a00c89
L
31 UINT64 res;
32 UINT32 sign_x;
33 int exponent_x;
34 UINT32 coefficient_x;
200359e8 35
b2a00c89 36if (!unpack_BID32 (&sign_x, &exponent_x, &coefficient_x, x)) {
200359e8 37 // Inf, NaN, 0
b2a00c89
L
38if (((x) & 0x78000000) == 0x78000000) {
39 if (((x) & 0x7e000000) == 0x7e000000) { // sNaN
40#ifdef SET_STATUS_FLAGS
41 __set_status_flags (pfpsf, INVALID_EXCEPTION);
42#endif
200359e8 43 }
b2a00c89
L
44 res = (coefficient_x & 0x000fffff);
45 res *= 1000000000;
46 res |= ((((UINT64) coefficient_x) << 32) & 0xfc00000000000000ull);
200359e8 47
200359e8 48 BID_RETURN (res);
b2a00c89
L
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
200359e8
L
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
b2a00c89 68bid64_to_bid32 (UINT32 * pres,
200359e8
L
69 UINT64 *
70 px _RND_MODE_PARAM _EXC_FLAGS_PARAM _EXC_MASKS_PARAM
71 _EXC_INFO_PARAM) {
72 UINT64 x;
73#else
74
75UINT32
b2a00c89 76bid64_to_bid32 (UINT64 x _RND_MODE_PARAM _EXC_FLAGS_PARAM
200359e8
L
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;
b2a00c89
L
83 int exponent_x, bin_expon_cx, extra_digits, rmode = 0, amount;
84 unsigned status = 0;
200359e8
L
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) {
b2a00c89
L
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
200359e8
L
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
b2a00c89
L
115 exponent_x =
116 exponent_x - DECIMAL_EXPONENT_BIAS + DECIMAL_EXPONENT_BIAS_32;
200359e8
L
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;
b2a00c89 122 extra_digits = estimate_decimal_digits[bin_expon_cx] - 7;
200359e8 123 // add test for range
b2a00c89 124 if (coefficient_x >= power10_index_binexp[bin_expon_cx])
200359e8
L
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
200359e8 139 exponent_x += extra_digits;
b2a00c89
L
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];
200359e8 150 __mul_64x64_to_128 (Q, coefficient_x,
b2a00c89 151 reciprocals10_64[extra_digits]);
200359e8
L
152
153 // now get P/10^extra_digits: shift Q_high right by M[extra_digits]-128
b2a00c89 154 amount = short_recip_scale[extra_digits];
200359e8
L
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
b2a00c89 164 // is exactly .5
200359e8
L
165
166 // get remainder
167 remainder_h = Q.w[1] << (64 - amount);
168
b2a00c89 169 if (!remainder_h && (Q.w[0] < reciprocals10_64[extra_digits]))
200359e8
L
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
b2a00c89 186 && (Q.w[0] < reciprocals10_64[extra_digits]))
200359e8
L
187 status = EXACT_STATUS;
188 break;
189 case ROUNDING_DOWN:
190 case ROUNDING_TO_ZERO:
b2a00c89 191 if (!remainder_h && (Q.w[0] < reciprocals10_64[extra_digits]))
200359e8
L
192 status = EXACT_STATUS;
193 break;
194 default:
195 // round up
196 __add_carry_out (Stemp, carry, Q.w[0],
b2a00c89 197 reciprocals10_64[extra_digits]);
200359e8
L
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),
b2a00c89 213 exponent_x, coefficient_x, rnd_mode, pfpsf);
200359e8
L
214 BID_RETURN (res);
215
216}