diff options
-rw-r--r-- | gdb/ChangeLog | 5 | ||||
-rw-r--r-- | gdb/doublest.c | 61 | ||||
-rw-r--r-- | gdb/doublest.h | 3 |
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 |