diff options
author | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2017-11-06 16:04:03 +0100 |
---|---|---|
committer | Ulrich Weigand <ulrich.weigand@de.ibm.com> | 2017-11-06 16:04:03 +0100 |
commit | 1cfb73dbb7503d1cfb088c14d1125a5030a1f386 (patch) | |
tree | a3446d08987ce758763ba739f3b8cb09d0f260db /gdb/dfp.c | |
parent | b07e9c466ed24af614090ac42d6730a291608f69 (diff) | |
download | fsf-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.c | 389 |
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); -} |