--- gcc/config/m68k/m68k.md 2018/04/24 18:20:44 1.1.1.3 +++ gcc/config/m68k/m68k.md 2018/04/24 18:27:54 1.1.1.4 @@ -1,5 +1,5 @@ ;;- Machine description for GNU compiler, Motorola 68000 Version -;; Copyright (C) 1987, 1988, 1993, 1994 Free Software Foundation, Inc. +;; Copyright (C) 1987, 1988, 1993, 1994, 1995 Free Software Foundation, Inc. ;; This file is part of GNU CC. @@ -15,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 @@ -64,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 @@ -274,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"))] @@ -377,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,>")))] @@ -749,29 +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 - } - else if (DATA_REG_P (operands[0]) - /* if -256 < N < 256 but N is not in range for a moveq - N^ff will be, so use moveq #N^ff, dreg; not.b dreg. */ - && INTVAL (operands[1]) < 256 - && INTVAL (operands[1]) >= -256) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) ^ 0xff); -#if defined(MOTOROLA) && !defined(CRDS) - return \"moveq%.l %1,%0\;not%.b %0\"; -#else - return \"moveq %1,%0\;not%.b %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) @@ -1362,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)) @@ -1537,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 @@ -1833,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, @@ -2206,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" @@ -2241,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" @@ -2253,6 +2593,100 @@ ;; subtract instructions +(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))))] + "" + "* +{ + 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 (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) + { + 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\"; + } + } + else if (GET_CODE (operands[0]) == MEM) + { + 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[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\"; + } + } +} ") + (define_insn "subsi3" [(set (match_operand:SI 0 "general_operand" "=m,r") (minus:SI (match_operand:SI 1 "general_operand" "0,0") @@ -2322,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" "* @@ -2357,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" "* @@ -2544,9 +3020,12 @@ " { operands[3] = gen_reg_rtx (SImode); - if (CONSTANT_P (operands[2])) + if (GET_CODE (operands[2]) == CONST_INT + || GET_CODE (operands[2]) == CONST_DOUBLE) { - /* We have to rearrange the operand order for the matching constraints. */ + 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; @@ -2569,7 +3048,7 @@ (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 2 "register_operand" "1")) - (match_operand:DI 3 "immediate_operand" "i")) + (match_operand 3 "const_uint32_operand" "")) (const_int 32)))) (clobber (match_operand:SI 1 "register_operand" "=d"))] "TARGET_68020" @@ -2588,9 +3067,12 @@ " { operands[3] = gen_reg_rtx (SImode); - if (CONSTANT_P (operands[2])) + if (GET_CODE (operands[2]) == CONST_INT + || GET_CODE (operands[2]) == CONST_DOUBLE) { - /* We have to rearrange the operand order for the matching constraints. */ + 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; @@ -2613,7 +3095,7 @@ (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 2 "register_operand" "1")) - (match_operand:DI 3 "immediate_operand" "i")) + (match_operand 3 "const_sint32_operand" "")) (const_int 32)))) (clobber (match_operand:SI 1 "register_operand" "=d"))] "TARGET_68020" @@ -2646,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" @@ -2690,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" @@ -2713,99 +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 -}") - -;; These patterns don't work because the divs instruction is undefined if -;; the quotient is more than 16 bits. This valid C would be miscompiled: -;; int n; short d; unsigned short q; ... q = (unsigned int) (n / d); -;; Imagine what happens when n = 100000 and d = 1. -;;(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 -}") - -;; See comment before divhisi3 why these are commented out. -;;(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" "") @@ -2832,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" "* @@ -2867,6 +3334,42 @@ (define_insn "" [(set (match_operand:SF 0 "general_operand" "=f") (div:SF (match_operand:SF 1 "general_operand" "0") + (float:SF (match_operand:SI 2 "general_operand" "dmi"))))] + "TARGET_68881" + "* +{ + return (TARGET_68040_ONLY + ? \"fsdiv%.l %2,%0\" + : \"fsgldiv%.l %2,%0\"); +}") + +(define_insn "" + [(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" + "* +{ + return (TARGET_68040_ONLY + ? \"fsdiv%.w %2,%0\" + : \"fsgldiv%.w %2,%0\"); +}") + +(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" + "* +{ + return (TARGET_68040_ONLY + ? \"fsdiv%.b %2,%0\" + : \"fsgldiv%.b %2,%0\"); +}") + +(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")))] "TARGET_68881" "* @@ -2889,108 +3392,6 @@ ;; 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 -}") - -;; See comment before divhisi3 why these are commented out. -;;(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 -;;}") - -;;(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")))] - "" - "* -{ - /* 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 -}") - -;; See comment before divhisi3 why these are commented out. -;;(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")))))] -;; "" -;; "* -;;{ -;; /* 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 -;;}") - -;;(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"))))] -;; "" -;; "* -;;{ -;; /* 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 -;;}") - (define_insn "divmodsi4" [(set (match_operand:SI 0 "general_operand" "=d") (div:SI (match_operand:SI 1 "general_operand" "0") @@ -3020,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 @@ -3194,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 @@ -3262,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")))] @@ -3292,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") @@ -3323,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") @@ -3350,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")))] @@ -3357,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") @@ -3390,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") @@ -3412,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")))] @@ -3445,6 +4060,104 @@ ;; 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 "" @@ -3537,6 +4250,103 @@ 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") @@ -3574,10 +4384,129 @@ ;; logical shift instructions +;; 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 "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))] + "" + "* +{ + return \"move%.l %1,%0\"; +} ") + +(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\"; +} ") + +;; 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; +} ") ;; On all 68k models, this makes faster code in a special case. -(define_insn "" +(define_insn "lshrsi_31" + [(set (match_operand:SI 0 "register_operand" "=d") + (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") + (const_int 31)))] + "" + "* +{ + return \"add%.l %0,%0\;subx%.l %0,%0\;neg%.l %0\"; +}") + +;; On all 68k models, this makes faster code in a special case. + +(define_insn "lshrsi_16" [(set (match_operand:SI 0 "register_operand" "=d") (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") (const_int 16)))] @@ -3590,7 +4519,7 @@ ;; 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 "const_int_operand" "n")))] @@ -3711,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, @@ -4083,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)))] @@ -4163,6 +5172,103 @@ ;; 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(); +#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 + 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,"))] + "" + "* +{ + 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 \"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 + return \"move%.l %0,%2\;or%.l %3,%2\;jbne %l1\"; +#else + return \"move%.l %0,%2\;or%.l %3,%2\;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)))] + "" + "* +{ +#ifdef MOTOROLA + return \"tst%.l %0\;jbge %l1\"; +#else + return \"tst%.l %0\;jge %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)))] + "" + "* +{ +#ifdef MOTOROLA + return \"tst%.l %0\;jbmi %l1\"; +#else + return \"tst%.l %0\;jmi %l1\"; +#endif +} ") + (define_insn "beq" [(set (pc) (if_then_else (eq (cc0) @@ -4545,7 +5651,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))) @@ -4588,7 +5694,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))) @@ -4634,7 +5740,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 "" "")) @@ -4679,7 +5785,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 "" "")) @@ -4722,23 +5828,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 @@ -4748,7 +5853,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 @@ -4770,12 +5875,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. @@ -4786,7 +5886,7 @@ "! 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) @@ -4806,15 +5906,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\"; ") @@ -4830,12 +5938,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 @@ -4846,7 +5949,7 @@ ;; 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) @@ -4866,15 +5969,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\"; ") @@ -5343,24 +6454,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" "* { @@ -5506,23 +6603,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" "* { @@ -5531,23 +6636,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" "* { @@ -5556,23 +6669,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" "* { @@ -5581,23 +6702,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" "* { @@ -5606,9 +6735,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" "* { @@ -5617,9 +6784,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" "* { @@ -5630,9 +6835,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" "* { - return \"fsqrt%.x %1,%0\"; + 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" + "* +{ + 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")