diff options
author | Joel Brobecker <brobecker@gnat.com> | 2010-01-29 05:29:21 +0000 |
---|---|---|
committer | Joel Brobecker <brobecker@gnat.com> | 2010-01-29 05:29:21 +0000 |
commit | cba6fab54a80261d8f1e6831bc5c560481cfc107 (patch) | |
tree | 9afc8fa0b150d82f63c72a8a5827e8419c99b874 /gdb/amd64-windows-tdep.c | |
parent | 3af6ddfec6363b97f9c850fef9f33e3bd2ad259c (diff) | |
download | gdb-cba6fab54a80261d8f1e6831bc5c560481cfc107.zip gdb-cba6fab54a80261d8f1e6831bc5c560481cfc107.tar.gz gdb-cba6fab54a80261d8f1e6831bc5c560481cfc107.tar.bz2 |
Implement return values on amd64-windows.
* amd64-windows-tdep.c: #include gdbcore.h and regcache.h.
(amd64_windows_return_value): New function.
(amd64_windows_init_abi): Call set_gdbarch_return_value with
amd64_windows_return_value.
Diffstat (limited to 'gdb/amd64-windows-tdep.c')
-rw-r--r-- | gdb/amd64-windows-tdep.c | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/gdb/amd64-windows-tdep.c b/gdb/amd64-windows-tdep.c index 05c4c1e..05d0824 100644 --- a/gdb/amd64-windows-tdep.c +++ b/gdb/amd64-windows-tdep.c @@ -21,6 +21,8 @@ #include "solib.h" #include "solib-target.h" #include "gdbtypes.h" +#include "gdbcore.h" +#include "regcache.h" /* The registers used to pass integer arguments during a function call. */ static int amd64_windows_dummy_call_integer_regs[] = @@ -68,6 +70,58 @@ amd64_windows_classify (struct type *type, enum amd64_reg_class class[2]) } } +/* Implement the "return_value" gdbarch method for amd64-windows. */ + +static enum return_value_convention +amd64_windows_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) +{ + int len = TYPE_LENGTH (type); + int regnum = -1; + + /* See if our value is returned through a register. If it is, then + store the associated register number in REGNUM. */ + switch (TYPE_CODE (type)) + { + case TYPE_CODE_FLT: + case TYPE_CODE_DECFLOAT: + /* __m128, __m128i, __m128d, floats, and doubles are returned + via XMM0. */ + if (len == 4 || len == 8 || len == 16) + regnum = AMD64_XMM0_REGNUM; + break; + default: + /* All other values that are 1, 2, 4 or 8 bytes long are returned + via RAX. */ + if (len == 1 || len == 2 || len == 4 || len == 8) + regnum = AMD64_RAX_REGNUM; + break; + } + + if (regnum < 0) + { + /* RAX contains the address where the return value has been stored. */ + if (readbuf) + { + ULONGEST addr; + + regcache_raw_read_unsigned (regcache, AMD64_RAX_REGNUM, &addr); + read_memory (addr, readbuf, TYPE_LENGTH (type)); + } + return RETURN_VALUE_ABI_RETURNS_ADDRESS; + } + else + { + /* Extract the return value from the register where it was stored. */ + if (readbuf) + regcache_raw_read_part (regcache, regnum, 0, len, readbuf); + if (writebuf) + regcache_raw_write_part (regcache, regnum, 0, len, writebuf); + return RETURN_VALUE_REGISTER_CONVENTION; + } +} + static void amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) { @@ -85,6 +139,7 @@ amd64_windows_init_abi (struct gdbarch_info info, struct gdbarch *gdbarch) tdep->classify = amd64_windows_classify; tdep->memory_args_by_pointer = 1; tdep->integer_param_regs_saved_in_caller_frame = 1; + set_gdbarch_return_value (gdbarch, amd64_windows_return_value); set_solib_ops (gdbarch, &solib_target_so_ops); } |