aboutsummaryrefslogtreecommitdiff
path: root/gcc/config
diff options
context:
space:
mode:
authordj <dj@138bc75d-0d04-0410-961f-82ee72b054a4>2003-09-04 03:18:05 +0000
committerdj <dj@138bc75d-0d04-0410-961f-82ee72b054a4>2003-09-04 03:18:05 +0000
commit455507905e358525176b45e9c2c49e0d35e79927 (patch)
tree99ad51d803293a4cc8d3ad48596aa725cf1cc596 /gcc/config
parent9d344979cab6242e4366ca8d9c5d924daa9112f5 (diff)
* targhooks.c: New file.
* targhooks.h: New file. * Makefile.in: Add targhooks.o support. (function.o): Depend on$(TARGET_H). (stmt.o): Likewise. (combine.o): Depend on $(TREE_H) and $(TARGET_H). * builtins.c (apply_args_size, expand_builtin_apply_args_1, expand_builtin_apply): Convert to calls.struct_value_rtx hook. (expand_builtin_saveregs): Convert to calls.expand_builtin_saveregs hook. * c-decl.c (start_decl): Handle new calls.promote_prototypes hook here, instead of ... (get_parm_info) ... here. (store_parm_decls_oldstyle): Convert to calls.promote_prototypes hook. (finish_function): Handle calls.promote_prototypes hook here too. * c-typeck.c (convert_arguments): Convert to calls.promote_prototypes hook. (c_convert_parm_for_inlining): Likewise. * calls.c (initialize_argument_information): Convert to calls.promote_function_args hook. (expand_call): Convert to calls.struct_value_rtx, calls.strict_argument_naming, calls.pretend_outgoing_varargs_named, and calls.promote_function_return hooks. Pass fndecl to aggregate_value_p. Initialize CUMULATIVE_ARGS before calling hooks, so they can use that. (emit_library_call_value_1): Likewise. * combine.c (setup_incoming_promotions): Convert to calls.promote_function_args hook. * emit-rtl.c: Convert to calls.struct_value_rtx hook. * expr.c (expand_assignment): Pass call to aggregate_value_p. (expand_expr): Likewise. * expr.h: Remove support for SETUP_INCOMING_VARARGS, STRICT_ARGUMENT_NAMING, PRETEND_OUTGOING_VARARGS_NAMED, RETURN_IN_MEMORY macro defaults. * final.c (profile_function): Convert to calls.struct_value_rtx hook. * function.c (aggregate_value_p): Accept function type tree as second parameter; try to deduce fntype from it. Convert to calls.return_in_memory hook. (assign_parms): Convert to calls.setup_incoming_varargs, calls.strict_argument_naming, calls.promote_function_args, calls.pretend_outgoing_varargs_named hooks. Pass fndecl to aggregate_value_p. (expand_function_start): Likewise. Convert to calls.struct_value_rtx hook. (expand_function_end): Convert to calls.promote_function_return hook. (allocate_struct_function): Pass fndecl to aggregate_value_p. * hard-reg-set.h: Update comments to new hook names. * integrate.c (expand_inline_function): Pass fndecl to aggregate_value_p. * reg-stack.c (stack_result): Likewise. * rtl.h (struct_value_rtx, struct_value_incoming_rtx): Delete. * stmt.c (expand_value_return): Convert to calls.promote_function_return hook. * target-def.h: Add TARGET_PROMOTE_FUNCTION_ARGS, TARGET_PROMOTE_FUNCTION_RETURN, TARGET_PROMOTE_PROTOTYPES, TARGET_STRUCT_VALUE_RTX, TARGET_RETURN_IN_MEMORY, TARGET_EXPAND_BUILTIN_SAVEREGS, TARGET_SETUP_INCOMING_VARARGS, TARGET_STRICT_ARGUMENT_NAMING, TARGET_PRETEND_OUTGOING_VARARGS_NAMED, and TARGET_CALLS. * target.h: Likewise. * tree.h (aggregate_value_p): Also takes a tree to deduce function attributes from (for target hooks). * doc/tm.texi (PROMOTE_FUNCTION_ARGS, PROMOTE_FUNCTION_RETURN, PROMOTE_PROTOTYPES, RETURN_IN_MEMORY, STRUCT_VALUE_REGNUM, STRUCT_VALUE, STRUCT_VALUE_INCOMING_REGNUM, STRUCT_VALUE_INCOMING, EXPAND_BUILTIN_SAVEREGS, SETUP_INCOMING_VARARGS, STRICT_ARGUMENT_NAMING, PRETEND_OUTGOING_VARARGS_NAMED): Convert to hooks. * config/alpha/alpha.c (alpha_output_mi_thunk_osf): Pass function to aggregate_value_p. * config/arm/arm.c (arm_init_cumulative_args, arm_output_mi_thunk): Likewise. * config/i386/i386.c (ix86_return_pops_args, x86_this_parameter): Likewise. * config/mips/mips.c (mips_save_reg_p, mips_expand_prologue, mips_can_use_return_insn): Likewise. * config/rs6000/rs6000.c (rs6000_output_mi_thunk): Likewise. * config/s390/s390.c (s390_output_mi_thunk): Likewise. * config/sparc/sparc.c (sparc_output_mi_thunk): Pass function to aggregate_value_p. * config/story16/stormy16.c (xstormy16_asm_output_mi_thunk): Pass function to aggregate_value_p. * objc/objc-act.c (generate_struct_by_value_array): Pass NULL to aggregate_value_p. * config/sh/sh-protos.h (sh_builtin_saveregs): Remove. (sh_attr_renesas_p, sh_cfun_attr_renesas_p, sh_function_arg, sh_function_arg_advance, sh_pass_in_reg_p): New. * config/sh/sh.c (sh_handle_renesas_attribute, sh_promote_prototypes, sh_struct_value_rtx, sh_return_in_memory, sh_builtin_saveregs, sh_setup_incoming_varargs, sh_strict_argument_naming, sh_pretend_outgoing_varargs_named): New decls. (targetm): Add new hooks. (calc_live_regs): Save MACL and MACH if the function has the renesas attribute. (sh_expand_prologue): Support renesas attribute. (sh_builtin_saveregs): Make static. (sh_build_va_list): Support renesas attribute. (sh_va_start): Likewise. (sh_va_arg): Likewise. (sh_promote_prototypes): New. (sh_function_arg): New, moved from sh.h. Support renesas attribute. (sh_function_arg_advance): Likewise. (sh_return_in_memory): Likewise. (sh_strict_argument_naming): Likewise. (sh_pretend_outgoing_varargs_named): Likewise. (sh_struct_value_rtx): New. (sh_attribute): Add renesas attribute. (sh_handle_renesas_attribute): New. (sh_attr_renesas_p, sh_cfun_attr_renesas_p): New. (sh_ms_bitfield_layout_p): Support renesas attribute also. (sh_output_mi_thunk): Pass function to aggregate_value_p. * config/sh/sh.h (TARGET_SWITCHES): Add -mrenesas as an alias for -mhitachi. (STRUCT_VALUE_REGNUM, STRUCT_VALUE, RETURN_IN_MEMORY): Moved to target hooks. (sh_args): Add renesas_abi flag. (INIT_CUMULATIVE_ARGS): Set it. Pass fndecl to aggregate_value_p. (FUNCTION_ARG_ADVANCE, FUNCTION_ARG): Move to sh.c. (PASS_IN_REG_P): Support renesas attribute. Pass DF and TF on the stack for the renesas abi. (STRICT_ARGUMENT_NAMING, PRETEND_OUTGOING_VARARGS_NAMED, SETUP_INCOMING_VARARGS, EXPAND_BUILTIN_SAVEREGS, PROMOTE_PROTOTYPES): Moved to sh.c. * config/sh/sh.md (call): Set call cookie to indicate renesas calls. * decl.c (finish_function): Pass fndecl to aggregate_value_p. * misc.c (default_pass_by_ref): Convert to calls.return_in_memory hook. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@71048 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config')
-rw-r--r--gcc/config/alpha/alpha.c2
-rw-r--r--gcc/config/arm/arm.c4
-rw-r--r--gcc/config/i386/i386.c6
-rw-r--r--gcc/config/i960/i960.c2
-rw-r--r--gcc/config/m68hc11/m68hc11.c2
-rw-r--r--gcc/config/mips/mips.c6
-rw-r--r--gcc/config/rs6000/rs6000.c2
-rw-r--r--gcc/config/s390/s390.c2
-rw-r--r--gcc/config/sh/sh-protos.h7
-rw-r--r--gcc/config/sh/sh.c436
-rw-r--r--gcc/config/sh/sh.h255
-rw-r--r--gcc/config/sh/sh.md3
-rw-r--r--gcc/config/sparc/sparc.c2
-rw-r--r--gcc/config/stormy16/stormy16.c2
14 files changed, 468 insertions, 263 deletions
diff --git a/gcc/config/alpha/alpha.c b/gcc/config/alpha/alpha.c
index 92fe830b2d1..72d01af2f15 100644
--- a/gcc/config/alpha/alpha.c
+++ b/gcc/config/alpha/alpha.c
@@ -7799,7 +7799,7 @@ alpha_output_mi_thunk_osf (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
/* Find the "this" pointer. If the function returns a structure,
the structure return pointer is in $16. */
- if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
+ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
this = gen_rtx_REG (Pmode, 17);
else
this = gen_rtx_REG (Pmode, 16);
diff --git a/gcc/config/arm/arm.c b/gcc/config/arm/arm.c
index 747b93115df..5e92b28b79b 100644
--- a/gcc/config/arm/arm.c
+++ b/gcc/config/arm/arm.c
@@ -1968,7 +1968,7 @@ arm_init_cumulative_args (CUMULATIVE_ARGS *pcum, tree fntype,
tree fndecl ATTRIBUTE_UNUSED)
{
/* On the ARM, the offset starts at 0. */
- pcum->nregs = ((fntype && aggregate_value_p (TREE_TYPE (fntype))) ? 1 : 0);
+ pcum->nregs = ((fntype && aggregate_value_p (TREE_TYPE (fntype), fntype)) ? 1 : 0);
pcum->iwmmxt_nregs = 0;
pcum->call_cookie = CALL_NORMAL;
@@ -12962,7 +12962,7 @@ arm_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
int mi_delta = delta;
const char *const mi_op = mi_delta < 0 ? "sub" : "add";
int shift = 0;
- int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)))
+ int this_regno = (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function)
? 1 : 0);
if (mi_delta < 0)
mi_delta = - mi_delta;
diff --git a/gcc/config/i386/i386.c b/gcc/config/i386/i386.c
index 4984fc4f9cf..bccbae9bb3c 100644
--- a/gcc/config/i386/i386.c
+++ b/gcc/config/i386/i386.c
@@ -1748,7 +1748,7 @@ ix86_return_pops_args (tree fundecl, tree funtype, int size)
}
/* Lose any fake structure return argument if it is passed on the stack. */
- if (aggregate_value_p (TREE_TYPE (funtype))
+ if (aggregate_value_p (TREE_TYPE (funtype), fundecl)
&& !TARGET_64BIT)
{
int nregs = ix86_function_regparm (funtype, fundecl);
@@ -15150,7 +15150,7 @@ x86_this_parameter (tree function)
if (TARGET_64BIT)
{
- int n = aggregate_value_p (TREE_TYPE (type)) != 0;
+ int n = aggregate_value_p (TREE_TYPE (type), type) != 0;
return gen_rtx_REG (DImode, x86_64_int_parameter_registers[n]);
}
@@ -15174,7 +15174,7 @@ x86_this_parameter (tree function)
}
}
- if (aggregate_value_p (TREE_TYPE (type)))
+ if (aggregate_value_p (TREE_TYPE (type), type))
return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 8));
else
return gen_rtx_MEM (SImode, plus_constant (stack_pointer_rtx, 4));
diff --git a/gcc/config/i960/i960.c b/gcc/config/i960/i960.c
index cb44ee3efe7..26443223ddc 100644
--- a/gcc/config/i960/i960.c
+++ b/gcc/config/i960/i960.c
@@ -1086,7 +1086,7 @@ i960_function_name_declare (file, name, fndecl)
/* See if caller passes in an address to return value. */
- if (aggregate_value_p (DECL_RESULT (fndecl)))
+ if (aggregate_value_p (DECL_RESULT (fndecl), fndecl))
{
tail_call_ok = 0;
leaf_proc_ok = 0;
diff --git a/gcc/config/m68hc11/m68hc11.c b/gcc/config/m68hc11/m68hc11.c
index 38690ee7319..2787ce11649 100644
--- a/gcc/config/m68hc11/m68hc11.c
+++ b/gcc/config/m68hc11/m68hc11.c
@@ -1490,7 +1490,7 @@ m68hc11_init_cumulative_args (cum, fntype, libname)
ret_type = TREE_TYPE (fntype);
- if (ret_type && aggregate_value_p (ret_type))
+ if (ret_type && aggregate_value_p (ret_type, fntype))
{
cum->words = 1;
cum->nregs = 1;
diff --git a/gcc/config/mips/mips.c b/gcc/config/mips/mips.c
index 74539249fab..7fa4ad80ebd 100644
--- a/gcc/config/mips/mips.c
+++ b/gcc/config/mips/mips.c
@@ -5933,7 +5933,7 @@ mips_save_reg_p (unsigned int regno)
if (regno == GP_REG_FIRST + 31
&& mips16_hard_float
&& !mips_entry
- && !aggregate_value_p (return_type)
+ && !aggregate_value_p (return_type, current_function_decl)
&& GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
&& GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
return true;
@@ -6712,7 +6712,7 @@ mips_expand_prologue (void)
REGNO (pic_offset_table_rtx) = cfun->machine->global_pointer;
/* If struct value address is treated as the first argument, make it so. */
- if (aggregate_value_p (DECL_RESULT (fndecl))
+ if (aggregate_value_p (DECL_RESULT (fndecl), fndecl)
&& ! current_function_returns_pcc_struct
&& struct_value_incoming_rtx == 0)
{
@@ -7179,7 +7179,7 @@ mips_can_use_return_insn (void)
registers. */
if (TARGET_MIPS16
&& mips16_hard_float
- && ! aggregate_value_p (return_type)
+ && ! aggregate_value_p (return_type, current_function_decl)
&& GET_MODE_CLASS (DECL_MODE (return_type)) == MODE_FLOAT
&& GET_MODE_SIZE (DECL_MODE (return_type)) <= UNITS_PER_FPVALUE)
return 0;
diff --git a/gcc/config/rs6000/rs6000.c b/gcc/config/rs6000/rs6000.c
index 6807511c3c8..378170ca79d 100644
--- a/gcc/config/rs6000/rs6000.c
+++ b/gcc/config/rs6000/rs6000.c
@@ -12430,7 +12430,7 @@ rs6000_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
/* Find the "this" pointer. If the function returns a structure,
the structure return pointer is in r3. */
- if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
+ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
this = gen_rtx_REG (Pmode, 4);
else
this = gen_rtx_REG (Pmode, 3);
diff --git a/gcc/config/s390/s390.c b/gcc/config/s390/s390.c
index 4bdb40584ac..7086d5b6932 100644
--- a/gcc/config/s390/s390.c
+++ b/gcc/config/s390/s390.c
@@ -6629,7 +6629,7 @@ s390_output_mi_thunk (FILE *file, tree thunk ATTRIBUTE_UNUSED,
}
/* Operand 1 is the 'this' pointer. */
- if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
+ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
op[1] = gen_rtx_REG (Pmode, 3);
else
op[1] = gen_rtx_REG (Pmode, 2);
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index e046206dc39..b87aecd0181 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -25,7 +25,6 @@ Boston, MA 02111-1307, USA. */
#define GCC_SH_PROTOS_H
#ifdef RTX_CODE
-extern struct rtx_def *sh_builtin_saveregs PARAMS ((void));
extern struct rtx_def *prepare_scc_operands PARAMS ((enum rtx_code));
/* Declare functions defined in sh.c and used in templates. */
@@ -121,6 +120,8 @@ extern int fldi_ok PARAMS ((void));
extern int sh_pr_n_sets PARAMS ((void));
extern int sh_hard_regno_rename_ok PARAMS ((unsigned int, unsigned int));
extern int sh_cfun_interrupt_handler_p PARAMS ((void));
+extern int sh_attr_renesas_p PARAMS ((tree));
+extern int sh_cfun_attr_renesas_p PARAMS ((void));
extern void sh_initialize_trampoline PARAMS ((rtx, rtx, rtx));
extern bool sh_cannot_change_mode_class
PARAMS ((enum machine_mode, enum machine_mode, enum reg_class));
@@ -138,4 +139,8 @@ extern void sh_pr_nosave_low_regs PARAMS ((struct cpp_reader *));
extern rtx function_symbol (const char *);
extern rtx sh_get_pr_initial_val (void);
+extern rtx sh_function_arg (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+extern void sh_function_arg_advance (CUMULATIVE_ARGS *, enum machine_mode, tree, int);
+extern int sh_pass_in_reg_p (CUMULATIVE_ARGS *, enum machine_mode, tree);
+
#endif /* ! GCC_SH_PROTOS_H */
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 15d1d1a57dd..a266471b063 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -203,6 +203,7 @@ const struct attribute_spec sh_attribute_table[];
static tree sh_handle_interrupt_handler_attribute PARAMS ((tree *, tree, tree, int, bool *));
static tree sh_handle_sp_switch_attribute PARAMS ((tree *, tree, tree, int, bool *));
static tree sh_handle_trap_exit_attribute PARAMS ((tree *, tree, tree, int, bool *));
+static tree sh_handle_renesas_attribute PARAMS ((tree *, tree, tree, int, bool *));
static void sh_output_function_epilogue PARAMS ((FILE *, HOST_WIDE_INT));
static void sh_insert_attributes PARAMS ((tree, tree *));
static int sh_adjust_cost PARAMS ((rtx, rtx, rtx, int));
@@ -238,6 +239,15 @@ static int scavenge_reg (HARD_REG_SET *s);
struct save_schedule_s;
static struct save_entry_s *sh5_schedule_saves (HARD_REG_SET *,
struct save_schedule_s *, int);
+
+static bool sh_promote_prototypes PARAMS ((tree));
+static rtx sh_struct_value_rtx PARAMS ((tree, int));
+static bool sh_return_in_memory PARAMS ((tree, tree));
+static rtx sh_builtin_saveregs PARAMS ((void));
+static void sh_setup_incoming_varargs PARAMS ((CUMULATIVE_ARGS *, enum machine_mode, tree, int *, int));
+static bool sh_strict_argument_naming PARAMS ((CUMULATIVE_ARGS *));
+static bool sh_pretend_outgoing_varargs_named PARAMS ((CUMULATIVE_ARGS *));
+
/* Initialize the GCC target structure. */
#undef TARGET_ATTRIBUTE_TABLE
@@ -315,6 +325,27 @@ static struct save_entry_s *sh5_schedule_saves (HARD_REG_SET *,
#define TARGET_HAVE_TLS true
#endif
+#undef TARGET_PROMOTE_PROTOTYPES
+#define TARGET_PROMOTE_PROTOTYPES sh_promote_prototypes
+#undef TARGET_PROMOTE_FUNCTION_ARGS
+#define TARGET_PROMOTE_FUNCTION_ARGS sh_promote_prototypes
+#undef TARGET_PROMOTE_FUNCTION_RETURN
+#define TARGET_PROMOTE_FUNCTION_RETURN sh_promote_prototypes
+
+#undef TARGET_STRUCT_VALUE_RTX
+#define TARGET_STRUCT_VALUE_RTX sh_struct_value_rtx
+#undef TARGET_RETURN_IN_MEMORY
+#define TARGET_RETURN_IN_MEMORY sh_return_in_memory
+
+#undef TARGET_EXPAND_BUILTIN_SAVEREGS
+#define TARGET_EXPAND_BUILTIN_SAVEREGS sh_builtin_saveregs
+#undef TARGET_SETUP_INCOMING_VARARGS
+#define TARGET_SETUP_INCOMING_VARARGS sh_setup_incoming_varargs
+#undef TARGET_STRICT_ARGUMENT_NAMING
+#define TARGET_STRICT_ARGUMENT_NAMING sh_strict_argument_naming
+#undef TARGET_PRETEND_OUTGOING_VARARGS_NAMED
+#define TARGET_PRETEND_OUTGOING_VARARGS_NAMED sh_pretend_outgoing_varargs_named
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Print the operand address in x to the stream. */
@@ -4898,7 +4929,11 @@ calc_live_regs (live_regs_mask)
&& (reg == (int) EH_RETURN_DATA_REGNO (0)
|| reg == (int) EH_RETURN_DATA_REGNO (1)
|| reg == (int) EH_RETURN_DATA_REGNO (2)
- || reg == (int) EH_RETURN_DATA_REGNO (3)))))
+ || reg == (int) EH_RETURN_DATA_REGNO (3)))
+ || ((reg == MACL_REG || reg == MACH_REG)
+ && regs_ever_live[reg]
+ && sh_cfun_attr_renesas_p ())
+ ))
{
SET_HARD_REG_BIT (*live_regs_mask, reg);
count += GET_MODE_SIZE (REGISTER_NATURAL_MODE (reg));
@@ -5190,7 +5225,8 @@ sh_expand_prologue ()
if (current_function_stdarg)
{
/* This is not used by the SH2E calling convention */
- if (TARGET_SH1 && ! TARGET_SH2E && ! TARGET_SH5 && ! TARGET_HITACHI)
+ if (TARGET_SH1 && ! TARGET_SH2E && ! TARGET_SH5
+ && ! (TARGET_HITACHI || sh_cfun_attr_renesas_p ()))
{
/* Push arg regs as if they'd been provided by caller in stack. */
for (i = 0; i < NPARM_REGS(SImode); i++)
@@ -5822,7 +5858,7 @@ sh_output_function_epilogue (file, size)
sp_switch = NULL_RTX;
}
-rtx
+static rtx
sh_builtin_saveregs ()
{
/* First unnamed integer register. */
@@ -5972,7 +6008,8 @@ sh_build_va_list ()
tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
tree record;
- if (TARGET_SH5 || (! TARGET_SH2E && ! TARGET_SH4) || TARGET_HITACHI)
+ if (TARGET_SH5 || (! TARGET_SH2E && ! TARGET_SH4)
+ || TARGET_HITACHI || sh_cfun_attr_renesas_p ())
return ptr_type_node;
record = make_node (RECORD_TYPE);
@@ -6026,7 +6063,8 @@ sh_va_start (valist, nextarg)
return;
}
- if ((! TARGET_SH2E && ! TARGET_SH4) || TARGET_HITACHI)
+ if ((! TARGET_SH2E && ! TARGET_SH4)
+ || TARGET_HITACHI || sh_cfun_attr_renesas_p ())
{
std_expand_builtin_va_start (valist, nextarg);
return;
@@ -6105,7 +6143,8 @@ sh_va_arg (valist, type)
if (pass_by_ref)
type = build_pointer_type (type);
- if (! TARGET_SH5 && (TARGET_SH2E || TARGET_SH4) && ! TARGET_HITACHI)
+ if (! TARGET_SH5 && (TARGET_SH2E || TARGET_SH4)
+ && ! (TARGET_HITACHI || sh_cfun_attr_renesas_p ()))
{
tree f_next_o, f_next_o_limit, f_next_fp, f_next_fp_limit, f_next_stack;
tree next_o, next_o_limit, next_fp, next_fp_limit, next_stack;
@@ -6289,6 +6328,343 @@ sh_va_arg (valist, type)
return result;
}
+static bool
+sh_promote_prototypes (type)
+ tree type;
+{
+ if (TARGET_HITACHI)
+ return 0;
+ if (! type)
+ return 1;
+ return ! sh_attr_renesas_p (type);
+}
+
+/* Define where to put the arguments to a function.
+ Value is zero to push the argument on the stack,
+ or a hard register in which to store the argument.
+
+ MODE is the argument's machine mode.
+ TYPE is the data type of the argument (as a tree).
+ This is null for libcalls where that information may
+ not be available.
+ CUM is a variable of type CUMULATIVE_ARGS which gives info about
+ the preceding args and about the function being called.
+ NAMED is nonzero if this argument is a named parameter
+ (otherwise it is an extra parameter matching an ellipsis).
+
+ On SH the first args are normally in registers
+ and the rest are pushed. Any arg that starts within the first
+ NPARM_REGS words is at least partially passed in a register unless
+ its data type forbids. */
+
+
+rtx
+sh_function_arg (ca, mode, type, named)
+ CUMULATIVE_ARGS *ca;
+ enum machine_mode mode;
+ tree type;
+ int named;
+{
+ if (! TARGET_SH5 && mode == VOIDmode)
+ return GEN_INT (ca->renesas_abi ? 1 : 0);
+
+ if (! TARGET_SH5
+ && PASS_IN_REG_P (*ca, mode, type)
+ && (named || ! (TARGET_HITACHI || ca->renesas_abi)))
+ {
+ int regno;
+
+ if (mode == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN
+ && (! FUNCTION_ARG_SCmode_WART || (ROUND_REG (*ca, mode) & 1)))
+ {
+ rtx r1 = gen_rtx_EXPR_LIST (VOIDmode,
+ gen_rtx_REG (SFmode,
+ BASE_ARG_REG (mode)
+ + (ROUND_REG (*ca, mode) ^ 1)),
+ const0_rtx);
+ rtx r2 = gen_rtx_EXPR_LIST(VOIDmode,
+ gen_rtx_REG (SFmode,
+ BASE_ARG_REG (mode)
+ + ((ROUND_REG (*ca, mode) + 1) ^ 1)),
+ GEN_INT (4));
+ return gen_rtx_PARALLEL(SCmode, gen_rtvec(2, r1, r2));
+ }
+
+ /* If the alignment of a DF value causes an SF register to be
+ skipped, we will use that skipped register for the next SF
+ value. */
+ if ((TARGET_HITACHI || ca->renesas_abi)
+ && ca->free_single_fp_reg
+ && mode == SFmode)
+ return gen_rtx_REG (mode, ca->free_single_fp_reg);
+
+ regno = (BASE_ARG_REG (mode) + ROUND_REG (*ca, mode))
+ ^ (mode == SFmode && TARGET_SH4
+ && TARGET_LITTLE_ENDIAN != 0
+ && ! TARGET_HITACHI && ! ca->renesas_abi);
+ return gen_rtx_REG (mode, regno);
+
+ }
+
+ if (TARGET_SH5)
+ {
+ if (mode == VOIDmode && TARGET_SHCOMPACT)
+ return GEN_INT (ca->call_cookie);
+
+ /* The following test assumes unnamed arguments are promoted to
+ DFmode. */
+ if (mode == SFmode && ca->free_single_fp_reg)
+ return SH5_PROTOTYPED_FLOAT_ARG (*ca, mode, ca->free_single_fp_reg);
+
+ if ((GET_SH_ARG_CLASS (mode) == SH_ARG_FLOAT)
+ && (named || ! ca->prototype_p)
+ && ca->arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (SFmode))
+ {
+ if (! ca->prototype_p && TARGET_SHMEDIA)
+ return SH5_PROTOTYPELESS_FLOAT_ARG (*ca, mode);
+
+ return SH5_PROTOTYPED_FLOAT_ARG (*ca, mode,
+ FIRST_FP_PARM_REG
+ + ca->arg_count[(int) SH_ARG_FLOAT]);
+ }
+
+ if (ca->arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode)
+ && (! TARGET_SHCOMPACT
+ || (! SHCOMPACT_FORCE_ON_STACK (mode, type)
+ && ! SH5_WOULD_BE_PARTIAL_NREGS (*ca, mode,
+ type, named))))
+ {
+ return gen_rtx_REG (mode, (FIRST_PARM_REG
+ + ca->arg_count[(int) SH_ARG_INT]));
+ }
+
+ return 0;
+ }
+
+ return 0;
+}
+
+/* Update the data in CUM to advance over an argument
+ of mode MODE and data type TYPE.
+ (TYPE is null for libcalls where that information may not be
+ available.) */
+
+void
+sh_function_arg_advance (ca, mode, type, named)
+ CUMULATIVE_ARGS *ca;
+ enum machine_mode mode;
+ tree type;
+ int named;
+{
+ if (ca->force_mem)
+ ca->force_mem = 0;
+ else if (TARGET_SH5)
+ {
+ tree type2 = (ca->byref && type
+ ? TREE_TYPE (type)
+ : type);
+ enum machine_mode mode2 = (ca->byref && type
+ ? TYPE_MODE (type2)
+ : mode);
+ int dwords = ((ca->byref
+ ? ca->byref
+ : mode2 == BLKmode
+ ? int_size_in_bytes (type2)
+ : GET_MODE_SIZE (mode2)) + 7) / 8;
+ int numregs = MIN (dwords, NPARM_REGS (SImode)
+ - ca->arg_count[(int) SH_ARG_INT]);
+
+ if (numregs)
+ {
+ ca->arg_count[(int) SH_ARG_INT] += numregs;
+ if (TARGET_SHCOMPACT
+ && SHCOMPACT_FORCE_ON_STACK (mode2, type2))
+ {
+ ca->call_cookie
+ |= CALL_COOKIE_INT_REG (ca->arg_count[(int) SH_ARG_INT]
+ - numregs, 1);
+ /* N.B. We want this also for outgoing. */
+ ca->stack_regs += numregs;
+ }
+ else if (ca->byref)
+ {
+ if (! ca->outgoing)
+ ca->stack_regs += numregs;
+ ca->byref_regs += numregs;
+ ca->byref = 0;
+ do
+ ca->call_cookie
+ |= CALL_COOKIE_INT_REG (ca->arg_count[(int) SH_ARG_INT]
+ - numregs, 2);
+ while (--numregs);
+ ca->call_cookie
+ |= CALL_COOKIE_INT_REG (ca->arg_count[(int) SH_ARG_INT]
+ - 1, 1);
+ }
+ else if (dwords > numregs)
+ {
+ int pushregs = numregs;
+
+ if (TARGET_SHCOMPACT)
+ ca->stack_regs += numregs;
+ while (pushregs < NPARM_REGS (SImode) - 1
+ && (CALL_COOKIE_INT_REG_GET
+ (ca->call_cookie,
+ NPARM_REGS (SImode) - pushregs)
+ == 1))
+ {
+ ca->call_cookie
+ &= ~ CALL_COOKIE_INT_REG (NPARM_REGS (SImode)
+ - pushregs, 1);
+ pushregs++;
+ }
+ if (numregs == NPARM_REGS (SImode))
+ ca->call_cookie
+ |= CALL_COOKIE_INT_REG (0, 1)
+ | CALL_COOKIE_STACKSEQ (numregs - 1);
+ else
+ ca->call_cookie
+ |= CALL_COOKIE_STACKSEQ (numregs);
+ }
+ }
+ if (GET_SH_ARG_CLASS (mode2) == SH_ARG_FLOAT
+ && (named || ! ca->prototype_p))
+ {
+ if (mode2 == SFmode && ca->free_single_fp_reg)
+ ca->free_single_fp_reg = 0;
+ else if (ca->arg_count[(int) SH_ARG_FLOAT]
+ < NPARM_REGS (SFmode))
+ {
+ int numfpregs
+ = MIN ((GET_MODE_SIZE (mode2) + 7) / 8 * 2,
+ NPARM_REGS (SFmode)
+ - ca->arg_count[(int) SH_ARG_FLOAT]);
+
+ ca->arg_count[(int) SH_ARG_FLOAT] += numfpregs;
+
+ if (TARGET_SHCOMPACT && ! ca->prototype_p)
+ {
+ if (ca->outgoing && numregs > 0)
+ do
+ {
+ ca->call_cookie
+ |= (CALL_COOKIE_INT_REG
+ (ca->arg_count[(int) SH_ARG_INT]
+ - numregs + ((numfpregs - 2) / 2),
+ 4 + (ca->arg_count[(int) SH_ARG_FLOAT]
+ - numfpregs) / 2));
+ }
+ while (numfpregs -= 2);
+ }
+ else if (mode2 == SFmode && (named)
+ && (ca->arg_count[(int) SH_ARG_FLOAT]
+ < NPARM_REGS (SFmode)))
+ ca->free_single_fp_reg
+ = FIRST_FP_PARM_REG - numfpregs
+ + ca->arg_count[(int) SH_ARG_FLOAT] + 1;
+ }
+ }
+ return;
+ }
+
+ if ((TARGET_HITACHI || ca->renesas_abi) && TARGET_FPU_DOUBLE)
+ {
+ /* Note that we've used the skipped register. */
+ if (mode == SFmode && ca->free_single_fp_reg)
+ {
+ ca->free_single_fp_reg = 0;
+ return;
+ }
+ /* When we have a DF after an SF, there's an SF register that get
+ skipped in order to align the DF value. We note this skipped
+ register, because the next SF value will use it, and not the
+ SF that follows the DF. */
+ if (mode == DFmode
+ && ROUND_REG (*ca, DFmode) != ROUND_REG (*ca, SFmode))
+ {
+ ca->free_single_fp_reg = (ROUND_REG (*ca, SFmode)
+ + BASE_ARG_REG (mode));
+ }
+ }
+
+ if (! (TARGET_SH4 || ca->renesas_abi)
+ || PASS_IN_REG_P (*ca, mode, type))
+ (ca->arg_count[(int) GET_SH_ARG_CLASS (mode)]
+ = (ROUND_REG (*ca, mode)
+ + (mode == BLKmode
+ ? ROUND_ADVANCE (int_size_in_bytes (type))
+ : ROUND_ADVANCE (GET_MODE_SIZE (mode)))));
+}
+
+/* If the structure value address is not passed in a register, define
+ `STRUCT_VALUE' as an expression returning an RTX for the place
+ where the address is passed. If it returns 0, the address is
+ passed as an "invisible" first argument. */
+/* The Renesas calling convention doesn't quite fit into this scheme since
+ the address is passed like an invisible argument, but one that is always
+ passed in memory. */
+static rtx
+sh_struct_value_rtx (fndecl, incoming)
+ tree fndecl;
+ int incoming ATTRIBUTE_UNUSED;
+{
+ if (TARGET_HITACHI || sh_attr_renesas_p (fndecl))
+ return 0;
+ return gen_rtx_REG (Pmode, 2);
+}
+
+static bool
+sh_return_in_memory (type, fndecl)
+ tree type;
+ tree fndecl;
+{
+ if (TARGET_SH5)
+ {
+ if (TYPE_MODE (type) == BLKmode)
+ return ((unsigned HOST_WIDE_INT) int_size_in_bytes (type)) > 8;
+ else
+ return GET_MODE_SIZE (TYPE_MODE (type)) > 8;
+ }
+ else
+ {
+ return (TYPE_MODE (type) == BLKmode
+ || ((TARGET_HITACHI || sh_attr_renesas_p (fndecl))
+ && TREE_CODE (type) == RECORD_TYPE));
+ }
+}
+
+/* We actually emit the code in sh_expand_prologue. We used to use
+ a static variable to flag that we need to emit this code, but that
+ doesn't when inlining, when functions are deferred and then emitted
+ later. Fortunately, we already have two flags that are part of struct
+ function that tell if a function uses varargs or stdarg. */
+static void
+sh_setup_incoming_varargs (ca, mode, type, pretend_arg_size, second_time)
+ CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED;
+ enum machine_mode mode ATTRIBUTE_UNUSED;
+ tree type ATTRIBUTE_UNUSED;
+ int *pretend_arg_size ATTRIBUTE_UNUSED;
+ int second_time ATTRIBUTE_UNUSED;
+{
+ if (! current_function_stdarg)
+ abort ();
+}
+
+static bool
+sh_strict_argument_naming (ca)
+ CUMULATIVE_ARGS *ca ATTRIBUTE_UNUSED;
+{
+ return TARGET_SH5;
+}
+
+static bool
+sh_pretend_outgoing_varargs_named (ca)
+ CUMULATIVE_ARGS *ca;
+{
+ return ! (TARGET_HITACHI || ca->renesas_abi) && ! TARGET_SH5;
+}
+
+
/* Define the offset between two registers, one to be eliminated, and
the other its replacement, at the start of a routine. */
@@ -6424,7 +6800,12 @@ sh_insert_attributes (node, attributes)
to run on.
trap_exit -- use a trapa to exit an interrupt function instead of
- an rte instruction. */
+ an rte instruction.
+
+ renesas -- use Renesas calling/layout conventions (functions and
+ structures).
+
+*/
const struct attribute_spec sh_attribute_table[] =
{
@@ -6432,6 +6813,7 @@ const struct attribute_spec sh_attribute_table[] =
{ "interrupt_handler", 0, 0, true, false, false, sh_handle_interrupt_handler_attribute },
{ "sp_switch", 1, 1, true, false, false, sh_handle_sp_switch_attribute },
{ "trap_exit", 1, 1, true, false, false, sh_handle_trap_exit_attribute },
+ { "renesas", 0, 0, false, true, false, sh_handle_renesas_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
@@ -6537,6 +6919,40 @@ sh_handle_trap_exit_attribute (node, name, args, flags, no_add_attrs)
return NULL_TREE;
}
+static tree
+sh_handle_renesas_attribute (node, name, args, flags, no_add_attrs)
+ tree *node ATTRIBUTE_UNUSED;
+ tree name ATTRIBUTE_UNUSED;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs ATTRIBUTE_UNUSED;
+{
+ return NULL_TREE;
+}
+
+/* True if __attribute__((renesas)) or -mrenesas. */
+int
+sh_attr_renesas_p (td)
+ tree td;
+{
+ if (TARGET_HITACHI)
+ return 1;
+ if (td == 0)
+ return 0;
+ if (DECL_P (td))
+ td = TREE_TYPE (td);
+ return (lookup_attribute ("renesas", TYPE_ATTRIBUTES (td))
+ != NULL_TREE);
+}
+
+/* True if __attribute__((renesas)) or -mrenesas, for the current
+ function. */
+int
+sh_cfun_attr_renesas_p ()
+{
+ return sh_attr_renesas_p (current_function_decl);
+}
+
int
sh_cfun_interrupt_handler_p ()
{
@@ -8000,7 +8416,7 @@ static bool
sh_ms_bitfield_layout_p (record_type)
tree record_type ATTRIBUTE_UNUSED;
{
- return TARGET_SH5;
+ return (TARGET_SH5 || TARGET_HITACHI || sh_attr_renesas_p (record_type));
}
/*
@@ -8683,10 +9099,10 @@ sh_output_mi_thunk (file, thunk_fndecl, delta, vcall_offset, function)
comes first, in which case "this" comes second. */
INIT_CUMULATIVE_ARGS (cum, funtype, NULL_RTX, 0);
#ifndef PCC_STATIC_STRUCT_RETURN
- if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
+ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
structure_value_byref = 1;
#endif /* not PCC_STATIC_STRUCT_RETURN */
- if (structure_value_byref && struct_value_rtx == 0)
+ if (structure_value_byref && sh_struct_value_rtx (function, 0) == 0)
{
tree ptype = build_pointer_type (TREE_TYPE (funtype));
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 3ab2120e9a5..a3aa1dd29ae 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -319,6 +319,7 @@ extern int target_flags;
{"dalign", DALIGN_BIT, "Aligns doubles at 64-bit boundaries" }, \
{"fmovd", FMOVD_BIT, "" }, \
{"hitachi", HITACHI_BIT, "Follow Renesas (formerly Hitachi) / SuperH calling conventions" }, \
+ {"renesas", HITACHI_BIT, "Follow Renesas (formerly Hitachi) / SuperH calling conventions" }, \
{"nomacsave", NOMACSAVE_BIT, "Mark MAC register as call-clobbered" }, \
{"ieee", IEEE_BIT, "Increase the IEEE compliance for floating-point code" }, \
{"isize", ISIZE_BIT, "" }, \
@@ -1126,29 +1127,6 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
/* Register in which the static-chain is passed to a function. */
#define STATIC_CHAIN_REGNUM (TARGET_SH5 ? 1 : 3)
-/* The register in which a struct value address is passed. */
-
-#define STRUCT_VALUE_REGNUM 2
-
-/* If the structure value address is not passed in a register, define
- `STRUCT_VALUE' as an expression returning an RTX for the place
- where the address is passed. If it returns 0, the address is
- passed as an "invisible" first argument. */
-
-/* The Renesas calling convention doesn't quite fit into this scheme since
- the address is passed like an invisible argument, but one that is always
- passed in memory. */
-#define STRUCT_VALUE \
- (TARGET_HITACHI ? 0 : gen_rtx_REG (Pmode, STRUCT_VALUE_REGNUM))
-
-#define RETURN_IN_MEMORY(TYPE) \
- (TARGET_SH5 \
- ? ((TYPE_MODE (TYPE) == BLKmode \
- ? (unsigned HOST_WIDE_INT) int_size_in_bytes (TYPE) \
- : GET_MODE_SIZE (TYPE_MODE (TYPE))) > 8) \
- : (TYPE_MODE (TYPE) == BLKmode \
- || (TARGET_HITACHI && TREE_CODE (TYPE) == RECORD_TYPE)))
-
/* Don't default to pcc-struct-return, because we have already specified
exactly how to return structures in the RETURN_IN_MEMORY macro. */
@@ -1797,6 +1775,10 @@ struct sh_args {
#define CALL_COOKIE_INT_REG_GET(COOKIE, REG) \
(((COOKIE) >> CALL_COOKIE_INT_REG_SHIFT (REG)) & ((REG) < 4 ? 7 : 15))
long call_cookie;
+
+ /* This is set to non-zero when the call in question must use the Renesas ABI,
+ even without the -mrenesas option. */
+ int renesas_abi;
};
#define CUMULATIVE_ARGS struct sh_args
@@ -1839,17 +1821,18 @@ struct sh_args {
For TARGET_HITACHI, the structure value pointer is passed in memory. */
-#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, INDIRECT) \
+#define INIT_CUMULATIVE_ARGS(CUM, FNTYPE, LIBNAME, FNDECL) \
do { \
(CUM).arg_count[(int) SH_ARG_INT] = 0; \
(CUM).arg_count[(int) SH_ARG_FLOAT] = 0; \
+ (CUM).renesas_abi = sh_attr_renesas_p (FNTYPE) ? 1 : 0; \
(CUM).force_mem \
- = (TARGET_HITACHI && FNTYPE \
- && aggregate_value_p (TREE_TYPE (FNTYPE))); \
+ = ((TARGET_HITACHI || (CUM).renesas_abi) && (FNTYPE) \
+ && aggregate_value_p (TREE_TYPE (FNTYPE), (FNDECL))); \
(CUM).prototype_p = (FNTYPE) && TYPE_ARG_TYPES (FNTYPE); \
(CUM).arg_count[(int) SH_ARG_INT] \
= (TARGET_SH5 && (FNTYPE) \
- && aggregate_value_p (TREE_TYPE (FNTYPE))); \
+ && aggregate_value_p (TREE_TYPE (FNTYPE), (FNDECL))); \
(CUM).free_single_fp_reg = 0; \
(CUM).outgoing = 1; \
(CUM).stack_regs = 0; \
@@ -1881,128 +1864,11 @@ struct sh_args {
INIT_CUMULATIVE_ARGS ((CUM), (FNTYPE), (LIBNAME), 0); \
(CUM).outgoing = 0; \
} while (0)
-
-/* Update the data in CUM to advance over an argument
- of mode MODE and data type TYPE.
- (TYPE is null for libcalls where that information may not be
- available.) */
#define FUNCTION_ARG_ADVANCE(CUM, MODE, TYPE, NAMED) \
- if ((CUM).force_mem) \
- (CUM).force_mem = 0; \
- else if (TARGET_SH5) \
- { \
- tree TYPE_ = ((CUM).byref && (TYPE) \
- ? TREE_TYPE (TYPE) \
- : (TYPE)); \
- enum machine_mode MODE_ = ((CUM).byref && (TYPE) \
- ? TYPE_MODE (TYPE_) \
- : (MODE)); \
- int dwords = (((CUM).byref \
- ? (CUM).byref \
- : (MODE_) == BLKmode \
- ? int_size_in_bytes (TYPE_) \
- : GET_MODE_SIZE (MODE_)) + 7) / 8; \
- int numregs = MIN (dwords, NPARM_REGS (SImode) \
- - (CUM).arg_count[(int) SH_ARG_INT]); \
- \
- if (numregs) \
- { \
- (CUM).arg_count[(int) SH_ARG_INT] += numregs; \
- if (TARGET_SHCOMPACT \
- && SHCOMPACT_FORCE_ON_STACK (MODE_, TYPE_)) \
- { \
- (CUM).call_cookie \
- |= CALL_COOKIE_INT_REG (((CUM).arg_count[(int) SH_ARG_INT] \
- - numregs), 1); \
- /* N.B. We want this also for outgoing. */\
- (CUM).stack_regs += numregs; \
- } \
- else if ((CUM).byref) \
- { \
- if (! (CUM).outgoing) \
- (CUM).stack_regs += numregs; \
- (CUM).byref_regs += numregs; \
- (CUM).byref = 0; \
- do \
- (CUM).call_cookie \
- |= CALL_COOKIE_INT_REG (((CUM).arg_count[(int) SH_ARG_INT] \
- - numregs), 2); \
- while (--numregs); \
- (CUM).call_cookie \
- |= CALL_COOKIE_INT_REG (((CUM).arg_count[(int) SH_ARG_INT] \
- - 1), 1); \
- } \
- else if (dwords > numregs) \
- { \
- int pushregs = numregs; \
- \
- if (TARGET_SHCOMPACT) \
- (CUM).stack_regs += numregs; \
- while (pushregs < NPARM_REGS (SImode) - 1 \
- && (CALL_COOKIE_INT_REG_GET \
- ((CUM).call_cookie, \
- NPARM_REGS (SImode) - pushregs) \
- == 1)) \
- { \
- (CUM).call_cookie \
- &= ~ CALL_COOKIE_INT_REG (NPARM_REGS (SImode) \
- - pushregs, 1); \
- pushregs++; \
- } \
- if (numregs == NPARM_REGS (SImode)) \
- (CUM).call_cookie \
- |= CALL_COOKIE_INT_REG (0, 1) \
- | CALL_COOKIE_STACKSEQ (numregs - 1); \
- else \
- (CUM).call_cookie \
- |= CALL_COOKIE_STACKSEQ (numregs); \
- } \
- } \
- if (GET_SH_ARG_CLASS (MODE_) == SH_ARG_FLOAT \
- && ((NAMED) || ! (CUM).prototype_p)) \
- { \
- if ((MODE_) == SFmode && (CUM).free_single_fp_reg) \
- (CUM).free_single_fp_reg = 0; \
- else if ((CUM).arg_count[(int) SH_ARG_FLOAT] \
- < NPARM_REGS (SFmode)) \
- { \
- int numfpregs \
- = MIN ((GET_MODE_SIZE (MODE_) + 7) / 8 * 2, \
- NPARM_REGS (SFmode) \
- - (CUM).arg_count[(int) SH_ARG_FLOAT]); \
- \
- (CUM).arg_count[(int) SH_ARG_FLOAT] += numfpregs; \
- \
- if (TARGET_SHCOMPACT && ! (CUM).prototype_p) \
- { \
- if ((CUM).outgoing && numregs > 0) \
- do \
- { \
- (CUM).call_cookie \
- |= (CALL_COOKIE_INT_REG \
- ((CUM).arg_count[(int) SH_ARG_INT] \
- - numregs + ((numfpregs - 2) / 2), \
- 4 + ((CUM).arg_count[(int) SH_ARG_FLOAT] \
- - numfpregs) / 2)); \
- } \
- while (numfpregs -= 2); \
- } \
- else if ((MODE_) == SFmode && (NAMED) \
- && ((CUM).arg_count[(int) SH_ARG_FLOAT] \
- < NPARM_REGS (SFmode))) \
- (CUM).free_single_fp_reg \
- = FIRST_FP_PARM_REG - numfpregs \
- + (CUM).arg_count[(int) SH_ARG_FLOAT] + 1; \
- } \
- } \
- } \
- else if (! TARGET_SH4 || PASS_IN_REG_P ((CUM), (MODE), (TYPE))) \
- ((CUM).arg_count[(int) GET_SH_ARG_CLASS (MODE)] \
- = (ROUND_REG ((CUM), (MODE)) \
- + ((MODE) == BLKmode \
- ? ROUND_ADVANCE (int_size_in_bytes (TYPE)) \
- : ROUND_ADVANCE (GET_MODE_SIZE (MODE)))))
+ sh_function_arg_advance (&(CUM), (MODE), (TYPE), (NAMED))
+#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
+ sh_function_arg (&(CUM), (MODE), (TYPE), (NAMED))
/* Return boolean indicating arg of mode MODE will be passed in a reg.
This macro is only used in this file. */
@@ -2010,7 +1876,11 @@ struct sh_args {
#define PASS_IN_REG_P(CUM, MODE, TYPE) \
(((TYPE) == 0 \
|| (! TREE_ADDRESSABLE ((tree)(TYPE)) \
- && (! TARGET_HITACHI || ! AGGREGATE_TYPE_P (TYPE)))) \
+ && (! (TARGET_HITACHI || (CUM).renesas_abi) \
+ || ! (AGGREGATE_TYPE_P (TYPE) \
+ || (!TARGET_FPU_ANY \
+ && (GET_MODE_CLASS (MODE) == MODE_FLOAT \
+ && GET_MODE_SIZE (MODE) > GET_MODE_SIZE (SFmode))))))) \
&& ! (CUM).force_mem \
&& (TARGET_SH2E \
? ((MODE) == BLKmode \
@@ -2040,75 +1910,6 @@ struct sh_args {
foo (float a, __complex float b); a: fr5 b.real: fr4 b.imag: fr7 */
#define FUNCTION_ARG_SCmode_WART 1
-/* Define where to put the arguments to a function.
- Value is zero to push the argument on the stack,
- or a hard register in which to store the argument.
-
- MODE is the argument's machine mode.
- TYPE is the data type of the argument (as a tree).
- This is null for libcalls where that information may
- not be available.
- CUM is a variable of type CUMULATIVE_ARGS which gives info about
- the preceding args and about the function being called.
- NAMED is nonzero if this argument is a named parameter
- (otherwise it is an extra parameter matching an ellipsis).
-
- On SH the first args are normally in registers
- and the rest are pushed. Any arg that starts within the first
- NPARM_REGS words is at least partially passed in a register unless
- its data type forbids. */
-
-#define FUNCTION_ARG(CUM, MODE, TYPE, NAMED) \
- ((! TARGET_SH5 \
- && PASS_IN_REG_P ((CUM), (MODE), (TYPE)) \
- && ((NAMED) || !TARGET_HITACHI)) \
- ? (((MODE) == SCmode && TARGET_SH4 && TARGET_LITTLE_ENDIAN \
- && (! FUNCTION_ARG_SCmode_WART || (ROUND_REG ((CUM), (MODE)) & 1)))\
- ? (gen_rtx_PARALLEL \
- (SCmode, \
- (gen_rtvec \
- (2, \
- (gen_rtx_EXPR_LIST \
- (VOIDmode, \
- gen_rtx_REG (SFmode, \
- BASE_ARG_REG (MODE) \
- + (ROUND_REG ((CUM), (MODE)) ^ 1)), \
- const0_rtx)), \
- (gen_rtx_EXPR_LIST \
- (VOIDmode, \
- gen_rtx_REG (SFmode, \
- BASE_ARG_REG (MODE) \
- + ((ROUND_REG ((CUM), (MODE)) + 1) ^ 1)), \
- GEN_INT (4))))))) \
- : gen_rtx_REG ((MODE), \
- ((BASE_ARG_REG (MODE) + ROUND_REG ((CUM), (MODE))) \
- ^ ((MODE) == SFmode && TARGET_SH4 \
- && TARGET_LITTLE_ENDIAN != 0)))) \
- : TARGET_SH5 \
- ? ((MODE) == VOIDmode && TARGET_SHCOMPACT \
- ? GEN_INT ((CUM).call_cookie) \
- /* The following test assumes unnamed arguments are promoted to \
- DFmode. */ \
- : (MODE) == SFmode && (CUM).free_single_fp_reg \
- ? SH5_PROTOTYPED_FLOAT_ARG ((CUM), (MODE), (CUM).free_single_fp_reg) \
- : (GET_SH_ARG_CLASS (MODE) == SH_ARG_FLOAT \
- && ((NAMED) || ! (CUM).prototype_p) \
- && (CUM).arg_count[(int) SH_ARG_FLOAT] < NPARM_REGS (SFmode)) \
- ? ((! (CUM).prototype_p && TARGET_SHMEDIA) \
- ? SH5_PROTOTYPELESS_FLOAT_ARG ((CUM), (MODE)) \
- : SH5_PROTOTYPED_FLOAT_ARG ((CUM), (MODE), \
- FIRST_FP_PARM_REG \
- + (CUM).arg_count[(int) SH_ARG_FLOAT])) \
- : ((CUM).arg_count[(int) SH_ARG_INT] < NPARM_REGS (SImode) \
- && (! TARGET_SHCOMPACT \
- || (! SHCOMPACT_FORCE_ON_STACK ((MODE), (TYPE)) \
- && ! SH5_WOULD_BE_PARTIAL_NREGS ((CUM), (MODE), \
- (TYPE), (NAMED))))) \
- ? gen_rtx_REG ((MODE), (FIRST_PARM_REG \
- + (CUM).arg_count[(int) SH_ARG_INT])) \
- : 0) \
- : 0)
-
/* Whether an argument must be passed by reference. On SHcompact, we
pretend arguments wider than 32-bits that would have been passed in
registers are passed by reference, so that an SHmedia trampoline
@@ -2203,10 +2004,6 @@ struct sh_args {
(REG)), \
const0_rtx))))
-#define STRICT_ARGUMENT_NAMING TARGET_SH5
-
-#define PRETEND_OUTGOING_VARARGS_NAMED (! TARGET_HITACHI && ! TARGET_SH5)
-
/* For an arg passed partly in registers and partly in memory,
this is the number of registers used.
For args passed entirely in registers or entirely in memory, zero.
@@ -2238,16 +2035,6 @@ struct sh_args {
/* Perform any needed actions needed for a function that is receiving a
variable number of arguments. */
-/* We actually emit the code in sh_expand_prologue. We used to use
- a static variable to flag that we need to emit this code, but that
- doesn't when inlining, when functions are deferred and then emitted
- later. Fortunately, we already have two flags that are part of struct
- function that tell if a function uses varargs or stdarg. */
-#define SETUP_INCOMING_VARARGS(ASF, MODE, TYPE, PAS, ST) do \
- if (! current_function_stdarg) \
- abort (); \
-while (0)
-
/* Define the `__builtin_va_list' type for the ABI. */
#define BUILD_VA_LIST_TYPE(VALIST) \
(VALIST) = sh_build_va_list ()
@@ -2336,9 +2123,6 @@ while (0)
#define INCOMING_RETURN_ADDR_RTX \
gen_rtx_REG (Pmode, TARGET_SHMEDIA ? PR_MEDIA_REG : PR_REG)
-/* Generate necessary RTL for __builtin_saveregs(). */
-#define EXPAND_BUILTIN_SAVEREGS() sh_builtin_saveregs ()
-
/* Addressing modes, and classification of registers for them. */
#define HAVE_POST_INCREMENT TARGET_SH1
#define HAVE_PRE_DECREMENT TARGET_SH1
@@ -2919,9 +2703,6 @@ while (0)
but a CALL with constant address is cheap. */
/*#define NO_FUNCTION_CSE 1*/
-/* Chars and shorts should be passed as ints. */
-#define PROMOTE_PROTOTYPES 1
-
/* The machine modes of pointers and functions. */
#define Pmode (TARGET_SHMEDIA64 ? DImode : SImode)
#define FUNCTION_MODE Pmode
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index bd341a0b2df..c5c55c76bf2 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -5869,7 +5869,10 @@
DONE;
}
else
+ {
operands[0] = force_reg (SImode, XEXP (operands[0], 0));
+ operands[1] = operands[2];
+ }
emit_call_insn (gen_calli (operands[0], operands[1]));
DONE;
diff --git a/gcc/config/sparc/sparc.c b/gcc/config/sparc/sparc.c
index b095a007bb8..84d27d26a34 100644
--- a/gcc/config/sparc/sparc.c
+++ b/gcc/config/sparc/sparc.c
@@ -8301,7 +8301,7 @@ sparc_output_mi_thunk (FILE *file, tree thunk_fndecl ATTRIBUTE_UNUSED,
/* Find the "this" pointer. Normally in %o0, but in ARCH64 if the function
returns a structure, the structure return pointer is there instead. */
- if (TARGET_ARCH64 && aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
+ if (TARGET_ARCH64 && aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
this = gen_rtx_REG (Pmode, SPARC_INCOMING_INT_ARG_FIRST + 1);
else
this = gen_rtx_REG (Pmode, SPARC_INCOMING_INT_ARG_FIRST);
diff --git a/gcc/config/stormy16/stormy16.c b/gcc/config/stormy16/stormy16.c
index 8ce526f90d2..d493b7ce797 100644
--- a/gcc/config/stormy16/stormy16.c
+++ b/gcc/config/stormy16/stormy16.c
@@ -1562,7 +1562,7 @@ xstormy16_asm_output_mi_thunk (file, thunk_fndecl, delta,
int regnum = FIRST_ARGUMENT_REGISTER;
/* There might be a hidden first argument for a returned structure. */
- if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function))))
+ if (aggregate_value_p (TREE_TYPE (TREE_TYPE (function)), function))
regnum += 1;
fprintf (file, "\tadd %s,#0x%x\n", reg_names[regnum], (int) delta & 0xFFFF);