#include "target-float.h"
+/* Helper routines operating on binary floating-point data. */
+
+/* Convert the byte-stream ADDR, interpreted as floating-point format FMT,
+ to an integer value (rounding towards zero). */
+static LONGEST
+floatformat_to_longest (const struct floatformat *fmt, const gdb_byte *addr)
+{
+ DOUBLEST d;
+ floatformat_to_doublest (fmt, addr, &d);
+ return (LONGEST) d;
+}
+
+/* Convert signed integer VAL to a target floating-number of format FMT
+ and store it as byte-stream ADDR. */
+static void
+floatformat_from_longest (const struct floatformat *fmt, gdb_byte *addr,
+ LONGEST val)
+{
+ DOUBLEST d = (DOUBLEST) val;
+ floatformat_from_doublest (fmt, &d, addr);
+}
+
+/* Convert unsigned integer VAL to a target floating-number of format FMT
+ and store it as byte-stream ADDR. */
+static void
+floatformat_from_ulongest (const struct floatformat *fmt, gdb_byte *addr,
+ ULONGEST val)
+{
+ DOUBLEST d = (DOUBLEST) val;
+ floatformat_from_doublest (fmt, &d, addr);
+}
+
+/* Convert a floating-point number of format FROM_FMT from the target
+ byte-stream FROM to a floating-point number of format TO_FMT, and
+ store it to the target byte-stream TO. */
+static void
+floatformat_convert (const gdb_byte *from, const struct floatformat *from_fmt,
+ gdb_byte *to, const struct floatformat *to_fmt)
+{
+ if (from_fmt == to_fmt)
+ {
+ /* The floating-point formats match, so we simply copy the data. */
+ memcpy (to, from, floatformat_totalsize_bytes (to_fmt));
+ }
+ else
+ {
+ /* The floating-point formats don't match. The best we can do
+ (apart from simulating the target FPU) is converting to the
+ widest floating-point type supported by the host, and then
+ again to the desired type. */
+ DOUBLEST d;
+
+ floatformat_to_doublest (from_fmt, from, &d);
+ floatformat_from_doublest (to_fmt, &d, to);
+ }
+}
+
+
/* 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
gdb_assert_not_reached ("unexpected type code");
}
+
+/* Convert the byte-stream ADDR, interpreted as floating-point type TYPE,
+ to an integer value (rounding towards zero). */
+LONGEST
+target_float_to_longest (const gdb_byte *addr, const struct type *type)
+{
+ if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ return floatformat_to_longest (floatformat_from_type (type), addr);
+
+ if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+ return decimal_to_longest (addr, TYPE_LENGTH (type),
+ gdbarch_byte_order (get_type_arch (type)));
+
+ gdb_assert_not_reached ("unexpected type code");
+}
+
+/* Convert signed integer VAL to a target floating-number of type TYPE
+ and store it as byte-stream ADDR. */
+void
+target_float_from_longest (gdb_byte *addr, const struct type *type,
+ LONGEST val)
+{
+ /* Ensure possible padding bytes in the target buffer are zeroed out. */
+ memset (addr, 0, TYPE_LENGTH (type));
+
+ if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ {
+ floatformat_from_longest (floatformat_from_type (type), addr, val);
+ return;
+ }
+
+ if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+ {
+ decimal_from_longest (val, addr, TYPE_LENGTH (type),
+ gdbarch_byte_order (get_type_arch (type)));
+ return;
+ }
+
+ gdb_assert_not_reached ("unexpected type code");
+}
+
+/* Convert unsigned integer VAL to a target floating-number of type TYPE
+ and store it as byte-stream ADDR. */
+void
+target_float_from_ulongest (gdb_byte *addr, const struct type *type,
+ ULONGEST val)
+{
+ /* Ensure possible padding bytes in the target buffer are zeroed out. */
+ memset (addr, 0, TYPE_LENGTH (type));
+
+ if (TYPE_CODE (type) == TYPE_CODE_FLT)
+ {
+ floatformat_from_ulongest (floatformat_from_type (type), addr, val);
+ return;
+ }
+
+ if (TYPE_CODE (type) == TYPE_CODE_DECFLOAT)
+ {
+ decimal_from_ulongest (val, addr, TYPE_LENGTH (type),
+ gdbarch_byte_order (get_type_arch (type)));
+ return;
+ }
+
+ gdb_assert_not_reached ("unexpected type code");
+}
+
+/* Convert a floating-point number of type FROM_TYPE from the target
+ byte-stream FROM to a floating-point number of type TO_TYPE, and
+ store it to the target byte-stream TO. */
+void
+target_float_convert (const gdb_byte *from, const struct type *from_type,
+ gdb_byte *to, const struct type *to_type)
+{
+ /* Ensure possible padding bytes in the target buffer are zeroed out. */
+ memset (to, 0, TYPE_LENGTH (to_type));
+
+ /* Use direct conversion routines if we have them. */
+
+ if (TYPE_CODE (from_type) == TYPE_CODE_FLT
+ && TYPE_CODE (to_type) == TYPE_CODE_FLT)
+ {
+ floatformat_convert (from, floatformat_from_type (from_type),
+ to, floatformat_from_type (to_type));
+ return;
+ }
+
+ if (TYPE_CODE (from_type) == TYPE_CODE_DECFLOAT
+ && TYPE_CODE (to_type) == TYPE_CODE_DECFLOAT)
+ {
+ decimal_convert (from, TYPE_LENGTH (from_type),
+ gdbarch_byte_order (get_type_arch (from_type)),
+ to, TYPE_LENGTH (to_type),
+ gdbarch_byte_order (get_type_arch (to_type)));
+ return;
+ }
+
+ /* We cannot directly convert between binary and decimal floating-point
+ types, so go via an intermediary string. */
+
+ if ((TYPE_CODE (from_type) == TYPE_CODE_FLT
+ && TYPE_CODE (to_type) == TYPE_CODE_DECFLOAT)
+ || (TYPE_CODE (from_type) == TYPE_CODE_DECFLOAT
+ && TYPE_CODE (to_type) == TYPE_CODE_FLT))
+ {
+ std::string str = target_float_to_string (from, from_type);
+ target_float_from_string (to, to_type, str);
+ return;
+ }
+
+ gdb_assert_not_reached ("unexpected type code");
+}
#include "infcall.h"
#include "dictionary.h"
#include "cp-support.h"
-#include "dfp.h"
+#include "target-float.h"
#include "tracepoint.h"
#include "observer.h"
#include "objfiles.h"
return v;
}
- if (code1 == TYPE_CODE_FLT && scalar)
- return value_from_double (to_type, value_as_double (arg2));
- else if (code1 == TYPE_CODE_DECFLOAT && scalar)
+ if (is_floating_type (type) && scalar)
{
- enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
- int dec_len = TYPE_LENGTH (type);
- gdb_byte dec[16];
+ if (is_floating_value (arg2))
+ {
+ struct value *v = allocate_value (to_type);
+ target_float_convert (value_contents (arg2), type2,
+ value_contents_raw (v), type);
+ return v;
+ }
- if (code2 == TYPE_CODE_FLT)
- decimal_from_doublest (value_as_double (arg2),
- dec, dec_len, byte_order);
- else if (code2 == TYPE_CODE_DECFLOAT)
- decimal_convert (value_contents (arg2), TYPE_LENGTH (type2),
- byte_order, dec, dec_len, byte_order);
/* The only option left is an integral type. */
- else if (TYPE_UNSIGNED (type2))
- decimal_from_ulongest (value_as_long (arg2),
- dec, dec_len, byte_order);
+ if (TYPE_UNSIGNED (type2))
+ return value_from_ulongest (to_type, value_as_long (arg2));
else
- decimal_from_longest (value_as_long (arg2),
- dec, dec_len, byte_order);
-
- return value_from_decfloat (to_type, dec);
+ return value_from_longest (to_type, value_as_long (arg2));
}
else if ((code1 == TYPE_CODE_INT || code1 == TYPE_CODE_ENUM
|| code1 == TYPE_CODE_RANGE)
struct type *type1 = check_typedef (type);
struct value *val;
- if (TYPE_CODE (type1) == TYPE_CODE_DECFLOAT)
- {
- enum bfd_endian byte_order = gdbarch_byte_order (get_type_arch (type));
- gdb_byte v[16];
-
- decimal_from_string (v, TYPE_LENGTH (type), byte_order, "1");
- val = value_from_decfloat (type, v);
- }
- else if (TYPE_CODE (type1) == TYPE_CODE_FLT)
- {
- val = value_from_double (type, (DOUBLEST) 1);
- }
- else if (is_integral_type (type1))
+ if (is_integral_type (type1) || is_floating_type (type1))
{
val = value_from_longest (type, (LONGEST) 1);
}