xref: /dragonfly/contrib/gdb-7/gdb/dfp.c (revision 67640b13)
1 /* Decimal floating point support for GDB.
2 
3    Copyright (C) 2007-2013 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"),
93 	     decContextStatusToString (ctx));
94     }
95 }
96 
97 /* Helper function to convert from libdecnumber's appropriate representation
98    for computation to each size of decimal float.  */
99 static void
100 decimal_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.  */
122 static void
123 decimal_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:
137 	error (_("Unknown decimal floating point type."));
138 	break;
139     }
140 }
141 
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.  */
145 void
146 decimal_to_string (const gdb_byte *decbytes, int len,
147 		   enum bfd_endian byte_order, char *s)
148 {
149   gdb_byte dec[16];
150 
151   match_endianness (decbytes, len, byte_order, dec);
152 
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:
165 	error (_("Unknown decimal floating point type."));
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.  */
173 int
174 decimal_from_string (gdb_byte *decbytes, int len, enum bfd_endian byte_order,
175 		     const char *string)
176 {
177   decContext set;
178   gdb_byte dec[16];
179 
180   set_decnumber_context (&set, len);
181 
182   switch (len)
183     {
184       case 4:
185 	decimal32FromString ((decimal32 *) dec, string, &set);
186 	break;
187       case 8:
188 	decimal64FromString ((decimal64 *) dec, string, &set);
189 	break;
190       case 16:
191 	decimal128FromString ((decimal128 *) dec, string, &set);
192 	break;
193       default:
194 	error (_("Unknown decimal floating point type."));
195 	break;
196     }
197 
198   match_endianness (dec, len, byte_order, decbytes);
199 
200   /* Check for errors in the DFP operation.  */
201   decimal_check_errors (&set);
202 
203   return 1;
204 }
205 
206 /* Converts a value of an integral type to a decimal float of
207    specified LEN bytes.  */
208 void
209 decimal_from_integral (struct value *from,
210 		       gdb_byte *to, int len, enum bfd_endian byte_order)
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.  */
221     error (_("Conversion of large integer to a "
222 	     "decimal floating type is not supported."));
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);
232   match_endianness (dec, len, byte_order, to);
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.  */
240 void
241 decimal_from_floating (struct value *from,
242 		       gdb_byte *to, int len, enum bfd_endian byte_order)
243 {
244   char *buffer;
245 
246   buffer = xstrprintf ("%.30" DOUBLEST_PRINT_FORMAT, value_as_double (from));
247 
248   decimal_from_string (to, len, byte_order, buffer);
249 
250   xfree (buffer);
251 }
252 
253 /* Converts a decimal float of LEN bytes to a double value.  */
254 DOUBLEST
255 decimal_to_doublest (const gdb_byte *from, int len, enum bfd_endian byte_order)
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.  */
261   decimal_to_string (from, len, byte_order, buffer);
262   return strtod (buffer, NULL);
263 }
264 
265 /* Perform operation OP with operands X and Y with sizes LEN_X and LEN_Y
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.  */
268 void
269 decimal_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)
274 {
275   decContext set;
276   decNumber number1, number2, number3;
277   gdb_byte dec1[16], dec2[16], dec3[16];
278 
279   match_endianness (x, len_x, byte_order_x, dec1);
280   match_endianness (y, len_y, byte_order_y, dec2);
281 
282   decimal_to_number (dec1, len_x, &number1);
283   decimal_to_number (dec2, len_y, &number2);
284 
285   set_decnumber_context (&set, len_result);
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 
313   decimal_from_number (&number3, dec3, len_result);
314 
315   match_endianness (dec3, len_result, byte_order_result, result);
316 }
317 
318 /* Returns true if X (which is LEN bytes wide) is the number zero.  */
319 int
320 decimal_is_zero (const gdb_byte *x, int len, enum bfd_endian byte_order)
321 {
322   decNumber number;
323   gdb_byte dec[16];
324 
325   match_endianness (x, len, byte_order, dec);
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.  */
334 int
335 decimal_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)
337 {
338   decNumber number1, number2, result;
339   decContext set;
340   gdb_byte dec1[16], dec2[16];
341   int len_result;
342 
343   match_endianness (x, len_x, byte_order_x, dec1);
344   match_endianness (y, len_y, byte_order_y, dec2);
345 
346   decimal_to_number (dec1, len_x, &number1);
347   decimal_to_number (dec2, len_y, &number2);
348 
349   /* Perform the comparison in the larger of the two sizes.  */
350   len_result = len_x > len_y ? len_x : len_y;
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.  */
370 void
371 decimal_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)
374 {
375   decNumber number;
376   gdb_byte dec[16];
377 
378   match_endianness (from, len_from, byte_order_from, dec);
379 
380   decimal_to_number (dec, len_from, &number);
381   decimal_from_number (&number, dec, len_to);
382 
383   match_endianness (dec, len_to, byte_order_to, to);
384 }
385