diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2008-04-22 11:03:42 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2008-04-22 11:03:42 +0000 |
commit | c055b1010f3ff41e33e30b195f809e05d68af989 (patch) | |
tree | 3cfebc634595897da73d7b53614b948bae1431ed /gdb/sh-tdep.c | |
parent | 9eec4d1e39028b54f54638c90b2c628b958162fe (diff) | |
download | gdb-c055b1010f3ff41e33e30b195f809e05d68af989.zip gdb-c055b1010f3ff41e33e30b195f809e05d68af989.tar.gz gdb-c055b1010f3ff41e33e30b195f809e05d68af989.tar.bz2 |
doc/ChangeLog:
--------------
* gdb.texinfo (Set SH Calling convention): New @item.
(Show SH Calling convention): Ditto.
ChangeLog:
----------
* 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.
Diffstat (limited to 'gdb/sh-tdep.c')
-rw-r--r-- | gdb/sh-tdep.c | 174 |
1 files changed, 152 insertions, 22 deletions
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); } |