2010-04-28 Kai Tietz <kai.tietz@onevision.com>
[deliverable/binutils-gdb.git] / gdb / dfp.c
CommitLineData
9b913628
TJB
1/* Decimal floating point support for GDB.
2
4c38e0a4 3 Copyright 2007, 2008, 2009, 2010 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;
92 error (_("Cannot perform operation: %s"), decContextStatusToString (ctx));
93 }
94}
95
96/* Helper function to convert from libdecnumber's appropriate representation
97 for computation to each size of decimal float. */
98static void
99decimal_from_number (const decNumber *from, gdb_byte *to, int len)
100{
101 decContext set;
102
103 set_decnumber_context (&set, len);
104
105 switch (len)
106 {
107 case 4:
108 decimal32FromNumber ((decimal32 *) to, from, &set);
109 break;
110 case 8:
111 decimal64FromNumber ((decimal64 *) to, from, &set);
112 break;
113 case 16:
114 decimal128FromNumber ((decimal128 *) to, from, &set);
115 break;
116 }
117}
118
119/* Helper function to convert each size of decimal float to libdecnumber's
120 appropriate representation for computation. */
121static void
122decimal_to_number (const gdb_byte *from, int len, decNumber *to)
123{
124 switch (len)
125 {
126 case 4:
127 decimal32ToNumber ((decimal32 *) from, to);
128 break;
129 case 8:
130 decimal64ToNumber ((decimal64 *) from, to);
131 break;
132 case 16:
133 decimal128ToNumber ((decimal128 *) from, to);
134 break;
135 default:
136 error (_("Unknown decimal floating point type.\n"));
137 break;
138 }
139}
140
9b913628
TJB
141/* Convert decimal type to its string representation. LEN is the length
142 of the decimal type, 4 bytes for decimal32, 8 bytes for decimal64 and
143 16 bytes for decimal128. */
144void
e17a4113
UW
145decimal_to_string (const gdb_byte *decbytes, int len,
146 enum bfd_endian byte_order, char *s)
9b913628
TJB
147{
148 gdb_byte dec[16];
149
e17a4113 150 match_endianness (decbytes, len, byte_order, dec);
4ef30785 151
9b913628
TJB
152 switch (len)
153 {
154 case 4:
155 decimal32ToString ((decimal32 *) dec, s);
156 break;
157 case 8:
158 decimal64ToString ((decimal64 *) dec, s);
159 break;
160 case 16:
161 decimal128ToString ((decimal128 *) dec, s);
162 break;
163 default:
a4ae0ca1 164 error (_("Unknown decimal floating point type."));
9b913628
TJB
165 break;
166 }
167}
168
169/* Convert the string form of a decimal value to its decimal representation.
170 LEN is the length of the decimal type, 4 bytes for decimal32, 8 bytes for
171 decimal64 and 16 bytes for decimal128. */
172int
e17a4113
UW
173decimal_from_string (gdb_byte *decbytes, int len, enum bfd_endian byte_order,
174 const char *string)
9b913628
TJB
175{
176 decContext set;
177 gdb_byte dec[16];
178
4ef30785
TJB
179 set_decnumber_context (&set, len);
180
9b913628
TJB
181 switch (len)
182 {
183 case 4:
9b913628
TJB
184 decimal32FromString ((decimal32 *) dec, string, &set);
185 break;
186 case 8:
9b913628
TJB
187 decimal64FromString ((decimal64 *) dec, string, &set);
188 break;
189 case 16:
9b913628
TJB
190 decimal128FromString ((decimal128 *) dec, string, &set);
191 break;
192 default:
a4ae0ca1 193 error (_("Unknown decimal floating point type."));
9b913628
TJB
194 break;
195 }
196
e17a4113 197 match_endianness (dec, len, byte_order, decbytes);
9b913628 198
4ef30785
TJB
199 /* Check for errors in the DFP operation. */
200 decimal_check_errors (&set);
201
9b913628
TJB
202 return 1;
203}
4ef30785
TJB
204
205/* Converts a value of an integral type to a decimal float of
206 specified LEN bytes. */
207void
e17a4113
UW
208decimal_from_integral (struct value *from,
209 gdb_byte *to, int len, enum bfd_endian byte_order)
4ef30785
TJB
210{
211 LONGEST l;
212 gdb_byte dec[16];
213 decNumber number;
214 struct type *type;
215
216 type = check_typedef (value_type (from));
217
218 if (TYPE_LENGTH (type) > 4)
219 /* libdecnumber can convert only 32-bit integers. */
220 error (_("Conversion of large integer to a decimal floating type is not supported."));
221
222 l = value_as_long (from);
223
224 if (TYPE_UNSIGNED (type))
225 decNumberFromUInt32 (&number, (unsigned int) l);
226 else
227 decNumberFromInt32 (&number, (int) l);
228
229 decimal_from_number (&number, dec, len);
e17a4113 230 match_endianness (dec, len, byte_order, to);
4ef30785
TJB
231}
232
233/* Converts a value of a float type to a decimal float of
234 specified LEN bytes.
235
236 This is an ugly way to do the conversion, but libdecnumber does
237 not offer a direct way to do it. */
238void
e17a4113
UW
239decimal_from_floating (struct value *from,
240 gdb_byte *to, int len, enum bfd_endian byte_order)
4ef30785
TJB
241{
242 char *buffer;
4ef30785 243
6c761d9c 244 buffer = xstrprintf ("%.30" DOUBLEST_PRINT_FORMAT, value_as_double (from));
4ef30785 245
e17a4113 246 decimal_from_string (to, len, byte_order, buffer);
4ef30785 247
6c761d9c 248 xfree (buffer);
4ef30785
TJB
249}
250
251/* Converts a decimal float of LEN bytes to a double value. */
252DOUBLEST
e17a4113 253decimal_to_doublest (const gdb_byte *from, int len, enum bfd_endian byte_order)
4ef30785
TJB
254{
255 char buffer[MAX_DECIMAL_STRING];
256
257 /* This is an ugly way to do the conversion, but libdecnumber does
258 not offer a direct way to do it. */
e17a4113 259 decimal_to_string (from, len, byte_order, buffer);
4ef30785
TJB
260 return strtod (buffer, NULL);
261}
262
289bd67a 263/* Perform operation OP with operands X and Y with sizes LEN_X and LEN_Y
e17a4113
UW
264 and byte orders BYTE_ORDER_X and BYTE_ORDER_Y, and store value in
265 RESULT with size LEN_RESULT and byte order BYTE_ORDER_RESULT. */
4ef30785 266void
e17a4113
UW
267decimal_binop (enum exp_opcode op,
268 const gdb_byte *x, int len_x, enum bfd_endian byte_order_x,
269 const gdb_byte *y, int len_y, enum bfd_endian byte_order_y,
270 gdb_byte *result, int len_result,
271 enum bfd_endian byte_order_result)
4ef30785
TJB
272{
273 decContext set;
274 decNumber number1, number2, number3;
275 gdb_byte dec1[16], dec2[16], dec3[16];
276
e17a4113
UW
277 match_endianness (x, len_x, byte_order_x, dec1);
278 match_endianness (y, len_y, byte_order_y, dec2);
4ef30785 279
289bd67a
UW
280 decimal_to_number (dec1, len_x, &number1);
281 decimal_to_number (dec2, len_y, &number2);
4ef30785 282
289bd67a 283 set_decnumber_context (&set, len_result);
4ef30785
TJB
284
285 switch (op)
286 {
287 case BINOP_ADD:
288 decNumberAdd (&number3, &number1, &number2, &set);
289 break;
290 case BINOP_SUB:
291 decNumberSubtract (&number3, &number1, &number2, &set);
292 break;
293 case BINOP_MUL:
294 decNumberMultiply (&number3, &number1, &number2, &set);
295 break;
296 case BINOP_DIV:
297 decNumberDivide (&number3, &number1, &number2, &set);
298 break;
299 case BINOP_EXP:
300 decNumberPower (&number3, &number1, &number2, &set);
301 break;
302 default:
303 internal_error (__FILE__, __LINE__,
304 _("Unknown decimal floating point operation."));
305 break;
306 }
307
308 /* Check for errors in the DFP operation. */
309 decimal_check_errors (&set);
310
289bd67a 311 decimal_from_number (&number3, dec3, len_result);
4ef30785 312
e17a4113 313 match_endianness (dec3, len_result, byte_order_result, result);
4ef30785
TJB
314}
315
316/* Returns true if X (which is LEN bytes wide) is the number zero. */
317int
e17a4113 318decimal_is_zero (const gdb_byte *x, int len, enum bfd_endian byte_order)
4ef30785
TJB
319{
320 decNumber number;
321 gdb_byte dec[16];
322
e17a4113 323 match_endianness (x, len, byte_order, dec);
4ef30785
TJB
324 decimal_to_number (dec, len, &number);
325
326 return decNumberIsZero (&number);
327}
328
329/* Compares two numbers numerically. If X is less than Y then the return value
330 will be -1. If they are equal, then the return value will be 0. If X is
331 greater than the Y then the return value will be 1. */
332int
e17a4113
UW
333decimal_compare (const gdb_byte *x, int len_x, enum bfd_endian byte_order_x,
334 const gdb_byte *y, int len_y, enum bfd_endian byte_order_y)
4ef30785
TJB
335{
336 decNumber number1, number2, result;
337 decContext set;
338 gdb_byte dec1[16], dec2[16];
339 int len_result;
340
e17a4113
UW
341 match_endianness (x, len_x, byte_order_x, dec1);
342 match_endianness (y, len_y, byte_order_y, dec2);
4ef30785 343
289bd67a
UW
344 decimal_to_number (dec1, len_x, &number1);
345 decimal_to_number (dec2, len_y, &number2);
4ef30785 346
289bd67a
UW
347 /* Perform the comparison in the larger of the two sizes. */
348 len_result = len_x > len_y ? len_x : len_y;
4ef30785
TJB
349 set_decnumber_context (&set, len_result);
350
351 decNumberCompare (&result, &number1, &number2, &set);
352
353 /* Check for errors in the DFP operation. */
354 decimal_check_errors (&set);
355
356 if (decNumberIsNaN (&result))
357 error (_("Comparison with an invalid number (NaN)."));
358 else if (decNumberIsZero (&result))
359 return 0;
360 else if (decNumberIsNegative (&result))
361 return -1;
362 else
363 return 1;
364}
365
366/* Convert a decimal value from a decimal type with LEN_FROM bytes to a
367 decimal type with LEN_TO bytes. */
368void
e17a4113
UW
369decimal_convert (const gdb_byte *from, int len_from,
370 enum bfd_endian byte_order_from, gdb_byte *to, int len_to,
371 enum bfd_endian byte_order_to)
4ef30785
TJB
372{
373 decNumber number;
cd0b43b1
JM
374 gdb_byte dec[16];
375
e17a4113 376 match_endianness (from, len_from, byte_order_from, dec);
cd0b43b1
JM
377
378 decimal_to_number (dec, len_from, &number);
379 decimal_from_number (&number, dec, len_to);
4ef30785 380
e17a4113 381 match_endianness (dec, len_to, byte_order_to, to);
4ef30785 382}
This page took 0.222556 seconds and 4 git commands to generate.