This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
m68k: Add __attribute__((interrupt)).
- From: Bernardo Innocenti <bernie at develer dot com>
- To: gcc-patches at gcc dot gnu dot org
- Cc: Peter Barada <pbarada at mail dot wm dot sps dot mot dot com>,Peter Barada <peter at baradas dot org>,Richard Henderson <rth at redhat dot com>
- Date: Thu, 21 Aug 2003 04:06:52 +0200
- Subject: m68k: Add __attribute__((interrupt)).
- Organization: Develer S.r.l.
This patch introduces __attribute__((interrupt)) support for m68k targets.
(adapted from Peter Barada's GCC 3.2.3 patches for ColdFire targets).
2003-08-06 Peter Barada <peter@baradas.org>
Bernardo Innocenti <bernie@develer.com>
* config/m68k/m68k.c (m68k_frame): Move before protos referencing it.
* config/m68k/m68k.c (m68k_save_reg): Add boolean parameter
`interrupt_handler'.
* config/m68k/m68k.c (m68k_interrupt_function_p): New function.
* config/m68k/m68k.c (m68k_handle_fndecl_attribute): Ditto.
* config/m68k/m68k.c (m68k_compute_frame_layout): Ditto.
* config/m68k/m68k.c (m68k_attribute_table): Define back-end specific
attributes.
* config/m68k/m68k.c (m68k_output_function_epilogue): Emit rte
instruction for interrupt functions.
diff -Nru gcc-3.4-20030806.orig/gcc/config/m68k/m68k.c gcc-3.4-20030806/gcc/config/m68k/m68k.c
--- gcc-3.4-20030806.orig/gcc/config/m68k/m68k.c 2003-08-07 19:06:25.000000000 +0200
+++ gcc-3.4-20030806/gcc/config/m68k/m68k.c 2003-08-07 19:21:01.000000000 +0200
@@ -45,6 +45,24 @@
/* Needed for use_return_insn. */
#include "flags.h"
+/* Structure describing stack frame layout. */
+struct m68k_frame {
+ HOST_WIDE_INT offset;
+ HOST_WIDE_INT size;
+ /* data and address register */
+ int reg_no;
+ unsigned int reg_mask;
+ unsigned int reg_rev_mask;
+ /* fpu registers */
+ int fpu_no;
+ unsigned int fpu_mask;
+ unsigned int fpu_rev_mask;
+ /* offsets relative to ARG_POINTER. */
+ HOST_WIDE_INT frame_pointer_offset;
+ HOST_WIDE_INT hard_frame_pointer_offset;
+ HOST_WIDE_INT stack_pointer_offset;
+};
+
/* This flag is used to communicate between movhi and ASM_OUTPUT_CASE_END,
if SGS_SWITCH_TABLE. */
int switch_table_difference_label_flag;
@@ -63,7 +81,12 @@
#endif
static void m68k_output_mi_thunk PARAMS ((FILE *, tree, HOST_WIDE_INT,
HOST_WIDE_INT, tree));
-static int m68k_save_reg PARAMS ((unsigned int));
+static bool m68k_interrupt_function_p PARAMS ((tree func));
+static tree m68k_handle_fndecl_attribute PARAMS ((tree *node, tree name,
+ tree args, int flags,
+ bool *no_add_attrs));
+static void m68k_compute_frame_layout PARAMS ((struct m68k_frame *frame));
+static bool m68k_save_reg PARAMS ((unsigned int regno, bool interrupt_handler));
static int const_int_cost PARAMS ((rtx));
static bool m68k_rtx_costs PARAMS ((rtx, int, int, int *));
@@ -138,6 +161,16 @@
#undef TARGET_RTX_COSTS
#define TARGET_RTX_COSTS m68k_rtx_costs
+#undef TARGET_ATTRIBUTE_TABLE
+#define TARGET_ATTRIBUTE_TABLE m68k_attribute_table
+
+static const struct attribute_spec m68k_attribute_table[] =
+{
+ /* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
+ { "interrupt", 0, 0, true, false, false, m68k_handle_fndecl_attribute },
+ { NULL, 0, 0, false, false, false, NULL }
+};
+
struct gcc_target targetm = TARGET_INITIALIZER;
/* Sometimes certain combinations of command options do not make
@@ -216,25 +249,40 @@
real_format_for_mode[XFmode - QFmode] = &ieee_extended_motorola_format;
}
-/* Structure describing stack frame layout. */
-struct m68k_frame {
- HOST_WIDE_INT offset;
- HOST_WIDE_INT size;
- /* data and address register */
- int reg_no;
- unsigned int reg_mask;
- unsigned int reg_rev_mask;
- /* fpu registers */
- int fpu_no;
- unsigned int fpu_mask;
- unsigned int fpu_rev_mask;
- /* fpa registers */
- int fpa_no;
- /* offsets relative to ARG_POINTER. */
- HOST_WIDE_INT frame_pointer_offset;
- HOST_WIDE_INT hard_frame_pointer_offset;
- HOST_WIDE_INT stack_pointer_offset;
-};
+/* Return nonzero if FUNC is an interrupt function as specified by the
+ "interrupt" attribute. */
+static bool
+m68k_interrupt_function_p(func)
+ tree func;
+{
+ tree a;
+
+ if (TREE_CODE (func) != FUNCTION_DECL)
+ return false;
+
+ a = lookup_attribute ("interrupt", DECL_ATTRIBUTES (func));
+ return (a != NULL_TREE);
+}
+
+/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
+ struct attribute_spec.handler. */
+static tree
+m68k_handle_fndecl_attribute (node, name, args, flags, no_add_attrs)
+ tree *node;
+ tree name;
+ tree args ATTRIBUTE_UNUSED;
+ int flags ATTRIBUTE_UNUSED;
+ bool *no_add_attrs;
+{
+ if (TREE_CODE (*node) != FUNCTION_DECL)
+ {
+ warning ("`%s' attribute only applies to functions",
+ IDENTIFIER_POINTER (name));
+ *no_add_attrs = true;
+ }
+
+ return NULL_TREE;
+}
static void
m68k_compute_frame_layout (frame)
@@ -242,12 +290,13 @@
{
int regno, saved;
unsigned int mask, rmask;
+ bool interrupt_handler = m68k_interrupt_function_p (current_function_decl);
frame->size = (get_frame_size () + 3) & -4;
mask = rmask = saved = 0;
for (regno = 0; regno < 16; regno++)
- if (m68k_save_reg (regno))
+ if (m68k_save_reg (regno, interrupt_handler))
{
mask |= 1 << regno;
rmask |= 1 << (15 - regno);
@@ -311,14 +360,15 @@
abort();
}
-/* Return 1 if we need to save REGNO. */
-static int
-m68k_save_reg (regno)
+/* Return true if we need to save REGNO. */
+static bool
+m68k_save_reg (regno, interrupt_handler)
unsigned int regno;
+ bool interrupt_handler;
{
if (flag_pic && current_function_uses_pic_offset_table
&& regno == PIC_OFFSET_TABLE_REGNUM)
- return 1;
+ return true;
if (current_function_calls_eh_return)
{
@@ -329,12 +379,18 @@
if (test == INVALID_REGNUM)
break;
if (test == regno)
- return 1;
+ return true;
}
}
- return (regs_ever_live[regno]
- && !call_used_regs[regno]
+ return (
+ ((regs_ever_live[regno] && !call_used_regs[regno])
+ || (interrupt_handler
+ && (regs_ever_live[regno]
+ || (call_used_regs[regno] && !current_function_is_leaf)
+ )
+ )
+ )
&& !fixed_regs[regno]
&& !(regno == FRAME_POINTER_REGNUM && frame_pointer_needed));
}
@@ -363,6 +419,7 @@
HOST_WIDE_INT fsize_with_regs;
HOST_WIDE_INT cfa_offset = INCOMING_FRAME_SP_OFFSET;
HOST_WIDE_INT cfa_store_offset = cfa_offset;
+ bool interrupt_handler = m68k_interrupt_function_p (current_function_decl);
/* If the stack limit is a symbol, we can check it here,
before actually allocating the space. */
@@ -382,7 +439,7 @@
{
/* on Coldfire add register save into initial stack frame setup, if possible */
for (regno = 0; regno < 16; regno++)
- if (m68k_save_reg (regno))
+ if (m68k_save_reg (regno, interrupt_handler))
num_saved_regs++;
if (num_saved_regs <= 2)
@@ -534,7 +591,7 @@
if (TARGET_68881)
{
for (regno = 16; regno < 24; regno++)
- if (m68k_save_reg (regno))
+ if (m68k_save_reg (regno, interrupt_handler))
{
mask |= 1 << (regno - 16);
num_saved_regs++;
@@ -567,7 +624,7 @@
num_saved_regs = 0;
}
for (regno = 0; regno < 16; regno++)
- if (m68k_save_reg (regno))
+ if (m68k_save_reg (regno, interrupt_handler))
{
mask |= 1 << (15 - regno);
num_saved_regs++;
@@ -696,12 +753,13 @@
use_return_insn ()
{
int regno;
+ bool interrupt_handler = m68k_interrupt_function_p (current_function_decl);
if (!reload_completed || frame_pointer_needed || get_frame_size () != 0)
return 0;
for (regno = 0; regno < FIRST_PSEUDO_REGISTER; regno++)
- if (m68k_save_reg (regno))
+ if (m68k_save_reg (regno, interrupt_handler))
return 0;
return 1;
@@ -729,6 +787,7 @@
int big = 0;
rtx insn = get_last_insn ();
int restore_from_sp = 0;
+ bool 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)
@@ -748,7 +807,7 @@
if (TARGET_68881)
{
for (regno = 16; regno < 24; regno++)
- if (m68k_save_reg (regno))
+ if (m68k_save_reg (regno, interrupt_handler))
{
nregs++;
fmask |= 1 << (23 - regno);
@@ -757,7 +816,7 @@
foffset = nregs * 12;
nregs = 0; mask = 0;
for (regno = 0; regno < 16; regno++)
- if (m68k_save_reg (regno))
+ if (m68k_save_reg (regno, interrupt_handler))
{
nregs++;
mask |= 1 << regno;
@@ -1049,7 +1108,9 @@
asm_fprintf (stream, "\taddl %Ra0,%Rsp\n");
#endif
}
- if (current_function_pops_args)
+ if (interrupt_handler)
+ fprintf (stream, "\trte\n");
+ else if (current_function_pops_args)
asm_fprintf (stream, "\trtd %I%d\n", current_function_pops_args);
else
fprintf (stream, "\trts\n");
--
// Bernardo Innocenti - Develer S.r.l., R&D dept.
\X/ http://www.develer.com/
Please don't send Word attachments - http://www.gnu.org/philosophy/no-word-attachments.html