--- gcc/config/m68k.md 2018/04/24 17:51:30 1.1.1.1 +++ gcc/config/m68k.md 2018/04/24 18:03:42 1.1.1.4 @@ -61,7 +61,7 @@ ;;- "%-" push operand "sp@-" move%.l d0,%- ;;- "%+" pop operand "sp@+" move%.l d0,%+ ;;- "%@" top of stack "sp@" move%.l d0,%@ -;;- "%!" ??? "cc" (not used) +;;- "%!" fpcr register ;;- "%$" single-precision fp specifier ("s" or "") f%$add.x fp0,fp1 ;;- "%&" double-precision fp specifier ("d" or "") f%&add.x fp0,fp1 @@ -221,7 +221,7 @@ ;;- "command register" mode means that no accessing of memory or the ;;- 68000 registers is being done. This can be expressed easily in ;;- constraints, so generally the mode of the instruction is -;;- determined by a branch off of which_alternative. In outputing +;;- determined by a branch off of which_alternative. In outputting ;;- instructions, a 'w' means to output an access to the constant ram ;;- (if the arg is CONST_DOUBLE and is one of the available ;;- constants), and 'x' means to output a register pair (if the arg is @@ -394,7 +394,7 @@ #ifdef SGS_CMP_ORDER return \"cmp%.l %d1,%d0\"; #else - return \"cmp%.l %d0,%d1\"; + return \"cmp%.l %d0,%d1\"; #endif } #ifdef SGS_CMP_ORDER @@ -419,7 +419,7 @@ #ifdef SGS_CMP_ORDER return \"cmp%.w %d1,%d0\"; #else - return \"cmp%.w %d0,%d1\"; + return \"cmp%.w %d0,%d1\"; #endif } #ifdef SGS_CMP_ORDER @@ -656,8 +656,8 @@ ;This is never used. ;(define_insn "swapsi" -; [(set (match_operand:SI 0 "general_operand" "r") -; (match_operand:SI 1 "general_operand" "r")) +; [(set (match_operand:SI 0 "general_operand" "+r") +; (match_operand:SI 1 "general_operand" "+r")) ; (set (match_dup 1) (match_dup 0))] ; "" ; "exg %1,%0") @@ -691,7 +691,7 @@ ;; ;; This is the main "hook" for PIC code. When generating ;; PIC, movsi is responsible for determining when the source address -;; needs PIC relocation and appropriatly calling legitimize_pic_address +;; needs PIC relocation and appropriately calling legitimize_pic_address ;; to perform the actual relocation. ;; ;; In both the PIC and non-PIC cases the patterns generated will @@ -759,9 +759,9 @@ { operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) - 8); #if defined(MOTOROLA) && !defined(CRDS) - return \"moveq%.l %1,%0;addq%.w %#8,%0\"; + return \"moveq%.l %1,%0\;addq%.w %#8,%0\"; #else - return \"moveq %1,%0;addq%.w %#8,%0\"; + return \"moveq %1,%0\;addq%.w %#8,%0\"; #endif } else if (DATA_REG_P (operands[0]) @@ -786,9 +786,9 @@ { operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) / 2); #if defined(MOTOROLA) && !defined(CRDS) - return \"moveq%.l %1,%0;add%.w %0,%0\"; + return \"moveq%.l %1,%0\;add%.w %0,%0\"; #else - return \"moveq %1,%0;add%.w %0,%0\"; + return \"moveq %1,%0\;add%.w %0,%0\"; #endif } else if (ADDRESS_REG_P (operands[0]) @@ -872,9 +872,11 @@ #else /* SGS_SWITCH_TABLES or not MOTOROLA */ ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"LI\", CODE_LABEL_NUMBER (XEXP (labelref, 0))); - /* For sake of 3b1, set flag saying we need to define the symbol - LD%n (with value L%n-LI%n) at the end of the switch table. */ - RTX_INTEGRATED_P (next_real_insn (XEXP (labelref, 0))) = 1; +#ifdef SGS_SWITCH_TABLES + /* Set flag saying we need to define the symbol + LD%n (with value L%n-LI%n) at the end of the switch table. */ + switch_table_difference_label_flag = 1; +#endif /* SGS_SWITCH_TABLES */ #endif /* SGS_SWITCH_TABLES or not MOTOROLA */ } #endif /* SGS_NO_LI */ @@ -1156,7 +1158,7 @@ { if (GET_CODE (operands[0]) == REG) { - /* Must clear condition codes, since the mov.l bases them on + /* Must clear condition codes, since the move.l bases them on the entire 32 bits, not just the desired 8 bits. */ CC_STATUS_INIT; return \"move%.l %1,%0\"; @@ -1177,14 +1179,14 @@ && (GET_CODE (operands[1]) == MEM || GET_CODE (operands[1]) == CONST_INT)) { - /* Must clear condition codes, since the mov.w bases them on + /* Must clear condition codes, since the move.w bases them on the entire 16 bits, not just the desired 8 bits. */ CC_STATUS_INIT; return \"move%.w %1,%0\"; } if (GET_CODE (operands[0]) == REG) { - /* Must clear condition codes, since the mov.l bases them on + /* Must clear condition codes, since the move.l bases them on the entire 32 bits, not just the desired 8 bits. */ CC_STATUS_INIT; return \"move%.l %1,%0\"; @@ -1203,7 +1205,7 @@ { if (GET_CODE (operands[0]) == REG) { - /* Must clear condition codes, since the mov.l bases them on + /* Must clear condition codes, since the move.l bases them on the entire 32 bits, not just the desired 8 bits. */ CC_STATUS_INIT; return \"move%.l %1,%0\"; @@ -1265,11 +1267,13 @@ ;; Patterns to recognize zero-extend insns produced by the combiner. ;; We don't allow both operands in memory, because of aliasing problems. +;; Explicitly disallow two memory operands via the condition since reloading +;; of this case will result in worse code than the uncombined patterns. (define_insn "" [(set (match_operand:SI 0 "general_operand" "=do<>,d<") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rn,m")))] - "" + (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] + "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" "* { if (DATA_REG_P (operands[0])) @@ -1297,8 +1301,8 @@ (define_insn "" [(set (match_operand:HI 0 "general_operand" "=do<>,d") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "dn,m")))] - "" + (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))] + "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" "* { if (DATA_REG_P (operands[0])) @@ -1337,8 +1341,8 @@ (define_insn "" [(set (match_operand:SI 0 "general_operand" "=do<>,d") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "dn,m")))] - "" + (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))] + "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" "* { if (DATA_REG_P (operands[0])) @@ -1391,7 +1395,7 @@ (define_insn "extendhisi2" [(set (match_operand:SI 0 "general_operand" "=*d,a") (sign_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "0,rmn")))] + (match_operand:HI 1 "nonimmediate_operand" "0,rm")))] "" "* { @@ -1577,7 +1581,7 @@ "* { CC_STATUS_INIT; - return \"fmovem%.l fpcr,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,fpcr\;fmove%.l %1,%0\;fmovem%.l %2,fpcr\"; + return \"fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.l %1,%0\;fmovem%.l %2,%!\"; }") (define_insn "fix_truncdfhi2" @@ -1589,7 +1593,7 @@ "* { CC_STATUS_INIT; - return \"fmovem%.l fpcr,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,fpcr\;fmove%.w %1,%0\;fmovem%.l %2,fpcr\"; + return \"fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.w %1,%0\;fmovem%.l %2,%!\"; }") (define_insn "fix_truncdfqi2" @@ -1601,7 +1605,7 @@ "* { CC_STATUS_INIT; - return \"fmovem%.l fpcr,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,fpcr\;fmove%.b %1,%0\;fmovem%.l %2,fpcr\"; + return \"fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.b %1,%0\;fmovem%.l %2,%!\"; }") ;; Convert a float to a float whose value is an integer. @@ -1747,7 +1751,7 @@ : \"subq%.l %2,%0\"); } /* On everything except the 68000 it is faster to use two - addqw instuctions to add a small integer (8 < N <= 16) + addqw instructions to add a small integer (8 < N <= 16) to an address register. Likewise for subqw.*/ if (INTVAL (operands[2]) > 8 && INTVAL (operands[2]) <= 16 @@ -1755,7 +1759,7 @@ && TARGET_68020) { operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 8); - return \"addq%.w %#8,%0; addq%.w %2,%0\"; + return \"addq%.w %#8,%0\;addq%.w %2,%0\"; } if (INTVAL (operands[2]) < -8 && INTVAL (operands[2]) >= -16 @@ -1764,7 +1768,7 @@ { operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]) - 8); - return \"subq%.w %#8,%0; subq%.w %2,%0\"; + return \"subq%.w %#8,%0\;subq%.w %2,%0\"; } #endif if (ADDRESS_REG_P (operands[0]) @@ -1793,6 +1797,15 @@ #ifndef NO_ADDSUB_Q if (GET_CODE (operands[2]) == CONST_INT) { + /* If the constant would be a negative number when interpreted as + HImode, make it negative. This is usually, but not always, done + elsewhere in the compiler. First check for constants out of range, + which could confuse us. */ + + if (INTVAL (operands[2]) >= 32768) + operands[2] = gen_rtx (CONST_INT, VOIDmode, + INTVAL (operands[2]) - 65536); + if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 8) return \"addq%.w %2,%0\"; @@ -1804,7 +1817,7 @@ return \"subq%.w %2,%0\"; } /* On everything except the 68000 it is faster to use two - addqw instuctions to add a small integer (8 < N <= 16) + addqw instructions to add a small integer (8 < N <= 16) to an address register. Likewise for subqw. */ if (INTVAL (operands[2]) > 8 && INTVAL (operands[2]) <= 16 @@ -1812,7 +1825,7 @@ && TARGET_68020) { operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 8); - return \"addq%.w %#8,%0; addq%.w %2,%0\"; + return \"addq%.w %#8,%0\;addq%.w %2,%0\"; } if (INTVAL (operands[2]) < -8 && INTVAL (operands[2]) >= -16 @@ -1821,19 +1834,126 @@ { operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]) - 8); - return \"subq%.w %#8,%0; subq%.w %2,%0\"; + return \"subq%.w %#8,%0\;subq%.w %2,%0\"; } } #endif return \"add%.w %2,%0\"; }") +;; These insns must use MATCH_DUP instead of the more expected +;; use of a matching constraint because the "output" here is also +;; an input, so you can't use the matching constraint. That also means +;; that you can't use the "%", so you need patterns with the matched +;; operand in both positions. + (define_insn "" [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) (plus:HI (match_dup 0) (match_operand:HI 1 "general_operand" "dn,rmn")))] "" - "add%.w %1,%0") + "* +{ +#ifndef NO_ADDSUB_Q + if (GET_CODE (operands[1]) == CONST_INT) + { + /* If the constant would be a negative number when interpreted as + HImode, make it negative. This is usually, but not always, done + elsewhere in the compiler. First check for constants out of range, + which could confuse us. */ + + if (INTVAL (operands[1]) >= 32768) + operands[1] = gen_rtx (CONST_INT, VOIDmode, + INTVAL (operands[1]) - 65536); + + if (INTVAL (operands[1]) > 0 + && INTVAL (operands[1]) <= 8) + return \"addq%.w %1,%0\"; + if (INTVAL (operands[1]) < 0 + && INTVAL (operands[1]) >= -8) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, + - INTVAL (operands[1])); + return \"subq%.w %1,%0\"; + } + /* On everything except the 68000 it is faster to use two + addqw instructions to add a small integer (8 < N <= 16) + to an address register. Likewise for subqw. */ + if (INTVAL (operands[1]) > 8 + && INTVAL (operands[1]) <= 16 + && ADDRESS_REG_P (operands[0]) + && TARGET_68020) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) - 8); + return \"addq%.w %#8,%0\;addq%.w %1,%0\"; + } + if (INTVAL (operands[1]) < -8 + && INTVAL (operands[1]) >= -16 + && ADDRESS_REG_P (operands[0]) + && TARGET_68020) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, + - INTVAL (operands[1]) - 8); + return \"subq%.w %#8,%0\;subq%.w %1,%0\"; + } + } +#endif + return \"add%.w %1,%0\"; +}") + +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) + (plus:HI (match_operand:HI 1 "general_operand" "dn,rmn") + (match_dup 0)))] + "" + "* +{ +#ifndef NO_ADDSUB_Q + if (GET_CODE (operands[1]) == CONST_INT) + { + /* If the constant would be a negative number when interpreted as + HImode, make it negative. This is usually, but not always, done + elsewhere in the compiler. First check for constants out of range, + which could confuse us. */ + + if (INTVAL (operands[1]) >= 32768) + operands[1] = gen_rtx (CONST_INT, VOIDmode, + INTVAL (operands[1]) - 65536); + + if (INTVAL (operands[1]) > 0 + && INTVAL (operands[1]) <= 8) + return \"addq%.w %1,%0\"; + if (INTVAL (operands[1]) < 0 + && INTVAL (operands[1]) >= -8) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, + - INTVAL (operands[1])); + return \"subq%.w %1,%0\"; + } + /* On everything except the 68000 it is faster to use two + addqw instructions to add a small integer (8 < N <= 16) + to an address register. Likewise for subqw. */ + if (INTVAL (operands[1]) > 8 + && INTVAL (operands[1]) <= 16 + && ADDRESS_REG_P (operands[0]) + && TARGET_68020) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) - 8); + return \"addq%.w %#8,%0\;addq%.w %1,%0\"; + } + if (INTVAL (operands[1]) < -8 + && INTVAL (operands[1]) >= -16 + && ADDRESS_REG_P (operands[0]) + && TARGET_68020) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, + - INTVAL (operands[1]) - 8); + return \"subq%.w %#8,%0\;subq%.w %1,%0\"; + } + } +#endif + return \"add%.w %1,%0\"; +}") (define_insn "addqi3" [(set (match_operand:QI 0 "general_operand" "=m,d") @@ -1845,12 +1965,13 @@ #ifndef NO_ADDSUB_Q if (GET_CODE (operands[2]) == CONST_INT) { + if (INTVAL (operands[2]) >= 128) + operands[2] = gen_rtx (CONST_INT, VOIDmode, + INTVAL (operands[2]) - 256); + if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 8) return \"addq%.b %2,%0\"; - } - if (GET_CODE (operands[2]) == CONST_INT) - { if (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) >= -8) { operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2])); @@ -1866,7 +1987,54 @@ (plus:QI (match_dup 0) (match_operand:QI 1 "general_operand" "dn,dmn")))] "" - "add%.b %1,%0") + "* +{ +#ifndef NO_ADDSUB_Q + if (GET_CODE (operands[1]) == CONST_INT) + { + if (INTVAL (operands[1]) >= 128) + operands[1] = gen_rtx (CONST_INT, VOIDmode, + INTVAL (operands[1]) - 256); + + if (INTVAL (operands[1]) > 0 + && INTVAL (operands[1]) <= 8) + return \"addq%.b %1,%0\"; + if (INTVAL (operands[1]) < 0 && INTVAL (operands[1]) >= -8) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1])); + return \"subq%.b %1,%0\"; + } + } +#endif + return \"add%.b %1,%0\"; +}") + +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d")) + (plus:QI (match_operand:QI 1 "general_operand" "dn,dmn") + (match_dup 0)))] + "" + "* +{ +#ifndef NO_ADDSUB_Q + if (GET_CODE (operands[1]) == CONST_INT) + { + if (INTVAL (operands[1]) >= 128) + operands[1] = gen_rtx (CONST_INT, VOIDmode, + INTVAL (operands[1]) - 256); + + if (INTVAL (operands[1]) > 0 + && INTVAL (operands[1]) <= 8) + return \"addq%.b %1,%0\"; + if (INTVAL (operands[1]) < 0 && INTVAL (operands[1]) >= -8) + { + operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1])); + return \"subq%.b %1,%0\"; + } + } +#endif + return \"add%.b %1,%0\"; +}") (define_expand "adddf3" [(set (match_operand:DF 0 "general_operand" "") @@ -1990,7 +2158,7 @@ && TARGET_68020) { operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 8); - return \"subq%.w %#8,%0; subq%.w %2,%0\"; + return \"subq%.w %#8,%0\;subq%.w %2,%0\"; } #endif if (ADDRESS_REG_P (operands[0]) @@ -2005,7 +2173,7 @@ [(set (match_operand:SI 0 "general_operand" "=a") (minus:SI (match_operand:SI 1 "general_operand" "0") (sign_extend:SI - (match_operand:HI 2 "nonimmediate_operand" "rmn"))))] + (match_operand:HI 2 "nonimmediate_operand" "rm"))))] "" "sub%.w %2,%0") @@ -2128,7 +2296,7 @@ (mult:SI (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "%0")) (sign_extend:SI - (match_operand:HI 2 "nonimmediate_operand" "dmn"))))] + (match_operand:HI 2 "nonimmediate_operand" "dm"))))] "" "* { @@ -2166,7 +2334,7 @@ (mult:SI (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "%0")) (zero_extend:SI - (match_operand:HI 2 "nonimmediate_operand" "dmn"))))] + (match_operand:HI 2 "nonimmediate_operand" "dm"))))] "" "* { @@ -2202,7 +2370,7 @@ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) (zero_extend:DI - (match_operand:SI 2 "general_operand" ""))) 1)) + (match_operand:SI 2 "nonimmediate_operand" ""))) 1)) (set (subreg:SI (match_dup 0) 0) (subreg:SI (mult:DI (zero_extend:DI @@ -2218,7 +2386,7 @@ (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) (zero_extend:DI - (match_operand:SI 2 "general_operand" "dmsK"))) 1)) + (match_operand:SI 2 "nonimmediate_operand" "dm"))) 1)) (set (match_operand:SI 3 "register_operand" "=d") (subreg:SI (mult:DI (zero_extend:DI @@ -2228,6 +2396,22 @@ "TARGET_68020" "mulu%.l %2,%3:%0") +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=d") + (subreg:SI + (mult:DI (zero_extend:DI + (match_operand:SI 1 "register_operand" "%0")) + (match_operand:SI 2 "immediate_operand" "sK")) 1)) + (set (match_operand:SI 3 "register_operand" "=d") + (subreg:SI + (mult:DI (zero_extend:DI + (match_dup 1)) + (match_dup 2)) 0))] + "TARGET_68020 + && (GET_CODE (operands[2]) != CONST_INT + || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))" + "mulu%.l %2,%3:%0") + (define_expand "mulsidi3" [(parallel [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 1) @@ -2235,7 +2419,7 @@ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) (sign_extend:DI - (match_operand:SI 2 "general_operand" ""))) 1)) + (match_operand:SI 2 "nonimmediate_operand" ""))) 1)) (set (subreg:SI (match_dup 0) 0) (subreg:SI (mult:DI (sign_extend:DI @@ -2251,7 +2435,7 @@ (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) (sign_extend:DI - (match_operand:SI 2 "general_operand" "dmKs"))) 1)) + (match_operand:SI 2 "nonimmediate_operand" "dm"))) 1)) (set (match_operand:SI 3 "register_operand" "=d") (subreg:SI (mult:DI (sign_extend:DI @@ -2261,6 +2445,22 @@ "TARGET_68020" "muls%.l %2,%3:%0") +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=d") + (subreg:SI + (mult:DI (sign_extend:DI + (match_operand:SI 1 "register_operand" "%0")) + (match_operand:SI 2 "immediate_operand" "sK")) 1)) + (set (match_operand:SI 3 "register_operand" "=d") + (subreg:SI + (mult:DI (sign_extend:DI + (match_dup 1)) + (match_dup 2)) 0))] + "TARGET_68020 + && (GET_CODE (operands[2]) != CONST_INT + || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))" + "muls%.l %2,%3:%0") + (define_expand "muldf3" [(set (match_operand:DF 0 "general_operand" "") (mult:DF (match_operand:DF 1 "general_operand" "") @@ -2282,7 +2482,7 @@ if (rtx_equal_p (operands[0], operands[2])) return \"fpmul%.d %y1,%0\"; if (which_alternative == 0) - return \"fpmul3%.d %w2,%w1,%0\"; + return \"fpmul3%.d %w2,%w1,%0\"; return \"fpmul3%.d %x2,%x1,%0\"; }") @@ -2337,10 +2537,17 @@ "TARGET_68881" "* { +#ifdef FSGLMUL_USE_S + if (REG_P (operands[2]) && ! DATA_REG_P (operands[2])) + return (TARGET_68040_ONLY + ? \"fsmul%.s %2,%0\" + : \"fsglmul%.s %2,%0\"); +#else if (REG_P (operands[2]) && ! DATA_REG_P (operands[2])) return (TARGET_68040_ONLY ? \"fsmul%.x %2,%0\" : \"fsglmul%.x %2,%0\"); +#endif return (TARGET_68040_ONLY ? \"fsmul%.s %f2,%0\" : \"fsglmul%.s %f2,%0\"); @@ -2501,10 +2708,17 @@ "TARGET_68881" "* { +#ifdef FSGLDIV_USE_S + if (REG_P (operands[2]) && ! DATA_REG_P (operands[2])) + return (TARGET_68040_ONLY + ? \"fsdiv%.s %2,%0\" + : \"fsgldiv%.s %2,%0\"); +#else if (REG_P (operands[2]) && ! DATA_REG_P (operands[2])) return (TARGET_68040_ONLY ? \"fsdiv%.x %2,%0\" : \"fsgldiv%.x %2,%0\"); +#endif return (TARGET_68040_ONLY ? \"fsdiv%.s %f2,%0\" : \"fsgldiv%.s %f2,%0\"); @@ -2522,11 +2736,7 @@ /* The swap insn produces cc's that don't correspond to the result. */ CC_STATUS_INIT; #ifdef MOTOROLA -#ifdef SGS_SWAP_W - return \"ext%.l %0\;divs%.w %2,%0\;swap%.w %0\"; -#else return \"ext%.l %0\;divs%.w %2,%0\;swap %0\"; -#endif #else return \"extl %0\;divs %2,%0\;swap %0\"; #endif @@ -2544,11 +2754,7 @@ /* The swap insn produces cc's that don't correspond to the result. */ CC_STATUS_INIT; #ifdef MOTOROLA -#ifdef SGS_SWAP_W - return \"divs%.w %2,%0\;swap%.w %0\"; -#else return \"divs%.w %2,%0\;swap %0\"; -#endif #else return \"divs %2,%0\;swap %0\"; #endif @@ -2564,11 +2770,7 @@ /* The swap insn produces cc's that don't correspond to the result. */ CC_STATUS_INIT; #ifdef MOTOROLA -#ifdef SGS_SWAP_W - return \"divs%.w %2,%0\;swap%.w %0\"; -#else return \"divs%.w %2,%0\;swap %0\"; -#endif #else return \"divs %2,%0\;swap %0\"; #endif @@ -2584,11 +2786,7 @@ /* The swap insn produces cc's that don't correspond to the result. */ CC_STATUS_INIT; #ifdef MOTOROLA -#ifdef SGS_SWAP_W - return \"and%.l %#0xFFFF,%0\;divu%.w %2,%0\;swap%.w %0\"; -#else return \"and%.l %#0xFFFF,%0\;divu%.w %2,%0\;swap %0\"; -#endif #else return \"andl %#0xFFFF,%0\;divu %2,%0\;swap %0\"; #endif @@ -2606,11 +2804,7 @@ /* The swap insn produces cc's that don't correspond to the result. */ CC_STATUS_INIT; #ifdef MOTOROLA -#ifdef SGS_SWAP_W - return \"divu%.w %2,%0\;swap%.w %0\"; -#else return \"divu%.w %2,%0\;swap %0\"; -#endif #else return \"divu %2,%0\;swap %0\"; #endif @@ -2626,11 +2820,7 @@ /* The swap insn produces cc's that don't correspond to the result. */ CC_STATUS_INIT; #ifdef MOTOROLA -#ifdef SGS_SWAP_W - return \"divu%.w %2,%0\;swap%.w %0\"; -#else return \"divu%.w %2,%0\;swap %0\"; -#endif #else return \"divu %2,%0\;swap %0\"; #endif @@ -2670,7 +2860,7 @@ ;; Prevent AND from being made with sp. This doesn't exist in the machine ;; and reload will cause inefficient code. Since sp is a FIXED_REG, we -;; can't allocate psuedos into it. +;; can't allocate pseudos into it. (define_insn "andsi3" [(set (match_operand:SI 0 "not_sp_operand" "=m,d") (and:SI (match_operand:SI 1 "general_operand" "%0,0") @@ -2721,6 +2911,20 @@ "" "and%.w %2,%0") +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) + (and:HI (match_dup 0) + (match_operand:HI 1 "general_operand" "dn,dmn")))] + "" + "and%.w %1,%0") + +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) + (and:HI (match_operand:HI 1 "general_operand" "dn,dmn") + (match_dup 0)))] + "" + "and%.w %1,%0") + (define_insn "andqi3" [(set (match_operand:QI 0 "general_operand" "=m,d") (and:QI (match_operand:QI 1 "general_operand" "%0,0") @@ -2728,6 +2932,19 @@ "" "and%.b %2,%0") +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d")) + (and:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "dn,dmn")))] + "" + "and%.b %1,%0") + +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d")) + (and:QI (match_operand:QI 1 "general_operand" "dn,dmn") + (match_dup 0)))] + "" + "and%.b %1,%0") ;; inclusive-or instructions @@ -2776,12 +2993,40 @@ "" "or%.w %2,%0") +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) + (ior:HI (match_dup 0) + (match_operand:HI 1 "general_operand" "dn,dmn")))] + "" + "or%.w %1,%0") + +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) + (ior:HI (match_operand:HI 1 "general_operand" "dn,dmn") + (match_dup 0)))] + "" + "or%.w %1,%0") + (define_insn "iorqi3" [(set (match_operand:QI 0 "general_operand" "=m,d") (ior:QI (match_operand:QI 1 "general_operand" "%0,0") (match_operand:QI 2 "general_operand" "dn,dmn")))] "" "or%.b %2,%0") + +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d")) + (ior:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "dn,dmn")))] + "" + "or%.b %1,%0") + +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d")) + (ior:QI (match_operand:QI 1 "general_operand" "dn,dmn") + (match_dup 0)))] + "" + "or%.b %1,%0") ;; xor instructions @@ -2812,12 +3057,41 @@ "" "eor%.w %2,%0") +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm")) + (xor:HI (match_dup 0) + (match_operand:HI 1 "general_operand" "dn")))] + "" + "eor%.w %1,%0") + + +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm")) + (xor:HI (match_operand:HI 1 "general_operand" "dn") + (match_dup 0)))] + "" + "eor%.w %1,%0") + (define_insn "xorqi3" [(set (match_operand:QI 0 "general_operand" "=dm") (xor:QI (match_operand:QI 1 "general_operand" "%0") (match_operand:QI 2 "general_operand" "dn")))] "" "eor%.b %2,%0") + +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm")) + (xor:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "dn")))] + "" + "eor%.b %1,%0") + +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm")) + (xor:QI (match_operand:QI 1 "general_operand" "dn") + (match_dup 0)))] + "" + "eor%.b %1,%0") ;; negation instructions @@ -2833,12 +3107,24 @@ "" "neg%.w %0") +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm")) + (neg:HI (match_dup 0)))] + "" + "neg%.w %0") + (define_insn "negqi2" [(set (match_operand:QI 0 "general_operand" "=dm") (neg:QI (match_operand:QI 1 "general_operand" "0")))] "" "neg%.b %0") +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm")) + (neg:QI (match_dup 0)))] + "" + "neg%.b %0") + (define_expand "negsf2" [(set (match_operand:SF 0 "general_operand" "") (neg:SF (match_operand:SF 1 "general_operand" "")))] @@ -2895,6 +3181,20 @@ return \"f%&neg%.d %f1,%0\"; }") +;; Sqrt instruction for the 68881 + +(define_insn "sqrtdf2" + [(set (match_operand:DF 0 "general_operand" "=f") + (sqrt:DF (match_operand:DF 1 "general_operand" "fm")))] + "TARGET_68881" + "* +{ + if (FP_REG_P (operands[1])) + return \"fsqrt%.x %1,%0\"; + else + return \"fsqrt%.d %1,%0\"; +}") + ;; Absolute value instructions (define_expand "abssf2" @@ -2957,15 +3257,40 @@ "" "not%.w %0") +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm")) + (not:HI (match_dup 0)))] + "" + "not%.w %0") + (define_insn "one_cmplqi2" [(set (match_operand:QI 0 "general_operand" "=dm") (not:QI (match_operand:QI 1 "general_operand" "0")))] "" "not%.b %0") + +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm")) + (not:QI (match_dup 0)))] + "" + "not%.b %0") ;; arithmetic shift instructions ;; We don't need the shift memory by 1 bit instruction +;; On all 68k models, this makes faster code in a special case. + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=d") + (ashift:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "immediate_operand" "i")))] + "(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 16)" + "* +{ + CC_STATUS_INIT; + return \"swap %0\;clr%.w %0\"; +}") + ;; On the 68000, this makes faster code in a special case. (define_insn "" @@ -2973,16 +3298,13 @@ (ashift:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "immediate_operand" "i")))] "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) >= 16 && INTVAL (operands[2]) <= 24)" + && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)" "* { CC_STATUS_INIT; - if (INTVAL (operands[2]) == 16) - return \"swap %0\;clrw %0\"; - operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16); - return \"asl%.w %2,%0\;swap %0\;clrw %0\"; + return \"asl%.w %2,%0\;swap %0\;clr%.w %0\"; }") (define_insn "ashlsi3" @@ -3004,6 +3326,13 @@ "" "asl%.w %2,%0") +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d")) + (ashift:HI (match_dup 0) + (match_operand:HI 1 "general_operand" "dI")))] + "" + "asl%.w %1,%0") + (define_insn "ashlqi3" [(set (match_operand:QI 0 "register_operand" "=d") (ashift:QI (match_operand:QI 1 "register_operand" "0") @@ -3011,6 +3340,22 @@ "" "asl%.b %2,%0") +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d")) + (ashift:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "dI")))] + "" + "asl%.b %1,%0") + +;; On all 68k models, this makes faster code in a special case. + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=d") + (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "immediate_operand" "i")))] + "(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 16)" + "swap %0\;ext%.l %0") + ;; On the 68000, this makes faster code in a special case. (define_insn "" @@ -3018,12 +3363,9 @@ (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "immediate_operand" "i")))] "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) >= 16 && INTVAL (operands[2]) <= 24)" + && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)" "* { - if (INTVAL (operands[2]) == 16) - return \"swap %0\;ext%.l %0\"; - operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16); return \"swap %0\;asr%.w %2,%0\;ext%.l %0\"; }") @@ -3045,15 +3387,42 @@ "" "asr%.w %2,%0") +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d")) + (ashiftrt:HI (match_dup 0) + (match_operand:HI 1 "general_operand" "dI")))] + "" + "asr%.w %1,%0") + (define_insn "ashrqi3" [(set (match_operand:QI 0 "register_operand" "=d") (ashiftrt:QI (match_operand:QI 1 "register_operand" "0") (match_operand:QI 2 "general_operand" "dI")))] "" "asr%.b %2,%0") + +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d")) + (ashiftrt:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "dI")))] + "" + "asr%.b %1,%0") ;; logical shift instructions +;; On all 68k models, this makes faster code in a special case. + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=d") + (lshift:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "immediate_operand" "i")))] + "(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 16)" + "* +{ + CC_STATUS_INIT; + return \"swap %0\;clr%.w %0\"; +}") + ;; On the 68000, this makes faster code in a special case. (define_insn "" @@ -3061,16 +3430,13 @@ (lshift:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "immediate_operand" "i")))] "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) >= 16 && INTVAL (operands[2]) <= 24)" + && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)" "* { CC_STATUS_INIT; - if (INTVAL (operands[2]) == 16) - return \"swap %0\;clrw %0\"; - operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16); - return \"lsl%.w %2,%0\;swap %0\;clrw %0\"; + return \"lsl%.w %2,%0\;swap %0\;clr%.w %0\"; }") (define_insn "lshlsi3" @@ -3092,6 +3458,13 @@ "" "lsl%.w %2,%0") +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d")) + (lshift:HI (match_dup 0) + (match_operand:HI 1 "general_operand" "dI")))] + "" + "lsl%.w %1,%0") + (define_insn "lshlqi3" [(set (match_operand:QI 0 "register_operand" "=d") (lshift:QI (match_operand:QI 1 "register_operand" "0") @@ -3099,6 +3472,26 @@ "" "lsl%.b %2,%0") +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d")) + (lshift:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "dI")))] + "" + "lsl%.b %1,%0") + +;; On all 68k models, this makes faster code in a special case. + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=d") + (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") + (match_operand:SI 2 "immediate_operand" "i")))] + "(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 16)" + "* +{ + CC_STATUS_INIT; + return \"clr%.w %0\;swap %0\"; +}") + ;; On the 68000, this makes faster code in a special case. (define_insn "" @@ -3106,18 +3499,12 @@ (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "immediate_operand" "i")))] "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) >= 16 && INTVAL (operands[2]) <= 24)" + && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)" "* { - if (INTVAL (operands[2]) == 16) - { - CC_STATUS_INIT; - return \"clrw %0\;swap %0\"; - } - /* I think lsr%.w sets the CC properly. */ operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16); - return \"clrw %0\;swap %0\;lsr%.w %2,%0\"; + return \"clr%.w %0\;swap %0\;lsr%.w %2,%0\"; }") (define_insn "lshrsi3" @@ -3137,12 +3524,26 @@ "" "lsr%.w %2,%0") +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d")) + (lshiftrt:HI (match_dup 0) + (match_operand:HI 1 "general_operand" "dI")))] + "" + "lsr%.w %1,%0") + (define_insn "lshrqi3" [(set (match_operand:QI 0 "register_operand" "=d") (lshiftrt:QI (match_operand:QI 1 "register_operand" "0") (match_operand:QI 2 "general_operand" "dI")))] "" "lsr%.b %2,%0") + +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d")) + (lshiftrt:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "dI")))] + "" + "lsr%.b %1,%0") ;; rotate instructions @@ -3160,6 +3561,14 @@ "" "rol%.w %2,%0") + +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d")) + (rotate:HI (match_dup 0) + (match_operand:HI 1 "general_operand" "dI")))] + "" + "rol%.w %1,%0") + (define_insn "rotlqi3" [(set (match_operand:QI 0 "register_operand" "=d") (rotate:QI (match_operand:QI 1 "register_operand" "0") @@ -3167,6 +3576,13 @@ "" "rol%.b %2,%0") +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d")) + (rotate:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "dI")))] + "" + "rol%.b %1,%0") + (define_insn "rotrsi3" [(set (match_operand:SI 0 "register_operand" "=d") (rotatert:SI (match_operand:SI 1 "register_operand" "0") @@ -3181,12 +3597,26 @@ "" "ror%.w %2,%0") +(define_insn "" + [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d")) + (rotatert:HI (match_dup 0) + (match_operand:HI 1 "general_operand" "dI")))] + "" + "ror%.w %1,%0") + (define_insn "rotrqi3" [(set (match_operand:QI 0 "register_operand" "=d") (rotatert:QI (match_operand:QI 1 "register_operand" "0") (match_operand:QI 2 "general_operand" "dI")))] "" "ror%.b %2,%0") + +(define_insn "" + [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d")) + (rotatert:QI (match_dup 0) + (match_operand:QI 1 "general_operand" "dI")))] + "" + "ror%.b %1,%0") ;; Special cases of bit-field insns which we should ;; recognize in preference to the general case. @@ -3201,7 +3631,7 @@ ; than an odd byte aligned bit field instruction. ; (define_insn "" - [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "o") + [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o") (match_operand:SI 1 "immediate_operand" "i") (match_operand:SI 2 "immediate_operand" "i")) (match_operand:SI 3 "general_operand" "rmi"))] @@ -4049,7 +4479,7 @@ } #ifdef MOTOROLA #ifdef SGS_CMP_ORDER -#ifndef NO_ADDSUB_Q +#ifdef NO_ADDSUB_Q return \"sub%.w %#1,%0\;cmp%.w %0,%#-1\;jbne %l1\"; #else return \"subq%.w %#1,%0\;cmp%.w %0,%#-1\;jbne %l1\"; @@ -4077,7 +4507,7 @@ { CC_STATUS_INIT; #ifdef MOTOROLA -#ifndef NO_ADDSUB_Q +#ifdef NO_ADDSUB_Q if (DATA_REG_P (operands[0])) return \"dbra %0,%l1\;clr%.w %0\;sub%.l %#1,%0\;jbcc %l1\"; if (GET_CODE (operands[0]) == MEM) @@ -4087,9 +4517,9 @@ return \"dbra %0,%l1\;clr%.w %0\;subq%.l %#1,%0\;jbcc %l1\"; if (GET_CODE (operands[0]) == MEM) return \"subq%.l %#1,%0\;jbcc %l1\"; -#endif /* not NO_ADDSUB_Q */ +#endif /* NO_ADDSUB_Q */ #ifdef SGS_CMP_ORDER -#ifndef NO_ADDSUB_Q +#ifdef NO_ADDSUB_Q return \"sub.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\"; #else return \"subq.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\"; @@ -4099,19 +4529,65 @@ #endif /* not SGS_CMP_ORDER */ #else /* not MOTOROLA */ if (DATA_REG_P (operands[0])) - return \"dbra %0,%l1\;clrw %0\;subql %#1,%0\;jcc %l1\"; + return \"dbra %0,%l1\;clr%.w %0\;subql %#1,%0\;jcc %l1\"; if (GET_CODE (operands[0]) == MEM) return \"subql %#1,%0\;jcc %l1\"; return \"subql %#1,%0\;cmpl %#-1,%0\;jne %l1\"; #endif /* not MOTOROLA */ }") -;; dbra patterns that use REG_NOTES info generated by strength_reduce. +;; Two dbra patterns that use REG_NOTES info generated by strength_reduce. + +(define_insn "" + [(set (pc) + (if_then_else + (ge (plus:HI (match_operand:HI 0 "general_operand" "+g") + (const_int -1)) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:HI (match_dup 0) + (const_int -1)))] + "find_reg_note (insn, REG_NONNEG, 0)" + "* +{ + CC_STATUS_INIT; +#ifdef MOTOROLA +#ifdef NO_ADDSUB_Q + if (DATA_REG_P (operands[0])) + return \"dbra %0,%l1\"; + if (GET_CODE (operands[0]) == MEM) + return \"sub%.w %#1,%0\;jbcc %l1\"; +#else + if (DATA_REG_P (operands[0])) + return \"dbra %0,%l1\"; + if (GET_CODE (operands[0]) == MEM) + return \"subq%.w %#1,%0\;jbcc %l1\"; +#endif +#ifdef SGS_CMP_ORDER +#ifdef NO_ADDSUB_Q + return \"sub.w %#1,%0\;cmp.w %0,%#-1\;jbne %l1\"; +#else + return \"subq.w %#1,%0\;cmp.w %0,%#-1\;jbne %l1\"; +#endif +#else /* not SGS_CMP_ORDER */ + return \"subq.w %#1,%0\;cmp.w %#-1,%0\;jbne %l1\"; +#endif /* not SGS_CMP_ORDER */ +#else /* not MOTOROLA */ + if (DATA_REG_P (operands[0])) + return \"dbra %0,%l1\"; + if (GET_CODE (operands[0]) == MEM) + return \"subqw %#1,%0\;jcc %l1\"; + return \"subqw %#1,%0\;cmpw %#-1,%0\;jne %l1\"; +#endif /* not MOTOROLA */ +}") (define_insn "decrement_and_branch_until_zero" [(set (pc) (if_then_else - (gt (match_operand:SI 0 "general_operand" "+g") + (ge (plus:SI (match_operand:SI 0 "general_operand" "+g") + (const_int -1)) (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) @@ -4123,7 +4599,7 @@ { CC_STATUS_INIT; #ifdef MOTOROLA -#ifndef NO_ADDSUB_Q +#ifdef NO_ADDSUB_Q if (DATA_REG_P (operands[0])) return \"dbra %0,%l1\;clr%.w %0\;sub%.l %#1,%0\;jbcc %l1\"; if (GET_CODE (operands[0]) == MEM) @@ -4135,7 +4611,7 @@ return \"subq%.l %#1,%0\;jbcc %l1\"; #endif #ifdef SGS_CMP_ORDER -#ifndef NO_ADDSUB_Q +#ifdef NO_ADDSUB_Q return \"sub.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\"; #else return \"subq.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\"; @@ -4145,7 +4621,7 @@ #endif /* not SGS_CMP_ORDER */ #else /* not MOTOROLA */ if (DATA_REG_P (operands[0])) - return \"dbra %0,%l1\;clrw %0\;subql %#1,%0\;jcc %l1\"; + return \"dbra %0,%l1\;clr%.w %0\;subql %#1,%0\;jcc %l1\"; if (GET_CODE (operands[0]) == MEM) return \"subql %#1,%0\;jcc %l1\"; return \"subql %#1,%0\;cmpl %#-1,%0\;jne %l1\"; @@ -4260,10 +4736,10 @@ { operands[0] = gen_rtx (PLUS, SImode, stack_pointer_rtx, gen_rtx (CONST_INT, VOIDmode, NEED_PROBE)); - return \"tstl %0\"; + return \"tstl %a0\"; }") -;; Used for framless functions which save no regs and allocate no locals. +;; Used for frameless functions which save no regs and allocate no locals. (define_insn "return" [(return)] "USE_RETURN_INSN" @@ -4276,15 +4752,9 @@ }") (define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "register_operand" "a"))] + [(set (pc) (match_operand:SI 0 "address_operand" "p"))] "" - "* -#ifdef MOTOROLA - return \"jmp (%0)\"; -#else - return \"jmp %0@\"; -#endif -") + "jmp %a0") ;; This should not be used unless the add/sub insns can't be. @@ -4301,7 +4771,7 @@ (define_peephole [(set (reg:SI 15) (plus:SI (reg:SI 15) (const_int 4))) - (set (match_operand:DF 0 "register_operand" "f") + (set (match_operand:DF 0 "register_operand" "=f") (match_operand:DF 1 "register_operand" "ad"))] "FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])" "* @@ -4339,7 +4809,7 @@ { xoperands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (xoperands[1]) - 8); - output_asm_insn (\"addq%.w %#8,%0; addq%.w %1,%0\", xoperands); + output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands); } else #endif @@ -4376,7 +4846,7 @@ { xoperands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (xoperands[1]) - 8); - output_asm_insn (\"addq%.w %#8,%0; addq%.w %1,%0\", xoperands); + output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands); } else #endif @@ -4413,6 +4883,71 @@ output_asm_insn (\"subq%.w %#4,%3\;move%.b %1,%2\", xoperands); return \"\"; }") + +;; dbCC peepholes +;; +;; Turns +;; loop: +;; [ ... ] +;; jCC label ; abnormal loop termination +;; dbra dN, loop ; normal loop termination +;; +;; Into +;; loop: +;; [ ... ] +;; dbCC dN, loop +;; jCC label +;; +;; Which moves the jCC condition outside the inner loop for free. +;; +(define_peephole + [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p" + [(cc0) (const_int 0)]) + (label_ref (match_operand 2 "" "")) + (pc))) + (parallel + [(set (pc) + (if_then_else + (ge (plus:HI (match_operand:HI 0 "register_operand" "+d") + (const_int -1)) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:HI (match_dup 0) + (const_int -1)))])] + "DATA_REG_P (operands[0])" + "* +{ + CC_STATUS_INIT; + output_dbcc_and_branch (operands); + return \"\"; +}") + +(define_peephole + [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p" + [(cc0) (const_int 0)]) + (label_ref (match_operand 2 "" "")) + (pc))) + (parallel + [(set (pc) + (if_then_else + (ge (plus:SI (match_operand:SI 0 "register_operand" "+d") + (const_int -1)) + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc))) + (set (match_dup 0) + (plus:SI (match_dup 0) + (const_int -1)))])] + "DATA_REG_P (operands[0])" + "* +{ + CC_STATUS_INIT; + output_dbcc_and_branch (operands); + return \"\"; +}") + ;; FPA multiply and add. (define_insn ""