mn10300.h (RETURN_ADDR_RTX): Define.

* mn10300.h (RETURN_ADDR_RTX): Define.

        * mn10300.c (count_tst_insns): New function.
        (expand_prologue): Load zero into data and/or address registers
        if any are free and the function has optimizable tst insns.
        (output_tst): If a suitable register is known to have the
        value zero, use it instead of searching for a suitable register.
        * mn10300.h (zero_dreg, zero_areg): Declare.
        (FRAME_POINTER_NEEDED): Frame pointers are not needed if the
        outgoing argument size is zero.
        * mn10300.md (movXX): Optimize loading zero i        register if possible.  Optimize loading a DF/DI mode value
        into an address register from a constant memory address.
        (addsi3): Provide alternative which doesn't require a matching
        inout operand.
        (return): Optimize consecutive return instructions.

From-SVN: r13845
This commit is contained in:
Jeff Law 1997-04-08 12:41:49 -06:00
parent 90e6057ba5
commit 74452ac323
3 changed files with 491 additions and 86 deletions

View File

@ -1,5 +1,5 @@
/* Subroutines for insn-output.c for Matsushita MN10300 series
Copyright (C) 1996 Free Software Foundation, Inc.
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
Contributed by Jeff Law (law@cygnus.com).
This file is part of GNU CC.
@ -36,6 +36,26 @@ Boston, MA 02111-1307, USA. */
#include "tree.h"
#include "obstack.h"
/* Global registers known to hold the value zero.
Normally we'd depend on CSE and combine to put zero into a
register and re-use it.
However, on the mn10x00 processors we implicitly use the constant
zero in tst instructions, so we might be able to do better by
loading the value into a register in the prologue, then re-useing
that register throughout the function.
We could perform similar optimizations for other constants, but with
gcse due soon, it doesn't seem worth the effort.
These variables hold a rtx for a register known to hold the value
zero throughout the entire function, or NULL if no register of
the appropriate class has such a value throughout the life of the
function. */
rtx zero_dreg;
rtx zero_areg;
void
asm_file_start (file)
FILE *file;
@ -339,15 +359,124 @@ can_use_return_insn ()
&& !frame_pointer_needed);
}
/* Count the number of tst insns which compare a data or address
register with zero. */
static void
count_tst_insns (dreg_countp, areg_countp)
int *dreg_countp;
int *areg_countp;
{
rtx insn;
/* Assume no tst insns exist. */
*dreg_countp = 0;
*areg_countp = 0;
/* If not optimizing, then quit now. */
if (!optimize)
return;
/* Walk through all the insns. */
for (insn = get_insns (); insn; insn = NEXT_INSN (insn))
{
rtx pat;
/* Ignore anything that is not a normal INSN. */
if (GET_CODE (insn) != INSN)
continue;
/* Ignore anything that isn't a SET. */
pat = PATTERN (insn);
if (GET_CODE (pat) != SET)
continue;
/* Check for a tst insn. */
if (SET_DEST (pat) == cc0_rtx
&& GET_CODE (SET_SRC (pat)) == REG)
{
if (REGNO_REG_CLASS (REGNO (SET_SRC (pat))) == DATA_REGS)
(*dreg_countp)++;
if (REGNO_REG_CLASS (REGNO (SET_SRC (pat))) == ADDRESS_REGS)
(*areg_countp)++;
}
/* Setting an address register to zero can also be optimized,
so count it just like a tst insn. */
if (GET_CODE (SET_DEST (pat)) == REG
&& GET_CODE (SET_SRC (pat)) == CONST_INT
&& INTVAL (SET_SRC (pat)) == 0
&& REGNO_REG_CLASS (REGNO (SET_DEST (pat))) == ADDRESS_REGS)
(*areg_countp)++;
}
}
void
expand_prologue ()
{
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. */
/* 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]
|| regs_ever_live[6] || regs_ever_live[7]
|| frame_pointer_needed)
{
int dreg_count, areg_count;
/* Get a count of the number of tst insns which use address and
data registers. */
count_tst_insns (&dreg_count, &areg_count);
/* If there's more than one tst insn using a data register, then
this optimization is a win. */
if (dreg_count > 1
&& (!regs_ever_live[2] || !regs_ever_live[3]))
{
if (!regs_ever_live[2])
{
regs_ever_live[2] = 1;
zero_dreg = gen_rtx (REG, SImode, 2);
}
else
{
regs_ever_live[3] = 1;
zero_dreg = gen_rtx (REG, SImode, 3);
}
}
else
zero_dreg = NULL_RTX;
/* If there's more than two tst insns using an address register,
then this optimization is a win. */
if (areg_count > 2
&& (!regs_ever_live[6] || !regs_ever_live[7]))
{
if (!regs_ever_live[6])
{
regs_ever_live[6] = 1;
zero_areg = gen_rtx (REG, SImode, 6);
}
else
{
regs_ever_live[7] = 1;
zero_areg = gen_rtx (REG, SImode, 7);
}
}
else
zero_areg = NULL_RTX;
}
else
{
zero_dreg = NULL_RTX;
zero_areg = NULL_RTX;
}
/* SIZE includes the fixed stack space needed for function calls. */
size = get_frame_size () + (!leaf_function_p () ? 12 : 0);
@ -384,6 +513,13 @@ expand_prologue ()
emit_insn (gen_addsi3 (stack_pointer_rtx,
stack_pointer_rtx,
GEN_INT (-size)));
/* Load zeros into registers as needed. */
if (zero_dreg)
emit_move_insn (zero_dreg, const0_rtx);
if (zero_areg)
emit_move_insn (zero_areg, const0_rtx);
}
void
@ -713,14 +849,36 @@ char *
output_tst (operand, insn)
rtx operand, insn;
{
rtx temp;
int past_call = 0;
/* If we have a data register which is known to be zero throughout
the function, then use it instead of doing a search. */
if (zero_dreg && REGNO_REG_CLASS (REGNO (operand)) == DATA_REGS)
{
rtx xoperands[2];
xoperands[0] = operand;
xoperands[1] = zero_dreg;
output_asm_insn ("cmp %1,%0", xoperands);
return "";
}
/* Similarly for address registers. */
if (zero_areg && REGNO_REG_CLASS (REGNO (operand)) == ADDRESS_REGS)
{
rtx xoperands[2];
xoperands[0] = operand;
xoperands[1] = zero_areg;
output_asm_insn ("cmp %1,%0", xoperands);
return "";
}
/* We can save a byte if we can find a register which has the value
zero in it. */
temp = PREV_INSN (insn);
while (temp)
while (optimize && temp)
{
rtx set;
@ -759,7 +917,8 @@ output_tst (operand, insn)
if (REG_P (SET_DEST (set))
&& SET_SRC (set) == CONST0_RTX (GET_MODE (SET_DEST (set)))
&& !reg_set_between_p (SET_DEST (set), temp, insn)
&& REGNO_REG_CLASS (REGNO (SET_DEST (set))) == DATA_REGS
&& (REGNO_REG_CLASS (REGNO (SET_DEST (set)))
== REGNO_REG_CLASS (REGNO (operand)))
&& REGNO (SET_DEST (set)) != REGNO (operand)
&& (!past_call
|| !call_used_regs[REGNO (SET_DEST (set))]))

View File

@ -1,6 +1,6 @@
/* Definitions of target machine for GNU compiler.
Matsushita MN10300 series
Copyright (C) 1996 Free Software Foundation, Inc.
Copyright (C) 1996, 1997 Free Software Foundation, Inc.
Contributed by Jeff Law (law@cygnus.com).
This file is part of GNU CC.
@ -37,6 +37,10 @@ Boston, MA 02111-1307, USA. */
extern int target_flags;
/* Global registers known to hold the value zero. */
extern struct rtx_def *zero_dreg;
extern struct rtx_def *zero_areg;
/* Macros used in the machine description to test the flags. */
/* Macro to define tables used to set the flags.
@ -404,8 +408,7 @@ enum reg_class {
OFFSET = initial_offset (FROM, TO)
#define FRAME_POINTER_REQUIRED \
!(leaf_function_p ())
!(leaf_function_p () || current_function_outgoing_args_size == 0)
#define CAN_DEBUG_WITHOUT_FP
/* A guess for the MN10300. */
@ -562,6 +565,20 @@ extern struct rtx_def *function_arg ();
emit_move_insn (gen_rtx (MEM, SImode, plus_constant ((TRAMP), 0x18)), \
(FNADDR)); \
}
/* A C expression whose value is RTL representing the value of the return
address for the frame COUNT steps up from the current frame.
On the mn10300, the return address is not at a constant location
due to the frame layout. Luckily, it is at a constant offset from
the argument pointer, so we define RETURN_ADDR_RTX to return a
MEM using arg_pointer_rtx. Reload will replace arg_pointer_rtx
with a reference to the stack/frame pointer + an appropriate offset. */
#define RETURN_ADDR_RTX(COUNT, FRAME) \
((COUNT == 0) \
? gen_rtx (MEM, Pmode, arg_pointer_rtx) \
: (rtx) 0)
/* Emit code for a call to builtin_saveregs. We must emit USE insns which
reference the 2 integer arg registers.
Ordinarily they are not call used registers, but they are for

View File

@ -1,4 +1,4 @@
;; GCC machine description for Matsushita MN10300
; GCC machine description for Matsushita MN10300
;; Copyright (C) 1996, 1997 Free Software Foundation, Inc.
;; Contributed by Jeff Law (law@cygnus.com).
@ -59,21 +59,45 @@
}")
(define_insn ""
[(set (match_operand:QI 0 "general_operand" "=d,a,d,d,a,d,a,d,m")
(match_operand:QI 1 "general_operand" "0,0,I,a,d,di,ia,m,d"))]
[(set (match_operand:QI 0 "general_operand" "=d,a,d,a,d,a,d,a,d,m")
(match_operand:QI 1 "general_operand" "0,0,I,I,a,d,di,ia,m,d"))]
"register_operand (operands[0], QImode)
|| register_operand (operands[1], QImode)"
"@
nop
nop
clr %0
mov %1,%0
mov %1,%0
mov %1,%0
mov %1,%0
movbu %1,%0
movbu %1,%0"
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
"*
{
switch (which_alternative)
{
case 0:
case 1:
return \"nop\";
case 2:
return \"clr %0\";
case 3:
if (zero_areg)
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = zero_areg;
if (rtx_equal_p (xoperands[0], xoperands[1]))
output_asm_insn (\"sub %1,%0\", xoperands);
else
output_asm_insn (\"mov %1,%0\", xoperands);
return \"\";
}
/* FALLTHROUGH */
case 4:
case 5:
case 6:
case 7:
return \"mov %1,%0\";
case 8:
case 9:
return \"movbu %1,%0\";
}
}"
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
;; movhi
@ -90,21 +114,45 @@
}")
(define_insn ""
[(set (match_operand:HI 0 "general_operand" "=d,a,d,d,a,d,a,d,m")
(match_operand:HI 1 "general_operand" "0,0,I,a,d,di,ia,m,d"))]
[(set (match_operand:HI 0 "general_operand" "=d,a,d,a,d,a,d,a,d,m")
(match_operand:HI 1 "general_operand" "0,0,I,I,a,d,di,ia,m,d"))]
"register_operand (operands[0], HImode)
|| register_operand (operands[1], HImode)"
"@
nop
nop
clr %0
mov %1,%0
mov %1,%0
mov %1,%0
mov %1,%0
movhu %1,%0
movhu %1,%0"
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
"*
{
switch (which_alternative)
{
case 0:
case 1:
return \"nop\";
case 2:
return \"clr %0\";
case 3:
if (zero_areg)
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = zero_areg;
if (rtx_equal_p (xoperands[0], xoperands[1]))
output_asm_insn (\"sub %1,%0\", xoperands);
else
output_asm_insn (\"mov %1,%0\", xoperands);
return \"\";
}
/* FALLTHROUGH */
case 4:
case 5:
case 6:
case 7:
return \"mov %1,%0\";
case 8:
case 9:
return \"movhu %1,%0\";
}
}"
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
;; movsi and helpers
@ -121,25 +169,50 @@
}")
(define_insn ""
[(set (match_operand:SI 0 "general_operand" "=d,a,d,dm,dm,am,am,d,d,a,a,aR,x")
(match_operand:SI 1 "general_operand" "0,0,I,d,a,d,a,dim,aim,dim,aim,x,aR"))]
[(set (match_operand:SI 0 "general_operand"
"=d,a,d,a,dm,dm,am,am,d,d,a,a,aR,x")
(match_operand:SI 1 "general_operand"
"0,0,I,I,d,a,d,a,dim,aim,dim,aim,x,aR"))]
"register_operand (operands[0], SImode)
|| register_operand (operands[1], SImode)"
"@
nop
nop
clr %0
mov %1,%0
mov %1,%0
mov %1,%0
mov %1,%0
mov %1,%0
mov %1,%0
mov %1,%0
mov %1,%0
mov %1,%0
mov %1,%0"
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
"*
{
switch (which_alternative)
{
case 0:
case 1:
return \"nop\";
case 2:
return \"clr %0\";
case 3:
if (zero_areg)
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = zero_areg;
if (rtx_equal_p (xoperands[0], xoperands[1]))
output_asm_insn (\"sub %1,%0\", xoperands);
else
output_asm_insn (\"mov %1,%0\", xoperands);
return \"\";
}
/* FALLTHROUGH */
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
return \"mov %1,%0\";
}
}"
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
(define_expand "movsf"
[(set (match_operand:SF 0 "general_operand" "")
@ -154,17 +227,40 @@
}")
(define_insn ""
[(set (match_operand:SF 0 "general_operand" "=d,a,d,dam,da")
(match_operand:SF 1 "general_operand" "0,0,G,da,daim"))]
[(set (match_operand:SF 0 "general_operand" "=d,a,d,a,dam,da")
(match_operand:SF 1 "general_operand" "0,0,G,G,da,daim"))]
"register_operand (operands[0], SFmode)
|| register_operand (operands[1], SFmode)"
"@
nop
nop
clr %0
mov %1,%0
mov %1,%0"
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit")])
"*
{
switch (which_alternative)
{
case 0:
case 1:
return \"nop\";
case 2:
return \"clr %0\";
case 3:
if (zero_areg)
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = zero_areg;
if (rtx_equal_p (xoperands[0], xoperands[1]))
output_asm_insn (\"sub %1,%0\", xoperands);
else
output_asm_insn (\"mov %1,%0\", xoperands);
return \"\";
}
/* FALLTHROUGH */
case 4:
case 5:
return \"mov %1,%0\";
}
}"
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit")])
(define_expand "movdi"
[(set (match_operand:DI 0 "general_operand" "")
@ -179,8 +275,10 @@
}")
(define_insn ""
[(set (match_operand:DI 0 "general_operand" "=d,a,d,dm,dm,am,am,d,d,a,a")
(match_operand:DI 1 "general_operand" "0,0,I,d,a,d,a,dim,aim,dim,aim"))]
[(set (match_operand:DI 0 "general_operand"
"=d,a,d,a,dm,dm,am,am,d,d,a,a")
(match_operand:DI 1 "general_operand"
"0,0,I,I,d,a,d,a,dim,aim,dim,aim"))]
"register_operand (operands[0], DImode)
|| register_operand (operands[1], DImode)"
"*
@ -198,6 +296,17 @@
return \"clr %L0\;clr %H0\";
case 3:
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = zero_areg ? zero_areg : operands[1];
if (rtx_equal_p (xoperands[0], xoperands[1]))
output_asm_insn (\"sub %L1,%L0\;mov %L0,%H0\", xoperands);
else
output_asm_insn (\"mov %1,%L0\;mov %L0,%H0\", xoperands);
return \"\";
}
case 4:
case 5:
case 6:
@ -205,6 +314,7 @@
case 8:
case 9:
case 10:
case 11:
if (GET_CODE (operands[1]) == CONST_INT)
{
val[0] = INTVAL (operands[1]);
@ -243,28 +353,75 @@
return \"mov %L1,%L0\;mov %H1,%H0\";
}
else if (GET_CODE (operands[1]) == MEM
&& CONSTANT_ADDRESS_P (XEXP (operands[1], 0))
&& REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS)
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = XEXP (operands[1], 0);
output_asm_insn (\"mov %1,%L0\;mov (4,%L0),%H0\;mov (%L0),%L0\",
xoperands);
return \"\";
}
else
{
if ((GET_CODE (operands[1]) == CONST_INT
|| GET_CODE (operands[1]) == CONST_DOUBLE)
&& val[0] == 0
&& REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
output_asm_insn (\"clr %L0\", operands);
&& val[0] == 0)
{
if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
output_asm_insn (\"clr %L0\", operands);
else if (zero_areg)
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = zero_areg;
if (rtx_equal_p (xoperands[0], xoperands[1]))
output_asm_insn (\"sub %L0,%L0\", xoperands);
else
output_asm_insn (\"mov %1,%L0\", xoperands);
}
else
output_asm_insn (\"mov %L1,%L0\", operands);
}
else
output_asm_insn (\"mov %L1,%L0\", operands);
if ((GET_CODE (operands[1]) == CONST_INT
|| GET_CODE (operands[1]) == CONST_DOUBLE)
&& val[1] == 0
&& REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
output_asm_insn (\"clr %H0\", operands);
&& val[1] == 0)
{
if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
output_asm_insn (\"clr %H0\", operands);
else if (zero_areg)
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = zero_areg;
if (rtx_equal_p (xoperands[0], xoperands[1]))
output_asm_insn (\"sub %H0,%H0\", xoperands);
else
output_asm_insn (\"mov %1,%H0\", xoperands);
}
else
output_asm_insn (\"mov %H1,%H0\", operands);
}
else if ((GET_CODE (operands[1]) == CONST_INT
|| GET_CODE (operands[1]) == CONST_DOUBLE)
&& val[0] == val[1])
output_asm_insn (\"mov %L0,%H0\", operands);
else
output_asm_insn (\"mov %H1,%H0\", operands);
return \"\";
}
}
}"
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
(define_expand "movdf"
[(set (match_operand:DF 0 "general_operand" "")
@ -279,8 +436,10 @@
}")
(define_insn ""
[(set (match_operand:DF 0 "general_operand" "=d,a,d,dm,dm,am,am,d,d,a,a")
(match_operand:DF 1 "general_operand" "0,0,G,d,a,d,a,dim,aim,dim,aim"))]
[(set (match_operand:DF 0 "general_operand"
"=d,a,d,a,dm,dm,am,am,d,d,a,a")
(match_operand:DF 1 "general_operand"
"0,0,G,G,d,a,d,a,dim,aim,dim,aim"))]
"register_operand (operands[0], DFmode)
|| register_operand (operands[1], DFmode)"
"*
@ -298,6 +457,17 @@
return \"clr %L0\;clr %H0\";
case 3:
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = zero_areg ? zero_areg : operands[1];
if (rtx_equal_p (xoperands[0], xoperands[1]))
output_asm_insn (\"sub %L1,%L0\;mov %L0,%H0\", xoperands);
else
output_asm_insn (\"mov %1,%L0\;mov %L0,%H0\", xoperands);
return \"\";
}
case 4:
case 5:
case 6:
@ -305,6 +475,7 @@
case 8:
case 9:
case 10:
case 11:
if (GET_CODE (operands[1]) == CONST_INT)
{
val[0] = INTVAL (operands[1]);
@ -343,28 +514,75 @@
return \"mov %L1,%L0\;mov %H1,%H0\";
}
else if (GET_CODE (operands[1]) == MEM
&& CONSTANT_ADDRESS_P (XEXP (operands[1], 0))
&& REGNO_REG_CLASS (REGNO (operands[0])) == ADDRESS_REGS)
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = XEXP (operands[1], 0);
output_asm_insn (\"mov %1,%L0\;mov (4,%L0),%H0\;mov (%L0),%L0\",
xoperands);
return \"\";
}
else
{
if ((GET_CODE (operands[1]) == CONST_INT
|| GET_CODE (operands[1]) == CONST_DOUBLE)
&& val[0] == 0
&& REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
output_asm_insn (\"clr %L0\", operands);
&& val[0] == 0)
{
if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
output_asm_insn (\"clr %L0\", operands);
else if (zero_areg)
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = zero_areg;
if (rtx_equal_p (xoperands[0], xoperands[1]))
output_asm_insn (\"sub %L0,%L0\", xoperands);
else
output_asm_insn (\"mov %1,%L0\", xoperands);
}
else
output_asm_insn (\"mov %L1,%L0\", operands);
}
else
output_asm_insn (\"mov %L1,%L0\", operands);
if ((GET_CODE (operands[1]) == CONST_INT
|| GET_CODE (operands[1]) == CONST_DOUBLE)
&& val[1] == 0
&& REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
output_asm_insn (\"clr %H0\", operands);
&& val[1] == 0)
{
if (REGNO_REG_CLASS (REGNO (operands[0])) == DATA_REGS)
output_asm_insn (\"clr %H0\", operands);
else if (zero_areg)
{
rtx xoperands[2];
xoperands[0] = operands[0];
xoperands[1] = zero_areg;
if (rtx_equal_p (xoperands[0], xoperands[1]))
output_asm_insn (\"sub %H0,%H0\", xoperands);
else
output_asm_insn (\"mov %1,%H0\", xoperands);
}
else
output_asm_insn (\"mov %H1,%H0\", operands);
}
else if ((GET_CODE (operands[1]) == CONST_INT
|| GET_CODE (operands[1]) == CONST_DOUBLE)
&& val[0] == val[1])
output_asm_insn (\"mov %L0,%H0\", operands);
else
output_asm_insn (\"mov %H1,%H0\", operands);
return \"\";
}
}
}"
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
[(set_attr "cc" "none,none,clobber,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit,none_0hit")])
@ -428,17 +646,18 @@
}")
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=d,a,a,da,x")
(plus:SI (match_operand:SI 1 "register_operand" "%0,0,0,0,0")
(match_operand:SI 2 "nonmemory_operand" "J,J,L,dai,i")))]
[(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")))]
""
"@
inc %0
inc %0
inc4 %0
add %2,%0
add %2,%0"
[(set_attr "cc" "set_zn_c0,none_0hit,none_0hit,set_zn_c0,none_0hit")])
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")])
(define_expand "adddi3"
[(set (reg:DI 0) (match_operand:DI 1 "register_operand" ""))
@ -1131,7 +1350,17 @@
(define_insn "return"
[(return)]
"can_use_return_insn ()"
"rets"
"*
{
rtx next = next_active_insn (insn);
if (next
&& GET_CODE (next) == JUMP_INSN
&& GET_CODE (PATTERN (next)) == RETURN)
return \"\";
else
return \"rets\";
}"
[(set_attr "cc" "clobber")])
;; Try to combine consecutive updates of the stack pointer (or any