This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]

patch: sh interrupt attribute


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.

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]