0
|
1 /* Copyright (C) 2007, 2009 Free Software Foundation, Inc.
|
|
2
|
|
3 This file is part of GCC.
|
|
4
|
|
5 GCC is free software; you can redistribute it and/or modify it under
|
|
6 the terms of the GNU General Public License as published by the Free
|
|
7 Software Foundation; either version 3, or (at your option) any later
|
|
8 version.
|
|
9
|
|
10 GCC is distributed in the hope that it will be useful, but WITHOUT ANY
|
|
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
|
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
|
13 for more details.
|
|
14
|
|
15 Under Section 7 of GPL version 3, you are granted additional
|
|
16 permissions described in the GCC Runtime Library Exception, version
|
|
17 3.1, as published by the Free Software Foundation.
|
|
18
|
|
19 You should have received a copy of the GNU General Public License and
|
|
20 a copy of the GCC Runtime Library Exception along with this program;
|
|
21 see 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 */
|
|
29 TYPE0_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
|
|
36 if (!unpack_BID32 (&sign_x, &exponent_x, &coefficient_x, x)) {
|
|
37 // Inf, NaN, 0
|
|
38 if (((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
|
|
52 res =
|
|
53 very_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);
|
|
58 BID_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
|
|
67 void
|
|
68 bid64_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
|
|
75 UINT32
|
|
76 bid64_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 }
|