aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/m68k
diff options
context:
space:
mode:
authorKazu Hirata <kazu@codesourcery.com>2007-05-14 13:52:18 +0000
committerKazu Hirata <kazu@gcc.gnu.org>2007-05-14 13:52:18 +0000
commita4242737202af64a394f5271c06b8be1979cbcfb (patch)
treecffefaf9bacdbe3a58b51e69c4fd92063f10a19c /gcc/config/m68k
parentab6bd6931e768e2348d83da9188d75f24247ff04 (diff)
downloadgcc-a4242737202af64a394f5271c06b8be1979cbcfb.zip
gcc-a4242737202af64a394f5271c06b8be1979cbcfb.tar.gz
gcc-a4242737202af64a394f5271c06b8be1979cbcfb.tar.bz2
m68k-protos.h: Rename m68k_interrupt_function_p to m68k_get_function_kind.
gcc/ * config/m68k/m68k-protos.h: Rename m68k_interrupt_function_p to m68k_get_function_kind. Update its prototype. * config/m68k/m68k.c (m68k_attribute_table): Add an entry for interrupt_thread. (m68k_interrupt_function_p): Return enum m68k_function_type instead of bool. Rename to m68k_get_function_kind. (m68k_handle_fndecl_attribute): Reject interrupt_thread if the target is not fido. (m68k_compute_frame_layout): Don't mark any register for save if an interrupt_thread attribute is specified. (m68k_hard_regno_rename_ok): Update a use of m68k_interrupt_function_p. * config/m68k/m68k.h (EPILOGUE_USES): Update a use of m68k_interrupt_function_p. (m68k_function_type): New. * config/m68k/m68k.md (*return): Output a 'sleep' instruction for a function with an interrupt_thread attribute. * doc/extend.texi: Document the interrupt_thread attribute. gcc/testsuite/ * gcc.target/m68k/interrupt_thread-1.c, gcc.target/m68k/interrupt_thread-2.c, gcc.target/m68k/interrupt_thread-3.c: New. * gcc.target/m68k/m68k.exp: Accept fido. From-SVN: r124713
Diffstat (limited to 'gcc/config/m68k')
-rw-r--r--gcc/config/m68k/m68k-protos.h2
-rw-r--r--gcc/config/m68k/m68k.c70
-rw-r--r--gcc/config/m68k/m68k.h13
-rw-r--r--gcc/config/m68k/m68k.md22
4 files changed, 78 insertions, 29 deletions
diff --git a/gcc/config/m68k/m68k-protos.h b/gcc/config/m68k/m68k-protos.h
index b3b78a1..f5d6c3a 100644
--- a/gcc/config/m68k/m68k-protos.h
+++ b/gcc/config/m68k/m68k-protos.h
@@ -21,7 +21,7 @@ Boston, MA 02110-1301, USA. */
/* Define functions defined in aux-output.c and used in templates. */
#ifdef RTX_CODE
-extern bool m68k_interrupt_function_p (tree);
+extern enum m68k_function_kind m68k_get_function_kind (tree);
extern HOST_WIDE_INT m68k_initial_elimination_offset (int from, int to);
extern void split_di (rtx[], int, rtx[], rtx[]);
diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c
index f975e06..8766559 100644
--- a/gcc/config/m68k/m68k.c
+++ b/gcc/config/m68k/m68k.c
@@ -223,6 +223,7 @@ static const struct attribute_spec m68k_attribute_table[] =
{
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
{ "interrupt_handler", 0, 0, true, false, false, m68k_handle_fndecl_attribute },
+ { "interrupt_thread", 0, 0, true, false, false, m68k_handle_fndecl_attribute },
{ NULL, 0, 0, false, false, false, NULL }
};
@@ -633,10 +634,12 @@ m68k_cpp_cpu_family (const char *prefix)
return concat ("__m", prefix, "_family_", m68k_cpu_entry->family, NULL);
}
-/* Return nonzero if FUNC is an interrupt function as specified by the
- "interrupt_handler" attribute. */
-bool
-m68k_interrupt_function_p (tree func)
+/* Return m68k_fk_interrupt_handler if FUNC has an "interrupt_handler"
+ attribute and interrupt_thread if FUNC has an "interrupt_thread"
+ attribute. Otherwise, return m68k_fk_normal_function. */
+
+enum m68k_function_kind
+m68k_get_function_kind (tree func)
{
tree a;
@@ -644,7 +647,14 @@ m68k_interrupt_function_p (tree func)
return false;
a = lookup_attribute ("interrupt_handler", DECL_ATTRIBUTES (func));
- return (a != NULL_TREE);
+ if (a != NULL_TREE)
+ return m68k_fk_interrupt_handler;
+
+ a = lookup_attribute ("interrupt_thread", DECL_ATTRIBUTES (func));
+ if (a != NULL_TREE)
+ return m68k_fk_interrupt_thread;
+
+ return m68k_fk_normal_function;
}
/* Handle an attribute requiring a FUNCTION_DECL; arguments as in
@@ -662,6 +672,19 @@ m68k_handle_fndecl_attribute (tree *node, tree name,
*no_add_attrs = true;
}
+ if (m68k_get_function_kind (*node) != m68k_fk_normal_function)
+ {
+ error ("multiple interrupt attributes not allowed");
+ *no_add_attrs = true;
+ }
+
+ if (!TARGET_FIDOA
+ && !strcmp (IDENTIFIER_POINTER (name), "interrupt_thread"))
+ {
+ error ("interrupt_thread is available only on fido");
+ *no_add_attrs = true;
+ }
+
return NULL_TREE;
}
@@ -670,7 +693,10 @@ m68k_compute_frame_layout (void)
{
int regno, saved;
unsigned int mask;
- bool interrupt_handler = m68k_interrupt_function_p (current_function_decl);
+ enum m68k_function_kind func_kind =
+ m68k_get_function_kind (current_function_decl);
+ bool interrupt_handler = func_kind == m68k_fk_interrupt_handler;
+ bool interrupt_thread = func_kind == m68k_fk_interrupt_thread;
/* Only compute the frame once per function.
Don't cache information until reload has been completed. */
@@ -681,12 +707,15 @@ m68k_compute_frame_layout (void)
current_frame.size = (get_frame_size () + 3) & -4;
mask = saved = 0;
- for (regno = 0; regno < 16; regno++)
- if (m68k_save_reg (regno, interrupt_handler))
- {
- mask |= 1 << (regno - D0_REG);
- saved++;
- }
+
+ /* Interrupt thread does not need to save any register. */
+ if (!interrupt_thread)
+ for (regno = 0; regno < 16; regno++)
+ if (m68k_save_reg (regno, interrupt_handler))
+ {
+ mask |= 1 << (regno - D0_REG);
+ saved++;
+ }
current_frame.offset = saved * 4;
current_frame.reg_no = saved;
current_frame.reg_mask = mask;
@@ -695,12 +724,14 @@ m68k_compute_frame_layout (void)
mask = saved = 0;
if (TARGET_HARD_FLOAT)
{
- for (regno = 16; regno < 24; regno++)
- if (m68k_save_reg (regno, interrupt_handler))
- {
- mask |= 1 << (regno - FP0_REG);
- saved++;
- }
+ /* Interrupt thread does not need to save any register. */
+ if (!interrupt_thread)
+ for (regno = 16; regno < 24; regno++)
+ if (m68k_save_reg (regno, interrupt_handler))
+ {
+ mask |= 1 << (regno - FP0_REG);
+ saved++;
+ }
current_frame.foffset = saved * TARGET_FP_REG_SIZE;
current_frame.offset += current_frame.foffset;
}
@@ -4211,7 +4242,8 @@ m68k_hard_regno_rename_ok (unsigned int old_reg ATTRIBUTE_UNUSED,
saved by the prologue, even if they would normally be
call-clobbered. */
- if (m68k_interrupt_function_p (current_function_decl)
+ if ((m68k_get_function_kind (current_function_decl)
+ == m68k_fk_interrupt_handler)
&& !regs_ever_live[new_reg])
return 0;
diff --git a/gcc/config/m68k/m68k.h b/gcc/config/m68k/m68k.h
index baa5bcb..1b19b4c 100644
--- a/gcc/config/m68k/m68k.h
+++ b/gcc/config/m68k/m68k.h
@@ -903,8 +903,10 @@ do { if (cc_prev_status.flags & CC_IN_68881) \
#define INCOMING_FRAME_SP_OFFSET 4
/* All registers are live on exit from an interrupt routine. */
-#define EPILOGUE_USES(REGNO) \
- (reload_completed && m68k_interrupt_function_p (current_function_decl))
+#define EPILOGUE_USES(REGNO) \
+ (reload_completed \
+ && (m68k_get_function_kind (current_function_decl) \
+ == m68k_fk_interrupt_handler))
/* Describe how we implement __builtin_eh_return. */
#define EH_RETURN_DATA_REGNO(N) \
@@ -1098,6 +1100,13 @@ enum fpu_type
FPUTYPE_COLDFIRE
};
+enum m68k_function_kind
+{
+ m68k_fk_normal_function,
+ m68k_fk_interrupt_handler,
+ m68k_fk_interrupt_thread
+};
+
/* Variables in m68k.c; see there for details. */
extern const char *m68k_library_id_string;
extern int m68k_last_compare_had_fp_operands;
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md
index 78ddf58..19abe62 100644
--- a/gcc/config/m68k/m68k.md
+++ b/gcc/config/m68k/m68k.md
@@ -6833,15 +6833,23 @@
[(return)]
""
{
- if (m68k_interrupt_function_p (current_function_decl))
- return "rte";
- else if (current_function_pops_args)
+ switch (m68k_get_function_kind (current_function_decl))
{
- operands[0] = GEN_INT (current_function_pops_args);
- return "rtd %0";
+ case m68k_fk_interrupt_handler:
+ return "rte";
+
+ case m68k_fk_interrupt_thread:
+ return "sleep";
+
+ default:
+ if (current_function_pops_args)
+ {
+ operands[0] = GEN_INT (current_function_pops_args);
+ return "rtd %0";
+ }
+ else
+ return "rts";
}
- else
- return "rts";
})
(define_insn "*m68k_store_multiple"