aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/nds32
diff options
context:
space:
mode:
authorjasonwucj <jasonwucj@138bc75d-0d04-0410-961f-82ee72b054a4>2014-09-03 08:57:02 +0000
committerjasonwucj <jasonwucj@138bc75d-0d04-0410-961f-82ee72b054a4>2014-09-03 08:57:02 +0000
commit775c6f73c5399491b379731d99d7dca53212d9a4 (patch)
tree3d780b782ef18d1f3a43d38cf23c58bca8ec5cfb /gcc/config/nds32
parenta80047437f1d82653fa5507126a05db37e1711cc (diff)
[NDS32] Consider varargs situation when creating stack operation assembly code.
-- In fact, we only need to take care of 'push.s' situation, because we have to push all the nameless arguments into stack. -- We do not have to use 'pop.s' to restore them back to registers, because we can just adjust stack pointer to set frame location. This operation should be done in epilogue expanding. -- Because 'pop25' instruction also performs return operation, we will not use v3push/v3pop on isr and vararg functions. Therefore, their instruction length should be 4 bytes. * config/nds32/nds32-md-auxiliary.c (nds32_output_stack_push): Check rtx for varargs implementation. (nds32_output_stack_pop): Likewise. * config/nds32/nds32-protos.h: Have a rtx argument for nds32_output_stack_push and nds32_output_stack_pop. * config/nds32/nds32.md: Likewise. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@214856 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/nds32')
-rw-r--r--gcc/config/nds32/nds32-md-auxiliary.c61
-rw-r--r--gcc/config/nds32/nds32-protos.h4
-rw-r--r--gcc/config/nds32/nds32.md12
3 files changed, 57 insertions, 20 deletions
diff --git a/gcc/config/nds32/nds32-md-auxiliary.c b/gcc/config/nds32/nds32-md-auxiliary.c
index 047417cf274..85a3a301bcd 100644
--- a/gcc/config/nds32/nds32-md-auxiliary.c
+++ b/gcc/config/nds32/nds32-md-auxiliary.c
@@ -563,17 +563,44 @@ nds32_output_32bit_load_s (rtx *operands, int byte)
/* Function to output stack push operation.
We need to deal with normal stack push multiple or stack v3push. */
const char *
-nds32_output_stack_push (void)
+nds32_output_stack_push (rtx par_rtx)
{
/* A string pattern for output_asm_insn(). */
char pattern[100];
/* The operands array which will be used in output_asm_insn(). */
rtx operands[3];
+ /* Pick up varargs first regno and last regno for further use. */
+ int rb_va_args = cfun->machine->va_args_first_regno;
+ int re_va_args = cfun->machine->va_args_last_regno;
+ int last_argument_regno = NDS32_FIRST_GPR_REGNUM
+ + NDS32_MAX_GPR_REGS_FOR_ARGS
+ - 1;
/* Pick up callee-saved first regno and last regno for further use. */
- int rb_regno = cfun->machine->callee_saved_regs_first_regno;
- int re_regno = cfun->machine->callee_saved_regs_last_regno;
+ int rb_callee_saved = cfun->machine->callee_saved_regs_first_regno;
+ int re_callee_saved = cfun->machine->callee_saved_regs_last_regno;
- if (TARGET_V3PUSH)
+ /* First we need to check if we are pushing argument registers not used
+ for the named arguments. If so, we have to create 'smw.adm' (push.s)
+ instruction. */
+ if (reg_mentioned_p (gen_rtx_REG (SImode, last_argument_regno), par_rtx))
+ {
+ /* Set operands[0] and operands[1]. */
+ operands[0] = gen_rtx_REG (SImode, rb_va_args);
+ operands[1] = gen_rtx_REG (SImode, re_va_args);
+ /* Create assembly code pattern: "Rb, Re, { }". */
+ snprintf (pattern, sizeof (pattern), "push.s\t%s", "%0, %1, { }");
+ /* We use output_asm_insn() to output assembly code by ourself. */
+ output_asm_insn (pattern, operands);
+ return "";
+ }
+
+ /* If we step here, we are going to do v3push or multiple push operation. */
+
+ /* The v3push/v3pop instruction should only be applied on
+ none-isr and none-variadic function. */
+ if (TARGET_V3PUSH
+ && !nds32_isr_function_p (current_function_decl)
+ && (cfun->machine->va_args_size == 0))
{
/* For stack v3push:
operands[0]: Re
@@ -583,7 +610,7 @@ nds32_output_stack_push (void)
int sp_adjust;
/* Set operands[0]. */
- operands[0] = gen_rtx_REG (SImode, re_regno);
+ operands[0] = gen_rtx_REG (SImode, re_callee_saved);
/* Check if we can generate 'push25 Re,imm8u',
otherwise, generate 'push25 Re,0'. */
@@ -611,8 +638,8 @@ nds32_output_stack_push (void)
int push_en4_only_p = 0;
/* Set operands[0] and operands[1]. */
- operands[0] = gen_rtx_REG (SImode, rb_regno);
- operands[1] = gen_rtx_REG (SImode, re_regno);
+ operands[0] = gen_rtx_REG (SImode, rb_callee_saved);
+ operands[1] = gen_rtx_REG (SImode, re_callee_saved);
/* 'smw.adm $sp,[$sp],$sp,0' means push nothing. */
if (!cfun->machine->fp_size
@@ -650,17 +677,23 @@ nds32_output_stack_push (void)
/* Function to output stack pop operation.
We need to deal with normal stack pop multiple or stack v3pop. */
const char *
-nds32_output_stack_pop (void)
+nds32_output_stack_pop (rtx par_rtx ATTRIBUTE_UNUSED)
{
/* A string pattern for output_asm_insn(). */
char pattern[100];
/* The operands array which will be used in output_asm_insn(). */
rtx operands[3];
/* Pick up callee-saved first regno and last regno for further use. */
- int rb_regno = cfun->machine->callee_saved_regs_first_regno;
- int re_regno = cfun->machine->callee_saved_regs_last_regno;
+ int rb_callee_saved = cfun->machine->callee_saved_regs_first_regno;
+ int re_callee_saved = cfun->machine->callee_saved_regs_last_regno;
+
+ /* If we step here, we are going to do v3pop or multiple pop operation. */
- if (TARGET_V3PUSH)
+ /* The v3push/v3pop instruction should only be applied on
+ none-isr and none-variadic function. */
+ if (TARGET_V3PUSH
+ && !nds32_isr_function_p (current_function_decl)
+ && (cfun->machine->va_args_size == 0))
{
/* For stack v3pop:
operands[0]: Re
@@ -670,7 +703,7 @@ nds32_output_stack_pop (void)
int sp_adjust;
/* Set operands[0]. */
- operands[0] = gen_rtx_REG (SImode, re_regno);
+ operands[0] = gen_rtx_REG (SImode, re_callee_saved);
/* Check if we can generate 'pop25 Re,imm8u',
otherwise, generate 'pop25 Re,0'.
@@ -704,8 +737,8 @@ nds32_output_stack_pop (void)
int pop_en4_only_p = 0;
/* Set operands[0] and operands[1]. */
- operands[0] = gen_rtx_REG (SImode, rb_regno);
- operands[1] = gen_rtx_REG (SImode, re_regno);
+ operands[0] = gen_rtx_REG (SImode, rb_callee_saved);
+ operands[1] = gen_rtx_REG (SImode, re_callee_saved);
/* 'lmw.bim $sp,[$sp],$sp,0' means pop nothing. */
if (!cfun->machine->fp_size
diff --git a/gcc/config/nds32/nds32-protos.h b/gcc/config/nds32/nds32-protos.h
index e57674a8311..8984ea75977 100644
--- a/gcc/config/nds32/nds32-protos.h
+++ b/gcc/config/nds32/nds32-protos.h
@@ -117,8 +117,8 @@ extern const char *nds32_output_32bit_load_s (rtx *, int);
/* Auxiliary functions to output stack push/pop instruction. */
-extern const char *nds32_output_stack_push (void);
-extern const char *nds32_output_stack_pop (void);
+extern const char *nds32_output_stack_push (rtx);
+extern const char *nds32_output_stack_pop (rtx);
/* Auxiliary functions to decide output alignment or not. */
diff --git a/gcc/config/nds32/nds32.md b/gcc/config/nds32/nds32.md
index da3a97a538f..ccf33d9861e 100644
--- a/gcc/config/nds32/nds32.md
+++ b/gcc/config/nds32/nds32.md
@@ -2025,12 +2025,14 @@ create_template:
])]
""
{
- return nds32_output_stack_push ();
+ return nds32_output_stack_push (operands[0]);
}
[(set_attr "type" "misc")
(set_attr "enabled" "1")
(set (attr "length")
- (if_then_else (match_test "TARGET_V3PUSH")
+ (if_then_else (match_test "TARGET_V3PUSH
+ && !nds32_isr_function_p (cfun->decl)
+ && (cfun->machine->va_args_size == 0)")
(const_int 2)
(const_int 4)))])
@@ -2045,12 +2047,14 @@ create_template:
])]
""
{
- return nds32_output_stack_pop ();
+ return nds32_output_stack_pop (operands[0]);
}
[(set_attr "type" "misc")
(set_attr "enabled" "1")
(set (attr "length")
- (if_then_else (match_test "TARGET_V3PUSH")
+ (if_then_else (match_test "TARGET_V3PUSH
+ && !nds32_isr_function_p (cfun->decl)
+ && (cfun->machine->va_args_size == 0)")
(const_int 2)
(const_int 4)))])