xref: /dragonfly/contrib/gdb-7/gdb/dfp.c (revision a68e0df0)
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, enum bfd_endian byte_order,
38 		  gdb_byte *to)
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 
48   if (byte_order == OPPOSITE_BYTE_ORDER)
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 
58 /* Helper function to get the appropriate libdecnumber context for each size
59    of decimal float.  */
60 static void
61 set_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.  */
80 static void
81 decimal_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.  */
98 static void
99 decimal_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.  */
121 static void
122 decimal_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 
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.  */
144 void
145 decimal_to_string (const gdb_byte *decbytes, int len,
146 		   enum bfd_endian byte_order, char *s)
147 {
148   gdb_byte dec[16];
149 
150   match_endianness (decbytes, len, byte_order, dec);
151 
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:
164 	error (_("Unknown decimal floating point type."));
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.  */
172 int
173 decimal_from_string (gdb_byte *decbytes, int len, enum bfd_endian byte_order,
174 		     const char *string)
175 {
176   decContext set;
177   gdb_byte dec[16];
178 
179   set_decnumber_context (&set, len);
180 
181   switch (len)
182     {
183       case 4:
184 	decimal32FromString ((decimal32 *) dec, string, &set);
185 	break;
186       case 8:
187 	decimal64FromString ((decimal64 *) dec, string, &set);
188 	break;
189       case 16:
190 	decimal128FromString ((decimal128 *) dec, string, &set);
191 	break;
192       default:
193 	error (_("Unknown decimal floating point type."));
194 	break;
195     }
196 
197   match_endianness (dec, len, byte_order, decbytes);
198 
199   /* Check for errors in the DFP operation.  */
200   decimal_check_errors (&set);
201 
202   return 1;
203 }
204 
205 /* Converts a value of an integral type to a decimal float of
206    specified LEN bytes.  */
207 void
208 decimal_from_integral (struct value *from,
209 		       gdb_byte *to, int len, enum bfd_endian byte_order)
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);
230   match_endianness (dec, len, byte_order, to);
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.  */
238 void
239 decimal_from_floating (struct value *from,
240 		       gdb_byte *to, int len, enum bfd_endian byte_order)
241 {
242   char *buffer;
243 
244   buffer = xstrprintf ("%.30" DOUBLEST_PRINT_FORMAT, value_as_double (from));
245 
246   decimal_from_string (to, len, byte_order, buffer);
247 
248   xfree (buffer);
249 }
250 
251 /* Converts a decimal float of LEN bytes to a double value.  */
252 DOUBLEST
253 decimal_to_doublest (const gdb_byte *from, int len, enum bfd_endian byte_order)
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.  */
259   decimal_to_string (from, len, byte_order, buffer);
260   return strtod (buffer, NULL);
261 }
262 
263 /* Perform operation OP with operands X and Y with sizes LEN_X and LEN_Y
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.  */
266 void
267 decimal_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)
272 {
273   decContext set;
274   decNumber number1, number2, number3;
275   gdb_byte dec1[16], dec2[16], dec3[16];
276 
277   match_endianness (x, len_x, byte_order_x, dec1);
278   match_endianness (y, len_y, byte_order_y, dec2);
279 
280   decimal_to_number (dec1, len_x, &number1);
281   decimal_to_number (dec2, len_y, &number2);
282 
283   set_decnumber_context (&set, len_result);
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 
311   decimal_from_number (&number3, dec3, len_result);
312 
313   match_endianness (dec3, len_result, byte_order_result, result);
314 }
315 
316 /* Returns true if X (which is LEN bytes wide) is the number zero.  */
317 int
318 decimal_is_zero (const gdb_byte *x, int len, enum bfd_endian byte_order)
319 {
320   decNumber number;
321   gdb_byte dec[16];
322 
323   match_endianness (x, len, byte_order, dec);
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.  */
332 int
333 decimal_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)
335 {
336   decNumber number1, number2, result;
337   decContext set;
338   gdb_byte dec1[16], dec2[16];
339   int len_result;
340 
341   match_endianness (x, len_x, byte_order_x, dec1);
342   match_endianness (y, len_y, byte_order_y, dec2);
343 
344   decimal_to_number (dec1, len_x, &number1);
345   decimal_to_number (dec2, len_y, &number2);
346 
347   /* Perform the comparison in the larger of the two sizes.  */
348   len_result = len_x > len_y ? len_x : len_y;
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.  */
368 void
369 decimal_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)
372 {
373   decNumber number;
374   gdb_byte dec[16];
375 
376   match_endianness (from, len_from, byte_order_from, dec);
377 
378   decimal_to_number (dec, len_from, &number);
379   decimal_from_number (&number, dec, len_to);
380 
381   match_endianness (dec, len_to, byte_order_to, to);
382 }
383