This is the mail archive of the crossgcc@cygnus.com mailing list for the crossgcc project.
Index Nav: | [Date Index] [Subject Index] [Author Index] [Thread Index] | |
---|---|---|
Message Nav: | [Date Prev] [Date Next] | [Thread Prev] [Thread Next] |
On Wed, Mar 10, 1999 at 12:37:21PM +1100, Brendan Simon wrote: > Some time ago I asked about interrupt keywords with egcs. Jeff kindly > responded with the above message. > How do if the interrupt keyword exists for a particular target. I am > interested in 68k and powerpc. Hm - I just did that. The patch could need some testing, but on my test cases, it seemed to work fine. It is mostly stolen from the NEC V850 target - note that #pragma interrupt and __attribute((interrupt)) in the Hitachi SH target (where I looked first for example code) seem to be broken because they use global variables ... > What is the syntax to the attribute ? Is it the same for all supported > targets or is it target dependent ? I used __attribute__((interrupt)). When set on a function, all modified registers are saved and the function terminates using rte instead of rts/rtd. Note that you can not call an interrupt function from normal code, and it might not be a good idea to declare them anything except void(void). I'll attach the patch, comments are welcome. The patch is against egcs-1.1b, but other versions should work, too. volatile int x; void __attribute__((interrupt)) intr(void) { x++; } .comm _x,2 .even .globl _intr _intr: move.l %d0,-(%sp) move.w _x,%d0 addq.w #1,%d0 move.w %d0,_x move.l (%sp)+,%d0 rte cu Michael -- Michael Schwingen, Ahornstrasse 36, 52074 Aachen
*** m68k.h.orig Sat Mar 6 22:34:40 1999 --- m68k.h Sun Mar 7 00:26:45 1999 *************** *** 2124,2129 **** --- 2124,2138 ---- extern void finalize_pic (); extern void override_options (); + + /* A C expression whose value is nonzero if IDENTIFIER with arguments ARGS + is a valid machine specific attribute for DECL. + The attributes in ATTRIBUTES have previously been assigned to DECL. */ + extern int m68k_valid_machine_decl_attribute (); + #define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \ + m68k_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS) + + /* Local variables: *** m68k.c.orig Sat Mar 6 22:34:37 1999 --- m68k.c Sun Mar 7 01:03:29 1999 *************** *** 171,176 **** --- 171,177 ---- extern char call_used_regs[]; int fsize = (size + 3) & -4; int cfa_offset = INCOMING_FRAME_SP_OFFSET, cfa_store_offset = cfa_offset; + int interrupt_handler = m68k_interrupt_function_p (current_function_decl); if (frame_pointer_needed) *************** *** 308,314 **** } #ifdef SUPPORT_SUN_FPA for (regno = 24; regno < 56; regno++) ! if (regs_ever_live[regno] && ! call_used_regs[regno]) { #ifdef MOTOROLA asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n", --- 309,315 ---- } #ifdef SUPPORT_SUN_FPA for (regno = 24; regno < 56; regno++) ! if (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_handler)) { #ifdef MOTOROLA asm_fprintf (stream, "\tfpmovd %s,-(%Rsp)\n", *************** *** 334,340 **** if (TARGET_68881) { for (regno = 16; regno < 24; regno++) ! if (regs_ever_live[regno] && ! call_used_regs[regno]) { mask |= 1 << (regno - 16); num_saved_regs++; --- 335,341 ---- if (TARGET_68881) { for (regno = 16; regno < 24; regno++) ! if (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_handler)) { mask |= 1 << (regno - 16); num_saved_regs++; *************** *** 367,373 **** num_saved_regs = 0; } for (regno = 0; regno < 16; regno++) ! if (regs_ever_live[regno] && ! call_used_regs[regno]) { mask |= 1 << (15 - regno); num_saved_regs++; --- 368,374 ---- num_saved_regs = 0; } for (regno = 0; regno < 16; regno++) ! if (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_handler)) { mask |= 1 << (15 - regno); num_saved_regs++; *************** *** 499,504 **** --- 500,506 ---- use_return_insn () { int regno; + int interrupt_handler = m68k_interrupt_function_p (current_function_decl); if (!reload_completed || frame_pointer_needed || get_frame_size () != 0) return 0; *************** *** 507,513 **** separate layout routine to perform the common work. */ for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++) ! if (regs_ever_live[regno] && ! call_used_regs[regno]) return 0; return 1; --- 509,515 ---- separate layout routine to perform the common work. */ for (regno = 0 ; regno < FIRST_PSEUDO_REGISTER ; regno++) ! if (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_handler)) return 0; return 1; *************** *** 535,540 **** --- 537,543 ---- int big = 0; rtx insn = get_last_insn (); int restore_from_sp = 0; + int interrupt_handler = m68k_interrupt_function_p (current_function_decl); /* If the last insn was a BARRIER, we don't have to write any code. */ if (GET_CODE (insn) == NOTE) *************** *** 560,566 **** nregs = 0; fmask = 0; fpoffset = 0; #ifdef SUPPORT_SUN_FPA for (regno = 24 ; regno < 56 ; regno++) ! if (regs_ever_live[regno] && ! call_used_regs[regno]) nregs++; fpoffset = nregs * 8; #endif --- 563,569 ---- nregs = 0; fmask = 0; fpoffset = 0; #ifdef SUPPORT_SUN_FPA for (regno = 24 ; regno < 56 ; regno++) ! if (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_handler)) nregs++; fpoffset = nregs * 8; #endif *************** *** 568,574 **** if (TARGET_68881) { for (regno = 16; regno < 24; regno++) ! if (regs_ever_live[regno] && ! call_used_regs[regno]) { nregs++; fmask |= 1 << (23 - regno); --- 571,577 ---- if (TARGET_68881) { for (regno = 16; regno < 24; regno++) ! if (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_handler)) { nregs++; fmask |= 1 << (23 - regno); *************** *** 579,585 **** if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; for (regno = 0; regno < 16; regno++) ! if (regs_ever_live[regno] && ! call_used_regs[regno]) { nregs++; mask |= 1 << regno; --- 582,588 ---- if (frame_pointer_needed) regs_ever_live[FRAME_POINTER_REGNUM] = 0; for (regno = 0; regno < 16; regno++) ! if (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_handler)) { nregs++; mask |= 1 << regno; *************** *** 729,735 **** } if (fpoffset != 0) for (regno = 55; regno >= 24; regno--) ! if (regs_ever_live[regno] && ! call_used_regs[regno]) { if (big) { --- 732,738 ---- } if (fpoffset != 0) for (regno = 55; regno >= 24; regno--) ! if (regs_ever_live[regno] && (!call_used_regs[regno] || interrupt_handler)) { if (big) { *************** *** 839,848 **** --- 842,858 ---- #endif } } + if (interrupt_handler) + { + fprintf (stream, "\trte\n"); + } + else + { if (current_function_pops_args) asm_fprintf (stream, "\trtd %0I%d\n", current_function_pops_args); else fprintf (stream, "\trts\n"); + } } /* Similar to general_operand, but exclude stack_pointer_rtx. */ *************** *** 3391,3393 **** --- 3401,3446 ---- } return "eor%.l %2,%0"; } + + /* Return nonzero if ATTR is a valid attribute for DECL. + ATTRIBUTES are any existing attributes and ARGS are the arguments + supplied with ATTR. + + Supported attributes: + + interrupt -- specifies this function is an interrupt handler. + */ + + int + m68k_valid_machine_decl_attribute (decl, attributes, attr, args) + tree decl; + tree attributes; + tree attr; + tree args; + { + if (args != NULL_TREE) + return 0; + + if (is_attribute_p ("interrupt", attr)) + return TREE_CODE (decl) == FUNCTION_DECL; + + return 0; + } + + /* Return nonzero if FUNC is an interrupt function as specified by the + "interrupt" attribute. */ + + int + m68k_interrupt_function_p(func) + tree func; + { + tree a; + + if (TREE_CODE (func) != FUNCTION_DECL) + return 0; + + a = lookup_attribute ("interrupt", DECL_MACHINE_ATTRIBUTES (func)); + return (a != NULL_TREE); + } + +