i386.md revision 56391
150650Sobrien; GCC machine description for Intel X86.
256391Sobrien;; Copyright (C) 1988, 94-99, 2000 Free Software Foundation, Inc.
318334Speter;; Mostly by William Schelter.
418334Speter
518334Speter;; This file is part of GNU CC.
618334Speter
718334Speter;; GNU CC is free software; you can redistribute it and/or modify
818334Speter;; it under the terms of the GNU General Public License as published by
918334Speter;; the Free Software Foundation; either version 2, or (at your option)
1018334Speter;; any later version.
1118334Speter
1218334Speter;; GNU CC is distributed in the hope that it will be useful,
1318334Speter;; but WITHOUT ANY WARRANTY; without even the implied warranty of
1418334Speter;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
1518334Speter;; GNU General Public License for more details.
1618334Speter
1718334Speter;; You should have received a copy of the GNU General Public License
1818334Speter;; along with GNU CC; see the file COPYING.  If not, write to
1918334Speter;; the Free Software Foundation, 59 Temple Place - Suite 330,
2050650Sobrien;; Boston, MA 02111-1307, USA. */
2118334Speter
2218334Speter;; The original PO technology requires these to be ordered by speed,
2318334Speter;; so that assigner will pick the fastest.
2418334Speter
2518334Speter;; See file "rtl.def" for documentation on define_insn, match_*, et. al.
2618334Speter
2718334Speter;; Macro #define NOTICE_UPDATE_CC in file i386.h handles condition code
2818334Speter;; updates for most instructions.
2918334Speter
3018334Speter;; Macro REG_CLASS_FROM_LETTER in file i386.h defines the register
3118334Speter;; constraint letters.
3218334Speter
3318334Speter;; the special asm out single letter directives following a '%' are:
3418334Speter;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of
3518334Speter;;     operands[1].
3618334Speter;; 'L' Print the opcode suffix for a 32-bit integer opcode.
3718334Speter;; 'W' Print the opcode suffix for a 16-bit integer opcode.
3818334Speter;; 'B' Print the opcode suffix for an 8-bit integer opcode.
3950650Sobrien;; 'Q' Print the opcode suffix for a 64-bit float opcode.
4018334Speter;; 'S' Print the opcode suffix for a 32-bit float opcode.
4118334Speter;; 'T' Print the opcode suffix for an 80-bit extended real XFmode float opcode.
4218334Speter;; 'J' Print the appropriate jump operand.
4318334Speter
4418334Speter;; 'b' Print the QImode name of the register for the indicated operand.
4518334Speter;;     %b0 would print %al if operands[0] is reg 0.
4618334Speter;; 'w' Likewise, print the HImode name of the register.
4718334Speter;; 'k' Likewise, print the SImode name of the register.
4818334Speter;; 'h' Print the QImode name for a "high" register, either ah, bh, ch or dh.
4918334Speter;; 'y' Print "st(0)" instead of "st" as a register.
5018334Speter
5118334Speter;; UNSPEC usage:
5218334Speter;; 0  This is a `scas' operation.  The mode of the UNSPEC is always SImode.
5318334Speter;;    operand 0 is the memory address to scan.
5418334Speter;;    operand 1 is a register containing the value to scan for.  The mode
5518334Speter;;       of the scas opcode will be the same as the mode of this operand.
5618334Speter;;    operand 2 is the known alignment of operand 0.
5718334Speter;; 1  This is a `sin' operation.  The mode of the UNSPEC is MODE_FLOAT.
5818334Speter;;    operand 0 is the argument for `sin'.
5918334Speter;; 2  This is a `cos' operation.  The mode of the UNSPEC is MODE_FLOAT.
6018334Speter;;    operand 0 is the argument for `cos'.
6150650Sobrien;; 3  This is part of a `stack probe' operation.  The mode of the UNSPEC is 
6250650Sobrien;;    always SImode.  operand 0 is the size of the stack allocation.
6350650Sobrien;; 4  This is the source of a fake SET of the frame pointer which is used to
6450650Sobrien;;    prevent insns referencing it being scheduled across the initial
6550650Sobrien;;    decrement of the stack pointer.
6650650Sobrien;; 5  This is a `bsf' operation.
6752296Sobrien;; 6  This is the @GOT offset of a PIC address.
6852296Sobrien;; 7  This is the @GOTOFF offset of a PIC address.
6952296Sobrien;; 8  This is a reference to a symbol's @PLT address.
7018334Speter
7150650Sobrien;; This shadows the processor_type enumeration, so changes must be made
7250650Sobrien;; to i386.h at the same time.
7350650Sobrien
7452296Sobrien;; $FreeBSD: head/contrib/gcc/config/i386/i386.md 56391 2000-01-22 16:04:30Z obrien $
7552296Sobrien
7652296Sobrien(define_attr "type"
7752296Sobrien  "integer,binary,memory,test,compare,fcompare,idiv,imul,lea,fld,fpop,fpdiv,fpmul"
7850650Sobrien  (const_string "integer"))
7950650Sobrien
8052296Sobrien(define_attr "memory" "none,load,store"
8152296Sobrien  (cond [(eq_attr "type" "idiv,lea")
8252296Sobrien	 (const_string "none")
8352296Sobrien
8452296Sobrien	 (eq_attr "type" "fld")
8552296Sobrien	 (const_string "load")
8652296Sobrien
8752296Sobrien	 (eq_attr "type" "test")
8852296Sobrien	 (if_then_else (match_operand 0 "memory_operand" "")
8952296Sobrien		       (const_string "load")
9052296Sobrien		       (const_string "none"))
9152296Sobrien
9252296Sobrien	 (eq_attr "type" "compare,fcompare")
9352296Sobrien	 (if_then_else (ior (match_operand 0 "memory_operand" "")
9452296Sobrien			    (match_operand 1 "memory_operand" ""))
9552296Sobrien		       (const_string "load")
9652296Sobrien		       (const_string "none"))
9752296Sobrien
9852296Sobrien	 (and (eq_attr "type" "integer,memory,fpop")
9952296Sobrien	      (match_operand 0 "memory_operand" ""))
10052296Sobrien	 (const_string "store")
10152296Sobrien
10252296Sobrien	 (and (eq_attr "type" "integer,memory,fpop")
10352296Sobrien	      (match_operand 1 "memory_operand" ""))
10452296Sobrien	 (const_string "load")
10552296Sobrien
10652296Sobrien	 (and (eq_attr "type" "binary,imul,fpmul,fpdiv")
10752296Sobrien	      (ior (match_operand 1 "memory_operand" "")
10852296Sobrien		   (match_operand 2 "memory_operand" "")))
10952296Sobrien	 (const_string "load")]
11052296Sobrien
11152296Sobrien	(const_string "none")))
11252296Sobrien
11350650Sobrien;; Functional units
11450650Sobrien
11550650Sobrien; (define_function_unit NAME MULTIPLICITY SIMULTANEITY
11650650Sobrien;                       TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST])
11750650Sobrien
11850650Sobrien; pentiumpro has a reservation station with 5 ports
11950650Sobrien; port  0 has integer, float add, integer divide, float divide, float 
12050650Sobrien;        multiply, and shifter units.
12150650Sobrien; port  1 has integer, and jump units.
12250650Sobrien; port  2 has the load address generation unit
12350650Sobrien; ports 3 and 4 have the store address generation units
12450650Sobrien
12550650Sobrien; pentium has two integer pipelines, the main u pipe and the secondary v pipe.
12650650Sobrien; and a float pipeline
12750650Sobrien
12850650Sobrien;; Floating point
12950650Sobrien
13050650Sobrien(define_function_unit "fp" 1 0
13152296Sobrien (and (eq_attr "type" "fpop,fcompare") (eq_attr "cpu" "i386,i486"))
13250650Sobrien 5 5)
13350650Sobrien
13450650Sobrien(define_function_unit "fp" 1 0
13552296Sobrien (and (eq_attr "type" "fpop,fcompare") (eq_attr "cpu" "pentium,pentiumpro")) 
13650650Sobrien 3 0)
13750650Sobrien
13850650Sobrien(define_function_unit "fp" 1 0
13950650Sobrien (and (eq_attr "type" "fpmul") (eq_attr "cpu" "pentium")) 
14050650Sobrien 7 0)
14150650Sobrien
14250650Sobrien(define_function_unit "fp" 1 0
14350650Sobrien (and (eq_attr "type" "fpmul") (eq_attr "cpu" "pentiumpro")) 
14450650Sobrien 5 0)
14550650Sobrien
14650650Sobrien(define_function_unit "fp" 1 0
14750650Sobrien (and (eq_attr "type" "idiv") (eq_attr "cpu" "pentiumpro")) 
14850650Sobrien 10 10)
14950650Sobrien
15050650Sobrien(define_function_unit "fp" 1 0
15150650Sobrien (and (eq_attr "type" "imul") (eq_attr "cpu" "pentiumpro")) 
15250650Sobrien 6 0)
15350650Sobrien
15450650Sobrien(define_function_unit "fp" 1 0
15550650Sobrien (eq_attr "type" "fpdiv") 
15650650Sobrien 10 10)
15750650Sobrien
15850650Sobrien(define_function_unit "fp" 1 0
15952296Sobrien  (and (eq_attr "type" "fld") (eq_attr "cpu" "!pentiumpro,k6"))
16050650Sobrien 1 0)
16150650Sobrien
16252296Sobrien;; K6 FPU is not pipelined.
16352296Sobrien(define_function_unit "fp" 1 0
16452296Sobrien  (and (eq_attr "type" "fpop,fpmul,fcompare") (eq_attr "cpu" "k6"))
16552296Sobrien 2 2)
16650650Sobrien
16752296Sobrien;; i386 and i486 have one integer unit, which need not be modeled
16852296Sobrien
16952296Sobrien(define_function_unit "integer" 2 0
17052296Sobrien  (and (eq_attr "type" "integer,binary,test,compare,lea") (eq_attr "cpu" "pentium,pentiumpro"))
17152296Sobrien 1 0)
17252296Sobrien
17352296Sobrien(define_function_unit "integer" 2 0
17452296Sobrien  (and (eq_attr "cpu" "k6")
17552296Sobrien       (and (eq_attr "type" "integer,binary,test,compare")
17652296Sobrien	    (eq_attr "memory" "!load")))
17752296Sobrien  1 0)
17852296Sobrien
17952296Sobrien;; Internally, K6 converts REG OP MEM instructions into a load (2 cycles)
18052296Sobrien;; and a register operation (1 cycle).
18152296Sobrien(define_function_unit "integer" 2 0
18252296Sobrien  (and (eq_attr "cpu" "k6")
18352296Sobrien       (and (eq_attr "type" "integer,binary,test,compare")
18452296Sobrien	    (eq_attr "memory" "load")))
18552296Sobrien  3 0)
18652296Sobrien
18752296Sobrien;; Multiplies use one of the integer units
18852296Sobrien(define_function_unit "integer" 2 0
18952296Sobrien  (and (eq_attr "cpu" "pentium") (eq_attr "type" "imul"))
19052296Sobrien  11 11)
19152296Sobrien
19252296Sobrien(define_function_unit "integer" 2 0
19352296Sobrien  (and (eq_attr "cpu" "k6") (eq_attr "type" "imul"))
19452296Sobrien  2 2)
19552296Sobrien
19652296Sobrien(define_function_unit "integer" 2 0
19752296Sobrien  (and (eq_attr "cpu" "pentium") (eq_attr "type" "idiv"))
19852296Sobrien  25 25)
19952296Sobrien
20052296Sobrien(define_function_unit "integer" 2 0
20152296Sobrien  (and (eq_attr "cpu" "k6") (eq_attr "type" "idiv"))
20252296Sobrien  17 17)
20352296Sobrien
20452296Sobrien;; Pentium Pro and K6 have a separate load unit.
20552296Sobrien(define_function_unit "load" 1 0
20652296Sobrien  (and (eq_attr "cpu" "pentiumpro") (eq_attr "memory" "load"))
20752296Sobrien  3 0)
20852296Sobrien
20952296Sobrien(define_function_unit "load" 1 0
21052296Sobrien  (and (eq_attr "cpu" "k6") (eq_attr "memory" "load"))
21152296Sobrien  2 0)
21252296Sobrien
21352296Sobrien;; Pentium Pro and K6 have a separate store unit.
21452296Sobrien(define_function_unit "store" 1 0
21552296Sobrien  (and (eq_attr "cpu" "pentiumpro,k6") (eq_attr "memory" "store"))
21652296Sobrien  1 0)
21752296Sobrien
21852296Sobrien;; lea executes in the K6 store unit with 1 cycle latency
21952296Sobrien(define_function_unit "store" 1 0
22052296Sobrien  (and (eq_attr "cpu" "k6") (eq_attr "type" "lea"))
22152296Sobrien  1 0)
22252296Sobrien
22350650Sobrien
22418334Speter;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM".
22518334Speter;; But restricting MEM here would mean that gcc could not remove a redundant
22618334Speter;; test in cases like "incl MEM / je TARGET".
22718334Speter;;
22818334Speter;; We don't want to allow a constant operand for test insns because
22918334Speter;; (set (cc0) (const_int foo)) has no mode information.  Such insns will
23018334Speter;; be folded while optimizing anyway.
23118334Speter
23218334Speter;; All test insns have expanders that save the operands away without
23318334Speter;; actually generating RTL.  The bCOND or sCOND (emitted immediately
23418334Speter;; after the tstM or cmp) will actually emit the tstM or cmpM.
23518334Speter
23650650Sobrien;; Processor type -- this attribute must exactly match the processor_type
23750650Sobrien;; enumeration in i386.h.
23850650Sobrien
23952296Sobrien(define_attr "cpu" "i386,i486,pentium,pentiumpro,k6"
24050650Sobrien  (const (symbol_ref "ix86_cpu")))
24150650Sobrien
24218334Speter(define_insn "tstsi_1"
24318334Speter  [(set (cc0)
24418334Speter	(match_operand:SI 0 "nonimmediate_operand" "rm"))]
24518334Speter  ""
24618334Speter  "*
24718334Speter{
24818334Speter  if (REG_P (operands[0]))
24918334Speter    return AS2 (test%L0,%0,%0);
25018334Speter
25118334Speter  operands[1] = const0_rtx;
25218334Speter  return AS2 (cmp%L0,%1,%0);
25352296Sobrien}"
25452296Sobrien  [(set_attr "type" "test")])
25518334Speter
25618334Speter(define_expand "tstsi"
25718334Speter  [(set (cc0)
25818334Speter	(match_operand:SI 0 "nonimmediate_operand" ""))]
25918334Speter  ""
26018334Speter  "
26118334Speter{
26218334Speter  i386_compare_gen = gen_tstsi_1;
26318334Speter  i386_compare_op0 = operands[0];
26450650Sobrien  i386_compare_op1 = const0_rtx;
26518334Speter  DONE;
26618334Speter}")
26718334Speter
26818334Speter(define_insn "tsthi_1"
26918334Speter  [(set (cc0)
27018334Speter	(match_operand:HI 0 "nonimmediate_operand" "rm"))]
27118334Speter  ""
27218334Speter  "*
27318334Speter{
27418334Speter  if (REG_P (operands[0]))
27518334Speter    return AS2 (test%W0,%0,%0);
27618334Speter
27718334Speter  operands[1] = const0_rtx;
27818334Speter  return AS2 (cmp%W0,%1,%0);
27952296Sobrien}"
28052296Sobrien  [(set_attr "type" "test")])
28118334Speter
28218334Speter(define_expand "tsthi"
28318334Speter  [(set (cc0)
28418334Speter	(match_operand:HI 0 "nonimmediate_operand" ""))]
28518334Speter  ""
28618334Speter  "
28718334Speter{
28818334Speter  i386_compare_gen = gen_tsthi_1;
28918334Speter  i386_compare_op0 = operands[0];
29050650Sobrien  i386_compare_op1 = const0_rtx;
29118334Speter  DONE;
29218334Speter}")
29318334Speter
29418334Speter(define_insn "tstqi_1"
29518334Speter  [(set (cc0)
29618334Speter	(match_operand:QI 0 "nonimmediate_operand" "qm"))]
29718334Speter  ""
29818334Speter  "*
29918334Speter{
30018334Speter  if (REG_P (operands[0]))
30118334Speter    return AS2 (test%B0,%0,%0);
30218334Speter
30318334Speter  operands[1] = const0_rtx;
30418334Speter  return AS2 (cmp%B0,%1,%0);
30552296Sobrien}"
30652296Sobrien  [(set_attr "type" "test")])
30718334Speter
30818334Speter(define_expand "tstqi"
30918334Speter  [(set (cc0)
31018334Speter	(match_operand:QI 0 "nonimmediate_operand" ""))]
31118334Speter  ""
31218334Speter  "
31318334Speter{
31418334Speter  i386_compare_gen = gen_tstqi_1;
31518334Speter  i386_compare_op0 = operands[0];
31650650Sobrien  i386_compare_op1 = const0_rtx;
31718334Speter  DONE;
31818334Speter}")
31918334Speter
32018334Speter(define_insn "tstsf_cc"
32118334Speter  [(set (cc0)
32218334Speter	(match_operand:SF 0 "register_operand" "f"))
32318334Speter   (clobber (match_scratch:HI 1 "=a"))]
32418334Speter  "TARGET_80387 && ! TARGET_IEEE_FP"
32518334Speter  "*
32618334Speter{
32718334Speter  if (! STACK_TOP_P (operands[0]))
32818334Speter    abort ();
32918334Speter
33018334Speter  output_asm_insn (\"ftst\", operands);
33118334Speter
33218334Speter  if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
33318334Speter    output_asm_insn (AS1 (fstp,%y0), operands);
33418334Speter
33518334Speter  return output_fp_cc0_set (insn);
33652296Sobrien}"
33752296Sobrien  [(set_attr "type" "test")])
33818334Speter
33918334Speter;; Don't generate tstsf if generating IEEE code, since the `ftst' opcode
34018334Speter;; isn't IEEE compliant.
34118334Speter
34218334Speter(define_expand "tstsf"
34318334Speter  [(parallel [(set (cc0)
34418334Speter		   (match_operand:SF 0 "register_operand" ""))
34518334Speter	      (clobber (match_scratch:HI 1 ""))])]
34618334Speter  "TARGET_80387 && ! TARGET_IEEE_FP"
34718334Speter  "
34818334Speter{
34918334Speter  i386_compare_gen = gen_tstsf_cc;
35018334Speter  i386_compare_op0 = operands[0];
35150650Sobrien  i386_compare_op1 = const0_rtx;
35218334Speter  DONE;
35318334Speter}")
35418334Speter
35518334Speter(define_insn "tstdf_cc"
35618334Speter  [(set (cc0)
35718334Speter	(match_operand:DF 0 "register_operand" "f"))
35818334Speter   (clobber (match_scratch:HI 1 "=a"))]
35918334Speter  "TARGET_80387 && ! TARGET_IEEE_FP"
36018334Speter  "*
36118334Speter{
36218334Speter  if (! STACK_TOP_P (operands[0]))
36318334Speter    abort ();
36418334Speter
36518334Speter  output_asm_insn (\"ftst\", operands);
36618334Speter
36718334Speter  if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
36818334Speter    output_asm_insn (AS1 (fstp,%y0), operands);
36918334Speter
37018334Speter  return output_fp_cc0_set (insn);
37152296Sobrien}"
37252296Sobrien  [(set_attr "type" "test")])
37318334Speter
37418334Speter;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode
37518334Speter;; isn't IEEE compliant.
37618334Speter
37718334Speter(define_expand "tstdf"
37818334Speter  [(parallel [(set (cc0)
37918334Speter		   (match_operand:DF 0 "register_operand" ""))
38018334Speter	      (clobber (match_scratch:HI 1 ""))])]
38118334Speter  "TARGET_80387 && ! TARGET_IEEE_FP"
38218334Speter  "
38318334Speter{
38418334Speter  i386_compare_gen = gen_tstdf_cc;
38518334Speter  i386_compare_op0 = operands[0];
38650650Sobrien  i386_compare_op1 = const0_rtx;
38718334Speter  DONE;
38818334Speter}")
38918334Speter
39018334Speter(define_insn "tstxf_cc"
39118334Speter  [(set (cc0)
39218334Speter	(match_operand:XF 0 "register_operand" "f"))
39318334Speter   (clobber (match_scratch:HI 1 "=a"))]
39418334Speter  "TARGET_80387 && ! TARGET_IEEE_FP"
39518334Speter  "*
39618334Speter{
39718334Speter  if (! STACK_TOP_P (operands[0]))
39818334Speter    abort ();
39918334Speter
40018334Speter  output_asm_insn (\"ftst\", operands);
40118334Speter
40218334Speter  if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
40318334Speter    output_asm_insn (AS1 (fstp,%y0), operands);
40418334Speter
40518334Speter  return output_fp_cc0_set (insn);
40652296Sobrien}"
40752296Sobrien  [(set_attr "type" "test")])
40818334Speter
40950650Sobrien;; Don't generate tstxf if generating IEEE code, since the `ftst' opcode
41018334Speter;; isn't IEEE compliant.
41118334Speter
41218334Speter(define_expand "tstxf"
41318334Speter  [(parallel [(set (cc0)
41418334Speter		   (match_operand:XF 0 "register_operand" ""))
41518334Speter	      (clobber (match_scratch:HI 1 ""))])]
41618334Speter  "TARGET_80387 && ! TARGET_IEEE_FP"
41718334Speter  "
41818334Speter{
41918334Speter  i386_compare_gen = gen_tstxf_cc;
42018334Speter  i386_compare_op0 = operands[0];
42150650Sobrien  i386_compare_op1 = const0_rtx;
42218334Speter  DONE;
42318334Speter}")
42418334Speter
42518334Speter;;- compare instructions.  See comments above tstM patterns about
42618334Speter;;  expansion of these insns.
42718334Speter
42818334Speter(define_insn "cmpsi_1"
42918334Speter  [(set (cc0)
43018334Speter	(compare (match_operand:SI 0 "nonimmediate_operand" "mr,r")
43118334Speter		 (match_operand:SI 1 "general_operand" "ri,mr")))]
43218334Speter  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
43352296Sobrien  "* return AS2 (cmp%L0,%1,%0);"
43452296Sobrien  [(set_attr "type" "compare")])
43518334Speter
43618334Speter(define_expand "cmpsi"
43718334Speter  [(set (cc0)
43818334Speter	(compare (match_operand:SI 0 "nonimmediate_operand" "")
43918334Speter		 (match_operand:SI 1 "general_operand" "")))]
44018334Speter  ""
44118334Speter  "
44218334Speter{
44318334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
44418334Speter    operands[0] = force_reg (SImode, operands[0]);
44518334Speter
44618334Speter  i386_compare_gen = gen_cmpsi_1;
44718334Speter  i386_compare_op0 = operands[0];
44818334Speter  i386_compare_op1 = operands[1];
44918334Speter  DONE;
45018334Speter}")
45118334Speter
45218334Speter(define_insn "cmphi_1"
45318334Speter  [(set (cc0)
45418334Speter	(compare (match_operand:HI 0 "nonimmediate_operand" "mr,r")
45518334Speter		 (match_operand:HI 1 "general_operand" "ri,mr")))]
45618334Speter  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
45752296Sobrien  "* return AS2 (cmp%W0,%1,%0);"
45852296Sobrien  [(set_attr "type" "compare")])
45918334Speter
46018334Speter(define_expand "cmphi"
46118334Speter  [(set (cc0)
46218334Speter	(compare (match_operand:HI 0 "nonimmediate_operand" "")
46318334Speter		 (match_operand:HI 1 "general_operand" "")))]
46418334Speter  ""
46518334Speter  "
46618334Speter{
46718334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
46818334Speter    operands[0] = force_reg (HImode, operands[0]);
46918334Speter
47018334Speter  i386_compare_gen = gen_cmphi_1;
47118334Speter  i386_compare_op0 = operands[0];
47218334Speter  i386_compare_op1 = operands[1];
47318334Speter  DONE;
47418334Speter}")
47518334Speter
47618334Speter(define_insn "cmpqi_1"
47718334Speter  [(set (cc0)
47818334Speter	(compare (match_operand:QI 0 "nonimmediate_operand" "q,mq")
47918334Speter		 (match_operand:QI 1 "general_operand" "qm,nq")))]
48018334Speter  "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM"
48152296Sobrien  "* return AS2 (cmp%B0,%1,%0);"
48252296Sobrien  [(set_attr "type" "compare")])
48318334Speter
48418334Speter(define_expand "cmpqi"
48518334Speter  [(set (cc0)
48618334Speter	(compare (match_operand:QI 0 "nonimmediate_operand" "")
48718334Speter		 (match_operand:QI 1 "general_operand" "")))]
48818334Speter  ""
48918334Speter  "
49018334Speter{
49118334Speter  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
49218334Speter    operands[0] = force_reg (QImode, operands[0]);
49318334Speter
49418334Speter  i386_compare_gen = gen_cmpqi_1;
49518334Speter  i386_compare_op0 = operands[0];
49618334Speter  i386_compare_op1 = operands[1];
49718334Speter  DONE;
49818334Speter}")
49918334Speter
50018334Speter;; These implement float point compares.  For each of DFmode and
50118334Speter;; SFmode, there is the normal insn, and an insn where the second operand
50218334Speter;; is converted to the desired mode.
50318334Speter
50418334Speter(define_insn ""
50518334Speter  [(set (cc0)
50618334Speter	(match_operator 2 "VOIDmode_compare_op"
50750650Sobrien			[(match_operand:XF 0 "register_operand" "f")
50850650Sobrien			 (match_operand:XF 1 "register_operand" "f")]))
50918334Speter   (clobber (match_scratch:HI 3 "=a"))]
51050650Sobrien  "TARGET_80387"
51152296Sobrien  "* return output_float_compare (insn, operands);"
51252296Sobrien  [(set_attr "type" "fcompare")])
51318334Speter
51418334Speter(define_insn ""
51518334Speter  [(set (cc0)
51618334Speter	(match_operator 2 "VOIDmode_compare_op"
51718334Speter			[(match_operand:XF 0 "register_operand" "f")
51818334Speter			 (float_extend:XF
51918334Speter			  (match_operand:DF 1 "nonimmediate_operand" "fm"))]))
52018334Speter   (clobber (match_scratch:HI 3 "=a"))]
52118334Speter  "TARGET_80387"
52252296Sobrien  "* return output_float_compare (insn, operands);"
52352296Sobrien  [(set_attr "type" "fcompare")])
52418334Speter
52518334Speter(define_insn ""
52618334Speter  [(set (cc0)
52718334Speter	(match_operator 2 "VOIDmode_compare_op"
52850650Sobrien			[(float_extend:XF
52950650Sobrien			  (match_operand:DF 0 "nonimmediate_operand" "fm"))
53050650Sobrien			 (match_operand:XF 1 "register_operand" "f")]))
53150650Sobrien   (clobber (match_scratch:HI 3 "=a"))]
53250650Sobrien  "TARGET_80387"
53352296Sobrien  "* return output_float_compare (insn, operands);"
53452296Sobrien  [(set_attr "type" "fcompare")])
53550650Sobrien
53650650Sobrien(define_insn ""
53750650Sobrien  [(set (cc0)
53850650Sobrien	(match_operator 2 "VOIDmode_compare_op"
53918334Speter			[(match_operand:XF 0 "register_operand" "f")
54018334Speter			 (float_extend:XF
54118334Speter			  (match_operand:SF 1 "nonimmediate_operand" "fm"))]))
54218334Speter   (clobber (match_scratch:HI 3 "=a"))]
54318334Speter  "TARGET_80387"
54452296Sobrien  "* return output_float_compare (insn, operands);"
54552296Sobrien  [(set_attr "type" "fcompare")])
54618334Speter
54718334Speter(define_insn ""
54818334Speter  [(set (cc0)
54950650Sobrien	(match_operator 2 "VOIDmode_compare_op"
55050650Sobrien			[(float_extend:XF
55150650Sobrien			  (match_operand:SF 0 "nonimmediate_operand" "fm"))
55250650Sobrien			 (match_operand:XF 1 "register_operand" "f")]))
55350650Sobrien   (clobber (match_scratch:HI 3 "=a"))]
55450650Sobrien  "TARGET_80387"
55552296Sobrien  "* return output_float_compare (insn, operands);"
55652296Sobrien  [(set_attr "type" "fcompare")])
55750650Sobrien
55850650Sobrien(define_insn ""
55950650Sobrien  [(set (cc0)
56018334Speter	(compare:CCFPEQ (match_operand:XF 0 "register_operand" "f")
56118334Speter			(match_operand:XF 1 "register_operand" "f")))
56218334Speter   (clobber (match_scratch:HI 2 "=a"))]
56318334Speter  "TARGET_80387"
56452296Sobrien  "* return output_float_compare (insn, operands);"
56552296Sobrien  [(set_attr "type" "fcompare")])
56618334Speter
56718334Speter(define_insn ""
56818334Speter  [(set (cc0)
56918334Speter	(match_operator 2 "VOIDmode_compare_op"
57018334Speter			[(match_operand:DF 0 "nonimmediate_operand" "f,fm")
57118334Speter			 (match_operand:DF 1 "nonimmediate_operand" "fm,f")]))
57218334Speter   (clobber (match_scratch:HI 3 "=a,a"))]
57318334Speter  "TARGET_80387
57418334Speter   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
57552296Sobrien  "* return output_float_compare (insn, operands);"
57652296Sobrien  [(set_attr "type" "fcompare")])
57718334Speter
57818334Speter(define_insn ""
57918334Speter  [(set (cc0)
58018334Speter	(match_operator 2 "VOIDmode_compare_op"
58118334Speter			[(match_operand:DF 0 "register_operand" "f")
58218334Speter			 (float_extend:DF
58318334Speter			  (match_operand:SF 1 "nonimmediate_operand" "fm"))]))
58418334Speter   (clobber (match_scratch:HI 3 "=a"))]
58518334Speter  "TARGET_80387"
58652296Sobrien  "* return output_float_compare (insn, operands);"
58752296Sobrien  [(set_attr "type" "fcompare")])
58818334Speter
58918334Speter(define_insn ""
59018334Speter  [(set (cc0)
59118334Speter	(match_operator 2 "VOIDmode_compare_op"
59218334Speter			[(float_extend:DF
59318334Speter			  (match_operand:SF 0 "nonimmediate_operand" "fm"))
59418334Speter			 (match_operand:DF 1 "register_operand" "f")]))
59518334Speter   (clobber (match_scratch:HI 3 "=a"))]
59618334Speter  "TARGET_80387"
59752296Sobrien  "* return output_float_compare (insn, operands);"
59852296Sobrien  [(set_attr "type" "fcompare")])
59918334Speter
60018334Speter(define_insn ""
60118334Speter  [(set (cc0)
60250650Sobrien	(match_operator 2 "VOIDmode_compare_op"
60350650Sobrien			[(float_extend:DF
60450650Sobrien			  (match_operand:SF 0 "register_operand" "f"))
60550650Sobrien			 (match_operand:DF 1 "nonimmediate_operand" "fm")]))
60650650Sobrien   (clobber (match_scratch:HI 3 "=a"))]
60750650Sobrien  "TARGET_80387"
60852296Sobrien  "* return output_float_compare (insn, operands);"
60952296Sobrien  [(set_attr "type" "fcompare")])
61050650Sobrien
61150650Sobrien(define_insn ""
61250650Sobrien  [(set (cc0)
61318334Speter	(compare:CCFPEQ (match_operand:DF 0 "register_operand" "f")
61418334Speter			(match_operand:DF 1 "register_operand" "f")))
61518334Speter   (clobber (match_scratch:HI 2 "=a"))]
61618334Speter  "TARGET_80387"
61752296Sobrien  "* return output_float_compare (insn, operands);"
61852296Sobrien  [(set_attr "type" "fcompare")])
61918334Speter
62018334Speter;; These two insns will never be generated by combine due to the mode of
62118334Speter;; the COMPARE.
62218334Speter;(define_insn ""
62318334Speter;  [(set (cc0)
62418334Speter;	(compare:CCFPEQ (match_operand:DF 0 "register_operand" "f")
62518334Speter;			(float_extend:DF
62618334Speter;			 (match_operand:SF 1 "register_operand" "f"))))
62718334Speter;   (clobber (match_scratch:HI 2 "=a"))]
62818334Speter;  "TARGET_80387"
62918334Speter;  "* return output_float_compare (insn, operands);")
63018334Speter;
63118334Speter;(define_insn ""
63218334Speter;  [(set (cc0)
63318334Speter;	(compare:CCFPEQ (float_extend:DF
63418334Speter;			 (match_operand:SF 0 "register_operand" "f"))
63518334Speter;			(match_operand:DF 1 "register_operand" "f")))
63618334Speter;   (clobber (match_scratch:HI 2 "=a"))]
63718334Speter;  "TARGET_80387"
63818334Speter;  "* return output_float_compare (insn, operands);")
63918334Speter
64052296Sobrien(define_insn "*cmpsf_cc_1"
64118334Speter  [(set (cc0)
64218334Speter	(match_operator 2 "VOIDmode_compare_op"
64318334Speter			[(match_operand:SF 0 "nonimmediate_operand" "f,fm")
64418334Speter			 (match_operand:SF 1 "nonimmediate_operand" "fm,f")]))
64518334Speter   (clobber (match_scratch:HI 3 "=a,a"))]
64618334Speter  "TARGET_80387
64718334Speter   && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
64852296Sobrien  "* return output_float_compare (insn, operands);"
64952296Sobrien  [(set_attr "type" "fcompare")])
65018334Speter
65118334Speter(define_insn ""
65218334Speter  [(set (cc0)
65318334Speter	(compare:CCFPEQ (match_operand:SF 0 "register_operand" "f")
65418334Speter			(match_operand:SF 1 "register_operand" "f")))
65518334Speter   (clobber (match_scratch:HI 2 "=a"))]
65618334Speter  "TARGET_80387"
65752296Sobrien  "* return output_float_compare (insn, operands);"
65852296Sobrien  [(set_attr "type" "fcompare")])
65918334Speter
66018334Speter(define_expand "cmpxf"
66118334Speter  [(set (cc0)
66218334Speter	(compare (match_operand:XF 0 "register_operand" "")
66350650Sobrien		 (match_operand:XF 1 "register_operand" "")))]
66418334Speter  "TARGET_80387"
66518334Speter  "
66618334Speter{
66718334Speter  i386_compare_gen = gen_cmpxf_cc;
66818334Speter  i386_compare_gen_eq = gen_cmpxf_ccfpeq;
66918334Speter  i386_compare_op0 = operands[0];
67018334Speter  i386_compare_op1 = operands[1];
67118334Speter  DONE;
67218334Speter}")
67318334Speter
67418334Speter(define_expand "cmpdf"
67518334Speter  [(set (cc0)
67618334Speter	(compare (match_operand:DF 0 "register_operand" "")
67750650Sobrien		 (match_operand:DF 1 "general_operand" "")))]
67818334Speter  "TARGET_80387"
67918334Speter  "
68018334Speter{
68118334Speter  i386_compare_gen = gen_cmpdf_cc;
68218334Speter  i386_compare_gen_eq = gen_cmpdf_ccfpeq;
68318334Speter  i386_compare_op0 = operands[0];
68450650Sobrien  i386_compare_op1 = (immediate_operand (operands[1], DFmode))
68550650Sobrien			? copy_to_mode_reg (DFmode, operands[1]) : operands[1];
68618334Speter  DONE;
68718334Speter}")
68818334Speter
68918334Speter(define_expand "cmpsf"
69018334Speter  [(set (cc0)
69118334Speter	(compare (match_operand:SF 0 "register_operand" "")
69250650Sobrien		 (match_operand:SF 1 "general_operand" "")))]
69318334Speter  "TARGET_80387"
69418334Speter  "
69518334Speter{
69618334Speter  i386_compare_gen = gen_cmpsf_cc;
69718334Speter  i386_compare_gen_eq = gen_cmpsf_ccfpeq;
69818334Speter  i386_compare_op0 = operands[0];
69950650Sobrien  i386_compare_op1 = (immediate_operand (operands[1], SFmode))
70050650Sobrien			? copy_to_mode_reg (SFmode, operands[1]) : operands[1];
70118334Speter  DONE;
70218334Speter}")
70318334Speter
70418334Speter(define_expand "cmpxf_cc"
70518334Speter  [(parallel [(set (cc0)
70618334Speter		   (compare (match_operand:XF 0 "register_operand" "")
70718334Speter			    (match_operand:XF 1 "register_operand" "")))
70818334Speter	      (clobber (match_scratch:HI 2 ""))])]
70918334Speter  "TARGET_80387"
71018334Speter  "")
71118334Speter
71218334Speter(define_expand "cmpxf_ccfpeq"
71318334Speter  [(parallel [(set (cc0)
71418334Speter		   (compare:CCFPEQ (match_operand:XF 0 "register_operand" "")
71518334Speter				   (match_operand:XF 1 "register_operand" "")))
71618334Speter	      (clobber (match_scratch:HI 2 ""))])]
71718334Speter  "TARGET_80387"
71850650Sobrien  "")
71918334Speter
72018334Speter(define_expand "cmpdf_cc"
72118334Speter  [(parallel [(set (cc0)
72218334Speter		   (compare (match_operand:DF 0 "register_operand" "")
72318334Speter			    (match_operand:DF 1 "register_operand" "")))
72418334Speter	      (clobber (match_scratch:HI 2 ""))])]
72518334Speter  "TARGET_80387"
72618334Speter  "")
72718334Speter
72818334Speter(define_expand "cmpdf_ccfpeq"
72918334Speter  [(parallel [(set (cc0)
73018334Speter		   (compare:CCFPEQ (match_operand:DF 0 "register_operand" "")
73118334Speter				   (match_operand:DF 1 "register_operand" "")))
73218334Speter	      (clobber (match_scratch:HI 2 ""))])]
73318334Speter  "TARGET_80387"
73418334Speter  "
73518334Speter{
73618334Speter  if (! register_operand (operands[1], DFmode))
73718334Speter    operands[1] = copy_to_mode_reg (DFmode, operands[1]);
73818334Speter}")
73918334Speter
74018334Speter(define_expand "cmpsf_cc"
74118334Speter  [(parallel [(set (cc0)
74218334Speter		   (compare (match_operand:SF 0 "register_operand" "")
74318334Speter			    (match_operand:SF 1 "register_operand" "")))
74418334Speter	      (clobber (match_scratch:HI 2 ""))])]
74518334Speter  "TARGET_80387"
74618334Speter  "")
74718334Speter
74818334Speter(define_expand "cmpsf_ccfpeq"
74918334Speter  [(parallel [(set (cc0)
75018334Speter		   (compare:CCFPEQ (match_operand:SF 0 "register_operand" "")
75118334Speter				   (match_operand:SF 1 "register_operand" "")))
75218334Speter	      (clobber (match_scratch:HI 2 ""))])]
75318334Speter  "TARGET_80387"
75418334Speter  "
75518334Speter{
75618334Speter  if (! register_operand (operands[1], SFmode))
75718334Speter    operands[1] = copy_to_mode_reg (SFmode, operands[1]);
75818334Speter}")
75918334Speter
76018334Speter;; logical compare
76118334Speter
76218334Speter(define_insn ""
76318334Speter  [(set (cc0)
76418334Speter	(and:SI (match_operand:SI 0 "general_operand" "%ro")
76550650Sobrien		(match_operand:SI 1 "nonmemory_operand" "ri")))]
76618334Speter  ""
76718334Speter  "*
76818334Speter{
76918334Speter  /* For small integers, we may actually use testb. */
77018334Speter  if (GET_CODE (operands[1]) == CONST_INT
77118334Speter      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
77252296Sobrien      && (! REG_P (operands[0]) || QI_REG_P (operands[0]))
77352296Sobrien      /* A Pentium test is pairable only with eax. Not with ah or al.  */
77452296Sobrien      && (! REG_P (operands[0]) || REGNO (operands[0]) || !TARGET_PENTIUM
77552296Sobrien          || optimize_size))
77618334Speter    {
77718334Speter      /* We may set the sign bit spuriously.  */
77818334Speter
77918334Speter      if ((INTVAL (operands[1]) & ~0xff) == 0)
78018334Speter        {
78118334Speter	  cc_status.flags |= CC_NOT_NEGATIVE;
78218334Speter	  return AS2 (test%B0,%1,%b0);
78318334Speter	}
78418334Speter
78518334Speter      if ((INTVAL (operands[1]) & ~0xff00) == 0)
78618334Speter        {
78718334Speter	  cc_status.flags |= CC_NOT_NEGATIVE;
78818334Speter	  operands[1] = GEN_INT (INTVAL (operands[1]) >> 8);
78918334Speter
79018334Speter	  if (QI_REG_P (operands[0]))
79118334Speter	    return AS2 (test%B0,%1,%h0);
79218334Speter	  else
79318334Speter	    {
79418334Speter	      operands[0] = adj_offsettable_operand (operands[0], 1);
79518334Speter	      return AS2 (test%B0,%1,%b0);
79618334Speter	    }
79718334Speter	}
79818334Speter
79918334Speter      if (GET_CODE (operands[0]) == MEM
80018334Speter	  && (INTVAL (operands[1]) & ~0xff0000) == 0)
80118334Speter        {
80218334Speter	  cc_status.flags |= CC_NOT_NEGATIVE;
80318334Speter	  operands[1] = GEN_INT (INTVAL (operands[1]) >> 16);
80418334Speter	  operands[0] = adj_offsettable_operand (operands[0], 2);
80518334Speter	  return AS2 (test%B0,%1,%b0);
80618334Speter	}
80718334Speter
80818334Speter      if (GET_CODE (operands[0]) == MEM
80918334Speter	  && (INTVAL (operands[1]) & ~0xff000000) == 0)
81018334Speter        {
81118334Speter	  operands[1] = GEN_INT ((INTVAL (operands[1]) >> 24) & 0xff);
81218334Speter	  operands[0] = adj_offsettable_operand (operands[0], 3);
81318334Speter	  return AS2 (test%B0,%1,%b0);
81418334Speter	}
81518334Speter    }
81618334Speter
81718334Speter  if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
81818334Speter    return AS2 (test%L0,%1,%0);
81918334Speter
82018334Speter  return AS2 (test%L1,%0,%1);
82152296Sobrien}"
82252296Sobrien  [(set_attr "type" "compare")])
82318334Speter
82418334Speter(define_insn ""
82518334Speter  [(set (cc0)
82618334Speter	(and:HI (match_operand:HI 0 "general_operand" "%ro")
82750650Sobrien		(match_operand:HI 1 "nonmemory_operand" "ri")))]
82818334Speter  ""
82918334Speter  "*
83018334Speter{
83118334Speter  if (GET_CODE (operands[1]) == CONST_INT
83218334Speter      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
83318334Speter      && (! REG_P (operands[0]) || QI_REG_P (operands[0])))
83418334Speter    {
83518334Speter      if ((INTVAL (operands[1]) & 0xff00) == 0)
83618334Speter	{
83718334Speter	  /* ??? This might not be necessary. */
83818334Speter	  if (INTVAL (operands[1]) & 0xffff0000)
83918334Speter	    operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff);
84018334Speter
84118334Speter	  /* We may set the sign bit spuriously.  */
84218334Speter	  cc_status.flags |= CC_NOT_NEGATIVE;
84318334Speter	  return AS2 (test%B0,%1,%b0);
84418334Speter	}
84518334Speter
84618334Speter      if ((INTVAL (operands[1]) & 0xff) == 0)
84718334Speter        {
84818334Speter	  operands[1] = GEN_INT ((INTVAL (operands[1]) >> 8) & 0xff);
84918334Speter
85018334Speter	  if (QI_REG_P (operands[0]))
85118334Speter	    return AS2 (test%B0,%1,%h0);
85218334Speter	  else
85318334Speter	    {
85418334Speter	      operands[0] = adj_offsettable_operand (operands[0], 1);
85518334Speter	      return AS2 (test%B0,%1,%b0);
85618334Speter	    }
85718334Speter	}
85818334Speter    }
85918334Speter
86050650Sobrien  /* use 32-bit test instruction if there are no sign issues */
86150650Sobrien  if (GET_CODE (operands[1]) == CONST_INT
86250650Sobrien      && !(INTVAL (operands[1]) & ~0x7fff)
86350650Sobrien      && i386_aligned_p (operands[0]))
86450650Sobrien    return AS2 (test%L0,%1,%k0);
86550650Sobrien
86618334Speter  if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
86718334Speter    return AS2 (test%W0,%1,%0);
86818334Speter
86918334Speter  return AS2 (test%W1,%0,%1);
87052296Sobrien}"
87152296Sobrien  [(set_attr "type" "compare")])
87218334Speter
87318334Speter(define_insn ""
87418334Speter  [(set (cc0)
87550650Sobrien	(and:QI (match_operand:QI 0 "nonimmediate_operand" "%qm")
87650650Sobrien		(match_operand:QI 1 "nonmemory_operand" "qi")))]
87718334Speter  ""
87818334Speter  "*
87918334Speter{
88018334Speter  if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
88118334Speter    return AS2 (test%B0,%1,%0);
88218334Speter
88318334Speter  return AS2 (test%B1,%0,%1);
88452296Sobrien}"
88552296Sobrien  [(set_attr "type" "compare")])
88618334Speter
88718334Speter;; move instructions.
88818334Speter;; There is one for each machine mode,
88918334Speter;; and each is preceded by a corresponding push-insn pattern
89018334Speter;; (since pushes are not general_operands on the 386).
89118334Speter
89218334Speter(define_insn ""
89318334Speter  [(set (match_operand:SI 0 "push_operand" "=<")
89450650Sobrien	(match_operand:SI 1 "nonmemory_operand" "rn"))]
89550650Sobrien  "flag_pic"
89652296Sobrien  "* return AS1 (push%L0,%1);"
89752296Sobrien  [(set_attr "memory" "store")])
89818334Speter
89918334Speter(define_insn ""
90018334Speter  [(set (match_operand:SI 0 "push_operand" "=<")
90118334Speter	(match_operand:SI 1 "nonmemory_operand" "ri"))]
90250650Sobrien  "!flag_pic"
90352296Sobrien  "* return AS1 (push%L0,%1);"
90452296Sobrien  [(set_attr "memory" "store")])
90518334Speter
90650650Sobrien;; On a 386, it is faster to push MEM directly.
90750650Sobrien
90818334Speter(define_insn ""
90918334Speter  [(set (match_operand:SI 0 "push_operand" "=<")
91050650Sobrien	(match_operand:SI 1 "memory_operand" "m"))]
91150650Sobrien  "TARGET_PUSH_MEMORY"
91252296Sobrien  "* return AS1 (push%L0,%1);"
91352296Sobrien  [(set_attr "type" "memory")
91452296Sobrien   (set_attr "memory" "load")])
91518334Speter
91618334Speter;; General case of fullword move.
91718334Speter
91818334Speter;; If generating PIC code and operands[1] is a symbolic CONST, emit a
91918334Speter;; move to get the address of the symbolic object from the GOT.
92018334Speter
92118334Speter(define_expand "movsi"
92218334Speter  [(set (match_operand:SI 0 "general_operand" "")
92318334Speter	(match_operand:SI 1 "general_operand" ""))]
92418334Speter  ""
92518334Speter  "
92618334Speter{
92718334Speter  extern int flag_pic;
92818334Speter
92918334Speter  if (flag_pic && SYMBOLIC_CONST (operands[1]))
93018334Speter    emit_pic_move (operands, SImode);
93118334Speter
93218334Speter  /* Don't generate memory->memory moves, go through a register */
93318334Speter  else if (TARGET_MOVE
93452296Sobrien	   && no_new_pseudos == 0
93518334Speter	   && GET_CODE (operands[0]) == MEM
93618334Speter	   && GET_CODE (operands[1]) == MEM)
93718334Speter    {
93818334Speter      operands[1] = force_reg (SImode, operands[1]);
93918334Speter    }
94018334Speter}")
94118334Speter
94218334Speter;; On i486, incl reg is faster than movl $1,reg.
94318334Speter
94418334Speter(define_insn ""
94552296Sobrien  [(set (match_operand:SI 0 "general_operand" "=g,r,r")
94652296Sobrien	(match_operand:SI 1 "general_operand" "rn,i,m"))]
94750650Sobrien  "((!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
94850650Sobrien    || (GET_CODE (operands[1]) != MEM))
94950650Sobrien   && flag_pic"
95018334Speter  "*
95118334Speter{
95218334Speter  rtx link;
95352296Sobrien
95452296Sobrien  /* K6: mov reg,0 is slightly faster than xor reg,reg but is 3 bytes
95552296Sobrien     longer.  */
95652296Sobrien  if ((ix86_cpu != PROCESSOR_K6 || optimize_size)
95752296Sobrien      && operands[1] == const0_rtx && REG_P (operands[0]))
95818334Speter    return AS2 (xor%L0,%0,%0);
95918334Speter
96018334Speter  if (operands[1] == const1_rtx
96152296Sobrien      /* PPRO and K6 prefer mov to inc to reduce dependencies.  */
96252296Sobrien      && (optimize_size || (int)ix86_cpu < (int)PROCESSOR_PENTIUMPRO)
96318334Speter      && (link = find_reg_note (insn, REG_WAS_0, 0))
96418334Speter      /* Make sure the insn that stored the 0 is still present.  */
96518334Speter      && ! INSN_DELETED_P (XEXP (link, 0))
96618334Speter      && GET_CODE (XEXP (link, 0)) != NOTE
96718334Speter      /* Make sure cross jumping didn't happen here.  */
96818334Speter      && no_labels_between_p (XEXP (link, 0), insn)
96918334Speter      /* Make sure the reg hasn't been clobbered.  */
97018334Speter      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
97118334Speter    /* Fastest way to change a 0 to a 1.  */
97218334Speter    return AS1 (inc%L0,%0);
97318334Speter
97450650Sobrien  if (SYMBOLIC_CONST (operands[1]))
97518334Speter    return AS2 (lea%L0,%a1,%0);
97618334Speter
97718334Speter  return AS2 (mov%L0,%1,%0);
97852296Sobrien}"
97952296Sobrien  [(set_attr "type" "integer,integer,memory")
98052296Sobrien   (set_attr "memory" "*,*,load")])
98118334Speter
98218334Speter(define_insn ""
98350650Sobrien  [(set (match_operand:SI 0 "general_operand" "=g,r")
98450650Sobrien	(match_operand:SI 1 "general_operand" "ri,m"))]
98550650Sobrien  "((!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
98650650Sobrien    || (GET_CODE (operands[1]) != MEM))
98750650Sobrien   && !flag_pic"
98850650Sobrien  "*
98950650Sobrien{
99050650Sobrien  rtx link;
99152296Sobrien
99252296Sobrien  /* Use of xor was disabled for AMD K6 as recommended by the Optimization
99352296Sobrien     Manual.  My test shows, that this generally hurts the performance, because
99452296Sobrien     mov is longer and takes longer to decode and decoding is the main
99552296Sobrien     bottleneck of K6 when executing GCC code.  */
99652296Sobrien
99750650Sobrien  if (operands[1] == const0_rtx && REG_P (operands[0]))
99850650Sobrien    return AS2 (xor%L0,%0,%0);
99918334Speter
100050650Sobrien  if (operands[1] == const1_rtx
100152296Sobrien      /* PPRO and K6 prefer mov to inc to reduce dependencies.  */
100252296Sobrien      && (optimize_size || (int)ix86_cpu < (int)PROCESSOR_PENTIUMPRO)
100350650Sobrien      && (link = find_reg_note (insn, REG_WAS_0, 0))
100450650Sobrien      /* Make sure the insn that stored the 0 is still present.  */
100550650Sobrien      && ! INSN_DELETED_P (XEXP (link, 0))
100650650Sobrien      && GET_CODE (XEXP (link, 0)) != NOTE
100750650Sobrien      /* Make sure cross jumping didn't happen here.  */
100850650Sobrien      && no_labels_between_p (XEXP (link, 0), insn)
100950650Sobrien      /* Make sure the reg hasn't been clobbered.  */
101050650Sobrien      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
101150650Sobrien    /* Fastest way to change a 0 to a 1.  */
101250650Sobrien    return AS1 (inc%L0,%0);
101350650Sobrien
101450650Sobrien  return AS2 (mov%L0,%1,%0);
101552296Sobrien}"
101652296Sobrien  [(set_attr "type" "integer,memory")
101752296Sobrien   (set_attr "memory" "*,load")])
101850650Sobrien
101918334Speter(define_insn ""
102018334Speter  [(set (match_operand:HI 0 "push_operand" "=<")
102118334Speter	(match_operand:HI 1 "nonmemory_operand" "ri"))]
102250650Sobrien  ""
102352296Sobrien  "* return AS1 (push%W0,%1);"
102452296Sobrien  [(set_attr "type" "memory")
102552296Sobrien   (set_attr "memory" "store")])
102618334Speter
102718334Speter(define_insn ""
102818334Speter  [(set (match_operand:HI 0 "push_operand" "=<")
102950650Sobrien	(match_operand:HI 1 "memory_operand" "m"))]
103050650Sobrien  "TARGET_PUSH_MEMORY"
103152296Sobrien  "* return AS1 (push%W0,%1);"
103252296Sobrien  [(set_attr "type" "memory")
103352296Sobrien   (set_attr "memory" "load")])
103418334Speter
103518334Speter;; On i486, an incl and movl are both faster than incw and movw.
103618334Speter
103718334Speter(define_expand "movhi"
103818334Speter  [(set (match_operand:HI 0 "general_operand" "")
103918334Speter	(match_operand:HI 1 "general_operand" ""))]
104018334Speter  ""
104118334Speter  "
104218334Speter{
104318334Speter  /* Don't generate memory->memory moves, go through a register */
104418334Speter  if (TARGET_MOVE
104552296Sobrien      && no_new_pseudos == 0
104618334Speter      && GET_CODE (operands[0]) == MEM
104718334Speter      && GET_CODE (operands[1]) == MEM)
104818334Speter    {
104918334Speter      operands[1] = force_reg (HImode, operands[1]);
105018334Speter    }
105118334Speter}")
105218334Speter
105318334Speter(define_insn ""
105418334Speter  [(set (match_operand:HI 0 "general_operand" "=g,r")
105518334Speter	(match_operand:HI 1 "general_operand" "ri,m"))]
105618334Speter  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
105718334Speter  "*
105818334Speter{
105918334Speter  rtx link;
106018334Speter  if (REG_P (operands[0]) && operands[1] == const0_rtx)
106118334Speter    return AS2 (xor%L0,%k0,%k0);
106218334Speter
106318334Speter  if (REG_P (operands[0]) && operands[1] == const1_rtx 
106452296Sobrien      /* PPRO and K6 prefer mov to inc to reduce dependencies.  */
106552296Sobrien      && (optimize_size || (int)ix86_cpu < (int)PROCESSOR_PENTIUMPRO)
106618334Speter      && (link = find_reg_note (insn, REG_WAS_0, 0))
106718334Speter      /* Make sure the insn that stored the 0 is still present.  */
106818334Speter      && ! INSN_DELETED_P (XEXP (link, 0))
106918334Speter      && GET_CODE (XEXP (link, 0)) != NOTE
107018334Speter      /* Make sure cross jumping didn't happen here.  */
107118334Speter      && no_labels_between_p (XEXP (link, 0), insn)
107218334Speter      /* Make sure the reg hasn't been clobbered.  */
107318334Speter      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
107418334Speter    /* Fastest way to change a 0 to a 1.  */
107518334Speter    return AS1 (inc%L0,%k0);
107618334Speter
107718334Speter  if (REG_P (operands[0]))
107818334Speter    {
107950650Sobrien      if (i386_aligned_p (operands[1]))
108050650Sobrien	{
108150650Sobrien	  operands[1] = i386_sext16_if_const (operands[1]);
108250650Sobrien	  return AS2 (mov%L0,%k1,%k0);
108350650Sobrien	}
108452296Sobrien      if (! TARGET_ZERO_EXTEND_WITH_AND)
108550650Sobrien	{
108650650Sobrien	  /* movzwl is faster than movw on the Pentium Pro,
108750650Sobrien	   * although not as fast as an aligned movl. */
108850650Sobrien#ifdef INTEL_SYNTAX
108950650Sobrien	  return AS2 (movzx,%1,%k0);
109050650Sobrien#else
109150650Sobrien	  return AS2 (movz%W0%L0,%1,%k0);
109250650Sobrien#endif
109350650Sobrien	}
109418334Speter    }
109518334Speter
109618334Speter  return AS2 (mov%W0,%1,%0);
109752296Sobrien}"
109852296Sobrien  [(set_attr "type" "integer,memory")
109952296Sobrien   (set_attr "memory" "*,load")])
110018334Speter
110118334Speter(define_expand "movstricthi"
110218334Speter  [(set (strict_low_part (match_operand:HI 0 "general_operand" ""))
110318334Speter	(match_operand:HI 1 "general_operand" ""))]
110418334Speter  ""
110518334Speter  "
110618334Speter{
110718334Speter  /* Don't generate memory->memory moves, go through a register */
110818334Speter  if (TARGET_MOVE
110952296Sobrien      && no_new_pseudos == 0
111018334Speter      && GET_CODE (operands[0]) == MEM
111118334Speter      && GET_CODE (operands[1]) == MEM)
111218334Speter    {
111318334Speter      operands[1] = force_reg (HImode, operands[1]);
111418334Speter    }
111518334Speter}")
111618334Speter
111718334Speter(define_insn ""
111818334Speter  [(set (strict_low_part (match_operand:HI 0 "general_operand" "+g,r"))
111918334Speter	(match_operand:HI 1 "general_operand" "ri,m"))]
112018334Speter  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
112118334Speter  "*
112218334Speter{
112318334Speter  rtx link;
112452296Sobrien
112552296Sobrien  /* Use of xor was disabled for AMD K6 as recommended by the Optimization
112652296Sobrien     Manual.  My test shows, that this generally hurts the performance, because
112752296Sobrien     mov is longer and takes longer to decode and decoding is the main
112852296Sobrien     bottleneck of K6 when executing GCC code.  */
112952296Sobrien
113018334Speter  if (operands[1] == const0_rtx && REG_P (operands[0]))
113118334Speter    return AS2 (xor%W0,%0,%0);
113218334Speter
113318334Speter  if (operands[1] == const1_rtx
113452296Sobrien      /* PPRO and K6 prefer mov to inc to reduce dependencies.  */
113552296Sobrien      && (optimize_size || (int)ix86_cpu < (int)PROCESSOR_PENTIUMPRO)
113618334Speter      && (link = find_reg_note (insn, REG_WAS_0, 0))
113718334Speter      /* Make sure the insn that stored the 0 is still present.  */
113818334Speter      && ! INSN_DELETED_P (XEXP (link, 0))
113918334Speter      && GET_CODE (XEXP (link, 0)) != NOTE
114018334Speter      /* Make sure cross jumping didn't happen here.  */
114118334Speter      && no_labels_between_p (XEXP (link, 0), insn)
114218334Speter      /* Make sure the reg hasn't been clobbered.  */
114318334Speter      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
114418334Speter    /* Fastest way to change a 0 to a 1.  */
114518334Speter    return AS1 (inc%W0,%0);
114618334Speter
114718334Speter  return AS2 (mov%W0,%1,%0);
114852296Sobrien}"
114952296Sobrien  [(set_attr "type" "integer,memory")])
115018334Speter
115118334Speter;; emit_push_insn when it calls move_by_pieces
115218334Speter;; requires an insn to "push a byte".
115318334Speter;; But actually we use pushw, which has the effect of rounding
115418334Speter;; the amount pushed up to a halfword.
115518334Speter(define_insn ""
115618334Speter  [(set (match_operand:QI 0 "push_operand" "=<")
115750650Sobrien	(match_operand:QI 1 "const_int_operand" "n"))]
115818334Speter  ""
115950650Sobrien  "* return AS1(push%W0,%1);")
116018334Speter
116118334Speter(define_insn ""
116218334Speter  [(set (match_operand:QI 0 "push_operand" "=<")
116318334Speter	(match_operand:QI 1 "register_operand" "q"))]
116450650Sobrien  ""
116518334Speter  "*
116618334Speter{
116750650Sobrien  operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
116818334Speter  return AS1 (push%W0,%1);
116918334Speter}")
117018334Speter
117118334Speter;; On i486, incb reg is faster than movb $1,reg.
117218334Speter
117318334Speter;; ??? Do a recognizer for zero_extract that looks just like this, but reads
117418334Speter;; or writes %ah, %bh, %ch, %dh.
117518334Speter
117618334Speter(define_expand "movqi"
117718334Speter  [(set (match_operand:QI 0 "general_operand" "")
117818334Speter	(match_operand:QI 1 "general_operand" ""))]
117918334Speter  ""
118018334Speter  "
118118334Speter{
118218334Speter  /* Don't generate memory->memory moves, go through a register */
118318334Speter  if (TARGET_MOVE
118452296Sobrien      && no_new_pseudos == 0
118518334Speter      && GET_CODE (operands[0]) == MEM
118618334Speter      && GET_CODE (operands[1]) == MEM)
118718334Speter    {
118818334Speter      operands[1] = force_reg (QImode, operands[1]);
118918334Speter    }
119018334Speter}")
119118334Speter
119218334Speter(define_insn ""
119350650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,*r,qm")
119450650Sobrien	(match_operand:QI 1 "general_operand" "*g,*rn,qn"))]
119518334Speter  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
119618334Speter  "*
119718334Speter{
119818334Speter  rtx link;
119918334Speter
120052296Sobrien  /* movb $0,reg8 is 2 bytes, the same as xorl reg8,reg8.
120152296Sobrien     It is at least as fast as xor on any processor except a Pentium. */
120252296Sobrien
120318334Speter  if (operands[1] == const1_rtx
120452296Sobrien      && TARGET_PENTIUM
120518334Speter      && (link = find_reg_note (insn, REG_WAS_0, 0))
120618334Speter      /* Make sure the insn that stored the 0 is still present.  */
120718334Speter      && ! INSN_DELETED_P (XEXP (link, 0))
120818334Speter      && GET_CODE (XEXP (link, 0)) != NOTE
120918334Speter      /* Make sure cross jumping didn't happen here.  */
121018334Speter      && no_labels_between_p (XEXP (link, 0), insn)
121118334Speter      /* Make sure the reg hasn't been clobbered.  */
121218334Speter      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
121350650Sobrien    {
121450650Sobrien      /* Fastest way to change a 0 to a 1.
121550650Sobrien	 If inc%B0 isn't allowed, use inc%L0.  */
121650650Sobrien      if (NON_QI_REG_P (operands[0]))
121750650Sobrien	return AS1 (inc%L0,%k0);
121850650Sobrien      else
121950650Sobrien	return AS1 (inc%B0,%0);
122050650Sobrien    }
122118334Speter
122218334Speter  /* If mov%B0 isn't allowed for one of these regs, use mov%L0.  */
122318334Speter  if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1]))
122418334Speter    return (AS2 (mov%L0,%k1,%k0));
122518334Speter
122618334Speter  return (AS2 (mov%B0,%1,%0));
122718334Speter}")
122818334Speter
122918334Speter;; If it becomes necessary to support movstrictqi into %esi or %edi,
123018334Speter;; use the insn sequence:
123118334Speter;;
123218334Speter;;	shrdl $8,srcreg,dstreg
123318334Speter;;	rorl $24,dstreg
123418334Speter;;
123518334Speter;; If operands[1] is a constant, then an andl/orl sequence would be
123618334Speter;; faster.
123718334Speter
123818334Speter(define_expand "movstrictqi"
123918334Speter  [(set (strict_low_part (match_operand:QI 0 "general_operand" ""))
124018334Speter	(match_operand:QI 1 "general_operand" ""))]
124118334Speter  ""
124218334Speter  "
124318334Speter{
124418334Speter  /* Don't generate memory->memory moves, go through a register */
124518334Speter  if (TARGET_MOVE
124652296Sobrien      && no_new_pseudos == 0
124718334Speter      && GET_CODE (operands[0]) == MEM
124818334Speter      && GET_CODE (operands[1]) == MEM)
124918334Speter    {
125018334Speter      operands[1] = force_reg (QImode, operands[1]);
125118334Speter    }
125218334Speter}")
125318334Speter
125418334Speter(define_insn ""
125550650Sobrien  [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q"))
125618334Speter	(match_operand:QI 1 "general_operand" "*qn,m"))]
125718334Speter  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
125818334Speter  "*
125918334Speter{
126018334Speter  rtx link;
126118334Speter
126252296Sobrien  /* movb $0,reg8 is 2 bytes, the same as xorl reg8,reg8.  */
126352296Sobrien
126418334Speter  if (operands[1] == const1_rtx
126552296Sobrien      && TARGET_PENTIUM
126650650Sobrien      && ! NON_QI_REG_P (operands[0])
126718334Speter      && (link = find_reg_note (insn, REG_WAS_0, 0))
126818334Speter      /* Make sure the insn that stored the 0 is still present.  */
126918334Speter      && ! INSN_DELETED_P (XEXP (link, 0))
127018334Speter      && GET_CODE (XEXP (link, 0)) != NOTE
127118334Speter      /* Make sure cross jumping didn't happen here.  */
127218334Speter      && no_labels_between_p (XEXP (link, 0), insn)
127318334Speter      /* Make sure the reg hasn't been clobbered.  */
127418334Speter      && ! reg_set_between_p (operands[0], XEXP (link, 0), insn))
127518334Speter    /* Fastest way to change a 0 to a 1.  */
127618334Speter    return AS1 (inc%B0,%0);
127718334Speter
127818334Speter  /* If mov%B0 isn't allowed for one of these regs, use mov%L0.  */
127918334Speter  if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1]))
128018334Speter    {
128118334Speter      abort ();
128218334Speter      return (AS2 (mov%L0,%k1,%k0));
128318334Speter    }
128418334Speter
128518334Speter  return AS2 (mov%B0,%1,%0);
128618334Speter}")
128718334Speter
128850650Sobrien(define_insn "movsf_push"
128918334Speter  [(set (match_operand:SF 0 "push_operand" "=<,<")
129050650Sobrien	(match_operand:SF 1 "general_operand" "*rfF,m"))]
129152296Sobrien  "TARGET_PUSH_MEMORY || GET_CODE (operands[1]) != MEM 
129252296Sobrien   || reload_in_progress || reload_completed"
129318334Speter  "*
129418334Speter{
129518334Speter  if (STACK_REG_P (operands[1]))
129618334Speter    {
129718334Speter      rtx xops[3];
129818334Speter
129918334Speter      if (! STACK_TOP_P (operands[1]))
130018334Speter        abort ();
130118334Speter
130218334Speter      xops[0] = AT_SP (SFmode);
130318334Speter      xops[1] = GEN_INT (4);
130418334Speter      xops[2] = stack_pointer_rtx;
130518334Speter
130618334Speter      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
130718334Speter
130818334Speter      if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
130918334Speter        output_asm_insn (AS1 (fstp%S0,%0), xops);
131018334Speter      else
131118334Speter        output_asm_insn (AS1 (fst%S0,%0), xops);
131250650Sobrien
131318334Speter      RET;
131418334Speter    }
131550650Sobrien
131650650Sobrien  return AS1 (push%L0,%1);
131718334Speter}")
131818334Speter
131952296Sobrien(define_split
132052296Sobrien  [(set (match_operand:SF 0 "push_operand" "")
132152296Sobrien        (match_operand:SF 1 "general_operand" ""))]
132252296Sobrien  "reload_completed && STACK_REG_P (operands[1])"
132352296Sobrien  [(set (reg:SI 7)
132452296Sobrien        (minus:SI (reg:SI 7) (const_int 4)))
132552296Sobrien   (set (mem:SF (reg:SI 7))
132652296Sobrien        (match_dup 1))]
132752296Sobrien  "")
132850650Sobrien
132950650Sobrien(define_expand "movsf"
133050650Sobrien  [(set (match_operand:SF 0 "general_operand" "")
133150650Sobrien	(match_operand:SF 1 "general_operand" ""))]
133218334Speter  ""
133350650Sobrien  "
133418334Speter{
133550650Sobrien  /* Don't generate memory->memory moves, go through a register */
133650650Sobrien  if (TARGET_MOVE
133752296Sobrien      && no_new_pseudos == 0
133850650Sobrien      && GET_CODE (operands[0]) == MEM
133950650Sobrien      && GET_CODE (operands[1]) == MEM)
134018334Speter    {
134150650Sobrien      operands[1] = force_reg (SFmode, operands[1]);
134250650Sobrien    }
134318334Speter
134450650Sobrien  /* If we are loading a floating point constant that isn't 0 or 1
134552296Sobrien     into a register, force the value to memory now, since we'll 
134652296Sobrien     get better code out the back end.  */
134750650Sobrien  else if ((reload_in_progress | reload_completed) == 0
134852296Sobrien	   && GET_CODE (operands[0]) != MEM
134952296Sobrien	   && GET_CODE (operands[1]) == CONST_DOUBLE
135052296Sobrien	   && !standard_80387_constant_p (operands[1]))
135150650Sobrien    {
135252296Sobrien      operands[1] = validize_mem (force_const_mem (SFmode, operands[1]));
135318334Speter    }
135418334Speter}")
135518334Speter
135618334Speter;; For the purposes of regclass, prefer FLOAT_REGS.
135750650Sobrien(define_insn ""
135852296Sobrien  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,!*r,!m")
135952296Sobrien	(match_operand:SF 1 "general_operand" "fmG,f,*rmF,*rF"))]
136018334Speter  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
136118334Speter  "*
136218334Speter{
136318334Speter  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
136418334Speter
136518334Speter  /* First handle a `pop' insn or a `fld %st(0)' */
136618334Speter
136718334Speter  if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
136818334Speter    {
136918334Speter      if (stack_top_dies)
137018334Speter	return AS1 (fstp,%y0);
137118334Speter      else
137218334Speter        return AS1 (fld,%y0);
137318334Speter    }
137418334Speter
137518334Speter  /* Handle other kinds of writes from the 387 */
137618334Speter
137718334Speter  if (STACK_TOP_P (operands[1]))
137818334Speter    {
137918334Speter      if (stack_top_dies)
138018334Speter	return AS1 (fstp%z0,%y0);
138118334Speter      else
138218334Speter        return AS1 (fst%z0,%y0);
138318334Speter    }
138418334Speter
138518334Speter  /* Handle other kinds of reads to the 387 */
138618334Speter
138718334Speter  if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
138818334Speter    return output_move_const_single (operands);
138918334Speter
139018334Speter  if (STACK_TOP_P (operands[0]))
139118334Speter    return AS1 (fld%z1,%y1);
139218334Speter
139318334Speter  /* Handle all SFmode moves not involving the 387 */
139418334Speter
139518334Speter  return singlemove_string (operands);
139650650Sobrien}"
139750650Sobrien  [(set_attr "type" "fld")])
139818334Speter
139950650Sobrien
140018334Speter(define_insn "swapsf"
140118334Speter  [(set (match_operand:SF 0 "register_operand" "f")
140218334Speter	(match_operand:SF 1 "register_operand" "f"))
140318334Speter   (set (match_dup 1)
140418334Speter	(match_dup 0))]
140518334Speter  ""
140618334Speter  "*
140718334Speter{
140818334Speter  if (STACK_TOP_P (operands[0]))
140918334Speter    return AS1 (fxch,%1);
141018334Speter  else
141118334Speter    return AS1 (fxch,%0);
141218334Speter}")
141318334Speter
141452296Sobrien
141550650Sobrien(define_insn "movdf_push"
141618334Speter  [(set (match_operand:DF 0 "push_operand" "=<,<")
141750650Sobrien	(match_operand:DF 1 "general_operand" "*rfF,o"))]
141852296Sobrien  "TARGET_PUSH_MEMORY || GET_CODE (operands[1]) != MEM 
141952296Sobrien   || reload_in_progress || reload_completed"
142018334Speter  "*
142118334Speter{
142218334Speter  if (STACK_REG_P (operands[1]))
142318334Speter    {
142418334Speter      rtx xops[3];
142518334Speter
142650650Sobrien      xops[0] = AT_SP (DFmode);
142718334Speter      xops[1] = GEN_INT (8);
142818334Speter      xops[2] = stack_pointer_rtx;
142918334Speter
143018334Speter      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
143118334Speter
143218334Speter      if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
143318334Speter        output_asm_insn (AS1 (fstp%Q0,%0), xops);
143418334Speter      else
143518334Speter        output_asm_insn (AS1 (fst%Q0,%0), xops);
143618334Speter
143718334Speter      RET;
143818334Speter    }
143950650Sobrien
144050650Sobrien  if (which_alternative == 1)
144150650Sobrien    return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 0, 0);
144250650Sobrien
144350650Sobrien  return output_move_double (operands);
144418334Speter}")
144518334Speter
144652296Sobrien(define_split
144752296Sobrien  [(set (match_operand:DF 0 "push_operand" "")
144852296Sobrien        (match_operand:DF 1 "register_operand" ""))]
144952296Sobrien  "reload_completed && STACK_REG_P (operands[1])"
145052296Sobrien  [(set (reg:SI 7)
145152296Sobrien        (minus:SI (reg:SI 7) (const_int 8)))
145252296Sobrien   (set (mem:DF (reg:SI 7))
145352296Sobrien        (match_dup 1))]
145452296Sobrien  "")
145550650Sobrien
145650650Sobrien(define_expand "movdf"
145750650Sobrien  [(set (match_operand:DF 0 "general_operand" "")
145850650Sobrien	(match_operand:DF 1 "general_operand" ""))]
145918334Speter  ""
146050650Sobrien  "
146118334Speter{
146250650Sobrien  /* Don't generate memory->memory moves, go through a register */
146350650Sobrien  if (TARGET_MOVE
146452296Sobrien      && no_new_pseudos == 0
146550650Sobrien      && GET_CODE (operands[0]) == MEM
146650650Sobrien      && GET_CODE (operands[1]) == MEM)
146718334Speter    {
146850650Sobrien      operands[1] = force_reg (DFmode, operands[1]);
146950650Sobrien    }
147018334Speter
147150650Sobrien  /* If we are loading a floating point constant that isn't 0 or 1 into a
147250650Sobrien     register, indicate we need the pic register loaded.  This could be
147350650Sobrien     optimized into stores of constants if the target eventually moves to
147450650Sobrien     memory, but better safe than sorry.  */
147550650Sobrien  else if ((reload_in_progress | reload_completed) == 0
147652296Sobrien	   && GET_CODE (operands[0]) != MEM
147752296Sobrien	   && GET_CODE (operands[1]) == CONST_DOUBLE
147852296Sobrien	   && !standard_80387_constant_p (operands[1]))
147950650Sobrien    {
148052296Sobrien      operands[1] = validize_mem (force_const_mem (DFmode, operands[1]));
148118334Speter    }
148218334Speter}")
148318334Speter
148418334Speter;; For the purposes of regclass, prefer FLOAT_REGS.
148550650Sobrien(define_insn ""
148652296Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,!*r,!o")
148752296Sobrien	(match_operand:DF 1 "general_operand" "fmG,f,*roF,*rF"))]
148850650Sobrien  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
148950650Sobrien   || (GET_CODE (operands[1]) != MEM)"
149018334Speter  "*
149118334Speter{
149218334Speter  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
149318334Speter
149418334Speter  /* First handle a `pop' insn or a `fld %st(0)' */
149518334Speter
149618334Speter  if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
149718334Speter    {
149818334Speter      if (stack_top_dies)
149918334Speter	return AS1 (fstp,%y0);
150018334Speter      else
150118334Speter        return AS1 (fld,%y0);
150218334Speter    }
150318334Speter
150418334Speter  /* Handle other kinds of writes from the 387 */
150518334Speter
150618334Speter  if (STACK_TOP_P (operands[1]))
150718334Speter    {
150818334Speter      if (stack_top_dies)
150918334Speter	return AS1 (fstp%z0,%y0);
151018334Speter      else
151118334Speter        return AS1 (fst%z0,%y0);
151218334Speter    }
151318334Speter
151418334Speter  /* Handle other kinds of reads to the 387 */
151518334Speter
151618334Speter  if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
151718334Speter    return output_move_const_single (operands);
151818334Speter
151918334Speter  if (STACK_TOP_P (operands[0]))
152018334Speter    return AS1 (fld%z1,%y1);
152118334Speter
152218334Speter  /* Handle all DFmode moves not involving the 387 */
152318334Speter
152418334Speter  return output_move_double (operands);
152550650Sobrien}"
152650650Sobrien  [(set_attr "type" "fld")])
152718334Speter
152850650Sobrien
152950650Sobrien
153018334Speter(define_insn "swapdf"
153118334Speter  [(set (match_operand:DF 0 "register_operand" "f")
153218334Speter	(match_operand:DF 1 "register_operand" "f"))
153318334Speter   (set (match_dup 1)
153418334Speter	(match_dup 0))]
153518334Speter  ""
153618334Speter  "*
153718334Speter{
153818334Speter  if (STACK_TOP_P (operands[0]))
153918334Speter    return AS1 (fxch,%1);
154018334Speter  else
154118334Speter    return AS1 (fxch,%0);
154218334Speter}")
154318334Speter
154450650Sobrien(define_insn "movxf_push"
154518334Speter  [(set (match_operand:XF 0 "push_operand" "=<,<")
154650650Sobrien 	(match_operand:XF 1 "general_operand" "*rfF,o"))]
154752296Sobrien  "TARGET_PUSH_MEMORY || GET_CODE (operands[1]) != MEM 
154852296Sobrien   || reload_in_progress || reload_completed"
154918334Speter  "*
155018334Speter{
155118334Speter  if (STACK_REG_P (operands[1]))
155218334Speter    {
155318334Speter      rtx xops[3];
155418334Speter
155550650Sobrien      xops[0] = AT_SP (XFmode);
155618334Speter      xops[1] = GEN_INT (12);
155718334Speter      xops[2] = stack_pointer_rtx;
155818334Speter
155918334Speter      output_asm_insn (AS2 (sub%L2,%1,%2), xops);
156050650Sobrien
156118334Speter      output_asm_insn (AS1 (fstp%T0,%0), xops);
156218334Speter      if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
156318334Speter	output_asm_insn (AS1 (fld%T0,%0), xops);
156418334Speter
156518334Speter      RET;
156618334Speter    }
156750650Sobrien
156850650Sobrien  if (which_alternative == 1)
156950650Sobrien    return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 0, 0);
157050650Sobrien
157150650Sobrien  return output_move_double (operands);
157218334Speter }")
157318334Speter
157452296Sobrien(define_split
157552296Sobrien  [(set (match_operand:XF 0 "push_operand" "")
157652296Sobrien        (match_operand:XF 1 "register_operand" ""))]
157752296Sobrien  "reload_completed && STACK_REG_P (operands[1])"
157852296Sobrien  [(set (reg:SI 7)
157952296Sobrien        (minus:SI (reg:SI 7) (const_int 12)))
158052296Sobrien   (set (mem:XF (reg:SI 7))
158152296Sobrien        (match_dup 1))]
158252296Sobrien  "")
158350650Sobrien
158450650Sobrien(define_expand "movxf"
158550650Sobrien  [(set (match_operand:XF 0 "general_operand" "")
158650650Sobrien	(match_operand:XF 1 "general_operand" ""))]
158718334Speter  ""
158850650Sobrien  "
158918334Speter{
159050650Sobrien  /* Don't generate memory->memory moves, go through a register */
159150650Sobrien  if (TARGET_MOVE
159252296Sobrien      && no_new_pseudos == 0
159350650Sobrien      && GET_CODE (operands[0]) == MEM
159450650Sobrien      && GET_CODE (operands[1]) == MEM)
159518334Speter    {
159650650Sobrien      operands[1] = force_reg (XFmode, operands[1]);
159750650Sobrien    }
159818334Speter
159950650Sobrien  /* If we are loading a floating point constant that isn't 0 or 1
160050650Sobrien     into a register, indicate we need the pic register loaded.  This could
160150650Sobrien     be optimized into stores of constants if the target eventually moves
160250650Sobrien     to memory, but better safe than sorry.  */
160350650Sobrien  else if ((reload_in_progress | reload_completed) == 0
160452296Sobrien	   && GET_CODE (operands[0]) != MEM
160552296Sobrien	   && GET_CODE (operands[1]) == CONST_DOUBLE
160652296Sobrien	   && !standard_80387_constant_p (operands[1]))
160750650Sobrien    {
160852296Sobrien      operands[1] = validize_mem (force_const_mem (XFmode, operands[1]));
160918334Speter    }
161018334Speter}")
161118334Speter
161218334Speter
161350650Sobrien(define_insn ""
161452296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,!*r,!o")
161552296Sobrien	(match_operand:XF 1 "general_operand" "fmG,f,*roF,*rF"))]
161650650Sobrien  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
161750650Sobrien   || (GET_CODE (operands[1]) != MEM)"
161818334Speter  "*
161918334Speter{
162018334Speter  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
162118334Speter
162218334Speter  /* First handle a `pop' insn or a `fld %st(0)' */
162318334Speter
162418334Speter  if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1]))
162518334Speter    {
162618334Speter      if (stack_top_dies)
162718334Speter	return AS1 (fstp,%y0);
162818334Speter      else
162918334Speter        return AS1 (fld,%y0);
163018334Speter    }
163118334Speter
163218334Speter  /* Handle other kinds of writes from the 387 */
163318334Speter
163418334Speter  if (STACK_TOP_P (operands[1]))
163518334Speter    {
163618334Speter      output_asm_insn (AS1 (fstp%z0,%y0), operands);
163718334Speter      if (! stack_top_dies)
163818334Speter	return AS1 (fld%z0,%y0);
163918334Speter
164018334Speter      RET;
164118334Speter    }
164218334Speter
164318334Speter  /* Handle other kinds of reads to the 387 */
164418334Speter
164518334Speter  if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE)
164618334Speter    return output_move_const_single (operands);
164718334Speter
164818334Speter  if (STACK_TOP_P (operands[0]))
164918334Speter       return AS1 (fld%z1,%y1);
165018334Speter
165118334Speter  /* Handle all XFmode moves not involving the 387 */
165218334Speter
165318334Speter  return output_move_double (operands);
165418334Speter}")
165518334Speter
165650650Sobrien(define_insn "swapxf" 
165718334Speter  [(set (match_operand:XF 0 "register_operand" "f")
165818334Speter	(match_operand:XF 1 "register_operand" "f"))
165918334Speter   (set (match_dup 1)
166018334Speter	(match_dup 0))]
166118334Speter  ""
166218334Speter  "*
166318334Speter{
166418334Speter  if (STACK_TOP_P (operands[0]))
166518334Speter    return AS1 (fxch,%1);
166618334Speter  else
166718334Speter    return AS1 (fxch,%0);
166818334Speter}")
166918334Speter
167018334Speter(define_insn ""
167150650Sobrien  [(set (match_operand:DI 0 "push_operand" "=<")
167250650Sobrien	(match_operand:DI 1 "general_operand" "riF"))]
167318334Speter  ""
167450650Sobrien  "* return output_move_double (operands);")
167518334Speter
167650650Sobrien(define_insn ""
167750650Sobrien  [(set (match_operand:DI 0 "push_operand" "=<")
167850650Sobrien	(match_operand:DI 1 "memory_operand" "o"))]
167950650Sobrien  "TARGET_PUSH_MEMORY"
168050650Sobrien  "* return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode),0,0);")
168118334Speter
168250650Sobrien(define_expand "movdi"
168350650Sobrien  [(set (match_operand:DI 0 "general_operand" "")
168450650Sobrien	(match_operand:DI 1 "general_operand" ""))]
168518334Speter  ""
168650650Sobrien  "
168718334Speter{
168850650Sobrien  /* Don't generate memory->memory moves, go through a register */
168950650Sobrien  if (TARGET_MOVE
169052296Sobrien      && no_new_pseudos == 0
169150650Sobrien      && GET_CODE (operands[0]) == MEM
169250650Sobrien      && GET_CODE (operands[1]) == MEM)
169350650Sobrien    {
169450650Sobrien      operands[1] = force_reg (DImode, operands[1]);
169550650Sobrien    }
169618334Speter}")
169718334Speter
169850650Sobrien(define_insn ""
169950650Sobrien  [(set (match_operand:DI 0 "general_operand" "=g,r")
170050650Sobrien	(match_operand:DI 1 "general_operand" "riF,m"))]
170150650Sobrien  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
170250650Sobrien   || (GET_CODE (operands[1]) != MEM)"
170352296Sobrien  "* return output_move_double (operands);"
170452296Sobrien  [(set_attr "type" "integer,memory")
170552296Sobrien   (set_attr "memory" "*,load")])
170650650Sobrien
170752296Sobrien(define_split
170852296Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
170952296Sobrien	(match_operand:DI 1 "general_operand" ""))]
171052296Sobrien  "reload_completed
171152296Sobrien   && (offsettable_memref_p (operands[0])
171252296Sobrien       || nonmemory_operand (operands[0], DImode))
171352296Sobrien   && (offsettable_memref_p (operands[1])
171452296Sobrien       || nonmemory_operand (operands[1], DImode))
171552296Sobrien   && (! reg_overlap_mentioned_p (gen_lowpart (SImode, operands[0]),
171652296Sobrien				  operands[1])
171752296Sobrien       || ! reg_overlap_mentioned_p (gen_highpart (SImode, operands[0]),
171852296Sobrien				     operands[1]))"
171952296Sobrien  [(set (match_dup 2)
172052296Sobrien	(match_dup 4))
172152296Sobrien   (set (match_dup 3)
172252296Sobrien	(match_dup 5))]
172352296Sobrien  "
172452296Sobrien{
172552296Sobrien  split_di (&operands[0], 1, &operands[2], &operands[3]);
172652296Sobrien  split_di (&operands[1], 1, &operands[4], &operands[5]);
172752296Sobrien
172852296Sobrien  if (reg_overlap_mentioned_p (operands[2], operands[1]))
172952296Sobrien    {
173052296Sobrien    rtx tmp;
173152296Sobrien
173252296Sobrien    tmp = operands[2];
173352296Sobrien    operands[2] = operands[3];
173452296Sobrien    operands[3] = tmp;
173552296Sobrien
173652296Sobrien    tmp = operands[4];
173752296Sobrien    operands[4] = operands[5];
173852296Sobrien    operands[5] = tmp;
173952296Sobrien    }
174052296Sobrien}")
174118334Speter
174218334Speter;;- conversion instructions
174318334Speter;;- NONE
174418334Speter
174518334Speter;;- zero extension instructions
174618334Speter;; See comments by `andsi' for when andl is faster than movzx.
174718334Speter
174852296Sobrien(define_expand "zero_extendhisi2"
174952296Sobrien  [(set (match_operand:SI 0 "register_operand" "")
175052296Sobrien	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
175152296Sobrien  ""
175252296Sobrien  "")
175352296Sobrien
175452296Sobrien;; When optimizing for the PPro/PII or code size, always use movzwl.
175552296Sobrien;; We want to use a different pattern so we can use different constraints
175652296Sobrien;; than the generic pattern.
175752296Sobrien(define_insn ""
175852296Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
175952296Sobrien	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
176052296Sobrien  "(optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO)"
176152296Sobrien  "* return AS2 (movz%W0%L0,%1,%0);")
176252296Sobrien
176352296Sobrien(define_insn ""
176450650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,&r,?r")
176550650Sobrien	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,rm,rm")))]
176652296Sobrien  "! (optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO)"
176718334Speter  "*
176850650Sobrien  {
176950650Sobrien  rtx xops[2];
177050650Sobrien
177150650Sobrien  if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0) 
177218334Speter      && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
177318334Speter    {
177418334Speter      xops[0] = operands[0];
177518334Speter      xops[1] = GEN_INT (0xffff);
177618334Speter      output_asm_insn (AS2 (and%L0,%1,%k0), xops);
177718334Speter      RET;
177818334Speter    }
177950650Sobrien  if (TARGET_ZERO_EXTEND_WITH_AND && !reg_overlap_mentioned_p (operands[0], operands[1]))
178050650Sobrien    {
178150650Sobrien      output_asm_insn (AS2 (xor%L0,%0,%0),operands);
178250650Sobrien      output_asm_insn (AS2 (mov%W0,%1,%w0),operands);
178350650Sobrien      RET;
178450650Sobrien    }
178518334Speter
178650650Sobrien  if (TARGET_ZERO_EXTEND_WITH_AND)
178750650Sobrien    {
178850650Sobrien      xops[0] = operands[0];
178950650Sobrien      xops[1] = GEN_INT (0xffff);
179050650Sobrien      if (i386_aligned_p (operands[1]))
179150650Sobrien	output_asm_insn (AS2 (mov%L0,%k1,%k0),operands);
179250650Sobrien      else
179350650Sobrien	output_asm_insn (AS2 (mov%W0,%1,%w0),operands);
179450650Sobrien      output_asm_insn (AS2 (and%L0,%1,%k0), xops);
179550650Sobrien      RET;
179650650Sobrien    }
179750650Sobrien
179818334Speter#ifdef INTEL_SYNTAX
179918334Speter  return AS2 (movzx,%1,%0);
180018334Speter#else
180118334Speter  return AS2 (movz%W0%L0,%1,%0);
180218334Speter#endif
180318334Speter}")
180418334Speter
180550650Sobrien(define_split
180650650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
180750650Sobrien	(zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))]
180850650Sobrien "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && !reg_overlap_mentioned_p (operands[0], operands[1])"
180950650Sobrien [(set (match_dup 0)
181050650Sobrien       (const_int 0))
181150650Sobrien  (set (strict_low_part (match_dup 2))
181250650Sobrien       (match_dup 1))]
181350650Sobrien "operands[2] = gen_rtx_REG (HImode, true_regnum (operands[0]));")
181450650Sobrien
181550650Sobrien
181650650Sobrien(define_split
181750650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
181850650Sobrien	(zero_extend:SI (match_operand:HI 1 "memory_operand" "")))]
181950650Sobrien "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && reg_overlap_mentioned_p (operands[0], operands[1])"
182050650Sobrien [(set (strict_low_part (match_dup 2))
182150650Sobrien       (match_dup 1))
182250650Sobrien  (set (match_dup 0)
182350650Sobrien       (and:SI (match_dup 0)
182450650Sobrien	       (const_int 65535)))]
182550650Sobrien  "operands[2] = gen_rtx_REG (HImode, true_regnum (operands[0]));")
182650650Sobrien
182752296Sobrien(define_expand "zero_extendqihi2"
182852296Sobrien  [(set (match_operand:HI 0 "register_operand" "")
182952296Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))]
183052296Sobrien  ""
183152296Sobrien  "")
183252296Sobrien
183352296Sobrien(define_insn ""
183452296Sobrien  [(set (match_operand:HI 0 "register_operand" "=r")
183552296Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
183652296Sobrien  "optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO"
183752296Sobrien
183852296Sobrien  "*  return AS2 (movz%B0%W0,%1,%0);")
183952296Sobrien
184052296Sobrien(define_insn ""
184150650Sobrien  [(set (match_operand:HI 0 "register_operand" "=q,&q,?r")
184250650Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))]
184352296Sobrien  "! (optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO)"
184418334Speter  "*
184550650Sobrien  {
184650650Sobrien  rtx xops[2];
184750650Sobrien
184850650Sobrien  if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0)
184950650Sobrien      && REG_P (operands[1]) 
185050650Sobrien      && REGNO (operands[0]) == REGNO (operands[1]))
185118334Speter    {
185218334Speter      xops[0] = operands[0];
185318334Speter      xops[1] = GEN_INT (0xff);
185418334Speter      output_asm_insn (AS2 (and%L0,%1,%k0), xops);
185518334Speter      RET;
185618334Speter    }
185750650Sobrien  if (TARGET_ZERO_EXTEND_WITH_AND && QI_REG_P (operands[0]))
185850650Sobrien    {
185950650Sobrien      if(!reg_overlap_mentioned_p(operands[0],operands[1]))
186050650Sobrien	{
186150650Sobrien	  output_asm_insn (AS2 (xor%L0,%k0,%k0), operands);
186250650Sobrien	  output_asm_insn (AS2 (mov%B0,%1,%b0), operands);
186350650Sobrien	}
186450650Sobrien      else
186550650Sobrien	{
186650650Sobrien	  xops[0] = operands[0];
186750650Sobrien	  xops[1] = GEN_INT (0xff);
186850650Sobrien	  output_asm_insn (AS2 (mov%B0,%1,%b0),operands);
186950650Sobrien	  output_asm_insn (AS2 (and%L0,%1,%k0), xops);
187050650Sobrien	}
187150650Sobrien      RET;
187250650Sobrien    }
187350650Sobrien  
187418334Speter#ifdef INTEL_SYNTAX
187518334Speter  return AS2 (movzx,%1,%0);
187618334Speter#else
187718334Speter  return AS2 (movz%B0%W0,%1,%0);
187818334Speter#endif
187918334Speter}")
188018334Speter
188150650Sobrien(define_split
188250650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
188350650Sobrien	(zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))]
188450650Sobrien "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND
188550650Sobrien  && !reg_overlap_mentioned_p (operands[0], operands[1])"
188650650Sobrien [(set (match_dup 0)
188750650Sobrien       (const_int 0))
188850650Sobrien  (set (strict_low_part (match_dup 2))
188950650Sobrien       (match_dup 1))]
189050650Sobrien "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));")
189150650Sobrien
189250650Sobrien
189350650Sobrien(define_split
189450650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
189550650Sobrien	(zero_extend:HI (match_operand:QI 1 "memory_operand" "")))]
189650650Sobrien "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND
189750650Sobrien  && reg_overlap_mentioned_p (operands[0], operands[1])"
189850650Sobrien [(set (strict_low_part (match_dup 2))
189950650Sobrien       (match_dup 1))
190050650Sobrien  (set (match_dup 0)
190150650Sobrien       (and:HI (match_dup 0)
190250650Sobrien	       (const_int 255)))]
190350650Sobrien "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));")
190450650Sobrien
190550650Sobrien(define_split
190650650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
190750650Sobrien	(zero_extend:HI (match_operand:QI 1 "register_operand" "")))]
190850650Sobrien "reload_completed && TARGET_ZERO_EXTEND_WITH_AND"
190950650Sobrien [(set (match_dup 0)
191050650Sobrien       (match_dup 2))
191150650Sobrien  (set (match_dup 0)
191250650Sobrien       (and:HI (match_dup 0)
191350650Sobrien	       (const_int 255)))]
191450650Sobrien "if (GET_CODE (operands[1]) == SUBREG && SUBREG_WORD (operands[1]) == 0)
191550650Sobrien    operands[1] = SUBREG_REG (operands[1]);
191650650Sobrien  if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG
191750650Sobrien      || REGNO (operands[0]) == REGNO (operands[1]))
191850650Sobrien    FAIL;
191950650Sobrien  operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));")
192050650Sobrien
192152296Sobrien(define_expand "zero_extendqisi2"
192252296Sobrien  [(set (match_operand:SI 0 "register_operand" "")
192352296Sobrien	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
192452296Sobrien  ""
192552296Sobrien  "")
192652296Sobrien
192752296Sobrien(define_insn ""
192852296Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
192952296Sobrien	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
193052296Sobrien  "optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO"
193152296Sobrien  "* return AS2 (movz%B0%L0,%1,%0);")
193252296Sobrien
193352296Sobrien(define_insn ""
193450650Sobrien  [(set (match_operand:SI 0 "register_operand" "=q,&q,?r")
193550650Sobrien	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))]
193652296Sobrien  "! (optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO)"
193718334Speter  "*
193850650Sobrien  {
193950650Sobrien  rtx xops[2];
194050650Sobrien
194150650Sobrien  if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0)
194250650Sobrien      && REG_P (operands[1]) 
194350650Sobrien      && REGNO (operands[0]) == REGNO (operands[1]))
194418334Speter    {
194518334Speter      xops[0] = operands[0];
194618334Speter      xops[1] = GEN_INT (0xff);
194718334Speter      output_asm_insn (AS2 (and%L0,%1,%k0), xops);
194818334Speter      RET;
194918334Speter    }
195050650Sobrien  if (TARGET_ZERO_EXTEND_WITH_AND && QI_REG_P (operands[0]))
195150650Sobrien    {
195250650Sobrien      if(!reg_overlap_mentioned_p (operands[0], operands[1]))
195350650Sobrien	{
195450650Sobrien	  output_asm_insn (AS2 (xor%L0,%0,%0),operands);
195550650Sobrien	  output_asm_insn (AS2 (mov%B0,%1,%b0),operands);
195650650Sobrien	}
195750650Sobrien      else
195850650Sobrien	{
195950650Sobrien	  xops[0] = operands[0];
196050650Sobrien	  xops[1] = GEN_INT (0xff);
196150650Sobrien	  output_asm_insn (AS2 (mov%B0,%1,%b0), operands);
196250650Sobrien	  output_asm_insn (AS2 (and%L0,%1,%k0), xops);
196350650Sobrien	}
196450650Sobrien      RET;
196550650Sobrien    }
196618334Speter
196750650Sobrien  if (TARGET_ZERO_EXTEND_WITH_AND && GET_CODE (operands[1]) == REG)
196850650Sobrien    {
196950650Sobrien      xops[0] = operands[0];
197050650Sobrien      xops[1] = GEN_INT (0xff);
197150650Sobrien      operands[1] = gen_rtx_REG (SImode, REGNO (operands[1]));
197250650Sobrien      output_asm_insn (AS2 (mov%L0,%1,%0), operands);
197350650Sobrien      output_asm_insn (AS2 (and%L0,%1,%k0), xops);
197450650Sobrien      RET;
197550650Sobrien    }
197650650Sobrien
197718334Speter#ifdef INTEL_SYNTAX
197818334Speter  return AS2 (movzx,%1,%0);
197918334Speter#else
198018334Speter  return AS2 (movz%B0%L0,%1,%0);
198118334Speter#endif
198218334Speter}")
198318334Speter
198450650Sobrien(define_split
198550650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
198650650Sobrien	(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))]
198750650Sobrien "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND
198850650Sobrien  && !reg_overlap_mentioned_p (operands[0], operands[1])"
198950650Sobrien [(set (match_dup 0)
199050650Sobrien       (const_int 0))
199150650Sobrien  (set (strict_low_part (match_dup 2))
199250650Sobrien       (match_dup 1))]
199350650Sobrien "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));")
199450650Sobrien
199550650Sobrien
199650650Sobrien(define_split
199750650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
199850650Sobrien	(zero_extend:SI (match_operand:QI 1 "memory_operand" "")))]
199950650Sobrien "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND
200050650Sobrien  && reg_overlap_mentioned_p (operands[0], operands[1])"
200150650Sobrien [(set (strict_low_part (match_dup 2))
200250650Sobrien       (match_dup 1))
200350650Sobrien  (set (match_dup 0)
200450650Sobrien       (and:SI (match_dup 0)
200550650Sobrien	       (const_int 255)))]
200650650Sobrien "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));")
200750650Sobrien
200850650Sobrien(define_split
200950650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
201050650Sobrien	(zero_extend:SI (match_operand:QI 1 "register_operand" "")))]
201150650Sobrien "reload_completed && TARGET_ZERO_EXTEND_WITH_AND
201250650Sobrien  && ! reg_overlap_mentioned_p (operands[0], operands[1])"
201350650Sobrien [(set (match_dup 0)
201450650Sobrien       (match_dup 2))
201550650Sobrien  (set (match_dup 0)
201650650Sobrien       (and:SI (match_dup 0)
201750650Sobrien	       (const_int 255)))]
201850650Sobrien "operands[2] = gen_rtx_REG (SImode, true_regnum (operands[1]));")
201950650Sobrien
202018334Speter(define_insn "zero_extendsidi2"
202152296Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o")
202252296Sobrien	(zero_extend:DI (match_operand:SI 1 "general_operand" "0,rm,r")))]
202318334Speter  ""
202452296Sobrien  "#")
202550650Sobrien
202652296Sobrien(define_split 
202752296Sobrien  [(set (match_operand:DI 0 "register_operand" "")
202852296Sobrien	(zero_extend:DI (match_operand:SI 1 "register_operand" "")))]
202952296Sobrien  "reload_completed && true_regnum (operands[0]) == true_regnum (operands[1])"
203052296Sobrien  [(set (match_dup 4) (const_int 0))]
203152296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
203250650Sobrien
203352296Sobrien(define_split 
203452296Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "")
203552296Sobrien	(zero_extend:DI (match_operand:SI 1 "general_operand" "")))]
203652296Sobrien  "reload_completed"
203752296Sobrien  [(set (match_dup 3) (match_dup 1))
203852296Sobrien   (set (match_dup 4) (const_int 0))]
203952296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
204018334Speter
204118334Speter;;- sign extension instructions
204218334Speter
204318334Speter(define_insn "extendsidi2"
204452296Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=A,?r,?Ar,*o")
204552296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "0,0,r,*r")))
204652296Sobrien   (clobber (match_scratch:SI 2 "=X,X,X,&r"))]
204718334Speter  ""
204852296Sobrien  "#")
204952296Sobrien
205052296Sobrien;; Extend to memory case when source register does die.
205152296Sobrien(define_split 
205252296Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
205352296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
205452296Sobrien   (clobber (match_operand:SI 2 "register_operand" ""))]
205552296Sobrien  "(flow2_completed
205652296Sobrien    && dead_or_set_p (insn, operands[1])
205752296Sobrien    && !reg_mentioned_p (operands[1], operands[0]))"
205852296Sobrien  [(set (match_dup 3) (match_dup 1))
205952296Sobrien   (set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31)))
206052296Sobrien   (set (match_dup 4) (match_dup 1))]
206152296Sobrien  "split_di (&operands[0], 1, &operands[3], &operands[4]);")
206252296Sobrien
206352296Sobrien;; Extend to memory case when source register does not die.
206452296Sobrien(define_split 
206552296Sobrien  [(set (match_operand:DI 0 "memory_operand" "")
206652296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
206752296Sobrien   (clobber (match_operand:SI 2 "register_operand" ""))]
206852296Sobrien  "flow2_completed"
206952296Sobrien  [(const_int 0)]
207052296Sobrien  "
207118334Speter{
207252296Sobrien  split_di (&operands[0], 1, &operands[3], &operands[4]);
207352296Sobrien
207452296Sobrien  emit_move_insn (operands[3], operands[1]);
207552296Sobrien
207652296Sobrien  /* Generate a cltd if possible and doing so it profitable.  */
207752296Sobrien  if (true_regnum (operands[1]) == 0
207852296Sobrien      && true_regnum (operands[2]) == 1
207952296Sobrien      && (optimize_size || !TARGET_PENTIUM))
208018334Speter    {
208152296Sobrien      emit_insn (gen_ashrsi3_31 (operands[2], operands[1]));
208218334Speter    }
208352296Sobrien  else
208452296Sobrien    {
208552296Sobrien      emit_move_insn (operands[2], operands[1]);
208652296Sobrien      emit_insn (gen_ashrsi3_31 (operands[2], operands[2]));
208752296Sobrien    }
208852296Sobrien  emit_move_insn (operands[4], operands[2]);
208952296Sobrien  DONE;
209052296Sobrien}")
209118334Speter
209252296Sobrien;; Extend to register case.  Optimize case where source and destination
209352296Sobrien;; registers match and cases where we can use cltd.
209452296Sobrien(define_split 
209552296Sobrien  [(set (match_operand:DI 0 "register_operand" "")
209652296Sobrien	(sign_extend:DI (match_operand:SI 1 "register_operand" "")))
209752296Sobrien   (clobber (match_scratch:SI 2 ""))]
209852296Sobrien  "reload_completed"
209952296Sobrien  [(const_int 0)]
210052296Sobrien  "
210152296Sobrien{
210252296Sobrien  split_di (&operands[0], 1, &operands[3], &operands[4]);
210318334Speter
210452296Sobrien  if (true_regnum (operands[3]) != true_regnum (operands[1]))
210552296Sobrien    emit_move_insn (operands[3], operands[1]);
210652296Sobrien
210752296Sobrien  /* Generate a cltd if possible and doing so it profitable.  */
210852296Sobrien  if (true_regnum (operands[3]) == 0
210952296Sobrien      && (optimize_size || !TARGET_PENTIUM))
211052296Sobrien    {
211152296Sobrien      emit_insn (gen_ashrsi3_31 (operands[4], operands[3]));
211252296Sobrien      DONE;
211352296Sobrien    }
211452296Sobrien
211552296Sobrien  if (true_regnum (operands[4]) != true_regnum (operands[1]))
211652296Sobrien    emit_move_insn (operands[4], operands[1]);
211752296Sobrien
211852296Sobrien  emit_insn (gen_ashrsi3_31 (operands[4], operands[4]));
211952296Sobrien  DONE;
212018334Speter}")
212118334Speter
212218334Speter;; Note that the i386 programmers' manual says that the opcodes
212318334Speter;; are named movsx..., but the assembler on Unix does not accept that.
212418334Speter;; We use what the Unix assembler expects.
212518334Speter
212618334Speter(define_insn "extendhisi2"
212750650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
212850650Sobrien	(sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
212918334Speter  ""
213018334Speter  "*
213118334Speter{
213218334Speter  if (REGNO (operands[0]) == 0
213352296Sobrien      && REG_P (operands[1]) && REGNO (operands[1]) == 0
213452296Sobrien      && (optimize_size || ix86_cpu != PROCESSOR_K6))
213518334Speter#ifdef INTEL_SYNTAX
213618334Speter    return \"cwde\";
213718334Speter#else
213818334Speter    return \"cwtl\";
213918334Speter#endif
214018334Speter
214118334Speter#ifdef INTEL_SYNTAX
214218334Speter  return AS2 (movsx,%1,%0);
214318334Speter#else
214418334Speter  return AS2 (movs%W0%L0,%1,%0);
214518334Speter#endif
214618334Speter}")
214718334Speter
214818334Speter(define_insn "extendqihi2"
214950650Sobrien  [(set (match_operand:HI 0 "register_operand" "=r")
215050650Sobrien	(sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
215118334Speter  ""
215218334Speter  "*
215318334Speter{
215418334Speter  if (REGNO (operands[0]) == 0
215552296Sobrien      && REG_P (operands[1]) && REGNO (operands[1]) == 0
215652296Sobrien      && (optimize_size || ix86_cpu != PROCESSOR_K6))
215718334Speter    return \"cbtw\";
215818334Speter
215918334Speter#ifdef INTEL_SYNTAX
216018334Speter  return AS2 (movsx,%1,%0);
216118334Speter#else
216218334Speter  return AS2 (movs%B0%W0,%1,%0);
216318334Speter#endif
216418334Speter}")
216518334Speter
216618334Speter(define_insn "extendqisi2"
216750650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
216850650Sobrien	(sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
216918334Speter  ""
217018334Speter  "*
217118334Speter{
217218334Speter#ifdef INTEL_SYNTAX
217318334Speter  return AS2 (movsx,%1,%0);
217418334Speter#else
217518334Speter  return AS2 (movs%B0%L0,%1,%0);
217618334Speter#endif
217718334Speter}")
217850650Sobrien
217918334Speter
218050650Sobrien;; Truncation of long long -> 32 bit
218150650Sobrien
218250650Sobrien(define_expand "truncdisi2"
218350650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m")
218450650Sobrien	(truncate:SI (match_operand:DI 1 "nonimmediate_operand" "ro,r")))]
218550650Sobrien  ""
218650650Sobrien  "
218750650Sobrien{
218850650Sobrien  /* Don't generate memory->memory moves, go through a register */
218950650Sobrien  if (TARGET_MOVE
219050650Sobrien      && (reload_in_progress | reload_completed) == 0
219150650Sobrien      && GET_CODE (operands[0]) == MEM
219250650Sobrien      && GET_CODE (operands[1]) == MEM)
219350650Sobrien    {
219450650Sobrien      rtx target = gen_reg_rtx (SImode);
219550650Sobrien      emit_insn (gen_truncdisi2 (target, operands[1]));
219650650Sobrien      emit_move_insn (operands[0], target);
219750650Sobrien      DONE;
219850650Sobrien    }
219950650Sobrien}")
220050650Sobrien
220150650Sobrien(define_insn ""
220250650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m")
220350650Sobrien	(truncate:SI (match_operand:DI 1 "nonimmediate_operand" "ro,r")))]
220450650Sobrien  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
220550650Sobrien  "*
220650650Sobrien{
220750650Sobrien  rtx low[2], high[2], xops[2];
220850650Sobrien
220950650Sobrien  split_di (&operands[1], 1, low, high);
221050650Sobrien  xops[0] = operands[0];
221150650Sobrien  xops[1] = low[0];
221250650Sobrien  if (!rtx_equal_p (xops[0], xops[1]))
221350650Sobrien    output_asm_insn (AS2 (mov%L0,%1,%0), xops);
221450650Sobrien
221550650Sobrien  RET;
221650650Sobrien}")
221750650Sobrien
221850650Sobrien(define_insn ""
221950650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m")
222050650Sobrien	(truncate:SI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r")
222150650Sobrien				  (const_int 32))))]
222250650Sobrien  "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
222350650Sobrien  "*
222450650Sobrien{
222550650Sobrien  rtx low[2], high[2], xops[2];
222650650Sobrien
222750650Sobrien  split_di (&operands[1], 1, low, high);
222850650Sobrien  xops[0] = operands[0];
222950650Sobrien  xops[1] = high[0];
223050650Sobrien  if (!rtx_equal_p (xops[0], xops[1]))
223150650Sobrien    output_asm_insn (AS2 (mov%L0,%1,%0), xops);
223250650Sobrien
223350650Sobrien  RET;
223450650Sobrien}")
223550650Sobrien
223650650Sobrien
223750650Sobrien
223818334Speter;; Conversions between float and double.
223918334Speter
224052296Sobrien(define_expand "extendsfdf2"
224152296Sobrien  [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
224252296Sobrien		   (float_extend:DF
224352296Sobrien		     (match_operand:SF 1 "nonimmediate_operand" "")))
224452296Sobrien     (clobber (match_dup 2))
224552296Sobrien     (clobber (match_dup 3))])]
224652296Sobrien  "TARGET_80387"
224752296Sobrien  "
224852296Sobrien{
224952296Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
225052296Sobrien    operands[1] = force_reg (SFmode, operands[1]);
225152296Sobrien
225252296Sobrien  operands[2] = assign_386_stack_local (SFmode, 0);
225352296Sobrien  operands[3] = assign_386_stack_local (DFmode, 0);
225452296Sobrien}")
225552296Sobrien
225652296Sobrien(define_insn ""
225752296Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,!f,!*r")
225818334Speter	(float_extend:DF
225952296Sobrien	  (match_operand:SF 1 "nonimmediate_operand" "fm,f,*r,f")))
226052296Sobrien   (clobber (match_operand:SF 2 "memory_operand" "m,m,m,m"))
226152296Sobrien   (clobber (match_operand:DF 3 "memory_operand" "m,m,m,o"))]
226252296Sobrien  "TARGET_80387 && (GET_CODE (operands[0]) != MEM
226352296Sobrien		    || GET_CODE (operands[1]) != MEM)"
226418334Speter  "*
226518334Speter{
226652296Sobrien  output_float_extend (insn, operands);
226752296Sobrien  return \"\";
226852296Sobrien}"
226952296Sobrien  [(set_attr "type" "fld,fpop,fld,fpop")])
227018334Speter
227152296Sobrien(define_split
227252296Sobrien  [(set (match_operand:DF 0 "register_operand" "")
227352296Sobrien	(float_extend:DF (match_operand:SF 1 "register_operand" "")))
227452296Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))
227552296Sobrien   (clobber (match_operand:DF 3 "memory_operand" ""))]
227652296Sobrien  "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[1])"
227752296Sobrien  [(set (match_dup 2)
227852296Sobrien	(match_dup 1))
227952296Sobrien   (set (match_dup 0)
228052296Sobrien	(float_extend:DF (match_dup 2)))]
228152296Sobrien  "")
228218334Speter
228352296Sobrien(define_split
228452296Sobrien  [(set (match_operand:DF 0 "register_operand" "")
228552296Sobrien	(float_extend:DF (match_operand:SF 1 "register_operand" "")))
228652296Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))
228752296Sobrien   (clobber (match_operand:DF 3 "memory_operand" ""))]
228852296Sobrien  "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[0])"
228952296Sobrien  [(set (match_dup 3)
229052296Sobrien	(float_extend:DF (match_dup 1)))
229152296Sobrien   (set (match_dup 0)
229252296Sobrien	(match_dup 3))]
229352296Sobrien  "")
229418334Speter
229552296Sobrien(define_split
229652296Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "")
229752296Sobrien	(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "")))
229852296Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))
229952296Sobrien   (clobber (match_operand:DF 3 "memory_operand" ""))]
230052296Sobrien  "TARGET_80387 && reload_completed"
230152296Sobrien  [(set (match_dup 0)
230252296Sobrien	(float_extend:DF (match_dup 1)))]
230352296Sobrien  "")
230418334Speter
230552296Sobrien(define_insn ""
230652296Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m")
230752296Sobrien	(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
230852296Sobrien  "TARGET_80387 && (GET_CODE (operands[0]) != MEM
230952296Sobrien		    || GET_CODE (operands[1]) != MEM)"
231052296Sobrien  "*
231152296Sobrien{
231252296Sobrien    output_float_extend (insn, operands);
231352296Sobrien    return \"\";
231452296Sobrien}"
231552296Sobrien  [(set_attr "type" "fld,fpop")])
231618334Speter
231752296Sobrien(define_expand "extenddfxf2"
231852296Sobrien  [(parallel [(set (match_operand:XF 0 "nonimmediate_operand" "")
231952296Sobrien		   (float_extend:XF
232052296Sobrien		     (match_operand:DF 1 "nonimmediate_operand" "")))
232152296Sobrien     (clobber (match_dup 2))
232252296Sobrien     (clobber (match_dup 3))])]
232352296Sobrien  "TARGET_80387"
232452296Sobrien  "
232552296Sobrien{
232652296Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
232752296Sobrien    operands[1] = force_reg (DFmode, operands[1]);
232852296Sobrien
232952296Sobrien  operands[2] = assign_386_stack_local (DFmode, 0);
233052296Sobrien  operands[3] = assign_386_stack_local (XFmode, 0);
233118334Speter}")
233218334Speter
233352296Sobrien(define_insn ""
233452296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,!f,!*r")
233518334Speter	(float_extend:XF
233652296Sobrien	  (match_operand:DF 1 "nonimmediate_operand" "fm,f,*r,f")))
233752296Sobrien   (clobber (match_operand:DF 2 "memory_operand" "m,m,o,m"))
233852296Sobrien   (clobber (match_operand:XF 3 "memory_operand" "m,m,m,o"))]
233952296Sobrien  "TARGET_80387 && (GET_CODE (operands[0]) != MEM
234052296Sobrien		    || GET_CODE (operands[1]) != MEM)"
234118334Speter  "*
234218334Speter{
234352296Sobrien    output_float_extend (insn, operands);
234452296Sobrien    return \"\";
234552296Sobrien}"
234652296Sobrien  [(set_attr "type" "fld,fpop,fld,fpop")])
234718334Speter
234852296Sobrien(define_split
234952296Sobrien  [(set (match_operand:XF 0 "register_operand" "")
235052296Sobrien	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
235152296Sobrien   (clobber (match_operand:DF 2 "memory_operand" ""))
235252296Sobrien   (clobber (match_operand:XF 3 "memory_operand" ""))]
235352296Sobrien  "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[1])"
235452296Sobrien  [(set (match_dup 2)
235552296Sobrien	(match_dup 1))
235652296Sobrien   (set (match_dup 0)
235752296Sobrien	(float_extend:XF (match_dup 2)))]
235852296Sobrien  "")
235918334Speter
236052296Sobrien(define_split
236152296Sobrien  [(set (match_operand:XF 0 "register_operand" "")
236252296Sobrien	(float_extend:XF (match_operand:DF 1 "register_operand" "")))
236352296Sobrien   (clobber (match_operand:DF 2 "memory_operand" ""))
236452296Sobrien   (clobber (match_operand:XF 3 "memory_operand" ""))]
236552296Sobrien  "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[0])"
236652296Sobrien  [(set (match_dup 3)
236752296Sobrien	(float_extend:XF (match_dup 1)))
236852296Sobrien   (set (match_dup 0)
236952296Sobrien	(match_dup 3))]
237052296Sobrien  "")
237118334Speter
237252296Sobrien(define_split
237352296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "")
237452296Sobrien	(float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "")))
237552296Sobrien   (clobber (match_operand:DF 2 "memory_operand" ""))
237652296Sobrien   (clobber (match_operand:XF 3 "memory_operand" ""))]
237752296Sobrien  "TARGET_80387 && reload_completed"
237852296Sobrien  [(set (match_dup 0)
237952296Sobrien	(float_extend:XF (match_dup 1)))]
238052296Sobrien  "")
238118334Speter
238252296Sobrien(define_insn ""
238352296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
238452296Sobrien	(float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "fm,f")))]
238552296Sobrien  "TARGET_80387 && (GET_CODE (operands[0]) != MEM
238652296Sobrien		    || GET_CODE (operands[1]) != MEM)"
238752296Sobrien  "*
238852296Sobrien{
238952296Sobrien    output_float_extend (insn, operands);
239052296Sobrien    return \"\";
239152296Sobrien}"
239252296Sobrien  [(set_attr "type" "fld,fpop")])
239318334Speter
239452296Sobrien(define_expand "extendsfxf2"
239552296Sobrien  [(parallel [(set (match_operand:XF 0 "nonimmediate_operand" "")
239652296Sobrien		   (float_extend:XF
239752296Sobrien		     (match_operand:SF 1 "nonimmediate_operand" "")))
239852296Sobrien     (clobber (match_dup 2))
239952296Sobrien     (clobber (match_dup 3))])]
240052296Sobrien  "TARGET_80387"
240152296Sobrien  "
240252296Sobrien{
240352296Sobrien  if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM)
240452296Sobrien    operands[1] = force_reg (SFmode, operands[1]);
240552296Sobrien
240652296Sobrien  operands[2] = assign_386_stack_local (SFmode, 0);
240752296Sobrien  operands[3] = assign_386_stack_local (XFmode, 0);
240818334Speter}")
240918334Speter
241052296Sobrien(define_insn ""
241152296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,!f,!*r")
241218334Speter	(float_extend:XF
241352296Sobrien	  (match_operand:SF 1 "nonimmediate_operand" "fm,f,*r,f")))
241452296Sobrien   (clobber (match_operand:SF 2 "memory_operand" "m,m,m,m"))
241552296Sobrien   (clobber (match_operand:XF 3 "memory_operand" "m,m,m,o"))]
241652296Sobrien  "TARGET_80387 && (GET_CODE (operands[0]) != MEM
241752296Sobrien		    || GET_CODE (operands[1]) != MEM)"
241818334Speter  "*
241918334Speter{
242052296Sobrien    output_float_extend (insn, operands);
242152296Sobrien    return \"\";
242252296Sobrien}"
242352296Sobrien  [(set_attr "type" "fld,fpop,fld,fpop")])
242418334Speter
242552296Sobrien(define_split
242652296Sobrien  [(set (match_operand:XF 0 "register_operand" "")
242752296Sobrien	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
242852296Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))
242952296Sobrien   (clobber (match_operand:XF 3 "memory_operand" ""))]
243052296Sobrien  "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[1])"
243152296Sobrien  [(set (match_dup 2)
243252296Sobrien	(match_dup 1))
243352296Sobrien   (set (match_dup 0)
243452296Sobrien	(float_extend:XF (match_dup 2)))]
243552296Sobrien  "")
243618334Speter
243752296Sobrien(define_split
243852296Sobrien  [(set (match_operand:XF 0 "register_operand" "")
243952296Sobrien	(float_extend:XF (match_operand:SF 1 "register_operand" "")))
244052296Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))
244152296Sobrien   (clobber (match_operand:XF 3 "memory_operand" ""))]
244252296Sobrien  "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[0])"
244352296Sobrien  [(set (match_dup 3)
244452296Sobrien	(float_extend:XF (match_dup 1)))
244552296Sobrien   (set (match_dup 0)
244652296Sobrien	(match_dup 3))]
244752296Sobrien  "")
244818334Speter
244952296Sobrien(define_split
245052296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "")
245152296Sobrien	(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "")))
245252296Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))
245352296Sobrien   (clobber (match_operand:XF 3 "memory_operand" ""))]
245452296Sobrien  "TARGET_80387 && reload_completed"
245552296Sobrien  [(set (match_dup 0)
245652296Sobrien	(float_extend:XF (match_dup 1)))]
245752296Sobrien  "")
245818334Speter
245952296Sobrien(define_insn ""
246052296Sobrien  [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m")
246152296Sobrien	(float_extend:XF
246252296Sobrien	 (match_operand:SF 1 "nonimmediate_operand" "fm,f")))]
246352296Sobrien  "TARGET_80387 && (GET_CODE (operands[0]) != MEM
246452296Sobrien		    || GET_CODE (operands[1]) != MEM)"
246552296Sobrien  "*
246652296Sobrien{
246752296Sobrien    output_float_extend (insn, operands);
246852296Sobrien    return \"\";
246952296Sobrien}"
247052296Sobrien  [(set_attr "type" "fld,fpop")])
247118334Speter
247218334Speter(define_expand "truncdfsf2"
247318334Speter  [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
247418334Speter		   (float_truncate:SF
247518334Speter		    (match_operand:DF 1 "register_operand" "")))
247618334Speter	      (clobber (match_dup 2))])]
247718334Speter  "TARGET_80387"
247818334Speter  "
247918334Speter{
248018334Speter  operands[2] = (rtx) assign_386_stack_local (SFmode, 0);
248118334Speter}")
248218334Speter
248318334Speter(define_insn ""
248452296Sobrien  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,!*r")
248518334Speter	(float_truncate:SF
248652296Sobrien	  (match_operand:DF 1 "register_operand" "0,f,f")))
248752296Sobrien   (clobber (match_operand:SF 2 "memory_operand" "m,m,m"))]
248818334Speter  "TARGET_80387"
248918334Speter  "*
249018334Speter{
249118334Speter  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
249252296Sobrien  rtx xops[1];
249318334Speter
249452296Sobrien  xops[0] = GET_CODE (operands[0]) == MEM ? operands[0] : operands[2];
249552296Sobrien
249652296Sobrien  if (stack_top_dies || STACK_REG_P (operands[0]))
249752296Sobrien    output_asm_insn (AS1 (fstp%z0,%0), xops);
249818334Speter  else
249952296Sobrien    output_asm_insn (AS1 (fst%z0,%0), xops);
250018334Speter
250152296Sobrien  if (STACK_REG_P (operands[0]))
250252296Sobrien    return AS1 (fld%z2,%2);
250352296Sobrien  else if (NON_STACK_REG_P (operands[0]))
250452296Sobrien    return AS2 (mov%L0,%2,%0);
250552296Sobrien
250652296Sobrien  return \"\";
250752296Sobrien}"
250852296Sobrien  [(set_attr "type" "fpop")])
250952296Sobrien
251052296Sobrien(define_split
251152296Sobrien  [(set (match_operand:SF 0 "register_operand" "")
251252296Sobrien	(float_truncate:SF (match_operand:DF 1 "register_operand" "")))
251352296Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))]
251452296Sobrien  "TARGET_80387 && reload_completed"
251552296Sobrien  [(set (match_dup 2)
251652296Sobrien	(float_truncate:SF (match_dup 1)))
251752296Sobrien   (set (match_dup 0)
251852296Sobrien	(match_dup 2))]
251952296Sobrien  "")
252052296Sobrien
252152296Sobrien(define_split
252252296Sobrien  [(set (match_operand:SF 0 "memory_operand" "")
252352296Sobrien	(float_truncate:SF (match_operand:DF 1 "register_operand" "")))
252452296Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))]
252552296Sobrien  "TARGET_80387 && reload_completed"
252652296Sobrien  [(set (match_dup 0)
252752296Sobrien	(float_truncate:SF (match_dup 1)))]
252852296Sobrien  "")
252952296Sobrien
253052296Sobrien;; This cannot output into an f-reg because there is no way to be sure
253152296Sobrien;; of truncating in that case.
253252296Sobrien
253352296Sobrien(define_insn ""
253452296Sobrien  [(set (match_operand:SF 0 "memory_operand" "=m")
253552296Sobrien	(float_truncate:SF (match_operand:DF 1 "register_operand" "f")))]
253618334Speter  "TARGET_80387"
253718334Speter  "*
253818334Speter{
253918334Speter  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
254018334Speter
254152296Sobrien  if (stack_top_dies)
254252296Sobrien    return AS1 (fstp%z0,%0);
254318334Speter  else
254452296Sobrien    return AS1 (fst%z0,%0);
254552296Sobrien}"
254652296Sobrien  [(set_attr "type" "fpop")])
254752296Sobrien
254852296Sobrien(define_expand "truncxfsf2"
254952296Sobrien  [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "")
255052296Sobrien		   (float_truncate:SF
255152296Sobrien		    (match_operand:XF 1 "register_operand" "")))
255252296Sobrien	      (clobber (match_dup 2))])]
255352296Sobrien  "TARGET_80387"
255452296Sobrien  "
255552296Sobrien{
255652296Sobrien  operands[2] = (rtx) assign_386_stack_local (SFmode, 0);
255718334Speter}")
255818334Speter
255952296Sobrien(define_insn ""
256052296Sobrien  [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,!*r")
256152296Sobrien	(float_truncate:SF
256252296Sobrien	  (match_operand:XF 1 "register_operand" "0,f,f")))
256352296Sobrien   (clobber (match_operand:SF 2 "memory_operand" "m,m,m"))]
256418334Speter  "TARGET_80387"
256518334Speter  "*
256618334Speter{
256718334Speter  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
256852296Sobrien  rtx xops[1];
256918334Speter
257052296Sobrien  xops[0] = GET_CODE (operands[0]) == MEM ? operands[0] : operands[2];
257152296Sobrien
257252296Sobrien  if (stack_top_dies || STACK_REG_P (operands[0]))
257352296Sobrien    output_asm_insn (AS1 (fstp%z0,%0), xops);
257418334Speter  else
257552296Sobrien    output_asm_insn (AS1 (fst%z0,%0), xops);
257618334Speter
257752296Sobrien  if (STACK_REG_P (operands[0]))
257852296Sobrien    return AS1 (fld%z2,%2);
257952296Sobrien  else if (NON_STACK_REG_P (operands[0]))
258052296Sobrien    return AS2 (mov%L0,%2,%0);
258118334Speter
258252296Sobrien  return \"\";
258352296Sobrien}"
258452296Sobrien  [(set_attr "type" "fpop")])
258518334Speter
258652296Sobrien(define_split
258752296Sobrien  [(set (match_operand:SF 0 "register_operand" "")
258852296Sobrien	(float_truncate:SF (match_operand:XF 1 "register_operand" "")))
258952296Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))]
259052296Sobrien  "TARGET_80387 && reload_completed"
259152296Sobrien  [(set (match_dup 2)
259252296Sobrien	(float_truncate:SF (match_dup 1)))
259352296Sobrien   (set (match_dup 0)
259452296Sobrien	(match_dup 2))]
259552296Sobrien  "")
259652296Sobrien
259752296Sobrien(define_split
259852296Sobrien  [(set (match_operand:SF 0 "memory_operand" "")
259952296Sobrien	(float_truncate:SF (match_operand:XF 1 "register_operand" "")))
260052296Sobrien   (clobber (match_operand:SF 2 "memory_operand" ""))]
260152296Sobrien  "TARGET_80387 && reload_completed"
260252296Sobrien  [(set (match_dup 0)
260352296Sobrien	(float_truncate:SF (match_dup 1)))]
260452296Sobrien  "")
260552296Sobrien
260652296Sobrien(define_insn ""
260752296Sobrien  [(set (match_operand:SF 0 "memory_operand" "=m")
260852296Sobrien	(float_truncate:SF (match_operand:XF 1 "register_operand" "f")))]
260918334Speter  "TARGET_80387"
261052296Sobrien  "*
261118334Speter{
261252296Sobrien  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
261318334Speter
261452296Sobrien  if (stack_top_dies)
261552296Sobrien    return AS1 (fstp%z0,%0);
261652296Sobrien  else
261752296Sobrien    return AS1 (fst%z0,%0);
261852296Sobrien}"
261952296Sobrien  [(set_attr "type" "fpop")])
262052296Sobrien
262152296Sobrien(define_expand "truncxfdf2"
262252296Sobrien  [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "")
262352296Sobrien		   (float_truncate:DF
262452296Sobrien		    (match_operand:XF 1 "register_operand" "")))
262552296Sobrien	      (clobber (match_dup 2))])]
262618334Speter  "TARGET_80387"
262718334Speter  "
262818334Speter{
262952296Sobrien  operands[2] = (rtx) assign_386_stack_local (DFmode, 0);
263018334Speter}")
263118334Speter
263252296Sobrien(define_insn ""
263352296Sobrien  [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,!*r")
263452296Sobrien	(float_truncate:DF
263552296Sobrien	  (match_operand:XF 1 "register_operand" "0,f,f")))
263652296Sobrien   (clobber (match_operand:DF 2 "memory_operand" "m,m,o"))]
263718334Speter  "TARGET_80387"
263852296Sobrien  "*
263918334Speter{
264052296Sobrien  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
264152296Sobrien  rtx xops[2];
264218334Speter
264352296Sobrien  xops[0] = GET_CODE (operands[0]) == MEM ? operands[0] : operands[2];
264418334Speter
264552296Sobrien  if (stack_top_dies || STACK_REG_P (operands[0]))
264652296Sobrien    output_asm_insn (AS1 (fstp%z0,%0), xops);
264752296Sobrien  else
264852296Sobrien    output_asm_insn (AS1 (fst%z0,%0), xops);
264952296Sobrien
265052296Sobrien  if (STACK_REG_P (operands[0]))
265152296Sobrien    return AS1 (fld%z2,%2);
265252296Sobrien  else if (NON_STACK_REG_P (operands[0]))
265352296Sobrien    {
265452296Sobrien    xops[0] = operands[0];
265552296Sobrien    xops[1] = operands[2];
265652296Sobrien    output_asm_insn (output_move_double (xops), xops);
265752296Sobrien    }
265852296Sobrien
265952296Sobrien  return \"\";
266052296Sobrien}"
266152296Sobrien  [(set_attr "type" "fpop")])
266252296Sobrien
266352296Sobrien(define_split
266452296Sobrien  [(set (match_operand:DF 0 "register_operand" "")
266552296Sobrien	(float_truncate:DF (match_operand:XF 1 "register_operand" "")))
266652296Sobrien   (clobber (match_operand:DF 2 "memory_operand" ""))]
266752296Sobrien  "TARGET_80387 && reload_completed"
266818334Speter  [(set (match_dup 2)
266952296Sobrien	(float_truncate:DF (match_dup 1)))
267052296Sobrien   (set (match_dup 0)
267152296Sobrien	(match_dup 2))]
267252296Sobrien  "")
267352296Sobrien
267452296Sobrien(define_split
267552296Sobrien  [(set (match_operand:DF 0 "memory_operand" "")
267652296Sobrien	(float_truncate:DF (match_operand:XF 1 "register_operand" "")))
267752296Sobrien   (clobber (match_operand:DF 2 "memory_operand" ""))]
267852296Sobrien  "TARGET_80387 && reload_completed"
267952296Sobrien  [(set (match_dup 0)
268052296Sobrien	(float_truncate:DF (match_dup 1)))]
268152296Sobrien  "")
268252296Sobrien
268352296Sobrien(define_insn ""
268452296Sobrien  [(set (match_operand:DF 0 "memory_operand" "=m")
268552296Sobrien	(float_truncate:DF (match_operand:XF 1 "register_operand" "f")))]
268618334Speter  "TARGET_80387"
268752296Sobrien  "*
268818334Speter{
268952296Sobrien  int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0;
269018334Speter
269152296Sobrien  if (stack_top_dies)
269252296Sobrien    return AS1 (fstp%z0,%0);
269352296Sobrien  else
269452296Sobrien    return AS1 (fst%z0,%0);
269552296Sobrien}"
269652296Sobrien  [(set_attr "type" "fpop")])
269752296Sobrien
269852296Sobrien;; Conversions between floating point and fix point.
269952296Sobrien
270052296Sobrien(define_expand "fix_truncsfsi2"
270152296Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
270252296Sobrien		   (fix:SI (fix:SF (match_operand:SF 1 "register_operand" ""))))
270318334Speter	      (clobber (match_dup 2))
270418334Speter	      (clobber (match_dup 3))
270518334Speter	      (clobber (match_dup 4))
270652296Sobrien	      (clobber (match_scratch:HI 5 ""))])]
270718334Speter  "TARGET_80387"
270818334Speter  "
270918334Speter{
271052296Sobrien  operands[2] = (rtx) assign_386_stack_local (HImode, 0);
271152296Sobrien  operands[3] = (rtx) assign_386_stack_local (HImode, 1);
271252296Sobrien  operands[4] = (rtx) assign_386_stack_local (SImode, 0);
271318334Speter}")
271418334Speter
271552296Sobrien(define_insn ""
271653176Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=m,!&r")
271752296Sobrien	(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f,f"))))
271852296Sobrien   (clobber (match_operand:HI 2 "memory_operand" "m,m"))
271952296Sobrien   (clobber (match_operand:HI 3 "memory_operand" "m,m"))
272052296Sobrien   (clobber (match_operand:SI 4 "memory_operand" "m,m"))
272152296Sobrien   (clobber (match_scratch:HI 5 "=&r,&r"))]
272252296Sobrien  "TARGET_80387"
272352296Sobrien  "* return output_fix_trunc (insn, operands);"
272452296Sobrien  [(set_attr "type" "fpop")])
272552296Sobrien
272618334Speter(define_expand "fix_truncsfdi2"
272752296Sobrien  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
272852296Sobrien		   (fix:DI (fix:SF (match_operand:SF 1 "register_operand" ""))))
272952296Sobrien	      (clobber (match_dup 1))
273018334Speter	      (clobber (match_dup 2))
273118334Speter	      (clobber (match_dup 3))
273218334Speter	      (clobber (match_dup 4))
273352296Sobrien	      (clobber (match_scratch:HI 5 ""))])]
273418334Speter  "TARGET_80387"
273518334Speter  "
273618334Speter{
273718334Speter  operands[1] = copy_to_mode_reg (SFmode, operands[1]);
273852296Sobrien  operands[2] = (rtx) assign_386_stack_local (HImode, 0);
273952296Sobrien  operands[3] = (rtx) assign_386_stack_local (HImode, 1);
274052296Sobrien  operands[4] = (rtx) assign_386_stack_local (DImode, 0);
274118334Speter}")
274218334Speter
274318334Speter(define_insn ""
274453176Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!&r")
274552296Sobrien	(fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f,f"))))
274618334Speter   (clobber (match_dup 1))
274752296Sobrien   (clobber (match_operand:HI 2 "memory_operand" "m,m"))
274852296Sobrien   (clobber (match_operand:HI 3 "memory_operand" "m,m"))
274952296Sobrien   (clobber (match_operand:DI 4 "memory_operand" "m,o"))
275052296Sobrien   (clobber (match_scratch:HI 5 "=&r,&r"))]
275118334Speter  "TARGET_80387"
275252296Sobrien  "* return output_fix_trunc (insn, operands);"
275352296Sobrien  [(set_attr "type" "fpop")])
275418334Speter
275552296Sobrien(define_expand "fix_truncdfsi2"
275652296Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
275752296Sobrien		   (fix:SI (fix:DF (match_operand:DF 1 "register_operand" ""))))
275852296Sobrien	      (clobber (match_dup 2))
275952296Sobrien	      (clobber (match_dup 3))
276052296Sobrien	      (clobber (match_dup 4))
276152296Sobrien	      (clobber (match_scratch:HI 5 ""))])]
276218334Speter  "TARGET_80387"
276352296Sobrien  "
276452296Sobrien{
276552296Sobrien  operands[2] = (rtx) assign_386_stack_local (HImode, 0);
276652296Sobrien  operands[3] = (rtx) assign_386_stack_local (HImode, 1);
276752296Sobrien  operands[4] = (rtx) assign_386_stack_local (SImode, 0);
276852296Sobrien}")
276918334Speter
277018334Speter(define_insn ""
277153176Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=m,!&r")
277252296Sobrien	(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f,f"))))
277352296Sobrien   (clobber (match_operand:HI 2 "memory_operand" "m,m"))
277452296Sobrien   (clobber (match_operand:HI 3 "memory_operand" "m,m"))
277552296Sobrien   (clobber (match_operand:SI 4 "memory_operand" "m,m"))
277652296Sobrien   (clobber (match_scratch:HI 5 "=&r,&r"))]
277718334Speter  "TARGET_80387"
277852296Sobrien  "* return output_fix_trunc (insn, operands);"
277952296Sobrien  [(set_attr "type" "fpop")])
278018334Speter
278152296Sobrien(define_expand "fix_truncdfdi2"
278252296Sobrien  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
278352296Sobrien		   (fix:DI (fix:DF (match_operand:DF 1 "register_operand" ""))))
278452296Sobrien	      (clobber (match_dup 1))
278518334Speter	      (clobber (match_dup 2))
278618334Speter	      (clobber (match_dup 3))
278752296Sobrien	      (clobber (match_dup 4))
278852296Sobrien	      (clobber (match_scratch:HI 5 ""))])]
278918334Speter  "TARGET_80387"
279018334Speter  "
279118334Speter{
279252296Sobrien  operands[1] = copy_to_mode_reg (DFmode, operands[1]);
279352296Sobrien  operands[2] = (rtx) assign_386_stack_local (HImode, 0);
279452296Sobrien  operands[3] = (rtx) assign_386_stack_local (HImode, 1);
279552296Sobrien  operands[4] = (rtx) assign_386_stack_local (DImode, 0);
279618334Speter}")
279718334Speter
279852296Sobrien(define_insn ""
279953176Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!&r")
280052296Sobrien	(fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f,f"))))
280152296Sobrien   (clobber (match_dup 1))
280252296Sobrien   (clobber (match_operand:HI 2 "memory_operand" "m,m"))
280352296Sobrien   (clobber (match_operand:HI 3 "memory_operand" "m,m"))
280452296Sobrien   (clobber (match_operand:DI 4 "memory_operand" "m,o"))
280552296Sobrien   (clobber (match_scratch:HI 5 "=&r,&r"))]
280652296Sobrien  "TARGET_80387"
280752296Sobrien  "* return output_fix_trunc (insn, operands);"
280852296Sobrien  [(set_attr "type" "fpop")])
280952296Sobrien
281052296Sobrien(define_expand "fix_truncxfsi2"
281152296Sobrien  [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "")
281252296Sobrien		   (fix:SI (fix:XF (match_operand:XF 1 "register_operand" ""))))
281318334Speter	      (clobber (match_dup 2))
281418334Speter	      (clobber (match_dup 3))
281552296Sobrien	      (clobber (match_dup 4))
281652296Sobrien	      (clobber (match_scratch:HI 5 ""))])]
281718334Speter  "TARGET_80387"
281818334Speter  "
281918334Speter{
282052296Sobrien  operands[2] = (rtx) assign_386_stack_local (HImode, 0);
282152296Sobrien  operands[3] = (rtx) assign_386_stack_local (HImode, 1);
282252296Sobrien  operands[4] = (rtx) assign_386_stack_local (SImode, 0);
282318334Speter}")
282418334Speter
282552296Sobrien(define_insn ""
282653176Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=m,!&r")
282752296Sobrien	(fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f,f"))))
282852296Sobrien   (clobber (match_operand:HI 2 "memory_operand" "m,m"))
282952296Sobrien   (clobber (match_operand:HI 3 "memory_operand" "m,m"))
283052296Sobrien   (clobber (match_operand:SI 4 "memory_operand" "m,m"))
283152296Sobrien   (clobber (match_scratch:HI 5 "=&r,&r"))]
283252296Sobrien  "TARGET_80387"
283352296Sobrien  "* return output_fix_trunc (insn, operands);"
283452296Sobrien  [(set_attr "type" "fpop")])
283552296Sobrien
283652296Sobrien(define_expand "fix_truncxfdi2"
283752296Sobrien  [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "")
283852296Sobrien		   (fix:DI (fix:XF (match_operand:XF 1 "register_operand" ""))))
283952296Sobrien	      (clobber (match_dup 1))
284018334Speter	      (clobber (match_dup 2))
284118334Speter	      (clobber (match_dup 3))
284252296Sobrien	      (clobber (match_dup 4))
284352296Sobrien	      (clobber (match_scratch:HI 5 ""))])]
284418334Speter  "TARGET_80387"
284518334Speter  "
284618334Speter{
284752296Sobrien  operands[1] = copy_to_mode_reg (XFmode, operands[1]);
284852296Sobrien  operands[2] = (rtx) assign_386_stack_local (HImode, 0);
284952296Sobrien  operands[3] = (rtx) assign_386_stack_local (HImode, 1);
285052296Sobrien  operands[4] = (rtx) assign_386_stack_local (DImode, 0);
285118334Speter}")
285218334Speter
285318334Speter(define_insn ""
285453176Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!&r")
285552296Sobrien	(fix:DI (fix:XF (match_operand:XF 1 "register_operand" "f,f"))))
285652296Sobrien   (clobber (match_dup 1))
285752296Sobrien   (clobber (match_operand:HI 2 "memory_operand" "m,m"))
285852296Sobrien   (clobber (match_operand:HI 3 "memory_operand" "m,m"))
285952296Sobrien   (clobber (match_operand:DI 4 "memory_operand" "m,o"))
286052296Sobrien   (clobber (match_scratch:HI 5 "=&r,&r"))]
286118334Speter  "TARGET_80387"
286252296Sobrien  "* return output_fix_trunc (insn, operands);"
286352296Sobrien  [(set_attr "type" "fpop")])
286452296Sobrien
286552296Sobrien;; Conversion between fixed point and floating point.
286618334Speter
286752296Sobrien;; ??? Possibly represent floatunssidf2 here in gcc2.
286852296Sobrien
286952296Sobrien(define_expand "floatsisf2"
287052296Sobrien  [(parallel [(set (match_operand:SF 0 "register_operand" "")
287152296Sobrien		   (float:SF (match_operand:SI 1 "nonimmediate_operand" "")))
287252296Sobrien	      (clobber (match_dup 2))])]
287352296Sobrien  "TARGET_80387"
287452296Sobrien  "operands[2] = assign_386_stack_local (SImode, 0);")
287552296Sobrien
287618334Speter(define_insn ""
287752296Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
287852296Sobrien	(float:SF (match_operand:SI 1 "nonimmediate_operand" "m,!r")))
287952296Sobrien   (clobber (match_operand:SI 2 "memory_operand" "m,m"))]
288018334Speter  "TARGET_80387"
288152296Sobrien  "#")
288218334Speter
288352296Sobrien(define_split
288452296Sobrien  [(set (match_operand:SF 0 "register_operand" "")
288552296Sobrien	(float:SF (match_operand:SI 1 "memory_operand" "")))
288652296Sobrien   (clobber (match_operand:SI 2 "memory_operand" ""))]
288752296Sobrien  "TARGET_80387 && reload_completed"
288852296Sobrien  [(set (match_dup 0)
288952296Sobrien	(float:SF (match_dup 1)))]
289052296Sobrien  "")
289152296Sobrien
289252296Sobrien(define_split
289352296Sobrien  [(set (match_operand:SF 0 "register_operand" "")
289452296Sobrien	(float:SF (match_operand:SI 1 "register_operand" "")))
289552296Sobrien   (clobber (match_operand:SI 2 "memory_operand" ""))]
289652296Sobrien  "TARGET_80387 && reload_completed"
289752296Sobrien  [(set (match_dup 2)
289852296Sobrien	(match_dup 1))
289952296Sobrien   (set (match_dup 0)
290052296Sobrien	(float:SF (match_dup 2)))]
290152296Sobrien  "")
290252296Sobrien
290318334Speter(define_insn ""
290452296Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
290552296Sobrien	(float:SF (match_operand:SI 1 "memory_operand" "m")))]
290618334Speter  "TARGET_80387"
290752296Sobrien  "* return AS1 (fild%z1,%1);"
290852296Sobrien  [(set_attr "type" "fpop")])
290918334Speter
291052296Sobrien(define_expand "floathisf2"
291152296Sobrien  [(parallel [(set (match_operand:SF 0 "register_operand" "")
291252296Sobrien		   (float:SF (match_operand:HI 1 "nonimmediate_operand" "")))
291352296Sobrien	      (clobber (match_dup 2))])]
291452296Sobrien  "TARGET_80387"
291552296Sobrien  "operands[2] = assign_386_stack_local (HImode, 0);")
291618334Speter
291752296Sobrien(define_insn ""
291852296Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
291952296Sobrien	(float:SF (match_operand:HI 1 "nonimmediate_operand" "m,!r")))
292052296Sobrien   (clobber (match_operand:HI 2 "memory_operand" "m,m"))]
292152296Sobrien  "TARGET_80387"
292252296Sobrien  "#")
292352296Sobrien
292452296Sobrien(define_split
292518334Speter  [(set (match_operand:SF 0 "register_operand" "")
292652296Sobrien	(float:SF (match_operand:HI 1 "memory_operand" "")))
292752296Sobrien   (clobber (match_operand:HI 2 "memory_operand" ""))]
292852296Sobrien  "TARGET_80387 && reload_completed"
292952296Sobrien  [(set (match_dup 0)
293052296Sobrien	(float:SF (match_dup 1)))]
293118334Speter  "")
293218334Speter
293352296Sobrien(define_split
293452296Sobrien  [(set (match_operand:SF 0 "register_operand" "")
293552296Sobrien	(float:SF (match_operand:HI 1 "register_operand" "")))
293652296Sobrien   (clobber (match_operand:HI 2 "memory_operand" ""))]
293752296Sobrien  "TARGET_80387 && reload_completed"
293852296Sobrien  [(set (match_dup 2)
293952296Sobrien	(match_dup 1))
294052296Sobrien   (set (match_dup 0)
294152296Sobrien	(float:SF (match_dup 2)))]
294252296Sobrien  "")
294352296Sobrien
294452296Sobrien(define_insn ""
294552296Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
294652296Sobrien	(float:SF (match_operand:HI 1 "memory_operand" "m")))]
294752296Sobrien  "TARGET_80387"
294852296Sobrien  "* return AS1 (fild%z1,%1);"
294952296Sobrien  [(set_attr "type" "fpop")])
295052296Sobrien
295118334Speter(define_expand "floatdisf2"
295252296Sobrien  [(parallel [(set (match_operand:SF 0 "register_operand" "")
295352296Sobrien		   (float:SF (match_operand:DI 1 "nonimmediate_operand" "")))
295452296Sobrien	      (clobber (match_dup 2))])]
295552296Sobrien  "TARGET_80387"
295652296Sobrien  "operands[2] = assign_386_stack_local (DImode, 0);")
295752296Sobrien
295852296Sobrien(define_insn ""
295952296Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
296052296Sobrien	(float:SF (match_operand:DI 1 "nonimmediate_operand" "m,!r")))
296152296Sobrien      (clobber (match_operand:DI 2 "memory_operand" "m,o"))]
296252296Sobrien  "TARGET_80387"
296352296Sobrien  "#")
296452296Sobrien
296552296Sobrien(define_split
296618334Speter  [(set (match_operand:SF 0 "register_operand" "")
296752296Sobrien	(float:SF (match_operand:DI 1 "memory_operand" "")))
296852296Sobrien   (clobber (match_operand:DI 2 "memory_operand" ""))]
296952296Sobrien  "TARGET_80387 && reload_completed"
297052296Sobrien  [(set (match_dup 0)
297152296Sobrien	(float:SF (match_dup 1)))]
297218334Speter  "")
297318334Speter
297452296Sobrien(define_split
297552296Sobrien  [(set (match_operand:SF 0 "register_operand" "")
297652296Sobrien	(float:SF (match_operand:DI 1 "register_operand" "")))
297752296Sobrien   (clobber (match_operand:DI 2 "memory_operand" ""))]
297852296Sobrien  "TARGET_80387 && reload_completed"
297952296Sobrien  [(set (match_dup 2)
298052296Sobrien	(match_dup 1))
298152296Sobrien   (set (match_dup 0)
298252296Sobrien	(float:SF (match_dup 2)))]
298352296Sobrien  "")
298452296Sobrien
298552296Sobrien(define_insn ""
298652296Sobrien  [(set (match_operand:SF 0 "register_operand" "=f")
298752296Sobrien	(float:SF (match_operand:DI 1 "memory_operand" "m")))]
298852296Sobrien  "TARGET_80387"
298952296Sobrien  "* return AS1 (fild%z1,%1);"
299052296Sobrien  [(set_attr "type" "fpop")])
299152296Sobrien
299218334Speter(define_expand "floatsidf2"
299352296Sobrien  [(parallel [(set (match_operand:DF 0 "register_operand" "")
299452296Sobrien		   (float:DF (match_operand:SI 1 "nonimmediate_operand" "")))
299552296Sobrien	      (clobber (match_dup 2))])]
299652296Sobrien  "TARGET_80387"
299752296Sobrien  "operands[2] = assign_386_stack_local (SImode, 0);")
299852296Sobrien
299952296Sobrien(define_insn ""
300052296Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
300152296Sobrien	(float:DF (match_operand:SI 1 "nonimmediate_operand" "m,!r")))
300252296Sobrien   (clobber (match_operand:SI 2 "memory_operand" "m,m"))]
300352296Sobrien  "TARGET_80387"
300452296Sobrien  "#")
300552296Sobrien
300652296Sobrien(define_split
300718334Speter  [(set (match_operand:DF 0 "register_operand" "")
300852296Sobrien	(float:DF (match_operand:SI 1 "memory_operand" "")))
300952296Sobrien   (clobber (match_operand:SI 2 "memory_operand" ""))]
301052296Sobrien  "TARGET_80387 && reload_completed"
301152296Sobrien  [(set (match_dup 0)
301252296Sobrien	(float:DF (match_dup 1)))]
301352296Sobrien  "")
301452296Sobrien
301552296Sobrien(define_split
301652296Sobrien  [(set (match_operand:DF 0 "register_operand" "")
301752296Sobrien	(float:DF (match_operand:SI 1 "register_operand" "")))
301852296Sobrien   (clobber (match_operand:SI 2 "memory_operand" ""))]
301952296Sobrien  "TARGET_80387 && reload_completed"
302052296Sobrien  [(set (match_dup 2)
302152296Sobrien	(match_dup 1))
302252296Sobrien   (set (match_dup 0)
302352296Sobrien	(float:DF (match_dup 2)))]
302452296Sobrien  "")
302552296Sobrien
302652296Sobrien(define_insn ""
302752296Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
302852296Sobrien	(float:DF (match_operand:SI 1 "memory_operand" "m")))]
302918334Speter  "TARGET_80387"
303052296Sobrien  "* return AS1 (fild%z1,%1);"
303152296Sobrien  [(set_attr "type" "fpop")])
303252296Sobrien
303352296Sobrien(define_expand "floathidf2"
303452296Sobrien  [(parallel [(set (match_operand:DF 0 "register_operand" "")
303552296Sobrien		   (float:DF (match_operand:HI 1 "nonimmediate_operand" "")))
303652296Sobrien	      (clobber (match_dup 2))])]
303752296Sobrien  "TARGET_80387"
303852296Sobrien  "operands[2] = assign_386_stack_local (HImode, 0);")
303952296Sobrien
304052296Sobrien(define_insn ""
304152296Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
304252296Sobrien	(float:DF (match_operand:HI 1 "nonimmediate_operand" "m,!r")))
304352296Sobrien   (clobber (match_operand:HI 2 "memory_operand" "m,m"))]
304452296Sobrien  "TARGET_80387"
304552296Sobrien  "#")
304652296Sobrien
304752296Sobrien(define_split
304852296Sobrien  [(set (match_operand:DF 0 "register_operand" "")
304952296Sobrien	(float:DF (match_operand:HI 1 "memory_operand" "")))
305052296Sobrien   (clobber (match_operand:HI 2 "memory_operand" ""))]
305152296Sobrien  "TARGET_80387 && reload_completed"
305252296Sobrien  [(set (match_dup 0)
305352296Sobrien	(float:DF (match_dup 1)))]
305418334Speter  "")
305518334Speter
305652296Sobrien(define_split
305752296Sobrien  [(set (match_operand:DF 0 "register_operand" "")
305852296Sobrien	(float:DF (match_operand:HI 1 "register_operand" "")))
305952296Sobrien   (clobber (match_operand:HI 2 "memory_operand" ""))]
306052296Sobrien  "TARGET_80387 && reload_completed"
306152296Sobrien  [(set (match_dup 2)
306252296Sobrien	(match_dup 1))
306352296Sobrien   (set (match_dup 0)
306452296Sobrien	(float:DF (match_dup 2)))]
306552296Sobrien  "")
306652296Sobrien
306752296Sobrien(define_insn ""
306852296Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
306952296Sobrien	(float:DF (match_operand:HI 1 "memory_operand" "m")))]
307052296Sobrien  "TARGET_80387"
307152296Sobrien  "* return AS1 (fild%z1,%1);"
307252296Sobrien  [(set_attr "type" "fpop")])
307352296Sobrien
307418334Speter(define_expand "floatdidf2"
307552296Sobrien  [(parallel [(set (match_operand:DF 0 "register_operand" "")
307652296Sobrien		   (float:DF (match_operand:DI 1 "nonimmediate_operand" "")))
307752296Sobrien	      (clobber (match_dup 2))])]
307852296Sobrien  "TARGET_80387"
307952296Sobrien  "operands[2] = assign_386_stack_local (DImode, 0);")
308052296Sobrien
308152296Sobrien(define_insn ""
308252296Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
308352296Sobrien	(float:DF (match_operand:DI 1 "nonimmediate_operand" "m,!r")))
308452296Sobrien   (clobber (match_operand:DI 2 "memory_operand" "m,o"))]
308552296Sobrien  "TARGET_80387"
308652296Sobrien  "#")
308752296Sobrien
308852296Sobrien(define_split
308918334Speter  [(set (match_operand:DF 0 "register_operand" "")
309052296Sobrien	(float:DF (match_operand:DI 1 "memory_operand" "")))
309152296Sobrien   (clobber (match_operand:DI 2 "memory_operand" ""))]
309252296Sobrien  "TARGET_80387 && reload_completed"
309352296Sobrien  [(set (match_dup 0)
309452296Sobrien	(float:DF (match_dup 1)))]
309518334Speter  "")
309618334Speter
309752296Sobrien(define_split
309852296Sobrien  [(set (match_operand:DF 0 "register_operand" "")
309952296Sobrien	(float:DF (match_operand:DI 1 "register_operand" "")))
310052296Sobrien   (clobber (match_operand:DI 2 "memory_operand" ""))]
310152296Sobrien  "TARGET_80387 && reload_completed"
310252296Sobrien  [(set (match_dup 2)
310352296Sobrien	(match_dup 1))
310452296Sobrien   (set (match_dup 0)
310552296Sobrien	(float:DF (match_dup 2)))]
310652296Sobrien  "")
310752296Sobrien
310852296Sobrien(define_insn ""
310952296Sobrien  [(set (match_operand:DF 0 "register_operand" "=f")
311052296Sobrien	(float:DF (match_operand:DI 1 "memory_operand" "m")))]
311152296Sobrien  "TARGET_80387"
311252296Sobrien  "* return AS1 (fild%z1,%1);"
311352296Sobrien  [(set_attr "type" "fpop")])
311452296Sobrien
311518334Speter(define_expand "floatsixf2"
311652296Sobrien  [(parallel [(set (match_operand:XF 0 "register_operand" "")
311752296Sobrien		   (float:XF (match_operand:SI 1 "nonimmediate_operand" "")))
311852296Sobrien	      (clobber (match_dup 2))])]
311952296Sobrien  "TARGET_80387"
312052296Sobrien  "operands[2] = assign_386_stack_local (SImode, 0);")
312152296Sobrien
312252296Sobrien(define_insn ""
312352296Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
312452296Sobrien	(float:XF (match_operand:SI 1 "nonimmediate_operand" "m,!r")))
312552296Sobrien   (clobber (match_operand:SI 2 "memory_operand" "m,m"))]
312652296Sobrien  "TARGET_80387"
312752296Sobrien  "#")
312852296Sobrien
312952296Sobrien(define_split
313018334Speter  [(set (match_operand:XF 0 "register_operand" "")
313152296Sobrien	(float:XF (match_operand:SI 1 "memory_operand" "")))
313252296Sobrien   (clobber (match_operand:SI 2 "memory_operand" ""))]
313352296Sobrien  "TARGET_80387 && reload_completed"
313452296Sobrien  [(set (match_dup 0)
313552296Sobrien	(float:XF (match_dup 1)))]
313618334Speter  "")
313718334Speter
313852296Sobrien(define_split
313918334Speter  [(set (match_operand:XF 0 "register_operand" "")
314052296Sobrien	(float:XF (match_operand:SI 1 "register_operand" "")))
314152296Sobrien   (clobber (match_operand:SI 2 "memory_operand" ""))]
314252296Sobrien  "TARGET_80387 && reload_completed"
314352296Sobrien  [(set (match_dup 2)
314452296Sobrien	(match_dup 1))
314552296Sobrien   (set (match_dup 0)
314652296Sobrien	(float:XF (match_dup 2)))]
314718334Speter  "")
314818334Speter
314918334Speter(define_insn ""
315018334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
315152296Sobrien	(float:XF (match_operand:SI 1 "memory_operand" "m")))]
315218334Speter  "TARGET_80387"
315352296Sobrien  "* return AS1 (fild%z1,%1);"
315452296Sobrien  [(set_attr "type" "fpop")])
315518334Speter
315652296Sobrien(define_expand "floathixf2"
315752296Sobrien  [(parallel [(set (match_operand:XF 0 "register_operand" "")
315852296Sobrien		   (float:XF (match_operand:HI 1 "nonimmediate_operand" "")))
315952296Sobrien	      (clobber (match_dup 2))])]
316018334Speter  "TARGET_80387"
316152296Sobrien  "operands[2] = assign_386_stack_local (HImode, 0);")
316218334Speter
316318334Speter(define_insn ""
316452296Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
316552296Sobrien	(float:XF (match_operand:HI 1 "nonimmediate_operand" "m,!r")))
316652296Sobrien   (clobber (match_operand:HI 2 "memory_operand" "m,m"))]
316718334Speter  "TARGET_80387"
316852296Sobrien  "#")
316918334Speter
317052296Sobrien(define_split
317152296Sobrien  [(set (match_operand:XF 0 "register_operand" "")
317252296Sobrien	(float:XF (match_operand:HI 1 "memory_operand" "")))
317352296Sobrien   (clobber (match_operand:HI 2 "memory_operand" ""))]
317452296Sobrien  "TARGET_80387 && reload_completed"
317552296Sobrien  [(set (match_dup 0)
317652296Sobrien	(float:XF (match_dup 1)))]
317752296Sobrien  "")
317852296Sobrien
317952296Sobrien(define_split
318052296Sobrien  [(set (match_operand:XF 0 "register_operand" "")
318152296Sobrien	(float:XF (match_operand:HI 1 "register_operand" "")))
318252296Sobrien   (clobber (match_operand:HI 2 "memory_operand" ""))]
318352296Sobrien  "TARGET_80387 && reload_completed"
318452296Sobrien  [(set (match_dup 2)
318552296Sobrien	(match_dup 1))
318652296Sobrien   (set (match_dup 0)
318752296Sobrien	(float:XF (match_dup 2)))]
318852296Sobrien  "")
318952296Sobrien
319018334Speter(define_insn ""
319152296Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
319252296Sobrien	(float:XF (match_operand:HI 1 "memory_operand" "m")))]
319318334Speter  "TARGET_80387"
319452296Sobrien  "* return AS1 (fild%z1,%1);"
319552296Sobrien  [(set_attr "type" "fpop")])
319618334Speter
319752296Sobrien(define_expand "floatdixf2"
319852296Sobrien  [(parallel [(set (match_operand:XF 0 "register_operand" "")
319952296Sobrien		   (float:XF (match_operand:DI 1 "nonimmediate_operand" "")))
320052296Sobrien	      (clobber (match_dup 2))])]
320152296Sobrien  "TARGET_80387"
320252296Sobrien  "operands[2] = assign_386_stack_local (DImode, 0);")
320352296Sobrien
320418334Speter(define_insn ""
320518334Speter  [(set (match_operand:XF 0 "register_operand" "=f,f")
320652296Sobrien	(float:XF (match_operand:DI 1 "nonimmediate_operand" "m,!r")))
320752296Sobrien   (clobber (match_operand:DI 2 "memory_operand" "m,o"))]
320818334Speter  "TARGET_80387"
320952296Sobrien  "#")
321018334Speter
321152296Sobrien(define_split
321252296Sobrien  [(set (match_operand:XF 0 "register_operand" "")
321352296Sobrien	(float:XF (match_operand:DI 1 "memory_operand" "")))
321452296Sobrien   (clobber (match_operand:DI 2 "memory_operand" ""))]
321552296Sobrien  "TARGET_80387 && reload_completed"
321652296Sobrien  [(set (match_dup 0)
321752296Sobrien	(float:XF (match_dup 1)))]
321852296Sobrien  "")
321952296Sobrien
322052296Sobrien(define_split
322152296Sobrien  [(set (match_operand:XF 0 "register_operand" "")
322252296Sobrien	(float:XF (match_operand:DI 1 "register_operand" "")))
322352296Sobrien   (clobber (match_operand:DI 2 "memory_operand" ""))]
322452296Sobrien  "TARGET_80387 && reload_completed"
322552296Sobrien  [(set (match_dup 2)
322652296Sobrien	(match_dup 1))
322752296Sobrien   (set (match_dup 0)
322852296Sobrien	(float:XF (match_dup 2)))]
322952296Sobrien  "")
323052296Sobrien
323118334Speter(define_insn ""
323252296Sobrien  [(set (match_operand:XF 0 "register_operand" "=f")
323352296Sobrien	(float:XF (match_operand:DI 1 "memory_operand" "m")))]
323418334Speter  "TARGET_80387"
323552296Sobrien  "* return AS1 (fild%z1,%1);"
323652296Sobrien  [(set_attr "type" "fpop")])
323718334Speter
323818334Speter;;- add instructions
323918334Speter
324052296Sobrien(define_insn "*addsidi3_1"
324150650Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,!&r,!r,o,!o")
324250650Sobrien	(plus:DI (match_operand:DI 1 "general_operand" "0,0,0,o,riF,riF,o")
324350650Sobrien		 (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,roi,roi,ri,ri"))))
324450650Sobrien   (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,&r"))]
324550650Sobrien  ""
324650650Sobrien  "*
324750650Sobrien{
324852296Sobrien  rtx low[3], high[3], xops[7];
324950650Sobrien
325050650Sobrien  CC_STATUS_INIT;
325150650Sobrien
325250650Sobrien  split_di (operands, 2, low, high);
325350650Sobrien  high[2] = const0_rtx;
325450650Sobrien  low[2]  = operands[2];
325550650Sobrien
325650650Sobrien  if (!rtx_equal_p (operands[0], operands[1]))
325750650Sobrien    {
325850650Sobrien      xops[0] = high[0];
325950650Sobrien      xops[1] = low[0];
326050650Sobrien      xops[2] = high[1];
326150650Sobrien      xops[3] = low[1];
326250650Sobrien
326350650Sobrien      if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
326450650Sobrien	{
326550650Sobrien	  output_asm_insn (AS2 (mov%L1,%3,%1), xops);
326650650Sobrien	  output_asm_insn (AS2 (mov%L0,%2,%0), xops);
326750650Sobrien	}
326850650Sobrien      else
326950650Sobrien	{
327050650Sobrien	  xops[4] = high[2];
327150650Sobrien	  xops[5] = low[2];
327250650Sobrien	  xops[6] = operands[3];
327350650Sobrien	  output_asm_insn (AS2 (mov%L6,%3,%6), xops);
327450650Sobrien	  output_asm_insn (AS2 (add%L6,%5,%6), xops);
327550650Sobrien	  output_asm_insn (AS2 (mov%L1,%6,%1), xops);
327650650Sobrien	  output_asm_insn (AS2 (mov%L6,%2,%6), xops);
327750650Sobrien	  output_asm_insn (AS2 (adc%L6,%4,%6), xops);
327850650Sobrien	  output_asm_insn (AS2 (mov%L0,%6,%0), xops);
327950650Sobrien	  RET;
328050650Sobrien	}
328150650Sobrien    }
328250650Sobrien
328350650Sobrien  output_asm_insn (AS2 (add%L0,%2,%0), low);
328450650Sobrien  output_asm_insn (AS2 (adc%L0,%2,%0), high);
328552296Sobrien  cc_status.value1 = high[0];
328652296Sobrien  cc_status.flags = CC_NO_OVERFLOW;
328750650Sobrien  RET;
328852296Sobrien}"
328952296Sobrien  [(set_attr "type" "binary")])
329050650Sobrien
329150650Sobrien(define_insn "addsidi3_2"
329250650Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,&r,!&r,&r,o,o,!o")
329350650Sobrien	(plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,o,o,ri,ri,i,r"))
329450650Sobrien		 (match_operand:DI 1 "general_operand" "0,0,0,iF,ro,roiF,riF,o,o")))
329550650Sobrien   (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,X,&r,&r"))]
329650650Sobrien  ""
329750650Sobrien  "*
329850650Sobrien{
329952296Sobrien  rtx low[3], high[3], xops[7];
330050650Sobrien
330150650Sobrien  CC_STATUS_INIT;
330250650Sobrien
330350650Sobrien  split_di (operands, 2, low, high);
330450650Sobrien  high[2] = const0_rtx;
330550650Sobrien  low[2]  = operands[2];
330650650Sobrien
330750650Sobrien  if (!rtx_equal_p (operands[0], operands[1]))
330850650Sobrien    {
330950650Sobrien      xops[0] = high[0];
331050650Sobrien      xops[1] = low[0];
331150650Sobrien      xops[2] = high[1];
331250650Sobrien      xops[3] = low[1];
331350650Sobrien
331450650Sobrien      if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
331550650Sobrien	{
331650650Sobrien	  if (rtx_equal_p (low[0], operands[2]))
331750650Sobrien	    {
331850650Sobrien	      output_asm_insn (AS2 (mov%L0,%2,%0), high);
331950650Sobrien	      output_asm_insn (AS2 (add%L0,%1,%0), low);
332050650Sobrien	      output_asm_insn (AS2 (adc%L0,%1,%0), high);
332150650Sobrien	      RET;
332250650Sobrien	    }
332350650Sobrien	  if (rtx_equal_p (high[0], operands[2]))
332450650Sobrien	    {
332550650Sobrien	      if (GET_CODE (operands[0]) != MEM)
332650650Sobrien		{
332750650Sobrien		  output_asm_insn (AS2 (mov%L0,%2,%0), low);
332850650Sobrien		  output_asm_insn (AS2 (mov%L0,%2,%0), high);
332950650Sobrien		  output_asm_insn (AS2 (add%L0,%1,%0), low);
333050650Sobrien		  output_asm_insn (AS2 (adc%L0,%1,%0), high);
333150650Sobrien		}
333250650Sobrien	      else
333350650Sobrien		{
333450650Sobrien		  /* It's too late to ask for a scratch now - but this
333550650Sobrien		     will probably not happen too often.  */
333650650Sobrien		  output_asm_insn (AS2 (add%L1,%2,%1), low);
333750650Sobrien		  output_asm_insn (AS2 (mov%L0,%1,%0), low);
333850650Sobrien		  output_asm_insn (AS2 (mov%L1,%2,%1), low);
333950650Sobrien		  output_asm_insn (AS2 (mov%L0,%2,%0), high);
334050650Sobrien		  output_asm_insn (AS2 (adc%L0,%1,%0), high);
334150650Sobrien		  output_asm_insn (AS2 (sub%L1,%0,%1), low);
334250650Sobrien		  output_asm_insn (AS1 (neg%L1,%1), low);
334350650Sobrien		}
334450650Sobrien	      RET;
334550650Sobrien	    }
334650650Sobrien	  output_asm_insn (AS2 (mov%L1,%3,%1), xops);
334750650Sobrien	  output_asm_insn (AS2 (mov%L0,%2,%0), xops);
334850650Sobrien	}
334950650Sobrien      else
335050650Sobrien	{
335150650Sobrien	  xops[4] = high[2];
335250650Sobrien	  xops[5] = low[2];
335350650Sobrien	  xops[6] = operands[3];
335450650Sobrien	  output_asm_insn (AS2 (mov%L6,%3,%6), xops);
335550650Sobrien	  output_asm_insn (AS2 (add%L6,%5,%6), xops);
335650650Sobrien	  output_asm_insn (AS2 (mov%L1,%6,%1), xops);
335750650Sobrien	  output_asm_insn (AS2 (mov%L6,%2,%6), xops);
335850650Sobrien	  output_asm_insn (AS2 (adc%L6,%4,%6), xops);
335950650Sobrien	  output_asm_insn (AS2 (mov%L0,%6,%0), xops);
336050650Sobrien	  RET;
336150650Sobrien	}
336250650Sobrien    }
336350650Sobrien
336450650Sobrien  output_asm_insn (AS2 (add%L0,%2,%0), low);
336550650Sobrien  output_asm_insn (AS2 (adc%L0,%2,%0), high);
336652296Sobrien  cc_status.value1 = high[0];
336752296Sobrien  cc_status.flags = CC_NO_OVERFLOW;
336850650Sobrien  RET;
336952296Sobrien}"
337052296Sobrien  [(set_attr "type" "binary")])
337150650Sobrien
337218334Speter(define_insn "adddi3"
337350650Sobrien  [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
337450650Sobrien	(plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o")
337550650Sobrien		 (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o")))
337650650Sobrien   (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))]
337718334Speter  ""
337818334Speter  "*
337918334Speter{
338018334Speter  rtx low[3], high[3], xops[7], temp;
338118334Speter
338218334Speter  CC_STATUS_INIT;
338318334Speter
338418334Speter  if (rtx_equal_p (operands[0], operands[2]))
338518334Speter    {
338618334Speter      temp = operands[1];
338718334Speter      operands[1] = operands[2];
338818334Speter      operands[2] = temp;
338918334Speter    }
339018334Speter
339118334Speter  split_di (operands, 3, low, high);
339218334Speter  if (!rtx_equal_p (operands[0], operands[1]))
339318334Speter    {
339418334Speter      xops[0] = high[0];
339518334Speter      xops[1] = low[0];
339618334Speter      xops[2] = high[1];
339718334Speter      xops[3] = low[1];
339818334Speter
339918334Speter      if (GET_CODE (operands[0]) != MEM)
340018334Speter	{
340118334Speter	  output_asm_insn (AS2 (mov%L1,%3,%1), xops);
340218334Speter	  output_asm_insn (AS2 (mov%L0,%2,%0), xops);
340318334Speter	}
340418334Speter      else
340518334Speter	{
340618334Speter	  xops[4] = high[2];
340718334Speter	  xops[5] = low[2];
340818334Speter	  xops[6] = operands[3];
340918334Speter	  output_asm_insn (AS2 (mov%L6,%3,%6), xops);
341018334Speter	  output_asm_insn (AS2 (add%L6,%5,%6), xops);
341118334Speter	  output_asm_insn (AS2 (mov%L1,%6,%1), xops);
341218334Speter	  output_asm_insn (AS2 (mov%L6,%2,%6), xops);
341318334Speter	  output_asm_insn (AS2 (adc%L6,%4,%6), xops);
341418334Speter	  output_asm_insn (AS2 (mov%L0,%6,%0), xops);
341518334Speter	  RET;
341618334Speter	}
341718334Speter    }
341818334Speter
341952296Sobrien  cc_status.value1 = high[0];
342052296Sobrien  cc_status.flags = CC_NO_OVERFLOW;
342152296Sobrien
342218334Speter  if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG)
342318334Speter    {
342418334Speter      xops[0] = high[0];
342518334Speter      xops[1] = low[0];
342618334Speter      xops[2] = high[2];
342718334Speter      xops[3] = low[2];
342818334Speter      xops[4] = operands[3];
342918334Speter
343018334Speter      output_asm_insn (AS2 (mov%L4,%3,%4), xops);
343118334Speter      output_asm_insn (AS2 (add%L1,%4,%1), xops);
343218334Speter      output_asm_insn (AS2 (mov%L4,%2,%4), xops);
343318334Speter      output_asm_insn (AS2 (adc%L0,%4,%0), xops);
343418334Speter    }
343518334Speter
343618334Speter  else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
343718334Speter    {
343818334Speter      output_asm_insn (AS2 (add%L0,%2,%0), low);
343918334Speter      output_asm_insn (AS2 (adc%L0,%2,%0), high);
344018334Speter    }
344118334Speter
344218334Speter  else
344318334Speter    output_asm_insn (AS2 (add%L0,%2,%0), high);
344418334Speter
344518334Speter  RET;
344652296Sobrien}"
344752296Sobrien  [(set_attr "type" "binary")])
344818334Speter
344918334Speter;; On a 486, it is faster to do movl/addl than to do a single leal if
345018334Speter;; operands[1] and operands[2] are both registers.
345118334Speter
345250650Sobrien(define_expand "addsi3"
345350650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
345450650Sobrien	(plus:SI (match_operand:SI 1 "nonimmediate_operand" "")
345550650Sobrien		 (match_operand:SI 2 "general_operand" "")))]
345618334Speter  ""
345750650Sobrien  "IX86_EXPAND_BINARY_OPERATOR (PLUS, SImode, operands);")
345850650Sobrien
345950650Sobrien(define_insn ""
346050650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r")
346150650Sobrien	(plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r")
346250650Sobrien		 (match_operand:SI 2 "general_operand" "rmi,ri,ri")))]
346350650Sobrien  "ix86_binary_operator_ok (PLUS, SImode, operands)"
346418334Speter  "*
346518334Speter{
346650650Sobrien  if (REG_P (operands[0]) && REG_P (operands[1])
346752296Sobrien      && (REG_P (operands[2]) || CONSTANT_P (operands[2]))
346850650Sobrien      && REGNO (operands[0]) != REGNO (operands[1]))
346918334Speter    {
347018334Speter      if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
347118334Speter	return AS2 (add%L0,%1,%0);
347218334Speter
347318334Speter      if (operands[2] == stack_pointer_rtx)
347418334Speter	{
347518334Speter	  rtx temp;
347618334Speter
347718334Speter	  temp = operands[1];
347818334Speter	  operands[1] = operands[2];
347918334Speter	  operands[2] = temp;
348018334Speter	}
348118334Speter
348218334Speter      if (operands[2] != stack_pointer_rtx)
348318334Speter	{
348418334Speter	  CC_STATUS_INIT;
348518334Speter	  operands[1] = SET_SRC (PATTERN (insn));
348618334Speter	  return AS2 (lea%L0,%a1,%0);
348718334Speter	}
348818334Speter    }
348918334Speter
349050650Sobrien  if (!rtx_equal_p (operands[0], operands[1]))
349150650Sobrien    output_asm_insn (AS2 (mov%L0,%1,%0), operands);
349250650Sobrien
349318334Speter  if (operands[2] == const1_rtx)
349418334Speter    return AS1 (inc%L0,%0);
349518334Speter
349618334Speter  if (operands[2] == constm1_rtx)
349718334Speter    return AS1 (dec%L0,%0);
349818334Speter
349950650Sobrien  /* subl $-128,%ebx is smaller than addl $128,%ebx. */
350050650Sobrien  if (GET_CODE (operands[2]) == CONST_INT
350150650Sobrien      && INTVAL (operands[2]) == 128)
350250650Sobrien    {
350350650Sobrien      /* This doesn't compute the carry bit in the same way
350450650Sobrien       * as add%L0, but we use inc and dec above and they
350550650Sobrien       * don't set the carry bit at all.  If inc/dec don't need
350650650Sobrien       * a CC_STATUS_INIT, this doesn't either... */
350750650Sobrien      operands[2] = GEN_INT (-128);
350850650Sobrien      return AS2 (sub%L0,%2,%0);
350950650Sobrien    }
351050650Sobrien
351118334Speter  return AS2 (add%L0,%2,%0);
351252296Sobrien}"
351352296Sobrien  [(set_attr "type" "binary")])
351418334Speter
351550650Sobrien;; addsi3 is faster, so put this after.
351650650Sobrien
351750650Sobrien(define_insn "movsi_lea"
351850650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
351950650Sobrien        (match_operand:QI 1 "address_operand" "p"))]
352050650Sobrien  ""
352150650Sobrien  "*
352250650Sobrien{
352350650Sobrien  /* Adding a constant to a register is faster with an add.  */
352450650Sobrien  /* ??? can this ever happen? */
352550650Sobrien  if (GET_CODE (operands[1]) == PLUS
352650650Sobrien      && GET_CODE (XEXP (operands[1], 1)) == CONST_INT
352750650Sobrien      && rtx_equal_p (operands[0], XEXP (operands[1], 0)))
352850650Sobrien    {
352950650Sobrien      operands[1] = XEXP (operands[1], 1);
353050650Sobrien
353150650Sobrien      if (operands[1] == const1_rtx)
353250650Sobrien        return AS1 (inc%L0,%0);
353350650Sobrien
353450650Sobrien      if (operands[1] == constm1_rtx)
353550650Sobrien        return AS1 (dec%L0,%0);
353650650Sobrien
353750650Sobrien      return AS2 (add%L0,%1,%0);
353850650Sobrien    }
353950650Sobrien
354050650Sobrien  CC_STATUS_INIT;
354150650Sobrien  return AS2 (lea%L0,%a1,%0);
354252296Sobrien}"
354352296Sobrien  [(set_attr "type" "lea")])
354450650Sobrien
354518334Speter;; ??? `lea' here, for three operand add?  If leaw is used, only %bx,
354618334Speter;; %si and %di can appear in SET_SRC, and output_asm_insn might not be
354718334Speter;; able to handle the operand.  But leal always works?
354818334Speter
354950650Sobrien(define_expand "addhi3"
355050650Sobrien  [(set (match_operand:HI 0 "general_operand" "")
355150650Sobrien	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "")
355250650Sobrien		 (match_operand:HI 2 "general_operand" "")))]
355350650Sobrien  ""
355450650Sobrien  "IX86_EXPAND_BINARY_OPERATOR (PLUS, HImode, operands);")
355550650Sobrien
355650650Sobrien(define_insn ""
355752296Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,?r")
355852296Sobrien	(plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r")
355952296Sobrien		 (match_operand:HI 2 "general_operand" "ri,rm,ri")))]
356050650Sobrien  "ix86_binary_operator_ok (PLUS, HImode, operands)"
356118334Speter  "*
356218334Speter{
356352296Sobrien  if (REG_P (operands[0]) && REG_P (operands[1])
356452296Sobrien      && (REG_P (operands[2]) || CONSTANT_P (operands[2]))
356552296Sobrien      && REGNO (operands[0]) != REGNO (operands[1]))
356652296Sobrien    {
356752296Sobrien      if (operands[2] == stack_pointer_rtx) 
356852296Sobrien	abort ();
356952296Sobrien
357052296Sobrien      CC_STATUS_INIT;
357152296Sobrien      operands[1]
357252296Sobrien	= gen_rtx_PLUS (SImode,
357352296Sobrien			gen_rtx_REG (SImode, REGNO (operands[1])),
357452296Sobrien			(! REG_P (operands[2])
357552296Sobrien			 ? operands[2]
357652296Sobrien			 : gen_rtx_REG (SImode, REGNO (operands[2]))));
357752296Sobrien      operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
357852296Sobrien      return AS2 (lea%L0,%a1,%0);
357952296Sobrien    }
358052296Sobrien
358118334Speter  /* ??? what about offsettable memory references? */
358250650Sobrien  if (!TARGET_PENTIUMPRO /* partial stalls are just too painful to risk. */
358350650Sobrien      && QI_REG_P (operands[0])
358418334Speter      && GET_CODE (operands[2]) == CONST_INT
358550650Sobrien      && (INTVAL (operands[2]) & 0xff) == 0
358650650Sobrien      && i386_cc_probably_useless_p (insn))
358718334Speter    {
358818334Speter      int byteval = (INTVAL (operands[2]) >> 8) & 0xff;
358918334Speter      CC_STATUS_INIT;
359018334Speter
359118334Speter      if (byteval == 1)
359218334Speter	return AS1 (inc%B0,%h0);
359318334Speter      else if (byteval == 255)
359418334Speter	return AS1 (dec%B0,%h0);
359518334Speter
359618334Speter      operands[2] = GEN_INT (byteval);
359718334Speter      return AS2 (add%B0,%2,%h0);
359818334Speter    }
359918334Speter
360050650Sobrien  /* Use a 32-bit operation when possible, to avoid the prefix penalty. */
360150650Sobrien  if (REG_P (operands[0])
360250650Sobrien      && i386_aligned_p (operands[2])
360350650Sobrien      && i386_cc_probably_useless_p (insn))
360450650Sobrien    {
360550650Sobrien      CC_STATUS_INIT;
360650650Sobrien
360750650Sobrien      if (GET_CODE (operands[2]) == CONST_INT)
360850650Sobrien	{
360950650Sobrien	  HOST_WIDE_INT intval = 0xffff & INTVAL (operands[2]);
361050650Sobrien
361150650Sobrien	  if (intval == 1)
361250650Sobrien	    return AS1 (inc%L0,%k0);
361350650Sobrien
361450650Sobrien	  if (intval == 0xffff)
361550650Sobrien	    return AS1 (dec%L0,%k0);
361650650Sobrien
361750650Sobrien	  operands[2] = i386_sext16_if_const (operands[2]);
361850650Sobrien	}
361950650Sobrien      return AS2 (add%L0,%k2,%k0);
362050650Sobrien    }
362150650Sobrien
362218334Speter  if (operands[2] == const1_rtx)
362318334Speter    return AS1 (inc%W0,%0);
362418334Speter
362518334Speter  if (operands[2] == constm1_rtx
362618334Speter      || (GET_CODE (operands[2]) == CONST_INT
362718334Speter	  && INTVAL (operands[2]) == 65535))
362818334Speter    return AS1 (dec%W0,%0);
362918334Speter
363018334Speter  return AS2 (add%W0,%2,%0);
363152296Sobrien}"
363252296Sobrien  [(set_attr "type" "binary")])
363318334Speter
363450650Sobrien(define_expand "addqi3"
363550650Sobrien  [(set (match_operand:QI 0 "general_operand" "")
363650650Sobrien	(plus:QI (match_operand:QI 1 "general_operand" "")
363750650Sobrien		 (match_operand:QI 2 "general_operand" "")))]
363850650Sobrien  ""
363950650Sobrien  "IX86_EXPAND_BINARY_OPERATOR (PLUS, QImode, operands);")
364050650Sobrien
364150650Sobrien(define_insn ""
364252296Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,?q")
364352296Sobrien	(plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,q")
364452296Sobrien		 (match_operand:QI 2 "general_operand" "qn,qmn,qn")))]
364550650Sobrien  "ix86_binary_operator_ok (PLUS, QImode, operands)"
364618334Speter  "*
364718334Speter{
364852296Sobrien  if (REG_P (operands[0]) && REG_P (operands[1])
364952296Sobrien      && (REG_P (operands[2]) || CONSTANT_P (operands[2]))
365052296Sobrien      && (REGNO (operands[0]) != REGNO (operands[1])
365152296Sobrien	  || NON_QI_REG_P (operands[1])
365252296Sobrien	  || (REG_P (operands[2]) && NON_QI_REG_P (operands[2]))))
365352296Sobrien    {
365452296Sobrien      if (operands[2] == stack_pointer_rtx) 
365552296Sobrien	abort ();
365652296Sobrien
365752296Sobrien      CC_STATUS_INIT;
365852296Sobrien      operands[1]
365952296Sobrien	= gen_rtx_PLUS (SImode,
366052296Sobrien			gen_rtx_REG (SImode, REGNO (operands[1])),
366152296Sobrien			(! REG_P (operands[2])
366252296Sobrien			 ? operands[2]
366352296Sobrien			 : gen_rtx_REG (SImode, REGNO (operands[2]))));
366452296Sobrien      operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
366552296Sobrien      return AS2 (lea%L0,%a1,%0);
366652296Sobrien    }
366718334Speter  if (operands[2] == const1_rtx)
366818334Speter    return AS1 (inc%B0,%0);
366918334Speter
367018334Speter  if (operands[2] == constm1_rtx
367118334Speter      || (GET_CODE (operands[2]) == CONST_INT
367218334Speter	  && INTVAL (operands[2]) == 255))
367318334Speter    return AS1 (dec%B0,%0);
367418334Speter
367518334Speter  return AS2 (add%B0,%2,%0);
367652296Sobrien}"
367752296Sobrien  [(set_attr "type" "binary")])
367818334Speter
367918334Speter;Lennart Augustsson <augustss@cs.chalmers.se>
368018334Speter;says this pattern just makes slower code:
368118334Speter;	pushl	%ebp
368218334Speter;	addl	$-80,(%esp)
368318334Speter;instead of
368418334Speter;	leal	-80(%ebp),%eax
368518334Speter;	pushl	%eax
368618334Speter;
368718334Speter;(define_insn ""
368818334Speter;  [(set (match_operand:SI 0 "push_operand" "=<")
368950650Sobrien;	(plus:SI (match_operand:SI 1 "register_operand" "%r")
369050650Sobrien;		 (match_operand:SI 2 "nonmemory_operand" "ri")))]
369118334Speter;  ""
369218334Speter;  "*
369318334Speter;{
369418334Speter;  rtx xops[4];
369518334Speter;  xops[0] = operands[0];
369618334Speter;  xops[1] = operands[1];
369718334Speter;  xops[2] = operands[2];
369850650Sobrien;  xops[3] = gen_rtx_MEM (SImode, stack_pointer_rtx);
369918334Speter;  output_asm_insn (\"push%z1 %1\", xops);
370018334Speter;  output_asm_insn (AS2 (add%z3,%2,%3), xops);
370118334Speter;  RET;
370218334Speter;}")
370318334Speter
370418334Speter;; The patterns that match these are at the end of this file.
370518334Speter
370618334Speter(define_expand "addxf3"
370718334Speter  [(set (match_operand:XF 0 "register_operand" "")
370850650Sobrien	(plus:XF (match_operand:XF 1 "register_operand" "")
370950650Sobrien		 (match_operand:XF 2 "register_operand" "")))]
371018334Speter  "TARGET_80387"
371118334Speter  "")
371218334Speter
371318334Speter(define_expand "adddf3"
371418334Speter  [(set (match_operand:DF 0 "register_operand" "")
371518334Speter	(plus:DF (match_operand:DF 1 "nonimmediate_operand" "")
371618334Speter		 (match_operand:DF 2 "nonimmediate_operand" "")))]
371718334Speter  "TARGET_80387"
371818334Speter  "")
371918334Speter
372018334Speter(define_expand "addsf3"
372118334Speter  [(set (match_operand:SF 0 "register_operand" "")
372218334Speter	(plus:SF (match_operand:SF 1 "nonimmediate_operand" "")
372318334Speter		 (match_operand:SF 2 "nonimmediate_operand" "")))]
372418334Speter  "TARGET_80387"
372518334Speter  "")
372618334Speter
372718334Speter;;- subtract instructions
372818334Speter
372950650Sobrien(define_insn "subsidi3"
373050650Sobrien  [(set (match_operand:DI 0 "general_operand" "=&r,&ro,&r,!&r,o,o,!o")
373150650Sobrien	(minus:DI (match_operand:DI 1 "general_operand" "0iF,0,roiF,roiF,riF,o,o")
373250650Sobrien		  (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,o,ri,i,r"))))
373350650Sobrien   (clobber (match_scratch:SI 3 "=X,X,X,X,X,&r,&r"))]
373450650Sobrien  ""
373550650Sobrien  "*
373650650Sobrien{
373750650Sobrien  rtx low[3], high[3], xops[7];
373850650Sobrien
373950650Sobrien  CC_STATUS_INIT;
374050650Sobrien
374150650Sobrien  split_di (operands, 2, low, high);
374250650Sobrien  high[2] = const0_rtx;
374350650Sobrien  low[2]  = operands[2];
374450650Sobrien
374550650Sobrien  if (!rtx_equal_p (operands[0], operands[1]))
374650650Sobrien    {
374750650Sobrien      xops[0] = high[0];
374850650Sobrien      xops[1] = low[0];
374950650Sobrien      xops[2] = high[1];
375050650Sobrien      xops[3] = low[1];
375150650Sobrien
375250650Sobrien      if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
375350650Sobrien	{
375450650Sobrien	  output_asm_insn (AS2 (mov%L1,%3,%1), xops);
375550650Sobrien	  output_asm_insn (AS2 (mov%L0,%2,%0), xops);
375650650Sobrien	}
375750650Sobrien      else
375850650Sobrien	{
375950650Sobrien	  xops[4] = high[2];
376050650Sobrien	  xops[5] = low[2];
376150650Sobrien	  xops[6] = operands[3];
376250650Sobrien	  output_asm_insn (AS2 (mov%L6,%3,%6), xops);
376350650Sobrien	  output_asm_insn (AS2 (sub%L6,%5,%6), xops);
376450650Sobrien	  output_asm_insn (AS2 (mov%L1,%6,%1), xops);
376550650Sobrien	  output_asm_insn (AS2 (mov%L6,%2,%6), xops);
376650650Sobrien	  output_asm_insn (AS2 (sbb%L6,%4,%6), xops);
376750650Sobrien	  output_asm_insn (AS2 (mov%L0,%6,%0), xops);
376850650Sobrien	  RET;
376950650Sobrien	}
377050650Sobrien    }
377150650Sobrien
377250650Sobrien  output_asm_insn (AS2 (sub%L0,%2,%0), low);
377350650Sobrien  output_asm_insn (AS2 (sbb%L0,%2,%0), high);
377452296Sobrien  cc_status.value1 = high[0];
377552296Sobrien  cc_status.flags = CC_NO_OVERFLOW;
377652296Sobrien
377750650Sobrien  RET;
377852296Sobrien}"
377952296Sobrien  [(set_attr "type" "binary")])
378050650Sobrien
378118334Speter(define_insn "subdi3"
378250650Sobrien  [(set (match_operand:DI 0 "general_operand" "=&r,&ro,o,o,!&r,!o")
378350650Sobrien	(minus:DI (match_operand:DI 1 "general_operand" "0,0,0iF,or,roiF,roiF")
378450650Sobrien		  (match_operand:DI 2 "general_operand" "or,riF,or,iF,roiF,roiF")))
378550650Sobrien   (clobber (match_scratch:SI 3 "=X,X,&r,&r,X,&r"))]
378618334Speter  ""
378718334Speter  "*
378818334Speter{
378918334Speter  rtx low[3], high[3], xops[7];
379018334Speter
379118334Speter  CC_STATUS_INIT;
379218334Speter
379318334Speter  split_di (operands, 3, low, high);
379418334Speter
379518334Speter  if (!rtx_equal_p (operands[0], operands[1]))
379618334Speter    {
379718334Speter      xops[0] = high[0];
379818334Speter      xops[1] = low[0];
379918334Speter      xops[2] = high[1];
380018334Speter      xops[3] = low[1];
380118334Speter
380218334Speter      if (GET_CODE (operands[0]) != MEM)
380318334Speter	{
380418334Speter	  output_asm_insn (AS2 (mov%L1,%3,%1), xops);
380518334Speter	  output_asm_insn (AS2 (mov%L0,%2,%0), xops);
380618334Speter	}
380718334Speter      else
380818334Speter	{
380918334Speter	  xops[4] = high[2];
381018334Speter	  xops[5] = low[2];
381118334Speter	  xops[6] = operands[3];
381218334Speter	  output_asm_insn (AS2 (mov%L6,%3,%6), xops);
381318334Speter	  output_asm_insn (AS2 (sub%L6,%5,%6), xops);
381418334Speter	  output_asm_insn (AS2 (mov%L1,%6,%1), xops);
381518334Speter	  output_asm_insn (AS2 (mov%L6,%2,%6), xops);
381618334Speter	  output_asm_insn (AS2 (sbb%L6,%4,%6), xops);
381718334Speter	  output_asm_insn (AS2 (mov%L0,%6,%0), xops);
381818334Speter	  RET;
381918334Speter	}
382018334Speter    }
382118334Speter
382252296Sobrien  cc_status.value1 = high[0];
382352296Sobrien  cc_status.flags = CC_NO_OVERFLOW;
382452296Sobrien
382518334Speter  if (GET_CODE (operands[3]) == REG)
382618334Speter    {
382718334Speter      xops[0] = high[0];
382818334Speter      xops[1] = low[0];
382918334Speter      xops[2] = high[2];
383018334Speter      xops[3] = low[2];
383118334Speter      xops[4] = operands[3];
383218334Speter
383318334Speter      output_asm_insn (AS2 (mov%L4,%3,%4), xops);
383418334Speter      output_asm_insn (AS2 (sub%L1,%4,%1), xops);
383518334Speter      output_asm_insn (AS2 (mov%L4,%2,%4), xops);
383618334Speter      output_asm_insn (AS2 (sbb%L0,%4,%0), xops);
383718334Speter    }
383818334Speter
383918334Speter  else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0)
384018334Speter    {
384118334Speter      output_asm_insn (AS2 (sub%L0,%2,%0), low);
384218334Speter      output_asm_insn (AS2 (sbb%L0,%2,%0), high);
384318334Speter    }
384418334Speter
384518334Speter  else
384652296Sobrien      output_asm_insn (AS2 (sub%L0,%2,%0), high);
384718334Speter
384852296Sobrien
384918334Speter  RET;
385052296Sobrien}"
385152296Sobrien  [(set_attr "type" "binary")])
385218334Speter
385350650Sobrien(define_expand "subsi3"
385450650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
385550650Sobrien	(minus:SI (match_operand:SI 1 "nonimmediate_operand" "")
385650650Sobrien		  (match_operand:SI 2 "general_operand" "")))]
385750650Sobrien  ""
385850650Sobrien  "IX86_EXPAND_BINARY_OPERATOR (MINUS, SImode, operands);")
385950650Sobrien
386050650Sobrien(define_insn ""
386150650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
386250650Sobrien	(minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0")
386318334Speter		  (match_operand:SI 2 "general_operand" "ri,rm")))]
386450650Sobrien  "ix86_binary_operator_ok (MINUS, SImode, operands)"
386552296Sobrien  "* return AS2 (sub%L0,%2,%0);"
386652296Sobrien  [(set_attr "type" "binary")])
386718334Speter
386850650Sobrien(define_expand "subhi3"
386950650Sobrien  [(set (match_operand:HI 0 "general_operand" "")
387050650Sobrien	(minus:HI (match_operand:HI 1 "nonimmediate_operand" "")
387150650Sobrien		  (match_operand:HI 2 "general_operand" "")))]
387250650Sobrien  ""
387350650Sobrien  "IX86_EXPAND_BINARY_OPERATOR (MINUS, HImode, operands);")
387450650Sobrien
387550650Sobrien(define_insn ""
387650650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
387750650Sobrien	(minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0")
387818334Speter		  (match_operand:HI 2 "general_operand" "ri,rm")))]
387950650Sobrien  "ix86_binary_operator_ok (MINUS, HImode, operands)"
388050650Sobrien  "*
388150650Sobrien{
388250650Sobrien  if (REG_P (operands[0])
388350650Sobrien      && i386_aligned_p (operands[2])
388450650Sobrien      && i386_cc_probably_useless_p (insn))
388550650Sobrien    {
388650650Sobrien      CC_STATUS_INIT;
388750650Sobrien      operands[2] = i386_sext16_if_const (operands[2]);
388850650Sobrien      return AS2 (sub%L0,%k2,%k0);
388950650Sobrien    }
389050650Sobrien return AS2 (sub%W0,%2,%0);
389152296Sobrien}"
389252296Sobrien  [(set_attr "type" "binary")])
389350650Sobrien
389450650Sobrien(define_expand "subqi3"
389550650Sobrien  [(set (match_operand:QI 0 "general_operand" "")
389650650Sobrien	(minus:QI (match_operand:QI 1 "general_operand" "")
389750650Sobrien		  (match_operand:QI 2 "general_operand" "")))]
389818334Speter  ""
389950650Sobrien  "IX86_EXPAND_BINARY_OPERATOR (MINUS, QImode, operands);")
390018334Speter
390150650Sobrien(define_insn ""
390250650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
390350650Sobrien	(minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0")
390418334Speter		  (match_operand:QI 2 "general_operand" "qn,qmn")))]
390550650Sobrien  "ix86_binary_operator_ok (MINUS, QImode, operands)"
390652296Sobrien  "* return AS2 (sub%B0,%2,%0);"
390752296Sobrien  [(set_attr "type" "binary")])
390818334Speter
390918334Speter;; The patterns that match these are at the end of this file.
391018334Speter
391118334Speter(define_expand "subxf3"
391218334Speter  [(set (match_operand:XF 0 "register_operand" "")
391350650Sobrien	(minus:XF (match_operand:XF 1 "register_operand" "")
391450650Sobrien		  (match_operand:XF 2 "register_operand" "")))]
391518334Speter  "TARGET_80387"
391618334Speter  "")
391718334Speter
391818334Speter(define_expand "subdf3"
391918334Speter  [(set (match_operand:DF 0 "register_operand" "")
392018334Speter	(minus:DF (match_operand:DF 1 "nonimmediate_operand" "")
392118334Speter		  (match_operand:DF 2 "nonimmediate_operand" "")))]
392218334Speter  "TARGET_80387"
392318334Speter  "")
392418334Speter
392518334Speter(define_expand "subsf3"
392618334Speter  [(set (match_operand:SF 0 "register_operand" "")
392718334Speter	(minus:SF (match_operand:SF 1 "nonimmediate_operand" "")
392818334Speter		  (match_operand:SF 2 "nonimmediate_operand" "")))]
392918334Speter  "TARGET_80387"
393018334Speter  "")
393118334Speter
393218334Speter;;- multiply instructions
393318334Speter
393418334Speter;(define_insn "mulqi3"
393550650Sobrien;  [(set (match_operand:QI 0 "register_operand" "=a")
393650650Sobrien;	(mult:QI (match_operand:QI 1 "register_operand" "%0")
393750650Sobrien;		 (match_operand:QI 2 "nonimmediate_operand" "qm")))]
393818334Speter;  ""
393918334Speter;  "imul%B0 %2,%0")
394018334Speter
394118334Speter(define_insn "mulhi3"
394250650Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r")
394350650Sobrien	(mult:HI (match_operand:HI 1 "nonimmediate_operand" "%0,rm")
394418334Speter		 (match_operand:HI 2 "general_operand" "g,i")))]
394518334Speter  ""
394618334Speter  "*
394718334Speter{
394818334Speter  if (GET_CODE (operands[1]) == REG
394918334Speter      && REGNO (operands[1]) == REGNO (operands[0])
395018334Speter      && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG))
395118334Speter    /* Assembler has weird restrictions.  */
395218334Speter    return AS2 (imul%W0,%2,%0);
395318334Speter  return AS3 (imul%W0,%2,%1,%0);
395450650Sobrien}"
395550650Sobrien  [(set_attr "type" "imul")])
395618334Speter
395718334Speter(define_insn "mulsi3"
395850650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
395950650Sobrien	(mult:SI (match_operand:SI 1 "nonimmediate_operand" "%0,rm")
396018334Speter		 (match_operand:SI 2 "general_operand" "g,i")))]
396118334Speter  ""
396218334Speter  "*
396318334Speter{
396418334Speter  if (GET_CODE (operands[1]) == REG
396518334Speter      && REGNO (operands[1]) == REGNO (operands[0])
396618334Speter      && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG))
396718334Speter    /* Assembler has weird restrictions.  */
396818334Speter    return AS2 (imul%L0,%2,%0);
396918334Speter  return AS3 (imul%L0,%2,%1,%0);
397050650Sobrien}"
397150650Sobrien  [(set_attr "type" "imul")])
397218334Speter
397318334Speter(define_insn "umulqihi3"
397450650Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
397550650Sobrien	(mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0"))
397618334Speter		 (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
397718334Speter  ""
397850650Sobrien  "mul%B0 %2"
397950650Sobrien  [(set_attr "type" "imul")])
398018334Speter
398118334Speter(define_insn "mulqihi3"
398250650Sobrien  [(set (match_operand:HI 0 "register_operand" "=a")
398350650Sobrien	(mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0"))
398418334Speter		 (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))]
398518334Speter  ""
398650650Sobrien  "imul%B0 %2"
398750650Sobrien  [(set_attr "type" "imul")])
398818334Speter
398918334Speter(define_insn "umulsidi3"
399018334Speter  [(set (match_operand:DI 0 "register_operand" "=A")
399118334Speter	(mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0"))
399218334Speter		 (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))]
399318334Speter  "TARGET_WIDE_MULTIPLY"
399450650Sobrien  "mul%L0 %2"
399550650Sobrien  [(set_attr "type" "imul")])
399618334Speter
399718334Speter(define_insn "mulsidi3"
399818334Speter  [(set (match_operand:DI 0 "register_operand" "=A")
399918334Speter	(mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0"))
400018334Speter		 (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))]
400118334Speter  "TARGET_WIDE_MULTIPLY"
400250650Sobrien  "imul%L0 %2"
400350650Sobrien  [(set_attr "type" "imul")])
400418334Speter
400518334Speter(define_insn "umulsi3_highpart"
400618334Speter  [(set (match_operand:SI 0 "register_operand" "=d")
400718334Speter	(truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%a"))
400818334Speter					   (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))
400918334Speter				  (const_int 32))))
401018334Speter   (clobber (match_scratch:SI 3 "=a"))]
401118334Speter  "TARGET_WIDE_MULTIPLY"
401250650Sobrien  "mul%L0 %2"
401350650Sobrien  [(set_attr "type" "imul")])
401418334Speter
401518334Speter(define_insn "smulsi3_highpart"
401618334Speter  [(set (match_operand:SI 0 "register_operand" "=d")
401718334Speter	(truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%a"))
401818334Speter					   (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm")))
401918334Speter				  (const_int 32))))
402018334Speter   (clobber (match_scratch:SI 3 "=a"))]
402118334Speter  "TARGET_WIDE_MULTIPLY"
402250650Sobrien  "imul%L0 %2"
402350650Sobrien  [(set_attr "type" "imul")])
402418334Speter
402518334Speter;; The patterns that match these are at the end of this file.
402618334Speter
402718334Speter(define_expand "mulxf3"
402818334Speter  [(set (match_operand:XF 0 "register_operand" "")
402950650Sobrien	(mult:XF (match_operand:XF 1 "register_operand" "")
403050650Sobrien		 (match_operand:XF 2 "register_operand" "")))]
403118334Speter  "TARGET_80387"
403218334Speter  "")
403318334Speter
403418334Speter(define_expand "muldf3"
403518334Speter  [(set (match_operand:DF 0 "register_operand" "")
403650650Sobrien	(mult:DF (match_operand:DF 1 "register_operand" "")
403718334Speter		 (match_operand:DF 2 "nonimmediate_operand" "")))]
403818334Speter  "TARGET_80387"
403918334Speter  "")
404018334Speter
404118334Speter(define_expand "mulsf3"
404218334Speter  [(set (match_operand:SF 0 "register_operand" "")
404350650Sobrien	(mult:SF (match_operand:SF 1 "register_operand" "")
404418334Speter		 (match_operand:SF 2 "nonimmediate_operand" "")))]
404518334Speter  "TARGET_80387"
404618334Speter  "")
404718334Speter
404818334Speter;;- divide instructions
404918334Speter
405018334Speter(define_insn "divqi3"
405150650Sobrien  [(set (match_operand:QI 0 "register_operand" "=a")
405250650Sobrien	(div:QI (match_operand:HI 1 "register_operand" "0")
405350650Sobrien		(match_operand:QI 2 "nonimmediate_operand" "qm")))]
405418334Speter  ""
405518334Speter  "idiv%B0 %2")
405618334Speter
405718334Speter(define_insn "udivqi3"
405850650Sobrien  [(set (match_operand:QI 0 "register_operand" "=a")
405950650Sobrien	(udiv:QI (match_operand:HI 1 "register_operand" "0")
406050650Sobrien		 (match_operand:QI 2 "nonimmediate_operand" "qm")))]
406118334Speter  ""
406250650Sobrien  "div%B0 %2"
406350650Sobrien  [(set_attr "type" "idiv")])
406418334Speter
406518334Speter;; The patterns that match these are at the end of this file.
406618334Speter
406718334Speter(define_expand "divxf3"
406818334Speter  [(set (match_operand:XF 0 "register_operand" "")
406950650Sobrien	(div:XF (match_operand:XF 1 "register_operand" "")
407050650Sobrien		(match_operand:XF 2 "register_operand" "")))]
407118334Speter  "TARGET_80387"
407218334Speter  "")
407318334Speter
407418334Speter(define_expand "divdf3"
407518334Speter  [(set (match_operand:DF 0 "register_operand" "")
407650650Sobrien 	(div:DF (match_operand:DF 1 "register_operand" "")
407750650Sobrien 		(match_operand:DF 2 "nonimmediate_operand" "")))]
407850650Sobrien   "TARGET_80387"
407950650Sobrien   "")
408050650Sobrien 
408118334Speter(define_expand "divsf3"
408218334Speter  [(set (match_operand:SF 0 "register_operand" "")
408350650Sobrien	(div:SF (match_operand:SF 1 "register_operand" "")
408418334Speter		(match_operand:SF 2 "nonimmediate_operand" "")))]
408518334Speter  "TARGET_80387"
408618334Speter  "")
408718334Speter
408818334Speter;; Remainder instructions.
408918334Speter
409018334Speter(define_insn "divmodsi4"
409118334Speter  [(set (match_operand:SI 0 "register_operand" "=a")
409218334Speter	(div:SI (match_operand:SI 1 "register_operand" "0")
409350650Sobrien		(match_operand:SI 2 "nonimmediate_operand" "rm")))
409418334Speter   (set (match_operand:SI 3 "register_operand" "=&d")
409518334Speter	(mod:SI (match_dup 1) (match_dup 2)))]
409618334Speter  ""
409718334Speter  "*
409818334Speter{
409918334Speter#ifdef INTEL_SYNTAX
410018334Speter  output_asm_insn (\"cdq\", operands);
410118334Speter#else
410218334Speter  output_asm_insn (\"cltd\", operands);
410318334Speter#endif
410418334Speter  return AS1 (idiv%L0,%2);
410550650Sobrien}"
410650650Sobrien  [(set_attr "type" "idiv")])
410718334Speter
410818334Speter(define_insn "divmodhi4"
410918334Speter  [(set (match_operand:HI 0 "register_operand" "=a")
411018334Speter	(div:HI (match_operand:HI 1 "register_operand" "0")
411150650Sobrien		(match_operand:HI 2 "nonimmediate_operand" "rm")))
411218334Speter   (set (match_operand:HI 3 "register_operand" "=&d")
411318334Speter	(mod:HI (match_dup 1) (match_dup 2)))]
411418334Speter  ""
411550650Sobrien  "cwtd\;idiv%W0 %2"
411650650Sobrien  [(set_attr "type" "idiv")])
411718334Speter
411818334Speter;; ??? Can we make gcc zero extend operand[0]?
411918334Speter(define_insn "udivmodsi4"
412018334Speter  [(set (match_operand:SI 0 "register_operand" "=a")
412118334Speter	(udiv:SI (match_operand:SI 1 "register_operand" "0")
412250650Sobrien		 (match_operand:SI 2 "nonimmediate_operand" "rm")))
412318334Speter   (set (match_operand:SI 3 "register_operand" "=&d")
412418334Speter	(umod:SI (match_dup 1) (match_dup 2)))]
412518334Speter  ""
412618334Speter  "*
412718334Speter{
412818334Speter  output_asm_insn (AS2 (xor%L3,%3,%3), operands);
412918334Speter  return AS1 (div%L0,%2);
413050650Sobrien}"
413150650Sobrien  [(set_attr "type" "idiv")])
413218334Speter
413318334Speter;; ??? Can we make gcc zero extend operand[0]?
413418334Speter(define_insn "udivmodhi4"
413518334Speter  [(set (match_operand:HI 0 "register_operand" "=a")
413618334Speter	(udiv:HI (match_operand:HI 1 "register_operand" "0")
413750650Sobrien		 (match_operand:HI 2 "nonimmediate_operand" "rm")))
413818334Speter   (set (match_operand:HI 3 "register_operand" "=&d")
413918334Speter	(umod:HI (match_dup 1) (match_dup 2)))]
414018334Speter  ""
414118334Speter  "*
414218334Speter{
414318334Speter  output_asm_insn (AS2 (xor%W0,%3,%3), operands);
414418334Speter  return AS1 (div%W0,%2);
414550650Sobrien}"
414650650Sobrien  [(set_attr "type" "idiv")])
414718334Speter
414818334Speter/*
414918334Speter;;this should be a valid double division which we may want to add
415018334Speter
415118334Speter(define_insn ""
415218334Speter  [(set (match_operand:SI 0 "register_operand" "=a")
415318334Speter	(udiv:DI (match_operand:DI 1 "register_operand" "a")
415450650Sobrien		 (match_operand:SI 2 "nonimmediate_operand" "rm")))
415518334Speter   (set (match_operand:SI 3 "register_operand" "=d")
415618334Speter	(umod:SI (match_dup 1) (match_dup 2)))]
415718334Speter  ""
415850650Sobrien  "div%L0 %2,%0"
415950650Sobrien  [(set_attr "type" "idiv")])
416018334Speter*/
416118334Speter
416218334Speter;;- and instructions
416318334Speter
416418334Speter;; On i386,
416518334Speter;;			movzbl %bl,%ebx
416618334Speter;; is faster than
416718334Speter;;			andl $255,%ebx
416818334Speter;;
416918334Speter;; but if the reg is %eax, then the "andl" is faster.
417018334Speter;;
417118334Speter;; On i486, the "andl" is always faster than the "movzbl".
417218334Speter;;
417318334Speter;; On both i386 and i486, a three operand AND is as fast with movzbl or
417418334Speter;; movzwl as with andl, if operands[0] != operands[1].
417518334Speter
417618334Speter;; The `r' in `rm' for operand 3 looks redundant, but it causes
417718334Speter;; optional reloads to be generated if op 3 is a pseudo in a stack slot.
417818334Speter
417918334Speter(define_insn "andsi3"
418050650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
418150650Sobrien	(and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
418250650Sobrien		(match_operand:SI 2 "general_operand" "ri,rm")))]
418318334Speter  ""
418418334Speter  "*
418518334Speter{
418650650Sobrien  HOST_WIDE_INT intval;
418750650Sobrien  if (!rtx_equal_p (operands[0], operands[1])
418850650Sobrien      && rtx_equal_p (operands[0], operands[2]))
418918334Speter    {
419050650Sobrien      rtx tmp;
419150650Sobrien      tmp = operands[1];
419250650Sobrien      operands[1] = operands[2];
419350650Sobrien      operands[2] = tmp;
419450650Sobrien    }
419550650Sobrien  switch (GET_CODE (operands[2]))
419650650Sobrien    {
419750650Sobrien    case CONST_INT:
419850650Sobrien      if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
419950650Sobrien	break;
420050650Sobrien      intval = INTVAL (operands[2]);
420150650Sobrien      /* zero-extend 16->32? */
420250650Sobrien      if (intval == 0xffff && REG_P (operands[0])
420318334Speter	  && (! REG_P (operands[1])
420418334Speter	      || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
420550650Sobrien	  && (!TARGET_ZERO_EXTEND_WITH_AND || ! rtx_equal_p (operands[0], operands[1])))
420618334Speter	{
420718334Speter	  /* ??? tege: Should forget CC_STATUS only if we clobber a
420818334Speter	     remembered operand.  Fix that later.  */
420918334Speter	  CC_STATUS_INIT;
421018334Speter#ifdef INTEL_SYNTAX
421118334Speter	  return AS2 (movzx,%w1,%0);
421218334Speter#else
421318334Speter	  return AS2 (movz%W0%L0,%w1,%0);
421418334Speter#endif
421518334Speter	}
421618334Speter
421750650Sobrien      /* zero extend 8->32? */
421850650Sobrien      if (intval == 0xff && REG_P (operands[0])
421918334Speter	  && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1]))
422018334Speter	  && (! REG_P (operands[1])
422118334Speter	      || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0)
422250650Sobrien	  && (!TARGET_ZERO_EXTEND_WITH_AND || ! rtx_equal_p (operands[0], operands[1])))
422318334Speter	{
422418334Speter	  /* ??? tege: Should forget CC_STATUS only if we clobber a
422518334Speter	     remembered operand.  Fix that later.  */
422618334Speter	  CC_STATUS_INIT;
422718334Speter#ifdef INTEL_SYNTAX
422818334Speter	  return AS2 (movzx,%b1,%0);
422918334Speter#else
423018334Speter	  return AS2 (movz%B0%L0,%b1,%0);
423118334Speter#endif
423218334Speter	}
423318334Speter
423450650Sobrien      /* Check partial bytes.. non-QI-regs are not available */
423550650Sobrien      if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
423650650Sobrien	break;
423750650Sobrien
423850650Sobrien      /* only low byte has zero bits? */
423950650Sobrien      if (~(intval | 0xff) == 0)
424018334Speter	{
424150650Sobrien	  intval &= 0xff;
424250650Sobrien	  if (REG_P (operands[0]))
424350650Sobrien	    {
424450650Sobrien	      if (intval == 0)
424550650Sobrien		{
424650650Sobrien		  CC_STATUS_INIT;
424750650Sobrien		  return AS2 (xor%B0,%b0,%b0);
424850650Sobrien		}
424918334Speter
425050650Sobrien	      /* we're better off with the 32-bit version if reg != EAX */
425150650Sobrien	      /* the value is sign-extended in 8 bits */
425250650Sobrien	      if (REGNO (operands[0]) != 0 && (intval & 0x80))
425350650Sobrien		break;
425418334Speter	    }
425518334Speter
425650650Sobrien	  CC_STATUS_INIT;
425750650Sobrien
425850650Sobrien	  operands[2] = GEN_INT (intval);
425950650Sobrien
426050650Sobrien	  if (intval == 0)
426150650Sobrien	    return AS2 (mov%B0,%2,%b0);
426250650Sobrien
426318334Speter	  return AS2 (and%B0,%2,%b0);
426418334Speter	}
426518334Speter
426650650Sobrien      /* only second byte has zero? */
426750650Sobrien      if (~(intval | 0xff00) == 0)
426818334Speter	{
426918334Speter	  CC_STATUS_INIT;
427018334Speter
427150650Sobrien	  intval = (intval >> 8) & 0xff;
427250650Sobrien	  operands[2] = GEN_INT (intval);
427350650Sobrien	  if (intval == 0)
427418334Speter	    {
427550650Sobrien	      if (REG_P (operands[0]))
427650650Sobrien		return AS2 (xor%B0,%h0,%h0);
427750650Sobrien	      operands[0] = adj_offsettable_operand (operands[0], 1);
427850650Sobrien	      return AS2 (mov%B0,%2,%b0);
427918334Speter	    }
428018334Speter
428150650Sobrien	  if (REG_P (operands[0]))
428250650Sobrien	    return AS2 (and%B0,%2,%h0);
428350650Sobrien
428450650Sobrien	  operands[0] = adj_offsettable_operand (operands[0], 1);
428550650Sobrien	  return AS2 (and%B0,%2,%b0);
428618334Speter	}
428718334Speter
428850650Sobrien      if (REG_P (operands[0]))
428950650Sobrien	break;
429050650Sobrien
429150650Sobrien      /* third byte has zero bits? */
429250650Sobrien      if (~(intval | 0xff0000) == 0)
429350650Sobrien	{
429450650Sobrien	  intval = (intval >> 16) & 0xff;
429550650Sobrien	  operands[0] = adj_offsettable_operand (operands[0], 2);
429650650Sobrienbyte_and_operation:
429750650Sobrien	  CC_STATUS_INIT;
429850650Sobrien	  operands[2] = GEN_INT (intval);
429950650Sobrien	  if (intval == 0)
430050650Sobrien	    return AS2 (mov%B0,%2,%b0);
430150650Sobrien	  return AS2 (and%B0,%2,%b0);
430250650Sobrien	}
430350650Sobrien
430450650Sobrien      /* fourth byte has zero bits? */
430550650Sobrien      if (~(intval | 0xff000000) == 0)
430650650Sobrien	{
430750650Sobrien	  intval = (intval >> 24) & 0xff;
430850650Sobrien	  operands[0] = adj_offsettable_operand (operands[0], 3);
430950650Sobrien	  goto byte_and_operation;
431050650Sobrien	}
431150650Sobrien
431250650Sobrien      /* Low word is zero? */
431350650Sobrien      if (intval == 0xffff0000)
431418334Speter        {
431550650Sobrienword_zero_and_operation:
431650650Sobrien	  CC_STATUS_INIT;
431718334Speter	  operands[2] = const0_rtx;
431818334Speter	  return AS2 (mov%W0,%2,%w0);
431918334Speter	}
432050650Sobrien
432150650Sobrien      /* High word is zero? */
432250650Sobrien      if (intval == 0x0000ffff)
432350650Sobrien        {
432450650Sobrien	  operands[0] = adj_offsettable_operand (operands[0], 2);
432550650Sobrien	  goto word_zero_and_operation;
432650650Sobrien	}
432750650Sobrien
432850650Sobrien    default:
432950650Sobrien      break;
433018334Speter    }
433118334Speter
433218334Speter  return AS2 (and%L0,%2,%0);
433352296Sobrien}"
433452296Sobrien  [(set_attr "type" "binary")])
433518334Speter
433618334Speter(define_insn "andhi3"
433750650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
433850650Sobrien	(and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
433918334Speter		(match_operand:HI 2 "general_operand" "ri,rm")))]
434018334Speter  ""
434118334Speter  "*
434218334Speter{
434318334Speter  if (GET_CODE (operands[2]) == CONST_INT
434418334Speter      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
434518334Speter    {
434618334Speter      /* Can we ignore the upper byte? */
434718334Speter      if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
434818334Speter	  && (INTVAL (operands[2]) & 0xff00) == 0xff00)
434918334Speter	{
435018334Speter	  CC_STATUS_INIT;
435118334Speter
435218334Speter	  if ((INTVAL (operands[2]) & 0xff) == 0)
435318334Speter	    {
435418334Speter	      operands[2] = const0_rtx;
435518334Speter	      return AS2 (mov%B0,%2,%b0);
435618334Speter	    }
435718334Speter
435818334Speter	  operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
435918334Speter	  return AS2 (and%B0,%2,%b0);
436018334Speter	}
436118334Speter
436218334Speter      /* Can we ignore the lower byte? */
436318334Speter      /* ??? what about offsettable memory references? */
436418334Speter      if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff) == 0xff)
436518334Speter	{
436618334Speter	  CC_STATUS_INIT;
436718334Speter
436818334Speter	  if ((INTVAL (operands[2]) & 0xff00) == 0)
436918334Speter	    {
437018334Speter	      operands[2] = const0_rtx;
437118334Speter	      return AS2 (mov%B0,%2,%h0);
437218334Speter	    }
437318334Speter
437418334Speter	  operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
437518334Speter	  return AS2 (and%B0,%2,%h0);
437618334Speter	}
437750650Sobrien
437850650Sobrien      /* use 32-bit ops on registers when there are no sign issues.. */
437950650Sobrien      if (REG_P (operands[0]))
438050650Sobrien	{
438150650Sobrien	  if (!(INTVAL (operands[2]) & ~0x7fff))
438250650Sobrien	    return AS2 (and%L0,%2,%k0);
438350650Sobrien	}
438418334Speter    }
438518334Speter
438650650Sobrien  if (REG_P (operands[0])
438750650Sobrien      && i386_aligned_p (operands[2]))
438850650Sobrien    {
438950650Sobrien      CC_STATUS_INIT;
439050650Sobrien      /* If op[2] is constant, we should zero-extend it and */
439150650Sobrien      /* make a note that op[0] has been zero-extended, so  */
439250650Sobrien      /* that we could use 32-bit ops on it forthwith, but  */
439350650Sobrien      /* there is no such reg-note available. Instead we do */
439450650Sobrien      /* a sign extension as that can result in shorter asm */
439550650Sobrien      operands[2] = i386_sext16_if_const (operands[2]);
439650650Sobrien      return AS2 (and%L0,%k2,%k0);
439750650Sobrien    }
439850650Sobrien
439950650Sobrien  /* Use a 32-bit word with the upper bits set, invalidate CC */
440050650Sobrien  if (GET_CODE (operands[2]) == CONST_INT
440150650Sobrien      && i386_aligned_p (operands[0]))
440250650Sobrien    {
440350650Sobrien      HOST_WIDE_INT val = INTVAL (operands[2]);
440450650Sobrien      CC_STATUS_INIT;
440550650Sobrien      val |= ~0xffff;
440650650Sobrien      if (val != INTVAL (operands[2]))
440750650Sobrien	operands[2] = GEN_INT (val);
440850650Sobrien      return AS2 (and%L0,%k2,%k0);
440950650Sobrien    }
441050650Sobrien
441118334Speter  return AS2 (and%W0,%2,%0);
441252296Sobrien}"
441352296Sobrien  [(set_attr "type" "binary")])
441418334Speter
441518334Speter(define_insn "andqi3"
441650650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
441750650Sobrien	(and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
441818334Speter		(match_operand:QI 2 "general_operand" "qn,qmn")))]
441918334Speter  ""
442052296Sobrien  "* return AS2 (and%B0,%2,%0);"
442152296Sobrien  [(set_attr "type" "binary")])
442218334Speter
442318334Speter/* I am nervous about these two.. add them later..
442418334Speter;I presume this means that we have something in say op0= eax which is small
442518334Speter;and we want to and it with memory so we can do this by just an
442618334Speter;andb m,%al  and have success.
442718334Speter(define_insn ""
442818334Speter  [(set (match_operand:SI 0 "general_operand" "=r")
442918334Speter	(and:SI (zero_extend:SI
443018334Speter		 (match_operand:HI 1 "nonimmediate_operand" "rm"))
443118334Speter		(match_operand:SI 2 "general_operand" "0")))]
443218334Speter  "GET_CODE (operands[2]) == CONST_INT
443318334Speter   && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))"
443418334Speter  "and%W0 %1,%0")
443518334Speter
443618334Speter(define_insn ""
443750650Sobrien  [(set (match_operand:SI 0 "register_operand" "=q")
443818334Speter	(and:SI
443918334Speter	 (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))
444050650Sobrien		(match_operand:SI 2 "register_operand" "0")))]
444118334Speter  "GET_CODE (operands[2]) == CONST_INT
444218334Speter   && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))"
444318334Speter  "and%L0 %1,%0")
444418334Speter
444518334Speter*/
444618334Speter
444718334Speter;;- Bit set (inclusive or) instructions
444818334Speter
444950650Sobrien;; This optimizes known byte-wide operations to memory, and in some cases
445050650Sobrien;; to QI registers.. Note that we don't want to use the QI registers too
445150650Sobrien;; aggressively, because often the 32-bit register instruction is the same
445250650Sobrien;; size, and likely to be faster on PentiumPro.
445318334Speter(define_insn "iorsi3"
445450650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
445550650Sobrien	(ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
445618334Speter		(match_operand:SI 2 "general_operand" "ri,rm")))]
445718334Speter  ""
445818334Speter  "*
445918334Speter{
446050650Sobrien  HOST_WIDE_INT intval;
446150650Sobrien  switch (GET_CODE (operands[2]))
446218334Speter    {
446350650Sobrien    case CONST_INT:
446450650Sobrien
446550650Sobrien      if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
446650650Sobrien	break;
446750650Sobrien
446850650Sobrien      /* don't try to optimize volatile accesses */
446950650Sobrien      if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
447050650Sobrien	break;
447150650Sobrien
447250650Sobrien      intval = INTVAL (operands[2]);
447350650Sobrien      if ((intval & ~0xff) == 0)
447450650Sobrien        {
447550650Sobrien	  if (REG_P (operands[0]))
447650650Sobrien	    {
447750650Sobrien	      /* Do low byte access only for %eax or when high bit is set */
447850650Sobrien	      if (REGNO (operands[0]) != 0 && !(intval & 0x80))
447950650Sobrien	        break;
448050650Sobrien	    }
448150650Sobrien
448250650Sobrienbyte_or_operation:
448350650Sobrien	    CC_STATUS_INIT;
448450650Sobrien
448550650Sobrien	    if (intval != INTVAL (operands[2]))
448650650Sobrien	      operands[2] = GEN_INT (intval);
448750650Sobrien
448850650Sobrien	    if (intval == 0xff)
448950650Sobrien	      return AS2 (mov%B0,%2,%b0);
449050650Sobrien
449150650Sobrien	    return AS2 (or%B0,%2,%b0);
449250650Sobrien	}
449350650Sobrien
449450650Sobrien      /* second byte? */
449550650Sobrien      if ((intval & ~0xff00) == 0)
449618334Speter	{
449750650Sobrien	  intval >>= 8;
449818334Speter
449950650Sobrien	  if (REG_P (operands[0]))
450050650Sobrien	    {
450150650Sobrien	      CC_STATUS_INIT;
450250650Sobrien	      operands[2] = GEN_INT (intval);
450350650Sobrien	      if (intval == 0xff)
450450650Sobrien		return AS2 (mov%B0,%2,%h0);
450518334Speter
450650650Sobrien	      return AS2 (or%B0,%2,%h0);
450750650Sobrien	    }
450850650Sobrien
450950650Sobrien	  operands[0] = adj_offsettable_operand (operands[0], 1);
451050650Sobrien	  goto byte_or_operation;
451118334Speter	}
451218334Speter
451350650Sobrien      if (REG_P (operands[0]))
451450650Sobrien	break;
451550650Sobrien
451650650Sobrien      /* third byte? */
451750650Sobrien      if ((intval & ~0xff0000) == 0)
451818334Speter	{
451950650Sobrien	  intval >>= 16;
452050650Sobrien	  operands[0] = adj_offsettable_operand (operands[0], 2);
452150650Sobrien	  goto byte_or_operation;
452250650Sobrien	}
452318334Speter
452450650Sobrien      /* fourth byte? */
452550650Sobrien      if ((intval & ~0xff000000) == 0)
452650650Sobrien	{
452750650Sobrien	  intval = (intval >> 24) & 0xff;
452850650Sobrien	  operands[0] = adj_offsettable_operand (operands[0], 3);
452950650Sobrien	  goto byte_or_operation;
453050650Sobrien	}
453118334Speter
453250650Sobrien    default:
453350650Sobrien      break;
453418334Speter    }
453518334Speter
453618334Speter  return AS2 (or%L0,%2,%0);
453752296Sobrien}"
453852296Sobrien  [(set_attr "type" "binary")])
453918334Speter
454018334Speter(define_insn "iorhi3"
454150650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
454250650Sobrien	(ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
454318334Speter		(match_operand:HI 2 "general_operand" "ri,rm")))]
454418334Speter  ""
454518334Speter  "*
454618334Speter{
454750650Sobrien  HOST_WIDE_INT intval;
454850650Sobrien  switch (GET_CODE (operands[2]))
454918334Speter    {
455050650Sobrien    case CONST_INT:
455118334Speter
455250650Sobrien      if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
455350650Sobrien	break;
455418334Speter
455550650Sobrien      /* don't try to optimize volatile accesses */
455650650Sobrien      if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
455750650Sobrien	break;
455850650Sobrien
455950650Sobrien      intval = 0xffff & INTVAL (operands[2]);
456050650Sobrien
456150650Sobrien      if ((intval & 0xff00) == 0)
456250650Sobrien        {
456350650Sobrien	  if (REG_P (operands[0]))
456450650Sobrien	    {
456550650Sobrien	      /* Do low byte access only for %eax or when high bit is set */
456650650Sobrien	      if (REGNO (operands[0]) != 0 && !(intval & 0x80))
456750650Sobrien	        break;
456850650Sobrien	    }
456950650Sobrien
457050650Sobrienbyte_or_operation:
457150650Sobrien	    CC_STATUS_INIT;
457250650Sobrien
457350650Sobrien	    if (intval == 0xff)
457450650Sobrien	      return AS2 (mov%B0,%2,%b0);
457550650Sobrien
457650650Sobrien	    return AS2 (or%B0,%2,%b0);
457718334Speter	}
457818334Speter
457950650Sobrien      /* high byte? */
458050650Sobrien      if ((intval & 0xff) == 0)
458118334Speter	{
458250650Sobrien	  intval >>= 8;
458350650Sobrien	  operands[2] = GEN_INT (intval);
458418334Speter
458550650Sobrien	  if (REG_P (operands[0]))
458650650Sobrien	    {
458750650Sobrien	      CC_STATUS_INIT;
458850650Sobrien	      if (intval == 0xff)
458950650Sobrien		return AS2 (mov%B0,%2,%h0);
459018334Speter
459150650Sobrien	      return AS2 (or%B0,%2,%h0);
459250650Sobrien	    }
459350650Sobrien
459450650Sobrien	  operands[0] = adj_offsettable_operand (operands[0], 1);
459550650Sobrien
459650650Sobrien	  goto byte_or_operation;
459718334Speter	}
459850650Sobrien
459950650Sobrien    default:
460050650Sobrien      break;
460118334Speter    }
460218334Speter
460350650Sobrien  if (REG_P (operands[0])
460450650Sobrien      && i386_aligned_p (operands[2]))
460550650Sobrien    {
460650650Sobrien      CC_STATUS_INIT;
460750650Sobrien      operands[2] = i386_sext16_if_const (operands[2]);
460850650Sobrien      return AS2 (or%L0,%k2,%k0);
460950650Sobrien    }
461050650Sobrien
461150650Sobrien  if (GET_CODE (operands[2]) == CONST_INT
461250650Sobrien      && i386_aligned_p (operands[0]))
461350650Sobrien    {
461450650Sobrien      CC_STATUS_INIT;
461550650Sobrien      intval = 0xffff & INTVAL (operands[2]);
461650650Sobrien      if (intval != INTVAL (operands[2]))
461750650Sobrien	operands[2] = GEN_INT (intval);
461850650Sobrien      return AS2 (or%L0,%2,%k0);
461950650Sobrien    }
462050650Sobrien
462118334Speter  return AS2 (or%W0,%2,%0);
462252296Sobrien}"
462352296Sobrien  [(set_attr "type" "binary")])
462418334Speter
462518334Speter(define_insn "iorqi3"
462650650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
462750650Sobrien	(ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
462818334Speter		(match_operand:QI 2 "general_operand" "qn,qmn")))]
462918334Speter  ""
463052296Sobrien  "* return AS2 (or%B0,%2,%0);"
463152296Sobrien  [(set_attr "type" "binary")])
463218334Speter
463318334Speter;;- xor instructions
463418334Speter
463518334Speter(define_insn "xorsi3"
463650650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r")
463750650Sobrien	(xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0")
463818334Speter		(match_operand:SI 2 "general_operand" "ri,rm")))]
463918334Speter  ""
464018334Speter  "*
464118334Speter{
464250650Sobrien  HOST_WIDE_INT intval;
464350650Sobrien  switch (GET_CODE (operands[2]))
464418334Speter    {
464550650Sobrien    case CONST_INT:
464650650Sobrien
464750650Sobrien      if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
464850650Sobrien	break;
464950650Sobrien
465050650Sobrien      /* don't try to optimize volatile accesses */
465150650Sobrien      if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))
465250650Sobrien	break;
465350650Sobrien
465450650Sobrien      intval = INTVAL (operands[2]);
465550650Sobrien      if ((intval & ~0xff) == 0)
465650650Sobrien        {
465750650Sobrien	  if (REG_P (operands[0]))
465850650Sobrien	    {
465950650Sobrien	      /* Do low byte access only for %eax or when high bit is set */
466050650Sobrien	      if (REGNO (operands[0]) != 0 && !(intval & 0x80))
466150650Sobrien	        break;
466250650Sobrien	    }
466350650Sobrien
466450650Sobrienbyte_xor_operation:
466550650Sobrien	    CC_STATUS_INIT;
466650650Sobrien	      
466752296Sobrien	    if (intval == 0xff
466852296Sobrien                && (!TARGET_PENTIUM || optimize_size
466952296Sobrien                    || (GET_CODE (operands[0]) == MEM 
467052296Sobrien                        && memory_address_info (XEXP (operands[0], 0), 1))))
467150650Sobrien	      return AS1 (not%B0,%b0);
467250650Sobrien
467350650Sobrien	    if (intval != INTVAL (operands[2]))
467450650Sobrien	      operands[2] = GEN_INT (intval);
467550650Sobrien	    return AS2 (xor%B0,%2,%b0);
467650650Sobrien	}
467750650Sobrien
467850650Sobrien      /* second byte? */
467950650Sobrien      if ((intval & ~0xff00) == 0)
468018334Speter	{
468150650Sobrien	  intval >>= 8;
468218334Speter
468350650Sobrien	  if (REG_P (operands[0]))
468450650Sobrien	    {
468550650Sobrien	      CC_STATUS_INIT;
468652296Sobrien	      if (intval == 0xff 
468752296Sobrien                  && (!TARGET_PENTIUM || optimize_size
468852296Sobrien                      || (GET_CODE (operands[0]) == MEM 
468952296Sobrien                          && memory_address_info (XEXP (operands[0], 0), 1))))
469050650Sobrien		return AS1 (not%B0,%h0);
469118334Speter
469250650Sobrien	      operands[2] = GEN_INT (intval);
469350650Sobrien	      return AS2 (xor%B0,%2,%h0);
469450650Sobrien	    }
469550650Sobrien
469650650Sobrien	  operands[0] = adj_offsettable_operand (operands[0], 1);
469750650Sobrien
469850650Sobrien	  goto byte_xor_operation;
469918334Speter	}
470018334Speter
470150650Sobrien      if (REG_P (operands[0]))
470250650Sobrien	break;
470350650Sobrien
470450650Sobrien      /* third byte? */
470550650Sobrien      if ((intval & ~0xff0000) == 0)
470618334Speter	{
470750650Sobrien	  intval >>= 16;
470850650Sobrien	  operands[0] = adj_offsettable_operand (operands[0], 2);
470950650Sobrien	  goto byte_xor_operation;
471050650Sobrien	}
471118334Speter
471250650Sobrien      /* fourth byte? */
471350650Sobrien      if ((intval & ~0xff000000) == 0)
471450650Sobrien	{
471550650Sobrien	  intval = (intval >> 24) & 0xff;
471650650Sobrien	  operands[0] = adj_offsettable_operand (operands[0], 3);
471750650Sobrien	  goto byte_xor_operation;
471850650Sobrien	}
471918334Speter
472050650Sobrien    default:
472150650Sobrien      break;
472218334Speter    }
472318334Speter
472418334Speter  return AS2 (xor%L0,%2,%0);
472552296Sobrien}"
472652296Sobrien  [(set_attr "type" "binary")])
472718334Speter
472818334Speter(define_insn "xorhi3"
472950650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r")
473050650Sobrien	(xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
473118334Speter		(match_operand:HI 2 "general_operand" "ri,rm")))]
473218334Speter  ""
473318334Speter  "*
473418334Speter{
473518334Speter  if (GET_CODE (operands[2]) == CONST_INT
473618334Speter      && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
473718334Speter    {
473818334Speter      /* Can we ignore the upper byte? */
473918334Speter      if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
474018334Speter	  && (INTVAL (operands[2]) & 0xff00) == 0)
474118334Speter	{
474218334Speter	  CC_STATUS_INIT;
474318334Speter	  if (INTVAL (operands[2]) & 0xffff0000)
474418334Speter	    operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff);
474518334Speter
474652296Sobrien	  if (INTVAL (operands[2]) == 0xff 
474752296Sobrien              && (!TARGET_PENTIUM || optimize_size
474852296Sobrien                  || (GET_CODE (operands[0]) == MEM 
474952296Sobrien                      && memory_address_info (XEXP (operands[0], 0), 1))))
475018334Speter	    return AS1 (not%B0,%b0);
475118334Speter
475218334Speter	  return AS2 (xor%B0,%2,%b0);
475318334Speter	}
475418334Speter
475518334Speter      /* Can we ignore the lower byte? */
475618334Speter      /* ??? what about offsettable memory references? */
475718334Speter      if (QI_REG_P (operands[0])
475818334Speter	  && (INTVAL (operands[2]) & 0xff) == 0)
475918334Speter	{
476018334Speter	  CC_STATUS_INIT;
476118334Speter	  operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
476218334Speter
476352296Sobrien	  if (INTVAL (operands[2]) == 0xff
476452296Sobrien              && (!TARGET_PENTIUM || optimize_size
476552296Sobrien                  || (GET_CODE (operands[0]) == MEM 
476652296Sobrien                      && memory_address_info (XEXP (operands[0], 0), 1))))
476718334Speter	    return AS1 (not%B0,%h0);
476818334Speter
476918334Speter	  return AS2 (xor%B0,%2,%h0);
477018334Speter	}
477118334Speter    }
477218334Speter
477350650Sobrien  if (REG_P (operands[0])
477450650Sobrien      && i386_aligned_p (operands[2]))
477550650Sobrien    {
477650650Sobrien      CC_STATUS_INIT;
477750650Sobrien      operands[2] = i386_sext16_if_const (operands[2]);
477850650Sobrien      return AS2 (xor%L0,%k2,%k0);
477950650Sobrien    }
478050650Sobrien
478150650Sobrien  if (GET_CODE (operands[2]) == CONST_INT
478250650Sobrien      && i386_aligned_p (operands[0]))
478350650Sobrien    {
478450650Sobrien      HOST_WIDE_INT intval;
478550650Sobrien      CC_STATUS_INIT;
478650650Sobrien      intval = 0xffff & INTVAL (operands[2]);
478750650Sobrien      if (intval != INTVAL (operands[2]))
478850650Sobrien	operands[2] = GEN_INT (intval);
478950650Sobrien      return AS2 (xor%L0,%2,%k0);
479050650Sobrien    }
479150650Sobrien
479218334Speter  return AS2 (xor%W0,%2,%0);
479352296Sobrien}"
479452296Sobrien  [(set_attr "type" "binary")])
479518334Speter
479618334Speter(define_insn "xorqi3"
479750650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q")
479850650Sobrien	(xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
479918334Speter		(match_operand:QI 2 "general_operand" "qn,qm")))]
480018334Speter  ""
480152296Sobrien  "* return AS2 (xor%B0,%2,%0);"
480252296Sobrien  [(set_attr "type" "binary")])
480318334Speter
480450650Sobrien;; logical operations for DImode
480550650Sobrien
480650650Sobrien(define_insn "anddi3"
480752296Sobrien  [(set (match_operand:DI 0 "general_operand" "=&r,&ro")
480852296Sobrien	(and:DI (match_operand:DI 1 "general_operand" "%0,0")
480952296Sobrien		(match_operand:DI 2 "general_operand" "oriF,riF")))]
481050650Sobrien  ""
481152296Sobrien  "#"
481252296Sobrien  [(set_attr "type" "binary")])
481350650Sobrien
481452296Sobrien
481550650Sobrien(define_insn "iordi3"
481652296Sobrien  [(set (match_operand:DI 0 "general_operand" "=&r,&ro")
481752296Sobrien	(ior:DI (match_operand:DI 1 "general_operand" "%0,0")
481852296Sobrien		(match_operand:DI 2 "general_operand" "oriF,riF")))]
481950650Sobrien  ""
482052296Sobrien  "#"
482152296Sobrien  [(set_attr "type" "binary")])
482252296Sobrien
482350650Sobrien(define_insn "xordi3"
482452296Sobrien  [(set (match_operand:DI 0 "general_operand" "=&r,&ro")
482552296Sobrien	(xor:DI (match_operand:DI 1 "general_operand" "%0,0")
482652296Sobrien		(match_operand:DI 2 "general_operand" "oriF,riF")))]
482750650Sobrien  ""
482852296Sobrien  "#"
482952296Sobrien  [(set_attr "type" "binary")])
483050650Sobrien
483150650Sobrien(define_split
483252296Sobrien  [(set (match_operand:DI 0 "general_operand" "")
483352296Sobrien	(match_operator:DI 3 "ix86_logical_operator"
483452296Sobrien	  [(match_operand:DI 1 "general_operand" "")
483552296Sobrien	   (match_operand:DI 2 "general_operand" "")]))]
483652296Sobrien  ""
483752296Sobrien  [(set (match_dup 4) (match_op_dup:SI 3 [(match_dup 6) (match_dup 8)]))
483852296Sobrien   (set (match_dup 5) (match_op_dup:SI 3 [(match_dup 7) (match_dup 9)]))]
483952296Sobrien  "split_di (&operands[0], 1, &operands[4], &operands[5]);
484052296Sobrien   split_di (&operands[1], 1, &operands[6], &operands[7]);
484152296Sobrien   split_di (&operands[2], 1, &operands[8], &operands[9]);")
484250650Sobrien
484318334Speter;;- negation instructions
484418334Speter
484518334Speter(define_insn "negdi2"
484618334Speter  [(set (match_operand:DI 0 "general_operand" "=&ro")
484718334Speter	(neg:DI (match_operand:DI 1 "general_operand" "0")))]
484818334Speter  ""
484918334Speter  "*
485018334Speter{
485118334Speter  rtx xops[2], low[1], high[1];
485218334Speter
485318334Speter  CC_STATUS_INIT;
485418334Speter
485518334Speter  split_di (operands, 1, low, high);
485618334Speter  xops[0] = const0_rtx;
485718334Speter  xops[1] = high[0];
485818334Speter
485918334Speter  output_asm_insn (AS1 (neg%L0,%0), low);
486018334Speter  output_asm_insn (AS2 (adc%L1,%0,%1), xops);
486118334Speter  output_asm_insn (AS1 (neg%L0,%0), high);
486218334Speter  RET;
486318334Speter}")
486418334Speter
486518334Speter(define_insn "negsi2"
486650650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
486750650Sobrien	(neg:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
486818334Speter  ""
486918334Speter  "neg%L0 %0")
487018334Speter
487118334Speter(define_insn "neghi2"
487250650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
487350650Sobrien	(neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
487418334Speter  ""
487552296Sobrien  "*
487652296Sobrien    if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn))
487752296Sobrien      {
487852296Sobrien	CC_STATUS_INIT;
487952296Sobrien	return AS1(neg%L0,%k0);
488052296Sobrien      }
488152296Sobrien    return AS1(neg%W0,%0);")
488218334Speter
488318334Speter(define_insn "negqi2"
488450650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
488550650Sobrien	(neg:QI (match_operand:QI 1 "nonimmediate_operand" "0")))]
488618334Speter  ""
488718334Speter  "neg%B0 %0")
488818334Speter
488918334Speter(define_insn "negsf2"
489018334Speter  [(set (match_operand:SF 0 "register_operand" "=f")
489150650Sobrien	(neg:SF (match_operand:SF 1 "register_operand" "0")))]
489218334Speter  "TARGET_80387"
489352296Sobrien  "fchs"
489452296Sobrien  [(set_attr "type" "fpop")])
489518334Speter
489618334Speter(define_insn "negdf2"
489718334Speter  [(set (match_operand:DF 0 "register_operand" "=f")
489850650Sobrien	(neg:DF (match_operand:DF 1 "register_operand" "0")))]
489918334Speter  "TARGET_80387"
490052296Sobrien  "fchs"
490152296Sobrien  [(set_attr "type" "fpop")])
490218334Speter
490318334Speter(define_insn ""
490418334Speter  [(set (match_operand:DF 0 "register_operand" "=f")
490550650Sobrien	(neg:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))]
490618334Speter  "TARGET_80387"
490752296Sobrien  "fchs"
490852296Sobrien  [(set_attr "type" "fpop")])
490918334Speter
491018334Speter(define_insn "negxf2"
491118334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
491250650Sobrien	(neg:XF (match_operand:XF 1 "register_operand" "0")))]
491318334Speter  "TARGET_80387"
491452296Sobrien  "fchs"
491552296Sobrien  [(set_attr "type" "fpop")])
491618334Speter
491718334Speter(define_insn ""
491818334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
491950650Sobrien	(neg:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))]
492018334Speter  "TARGET_80387"
492152296Sobrien  "fchs"
492252296Sobrien  [(set_attr "type" "fpop")])
492318334Speter
492418334Speter;; Absolute value instructions
492518334Speter
492618334Speter(define_insn "abssf2"
492718334Speter  [(set (match_operand:SF 0 "register_operand" "=f")
492850650Sobrien	(abs:SF (match_operand:SF 1 "register_operand" "0")))]
492918334Speter  "TARGET_80387"
493050650Sobrien  "fabs"
493150650Sobrien  [(set_attr "type" "fpop")])
493218334Speter
493318334Speter(define_insn "absdf2"
493418334Speter  [(set (match_operand:DF 0 "register_operand" "=f")
493550650Sobrien	(abs:DF (match_operand:DF 1 "register_operand" "0")))]
493618334Speter  "TARGET_80387"
493750650Sobrien  "fabs"
493850650Sobrien  [(set_attr "type" "fpop")])
493918334Speter
494018334Speter(define_insn ""
494118334Speter  [(set (match_operand:DF 0 "register_operand" "=f")
494250650Sobrien	(abs:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))]
494318334Speter  "TARGET_80387"
494450650Sobrien  "fabs"
494550650Sobrien  [(set_attr "type" "fpop")])
494618334Speter
494718334Speter(define_insn "absxf2"
494818334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
494950650Sobrien	(abs:XF (match_operand:XF 1 "register_operand" "0")))]
495018334Speter  "TARGET_80387"
495150650Sobrien  "fabs"
495250650Sobrien  [(set_attr "type" "fpop")])
495318334Speter
495418334Speter(define_insn ""
495518334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
495650650Sobrien	(abs:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))]
495718334Speter  "TARGET_80387"
495850650Sobrien  "fabs"
495950650Sobrien  [(set_attr "type" "fpop")])
496018334Speter
496118334Speter(define_insn "sqrtsf2"
496218334Speter  [(set (match_operand:SF 0 "register_operand" "=f")
496350650Sobrien	(sqrt:SF (match_operand:SF 1 "register_operand" "0")))]
496450650Sobrien  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387"
496518334Speter  "fsqrt")
496618334Speter
496718334Speter(define_insn "sqrtdf2"
496818334Speter  [(set (match_operand:DF 0 "register_operand" "=f")
496950650Sobrien	(sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
497018334Speter  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
497118334Speter   && (TARGET_IEEE_FP || flag_fast_math) "
497218334Speter  "fsqrt")
497318334Speter
497418334Speter(define_insn ""
497518334Speter  [(set (match_operand:DF 0 "register_operand" "=f")
497618334Speter	(sqrt:DF (float_extend:DF
497750650Sobrien		  (match_operand:SF 1 "register_operand" "0"))))]
497850650Sobrien  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387"
497918334Speter  "fsqrt")
498018334Speter
498118334Speter(define_insn "sqrtxf2"
498218334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
498350650Sobrien	(sqrt:XF (match_operand:XF 1 "register_operand" "0")))]
498418334Speter  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 
498518334Speter   && (TARGET_IEEE_FP || flag_fast_math) "
498618334Speter  "fsqrt")
498718334Speter
498818334Speter(define_insn ""
498918334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
499018334Speter	(sqrt:XF (float_extend:XF
499150650Sobrien		  (match_operand:DF 1 "register_operand" "0"))))]
499250650Sobrien  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387"
499318334Speter  "fsqrt")
499418334Speter
499518334Speter(define_insn ""
499618334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
499718334Speter	(sqrt:XF (float_extend:XF
499850650Sobrien		  (match_operand:SF 1 "register_operand" "0"))))]
499950650Sobrien  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387"
500018334Speter  "fsqrt")
500118334Speter
500218334Speter(define_insn "sindf2"
500318334Speter  [(set (match_operand:DF 0 "register_operand" "=f")
500418334Speter	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))]
500550650Sobrien  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
500618334Speter  "fsin")
500718334Speter
500818334Speter(define_insn "sinsf2"
500918334Speter  [(set (match_operand:SF 0 "register_operand" "=f")
501018334Speter	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))]
501150650Sobrien  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
501218334Speter  "fsin")
501318334Speter
501418334Speter(define_insn ""
501518334Speter  [(set (match_operand:DF 0 "register_operand" "=f")
501618334Speter	(unspec:DF [(float_extend:DF
501718334Speter		     (match_operand:SF 1 "register_operand" "0"))] 1))]
501850650Sobrien  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
501918334Speter  "fsin")
502018334Speter
502118334Speter(define_insn "sinxf2"
502218334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
502318334Speter	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))]
502450650Sobrien  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
502518334Speter  "fsin")
502618334Speter
502718334Speter(define_insn "cosdf2"
502818334Speter  [(set (match_operand:DF 0 "register_operand" "=f")
502918334Speter	(unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))]
503050650Sobrien  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
503118334Speter  "fcos")
503218334Speter
503318334Speter(define_insn "cossf2"
503418334Speter  [(set (match_operand:SF 0 "register_operand" "=f")
503518334Speter	(unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))]
503650650Sobrien  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
503718334Speter  "fcos")
503818334Speter
503918334Speter(define_insn ""
504018334Speter  [(set (match_operand:DF 0 "register_operand" "=f")
504118334Speter	(unspec:DF [(float_extend:DF
504218334Speter		     (match_operand:SF 1 "register_operand" "0"))] 2))]
504350650Sobrien  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
504418334Speter  "fcos")
504518334Speter
504618334Speter(define_insn "cosxf2"
504718334Speter  [(set (match_operand:XF 0 "register_operand" "=f")
504818334Speter	(unspec:XF [(match_operand:XF 1 "register_operand" "0")] 2))]
504950650Sobrien  "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
505018334Speter  "fcos")
505118334Speter
505218334Speter;;- one complement instructions
505318334Speter
505418334Speter(define_insn "one_cmplsi2"
505550650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
505650650Sobrien	(not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
505718334Speter  ""
505852296Sobrien  "*
505952296Sobrien{
506052296Sobrien  /* A Pentium NOT is not pariable.  Output it only in case of complex
506152296Sobrien     memory address, because XOR will be inpariable anyway because
506252296Sobrien     of immediate/displacement rule.  */
506318334Speter
506452296Sobrien  if (TARGET_PENTIUM && !optimize_size
506552296Sobrien      && (GET_CODE (operands[0]) != MEM 
506652296Sobrien	  || memory_address_info (XEXP (operands[0], 0), 1) == 0))
506752296Sobrien    {
506852296Sobrien      rtx xops[2];
506952296Sobrien      xops[0] = operands[0];
507052296Sobrien      xops[1] = GEN_INT (0xffffffff);
507152296Sobrien      output_asm_insn (AS2 (xor%L0,%1,%0), xops);
507252296Sobrien      RET;
507352296Sobrien    }
507452296Sobrien  else
507552296Sobrien    return AS1 (not%L0,%0);
507652296Sobrien}")
507752296Sobrien
507818334Speter(define_insn "one_cmplhi2"
507950650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
508050650Sobrien	(not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
508118334Speter  ""
508252296Sobrien  "*
508352296Sobrien{
508452296Sobrien  /* A Pentium NOT is not pariable.  Output it only in case of complex
508552296Sobrien     memory address, because XOR will be inpariable anyway because
508652296Sobrien     of immediate/displacement rule.  */
508718334Speter
508852296Sobrien  if (TARGET_PENTIUM && !optimize_size
508952296Sobrien      && (GET_CODE (operands[0]) != MEM 
509052296Sobrien	  || memory_address_info (XEXP (operands[0], 0), 1) == 0))
509152296Sobrien    {
509252296Sobrien      rtx xops[2];
509352296Sobrien      xops[0] = operands[0];
509452296Sobrien      xops[1] = GEN_INT (0xffff);
509552296Sobrien      if (REG_P (operands[0])
509652296Sobrien	  && i386_cc_probably_useless_p (insn))
509752296Sobrien       {
509852296Sobrien	  CC_STATUS_INIT;
509952296Sobrien	  output_asm_insn (AS2 (xor%L0,%1,%k0), xops);
510052296Sobrien       }
510152296Sobrien      else
510252296Sobrien	output_asm_insn (AS2 (xor%W0,%1,%0), xops);
510352296Sobrien      RET;
510452296Sobrien    }
510552296Sobrien  else
510652296Sobrien    {
510752296Sobrien      if (REG_P (operands[0])
510852296Sobrien	  && i386_cc_probably_useless_p (insn))
510952296Sobrien	{
511052296Sobrien	  CC_STATUS_INIT;
511152296Sobrien	  return AS1 (not%L0,%k0);
511252296Sobrien	}
511352296Sobrien      return AS1 (not%W0,%0);
511452296Sobrien    }
511552296Sobrien}")
511652296Sobrien
511718334Speter(define_insn "one_cmplqi2"
511850650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
511950650Sobrien	(not:QI (match_operand:QI 1 "nonimmediate_operand" "0")))]
512018334Speter  ""
512152296Sobrien  "*
512252296Sobrien{
512352296Sobrien  /* A Pentium NOT is not pariable.  Output it only in case of complex
512452296Sobrien     memory address, because XOR will be inpariable anyway because
512552296Sobrien     of immediate/displacement rule.  */
512652296Sobrien
512752296Sobrien  if (TARGET_PENTIUM && !optimize_size
512852296Sobrien      && (GET_CODE (operands[0]) != MEM 
512952296Sobrien	  || memory_address_info (XEXP (operands[0], 0), 1) == 0))
513052296Sobrien    {
513152296Sobrien      rtx xops[2];
513252296Sobrien      xops[0] = operands[0];
513352296Sobrien      xops[1] = GEN_INT (0xff);
513452296Sobrien      output_asm_insn (AS2 (xor%B0,%1,%0), xops);
513552296Sobrien      RET;
513652296Sobrien    }
513752296Sobrien  else
513852296Sobrien    return AS1 (not%B0,%0);
513952296Sobrien}")
514018334Speter
514118334Speter;;- arithmetic shift instructions
514218334Speter
514318334Speter;; DImode shifts are implemented using the i386 "shift double" opcode,
514418334Speter;; which is written as "sh[lr]d[lw] imm,reg,reg/mem".  If the shift count
514518334Speter;; is variable, then the count is in %cl and the "imm" operand is dropped
514618334Speter;; from the assembler input.
514718334Speter
514818334Speter;; This instruction shifts the target reg/mem as usual, but instead of
514918334Speter;; shifting in zeros, bits are shifted in from reg operand.  If the insn
515018334Speter;; is a left shift double, bits are taken from the high order bits of
515118334Speter;; reg, else if the insn is a shift right double, bits are taken from the
515218334Speter;; low order bits of reg.  So if %eax is "1234" and %edx is "5678",
515318334Speter;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345".
515418334Speter
515518334Speter;; Since sh[lr]d does not change the `reg' operand, that is done
515618334Speter;; separately, making all shifts emit pairs of shift double and normal
515718334Speter;; shift.  Since sh[lr]d does not shift more than 31 bits, and we wish to
515818334Speter;; support a 63 bit shift, each shift where the count is in a reg expands
515950650Sobrien;; to a pair of shifts, a branch, a shift by 32 and a label.
516018334Speter
516118334Speter;; If the shift count is a constant, we need never emit more than one
516218334Speter;; shift pair, instead using moves and sign extension for counts greater
516318334Speter;; than 31.
516418334Speter
516518334Speter(define_expand "ashldi3"
516618334Speter  [(set (match_operand:DI 0 "register_operand" "")
516718334Speter	(ashift:DI (match_operand:DI 1 "register_operand" "")
516818334Speter		   (match_operand:QI 2 "nonmemory_operand" "")))]
516918334Speter  ""
517018334Speter  "
517118334Speter{
517218334Speter  if (GET_CODE (operands[2]) != CONST_INT
517318334Speter      || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
517418334Speter    {
517518334Speter      operands[2] = copy_to_mode_reg (QImode, operands[2]);
517618334Speter      emit_insn (gen_ashldi3_non_const_int (operands[0], operands[1],
517718334Speter					    operands[2]));
517818334Speter    }
517918334Speter  else
518018334Speter    emit_insn (gen_ashldi3_const_int (operands[0], operands[1], operands[2]));
518118334Speter
518218334Speter  DONE;
518318334Speter}")
518418334Speter
518518334Speter(define_insn "ashldi3_const_int"
518618334Speter  [(set (match_operand:DI 0 "register_operand" "=&r")
518718334Speter	(ashift:DI (match_operand:DI 1 "register_operand" "0")
518818334Speter		   (match_operand:QI 2 "const_int_operand" "J")))]
518950650Sobrien  "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')"
519018334Speter  "*
519118334Speter{
519218334Speter  rtx xops[4], low[1], high[1];
519318334Speter
519418334Speter  CC_STATUS_INIT;
519518334Speter
519618334Speter  split_di (operands, 1, low, high);
519718334Speter  xops[0] = operands[2];
519818334Speter  xops[1] = const1_rtx;
519918334Speter  xops[2] = low[0];
520018334Speter  xops[3] = high[0];
520118334Speter
520218334Speter  if (INTVAL (xops[0]) > 31)
520318334Speter    {
520418334Speter      output_asm_insn (AS2 (mov%L3,%2,%3), xops);	/* Fast shift by 32 */
520518334Speter      output_asm_insn (AS2 (xor%L2,%2,%2), xops);
520618334Speter
520718334Speter      if (INTVAL (xops[0]) > 32)
520818334Speter        {
520918334Speter	  xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
521018334Speter	  output_asm_insn (AS2 (sal%L3,%0,%3), xops); /* Remaining shift */
521118334Speter	}
521218334Speter    }
521318334Speter  else
521418334Speter    {
521518334Speter      output_asm_insn (AS3 (shld%L3,%0,%2,%3), xops);
521618334Speter      output_asm_insn (AS2 (sal%L2,%0,%2), xops);
521718334Speter    }
521818334Speter  RET;
521918334Speter}")
522018334Speter
522118334Speter(define_insn "ashldi3_non_const_int"
522218334Speter  [(set (match_operand:DI 0 "register_operand" "=&r")
522318334Speter	(ashift:DI (match_operand:DI 1 "register_operand" "0")
522450650Sobrien		   (match_operand:QI 2 "register_operand" "c")))]
522518334Speter  ""
522618334Speter  "*
522718334Speter{
522850650Sobrien  rtx xops[5], low[1], high[1];
522918334Speter
523018334Speter  CC_STATUS_INIT;
523118334Speter
523218334Speter  split_di (operands, 1, low, high);
523318334Speter  xops[0] = operands[2];
523450650Sobrien  xops[1] = GEN_INT (32);
523518334Speter  xops[2] = low[0];
523618334Speter  xops[3] = high[0];
523750650Sobrien  xops[4] = gen_label_rtx ();
523818334Speter
523918334Speter  output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops);
524018334Speter  output_asm_insn (AS2 (sal%L2,%0,%2), xops);
524150650Sobrien  output_asm_insn (AS2 (test%B0,%1,%b0), xops);
524250650Sobrien  output_asm_insn (AS1 (je,%X4), xops);
524350650Sobrien  output_asm_insn (AS2 (mov%L3,%2,%3), xops);	/* Fast shift by 32 */
524450650Sobrien  output_asm_insn (AS2 (xor%L2,%2,%2), xops);
524550650Sobrien  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
524650650Sobrien                             CODE_LABEL_NUMBER (xops[4]));
524718334Speter  RET;
524818334Speter}")
524918334Speter
525052296Sobrien(define_expand "ashlsi3"
525152296Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "")
525252296Sobrien	(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "")
525352296Sobrien		   (match_operand:SI 2 "nonmemory_operand" "")))]
525452296Sobrien  ""
525552296Sobrien  "")
525618334Speter
525752296Sobrien(define_expand "ashlhi3"
525852296Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "")
525952296Sobrien	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "")
526052296Sobrien		   (match_operand:HI 2 "nonmemory_operand" "")))]
526118334Speter  ""
526252296Sobrien  "")
526318334Speter
526452296Sobrien(define_expand "ashlqi3"
526552296Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "")
526652296Sobrien	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "")
526752296Sobrien		   (match_operand:QI 2 "nonmemory_operand" "")))]
526852296Sobrien  ""
526952296Sobrien  "")
527018334Speter
527152296Sobrien;; Pattern for shifts which can be encoded into an lea instruction.
527252296Sobrien;; This is kept as a separate pattern so that regmove can optimize cases
527352296Sobrien;; where we know the source and destination must match.
527452296Sobrien;;
527552296Sobrien;; Do not expose this pattern when optimizing for size since we never want
527652296Sobrien;; to use lea when optimizing for size since mov+sal is smaller than lea.
527718334Speter
527852296Sobrien(define_insn ""
527952296Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r")
528052296Sobrien	(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,r")
528152296Sobrien		   (match_operand:SI 2 "small_shift_operand" "M,M")))]
528252296Sobrien  "! optimize_size"
528352296Sobrien  "* return output_ashl (insn, operands);")
528418334Speter
528552296Sobrien;; Generic left shift pattern to catch all cases not handled by the
528652296Sobrien;; shift pattern above.
528752296Sobrien(define_insn ""
528852296Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
528952296Sobrien	(ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0")
529052296Sobrien		   (match_operand:SI 2 "nonmemory_operand" "cI")))]
529152296Sobrien  ""
529252296Sobrien  "* return output_ashl (insn, operands);")
529318334Speter
529452296Sobrien(define_insn ""
529552296Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r")
529652296Sobrien	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,r")
529752296Sobrien		   (match_operand:HI 2 "small_shift_operand" "M,M")))]
529852296Sobrien  "! optimize_size"
529952296Sobrien  "* return output_ashl (insn, operands);")
530052296Sobrien
530152296Sobrien(define_insn ""
530250650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
530350650Sobrien	(ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
530418334Speter		   (match_operand:HI 2 "nonmemory_operand" "cI")))]
530518334Speter  ""
530652296Sobrien  "* return output_ashl (insn, operands);")
530718334Speter
530852296Sobrien(define_insn ""
530952296Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q")
531052296Sobrien	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,q")
531152296Sobrien		   (match_operand:QI 2 "small_shift_operand" "M,M")))]
531252296Sobrien  "! optimize_size"
531352296Sobrien  "* return output_ashl (insn, operands);")
531418334Speter
531552296Sobrien;; Generic left shift pattern to catch all cases not handled by the
531652296Sobrien;; shift pattern above.
531752296Sobrien(define_insn ""
531850650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
531950650Sobrien	(ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
532018334Speter		   (match_operand:QI 2 "nonmemory_operand" "cI")))]
532118334Speter  ""
532252296Sobrien  "* return output_ashl (insn, operands);")
532318334Speter
532418334Speter;; See comment above `ashldi3' about how this works.
532518334Speter
532618334Speter(define_expand "ashrdi3"
532718334Speter  [(set (match_operand:DI 0 "register_operand" "")
532818334Speter	(ashiftrt:DI (match_operand:DI 1 "register_operand" "")
532918334Speter		     (match_operand:QI 2 "nonmemory_operand" "")))]
533018334Speter  ""
533118334Speter  "
533218334Speter{
533318334Speter  if (GET_CODE (operands[2]) != CONST_INT
533418334Speter      || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
533518334Speter    {
533618334Speter      operands[2] = copy_to_mode_reg (QImode, operands[2]);
533718334Speter      emit_insn (gen_ashrdi3_non_const_int (operands[0], operands[1],
533818334Speter					    operands[2]));
533918334Speter    }
534018334Speter  else
534118334Speter    emit_insn (gen_ashrdi3_const_int (operands[0], operands[1], operands[2]));
534218334Speter
534318334Speter  DONE;
534418334Speter}")
534518334Speter
534650650Sobrien(define_insn "ashldi3_32"
534750650Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,m")
534850650Sobrien	(ashift:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r")
534950650Sobrien		   (const_int 32)))]
535050650Sobrien  ""
535150650Sobrien  "*
535250650Sobrien{
535350650Sobrien  rtx low[2], high[2], xops[4];
535450650Sobrien
535550650Sobrien  split_di (operands, 2, low, high);
535650650Sobrien  xops[0] = high[0];
535750650Sobrien  xops[1] = low[1];
535850650Sobrien  xops[2] = low[0];
535950650Sobrien  xops[3] = const0_rtx;
536050650Sobrien  if (!rtx_equal_p (xops[0], xops[1]))
536150650Sobrien    output_asm_insn (AS2 (mov%L0,%1,%0), xops);
536250650Sobrien
536350650Sobrien  if (GET_CODE (low[0]) == MEM)
536450650Sobrien    output_asm_insn (AS2 (mov%L2,%3,%2), xops);
536550650Sobrien  else
536650650Sobrien    output_asm_insn (AS2 (xor%L2,%2,%2), xops);
536750650Sobrien
536850650Sobrien  RET;
536950650Sobrien}")
537050650Sobrien
537118334Speter(define_insn "ashrdi3_const_int"
537218334Speter  [(set (match_operand:DI 0 "register_operand" "=&r")
537318334Speter	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
537418334Speter		     (match_operand:QI 2 "const_int_operand" "J")))]
537550650Sobrien  "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')"
537618334Speter  "*
537718334Speter{
537818334Speter  rtx xops[4], low[1], high[1];
537918334Speter
538018334Speter  CC_STATUS_INIT;
538118334Speter
538218334Speter  split_di (operands, 1, low, high);
538318334Speter  xops[0] = operands[2];
538418334Speter  xops[1] = const1_rtx;
538518334Speter  xops[2] = low[0];
538618334Speter  xops[3] = high[0];
538718334Speter
538818334Speter  if (INTVAL (xops[0]) > 31)
538918334Speter    {
539018334Speter      xops[1] = GEN_INT (31);
539118334Speter      output_asm_insn (AS2 (mov%L2,%3,%2), xops);
539218334Speter      output_asm_insn (AS2 (sar%L3,%1,%3), xops);	/* shift by 32 */
539318334Speter
539418334Speter      if (INTVAL (xops[0]) > 32)
539518334Speter        {
539618334Speter	  xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
539718334Speter	  output_asm_insn (AS2 (sar%L2,%0,%2), xops); /* Remaining shift */
539818334Speter	}
539918334Speter    }
540018334Speter  else
540118334Speter    {
540218334Speter      output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops);
540318334Speter      output_asm_insn (AS2 (sar%L3,%0,%3), xops);
540418334Speter    }
540518334Speter
540618334Speter  RET;
540718334Speter}")
540818334Speter
540918334Speter(define_insn "ashrdi3_non_const_int"
541018334Speter  [(set (match_operand:DI 0 "register_operand" "=&r")
541118334Speter	(ashiftrt:DI (match_operand:DI 1 "register_operand" "0")
541250650Sobrien		     (match_operand:QI 2 "register_operand" "c")))]
541318334Speter  ""
541418334Speter  "*
541518334Speter{
541650650Sobrien  rtx xops[5], low[1], high[1];
541718334Speter
541818334Speter  CC_STATUS_INIT;
541918334Speter
542018334Speter  split_di (operands, 1, low, high);
542118334Speter  xops[0] = operands[2];
542250650Sobrien  xops[1] = GEN_INT (32);
542318334Speter  xops[2] = low[0];
542418334Speter  xops[3] = high[0];
542550650Sobrien  xops[4] = gen_label_rtx ();
542618334Speter
542718334Speter  output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
542818334Speter  output_asm_insn (AS2 (sar%L3,%0,%3), xops);
542950650Sobrien  output_asm_insn (AS2 (test%B0,%1,%b0), xops);
543050650Sobrien  output_asm_insn (AS1 (je,%X4), xops);
543150650Sobrien  xops[1] = GEN_INT (31);
543250650Sobrien  output_asm_insn (AS2 (mov%L2,%3,%2), xops);
543350650Sobrien  output_asm_insn (AS2 (sar%L3,%1,%3), xops);	/* shift by 32 */
543450650Sobrien  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
543550650Sobrien                             CODE_LABEL_NUMBER (xops[4]));
543618334Speter  RET;
543718334Speter}")
543818334Speter
543952296Sobrien(define_insn "ashrsi3_31"
544052296Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,d")
544152296Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,a")
544252296Sobrien		     (const_int 31)))]
544352296Sobrien  "!TARGET_PENTIUM || optimize_size"
544452296Sobrien  "@
544552296Sobrien    sar%L0 $31,%0
544652296Sobrien    cltd")
544752296Sobrien
544818334Speter(define_insn "ashrsi3"
544950650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
545050650Sobrien	(ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
545118334Speter		     (match_operand:SI 2 "nonmemory_operand" "cI")))]
545218334Speter  ""
545318334Speter  "*
545418334Speter{
545518334Speter  if (REG_P (operands[2]))
545618334Speter    return AS2 (sar%L0,%b2,%0);
545718334Speter  else
545818334Speter    return AS2 (sar%L0,%2,%0);
545918334Speter}")
546018334Speter
546118334Speter(define_insn "ashrhi3"
546250650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
546350650Sobrien	(ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
546418334Speter		     (match_operand:HI 2 "nonmemory_operand" "cI")))]
546518334Speter  ""
546618334Speter  "*
546718334Speter{
546818334Speter  if (REG_P (operands[2]))
546918334Speter    return AS2 (sar%W0,%b2,%0);
547018334Speter  else
547118334Speter    return AS2 (sar%W0,%2,%0);
547218334Speter}")
547318334Speter
547418334Speter(define_insn "ashrqi3"
547550650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
547650650Sobrien	(ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
547718334Speter		     (match_operand:QI 2 "nonmemory_operand" "cI")))]
547818334Speter  ""
547918334Speter  "*
548018334Speter{
548118334Speter  if (REG_P (operands[2]))
548218334Speter    return AS2 (sar%B0,%b2,%0);
548318334Speter  else
548418334Speter    return AS2 (sar%B0,%2,%0);
548518334Speter}")
548618334Speter
548718334Speter;;- logical shift instructions
548818334Speter
548918334Speter;; See comment above `ashldi3' about how this works.
549018334Speter
549118334Speter(define_expand "lshrdi3"
549218334Speter  [(set (match_operand:DI 0 "register_operand" "")
549318334Speter	(lshiftrt:DI (match_operand:DI 1 "register_operand" "")
549418334Speter		     (match_operand:QI 2 "nonmemory_operand" "")))]
549518334Speter  ""
549618334Speter  "
549718334Speter{
549818334Speter  if (GET_CODE (operands[2]) != CONST_INT
549918334Speter      || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J'))
550018334Speter    {
550118334Speter      operands[2] = copy_to_mode_reg (QImode, operands[2]);
550218334Speter      emit_insn (gen_lshrdi3_non_const_int (operands[0], operands[1],
550318334Speter					    operands[2]));
550418334Speter    }
550518334Speter  else
550618334Speter    emit_insn (gen_lshrdi3_const_int (operands[0], operands[1], operands[2]));
550718334Speter
550818334Speter  DONE;
550918334Speter}")
551018334Speter
551150650Sobrien(define_insn "lshrdi3_32"
551250650Sobrien  [(set (match_operand:DI 0 "nonimmediate_operand" "=r,m")
551350650Sobrien	(lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r")
551450650Sobrien		     (const_int 32)))]
551550650Sobrien  ""
551650650Sobrien  "*
551750650Sobrien{
551850650Sobrien  rtx low[2], high[2], xops[4];
551950650Sobrien
552050650Sobrien  split_di (operands, 2, low, high);
552150650Sobrien  xops[0] = low[0];
552250650Sobrien  xops[1] = high[1];
552350650Sobrien  xops[2] = high[0];
552450650Sobrien  xops[3] = const0_rtx;
552550650Sobrien  if (!rtx_equal_p (xops[0], xops[1]))
552650650Sobrien    output_asm_insn (AS2 (mov%L0,%1,%0), xops);
552750650Sobrien
552850650Sobrien  if (GET_CODE (low[0]) == MEM)
552950650Sobrien    output_asm_insn (AS2 (mov%L2,%3,%2), xops);
553050650Sobrien  else
553150650Sobrien    output_asm_insn (AS2 (xor%L2,%2,%2), xops);
553250650Sobrien
553350650Sobrien  RET;
553450650Sobrien}")
553550650Sobrien
553618334Speter(define_insn "lshrdi3_const_int"
553718334Speter  [(set (match_operand:DI 0 "register_operand" "=&r")
553818334Speter	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
553918334Speter		     (match_operand:QI 2 "const_int_operand" "J")))]
554050650Sobrien  "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')"
554118334Speter  "*
554218334Speter{
554318334Speter  rtx xops[4], low[1], high[1];
554418334Speter
554518334Speter  CC_STATUS_INIT;
554618334Speter
554718334Speter  split_di (operands, 1, low, high);
554818334Speter  xops[0] = operands[2];
554918334Speter  xops[1] = const1_rtx;
555018334Speter  xops[2] = low[0];
555118334Speter  xops[3] = high[0];
555218334Speter
555318334Speter  if (INTVAL (xops[0]) > 31)
555418334Speter    {
555518334Speter      output_asm_insn (AS2 (mov%L2,%3,%2), xops);	/* Fast shift by 32 */
555618334Speter      output_asm_insn (AS2 (xor%L3,%3,%3), xops);
555718334Speter
555818334Speter      if (INTVAL (xops[0]) > 32)
555918334Speter        {
556018334Speter	  xops[0] = GEN_INT (INTVAL (xops[0]) - 32);
556118334Speter	  output_asm_insn (AS2 (shr%L2,%0,%2), xops); /* Remaining shift */
556218334Speter	}
556318334Speter    }
556418334Speter  else
556518334Speter    {
556618334Speter      output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops);
556718334Speter      output_asm_insn (AS2 (shr%L3,%0,%3), xops);
556818334Speter    }
556918334Speter
557018334Speter  RET;
557118334Speter}")
557218334Speter
557318334Speter(define_insn "lshrdi3_non_const_int"
557418334Speter  [(set (match_operand:DI 0 "register_operand" "=&r")
557518334Speter	(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
557650650Sobrien		     (match_operand:QI 2 "register_operand" "c")))]
557718334Speter  ""
557818334Speter  "*
557918334Speter{
558050650Sobrien  rtx xops[5], low[1], high[1];
558118334Speter
558218334Speter  CC_STATUS_INIT;
558318334Speter
558418334Speter  split_di (operands, 1, low, high);
558518334Speter  xops[0] = operands[2];
558650650Sobrien  xops[1] = GEN_INT (32);
558718334Speter  xops[2] = low[0];
558818334Speter  xops[3] = high[0];
558950650Sobrien  xops[4] = gen_label_rtx ();
559018334Speter
559118334Speter  output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
559218334Speter  output_asm_insn (AS2 (shr%L3,%0,%3), xops);
559350650Sobrien  output_asm_insn (AS2 (test%B0,%1,%b0), xops);
559450650Sobrien  output_asm_insn (AS1 (je,%X4), xops);
559550650Sobrien  output_asm_insn (AS2 (mov%L2,%3,%2), xops);	/* Fast shift by 32 */
559650650Sobrien  output_asm_insn (AS2 (xor%L3,%3,%3), xops);
559750650Sobrien  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
559850650Sobrien                             CODE_LABEL_NUMBER (xops[4]));
559918334Speter  RET;
560018334Speter}")
560118334Speter
560218334Speter(define_insn "lshrsi3"
560350650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
560450650Sobrien	(lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
560518334Speter		     (match_operand:SI 2 "nonmemory_operand" "cI")))]
560618334Speter  ""
560718334Speter  "*
560818334Speter{
560918334Speter  if (REG_P (operands[2]))
561018334Speter    return AS2 (shr%L0,%b2,%0);
561118334Speter  else
561218334Speter    return AS2 (shr%L0,%2,%1);
561318334Speter}")
561418334Speter
561518334Speter(define_insn "lshrhi3"
561650650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
561750650Sobrien	(lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
561818334Speter		     (match_operand:HI 2 "nonmemory_operand" "cI")))]
561918334Speter  ""
562018334Speter  "*
562118334Speter{
562218334Speter  if (REG_P (operands[2]))
562318334Speter    return AS2 (shr%W0,%b2,%0);
562418334Speter  else
562518334Speter    return AS2 (shr%W0,%2,%0);
562618334Speter}")
562718334Speter
562818334Speter(define_insn "lshrqi3"
562950650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
563050650Sobrien	(lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
563118334Speter		     (match_operand:QI 2 "nonmemory_operand" "cI")))]
563218334Speter  ""
563318334Speter  "*
563418334Speter{
563518334Speter  if (REG_P (operands[2]))
563618334Speter    return AS2 (shr%B0,%b2,%0);
563718334Speter  else
563818334Speter    return AS2 (shr%B0,%2,%0);
563918334Speter}")
564018334Speter
564118334Speter;;- rotate instructions
564218334Speter
564318334Speter(define_insn "rotlsi3"
564450650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
564550650Sobrien	(rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0")
564618334Speter		   (match_operand:SI 2 "nonmemory_operand" "cI")))]
564718334Speter  ""
564818334Speter  "*
564918334Speter{
565018334Speter  if (REG_P (operands[2]))
565118334Speter    return AS2 (rol%L0,%b2,%0);
565218334Speter  else
565318334Speter    return AS2 (rol%L0,%2,%0);
565418334Speter}")
565518334Speter
565618334Speter(define_insn "rotlhi3"
565750650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
565850650Sobrien	(rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0")
565918334Speter		   (match_operand:HI 2 "nonmemory_operand" "cI")))]
566018334Speter  ""
566118334Speter  "*
566218334Speter{
566318334Speter  if (REG_P (operands[2]))
566418334Speter    return AS2 (rol%W0,%b2,%0);
566518334Speter  else
566618334Speter    return AS2 (rol%W0,%2,%0);
566718334Speter}")
566818334Speter
566918334Speter(define_insn "rotlqi3"
567050650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
567150650Sobrien	(rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0")
567218334Speter		   (match_operand:QI 2 "nonmemory_operand" "cI")))]
567318334Speter  ""
567418334Speter  "*
567518334Speter{
567618334Speter  if (REG_P (operands[2]))
567718334Speter    return AS2 (rol%B0,%b2,%0);
567818334Speter  else
567918334Speter    return AS2 (rol%B0,%2,%0);
568018334Speter}")
568118334Speter
568218334Speter(define_insn "rotrsi3"
568350650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
568450650Sobrien	(rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0")
568518334Speter		     (match_operand:SI 2 "nonmemory_operand" "cI")))]
568618334Speter  ""
568718334Speter  "*
568818334Speter{
568918334Speter  if (REG_P (operands[2]))
569018334Speter    return AS2 (ror%L0,%b2,%0);
569118334Speter  else
569218334Speter    return AS2 (ror%L0,%2,%0);
569318334Speter}")
569418334Speter
569518334Speter(define_insn "rotrhi3"
569650650Sobrien  [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
569750650Sobrien	(rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0")
569818334Speter		     (match_operand:HI 2 "nonmemory_operand" "cI")))]
569918334Speter  ""
570018334Speter  "*
570118334Speter{
570218334Speter  if (REG_P (operands[2]))
570318334Speter    return AS2 (ror%W0,%b2,%0);
570418334Speter  else
570518334Speter    return AS2 (ror%W0,%2,%0);
570618334Speter}")
570718334Speter
570818334Speter(define_insn "rotrqi3"
570950650Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
571050650Sobrien	(rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0")
571118334Speter		     (match_operand:QI 2 "nonmemory_operand" "cI")))]
571218334Speter  ""
571318334Speter  "*
571418334Speter{
571518334Speter  if (REG_P (operands[2]))
571618334Speter    return AS2 (ror%B0,%b2,%0);
571718334Speter  else
571818334Speter    return AS2 (ror%B0,%2,%0);
571918334Speter}")
572018334Speter
572118334Speter/*
572218334Speter;; This usually looses.  But try a define_expand to recognize a few case
572318334Speter;; we can do efficiently, such as accessing the "high" QImode registers,
572418334Speter;; %ah, %bh, %ch, %dh.
572550650Sobrien;; ??? Note this has a botch on the mode of operand 0, which needs to be
572650650Sobrien;; fixed if this is ever enabled.
572718334Speter(define_insn "insv"
572818334Speter  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+&r")
572950650Sobrien			 (match_operand:SI 1 "immediate_operand" "i")
573050650Sobrien			 (match_operand:SI 2 "immediate_operand" "i"))
573150650Sobrien	(match_operand:SI 3 "nonmemory_operand" "ri"))]
573218334Speter  ""
573318334Speter  "*
573418334Speter{
573518334Speter  if (INTVAL (operands[1]) + INTVAL (operands[2]) > GET_MODE_BITSIZE (SImode))
573618334Speter    abort ();
573718334Speter  if (GET_CODE (operands[3]) == CONST_INT)
573818334Speter    {
573918334Speter      unsigned int mask = (1 << INTVAL (operands[1])) - 1; 
574018334Speter      operands[1] = GEN_INT (~(mask << INTVAL (operands[2])));
574118334Speter      output_asm_insn (AS2 (and%L0,%1,%0), operands);
574218334Speter      operands[3] = GEN_INT (INTVAL (operands[3]) << INTVAL (operands[2]));
574318334Speter      output_asm_insn (AS2 (or%L0,%3,%0), operands);
574418334Speter    }
574518334Speter  else
574618334Speter    {
574750650Sobrien      operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]));
574818334Speter      if (INTVAL (operands[2]))
574918334Speter	output_asm_insn (AS2 (ror%L0,%2,%0), operands);
575018334Speter      output_asm_insn (AS3 (shrd%L0,%1,%3,%0), operands);
575118334Speter      operands[2] = GEN_INT (BITS_PER_WORD
575218334Speter			     - INTVAL (operands[1]) - INTVAL (operands[2]));
575318334Speter      if (INTVAL (operands[2]))
575418334Speter	output_asm_insn (AS2 (ror%L0,%2,%0), operands);
575518334Speter    }
575618334Speter  RET;
575718334Speter}")
575818334Speter*/
575918334Speter/*
576018334Speter;; ??? There are problems with the mode of operand[3].  The point of this
576118334Speter;; is to represent an HImode move to a "high byte" register.
576218334Speter
576318334Speter(define_expand "insv"
576418334Speter  [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "")
576518334Speter			 (match_operand:SI 1 "immediate_operand" "")
576618334Speter			 (match_operand:SI 2 "immediate_operand" ""))
576750650Sobrien	(match_operand:QI 3 "nonmemory_operand" "ri"))]
576818334Speter  ""
576918334Speter  "
577018334Speter{
577118334Speter  if (GET_CODE (operands[1]) != CONST_INT
577218334Speter      || GET_CODE (operands[2]) != CONST_INT)
577318334Speter    FAIL;
577418334Speter
577518334Speter  if (! (INTVAL (operands[1]) == 8
577618334Speter	 && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 0))
577718334Speter      && ! INTVAL (operands[1]) == 1)
577818334Speter    FAIL;
577918334Speter}")
578018334Speter*/
578118334Speter
578218334Speter;; On i386, the register count for a bit operation is *not* truncated,
578318334Speter;; so SHIFT_COUNT_TRUNCATED must not be defined.
578418334Speter
578518334Speter;; On i486, the shift & or/and code is faster than bts or btr.  If
578618334Speter;; operands[0] is a MEM, the bt[sr] is half as fast as the normal code.
578718334Speter
578818334Speter;; On i386, bts is a little faster if operands[0] is a reg, and a
578918334Speter;; little slower if operands[0] is a MEM, than the shift & or/and code.
579018334Speter;; Use bts & btr, since they reload better.
579118334Speter
579218334Speter;; General bit set and clear.
579318334Speter(define_insn ""
579450650Sobrien  [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+rm")
579518334Speter			 (const_int 1)
579650650Sobrien			 (match_operand:SI 2 "register_operand" "r"))
579718334Speter	(match_operand:SI 3 "const_int_operand" "n"))]
579850650Sobrien  "TARGET_USE_BIT_TEST && GET_CODE (operands[2]) != CONST_INT"
579918334Speter  "*
580018334Speter{
580118334Speter  CC_STATUS_INIT;
580218334Speter
580318334Speter  if (INTVAL (operands[3]) == 1)
580418334Speter    return AS2 (bts%L0,%2,%0);
580518334Speter  else
580618334Speter    return AS2 (btr%L0,%2,%0);
580718334Speter}")
580818334Speter
580918334Speter;; Bit complement.  See comments on previous pattern.
581018334Speter;; ??? Is this really worthwhile?
581118334Speter(define_insn ""
581250650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
581318334Speter	(xor:SI (ashift:SI (const_int 1)
581450650Sobrien			   (match_operand:SI 1 "register_operand" "r"))
581550650Sobrien		(match_operand:SI 2 "nonimmediate_operand" "0")))]
581650650Sobrien  "TARGET_USE_BIT_TEST && GET_CODE (operands[1]) != CONST_INT"
581718334Speter  "*
581818334Speter{
581918334Speter  CC_STATUS_INIT;
582018334Speter
582118334Speter  return AS2 (btc%L0,%1,%0);
582218334Speter}")
582318334Speter
582418334Speter(define_insn ""
582550650Sobrien  [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
582650650Sobrien	(xor:SI (match_operand:SI 1 "nonimmediate_operand" "0")
582718334Speter		(ashift:SI (const_int 1)
582850650Sobrien			   (match_operand:SI 2 "register_operand" "r"))))]
582950650Sobrien  "TARGET_USE_BIT_TEST && GET_CODE (operands[2]) != CONST_INT"
583018334Speter  "*
583118334Speter{
583218334Speter  CC_STATUS_INIT;
583318334Speter
583418334Speter  return AS2 (btc%L0,%2,%0);
583518334Speter}")
583618334Speter
583718334Speter;; Recognizers for bit-test instructions.
583818334Speter
583918334Speter;; The bt opcode allows a MEM in operands[0].  But on both i386 and
584018334Speter;; i486, it is faster to copy a MEM to REG and then use bt, than to use
584118334Speter;; bt on the MEM directly.
584218334Speter
584318334Speter;; ??? The first argument of a zero_extract must not be reloaded, so
584418334Speter;; don't allow a MEM in the operand predicate without allowing it in the
584518334Speter;; constraint.
584618334Speter
584718334Speter(define_insn ""
584818334Speter  [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
584918334Speter			    (const_int 1)
585050650Sobrien			    (match_operand:SI 1 "register_operand" "r")))]
585118334Speter  "GET_CODE (operands[1]) != CONST_INT"
585218334Speter  "*
585318334Speter{
585418334Speter  cc_status.flags |= CC_Z_IN_NOT_C;
585518334Speter  return AS2 (bt%L0,%1,%0);
585618334Speter}")
585718334Speter
585818334Speter(define_insn ""
585918334Speter  [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
586018334Speter			    (match_operand:SI 1 "const_int_operand" "n")
586118334Speter			    (match_operand:SI 2 "const_int_operand" "n")))]
586218334Speter  ""
586318334Speter  "*
586418334Speter{
586518334Speter  unsigned int mask;
586618334Speter
586718334Speter  mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]);
586818334Speter  operands[1] = GEN_INT (mask);
586918334Speter
587052296Sobrien  if (QI_REG_P (operands[0])
587152296Sobrien      /* A Pentium test is pairable only with eax. Not with ah or al.  */
587252296Sobrien      && (! REG_P (operands[0]) || REGNO (operands[0]) || !TARGET_PENTIUM
587352296Sobrien          || optimize_size))
587418334Speter    {
587518334Speter      if ((mask & ~0xff) == 0)
587618334Speter        {
587718334Speter	  cc_status.flags |= CC_NOT_NEGATIVE;
587818334Speter	  return AS2 (test%B0,%1,%b0);
587918334Speter	}
588018334Speter
588118334Speter      if ((mask & ~0xff00) == 0)
588218334Speter        {
588318334Speter	  cc_status.flags |= CC_NOT_NEGATIVE;
588418334Speter	  operands[1] = GEN_INT (mask >> 8);
588518334Speter	  return AS2 (test%B0,%1,%h0);
588618334Speter	}
588718334Speter    }
588818334Speter
588918334Speter  return AS2 (test%L0,%1,%0);
589018334Speter}")
589118334Speter
589218334Speter;; ??? All bets are off if operand 0 is a volatile MEM reference.
589318334Speter;; The CPU may access unspecified bytes around the actual target byte.
589418334Speter
589518334Speter(define_insn ""
589650650Sobrien  [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m")
589718334Speter			    (match_operand:SI 1 "const_int_operand" "n")
589818334Speter			    (match_operand:SI 2 "const_int_operand" "n")))]
589918334Speter  "GET_CODE (operands[0]) != MEM || ! MEM_VOLATILE_P (operands[0])"
590018334Speter  "*
590118334Speter{
590218334Speter  unsigned int mask;
590318334Speter
590418334Speter  mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]);
590518334Speter  operands[1] = GEN_INT (mask);
590618334Speter
590752296Sobrien  if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
590852296Sobrien      /* A Pentium test is pairable only with eax. Not with ah or al.  */
590952296Sobrien      && (! REG_P (operands[0]) || REGNO (operands[0]) || !TARGET_PENTIUM
591052296Sobrien          || optimize_size))
591118334Speter    {
591218334Speter      if ((mask & ~0xff) == 0)
591318334Speter        {
591418334Speter	  cc_status.flags |= CC_NOT_NEGATIVE;
591518334Speter	  return AS2 (test%B0,%1,%b0);
591618334Speter	}
591718334Speter
591818334Speter      if ((mask & ~0xff00) == 0)
591918334Speter        {
592018334Speter	  cc_status.flags |= CC_NOT_NEGATIVE;
592118334Speter	  operands[1] = GEN_INT (mask >> 8);
592218334Speter
592318334Speter	  if (QI_REG_P (operands[0]))
592418334Speter	    return AS2 (test%B0,%1,%h0);
592518334Speter	  else
592618334Speter	    {
592718334Speter	      operands[0] = adj_offsettable_operand (operands[0], 1);
592818334Speter	      return AS2 (test%B0,%1,%b0);
592918334Speter	    }
593018334Speter	}
593118334Speter
593218334Speter      if (GET_CODE (operands[0]) == MEM && (mask & ~0xff0000) == 0)
593318334Speter        {
593418334Speter	  cc_status.flags |= CC_NOT_NEGATIVE;
593518334Speter	  operands[1] = GEN_INT (mask >> 16);
593618334Speter	  operands[0] = adj_offsettable_operand (operands[0], 2);
593718334Speter	  return AS2 (test%B0,%1,%b0);
593818334Speter	}
593918334Speter
594018334Speter      if (GET_CODE (operands[0]) == MEM && (mask & ~0xff000000) == 0)
594118334Speter        {
594218334Speter	  cc_status.flags |= CC_NOT_NEGATIVE;
594318334Speter	  operands[1] = GEN_INT (mask >> 24);
594418334Speter	  operands[0] = adj_offsettable_operand (operands[0], 3);
594518334Speter	  return AS2 (test%B0,%1,%b0);
594618334Speter	}
594718334Speter    }
594818334Speter
594918334Speter  if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM)
595018334Speter    return AS2 (test%L0,%1,%0);
595118334Speter
595218334Speter  return AS2 (test%L1,%0,%1);
595318334Speter}")
595418334Speter
595518334Speter;; Store-flag instructions.
595618334Speter
595718334Speter;; For all sCOND expanders, also expand the compare or test insn that
595818334Speter;; generates cc0.  Generate an equality comparison if `seq' or `sne'.
595918334Speter
596018334Speter(define_expand "seq"
596118334Speter  [(match_dup 1)
596218334Speter   (set (match_operand:QI 0 "register_operand" "")
596318334Speter	(eq:QI (cc0) (const_int 0)))]
596418334Speter  ""
596518334Speter  "
596618334Speter{
596718334Speter  if (TARGET_IEEE_FP
596818334Speter      && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
596918334Speter    operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
597018334Speter  else
597118334Speter    operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
597218334Speter}")
597318334Speter
597418334Speter(define_expand "sne"
597518334Speter  [(match_dup 1)
597618334Speter   (set (match_operand:QI 0 "register_operand" "")
597718334Speter	(ne:QI (cc0) (const_int 0)))]
597818334Speter  ""
597918334Speter  "
598018334Speter{
598118334Speter  if (TARGET_IEEE_FP
598218334Speter      && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
598318334Speter    operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
598418334Speter  else
598518334Speter    operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
598618334Speter}")
598718334Speter
598818334Speter(define_expand "sgt"
598918334Speter  [(match_dup 1)
599018334Speter   (set (match_operand:QI 0 "register_operand" "")
599118334Speter	(gt:QI (cc0) (const_int 0)))]
599218334Speter  ""
599318334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
599418334Speter
599518334Speter(define_expand "sgtu"
599618334Speter  [(match_dup 1)
599718334Speter   (set (match_operand:QI 0 "register_operand" "")
599818334Speter	(gtu:QI (cc0) (const_int 0)))]
599918334Speter  ""
600018334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
600118334Speter
600218334Speter(define_expand "slt"
600318334Speter  [(match_dup 1)
600418334Speter   (set (match_operand:QI 0 "register_operand" "")
600518334Speter	(lt:QI (cc0) (const_int 0)))]
600618334Speter  ""
600718334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
600818334Speter
600918334Speter(define_expand "sltu"
601018334Speter  [(match_dup 1)
601118334Speter   (set (match_operand:QI 0 "register_operand" "")
601218334Speter	(ltu:QI (cc0) (const_int 0)))]
601318334Speter  ""
601418334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
601518334Speter
601618334Speter(define_expand "sge"
601718334Speter  [(match_dup 1)
601818334Speter   (set (match_operand:QI 0 "register_operand" "")
601918334Speter	(ge:QI (cc0) (const_int 0)))]
602018334Speter  ""
602118334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
602218334Speter
602318334Speter(define_expand "sgeu"
602418334Speter  [(match_dup 1)
602518334Speter   (set (match_operand:QI 0 "register_operand" "")
602618334Speter	(geu:QI (cc0) (const_int 0)))]
602718334Speter  ""
602818334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
602918334Speter
603018334Speter(define_expand "sle"
603118334Speter  [(match_dup 1)
603218334Speter   (set (match_operand:QI 0 "register_operand" "")
603318334Speter	(le:QI (cc0) (const_int 0)))]
603418334Speter  ""
603518334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
603618334Speter
603718334Speter(define_expand "sleu"
603818334Speter  [(match_dup 1)
603918334Speter   (set (match_operand:QI 0 "register_operand" "")
604018334Speter	(leu:QI (cc0) (const_int 0)))]
604118334Speter  ""
604218334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
604318334Speter
604452296Sobrien;; The 386 sCOND opcodes can write to memory.  But a gcc sCOND insn may
604552296Sobrien;; not have any input reloads.  A MEM write might need an input reload
604652296Sobrien;; for the address of the MEM.  So don't allow MEM as the SET_DEST.
604752296Sobrien
604852296Sobrien(define_insn "*setcc"
604952296Sobrien  [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
605052296Sobrien	(match_operator:QI 1 "comparison_operator" [(cc0) (const_int 0)]))]
605152296Sobrien  "reload_completed || register_operand (operands[0], QImode)"
605252296Sobrien  "*
605352296Sobrien{
605452296Sobrien  enum rtx_code code = GET_CODE (operands[1]);
605552296Sobrien  if (cc_prev_status.flags & CC_TEST_AX)
605652296Sobrien    {
605752296Sobrien      int eq;
605852296Sobrien      HOST_WIDE_INT c;
605952296Sobrien      operands[2] = gen_rtx_REG (SImode, 0);
606052296Sobrien      switch (code)
606152296Sobrien	{
606252296Sobrien	case EQ:
606352296Sobrien	  c = 0x4000;
606452296Sobrien	  eq = 0;
606552296Sobrien	  break;
606652296Sobrien	case NE:
606752296Sobrien	  c = 0x4000;
606852296Sobrien	  eq = 1;
606952296Sobrien	  break;
607052296Sobrien	case GT:
607152296Sobrien	  c = 0x4100;
607252296Sobrien	  eq = 1;
607352296Sobrien	  break;
607452296Sobrien	case LT:
607552296Sobrien	  c = 0x100;
607652296Sobrien	  eq = 0;
607752296Sobrien	  break;
607852296Sobrien	case GE:
607952296Sobrien	  c = 0x100;
608052296Sobrien	  eq = 1;
608152296Sobrien	  break;
608252296Sobrien	case LE:
608352296Sobrien	  c = 0x4100;
608452296Sobrien	  eq = 0;
608552296Sobrien	  break;
608652296Sobrien	default:
608752296Sobrien	  abort ();
608852296Sobrien	}
608952296Sobrien      if (!TARGET_PENTIUM || optimize_size)
609052296Sobrien        {
609152296Sobrien          operands[3] = GEN_INT (c >> 8);
609252296Sobrien          output_asm_insn (AS2 (test%B0,%3,%h2), operands);
609352296Sobrien        }
609452296Sobrien      else
609552296Sobrien        {
609652296Sobrien          operands[3] = GEN_INT (c);
609752296Sobrien          output_asm_insn (AS2 (test%L0,%3,%2), operands);
609852296Sobrien        }
609952296Sobrien      return eq ? AS1 (sete,%0) : AS1 (setne, %0);
610052296Sobrien    }
610152296Sobrien
610252296Sobrien  if ((cc_status.flags & CC_NO_OVERFLOW) && (code == LE || code == GT))
610352296Sobrien    return (char *)0;
610452296Sobrien  return AS1(set%D1,%0);
610552296Sobrien}")
610652296Sobrien
610718334Speter
610818334Speter;; Basic conditional jump instructions.
610918334Speter;; We ignore the overflow flag for signed branch instructions.
611018334Speter
611118334Speter;; For all bCOND expanders, also expand the compare or test insn that
611218334Speter;; generates cc0.  Generate an equality comparison if `beq' or `bne'.
611318334Speter
611418334Speter(define_expand "beq"
611518334Speter  [(match_dup 1)
611618334Speter   (set (pc)
611718334Speter	(if_then_else (eq (cc0)
611818334Speter			  (const_int 0))
611918334Speter		      (label_ref (match_operand 0 "" ""))
612018334Speter		      (pc)))]
612118334Speter  ""
612218334Speter  "
612318334Speter{
612418334Speter  if (TARGET_IEEE_FP
612518334Speter      && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
612618334Speter    operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
612718334Speter  else
612818334Speter    operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
612918334Speter}")
613018334Speter
613118334Speter(define_expand "bne"
613218334Speter  [(match_dup 1)
613318334Speter   (set (pc)
613418334Speter	(if_then_else (ne (cc0)
613518334Speter			  (const_int 0))
613618334Speter		      (label_ref (match_operand 0 "" ""))
613718334Speter		      (pc)))]
613818334Speter  ""
613918334Speter  "
614018334Speter{
614118334Speter  if (TARGET_IEEE_FP
614218334Speter      && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT)
614318334Speter    operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1);
614418334Speter  else
614518334Speter    operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);
614618334Speter}")
614718334Speter
614850650Sobrien
614918334Speter(define_expand "bgt"
615018334Speter  [(match_dup 1)
615118334Speter   (set (pc)
615218334Speter	(if_then_else (gt (cc0)
615318334Speter			  (const_int 0))
615418334Speter		      (label_ref (match_operand 0 "" ""))
615518334Speter		      (pc)))]
615618334Speter  ""
615718334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
615818334Speter
615918334Speter(define_expand "bgtu"
616018334Speter  [(match_dup 1)
616118334Speter   (set (pc)
616218334Speter	(if_then_else (gtu (cc0)
616318334Speter			   (const_int 0))
616418334Speter		      (label_ref (match_operand 0 "" ""))
616518334Speter		      (pc)))]
616618334Speter  ""
616718334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
616818334Speter
616918334Speter(define_expand "blt"
617018334Speter  [(match_dup 1)
617118334Speter   (set (pc)
617218334Speter	(if_then_else (lt (cc0)
617318334Speter			  (const_int 0))
617418334Speter		      (label_ref (match_operand 0 "" ""))
617518334Speter		      (pc)))]
617618334Speter  ""
617718334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
617818334Speter
617918334Speter
618018334Speter(define_expand "bltu"
618118334Speter  [(match_dup 1)
618218334Speter   (set (pc)
618318334Speter	(if_then_else (ltu (cc0)
618418334Speter			   (const_int 0))
618518334Speter		      (label_ref (match_operand 0 "" ""))
618618334Speter		      (pc)))]
618718334Speter  ""
618818334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
618918334Speter
619018334Speter(define_expand "bge"
619118334Speter  [(match_dup 1)
619218334Speter   (set (pc)
619318334Speter	(if_then_else (ge (cc0)
619418334Speter			  (const_int 0))
619518334Speter		      (label_ref (match_operand 0 "" ""))
619618334Speter		      (pc)))]
619718334Speter  ""
619818334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
619918334Speter
620018334Speter(define_expand "bgeu"
620118334Speter  [(match_dup 1)
620218334Speter   (set (pc)
620318334Speter	(if_then_else (geu (cc0)
620418334Speter			   (const_int 0))
620518334Speter		      (label_ref (match_operand 0 "" ""))
620618334Speter		      (pc)))]
620718334Speter  ""
620818334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
620918334Speter
621018334Speter(define_expand "ble"
621118334Speter  [(match_dup 1)
621218334Speter   (set (pc)
621318334Speter	(if_then_else (le (cc0)
621418334Speter			  (const_int 0))
621518334Speter		      (label_ref (match_operand 0 "" ""))
621618334Speter		      (pc)))]
621718334Speter  ""
621818334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
621918334Speter
622018334Speter(define_expand "bleu"
622118334Speter  [(match_dup 1)
622218334Speter   (set (pc)
622318334Speter	(if_then_else (leu (cc0)
622418334Speter			   (const_int 0))
622518334Speter		      (label_ref (match_operand 0 "" ""))
622618334Speter		      (pc)))]
622718334Speter  ""
622818334Speter  "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);")
622918334Speter
623018334Speter(define_insn ""
623118334Speter  [(set (pc)
623252296Sobrien	(if_then_else (match_operator 0 "comparison_operator"
623352296Sobrien				      [(cc0) (const_int 0)])
623452296Sobrien		      (label_ref (match_operand 1 "" ""))
623518334Speter		      (pc)))]
623618334Speter  ""
623718334Speter  "*
623818334Speter{
623952296Sobrien  enum rtx_code code = GET_CODE (operands[0]);
624050650Sobrien  if (cc_prev_status.flags & CC_TEST_AX)
624150650Sobrien    {
624252296Sobrien      int eq;
624352296Sobrien      HOST_WIDE_INT c;
624452296Sobrien      operands[2] = gen_rtx_REG (SImode, 0);
624552296Sobrien      switch (code)
624652296Sobrien	{
624752296Sobrien	case EQ:
624852296Sobrien	  c = 0x4000;
624952296Sobrien	  eq = 0;
625052296Sobrien	  break;
625152296Sobrien	case NE:
625252296Sobrien	  c = 0x4000;
625352296Sobrien	  eq = 1;
625452296Sobrien	  break;
625552296Sobrien	case GT:
625652296Sobrien	  c = 0x4100;
625752296Sobrien	  eq = 1;
625852296Sobrien	  break;
625952296Sobrien	case LT:
626052296Sobrien	  c = 0x100;
626152296Sobrien	  eq = 0;
626252296Sobrien	  break;
626352296Sobrien	case GE:
626452296Sobrien	  c = 0x100;
626552296Sobrien	  eq = 1;
626652296Sobrien	  break;
626752296Sobrien	case LE:
626852296Sobrien	  c = 0x4100;
626952296Sobrien	  eq = 0;
627052296Sobrien	  break;
627152296Sobrien	default:
627252296Sobrien	  abort ();
627352296Sobrien	}
627452296Sobrien      if (!TARGET_PENTIUM || optimize_size)
627552296Sobrien        {
627652296Sobrien          operands[3] = GEN_INT (c >> 8);
627752296Sobrien          output_asm_insn (AS2 (test%B0,%3,%h2), operands);
627852296Sobrien        }
627952296Sobrien      else
628052296Sobrien        {
628152296Sobrien          operands[3] = GEN_INT (c);
628252296Sobrien          output_asm_insn (AS2 (test%L0,%3,%2), operands);
628352296Sobrien        }
628452296Sobrien      return eq ? AS1 (je,%l1) : AS1 (jne, %l1);
628550650Sobrien    }
628652296Sobrien  if ((cc_status.flags & CC_NO_OVERFLOW) && (code == LE || code == GT))
628752296Sobrien    return (char *)0;
628818334Speter
628952296Sobrien  return AS1(j%D0,%l1);
629018334Speter}")
629118334Speter
629218334Speter(define_insn ""
629318334Speter  [(set (pc)
629452296Sobrien	(if_then_else (match_operator 0 "comparison_operator"
629552296Sobrien				      [(cc0) (const_int 0)])
629618334Speter		      (pc)
629752296Sobrien		      (label_ref (match_operand 1 "" ""))))]
629818334Speter  ""
629918334Speter  "*
630018334Speter{
630152296Sobrien  enum rtx_code code = GET_CODE (operands[0]);
630250650Sobrien  if (cc_prev_status.flags & CC_TEST_AX)
630350650Sobrien    {
630452296Sobrien      int eq;
630552296Sobrien      HOST_WIDE_INT c;
630652296Sobrien      operands[2] = gen_rtx_REG (SImode, 0);
630752296Sobrien      switch (code)
630852296Sobrien	{
630952296Sobrien	case EQ:
631052296Sobrien	  c = 0x4000;
631152296Sobrien	  eq = 1;
631252296Sobrien	  break;
631352296Sobrien	case NE:
631452296Sobrien	  c = 0x4000;
631552296Sobrien	  eq = 0;
631652296Sobrien	  break;
631752296Sobrien	case GT:
631852296Sobrien	  c = 0x4100;
631952296Sobrien	  eq = 0;
632052296Sobrien	  break;
632152296Sobrien	case LT:
632252296Sobrien	  c = 0x100;
632352296Sobrien	  eq = 1;
632452296Sobrien	  break;
632552296Sobrien	case GE:
632652296Sobrien	  c = 0x100;
632752296Sobrien	  eq = 0;
632852296Sobrien	  break;
632952296Sobrien	case LE:
633052296Sobrien	  c = 0x4100;
633152296Sobrien	  eq = 1;
633252296Sobrien	  break;
633352296Sobrien	default:
633452296Sobrien	  abort ();
633552296Sobrien	}
633652296Sobrien      if (!TARGET_PENTIUM || optimize_size)
633752296Sobrien        {
633852296Sobrien          operands[3] = GEN_INT (c >> 8);
633952296Sobrien          output_asm_insn (AS2 (test%B0,%3,%h2), operands);
634052296Sobrien        }
634152296Sobrien      else
634252296Sobrien        {
634352296Sobrien          operands[3] = GEN_INT (c);
634452296Sobrien          output_asm_insn (AS2 (test%L0,%3,%2), operands);
634552296Sobrien        }
634652296Sobrien      return eq ? AS1 (je,%l1) : AS1 (jne, %l1);
634750650Sobrien    }
634852296Sobrien  if ((cc_status.flags & CC_NO_OVERFLOW) && (code == LE || code == GT))
634952296Sobrien    return (char *)0;
635018334Speter
635152296Sobrien  return AS1(j%d0,%l1);
635218334Speter}")
635318334Speter
635418334Speter;; Unconditional and other jump instructions
635518334Speter
635618334Speter(define_insn "jump"
635718334Speter  [(set (pc)
635818334Speter	(label_ref (match_operand 0 "" "")))]
635918334Speter  ""
636052296Sobrien  "jmp %l0"
636152296Sobrien  [(set_attr "memory" "none")])
636218334Speter
636318334Speter(define_insn "indirect_jump"
636450650Sobrien  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
636518334Speter  ""
636618334Speter  "*
636718334Speter{
636818334Speter  CC_STATUS_INIT;
636918334Speter
637018334Speter  return AS1 (jmp,%*%0);
637152296Sobrien}"
637252296Sobrien  [(set_attr "memory" "none")])
637318334Speter
637418334Speter;; ??? could transform while(--i > 0) S; to if (--i > 0) do S; while(--i);
637518334Speter;;     if S does not change i
637618334Speter
637718334Speter(define_expand "decrement_and_branch_until_zero"
637818334Speter  [(parallel [(set (pc)
637918334Speter		   (if_then_else (ge (plus:SI (match_operand:SI 0 "general_operand" "")
638018334Speter					      (const_int -1))
638118334Speter				     (const_int 0))
638218334Speter				 (label_ref (match_operand 1 "" ""))
638318334Speter				 (pc)))
638418334Speter	      (set (match_dup 0)
638518334Speter		   (plus:SI (match_dup 0)
638618334Speter			    (const_int -1)))])]
638718334Speter  ""
638818334Speter  "")
638918334Speter
639018334Speter(define_insn ""
639118334Speter  [(set (pc)
639218334Speter	(if_then_else (match_operator 0 "arithmetic_comparison_operator"
639352296Sobrien				      [(plus:SI (match_operand:SI 1 "nonimmediate_operand" "+c*r,m")
639418334Speter						(match_operand:SI 2 "general_operand" "rmi,ri"))
639518334Speter				       (const_int 0)])
639618334Speter		      (label_ref (match_operand 3 "" ""))
639718334Speter		      (pc)))
639818334Speter   (set (match_dup 1)
639918334Speter	(plus:SI (match_dup 1)
640018334Speter		 (match_dup 2)))]
640118334Speter  ""
640218334Speter  "*
640318334Speter{
640418334Speter  CC_STATUS_INIT;
640552296Sobrien
640652296Sobrien  if (GET_CODE (operands[1]) == REG && REGNO (operands[2]) == 2 &&
640752296Sobrien      operands[2] == constm1_rtx && ix86_cpu == PROCESSOR_K6)
640852296Sobrien    return \"loop %l3\";
640952296Sobrien
641018334Speter  if (operands[2] == constm1_rtx)
641118334Speter    output_asm_insn (AS1 (dec%L1,%1), operands);
641218334Speter
641350650Sobrien  else if (operands[2] == const1_rtx)
641418334Speter    output_asm_insn (AS1 (inc%L1,%1), operands);
641518334Speter
641618334Speter  else
641718334Speter    output_asm_insn (AS2 (add%L1,%2,%1), operands);
641818334Speter
641918334Speter  return AS1 (%J0,%l3);
642018334Speter}")
642118334Speter
642218334Speter(define_insn ""
642318334Speter  [(set (pc)
642418334Speter	(if_then_else (match_operator 0 "arithmetic_comparison_operator"
642550650Sobrien				      [(minus:SI (match_operand:SI 1 "nonimmediate_operand" "+r,m")
642618334Speter						 (match_operand:SI 2 "general_operand" "rmi,ri"))
642718334Speter				       (const_int 0)])
642818334Speter		      (label_ref (match_operand 3 "" ""))
642918334Speter		      (pc)))
643018334Speter   (set (match_dup 1)
643118334Speter	(minus:SI (match_dup 1)
643218334Speter		  (match_dup 2)))]
643318334Speter  ""
643418334Speter  "*
643518334Speter{
643618334Speter  CC_STATUS_INIT;
643718334Speter  if (operands[2] == const1_rtx)
643818334Speter    output_asm_insn (AS1 (dec%L1,%1), operands);
643918334Speter
644018334Speter  else if (operands[1] == constm1_rtx)
644118334Speter    output_asm_insn (AS1 (inc%L1,%1), operands);
644218334Speter
644318334Speter  else
644418334Speter    output_asm_insn (AS2 (sub%L1,%2,%1), operands);
644518334Speter
644618334Speter  return AS1 (%J0,%l3);
644718334Speter}")
644818334Speter
644950650Sobrien(define_insn ""
645050650Sobrien  [(set (pc)
645150650Sobrien	(if_then_else (ne (match_operand:SI 0 "general_operand" "+g")
645250650Sobrien			  (const_int 0))
645350650Sobrien		      (label_ref (match_operand 1 "" ""))
645450650Sobrien		      (pc)))
645550650Sobrien   (set (match_dup 0)
645650650Sobrien	(plus:SI (match_dup 0)
645750650Sobrien		 (const_int -1)))]
645850650Sobrien  ""
645950650Sobrien  "*
646050650Sobrien{
646150650Sobrien  CC_STATUS_INIT;
646250650Sobrien  operands[2] = const1_rtx;
646350650Sobrien  output_asm_insn (AS2 (sub%L0,%2,%0), operands);
646450650Sobrien  return \"jnc %l1\";
646550650Sobrien}")
646650650Sobrien
646750650Sobrien(define_insn ""
646850650Sobrien  [(set (pc)
646950650Sobrien	(if_then_else (eq (match_operand:SI 0 "general_operand" "+g")
647050650Sobrien			  (const_int 0))
647150650Sobrien		      (label_ref (match_operand 1 "" ""))
647250650Sobrien		      (pc)))
647350650Sobrien   (set (match_dup 0)
647450650Sobrien	(plus:SI (match_dup 0)
647550650Sobrien		 (const_int -1)))]
647650650Sobrien  ""
647750650Sobrien  "*
647850650Sobrien{
647950650Sobrien  CC_STATUS_INIT;
648050650Sobrien  operands[2] = const1_rtx;
648150650Sobrien  output_asm_insn (AS2 (sub%L0,%2,%0), operands);
648250650Sobrien  return \"jc %l1\";
648350650Sobrien}")
648450650Sobrien
648550650Sobrien(define_insn ""
648650650Sobrien  [(set (pc)
648750650Sobrien	(if_then_else (ne (match_operand:SI 0 "general_operand" "+g")
648850650Sobrien			  (const_int 1))
648950650Sobrien		      (label_ref (match_operand 1 "" ""))
649050650Sobrien		      (pc)))
649150650Sobrien   (set (match_dup 0)
649250650Sobrien	(plus:SI (match_dup 0)
649350650Sobrien		 (const_int -1)))]
649450650Sobrien  ""
649550650Sobrien  "*
649650650Sobrien{
649750650Sobrien  CC_STATUS_INIT;
649850650Sobrien  output_asm_insn (AS1 (dec%L0,%0), operands);
649950650Sobrien  return \"jnz %l1\";
650050650Sobrien}")
650150650Sobrien
650250650Sobrien(define_insn ""
650350650Sobrien  [(set (pc)
650450650Sobrien	(if_then_else (eq (match_operand:SI 0 "general_operand" "+g")
650550650Sobrien			  (const_int 1))
650650650Sobrien		      (label_ref (match_operand 1 "" ""))
650750650Sobrien		      (pc)))
650850650Sobrien   (set (match_dup 0)
650950650Sobrien	(plus:SI (match_dup 0)
651050650Sobrien		 (const_int -1)))]
651150650Sobrien  ""
651250650Sobrien  "*
651350650Sobrien{
651450650Sobrien  CC_STATUS_INIT;
651550650Sobrien  output_asm_insn (AS1 (dec%L0,%0), operands);
651650650Sobrien  return \"jz %l1\";
651750650Sobrien}")
651850650Sobrien
651950650Sobrien(define_insn ""
652050650Sobrien  [(set (pc)
652150650Sobrien	(if_then_else (ne (match_operand:SI 0 "general_operand" "+g")
652250650Sobrien			  (const_int -1))
652350650Sobrien		      (label_ref (match_operand 1 "" ""))
652450650Sobrien		      (pc)))
652550650Sobrien   (set (match_dup 0)
652650650Sobrien	(plus:SI (match_dup 0)
652750650Sobrien		 (const_int 1)))]
652850650Sobrien  ""
652950650Sobrien  "*
653050650Sobrien{
653150650Sobrien  CC_STATUS_INIT;
653250650Sobrien  output_asm_insn (AS1 (inc%L0,%0), operands);
653350650Sobrien  return \"jnz %l1\";
653450650Sobrien}")
653550650Sobrien
653650650Sobrien(define_insn ""
653750650Sobrien  [(set (pc)
653850650Sobrien	(if_then_else (eq (match_operand:SI 0 "general_operand" "+g")
653950650Sobrien			  (const_int -1))
654050650Sobrien		      (label_ref (match_operand 1 "" ""))
654150650Sobrien		      (pc)))
654250650Sobrien   (set (match_dup 0)
654350650Sobrien	(plus:SI (match_dup 0)
654450650Sobrien		 (const_int 1)))]
654550650Sobrien  ""
654650650Sobrien  "*
654750650Sobrien{
654850650Sobrien  CC_STATUS_INIT;
654950650Sobrien  output_asm_insn (AS1 (inc%L0,%0), operands);
655050650Sobrien  return \"jz %l1\";
655150650Sobrien}")
655250650Sobrien
655318334Speter;; Implement switch statements when generating PIC code.  Switches are
655418334Speter;; implemented by `tablejump' when not using -fpic.
655518334Speter
655618334Speter;; Emit code here to do the range checking and make the index zero based.
655718334Speter
655818334Speter(define_expand "casesi"
655918334Speter  [(set (match_dup 5)
656050650Sobrien	(match_operand:SI 0 "general_operand" ""))
656150650Sobrien   (set (match_dup 6)
656250650Sobrien	(minus:SI (match_dup 5)
656318334Speter		  (match_operand:SI 1 "general_operand" "")))
656418334Speter   (set (cc0)
656550650Sobrien	(compare:CC (match_dup 6)
656618334Speter		    (match_operand:SI 2 "general_operand" "")))
656718334Speter   (set (pc)
656818334Speter	(if_then_else (gtu (cc0)
656918334Speter			   (const_int 0))
657018334Speter		      (label_ref (match_operand 4 "" ""))
657118334Speter		      (pc)))
657218334Speter   (parallel
657318334Speter    [(set (pc)
657418334Speter	  (minus:SI (reg:SI 3)
657550650Sobrien		    (mem:SI (plus:SI (mult:SI (match_dup 6)
657618334Speter					      (const_int 4))
657718334Speter				     (label_ref (match_operand 3 "" ""))))))
657850650Sobrien     (clobber (match_scratch:SI 7 ""))])]
657918334Speter  "flag_pic"
658018334Speter  "
658118334Speter{
658218334Speter  operands[5] = gen_reg_rtx (SImode);
658350650Sobrien  operands[6] = gen_reg_rtx (SImode);
658418334Speter  current_function_uses_pic_offset_table = 1;
658518334Speter}")
658618334Speter
658718334Speter;; Implement a casesi insn.
658818334Speter
658918334Speter;; Each entry in the "addr_diff_vec" looks like this as the result of the
659018334Speter;; two rules below:
659118334Speter;; 
659218334Speter;; 	.long _GLOBAL_OFFSET_TABLE_+[.-.L2]
659318334Speter;; 
659418334Speter;; 1. An expression involving an external reference may only use the
659518334Speter;;    addition operator, and only with an assembly-time constant.
659618334Speter;;    The example above satisfies this because ".-.L2" is a constant.
659718334Speter;; 
659818334Speter;; 2. The symbol _GLOBAL_OFFSET_TABLE_ is magic, and at link time is
659918334Speter;;    given the value of "GOT - .", where GOT is the actual address of
660018334Speter;;    the Global Offset Table.  Therefore, the .long above actually
660118334Speter;;    stores the value "( GOT - . ) + [ . - .L2 ]", or "GOT - .L2".  The
660218334Speter;;    expression "GOT - .L2" by itself would generate an error from as(1).
660318334Speter;; 
660418334Speter;; The pattern below emits code that looks like this:
660518334Speter;; 
660618334Speter;; 	movl %ebx,reg
660718334Speter;; 	subl TABLE@GOTOFF(%ebx,index,4),reg
660818334Speter;; 	jmp reg
660918334Speter;; 
661018334Speter;; The addr_diff_vec contents may be directly referenced with @GOTOFF, since
661118334Speter;; the addr_diff_vec is known to be part of this module.
661218334Speter;; 
661318334Speter;; The subl above calculates "GOT - (( GOT - . ) + [ . - .L2 ])", which
661418334Speter;; evaluates to just ".L2".
661518334Speter
661618334Speter(define_insn ""
661718334Speter  [(set (pc)
661818334Speter	(minus:SI (reg:SI 3)
661918334Speter		  (mem:SI (plus:SI
662018334Speter			   (mult:SI (match_operand:SI 0 "register_operand" "r")
662118334Speter				    (const_int 4))
662218334Speter			   (label_ref (match_operand 1 "" ""))))))
662318334Speter   (clobber (match_scratch:SI 2 "=&r"))]
662418334Speter  ""
662518334Speter  "*
662618334Speter{
662718334Speter  rtx xops[4];
662818334Speter
662918334Speter  xops[0] = operands[0];
663018334Speter  xops[1] = operands[1];
663118334Speter  xops[2] = operands[2];
663218334Speter  xops[3] = pic_offset_table_rtx;
663318334Speter
663418334Speter  output_asm_insn (AS2 (mov%L2,%3,%2), xops);
663518334Speter  output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops);
663618334Speter  output_asm_insn (AS1 (jmp,%*%2), xops);
663750650Sobrien  ASM_OUTPUT_ALIGN (asm_out_file, i386_align_jumps);
663818334Speter  RET;
663918334Speter}")
664018334Speter
664118334Speter(define_insn "tablejump"
664250650Sobrien  [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))
664318334Speter   (use (label_ref (match_operand 1 "" "")))]
664418334Speter  ""
664518334Speter  "*
664618334Speter{
664718334Speter  CC_STATUS_INIT;
664818334Speter
664918334Speter  return AS1 (jmp,%*%0);
665018334Speter}")
665118334Speter
665218334Speter;; Call insns.
665318334Speter
665418334Speter;; If generating PIC code, the predicate indirect_operand will fail
665518334Speter;; for operands[0] containing symbolic references on all of the named
665618334Speter;; call* patterns.  Each named pattern is followed by an unnamed pattern
665718334Speter;; that matches any call to a symbolic CONST (ie, a symbol_ref).  The
665818334Speter;; unnamed patterns are only used while generating PIC code, because
665918334Speter;; otherwise the named patterns match.
666018334Speter
666118334Speter;; Call subroutine returning no value.
666218334Speter
666318334Speter(define_expand "call_pop"
666418334Speter  [(parallel [(call (match_operand:QI 0 "indirect_operand" "")
666518334Speter		    (match_operand:SI 1 "general_operand" ""))
666618334Speter	      (set (reg:SI 7)
666718334Speter		   (plus:SI (reg:SI 7)
666818334Speter			    (match_operand:SI 3 "immediate_operand" "")))])]
666918334Speter  ""
667018334Speter  "
667118334Speter{
667218334Speter  rtx addr;
667318334Speter
667452296Sobrien  if (operands[3] == const0_rtx)
667552296Sobrien    {
667652296Sobrien      emit_insn (gen_call (operands[0], operands[1]));
667752296Sobrien      DONE;
667852296Sobrien    }
667952296Sobrien
668018334Speter  if (flag_pic)
668118334Speter    current_function_uses_pic_offset_table = 1;
668218334Speter
668318334Speter  /* With half-pic, force the address into a register.  */
668418334Speter  addr = XEXP (operands[0], 0);
668518334Speter  if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
668618334Speter    XEXP (operands[0], 0) = force_reg (Pmode, addr);
668718334Speter
668818334Speter  if (! expander_call_insn_operand (operands[0], QImode))
668918334Speter    operands[0]
669018334Speter      = change_address (operands[0], VOIDmode,
669118334Speter			copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
669218334Speter}")
669318334Speter
669418334Speter(define_insn ""
669518334Speter  [(call (match_operand:QI 0 "call_insn_operand" "m")
669618334Speter	 (match_operand:SI 1 "general_operand" "g"))
669718334Speter   (set (reg:SI 7) (plus:SI (reg:SI 7)
669818334Speter			    (match_operand:SI 3 "immediate_operand" "i")))]
669918334Speter  ""
670018334Speter  "*
670118334Speter{
670218334Speter  if (GET_CODE (operands[0]) == MEM
670318334Speter      && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
670418334Speter    {
670518334Speter      operands[0] = XEXP (operands[0], 0);
670618334Speter      return AS1 (call,%*%0);
670718334Speter    }
670818334Speter  else
670918334Speter    return AS1 (call,%P0);
671018334Speter}")
671118334Speter
671218334Speter(define_insn ""
671318334Speter  [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
671418334Speter	 (match_operand:SI 1 "general_operand" "g"))
671518334Speter   (set (reg:SI 7) (plus:SI (reg:SI 7)
671618334Speter			    (match_operand:SI 3 "immediate_operand" "i")))]
671718334Speter  "!HALF_PIC_P ()"
671818334Speter  "call %P0")
671918334Speter
672018334Speter(define_expand "call"
672118334Speter  [(call (match_operand:QI 0 "indirect_operand" "")
672218334Speter	 (match_operand:SI 1 "general_operand" ""))]
672318334Speter  ;; Operand 1 not used on the i386.
672418334Speter  ""
672518334Speter  "
672618334Speter{
672718334Speter  rtx addr;
672818334Speter
672918334Speter  if (flag_pic)
673018334Speter    current_function_uses_pic_offset_table = 1;
673118334Speter
673218334Speter  /* With half-pic, force the address into a register.  */
673318334Speter  addr = XEXP (operands[0], 0);
673418334Speter  if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
673518334Speter    XEXP (operands[0], 0) = force_reg (Pmode, addr);
673618334Speter
673718334Speter  if (! expander_call_insn_operand (operands[0], QImode))
673818334Speter    operands[0]
673918334Speter      = change_address (operands[0], VOIDmode,
674018334Speter			copy_to_mode_reg (Pmode, XEXP (operands[0], 0)));
674118334Speter}")
674218334Speter
674318334Speter(define_insn ""
674418334Speter  [(call (match_operand:QI 0 "call_insn_operand" "m")
674518334Speter	 (match_operand:SI 1 "general_operand" "g"))]
674618334Speter  ;; Operand 1 not used on the i386.
674718334Speter  ""
674818334Speter  "*
674918334Speter{
675018334Speter  if (GET_CODE (operands[0]) == MEM
675118334Speter      && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0)))
675218334Speter    {
675318334Speter      operands[0] = XEXP (operands[0], 0);
675418334Speter      return AS1 (call,%*%0);
675518334Speter    }
675618334Speter  else
675718334Speter    return AS1 (call,%P0);
675818334Speter}")
675918334Speter
676018334Speter(define_insn ""
676118334Speter  [(call (mem:QI (match_operand:SI 0 "symbolic_operand" ""))
676218334Speter	 (match_operand:SI 1 "general_operand" "g"))]
676318334Speter  ;; Operand 1 not used on the i386.
676418334Speter  "!HALF_PIC_P ()"
676518334Speter  "call %P0")
676618334Speter
676718334Speter;; Call subroutine, returning value in operand 0
676818334Speter;; (which must be a hard register).
676918334Speter
677018334Speter(define_expand "call_value_pop"
677118334Speter  [(parallel [(set (match_operand 0 "" "")
677218334Speter		   (call (match_operand:QI 1 "indirect_operand" "")
677318334Speter			 (match_operand:SI 2 "general_operand" "")))
677418334Speter	      (set (reg:SI 7)
677518334Speter		   (plus:SI (reg:SI 7)
677618334Speter			    (match_operand:SI 4 "immediate_operand" "")))])]
677718334Speter  ""
677818334Speter  "
677918334Speter{
678018334Speter  rtx addr;
678118334Speter
678252296Sobrien  if (operands[4] == const0_rtx)
678352296Sobrien    {
678452296Sobrien      emit_insn (gen_call_value (operands[0], operands[1], operands[2]));
678552296Sobrien      DONE;
678652296Sobrien    }
678752296Sobrien
678818334Speter  if (flag_pic)
678918334Speter    current_function_uses_pic_offset_table = 1;
679018334Speter
679118334Speter  /* With half-pic, force the address into a register.  */
679218334Speter  addr = XEXP (operands[1], 0);
679318334Speter  if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
679418334Speter    XEXP (operands[1], 0) = force_reg (Pmode, addr);
679518334Speter
679618334Speter  if (! expander_call_insn_operand (operands[1], QImode))
679718334Speter    operands[1]
679818334Speter      = change_address (operands[1], VOIDmode,
679918334Speter			copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
680018334Speter}")
680118334Speter
680218334Speter(define_insn ""
680318334Speter  [(set (match_operand 0 "" "=rf")
680418334Speter	(call (match_operand:QI 1 "call_insn_operand" "m")
680518334Speter	      (match_operand:SI 2 "general_operand" "g")))
680618334Speter   (set (reg:SI 7) (plus:SI (reg:SI 7)
680718334Speter			    (match_operand:SI 4 "immediate_operand" "i")))]
680818334Speter  ""
680918334Speter  "*
681018334Speter{
681118334Speter  if (GET_CODE (operands[1]) == MEM
681218334Speter      && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
681318334Speter    {
681418334Speter      operands[1] = XEXP (operands[1], 0);
681518334Speter      output_asm_insn (AS1 (call,%*%1), operands);
681618334Speter    }
681718334Speter  else
681818334Speter    output_asm_insn (AS1 (call,%P1), operands);
681918334Speter
682018334Speter  RET;
682118334Speter}")
682218334Speter
682318334Speter(define_insn ""
682418334Speter  [(set (match_operand 0 "" "=rf")
682518334Speter	(call (mem:QI (match_operand:SI 1 "symbolic_operand" ""))
682618334Speter	      (match_operand:SI 2 "general_operand" "g")))
682718334Speter   (set (reg:SI 7) (plus:SI (reg:SI 7)
682818334Speter			    (match_operand:SI 4 "immediate_operand" "i")))]
682918334Speter  "!HALF_PIC_P ()"
683018334Speter  "call %P1")
683118334Speter
683218334Speter(define_expand "call_value"
683318334Speter  [(set (match_operand 0 "" "")
683418334Speter	(call (match_operand:QI 1 "indirect_operand" "")
683518334Speter	      (match_operand:SI 2 "general_operand" "")))]
683618334Speter  ;; Operand 2 not used on the i386.
683718334Speter  ""
683818334Speter  "
683918334Speter{
684018334Speter  rtx addr;
684118334Speter
684218334Speter  if (flag_pic)
684318334Speter    current_function_uses_pic_offset_table = 1;
684418334Speter
684518334Speter  /* With half-pic, force the address into a register.  */
684618334Speter  addr = XEXP (operands[1], 0);
684718334Speter  if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr))
684818334Speter    XEXP (operands[1], 0) = force_reg (Pmode, addr);
684918334Speter
685018334Speter  if (! expander_call_insn_operand (operands[1], QImode))
685118334Speter    operands[1]
685218334Speter      = change_address (operands[1], VOIDmode,
685318334Speter			copy_to_mode_reg (Pmode, XEXP (operands[1], 0)));
685418334Speter}")
685518334Speter
685618334Speter(define_insn ""
685718334Speter  [(set (match_operand 0 "" "=rf")
685818334Speter	(call (match_operand:QI 1 "call_insn_operand" "m")
685918334Speter	      (match_operand:SI 2 "general_operand" "g")))]
686018334Speter  ;; Operand 2 not used on the i386.
686118334Speter  ""
686218334Speter  "*
686318334Speter{
686418334Speter  if (GET_CODE (operands[1]) == MEM
686518334Speter      && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0)))
686618334Speter    {
686718334Speter      operands[1] = XEXP (operands[1], 0);
686818334Speter      output_asm_insn (AS1 (call,%*%1), operands);
686918334Speter    }
687018334Speter  else
687118334Speter    output_asm_insn (AS1 (call,%P1), operands);
687218334Speter
687318334Speter  RET;
687418334Speter}")
687518334Speter
687618334Speter(define_insn ""
687718334Speter  [(set (match_operand 0 "" "=rf")
687818334Speter	(call (mem:QI (match_operand:SI 1 "symbolic_operand" ""))
687918334Speter	      (match_operand:SI 2 "general_operand" "g")))]
688018334Speter  ;; Operand 2 not used on the i386.
688118334Speter  "!HALF_PIC_P ()"
688218334Speter  "call %P1")
688318334Speter
688418334Speter;; Call subroutine returning any type.
688518334Speter
688618334Speter(define_expand "untyped_call"
688718334Speter  [(parallel [(call (match_operand 0 "" "")
688818334Speter		    (const_int 0))
688918334Speter	      (match_operand 1 "" "")
689018334Speter	      (match_operand 2 "" "")])]
689118334Speter  ""
689218334Speter  "
689318334Speter{
689418334Speter  int i;
689518334Speter
689618334Speter  /* In order to give reg-stack an easier job in validating two
689718334Speter     coprocessor registers as containing a possible return value,
689818334Speter     simply pretend the untyped call returns a complex long double
689918334Speter     value.  */
690050650Sobrien
690118334Speter  emit_call_insn (TARGET_80387
690250650Sobrien                  ? gen_call_value (gen_rtx_REG (XCmode, FIRST_FLOAT_REG),
690350650Sobrien				    operands[0], const0_rtx)
690418334Speter                  : gen_call (operands[0], const0_rtx));
690518334Speter
690618334Speter  for (i = 0; i < XVECLEN (operands[2], 0); i++)
690718334Speter    {
690818334Speter      rtx set = XVECEXP (operands[2], 0, i);
690918334Speter      emit_move_insn (SET_DEST (set), SET_SRC (set));
691018334Speter    }
691118334Speter
691218334Speter  /* The optimizer does not know that the call sets the function value
691318334Speter     registers we stored in the result block.  We avoid problems by
691418334Speter     claiming that all hard registers are used and clobbered at this
691518334Speter     point.  */
691618334Speter  emit_insn (gen_blockage ());
691718334Speter
691818334Speter  DONE;
691918334Speter}")
692018334Speter
692118334Speter;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and
692218334Speter;; all of memory.  This blocks insns from being moved across this point.
692318334Speter
692418334Speter(define_insn "blockage"
692518334Speter  [(unspec_volatile [(const_int 0)] 0)]
692618334Speter  ""
692752296Sobrien  ""
692852296Sobrien  [(set_attr "memory" "none")])
692918334Speter
693018334Speter;; Insn emitted into the body of a function to return from a function.
693118334Speter;; This is only done if the function's epilogue is known to be simple.
693218334Speter;; See comments for simple_386_epilogue in i386.c.
693318334Speter
693450650Sobrien(define_expand "return"
693518334Speter  [(return)]
693650650Sobrien  "ix86_can_use_return_insn_p ()"
693750650Sobrien  "")
693850650Sobrien
693950650Sobrien(define_insn "return_internal"
694050650Sobrien  [(return)]
694150650Sobrien  "reload_completed"
694252296Sobrien  "ret"
694352296Sobrien  [(set_attr "memory" "none")])
694450650Sobrien
694550650Sobrien(define_insn "return_pop_internal"
694650650Sobrien  [(return)
694750650Sobrien   (use (match_operand:SI 0 "const_int_operand" ""))]
694850650Sobrien  "reload_completed"
694952296Sobrien  "ret %0"
695052296Sobrien  [(set_attr "memory" "none")])
695150650Sobrien
695250650Sobrien(define_insn "nop"
695350650Sobrien  [(const_int 0)]
695450650Sobrien  ""
695552296Sobrien  "nop"
695652296Sobrien  [(set_attr "memory" "none")])
695750650Sobrien
695850650Sobrien(define_expand "prologue"
695950650Sobrien  [(const_int 1)]
696050650Sobrien  ""
696150650Sobrien  "
696250650Sobrien{
696350650Sobrien  ix86_expand_prologue ();
696450650Sobrien  DONE;
696550650Sobrien}")
696650650Sobrien
696750650Sobrien;; The use of UNSPEC here is currently not necessary - a simple SET of ebp
696850650Sobrien;; to itself would be enough. But this way we are safe even if some optimizer
696950650Sobrien;; becomes too clever in the future.
697050650Sobrien(define_insn "prologue_set_stack_ptr"
697150650Sobrien  [(set (reg:SI 7)
697250650Sobrien	(minus:SI (reg:SI 7) (match_operand:SI 0 "immediate_operand" "i")))
697350650Sobrien   (set (reg:SI 6) (unspec:SI [(reg:SI 6)] 4))]
697450650Sobrien  ""
697518334Speter  "*
697618334Speter{
697750650Sobrien  rtx xops [2];
697850650Sobrien
697950650Sobrien  xops[0] = operands[0];
698050650Sobrien  xops[1] = stack_pointer_rtx;
698150650Sobrien  output_asm_insn (AS2 (sub%L1,%0,%1), xops);
698218334Speter  RET;
698352296Sobrien}"
698452296Sobrien  [(set_attr "memory" "none")])
698518334Speter
698650650Sobrien(define_insn "prologue_set_got"
698750650Sobrien  [(set (match_operand:SI 0 "" "")
698850650Sobrien	(unspec_volatile
698950650Sobrien	 [(plus:SI (match_dup 0)
699050650Sobrien		   (plus:SI (match_operand:SI 1 "symbolic_operand" "")
699150650Sobrien			    (minus:SI (pc) (match_operand 2 "" ""))))] 1))]
699218334Speter  ""
699350650Sobrien  "*
699450650Sobrien{
699550650Sobrien  char buffer[64];
699618334Speter
699750650Sobrien  if (TARGET_DEEP_BRANCH_PREDICTION) 
699850650Sobrien    {
699950650Sobrien      sprintf (buffer, \"addl %s,%%0\", XSTR (operands[1], 0));
700050650Sobrien      output_asm_insn (buffer, operands);
700150650Sobrien    }
700250650Sobrien  else  
700350650Sobrien    {
700450650Sobrien      sprintf (buffer, \"addl %s+[.-%%X2],%%0\", XSTR (operands[1], 0));
700550650Sobrien      output_asm_insn (buffer, operands);
700650650Sobrien    }    
700750650Sobrien  RET;
700850650Sobrien}")
700950650Sobrien
701050650Sobrien(define_insn "prologue_get_pc"
701150650Sobrien  [(set (match_operand:SI 0 "" "")
701250650Sobrien    (unspec_volatile [(plus:SI (pc) (match_operand 1 "" ""))] 2))]
701350650Sobrien  ""
701450650Sobrien  "*
701550650Sobrien{
701650650Sobrien  output_asm_insn (AS1 (call,%X1), operands);
701750650Sobrien  if (! TARGET_DEEP_BRANCH_PREDICTION) 
701850650Sobrien    {
701950650Sobrien      ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (operands[1]));
702050650Sobrien    }    
702150650Sobrien  RET;
702252296Sobrien}"
702352296Sobrien  [(set_attr "memory" "none")])
702450650Sobrien
702550650Sobrien(define_insn "prologue_get_pc_and_set_got"
702650650Sobrien  [(unspec_volatile [(match_operand:SI 0 "" "")] 3)]
702750650Sobrien  ""
702850650Sobrien  "*
702950650Sobrien{
703050650Sobrien  operands[1] = gen_label_rtx ();
703150650Sobrien  output_asm_insn (AS1 (call,%X1), operands);
703250650Sobrien  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\",
703350650Sobrien			     CODE_LABEL_NUMBER (operands[1]));
703450650Sobrien  output_asm_insn (AS1 (pop%L0,%0), operands);
703552296Sobrien  output_asm_insn (\"addl $%__GLOBAL_OFFSET_TABLE_+[.-%X1],%0\", operands);
703650650Sobrien  RET;
703752296Sobrien}"
703852296Sobrien  [(set_attr "memory" "none")])
703950650Sobrien
704050650Sobrien(define_expand "epilogue"
704150650Sobrien  [(const_int 1)]
704250650Sobrien  ""
704350650Sobrien  "
704450650Sobrien{
704550650Sobrien  ix86_expand_epilogue ();
704650650Sobrien  DONE;
704750650Sobrien}")
704850650Sobrien
704950650Sobrien(define_insn "epilogue_set_stack_ptr"
705050650Sobrien  [(set (reg:SI 7) (reg:SI 6))
705150650Sobrien	(clobber (reg:SI 6))]
705250650Sobrien  ""
705350650Sobrien  "*
705450650Sobrien{
705550650Sobrien  rtx xops [2];
705650650Sobrien
705750650Sobrien    xops[0] = frame_pointer_rtx;
705850650Sobrien    xops[1] = stack_pointer_rtx;
705950650Sobrien    output_asm_insn (AS2 (mov%L0,%0,%1), xops);
706050650Sobrien    RET;
706152296Sobrien}"
706252296Sobrien  [(set_attr "memory" "none")])
706350650Sobrien
706450650Sobrien(define_insn "leave"
706550650Sobrien  [(const_int 2)
706650650Sobrien      (clobber (reg:SI 6))
706750650Sobrien      (clobber (reg:SI 7))]
706850650Sobrien  ""
706952296Sobrien  "leave"
707052296Sobrien  [(set_attr "memory" "none")])
707150650Sobrien
707250650Sobrien(define_insn "pop"
707350650Sobrien  [(set (match_operand:SI 0 "register_operand" "r")
707450650Sobrien	(mem:SI (reg:SI 7)))
707550650Sobrien   (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))]
707650650Sobrien  ""
707750650Sobrien  "*
707850650Sobrien{
707950650Sobrien    output_asm_insn (AS1 (pop%L0,%P0), operands);
708050650Sobrien    RET;
708152296Sobrien}"
708252296Sobrien  [(set_attr "memory" "load")])
708350650Sobrien
708418334Speter(define_expand "movstrsi"
708518334Speter  [(parallel [(set (match_operand:BLK 0 "memory_operand" "")
708618334Speter		   (match_operand:BLK 1 "memory_operand" ""))
708718334Speter	      (use (match_operand:SI 2 "const_int_operand" ""))
708818334Speter	      (use (match_operand:SI 3 "const_int_operand" ""))
708918334Speter	      (clobber (match_scratch:SI 4 ""))
709018334Speter	      (clobber (match_dup 5))
709118334Speter	      (clobber (match_dup 6))])]
709218334Speter  ""
709318334Speter  "
709418334Speter{
709518334Speter  rtx addr0, addr1;
709618334Speter
709718334Speter  if (GET_CODE (operands[2]) != CONST_INT)
709818334Speter    FAIL;
709918334Speter
710018334Speter  addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
710118334Speter  addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
710218334Speter
710318334Speter  operands[5] = addr0;
710418334Speter  operands[6] = addr1;
710518334Speter
710650650Sobrien  operands[0] = change_address (operands[0], VOIDmode, addr0);
710750650Sobrien  operands[1] = change_address (operands[1], VOIDmode, addr1);
710818334Speter}")
710918334Speter
711018334Speter;; It might seem that operands 0 & 1 could use predicate register_operand.
711118334Speter;; But strength reduction might offset the MEM expression.  So we let
711218334Speter;; reload put the address into %edi & %esi.
711318334Speter
711418334Speter(define_insn ""
711518334Speter  [(set (mem:BLK (match_operand:SI 0 "address_operand" "D"))
711618334Speter	(mem:BLK (match_operand:SI 1 "address_operand" "S")))
711718334Speter   (use (match_operand:SI 2 "const_int_operand" "n"))
711818334Speter   (use (match_operand:SI 3 "immediate_operand" "i"))
711918334Speter   (clobber (match_scratch:SI 4 "=&c"))
712018334Speter   (clobber (match_dup 0))
712118334Speter   (clobber (match_dup 1))]
712218334Speter  ""
712318334Speter  "*
712418334Speter{
712518334Speter  rtx xops[2];
712618334Speter
712718334Speter  output_asm_insn (\"cld\", operands);
712818334Speter  if (GET_CODE (operands[2]) == CONST_INT)
712918334Speter    {
713018334Speter      if (INTVAL (operands[2]) & ~0x03)
713118334Speter	{
713218334Speter	  xops[0] = GEN_INT ((INTVAL (operands[2]) >> 2) & 0x3fffffff);
713318334Speter	  xops[1] = operands[4];
713418334Speter
713518334Speter	  output_asm_insn (AS2 (mov%L1,%0,%1), xops);
713618334Speter#ifdef INTEL_SYNTAX
713718334Speter	  output_asm_insn (\"rep movsd\", xops);
713818334Speter#else
713918334Speter	  output_asm_insn (\"rep\;movsl\", xops);
714018334Speter#endif
714118334Speter	}
714218334Speter      if (INTVAL (operands[2]) & 0x02)
714318334Speter	output_asm_insn (\"movsw\", operands);
714418334Speter      if (INTVAL (operands[2]) & 0x01)
714518334Speter	output_asm_insn (\"movsb\", operands);
714618334Speter    }
714718334Speter  else
714818334Speter    abort ();
714918334Speter  RET;
715018334Speter}")
715118334Speter
715250650Sobrien(define_expand "clrstrsi"
715350650Sobrien  [(set (match_dup 3) (const_int 0))
715450650Sobrien   (parallel [(set (match_operand:BLK 0 "memory_operand" "")
715550650Sobrien		   (const_int 0))
715650650Sobrien	      (use (match_operand:SI 1 "const_int_operand" ""))
715750650Sobrien	      (use (match_operand:SI 2 "const_int_operand" ""))
715850650Sobrien	      (use (match_dup 3))
715950650Sobrien	      (clobber (match_scratch:SI 4 ""))
716050650Sobrien	      (clobber (match_dup 5))])]
716150650Sobrien  ""
716250650Sobrien  "
716350650Sobrien{
716452296Sobrien  rtx addr0;
716550650Sobrien
716650650Sobrien  if (GET_CODE (operands[1]) != CONST_INT)
716750650Sobrien    FAIL;
716850650Sobrien
716950650Sobrien  addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
717050650Sobrien
717150650Sobrien  operands[3] = gen_reg_rtx (SImode);
717250650Sobrien  operands[5] = addr0;
717350650Sobrien
717450650Sobrien  operands[0] = gen_rtx_MEM (BLKmode, addr0);
717550650Sobrien}")
717650650Sobrien
717750650Sobrien;; It might seem that operand 0 could use predicate register_operand.
717850650Sobrien;; But strength reduction might offset the MEM expression.  So we let
717950650Sobrien;; reload put the address into %edi.
718050650Sobrien
718152296Sobrien(define_insn "*bzero"
718250650Sobrien  [(set (mem:BLK (match_operand:SI 0 "address_operand" "D"))
718350650Sobrien	(const_int 0))
718450650Sobrien   (use (match_operand:SI 1 "const_int_operand" "n"))
718550650Sobrien   (use (match_operand:SI 2 "immediate_operand" "i"))
718650650Sobrien   (use (match_operand:SI 3 "register_operand" "a"))
718750650Sobrien   (clobber (match_scratch:SI 4 "=&c"))
718850650Sobrien   (clobber (match_dup 0))]
718950650Sobrien  ""
719050650Sobrien  "*
719150650Sobrien{
719250650Sobrien  rtx xops[2];
719350650Sobrien
719450650Sobrien  output_asm_insn (\"cld\", operands);
719550650Sobrien  if (GET_CODE (operands[1]) == CONST_INT)
719650650Sobrien    {
719752296Sobrien      unsigned int count = INTVAL (operands[1]) & 0xffffffff;
719852296Sobrien      if (count & ~0x03)
719950650Sobrien	{
720052296Sobrien	  xops[0] = GEN_INT (count / 4);
720150650Sobrien	  xops[1] = operands[4];
720250650Sobrien
720352296Sobrien	  /* K6: stos takes 1 cycle, rep stos takes 8 + %ecx cycles.
720452296Sobrien	     80386: 4/5+5n (+2 for set of ecx)
720552296Sobrien	     80486: 5/7+5n (+1 for set of ecx)
720652296Sobrien	     */
720752296Sobrien	  if (count / 4 < ((int) ix86_cpu < (int)PROCESSOR_PENTIUM ? 4 : 6))
720852296Sobrien	    {
720952296Sobrien	      do
721050650Sobrien#ifdef INTEL_SYNTAX
721152296Sobrien		output_asm_insn (\"stosd\", xops);
721250650Sobrien#else
721352296Sobrien		output_asm_insn (\"stosl\", xops);
721450650Sobrien#endif
721552296Sobrien	      while ((count -= 4) > 3);
721652296Sobrien	    }
721752296Sobrien	  else
721852296Sobrien	    {
721952296Sobrien	      output_asm_insn (AS2 (mov%L1,%0,%1), xops);
722052296Sobrien#ifdef INTEL_SYNTAX
722152296Sobrien	      output_asm_insn (\"rep stosd\", xops);
722252296Sobrien#else
722352296Sobrien	      output_asm_insn (\"rep\;stosl\", xops);
722452296Sobrien#endif
722552296Sobrien	    }
722650650Sobrien	}
722750650Sobrien      if (INTVAL (operands[1]) & 0x02)
722850650Sobrien	output_asm_insn (\"stosw\", operands);
722950650Sobrien      if (INTVAL (operands[1]) & 0x01)
723050650Sobrien	output_asm_insn (\"stosb\", operands);
723150650Sobrien    }
723250650Sobrien  else
723350650Sobrien    abort ();
723450650Sobrien  RET;
723550650Sobrien}")
723650650Sobrien
723718334Speter(define_expand "cmpstrsi"
723818334Speter  [(parallel [(set (match_operand:SI 0 "general_operand" "")
723918334Speter		   (compare:SI (match_operand:BLK 1 "general_operand" "")
724018334Speter			       (match_operand:BLK 2 "general_operand" "")))
724118334Speter	      (use (match_operand:SI 3 "general_operand" ""))
724218334Speter	      (use (match_operand:SI 4 "immediate_operand" ""))
724318334Speter	      (clobber (match_dup 5))
724418334Speter	      (clobber (match_dup 6))
724518334Speter	      (clobber (match_dup 3))])]
724618334Speter  ""
724718334Speter  "
724818334Speter{
724918334Speter  rtx addr1, addr2;
725018334Speter
725118334Speter  addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
725218334Speter  addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0));
725318334Speter  operands[3] = copy_to_mode_reg (SImode, operands[3]);
725418334Speter
725518334Speter  operands[5] = addr1;
725618334Speter  operands[6] = addr2;
725718334Speter
725850650Sobrien  operands[1] = gen_rtx_MEM (BLKmode, addr1);
725950650Sobrien  operands[2] = gen_rtx_MEM (BLKmode, addr2);
726018334Speter
726118334Speter}")
726218334Speter
726318334Speter;; memcmp recognizers.  The `cmpsb' opcode does nothing if the count is
726418334Speter;; zero.  Emit extra code to make sure that a zero-length compare is EQ.
726518334Speter
726618334Speter;; It might seem that operands 0 & 1 could use predicate register_operand.
726718334Speter;; But strength reduction might offset the MEM expression.  So we let
726818334Speter;; reload put the address into %edi & %esi.
726918334Speter
727018334Speter;; ??? Most comparisons have a constant length, and it's therefore
727118334Speter;; possible to know that the length is non-zero, and to avoid the extra
727218334Speter;; code to handle zero-length compares.
727318334Speter
727418334Speter(define_insn ""
727550650Sobrien  [(set (match_operand:SI 0 "register_operand" "=&r")
727618334Speter	(compare:SI (mem:BLK (match_operand:SI 1 "address_operand" "S"))
727718334Speter		    (mem:BLK (match_operand:SI 2 "address_operand" "D"))))
727818334Speter   (use (match_operand:SI 3 "register_operand" "c"))
727918334Speter   (use (match_operand:SI 4 "immediate_operand" "i"))
728018334Speter   (clobber (match_dup 1))
728118334Speter   (clobber (match_dup 2))
728218334Speter   (clobber (match_dup 3))]
728318334Speter  ""
728418334Speter  "*
728518334Speter{
728650650Sobrien  rtx xops[2], label;
728718334Speter
728818334Speter  label = gen_label_rtx ();
728918334Speter
729018334Speter  output_asm_insn (\"cld\", operands);
729118334Speter  output_asm_insn (AS2 (xor%L0,%0,%0), operands);
729218334Speter  output_asm_insn (\"repz\;cmps%B2\", operands);
729318334Speter  output_asm_insn (\"je %l0\", &label);
729418334Speter
729518334Speter  xops[0] = operands[0];
729650650Sobrien  xops[1] = const1_rtx;
729750650Sobrien  output_asm_insn (AS2 (sbb%L0,%0,%0), xops);
729850650Sobrien  if (QI_REG_P (xops[0]))
729950650Sobrien     output_asm_insn (AS2 (or%B0,%1,%b0), xops);
730050650Sobrien  else
730150650Sobrien     output_asm_insn (AS2 (or%L0,%1,%0), xops);
730250650Sobrien	
730318334Speter  ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label));
730418334Speter  RET;
730518334Speter}")
730618334Speter
730718334Speter(define_insn ""
730818334Speter  [(set (cc0)
730918334Speter	(compare:SI (mem:BLK (match_operand:SI 0 "address_operand" "S"))
731018334Speter		    (mem:BLK (match_operand:SI 1 "address_operand" "D"))))
731118334Speter   (use (match_operand:SI 2 "register_operand" "c"))
731218334Speter   (use (match_operand:SI 3 "immediate_operand" "i"))
731318334Speter   (clobber (match_dup 0))
731418334Speter   (clobber (match_dup 1))
731518334Speter   (clobber (match_dup 2))]
731618334Speter  ""
731718334Speter  "*
731818334Speter{
731918334Speter  rtx xops[2];
732018334Speter
732118334Speter  cc_status.flags |= CC_NOT_SIGNED;
732218334Speter
732350650Sobrien  xops[0] = gen_rtx_REG (QImode, 0);
732418334Speter  xops[1] = CONST0_RTX (QImode);
732518334Speter
732618334Speter  output_asm_insn (\"cld\", operands);
732718334Speter  output_asm_insn (AS2 (test%B0,%1,%0), xops);
732818334Speter  return \"repz\;cmps%B2\";
732918334Speter}")
733018334Speter
733150650Sobrien
733218334Speter;; Note, you cannot optimize away the branch following the bsfl by assuming
733318334Speter;; that the destination is not modified if the input is 0, since not all
733418334Speter;; x86 implementations do this.
733518334Speter
733650650Sobrien(define_expand "ffssi2"
733750650Sobrien  [(set (match_operand:SI 0 "general_operand" "") 
733850650Sobrien	(ffs:SI (match_operand:SI 1 "general_operand" "")))]
733918334Speter  ""
734050650Sobrien  "
734118334Speter{
734250650Sobrien  rtx label = gen_label_rtx (), temp = gen_reg_rtx (SImode);
734318334Speter
734450650Sobrien  emit_insn (gen_ffssi_1 (temp, operands[1]));
734550650Sobrien  emit_cmp_insn (operands[1], const0_rtx, NE, NULL_RTX, SImode, 0, 0);
734650650Sobrien  emit_jump_insn (gen_bne (label));
734750650Sobrien  emit_move_insn (temp, constm1_rtx);
734850650Sobrien  emit_label (label);
734950650Sobrien  temp = expand_binop (SImode, add_optab, temp, const1_rtx,
735050650Sobrien		       operands[0], 0, OPTAB_WIDEN);
735118334Speter
735250650Sobrien  if (temp != operands[0])
735350650Sobrien    emit_move_insn (operands[0], temp);
735450650Sobrien  DONE;  
735518334Speter}")
735618334Speter
735750650Sobrien(define_insn "ffssi_1"
735850650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
735950650Sobrien	(unspec:SI [(match_operand:SI 1 "nonimmediate_operand" "rm")] 5))]
736018334Speter  ""
736150650Sobrien  "* return AS2 (bsf%L0,%1,%0);")
736218334Speter
736350650Sobrien(define_expand "ffshi2"
736450650Sobrien  [(set (match_operand:SI 0 "general_operand" "") 
736550650Sobrien	(ffs:HI (match_operand:HI 1 "general_operand" "")))]
736618334Speter  ""
736750650Sobrien  "
736818334Speter{
736950650Sobrien  rtx label = gen_label_rtx (), temp = gen_reg_rtx (HImode);
737018334Speter
737150650Sobrien  emit_insn (gen_ffshi_1 (temp, operands[1]));
737250650Sobrien  emit_cmp_insn (operands[1], const0_rtx, NE, NULL_RTX, HImode, 0, 0);
737350650Sobrien  emit_jump_insn (gen_bne (label));
737450650Sobrien  emit_move_insn (temp, constm1_rtx);
737550650Sobrien  emit_label (label);
737650650Sobrien  temp = expand_binop (HImode, add_optab, temp, const1_rtx,
737750650Sobrien		       operands[0], 0, OPTAB_WIDEN);
737818334Speter
737950650Sobrien  if (temp != operands[0])
738050650Sobrien    emit_move_insn (operands[0], temp);
738150650Sobrien  DONE;  
738218334Speter}")
738350650Sobrien
738450650Sobrien(define_insn "ffshi_1"
738550650Sobrien  [(set (match_operand:HI 0 "register_operand" "=r")
738650650Sobrien	(unspec:HI [(match_operand:SI 1 "nonimmediate_operand" "rm")] 5))]
738750650Sobrien  ""
738850650Sobrien  "* return AS2 (bsf%W0,%1,%0);")
738918334Speter
739018334Speter;; These patterns match the binary 387 instructions for addM3, subM3,
739118334Speter;; mulM3 and divM3.  There are three patterns for each of DFmode and
739218334Speter;; SFmode.  The first is the normal insn, the second the same insn but
739318334Speter;; with one operand a conversion, and the third the same insn but with
739452296Sobrien;; the other operand a conversion.
739518334Speter
739618334Speter(define_insn ""
739718334Speter  [(set (match_operand:DF 0 "register_operand" "=f,f")
739818334Speter	(match_operator:DF 3 "binary_387_op"
739918334Speter			[(match_operand:DF 1 "nonimmediate_operand" "0,fm")
740018334Speter			 (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))]
740118334Speter  "TARGET_80387"
740250650Sobrien  "* return output_387_binary_op (insn, operands);"
740350650Sobrien  [(set (attr "type") 
740450650Sobrien        (cond [(match_operand:DF 3 "is_mul" "") 
740550650Sobrien                 (const_string "fpmul")
740650650Sobrien               (match_operand:DF 3 "is_div" "") 
740750650Sobrien                 (const_string "fpdiv")
740850650Sobrien              ]
740950650Sobrien               (const_string "fpop")
741050650Sobrien        )
741150650Sobrien  )])
741218334Speter
741318334Speter(define_insn ""
741418334Speter  [(set (match_operand:XF 0 "register_operand" "=f,f")
741518334Speter	(match_operator:XF 3 "binary_387_op"
741650650Sobrien			[(match_operand:XF 1 "register_operand" "0,f")
741750650Sobrien			 (match_operand:XF 2 "register_operand" "f,0")]))]
741818334Speter  "TARGET_80387"
741950650Sobrien  "* return output_387_binary_op (insn, operands);"
742050650Sobrien  [(set (attr "type") 
742150650Sobrien        (cond [(match_operand:DF 3 "is_mul" "") 
742250650Sobrien                 (const_string "fpmul")
742350650Sobrien               (match_operand:DF 3 "is_div" "") 
742450650Sobrien                 (const_string "fpdiv")
742550650Sobrien              ]
742650650Sobrien               (const_string "fpop")
742750650Sobrien        )
742850650Sobrien  )])
742918334Speter
743018334Speter(define_insn ""
743118334Speter  [(set (match_operand:XF 0 "register_operand" "=f,f")
743218334Speter	(match_operator:XF 3 "binary_387_op"
743350650Sobrien	   [(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,0"))
743450650Sobrien	    (match_operand:XF 2 "register_operand" "0,f")]))]
743518334Speter  "TARGET_80387"
743650650Sobrien  "* return output_387_binary_op (insn, operands);"
743750650Sobrien  [(set (attr "type") 
743850650Sobrien        (cond [(match_operand:DF 3 "is_mul" "") 
743950650Sobrien                 (const_string "fpmul")
744050650Sobrien               (match_operand:DF 3 "is_div" "") 
744150650Sobrien                 (const_string "fpdiv")
744250650Sobrien              ]
744350650Sobrien               (const_string "fpop")
744450650Sobrien        )
744550650Sobrien  )])
744618334Speter
744718334Speter(define_insn ""
744818334Speter  [(set (match_operand:XF 0 "register_operand" "=f,f")
744918334Speter	(match_operator:XF 3 "binary_387_op"
745050650Sobrien	  [(match_operand:XF 1 "register_operand" "0,f")
745118334Speter	   (float_extend:XF
745250650Sobrien	    (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
745318334Speter  "TARGET_80387"
745450650Sobrien  "* return output_387_binary_op (insn, operands);"
745550650Sobrien  [(set (attr "type") 
745650650Sobrien        (cond [(match_operand:DF 3 "is_mul" "") 
745750650Sobrien                 (const_string "fpmul")
745850650Sobrien               (match_operand:DF 3 "is_div" "") 
745950650Sobrien                 (const_string "fpdiv")
746050650Sobrien              ]
746150650Sobrien               (const_string "fpop")
746250650Sobrien        )
746350650Sobrien  )])
746418334Speter
746518334Speter(define_insn ""
746618334Speter  [(set (match_operand:DF 0 "register_operand" "=f,f")
746718334Speter	(match_operator:DF 3 "binary_387_op"
746850650Sobrien	   [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0"))
746950650Sobrien	    (match_operand:DF 2 "register_operand" "0,f")]))]
747018334Speter  "TARGET_80387"
747150650Sobrien  "* return output_387_binary_op (insn, operands);"
747250650Sobrien  [(set (attr "type") 
747350650Sobrien        (cond [(match_operand:DF 3 "is_mul" "") 
747450650Sobrien                 (const_string "fpmul")
747550650Sobrien               (match_operand:DF 3 "is_div" "") 
747650650Sobrien                 (const_string "fpdiv")
747750650Sobrien              ]
747850650Sobrien               (const_string "fpop")
747950650Sobrien        )
748050650Sobrien  )])
748118334Speter
748218334Speter(define_insn ""
748318334Speter  [(set (match_operand:DF 0 "register_operand" "=f,f")
748418334Speter	(match_operator:DF 3 "binary_387_op"
748550650Sobrien	  [(match_operand:DF 1 "register_operand" "0,f")
748618334Speter	   (float_extend:DF
748750650Sobrien	    (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
748818334Speter  "TARGET_80387"
748950650Sobrien  "* return output_387_binary_op (insn, operands);"
749050650Sobrien  [(set (attr "type") 
749150650Sobrien        (cond [(match_operand:DF 3 "is_mul" "") 
749250650Sobrien                 (const_string "fpmul")
749350650Sobrien               (match_operand:DF 3 "is_div" "") 
749450650Sobrien                 (const_string "fpdiv")
749550650Sobrien              ]
749650650Sobrien               (const_string "fpop")
749750650Sobrien        )
749850650Sobrien  )])
749918334Speter
750018334Speter(define_insn ""
750118334Speter  [(set (match_operand:SF 0 "register_operand" "=f,f")
750218334Speter	(match_operator:SF 3 "binary_387_op"
750318334Speter			[(match_operand:SF 1 "nonimmediate_operand" "0,fm")
750418334Speter			 (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))]
750518334Speter  "TARGET_80387"
750650650Sobrien  "* return output_387_binary_op (insn, operands);"
750750650Sobrien  [(set (attr "type") 
750850650Sobrien        (cond [(match_operand:DF 3 "is_mul" "") 
750950650Sobrien                 (const_string "fpmul")
751050650Sobrien               (match_operand:DF 3 "is_div" "") 
751150650Sobrien                 (const_string "fpdiv")
751250650Sobrien              ]
751350650Sobrien               (const_string "fpop")
751450650Sobrien        )
751550650Sobrien  )])
751618334Speter
751718334Speter(define_expand "strlensi"
751818334Speter  [(parallel [(set (match_dup 4)
751918334Speter		   (unspec:SI [(mem:BLK (match_operand:BLK 1 "general_operand" ""))
752050650Sobrien			       (match_operand:QI 2 "immediate_operand" "")
752118334Speter			       (match_operand:SI 3 "immediate_operand" "")] 0))
752218334Speter	      (clobber (match_dup 1))])
752318334Speter   (set (match_dup 5)
752418334Speter	(not:SI (match_dup 4)))
752518334Speter   (set (match_operand:SI 0 "register_operand" "")
752650650Sobrien	(plus:SI (match_dup 5)
752750650Sobrien	         (const_int -1)))]
752818334Speter  ""
752918334Speter  "
753018334Speter{
753150650Sobrien  if (TARGET_UNROLL_STRLEN && operands[2] == const0_rtx && optimize > 1)
753250650Sobrien    {
753350650Sobrien      rtx address;
753450650Sobrien      rtx scratch;
753550650Sobrien
753650650Sobrien	/* well it seems that some optimizer does not combine a call like
753750650Sobrien	     foo(strlen(bar), strlen(bar));
753850650Sobrien	   when the move and the subtraction is done here.  It does calculate
753950650Sobrien	   the length just once when these instructions are done inside of
754050650Sobrien	   output_strlen_unroll().  But I think since &bar[strlen(bar)] is
754150650Sobrien	   often used and I use one fewer register for the lifetime of
754250650Sobrien	   output_strlen_unroll() this is better.  */
754350650Sobrien      scratch = gen_reg_rtx (SImode);
754450650Sobrien      address = force_reg (SImode, XEXP (operands[1], 0));
754550650Sobrien
754650650Sobrien	/* move address to scratch-register
754750650Sobrien	   this is done here because the i586 can do the following and
754850650Sobrien	   in the same cycle with the following move.  */
754950650Sobrien      if (GET_CODE (operands[3]) != CONST_INT || INTVAL (operands[3]) < 4)
755050650Sobrien	  emit_insn (gen_movsi (scratch, address));
755150650Sobrien
755250650Sobrien      emit_insn (gen_movsi (operands[0], address));
755350650Sobrien
755450650Sobrien      if(TARGET_USE_Q_REG)
755550650Sobrien	emit_insn (gen_strlensi_unroll5 (operands[0],
755650650Sobrien					operands[3],
755750650Sobrien					scratch,
755850650Sobrien					operands[0]));
755950650Sobrien      else
756050650Sobrien	emit_insn (gen_strlensi_unroll4 (operands[0],
756150650Sobrien					operands[3],
756250650Sobrien					scratch,
756350650Sobrien					operands[0]));
756450650Sobrien
756550650Sobrien        /* gen_strlensi_unroll[45] returns the address of the zero
756650650Sobrien           at the end of the string, like memchr(), so compute the
756750650Sobrien           length by subtracting the startaddress.  */
756850650Sobrien      emit_insn (gen_subsi3 (operands[0], operands[0], address));
756950650Sobrien      DONE;
757050650Sobrien    }
757150650Sobrien
757218334Speter  operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0));
757318334Speter  operands[4] = gen_reg_rtx (SImode);
757418334Speter  operands[5] = gen_reg_rtx (SImode);
757518334Speter}")
757618334Speter
757718334Speter;; It might seem that operands 0 & 1 could use predicate register_operand.
757818334Speter;; But strength reduction might offset the MEM expression.  So we let
757918334Speter;; reload put the address into %edi.
758018334Speter
758118334Speter(define_insn ""
758218334Speter  [(set (match_operand:SI 0 "register_operand" "=&c")
758318334Speter	(unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "D"))
758450650Sobrien		    (match_operand:QI 2 "immediate_operand" "a")
758518334Speter		    (match_operand:SI 3 "immediate_operand" "i")] 0))
758618334Speter   (clobber (match_dup 1))]
758718334Speter  ""
758818334Speter  "*
758918334Speter{
759018334Speter  rtx xops[2];
759118334Speter
759218334Speter  xops[0] = operands[0];
759318334Speter  xops[1] = constm1_rtx;
759418334Speter  output_asm_insn (\"cld\", operands);
759518334Speter  output_asm_insn (AS2 (mov%L0,%1,%0), xops);
759618334Speter  return \"repnz\;scas%B2\";
759718334Speter}")
759850650Sobrien
759950650Sobrien/* Conditional move define_insns.  */
760050650Sobrien
760150650Sobrien(define_expand "movsicc"
760250650Sobrien  [(set (match_operand:SI 0 "register_operand" "")
760350650Sobrien	(if_then_else:SI (match_operand 1 "comparison_operator" "")
760450650Sobrien			 (match_operand:SI 2 "nonimmediate_operand" "")
760550650Sobrien			 (match_operand:SI 3 "nonimmediate_operand" "")))]
760650650Sobrien  "TARGET_CMOVE"
760750650Sobrien  "
760850650Sobrien{
760950650Sobrien  if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT)
761050650Sobrien    FAIL;
761150650Sobrien
761250650Sobrien  operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
761350650Sobrien			GET_MODE (i386_compare_op0),
761450650Sobrien			i386_compare_op0, i386_compare_op1);
761550650Sobrien}")
761650650Sobrien
761750650Sobrien(define_insn ""
761850650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
761950650Sobrien	(if_then_else:SI (match_operator 1 "comparison_operator" 
762050650Sobrien	      [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m")
762150650Sobrien		(match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")])
762250650Sobrien	      (match_operand:SI 4 "nonimmediate_operand" "rm,rm,0,0")
762350650Sobrien	      (match_operand:SI 5 "nonimmediate_operand" "0,0,rm,rm")))]
762450650Sobrien  "TARGET_CMOVE"
762550650Sobrien  "#")
762650650Sobrien
762750650Sobrien(define_insn ""
762850650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r,r,r")
762950650Sobrien	(if_then_else:SI (match_operator 1 "comparison_operator" 
763050650Sobrien	      [(match_operand 2 "nonimmediate_operand" "r,m,r,m")
763150650Sobrien		(match_operand 3 "general_operand" "rmi,ri,rmi,ri")])
763250650Sobrien	      (match_operand:SI 4 "nonimmediate_operand" "rm,rm,0,0")
763350650Sobrien	      (match_operand:SI 5 "nonimmediate_operand" "0,0,rm,rm")))]
763450650Sobrien  "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT"
763550650Sobrien  "#")
763650650Sobrien
763750650Sobrien(define_split
763852296Sobrien  [(set (match_operand:SI 0 "register_operand" "")
763950650Sobrien	(if_then_else:SI (match_operator 1 "comparison_operator" 
764050650Sobrien				[(match_operand 2 "nonimmediate_operand" "")
764150650Sobrien				 (const_int 0)])
764252296Sobrien		      (match_operand:SI 3 "nonimmediate_operand" "")
764352296Sobrien		      (match_operand:SI 4 "nonimmediate_operand" "")))]
764450650Sobrien  "TARGET_CMOVE && reload_completed"
764550650Sobrien  [(set (cc0)
764650650Sobrien	(match_dup 2))
764750650Sobrien   (set (match_dup 0)
764850650Sobrien	(if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)])
764950650Sobrien		      (match_dup 3) (match_dup 4)))]
765050650Sobrien  "")
765150650Sobrien
765250650Sobrien(define_split
765352296Sobrien  [(set (match_operand:SI 0 "register_operand" "")
765450650Sobrien	(if_then_else:SI (match_operator 1 "comparison_operator" 
765550650Sobrien				[(match_operand 2 "nonimmediate_operand" "")
765650650Sobrien				 (match_operand 3 "general_operand" "")])
765752296Sobrien		      (match_operand:SI 4 "nonimmediate_operand" "")
765852296Sobrien		      (match_operand:SI 5 "nonimmediate_operand" "")))]
765950650Sobrien  "TARGET_CMOVE && reload_completed"
766050650Sobrien  [(set (cc0) (compare (match_dup 2) (match_dup 3)))
766150650Sobrien   (set (match_dup 0)
766250650Sobrien	(if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)])
766350650Sobrien		      (match_dup 4) (match_dup 5)))]
766450650Sobrien  "")
766550650Sobrien
766650650Sobrien(define_insn ""
766750650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
766850650Sobrien	(if_then_else:SI (match_operator 1 "comparison_operator" 
766950650Sobrien				[(cc0) (const_int 0)])
767050650Sobrien		      (match_operand:SI 2 "nonimmediate_operand" "rm,0")
767150650Sobrien		      (match_operand:SI 3 "nonimmediate_operand" "0,rm")))]
767250650Sobrien  "TARGET_CMOVE && reload_completed"
767350650Sobrien  "* return output_int_conditional_move (which_alternative, operands);")
767450650Sobrien
767550650Sobrien(define_expand "movhicc"
767650650Sobrien  [(set (match_operand:HI 0 "register_operand" "")
767750650Sobrien	(if_then_else:HI (match_operand 1 "comparison_operator" "")
767850650Sobrien			 (match_operand:HI 2 "nonimmediate_operand" "")
767950650Sobrien			 (match_operand:HI 3 "nonimmediate_operand" "")))]
768050650Sobrien  "TARGET_CMOVE"
768150650Sobrien  "
768250650Sobrien{
768350650Sobrien  if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT)
768450650Sobrien    FAIL;
768550650Sobrien
768650650Sobrien  operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
768750650Sobrien			GET_MODE (i386_compare_op0),
768850650Sobrien			i386_compare_op0, i386_compare_op1);
768950650Sobrien}")
769050650Sobrien
769150650Sobrien(define_insn ""
769250650Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
769350650Sobrien	(if_then_else:HI (match_operator 1 "comparison_operator" 
769450650Sobrien	      [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m")
769550650Sobrien		(match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")])
769650650Sobrien	      (match_operand:HI 4 "nonimmediate_operand" "rm,rm,0,0")
769750650Sobrien	      (match_operand:HI 5 "nonimmediate_operand" "0,0,rm,rm")))]
769850650Sobrien  "TARGET_CMOVE"
769950650Sobrien  "#")
770050650Sobrien
770150650Sobrien(define_insn ""
770250650Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r,r,r")
770350650Sobrien	(if_then_else:HI (match_operator 1 "comparison_operator" 
770450650Sobrien	      [(match_operand 2 "nonimmediate_operand" "r,m,r,m")
770550650Sobrien		(match_operand 3 "general_operand" "rmi,ri,rmi,ri")])
770650650Sobrien	      (match_operand:HI 4 "nonimmediate_operand" "rm,rm,0,0")
770750650Sobrien	      (match_operand:HI 5 "nonimmediate_operand" "0,0,rm,rm")))]
770850650Sobrien  "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT"
770950650Sobrien  "#")
771050650Sobrien
771150650Sobrien(define_split
771252296Sobrien  [(set (match_operand:HI 0 "register_operand" "")
771350650Sobrien	(if_then_else:HI (match_operator 1 "comparison_operator" 
771450650Sobrien				[(match_operand 2 "nonimmediate_operand" "")
771550650Sobrien				 (const_int 0)])
771652296Sobrien		      (match_operand:HI 3 "nonimmediate_operand" "")
771752296Sobrien		      (match_operand:HI 4 "nonimmediate_operand" "")))]
771850650Sobrien  "TARGET_CMOVE && reload_completed"
771950650Sobrien  [(set (cc0)
772050650Sobrien	(match_dup 2))
772150650Sobrien   (set (match_dup 0)
772250650Sobrien	(if_then_else:HI (match_op_dup 1 [(cc0) (const_int 0)])
772350650Sobrien		      (match_dup 3) (match_dup 4)))]
772450650Sobrien  "")
772550650Sobrien
772650650Sobrien(define_split
772752296Sobrien  [(set (match_operand:HI 0 "register_operand" "")
772850650Sobrien	(if_then_else:HI (match_operator 1 "comparison_operator" 
772950650Sobrien				[(match_operand 2 "nonimmediate_operand" "")
773050650Sobrien				 (match_operand 3 "general_operand" "")])
773152296Sobrien		      (match_operand:HI 4 "nonimmediate_operand" "")
773252296Sobrien		      (match_operand:HI 5 "nonimmediate_operand" "")))]
773350650Sobrien  "TARGET_CMOVE && reload_completed"
773450650Sobrien  [(set (cc0)
773550650Sobrien	(compare (match_dup 2) (match_dup 3)))
773650650Sobrien   (set (match_dup 0)
773750650Sobrien	(if_then_else:HI (match_op_dup 1 [(cc0) (const_int 0)])
773850650Sobrien		      (match_dup 4) (match_dup 5)))]
773950650Sobrien  "")
774050650Sobrien
774150650Sobrien(define_insn ""
774250650Sobrien  [(set (match_operand:HI 0 "register_operand" "=r,r")
774350650Sobrien	(if_then_else:HI (match_operator 1 "comparison_operator" 
774450650Sobrien				[(cc0) (const_int 0)])
774550650Sobrien		      (match_operand:HI 2 "nonimmediate_operand" "rm,0")
774650650Sobrien		      (match_operand:HI 3 "nonimmediate_operand" "0,rm")))]
774750650Sobrien  "TARGET_CMOVE && reload_completed"
774850650Sobrien  "* return output_int_conditional_move (which_alternative, operands);")
774950650Sobrien
775050650Sobrien(define_expand "movsfcc"
775150650Sobrien  [(set (match_operand:SF 0 "register_operand" "")
775250650Sobrien	(if_then_else:SF (match_operand 1 "comparison_operator" "")
775350650Sobrien			 (match_operand:SF 2 "register_operand" "")
775450650Sobrien			 (match_operand:SF 3 "register_operand" "")))]
775550650Sobrien  "TARGET_CMOVE"
775650650Sobrien  "
775750650Sobrien{
775850650Sobrien  rtx temp;
775950650Sobrien
776050650Sobrien  if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT)
776150650Sobrien    FAIL;
776250650Sobrien
776350650Sobrien  /* The floating point conditional move instructions don't directly
776450650Sobrien     support conditions resulting from a signed integer comparison. */
776550650Sobrien
776650650Sobrien  switch (GET_CODE (operands[1]))
776750650Sobrien    {
776850650Sobrien    case LT:
776950650Sobrien    case LE:
777050650Sobrien    case GE:
777150650Sobrien    case GT:
777250650Sobrien      temp = emit_store_flag (gen_reg_rtx (QImode),
777350650Sobrien		GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1,
777450650Sobrien		VOIDmode, 0, 0);
777550650Sobrien
777650650Sobrien      if (!temp)
777750650Sobrien        FAIL;
777850650Sobrien
777950650Sobrien      operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx);
778050650Sobrien      break;
778150650Sobrien
778250650Sobrien    default:
778350650Sobrien      operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
778450650Sobrien			GET_MODE (i386_compare_op0),
778550650Sobrien			i386_compare_op0, i386_compare_op1);
778650650Sobrien      break;
778750650Sobrien    }
778850650Sobrien}")
778950650Sobrien
779050650Sobrien(define_insn ""
779150650Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f,f,f")
779250650Sobrien	(if_then_else:SF (match_operator 1 "comparison_operator" 
779350650Sobrien	      [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m")
779450650Sobrien		(match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")])
779550650Sobrien	      (match_operand:SF 4 "register_operand" "f,f,0,0")
779650650Sobrien	      (match_operand:SF 5 "register_operand" "0,0,f,f")))]
779750650Sobrien  "TARGET_CMOVE
779850650Sobrien    && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE
779950650Sobrien    && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT"
780050650Sobrien  "#")
780150650Sobrien
780250650Sobrien(define_insn ""
780350650Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f,f,f")
780450650Sobrien	(if_then_else:SF (match_operator 1 "comparison_operator" 
780550650Sobrien		[(match_operand 2 "nonimmediate_operand" "r,m,r,m")
780650650Sobrien		 (match_operand 3 "general_operand" "rmi,ri,rmi,ri")])
780750650Sobrien	      (match_operand:SF 4 "register_operand" "f,f,0,0")
780850650Sobrien	      (match_operand:SF 5 "register_operand" "0,0,f,f")))]
780950650Sobrien  "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT
781050650Sobrien    && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE
781150650Sobrien    && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT"
781250650Sobrien  "#")
781350650Sobrien
781450650Sobrien(define_split
781552296Sobrien  [(set (match_operand:SF 0 "register_operand" "")
781650650Sobrien	(if_then_else:SF (match_operator 1 "comparison_operator" 
781750650Sobrien				[(match_operand 2 "nonimmediate_operand" "")
781850650Sobrien				 (const_int 0)])
781952296Sobrien		      (match_operand:SF 3 "register_operand" "")
782052296Sobrien		      (match_operand:SF 4 "register_operand" "")))]
782150650Sobrien  "TARGET_CMOVE && reload_completed"
782250650Sobrien  [(set (cc0)
782350650Sobrien	(match_dup 2))
782450650Sobrien   (set (match_dup 0)
782550650Sobrien	(if_then_else:SF (match_op_dup 1 [(cc0) (const_int 0)])
782650650Sobrien		      (match_dup 3) (match_dup 4)))]
782750650Sobrien  "")
782850650Sobrien
782950650Sobrien(define_split
783052296Sobrien  [(set (match_operand:SF 0 "register_operand" "")
783150650Sobrien	(if_then_else:SF (match_operator 1 "comparison_operator" 
783250650Sobrien				[(match_operand 2 "nonimmediate_operand" "")
783350650Sobrien				 (match_operand 3 "general_operand" "")])
783452296Sobrien		      (match_operand:SF 4 "register_operand" "")
783552296Sobrien		      (match_operand:SF 5 "register_operand" "")))]
783650650Sobrien  "TARGET_CMOVE && reload_completed"
783750650Sobrien  [(set (cc0) (compare (match_dup 2) (match_dup 3)))
783850650Sobrien   (set (match_dup 0)
783950650Sobrien	(if_then_else:SF (match_op_dup 1 [(cc0) (const_int 0)])
784050650Sobrien		      (match_dup 4) (match_dup 5)))]
784150650Sobrien  "")
784250650Sobrien
784350650Sobrien(define_insn ""
784450650Sobrien  [(set (match_operand:SF 0 "register_operand" "=f,f")
784550650Sobrien	(if_then_else:SF (match_operator 1 "comparison_operator" 
784650650Sobrien				[(cc0) (const_int 0)])
784750650Sobrien		      (match_operand:SF 2 "register_operand" "f,0")
784850650Sobrien		      (match_operand:SF 3 "register_operand" "0,f")))]
784950650Sobrien  "TARGET_CMOVE && reload_completed"
785050650Sobrien  "* return output_fp_conditional_move (which_alternative, operands);")
785150650Sobrien
785250650Sobrien(define_expand "movdfcc"
785350650Sobrien  [(set (match_operand:DF 0 "register_operand" "")
785450650Sobrien	(if_then_else:DF (match_operand 1 "comparison_operator" "")
785550650Sobrien			 (match_operand:DF 2 "register_operand" "")
785650650Sobrien			 (match_operand:DF 3 "register_operand" "")))]
785750650Sobrien  "TARGET_CMOVE"
785850650Sobrien  "
785950650Sobrien{
786050650Sobrien  rtx temp;
786150650Sobrien
786250650Sobrien  if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT)
786350650Sobrien    FAIL;
786450650Sobrien
786550650Sobrien  /* The floating point conditional move instructions don't directly
786650650Sobrien     support conditions resulting from a signed integer comparison. */
786750650Sobrien
786850650Sobrien  switch (GET_CODE (operands[1]))
786950650Sobrien    {
787050650Sobrien    case LT:
787150650Sobrien    case LE:
787250650Sobrien    case GE:
787350650Sobrien    case GT:
787450650Sobrien      temp = emit_store_flag (gen_reg_rtx (QImode),
787550650Sobrien		GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1,
787650650Sobrien		VOIDmode, 0, 0);
787750650Sobrien
787850650Sobrien      if (!temp)
787950650Sobrien        FAIL;
788050650Sobrien
788150650Sobrien      operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx);
788250650Sobrien      break;
788350650Sobrien
788450650Sobrien    default:
788550650Sobrien      operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
788650650Sobrien			GET_MODE (i386_compare_op0),
788750650Sobrien			i386_compare_op0, i386_compare_op1);
788850650Sobrien      break;
788950650Sobrien    }
789050650Sobrien}")
789150650Sobrien
789250650Sobrien(define_insn ""
789350650Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f,f,f")
789450650Sobrien	(if_then_else:DF (match_operator 1 "comparison_operator" 
789550650Sobrien	      [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m")
789650650Sobrien		(match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")])
789750650Sobrien	      (match_operand:DF 4 "register_operand" "f,f,0,0")
789850650Sobrien	      (match_operand:DF 5 "register_operand" "0,0,f,f")))]
789950650Sobrien  "TARGET_CMOVE
790050650Sobrien    && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE
790150650Sobrien    && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT"
790250650Sobrien  "#")
790350650Sobrien
790450650Sobrien(define_insn ""
790550650Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f,f,f")
790650650Sobrien	(if_then_else:DF (match_operator 1 "comparison_operator" 
790750650Sobrien	      [(match_operand 2 "nonimmediate_operand" "r,m,r,m")
790850650Sobrien		(match_operand 3 "general_operand" "rmi,ri,rmi,ri")])
790950650Sobrien	      (match_operand:DF 4 "register_operand" "f,f,0,0")
791050650Sobrien	      (match_operand:DF 5 "register_operand" "0,0,f,f")))]
791150650Sobrien  "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT
791250650Sobrien    && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE
791350650Sobrien    && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT"
791450650Sobrien  "#")
791550650Sobrien
791650650Sobrien(define_split
791752296Sobrien  [(set (match_operand:DF 0 "register_operand" "")
791850650Sobrien	(if_then_else:DF (match_operator 1 "comparison_operator" 
791950650Sobrien				[(match_operand 2 "nonimmediate_operand" "")
792050650Sobrien				 (const_int 0)])
792152296Sobrien		      (match_operand:DF 3 "register_operand" "")
792252296Sobrien		      (match_operand:DF 4 "register_operand" "")))]
792350650Sobrien  "TARGET_CMOVE && reload_completed"
792450650Sobrien  [(set (cc0)
792550650Sobrien	(match_dup 2))
792650650Sobrien   (set (match_dup 0)
792750650Sobrien	(if_then_else:DF (match_op_dup 1 [(cc0) (const_int 0)])
792850650Sobrien		      (match_dup 3) (match_dup 4)))]
792950650Sobrien  "")
793050650Sobrien
793150650Sobrien(define_split
793252296Sobrien  [(set (match_operand:DF 0 "register_operand" "")
793350650Sobrien	(if_then_else:DF (match_operator 1 "comparison_operator" 
793450650Sobrien				[(match_operand 2 "nonimmediate_operand" "")
793550650Sobrien				 (match_operand 3 "general_operand" "")])
793652296Sobrien		      (match_operand:DF 4 "register_operand" "")
793752296Sobrien		      (match_operand:DF 5 "register_operand" "")))]
793850650Sobrien  "TARGET_CMOVE && reload_completed"
793950650Sobrien  [(set (cc0) (compare (match_dup 2) (match_dup 3)))
794050650Sobrien   (set (match_dup 0)
794150650Sobrien	(if_then_else:DF (match_op_dup 1 [(cc0) (const_int 0)])
794250650Sobrien		      (match_dup 4) (match_dup 5)))]
794350650Sobrien  "")
794450650Sobrien
794550650Sobrien(define_insn ""
794650650Sobrien  [(set (match_operand:DF 0 "register_operand" "=f,f")
794750650Sobrien	(if_then_else:DF (match_operator 1 "comparison_operator" 
794850650Sobrien				[(cc0) (const_int 0)])
794950650Sobrien		      (match_operand:DF 2 "register_operand" "f,0")
795050650Sobrien		      (match_operand:DF 3 "register_operand" "0,f")))]
795150650Sobrien  "TARGET_CMOVE && reload_completed"
795250650Sobrien  "* return output_fp_conditional_move (which_alternative, operands);")
795350650Sobrien
795450650Sobrien(define_expand "movxfcc"
795550650Sobrien  [(set (match_operand:XF 0 "register_operand" "")
795650650Sobrien	(if_then_else:XF (match_operand 1 "comparison_operator" "")
795750650Sobrien			 (match_operand:XF 2 "register_operand" "")
795850650Sobrien			 (match_operand:XF 3 "register_operand" "")))]
795950650Sobrien  "TARGET_CMOVE"
796050650Sobrien  "
796150650Sobrien{
796250650Sobrien  rtx temp;
796350650Sobrien
796450650Sobrien  if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT)
796550650Sobrien    FAIL;
796650650Sobrien
796750650Sobrien  /* The floating point conditional move instructions don't directly
796850650Sobrien     support conditions resulting from a signed integer comparison. */
796950650Sobrien
797050650Sobrien  switch (GET_CODE (operands[1]))
797150650Sobrien    {
797250650Sobrien    case LT:
797350650Sobrien    case LE:
797450650Sobrien    case GE:
797550650Sobrien    case GT:
797650650Sobrien      temp = emit_store_flag (gen_reg_rtx (QImode),
797750650Sobrien		GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1,
797850650Sobrien		VOIDmode, 0, 0);
797950650Sobrien
798050650Sobrien      if (!temp)
798150650Sobrien        FAIL;
798250650Sobrien
798350650Sobrien      operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx);
798450650Sobrien      break;
798550650Sobrien
798650650Sobrien    default:
798750650Sobrien      operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
798850650Sobrien			GET_MODE (i386_compare_op0),
798950650Sobrien			i386_compare_op0, i386_compare_op1);
799050650Sobrien      break;
799150650Sobrien    }
799250650Sobrien}")
799350650Sobrien
799450650Sobrien(define_insn ""
799550650Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f,f,f")
799650650Sobrien	(if_then_else:XF (match_operator 1 "comparison_operator" 
799750650Sobrien	      [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m")
799850650Sobrien		(match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")])
799950650Sobrien	      (match_operand:XF 4 "register_operand" "f,f,0,0")
800050650Sobrien	      (match_operand:XF 5 "register_operand" "0,0,f,f")))]
800150650Sobrien  "TARGET_CMOVE
800250650Sobrien    && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE
800350650Sobrien    && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT"
800450650Sobrien  "#")
800550650Sobrien
800650650Sobrien(define_insn ""
800750650Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f,f,f")
800850650Sobrien	(if_then_else:XF (match_operator 1 "comparison_operator" 
800950650Sobrien	      [(match_operand 2 "nonimmediate_operand" "r,m,r,m")
801050650Sobrien		(match_operand 3 "general_operand" "rmi,ri,rmi,ri")])
801150650Sobrien	      (match_operand:XF 4 "register_operand" "f,f,0,0")
801250650Sobrien	      (match_operand:XF 5 "register_operand" "0,0,f,f")))]
801350650Sobrien  "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT
801450650Sobrien    && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE
801550650Sobrien    && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT"
801650650Sobrien  "#")
801750650Sobrien
801850650Sobrien(define_split
801952296Sobrien  [(set (match_operand:XF 0 "register_operand" "")
802050650Sobrien	(if_then_else:XF (match_operator 1 "comparison_operator" 
802150650Sobrien				[(match_operand 2 "nonimmediate_operand" "")
802250650Sobrien				 (const_int 0)])
802352296Sobrien		      (match_operand:XF 3 "register_operand" "")
802452296Sobrien		      (match_operand:XF 4 "register_operand" "")))]
802550650Sobrien  "TARGET_CMOVE && reload_completed"
802650650Sobrien  [(set (cc0)
802750650Sobrien	(match_dup 2))
802850650Sobrien   (set (match_dup 0)
802950650Sobrien	(if_then_else:XF (match_op_dup 1 [(cc0) (const_int 0)])
803050650Sobrien		      (match_dup 3) (match_dup 4)))]
803150650Sobrien  "")
803250650Sobrien
803350650Sobrien(define_split
803452296Sobrien  [(set (match_operand:XF 0 "register_operand" "")
803550650Sobrien	(if_then_else:XF (match_operator 1 "comparison_operator" 
803650650Sobrien				[(match_operand 2 "nonimmediate_operand" "")
803750650Sobrien				 (match_operand 3 "general_operand" "")])
803852296Sobrien		      (match_operand:XF 4 "register_operand" "")
803952296Sobrien		      (match_operand:XF 5 "register_operand" "")))]
804050650Sobrien  "TARGET_CMOVE && reload_completed"
804150650Sobrien  [(set (cc0) (compare (match_dup 2) (match_dup 3)))
804250650Sobrien   (set (match_dup 0)
804350650Sobrien	(if_then_else:XF (match_op_dup 1 [(cc0) (const_int 0)])
804450650Sobrien		      (match_dup 4) (match_dup 5)))]
804550650Sobrien  "")
804650650Sobrien
804750650Sobrien(define_insn ""
804850650Sobrien  [(set (match_operand:XF 0 "register_operand" "=f,f")
804950650Sobrien	(if_then_else:XF (match_operator 1 "comparison_operator" 
805050650Sobrien				[(cc0) (const_int 0)])
805150650Sobrien		      (match_operand:XF 2 "register_operand" "f,0")
805250650Sobrien		      (match_operand:XF 3 "register_operand" "0,f")))]
805350650Sobrien  "TARGET_CMOVE && reload_completed"
805450650Sobrien  "* return output_fp_conditional_move (which_alternative, operands);")
805550650Sobrien
805650650Sobrien(define_expand "movdicc"
805750650Sobrien  [(set (match_operand:DI 0 "register_operand" "")
805850650Sobrien	(if_then_else:DI (match_operand 1 "comparison_operator" "")
805950650Sobrien			 (match_operand:DI 2 "nonimmediate_operand" "")
806050650Sobrien			 (match_operand:DI 3 "nonimmediate_operand" "")))]
806150650Sobrien  "TARGET_CMOVE"
806250650Sobrien  "
806350650Sobrien{
806450650Sobrien  if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT)
806550650Sobrien    FAIL;
806650650Sobrien
806750650Sobrien  operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]),
806850650Sobrien			GET_MODE (i386_compare_op0),
806950650Sobrien			i386_compare_op0, i386_compare_op1);
807050650Sobrien}")
807150650Sobrien
807250650Sobrien(define_insn ""
807350650Sobrien  [(set (match_operand:DI 0 "register_operand" "=&r,&r,&r,&r")
807450650Sobrien	(if_then_else:DI (match_operator 1 "comparison_operator" 
807550650Sobrien	      [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m")
807650650Sobrien		(match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")])
807750650Sobrien	      (match_operand:DI 4 "nonimmediate_operand" "ro,ro,0,0")
807850650Sobrien	      (match_operand:DI 5 "nonimmediate_operand" "0,0,ro,ro")))]
807950650Sobrien  "TARGET_CMOVE"
808050650Sobrien  "#")
808150650Sobrien
808250650Sobrien(define_insn ""
808350650Sobrien  [(set (match_operand:DI 0 "register_operand" "=&r,&r,&r,&r")
808450650Sobrien	(if_then_else:DI (match_operator 1 "comparison_operator" 
808550650Sobrien	      [(match_operand 2 "nonimmediate_operand" "r,m,r,m")
808650650Sobrien		(match_operand 3 "general_operand" "rmi,ri,rmi,ri")])
808750650Sobrien	      (match_operand:DI 4 "nonimmediate_operand" "ro,ro,0,0")
808850650Sobrien	      (match_operand:DI 5 "nonimmediate_operand" "0,0,ro,ro")))]
808950650Sobrien  "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT"
809050650Sobrien  "#")
809150650Sobrien
809250650Sobrien(define_split
809352296Sobrien  [(set (match_operand:DI 0 "register_operand" "")
809450650Sobrien	(if_then_else:DI (match_operator 1 "comparison_operator" 
809550650Sobrien				[(match_operand 2 "nonimmediate_operand" "")
809650650Sobrien				 (const_int 0)])
809752296Sobrien		      (match_operand:DI 3 "nonimmediate_operand" "")
809852296Sobrien		      (match_operand:DI 4 "nonimmediate_operand" "")))]
809950650Sobrien  "TARGET_CMOVE && reload_completed"
810050650Sobrien  [(set (cc0)
810150650Sobrien	(match_dup 2))
810252296Sobrien   (set (match_dup 5)
810352296Sobrien	(if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)])
810452296Sobrien		      (match_dup 7) (match_dup 9)))
810552296Sobrien   (set (match_dup 6)
810652296Sobrien	(if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)])
810752296Sobrien		      (match_dup 8) (match_dup 10)))]
810852296Sobrien  "split_di (&operands[0], 1, &operands[5], &operands[6]);
810952296Sobrien   split_di (&operands[3], 1, &operands[7], &operands[8]);
811052296Sobrien   split_di (&operands[4], 1, &operands[9], &operands[10]);")
811150650Sobrien
811250650Sobrien(define_split
811352296Sobrien  [(set (match_operand:DI 0 "register_operand" "")
811450650Sobrien	(if_then_else:DI (match_operator 1 "comparison_operator" 
811550650Sobrien				[(match_operand 2 "nonimmediate_operand" "")
811650650Sobrien				 (match_operand 3 "general_operand" "")])
811752296Sobrien		      (match_operand:DI 4 "nonimmediate_operand" "")
811852296Sobrien		      (match_operand:DI 5 "nonimmediate_operand" "")))]
811950650Sobrien  "TARGET_CMOVE && reload_completed"
812050650Sobrien  [(set (cc0) (compare (match_dup 2) (match_dup 3)))
812152296Sobrien   (set (match_dup 6)
812252296Sobrien	(if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)])
812352296Sobrien		      (match_dup 8) (match_dup 10)))
812452296Sobrien   (set (match_dup 7)
812552296Sobrien	(if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)])
812652296Sobrien		      (match_dup 9) (match_dup 11)))]
812752296Sobrien  "split_di (&operands[0], 1, &operands[6], &operands[7]);
812852296Sobrien   split_di (&operands[4], 1, &operands[8], &operands[9]);
812952296Sobrien   split_di (&operands[5], 1, &operands[10], &operands[11]);")
813050650Sobrien
813150650Sobrien(define_insn "strlensi_unroll"
813250650Sobrien  [(set (match_operand:SI 0 "register_operand" "=&r,&r")
813350650Sobrien	(unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "r,r"))
813450650Sobrien		    (match_operand:SI 2 "immediate_operand" "i,i")] 0))
813550650Sobrien   (clobber (match_scratch:SI 3 "=&q,&r"))]
813650650Sobrien  "optimize > 1"
813750650Sobrien  "* return output_strlen_unroll (operands);")
813850650Sobrien
813950650Sobrien;; the only difference between the following patterns is the register preference
814050650Sobrien;; on a pentium using a q-register saves one clock cycle per 4 characters
814150650Sobrien
814250650Sobrien(define_insn "strlensi_unroll4"
814350650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r,r")
814450650Sobrien		   (unspec:SI [(mem:BLK (match_operand:SI 3 "register_operand" "0,0"))
814550650Sobrien			       (match_operand:SI 1 "immediate_operand" "i,i")
814650650Sobrien			       (match_operand:SI 2 "register_operand" "+q,!r")] 0))
814750650Sobrien   (clobber (match_dup 2))]
814850650Sobrien  "(TARGET_USE_ANY_REG && optimize > 1)"
814950650Sobrien  "* return output_strlen_unroll (operands);")
815050650Sobrien
815150650Sobrien(define_insn "strlensi_unroll5"
815250650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
815350650Sobrien		   (unspec:SI [(mem:BLK (match_operand:SI 3 "register_operand" "0"))
815450650Sobrien			       (match_operand:SI 1 "immediate_operand" "i")
815550650Sobrien			       (match_operand:SI 2 "register_operand" "+q")] 0))
815650650Sobrien   (clobber (match_dup 2))]
815750650Sobrien  "(TARGET_USE_Q_REG && optimize > 1)"
815850650Sobrien  "* return output_strlen_unroll (operands);"
815950650Sobrien)
816050650Sobrien
816150650Sobrien(define_insn "allocate_stack_worker"
816250650Sobrien  [(unspec:SI [(match_operand:SI 0 "register_operand" "a")] 3)
816350650Sobrien   (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0)))
816450650Sobrien   (clobber (match_dup 0))]
816550650Sobrien  "TARGET_STACK_PROBE"
816652296Sobrien  "* return AS1(call,__alloca);"
816752296Sobrien  [(set_attr "memory" "none")])
816850650Sobrien
816950650Sobrien(define_expand "allocate_stack"
817050650Sobrien  [(set (match_operand:SI 0 "register_operand" "=r")
817150650Sobrien  	(minus:SI (reg:SI 7) (match_operand:SI 1 "general_operand" "")))
817250650Sobrien   (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 1)))]
817350650Sobrien   "TARGET_STACK_PROBE"
817450650Sobrien  "
817550650Sobrien{
817650650Sobrien#ifdef CHECK_STACK_LIMIT
817750650Sobrien  if (GET_CODE (operands[1]) == CONST_INT
817850650Sobrien      && INTVAL (operands[1]) < CHECK_STACK_LIMIT)
817950650Sobrien    emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx,
818050650Sobrien			   operands[1]));
818150650Sobrien  else 
818250650Sobrien#endif
818350650Sobrien    emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode,
818450650Sobrien							    operands[1])));
818550650Sobrien
818650650Sobrien  emit_move_insn (operands[0], virtual_stack_dynamic_rtx);
818750650Sobrien  DONE;
818850650Sobrien}")
818950650Sobrien
819050650Sobrien(define_expand "exception_receiver"
819150650Sobrien  [(const_int 0)]
819250650Sobrien  "flag_pic"
819350650Sobrien  "
819450650Sobrien{
819556391Sobrien  load_pic_register ();
819656391Sobrien  DONE;
819756391Sobrien}")
819856391Sobrien
819956391Sobrien(define_expand "builtin_setjmp_receiver"
820056391Sobrien  [(label_ref (match_operand 0 "" ""))]
820156391Sobrien  "flag_pic"
820256391Sobrien  "
820356391Sobrien{
820450650Sobrien  load_pic_register (1);
820550650Sobrien  DONE;
820650650Sobrien}")
8207