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:
parent
90e6057ba5
commit
74452ac323
@ -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))]))
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user