Commit 460f4b9d by Jeff Law

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
parent f046b3cc
...@@ -347,8 +347,11 @@ print_operand_address (file, addr) ...@@ -347,8 +347,11 @@ print_operand_address (file, addr)
int int
can_use_return_insn () can_use_return_insn ()
{ {
/* SIZE includes the fixed stack space needed for function calls. */ /* size includes the fixed stack space needed for function calls. */
int size = get_frame_size () + (!leaf_function_p () ? 12 : 0); 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 return (reload_completed
&& size == 0 && size == 0
...@@ -416,11 +419,6 @@ expand_prologue () ...@@ -416,11 +419,6 @@ expand_prologue ()
{ {
unsigned int size; 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 /* 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. */ for the entire function. If so, set ZERO_DREG and ZERO_AREG. */
if (regs_ever_live[2] || regs_ever_live[3] if (regs_ever_live[2] || regs_ever_live[3]
...@@ -478,10 +476,8 @@ expand_prologue () ...@@ -478,10 +476,8 @@ expand_prologue ()
} }
/* SIZE includes the fixed stack space needed for function calls. */ /* SIZE includes the fixed stack space needed for function calls. */
size = get_frame_size () + (!leaf_function_p () ? 12 : 0); size = get_frame_size () + current_function_outgoing_args_size;
size += (current_function_outgoing_args_size ? 4 : 0);
/* Start a new sequence for the prologue/epilogue. */
start_sequence ();
/* If this is an old-style varargs function, then its arguments /* If this is an old-style varargs function, then its arguments
need to be flushed back to the stack. */ need to be flushed back to the stack. */
...@@ -527,15 +523,9 @@ expand_epilogue () ...@@ -527,15 +523,9 @@ expand_epilogue ()
{ {
unsigned int size; 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 includes the fixed stack space needed for function calls. */
size = get_frame_size () + (!leaf_function_p () ? 12 : 0); size = get_frame_size () + current_function_outgoing_args_size;
size += (current_function_outgoing_args_size ? 4 : 0);
/* Start a new sequence for the prologue/epilogue. */
start_sequence ();
/* Cut back the stack. */ /* Cut back the stack. */
if (frame_pointer_needed) if (frame_pointer_needed)
...@@ -705,16 +695,22 @@ initial_offset (from, to) ...@@ -705,16 +695,22 @@ initial_offset (from, to)
if (regs_ever_live[2] || regs_ever_live[3] if (regs_ever_live[2] || regs_ever_live[3]
|| regs_ever_live[6] || regs_ever_live[7] || regs_ever_live[6] || regs_ever_live[7]
|| frame_pointer_needed) || 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 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 /* 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 of the size of this function's frame and the fixed stack space needed
for function calls (if any). */ for function calls (if any). */
if (from == FRAME_POINTER_REGNUM && to == STACK_POINTER_REGNUM) 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 (); abort ();
} }
...@@ -934,3 +930,28 @@ output_tst (operand, insn) ...@@ -934,3 +930,28 @@ output_tst (operand, insn)
} }
return "cmp 0,%0"; 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 { ...@@ -374,29 +374,6 @@ enum reg_class {
/* Register in which static-chain is passed to a function. */ /* Register in which static-chain is passed to a function. */
#define STATIC_CHAIN_REGNUM 5 #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 \ #define ELIMINABLE_REGS \
{{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \ {{ ARG_POINTER_REGNUM, STACK_POINTER_REGNUM}, \
{ ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \ { ARG_POINTER_REGNUM, FRAME_POINTER_REGNUM}, \
...@@ -407,8 +384,9 @@ enum reg_class { ...@@ -407,8 +384,9 @@ enum reg_class {
#define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \ #define INITIAL_ELIMINATION_OFFSET(FROM, TO, OFFSET) \
OFFSET = initial_offset (FROM, TO) OFFSET = initial_offset (FROM, TO)
#define FRAME_POINTER_REQUIRED \ /* We can debug without frame pointers on the mn10300, so eliminate
!(leaf_function_p () || current_function_outgoing_args_size == 0) them whenever possible. */
#define FRAME_POINTER_REQUIRED 0
#define CAN_DEBUG_WITHOUT_FP #define CAN_DEBUG_WITHOUT_FP
/* A guess for the MN10300. */ /* A guess for the MN10300. */
...@@ -426,6 +404,8 @@ enum reg_class { ...@@ -426,6 +404,8 @@ enum reg_class {
/* We use d0/d1 for passing parameters, so allocate 8 bytes of space /* We use d0/d1 for passing parameters, so allocate 8 bytes of space
for a register flushback area. */ for a register flushback area. */
#define REG_PARM_STACK_SPACE(DECL) 8 #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 /* So we can allocate space for return pointers once for the function
instead of around every call. */ instead of around every call. */
...@@ -500,8 +480,9 @@ extern struct rtx_def *function_arg (); ...@@ -500,8 +480,9 @@ extern struct rtx_def *function_arg ();
VALTYPE is the data type of the value (as a tree). VALTYPE is the data type of the value (as a tree).
If the precise function being called is known, FUNC is its FUNCTION_DECL; If the precise function being called is known, FUNC is its FUNCTION_DECL;
otherwise, FUNC is 0. */ 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 /* Define how to find the value returned by a library function
assuming the value has mode MODE. */ assuming the value has mode MODE. */
...@@ -510,7 +491,7 @@ extern struct rtx_def *function_arg (); ...@@ -510,7 +491,7 @@ extern struct rtx_def *function_arg ();
/* 1 if N is a possible register number for a function value. */ /* 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. */ /* Return values > 8 bytes in length in memory. */
#define DEFAULT_PCC_STRUCT_RETURN 0 #define DEFAULT_PCC_STRUCT_RETURN 0
...@@ -1014,6 +995,7 @@ extern void expand_prologue (); ...@@ -1014,6 +995,7 @@ extern void expand_prologue ();
extern void expand_epilogue (); extern void expand_epilogue ();
extern void notice_update_cc (); extern void notice_update_cc ();
extern int call_address_operand (); extern int call_address_operand ();
extern int impossible_plus_operand ();
extern enum reg_class secondary_reload_class (); extern enum reg_class secondary_reload_class ();
extern int initial_offset (); extern int initial_offset ();
extern char *output_tst (); extern char *output_tst ();
...@@ -156,6 +156,22 @@ ...@@ -156,6 +156,22 @@
;; movsi and helpers ;; 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" (define_expand "movsi"
[(set (match_operand:SI 0 "general_operand" "") [(set (match_operand:SI 0 "general_operand" "")
(match_operand:SI 1 "general_operand" ""))] (match_operand:SI 1 "general_operand" ""))]
...@@ -646,7 +662,7 @@ ...@@ -646,7 +662,7 @@
}") }")
(define_insn "" (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") (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")))] (match_operand:SI 2 "nonmemory_operand" "J,J,L,dai,i,da")))]
"" ""
...@@ -657,7 +673,7 @@ ...@@ -657,7 +673,7 @@
add %2,%0 add %2,%0
add %2,%0 add %2,%0
mov %2,%0\;add %1,%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" (define_expand "adddi3"
[(set (reg:DI 0) (match_operand:DI 1 "register_operand" "")) [(set (reg:DI 0) (match_operand:DI 1 "register_operand" ""))
...@@ -1211,7 +1227,7 @@ ...@@ -1211,7 +1227,7 @@
}") }")
(define_insn "call_value_internal" (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")) (call (mem:QI (match_operand:SI 1 "call_address_operand" "aS"))
(match_operand:SI 2 "general_operand" "g")))] (match_operand:SI 2 "general_operand" "g")))]
"" ""
...@@ -1424,3 +1440,4 @@ ...@@ -1424,3 +1440,4 @@
"dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])" "dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
"add %0,%0\;bcc %1" "add %0,%0\;bcc %1"
[(set_attr "cc" "clobber")]) [(set_attr "cc" "clobber")])
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment