binutils-gdb/gdb/target-float.c

100 lines
3.4 KiB
C
Raw Normal View History

Target FP: Introduce target-float.{c,h} This patch introduces the new set of target floating-point handling routines in target-float.{c,h}. In the end, the intention is that this file will contain support for all operations in target FP format, fully replacing both the current doublest.{c,h} and dfp.{c,h}. To begin with, this patch only adds a target_float_is_zero routine, which handles the equivalent of decimal_is_zero for both binary and decimal FP. For the binary case, to avoid conversion to DOUBLEST, this is implemented using the floatformat_classify routine. However, it turns out that floatformat_classify actually has a bug (it was not used to check for zero before), so this is fixed as well. The new routine is used in both value_logical_not and valpy_nonzero. There is one extra twist: the code previously used value_as_double to convert to DOUBLEST and then compare against zero. That routine performs an extra task: it detects invalid floating-point values and raises an error. In any place where value_as_double is removed in favor of some target-float.c routine, we need to replace that check. To keep this check centralized in one place, I've added a new routine is_floating_value, which returns a boolean determining whether a value's type is floating point (binary or decimal), and if so, also performs the validity check. Since we need to check whether a value is FP before calling any of the target-float routines anyway, this seems a good place to add the check without much code size overhead. In some places where we only want to check for floating-point types and not perform a validity check (e.g. for the *output* of an operation), we can use the new is_floating_type routine (in gdbarch) instead. The validity check itself is done by a new target_float_is_valid routine in target-float, encapsulating floatformat_is_valid. ChangeLog: 2017-11-06 Ulrich Weigand <uweigand@de.ibm.com> * Makefile.c (SFILES): Add target-float.c. (HFILES_NO_SRCDIR): Add target-float.h. (COMMON_OBS): Add target-float.o. * target-float.h: New file. * target-float.c: New file. * doublest.c (floatformat_classify): Fix detection of float_zero. * gdbtypes.c (is_floating_type): New function. * gdbtypes.h (is_floating_type): Add prototype. * value.c: Do not include "floatformat.h". (unpack_double): Use target_float_is_valid. (is_floating_value): New function. * value.h (is_floating_value): Add prototype- * valarith.c: Include "target-float.h". (value_logical_not): Use target_float_is_zero. * python/py-value.c: Include "target-float.h". (valpy_nonzero): Use target_float_is_zero.
2017-11-06 15:55:11 +01:00
/* Floating point routines for GDB, the GNU debugger.
Copyright (C) 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 "dfp.h"
#include "doublest.h"
#include "gdbtypes.h"
#include "floatformat.h"
#include "target-float.h"
/* Typed floating-point routines. These routines operate on floating-point
values in target format, represented by a byte buffer interpreted as a
"struct type", which may be either a binary or decimal floating-point
type (TYPE_CODE_FLT or TYPE_CODE_DECFLOAT). */
/* Return whether the byte-stream ADDR holds a valid value of
floating-point type TYPE. */
bool
target_float_is_valid (const gdb_byte *addr, const struct type *type)
{
if (TYPE_CODE (type) == TYPE_CODE_FLT)
return floatformat_is_valid (floatformat_from_type (type), addr);
if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
return true;
gdb_assert_not_reached ("unexpected type code");
}
/* Return whether the byte-stream ADDR, interpreted as floating-point
type TYPE, is numerically equal to zero (of either sign). */
bool
target_float_is_zero (const gdb_byte *addr, const struct type *type)
{
if (TYPE_CODE (type) == TYPE_CODE_FLT)
return (floatformat_classify (floatformat_from_type (type), addr)
== float_zero);
if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
return decimal_is_zero (addr, TYPE_LENGTH (type),
gdbarch_byte_order (get_type_arch (type)));
gdb_assert_not_reached ("unexpected type code");
}
Target FP: Add string routines to target-float.{c,h} This adds target_float_to_string and target_float_from_string, which dispatch to the corresponding floatformat_ or decimal_ routines. Existing users of those routines are changed to use the new target-float routines instead (most of those places already handle both binary and decimal FP). In addition, two other places are changes to use target_float_from_string: - define_symbol in stabsread.c, when parsing a floating-point literal from stabs debug info - gdbarch-selftest.c when initializing a target format values (to eliminate use of DOUBLEST there). gdb/ChangeLog: 2017-11-06 Ulrich Weigand <uweigand@de.ibm.com> * target-float.c (target_float_to_string): New function. (target_float_from_string): New function. * target-float.h (target_float_to_string): Add prototype. (target_float_from_string): Add prototype. * valprint.c: Include "target-float.h". Do not include "doublest.h" and "dfp.h". (print_floating): Use target_float_to_string. * printcmd.c: Include "target-float.h". Do not include "dfp.h". (printf_floating): Use target_float_to_string. * i387-tdep.c: Include "target-float.h". Do not include "doublest.h". (print_i387_value): Use target_float_to_string. * mips-tdep.c: Include "target-float.h". (mips_print_fp_register): Use target_float_to_string. * sh64-tdep.c: Include "target-float.h". (sh64_do_fp_register): Use target_float_to_string. * parse.c: Include "target-float.h". Do not include "doublest.h" and "dfp.h". (parse_float): Use target_float_from_string. * stabsread.c: Include "target-float.h". Do not include "doublest.h". (define_symbol): Use target_float_from_string. * gdbarch-selftests.c: Include "target-float.h". (register_to_value_test): Use target_float_from_string.
2017-11-06 15:56:35 +01:00
/* Convert the byte-stream ADDR, interpreted as floating-point type TYPE,
to a string, optionally using the print format FORMAT. */
std::string
target_float_to_string (const gdb_byte *addr, const struct type *type,
const char *format)
{
if (TYPE_CODE (type) == TYPE_CODE_FLT)
return floatformat_to_string (floatformat_from_type (type), addr, format);
if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
return decimal_to_string (addr, TYPE_LENGTH (type),
gdbarch_byte_order (get_type_arch (type)),
format);
gdb_assert_not_reached ("unexpected type code");
}
/* Parse string STRING into a target floating-number of type TYPE and
store it as byte-stream ADDR. Return whether parsing succeeded. */
bool
target_float_from_string (gdb_byte *addr, const struct type *type,
const std::string &string)
{
/* Ensure possible padding bytes in the target buffer are zeroed out. */
memset (addr, 0, TYPE_LENGTH (type));
if (TYPE_CODE (type) == TYPE_CODE_FLT)
return floatformat_from_string (floatformat_from_type (type), addr,
string);
if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
return decimal_from_string (addr, TYPE_LENGTH (type),
gdbarch_byte_order (get_type_arch (type)),
string);
gdb_assert_not_reached ("unexpected type code");
}