OSDN Git Service

* config/sh/sh.c (push_regs): Emit movml for interrupt handler
authorkkojima <kkojima@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 27 Aug 2010 23:29:41 +0000 (23:29 +0000)
committerkkojima <kkojima@138bc75d-0d04-0410-961f-82ee72b054a4>
Fri, 27 Aug 2010 23:29:41 +0000 (23:29 +0000)
when possible.
(sh_expand_epilogue): Likewise.
* config/sh/sh.md (movml_push_banked): New insn.
(movml_pop_banked): Likewise.
* gcc.dg/attr-isr.c: Skip test for -m2a.  Don't run on sh2a*-*-*.

git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@163602 138bc75d-0d04-0410-961f-82ee72b054a4

gcc/ChangeLog
gcc/config/sh/sh.c
gcc/config/sh/sh.md
gcc/testsuite/ChangeLog
gcc/testsuite/gcc.dg/attr-isr.c

index 07a97f5..bce04c4 100644 (file)
@@ -1,3 +1,12 @@
+2010-08-27  Naveen H.S  <naveen.S@kpitcummins.com>
+           Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * config/sh/sh.c (push_regs): Emit movml for interrupt handler
+       when possible.
+       (sh_expand_epilogue): Likewise.
+       * config/sh/sh.md (movml_push_banked): New insn.
+       (movml_pop_banked): Likewise.
+
 2010-08-28  Bernd Schmidt  <bernds@codesourcery.com>
 
        * genautomata.c (gen_regexp_repeat, gen_regexp_allof,
index 8ace99c..d693351 100644 (file)
@@ -6407,9 +6407,50 @@ push_regs (HARD_REG_SET *mask, int interrupt_handler)
 
   /* Push banked registers last to improve delay slot opportunities.  */
   if (interrupt_handler)
-    for (i = FIRST_BANKED_REG; i <= LAST_BANKED_REG; i++)
-      if (TEST_HARD_REG_BIT (*mask, i))
-       push (i);
+    {
+      bool use_movml = false;
+
+      if (TARGET_SH2A)
+       {
+         unsigned int count = 0;
+
+         for (i = FIRST_BANKED_REG; i <= LAST_BANKED_REG; i++)
+           if (TEST_HARD_REG_BIT (*mask, i))
+             count++;
+           else
+             break;
+
+         /* Use movml when all banked registers are pushed.  */
+         if (count == LAST_BANKED_REG - FIRST_BANKED_REG + 1)
+           use_movml = true;
+       }
+
+      if (use_movml)
+       {
+         rtx x, mem, reg, set;
+         rtx sp_reg = gen_rtx_REG (SImode, STACK_POINTER_REGNUM);
+
+         /* We must avoid scheduling multiple store insn with another
+            insns.  */
+         emit_insn (gen_blockage ());
+         x = gen_movml_push_banked (sp_reg);
+         x = frame_insn (x);
+         for (i = FIRST_BANKED_REG; i <= LAST_BANKED_REG; i++)
+           {
+             mem = gen_rtx_MEM (SImode, plus_constant (sp_reg, i * 4));
+             reg = gen_rtx_REG (SImode, i);
+             add_reg_note (x, REG_CFA_OFFSET, gen_rtx_SET (SImode, mem, reg));
+           }
+
+         set = gen_rtx_SET (SImode, sp_reg, plus_constant (sp_reg, - 32));
+         add_reg_note (x, REG_CFA_ADJUST_CFA, set);
+         emit_insn (gen_blockage ());
+       }
+      else
+       for (i = FIRST_BANKED_REG; i <= LAST_BANKED_REG; i++)
+         if (TEST_HARD_REG_BIT (*mask, i))
+           push (i);
+    }
 
   /* Don't push PR register for an ISR with RESBANK attribute assigned.  */
   if (TEST_HARD_REG_BIT (*mask, PR_REG) && !sh_cfun_resbank_handler_p ())
@@ -7347,9 +7388,37 @@ sh_expand_epilogue (bool sibcall_p)
         delay slot. RTE switches banks before the ds instruction.  */
       if (current_function_interrupt)
        {
-         for (i = LAST_BANKED_REG; i >= FIRST_BANKED_REG; i--)
-           if (TEST_HARD_REG_BIT (live_regs_mask, i))
-             pop (i);
+         bool use_movml = false;
+
+         if (TARGET_SH2A)
+           {
+             unsigned int count = 0;
+
+             for (i = FIRST_BANKED_REG; i <= LAST_BANKED_REG; i++)
+               if (TEST_HARD_REG_BIT (live_regs_mask, i))
+                 count++;
+               else
+                 break;
+
+             /* Use movml when all banked register are poped.  */
+             if (count == LAST_BANKED_REG - FIRST_BANKED_REG + 1)
+               use_movml = true;
+           }
+
+         if (use_movml)
+           {
+             rtx sp_reg = gen_rtx_REG (SImode, STACK_POINTER_REGNUM);
+
+             /* We must avoid scheduling multiple load insn with another
+                insns.  */
+             emit_insn (gen_blockage ());
+             emit_insn (gen_movml_pop_banked (sp_reg));
+             emit_insn (gen_blockage ());
+           }
+         else
+           for (i = LAST_BANKED_REG; i >= FIRST_BANKED_REG; i--)
+             if (TEST_HARD_REG_BIT (live_regs_mask, i))
+               pop (i);
 
          last_reg = FIRST_PSEUDO_REGISTER - LAST_BANKED_REG - 1;
        }
index 495e151..dd63f63 100644 (file)
@@ -9216,6 +9216,39 @@ mov.l\\t1f,r0\\n\\
   ""
   [(set_attr "length" "0")])
 \f
+;; Define movml instructions for SH2A target.  Currently they are
+;; used to push and pop all banked registers only.
+
+(define_insn "movml_push_banked"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+         (plus (match_dup 0) (const_int -32)))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 28))) (reg:SI R7_REG))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 24))) (reg:SI R6_REG))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 20))) (reg:SI R5_REG))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 16))) (reg:SI R4_REG))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 12))) (reg:SI R3_REG))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 8))) (reg:SI R2_REG))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 4))) (reg:SI R1_REG))
+   (set (mem:SI (plus:SI (match_dup 0) (const_int 0))) (reg:SI R0_REG))]
+  "TARGET_SH2A && REGNO (operands[0]) == 15"
+  "movml.l\tr7,@-r15"
+  [(set_attr "in_delay_slot" "no")])
+
+(define_insn "movml_pop_banked"
+  [(set (match_operand:SI 0 "register_operand" "=r")
+         (plus (match_dup 0) (const_int 32)))
+   (set (reg:SI R0_REG) (mem:SI (plus:SI (match_dup 0) (const_int -32))))
+   (set (reg:SI R1_REG) (mem:SI (plus:SI (match_dup 0) (const_int -28))))
+   (set (reg:SI R2_REG) (mem:SI (plus:SI (match_dup 0) (const_int -24))))
+   (set (reg:SI R3_REG) (mem:SI (plus:SI (match_dup 0) (const_int -20))))
+   (set (reg:SI R4_REG) (mem:SI (plus:SI (match_dup 0) (const_int -16))))
+   (set (reg:SI R5_REG) (mem:SI (plus:SI (match_dup 0) (const_int -12))))
+   (set (reg:SI R6_REG) (mem:SI (plus:SI (match_dup 0) (const_int -8))))
+   (set (reg:SI R7_REG) (mem:SI (plus:SI (match_dup 0) (const_int -4))))]
+  "TARGET_SH2A && REGNO (operands[0]) == 15"
+  "movml.l\t@r15+,r7"
+  [(set_attr "in_delay_slot" "no")])
+\f
 ;; ------------------------------------------------------------------------
 ;; Scc instructions
 ;; ------------------------------------------------------------------------
index 959f3fd..3cf65f3 100644 (file)
@@ -1,3 +1,8 @@
+2010-08-27  Naveen H.S  <naveen.S@kpitcummins.com>
+           Kaz Kojima  <kkojima@gcc.gnu.org>
+
+       * gcc.dg/attr-isr.c: Skip test for -m2a.  Don't run on sh2a*-*-*.
+
 2010-08-23  Michael Meissner  <meissner@linux.vnet.ibm.com>
 
        * gcc.target/powerpc/ppc-fpconv-1.c: New test for integer to
index 3e86631..1373c15 100644 (file)
@@ -1,4 +1,5 @@
-/* { dg-do compile { target { { sh-*-* sh[1234ble]*-*-* } && nonpic } } } */
+/* { dg-do compile { target { { { sh-*-* sh[1234ble]*-*-* } && { ! sh2a*-*-* } } && nonpic } } } */
+/* { dg-skip-if "" { "sh*-*-*" } { "-m2a*" } { "" } } */
 /* { dg-options "-O" } */
 extern void foo ();