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:
Jeff Law 1997-04-14 14:59:44 -06:00
parent f046b3cc23
commit 460f4b9ddd
3 changed files with 73 additions and 53 deletions

View File

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

View File

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

View File

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