Target FP: Remove unused floating-point routines
[deliverable/binutils-gdb.git] / gdb / dfp.c
1 /* Decimal floating point support for GDB.
2
3 Copyright (C) 2007-2017 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 "dfp.h"
23
24 /* The order of the following headers is important for making sure
25 decNumber structure is large enough to hold decimal128 digits. */
26
27 #include "dpd/decimal128.h"
28 #include "dpd/decimal64.h"
29 #include "dpd/decimal32.h"
30
31 /* When using decimal128, this is the maximum string length + 1
32 (value comes from libdecnumber's DECIMAL128_String constant). */
33 #define MAX_DECIMAL_STRING 43
34
35 /* In GDB, we are using an array of gdb_byte to represent decimal values.
36 They are stored in host byte order. This routine does the conversion if
37 the target byte order is different. */
38 static void
39 match_endianness (const gdb_byte *from, int len, enum bfd_endian byte_order,
40 gdb_byte *to)
41 {
42 int i;
43
44 #if WORDS_BIGENDIAN
45 #define OPPOSITE_BYTE_ORDER BFD_ENDIAN_LITTLE
46 #else
47 #define OPPOSITE_BYTE_ORDER BFD_ENDIAN_BIG
48 #endif
49
50 if (byte_order == OPPOSITE_BYTE_ORDER)
51 for (i = 0; i < len; i++)
52 to[i] = from[len - i - 1];
53 else
54 for (i = 0; i < len; i++)
55 to[i] = from[i];
56
57 return;
58 }
59
60 /* Helper function to get the appropriate libdecnumber context for each size
61 of decimal float. */
62 static void
63 set_decnumber_context (decContext *ctx, int len)
64 {
65 switch (len)
66 {
67 case 4:
68 decContextDefault (ctx, DEC_INIT_DECIMAL32);
69 break;
70 case 8:
71 decContextDefault (ctx, DEC_INIT_DECIMAL64);
72 break;
73 case 16:
74 decContextDefault (ctx, DEC_INIT_DECIMAL128);
75 break;
76 }
77
78 ctx->traps = 0;
79 }
80
81 /* Check for errors signaled in the decimal context structure. */
82 static void
83 decimal_check_errors (decContext *ctx)
84 {
85 /* An error here could be a division by zero, an overflow, an underflow or
86 an invalid operation (from the DEC_Errors constant in decContext.h).
87 Since GDB doesn't complain about division by zero, overflow or underflow
88 errors for binary floating, we won't complain about them for decimal
89 floating either. */
90 if (ctx->status & DEC_IEEE_854_Invalid_operation)
91 {
92 /* Leave only the error bits in the status flags. */
93 ctx->status &= DEC_IEEE_854_Invalid_operation;
94 error (_("Cannot perform operation: %s"),
95 decContextStatusToString (ctx));
96 }
97 }
98
99 /* Helper function to convert from libdecnumber's appropriate representation
100 for computation to each size of decimal float. */
101 static void
102 decimal_from_number (const decNumber *from, gdb_byte *to, int len)
103 {
104 decContext set;
105
106 set_decnumber_context (&set, len);
107
108 switch (len)
109 {
110 case 4:
111 decimal32FromNumber ((decimal32 *) to, from, &set);
112 break;
113 case 8:
114 decimal64FromNumber ((decimal64 *) to, from, &set);
115 break;
116 case 16:
117 decimal128FromNumber ((decimal128 *) to, from, &set);
118 break;
119 }
120 }
121
122 /* Helper function to convert each size of decimal float to libdecnumber's
123 appropriate representation for computation. */
124 static void
125 decimal_to_number (const gdb_byte *from, int len, decNumber *to)
126 {
127 switch (len)
128 {
129 case 4:
130 decimal32ToNumber ((decimal32 *) from, to);
131 break;
132 case 8:
133 decimal64ToNumber ((decimal64 *) from, to);
134 break;
135 case 16:
136 decimal128ToNumber ((decimal128 *) from, to);
137 break;
138 default:
139 error (_("Unknown decimal floating point type."));
140 break;
141 }
142 }
143
144 /* Convert decimal type to its string representation. LEN is the length
145 of the decimal type, 4 bytes for decimal32, 8 bytes for decimal64 and
146 16 bytes for decimal128. */
147 std::string
148 decimal_to_string (const gdb_byte *decbytes, int len,
149 enum bfd_endian byte_order, const char *format)
150 {
151 gdb_byte dec[16];
152
153 match_endianness (decbytes, len, byte_order, dec);
154
155 if (format != nullptr)
156 {
157 /* We don't handle format strings (yet). If the host printf supports
158 decimal floating point types, just use this. Otherwise, fall back
159 to printing the number while ignoring the format string. */
160 #if defined (PRINTF_HAS_DECFLOAT)
161 /* FIXME: This makes unwarranted assumptions about the host ABI! */
162 return string_printf (format, dec);
163 #endif
164 }
165
166 std::string result;
167 result.resize (MAX_DECIMAL_STRING);
168
169 switch (len)
170 {
171 case 4:
172 decimal32ToString ((decimal32 *) dec, &result[0]);
173 break;
174 case 8:
175 decimal64ToString ((decimal64 *) dec, &result[0]);
176 break;
177 case 16:
178 decimal128ToString ((decimal128 *) dec, &result[0]);
179 break;
180 default:
181 error (_("Unknown decimal floating point type."));
182 break;
183 }
184
185 return result;
186 }
187
188 /* Convert the string form of a decimal value to its decimal representation.
189 LEN is the length of the decimal type, 4 bytes for decimal32, 8 bytes for
190 decimal64 and 16 bytes for decimal128. */
191 bool
192 decimal_from_string (gdb_byte *decbytes, int len, enum bfd_endian byte_order,
193 const std::string &string)
194 {
195 decContext set;
196 gdb_byte dec[16];
197
198 set_decnumber_context (&set, len);
199
200 switch (len)
201 {
202 case 4:
203 decimal32FromString ((decimal32 *) dec, string.c_str (), &set);
204 break;
205 case 8:
206 decimal64FromString ((decimal64 *) dec, string.c_str (), &set);
207 break;
208 case 16:
209 decimal128FromString ((decimal128 *) dec, string.c_str (), &set);
210 break;
211 default:
212 error (_("Unknown decimal floating point type."));
213 break;
214 }
215
216 match_endianness (dec, len, byte_order, decbytes);
217
218 /* Check for errors in the DFP operation. */
219 decimal_check_errors (&set);
220
221 return true;
222 }
223
224 /* Converts a LONGEST to a decimal float of specified LEN bytes. */
225 void
226 decimal_from_longest (LONGEST from,
227 gdb_byte *to, int len, enum bfd_endian byte_order)
228 {
229 gdb_byte dec[16];
230 decNumber number;
231 if ((int32_t) from != from)
232 /* libdecnumber can convert only 32-bit integers. */
233 error (_("Conversion of large integer to a "
234 "decimal floating type is not supported."));
235
236 decNumberFromInt32 (&number, (int32_t) from);
237
238 decimal_from_number (&number, dec, len);
239 match_endianness (dec, len, byte_order, to);
240 }
241
242 /* Converts a ULONGEST to a decimal float of specified LEN bytes. */
243 void
244 decimal_from_ulongest (ULONGEST from,
245 gdb_byte *to, int len, enum bfd_endian byte_order)
246 {
247 gdb_byte dec[16];
248 decNumber number;
249
250 if ((uint32_t) from != from)
251 /* libdecnumber can convert only 32-bit integers. */
252 error (_("Conversion of large integer to a "
253 "decimal floating type is not supported."));
254
255 decNumberFromUInt32 (&number, (uint32_t) from);
256
257 decimal_from_number (&number, dec, len);
258 match_endianness (dec, len, byte_order, to);
259 }
260
261 /* Converts a decimal float of LEN bytes to a LONGEST. */
262 LONGEST
263 decimal_to_longest (const gdb_byte *from, int len, enum bfd_endian byte_order)
264 {
265 /* libdecnumber has a function to convert from decimal to integer, but
266 it doesn't work when the decimal number has a fractional part. */
267 std::string str = decimal_to_string (from, len, byte_order);
268 return strtoll (str.c_str (), NULL, 10);
269 }
270
271 /* Perform operation OP with operands X and Y with sizes LEN_X and LEN_Y
272 and byte orders BYTE_ORDER_X and BYTE_ORDER_Y, and store value in
273 RESULT with size LEN_RESULT and byte order BYTE_ORDER_RESULT. */
274 void
275 decimal_binop (enum exp_opcode op,
276 const gdb_byte *x, int len_x, enum bfd_endian byte_order_x,
277 const gdb_byte *y, int len_y, enum bfd_endian byte_order_y,
278 gdb_byte *result, int len_result,
279 enum bfd_endian byte_order_result)
280 {
281 decContext set;
282 decNumber number1, number2, number3;
283 gdb_byte dec1[16], dec2[16], dec3[16];
284
285 match_endianness (x, len_x, byte_order_x, dec1);
286 match_endianness (y, len_y, byte_order_y, dec2);
287
288 decimal_to_number (dec1, len_x, &number1);
289 decimal_to_number (dec2, len_y, &number2);
290
291 set_decnumber_context (&set, len_result);
292
293 switch (op)
294 {
295 case BINOP_ADD:
296 decNumberAdd (&number3, &number1, &number2, &set);
297 break;
298 case BINOP_SUB:
299 decNumberSubtract (&number3, &number1, &number2, &set);
300 break;
301 case BINOP_MUL:
302 decNumberMultiply (&number3, &number1, &number2, &set);
303 break;
304 case BINOP_DIV:
305 decNumberDivide (&number3, &number1, &number2, &set);
306 break;
307 case BINOP_EXP:
308 decNumberPower (&number3, &number1, &number2, &set);
309 break;
310 default:
311 error (_("Operation not valid for decimal floating point number."));
312 break;
313 }
314
315 /* Check for errors in the DFP operation. */
316 decimal_check_errors (&set);
317
318 decimal_from_number (&number3, dec3, len_result);
319
320 match_endianness (dec3, len_result, byte_order_result, result);
321 }
322
323 /* Returns true if X (which is LEN bytes wide) is the number zero. */
324 int
325 decimal_is_zero (const gdb_byte *x, int len, enum bfd_endian byte_order)
326 {
327 decNumber number;
328 gdb_byte dec[16];
329
330 match_endianness (x, len, byte_order, dec);
331 decimal_to_number (dec, len, &number);
332
333 return decNumberIsZero (&number);
334 }
335
336 /* Compares two numbers numerically. If X is less than Y then the return value
337 will be -1. If they are equal, then the return value will be 0. If X is
338 greater than the Y then the return value will be 1. */
339 int
340 decimal_compare (const gdb_byte *x, int len_x, enum bfd_endian byte_order_x,
341 const gdb_byte *y, int len_y, enum bfd_endian byte_order_y)
342 {
343 decNumber number1, number2, result;
344 decContext set;
345 gdb_byte dec1[16], dec2[16];
346 int len_result;
347
348 match_endianness (x, len_x, byte_order_x, dec1);
349 match_endianness (y, len_y, byte_order_y, dec2);
350
351 decimal_to_number (dec1, len_x, &number1);
352 decimal_to_number (dec2, len_y, &number2);
353
354 /* Perform the comparison in the larger of the two sizes. */
355 len_result = len_x > len_y ? len_x : len_y;
356 set_decnumber_context (&set, len_result);
357
358 decNumberCompare (&result, &number1, &number2, &set);
359
360 /* Check for errors in the DFP operation. */
361 decimal_check_errors (&set);
362
363 if (decNumberIsNaN (&result))
364 error (_("Comparison with an invalid number (NaN)."));
365 else if (decNumberIsZero (&result))
366 return 0;
367 else if (decNumberIsNegative (&result))
368 return -1;
369 else
370 return 1;
371 }
372
373 /* Convert a decimal value from a decimal type with LEN_FROM bytes to a
374 decimal type with LEN_TO bytes. */
375 void
376 decimal_convert (const gdb_byte *from, int len_from,
377 enum bfd_endian byte_order_from, gdb_byte *to, int len_to,
378 enum bfd_endian byte_order_to)
379 {
380 decNumber number;
381 gdb_byte dec[16];
382
383 match_endianness (from, len_from, byte_order_from, dec);
384
385 decimal_to_number (dec, len_from, &number);
386 decimal_from_number (&number, dec, len_to);
387
388 match_endianness (dec, len_to, byte_order_to, to);
389 }
This page took 0.036457 seconds and 4 git commands to generate.