aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--gdb/ChangeLog5
-rw-r--r--gdb/doublest.c61
-rw-r--r--gdb/doublest.h3
3 files changed, 68 insertions, 1 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog
index 67e27fe..5f4c9ef 100644
--- a/gdb/ChangeLog
+++ b/gdb/ChangeLog
@@ -1,3 +1,8 @@
+2001-10-29 Mark Kettenis <kettenis@gnu.org>
+
+ * doublest.h (convert_typed_floating): New prototype.
+ * doublest.c (convert_typed_floating): New function.
+
2001-10-28 Mark Kettenis <kettenis@gnu.org>
* doublest.c: Improve comments a bit.
diff --git a/gdb/doublest.c b/gdb/doublest.c
index 2fbf375..083a50a 100644
--- a/gdb/doublest.c
+++ b/gdb/doublest.c
@@ -713,7 +713,9 @@ store_typed_floating (void *addr, const struct type *type, DOUBLEST val)
TYPE_LENGTH (type) bits. If the end of the buffer wasn't
initialized, GDB would write undefined data to the target. An
errant program, refering to that undefined data, would then
- become non-deterministic. */
+ become non-deterministic.
+
+ See also the function convert_typed_floating below. */
memset (addr, 0, TYPE_LENGTH (type));
if (TYPE_FLOATFORMAT (type) == NULL)
@@ -721,3 +723,60 @@ store_typed_floating (void *addr, const struct type *type, DOUBLEST val)
floatformat_from_doublest (TYPE_FLOATFORMAT (type), &val, addr);
}
+
+/* Convert a floating-point number of type FROM_TYPE from a
+ target-order byte-stream at FROM to a floating-point number of type
+ TO_TYPE, and store it to a target-order byte-stream at TO. */
+
+void
+convert_typed_floating (const void *from, const struct type *from_type,
+ void *to, const struct type *to_type)
+{
+ const struct floatformat *from_fmt = TYPE_FLOATFORMAT (from_type);
+ const struct floatformat *to_fmt = TYPE_FLOATFORMAT (to_type);
+
+ gdb_assert (TYPE_CODE (from_type) == TYPE_CODE_FLT);
+ gdb_assert (TYPE_CODE (to_type) == TYPE_CODE_FLT);
+
+ /* If the floating-point format of FROM_TYPE or TO_TYPE isn't known,
+ try to guess it from the type's length. */
+ if (from_fmt == NULL)
+ from_fmt = floatformat_from_length (TYPE_LENGTH (from_type));
+ if (to_fmt == NULL)
+ to_fmt = floatformat_from_length (TYPE_LENGTH (to_type));
+
+ if (from_fmt == NULL || to_fmt == NULL)
+ {
+ /* If we don't know the floating-point format of FROM_TYPE or
+ TO_TYPE, there's not much we can do. We might make the
+ assumption that if the length of FROM_TYPE and TO_TYPE match,
+ their floating-point format would match too, but that
+ assumption might be wrong on targets that support
+ floating-point types that only differ in endianness for
+ example. So we warn instead, and zero out the target buffer. */
+ warning ("Can't convert floating-point number to desired type.");
+ memset (to, 0, TYPE_LENGTH (to_type));
+ }
+ else if (from_fmt == to_fmt)
+ {
+ /* We're in business. The floating-point format of FROM_TYPE
+ and TO_TYPE match. However, even though the floating-point
+ format matches, the length of the type might still be
+ different. Make sure we don't overrun any buffers. See
+ comment in store_typed_floating for a discussion about
+ zeroing out remaining bytes in the target buffer. */
+ memset (to, 0, TYPE_LENGTH (to_type));
+ memcpy (to, from, min (TYPE_LENGTH (from_type), TYPE_LENGTH (to_type)));
+ }
+ else
+ {
+ /* The floating-point types don't match. The best we can do
+ (aport 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);
+ }
+}
diff --git a/gdb/doublest.h b/gdb/doublest.h
index a31d849..ccd9233 100644
--- a/gdb/doublest.h
+++ b/gdb/doublest.h
@@ -72,5 +72,8 @@ extern DOUBLEST extract_typed_floating (const void *addr,
const struct type *type);
extern void store_typed_floating (void *addr, const struct type *type,
DOUBLEST val);
+extern void convert_typed_floating (const void *from,
+ const struct type *from_type,
+ void *to, const struct type *to_type);
#endif