diff options
51 files changed, 441 insertions, 156 deletions
diff --git a/gdb/ChangeLog b/gdb/ChangeLog index db29ac8..a5aa714 100644 --- a/gdb/ChangeLog +++ b/gdb/ChangeLog @@ -1,3 +1,102 @@ +2008-04-22 Corinna Vinschen <vinschen@redhat.com> + + * NEWS: Add information on calling convention and new SH CLI options. + + * sh-tdep.c (sh_cc_gcc): New static string. + (sh_cc_renesas): Ditto. + (sh_cc_enum): New static string array. + (sh_active_calling_convention): New static string pointer denoting + active user chosen ABI. + (sh_is_renesas_calling_convention): New function to return function + specific ABI, or user choice if necessary. + (sh_use_struct_convention): Rename first argument and turn around its + meaning. Check for renesas ABI and return accordingly. + (sh_use_struct_convention_nofpu): New function. + (sh_next_flt_argreg): Get function type as third parameter. Check + for renesas ABI and choose floating registers accordingly. + (sh_push_dummy_call_fpu): Check for ABI and choose argument slot and + struct return slot accordingly. + (sh_push_dummy_call_nofpu): Ditto. + (sh_return_value_nofpu): Call sh_use_struct_convention_nofpu from here. + Evaluate ABI and give to sh_use_struct_convention_nofpu. + (sh_return_value_fpu): Evaluate ABI and give to + sh_use_struct_convention. + (show_sh_command): New function. + (set_sh_command): Ditto. + (_initialize_sh_tdep): Initialize `set/show sh calling-convention + CLI command. + + * gdbarch.sh (return_value): Add func_type argument. + * gdbarch.c: Regenerate. + * gdbarch.h: Ditto. + * eval.c (evaluate_subexp_standard): Rename local variable value_type to + val_type so as not to collide with value_type function. Call + using_struct_return with additional function type argument. + * infcall.c (call_function_by_hand): Call using_struct_return and + gdbarch_return_value with additional function type argument. + * infcmd.c (print_return_value): Take addition func_type argument. + Call gdbarch_return_value with additional function type argument. + (finish_command_continuation): Call print_return_value with additional + function type argument. + (finish_command): Ditto. + * sparc-tdep.c (sparc32_push_dummy_code): Call using_struct_return with + additional function type argument. + * stack.c (return_command): Call using_struct_return and + gdbarch_return_value with additional function type argument. + * value.c (using_struct_return): Take additional function type argument. + * value.h (using_struct_return): Accommodate declaration. + * alpha-tdep.c (alpha_return_value): Add func_type argument. + * amd64-tdep.c (amd64_return_value): Ditto. + * arm-tdep.c (arm_return_value): Ditto. + * avr-tdep.c (avr_return_value): Ditto. + * cris-tdep.c (cris_return_value): Ditto. + * frv-tdep.c (frv_return_value): Ditto. + * h8300-tdep.c (h8300_return_value): Ditto. + (h8300h_return_value): Ditto. + * hppa-tdep.c (hppa32_return_value): Ditto. + (hppa64_return_value): Ditto. + * i386-tdep.c (i386_return_value): Ditto. + * ia64-tdep.c (ia64_return_value): Ditto. + * iq2000-tdep.c (iq2000_return_value): Ditto. + * m32c-tdep.c (m32c_return_value): Ditto. + * m32r-tdep.c (m32r_return_value): Ditto. + * m68hc11-tdep.c (m68hc11_return_value): Ditto. + * m68k-tdep.c (m68k_return_value): Ditto. + (m68k_svr4_return_value): Ditto. + * m88k-tdep.c (m88k_return_value): Ditto. + * mep-tdep.c (mep_return_value): Ditto. + * mips-tdep.c (mips_eabi_return_value): Ditto. + (mips_n32n64_return_value): Ditto. + (mips_o32_return_value): Ditto. + (mips_o64_return_value): Ditto. + * mn10300-tdep.c (mn10300_return_value): Ditto. + * mt-tdep.c (mt_return_value): Ditto. + * ppc-linux-tdep.c (ppc_linux_return_value): Ditto. + * ppc-sysv-tdep.c (ppc_sysv_abi_return_value): Ditto. + (ppc_sysv_abi_broken_return_value): Ditto. + (ppc64_sysv_abi_return_value): Ditto. + * ppc-tdep.h (ppc_sysv_abi_return_value): Ditto. + (ppc_sysv_abi_broken_return_value): Ditto. + (ppc64_sysv_abi_return_value): Ditto. + * ppcnbsd-tdep.c (ppcnbsd_return_value): Ditto. + * rs6000-tdep.c (rs6000_return_value): Ditto. + * s390-tdep.c (s390_return_value): Ditto. + * score-tdep.c (score_return_value): Ditto. + * sh-tdep.c (sh_return_value_nofpu): Ditto. + (sh_return_value_fpu): Ditto. + * sh64-tdep.c (sh64_return_value): Ditto. + * sparc-tdep.c (sparc32_return_value): Ditto. + * sparc64-tdep.c (sparc64_return_value): Ditto. + * spu-tdep.c (spu_return_value): Ditto. + * v850-tdep.c (v850_return_value): Ditto. + * vax-tdep.c (vax_return_value): Ditto. + * xstormy16-tdep.c (xstormy16_return_value): Ditto. + * xtensa-tdep.c (xtensa_return_value): Ditto. + + * gdbtypes.h (struct type): Add calling_convention member. + * dwarf2read.c (read_subroutine_type): Add calling convention read + from DW_AT_calling_convention attribute to function type. + 2008-04-22 Markus Deuling <deuling@de.ibm.com> * eval.c (evaluate_subexp_standard): Use value_subscripted_rvalue for @@ -3,6 +3,13 @@ *** Changes since GDB 6.8 +* GDB now supports multiple function calling conventions according to the + DWARF-2 DW_AT_calling_convention function attribute. + +* The SH target utilizes the aforementioned change to distinguish between gcc + and Renesas calling convention. It also adds the new CLI commands + `set/show sh calling-convention'. + * GDB can now read compressed debug sections, as produced by GNU gold with the --compress-debug-sections=zlib flag. diff --git a/gdb/alpha-tdep.c b/gdb/alpha-tdep.c index 6a55700..107b46f 100644 --- a/gdb/alpha-tdep.c +++ b/gdb/alpha-tdep.c @@ -564,9 +564,9 @@ alpha_store_return_value (struct type *valtype, struct regcache *regcache, } static enum return_value_convention -alpha_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +alpha_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { enum type_code code = TYPE_CODE (type); diff --git a/gdb/amd64-tdep.c b/gdb/amd64-tdep.c index 891a425..a9a29b3 100644 --- a/gdb/amd64-tdep.c +++ b/gdb/amd64-tdep.c @@ -392,8 +392,8 @@ amd64_classify (struct type *type, enum amd64_reg_class class[2]) } static enum return_value_convention -amd64_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, +amd64_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { enum amd64_reg_class class[2]; diff --git a/gdb/arm-tdep.c b/gdb/arm-tdep.c index 1cac2fb..48901c0 100644 --- a/gdb/arm-tdep.c +++ b/gdb/arm-tdep.c @@ -2373,9 +2373,9 @@ arm_store_return_value (struct type *type, struct regcache *regs, /* Handle function return values. */ static enum return_value_convention -arm_return_value (struct gdbarch *gdbarch, struct type *valtype, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +arm_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); diff --git a/gdb/avr-tdep.c b/gdb/avr-tdep.c index 46c6258..f2a69f4 100644 --- a/gdb/avr-tdep.c +++ b/gdb/avr-tdep.c @@ -834,9 +834,9 @@ avr_extract_return_value (struct type *type, struct regcache *regcache, 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) +avr_return_value (struct gdbarch *gdbarch, struct type *func_type, + 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 diff --git a/gdb/cris-tdep.c b/gdb/cris-tdep.c index b95a9d9..c26dfb5 100644 --- a/gdb/cris-tdep.c +++ b/gdb/cris-tdep.c @@ -1924,9 +1924,9 @@ cris_extract_return_value (struct type *type, struct regcache *regcache, /* Handle the CRIS return value convention. */ static enum return_value_convention -cris_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +cris_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { if (TYPE_CODE (type) == TYPE_CODE_STRUCT || TYPE_CODE (type) == TYPE_CODE_UNION diff --git a/gdb/doc/ChangeLog b/gdb/doc/ChangeLog index 152bbf3..fa94e40 100644 --- a/gdb/doc/ChangeLog +++ b/gdb/doc/ChangeLog @@ -1,3 +1,8 @@ +2008-04-22 Corinna Vinschen <vinschen@redhat.com> + + * gdb.texinfo (Set SH Calling convention): New @item. + (Show SH Calling convention): Ditto. + 2008-04-22 Markus Deuling <deuling@de.ibm.com> * gdb.texinfo (Fortran Operators): Describe '%' operator. diff --git a/gdb/doc/gdb.texinfo b/gdb/doc/gdb.texinfo index 4f77c9d..6337790 100644 --- a/gdb/doc/gdb.texinfo +++ b/gdb/doc/gdb.texinfo @@ -15655,6 +15655,24 @@ commands: @item regs @kindex regs@r{, Super-H} Show the values of all Super-H registers. + +@item set sh calling-convention @var{convention} +@kindex set sh calling-convention +Set the calling-convention used when calling functions from @value{GDBN}. +Allowed values are @samp{gcc}, which is the default setting, and @samp{renesas}. +With the @samp{gcc} setting, functions are called using the @value{NGCC} calling +convention. If the DWARF-2 information of the called function specifies +that the function follows the Renesas calling convention, the function +is called using the Renesas calling convention. If the calling convention +is set to @samp{renesas}, the Renesas calling convention is always used, +regardless of the DWARF-2 information. This can be used to override the +default of @samp{gcc} if debug information is missing, or the compiler +does not emit the DWARF-2 calling convention entry for a function. + +@item show sh calling-convention +@kindex show sh calling-convention +Show the current calling convention setting. + @end table diff --git a/gdb/dwarf2read.c b/gdb/dwarf2read.c index 468ac87..dab4290 100644 --- a/gdb/dwarf2read.c +++ b/gdb/dwarf2read.c @@ -4941,6 +4941,12 @@ read_subroutine_type (struct die_info *die, struct dwarf2_cu *cu) || cu->language == language_pascal) TYPE_FLAGS (ftype) |= TYPE_FLAG_PROTOTYPED; + /* Store the calling convention in the type if it's available in + the subroutine die. Otherwise set the calling convention to + the default value DW_CC_normal. */ + attr = dwarf2_attr (die, DW_AT_calling_convention, cu); + TYPE_CALLING_CONVENTION (ftype) = attr ? DW_UNSND (attr) : DW_CC_normal; + if (die->child != NULL) { struct die_info *child_die; @@ -918,26 +918,27 @@ evaluate_subexp_standard (struct type *expect_type, { struct block *b; CORE_ADDR funaddr; - struct type *value_type; + struct type *val_type; - funaddr = find_function_addr (method, &value_type); + funaddr = find_function_addr (method, &val_type); b = block_for_pc (funaddr); - CHECK_TYPEDEF (value_type); + CHECK_TYPEDEF (val_type); - if ((value_type == NULL) - || (TYPE_CODE(value_type) == TYPE_CODE_ERROR)) + if ((val_type == NULL) + || (TYPE_CODE(val_type) == TYPE_CODE_ERROR)) { if (expect_type != NULL) - value_type = expect_type; + val_type = expect_type; } - struct_return = using_struct_return (value_type); + struct_return = using_struct_return (value_type (method), val_type); } else if (expect_type != NULL) { - struct_return = using_struct_return (check_typedef (expect_type)); + struct_return = using_struct_return (NULL, + check_typedef (expect_type)); } /* Found a function symbol. Now we will substitute its diff --git a/gdb/frv-tdep.c b/gdb/frv-tdep.c index 1611d22..a6bbf03 100644 --- a/gdb/frv-tdep.c +++ b/gdb/frv-tdep.c @@ -1248,9 +1248,9 @@ frv_store_return_value (struct type *type, struct regcache *regcache, } enum return_value_convention -frv_return_value (struct gdbarch *gdbarch, struct type *valtype, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +frv_return_value (struct gdbarch *gdbarch, struct type *func_type, + 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 diff --git a/gdb/gdbarch.c b/gdb/gdbarch.c index 613064c..f63dcdc 100644 --- a/gdb/gdbarch.c +++ b/gdb/gdbarch.c @@ -2041,13 +2041,13 @@ gdbarch_return_value_p (struct gdbarch *gdbarch) } enum return_value_convention -gdbarch_return_value (struct gdbarch *gdbarch, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) +gdbarch_return_value (struct gdbarch *gdbarch, struct type *functype, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { gdb_assert (gdbarch != NULL); gdb_assert (gdbarch->return_value != NULL); if (gdbarch_debug >= 2) fprintf_unfiltered (gdb_stdlog, "gdbarch_return_value called\n"); - return gdbarch->return_value (gdbarch, valtype, regcache, readbuf, writebuf); + return gdbarch->return_value (gdbarch, functype, valtype, regcache, readbuf, writebuf); } void diff --git a/gdb/gdbarch.h b/gdb/gdbarch.h index 06ac3ce..6b4658e 100644 --- a/gdb/gdbarch.h +++ b/gdb/gdbarch.h @@ -366,8 +366,8 @@ extern void set_gdbarch_integer_to_address (struct gdbarch *gdbarch, gdbarch_int extern int gdbarch_return_value_p (struct gdbarch *gdbarch); -typedef enum return_value_convention (gdbarch_return_value_ftype) (struct gdbarch *gdbarch, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf); -extern enum return_value_convention gdbarch_return_value (struct gdbarch *gdbarch, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf); +typedef enum return_value_convention (gdbarch_return_value_ftype) (struct gdbarch *gdbarch, struct type *functype, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf); +extern enum return_value_convention gdbarch_return_value (struct gdbarch *gdbarch, struct type *functype, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf); extern void set_gdbarch_return_value (struct gdbarch *gdbarch, gdbarch_return_value_ftype *return_value); typedef CORE_ADDR (gdbarch_skip_prologue_ftype) (struct gdbarch *gdbarch, CORE_ADDR ip); diff --git a/gdb/gdbarch.sh b/gdb/gdbarch.sh index 5e91d6e..f9fee17 100755 --- a/gdb/gdbarch.sh +++ b/gdb/gdbarch.sh @@ -474,7 +474,7 @@ M:CORE_ADDR:integer_to_address:struct type *type, const gdb_byte *buf:type, buf # should take the type/value of the function to be called and not the # return type. This is left as an exercise for the reader. -M:enum return_value_convention:return_value:struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf:valtype, regcache, readbuf, writebuf +M:enum return_value_convention:return_value:struct type *functype, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf:functype, valtype, regcache, readbuf, writebuf m:CORE_ADDR:skip_prologue:CORE_ADDR ip:ip:0:0 f:int:inner_than:CORE_ADDR lhs, CORE_ADDR rhs:lhs, rhs:0:0 diff --git a/gdb/gdbtypes.h b/gdb/gdbtypes.h index f829cc7..b33ba25 100644 --- a/gdb/gdbtypes.h +++ b/gdb/gdbtypes.h @@ -481,6 +481,11 @@ struct main_type targets and the second is for little endian targets. */ const struct floatformat **floatformat; + + /* For TYPE_CODE_FUNC types, the calling convention for targets + supporting multiple ABIs. Right now this is only fetched from + the Dwarf-2 DW_AT_calling_convention attribute. */ + unsigned calling_convention; } type_specific; }; @@ -812,6 +817,7 @@ extern void allocate_cplus_struct_type (struct type *); #define TYPE_TYPE_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific #define TYPE_CPLUS_SPECIFIC(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.cplus_stuff #define TYPE_FLOATFORMAT(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.floatformat +#define TYPE_CALLING_CONVENTION(thistype) TYPE_MAIN_TYPE(thistype)->type_specific.calling_convention #define TYPE_BASECLASS(thistype,index) TYPE_MAIN_TYPE(thistype)->fields[index].type #define TYPE_N_BASECLASSES(thistype) TYPE_CPLUS_SPECIFIC(thistype)->n_baseclasses #define TYPE_BASECLASS_NAME(thistype,index) TYPE_MAIN_TYPE(thistype)->fields[index].name diff --git a/gdb/h8300-tdep.c b/gdb/h8300-tdep.c index 0e3d0df..77e0e93 100644 --- a/gdb/h8300-tdep.c +++ b/gdb/h8300-tdep.c @@ -909,8 +909,8 @@ h8300h_store_return_value (struct type *type, struct regcache *regcache, } static enum return_value_convention -h8300_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, +h8300_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { if (h8300_use_struct_convention (type)) @@ -923,8 +923,8 @@ h8300_return_value (struct gdbarch *gdbarch, struct type *type, } static enum return_value_convention -h8300h_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, +h8300h_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { if (h8300h_use_struct_convention (type)) diff --git a/gdb/hppa-tdep.c b/gdb/hppa-tdep.c index d91ed95..8d597e2 100644 --- a/gdb/hppa-tdep.c +++ b/gdb/hppa-tdep.c @@ -1105,7 +1105,7 @@ hppa64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* Handle 32/64-bit struct return conventions. */ static enum return_value_convention -hppa32_return_value (struct gdbarch *gdbarch, +hppa32_return_value (struct gdbarch *gdbarch, struct type *func_type, struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { @@ -1145,7 +1145,7 @@ hppa32_return_value (struct gdbarch *gdbarch, } static enum return_value_convention -hppa64_return_value (struct gdbarch *gdbarch, +hppa64_return_value (struct gdbarch *gdbarch, struct type *func_type, struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { diff --git a/gdb/i386-tdep.c b/gdb/i386-tdep.c index 9215a52..ee7ed51 100644 --- a/gdb/i386-tdep.c +++ b/gdb/i386-tdep.c @@ -1560,9 +1560,9 @@ i386_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type) from WRITEBUF into REGCACHE. */ static enum return_value_convention -i386_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +i386_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { enum type_code code = TYPE_CODE (type); @@ -1611,7 +1611,8 @@ i386_return_value (struct gdbarch *gdbarch, struct type *type, 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); + return i386_return_value (gdbarch, func_type, type, regcache, + readbuf, writebuf); } if (readbuf) diff --git a/gdb/ia64-tdep.c b/gdb/ia64-tdep.c index 3876c23..37ed4fc 100644 --- a/gdb/ia64-tdep.c +++ b/gdb/ia64-tdep.c @@ -3059,9 +3059,9 @@ ia64_store_return_value (struct type *type, struct regcache *regcache, } static enum return_value_convention -ia64_return_value (struct gdbarch *gdbarch, struct type *valtype, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +ia64_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { int struct_return = ia64_use_struct_convention (valtype); diff --git a/gdb/infcall.c b/gdb/infcall.c index 721b32d..ca4785e 100644 --- a/gdb/infcall.c +++ b/gdb/infcall.c @@ -493,7 +493,7 @@ call_function_by_hand (struct value *function, int nargs, struct value **args) } else { - struct_return = using_struct_return (values_type); + struct_return = using_struct_return (value_type (function), values_type); target_values_type = values_type; } @@ -852,15 +852,15 @@ the function call)."), name); } else { - switch (gdbarch_return_value (gdbarch, target_values_type, - NULL, NULL, NULL)) + switch (gdbarch_return_value (gdbarch, value_type (function), + target_values_type, NULL, NULL, NULL)) { case RETURN_VALUE_REGISTER_CONVENTION: case RETURN_VALUE_ABI_RETURNS_ADDRESS: case RETURN_VALUE_ABI_PRESERVES_ADDRESS: retval = allocate_value (values_type); - gdbarch_return_value (gdbarch, values_type, retbuf, - value_contents_raw (retval), NULL); + gdbarch_return_value (gdbarch, value_type (function), values_type, + retbuf, value_contents_raw (retval), NULL); break; case RETURN_VALUE_STRUCT_CONVENTION: retval = value_at (values_type, struct_addr); diff --git a/gdb/infcmd.c b/gdb/infcmd.c index 2c30b7e..22a4abb 100644 --- a/gdb/infcmd.c +++ b/gdb/infcmd.c @@ -69,7 +69,8 @@ void interrupt_target_command (char *args, int from_tty); static void nofp_registers_info (char *, int); -static void print_return_value (struct type *value_type); +static void print_return_value (struct type *func_type, + struct type *value_type); static void finish_command_continuation (struct continuation_arg *); @@ -1183,7 +1184,7 @@ advance_command (char *arg, int from_tty) /* Print the result of a function at the end of a 'finish' command. */ static void -print_return_value (struct type *value_type) +print_return_value (struct type *func_type, struct type *value_type) { struct gdbarch *gdbarch = current_gdbarch; struct cleanup *old_chain; @@ -1200,13 +1201,14 @@ print_return_value (struct type *value_type) inferior function call code. In fact, when inferior function calls are made async, this will likely be made the norm. */ - switch (gdbarch_return_value (gdbarch, value_type, NULL, NULL, NULL)) + switch (gdbarch_return_value (gdbarch, func_type, value_type, + NULL, NULL, NULL)) { case RETURN_VALUE_REGISTER_CONVENTION: case RETURN_VALUE_ABI_RETURNS_ADDRESS: case RETURN_VALUE_ABI_PRESERVES_ADDRESS: value = allocate_value (value_type); - gdbarch_return_value (gdbarch, value_type, stop_registers, + gdbarch_return_value (gdbarch, func_type, value_type, stop_registers, value_contents_raw (value), NULL); break; case RETURN_VALUE_STRUCT_CONVENTION: @@ -1270,7 +1272,7 @@ finish_command_continuation (struct continuation_arg *arg) _("finish_command: function has no target type")); if (TYPE_CODE (value_type) != TYPE_CODE_VOID) - print_return_value (value_type); + print_return_value (SYMBOL_TYPE (function), value_type); } do_exec_cleanups (cleanups); @@ -1384,7 +1386,7 @@ finish_command (char *arg, int from_tty) _("finish_command: function has no target type")); if (TYPE_CODE (value_type) != TYPE_CODE_VOID) - print_return_value (value_type); + print_return_value (SYMBOL_TYPE (function), value_type); } do_cleanups (old_chain); diff --git a/gdb/iq2000-tdep.c b/gdb/iq2000-tdep.c index e5b558e..d938fe7 100644 --- a/gdb/iq2000-tdep.c +++ b/gdb/iq2000-tdep.c @@ -591,8 +591,8 @@ iq2000_extract_return_value (struct type *type, struct regcache *regcache, } static enum return_value_convention -iq2000_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, +iq2000_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { if (iq2000_use_struct_convention (type)) diff --git a/gdb/m32c-tdep.c b/gdb/m32c-tdep.c index 7302a7f..fa7b465 100644 --- a/gdb/m32c-tdep.c +++ b/gdb/m32c-tdep.c @@ -2198,6 +2198,7 @@ m32c_return_by_passed_buf (struct type *type) static enum return_value_convention m32c_return_value (struct gdbarch *gdbarch, + struct type *func_type, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, diff --git a/gdb/m32r-tdep.c b/gdb/m32r-tdep.c index 8085b86..964ae38 100644 --- a/gdb/m32r-tdep.c +++ b/gdb/m32r-tdep.c @@ -786,9 +786,9 @@ m32r_extract_return_value (struct type *type, struct regcache *regcache, } enum return_value_convention -m32r_return_value (struct gdbarch *gdbarch, struct type *valtype, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +m32r_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { if (TYPE_LENGTH (valtype) > 8) return RETURN_VALUE_STRUCT_CONVENTION; diff --git a/gdb/m68hc11-tdep.c b/gdb/m68hc11-tdep.c index 1504bf3..f765d44 100644 --- a/gdb/m68hc11-tdep.c +++ b/gdb/m68hc11-tdep.c @@ -1311,9 +1311,9 @@ m68hc11_extract_return_value (struct type *type, struct regcache *regcache, } enum return_value_convention -m68hc11_return_value (struct gdbarch *gdbarch, struct type *valtype, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +m68hc11_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { if (TYPE_CODE (valtype) == TYPE_CODE_STRUCT || TYPE_CODE (valtype) == TYPE_CODE_UNION diff --git a/gdb/m68k-tdep.c b/gdb/m68k-tdep.c index bfb1af9..35ad4ca 100644 --- a/gdb/m68k-tdep.c +++ b/gdb/m68k-tdep.c @@ -372,9 +372,9 @@ m68k_reg_struct_return_p (struct gdbarch *gdbarch, struct type *type) from WRITEBUF into REGCACHE. */ static enum return_value_convention -m68k_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +m68k_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { enum type_code code = TYPE_CODE (type); @@ -407,9 +407,9 @@ m68k_return_value (struct gdbarch *gdbarch, struct type *type, } static enum return_value_convention -m68k_svr4_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +m68k_svr4_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { enum type_code code = TYPE_CODE (type); @@ -446,7 +446,7 @@ m68k_svr4_return_value (struct gdbarch *gdbarch, struct type *type, if (code == TYPE_CODE_STRUCT && TYPE_NFIELDS (type) == 1) { type = check_typedef (TYPE_FIELD_TYPE (type, 0)); - return m68k_svr4_return_value (gdbarch, type, regcache, + return m68k_svr4_return_value (gdbarch, func_type, type, regcache, readbuf, writebuf); } diff --git a/gdb/m88k-tdep.c b/gdb/m88k-tdep.c index 9b71779..1b9f312 100644 --- a/gdb/m88k-tdep.c +++ b/gdb/m88k-tdep.c @@ -381,9 +381,9 @@ m88k_unwind_dummy_id (struct gdbarch *arch, struct frame_info *next_frame) from WRITEBUF into REGCACHE. */ static enum return_value_convention -m88k_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +m88k_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); gdb_byte buf[8]; diff --git a/gdb/mep-tdep.c b/gdb/mep-tdep.c index 57f2415..6079236 100644 --- a/gdb/mep-tdep.c +++ b/gdb/mep-tdep.c @@ -2195,9 +2195,9 @@ mep_store_return_value (struct gdbarch *arch, } enum return_value_convention -mep_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +mep_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { if (mep_use_struct_convention (type)) { diff --git a/gdb/mips-tdep.c b/gdb/mips-tdep.c index 3722120..ebb216f 100644 --- a/gdb/mips-tdep.c +++ b/gdb/mips-tdep.c @@ -2955,7 +2955,7 @@ mips_eabi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, /* Determine the return value convention being used. */ static enum return_value_convention -mips_eabi_return_value (struct gdbarch *gdbarch, +mips_eabi_return_value (struct gdbarch *gdbarch, struct type *func_type, struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { @@ -3265,7 +3265,7 @@ mips_n32n64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } static enum return_value_convention -mips_n32n64_return_value (struct gdbarch *gdbarch, +mips_n32n64_return_value (struct gdbarch *gdbarch, struct type *func_type, struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { @@ -3723,8 +3723,8 @@ mips_o32_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } static enum return_value_convention -mips_o32_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, +mips_o32_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); @@ -4112,7 +4112,7 @@ mips_o64_push_dummy_call (struct gdbarch *gdbarch, struct value *function, } static enum return_value_convention -mips_o64_return_value (struct gdbarch *gdbarch, +mips_o64_return_value (struct gdbarch *gdbarch, struct type *func_type, struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { diff --git a/gdb/mn10300-tdep.c b/gdb/mn10300-tdep.c index f043604..db35b5c 100644 --- a/gdb/mn10300-tdep.c +++ b/gdb/mn10300-tdep.c @@ -196,9 +196,9 @@ mn10300_extract_return_value (struct gdbarch *gdbarch, struct type *type, from WRITEBUF into REGCACHE. */ static enum return_value_convention -mn10300_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +mn10300_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { if (mn10300_use_struct_convention (type)) return RETURN_VALUE_STRUCT_CONVENTION; diff --git a/gdb/mt-tdep.c b/gdb/mt-tdep.c index a3098b2..57ff460 100644 --- a/gdb/mt-tdep.c +++ b/gdb/mt-tdep.c @@ -332,9 +332,9 @@ mt_register_reggroup_p (struct gdbarch *gdbarch, int regnum, values. */ static enum return_value_convention -mt_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +mt_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { if (TYPE_LENGTH (type) > 4) { diff --git a/gdb/ppc-linux-tdep.c b/gdb/ppc-linux-tdep.c index d0901de..98a4156 100644 --- a/gdb/ppc-linux-tdep.c +++ b/gdb/ppc-linux-tdep.c @@ -308,9 +308,9 @@ ppc_linux_memory_remove_breakpoint (struct gdbarch *gdbarch, which were added later, do get returned in a register though. */ static enum return_value_convention -ppc_linux_return_value (struct gdbarch *gdbarch, struct type *valtype, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +ppc_linux_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { if ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT || TYPE_CODE (valtype) == TYPE_CODE_UNION) @@ -318,8 +318,8 @@ ppc_linux_return_value (struct gdbarch *gdbarch, struct type *valtype, && TYPE_VECTOR (valtype))) return RETURN_VALUE_STRUCT_CONVENTION; else - return ppc_sysv_abi_return_value (gdbarch, valtype, regcache, readbuf, - writebuf); + return ppc_sysv_abi_return_value (gdbarch, func_type, valtype, regcache, + readbuf, writebuf); } /* Macros for matching instructions. Note that, since all the diff --git a/gdb/ppc-sysv-tdep.c b/gdb/ppc-sysv-tdep.c index eea2287..27627da 100644 --- a/gdb/ppc-sysv-tdep.c +++ b/gdb/ppc-sysv-tdep.c @@ -805,9 +805,9 @@ do_ppc_sysv_return_value (struct gdbarch *gdbarch, struct type *type, } enum return_value_convention -ppc_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +ppc_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { return do_ppc_sysv_return_value (gdbarch, valtype, regcache, readbuf, writebuf, 0); @@ -815,6 +815,7 @@ ppc_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype, enum return_value_convention ppc_sysv_abi_broken_return_value (struct gdbarch *gdbarch, + struct type *func_type, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) @@ -1322,9 +1323,9 @@ ppc64_sysv_abi_push_dummy_call (struct gdbarch *gdbarch, struct value *function, location; when READBUF is non-NULL, fill the buffer from the corresponding register return-value location. */ enum return_value_convention -ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *valtype, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); diff --git a/gdb/ppc-tdep.h b/gdb/ppc-tdep.h index 50805ae..63423c9 100644 --- a/gdb/ppc-tdep.h +++ b/gdb/ppc-tdep.h @@ -29,11 +29,13 @@ struct type; /* From ppc-linux-tdep.c... */ enum return_value_convention ppc_sysv_abi_return_value (struct gdbarch *gdbarch, + struct type *func_type, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf); enum return_value_convention ppc_sysv_abi_broken_return_value (struct gdbarch *gdbarch, + struct type *func_type, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, @@ -60,6 +62,7 @@ const struct regset *ppc_linux_gregset (int); const struct regset *ppc_linux_fpregset (void); enum return_value_convention ppc64_sysv_abi_return_value (struct gdbarch *gdbarch, + struct type *func_type, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, diff --git a/gdb/ppcnbsd-tdep.c b/gdb/ppcnbsd-tdep.c index 2fed4ea..0d4ad6b 100644 --- a/gdb/ppcnbsd-tdep.c +++ b/gdb/ppcnbsd-tdep.c @@ -77,9 +77,9 @@ ppcnbsd_regset_from_core_section (struct gdbarch *gdbarch, the moment use the broken convention. Ulgh!. */ static enum return_value_convention -ppcnbsd_return_value (struct gdbarch *gdbarch, struct type *valtype, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +ppcnbsd_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { #if 0 if ((TYPE_CODE (valtype) == TYPE_CODE_STRUCT @@ -93,8 +93,8 @@ ppcnbsd_return_value (struct gdbarch *gdbarch, struct type *valtype, return RETURN_VALUE_STRUCT_CONVENTION; else #endif - return ppc_sysv_abi_broken_return_value (gdbarch, valtype, regcache, - readbuf, writebuf); + return ppc_sysv_abi_broken_return_value (gdbarch, func_type, valtype, + regcache, readbuf, writebuf); } diff --git a/gdb/rs6000-tdep.c b/gdb/rs6000-tdep.c index 50dbf2b..00a7d7e 100644 --- a/gdb/rs6000-tdep.c +++ b/gdb/rs6000-tdep.c @@ -2095,9 +2095,9 @@ ran_out_of_registers_for_arguments: } static enum return_value_convention -rs6000_return_value (struct gdbarch *gdbarch, struct type *valtype, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +rs6000_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *valtype, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { struct gdbarch_tdep *tdep = gdbarch_tdep (gdbarch); gdb_byte buf[8]; diff --git a/gdb/s390-tdep.c b/gdb/s390-tdep.c index bfcb247..c073d73 100644 --- a/gdb/s390-tdep.c +++ b/gdb/s390-tdep.c @@ -2175,9 +2175,9 @@ s390_return_value_convention (struct gdbarch *gdbarch, struct type *type) } static enum return_value_convention -s390_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *out, - const gdb_byte *in) +s390_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *out, const gdb_byte *in) { int word_size = gdbarch_ptr_bit (gdbarch) / 8; int length = TYPE_LENGTH (type); diff --git a/gdb/score-tdep.c b/gdb/score-tdep.c index 4ef6200..709e0fa 100644 --- a/gdb/score-tdep.c +++ b/gdb/score-tdep.c @@ -414,8 +414,8 @@ score_xfer_register (struct regcache *regcache, int regnum, int length, } static enum return_value_convention -score_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, +score_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, gdb_byte * readbuf, const gdb_byte * writebuf) { if (TYPE_CODE (type) == TYPE_CODE_STRUCT diff --git a/gdb/sh-tdep.c b/gdb/sh-tdep.c index 6aeb0e8..58a142a 100644 --- a/gdb/sh-tdep.c +++ b/gdb/sh-tdep.c @@ -51,9 +51,24 @@ /* sh flags */ #include "elf/sh.h" +#include "elf/dwarf2.h" /* registers numbers shared with the simulator */ #include "gdb/sim-sh.h" +/* List of "set sh ..." and "show sh ..." commands. */ +static struct cmd_list_element *setshcmdlist = NULL; +static struct cmd_list_element *showshcmdlist = NULL; + +static const char sh_cc_gcc[] = "gcc"; +static const char sh_cc_renesas[] = "renesas"; +static const char *sh_cc_enum[] = { + sh_cc_gcc, + sh_cc_renesas, + NULL +}; + +static const char *sh_active_calling_convention = sh_cc_gcc; + static void (*sh_show_regs) (struct frame_info *); #define SH_NUM_REGS 67 @@ -73,6 +88,14 @@ struct sh_frame_cache CORE_ADDR saved_sp; }; +static int +sh_is_renesas_calling_convention (struct type *func_type) +{ + return ((func_type + && TYPE_CALLING_CONVENTION (func_type) == DW_CC_GNU_renesas_sh) + || sh_active_calling_convention == sh_cc_renesas); +} + static const char * sh_sh_register_name (struct gdbarch *gdbarch, int reg_nr) { @@ -783,11 +806,16 @@ sh_skip_prologue (struct gdbarch *gdbarch, CORE_ADDR start_pc) */ static int -sh_use_struct_convention (int gcc_p, struct type *type) +sh_use_struct_convention (int renesas_abi, struct type *type) { int len = TYPE_LENGTH (type); int nelem = TYPE_NFIELDS (type); + /* The Renesas ABI returns aggregate types always on stack. */ + if (renesas_abi && (TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION)) + return 1; + /* Non-power of 2 length types and types bigger than 8 bytes (which don't fit in two registers anyway) use struct convention. */ if (len != 1 && len != 2 && len != 4 && len != 8) @@ -813,6 +841,15 @@ sh_use_struct_convention (int gcc_p, struct type *type) return 1; } +static int +sh_use_struct_convention_nofpu (int renesas_abi, struct type *type) +{ + /* The Renesas ABI returns long longs/doubles etc. always on stack. */ + if (renesas_abi && TYPE_NFIELDS (type) == 0 && TYPE_LENGTH (type) >= 8) + return 1; + return sh_use_struct_convention (renesas_abi, type); +} + static CORE_ADDR sh_frame_align (struct gdbarch *ignore, CORE_ADDR sp) { @@ -924,7 +961,7 @@ sh_init_flt_argreg (void) 29) the parity of the register number is preserved, which is important for the double register passing test (see the "argreg & 1" test below). */ static int -sh_next_flt_argreg (struct gdbarch *gdbarch, int len) +sh_next_flt_argreg (struct gdbarch *gdbarch, int len, struct type *func_type) { int argreg; @@ -943,7 +980,10 @@ sh_next_flt_argreg (struct gdbarch *gdbarch, int len) /* Doubles are always starting in a even register number. */ if (argreg & 1) { - flt_argreg_array[argreg] = 1; + /* In gcc ABI, the skipped register is lost for further argument + passing now. Not so in Renesas ABI. */ + if (!sh_is_renesas_calling_convention (func_type)) + flt_argreg_array[argreg] = 1; ++argreg; @@ -954,7 +994,8 @@ sh_next_flt_argreg (struct gdbarch *gdbarch, int len) /* Also mark the next register as used. */ flt_argreg_array[argreg + 1] = 1; } - else if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE) + else if (gdbarch_byte_order (gdbarch) == BFD_ENDIAN_LITTLE + && !sh_is_renesas_calling_convention (func_type)) { /* In little endian, gcc passes floats like this: f5, f4, f7, f6, ... */ if (!flt_argreg_array[argreg + 1]) @@ -1026,20 +1067,25 @@ sh_push_dummy_call_fpu (struct gdbarch *gdbarch, int argreg = ARG0_REGNUM; int flt_argreg = 0; int argnum; + struct type *func_type = value_type (function); struct type *type; CORE_ADDR regval; char *val; int len, reg_size = 0; int pass_on_stack = 0; int treat_as_flt; + int last_reg_arg = INT_MAX; + + /* The Renesas ABI expects all varargs arguments, plus the last + non-vararg argument to be on the stack, no matter how many + registers have been used so far. */ + if (sh_is_renesas_calling_convention (func_type) + && (TYPE_FLAGS (func_type) & TYPE_FLAG_VARARGS)) + last_reg_arg = TYPE_NFIELDS (func_type) - 2; /* first force sp to a 4-byte alignment */ sp = sh_frame_align (gdbarch, sp); - if (struct_return) - regcache_cooked_write_unsigned (regcache, - STRUCT_RETURN_REGNUM, struct_addr); - /* make room on stack for args */ sp -= sh_stack_allocsize (nargs, args); @@ -1062,7 +1108,14 @@ sh_push_dummy_call_fpu (struct gdbarch *gdbarch, /* Find out the next register to use for a floating point value. */ treat_as_flt = sh_treat_as_flt_p (type); if (treat_as_flt) - flt_argreg = sh_next_flt_argreg (gdbarch, len); + flt_argreg = sh_next_flt_argreg (gdbarch, len, func_type); + /* In Renesas ABI, long longs and aggregate types are always passed + on stack. */ + else if (sh_is_renesas_calling_convention (func_type) + && ((TYPE_CODE (type) == TYPE_CODE_INT && len == 8) + || TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION)) + pass_on_stack = 1; /* In contrast to non-FPU CPUs, arguments are never split between registers and stack. If an argument doesn't fit in the remaining registers it's always pushed entirely on the stack. */ @@ -1073,7 +1126,8 @@ sh_push_dummy_call_fpu (struct gdbarch *gdbarch, { if ((treat_as_flt && flt_argreg > FLOAT_ARGLAST_REGNUM) || (!treat_as_flt && (argreg > ARGLAST_REGNUM - || pass_on_stack))) + || pass_on_stack)) + || argnum > last_reg_arg) { /* The data goes entirely on the stack, 4-byte aligned. */ reg_size = (len + 3) & ~3; @@ -1116,6 +1170,19 @@ sh_push_dummy_call_fpu (struct gdbarch *gdbarch, } } + if (struct_return) + { + if (sh_is_renesas_calling_convention (func_type)) + /* If the function uses the Renesas ABI, subtract another 4 bytes from + the stack and store the struct return address there. */ + write_memory_unsigned_integer (sp -= 4, 4, struct_addr); + else + /* Using the gcc ABI, the "struct return pointer" pseudo-argument has + its own dedicated register. */ + regcache_cooked_write_unsigned (regcache, + STRUCT_RETURN_REGNUM, struct_addr); + } + /* Store return address. */ regcache_cooked_write_unsigned (regcache, PR_REGNUM, bp_addr); @@ -1138,18 +1205,24 @@ sh_push_dummy_call_nofpu (struct gdbarch *gdbarch, int stack_offset = 0; int argreg = ARG0_REGNUM; int argnum; + struct type *func_type = value_type (function); struct type *type; CORE_ADDR regval; char *val; - int len, reg_size; + int len, reg_size = 0; + int pass_on_stack = 0; + int last_reg_arg = INT_MAX; + + /* The Renesas ABI expects all varargs arguments, plus the last + non-vararg argument to be on the stack, no matter how many + registers have been used so far. */ + if (sh_is_renesas_calling_convention (func_type) + && (TYPE_FLAGS (func_type) & TYPE_FLAG_VARARGS)) + last_reg_arg = TYPE_NFIELDS (func_type) - 2; /* first force sp to a 4-byte alignment */ sp = sh_frame_align (gdbarch, sp); - if (struct_return) - regcache_cooked_write_unsigned (regcache, - STRUCT_RETURN_REGNUM, struct_addr); - /* make room on stack for args */ sp -= sh_stack_allocsize (nargs, args); @@ -1162,9 +1235,21 @@ sh_push_dummy_call_nofpu (struct gdbarch *gdbarch, len = TYPE_LENGTH (type); val = sh_justify_value_in_reg (gdbarch, args[argnum], len); + /* Some decisions have to be made how various types are handled. + This also differs in different ABIs. */ + pass_on_stack = 0; + /* Renesas ABI pushes doubles and long longs entirely on stack. + Same goes for aggregate types. */ + if (sh_is_renesas_calling_convention (func_type) + && ((TYPE_CODE (type) == TYPE_CODE_INT && len >= 8) + || (TYPE_CODE (type) == TYPE_CODE_FLT && len >= 8) + || TYPE_CODE (type) == TYPE_CODE_STRUCT + || TYPE_CODE (type) == TYPE_CODE_UNION)) + pass_on_stack = 1; while (len > 0) { - if (argreg > ARGLAST_REGNUM) + if (argreg > ARGLAST_REGNUM || pass_on_stack + || argnum > last_reg_arg) { /* The remainder of the data goes entirely on the stack, 4-byte aligned. */ @@ -1187,6 +1272,19 @@ sh_push_dummy_call_nofpu (struct gdbarch *gdbarch, } } + if (struct_return) + { + if (sh_is_renesas_calling_convention (func_type)) + /* If the function uses the Renesas ABI, subtract another 4 bytes from + the stack and store the struct return address there. */ + write_memory_unsigned_integer (sp -= 4, 4, struct_addr); + else + /* Using the gcc ABI, the "struct return pointer" pseudo-argument has + its own dedicated register. */ + regcache_cooked_write_unsigned (regcache, + STRUCT_RETURN_REGNUM, struct_addr); + } + /* Store return address. */ regcache_cooked_write_unsigned (regcache, PR_REGNUM, bp_addr); @@ -1292,11 +1390,12 @@ sh_store_return_value_fpu (struct type *type, struct regcache *regcache, } static enum return_value_convention -sh_return_value_nofpu (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, +sh_return_value_nofpu (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { - if (sh_use_struct_convention (0, type)) + if (sh_use_struct_convention_nofpu ( + sh_is_renesas_calling_convention (func_type), type)) return RETURN_VALUE_STRUCT_CONVENTION; if (writebuf) sh_store_return_value_nofpu (type, regcache, writebuf); @@ -1306,11 +1405,12 @@ sh_return_value_nofpu (struct gdbarch *gdbarch, struct type *type, } static enum return_value_convention -sh_return_value_fpu (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, +sh_return_value_fpu (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { - if (sh_use_struct_convention (0, type)) + if (sh_use_struct_convention ( + sh_is_renesas_calling_convention (func_type), type)) return RETURN_VALUE_STRUCT_CONVENTION; if (writebuf) sh_store_return_value_fpu (type, regcache, writebuf); @@ -2879,6 +2979,20 @@ sh_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) return gdbarch; } +static void +show_sh_command (char *args, int from_tty) +{ + help_list (showshcmdlist, "show sh ", all_commands, gdb_stdout); +} + +static void +set_sh_command (char *args, int from_tty) +{ + printf_unfiltered + ("\"set sh\" must be followed by an appropriate subcommand.\n"); + help_list (setshcmdlist, "set sh ", all_commands, gdb_stdout); +} + extern initialize_file_ftype _initialize_sh_tdep; /* -Wmissing-prototypes */ void @@ -2889,4 +3003,20 @@ _initialize_sh_tdep (void) gdbarch_register (bfd_arch_sh, sh_gdbarch_init, NULL); add_com ("regs", class_vars, sh_show_regs_command, _("Print all registers")); + + add_prefix_cmd ("sh", no_class, set_sh_command, "SH specific commands.", + &setshcmdlist, "set sh ", 0, &setlist); + add_prefix_cmd ("sh", no_class, show_sh_command, "SH specific commands.", + &showshcmdlist, "show sh ", 0, &showlist); + + add_setshow_enum_cmd ("calling-convention", class_vars, sh_cc_enum, + &sh_active_calling_convention, + _("Set calling convention used when calling target " + "functions from GDB."), + _("Show calling convention used when calling target " + "functions from GDB."), + _("gcc - Use GCC calling convention (default).\n" + "renesas - Enforce Renesas calling convention."), + NULL, NULL, + &setshcmdlist, &showshcmdlist); } diff --git a/gdb/sh64-tdep.c b/gdb/sh64-tdep.c index d4d93d6..10e6099 100644 --- a/gdb/sh64-tdep.c +++ b/gdb/sh64-tdep.c @@ -1301,8 +1301,8 @@ sh64_store_return_value (struct type *type, struct regcache *regcache, } static enum return_value_convention -sh64_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, +sh64_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { if (sh64_use_struct_convention (type)) diff --git a/gdb/sparc-tdep.c b/gdb/sparc-tdep.c index 4d690ef..0140c0f 100644 --- a/gdb/sparc-tdep.c +++ b/gdb/sparc-tdep.c @@ -388,7 +388,8 @@ sparc32_push_dummy_code (struct gdbarch *gdbarch, CORE_ADDR sp, *bp_addr = sp - 4; *real_pc = funcaddr; - if (using_struct_return (value_type)) + if (using_struct_return (SYMBOL_TYPE (find_pc_function (funcaddr)), + value_type)) { gdb_byte buf[4]; @@ -1148,9 +1149,9 @@ sparc32_store_return_value (struct type *type, struct regcache *regcache, } static enum return_value_convention -sparc32_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +sparc32_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { /* The psABI says that "...every stack frame reserves the word at %fp+64. If a function returns a structure, union, or diff --git a/gdb/sparc64-tdep.c b/gdb/sparc64-tdep.c index 371d02e..36565b2 100644 --- a/gdb/sparc64-tdep.c +++ b/gdb/sparc64-tdep.c @@ -1067,9 +1067,9 @@ sparc64_store_return_value (struct type *type, struct regcache *regcache, } static enum return_value_convention -sparc64_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +sparc64_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *readbuf, const gdb_byte *writebuf) { if (TYPE_LENGTH (type) > 32) return RETURN_VALUE_STRUCT_CONVENTION; diff --git a/gdb/spu-tdep.c b/gdb/spu-tdep.c index 882b613..fef42e6 100644 --- a/gdb/spu-tdep.c +++ b/gdb/spu-tdep.c @@ -1204,8 +1204,9 @@ spu_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) /* Function return value access. */ static enum return_value_convention -spu_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *out, const gdb_byte *in) +spu_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, + gdb_byte *out, const gdb_byte *in) { enum return_value_convention rvc; diff --git a/gdb/stack.c b/gdb/stack.c index 374848b..414a59a 100644 --- a/gdb/stack.c +++ b/gdb/stack.c @@ -1834,7 +1834,7 @@ return_command (char *retval_exp, int from_tty) is discarded, side effects such as "return i++" still occur. */ return_value = NULL; - else if (using_struct_return (return_type)) + else if (using_struct_return (SYMBOL_TYPE (thisfun), return_type)) { query_prefix = "\ The location at which to store the function's return value is unknown.\n\ @@ -1888,9 +1888,10 @@ If you continue, the return value that you specified will be ignored.\n"; { struct type *return_type = value_type (return_value); struct gdbarch *gdbarch = get_regcache_arch (get_current_regcache ()); - gdb_assert (gdbarch_return_value (gdbarch, return_type, NULL, NULL, NULL) + gdb_assert (gdbarch_return_value (gdbarch, SYMBOL_TYPE (thisfun), + return_type, NULL, NULL, NULL) == RETURN_VALUE_REGISTER_CONVENTION); - gdbarch_return_value (gdbarch, return_type, + gdbarch_return_value (gdbarch, SYMBOL_TYPE (thisfun), return_type, get_current_regcache (), NULL /*read*/, value_contents (return_value) /*write*/); } diff --git a/gdb/v850-tdep.c b/gdb/v850-tdep.c index 2891d1a..5349329 100644 --- a/gdb/v850-tdep.c +++ b/gdb/v850-tdep.c @@ -790,8 +790,8 @@ v850_store_return_value (struct type *type, struct regcache *regcache, } static enum return_value_convention -v850_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, +v850_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { if (v850_use_struct_convention (type)) diff --git a/gdb/value.c b/gdb/value.c index e620550..2cb989d 100644 --- a/gdb/value.c +++ b/gdb/value.c @@ -1705,7 +1705,7 @@ coerce_enum (struct value *arg) address as a hidden first parameter). */ int -using_struct_return (struct type *value_type) +using_struct_return (struct type *func_type, struct type *value_type) { enum type_code code = TYPE_CODE (value_type); @@ -1718,7 +1718,7 @@ using_struct_return (struct type *value_type) return 0; /* Probe the architecture for the return-value convention. */ - return (gdbarch_return_value (current_gdbarch, value_type, + return (gdbarch_return_value (current_gdbarch, func_type, value_type, NULL, NULL, NULL) != RETURN_VALUE_REGISTER_CONVENTION); } diff --git a/gdb/value.h b/gdb/value.h index 55eb253..731b6be 100644 --- a/gdb/value.h +++ b/gdb/value.h @@ -410,7 +410,8 @@ extern struct value *value_in (struct value *element, struct value *set); extern int value_bit_index (struct type *type, const gdb_byte *addr, int index); -extern int using_struct_return (struct type *value_type); +extern int using_struct_return (struct type *func_type, + struct type *value_type); extern struct value *evaluate_expression (struct expression *exp); diff --git a/gdb/vax-tdep.c b/gdb/vax-tdep.c index cd39645..4daf95d 100644 --- a/gdb/vax-tdep.c +++ b/gdb/vax-tdep.c @@ -201,9 +201,9 @@ vax_unwind_dummy_id (struct gdbarch *gdbarch, struct frame_info *next_frame) static enum return_value_convention -vax_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, gdb_byte *readbuf, - const gdb_byte *writebuf) +vax_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); gdb_byte buf[8]; diff --git a/gdb/xstormy16-tdep.c b/gdb/xstormy16-tdep.c index 78173cf..d21e15d 100644 --- a/gdb/xstormy16-tdep.c +++ b/gdb/xstormy16-tdep.c @@ -198,8 +198,8 @@ xstormy16_store_return_value (struct type *type, struct regcache *regcache, } static enum return_value_convention -xstormy16_return_value (struct gdbarch *gdbarch, struct type *type, - struct regcache *regcache, +xstormy16_return_value (struct gdbarch *gdbarch, struct type *func_type, + struct type *type, struct regcache *regcache, gdb_byte *readbuf, const gdb_byte *writebuf) { if (xstormy16_use_struct_convention (type)) diff --git a/gdb/xtensa-tdep.c b/gdb/xtensa-tdep.c index 16434b4..0ed254f 100644 --- a/gdb/xtensa-tdep.c +++ b/gdb/xtensa-tdep.c @@ -1519,6 +1519,7 @@ xtensa_store_return_value (struct type *type, static enum return_value_convention xtensa_return_value (struct gdbarch *gdbarch, + struct type *func_type, struct type *valtype, struct regcache *regcache, gdb_byte *readbuf, |