mirror of
git://gcc.gnu.org/git/gcc.git
synced 2025-03-15 22:51:38 +08:00
m68k.c (split_di): New.
* config/m68k/m68k.c (split_di): New. * config/m68k/m68k-protos.h: Declare split_di. * config/m68k/m68k.md (extendsidi2*,ashldi3*,ashrdi3*,lshrdi3*): Improve predicate handling and split constant shifts. From-SVN: r122084
This commit is contained in:
parent
3670ec284d
commit
01e304f8a9
@ -1,3 +1,10 @@
|
||||
2007-02-18 Roman Zippel <zippel@linux-m68k.org>
|
||||
|
||||
* config/m68k/m68k.c (split_di): New.
|
||||
* config/m68k/m68k-protos.h: Declare split_di.
|
||||
* config/m68k/m68k.md (extendsidi2*,ashldi3*,ashrdi3*,lshrdi3*):
|
||||
Improve predicate handling and split constant shifts.
|
||||
|
||||
2007-02-18 Roman Zippel <zippel@linux-m68k.org>
|
||||
|
||||
* config/m68k/m68k.md (extv,extzv,insv): disable dynamic
|
||||
|
@ -22,6 +22,9 @@ Boston, MA 02110-1301, USA. */
|
||||
|
||||
#ifdef RTX_CODE
|
||||
extern HOST_WIDE_INT m68k_initial_elimination_offset (int from, int to);
|
||||
|
||||
extern void split_di (rtx[], int, rtx[], rtx[]);
|
||||
|
||||
extern bool valid_mov3q_const (HOST_WIDE_INT);
|
||||
extern const char *output_move_simode (rtx *);
|
||||
extern const char *output_move_himode (rtx *);
|
||||
|
@ -2722,6 +2722,38 @@ emit_move_sequence (rtx *operands, enum machine_mode mode, rtx scratch_reg)
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Split one or more DImode RTL references into pairs of SImode
|
||||
references. The RTL can be REG, offsettable MEM, integer constant, or
|
||||
CONST_DOUBLE. "operands" is a pointer to an array of DImode RTL to
|
||||
split and "num" is its length. lo_half and hi_half are output arrays
|
||||
that parallel "operands". */
|
||||
|
||||
void
|
||||
split_di (rtx operands[], int num, rtx lo_half[], rtx hi_half[])
|
||||
{
|
||||
while (num--)
|
||||
{
|
||||
rtx op = operands[num];
|
||||
|
||||
/* simplify_subreg refuses to split volatile memory addresses,
|
||||
but we still have to handle it. */
|
||||
if (GET_CODE (op) == MEM)
|
||||
{
|
||||
lo_half[num] = adjust_address (op, SImode, 4);
|
||||
hi_half[num] = adjust_address (op, SImode, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
lo_half[num] = simplify_gen_subreg (SImode, op,
|
||||
GET_MODE (op) == VOIDmode
|
||||
? DImode : GET_MODE (op), 4);
|
||||
hi_half[num] = simplify_gen_subreg (SImode, op,
|
||||
GET_MODE (op) == VOIDmode
|
||||
? DImode : GET_MODE (op), 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Return a REG that occurs in ADDR with coefficient 1.
|
||||
ADDR can be effectively incremented by incrementing REG. */
|
||||
|
||||
|
@ -1476,17 +1476,31 @@
|
||||
})
|
||||
|
||||
(define_insn "extendsidi2"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=d")
|
||||
(sign_extend:DI
|
||||
(match_operand:SI 1 "general_operand" "rm")))]
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(sign_extend:DI (match_operand:SI 1 "nonimmediate_src_operand" "rm")))]
|
||||
""
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
|
||||
if (TARGET_68020 || TARGET_COLDFIRE)
|
||||
return "move%.l %1,%2\;smi %0\;extb%.l %0";
|
||||
return "move%.l %1,%R0\;smi %0\;extb%.l %0";
|
||||
else
|
||||
return "move%.l %1,%2\;smi %0\;ext%.w %0\;ext%.l %0";
|
||||
return "move%.l %1,%R0\;smi %0\;ext%.w %0\;ext%.l %0";
|
||||
})
|
||||
|
||||
(define_insn "*extendsidi2_mem"
|
||||
[(set (match_operand:DI 0 "memory_operand" "=o,<")
|
||||
(sign_extend:DI (match_operand:SI 1 "nonimmediate_src_operand" "rm,rm")))
|
||||
(clobber (match_scratch:SI 2 "=d,d"))]
|
||||
""
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
operands[3] = adjust_address (operands[0], SImode,
|
||||
which_alternative == 0 ? 4 : 0);
|
||||
operands[0] = adjust_address (operands[0], SImode, 0);
|
||||
if (TARGET_68020 || TARGET_COLDFIRE)
|
||||
return "move%.l %1,%3\;smi %2\;extb%.l %2\;move%.l %2,%0";
|
||||
else
|
||||
return "move%.l %1,%3\;smi %2\;ext%.w %2\;ext%.l %2\;move%.l %2,%0";
|
||||
})
|
||||
|
||||
;; Special case when one can avoid register clobbering, copy and test
|
||||
@ -4087,69 +4101,168 @@
|
||||
return "move%.w %1,%0\;sub%.l %R0,%R0";
|
||||
})
|
||||
|
||||
(define_insn "ashldi_const32"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
|
||||
(ashift:DI (match_operand:DI 1 "general_operand" "ro")
|
||||
(const_int 32)))]
|
||||
""
|
||||
(define_insn "*ashldi3_const1"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(ashift:DI (match_operand:DI 1 "register_operand" "0")
|
||||
(const_int 1)))]
|
||||
"!TARGET_COLDFIRE"
|
||||
"add%.l %R0,%R0\;addx%.l %0,%0")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(ashift:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 2)))]
|
||||
"reload_completed && !TARGET_COLDFIRE"
|
||||
[(set (match_dup 0)
|
||||
(ashift:DI (match_dup 1) (const_int 1)))
|
||||
(set (match_dup 0)
|
||||
(ashift:DI (match_dup 0) (const_int 1)))]
|
||||
"")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(ashift:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 3)))]
|
||||
"reload_completed && !TARGET_COLDFIRE"
|
||||
[(set (match_dup 0)
|
||||
(ashift:DI (match_dup 1) (const_int 2)))
|
||||
(set (match_dup 0)
|
||||
(ashift:DI (match_dup 0) (const_int 1)))]
|
||||
"")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(ashift:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 8)))]
|
||||
"reload_completed && !TARGET_COLDFIRE"
|
||||
[(set (match_dup 2)
|
||||
(rotate:SI (match_dup 2) (const_int 8)))
|
||||
(set (match_dup 3)
|
||||
(rotate:SI (match_dup 3) (const_int 8)))
|
||||
(set (strict_low_part (subreg:QI (match_dup 0) 3))
|
||||
(subreg:QI (match_dup 0) 7))
|
||||
(set (strict_low_part (subreg:QI (match_dup 0) 7))
|
||||
(const_int 0))]
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
if (GET_CODE (operands[1]) == REG)
|
||||
operands[3] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
|
||||
else
|
||||
operands[3] = adjust_address (operands[1], SImode, 4);
|
||||
if (GET_CODE (operands[0]) == REG)
|
||||
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
|
||||
else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
|
||||
return "clr%.l %0\;move%.l %3,%0";
|
||||
else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC)
|
||||
return "move%.l %3,%0\;clr%.l %0";
|
||||
else
|
||||
operands[2] = adjust_address (operands[0], SImode, 4);
|
||||
if (ADDRESS_REG_P (operands[2]))
|
||||
return "move%.l %3,%0\;sub%.l %2,%2";
|
||||
else
|
||||
return "move%.l %3,%0\;clr%.l %2";
|
||||
operands[2] = gen_highpart (SImode, operands[0]);
|
||||
operands[3] = gen_lowpart (SImode, operands[0]);
|
||||
})
|
||||
|
||||
;; The predicate below must be general_operand, because ashldi3 allows that
|
||||
(define_insn "ashldi_const"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=d")
|
||||
(ashift:DI (match_operand:DI 1 "general_operand" "0")
|
||||
(match_operand 2 "const_int_operand" "n")))]
|
||||
"(!TARGET_COLDFIRE
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(ashift:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 16)))]
|
||||
"reload_completed && !TARGET_COLDFIRE"
|
||||
[(set (match_dup 2)
|
||||
(rotate:SI (match_dup 2) (const_int 16)))
|
||||
(set (match_dup 3)
|
||||
(rotate:SI (match_dup 3) (const_int 16)))
|
||||
(set (strict_low_part (subreg:HI (match_dup 0) 2))
|
||||
(subreg:HI (match_dup 0) 6))
|
||||
(set (strict_low_part (subreg:HI (match_dup 0) 6))
|
||||
(const_int 0))]
|
||||
{
|
||||
operands[2] = gen_highpart (SImode, operands[0]);
|
||||
operands[3] = gen_lowpart (SImode, operands[0]);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "pre_dec_operand" "")
|
||||
(ashift:DI (match_operand:DI 1 "nonimmediate_operand" "")
|
||||
(const_int 32)))]
|
||||
"reload_completed"
|
||||
[(set (match_dup 0) (const_int 0))
|
||||
(set (match_dup 0) (match_dup 1))]
|
||||
{
|
||||
operands[0] = adjust_address(operands[0], SImode, 0);
|
||||
operands[1] = gen_lowpart(SImode, operands[1]);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "post_inc_operand" "")
|
||||
(ashift:DI (match_operand:DI 1 "nonimmediate_operand" "")
|
||||
(const_int 32)))]
|
||||
"reload_completed"
|
||||
[(set (match_dup 0) (match_dup 1))
|
||||
(set (match_dup 0) (const_int 0))]
|
||||
{
|
||||
operands[0] = adjust_address(operands[0], SImode, 0);
|
||||
operands[1] = gen_lowpart(SImode, operands[1]);
|
||||
})
|
||||
|
||||
(define_insn_and_split "*ashldi3_const32"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=ro<>")
|
||||
(ashift:DI (match_operand:DI 1 "nonimmediate_operand" "ro")
|
||||
(const_int 32)))]
|
||||
""
|
||||
"#"
|
||||
"&& reload_completed"
|
||||
[(set (match_dup 4) (match_dup 3))
|
||||
(set (match_dup 2) (const_int 0))]
|
||||
"split_di(operands, 2, operands + 2, operands + 4);")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(ashift:DI (match_operand:DI 1 "register_operand" "")
|
||||
(match_operand 2 "const_int_operand" "")))]
|
||||
"reload_completed && !TARGET_COLDFIRE
|
||||
&& INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 40"
|
||||
[(set (match_dup 4) (ashift:SI (match_dup 4) (match_dup 2)))
|
||||
(set (match_dup 3) (match_dup 4))
|
||||
(set (match_dup 4) (const_int 0))]
|
||||
{
|
||||
operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
|
||||
operands[3] = gen_highpart (SImode, operands[0]);
|
||||
operands[4] = gen_lowpart (SImode, operands[0]);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(ashift:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 48)))]
|
||||
"reload_completed && !TARGET_COLDFIRE"
|
||||
[(set (match_dup 2) (match_dup 3))
|
||||
(set (match_dup 2)
|
||||
(rotate:SI (match_dup 2) (const_int 16)))
|
||||
(set (match_dup 3) (const_int 0))
|
||||
(set (strict_low_part (subreg:HI (match_dup 0) 2))
|
||||
(const_int 0))]
|
||||
{
|
||||
operands[2] = gen_highpart (SImode, operands[0]);
|
||||
operands[3] = gen_lowpart (SImode, operands[0]);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(ashift:DI (match_operand:DI 1 "register_operand" "")
|
||||
(match_operand 2 "const_int_operand" "")))]
|
||||
"reload_completed && !TARGET_COLDFIRE
|
||||
&& INTVAL (operands[2]) > 40 && INTVAL (operands[2]) <= 63"
|
||||
[(set (match_dup 3) (match_dup 2))
|
||||
(set (match_dup 4) (ashift:SI (match_dup 4) (match_dup 3)))
|
||||
(set (match_dup 3) (match_dup 4))
|
||||
(set (match_dup 4) (const_int 0))]
|
||||
{
|
||||
operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
|
||||
operands[3] = gen_highpart (SImode, operands[0]);
|
||||
operands[4] = gen_lowpart (SImode, operands[0]);
|
||||
})
|
||||
|
||||
(define_insn "*ashldi3"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(ashift:DI (match_operand:DI 1 "register_operand" "0")
|
||||
(match_operand 2 "const_int_operand" "n")))]
|
||||
"!TARGET_COLDFIRE
|
||||
&& ((INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3)
|
||||
|| INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16
|
||||
|| (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63)))"
|
||||
{
|
||||
operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
|
||||
if (INTVAL (operands[2]) == 1)
|
||||
return "add%.l %1,%1\;addx%.l %0,%0";
|
||||
else if (INTVAL (operands[2]) == 8)
|
||||
return "rol%.l #8,%1\;rol%.l #8,%0\;move%.b %1,%0\;clr%.b %1";
|
||||
else if (INTVAL (operands[2]) == 16)
|
||||
return "swap %1\;swap %0\;move%.w %1,%0\;clr%.w %1";
|
||||
else if (INTVAL (operands[2]) == 48)
|
||||
return "mov%.l %1,%0\;swap %0\;clr%.l %1\;clr%.w %0";
|
||||
else if (INTVAL (operands[2]) == 2)
|
||||
return "add%.l %1,%1\;addx%.l %0,%0\;add%.l %1,%1\;addx%.l %0,%0";
|
||||
else if (INTVAL (operands[2]) == 3)
|
||||
return "add%.l %1,%1\;addx%.l %0,%0\;add%.l %1,%1\;addx%.l %0,%0\;add%.l %1,%1\;addx%.l %0,%0";
|
||||
else /* 32 < INTVAL (operands[2]) <= 63 */
|
||||
{
|
||||
operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
|
||||
output_asm_insn (INTVAL (operands[2]) <= 8 ? "asl%.l %2,%1" :
|
||||
"moveq %2,%0\;asl%.l %0,%1", operands);
|
||||
return "mov%.l %1,%0\;moveq #0,%1";
|
||||
}
|
||||
})
|
||||
|| (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63))"
|
||||
"#")
|
||||
|
||||
(define_expand "ashldi3"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "")
|
||||
(ashift:DI (match_operand:DI 1 "general_operand" "")
|
||||
(match_operand 2 "const_int_operand" "")))]
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(ashift:DI (match_operand:DI 1 "register_operand" "")
|
||||
(match_operand 2 "const_int_operand" "")))]
|
||||
"!TARGET_COLDFIRE"
|
||||
"
|
||||
{
|
||||
/* ??? This is a named pattern like this is not allowed to FAIL based
|
||||
on its operands. */
|
||||
@ -4158,7 +4271,7 @@
|
||||
&& INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16
|
||||
&& (INTVAL (operands[2]) < 32 || INTVAL (operands[2]) > 63)))
|
||||
FAIL;
|
||||
} ")
|
||||
})
|
||||
|
||||
;; On most 68k models, this makes faster code in a special case.
|
||||
|
||||
@ -4276,66 +4389,131 @@
|
||||
return "move%.l %1,%0";
|
||||
})
|
||||
|
||||
(define_insn "ashrdi_const32"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=d,o,<")
|
||||
(ashiftrt:DI (match_operand:DI 1 "general_operand" "ro,ro,ro")
|
||||
(const_int 32)))
|
||||
(clobber (match_scratch:SI 2 "=X,d,d"))]
|
||||
(define_insn "*ashrdi3_const1"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
|
||||
(const_int 1)))]
|
||||
"!TARGET_COLDFIRE"
|
||||
{
|
||||
operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
|
||||
return "asr%.l #1,%0\;roxr%.l #1,%1";
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 2)))]
|
||||
"reload_completed && !TARGET_COLDFIRE"
|
||||
[(set (match_dup 0)
|
||||
(ashiftrt:DI (match_dup 1) (const_int 1)))
|
||||
(set (match_dup 0)
|
||||
(ashiftrt:DI (match_dup 0) (const_int 1)))]
|
||||
"")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 3)))]
|
||||
"reload_completed && !TARGET_COLDFIRE"
|
||||
[(set (match_dup 0)
|
||||
(ashiftrt:DI (match_dup 1) (const_int 2)))
|
||||
(set (match_dup 0)
|
||||
(ashiftrt:DI (match_dup 0) (const_int 1)))]
|
||||
"")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 8)))]
|
||||
"reload_completed && !TARGET_COLDFIRE"
|
||||
[(set (strict_low_part (subreg:QI (match_dup 0) 7))
|
||||
(subreg:QI (match_dup 0) 3))
|
||||
(set (match_dup 2)
|
||||
(ashiftrt:SI (match_dup 2) (const_int 8)))
|
||||
(set (match_dup 3)
|
||||
(rotatert:SI (match_dup 3) (const_int 8)))]
|
||||
{
|
||||
operands[2] = gen_highpart (SImode, operands[0]);
|
||||
operands[3] = gen_lowpart (SImode, operands[0]);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 16)))]
|
||||
"reload_completed && !TARGET_COLDFIRE"
|
||||
[(set (strict_low_part (subreg:HI (match_dup 0) 6))
|
||||
(subreg:HI (match_dup 0) 2))
|
||||
(set (match_dup 2)
|
||||
(rotate:SI (match_dup 2) (const_int 16)))
|
||||
(set (match_dup 3)
|
||||
(rotate:SI (match_dup 3) (const_int 16)))
|
||||
(set (match_dup 2)
|
||||
(sign_extend:SI (subreg:HI (match_dup 2) 2)))]
|
||||
{
|
||||
operands[2] = gen_highpart (SImode, operands[0]);
|
||||
operands[3] = gen_lowpart (SImode, operands[0]);
|
||||
})
|
||||
|
||||
(define_insn "*ashrdi_const32"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(ashiftrt:DI (match_operand:DI 1 "nonimmediate_src_operand" "ro")
|
||||
(const_int 32)))]
|
||||
""
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
if (which_alternative == 0)
|
||||
{
|
||||
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
|
||||
if (TARGET_68020)
|
||||
return "move%.l %1,%2\;smi %0\;extb%.l %0";
|
||||
else
|
||||
return "move%.l %1,%2\;smi %0\;ext%.w %0\;ext%.l %0";
|
||||
}
|
||||
if (TARGET_68020)
|
||||
return "move%.l %1,%R0\;smi %0\;extb%.l %0";
|
||||
else
|
||||
{
|
||||
if (which_alternative == 2)
|
||||
operands[3] = operands[0];
|
||||
else if (which_alternative == 1)
|
||||
operands[3] = adjust_address (operands[0], SImode, 4);
|
||||
if (TARGET_68020)
|
||||
return "move%.l %1,%3\;smi %2\;extb%.l %2\;move%.l %2,%0";
|
||||
else
|
||||
return "move%.l %1,%3\;smi %2\;ext%.w %2\;ext%.l %2\;move%.l %2,%0";
|
||||
}
|
||||
return "move%.l %1,%R0\;smi %0\;ext%.w %0\;ext%.l %0";
|
||||
})
|
||||
|
||||
(define_insn "*ashrdi_const32_mem"
|
||||
[(set (match_operand:DI 0 "memory_operand" "=o,<")
|
||||
(ashiftrt:DI (match_operand:DI 1 "nonimmediate_src_operand" "ro,ro")
|
||||
(const_int 32)))
|
||||
(clobber (match_scratch:SI 2 "=d,d"))]
|
||||
""
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
operands[3] = adjust_address (operands[0], SImode,
|
||||
which_alternative == 0 ? 4 : 0);
|
||||
operands[0] = adjust_address (operands[0], SImode, 0);
|
||||
if (TARGET_68020 || TARGET_COLDFIRE)
|
||||
return "move%.l %1,%3\;smi %2\;extb%.l %2\;move%.l %2,%0";
|
||||
else
|
||||
return "move%.l %1,%3\;smi %2\;ext%.w %2\;ext%.l %2\;move%.l %2,%0";
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 63)))]
|
||||
"reload_completed && !TARGET_COLDFIRE"
|
||||
[(set (match_dup 3)
|
||||
(ashiftrt:SI (match_dup 3) (const_int 31)))
|
||||
(set (match_dup 2)
|
||||
(match_dup 3))]
|
||||
"split_di(operands, 1, operands + 2, operands + 3);")
|
||||
|
||||
;; The predicate below must be general_operand, because ashrdi3 allows that
|
||||
(define_insn "ashrdi_const"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=d")
|
||||
(ashiftrt:DI (match_operand:DI 1 "general_operand" "0")
|
||||
(match_operand 2 "const_int_operand" "n")))
|
||||
(clobber (match_scratch:SI 3 "=X"))]
|
||||
"(!TARGET_COLDFIRE
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
|
||||
(match_operand 2 "const_int_operand" "n")))]
|
||||
"!TARGET_COLDFIRE
|
||||
&& ((INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3)
|
||||
|| INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16
|
||||
|| INTVAL (operands[2]) == 31
|
||||
|| (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63)))"
|
||||
|| (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63))"
|
||||
{
|
||||
operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
|
||||
if (INTVAL (operands[2]) == 63)
|
||||
return "add%.l %0,%0\;subx%.l %0,%0\;move%.l %0,%1";
|
||||
CC_STATUS_INIT;
|
||||
if (INTVAL (operands[2]) == 1)
|
||||
return "asr%.l #1,%0\;roxr%.l #1,%1";
|
||||
else if (INTVAL (operands[2]) == 8)
|
||||
return "move%.b %0,%1\;asr%.l #8,%0\;ror%.l #8,%1";
|
||||
else if (INTVAL (operands[2]) == 16)
|
||||
return "move%.w %0,%1\;swap %0\;ext%.l %0\;swap %1";
|
||||
else if (INTVAL (operands[2]) == 48)
|
||||
if (INTVAL (operands[2]) == 48)
|
||||
return "swap %0\;ext%.l %0\;move%.l %0,%1\;smi %0\;ext%.w %0";
|
||||
else if (INTVAL (operands[2]) == 31)
|
||||
if (INTVAL (operands[2]) == 31)
|
||||
return "add%.l %1,%1\;addx%.l %0,%0\;move%.l %0,%1\;subx%.l %0,%0";
|
||||
else if (INTVAL (operands[2]) == 2)
|
||||
return "asr%.l #1,%0\;roxr%.l #1,%1\;asr%.l #1,%0\;roxr%.l #1,%1";
|
||||
else if (INTVAL (operands[2]) == 3)
|
||||
return "asr%.l #1,%0\;roxr%.l #1,%1\;asr%.l #1,%0\;roxr%.l #1,%1\;asr%.l #1,%0\;roxr%.l #1,%1";
|
||||
else /* 32 < INTVAL (operands[2]) <= 63 */
|
||||
if (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63)
|
||||
{
|
||||
operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
|
||||
output_asm_insn (INTVAL (operands[2]) <= 8 ? "asr%.l %2,%0" :
|
||||
@ -4344,15 +4522,14 @@
|
||||
return INTVAL (operands[2]) >= 15 ? "ext%.w %d0" :
|
||||
TARGET_68020 ? "extb%.l %0" : "ext%.w %0\;ext%.l %0";
|
||||
}
|
||||
return "#";
|
||||
})
|
||||
|
||||
(define_expand "ashrdi3"
|
||||
[(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
|
||||
(ashiftrt:DI (match_operand:DI 1 "general_operand" "")
|
||||
(match_operand 2 "const_int_operand" "")))
|
||||
(clobber (match_scratch:SI 3 ""))])]
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
|
||||
(match_operand 2 "const_int_operand" "")))]
|
||||
"!TARGET_COLDFIRE"
|
||||
"
|
||||
{
|
||||
/* ??? This is a named pattern like this is not allowed to FAIL based
|
||||
on its operands. */
|
||||
@ -4361,8 +4538,7 @@
|
||||
&& INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16
|
||||
&& (INTVAL (operands[2]) < 31 || INTVAL (operands[2]) > 63)))
|
||||
FAIL;
|
||||
operands[3] = gen_rtx_SCRATCH (SImode);
|
||||
} ")
|
||||
})
|
||||
|
||||
;; On all 68k models, this makes faster code in a special case.
|
||||
|
||||
@ -4450,69 +4626,176 @@
|
||||
return "move%.l %1,%0";
|
||||
})
|
||||
|
||||
(define_insn "lshrdi_const32"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=ro,<,>")
|
||||
(lshiftrt:DI (match_operand:DI 1 "general_operand" "ro,ro,ro")
|
||||
(define_insn "*lshrdi3_const1"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
|
||||
(const_int 1)))]
|
||||
"!TARGET_COLDFIRE"
|
||||
"lsr%.l #1,%0\;roxr%.l #1,%R0")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 2)))]
|
||||
"reload_completed && !TARGET_COLDFIRE"
|
||||
[(set (match_dup 0)
|
||||
(lshiftrt:DI (match_dup 1) (const_int 1)))
|
||||
(set (match_dup 0)
|
||||
(lshiftrt:DI (match_dup 0) (const_int 1)))]
|
||||
"")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 3)))]
|
||||
"reload_completed && !TARGET_COLDFIRE"
|
||||
[(set (match_dup 0)
|
||||
(lshiftrt:DI (match_dup 1) (const_int 2)))
|
||||
(set (match_dup 0)
|
||||
(lshiftrt:DI (match_dup 0) (const_int 1)))]
|
||||
"")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 8)))]
|
||||
"reload_completed && !TARGET_COLDFIRE"
|
||||
[(set (strict_low_part (subreg:QI (match_dup 0) 7))
|
||||
(subreg:QI (match_dup 0) 3))
|
||||
(set (match_dup 2)
|
||||
(lshiftrt:SI (match_dup 2) (const_int 8)))
|
||||
(set (match_dup 3)
|
||||
(rotatert:SI (match_dup 3) (const_int 8)))]
|
||||
{
|
||||
operands[2] = gen_highpart (SImode, operands[0]);
|
||||
operands[3] = gen_lowpart (SImode, operands[0]);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 16)))]
|
||||
"reload_completed && !TARGET_COLDFIRE"
|
||||
[(set (strict_low_part (subreg:HI (match_dup 0) 6))
|
||||
(subreg:HI (match_dup 0) 2))
|
||||
(set (strict_low_part (subreg:HI (match_dup 0) 2))
|
||||
(const_int 0))
|
||||
(set (match_dup 3)
|
||||
(rotate:SI (match_dup 3) (const_int 16)))
|
||||
(set (match_dup 2)
|
||||
(rotate:SI (match_dup 2) (const_int 16)))]
|
||||
{
|
||||
operands[2] = gen_highpart (SImode, operands[0]);
|
||||
operands[3] = gen_lowpart (SImode, operands[0]);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "pre_dec_operand" "")
|
||||
(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "")
|
||||
(const_int 32)))]
|
||||
"reload_completed"
|
||||
[(set (match_dup 0) (match_dup 1))
|
||||
(set (match_dup 0) (const_int 0))]
|
||||
{
|
||||
operands[0] = adjust_address(operands[0], SImode, 0);
|
||||
operands[1] = gen_highpart(SImode, operands[1]);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "post_inc_operand" "")
|
||||
(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "")
|
||||
(const_int 32)))]
|
||||
"reload_completed"
|
||||
[(set (match_dup 0) (const_int 0))
|
||||
(set (match_dup 0) (match_dup 1))]
|
||||
{
|
||||
operands[0] = adjust_address(operands[0], SImode, 0);
|
||||
operands[1] = gen_highpart(SImode, operands[1]);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "")
|
||||
(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "")
|
||||
(const_int 32)))]
|
||||
"reload_completed"
|
||||
[(set (match_dup 2) (match_dup 5))
|
||||
(set (match_dup 4) (const_int 0))]
|
||||
"split_di(operands, 2, operands + 2, operands + 4);")
|
||||
|
||||
(define_insn "*lshrdi_const32"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=ro<>")
|
||||
(lshiftrt:DI (match_operand:DI 1 "general_operand" "ro")
|
||||
(const_int 32)))]
|
||||
""
|
||||
"#")
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
|
||||
(match_operand 2 "const_int_operand" "")))]
|
||||
"reload_completed && !TARGET_COLDFIRE
|
||||
&& INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 40"
|
||||
[(set (match_dup 3) (lshiftrt:SI (match_dup 3) (match_dup 2)))
|
||||
(set (match_dup 4) (match_dup 3))
|
||||
(set (match_dup 3) (const_int 0))]
|
||||
{
|
||||
CC_STATUS_INIT;
|
||||
if (which_alternative == 1)
|
||||
return "move%.l %1,%0\;clr%.l %0";
|
||||
if (which_alternative == 2)
|
||||
return "clr%.l %0\;move%.l %1,%0";
|
||||
if (GET_CODE (operands[0]) == REG)
|
||||
operands[2] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
|
||||
else
|
||||
operands[2] = adjust_address (operands[0], SImode, 4);
|
||||
if (GET_CODE (operands[1]) == REG)
|
||||
operands[3] = gen_rtx_REG (SImode, REGNO (operands[1]) + 1);
|
||||
else
|
||||
operands[3] = adjust_address (operands[1], SImode, 4);
|
||||
if (ADDRESS_REG_P (operands[0]))
|
||||
return "move%.l %1,%2\;sub%.l %0,%0";
|
||||
else
|
||||
return "move%.l %1,%2\;clr%.l %0";
|
||||
operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
|
||||
operands[3] = gen_highpart (SImode, operands[0]);
|
||||
operands[4] = gen_lowpart (SImode, operands[0]);
|
||||
})
|
||||
|
||||
;; The predicate below must be general_operand, because lshrdi3 allows that
|
||||
(define_insn "lshrdi_const"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "=d")
|
||||
(lshiftrt:DI (match_operand:DI 1 "general_operand" "0")
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
|
||||
(const_int 48)))]
|
||||
"reload_completed"
|
||||
[(set (match_dup 3) (match_dup 2))
|
||||
(set (strict_low_part (subreg:HI (match_dup 0) 6))
|
||||
(const_int 0))
|
||||
(set (match_dup 2) (const_int 0))
|
||||
(set (match_dup 3)
|
||||
(rotate:SI (match_dup 3) (const_int 16)))]
|
||||
{
|
||||
operands[2] = gen_highpart (SImode, operands[0]);
|
||||
operands[3] = gen_lowpart (SImode, operands[0]);
|
||||
})
|
||||
|
||||
(define_split
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
|
||||
(match_operand 2 "const_int_operand" "")))]
|
||||
"reload_completed && !TARGET_COLDFIRE
|
||||
&& INTVAL (operands[2]) > 40 && INTVAL (operands[2]) <= 62"
|
||||
[(set (match_dup 4) (match_dup 2))
|
||||
(set (match_dup 3) (lshiftrt:SI (match_dup 3) (match_dup 4)))
|
||||
(set (match_dup 4) (match_dup 3))
|
||||
(set (match_dup 3) (const_int 0))]
|
||||
{
|
||||
operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
|
||||
operands[3] = gen_highpart (SImode, operands[0]);
|
||||
operands[4] = gen_lowpart (SImode, operands[0]);
|
||||
})
|
||||
|
||||
(define_insn "*lshrdi_const63"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
|
||||
(const_int 63)))]
|
||||
""
|
||||
"add%.l %0,%0\;clr%.l %0\;clr%.l %R1\;addx%.l %R1,%R1")
|
||||
|
||||
(define_insn "*lshrdi3_const"
|
||||
[(set (match_operand:DI 0 "register_operand" "=d")
|
||||
(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
|
||||
(match_operand 2 "const_int_operand" "n")))]
|
||||
"(!TARGET_COLDFIRE
|
||||
&& ((INTVAL (operands[2]) >= 1 && INTVAL (operands[2]) <= 3)
|
||||
&& ((INTVAL (operands[2]) >= 2 && INTVAL (operands[2]) <= 3)
|
||||
|| INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16
|
||||
|| (INTVAL (operands[2]) > 32 && INTVAL (operands[2]) <= 63)))"
|
||||
{
|
||||
operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
|
||||
if (INTVAL (operands[2]) == 63)
|
||||
return "add%.l %0,%0\;clr%.l %0\;clr%.l %1\;addx%.l %1,%1";
|
||||
CC_STATUS_INIT;
|
||||
if (INTVAL (operands[2]) == 1)
|
||||
return "lsr%.l #1,%0\;roxr%.l #1,%1";
|
||||
else if (INTVAL (operands[2]) == 8)
|
||||
return "move%.b %0,%1\;lsr%.l #8,%0\;ror%.l #8,%1";
|
||||
else if (INTVAL (operands[2]) == 16)
|
||||
return "move%.w %0,%1\;clr%.w %0\;swap %1\;swap %0";
|
||||
else if (INTVAL (operands[2]) == 48)
|
||||
return "move%.l %0,%1\;clr%.w %1\;clr%.l %0\;swap %1";
|
||||
else if (INTVAL (operands[2]) == 2)
|
||||
return "lsr%.l #1,%0\;roxr%.l #1,%1\;lsr%.l #1,%0\;roxr%.l #1,%1";
|
||||
else if (INTVAL (operands[2]) == 3)
|
||||
return "lsr%.l #1,%0\;roxr%.l #1,%1\;lsr%.l #1,%0\;roxr%.l #1,%1\;lsr%.l #1,%0\;roxr%.l #1,%1";
|
||||
else /* 32 < INTVAL (operands[2]) <= 63 */
|
||||
{
|
||||
operands[2] = GEN_INT (INTVAL (operands[2]) - 32);
|
||||
output_asm_insn (INTVAL (operands[2]) <= 8 ? "lsr%.l %2,%0" :
|
||||
"moveq %2,%1\;lsr%.l %1,%0", operands);
|
||||
return "mov%.l %0,%1\;moveq #0,%0";
|
||||
}
|
||||
})
|
||||
"#")
|
||||
|
||||
(define_expand "lshrdi3"
|
||||
[(set (match_operand:DI 0 "nonimmediate_operand" "")
|
||||
(lshiftrt:DI (match_operand:DI 1 "general_operand" "")
|
||||
[(set (match_operand:DI 0 "register_operand" "")
|
||||
(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
|
||||
(match_operand 2 "const_int_operand" "")))]
|
||||
"!TARGET_COLDFIRE"
|
||||
{
|
||||
|
Loading…
x
Reference in New Issue
Block a user