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