aboutsummaryrefslogtreecommitdiff
path: root/gdb/dfp.c
diff options
context:
space:
mode:
authorUlrich Weigand <ulrich.weigand@de.ibm.com>2017-11-06 16:04:03 +0100
committerUlrich Weigand <ulrich.weigand@de.ibm.com>2017-11-06 16:04:03 +0100
commit1cfb73dbb7503d1cfb088c14d1125a5030a1f386 (patch)
treea3446d08987ce758763ba739f3b8cb09d0f260db /gdb/dfp.c
parentb07e9c466ed24af614090ac42d6730a291608f69 (diff)
downloadfsf-binutils-gdb-1cfb73dbb7503d1cfb088c14d1125a5030a1f386.zip
fsf-binutils-gdb-1cfb73dbb7503d1cfb088c14d1125a5030a1f386.tar.gz
fsf-binutils-gdb-1cfb73dbb7503d1cfb088c14d1125a5030a1f386.tar.bz2
Target FP: Merge doublest.c and dfp.c into target-float.c
Now that all target FP operations are performed via target-float.c, this file remains the sole caller of functions in doublest.c and dfp.c. Therefore, this patch merges the latter files into the former and makes all their function static there. gdb/ChangeLog: 2017-11-06 Ulrich Weigand <uweigand@de.ibm.com> * Makefile.in (SFILES): Remove doublest.c and dfp.c. (HFILES_NO_SRCDIR): Remove doublest.h and dfp.h. (COMMON_OBS): Remove doublest.o and dfp.o. Do not build target-float.c (instead of doublest.c) with -Wformat-nonliteral. * doublest.c: Remove file. * doublest.h: Remove file. * dfp.c: Remove file. * dfp.h: Remove file. * target-float.c: Do not include "doublest.h" and "dfp.h". (DOUBLEST): Move here from doublest.h. (enum float_kind): Likewise. (FLOATFORMAT_CHAR_BIT): Likewise. (FLOATFORMAT_LARGEST_BYTES): Likewise. (floatformat_totalsize_bytes): Move here from doublest.c. Make static. (floatformat_precision): Likewise. (floatformat_normalize_byteorder, get_field, put_field): Likewise. (floatformat_is_negative, floatformat_classify, floatformat_mantissa): Likewise. (host_float_format, host_double_format, host_long_double_format): Likewise. (floatformat_to_string, floatformat_from_string): Likewise. (floatformat_to_doublest): Likewise. Also, inline the original convert_floatformat_to_doublest. (floatformat_from_doublest): Likewise. Also, inline the original convert_floatformat_from_doublest. Include "dpd/decimal128.h", "dpd/decimal64.h", and "dpd/decimal32.h". (MAX_DECIMAL_STRING): Move here from dfp.c. (match_endianness): Likewise. (set_decnumber_context, decimal_check_errors): Likewise. (decimal_from_number, decimal_to_number): Likewise. (decimal_to_string, decimal_from_string): Likewise. Make static. (decimal_from_longest, decimal_from_ulongest): Likewise. (decimal_to_longest): Likewise. (decimal_binop, decimal_is_zero, decimal_compare): Likewise. (decimal_convert): Likewise.
Diffstat (limited to 'gdb/dfp.c')
-rw-r--r--gdb/dfp.c389
1 files changed, 0 insertions, 389 deletions
diff --git a/gdb/dfp.c b/gdb/dfp.c
deleted file mode 100644
index ec05134..0000000
--- a/gdb/dfp.c
+++ /dev/null
@@ -1,389 +0,0 @@
-/* Decimal floating point support for GDB.
-
- Copyright (C) 2007-2017 Free Software Foundation, Inc.
-
- This file is part of GDB.
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 3 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>. */
-
-#include "defs.h"
-#include "expression.h"
-#include "dfp.h"
-
-/* The order of the following headers is important for making sure
- decNumber structure is large enough to hold decimal128 digits. */
-
-#include "dpd/decimal128.h"
-#include "dpd/decimal64.h"
-#include "dpd/decimal32.h"
-
-/* When using decimal128, this is the maximum string length + 1
- (value comes from libdecnumber's DECIMAL128_String constant). */
-#define MAX_DECIMAL_STRING 43
-
-/* In GDB, we are using an array of gdb_byte to represent decimal values.
- They are stored in host byte order. This routine does the conversion if
- the target byte order is different. */
-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;
-}
-
-/* Helper function to get the appropriate libdecnumber context for each size
- of decimal float. */
-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;
-}
-
-/* Check for errors signaled in the decimal context structure. */
-static void
-decimal_check_errors (decContext *ctx)
-{
- /* An error here could be a division by zero, an overflow, an underflow or
- an invalid operation (from the DEC_Errors constant in decContext.h).
- Since GDB doesn't complain about division by zero, overflow or underflow
- errors for binary floating, we won't complain about them for decimal
- floating either. */
- if (ctx->status & DEC_IEEE_854_Invalid_operation)
- {
- /* Leave only the error bits in the status flags. */
- ctx->status &= DEC_IEEE_854_Invalid_operation;
- error (_("Cannot perform operation: %s"),
- decContextStatusToString (ctx));
- }
-}
-
-/* Helper function to convert from libdecnumber's appropriate representation
- for computation to each size of decimal float. */
-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;
- }
-}
-
-/* Helper function to convert each size of decimal float to libdecnumber's
- appropriate representation for computation. */
-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;
- }
-}
-
-/* Convert decimal type to its string representation. LEN is the length
- of the decimal type, 4 bytes for decimal32, 8 bytes for decimal64 and
- 16 bytes for decimal128. */
-std::string
-decimal_to_string (const gdb_byte *decbytes, int len,
- enum bfd_endian byte_order, const char *format)
-{
- gdb_byte dec[16];
-
- match_endianness (decbytes, len, byte_order, dec);
-
- if (format != nullptr)
- {
- /* We don't handle format strings (yet). If the host printf supports
- decimal floating point types, just use this. Otherwise, fall back
- to printing the number while ignoring the format string. */
-#if defined (PRINTF_HAS_DECFLOAT)
- /* FIXME: This makes unwarranted assumptions about the host ABI! */
- return string_printf (format, dec);
-#endif
- }
-
- std::string result;
- result.resize (MAX_DECIMAL_STRING);
-
- switch (len)
- {
- case 4:
- decimal32ToString ((decimal32 *) dec, &result[0]);
- break;
- case 8:
- decimal64ToString ((decimal64 *) dec, &result[0]);
- break;
- case 16:
- decimal128ToString ((decimal128 *) dec, &result[0]);
- break;
- default:
- error (_("Unknown decimal floating point type."));
- break;
- }
-
- return result;
-}
-
-/* Convert the string form of a decimal value to its decimal representation.
- LEN is the length of the decimal type, 4 bytes for decimal32, 8 bytes for
- decimal64 and 16 bytes for decimal128. */
-bool
-decimal_from_string (gdb_byte *decbytes, int len, enum bfd_endian byte_order,
- const std::string &string)
-{
- decContext set;
- gdb_byte dec[16];
-
- set_decnumber_context (&set, len);
-
- switch (len)
- {
- case 4:
- decimal32FromString ((decimal32 *) dec, string.c_str (), &set);
- break;
- case 8:
- decimal64FromString ((decimal64 *) dec, string.c_str (), &set);
- break;
- case 16:
- decimal128FromString ((decimal128 *) dec, string.c_str (), &set);
- break;
- default:
- error (_("Unknown decimal floating point type."));
- break;
- }
-
- match_endianness (dec, len, byte_order, decbytes);
-
- /* Check for errors in the DFP operation. */
- decimal_check_errors (&set);
-
- return true;
-}
-
-/* Converts a LONGEST to a decimal float of specified LEN bytes. */
-void
-decimal_from_longest (LONGEST from,
- gdb_byte *to, int len, enum bfd_endian byte_order)
-{
- gdb_byte dec[16];
- decNumber number;
- if ((int32_t) from != from)
- /* libdecnumber can convert only 32-bit integers. */
- error (_("Conversion of large integer to a "
- "decimal floating type is not supported."));
-
- decNumberFromInt32 (&number, (int32_t) from);
-
- decimal_from_number (&number, dec, len);
- match_endianness (dec, len, byte_order, to);
-}
-
-/* Converts a ULONGEST to a decimal float of specified LEN bytes. */
-void
-decimal_from_ulongest (ULONGEST from,
- gdb_byte *to, int len, enum bfd_endian byte_order)
-{
- gdb_byte dec[16];
- decNumber number;
-
- if ((uint32_t) from != from)
- /* libdecnumber can convert only 32-bit integers. */
- error (_("Conversion of large integer to a "
- "decimal floating type is not supported."));
-
- decNumberFromUInt32 (&number, (uint32_t) from);
-
- decimal_from_number (&number, dec, len);
- match_endianness (dec, len, byte_order, to);
-}
-
-/* Converts a decimal float of LEN bytes to a LONGEST. */
-LONGEST
-decimal_to_longest (const gdb_byte *from, int len, enum bfd_endian byte_order)
-{
- /* libdecnumber has a function to convert from decimal to integer, but
- it doesn't work when the decimal number has a fractional part. */
- std::string str = decimal_to_string (from, len, byte_order);
- return strtoll (str.c_str (), NULL, 10);
-}
-
-/* Perform operation OP with operands X and Y with sizes LEN_X and LEN_Y
- and byte orders BYTE_ORDER_X and BYTE_ORDER_Y, and store value in
- RESULT with size LEN_RESULT and byte order BYTE_ORDER_RESULT. */
-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:
- error (_("Operation not valid for decimal floating point number."));
- break;
- }
-
- /* Check for errors in the DFP operation. */
- decimal_check_errors (&set);
-
- decimal_from_number (&number3, dec3, len_result);
-
- match_endianness (dec3, len_result, byte_order_result, result);
-}
-
-/* Returns true if X (which is LEN bytes wide) is the number zero. */
-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);
-}
-
-/* Compares two numbers numerically. If X is less than Y then the return value
- will be -1. If they are equal, then the return value will be 0. If X is
- greater than the Y then the return value will be 1. */
-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);
-
- /* Perform the comparison in the larger of the two sizes. */
- len_result = len_x > len_y ? len_x : len_y;
- set_decnumber_context (&set, len_result);
-
- decNumberCompare (&result, &number1, &number2, &set);
-
- /* Check for errors in the DFP operation. */
- 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;
-}
-
-/* Convert a decimal value from a decimal type with LEN_FROM bytes to a
- decimal type with LEN_TO bytes. */
-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);
-}