summaryrefslogtreecommitdiff
path: root/gcc/config/m32c
diff options
context:
space:
mode:
authordj <dj@138bc75d-0d04-0410-961f-82ee72b054a4>2009-08-17 22:25:06 +0000
committerdj <dj@138bc75d-0d04-0410-961f-82ee72b054a4>2009-08-17 22:25:06 +0000
commitcc24427cdc2401f499a19df7550138f8911ec05e (patch)
treec06c38535dd2071c8584011e69f62f150c8e33df /gcc/config/m32c
parentc3023e22eb19eb3dad408a20ef7ea89f860b8be0 (diff)
downloadgcc-cc24427cdc2401f499a19df7550138f8911ec05e.tar.gz
* config/m32c/m32c.md (UNS_FSETB, UNS_FREIT): New.
* config/m32c/prologue.md (epilogue_freit): New. (fset_b): New. * config/m32c/m32c.c (m32c_function_needs_enter): Add prototype. (bank_switch_p): Likewise. (fast_interrupt_p): Likewise. (interrupt_p): Likewise. (m32c_conditional_register_usage): Round memregs size up. (need_to_save): We only need to save $a0 when we use ENTER. (interrupt_p): Check for fast_interrupt too. (bank_switch_p): New. (fast_interrupt_p): New. (m32c_attribute_table): Add bank_switch and fast_interrupt. (m32c_emit_prolog): Support bank switching and fast interrupts. * doc/extend.texi (Function Attributes): Add bank_switch and fast_interrupt. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@150862 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc/config/m32c')
-rw-r--r--gcc/config/m32c/m32c.c85
-rw-r--r--gcc/config/m32c/m32c.md2
-rw-r--r--gcc/config/m32c/prologue.md17
3 files changed, 90 insertions, 14 deletions
diff --git a/gcc/config/m32c/m32c.c b/gcc/config/m32c/m32c.c
index 46dc4dc6639..ae4c8973dea 100644
--- a/gcc/config/m32c/m32c.c
+++ b/gcc/config/m32c/m32c.c
@@ -60,9 +60,13 @@ typedef enum
PP_justcount
} Push_Pop_Type;
+static bool m32c_function_needs_enter (void);
static tree interrupt_handler (tree *, tree, tree, int, bool *);
static tree function_vector_handler (tree *, tree, tree, int, bool *);
static int interrupt_p (tree node);
+static int bank_switch_p (tree node);
+static int fast_interrupt_p (tree node);
+static int interrupt_p (tree node);
static bool m32c_asm_integer (rtx, unsigned int, int);
static int m32c_comp_type_attributes (const_tree, const_tree);
static bool m32c_fixed_condition_code_regs (unsigned int *, unsigned int *);
@@ -493,7 +497,7 @@ m32c_conditional_register_usage (void)
{
/* The command line option is bytes, but our "registers" are
16-bit words. */
- for (i = target_memregs/2; i < 8; i++)
+ for (i = (target_memregs+1)/2; i < 8; i++)
{
fixed_regs[MEM0_REGNO + i] = 1;
CLEAR_HARD_REG_BIT (reg_class_contents[MEM_REGS], MEM0_REGNO + i);
@@ -1255,7 +1259,10 @@ need_to_save (int regno)
if (regno == FP_REGNO)
return 0;
if (cfun->machine->is_interrupt
- && (!cfun->machine->is_leaf || regno == A0_REGNO))
+ && (!cfun->machine->is_leaf
+ || (regno == A0_REGNO
+ && m32c_function_needs_enter ())
+ ))
return 1;
if (df_regs_ever_live_p (regno)
&& (!call_used_regs[regno] || cfun->machine->is_interrupt))
@@ -2733,6 +2740,34 @@ interrupt_p (tree node ATTRIBUTE_UNUSED)
return 1;
list = TREE_CHAIN (list);
}
+ return fast_interrupt_p (node);
+}
+
+/* Returns TRUE if the given tree has the "bank_switch" attribute. */
+static int
+bank_switch_p (tree node ATTRIBUTE_UNUSED)
+{
+ tree list = M32C_ATTRIBUTES (node);
+ while (list)
+ {
+ if (is_attribute_p ("bank_switch", TREE_PURPOSE (list)))
+ return 1;
+ list = TREE_CHAIN (list);
+ }
+ return 0;
+}
+
+/* Returns TRUE if the given tree has the "fast_interrupt" attribute. */
+static int
+fast_interrupt_p (tree node ATTRIBUTE_UNUSED)
+{
+ tree list = M32C_ATTRIBUTES (node);
+ while (list)
+ {
+ if (is_attribute_p ("fast_interrupt", TREE_PURPOSE (list)))
+ return 1;
+ list = TREE_CHAIN (list);
+ }
return 0;
}
@@ -2846,6 +2881,8 @@ current_function_special_page_vector (rtx x)
#define TARGET_ATTRIBUTE_TABLE m32c_attribute_table
static const struct attribute_spec m32c_attribute_table[] = {
{"interrupt", 0, 0, false, false, false, interrupt_handler},
+ {"bank_switch", 0, 0, false, false, false, interrupt_handler},
+ {"fast_interrupt", 0, 0, false, false, false, interrupt_handler},
{"function_vector", 1, 1, true, false, false, function_vector_handler},
{0, 0, 0, 0, 0, 0, 0}
};
@@ -3928,16 +3965,23 @@ m32c_emit_prologue (void)
cfun->machine->is_interrupt = 1;
complex_prologue = 1;
}
+ else if (bank_switch_p (cfun->decl))
+ warning (OPT_Wattributes,
+ "%<bank_switch%> has no effect on non-interrupt functions");
reg_save_size = m32c_pushm_popm (PP_justcount);
if (interrupt_p (cfun->decl))
- emit_insn (gen_pushm (GEN_INT (cfun->machine->intr_pushm)));
+ {
+ if (bank_switch_p (cfun->decl))
+ emit_insn (gen_fset_b ());
+ else if (cfun->machine->intr_pushm)
+ emit_insn (gen_pushm (GEN_INT (cfun->machine->intr_pushm)));
+ }
frame_size =
m32c_initial_elimination_offset (FB_REGNO, SP_REGNO) - reg_save_size;
if (frame_size == 0
- && !cfun->machine->is_interrupt
&& !m32c_function_needs_enter ())
cfun->machine->use_rts = 1;
@@ -3988,16 +4032,29 @@ m32c_emit_epilogue (void)
{
enum machine_mode spmode = TARGET_A16 ? HImode : PSImode;
- emit_move_insn (gen_rtx_REG (spmode, A0_REGNO),
- gen_rtx_REG (spmode, FP_REGNO));
- emit_move_insn (gen_rtx_REG (spmode, SP_REGNO),
- gen_rtx_REG (spmode, A0_REGNO));
- if (TARGET_A16)
- emit_insn (gen_pophi_16 (gen_rtx_REG (HImode, FP_REGNO)));
- else
- emit_insn (gen_poppsi (gen_rtx_REG (PSImode, FP_REGNO)));
- emit_insn (gen_popm (GEN_INT (cfun->machine->intr_pushm)));
- if (TARGET_A16)
+ /* REIT clears B flag and restores $fp for us, but we still
+ have to fix up the stack. USE_RTS just means we didn't
+ emit ENTER. */
+ if (!cfun->machine->use_rts)
+ {
+ emit_move_insn (gen_rtx_REG (spmode, A0_REGNO),
+ gen_rtx_REG (spmode, FP_REGNO));
+ emit_move_insn (gen_rtx_REG (spmode, SP_REGNO),
+ gen_rtx_REG (spmode, A0_REGNO));
+ /* We can't just add this to the POPM because it would be in
+ the wrong order, and wouldn't fix the stack if we're bank
+ switching. */
+ if (TARGET_A16)
+ emit_insn (gen_pophi_16 (gen_rtx_REG (HImode, FP_REGNO)));
+ else
+ emit_insn (gen_poppsi (gen_rtx_REG (PSImode, FP_REGNO)));
+ }
+ if (!bank_switch_p (cfun->decl) && cfun->machine->intr_pushm)
+ emit_insn (gen_popm (GEN_INT (cfun->machine->intr_pushm)));
+
+ if (fast_interrupt_p (cfun->decl))
+ emit_jump_insn (gen_epilogue_freit ());
+ else if (TARGET_A16)
emit_jump_insn (gen_epilogue_reit_16 ());
else
emit_jump_insn (gen_epilogue_reit_24 ());
diff --git a/gcc/config/m32c/m32c.md b/gcc/config/m32c/m32c.md
index da0f8dd23f9..739f24c177e 100644
--- a/gcc/config/m32c/m32c.md
+++ b/gcc/config/m32c/m32c.md
@@ -47,6 +47,8 @@
(UNS_SSTR 7)
(UNS_SCMPU 8)
(UNS_SMOVU 9)
+ (UNS_FSETB 10)
+ (UNS_FREIT 11)
])
;; n = no change, x = clobbered. The first 16 values are chosen such
diff --git a/gcc/config/m32c/prologue.md b/gcc/config/m32c/prologue.md
index 9db49204aae..175b2b0ab9f 100644
--- a/gcc/config/m32c/prologue.md
+++ b/gcc/config/m32c/prologue.md
@@ -149,6 +149,15 @@
[(set_attr "flags" "x")]
)
+(define_insn "epilogue_freit"
+ [(unspec [(const_int 0)] UNS_FREIT)
+ (return)
+ ]
+ ""
+ "freit"
+ [(set_attr "flags" "x")]
+ )
+
(define_insn "epilogue_rts"
[(return)
]
@@ -180,3 +189,11 @@
"popm\t%p0"
[(set_attr "flags" "n")]
)
+
+(define_insn "fset_b"
+ [(unspec [(const_int 0)] UNS_FSETB)]
+ ""
+ "fset\tB"
+ [(set_attr "flags" "n")]
+ )
+