mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-04-08 20:52:05 +08:00
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:
parent
df15255add
commit
65655f7921
@ -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.
|
||||
|
@ -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 ());
|
||||
|
@ -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
|
||||
|
@ -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")]
|
||||
)
|
||||
|
||||
|
@ -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
|
||||
|
Loading…
x
Reference in New Issue
Block a user