gdb/testsuite/
[deliverable/binutils-gdb.git] / gdb / dfp.c
CommitLineData
9b913628
TJB
1/* Decimal floating point support for GDB.
2
0b302171 3 Copyright 2007-2012 Free Software Foundation, Inc.
9b913628
TJB
4
5 This file is part of GDB.
6
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
11
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
16
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>. */
19
20#include "defs.h"
4ef30785
TJB
21#include "expression.h"
22#include "gdbtypes.h"
23#include "value.h"
24#include "dfp.h"
9b913628
TJB
25
26/* The order of the following headers is important for making sure
27 decNumber structure is large enough to hold decimal128 digits. */
28
29#include "dpd/decimal128.h"
30#include "dpd/decimal64.h"
31#include "dpd/decimal32.h"
32
33/* In GDB, we are using an array of gdb_byte to represent decimal values.
34 They are stored in host byte order. This routine does the conversion if
35 the target byte order is different. */
36static void
e17a4113
UW
37match_endianness (const gdb_byte *from, int len, enum bfd_endian byte_order,
38 gdb_byte *to)
9b913628
TJB
39{
40 int i;
41
42#if WORDS_BIGENDIAN
43#define OPPOSITE_BYTE_ORDER BFD_ENDIAN_LITTLE
44#else
45#define OPPOSITE_BYTE_ORDER BFD_ENDIAN_BIG
46#endif
47
e17a4113 48 if (byte_order == OPPOSITE_BYTE_ORDER)
9b913628
TJB
49 for (i = 0; i < len; i++)
50 to[i] = from[len - i - 1];
51 else
52 for (i = 0; i < len; i++)
53 to[i] = from[i];
54
55 return;
56}
57
4ef30785
TJB
58/* Helper function to get the appropriate libdecnumber context for each size
59 of decimal float. */
60static void
61set_decnumber_context (decContext *ctx, int len)
62{
63 switch (len)
64 {
65 case 4:
66 decContextDefault (ctx, DEC_INIT_DECIMAL32);
67 break;
68 case 8:
69 decContextDefault (ctx, DEC_INIT_DECIMAL64);
70 break;
71 case 16:
72 decContextDefault (ctx, DEC_INIT_DECIMAL128);
73 break;
74 }
75
76 ctx->traps = 0;
77}
78
79/* Check for errors signaled in the decimal context structure. */
80static void
81decimal_check_errors (decContext *ctx)
82{
83 /* An error here could be a division by zero, an overflow, an underflow or
84 an invalid operation (from the DEC_Errors constant in decContext.h).
85 Since GDB doesn't complain about division by zero, overflow or underflow
86 errors for binary floating, we won't complain about them for decimal
87 floating either. */
88 if (ctx->status & DEC_IEEE_854_Invalid_operation)
89 {
90 /* Leave only the error bits in the status flags. */
91 ctx->status &= DEC_IEEE_854_Invalid_operation;
3e43a32a
MS
92 error (_("Cannot perform operation: %s"),
93 decContextStatusToString (ctx));
4ef30785
TJB
94 }
95}
96
97/* Helper function to convert from libdecnumber's appropriate representation
98 for computation to each size of decimal float. */
99static void
100decimal_from_number (const decNumber *from, gdb_byte *to, int len)
101{
102 decContext set;
103
104 set_decnumber_context (&set, len);
105
106 switch (len)
107 {
108 case 4:
109 decimal32FromNumber ((decimal32 *) to, from, &set);
110 break;
111 case 8:
112 decimal64FromNumber ((decimal64 *) to, from, &set);
113 break;
114 case 16:
115 decimal128FromNumber ((decimal128 *) to, from, &set);
116 break;
117 }
118}
119
120/* Helper function to convert each size of decimal float to libdecnumber's
121 appropriate representation for computation. */
122static void
123decimal_to_number (const gdb_byte *from, int len, decNumber *to)
124{
125 switch (len)
126 {
127 case 4:
128 decimal32ToNumber ((decimal32 *) from, to);
129 break;
130 case 8:
131 decimal64ToNumber ((decimal64 *) from, to);
132 break;
133 case 16:
134 decimal128ToNumber ((decimal128 *) from, to);
135 break;
136 default:
b37520b6 137 error (_("Unknown decimal floating point type."));
4ef30785
TJB
138 break;
139 }
140}
141
9b913628
TJB
142/* Convert decimal type to its string representation. LEN is the length
143 of the decimal type, 4 bytes for decimal32, 8 bytes for decimal64 and
144 16 bytes for decimal128. */
145void
e17a4113
UW
146decimal_to_string (const gdb_byte *decbytes, int len,
147 enum bfd_endian byte_order, char *s)
9b913628
TJB
148{
149 gdb_byte dec[16];
150
e17a4113 151 match_endianness (decbytes, len, byte_order, dec);
4ef30785 152
9b913628
TJB
153 switch (len)
154 {
155 case 4:
156 decimal32ToString ((decimal32 *) dec, s);
157 break;
158 case 8:
159 decimal64ToString ((decimal64 *) dec, s);
160 break;
161 case 16:
162 decimal128ToString ((decimal128 *) dec, s);
163 break;
164 default:
a4ae0ca1 165 error (_("Unknown decimal floating point type."));
9b913628
TJB
166 break;
167 }
168}
169
170/* Convert the string form of a decimal value to its decimal representation.
171 LEN is the length of the decimal type, 4 bytes for decimal32, 8 bytes for
172 decimal64 and 16 bytes for decimal128. */
173int
e17a4113
UW
174decimal_from_string (gdb_byte *decbytes, int len, enum bfd_endian byte_order,
175 const char *string)
9b913628
TJB
176{
177 decContext set;
178 gdb_byte dec[16];
179
4ef30785
TJB
180 set_decnumber_context (&set, len);
181
9b913628
TJB
182 switch (len)
183 {
184 case 4:
9b913628
TJB
185 decimal32FromString ((decimal32 *) dec, string, &set);
186 break;
187 case 8:
9b913628
TJB
188 decimal64FromString ((decimal64 *) dec, string, &set);
189 break;
190 case 16:
9b913628
TJB
191 decimal128FromString ((decimal128 *) dec, string, &set);
192 break;
193 default:
a4ae0ca1 194 error (_("Unknown decimal floating point type."));
9b913628
TJB
195 break;
196 }
197
e17a4113 198 match_endianness (dec, len, byte_order, decbytes);
9b913628 199
4ef30785
TJB
200 /* Check for errors in the DFP operation. */
201 decimal_check_errors (&set);
202
9b913628
TJB
203 return 1;
204}
4ef30785
TJB
205
206/* Converts a value of an integral type to a decimal float of
207 specified LEN bytes. */
208void
e17a4113
UW
209decimal_from_integral (struct value *from,
210 gdb_byte *to, int len, enum bfd_endian byte_order)
4ef30785
TJB
211{
212 LONGEST l;
213 gdb_byte dec[16];
214 decNumber number;
215 struct type *type;
216
217 type = check_typedef (value_type (from));
218
219 if (TYPE_LENGTH (type) > 4)
220 /* libdecnumber can convert only 32-bit integers. */
3e43a32a
MS
221 error (_("Conversion of large integer to a "
222 "decimal floating type is not supported."));
4ef30785
TJB
223
224 l = value_as_long (from);
225
226 if (TYPE_UNSIGNED (type))
227 decNumberFromUInt32 (&number, (unsigned int) l);
228 else
229 decNumberFromInt32 (&number, (int) l);
230
231 decimal_from_number (&number, dec, len);
e17a4113 232 match_endianness (dec, len, byte_order, to);
4ef30785
TJB
233}
234
235/* Converts a value of a float type to a decimal float of
236 specified LEN bytes.
237
238 This is an ugly way to do the conversion, but libdecnumber does
239 not offer a direct way to do it. */
240void
e17a4113
UW
241decimal_from_floating (struct value *from,
242 gdb_byte *to, int len, enum bfd_endian byte_order)
4ef30785
TJB
243{
244 char *buffer;
4ef30785 245
6c761d9c 246 buffer = xstrprintf ("%.30" DOUBLEST_PRINT_FORMAT, value_as_double (from));
4ef30785 247
e17a4113 248 decimal_from_string (to, len, byte_order, buffer);
4ef30785 249
6c761d9c 250 xfree (buffer);
4ef30785
TJB
251}
252
253/* Converts a decimal float of LEN bytes to a double value. */
254DOUBLEST
e17a4113 255decimal_to_doublest (const gdb_byte *from, int len, enum bfd_endian byte_order)
4ef30785
TJB
256{
257 char buffer[MAX_DECIMAL_STRING];
258
259 /* This is an ugly way to do the conversion, but libdecnumber does
260 not offer a direct way to do it. */
e17a4113 261 decimal_to_string (from, len, byte_order, buffer);
4ef30785
TJB
262 return strtod (buffer, NULL);
263}
264
289bd67a 265/* Perform operation OP with operands X and Y with sizes LEN_X and LEN_Y
e17a4113
UW
266 and byte orders BYTE_ORDER_X and BYTE_ORDER_Y, and store value in
267 RESULT with size LEN_RESULT and byte order BYTE_ORDER_RESULT. */
4ef30785 268void
e17a4113
UW
269decimal_binop (enum exp_opcode op,
270 const gdb_byte *x, int len_x, enum bfd_endian byte_order_x,
271 const gdb_byte *y, int len_y, enum bfd_endian byte_order_y,
272 gdb_byte *result, int len_result,
273 enum bfd_endian byte_order_result)
4ef30785
TJB
274{
275 decContext set;
276 decNumber number1, number2, number3;
277 gdb_byte dec1[16], dec2[16], dec3[16];
278
e17a4113
UW
279 match_endianness (x, len_x, byte_order_x, dec1);
280 match_endianness (y, len_y, byte_order_y, dec2);
4ef30785 281
289bd67a
UW
282 decimal_to_number (dec1, len_x, &number1);
283 decimal_to_number (dec2, len_y, &number2);
4ef30785 284
289bd67a 285 set_decnumber_context (&set, len_result);
4ef30785
TJB
286
287 switch (op)
288 {
289 case BINOP_ADD:
290 decNumberAdd (&number3, &number1, &number2, &set);
291 break;
292 case BINOP_SUB:
293 decNumberSubtract (&number3, &number1, &number2, &set);
294 break;
295 case BINOP_MUL:
296 decNumberMultiply (&number3, &number1, &number2, &set);
297 break;
298 case BINOP_DIV:
299 decNumberDivide (&number3, &number1, &number2, &set);
300 break;
301 case BINOP_EXP:
302 decNumberPower (&number3, &number1, &number2, &set);
303 break;
304 default:
305 internal_error (__FILE__, __LINE__,
306 _("Unknown decimal floating point operation."));
307 break;
308 }
309
310 /* Check for errors in the DFP operation. */
311 decimal_check_errors (&set);
312
289bd67a 313 decimal_from_number (&number3, dec3, len_result);
4ef30785 314
e17a4113 315 match_endianness (dec3, len_result, byte_order_result, result);
4ef30785
TJB
316}
317
318/* Returns true if X (which is LEN bytes wide) is the number zero. */
319int
e17a4113 320decimal_is_zero (const gdb_byte *x, int len, enum bfd_endian byte_order)
4ef30785
TJB
321{
322 decNumber number;
323 gdb_byte dec[16];
324
e17a4113 325 match_endianness (x, len, byte_order, dec);
4ef30785
TJB
326 decimal_to_number (dec, len, &number);
327
328 return decNumberIsZero (&number);
329}
330
331/* Compares two numbers numerically. If X is less than Y then the return value
332 will be -1. If they are equal, then the return value will be 0. If X is
333 greater than the Y then the return value will be 1. */
334int
e17a4113
UW
335decimal_compare (const gdb_byte *x, int len_x, enum bfd_endian byte_order_x,
336 const gdb_byte *y, int len_y, enum bfd_endian byte_order_y)
4ef30785
TJB
337{
338 decNumber number1, number2, result;
339 decContext set;
340 gdb_byte dec1[16], dec2[16];
341 int len_result;
342
e17a4113
UW
343 match_endianness (x, len_x, byte_order_x, dec1);
344 match_endianness (y, len_y, byte_order_y, dec2);
4ef30785 345
289bd67a
UW
346 decimal_to_number (dec1, len_x, &number1);
347 decimal_to_number (dec2, len_y, &number2);
4ef30785 348
289bd67a
UW
349 /* Perform the comparison in the larger of the two sizes. */
350 len_result = len_x > len_y ? len_x : len_y;
4ef30785
TJB
351 set_decnumber_context (&set, len_result);
352
353 decNumberCompare (&result, &number1, &number2, &set);
354
355 /* Check for errors in the DFP operation. */
356 decimal_check_errors (&set);
357
358 if (decNumberIsNaN (&result))
359 error (_("Comparison with an invalid number (NaN)."));
360 else if (decNumberIsZero (&result))
361 return 0;
362 else if (decNumberIsNegative (&result))
363 return -1;
364 else
365 return 1;
366}
367
368/* Convert a decimal value from a decimal type with LEN_FROM bytes to a
369 decimal type with LEN_TO bytes. */
370void
e17a4113
UW
371decimal_convert (const gdb_byte *from, int len_from,
372 enum bfd_endian byte_order_from, gdb_byte *to, int len_to,
373 enum bfd_endian byte_order_to)
4ef30785
TJB
374{
375 decNumber number;
cd0b43b1
JM
376 gdb_byte dec[16];
377
e17a4113 378 match_endianness (from, len_from, byte_order_from, dec);
cd0b43b1
JM
379
380 decimal_to_number (dec, len_from, &number);
381 decimal_from_number (&number, dec, len_to);
4ef30785 382
e17a4113 383 match_endianness (dec, len_to, byte_order_to, to);
4ef30785 384}
This page took 0.386945 seconds and 4 git commands to generate.