From-SVN: r221
129 KiB
;;- Machine description for GNU compiler ;;- Motorola 68000 Version ;; Copyright (C) 1987, 1988 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, 675 Mass Ave, Cambridge, MA 02139, USA.
;;- 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
;;- 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,%@ ;;- "%!" ??? "cc" (not used) ;;- "%$" single-precision fp specifier ("s" or "") f%$add.x fp0,fp1 ;;- "%&" double-precision fp specifier ("d" or "") f%&add.x fp0,fp1
;;- 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 "".
;;- 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 outputing ;;- 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 "" [(set (match_operand:DI 0 "push_operand" "=m") (match_operand:DI 1 "general_operand" "ro<>Fy"))] "" "* { 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_insn "tstsi" [(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 || ! 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_insn "tsthi" [(set (cc0) (match_operand:HI 0 "nonimmediate_operand" "dm"))] "" "tst%.w %0")
(define_insn "tstqi" [(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" " { 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" " { 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.
;; A composite of the cmp, cmpa, & cmpi m68000 op codes. (define_insn "cmpsi" [(set (cc0) (compare (match_operand:SI 0 "nonimmediate_operand" "rKs,mr,>") (match_operand:SI 1 "general_operand" "mr,Ksr,>")))] "" "* { if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) return "cmpm%.l %1,%0"; 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 "cmphi" [(set (cc0) (compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m") (match_operand:HI 1 "general_operand" "d,rnm,m,n")))] "" "* { if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) return "cmpm%.w %1,%0"; 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_insn "cmpqi" [(set (cc0) (compare (match_operand:QI 0 "nonimmediate_operand" "dn,md,>") (match_operand:QI 1 "general_operand" "dm,nd,>")))] "" "* { if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) return "cmpm%.b %1,%0"; 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" " { 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" " { 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 "nonimmediate_operand" "do") (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 "nonimmediate_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 "nonimmediate_operand" "do") (const_int 1) (minus:SI (const_int 7) (and:SI (match_operand:SI 1 "general_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 "nonimmediate_operand" "d") (const_int 1) (minus:SI (const_int 31) (and:SI (match_operand:SI 1 "general_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 "nonimmediate_operand" "md") (const_int 1) (match_operand:SI 1 "general_operand" "i")))] "GET_CODE (operands[1]) == CONST_INT && (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 "nonimmediate_operand" "do") (const_int 1) (match_operand:SI 1 "general_operand" "i")))] "GET_CODE (operands[1]) == CONST_INT" "* { 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 "" [(set (match_operand:SI 0 "push_operand" "=m") (match_operand:SI 1 "general_operand" "J"))] "GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) >= -0x8000 && INTVAL (operands[1]) < 0x8000" "* { 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 "" [(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 alternative for it. "(TARGET_68020 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))" "* { if (ADDRESS_REG_P (operands[0])) return "sub%.l %0,%0"; /* moveq is faster on the 68000. */ if (DATA_REG_P (operands[0]) && !TARGET_68020) #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 appropriatly 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,!xrm") (match_operand:SI 1 "general_operand" "daymKs,i,g,xrm"))] "" "* { 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"; 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 alternative for it. / && (TARGET_68020 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))) return "clr%.l %0"; else if (DATA_REG_P (operands[0]) && INTVAL (operands[1]) < 128 && INTVAL (operands[1]) >= -128) { #if defined(MOTOROLA) && !defined(CRDS) return "moveq%.l %1,%0"; #else return "moveq %1,%0"; #endif } #ifndef NO_ADDSUB_Q else if (DATA_REG_P (operands[0]) / Do this with a moveq #N-8, dreg; addq #8,dreg / && INTVAL (operands[1]) < 136 && INTVAL (operands[1]) >= 128) { operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) - 8); #if defined(MOTOROLA) && !defined(CRDS) return "moveq%.l %1,%0;addq%.w %#8,%0"; #else return "moveq %1,%0;addq%.w %#8,%0"; #endif } else if (DATA_REG_P (operands[0]) / Do this with a moveq #N+8, dreg; subq #8,dreg / && INTVAL (operands[1]) < -128 && INTVAL (operands[1]) >= -136) { operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) + 8); #if defined(MOTOROLA) && !defined(CRDS) return "moveq%.l %1,%0;subq%.w %#8,%0"; #else return "moveq %1,%0;subq%.w %#8,%0"; #endif } #endif else if (DATA_REG_P (operands[0]) / If N is in the right range and is even, then use moveq #N/2, dreg; addl dreg,dreg */ && INTVAL (operands[1]) > 127 && INTVAL (operands[1]) <= 254 && INTVAL (operands[1]) % 2 == 0) { operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) / 2); #if defined(MOTOROLA) && !defined(CRDS) return "moveq%.l %1,%0;add%.w %0,%0"; #else return "moveq %1,%0;add%.w %0,%0"; #endif } else if (ADDRESS_REG_P (operands[0]) && INTVAL (operands[1]) < 0x8000 && INTVAL (operands[1]) >= -0x8000) return "move%.w %1,%0"; else if (push_operand (operands[0], SImode) && INTVAL (operands[1]) < 0x8000 && INTVAL (operands[1]) >= -0x8000) return "pea %a1"; } else if ((GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST) && push_operand (operands[0], SImode)) return "pea %a1"; else if ((GET_CODE (operands[1]) == SYMBOL_REF || GET_CODE (operands[1]) == CONST) && ADDRESS_REG_P (operands[0])) return "lea %a1,%0"; return "move%.l %1,%0"; }")
(define_insn "movhi" [(set (match_operand:HI 0 "general_operand" "=g") (match_operand:HI 1 "general_operand" "g"))] "" "* { 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 alternative for it. / && (TARGET_68020 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))) return "clr%.w %0"; else if (DATA_REG_P (operands[0]) && INTVAL (operands[1]) < 128 && INTVAL (operands[1]) >= -128) { #if defined(MOTOROLA) && !defined(CRDS) return "moveq%.l %1,%0"; #else return "moveq %1,%0"; #endif } else if (INTVAL (operands[1]) < 0x8000 && INTVAL (operands[1]) >= -0x8000) return "move%.w %1,%0"; } else if (CONSTANT_P (operands[1])) return "move%.l %1,%0"; #ifndef SGS_NO_LI / Recognize the insn before a tablejump, one that refers to a table of offsets. Such an insn will need to refer to a label on the insn. So output one. Use the label-number of the table of offsets to generate this label. / if (GET_CODE (operands[1]) == MEM && GET_CODE (XEXP (operands[1], 0)) == PLUS && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF || GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF) && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) != PLUS) { rtx labelref; if (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF) labelref = XEXP (XEXP (operands[1], 0), 0); else labelref = XEXP (XEXP (operands[1], 0), 1); #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))); / For sake of 3b1, set flag saying we need to define the symbol LD%n (with value L%n-LI%n) at the end of the switch table. / RTX_INTEGRATED_P (next_real_insn (XEXP (labelref, 0))) = 1; #endif / SGS_SWITCH_TABLES or not MOTOROLA / } #endif / SGS_NO_LI */ return "move%.w %1,%0"; }")
(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 alternative for it. */ && (TARGET_68020 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))) return "clr%.w %0"; } return "move%.w %1,%0"; }")
(define_insn "movqi" [(set (match_operand:QI 0 "general_operand" "=d,a,m,m,?a") (match_operand:QI 1 "general_operand" "dmia,da,dmi,?a,m"))] "" " { rtx xoperands[4];
/* This is probably useless, since it loses for pushing a struct of several bytes a byte at a time. / if (GET_CODE (operands[0]) == MEM && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx) { xoperands[1] = operands[1]; xoperands[2] = gen_rtx (MEM, QImode, gen_rtx (PLUS, VOIDmode, stack_pointer_rtx, const1_rtx)); xoperands[3] = stack_pointer_rtx; / Just pushing a byte puts it in the high byte of the halfword. / / We must put it in the low-order, high-numbered byte. */ output_asm_insn ("subq%.w %#2,%3;move%.b %1,%2", xoperands); return ""; }
if (ADDRESS_REG_P (operands[0]) && GET_CODE (operands[1]) == MEM) { xoperands[1] = operands[1]; xoperands[2] = gen_rtx (MEM, QImode, gen_rtx (PLUS, VOIDmode, stack_pointer_rtx, const1_rtx)); xoperands[3] = stack_pointer_rtx; /* Just pushing a byte puts it in the high byte of the halfword. / / We must put it in the low half, the second byte. / output_asm_insn ("subq%.w %#2,%3;move%.b %1,%2", xoperands); return "move%.w %+,%0"; } if (ADDRESS_REG_P (operands[1]) && GET_CODE (operands[0]) == MEM) { xoperands[0] = operands[0]; xoperands[1] = operands[1]; xoperands[2] = gen_rtx (MEM, QImode, gen_rtx (PLUS, VOIDmode, stack_pointer_rtx, const1_rtx)); xoperands[3] = stack_pointer_rtx; output_asm_insn ("move%.w %1,%-;move%.b %2,%0;addq%.w %#2,%3", xoperands); return ""; } / clr and st insns on 68000 read before writing. This isn't so on the 68010, but we have no alternative for it. */ if (TARGET_68020 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) { if (operands[1] == const0_rtx) return "clr%.b %0"; if (GET_CODE (operands[1]) == CONST_INT && INTVAL (operands[1]) == -1) { CC_STATUS_INIT; return "st %0"; } } if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1])) return "move%.l %1,%0"; if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1])) return "move%.w %1,%0"; return "move%.b %1,%0"; }")
(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 alternative for it. */ && (TARGET_68020 || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))) return "clr%.b %0"; return "move%.b %1,%0"; }")
(define_insn "movsf" [(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"))] "" "* { 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 "movdf" [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>,y,rm,x,!x,!rm") (match_operand:DF 1 "general_operand" "rf,m,rofE<>,rmE,y,xH,rm,x"))] ; [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>") ; (match_operand:DF 1 "general_operand" "rf,m,rofF<>"))] "" "* { if (which_alternative == 6) 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); } ")
;; movdi can apply to fp regs in some cases (define_insn "movdi" ;; Let's see if it really still needs to handle fp regs, and, if so, why. [(set (match_operand:DI 0 "general_operand" "=rm,&r,&ro<>,y,rm,!*x,!rm") (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"))] "" " { 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); } ")
;; 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 mov.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 mov.w bases them on the entire 16 bits, not just the desired 8 bits. / CC_STATUS_INIT; return "move%.w %1,%0"; } if (GET_CODE (operands[0]) == REG) { / Must clear condition codes, since the mov.l bases them on 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 mov.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
(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.
(define_insn "" [(set (match_operand:SI 0 "general_operand" "=do<>,d<") (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rn,m")))] "" "* { 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" "dn,m")))] "" "* { 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" "dn,m")))] "" "* { 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 "extendhisi2" [(set (match_operand:SI 0 "general_operand" "=d,a") (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,rmn")))] "" " { 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" "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 "fsmove%.x %1,%0"; return "fsmove%.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_68040" "* { CC_STATUS_INIT; return "fmovem%.l fpcr,%2;moveq #16,%3;or%.l %2,%3;and%.w #-33,%3;fmovem%.l %3,fpcr;fmove%.l %1,%0;fmovem%.l %2,fpcr"; }")
(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_68040" "* { CC_STATUS_INIT; return "fmovem%.l fpcr,%2;moveq #16,%3;or%.l %2,%3;and%.w #-33,%3;fmovem%.l %3,fpcr;fmove%.w %1,%0;fmovem%.l %2,fpcr"; }")
(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_68040" "* { CC_STATUS_INIT; return "fmovem%.l fpcr,%2;moveq #16,%3;or%.l %2,%3;and%.w #-33,%3;fmovem%.l %3,fpcr;fmove%.b %1,%0;fmovem%.l %2,fpcr"; }")
;; 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
;; 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 (ADDRESS_REG_P (operands[0]) ? "addq%.w %2,%0" : "addq%.l %2,%0"); if (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) >= -8) { operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2])); return (ADDRESS_REG_P (operands[0]) ? "subq%.w %2,%0" : "subq%.l %2,%0"); } / On everything except the 68000 it is faster to use two addqw instuctions to add a small integer (8 < N <= 16) to an address register. Likewise for subqw.*/ if (INTVAL (operands[2]) > 8 && INTVAL (operands[2]) <= 16 && ADDRESS_REG_P (operands[0]) && TARGET_68020) { 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 && ADDRESS_REG_P (operands[0]) && TARGET_68020) { 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]) && INTVAL (operands[2]) >= -0x8000 && INTVAL (operands[2]) < 0x8000) return "add%.w %2,%0"; } 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"))))] "" "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")))] "" "* { #ifndef NO_ADDSUB_Q if (GET_CODE (operands[2]) == CONST_INT) { 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 everything except the 68000 it is faster to use two addqw instuctions to add a small integer (8 < N <= 16) to an address register. Likewise for subqw. */ if (INTVAL (operands[2]) > 8 && INTVAL (operands[2]) <= 16 && ADDRESS_REG_P (operands[0]) && TARGET_68020) { 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 && ADDRESS_REG_P (operands[0]) && TARGET_68020) { operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]) - 8); return "subq%.w %#8,%0; subq%.w %2,%0"; } } #endif return "add%.w %2,%0"; }")
(define_insn "" [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d")) (plus:HI (match_dup 0) (match_operand:HI 1 "general_operand" "dn,rmn")))] "" "add%.w %1,%0")
(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")))] "" "* { #ifndef NO_ADDSUB_Q if (GET_CODE (operands[2]) == CONST_INT) { if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 8) return "addq%.b %2,%0"; } if (GET_CODE (operands[2]) == CONST_INT) { if (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) >= -8) { operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2])); 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")))] "" "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 (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 (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 "subsi3" [(set (match_operand:SI 0 "general_operand" "=m,r,!a,?d") (minus:SI (match_operand:SI 1 "general_operand" "0,0,a,mrIKs") (match_operand:SI 2 "general_operand" "dIKs,mrIKs,J,0")))] "" "* { if (! operands_match_p (operands[0], operands[1])) { if (operands_match_p (operands[0], operands[2])) { #ifndef NO_ADDSUB_Q if (GET_CODE (operands[1]) == CONST_INT) { if (INTVAL (operands[1]) > 0 && INTVAL (operands[1]) <= 8) return "subq%.l %1,%0;neg%.l %0"; } #endif return "sub%.l %1,%0;neg%.l %0"; } /* This case is matched by J, but negating -0x8000 in an lea would give an invalid displacement. So do this specially. / if (INTVAL (operands[2]) == -0x8000) return "move%.l %1,%0;sub%.l %2,%0"; #ifdef SGS return "lea %n2(%1),%0"; #else #ifdef MOTOROLA return "lea (%n2,%1),%0"; #else / not MOTOROLA (MIT syntax) / return "lea %1@(%n2),%0"; #endif / not MOTOROLA / #endif / not SGS / } if (GET_CODE (operands[2]) == CONST_INT) { #ifndef NO_ADDSUB_Q if (INTVAL (operands[2]) > 0 && INTVAL (operands[2]) <= 8) return "subq%.l %2,%0"; / Using two subqw for 8 < N <= 16 being subtracted from an address register is faster on all but 68000 */ if (INTVAL (operands[2]) > 8 && INTVAL (operands[2]) <= 16 && ADDRESS_REG_P (operands[0]) && TARGET_68020) { 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]) && INTVAL (operands[2]) >= -0x8000 && INTVAL (operands[2]) < 0x8000) return "sub%.w %2,%0"; } return "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" "rmn"))))] "" "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")))] "" "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")))] "" "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")))] "" "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")))] "" "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") (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") (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" "dmn"))))] "" "* { #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")))] "" "* { #if defined(MOTOROLA) && !defined(CRDS) return "muls%.w %2,%0"; #else return "muls %2,%0"; #endif }")
(define_insn "mulsi3" [(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 "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" "dmn"))))] "" "* { #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")))] "" "* { #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) (subreg:SI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "")) (zero_extend:DI (match_operand:SI 2 "general_operand" ""))) 1)) (set (subreg:SI (match_dup 0) 0) (subreg:SI (mult:DI (zero_extend:DI (match_dup 1)) (zero_extend:DI (match_dup 2))) 0))])] "TARGET_68020" "")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (subreg:SI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) (zero_extend:DI (match_operand:SI 2 "general_operand" "dmsK"))) 1)) (set (match_operand:SI 3 "register_operand" "=d") (subreg:SI (mult:DI (zero_extend:DI (match_dup 1)) (zero_extend:DI (match_dup 2))) 0))] "TARGET_68020" "mulu%.l %2,%3:%0")
(define_expand "mulsidi3" [(parallel [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 1) (subreg:SI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "")) (sign_extend:DI (match_operand:SI 2 "general_operand" ""))) 1)) (set (subreg:SI (match_dup 0) 0) (subreg:SI (mult:DI (sign_extend:DI (match_dup 1)) (sign_extend:DI (match_dup 2))) 0))])] "TARGET_68020" "")
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (subreg:SI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) (sign_extend:DI (match_operand:SI 2 "general_operand" "dmKs"))) 1)) (set (match_operand:SI 3 "register_operand" "=d") (subreg:SI (mult:DI (sign_extend:DI (match_dup 1)) (sign_extend:DI (match_dup 2))) 0))] "TARGET_68020" "muls%.l %2,%3:%0")
(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 (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) { 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 (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 (TARGET_68040_ONLY ? "fsmul%.x %2,%0" : "fsglmul%.x %2,%0"); return (TARGET_68040_ONLY ? "fsmul%.s %f2,%0" : "fsglmul%.s %f2,%0"); }") ;; divide instructions
(define_insn "divhi3" [(set (match_operand:HI 0 "general_operand" "=d") (div:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "dmn")))] "" "* { #ifdef MOTOROLA return "ext%.l %0;divs%.w %2,%0"; #else return "extl %0;divs %2,%0"; #endif }")
(define_insn "divhisi3" [(set (match_operand:HI 0 "general_operand" "=d") (truncate:HI (div:SI (match_operand:SI 1 "general_operand" "0") (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "dm")))))] "" "* { #ifdef MOTOROLA return "divs%.w %2,%0"; #else return "divs %2,%0"; #endif }")
(define_insn "" [(set (match_operand:HI 0 "general_operand" "=d") (truncate:HI (div:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "const_int_operand" "n"))))] "" "* { #ifdef MOTOROLA return "divs%.w %2,%0"; #else return "divs %2,%0"; #endif }")
(define_insn "udivhi3" [(set (match_operand:HI 0 "general_operand" "=d") (udiv:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "dmn")))] "" "* { #ifdef MOTOROLA return "and%.l %#0xFFFF,%0;divu%.w %2,%0"; #else return "andl %#0xFFFF,%0;divu %2,%0"; #endif }")
(define_insn "udivhisi3" [(set (match_operand:HI 0 "general_operand" "=d") (truncate:HI (udiv:SI (match_operand:SI 1 "general_operand" "0") (zero_extend:SI (match_operand:HI 2 "nonimmediate_operand" "dm")))))] "" "* { #ifdef MOTOROLA return "divu%.w %2,%0"; #else return "divu %2,%0"; #endif }")
(define_insn "" [(set (match_operand:HI 0 "general_operand" "=d") (truncate:HI (udiv:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "const_int_operand" "n"))))] "" "* { #ifdef MOTOROLA return "divu%.w %2,%0"; #else return "divu %2,%0"; #endif }")
(define_expand "divdf3" [(set (match_operand:DF 0 "general_operand" "") (div:DF (match_operand:DF 1 "general_operand" "") (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") (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") (match_operand:SF 2 "general_operand" "fdmF")))] "TARGET_68881" "* { if (REG_P (operands[2]) && ! DATA_REG_P (operands[2])) return (TARGET_68040_ONLY ? "fsdiv%.x %2,%0" : "fsgldiv%.x %2,%0"); return (TARGET_68040_ONLY ? "fsdiv%.s %f2,%0" : "fsgldiv%.s %f2,%0"); }") ;; Remainder instructions.
(define_insn "modhi3" [(set (match_operand:HI 0 "general_operand" "=d") (mod:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "dmn")))] "" "* { /* The swap insn produces cc's that don't correspond to the result. */ CC_STATUS_INIT; #ifdef MOTOROLA #ifdef SGS_SWAP_W return "ext%.l %0;divs%.w %2,%0;swap%.w %0"; #else return "ext%.l %0;divs%.w %2,%0;swap %0"; #endif #else return "extl %0;divs %2,%0;swap %0"; #endif }")
(define_insn "modhisi3" [(set (match_operand:HI 0 "general_operand" "=d") (truncate:HI (mod:SI (match_operand:SI 1 "general_operand" "0") (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "dm")))))] "" "* { /* The swap insn produces cc's that don't correspond to the result. */ CC_STATUS_INIT; #ifdef MOTOROLA #ifdef SGS_SWAP_W return "divs%.w %2,%0;swap%.w %0"; #else return "divs%.w %2,%0;swap %0"; #endif #else return "divs %2,%0;swap %0"; #endif }")
(define_insn "" [(set (match_operand:HI 0 "general_operand" "=d") (truncate:HI (mod:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "const_int_operand" "n"))))] "" "* { /* The swap insn produces cc's that don't correspond to the result. */ CC_STATUS_INIT; #ifdef MOTOROLA #ifdef SGS_SWAP_W return "divs%.w %2,%0;swap%.w %0"; #else return "divs%.w %2,%0;swap %0"; #endif #else return "divs %2,%0;swap %0"; #endif }")
(define_insn "umodhi3" [(set (match_operand:HI 0 "general_operand" "=d") (umod:HI (match_operand:HI 1 "general_operand" "0") (match_operand:HI 2 "general_operand" "dmn")))] "" "* { /* The swap insn produces cc's that don't correspond to the result. */ CC_STATUS_INIT; #ifdef MOTOROLA #ifdef SGS_SWAP_W return "and%.l %#0xFFFF,%0;divu%.w %2,%0;swap%.w %0"; #else return "and%.l %#0xFFFF,%0;divu%.w %2,%0;swap %0"; #endif #else return "andl %#0xFFFF,%0;divu %2,%0;swap %0"; #endif }")
(define_insn "umodhisi3" [(set (match_operand:HI 0 "general_operand" "=d") (truncate:HI (umod:SI (match_operand:SI 1 "general_operand" "0") (zero_extend:SI (match_operand:HI 2 "nonimmediate_operand" "dm")))))] "" "* { /* The swap insn produces cc's that don't correspond to the result. */ CC_STATUS_INIT; #ifdef MOTOROLA #ifdef SGS_SWAP_W return "divu%.w %2,%0;swap%.w %0"; #else return "divu%.w %2,%0;swap %0"; #endif #else return "divu %2,%0;swap %0"; #endif }")
(define_insn "" [(set (match_operand:HI 0 "general_operand" "=d") (truncate:HI (umod:SI (match_operand:SI 1 "general_operand" "0") (match_operand:SI 2 "const_int_operand" "n"))))] "" "* { /* The swap insn produces cc's that don't correspond to the result. */ CC_STATUS_INIT; #ifdef MOTOROLA #ifdef SGS_SWAP_W return "divu%.w %2,%0;swap%.w %0"; #else return "divu%.w %2,%0;swap %0"; #endif #else return "divu %2,%0;swap %0"; #endif }")
(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" "* { 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" "* { if (find_reg_note (insn, REG_UNUSED, operands[3])) return "divu%.l %2,%0"; else return "divul%.l %2,%3:%0"; }") ;; 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 psuedos into it. (define_insn "andsi3" [(set (match_operand:SI 0 "not_sp_operand" "=m,d") (and:SI (match_operand:SI 1 "general_operand" "%0,0") (match_operand:SI 2 "general_operand" "dKs,dmKs")))] "" "* { 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 "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")))] "" "and%.w %2,%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")))] "" "and%.b %2,%0")
;; inclusive-or instructions
(define_insn "iorsi3" [(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,dmKs")))] "" "* { 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); } return "bset %1,%0"; } return "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")))] "" "or%.w %2,%0")
(define_insn "iorqi3" [(set (match_operand:QI 0 "general_operand" "=m,d") (ior:QI (match_operand:QI 1 "general_operand" "%0,0") (match_operand:QI 2 "general_operand" "dn,dmn")))] "" "or%.b %2,%0") ;; xor instructions
(define_insn "xorsi3" [(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")))] "" "* { 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 "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")))] "" "eor%.w %2,%0")
(define_insn "xorqi3" [(set (match_operand:QI 0 "general_operand" "=dm") (xor:QI (match_operand:QI 1 "general_operand" "%0") (match_operand:QI 2 "general_operand" "dn")))] "" "eor%.b %2,%0") ;; negation instructions
(define_insn "negsi2" [(set (match_operand:SI 0 "general_operand" "=dm") (neg:SI (match_operand:SI 1 "general_operand" "0")))] "" "neg%.l %0")
(define_insn "neghi2" [(set (match_operand:HI 0 "general_operand" "=dm") (neg:HI (match_operand:HI 1 "general_operand" "0")))] "" "neg%.w %0")
(define_insn "negqi2" [(set (match_operand:QI 0 "general_operand" "=dm") (neg:QI (match_operand:QI 1 "general_operand" "0")))] "" "neg%.b %0")
(define_expand "negsf2" [(set (match_operand:SF 0 "general_operand" "") (neg:SF (match_operand:SF 1 "general_operand" "")))] "TARGET_68881 || TARGET_FPA" "")
(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" "")))] "TARGET_68881 || TARGET_FPA" "")
(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"; }") ;; Absolute value instructions
(define_expand "abssf2" [(set (match_operand:SF 0 "general_operand" "") (abs:SF (match_operand:SF 1 "general_operand" "")))] "TARGET_68881 || TARGET_FPA" "")
(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" "")))] "TARGET_68881 || TARGET_FPA" "")
(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
(define_insn "one_cmplsi2" [(set (match_operand:SI 0 "general_operand" "=dm") (not:SI (match_operand:SI 1 "general_operand" "0")))] "" "not%.l %0")
(define_insn "one_cmplhi2" [(set (match_operand:HI 0 "general_operand" "=dm") (not:HI (match_operand:HI 1 "general_operand" "0")))] "" "not%.w %0")
(define_insn "one_cmplqi2" [(set (match_operand:QI 0 "general_operand" "=dm") (not:QI (match_operand:QI 1 "general_operand" "0")))] "" "not%.b %0") ;; arithmetic shift instructions ;; We don't need the shift memory by 1 bit instruction
;; On the 68000, this makes faster code in a special case.
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (ashift:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "immediate_operand" "i")))] "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 16 && INTVAL (operands[2]) <= 24)" "* { CC_STATUS_INIT;
if (INTVAL (operands[2]) == 16) return "swap %0;clrw %0";
operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16); return "asl%.w %2,%0;swap %0;clrw %0"; }")
(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) return "add%.l %0,%0"; return "asl%.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")))] "" "asl%.w %2,%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")))] "" "asl%.b %2,%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 "immediate_operand" "i")))] "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 16 && INTVAL (operands[2]) <= 24)" "* { if (INTVAL (operands[2]) == 16) return "swap %0;ext%.l %0";
operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16); return "swap %0;asr%.w %2,%0;ext%.l %0"; }")
(define_insn "ashrsi3" [(set (match_operand:SI 0 "register_operand" "=d") (ashiftrt:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "general_operand" "dI")))] "" "* { return "asr%.l %2,%0"; }")
(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")))] "" "asr%.w %2,%0")
(define_insn "ashrqi3" [(set (match_operand:QI 0 "register_operand" "=d") (ashiftrt:QI (match_operand:QI 1 "register_operand" "0") (match_operand:QI 2 "general_operand" "dI")))] "" "asr%.b %2,%0") ;; logical shift instructions
;; On the 68000, this makes faster code in a special case.
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (lshift:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "immediate_operand" "i")))] "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 16 && INTVAL (operands[2]) <= 24)" "* { CC_STATUS_INIT;
if (INTVAL (operands[2]) == 16) return "swap %0;clrw %0";
operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16); return "lsl%.w %2,%0;swap %0;clrw %0"; }")
(define_insn "lshlsi3" [(set (match_operand:SI 0 "register_operand" "=d") (lshift:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "general_operand" "dI")))] "" "* { if (operands[2] == const1_rtx) return "add%.l %0,%0"; return "lsl%.l %2,%0"; }")
(define_insn "lshlhi3" [(set (match_operand:HI 0 "register_operand" "=d") (lshift:HI (match_operand:HI 1 "register_operand" "0") (match_operand:HI 2 "general_operand" "dI")))] "" "lsl%.w %2,%0")
(define_insn "lshlqi3" [(set (match_operand:QI 0 "register_operand" "=d") (lshift:QI (match_operand:QI 1 "register_operand" "0") (match_operand:QI 2 "general_operand" "dI")))] "" "lsl%.b %2,%0")
;; On the 68000, this makes faster code in a special case.
(define_insn "" [(set (match_operand:SI 0 "register_operand" "=d") (lshiftrt:SI (match_operand:SI 1 "register_operand" "0") (match_operand:SI 2 "immediate_operand" "i")))] "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) >= 16 && INTVAL (operands[2]) <= 24)" "* { if (INTVAL (operands[2]) == 16) { CC_STATUS_INIT; return "clrw %0;swap %0"; }
/* I think lsr%.w sets the CC properly. */ operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16); return "clrw %0;swap %0;lsr%.w %2,%0"; }")
(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")))] "" "* { return "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")))] "" "lsr%.w %2,%0")
(define_insn "lshrqi3" [(set (match_operand:QI 0 "register_operand" "=d") (lshiftrt:QI (match_operand:QI 1 "register_operand" "0") (match_operand:QI 2 "general_operand" "dI")))] "" "lsr%.b %2,%0") ;; 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" "dI")))] "" "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" "dI")))] "" "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")))] "" "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")))] "" "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")))] "" "ror%.w %2,%0")
(define_insn "rotrqi3" [(set (match_operand:QI 0 "register_operand" "=d") (rotatert:QI (match_operand:QI 1 "register_operand" "0") (match_operand:QI 2 "general_operand" "dI")))] "" "ror%.b %2,%0") ;; 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 "nonimmediate_operand" "o") (match_operand:SI 1 "immediate_operand" "i") (match_operand:SI 2 "immediate_operand" "i")) (match_operand:SI 3 "general_operand" "rmi"))] "TARGET_68020 && TARGET_BITFIELD && GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) == 32) && GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) % 8) == 0 && ! mode_dependent_address_p (XEXP (operands[0], 0))" "* { 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 "nonimmediate_operand" "+do") (match_operand:SI 1 "immediate_operand" "i") (match_operand:SI 2 "immediate_operand" "i")) (match_operand:SI 3 "general_operand" "d"))] "TARGET_68020 && TARGET_BITFIELD && GET_CODE (operands[1]) == CONST_INT && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16) && GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) % INTVAL (operands[1]) == 0 && (GET_CODE (operands[0]) == REG || ! mode_dependent_address_p (XEXP (operands[0], 0)))" "* { 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 "nonimmediate_operand" "o") (match_operand:SI 2 "immediate_operand" "i") (match_operand:SI 3 "immediate_operand" "i")))] "TARGET_68020 && TARGET_BITFIELD && GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) == 32) && GET_CODE (operands[3]) == CONST_INT && (INTVAL (operands[3]) % 8) == 0 && ! mode_dependent_address_p (XEXP (operands[1], 0))" "* { 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 "nonimmediate_operand" "do") (match_operand:SI 2 "immediate_operand" "i") (match_operand:SI 3 "immediate_operand" "i")))] "TARGET_68020 && TARGET_BITFIELD && GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) && GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) % INTVAL (operands[2]) == 0 && (GET_CODE (operands[1]) == REG || ! mode_dependent_address_p (XEXP (operands[1], 0)))" "* { 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 "nonimmediate_operand" "o") (match_operand:SI 2 "immediate_operand" "i") (match_operand:SI 3 "immediate_operand" "i")))] "TARGET_68020 && TARGET_BITFIELD && GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) == 32) && GET_CODE (operands[3]) == CONST_INT && (INTVAL (operands[3]) % 8) == 0 && ! mode_dependent_address_p (XEXP (operands[1], 0))" "* { 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 "nonimmediate_operand" "do") (match_operand:SI 2 "immediate_operand" "i") (match_operand:SI 3 "immediate_operand" "i")))] "TARGET_68020 && TARGET_BITFIELD && GET_CODE (operands[2]) == CONST_INT && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16) && GET_CODE (operands[3]) == CONST_INT && INTVAL (operands[3]) % INTVAL (operands[2]) == 0 && (GET_CODE (operands[1]) == REG || ! mode_dependent_address_p (XEXP (operands[1], 0)))" "* { 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_insn "extv" [(set (match_operand:SI 0 "general_operand" "=d,d") (sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o,d") (match_operand:SI 2 "general_operand" "di,di") (match_operand:SI 3 "general_operand" "di,di")))] "TARGET_68020 && TARGET_BITFIELD" "bfexts %1{%b3:%b2},%0")
(define_insn "extzv" [(set (match_operand:SI 0 "general_operand" "=d,d") (zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o,d") (match_operand:SI 2 "general_operand" "di,di") (match_operand:SI 3 "general_operand" "di,di")))] "TARGET_68020 && TARGET_BITFIELD" "* { cc_status.flags |= CC_NOT_NEGATIVE; return "bfextu %1{%b3:%b2},%0"; }")
(define_insn "" [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d") (match_operand:SI 1 "general_operand" "di,di") (match_operand:SI 2 "general_operand" "di,di")) (xor:SI (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2)) (match_operand 3 "immediate_operand" "i,i")))] "TARGET_68020 && TARGET_BITFIELD && GET_CODE (operands[3]) == CONST_INT && (INTVAL (operands[3]) == -1 || (GET_CODE (operands[1]) == CONST_INT && (~ INTVAL (operands[3]) & ((1 << INTVAL (operands[1]))- 1)) == 0))" "* { CC_STATUS_INIT; return "bfchg %0{%b2:%b1}"; }")
(define_insn "" [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d") (match_operand:SI 1 "general_operand" "di,di") (match_operand:SI 2 "general_operand" "di,di")) (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 "nonimmediate_operand" "+o,d") (match_operand:SI 1 "general_operand" "di,di") (match_operand:SI 2 "general_operand" "di,di")) (const_int -1))] "TARGET_68020 && TARGET_BITFIELD" "* { CC_STATUS_INIT; return "bfset %0{%b2:%b1}"; }")
(define_insn "insv" [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d") (match_operand:SI 1 "general_operand" "di,di") (match_operand:SI 2 "general_operand" "di,di")) (match_operand:SI 3 "general_operand" "d,d"))] "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 "nonimmediate_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 "nonimmediate_operand" "d") (match_operand:SI 2 "general_operand" "di") (match_operand:SI 3 "general_operand" "di")))] "TARGET_68020 && TARGET_BITFIELD" "* { cc_status.flags |= CC_NOT_NEGATIVE; return "bfextu %1{%b3:%b2},%0"; }")
(define_insn "" [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d") (match_operand:SI 1 "general_operand" "di") (match_operand:SI 2 "general_operand" "di")) (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 "nonimmediate_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 "nonimmediate_operand" "+d") (match_operand:SI 1 "general_operand" "di") (match_operand:SI 2 "general_operand" "di")) (match_operand:SI 3 "general_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 "general_operand" "di")
(match_operand:SI 2 "general_operand" "di")))]
"TARGET_68020 && TARGET_BITFIELD
&& GET_CODE (operands[1]) == CONST_INT"
"*
{
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 "nonimmediate_operand" "d")
(match_operand:SI 1 "general_operand" "di")
(match_operand:SI 2 "general_operand" "di")))]
"TARGET_68020 && TARGET_BITFIELD
&& GET_CODE (operands[1]) == CONST_INT"
"*
{
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 "seq"
[(set (match_operand:QI 0 "general_operand" "=d")
(eq:QI (cc0) (const_int 0)))]
""
"
cc_status = cc_prev_status;
OUTPUT_JUMP ("seq %0", "fseq %0", "seq %0");
")
(define_insn "sne" [(set (match_operand:QI 0 "general_operand" "=d") (ne:QI (cc0) (const_int 0)))] "" "* cc_status = cc_prev_status; OUTPUT_JUMP ("sne %0", "fsne %0", "sne %0"); ")
(define_insn "sgt" [(set (match_operand:QI 0 "general_operand" "=d") (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" "=d") (gtu:QI (cc0) (const_int 0)))] "" "* cc_status = cc_prev_status; return "shi %0"; ")
(define_insn "slt" [(set (match_operand:QI 0 "general_operand" "=d") (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" "=d") (ltu:QI (cc0) (const_int 0)))] "" "* cc_status = cc_prev_status; return "scs %0"; ")
(define_insn "sge" [(set (match_operand:QI 0 "general_operand" "=d") (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" "=d") (geu:QI (cc0) (const_int 0)))] "" "* cc_status = cc_prev_status; return "scc %0"; ")
(define_insn "sle" [(set (match_operand:QI 0 "general_operand" "=d") (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" "=d") (leu:QI (cc0) (const_int 0)))] "" "* cc_status = cc_prev_status; return "sls %0"; ") ;; Basic conditional jump instructions.
(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, 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) (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 return "jmp 6(%%pc,%0.w)"; #else #ifdef CRDS return "jmp 2(pc,%0.w)"; #else return "jmp 2(%%pc,%0.w)"; #endif /* end !CRDS / #endif #else / not SGS */ #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" "+g") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) (set (match_dup 0) (plus:HI (match_dup 0) (const_int -1)))] "" "* { 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 #ifndef 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" "+g") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] "" "* { CC_STATUS_INIT; #ifdef MOTOROLA #ifndef 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 /* not NO_ADDSUB_Q / #ifdef SGS_CMP_ORDER #ifndef 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;clrw %0;subql %#1,%0;jcc %l1"; if (GET_CODE (operands[0]) == MEM) return "subql %#1,%0;jcc %l1"; return "subql %#1,%0;cmpl %#-1,%0;jne %l1"; #endif / not MOTOROLA */ }")
;; dbra patterns that use REG_NOTES info generated by strength_reduce.
(define_insn "decrement_and_branch_until_zero" [(set (pc) (if_then_else (gt (match_operand:SI 0 "general_operand" "+g") (const_int 0)) (label_ref (match_operand 1 "" "")) (pc))) (set (match_dup 0) (plus:SI (match_dup 0) (const_int -1)))] "find_reg_note (insn, REG_NONNEG, 0)" "* { CC_STATUS_INIT; #ifdef MOTOROLA #ifndef 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 #ifndef 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;clrw %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 */ }")
;; PIC calls are handled by loading the address of the function into a ;; register (via movsi), then emitting a register indirect call using ;; the "jsr" function call syntax. ;; ;; It is important to note that the "jsr" syntax is always used for ;; PIC calls, even on machines in which GCC normally uses the "jbsr" ;; syntax for non-PIC calls. This keeps at least 1 assembler (Sun) ;; from emitting incorrect code for a PIC call. ;; ;; We have different patterns for PIC calls and non-PIC calls. The ;; different patterns are only used to choose the right syntax ;; ("jsr" vs "jbsr").
;; 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) operands[0] = gen_rtx (MEM, GET_MODE (operands[0]), force_reg (Pmode, XEXP (operands[0], 0))); }")
;; 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" "* #ifdef MOTOROLA 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" "* 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) operands[1] = gen_rtx (MEM, GET_MODE (operands[1]), force_reg (Pmode, XEXP (operands[1], 0))); }")
;; 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" "* #ifdef MOTOROLA 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" "* return "jsr %1"; ")
(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 %0"; }")
;; Used for framless 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 "register_operand" "a"))] "" "* #ifdef MOTOROLA return "jmp (%0)"; #else return "jmp %0@"; #endif ") ;; 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"))] "" "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 "immediate_operand" "n"))) (set (match_operand:SF 1 "push_operand" "=m") (match_operand:SF 2 "general_operand" "rmfF"))] "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) >= 4 && ! 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) output_asm_insn ("addq%.w %1,%0", xoperands); else if (INTVAL (xoperands[1]) <= 16 && TARGET_68020) { 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) output_asm_insn ("add%.w %1,%0", xoperands); 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 "immediate_operand" "n"))) (set (match_operand:SI 1 "push_operand" "=m") (match_operand:SI 2 "general_operand" "g"))] "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) >= 4 && ! 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) output_asm_insn ("addq%.w %1,%0", xoperands); else if (INTVAL (xoperands[1]) <= 16 && TARGET_68020) { 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) output_asm_insn ("add%.w %1,%0", xoperands); 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; output_asm_insn ("subq%.w %#4,%3;move%.b %1,%2", xoperands); 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") ;;- Local variables: ;;- mode:emacs-lisp ;;- comment-start: ";;- " ;;- comment-start-skip: ";+- *" ;;- eval: (set-syntax-table (copy-sequence (syntax-table))) ;;- eval: (modify-syntax-entry ?[ "(]") ;;- eval: (modify-syntax-entry ?] ")[") ;;- eval: (modify-syntax-entry ?{ "(}") ;;- eval: (modify-syntax-entry ?} "){") ;;- End: