* i386-linux-tdep.c (I386_LINUX_RECORD_SIZE_*,
[deliverable/binutils-gdb.git] / gdb / dfp.c
1 /* Decimal floating point support for GDB.
2
3 Copyright 2007, 2008, 2009 Free Software Foundation, Inc.
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"
21 #include "expression.h"
22 #include "gdbtypes.h"
23 #include "value.h"
24 #include "dfp.h"
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. */
36 static void
37 match_endianness (const gdb_byte *from, int len, gdb_byte *to)
38 {
39 int i;
40
41 #if WORDS_BIGENDIAN
42 #define OPPOSITE_BYTE_ORDER BFD_ENDIAN_LITTLE
43 #else
44 #define OPPOSITE_BYTE_ORDER BFD_ENDIAN_BIG
45 #endif
46
47 if (gdbarch_byte_order (current_gdbarch) == OPPOSITE_BYTE_ORDER)
48 for (i = 0; i < len; i++)
49 to[i] = from[len - i - 1];
50 else
51 for (i = 0; i < len; i++)
52 to[i] = from[i];
53
54 return;
55 }
56
57 /* Helper function to get the appropriate libdecnumber context for each size
58 of decimal float. */
59 static void
60 set_decnumber_context (decContext *ctx, int len)
61 {
62 switch (len)
63 {
64 case 4:
65 decContextDefault (ctx, DEC_INIT_DECIMAL32);
66 break;
67 case 8:
68 decContextDefault (ctx, DEC_INIT_DECIMAL64);
69 break;
70 case 16:
71 decContextDefault (ctx, DEC_INIT_DECIMAL128);
72 break;
73 }
74
75 ctx->traps = 0;
76 }
77
78 /* Check for errors signaled in the decimal context structure. */
79 static void
80 decimal_check_errors (decContext *ctx)
81 {
82 /* An error here could be a division by zero, an overflow, an underflow or
83 an invalid operation (from the DEC_Errors constant in decContext.h).
84 Since GDB doesn't complain about division by zero, overflow or underflow
85 errors for binary floating, we won't complain about them for decimal
86 floating either. */
87 if (ctx->status & DEC_IEEE_854_Invalid_operation)
88 {
89 /* Leave only the error bits in the status flags. */
90 ctx->status &= DEC_IEEE_854_Invalid_operation;
91 error (_("Cannot perform operation: %s"), decContextStatusToString (ctx));
92 }
93 }
94
95 /* Helper function to convert from libdecnumber's appropriate representation
96 for computation to each size of decimal float. */
97 static void
98 decimal_from_number (const decNumber *from, gdb_byte *to, int len)
99 {
100 decContext set;
101
102 set_decnumber_context (&set, len);
103
104 switch (len)
105 {
106 case 4:
107 decimal32FromNumber ((decimal32 *) to, from, &set);
108 break;
109 case 8:
110 decimal64FromNumber ((decimal64 *) to, from, &set);
111 break;
112 case 16:
113 decimal128FromNumber ((decimal128 *) to, from, &set);
114 break;
115 }
116 }
117
118 /* Helper function to convert each size of decimal float to libdecnumber's
119 appropriate representation for computation. */
120 static void
121 decimal_to_number (const gdb_byte *from, int len, decNumber *to)
122 {
123 switch (len)
124 {
125 case 4:
126 decimal32ToNumber ((decimal32 *) from, to);
127 break;
128 case 8:
129 decimal64ToNumber ((decimal64 *) from, to);
130 break;
131 case 16:
132 decimal128ToNumber ((decimal128 *) from, to);
133 break;
134 default:
135 error (_("Unknown decimal floating point type.\n"));
136 break;
137 }
138 }
139
140 /* Convert decimal type to its string representation. LEN is the length
141 of the decimal type, 4 bytes for decimal32, 8 bytes for decimal64 and
142 16 bytes for decimal128. */
143 void
144 decimal_to_string (const gdb_byte *decbytes, int len, char *s)
145 {
146 gdb_byte dec[16];
147
148 match_endianness (decbytes, len, dec);
149
150 switch (len)
151 {
152 case 4:
153 decimal32ToString ((decimal32 *) dec, s);
154 break;
155 case 8:
156 decimal64ToString ((decimal64 *) dec, s);
157 break;
158 case 16:
159 decimal128ToString ((decimal128 *) dec, s);
160 break;
161 default:
162 error (_("Unknown decimal floating point type."));
163 break;
164 }
165 }
166
167 /* Convert the string form of a decimal value to its decimal representation.
168 LEN is the length of the decimal type, 4 bytes for decimal32, 8 bytes for
169 decimal64 and 16 bytes for decimal128. */
170 int
171 decimal_from_string (gdb_byte *decbytes, int len, const char *string)
172 {
173 decContext set;
174 gdb_byte dec[16];
175
176 set_decnumber_context (&set, len);
177
178 switch (len)
179 {
180 case 4:
181 decimal32FromString ((decimal32 *) dec, string, &set);
182 break;
183 case 8:
184 decimal64FromString ((decimal64 *) dec, string, &set);
185 break;
186 case 16:
187 decimal128FromString ((decimal128 *) dec, string, &set);
188 break;
189 default:
190 error (_("Unknown decimal floating point type."));
191 break;
192 }
193
194 match_endianness (dec, len, decbytes);
195
196 /* Check for errors in the DFP operation. */
197 decimal_check_errors (&set);
198
199 return 1;
200 }
201
202 /* Converts a value of an integral type to a decimal float of
203 specified LEN bytes. */
204 void
205 decimal_from_integral (struct value *from, gdb_byte *to, int len)
206 {
207 LONGEST l;
208 gdb_byte dec[16];
209 decNumber number;
210 struct type *type;
211
212 type = check_typedef (value_type (from));
213
214 if (TYPE_LENGTH (type) > 4)
215 /* libdecnumber can convert only 32-bit integers. */
216 error (_("Conversion of large integer to a decimal floating type is not supported."));
217
218 l = value_as_long (from);
219
220 if (TYPE_UNSIGNED (type))
221 decNumberFromUInt32 (&number, (unsigned int) l);
222 else
223 decNumberFromInt32 (&number, (int) l);
224
225 decimal_from_number (&number, dec, len);
226 match_endianness (dec, len, to);
227 }
228
229 /* Converts a value of a float type to a decimal float of
230 specified LEN bytes.
231
232 This is an ugly way to do the conversion, but libdecnumber does
233 not offer a direct way to do it. */
234 void
235 decimal_from_floating (struct value *from, gdb_byte *to, int len)
236 {
237 char *buffer;
238
239 buffer = xstrprintf ("%.30" DOUBLEST_PRINT_FORMAT, value_as_double (from));
240
241 decimal_from_string (to, len, buffer);
242
243 xfree (buffer);
244 }
245
246 /* Converts a decimal float of LEN bytes to a double value. */
247 DOUBLEST
248 decimal_to_doublest (const gdb_byte *from, int len)
249 {
250 char buffer[MAX_DECIMAL_STRING];
251
252 /* This is an ugly way to do the conversion, but libdecnumber does
253 not offer a direct way to do it. */
254 decimal_to_string (from, len, buffer);
255 return strtod (buffer, NULL);
256 }
257
258 /* Check if operands have the same size and convert them to the
259 biggest of the two if necessary. */
260 static int
261 promote_decimal (gdb_byte *x, int len_x, gdb_byte *y, int len_y)
262 {
263 int len_result;
264 decNumber number;
265
266 if (len_x < len_y)
267 {
268 decimal_to_number (x, len_x, &number);
269 decimal_from_number (&number, x, len_y);
270 len_result = len_y;
271 }
272 else if (len_x > len_y)
273 {
274 decimal_to_number (y, len_y, &number);
275 decimal_from_number (&number, y, len_x);
276 len_result = len_x;
277 }
278 else
279 len_result = len_x;
280
281 return len_result;
282 }
283
284 /* Perform operation OP with operands X and Y and store value in RESULT.
285 If LEN_X and LEN_Y are not equal, RESULT will have the size of the biggest
286 of the two, and LEN_RESULT will be set accordingly. */
287 void
288 decimal_binop (enum exp_opcode op, const gdb_byte *x, int len_x,
289 const gdb_byte *y, int len_y, gdb_byte *result, int *len_result)
290 {
291 decContext set;
292 decNumber number1, number2, number3;
293 gdb_byte dec1[16], dec2[16], dec3[16];
294
295 match_endianness (x, len_x, dec1);
296 match_endianness (y, len_y, dec2);
297
298 *len_result = promote_decimal (dec1, len_x, dec2, len_y);
299
300 /* Both operands are of size *len_result from now on. */
301
302 decimal_to_number (dec1, *len_result, &number1);
303 decimal_to_number (dec2, *len_result, &number2);
304
305 set_decnumber_context (&set, *len_result);
306
307 switch (op)
308 {
309 case BINOP_ADD:
310 decNumberAdd (&number3, &number1, &number2, &set);
311 break;
312 case BINOP_SUB:
313 decNumberSubtract (&number3, &number1, &number2, &set);
314 break;
315 case BINOP_MUL:
316 decNumberMultiply (&number3, &number1, &number2, &set);
317 break;
318 case BINOP_DIV:
319 decNumberDivide (&number3, &number1, &number2, &set);
320 break;
321 case BINOP_EXP:
322 decNumberPower (&number3, &number1, &number2, &set);
323 break;
324 default:
325 internal_error (__FILE__, __LINE__,
326 _("Unknown decimal floating point operation."));
327 break;
328 }
329
330 /* Check for errors in the DFP operation. */
331 decimal_check_errors (&set);
332
333 decimal_from_number (&number3, dec3, *len_result);
334
335 match_endianness (dec3, *len_result, result);
336 }
337
338 /* Returns true if X (which is LEN bytes wide) is the number zero. */
339 int
340 decimal_is_zero (const gdb_byte *x, int len)
341 {
342 decNumber number;
343 gdb_byte dec[16];
344
345 match_endianness (x, len, dec);
346 decimal_to_number (dec, len, &number);
347
348 return decNumberIsZero (&number);
349 }
350
351 /* Compares two numbers numerically. If X is less than Y then the return value
352 will be -1. If they are equal, then the return value will be 0. If X is
353 greater than the Y then the return value will be 1. */
354 int
355 decimal_compare (const gdb_byte *x, int len_x, const gdb_byte *y, int len_y)
356 {
357 decNumber number1, number2, result;
358 decContext set;
359 gdb_byte dec1[16], dec2[16];
360 int len_result;
361
362 match_endianness (x, len_x, dec1);
363 match_endianness (y, len_y, dec2);
364
365 len_result = promote_decimal (dec1, len_x, dec2, len_y);
366
367 decimal_to_number (dec1, len_result, &number1);
368 decimal_to_number (dec2, len_result, &number2);
369
370 set_decnumber_context (&set, len_result);
371
372 decNumberCompare (&result, &number1, &number2, &set);
373
374 /* Check for errors in the DFP operation. */
375 decimal_check_errors (&set);
376
377 if (decNumberIsNaN (&result))
378 error (_("Comparison with an invalid number (NaN)."));
379 else if (decNumberIsZero (&result))
380 return 0;
381 else if (decNumberIsNegative (&result))
382 return -1;
383 else
384 return 1;
385 }
386
387 /* Convert a decimal value from a decimal type with LEN_FROM bytes to a
388 decimal type with LEN_TO bytes. */
389 void
390 decimal_convert (const gdb_byte *from, int len_from, gdb_byte *to,
391 int len_to)
392 {
393 decNumber number;
394 gdb_byte dec[16];
395
396 match_endianness (from, len_from, dec);
397
398 decimal_to_number (dec, len_from, &number);
399 decimal_from_number (&number, dec, len_to);
400
401 match_endianness (dec, len_to, to);
402 }
This page took 0.037694 seconds and 4 git commands to generate.