diff --git a/gcc/ChangeLog b/gcc/ChangeLog index d9f22c21a58..4c3bfe0466c 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -22,6 +22,16 @@ (fix-header.o): Likewise. (scan-decls.o): Likewise. +Fri Dec 11 11:02:49 1998 Stan Cox + + * sh.c (print_operand): lookup interrupt_handler attribute instead + of relying on static variable. + * (calc_live_regs): Likewise. + * (sh_pragma_insert_attributes): Create interrupt_handler + attribute if a pragma was specified + * (sh_valid_machine_decl_attribute): Don't set static flag. + * sh.h (PRAGMA_INSERT_ATTRIBUTES): New. + Fri Dec 11 12:56:07 1998 J"orn Rennecke * reload1.c (reload_combine): Use BASIC_BLOCK_LIVE_AT_START diff --git a/gcc/config/sh/sh.c b/gcc/config/sh/sh.c index cb40718c057..2eb4674c7d0 100644 --- a/gcc/config/sh/sh.c +++ b/gcc/config/sh/sh.c @@ -226,13 +226,25 @@ print_operand (stream, x, code) fprintf (stream, "%s", LOCAL_LABEL_PREFIX); break; case '@': + { + int interrupt_handler; + + if ((lookup_attribute + ("interrupt_handler", + DECL_MACHINE_ATTRIBUTES (current_function_decl))) + != NULL_TREE) + interrupt_handler = 1; + else + interrupt_handler = 0; + if (trap_exit) fprintf (stream, "trapa #%d", trap_exit); - else if (pragma_interrupt) + else if (interrupt_handler) fprintf (stream, "rte"); else fprintf (stream, "rts"); break; + } case '#': /* Output a nop if there's nothing in the delay slot. */ if (dbr_sequence_length () == 0) @@ -3615,13 +3627,22 @@ calc_live_regs (count_ptr, live_regs_mask2) int reg; int live_regs_mask = 0; int count; + int interrupt_handler; + + if ((lookup_attribute + ("interrupt_handler", + DECL_MACHINE_ATTRIBUTES (current_function_decl))) + != NULL_TREE) + interrupt_handler = 1; + else + interrupt_handler = 0; *live_regs_mask2 = 0; /* If we can save a lot of saves by switching to double mode, do that. */ if (TARGET_SH4 && TARGET_FMOVD && TARGET_FPU_SINGLE) for (count = 0, reg = FIRST_FP_REG; reg <= LAST_FP_REG; reg += 2) if (regs_ever_live[reg] && regs_ever_live[reg+1] - && (! call_used_regs[reg] || (pragma_interrupt && ! pragma_trapa)) + && (! call_used_regs[reg] || (interrupt_handler && ! pragma_trapa)) && ++count > 2) { target_flags &= ~FPU_SINGLE_BIT; @@ -3629,7 +3650,7 @@ calc_live_regs (count_ptr, live_regs_mask2) } for (count = 0, reg = FIRST_PSEUDO_REGISTER - 1; reg >= 0; reg--) { - if ((pragma_interrupt && ! pragma_trapa) + if ((interrupt_handler && ! pragma_trapa) ? (/* Need to save all the regs ever live. */ (regs_ever_live[reg] || (call_used_regs[reg] @@ -3951,6 +3972,31 @@ sh_handle_pragma (p_getc, p_ungetc, pname) return retval; } + +/* Generate 'handle_interrupt' attribute for decls */ + +void +sh_pragma_insert_attributes (node, attributes, prefix) + tree node; + tree * attributes; + tree * prefix; +{ + tree a; + + if (! pragma_interrupt + || TREE_CODE (node) != FUNCTION_DECL) + return; + + /* We are only interested in fields. */ + if (TREE_CODE_CLASS (TREE_CODE (node)) != 'd') + return; + + /* Add a 'handle_interrupt' attribute. */ + * attributes = tree_cons (get_identifier ("interrupt_handler"), NULL, * attributes); + + return; +} + /* Return nonzero if ATTR is a valid attribute for DECL. ATTRIBUTES are any existing attributes and ARGS are the arguments supplied with ATTR. @@ -3979,7 +4025,6 @@ sh_valid_machine_decl_attribute (decl, attributes, attr, args) if (is_attribute_p ("interrupt_handler", attr)) { - pragma_interrupt = 1; return 1; } diff --git a/gcc/config/sh/sh.h b/gcc/config/sh/sh.h index c32b13a000d..e2bf8c7bed9 100644 --- a/gcc/config/sh/sh.h +++ b/gcc/config/sh/sh.h @@ -2062,6 +2062,10 @@ extern int sh_valid_machine_decl_attribute (); #define VALID_MACHINE_DECL_ATTRIBUTE(DECL, ATTRIBUTES, IDENTIFIER, ARGS) \ sh_valid_machine_decl_attribute (DECL, ATTRIBUTES, IDENTIFIER, ARGS) +extern void sh_pragma_insert_attributes (); +#define PRAGMA_INSERT_ATTRIBUTES(node, pattr, prefix_attr) \ + sh_pragma_insert_attributes (node, pattr, prefix_attr) + extern int sh_flag_remove_dead_before_cse; extern int rtx_equal_function_value_matters; extern struct rtx_def *fpscr_rtx;