aboutsummaryrefslogtreecommitdiff
path: root/gdb/i386-tdep.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2000-12-21 20:52:59 +0000
committerMark Kettenis <kettenis@gnu.org>2000-12-21 20:52:59 +0000
commitef9dff19c46d6269eb1faed4d8903710f2c91f2d (patch)
treea17a033f5637650e2436d93951b5b51ef44b5c4b /gdb/i386-tdep.c
parent2866d3057449bb4fe35784fb86accf03863ed87b (diff)
downloadgdb-ef9dff19c46d6269eb1faed4d8903710f2c91f2d.zip
gdb-ef9dff19c46d6269eb1faed4d8903710f2c91f2d.tar.gz
gdb-ef9dff19c46d6269eb1faed4d8903710f2c91f2d.tar.bz2
* i386-tdep.c: Add missing ')' in comment.
(i386_extract_return_value): Return directly after issuing the warning and filling *VALBUF with zeroes if we cannot get at the floating-point registers. (i386_store_return_value): New function. * config/i386/tm-i386.h (STORE_RETURN_VALUE): Simply call i386_store_return_value. Add prototype for i386_store_return_value.
Diffstat (limited to 'gdb/i386-tdep.c')
-rw-r--r--gdb/i386-tdep.c61
1 files changed, 60 insertions, 1 deletions
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 8aaf651..0750efc 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -713,7 +713,7 @@ get_longjmp_target (CORE_ADDR *pc)
/* These registers are used for returning integers (and on some
targets also for returning `struct' and `union' values when their
- size and alignment match an integer type. */
+ size and alignment match an integer type). */
#define LOW_RETURN_REGNUM 0 /* %eax */
#define HIGH_RETURN_REGNUM 2 /* %edx */
@@ -732,6 +732,7 @@ i386_extract_return_value (struct type *type, char *regbuf, char *valbuf)
{
warning ("Cannot find floating-point return value.");
memset (valbuf, 0, len);
+ return;
}
/* Floating-point return values can be found in %st(0). */
@@ -774,6 +775,64 @@ i386_extract_return_value (struct type *type, char *regbuf, char *valbuf)
}
}
+/* Write into the appropriate registers a function return value stored
+ in VALBUF of type TYPE, given in virtual format. */
+
+void
+i386_store_return_value (struct type *type, char *valbuf)
+{
+ int len = TYPE_LENGTH (type);
+
+ if (TYPE_CODE_FLT == TYPE_CODE (type))
+ {
+ if (NUM_FREGS == 0)
+ {
+ warning ("Cannot set floating-point return value.");
+ return;
+ }
+
+ /* Floating-point return values can be found in %st(0). */
+ if (len == TARGET_LONG_DOUBLE_BIT / TARGET_CHAR_BIT
+ && TARGET_LONG_DOUBLE_FORMAT == &floatformat_i387_ext)
+ {
+ /* Copy straight over. */
+ write_register_bytes (REGISTER_BYTE (FP0_REGNUM), valbuf,
+ FPU_REG_RAW_SIZE);
+ }
+ else
+ {
+ char buf[FPU_REG_RAW_SIZE];
+ DOUBLEST val;
+
+ /* Convert the value found in VALBUF to the extended
+ floating point format used by the FPU. This is probably
+ not exactly how it would happen on the target itself, but
+ it is the best we can do. */
+ val = extract_floating (valbuf, TYPE_LENGTH (type));
+ floatformat_from_doublest (&floatformat_i387_ext, &val, buf);
+ write_register_bytes (REGISTER_BYTE (FP0_REGNUM), buf,
+ FPU_REG_RAW_SIZE);
+ }
+ }
+ else
+ {
+ int low_size = REGISTER_RAW_SIZE (LOW_RETURN_REGNUM);
+ int high_size = REGISTER_RAW_SIZE (HIGH_RETURN_REGNUM);
+
+ if (len <= low_size)
+ write_register_bytes (REGISTER_BYTE (LOW_RETURN_REGNUM), valbuf, len);
+ else if (len <= (low_size + high_size))
+ {
+ write_register_bytes (REGISTER_BYTE (LOW_RETURN_REGNUM),
+ valbuf, low_size);
+ write_register_bytes (REGISTER_BYTE (HIGH_RETURN_REGNUM),
+ valbuf + low_size, len - low_size);
+ }
+ else
+ internal_error ("Cannot store return value of %d bytes long.", len);
+ }
+}
+
/* Convert data from raw format for register REGNUM in buffer FROM to
virtual format with type TYPE in buffer TO. In principle both
formats are identical except that the virtual format has two extra