aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorChristian Bruel <christian.bruel@st.com>2007-06-21 10:58:53 +0200
committerChristian Bruel <chrbr@gcc.gnu.org>2007-06-21 10:58:53 +0200
commit5c7cafa8dc040ac9573f81ce9f9cdd6111ca83a4 (patch)
tree8d7710b8980080d3eb483bf37da36f82da80d011
parent86488aa376bcc3c3e34acf895039236e7f107c94 (diff)
downloadgcc-5c7cafa8dc040ac9573f81ce9f9cdd6111ca83a4.zip
gcc-5c7cafa8dc040ac9573f81ce9f9cdd6111ca83a4.tar.gz
gcc-5c7cafa8dc040ac9573f81ce9f9cdd6111ca83a4.tar.bz2
svn ci -m "introduce bank[0,1] registers and fix rte delay slot scheduling"
2007-06-21 Christian Bruel <christian.bruel@st.com> * config/sh/sh-protos.h (sh_loads_bankedreg_p): Declare. * config/sh/sh.c (sh_loads_bankedreg_p): New function. (push_regs): Changed saving order or banked registers. (sh_expand_epilogue): Likewise. * config/sh/sh.h (BANKED_REGISTER_P): New macro. (FIRST_BANKED_REG): Likewise. (LAST_BANKED_REG): Likewise. * config/sh/sh.md (banked) New attribute. (in_delay_slot): Check banked attribute. 2007-06-21 Christian Bruel <christian.bruel@st.com> * gcc.dg/attr-isr.c: Test delay slot content. From-SVN: r125914
-rw-r--r--gcc/ChangeLog12
-rw-r--r--gcc/config/sh/sh-protos.h1
-rw-r--r--gcc/config/sh/sh.c45
-rw-r--r--gcc/config/sh/sh.h10
-rw-r--r--gcc/config/sh/sh.md11
-rw-r--r--gcc/testsuite/ChangeLog4
-rw-r--r--gcc/testsuite/gcc.dg/attr-isr.c1
7 files changed, 78 insertions, 6 deletions
diff --git a/gcc/ChangeLog b/gcc/ChangeLog
index aaf940e..212090b 100644
--- a/gcc/ChangeLog
+++ b/gcc/ChangeLog
@@ -1,3 +1,15 @@
+2007-06-21 Christian Bruel <christian.bruel@st.com>
+
+ * config/sh/sh-protos.h (sh_loads_bankedreg_p): Declare.
+ * config/sh/sh.c (sh_loads_bankedreg_p): New function.
+ (push_regs): Changed saving order or banked registers.
+ (sh_expand_epilogue): Likewise.
+ * config/sh/sh.h (BANKED_REGISTER_P): New macro.
+ (FIRST_BANKED_REG): Likewise.
+ (LAST_BANKED_REG): Likewise.
+ * config/sh/sh.md (banked) New attribute.
+ (in_delay_slot): Check banked attribute.
+
2007-06-20 Sebastian Pop <sebpop@gmail.com>
PR tree-optimization/32075
diff --git a/gcc/config/sh/sh-protos.h b/gcc/config/sh/sh-protos.h
index e142b1c..b3c9387 100644
--- a/gcc/config/sh/sh-protos.h
+++ b/gcc/config/sh/sh-protos.h
@@ -168,6 +168,7 @@ extern rtx replace_n_hard_rtx (rtx, rtx *, int , int);
extern int shmedia_cleanup_truncate (rtx *, void *);
extern int sh_contains_memref_p (rtx);
+extern int sh_loads_bankedreg_p (rtx);
extern rtx shmedia_prepare_call_address (rtx fnaddr, int is_sibcall);
struct secondary_reload_info;
extern enum reg_class sh_secondary_reload (bool, rtx, enum reg_class,
diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c
index 60520f7..0541256 100644
--- a/gcc/config/sh/sh.c
+++ b/gcc/config/sh/sh.c
@@ -5723,13 +5723,13 @@ pop (int rn)
static void
push_regs (HARD_REG_SET *mask, int interrupt_handler)
{
- int i;
+ int i = interrupt_handler ? LAST_BANKED_REG + 1 : 0;
int skip_fpscr = 0;
/* Push PR last; this gives better latencies after the prologue, and
candidates for the return delay slot when there are no general
registers pushed. */
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+ for (; i < FIRST_PSEUDO_REGISTER; i++)
{
/* If this is an interrupt handler, and the SZ bit varies,
and we have to push any floating point register, we need
@@ -5749,6 +5749,13 @@ push_regs (HARD_REG_SET *mask, int interrupt_handler)
&& TEST_HARD_REG_BIT (*mask, i))
push (i);
}
+
+ /* 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);
+
if (TEST_HARD_REG_BIT (*mask, PR_REG))
push (PR_REG);
}
@@ -6675,6 +6682,8 @@ sh_expand_epilogue (bool sibcall_p)
}
else /* ! TARGET_SH5 */
{
+ int last_reg;
+
save_size = 0;
if (TEST_HARD_REG_BIT (live_regs_mask, PR_REG))
{
@@ -6682,7 +6691,21 @@ sh_expand_epilogue (bool sibcall_p)
emit_insn (gen_blockage ());
pop (PR_REG);
}
- for (i = 0; i < FIRST_PSEUDO_REGISTER; i++)
+
+ /* Banked registers are poped first to avoid being scheduled in the
+ delay slot. RTE switches banks before the ds instruction. */
+ if (current_function_interrupt)
+ {
+ for (i = FIRST_BANKED_REG; i <= LAST_BANKED_REG; i++)
+ if (TEST_HARD_REG_BIT (live_regs_mask, i))
+ pop (LAST_BANKED_REG - i);
+
+ last_reg = FIRST_PSEUDO_REGISTER - LAST_BANKED_REG - 1;
+ }
+ else
+ last_reg = FIRST_PSEUDO_REGISTER;
+
+ for (i = 0; i < last_reg; i++)
{
int j = (FIRST_PSEUDO_REGISTER - 1) - i;
@@ -6692,9 +6715,9 @@ sh_expand_epilogue (bool sibcall_p)
fpscr_deferred = 1;
else if (j != PR_REG && TEST_HARD_REG_BIT (live_regs_mask, j))
pop (j);
+
if (j == FIRST_FP_REG && fpscr_deferred)
pop (FPSCR_REG);
-
}
}
if (target_flags != save_flags && ! current_function_interrupt)
@@ -10839,6 +10862,20 @@ sh_contains_memref_p (rtx insn)
return for_each_rtx (&PATTERN (insn), &sh_contains_memref_p_1, NULL);
}
+/* Return nonzero iff INSN loads a banked register. */
+int
+sh_loads_bankedreg_p (rtx insn)
+{
+ if (GET_CODE (PATTERN (insn)) == SET)
+ {
+ rtx op = SET_DEST (PATTERN(insn));
+ if (REG_P (op) && BANKED_REGISTER_P (REGNO (op)))
+ return 1;
+ }
+
+ return 0;
+}
+
/* FNADDR is the MEM expression from a call expander. Return an address
to use in an SHmedia insn pattern. */
rtx
diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h
index 91a5611..4fe0de8 100644
--- a/gcc/config/sh/sh.h
+++ b/gcc/config/sh/sh.h
@@ -1033,6 +1033,16 @@ extern char sh_additional_register_names[ADDREGNAMES_SIZE] \
#define FIRST_TARGET_REG TR0_REG
#define LAST_TARGET_REG (FIRST_TARGET_REG + (TARGET_SHMEDIA ? 7 : -1))
+/* Registers that can be accessed through bank0 or bank1 depending on sr.md. */
+
+#define FIRST_BANKED_REG R0_REG
+#define LAST_BANKED_REG R7_REG
+
+#define BANKED_REGISTER_P(REGNO) \
+ IN_RANGE ((REGNO), \
+ (unsigned HOST_WIDE_INT) FIRST_BANKED_REG, \
+ (unsigned HOST_WIDE_INT) LAST_BANKED_REG)
+
#define GENERAL_REGISTER_P(REGNO) \
IN_RANGE ((REGNO), \
(unsigned HOST_WIDE_INT) FIRST_GENERAL_REG, \
diff --git a/gcc/config/sh/sh.md b/gcc/config/sh/sh.md
index e85470e..be6294f 100644
--- a/gcc/config/sh/sh.md
+++ b/gcc/config/sh/sh.md
@@ -463,6 +463,12 @@
(define_attr "needs_delay_slot" "yes,no" (const_string "no"))
+(define_attr "banked" "yes,no"
+ (cond [(eq (symbol_ref "sh_loads_bankedreg_p (insn)")
+ (const_int 1))
+ (const_string "yes")]
+ (const_string "no")))
+
;; ??? This should be (nil) instead of (const_int 0)
(define_attr "hit_stack" "yes,no"
(cond [(eq (symbol_ref "find_regno_note (insn, REG_INC, SP_REG)")
@@ -541,8 +547,9 @@
(eq_attr "type" "!pload,prset"))
(and (eq_attr "interrupt_function" "yes")
(ior
- (ne (symbol_ref "TARGET_SH3") (const_int 0))
- (eq_attr "hit_stack" "no"))))) (nil) (nil)])
+ (eq (symbol_ref "TARGET_SH3") (const_int 0))
+ (eq_attr "hit_stack" "no")
+ (eq_attr "banked" "no"))))) (nil) (nil)])
;; Since a call implicitly uses the PR register, we can't allow
;; a PR register store in a jsr delay slot.
diff --git a/gcc/testsuite/ChangeLog b/gcc/testsuite/ChangeLog
index caf24ed..f38fda0 100644
--- a/gcc/testsuite/ChangeLog
+++ b/gcc/testsuite/ChangeLog
@@ -1,3 +1,7 @@
+2007-06-21 Christian Bruel <christian.bruel@st.com>
+
+ * gcc.dg/attr-isr.c: Test delay slot content.
+
2007-06-20 Jerry DeLisle <jvdelisle@gcc.gnu.org>
PR fortran/32361
diff --git a/gcc/testsuite/gcc.dg/attr-isr.c b/gcc/testsuite/gcc.dg/attr-isr.c
index 113ac21..8292fe9 100644
--- a/gcc/testsuite/gcc.dg/attr-isr.c
+++ b/gcc/testsuite/gcc.dg/attr-isr.c
@@ -16,3 +16,4 @@ void
/* { dg-final { scan-assembler-times "\[^f\]r\[0-9\]\[ \t\]*," 8 } } */
/* { dg-final { scan-assembler-not "\[^f\]r1\[0-3\]" } } */
/* { dg-final { scan-assembler-times "macl" 2} } */
+/* { dg-final { scan-assembler-not "rte.*\n.*r15\[+\],r\[0-7\]\n" } } */