OSDN Git Service

* dfp.h (decimal_binop): Convert LEN_RESULT to input parameter.
[pf3gnuchains/pf3gnuchains3x.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 /* Perform operation OP with operands X and Y with sizes LEN_X and LEN_Y
259    and store value in RESULT with size LEN_RESULT.  */
260 void
261 decimal_binop (enum exp_opcode op, const gdb_byte *x, int len_x,
262                const gdb_byte *y, int len_y, gdb_byte *result, int len_result)
263 {
264   decContext set;
265   decNumber number1, number2, number3;
266   gdb_byte dec1[16], dec2[16], dec3[16];
267
268   match_endianness (x, len_x, dec1);
269   match_endianness (y, len_y, dec2);
270
271   decimal_to_number (dec1, len_x, &number1);
272   decimal_to_number (dec2, len_y, &number2);
273
274   set_decnumber_context (&set, len_result);
275
276   switch (op)
277     {
278       case BINOP_ADD:
279         decNumberAdd (&number3, &number1, &number2, &set);
280         break;
281       case BINOP_SUB:
282         decNumberSubtract (&number3, &number1, &number2, &set);
283         break;
284       case BINOP_MUL:
285         decNumberMultiply (&number3, &number1, &number2, &set);
286         break;
287       case BINOP_DIV:
288         decNumberDivide (&number3, &number1, &number2, &set);
289         break;
290       case BINOP_EXP:
291         decNumberPower (&number3, &number1, &number2, &set);
292         break;
293       default:
294         internal_error (__FILE__, __LINE__,
295                         _("Unknown decimal floating point operation."));
296         break;
297     }
298
299   /* Check for errors in the DFP operation.  */
300   decimal_check_errors (&set);
301
302   decimal_from_number (&number3, dec3, len_result);
303
304   match_endianness (dec3, len_result, result);
305 }
306
307 /* Returns true if X (which is LEN bytes wide) is the number zero.  */
308 int
309 decimal_is_zero (const gdb_byte *x, int len)
310 {
311   decNumber number;
312   gdb_byte dec[16];
313
314   match_endianness (x, len, dec);
315   decimal_to_number (dec, len, &number);
316
317   return decNumberIsZero (&number);
318 }
319
320 /* Compares two numbers numerically.  If X is less than Y then the return value
321    will be -1.  If they are equal, then the return value will be 0.  If X is
322    greater than the Y then the return value will be 1.  */
323 int
324 decimal_compare (const gdb_byte *x, int len_x, const gdb_byte *y, int len_y)
325 {
326   decNumber number1, number2, result;
327   decContext set;
328   gdb_byte dec1[16], dec2[16];
329   int len_result;
330
331   match_endianness (x, len_x, dec1);
332   match_endianness (y, len_y, dec2);
333
334   decimal_to_number (dec1, len_x, &number1);
335   decimal_to_number (dec2, len_y, &number2);
336
337   /* Perform the comparison in the larger of the two sizes.  */
338   len_result = len_x > len_y ? len_x : len_y;
339   set_decnumber_context (&set, len_result);
340
341   decNumberCompare (&result, &number1, &number2, &set);
342
343   /* Check for errors in the DFP operation.  */
344   decimal_check_errors (&set);
345
346   if (decNumberIsNaN (&result))
347     error (_("Comparison with an invalid number (NaN)."));
348   else if (decNumberIsZero (&result))
349     return 0;
350   else if (decNumberIsNegative (&result))
351     return -1;
352   else
353     return 1;
354 }
355
356 /* Convert a decimal value from a decimal type with LEN_FROM bytes to a
357    decimal type with LEN_TO bytes.  */
358 void
359 decimal_convert (const gdb_byte *from, int len_from, gdb_byte *to,
360                  int len_to)
361 {
362   decNumber number;
363   gdb_byte dec[16];
364
365   match_endianness (from, len_from, dec);
366
367   decimal_to_number (dec, len_from, &number);
368   decimal_from_number (&number, dec, len_to);
369
370   match_endianness (dec, len_to, to);
371 }