From 1b5c01d5dc2b81457773ec900d80c4fee8bb7857 Mon Sep 17 00:00:00 2001 From: kkojima Date: Fri, 27 Aug 2010 23:29:41 +0000 Subject: [PATCH] * 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*-*-*. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@163602 138bc75d-0d04-0410-961f-82ee72b054a4 --- gcc/ChangeLog | 9 +++++ gcc/config/sh/sh.c | 81 ++++++++++++++++++++++++++++++++++++++--- gcc/config/sh/sh.md | 33 +++++++++++++++++ gcc/testsuite/ChangeLog | 5 +++ gcc/testsuite/gcc.dg/attr-isr.c | 3 +- 5 files changed, 124 insertions(+), 7 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 07a97f52f9b..bce04c43052 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,12 @@ +2010-08-27 Naveen H.S + Kaz Kojima + + * 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 * genautomata.c (gen_regexp_repeat, gen_regexp_allof, diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index 8ace99c732c..d693351ecb4 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 495e15105d2..dd63f63136f 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 959f3fdcf37..3cf65f34ae2 100644 --- a/gcc/testsuite/ChangeLog +++ b/gcc/testsuite/ChangeLog @@ -1,3 +1,8 @@ +2010-08-27 Naveen H.S + Kaz Kojima + + * gcc.dg/attr-isr.c: Skip test for -m2a. Don't run on sh2a*-*-*. + 2010-08-23 Michael Meissner * 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 3e866317311..1373c15f44a 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 (); -- 2.11.4.GIT