Commit 6f3d3f9c by Chung-Ju Wu Committed by Chung-Ju Wu

[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.

From-SVN: r214856
parent 126b11c6
2014-09-03 Chung-Ju Wu <jasonwucj@gmail.com> 2014-09-03 Chung-Ju Wu <jasonwucj@gmail.com>
* 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.
2014-09-03 Chung-Ju Wu <jasonwucj@gmail.com>
* config/nds32/nds32-isr.c (nds32_isr_function_p): Define new function * config/nds32/nds32-isr.c (nds32_isr_function_p): Define new function
to check if FUNC is an interrupt service routine. to check if FUNC is an interrupt service routine.
* config/nds32/nds32-protos.h (nds32_isr_function_p): Declaration. * config/nds32/nds32-protos.h (nds32_isr_function_p): Declaration.
...@@ -563,17 +563,44 @@ nds32_output_32bit_load_s (rtx *operands, int byte) ...@@ -563,17 +563,44 @@ nds32_output_32bit_load_s (rtx *operands, int byte)
/* Function to output stack push operation. /* Function to output stack push operation.
We need to deal with normal stack push multiple or stack v3push. */ We need to deal with normal stack push multiple or stack v3push. */
const char * const char *
nds32_output_stack_push (void) nds32_output_stack_push (rtx par_rtx)
{ {
/* A string pattern for output_asm_insn(). */ /* A string pattern for output_asm_insn(). */
char pattern[100]; char pattern[100];
/* The operands array which will be used in output_asm_insn(). */ /* The operands array which will be used in output_asm_insn(). */
rtx operands[3]; 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. */ /* Pick up callee-saved first regno and last regno for further use. */
int rb_regno = cfun->machine->callee_saved_regs_first_regno; int rb_callee_saved = cfun->machine->callee_saved_regs_first_regno;
int re_regno = cfun->machine->callee_saved_regs_last_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: /* For stack v3push:
operands[0]: Re operands[0]: Re
...@@ -583,7 +610,7 @@ nds32_output_stack_push (void) ...@@ -583,7 +610,7 @@ nds32_output_stack_push (void)
int sp_adjust; int sp_adjust;
/* Set operands[0]. */ /* 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', /* Check if we can generate 'push25 Re,imm8u',
otherwise, generate 'push25 Re,0'. */ otherwise, generate 'push25 Re,0'. */
...@@ -611,8 +638,8 @@ nds32_output_stack_push (void) ...@@ -611,8 +638,8 @@ nds32_output_stack_push (void)
int push_en4_only_p = 0; int push_en4_only_p = 0;
/* Set operands[0] and operands[1]. */ /* Set operands[0] and operands[1]. */
operands[0] = gen_rtx_REG (SImode, rb_regno); operands[0] = gen_rtx_REG (SImode, rb_callee_saved);
operands[1] = gen_rtx_REG (SImode, re_regno); operands[1] = gen_rtx_REG (SImode, re_callee_saved);
/* 'smw.adm $sp,[$sp],$sp,0' means push nothing. */ /* 'smw.adm $sp,[$sp],$sp,0' means push nothing. */
if (!cfun->machine->fp_size if (!cfun->machine->fp_size
...@@ -650,17 +677,23 @@ nds32_output_stack_push (void) ...@@ -650,17 +677,23 @@ nds32_output_stack_push (void)
/* Function to output stack pop operation. /* Function to output stack pop operation.
We need to deal with normal stack pop multiple or stack v3pop. */ We need to deal with normal stack pop multiple or stack v3pop. */
const char * const char *
nds32_output_stack_pop (void) nds32_output_stack_pop (rtx par_rtx ATTRIBUTE_UNUSED)
{ {
/* A string pattern for output_asm_insn(). */ /* A string pattern for output_asm_insn(). */
char pattern[100]; char pattern[100];
/* The operands array which will be used in output_asm_insn(). */ /* The operands array which will be used in output_asm_insn(). */
rtx operands[3]; rtx operands[3];
/* Pick up callee-saved first regno and last regno for further use. */ /* Pick up callee-saved first regno and last regno for further use. */
int rb_regno = cfun->machine->callee_saved_regs_first_regno; int rb_callee_saved = cfun->machine->callee_saved_regs_first_regno;
int re_regno = cfun->machine->callee_saved_regs_last_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: /* For stack v3pop:
operands[0]: Re operands[0]: Re
...@@ -670,7 +703,7 @@ nds32_output_stack_pop (void) ...@@ -670,7 +703,7 @@ nds32_output_stack_pop (void)
int sp_adjust; int sp_adjust;
/* Set operands[0]. */ /* 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', /* Check if we can generate 'pop25 Re,imm8u',
otherwise, generate 'pop25 Re,0'. otherwise, generate 'pop25 Re,0'.
...@@ -704,8 +737,8 @@ nds32_output_stack_pop (void) ...@@ -704,8 +737,8 @@ nds32_output_stack_pop (void)
int pop_en4_only_p = 0; int pop_en4_only_p = 0;
/* Set operands[0] and operands[1]. */ /* Set operands[0] and operands[1]. */
operands[0] = gen_rtx_REG (SImode, rb_regno); operands[0] = gen_rtx_REG (SImode, rb_callee_saved);
operands[1] = gen_rtx_REG (SImode, re_regno); operands[1] = gen_rtx_REG (SImode, re_callee_saved);
/* 'lmw.bim $sp,[$sp],$sp,0' means pop nothing. */ /* 'lmw.bim $sp,[$sp],$sp,0' means pop nothing. */
if (!cfun->machine->fp_size if (!cfun->machine->fp_size
......
...@@ -117,8 +117,8 @@ extern const char *nds32_output_32bit_load_s (rtx *, int); ...@@ -117,8 +117,8 @@ extern const char *nds32_output_32bit_load_s (rtx *, int);
/* Auxiliary functions to output stack push/pop instruction. */ /* Auxiliary functions to output stack push/pop instruction. */
extern const char *nds32_output_stack_push (void); extern const char *nds32_output_stack_push (rtx);
extern const char *nds32_output_stack_pop (void); extern const char *nds32_output_stack_pop (rtx);
/* Auxiliary functions to decide output alignment or not. */ /* Auxiliary functions to decide output alignment or not. */
......
...@@ -2025,12 +2025,14 @@ create_template: ...@@ -2025,12 +2025,14 @@ create_template:
])] ])]
"" ""
{ {
return nds32_output_stack_push (); return nds32_output_stack_push (operands[0]);
} }
[(set_attr "type" "misc") [(set_attr "type" "misc")
(set_attr "enabled" "1") (set_attr "enabled" "1")
(set (attr "length") (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 2)
(const_int 4)))]) (const_int 4)))])
...@@ -2045,12 +2047,14 @@ create_template: ...@@ -2045,12 +2047,14 @@ create_template:
])] ])]
"" ""
{ {
return nds32_output_stack_pop (); return nds32_output_stack_pop (operands[0]);
} }
[(set_attr "type" "misc") [(set_attr "type" "misc")
(set_attr "enabled" "1") (set_attr "enabled" "1")
(set (attr "length") (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 2)
(const_int 4)))]) (const_int 4)))])
......
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