aboutsummaryrefslogtreecommitdiff
path: root/gdb/i386-tdep.c
diff options
context:
space:
mode:
authorMark Kettenis <kettenis@gnu.org>2003-11-20 22:37:50 +0000
committerMark Kettenis <kettenis@gnu.org>2003-11-20 22:37:50 +0000
commitc5e656c1c7ab1e26ead1530b708af08ac272b95d (patch)
tree1f1a2a03c44a233c64ebd1dff416a3dda2a47f5d /gdb/i386-tdep.c
parent0d78efdfab83b824b6496ac65ea4c893e816f8ea (diff)
downloadgdb-c5e656c1c7ab1e26ead1530b708af08ac272b95d.zip
gdb-c5e656c1c7ab1e26ead1530b708af08ac272b95d.tar.gz
gdb-c5e656c1c7ab1e26ead1530b708af08ac272b95d.tar.bz2
* i386-tdep.c (i386_extract_return_value,
i386_store_return_value): Add gdbarch argument. Use it instead of determining it from REGCACHE. Remove recursive call for structures with a single member. (i386_use_struct_convention): Remove. (i386_reg_struct_return_p): New function. (i386_return_value): New function. (i386_gdbarch_init): Set return_value, don't set extract_return_value, store_return_value and use_struct_convention. * x86-64-tdep.c (x86_64_init_abi): Set return_value to NULL.
Diffstat (limited to 'gdb/i386-tdep.c')
-rw-r--r--gdb/i386-tdep.c101
1 files changed, 63 insertions, 38 deletions
diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c
index 120b78c..973fa63 100644
--- a/gdb/i386-tdep.c
+++ b/gdb/i386-tdep.c
@@ -1151,25 +1151,17 @@ i386_push_dummy_call (struct gdbarch *gdbarch, CORE_ADDR func_addr,
#define LOW_RETURN_REGNUM I386_EAX_REGNUM /* %eax */
#define HIGH_RETURN_REGNUM I386_EDX_REGNUM /* %edx */
-/* Extract from an array REGBUF containing the (raw) register state, a
- function return value of TYPE, and copy that, in virtual format,
- into VALBUF. */
+/* Read, for architecture GDBARCH, a function return value of TYPE
+ from REGCACHE, and copy that into VALBUF. */
static void
-i386_extract_return_value (struct type *type, struct regcache *regcache,
- void *valbuf)
+i386_extract_return_value (struct gdbarch *gdbarch, struct type *type,
+ struct regcache *regcache, void *valbuf)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
int len = TYPE_LENGTH (type);
char buf[I386_MAX_REGISTER_SIZE];
- if (TYPE_CODE (type) == TYPE_CODE_STRUCT
- && TYPE_NFIELDS (type) == 1)
- {
- i386_extract_return_value (TYPE_FIELD_TYPE (type, 0), regcache, valbuf);
- return;
- }
-
if (TYPE_CODE (type) == TYPE_CODE_FLT)
{
if (tdep->st0_regnum < 0)
@@ -1209,27 +1201,20 @@ i386_extract_return_value (struct type *type, struct regcache *regcache,
}
}
-/* Write into the appropriate registers a function return value stored
- in VALBUF of type TYPE, given in virtual format. */
+/* Write, for architecture GDBARCH, a function return value of TYPE
+ from VALBUF into REGCACHE. */
static void
-i386_store_return_value (struct type *type, struct regcache *regcache,
- const void *valbuf)
+i386_store_return_value (struct gdbarch *gdbarch, struct type *type,
+ struct regcache *regcache, const void *valbuf)
{
- struct gdbarch_tdep *tdep = gdbarch_tdep (get_regcache_arch (regcache));
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
int len = TYPE_LENGTH (type);
/* Define I387_ST0_REGNUM such that we use the proper definitions
for the architecture. */
#define I387_ST0_REGNUM I386_ST0_REGNUM
- if (TYPE_CODE (type) == TYPE_CODE_STRUCT
- && TYPE_NFIELDS (type) == 1)
- {
- i386_store_return_value (TYPE_FIELD_TYPE (type, 0), regcache, valbuf);
- return;
- }
-
if (TYPE_CODE (type) == TYPE_CODE_FLT)
{
ULONGEST fstat;
@@ -1314,20 +1299,62 @@ static const char *valid_conventions[] =
};
static const char *struct_convention = default_struct_convention;
+/* Return non-zero if TYPE, which is assumed to be a structure or
+ union type, should be returned in registers for architecture
+ GDBARCH. */
+
static int
-i386_use_struct_convention (int gcc_p, struct type *type)
+i386_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type)
+{
+ struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch);
+ enum type_code code = TYPE_CODE (type);
+ int len = TYPE_LENGTH (type);
+
+ gdb_assert (code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION);
+
+ if (struct_convention == pcc_struct_convention
+ || (struct_convention == default_struct_convention
+ && tdep->struct_return == pcc_struct_return))
+ return 0;
+
+ return (len == 1 || len == 2 || len == 4 || len == 8);
+}
+
+/* Determine, for architecture GDBARCH, how a return value of TYPE
+ should be returned. If it is supposed to be returned in registers,
+ and READBUF is non-zero, read the appropriate value from REGCACHE,
+ and copy it into READBUF. If WRITEBUF is non-zero, write the value
+ from WRITEBUF into REGCACHE. */
+
+static enum return_value_convention
+i386_return_value (struct gdbarch *gdbarch, struct type *type,
+ struct regcache *regcache, void *readbuf,
+ const void *writebuf)
{
- enum struct_return struct_return;
+ enum type_code code = TYPE_CODE (type);
- if (struct_convention == default_struct_convention)
- struct_return = gdbarch_tdep (current_gdbarch)->struct_return;
- else if (struct_convention == pcc_struct_convention)
- struct_return = pcc_struct_return;
- else
- struct_return = reg_struct_return;
+ if ((code == TYPE_CODE_STRUCT || code == TYPE_CODE_UNION)
+ && !i386_reg_struct_return_p (gdbarch, type))
+ return RETURN_VALUE_STRUCT_CONVENTION;
+
+ /* This special case is for structures consisting of a single
+ `float' or `double' member. These structures are returned in
+ %st(0). For these structures, we call ourselves recursively,
+ changing TYPE into the type of the first member of the structure.
+ Since that should work for all structures that have only one
+ member, we don't bother to check the member's type here. */
+ if (code == TYPE_CODE_STRUCT && TYPE_NFIELDS (type) == 1)
+ {
+ type = check_typedef (TYPE_FIELD_TYPE (type, 0));
+ return i386_return_value (gdbarch, type, regcache, readbuf, writebuf);
+ }
+
+ if (readbuf)
+ i386_extract_return_value (gdbarch, type, regcache, readbuf);
+ if (writebuf)
+ i386_store_return_value (gdbarch, type, regcache, writebuf);
- return generic_use_struct_convention (struct_return == reg_struct_return,
- type);
+ return RETURN_VALUE_REGISTER_CONVENTION;
}
@@ -1963,11 +1990,9 @@ i386_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches)
set_gdbarch_register_to_value (gdbarch, i386_register_to_value);
set_gdbarch_value_to_register (gdbarch, i386_value_to_register);
- set_gdbarch_extract_return_value (gdbarch, i386_extract_return_value);
- set_gdbarch_store_return_value (gdbarch, i386_store_return_value);
+ set_gdbarch_return_value (gdbarch, i386_return_value);
set_gdbarch_extract_struct_value_address (gdbarch,
i386_extract_struct_value_address);
- set_gdbarch_use_struct_convention (gdbarch, i386_use_struct_convention);
set_gdbarch_skip_prologue (gdbarch, i386_skip_prologue);