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.
This commit is contained in:
parent
50637b26f8
commit
66c02b9ed1
@ -1,3 +1,29 @@
|
|||||||
|
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.
|
||||||
|
|
||||||
2017-11-06 Ulrich Weigand <uweigand@de.ibm.com>
|
2017-11-06 Ulrich Weigand <uweigand@de.ibm.com>
|
||||||
|
|
||||||
* target-float.c (target_float_to_string): New function.
|
* target-float.c (target_float_to_string): New function.
|
||||||
|
@ -330,9 +330,8 @@ decimal_binop (enum exp_opcode op,
|
|||||||
case BINOP_EXP:
|
case BINOP_EXP:
|
||||||
decNumberPower (&number3, &number1, &number2, &set);
|
decNumberPower (&number3, &number1, &number2, &set);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
internal_error (__FILE__, __LINE__,
|
error (_("Operation not valid for decimal floating point number."));
|
||||||
_("Unknown decimal floating point operation."));
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,6 +27,8 @@
|
|||||||
|
|
||||||
/* Helper routines operating on binary floating-point data. */
|
/* Helper routines operating on binary floating-point data. */
|
||||||
|
|
||||||
|
#include <math.h>
|
||||||
|
|
||||||
/* Convert the byte-stream ADDR, interpreted as floating-point format FMT,
|
/* Convert the byte-stream ADDR, interpreted as floating-point format FMT,
|
||||||
to an integer value (rounding towards zero). */
|
to an integer value (rounding towards zero). */
|
||||||
static LONGEST
|
static LONGEST
|
||||||
@ -82,6 +84,82 @@ floatformat_convert (const gdb_byte *from, const struct floatformat *from_fmt,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Perform the binary operation indicated by OPCODE, using as operands the
|
||||||
|
target byte streams X and Y, interpreted as floating-point numbers of
|
||||||
|
formats FMT_X and FMT_Y, respectively. Convert the result to format
|
||||||
|
FMT_RES and store it into the byte-stream RES. */
|
||||||
|
static void
|
||||||
|
floatformat_binop (enum exp_opcode op,
|
||||||
|
const struct floatformat *fmt_x, const gdb_byte *x,
|
||||||
|
const struct floatformat *fmt_y, const gdb_byte *y,
|
||||||
|
const struct floatformat *fmt_result, gdb_byte *result)
|
||||||
|
{
|
||||||
|
DOUBLEST v1, v2, v = 0;
|
||||||
|
|
||||||
|
floatformat_to_doublest (fmt_x, x, &v1);
|
||||||
|
floatformat_to_doublest (fmt_y, y, &v2);
|
||||||
|
|
||||||
|
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."));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
floatformat_from_doublest (fmt_result, &v, result);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compare the two target byte streams X and Y, interpreted as floating-point
|
||||||
|
numbers of formats FMT_X and FMT_Y, respectively. Return zero if X and Y
|
||||||
|
are equal, -1 if X is less than Y, and 1 otherwise. */
|
||||||
|
static int
|
||||||
|
floatformat_compare (const struct floatformat *fmt_x, const gdb_byte *x,
|
||||||
|
const struct floatformat *fmt_y, const gdb_byte *y)
|
||||||
|
{
|
||||||
|
DOUBLEST v1, v2;
|
||||||
|
|
||||||
|
floatformat_to_doublest (fmt_x, x, &v1);
|
||||||
|
floatformat_to_doublest (fmt_y, y, &v2);
|
||||||
|
|
||||||
|
if (v1 == v2)
|
||||||
|
return 0;
|
||||||
|
if (v1 < v2)
|
||||||
|
return -1;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Typed floating-point routines. These routines operate on floating-point
|
/* Typed floating-point routines. These routines operate on floating-point
|
||||||
values in target format, represented by a byte buffer interpreted as a
|
values in target format, represented by a byte buffer interpreted as a
|
||||||
@ -266,3 +344,77 @@ target_float_convert (const gdb_byte *from, const struct type *from_type,
|
|||||||
|
|
||||||
gdb_assert_not_reached ("unexpected type code");
|
gdb_assert_not_reached ("unexpected type code");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Perform the binary operation indicated by OPCODE, using as operands the
|
||||||
|
target byte streams X and Y, interpreted as floating-point numbers of
|
||||||
|
types TYPE_X and TYPE_Y, respectively. Convert the result to type
|
||||||
|
TYPE_RES and store it into the byte-stream RES.
|
||||||
|
|
||||||
|
The three types must either be all binary floating-point types, or else
|
||||||
|
all decimal floating-point types. Binary and decimal floating-point
|
||||||
|
types cannot be mixed within a single operation. */
|
||||||
|
void
|
||||||
|
target_float_binop (enum exp_opcode opcode,
|
||||||
|
const gdb_byte *x, const struct type *type_x,
|
||||||
|
const gdb_byte *y, const struct type *type_y,
|
||||||
|
gdb_byte *res, const struct type *type_res)
|
||||||
|
{
|
||||||
|
/* Ensure possible padding bytes in the target buffer are zeroed out. */
|
||||||
|
memset (res, 0, TYPE_LENGTH (type_res));
|
||||||
|
|
||||||
|
if (TYPE_CODE (type_res) == TYPE_CODE_FLT)
|
||||||
|
{
|
||||||
|
gdb_assert (TYPE_CODE (type_x) == TYPE_CODE_FLT);
|
||||||
|
gdb_assert (TYPE_CODE (type_y) == TYPE_CODE_FLT);
|
||||||
|
return floatformat_binop (opcode,
|
||||||
|
floatformat_from_type (type_x), x,
|
||||||
|
floatformat_from_type (type_y), y,
|
||||||
|
floatformat_from_type (type_res), res);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TYPE_CODE (type_res) == TYPE_CODE_DECFLOAT)
|
||||||
|
{
|
||||||
|
gdb_assert (TYPE_CODE (type_x) == TYPE_CODE_DECFLOAT);
|
||||||
|
gdb_assert (TYPE_CODE (type_y) == TYPE_CODE_DECFLOAT);
|
||||||
|
return decimal_binop (opcode,
|
||||||
|
x, TYPE_LENGTH (type_x),
|
||||||
|
gdbarch_byte_order (get_type_arch (type_x)),
|
||||||
|
y, TYPE_LENGTH (type_y),
|
||||||
|
gdbarch_byte_order (get_type_arch (type_y)),
|
||||||
|
res, TYPE_LENGTH (type_res),
|
||||||
|
gdbarch_byte_order (get_type_arch (type_res)));
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_assert_not_reached ("unexpected type code");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Compare the two target byte streams X and Y, interpreted as floating-point
|
||||||
|
numbers of types TYPE_X and TYPE_Y, respectively. Return zero if X and Y
|
||||||
|
are equal, -1 if X is less than Y, and 1 otherwise.
|
||||||
|
|
||||||
|
The two types must either both be binary floating-point types, or else
|
||||||
|
both be decimal floating-point types. Binary and decimal floating-point
|
||||||
|
types cannot compared directly against each other. */
|
||||||
|
int
|
||||||
|
target_float_compare (const gdb_byte *x, const struct type *type_x,
|
||||||
|
const gdb_byte *y, const struct type *type_y)
|
||||||
|
{
|
||||||
|
if (TYPE_CODE (type_x) == TYPE_CODE_FLT)
|
||||||
|
{
|
||||||
|
gdb_assert (TYPE_CODE (type_y) == TYPE_CODE_FLT);
|
||||||
|
return floatformat_compare (floatformat_from_type (type_x), x,
|
||||||
|
floatformat_from_type (type_y), y);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (TYPE_CODE (type_x) == TYPE_CODE_DECFLOAT)
|
||||||
|
{
|
||||||
|
gdb_assert (TYPE_CODE (type_y) == TYPE_CODE_DECFLOAT);
|
||||||
|
return decimal_compare (x, TYPE_LENGTH (type_x),
|
||||||
|
gdbarch_byte_order (get_type_arch (type_x)),
|
||||||
|
y, TYPE_LENGTH (type_y),
|
||||||
|
gdbarch_byte_order (get_type_arch (type_y)));
|
||||||
|
}
|
||||||
|
|
||||||
|
gdb_assert_not_reached ("unexpected type code");
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -20,6 +20,8 @@
|
|||||||
#ifndef TYPED_FLOAT_H
|
#ifndef TYPED_FLOAT_H
|
||||||
#define TYPED_FLOAT_H
|
#define TYPED_FLOAT_H
|
||||||
|
|
||||||
|
#include "expression.h"
|
||||||
|
|
||||||
extern bool target_float_is_valid (const gdb_byte *addr,
|
extern bool target_float_is_valid (const gdb_byte *addr,
|
||||||
const struct type *type);
|
const struct type *type);
|
||||||
extern bool target_float_is_zero (const gdb_byte *addr,
|
extern bool target_float_is_zero (const gdb_byte *addr,
|
||||||
@ -44,4 +46,11 @@ extern void target_float_convert (const gdb_byte *from,
|
|||||||
const struct type *from_type,
|
const struct type *from_type,
|
||||||
gdb_byte *to, const struct type *to_type);
|
gdb_byte *to, const struct type *to_type);
|
||||||
|
|
||||||
|
extern void target_float_binop (enum exp_opcode opcode,
|
||||||
|
const gdb_byte *x, const struct type *type_x,
|
||||||
|
const gdb_byte *y, const struct type *type_y,
|
||||||
|
gdb_byte *res, const struct type *type_res);
|
||||||
|
extern int target_float_compare (const gdb_byte *x, const struct type *type_x,
|
||||||
|
const gdb_byte *y, const struct type *type_y);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
277
gdb/valarith.c
277
gdb/valarith.c
@ -24,11 +24,9 @@
|
|||||||
#include "expression.h"
|
#include "expression.h"
|
||||||
#include "target.h"
|
#include "target.h"
|
||||||
#include "language.h"
|
#include "language.h"
|
||||||
#include "doublest.h"
|
|
||||||
#include "dfp.h"
|
|
||||||
#include "target-float.h"
|
#include "target-float.h"
|
||||||
#include <math.h>
|
|
||||||
#include "infcall.h"
|
#include "infcall.h"
|
||||||
|
#include "common/byte-vector.h"
|
||||||
|
|
||||||
/* Define whether or not the C operator '/' truncates towards zero for
|
/* Define whether or not the C operator '/' truncates towards zero for
|
||||||
differently signed operands (truncation direction is undefined in C). */
|
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
|
/* Obtain argument values for binary operation, converting from
|
||||||
other types if one of them is not decimal floating point. */
|
other types if one of them is not floating point. */
|
||||||
static void
|
static void
|
||||||
value_args_as_decimal (struct value *arg1, struct value *arg2,
|
value_args_as_target_float (struct value *arg1, struct value *arg2,
|
||||||
gdb_byte *x, int *len_x, enum bfd_endian *byte_order_x,
|
gdb_byte *x, struct type **eff_type_x,
|
||||||
gdb_byte *y, int *len_y, enum bfd_endian *byte_order_y)
|
gdb_byte *y, struct type **eff_type_y)
|
||||||
{
|
{
|
||||||
struct type *type1, *type2;
|
struct type *type1, *type2;
|
||||||
|
|
||||||
type1 = check_typedef (value_type (arg1));
|
type1 = check_typedef (value_type (arg1));
|
||||||
type2 = check_typedef (value_type (arg2));
|
type2 = check_typedef (value_type (arg2));
|
||||||
|
|
||||||
/* At least one of the arguments must be of decimal float type. */
|
/* At least one of the arguments must be of floating-point type. */
|
||||||
gdb_assert (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT
|
gdb_assert (is_floating_type (type1) || is_floating_type (type2));
|
||||||
|| TYPE_CODE (type2) == TYPE_CODE_DECFLOAT);
|
|
||||||
|
|
||||||
if (TYPE_CODE (type1) == TYPE_CODE_FLT
|
if (is_floating_type (type1) && is_floating_type (type2)
|
||||||
|| TYPE_CODE (type2) == TYPE_CODE_FLT)
|
&& TYPE_CODE (type1) != TYPE_CODE (type2))
|
||||||
/* The DFP extension to the C language does not allow mixing of
|
/* The DFP extension to the C language does not allow mixing of
|
||||||
* decimal float types with other float types in expressions
|
* decimal float types with other float types in expressions
|
||||||
* (see WDTR 24732, page 12). */
|
* (see WDTR 24732, page 12). */
|
||||||
error (_("Mixing decimal floating types with "
|
error (_("Mixing decimal floating types with "
|
||||||
"other floating types is not allowed."));
|
"other floating types is not allowed."));
|
||||||
|
|
||||||
/* Obtain decimal value of arg1, converting from other types
|
/* Obtain value of arg1, converting from other types if necessary. */
|
||||||
if necessary. */
|
|
||||||
|
|
||||||
if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT)
|
if (is_floating_type (type1))
|
||||||
{
|
{
|
||||||
*byte_order_x = gdbarch_byte_order (get_type_arch (type1));
|
*eff_type_x = type1;
|
||||||
*len_x = TYPE_LENGTH (type1);
|
memcpy (x, value_contents (arg1), TYPE_LENGTH (type1));
|
||||||
memcpy (x, value_contents (arg1), *len_x);
|
|
||||||
}
|
}
|
||||||
else if (is_integral_type (type1))
|
else if (is_integral_type (type1))
|
||||||
{
|
{
|
||||||
*byte_order_x = gdbarch_byte_order (get_type_arch (type2));
|
*eff_type_x = type2;
|
||||||
*len_x = TYPE_LENGTH (type2);
|
|
||||||
if (TYPE_UNSIGNED (type1))
|
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
|
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
|
else
|
||||||
error (_("Don't know how to convert from %s to %s."), TYPE_NAME (type1),
|
error (_("Don't know how to convert from %s to %s."), TYPE_NAME (type1),
|
||||||
TYPE_NAME (type2));
|
TYPE_NAME (type2));
|
||||||
|
|
||||||
/* Obtain decimal value of arg2, converting from other types
|
/* Obtain value of arg2, converting from other types if necessary. */
|
||||||
if necessary. */
|
|
||||||
|
|
||||||
if (TYPE_CODE (type2) == TYPE_CODE_DECFLOAT)
|
if (is_floating_type (type2))
|
||||||
{
|
{
|
||||||
*byte_order_y = gdbarch_byte_order (get_type_arch (type2));
|
*eff_type_y = type2;
|
||||||
*len_y = TYPE_LENGTH (type2);
|
memcpy (y, value_contents (arg2), TYPE_LENGTH (type2));
|
||||||
memcpy (y, value_contents (arg2), *len_y);
|
|
||||||
}
|
}
|
||||||
else if (is_integral_type (type2))
|
else if (is_integral_type (type2))
|
||||||
{
|
{
|
||||||
*byte_order_y = gdbarch_byte_order (get_type_arch (type1));
|
*eff_type_y = type1;
|
||||||
*len_y = TYPE_LENGTH (type1);
|
|
||||||
if (TYPE_UNSIGNED (type2))
|
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
|
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
|
else
|
||||||
error (_("Don't know how to convert from %s to %s."), TYPE_NAME (type1),
|
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));
|
type1 = check_typedef (value_type (arg1));
|
||||||
type2 = check_typedef (value_type (arg2));
|
type2 = check_typedef (value_type (arg2));
|
||||||
|
|
||||||
if ((TYPE_CODE (type1) != TYPE_CODE_FLT
|
if ((!is_floating_value (arg1) && !is_integral_type (type1))
|
||||||
&& TYPE_CODE (type1) != TYPE_CODE_DECFLOAT
|
|| (!is_floating_value (arg2) && !is_integral_type (type2)))
|
||||||
&& !is_integral_type (type1))
|
|
||||||
|| (TYPE_CODE (type2) != TYPE_CODE_FLT
|
|
||||||
&& TYPE_CODE (type2) != TYPE_CODE_DECFLOAT
|
|
||||||
&& !is_integral_type (type2)))
|
|
||||||
error (_("Argument to arithmetic operation not a number or boolean."));
|
error (_("Argument to arithmetic operation not a number or boolean."));
|
||||||
|
|
||||||
if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT
|
if (is_floating_type (type1) || is_floating_type (type2))
|
||||||
|| TYPE_CODE (type2) == TYPE_CODE_DECFLOAT)
|
|
||||||
{
|
{
|
||||||
int len_v1, len_v2, len_v;
|
/* If only one type is floating-point, use its type.
|
||||||
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.
|
|
||||||
Otherwise use the bigger type. */
|
Otherwise use the bigger type. */
|
||||||
if (TYPE_CODE (type1) != TYPE_CODE_DECFLOAT)
|
if (!is_floating_type (type1))
|
||||||
result_type = type2;
|
result_type = type2;
|
||||||
else if (TYPE_CODE (type2) != TYPE_CODE_DECFLOAT)
|
else if (!is_floating_type (type2))
|
||||||
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)
|
|
||||||
result_type = type1;
|
result_type = type1;
|
||||||
else if (TYPE_LENGTH (type2) > TYPE_LENGTH (type1))
|
else if (TYPE_LENGTH (type2) > TYPE_LENGTH (type1))
|
||||||
result_type = type2;
|
result_type = type2;
|
||||||
@ -1044,7 +941,18 @@ scalar_binop (struct value *arg1, struct value *arg2, enum exp_opcode op)
|
|||||||
result_type = type1;
|
result_type = type1;
|
||||||
|
|
||||||
val = allocate_value (result_type);
|
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
|
else if (TYPE_CODE (type1) == TYPE_CODE_BOOL
|
||||||
|| TYPE_CODE (type2) == 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)
|
if (is_int1 && is_int2)
|
||||||
return longest_to_int (value_as_long (value_binop (arg1, arg2,
|
return longest_to_int (value_as_long (value_binop (arg1, arg2,
|
||||||
BINOP_EQUAL)));
|
BINOP_EQUAL)));
|
||||||
else if ((code1 == TYPE_CODE_FLT || is_int1)
|
else if ((is_floating_value (arg1) || is_int1)
|
||||||
&& (code2 == TYPE_CODE_FLT || is_int2))
|
&& (is_floating_value (arg2) || is_int2))
|
||||||
{
|
{
|
||||||
/* NOTE: kettenis/20050816: Avoid compiler bug on systems where
|
struct type *eff_type_v1, *eff_type_v2;
|
||||||
`long double' values are returned in static storage (m68k). */
|
gdb::byte_vector v1, v2;
|
||||||
DOUBLEST d = value_as_double (arg1);
|
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);
|
value_args_as_target_float (arg1, arg2,
|
||||||
}
|
v1.data (), &eff_type_v1,
|
||||||
else if ((code1 == TYPE_CODE_DECFLOAT || is_int1)
|
v2.data (), &eff_type_v2);
|
||||||
&& (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,
|
return target_float_compare (v1.data (), eff_type_v1,
|
||||||
v2, &len_v2, &byte_order_v2);
|
v2.data (), eff_type_v2) == 0;
|
||||||
|
|
||||||
return decimal_compare (v1, len_v1, byte_order_v1,
|
|
||||||
v2, len_v2, byte_order_v2) == 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* FIXME: Need to promote to either CORE_ADDR or LONGEST, whichever
|
/* 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)
|
if (is_int1 && is_int2)
|
||||||
return longest_to_int (value_as_long (value_binop (arg1, arg2,
|
return longest_to_int (value_as_long (value_binop (arg1, arg2,
|
||||||
BINOP_LESS)));
|
BINOP_LESS)));
|
||||||
else if ((code1 == TYPE_CODE_FLT || is_int1)
|
else if ((is_floating_value (arg1) || is_int1)
|
||||||
&& (code2 == TYPE_CODE_FLT || is_int2))
|
&& (is_floating_value (arg2) || is_int2))
|
||||||
{
|
{
|
||||||
/* NOTE: kettenis/20050816: Avoid compiler bug on systems where
|
struct type *eff_type_v1, *eff_type_v2;
|
||||||
`long double' values are returned in static storage (m68k). */
|
gdb::byte_vector v1, v2;
|
||||||
DOUBLEST d = value_as_double (arg1);
|
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);
|
value_args_as_target_float (arg1, arg2,
|
||||||
}
|
v1.data (), &eff_type_v1,
|
||||||
else if ((code1 == TYPE_CODE_DECFLOAT || is_int1)
|
v2.data (), &eff_type_v2);
|
||||||
&& (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,
|
return target_float_compare (v1.data (), eff_type_v1,
|
||||||
v2, &len_v2, &byte_order_v2);
|
v2.data (), eff_type_v2) == -1;
|
||||||
|
|
||||||
return decimal_compare (v1, len_v1, byte_order_v1,
|
|
||||||
v2, len_v2, byte_order_v2) == -1;
|
|
||||||
}
|
}
|
||||||
else if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
|
else if (code1 == TYPE_CODE_PTR && code2 == TYPE_CODE_PTR)
|
||||||
return value_as_address (arg1) < value_as_address (arg2);
|
return value_as_address (arg1) < value_as_address (arg2);
|
||||||
@ -1733,22 +1627,9 @@ value_pos (struct value *arg1)
|
|||||||
arg1 = coerce_ref (arg1);
|
arg1 = coerce_ref (arg1);
|
||||||
type = check_typedef (value_type (arg1));
|
type = check_typedef (value_type (arg1));
|
||||||
|
|
||||||
if (TYPE_CODE (type) == TYPE_CODE_FLT)
|
if (is_integral_type (type) || is_floating_value (arg1)
|
||||||
return value_from_double (type, value_as_double (arg1));
|
|| (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type)))
|
||||||
else if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
|
return value_from_contents (type, value_contents (arg1));
|
||||||
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;
|
|
||||||
}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
error (_("Argument to positive operation not a number."));
|
error (_("Argument to positive operation not a number."));
|
||||||
@ -1764,28 +1645,8 @@ value_neg (struct value *arg1)
|
|||||||
arg1 = coerce_ref (arg1);
|
arg1 = coerce_ref (arg1);
|
||||||
type = check_typedef (value_type (arg1));
|
type = check_typedef (value_type (arg1));
|
||||||
|
|
||||||
if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
|
if (is_integral_type (type) || is_floating_type (type))
|
||||||
{
|
return value_binop (value_from_longest (type, 0), arg1, BINOP_SUB);
|
||||||
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));
|
|
||||||
}
|
|
||||||
else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type))
|
else if (TYPE_CODE (type) == TYPE_CODE_ARRAY && TYPE_VECTOR (type))
|
||||||
{
|
{
|
||||||
struct value *tmp, *val = allocate_value (type);
|
struct value *tmp, *val = allocate_value (type);
|
||||||
|
Loading…
Reference in New Issue
Block a user