From 6f3d3f9c7c6db3468b8d0269bbca946df2c48d5f Mon Sep 17 00:00:00 2001 From: Chung-Ju Wu Date: Wed, 3 Sep 2014 08:57:02 +0000 Subject: [PATCH] [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 --- gcc/ChangeLog | 9 ++++++ gcc/config/nds32/nds32-md-auxiliary.c | 61 +++++++++++++++++++++++++++-------- gcc/config/nds32/nds32-protos.h | 4 +-- gcc/config/nds32/nds32.md | 12 ++++--- 4 files changed, 66 insertions(+), 20 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index aa65d6a..a8d27bf 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,5 +1,14 @@ 2014-09-03 Chung-Ju Wu + * 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 + * config/nds32/nds32-isr.c (nds32_isr_function_p): Define new function to check if FUNC is an interrupt service routine. * config/nds32/nds32-protos.h (nds32_isr_function_p): Declaration. diff --git a/gcc/config/nds32/nds32-md-auxiliary.c b/gcc/config/nds32/nds32-md-auxiliary.c index 047417c..85a3a30 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 e57674a..8984ea7 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 da3a97a..ccf33d9 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)))]) -- 2.7.4