gdb/dfp.c - gdb
Functions defined
Macros defined
Source code
- #include "defs.h"
- #include "expression.h"
- #include "gdbtypes.h"
- #include "value.h"
- #include "dfp.h"
- #include "dpd/decimal128.h"
- #include "dpd/decimal64.h"
- #include "dpd/decimal32.h"
- static void
- match_endianness (const gdb_byte *from, int len, enum bfd_endian byte_order,
- gdb_byte *to)
- {
- int i;
- #if WORDS_BIGENDIAN
- #define OPPOSITE_BYTE_ORDER BFD_ENDIAN_LITTLE
- #else
- #define OPPOSITE_BYTE_ORDER BFD_ENDIAN_BIG
- #endif
- if (byte_order == OPPOSITE_BYTE_ORDER)
- for (i = 0; i < len; i++)
- to[i] = from[len - i - 1];
- else
- for (i = 0; i < len; i++)
- to[i] = from[i];
- return;
- }
- static void
- set_decnumber_context (decContext *ctx, int len)
- {
- switch (len)
- {
- case 4:
- decContextDefault (ctx, DEC_INIT_DECIMAL32);
- break;
- case 8:
- decContextDefault (ctx, DEC_INIT_DECIMAL64);
- break;
- case 16:
- decContextDefault (ctx, DEC_INIT_DECIMAL128);
- break;
- }
- ctx->traps = 0;
- }
- static void
- decimal_check_errors (decContext *ctx)
- {
-
- if (ctx->status & DEC_IEEE_854_Invalid_operation)
- {
-
- ctx->status &= DEC_IEEE_854_Invalid_operation;
- error (_("Cannot perform operation: %s"),
- decContextStatusToString (ctx));
- }
- }
- static void
- decimal_from_number (const decNumber *from, gdb_byte *to, int len)
- {
- decContext set;
- set_decnumber_context (&set, len);
- switch (len)
- {
- case 4:
- decimal32FromNumber ((decimal32 *) to, from, &set);
- break;
- case 8:
- decimal64FromNumber ((decimal64 *) to, from, &set);
- break;
- case 16:
- decimal128FromNumber ((decimal128 *) to, from, &set);
- break;
- }
- }
- static void
- decimal_to_number (const gdb_byte *from, int len, decNumber *to)
- {
- switch (len)
- {
- case 4:
- decimal32ToNumber ((decimal32 *) from, to);
- break;
- case 8:
- decimal64ToNumber ((decimal64 *) from, to);
- break;
- case 16:
- decimal128ToNumber ((decimal128 *) from, to);
- break;
- default:
- error (_("Unknown decimal floating point type."));
- break;
- }
- }
- void
- decimal_to_string (const gdb_byte *decbytes, int len,
- enum bfd_endian byte_order, char *s)
- {
- gdb_byte dec[16];
- match_endianness (decbytes, len, byte_order, dec);
- switch (len)
- {
- case 4:
- decimal32ToString ((decimal32 *) dec, s);
- break;
- case 8:
- decimal64ToString ((decimal64 *) dec, s);
- break;
- case 16:
- decimal128ToString ((decimal128 *) dec, s);
- break;
- default:
- error (_("Unknown decimal floating point type."));
- break;
- }
- }
- int
- decimal_from_string (gdb_byte *decbytes, int len, enum bfd_endian byte_order,
- const char *string)
- {
- decContext set;
- gdb_byte dec[16];
- set_decnumber_context (&set, len);
- switch (len)
- {
- case 4:
- decimal32FromString ((decimal32 *) dec, string, &set);
- break;
- case 8:
- decimal64FromString ((decimal64 *) dec, string, &set);
- break;
- case 16:
- decimal128FromString ((decimal128 *) dec, string, &set);
- break;
- default:
- error (_("Unknown decimal floating point type."));
- break;
- }
- match_endianness (dec, len, byte_order, decbytes);
-
- decimal_check_errors (&set);
- return 1;
- }
- void
- decimal_from_integral (struct value *from,
- gdb_byte *to, int len, enum bfd_endian byte_order)
- {
- LONGEST l;
- gdb_byte dec[16];
- decNumber number;
- struct type *type;
- type = check_typedef (value_type (from));
- if (TYPE_LENGTH (type) > 4)
-
- error (_("Conversion of large integer to a "
- "decimal floating type is not supported."));
- l = value_as_long (from);
- if (TYPE_UNSIGNED (type))
- decNumberFromUInt32 (&number, (unsigned int) l);
- else
- decNumberFromInt32 (&number, (int) l);
- decimal_from_number (&number, dec, len);
- match_endianness (dec, len, byte_order, to);
- }
- void
- decimal_from_floating (struct value *from,
- gdb_byte *to, int len, enum bfd_endian byte_order)
- {
- char *buffer;
- buffer = xstrprintf ("%.30" DOUBLEST_PRINT_FORMAT, value_as_double (from));
- decimal_from_string (to, len, byte_order, buffer);
- xfree (buffer);
- }
- DOUBLEST
- decimal_to_doublest (const gdb_byte *from, int len, enum bfd_endian byte_order)
- {
- char buffer[MAX_DECIMAL_STRING];
-
- decimal_to_string (from, len, byte_order, buffer);
- return strtod (buffer, NULL);
- }
- void
- decimal_binop (enum exp_opcode op,
- const gdb_byte *x, int len_x, enum bfd_endian byte_order_x,
- const gdb_byte *y, int len_y, enum bfd_endian byte_order_y,
- gdb_byte *result, int len_result,
- enum bfd_endian byte_order_result)
- {
- decContext set;
- decNumber number1, number2, number3;
- gdb_byte dec1[16], dec2[16], dec3[16];
- match_endianness (x, len_x, byte_order_x, dec1);
- match_endianness (y, len_y, byte_order_y, dec2);
- decimal_to_number (dec1, len_x, &number1);
- decimal_to_number (dec2, len_y, &number2);
- set_decnumber_context (&set, len_result);
- switch (op)
- {
- case BINOP_ADD:
- decNumberAdd (&number3, &number1, &number2, &set);
- break;
- case BINOP_SUB:
- decNumberSubtract (&number3, &number1, &number2, &set);
- break;
- case BINOP_MUL:
- decNumberMultiply (&number3, &number1, &number2, &set);
- break;
- case BINOP_DIV:
- decNumberDivide (&number3, &number1, &number2, &set);
- break;
- case BINOP_EXP:
- decNumberPower (&number3, &number1, &number2, &set);
- break;
- default:
- internal_error (__FILE__, __LINE__,
- _("Unknown decimal floating point operation."));
- break;
- }
-
- decimal_check_errors (&set);
- decimal_from_number (&number3, dec3, len_result);
- match_endianness (dec3, len_result, byte_order_result, result);
- }
- int
- decimal_is_zero (const gdb_byte *x, int len, enum bfd_endian byte_order)
- {
- decNumber number;
- gdb_byte dec[16];
- match_endianness (x, len, byte_order, dec);
- decimal_to_number (dec, len, &number);
- return decNumberIsZero (&number);
- }
- int
- decimal_compare (const gdb_byte *x, int len_x, enum bfd_endian byte_order_x,
- const gdb_byte *y, int len_y, enum bfd_endian byte_order_y)
- {
- decNumber number1, number2, result;
- decContext set;
- gdb_byte dec1[16], dec2[16];
- int len_result;
- match_endianness (x, len_x, byte_order_x, dec1);
- match_endianness (y, len_y, byte_order_y, dec2);
- decimal_to_number (dec1, len_x, &number1);
- decimal_to_number (dec2, len_y, &number2);
-
- len_result = len_x > len_y ? len_x : len_y;
- set_decnumber_context (&set, len_result);
- decNumberCompare (&result, &number1, &number2, &set);
-
- decimal_check_errors (&set);
- if (decNumberIsNaN (&result))
- error (_("Comparison with an invalid number (NaN)."));
- else if (decNumberIsZero (&result))
- return 0;
- else if (decNumberIsNegative (&result))
- return -1;
- else
- return 1;
- }
- void
- decimal_convert (const gdb_byte *from, int len_from,
- enum bfd_endian byte_order_from, gdb_byte *to, int len_to,
- enum bfd_endian byte_order_to)
- {
- decNumber number;
- gdb_byte dec[16];
- match_endianness (from, len_from, byte_order_from, dec);
- decimal_to_number (dec, len_from, &number);
- decimal_from_number (&number, dec, len_to);
- match_endianness (dec, len_to, byte_order_to, to);
- }