This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
patch: sh interrupt attribute
- To: amylaar at cygnus dot com
- Subject: patch: sh interrupt attribute
- From: Aldy Hernandez <aldyh at redhat dot com>
- Date: 21 Jun 2001 19:02:17 +0100
- Cc: gcc-patches at gcc dot gnu dot org
Hi Joern.
As per our conversation...
The sh port is currently filling the delay slot in an interrupt_handler
function. This may cause the wrong value to be popped out of the stack
if the insn in the delay slot updates the stack. Like thus:
foo
rte
mov.l @r15+,r1
The rte will update PC and SR from the stack before the insn in the
delay slot finishes, thus getting the wrong value.
This is not a problem in >= TARGET_SH3.
The problem is that functions with the interrupt_handler attribute are
not considered to be interrupt handlers correctly by the SH backend:
void f(void) __attribute__ ((interrupt_handler));
The sh port is currently looking at "#pragma interrupt" instead of the
interrupt_handler attribute.
The following patch fixes this and schedules insns in the delay slot if
>= TARGET_SH3.
Ok to install?
--
Aldy Hernandez E-mail: aldyh@redhat.com
Professional Gypsy
Red Hat, Inc.
2001-06-20 Aldy Hernandez <aldyh@redhat.com>
* config/sh/sh.md (interrupt_function): Use
current_function_interrupt.
(define_delay): Schedule in delay slot if TARGET_SH3, even if it is
an interrupt function.
* config/sh/sh.h (current_function_interrupt): Define extern.
* config/sh/sh.c (current_function_interrupt): New global.
(sh_expand_prologue): Set current_function_interrupt.
Index: sh.c
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/sh/sh.c,v
retrieving revision 1.99
diff -c -p -r1.99 sh.c
*** sh.c 2001/06/20 16:04:31 1.99
--- sh.c 2001/06/21 17:48:49
*************** int code_for_indirect_jump_scratch = COD
*** 43,48 ****
--- 43,51 ----
#define MSW (TARGET_LITTLE_ENDIAN ? 1 : 0)
#define LSW (TARGET_LITTLE_ENDIAN ? 0 : 1)
+ /* Set to 1 by expand_prologue() when the function is an interrupt handler. */
+ int current_function_interrupt;
+
/* ??? The pragma interrupt support will not work for SH3. */
/* This is set by #pragma interrupt and #pragma trapa, and causes gcc to
output code for the next function appropriate for an interrupt handler. */
*************** sh_expand_prologue ()
*** 4008,4013 ****
--- 4011,4021 ----
int d, i;
int live_regs_mask2;
int save_flags = target_flags;
+
+ current_function_interrupt
+ = lookup_attribute ("interrupt_handler",
+ DECL_MACHINE_ATTRIBUTES (current_function_decl))
+ != NULL_TREE;
/* We have pretend args if we had an object sent partially in registers
and partially on the stack, e.g. a large structure. */
Index: sh.h
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/sh/sh.h,v
retrieving revision 1.103
diff -c -p -r1.103 sh.h
*** sh.h 2001/05/29 10:44:01 1.103
--- sh.h 2001/06/21 17:48:50
*************** extern enum mdep_reorg_phase_e mdep_reor
*** 2299,2304 ****
--- 2299,2308 ----
extern int pragma_interrupt;
+ /* Set when processing a function with interrupt attribute. */
+
+ extern int current_function_interrupt;
+
/* Set to an RTX containing the address of the stack to switch to
for interrupt functions. */
extern struct rtx_def *sp_switch;
Index: sh.md
===================================================================
RCS file: /cvs/gcc/egcs/gcc/config/sh/sh.md,v
retrieving revision 1.84
diff -c -p -r1.84 sh.md
*** sh.md 2001/06/04 00:20:46 1.84
--- sh.md 2001/06/21 17:48:51
***************
*** 547,553 ****
(const_string "yes")))
(define_attr "interrupt_function" "no,yes"
! (const (symbol_ref "pragma_interrupt")))
(define_attr "in_delay_slot" "yes,no"
(cond [(eq_attr "type" "cbranch") (const_string "no")
--- 547,553 ----
(const_string "yes")))
(define_attr "interrupt_function" "no,yes"
! (const (symbol_ref "current_function_interrupt")))
(define_attr "in_delay_slot" "yes,no"
(cond [(eq_attr "type" "cbranch") (const_string "no")
***************
*** 577,583 ****
(ior (and (eq_attr "interrupt_function" "no")
(eq_attr "type" "!pload,prset"))
(and (eq_attr "interrupt_function" "yes")
! (eq_attr "hit_stack" "no")))) (nil) (nil)])
;; Since a call implicitly uses the PR register, we can't allow
;; a PR register store in a jsr delay slot.
--- 577,585 ----
(ior (and (eq_attr "interrupt_function" "no")
(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)])
;; Since a call implicitly uses the PR register, we can't allow
;; a PR register store in a jsr delay slot.