From 01e304f8a9671bc5e30a66326573b216282dabf0 Mon Sep 17 00:00:00 2001 From: Roman Zippel Date: Sun, 18 Feb 2007 01:30:58 +0000 Subject: [PATCH] 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 --- gcc/ChangeLog | 7 + gcc/config/m68k/m68k-protos.h | 3 + gcc/config/m68k/m68k.c | 32 ++ gcc/config/m68k/m68k.md | 613 +++++++++++++++++++++++++--------- 4 files changed, 490 insertions(+), 165 deletions(-) diff --git a/gcc/ChangeLog b/gcc/ChangeLog index f0be35cb21a..8e104718950 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2007-02-18 Roman Zippel + + * 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 * config/m68k/m68k.md (extv,extzv,insv): disable dynamic diff --git a/gcc/config/m68k/m68k-protos.h b/gcc/config/m68k/m68k-protos.h index 14a9e2c1fed..85a5376826b 100644 --- a/gcc/config/m68k/m68k-protos.h +++ b/gcc/config/m68k/m68k-protos.h @@ -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 *); diff --git a/gcc/config/m68k/m68k.c b/gcc/config/m68k/m68k.c index 225baed5ac6..08ebbd20dac 100644 --- a/gcc/config/m68k/m68k.c +++ b/gcc/config/m68k/m68k.c @@ -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. */ diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md index 285abf18090..42e5f21dfce 100644 --- a/gcc/config/m68k/m68k.md +++ b/gcc/config/m68k/m68k.md @@ -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" {