summaryrefslogtreecommitdiff
path: root/gdb/valarith.c
diff options
context:
space:
mode:
authorUlrich Weigand <ulrich.weigand@de.ibm.com>2017-11-06 15:58:46 +0100
committerUlrich Weigand <ulrich.weigand@de.ibm.com>2017-11-06 15:58:46 +0100
commit66c02b9ed1eabf1d7981c0c27ec9fd3c17fc5d35 (patch)
tree004642d484425eddaec7fdc33f68b1501c1ad104 /gdb/valarith.c
parent50637b26f85dc3e59b616f1b01ca8885cf98f0b4 (diff)
downloadbinutils-gdb-66c02b9ed1eabf1d7981c0c27ec9fd3c17fc5d35.tar.gz
Target FP: Add binop and compare routines to target-float.{c,h}
This patch adds the following target floating-point routines: - target_float_binop - target_float_compare which call the equivalent decimal_ routines to handle decimal FP, and call helper routines that currently still go via DOUBLEST to handle binary FP (derived from current valarith.c code). These routines are used to handle both binary and decimal FP types in scalar_binop, value_equal, and value_less, mostly following the method currently used for decimal FP. The existing value_args_as_decimal helper is renamed to value_args_as_target_float and extended to handle both binary and decimal types. The unary operations value_pos and value_neg are also simplified, the former by using a simple copy for all scalar types, the latter by using value_binop (... BINOP_SUB) to implement negation as subtraction from zero. ChangeLog: 2017-11-06 Ulrich Weigand <uweigand@de.ibm.com> * target-float.c: Include <math.h>. (floatformat_binop): New function. (floatformat_compare): Likewise. (target_float_binop): Likewise. (target_float_compare): Likewise. * target-float.h: Include "expression.h". (target_float_binop): Add prototype. (target_float_compare): Likewise. * valarith.c: Do not include "doublest.h" and "dfp.h". Include "common/byte-vector.h". (value_args_as_decimal): Remove, replace by ... (value_args_as_target_float): ... this function. Handle both binary and decimal target floating-point formats. (scalar_binop): Handle both binary and decimal FP using value_args_as_target_float and target_float_binop. (value_equal): Handle both binary and decimal FP using value_args_as_target_float and target_float_compare. (value_less): Likewise. (value_pos): Handle all scalar types as simple copy. (value_neg): Handle all scalar types via BINOP_SUB from 0. * dfp.c (decimal_binop): Throw error instead of internal_error when called with an unsupported operation code.
Diffstat (limited to 'gdb/valarith.c')
-rw-r--r--gdb/valarith.c277
1 files changed, 69 insertions, 208 deletions
diff --git a/gdb/valarith.c b/gdb/valarith.c
index 3e52e9d566d..89e44f3fb01 100644
--- a/gdb/valarith.c
+++ b/gdb/valarith.c
@@ -24,11 +24,9 @@
#include "expression.h"
#include "target.h"
#include "language.h"
-#include "doublest.h"
-#include "dfp.h"
#include "target-float.h"
-#include <math.h>
#include "infcall.h"
+#include "common/byte-vector.h"
/* Define whether or not the C operator '/' truncates towards zero for
differently signed operands (truncation direction is undefined in C). */
@@ -845,69 +843,62 @@ uinteger_pow (ULONGEST v1, LONGEST v2)
}
}
-/* Obtain decimal value of arguments for binary operation, converting from
- other types if one of them is not decimal floating point. */
+/* Obtain argument values for binary operation, converting from
+ other types if one of them is not floating point. */
static void
-value_args_as_decimal (struct value *arg1, struct value *arg2,
- gdb_byte *x, int *len_x, enum bfd_endian *byte_order_x,
- gdb_byte *y, int *len_y, enum bfd_endian *byte_order_y)
+value_args_as_target_float (struct value *arg1, struct value *arg2,
+ gdb_byte *x, struct type **eff_type_x,
+ gdb_byte *y, struct type **eff_type_y)
{
struct type *type1, *type2;
type1 = check_typedef (value_type (arg1));
type2 = check_typedef (value_type (arg2));
- /* At least one of the arguments must be of decimal float type. */
- gdb_assert (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT
- || TYPE_CODE (type2) == TYPE_CODE_DECFLOAT);
+ /* At least one of the arguments must be of floating-point type. */
+ gdb_assert (is_floating_type (type1) || is_floating_type (type2));
- if (TYPE_CODE (type1) == TYPE_CODE_FLT
- || TYPE_CODE (type2) == TYPE_CODE_FLT)
+ if (is_floating_type (type1) && is_floating_type (type2)
+ && TYPE_CODE (type1) != TYPE_CODE (type2))
/* The DFP extension to the C language does not allow mixing of
* decimal float types with other float types in expressions
* (see WDTR 24732, page 12). */
error (_("Mixing decimal floating types with "
"other floating types is not allowed."));
- /* Obtain decimal value of arg1, converting from other types
- if necessary. */
+ /* Obtain value of arg1, converting from other types if necessary. */
- if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT)
+ if (is_floating_type (type1))
{
- *byte_order_x = gdbarch_byte_order (get_type_arch (type1));
- *len_x = TYPE_LENGTH (type1);
- memcpy (x, value_contents (arg1), *len_x);
+ *eff_type_x = type1;
+ memcpy (x, value_contents (arg1), TYPE_LENGTH (type1));
}
else if (is_integral_type (type1))
{
- *byte_order_x = gdbarch_byte_order (get_type_arch (type2));
- *len_x = TYPE_LENGTH (type2);
+ *eff_type_x = type2;
if (TYPE_UNSIGNED (type1))
- decimal_from_ulongest (value_as_long (arg1), x, *len_x, *byte_order_x);
+ target_float_from_ulongest (x, *eff_type_x, value_as_long (arg1));
else
- decimal_from_longest (value_as_long (arg1), x, *len_x, *byte_order_x);
+ target_float_from_longest (x, *eff_type_x, value_as_long (arg1));
}
else
error (_("Don't know how to convert from %s to %s."), TYPE_NAME (type1),
TYPE_NAME (type2));
- /* Obtain decimal value of arg2, converting from other types
- if necessary. */
+ /* Obtain value of arg2, converting from other types if necessary. */
- if (TYPE_CODE (type2) == TYPE_CODE_DECFLOAT)
+ if (is_floating_type (type2))
{
- *byte_order_y = gdbarch_byte_order (get_type_arch (type2));
- *len_y = TYPE_LENGTH (type2);
- memcpy (y, value_contents (arg2), *len_y);
+ *eff_type_y = type2;
+ memcpy (y, value_contents (arg2), TYPE_LENGTH (type2));
}
else if (is_integral_type (type2))
{
- *byte_order_y = gdbarch_byte_order (get_type_arch (type1));
- *len_y = TYPE_LENGTH (type1);
+ *eff_type_y = type1;
if (TYPE_UNSIGNED (type2))
- decimal_from_ulongest (value_as_long (arg2), y, *len_y, *byte_order_y);
+ target_float_from_ulongest (y, *eff_type_y, value_as_long (arg2));
else
- decimal_from_longest (value_as_long (arg2), y, *len_y, *byte_order_y);
+ target_float_from_longest (y, *eff_type_y, value_as_long (arg2));
}
else
error (_("Don't know how to convert from %s to %s."), TYPE_NAME (type1),
@@ -932,111 +923,17 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
type1 = check_typedef (value_type (arg1));
type2 = check_typedef (value_type (arg2));
- if ((TYPE_CODE (type1) != TYPE_CODE_FLT
- && TYPE_CODE (type1) != TYPE_CODE_DECFLOAT
- && !is_integral_type (type1))
- || (TYPE_CODE (type2) != TYPE_CODE_FLT
- && TYPE_CODE (type2) != TYPE_CODE_DECFLOAT
- && !is_integral_type (type2)))
+ if ((!is_floating_value (arg1) && !is_integral_type (type1))
+ || (!is_floating_value (arg2) && !is_integral_type (type2)))
error (_("Argument to arithmetic operation not a number or boolean."));
- if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT
- || TYPE_CODE (type2) == TYPE_CODE_DECFLOAT)
+ if (is_floating_type (type1) || is_floating_type (type2))
{
- int len_v1, len_v2, len_v;
- enum bfd_endian byte_order_v1, byte_order_v2, byte_order_v;
- gdb_byte v1[16], v2[16];
- gdb_byte v[16];
-
- /* If only one type is decimal float, use its type.
+ /* If only one type is floating-point, use its type.
Otherwise use the bigger type. */
- if (TYPE_CODE (type1) != TYPE_CODE_DECFLOAT)
+ if (!is_floating_type (type1))
result_type = type2;
- else if (TYPE_CODE (type2) != TYPE_CODE_DECFLOAT)
- result_type = type1;
- else if (TYPE_LENGTH (type2) > TYPE_LENGTH (type1))
- result_type = type2;
- else
- result_type = type1;
-
- len_v = TYPE_LENGTH (result_type);
- byte_order_v = gdbarch_byte_order (get_type_arch (result_type));
-
- value_args_as_decimal (arg1, arg2, v1, &len_v1, &byte_order_v1,
- v2, &len_v2, &byte_order_v2);
-
- switch (op)
- {
- case BINOP_ADD:
- case BINOP_SUB:
- case BINOP_MUL:
- case BINOP_DIV:
- case BINOP_EXP:
- decimal_binop (op, v1, len_v1, byte_order_v1,
- v2, len_v2, byte_order_v2,
- v, len_v, byte_order_v);
- break;
-
- default:
- error (_("Operation not valid for decimal floating point number."));
- }
-
- val = value_from_decfloat (result_type, v);
- }
- else if (TYPE_CODE (type1) == TYPE_CODE_FLT
- || TYPE_CODE (type2) == TYPE_CODE_FLT)
- {
- /* FIXME-if-picky-about-floating-accuracy: Should be doing this
- in target format. real.c in GCC probably has the necessary
- code. */
- DOUBLEST v1, v2, v = 0;
-
- v1 = value_as_double (arg1);
- v2 = value_as_double (arg2);
-
- switch (op)
- {
- case BINOP_ADD:
- v = v1 + v2;
- break;
-
- case BINOP_SUB:
- v = v1 - v2;
- break;
-
- case BINOP_MUL:
- v = v1 * v2;
- break;
-
- case BINOP_DIV:
- v = v1 / v2;
- break;
-
- case BINOP_EXP:
- errno = 0;
- v = pow (v1, v2);
- if (errno)
- error (_("Cannot perform exponentiation: %s"),
- safe_strerror (errno));
- break;
-
- case BINOP_MIN:
- v = v1 < v2 ? v1 : v2;
- break;
-
- case BINOP_MAX:
- v = v1 > v2 ? v1 : v2;
- break;
-
- default:
- error (_("Integer-only operation on floating point number."));
- }
-
- /* If only one type is float, use its type.
- Otherwise use the bigger type. */
- if (TYPE_CODE (type1) != TYPE_CODE_FLT)
- result_type = type2;
- else if (TYPE_CODE (type2) != TYPE_CODE_FLT)
+ else if (!is_floating_type (type2))
result_type = type1;
else if (TYPE_LENGTH (type2) > TYPE_LENGTH (type1))
result_type = type2;
@@ -1044,7 +941,18 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
result_type = type1;
val = allocate_value (result_type);
- store_typed_floating (value_contents_raw (val), value_type (val), v);
+
+ struct type *eff_type_v1, *eff_type_v2;
+ gdb::byte_vector v1, v2;
+ v1.resize (TYPE_LENGTH (result_type));
+ v2.resize (TYPE_LENGTH (result_type));
+
+ value_args_as_target_float (arg1, arg2,
+ v1.data (), &eff_type_v1,
+ v2.data (), &eff_type_v2);
+ target_float_binop (op, v1.data (), eff_type_v1,
+ v2.data (), eff_type_v2,
+ value_contents_raw (val), result_type);
}
else if (TYPE_CODE (type1) == TYPE_CODE_BOOL
|| TYPE_CODE (type2) == TYPE_CODE_BOOL)
@@ -1587,27 +1495,20 @@ value_equal (struct value *arg1, struct value *arg2)
if (is_int1 && is_int2)
return longest_to_int (value_as_long (value_binop (arg1, arg2,
BINOP_EQUAL)));
- else if ((code1 == TYPE_CODE_FLT || is_int1)
- && (code2 == TYPE_CODE_FLT || is_int2))
+ else if ((is_floating_value (arg1) || is_int1)
+ && (is_floating_value (arg2) || is_int2))
{
- /* NOTE: kettenis/20050816: Avoid compiler bug on systems where
- `long double' values are returned in static storage (m68k). */
- DOUBLEST d = value_as_double (arg1);
+ struct type *eff_type_v1, *eff_type_v2;
+ gdb::byte_vector v1, v2;
+ v1.resize (std::max (TYPE_LENGTH (type1), TYPE_LENGTH (type2)));
+ v2.resize (std::max (TYPE_LENGTH (type1), TYPE_LENGTH (type2)));
- return d == value_as_double (arg2);
- }
- else if ((code1 == TYPE_CODE_DECFLOAT || is_int1)
- && (code2 == TYPE_CODE_DECFLOAT || is_int2))
- {
- gdb_byte v1[16], v2[16];
- int len_v1, len_v2;
- enum bfd_endian byte_order_v1, byte_order_v2;
-
- value_args_as_decimal (arg1, arg2, v1, &len_v1, &byte_order_v1,
- v2, &len_v2, &byte_order_v2);
+ value_args_as_target_float (arg1, arg2,
+ v1.data (), &eff_type_v1,
+ v2.data (), &eff_type_v2);
- return decimal_compare (v1, len_v1, byte_order_v1,
- v2, len_v2, byte_order_v2) == 0;
+ return target_float_compare (v1.data (), eff_type_v1,
+ v2.data (), eff_type_v2) == 0;
}
/* FIXME: Need to promote to either CORE_ADDR or LONGEST, whichever
@@ -1683,27 +1584,20 @@ value_less (struct value *arg1, struct value *arg2)
if (is_int1 && is_int2)
return longest_to_int (value_as_long (value_binop (arg1, arg2,
BINOP_LESS)));
- else if ((code1 == TYPE_CODE_FLT || is_int1)
- && (code2 == TYPE_CODE_FLT || is_int2))
+ else if ((is_floating_value (arg1) || is_int1)
+ && (is_floating_value (arg2) || is_int2))
{
- /* NOTE: kettenis/20050816: Avoid compiler bug on systems where
- `long double' values are returned in static storage (m68k). */
- DOUBLEST d = value_as_double (arg1);
+ struct type *eff_type_v1, *eff_type_v2;
+ gdb::byte_vector v1, v2;
+ v1.resize (std::max (TYPE_LENGTH (type1), TYPE_LENGTH (type2)));
+ v2.resize (std::max (TYPE_LENGTH (type1), TYPE_LENGTH (type2)));
- return d < value_as_double (arg2);
- }
- else if ((code1 == TYPE_CODE_DECFLOAT || is_int1)
- && (code2 == TYPE_CODE_DECFLOAT || is_int2))
- {
- gdb_byte v1[16], v2[16];
- int len_v1, len_v2;
- enum bfd_endian byte_order_v1, byte_order_v2;
+ value_args_as_target_float (arg1, arg2,
+ v1.data (), &eff_type_v1,
+ v2.data (), &eff_type_v2);
- value_args_as_decimal (arg1, arg2, v1, &len_v1, &byte_order_v1,
- v2, &len_v2, &byte_order_v2);
-
- return decimal_compare (v1, len_v1, byte_order_v1,
- v2, len_v2, byte_order_v2) == -1;
+ return target_float_compare (v1.data (), eff_type_v1,
+ v2.data (), eff_type_v2) == -1;
}
else if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
return value_as_address (arg1) < value_as_address (arg2);
@@ -1733,22 +1627,9 @@ value_pos (struct value *arg1)
arg1 = coerce_ref (arg1);
type = check_typedef (value_type (arg1));
- if (TYPE_CODE (type) == TYPE_CODE_FLT)
- return value_from_double (type, value_as_double (arg1));
- else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
- return value_from_decfloat (type, value_contents (arg1));
- else if (is_integral_type (type))
- {
- return value_from_longest (type, value_as_long (arg1));
- }
- else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type))
- {
- struct value *val = allocate_value (type);
-
- memcpy (value_contents_raw (val), value_contents (arg1),
- TYPE_LENGTH (type));
- return val;
- }
+ if (is_integral_type (type) || is_floating_value (arg1)
+ || (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type)))
+ return value_from_contents (type, value_contents (arg1));
else
{
error (_("Argument to positive operation not a number."));
@@ -1764,28 +1645,8 @@ value_neg (struct value *arg1)
arg1 = coerce_ref (arg1);
type = check_typedef (value_type (arg1));
- if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
- {
- struct value *val = allocate_value (type);
- int len = TYPE_LENGTH (type);
- gdb_byte decbytes[16]; /* a decfloat is at most 128 bits long. */
-
- memcpy (decbytes, value_contents (arg1), len);
-
- if (gdbarch_byte_order (get_type_arch (type)) == BFD_ENDIAN_LITTLE)
- decbytes[len-1] = decbytes[len - 1] | 0x80;
- else
- decbytes[0] = decbytes[0] | 0x80;
-
- memcpy (value_contents_raw (val), decbytes, len);
- return val;
- }
- else if (TYPE_CODE (type) == TYPE_CODE_FLT)
- return value_from_double (type, -value_as_double (arg1));
- else if (is_integral_type (type))
- {
- return value_from_longest (type, -value_as_long (arg1));
- }
+ if (is_integral_type (type) || is_floating_type (type))
+ return value_binop (value_from_longest (type, 0), arg1, BINOP_SUB);
else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type))
{
struct value *tmp, *val = allocate_value (type);