--- gcc/config/m68k/m68k.md 2018/04/24 18:10:23 1.1.1.1 +++ gcc/config/m68k/m68k.md 2018/04/24 18:43:56 1.1.1.5 @@ -1,6 +1,5 @@ -;;- Machine description for GNU compiler -;;- Motorola 68000 Version -;; Copyright (C) 1987, 1988, 1993 Free Software Foundation, Inc. +;;- Machine description for GNU compiler, Motorola 68000 Version +;; Copyright (C) 1987, 1988, 1993, 1994, 1995 Free Software Foundation, Inc. ;; This file is part of GNU CC. @@ -16,7 +15,8 @@ ;; You should have received a copy of the GNU General Public License ;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. +;; the Free Software Foundation, 59 Temple Place - Suite 330, +;; Boston, MA 02111-1307, USA. ;;- instruction definitions @@ -65,6 +65,12 @@ ;;- "%$" single-precision fp specifier ("s" or "") f%$add.x fp0,fp1 ;;- "%&" double-precision fp specifier ("d" or "") f%&add.x fp0,fp1 +;; UNSPEC usage: +;; 1 This is a `sin' operation. The mode of the UNSPEC is MODE_FLOAT. +;; operand 1 is the argument for `sin'. +;; 2 This is a `cos' operation. The mode of the UNSPEC is MODE_FLOAT. +;; operand 1 is the argument for `cos'. + ;;- Information about 68040 port. ;;- The 68040 executes all 68030 and 68881/2 instructions, but some must @@ -275,6 +281,26 @@ ;; We don't want to allow a constant operand for test insns because ;; (set (cc0) (const_int foo)) has no mode information. Such insns will ;; be folded while optimizing anyway. + +(define_expand "tstdi" + [(parallel + [(set (cc0) + (match_operand:DI 0 "nonimmediate_operand" "d")) + (clobber (match_dup 1))])] + "" + "operands[1] = gen_reg_rtx (DImode);") + +(define_insn "" + [(set (cc0) + (match_operand:DI 1 "nonimmediate_operand" "0")) + (clobber (match_operand:DI 0 "register_operand" "=d"))] + "" + "* +{ + cc_status.flags |= CC_REVERSED; + return \"neg%.l %R0\;negx%.l %0\"; +}") + (define_insn "tstsi" [(set (cc0) (match_operand:SI 0 "nonimmediate_operand" "rm"))] @@ -378,8 +404,55 @@ ;; compare instructions. +(define_expand "cmpdi" + [(parallel + [(set (cc0) + (compare (match_operand:DI 0 "nonimmediate_operand" "") + (match_operand:DI 1 "general_operand" ""))) + (clobber (match_dup 2))])] + "" + "operands[2] = gen_reg_rtx (DImode);") + +(define_insn "" + [(set (cc0) + (compare (match_operand:DI 1 "nonimmediate_operand" "0,d") + (match_operand:DI 2 "general_operand" "d,0"))) + (clobber (match_operand:DI 0 "register_operand" "=d,d"))] + "" + "* +{ + if (rtx_equal_p (operands[0], operands[1])) + return \"sub%.l %R2,%R0\;subx%.l %2,%0\"; + else + { + cc_status.flags |= CC_REVERSED; + return \"sub%.l %R1,%R0\;subx%.l %1,%0\"; + } +}") + +;; This is the second "hook" for PIC code (in addition to movsi). See +;; comment of movsi for a description of PIC handling. +(define_expand "cmpsi" + [(set (cc0) + (compare (match_operand:SI 0 "nonimmediate_operand" "") + (match_operand:SI 1 "general_operand" "")))] + "" + " +{ + if (flag_pic && symbolic_operand (operands[1], SImode)) + { + /* The source is an address which requires PIC relocation. + Call legitimize_pic_address with the source, mode, and a relocation + register (a new pseudo, or the final destination if reload_in_progress + is set). Then fall through normally */ + extern rtx legitimize_pic_address(); + rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode); + operands[1] = legitimize_pic_address (operands[1], SImode, temp); + } +}") + ;; A composite of the cmp, cmpa, & cmpi m68000 op codes. -(define_insn "cmpsi" +(define_insn "" [(set (cc0) (compare (match_operand:SI 0 "nonimmediate_operand" "rKs,mr,>") (match_operand:SI 1 "general_operand" "mr,Ksr,>")))] @@ -387,7 +460,11 @@ "* { if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) +#ifdef SGS_CMP_ORDER + return \"cmpm%.l %0,%1\"; +#else return \"cmpm%.l %1,%0\"; +#endif if (REG_P (operands[1]) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) { cc_status.flags |= CC_REVERSED; @@ -406,13 +483,17 @@ (define_insn "cmphi" [(set (cc0) - (compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m") - (match_operand:HI 1 "general_operand" "d,rnm,m,n")))] + (compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m,>") + (match_operand:HI 1 "general_operand" "d,rnm,m,n,>")))] "" "* { if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) +#ifdef SGS_CMP_ORDER + return \"cmpm%.w %0,%1\"; +#else return \"cmpm%.w %1,%0\"; +#endif if ((REG_P (operands[1]) && !ADDRESS_REG_P (operands[1])) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) { cc_status.flags |= CC_REVERSED; @@ -437,7 +518,11 @@ "* { if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) +#ifdef SGS_CMP_ORDER + return \"cmpm%.b %0,%1\"; +#else return \"cmpm%.b %1,%0\"; +#endif if (REG_P (operands[1]) || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) { cc_status.flags |= CC_REVERSED; @@ -587,7 +672,7 @@ (const_int 1) (minus:SI (const_int 7) (and:SI - (match_operand:SI 1 "general_operand" "d") + (match_operand:SI 1 "register_operand" "d") (const_int 7)))))] "" "* { return output_btst (operands, operands[1], operands[0], insn, 7); }") @@ -597,7 +682,7 @@ (const_int 1) (minus:SI (const_int 31) (and:SI - (match_operand:SI 1 "general_operand" "d") + (match_operand:SI 1 "register_operand" "d") (const_int 31)))))] "" "* { return output_btst (operands, operands[1], operands[0], insn, 31); }") @@ -607,9 +692,8 @@ (define_insn "" [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "md") (const_int 1) - (match_operand:SI 1 "general_operand" "i")))] - "GET_CODE (operands[1]) == CONST_INT - && (unsigned) INTVAL (operands[1]) < 8" + (match_operand:SI 1 "const_int_operand" "n")))] + "(unsigned) INTVAL (operands[1]) < 8" "* { operands[1] = gen_rtx (CONST_INT, VOIDmode, 7 - INTVAL (operands[1])); @@ -619,8 +703,8 @@ (define_insn "" [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "do") (const_int 1) - (match_operand:SI 1 "general_operand" "i")))] - "GET_CODE (operands[1]) == CONST_INT" + (match_operand:SI 1 "const_int_operand" "n")))] + "" "* { if (GET_CODE (operands[0]) == MEM) @@ -643,10 +727,8 @@ ;; to reload the constant into a data register. (define_insn "" [(set (match_operand:SI 0 "push_operand" "=m") - (match_operand:SI 1 "general_operand" "J"))] - "GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) >= -0x8000 - && INTVAL (operands[1]) < 0x8000" + (match_operand:SI 1 "const_int_operand" "J"))] + "INTVAL (operands[1]) >= -0x8000 && INTVAL (operands[1]) < 0x8000" "* { if (operands[1] == const0_rtx) @@ -741,56 +823,8 @@ || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))) return \"clr%.l %0\"; - else if (DATA_REG_P (operands[0]) - && INTVAL (operands[1]) < 128 - && INTVAL (operands[1]) >= -128) - { -#if defined(MOTOROLA) && !defined(CRDS) - return \"moveq%.l %1,%0\"; -#else - return \"moveq %1,%0\"; -#endif - } -#ifndef NO_ADDSUB_Q - else if (DATA_REG_P (operands[0]) - /* Do this with a moveq #N-8, dreg; addq #8,dreg */ - && INTVAL (operands[1]) < 136 - && INTVAL (operands[1]) >= 128) - { - 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\"; -#else - return \"moveq %1,%0\;addq%.w %#8,%0\"; -#endif - } - else if (DATA_REG_P (operands[0]) - /* Do this with a moveq #N+8, dreg; subq #8,dreg */ - && INTVAL (operands[1]) < -128 - && INTVAL (operands[1]) >= -136) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) + 8); -#if defined(MOTOROLA) && !defined(CRDS) - return \"moveq%.l %1,%0;subq%.w %#8,%0\"; -#else - return \"moveq %1,%0;subq%.w %#8,%0\"; -#endif - } -#endif - else if (DATA_REG_P (operands[0]) - /* If N is in the right range and is even, then use - moveq #N/2, dreg; addl dreg,dreg */ - && INTVAL (operands[1]) > 127 - && INTVAL (operands[1]) <= 254 - && INTVAL (operands[1]) % 2 == 0) - { - 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\"; -#else - return \"moveq %1,%0\;add%.w %0,%0\"; -#endif - } + else if (DATA_REG_P (operands[0])) + return output_move_const_into_data_reg (operands); else if (ADDRESS_REG_P (operands[0]) && INTVAL (operands[1]) < 0x8000 && INTVAL (operands[1]) >= -0x8000) @@ -848,19 +882,15 @@ /* Recognize the insn before a tablejump, one that refers to a table of offsets. Such an insn will need to refer to a label on the insn. So output one. Use the label-number - of the table of offsets to generate this label. */ + of the table of offsets to generate this label. This code, + and similar code below, assumes that there will be at most one + reference to each table. */ if (GET_CODE (operands[1]) == MEM && GET_CODE (XEXP (operands[1], 0)) == PLUS - && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF - || GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF) - && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS - && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) != PLUS) - { - rtx labelref; - if (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF) - labelref = XEXP (XEXP (operands[1], 0), 0); - else - labelref = XEXP (XEXP (operands[1], 0), 1); + && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF + && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS) + { + rtx labelref = XEXP (XEXP (operands[1], 0), 1); #if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES) #ifdef SGS asm_fprintf (asm_out_file, \"\\tset %LLI%d,.+2\\n\", @@ -916,7 +946,8 @@ of several bytes a byte at a time. */ if (GET_CODE (operands[0]) == MEM && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC - && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx) + && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx + && ! ADDRESS_REG_P (operands[1])) { xoperands[1] = operands[1]; xoperands[2] @@ -946,7 +977,7 @@ and pop d0/1. */ if (! reg_mentioned_p (stack_pointer_rtx, operands[1])) { - if (refers_to_regno_p (0, 1, operands[1], NULL_RTX)) + if (! refers_to_regno_p (0, 1, operands[1], NULL_RTX)) return \"move%.l %/d0,%-\;move%.b %1,%/d0\;move%.l %/d0,%0\;move%.l %+,%/d0\"; else return \"move%.l %/d1,%-\;move%.b %1,%/d1\;move%.l %/d1,%0\;move%.l %+,%/d1\"; @@ -996,7 +1027,7 @@ and pop d0/1. */ if (! reg_mentioned_p (stack_pointer_rtx, operands[0])) { - if (refers_to_regno_p (0, 1, operands[0], NULL_RTX)) + if (! refers_to_regno_p (0, 1, operands[0], NULL_RTX)) return \"move%.l %/d0,%-\;move%.l %1,%/d0\;move%.b %/d0,%0\;move%.l %+,%/d0\"; else return \"move%.l %/d1,%-\;move%.l %1,%/d1\;move%.b %/d1,%0\;move%.l %+,%/d1\"; @@ -1109,14 +1140,14 @@ }") (define_insn "movdf" - [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>,y,rm,x,!x,!rm") - (match_operand:DF 1 "general_operand" "rf,m,rofE<>,rmE,y,xH,rm,x"))] + [(set (match_operand:DF 0 "general_operand" "=rm,rf,rf,&rof<>,y,rm,x,!x,!rm") + (match_operand:DF 1 "general_operand" "rf,m,0,rofE<>,rmE,y,xH,rm,x"))] ; [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>") ; (match_operand:DF 1 "general_operand" "rf,m,rofF<>"))] "" "* { - if (which_alternative == 6) + if (which_alternative == 7) return \"fpmove%.d %x1,fpa0\;fpmove%.d fpa0,%x0\"; if (FPA_REG_P (operands[0])) { @@ -1217,7 +1248,7 @@ ") (define_insn "" - [(set (match_operand:XF 0 "nonimmediate_operand" "=rm,&rf,&rof<>") + [(set (match_operand:XF 0 "nonimmediate_operand" "=rm,rf,&rof<>") (match_operand:XF 1 "nonimmediate_operand" "rf,m,rof<>"))] "! TARGET_68881" "* @@ -1260,7 +1291,7 @@ ;; movdi can apply to fp regs in some cases (define_insn "movdi" ;; Let's see if it really still needs to handle fp regs, and, if so, why. - [(set (match_operand:DI 0 "general_operand" "=rm,&r,&ro<>,y,rm,!*x,!rm") + [(set (match_operand:DI 0 "general_operand" "=rm,r,&ro<>,y,rm,!*x,!rm") (match_operand:DI 1 "general_operand" "rF,m,roi<>F,rmiF,y,rmF,*x"))] ; [(set (match_operand:DI 0 "general_operand" "=rm,&r,&ro<>,!&rm,!&f,y,rm,x,!x,!rm") ; (match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfmF,rmi,y,rm,x"))] @@ -1384,6 +1415,28 @@ ;; zero extension instructions +;; this is the canonical form for (lshiftrt:DI x 32) +(define_insn "zero_extendsidi2" + [(set (match_operand:DI 0 "general_operand" "ro,<,>") + (zero_extend:DI (match_operand:SI 1 "general_operand" "rm,rm,rm")))] + "" + "* +{ + CC_STATUS_INIT; + if (which_alternative == 2) + return \"clr%.l %0\;move%.l %1,%0\"; + if (which_alternative == 1) + return \"move%.l %1,%0\;clr%.l %0\"; + if (GET_CODE (operands[0]) == REG) + operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + else + operands[2] = adj_offsettable_operand (operands[0], 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\"; +}") + (define_expand "zero_extendhisi2" [(set (match_operand:SI 0 "register_operand" "") (const_int 0)) @@ -1559,6 +1612,78 @@ ;; sign extension instructions +(define_insn "extendqidi2" + [(set (match_operand:DI 0 "general_operand" "=d") + (sign_extend:DI + (match_operand:QI 1 "general_operand" "rm")))] + "" + "* +{ + CC_STATUS_INIT; + operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + if (TARGET_68020) + return \"move%.b %1,%2\;extb%.l %2\;smi %0\;extb%.l %0\"; + else + return \"move%.b %1,%2\;ext%.w %0\;ext%.l %2\;smi %0\;ext%.w %0\;ext%.l %0\"; +}") + +(define_insn "extendhidi2" + [(set (match_operand:DI 0 "general_operand" "=d") + (sign_extend:DI + (match_operand:HI 1 "general_operand" "rm")))] + "" + "* +{ + CC_STATUS_INIT; + operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + if (TARGET_68020) + return \"move%.w %1,%2\;ext%.l %2\;smi %0\;extb%.l %0\"; + else + return \"move%.w %1,%2\;ext%.l %2\;smi %0\;ext%.w %0\;ext%.l %0\"; +}") + +(define_insn "extendsidi2" + [(set (match_operand:DI 0 "general_operand" "=d") + (sign_extend:DI + (match_operand:SI 1 "general_operand" "rm")))] + "" + "* +{ + CC_STATUS_INIT; + 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\"; +}") + +;; Special case when one can avoid register clobbering, copy and test +;; Maybe there is a way to make that the general case, by forcing the +;; result of the SI tree to be in the lower register of the DI target + +(define_insn "extendplussidi" + [(set (match_operand:DI 0 "register_operand" "=d") + (sign_extend:DI (plus:SI (match_operand:SI 1 "general_operand" "%rmn") + (match_operand:SI 2 "general_operand" "rmn"))))] + "" + "* +{ + CC_STATUS_INIT; + operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + if (GET_CODE (operands[1]) == CONST_INT + && (unsigned) INTVAL (operands[1]) > 8) + { + rtx tmp = operands[1]; + + operands[1] = operands[2]; + operands[2] = tmp; + } + if (TARGET_68020) + return \"move%.l %2,%3\;add%.l %1,%3\;smi %0\;extb%.l %0\"; + else + return \"move%.l %2,%3\;add%.l %1,%3\;smi %0\;ext%.w %0\;ext%.l %0\"; +}") + (define_insn "extendhisi2" [(set (match_operand:SI 0 "general_operand" "=*d,a") (sign_extend:SI @@ -1744,7 +1869,7 @@ (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f")))) (clobber (match_scratch:SI 2 "=d")) (clobber (match_scratch:SI 3 "=d"))] - "TARGET_68040" + "TARGET_68881 && TARGET_68040" "* { CC_STATUS_INIT; @@ -1756,7 +1881,7 @@ (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "f")))) (clobber (match_scratch:SI 2 "=d")) (clobber (match_scratch:SI 3 "=d"))] - "TARGET_68040" + "TARGET_68881 && TARGET_68040" "* { CC_STATUS_INIT; @@ -1768,7 +1893,7 @@ (fix:QI (fix:DF (match_operand:DF 1 "register_operand" "f")))) (clobber (match_scratch:SI 2 "=d")) (clobber (match_scratch:SI 3 "=d"))] - "TARGET_68040" + "TARGET_68881 && TARGET_68040" "* { CC_STATUS_INIT; @@ -1855,6 +1980,157 @@ ;; add instructions +(define_insn "adddia_sexthishl32" + [(set (match_operand:DI 0 "register_operand" "+a") + (plus:DI (ashift:DI (sign_extend:DI + (match_operand:HI 1 "general_operand" "rm")) + (const_int 32)) + (match_dup 0)))] + "" + "* +{ + CC_STATUS_INIT; + return \"add%.w %1,%0\"; +} ") + +(define_insn "adddid_sexthishl32" + [(set (match_operand:DI 0 "general_operand" "+ro") + (plus:DI (ashift:DI (sign_extend:DI + (match_operand:HI 1 "general_operand" "rm")) + (const_int 32)) + (match_dup 0))) + (clobber (match_scratch:SI 2 "=a"))] + "" + "* +{ + CC_STATUS_INIT; + return \"move%.w %1,%2\;add%.l %2,%0\"; +} ") + +(define_insn "adddi_dilshr32" + [(set (match_operand:DI 0 "general_operand" "=do") +;; (plus:DI (match_operand:DI 2 "general_operand" "%0") +;; (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro") +;; (const_int 32))))] + (plus:DI (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro") + (const_int 32)) + (match_operand:DI 2 "general_operand" "0")))] + "" + "* +{ + CC_STATUS_INIT; + if (GET_CODE (operands[0]) == REG) + operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + else + operands[2] = adj_offsettable_operand (operands[0], 4); + return \"add%.l %1,%2\;negx%.l %0\;neg%.l %0\"; +} ") + +(define_insn "adddi_dishl32" + [(set (match_operand:DI 0 "general_operand" "=ro") +;; (plus:DI (match_operand:DI 2 "general_operand" "%0") +;; (ashift:DI (match_operand:DI 1 "general_operand" "ro") +;; (const_int 32))))] + (plus:DI (ashift:DI (match_operand:DI 1 "general_operand" "ro") + (const_int 32)) + (match_operand:DI 2 "general_operand" "0")))] + "" + "* +{ + CC_STATUS_INIT; + if (GET_CODE (operands[1]) == REG) + operands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); + else + operands[1] = adj_offsettable_operand (operands[1], 4); + return \"add%.l %1,%0\"; +} ") + +(define_insn "adddi3" + [(set (match_operand:DI 0 "general_operand" "=d,<,d,o<>") + (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0") + (match_operand:DI 2 "general_operand" "d,<,*ao>,d"))) + (clobber (match_scratch:SI 3 "=X,X,&d,&d"))] + "" + "* +{ + if (DATA_REG_P (operands[0])) + { + if (DATA_REG_P (operands[2])) + return \"add%.l %R2,%R0\;addx%.l %2,%0\"; + else if (GET_CODE (operands[2]) == MEM + && GET_CODE (XEXP (operands[2], 0)) == POST_INC) + { + return \"move%.l %2,%3\;add%.l %2,%R0\;addx%.l %3,%0\"; + } + else + { + /* TODO : this should work also for CONST operands[2] */ + if (GET_CODE (operands[2]) == REG) + operands[1] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1); + else + operands[1] = adj_offsettable_operand (operands[2], 4); + return \"move%.l %2,%3\;add%.l %1,%R0\;addx%.l %3,%0\"; + } + } + else if (GET_CODE (operands[0]) == MEM) + { + if (GET_CODE (operands[2]) == MEM + && GET_CODE (XEXP (operands[2], 0)) == PRE_DEC) + return \"add%.l %2,%0\;addx%.l %2,%0\"; + CC_STATUS_INIT; + if (GET_CODE (XEXP (operands[0], 0)) == POST_INC) + { + operands[1] = gen_rtx (MEM, SImode, + gen_rtx (PLUS, VOIDmode, XEXP(operands[0], 0), + gen_rtx (CONST_INT, VOIDmode, -8))); + return \"move%.l %0,%3\;add%.l %R2,%0\;addx%.l %2,%3\;move%.l %3,%1\"; + } + else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) + { + operands[1] = XEXP(operands[0], 0); + return \"add%.l %R2,%0\;move%.l %0,%3\;addx%.l %2,%3\;move%.l %3,%1\"; + } + else + { + operands[1] = adj_offsettable_operand (operands[0], 4); + return \"add%.l %R2,%1\;move%.l %0,%3\;addx%.l %2,%3\;move%.l %3,%0\"; + } + } +} ") + +(define_insn "addsi_lshrsi_31" + [(set (match_operand:SI 0 "general_operand" "=dm") + (plus:SI (lshiftrt:SI (match_operand:SI 1 "general_operand" "rm") + (const_int 31)) + (match_dup 1)))] + "" + "* +{ + operands[2] = operands[0]; + operands[3] = gen_label_rtx(); + if (GET_CODE (operands[0]) == MEM) + { + if (GET_CODE (XEXP (operands[0], 0)) == POST_INC) + operands[0] = gen_rtx (MEM, SImode, XEXP (XEXP (operands[0], 0), 0)); + else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) + operands[2] = gen_rtx (MEM, SImode, XEXP (XEXP (operands[0], 0), 0)); + } + output_asm_insn (\"move%.l %1,%0\", operands); +#ifdef MOTOROLA + output_asm_insn (\"jbpl %l3\", operands); +#else + output_asm_insn (\"jpl %l3\", operands); +#endif +#ifndef NO_ADDSUB_Q + output_asm_insn (\"addq%.l %#1,%2\", operands); +#else + output_asm_insn (\"add%.l %#1,%2\", operands); +#endif + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (operands[3])); + return \"\"; +}") + ;; Note that the middle two alternatives are near-duplicates ;; in order to handle insns generated by reload. ;; This is needed since they are not themselves reloaded, @@ -2228,6 +2504,27 @@ (define_insn "" [(set (match_operand:DF 0 "general_operand" "=f") + (plus:DF (float:DF (match_operand:SI 2 "general_operand" "dmi")) + (match_operand:DF 1 "general_operand" "0")))] + "TARGET_68881" + "f%&add%.l %2,%0") + +(define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (plus:DF (float:DF (match_operand:HI 2 "general_operand" "dmn")) + (match_operand:DF 1 "general_operand" "0")))] + "TARGET_68881" + "f%&add%.w %2,%0") + +(define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (plus:DF (float:DF (match_operand:QI 2 "general_operand" "dmn")) + (match_operand:DF 1 "general_operand" "0")))] + "TARGET_68881" + "f%&add%.b %2,%0") + +(define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") (plus:DF (match_operand:DF 1 "general_operand" "%0") (match_operand:DF 2 "general_operand" "fmG")))] "TARGET_68881" @@ -2263,6 +2560,27 @@ (define_insn "" [(set (match_operand:SF 0 "general_operand" "=f") + (plus:SF (float:SF (match_operand:SI 2 "general_operand" "dmi")) + (match_operand:SF 1 "general_operand" "0")))] + "TARGET_68881" + "f%$add%.l %2,%0") + +(define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (plus:SF (float:SF (match_operand:HI 2 "general_operand" "dmn")) + (match_operand:SF 1 "general_operand" "0")))] + "TARGET_68881" + "f%$add%.w %2,%0") + +(define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (plus:SF (float:SF (match_operand:QI 2 "general_operand" "dmn")) + (match_operand:SF 1 "general_operand" "0")))] + "TARGET_68881" + "f%$add%.b %2,%0") + +(define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") (plus:SF (match_operand:SF 1 "general_operand" "%0") (match_operand:SF 2 "general_operand" "fdmF")))] "TARGET_68881" @@ -2275,66 +2593,106 @@ ;; subtract instructions -(define_insn "subsi3" - [(set (match_operand:SI 0 "general_operand" "=m,r,!a,?d") - (minus:SI (match_operand:SI 1 "general_operand" "0,0,a,mrIKs") - (match_operand:SI 2 "general_operand" "dIKs,mrIKs,J,0")))] +(define_insn "subdia_sexthishl32" + [(set (match_operand:DI 0 "register_operand" "+a") + (minus:DI (match_dup 0) + (ashift:DI (sign_extend:DI (match_operand:HI 1 "general_operand" "rm")) + (const_int 32))))] "" "* { - if (! operands_match_p (operands[0], operands[1])) + CC_STATUS_INIT; + return \"sub%.w %1,%0\"; +} ") + +(define_insn "subdid_sexthishl32" + [(set (match_operand:DI 0 "general_operand" "+ro") + (minus:DI (match_dup 0) + (ashift:DI (sign_extend:DI (match_operand:HI 1 "general_operand" "rm")) + (const_int 32)))) + (clobber (match_scratch:SI 2 "=a"))] + "" + "* +{ + CC_STATUS_INIT; + return \"move%.w %1,%2\;sub%.l %2,%0\"; +} ") + +(define_insn "subdi_dishl32" + [(set (match_operand:DI 0 "general_operand" "+ro") + (minus:DI (match_dup 0) + (ashift:DI (match_operand:DI 1 "general_operand" "ro") + (const_int 32))))] + "" + "* +{ + CC_STATUS_INIT; + if (GET_CODE (operands[1]) == REG) + operands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); + else + operands[1] = adj_offsettable_operand (operands[1], 4); + return \"sub%.l %1,%0\"; +} ") + +(define_insn "subdi3" + [(set (match_operand:DI 0 "general_operand" "=d,<,d,o<>") + (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0") + (match_operand:DI 2 "general_operand" "d,<,*ao>,d"))) + (clobber (match_scratch:SI 3 "=X,X,&d,&d"))] + "" + "* +{ + if (DATA_REG_P (operands[0])) { - if (operands_match_p (operands[0], operands[2])) + if (DATA_REG_P (operands[2])) + return \"sub%.l %R2,%R0\;subx%.l %2,%0\"; + else if (GET_CODE (operands[2]) == MEM + && GET_CODE (XEXP (operands[2], 0)) == POST_INC) { -#ifndef NO_ADDSUB_Q - if (GET_CODE (operands[1]) == CONST_INT) - { - if (INTVAL (operands[1]) > 0 - && INTVAL (operands[1]) <= 8) - return \"subq%.l %1,%0\;neg%.l %0\"; - } -#endif - return \"sub%.l %1,%0\;neg%.l %0\"; + return \"move%.l %2,%3\;sub%.l %2,%R0\;subx%.l %3,%0\"; + } + else + { + /* TODO : this should work also for CONST operands[2] */ + if (GET_CODE (operands[2]) == REG) + operands[1] = gen_rtx (REG, SImode, REGNO (operands[2]) + 1); + else + operands[1] = adj_offsettable_operand (operands[2], 4); + return \"move%.l %2,%3\;sub%.l %1,%R0\;subx%.l %3,%0\"; } - /* This case is matched by J, but negating -0x8000 - in an lea would give an invalid displacement. - So do this specially. */ - if (INTVAL (operands[2]) == -0x8000) - return \"move%.l %1,%0\;sub%.l %2,%0\"; -#ifdef SGS - return \"lea %n2(%1),%0\"; -#else -#ifdef MOTOROLA - return \"lea (%n2,%1),%0\"; -#else /* not MOTOROLA (MIT syntax) */ - return \"lea %1@(%n2),%0\"; -#endif /* not MOTOROLA */ -#endif /* not SGS */ } - if (GET_CODE (operands[2]) == CONST_INT) + else if (GET_CODE (operands[0]) == MEM) { -#ifndef NO_ADDSUB_Q - if (INTVAL (operands[2]) > 0 - && INTVAL (operands[2]) <= 8) - return \"subq%.l %2,%0\"; - /* Using two subqw for 8 < N <= 16 being subtracted from an - address register is faster on all but 68000 */ - if (INTVAL (operands[2]) > 8 - && INTVAL (operands[2]) <= 16 - && ADDRESS_REG_P (operands[0]) - && TARGET_68020) + if (GET_CODE (operands[2]) == MEM + && GET_CODE (XEXP (operands[2], 0)) == PRE_DEC) + return \"sub%.l %2,%0\;subx%.l %2,%0\"; + CC_STATUS_INIT; + if (GET_CODE (XEXP (operands[0], 0)) == POST_INC) { - operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 8); - return \"subq%.w %#8,%0\;subq%.w %2,%0\"; + operands[1] = gen_rtx (MEM, SImode, + gen_rtx (PLUS, VOIDmode, XEXP(operands[0], 0), + gen_rtx (CONST_INT, VOIDmode, -8))); + return \"move%.l %0,%3\;sub%.l %R2,%0\;subx%.l %2,%3\;move%.l %3,%1\"; + } + else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) + { + operands[1] = XEXP(operands[0], 0); + return \"sub%.l %R2,%0\;move%.l %0,%3\;subx%.l %2,%3\;move%.l %3,%1\"; + } + else + { + operands[1] = adj_offsettable_operand (operands[0], 4); + return \"sub%.l %R2,%1\;move%.l %0,%3\;subx%.l %2,%3\;move%.l %3,%0\"; } -#endif - if (ADDRESS_REG_P (operands[0]) - && INTVAL (operands[2]) >= -0x8000 - && INTVAL (operands[2]) < 0x8000) - return \"sub%.w %2,%0\"; } - return \"sub%.l %2,%0\"; -}") +} ") + +(define_insn "subsi3" + [(set (match_operand:SI 0 "general_operand" "=m,r") + (minus:SI (match_operand:SI 1 "general_operand" "0,0") + (match_operand:SI 2 "general_operand" "ds,mrs")))] + "" + "sub%.l %2,%0") (define_insn "" [(set (match_operand:SI 0 "general_operand" "=a") @@ -2398,6 +2756,27 @@ (define_insn "" [(set (match_operand:DF 0 "general_operand" "=f") (minus:DF (match_operand:DF 1 "general_operand" "0") + (float:DF (match_operand:SI 2 "general_operand" "dmi"))))] + "TARGET_68881" + "f%&sub%.l %2,%0") + +(define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (minus:DF (match_operand:DF 1 "general_operand" "0") + (float:DF (match_operand:HI 2 "general_operand" "dmn"))))] + "TARGET_68881" + "f%&sub%.w %2,%0") + +(define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (minus:DF (match_operand:DF 1 "general_operand" "0") + (float:DF (match_operand:QI 2 "general_operand" "dmn"))))] + "TARGET_68881" + "f%&sub%.b %2,%0") + +(define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (minus:DF (match_operand:DF 1 "general_operand" "0") (match_operand:DF 2 "general_operand" "fmG")))] "TARGET_68881" "* @@ -2433,6 +2812,27 @@ (define_insn "" [(set (match_operand:SF 0 "general_operand" "=f") (minus:SF (match_operand:SF 1 "general_operand" "0") + (float:SF (match_operand:SI 2 "general_operand" "dmi"))))] + "TARGET_68881" + "f%$sub%.l %2,%0") + +(define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (minus:SF (match_operand:SF 1 "general_operand" "0") + (float:SF (match_operand:HI 2 "general_operand" "dmn"))))] + "TARGET_68881" + "f%$sub%.w %2,%0") + +(define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (minus:SF (match_operand:SF 1 "general_operand" "0") + (float:SF (match_operand:QI 2 "general_operand" "dmn"))))] + "TARGET_68881" + "f%$sub%.b %2,%0") + +(define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (minus:SF (match_operand:SF 1 "general_operand" "0") (match_operand:SF 2 "general_operand" "fdmF")))] "TARGET_68881" "* @@ -2575,9 +2975,9 @@ (mult:SI (match_operand:SI 1 "register_operand" "") (match_operand:SI 2 "nonimmediate_operand" ""))) (set (subreg:SI (match_dup 0) 0) - (truncate:SI (ashift:DI (mult:DI (sign_extend:DI (match_dup 1)) - (sign_extend:DI (match_dup 2))) - (const_int 32))))])] + (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1)) + (sign_extend:DI (match_dup 2))) + (const_int 32))))])] "TARGET_68020" "") @@ -2586,9 +2986,9 @@ (mult:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "nonimmediate_operand" "dm"))) (set (match_operand:SI 3 "register_operand" "=d") - (truncate:SI (ashift:DI (mult:DI (sign_extend:DI (match_dup 1)) - (sign_extend:DI (match_dup 2))) - (const_int 32))))] + (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1)) + (sign_extend:DI (match_dup 2))) + (const_int 32))))] "TARGET_68020" "muls%.l %2,%3:%0") @@ -2597,9 +2997,9 @@ (mult:SI (match_operand:SI 1 "register_operand" "%0") (match_operand:SI 2 "const_int_operand" "n"))) (set (match_operand:SI 3 "register_operand" "=d") - (truncate:SI (ashift:DI (mult:DI (sign_extend:DI (match_dup 1)) - (match_dup 2)) - (const_int 32))))] + (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1)) + (match_dup 2)) + (const_int 32))))] "TARGET_68020 /* This test is a noop on 32 bit machines, but important for a cross-compiler hosted on 64-bit machines. */ @@ -2607,6 +3007,100 @@ && INTVAL (operands[2]) >= -0x80000000" "muls%.l %2,%3:%0") +(define_expand "umulsi3_highpart" + [(parallel + [(set (match_operand:SI 0 "register_operand" "") + (truncate:SI + (lshiftrt:DI + (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) + (zero_extend:DI (match_operand:SI 2 "general_operand" ""))) + (const_int 32)))) + (clobber (match_dup 3))])] + "TARGET_68020" + " +{ + operands[3] = gen_reg_rtx (SImode); + if (GET_CODE (operands[2]) == CONST_INT + || GET_CODE (operands[2]) == CONST_DOUBLE) + { + if (! const_uint32_operand (operands[2], VOIDmode)) + abort (); + /* We have to adjust the operand order for the matching constraints. */ + emit_insn (gen_const_umulsi3_highpart (operands[0], operands[3], + operands[1], operands[2])); + DONE; + } +}") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=d") + (truncate:SI + (lshiftrt:DI + (mult:DI (zero_extend:DI (match_operand:SI 2 "register_operand" "%1")) + (zero_extend:DI (match_operand:SI 3 "nonimmediate_operand" "dm"))) + (const_int 32)))) + (clobber (match_operand:SI 1 "register_operand" "=d"))] + "TARGET_68020" + "mulu%.l %3,%0:%1") + +(define_insn "const_umulsi3_highpart" + [(set (match_operand:SI 0 "register_operand" "=d") + (truncate:SI + (lshiftrt:DI + (mult:DI (zero_extend:DI (match_operand:SI 2 "register_operand" "1")) + (match_operand 3 "const_uint32_operand" "")) + (const_int 32)))) + (clobber (match_operand:SI 1 "register_operand" "=d"))] + "TARGET_68020" + "mulu%.l %3,%0:%1") + +(define_expand "smulsi3_highpart" + [(parallel + [(set (match_operand:SI 0 "register_operand" "") + (truncate:SI + (lshiftrt:DI + (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) + (sign_extend:DI (match_operand:SI 2 "general_operand" ""))) + (const_int 32)))) + (clobber (match_dup 3))])] + "TARGET_68020" + " +{ + operands[3] = gen_reg_rtx (SImode); + if (GET_CODE (operands[2]) == CONST_INT + || GET_CODE (operands[2]) == CONST_DOUBLE) + { + if (! const_sint32_operand (operands[2], VOIDmode)) + abort (); + /* We have to adjust the operand order for the matching constraints. */ + emit_insn (gen_const_smulsi3_highpart (operands[0], operands[3], + operands[1], operands[2])); + DONE; + } +}") + +(define_insn "" + [(set (match_operand:SI 0 "register_operand" "=d") + (truncate:SI + (lshiftrt:DI + (mult:DI (sign_extend:DI (match_operand:SI 2 "register_operand" "%1")) + (sign_extend:DI (match_operand:SI 3 "nonimmediate_operand" "dm"))) + (const_int 32)))) + (clobber (match_operand:SI 1 "register_operand" "=d"))] + "TARGET_68020" + "muls%.l %3,%0:%1") + +(define_insn "const_smulsi3_highpart" + [(set (match_operand:SI 0 "register_operand" "=d") + (truncate:SI + (lshiftrt:DI + (mult:DI (sign_extend:DI (match_operand:SI 2 "register_operand" "1")) + (match_operand 3 "const_sint32_operand" "")) + (const_int 32)))) + (clobber (match_operand:SI 1 "register_operand" "=d"))] + "TARGET_68020" + "muls%.l %3,%0:%1") + (define_expand "muldf3" [(set (match_operand:DF 0 "general_operand" "") (mult:DF (match_operand:DF 1 "general_operand" "") @@ -2634,6 +3128,27 @@ (define_insn "" [(set (match_operand:DF 0 "general_operand" "=f") + (mult:DF (float:DF (match_operand:SI 2 "general_operand" "dmi")) + (match_operand:DF 1 "general_operand" "0")))] + "TARGET_68881" + "f%&mul%.l %2,%0") + +(define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (mult:DF (float:DF (match_operand:HI 2 "general_operand" "dmn")) + (match_operand:DF 1 "general_operand" "0")))] + "TARGET_68881" + "f%&mul%.w %2,%0") + +(define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (mult:DF (float:DF (match_operand:QI 2 "general_operand" "dmn")) + (match_operand:DF 1 "general_operand" "0")))] + "TARGET_68881" + "f%&mul%.b %2,%0") + +(define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") (mult:DF (match_operand:DF 1 "general_operand" "%0") (match_operand:DF 2 "general_operand" "fmG")))] "TARGET_68881" @@ -2678,6 +3193,42 @@ (define_insn "" [(set (match_operand:SF 0 "general_operand" "=f") + (mult:SF (float:SF (match_operand:SI 2 "general_operand" "dmi")) + (match_operand:SF 1 "general_operand" "0")))] + "TARGET_68881" + "* +{ + return (TARGET_68040_ONLY + ? \"fsmul%.l %2,%0\" + : \"fsglmul%.l %2,%0\"); +}") + +(define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (mult:SF (float:SF (match_operand:HI 2 "general_operand" "dmn")) + (match_operand:SF 1 "general_operand" "0")))] + "TARGET_68881" + "* +{ + return (TARGET_68040_ONLY + ? \"fsmul%.w %2,%0\" + : \"fsglmul%.w %2,%0\"); +}") + +(define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (mult:SF (float:SF (match_operand:QI 2 "general_operand" "dmn")) + (match_operand:SF 1 "general_operand" "0")))] + "TARGET_68881" + "* +{ + return (TARGET_68040_ONLY + ? \"fsmul%.b %2,%0\" + : \"fsglmul%.b %2,%0\"); +}") + +(define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") (mult:SF (match_operand:SF 1 "general_operand" "%0") (match_operand:SF 2 "general_operand" "fdmF")))] "TARGET_68881" @@ -2701,94 +3252,6 @@ ;; divide instructions -(define_insn "divhi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (div:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:HI 2 "general_operand" "dmn")))] - "" - "* -{ -#ifdef MOTOROLA - return \"ext%.l %0\;divs%.w %2,%0\"; -#else - return \"extl %0\;divs %2,%0\"; -#endif -}") - -(define_insn "divhisi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (truncate:HI - (div:SI - (match_operand:SI 1 "general_operand" "0") - (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "dm")))))] - "" - "* -{ -#ifdef MOTOROLA - return \"divs%.w %2,%0\"; -#else - return \"divs %2,%0\"; -#endif -}") - -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=d") - (truncate:HI (div:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "const_int_operand" "n"))))] - "" - "* -{ -#ifdef MOTOROLA - return \"divs%.w %2,%0\"; -#else - return \"divs %2,%0\"; -#endif -}") - -(define_insn "udivhi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (udiv:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:HI 2 "general_operand" "dmn")))] - "" - "* -{ -#ifdef MOTOROLA - return \"and%.l %#0xFFFF,%0\;divu%.w %2,%0\"; -#else - return \"andl %#0xFFFF,%0\;divu %2,%0\"; -#endif -}") - -(define_insn "udivhisi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (truncate:HI - (udiv:SI - (match_operand:SI 1 "general_operand" "0") - (zero_extend:SI (match_operand:HI 2 "nonimmediate_operand" "dm")))))] - "" - "* -{ -#ifdef MOTOROLA - return \"divu%.w %2,%0\"; -#else - return \"divu %2,%0\"; -#endif -}") - -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=d") - (truncate:HI (udiv:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "const_int_operand" "n"))))] - "" - "* -{ -#ifdef MOTOROLA - return \"divu%.w %2,%0\"; -#else - return \"divu %2,%0\"; -#endif -}") - (define_expand "divdf3" [(set (match_operand:DF 0 "general_operand" "") (div:DF (match_operand:DF 1 "general_operand" "") @@ -2815,6 +3278,27 @@ (define_insn "" [(set (match_operand:DF 0 "general_operand" "=f") (div:DF (match_operand:DF 1 "general_operand" "0") + (float:DF (match_operand:SI 2 "general_operand" "dmi"))))] + "TARGET_68881" + "f%&div%.l %2,%0") + +(define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (div:DF (match_operand:DF 1 "general_operand" "0") + (float:DF (match_operand:HI 2 "general_operand" "dmn"))))] + "TARGET_68881" + "f%&div%.w %2,%0") + +(define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (div:DF (match_operand:DF 1 "general_operand" "0") + (float:DF (match_operand:QI 2 "general_operand" "dmn"))))] + "TARGET_68881" + "f%&div%.b %2,%0") + +(define_insn "" + [(set (match_operand:DF 0 "general_operand" "=f") + (div:DF (match_operand:DF 1 "general_operand" "0") (match_operand:DF 2 "general_operand" "fmG")))] "TARGET_68881" "* @@ -2850,127 +3334,63 @@ (define_insn "" [(set (match_operand:SF 0 "general_operand" "=f") (div:SF (match_operand:SF 1 "general_operand" "0") - (match_operand:SF 2 "general_operand" "fdmF")))] + (float:SF (match_operand:SI 2 "general_operand" "dmi"))))] "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\"); -}") - -;; Remainder instructions. - -(define_insn "modhi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (mod:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:HI 2 "general_operand" "dmn")))] - "" - "* -{ - /* The swap insn produces cc's that don't correspond to the result. */ - CC_STATUS_INIT; -#ifdef MOTOROLA - return \"ext%.l %0\;divs%.w %2,%0\;swap %0\"; -#else - return \"extl %0\;divs %2,%0\;swap %0\"; -#endif -}") - -(define_insn "modhisi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (truncate:HI - (mod:SI - (match_operand:SI 1 "general_operand" "0") - (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "dm")))))] - "" - "* -{ - /* The swap insn produces cc's that don't correspond to the result. */ - CC_STATUS_INIT; -#ifdef MOTOROLA - return \"divs%.w %2,%0\;swap %0\"; -#else - return \"divs %2,%0\;swap %0\"; -#endif + ? \"fsdiv%.l %2,%0\" + : \"fsgldiv%.l %2,%0\"); }") (define_insn "" - [(set (match_operand:HI 0 "general_operand" "=d") - (truncate:HI (mod:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "const_int_operand" "n"))))] - "" - "* -{ - /* The swap insn produces cc's that don't correspond to the result. */ - CC_STATUS_INIT; -#ifdef MOTOROLA - return \"divs%.w %2,%0\;swap %0\"; -#else - return \"divs %2,%0\;swap %0\"; -#endif -}") - -(define_insn "umodhi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (umod:HI (match_operand:HI 1 "general_operand" "0") - (match_operand:HI 2 "general_operand" "dmn")))] - "" + [(set (match_operand:SF 0 "general_operand" "=f") + (div:SF (match_operand:SF 1 "general_operand" "0") + (float:SF (match_operand:HI 2 "general_operand" "dmn"))))] + "TARGET_68881" "* { - /* The swap insn produces cc's that don't correspond to the result. */ - CC_STATUS_INIT; -#ifdef MOTOROLA - return \"and%.l %#0xFFFF,%0\;divu%.w %2,%0\;swap %0\"; -#else - return \"andl %#0xFFFF,%0\;divu %2,%0\;swap %0\"; -#endif + return (TARGET_68040_ONLY + ? \"fsdiv%.w %2,%0\" + : \"fsgldiv%.w %2,%0\"); }") -(define_insn "umodhisi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (truncate:HI - (umod:SI - (match_operand:SI 1 "general_operand" "0") - (zero_extend:SI (match_operand:HI 2 "nonimmediate_operand" "dm")))))] - "" +(define_insn "" + [(set (match_operand:SF 0 "general_operand" "=f") + (div:SF (match_operand:SF 1 "general_operand" "0") + (float:SF (match_operand:QI 2 "general_operand" "dmn"))))] + "TARGET_68881" "* { - /* The swap insn produces cc's that don't correspond to the result. */ - CC_STATUS_INIT; -#ifdef MOTOROLA - return \"divu%.w %2,%0\;swap %0\"; -#else - return \"divu %2,%0\;swap %0\"; -#endif + return (TARGET_68040_ONLY + ? \"fsdiv%.b %2,%0\" + : \"fsgldiv%.b %2,%0\"); }") (define_insn "" - [(set (match_operand:HI 0 "general_operand" "=d") - (truncate:HI (umod:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "const_int_operand" "n"))))] - "" + [(set (match_operand:SF 0 "general_operand" "=f") + (div:SF (match_operand:SF 1 "general_operand" "0") + (match_operand:SF 2 "general_operand" "fdmF")))] + "TARGET_68881" "* { - /* The swap insn produces cc's that don't correspond to the result. */ - CC_STATUS_INIT; -#ifdef MOTOROLA - return \"divu%.w %2,%0\;swap %0\"; +#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 - return \"divu %2,%0\;swap %0\"; + 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\"); }") + +;; Remainder instructions. (define_insn "divmodsi4" [(set (match_operand:SI 0 "general_operand" "=d") @@ -3001,6 +3421,52 @@ else return \"divul%.l %2,%3:%0\"; }") + +(define_insn "divmodhi4" + [(set (match_operand:HI 0 "general_operand" "=d") + (div:HI (match_operand:HI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dmsK"))) + (set (match_operand:HI 3 "general_operand" "=d") + (mod:HI (match_dup 1) (match_dup 2)))] + "" + "* +{ +#ifdef MOTOROLA + output_asm_insn(\"ext%.l %0\;divs%.w %2,%0\", operands); +#else + output_asm_insn(\"extl %0\;divs %2,%0\", operands); +#endif + if (!find_reg_note(insn, REG_UNUSED, operands[3])) + { + CC_STATUS_INIT; + return \"move%.l %0,%3\;swap %3\"; + } + else + return \"\"; +}") + +(define_insn "udivmodhi4" + [(set (match_operand:HI 0 "general_operand" "=d") + (udiv:HI (match_operand:HI 1 "general_operand" "0") + (match_operand:HI 2 "general_operand" "dmsK"))) + (set (match_operand:HI 3 "general_operand" "=d") + (umod:HI (match_dup 1) (match_dup 2)))] + "" + "* +{ +#ifdef MOTOROLA + output_asm_insn(\"and%.l %#0xFFFF,%0\;divu%.w %2,%0\", operands); +#else + output_asm_insn(\"and%.l %#0xFFFF,%0\;divu %2,%0\", operands); +#endif + if (!find_reg_note(insn, REG_UNUSED, operands[3])) + { + CC_STATUS_INIT; + return \"move%.l %0,%3\;swap %3\"; + } + else + return \"\"; +}") ;; logical-and instructions @@ -3041,7 +3507,8 @@ } else { - operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8)); operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8); + operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8)); + operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8); } /* This does not set condition codes in a standard way. */ CC_STATUS_INIT; @@ -3174,6 +3641,25 @@ (match_dup 0)))] "" "or%.b %1,%0") + +(define_insn "" + [(set (match_operand:SI 0 "general_operand" "=o,d") + (ior:SI (zero_extend:SI (match_operand 1 "general_operand" "dn,dmn")) + (match_operand:SI 2 "general_operand" "0,0")))] + "" + "* +{ + int byte_mode; + + CC_STATUS_INIT; + byte_mode = (GET_MODE(operands[1]) == QImode); + if (GET_CODE (operands[0]) == MEM) + operands[0] = adj_offsettable_operand (operands[0], byte_mode ? 3 : 2); + if (byte_mode) + return \"or%.b %1,%0\"; + else + return \"or%.w %1,%0\"; +}") ;; xor instructions @@ -3242,6 +3728,24 @@ ;; negation instructions +(define_insn "negdi2" + [(set (match_operand:DI 0 "general_operand" "=d*ao,<") + (neg:DI (match_operand:DI 1 "general_operand" "0,0")))] + "" + "* +{ + if (which_alternative == 1) + return \"neg%.l %0\;negx%.l %0\"; + if (GET_CODE (operands[0]) == REG) + operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + else + operands[1] = adj_offsettable_operand (operands[0], 4); + if (ADDRESS_REG_P (operands[0])) + return \"exg %/d0,%1\;neg%.l %/d0\;exg %/d0,%1\;exg %/d0,%0\;negx%.l %/d0\;exg %/d0,%0\"; + else + return \"neg%.l %1\;negx%.l %0\"; +} ") + (define_insn "negsi2" [(set (match_operand:SI 0 "general_operand" "=dm") (neg:SI (match_operand:SI 1 "general_operand" "0")))] @@ -3272,11 +3776,34 @@ "" "neg%.b %0") +;; If using software floating point, just flip the sign bit. + (define_expand "negsf2" [(set (match_operand:SF 0 "general_operand" "") (neg:SF (match_operand:SF 1 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") + "" + " +{ + if (!TARGET_FPA && !TARGET_68881) + { + rtx result; + rtx target; + + target = operand_subword_force (operands[0], 0, SFmode); + result = expand_binop (SImode, xor_optab, + operand_subword_force (operands[1], 0, SFmode), + GEN_INT(0x80000000), target, 0, OPTAB_WIDEN); + if (result == 0) + abort (); + + if (result != target) + emit_move_insn (result, target); + + /* Make a place for REG_EQUAL. */ + emit_move_insn (operands[0], operands[0]); + DONE; + } +}") (define_insn "" [(set (match_operand:SF 0 "general_operand" "=x,y") @@ -3303,8 +3830,36 @@ (define_expand "negdf2" [(set (match_operand:DF 0 "general_operand" "") (neg:DF (match_operand:DF 1 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") + "" + " +{ + if (!TARGET_FPA && !TARGET_68881) + { + rtx result; + rtx target; + rtx insns; + + start_sequence (); + target = operand_subword (operands[0], 0, 1, DFmode); + result = expand_binop (SImode, xor_optab, + operand_subword_force (operands[1], 0, DFmode), + GEN_INT(0x80000000), target, 0, OPTAB_WIDEN); + if (result == 0) + abort (); + + if (result != target) + emit_move_insn (result, target); + + emit_move_insn (operand_subword (operands[0], 1, 1, DFmode), + operand_subword_force (operands[1], 1, DFmode)); + + insns = get_insns (); + end_sequence (); + + emit_no_conflict_block (insns, operands[0], operands[1], 0, 0); + DONE; + } +}") (define_insn "" [(set (match_operand:DF 0 "general_operand" "=x,y") @@ -3330,6 +3885,18 @@ ;; Sqrt instruction for the 68881 +(define_insn "sqrtsf2" + [(set (match_operand:SF 0 "general_operand" "=f") + (sqrt:SF (match_operand:SF 1 "general_operand" "fm")))] + "TARGET_68881" + "* +{ + if (FP_REG_P (operands[1])) + return \"f%$sqrt%.x %1,%0\"; + else + return \"f%$sqrt%.s %1,%0\"; +}") + (define_insn "sqrtdf2" [(set (match_operand:DF 0 "general_operand" "=f") (sqrt:DF (match_operand:DF 1 "general_operand" "fm")))] @@ -3337,18 +3904,40 @@ "* { if (FP_REG_P (operands[1])) - return \"fsqrt%.x %1,%0\"; + return \"f%&sqrt%.x %1,%0\"; else - return \"fsqrt%.d %1,%0\"; + return \"f%&sqrt%.d %1,%0\"; }") ;; Absolute value instructions +;; If using software floating point, just zero the sign bit. (define_expand "abssf2" [(set (match_operand:SF 0 "general_operand" "") (abs:SF (match_operand:SF 1 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") + "" + " +{ + if (!TARGET_FPA && !TARGET_68881) + { + rtx result; + rtx target; + + target = operand_subword_force (operands[0], 0, SFmode); + result = expand_binop (SImode, and_optab, + operand_subword_force (operands[1], 0, SFmode), + GEN_INT(0x7fffffff), target, 0, OPTAB_WIDEN); + if (result == 0) + abort (); + + if (result != target) + emit_move_insn (result, target); + + /* Make a place for REG_EQUAL. */ + emit_move_insn (operands[0], operands[0]); + DONE; + } +}") (define_insn "" [(set (match_operand:SF 0 "general_operand" "=x,y") @@ -3370,8 +3959,36 @@ (define_expand "absdf2" [(set (match_operand:DF 0 "general_operand" "") (abs:DF (match_operand:DF 1 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") + "" + " +{ + if (!TARGET_FPA && !TARGET_68881) + { + rtx result; + rtx target; + rtx insns; + + start_sequence (); + target = operand_subword (operands[0], 0, 1, DFmode); + result = expand_binop (SImode, and_optab, + operand_subword_force (operands[1], 0, DFmode), + GEN_INT(0x7fffffff), target, 0, OPTAB_WIDEN); + if (result == 0) + abort (); + + if (result != target) + emit_move_insn (result, target); + + emit_move_insn (operand_subword (operands[0], 1, 1, DFmode), + operand_subword_force (operands[1], 1, DFmode)); + + insns = get_insns (); + end_sequence (); + + emit_no_conflict_block (insns, operands[0], operands[1], 0, 0); + DONE; + } +}") (define_insn "" [(set (match_operand:DF 0 "general_operand" "=x,y") @@ -3392,6 +4009,24 @@ ;; one complement instructions +;; "one_cmpldi2" is only here to help combine(). +(define_insn "one_cmpldi2" + [(set (match_operand:DI 0 "general_operand" "=dm") + (not:DI (match_operand:DI 1 "general_operand" "0")))] + "" + "* +{ + CC_STATUS_INIT; + if (GET_CODE (operands[0]) == REG) + operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC + || GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) + operands[1] = operands[0]; + else + operands[1] = adj_offsettable_operand (operands[0], 4); + return \"not%.l %1\;not%.l %0\"; +}") + (define_insn "one_cmplsi2" [(set (match_operand:SI 0 "general_operand" "=dm") (not:SI (match_operand:SI 1 "general_operand" "0")))] @@ -3425,13 +4060,111 @@ ;; arithmetic shift instructions ;; We don't need the shift memory by 1 bit instruction +(define_insn "ashldi_extsi" + [(set (match_operand:DI 0 "general_operand" "=ro") + (ashift:DI + (match_operator:DI 2 "extend_operator" + [(match_operand:SI 1 "general_operand" "rm")]) + (const_int 32)))] + "" + "* +{ + CC_STATUS_INIT; + if (GET_CODE (operands[0]) == REG) + operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + else + operands[2] = adj_offsettable_operand (operands[0], 4); + if (ADDRESS_REG_P (operands[0])) + return \"move%.l %1,%0\;sub%.l %2,%2\"; + else + return \"move%.l %1,%0\;clr%.l %2\"; +} ") + +(define_insn "ashldi_sexthi" + [(set (match_operand:DI 0 "register_operand" "=*da") + (ashift:DI (sign_extend:DI (match_operand:HI 1 "general_operand" "rm")) + (const_int 32)))] + "" + "* +{ + CC_STATUS_INIT; + operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + if (DATA_REG_P (operands[0])) + return \"move%.w %1,%0\;ext%.l %0\;clr%.l %2\"; + else + return \"move%.w %1,%0\;sub%.l %2,%2\"; +} ") + +(define_insn "ashldi_const32" + [(set (match_operand:DI 0 "general_operand" "=ro,<,>") + (ashift:DI (match_operand:DI 1 "general_operand" "ro,ro,ro") + (const_int 32)))] + "" + "* +{ + CC_STATUS_INIT; + if (GET_CODE (operands[1]) == REG) + operands[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); + else + operands[3] = adj_offsettable_operand (operands[1], 4); + if (which_alternative == 1) + return \"clr%.l %0\;move%.l %3,%0\"; + if (which_alternative == 2) + return \"move%.l %3,%0\;clr%.l %0\"; + if (GET_CODE (operands[0]) == REG) + operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + else + operands[2] = adj_offsettable_operand (operands[0], 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\"; +} ") + +;; The predicate below must be general_operand, because ashldi3 allows that +(define_insn "ashldi_const" + [(set (match_operand:DI 0 "general_operand" "=d") + (ashift:DI (match_operand:DI 1 "general_operand" "0") + (match_operand 2 "const_int_operand" "n")))] + "(INTVAL (operands[2]) == 1 + || INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16 + || INTVAL (operands[2]) == 2 || INTVAL (operands[2]) == 3)" + "* +{ + 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]) == 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\"; +} ") + +(define_expand "ashldi3" + [(set (match_operand:DI 0 "general_operand" "") + (ashift:DI (match_operand:DI 1 "general_operand" "") + (match_operand 2 "const_int_operand" "")))] + "" + " +{ + if (GET_CODE (operands[2]) != CONST_INT + || (INTVAL (operands[2]) != 1 && INTVAL (operands[2]) != 32 + && INTVAL (operands[2]) != 8 && INTVAL (operands[2]) != 16 + && INTVAL (operands[2]) != 2 && INTVAL (operands[2]) != 3)) + FAIL; +} ") + ;; 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)" + (const_int 16)))] + "" "* { CC_STATUS_INIT; @@ -3443,8 +4176,8 @@ (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")))] - "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT + (match_operand:SI 2 "const_int_operand" "n")))] + "(! TARGET_68020 && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)" "* { @@ -3499,8 +4232,8 @@ (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)" + (const_int 16)))] + "" "swap %0\;ext%.l %0") ;; On the 68000, this makes faster code in a special case. @@ -3508,8 +4241,8 @@ (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")))] - "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT + (match_operand:SI 2 "const_int_operand" "n")))] + "(! TARGET_68020 && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)" "* { @@ -3517,15 +4250,109 @@ return \"swap %0\;asr%.w %2,%0\;ext%.l %0\"; }") +(define_insn "subreghi1ashrdi_const32" + [(set (match_operand:HI 0 "general_operand" "=rm") + (subreg:HI (ashiftrt:DI (match_operand:DI 1 "general_operand" "ro") + (const_int 32)) 1))] + "" + "* +{ + if (GET_CODE (operands[1]) != REG) + operands[1] = adj_offsettable_operand (operands[1], 2); + return \"move%.w %1,%0\"; +} ") + +(define_insn "subregsi1ashrdi_const32" + [(set (match_operand:SI 0 "general_operand" "=rm") + (subreg:SI (ashiftrt:DI (match_operand:DI 1 "general_operand" "ro") + (const_int 32)) 1))] + "" + "* +{ + return \"move%.l %1,%0\"; +} ") + +(define_insn "ashrdi_const32" + [(set (match_operand:DI 0 "register_operand" "=d") + (ashiftrt:DI (match_operand:DI 1 "general_operand" "ro") + (const_int 32)))] + "" + "* +{ + CC_STATUS_INIT; + 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\"; +} ") + +(define_insn "ashrdi_const32_mem" + [(set (match_operand:DI 0 "general_operand" "=o,<") + (ashiftrt:DI (match_operand:DI 1 "general_operand" "ro,ro") + (const_int 32))) + (clobber (match_scratch:SI 2 "=d,d"))] + "" + "* +{ + CC_STATUS_INIT; + if (which_alternative == 1) + operands[3] = operands[0]; + else + operands[3] = adj_offsettable_operand (operands[0], 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\"; +} ") + +;; The predicate below must be general_operand, because ashrdi3 allows that +(define_insn "ashrdi_const" + [(set (match_operand:DI 0 "general_operand" "=d") + (ashiftrt:DI (match_operand:DI 1 "general_operand" "0") + (match_operand 2 "const_int_operand" "n")))] + "(INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == 2 + || INTVAL (operands[2]) == 3 || INTVAL (operands[2]) == 8 + || INTVAL (operands[2]) == 16 || 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\;clr%.w %0\;swap %1\;ext%.l %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\"; +} ") + +(define_expand "ashrdi3" + [(set (match_operand:DI 0 "general_operand" "") + (ashiftrt:DI (match_operand:DI 1 "general_operand" "") + (match_operand 2 "const_int_operand" "")))] + "" + " +{ + if (GET_CODE (operands[2]) != CONST_INT + || (INTVAL (operands[2]) != 1 && INTVAL (operands[2]) != 2 + && INTVAL (operands[2]) != 3 && INTVAL (operands[2]) != 8 + && INTVAL (operands[2]) != 16 && INTVAL (operands[2]) != 32 + && INTVAL (operands[2]) != 63)) + FAIL; +} ") + (define_insn "ashrsi3" [(set (match_operand:SI 0 "register_operand" "=d") (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "general_operand" "dI")))] "" - "* -{ - return \"asr%.l %2,%0\"; -}") + "asr%.l %2,%0") (define_insn "ashrhi3" [(set (match_operand:HI 0 "register_operand" "=d") @@ -3557,82 +4384,133 @@ ;; logical shift instructions -;; On all 68k models, this makes faster code in a special case. +;; commented out because of reload problems in 950612-1.c +;;(define_insn "" +;; [(set (cc0) +;; (subreg:SI (lshiftrt:DI (match_operand:DI 0 "general_operand" "ro") +;; (const_int 32)) 1)) +;; (set (match_operand:SI 1 "general_operand" "=dm") +;; (subreg:SI (lshiftrt:DI (match_dup 0) +;; (const_int 32)) 1))] +;; "" +;; "* +;;{ +;; return \"move%.l %0,%1\"; +;;} ") +;; +;;(define_insn "" +;; [(set (cc0) +;; (subreg:SI (lshiftrt:DI (match_operand:DI 0 "general_operand" "ro") +;; (const_int 32)) 0)) +;; (set (match_operand:DI 1 "general_operand" "=do") +;; (lshiftrt:DI (match_dup 0) +;; (const_int 32)))] +;; "" +;; "* +;;{ +;; if (GET_CODE (operands[1]) == REG) +;; operands[2] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); +;; else +;; operands[2] = adj_offsettable_operand (operands[1], 4); +;; return \"move%.l %0,%2\;clr%.l %1\"; +;;} ") -(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)" +(define_insn "subreg1lshrdi_const32" + [(set (match_operand:SI 0 "general_operand" "=rm") + (subreg:SI (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro") + (const_int 32)) 1))] + "" "* { - CC_STATUS_INIT; - return \"swap %0\;clr%.w %0\"; -}") - -;; On the 68000, this makes faster code in a special case. + return \"move%.l %1,%0\"; +} ") -(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")))] - "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)" +(define_insn "lshrdi_const32" + [(set (match_operand:DI 0 "general_operand" "=ro,<,>") + (lshiftrt:DI (match_operand:DI 1 "general_operand" "ro,ro,ro") + (const_int 32)))] + "" "* { 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] = adj_offsettable_operand (operands[0], 4); + if (GET_CODE (operands[1]) == REG) + operands[3] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); + else + operands[3] = adj_offsettable_operand (operands[1], 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_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16); - return \"lsl%.w %2,%0\;swap %0\;clr%.w %0\"; -}") +;; The predicate below must be general_operand, because lshrdi3 allows that +(define_insn "lshrdi_const" + [(set (match_operand:DI 0 "general_operand" "=d") + (lshiftrt:DI (match_operand:DI 1 "general_operand" "0") + (match_operand 2 "const_int_operand" "n")))] + "(INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == 2 + || INTVAL (operands[2]) == 3 || INTVAL (operands[2]) == 8 + || INTVAL (operands[2]) == 16 || 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]) == 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\"; +} ") + +(define_expand "lshrdi3" + [(set (match_operand:DI 0 "general_operand" "") + (lshiftrt:DI (match_operand:DI 1 "general_operand" "") + (match_operand 2 "const_int_operand" "")))] + "" + " +{ + if (GET_CODE (operands[2]) != CONST_INT + || (INTVAL (operands[2]) != 1 && INTVAL (operands[2]) != 2 + && INTVAL (operands[2]) != 3 && INTVAL (operands[2]) != 8 + && INTVAL (operands[2]) != 16 && INTVAL (operands[2]) != 32 + && INTVAL (operands[2]) != 63)) + FAIL; +} ") -(define_insn "lshlsi3" +;; On all 68k models, this makes faster code in a special case. + +(define_insn "lshrsi_31" [(set (match_operand:SI 0 "register_operand" "=d") - (lshift:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "dI")))] + (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") + (const_int 31)))] "" "* { - if (operands[2] == const1_rtx) - return \"add%.l %0,%0\"; - return \"lsl%.l %2,%0\"; + return \"add%.l %0,%0\;subx%.l %0,%0\;neg%.l %0\"; }") -(define_insn "lshlhi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (lshift:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "general_operand" "dI")))] - "" - "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") - (match_operand:QI 2 "general_operand" "dI")))] - "" - "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 "" +(define_insn "lshrsi_16" [(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)" + (const_int 16)))] + "" "* { CC_STATUS_INIT; @@ -3641,11 +4519,11 @@ ;; On the 68000, this makes faster code in a special case. -(define_insn "" +(define_insn "lshrsi_17_24" [(set (match_operand:SI 0 "register_operand" "=d") (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "immediate_operand" "i")))] - "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT + (match_operand:SI 2 "const_int_operand" "n")))] + "(! TARGET_68020 && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)" "* { @@ -3659,10 +4537,7 @@ (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "general_operand" "dI")))] "" - "* -{ - return \"lsr%.l %2,%0\"; -}") + "lsr%.l %2,%0") (define_insn "lshrhi3" [(set (match_operand:HI 0 "register_operand" "=d") @@ -3765,6 +4640,65 @@ "" "ror%.b %1,%0") + +;; Bit set/clear in memory byte. + +;; set bit, bit number is int +(define_insn "bsetmemqi" + [(set (match_operand:QI 0 "memory_operand" "+m") + (ior:QI (subreg:QI (ashift:SI (const_int 1) + (match_operand:SI 1 "general_operand" "d")) 0) + (match_dup 0)))] + "" + "* +{ + CC_STATUS_INIT; + return \"bset %1,%0\"; +}") + +;; set bit, bit number is (sign/zero)_extended from HImode/QImode +(define_insn "" + [(set (match_operand:QI 0 "memory_operand" "+m") + (ior:QI (subreg:QI (ashift:SI (const_int 1) + (match_operator:SI 2 "extend_operator" + [(match_operand 1 "general_operand" "d")])) 0) + (match_dup 0)))] + "" + "* +{ + CC_STATUS_INIT; + return \"bset %1,%0\"; +}") + +;; clear bit, bit number is int +(define_insn "bclrmemqi" + [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+m") + (const_int 1) + (minus:SI (const_int 7) + (match_operand:SI 1 "general_operand" "d"))) + (const_int 0))] + "" + "* +{ + CC_STATUS_INIT; + return \"bclr %1,%0\"; +}") + +;; clear bit, bit number is (sign/zero)_extended from HImode/QImode +(define_insn "" + [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+m") + (const_int 1) + (minus:SI (const_int 7) + (match_operator:SI 2 "extend_operator" + [(match_operand 1 "general_operand" "d")]))) + (const_int 0))] + "" + "* +{ + CC_STATUS_INIT; + return \"bclr %1,%0\"; +}") + ;; Special cases of bit-field insns which we should ;; recognize in preference to the general case. ;; These handle aligned 8-bit and 16-bit fields, @@ -3779,13 +4713,10 @@ ; (define_insn "" [(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")) + (const_int 32) + (match_operand:SI 2 "const_int_operand" "n")) (match_operand:SI 3 "general_operand" "rmi"))] "TARGET_68020 && TARGET_BITFIELD - && GET_CODE (operands[1]) == CONST_INT - && (INTVAL (operands[1]) == 32) - && GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) % 8) == 0 && ! mode_dependent_address_p (XEXP (operands[0], 0))" "* @@ -3798,13 +4729,11 @@ (define_insn "" [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+do") - (match_operand:SI 1 "immediate_operand" "i") - (match_operand:SI 2 "immediate_operand" "i")) - (match_operand:SI 3 "general_operand" "d"))] + (match_operand:SI 1 "const_int_operand" "n") + (match_operand:SI 2 "const_int_operand" "n")) + (match_operand:SI 3 "register_operand" "d"))] "TARGET_68020 && TARGET_BITFIELD - && GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16) - && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) % INTVAL (operands[1]) == 0 && (GET_CODE (operands[0]) == REG || ! mode_dependent_address_p (XEXP (operands[0], 0)))" @@ -3838,12 +4767,9 @@ (define_insn "" [(set (match_operand:SI 0 "general_operand" "=rm") (zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o") - (match_operand:SI 2 "immediate_operand" "i") - (match_operand:SI 3 "immediate_operand" "i")))] + (const_int 32) + (match_operand:SI 3 "const_int_operand" "n")))] "TARGET_68020 && TARGET_BITFIELD - && GET_CODE (operands[2]) == CONST_INT - && (INTVAL (operands[2]) == 32) - && GET_CODE (operands[3]) == CONST_INT && (INTVAL (operands[3]) % 8) == 0 && ! mode_dependent_address_p (XEXP (operands[1], 0))" "* @@ -3857,12 +4783,10 @@ (define_insn "" [(set (match_operand:SI 0 "general_operand" "=&d") (zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do") - (match_operand:SI 2 "immediate_operand" "i") - (match_operand:SI 3 "immediate_operand" "i")))] + (match_operand:SI 2 "const_int_operand" "n") + (match_operand:SI 3 "const_int_operand" "n")))] "TARGET_68020 && TARGET_BITFIELD - && GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) % INTVAL (operands[2]) == 0 && (GET_CODE (operands[1]) == REG || ! mode_dependent_address_p (XEXP (operands[1], 0)))" @@ -3897,12 +4821,9 @@ (define_insn "" [(set (match_operand:SI 0 "general_operand" "=rm") (sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o") - (match_operand:SI 2 "immediate_operand" "i") - (match_operand:SI 3 "immediate_operand" "i")))] + (const_int 32) + (match_operand:SI 3 "const_int_operand" "n")))] "TARGET_68020 && TARGET_BITFIELD - && GET_CODE (operands[2]) == CONST_INT - && (INTVAL (operands[2]) == 32) - && GET_CODE (operands[3]) == CONST_INT && (INTVAL (operands[3]) % 8) == 0 && ! mode_dependent_address_p (XEXP (operands[1], 0))" "* @@ -3916,12 +4837,10 @@ (define_insn "" [(set (match_operand:SI 0 "general_operand" "=d") (sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do") - (match_operand:SI 2 "immediate_operand" "i") - (match_operand:SI 3 "immediate_operand" "i")))] + (match_operand:SI 2 "const_int_operand" "n") + (match_operand:SI 3 "const_int_operand" "n")))] "TARGET_68020 && TARGET_BITFIELD - && GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) % INTVAL (operands[2]) == 0 && (GET_CODE (operands[1]) == REG || ! mode_dependent_address_p (XEXP (operands[1], 0)))" @@ -3961,7 +4880,15 @@ "TARGET_68020 && TARGET_BITFIELD" "* { - cc_status.flags |= CC_NOT_NEGATIVE; + if (GET_CODE (operands[2]) == CONST_INT) + { + if (INTVAL (operands[2]) != 32) + cc_status.flags |= CC_NOT_NEGATIVE; + } + else + { + CC_STATUS_INIT; + } return \"bfextu %1{%b3:%b2},%0\"; }") @@ -3970,9 +4897,8 @@ (match_operand:SI 1 "general_operand" "di,di") (match_operand:SI 2 "general_operand" "di,di")) (xor:SI (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2)) - (match_operand 3 "immediate_operand" "i,i")))] + (match_operand 3 "const_int_operand" "n,n")))] "TARGET_68020 && TARGET_BITFIELD - && GET_CODE (operands[3]) == CONST_INT && (INTVAL (operands[3]) == -1 || (GET_CODE (operands[1]) == CONST_INT && (~ INTVAL (operands[3]) & ((1 << INTVAL (operands[1]))- 1)) == 0))" @@ -4010,7 +4936,7 @@ [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d") (match_operand:SI 1 "general_operand" "di,di") (match_operand:SI 2 "general_operand" "di,di")) - (match_operand:SI 3 "general_operand" "d,d"))] + (match_operand:SI 3 "register_operand" "d,d"))] "TARGET_68020 && TARGET_BITFIELD" "bfins %3,%0{%b2:%b1}") @@ -4033,7 +4959,15 @@ "TARGET_68020 && TARGET_BITFIELD" "* { - cc_status.flags |= CC_NOT_NEGATIVE; + if (GET_CODE (operands[2]) == CONST_INT) + { + if (INTVAL (operands[2]) != 32) + cc_status.flags |= CC_NOT_NEGATIVE; + } + else + { + CC_STATUS_INIT; + } return \"bfextu %1{%b3:%b2},%0\"; }") @@ -4065,7 +4999,7 @@ [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d") (match_operand:SI 1 "general_operand" "di") (match_operand:SI 2 "general_operand" "di")) - (match_operand:SI 3 "general_operand" "d"))] + (match_operand:SI 3 "register_operand" "d"))] "TARGET_68020 && TARGET_BITFIELD" "* { @@ -4086,10 +5020,9 @@ (define_insn "" [(set (cc0) (zero_extract:SI (match_operand:QI 0 "memory_operand" "o") - (match_operand:SI 1 "general_operand" "di") + (match_operand:SI 1 "const_int_operand" "n") (match_operand:SI 2 "general_operand" "di")))] - "TARGET_68020 && TARGET_BITFIELD - && GET_CODE (operands[1]) == CONST_INT" + "TARGET_68020 && TARGET_BITFIELD" "* { if (operands[1] == const1_rtx @@ -4115,10 +5048,9 @@ (define_insn "" [(set (cc0) (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "d") - (match_operand:SI 1 "general_operand" "di") + (match_operand:SI 1 "const_int_operand" "n") (match_operand:SI 2 "general_operand" "di")))] - "TARGET_68020 && TARGET_BITFIELD - && GET_CODE (operands[1]) == CONST_INT" + "TARGET_68020 && TARGET_BITFIELD" "* { if (operands[1] == const1_rtx @@ -4139,6 +5071,27 @@ return \"bftst %0{%b2:%b1}\"; }") +(define_insn "scc0_di" + [(set (match_operand:QI 0 "general_operand" "=dm") + (match_operator 1 "valid_dbcc_comparison_p" + [(match_operand:DI 2 "general_operand" "ro") (const_int 0)]))] + "" + "* +{ + return output_scc_di (operands[1], operands[2], const0_rtx, operands[0]); +} ") + +(define_insn "scc_di" + [(set (match_operand:QI 0 "general_operand" "=dm,dm") + (match_operator 1 "valid_dbcc_comparison_p" + [(match_operand:DI 2 "general_operand" "ro,r") + (match_operand:DI 3 "general_operand" "r,ro")]))] + "" + "* +{ + return output_scc_di (operands[1], operands[2], operands[3], operands[0]); +} ") + (define_insn "seq" [(set (match_operand:QI 0 "general_operand" "=d") (eq:QI (cc0) (const_int 0)))] @@ -4219,6 +5172,147 @@ ;; Basic conditional jump instructions. +(define_insn "beq0_di" + [(set (pc) + (if_then_else (eq (match_operand:DI 0 "general_operand" "d*ao,<>") + (const_int 0)) + (label_ref (match_operand 1 "" ",")) + (pc))) + (clobber (match_scratch:SI 2 "=d,d"))] + "" + "* +{ + if (which_alternative == 1) +#ifdef MOTOROLA + return \"move%.l %0,%2\;or%.l %0,%2\;jbeq %l1\"; +#else + return \"move%.l %0,%2\;or%.l %0,%2\;jeq %l1\"; +#endif + if (GET_CODE (operands[0]) == REG) + operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + else + operands[3] = adj_offsettable_operand (operands[0], 4); + if (! ADDRESS_REG_P (operands[0])) +#ifdef MOTOROLA + return \"move%.l %0,%2\;or%.l %3,%2\;jbeq %l1\"; +#else + return \"move%.l %0,%2\;or%.l %3,%2\;jeq %l1\"; +#endif + operands[4] = gen_label_rtx(); + if (TARGET_68020) +#ifdef MOTOROLA + output_asm_insn (\"tst%.l %0\;jbne %l4\;tst%.l %3\;jbeq %l1\", operands); +#else + output_asm_insn (\"tst%.l %0\;jne %l4\;tst%.l %3\;jeq %l1\", operands); +#endif + else +#ifdef MOTOROLA +#ifdef SGS_CMP_ORDER + output_asm_insn (\"cmp%.w %0,%#0\;jbne %l4\;cmp%.w %3,%#0\;jbeq %l1\", operands); +#else + output_asm_insn (\"cmp%.w %#0,%0\;jbne %l4\;cmp%.w %#0,%3\;jbeq %l1\", operands); +#endif +#else + output_asm_insn (\"cmp%.w %#0,%0\;jne %l4\;cmp%.w %#0,%3\;jeq %l1\", operands); +#endif + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", + CODE_LABEL_NUMBER (operands[4])); + return \"\"; +} ") + +(define_insn "bne0_di" + [(set (pc) + (if_then_else (ne (match_operand:DI 0 "general_operand" "do,*a") + (const_int 0)) + (label_ref (match_operand 1 "" ",")) + (pc))) + (clobber (match_scratch:SI 2 "=d,X"))] + "" + "* +{ + CC_STATUS_INIT; + if (GET_CODE (operands[0]) == REG) + operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); + else + operands[3] = adj_offsettable_operand (operands[0], 4); + if (!ADDRESS_REG_P (operands[0])) +#ifdef MOTOROLA + return \"move%.l %0,%2\;or%.l %3,%2\;jbne %l1\"; +#else + return \"move%.l %0,%2\;or%.l %3,%2\;jne %l1\"; +#endif + if (TARGET_68020) +#ifdef MOTOROLA + return \"tst%.l %0\;jbne %l1\;tst%.l %3\;jbne %l1\"; +#else + return \"tst%.l %0\;jne %l1\;tst%.l %3\;jne %l1\"; +#endif + else +#ifdef MOTOROLA +#ifdef SGS_CMP_ORDER + return \"cmp%.w %0,%#0\;jbne %l1\;cmp%.w %3,%#0\;jbne %l1\"; +#else + return \"cmp%.w %#0,%0\;jbne %l1\;cmp%.w %#0,%3\;jbne %l1\"; +#endif +#else + return \"cmp%.w %#0,%0\;jne %l1\;cmp%.w %#0,%3\;jne %l1\"; +#endif +} ") + +(define_insn "bge0_di" + [(set (pc) + (if_then_else (ge (match_operand:DI 0 "general_operand" "ro") + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc)))] + "" + "* +{ + CC_STATUS_INIT; + if (TARGET_68020 || ! ADDRESS_REG_P (operands[0])) + output_asm_insn(\"tst%.l %0\", operands); + else + /* On an address reg, cmpw may replace cmpl. */ +#ifdef SGS_CMP_ORDER + output_asm_insn(\"cmp%.w %0,%#0\", operands); +#else + output_asm_insn(\"cmp%.w %#0,%0\", operands); +#endif + +#ifdef MOTOROLA + return \"jbpl %l1\"; +#else + return \"jpl %l1\"; +#endif +} ") + +(define_insn "blt0_di" + [(set (pc) + (if_then_else (lt (match_operand:DI 0 "general_operand" "ro") + (const_int 0)) + (label_ref (match_operand 1 "" "")) + (pc)))] + "" + "* +{ + CC_STATUS_INIT; + if (TARGET_68020 || ! ADDRESS_REG_P (operands[0])) + output_asm_insn(\"tst%.l %0\", operands); + else + /* On an address reg, cmpw may replace cmpl. */ +#ifdef SGS_CMP_ORDER + output_asm_insn(\"cmp%.w %0,%#0\", operands); +#else + output_asm_insn(\"cmp%.w %#0,%0\", operands); +#endif + +#ifdef MOTOROLA + return \"jbmi %l1\"; +#else + return \"jmi %l1\"; +#endif +} ") + (define_insn "beq" [(set (pc) (if_then_else (eq (cc0) @@ -4548,7 +5642,8 @@ " { #ifdef CASE_VECTOR_PC_RELATIVE - operands[0] = gen_rtx (PLUS, SImode, pc_rtx, operands[0]); + operands[0] = gen_rtx (PLUS, SImode, pc_rtx, + gen_rtx (SIGN_EXTEND, SImode, operands[0])); #endif }") @@ -4568,7 +5663,8 @@ ;; Jump to variable address from dispatch table of relative addresses. (define_insn "" [(set (pc) - (plus:SI (pc) (match_operand:HI 0 "register_operand" "r"))) + (plus:SI (pc) + (sign_extend:SI (match_operand:HI 0 "register_operand" "r")))) (use (label_ref (match_operand 1 "" "")))] "" "* @@ -4599,7 +5695,7 @@ (define_insn "" [(set (pc) (if_then_else - (ne (match_operand:HI 0 "general_operand" "+g") + (ne (match_operand:HI 0 "general_operand" "+d*g") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) @@ -4642,7 +5738,7 @@ (define_insn "" [(set (pc) (if_then_else - (ne (match_operand:SI 0 "general_operand" "+g") + (ne (match_operand:SI 0 "general_operand" "+d*g") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) @@ -4688,7 +5784,7 @@ (define_insn "" [(set (pc) (if_then_else - (ge (plus:HI (match_operand:HI 0 "general_operand" "+g") + (ge (plus:HI (match_operand:HI 0 "general_operand" "+d*am") (const_int -1)) (const_int 0)) (label_ref (match_operand 1 "" "")) @@ -4733,7 +5829,7 @@ (define_insn "decrement_and_branch_until_zero" [(set (pc) (if_then_else - (ge (plus:SI (match_operand:SI 0 "general_operand" "+g") + (ge (plus:SI (match_operand:SI 0 "general_operand" "+d*am") (const_int -1)) (const_int 0)) (label_ref (match_operand 1 "" "")) @@ -4776,23 +5872,22 @@ }") +;; For PIC calls, in order to be able to support +;; dynamic linker LAZY BINDING, all the procedure calls need to go +;; through the PLT (Procedure Linkage Table) section in PIC mode. +;; ;; PIC calls are handled by loading the address of the function into a ;; register (via movsi), then emitting a register indirect call using ;; the "jsr" function call syntax. ;; -;; It is important to note that the "jsr" syntax is always used for -;; PIC calls, even on machines in which GCC normally uses the "jbsr" -;; syntax for non-PIC calls. This keeps at least 1 assembler (Sun) -;; from emitting incorrect code for a PIC call. +;; When outputting MIT syntax (e.g. on Suns), we add a bogus extra +;; operand to the jbsr statement to indicate that this call should +;; go through the PLT (why? because this is the way that Sun does it). ;; ;; We have different patterns for PIC calls and non-PIC calls. The -;; different patterns are only used to choose the right syntax -;; ("jsr" vs "jbsr"). +;; different patterns are only used to choose the right syntax. ;; -;; On svr4 m68k, PIC stuff is done differently. To be able to support -;; dynamic linker LAZY BINDING, all the procedure calls need to go -;; through the PLT (Procedure Linkage Table) section in PIC mode. The -;; svr4 m68k assembler recognizes this syntax: `bsr FUNC@PLTPC' and it +;; The svr4 m68k assembler recognizes this syntax: `bsr FUNC@PLTPC' and it ;; will create the correct relocation entry (R_68K_PLT32) for `FUNC', ;; that tells the linker editor to create an entry for `FUNC' in PLT ;; section at link time. However, all global objects reference are still @@ -4802,7 +5897,7 @@ ;; ;; The strategy I use here is to use SYMBOL_REF_FLAG to differentiate ;; these two different operands. The macro LEGITIMATE_PIC_OPERAND_P needs -;; to be changed to recognize function calls symbol_ref operand as a legal +;; to be changed to recognize function calls symbol_ref operand as a valid ;; PIC operand (by checking whether SYMBOL_REF_FLAG is set). This will ;; avoid the compiler to load this symbol_ref operand into a register. ;; Remember, the operand "foo@PLTPC" cannot be called via jsr directly @@ -4824,12 +5919,7 @@ " { if (flag_pic && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) -#ifdef MOTOROLA SYMBOL_REF_FLAG (XEXP (operands[0], 0)) = 1; -#else - operands[0] = gen_rtx (MEM, GET_MODE (operands[0]), - force_reg (Pmode, XEXP (operands[0], 0))); -#endif }") ;; This is a normal call sequence. @@ -4840,7 +5930,12 @@ "! flag_pic" "* -#ifdef MOTOROLA +#if defined (MOTOROLA) && !defined (USE_GAS) +#ifdef MOTOROLA_BSR + if (GET_CODE (operands[0]) == MEM + && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) + return \"bsr %0\"; +#endif return \"jsr %0\"; #else return \"jbsr %0\"; @@ -4855,11 +5950,23 @@ "flag_pic" "* -#ifdef MOTOROLA if (GET_CODE (operands[0]) == MEM && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) +#ifdef MOTOROLA +#ifdef HPUX_ASM + return \"bsr.l %0\"; +#else +#ifdef USE_GAS + return \"bsr.l %0@PLTPC\"; +#else return \"bsr %0@PLTPC\"; #endif +#endif +#else + /* The ',a1' is a dummy argument telling the Sun assembler we want PIC, + GAS just plain ignores it. */ + return \"jbsr %0,a1\"; +#endif return \"jsr %0\"; ") @@ -4875,12 +5982,7 @@ " { if (flag_pic && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) -#ifdef MOTOROLA SYMBOL_REF_FLAG (XEXP (operands[1], 0)) = 1; -#else - operands[1] = gen_rtx (MEM, GET_MODE (operands[1]), - force_reg (Pmode, XEXP (operands[1], 0))); -#endif }") ;; This is a normal call_value @@ -4891,7 +5993,12 @@ ;; Operand 2 not really used on the m68000. "! flag_pic" "* -#ifdef MOTOROLA +#if defined (MOTOROLA) && !defined (USE_GAS) +#ifdef MOTOROLA_BSR + if (GET_CODE (operands[1]) == MEM + && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) + return \"bsr %1\"; +#endif return \"jsr %1\"; #else return \"jbsr %1\"; @@ -4906,11 +6013,23 @@ ;; Operand 2 not really used on the m68000. "flag_pic" "* -#ifdef MOTOROLA if (GET_CODE (operands[1]) == MEM && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) +#ifdef MOTOROLA +#ifdef HPUX_ASM + return \"bsr.l %1\"; +#else +#ifdef USE_GAS + return \"bsr.l %1@PLTPC\"; +#else return \"bsr %1@PLTPC\"; #endif +#endif +#else + /* The ',a1' is a dummy argument telling the Sun assembler we want PIC + GAS just plain ignores it. */ + return \"jbsr %1,a1\"; +#endif return \"jsr %1\"; ") @@ -4989,7 +6108,41 @@ [(set (match_operand:SI 0 "general_operand" "=a") (match_operand:QI 1 "address_operand" "p"))] "" - "lea %a1,%0") + "* +{ +#ifndef SGS_NO_LI + /* Recognize an insn that refers to a table of offsets. Such an insn will + need to refer to a label on the insn. So output one. Use the + label-number of the table of offsets to generate this label. This code, + and similar code above, assumes that there will be at most one reference + to each table. */ + if (GET_CODE (operands[1]) == PLUS + && GET_CODE (XEXP (operands[1], 1)) == LABEL_REF + && GET_CODE (XEXP (operands[1], 0)) != PLUS) + { + rtx labelref = XEXP (operands[1], 1); +#if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES) +#ifdef SGS + asm_fprintf (asm_out_file, \"\\tset %LLI%d,.+2\\n\", + CODE_LABEL_NUMBER (XEXP (labelref, 0))); +#else /* not SGS */ + asm_fprintf (asm_out_file, \"\\t.set %LLI%d,.+2\\n\", + CODE_LABEL_NUMBER (XEXP (labelref, 0))); +#endif /* not SGS */ +#else /* SGS_SWITCH_TABLES or not MOTOROLA */ + ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"LI\", + CODE_LABEL_NUMBER (XEXP (labelref, 0))); +#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 */ + + return \"lea %a1,%0\"; +}") ;; This is the first machine-dependent peephole optimization. ;; It is useful when a floating value is returned from a function call @@ -5017,10 +6170,10 @@ (define_peephole [(set (reg:SI 15) (plus:SI (reg:SI 15) - (match_operand:SI 0 "immediate_operand" "n"))) + (match_operand:SI 0 "const_int_operand" "n"))) (set (match_operand:SF 1 "push_operand" "=m") (match_operand:SF 2 "general_operand" "rmfF"))] - "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) >= 4 + "INTVAL (operands[0]) >= 4 && ! reg_mentioned_p (stack_pointer_rtx, operands[2])" "* { @@ -5054,10 +6207,10 @@ (define_peephole [(set (reg:SI 15) (plus:SI (reg:SI 15) - (match_operand:SI 0 "immediate_operand" "n"))) + (match_operand:SI 0 "const_int_operand" "n"))) (set (match_operand:SI 1 "push_operand" "=m") (match_operand:SI 2 "general_operand" "g"))] - "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) >= 4 + "INTVAL (operands[0]) >= 4 && ! reg_mentioned_p (stack_pointer_rtx, operands[2])" "* { @@ -5345,24 +6498,10 @@ return \"ftst%.x %0\"; }") - -(define_expand "cmpxf" +(define_insn "cmpxf" [(set (cc0) - (compare (match_operand:XF 0 "general_operand" "f,mG") - (match_operand:XF 1 "general_operand" "fmG,f")))] - "TARGET_68881" - " -{ - if (CONSTANT_P (operands[0])) - operands[0] = force_const_mem (XFmode, operands[0]); - if (CONSTANT_P (operands[1])) - operands[1] = force_const_mem (XFmode, operands[1]); -}") - -(define_insn "" - [(set (cc0) - (compare (match_operand:XF 0 "nonimmediate_operand" "f,mG") - (match_operand:XF 1 "nonimmediate_operand" "fmG,f")))] + (compare (match_operand:XF 0 "nonimmediate_operand" "f,m") + (match_operand:XF 1 "nonimmediate_operand" "fm,f")))] "TARGET_68881" "* { @@ -5508,23 +6647,31 @@ "TARGET_68881" "fmove%.l %1,%0") -(define_expand "addxf3" - [(set (match_operand:XF 0 "general_operand" "") - (plus:XF (match_operand:XF 1 "general_operand" "") - (match_operand:XF 2 "general_operand" "")))] +(define_insn "" + [(set (match_operand:XF 0 "general_operand" "=f") + (plus:XF (float:XF (match_operand:SI 2 "general_operand" "dmi")) + (match_operand:XF 1 "nonimmediate_operand" "0")))] "TARGET_68881" - " -{ - if (CONSTANT_P (operands[1])) - operands[1] = force_const_mem (XFmode, operands[1]); - if (CONSTANT_P (operands[2])) - operands[2] = force_const_mem (XFmode, operands[2]); -}") + "fadd%.l %2,%0") + +(define_insn "" + [(set (match_operand:XF 0 "general_operand" "=f") + (plus:XF (float:XF (match_operand:HI 2 "general_operand" "dmn")) + (match_operand:XF 1 "nonimmediate_operand" "0")))] + "TARGET_68881" + "fadd%.w %2,%0") (define_insn "" [(set (match_operand:XF 0 "general_operand" "=f") + (plus:XF (float:XF (match_operand:QI 2 "general_operand" "dmn")) + (match_operand:XF 1 "general_operand" "0")))] + "TARGET_68881" + "fadd%.b %2,%0") + +(define_insn "addxf3" + [(set (match_operand:XF 0 "general_operand" "=f") (plus:XF (match_operand:XF 1 "nonimmediate_operand" "%0") - (match_operand:XF 2 "nonimmediate_operand" "fmG")))] + (match_operand:XF 2 "nonimmediate_operand" "fm")))] "TARGET_68881" "* { @@ -5533,23 +6680,31 @@ return \"fadd%.x %f2,%0\"; }") -(define_expand "subxf3" - [(set (match_operand:XF 0 "general_operand" "") - (minus:XF (match_operand:XF 1 "general_operand" "") - (match_operand:XF 2 "general_operand" "")))] +(define_insn "" + [(set (match_operand:XF 0 "general_operand" "=f") + (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0") + (float:XF (match_operand:SI 2 "general_operand" "dmi"))))] "TARGET_68881" - " -{ - if (CONSTANT_P (operands[1])) - operands[1] = force_const_mem (XFmode, operands[1]); - if (CONSTANT_P (operands[2])) - operands[2] = force_const_mem (XFmode, operands[2]); -}") + "fsub%.l %2,%0") (define_insn "" [(set (match_operand:XF 0 "general_operand" "=f") (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0") - (match_operand:XF 2 "nonimmediate_operand" "fmG")))] + (float:XF (match_operand:HI 2 "general_operand" "dmn"))))] + "TARGET_68881" + "fsub%.w %2,%0") + +(define_insn "" + [(set (match_operand:XF 0 "general_operand" "=f") + (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0") + (float:XF (match_operand:QI 2 "general_operand" "dmn"))))] + "TARGET_68881" + "fsub%.b %2,%0") + +(define_insn "subxf3" + [(set (match_operand:XF 0 "general_operand" "=f") + (minus:XF (match_operand:XF 1 "nonimmediate_operand" "0") + (match_operand:XF 2 "nonimmediate_operand" "fm")))] "TARGET_68881" "* { @@ -5558,23 +6713,31 @@ return \"fsub%.x %f2,%0\"; }") -(define_expand "mulxf3" - [(set (match_operand:XF 0 "general_operand" "") - (mult:XF (match_operand:XF 1 "general_operand" "") - (match_operand:XF 2 "general_operand" "")))] +(define_insn "" + [(set (match_operand:XF 0 "general_operand" "=f") + (mult:XF (float:XF (match_operand:SI 2 "general_operand" "dmi")) + (match_operand:XF 1 "nonimmediate_operand" "0")))] "TARGET_68881" - " -{ - if (CONSTANT_P (operands[1])) - operands[1] = force_const_mem (XFmode, operands[1]); - if (CONSTANT_P (operands[2])) - operands[2] = force_const_mem (XFmode, operands[2]); -}") + "fmul%.l %2,%0") (define_insn "" [(set (match_operand:XF 0 "general_operand" "=f") + (mult:XF (float:XF (match_operand:HI 2 "general_operand" "dmn")) + (match_operand:XF 1 "nonimmediate_operand" "0")))] + "TARGET_68881" + "fmul%.w %2,%0") + +(define_insn "" + [(set (match_operand:XF 0 "general_operand" "=f") + (mult:XF (float:XF (match_operand:QI 2 "general_operand" "dmn")) + (match_operand:XF 1 "nonimmediate_operand" "0")))] + "TARGET_68881" + "fmul%.b %2,%0") + +(define_insn "mulxf3" + [(set (match_operand:XF 0 "general_operand" "=f") (mult:XF (match_operand:XF 1 "nonimmediate_operand" "%0") - (match_operand:XF 2 "nonimmediate_operand" "fmG")))] + (match_operand:XF 2 "nonimmediate_operand" "fm")))] "TARGET_68881" "* { @@ -5583,23 +6746,31 @@ return \"fmul%.x %f2,%0\"; }") -(define_expand "divxf3" - [(set (match_operand:XF 0 "general_operand" "") - (div:XF (match_operand:XF 1 "general_operand" "") - (match_operand:XF 2 "general_operand" "")))] +(define_insn "" + [(set (match_operand:XF 0 "general_operand" "=f") + (div:XF (match_operand:XF 1 "nonimmediate_operand" "0") + (float:XF (match_operand:SI 2 "general_operand" "dmi"))))] "TARGET_68881" - " -{ - if (CONSTANT_P (operands[1])) - operands[1] = force_const_mem (XFmode, operands[1]); - if (CONSTANT_P (operands[2])) - operands[2] = force_const_mem (XFmode, operands[2]); -}") + "fdiv%.l %2,%0") (define_insn "" [(set (match_operand:XF 0 "general_operand" "=f") (div:XF (match_operand:XF 1 "nonimmediate_operand" "0") - (match_operand:XF 2 "nonimmediate_operand" "fmG")))] + (float:XF (match_operand:HI 2 "general_operand" "dmn"))))] + "TARGET_68881" + "fdiv%.w %2,%0") + +(define_insn "" + [(set (match_operand:XF 0 "general_operand" "=f") + (div:XF (match_operand:XF 1 "nonimmediate_operand" "0") + (float:XF (match_operand:QI 2 "general_operand" "dmn"))))] + "TARGET_68881" + "fdiv%.b %2,%0") + +(define_insn "divxf3" + [(set (match_operand:XF 0 "general_operand" "=f") + (div:XF (match_operand:XF 1 "nonimmediate_operand" "0") + (match_operand:XF 2 "nonimmediate_operand" "fm")))] "TARGET_68881" "* { @@ -5608,9 +6779,47 @@ return \"fdiv%.x %f2,%0\"; }") -(define_insn "negxf2" +(define_expand "negxf2" + [(set (match_operand:XF 0 "general_operand" "") + (neg:XF (match_operand:XF 1 "nonimmediate_operand" "")))] + "" + " +{ + /* ??? There isn't an FPA define_insn so we could handle it here too. + For now we don't (paranoia). */ + if (!TARGET_68881) + { + rtx result; + rtx target; + rtx insns; + + start_sequence (); + target = operand_subword (operands[0], 0, 1, XFmode); + result = expand_binop (SImode, xor_optab, + operand_subword_force (operands[1], 0, XFmode), + GEN_INT(0x80000000), target, 0, OPTAB_WIDEN); + if (result == 0) + abort (); + + if (result != target) + emit_move_insn (result, target); + + emit_move_insn (operand_subword (operands[0], 1, 1, XFmode), + operand_subword_force (operands[1], 1, XFmode)); + emit_move_insn (operand_subword (operands[0], 2, 1, XFmode), + operand_subword_force (operands[1], 2, XFmode)); + + insns = get_insns (); + end_sequence (); + + emit_no_conflict_block (insns, operands[0], operands[1], 0, 0); + DONE; + } +}") + +(define_insn "negxf2_68881" [(set (match_operand:XF 0 "general_operand" "=f") - (neg:XF (match_operand:XF 1 "nonimmediate_operand" "fmF")))] + (neg:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))] "TARGET_68881" "* { @@ -5619,9 +6828,47 @@ return \"fneg%.x %f1,%0\"; }") -(define_insn "absxf2" +(define_expand "absxf2" + [(set (match_operand:XF 0 "general_operand" "") + (abs:XF (match_operand:XF 1 "nonimmediate_operand" "")))] + "" + " +{ + /* ??? There isn't an FPA define_insn so we could handle it here too. + For now we don't (paranoia). */ + if (!TARGET_68881) + { + rtx result; + rtx target; + rtx insns; + + start_sequence (); + target = operand_subword (operands[0], 0, 1, XFmode); + result = expand_binop (SImode, and_optab, + operand_subword_force (operands[1], 0, XFmode), + GEN_INT(0x7fffffff), target, 0, OPTAB_WIDEN); + if (result == 0) + abort (); + + if (result != target) + emit_move_insn (result, target); + + emit_move_insn (operand_subword (operands[0], 1, 1, XFmode), + operand_subword_force (operands[1], 1, XFmode)); + emit_move_insn (operand_subword (operands[0], 2, 1, XFmode), + operand_subword_force (operands[1], 2, XFmode)); + + insns = get_insns (); + end_sequence (); + + emit_no_conflict_block (insns, operands[0], operands[1], 0, 0); + DONE; + } +}") + +(define_insn "absxf2_68881" [(set (match_operand:XF 0 "general_operand" "=f") - (abs:XF (match_operand:XF 1 "nonimmediate_operand" "fmF")))] + (abs:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))] "TARGET_68881" "* { @@ -5632,9 +6879,66 @@ (define_insn "sqrtxf2" [(set (match_operand:XF 0 "general_operand" "=f") - (sqrt:XF (match_operand:DF 1 "nonimmediate_operand" "fm")))] + (sqrt:XF (match_operand:XF 1 "nonimmediate_operand" "fm")))] "TARGET_68881" + "fsqrt%.x %1,%0") + +(define_insn "sinsf2" + [(set (match_operand:SF 0 "general_operand" "=f") + (unspec:SF [(match_operand:SF 1 "general_operand" "fm")] 1))] + "TARGET_68881 && flag_fast_math" + "* +{ + if (FP_REG_P (operands[1])) + return \"fsin%.x %1,%0\"; + else + return \"fsin%.s %1,%0\"; +}") + +(define_insn "sindf2" + [(set (match_operand:DF 0 "general_operand" "=f") + (unspec:DF [(match_operand:DF 1 "general_operand" "fm")] 1))] + "TARGET_68881 && flag_fast_math" + "* +{ + if (FP_REG_P (operands[1])) + return \"fsin%.x %1,%0\"; + else + return \"fsin%.d %1,%0\"; +}") + +(define_insn "sinxf2" + [(set (match_operand:XF 0 "general_operand" "=f") + (unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 1))] + "TARGET_68881 && flag_fast_math" + "fsin%.x %1,%0") + +(define_insn "cossf2" + [(set (match_operand:SF 0 "general_operand" "=f") + (unspec:SF [(match_operand:SF 1 "general_operand" "fm")] 2))] + "TARGET_68881 && flag_fast_math" "* { - return \"fsqrt%.x %1,%0\"; + if (FP_REG_P (operands[1])) + return \"fcos%.x %1,%0\"; + else + return \"fcos%.s %1,%0\"; }") + +(define_insn "cosdf2" + [(set (match_operand:DF 0 "general_operand" "=f") + (unspec:DF [(match_operand:DF 1 "general_operand" "fm")] 2))] + "TARGET_68881 && flag_fast_math" + "* +{ + if (FP_REG_P (operands[1])) + return \"fcos%.x %1,%0\"; + else + return \"fcos%.d %1,%0\"; +}") + +(define_insn "cosxf2" + [(set (match_operand:XF 0 "general_operand" "=f") + (unspec:XF [(match_operand:XF 1 "nonimmediate_operand" "fm")] 2))] + "TARGET_68881 && flag_fast_math" + "fcos%.x %1,%0")