From 650fc46935f19fe1e935fa62891689cb1375d8b6 Mon Sep 17 00:00:00 2001 From: Chung-Ju Wu Date: Wed, 3 Sep 2014 10:15:06 +0000 Subject: [PATCH] [NDS32] Provide TARGET_ARG_PARTIAL_BYTES so that we can have structure argument partially in registers and stack. -- This is needed if we would like to pass variadic arguments via registers that are pused on the stack by callee. So that va_arg() can access arguments continously in memory. * config/nds32/nds32.c (nds32_arg_partial_bytes): New implementation for TARGET_ARG_PARTIAL_BYTES. From-SVN: r214868 --- gcc/ChangeLog | 5 +++++ gcc/config/nds32/nds32.c | 47 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 26e89f6762b..2ea7792588a 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,8 @@ +2014-09-03 Chung-Ju Wu + + * config/nds32/nds32.c (nds32_arg_partial_bytes): New implementation + for TARGET_ARG_PARTIAL_BYTES. + 2014-09-03 Chung-Ju Wu * config/nds32/nds32.c (nds32_expand_prologue): Emit stack push diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c index d2890dc3d27..fdd4fd4151b 100644 --- a/gcc/config/nds32/nds32.c +++ b/gcc/config/nds32/nds32.c @@ -1352,6 +1352,50 @@ nds32_function_arg (cumulative_args_t ca, enum machine_mode mode, return NULL_RTX; } +static int +nds32_arg_partial_bytes (cumulative_args_t ca, enum machine_mode mode, + tree type, bool named ATTRIBUTE_UNUSED) +{ + /* Returns the number of bytes at the beginning of an argument that + must be put in registers. The value must be zero for arguments that are + passed entirely in registers or that are entirely pushed on the stack. + Besides, TARGET_FUNCTION_ARG for these arguments should return the + first register to be used by the caller for this argument. */ + unsigned int needed_reg_count; + unsigned int remaining_reg_count; + CUMULATIVE_ARGS *cum; + + cum = get_cumulative_args (ca); + + /* Under hard float abi, we better have argument entirely passed in + registers or pushed on the stack so that we can reduce the complexity + of dealing with cum->gpr_offset and cum->fpr_offset. */ + if (TARGET_HARD_FLOAT) + return 0; + + /* If we have already runned out of argument registers, return zero + so that the argument will be entirely pushed on the stack. */ + if (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type) + >= NDS32_GPR_ARG_FIRST_REGNUM + NDS32_MAX_GPR_REGS_FOR_ARGS) + return 0; + + /* Calculate how many registers do we need for this argument. */ + needed_reg_count = NDS32_NEED_N_REGS_FOR_ARG (mode, type); + + /* Calculate how many argument registers have left for passing argument. + Note that we should count it from next available register number. */ + remaining_reg_count + = NDS32_MAX_GPR_REGS_FOR_ARGS + - (NDS32_AVAILABLE_REGNUM_FOR_GPR_ARG (cum->gpr_offset, mode, type) + - NDS32_GPR_ARG_FIRST_REGNUM); + + /* Note that we have to return the nubmer of bytes, not registers count. */ + if (needed_reg_count > remaining_reg_count) + return remaining_reg_count * UNITS_PER_WORD; + + return 0; +} + static void nds32_function_arg_advance (cumulative_args_t ca, enum machine_mode mode, const_tree type, bool named) @@ -3454,6 +3498,9 @@ nds32_target_alignment (rtx label) #undef TARGET_FUNCTION_ARG #define TARGET_FUNCTION_ARG nds32_function_arg +#undef TARGET_ARG_PARTIAL_BYTES +#define TARGET_ARG_PARTIAL_BYTES nds32_arg_partial_bytes + #undef TARGET_FUNCTION_ARG_ADVANCE #define TARGET_FUNCTION_ARG_ADVANCE nds32_function_arg_advance -- 2.30.2