mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-19 03:30:27 +08:00
mn10300.c (can_use_return_insn): Include outgoing argument area in size computation.
* mn10300.c (can_use_return_insn): Include outgoing argument area in size computation. (expand_prologue): Likewise. No longer diddle with sequences. Put register saves just before outgoing argument area. (expand_epilogue): Similarly. (impossible_plus_operand): New function. * mn10300.h (FRAME_POINTER_REQUIRED): Never require a frame pointer. (ACCUMULATE_OUTGOING_ARGS, OUTGOING_REG_PARM_STACK_SPACE): Define. (impossible_plus_operand): Declare. * mn10300.md (reload_insi): New expander to handle pathological reload cases. (addsi3): Fix CC status. * mn10300.h (FUNCTION_VALUE): Return addresses in $a0. (FUNCTION_VALUE_REGNO_P): Corresponding changes. * mn10300.md (call_value_internal): Allow output to be in an address register. From-SVN: r13903
This commit is contained in:
parent
f046b3cc23
commit
460f4b9ddd
@ -347,8 +347,11 @@ print_operand_address (file, addr)
|
||||
int
|
||||
can_use_return_insn ()
|
||||
{
|
||||
/* SIZE includes the fixed stack space needed for function calls. */
|
||||
int size = get_frame_size () + (!leaf_function_p () ? 12 : 0);
|
||||
/* size includes the fixed stack space needed for function calls. */
|
||||
int size = get_frame_size () + current_function_outgoing_args_size;
|
||||
|
||||
/* And space for the return pointer. */
|
||||
size += current_function_outgoing_args_size ? 4 : 0;
|
||||
|
||||
return (reload_completed
|
||||
&& size == 0
|
||||
@ -416,11 +419,6 @@ expand_prologue ()
|
||||
{
|
||||
unsigned int size;
|
||||
|
||||
/* We have to end the current sequence so leaf_function_p and
|
||||
count_tst_insns will work. We then start a new sequence to
|
||||
hold the prologue/epilogue. */
|
||||
end_sequence ();
|
||||
|
||||
/* Determine if it is profitable to put the value zero into a register
|
||||
for the entire function. If so, set ZERO_DREG and ZERO_AREG. */
|
||||
if (regs_ever_live[2] || regs_ever_live[3]
|
||||
@ -478,10 +476,8 @@ expand_prologue ()
|
||||
}
|
||||
|
||||
/* SIZE includes the fixed stack space needed for function calls. */
|
||||
size = get_frame_size () + (!leaf_function_p () ? 12 : 0);
|
||||
|
||||
/* Start a new sequence for the prologue/epilogue. */
|
||||
start_sequence ();
|
||||
size = get_frame_size () + current_function_outgoing_args_size;
|
||||
size += (current_function_outgoing_args_size ? 4 : 0);
|
||||
|
||||
/* If this is an old-style varargs function, then its arguments
|
||||
need to be flushed back to the stack. */
|
||||
@ -527,15 +523,9 @@ expand_epilogue ()
|
||||
{
|
||||
unsigned int size;
|
||||
|
||||
/* We have to end the current sequence so leaf_function_p will
|
||||
work. We then start a new sequence to hold the prologue/epilogue. */
|
||||
end_sequence ();
|
||||
|
||||
/* SIZE includes the fixed stack space needed for function calls. */
|
||||
size = get_frame_size () + (!leaf_function_p () ? 12 : 0);
|
||||
|
||||
/* Start a new sequence for the prologue/epilogue. */
|
||||
start_sequence ();
|
||||
size = get_frame_size () + current_function_outgoing_args_size;
|
||||
size += (current_function_outgoing_args_size ? 4 : 0);
|
||||
|
||||
/* Cut back the stack. */
|
||||
if (frame_pointer_needed)
|
||||
@ -705,16 +695,22 @@ initial_offset (from, to)
|
||||
if (regs_ever_live[2] || regs_ever_live[3]
|
||||
|| regs_ever_live[6] || regs_ever_live[7]
|
||||
|| frame_pointer_needed)
|
||||
return (get_frame_size () + 16 + (!leaf_function_p () ? 12 : 0));
|
||||
return (get_frame_size () + 16
|
||||
+ (current_function_outgoing_args_size
|
||||
? current_function_outgoing_args_size + 4 : 0));
|
||||
else
|
||||
return (get_frame_size () + (!leaf_function_p () ? 12 : 0));
|
||||
return (get_frame_size ()
|
||||
+ (current_function_outgoing_args_size
|
||||
? current_function_outgoing_args_size + 4 : 0));
|
||||
}
|
||||
|
||||
/* The difference between the frame pointer and stack pointer is the sum
|
||||
of the size of this function's frame and the fixed stack space needed
|
||||
for function calls (if any). */
|
||||
if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM)
|
||||
return get_frame_size () + (!leaf_function_p () ? 12 : 0);
|
||||
return (get_frame_size ()
|
||||
+ (current_function_outgoing_args_size
|
||||
? current_function_outgoing_args_size + 4 : 0));
|
||||
|
||||
abort ();
|
||||
}
|
||||
@ -934,3 +930,28 @@ output_tst (operand, insn)
|
||||
}
|
||||
return "cmp 0,%0";
|
||||
}
|
||||
|
||||
int
|
||||
impossible_plus_operand (op, mode)
|
||||
rtx op;
|
||||
enum machine_mode mode;
|
||||
{
|
||||
extern rtx *reg_equiv_mem;
|
||||
rtx reg1, reg2;
|
||||
|
||||
if (GET_CODE (op) != PLUS)
|
||||
return 0;
|
||||
|
||||
if ((XEXP (op, 0) == stack_pointer_rtx)
|
||||
&& ((REG_P (XEXP (op, 1)) && reg_equiv_mem [REGNO (XEXP (op, 1))])
|
||||
|| (GET_CODE (XEXP (op, 1)) == SUBREG
|
||||
&& GET_CODE (SUBREG_REG (XEXP (op, 1))) == MEM)))
|
||||
return 1;
|
||||
|
||||
if ((XEXP (op, 1) == stack_pointer_rtx)
|
||||
&& ((REG_P (XEXP (op, 0)) && reg_equiv_mem [REGNO (XEXP (op, 0))])
|
||||
|| (GET_CODE (XEXP (op, 0)) == SUBREG
|
||||
&& GET_CODE (SUBREG_REG (XEXP (op, 0))) == MEM)))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
@ -374,29 +374,6 @@ enum reg_class {
|
||||
/* Register in which static-chain is passed to a function. */
|
||||
#define STATIC_CHAIN_REGNUM 5
|
||||
|
||||
/* Value should be nonzero if functions must have frame pointers.
|
||||
Zero means the frame pointer need not be set up (and parms
|
||||
may be accessed via the stack pointer) in functions that seem suitable.
|
||||
This is computed in `reload', in reload1.c.
|
||||
|
||||
We allow frame pointers to be eliminated when not having one will
|
||||
not interfere with debugging.
|
||||
|
||||
* If this is a leaf function, then we can keep the stack pointer
|
||||
constant throughout the function, and therefore gdb can easily
|
||||
find the base of the current frame.
|
||||
|
||||
* If this function never allocates stack space for outgoing
|
||||
args (ie calls functions with either no args, or args only
|
||||
in registers), then the stack pointer will be constant and
|
||||
gdb can easily find the base of the current frame.
|
||||
|
||||
We'd really like to define ACCUMULATE_OUTGOING_ARGS and eliminate
|
||||
all frame pointer, but currently we can't.
|
||||
|
||||
We probably also want a -m option to eliminate frame pointer, even
|
||||
if the resulting executable can not be debugged. */
|
||||
|
||||
#define ELIMINABLE_REGS \
|
||||
{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
|
||||
{ ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
|
||||
@ -407,8 +384,9 @@ enum reg_class {
|
||||
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
|
||||
OFFSET = initial_offset (FROM, TO)
|
||||
|
||||
#define FRAME_POINTER_REQUIRED \
|
||||
!(leaf_function_p () || current_function_outgoing_args_size == 0)
|
||||
/* We can debug without frame pointers on the mn10300, so eliminate
|
||||
them whenever possible. */
|
||||
#define FRAME_POINTER_REQUIRED 0
|
||||
#define CAN_DEBUG_WITHOUT_FP
|
||||
|
||||
/* A guess for the MN10300. */
|
||||
@ -426,6 +404,8 @@ enum reg_class {
|
||||
/* We use d0/d1 for passing parameters, so allocate 8 bytes of space
|
||||
for a register flushback area. */
|
||||
#define REG_PARM_STACK_SPACE(DECL) 8
|
||||
#define OUTGOING_REG_PARM_STACK_SPACE
|
||||
#define ACCUMULATE_OUTGOING_ARGS
|
||||
|
||||
/* So we can allocate space for return pointers once for the function
|
||||
instead of around every call. */
|
||||
@ -500,8 +480,9 @@ extern struct rtx_def *function_arg ();
|
||||
VALTYPE is the data type of the value (as a tree).
|
||||
If the precise function being called is known, FUNC is its FUNCTION_DECL;
|
||||
otherwise, FUNC is 0. */
|
||||
|
||||
#define FUNCTION_VALUE(VALTYPE, FUNC) gen_rtx (REG, TYPE_MODE (VALTYPE), 0)
|
||||
|
||||
#define FUNCTION_VALUE(VALTYPE, FUNC) \
|
||||
gen_rtx (REG, TYPE_MODE (VALTYPE), POINTER_TYPE_P (VALTYPE) ? 4 : 0)
|
||||
|
||||
/* Define how to find the value returned by a library function
|
||||
assuming the value has mode MODE. */
|
||||
@ -510,7 +491,7 @@ extern struct rtx_def *function_arg ();
|
||||
|
||||
/* 1 if N is a possible register number for a function value. */
|
||||
|
||||
#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0)
|
||||
#define FUNCTION_VALUE_REGNO_P(N) ((N) == 0 || (N) == 4)
|
||||
|
||||
/* Return values > 8 bytes in length in memory. */
|
||||
#define DEFAULT_PCC_STRUCT_RETURN 0
|
||||
@ -1014,6 +995,7 @@ extern void expand_prologue ();
|
||||
extern void expand_epilogue ();
|
||||
extern void notice_update_cc ();
|
||||
extern int call_address_operand ();
|
||||
extern int impossible_plus_operand ();
|
||||
extern enum reg_class secondary_reload_class ();
|
||||
extern int initial_offset ();
|
||||
extern char *output_tst ();
|
||||
|
@ -156,6 +156,22 @@
|
||||
|
||||
;; movsi and helpers
|
||||
|
||||
;; We use this to handle addition of two values when one operand is the
|
||||
;; stack pointer and the other is a memory reference of some kind. Reload
|
||||
;; does not handle them correctly without this expander.
|
||||
(define_expand "reload_insi"
|
||||
[(set (match_operand:SI 0 "register_operand" "=a")
|
||||
(match_operand:SI 1 "impossible_plus_operand" ""))
|
||||
(clobber (match_operand:SI 2 "register_operand" "=&a"))]
|
||||
""
|
||||
"
|
||||
{
|
||||
emit_move_insn (operands[0], XEXP (operands[1], 0));
|
||||
emit_move_insn (operands[2], XEXP (operands[1], 1));
|
||||
emit_insn (gen_addsi3 (operands[0], operands[0], operands[2]));
|
||||
DONE;
|
||||
}")
|
||||
|
||||
(define_expand "movsi"
|
||||
[(set (match_operand:SI 0 "general_operand" "")
|
||||
(match_operand:SI 1 "general_operand" ""))]
|
||||
@ -646,7 +662,7 @@
|
||||
}")
|
||||
|
||||
(define_insn ""
|
||||
[(set (match_operand:SI 0 "register_operand" "=d,a,a,da,x,!&da")
|
||||
[(set (match_operand:SI 0 "register_operand" "=d,a,a,da,x,&!da")
|
||||
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0,da")
|
||||
(match_operand:SI 2 "nonmemory_operand" "J,J,L,dai,i,da")))]
|
||||
""
|
||||
@ -657,7 +673,7 @@
|
||||
add %2,%0
|
||||
add %2,%0
|
||||
mov %2,%0\;add %1,%0"
|
||||
[(set_attr "cc" "set_zn_c0,none_0hit,none_0hit,set_zn_c0,none_0hit,none_0hit")])
|
||||
[(set_attr "cc" "set_zn_c0,none_0hit,none_0hit,set_zn_c0,none_0hit,set_zn_c0")])
|
||||
|
||||
(define_expand "adddi3"
|
||||
[(set (reg:DI 0) (match_operand:DI 1 "register_operand" ""))
|
||||
@ -1211,7 +1227,7 @@
|
||||
}")
|
||||
|
||||
(define_insn "call_value_internal"
|
||||
[(set (match_operand 0 "" "=d")
|
||||
[(set (match_operand 0 "" "=da")
|
||||
(call (mem:QI (match_operand:SI 1 "call_address_operand" "aS"))
|
||||
(match_operand:SI 2 "general_operand" "g")))]
|
||||
""
|
||||
@ -1424,3 +1440,4 @@
|
||||
"dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
|
||||
"add %0,%0\;bcc %1"
|
||||
[(set_attr "cc" "clobber")])
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user