aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNaveen H.S <naveen.S@kpitcummins.com>2010-08-27 23:29:41 +0000
committerKaz Kojima <kkojima@gcc.gnu.org>2010-08-27 23:29:41 +0000
commit91a19652f8199bfad17f77d91e9f3bfe24efc5f0 (patch)
tree7c71ab51c02bd0b1b964e45c1e9be52994d291db /gcc
parentf8045c4158f628673fdb4b1b42cf210bd516b486 (diff)
downloadgcc-91a19652f8199bfad17f77d91e9f3bfe24efc5f0.zip
gcc-91a19652f8199bfad17f77d91e9f3bfe24efc5f0.tar.gz
gcc-91a19652f8199bfad17f77d91e9f3bfe24efc5f0.tar.bz2
sh.c (push_regs): Emit movml for interrupt handler when possible.
* 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. * gcc.dg/attr-isr.c: Skip test for -m2a. Don't run on sh2a*-*-*. Co-Authored-By: Kaz Kojima <kkojima@gcc.gnu.org> From-SVN: r163602
Diffstat (limited to 'gcc')
-rw-r--r--gcc/ChangeLog9
-rw-r--r--gcc/config/sh/sh.c81
-rw-r--r--gcc/config/sh/sh.md33
-rw-r--r--gcc/testsuite/ChangeLog5
-rw-r--r--gcc/testsuite/gcc.dg/attr-isr.c3
5 files changed, 124 insertions, 7 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index 07a97f5..bce04c4 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -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,
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 8ace99c..d693351 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -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;
}
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index 495e151..dd63f63 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -9216,6 +9216,39 @@ mov.l\\t1f,r0\\n\\
""
[(set_attr "length" "0")])
+;; 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")])
+
;; ------------------------------------------------------------------------
;; Scc instructions
;; ------------------------------------------------------------------------
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index 959f3fd..3cf65f3 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -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
diff --git a/gcc/testsuite/gcc.dg/attr-isr.c b/gcc/testsuite/gcc.dg/attr-isr.c
index 3e86631..1373c15 100644
--- a/gcc/testsuite/gcc.dg/attr-isr.c
+++ b/gcc/testsuite/gcc.dg/attr-isr.c
@@ -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 ();