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
{
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]
}
/* 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. */
{
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)
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 ();
}
}
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;
+}
/* 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}, \
#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. */
/* 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. */
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. */
/* 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
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 ();
;; 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" ""))]
}")
(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")))]
""
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" ""))
}")
(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")))]
""
"dead_or_set_p (ins1, operands[0]) && REG_OK_FOR_INDEX_P (operands[0])"
"add %0,%0\;bcc %1"
[(set_attr "cc" "clobber")])
+