From 4c8b6ae009ad0e664cb1ec681e58c4a942fa4915 Mon Sep 17 00:00:00 2001 From: Ulrich Weigand Date: Sat, 13 Oct 2007 00:05:07 +0000 Subject: [PATCH] * avr-tdep.c (avr_return_value): New function. (avr_gdbarch_init): Call set_gdbarch_return_value instead of set_gdbarch_extract_return_value. * fvr-tdep.c (frv_return_value): New function. (frv_gdbarch_init): Call set_gdbarch_return_value instead of set_gdbarch_extract_return_value, set_gdbarch_store_return_value, and set_gdbarch_deprecated_use_struct_convention. * ia64-tdep.c (ia64_use_struct_convention): Make static. Add check for structure, union, or array types. (ia64_extract_return_value): Make static. (ia64_store_return_value): Make static. Support multi-word values. (ia64_return_value): New function. (ia64_gdbarch_init): Call set_gdbarch_return_value instead of set_gdbarch_extract_return_value, set_gdbarch_store_return_value, and set_gdbarch_deprecated_use_struct_convention. --- gdb/ChangeLog | 20 +++++++++ gdb/avr-tdep.c | 40 +++++++++++++++++- gdb/frv-tdep.c | 32 ++++++++++++-- gdb/ia64-tdep.c | 110 +++++++++++++++++++++++++++++++++++++----------- 4 files changed, 172 insertions(+), 30 deletions(-) diff --git a/gdb/ChangeLog b/gdb/ChangeLog index 7a13c9ea73a..743f1440cf2 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,23 @@ +2007-10-12 Ulrich Weigand + + * avr-tdep.c (avr_return_value): New function. + (avr_gdbarch_init): Call set_gdbarch_return_value instead of + set_gdbarch_extract_return_value. + + * fvr-tdep.c (frv_return_value): New function. + (frv_gdbarch_init): Call set_gdbarch_return_value instead of + set_gdbarch_extract_return_value, set_gdbarch_store_return_value, + and set_gdbarch_deprecated_use_struct_convention. + + * ia64-tdep.c (ia64_use_struct_convention): Make static. + Add check for structure, union, or array types. + (ia64_extract_return_value): Make static. + (ia64_store_return_value): Make static. Support multi-word values. + (ia64_return_value): New function. + (ia64_gdbarch_init): Call set_gdbarch_return_value instead of + set_gdbarch_extract_return_value, set_gdbarch_store_return_value, + and set_gdbarch_deprecated_use_struct_convention. + 2007-10-12 Joel Brobecker * solib-target.c (solib_target_parse_libraries) diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c index 3db8530c14d..d3ecf2b5d64 100644 --- a/gdb/avr-tdep.c +++ b/gdb/avr-tdep.c @@ -827,6 +827,44 @@ avr_extract_return_value (struct type *type, struct regcache *regcache, } } +/* 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. */ + +enum return_value_convention +avr_return_value (struct gdbarch *gdbarch, struct type *valtype, + struct regcache *regcache, gdb_byte *readbuf, + const gdb_byte *writebuf) +{ + int struct_return = ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT + || TYPE_CODE (valtype) == TYPE_CODE_UNION + || TYPE_CODE (valtype) == TYPE_CODE_ARRAY) + && !(TYPE_LENGTH (valtype) == 1 + || TYPE_LENGTH (valtype) == 2 + || TYPE_LENGTH (valtype) == 4 + || TYPE_LENGTH (valtype) == 8)); + + if (writebuf != NULL) + { + gdb_assert (!struct_return); + error (_("Cannot store return value.")); + } + + if (readbuf != NULL) + { + gdb_assert (!struct_return); + avr_extract_return_value (valtype, regcache, readbuf); + } + + if (struct_return) + return RETURN_VALUE_STRUCT_CONVENTION; + else + return RETURN_VALUE_REGISTER_CONVENTION; +} + + /* Put here the code to store, into fi->saved_regs, the addresses of the saved registers of frame described by FRAME_INFO. This includes special registers such as pc and fp saved in special ways @@ -1271,7 +1309,7 @@ avr_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_register_name (gdbarch, avr_register_name); set_gdbarch_register_type (gdbarch, avr_register_type); - set_gdbarch_extract_return_value (gdbarch, avr_extract_return_value); + set_gdbarch_return_value (gdbarch, avr_return_value); set_gdbarch_print_insn (gdbarch, print_insn_avr); set_gdbarch_push_dummy_call (gdbarch, avr_push_dummy_call); diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c index c6746b99b28..6dd7d365d17 100644 --- a/gdb/frv-tdep.c +++ b/gdb/frv-tdep.c @@ -1247,6 +1247,33 @@ frv_store_return_value (struct type *type, struct regcache *regcache, _("Don't know how to return a %d-byte value."), len); } +enum return_value_convention +frv_return_value (struct gdbarch *gdbarch, struct type *valtype, + struct regcache *regcache, gdb_byte *readbuf, + const gdb_byte *writebuf) +{ + int struct_return = TYPE_CODE (valtype) == TYPE_CODE_STRUCT + || TYPE_CODE (valtype) == TYPE_CODE_UNION + || TYPE_CODE (valtype) == TYPE_CODE_ARRAY; + + if (writebuf != NULL) + { + gdb_assert (!struct_return); + frv_store_return_value (valtype, regcache, writebuf); + } + + if (readbuf != NULL) + { + gdb_assert (!struct_return); + frv_extract_return_value (valtype, regcache, readbuf); + } + + if (struct_return) + return RETURN_VALUE_STRUCT_CONVENTION; + else + return RETURN_VALUE_REGISTER_CONVENTION; +} + /* Hardware watchpoint / breakpoint support for the FR500 and FR400. */ @@ -1488,10 +1515,7 @@ frv_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_adjust_breakpoint_address (gdbarch, frv_adjust_breakpoint_address); - set_gdbarch_deprecated_use_struct_convention (gdbarch, always_use_struct_convention); - set_gdbarch_extract_return_value (gdbarch, frv_extract_return_value); - - set_gdbarch_store_return_value (gdbarch, frv_store_return_value); + set_gdbarch_return_value (gdbarch, frv_return_value); /* Frame stuff. */ set_gdbarch_unwind_pc (gdbarch, frv_unwind_pc); diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c index dd938c95e85..debee50851c 100644 --- a/gdb/ia64-tdep.c +++ b/gdb/ia64-tdep.c @@ -2929,14 +2929,18 @@ static struct libunwind_descr ia64_libunwind_descr = #endif /* HAVE_LIBUNWIND_IA64_H */ -/* Should we use DEPRECATED_EXTRACT_STRUCT_VALUE_ADDRESS instead of - gdbarch_extract_return_value? GCC_P is true if compiled with gcc and TYPE - is the type (which is known to be struct, union or array). */ -int -ia64_use_struct_convention (int gcc_p, struct type *type) +static int +ia64_use_struct_convention (struct type *type) { struct type *float_elt_type; + /* Don't use the struct convention for anything but structure, + union, or array types. */ + if (!(TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION + || TYPE_CODE (type) == TYPE_CODE_ARRAY)) + return 0; + /* HFAs are structures (or arrays) consisting entirely of floating point values of the same length. Up to 8 of these are returned in registers. Don't use the struct convention when this is the @@ -2951,7 +2955,7 @@ ia64_use_struct_convention (int gcc_p, struct type *type) return TYPE_LENGTH (type) > 32; } -void +static void ia64_extract_return_value (struct type *type, struct regcache *regcache, gdb_byte *valbuf) { @@ -3001,6 +3005,80 @@ ia64_extract_return_value (struct type *type, struct regcache *regcache, } } +static void +ia64_store_return_value (struct type *type, struct regcache *regcache, + const gdb_byte *valbuf) +{ + struct type *float_elt_type; + + float_elt_type = is_float_or_hfa_type (type); + if (float_elt_type != NULL) + { + char to[MAX_REGISTER_SIZE]; + int offset = 0; + int regnum = IA64_FR8_REGNUM; + int n = TYPE_LENGTH (type) / TYPE_LENGTH (float_elt_type); + + while (n-- > 0) + { + convert_typed_floating ((char *)valbuf + offset, float_elt_type, + to, builtin_type_ia64_ext); + regcache_cooked_write (regcache, regnum, to); + offset += TYPE_LENGTH (float_elt_type); + regnum++; + } + } + else + { + ULONGEST val; + int offset = 0; + int regnum = IA64_GR8_REGNUM; + int reglen = TYPE_LENGTH (register_type (get_regcache_arch (regcache), + IA64_GR8_REGNUM)); + int n = TYPE_LENGTH (type) / reglen; + int m = TYPE_LENGTH (type) % reglen; + + while (n-- > 0) + { + ULONGEST val; + memcpy (&val, (char *)valbuf + offset, reglen); + regcache_cooked_write_unsigned (regcache, regnum, val); + offset += reglen; + regnum++; + } + + if (m) + { + memcpy (&val, (char *)valbuf + offset, m); + regcache_cooked_write_unsigned (regcache, regnum, val); + } + } +} + +static enum return_value_convention +ia64_return_value (struct gdbarch *gdbarch, struct type *valtype, + struct regcache *regcache, gdb_byte *readbuf, + const gdb_byte *writebuf) +{ + int struct_return = ia64_use_struct_convention (valtype); + + if (writebuf != NULL) + { + gdb_assert (!struct_return); + ia64_store_return_value (valtype, regcache, writebuf); + } + + if (readbuf != NULL) + { + gdb_assert (!struct_return); + ia64_extract_return_value (valtype, regcache, readbuf); + } + + if (struct_return) + return RETURN_VALUE_STRUCT_CONVENTION; + else + return RETURN_VALUE_REGISTER_CONVENTION; +} static int is_float_or_hfa_type_recurse (struct type *t, struct type **etp) @@ -3462,21 +3540,6 @@ ia64_unwind_pc (struct gdbarch *gdbarch, struct frame_info *next_frame) return pc; } -static void -ia64_store_return_value (struct type *type, struct regcache *regcache, - const gdb_byte *valbuf) -{ - if (TYPE_CODE (type) == TYPE_CODE_FLT) - { - char to[MAX_REGISTER_SIZE]; - convert_typed_floating (valbuf, type, to, builtin_type_ia64_ext); - regcache_cooked_write (regcache, IA64_FR8_REGNUM, (void *)to); - target_store_registers (regcache, IA64_FR8_REGNUM); - } - else - regcache_cooked_write (regcache, IA64_GR8_REGNUM, valbuf); -} - static int ia64_print_insn (bfd_vma memaddr, struct disassemble_info *info) { @@ -3544,10 +3607,7 @@ ia64_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) set_gdbarch_skip_prologue (gdbarch, ia64_skip_prologue); - set_gdbarch_deprecated_use_struct_convention (gdbarch, ia64_use_struct_convention); - set_gdbarch_extract_return_value (gdbarch, ia64_extract_return_value); - - set_gdbarch_store_return_value (gdbarch, ia64_store_return_value); + set_gdbarch_return_value (gdbarch, ia64_return_value); set_gdbarch_memory_insert_breakpoint (gdbarch, ia64_memory_insert_breakpoint); set_gdbarch_memory_remove_breakpoint (gdbarch, ia64_memory_remove_breakpoint);