/* Floating point routines for GDB, the GNU debugger.
- Copyright (C) 2017-2018 Free Software Foundation, Inc.
+ Copyright (C) 2017-2022 Free Software Foundation, Inc.
This file is part of GDB.
#include "gdbtypes.h"
#include "floatformat.h"
#include "target-float.h"
-
+#include "gdbarch.h"
/* Target floating-point operations.
int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT);
cur_byte = (total_len / FLOATFORMAT_CHAR_BIT)
- - ((start + len + excess) / FLOATFORMAT_CHAR_BIT);
+ - ((start + len + excess) / FLOATFORMAT_CHAR_BIT);
cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT)
- - FLOATFORMAT_CHAR_BIT;
+ - FLOATFORMAT_CHAR_BIT;
}
else
{
int excess = FLOATFORMAT_CHAR_BIT - (total_len % FLOATFORMAT_CHAR_BIT);
cur_byte = (total_len / FLOATFORMAT_CHAR_BIT)
- - ((start + len + excess) / FLOATFORMAT_CHAR_BIT);
+ - ((start + len + excess) / FLOATFORMAT_CHAR_BIT);
cur_bitshift = ((start + len + excess) % FLOATFORMAT_CHAR_BIT)
- - FLOATFORMAT_CHAR_BIT;
+ - FLOATFORMAT_CHAR_BIT;
}
else
{
floating-point number of format FMT. */
static std::string
floatformat_printf_format (const struct floatformat *fmt,
- const char *format, char length)
+ const char *format, char length)
{
std::string host_format;
char conversion;
else
{
/* Use the specified format, stripping out the conversion character
- and length modifier, if present. */
+ and length modifier, if present. */
size_t len = strlen (format);
gdb_assert (len > 1);
conversion = format[--len];
}
unsigned char *ufrom = (unsigned char *) from;
- T dto;
long exponent;
unsigned long mant;
unsigned int mant_bits, mant_off;
{
double dto;
- floatformat_to_double (fmt->split_half ? fmt->split_half : fmt,
- from, &dto);
+ floatformat_to_double /* ARI: floatformat_to_double */
+ (fmt->split_half ? fmt->split_half : fmt, from, &dto);
*to = (T) dto;
return;
}
mant_bits_left = fmt->man_len;
mant_off = fmt->man_start;
- dto = 0.0;
+ T dto = 0.0;
special_exponent = exponent == 0 || exponent == fmt->exp_nan;
mant -= mant_long;
/* If the integer bit is implicit, then we need to discard it.
- If we are discarding a zero, we should be (but are not) creating
- a denormalized number which means adjusting the exponent
- (I think). */
+ If we are discarding a zero, we should be (but are not) creating
+ a denormalized number which means adjusting the exponent
+ (I think). */
if (mant_bits_left == fmt->man_len
&& fmt->intbit == floatformat_intbit_no)
{
mant_long <<= 1;
mant_long &= 0xffffffffL;
- /* If we are processing the top 32 mantissa bits of a doublest
- so as to convert to a float value with implied integer bit,
- we will only be putting 31 of those 32 bits into the
- final value due to the discarding of the top bit. In the
- case of a small float value where the number of mantissa
- bits is less than 32, discarding the top bit does not alter
- the number of bits we will be adding to the result. */
- if (mant_bits == 32)
- mant_bits -= 1;
+ /* If we are processing the top 32 mantissa bits of a doublest
+ so as to convert to a float value with implied integer bit,
+ we will only be putting 31 of those 32 bits into the
+ final value due to the discarding of the top bit. In the
+ case of a small float value where the number of mantissa
+ bits is less than 32, discarding the top bit does not alter
+ the number of bits we will be adding to the result. */
+ if (mant_bits == 32)
+ mant_bits -= 1;
}
if (mant_bits < 32)
T host_float;
from_target (type, addr, &host_float);
+
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
return string_printf (host_format.c_str (), host_float);
+ DIAGNOSTIC_POP
}
/* Parse string IN into a target floating-number of type TYPE and
scan_format += scanf_length_modifier<T>::value;
scan_format += "g%n";
+ DIAGNOSTIC_PUSH
+ DIAGNOSTIC_IGNORE_FORMAT_NONLITERAL
num = sscanf (in.c_str (), scan_format.c_str(), &host_float, &n);
+ DIAGNOSTIC_POP
/* The sscanf man page suggests not making any assumptions on the effect
of %n on the result, so we don't.
{
T host_float;
from_target (type, addr, &host_float);
- /* Converting an out-of-range value is undefined behavior in C, but we
- prefer to return a defined value here. */
- if (host_float > std::numeric_limits<LONGEST>::max())
- return std::numeric_limits<LONGEST>::max();
- if (host_float < std::numeric_limits<LONGEST>::min())
+ T min_possible_range = static_cast<T>(std::numeric_limits<LONGEST>::min());
+ T max_possible_range = -min_possible_range;
+ /* host_float can be converted to an integer as long as it's in
+ the range [min_possible_range, max_possible_range). If not, it is either
+ too large, or too small, or is NaN; in this case return the maximum or
+ minimum possible value. */
+ if (host_float < max_possible_range && host_float >= min_possible_range)
+ return static_cast<LONGEST> (host_float);
+ if (host_float < min_possible_range)
return std::numeric_limits<LONGEST>::min();
- return (LONGEST) host_float;
+ /* This line will be executed if host_float is NaN. */
+ return std::numeric_limits<LONGEST>::max();
}
/* Convert signed integer VAL to a target floating-number of type TYPE
const gdb_byte *y, const struct type *type_y) const override;
private:
- /* Local wrapper class to handle mpfr_t initalization and cleanup. */
+ /* Local wrapper class to handle mpfr_t initialization and cleanup. */
class gdb_mpfr
{
public:
mpfr_sub_ui (tmp.val, tmp.val, mant_long, MPFR_RNDZ);
/* If the integer bit is implicit, then we need to discard it.
- If we are discarding a zero, we should be (but are not) creating
- a denormalized number which means adjusting the exponent
- (I think). */
+ If we are discarding a zero, we should be (but are not) creating
+ a denormalized number which means adjusting the exponent
+ (I think). */
if (mant_bits_left == fmt->man_len
&& fmt->intbit == floatformat_intbit_no)
{
mant_long <<= 1;
mant_long &= 0xffffffffL;
- /* If we are processing the top 32 mantissa bits of a doublest
- so as to convert to a float value with implied integer bit,
- we will only be putting 31 of those 32 bits into the
- final value due to the discarding of the top bit. In the
- case of a small float value where the number of mantissa
- bits is less than 32, discarding the top bit does not alter
- the number of bits we will be adding to the result. */
- if (mant_bits == 32)
- mant_bits -= 1;
+ /* If we are processing the top 32 mantissa bits of a doublest
+ so as to convert to a float value with implied integer bit,
+ we will only be putting 31 of those 32 bits into the
+ final value due to the discarding of the top bit. In the
+ case of a small float value where the number of mantissa
+ bits is less than 32, discarding the top bit does not alter
+ the number of bits we will be adding to the result. */
+ if (mant_bits == 32)
+ mant_bits -= 1;
}
if (mant_bits < 32)
static void
match_endianness (const gdb_byte *from, const struct type *type, gdb_byte *to)
{
- gdb_assert (TYPE_CODE (type) == TYPE_CODE_DECFLOAT);
+ gdb_assert (type->code () == TYPE_CODE_DECFLOAT);
int len = TYPE_LENGTH (type);
int i;
#define OPPOSITE_BYTE_ORDER BFD_ENDIAN_BIG
#endif
- if (gdbarch_byte_order (get_type_arch (type)) == OPPOSITE_BYTE_ORDER)
+ if (type_byte_order (type) == OPPOSITE_BYTE_ORDER)
for (i = 0; i < len; i++)
to[i] = from[len - i - 1];
else
static void
set_decnumber_context (decContext *ctx, const struct type *type)
{
- gdb_assert (TYPE_CODE (type) == TYPE_CODE_DECFLOAT);
+ gdb_assert (type->code () == TYPE_CODE_DECFLOAT);
switch (TYPE_LENGTH (type))
{
for computation to each size of decimal float. */
static void
decimal_from_number (const decNumber *from,
- gdb_byte *to, const struct type *type)
+ gdb_byte *to, const struct type *type)
{
gdb_byte dec[16];
appropriate representation for computation. */
static void
decimal_to_number (const gdb_byte *addr, const struct type *type,
- decNumber *to)
+ decNumber *to)
{
gdb_byte dec[16];
match_endianness (addr, type, dec);
/* Converts a decimal float of LEN bytes to a LONGEST. */
LONGEST
decimal_float_ops::to_longest (const gdb_byte *addr,
- const struct type *type) const
+ const struct type *type) const
{
/* libdecnumber has a function to convert from decimal to integer, but
it doesn't work when the decimal number has a fractional part. */
target_float_same_category_p (const struct type *type1,
const struct type *type2)
{
- return TYPE_CODE (type1) == TYPE_CODE (type2);
+ return type1->code () == type2->code ();
}
/* Return whether TYPE1 and TYPE2 use the same floating-point format. */
if (!target_float_same_category_p (type1, type2))
return false;
- switch (TYPE_CODE (type1))
+ switch (type1->code ())
{
case TYPE_CODE_FLT:
return floatformat_from_type (type1) == floatformat_from_type (type2);
case TYPE_CODE_DECFLOAT:
return (TYPE_LENGTH (type1) == TYPE_LENGTH (type2)
- && (gdbarch_byte_order (get_type_arch (type1))
- == gdbarch_byte_order (get_type_arch (type2))));
+ && (type_byte_order (type1)
+ == type_byte_order (type2)));
default:
gdb_assert_not_reached ("unexpected type code");
static int
target_float_format_length (const struct type *type)
{
- switch (TYPE_CODE (type))
+ switch (type->code ())
{
case TYPE_CODE_FLT:
return floatformat_totalsize_bytes (floatformat_from_type (type));
static enum target_float_ops_kind
get_target_float_ops_kind (const struct type *type)
{
- switch (TYPE_CODE (type))
+ switch (type->code ())
{
case TYPE_CODE_FLT:
- {
+ {
const struct floatformat *fmt = floatformat_from_type (type);
/* Binary floating-point formats matching a host format. */
}
}
-/* Return target_float_ops to peform operations for KIND. */
+/* Return target_float_ops to perform operations for KIND. */
static const target_float_ops *
get_target_float_ops (enum target_float_ops_kind kind)
{
/* If the type format matches one of the host floating-point
types, use that type as intermediate format. */
case target_float_ops_kind::host_float:
- {
+ {
static host_float_ops<float> host_float_ops_float;
return &host_float_ops_float;
}
case target_float_ops_kind::host_double:
- {
+ {
static host_float_ops<double> host_float_ops_double;
return &host_float_ops_double;
}
case target_float_ops_kind::host_long_double:
- {
+ {
static host_float_ops<long double> host_float_ops_long_double;
return &host_float_ops_long_double;
}
/* For binary floating-point formats that do not match any host format,
- use mpfr_t as intermediate format to provide precise target-floating
- point emulation. However, if the MPFR library is not availabe,
- use the largest host floating-point type as intermediate format. */
+ use mpfr_t as intermediate format to provide precise target-floating
+ point emulation. However, if the MPFR library is not available,
+ use the largest host floating-point type as intermediate format. */
case target_float_ops_kind::binary:
- {
+ {
#ifdef HAVE_LIBMPFR
static mpfr_float_ops binary_float_ops;
#else
static const target_float_ops *
get_target_float_ops (const struct type *type1, const struct type *type2)
{
- gdb_assert (TYPE_CODE (type1) == TYPE_CODE (type2));
+ gdb_assert (type1->code () == type2->code ());
enum target_float_ops_kind kind1 = get_target_float_ops_kind (type1);
enum target_float_ops_kind kind2 = get_target_float_ops_kind (type2);
bool
target_float_is_valid (const gdb_byte *addr, const struct type *type)
{
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ if (type->code () == TYPE_CODE_FLT)
return floatformat_is_valid (floatformat_from_type (type), addr);
- if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+ if (type->code () == TYPE_CODE_DECFLOAT)
return true;
gdb_assert_not_reached ("unexpected type code");
bool
target_float_is_zero (const gdb_byte *addr, const struct type *type)
{
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ if (type->code () == TYPE_CODE_FLT)
return (floatformat_classify (floatformat_from_type (type), addr)
== float_zero);
- if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+ if (type->code () == TYPE_CODE_DECFLOAT)
return decimal_is_zero (addr, type);
gdb_assert_not_reached ("unexpected type code");
{
/* Unless we need to adhere to a specific format, provide special
output for special cases of binary floating-point numbers. */
- if (format == nullptr && TYPE_CODE (type) == TYPE_CODE_FLT)
+ if (format == nullptr && type->code () == TYPE_CODE_FLT)
{
const struct floatformat *fmt = floatformat_from_type (type);
/* Convert between two different formats in the same category. */
if (!target_float_same_format_p (from_type, to_type))
- {
- const target_float_ops *ops = get_target_float_ops (from_type, to_type);
- ops->convert (from, from_type, to, to_type);
- return;
- }
+ {
+ const target_float_ops *ops = get_target_float_ops (from_type, to_type);
+ ops->convert (from, from_type, to, to_type);
+ return;
+ }
/* The floating-point formats match, so we simply copy the data, ensuring
possible padding bytes in the target buffer are zeroed out. */