[NDS32] Consider varargs situation when creating stack operation assembly code.
authorChung-Ju Wu <jasonwucj@gmail.com>
Wed, 3 Sep 2014 08:57:02 +0000 (08:57 +0000)
committerChung-Ju Wu <jasonwucj@gcc.gnu.org>
Wed, 3 Sep 2014 08:57:02 +0000 (08:57 +0000)
  -- 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
gcc/config/nds32/nds32-md-auxiliary.c
gcc/config/nds32/nds32-protos.h
gcc/config/nds32/nds32.md

index aa65d6a890a494ddd62e15eac46d9acb475186a0..a8d27bf6ac1b591da139a12e34b978d2c3001638 100644 (file)
@@ -1,3 +1,12 @@
+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
index 047417cf27475b4af27308309d13259c76baedc0..85a3a301bcd15c4abd9d4d217674d2698013813f 100644 (file)
@@ -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
index e57674a83114207bd78e12446bfb16616ed457bf..8984ea759773f9b919f77e680bd79f5681782d66 100644 (file)
@@ -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.  */
 
index da3a97a538feac506084d5064f2d4285c05bd3b0..ccf33d9861ed52ab6c0801575090e980f69fb2ce 100644 (file)
@@ -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)))])