m68k-protos.h (output_sibcall): Declare.
gcc/ * config/m68k/m68k-protos.h (output_sibcall): Declare. (mips_expand_epilogue): Add a bool parameter. (m68k_legitimize_sibcall_address): Declare. * config/m68k/m68k.c (TARGET_FUNCTION_OK_FOR_SIBCALL): Define. (m68k_expand_epilogue): Add a parameter to select between sibling and normal epilogues. Only generate a return for the latter. (m68k_ok_for_sibcall_p): New function. (m68k_legitimize_sibcall_address, output_sibcall): New functions. * config/m68k/m68k.md (sibcall, *sibcall): New patterns. (sibcall_value, *sibcall_value): Likewise. (*call, *call_value): Require !SIBLING_CALL_P. (epilogue): Update call to m68k_expand_epilogue. (sibcall_epilogue): New pattern. * config/m68k/predicates.md (const_call_operand): Say that this predicate applies to sibling calls too. (sibcall_operand): New predicate. From-SVN: r122607
This commit is contained in:
parent
31c5b44477
commit
f7e7089441
@ -1,3 +1,22 @@
|
|||||||
|
2007-03-06 Richard Sandiford <richard@codesourcery.com>
|
||||||
|
|
||||||
|
* config/m68k/m68k-protos.h (output_sibcall): Declare.
|
||||||
|
(mips_expand_epilogue): Add a bool parameter.
|
||||||
|
(m68k_legitimize_sibcall_address): Declare.
|
||||||
|
* config/m68k/m68k.c (TARGET_FUNCTION_OK_FOR_SIBCALL): Define.
|
||||||
|
(m68k_expand_epilogue): Add a parameter to select between sibling
|
||||||
|
and normal epilogues. Only generate a return for the latter.
|
||||||
|
(m68k_ok_for_sibcall_p): New function.
|
||||||
|
(m68k_legitimize_sibcall_address, output_sibcall): New functions.
|
||||||
|
* config/m68k/m68k.md (sibcall, *sibcall): New patterns.
|
||||||
|
(sibcall_value, *sibcall_value): Likewise.
|
||||||
|
(*call, *call_value): Require !SIBLING_CALL_P.
|
||||||
|
(epilogue): Update call to m68k_expand_epilogue.
|
||||||
|
(sibcall_epilogue): New pattern.
|
||||||
|
* config/m68k/predicates.md (const_call_operand): Say that this
|
||||||
|
predicate applies to sibling calls too.
|
||||||
|
(sibcall_operand): New predicate.
|
||||||
|
|
||||||
2007-03-06 Richard Sandiford <richard@codesourcery.com>
|
2007-03-06 Richard Sandiford <richard@codesourcery.com>
|
||||||
|
|
||||||
* config/m68k/m68k.md (movsf_cf_soft): Provide the same non-mov3q
|
* config/m68k/m68k.md (movsf_cf_soft): Provide the same non-mov3q
|
||||||
|
@ -42,6 +42,7 @@ extern const char *output_andsi3 (rtx *);
|
|||||||
extern const char *output_iorsi3 (rtx *);
|
extern const char *output_iorsi3 (rtx *);
|
||||||
extern const char *output_xorsi3 (rtx *);
|
extern const char *output_xorsi3 (rtx *);
|
||||||
extern const char *output_call (rtx);
|
extern const char *output_call (rtx);
|
||||||
|
extern const char *output_sibcall (rtx);
|
||||||
extern void output_dbcc_and_branch (rtx *);
|
extern void output_dbcc_and_branch (rtx *);
|
||||||
extern int floating_exact_log2 (rtx);
|
extern int floating_exact_log2 (rtx);
|
||||||
extern bool strict_low_part_peephole_ok (enum machine_mode mode, rtx first_insn, rtx target);
|
extern bool strict_low_part_peephole_ok (enum machine_mode mode, rtx first_insn, rtx target);
|
||||||
@ -71,10 +72,11 @@ extern bool m68k_regno_mode_ok (int, enum machine_mode);
|
|||||||
extern int flags_in_68881 (void);
|
extern int flags_in_68881 (void);
|
||||||
extern void m68k_expand_prologue (void);
|
extern void m68k_expand_prologue (void);
|
||||||
extern bool m68k_use_return_insn (void);
|
extern bool m68k_use_return_insn (void);
|
||||||
extern void m68k_expand_epilogue (void);
|
extern void m68k_expand_epilogue (bool);
|
||||||
extern void override_options (void);
|
extern void override_options (void);
|
||||||
extern const char *m68k_cpp_cpu_ident (const char *);
|
extern const char *m68k_cpp_cpu_ident (const char *);
|
||||||
extern const char *m68k_cpp_cpu_family (const char *);
|
extern const char *m68k_cpp_cpu_family (const char *);
|
||||||
extern void init_68881_table (void);
|
extern void init_68881_table (void);
|
||||||
extern rtx m68k_legitimize_call_address (rtx);
|
extern rtx m68k_legitimize_call_address (rtx);
|
||||||
|
extern rtx m68k_legitimize_sibcall_address (rtx);
|
||||||
extern int m68k_hard_regno_rename_ok(unsigned int, unsigned int);
|
extern int m68k_hard_regno_rename_ok(unsigned int, unsigned int);
|
||||||
|
@ -146,6 +146,7 @@ static tree m68k_handle_fndecl_attribute (tree *node, tree name,
|
|||||||
bool *no_add_attrs);
|
bool *no_add_attrs);
|
||||||
static void m68k_compute_frame_layout (void);
|
static void m68k_compute_frame_layout (void);
|
||||||
static bool m68k_save_reg (unsigned int regno, bool interrupt_handler);
|
static bool m68k_save_reg (unsigned int regno, bool interrupt_handler);
|
||||||
|
static bool m68k_ok_for_sibcall_p (tree, tree);
|
||||||
static bool m68k_rtx_costs (rtx, int, int, int *);
|
static bool m68k_rtx_costs (rtx, int, int, int *);
|
||||||
|
|
||||||
|
|
||||||
@ -215,6 +216,9 @@ int m68k_last_compare_had_fp_operands;
|
|||||||
#undef TARGET_CANNOT_FORCE_CONST_MEM
|
#undef TARGET_CANNOT_FORCE_CONST_MEM
|
||||||
#define TARGET_CANNOT_FORCE_CONST_MEM m68k_illegitimate_symbolic_constant_p
|
#define TARGET_CANNOT_FORCE_CONST_MEM m68k_illegitimate_symbolic_constant_p
|
||||||
|
|
||||||
|
#undef TARGET_FUNCTION_OK_FOR_SIBCALL
|
||||||
|
#define TARGET_FUNCTION_OK_FOR_SIBCALL m68k_ok_for_sibcall_p
|
||||||
|
|
||||||
static const struct attribute_spec m68k_attribute_table[] =
|
static const struct attribute_spec m68k_attribute_table[] =
|
||||||
{
|
{
|
||||||
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
/* { name, min_len, max_len, decl_req, type_req, fn_type_req, handler } */
|
||||||
@ -1015,7 +1019,8 @@ m68k_use_return_insn (void)
|
|||||||
return current_frame.offset == 0;
|
return current_frame.offset == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emit RTL for the "epilogue" define_expand.
|
/* Emit RTL for the "epilogue" or "sibcall_epilogue" define_expand;
|
||||||
|
SIBCALL_P says which.
|
||||||
|
|
||||||
The function epilogue should not depend on the current stack pointer!
|
The function epilogue should not depend on the current stack pointer!
|
||||||
It should use the frame pointer only, if there is a frame pointer.
|
It should use the frame pointer only, if there is a frame pointer.
|
||||||
@ -1023,7 +1028,7 @@ m68k_use_return_insn (void)
|
|||||||
omit stack adjustments before returning. */
|
omit stack adjustments before returning. */
|
||||||
|
|
||||||
void
|
void
|
||||||
m68k_expand_epilogue (void)
|
m68k_expand_epilogue (bool sibcall_p)
|
||||||
{
|
{
|
||||||
HOST_WIDE_INT fsize, fsize_with_regs;
|
HOST_WIDE_INT fsize, fsize_with_regs;
|
||||||
bool big, restore_from_sp;
|
bool big, restore_from_sp;
|
||||||
@ -1181,6 +1186,7 @@ m68k_expand_epilogue (void)
|
|||||||
stack_pointer_rtx,
|
stack_pointer_rtx,
|
||||||
EH_RETURN_STACKADJ_RTX));
|
EH_RETURN_STACKADJ_RTX));
|
||||||
|
|
||||||
|
if (!sibcall_p)
|
||||||
emit_insn (gen_rtx_RETURN (VOIDmode));
|
emit_insn (gen_rtx_RETURN (VOIDmode));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1218,6 +1224,16 @@ flags_in_68881 (void)
|
|||||||
return cc_status.flags & CC_IN_68881;
|
return cc_status.flags & CC_IN_68881;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Implement TARGET_FUNCTION_OK_FOR_SIBCALL_P. We cannot use sibcalls
|
||||||
|
for nested functions because we use the static chain register for
|
||||||
|
indirect calls. */
|
||||||
|
|
||||||
|
static bool
|
||||||
|
m68k_ok_for_sibcall_p (tree decl ATTRIBUTE_UNUSED, tree exp)
|
||||||
|
{
|
||||||
|
return TREE_OPERAND (exp, 2) == NULL;
|
||||||
|
}
|
||||||
|
|
||||||
/* Convert X to a legitimate function call memory reference and return the
|
/* Convert X to a legitimate function call memory reference and return the
|
||||||
result. */
|
result. */
|
||||||
|
|
||||||
@ -1230,6 +1246,19 @@ m68k_legitimize_call_address (rtx x)
|
|||||||
return replace_equiv_address (x, force_reg (Pmode, XEXP (x, 0)));
|
return replace_equiv_address (x, force_reg (Pmode, XEXP (x, 0)));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Likewise for sibling calls. */
|
||||||
|
|
||||||
|
rtx
|
||||||
|
m68k_legitimize_sibcall_address (rtx x)
|
||||||
|
{
|
||||||
|
gcc_assert (MEM_P (x));
|
||||||
|
if (sibcall_operand (XEXP (x, 0), VOIDmode))
|
||||||
|
return x;
|
||||||
|
|
||||||
|
emit_move_insn (gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM), XEXP (x, 0));
|
||||||
|
return replace_equiv_address (x, gen_rtx_REG (Pmode, STATIC_CHAIN_REGNUM));
|
||||||
|
}
|
||||||
|
|
||||||
/* Output a dbCC; jCC sequence. Note we do not handle the
|
/* Output a dbCC; jCC sequence. Note we do not handle the
|
||||||
floating point version of this sequence (Fdbcc). We also
|
floating point version of this sequence (Fdbcc). We also
|
||||||
do not handle alternative conditions when CC_NO_OVERFLOW is
|
do not handle alternative conditions when CC_NO_OVERFLOW is
|
||||||
@ -4013,6 +4042,17 @@ output_call (rtx x)
|
|||||||
return "jsr %a0";
|
return "jsr %a0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Likewise sibling calls. */
|
||||||
|
|
||||||
|
const char *
|
||||||
|
output_sibcall (rtx x)
|
||||||
|
{
|
||||||
|
if (symbolic_operand (x, VOIDmode))
|
||||||
|
return m68k_symbolic_jump;
|
||||||
|
else
|
||||||
|
return "jmp %a0";
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef M68K_TARGET_COFF
|
#ifdef M68K_TARGET_COFF
|
||||||
|
|
||||||
/* Output assembly to switch to section NAME with attribute FLAGS. */
|
/* Output assembly to switch to section NAME with attribute FLAGS. */
|
||||||
|
@ -6679,6 +6679,41 @@
|
|||||||
"subql #1,%0\;cmpl #-1,%0\;jne %l1";
|
"subql #1,%0\;cmpl #-1,%0\;jne %l1";
|
||||||
})
|
})
|
||||||
|
|
||||||
|
(define_expand "sibcall"
|
||||||
|
[(call (match_operand:QI 0 "memory_operand" "")
|
||||||
|
(match_operand:SI 1 "general_operand" ""))]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
operands[0] = m68k_legitimize_sibcall_address (operands[0]);
|
||||||
|
})
|
||||||
|
|
||||||
|
(define_insn "*sibcall"
|
||||||
|
[(call (mem:QI (match_operand:SI 0 "sibcall_operand" ""))
|
||||||
|
(match_operand:SI 1 "general_operand" ""))]
|
||||||
|
"SIBLING_CALL_P (insn)"
|
||||||
|
{
|
||||||
|
return output_sibcall (operands[0]);
|
||||||
|
})
|
||||||
|
|
||||||
|
(define_expand "sibcall_value"
|
||||||
|
[(set (match_operand 0 "" "")
|
||||||
|
(call (match_operand:QI 1 "memory_operand" "")
|
||||||
|
(match_operand:SI 2 "general_operand" "")))]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
operands[1] = m68k_legitimize_sibcall_address (operands[1]);
|
||||||
|
})
|
||||||
|
|
||||||
|
(define_insn "*sibcall_value"
|
||||||
|
[(set (match_operand 0 "" "=rf,rf")
|
||||||
|
(call (mem:QI (match_operand:SI 1 "sibcall_operand" ""))
|
||||||
|
(match_operand:SI 2 "general_operand" "")))]
|
||||||
|
"SIBLING_CALL_P (insn)"
|
||||||
|
{
|
||||||
|
operands[0] = operands[1];
|
||||||
|
return output_sibcall (operands[0]);
|
||||||
|
})
|
||||||
|
|
||||||
;; Call subroutine with no return value.
|
;; Call subroutine with no return value.
|
||||||
(define_expand "call"
|
(define_expand "call"
|
||||||
[(call (match_operand:QI 0 "memory_operand" "")
|
[(call (match_operand:QI 0 "memory_operand" "")
|
||||||
@ -6693,7 +6728,7 @@
|
|||||||
[(call (mem:QI (match_operand:SI 0 "call_operand" "a,W"))
|
[(call (mem:QI (match_operand:SI 0 "call_operand" "a,W"))
|
||||||
(match_operand:SI 1 "general_operand" "g,g"))]
|
(match_operand:SI 1 "general_operand" "g,g"))]
|
||||||
;; Operand 1 not really used on the m68000.
|
;; Operand 1 not really used on the m68000.
|
||||||
""
|
"!SIBLING_CALL_P (insn)"
|
||||||
{
|
{
|
||||||
return output_call (operands[0]);
|
return output_call (operands[0]);
|
||||||
})
|
})
|
||||||
@ -6715,7 +6750,7 @@
|
|||||||
(call (mem:QI (match_operand:SI 1 "call_operand" "a,W"))
|
(call (mem:QI (match_operand:SI 1 "call_operand" "a,W"))
|
||||||
(match_operand:SI 2 "general_operand" "g,g")))]
|
(match_operand:SI 2 "general_operand" "g,g")))]
|
||||||
;; Operand 2 not really used on the m68000.
|
;; Operand 2 not really used on the m68000.
|
||||||
""
|
"!SIBLING_CALL_P (insn)"
|
||||||
{
|
{
|
||||||
operands[0] = operands[1];
|
operands[0] = operands[1];
|
||||||
return output_call (operands[0]);
|
return output_call (operands[0]);
|
||||||
@ -6774,7 +6809,15 @@
|
|||||||
[(return)]
|
[(return)]
|
||||||
""
|
""
|
||||||
{
|
{
|
||||||
m68k_expand_epilogue ();
|
m68k_expand_epilogue (false);
|
||||||
|
DONE;
|
||||||
|
})
|
||||||
|
|
||||||
|
(define_expand "sibcall_epilogue"
|
||||||
|
[(return)]
|
||||||
|
""
|
||||||
|
{
|
||||||
|
m68k_expand_epilogue (true);
|
||||||
DONE;
|
DONE;
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -159,7 +159,7 @@
|
|||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
;; A constant that can be used the address in a call insn.
|
;; A constant that can be used the address in a call or sibcall insn.
|
||||||
(define_predicate "const_call_operand"
|
(define_predicate "const_call_operand"
|
||||||
(ior (match_operand 0 "const_int_operand")
|
(ior (match_operand 0 "const_int_operand")
|
||||||
(and (match_test "m68k_symbolic_call != NULL")
|
(and (match_test "m68k_symbolic_call != NULL")
|
||||||
@ -170,6 +170,12 @@
|
|||||||
(ior (match_operand 0 "const_call_operand")
|
(ior (match_operand 0 "const_call_operand")
|
||||||
(match_operand 0 "register_operand")))
|
(match_operand 0 "register_operand")))
|
||||||
|
|
||||||
|
;; An operand that can be used as the address in a sibcall insn.
|
||||||
|
(define_predicate "sibcall_operand"
|
||||||
|
(ior (match_operand 0 "const_call_operand")
|
||||||
|
(and (match_code "reg")
|
||||||
|
(match_test "REGNO (op) == STATIC_CHAIN_REGNUM"))))
|
||||||
|
|
||||||
;; TODO: Add a comment here.
|
;; TODO: Add a comment here.
|
||||||
|
|
||||||
(define_predicate "post_inc_operand"
|
(define_predicate "post_inc_operand"
|
||||||
|
Loading…
Reference in New Issue
Block a user