diff options
Diffstat (limited to 'gcc/config/m68k/m68k.md')
-rw-r--r-- | gcc/config/m68k/m68k.md | 7415 |
1 files changed, 0 insertions, 7415 deletions
diff --git a/gcc/config/m68k/m68k.md b/gcc/config/m68k/m68k.md deleted file mode 100644 index 86a70b6361d..00000000000 --- a/gcc/config/m68k/m68k.md +++ /dev/null @@ -1,7415 +0,0 @@ -;;- Machine description for GNU compiler, Motorola 68000 Version -;; Copyright (C) 1987, 88, 93, 94, 95, 96, 1997 Free Software Foundation, Inc. - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; 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, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. - -;;- Information about MCF5200 port. - -;;- The MCF5200 "ColdFire" architecture is a reduced version of the -;;- 68k ISA. Differences include reduced support for byte and word -;;- operands and the removal of BCD, bitfield, rotate, and integer -;;- divide instructions. The TARGET_5200 flag turns the use of the -;;- removed opcodes and addressing modes off. -;;- - - -;;- instruction definitions - -;;- @@The original PO technology requires these to be ordered by speed, -;;- @@ so that assigner will pick the fastest. - -;;- See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;;- When naming insn's (operand 0 of define_insn) be careful about using -;;- names from other targets machine descriptions. - -;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code -;;- updates for most instructions. - -;;- Operand classes for the register allocator: -;;- 'a' one of the address registers can be used. -;;- 'd' one of the data registers can be used. -;;- 'f' one of the m68881 registers can be used -;;- 'r' either a data or an address register can be used. -;;- 'x' if one of the Sun FPA registers -;;- 'y' if one of the Low Sun FPA registers (fpa0-fpa15). - -;;- Immediate Floating point operator constraints -;;- 'G' a floating point constant that is *NOT* one of the standard -;; 68881 constant values (to force calling output_move_const_double -;; to get it from rom if it is a 68881 constant). -;;- 'H' one of the standard FPA constant values -;; -;; See the functions standard_XXX_constant_p in output-m68k.c for more -;; info. - -;;- Immediate integer operand constraints: -;;- 'I' 1 .. 8 -;;- 'J' -32768 .. 32767 -;;- 'K' all integers EXCEPT -128 .. 127 -;;- 'L' -8 .. -1 -;;- 'M' all integers EXCEPT -256 .. 255 -;;- 'N' 24 .. 31 -;;- 'O' 16 -;;- 'P' 8 .. 15 - -;;- Assembler specs: -;;- "%." size separator ("." or "") move%.l d0,d1 -;;- "%#" immediate separator ("#" or "") move%.l %#0,d0 -;;- "%-" push operand "sp@-" move%.l d0,%- -;;- "%+" pop operand "sp@+" move%.l d0,%+ -;;- "%@" top of stack "sp@" move%.l d0,%@ -;;- "%!" fpcr register -;;- "%$" 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 -;;- be emulated in software by the OS. It is faster to avoid these -;;- instructions and issue a library call rather than trapping into -;;- the kernel. The affected instructions are fintrz and fscale. The -;;- TARGET_68040 flag turns the use of the opcodes off. - -;;- The '040 also implements a set of new floating-point instructions -;;- which specify the rounding precision in the opcode. This finally -;;- permit the 68k series to be truly IEEE compliant, and solves all -;;- issues of excess precision accumulating in the extended registers. -;;- By default, GCC does not use these instructions, since such code will -;;- not run on an '030. To use these instructions, use the -m68040-only -;;- switch. By changing TARGET_DEFAULT to include TARGET_68040_ONLY, -;;- you can make these instructions the default. - -;;- These new instructions aren't directly in the md. They are brought -;;- into play by defining "%$" and "%&" to expand to "s" and "d" rather -;;- than "". - -;;- Information about 68060 port. - -;;- The 68060 executes all 68030 and 68881/2 instructions, but some must -;;- be emulated in software by the OS. It is faster to avoid these -;;- instructions and issue a library call rather than trapping into -;;- the kernel. The affected instructions are: divs.l <ea>,Dr:Dq; -;;- divu.l <ea>,Dr:Dq; muls.l <ea>,Dr:Dq; mulu.l <ea>,Dr:Dq; and -;;- fscale. The TARGET_68060 flag turns the use of the opcodes off. - -;;- FPA port explanation: - -;;- Usage of the Sun FPA and the 68881 together - -;;- The current port of gcc to the sun fpa disallows use of the m68881 -;;- instructions completely if code is targeted for the fpa. This is -;;- for the following reasons: - -;;- 1) Expressing the preference hierarchy (ie. use the fpa if you -;;- can, the 68881 otherwise, and data registers only if you are -;;- forced to it) is a bitch with the current constraint scheme, -;;- especially since it would have to work for any combination of -;;- -mfpa, -m68881. - -;;- 2) There are no instructions to move between the two types of -;;- registers; the stack must be used as an intermediary. - -;;- It could indeed be done; I think the best way would be to have -;;- separate patterns for TARGET_FPA (which implies a 68881), -;;- TARGET_68881, and no floating point co-processor. Use -;;- define_expands for all of the named instruction patterns, and -;;- include code in the FPA instruction to deal with the 68881 with -;;- preferences specifically set to favor the fpa. Some of this has -;;- already been done: -;;- -;;- 1) Separation of most of the patterns out into a TARGET_FPA -;;- case and a TARGET_68881 case (the exceptions are the patterns -;;- which would need one define_expand and three define_insn's under -;;- it (with a lot of duplicate code between them) to replace the -;;- current single define_insn. These are mov{[ds]f,[ds]i} and the -;;- first two patterns in the md. -;;- -;;- Some would still have to be done: -;;- -;;- 1) Add code to the fpa patterns which correspond to 68881 -;;- patterns to deal with the 68881 case (including preferences!). -;;- What you might actually do here is combine the fpa and 68881 code -;;- back together into one pattern for those instructions where it's -;;- absolutely necessary and save yourself some duplicate code. I'm -;;- not completely sure as to whether you could get away with doing -;;- this only for the mov* insns, or if you'd have to do it for all -;;- named insns. -;;- 2) Add code to the mov{[ds]f,[ds]i} instructions to handle -;;- moving between fpa regs and 68881 regs. - -;;- Since the fpa is more powerful than the 68881 and also has more -;;- registers, and since I think the resultant md would be medium ugly -;;- (lot's of duplicate code, ugly constraint strings), I elected not -;;- to do this change. - -;;- Another reason why someone *might* want to do the change is to -;;- control which register classes are accessed in a slightly cleaner -;;- way than I have. See the blurb on CONDITIONAL_REGISTER_USAGE in -;;- the internals manual. - -;;- Yet another reason why someone might want to do this change is to -;;- allow use of some of the 68881 insns which have no equivalent on -;;- the fpa. The sqrt instruction comes fairly quickly to mind. - -;;- If this is ever done, don't forget to change sun3.h so that -;;- it *will* define __HAVE_68881__ when the FPA is in use. - -;;- Condition code hack - -;;- When a floating point compare is done in the fpa, the resulting -;;- condition codes are left in the fpastatus register. The values in -;;- this register must be moved into the 68000 cc register before any -;;- jump is executed. Once this has been done, regular jump -;;- instructions are fine (ie. floating point jumps are not necessary. -;;- They are only done if the cc is in the 68881). - -;;- The instructions that move the fpastatus register to the 68000 -;;- register clobber a data register (the move cannot be done direct). -;;- These instructions might be bundled either with the compare -;;- instruction, or the branch instruction. If we were using both the -;;- fpa and the 68881 together, we would wish to only mark the -;;- register clobbered if we were doing the compare in the fpa, but I -;;- think that that decision (whether to clobber the register or not) -;;- must be done before register allocation (makes sense) and hence we -;;- can't know if the floating point compare will be done in the fpa -;;- or the fp. So whenever we are asked for code that uses the fpa, -;;- we will mark a data register as clobbered. This is reasonable, as -;;- almost all floating point compare operations done with fpa code -;;- enabled will be done in the fpa. It's even more reasonable since -;;- we decided to make the 68881 and the fpa mutually exclusive. - -;;- We place to code to move the fpastatus register inside of a -;;- define_expand so that we can do it conditionally based on whether -;;- we are targeting an fpa or not. - -;;- This still leaves us with the question of where we wish to put the -;;- code to move the fpastatus reg. If we put it in the compare -;;- instruction, we can restrict the clobbering of the register to -;;- floating point compares, but we can't take advantage of floating -;;- point subtracts & etc. that alter the fpastatus register. If we -;;- put it in the branch instruction, all branches compiled with fpa -;;- code enabled will clobber a data register, but we will be able to -;;- take advantage of fpa subtracts. This balance favors putting the -;;- code in with the compare instruction. - -;;- Note that if some enterprising hacker should decide to switch -;;- this, he'll need to modify the code in NOTICE_UPDATE_CC. - -;;- Usage of the top 16 fpa registers - -;;- The only locations which we may transfer fpa registers 16-31 from -;;- or to are the fpa registers 0-15. (68000 registers and memory -;;- locations are impossible). This causes problems in gcc, which -;;- assumes that mov?? instructions require no additional registers -;;- (see section 11.7) and since floating point moves *must* be -;;- supported into general registers (see section 12.3 under -;;- HARD_REGNO_OK_FOR_MODE_P) from anywhere. - -;;- My solution was to reserve fpa0 for moves into or out of these top -;;- 16 registers and to disparage the choice to reload into or out of -;;- these registers as much as I could. That alternative is always -;;- last in the list, so it will not be used unless all else fails. I -;;- will note that according to my current information, sun's compiler -;;- doesn't use these top 16 registers at all. - -;;- There is another possible way to do it. I *believe* that if you -;;- make absolutely sure that the code will not be executed in the -;;- reload pass, you can support the mov?? names with define_expands -;;- which require new registers. This may be possible by the -;;- appropriate juggling of constraints. I may come back to this later. - -;;- Usage of constant RAM - -;;- This has been handled correctly (I believe) but the way I've done -;;- it could use a little explanation. The constant RAM can only be -;;- accessed when the instruction is in "command register" mode. -;;- "command register" mode means that no accessing of memory or the -;;- 68000 registers is being done. This can be expressed easily in -;;- constraints, so generally the mode of the instruction is -;;- determined by a branch off of which_alternative. In outputting -;;- instructions, a 'w' means to output an access to the constant ram -;;- (if the arg is CONST_DOUBLE and is one of the available -;;- constants), and 'x' means to output a register pair (if the arg is -;;- a 68000 register) and a 'y' is the combination of the above two -;;- processes. You use a 'y' in two operand DF instructions where you -;;- *know* the other operand is an fpa register, you use an 'x' in DF -;;- instructions where the arg might be a 68000 register and the -;;- instruction is *not* in "command register" mode, and you use a 'w' -;;- in two situations: 1) The instruction *is* in command register -;;- mode (and hence won't be accessing 68000 registers), or 2) The -;;- instruction is a two operand SF instruction where you know the -;;- other operand is an fpa register. - -;;- Optimization issues - -;;- I actually think that I've included all of the fpa instructions -;;- that should be included. Note that if someone is interested in -;;- doing serious floating point work on the sun fpa, I would advise -;;- the use of the "asm" instruction in gcc to allow you to use the -;;- sin, cos, and exponential functions on the fpa board. - -;;- END FPA Explanation Section. - - -;;- Some of these insn's are composites of several m68000 op codes. -;;- The assembler (or final @@??) insures that the appropriate one is -;;- selected. - -(define_insn "" - [(set (match_operand:DF 0 "push_operand" "=m") - (match_operand:DF 1 "general_operand" "ro<>fyE"))] - "" - "* -{ - if (FP_REG_P (operands[1])) - return \"fmove%.d %f1,%0\"; - if (FPA_REG_P (operands[1])) - return \"fpmove%.d %1, %x0\"; - return output_move_double (operands); -}") - -(define_insn "pushdi" - [(set (match_operand:DI 0 "push_operand" "=m") - (match_operand:DI 1 "general_operand" "ro<>Fyi"))] - "" - "* -{ - return output_move_double (operands); -}") - -;; 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" - [(set (cc0) - (match_operand:DI 0 "nonimmediate_operand" "")) - (clobber (match_scratch:SI 1 "")) - (clobber (match_scratch:DI 2 ""))] - "" - "m68k_last_compare_had_fp_operands = 0;") - -(define_insn "" - [(set (cc0) - (match_operand:DI 0 "nonimmediate_operand" "am,d")) - (clobber (match_scratch:SI 1 "=X,d")) - (clobber (match_scratch:DI 2 "=d,X"))] - "" - "* -{ - if (which_alternative == 0) - { - rtx xoperands[2]; - - xoperands[0] = operands[2]; - xoperands[1] = operands[0]; - output_move_double (xoperands); - cc_status.flags |= CC_REVERSED; - return \"neg%.l %R2\;negx%.l %2\"; - } - if (find_reg_note (insn, REG_DEAD, operands[0])) - { - cc_status.flags |= CC_REVERSED; - return \"neg%.l %R0\;negx%.l %0\"; - } - else - /* - ** 'sub' clears %1, and also clears the X cc bit - ** 'tst' sets the Z cc bit according to the low part of the DImode operand - ** 'subx %1' (i.e. subx #0) acts as a (non-existent) tstx on the high part - */ - return \"sub%.l %1,%1\;tst%.l %R0\;subx%.l %1,%0\"; -}") - -(define_expand "tstsi" - [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" ""))] - "" - "m68k_last_compare_had_fp_operands = 0;") - -(define_insn "" - [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" "rm"))] - "" - "* -{ -#ifdef ISI_OV - /* ISI's assembler fails to handle tstl a0. */ - if (! ADDRESS_REG_P (operands[0])) -#else - if (TARGET_68020 || TARGET_5200 || ! ADDRESS_REG_P (operands[0])) -#endif - return \"tst%.l %0\"; - /* If you think that the 68020 does not support tstl a0, - reread page B-167 of the 68020 manual more carefully. */ - /* On an address reg, cmpw may replace cmpl. */ -#ifdef SGS_CMP_ORDER - return \"cmp%.w %0,%#0\"; -#else - return \"cmp%.w %#0,%0\"; -#endif -}") - -;; This can't use an address register, because comparisons -;; with address registers as second operand always test the whole word. -(define_expand "tsthi" - [(set (cc0) - (match_operand:HI 0 "nonimmediate_operand" ""))] - "" - "m68k_last_compare_had_fp_operands = 0;") - -(define_insn "" - [(set (cc0) - (match_operand:HI 0 "nonimmediate_operand" "dm"))] - "" - "tst%.w %0") - -(define_expand "tstqi" - [(set (cc0) - (match_operand:QI 0 "nonimmediate_operand" ""))] - "" - "m68k_last_compare_had_fp_operands = 0;") - -(define_insn "" - [(set (cc0) - (match_operand:QI 0 "nonimmediate_operand" "dm"))] - "" - "tst%.b %0") - -(define_expand "tstsf" - [(set (cc0) - (match_operand:SF 0 "general_operand" ""))] - "TARGET_68881 || TARGET_FPA" - " -{ - m68k_last_compare_had_fp_operands = 1; - if (TARGET_FPA) - { - emit_insn (gen_tstsf_fpa (operands[0])); - DONE; - } -}") - -(define_insn "tstsf_fpa" - [(set (cc0) - (match_operand:SF 0 "general_operand" "xmdF")) - (clobber (match_scratch:SI 1 "=d"))] - "TARGET_FPA" - "fptst%.s %x0\;fpmove fpastatus,%1\;movw %1,cc") - -(define_insn "" - [(set (cc0) - (match_operand:SF 0 "general_operand" "fdm"))] - "TARGET_68881" - "* -{ - cc_status.flags = CC_IN_68881; - if (FP_REG_P (operands[0])) - return \"ftst%.x %0\"; - return \"ftst%.s %0\"; -}") - -(define_expand "tstdf" - [(set (cc0) - (match_operand:DF 0 "general_operand" ""))] - "TARGET_68881 || TARGET_FPA" - " -{ - m68k_last_compare_had_fp_operands = 1; - if (TARGET_FPA) - { - emit_insn (gen_tstsf_fpa (operands[0])); - DONE; - } -}") - -(define_insn "tstdf_fpa" - [(set (cc0) - (match_operand:DF 0 "general_operand" "xrmF")) - (clobber (match_scratch:SI 1 "=d"))] - "TARGET_FPA" - "fptst%.d %x0\;fpmove fpastatus,%1\;movw %1,cc") - -(define_insn "" - [(set (cc0) - (match_operand:DF 0 "general_operand" "fm"))] - "TARGET_68881" - "* -{ - cc_status.flags = CC_IN_68881; - if (FP_REG_P (operands[0])) - return \"ftst%.x %0\"; - return \"ftst%.d %0\"; -}") - -;; 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))])] - "" - "m68k_last_compare_had_fp_operands = 0; 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" "")))] - "" - " -{ - m68k_last_compare_had_fp_operands = 0; - 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 & cmpm m68000 op codes. -(define_insn "" - [(set (cc0) - (compare (match_operand:SI 0 "nonimmediate_operand" "rKs,mr,>") - (match_operand:SI 1 "general_operand" "mr,rKs,>")))] - "!TARGET_5200" - "* -{ - 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; -#ifdef SGS_CMP_ORDER - return \"cmp%.l %d1,%d0\"; -#else - return \"cmp%.l %d0,%d1\"; -#endif - } -#ifdef SGS_CMP_ORDER - return \"cmp%.l %d0,%d1\"; -#else - return \"cmp%.l %d1,%d0\"; -#endif -}") - -(define_insn "" - [(set (cc0) - (compare (match_operand:SI 0 "nonimmediate_operand" "mrKs,r") - (match_operand:SI 1 "general_operand" "r,mrKs")))] - "TARGET_5200" - "* -{ - if (REG_P (operands[1]) - || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM)) - { cc_status.flags |= CC_REVERSED; -#ifdef SGS_CMP_ORDER - return \"cmp%.l %d1,%d0\"; -#else - return \"cmp%.l %d0,%d1\"; -#endif - } -#ifdef SGS_CMP_ORDER - return \"cmp%.l %d0,%d1\"; -#else - return \"cmp%.l %d1,%d0\"; -#endif -}") - -(define_expand "cmphi" - [(set (cc0) - (compare (match_operand:HI 0 "nonimmediate_operand" "") - (match_operand:HI 1 "general_operand" "")))] - "!TARGET_5200" - "m68k_last_compare_had_fp_operands = 0;") - -(define_insn "" - [(set (cc0) - (compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m,>") - (match_operand:HI 1 "general_operand" "d,rnm,m,n,>")))] - "!TARGET_5200" - "* -{ - 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; -#ifdef SGS_CMP_ORDER - return \"cmp%.w %d1,%d0\"; -#else - return \"cmp%.w %d0,%d1\"; -#endif - } -#ifdef SGS_CMP_ORDER - return \"cmp%.w %d0,%d1\"; -#else - return \"cmp%.w %d1,%d0\"; -#endif -}") - -(define_expand "cmpqi" - [(set (cc0) - (compare (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" "")))] - "!TARGET_5200" - "m68k_last_compare_had_fp_operands = 0;") - -(define_insn "" - [(set (cc0) - (compare (match_operand:QI 0 "nonimmediate_operand" "dn,md,>") - (match_operand:QI 1 "general_operand" "dm,nd,>")))] - "!TARGET_5200" - "* -{ - 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; -#ifdef SGS_CMP_ORDER - return \"cmp%.b %d1,%d0\"; -#else - return \"cmp%.b %d0,%d1\"; -#endif - } -#ifdef SGS_CMP_ORDER - return \"cmp%.b %d0,%d1\"; -#else - return \"cmp%.b %d1,%d0\"; -#endif -}") - -(define_expand "cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - " -{ - m68k_last_compare_had_fp_operands = 1; - if (TARGET_FPA) - { - emit_insn (gen_cmpdf_fpa (operands[0], operands[1])); - DONE; - } -}") - -(define_insn "cmpdf_fpa" - [(set (cc0) - (compare (match_operand:DF 0 "general_operand" "x,y") - (match_operand:DF 1 "general_operand" "xH,rmF"))) - (clobber (match_scratch:SI 2 "=d,d"))] - "TARGET_FPA" - "fpcmp%.d %y1,%0\;fpmove fpastatus,%2\;movw %2,cc") - -(define_insn "" - [(set (cc0) - (compare (match_operand:DF 0 "general_operand" "f,mG") - (match_operand:DF 1 "general_operand" "fmG,f")))] - "TARGET_68881" - "* -{ - cc_status.flags = CC_IN_68881; -#ifdef SGS_CMP_ORDER - if (REG_P (operands[0])) - { - if (REG_P (operands[1])) - return \"fcmp%.x %0,%1\"; - else - return \"fcmp%.d %0,%f1\"; - } - cc_status.flags |= CC_REVERSED; - return \"fcmp%.d %1,%f0\"; -#else - if (REG_P (operands[0])) - { - if (REG_P (operands[1])) - return \"fcmp%.x %1,%0\"; - else - return \"fcmp%.d %f1,%0\"; - } - cc_status.flags |= CC_REVERSED; - return \"fcmp%.d %f0,%1\"; -#endif -}") - -(define_expand "cmpsf" - [(set (cc0) - (compare (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - " -{ - m68k_last_compare_had_fp_operands = 1; - if (TARGET_FPA) - { - emit_insn (gen_cmpsf_fpa (operands[0], operands[1])); - DONE; - } -}") - -(define_insn "cmpsf_fpa" - [(set (cc0) - (compare (match_operand:SF 0 "general_operand" "x,y") - (match_operand:SF 1 "general_operand" "xH,rmF"))) - (clobber (match_scratch:SI 2 "=d,d"))] - "TARGET_FPA" - "fpcmp%.s %w1,%x0\;fpmove fpastatus,%2\;movw %2,cc") - -(define_insn "" - [(set (cc0) - (compare (match_operand:SF 0 "general_operand" "f,mdG") - (match_operand:SF 1 "general_operand" "fmdG,f")))] - "TARGET_68881" - "* -{ - cc_status.flags = CC_IN_68881; -#ifdef SGS_CMP_ORDER - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - return \"fcmp%.x %0,%1\"; - else - return \"fcmp%.s %0,%f1\"; - } - cc_status.flags |= CC_REVERSED; - return \"fcmp%.s %1,%f0\"; -#else - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - return \"fcmp%.x %1,%0\"; - else - return \"fcmp%.s %f1,%0\"; - } - cc_status.flags |= CC_REVERSED; - return \"fcmp%.s %f0,%1\"; -#endif -}") - -;; Recognizers for btst instructions. - -(define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o") - (const_int 1) - (minus:SI (const_int 7) - (match_operand:SI 1 "general_operand" "di"))))] - "" - "* { return output_btst (operands, operands[1], operands[0], insn, 7); }") - -(define_insn "" - [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d") - (const_int 1) - (minus:SI (const_int 31) - (match_operand:SI 1 "general_operand" "di"))))] - "" - "* { return output_btst (operands, operands[1], operands[0], insn, 31); }") - -;; The following two patterns are like the previous two -;; except that they use the fact that bit-number operands -;; are automatically masked to 3 or 5 bits. - -(define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "o") - (const_int 1) - (minus:SI (const_int 7) - (and:SI - (match_operand:SI 1 "register_operand" "d") - (const_int 7)))))] - "" - "* { return output_btst (operands, operands[1], operands[0], insn, 7); }") - -(define_insn "" - [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "d") - (const_int 1) - (minus:SI (const_int 31) - (and:SI - (match_operand:SI 1 "register_operand" "d") - (const_int 31)))))] - "" - "* { return output_btst (operands, operands[1], operands[0], insn, 31); }") - -;; Nonoffsettable mem refs are ok in this one pattern -;; since we don't try to adjust them. -(define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m") - (const_int 1) - (match_operand:SI 1 "const_int_operand" "n")))] - "(unsigned) INTVAL (operands[1]) < 8" - "* -{ - operands[1] = gen_rtx (CONST_INT, VOIDmode, 7 - INTVAL (operands[1])); - return output_btst (operands, operands[1], operands[0], insn, 7); -}") - -(define_insn "" - [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "do") - (const_int 1) - (match_operand:SI 1 "const_int_operand" "n")))] - "" - "* -{ - if (GET_CODE (operands[0]) == MEM) - { - operands[0] = adj_offsettable_operand (operands[0], - INTVAL (operands[1]) / 8); - operands[1] = gen_rtx (CONST_INT, VOIDmode, - 7 - INTVAL (operands[1]) % 8); - return output_btst (operands, operands[1], operands[0], insn, 7); - } - operands[1] = gen_rtx (CONST_INT, VOIDmode, - 31 - INTVAL (operands[1])); - return output_btst (operands, operands[1], operands[0], insn, 31); -}") - - -;; move instructions - -;; A special case in which it is not desirable -;; to reload the constant into a data register. -(define_insn "pushexthisi_const" - [(set (match_operand:SI 0 "push_operand" "=m") - (match_operand:SI 1 "const_int_operand" "J"))] - "INTVAL (operands[1]) >= -0x8000 && INTVAL (operands[1]) < 0x8000" - "* -{ - if (operands[1] == const0_rtx) - return \"clr%.l %0\"; - return \"pea %a1\"; -}") - -;This is never used. -;(define_insn "swapsi" -; [(set (match_operand:SI 0 "general_operand" "+r") -; (match_operand:SI 1 "general_operand" "+r")) -; (set (match_dup 1) (match_dup 0))] -; "" -; "exg %1,%0") - -;; Special case of fullword move when source is zero. -;; The reason this is special is to avoid loading a zero -;; into a data reg with moveq in order to store it elsewhere. - -(define_insn "movsi_const0" - [(set (match_operand:SI 0 "general_operand" "=g") - (const_int 0))] - ;; clr insns on 68000 read before writing. - ;; This isn't so on the 68010, but we have no TARGET_68010. - "((TARGET_68020 || TARGET_5200) - || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))" - "* -{ - if (ADDRESS_REG_P (operands[0])) - { - /* On the '040, 'subl an,an' takes 2 clocks while lea takes only 1 */ - if (!TARGET_68040 && !TARGET_68060) - return \"sub%.l %0,%0\"; - else - { -#ifdef MOTOROLA -#ifdef SGS - /* Many SGS assemblers croak on size specifiers for constants. */ - return \"lea 0,%0\"; -#else - return \"lea 0.w,%0\"; -#endif -#else - return \"lea 0:w,%0\"; -#endif - } - } - /* moveq is faster on the 68000. */ - if (DATA_REG_P (operands[0]) && (!TARGET_68020 && !TARGET_5200)) -#if defined(MOTOROLA) && !defined(CRDS) - return \"moveq%.l %#0,%0\"; -#else - return \"moveq %#0,%0\"; -#endif - return \"clr%.l %0\"; -}") - -;; General case of fullword move. -;; -;; This is the main "hook" for PIC code. When generating -;; PIC, movsi is responsible for determining when the source address -;; needs PIC relocation and appropriately calling legitimize_pic_address -;; to perform the actual relocation. -;; -;; In both the PIC and non-PIC cases the patterns generated will -;; matched by the next define_insn. -(define_expand "movsi" - [(set (match_operand:SI 0 "general_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); - } -}") - -;; General case of fullword move. The register constraints -;; force integer constants in range for a moveq to be reloaded -;; if they are headed for memory. -(define_insn "" - ;; Notes: make sure no alternative allows g vs g. - ;; We don't allow f-regs since fixed point cannot go in them. - ;; We do allow y and x regs since fixed point is allowed in them. - [(set (match_operand:SI 0 "general_operand" "=g,da,y,!*x*r*m") - (match_operand:SI 1 "general_operand" "daymKs,i,g,*x*r*m"))] - "!TARGET_5200" - "* -{ - if (which_alternative == 3) - return \"fpmove%.l %x1,fpa0\;fpmove%.l fpa0,%x0\"; - if (FPA_REG_P (operands[1]) || FPA_REG_P (operands[0])) - return \"fpmove%.l %x1,%x0\"; - return output_move_simode (operands); -}") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=r<>,g") - (match_operand:SI 1 "general_operand" "g,r<>"))] - "TARGET_5200" - "* return output_move_simode (operands);") - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - "") - -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=g") - (match_operand:HI 1 "general_operand" "g"))] - "!TARGET_5200" - "* return output_move_himode (operands);") - - (define_insn "" - [(set (match_operand:HI 0 "general_operand" "=r<>,g") - (match_operand:HI 1 "general_operand" "g,r<>"))] - "TARGET_5200" - "* return output_move_himode (operands);") - -(define_insn "movstricthi" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm")) - (match_operand:HI 1 "general_operand" "rmn"))] - "" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - { - if (operands[1] == const0_rtx - && (DATA_REG_P (operands[0]) - || GET_CODE (operands[0]) == MEM) - /* clr insns on 68000 read before writing. - This isn't so on the 68010, but we have no TARGET_68010. */ - && ((TARGET_68020 || TARGET_5200) - || !(GET_CODE (operands[0]) == MEM - && MEM_VOLATILE_P (operands[0])))) - return \"clr%.w %0\"; - } - return \"move%.w %1,%0\"; -}") - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - "") - -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=d,*a,m") - (match_operand:QI 1 "general_operand" "dmi*a,di*a,dmi"))] - "!TARGET_5200" - "* return output_move_qimode (operands);") - -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=d<>,dm") - (match_operand:QI 1 "general_operand" "dmi,d<>"))] - "TARGET_5200" - "* return output_move_qimode (operands);") - -(define_insn "movstrictqi" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm")) - (match_operand:QI 1 "general_operand" "dmn"))] - "" - "* -{ - if (operands[1] == const0_rtx - /* clr insns on 68000 read before writing. - This isn't so on the 68010, but we have no TARGET_68010. */ - && ((TARGET_68020 || TARGET_5200) - || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))) - return \"clr%.b %0\"; - return \"move%.b %1,%0\"; -}") - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - "") - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=rmf,x,y,rm,!x,!rm") - (match_operand:SF 1 "general_operand" "rmfF,xH,rmF,y,rm,x"))] -; [(set (match_operand:SF 0 "general_operand" "=rmf") -; (match_operand:SF 1 "general_operand" "rmfF"))] - "!TARGET_5200" - "* -{ - if (which_alternative >= 4) - return \"fpmove%.s %1,fpa0\;fpmove%.s fpa0,%0\"; - if (FPA_REG_P (operands[0])) - { - if (FPA_REG_P (operands[1])) - return \"fpmove%.s %x1,%x0\"; - else if (GET_CODE (operands[1]) == CONST_DOUBLE) - return output_move_const_single (operands); - else if (FP_REG_P (operands[1])) - return \"fmove%.s %1,sp@-\;fpmove%.d sp@+, %0\"; - return \"fpmove%.s %x1,%x0\"; - } - if (FPA_REG_P (operands[1])) - { - if (FP_REG_P (operands[0])) - return \"fpmove%.s %x1,sp@-\;fmove%.s sp@+,%0\"; - else - return \"fpmove%.s %x1,%x0\"; - } - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - return \"f%$move%.x %1,%0\"; - else if (ADDRESS_REG_P (operands[1])) - return \"move%.l %1,%-\;f%$move%.s %+,%0\"; - else if (GET_CODE (operands[1]) == CONST_DOUBLE) - return output_move_const_single (operands); - return \"f%$move%.s %f1,%0\"; - } - if (FP_REG_P (operands[1])) - { - if (ADDRESS_REG_P (operands[0])) - return \"fmove%.s %1,%-\;move%.l %+,%0\"; - return \"fmove%.s %f1,%0\"; - } - return \"move%.l %1,%0\"; -}") - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=r,g") - (match_operand:SF 1 "general_operand" "g,r"))] - "TARGET_5200" - "* return \"move%.l %1,%0\";") - -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - "") - -(define_insn "" - [(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<>"))] - "!TARGET_5200" - "* -{ - if (which_alternative == 7) - return \"fpmove%.d %x1,fpa0\;fpmove%.d fpa0,%x0\"; - if (FPA_REG_P (operands[0])) - { - if (GET_CODE (operands[1]) == CONST_DOUBLE) - return output_move_const_double (operands); - if (FP_REG_P (operands[1])) - return \"fmove%.d %1,sp@-\;fpmove%.d sp@+,%x0\"; - return \"fpmove%.d %x1,%x0\"; - } - else if (FPA_REG_P (operands[1])) - { - if (FP_REG_P(operands[0])) - return \"fpmove%.d %x1,sp@-\;fmoved sp@+,%0\"; - else - return \"fpmove%.d %x1,%x0\"; - } - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - return \"f%&move%.x %1,%0\"; - if (REG_P (operands[1])) - { - rtx xoperands[2]; - xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); - output_asm_insn (\"move%.l %1,%-\", xoperands); - output_asm_insn (\"move%.l %1,%-\", operands); - return \"f%&move%.d %+,%0\"; - } - if (GET_CODE (operands[1]) == CONST_DOUBLE) - return output_move_const_double (operands); - return \"f%&move%.d %f1,%0\"; - } - else if (FP_REG_P (operands[1])) - { - if (REG_P (operands[0])) - { - output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands); - operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - return \"move%.l %+,%0\"; - } - else - return \"fmove%.d %f1,%0\"; - } - return output_move_double (operands); -}") - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=r,g") - (match_operand:DF 1 "general_operand" "g,r"))] - "TARGET_5200" - "* return output_move_double (operands);") - -(define_expand "movxf" - [(set (match_operand:XF 0 "nonimmediate_operand" "") - (match_operand:XF 1 "general_operand" ""))] - "" - " -{ - if (CONSTANT_P (operands[1])) - { - operands[1] = force_const_mem (XFmode, operands[1]); - if (! memory_address_p (XFmode, XEXP (operands[1], 0)) - && ! reload_in_progress) - operands[1] = change_address (operands[1], XFmode, - XEXP (operands[1], 0)); - } -}") - -(define_insn "" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,f,!r,!f") - (match_operand:XF 1 "nonimmediate_operand" "m,f,f,f,r"))] - "TARGET_68881" - "* -{ - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - return \"fmove%.x %1,%0\"; - if (REG_P (operands[1])) - { - rtx xoperands[2]; - xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2); - output_asm_insn (\"move%.l %1,%-\", xoperands); - xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); - output_asm_insn (\"move%.l %1,%-\", xoperands); - output_asm_insn (\"move%.l %1,%-\", operands); - return \"fmove%.x %+,%0\"; - } - if (GET_CODE (operands[1]) == CONST_DOUBLE) - return \"fmove%.x %1,%0\"; - return \"fmove%.x %f1,%0\"; - } - if (REG_P (operands[0])) - { - output_asm_insn (\"fmove%.x %f1,%-\;move%.l %+,%0\", operands); - operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - output_asm_insn (\"move%.l %+,%0\", operands); - operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - return \"move%.l %+,%0\"; - } - return \"fmove%.x %f1,%0\"; -} -") - -(define_insn "" - [(set (match_operand:XF 0 "nonimmediate_operand" "=rm,rf,&rof<>") - (match_operand:XF 1 "nonimmediate_operand" "rf,m,rof<>"))] - "! TARGET_68881" - "* -{ - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - return \"fmove%.x %1,%0\"; - if (REG_P (operands[1])) - { - rtx xoperands[2]; - xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 2); - output_asm_insn (\"move%.l %1,%-\", xoperands); - xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); - output_asm_insn (\"move%.l %1,%-\", xoperands); - output_asm_insn (\"move%.l %1,%-\", operands); - return \"fmove%.x %+,%0\"; - } - if (GET_CODE (operands[1]) == CONST_DOUBLE) - return \"fmove%.x %1,%0\"; - return \"fmove%.x %f1,%0\"; - } - if (FP_REG_P (operands[1])) - { - if (REG_P (operands[0])) - { - output_asm_insn (\"fmove%.x %f1,%-\;move%.l %+,%0\", operands); - operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - output_asm_insn (\"move%.l %+,%0\", operands); - operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - return \"move%.l %+,%0\"; - } - else - return \"fmove%.x %f1,%0\"; - } - return output_move_double (operands); -} -") - -(define_expand "movdi" - ;; Let's see if it really still needs to handle fp regs, and, if so, why. - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - "") - -;; movdi can apply to fp regs in some cases -(define_insn "" - ;; 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") - (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"))] -; [(set (match_operand:DI 0 "general_operand" "=rm,&rf,&ro<>,!&rm,!&f") -; (match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfF"))] - "!TARGET_5200" - "* -{ - if (which_alternative == 8) - return \"fpmove%.d %x1,fpa0\;fpmove%.d fpa0,%x0\"; - if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1])) - return \"fpmove%.d %x1,%x0\"; - if (FP_REG_P (operands[0])) - { - if (FP_REG_P (operands[1])) - return \"fmove%.x %1,%0\"; - if (REG_P (operands[1])) - { - rtx xoperands[2]; - xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); - output_asm_insn (\"move%.l %1,%-\", xoperands); - output_asm_insn (\"move%.l %1,%-\", operands); - return \"fmove%.d %+,%0\"; - } - if (GET_CODE (operands[1]) == CONST_DOUBLE) - return output_move_const_double (operands); - return \"fmove%.d %f1,%0\"; - } - else if (FP_REG_P (operands[1])) - { - if (REG_P (operands[0])) - { - output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands); - operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - return \"move%.l %+,%0\"; - } - else - return \"fmove%.d %f1,%0\"; - } - return output_move_double (operands); -}") - -(define_insn "" - [(set (match_operand:DI 0 "general_operand" "=r,g") - (match_operand:DI 1 "general_operand" "g,r"))] - "TARGET_5200" - "* return output_move_double (operands);") - -;; Thus goes after the move instructions -;; because the move instructions are better (require no spilling) -;; when they can apply. It goes before the add/sub insns -;; so we will prefer it to them. - -(define_insn "pushasi" - [(set (match_operand:SI 0 "push_operand" "=m") - (match_operand:SI 1 "address_operand" "p"))] - "" - "pea %a1") - -;; truncation instructions -(define_insn "truncsiqi2" - [(set (match_operand:QI 0 "general_operand" "=dm,d") - (truncate:QI - (match_operand:SI 1 "general_operand" "doJ,i")))] - "" - "* -{ - if (GET_CODE (operands[0]) == REG) - { - /* Must clear condition codes, since the move.l bases them on - the entire 32 bits, not just the desired 8 bits. */ - CC_STATUS_INIT; - return \"move%.l %1,%0\"; - } - if (GET_CODE (operands[1]) == MEM) - operands[1] = adj_offsettable_operand (operands[1], 3); - return \"move%.b %1,%0\"; -}") - -(define_insn "trunchiqi2" - [(set (match_operand:QI 0 "general_operand" "=dm,d") - (truncate:QI - (match_operand:HI 1 "general_operand" "doJ,i")))] - "" - "* -{ - if (GET_CODE (operands[0]) == REG - && (GET_CODE (operands[1]) == MEM - || GET_CODE (operands[1]) == CONST_INT)) - { - /* Must clear condition codes, since the move.w bases them on - the entire 16 bits, not just the desired 8 bits. */ - CC_STATUS_INIT; - return \"move%.w %1,%0\"; - } - if (GET_CODE (operands[0]) == REG) - { - /* Must clear condition codes, since the move.l bases them on - the entire 32 bits, not just the desired 8 bits. */ - CC_STATUS_INIT; - return \"move%.l %1,%0\"; - } - if (GET_CODE (operands[1]) == MEM) - operands[1] = adj_offsettable_operand (operands[1], 1); - return \"move%.b %1,%0\"; -}") - -(define_insn "truncsihi2" - [(set (match_operand:HI 0 "general_operand" "=dm,d") - (truncate:HI - (match_operand:SI 1 "general_operand" "roJ,i")))] - "" - "* -{ - if (GET_CODE (operands[0]) == REG) - { - /* Must clear condition codes, since the move.l bases them on - the entire 32 bits, not just the desired 8 bits. */ - CC_STATUS_INIT; - return \"move%.l %1,%0\"; - } - if (GET_CODE (operands[1]) == MEM) - operands[1] = adj_offsettable_operand (operands[1], 2); - return \"move%.w %1,%0\"; -}") - -;; zero extension instructions - -;; this is the canonical form for (lshiftrt:DI x 32) -(define_insn "zero_extendsidi2" - [(set (match_operand:DI 0 "general_operand" "rm") - (zero_extend:DI (match_operand:SI 1 "general_operand" "rm")))] - "" - "* -{ - CC_STATUS_INIT; - if (GET_CODE (operands[0]) == REG) - operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) - return \"move%.l %1,%0\;clr%.l %0\"; - else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC) - return \"clr%.l %0\;move%.l %1,%0\"; - 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)) - (set (strict_low_part (match_dup 2)) - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - operands[1] = make_safe_from (operands[1], operands[0]); - if (GET_CODE (operands[0]) == SUBREG) - operands[2] = gen_rtx (SUBREG, HImode, SUBREG_REG (operands[0]), - SUBREG_WORD (operands[0])); - else - operands[2] = gen_rtx (SUBREG, HImode, operands[0], 0); -}") - -(define_expand "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (const_int 0)) - (set (strict_low_part (match_dup 2)) - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - operands[1] = make_safe_from (operands[1], operands[0]); - if (GET_CODE (operands[0]) == SUBREG) - operands[2] = gen_rtx (SUBREG, QImode, SUBREG_REG (operands[0]), - SUBREG_WORD (operands[0])); - else - operands[2] = gen_rtx (SUBREG, QImode, operands[0], 0); -}") - -(define_expand "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (const_int 0)) - (set (strict_low_part (match_dup 2)) - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - operands[1] = make_safe_from (operands[1], operands[0]); - if (GET_CODE (operands[0]) == SUBREG) - operands[2] = gen_rtx (SUBREG, QImode, SUBREG_REG (operands[0]), - SUBREG_WORD (operands[0])); - else - operands[2] = gen_rtx (SUBREG, QImode, operands[0], 0); -}") - -;; Patterns to recognize zero-extend insns produced by the combiner. -;; We don't allow both operands in memory, because of aliasing problems. -;; Explicitly disallow two memory operands via the condition since reloading -;; of this case will result in worse code than the uncombined patterns. - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=do<>,d<") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))] - "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" - "* -{ - if (DATA_REG_P (operands[0])) - { - if (GET_CODE (operands[1]) == REG - && REGNO (operands[0]) == REGNO (operands[1])) - return \"and%.l %#0xFFFF,%0\"; - if (reg_mentioned_p (operands[0], operands[1])) - return \"move%.w %1,%0\;and%.l %#0xFFFF,%0\"; - return \"clr%.l %0\;move%.w %1,%0\"; - } - else if (GET_CODE (operands[0]) == MEM - && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) - return \"move%.w %1,%0\;clr%.w %0\"; - else if (GET_CODE (operands[0]) == MEM - && GET_CODE (XEXP (operands[0], 0)) == POST_INC) - return \"clr%.w %0\;move%.w %1,%0\"; - else - { - output_asm_insn (\"clr%.w %0\", operands); - operands[0] = adj_offsettable_operand (operands[0], 2); - return \"move%.w %1,%0\"; - } -}") - -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=do<>,d") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))] - "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" - "* -{ - if (DATA_REG_P (operands[0])) - { - if (GET_CODE (operands[1]) == REG - && REGNO (operands[0]) == REGNO (operands[1])) - return \"and%.w %#0xFF,%0\"; - if (reg_mentioned_p (operands[0], operands[1])) - return \"move%.b %1,%0\;and%.w %#0xFF,%0\"; - return \"clr%.w %0\;move%.b %1,%0\"; - } - else if (GET_CODE (operands[0]) == MEM - && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) - { - if (REGNO (XEXP (XEXP (operands[0], 0), 0)) - == STACK_POINTER_REGNUM) - { - output_asm_insn (\"clr%.w %-\", operands); - operands[0] = gen_rtx (MEM, GET_MODE (operands[0]), - plus_constant (stack_pointer_rtx, 1)); - return \"move%.b %1,%0\"; - } - else - return \"move%.b %1,%0\;clr%.b %0\"; - } - else if (GET_CODE (operands[0]) == MEM - && GET_CODE (XEXP (operands[0], 0)) == POST_INC) - return \"clr%.b %0\;move%.b %1,%0\"; - else - { - output_asm_insn (\"clr%.b %0\", operands); - operands[0] = adj_offsettable_operand (operands[0], 1); - return \"move%.b %1,%0\"; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=do<>,d") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))] - "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" - "* -{ - if (DATA_REG_P (operands[0])) - { - if (GET_CODE (operands[1]) == REG - && REGNO (operands[0]) == REGNO (operands[1])) - return \"and%.l %#0xFF,%0\"; - if (reg_mentioned_p (operands[0], operands[1])) - return \"move%.b %1,%0\;and%.l %#0xFF,%0\"; - return \"clr%.l %0\;move%.b %1,%0\"; - } - else if (GET_CODE (operands[0]) == MEM - && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) - { - operands[0] = XEXP (XEXP (operands[0], 0), 0); -#ifdef MOTOROLA -#ifdef SGS - return \"clr%.l -(%0)\;move%.b %1,3(%0)\"; -#else - return \"clr%.l -(%0)\;move%.b %1,(3,%0)\"; -#endif -#else - return \"clrl %0@-\;moveb %1,%0@(3)\"; -#endif - } - else if (GET_CODE (operands[0]) == MEM - && GET_CODE (XEXP (operands[0], 0)) == POST_INC) - { - operands[0] = XEXP (XEXP (operands[0], 0), 0); -#ifdef MOTOROLA -#ifdef SGS - return \"clr%.l (%0)+\;move%.b %1,-1(%0)\"; -#else - return \"clr%.l (%0)+\;move%.b %1,(-1,%0)\"; -#endif -#else - return \"clrl %0@+\;moveb %1,%0@(-1)\"; -#endif - } - else - { - output_asm_insn (\"clr%.l %0\", operands); - operands[0] = adj_offsettable_operand (operands[0], 3); - return \"move%.b %1,%0\"; - } -}") - -;; 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 || TARGET_5200) - 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\;move%.l %2,%0\;smi %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 || TARGET_5200) - 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 || TARGET_5200) - 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 (GET_CODE (operands[1]) == REG - && REGNO (operands[1]) == REGNO (operands[3])) - output_asm_insn (\"add%.l %2,%3\", operands); - else - output_asm_insn (\"move%.l %2,%3\;add%.l %1,%3\", operands); - if (TARGET_68020 || TARGET_5200) - return \"smi %0\;extb%.l %0\"; - else - return \"smi %0\;ext%.w %0\;ext%.l %0\"; -}") - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "general_operand" "=*d,a") - (sign_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "0,rm")))] - "" - "* -{ - if (ADDRESS_REG_P (operands[0])) - return \"move%.w %1,%0\"; - return \"ext%.l %0\"; -}") - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "general_operand" "=d") - (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0")))] - "" - "ext%.w %0") - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "general_operand" "=d") - (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0")))] - "TARGET_68020 || TARGET_5200" - "extb%.l %0") - -;; Conversions between float and double. - -(define_expand "extendsfdf2" - [(set (match_operand:DF 0 "general_operand" "") - (float_extend:DF - (match_operand:SF 1 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=x,y") - (float_extend:DF - (match_operand:SF 1 "general_operand" "xH,rmF")))] - "TARGET_FPA" - "fpstod %w1,%0") - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=*fdm,f") - (float_extend:DF - (match_operand:SF 1 "general_operand" "f,dmF")))] - "TARGET_68881" - "* -{ - if (FP_REG_P (operands[0]) && FP_REG_P (operands[1])) - { - if (REGNO (operands[0]) == REGNO (operands[1])) - { - /* Extending float to double in an fp-reg is a no-op. - NOTICE_UPDATE_CC has already assumed that the - cc will be set. So cancel what it did. */ - cc_status = cc_prev_status; - return \"\"; - } - return \"f%&move%.x %1,%0\"; - } - if (FP_REG_P (operands[0])) - return \"f%&move%.s %f1,%0\"; - if (DATA_REG_P (operands[0]) && FP_REG_P (operands[1])) - { - output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands); - operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - return \"move%.l %+,%0\"; - } - return \"fmove%.d %f1,%0\"; -}") - -;; This cannot output into an f-reg because there is no way to be -;; sure of truncating in that case. -;; But on the Sun FPA, we can be sure. -(define_expand "truncdfsf2" - [(set (match_operand:SF 0 "general_operand" "") - (float_truncate:SF - (match_operand:DF 1 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=x,y") - (float_truncate:SF - (match_operand:DF 1 "general_operand" "xH,rmF")))] - "TARGET_FPA" - "fpdtos %y1,%0") - -;; On the '040 we can truncate in a register accurately and easily. -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=f") - (float_truncate:SF - (match_operand:DF 1 "general_operand" "fmG")))] - "TARGET_68040_ONLY" - "* -{ - if (FP_REG_P (operands[1])) - return \"f%$move%.x %1,%0\"; - return \"f%$move%.d %f1,%0\"; -}") - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=dm") - (float_truncate:SF - (match_operand:DF 1 "general_operand" "f")))] - "TARGET_68881" - "fmove%.s %f1,%0") - -;; Conversion between fixed point and floating point. -;; Note that among the fix-to-float insns -;; the ones that start with SImode come first. -;; That is so that an operand that is a CONST_INT -;; (and therefore lacks a specific machine mode). -;; will be recognized as SImode (which is always valid) -;; rather than as QImode or HImode. - -(define_expand "floatsisf2" - [(set (match_operand:SF 0 "general_operand" "") - (float:SF (match_operand:SI 1 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=y,x") - (float:SF (match_operand:SI 1 "general_operand" "rmi,x")))] - "TARGET_FPA" - "fpltos %1,%0") - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=f") - (float:SF (match_operand:SI 1 "general_operand" "dmi")))] - "TARGET_68881" - "f%$move%.l %1,%0") - -(define_expand "floatsidf2" - [(set (match_operand:DF 0 "general_operand" "") - (float:DF (match_operand:SI 1 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=y,x") - (float:DF (match_operand:SI 1 "general_operand" "rmi,x")))] - "TARGET_FPA" - "fpltod %1,%0") - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=f") - (float:DF (match_operand:SI 1 "general_operand" "dmi")))] - "TARGET_68881" - "f%&move%.l %1,%0") - -(define_insn "floathisf2" - [(set (match_operand:SF 0 "general_operand" "=f") - (float:SF (match_operand:HI 1 "general_operand" "dmn")))] - "TARGET_68881" - "f%$move%.w %1,%0") - -(define_insn "floathidf2" - [(set (match_operand:DF 0 "general_operand" "=f") - (float:DF (match_operand:HI 1 "general_operand" "dmn")))] - "TARGET_68881" - "fmove%.w %1,%0") - -(define_insn "floatqisf2" - [(set (match_operand:SF 0 "general_operand" "=f") - (float:SF (match_operand:QI 1 "general_operand" "dmn")))] - "TARGET_68881" - "fmove%.b %1,%0") - -(define_insn "floatqidf2" - [(set (match_operand:DF 0 "general_operand" "=f") - (float:DF (match_operand:QI 1 "general_operand" "dmn")))] - "TARGET_68881" - "f%&move%.b %1,%0") - -;; New routines to convert floating-point values to integers -;; to be used on the '040. These should be faster than trapping -;; into the kernel to emulate fintrz. They should also be faster -;; than calling the subroutines fixsfsi or fixdfsi. - -(define_insn "fix_truncdfsi2" - [(set (match_operand:SI 0 "general_operand" "=dm") - (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f")))) - (clobber (match_scratch:SI 2 "=d")) - (clobber (match_scratch:SI 3 "=d"))] - "TARGET_68881 && TARGET_68040" - "* -{ - CC_STATUS_INIT; - return \"fmovem%.l %!,%2\;moveq %#16,%3\;or%.l %2,%3\;and%.w %#-33,%3\;fmovem%.l %3,%!\;fmove%.l %1,%0\;fmovem%.l %2,%!\"; -}") - -(define_insn "fix_truncdfhi2" - [(set (match_operand:HI 0 "general_operand" "=dm") - (fix:HI (fix:DF (match_operand:DF 1 "register_operand" "f")))) - (clobber (match_scratch:SI 2 "=d")) - (clobber (match_scratch:SI 3 "=d"))] - "TARGET_68881 && TARGET_68040" - "* -{ - CC_STATUS_INIT; - return \"fmovem%.l %!,%2\;moveq %#16,%3\;or%.l %2,%3\;and%.w %#-33,%3\;fmovem%.l %3,%!\;fmove%.w %1,%0\;fmovem%.l %2,%!\"; -}") - -(define_insn "fix_truncdfqi2" - [(set (match_operand:QI 0 "general_operand" "=dm") - (fix:QI (fix:DF (match_operand:DF 1 "register_operand" "f")))) - (clobber (match_scratch:SI 2 "=d")) - (clobber (match_scratch:SI 3 "=d"))] - "TARGET_68881 && TARGET_68040" - "* -{ - CC_STATUS_INIT; - return \"fmovem%.l %!,%2\;moveq %#16,%3\;or%.l %2,%3\;and%.w %#-33,%3\;fmovem%.l %3,%!\;fmove%.b %1,%0\;fmovem%.l %2,%!\"; -}") - -;; Convert a float to a float whose value is an integer. -;; This is the first stage of converting it to an integer type. - -(define_insn "ftruncdf2" - [(set (match_operand:DF 0 "general_operand" "=f") - (fix:DF (match_operand:DF 1 "general_operand" "fFm")))] - "TARGET_68881 && !TARGET_68040" - "* -{ - if (FP_REG_P (operands[1])) - return \"fintrz%.x %f1,%0\"; - return \"fintrz%.d %f1,%0\"; -}") - -(define_insn "ftruncsf2" - [(set (match_operand:SF 0 "general_operand" "=f") - (fix:SF (match_operand:SF 1 "general_operand" "dfFm")))] - "TARGET_68881 && !TARGET_68040" - "* -{ - if (FP_REG_P (operands[1])) - return \"fintrz%.x %f1,%0\"; - return \"fintrz%.s %f1,%0\"; -}") - -;; Convert a float whose value is an integer -;; to an actual integer. Second stage of converting float to integer type. -(define_insn "fixsfqi2" - [(set (match_operand:QI 0 "general_operand" "=dm") - (fix:QI (match_operand:SF 1 "general_operand" "f")))] - "TARGET_68881" - "fmove%.b %1,%0") - -(define_insn "fixsfhi2" - [(set (match_operand:HI 0 "general_operand" "=dm") - (fix:HI (match_operand:SF 1 "general_operand" "f")))] - "TARGET_68881" - "fmove%.w %1,%0") - -(define_insn "fixsfsi2" - [(set (match_operand:SI 0 "general_operand" "=dm") - (fix:SI (match_operand:SF 1 "general_operand" "f")))] - "TARGET_68881" - "fmove%.l %1,%0") - -(define_insn "fixdfqi2" - [(set (match_operand:QI 0 "general_operand" "=dm") - (fix:QI (match_operand:DF 1 "general_operand" "f")))] - "TARGET_68881" - "fmove%.b %1,%0") - -(define_insn "fixdfhi2" - [(set (match_operand:HI 0 "general_operand" "=dm") - (fix:HI (match_operand:DF 1 "general_operand" "f")))] - "TARGET_68881" - "fmove%.w %1,%0") - -(define_insn "fixdfsi2" - [(set (match_operand:SI 0 "general_operand" "=dm") - (fix:SI (match_operand:DF 1 "general_operand" "f")))] - "TARGET_68881" - "fmove%.l %1,%0") - -;; Convert a float to an integer. -;; On the Sun FPA, this is done in one step. - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=x,y") - (fix:SI (fix:SF (match_operand:SF 1 "general_operand" "xH,rmF"))))] - "TARGET_FPA" - "fpstol %w1,%0") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=x,y") - (fix:SI (fix:DF (match_operand:DF 1 "general_operand" "xH,rmF"))))] - "TARGET_FPA" - "fpdtol %y1,%0") - -;; add instructions - -(define_insn "adddi_lshrdi_63" - [(set (match_operand:DI 0 "general_operand" "=d") - (plus:DI (lshiftrt:DI (match_operand:DI 1 "general_operand" "rm") - (const_int 63)) - (match_dup 1))) - (clobber (match_scratch:SI 2 "=d"))] - "" - "* -{ - operands[3] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - if (REG_P (operands[1]) && REGNO (operands[1]) == REGNO (operands[0])) - return - \"move%.l %1,%2\;add%.l %2,%2\;subx%.l %2,%2\;sub%.l %2,%3\;subx%.l %2,%0\"; - if (GET_CODE (operands[1]) == REG) - operands[4] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); - else if (GET_CODE (XEXP (operands[1], 0)) == POST_INC - || GET_CODE (XEXP (operands[1], 0)) == PRE_DEC) - operands[4] = operands[1]; - else - operands[4] = adj_offsettable_operand (operands[1], 4); - if (GET_CODE (operands[1]) == MEM - && GET_CODE (XEXP (operands[1], 0)) == PRE_DEC) - output_asm_insn (\"move%.l %4,%3\", operands); - output_asm_insn (\"move%.l %1,%0\;smi %2\", operands); - if (TARGET_68020 || TARGET_5200) - output_asm_insn (\"extb%.l %2\", operands); - else - output_asm_insn (\"ext%.w %2\;ext%.l %2\", operands); - if (GET_CODE (operands[1]) != MEM - || GET_CODE (XEXP (operands[1], 0)) != PRE_DEC) - output_asm_insn (\"move%.l %4,%3\", operands); - return \"sub%.l %2,%3\;subx%.l %2,%0\"; -}") - -(define_insn "adddi_sexthishl32" - [(set (match_operand:DI 0 "general_operand" "=o,a,*d,*d") - (plus:DI (ashift:DI (sign_extend:DI - (match_operand:HI 1 "general_operand" "rm,rm,rm,rm")) - (const_int 32)) - (match_operand:DI 2 "general_operand" "0,0,0,0"))) - (clobber (match_scratch:SI 3 "=&d,X,a,?d"))] - "!TARGET_5200" - "* -{ - CC_STATUS_INIT; - if (ADDRESS_REG_P (operands[0])) - return \"add%.w %1,%0\"; - else if (ADDRESS_REG_P (operands[3])) - return \"move%.w %1,%3\;add%.l %3,%0\"; - else - return \"move%.w %1,%3\;ext%.l %3\;add%.l %3,%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" "=<,o<>,d,d,d") - (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0,0") - (match_operand:DI 2 "general_operand" "<,d,o>,d,a"))) - (clobber (match_scratch:SI 3 "=X,&d,&d,X,&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, -;; so commutativity won't apply to them. -(define_insn "addsi3" - [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,r") - (plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0") - (match_operand:SI 2 "general_operand" "dIKLs,rJK,a,mrIKLs")))] - "" - "* -{ - if (! operands_match_p (operands[0], operands[1])) - { - if (!ADDRESS_REG_P (operands[1])) - { - rtx tmp = operands[1]; - - operands[1] = operands[2]; - operands[2] = tmp; - } - - /* These insns can result from reloads to access - stack slots over 64k from the frame pointer. */ - if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) + 0x8000 >= (unsigned) 0x10000) - return \"move%.l %2,%0\;add%.l %1,%0\"; -#ifdef SGS - if (GET_CODE (operands[2]) == REG) - return \"lea 0(%1,%2.l),%0\"; - else - return \"lea %c2(%1),%0\"; -#else /* not SGS */ -#ifdef MOTOROLA - if (GET_CODE (operands[2]) == REG) - return \"lea (%1,%2.l),%0\"; - else - return \"lea (%c2,%1),%0\"; -#else /* not MOTOROLA (MIT syntax) */ - if (GET_CODE (operands[2]) == REG) - return \"lea %1@(0,%2:l),%0\"; - else - return \"lea %1@(%c2),%0\"; -#endif /* not MOTOROLA */ -#endif /* not SGS */ - } - if (GET_CODE (operands[2]) == CONST_INT) - { -#ifndef NO_ADDSUB_Q - if (INTVAL (operands[2]) > 0 - && INTVAL (operands[2]) <= 8) - return \"addq%.l %2,%0\"; - if (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) >= -8) - { - operands[2] = gen_rtx (CONST_INT, VOIDmode, - - INTVAL (operands[2])); - return \"subq%.l %2,%0\"; - } - /* On the CPU32 it is faster to use two addql instructions to - add a small integer (8 < N <= 16) to a register. - Likewise for subql. */ - if (TARGET_CPU32 && REG_P (operands[0])) - { - if (INTVAL (operands[2]) > 8 - && INTVAL (operands[2]) <= 16) - { - operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]) - 8); - return \"addq%.l %#8,%0\;addq%.l %2,%0\"; - } - if (INTVAL (operands[2]) < -8 - && INTVAL (operands[2]) >= -16) - { - operands[2] = gen_rtx (CONST_INT, VOIDmode, - - INTVAL (operands[2]) - 8); - return \"subq%.l %#8,%0\;subq%.l %2,%0\"; - } - } -#endif - if (ADDRESS_REG_P (operands[0]) - && INTVAL (operands[2]) >= -0x8000 - && INTVAL (operands[2]) < 0x8000) - { - if (TARGET_68040) - return \"add%.w %2,%0\"; - else -#ifdef MOTOROLA - return \"lea (%c2,%0),%0\"; -#else - return \"lea %0@(%c2),%0\"; -#endif - } - } - return \"add%.l %2,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=a") - (plus:SI (match_operand:SI 1 "general_operand" "0") - (sign_extend:SI - (match_operand:HI 2 "nonimmediate_operand" "rm"))))] - "!TARGET_5200" - "add%.w %2,%0") - -(define_insn "addhi3" - [(set (match_operand:HI 0 "general_operand" "=m,r") - (plus:HI (match_operand:HI 1 "general_operand" "%0,0") - (match_operand:HI 2 "general_operand" "dn,rmn")))] - "!TARGET_5200" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT) - { -#ifndef NO_ADDSUB_Q - /* If the constant would be a negative number when interpreted as - HImode, make it negative. This is usually, but not always, done - elsewhere in the compiler. First check for constants out of range, - which could confuse us. */ - - if (INTVAL (operands[2]) >= 32768) - operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]) - 65536); - - if (INTVAL (operands[2]) > 0 - && INTVAL (operands[2]) <= 8) - return \"addq%.w %2,%0\"; - if (INTVAL (operands[2]) < 0 - && INTVAL (operands[2]) >= -8) - { - operands[2] = gen_rtx (CONST_INT, VOIDmode, - - INTVAL (operands[2])); - return \"subq%.w %2,%0\"; - } - /* On the CPU32 it is faster to use two addqw instructions to - add a small integer (8 < N <= 16) to a register. - Likewise for subqw. */ - if (TARGET_CPU32 && REG_P (operands[0])) - { - if (INTVAL (operands[2]) > 8 - && INTVAL (operands[2]) <= 16) - { - operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]) - 8); - return \"addq%.w %#8,%0\;addq%.w %2,%0\"; - } - if (INTVAL (operands[2]) < -8 - && INTVAL (operands[2]) >= -16) - { - operands[2] = gen_rtx (CONST_INT, VOIDmode, - - INTVAL (operands[2]) - 8); - return \"subq%.w %#8,%0\;subq%.w %2,%0\"; - } - } -#endif - if (ADDRESS_REG_P (operands[0]) && !TARGET_68040) -#ifdef MOTOROLA - return \"lea (%c2,%0),%0\"; -#else - return \"lea %0@(%c2),%0\"; -#endif - } - return \"add%.w %2,%0\"; -}") - -;; These insns must use MATCH_DUP instead of the more expected -;; use of a matching constraint because the "output" here is also -;; an input, so you can't use the matching constraint. That also means -;; that you can't use the "%", so you need patterns with the matched -;; operand in both positions. - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) - (plus:HI (match_dup 0) - (match_operand:HI 1 "general_operand" "dn,rmn")))] - "!TARGET_5200" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - { -#ifndef NO_ADDSUB_Q - /* If the constant would be a negative number when interpreted as - HImode, make it negative. This is usually, but not always, done - elsewhere in the compiler. First check for constants out of range, - which could confuse us. */ - - if (INTVAL (operands[1]) >= 32768) - operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]) - 65536); - - if (INTVAL (operands[1]) > 0 - && INTVAL (operands[1]) <= 8) - return \"addq%.w %1,%0\"; - if (INTVAL (operands[1]) < 0 - && INTVAL (operands[1]) >= -8) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, - - INTVAL (operands[1])); - return \"subq%.w %1,%0\"; - } - /* On the CPU32 it is faster to use two addqw instructions to - add a small integer (8 < N <= 16) to a register. - Likewise for subqw. */ - if (TARGET_CPU32 && REG_P (operands[0])) - { - if (INTVAL (operands[1]) > 8 - && INTVAL (operands[1]) <= 16) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]) - 8); - return \"addq%.w %#8,%0\;addq%.w %1,%0\"; - } - if (INTVAL (operands[1]) < -8 - && INTVAL (operands[1]) >= -16) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, - - INTVAL (operands[1]) - 8); - return \"subq%.w %#8,%0\;subq%.w %1,%0\"; - } - } -#endif - if (ADDRESS_REG_P (operands[0]) && !TARGET_68040) -#ifdef MOTOROLA - return \"lea (%c1,%0),%0\"; -#else - return \"lea %0@(%c1),%0\"; -#endif - } - return \"add%.w %1,%0\"; -}") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) - (plus:HI (match_operand:HI 1 "general_operand" "dn,rmn") - (match_dup 0)))] - "!TARGET_5200" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - { -#ifndef NO_ADDSUB_Q - /* If the constant would be a negative number when interpreted as - HImode, make it negative. This is usually, but not always, done - elsewhere in the compiler. First check for constants out of range, - which could confuse us. */ - - if (INTVAL (operands[1]) >= 32768) - operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]) - 65536); - - if (INTVAL (operands[1]) > 0 - && INTVAL (operands[1]) <= 8) - return \"addq%.w %1,%0\"; - if (INTVAL (operands[1]) < 0 - && INTVAL (operands[1]) >= -8) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, - - INTVAL (operands[1])); - return \"subq%.w %1,%0\"; - } - /* On the CPU32 it is faster to use two addqw instructions to - add a small integer (8 < N <= 16) to a register. - Likewise for subqw. */ - if (TARGET_CPU32 && REG_P (operands[0])) - { - if (INTVAL (operands[1]) > 8 - && INTVAL (operands[1]) <= 16) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]) - 8); - return \"addq%.w %#8,%0\;addq%.w %1,%0\"; - } - if (INTVAL (operands[1]) < -8 - && INTVAL (operands[1]) >= -16) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, - - INTVAL (operands[1]) - 8); - return \"subq%.w %#8,%0\;subq%.w %1,%0\"; - } - } -#endif - if (ADDRESS_REG_P (operands[0]) && !TARGET_68040) -#ifdef MOTOROLA - return \"lea (%c1,%0),%0\"; -#else - return \"lea %0@(%c1),%0\"; -#endif - } - return \"add%.w %1,%0\"; -}") - -(define_insn "addqi3" - [(set (match_operand:QI 0 "general_operand" "=m,d") - (plus:QI (match_operand:QI 1 "general_operand" "%0,0") - (match_operand:QI 2 "general_operand" "dn,dmn")))] - "!TARGET_5200" - "* -{ -#ifndef NO_ADDSUB_Q - if (GET_CODE (operands[2]) == CONST_INT) - { - if (INTVAL (operands[2]) >= 128) - operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]) - 256); - - if (INTVAL (operands[2]) > 0 - && INTVAL (operands[2]) <= 8) - return \"addq%.b %2,%0\"; - if (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) >= -8) - { - operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2])); - return \"subq%.b %2,%0\"; - } - } -#endif - return \"add%.b %2,%0\"; -}") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d")) - (plus:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "dn,dmn")))] - "!TARGET_5200" - "* -{ -#ifndef NO_ADDSUB_Q - if (GET_CODE (operands[1]) == CONST_INT) - { - if (INTVAL (operands[1]) >= 128) - operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]) - 256); - - if (INTVAL (operands[1]) > 0 - && INTVAL (operands[1]) <= 8) - return \"addq%.b %1,%0\"; - if (INTVAL (operands[1]) < 0 && INTVAL (operands[1]) >= -8) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1])); - return \"subq%.b %1,%0\"; - } - } -#endif - return \"add%.b %1,%0\"; -}") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d")) - (plus:QI (match_operand:QI 1 "general_operand" "dn,dmn") - (match_dup 0)))] - "!TARGET_5200" - "* -{ -#ifndef NO_ADDSUB_Q - if (GET_CODE (operands[1]) == CONST_INT) - { - if (INTVAL (operands[1]) >= 128) - operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]) - 256); - - if (INTVAL (operands[1]) > 0 - && INTVAL (operands[1]) <= 8) - return \"addq%.b %1,%0\"; - if (INTVAL (operands[1]) < 0 && INTVAL (operands[1]) >= -8) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1])); - return \"subq%.b %1,%0\"; - } - } -#endif - return \"add%.b %1,%0\"; -}") - -(define_expand "adddf3" - [(set (match_operand:DF 0 "general_operand" "") - (plus:DF (match_operand:DF 1 "general_operand" "") - (match_operand:DF 2 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=x,y") - (plus:DF (match_operand:DF 1 "general_operand" "%xH,y") - (match_operand:DF 2 "general_operand" "xH,dmF")))] - "TARGET_FPA" - "* -{ - if (rtx_equal_p (operands[0], operands[1])) - return \"fpadd%.d %y2,%0\"; - if (rtx_equal_p (operands[0], operands[2])) - return \"fpadd%.d %y1,%0\"; - if (which_alternative == 0) - return \"fpadd3%.d %w2,%w1,%0\"; - return \"fpadd3%.d %x2,%x1,%0\"; -}") - -(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" - "* -{ - if (REG_P (operands[2])) - return \"f%&add%.x %2,%0\"; - return \"f%&add%.d %f2,%0\"; -}") - -(define_expand "addsf3" - [(set (match_operand:SF 0 "general_operand" "") - (plus:SF (match_operand:SF 1 "general_operand" "") - (match_operand:SF 2 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=x,y") - (plus:SF (match_operand:SF 1 "general_operand" "%xH,y") - (match_operand:SF 2 "general_operand" "xH,rmF")))] - "TARGET_FPA" - "* -{ - if (rtx_equal_p (operands[0], operands[1])) - return \"fpadd%.s %w2,%0\"; - if (rtx_equal_p (operands[0], operands[2])) - return \"fpadd%.s %w1,%0\"; - if (which_alternative == 0) - return \"fpadd3%.s %w2,%w1,%0\"; - return \"fpadd3%.s %2,%1,%0\"; -}") - -(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" - "* -{ - if (REG_P (operands[2]) && ! DATA_REG_P (operands[2])) - return \"f%$add%.x %2,%0\"; - return \"f%$add%.s %f2,%0\"; -}") - -;; subtract instructions - -(define_insn "subdi_sexthishl32" - [(set (match_operand:DI 0 "general_operand" "=o,a,*d,*d") - (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0") - (ashift:DI (sign_extend:DI (match_operand:HI 2 "general_operand" "rm,rm,rm,rm")) - (const_int 32)))) - (clobber (match_scratch:SI 3 "=&d,X,a,?d"))] - "!TARGET_5200" - "* -{ - CC_STATUS_INIT; - if (ADDRESS_REG_P (operands[0])) - return \"sub%.w %2,%0\"; - else if (ADDRESS_REG_P (operands[3])) - return \"move%.w %2,%3\;sub%.l %3,%0\"; - else - return \"move%.w %2,%3\;ext%.l %3\;sub%.l %3,%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" "=<,o<>,d,d,d") - (minus:DI (match_operand:DI 1 "general_operand" "0,0,0,0,0") - (match_operand:DI 2 "general_operand" "<,d,o>,d,a"))) - (clobber (match_scratch:SI 3 "=X,&d,&d,X,&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") - (match_operand:SI 2 "general_operand" "ds,mrs")))] - "" - "sub%.l %2,%0") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=a") - (minus:SI (match_operand:SI 1 "general_operand" "0") - (sign_extend:SI - (match_operand:HI 2 "nonimmediate_operand" "rm"))))] - "!TARGET_5200" - "sub%.w %2,%0") - -(define_insn "subhi3" - [(set (match_operand:HI 0 "general_operand" "=m,r") - (minus:HI (match_operand:HI 1 "general_operand" "0,0") - (match_operand:HI 2 "general_operand" "dn,rmn")))] - "!TARGET_5200" - "sub%.w %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) - (minus:HI (match_dup 0) - (match_operand:HI 1 "general_operand" "dn,rmn")))] - "!TARGET_5200" - "sub%.w %1,%0") - -(define_insn "subqi3" - [(set (match_operand:QI 0 "general_operand" "=m,d") - (minus:QI (match_operand:QI 1 "general_operand" "0,0") - (match_operand:QI 2 "general_operand" "dn,dmn")))] - "!TARGET_5200" - "sub%.b %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d")) - (minus:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "dn,dmn")))] - "!TARGET_5200" - "sub%.b %1,%0") - -(define_expand "subdf3" - [(set (match_operand:DF 0 "general_operand" "") - (minus:DF (match_operand:DF 1 "general_operand" "") - (match_operand:DF 2 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=x,y,y") - (minus:DF (match_operand:DF 1 "general_operand" "xH,y,dmF") - (match_operand:DF 2 "general_operand" "xH,dmF,0")))] - "TARGET_FPA" - "* -{ - if (rtx_equal_p (operands[0], operands[2])) - return \"fprsub%.d %y1,%0\"; - if (rtx_equal_p (operands[0], operands[1])) - return \"fpsub%.d %y2,%0\"; - if (which_alternative == 0) - return \"fpsub3%.d %w2,%w1,%0\"; - return \"fpsub3%.d %x2,%x1,%0\"; -}") - -(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" - "* -{ - if (REG_P (operands[2])) - return \"f%&sub%.x %2,%0\"; - return \"f%&sub%.d %f2,%0\"; -}") - -(define_expand "subsf3" - [(set (match_operand:SF 0 "general_operand" "") - (minus:SF (match_operand:SF 1 "general_operand" "") - (match_operand:SF 2 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=x,y,y") - (minus:SF (match_operand:SF 1 "general_operand" "xH,y,rmF") - (match_operand:SF 2 "general_operand" "xH,rmF,0")))] - "TARGET_FPA" - "* -{ - if (rtx_equal_p (operands[0], operands[2])) - return \"fprsub%.s %w1,%0\"; - if (rtx_equal_p (operands[0], operands[1])) - return \"fpsub%.s %w2,%0\"; - if (which_alternative == 0) - return \"fpsub3%.s %w2,%w1,%0\"; - return \"fpsub3%.s %2,%1,%0\"; -}") - -(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" - "* -{ - if (REG_P (operands[2]) && ! DATA_REG_P (operands[2])) - return \"f%$sub%.x %2,%0\"; - return \"f%$sub%.s %f2,%0\"; -}") - -;; multiply instructions - -(define_insn "mulhi3" - [(set (match_operand:HI 0 "general_operand" "=d") - (mult:HI (match_operand:HI 1 "general_operand" "%0") - (match_operand:HI 2 "general_operand" "dmn")))] - "" - "* -{ -#if defined(MOTOROLA) && !defined(CRDS) - return \"muls%.w %2,%0\"; -#else - return \"muls %2,%0\"; -#endif -}") - -(define_insn "mulhisi3" - [(set (match_operand:SI 0 "general_operand" "=d") - (mult:SI (sign_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "%0")) - (sign_extend:SI - (match_operand:HI 2 "nonimmediate_operand" "dm"))))] - "" - "* -{ -#if defined(MOTOROLA) && !defined(CRDS) - return \"muls%.w %2,%0\"; -#else - return \"muls %2,%0\"; -#endif -}") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d") - (mult:SI (sign_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "%0")) - (match_operand:SI 2 "const_int_operand" "n")))] - "INTVAL (operands[2]) >= -0x8000 && INTVAL (operands[2]) <= 0x7fff" - "* -{ -#if defined(MOTOROLA) && !defined(CRDS) - return \"muls%.w %2,%0\"; -#else - return \"muls %2,%0\"; -#endif -}") - -(define_expand "mulsi3" - [(set (match_operand:SI 0 "general_operand" "") - (mult:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "TARGET_68020 || TARGET_5200" - "") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d") - (mult:SI (match_operand:SI 1 "general_operand" "%0") - (match_operand:SI 2 "general_operand" "dmsK")))] - "TARGET_68020" - "muls%.l %2,%0") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d") - (mult:SI (match_operand:SI 1 "general_operand" "%0") - (match_operand:SI 2 "general_operand" "d<>")))] - "TARGET_5200" - "muls%.l %2,%0") - -(define_insn "umulhisi3" - [(set (match_operand:SI 0 "general_operand" "=d") - (mult:SI (zero_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "%0")) - (zero_extend:SI - (match_operand:HI 2 "nonimmediate_operand" "dm"))))] - "" - "* -{ -#if defined(MOTOROLA) && !defined(CRDS) - return \"mulu%.w %2,%0\"; -#else - return \"mulu %2,%0\"; -#endif -}") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d") - (mult:SI (zero_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "%0")) - (match_operand:SI 2 "const_int_operand" "n")))] - "INTVAL (operands[2]) >= 0 && INTVAL (operands[2]) <= 0xffff" - "* -{ -#if defined(MOTOROLA) && !defined(CRDS) - return \"mulu%.w %2,%0\"; -#else - return \"mulu %2,%0\"; -#endif -}") - -;; We need a separate DEFINE_EXPAND for u?mulsidi3 to be able to use the -;; proper matching constraint. This is because the matching is between -;; the high-numbered word of the DImode operand[0] and operand[1]. -(define_expand "umulsidi3" - [(parallel - [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 1) - (mult:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonimmediate_operand" ""))) - (set (subreg:SI (match_dup 0) 0) - (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1)) - (zero_extend:DI (match_dup 2))) - (const_int 32))))])] - "TARGET_68020 && !TARGET_68060 && !TARGET_5200" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (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 (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1)) - (zero_extend:DI (match_dup 2))) - (const_int 32))))] - "TARGET_68020 && !TARGET_68060 && !TARGET_5200" - "mulu%.l %2,%3:%0") - -; Match immediate case. For 2.4 only match things < 2^31. -; It's tricky with larger values in these patterns since we need to match -; values between the two parallel multiplies, between a CONST_DOUBLE and -; a CONST_INT. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (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 (lshiftrt:DI (mult:DI (zero_extend:DI (match_dup 1)) - (match_dup 2)) - (const_int 32))))] - "TARGET_68020 && !TARGET_68060 && !TARGET_5200 - && (unsigned) INTVAL (operands[2]) <= 0x7fffffff" - "mulu%.l %2,%3:%0") - -(define_expand "mulsidi3" - [(parallel - [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 1) - (mult:SI (match_operand:SI 1 "register_operand" "") - (match_operand:SI 2 "nonimmediate_operand" ""))) - (set (subreg:SI (match_dup 0) 0) - (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1)) - (sign_extend:DI (match_dup 2))) - (const_int 32))))])] - "TARGET_68020 && !TARGET_68060 && !TARGET_5200" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (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 (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1)) - (sign_extend:DI (match_dup 2))) - (const_int 32))))] - "TARGET_68020 && !TARGET_68060 && !TARGET_5200" - "muls%.l %2,%3:%0") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (mult:SI (match_operand:SI 1 "register_operand" "%0") - (match_operand:SI 2 "const_sint32_operand" ""))) - (set (match_operand:SI 3 "register_operand" "=d") - (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_dup 1)) - (match_dup 2)) - (const_int 32))))] - "TARGET_68020 && !TARGET_68060 && !TARGET_5200" - "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 && !TARGET_68060 && !TARGET_5200" - " -{ - 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 && !TARGET_68060 && !TARGET_5200" - "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 && !TARGET_68060 && !TARGET_5200" - "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 && !TARGET_68060 && !TARGET_5200" - " -{ - 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 && !TARGET_68060 && !TARGET_5200" - "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 && !TARGET_68060 && !TARGET_5200" - "muls%.l %3,%0:%1") - -(define_expand "muldf3" - [(set (match_operand:DF 0 "general_operand" "") - (mult:DF (match_operand:DF 1 "general_operand" "") - (match_operand:DF 2 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=x,y") - (mult:DF (match_operand:DF 1 "general_operand" "%xH,y") - (match_operand:DF 2 "general_operand" "xH,rmF")))] - "TARGET_FPA" - "* -{ - if (rtx_equal_p (operands[1], operands[2])) - return \"fpsqr%.d %y1,%0\"; - if (rtx_equal_p (operands[0], operands[1])) - return \"fpmul%.d %y2,%0\"; - if (rtx_equal_p (operands[0], operands[2])) - return \"fpmul%.d %y1,%0\"; - if (which_alternative == 0) - return \"fpmul3%.d %w2,%w1,%0\"; - return \"fpmul3%.d %x2,%x1,%0\"; -}") - -(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" - "* -{ - if (GET_CODE (operands[2]) == CONST_DOUBLE - && floating_exact_log2 (operands[2]) && !TARGET_68040 && !TARGET_68060) - { - int i = floating_exact_log2 (operands[2]); - operands[2] = gen_rtx (CONST_INT, VOIDmode, i); - return \"fscale%.l %2,%0\"; - } - if (REG_P (operands[2])) - return \"f%&mul%.x %2,%0\"; - return \"f%&mul%.d %f2,%0\"; -}") - -(define_expand "mulsf3" - [(set (match_operand:SF 0 "general_operand" "") - (mult:SF (match_operand:SF 1 "general_operand" "") - (match_operand:SF 2 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=x,y") - (mult:SF (match_operand:SF 1 "general_operand" "%xH,y") - (match_operand:SF 2 "general_operand" "xH,rmF")))] - "TARGET_FPA" - "* -{ - if (rtx_equal_p (operands[1], operands[2])) - return \"fpsqr%.s %w1,%0\"; - if (rtx_equal_p (operands[0], operands[1])) - return \"fpmul%.s %w2,%0\"; - if (rtx_equal_p (operands[0], operands[2])) - return \"fpmul%.s %w1,%0\"; - if (which_alternative == 0) - return \"fpmul3%.s %w2,%w1,%0\"; - return \"fpmul3%.s %2,%1,%0\"; -}") - -(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" - "* -{ -#ifdef FSGLMUL_USE_S - if (REG_P (operands[2]) && ! DATA_REG_P (operands[2])) - return (TARGET_68040_ONLY - ? \"fsmul%.s %2,%0\" - : \"fsglmul%.s %2,%0\"); -#else - if (REG_P (operands[2]) && ! DATA_REG_P (operands[2])) - return (TARGET_68040_ONLY - ? \"fsmul%.x %2,%0\" - : \"fsglmul%.x %2,%0\"); -#endif - return (TARGET_68040_ONLY - ? \"fsmul%.s %f2,%0\" - : \"fsglmul%.s %f2,%0\"); -}") - -;; divide instructions - -(define_expand "divdf3" - [(set (match_operand:DF 0 "general_operand" "") - (div:DF (match_operand:DF 1 "general_operand" "") - (match_operand:DF 2 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=x,y,y") - (div:DF (match_operand:DF 1 "general_operand" "xH,y,rmF") - (match_operand:DF 2 "general_operand" "xH,rmF,0")))] - "TARGET_FPA" - "* -{ - if (rtx_equal_p (operands[0], operands[2])) - return \"fprdiv%.d %y1,%0\"; - if (rtx_equal_p (operands[0], operands[1])) - return \"fpdiv%.d %y2,%0\"; - if (which_alternative == 0) - return \"fpdiv3%.d %w2,%w1,%0\"; - return \"fpdiv3%.d %x2,%x1,%x0\"; -}") - -(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" - "* -{ - if (REG_P (operands[2])) - return \"f%&div%.x %2,%0\"; - return \"f%&div%.d %f2,%0\"; -}") - -(define_expand "divsf3" - [(set (match_operand:SF 0 "general_operand" "") - (div:SF (match_operand:SF 1 "general_operand" "") - (match_operand:SF 2 "general_operand" "")))] - "TARGET_68881 || TARGET_FPA" - "") - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=x,y,y") - (div:SF (match_operand:SF 1 "general_operand" "xH,y,rmF") - (match_operand:SF 2 "general_operand" "xH,rmF,0")))] - "TARGET_FPA" - "* -{ - if (rtx_equal_p (operands[0], operands[1])) - return \"fpdiv%.s %w2,%0\"; - if (rtx_equal_p (operands[0], operands[2])) - return \"fprdiv%.s %w1,%0\"; - if (which_alternative == 0) - return \"fpdiv3%.s %w2,%w1,%0\"; - return \"fpdiv3%.s %2,%1,%0\"; -}") - -(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" - "* -{ -#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 "divmodsi4" - [(set (match_operand:SI 0 "general_operand" "=d") - (div:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "dmsK"))) - (set (match_operand:SI 3 "general_operand" "=d") - (mod:SI (match_dup 1) (match_dup 2)))] - "TARGET_68020 && !TARGET_5200" - "* -{ - if (find_reg_note (insn, REG_UNUSED, operands[3])) - return \"divs%.l %2,%0\"; - else - return \"divsl%.l %2,%3:%0\"; -}") - -(define_insn "udivmodsi4" - [(set (match_operand:SI 0 "general_operand" "=d") - (udiv:SI (match_operand:SI 1 "general_operand" "0") - (match_operand:SI 2 "general_operand" "dmsK"))) - (set (match_operand:SI 3 "general_operand" "=d") - (umod:SI (match_dup 1) (match_dup 2)))] - "TARGET_68020 && !TARGET_5200" - "* -{ - if (find_reg_note (insn, REG_UNUSED, operands[3])) - return \"divu%.l %2,%0\"; - 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)))] - "!TARGET_5200" - "* -{ -#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)))] - "!TARGET_5200" - "* -{ -#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 - -;; Prevent AND from being made with sp. This doesn't exist in the machine -;; and reload will cause inefficient code. Since sp is a FIXED_REG, we -;; can't allocate pseudos into it. - -(define_expand "andsi3" - [(set (match_operand:SI 0 "not_sp_operand" "=m,d") - (and:SI (match_operand:SI 1 "general_operand" "%0,0") - (match_operand:SI 2 "general_operand" "dKs,dmMs")))] - "" - "") - -(define_insn "andsi3_internal" - [(set (match_operand:SI 0 "not_sp_operand" "=m,d") - (and:SI (match_operand:SI 1 "general_operand" "%0,0") - (match_operand:SI 2 "general_operand" "dKs,dmMs")))] - "!TARGET_5200" - "* -{ - int logval; - if (GET_CODE (operands[2]) == CONST_INT - && (INTVAL (operands[2]) | 0xffff) == 0xffffffff - && (DATA_REG_P (operands[0]) - || offsettable_memref_p (operands[0]))) - { - if (GET_CODE (operands[0]) != REG) - operands[0] = adj_offsettable_operand (operands[0], 2); - operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]) & 0xffff); - /* Do not delete a following tstl %0 insn; that would be incorrect. */ - CC_STATUS_INIT; - if (operands[2] == const0_rtx) - return \"clr%.w %0\"; - return \"and%.w %2,%0\"; - } - if (GET_CODE (operands[2]) == CONST_INT - && (logval = exact_log2 (~ INTVAL (operands[2]))) >= 0 - && (DATA_REG_P (operands[0]) - || offsettable_memref_p (operands[0]))) - { - if (DATA_REG_P (operands[0])) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, logval); - } - else - { - 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; - return \"bclr %1,%0\"; - } - return \"and%.l %2,%0\"; -}") - -(define_insn "andsi3_5200" - [(set (match_operand:SI 0 "not_sp_operand" "=m,d") - (and:SI (match_operand:SI 1 "general_operand" "%0,0") - (match_operand:SI 2 "general_operand" "d,dmsK")))] - "TARGET_5200" - "and%.l %2,%0") - -(define_insn "andhi3" - [(set (match_operand:HI 0 "general_operand" "=m,d") - (and:HI (match_operand:HI 1 "general_operand" "%0,0") - (match_operand:HI 2 "general_operand" "dn,dmn")))] - "!TARGET_5200" - "and%.w %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) - (and:HI (match_dup 0) - (match_operand:HI 1 "general_operand" "dn,dmn")))] - "!TARGET_5200" - "and%.w %1,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) - (and:HI (match_operand:HI 1 "general_operand" "dn,dmn") - (match_dup 0)))] - "!TARGET_5200" - "and%.w %1,%0") - -(define_insn "andqi3" - [(set (match_operand:QI 0 "general_operand" "=m,d") - (and:QI (match_operand:QI 1 "general_operand" "%0,0") - (match_operand:QI 2 "general_operand" "dn,dmn")))] - "!TARGET_5200" - "and%.b %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d")) - (and:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "dn,dmn")))] - "!TARGET_5200" - "and%.b %1,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d")) - (and:QI (match_operand:QI 1 "general_operand" "dn,dmn") - (match_dup 0)))] - "!TARGET_5200" - "and%.b %1,%0") - -;; inclusive-or instructions - -(define_expand "iorsi3" - [(set (match_operand:SI 0 "general_operand" "") - (ior:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - "") - -(define_insn "iorsi3_internal" - [(set (match_operand:SI 0 "general_operand" "=m,d") - (ior:SI (match_operand:SI 1 "general_operand" "%0,0") - (match_operand:SI 2 "general_operand" "dKs,dmMs")))] - "!TARGET_5200" - "* -{ - register int logval; - if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) >> 16 == 0 - && (DATA_REG_P (operands[0]) - || offsettable_memref_p (operands[0]))) - { - if (GET_CODE (operands[0]) != REG) - operands[0] = adj_offsettable_operand (operands[0], 2); - /* Do not delete a following tstl %0 insn; that would be incorrect. */ - CC_STATUS_INIT; - return \"or%.w %2,%0\"; - } - if (GET_CODE (operands[2]) == CONST_INT - && (logval = exact_log2 (INTVAL (operands[2]))) >= 0 - && (DATA_REG_P (operands[0]) - || offsettable_memref_p (operands[0]))) - { - if (DATA_REG_P (operands[0])) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, logval); - } - else - { - operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8)); - operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8); - } - CC_STATUS_INIT; - return \"bset %1,%0\"; - } - return \"or%.l %2,%0\"; -}") - -(define_insn "iorsi3_5200" - [(set (match_operand:SI 0 "general_operand" "=m,d") - (ior:SI (match_operand:SI 1 "general_operand" "%0,0") - (match_operand:SI 2 "general_operand" "d,dmsK")))] - "TARGET_5200" - "or%.l %2,%0") - -(define_insn "iorhi3" - [(set (match_operand:HI 0 "general_operand" "=m,d") - (ior:HI (match_operand:HI 1 "general_operand" "%0,0") - (match_operand:HI 2 "general_operand" "dn,dmn")))] - "!TARGET_5200" - "or%.w %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) - (ior:HI (match_dup 0) - (match_operand:HI 1 "general_operand" "dn,dmn")))] - "!TARGET_5200" - "or%.w %1,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) - (ior:HI (match_operand:HI 1 "general_operand" "dn,dmn") - (match_dup 0)))] - "!TARGET_5200" - "or%.w %1,%0") - -(define_insn "iorqi3" - [(set (match_operand:QI 0 "general_operand" "=m,d") - (ior:QI (match_operand:QI 1 "general_operand" "%0,0") - (match_operand:QI 2 "general_operand" "dn,dmn")))] - "!TARGET_5200" - "or%.b %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d")) - (ior:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "dn,dmn")))] - "!TARGET_5200" - "or%.b %1,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d")) - (ior:QI (match_operand:QI 1 "general_operand" "dn,dmn") - (match_dup 0)))] - "!TARGET_5200" - "or%.b %1,%0") - -;; On all 68k models, this makes faster code in a special case. -;; See also ashlsi_16, ashrsi_16 and lshrsi_16. - -(define_insn "iorsi_zexthi_ashl16" - [(set (match_operand:SI 0 "general_operand" "=d,d") - (ior:SI (zero_extend:SI (match_operand:HI 1 "general_operand" "dmn,dmn")) - (ashift:SI (match_operand:SI 2 "general_operand" "o,0") - (const_int 16))))] - "" - "* -{ - CC_STATUS_INIT; - if (GET_CODE (operands[2]) != REG) - { - operands[2] = adj_offsettable_operand (operands[2], 2); - output_asm_insn (\"move%.w %2,%0\", operands); - } - return \"swap %0\;mov%.w %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")))] - "!TARGET_5200" - "* -{ - 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 - -(define_expand "xorsi3" - [(set (match_operand:SI 0 "general_operand" "") - (xor:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - "") - -(define_insn "xorsi3_internal" - [(set (match_operand:SI 0 "general_operand" "=do,m") - (xor:SI (match_operand:SI 1 "general_operand" "%0,0") - (match_operand:SI 2 "general_operand" "di,dKs")))] - "!TARGET_5200" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) >> 16 == 0 - && (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0]))) - { - if (! DATA_REG_P (operands[0])) - operands[0] = adj_offsettable_operand (operands[0], 2); - /* Do not delete a following tstl %0 insn; that would be incorrect. */ - CC_STATUS_INIT; - return \"eor%.w %2,%0\"; - } - return \"eor%.l %2,%0\"; -}") - -(define_insn "xorsi3_5200" - [(set (match_operand:SI 0 "general_operand" "=dm,d") - (xor:SI (match_operand:SI 1 "general_operand" "%0,0") - (match_operand:SI 2 "general_operand" "d,Ks")))] - "TARGET_5200" - "eor%.l %2,%0") - -(define_insn "xorhi3" - [(set (match_operand:HI 0 "general_operand" "=dm") - (xor:HI (match_operand:HI 1 "general_operand" "%0") - (match_operand:HI 2 "general_operand" "dn")))] - "!TARGET_5200" - "eor%.w %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm")) - (xor:HI (match_dup 0) - (match_operand:HI 1 "general_operand" "dn")))] - "!TARGET_5200" - "eor%.w %1,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm")) - (xor:HI (match_operand:HI 1 "general_operand" "dn") - (match_dup 0)))] - "!TARGET_5200" - "eor%.w %1,%0") - -(define_insn "xorqi3" - [(set (match_operand:QI 0 "general_operand" "=dm") - (xor:QI (match_operand:QI 1 "general_operand" "%0") - (match_operand:QI 2 "general_operand" "dn")))] - "!TARGET_5200" - "eor%.b %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm")) - (xor:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "dn")))] - "!TARGET_5200" - "eor%.b %1,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm")) - (xor:QI (match_operand:QI 1 "general_operand" "dn") - (match_dup 0)))] - "!TARGET_5200" - "eor%.b %1,%0") - -;; negation instructions - -(define_expand "negdi2" - [(set (match_operand:DI 0 "general_operand" "") - (neg:DI (match_operand:DI 1 "general_operand" "")))] - "" - " -{ - if (TARGET_5200) - emit_insn (gen_negdi2_5200 (operands[0], operands[1])); - else - emit_insn (gen_negdi2_internal (operands[0], operands[1])); - DONE; -}") - -(define_insn "negdi2_internal" - [(set (match_operand:DI 0 "general_operand" "=<,do,!*a") - (neg:DI (match_operand:DI 1 "general_operand" "0,0,0")))] - "!TARGET_5200" - "* -{ - if (which_alternative == 0) - 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 "negdi2_5200" - [(set (match_operand:DI 0 "general_operand" "=d") - (neg:DI (match_operand:DI 1 "general_operand" "0")))] - "TARGET_5200" - "* -{ - operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - return \"neg%.l %1\;negx%.l %0\"; -} ") - -(define_expand "negsi2" - [(set (match_operand:SI 0 "general_operand" "") - (neg:SI (match_operand:SI 1 "general_operand" "")))] - "" - " -{ - if (TARGET_5200) - emit_insn (gen_negsi2_5200 (operands[0], operands[1])); - else - emit_insn (gen_negsi2_internal (operands[0], operands[1])); - DONE; -}") - -(define_insn "negsi2_internal" - [(set (match_operand:SI 0 "general_operand" "=dm") - (neg:SI (match_operand:SI 1 "general_operand" "0")))] - "!TARGET_5200" - "neg%.l %0") - -(define_insn "negsi2_5200" - [(set (match_operand:SI 0 "general_operand" "=d") - (neg:SI (match_operand:SI 1 "general_operand" "0")))] - "TARGET_5200" - "neg%.l %0") - -(define_insn "neghi2" - [(set (match_operand:HI 0 "general_operand" "=dm") - (neg:HI (match_operand:HI 1 "general_operand" "0")))] - "!TARGET_5200" - "neg%.w %0") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm")) - (neg:HI (match_dup 0)))] - "!TARGET_5200" - "neg%.w %0") - -(define_insn "negqi2" - [(set (match_operand:QI 0 "general_operand" "=dm") - (neg:QI (match_operand:QI 1 "general_operand" "0")))] - "!TARGET_5200" - "neg%.b %0") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm")) - (neg:QI (match_dup 0)))] - "!TARGET_5200" - "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" "")))] - "" - " -{ - 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") - (neg:SF (match_operand:SF 1 "general_operand" "xH,rmF")))] - "TARGET_FPA" - "fpneg%.s %w1,%0") - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=f,d") - (neg:SF (match_operand:SF 1 "general_operand" "fdmF,0")))] - "TARGET_68881" - "* -{ - if (DATA_REG_P (operands[0])) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, 31); - return \"bchg %1,%0\"; - } - if (REG_P (operands[1]) && ! DATA_REG_P (operands[1])) - return \"f%$neg%.x %1,%0\"; - return \"f%$neg%.s %f1,%0\"; -}") - -(define_expand "negdf2" - [(set (match_operand:DF 0 "general_operand" "") - (neg:DF (match_operand:DF 1 "general_operand" "")))] - "" - " -{ - 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") - (neg:DF (match_operand:DF 1 "general_operand" "xH,rmF")))] - "TARGET_FPA" - "fpneg%.d %y1, %0") - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=f,d") - (neg:DF (match_operand:DF 1 "general_operand" "fmF,0")))] - "TARGET_68881" - "* -{ - if (DATA_REG_P (operands[0])) - { - operands[1] = gen_rtx (CONST_INT, VOIDmode, 31); - return \"bchg %1,%0\"; - } - if (REG_P (operands[1]) && ! DATA_REG_P (operands[1])) - return \"f%&neg%.x %1,%0\"; - return \"f%&neg%.d %f1,%0\"; -}") - -;; 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")))] - "TARGET_68881" - "* -{ - if (FP_REG_P (operands[1])) - return \"f%&sqrt%.x %1,%0\"; - else - 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" "")))] - "" - " -{ - 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") - (abs:SF (match_operand:SF 1 "general_operand" "xH,rmF")))] - "TARGET_FPA" - "fpabs%.s %y1,%0") - -(define_insn "" - [(set (match_operand:SF 0 "general_operand" "=f") - (abs:SF (match_operand:SF 1 "general_operand" "fdmF")))] - "TARGET_68881" - "* -{ - if (REG_P (operands[1]) && ! DATA_REG_P (operands[1])) - return \"f%$abs%.x %1,%0\"; - return \"f%$abs%.s %f1,%0\"; -}") - -(define_expand "absdf2" - [(set (match_operand:DF 0 "general_operand" "") - (abs:DF (match_operand:DF 1 "general_operand" "")))] - "" - " -{ - 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") - (abs:DF (match_operand:DF 1 "general_operand" "xH,rmF")))] - "TARGET_FPA" - "fpabs%.d %y1,%0") - -(define_insn "" - [(set (match_operand:DF 0 "general_operand" "=f") - (abs:DF (match_operand:DF 1 "general_operand" "fmF")))] - "TARGET_68881" - "* -{ - if (REG_P (operands[1]) && ! DATA_REG_P (operands[1])) - return \"f%&abs%.x %1,%0\"; - return \"f%&abs%.d %f1,%0\"; -}") - -;; 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")))] - "!TARGET_5200" - "* -{ - 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_expand "one_cmplsi2" - [(set (match_operand:SI 0 "general_operand" "") - (not:SI (match_operand:SI 1 "general_operand" "")))] - "" - " -{ - if (TARGET_5200) - emit_insn (gen_one_cmplsi2_5200 (operands[0], operands[1])); - else - emit_insn (gen_one_cmplsi2_internal (operands[0], operands[1])); - DONE; -}") - -(define_insn "one_cmplsi2_internal" - [(set (match_operand:SI 0 "general_operand" "=dm") - (not:SI (match_operand:SI 1 "general_operand" "0")))] - "!TARGET_5200" - "not%.l %0") - -(define_insn "one_cmplsi2_5200" - [(set (match_operand:SI 0 "general_operand" "=d") - (not:SI (match_operand:SI 1 "general_operand" "0")))] - "TARGET_5200" - "not%.l %0") - -(define_insn "one_cmplhi2" - [(set (match_operand:HI 0 "general_operand" "=dm") - (not:HI (match_operand:HI 1 "general_operand" "0")))] - "!TARGET_5200" - "not%.w %0") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm")) - (not:HI (match_dup 0)))] - "!TARGET_5200" - "not%.w %0") - -(define_insn "one_cmplqi2" - [(set (match_operand:QI 0 "general_operand" "=dm") - (not:QI (match_operand:QI 1 "general_operand" "0")))] - "!TARGET_5200" - "not%.b %0") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm")) - (not:QI (match_dup 0)))] - "!TARGET_5200" - "not%.b %0") - -;; 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 "general_operand" "=m,a*d") - (ashift:DI (sign_extend:DI (match_operand:HI 1 "general_operand" "rm,rm")) - (const_int 32))) - (clobber (match_scratch:SI 2 "=a,X"))] - "" - "* -{ - CC_STATUS_INIT; - if (GET_CODE (operands[0]) == MEM) - { - if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) - return \"clr%.l %0\;move%.w %1,%2\;move%.l %2,%0\"; - else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC) - return \"move%.w %1,%2\;move%.l %2,%0\;clr%.l %0\"; - else - { - operands[3] = adj_offsettable_operand (operands[0], 4); - return \"move%.w %1,%2\;move%.l %2,%0\;clr%.l %3\"; - } - } - else if (DATA_REG_P (operands[0])) - return \"move%.w %1,%0\;ext%.l %0\;clr%.l %R0\"; - else - return \"move%.w %1,%0\;sub%.l %R0,%R0\"; -} ") - -(define_insn "ashldi_const32" - [(set (match_operand:DI 0 "general_operand" "=rm") - (ashift:DI (match_operand:DI 1 "general_operand" "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 (GET_CODE (operands[0]) == REG) - operands[2] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - else if (GET_CODE (XEXP (operands[0], 0)) == PRE_DEC) - return \"clr%.l %0\;move%.l %3,%0\"; - else if (GET_CODE (XEXP (operands[0], 0)) == POST_INC) - return \"move%.l %3,%0\;clr%.l %0\"; - else - operands[2] = 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 most 68k models, this makes faster code in a special case. - -(define_insn "ashlsi_16" - [(set (match_operand:SI 0 "register_operand" "=d") - (ashift:SI (match_operand:SI 1 "register_operand" "0") - (const_int 16)))] - "!TARGET_68060" - "* -{ - CC_STATUS_INIT; - return \"swap %0\;clr%.w %0\"; -}") - -;; ashift patterns : use lsl instead of asl, because lsl always clears the -;; overflow bit, so we must not set CC_NO_OVERFLOW. - -;; On the 68000, this makes faster code in a special case. - -(define_insn "ashlsi_17_24" - [(set (match_operand:SI 0 "register_operand" "=d") - (ashift:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "const_int_operand" "n")))] - "(! TARGET_68020 && !TARGET_5200 - && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)" - "* -{ - CC_STATUS_INIT; - - operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16); - return \"lsl%.w %2,%0\;swap %0\;clr%.w %0\"; -}") - -(define_insn "ashlsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (ashift:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "dI")))] - "" - "* -{ - if (operands[2] == const1_rtx) - { - cc_status.flags = CC_NO_OVERFLOW; - return \"add%.l %0,%0\"; - } - return \"lsl%.l %2,%0\"; -}") - -(define_insn "ashlhi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (ashift:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "general_operand" "dI")))] - "!TARGET_5200" - "lsl%.w %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d")) - (ashift:HI (match_dup 0) - (match_operand:HI 1 "general_operand" "dI")))] - "!TARGET_5200" - "lsl%.w %1,%0") - -(define_insn "ashlqi3" - [(set (match_operand:QI 0 "register_operand" "=d") - (ashift:QI (match_operand:QI 1 "register_operand" "0") - (match_operand:QI 2 "general_operand" "dI")))] - "!TARGET_5200" - "lsl%.b %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d")) - (ashift:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "dI")))] - "!TARGET_5200" - "lsl%.b %1,%0") - -;; On most 68k models, this makes faster code in a special case. - -(define_insn "ashrsi_16" - [(set (match_operand:SI 0 "register_operand" "=d") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") - (const_int 16)))] - "!TARGET_68060" - "swap %0\;ext%.l %0") - -;; On the 68000, this makes faster code in a special case. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=d") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "const_int_operand" "n")))] - "(! TARGET_68020 && !TARGET_5200 - && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)" - "* -{ - operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16); - 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")))] - "!TARGET_5200 - && ((INTVAL (operands[2]) == 1 || INTVAL (operands[2]) == 2 - || INTVAL (operands[2]) == 3 || INTVAL (operands[2]) == 8 - || INTVAL (operands[2]) == 16 || INTVAL (operands[2]) == 31 - || 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]) == 31) - return \"add%.l %1,%1\;addx%.l %0,%0\;move%.l %0,%1\;subx%.l %0,%0\"; - else if (INTVAL (operands[2]) == 2) - return \"asr%.l %#1,%0\;roxr%.l %#1,%1\;asr%.l %#1,%0\;roxr%.l %#1,%1\"; - else/* if (INTVAL (operands[2]) == 3)*/ - return \"asr%.l %#1,%0\;roxr%.l %#1,%1\;asr%.l %#1,%0\;roxr%.l %#1,%1\;asr%.l %#1,%0\;roxr%.l %#1,%1\"; -} ") - -(define_expand "ashrdi3" - [(set (match_operand:DI 0 "general_operand" "") - (ashiftrt:DI (match_operand:DI 1 "general_operand" "") - (match_operand 2 "const_int_operand" "")))] - "!TARGET_5200" - " -{ - 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]) != 31 - && INTVAL (operands[2]) != 32 && INTVAL (operands[2]) != 63)) - FAIL; -} ") - -;; On all 68k models, this makes faster code in a special case. - -(define_insn "ashrsi_31" - [(set (match_operand:SI 0 "register_operand" "=d") - (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") - (const_int 31)))] - "" - "* -{ - return \"add%.l %0,%0\;subx%.l %0,%0\"; -}") - -(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")))] - "" - "asr%.l %2,%0") - -(define_insn "ashrhi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (ashiftrt:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "general_operand" "dI")))] - "!TARGET_5200" - "asr%.w %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d")) - (ashiftrt:HI (match_dup 0) - (match_operand:HI 1 "general_operand" "dI")))] - "!TARGET_5200" - "asr%.w %1,%0") - -(define_insn "ashrqi3" - [(set (match_operand:QI 0 "register_operand" "=d") - (ashiftrt:QI (match_operand:QI 1 "register_operand" "0") - (match_operand:QI 2 "general_operand" "dI")))] - "!TARGET_5200" - "asr%.b %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d")) - (ashiftrt:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "dI")))] - "!TARGET_5200" - "asr%.b %1,%0") - -;; 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")))] - "!TARGET_5200 - && ((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" "")))] - "!TARGET_5200" - " -{ - 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 "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 most 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)))] - "!TARGET_68060" - "* -{ - CC_STATUS_INIT; - return \"clr%.w %0\;swap %0\"; -}") - -;; On the 68000, this makes faster code in a special case. - -(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")))] - "(! TARGET_68020 && !TARGET_5200 - && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)" - "* -{ - /* I think lsr%.w sets the CC properly. */ - operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16); - return \"clr%.w %0\;swap %0\;lsr%.w %2,%0\"; -}") - -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "dI")))] - "" - "lsr%.l %2,%0") - -(define_insn "lshrhi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (lshiftrt:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "general_operand" "dI")))] - "!TARGET_5200" - "lsr%.w %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d")) - (lshiftrt:HI (match_dup 0) - (match_operand:HI 1 "general_operand" "dI")))] - "!TARGET_5200" - "lsr%.w %1,%0") - -(define_insn "lshrqi3" - [(set (match_operand:QI 0 "register_operand" "=d") - (lshiftrt:QI (match_operand:QI 1 "register_operand" "0") - (match_operand:QI 2 "general_operand" "dI")))] - "!TARGET_5200" - "lsr%.b %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d")) - (lshiftrt:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "dI")))] - "!TARGET_5200" - "lsr%.b %1,%0") - -;; rotate instructions - -(define_insn "rotlsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (rotate:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "dINO")))] - "!TARGET_5200" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 16) - return \"swap %0\"; - else if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 16) - { - INTVAL (operands[2]) = 32 - INTVAL (operands[2]); - return \"ror%.l %2,%0\"; - } - else - return \"rol%.l %2,%0\"; -}") - -(define_insn "rotlhi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (rotate:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "general_operand" "dIP")))] - "!TARGET_5200" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 8) - { - INTVAL (operands[2]) = 16 - INTVAL (operands[2]); - return \"ror%.w %2,%0\"; - } - else - return \"rol%.w %2,%0\"; -}") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d")) - (rotate:HI (match_dup 0) - (match_operand:HI 1 "general_operand" "dIP")))] - "!TARGET_5200" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 8) - { - INTVAL (operands[2]) = 16 - INTVAL (operands[2]); - return \"ror%.w %2,%0\"; - } - else - return \"rol%.w %2,%0\"; -}") - -(define_insn "rotlqi3" - [(set (match_operand:QI 0 "register_operand" "=d") - (rotate:QI (match_operand:QI 1 "register_operand" "0") - (match_operand:QI 2 "general_operand" "dI")))] - "!TARGET_5200" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 4) - { - INTVAL (operands[2]) = 8 - INTVAL (operands[2]); - return \"ror%.b %2,%0\"; - } - else - return \"rol%.b %2,%0\"; -}") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d")) - (rotate:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "dI")))] - "!TARGET_5200" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 4) - { - INTVAL (operands[2]) = 8 - INTVAL (operands[2]); - return \"ror%.b %2,%0\"; - } - else - return \"rol%.b %2,%0\"; -}") - -(define_insn "rotrsi3" - [(set (match_operand:SI 0 "register_operand" "=d") - (rotatert:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "general_operand" "dI")))] - "!TARGET_5200" - "ror%.l %2,%0") - -(define_insn "rotrhi3" - [(set (match_operand:HI 0 "register_operand" "=d") - (rotatert:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "general_operand" "dI")))] - "!TARGET_5200" - "ror%.w %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d")) - (rotatert:HI (match_dup 0) - (match_operand:HI 1 "general_operand" "dI")))] - "!TARGET_5200" - "ror%.w %1,%0") - -(define_insn "rotrqi3" - [(set (match_operand:QI 0 "register_operand" "=d") - (rotatert:QI (match_operand:QI 1 "register_operand" "0") - (match_operand:QI 2 "general_operand" "dI")))] - "!TARGET_5200" - "ror%.b %2,%0") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d")) - (rotatert:QI (match_dup 0) - (match_operand:QI 1 "general_operand" "dI")))] - "!TARGET_5200" - "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, -;; which can usually be done with move instructions. - -; -; Special case for 32-bit field in memory. This only occurs when 32-bit -; alignment of structure members is specified. -; -; The move is allowed to be odd byte aligned, because that's still faster -; than an odd byte aligned bit field instruction. -; -(define_insn "" - [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o") - (const_int 32) - (match_operand:SI 2 "const_int_operand" "n")) - (match_operand:SI 3 "general_operand" "rmi"))] - "TARGET_68020 && TARGET_BITFIELD - && (INTVAL (operands[2]) % 8) == 0 - && ! mode_dependent_address_p (XEXP (operands[0], 0))" - "* -{ - operands[0] - = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8); - - return \"move%.l %3,%0\"; -}") - -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+do") - (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 - && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16) - && INTVAL (operands[2]) % INTVAL (operands[1]) == 0 - && (GET_CODE (operands[0]) == REG - || ! mode_dependent_address_p (XEXP (operands[0], 0)))" - "* -{ - if (REG_P (operands[0])) - { - if (INTVAL (operands[1]) + INTVAL (operands[2]) != 32) - return \"bfins %3,%0{%b2:%b1}\"; - } - else - operands[0] - = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8); - - if (GET_CODE (operands[3]) == MEM) - operands[3] = adj_offsettable_operand (operands[3], - (32 - INTVAL (operands[1])) / 8); - if (INTVAL (operands[1]) == 8) - return \"move%.b %3,%0\"; - return \"move%.w %3,%0\"; -}") - - -; -; Special case for 32-bit field in memory. This only occurs when 32-bit -; alignment of structure members is specified. -; -; The move is allowed to be odd byte aligned, because that's still faster -; than an odd byte aligned bit field instruction. -; -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=rm") - (zero_extract:SI (match_operand:QI 1 "memory_operand" "o") - (const_int 32) - (match_operand:SI 3 "const_int_operand" "n")))] - "TARGET_68020 && TARGET_BITFIELD - && (INTVAL (operands[3]) % 8) == 0 - && ! mode_dependent_address_p (XEXP (operands[1], 0))" - "* -{ - operands[1] - = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8); - - return \"move%.l %1,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=&d") - (zero_extract:SI (match_operand:SI 1 "register_operand" "do") - (match_operand:SI 2 "const_int_operand" "n") - (match_operand:SI 3 "const_int_operand" "n")))] - "TARGET_68020 && TARGET_BITFIELD - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && INTVAL (operands[3]) % INTVAL (operands[2]) == 0 - && (GET_CODE (operands[1]) == REG - || ! mode_dependent_address_p (XEXP (operands[1], 0)))" - "* -{ - cc_status.flags |= CC_NOT_NEGATIVE; - if (REG_P (operands[1])) - { - if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32) - return \"bfextu %1{%b3:%b2},%0\"; - } - else - operands[1] - = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8); - - output_asm_insn (\"clr%.l %0\", operands); - if (GET_CODE (operands[0]) == MEM) - operands[0] = adj_offsettable_operand (operands[0], - (32 - INTVAL (operands[1])) / 8); - if (INTVAL (operands[2]) == 8) - return \"move%.b %1,%0\"; - return \"move%.w %1,%0\"; -}") - -; -; Special case for 32-bit field in memory. This only occurs when 32-bit -; alignment of structure members is specified. -; -; The move is allowed to be odd byte aligned, because that's still faster -; than an odd byte aligned bit field instruction. -; -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=rm") - (sign_extract:SI (match_operand:QI 1 "memory_operand" "o") - (const_int 32) - (match_operand:SI 3 "const_int_operand" "n")))] - "TARGET_68020 && TARGET_BITFIELD - && (INTVAL (operands[3]) % 8) == 0 - && ! mode_dependent_address_p (XEXP (operands[1], 0))" - "* -{ - operands[1] - = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8); - - return \"move%.l %1,%0\"; -}") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d") - (sign_extract:SI (match_operand:SI 1 "register_operand" "do") - (match_operand:SI 2 "const_int_operand" "n") - (match_operand:SI 3 "const_int_operand" "n")))] - "TARGET_68020 && TARGET_BITFIELD - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) - && INTVAL (operands[3]) % INTVAL (operands[2]) == 0 - && (GET_CODE (operands[1]) == REG - || ! mode_dependent_address_p (XEXP (operands[1], 0)))" - "* -{ - if (REG_P (operands[1])) - { - if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32) - return \"bfexts %1{%b3:%b2},%0\"; - } - else - operands[1] - = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8); - - if (INTVAL (operands[2]) == 8) - return \"move%.b %1,%0\;extb%.l %0\"; - return \"move%.w %1,%0\;ext%.l %0\"; -}") - -;; Bit field instructions, general cases. -;; "o,d" constraint causes a nonoffsettable memref to match the "o" -;; so that its address is reloaded. - -(define_expand "extv" - [(set (match_operand:SI 0 "general_operand" "") - (sign_extract:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "") - (match_operand:SI 3 "general_operand" "")))] - "TARGET_68020 && TARGET_BITFIELD" - "") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d") - (sign_extract:SI (match_operand:QI 1 "memory_operand" "o") - (match_operand:SI 2 "general_operand" "di") - (match_operand:SI 3 "general_operand" "di")))] - "TARGET_68020 && TARGET_BITFIELD" - "bfexts %1{%b3:%b2},%0") - -(define_expand "extzv" - [(set (match_operand:SI 0 "general_operand" "") - (zero_extract:SI (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "") - (match_operand:SI 3 "general_operand" "")))] - "TARGET_68020 && TARGET_BITFIELD" - "") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d,d") - (zero_extract:SI (match_operand:QI 1 "memory_operand" "o,d") - (match_operand:SI 2 "general_operand" "di,di") - (match_operand:SI 3 "general_operand" "di,di")))] - "TARGET_68020 && TARGET_BITFIELD" - "* -{ - 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\"; -}") - -(define_insn "" - [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o") - (match_operand:SI 1 "general_operand" "di") - (match_operand:SI 2 "general_operand" "di")) - (xor:SI (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2)) - (match_operand 3 "const_int_operand" "n")))] - "TARGET_68020 && TARGET_BITFIELD - && (INTVAL (operands[3]) == -1 - || (GET_CODE (operands[1]) == CONST_INT - && (~ INTVAL (operands[3]) & ((1 << INTVAL (operands[1]))- 1)) == 0))" - "* -{ - CC_STATUS_INIT; - return \"bfchg %0{%b2:%b1}\"; -}") - -(define_insn "" - [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o") - (match_operand:SI 1 "general_operand" "di") - (match_operand:SI 2 "general_operand" "di")) - (const_int 0))] - "TARGET_68020 && TARGET_BITFIELD" - "* -{ - CC_STATUS_INIT; - return \"bfclr %0{%b2:%b1}\"; -}") - -(define_insn "" - [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o") - (match_operand:SI 1 "general_operand" "di") - (match_operand:SI 2 "general_operand" "di")) - (const_int -1))] - "TARGET_68020 && TARGET_BITFIELD" - "* -{ - CC_STATUS_INIT; - return \"bfset %0{%b2:%b1}\"; -}") - -(define_expand "insv" - [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" "") - (match_operand:SI 2 "general_operand" "")) - (match_operand:SI 3 "register_operand" ""))] - "TARGET_68020 && TARGET_BITFIELD" - "") - -(define_insn "" - [(set (zero_extract:SI (match_operand:QI 0 "memory_operand" "+o") - (match_operand:SI 1 "general_operand" "di") - (match_operand:SI 2 "general_operand" "di")) - (match_operand:SI 3 "register_operand" "d"))] - "TARGET_68020 && TARGET_BITFIELD" - "bfins %3,%0{%b2:%b1}") - -;; Now recognize bit field insns that operate on registers -;; (or at least were intended to do so). - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d") - (sign_extract:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "general_operand" "di") - (match_operand:SI 3 "general_operand" "di")))] - "TARGET_68020 && TARGET_BITFIELD" - "bfexts %1{%b3:%b2},%0") - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=d") - (zero_extract:SI (match_operand:SI 1 "register_operand" "d") - (match_operand:SI 2 "general_operand" "di") - (match_operand:SI 3 "general_operand" "di")))] - "TARGET_68020 && TARGET_BITFIELD" - "* -{ - 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\"; -}") - -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d") - (match_operand:SI 1 "general_operand" "di") - (match_operand:SI 2 "general_operand" "di")) - (const_int 0))] - "TARGET_68020 && TARGET_BITFIELD" - "* -{ - CC_STATUS_INIT; - return \"bfclr %0{%b2:%b1}\"; -}") - -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d") - (match_operand:SI 1 "general_operand" "di") - (match_operand:SI 2 "general_operand" "di")) - (const_int -1))] - "TARGET_68020 && TARGET_BITFIELD" - "* -{ - CC_STATUS_INIT; - return \"bfset %0{%b2:%b1}\"; -}") - -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+d") - (match_operand:SI 1 "general_operand" "di") - (match_operand:SI 2 "general_operand" "di")) - (match_operand:SI 3 "register_operand" "d"))] - "TARGET_68020 && TARGET_BITFIELD" - "* -{ -#if 0 - /* These special cases are now recognized by a specific pattern. */ - if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[1]) == 16 && INTVAL (operands[2]) == 16) - return \"move%.w %3,%0\"; - if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[1]) == 24 && INTVAL (operands[2]) == 8) - return \"move%.b %3,%0\"; -#endif - return \"bfins %3,%0{%b2:%b1}\"; -}") - -;; Special patterns for optimizing bit-field instructions. - -(define_insn "" - [(set (cc0) - (zero_extract:SI (match_operand:QI 0 "memory_operand" "o") - (match_operand:SI 1 "const_int_operand" "n") - (match_operand:SI 2 "general_operand" "di")))] - "TARGET_68020 && TARGET_BITFIELD" - "* -{ - if (operands[1] == const1_rtx - && GET_CODE (operands[2]) == CONST_INT) - { - int width = GET_CODE (operands[0]) == REG ? 31 : 7; - return output_btst (operands, - gen_rtx (CONST_INT, VOIDmode, - width - INTVAL (operands[2])), - operands[0], - insn, 1000); - /* Pass 1000 as SIGNPOS argument so that btst will - not think we are testing the sign bit for an `and' - and assume that nonzero implies a negative result. */ - } - if (INTVAL (operands[1]) != 32) - cc_status.flags = CC_NOT_NEGATIVE; - return \"bftst %0{%b2:%b1}\"; -}") - - -;;; now handle the register cases -(define_insn "" - [(set (cc0) - (zero_extract:SI (match_operand:SI 0 "register_operand" "d") - (match_operand:SI 1 "const_int_operand" "n") - (match_operand:SI 2 "general_operand" "di")))] - "TARGET_68020 && TARGET_BITFIELD" - "* -{ - if (operands[1] == const1_rtx - && GET_CODE (operands[2]) == CONST_INT) - { - int width = GET_CODE (operands[0]) == REG ? 31 : 7; - return output_btst (operands, - gen_rtx (CONST_INT, VOIDmode, - width - INTVAL (operands[2])), - operands[0], - insn, 1000); - /* Pass 1000 as SIGNPOS argument so that btst will - not think we are testing the sign bit for an `and' - and assume that nonzero implies a negative result. */ - } - if (INTVAL (operands[1]) != 32) - cc_status.flags = CC_NOT_NEGATIVE; - 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_expand "seq" - [(set (match_operand:QI 0 "general_operand" "") - (eq:QI (cc0) (const_int 0)))] - "" - " -{ - if (TARGET_68060 && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}") - -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=dm") - (eq:QI (cc0) (const_int 0)))] - "" - "* - cc_status = cc_prev_status; - OUTPUT_JUMP (\"seq %0\", \"fseq %0\", \"seq %0\"); -") - -(define_expand "sne" - [(set (match_operand:QI 0 "general_operand" "") - (ne:QI (cc0) (const_int 0)))] - "" - " -{ - if (TARGET_68060 && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}") - -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=dm") - (ne:QI (cc0) (const_int 0)))] - "" - "* - cc_status = cc_prev_status; - OUTPUT_JUMP (\"sne %0\", \"fsne %0\", \"sne %0\"); -") - -(define_expand "sgt" - [(set (match_operand:QI 0 "general_operand" "") - (gt:QI (cc0) (const_int 0)))] - "" - " -{ - if (TARGET_68060 && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}") - -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=dm") - (gt:QI (cc0) (const_int 0)))] - "" - "* - cc_status = cc_prev_status; - OUTPUT_JUMP (\"sgt %0\", \"fsgt %0\", 0); -") - -(define_insn "sgtu" - [(set (match_operand:QI 0 "general_operand" "=dm") - (gtu:QI (cc0) (const_int 0)))] - "" - "* cc_status = cc_prev_status; - return \"shi %0\"; ") - -(define_expand "slt" - [(set (match_operand:QI 0 "general_operand" "") - (lt:QI (cc0) (const_int 0)))] - "" - " -{ - if (TARGET_68060 && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}") - -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=dm") - (lt:QI (cc0) (const_int 0)))] - "" - "* cc_status = cc_prev_status; - OUTPUT_JUMP (\"slt %0\", \"fslt %0\", \"smi %0\"); ") - -(define_insn "sltu" - [(set (match_operand:QI 0 "general_operand" "=dm") - (ltu:QI (cc0) (const_int 0)))] - "" - "* cc_status = cc_prev_status; - return \"scs %0\"; ") - -(define_expand "sge" - [(set (match_operand:QI 0 "general_operand" "") - (ge:QI (cc0) (const_int 0)))] - "" - " -{ - if (TARGET_68060 && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}") - -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=dm") - (ge:QI (cc0) (const_int 0)))] - "" - "* cc_status = cc_prev_status; - OUTPUT_JUMP (\"sge %0\", \"fsge %0\", \"spl %0\"); ") - -(define_insn "sgeu" - [(set (match_operand:QI 0 "general_operand" "=dm") - (geu:QI (cc0) (const_int 0)))] - "" - "* cc_status = cc_prev_status; - return \"scc %0\"; ") - -(define_expand "sle" - [(set (match_operand:QI 0 "general_operand" "") - (le:QI (cc0) (const_int 0)))] - "" - " -{ - if (TARGET_68060 && m68k_last_compare_had_fp_operands) - { - m68k_last_compare_had_fp_operands = 0; - FAIL; - } -}") - -(define_insn "" - [(set (match_operand:QI 0 "general_operand" "=dm") - (le:QI (cc0) (const_int 0)))] - "" - "* - cc_status = cc_prev_status; - OUTPUT_JUMP (\"sle %0\", \"fsle %0\", 0); -") - -(define_insn "sleu" - [(set (match_operand:QI 0 "general_operand" "=dm") - (leu:QI (cc0) (const_int 0)))] - "" - "* cc_status = cc_prev_status; - return \"sls %0\"; ") - -;; 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"))] - "" - "* -{ - CC_STATUS_INIT; - 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 ((cc_prev_status.value1 - && rtx_equal_p (cc_prev_status.value1, operands[0])) - || (cc_prev_status.value2 - && rtx_equal_p (cc_prev_status.value2, operands[0]))) - { - cc_status = cc_prev_status; -#ifdef MOTOROLA - return \"jbeq %l1\"; -#else - return \"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 || TARGET_5200) -#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"))] - "" - "* -{ - if ((cc_prev_status.value1 - && rtx_equal_p (cc_prev_status.value1, operands[0])) - || (cc_prev_status.value2 - && rtx_equal_p (cc_prev_status.value2, operands[0]))) - { - cc_status = cc_prev_status; -#ifdef MOTOROLA - return \"jbne %l1\"; -#else - return \"jne %l1\"; -#endif - } - 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 || TARGET_5200) -#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)))] - "" - "* -{ - if ((cc_prev_status.value1 - && rtx_equal_p (cc_prev_status.value1, operands[0])) - || (cc_prev_status.value2 - && rtx_equal_p (cc_prev_status.value2, operands[0]))) - { - cc_status = cc_prev_status; - if (cc_status.flags & CC_REVERSED) - { -#ifdef MOTOROLA - return \"jble %l1\"; -#else - return \"jle %l1\"; -#endif - } - else - { -#ifdef MOTOROLA - return \"jbpl %l1\"; -#else - return \"jpl %l1\"; -#endif - } - } - CC_STATUS_INIT; - if (TARGET_68020 || TARGET_5200 || ! 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)))] - "" - "* -{ - if ((cc_prev_status.value1 - && rtx_equal_p (cc_prev_status.value1, operands[0])) - || (cc_prev_status.value2 - && rtx_equal_p (cc_prev_status.value2, operands[0]))) - { - cc_status = cc_prev_status; - if (cc_status.flags & CC_REVERSED) - { -#ifdef MOTOROLA - return \"jbgt %l1\"; -#else - return \"jgt %l1\"; -#endif - } - else - { -#ifdef MOTOROLA - return \"jbmi %l1\"; -#else - return \"jmi %l1\"; -#endif - } - } - CC_STATUS_INIT; - if (TARGET_68020 || TARGET_5200 || ! 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) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -{ -#ifdef MOTOROLA - OUTPUT_JUMP (\"jbeq %l0\", \"fbeq %l0\", \"jbeq %l0\"); -#else - OUTPUT_JUMP (\"jeq %l0\", \"fjeq %l0\", \"jeq %l0\"); -#endif -}") - -(define_insn "bne" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -{ -#ifdef MOTOROLA - OUTPUT_JUMP (\"jbne %l0\", \"fbne %l0\", \"jbne %l0\"); -#else - OUTPUT_JUMP (\"jne %l0\", \"fjne %l0\", \"jne %l0\"); -#endif -}") - -(define_insn "bgt" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -#ifdef MOTOROLA - OUTPUT_JUMP (\"jbgt %l0\", \"fbgt %l0\", 0); -#else - OUTPUT_JUMP (\"jgt %l0\", \"fjgt %l0\", 0); -#endif -") - -(define_insn "bgtu" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -#ifdef MOTOROLA - return \"jbhi %l0\"; -#else - return \"jhi %l0\"; -#endif -") - -(define_insn "blt" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -#ifdef MOTOROLA - OUTPUT_JUMP (\"jblt %l0\", \"fblt %l0\", \"jbmi %l0\"); -#else - OUTPUT_JUMP (\"jlt %l0\", \"fjlt %l0\", \"jmi %l0\"); -#endif -") - -(define_insn "bltu" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -#ifdef MOTOROLA - return \"jbcs %l0\"; -#else - return \"jcs %l0\"; -#endif -") - -(define_insn "bge" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -#ifdef MOTOROLA - OUTPUT_JUMP (\"jbge %l0\", \"fbge %l0\", \"jbpl %l0\"); -#else - OUTPUT_JUMP (\"jge %l0\", \"fjge %l0\", \"jpl %l0\"); -#endif -") - -(define_insn "bgeu" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -#ifdef MOTOROLA - return \"jbcc %l0\"; -#else - return \"jcc %l0\"; -#endif -") - -(define_insn "ble" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -#ifdef MOTOROLA - OUTPUT_JUMP (\"jble %l0\", \"fble %l0\", 0); -#else - OUTPUT_JUMP (\"jle %l0\", \"fjle %l0\", 0); -#endif -") - -(define_insn "bleu" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "* -#ifdef MOTOROLA - return \"jbls %l0\"; -#else - return \"jls %l0\"; -#endif -") - -;; Negated conditional jump instructions. - -(define_insn "" - [(set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ -#ifdef MOTOROLA - OUTPUT_JUMP (\"jbne %l0\", \"fbne %l0\", \"jbne %l0\"); -#else - OUTPUT_JUMP (\"jne %l0\", \"fjne %l0\", \"jne %l0\"); -#endif -}") - -(define_insn "" - [(set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -{ -#ifdef MOTOROLA - OUTPUT_JUMP (\"jbeq %l0\", \"fbeq %l0\", \"jbeq %l0\"); -#else - OUTPUT_JUMP (\"jeq %l0\", \"fjeq %l0\", \"jeq %l0\"); -#endif -}") - -(define_insn "" - [(set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -#ifdef MOTOROLA - OUTPUT_JUMP (\"jble %l0\", \"fbngt %l0\", 0); -#else - OUTPUT_JUMP (\"jle %l0\", \"fjngt %l0\", 0); -#endif -") - -(define_insn "" - [(set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -#ifdef MOTOROLA - return \"jbls %l0\"; -#else - return \"jls %l0\"; -#endif -") - -(define_insn "" - [(set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -#ifdef MOTOROLA - OUTPUT_JUMP (\"jbge %l0\", \"fbnlt %l0\", \"jbpl %l0\"); -#else - OUTPUT_JUMP (\"jge %l0\", \"fjnlt %l0\", \"jpl %l0\"); -#endif -") - -(define_insn "" - [(set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -#ifdef MOTOROLA - return \"jbcc %l0\"; -#else - return \"jcc %l0\"; -#endif -") - -(define_insn "" - [(set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -#ifdef MOTOROLA - OUTPUT_JUMP (\"jblt %l0\", \"fbnge %l0\", \"jbmi %l0\"); -#else - OUTPUT_JUMP (\"jlt %l0\", \"fjnge %l0\", \"jmi %l0\"); -#endif -") - -(define_insn "" - [(set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -#ifdef MOTOROLA - return \"jbcs %l0\"; -#else - return \"jcs %l0\"; -#endif -") - -(define_insn "" - [(set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -#ifdef MOTOROLA - OUTPUT_JUMP (\"jbgt %l0\", \"fbnle %l0\", 0); -#else - OUTPUT_JUMP (\"jgt %l0\", \"fjnle %l0\", 0); -#endif -") - -(define_insn "" - [(set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (pc) - (label_ref (match_operand 0 "" ""))))] - "" - "* -#ifdef MOTOROLA - return \"jbhi %l0\"; -#else - return \"jhi %l0\"; -#endif -") - -;; Unconditional and other jump instructions -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "* -#ifdef MOTOROLA - return \"jbra %l0\"; -#else - return \"jra %l0\"; -#endif -") - -;; We support two different ways of handling dispatch tables. -;; The NeXT uses absolute tables, and other machines use relative. -;; This define_expand can generate either kind. -(define_expand "tablejump" - [(parallel [(set (pc) (match_operand 0 "" "")) - (use (label_ref (match_operand 1 "" "")))])] - "" - " -{ -#ifdef CASE_VECTOR_PC_RELATIVE - operands[0] = gen_rtx (PLUS, SImode, pc_rtx, - gen_rtx (SIGN_EXTEND, SImode, operands[0])); -#endif -}") - -;; Jump to variable address from dispatch table of absolute addresses. -(define_insn "" - [(set (pc) (match_operand:SI 0 "register_operand" "a")) - (use (label_ref (match_operand 1 "" "")))] - "" - "* -#ifdef MOTOROLA - return \"jmp (%0)\"; -#else - return \"jmp %0@\"; -#endif -") - -;; Jump to variable address from dispatch table of relative addresses. -(define_insn "" - [(set (pc) - (plus:SI (pc) - (sign_extend:SI (match_operand:HI 0 "register_operand" "r")))) - (use (label_ref (match_operand 1 "" "")))] - "" - "* -#ifdef ASM_RETURN_CASE_JUMP - ASM_RETURN_CASE_JUMP; -#else -#ifdef SGS -#ifdef ASM_OUTPUT_CASE_LABEL - if (TARGET_5200) - return \"ext%.l %0\;jmp 6(%%pc,%0.l)\"; - else - return \"jmp 6(%%pc,%0.w)\"; -#else - if (TARGET_5200) - { -#ifdef CRDS - return \"ext%.l %0\;jmp 2(pc,%0.l)\"; -#else - return \"extl %0\;jmp 2(%%pc,%0.l)\"; -#endif /* end !CRDS */ - } - else - { -#ifdef CRDS - return \"jmp 2(pc,%0.w)\"; -#else - return \"jmp 2(%%pc,%0.w)\"; -#endif /* end !CRDS */ - } -#endif -#else /* not SGS */ - if (TARGET_5200) - { -#ifdef MOTOROLA - return \"ext%.l %0\;jmp (2,pc,%0.l)\"; -#else - return \"extl %0\;jmp pc@(2,%0:l)\"; -#endif - } - else - { -#ifdef MOTOROLA - return \"jmp (2,pc,%0.w)\"; -#else - return \"jmp pc@(2,%0:w)\"; -#endif - } -#endif -#endif -") - -;; Decrement-and-branch insns. -(define_insn "" - [(set (pc) - (if_then_else - (ne (match_operand:HI 0 "general_operand" "+d*g") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:HI (match_dup 0) - (const_int -1)))] - "!TARGET_5200" - "* -{ - CC_STATUS_INIT; - if (DATA_REG_P (operands[0])) - return \"dbra %0,%l1\"; - if (GET_CODE (operands[0]) == MEM) - { -#ifdef MOTOROLA -#ifdef NO_ADDSUB_Q - return \"sub%.w %#1,%0\;jbcc %l1\"; -#else - return \"subq%.w %#1,%0\;jbcc %l1\"; -#endif -#else /* not MOTOROLA */ - return \"subqw %#1,%0\;jcc %l1\"; -#endif - } -#ifdef MOTOROLA -#ifdef SGS_CMP_ORDER -#ifdef NO_ADDSUB_Q - return \"sub%.w %#1,%0\;cmp%.w %0,%#-1\;jbne %l1\"; -#else - return \"subq%.w %#1,%0\;cmp%.w %0,%#-1\;jbne %l1\"; -#endif -#else /* not SGS_CMP_ORDER */ - return \"subq%.w %#1,%0\;cmp%.w %#-1,%0\;jbne %l1\"; -#endif -#else /* not MOTOROLA */ - return \"subqw %#1,%0\;cmpw %#-1,%0\;jne %l1\"; -#endif -}") - -(define_insn "" - [(set (pc) - (if_then_else - (ne (match_operand:SI 0 "general_operand" "+d*g") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1)))] - "!TARGET_5200" - "* -{ - CC_STATUS_INIT; -#ifdef MOTOROLA -#ifdef NO_ADDSUB_Q - if (DATA_REG_P (operands[0])) - return \"dbra %0,%l1\;clr%.w %0\;sub%.l %#1,%0\;jbcc %l1\"; - if (GET_CODE (operands[0]) == MEM) - return \"sub%.l %#1,%0\;jbcc %l1\"; -#else - if (DATA_REG_P (operands[0])) - return \"dbra %0,%l1\;clr%.w %0\;subq%.l %#1,%0\;jbcc %l1\"; - if (GET_CODE (operands[0]) == MEM) - return \"subq%.l %#1,%0\;jbcc %l1\"; -#endif /* NO_ADDSUB_Q */ -#ifdef SGS_CMP_ORDER -#ifdef NO_ADDSUB_Q - return \"sub.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\"; -#else - return \"subq.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\"; -#endif -#else /* not SGS_CMP_ORDER */ - return \"subq.l %#1,%0\;cmp.l %#-1,%0\;jbne %l1\"; -#endif /* not SGS_CMP_ORDER */ -#else /* not MOTOROLA */ - if (DATA_REG_P (operands[0])) - return \"dbra %0,%l1\;clr%.w %0\;subql %#1,%0\;jcc %l1\"; - if (GET_CODE (operands[0]) == MEM) - return \"subql %#1,%0\;jcc %l1\"; - return \"subql %#1,%0\;cmpl %#-1,%0\;jne %l1\"; -#endif /* not MOTOROLA */ -}") - -;; Two dbra patterns that use REG_NOTES info generated by strength_reduce. - -(define_insn "" - [(set (pc) - (if_then_else - (ge (plus:HI (match_operand:HI 0 "general_operand" "+d*am") - (const_int -1)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:HI (match_dup 0) - (const_int -1)))] - "!TARGET_5200 && find_reg_note (insn, REG_NONNEG, 0)" - "* -{ - CC_STATUS_INIT; -#ifdef MOTOROLA -#ifdef NO_ADDSUB_Q - if (DATA_REG_P (operands[0])) - return \"dbra %0,%l1\"; - if (GET_CODE (operands[0]) == MEM) - return \"sub%.w %#1,%0\;jbcc %l1\"; -#else - if (DATA_REG_P (operands[0])) - return \"dbra %0,%l1\"; - if (GET_CODE (operands[0]) == MEM) - return \"subq%.w %#1,%0\;jbcc %l1\"; -#endif -#ifdef SGS_CMP_ORDER -#ifdef NO_ADDSUB_Q - return \"sub.w %#1,%0\;cmp.w %0,%#-1\;jbne %l1\"; -#else - return \"subq.w %#1,%0\;cmp.w %0,%#-1\;jbne %l1\"; -#endif -#else /* not SGS_CMP_ORDER */ - return \"subq.w %#1,%0\;cmp.w %#-1,%0\;jbne %l1\"; -#endif /* not SGS_CMP_ORDER */ -#else /* not MOTOROLA */ - if (DATA_REG_P (operands[0])) - return \"dbra %0,%l1\"; - if (GET_CODE (operands[0]) == MEM) - return \"subqw %#1,%0\;jcc %l1\"; - return \"subqw %#1,%0\;cmpw %#-1,%0\;jne %l1\"; -#endif /* not MOTOROLA */ -}") - -(define_expand "decrement_and_branch_until_zero" - [(parallel [(set (pc) - (if_then_else - (ge (plus:SI (match_operand:SI 0 "general_operand" "") - (const_int -1)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1)))])] - "" - "") - -(define_insn "" - [(set (pc) - (if_then_else - (ge (plus:SI (match_operand:SI 0 "general_operand" "+d*am") - (const_int -1)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1)))] - "!TARGET_5200 && find_reg_note (insn, REG_NONNEG, 0)" - "* -{ - CC_STATUS_INIT; -#ifdef MOTOROLA -#ifdef NO_ADDSUB_Q - if (DATA_REG_P (operands[0])) - return \"dbra %0,%l1\;clr%.w %0\;sub%.l %#1,%0\;jbcc %l1\"; - if (GET_CODE (operands[0]) == MEM) - return \"sub%.l %#1,%0\;jbcc %l1\"; -#else - if (DATA_REG_P (operands[0])) - return \"dbra %0,%l1\;clr%.w %0\;subq%.l %#1,%0\;jbcc %l1\"; - if (GET_CODE (operands[0]) == MEM) - return \"subq%.l %#1,%0\;jbcc %l1\"; -#endif -#ifdef SGS_CMP_ORDER -#ifdef NO_ADDSUB_Q - return \"sub.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\"; -#else - return \"subq.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\"; -#endif -#else /* not SGS_CMP_ORDER */ - return \"subq.l %#1,%0\;cmp.l %#-1,%0\;jbne %l1\"; -#endif /* not SGS_CMP_ORDER */ -#else /* not MOTOROLA */ - if (DATA_REG_P (operands[0])) - return \"dbra %0,%l1\;clr%.w %0\;subql %#1,%0\;jcc %l1\"; - if (GET_CODE (operands[0]) == MEM) - return \"subql %#1,%0\;jcc %l1\"; - return \"subql %#1,%0\;cmpl %#-1,%0\;jne %l1\"; -#endif /* not MOTOROLA */ -}") - - -;; 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. -;; -;; 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. -;; -;; 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 -;; done by using `OBJ@GOT'. So, the goal here is to output the function -;; call operand as `FUNC@PLTPC', but output object operand as `OBJ@GOT'. -;; We need to have a way to differentiate these two different operands. -;; -;; 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 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 -;; since the value is a PC relative offset, not a real address. -;; -;; All global objects are treated in the similar way as in SUN3. The only -;; difference is: on m68k svr4, the reference of such global object needs -;; to end with a suffix "@GOT" so the assembler and linker know to create -;; an entry for it in GOT (Global Offset Table) section. This is done in -;; m68k.c. - -;; Call subroutine with no return value. -(define_expand "call" - [(call (match_operand:QI 0 "memory_operand" "") - (match_operand:SI 1 "general_operand" ""))] - ;; Operand 1 not really used on the m68000. - - "" - " -{ - if (flag_pic && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF) - SYMBOL_REF_FLAG (XEXP (operands[0], 0)) = 1; -}") - -;; This is a normal call sequence. -(define_insn "" - [(call (match_operand:QI 0 "memory_operand" "o") - (match_operand:SI 1 "general_operand" "g"))] - ;; Operand 1 not really used on the m68000. - - "! flag_pic" - "* -#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\"; -#endif -") - -;; This is a PIC call sequence. -(define_insn "" - [(call (match_operand:QI 0 "memory_operand" "o") - (match_operand:SI 1 "general_operand" "g"))] - ;; Operand 1 not really used on the m68000. - - "flag_pic" - "* - 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\"; -") - -;; Call subroutine, returning value in operand 0 -;; (which must be a hard register). -;; See comments before "call" regarding PIC calls. -(define_expand "call_value" - [(set (match_operand 0 "" "") - (call (match_operand:QI 1 "memory_operand" "") - (match_operand:SI 2 "general_operand" "")))] - ;; Operand 2 not really used on the m68000. - "" - " -{ - if (flag_pic && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF) - SYMBOL_REF_FLAG (XEXP (operands[1], 0)) = 1; -}") - -;; This is a normal call_value -(define_insn "" - [(set (match_operand 0 "" "=rf") - (call (match_operand:QI 1 "memory_operand" "o") - (match_operand:SI 2 "general_operand" "g")))] - ;; Operand 2 not really used on the m68000. - "! flag_pic" - "* -#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\"; -#endif -") - -;; This is a PIC call_value -(define_insn "" - [(set (match_operand 0 "" "=rf") - (call (match_operand:QI 1 "memory_operand" "o") - (match_operand:SI 2 "general_operand" "g")))] - ;; Operand 2 not really used on the m68000. - "flag_pic" - "* - 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\"; -") - -;; Call subroutine returning any type. - -(define_expand "untyped_call" - [(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] - "NEEDS_UNTYPED_CALL" - " -{ - int i; - - emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx)); - - for (i = 0; i < XVECLEN (operands[2], 0); i++) - { - rtx set = XVECEXP (operands[2], 0, i); - emit_move_insn (SET_DEST (set), SET_SRC (set)); - } - - /* The optimizer does not know that the call sets the function value - registers we stored in the result block. We avoid problems by - claiming that all hard registers are used and clobbered at this - point. */ - emit_insn (gen_blockage ()); - - DONE; -}") - -;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and -;; all of memory. This blocks insns from being moved across this point. - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] - "" - "") - -(define_insn "nop" - [(const_int 0)] - "" - "nop") - -(define_insn "probe" - [(reg:SI 15)] - "NEED_PROBE" - "* -{ - operands[0] = gen_rtx (PLUS, SImode, stack_pointer_rtx, - gen_rtx (CONST_INT, VOIDmode, NEED_PROBE)); - return \"tstl %a0\"; -}") - -;; Used for frameless functions which save no regs and allocate no locals. -(define_insn "return" - [(return)] - "USE_RETURN_INSN" - "* -{ - if (current_function_pops_args == 0) - return \"rts\"; - operands[0] = gen_rtx (CONST_INT, VOIDmode, current_function_pops_args); - return \"rtd %0\"; -}") - -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "address_operand" "p"))] - "" - "jmp %a0") - -;; This should not be used unless the add/sub insns can't be. - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=a") - (match_operand:QI 1 "address_operand" "p"))] - "" - "* -{ -#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 -;; and then is moved into an FP register. -;; But it is mainly intended to test the support for these optimizations. - -(define_peephole - [(set (reg:SI 15) (plus:SI (reg:SI 15) (const_int 4))) - (set (match_operand:DF 0 "register_operand" "=f") - (match_operand:DF 1 "register_operand" "ad"))] - "FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])" - "* -{ - rtx xoperands[2]; - xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1); - output_asm_insn (\"move%.l %1,%@\", xoperands); - output_asm_insn (\"move%.l %1,%-\", operands); - return \"fmove%.d %+,%0\"; -} -") - -;; Optimize a stack-adjust followed by a push of an argument. -;; This is said to happen frequently with -msoft-float -;; when there are consecutive library calls. - -(define_peephole - [(set (reg:SI 15) (plus:SI (reg:SI 15) - (match_operand:SI 0 "const_int_operand" "n"))) - (set (match_operand:SF 1 "push_operand" "=m") - (match_operand:SF 2 "general_operand" "rmfF"))] - "INTVAL (operands[0]) >= 4 - && ! reg_mentioned_p (stack_pointer_rtx, operands[2])" - "* -{ - if (INTVAL (operands[0]) > 4) - { - rtx xoperands[2]; - xoperands[0] = stack_pointer_rtx; - xoperands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[0]) - 4); -#ifndef NO_ADDSUB_Q - if (INTVAL (xoperands[1]) <= 8) - { - if (!TARGET_5200) - output_asm_insn (\"addq%.w %1,%0\", xoperands); - else - output_asm_insn (\"addq%.l %1,%0\", xoperands); - } - else if (TARGET_CPU32 && INTVAL (xoperands[1]) <= 16) - { - xoperands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (xoperands[1]) - 8); - output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands); - } - else -#endif - if (INTVAL (xoperands[1]) <= 0x7FFF) - { - if (TARGET_68040) - output_asm_insn (\"add%.w %1,%0\", xoperands); - else -#ifdef MOTOROLA - output_asm_insn (\"lea (%c1,%0),%0\", xoperands); -#else - output_asm_insn (\"lea %0@(%c1),%0\", xoperands); -#endif - } - else - output_asm_insn (\"add%.l %1,%0\", xoperands); - } - if (FP_REG_P (operands[2])) - return \"fmove%.s %2,%@\"; - return \"move%.l %2,%@\"; -}") - -;; Speed up stack adjust followed by a fullword fixedpoint push. - -(define_peephole - [(set (reg:SI 15) (plus:SI (reg:SI 15) - (match_operand:SI 0 "const_int_operand" "n"))) - (set (match_operand:SI 1 "push_operand" "=m") - (match_operand:SI 2 "general_operand" "g"))] - "INTVAL (operands[0]) >= 4 - && ! reg_mentioned_p (stack_pointer_rtx, operands[2])" - "* -{ - if (INTVAL (operands[0]) > 4) - { - rtx xoperands[2]; - xoperands[0] = stack_pointer_rtx; - xoperands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[0]) - 4); -#ifndef NO_ADDSUB_Q - if (INTVAL (xoperands[1]) <= 8) - { - if (!TARGET_5200) - output_asm_insn (\"addq%.w %1,%0\", xoperands); - else - output_asm_insn (\"addq%.l %1,%0\", xoperands); - } - else if (TARGET_CPU32 && INTVAL (xoperands[1]) <= 16) - { - xoperands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (xoperands[1]) - 8); - output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands); - } - else -#endif - if (INTVAL (xoperands[1]) <= 0x7FFF) - { - if (TARGET_68040) - output_asm_insn (\"add%.w %1,%0\", xoperands); - else -#ifdef MOTOROLA - output_asm_insn (\"lea (%c1,%0),%0\", xoperands); -#else - output_asm_insn (\"lea %0@(%c1),%0\", xoperands); -#endif - } - else - output_asm_insn (\"add%.l %1,%0\", xoperands); - } - if (operands[2] == const0_rtx) - return \"clr%.l %@\"; - return \"move%.l %2,%@\"; -}") - -;; Speed up pushing a single byte but leaving four bytes of space. - -(define_peephole - [(set (mem:QI (pre_dec:SI (reg:SI 15))) - (match_operand:QI 1 "general_operand" "dami")) - (set (reg:SI 15) (minus:SI (reg:SI 15) (const_int 2)))] - "! reg_mentioned_p (stack_pointer_rtx, operands[1])" - "* -{ - rtx xoperands[4]; - - if (GET_CODE (operands[1]) == REG) - return \"move%.l %1,%-\"; - - xoperands[1] = operands[1]; - xoperands[2] - = gen_rtx (MEM, QImode, - gen_rtx (PLUS, VOIDmode, stack_pointer_rtx, - gen_rtx (CONST_INT, VOIDmode, 3))); - xoperands[3] = stack_pointer_rtx; - if (!TARGET_5200) - output_asm_insn (\"subq%.w %#4,%3\;move%.b %1,%2\", xoperands); - else - output_asm_insn (\"subq%.l %#4,%3\;move%.b %1,%2\", xoperands); - return \"\"; -}") - -(define_peephole - [(set (match_operand:SI 0 "register_operand" "=d") - (const_int 0)) - (set (strict_low_part (subreg:HI (match_dup 0) 0)) - (match_operand:HI 1 "general_operand" "rmn"))] - "strict_low_part_peephole_ok (HImode, prev_nonnote_insn (insn), operands[0])" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT) - { - if (operands[1] == const0_rtx - && (DATA_REG_P (operands[0]) - || GET_CODE (operands[0]) == MEM) - /* clr insns on 68000 read before writing. - This isn't so on the 68010, but we have no TARGET_68010. */ - && ((TARGET_68020 || TARGET_5200) - || !(GET_CODE (operands[0]) == MEM - && MEM_VOLATILE_P (operands[0])))) - return \"clr%.w %0\"; - } - return \"move%.w %1,%0\"; -}") - -;; dbCC peepholes -;; -;; Turns -;; loop: -;; [ ... ] -;; jCC label ; abnormal loop termination -;; dbra dN, loop ; normal loop termination -;; -;; Into -;; loop: -;; [ ... ] -;; dbCC dN, loop -;; jCC label -;; -;; Which moves the jCC condition outside the inner loop for free. -;; -(define_peephole - [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p" - [(cc0) (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc))) - (parallel - [(set (pc) - (if_then_else - (ge (plus:HI (match_operand:HI 0 "register_operand" "+d") - (const_int -1)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:HI (match_dup 0) - (const_int -1)))])] - "!TARGET_5200 && DATA_REG_P (operands[0]) && ! flags_in_68881 ()" - "* -{ - CC_STATUS_INIT; - output_dbcc_and_branch (operands); - return \"\"; -}") - -(define_peephole - [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p" - [(cc0) (const_int 0)]) - (label_ref (match_operand 2 "" "")) - (pc))) - (parallel - [(set (pc) - (if_then_else - (ge (plus:SI (match_operand:SI 0 "register_operand" "+d") - (const_int -1)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1)))])] - "!TARGET_5200 && DATA_REG_P (operands[0]) && ! flags_in_68881 ()" - "* -{ - CC_STATUS_INIT; - output_dbcc_and_branch (operands); - return \"\"; -}") - - -;; FPA multiply and add. -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=x,y,y") - (plus:DF (mult:DF (match_operand:DF 1 "general_operand" "%x,dmF,y") - (match_operand:DF 2 "general_operand" "xH,y,y")) - (match_operand:DF 3 "general_operand" "xH,y,dmF")))] - "TARGET_FPA" - "@ - fpma%.d %1,%w2,%w3,%0 - fpma%.d %x1,%x2,%x3,%0 - fpma%.d %x1,%x2,%x3,%0") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=x,y,y") - (plus:SF (mult:SF (match_operand:SF 1 "general_operand" "%x,ydmF,y") - (match_operand:SF 2 "general_operand" "xH,y,ydmF")) - (match_operand:SF 3 "general_operand" "xH,ydmF,ydmF")))] - "TARGET_FPA" - "@ - fpma%.s %1,%w2,%w3,%0 - fpma%.s %1,%2,%3,%0 - fpma%.s %1,%2,%3,%0") - -;; FPA Multiply and subtract -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=x,y,y") - (minus:DF (match_operand:DF 1 "general_operand" "xH,rmF,y") - (mult:DF (match_operand:DF 2 "general_operand" "%xH,y,y") - (match_operand:DF 3 "general_operand" "x,y,rmF"))))] - "TARGET_FPA" - "@ - fpms%.d %3,%w2,%w1,%0 - fpms%.d %x3,%2,%x1,%0 - fpms%.d %x3,%2,%x1,%0") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=x,y,y") - (minus:SF (match_operand:SF 1 "general_operand" "xH,rmF,yrmF") - (mult:SF (match_operand:SF 2 "general_operand" "%xH,rmF,y") - (match_operand:SF 3 "general_operand" "x,y,yrmF"))))] - "TARGET_FPA" - "@ - fpms%.s %3,%w2,%w1,%0 - fpms%.s %3,%2,%1,%0 - fpms%.s %3,%2,%1,%0") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=x,y,y") - (minus:DF (mult:DF (match_operand:DF 1 "general_operand" "%xH,y,y") - (match_operand:DF 2 "general_operand" "x,y,rmF")) - (match_operand:DF 3 "general_operand" "xH,rmF,y")))] - "TARGET_FPA" - "@ - fpmr%.d %2,%w1,%w3,%0 - fpmr%.d %x2,%1,%x3,%0 - fpmr%.d %x2,%1,%x3,%0") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=x,y,y") - (minus:SF (mult:SF (match_operand:SF 1 "general_operand" "%xH,rmF,y") - (match_operand:SF 2 "general_operand" "x,y,yrmF")) - (match_operand:SF 3 "general_operand" "xH,rmF,yrmF")))] - "TARGET_FPA" - "@ - fpmr%.s %2,%w1,%w3,%0 - fpmr%.s %x2,%1,%x3,%0 - fpmr%.s %x2,%1,%x3,%0") - -;; FPA Add and multiply -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=x,y,y") - (mult:DF (plus:DF (match_operand:DF 1 "general_operand" "%xH,y,y") - (match_operand:DF 2 "general_operand" "x,y,rmF")) - (match_operand:DF 3 "general_operand" "xH,rmF,y")))] - "TARGET_FPA" - "@ - fpam%.d %2,%w1,%w3,%0 - fpam%.d %x2,%1,%x3,%0 - fpam%.d %x2,%1,%x3,%0") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=x,y,y") - (mult:SF (plus:SF (match_operand:SF 1 "general_operand" "%xH,rmF,y") - (match_operand:SF 2 "general_operand" "x,y,yrmF")) - (match_operand:SF 3 "general_operand" "xH,rmF,yrmF")))] - "TARGET_FPA" - "@ - fpam%.s %2,%w1,%w3,%0 - fpam%.s %x2,%1,%x3,%0 - fpam%.s %x2,%1,%x3,%0") - -;;FPA Subtract and multiply -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=x,y,y") - (mult:DF (minus:DF (match_operand:DF 1 "general_operand" "xH,y,y") - (match_operand:DF 2 "general_operand" "x,y,rmF")) - (match_operand:DF 3 "general_operand" "xH,rmF,y")))] - "TARGET_FPA" - "@ - fpsm%.d %2,%w1,%w3,%0 - fpsm%.d %x2,%1,%x3,%0 - fpsm%.d %x2,%1,%x3,%0") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=x,y,y") - (mult:DF (match_operand:DF 1 "general_operand" "xH,rmF,y") - (minus:DF (match_operand:DF 2 "general_operand" "xH,y,y") - (match_operand:DF 3 "general_operand" "x,y,rmF"))))] - "TARGET_FPA" - "@ - fpsm%.d %3,%w2,%w1,%0 - fpsm%.d %x3,%2,%x1,%0 - fpsm%.d %x3,%2,%x1,%0") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=x,y,y") - (mult:SF (minus:SF (match_operand:SF 1 "general_operand" "xH,rmF,y") - (match_operand:SF 2 "general_operand" "x,y,yrmF")) - (match_operand:SF 3 "general_operand" "xH,rmF,yrmF")))] - "TARGET_FPA" - "@ - fpsm%.s %2,%w1,%w3,%0 - fpsm%.s %x2,%1,%x3,%0 - fpsm%.s %x2,%1,%x3,%0") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=x,y,y") - (mult:SF (match_operand:SF 1 "general_operand" "xH,rmF,yrmF") - (minus:SF (match_operand:SF 2 "general_operand" "xH,rmF,y") - (match_operand:SF 3 "general_operand" "x,y,yrmF"))))] - "TARGET_FPA" - "@ - fpsm%.s %3,%w2,%w1,%0 - fpsm%.s %x3,%2,%x1,%0 - fpsm%.s %x3,%2,%x1,%0") - -(define_expand "tstxf" - [(set (cc0) - (match_operand:XF 0 "nonimmediate_operand" ""))] - "TARGET_68881" - "m68k_last_compare_had_fp_operands = 1;") - -(define_insn "" - [(set (cc0) - (match_operand:XF 0 "nonimmediate_operand" "fm"))] - "TARGET_68881" - "* -{ - cc_status.flags = CC_IN_68881; - return \"ftst%.x %0\"; -}") - -(define_expand "cmpxf" - [(set (cc0) - (compare (match_operand:XF 0 "nonimmediate_operand" "") - (match_operand:XF 1 "nonimmediate_operand" "")))] - "TARGET_68881" - "m68k_last_compare_had_fp_operands = 1;") - -(define_insn "" - [(set (cc0) - (compare (match_operand:XF 0 "nonimmediate_operand" "f,m") - (match_operand:XF 1 "nonimmediate_operand" "fm,f")))] - "TARGET_68881" - "* -{ - cc_status.flags = CC_IN_68881; -#ifdef SGS_CMP_ORDER - if (REG_P (operands[0])) - { - if (REG_P (operands[1])) - return \"fcmp%.x %0,%1\"; - else - return \"fcmp%.x %0,%f1\"; - } - cc_status.flags |= CC_REVERSED; - return \"fcmp%.x %1,%f0\"; -#else - if (REG_P (operands[0])) - { - if (REG_P (operands[1])) - return \"fcmp%.x %1,%0\"; - else - return \"fcmp%.x %f1,%0\"; - } - cc_status.flags |= CC_REVERSED; - return \"fcmp%.x %f0,%1\"; -#endif -}") - -(define_insn "extendsfxf2" - [(set (match_operand:XF 0 "general_operand" "=fm,f") - (float_extend:XF (match_operand:SF 1 "general_operand" "f,m")))] - "TARGET_68881" - "* -{ - if (FP_REG_P (operands[0]) && FP_REG_P (operands[1])) - { - if (REGNO (operands[0]) == REGNO (operands[1])) - { - /* Extending float to double in an fp-reg is a no-op. - NOTICE_UPDATE_CC has already assumed that the - cc will be set. So cancel what it did. */ - cc_status = cc_prev_status; - return \"\"; - } - return \"f%$move%.x %1,%0\"; - } - if (FP_REG_P (operands[0])) - return \"f%$move%.s %f1,%0\"; - return \"fmove%.x %f1,%0\"; -}") - - -(define_insn "extenddfxf2" - [(set (match_operand:XF 0 "general_operand" "=fm,f") - (float_extend:XF - (match_operand:DF 1 "general_operand" "f,m")))] - "TARGET_68881" - "* -{ - if (FP_REG_P (operands[0]) && FP_REG_P (operands[1])) - { - if (REGNO (operands[0]) == REGNO (operands[1])) - { - /* Extending float to double in an fp-reg is a no-op. - NOTICE_UPDATE_CC has already assumed that the - cc will be set. So cancel what it did. */ - cc_status = cc_prev_status; - return \"\"; - } - return \"fmove%.x %1,%0\"; - } - if (FP_REG_P (operands[0])) - return \"f%&move%.d %f1,%0\"; - return \"fmove%.x %f1,%0\"; -}") - -(define_insn "truncxfdf2" - [(set (match_operand:DF 0 "general_operand" "=m,!r") - (float_truncate:DF - (match_operand:XF 1 "general_operand" "f,f")))] - "TARGET_68881" - "* -{ - if (REG_P (operands[0])) - { - output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands); - operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1); - return \"move%.l %+,%0\"; - } - return \"fmove%.d %f1,%0\"; -}") - -(define_insn "truncxfsf2" - [(set (match_operand:SF 0 "general_operand" "=dm") - (float_truncate:SF - (match_operand:XF 1 "general_operand" "f")))] - "TARGET_68881" - "fmove%.s %f1,%0") - -(define_insn "floatsixf2" - [(set (match_operand:XF 0 "general_operand" "=f") - (float:XF (match_operand:SI 1 "general_operand" "dmi")))] - "TARGET_68881" - "fmove%.l %1,%0") - -(define_insn "floathixf2" - [(set (match_operand:XF 0 "general_operand" "=f") - (float:XF (match_operand:HI 1 "general_operand" "dmn")))] - "TARGET_68881" - "fmove%.w %1,%0") - -(define_insn "floatqixf2" - [(set (match_operand:XF 0 "general_operand" "=f") - (float:XF (match_operand:QI 1 "general_operand" "dmn")))] - "TARGET_68881" - "fmove%.b %1,%0") - -(define_insn "ftruncxf2" - [(set (match_operand:XF 0 "general_operand" "=f") - (fix:XF (match_operand:XF 1 "general_operand" "fFm")))] - "TARGET_68881" - "* -{ - if (FP_REG_P (operands[1])) - return \"fintrz%.x %f1,%0\"; - return \"fintrz%.x %f1,%0\"; -}") - -(define_insn "fixxfqi2" - [(set (match_operand:QI 0 "general_operand" "=dm") - (fix:QI (match_operand:XF 1 "general_operand" "f")))] - "TARGET_68881" - "fmove%.b %1,%0") - -(define_insn "fixxfhi2" - [(set (match_operand:HI 0 "general_operand" "=dm") - (fix:HI (match_operand:XF 1 "general_operand" "f")))] - "TARGET_68881" - "fmove%.w %1,%0") - -(define_insn "fixxfsi2" - [(set (match_operand:SI 0 "general_operand" "=dm") - (fix:SI (match_operand:XF 1 "general_operand" "f")))] - "TARGET_68881" - "fmove%.l %1,%0") - -(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" - "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" "fm")))] - "TARGET_68881" - "* -{ - if (REG_P (operands[2])) - return \"fadd%.x %2,%0\"; - return \"fadd%.x %f2,%0\"; -}") - -(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" - "fsub%.l %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: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" - "* -{ - if (REG_P (operands[2])) - return \"fsub%.x %2,%0\"; - return \"fsub%.x %f2,%0\"; -}") - -(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" - "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" "fm")))] - "TARGET_68881" - "* -{ - if (REG_P (operands[2])) - return \"fmul%.x %2,%0\"; - return \"fmul%.x %f2,%0\"; -}") - -(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" - "fdiv%.l %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: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" - "* -{ - if (REG_P (operands[2])) - return \"fdiv%.x %2,%0\"; - return \"fdiv%.x %f2,%0\"; -}") - -(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" "fm")))] - "TARGET_68881" - "* -{ - if (REG_P (operands[1]) && ! DATA_REG_P (operands[1])) - return \"fneg%.x %1,%0\"; - return \"fneg%.x %f1,%0\"; -}") - -(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" "fm")))] - "TARGET_68881" - "* -{ - if (REG_P (operands[1]) && ! DATA_REG_P (operands[1])) - return \"fabs%.x %1,%0\"; - return \"fabs%.x %f1,%0\"; -}") - -(define_insn "sqrtxf2" - [(set (match_operand:XF 0 "general_operand" "=f") - (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" - "* -{ - 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") |