m32c.md (UNS_FSETB, UNS_FREIT): New.

* 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.

From-SVN: r150862
This commit is contained in:
DJ Delorie 2009-08-17 18:25:06 -04:00 committed by DJ Delorie
parent df15255add
commit 65655f7921
5 changed files with 122 additions and 14 deletions

View File

@ -1,3 +1,22 @@
2009-08-17 DJ Delorie <dj@redhat.com>
* 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.
2009-08-17 Douglas B Rupp <rupp@gnat.com>
* config/alpha/alpha.c (vms_valid_pointer_mode): New function.

View File

@ -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 ());

View File

@ -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

View File

@ -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")]
)

View File

@ -2019,6 +2019,12 @@ info format it will either mean marking the function as artificial
or using the caller location for all instructions within the inlined
body.
@item bank_switch
@cindex interrupt handler functions
When added to an interrupt handler with the M32C port, causes the
prologue and epilogue to use bank switching to preserve the registers
rather than saving them on the stack.
@item flatten
@cindex @code{flatten} function attribute
Generally, inlining into a function is limited. For a function marked with
@ -2272,6 +2278,13 @@ On MeP targets this causes the compiler to use a calling convention
which assumes the called function is too far away for the built-in
addressing modes.
@item fast_interrupt
@cindex interrupt handler functions
Use this attribute on the M32C port to indicate that the specified
function is a fast interrupt handler. This is just like the
@code{interrupt} attribute, except that @code{freit} is used to return
instead of @code{reit}.
@item fastcall
@cindex functions that pop the argument stack on the 386
On the Intel 386, the @code{fastcall} attribute causes the compiler to