Mercurial > hg > CbC > CbC_gcc
annotate gcc/dfp.c @ 158:494b0b89df80 default tip
...
author | Shinji KONO <kono@ie.u-ryukyu.ac.jp> |
---|---|
date | Mon, 25 May 2020 18:13:55 +0900 |
parents | 1830386684a0 |
children |
rev | line source |
---|---|
0 | 1 /* Decimal floating point support. |
145 | 2 Copyright (C) 2005-2020 Free Software Foundation, Inc. |
0 | 3 |
4 This file is part of GCC. | |
5 | |
6 GCC is free software; you can redistribute it and/or modify it under | |
7 the terms of the GNU General Public License as published by the Free | |
8 Software Foundation; either version 3, or (at your option) any later | |
9 version. | |
10 | |
11 GCC is distributed in the hope that it will be useful, but WITHOUT ANY | |
12 WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
13 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
14 for more details. | |
15 | |
16 You should have received a copy of the GNU General Public License | |
17 along with GCC; see the file COPYING3. If not see | |
18 <http://www.gnu.org/licenses/>. */ | |
19 | |
20 #include "config.h" | |
21 #include "system.h" | |
22 #include "coretypes.h" | |
23 #include "tm.h" | |
24 #include "tree.h" | |
25 #include "dfp.h" | |
26 | |
27 /* The order of the following headers is important for making sure | |
28 decNumber structure is large enough to hold decimal128 digits. */ | |
29 | |
30 #include "decimal128.h" | |
31 #include "decimal64.h" | |
32 #include "decimal32.h" | |
33 | |
34 #ifndef WORDS_BIGENDIAN | |
35 #define WORDS_BIGENDIAN 0 | |
36 #endif | |
37 | |
38 /* Initialize R (a real with the decimal flag set) from DN. Can | |
39 utilize status passed in via CONTEXT, if a previous operation had | |
40 interesting status. */ | |
41 | |
42 static void | |
43 decimal_from_decnumber (REAL_VALUE_TYPE *r, decNumber *dn, decContext *context) | |
44 { | |
45 memset (r, 0, sizeof (REAL_VALUE_TYPE)); | |
46 | |
47 r->cl = rvc_normal; | |
48 if (decNumberIsNaN (dn)) | |
49 r->cl = rvc_nan; | |
50 if (decNumberIsInfinite (dn)) | |
51 r->cl = rvc_inf; | |
52 if (context->status & DEC_Overflow) | |
53 r->cl = rvc_inf; | |
54 if (decNumberIsNegative (dn)) | |
55 r->sign = 1; | |
56 r->decimal = 1; | |
57 | |
58 if (r->cl != rvc_normal) | |
59 return; | |
60 | |
61 decContextDefault (context, DEC_INIT_DECIMAL128); | |
62 context->traps = 0; | |
63 | |
64 decimal128FromNumber ((decimal128 *) r->sig, dn, context); | |
65 } | |
66 | |
67 /* Create decimal encoded R from string S. */ | |
68 | |
69 void | |
70 decimal_real_from_string (REAL_VALUE_TYPE *r, const char *s) | |
71 { | |
72 decNumber dn; | |
73 decContext set; | |
74 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
75 set.traps = 0; | |
76 | |
77 decNumberFromString (&dn, s, &set); | |
78 | |
79 /* It would be more efficient to store directly in decNumber format, | |
80 but that is impractical from current data structure size. | |
81 Encoding as a decimal128 is much more compact. */ | |
82 decimal_from_decnumber (r, &dn, &set); | |
83 } | |
84 | |
85 /* Initialize a decNumber from a REAL_VALUE_TYPE. */ | |
86 | |
87 static void | |
88 decimal_to_decnumber (const REAL_VALUE_TYPE *r, decNumber *dn) | |
89 { | |
90 decContext set; | |
91 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
92 set.traps = 0; | |
93 | |
94 switch (r->cl) | |
95 { | |
96 case rvc_zero: | |
97 decNumberZero (dn); | |
98 break; | |
99 case rvc_inf: | |
100 decNumberFromString (dn, "Infinity", &set); | |
101 break; | |
102 case rvc_nan: | |
103 if (r->signalling) | |
104 decNumberFromString (dn, "snan", &set); | |
105 else | |
106 decNumberFromString (dn, "nan", &set); | |
107 break; | |
108 case rvc_normal: | |
111 | 109 if (!r->decimal) |
110 { | |
111 /* dconst{1,2,m1,half} are used in various places in | |
112 the middle-end and optimizers, allow them here | |
113 as an exception by converting them to decimal. */ | |
114 if (memcmp (r, &dconst1, sizeof (*r)) == 0) | |
115 { | |
116 decNumberFromString (dn, "1", &set); | |
117 break; | |
118 } | |
119 if (memcmp (r, &dconst2, sizeof (*r)) == 0) | |
120 { | |
121 decNumberFromString (dn, "2", &set); | |
122 break; | |
123 } | |
124 if (memcmp (r, &dconstm1, sizeof (*r)) == 0) | |
125 { | |
126 decNumberFromString (dn, "-1", &set); | |
127 break; | |
128 } | |
129 if (memcmp (r, &dconsthalf, sizeof (*r)) == 0) | |
130 { | |
131 decNumberFromString (dn, "0.5", &set); | |
132 break; | |
133 } | |
134 gcc_unreachable (); | |
135 } | |
0 | 136 decimal128ToNumber ((const decimal128 *) r->sig, dn); |
137 break; | |
138 default: | |
139 gcc_unreachable (); | |
140 } | |
141 | |
142 /* Fix up sign bit. */ | |
143 if (r->sign != decNumberIsNegative (dn)) | |
144 dn->bits ^= DECNEG; | |
145 } | |
146 | |
147 /* Encode a real into an IEEE 754 decimal32 type. */ | |
148 | |
149 void | |
150 encode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED, | |
151 long *buf, const REAL_VALUE_TYPE *r) | |
152 { | |
153 decNumber dn; | |
154 decimal32 d32; | |
155 decContext set; | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
156 int32_t image; |
0 | 157 |
158 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
159 set.traps = 0; | |
160 | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
161 decimal_to_decnumber (r, &dn); |
0 | 162 decimal32FromNumber (&d32, &dn, &set); |
163 | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
164 memcpy (&image, d32.bytes, sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
165 buf[0] = image; |
0 | 166 } |
167 | |
168 /* Decode an IEEE 754 decimal32 type into a real. */ | |
169 | |
170 void | |
171 decode_decimal32 (const struct real_format *fmt ATTRIBUTE_UNUSED, | |
172 REAL_VALUE_TYPE *r, const long *buf) | |
173 { | |
174 decNumber dn; | |
175 decimal32 d32; | |
176 decContext set; | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
177 int32_t image; |
0 | 178 |
179 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
180 set.traps = 0; | |
181 | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
182 image = buf[0]; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
183 memcpy (&d32.bytes, &image, sizeof (int32_t)); |
0 | 184 |
185 decimal32ToNumber (&d32, &dn); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
186 decimal_from_decnumber (r, &dn, &set); |
0 | 187 } |
188 | |
189 /* Encode a real into an IEEE 754 decimal64 type. */ | |
190 | |
191 void | |
192 encode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED, | |
193 long *buf, const REAL_VALUE_TYPE *r) | |
194 { | |
195 decNumber dn; | |
196 decimal64 d64; | |
197 decContext set; | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
198 int32_t image; |
0 | 199 |
200 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
201 set.traps = 0; | |
202 | |
203 decimal_to_decnumber (r, &dn); | |
204 decimal64FromNumber (&d64, &dn, &set); | |
205 | |
206 if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN) | |
207 { | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
208 memcpy (&image, &d64.bytes[0], sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
209 buf[0] = image; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
210 memcpy (&image, &d64.bytes[4], sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
211 buf[1] = image; |
0 | 212 } |
213 else | |
214 { | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
215 memcpy (&image, &d64.bytes[4], sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
216 buf[0] = image; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
217 memcpy (&image, &d64.bytes[0], sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
218 buf[1] = image; |
0 | 219 } |
220 } | |
221 | |
222 /* Decode an IEEE 754 decimal64 type into a real. */ | |
223 | |
224 void | |
225 decode_decimal64 (const struct real_format *fmt ATTRIBUTE_UNUSED, | |
226 REAL_VALUE_TYPE *r, const long *buf) | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
227 { |
0 | 228 decNumber dn; |
229 decimal64 d64; | |
230 decContext set; | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
231 int32_t image; |
0 | 232 |
233 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
234 set.traps = 0; | |
235 | |
236 if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN) | |
237 { | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
238 image = buf[0]; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
239 memcpy (&d64.bytes[0], &image, sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
240 image = buf[1]; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
241 memcpy (&d64.bytes[4], &image, sizeof (int32_t)); |
0 | 242 } |
243 else | |
244 { | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
245 image = buf[1]; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
246 memcpy (&d64.bytes[0], &image, sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
247 image = buf[0]; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
248 memcpy (&d64.bytes[4], &image, sizeof (int32_t)); |
0 | 249 } |
250 | |
251 decimal64ToNumber (&d64, &dn); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
252 decimal_from_decnumber (r, &dn, &set); |
0 | 253 } |
254 | |
255 /* Encode a real into an IEEE 754 decimal128 type. */ | |
256 | |
257 void | |
258 encode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED, | |
259 long *buf, const REAL_VALUE_TYPE *r) | |
260 { | |
261 decNumber dn; | |
262 decContext set; | |
263 decimal128 d128; | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
264 int32_t image; |
0 | 265 |
266 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
267 set.traps = 0; | |
268 | |
269 decimal_to_decnumber (r, &dn); | |
270 decimal128FromNumber (&d128, &dn, &set); | |
271 | |
272 if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN) | |
273 { | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
274 memcpy (&image, &d128.bytes[0], sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
275 buf[0] = image; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
276 memcpy (&image, &d128.bytes[4], sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
277 buf[1] = image; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
278 memcpy (&image, &d128.bytes[8], sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
279 buf[2] = image; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
280 memcpy (&image, &d128.bytes[12], sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
281 buf[3] = image; |
0 | 282 } |
283 else | |
284 { | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
285 memcpy (&image, &d128.bytes[12], sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
286 buf[0] = image; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
287 memcpy (&image, &d128.bytes[8], sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
288 buf[1] = image; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
289 memcpy (&image, &d128.bytes[4], sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
290 buf[2] = image; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
291 memcpy (&image, &d128.bytes[0], sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
292 buf[3] = image; |
0 | 293 } |
294 } | |
295 | |
296 /* Decode an IEEE 754 decimal128 type into a real. */ | |
297 | |
298 void | |
299 decode_decimal128 (const struct real_format *fmt ATTRIBUTE_UNUSED, | |
300 REAL_VALUE_TYPE *r, const long *buf) | |
301 { | |
302 decNumber dn; | |
303 decimal128 d128; | |
304 decContext set; | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
305 int32_t image; |
0 | 306 |
307 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
308 set.traps = 0; | |
309 | |
310 if (WORDS_BIGENDIAN == FLOAT_WORDS_BIG_ENDIAN) | |
311 { | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
312 image = buf[0]; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
313 memcpy (&d128.bytes[0], &image, sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
314 image = buf[1]; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
315 memcpy (&d128.bytes[4], &image, sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
316 image = buf[2]; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
317 memcpy (&d128.bytes[8], &image, sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
318 image = buf[3]; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
319 memcpy (&d128.bytes[12], &image, sizeof (int32_t)); |
0 | 320 } |
321 else | |
322 { | |
19
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
323 image = buf[3]; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
324 memcpy (&d128.bytes[0], &image, sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
325 image = buf[2]; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
326 memcpy (&d128.bytes[4], &image, sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
327 image = buf[1]; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
328 memcpy (&d128.bytes[8], &image, sizeof (int32_t)); |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
329 image = buf[0]; |
58ad6c70ea60
update gcc from 4.4.0 to 4.4.1.
kent@firefly.cr.ie.u-ryukyu.ac.jp
parents:
0
diff
changeset
|
330 memcpy (&d128.bytes[12], &image, sizeof (int32_t)); |
0 | 331 } |
332 | |
333 decimal128ToNumber (&d128, &dn); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
334 decimal_from_decnumber (r, &dn, &set); |
0 | 335 } |
336 | |
337 /* Helper function to convert from a binary real internal | |
338 representation. */ | |
339 | |
340 static void | |
341 decimal_to_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from, | |
111 | 342 const real_format *fmt) |
0 | 343 { |
344 char string[256]; | |
345 const decimal128 *const d128 = (const decimal128 *) from->sig; | |
346 | |
347 decimal128ToString (d128, string); | |
111 | 348 real_from_string3 (to, string, fmt); |
0 | 349 } |
350 | |
351 | |
352 /* Helper function to convert from a binary real internal | |
353 representation. */ | |
354 | |
355 static void | |
356 decimal_from_binary (REAL_VALUE_TYPE *to, const REAL_VALUE_TYPE *from) | |
357 { | |
358 char string[256]; | |
359 | |
360 /* We convert to string, then to decNumber then to decimal128. */ | |
361 real_to_decimal (string, from, sizeof (string), 0, 1); | |
362 decimal_real_from_string (to, string); | |
363 } | |
364 | |
365 /* Helper function to real.c:do_compare() to handle decimal internal | |
366 representation including when one of the operands is still in the | |
367 binary internal representation. */ | |
368 | |
369 int | |
370 decimal_do_compare (const REAL_VALUE_TYPE *a, const REAL_VALUE_TYPE *b, | |
371 int nan_result) | |
372 { | |
373 decContext set; | |
374 decNumber dn, dn2, dn3; | |
375 REAL_VALUE_TYPE a1, b1; | |
376 | |
377 /* If either operand is non-decimal, create temporary versions. */ | |
378 if (!a->decimal) | |
379 { | |
380 decimal_from_binary (&a1, a); | |
381 a = &a1; | |
382 } | |
383 if (!b->decimal) | |
384 { | |
385 decimal_from_binary (&b1, b); | |
386 b = &b1; | |
387 } | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
388 |
0 | 389 /* Convert into decNumber form for comparison operation. */ |
390 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
391 set.traps = 0; |
0 | 392 decimal128ToNumber ((const decimal128 *) a->sig, &dn2); |
393 decimal128ToNumber ((const decimal128 *) b->sig, &dn3); | |
394 | |
395 /* Finally, do the comparison. */ | |
396 decNumberCompare (&dn, &dn2, &dn3, &set); | |
397 | |
398 /* Return the comparison result. */ | |
399 if (decNumberIsNaN (&dn)) | |
400 return nan_result; | |
401 else if (decNumberIsZero (&dn)) | |
402 return 0; | |
403 else if (decNumberIsNegative (&dn)) | |
404 return -1; | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
405 else |
0 | 406 return 1; |
407 } | |
408 | |
409 /* Helper to round_for_format, handling decimal float types. */ | |
410 | |
411 void | |
412 decimal_round_for_format (const struct real_format *fmt, REAL_VALUE_TYPE *r) | |
413 { | |
414 decNumber dn; | |
415 decContext set; | |
416 | |
417 /* Real encoding occurs later. */ | |
418 if (r->cl != rvc_normal) | |
419 return; | |
420 | |
421 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
422 set.traps = 0; | |
423 decimal128ToNumber ((decimal128 *) r->sig, &dn); | |
424 | |
425 if (fmt == &decimal_quad_format) | |
426 { | |
427 /* The internal format is already in this format. */ | |
428 return; | |
429 } | |
430 else if (fmt == &decimal_single_format) | |
431 { | |
432 decimal32 d32; | |
433 decContextDefault (&set, DEC_INIT_DECIMAL32); | |
434 set.traps = 0; | |
435 | |
436 decimal32FromNumber (&d32, &dn, &set); | |
437 decimal32ToNumber (&d32, &dn); | |
438 } | |
439 else if (fmt == &decimal_double_format) | |
440 { | |
441 decimal64 d64; | |
442 decContextDefault (&set, DEC_INIT_DECIMAL64); | |
443 set.traps = 0; | |
444 | |
445 decimal64FromNumber (&d64, &dn, &set); | |
446 decimal64ToNumber (&d64, &dn); | |
447 } | |
448 else | |
449 gcc_unreachable (); | |
450 | |
451 decimal_from_decnumber (r, &dn, &set); | |
452 } | |
453 | |
454 /* Extend or truncate to a new mode. Handles conversions between | |
455 binary and decimal types. */ | |
456 | |
457 void | |
111 | 458 decimal_real_convert (REAL_VALUE_TYPE *r, const real_format *fmt, |
0 | 459 const REAL_VALUE_TYPE *a) |
460 { | |
461 if (a->decimal && fmt->b == 10) | |
462 return; | |
463 if (a->decimal) | |
111 | 464 decimal_to_binary (r, a, fmt); |
0 | 465 else |
466 decimal_from_binary (r, a); | |
467 } | |
468 | |
469 /* Render R_ORIG as a decimal floating point constant. Emit DIGITS | |
470 significant digits in the result, bounded by BUF_SIZE. If DIGITS | |
471 is 0, choose the maximum for the representation. If | |
472 CROP_TRAILING_ZEROS, strip trailing zeros. Currently, not honoring | |
473 DIGITS or CROP_TRAILING_ZEROS. */ | |
474 | |
475 void | |
476 decimal_real_to_decimal (char *str, const REAL_VALUE_TYPE *r_orig, | |
477 size_t buf_size, | |
478 size_t digits ATTRIBUTE_UNUSED, | |
479 int crop_trailing_zeros ATTRIBUTE_UNUSED) | |
480 { | |
481 const decimal128 *const d128 = (const decimal128*) r_orig->sig; | |
482 | |
483 /* decimal128ToString requires space for at least 24 characters; | |
484 Require two more for suffix. */ | |
485 gcc_assert (buf_size >= 24); | |
486 decimal128ToString (d128, str); | |
487 } | |
488 | |
489 static bool | |
490 decimal_do_add (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, | |
491 const REAL_VALUE_TYPE *op1, int subtract_p) | |
492 { | |
493 decNumber dn; | |
494 decContext set; | |
495 decNumber dn2, dn3; | |
496 | |
497 decimal_to_decnumber (op0, &dn2); | |
498 decimal_to_decnumber (op1, &dn3); | |
499 | |
500 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
501 set.traps = 0; | |
502 | |
503 if (subtract_p) | |
504 decNumberSubtract (&dn, &dn2, &dn3, &set); | |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
505 else |
0 | 506 decNumberAdd (&dn, &dn2, &dn3, &set); |
507 | |
508 decimal_from_decnumber (r, &dn, &set); | |
509 | |
510 /* Return true, if inexact. */ | |
511 return (set.status & DEC_Inexact); | |
512 } | |
513 | |
514 /* Compute R = OP0 * OP1. */ | |
515 | |
516 static bool | |
517 decimal_do_multiply (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, | |
518 const REAL_VALUE_TYPE *op1) | |
519 { | |
520 decContext set; | |
521 decNumber dn, dn2, dn3; | |
522 | |
523 decimal_to_decnumber (op0, &dn2); | |
524 decimal_to_decnumber (op1, &dn3); | |
525 | |
526 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
527 set.traps = 0; | |
528 | |
529 decNumberMultiply (&dn, &dn2, &dn3, &set); | |
530 decimal_from_decnumber (r, &dn, &set); | |
531 | |
532 /* Return true, if inexact. */ | |
533 return (set.status & DEC_Inexact); | |
534 } | |
535 | |
536 /* Compute R = OP0 / OP1. */ | |
537 | |
538 static bool | |
539 decimal_do_divide (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *op0, | |
540 const REAL_VALUE_TYPE *op1) | |
541 { | |
542 decContext set; | |
543 decNumber dn, dn2, dn3; | |
544 | |
545 decimal_to_decnumber (op0, &dn2); | |
546 decimal_to_decnumber (op1, &dn3); | |
547 | |
548 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
549 set.traps = 0; | |
550 | |
551 decNumberDivide (&dn, &dn2, &dn3, &set); | |
552 decimal_from_decnumber (r, &dn, &set); | |
553 | |
554 /* Return true, if inexact. */ | |
555 return (set.status & DEC_Inexact); | |
556 } | |
557 | |
558 /* Set R to A truncated to an integral value toward zero (decimal | |
559 floating point). */ | |
560 | |
561 void | |
562 decimal_do_fix_trunc (REAL_VALUE_TYPE *r, const REAL_VALUE_TYPE *a) | |
563 { | |
564 decNumber dn, dn2; | |
565 decContext set; | |
566 | |
567 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
568 set.traps = 0; | |
569 set.round = DEC_ROUND_DOWN; | |
570 decimal128ToNumber ((const decimal128 *) a->sig, &dn2); | |
571 | |
572 decNumberToIntegralValue (&dn, &dn2, &set); | |
573 decimal_from_decnumber (r, &dn, &set); | |
574 } | |
575 | |
576 /* Render decimal float value R as an integer. */ | |
577 | |
578 HOST_WIDE_INT | |
579 decimal_real_to_integer (const REAL_VALUE_TYPE *r) | |
580 { | |
581 decContext set; | |
582 decNumber dn, dn2, dn3; | |
583 REAL_VALUE_TYPE to; | |
584 char string[256]; | |
585 | |
586 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
587 set.traps = 0; | |
588 set.round = DEC_ROUND_DOWN; | |
589 decimal128ToNumber ((const decimal128 *) r->sig, &dn); | |
590 | |
591 decNumberToIntegralValue (&dn2, &dn, &set); | |
592 decNumberZero (&dn3); | |
593 decNumberRescale (&dn, &dn2, &dn3, &set); | |
594 | |
595 /* Convert to REAL_VALUE_TYPE and call appropriate conversion | |
596 function. */ | |
597 decNumberToString (&dn, string); | |
598 real_from_string (&to, string); | |
599 return real_to_integer (&to); | |
600 } | |
601 | |
111 | 602 /* Likewise, but returns a wide_int with PRECISION. *FAIL is set if the |
603 value does not fit. */ | |
0 | 604 |
111 | 605 wide_int |
606 decimal_real_to_integer (const REAL_VALUE_TYPE *r, bool *fail, int precision) | |
0 | 607 { |
608 decContext set; | |
609 decNumber dn, dn2, dn3; | |
610 REAL_VALUE_TYPE to; | |
611 char string[256]; | |
612 | |
613 decContextDefault (&set, DEC_INIT_DECIMAL128); | |
614 set.traps = 0; | |
615 set.round = DEC_ROUND_DOWN; | |
616 decimal128ToNumber ((const decimal128 *) r->sig, &dn); | |
617 | |
618 decNumberToIntegralValue (&dn2, &dn, &set); | |
619 decNumberZero (&dn3); | |
620 decNumberRescale (&dn, &dn2, &dn3, &set); | |
621 | |
622 /* Convert to REAL_VALUE_TYPE and call appropriate conversion | |
623 function. */ | |
624 decNumberToString (&dn, string); | |
625 real_from_string (&to, string); | |
111 | 626 return real_to_integer (&to, fail, precision); |
0 | 627 } |
628 | |
629 /* Perform the decimal floating point operation described by CODE. | |
630 For a unary operation, OP1 will be NULL. This function returns | |
631 true if the result may be inexact due to loss of precision. */ | |
632 | |
633 bool | |
634 decimal_real_arithmetic (REAL_VALUE_TYPE *r, enum tree_code code, | |
635 const REAL_VALUE_TYPE *op0, | |
636 const REAL_VALUE_TYPE *op1) | |
637 { | |
638 REAL_VALUE_TYPE a, b; | |
639 | |
640 /* If either operand is non-decimal, create temporaries. */ | |
641 if (!op0->decimal) | |
642 { | |
643 decimal_from_binary (&a, op0); | |
644 op0 = &a; | |
645 } | |
646 if (op1 && !op1->decimal) | |
647 { | |
648 decimal_from_binary (&b, op1); | |
649 op1 = &b; | |
650 } | |
651 | |
652 switch (code) | |
653 { | |
654 case PLUS_EXPR: | |
655 return decimal_do_add (r, op0, op1, 0); | |
656 | |
657 case MINUS_EXPR: | |
658 return decimal_do_add (r, op0, op1, 1); | |
659 | |
660 case MULT_EXPR: | |
661 return decimal_do_multiply (r, op0, op1); | |
662 | |
663 case RDIV_EXPR: | |
664 return decimal_do_divide (r, op0, op1); | |
665 | |
666 case MIN_EXPR: | |
667 if (op1->cl == rvc_nan) | |
668 *r = *op1; | |
669 else if (real_compare (UNLT_EXPR, op0, op1)) | |
670 *r = *op0; | |
671 else | |
672 *r = *op1; | |
673 return false; | |
674 | |
675 case MAX_EXPR: | |
676 if (op1->cl == rvc_nan) | |
677 *r = *op1; | |
678 else if (real_compare (LT_EXPR, op0, op1)) | |
679 *r = *op1; | |
680 else | |
681 *r = *op0; | |
682 return false; | |
683 | |
684 case NEGATE_EXPR: | |
685 { | |
686 *r = *op0; | |
687 /* Flip sign bit. */ | |
688 decimal128FlipSign ((decimal128 *) r->sig); | |
689 /* Keep sign field in sync. */ | |
690 r->sign ^= 1; | |
691 } | |
692 return false; | |
693 | |
694 case ABS_EXPR: | |
695 { | |
696 *r = *op0; | |
697 /* Clear sign bit. */ | |
698 decimal128ClearSign ((decimal128 *) r->sig); | |
699 /* Keep sign field in sync. */ | |
700 r->sign = 0; | |
701 } | |
702 return false; | |
703 | |
704 case FIX_TRUNC_EXPR: | |
705 decimal_do_fix_trunc (r, op0); | |
706 return false; | |
707 | |
708 default: | |
709 gcc_unreachable (); | |
710 } | |
711 } | |
712 | |
713 /* Fills R with the largest finite value representable in mode MODE. | |
714 If SIGN is nonzero, R is set to the most negative finite value. */ | |
715 | |
716 void | |
111 | 717 decimal_real_maxval (REAL_VALUE_TYPE *r, int sign, machine_mode mode) |
55
77e2b8dfacca
update it from 4.4.3 to 4.5.0
ryoma <e075725@ie.u-ryukyu.ac.jp>
parents:
19
diff
changeset
|
718 { |
0 | 719 const char *max; |
720 | |
721 switch (mode) | |
722 { | |
111 | 723 case E_SDmode: |
0 | 724 max = "9.999999E96"; |
725 break; | |
111 | 726 case E_DDmode: |
0 | 727 max = "9.999999999999999E384"; |
728 break; | |
111 | 729 case E_TDmode: |
0 | 730 max = "9.999999999999999999999999999999999E6144"; |
731 break; | |
732 default: | |
733 gcc_unreachable (); | |
734 } | |
735 | |
736 decimal_real_from_string (r, max); | |
737 if (sign) | |
738 decimal128SetSign ((decimal128 *) r->sig, 1); | |
739 } |