159693Selan;;- Machine description for GNU compiler
259693Selan;;- Motorola 68000 Version
359693Selan;;   Copyright (C) 1987, 1988 Free Software Foundation, Inc.
459693Selan
559693Selan;; This file is part of GNU CC.
659693Selan
759693Selan;; GNU CC is free software; you can redistribute it and/or modify
859693Selan;; it under the terms of the GNU General Public License as published by
959693Selan;; the Free Software Foundation; either version 2, or (at your option)
1059693Selan;; any later version.
1159693Selan
1259693Selan;; GNU CC is distributed in the hope that it will be useful,
1359693Selan;; but WITHOUT ANY WARRANTY; without even the implied warranty of
1459693Selan;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1559693Selan;; GNU General Public License for more details.
1659693Selan
1759693Selan;; You should have received a copy of the GNU General Public License
1859693Selan;; along with GNU CC; see the file COPYING.  If not, write to
1959693Selan;; the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
2059693Selan
2159693Selan
2259693Selan;;- instruction definitions
2359693Selan
2459693Selan;;- @@The original PO technology requires these to be ordered by speed,
2559693Selan;;- @@    so that assigner will pick the fastest.
2659693Selan
2759693Selan;;- See file "rtl.def" for documentation on define_insn, match_*, et. al.
2859693Selan
2959693Selan;;- When naming insn's (operand 0 of define_insn) be careful about using
3059693Selan;;- names from other targets machine descriptions.
3159693Selan
3259693Selan;;- cpp macro #define NOTICE_UPDATE_CC in file tm.h handles condition code
3359693Selan;;- updates for most instructions.
3459693Selan
3559693Selan;;- Operand classes for the register allocator:
3659693Selan;;- 'a' one of the address registers can be used.
3759693Selan;;- 'd' one of the data registers can be used.
3859693Selan;;- 'f' one of the m68881 registers can be used
3959693Selan;;- 'r' either a data or an address register can be used.
4059693Selan;;- 'x' if one of the Sun FPA registers
4159693Selan;;- 'y' if one of the Low Sun FPA registers (fpa0-fpa15).
4259693Selan
4359693Selan;;- Immediate Floating point operator constraints
4459693Selan;;- 'G' a floating point constant that is *NOT* one of the standard
4559693Selan;;   68881 constant values (to force calling output_move_const_double
4659693Selan;;   to get it from rom if it is a 68881 constant).
4759693Selan;;- 'H' one of the standard FPA constant values
4859693Selan;;
4959693Selan;;   See the functions standard_XXX_constant_p in output-m68k.c for more
5059693Selan;; info.
5159693Selan
5259693Selan;;- Immediate integer operand constraints:
5359693Selan;;- 'I'  1 .. 8
5459693Selan;;- 'J'  -32768 .. 32767
5559693Selan;;- 'K'  all integers EXCEPT -128 .. 127
5659693Selan;;- 'L'  -8 .. -1
5759693Selan
5859693Selan;;- Assembler specs:
5959693Selan;;- "%."    size separator ("." or "")			move%.l d0,d1
6059693Selan;;- "%#"    immediate separator ("#" or "")		move%.l %#0,d0
6159693Selan;;- "%-"    push operand "sp@-"				move%.l d0,%-
6259693Selan;;- "%+"    pop operand "sp@+"				move%.l d0,%+
6359693Selan;;- "%@"    top of stack "sp@"				move%.l d0,%@
6459693Selan;;- "%!"    fpcr register
6559693Selan;;- "%$"    single-precision fp specifier ("s" or "")	f%$add.x fp0,fp1
6659693Selan;;- "%&"    double-precision fp specifier ("d" or "")	f%&add.x fp0,fp1
6759693Selan
6859693Selan;;- Information about 68040 port.
6959693Selan
7059693Selan;;- The 68040 executes all 68030 and 68881/2 instructions, but some must
7159693Selan;;- be emulated in software by the OS.  It is faster to avoid these
7259693Selan;;- instructions and issue a library call rather than trapping into
7359693Selan;;- the kernel.  The affected instructions are fintrz and fscale.  The
7459693Selan;;- TARGET_68040 flag turns the use of the opcodes off.
7559693Selan
7659693Selan;;- The '040 also implements a set of new floating-point instructions
7759693Selan;;- which specify the rounding precision in the opcode.  This finally
7859693Selan;;- permit the 68k series to be truly IEEE compliant, and solves all
7959693Selan;;- issues of excess precision accumulating in the extended registers.
8059693Selan;;- By default, GCC does not use these instructions, since such code will
8159693Selan;;- not run on an '030.  To use these instructions, use the -m68040-only
8259693Selan;;- switch.  By changing TARGET_DEFAULT to include TARGET_68040_ONLY,
8359693Selan;;- you can make these instructions the default.
8459693Selan
8559693Selan;;- These new instructions aren't directly in the md.  They are brought
8659693Selan;;- into play by defining "%$" and "%&" to expand to "s" and "d" rather
8759693Selan;;- than "".
8859693Selan
8959693Selan
9059693Selan;;- 		FPA port explanation:
9159693Selan
9259693Selan;;-		Usage of the Sun FPA and the 68881 together
9359693Selan
9459693Selan;;- The current port of gcc to the sun fpa disallows use of the m68881
9559693Selan;;- instructions completely if code is targeted for the fpa.  This is
9659693Selan;;- for the following reasons:
9759693Selan
9859693Selan;;- 1) Expressing the preference hierarchy (ie. use the fpa if you
9959693Selan;;- can, the 68881 otherwise, and data registers only if you are
10059693Selan;;- forced to it) is a bitch with the current constraint scheme,
10159693Selan;;- especially since it would have to work for any combination of
10259693Selan;;- -mfpa, -m68881.
10359693Selan
10459693Selan;;- 2) There are no instructions to move between the two types of
10559693Selan;;- registers; the stack must be used as an intermediary.
10659693Selan
10759693Selan;;- It could indeed be done; I think the best way would be to have
10859693Selan;;- separate patterns for TARGET_FPA (which implies a 68881),
10959693Selan;;- TARGET_68881, and no floating point co-processor.  Use
11059693Selan;;- define_expands for all of the named instruction patterns, and
11159693Selan;;- include code in the FPA instruction to deal with the 68881 with
11259693Selan;;- preferences specifically set to favor the fpa.  Some of this has
11359693Selan;;- already been done:
11459693Selan;;-
11559693Selan;;- 	1) Separation of most of the patterns out into a TARGET_FPA
11659693Selan;;- case and a TARGET_68881 case (the exceptions are the patterns
11759693Selan;;- which would need one define_expand and three define_insn's under
11859693Selan;;- it (with a lot of duplicate code between them) to replace the
11959693Selan;;- current single define_insn.  These are mov{[ds]f,[ds]i} and the
12059693Selan;;- first two patterns in the md.
12159693Selan;;-
12259693Selan;;- Some would still have to be done:
12359693Selan;;-
12459693Selan;;-	1) Add code to the fpa patterns which correspond to 68881
12559693Selan;;- patterns to deal with the 68881 case (including preferences!).
12659693Selan;;- What you might actually do here is combine the fpa and 68881 code
12759693Selan;;- back together into one pattern for those instructions where it's
12859693Selan;;- absolutely necessary and save yourself some duplicate code.  I'm
12959693Selan;;- not completely sure as to whether you could get away with doing
13059693Selan;;- this only for the mov* insns, or if you'd have to do it for all
13159693Selan;;- named insns.
13259693Selan;;- 	2) Add code to the mov{[ds]f,[ds]i} instructions to handle
13359693Selan;;- moving between fpa regs and 68881 regs.
13459693Selan
13559693Selan;;- Since the fpa is more powerful than the 68881 and also has more
13659693Selan;;- registers, and since I think the resultant md would be medium ugly
13759693Selan;;- (lot's of duplicate code, ugly constraint strings), I elected not
13859693Selan;;- to do this change.
13959693Selan
14059693Selan;;- Another reason why someone *might* want to do the change is to
14159693Selan;;- control which register classes are accessed in a slightly cleaner
14259693Selan;;- way than I have.  See the blurb on CONDITIONAL_REGISTER_USAGE in
14359693Selan;;- the internals manual.
14459693Selan
14559693Selan;;- Yet another reason why someone might want to do this change is to
14659693Selan;;- allow use of some of the 68881 insns which have no equivalent on
14759693Selan;;- the fpa.  The sqrt instruction comes fairly quickly to mind.
14859693Selan
14959693Selan;;- If this is ever done, don't forget to change sun3.h so that
15059693Selan;;- it *will* define __HAVE_68881__ when the FPA is in use.
15159693Selan
15259693Selan;;-		Condition code hack
15359693Selan
15459693Selan;;- When a floating point compare is done in the fpa, the resulting
15559693Selan;;- condition codes are left in the fpastatus register.  The values in
15659693Selan;;- this register must be moved into the 68000 cc register before any
15759693Selan;;- jump is executed.  Once this has been done, regular jump
15859693Selan;;- instructions are fine (ie. floating point jumps are not necessary.
15959693Selan;;- They are only done if the cc is in the 68881).
16059693Selan
16159693Selan;;- The instructions that move the fpastatus register to the 68000
16259693Selan;;- register clobber a data register (the move cannot be done direct).
16359693Selan;;- These instructions might be bundled either with the compare
16459693Selan;;- instruction, or the branch instruction.  If we were using both the
16559693Selan;;- fpa and the 68881 together, we would wish to only mark the
16659693Selan;;- register clobbered if we were doing the compare in the fpa, but I
16759693Selan;;- think that that decision (whether to clobber the register or not)
16859693Selan;;- must be done before register allocation (makes sense) and hence we
16959693Selan;;- can't know if the floating point compare will be done in the fpa
17059693Selan;;- or the fp.  So whenever we are asked for code that uses the fpa,
17159693Selan;;- we will mark a data register as clobbered.  This is reasonable, as
17259693Selan;;- almost all floating point compare operations done with fpa code
17359693Selan;;- enabled will be done in the fpa.  It's even more reasonable since
17459693Selan;;- we decided to make the 68881 and the fpa mutually exclusive.
17559693Selan
17659693Selan;;- We place to code to move the fpastatus register inside of a
17759693Selan;;- define_expand so that we can do it conditionally based on whether
17859693Selan;;- we are targeting an fpa or not.
17959693Selan
18059693Selan;;- This still leaves us with the question of where we wish to put the
18159693Selan;;- code to move the fpastatus reg.  If we put it in the compare
18259693Selan;;- instruction, we can restrict the clobbering of the register to
18359693Selan;;- floating point compares, but we can't take advantage of floating
18459693Selan;;- point subtracts & etc. that alter the fpastatus register.  If we
18559693Selan;;- put it in the branch instruction, all branches compiled with fpa
18659693Selan;;- code enabled will clobber a data register, but we will be able to
18759693Selan;;- take advantage of fpa subtracts.  This balance favors putting the
18859693Selan;;- code in with the compare instruction.
18959693Selan
19059693Selan;;- Note that if some enterprising hacker should decide to switch
19159693Selan;;- this, he'll need to modify the code in NOTICE_UPDATE_CC.
19259693Selan
19359693Selan;;-		Usage of the top 16 fpa registers
19459693Selan
19559693Selan;;- The only locations which we may transfer fpa registers 16-31 from
19659693Selan;;- or to are the fpa registers 0-15.  (68000 registers and memory
19759693Selan;;- locations are impossible).  This causes problems in gcc, which
19859693Selan;;- assumes that mov?? instructions require no additional registers
19959693Selan;;- (see section 11.7) and since floating point moves *must* be
20059693Selan;;- supported into general registers (see section 12.3 under
20159693Selan;;- HARD_REGNO_OK_FOR_MODE_P) from anywhere.
20259693Selan
20359693Selan;;- My solution was to reserve fpa0 for moves into or out of these top
20459693Selan;;- 16 registers and to disparage the choice to reload into or out of
20559693Selan;;- these registers as much as I could.  That alternative is always
20659693Selan;;- last in the list, so it will not be used unless all else fails.  I
20759693Selan;;- will note that according to my current information, sun's compiler
20859693Selan;;- doesn't use these top 16 registers at all.
20959693Selan
21059693Selan;;- There is another possible way to do it.  I *believe* that if you
21159693Selan;;- make absolutely sure that the code will not be executed in the
21259693Selan;;- reload pass, you can support the mov?? names with define_expands
21359693Selan;;- which require new registers.  This may be possible by the
21459693Selan;;- appropriate juggling of constraints.  I may come back to this later.
21559693Selan
21659693Selan;;- 		Usage of constant RAM
21759693Selan
21859693Selan;;- This has been handled correctly (I believe) but the way I've done
21959693Selan;;- it could use a little explanation.  The constant RAM can only be
22059693Selan;;- accessed when the instruction is in "command register" mode.
22159693Selan;;- "command register" mode means that no accessing of memory or the
22259693Selan;;- 68000 registers is being done.  This can be expressed easily in
22359693Selan;;- constraints, so generally the mode of the instruction is
22459693Selan;;- determined by a branch off of which_alternative.  In outputting
22559693Selan;;- instructions, a 'w' means to output an access to the constant ram
22659693Selan;;- (if the arg is CONST_DOUBLE and is one of the available
22759693Selan;;- constants), and 'x' means to output a register pair (if the arg is
22859693Selan;;- a 68000 register) and a 'y' is the combination of the above two
22959693Selan;;- processes.  You use a 'y' in two operand DF instructions where you
23059693Selan;;- *know* the other operand is an fpa register, you use an 'x' in DF
23159693Selan;;- instructions where the arg might be a 68000 register and the
23259693Selan;;- instruction is *not* in "command register" mode, and you use a 'w'
23359693Selan;;- in two situations: 1) The instruction *is* in command register
23459693Selan;;- mode (and hence won't be accessing 68000 registers), or 2) The
23559693Selan;;- instruction is a two operand SF instruction where you know the
23659693Selan;;- other operand is an fpa register.
23759693Selan
23859693Selan;;-		Optimization issues
23959693Selan
24059693Selan;;- I actually think that I've included all of the fpa instructions
24159693Selan;;- that should be included.  Note that if someone is interested in
24259693Selan;;- doing serious floating point work on the sun fpa, I would advise
24359693Selan;;- the use of the "asm" instruction in gcc to allow you to use the
24459693Selan;;- sin, cos, and exponential functions on the fpa board.
24559693Selan
24659693Selan;;- END FPA Explanation Section.
24759693Selan
24859693Selan
24959693Selan;;- Some of these insn's are composites of several m68000 op codes.
25059693Selan;;- The assembler (or final @@??) insures that the appropriate one is
25159693Selan;;- selected.
25259693Selan
25359693Selan(define_insn ""
25459693Selan  [(set (match_operand:DF 0 "push_operand" "=m")
25559693Selan	(match_operand:DF 1 "general_operand" "ro<>fyE"))]
25659693Selan  ""
25759693Selan  "*
25859693Selan{
25959693Selan  if (FP_REG_P (operands[1]))
26059693Selan    return \"fmove%.d %f1,%0\";
26159693Selan  if (FPA_REG_P (operands[1]))
26259693Selan    return \"fpmove%.d %1, %x0\";
26359693Selan  return output_move_double (operands);
26459693Selan}")
26559693Selan
26659693Selan(define_insn ""
26759693Selan  [(set (match_operand:DI 0 "push_operand" "=m")
26859693Selan	(match_operand:DI 1 "general_operand" "ro<>Fy"))]
26959693Selan  ""
27059693Selan  "*
27159693Selan{
27259693Selan  return output_move_double (operands);
27359693Selan}")
27459693Selan
27559693Selan;; We don't want to allow a constant operand for test insns because
27659693Selan;; (set (cc0) (const_int foo)) has no mode information.  Such insns will
27759693Selan;; be folded while optimizing anyway.
27859693Selan(define_insn "tstsi"
27959693Selan  [(set (cc0)
28059693Selan	(match_operand:SI 0 "nonimmediate_operand" "rm"))]
28159693Selan  ""
28259693Selan  "*
28359693Selan{
28459693Selan#ifdef ISI_OV
28559693Selan  /* ISI's assembler fails to handle tstl a0.  */
28659693Selan  if (! ADDRESS_REG_P (operands[0]))
28759693Selan#else
28859693Selan  if (TARGET_68020 || ! ADDRESS_REG_P (operands[0]))
28959693Selan#endif
29059693Selan    return \"tst%.l %0\";
29159693Selan  /* If you think that the 68020 does not support tstl a0,
29259693Selan     reread page B-167 of the 68020 manual more carefully.  */
29359693Selan  /* On an address reg, cmpw may replace cmpl.  */
29459693Selan#ifdef SGS_CMP_ORDER
29559693Selan  return \"cmp%.w %0,%#0\";
29659693Selan#else
29759693Selan  return \"cmp%.w %#0,%0\";
29859693Selan#endif
29959693Selan}")
30059693Selan
30159693Selan;; This can't use an address register, because comparisons
30259693Selan;; with address registers as second operand always test the whole word.
30359693Selan(define_insn "tsthi"
30459693Selan  [(set (cc0)
30559693Selan	(match_operand:HI 0 "nonimmediate_operand" "dm"))]
30659693Selan  ""
30759693Selan  "tst%.w %0")
30859693Selan
30959693Selan(define_insn "tstqi"
31059693Selan  [(set (cc0)
31159693Selan	(match_operand:QI 0 "nonimmediate_operand" "dm"))]
31259693Selan  ""
31359693Selan  "tst%.b %0")
31459693Selan
31559693Selan(define_expand "tstsf"
31659693Selan  [(set (cc0)
31759693Selan	(match_operand:SF 0 "general_operand" ""))]
31859693Selan  "TARGET_68881 || TARGET_FPA"
31959693Selan  "
32059693Selan{
32159693Selan  if (TARGET_FPA)
32259693Selan    {
32359693Selan      emit_insn (gen_tstsf_fpa (operands[0]));
32459693Selan      DONE;
32559693Selan    }
32659693Selan}")
32759693Selan
32859693Selan(define_insn "tstsf_fpa"
32959693Selan  [(set (cc0)
33059693Selan	(match_operand:SF 0 "general_operand" "xmdF"))
33159693Selan   (clobber (match_scratch:SI 1 "=d"))]
33259693Selan  "TARGET_FPA"
33359693Selan  "fptst%.s %x0\;fpmove fpastatus,%1\;movw %1,cc")
33459693Selan
33559693Selan(define_insn ""
33659693Selan  [(set (cc0)
33759693Selan	(match_operand:SF 0 "general_operand" "fdm"))]
33859693Selan  "TARGET_68881"
33959693Selan  "*
34059693Selan{
34159693Selan  cc_status.flags = CC_IN_68881;
34259693Selan  if (FP_REG_P (operands[0]))
34359693Selan    return \"ftst%.x %0\";
34459693Selan  return \"ftst%.s %0\";
34559693Selan}")
34659693Selan
34759693Selan(define_expand "tstdf"
34859693Selan  [(set (cc0)
34959693Selan	(match_operand:DF 0 "general_operand" ""))]
35059693Selan  "TARGET_68881 || TARGET_FPA"
35159693Selan  "
35259693Selan{
35359693Selan  if (TARGET_FPA)
35459693Selan    {
35559693Selan      emit_insn (gen_tstsf_fpa (operands[0]));
35659693Selan      DONE;
35759693Selan    }
35859693Selan}")
35959693Selan
36059693Selan(define_insn "tstdf_fpa"
36159693Selan  [(set (cc0)
36259693Selan	(match_operand:DF 0 "general_operand" "xrmF"))
36359693Selan   (clobber (match_scratch:SI 1 "=d"))]
36459693Selan  "TARGET_FPA"
36559693Selan  "fptst%.d %x0\;fpmove fpastatus,%1\;movw %1,cc")
36659693Selan
36759693Selan(define_insn ""
36859693Selan  [(set (cc0)
36959693Selan	(match_operand:DF 0 "general_operand" "fm"))]
37059693Selan  "TARGET_68881"
37159693Selan  "*
37259693Selan{
37359693Selan  cc_status.flags = CC_IN_68881;
37459693Selan  if (FP_REG_P (operands[0]))
37559693Selan    return \"ftst%.x %0\";
37659693Selan  return \"ftst%.d %0\";
37759693Selan}")
37859693Selan
37959693Selan;; compare instructions.
38059693Selan
38159693Selan;; A composite of the cmp, cmpa, & cmpi m68000 op codes.
38259693Selan(define_insn "cmpsi"
38359693Selan  [(set (cc0)
38459693Selan	(compare (match_operand:SI 0 "nonimmediate_operand" "rKs,mr,>")
38559693Selan		 (match_operand:SI 1 "general_operand" "mr,Ksr,>")))]
38659693Selan  ""
38759693Selan  "*
38859693Selan{
38959693Selan  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
39059693Selan    return \"cmpm%.l %1,%0\";
39159693Selan  if (REG_P (operands[1])
39259693Selan      || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
39359693Selan    { cc_status.flags |= CC_REVERSED;
39459693Selan#ifdef SGS_CMP_ORDER
39559693Selan      return \"cmp%.l %d1,%d0\";
39659693Selan#else
39759693Selan      return \"cmp%.l %d0,%d1\";
39859693Selan#endif
39959693Selan    }
40059693Selan#ifdef SGS_CMP_ORDER
40159693Selan  return \"cmp%.l %d0,%d1\";
40259693Selan#else
40359693Selan  return \"cmp%.l %d1,%d0\";
40459693Selan#endif
40559693Selan}")
40659693Selan
40759693Selan(define_insn "cmphi"
40859693Selan  [(set (cc0)
40959693Selan	(compare (match_operand:HI 0 "nonimmediate_operand" "rnm,d,n,m")
41059693Selan		 (match_operand:HI 1 "general_operand" "d,rnm,m,n")))]
41159693Selan  ""
41259693Selan  "*
41359693Selan{
41459693Selan  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
41559693Selan    return \"cmpm%.w %1,%0\";
41659693Selan  if ((REG_P (operands[1]) && !ADDRESS_REG_P (operands[1]))
41759693Selan      || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
41859693Selan    { cc_status.flags |= CC_REVERSED;
41959693Selan#ifdef SGS_CMP_ORDER
42059693Selan      return \"cmp%.w %d1,%d0\";
42159693Selan#else
42259693Selan      return \"cmp%.w %d0,%d1\";
42359693Selan#endif
42459693Selan    }
42559693Selan#ifdef SGS_CMP_ORDER
42659693Selan  return \"cmp%.w %d0,%d1\";
42759693Selan#else
42859693Selan  return \"cmp%.w %d1,%d0\";
42959693Selan#endif
43059693Selan}")
43159693Selan
43259693Selan(define_insn "cmpqi"
43359693Selan  [(set (cc0)
43459693Selan	(compare (match_operand:QI 0 "nonimmediate_operand" "dn,md,>")
43559693Selan		 (match_operand:QI 1 "general_operand" "dm,nd,>")))]
43659693Selan  ""
43759693Selan  "*
43859693Selan{
43959693Selan  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
44059693Selan    return \"cmpm%.b %1,%0\";
44159693Selan  if (REG_P (operands[1])
44259693Selan      || (!REG_P (operands[0]) && GET_CODE (operands[0]) != MEM))
44359693Selan    { cc_status.flags |= CC_REVERSED;
44459693Selan#ifdef SGS_CMP_ORDER
44559693Selan      return \"cmp%.b %d1,%d0\";
44659693Selan#else
44759693Selan      return \"cmp%.b %d0,%d1\";
44859693Selan#endif
44959693Selan    }
45059693Selan#ifdef SGS_CMP_ORDER
45159693Selan  return \"cmp%.b %d0,%d1\";
45259693Selan#else
45359693Selan  return \"cmp%.b %d1,%d0\";
45459693Selan#endif
45559693Selan}")
45659693Selan
45759693Selan(define_expand "cmpdf"
45859693Selan  [(set (cc0)
45959693Selan	(compare (match_operand:DF 0 "general_operand" "")
46059693Selan		 (match_operand:DF 1 "general_operand" "")))]
46159693Selan  "TARGET_68881 || TARGET_FPA"
46259693Selan  "
46359693Selan{
46459693Selan  if (TARGET_FPA)
46559693Selan    {
46659693Selan      emit_insn (gen_cmpdf_fpa (operands[0], operands[1]));
46759693Selan      DONE;
46859693Selan    }
46959693Selan}")
47059693Selan
47159693Selan(define_insn "cmpdf_fpa"
47259693Selan  [(set (cc0)
47359693Selan	(compare (match_operand:DF 0 "general_operand" "x,y")
47459693Selan		 (match_operand:DF 1 "general_operand" "xH,rmF")))
47559693Selan   (clobber (match_scratch:SI 2 "=d,d"))]
47659693Selan  "TARGET_FPA"
47759693Selan  "fpcmp%.d %y1,%0\;fpmove fpastatus,%2\;movw %2,cc")
47859693Selan
47959693Selan(define_insn ""
48059693Selan  [(set (cc0)
48159693Selan	(compare (match_operand:DF 0 "general_operand" "f,mG")
48259693Selan		 (match_operand:DF 1 "general_operand" "fmG,f")))]
48359693Selan  "TARGET_68881"
48459693Selan  "*
48559693Selan{
48659693Selan  cc_status.flags = CC_IN_68881;
48759693Selan#ifdef SGS_CMP_ORDER
48859693Selan  if (REG_P (operands[0]))
48959693Selan    {
49059693Selan      if (REG_P (operands[1]))
49159693Selan	return \"fcmp%.x %0,%1\";
49259693Selan      else
49359693Selan        return \"fcmp%.d %0,%f1\";
49459693Selan    }
49559693Selan  cc_status.flags |= CC_REVERSED;
49659693Selan  return \"fcmp%.d %1,%f0\";
49759693Selan#else
49859693Selan  if (REG_P (operands[0]))
49959693Selan    {
50059693Selan      if (REG_P (operands[1]))
50159693Selan	return \"fcmp%.x %1,%0\";
50259693Selan      else
50359693Selan        return \"fcmp%.d %f1,%0\";
50459693Selan    }
50559693Selan  cc_status.flags |= CC_REVERSED;
50659693Selan  return \"fcmp%.d %f0,%1\";
50759693Selan#endif
50859693Selan}")
50959693Selan
51059693Selan(define_expand "cmpsf"
51159693Selan [(set (cc0)
51259693Selan       (compare (match_operand:SF 0 "general_operand" "")
51359693Selan		(match_operand:SF 1 "general_operand" "")))]
51459693Selan "TARGET_68881 || TARGET_FPA"
51559693Selan "
51659693Selan{
51759693Selan  if (TARGET_FPA)
51859693Selan    {
51959693Selan      emit_insn (gen_cmpsf_fpa (operands[0], operands[1]));
52059693Selan      DONE;
52159693Selan    }
52259693Selan}")
52359693Selan
52459693Selan(define_insn "cmpsf_fpa"
52559693Selan  [(set (cc0)
52659693Selan	(compare (match_operand:SF 0 "general_operand" "x,y")
52759693Selan		 (match_operand:SF 1 "general_operand" "xH,rmF")))
52859693Selan   (clobber (match_scratch:SI 2 "=d,d"))]
52959693Selan  "TARGET_FPA"
53059693Selan  "fpcmp%.s %w1,%x0\;fpmove fpastatus,%2\;movw %2,cc")
53159693Selan
53259693Selan(define_insn ""
53359693Selan  [(set (cc0)
53459693Selan	(compare (match_operand:SF 0 "general_operand" "f,mdG")
53559693Selan		 (match_operand:SF 1 "general_operand" "fmdG,f")))]
53659693Selan  "TARGET_68881"
53759693Selan  "*
53859693Selan{
53959693Selan  cc_status.flags = CC_IN_68881;
54059693Selan#ifdef SGS_CMP_ORDER
54159693Selan  if (FP_REG_P (operands[0]))
54259693Selan    {
54359693Selan      if (FP_REG_P (operands[1]))
54459693Selan	return \"fcmp%.x %0,%1\";
54559693Selan      else
54659693Selan        return \"fcmp%.s %0,%f1\";
54759693Selan    }
54859693Selan  cc_status.flags |= CC_REVERSED;
54959693Selan  return \"fcmp%.s %1,%f0\";
55059693Selan#else
55159693Selan  if (FP_REG_P (operands[0]))
55259693Selan    {
55359693Selan      if (FP_REG_P (operands[1]))
55459693Selan	return \"fcmp%.x %1,%0\";
55559693Selan      else
55659693Selan        return \"fcmp%.s %f1,%0\";
55759693Selan    }
55859693Selan  cc_status.flags |= CC_REVERSED;
55959693Selan  return \"fcmp%.s %f0,%1\";
56059693Selan#endif
56159693Selan}")
56259693Selan
56359693Selan;; Recognizers for btst instructions.
56459693Selan
56559693Selan(define_insn ""
56659693Selan  [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "do")
56759693Selan			    (const_int 1)
56859693Selan			    (minus:SI (const_int 7)
56959693Selan				      (match_operand:SI 1 "general_operand" "di"))))]
57059693Selan  ""
57159693Selan  "* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
57259693Selan
57359693Selan(define_insn ""
57459693Selan  [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "d")
57559693Selan			    (const_int 1)
57659693Selan			    (minus:SI (const_int 31)
57759693Selan				      (match_operand:SI 1 "general_operand" "di"))))]
57859693Selan  ""
57959693Selan  "* { return output_btst (operands, operands[1], operands[0], insn, 31); }")
58059693Selan
58159693Selan;; The following two patterns are like the previous two
58259693Selan;; except that they use the fact that bit-number operands
58359693Selan;; are automatically masked to 3 or 5 bits.
58459693Selan
58559693Selan(define_insn ""
58659693Selan  [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "do")
58759693Selan			    (const_int 1)
58859693Selan			    (minus:SI (const_int 7)
58959693Selan				      (and:SI
59059693Selan				       (match_operand:SI 1 "general_operand" "d")
59159693Selan				       (const_int 7)))))]
59259693Selan  ""
59359693Selan  "* { return output_btst (operands, operands[1], operands[0], insn, 7); }")
59459693Selan
59559693Selan(define_insn ""
59659693Selan  [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "d")
59759693Selan			    (const_int 1)
59859693Selan			    (minus:SI (const_int 31)
59959693Selan				      (and:SI
60059693Selan				       (match_operand:SI 1 "general_operand" "d")
60159693Selan				       (const_int 31)))))]
60259693Selan  ""
60359693Selan  "* { return output_btst (operands, operands[1], operands[0], insn, 31); }")
60459693Selan
60559693Selan;; Nonoffsettable mem refs are ok in this one pattern
60659693Selan;; since we don't try to adjust them.
60759693Selan(define_insn ""
60859693Selan  [(set (cc0) (zero_extract (match_operand:QI 0 "nonimmediate_operand" "md")
60959693Selan			    (const_int 1)
61059693Selan			    (match_operand:SI 1 "general_operand" "i")))]
61159693Selan  "GET_CODE (operands[1]) == CONST_INT
61259693Selan   && (unsigned) INTVAL (operands[1]) < 8"
61359693Selan  "*
61459693Selan{
61559693Selan  operands[1] = gen_rtx (CONST_INT, VOIDmode, 7 - INTVAL (operands[1]));
61659693Selan  return output_btst (operands, operands[1], operands[0], insn, 7);
61759693Selan}")
61859693Selan
61959693Selan(define_insn ""
62059693Selan  [(set (cc0) (zero_extract (match_operand:SI 0 "nonimmediate_operand" "do")
62159693Selan			    (const_int 1)
62259693Selan			    (match_operand:SI 1 "general_operand" "i")))]
62359693Selan  "GET_CODE (operands[1]) == CONST_INT"
62459693Selan  "*
62559693Selan{
62659693Selan  if (GET_CODE (operands[0]) == MEM)
62759693Selan    {
62859693Selan      operands[0] = adj_offsettable_operand (operands[0],
62959693Selan					     INTVAL (operands[1]) / 8);
63059693Selan      operands[1] = gen_rtx (CONST_INT, VOIDmode,
63159693Selan			     7 - INTVAL (operands[1]) % 8);
63259693Selan      return output_btst (operands, operands[1], operands[0], insn, 7);
63359693Selan    }
63459693Selan  operands[1] = gen_rtx (CONST_INT, VOIDmode,
63559693Selan			 31 - INTVAL (operands[1]));
63659693Selan  return output_btst (operands, operands[1], operands[0], insn, 31);
63759693Selan}")
63859693Selan
63959693Selan
64059693Selan;; move instructions
64159693Selan
64259693Selan;; A special case in which it is not desirable
64359693Selan;; to reload the constant into a data register.
64459693Selan(define_insn ""
64559693Selan  [(set (match_operand:SI 0 "push_operand" "=m")
64659693Selan	(match_operand:SI 1 "general_operand" "J"))]
64759693Selan  "GET_CODE (operands[1]) == CONST_INT
64859693Selan   && INTVAL (operands[1]) >= -0x8000
64959693Selan   && INTVAL (operands[1]) < 0x8000"
65059693Selan  "*
65159693Selan{
65259693Selan  if (operands[1] == const0_rtx)
65359693Selan    return \"clr%.l %0\";
65459693Selan  return \"pea %a1\";
65559693Selan}")
65659693Selan
65759693Selan;This is never used.
65859693Selan;(define_insn "swapsi"
65959693Selan;  [(set (match_operand:SI 0 "general_operand" "+r")
66059693Selan;	(match_operand:SI 1 "general_operand" "+r"))
66159693Selan;   (set (match_dup 1) (match_dup 0))]
66259693Selan;  ""
66359693Selan;  "exg %1,%0")
66459693Selan
66559693Selan;; Special case of fullword move when source is zero.
66659693Selan;; The reason this is special is to avoid loading a zero
66759693Selan;; into a data reg with moveq in order to store it elsewhere.
66859693Selan
66959693Selan(define_insn ""
67059693Selan  [(set (match_operand:SI 0 "general_operand" "=g")
67159693Selan	(const_int 0))]
67259693Selan  ;; clr insns on 68000 read before writing.
67359693Selan  ;; This isn't so on the 68010, but we have no alternative for it.
67459693Selan  "(TARGET_68020
67559693Selan    || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))"
67659693Selan  "*
67759693Selan{
67859693Selan  if (ADDRESS_REG_P (operands[0]))
67959693Selan    return \"sub%.l %0,%0\";
68059693Selan  /* moveq is faster on the 68000.  */
68159693Selan  if (DATA_REG_P (operands[0]) && !TARGET_68020)
68259693Selan#if defined(MOTOROLA) && !defined(CRDS)
68359693Selan    return \"moveq%.l %#0,%0\";
68459693Selan#else
68559693Selan    return \"moveq %#0,%0\";
68659693Selan#endif
68759693Selan  return \"clr%.l %0\";
68859693Selan}")
68959693Selan
69059693Selan;; General case of fullword move.
69159693Selan;;
69259693Selan;; This is the main "hook" for PIC code.  When generating
69359693Selan;; PIC, movsi is responsible for determining when the source address
69459693Selan;; needs PIC relocation and appropriately calling legitimize_pic_address
69559693Selan;; to perform the actual relocation.
69659693Selan;;
69759693Selan;; In both the PIC and non-PIC cases the patterns generated will
69859693Selan;; matched by the next define_insn.
69959693Selan(define_expand "movsi"
70059693Selan  [(set (match_operand:SI 0 "general_operand" "")
70159693Selan	(match_operand:SI 1 "general_operand" ""))]
70259693Selan  ""
70359693Selan  "
70459693Selan{
70559693Selan  if (flag_pic && symbolic_operand (operands[1], SImode))
70659693Selan    {
70759693Selan      /* The source is an address which requires PIC relocation.
70859693Selan         Call legitimize_pic_address with the source, mode, and a relocation
70959693Selan         register (a new pseudo, or the final destination if reload_in_progress
71059693Selan         is set).   Then fall through normally */
71159693Selan      extern rtx legitimize_pic_address();
71259693Selan      rtx temp = reload_in_progress ? operands[0] : gen_reg_rtx (Pmode);
71359693Selan      operands[1] = legitimize_pic_address (operands[1], SImode, temp);
71459693Selan    }
71559693Selan}")
71659693Selan
71759693Selan;; General case of fullword move.  The register constraints
71859693Selan;; force integer constants in range for a moveq to be reloaded
71959693Selan;; if they are headed for memory.
72059693Selan(define_insn ""
72159693Selan  ;; Notes: make sure no alternative allows g vs g.
72259693Selan  ;; We don't allow f-regs since fixed point cannot go in them.
72359693Selan  ;; We do allow y and x regs since fixed point is allowed in them.
72459693Selan  [(set (match_operand:SI 0 "general_operand" "=g,da,y,!*x*r*m")
72559693Selan	(match_operand:SI 1 "general_operand" "daymKs,i,g,*x*r*m"))]
72659693Selan  ""
72759693Selan  "*
72859693Selan{
72959693Selan  if (which_alternative == 3)
73059693Selan    return \"fpmove%.l %x1,fpa0\;fpmove%.l fpa0,%x0\";
73159693Selan  if (FPA_REG_P (operands[1]) || FPA_REG_P (operands[0]))
73259693Selan    return \"fpmove%.l %x1,%x0\";
73359693Selan  if (GET_CODE (operands[1]) == CONST_INT)
73459693Selan    {
73559693Selan      if (operands[1] == const0_rtx
73659693Selan	  && (DATA_REG_P (operands[0])
73759693Selan	      || GET_CODE (operands[0]) == MEM)
73859693Selan	  /* clr insns on 68000 read before writing.
73959693Selan	     This isn't so on the 68010, but we have no alternative for it.  */
74059693Selan	  && (TARGET_68020
74159693Selan	      || !(GET_CODE (operands[0]) == MEM
74259693Selan		   && MEM_VOLATILE_P (operands[0]))))
74359693Selan	return \"clr%.l %0\";
74459693Selan      else if (DATA_REG_P (operands[0])
74559693Selan	       && INTVAL (operands[1]) < 128
74659693Selan	       && INTVAL (operands[1]) >= -128)
74759693Selan        {
74859693Selan#if defined(MOTOROLA) && !defined(CRDS)
74959693Selan          return \"moveq%.l %1,%0\";
75059693Selan#else
75159693Selan	  return \"moveq %1,%0\";
75259693Selan#endif
75359693Selan	}
75459693Selan#ifndef NO_ADDSUB_Q
75559693Selan      else if (DATA_REG_P (operands[0])
75659693Selan	       /* Do this with a moveq #N-8, dreg; addq #8,dreg */
75759693Selan	       && INTVAL (operands[1]) < 136
75859693Selan	       && INTVAL (operands[1]) >= 128)
75959693Selan        {
76059693Selan	  operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) - 8);
76159693Selan#if defined(MOTOROLA) && !defined(CRDS)
76259693Selan          return \"moveq%.l %1,%0\;addq%.w %#8,%0\";
76359693Selan#else
76459693Selan	  return \"moveq %1,%0\;addq%.w %#8,%0\";
76559693Selan#endif
76659693Selan	}
76759693Selan      else if (DATA_REG_P (operands[0])
76859693Selan	       /* Do this with a moveq #N+8, dreg; subq #8,dreg */
76959693Selan	       && INTVAL (operands[1]) < -128
77059693Selan	       && INTVAL (operands[1]) >= -136)
77159693Selan        {
77259693Selan	  operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) + 8);
77359693Selan#if defined(MOTOROLA) && !defined(CRDS)
77459693Selan          return \"moveq%.l %1,%0;subq%.w %#8,%0\";
77559693Selan#else
77659693Selan	  return \"moveq %1,%0;subq%.w %#8,%0\";
77759693Selan#endif
77859693Selan	}
77959693Selan#endif
78059693Selan      else if (DATA_REG_P (operands[0])
78159693Selan	       /* If N is in the right range and is even, then use
78259693Selan	          moveq #N/2, dreg; addl dreg,dreg */
78359693Selan	       && INTVAL (operands[1]) > 127
78459693Selan	       && INTVAL (operands[1]) <= 254
78559693Selan	       && INTVAL (operands[1]) % 2 == 0)
78659693Selan        {
78759693Selan	  operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) / 2);
78859693Selan#if defined(MOTOROLA) && !defined(CRDS)
78959693Selan          return \"moveq%.l %1,%0\;add%.w %0,%0\";
79059693Selan#else
79159693Selan	  return \"moveq %1,%0\;add%.w %0,%0\";
79259693Selan#endif
79359693Selan	}
79459693Selan      else if (ADDRESS_REG_P (operands[0])
79559693Selan	       && INTVAL (operands[1]) < 0x8000
79659693Selan	       && INTVAL (operands[1]) >= -0x8000)
79759693Selan	return \"move%.w %1,%0\";
79859693Selan      else if (push_operand (operands[0], SImode)
79959693Selan	       && INTVAL (operands[1]) < 0x8000
80059693Selan	       && INTVAL (operands[1]) >= -0x8000)
80159693Selan        return \"pea %a1\";
80259693Selan    }
80359693Selan  else if ((GET_CODE (operands[1]) == SYMBOL_REF
80459693Selan	    || GET_CODE (operands[1]) == CONST)
80559693Selan	   && push_operand (operands[0], SImode))
80659693Selan    return \"pea %a1\";
80759693Selan  else if ((GET_CODE (operands[1]) == SYMBOL_REF
80859693Selan	    || GET_CODE (operands[1]) == CONST)
80959693Selan	   && ADDRESS_REG_P (operands[0]))
81059693Selan    return \"lea %a1,%0\";
81159693Selan  return \"move%.l %1,%0\";
81259693Selan}")
81359693Selan
81459693Selan(define_insn "movhi"
81559693Selan  [(set (match_operand:HI 0 "general_operand" "=g")
81659693Selan	(match_operand:HI 1 "general_operand" "g"))]
81759693Selan  ""
81859693Selan  "*
81959693Selan{
82059693Selan  if (GET_CODE (operands[1]) == CONST_INT)
82159693Selan    {
82259693Selan      if (operands[1] == const0_rtx
82359693Selan	  && (DATA_REG_P (operands[0])
82459693Selan	      || GET_CODE (operands[0]) == MEM)
82559693Selan	  /* clr insns on 68000 read before writing.
82659693Selan	     This isn't so on the 68010, but we have no alternative for it.  */
82759693Selan	  && (TARGET_68020
82859693Selan	      || !(GET_CODE (operands[0]) == MEM
82959693Selan		   && MEM_VOLATILE_P (operands[0]))))
83059693Selan	return \"clr%.w %0\";
83159693Selan      else if (DATA_REG_P (operands[0])
83259693Selan	       && INTVAL (operands[1]) < 128
83359693Selan	       && INTVAL (operands[1]) >= -128)
83459693Selan        {
83559693Selan#if defined(MOTOROLA) && !defined(CRDS)
83659693Selan          return \"moveq%.l %1,%0\";
83759693Selan#else
83859693Selan	  return \"moveq %1,%0\";
83959693Selan#endif
84059693Selan	}
84159693Selan      else if (INTVAL (operands[1]) < 0x8000
84259693Selan	       && INTVAL (operands[1]) >= -0x8000)
84359693Selan	return \"move%.w %1,%0\";
84459693Selan    }
84559693Selan  else if (CONSTANT_P (operands[1]))
84659693Selan    return \"move%.l %1,%0\";
84759693Selan#ifndef SGS_NO_LI
84859693Selan  /* Recognize the insn before a tablejump, one that refers
84959693Selan     to a table of offsets.  Such an insn will need to refer
85059693Selan     to a label on the insn.  So output one.  Use the label-number
85159693Selan     of the table of offsets to generate this label.  */
85259693Selan  if (GET_CODE (operands[1]) == MEM
85359693Selan      && GET_CODE (XEXP (operands[1], 0)) == PLUS
85459693Selan      && (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF
85559693Selan	  || GET_CODE (XEXP (XEXP (operands[1], 0), 1)) == LABEL_REF)
85659693Selan      && GET_CODE (XEXP (XEXP (operands[1], 0), 0)) != PLUS
85759693Selan      && GET_CODE (XEXP (XEXP (operands[1], 0), 1)) != PLUS)
85859693Selan    {
85959693Selan      rtx labelref;
86059693Selan      if (GET_CODE (XEXP (XEXP (operands[1], 0), 0)) == LABEL_REF)
86159693Selan	labelref = XEXP (XEXP (operands[1], 0), 0);
86259693Selan      else
86359693Selan	labelref = XEXP (XEXP (operands[1], 0), 1);
86459693Selan#if defined (MOTOROLA) && !defined (SGS_SWITCH_TABLES)
86559693Selan#ifdef SGS
86659693Selan      asm_fprintf (asm_out_file, \"\\tset %LLI%d,.+2\\n\",
86759693Selan		   CODE_LABEL_NUMBER (XEXP (labelref, 0)));
86859693Selan#else /* not SGS */
86959693Selan      asm_fprintf (asm_out_file, \"\\t.set %LLI%d,.+2\\n\",
87059693Selan	           CODE_LABEL_NUMBER (XEXP (labelref, 0)));
87159693Selan#endif /* not SGS */
87259693Selan#else /* SGS_SWITCH_TABLES or not MOTOROLA */
87359693Selan      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"LI\",
87459693Selan				 CODE_LABEL_NUMBER (XEXP (labelref, 0)));
87559693Selan#ifdef SGS_SWITCH_TABLES
87659693Selan      /* Set flag saying we need to define the symbol
87759693Selan	 LD%n (with value L%n-LI%n) at the end of the switch table.  */
87859693Selan      switch_table_difference_label_flag = 1;
87959693Selan#endif /* SGS_SWITCH_TABLES */
88059693Selan#endif /* SGS_SWITCH_TABLES or not MOTOROLA */
88159693Selan    }
88259693Selan#endif /* SGS_NO_LI */
88359693Selan  return \"move%.w %1,%0\";
88459693Selan}")
88559693Selan
88659693Selan(define_insn "movstricthi"
88759693Selan  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
88859693Selan	(match_operand:HI 1 "general_operand" "rmn"))]
88959693Selan  ""
89059693Selan  "*
89159693Selan{
89259693Selan  if (GET_CODE (operands[1]) == CONST_INT)
89359693Selan    {
89459693Selan      if (operands[1] == const0_rtx
89559693Selan	  && (DATA_REG_P (operands[0])
89659693Selan	      || GET_CODE (operands[0]) == MEM)
89759693Selan	  /* clr insns on 68000 read before writing.
89859693Selan	     This isn't so on the 68010, but we have no alternative for it.  */
89959693Selan	  && (TARGET_68020
90059693Selan	      || !(GET_CODE (operands[0]) == MEM
90159693Selan		   && MEM_VOLATILE_P (operands[0]))))
90259693Selan	return \"clr%.w %0\";
90359693Selan    }
90459693Selan  return \"move%.w %1,%0\";
90559693Selan}")
90659693Selan
90759693Selan(define_insn "movqi"
90859693Selan  [(set (match_operand:QI 0 "general_operand" "=d,*a,m,m,?*a")
90959693Selan	(match_operand:QI 1 "general_operand" "dmi*a,d*a,dmi,?*a,m"))]
91059693Selan  ""
91159693Selan  "*
91259693Selan{
91359693Selan  rtx xoperands[4];
91459693Selan
91559693Selan  /* This is probably useless, since it loses for pushing a struct
91659693Selan     of several bytes a byte at a time.  */
91759693Selan  if (GET_CODE (operands[0]) == MEM
91859693Selan      && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC
91959693Selan      && XEXP (XEXP (operands[0], 0), 0) == stack_pointer_rtx)
92059693Selan    {
92159693Selan      xoperands[1] = operands[1];
92259693Selan      xoperands[2]
92359693Selan        = gen_rtx (MEM, QImode,
92459693Selan		   gen_rtx (PLUS, VOIDmode, stack_pointer_rtx, const1_rtx));
92559693Selan      /* Just pushing a byte puts it in the high byte of the halfword.  */
92659693Selan      /* We must put it in the low-order, high-numbered byte.  */
927*60382Selan      output_asm_insn (\"move%.b %1,%-\;move%.b %@,%2\", xoperands);
92859693Selan      return \"\";
92959693Selan    }
93059693Selan
931*60382Selan  /* HACK Alert.  This is a quick fix while RMS makes up his
932*60382Selan     mind about what he wants to do about this case.  */
933*60382Selan
934*60382Selan  /* if d0 is used in the address calculation, use d1 */
935*60382Selan  if (refers_to_regno_p (0, 1, PATTERN (insn), NULL_PTR))
93659693Selan    {
937*60382Selan      /* Moving a byte into an address register is not possible.  */
938*60382Selan      /* Use d1 as an intermediate, but don't clobber its contents.  */
939*60382Selan      if (ADDRESS_REG_P (operands[0]) && GET_CODE (operands[1]) == MEM)
940*60382Selan	return \"exg %/d1,%0\;move%.b %1,%/d1\;exg %/d1,%0\";
941*60382Selan      /* Likewise for moving from an address reg.  */
942*60382Selan      if (ADDRESS_REG_P (operands[1]) && GET_CODE (operands[0]) == MEM)
943*60382Selan	return \"exg %/d1,%1\;move%.b %/d1,%0\;exg %/d1,%1\";
94459693Selan    }
945*60382Selan  else
94659693Selan    {
947*60382Selan      /* Moving a byte into an address register is not possible.  */
948*60382Selan      /* Use d0 as an intermediate, but don't clobber its contents.  */
949*60382Selan      if (ADDRESS_REG_P (operands[0]) && GET_CODE (operands[1]) == MEM)
950*60382Selan	return \"exg %/d0,%0\;move%.b %1,%/d0\;exg %/d0,%0\";
951*60382Selan      /* Likewise for moving from an address reg.  */
952*60382Selan      if (ADDRESS_REG_P (operands[1]) && GET_CODE (operands[0]) == MEM)
953*60382Selan	return \"exg %/d0,%1\;move%.b %/d0,%0\;exg %/d0,%1\";
95459693Selan    }
955*60382Selan
95659693Selan  /* clr and st insns on 68000 read before writing.
95759693Selan     This isn't so on the 68010, but we have no alternative for it.  */
95859693Selan  if (TARGET_68020
95959693Selan      || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
96059693Selan    {
96159693Selan      if (operands[1] == const0_rtx)
96259693Selan	return \"clr%.b %0\";
96359693Selan      if (GET_CODE (operands[1]) == CONST_INT
96459693Selan	  && INTVAL (operands[1]) == -1)
96559693Selan	{
96659693Selan	  CC_STATUS_INIT;
96759693Selan	  return \"st %0\";
96859693Selan	}
96959693Selan    }
97059693Selan  if (GET_CODE (operands[1]) != CONST_INT && CONSTANT_P (operands[1]))
97159693Selan    return \"move%.l %1,%0\";
97259693Selan  if (ADDRESS_REG_P (operands[0]) || ADDRESS_REG_P (operands[1]))
97359693Selan    return \"move%.w %1,%0\";
97459693Selan  return \"move%.b %1,%0\";
97559693Selan}")
97659693Selan
97759693Selan(define_insn "movstrictqi"
97859693Selan  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
97959693Selan	(match_operand:QI 1 "general_operand" "dmn"))]
98059693Selan  ""
98159693Selan  "*
98259693Selan{
98359693Selan  if (operands[1] == const0_rtx
98459693Selan      /* clr insns on 68000 read before writing.
98559693Selan         This isn't so on the 68010, but we have no alternative for it.  */
98659693Selan      && (TARGET_68020
98759693Selan          || !(GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))))
98859693Selan    return \"clr%.b %0\";
98959693Selan  return \"move%.b %1,%0\";
99059693Selan}")
99159693Selan
99259693Selan(define_insn "movsf"
99359693Selan  [(set (match_operand:SF 0 "general_operand" "=rmf,x,y,rm,!x,!rm")
99459693Selan	(match_operand:SF 1 "general_operand" "rmfF,xH,rmF,y,rm,x"))]
99559693Selan;  [(set (match_operand:SF 0 "general_operand" "=rmf")
99659693Selan;	(match_operand:SF 1 "general_operand" "rmfF"))]
99759693Selan  ""
99859693Selan  "*
99959693Selan{
100059693Selan  if (which_alternative >= 4)
100159693Selan    return \"fpmove%.s %1,fpa0\;fpmove%.s fpa0,%0\";
100259693Selan  if (FPA_REG_P (operands[0]))
100359693Selan    {
100459693Selan      if (FPA_REG_P (operands[1]))
100559693Selan	return \"fpmove%.s %x1,%x0\";
100659693Selan      else if (GET_CODE (operands[1]) == CONST_DOUBLE)
100759693Selan	return output_move_const_single (operands);
100859693Selan      else if (FP_REG_P (operands[1]))
100959693Selan        return \"fmove%.s %1,sp@-\;fpmove%.d sp@+, %0\";
101059693Selan      return \"fpmove%.s %x1,%x0\";
101159693Selan    }
101259693Selan  if (FPA_REG_P (operands[1]))
101359693Selan    {
101459693Selan      if (FP_REG_P (operands[0]))
101559693Selan	return \"fpmove%.s %x1,sp@-\;fmove%.s sp@+,%0\";
101659693Selan      else
101759693Selan	return \"fpmove%.s %x1,%x0\";
101859693Selan    }
101959693Selan  if (FP_REG_P (operands[0]))
102059693Selan    {
102159693Selan      if (FP_REG_P (operands[1]))
102259693Selan	return \"f%$move%.x %1,%0\";
102359693Selan      else if (ADDRESS_REG_P (operands[1]))
102459693Selan	return \"move%.l %1,%-\;f%$move%.s %+,%0\";
102559693Selan      else if (GET_CODE (operands[1]) == CONST_DOUBLE)
102659693Selan	return output_move_const_single (operands);
102759693Selan      return \"f%$move%.s %f1,%0\";
102859693Selan    }
102959693Selan  if (FP_REG_P (operands[1]))
103059693Selan    {
103159693Selan      if (ADDRESS_REG_P (operands[0]))
103259693Selan	return \"fmove%.s %1,%-\;move%.l %+,%0\";
103359693Selan      return \"fmove%.s %f1,%0\";
103459693Selan    }
103559693Selan  return \"move%.l %1,%0\";
103659693Selan}")
103759693Selan
103859693Selan(define_insn "movdf"
103959693Selan  [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>,y,rm,x,!x,!rm")
104059693Selan	(match_operand:DF 1 "general_operand" "rf,m,rofE<>,rmE,y,xH,rm,x"))]
104159693Selan;  [(set (match_operand:DF 0 "general_operand" "=rm,&rf,&rof<>")
104259693Selan;	(match_operand:DF 1 "general_operand" "rf,m,rofF<>"))]
104359693Selan  ""
104459693Selan  "*
104559693Selan{
104659693Selan  if (which_alternative == 6)
104759693Selan    return \"fpmove%.d %x1,fpa0\;fpmove%.d fpa0,%x0\";
104859693Selan  if (FPA_REG_P (operands[0]))
104959693Selan    {
105059693Selan      if (GET_CODE (operands[1]) == CONST_DOUBLE)
105159693Selan	return output_move_const_double (operands);
105259693Selan      if (FP_REG_P (operands[1]))
105359693Selan        return \"fmove%.d %1,sp@-\;fpmove%.d sp@+,%x0\";
105459693Selan      return \"fpmove%.d %x1,%x0\";
105559693Selan    }
105659693Selan  else if (FPA_REG_P (operands[1]))
105759693Selan    {
105859693Selan      if (FP_REG_P(operands[0]))
105959693Selan        return \"fpmove%.d %x1,sp@-\;fmoved sp@+,%0\";
106059693Selan      else
106159693Selan        return \"fpmove%.d %x1,%x0\";
106259693Selan    }
106359693Selan  if (FP_REG_P (operands[0]))
106459693Selan    {
106559693Selan      if (FP_REG_P (operands[1]))
106659693Selan	return \"f%&move%.x %1,%0\";
106759693Selan      if (REG_P (operands[1]))
106859693Selan	{
106959693Selan	  rtx xoperands[2];
107059693Selan	  xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
107159693Selan	  output_asm_insn (\"move%.l %1,%-\", xoperands);
107259693Selan	  output_asm_insn (\"move%.l %1,%-\", operands);
107359693Selan	  return \"f%&move%.d %+,%0\";
107459693Selan	}
107559693Selan      if (GET_CODE (operands[1]) == CONST_DOUBLE)
107659693Selan	return output_move_const_double (operands);
107759693Selan      return \"f%&move%.d %f1,%0\";
107859693Selan    }
107959693Selan  else if (FP_REG_P (operands[1]))
108059693Selan    {
108159693Selan      if (REG_P (operands[0]))
108259693Selan	{
108359693Selan	  output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands);
108459693Selan	  operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
108559693Selan	  return \"move%.l %+,%0\";
108659693Selan	}
108759693Selan      else
108859693Selan        return \"fmove%.d %f1,%0\";
108959693Selan    }
109059693Selan  return output_move_double (operands);
109159693Selan}
109259693Selan")
109359693Selan
109459693Selan;; movdi can apply to fp regs in some cases
109559693Selan(define_insn "movdi"
109659693Selan  ;; Let's see if it really still needs to handle fp regs, and, if so, why.
109759693Selan  [(set (match_operand:DI 0 "general_operand" "=rm,&r,&ro<>,y,rm,!*x,!rm")
109859693Selan	(match_operand:DI 1 "general_operand" "rF,m,roi<>F,rmiF,y,rmF,*x"))]
109959693Selan;  [(set (match_operand:DI 0 "general_operand" "=rm,&r,&ro<>,!&rm,!&f,y,rm,x,!x,!rm")
110059693Selan;	(match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfmF,rmi,y,rm,x"))]
110159693Selan;  [(set (match_operand:DI 0 "general_operand" "=rm,&rf,&ro<>,!&rm,!&f")
110259693Selan;	(match_operand:DI 1 "general_operand" "r,m,roi<>,fF,rfF"))]
110359693Selan  ""
110459693Selan  "*
110559693Selan{
110659693Selan  if (which_alternative == 8)
110759693Selan    return \"fpmove%.d %x1,fpa0\;fpmove%.d fpa0,%x0\";
110859693Selan  if (FPA_REG_P (operands[0]) || FPA_REG_P (operands[1]))
110959693Selan    return \"fpmove%.d %x1,%x0\";
111059693Selan  if (FP_REG_P (operands[0]))
111159693Selan    {
111259693Selan      if (FP_REG_P (operands[1]))
111359693Selan	return \"fmove%.x %1,%0\";
111459693Selan      if (REG_P (operands[1]))
111559693Selan	{
111659693Selan	  rtx xoperands[2];
111759693Selan	  xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
111859693Selan	  output_asm_insn (\"move%.l %1,%-\", xoperands);
111959693Selan	  output_asm_insn (\"move%.l %1,%-\", operands);
112059693Selan	  return \"fmove%.d %+,%0\";
112159693Selan	}
112259693Selan      if (GET_CODE (operands[1]) == CONST_DOUBLE)
112359693Selan	return output_move_const_double (operands);
112459693Selan      return \"fmove%.d %f1,%0\";
112559693Selan    }
112659693Selan  else if (FP_REG_P (operands[1]))
112759693Selan    {
112859693Selan      if (REG_P (operands[0]))
112959693Selan	{
113059693Selan	  output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands);
113159693Selan	  operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
113259693Selan	  return \"move%.l %+,%0\";
113359693Selan	}
113459693Selan      else
113559693Selan        return \"fmove%.d %f1,%0\";
113659693Selan    }
113759693Selan  return output_move_double (operands);
113859693Selan}
113959693Selan")
114059693Selan
114159693Selan;; Thus goes after the move instructions
114259693Selan;; because the move instructions are better (require no spilling)
114359693Selan;; when they can apply.  It goes before the add/sub insns
114459693Selan;; so we will prefer it to them.
114559693Selan
114659693Selan(define_insn "pushasi"
114759693Selan  [(set (match_operand:SI 0 "push_operand" "=m")
114859693Selan	(match_operand:SI 1 "address_operand" "p"))]
114959693Selan  ""
115059693Selan  "pea %a1")
115159693Selan
115259693Selan;; truncation instructions
115359693Selan(define_insn "truncsiqi2"
115459693Selan  [(set (match_operand:QI 0 "general_operand" "=dm,d")
115559693Selan	(truncate:QI
115659693Selan	 (match_operand:SI 1 "general_operand" "doJ,i")))]
115759693Selan  ""
115859693Selan  "*
115959693Selan{
116059693Selan  if (GET_CODE (operands[0]) == REG)
116159693Selan    {
116259693Selan      /* Must clear condition codes, since the move.l bases them on
116359693Selan	 the entire 32 bits, not just the desired 8 bits.  */
116459693Selan      CC_STATUS_INIT;
116559693Selan      return \"move%.l %1,%0\";
116659693Selan    }
116759693Selan  if (GET_CODE (operands[1]) == MEM)
116859693Selan    operands[1] = adj_offsettable_operand (operands[1], 3);
116959693Selan  return \"move%.b %1,%0\";
117059693Selan}")
117159693Selan
117259693Selan(define_insn "trunchiqi2"
117359693Selan  [(set (match_operand:QI 0 "general_operand" "=dm,d")
117459693Selan	(truncate:QI
117559693Selan	 (match_operand:HI 1 "general_operand" "doJ,i")))]
117659693Selan  ""
117759693Selan  "*
117859693Selan{
117959693Selan  if (GET_CODE (operands[0]) == REG
118059693Selan      && (GET_CODE (operands[1]) == MEM
118159693Selan	  || GET_CODE (operands[1]) == CONST_INT))
118259693Selan    {
118359693Selan      /* Must clear condition codes, since the move.w bases them on
118459693Selan	 the entire 16 bits, not just the desired 8 bits.  */
118559693Selan      CC_STATUS_INIT;
118659693Selan      return \"move%.w %1,%0\";
118759693Selan    }
118859693Selan  if (GET_CODE (operands[0]) == REG)
118959693Selan    {
119059693Selan      /* Must clear condition codes, since the move.l bases them on
119159693Selan	 the entire 32 bits, not just the desired 8 bits.  */
119259693Selan      CC_STATUS_INIT;
119359693Selan      return \"move%.l %1,%0\";
119459693Selan    }
119559693Selan  if (GET_CODE (operands[1]) == MEM)
119659693Selan    operands[1] = adj_offsettable_operand (operands[1], 1);
119759693Selan  return \"move%.b %1,%0\";
119859693Selan}")
119959693Selan
120059693Selan(define_insn "truncsihi2"
120159693Selan  [(set (match_operand:HI 0 "general_operand" "=dm,d")
120259693Selan	(truncate:HI
120359693Selan	 (match_operand:SI 1 "general_operand" "roJ,i")))]
120459693Selan  ""
120559693Selan  "*
120659693Selan{
120759693Selan  if (GET_CODE (operands[0]) == REG)
120859693Selan    {
120959693Selan      /* Must clear condition codes, since the move.l bases them on
121059693Selan	 the entire 32 bits, not just the desired 8 bits.  */
121159693Selan      CC_STATUS_INIT;
121259693Selan      return \"move%.l %1,%0\";
121359693Selan    }
121459693Selan  if (GET_CODE (operands[1]) == MEM)
121559693Selan    operands[1] = adj_offsettable_operand (operands[1], 2);
121659693Selan  return \"move%.w %1,%0\";
121759693Selan}")
121859693Selan
121959693Selan;; zero extension instructions
122059693Selan
122159693Selan(define_expand "zero_extendhisi2"
122259693Selan  [(set (match_operand:SI 0 "register_operand" "")
122359693Selan	(const_int 0))
122459693Selan   (set (strict_low_part (match_dup 2))
122559693Selan	(match_operand:HI 1 "general_operand" ""))]
122659693Selan  ""
122759693Selan  "
122859693Selan{
122959693Selan  operands[1] = make_safe_from (operands[1], operands[0]);
123059693Selan  if (GET_CODE (operands[0]) == SUBREG)
123159693Selan    operands[2] = gen_rtx (SUBREG, HImode, SUBREG_REG (operands[0]),
123259693Selan			   SUBREG_WORD (operands[0]));
123359693Selan  else
123459693Selan    operands[2] = gen_rtx (SUBREG, HImode, operands[0], 0);
123559693Selan}")
123659693Selan
123759693Selan(define_expand "zero_extendqihi2"
123859693Selan  [(set (match_operand:HI 0 "register_operand" "")
123959693Selan	(const_int 0))
124059693Selan   (set (strict_low_part (match_dup 2))
124159693Selan	(match_operand:QI 1 "general_operand" ""))]
124259693Selan  ""
124359693Selan  "
124459693Selan{
124559693Selan  operands[1] = make_safe_from (operands[1], operands[0]);
124659693Selan  if (GET_CODE (operands[0]) == SUBREG)
124759693Selan    operands[2] = gen_rtx (SUBREG, QImode, SUBREG_REG (operands[0]),
124859693Selan			   SUBREG_WORD (operands[0]));
124959693Selan  else
125059693Selan    operands[2] = gen_rtx (SUBREG, QImode, operands[0], 0);
125159693Selan}")
125259693Selan
125359693Selan(define_expand "zero_extendqisi2"
125459693Selan  [(set (match_operand:SI 0 "register_operand" "")
125559693Selan	(const_int 0))
125659693Selan   (set (strict_low_part (match_dup 2))
125759693Selan	(match_operand:QI 1 "general_operand" ""))]
125859693Selan  ""
125959693Selan  "
126059693Selan{
126159693Selan  operands[1] = make_safe_from (operands[1], operands[0]);
126259693Selan  if (GET_CODE (operands[0]) == SUBREG)
126359693Selan    operands[2] = gen_rtx (SUBREG, QImode, SUBREG_REG (operands[0]),
126459693Selan			   SUBREG_WORD (operands[0]));
126559693Selan  else
126659693Selan    operands[2] = gen_rtx (SUBREG, QImode, operands[0], 0);
126759693Selan}")
126859693Selan
126959693Selan;; Patterns to recognize zero-extend insns produced by the combiner.
127059693Selan;; We don't allow both operands in memory, because of aliasing problems.
127159693Selan;; Explicitly disallow two memory operands via the condition since reloading
127259693Selan;; of this case will result in worse code than the uncombined patterns.
127359693Selan
127459693Selan(define_insn ""
127559693Selan  [(set (match_operand:SI 0 "general_operand" "=do<>,d<")
127659693Selan	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "r,m")))]
127759693Selan  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
127859693Selan  "*
127959693Selan{
128059693Selan  if (DATA_REG_P (operands[0]))
128159693Selan    {
128259693Selan      if (GET_CODE (operands[1]) == REG
128359693Selan	  && REGNO (operands[0]) == REGNO (operands[1]))
128459693Selan	return \"and%.l %#0xFFFF,%0\";
128559693Selan      if (reg_mentioned_p (operands[0], operands[1]))
128659693Selan        return \"move%.w %1,%0\;and%.l %#0xFFFF,%0\";
128759693Selan      return \"clr%.l %0\;move%.w %1,%0\";
128859693Selan    }
128959693Selan  else if (GET_CODE (operands[0]) == MEM
129059693Selan	   && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
129159693Selan    return \"move%.w %1,%0\;clr%.w %0\";
129259693Selan  else if (GET_CODE (operands[0]) == MEM
129359693Selan	   && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
129459693Selan    return \"clr%.w %0\;move%.w %1,%0\";
129559693Selan  else
129659693Selan    {
129759693Selan      output_asm_insn (\"clr%.w %0\", operands);
129859693Selan      operands[0] = adj_offsettable_operand (operands[0], 2);
129959693Selan      return \"move%.w %1,%0\";
130059693Selan    }
130159693Selan}")
130259693Selan
130359693Selan(define_insn ""
130459693Selan  [(set (match_operand:HI 0 "general_operand" "=do<>,d")
130559693Selan	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
130659693Selan  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
130759693Selan  "*
130859693Selan{
130959693Selan  if (DATA_REG_P (operands[0]))
131059693Selan    {
131159693Selan      if (GET_CODE (operands[1]) == REG
131259693Selan	  && REGNO (operands[0]) == REGNO (operands[1]))
131359693Selan	return \"and%.w %#0xFF,%0\";
131459693Selan      if (reg_mentioned_p (operands[0], operands[1]))
131559693Selan        return \"move%.b %1,%0\;and%.w %#0xFF,%0\";
131659693Selan      return \"clr%.w %0\;move%.b %1,%0\";
131759693Selan    }
131859693Selan  else if (GET_CODE (operands[0]) == MEM
131959693Selan	   && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
132059693Selan    {
132159693Selan      if (REGNO (XEXP (XEXP (operands[0], 0), 0))
132259693Selan	  == STACK_POINTER_REGNUM)
132359693Selan	{
132459693Selan	  output_asm_insn (\"clr%.w %-\", operands);
132559693Selan	  operands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
132659693Selan				 plus_constant (stack_pointer_rtx, 1));
132759693Selan	  return \"move%.b %1,%0\";
132859693Selan	}
132959693Selan      else
133059693Selan	return \"move%.b %1,%0\;clr%.b %0\";
133159693Selan    }
133259693Selan  else if (GET_CODE (operands[0]) == MEM
133359693Selan	   && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
133459693Selan    return \"clr%.b %0\;move%.b %1,%0\";
133559693Selan  else
133659693Selan    {
133759693Selan      output_asm_insn (\"clr%.b %0\", operands);
133859693Selan      operands[0] = adj_offsettable_operand (operands[0], 1);
133959693Selan      return \"move%.b %1,%0\";
134059693Selan    }
134159693Selan}")
134259693Selan
134359693Selan(define_insn ""
134459693Selan  [(set (match_operand:SI 0 "general_operand" "=do<>,d")
134559693Selan	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "d,m")))]
134659693Selan  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
134759693Selan  "*
134859693Selan{
134959693Selan  if (DATA_REG_P (operands[0]))
135059693Selan    {
135159693Selan      if (GET_CODE (operands[1]) == REG
135259693Selan	  && REGNO (operands[0]) == REGNO (operands[1]))
135359693Selan	return \"and%.l %#0xFF,%0\";
135459693Selan      if (reg_mentioned_p (operands[0], operands[1]))
135559693Selan        return \"move%.b %1,%0\;and%.l %#0xFF,%0\";
135659693Selan      return \"clr%.l %0\;move%.b %1,%0\";
135759693Selan    }
135859693Selan  else if (GET_CODE (operands[0]) == MEM
135959693Selan	   && GET_CODE (XEXP (operands[0], 0)) == PRE_DEC)
136059693Selan    {
136159693Selan      operands[0] = XEXP (XEXP (operands[0], 0), 0);
136259693Selan#ifdef MOTOROLA
136359693Selan#ifdef SGS
136459693Selan      return \"clr%.l -(%0)\;move%.b %1,3(%0)\";
136559693Selan#else
136659693Selan      return \"clr%.l -(%0)\;move%.b %1,(3,%0)\";
136759693Selan#endif
136859693Selan#else
136959693Selan      return \"clrl %0@-\;moveb %1,%0@(3)\";
137059693Selan#endif
137159693Selan    }
137259693Selan  else if (GET_CODE (operands[0]) == MEM
137359693Selan	   && GET_CODE (XEXP (operands[0], 0)) == POST_INC)
137459693Selan    {
137559693Selan      operands[0] = XEXP (XEXP (operands[0], 0), 0);
137659693Selan#ifdef MOTOROLA
137759693Selan#ifdef SGS
137859693Selan      return \"clr%.l (%0)+\;move%.b %1,-1(%0)\";
137959693Selan#else
138059693Selan      return \"clr%.l (%0)+\;move%.b %1,(-1,%0)\";
138159693Selan#endif
138259693Selan#else
138359693Selan      return \"clrl %0@+\;moveb %1,%0@(-1)\";
138459693Selan#endif
138559693Selan    }
138659693Selan  else
138759693Selan    {
138859693Selan      output_asm_insn (\"clr%.l %0\", operands);
138959693Selan      operands[0] = adj_offsettable_operand (operands[0], 3);
139059693Selan      return \"move%.b %1,%0\";
139159693Selan    }
139259693Selan}")
139359693Selan
139459693Selan;; sign extension instructions
139559693Selan
139659693Selan(define_insn "extendhisi2"
139759693Selan  [(set (match_operand:SI 0 "general_operand" "=*d,a")
139859693Selan	(sign_extend:SI
139959693Selan	 (match_operand:HI 1 "nonimmediate_operand" "0,rm")))]
140059693Selan  ""
140159693Selan  "*
140259693Selan{
140359693Selan  if (ADDRESS_REG_P (operands[0]))
140459693Selan    return \"move%.w %1,%0\";
140559693Selan  return \"ext%.l %0\";
140659693Selan}")
140759693Selan
140859693Selan(define_insn "extendqihi2"
140959693Selan  [(set (match_operand:HI 0 "general_operand" "=d")
141059693Selan	(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0")))]
141159693Selan  ""
141259693Selan  "ext%.w %0")
141359693Selan
141459693Selan(define_insn "extendqisi2"
141559693Selan  [(set (match_operand:SI 0 "general_operand" "=d")
141659693Selan	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0")))]
141759693Selan  "TARGET_68020"
141859693Selan  "extb%.l %0")
141959693Selan
142059693Selan;; Conversions between float and double.
142159693Selan
142259693Selan(define_expand "extendsfdf2"
142359693Selan  [(set (match_operand:DF 0 "general_operand" "")
142459693Selan	(float_extend:DF
142559693Selan	 (match_operand:SF 1 "general_operand" "")))]
142659693Selan  "TARGET_68881 || TARGET_FPA"
142759693Selan  "")
142859693Selan
142959693Selan(define_insn ""
143059693Selan  [(set (match_operand:DF 0 "general_operand" "=x,y")
143159693Selan	(float_extend:DF
143259693Selan	 (match_operand:SF 1 "general_operand" "xH,rmF")))]
143359693Selan  "TARGET_FPA"
143459693Selan  "fpstod %w1,%0")
143559693Selan
143659693Selan(define_insn ""
143759693Selan  [(set (match_operand:DF 0 "general_operand" "=*fdm,f")
143859693Selan	(float_extend:DF
143959693Selan	  (match_operand:SF 1 "general_operand" "f,dmF")))]
144059693Selan  "TARGET_68881"
144159693Selan  "*
144259693Selan{
144359693Selan  if (FP_REG_P (operands[0]) && FP_REG_P (operands[1]))
144459693Selan    {
144559693Selan      if (REGNO (operands[0]) == REGNO (operands[1]))
144659693Selan	{
144759693Selan	  /* Extending float to double in an fp-reg is a no-op.
144859693Selan	     NOTICE_UPDATE_CC has already assumed that the
144959693Selan	     cc will be set.  So cancel what it did.  */
145059693Selan	  cc_status = cc_prev_status;
145159693Selan	  return \"\";
145259693Selan	}
145359693Selan      return \"f%&move%.x %1,%0\";
145459693Selan    }
145559693Selan  if (FP_REG_P (operands[0]))
145659693Selan    return \"f%&move%.s %f1,%0\";
145759693Selan  if (DATA_REG_P (operands[0]) && FP_REG_P (operands[1]))
145859693Selan    {
145959693Selan      output_asm_insn (\"fmove%.d %f1,%-\;move%.l %+,%0\", operands);
146059693Selan      operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
146159693Selan      return \"move%.l %+,%0\";
146259693Selan    }
146359693Selan  return \"fmove%.d %f1,%0\";
146459693Selan}")
146559693Selan
146659693Selan;; This cannot output into an f-reg because there is no way to be
146759693Selan;; sure of truncating in that case.
146859693Selan;; But on the Sun FPA, we can be sure.
146959693Selan(define_expand "truncdfsf2"
147059693Selan  [(set (match_operand:SF 0 "general_operand" "")
147159693Selan	(float_truncate:SF
147259693Selan	  (match_operand:DF 1 "general_operand" "")))]
147359693Selan  "TARGET_68881 || TARGET_FPA"
147459693Selan  "")
147559693Selan
147659693Selan(define_insn ""
147759693Selan  [(set (match_operand:SF 0 "general_operand" "=x,y")
147859693Selan	(float_truncate:SF
147959693Selan	  (match_operand:DF 1 "general_operand" "xH,rmF")))]
148059693Selan  "TARGET_FPA"
148159693Selan  "fpdtos %y1,%0")
148259693Selan
148359693Selan;; On the '040 we can truncate in a register accurately and easily.
148459693Selan(define_insn ""
148559693Selan  [(set (match_operand:SF 0 "general_operand" "=f")
148659693Selan	(float_truncate:SF
148759693Selan	  (match_operand:DF 1 "general_operand" "fmG")))]
148859693Selan  "TARGET_68040_ONLY"
148959693Selan  "*
149059693Selan{
149159693Selan  if (FP_REG_P (operands[1]))
149259693Selan    return \"fsmove%.x %1,%0\";
149359693Selan  return \"fsmove%.d %f1,%0\";
149459693Selan}")
149559693Selan
149659693Selan(define_insn ""
149759693Selan  [(set (match_operand:SF 0 "general_operand" "=dm")
149859693Selan	(float_truncate:SF
149959693Selan	  (match_operand:DF 1 "general_operand" "f")))]
150059693Selan  "TARGET_68881"
150159693Selan  "fmove%.s %f1,%0")
150259693Selan
150359693Selan;; Conversion between fixed point and floating point.
150459693Selan;; Note that among the fix-to-float insns
150559693Selan;; the ones that start with SImode come first.
150659693Selan;; That is so that an operand that is a CONST_INT
150759693Selan;; (and therefore lacks a specific machine mode).
150859693Selan;; will be recognized as SImode (which is always valid)
150959693Selan;; rather than as QImode or HImode.
151059693Selan
151159693Selan(define_expand "floatsisf2"
151259693Selan  [(set (match_operand:SF 0 "general_operand" "")
151359693Selan	(float:SF (match_operand:SI 1 "general_operand" "")))]
151459693Selan  "TARGET_68881 || TARGET_FPA"
151559693Selan  "")
151659693Selan
151759693Selan(define_insn ""
151859693Selan  [(set (match_operand:SF 0 "general_operand" "=y,x")
151959693Selan	(float:SF (match_operand:SI 1 "general_operand" "rmi,x")))]
152059693Selan  "TARGET_FPA"
152159693Selan  "fpltos %1,%0")
152259693Selan
152359693Selan(define_insn ""
152459693Selan  [(set (match_operand:SF 0 "general_operand" "=f")
152559693Selan	(float:SF (match_operand:SI 1 "general_operand" "dmi")))]
152659693Selan  "TARGET_68881"
152759693Selan  "f%$move%.l %1,%0")
152859693Selan
152959693Selan(define_expand "floatsidf2"
153059693Selan  [(set (match_operand:DF 0 "general_operand" "")
153159693Selan	(float:DF (match_operand:SI 1 "general_operand" "")))]
153259693Selan  "TARGET_68881 || TARGET_FPA"
153359693Selan  "")
153459693Selan
153559693Selan(define_insn ""
153659693Selan  [(set (match_operand:DF 0 "general_operand" "=y,x")
153759693Selan	(float:DF (match_operand:SI 1 "general_operand" "rmi,x")))]
153859693Selan  "TARGET_FPA"
153959693Selan  "fpltod %1,%0")
154059693Selan
154159693Selan(define_insn ""
154259693Selan  [(set (match_operand:DF 0 "general_operand" "=f")
154359693Selan	(float:DF (match_operand:SI 1 "general_operand" "dmi")))]
154459693Selan  "TARGET_68881"
154559693Selan  "f%&move%.l %1,%0")
154659693Selan
154759693Selan(define_insn "floathisf2"
154859693Selan  [(set (match_operand:SF 0 "general_operand" "=f")
154959693Selan	(float:SF (match_operand:HI 1 "general_operand" "dmn")))]
155059693Selan  "TARGET_68881"
155159693Selan  "f%$move%.w %1,%0")
155259693Selan
155359693Selan(define_insn "floathidf2"
155459693Selan  [(set (match_operand:DF 0 "general_operand" "=f")
155559693Selan	(float:DF (match_operand:HI 1 "general_operand" "dmn")))]
155659693Selan  "TARGET_68881"
155759693Selan  "fmove%.w %1,%0")
155859693Selan
155959693Selan(define_insn "floatqisf2"
156059693Selan  [(set (match_operand:SF 0 "general_operand" "=f")
156159693Selan	(float:SF (match_operand:QI 1 "general_operand" "dmn")))]
156259693Selan  "TARGET_68881"
156359693Selan  "fmove%.b %1,%0")
156459693Selan
156559693Selan(define_insn "floatqidf2"
156659693Selan  [(set (match_operand:DF 0 "general_operand" "=f")
156759693Selan	(float:DF (match_operand:QI 1 "general_operand" "dmn")))]
156859693Selan  "TARGET_68881"
156959693Selan  "f%&move%.b %1,%0")
157059693Selan
157159693Selan;; New routines to convert floating-point values to integers
157259693Selan;; to be used on the '040.  These should be faster than trapping
157359693Selan;; into the kernel to emulate fintrz.  They should also be faster
157459693Selan;; than calling the subroutines fixsfsi() or fixdfsi().
157559693Selan
157659693Selan(define_insn "fix_truncdfsi2"
157759693Selan  [(set (match_operand:SI 0 "general_operand" "=dm")
157859693Selan	(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
157959693Selan   (clobber (match_scratch:SI 2 "=d"))
158059693Selan   (clobber (match_scratch:SI 3 "=d"))]
158159693Selan  "TARGET_68040"
158259693Selan  "*
158359693Selan{
158459693Selan  CC_STATUS_INIT;
158559693Selan  return \"fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.l %1,%0\;fmovem%.l %2,%!\";
158659693Selan}")
158759693Selan
158859693Selan(define_insn "fix_truncdfhi2"
158959693Selan  [(set (match_operand:HI 0 "general_operand" "=dm")
159059693Selan	(fix:HI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
159159693Selan   (clobber (match_scratch:SI 2 "=d"))
159259693Selan   (clobber (match_scratch:SI 3 "=d"))]
159359693Selan  "TARGET_68040"
159459693Selan  "*
159559693Selan{
159659693Selan  CC_STATUS_INIT;
159759693Selan  return \"fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.w %1,%0\;fmovem%.l %2,%!\";
159859693Selan}")
159959693Selan
160059693Selan(define_insn "fix_truncdfqi2"
160159693Selan  [(set (match_operand:QI 0 "general_operand" "=dm")
160259693Selan	(fix:QI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
160359693Selan   (clobber (match_scratch:SI 2 "=d"))
160459693Selan   (clobber (match_scratch:SI 3 "=d"))]
160559693Selan  "TARGET_68040"
160659693Selan  "*
160759693Selan{
160859693Selan  CC_STATUS_INIT;
160959693Selan  return \"fmovem%.l %!,%2\;moveq #16,%3\;or%.l %2,%3\;and%.w #-33,%3\;fmovem%.l %3,%!\;fmove%.b %1,%0\;fmovem%.l %2,%!\";
161059693Selan}")
161159693Selan
161259693Selan;; Convert a float to a float whose value is an integer.
161359693Selan;; This is the first stage of converting it to an integer type.
161459693Selan
161559693Selan(define_insn "ftruncdf2"
161659693Selan  [(set (match_operand:DF 0 "general_operand" "=f")
161759693Selan	(fix:DF (match_operand:DF 1 "general_operand" "fFm")))]
161859693Selan  "TARGET_68881 && !TARGET_68040"
161959693Selan  "*
162059693Selan{
162159693Selan  if (FP_REG_P (operands[1]))
162259693Selan    return \"fintrz%.x %f1,%0\";
162359693Selan  return \"fintrz%.d %f1,%0\";
162459693Selan}")
162559693Selan
162659693Selan(define_insn "ftruncsf2"
162759693Selan  [(set (match_operand:SF 0 "general_operand" "=f")
162859693Selan	(fix:SF (match_operand:SF 1 "general_operand" "dfFm")))]
162959693Selan  "TARGET_68881 && !TARGET_68040"
163059693Selan  "*
163159693Selan{
163259693Selan  if (FP_REG_P (operands[1]))
163359693Selan    return \"fintrz%.x %f1,%0\";
163459693Selan  return \"fintrz%.s %f1,%0\";
163559693Selan}")
163659693Selan
163759693Selan;; Convert a float whose value is an integer
163859693Selan;; to an actual integer.  Second stage of converting float to integer type.
163959693Selan(define_insn "fixsfqi2"
164059693Selan  [(set (match_operand:QI 0 "general_operand" "=dm")
164159693Selan	(fix:QI (match_operand:SF 1 "general_operand" "f")))]
164259693Selan  "TARGET_68881"
164359693Selan  "fmove%.b %1,%0")
164459693Selan
164559693Selan(define_insn "fixsfhi2"
164659693Selan  [(set (match_operand:HI 0 "general_operand" "=dm")
164759693Selan	(fix:HI (match_operand:SF 1 "general_operand" "f")))]
164859693Selan  "TARGET_68881"
164959693Selan  "fmove%.w %1,%0")
165059693Selan
165159693Selan(define_insn "fixsfsi2"
165259693Selan  [(set (match_operand:SI 0 "general_operand" "=dm")
165359693Selan	(fix:SI (match_operand:SF 1 "general_operand" "f")))]
165459693Selan  "TARGET_68881"
165559693Selan  "fmove%.l %1,%0")
165659693Selan
165759693Selan(define_insn "fixdfqi2"
165859693Selan  [(set (match_operand:QI 0 "general_operand" "=dm")
165959693Selan	(fix:QI (match_operand:DF 1 "general_operand" "f")))]
166059693Selan  "TARGET_68881"
166159693Selan  "fmove%.b %1,%0")
166259693Selan
166359693Selan(define_insn "fixdfhi2"
166459693Selan  [(set (match_operand:HI 0 "general_operand" "=dm")
166559693Selan	(fix:HI (match_operand:DF 1 "general_operand" "f")))]
166659693Selan  "TARGET_68881"
166759693Selan  "fmove%.w %1,%0")
166859693Selan
166959693Selan(define_insn "fixdfsi2"
167059693Selan  [(set (match_operand:SI 0 "general_operand" "=dm")
167159693Selan	(fix:SI (match_operand:DF 1 "general_operand" "f")))]
167259693Selan  "TARGET_68881"
167359693Selan  "fmove%.l %1,%0")
167459693Selan
167559693Selan;; Convert a float to an integer.
167659693Selan;; On the Sun FPA, this is done in one step.
167759693Selan
167859693Selan(define_insn ""
167959693Selan  [(set (match_operand:SI 0 "general_operand" "=x,y")
168059693Selan	(fix:SI (fix:SF (match_operand:SF 1 "general_operand" "xH,rmF"))))]
168159693Selan  "TARGET_FPA"
168259693Selan  "fpstol %w1,%0")
168359693Selan
168459693Selan(define_insn ""
168559693Selan  [(set (match_operand:SI 0 "general_operand" "=x,y")
168659693Selan	(fix:SI (fix:DF (match_operand:DF 1 "general_operand" "xH,rmF"))))]
168759693Selan  "TARGET_FPA"
168859693Selan  "fpdtol %y1,%0")
168959693Selan
169059693Selan;; add instructions
169159693Selan
169259693Selan;; Note that the middle two alternatives are near-duplicates
169359693Selan;; in order to handle insns generated by reload.
169459693Selan;; This is needed since they are not themselves reloaded,
169559693Selan;; so commutativity won't apply to them.
169659693Selan(define_insn "addsi3"
169759693Selan  [(set (match_operand:SI 0 "general_operand" "=m,?a,?a,r")
169859693Selan	(plus:SI (match_operand:SI 1 "general_operand" "%0,a,rJK,0")
169959693Selan		 (match_operand:SI 2 "general_operand" "dIKLs,rJK,a,mrIKLs")))]
170059693Selan  ""
170159693Selan  "*
170259693Selan{
170359693Selan  if (! operands_match_p (operands[0], operands[1]))
170459693Selan    {
170559693Selan      if (!ADDRESS_REG_P (operands[1]))
170659693Selan	{
170759693Selan	  rtx tmp = operands[1];
170859693Selan
170959693Selan	  operands[1] = operands[2];
171059693Selan	  operands[2] = tmp;
171159693Selan	}
171259693Selan
171359693Selan      /* These insns can result from reloads to access
171459693Selan	 stack slots over 64k from the frame pointer.  */
171559693Selan      if (GET_CODE (operands[2]) == CONST_INT
171659693Selan	  && INTVAL (operands[2]) + 0x8000 >= (unsigned) 0x10000)
171759693Selan        return \"move%.l %2,%0\;add%.l %1,%0\";
171859693Selan#ifdef SGS
171959693Selan      if (GET_CODE (operands[2]) == REG)
172059693Selan	return \"lea 0(%1,%2.l),%0\";
172159693Selan      else
172259693Selan	return \"lea %c2(%1),%0\";
172359693Selan#else /* not SGS */
172459693Selan#ifdef MOTOROLA
172559693Selan      if (GET_CODE (operands[2]) == REG)
172659693Selan	return \"lea (%1,%2.l),%0\";
172759693Selan      else
172859693Selan	return \"lea (%c2,%1),%0\";
172959693Selan#else /* not MOTOROLA (MIT syntax) */
173059693Selan      if (GET_CODE (operands[2]) == REG)
173159693Selan	return \"lea %1@(0,%2:l),%0\";
173259693Selan      else
173359693Selan	return \"lea %1@(%c2),%0\";
173459693Selan#endif /* not MOTOROLA */
173559693Selan#endif /* not SGS */
173659693Selan    }
173759693Selan  if (GET_CODE (operands[2]) == CONST_INT)
173859693Selan    {
173959693Selan#ifndef NO_ADDSUB_Q
174059693Selan      if (INTVAL (operands[2]) > 0
174159693Selan	  && INTVAL (operands[2]) <= 8)
174259693Selan	return (ADDRESS_REG_P (operands[0])
174359693Selan		? \"addq%.w %2,%0\"
174459693Selan		: \"addq%.l %2,%0\");
174559693Selan      if (INTVAL (operands[2]) < 0
174659693Selan	  && INTVAL (operands[2]) >= -8)
174759693Selan        {
174859693Selan	  operands[2] = gen_rtx (CONST_INT, VOIDmode,
174959693Selan			         - INTVAL (operands[2]));
175059693Selan	  return (ADDRESS_REG_P (operands[0])
175159693Selan		  ? \"subq%.w %2,%0\"
175259693Selan		  : \"subq%.l %2,%0\");
175359693Selan	}
175459693Selan      /* On everything except the 68000 it is faster to use two
175559693Selan	 addqw instructions to add a small integer (8 < N <= 16)
175659693Selan	 to an address register.  Likewise for subqw.*/
175759693Selan      if (INTVAL (operands[2]) > 8
175859693Selan	  && INTVAL (operands[2]) <= 16
175959693Selan	  && ADDRESS_REG_P (operands[0])
176059693Selan	  && TARGET_68020)
176159693Selan	{
176259693Selan	  operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 8);
176359693Selan	  return \"addq%.w %#8,%0\;addq%.w %2,%0\";
176459693Selan	}
176559693Selan      if (INTVAL (operands[2]) < -8
176659693Selan	  && INTVAL (operands[2]) >= -16
176759693Selan	  && ADDRESS_REG_P (operands[0])
176859693Selan	  && TARGET_68020)
176959693Selan	{
177059693Selan	  operands[2] = gen_rtx (CONST_INT, VOIDmode,
177159693Selan				  - INTVAL (operands[2]) - 8);
177259693Selan	  return \"subq%.w %#8,%0\;subq%.w %2,%0\";
177359693Selan	}
177459693Selan#endif
177559693Selan      if (ADDRESS_REG_P (operands[0])
177659693Selan	  && INTVAL (operands[2]) >= -0x8000
177759693Selan	  && INTVAL (operands[2]) < 0x8000)
177859693Selan	return \"add%.w %2,%0\";
177959693Selan    }
178059693Selan  return \"add%.l %2,%0\";
178159693Selan}")
178259693Selan
178359693Selan(define_insn ""
178459693Selan  [(set (match_operand:SI 0 "general_operand" "=a")
178559693Selan	(plus:SI (match_operand:SI 1 "general_operand" "0")
178659693Selan		 (sign_extend:SI
178759693Selan		  (match_operand:HI 2 "nonimmediate_operand" "rm"))))]
178859693Selan  ""
178959693Selan  "add%.w %2,%0")
179059693Selan
179159693Selan(define_insn "addhi3"
179259693Selan  [(set (match_operand:HI 0 "general_operand" "=m,r")
179359693Selan	(plus:HI (match_operand:HI 1 "general_operand" "%0,0")
179459693Selan		 (match_operand:HI 2 "general_operand" "dn,rmn")))]
179559693Selan  ""
179659693Selan  "*
179759693Selan{
179859693Selan#ifndef NO_ADDSUB_Q
179959693Selan  if (GET_CODE (operands[2]) == CONST_INT)
180059693Selan    {
180159693Selan      /* If the constant would be a negative number when interpreted as
180259693Selan	 HImode, make it negative.  This is usually, but not always, done
180359693Selan	 elsewhere in the compiler.  First check for constants out of range,
180459693Selan	 which could confuse us.  */
180559693Selan
180659693Selan      if (INTVAL (operands[2]) >= 32768)
180759693Selan	operands[2] = gen_rtx (CONST_INT, VOIDmode,
180859693Selan			       INTVAL (operands[2]) - 65536);
180959693Selan
181059693Selan      if (INTVAL (operands[2]) > 0
181159693Selan	  && INTVAL (operands[2]) <= 8)
181259693Selan	return \"addq%.w %2,%0\";
181359693Selan      if (INTVAL (operands[2]) < 0
181459693Selan	  && INTVAL (operands[2]) >= -8)
181559693Selan	{
181659693Selan	  operands[2] = gen_rtx (CONST_INT, VOIDmode,
181759693Selan			         - INTVAL (operands[2]));
181859693Selan	  return \"subq%.w %2,%0\";
181959693Selan	}
182059693Selan      /* On everything except the 68000 it is faster to use two
182159693Selan	 addqw instructions to add a small integer (8 < N <= 16)
182259693Selan	 to an address register.  Likewise for subqw. */
182359693Selan      if (INTVAL (operands[2]) > 8
182459693Selan	  && INTVAL (operands[2]) <= 16
182559693Selan	  && ADDRESS_REG_P (operands[0])
182659693Selan	  && TARGET_68020)
182759693Selan	{
182859693Selan	  operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 8);
182959693Selan	  return \"addq%.w %#8,%0\;addq%.w %2,%0\";
183059693Selan	}
183159693Selan      if (INTVAL (operands[2]) < -8
183259693Selan	  && INTVAL (operands[2]) >= -16
183359693Selan	  && ADDRESS_REG_P (operands[0])
183459693Selan	  && TARGET_68020)
183559693Selan	{
183659693Selan	  operands[2] = gen_rtx (CONST_INT, VOIDmode,
183759693Selan				 - INTVAL (operands[2]) - 8);
183859693Selan	  return \"subq%.w %#8,%0\;subq%.w %2,%0\";
183959693Selan	}
184059693Selan    }
184159693Selan#endif
184259693Selan  return \"add%.w %2,%0\";
184359693Selan}")
184459693Selan
184559693Selan;; These insns must use MATCH_DUP instead of the more expected
184659693Selan;; use of a matching constraint because the "output" here is also
184759693Selan;; an input, so you can't use the matching constraint.  That also means
184859693Selan;; that you can't use the "%", so you need patterns with the matched
184959693Selan;; operand in both positions.
185059693Selan
185159693Selan(define_insn ""
185259693Selan  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
185359693Selan	(plus:HI (match_dup 0)
185459693Selan		 (match_operand:HI 1 "general_operand" "dn,rmn")))]
185559693Selan  ""
185659693Selan  "*
185759693Selan{
185859693Selan#ifndef NO_ADDSUB_Q
185959693Selan  if (GET_CODE (operands[1]) == CONST_INT)
186059693Selan    {
186159693Selan      /* If the constant would be a negative number when interpreted as
186259693Selan	 HImode, make it negative.  This is usually, but not always, done
186359693Selan	 elsewhere in the compiler.  First check for constants out of range,
186459693Selan	 which could confuse us.  */
186559693Selan
186659693Selan      if (INTVAL (operands[1]) >= 32768)
186759693Selan	operands[1] = gen_rtx (CONST_INT, VOIDmode,
186859693Selan			       INTVAL (operands[1]) - 65536);
186959693Selan
187059693Selan      if (INTVAL (operands[1]) > 0
187159693Selan	  && INTVAL (operands[1]) <= 8)
187259693Selan	return \"addq%.w %1,%0\";
187359693Selan      if (INTVAL (operands[1]) < 0
187459693Selan	  && INTVAL (operands[1]) >= -8)
187559693Selan	{
187659693Selan	  operands[1] = gen_rtx (CONST_INT, VOIDmode,
187759693Selan			         - INTVAL (operands[1]));
187859693Selan	  return \"subq%.w %1,%0\";
187959693Selan	}
188059693Selan      /* On everything except the 68000 it is faster to use two
188159693Selan	 addqw instructions to add a small integer (8 < N <= 16)
188259693Selan	 to an address register.  Likewise for subqw. */
188359693Selan      if (INTVAL (operands[1]) > 8
188459693Selan	  && INTVAL (operands[1]) <= 16
188559693Selan	  && ADDRESS_REG_P (operands[0])
188659693Selan	  && TARGET_68020)
188759693Selan	{
188859693Selan	  operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) - 8);
188959693Selan	  return \"addq%.w %#8,%0\;addq%.w %1,%0\";
189059693Selan	}
189159693Selan      if (INTVAL (operands[1]) < -8
189259693Selan	  && INTVAL (operands[1]) >= -16
189359693Selan	  && ADDRESS_REG_P (operands[0])
189459693Selan	  && TARGET_68020)
189559693Selan	{
189659693Selan	  operands[1] = gen_rtx (CONST_INT, VOIDmode,
189759693Selan				 - INTVAL (operands[1]) - 8);
189859693Selan	  return \"subq%.w %#8,%0\;subq%.w %1,%0\";
189959693Selan	}
190059693Selan    }
190159693Selan#endif
190259693Selan  return \"add%.w %1,%0\";
190359693Selan}")
190459693Selan
190559693Selan(define_insn ""
190659693Selan  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
190759693Selan	(plus:HI (match_operand:HI 1 "general_operand" "dn,rmn")
190859693Selan		 (match_dup 0)))]
190959693Selan  ""
191059693Selan  "*
191159693Selan{
191259693Selan#ifndef NO_ADDSUB_Q
191359693Selan  if (GET_CODE (operands[1]) == CONST_INT)
191459693Selan    {
191559693Selan      /* If the constant would be a negative number when interpreted as
191659693Selan	 HImode, make it negative.  This is usually, but not always, done
191759693Selan	 elsewhere in the compiler.  First check for constants out of range,
191859693Selan	 which could confuse us.  */
191959693Selan
192059693Selan      if (INTVAL (operands[1]) >= 32768)
192159693Selan	operands[1] = gen_rtx (CONST_INT, VOIDmode,
192259693Selan			       INTVAL (operands[1]) - 65536);
192359693Selan
192459693Selan      if (INTVAL (operands[1]) > 0
192559693Selan	  && INTVAL (operands[1]) <= 8)
192659693Selan	return \"addq%.w %1,%0\";
192759693Selan      if (INTVAL (operands[1]) < 0
192859693Selan	  && INTVAL (operands[1]) >= -8)
192959693Selan	{
193059693Selan	  operands[1] = gen_rtx (CONST_INT, VOIDmode,
193159693Selan			         - INTVAL (operands[1]));
193259693Selan	  return \"subq%.w %1,%0\";
193359693Selan	}
193459693Selan      /* On everything except the 68000 it is faster to use two
193559693Selan	 addqw instructions to add a small integer (8 < N <= 16)
193659693Selan	 to an address register.  Likewise for subqw. */
193759693Selan      if (INTVAL (operands[1]) > 8
193859693Selan	  && INTVAL (operands[1]) <= 16
193959693Selan	  && ADDRESS_REG_P (operands[0])
194059693Selan	  && TARGET_68020)
194159693Selan	{
194259693Selan	  operands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[1]) - 8);
194359693Selan	  return \"addq%.w %#8,%0\;addq%.w %1,%0\";
194459693Selan	}
194559693Selan      if (INTVAL (operands[1]) < -8
194659693Selan	  && INTVAL (operands[1]) >= -16
194759693Selan	  && ADDRESS_REG_P (operands[0])
194859693Selan	  && TARGET_68020)
194959693Selan	{
195059693Selan	  operands[1] = gen_rtx (CONST_INT, VOIDmode,
195159693Selan				 - INTVAL (operands[1]) - 8);
195259693Selan	  return \"subq%.w %#8,%0\;subq%.w %1,%0\";
195359693Selan	}
195459693Selan    }
195559693Selan#endif
195659693Selan  return \"add%.w %1,%0\";
195759693Selan}")
195859693Selan
195959693Selan(define_insn "addqi3"
196059693Selan  [(set (match_operand:QI 0 "general_operand" "=m,d")
196159693Selan	(plus:QI (match_operand:QI 1 "general_operand" "%0,0")
196259693Selan		 (match_operand:QI 2 "general_operand" "dn,dmn")))]
196359693Selan  ""
196459693Selan  "*
196559693Selan{
196659693Selan#ifndef NO_ADDSUB_Q
196759693Selan  if (GET_CODE (operands[2]) == CONST_INT)
196859693Selan    {
196959693Selan      if (INTVAL (operands[2]) >= 128)
197059693Selan	operands[2] = gen_rtx (CONST_INT, VOIDmode,
197159693Selan			       INTVAL (operands[2]) - 256);
197259693Selan
197359693Selan      if (INTVAL (operands[2]) > 0
197459693Selan	  && INTVAL (operands[2]) <= 8)
197559693Selan	return \"addq%.b %2,%0\";
197659693Selan      if (INTVAL (operands[2]) < 0 && INTVAL (operands[2]) >= -8)
197759693Selan       {
197859693Selan	 operands[2] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[2]));
197959693Selan	 return \"subq%.b %2,%0\";
198059693Selan       }
198159693Selan    }
198259693Selan#endif
198359693Selan  return \"add%.b %2,%0\";
198459693Selan}")
198559693Selan
198659693Selan(define_insn ""
198759693Selan  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
198859693Selan	(plus:QI (match_dup 0)
198959693Selan		 (match_operand:QI 1 "general_operand" "dn,dmn")))]
199059693Selan  ""
199159693Selan  "*
199259693Selan{
199359693Selan#ifndef NO_ADDSUB_Q
199459693Selan  if (GET_CODE (operands[1]) == CONST_INT)
199559693Selan    {
199659693Selan      if (INTVAL (operands[1]) >= 128)
199759693Selan	operands[1] = gen_rtx (CONST_INT, VOIDmode,
199859693Selan			       INTVAL (operands[1]) - 256);
199959693Selan
200059693Selan      if (INTVAL (operands[1]) > 0
200159693Selan	  && INTVAL (operands[1]) <= 8)
200259693Selan	return \"addq%.b %1,%0\";
200359693Selan      if (INTVAL (operands[1]) < 0 && INTVAL (operands[1]) >= -8)
200459693Selan       {
200559693Selan	 operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]));
200659693Selan	 return \"subq%.b %1,%0\";
200759693Selan       }
200859693Selan    }
200959693Selan#endif
201059693Selan  return \"add%.b %1,%0\";
201159693Selan}")
201259693Selan
201359693Selan(define_insn ""
201459693Selan  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
201559693Selan	(plus:QI (match_operand:QI 1 "general_operand" "dn,dmn")
201659693Selan		 (match_dup 0)))]
201759693Selan  ""
201859693Selan  "*
201959693Selan{
202059693Selan#ifndef NO_ADDSUB_Q
202159693Selan  if (GET_CODE (operands[1]) == CONST_INT)
202259693Selan    {
202359693Selan      if (INTVAL (operands[1]) >= 128)
202459693Selan	operands[1] = gen_rtx (CONST_INT, VOIDmode,
202559693Selan			       INTVAL (operands[1]) - 256);
202659693Selan
202759693Selan      if (INTVAL (operands[1]) > 0
202859693Selan	  && INTVAL (operands[1]) <= 8)
202959693Selan	return \"addq%.b %1,%0\";
203059693Selan      if (INTVAL (operands[1]) < 0 && INTVAL (operands[1]) >= -8)
203159693Selan       {
203259693Selan	 operands[1] = gen_rtx (CONST_INT, VOIDmode, - INTVAL (operands[1]));
203359693Selan	 return \"subq%.b %1,%0\";
203459693Selan       }
203559693Selan    }
203659693Selan#endif
203759693Selan  return \"add%.b %1,%0\";
203859693Selan}")
203959693Selan
204059693Selan(define_expand "adddf3"
204159693Selan  [(set (match_operand:DF 0 "general_operand" "")
204259693Selan	(plus:DF (match_operand:DF 1 "general_operand" "")
204359693Selan		 (match_operand:DF 2 "general_operand" "")))]
204459693Selan  "TARGET_68881 || TARGET_FPA"
204559693Selan  "")
204659693Selan
204759693Selan(define_insn ""
204859693Selan  [(set (match_operand:DF 0 "general_operand" "=x,y")
204959693Selan	(plus:DF (match_operand:DF 1 "general_operand" "%xH,y")
205059693Selan		 (match_operand:DF 2 "general_operand" "xH,dmF")))]
205159693Selan  "TARGET_FPA"
205259693Selan  "*
205359693Selan{
205459693Selan  if (rtx_equal_p (operands[0], operands[1]))
205559693Selan    return \"fpadd%.d %y2,%0\";
205659693Selan  if (rtx_equal_p (operands[0], operands[2]))
205759693Selan    return \"fpadd%.d %y1,%0\";
205859693Selan  if (which_alternative == 0)
205959693Selan    return \"fpadd3%.d %w2,%w1,%0\";
206059693Selan  return \"fpadd3%.d %x2,%x1,%0\";
206159693Selan}")
206259693Selan
206359693Selan(define_insn ""
206459693Selan  [(set (match_operand:DF 0 "general_operand" "=f")
206559693Selan	(plus:DF (match_operand:DF 1 "general_operand" "%0")
206659693Selan		 (match_operand:DF 2 "general_operand" "fmG")))]
206759693Selan  "TARGET_68881"
206859693Selan  "*
206959693Selan{
207059693Selan  if (REG_P (operands[2]))
207159693Selan    return \"f%&add%.x %2,%0\";
207259693Selan  return \"f%&add%.d %f2,%0\";
207359693Selan}")
207459693Selan
207559693Selan(define_expand "addsf3"
207659693Selan  [(set (match_operand:SF 0 "general_operand" "")
207759693Selan	(plus:SF (match_operand:SF 1 "general_operand" "")
207859693Selan		 (match_operand:SF 2 "general_operand" "")))]
207959693Selan  "TARGET_68881 || TARGET_FPA"
208059693Selan  "")
208159693Selan
208259693Selan(define_insn ""
208359693Selan  [(set (match_operand:SF 0 "general_operand" "=x,y")
208459693Selan	(plus:SF (match_operand:SF 1 "general_operand" "%xH,y")
208559693Selan		 (match_operand:SF 2 "general_operand" "xH,rmF")))]
208659693Selan  "TARGET_FPA"
208759693Selan  "*
208859693Selan{
208959693Selan  if (rtx_equal_p (operands[0], operands[1]))
209059693Selan    return \"fpadd%.s %w2,%0\";
209159693Selan  if (rtx_equal_p (operands[0], operands[2]))
209259693Selan    return \"fpadd%.s %w1,%0\";
209359693Selan  if (which_alternative == 0)
209459693Selan    return \"fpadd3%.s %w2,%w1,%0\";
209559693Selan  return \"fpadd3%.s %2,%1,%0\";
209659693Selan}")
209759693Selan
209859693Selan(define_insn ""
209959693Selan  [(set (match_operand:SF 0 "general_operand" "=f")
210059693Selan	(plus:SF (match_operand:SF 1 "general_operand" "%0")
210159693Selan		 (match_operand:SF 2 "general_operand" "fdmF")))]
210259693Selan  "TARGET_68881"
210359693Selan  "*
210459693Selan{
210559693Selan  if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
210659693Selan    return \"f%$add%.x %2,%0\";
210759693Selan  return \"f%$add%.s %f2,%0\";
210859693Selan}")
210959693Selan
211059693Selan;; subtract instructions
211159693Selan
211259693Selan(define_insn "subsi3"
211359693Selan  [(set (match_operand:SI 0 "general_operand" "=m,r,!a,?d")
211459693Selan	(minus:SI (match_operand:SI 1 "general_operand" "0,0,a,mrIKs")
211559693Selan		  (match_operand:SI 2 "general_operand" "dIKs,mrIKs,J,0")))]
211659693Selan  ""
211759693Selan  "*
211859693Selan{
211959693Selan  if (! operands_match_p (operands[0], operands[1]))
212059693Selan    {
212159693Selan      if (operands_match_p (operands[0], operands[2]))
212259693Selan	{
212359693Selan#ifndef NO_ADDSUB_Q
212459693Selan	  if (GET_CODE (operands[1]) == CONST_INT)
212559693Selan	    {
212659693Selan	      if (INTVAL (operands[1]) > 0
212759693Selan		  && INTVAL (operands[1]) <= 8)
212859693Selan		return \"subq%.l %1,%0\;neg%.l %0\";
212959693Selan	    }
213059693Selan#endif
213159693Selan	  return \"sub%.l %1,%0\;neg%.l %0\";
213259693Selan	}
213359693Selan      /* This case is matched by J, but negating -0x8000
213459693Selan         in an lea would give an invalid displacement.
213559693Selan	 So do this specially.  */
213659693Selan      if (INTVAL (operands[2]) == -0x8000)
213759693Selan	return \"move%.l %1,%0\;sub%.l %2,%0\";
213859693Selan#ifdef SGS
213959693Selan      return \"lea %n2(%1),%0\";
214059693Selan#else
214159693Selan#ifdef MOTOROLA
214259693Selan      return \"lea (%n2,%1),%0\";
214359693Selan#else /* not MOTOROLA (MIT syntax) */
214459693Selan      return \"lea %1@(%n2),%0\";
214559693Selan#endif /* not MOTOROLA */
214659693Selan#endif /* not SGS */
214759693Selan    }
214859693Selan  if (GET_CODE (operands[2]) == CONST_INT)
214959693Selan    {
215059693Selan#ifndef NO_ADDSUB_Q
215159693Selan      if (INTVAL (operands[2]) > 0
215259693Selan	  && INTVAL (operands[2]) <= 8)
215359693Selan	return \"subq%.l %2,%0\";
215459693Selan      /* Using two subqw for 8 < N <= 16 being subtracted from an
215559693Selan	 address register is faster on all but 68000 */
215659693Selan      if (INTVAL (operands[2]) > 8
215759693Selan	  && INTVAL (operands[2]) <= 16
215859693Selan	  && ADDRESS_REG_P (operands[0])
215959693Selan	  && TARGET_68020)
216059693Selan	{
216159693Selan	  operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 8);
216259693Selan	  return \"subq%.w %#8,%0\;subq%.w %2,%0\";
216359693Selan	}
216459693Selan#endif
216559693Selan      if (ADDRESS_REG_P (operands[0])
216659693Selan	  && INTVAL (operands[2]) >= -0x8000
216759693Selan	  && INTVAL (operands[2]) < 0x8000)
216859693Selan	return \"sub%.w %2,%0\";
216959693Selan    }
217059693Selan  return \"sub%.l %2,%0\";
217159693Selan}")
217259693Selan
217359693Selan(define_insn ""
217459693Selan  [(set (match_operand:SI 0 "general_operand" "=a")
217559693Selan	(minus:SI (match_operand:SI 1 "general_operand" "0")
217659693Selan		  (sign_extend:SI
217759693Selan		   (match_operand:HI 2 "nonimmediate_operand" "rm"))))]
217859693Selan  ""
217959693Selan  "sub%.w %2,%0")
218059693Selan
218159693Selan(define_insn "subhi3"
218259693Selan  [(set (match_operand:HI 0 "general_operand" "=m,r")
218359693Selan	(minus:HI (match_operand:HI 1 "general_operand" "0,0")
218459693Selan		  (match_operand:HI 2 "general_operand" "dn,rmn")))]
218559693Selan  ""
218659693Selan  "sub%.w %2,%0")
218759693Selan
218859693Selan(define_insn ""
218959693Selan  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
219059693Selan	(minus:HI (match_dup 0)
219159693Selan		  (match_operand:HI 1 "general_operand" "dn,rmn")))]
219259693Selan  ""
219359693Selan  "sub%.w %1,%0")
219459693Selan
219559693Selan(define_insn "subqi3"
219659693Selan  [(set (match_operand:QI 0 "general_operand" "=m,d")
219759693Selan	(minus:QI (match_operand:QI 1 "general_operand" "0,0")
219859693Selan		  (match_operand:QI 2 "general_operand" "dn,dmn")))]
219959693Selan  ""
220059693Selan  "sub%.b %2,%0")
220159693Selan
220259693Selan(define_insn ""
220359693Selan  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
220459693Selan	(minus:QI (match_dup 0)
220559693Selan		  (match_operand:QI 1 "general_operand" "dn,dmn")))]
220659693Selan  ""
220759693Selan  "sub%.b %1,%0")
220859693Selan
220959693Selan(define_expand "subdf3"
221059693Selan  [(set (match_operand:DF 0 "general_operand" "")
221159693Selan	(minus:DF (match_operand:DF 1 "general_operand" "")
221259693Selan		  (match_operand:DF 2 "general_operand" "")))]
221359693Selan  "TARGET_68881 || TARGET_FPA"
221459693Selan  "")
221559693Selan
221659693Selan(define_insn ""
221759693Selan  [(set (match_operand:DF 0 "general_operand" "=x,y,y")
221859693Selan	(minus:DF (match_operand:DF 1 "general_operand" "xH,y,dmF")
221959693Selan		  (match_operand:DF 2 "general_operand" "xH,dmF,0")))]
222059693Selan  "TARGET_FPA"
222159693Selan  "*
222259693Selan{
222359693Selan  if (rtx_equal_p (operands[0], operands[2]))
222459693Selan    return \"fprsub%.d %y1,%0\";
222559693Selan  if (rtx_equal_p (operands[0], operands[1]))
222659693Selan    return \"fpsub%.d %y2,%0\";
222759693Selan  if (which_alternative == 0)
222859693Selan    return \"fpsub3%.d %w2,%w1,%0\";
222959693Selan  return \"fpsub3%.d %x2,%x1,%0\";
223059693Selan}")
223159693Selan
223259693Selan(define_insn ""
223359693Selan  [(set (match_operand:DF 0 "general_operand" "=f")
223459693Selan	(minus:DF (match_operand:DF 1 "general_operand" "0")
223559693Selan		  (match_operand:DF 2 "general_operand" "fmG")))]
223659693Selan  "TARGET_68881"
223759693Selan  "*
223859693Selan{
223959693Selan  if (REG_P (operands[2]))
224059693Selan    return \"f%&sub%.x %2,%0\";
224159693Selan  return \"f%&sub%.d %f2,%0\";
224259693Selan}")
224359693Selan
224459693Selan(define_expand "subsf3"
224559693Selan  [(set (match_operand:SF 0 "general_operand" "")
224659693Selan	(minus:SF (match_operand:SF 1 "general_operand" "")
224759693Selan		  (match_operand:SF 2 "general_operand" "")))]
224859693Selan  "TARGET_68881 || TARGET_FPA"
224959693Selan  "")
225059693Selan
225159693Selan(define_insn ""
225259693Selan  [(set (match_operand:SF 0 "general_operand" "=x,y,y")
225359693Selan	(minus:SF (match_operand:SF 1 "general_operand" "xH,y,rmF")
225459693Selan		  (match_operand:SF 2 "general_operand" "xH,rmF,0")))]
225559693Selan  "TARGET_FPA"
225659693Selan  "*
225759693Selan{
225859693Selan  if (rtx_equal_p (operands[0], operands[2]))
225959693Selan    return \"fprsub%.s %w1,%0\";
226059693Selan  if (rtx_equal_p (operands[0], operands[1]))
226159693Selan    return \"fpsub%.s %w2,%0\";
226259693Selan  if (which_alternative == 0)
226359693Selan    return \"fpsub3%.s %w2,%w1,%0\";
226459693Selan  return \"fpsub3%.s %2,%1,%0\";
226559693Selan}")
226659693Selan
226759693Selan(define_insn ""
226859693Selan  [(set (match_operand:SF 0 "general_operand" "=f")
226959693Selan	(minus:SF (match_operand:SF 1 "general_operand" "0")
227059693Selan		  (match_operand:SF 2 "general_operand" "fdmF")))]
227159693Selan  "TARGET_68881"
227259693Selan  "*
227359693Selan{
227459693Selan  if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
227559693Selan    return \"f%$sub%.x %2,%0\";
227659693Selan  return \"f%$sub%.s %f2,%0\";
227759693Selan}")
227859693Selan
227959693Selan;; multiply instructions
228059693Selan
228159693Selan(define_insn "mulhi3"
228259693Selan  [(set (match_operand:HI 0 "general_operand" "=d")
228359693Selan	(mult:HI (match_operand:HI 1 "general_operand" "%0")
228459693Selan		 (match_operand:HI 2 "general_operand" "dmn")))]
228559693Selan  ""
228659693Selan  "*
228759693Selan{
228859693Selan#if defined(MOTOROLA) && !defined(CRDS)
228959693Selan  return \"muls%.w %2,%0\";
229059693Selan#else
229159693Selan  return \"muls %2,%0\";
229259693Selan#endif
229359693Selan}")
229459693Selan
229559693Selan(define_insn "mulhisi3"
229659693Selan  [(set (match_operand:SI 0 "general_operand" "=d")
229759693Selan	(mult:SI (sign_extend:SI
229859693Selan		  (match_operand:HI 1 "nonimmediate_operand" "%0"))
229959693Selan		 (sign_extend:SI
230059693Selan		  (match_operand:HI 2 "nonimmediate_operand" "dm"))))]
230159693Selan  ""
230259693Selan  "*
230359693Selan{
230459693Selan#if defined(MOTOROLA) && !defined(CRDS)
230559693Selan  return \"muls%.w %2,%0\";
230659693Selan#else
230759693Selan  return \"muls %2,%0\";
230859693Selan#endif
230959693Selan}")
231059693Selan
231159693Selan(define_insn ""
231259693Selan  [(set (match_operand:SI 0 "general_operand" "=d")
231359693Selan	(mult:SI (sign_extend:SI
231459693Selan		  (match_operand:HI 1 "nonimmediate_operand" "%0"))
231559693Selan		 (match_operand:SI 2 "const_int_operand" "n")))]
231659693Selan  ""
231759693Selan  "*
231859693Selan{
231959693Selan#if defined(MOTOROLA) && !defined(CRDS)
232059693Selan  return \"muls%.w %2,%0\";
232159693Selan#else
232259693Selan  return \"muls %2,%0\";
232359693Selan#endif
232459693Selan}")
232559693Selan
232659693Selan(define_insn "mulsi3"
232759693Selan  [(set (match_operand:SI 0 "general_operand" "=d")
232859693Selan	(mult:SI (match_operand:SI 1 "general_operand" "%0")
232959693Selan		 (match_operand:SI 2 "general_operand" "dmsK")))]
233059693Selan  "TARGET_68020"
233159693Selan  "muls%.l %2,%0")
233259693Selan
233359693Selan(define_insn "umulhisi3"
233459693Selan  [(set (match_operand:SI 0 "general_operand" "=d")
233559693Selan	(mult:SI (zero_extend:SI
233659693Selan		  (match_operand:HI 1 "nonimmediate_operand" "%0"))
233759693Selan		 (zero_extend:SI
233859693Selan		  (match_operand:HI 2 "nonimmediate_operand" "dm"))))]
233959693Selan  ""
234059693Selan  "*
234159693Selan{
234259693Selan#if defined(MOTOROLA) && !defined(CRDS)
234359693Selan  return \"mulu%.w %2,%0\";
234459693Selan#else
234559693Selan  return \"mulu %2,%0\";
234659693Selan#endif
234759693Selan}")
234859693Selan
234959693Selan(define_insn ""
235059693Selan  [(set (match_operand:SI 0 "general_operand" "=d")
235159693Selan	(mult:SI (zero_extend:SI
235259693Selan		  (match_operand:HI 1 "nonimmediate_operand" "%0"))
235359693Selan		 (match_operand:SI 2 "const_int_operand" "n")))]
235459693Selan  ""
235559693Selan  "*
235659693Selan{
235759693Selan#if defined(MOTOROLA) && !defined(CRDS)
235859693Selan  return \"mulu%.w %2,%0\";
235959693Selan#else
236059693Selan  return \"mulu %2,%0\";
236159693Selan#endif
236259693Selan}")
236359693Selan
236459693Selan;; We need a separate DEFINE_EXPAND for u?mulsidi3 to be able to use the
236559693Selan;; proper matching constraint.  This is because the matching is between
236659693Selan;; the high-numbered word of the DImode operand[0] and operand[1].
236759693Selan(define_expand "umulsidi3"
236859693Selan  [(parallel
236959693Selan    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 1)
237059693Selan	  (subreg:SI
237159693Selan	   (mult:DI (zero_extend:DI
237259693Selan		     (match_operand:SI 1 "register_operand" ""))
237359693Selan		    (zero_extend:DI
237459693Selan		     (match_operand:SI 2 "nonimmediate_operand" ""))) 1))
237559693Selan     (set (subreg:SI (match_dup 0) 0)
237659693Selan	  (subreg:SI
237759693Selan	   (mult:DI (zero_extend:DI
237859693Selan		     (match_dup 1))
237959693Selan		    (zero_extend:DI
238059693Selan		     (match_dup 2))) 0))])]
238159693Selan  "TARGET_68020"
238259693Selan  "")
238359693Selan
238459693Selan(define_insn ""
238559693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
238659693Selan	(subreg:SI
238759693Selan	 (mult:DI (zero_extend:DI
238859693Selan		   (match_operand:SI 1 "register_operand" "%0"))
238959693Selan		  (zero_extend:DI
239059693Selan		   (match_operand:SI 2 "nonimmediate_operand" "dm"))) 1))
239159693Selan   (set (match_operand:SI 3 "register_operand" "=d")
239259693Selan	(subreg:SI
239359693Selan	 (mult:DI (zero_extend:DI
239459693Selan		   (match_dup 1))
239559693Selan		  (zero_extend:DI
239659693Selan		   (match_dup 2))) 0))]
239759693Selan  "TARGET_68020"
239859693Selan  "mulu%.l %2,%3:%0")
239959693Selan
240059693Selan(define_insn ""
240159693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
240259693Selan	(subreg:SI
240359693Selan	 (mult:DI (zero_extend:DI
240459693Selan		   (match_operand:SI 1 "register_operand" "%0"))
240559693Selan		  (match_operand:SI 2 "immediate_operand" "sK")) 1))
240659693Selan   (set (match_operand:SI 3 "register_operand" "=d")
240759693Selan	(subreg:SI
240859693Selan	 (mult:DI (zero_extend:DI
240959693Selan		   (match_dup 1))
241059693Selan		  (match_dup 2)) 0))]
241159693Selan  "TARGET_68020
241259693Selan   && (GET_CODE (operands[2]) != CONST_INT
241359693Selan       || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))"
241459693Selan  "mulu%.l %2,%3:%0")
241559693Selan
241659693Selan(define_expand "mulsidi3"
241759693Selan  [(parallel
241859693Selan    [(set (subreg:SI (match_operand:DI 0 "register_operand" "") 1)
241959693Selan	  (subreg:SI
242059693Selan	   (mult:DI (sign_extend:DI
242159693Selan		     (match_operand:SI 1 "register_operand" ""))
242259693Selan		    (sign_extend:DI
242359693Selan		     (match_operand:SI 2 "nonimmediate_operand" ""))) 1))
242459693Selan     (set (subreg:SI (match_dup 0) 0)
242559693Selan	  (subreg:SI
242659693Selan	   (mult:DI (sign_extend:DI
242759693Selan		     (match_dup 1))
242859693Selan		    (sign_extend:DI
242959693Selan		     (match_dup 2))) 0))])]
243059693Selan  "TARGET_68020"
243159693Selan  "")
243259693Selan
243359693Selan(define_insn ""
243459693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
243559693Selan	(subreg:SI
243659693Selan	 (mult:DI (sign_extend:DI
243759693Selan		   (match_operand:SI 1 "register_operand" "%0"))
243859693Selan		  (sign_extend:DI
243959693Selan		   (match_operand:SI 2 "nonimmediate_operand" "dm"))) 1))
244059693Selan   (set (match_operand:SI 3 "register_operand" "=d")
244159693Selan	(subreg:SI
244259693Selan	 (mult:DI (sign_extend:DI
244359693Selan		   (match_dup 1))
244459693Selan		  (sign_extend:DI
244559693Selan		   (match_dup 2))) 0))]
244659693Selan  "TARGET_68020"
244759693Selan  "muls%.l %2,%3:%0")
244859693Selan
244959693Selan(define_insn ""
245059693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
245159693Selan	(subreg:SI
245259693Selan	 (mult:DI (sign_extend:DI
245359693Selan		   (match_operand:SI 1 "register_operand" "%0"))
245459693Selan		  (match_operand:SI 2 "immediate_operand" "sK")) 1))
245559693Selan   (set (match_operand:SI 3 "register_operand" "=d")
245659693Selan	(subreg:SI
245759693Selan	 (mult:DI (sign_extend:DI
245859693Selan		   (match_dup 1))
245959693Selan		   (match_dup 2)) 0))]
246059693Selan  "TARGET_68020
246159693Selan   && (GET_CODE (operands[2]) != CONST_INT
246259693Selan       || CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'K'))"
246359693Selan  "muls%.l %2,%3:%0")
246459693Selan
246559693Selan(define_expand "muldf3"
246659693Selan  [(set (match_operand:DF 0 "general_operand" "")
246759693Selan	(mult:DF (match_operand:DF 1 "general_operand" "")
246859693Selan		 (match_operand:DF 2 "general_operand" "")))]
246959693Selan  "TARGET_68881 || TARGET_FPA"
247059693Selan  "")
247159693Selan
247259693Selan(define_insn ""
247359693Selan  [(set (match_operand:DF 0 "general_operand" "=x,y")
247459693Selan	(mult:DF (match_operand:DF 1 "general_operand" "%xH,y")
247559693Selan		 (match_operand:DF 2 "general_operand" "xH,rmF")))]
247659693Selan  "TARGET_FPA"
247759693Selan  "*
247859693Selan{
247959693Selan  if (rtx_equal_p (operands[1], operands[2]))
248059693Selan    return \"fpsqr%.d %y1,%0\";
248159693Selan  if (rtx_equal_p (operands[0], operands[1]))
248259693Selan    return \"fpmul%.d %y2,%0\";
248359693Selan  if (rtx_equal_p (operands[0], operands[2]))
248459693Selan    return \"fpmul%.d %y1,%0\";
248559693Selan  if (which_alternative == 0)
248659693Selan    return \"fpmul3%.d %w2,%w1,%0\";
248759693Selan  return \"fpmul3%.d %x2,%x1,%0\";
248859693Selan}")
248959693Selan
249059693Selan(define_insn ""
249159693Selan  [(set (match_operand:DF 0 "general_operand" "=f")
249259693Selan	(mult:DF (match_operand:DF 1 "general_operand" "%0")
249359693Selan		 (match_operand:DF 2 "general_operand" "fmG")))]
249459693Selan  "TARGET_68881"
249559693Selan  "*
249659693Selan{
249759693Selan  if (GET_CODE (operands[2]) == CONST_DOUBLE
249859693Selan      && floating_exact_log2 (operands[2]) && !TARGET_68040)
249959693Selan    {
250059693Selan      int i = floating_exact_log2 (operands[2]);
250159693Selan      operands[2] = gen_rtx (CONST_INT, VOIDmode, i);
250259693Selan      return \"fscale%.l %2,%0\";
250359693Selan    }
250459693Selan  if (REG_P (operands[2]))
250559693Selan    return \"f%&mul%.x %2,%0\";
250659693Selan  return \"f%&mul%.d %f2,%0\";
250759693Selan}")
250859693Selan
250959693Selan(define_expand "mulsf3"
251059693Selan  [(set (match_operand:SF 0 "general_operand" "")
251159693Selan	(mult:SF (match_operand:SF 1 "general_operand" "")
251259693Selan		 (match_operand:SF 2 "general_operand" "")))]
251359693Selan  "TARGET_68881 || TARGET_FPA"
251459693Selan  "")
251559693Selan
251659693Selan(define_insn ""
251759693Selan  [(set (match_operand:SF 0 "general_operand" "=x,y")
251859693Selan	(mult:SF (match_operand:SF 1 "general_operand" "%xH,y")
251959693Selan		 (match_operand:SF 2 "general_operand" "xH,rmF")))]
252059693Selan  "TARGET_FPA"
252159693Selan  "*
252259693Selan{
252359693Selan  if (rtx_equal_p (operands[1], operands[2]))
252459693Selan    return \"fpsqr%.s %w1,%0\";
252559693Selan  if (rtx_equal_p (operands[0], operands[1]))
252659693Selan    return \"fpmul%.s %w2,%0\";
252759693Selan  if (rtx_equal_p (operands[0], operands[2]))
252859693Selan    return \"fpmul%.s %w1,%0\";
252959693Selan  if (which_alternative == 0)
253059693Selan    return \"fpmul3%.s %w2,%w1,%0\";
253159693Selan  return \"fpmul3%.s %2,%1,%0\";
253259693Selan}")
253359693Selan
253459693Selan(define_insn ""
253559693Selan  [(set (match_operand:SF 0 "general_operand" "=f")
253659693Selan	(mult:SF (match_operand:SF 1 "general_operand" "%0")
253759693Selan		 (match_operand:SF 2 "general_operand" "fdmF")))]
253859693Selan  "TARGET_68881"
253959693Selan  "*
254059693Selan{
254159693Selan#ifdef FSGLMUL_USE_S
254259693Selan  if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
254359693Selan    return (TARGET_68040_ONLY
254459693Selan	    ? \"fsmul%.s %2,%0\"
254559693Selan	    : \"fsglmul%.s %2,%0\");
254659693Selan#else
254759693Selan  if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
254859693Selan    return (TARGET_68040_ONLY
254959693Selan	    ? \"fsmul%.x %2,%0\"
255059693Selan	    : \"fsglmul%.x %2,%0\");
255159693Selan#endif
255259693Selan  return (TARGET_68040_ONLY
255359693Selan	  ? \"fsmul%.s %f2,%0\"
255459693Selan	  : \"fsglmul%.s %f2,%0\");
255559693Selan}")
255659693Selan
255759693Selan;; divide instructions
255859693Selan
255959693Selan(define_insn "divhi3"
256059693Selan  [(set (match_operand:HI 0 "general_operand" "=d")
256159693Selan	(div:HI (match_operand:HI 1 "general_operand" "0")
256259693Selan		(match_operand:HI 2 "general_operand" "dmn")))]
256359693Selan  ""
256459693Selan  "*
256559693Selan{
256659693Selan#ifdef MOTOROLA
256759693Selan  return \"ext%.l %0\;divs%.w %2,%0\";
256859693Selan#else
256959693Selan  return \"extl %0\;divs %2,%0\";
257059693Selan#endif
257159693Selan}")
257259693Selan
257359693Selan(define_insn "divhisi3"
257459693Selan  [(set (match_operand:HI 0 "general_operand" "=d")
257559693Selan	(truncate:HI
257659693Selan	 (div:SI
257759693Selan	  (match_operand:SI 1 "general_operand" "0")
257859693Selan	  (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "dm")))))]
257959693Selan  ""
258059693Selan  "*
258159693Selan{
258259693Selan#ifdef MOTOROLA
258359693Selan  return \"divs%.w %2,%0\";
258459693Selan#else
258559693Selan  return \"divs %2,%0\";
258659693Selan#endif
258759693Selan}")
258859693Selan
258959693Selan(define_insn ""
259059693Selan  [(set (match_operand:HI 0 "general_operand" "=d")
259159693Selan	(truncate:HI (div:SI (match_operand:SI 1 "general_operand" "0")
259259693Selan			     (match_operand:SI 2 "const_int_operand" "n"))))]
259359693Selan  ""
259459693Selan  "*
259559693Selan{
259659693Selan#ifdef MOTOROLA
259759693Selan  return \"divs%.w %2,%0\";
259859693Selan#else
259959693Selan  return \"divs %2,%0\";
260059693Selan#endif
260159693Selan}")
260259693Selan
260359693Selan(define_insn "udivhi3"
260459693Selan  [(set (match_operand:HI 0 "general_operand" "=d")
260559693Selan	(udiv:HI (match_operand:HI 1 "general_operand" "0")
260659693Selan		 (match_operand:HI 2 "general_operand" "dmn")))]
260759693Selan  ""
260859693Selan  "*
260959693Selan{
261059693Selan#ifdef MOTOROLA
261159693Selan  return \"and%.l %#0xFFFF,%0\;divu%.w %2,%0\";
261259693Selan#else
261359693Selan  return \"andl %#0xFFFF,%0\;divu %2,%0\";
261459693Selan#endif
261559693Selan}")
261659693Selan
261759693Selan(define_insn "udivhisi3"
261859693Selan  [(set (match_operand:HI 0 "general_operand" "=d")
261959693Selan	(truncate:HI
262059693Selan	 (udiv:SI
262159693Selan	  (match_operand:SI 1 "general_operand" "0")
262259693Selan	  (zero_extend:SI (match_operand:HI 2 "nonimmediate_operand" "dm")))))]
262359693Selan  ""
262459693Selan  "*
262559693Selan{
262659693Selan#ifdef MOTOROLA
262759693Selan  return \"divu%.w %2,%0\";
262859693Selan#else
262959693Selan  return \"divu %2,%0\";
263059693Selan#endif
263159693Selan}")
263259693Selan
263359693Selan(define_insn ""
263459693Selan  [(set (match_operand:HI 0 "general_operand" "=d")
263559693Selan	(truncate:HI (udiv:SI (match_operand:SI 1 "general_operand" "0")
263659693Selan			      (match_operand:SI 2 "const_int_operand" "n"))))]
263759693Selan  ""
263859693Selan  "*
263959693Selan{
264059693Selan#ifdef MOTOROLA
264159693Selan  return \"divu%.w %2,%0\";
264259693Selan#else
264359693Selan  return \"divu %2,%0\";
264459693Selan#endif
264559693Selan}")
264659693Selan
264759693Selan(define_expand "divdf3"
264859693Selan  [(set (match_operand:DF 0 "general_operand" "")
264959693Selan	(div:DF (match_operand:DF 1 "general_operand" "")
265059693Selan		(match_operand:DF 2 "general_operand" "")))]
265159693Selan  "TARGET_68881 || TARGET_FPA"
265259693Selan  "")
265359693Selan
265459693Selan(define_insn ""
265559693Selan  [(set (match_operand:DF 0 "general_operand" "=x,y,y")
265659693Selan	(div:DF (match_operand:DF 1 "general_operand" "xH,y,rmF")
265759693Selan		(match_operand:DF 2 "general_operand" "xH,rmF,0")))]
265859693Selan  "TARGET_FPA"
265959693Selan  "*
266059693Selan{
266159693Selan  if (rtx_equal_p (operands[0], operands[2]))
266259693Selan    return \"fprdiv%.d %y1,%0\";
266359693Selan  if (rtx_equal_p (operands[0], operands[1]))
266459693Selan    return \"fpdiv%.d %y2,%0\";
266559693Selan  if (which_alternative == 0)
266659693Selan    return \"fpdiv3%.d %w2,%w1,%0\";
266759693Selan  return \"fpdiv3%.d %x2,%x1,%x0\";
266859693Selan}")
266959693Selan
267059693Selan(define_insn ""
267159693Selan  [(set (match_operand:DF 0 "general_operand" "=f")
267259693Selan	(div:DF (match_operand:DF 1 "general_operand" "0")
267359693Selan		(match_operand:DF 2 "general_operand" "fmG")))]
267459693Selan  "TARGET_68881"
267559693Selan  "*
267659693Selan{
267759693Selan  if (REG_P (operands[2]))
267859693Selan    return \"f%&div%.x %2,%0\";
267959693Selan  return \"f%&div%.d %f2,%0\";
268059693Selan}")
268159693Selan
268259693Selan(define_expand "divsf3"
268359693Selan  [(set (match_operand:SF 0 "general_operand" "")
268459693Selan	(div:SF (match_operand:SF 1 "general_operand" "")
268559693Selan		(match_operand:SF 2 "general_operand" "")))]
268659693Selan  "TARGET_68881 || TARGET_FPA"
268759693Selan  "")
268859693Selan
268959693Selan(define_insn ""
269059693Selan  [(set (match_operand:SF 0 "general_operand" "=x,y,y")
269159693Selan	(div:SF (match_operand:SF 1 "general_operand" "xH,y,rmF")
269259693Selan		(match_operand:SF 2 "general_operand" "xH,rmF,0")))]
269359693Selan  "TARGET_FPA"
269459693Selan  "*
269559693Selan{
269659693Selan  if (rtx_equal_p (operands[0], operands[1]))
269759693Selan    return \"fpdiv%.s %w2,%0\";
269859693Selan  if (rtx_equal_p (operands[0], operands[2]))
269959693Selan    return \"fprdiv%.s %w1,%0\";
270059693Selan  if (which_alternative == 0)
270159693Selan    return \"fpdiv3%.s %w2,%w1,%0\";
270259693Selan  return \"fpdiv3%.s %2,%1,%0\";
270359693Selan}")
270459693Selan
270559693Selan(define_insn ""
270659693Selan  [(set (match_operand:SF 0 "general_operand" "=f")
270759693Selan	(div:SF (match_operand:SF 1 "general_operand" "0")
270859693Selan		(match_operand:SF 2 "general_operand" "fdmF")))]
270959693Selan  "TARGET_68881"
271059693Selan  "*
271159693Selan{
271259693Selan#ifdef FSGLDIV_USE_S
271359693Selan  if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
271459693Selan    return (TARGET_68040_ONLY
271559693Selan	    ? \"fsdiv%.s %2,%0\"
271659693Selan	    : \"fsgldiv%.s %2,%0\");
271759693Selan#else
271859693Selan  if (REG_P (operands[2]) && ! DATA_REG_P (operands[2]))
271959693Selan    return (TARGET_68040_ONLY
272059693Selan	    ? \"fsdiv%.x %2,%0\"
272159693Selan	    : \"fsgldiv%.x %2,%0\");
272259693Selan#endif
272359693Selan  return (TARGET_68040_ONLY
272459693Selan	  ? \"fsdiv%.s %f2,%0\"
272559693Selan	  : \"fsgldiv%.s %f2,%0\");
272659693Selan}")
272759693Selan
272859693Selan;; Remainder instructions.
272959693Selan
273059693Selan(define_insn "modhi3"
273159693Selan  [(set (match_operand:HI 0 "general_operand" "=d")
273259693Selan	(mod:HI (match_operand:HI 1 "general_operand" "0")
273359693Selan		(match_operand:HI 2 "general_operand" "dmn")))]
273459693Selan  ""
273559693Selan  "*
273659693Selan{
273759693Selan  /* The swap insn produces cc's that don't correspond to the result.  */
273859693Selan  CC_STATUS_INIT;
273959693Selan#ifdef MOTOROLA
274059693Selan  return \"ext%.l %0\;divs%.w %2,%0\;swap %0\";
274159693Selan#else
274259693Selan  return \"extl %0\;divs %2,%0\;swap %0\";
274359693Selan#endif
274459693Selan}")
274559693Selan
274659693Selan(define_insn "modhisi3"
274759693Selan  [(set (match_operand:HI 0 "general_operand" "=d")
274859693Selan	(truncate:HI
274959693Selan	 (mod:SI
275059693Selan	  (match_operand:SI 1 "general_operand" "0")
275159693Selan	  (sign_extend:SI (match_operand:HI 2 "nonimmediate_operand" "dm")))))]
275259693Selan  ""
275359693Selan  "*
275459693Selan{
275559693Selan  /* The swap insn produces cc's that don't correspond to the result.  */
275659693Selan  CC_STATUS_INIT;
275759693Selan#ifdef MOTOROLA
275859693Selan  return \"divs%.w %2,%0\;swap %0\";
275959693Selan#else
276059693Selan  return \"divs %2,%0\;swap %0\";
276159693Selan#endif
276259693Selan}")
276359693Selan
276459693Selan(define_insn ""
276559693Selan  [(set (match_operand:HI 0 "general_operand" "=d")
276659693Selan	(truncate:HI (mod:SI (match_operand:SI 1 "general_operand" "0")
276759693Selan			     (match_operand:SI 2 "const_int_operand" "n"))))]
276859693Selan  ""
276959693Selan  "*
277059693Selan{
277159693Selan  /* The swap insn produces cc's that don't correspond to the result.  */
277259693Selan  CC_STATUS_INIT;
277359693Selan#ifdef MOTOROLA
277459693Selan  return \"divs%.w %2,%0\;swap %0\";
277559693Selan#else
277659693Selan  return \"divs %2,%0\;swap %0\";
277759693Selan#endif
277859693Selan}")
277959693Selan
278059693Selan(define_insn "umodhi3"
278159693Selan  [(set (match_operand:HI 0 "general_operand" "=d")
278259693Selan	(umod:HI (match_operand:HI 1 "general_operand" "0")
278359693Selan		 (match_operand:HI 2 "general_operand" "dmn")))]
278459693Selan  ""
278559693Selan  "*
278659693Selan{
278759693Selan  /* The swap insn produces cc's that don't correspond to the result.  */
278859693Selan  CC_STATUS_INIT;
278959693Selan#ifdef MOTOROLA
279059693Selan  return \"and%.l %#0xFFFF,%0\;divu%.w %2,%0\;swap %0\";
279159693Selan#else
279259693Selan  return \"andl %#0xFFFF,%0\;divu %2,%0\;swap %0\";
279359693Selan#endif
279459693Selan}")
279559693Selan
279659693Selan(define_insn "umodhisi3"
279759693Selan  [(set (match_operand:HI 0 "general_operand" "=d")
279859693Selan	(truncate:HI
279959693Selan	 (umod:SI
280059693Selan	  (match_operand:SI 1 "general_operand" "0")
280159693Selan	  (zero_extend:SI (match_operand:HI 2 "nonimmediate_operand" "dm")))))]
280259693Selan  ""
280359693Selan  "*
280459693Selan{
280559693Selan  /* The swap insn produces cc's that don't correspond to the result.  */
280659693Selan  CC_STATUS_INIT;
280759693Selan#ifdef MOTOROLA
280859693Selan  return \"divu%.w %2,%0\;swap %0\";
280959693Selan#else
281059693Selan  return \"divu %2,%0\;swap %0\";
281159693Selan#endif
281259693Selan}")
281359693Selan
281459693Selan(define_insn ""
281559693Selan  [(set (match_operand:HI 0 "general_operand" "=d")
281659693Selan	(truncate:HI (umod:SI (match_operand:SI 1 "general_operand" "0")
281759693Selan			      (match_operand:SI 2 "const_int_operand" "n"))))]
281859693Selan  ""
281959693Selan  "*
282059693Selan{
282159693Selan  /* The swap insn produces cc's that don't correspond to the result.  */
282259693Selan  CC_STATUS_INIT;
282359693Selan#ifdef MOTOROLA
282459693Selan  return \"divu%.w %2,%0\;swap %0\";
282559693Selan#else
282659693Selan  return \"divu %2,%0\;swap %0\";
282759693Selan#endif
282859693Selan}")
282959693Selan
283059693Selan(define_insn "divmodsi4"
283159693Selan  [(set (match_operand:SI 0 "general_operand" "=d")
283259693Selan	(div:SI (match_operand:SI 1 "general_operand" "0")
283359693Selan		(match_operand:SI 2 "general_operand" "dmsK")))
283459693Selan   (set (match_operand:SI 3 "general_operand" "=d")
283559693Selan	(mod:SI (match_dup 1) (match_dup 2)))]
283659693Selan  "TARGET_68020"
283759693Selan  "*
283859693Selan{
283959693Selan  if (find_reg_note (insn, REG_UNUSED, operands[3]))
284059693Selan    return \"divs%.l %2,%0\";
284159693Selan  else
284259693Selan    return \"divsl%.l %2,%3:%0\";
284359693Selan}")
284459693Selan
284559693Selan(define_insn "udivmodsi4"
284659693Selan  [(set (match_operand:SI 0 "general_operand" "=d")
284759693Selan	(udiv:SI (match_operand:SI 1 "general_operand" "0")
284859693Selan		 (match_operand:SI 2 "general_operand" "dmsK")))
284959693Selan   (set (match_operand:SI 3 "general_operand" "=d")
285059693Selan	(umod:SI (match_dup 1) (match_dup 2)))]
285159693Selan  "TARGET_68020"
285259693Selan  "*
285359693Selan{
285459693Selan  if (find_reg_note (insn, REG_UNUSED, operands[3]))
285559693Selan    return \"divu%.l %2,%0\";
285659693Selan  else
285759693Selan    return \"divul%.l %2,%3:%0\";
285859693Selan}")
285959693Selan
286059693Selan;; logical-and instructions
286159693Selan
286259693Selan;; Prevent AND from being made with sp.  This doesn't exist in the machine
286359693Selan;; and reload will cause inefficient code.  Since sp is a FIXED_REG, we
286459693Selan;; can't allocate pseudos into it.
286559693Selan(define_insn "andsi3"
286659693Selan  [(set (match_operand:SI 0 "not_sp_operand" "=m,d")
286759693Selan	(and:SI (match_operand:SI 1 "general_operand" "%0,0")
286859693Selan		(match_operand:SI 2 "general_operand" "dKs,dmKs")))]
286959693Selan  ""
287059693Selan  "*
287159693Selan{
287259693Selan  int logval;
287359693Selan  if (GET_CODE (operands[2]) == CONST_INT
287459693Selan      && (INTVAL (operands[2]) | 0xffff) == 0xffffffff
287559693Selan      && (DATA_REG_P (operands[0])
287659693Selan	  || offsettable_memref_p (operands[0])))
287759693Selan    {
287859693Selan      if (GET_CODE (operands[0]) != REG)
287959693Selan        operands[0] = adj_offsettable_operand (operands[0], 2);
288059693Selan      operands[2] = gen_rtx (CONST_INT, VOIDmode,
288159693Selan			     INTVAL (operands[2]) & 0xffff);
288259693Selan      /* Do not delete a following tstl %0 insn; that would be incorrect.  */
288359693Selan      CC_STATUS_INIT;
288459693Selan      if (operands[2] == const0_rtx)
288559693Selan        return \"clr%.w %0\";
288659693Selan      return \"and%.w %2,%0\";
288759693Selan    }
288859693Selan  if (GET_CODE (operands[2]) == CONST_INT
288959693Selan      && (logval = exact_log2 (~ INTVAL (operands[2]))) >= 0
289059693Selan      && (DATA_REG_P (operands[0])
289159693Selan          || offsettable_memref_p (operands[0])))
289259693Selan    {
289359693Selan      if (DATA_REG_P (operands[0]))
289459693Selan        {
289559693Selan          operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
289659693Selan        }
289759693Selan      else
289859693Selan        {
289959693Selan          operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));          operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8);
290059693Selan        }
290159693Selan      /* This does not set condition codes in a standard way.  */
290259693Selan      CC_STATUS_INIT;
290359693Selan      return \"bclr %1,%0\";
290459693Selan    }
290559693Selan  return \"and%.l %2,%0\";
290659693Selan}")
290759693Selan
290859693Selan(define_insn "andhi3"
290959693Selan  [(set (match_operand:HI 0 "general_operand" "=m,d")
291059693Selan	(and:HI (match_operand:HI 1 "general_operand" "%0,0")
291159693Selan		(match_operand:HI 2 "general_operand" "dn,dmn")))]
291259693Selan  ""
291359693Selan  "and%.w %2,%0")
291459693Selan
291559693Selan(define_insn ""
291659693Selan  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
291759693Selan	(and:HI (match_dup 0)
291859693Selan		(match_operand:HI 1 "general_operand" "dn,dmn")))]
291959693Selan  ""
292059693Selan  "and%.w %1,%0")
292159693Selan
292259693Selan(define_insn ""
292359693Selan  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
292459693Selan	(and:HI (match_operand:HI 1 "general_operand" "dn,dmn")
292559693Selan		(match_dup 0)))]
292659693Selan  ""
292759693Selan  "and%.w %1,%0")
292859693Selan
292959693Selan(define_insn "andqi3"
293059693Selan  [(set (match_operand:QI 0 "general_operand" "=m,d")
293159693Selan	(and:QI (match_operand:QI 1 "general_operand" "%0,0")
293259693Selan		(match_operand:QI 2 "general_operand" "dn,dmn")))]
293359693Selan  ""
293459693Selan  "and%.b %2,%0")
293559693Selan
293659693Selan(define_insn ""
293759693Selan  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
293859693Selan	(and:QI (match_dup 0)
293959693Selan		(match_operand:QI 1 "general_operand" "dn,dmn")))]
294059693Selan  ""
294159693Selan  "and%.b %1,%0")
294259693Selan
294359693Selan(define_insn ""
294459693Selan  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
294559693Selan	(and:QI (match_operand:QI 1 "general_operand" "dn,dmn")
294659693Selan		(match_dup 0)))]
294759693Selan  ""
294859693Selan  "and%.b %1,%0")
294959693Selan
295059693Selan;; inclusive-or instructions
295159693Selan
295259693Selan(define_insn "iorsi3"
295359693Selan  [(set (match_operand:SI 0 "general_operand" "=m,d")
295459693Selan	(ior:SI (match_operand:SI 1 "general_operand" "%0,0")
295559693Selan		(match_operand:SI 2 "general_operand" "dKs,dmKs")))]
295659693Selan  ""
295759693Selan  "*
295859693Selan{
295959693Selan  register int logval;
296059693Selan  if (GET_CODE (operands[2]) == CONST_INT
296159693Selan      && INTVAL (operands[2]) >> 16 == 0
296259693Selan      && (DATA_REG_P (operands[0])
296359693Selan	  || offsettable_memref_p (operands[0])))
296459693Selan    {
296559693Selan      if (GET_CODE (operands[0]) != REG)
296659693Selan        operands[0] = adj_offsettable_operand (operands[0], 2);
296759693Selan      /* Do not delete a following tstl %0 insn; that would be incorrect.  */
296859693Selan      CC_STATUS_INIT;
296959693Selan      return \"or%.w %2,%0\";
297059693Selan    }
297159693Selan  if (GET_CODE (operands[2]) == CONST_INT
297259693Selan      && (logval = exact_log2 (INTVAL (operands[2]))) >= 0
297359693Selan      && (DATA_REG_P (operands[0])
297459693Selan	  || offsettable_memref_p (operands[0])))
297559693Selan    {
297659693Selan      if (DATA_REG_P (operands[0]))
297759693Selan	{
297859693Selan	  operands[1] = gen_rtx (CONST_INT, VOIDmode, logval);
297959693Selan	}
298059693Selan      else
298159693Selan        {
298259693Selan	  operands[0] = adj_offsettable_operand (operands[0], 3 - (logval / 8));
298359693Selan	  operands[1] = gen_rtx (CONST_INT, VOIDmode, logval % 8);
298459693Selan	}
298559693Selan      return \"bset %1,%0\";
298659693Selan    }
298759693Selan  return \"or%.l %2,%0\";
298859693Selan}")
298959693Selan
299059693Selan(define_insn "iorhi3"
299159693Selan  [(set (match_operand:HI 0 "general_operand" "=m,d")
299259693Selan	(ior:HI (match_operand:HI 1 "general_operand" "%0,0")
299359693Selan		(match_operand:HI 2 "general_operand" "dn,dmn")))]
299459693Selan  ""
299559693Selan  "or%.w %2,%0")
299659693Selan
299759693Selan(define_insn ""
299859693Selan  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
299959693Selan	(ior:HI (match_dup 0)
300059693Selan		(match_operand:HI 1 "general_operand" "dn,dmn")))]
300159693Selan  ""
300259693Selan  "or%.w %1,%0")
300359693Selan
300459693Selan(define_insn ""
300559693Selan  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+m,d"))
300659693Selan	(ior:HI (match_operand:HI 1 "general_operand" "dn,dmn")
300759693Selan		(match_dup 0)))]
300859693Selan  ""
300959693Selan  "or%.w %1,%0")
301059693Selan
301159693Selan(define_insn "iorqi3"
301259693Selan  [(set (match_operand:QI 0 "general_operand" "=m,d")
301359693Selan	(ior:QI (match_operand:QI 1 "general_operand" "%0,0")
301459693Selan		(match_operand:QI 2 "general_operand" "dn,dmn")))]
301559693Selan  ""
301659693Selan  "or%.b %2,%0")
301759693Selan
301859693Selan(define_insn ""
301959693Selan  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
302059693Selan	(ior:QI (match_dup 0)
302159693Selan		(match_operand:QI 1 "general_operand" "dn,dmn")))]
302259693Selan  ""
302359693Selan  "or%.b %1,%0")
302459693Selan
302559693Selan(define_insn ""
302659693Selan  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+m,d"))
302759693Selan	(ior:QI (match_operand:QI 1 "general_operand" "dn,dmn")
302859693Selan		(match_dup 0)))]
302959693Selan  ""
303059693Selan  "or%.b %1,%0")
303159693Selan
303259693Selan;; xor instructions
303359693Selan
303459693Selan(define_insn "xorsi3"
303559693Selan  [(set (match_operand:SI 0 "general_operand" "=do,m")
303659693Selan	(xor:SI (match_operand:SI 1 "general_operand" "%0,0")
303759693Selan		(match_operand:SI 2 "general_operand" "di,dKs")))]
303859693Selan  ""
303959693Selan  "*
304059693Selan{
304159693Selan  if (GET_CODE (operands[2]) == CONST_INT
304259693Selan      && INTVAL (operands[2]) >> 16 == 0
304359693Selan      && (offsettable_memref_p (operands[0]) || DATA_REG_P (operands[0])))
304459693Selan    {
304559693Selan      if (! DATA_REG_P (operands[0]))
304659693Selan	operands[0] = adj_offsettable_operand (operands[0], 2);
304759693Selan      /* Do not delete a following tstl %0 insn; that would be incorrect.  */
304859693Selan      CC_STATUS_INIT;
304959693Selan      return \"eor%.w %2,%0\";
305059693Selan    }
305159693Selan  return \"eor%.l %2,%0\";
305259693Selan}")
305359693Selan
305459693Selan(define_insn "xorhi3"
305559693Selan  [(set (match_operand:HI 0 "general_operand" "=dm")
305659693Selan	(xor:HI (match_operand:HI 1 "general_operand" "%0")
305759693Selan		(match_operand:HI 2 "general_operand" "dn")))]
305859693Selan  ""
305959693Selan  "eor%.w %2,%0")
306059693Selan
306159693Selan(define_insn ""
306259693Selan  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
306359693Selan	(xor:HI (match_dup 0)
306459693Selan		(match_operand:HI 1 "general_operand" "dn")))]
306559693Selan  ""
306659693Selan  "eor%.w %1,%0")
306759693Selan
306859693Selan
306959693Selan(define_insn ""
307059693Selan  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
307159693Selan	(xor:HI (match_operand:HI 1 "general_operand" "dn")
307259693Selan		(match_dup 0)))]
307359693Selan  ""
307459693Selan  "eor%.w %1,%0")
307559693Selan
307659693Selan(define_insn "xorqi3"
307759693Selan  [(set (match_operand:QI 0 "general_operand" "=dm")
307859693Selan	(xor:QI (match_operand:QI 1 "general_operand" "%0")
307959693Selan		(match_operand:QI 2 "general_operand" "dn")))]
308059693Selan  ""
308159693Selan  "eor%.b %2,%0")
308259693Selan
308359693Selan(define_insn ""
308459693Selan  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
308559693Selan	(xor:QI (match_dup 0)
308659693Selan		(match_operand:QI 1 "general_operand" "dn")))]
308759693Selan  ""
308859693Selan  "eor%.b %1,%0")
308959693Selan
309059693Selan(define_insn ""
309159693Selan  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
309259693Selan	(xor:QI (match_operand:QI 1 "general_operand" "dn")
309359693Selan		(match_dup 0)))]
309459693Selan  ""
309559693Selan  "eor%.b %1,%0")
309659693Selan
309759693Selan;; negation instructions
309859693Selan
309959693Selan(define_insn "negsi2"
310059693Selan  [(set (match_operand:SI 0 "general_operand" "=dm")
310159693Selan	(neg:SI (match_operand:SI 1 "general_operand" "0")))]
310259693Selan  ""
310359693Selan  "neg%.l %0")
310459693Selan
310559693Selan(define_insn "neghi2"
310659693Selan  [(set (match_operand:HI 0 "general_operand" "=dm")
310759693Selan	(neg:HI (match_operand:HI 1 "general_operand" "0")))]
310859693Selan  ""
310959693Selan  "neg%.w %0")
311059693Selan
311159693Selan(define_insn ""
311259693Selan  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
311359693Selan	(neg:HI (match_dup 0)))]
311459693Selan  ""
311559693Selan  "neg%.w %0")
311659693Selan
311759693Selan(define_insn "negqi2"
311859693Selan  [(set (match_operand:QI 0 "general_operand" "=dm")
311959693Selan	(neg:QI (match_operand:QI 1 "general_operand" "0")))]
312059693Selan  ""
312159693Selan  "neg%.b %0")
312259693Selan
312359693Selan(define_insn ""
312459693Selan  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
312559693Selan	(neg:QI (match_dup 0)))]
312659693Selan  ""
312759693Selan  "neg%.b %0")
312859693Selan
312959693Selan(define_expand "negsf2"
313059693Selan  [(set (match_operand:SF 0 "general_operand" "")
313159693Selan	(neg:SF (match_operand:SF 1 "general_operand" "")))]
313259693Selan  "TARGET_68881 || TARGET_FPA"
313359693Selan  "")
313459693Selan
313559693Selan(define_insn ""
313659693Selan  [(set (match_operand:SF 0 "general_operand" "=x,y")
313759693Selan	(neg:SF (match_operand:SF 1 "general_operand" "xH,rmF")))]
313859693Selan  "TARGET_FPA"
313959693Selan  "fpneg%.s %w1,%0")
314059693Selan
314159693Selan(define_insn ""
314259693Selan  [(set (match_operand:SF 0 "general_operand" "=f,d")
314359693Selan	(neg:SF (match_operand:SF 1 "general_operand" "fdmF,0")))]
314459693Selan  "TARGET_68881"
314559693Selan  "*
314659693Selan{
314759693Selan  if (DATA_REG_P (operands[0]))
314859693Selan    {
314959693Selan      operands[1] = gen_rtx (CONST_INT, VOIDmode, 31);
315059693Selan      return \"bchg %1,%0\";
315159693Selan    }
315259693Selan  if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
315359693Selan    return \"f%$neg%.x %1,%0\";
315459693Selan  return \"f%$neg%.s %f1,%0\";
315559693Selan}")
315659693Selan
315759693Selan(define_expand "negdf2"
315859693Selan  [(set (match_operand:DF 0 "general_operand" "")
315959693Selan	(neg:DF (match_operand:DF 1 "general_operand" "")))]
316059693Selan  "TARGET_68881 || TARGET_FPA"
316159693Selan  "")
316259693Selan
316359693Selan(define_insn ""
316459693Selan  [(set (match_operand:DF 0 "general_operand" "=x,y")
316559693Selan	(neg:DF (match_operand:DF 1 "general_operand" "xH,rmF")))]
316659693Selan  "TARGET_FPA"
316759693Selan  "fpneg%.d %y1, %0")
316859693Selan
316959693Selan(define_insn ""
317059693Selan  [(set (match_operand:DF 0 "general_operand" "=f,d")
317159693Selan	(neg:DF (match_operand:DF 1 "general_operand" "fmF,0")))]
317259693Selan  "TARGET_68881"
317359693Selan  "*
317459693Selan{
317559693Selan  if (DATA_REG_P (operands[0]))
317659693Selan    {
317759693Selan      operands[1] = gen_rtx (CONST_INT, VOIDmode, 31);
317859693Selan      return \"bchg %1,%0\";
317959693Selan    }
318059693Selan  if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
318159693Selan    return \"f%&neg%.x %1,%0\";
318259693Selan  return \"f%&neg%.d %f1,%0\";
318359693Selan}")
318459693Selan
318559693Selan;; Sqrt instruction for the 68881
318659693Selan
318759693Selan(define_insn "sqrtdf2"
318859693Selan  [(set (match_operand:DF 0 "general_operand" "=f")
318959693Selan	(sqrt:DF (match_operand:DF 1 "general_operand" "fm")))]
319059693Selan  "TARGET_68881"
319159693Selan  "*
319259693Selan{
319359693Selan  if (FP_REG_P (operands[1]))
319459693Selan    return \"fsqrt%.x %1,%0\";
319559693Selan  else
319659693Selan    return \"fsqrt%.d %1,%0\";
319759693Selan}")
319859693Selan
319959693Selan;; Absolute value instructions
320059693Selan
320159693Selan(define_expand "abssf2"
320259693Selan  [(set (match_operand:SF 0 "general_operand" "")
320359693Selan	(abs:SF (match_operand:SF 1 "general_operand" "")))]
320459693Selan  "TARGET_68881 || TARGET_FPA"
320559693Selan  "")
320659693Selan
320759693Selan(define_insn ""
320859693Selan  [(set (match_operand:SF 0 "general_operand" "=x,y")
320959693Selan	(abs:SF (match_operand:SF 1 "general_operand" "xH,rmF")))]
321059693Selan  "TARGET_FPA"
321159693Selan  "fpabs%.s %y1,%0")
321259693Selan
321359693Selan(define_insn ""
321459693Selan  [(set (match_operand:SF 0 "general_operand" "=f")
321559693Selan	(abs:SF (match_operand:SF 1 "general_operand" "fdmF")))]
321659693Selan  "TARGET_68881"
321759693Selan  "*
321859693Selan{
321959693Selan  if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
322059693Selan    return \"f%$abs%.x %1,%0\";
322159693Selan  return \"f%$abs%.s %f1,%0\";
322259693Selan}")
322359693Selan
322459693Selan(define_expand "absdf2"
322559693Selan  [(set (match_operand:DF 0 "general_operand" "")
322659693Selan	(abs:DF (match_operand:DF 1 "general_operand" "")))]
322759693Selan  "TARGET_68881 || TARGET_FPA"
322859693Selan  "")
322959693Selan
323059693Selan(define_insn ""
323159693Selan  [(set (match_operand:DF 0 "general_operand" "=x,y")
323259693Selan	(abs:DF (match_operand:DF 1 "general_operand" "xH,rmF")))]
323359693Selan  "TARGET_FPA"
323459693Selan  "fpabs%.d %y1,%0")
323559693Selan
323659693Selan(define_insn ""
323759693Selan  [(set (match_operand:DF 0 "general_operand" "=f")
323859693Selan	(abs:DF (match_operand:DF 1 "general_operand" "fmF")))]
323959693Selan  "TARGET_68881"
324059693Selan  "*
324159693Selan{
324259693Selan  if (REG_P (operands[1]) && ! DATA_REG_P (operands[1]))
324359693Selan    return \"f%&abs%.x %1,%0\";
324459693Selan  return \"f%&abs%.d %f1,%0\";
324559693Selan}")
324659693Selan
324759693Selan;; one complement instructions
324859693Selan
324959693Selan(define_insn "one_cmplsi2"
325059693Selan  [(set (match_operand:SI 0 "general_operand" "=dm")
325159693Selan	(not:SI (match_operand:SI 1 "general_operand" "0")))]
325259693Selan  ""
325359693Selan  "not%.l %0")
325459693Selan
325559693Selan(define_insn "one_cmplhi2"
325659693Selan  [(set (match_operand:HI 0 "general_operand" "=dm")
325759693Selan	(not:HI (match_operand:HI 1 "general_operand" "0")))]
325859693Selan  ""
325959693Selan  "not%.w %0")
326059693Selan
326159693Selan(define_insn ""
326259693Selan  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+dm"))
326359693Selan	(not:HI (match_dup 0)))]
326459693Selan  ""
326559693Selan  "not%.w %0")
326659693Selan
326759693Selan(define_insn "one_cmplqi2"
326859693Selan  [(set (match_operand:QI 0 "general_operand" "=dm")
326959693Selan	(not:QI (match_operand:QI 1 "general_operand" "0")))]
327059693Selan  ""
327159693Selan  "not%.b %0")
327259693Selan
327359693Selan(define_insn ""
327459693Selan  [(set (strict_low_part (match_operand:QI 0 "general_operand" "+dm"))
327559693Selan	(not:QI (match_dup 0)))]
327659693Selan  ""
327759693Selan  "not%.b %0")
327859693Selan
327959693Selan;; arithmetic shift instructions
328059693Selan;; We don't need the shift memory by 1 bit instruction
328159693Selan
328259693Selan;; On all 68k models, this makes faster code in a special case.
328359693Selan
328459693Selan(define_insn ""
328559693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
328659693Selan	(ashift:SI (match_operand:SI 1 "register_operand" "0")
328759693Selan		   (match_operand:SI 2 "immediate_operand" "i")))]
328859693Selan  "(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 16)"
328959693Selan  "*
329059693Selan{
329159693Selan  CC_STATUS_INIT;
329259693Selan  return \"swap %0\;clr%.w %0\";
329359693Selan}")
329459693Selan
329559693Selan;; On the 68000, this makes faster code in a special case.
329659693Selan
329759693Selan(define_insn ""
329859693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
329959693Selan	(ashift:SI (match_operand:SI 1 "register_operand" "0")
330059693Selan		   (match_operand:SI 2 "immediate_operand" "i")))]
330159693Selan  "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT
330259693Selan    && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)"
330359693Selan  "*
330459693Selan{
330559693Selan  CC_STATUS_INIT;
330659693Selan
330759693Selan  operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16);
330859693Selan  return \"asl%.w %2,%0\;swap %0\;clr%.w %0\";
330959693Selan}")
331059693Selan
331159693Selan(define_insn "ashlsi3"
331259693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
331359693Selan	(ashift:SI (match_operand:SI 1 "register_operand" "0")
331459693Selan		   (match_operand:SI 2 "general_operand" "dI")))]
331559693Selan  ""
331659693Selan  "*
331759693Selan{
331859693Selan  if (operands[2] == const1_rtx)
331959693Selan    return \"add%.l %0,%0\";
332059693Selan  return \"asl%.l %2,%0\";
332159693Selan}")
332259693Selan
332359693Selan(define_insn "ashlhi3"
332459693Selan  [(set (match_operand:HI 0 "register_operand" "=d")
332559693Selan	(ashift:HI (match_operand:HI 1 "register_operand" "0")
332659693Selan		   (match_operand:HI 2 "general_operand" "dI")))]
332759693Selan  ""
332859693Selan  "asl%.w %2,%0")
332959693Selan
333059693Selan(define_insn ""
333159693Selan  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
333259693Selan	(ashift:HI (match_dup 0)
333359693Selan		   (match_operand:HI 1 "general_operand" "dI")))]
333459693Selan  ""
333559693Selan  "asl%.w %1,%0")
333659693Selan
333759693Selan(define_insn "ashlqi3"
333859693Selan  [(set (match_operand:QI 0 "register_operand" "=d")
333959693Selan	(ashift:QI (match_operand:QI 1 "register_operand" "0")
334059693Selan		   (match_operand:QI 2 "general_operand" "dI")))]
334159693Selan  ""
334259693Selan  "asl%.b %2,%0")
334359693Selan
334459693Selan(define_insn ""
334559693Selan  [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
334659693Selan	(ashift:QI (match_dup 0)
334759693Selan		   (match_operand:QI 1 "general_operand" "dI")))]
334859693Selan  ""
334959693Selan  "asl%.b %1,%0")
335059693Selan
335159693Selan;; On all 68k models, this makes faster code in a special case.
335259693Selan
335359693Selan(define_insn ""
335459693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
335559693Selan	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
335659693Selan		     (match_operand:SI 2 "immediate_operand" "i")))]
335759693Selan  "(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 16)"
335859693Selan  "swap %0\;ext%.l %0")
335959693Selan
336059693Selan;; On the 68000, this makes faster code in a special case.
336159693Selan
336259693Selan(define_insn ""
336359693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
336459693Selan	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
336559693Selan		     (match_operand:SI 2 "immediate_operand" "i")))]
336659693Selan  "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT
336759693Selan    && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)"
336859693Selan  "*
336959693Selan{
337059693Selan  operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16);
337159693Selan  return \"swap %0\;asr%.w %2,%0\;ext%.l %0\";
337259693Selan}")
337359693Selan
337459693Selan(define_insn "ashrsi3"
337559693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
337659693Selan	(ashiftrt:SI (match_operand:SI 1 "register_operand" "0")
337759693Selan		     (match_operand:SI 2 "general_operand" "dI")))]
337859693Selan  ""
337959693Selan  "*
338059693Selan{
338159693Selan  return \"asr%.l %2,%0\";
338259693Selan}")
338359693Selan
338459693Selan(define_insn "ashrhi3"
338559693Selan  [(set (match_operand:HI 0 "register_operand" "=d")
338659693Selan	(ashiftrt:HI (match_operand:HI 1 "register_operand" "0")
338759693Selan		     (match_operand:HI 2 "general_operand" "dI")))]
338859693Selan  ""
338959693Selan  "asr%.w %2,%0")
339059693Selan
339159693Selan(define_insn ""
339259693Selan  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
339359693Selan	(ashiftrt:HI (match_dup 0)
339459693Selan		     (match_operand:HI 1 "general_operand" "dI")))]
339559693Selan  ""
339659693Selan  "asr%.w %1,%0")
339759693Selan
339859693Selan(define_insn "ashrqi3"
339959693Selan  [(set (match_operand:QI 0 "register_operand" "=d")
340059693Selan	(ashiftrt:QI (match_operand:QI 1 "register_operand" "0")
340159693Selan		     (match_operand:QI 2 "general_operand" "dI")))]
340259693Selan  ""
340359693Selan  "asr%.b %2,%0")
340459693Selan
340559693Selan(define_insn ""
340659693Selan  [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
340759693Selan	(ashiftrt:QI (match_dup 0)
340859693Selan		     (match_operand:QI 1 "general_operand" "dI")))]
340959693Selan  ""
341059693Selan  "asr%.b %1,%0")
341159693Selan
341259693Selan;; logical shift instructions
341359693Selan
341459693Selan;; On all 68k models, this makes faster code in a special case.
341559693Selan
341659693Selan(define_insn ""
341759693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
341859693Selan	(lshift:SI (match_operand:SI 1 "register_operand" "0")
341959693Selan		   (match_operand:SI 2 "immediate_operand" "i")))]
342059693Selan  "(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 16)"
342159693Selan  "*
342259693Selan{
342359693Selan  CC_STATUS_INIT;
342459693Selan  return \"swap %0\;clr%.w %0\";
342559693Selan}")
342659693Selan
342759693Selan;; On the 68000, this makes faster code in a special case.
342859693Selan
342959693Selan(define_insn ""
343059693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
343159693Selan	(lshift:SI (match_operand:SI 1 "register_operand" "0")
343259693Selan		   (match_operand:SI 2 "immediate_operand" "i")))]
343359693Selan  "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT
343459693Selan    && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)"
343559693Selan  "*
343659693Selan{
343759693Selan  CC_STATUS_INIT;
343859693Selan
343959693Selan  operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16);
344059693Selan  return \"lsl%.w %2,%0\;swap %0\;clr%.w %0\";
344159693Selan}")
344259693Selan
344359693Selan(define_insn "lshlsi3"
344459693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
344559693Selan	(lshift:SI (match_operand:SI 1 "register_operand" "0")
344659693Selan		   (match_operand:SI 2 "general_operand" "dI")))]
344759693Selan  ""
344859693Selan  "*
344959693Selan{
345059693Selan  if (operands[2] == const1_rtx)
345159693Selan    return \"add%.l %0,%0\";
345259693Selan  return \"lsl%.l %2,%0\";
345359693Selan}")
345459693Selan
345559693Selan(define_insn "lshlhi3"
345659693Selan  [(set (match_operand:HI 0 "register_operand" "=d")
345759693Selan	(lshift:HI (match_operand:HI 1 "register_operand" "0")
345859693Selan		   (match_operand:HI 2 "general_operand" "dI")))]
345959693Selan  ""
346059693Selan  "lsl%.w %2,%0")
346159693Selan
346259693Selan(define_insn ""
346359693Selan  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
346459693Selan	(lshift:HI (match_dup 0)
346559693Selan		   (match_operand:HI 1 "general_operand" "dI")))]
346659693Selan  ""
346759693Selan  "lsl%.w %1,%0")
346859693Selan
346959693Selan(define_insn "lshlqi3"
347059693Selan  [(set (match_operand:QI 0 "register_operand" "=d")
347159693Selan	(lshift:QI (match_operand:QI 1 "register_operand" "0")
347259693Selan		   (match_operand:QI 2 "general_operand" "dI")))]
347359693Selan  ""
347459693Selan  "lsl%.b %2,%0")
347559693Selan
347659693Selan(define_insn ""
347759693Selan  [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
347859693Selan	(lshift:QI (match_dup 0)
347959693Selan		   (match_operand:QI 1 "general_operand" "dI")))]
348059693Selan  ""
348159693Selan  "lsl%.b %1,%0")
348259693Selan
348359693Selan;; On all 68k models, this makes faster code in a special case.
348459693Selan
348559693Selan(define_insn ""
348659693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
348759693Selan	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
348859693Selan		     (match_operand:SI 2 "immediate_operand" "i")))]
348959693Selan  "(GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 16)"
349059693Selan  "*
349159693Selan{
349259693Selan  CC_STATUS_INIT;
349359693Selan  return \"clr%.w %0\;swap %0\";
349459693Selan}")
349559693Selan
349659693Selan;; On the 68000, this makes faster code in a special case.
349759693Selan
349859693Selan(define_insn ""
349959693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
350059693Selan	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
350159693Selan		     (match_operand:SI 2 "immediate_operand" "i")))]
350259693Selan  "(! TARGET_68020 && GET_CODE (operands[2]) == CONST_INT
350359693Selan    && INTVAL (operands[2]) > 16 && INTVAL (operands[2]) <= 24)"
350459693Selan  "*
350559693Selan{
350659693Selan  /* I think lsr%.w sets the CC properly.  */
350759693Selan  operands[2] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[2]) - 16);
350859693Selan  return \"clr%.w %0\;swap %0\;lsr%.w %2,%0\";
350959693Selan}")
351059693Selan
351159693Selan(define_insn "lshrsi3"
351259693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
351359693Selan	(lshiftrt:SI (match_operand:SI 1 "register_operand" "0")
351459693Selan		     (match_operand:SI 2 "general_operand" "dI")))]
351559693Selan  ""
351659693Selan  "*
351759693Selan{
351859693Selan  return \"lsr%.l %2,%0\";
351959693Selan}")
352059693Selan
352159693Selan(define_insn "lshrhi3"
352259693Selan  [(set (match_operand:HI 0 "register_operand" "=d")
352359693Selan	(lshiftrt:HI (match_operand:HI 1 "register_operand" "0")
352459693Selan		     (match_operand:HI 2 "general_operand" "dI")))]
352559693Selan  ""
352659693Selan  "lsr%.w %2,%0")
352759693Selan
352859693Selan(define_insn ""
352959693Selan  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
353059693Selan	(lshiftrt:HI (match_dup 0)
353159693Selan		     (match_operand:HI 1 "general_operand" "dI")))]
353259693Selan  ""
353359693Selan  "lsr%.w %1,%0")
353459693Selan
353559693Selan(define_insn "lshrqi3"
353659693Selan  [(set (match_operand:QI 0 "register_operand" "=d")
353759693Selan	(lshiftrt:QI (match_operand:QI 1 "register_operand" "0")
353859693Selan		     (match_operand:QI 2 "general_operand" "dI")))]
353959693Selan  ""
354059693Selan  "lsr%.b %2,%0")
354159693Selan
354259693Selan(define_insn ""
354359693Selan  [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
354459693Selan	(lshiftrt:QI (match_dup 0)
354559693Selan		     (match_operand:QI 1 "general_operand" "dI")))]
354659693Selan  ""
354759693Selan  "lsr%.b %1,%0")
354859693Selan
354959693Selan;; rotate instructions
355059693Selan
355159693Selan(define_insn "rotlsi3"
355259693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
355359693Selan	(rotate:SI (match_operand:SI 1 "register_operand" "0")
355459693Selan		   (match_operand:SI 2 "general_operand" "dI")))]
355559693Selan  ""
355659693Selan  "rol%.l %2,%0")
355759693Selan
355859693Selan(define_insn "rotlhi3"
355959693Selan  [(set (match_operand:HI 0 "register_operand" "=d")
356059693Selan	(rotate:HI (match_operand:HI 1 "register_operand" "0")
356159693Selan		   (match_operand:HI 2 "general_operand" "dI")))]
356259693Selan  ""
356359693Selan  "rol%.w %2,%0")
356459693Selan
356559693Selan
356659693Selan(define_insn ""
356759693Selan  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
356859693Selan	(rotate:HI (match_dup 0)
356959693Selan		   (match_operand:HI 1 "general_operand" "dI")))]
357059693Selan  ""
357159693Selan  "rol%.w %1,%0")
357259693Selan
357359693Selan(define_insn "rotlqi3"
357459693Selan  [(set (match_operand:QI 0 "register_operand" "=d")
357559693Selan	(rotate:QI (match_operand:QI 1 "register_operand" "0")
357659693Selan		   (match_operand:QI 2 "general_operand" "dI")))]
357759693Selan  ""
357859693Selan  "rol%.b %2,%0")
357959693Selan
358059693Selan(define_insn ""
358159693Selan  [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
358259693Selan	(rotate:QI (match_dup 0)
358359693Selan		   (match_operand:QI 1 "general_operand" "dI")))]
358459693Selan  ""
358559693Selan  "rol%.b %1,%0")
358659693Selan
358759693Selan(define_insn "rotrsi3"
358859693Selan  [(set (match_operand:SI 0 "register_operand" "=d")
358959693Selan	(rotatert:SI (match_operand:SI 1 "register_operand" "0")
359059693Selan		     (match_operand:SI 2 "general_operand" "dI")))]
359159693Selan  ""
359259693Selan  "ror%.l %2,%0")
359359693Selan
359459693Selan(define_insn "rotrhi3"
359559693Selan  [(set (match_operand:HI 0 "register_operand" "=d")
359659693Selan	(rotatert:HI (match_operand:HI 1 "register_operand" "0")
359759693Selan		     (match_operand:HI 2 "general_operand" "dI")))]
359859693Selan  ""
359959693Selan  "ror%.w %2,%0")
360059693Selan
360159693Selan(define_insn ""
360259693Selan  [(set (strict_low_part (match_operand:HI 0 "register_operand" "+d"))
360359693Selan	(rotatert:HI (match_dup 0)
360459693Selan		     (match_operand:HI 1 "general_operand" "dI")))]
360559693Selan  ""
360659693Selan  "ror%.w %1,%0")
360759693Selan
360859693Selan(define_insn "rotrqi3"
360959693Selan  [(set (match_operand:QI 0 "register_operand" "=d")
361059693Selan	(rotatert:QI (match_operand:QI 1 "register_operand" "0")
361159693Selan		     (match_operand:QI 2 "general_operand" "dI")))]
361259693Selan  ""
361359693Selan  "ror%.b %2,%0")
361459693Selan
361559693Selan(define_insn ""
361659693Selan  [(set (strict_low_part (match_operand:QI 0 "register_operand" "+d"))
361759693Selan	(rotatert:QI (match_dup 0)
361859693Selan		     (match_operand:QI 1 "general_operand" "dI")))]
361959693Selan  ""
362059693Selan  "ror%.b %1,%0")
362159693Selan
362259693Selan;; Special cases of bit-field insns which we should
362359693Selan;; recognize in preference to the general case.
362459693Selan;; These handle aligned 8-bit and 16-bit fields,
362559693Selan;; which can usually be done with move instructions.
362659693Selan
362759693Selan;
362859693Selan; Special case for 32-bit field in memory.  This only occurs when 32-bit
362959693Selan; alignment of structure members is specified.
363059693Selan;
363159693Selan; The move is allowed to be odd byte aligned, because that's still faster
363259693Selan; than an odd byte aligned bit field instruction.
363359693Selan;
363459693Selan(define_insn ""
363559693Selan  [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o")
363659693Selan			 (match_operand:SI 1 "immediate_operand" "i")
363759693Selan			 (match_operand:SI 2 "immediate_operand" "i"))
363859693Selan	(match_operand:SI 3 "general_operand" "rmi"))]
363959693Selan  "TARGET_68020 && TARGET_BITFIELD
364059693Selan   && GET_CODE (operands[1]) == CONST_INT
364159693Selan   && (INTVAL (operands[1]) == 32)
364259693Selan   && GET_CODE (operands[2]) == CONST_INT
364359693Selan   && (INTVAL (operands[2]) % 8) == 0
364459693Selan   && ! mode_dependent_address_p (XEXP (operands[0], 0))"
364559693Selan  "*
364659693Selan{
364759693Selan  operands[0]
364859693Selan    = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8);
364959693Selan
365059693Selan  return \"move%.l %3,%0\";
365159693Selan}")
365259693Selan
365359693Selan(define_insn ""
365459693Selan  [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+do")
365559693Selan			 (match_operand:SI 1 "immediate_operand" "i")
365659693Selan			 (match_operand:SI 2 "immediate_operand" "i"))
365759693Selan	(match_operand:SI 3 "general_operand" "d"))]
365859693Selan  "TARGET_68020 && TARGET_BITFIELD
365959693Selan   && GET_CODE (operands[1]) == CONST_INT
366059693Selan   && (INTVAL (operands[1]) == 8 || INTVAL (operands[1]) == 16)
366159693Selan   && GET_CODE (operands[2]) == CONST_INT
366259693Selan   && INTVAL (operands[2]) % INTVAL (operands[1]) == 0
366359693Selan   && (GET_CODE (operands[0]) == REG
366459693Selan       || ! mode_dependent_address_p (XEXP (operands[0], 0)))"
366559693Selan  "*
366659693Selan{
366759693Selan  if (REG_P (operands[0]))
366859693Selan    {
366959693Selan      if (INTVAL (operands[1]) + INTVAL (operands[2]) != 32)
367059693Selan        return \"bfins %3,%0{%b2:%b1}\";
367159693Selan    }
367259693Selan  else
367359693Selan    operands[0]
367459693Selan      = adj_offsettable_operand (operands[0], INTVAL (operands[2]) / 8);
367559693Selan
367659693Selan  if (GET_CODE (operands[3]) == MEM)
367759693Selan    operands[3] = adj_offsettable_operand (operands[3],
367859693Selan					   (32 - INTVAL (operands[1])) / 8);
367959693Selan  if (INTVAL (operands[1]) == 8)
368059693Selan    return \"move%.b %3,%0\";
368159693Selan  return \"move%.w %3,%0\";
368259693Selan}")
368359693Selan
368459693Selan
368559693Selan;
368659693Selan; Special case for 32-bit field in memory.  This only occurs when 32-bit
368759693Selan; alignment of structure members is specified.
368859693Selan;
368959693Selan; The move is allowed to be odd byte aligned, because that's still faster
369059693Selan; than an odd byte aligned bit field instruction.
369159693Selan;
369259693Selan(define_insn ""
369359693Selan  [(set (match_operand:SI 0 "general_operand" "=rm")
369459693Selan	(zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o")
369559693Selan			 (match_operand:SI 2 "immediate_operand" "i")
369659693Selan			 (match_operand:SI 3 "immediate_operand" "i")))]
369759693Selan  "TARGET_68020 && TARGET_BITFIELD
369859693Selan   && GET_CODE (operands[2]) == CONST_INT
369959693Selan   && (INTVAL (operands[2]) == 32)
370059693Selan   && GET_CODE (operands[3]) == CONST_INT
370159693Selan   && (INTVAL (operands[3]) % 8) == 0
370259693Selan   && ! mode_dependent_address_p (XEXP (operands[1], 0))"
370359693Selan  "*
370459693Selan{
370559693Selan  operands[1]
370659693Selan    = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
370759693Selan
370859693Selan  return \"move%.l %1,%0\";
370959693Selan}")
371059693Selan
371159693Selan(define_insn ""
371259693Selan  [(set (match_operand:SI 0 "general_operand" "=&d")
371359693Selan	(zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do")
371459693Selan			 (match_operand:SI 2 "immediate_operand" "i")
371559693Selan			 (match_operand:SI 3 "immediate_operand" "i")))]
371659693Selan  "TARGET_68020 && TARGET_BITFIELD
371759693Selan   && GET_CODE (operands[2]) == CONST_INT
371859693Selan   && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
371959693Selan   && GET_CODE (operands[3]) == CONST_INT
372059693Selan   && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
372159693Selan   && (GET_CODE (operands[1]) == REG
372259693Selan       || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
372359693Selan  "*
372459693Selan{
372559693Selan  cc_status.flags |= CC_NOT_NEGATIVE;
372659693Selan  if (REG_P (operands[1]))
372759693Selan    {
372859693Selan      if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
372959693Selan	return \"bfextu %1{%b3:%b2},%0\";
373059693Selan    }
373159693Selan  else
373259693Selan    operands[1]
373359693Selan      = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
373459693Selan
373559693Selan  output_asm_insn (\"clr%.l %0\", operands);
373659693Selan  if (GET_CODE (operands[0]) == MEM)
373759693Selan    operands[0] = adj_offsettable_operand (operands[0],
373859693Selan					   (32 - INTVAL (operands[1])) / 8);
373959693Selan  if (INTVAL (operands[2]) == 8)
374059693Selan    return \"move%.b %1,%0\";
374159693Selan  return \"move%.w %1,%0\";
374259693Selan}")
374359693Selan
374459693Selan;
374559693Selan; Special case for 32-bit field in memory.  This only occurs when 32-bit
374659693Selan; alignment of structure members is specified.
374759693Selan;
374859693Selan; The move is allowed to be odd byte aligned, because that's still faster
374959693Selan; than an odd byte aligned bit field instruction.
375059693Selan;
375159693Selan(define_insn ""
375259693Selan  [(set (match_operand:SI 0 "general_operand" "=rm")
375359693Selan	(sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o")
375459693Selan			 (match_operand:SI 2 "immediate_operand" "i")
375559693Selan			 (match_operand:SI 3 "immediate_operand" "i")))]
375659693Selan  "TARGET_68020 && TARGET_BITFIELD
375759693Selan   && GET_CODE (operands[2]) == CONST_INT
375859693Selan   && (INTVAL (operands[2]) == 32)
375959693Selan   && GET_CODE (operands[3]) == CONST_INT
376059693Selan   && (INTVAL (operands[3]) % 8) == 0
376159693Selan   && ! mode_dependent_address_p (XEXP (operands[1], 0))"
376259693Selan  "*
376359693Selan{
376459693Selan  operands[1]
376559693Selan    = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
376659693Selan
376759693Selan  return \"move%.l %1,%0\";
376859693Selan}")
376959693Selan
377059693Selan(define_insn ""
377159693Selan  [(set (match_operand:SI 0 "general_operand" "=d")
377259693Selan	(sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "do")
377359693Selan			 (match_operand:SI 2 "immediate_operand" "i")
377459693Selan			 (match_operand:SI 3 "immediate_operand" "i")))]
377559693Selan  "TARGET_68020 && TARGET_BITFIELD
377659693Selan   && GET_CODE (operands[2]) == CONST_INT
377759693Selan   && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 16)
377859693Selan   && GET_CODE (operands[3]) == CONST_INT
377959693Selan   && INTVAL (operands[3]) % INTVAL (operands[2]) == 0
378059693Selan   && (GET_CODE (operands[1]) == REG
378159693Selan       || ! mode_dependent_address_p (XEXP (operands[1], 0)))"
378259693Selan  "*
378359693Selan{
378459693Selan  if (REG_P (operands[1]))
378559693Selan    {
378659693Selan      if (INTVAL (operands[2]) + INTVAL (operands[3]) != 32)
378759693Selan	return \"bfexts %1{%b3:%b2},%0\";
378859693Selan    }
378959693Selan  else
379059693Selan    operands[1]
379159693Selan      = adj_offsettable_operand (operands[1], INTVAL (operands[3]) / 8);
379259693Selan
379359693Selan  if (INTVAL (operands[2]) == 8)
379459693Selan    return \"move%.b %1,%0\;extb%.l %0\";
379559693Selan  return \"move%.w %1,%0\;ext%.l %0\";
379659693Selan}")
379759693Selan
379859693Selan;; Bit field instructions, general cases.
379959693Selan;; "o,d" constraint causes a nonoffsettable memref to match the "o"
380059693Selan;; so that its address is reloaded.
380159693Selan
380259693Selan(define_insn "extv"
380359693Selan  [(set (match_operand:SI 0 "general_operand" "=d,d")
380459693Selan	(sign_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o,d")
380559693Selan			 (match_operand:SI 2 "general_operand" "di,di")
380659693Selan			 (match_operand:SI 3 "general_operand" "di,di")))]
380759693Selan  "TARGET_68020 && TARGET_BITFIELD"
380859693Selan  "bfexts %1{%b3:%b2},%0")
380959693Selan
381059693Selan(define_insn "extzv"
381159693Selan  [(set (match_operand:SI 0 "general_operand" "=d,d")
381259693Selan	(zero_extract:SI (match_operand:QI 1 "nonimmediate_operand" "o,d")
381359693Selan			 (match_operand:SI 2 "general_operand" "di,di")
381459693Selan			 (match_operand:SI 3 "general_operand" "di,di")))]
381559693Selan  "TARGET_68020 && TARGET_BITFIELD"
381659693Selan  "*
381759693Selan{
381859693Selan  cc_status.flags |= CC_NOT_NEGATIVE;
381959693Selan  return \"bfextu %1{%b3:%b2},%0\";
382059693Selan}")
382159693Selan
382259693Selan(define_insn ""
382359693Selan  [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
382459693Selan			 (match_operand:SI 1 "general_operand" "di,di")
382559693Selan			 (match_operand:SI 2 "general_operand" "di,di"))
382659693Selan        (xor:SI (zero_extract:SI (match_dup 0) (match_dup 1) (match_dup 2))
382759693Selan		(match_operand 3 "immediate_operand" "i,i")))]
382859693Selan  "TARGET_68020 && TARGET_BITFIELD
382959693Selan   && GET_CODE (operands[3]) == CONST_INT
383059693Selan   && (INTVAL (operands[3]) == -1
383159693Selan       || (GET_CODE (operands[1]) == CONST_INT
383259693Selan           && (~ INTVAL (operands[3]) & ((1 << INTVAL (operands[1]))- 1)) == 0))"
383359693Selan  "*
383459693Selan{
383559693Selan  CC_STATUS_INIT;
383659693Selan  return \"bfchg %0{%b2:%b1}\";
383759693Selan}")
383859693Selan
383959693Selan(define_insn ""
384059693Selan  [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
384159693Selan			 (match_operand:SI 1 "general_operand" "di,di")
384259693Selan			 (match_operand:SI 2 "general_operand" "di,di"))
384359693Selan	(const_int 0))]
384459693Selan  "TARGET_68020 && TARGET_BITFIELD"
384559693Selan  "*
384659693Selan{
384759693Selan  CC_STATUS_INIT;
384859693Selan  return \"bfclr %0{%b2:%b1}\";
384959693Selan}")
385059693Selan
385159693Selan(define_insn ""
385259693Selan  [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
385359693Selan			 (match_operand:SI 1 "general_operand" "di,di")
385459693Selan			 (match_operand:SI 2 "general_operand" "di,di"))
385559693Selan	(const_int -1))]
385659693Selan  "TARGET_68020 && TARGET_BITFIELD"
385759693Selan  "*
385859693Selan{
385959693Selan  CC_STATUS_INIT;
386059693Selan  return \"bfset %0{%b2:%b1}\";
386159693Selan}")
386259693Selan
386359693Selan(define_insn "insv"
386459693Selan  [(set (zero_extract:SI (match_operand:QI 0 "nonimmediate_operand" "+o,d")
386559693Selan			 (match_operand:SI 1 "general_operand" "di,di")
386659693Selan			 (match_operand:SI 2 "general_operand" "di,di"))
386759693Selan	(match_operand:SI 3 "general_operand" "d,d"))]
386859693Selan  "TARGET_68020 && TARGET_BITFIELD"
386959693Selan  "bfins %3,%0{%b2:%b1}")
387059693Selan
387159693Selan;; Now recognize bit field insns that operate on registers
387259693Selan;; (or at least were intended to do so).
387359693Selan
387459693Selan(define_insn ""
387559693Selan  [(set (match_operand:SI 0 "general_operand" "=d")
387659693Selan	(sign_extract:SI (match_operand:SI 1 "nonimmediate_operand" "d")
387759693Selan			 (match_operand:SI 2 "general_operand" "di")
387859693Selan			 (match_operand:SI 3 "general_operand" "di")))]
387959693Selan  "TARGET_68020 && TARGET_BITFIELD"
388059693Selan  "bfexts %1{%b3:%b2},%0")
388159693Selan
388259693Selan(define_insn ""
388359693Selan  [(set (match_operand:SI 0 "general_operand" "=d")
388459693Selan	(zero_extract:SI (match_operand:SI 1 "nonimmediate_operand" "d")
388559693Selan			 (match_operand:SI 2 "general_operand" "di")
388659693Selan			 (match_operand:SI 3 "general_operand" "di")))]
388759693Selan  "TARGET_68020 && TARGET_BITFIELD"
388859693Selan  "*
388959693Selan{
389059693Selan  cc_status.flags |= CC_NOT_NEGATIVE;
389159693Selan  return \"bfextu %1{%b3:%b2},%0\";
389259693Selan}")
389359693Selan
389459693Selan(define_insn ""
389559693Selan  [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
389659693Selan			 (match_operand:SI 1 "general_operand" "di")
389759693Selan			 (match_operand:SI 2 "general_operand" "di"))
389859693Selan	(const_int 0))]
389959693Selan  "TARGET_68020 && TARGET_BITFIELD"
390059693Selan  "*
390159693Selan{
390259693Selan  CC_STATUS_INIT;
390359693Selan  return \"bfclr %0{%b2:%b1}\";
390459693Selan}")
390559693Selan
390659693Selan(define_insn ""
390759693Selan  [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
390859693Selan			 (match_operand:SI 1 "general_operand" "di")
390959693Selan			 (match_operand:SI 2 "general_operand" "di"))
391059693Selan	(const_int -1))]
391159693Selan  "TARGET_68020 && TARGET_BITFIELD"
391259693Selan  "*
391359693Selan{
391459693Selan  CC_STATUS_INIT;
391559693Selan  return \"bfset %0{%b2:%b1}\";
391659693Selan}")
391759693Selan
391859693Selan(define_insn ""
391959693Selan  [(set (zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "+d")
392059693Selan			 (match_operand:SI 1 "general_operand" "di")
392159693Selan			 (match_operand:SI 2 "general_operand" "di"))
392259693Selan	(match_operand:SI 3 "general_operand" "d"))]
392359693Selan  "TARGET_68020 && TARGET_BITFIELD"
392459693Selan  "*
392559693Selan{
392659693Selan#if 0
392759693Selan  /* These special cases are now recognized by a specific pattern.  */
392859693Selan  if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (operands[2]) == CONST_INT
392959693Selan      && INTVAL (operands[1]) == 16 && INTVAL (operands[2]) == 16)
393059693Selan    return \"move%.w %3,%0\";
393159693Selan  if (GET_CODE (operands[1]) == CONST_INT && GET_CODE (operands[2]) == CONST_INT
393259693Selan      && INTVAL (operands[1]) == 24 && INTVAL (operands[2]) == 8)
393359693Selan    return \"move%.b %3,%0\";
393459693Selan#endif
393559693Selan  return \"bfins %3,%0{%b2:%b1}\";
393659693Selan}")
393759693Selan
393859693Selan;; Special patterns for optimizing bit-field instructions.
393959693Selan
394059693Selan(define_insn ""
394159693Selan  [(set (cc0)
394259693Selan	(zero_extract:SI (match_operand:QI 0 "memory_operand" "o")
394359693Selan			 (match_operand:SI 1 "general_operand" "di")
394459693Selan			 (match_operand:SI 2 "general_operand" "di")))]
394559693Selan  "TARGET_68020 && TARGET_BITFIELD
394659693Selan   && GET_CODE (operands[1]) == CONST_INT"
394759693Selan  "*
394859693Selan{
394959693Selan  if (operands[1] == const1_rtx
395059693Selan      && GET_CODE (operands[2]) == CONST_INT)
395159693Selan    {
395259693Selan      int width = GET_CODE (operands[0]) == REG ? 31 : 7;
395359693Selan      return output_btst (operands,
395459693Selan			  gen_rtx (CONST_INT, VOIDmode,
395559693Selan				   width - INTVAL (operands[2])),
395659693Selan			  operands[0],
395759693Selan			  insn, 1000);
395859693Selan      /* Pass 1000 as SIGNPOS argument so that btst will
395959693Selan         not think we are testing the sign bit for an `and'
396059693Selan	 and assume that nonzero implies a negative result.  */
396159693Selan    }
396259693Selan  if (INTVAL (operands[1]) != 32)
396359693Selan    cc_status.flags = CC_NOT_NEGATIVE;
396459693Selan  return \"bftst %0{%b2:%b1}\";
396559693Selan}")
396659693Selan
396759693Selan
396859693Selan;;; now handle the register cases
396959693Selan(define_insn ""
397059693Selan  [(set (cc0)
397159693Selan	(zero_extract:SI (match_operand:SI 0 "nonimmediate_operand" "d")
397259693Selan			 (match_operand:SI 1 "general_operand" "di")
397359693Selan			 (match_operand:SI 2 "general_operand" "di")))]
397459693Selan  "TARGET_68020 && TARGET_BITFIELD
397559693Selan   && GET_CODE (operands[1]) == CONST_INT"
397659693Selan  "*
397759693Selan{
397859693Selan  if (operands[1] == const1_rtx
397959693Selan      && GET_CODE (operands[2]) == CONST_INT)
398059693Selan    {
398159693Selan      int width = GET_CODE (operands[0]) == REG ? 31 : 7;
398259693Selan      return output_btst (operands,
398359693Selan			  gen_rtx (CONST_INT, VOIDmode,
398459693Selan				   width - INTVAL (operands[2])),
398559693Selan			  operands[0],
398659693Selan			  insn, 1000);
398759693Selan      /* Pass 1000 as SIGNPOS argument so that btst will
398859693Selan         not think we are testing the sign bit for an `and'
398959693Selan	 and assume that nonzero implies a negative result.  */
399059693Selan    }
399159693Selan  if (INTVAL (operands[1]) != 32)
399259693Selan    cc_status.flags = CC_NOT_NEGATIVE;
399359693Selan  return \"bftst %0{%b2:%b1}\";
399459693Selan}")
399559693Selan
399659693Selan(define_insn "seq"
399759693Selan  [(set (match_operand:QI 0 "general_operand" "=d")
399859693Selan	(eq:QI (cc0) (const_int 0)))]
399959693Selan  ""
400059693Selan  "*
400159693Selan  cc_status = cc_prev_status;
400259693Selan  OUTPUT_JUMP (\"seq %0\", \"fseq %0\", \"seq %0\");
400359693Selan")
400459693Selan
400559693Selan(define_insn "sne"
400659693Selan  [(set (match_operand:QI 0 "general_operand" "=d")
400759693Selan	(ne:QI (cc0) (const_int 0)))]
400859693Selan  ""
400959693Selan  "*
401059693Selan  cc_status = cc_prev_status;
401159693Selan  OUTPUT_JUMP (\"sne %0\", \"fsne %0\", \"sne %0\");
401259693Selan")
401359693Selan
401459693Selan(define_insn "sgt"
401559693Selan  [(set (match_operand:QI 0 "general_operand" "=d")
401659693Selan	(gt:QI (cc0) (const_int 0)))]
401759693Selan  ""
401859693Selan  "*
401959693Selan  cc_status = cc_prev_status;
402059693Selan  OUTPUT_JUMP (\"sgt %0\", \"fsgt %0\", 0);
402159693Selan")
402259693Selan
402359693Selan(define_insn "sgtu"
402459693Selan  [(set (match_operand:QI 0 "general_operand" "=d")
402559693Selan	(gtu:QI (cc0) (const_int 0)))]
402659693Selan  ""
402759693Selan  "* cc_status = cc_prev_status;
402859693Selan     return \"shi %0\"; ")
402959693Selan
403059693Selan(define_insn "slt"
403159693Selan  [(set (match_operand:QI 0 "general_operand" "=d")
403259693Selan	(lt:QI (cc0) (const_int 0)))]
403359693Selan  ""
403459693Selan  "* cc_status = cc_prev_status;
403559693Selan     OUTPUT_JUMP (\"slt %0\", \"fslt %0\", \"smi %0\"); ")
403659693Selan
403759693Selan(define_insn "sltu"
403859693Selan  [(set (match_operand:QI 0 "general_operand" "=d")
403959693Selan	(ltu:QI (cc0) (const_int 0)))]
404059693Selan  ""
404159693Selan  "* cc_status = cc_prev_status;
404259693Selan     return \"scs %0\"; ")
404359693Selan
404459693Selan(define_insn "sge"
404559693Selan  [(set (match_operand:QI 0 "general_operand" "=d")
404659693Selan	(ge:QI (cc0) (const_int 0)))]
404759693Selan  ""
404859693Selan  "* cc_status = cc_prev_status;
404959693Selan     OUTPUT_JUMP (\"sge %0\", \"fsge %0\", \"spl %0\"); ")
405059693Selan
405159693Selan(define_insn "sgeu"
405259693Selan  [(set (match_operand:QI 0 "general_operand" "=d")
405359693Selan	(geu:QI (cc0) (const_int 0)))]
405459693Selan  ""
405559693Selan  "* cc_status = cc_prev_status;
405659693Selan     return \"scc %0\"; ")
405759693Selan
405859693Selan(define_insn "sle"
405959693Selan  [(set (match_operand:QI 0 "general_operand" "=d")
406059693Selan	(le:QI (cc0) (const_int 0)))]
406159693Selan  ""
406259693Selan  "*
406359693Selan  cc_status = cc_prev_status;
406459693Selan  OUTPUT_JUMP (\"sle %0\", \"fsle %0\", 0);
406559693Selan")
406659693Selan
406759693Selan(define_insn "sleu"
406859693Selan  [(set (match_operand:QI 0 "general_operand" "=d")
406959693Selan	(leu:QI (cc0) (const_int 0)))]
407059693Selan  ""
407159693Selan  "* cc_status = cc_prev_status;
407259693Selan     return \"sls %0\"; ")
407359693Selan
407459693Selan;; Basic conditional jump instructions.
407559693Selan
407659693Selan(define_insn "beq"
407759693Selan  [(set (pc)
407859693Selan	(if_then_else (eq (cc0)
407959693Selan			  (const_int 0))
408059693Selan		      (label_ref (match_operand 0 "" ""))
408159693Selan		      (pc)))]
408259693Selan  ""
408359693Selan  "*
408459693Selan{
408559693Selan#ifdef MOTOROLA
408659693Selan  OUTPUT_JUMP (\"jbeq %l0\", \"fbeq %l0\", \"jbeq %l0\");
408759693Selan#else
408859693Selan  OUTPUT_JUMP (\"jeq %l0\", \"fjeq %l0\", \"jeq %l0\");
408959693Selan#endif
409059693Selan}")
409159693Selan
409259693Selan(define_insn "bne"
409359693Selan  [(set (pc)
409459693Selan	(if_then_else (ne (cc0)
409559693Selan			  (const_int 0))
409659693Selan		      (label_ref (match_operand 0 "" ""))
409759693Selan		      (pc)))]
409859693Selan  ""
409959693Selan  "*
410059693Selan{
410159693Selan#ifdef MOTOROLA
410259693Selan  OUTPUT_JUMP (\"jbne %l0\", \"fbne %l0\", \"jbne %l0\");
410359693Selan#else
410459693Selan  OUTPUT_JUMP (\"jne %l0\", \"fjne %l0\", \"jne %l0\");
410559693Selan#endif
410659693Selan}")
410759693Selan
410859693Selan(define_insn "bgt"
410959693Selan  [(set (pc)
411059693Selan	(if_then_else (gt (cc0)
411159693Selan			  (const_int 0))
411259693Selan		      (label_ref (match_operand 0 "" ""))
411359693Selan		      (pc)))]
411459693Selan  ""
411559693Selan  "*
411659693Selan#ifdef MOTOROLA
411759693Selan  OUTPUT_JUMP (\"jbgt %l0\", \"fbgt %l0\", 0);
411859693Selan#else
411959693Selan  OUTPUT_JUMP (\"jgt %l0\", \"fjgt %l0\", 0);
412059693Selan#endif
412159693Selan")
412259693Selan
412359693Selan(define_insn "bgtu"
412459693Selan  [(set (pc)
412559693Selan	(if_then_else (gtu (cc0)
412659693Selan			   (const_int 0))
412759693Selan		      (label_ref (match_operand 0 "" ""))
412859693Selan		      (pc)))]
412959693Selan  ""
413059693Selan  "*
413159693Selan#ifdef MOTOROLA
413259693Selan  return \"jbhi %l0\";
413359693Selan#else
413459693Selan  return \"jhi %l0\";
413559693Selan#endif
413659693Selan")
413759693Selan
413859693Selan(define_insn "blt"
413959693Selan  [(set (pc)
414059693Selan	(if_then_else (lt (cc0)
414159693Selan			  (const_int 0))
414259693Selan		      (label_ref (match_operand 0 "" ""))
414359693Selan		      (pc)))]
414459693Selan  ""
414559693Selan  "*
414659693Selan#ifdef MOTOROLA
414759693Selan  OUTPUT_JUMP (\"jblt %l0\", \"fblt %l0\", \"jbmi %l0\");
414859693Selan#else
414959693Selan  OUTPUT_JUMP (\"jlt %l0\", \"fjlt %l0\", \"jmi %l0\");
415059693Selan#endif
415159693Selan")
415259693Selan
415359693Selan(define_insn "bltu"
415459693Selan  [(set (pc)
415559693Selan	(if_then_else (ltu (cc0)
415659693Selan			   (const_int 0))
415759693Selan		      (label_ref (match_operand 0 "" ""))
415859693Selan		      (pc)))]
415959693Selan  ""
416059693Selan  "*
416159693Selan#ifdef MOTOROLA
416259693Selan  return \"jbcs %l0\";
416359693Selan#else
416459693Selan  return \"jcs %l0\";
416559693Selan#endif
416659693Selan")
416759693Selan
416859693Selan(define_insn "bge"
416959693Selan  [(set (pc)
417059693Selan	(if_then_else (ge (cc0)
417159693Selan			  (const_int 0))
417259693Selan		      (label_ref (match_operand 0 "" ""))
417359693Selan		      (pc)))]
417459693Selan  ""
417559693Selan  "*
417659693Selan#ifdef MOTOROLA
417759693Selan  OUTPUT_JUMP (\"jbge %l0\", \"fbge %l0\", \"jbpl %l0\");
417859693Selan#else
417959693Selan  OUTPUT_JUMP (\"jge %l0\", \"fjge %l0\", \"jpl %l0\");
418059693Selan#endif
418159693Selan")
418259693Selan
418359693Selan(define_insn "bgeu"
418459693Selan  [(set (pc)
418559693Selan	(if_then_else (geu (cc0)
418659693Selan			   (const_int 0))
418759693Selan		      (label_ref (match_operand 0 "" ""))
418859693Selan		      (pc)))]
418959693Selan  ""
419059693Selan  "*
419159693Selan#ifdef MOTOROLA
419259693Selan  return \"jbcc %l0\";
419359693Selan#else
419459693Selan  return \"jcc %l0\";
419559693Selan#endif
419659693Selan")
419759693Selan
419859693Selan(define_insn "ble"
419959693Selan  [(set (pc)
420059693Selan	(if_then_else (le (cc0)
420159693Selan			  (const_int 0))
420259693Selan		      (label_ref (match_operand 0 "" ""))
420359693Selan		      (pc)))]
420459693Selan  ""
420559693Selan  "*
420659693Selan#ifdef MOTOROLA
420759693Selan  OUTPUT_JUMP (\"jble %l0\", \"fble %l0\", 0);
420859693Selan#else
420959693Selan  OUTPUT_JUMP (\"jle %l0\", \"fjle %l0\", 0);
421059693Selan#endif
421159693Selan")
421259693Selan
421359693Selan(define_insn "bleu"
421459693Selan  [(set (pc)
421559693Selan	(if_then_else (leu (cc0)
421659693Selan			   (const_int 0))
421759693Selan		      (label_ref (match_operand 0 "" ""))
421859693Selan		      (pc)))]
421959693Selan  ""
422059693Selan  "*
422159693Selan#ifdef MOTOROLA
422259693Selan  return \"jbls %l0\";
422359693Selan#else
422459693Selan  return \"jls %l0\";
422559693Selan#endif
422659693Selan")
422759693Selan
422859693Selan;; Negated conditional jump instructions.
422959693Selan
423059693Selan(define_insn ""
423159693Selan  [(set (pc)
423259693Selan	(if_then_else (eq (cc0)
423359693Selan			  (const_int 0))
423459693Selan		      (pc)
423559693Selan		      (label_ref (match_operand 0 "" ""))))]
423659693Selan  ""
423759693Selan  "*
423859693Selan{
423959693Selan#ifdef MOTOROLA
424059693Selan  OUTPUT_JUMP (\"jbne %l0\", \"fbne %l0\", \"jbne %l0\");
424159693Selan#else
424259693Selan  OUTPUT_JUMP (\"jne %l0\", \"fjne %l0\", \"jne %l0\");
424359693Selan#endif
424459693Selan}")
424559693Selan
424659693Selan(define_insn ""
424759693Selan  [(set (pc)
424859693Selan	(if_then_else (ne (cc0)
424959693Selan			  (const_int 0))
425059693Selan		      (pc)
425159693Selan		      (label_ref (match_operand 0 "" ""))))]
425259693Selan  ""
425359693Selan  "*
425459693Selan{
425559693Selan#ifdef MOTOROLA
425659693Selan  OUTPUT_JUMP (\"jbeq %l0\", \"fbeq %l0\", \"jbeq %l0\");
425759693Selan#else
425859693Selan  OUTPUT_JUMP (\"jeq %l0\", \"fjeq %l0\", \"jeq %l0\");
425959693Selan#endif
426059693Selan}")
426159693Selan
426259693Selan(define_insn ""
426359693Selan  [(set (pc)
426459693Selan	(if_then_else (gt (cc0)
426559693Selan			  (const_int 0))
426659693Selan		      (pc)
426759693Selan		      (label_ref (match_operand 0 "" ""))))]
426859693Selan  ""
426959693Selan  "*
427059693Selan#ifdef MOTOROLA
427159693Selan  OUTPUT_JUMP (\"jble %l0\", \"fbngt %l0\", 0);
427259693Selan#else
427359693Selan  OUTPUT_JUMP (\"jle %l0\", \"fjngt %l0\", 0);
427459693Selan#endif
427559693Selan")
427659693Selan
427759693Selan(define_insn ""
427859693Selan  [(set (pc)
427959693Selan	(if_then_else (gtu (cc0)
428059693Selan			   (const_int 0))
428159693Selan		      (pc)
428259693Selan		      (label_ref (match_operand 0 "" ""))))]
428359693Selan  ""
428459693Selan  "*
428559693Selan#ifdef MOTOROLA
428659693Selan  return \"jbls %l0\";
428759693Selan#else
428859693Selan  return \"jls %l0\";
428959693Selan#endif
429059693Selan")
429159693Selan
429259693Selan(define_insn ""
429359693Selan  [(set (pc)
429459693Selan	(if_then_else (lt (cc0)
429559693Selan			  (const_int 0))
429659693Selan		      (pc)
429759693Selan		      (label_ref (match_operand 0 "" ""))))]
429859693Selan  ""
429959693Selan  "*
430059693Selan#ifdef MOTOROLA
430159693Selan  OUTPUT_JUMP (\"jbge %l0\", \"fbnlt %l0\", \"jbpl %l0\");
430259693Selan#else
430359693Selan  OUTPUT_JUMP (\"jge %l0\", \"fjnlt %l0\", \"jpl %l0\");
430459693Selan#endif
430559693Selan")
430659693Selan
430759693Selan(define_insn ""
430859693Selan  [(set (pc)
430959693Selan	(if_then_else (ltu (cc0)
431059693Selan			   (const_int 0))
431159693Selan		      (pc)
431259693Selan		      (label_ref (match_operand 0 "" ""))))]
431359693Selan  ""
431459693Selan  "*
431559693Selan#ifdef MOTOROLA
431659693Selan  return \"jbcc %l0\";
431759693Selan#else
431859693Selan  return \"jcc %l0\";
431959693Selan#endif
432059693Selan")
432159693Selan
432259693Selan(define_insn ""
432359693Selan  [(set (pc)
432459693Selan	(if_then_else (ge (cc0)
432559693Selan			  (const_int 0))
432659693Selan		      (pc)
432759693Selan		      (label_ref (match_operand 0 "" ""))))]
432859693Selan  ""
432959693Selan  "*
433059693Selan#ifdef MOTOROLA
433159693Selan  OUTPUT_JUMP (\"jblt %l0\", \"fbnge %l0\", \"jbmi %l0\");
433259693Selan#else
433359693Selan  OUTPUT_JUMP (\"jlt %l0\", \"fjnge %l0\", \"jmi %l0\");
433459693Selan#endif
433559693Selan")
433659693Selan
433759693Selan(define_insn ""
433859693Selan  [(set (pc)
433959693Selan	(if_then_else (geu (cc0)
434059693Selan			   (const_int 0))
434159693Selan		      (pc)
434259693Selan		      (label_ref (match_operand 0 "" ""))))]
434359693Selan  ""
434459693Selan  "*
434559693Selan#ifdef MOTOROLA
434659693Selan  return \"jbcs %l0\";
434759693Selan#else
434859693Selan  return \"jcs %l0\";
434959693Selan#endif
435059693Selan")
435159693Selan
435259693Selan(define_insn ""
435359693Selan  [(set (pc)
435459693Selan	(if_then_else (le (cc0)
435559693Selan			  (const_int 0))
435659693Selan		      (pc)
435759693Selan		      (label_ref (match_operand 0 "" ""))))]
435859693Selan  ""
435959693Selan  "*
436059693Selan#ifdef MOTOROLA
436159693Selan  OUTPUT_JUMP (\"jbgt %l0\", \"fbnle %l0\", 0);
436259693Selan#else
436359693Selan  OUTPUT_JUMP (\"jgt %l0\", \"fjnle %l0\", 0);
436459693Selan#endif
436559693Selan")
436659693Selan
436759693Selan(define_insn ""
436859693Selan  [(set (pc)
436959693Selan	(if_then_else (leu (cc0)
437059693Selan			   (const_int 0))
437159693Selan		      (pc)
437259693Selan		      (label_ref (match_operand 0 "" ""))))]
437359693Selan  ""
437459693Selan  "*
437559693Selan#ifdef MOTOROLA
437659693Selan  return \"jbhi %l0\";
437759693Selan#else
437859693Selan  return \"jhi %l0\";
437959693Selan#endif
438059693Selan")
438159693Selan
438259693Selan;; Unconditional and other jump instructions
438359693Selan(define_insn "jump"
438459693Selan  [(set (pc)
438559693Selan	(label_ref (match_operand 0 "" "")))]
438659693Selan  ""
438759693Selan  "*
438859693Selan#ifdef MOTOROLA
438959693Selan  return \"jbra %l0\";
439059693Selan#else
439159693Selan  return \"jra %l0\";
439259693Selan#endif
439359693Selan")
439459693Selan
439559693Selan;; We support two different ways of handling dispatch tables.
439659693Selan;; The NeXT uses absolute tables, and other machines use relative.
439759693Selan;; This define_expand can generate either kind.
439859693Selan(define_expand "tablejump"
439959693Selan  [(parallel [(set (pc) (match_operand 0 "" ""))
440059693Selan	      (use (label_ref (match_operand 1 "" "")))])]
440159693Selan  ""
440259693Selan  "
440359693Selan{
440459693Selan#ifdef CASE_VECTOR_PC_RELATIVE
440559693Selan    operands[0] = gen_rtx (PLUS, SImode, pc_rtx, operands[0]);
440659693Selan#endif
440759693Selan}")
440859693Selan
440959693Selan;; Jump to variable address from dispatch table of absolute addresses.
441059693Selan(define_insn ""
441159693Selan  [(set (pc) (match_operand:SI 0 "register_operand" "a"))
441259693Selan   (use (label_ref (match_operand 1 "" "")))]
441359693Selan  ""
441459693Selan  "*
441559693Selan#ifdef MOTOROLA
441659693Selan  return \"jmp (%0)\";
441759693Selan#else
441859693Selan  return \"jmp %0@\";
441959693Selan#endif
442059693Selan")
442159693Selan
442259693Selan;; Jump to variable address from dispatch table of relative addresses.
442359693Selan(define_insn ""
442459693Selan  [(set (pc)
442559693Selan	(plus:SI (pc) (match_operand:HI 0 "register_operand" "r")))
442659693Selan   (use (label_ref (match_operand 1 "" "")))]
442759693Selan  ""
442859693Selan  "*
442959693Selan#ifdef ASM_RETURN_CASE_JUMP
443059693Selan ASM_RETURN_CASE_JUMP;
443159693Selan#else
443259693Selan#ifdef SGS
443359693Selan#ifdef ASM_OUTPUT_CASE_LABEL
443459693Selan  return \"jmp 6(%%pc,%0.w)\";
443559693Selan#else
443659693Selan#ifdef CRDS
443759693Selan  return \"jmp 2(pc,%0.w)\";
443859693Selan#else
443959693Selan  return \"jmp 2(%%pc,%0.w)\";
444059693Selan#endif  /* end !CRDS */
444159693Selan#endif
444259693Selan#else /* not SGS */
444359693Selan#ifdef MOTOROLA
444459693Selan  return \"jmp (2,pc,%0.w)\";
444559693Selan#else
444659693Selan  return \"jmp pc@(2,%0:w)\";
444759693Selan#endif
444859693Selan#endif
444959693Selan#endif
445059693Selan")
445159693Selan
445259693Selan;; Decrement-and-branch insns.
445359693Selan(define_insn ""
445459693Selan  [(set (pc)
445559693Selan	(if_then_else
445659693Selan	 (ne (match_operand:HI 0 "general_operand" "+g")
445759693Selan	     (const_int 0))
445859693Selan	 (label_ref (match_operand 1 "" ""))
445959693Selan	 (pc)))
446059693Selan   (set (match_dup 0)
446159693Selan	(plus:HI (match_dup 0)
446259693Selan		 (const_int -1)))]
446359693Selan  ""
446459693Selan  "*
446559693Selan{
446659693Selan  CC_STATUS_INIT;
446759693Selan  if (DATA_REG_P (operands[0]))
446859693Selan    return \"dbra %0,%l1\";
446959693Selan  if (GET_CODE (operands[0]) == MEM)
447059693Selan    {
447159693Selan#ifdef MOTOROLA
447259693Selan#ifdef NO_ADDSUB_Q
447359693Selan      return \"sub%.w %#1,%0\;jbcc %l1\";
447459693Selan#else
447559693Selan      return \"subq%.w %#1,%0\;jbcc %l1\";
447659693Selan#endif
447759693Selan#else /* not MOTOROLA */
447859693Selan      return \"subqw %#1,%0\;jcc %l1\";
447959693Selan#endif
448059693Selan    }
448159693Selan#ifdef MOTOROLA
448259693Selan#ifdef SGS_CMP_ORDER
448359693Selan#ifdef NO_ADDSUB_Q
448459693Selan  return \"sub%.w %#1,%0\;cmp%.w %0,%#-1\;jbne %l1\";
448559693Selan#else
448659693Selan  return \"subq%.w %#1,%0\;cmp%.w %0,%#-1\;jbne %l1\";
448759693Selan#endif
448859693Selan#else /* not SGS_CMP_ORDER */
448959693Selan  return \"subq%.w %#1,%0\;cmp%.w %#-1,%0\;jbne %l1\";
449059693Selan#endif
449159693Selan#else /* not MOTOROLA */
449259693Selan  return \"subqw %#1,%0\;cmpw %#-1,%0\;jne %l1\";
449359693Selan#endif
449459693Selan}")
449559693Selan
449659693Selan(define_insn ""
449759693Selan  [(set (pc)
449859693Selan	(if_then_else
449959693Selan	 (ne (match_operand:SI 0 "general_operand" "+g")
450059693Selan	     (const_int 0))
450159693Selan	 (label_ref (match_operand 1 "" ""))
450259693Selan	 (pc)))
450359693Selan   (set (match_dup 0)
450459693Selan	(plus:SI (match_dup 0)
450559693Selan		 (const_int -1)))]
450659693Selan  ""
450759693Selan  "*
450859693Selan{
450959693Selan  CC_STATUS_INIT;
451059693Selan#ifdef MOTOROLA
451159693Selan#ifdef NO_ADDSUB_Q
451259693Selan  if (DATA_REG_P (operands[0]))
451359693Selan    return \"dbra %0,%l1\;clr%.w %0\;sub%.l %#1,%0\;jbcc %l1\";
451459693Selan  if (GET_CODE (operands[0]) == MEM)
451559693Selan    return \"sub%.l %#1,%0\;jbcc %l1\";
451659693Selan#else
451759693Selan  if (DATA_REG_P (operands[0]))
451859693Selan    return \"dbra %0,%l1\;clr%.w %0\;subq%.l %#1,%0\;jbcc %l1\";
451959693Selan  if (GET_CODE (operands[0]) == MEM)
452059693Selan    return \"subq%.l %#1,%0\;jbcc %l1\";
452159693Selan#endif /* NO_ADDSUB_Q */
452259693Selan#ifdef SGS_CMP_ORDER
452359693Selan#ifdef NO_ADDSUB_Q
452459693Selan  return \"sub.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\";
452559693Selan#else
452659693Selan  return \"subq.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\";
452759693Selan#endif
452859693Selan#else /* not SGS_CMP_ORDER */
452959693Selan  return \"subq.l %#1,%0\;cmp.l %#-1,%0\;jbne %l1\";
453059693Selan#endif /* not SGS_CMP_ORDER */
453159693Selan#else /* not MOTOROLA */
453259693Selan  if (DATA_REG_P (operands[0]))
453359693Selan    return \"dbra %0,%l1\;clr%.w %0\;subql %#1,%0\;jcc %l1\";
453459693Selan  if (GET_CODE (operands[0]) == MEM)
453559693Selan    return \"subql %#1,%0\;jcc %l1\";
453659693Selan  return \"subql %#1,%0\;cmpl %#-1,%0\;jne %l1\";
453759693Selan#endif /* not MOTOROLA */
453859693Selan}")
453959693Selan
454059693Selan;; Two dbra patterns that use REG_NOTES info generated by strength_reduce.
454159693Selan
454259693Selan(define_insn ""
454359693Selan  [(set (pc)
454459693Selan	(if_then_else
454559693Selan	  (ge (plus:HI (match_operand:HI 0 "general_operand" "+g")
454659693Selan		       (const_int -1))
454759693Selan	      (const_int 0))
454859693Selan	  (label_ref (match_operand 1 "" ""))
454959693Selan	  (pc)))
455059693Selan   (set (match_dup 0)
455159693Selan	(plus:HI (match_dup 0)
455259693Selan		 (const_int -1)))]
455359693Selan  "find_reg_note (insn, REG_NONNEG, 0)"
455459693Selan  "*
455559693Selan{
455659693Selan  CC_STATUS_INIT;
455759693Selan#ifdef MOTOROLA
455859693Selan#ifdef NO_ADDSUB_Q
455959693Selan  if (DATA_REG_P (operands[0]))
456059693Selan    return \"dbra %0,%l1\";
456159693Selan  if (GET_CODE (operands[0]) == MEM)
456259693Selan    return \"sub%.w %#1,%0\;jbcc %l1\";
456359693Selan#else
456459693Selan  if (DATA_REG_P (operands[0]))
456559693Selan    return \"dbra %0,%l1\";
456659693Selan  if (GET_CODE (operands[0]) == MEM)
456759693Selan    return \"subq%.w %#1,%0\;jbcc %l1\";
456859693Selan#endif
456959693Selan#ifdef SGS_CMP_ORDER
457059693Selan#ifdef NO_ADDSUB_Q
457159693Selan  return \"sub.w %#1,%0\;cmp.w %0,%#-1\;jbne %l1\";
457259693Selan#else
457359693Selan  return \"subq.w %#1,%0\;cmp.w %0,%#-1\;jbne %l1\";
457459693Selan#endif
457559693Selan#else /* not SGS_CMP_ORDER */
457659693Selan  return \"subq.w %#1,%0\;cmp.w %#-1,%0\;jbne %l1\";
457759693Selan#endif /* not SGS_CMP_ORDER */
457859693Selan#else /* not MOTOROLA */
457959693Selan  if (DATA_REG_P (operands[0]))
458059693Selan    return \"dbra %0,%l1\";
458159693Selan  if (GET_CODE (operands[0]) == MEM)
458259693Selan    return \"subqw %#1,%0\;jcc %l1\";
458359693Selan  return \"subqw %#1,%0\;cmpw %#-1,%0\;jne %l1\";
458459693Selan#endif /* not MOTOROLA */
458559693Selan}")
458659693Selan
458759693Selan(define_insn "decrement_and_branch_until_zero"
458859693Selan  [(set (pc)
458959693Selan	(if_then_else
459059693Selan	  (ge (plus:SI (match_operand:SI 0 "general_operand" "+g")
459159693Selan		       (const_int -1))
459259693Selan	      (const_int 0))
459359693Selan	  (label_ref (match_operand 1 "" ""))
459459693Selan	  (pc)))
459559693Selan   (set (match_dup 0)
459659693Selan	(plus:SI (match_dup 0)
459759693Selan		 (const_int -1)))]
459859693Selan  "find_reg_note (insn, REG_NONNEG, 0)"
459959693Selan  "*
460059693Selan{
460159693Selan  CC_STATUS_INIT;
460259693Selan#ifdef MOTOROLA
460359693Selan#ifdef NO_ADDSUB_Q
460459693Selan  if (DATA_REG_P (operands[0]))
460559693Selan    return \"dbra %0,%l1\;clr%.w %0\;sub%.l %#1,%0\;jbcc %l1\";
460659693Selan  if (GET_CODE (operands[0]) == MEM)
460759693Selan    return \"sub%.l %#1,%0\;jbcc %l1\";
460859693Selan#else
460959693Selan  if (DATA_REG_P (operands[0]))
461059693Selan    return \"dbra %0,%l1\;clr%.w %0\;subq%.l %#1,%0\;jbcc %l1\";
461159693Selan  if (GET_CODE (operands[0]) == MEM)
461259693Selan    return \"subq%.l %#1,%0\;jbcc %l1\";
461359693Selan#endif
461459693Selan#ifdef SGS_CMP_ORDER
461559693Selan#ifdef NO_ADDSUB_Q
461659693Selan  return \"sub.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\";
461759693Selan#else
461859693Selan  return \"subq.l %#1,%0\;cmp.l %0,%#-1\;jbne %l1\";
461959693Selan#endif
462059693Selan#else /* not SGS_CMP_ORDER */
462159693Selan  return \"subq.l %#1,%0\;cmp.l %#-1,%0\;jbne %l1\";
462259693Selan#endif /* not SGS_CMP_ORDER */
462359693Selan#else /* not MOTOROLA */
462459693Selan  if (DATA_REG_P (operands[0]))
462559693Selan    return \"dbra %0,%l1\;clr%.w %0\;subql %#1,%0\;jcc %l1\";
462659693Selan  if (GET_CODE (operands[0]) == MEM)
462759693Selan    return \"subql %#1,%0\;jcc %l1\";
462859693Selan  return \"subql %#1,%0\;cmpl %#-1,%0\;jne %l1\";
462959693Selan#endif /* not MOTOROLA */
463059693Selan}")
463159693Selan
463259693Selan
463359693Selan;; PIC calls are handled by loading the address of the function into a
463459693Selan;; register (via movsi), then emitting a register indirect call using
463559693Selan;; the "jsr" function call syntax.
463659693Selan;;
463759693Selan;; It is important to note that the "jsr" syntax is always used for
463859693Selan;; PIC calls, even on machines in which GCC normally uses the "jbsr"
463959693Selan;; syntax for non-PIC calls.  This keeps at least 1 assembler (Sun)
464059693Selan;; from emitting incorrect code for a PIC call.
464159693Selan;;
464259693Selan;; We have different patterns for PIC calls and non-PIC calls.  The
464359693Selan;; different patterns are only used to choose the right syntax
464459693Selan;; ("jsr" vs "jbsr").
464559693Selan
464659693Selan;; Call subroutine with no return value.
464759693Selan(define_expand "call"
464859693Selan  [(call (match_operand:QI 0 "memory_operand" "")
464959693Selan	 (match_operand:SI 1 "general_operand" ""))]
465059693Selan  ;; Operand 1 not really used on the m68000.
465159693Selan
465259693Selan  ""
465359693Selan  "
465459693Selan{
465559693Selan  if (flag_pic && GET_CODE (XEXP (operands[0], 0)) == SYMBOL_REF)
465659693Selan    operands[0] = gen_rtx (MEM, GET_MODE (operands[0]),
465759693Selan			   force_reg (Pmode, XEXP (operands[0], 0)));
465859693Selan}")
465959693Selan
466059693Selan;; This is a normal call sequence.
466159693Selan(define_insn ""
466259693Selan  [(call (match_operand:QI 0 "memory_operand" "o")
466359693Selan	 (match_operand:SI 1 "general_operand" "g"))]
466459693Selan  ;; Operand 1 not really used on the m68000.
466559693Selan
466659693Selan  "! flag_pic"
466759693Selan  "*
466859693Selan#ifdef MOTOROLA
466959693Selan  return \"jsr %0\";
467059693Selan#else
467159693Selan  return \"jbsr %0\";
467259693Selan#endif
467359693Selan")
467459693Selan
467559693Selan;; This is a PIC call sequence.
467659693Selan(define_insn ""
467759693Selan  [(call (match_operand:QI 0 "memory_operand" "o")
467859693Selan	 (match_operand:SI 1 "general_operand" "g"))]
467959693Selan  ;; Operand 1 not really used on the m68000.
468059693Selan
468159693Selan  "flag_pic"
468259693Selan  "*
468359693Selan  return \"jsr %0\";
468459693Selan")
468559693Selan
468659693Selan;; Call subroutine, returning value in operand 0
468759693Selan;; (which must be a hard register).
468859693Selan;; See comments before "call" regarding PIC calls.
468959693Selan(define_expand "call_value"
469059693Selan  [(set (match_operand 0 "" "")
469159693Selan	(call (match_operand:QI 1 "memory_operand" "")
469259693Selan     (match_operand:SI 2 "general_operand" "")))]
469359693Selan  ;; Operand 2 not really used on the m68000.
469459693Selan  ""
469559693Selan  "
469659693Selan{
469759693Selan  if (flag_pic && GET_CODE (XEXP (operands[1], 0)) == SYMBOL_REF)
469859693Selan    operands[1] = gen_rtx (MEM, GET_MODE (operands[1]),
469959693Selan			   force_reg (Pmode, XEXP (operands[1], 0)));
470059693Selan}")
470159693Selan
470259693Selan;; This is a normal call_value
470359693Selan(define_insn ""
470459693Selan  [(set (match_operand 0 "" "=rf")
470559693Selan	(call (match_operand:QI 1 "memory_operand" "o")
470659693Selan	      (match_operand:SI 2 "general_operand" "g")))]
470759693Selan  ;; Operand 2 not really used on the m68000.
470859693Selan  "! flag_pic"
470959693Selan  "*
471059693Selan#ifdef MOTOROLA
471159693Selan  return \"jsr %1\";
471259693Selan#else
471359693Selan  return \"jbsr %1\";
471459693Selan#endif
471559693Selan")
471659693Selan
471759693Selan;; This is a PIC call_value
471859693Selan(define_insn ""
471959693Selan  [(set (match_operand 0 "" "=rf")
472059693Selan	(call (match_operand:QI 1 "memory_operand" "o")
472159693Selan	      (match_operand:SI 2 "general_operand" "g")))]
472259693Selan  ;; Operand 2 not really used on the m68000.
472359693Selan  "flag_pic"
472459693Selan  "*
472559693Selan  return \"jsr %1\";
472659693Selan")
472759693Selan
472859693Selan(define_insn "nop"
472959693Selan  [(const_int 0)]
473059693Selan  ""
473159693Selan  "nop")
473259693Selan
473359693Selan(define_insn "probe"
473459693Selan [(reg:SI 15)]
473559693Selan "NEED_PROBE"
473659693Selan "*
473759693Selan{
473859693Selan  operands[0] = gen_rtx (PLUS, SImode, stack_pointer_rtx,
473959693Selan			 gen_rtx (CONST_INT, VOIDmode, NEED_PROBE));
474059693Selan  return \"tstl %a0\";
474159693Selan}")
474259693Selan
474359693Selan;; Used for frameless functions which save no regs and allocate no locals.
474459693Selan(define_insn "return"
474559693Selan  [(return)]
474659693Selan  "USE_RETURN_INSN"
474759693Selan  "*
474859693Selan{
474959693Selan  if (current_function_pops_args == 0)
475059693Selan    return \"rts\";
475159693Selan  operands[0] = gen_rtx (CONST_INT, VOIDmode, current_function_pops_args);
475259693Selan  return \"rtd %0\";
475359693Selan}")
475459693Selan
475559693Selan(define_insn "indirect_jump"
475659693Selan  [(set (pc) (match_operand:SI 0 "address_operand" "p"))]
475759693Selan  ""
475859693Selan  "jmp %a0")
475959693Selan
476059693Selan;; This should not be used unless the add/sub insns can't be.
476159693Selan
476259693Selan(define_insn ""
476359693Selan  [(set (match_operand:SI 0 "general_operand" "=a")
476459693Selan	(match_operand:QI 1 "address_operand" "p"))]
476559693Selan  ""
476659693Selan  "lea %a1,%0")
476759693Selan
476859693Selan;; This is the first machine-dependent peephole optimization.
476959693Selan;; It is useful when a floating value is returned from a function call
477059693Selan;; and then is moved into an FP register.
477159693Selan;; But it is mainly intended to test the support for these optimizations.
477259693Selan
477359693Selan(define_peephole
477459693Selan  [(set (reg:SI 15) (plus:SI (reg:SI 15) (const_int 4)))
477559693Selan   (set (match_operand:DF 0 "register_operand" "=f")
477659693Selan	(match_operand:DF 1 "register_operand" "ad"))]
477759693Selan  "FP_REG_P (operands[0]) && ! FP_REG_P (operands[1])"
477859693Selan  "*
477959693Selan{
478059693Selan  rtx xoperands[2];
478159693Selan  xoperands[1] = gen_rtx (REG, SImode, REGNO (operands[1]) + 1);
478259693Selan  output_asm_insn (\"move%.l %1,%@\", xoperands);
478359693Selan  output_asm_insn (\"move%.l %1,%-\", operands);
478459693Selan  return \"fmove%.d %+,%0\";
478559693Selan}
478659693Selan")
478759693Selan
478859693Selan;; Optimize a stack-adjust followed by a push of an argument.
478959693Selan;; This is said to happen frequently with -msoft-float
479059693Selan;; when there are consecutive library calls.
479159693Selan
479259693Selan(define_peephole
479359693Selan  [(set (reg:SI 15) (plus:SI (reg:SI 15)
479459693Selan			     (match_operand:SI 0 "immediate_operand" "n")))
479559693Selan   (set (match_operand:SF 1 "push_operand" "=m")
479659693Selan	(match_operand:SF 2 "general_operand" "rmfF"))]
479759693Selan  "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) >= 4
479859693Selan   && ! reg_mentioned_p (stack_pointer_rtx, operands[2])"
479959693Selan  "*
480059693Selan{
480159693Selan  if (INTVAL (operands[0]) > 4)
480259693Selan    {
480359693Selan      rtx xoperands[2];
480459693Selan      xoperands[0] = stack_pointer_rtx;
480559693Selan      xoperands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[0]) - 4);
480659693Selan#ifndef NO_ADDSUB_Q
480759693Selan      if (INTVAL (xoperands[1]) <= 8)
480859693Selan        output_asm_insn (\"addq%.w %1,%0\", xoperands);
480959693Selan      else if (INTVAL (xoperands[1]) <= 16 && TARGET_68020)
481059693Selan	{
481159693Selan	  xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
481259693Selan				  INTVAL (xoperands[1]) - 8);
481359693Selan	  output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands);
481459693Selan	}
481559693Selan      else
481659693Selan#endif
481759693Selan        if (INTVAL (xoperands[1]) <= 0x7FFF)
481859693Selan          output_asm_insn (\"add%.w %1,%0\", xoperands);
481959693Selan      else
482059693Selan        output_asm_insn (\"add%.l %1,%0\", xoperands);
482159693Selan    }
482259693Selan  if (FP_REG_P (operands[2]))
482359693Selan    return \"fmove%.s %2,%@\";
482459693Selan  return \"move%.l %2,%@\";
482559693Selan}")
482659693Selan
482759693Selan;; Speed up stack adjust followed by a fullword fixedpoint push.
482859693Selan
482959693Selan(define_peephole
483059693Selan  [(set (reg:SI 15) (plus:SI (reg:SI 15)
483159693Selan			     (match_operand:SI 0 "immediate_operand" "n")))
483259693Selan   (set (match_operand:SI 1 "push_operand" "=m")
483359693Selan	(match_operand:SI 2 "general_operand" "g"))]
483459693Selan  "GET_CODE (operands[0]) == CONST_INT && INTVAL (operands[0]) >= 4
483559693Selan   && ! reg_mentioned_p (stack_pointer_rtx, operands[2])"
483659693Selan  "*
483759693Selan{
483859693Selan  if (INTVAL (operands[0]) > 4)
483959693Selan    {
484059693Selan      rtx xoperands[2];
484159693Selan      xoperands[0] = stack_pointer_rtx;
484259693Selan      xoperands[1] = gen_rtx (CONST_INT, VOIDmode, INTVAL (operands[0]) - 4);
484359693Selan#ifndef NO_ADDSUB_Q
484459693Selan      if (INTVAL (xoperands[1]) <= 8)
484559693Selan        output_asm_insn (\"addq%.w %1,%0\", xoperands);
484659693Selan      else if (INTVAL (xoperands[1]) <= 16 && TARGET_68020)
484759693Selan	{
484859693Selan	  xoperands[1] = gen_rtx (CONST_INT, VOIDmode,
484959693Selan				  INTVAL (xoperands[1]) - 8);
485059693Selan	  output_asm_insn (\"addq%.w %#8,%0\;addq%.w %1,%0\", xoperands);
485159693Selan	}
485259693Selan      else
485359693Selan#endif
485459693Selan        if (INTVAL (xoperands[1]) <= 0x7FFF)
485559693Selan          output_asm_insn (\"add%.w %1,%0\", xoperands);
485659693Selan      else
485759693Selan        output_asm_insn (\"add%.l %1,%0\", xoperands);
485859693Selan    }
485959693Selan  if (operands[2] == const0_rtx)
486059693Selan    return \"clr%.l %@\";
486159693Selan  return \"move%.l %2,%@\";
486259693Selan}")
486359693Selan
486459693Selan;; Speed up pushing a single byte but leaving four bytes of space.
486559693Selan
486659693Selan(define_peephole
486759693Selan  [(set (mem:QI (pre_dec:SI (reg:SI 15)))
486859693Selan	(match_operand:QI 1 "general_operand" "dami"))
486959693Selan   (set (reg:SI 15) (minus:SI (reg:SI 15) (const_int 2)))]
487059693Selan  "! reg_mentioned_p (stack_pointer_rtx, operands[1])"
487159693Selan  "*
487259693Selan{
487359693Selan  rtx xoperands[4];
487459693Selan
487559693Selan  if (GET_CODE (operands[1]) == REG)
487659693Selan    return \"move%.l %1,%-\";
487759693Selan
487859693Selan  xoperands[1] = operands[1];
487959693Selan  xoperands[2]
488059693Selan    = gen_rtx (MEM, QImode,
488159693Selan	       gen_rtx (PLUS, VOIDmode, stack_pointer_rtx,
488259693Selan			gen_rtx (CONST_INT, VOIDmode, 3)));
488359693Selan  xoperands[3] = stack_pointer_rtx;
488459693Selan  output_asm_insn (\"subq%.w %#4,%3\;move%.b %1,%2\", xoperands);
488559693Selan  return \"\";
488659693Selan}")
488759693Selan
488859693Selan;; dbCC peepholes
488959693Selan;;
489059693Selan;; Turns
489159693Selan;;   loop:
489259693Selan;;           [ ... ]
489359693Selan;;           jCC label		; abnormal loop termination
489459693Selan;;           dbra dN, loop	; normal loop termination
489559693Selan;;
489659693Selan;; Into
489759693Selan;;   loop:
489859693Selan;;           [ ... ]
489959693Selan;;           dbCC dN, loop
490059693Selan;;           jCC label
490159693Selan;;
490259693Selan;; Which moves the jCC condition outside the inner loop for free.
490359693Selan;;
490459693Selan(define_peephole
490559693Selan  [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
490659693Selan                             [(cc0) (const_int 0)])
490759693Selan                           (label_ref (match_operand 2 "" ""))
490859693Selan                           (pc)))
490959693Selan   (parallel
491059693Selan    [(set (pc)
491159693Selan	  (if_then_else
491259693Selan	    (ge (plus:HI (match_operand:HI 0 "register_operand" "+d")
491359693Selan		         (const_int -1))
491459693Selan	        (const_int 0))
491559693Selan	    (label_ref (match_operand 1 "" ""))
491659693Selan	    (pc)))
491759693Selan     (set (match_dup 0)
491859693Selan	  (plus:HI (match_dup 0)
491959693Selan		   (const_int -1)))])]
492059693Selan  "DATA_REG_P (operands[0])"
492159693Selan  "*
492259693Selan{
492359693Selan  CC_STATUS_INIT;
492459693Selan  output_dbcc_and_branch (operands);
492559693Selan  return \"\";
492659693Selan}")
492759693Selan
492859693Selan(define_peephole
492959693Selan  [(set (pc) (if_then_else (match_operator 3 "valid_dbcc_comparison_p"
493059693Selan                             [(cc0) (const_int 0)])
493159693Selan                           (label_ref (match_operand 2 "" ""))
493259693Selan                           (pc)))
493359693Selan   (parallel
493459693Selan    [(set (pc)
493559693Selan	  (if_then_else
493659693Selan	    (ge (plus:SI (match_operand:SI 0 "register_operand" "+d")
493759693Selan		         (const_int -1))
493859693Selan	        (const_int 0))
493959693Selan	    (label_ref (match_operand 1 "" ""))
494059693Selan	    (pc)))
494159693Selan     (set (match_dup 0)
494259693Selan	  (plus:SI (match_dup 0)
494359693Selan		   (const_int -1)))])]
494459693Selan  "DATA_REG_P (operands[0])"
494559693Selan  "*
494659693Selan{
494759693Selan  CC_STATUS_INIT;
494859693Selan  output_dbcc_and_branch (operands);
494959693Selan  return \"\";
495059693Selan}")
495159693Selan
495259693Selan
495359693Selan;; FPA multiply and add.
495459693Selan(define_insn ""
495559693Selan  [(set (match_operand:DF 0 "register_operand" "=x,y,y")
495659693Selan	(plus:DF (mult:DF (match_operand:DF 1 "general_operand" "%x,dmF,y")
495759693Selan			  (match_operand:DF 2 "general_operand" "xH,y,y"))
495859693Selan		 (match_operand:DF 3 "general_operand" "xH,y,dmF")))]
495959693Selan   "TARGET_FPA"
496059693Selan   "@
496159693Selan    fpma%.d %1,%w2,%w3,%0
496259693Selan    fpma%.d %x1,%x2,%x3,%0
496359693Selan    fpma%.d %x1,%x2,%x3,%0")
496459693Selan
496559693Selan(define_insn ""
496659693Selan  [(set (match_operand:SF 0 "register_operand" "=x,y,y")
496759693Selan	(plus:SF (mult:SF (match_operand:SF 1 "general_operand" "%x,ydmF,y")
496859693Selan			  (match_operand:SF 2 "general_operand" "xH,y,ydmF"))
496959693Selan		 (match_operand:SF 3 "general_operand" "xH,ydmF,ydmF")))]
497059693Selan   "TARGET_FPA"
497159693Selan   "@
497259693Selan    fpma%.s %1,%w2,%w3,%0
497359693Selan    fpma%.s %1,%2,%3,%0
497459693Selan    fpma%.s %1,%2,%3,%0")
497559693Selan
497659693Selan;; FPA Multiply and subtract
497759693Selan(define_insn ""
497859693Selan  [(set (match_operand:DF 0 "register_operand" "=x,y,y")
497959693Selan	(minus:DF (match_operand:DF 1 "general_operand" "xH,rmF,y")
498059693Selan		  (mult:DF (match_operand:DF 2 "general_operand" "%xH,y,y")
498159693Selan			   (match_operand:DF 3 "general_operand" "x,y,rmF"))))]
498259693Selan  "TARGET_FPA"
498359693Selan  "@
498459693Selan   fpms%.d %3,%w2,%w1,%0
498559693Selan   fpms%.d %x3,%2,%x1,%0
498659693Selan   fpms%.d %x3,%2,%x1,%0")
498759693Selan
498859693Selan(define_insn ""
498959693Selan  [(set (match_operand:SF 0 "register_operand" "=x,y,y")
499059693Selan	(minus:SF (match_operand:SF 1 "general_operand" "xH,rmF,yrmF")
499159693Selan		  (mult:SF (match_operand:SF 2 "general_operand" "%xH,rmF,y")
499259693Selan			   (match_operand:SF 3 "general_operand" "x,y,yrmF"))))]
499359693Selan  "TARGET_FPA"
499459693Selan  "@
499559693Selan   fpms%.s %3,%w2,%w1,%0
499659693Selan   fpms%.s %3,%2,%1,%0
499759693Selan   fpms%.s %3,%2,%1,%0")
499859693Selan
499959693Selan(define_insn ""
500059693Selan  [(set (match_operand:DF 0 "register_operand" "=x,y,y")
500159693Selan	(minus:DF (mult:DF (match_operand:DF 1 "general_operand" "%xH,y,y")
500259693Selan			   (match_operand:DF 2 "general_operand" "x,y,rmF"))
500359693Selan		  (match_operand:DF 3 "general_operand" "xH,rmF,y")))]
500459693Selan  "TARGET_FPA"
500559693Selan  "@
500659693Selan   fpmr%.d %2,%w1,%w3,%0
500759693Selan   fpmr%.d %x2,%1,%x3,%0
500859693Selan   fpmr%.d %x2,%1,%x3,%0")
500959693Selan
501059693Selan(define_insn ""
501159693Selan  [(set (match_operand:SF 0 "register_operand" "=x,y,y")
501259693Selan	(minus:SF (mult:SF (match_operand:SF 1 "general_operand" "%xH,rmF,y")
501359693Selan			   (match_operand:SF 2 "general_operand" "x,y,yrmF"))
501459693Selan		  (match_operand:SF 3 "general_operand" "xH,rmF,yrmF")))]
501559693Selan  "TARGET_FPA"
501659693Selan  "@
501759693Selan   fpmr%.s %2,%w1,%w3,%0
501859693Selan   fpmr%.s %x2,%1,%x3,%0
501959693Selan   fpmr%.s %x2,%1,%x3,%0")
502059693Selan
502159693Selan;; FPA Add and multiply
502259693Selan(define_insn ""
502359693Selan  [(set (match_operand:DF 0 "register_operand" "=x,y,y")
502459693Selan	(mult:DF (plus:DF (match_operand:DF 1 "general_operand" "%xH,y,y")
502559693Selan			  (match_operand:DF 2 "general_operand" "x,y,rmF"))
502659693Selan		 (match_operand:DF 3 "general_operand" "xH,rmF,y")))]
502759693Selan  "TARGET_FPA"
502859693Selan  "@
502959693Selan   fpam%.d %2,%w1,%w3,%0
503059693Selan   fpam%.d %x2,%1,%x3,%0
503159693Selan   fpam%.d %x2,%1,%x3,%0")
503259693Selan
503359693Selan(define_insn ""
503459693Selan  [(set (match_operand:SF 0 "register_operand" "=x,y,y")
503559693Selan	(mult:SF (plus:SF (match_operand:SF 1 "general_operand" "%xH,rmF,y")
503659693Selan			  (match_operand:SF 2 "general_operand" "x,y,yrmF"))
503759693Selan		 (match_operand:SF 3 "general_operand" "xH,rmF,yrmF")))]
503859693Selan  "TARGET_FPA"
503959693Selan  "@
504059693Selan   fpam%.s %2,%w1,%w3,%0
504159693Selan   fpam%.s %x2,%1,%x3,%0
504259693Selan   fpam%.s %x2,%1,%x3,%0")
504359693Selan
504459693Selan;;FPA Subtract and multiply
504559693Selan(define_insn ""
504659693Selan  [(set (match_operand:DF 0 "register_operand" "=x,y,y")
504759693Selan	(mult:DF (minus:DF (match_operand:DF 1 "general_operand" "xH,y,y")
504859693Selan			   (match_operand:DF 2 "general_operand" "x,y,rmF"))
504959693Selan		 (match_operand:DF 3 "general_operand" "xH,rmF,y")))]
505059693Selan  "TARGET_FPA"
505159693Selan  "@
505259693Selan   fpsm%.d %2,%w1,%w3,%0
505359693Selan   fpsm%.d %x2,%1,%x3,%0
505459693Selan   fpsm%.d %x2,%1,%x3,%0")
505559693Selan
505659693Selan(define_insn ""
505759693Selan  [(set (match_operand:DF 0 "register_operand" "=x,y,y")
505859693Selan	(mult:DF (match_operand:DF 1 "general_operand" "xH,rmF,y")
505959693Selan		 (minus:DF (match_operand:DF 2 "general_operand" "xH,y,y")
506059693Selan			   (match_operand:DF 3 "general_operand" "x,y,rmF"))))]
506159693Selan  "TARGET_FPA"
506259693Selan  "@
506359693Selan   fpsm%.d %3,%w2,%w1,%0
506459693Selan   fpsm%.d %x3,%2,%x1,%0
506559693Selan   fpsm%.d %x3,%2,%x1,%0")
506659693Selan
506759693Selan(define_insn ""
506859693Selan  [(set (match_operand:SF 0 "register_operand" "=x,y,y")
506959693Selan	(mult:SF (minus:SF (match_operand:SF 1 "general_operand" "xH,rmF,y")
507059693Selan			   (match_operand:SF 2 "general_operand" "x,y,yrmF"))
507159693Selan		 (match_operand:SF 3 "general_operand" "xH,rmF,yrmF")))]
507259693Selan  "TARGET_FPA"
507359693Selan  "@
507459693Selan   fpsm%.s %2,%w1,%w3,%0
507559693Selan   fpsm%.s %x2,%1,%x3,%0
507659693Selan   fpsm%.s %x2,%1,%x3,%0")
507759693Selan
507859693Selan(define_insn ""
507959693Selan  [(set (match_operand:SF 0 "register_operand" "=x,y,y")
508059693Selan	(mult:SF (match_operand:SF 1 "general_operand" "xH,rmF,yrmF")
508159693Selan		 (minus:SF (match_operand:SF 2 "general_operand" "xH,rmF,y")
508259693Selan			   (match_operand:SF 3 "general_operand" "x,y,yrmF"))))]
508359693Selan  "TARGET_FPA"
508459693Selan  "@
508559693Selan   fpsm%.s %3,%w2,%w1,%0
508659693Selan   fpsm%.s %x3,%2,%x1,%0
508759693Selan   fpsm%.s %x3,%2,%x1,%0")
508859693Selan
508959693Selan;;- Local variables:
509059693Selan;;- mode:emacs-lisp
509159693Selan;;- comment-start: ";;- "
509259693Selan;;- comment-start-skip: ";+- *"
509359693Selan;;- eval: (set-syntax-table (copy-sequence (syntax-table)))
509459693Selan;;- eval: (modify-syntax-entry ?[ "(]")
509559693Selan;;- eval: (modify-syntax-entry ?] ")[")
509659693Selan;;- eval: (modify-syntax-entry ?{ "(}")
509759693Selan;;- eval: (modify-syntax-entry ?} "){")
509859693Selan;;- End:
5099