summaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1997-04-14 20:59:44 +0000
committerlaw <law@138bc75d-0d04-0410-961f-82ee72b054a4>1997-04-14 20:59:44 +0000
commit36ed44068db8a11c50e1494c752b07599e877eeb (patch)
tree9c02115a5fab37fecb33b292a41ee8321de14ddc /gcc
parentd3c451dde186316692e666f3131d302c4f9cbce4 (diff)
downloadgcc-36ed44068db8a11c50e1494c752b07599e877eeb.tar.gz
* 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. git-svn-id: svn+ssh://gcc.gnu.org/svn/gcc/trunk@13903 138bc75d-0d04-0410-961f-82ee72b054a4
Diffstat (limited to 'gcc')
-rw-r--r--gcc/config/mn10300/mn10300.c65
-rw-r--r--gcc/config/mn10300/mn10300.h38
-rw-r--r--gcc/config/mn10300/mn10300.md23
3 files changed, 73 insertions, 53 deletions
diff --git a/gcc/config/mn10300/mn10300.c b/gcc/config/mn10300/mn10300.c
index 10e7ae36030..f2161024dc0 100644
--- a/gcc/config/mn10300/mn10300.c
+++ b/gcc/config/mn10300/mn10300.c
@@ -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;
+}
diff --git a/gcc/config/mn10300/mn10300.h b/gcc/config/mn10300/mn10300.h
index c36c6c499f6..d7ac6af3e99 100644
--- a/gcc/config/mn10300/mn10300.h
+++ b/gcc/config/mn10300/mn10300.h
@@ -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 ();
diff --git a/gcc/config/mn10300/mn10300.md b/gcc/config/mn10300/mn10300.md
index 13628ecf1f3..d936a02df12 100644
--- a/gcc/config/mn10300/mn10300.md
+++ b/gcc/config/mn10300/mn10300.md
@@ -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")])
+