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