summaryrefslogtreecommitdiff
path: root/gcc/config/nds32/nds32.c
diff options
context:
space:
mode:
authorjasonwucj <jasonwucj@138bc75d-0d04-0410-961f-82ee72b054a4>2014-09-03 10:09:14 +0000
committerjasonwucj <jasonwucj@138bc75d-0d04-0410-961f-82ee72b054a4>2014-09-03 10:09:14 +0000
commit4ef804449fc8dc20d3680a547460c44297e67548 (patch)
tree3b4e9ae67fd1e063070cf66b91e128dfb9764157 /gcc/config/nds32/nds32.c
parent6c1b7455691f2c133f99c2dee0fad573e8865a0b (diff)
downloadgcc-4ef804449fc8dc20d3680a547460c44297e67548.tar.gz
[NDS32] Emit stack push instructions for varargs at prologue stage and
emit stack adjustment instructions for varargs at epilogue stage. -- Note that we do not need to handle it in v3push/v3pop prologue/epilogue expanding because we do not apply v3push/v3pop for variadic function. * config/nds32/nds32.c (nds32_expand_prologue): Emit stack push instructions for varargs implementation. (nds32_expand_epilogue): Emit stack adjustment instructions for varargs implementation. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@214867 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/nds32/nds32.c')
-rw-r--r--gcc/config/nds32/nds32.c81
1 files changed, 80 insertions, 1 deletions
diff --git a/gcc/config/nds32/nds32.c b/gcc/config/nds32/nds32.c
index d76d8251db3..d2890dc3d27 100644
--- a/gcc/config/nds32/nds32.c
+++ b/gcc/config/nds32/nds32.c
@@ -2788,6 +2788,35 @@ nds32_expand_prologue (void)
The result will be in cfun->machine. */
nds32_compute_stack_frame ();
+ /* If this is a variadic function, first we need to push argument
+ registers that hold the unnamed argument value. */
+ if (cfun->machine->va_args_size != 0)
+ {
+ Rb = gen_rtx_REG (SImode, cfun->machine->va_args_first_regno);
+ Re = gen_rtx_REG (SImode, cfun->machine->va_args_last_regno);
+ /* No need to push $fp, $gp, or $lp, so use GEN_INT(0). */
+ nds32_emit_stack_push_multiple (Rb, Re, GEN_INT (0));
+
+ /* We may also need to adjust stack pointer for padding bytes
+ because varargs may cause $sp not 8-byte aligned. */
+ if (cfun->machine->va_args_area_padding_bytes)
+ {
+ /* Generate sp adjustment instruction. */
+ sp_adjust = cfun->machine->va_args_area_padding_bytes;
+ sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (-1 * sp_adjust));
+
+ /* Emit rtx into instructions list and receive INSN rtx form. */
+ sp_adjust_insn = emit_insn (sp_adjust_insn);
+
+ /* The insn rtx 'sp_adjust_insn' will change frame layout.
+ We need to use RTX_FRAME_RELATED_P so that GCC is able to
+ generate CFI (Call Frame Information) stuff. */
+ RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
+ }
+ }
+
/* If the function is 'naked',
we do not have to generate prologue code fragment. */
if (cfun->machine->naked_p)
@@ -2887,9 +2916,32 @@ nds32_expand_epilogue (void)
emit_insn (gen_blockage ());
/* If the function is 'naked', we do not have to generate
- epilogue code fragment BUT 'ret' instruction. */
+ epilogue code fragment BUT 'ret' instruction.
+ However, if this function is also a variadic function,
+ we need to create adjust stack pointer before 'ret' instruction. */
if (cfun->machine->naked_p)
{
+ /* If this is a variadic function, we do not have to restore argument
+ registers but need to adjust stack pointer back to previous stack
+ frame location before return. */
+ if (cfun->machine->va_args_size != 0)
+ {
+ /* Generate sp adjustment instruction.
+ We need to consider padding bytes here. */
+ sp_adjust = cfun->machine->va_args_size
+ + cfun->machine->va_args_area_padding_bytes;
+ sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (sp_adjust));
+ /* Emit rtx into instructions list and receive INSN rtx form. */
+ sp_adjust_insn = emit_insn (sp_adjust_insn);
+
+ /* The insn rtx 'sp_adjust_insn' will change frame layout.
+ We need to use RTX_FRAME_RELATED_P so that GCC is able to
+ generate CFI (Call Frame Information) stuff. */
+ RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
+ }
+
/* Generate return instruction by using
unspec_volatile_func_return pattern.
Make sure this instruction is after gen_blockage().
@@ -2916,6 +2968,9 @@ nds32_expand_epilogue (void)
GEN_INT (-1 * sp_adjust));
/* Emit rtx into instructions list and receive INSN rtx form. */
sp_adjust_insn = emit_insn (sp_adjust_insn);
+
+ /* The insn rtx 'sp_adjust_insn' will change frame layout. */
+ RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
}
else
{
@@ -2944,6 +2999,9 @@ nds32_expand_epilogue (void)
GEN_INT (sp_adjust));
/* Emit rtx into instructions list and receive INSN rtx form. */
sp_adjust_insn = emit_insn (sp_adjust_insn);
+
+ /* The insn rtx 'sp_adjust_insn' will change frame layout. */
+ RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
}
}
@@ -2972,6 +3030,27 @@ nds32_expand_epilogue (void)
nds32_emit_stack_pop_multiple (Rb, Re, GEN_INT (en4_const));
}
+ /* If this is a variadic function, we do not have to restore argument
+ registers but need to adjust stack pointer back to previous stack
+ frame location before return. */
+ if (cfun->machine->va_args_size != 0)
+ {
+ /* Generate sp adjustment instruction.
+ We need to consider padding bytes here. */
+ sp_adjust = cfun->machine->va_args_size
+ + cfun->machine->va_args_area_padding_bytes;
+ sp_adjust_insn = gen_addsi3 (stack_pointer_rtx,
+ stack_pointer_rtx,
+ GEN_INT (sp_adjust));
+ /* Emit rtx into instructions list and receive INSN rtx form. */
+ sp_adjust_insn = emit_insn (sp_adjust_insn);
+
+ /* The insn rtx 'sp_adjust_insn' will change frame layout.
+ We need to use RTX_FRAME_RELATED_P so that GCC is able to
+ generate CFI (Call Frame Information) stuff. */
+ RTX_FRAME_RELATED_P (sp_adjust_insn) = 1;
+ }
+
/* Generate return instruction by using
unspec_volatile_func_return pattern. */
emit_insn (gen_unspec_volatile_func_return ());