Commit 650fc469 by Chung-Ju Wu Committed by Chung-Ju Wu

[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
parent 557430f1
2014-09-03 Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32.c (nds32_arg_partial_bytes): New implementation
for TARGET_ARG_PARTIAL_BYTES.
2014-09-03 Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32.c (nds32_expand_prologue): Emit stack push
instructions for varargs implementation.
(nds32_expand_epilogue): Emit stack adjustment instructions for
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment