diff options
Diffstat (limited to 'contrib/gcc/config/i386/i386.md')
-rw-r--r-- | contrib/gcc/config/i386/i386.md | 8195 |
1 files changed, 0 insertions, 8195 deletions
diff --git a/contrib/gcc/config/i386/i386.md b/contrib/gcc/config/i386/i386.md deleted file mode 100644 index b52e2550c4df0..0000000000000 --- a/contrib/gcc/config/i386/i386.md +++ /dev/null @@ -1,8195 +0,0 @@ -; GCC machine description for Intel X86. -;; Copyright (C) 1988, 94, 95, 96, 97, 98, 1999 Free Software Foundation, Inc. -;; Mostly by William Schelter. - -;; This file is part of GNU CC. - -;; GNU CC is free software; you can redistribute it and/or modify -;; it under the terms of the GNU General Public License as published by -;; the Free Software Foundation; either version 2, or (at your option) -;; any later version. - -;; GNU CC is distributed in the hope that it will be useful, -;; but WITHOUT ANY WARRANTY; without even the implied warranty of -;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -;; GNU General Public License for more details. - -;; You should have received a copy of the GNU General Public License -;; along with GNU CC; see the file COPYING. If not, write to -;; the Free Software Foundation, 59 Temple Place - Suite 330, -;; Boston, MA 02111-1307, USA. */ - -;; The original PO technology requires these to be ordered by speed, -;; so that assigner will pick the fastest. - -;; See file "rtl.def" for documentation on define_insn, match_*, et. al. - -;; Macro #define NOTICE_UPDATE_CC in file i386.h handles condition code -;; updates for most instructions. - -;; Macro REG_CLASS_FROM_LETTER in file i386.h defines the register -;; constraint letters. - -;; the special asm out single letter directives following a '%' are: -;; 'z' mov%z1 would be movl, movw, or movb depending on the mode of -;; operands[1]. -;; 'L' Print the opcode suffix for a 32-bit integer opcode. -;; 'W' Print the opcode suffix for a 16-bit integer opcode. -;; 'B' Print the opcode suffix for an 8-bit integer opcode. -;; 'Q' Print the opcode suffix for a 64-bit float opcode. -;; 'S' Print the opcode suffix for a 32-bit float opcode. -;; 'T' Print the opcode suffix for an 80-bit extended real XFmode float opcode. -;; 'J' Print the appropriate jump operand. - -;; 'b' Print the QImode name of the register for the indicated operand. -;; %b0 would print %al if operands[0] is reg 0. -;; 'w' Likewise, print the HImode name of the register. -;; 'k' Likewise, print the SImode name of the register. -;; 'h' Print the QImode name for a "high" register, either ah, bh, ch or dh. -;; 'y' Print "st(0)" instead of "st" as a register. - -;; UNSPEC usage: -;; 0 This is a `scas' operation. The mode of the UNSPEC is always SImode. -;; operand 0 is the memory address to scan. -;; operand 1 is a register containing the value to scan for. The mode -;; of the scas opcode will be the same as the mode of this operand. -;; operand 2 is the known alignment of operand 0. -;; 1 This is a `sin' operation. The mode of the UNSPEC is MODE_FLOAT. -;; operand 0 is the argument for `sin'. -;; 2 This is a `cos' operation. The mode of the UNSPEC is MODE_FLOAT. -;; operand 0 is the argument for `cos'. -;; 3 This is part of a `stack probe' operation. The mode of the UNSPEC is -;; always SImode. operand 0 is the size of the stack allocation. -;; 4 This is the source of a fake SET of the frame pointer which is used to -;; prevent insns referencing it being scheduled across the initial -;; decrement of the stack pointer. -;; 5 This is a `bsf' operation. -;; 6 This is the @GOT offset of a PIC address. -;; 7 This is the @GOTOFF offset of a PIC address. -;; 8 This is a reference to a symbol's @PLT address. - -;; This shadows the processor_type enumeration, so changes must be made -;; to i386.h at the same time. - -(define_attr "type" - "integer,binary,memory,test,compare,fcompare,idiv,imul,lea,fld,fpop,fpdiv,fpmul" - (const_string "integer")) - -(define_attr "memory" "none,load,store" - (cond [(eq_attr "type" "idiv,lea") - (const_string "none") - - (eq_attr "type" "fld") - (const_string "load") - - (eq_attr "type" "test") - (if_then_else (match_operand 0 "memory_operand" "") - (const_string "load") - (const_string "none")) - - (eq_attr "type" "compare,fcompare") - (if_then_else (ior (match_operand 0 "memory_operand" "") - (match_operand 1 "memory_operand" "")) - (const_string "load") - (const_string "none")) - - (and (eq_attr "type" "integer,memory,fpop") - (match_operand 0 "memory_operand" "")) - (const_string "store") - - (and (eq_attr "type" "integer,memory,fpop") - (match_operand 1 "memory_operand" "")) - (const_string "load") - - (and (eq_attr "type" "binary,imul,fpmul,fpdiv") - (ior (match_operand 1 "memory_operand" "") - (match_operand 2 "memory_operand" ""))) - (const_string "load")] - - (const_string "none"))) - -;; Functional units - -; (define_function_unit NAME MULTIPLICITY SIMULTANEITY -; TEST READY-DELAY ISSUE-DELAY [CONFLICT-LIST]) - -; pentiumpro has a reservation station with 5 ports -; port 0 has integer, float add, integer divide, float divide, float -; multiply, and shifter units. -; port 1 has integer, and jump units. -; port 2 has the load address generation unit -; ports 3 and 4 have the store address generation units - -; pentium has two integer pipelines, the main u pipe and the secondary v pipe. -; and a float pipeline - -;; Floating point - -(define_function_unit "fp" 1 0 - (and (eq_attr "type" "fpop,fcompare") (eq_attr "cpu" "i386,i486")) - 5 5) - -(define_function_unit "fp" 1 0 - (and (eq_attr "type" "fpop,fcompare") (eq_attr "cpu" "pentium,pentiumpro")) - 3 0) - -(define_function_unit "fp" 1 0 - (and (eq_attr "type" "fpmul") (eq_attr "cpu" "pentium")) - 7 0) - -(define_function_unit "fp" 1 0 - (and (eq_attr "type" "fpmul") (eq_attr "cpu" "pentiumpro")) - 5 0) - -(define_function_unit "fp" 1 0 - (and (eq_attr "type" "idiv") (eq_attr "cpu" "pentiumpro")) - 10 10) - -(define_function_unit "fp" 1 0 - (and (eq_attr "type" "imul") (eq_attr "cpu" "pentiumpro")) - 6 0) - -(define_function_unit "fp" 1 0 - (eq_attr "type" "fpdiv") - 10 10) - -(define_function_unit "fp" 1 0 - (and (eq_attr "type" "fld") (eq_attr "cpu" "!pentiumpro,k6")) - 1 0) - -;; K6 FPU is not pipelined. -(define_function_unit "fp" 1 0 - (and (eq_attr "type" "fpop,fpmul,fcompare") (eq_attr "cpu" "k6")) - 2 2) - -;; i386 and i486 have one integer unit, which need not be modeled - -(define_function_unit "integer" 2 0 - (and (eq_attr "type" "integer,binary,test,compare,lea") (eq_attr "cpu" "pentium,pentiumpro")) - 1 0) - -(define_function_unit "integer" 2 0 - (and (eq_attr "cpu" "k6") - (and (eq_attr "type" "integer,binary,test,compare") - (eq_attr "memory" "!load"))) - 1 0) - -;; Internally, K6 converts REG OP MEM instructions into a load (2 cycles) -;; and a register operation (1 cycle). -(define_function_unit "integer" 2 0 - (and (eq_attr "cpu" "k6") - (and (eq_attr "type" "integer,binary,test,compare") - (eq_attr "memory" "load"))) - 3 0) - -;; Multiplies use one of the integer units -(define_function_unit "integer" 2 0 - (and (eq_attr "cpu" "pentium") (eq_attr "type" "imul")) - 11 11) - -(define_function_unit "integer" 2 0 - (and (eq_attr "cpu" "k6") (eq_attr "type" "imul")) - 2 2) - -(define_function_unit "integer" 2 0 - (and (eq_attr "cpu" "pentium") (eq_attr "type" "idiv")) - 25 25) - -(define_function_unit "integer" 2 0 - (and (eq_attr "cpu" "k6") (eq_attr "type" "idiv")) - 17 17) - -;; Pentium Pro and K6 have a separate load unit. -(define_function_unit "load" 1 0 - (and (eq_attr "cpu" "pentiumpro") (eq_attr "memory" "load")) - 3 0) - -(define_function_unit "load" 1 0 - (and (eq_attr "cpu" "k6") (eq_attr "memory" "load")) - 2 0) - -;; Pentium Pro and K6 have a separate store unit. -(define_function_unit "store" 1 0 - (and (eq_attr "cpu" "pentiumpro,k6") (eq_attr "memory" "store")) - 1 0) - -;; lea executes in the K6 store unit with 1 cycle latency -(define_function_unit "store" 1 0 - (and (eq_attr "cpu" "k6") (eq_attr "type" "lea")) - 1 0) - - -;; "movl MEM,REG / testl REG,REG" is faster on a 486 than "cmpl $0,MEM". -;; But restricting MEM here would mean that gcc could not remove a redundant -;; test in cases like "incl MEM / je TARGET". -;; -;; We don't want to allow a constant operand for test insns because -;; (set (cc0) (const_int foo)) has no mode information. Such insns will -;; be folded while optimizing anyway. - -;; All test insns have expanders that save the operands away without -;; actually generating RTL. The bCOND or sCOND (emitted immediately -;; after the tstM or cmp) will actually emit the tstM or cmpM. - -;; Processor type -- this attribute must exactly match the processor_type -;; enumeration in i386.h. - -(define_attr "cpu" "i386,i486,pentium,pentiumpro,k6" - (const (symbol_ref "ix86_cpu"))) - -(define_insn "tstsi_1" - [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" "rm"))] - "" - "* -{ - if (REG_P (operands[0])) - return AS2 (test%L0,%0,%0); - - operands[1] = const0_rtx; - return AS2 (cmp%L0,%1,%0); -}" - [(set_attr "type" "test")]) - -(define_expand "tstsi" - [(set (cc0) - (match_operand:SI 0 "nonimmediate_operand" ""))] - "" - " -{ - i386_compare_gen = gen_tstsi_1; - i386_compare_op0 = operands[0]; - i386_compare_op1 = const0_rtx; - DONE; -}") - -(define_insn "tsthi_1" - [(set (cc0) - (match_operand:HI 0 "nonimmediate_operand" "rm"))] - "" - "* -{ - if (REG_P (operands[0])) - return AS2 (test%W0,%0,%0); - - operands[1] = const0_rtx; - return AS2 (cmp%W0,%1,%0); -}" - [(set_attr "type" "test")]) - -(define_expand "tsthi" - [(set (cc0) - (match_operand:HI 0 "nonimmediate_operand" ""))] - "" - " -{ - i386_compare_gen = gen_tsthi_1; - i386_compare_op0 = operands[0]; - i386_compare_op1 = const0_rtx; - DONE; -}") - -(define_insn "tstqi_1" - [(set (cc0) - (match_operand:QI 0 "nonimmediate_operand" "qm"))] - "" - "* -{ - if (REG_P (operands[0])) - return AS2 (test%B0,%0,%0); - - operands[1] = const0_rtx; - return AS2 (cmp%B0,%1,%0); -}" - [(set_attr "type" "test")]) - -(define_expand "tstqi" - [(set (cc0) - (match_operand:QI 0 "nonimmediate_operand" ""))] - "" - " -{ - i386_compare_gen = gen_tstqi_1; - i386_compare_op0 = operands[0]; - i386_compare_op1 = const0_rtx; - DONE; -}") - -(define_insn "tstsf_cc" - [(set (cc0) - (match_operand:SF 0 "register_operand" "f")) - (clobber (match_scratch:HI 1 "=a"))] - "TARGET_80387 && ! TARGET_IEEE_FP" - "* -{ - if (! STACK_TOP_P (operands[0])) - abort (); - - output_asm_insn (\"ftst\", operands); - - if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) - output_asm_insn (AS1 (fstp,%y0), operands); - - return output_fp_cc0_set (insn); -}" - [(set_attr "type" "test")]) - -;; Don't generate tstsf if generating IEEE code, since the `ftst' opcode -;; isn't IEEE compliant. - -(define_expand "tstsf" - [(parallel [(set (cc0) - (match_operand:SF 0 "register_operand" "")) - (clobber (match_scratch:HI 1 ""))])] - "TARGET_80387 && ! TARGET_IEEE_FP" - " -{ - i386_compare_gen = gen_tstsf_cc; - i386_compare_op0 = operands[0]; - i386_compare_op1 = const0_rtx; - DONE; -}") - -(define_insn "tstdf_cc" - [(set (cc0) - (match_operand:DF 0 "register_operand" "f")) - (clobber (match_scratch:HI 1 "=a"))] - "TARGET_80387 && ! TARGET_IEEE_FP" - "* -{ - if (! STACK_TOP_P (operands[0])) - abort (); - - output_asm_insn (\"ftst\", operands); - - if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) - output_asm_insn (AS1 (fstp,%y0), operands); - - return output_fp_cc0_set (insn); -}" - [(set_attr "type" "test")]) - -;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode -;; isn't IEEE compliant. - -(define_expand "tstdf" - [(parallel [(set (cc0) - (match_operand:DF 0 "register_operand" "")) - (clobber (match_scratch:HI 1 ""))])] - "TARGET_80387 && ! TARGET_IEEE_FP" - " -{ - i386_compare_gen = gen_tstdf_cc; - i386_compare_op0 = operands[0]; - i386_compare_op1 = const0_rtx; - DONE; -}") - -(define_insn "tstxf_cc" - [(set (cc0) - (match_operand:XF 0 "register_operand" "f")) - (clobber (match_scratch:HI 1 "=a"))] - "TARGET_80387 && ! TARGET_IEEE_FP" - "* -{ - if (! STACK_TOP_P (operands[0])) - abort (); - - output_asm_insn (\"ftst\", operands); - - if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) - output_asm_insn (AS1 (fstp,%y0), operands); - - return output_fp_cc0_set (insn); -}" - [(set_attr "type" "test")]) - -;; Don't generate tstxf if generating IEEE code, since the `ftst' opcode -;; isn't IEEE compliant. - -(define_expand "tstxf" - [(parallel [(set (cc0) - (match_operand:XF 0 "register_operand" "")) - (clobber (match_scratch:HI 1 ""))])] - "TARGET_80387 && ! TARGET_IEEE_FP" - " -{ - i386_compare_gen = gen_tstxf_cc; - i386_compare_op0 = operands[0]; - i386_compare_op1 = const0_rtx; - DONE; -}") - -;;- compare instructions. See comments above tstM patterns about -;; expansion of these insns. - -(define_insn "cmpsi_1" - [(set (cc0) - (compare (match_operand:SI 0 "nonimmediate_operand" "mr,r") - (match_operand:SI 1 "general_operand" "ri,mr")))] - "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" - "* return AS2 (cmp%L0,%1,%0);" - [(set_attr "type" "compare")]) - -(define_expand "cmpsi" - [(set (cc0) - (compare (match_operand:SI 0 "nonimmediate_operand" "") - (match_operand:SI 1 "general_operand" "")))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[0] = force_reg (SImode, operands[0]); - - i386_compare_gen = gen_cmpsi_1; - i386_compare_op0 = operands[0]; - i386_compare_op1 = operands[1]; - DONE; -}") - -(define_insn "cmphi_1" - [(set (cc0) - (compare (match_operand:HI 0 "nonimmediate_operand" "mr,r") - (match_operand:HI 1 "general_operand" "ri,mr")))] - "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" - "* return AS2 (cmp%W0,%1,%0);" - [(set_attr "type" "compare")]) - -(define_expand "cmphi" - [(set (cc0) - (compare (match_operand:HI 0 "nonimmediate_operand" "") - (match_operand:HI 1 "general_operand" "")))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[0] = force_reg (HImode, operands[0]); - - i386_compare_gen = gen_cmphi_1; - i386_compare_op0 = operands[0]; - i386_compare_op1 = operands[1]; - DONE; -}") - -(define_insn "cmpqi_1" - [(set (cc0) - (compare (match_operand:QI 0 "nonimmediate_operand" "q,mq") - (match_operand:QI 1 "general_operand" "qm,nq")))] - "GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM" - "* return AS2 (cmp%B0,%1,%0);" - [(set_attr "type" "compare")]) - -(define_expand "cmpqi" - [(set (cc0) - (compare (match_operand:QI 0 "nonimmediate_operand" "") - (match_operand:QI 1 "general_operand" "")))] - "" - " -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[0] = force_reg (QImode, operands[0]); - - i386_compare_gen = gen_cmpqi_1; - i386_compare_op0 = operands[0]; - i386_compare_op1 = operands[1]; - DONE; -}") - -;; These implement float point compares. For each of DFmode and -;; SFmode, there is the normal insn, and an insn where the second operand -;; is converted to the desired mode. - -(define_insn "" - [(set (cc0) - (match_operator 2 "VOIDmode_compare_op" - [(match_operand:XF 0 "register_operand" "f") - (match_operand:XF 1 "register_operand" "f")])) - (clobber (match_scratch:HI 3 "=a"))] - "TARGET_80387" - "* return output_float_compare (insn, operands);" - [(set_attr "type" "fcompare")]) - -(define_insn "" - [(set (cc0) - (match_operator 2 "VOIDmode_compare_op" - [(match_operand:XF 0 "register_operand" "f") - (float_extend:XF - (match_operand:DF 1 "nonimmediate_operand" "fm"))])) - (clobber (match_scratch:HI 3 "=a"))] - "TARGET_80387" - "* return output_float_compare (insn, operands);" - [(set_attr "type" "fcompare")]) - -(define_insn "" - [(set (cc0) - (match_operator 2 "VOIDmode_compare_op" - [(float_extend:XF - (match_operand:DF 0 "nonimmediate_operand" "fm")) - (match_operand:XF 1 "register_operand" "f")])) - (clobber (match_scratch:HI 3 "=a"))] - "TARGET_80387" - "* return output_float_compare (insn, operands);" - [(set_attr "type" "fcompare")]) - -(define_insn "" - [(set (cc0) - (match_operator 2 "VOIDmode_compare_op" - [(match_operand:XF 0 "register_operand" "f") - (float_extend:XF - (match_operand:SF 1 "nonimmediate_operand" "fm"))])) - (clobber (match_scratch:HI 3 "=a"))] - "TARGET_80387" - "* return output_float_compare (insn, operands);" - [(set_attr "type" "fcompare")]) - -(define_insn "" - [(set (cc0) - (match_operator 2 "VOIDmode_compare_op" - [(float_extend:XF - (match_operand:SF 0 "nonimmediate_operand" "fm")) - (match_operand:XF 1 "register_operand" "f")])) - (clobber (match_scratch:HI 3 "=a"))] - "TARGET_80387" - "* return output_float_compare (insn, operands);" - [(set_attr "type" "fcompare")]) - -(define_insn "" - [(set (cc0) - (compare:CCFPEQ (match_operand:XF 0 "register_operand" "f") - (match_operand:XF 1 "register_operand" "f"))) - (clobber (match_scratch:HI 2 "=a"))] - "TARGET_80387" - "* return output_float_compare (insn, operands);" - [(set_attr "type" "fcompare")]) - -(define_insn "" - [(set (cc0) - (match_operator 2 "VOIDmode_compare_op" - [(match_operand:DF 0 "nonimmediate_operand" "f,fm") - (match_operand:DF 1 "nonimmediate_operand" "fm,f")])) - (clobber (match_scratch:HI 3 "=a,a"))] - "TARGET_80387 - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "* return output_float_compare (insn, operands);" - [(set_attr "type" "fcompare")]) - -(define_insn "" - [(set (cc0) - (match_operator 2 "VOIDmode_compare_op" - [(match_operand:DF 0 "register_operand" "f") - (float_extend:DF - (match_operand:SF 1 "nonimmediate_operand" "fm"))])) - (clobber (match_scratch:HI 3 "=a"))] - "TARGET_80387" - "* return output_float_compare (insn, operands);" - [(set_attr "type" "fcompare")]) - -(define_insn "" - [(set (cc0) - (match_operator 2 "VOIDmode_compare_op" - [(float_extend:DF - (match_operand:SF 0 "nonimmediate_operand" "fm")) - (match_operand:DF 1 "register_operand" "f")])) - (clobber (match_scratch:HI 3 "=a"))] - "TARGET_80387" - "* return output_float_compare (insn, operands);" - [(set_attr "type" "fcompare")]) - -(define_insn "" - [(set (cc0) - (match_operator 2 "VOIDmode_compare_op" - [(float_extend:DF - (match_operand:SF 0 "register_operand" "f")) - (match_operand:DF 1 "nonimmediate_operand" "fm")])) - (clobber (match_scratch:HI 3 "=a"))] - "TARGET_80387" - "* return output_float_compare (insn, operands);" - [(set_attr "type" "fcompare")]) - -(define_insn "" - [(set (cc0) - (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f") - (match_operand:DF 1 "register_operand" "f"))) - (clobber (match_scratch:HI 2 "=a"))] - "TARGET_80387" - "* return output_float_compare (insn, operands);" - [(set_attr "type" "fcompare")]) - -;; These two insns will never be generated by combine due to the mode of -;; the COMPARE. -;(define_insn "" -; [(set (cc0) -; (compare:CCFPEQ (match_operand:DF 0 "register_operand" "f") -; (float_extend:DF -; (match_operand:SF 1 "register_operand" "f")))) -; (clobber (match_scratch:HI 2 "=a"))] -; "TARGET_80387" -; "* return output_float_compare (insn, operands);") -; -;(define_insn "" -; [(set (cc0) -; (compare:CCFPEQ (float_extend:DF -; (match_operand:SF 0 "register_operand" "f")) -; (match_operand:DF 1 "register_operand" "f"))) -; (clobber (match_scratch:HI 2 "=a"))] -; "TARGET_80387" -; "* return output_float_compare (insn, operands);") - -(define_insn "*cmpsf_cc_1" - [(set (cc0) - (match_operator 2 "VOIDmode_compare_op" - [(match_operand:SF 0 "nonimmediate_operand" "f,fm") - (match_operand:SF 1 "nonimmediate_operand" "fm,f")])) - (clobber (match_scratch:HI 3 "=a,a"))] - "TARGET_80387 - && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)" - "* return output_float_compare (insn, operands);" - [(set_attr "type" "fcompare")]) - -(define_insn "" - [(set (cc0) - (compare:CCFPEQ (match_operand:SF 0 "register_operand" "f") - (match_operand:SF 1 "register_operand" "f"))) - (clobber (match_scratch:HI 2 "=a"))] - "TARGET_80387" - "* return output_float_compare (insn, operands);" - [(set_attr "type" "fcompare")]) - -(define_expand "cmpxf" - [(set (cc0) - (compare (match_operand:XF 0 "register_operand" "") - (match_operand:XF 1 "register_operand" "")))] - "TARGET_80387" - " -{ - i386_compare_gen = gen_cmpxf_cc; - i386_compare_gen_eq = gen_cmpxf_ccfpeq; - i386_compare_op0 = operands[0]; - i386_compare_op1 = operands[1]; - DONE; -}") - -(define_expand "cmpdf" - [(set (cc0) - (compare (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "general_operand" "")))] - "TARGET_80387" - " -{ - i386_compare_gen = gen_cmpdf_cc; - i386_compare_gen_eq = gen_cmpdf_ccfpeq; - i386_compare_op0 = operands[0]; - i386_compare_op1 = (immediate_operand (operands[1], DFmode)) - ? copy_to_mode_reg (DFmode, operands[1]) : operands[1]; - DONE; -}") - -(define_expand "cmpsf" - [(set (cc0) - (compare (match_operand:SF 0 "register_operand" "") - (match_operand:SF 1 "general_operand" "")))] - "TARGET_80387" - " -{ - i386_compare_gen = gen_cmpsf_cc; - i386_compare_gen_eq = gen_cmpsf_ccfpeq; - i386_compare_op0 = operands[0]; - i386_compare_op1 = (immediate_operand (operands[1], SFmode)) - ? copy_to_mode_reg (SFmode, operands[1]) : operands[1]; - DONE; -}") - -(define_expand "cmpxf_cc" - [(parallel [(set (cc0) - (compare (match_operand:XF 0 "register_operand" "") - (match_operand:XF 1 "register_operand" ""))) - (clobber (match_scratch:HI 2 ""))])] - "TARGET_80387" - "") - -(define_expand "cmpxf_ccfpeq" - [(parallel [(set (cc0) - (compare:CCFPEQ (match_operand:XF 0 "register_operand" "") - (match_operand:XF 1 "register_operand" ""))) - (clobber (match_scratch:HI 2 ""))])] - "TARGET_80387" - "") - -(define_expand "cmpdf_cc" - [(parallel [(set (cc0) - (compare (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" ""))) - (clobber (match_scratch:HI 2 ""))])] - "TARGET_80387" - "") - -(define_expand "cmpdf_ccfpeq" - [(parallel [(set (cc0) - (compare:CCFPEQ (match_operand:DF 0 "register_operand" "") - (match_operand:DF 1 "register_operand" ""))) - (clobber (match_scratch:HI 2 ""))])] - "TARGET_80387" - " -{ - if (! register_operand (operands[1], DFmode)) - operands[1] = copy_to_mode_reg (DFmode, operands[1]); -}") - -(define_expand "cmpsf_cc" - [(parallel [(set (cc0) - (compare (match_operand:SF 0 "register_operand" "") - (match_operand:SF 1 "register_operand" ""))) - (clobber (match_scratch:HI 2 ""))])] - "TARGET_80387" - "") - -(define_expand "cmpsf_ccfpeq" - [(parallel [(set (cc0) - (compare:CCFPEQ (match_operand:SF 0 "register_operand" "") - (match_operand:SF 1 "register_operand" ""))) - (clobber (match_scratch:HI 2 ""))])] - "TARGET_80387" - " -{ - if (! register_operand (operands[1], SFmode)) - operands[1] = copy_to_mode_reg (SFmode, operands[1]); -}") - -;; logical compare - -(define_insn "" - [(set (cc0) - (and:SI (match_operand:SI 0 "general_operand" "%ro") - (match_operand:SI 1 "nonmemory_operand" "ri")))] - "" - "* -{ - /* For small integers, we may actually use testb. */ - if (GET_CODE (operands[1]) == CONST_INT - && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) - && (! REG_P (operands[0]) || QI_REG_P (operands[0])) - /* A Pentium test is pairable only with eax. Not with ah or al. */ - && (! REG_P (operands[0]) || REGNO (operands[0]) || !TARGET_PENTIUM - || optimize_size)) - { - /* We may set the sign bit spuriously. */ - - if ((INTVAL (operands[1]) & ~0xff) == 0) - { - cc_status.flags |= CC_NOT_NEGATIVE; - return AS2 (test%B0,%1,%b0); - } - - if ((INTVAL (operands[1]) & ~0xff00) == 0) - { - cc_status.flags |= CC_NOT_NEGATIVE; - operands[1] = GEN_INT (INTVAL (operands[1]) >> 8); - - if (QI_REG_P (operands[0])) - return AS2 (test%B0,%1,%h0); - else - { - operands[0] = adj_offsettable_operand (operands[0], 1); - return AS2 (test%B0,%1,%b0); - } - } - - if (GET_CODE (operands[0]) == MEM - && (INTVAL (operands[1]) & ~0xff0000) == 0) - { - cc_status.flags |= CC_NOT_NEGATIVE; - operands[1] = GEN_INT (INTVAL (operands[1]) >> 16); - operands[0] = adj_offsettable_operand (operands[0], 2); - return AS2 (test%B0,%1,%b0); - } - - if (GET_CODE (operands[0]) == MEM - && (INTVAL (operands[1]) & ~0xff000000) == 0) - { - operands[1] = GEN_INT ((INTVAL (operands[1]) >> 24) & 0xff); - operands[0] = adj_offsettable_operand (operands[0], 3); - return AS2 (test%B0,%1,%b0); - } - } - - if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) - return AS2 (test%L0,%1,%0); - - return AS2 (test%L1,%0,%1); -}" - [(set_attr "type" "compare")]) - -(define_insn "" - [(set (cc0) - (and:HI (match_operand:HI 0 "general_operand" "%ro") - (match_operand:HI 1 "nonmemory_operand" "ri")))] - "" - "* -{ - if (GET_CODE (operands[1]) == CONST_INT - && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) - && (! REG_P (operands[0]) || QI_REG_P (operands[0]))) - { - if ((INTVAL (operands[1]) & 0xff00) == 0) - { - /* ??? This might not be necessary. */ - if (INTVAL (operands[1]) & 0xffff0000) - operands[1] = GEN_INT (INTVAL (operands[1]) & 0xff); - - /* We may set the sign bit spuriously. */ - cc_status.flags |= CC_NOT_NEGATIVE; - return AS2 (test%B0,%1,%b0); - } - - if ((INTVAL (operands[1]) & 0xff) == 0) - { - operands[1] = GEN_INT ((INTVAL (operands[1]) >> 8) & 0xff); - - if (QI_REG_P (operands[0])) - return AS2 (test%B0,%1,%h0); - else - { - operands[0] = adj_offsettable_operand (operands[0], 1); - return AS2 (test%B0,%1,%b0); - } - } - } - - /* use 32-bit test instruction if there are no sign issues */ - if (GET_CODE (operands[1]) == CONST_INT - && !(INTVAL (operands[1]) & ~0x7fff) - && i386_aligned_p (operands[0])) - return AS2 (test%L0,%1,%k0); - - if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) - return AS2 (test%W0,%1,%0); - - return AS2 (test%W1,%0,%1); -}" - [(set_attr "type" "compare")]) - -(define_insn "" - [(set (cc0) - (and:QI (match_operand:QI 0 "nonimmediate_operand" "%qm") - (match_operand:QI 1 "nonmemory_operand" "qi")))] - "" - "* -{ - if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) - return AS2 (test%B0,%1,%0); - - return AS2 (test%B1,%0,%1); -}" - [(set_attr "type" "compare")]) - -;; move instructions. -;; There is one for each machine mode, -;; and each is preceded by a corresponding push-insn pattern -;; (since pushes are not general_operands on the 386). - -(define_insn "" - [(set (match_operand:SI 0 "push_operand" "=<") - (match_operand:SI 1 "nonmemory_operand" "rn"))] - "flag_pic" - "* return AS1 (push%L0,%1);" - [(set_attr "memory" "store")]) - -(define_insn "" - [(set (match_operand:SI 0 "push_operand" "=<") - (match_operand:SI 1 "nonmemory_operand" "ri"))] - "!flag_pic" - "* return AS1 (push%L0,%1);" - [(set_attr "memory" "store")]) - -;; On a 386, it is faster to push MEM directly. - -(define_insn "" - [(set (match_operand:SI 0 "push_operand" "=<") - (match_operand:SI 1 "memory_operand" "m"))] - "TARGET_PUSH_MEMORY" - "* return AS1 (push%L0,%1);" - [(set_attr "type" "memory") - (set_attr "memory" "load")]) - -;; General case of fullword move. - -;; If generating PIC code and operands[1] is a symbolic CONST, emit a -;; move to get the address of the symbolic object from the GOT. - -(define_expand "movsi" - [(set (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "general_operand" ""))] - "" - " -{ - extern int flag_pic; - - if (flag_pic && SYMBOLIC_CONST (operands[1])) - emit_pic_move (operands, SImode); - - /* Don't generate memory->memory moves, go through a register */ - else if (TARGET_MOVE - && no_new_pseudos == 0 - && GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) == MEM) - { - operands[1] = force_reg (SImode, operands[1]); - } -}") - -;; On i486, incl reg is faster than movl $1,reg. - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=g,r,r") - (match_operand:SI 1 "general_operand" "rn,i,m"))] - "((!TARGET_MOVE || GET_CODE (operands[0]) != MEM) - || (GET_CODE (operands[1]) != MEM)) - && flag_pic" - "* -{ - rtx link; - - /* K6: mov reg,0 is slightly faster than xor reg,reg but is 3 bytes - longer. */ - if ((ix86_cpu != PROCESSOR_K6 || optimize_size) - && operands[1] == const0_rtx && REG_P (operands[0])) - return AS2 (xor%L0,%0,%0); - - if (operands[1] == const1_rtx - /* PPRO and K6 prefer mov to inc to reduce dependencies. */ - && (optimize_size || (int)ix86_cpu < (int)PROCESSOR_PENTIUMPRO) - && (link = find_reg_note (insn, REG_WAS_0, 0)) - /* Make sure the insn that stored the 0 is still present. */ - && ! INSN_DELETED_P (XEXP (link, 0)) - && GET_CODE (XEXP (link, 0)) != NOTE - /* Make sure cross jumping didn't happen here. */ - && no_labels_between_p (XEXP (link, 0), insn) - /* Make sure the reg hasn't been clobbered. */ - && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) - /* Fastest way to change a 0 to a 1. */ - return AS1 (inc%L0,%0); - - if (SYMBOLIC_CONST (operands[1])) - return AS2 (lea%L0,%a1,%0); - - return AS2 (mov%L0,%1,%0); -}" - [(set_attr "type" "integer,integer,memory") - (set_attr "memory" "*,*,load")]) - -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=g,r") - (match_operand:SI 1 "general_operand" "ri,m"))] - "((!TARGET_MOVE || GET_CODE (operands[0]) != MEM) - || (GET_CODE (operands[1]) != MEM)) - && !flag_pic" - "* -{ - rtx link; - - /* Use of xor was disabled for AMD K6 as recommended by the Optimization - Manual. My test shows, that this generally hurts the performance, because - mov is longer and takes longer to decode and decoding is the main - bottleneck of K6 when executing GCC code. */ - - if (operands[1] == const0_rtx && REG_P (operands[0])) - return AS2 (xor%L0,%0,%0); - - if (operands[1] == const1_rtx - /* PPRO and K6 prefer mov to inc to reduce dependencies. */ - && (optimize_size || (int)ix86_cpu < (int)PROCESSOR_PENTIUMPRO) - && (link = find_reg_note (insn, REG_WAS_0, 0)) - /* Make sure the insn that stored the 0 is still present. */ - && ! INSN_DELETED_P (XEXP (link, 0)) - && GET_CODE (XEXP (link, 0)) != NOTE - /* Make sure cross jumping didn't happen here. */ - && no_labels_between_p (XEXP (link, 0), insn) - /* Make sure the reg hasn't been clobbered. */ - && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) - /* Fastest way to change a 0 to a 1. */ - return AS1 (inc%L0,%0); - - return AS2 (mov%L0,%1,%0); -}" - [(set_attr "type" "integer,memory") - (set_attr "memory" "*,load")]) - -(define_insn "" - [(set (match_operand:HI 0 "push_operand" "=<") - (match_operand:HI 1 "nonmemory_operand" "ri"))] - "" - "* return AS1 (push%W0,%1);" - [(set_attr "type" "memory") - (set_attr "memory" "store")]) - -(define_insn "" - [(set (match_operand:HI 0 "push_operand" "=<") - (match_operand:HI 1 "memory_operand" "m"))] - "TARGET_PUSH_MEMORY" - "* return AS1 (push%W0,%1);" - [(set_attr "type" "memory") - (set_attr "memory" "load")]) - -;; On i486, an incl and movl are both faster than incw and movw. - -(define_expand "movhi" - [(set (match_operand:HI 0 "general_operand" "") - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - /* Don't generate memory->memory moves, go through a register */ - if (TARGET_MOVE - && no_new_pseudos == 0 - && GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) == MEM) - { - operands[1] = force_reg (HImode, operands[1]); - } -}") - -(define_insn "" - [(set (match_operand:HI 0 "general_operand" "=g,r") - (match_operand:HI 1 "general_operand" "ri,m"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" - "* -{ - rtx link; - if (REG_P (operands[0]) && operands[1] == const0_rtx) - return AS2 (xor%L0,%k0,%k0); - - if (REG_P (operands[0]) && operands[1] == const1_rtx - /* PPRO and K6 prefer mov to inc to reduce dependencies. */ - && (optimize_size || (int)ix86_cpu < (int)PROCESSOR_PENTIUMPRO) - && (link = find_reg_note (insn, REG_WAS_0, 0)) - /* Make sure the insn that stored the 0 is still present. */ - && ! INSN_DELETED_P (XEXP (link, 0)) - && GET_CODE (XEXP (link, 0)) != NOTE - /* Make sure cross jumping didn't happen here. */ - && no_labels_between_p (XEXP (link, 0), insn) - /* Make sure the reg hasn't been clobbered. */ - && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) - /* Fastest way to change a 0 to a 1. */ - return AS1 (inc%L0,%k0); - - if (REG_P (operands[0])) - { - if (i386_aligned_p (operands[1])) - { - operands[1] = i386_sext16_if_const (operands[1]); - return AS2 (mov%L0,%k1,%k0); - } - if (! TARGET_ZERO_EXTEND_WITH_AND) - { - /* movzwl is faster than movw on the Pentium Pro, - * although not as fast as an aligned movl. */ -#ifdef INTEL_SYNTAX - return AS2 (movzx,%1,%k0); -#else - return AS2 (movz%W0%L0,%1,%k0); -#endif - } - } - - return AS2 (mov%W0,%1,%0); -}" - [(set_attr "type" "integer,memory") - (set_attr "memory" "*,load")]) - -(define_expand "movstricthi" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "")) - (match_operand:HI 1 "general_operand" ""))] - "" - " -{ - /* Don't generate memory->memory moves, go through a register */ - if (TARGET_MOVE - && no_new_pseudos == 0 - && GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) == MEM) - { - operands[1] = force_reg (HImode, operands[1]); - } -}") - -(define_insn "" - [(set (strict_low_part (match_operand:HI 0 "general_operand" "+g,r")) - (match_operand:HI 1 "general_operand" "ri,m"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" - "* -{ - rtx link; - - /* Use of xor was disabled for AMD K6 as recommended by the Optimization - Manual. My test shows, that this generally hurts the performance, because - mov is longer and takes longer to decode and decoding is the main - bottleneck of K6 when executing GCC code. */ - - if (operands[1] == const0_rtx && REG_P (operands[0])) - return AS2 (xor%W0,%0,%0); - - if (operands[1] == const1_rtx - /* PPRO and K6 prefer mov to inc to reduce dependencies. */ - && (optimize_size || (int)ix86_cpu < (int)PROCESSOR_PENTIUMPRO) - && (link = find_reg_note (insn, REG_WAS_0, 0)) - /* Make sure the insn that stored the 0 is still present. */ - && ! INSN_DELETED_P (XEXP (link, 0)) - && GET_CODE (XEXP (link, 0)) != NOTE - /* Make sure cross jumping didn't happen here. */ - && no_labels_between_p (XEXP (link, 0), insn) - /* Make sure the reg hasn't been clobbered. */ - && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) - /* Fastest way to change a 0 to a 1. */ - return AS1 (inc%W0,%0); - - return AS2 (mov%W0,%1,%0); -}" - [(set_attr "type" "integer,memory")]) - -;; emit_push_insn when it calls move_by_pieces -;; requires an insn to "push a byte". -;; But actually we use pushw, which has the effect of rounding -;; the amount pushed up to a halfword. -(define_insn "" - [(set (match_operand:QI 0 "push_operand" "=<") - (match_operand:QI 1 "const_int_operand" "n"))] - "" - "* return AS1(push%W0,%1);") - -(define_insn "" - [(set (match_operand:QI 0 "push_operand" "=<") - (match_operand:QI 1 "register_operand" "q"))] - "" - "* -{ - operands[1] = gen_rtx_REG (HImode, REGNO (operands[1])); - return AS1 (push%W0,%1); -}") - -;; On i486, incb reg is faster than movb $1,reg. - -;; ??? Do a recognizer for zero_extract that looks just like this, but reads -;; or writes %ah, %bh, %ch, %dh. - -(define_expand "movqi" - [(set (match_operand:QI 0 "general_operand" "") - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - /* Don't generate memory->memory moves, go through a register */ - if (TARGET_MOVE - && no_new_pseudos == 0 - && GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) == MEM) - { - operands[1] = force_reg (QImode, operands[1]); - } -}") - -(define_insn "" - [(set (match_operand:QI 0 "nonimmediate_operand" "=q,*r,qm") - (match_operand:QI 1 "general_operand" "*g,*rn,qn"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" - "* -{ - rtx link; - - /* movb $0,reg8 is 2 bytes, the same as xorl reg8,reg8. - It is at least as fast as xor on any processor except a Pentium. */ - - if (operands[1] == const1_rtx - && TARGET_PENTIUM - && (link = find_reg_note (insn, REG_WAS_0, 0)) - /* Make sure the insn that stored the 0 is still present. */ - && ! INSN_DELETED_P (XEXP (link, 0)) - && GET_CODE (XEXP (link, 0)) != NOTE - /* Make sure cross jumping didn't happen here. */ - && no_labels_between_p (XEXP (link, 0), insn) - /* Make sure the reg hasn't been clobbered. */ - && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) - { - /* Fastest way to change a 0 to a 1. - If inc%B0 isn't allowed, use inc%L0. */ - if (NON_QI_REG_P (operands[0])) - return AS1 (inc%L0,%k0); - else - return AS1 (inc%B0,%0); - } - - /* If mov%B0 isn't allowed for one of these regs, use mov%L0. */ - if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1])) - return (AS2 (mov%L0,%k1,%k0)); - - return (AS2 (mov%B0,%1,%0)); -}") - -;; If it becomes necessary to support movstrictqi into %esi or %edi, -;; use the insn sequence: -;; -;; shrdl $8,srcreg,dstreg -;; rorl $24,dstreg -;; -;; If operands[1] is a constant, then an andl/orl sequence would be -;; faster. - -(define_expand "movstrictqi" - [(set (strict_low_part (match_operand:QI 0 "general_operand" "")) - (match_operand:QI 1 "general_operand" ""))] - "" - " -{ - /* Don't generate memory->memory moves, go through a register */ - if (TARGET_MOVE - && no_new_pseudos == 0 - && GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) == MEM) - { - operands[1] = force_reg (QImode, operands[1]); - } -}") - -(define_insn "" - [(set (strict_low_part (match_operand:QI 0 "nonimmediate_operand" "+qm,q")) - (match_operand:QI 1 "general_operand" "*qn,m"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" - "* -{ - rtx link; - - /* movb $0,reg8 is 2 bytes, the same as xorl reg8,reg8. */ - - if (operands[1] == const1_rtx - && TARGET_PENTIUM - && ! NON_QI_REG_P (operands[0]) - && (link = find_reg_note (insn, REG_WAS_0, 0)) - /* Make sure the insn that stored the 0 is still present. */ - && ! INSN_DELETED_P (XEXP (link, 0)) - && GET_CODE (XEXP (link, 0)) != NOTE - /* Make sure cross jumping didn't happen here. */ - && no_labels_between_p (XEXP (link, 0), insn) - /* Make sure the reg hasn't been clobbered. */ - && ! reg_set_between_p (operands[0], XEXP (link, 0), insn)) - /* Fastest way to change a 0 to a 1. */ - return AS1 (inc%B0,%0); - - /* If mov%B0 isn't allowed for one of these regs, use mov%L0. */ - if (NON_QI_REG_P (operands[0]) || NON_QI_REG_P (operands[1])) - { - abort (); - return (AS2 (mov%L0,%k1,%k0)); - } - - return AS2 (mov%B0,%1,%0); -}") - -(define_insn "movsf_push" - [(set (match_operand:SF 0 "push_operand" "=<,<") - (match_operand:SF 1 "general_operand" "*rfF,m"))] - "TARGET_PUSH_MEMORY || GET_CODE (operands[1]) != MEM - || reload_in_progress || reload_completed" - "* -{ - if (STACK_REG_P (operands[1])) - { - rtx xops[3]; - - if (! STACK_TOP_P (operands[1])) - abort (); - - xops[0] = AT_SP (SFmode); - xops[1] = GEN_INT (4); - xops[2] = stack_pointer_rtx; - - output_asm_insn (AS2 (sub%L2,%1,%2), xops); - - if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) - output_asm_insn (AS1 (fstp%S0,%0), xops); - else - output_asm_insn (AS1 (fst%S0,%0), xops); - - RET; - } - - return AS1 (push%L0,%1); -}") - -(define_split - [(set (match_operand:SF 0 "push_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "reload_completed && STACK_REG_P (operands[1])" - [(set (reg:SI 7) - (minus:SI (reg:SI 7) (const_int 4))) - (set (mem:SF (reg:SI 7)) - (match_dup 1))] - "") - -(define_expand "movsf" - [(set (match_operand:SF 0 "general_operand" "") - (match_operand:SF 1 "general_operand" ""))] - "" - " -{ - /* Don't generate memory->memory moves, go through a register */ - if (TARGET_MOVE - && no_new_pseudos == 0 - && GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) == MEM) - { - operands[1] = force_reg (SFmode, operands[1]); - } - - /* If we are loading a floating point constant that isn't 0 or 1 - into a register, force the value to memory now, since we'll - get better code out the back end. */ - else if ((reload_in_progress | reload_completed) == 0 - && GET_CODE (operands[0]) != MEM - && GET_CODE (operands[1]) == CONST_DOUBLE - && !standard_80387_constant_p (operands[1])) - { - operands[1] = validize_mem (force_const_mem (SFmode, operands[1])); - } -}") - -;; For the purposes of regclass, prefer FLOAT_REGS. -(define_insn "" - [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,!*r,!m") - (match_operand:SF 1 "general_operand" "fmG,f,*rmF,*rF"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" - "* -{ - int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; - - /* First handle a `pop' insn or a `fld %st(0)' */ - - if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1])) - { - if (stack_top_dies) - return AS1 (fstp,%y0); - else - return AS1 (fld,%y0); - } - - /* Handle other kinds of writes from the 387 */ - - if (STACK_TOP_P (operands[1])) - { - if (stack_top_dies) - return AS1 (fstp%z0,%y0); - else - return AS1 (fst%z0,%y0); - } - - /* Handle other kinds of reads to the 387 */ - - if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE) - return output_move_const_single (operands); - - if (STACK_TOP_P (operands[0])) - return AS1 (fld%z1,%y1); - - /* Handle all SFmode moves not involving the 387 */ - - return singlemove_string (operands); -}" - [(set_attr "type" "fld")]) - - -(define_insn "swapsf" - [(set (match_operand:SF 0 "register_operand" "f") - (match_operand:SF 1 "register_operand" "f")) - (set (match_dup 1) - (match_dup 0))] - "" - "* -{ - if (STACK_TOP_P (operands[0])) - return AS1 (fxch,%1); - else - return AS1 (fxch,%0); -}") - - -(define_insn "movdf_push" - [(set (match_operand:DF 0 "push_operand" "=<,<") - (match_operand:DF 1 "general_operand" "*rfF,o"))] - "TARGET_PUSH_MEMORY || GET_CODE (operands[1]) != MEM - || reload_in_progress || reload_completed" - "* -{ - if (STACK_REG_P (operands[1])) - { - rtx xops[3]; - - xops[0] = AT_SP (DFmode); - xops[1] = GEN_INT (8); - xops[2] = stack_pointer_rtx; - - output_asm_insn (AS2 (sub%L2,%1,%2), xops); - - if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) - output_asm_insn (AS1 (fstp%Q0,%0), xops); - else - output_asm_insn (AS1 (fst%Q0,%0), xops); - - RET; - } - - if (which_alternative == 1) - return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 0, 0); - - return output_move_double (operands); -}") - -(define_split - [(set (match_operand:DF 0 "push_operand" "") - (match_operand:DF 1 "register_operand" ""))] - "reload_completed && STACK_REG_P (operands[1])" - [(set (reg:SI 7) - (minus:SI (reg:SI 7) (const_int 8))) - (set (mem:DF (reg:SI 7)) - (match_dup 1))] - "") - -(define_expand "movdf" - [(set (match_operand:DF 0 "general_operand" "") - (match_operand:DF 1 "general_operand" ""))] - "" - " -{ - /* Don't generate memory->memory moves, go through a register */ - if (TARGET_MOVE - && no_new_pseudos == 0 - && GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) == MEM) - { - operands[1] = force_reg (DFmode, operands[1]); - } - - /* If we are loading a floating point constant that isn't 0 or 1 into a - register, indicate we need the pic register loaded. This could be - optimized into stores of constants if the target eventually moves to - memory, but better safe than sorry. */ - else if ((reload_in_progress | reload_completed) == 0 - && GET_CODE (operands[0]) != MEM - && GET_CODE (operands[1]) == CONST_DOUBLE - && !standard_80387_constant_p (operands[1])) - { - operands[1] = validize_mem (force_const_mem (DFmode, operands[1])); - } -}") - -;; For the purposes of regclass, prefer FLOAT_REGS. -(define_insn "" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,!*r,!o") - (match_operand:DF 1 "general_operand" "fmG,f,*roF,*rF"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) - || (GET_CODE (operands[1]) != MEM)" - "* -{ - int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; - - /* First handle a `pop' insn or a `fld %st(0)' */ - - if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1])) - { - if (stack_top_dies) - return AS1 (fstp,%y0); - else - return AS1 (fld,%y0); - } - - /* Handle other kinds of writes from the 387 */ - - if (STACK_TOP_P (operands[1])) - { - if (stack_top_dies) - return AS1 (fstp%z0,%y0); - else - return AS1 (fst%z0,%y0); - } - - /* Handle other kinds of reads to the 387 */ - - if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE) - return output_move_const_single (operands); - - if (STACK_TOP_P (operands[0])) - return AS1 (fld%z1,%y1); - - /* Handle all DFmode moves not involving the 387 */ - - return output_move_double (operands); -}" - [(set_attr "type" "fld")]) - - - -(define_insn "swapdf" - [(set (match_operand:DF 0 "register_operand" "f") - (match_operand:DF 1 "register_operand" "f")) - (set (match_dup 1) - (match_dup 0))] - "" - "* -{ - if (STACK_TOP_P (operands[0])) - return AS1 (fxch,%1); - else - return AS1 (fxch,%0); -}") - -(define_insn "movxf_push" - [(set (match_operand:XF 0 "push_operand" "=<,<") - (match_operand:XF 1 "general_operand" "*rfF,o"))] - "TARGET_PUSH_MEMORY || GET_CODE (operands[1]) != MEM - || reload_in_progress || reload_completed" - "* -{ - if (STACK_REG_P (operands[1])) - { - rtx xops[3]; - - xops[0] = AT_SP (XFmode); - xops[1] = GEN_INT (12); - xops[2] = stack_pointer_rtx; - - output_asm_insn (AS2 (sub%L2,%1,%2), xops); - - output_asm_insn (AS1 (fstp%T0,%0), xops); - if (! find_regno_note (insn, REG_DEAD, FIRST_STACK_REG)) - output_asm_insn (AS1 (fld%T0,%0), xops); - - RET; - } - - if (which_alternative == 1) - return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 0, 0); - - return output_move_double (operands); - }") - -(define_split - [(set (match_operand:XF 0 "push_operand" "") - (match_operand:XF 1 "register_operand" ""))] - "reload_completed && STACK_REG_P (operands[1])" - [(set (reg:SI 7) - (minus:SI (reg:SI 7) (const_int 12))) - (set (mem:XF (reg:SI 7)) - (match_dup 1))] - "") - -(define_expand "movxf" - [(set (match_operand:XF 0 "general_operand" "") - (match_operand:XF 1 "general_operand" ""))] - "" - " -{ - /* Don't generate memory->memory moves, go through a register */ - if (TARGET_MOVE - && no_new_pseudos == 0 - && GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) == MEM) - { - operands[1] = force_reg (XFmode, operands[1]); - } - - /* If we are loading a floating point constant that isn't 0 or 1 - into a register, indicate we need the pic register loaded. This could - be optimized into stores of constants if the target eventually moves - to memory, but better safe than sorry. */ - else if ((reload_in_progress | reload_completed) == 0 - && GET_CODE (operands[0]) != MEM - && GET_CODE (operands[1]) == CONST_DOUBLE - && !standard_80387_constant_p (operands[1])) - { - operands[1] = validize_mem (force_const_mem (XFmode, operands[1])); - } -}") - - -(define_insn "" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,!*r,!o") - (match_operand:XF 1 "general_operand" "fmG,f,*roF,*rF"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) - || (GET_CODE (operands[1]) != MEM)" - "* -{ - int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; - - /* First handle a `pop' insn or a `fld %st(0)' */ - - if (STACK_TOP_P (operands[0]) && STACK_TOP_P (operands[1])) - { - if (stack_top_dies) - return AS1 (fstp,%y0); - else - return AS1 (fld,%y0); - } - - /* Handle other kinds of writes from the 387 */ - - if (STACK_TOP_P (operands[1])) - { - output_asm_insn (AS1 (fstp%z0,%y0), operands); - if (! stack_top_dies) - return AS1 (fld%z0,%y0); - - RET; - } - - /* Handle other kinds of reads to the 387 */ - - if (STACK_TOP_P (operands[0]) && GET_CODE (operands[1]) == CONST_DOUBLE) - return output_move_const_single (operands); - - if (STACK_TOP_P (operands[0])) - return AS1 (fld%z1,%y1); - - /* Handle all XFmode moves not involving the 387 */ - - return output_move_double (operands); -}") - -(define_insn "swapxf" - [(set (match_operand:XF 0 "register_operand" "f") - (match_operand:XF 1 "register_operand" "f")) - (set (match_dup 1) - (match_dup 0))] - "" - "* -{ - if (STACK_TOP_P (operands[0])) - return AS1 (fxch,%1); - else - return AS1 (fxch,%0); -}") - -(define_insn "" - [(set (match_operand:DI 0 "push_operand" "=<") - (match_operand:DI 1 "general_operand" "riF"))] - "" - "* return output_move_double (operands);") - -(define_insn "" - [(set (match_operand:DI 0 "push_operand" "=<") - (match_operand:DI 1 "memory_operand" "o"))] - "TARGET_PUSH_MEMORY" - "* return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode),0,0);") - -(define_expand "movdi" - [(set (match_operand:DI 0 "general_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "" - " -{ - /* Don't generate memory->memory moves, go through a register */ - if (TARGET_MOVE - && no_new_pseudos == 0 - && GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) == MEM) - { - operands[1] = force_reg (DImode, operands[1]); - } -}") - -(define_insn "" - [(set (match_operand:DI 0 "general_operand" "=g,r") - (match_operand:DI 1 "general_operand" "riF,m"))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) - || (GET_CODE (operands[1]) != MEM)" - "* return output_move_double (operands);" - [(set_attr "type" "integer,memory") - (set_attr "memory" "*,load")]) - -(define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (match_operand:DI 1 "general_operand" ""))] - "reload_completed - && (offsettable_memref_p (operands[0]) - || nonmemory_operand (operands[0], DImode)) - && (offsettable_memref_p (operands[1]) - || nonmemory_operand (operands[1], DImode)) - && (! reg_overlap_mentioned_p (gen_lowpart (SImode, operands[0]), - operands[1]) - || ! reg_overlap_mentioned_p (gen_highpart (SImode, operands[0]), - operands[1]))" - [(set (match_dup 2) - (match_dup 4)) - (set (match_dup 3) - (match_dup 5))] - " -{ - split_di (&operands[0], 1, &operands[2], &operands[3]); - split_di (&operands[1], 1, &operands[4], &operands[5]); - - if (reg_overlap_mentioned_p (operands[2], operands[1])) - { - rtx tmp; - - tmp = operands[2]; - operands[2] = operands[3]; - operands[3] = tmp; - - tmp = operands[4]; - operands[4] = operands[5]; - operands[5] = tmp; - } -}") - -;;- conversion instructions -;;- NONE - -;;- zero extension instructions -;; See comments by `andsi' for when andl is faster than movzx. - -(define_expand "zero_extendhisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] - "" - "") - -;; When optimizing for the PPro/PII or code size, always use movzwl. -;; We want to use a different pattern so we can use different constraints -;; than the generic pattern. -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))] - "(optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO)" - "* return AS2 (movz%W0%L0,%1,%0);") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,&r,?r") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,rm,rm")))] - "! (optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO)" - "* - { - rtx xops[2]; - - if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0) - && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1])) - { - xops[0] = operands[0]; - xops[1] = GEN_INT (0xffff); - output_asm_insn (AS2 (and%L0,%1,%k0), xops); - RET; - } - if (TARGET_ZERO_EXTEND_WITH_AND && !reg_overlap_mentioned_p (operands[0], operands[1])) - { - output_asm_insn (AS2 (xor%L0,%0,%0),operands); - output_asm_insn (AS2 (mov%W0,%1,%w0),operands); - RET; - } - - if (TARGET_ZERO_EXTEND_WITH_AND) - { - xops[0] = operands[0]; - xops[1] = GEN_INT (0xffff); - if (i386_aligned_p (operands[1])) - output_asm_insn (AS2 (mov%L0,%k1,%k0),operands); - else - output_asm_insn (AS2 (mov%W0,%1,%w0),operands); - output_asm_insn (AS2 (and%L0,%1,%k0), xops); - RET; - } - -#ifdef INTEL_SYNTAX - return AS2 (movzx,%1,%0); -#else - return AS2 (movz%W0%L0,%1,%0); -#endif -}") - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "")))] - "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && !reg_overlap_mentioned_p (operands[0], operands[1])" - [(set (match_dup 0) - (const_int 0)) - (set (strict_low_part (match_dup 2)) - (match_dup 1))] - "operands[2] = gen_rtx_REG (HImode, true_regnum (operands[0]));") - - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:HI 1 "memory_operand" "")))] - "reload_completed && TARGET_ZERO_EXTEND_WITH_AND && reg_overlap_mentioned_p (operands[0], operands[1])" - [(set (strict_low_part (match_dup 2)) - (match_dup 1)) - (set (match_dup 0) - (and:SI (match_dup 0) - (const_int 65535)))] - "operands[2] = gen_rtx_REG (HImode, true_regnum (operands[0]));") - -(define_expand "zero_extendqihi2" - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))] - "optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO" - - "* return AS2 (movz%B0%W0,%1,%0);") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=q,&q,?r") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))] - "! (optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO)" - "* - { - rtx xops[2]; - - if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0) - && REG_P (operands[1]) - && REGNO (operands[0]) == REGNO (operands[1])) - { - xops[0] = operands[0]; - xops[1] = GEN_INT (0xff); - output_asm_insn (AS2 (and%L0,%1,%k0), xops); - RET; - } - if (TARGET_ZERO_EXTEND_WITH_AND && QI_REG_P (operands[0])) - { - if(!reg_overlap_mentioned_p(operands[0],operands[1])) - { - output_asm_insn (AS2 (xor%L0,%k0,%k0), operands); - output_asm_insn (AS2 (mov%B0,%1,%b0), operands); - } - else - { - xops[0] = operands[0]; - xops[1] = GEN_INT (0xff); - output_asm_insn (AS2 (mov%B0,%1,%b0),operands); - output_asm_insn (AS2 (and%L0,%1,%k0), xops); - } - RET; - } - -#ifdef INTEL_SYNTAX - return AS2 (movzx,%1,%0); -#else - return AS2 (movz%B0%W0,%1,%0); -#endif -}") - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "")))] - "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND - && !reg_overlap_mentioned_p (operands[0], operands[1])" - [(set (match_dup 0) - (const_int 0)) - (set (strict_low_part (match_dup 2)) - (match_dup 1))] - "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));") - - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "memory_operand" "")))] - "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND - && reg_overlap_mentioned_p (operands[0], operands[1])" - [(set (strict_low_part (match_dup 2)) - (match_dup 1)) - (set (match_dup 0) - (and:HI (match_dup 0) - (const_int 255)))] - "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));") - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (zero_extend:HI (match_operand:QI 1 "register_operand" "")))] - "reload_completed && TARGET_ZERO_EXTEND_WITH_AND" - [(set (match_dup 0) - (match_dup 2)) - (set (match_dup 0) - (and:HI (match_dup 0) - (const_int 255)))] - "if (GET_CODE (operands[1]) == SUBREG && SUBREG_WORD (operands[1]) == 0) - operands[1] = SUBREG_REG (operands[1]); - if (GET_CODE (operands[0]) != REG || GET_CODE (operands[1]) != REG - || REGNO (operands[0]) == REGNO (operands[1])) - FAIL; - operands[2] = gen_rtx_REG (HImode, REGNO (operands[1]));") - -(define_expand "zero_extendqisi2" - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] - "" - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))] - "optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO" - "* return AS2 (movz%B0%L0,%1,%0);") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=q,&q,?r") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))] - "! (optimize_size || (int)ix86_cpu == (int)PROCESSOR_PENTIUMPRO)" - "* - { - rtx xops[2]; - - if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0) - && REG_P (operands[1]) - && REGNO (operands[0]) == REGNO (operands[1])) - { - xops[0] = operands[0]; - xops[1] = GEN_INT (0xff); - output_asm_insn (AS2 (and%L0,%1,%k0), xops); - RET; - } - if (TARGET_ZERO_EXTEND_WITH_AND && QI_REG_P (operands[0])) - { - if(!reg_overlap_mentioned_p (operands[0], operands[1])) - { - output_asm_insn (AS2 (xor%L0,%0,%0),operands); - output_asm_insn (AS2 (mov%B0,%1,%b0),operands); - } - else - { - xops[0] = operands[0]; - xops[1] = GEN_INT (0xff); - output_asm_insn (AS2 (mov%B0,%1,%b0), operands); - output_asm_insn (AS2 (and%L0,%1,%k0), xops); - } - RET; - } - - if (TARGET_ZERO_EXTEND_WITH_AND && GET_CODE (operands[1]) == REG) - { - xops[0] = operands[0]; - xops[1] = GEN_INT (0xff); - operands[1] = gen_rtx_REG (SImode, REGNO (operands[1])); - output_asm_insn (AS2 (mov%L0,%1,%0), operands); - output_asm_insn (AS2 (and%L0,%1,%k0), xops); - RET; - } - -#ifdef INTEL_SYNTAX - return AS2 (movzx,%1,%0); -#else - return AS2 (movz%B0%L0,%1,%0); -#endif -}") - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "")))] - "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND - && !reg_overlap_mentioned_p (operands[0], operands[1])" - [(set (match_dup 0) - (const_int 0)) - (set (strict_low_part (match_dup 2)) - (match_dup 1))] - "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));") - - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "memory_operand" "")))] - "reload_completed && QI_REG_P (operands[0]) && TARGET_ZERO_EXTEND_WITH_AND - && reg_overlap_mentioned_p (operands[0], operands[1])" - [(set (strict_low_part (match_dup 2)) - (match_dup 1)) - (set (match_dup 0) - (and:SI (match_dup 0) - (const_int 255)))] - "operands[2] = gen_rtx_REG (QImode, REGNO (operands[0]));") - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (zero_extend:SI (match_operand:QI 1 "register_operand" "")))] - "reload_completed && TARGET_ZERO_EXTEND_WITH_AND - && ! reg_overlap_mentioned_p (operands[0], operands[1])" - [(set (match_dup 0) - (match_dup 2)) - (set (match_dup 0) - (and:SI (match_dup 0) - (const_int 255)))] - "operands[2] = gen_rtx_REG (SImode, true_regnum (operands[1]));") - -(define_insn "zero_extendsidi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?*o") - (zero_extend:DI (match_operand:SI 1 "general_operand" "0,rm,r")))] - "" - "#") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (zero_extend:DI (match_operand:SI 1 "register_operand" "")))] - "reload_completed && true_regnum (operands[0]) == true_regnum (operands[1])" - [(set (match_dup 4) (const_int 0))] - "split_di (&operands[0], 1, &operands[3], &operands[4]);") - -(define_split - [(set (match_operand:DI 0 "nonimmediate_operand" "") - (zero_extend:DI (match_operand:SI 1 "general_operand" "")))] - "reload_completed" - [(set (match_dup 3) (match_dup 1)) - (set (match_dup 4) (const_int 0))] - "split_di (&operands[0], 1, &operands[3], &operands[4]);") - -;;- sign extension instructions - -(define_insn "extendsidi2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=A,?r,?Ar,*o") - (sign_extend:DI (match_operand:SI 1 "register_operand" "0,0,r,*r"))) - (clobber (match_scratch:SI 2 "=X,X,X,&r"))] - "" - "#") - -;; Extend to memory case when source register does die. -(define_split - [(set (match_operand:DI 0 "memory_operand" "") - (sign_extend:DI (match_operand:SI 1 "register_operand" ""))) - (clobber (match_operand:SI 2 "register_operand" ""))] - "(flow2_completed - && dead_or_set_p (insn, operands[1]) - && !reg_mentioned_p (operands[1], operands[0]))" - [(set (match_dup 3) (match_dup 1)) - (set (match_dup 1) (ashiftrt:SI (match_dup 1) (const_int 31))) - (set (match_dup 4) (match_dup 1))] - "split_di (&operands[0], 1, &operands[3], &operands[4]);") - -;; Extend to memory case when source register does not die. -(define_split - [(set (match_operand:DI 0 "memory_operand" "") - (sign_extend:DI (match_operand:SI 1 "register_operand" ""))) - (clobber (match_operand:SI 2 "register_operand" ""))] - "flow2_completed" - [(const_int 0)] - " -{ - split_di (&operands[0], 1, &operands[3], &operands[4]); - - emit_move_insn (operands[3], operands[1]); - - /* Generate a cltd if possible and doing so it profitable. */ - if (true_regnum (operands[1]) == 0 - && true_regnum (operands[2]) == 1 - && (optimize_size || !TARGET_PENTIUM)) - { - emit_insn (gen_ashrsi3_31 (operands[2], operands[1])); - } - else - { - emit_move_insn (operands[2], operands[1]); - emit_insn (gen_ashrsi3_31 (operands[2], operands[2])); - } - emit_move_insn (operands[4], operands[2]); - DONE; -}") - -;; Extend to register case. Optimize case where source and destination -;; registers match and cases where we can use cltd. -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (sign_extend:DI (match_operand:SI 1 "register_operand" ""))) - (clobber (match_scratch:SI 2 ""))] - "reload_completed" - [(const_int 0)] - " -{ - split_di (&operands[0], 1, &operands[3], &operands[4]); - - if (true_regnum (operands[3]) != true_regnum (operands[1])) - emit_move_insn (operands[3], operands[1]); - - /* Generate a cltd if possible and doing so it profitable. */ - if (true_regnum (operands[3]) == 0 - && (optimize_size || !TARGET_PENTIUM)) - { - emit_insn (gen_ashrsi3_31 (operands[4], operands[3])); - DONE; - } - - if (true_regnum (operands[4]) != true_regnum (operands[1])) - emit_move_insn (operands[4], operands[1]); - - emit_insn (gen_ashrsi3_31 (operands[4], operands[4])); - DONE; -}") - -;; Note that the i386 programmers' manual says that the opcodes -;; are named movsx..., but the assembler on Unix does not accept that. -;; We use what the Unix assembler expects. - -(define_insn "extendhisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))] - "" - "* -{ - if (REGNO (operands[0]) == 0 - && REG_P (operands[1]) && REGNO (operands[1]) == 0 - && (optimize_size || ix86_cpu != PROCESSOR_K6)) -#ifdef INTEL_SYNTAX - return \"cwde\"; -#else - return \"cwtl\"; -#endif - -#ifdef INTEL_SYNTAX - return AS2 (movsx,%1,%0); -#else - return AS2 (movs%W0%L0,%1,%0); -#endif -}") - -(define_insn "extendqihi2" - [(set (match_operand:HI 0 "register_operand" "=r") - (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))] - "" - "* -{ - if (REGNO (operands[0]) == 0 - && REG_P (operands[1]) && REGNO (operands[1]) == 0 - && (optimize_size || ix86_cpu != PROCESSOR_K6)) - return \"cbtw\"; - -#ifdef INTEL_SYNTAX - return AS2 (movsx,%1,%0); -#else - return AS2 (movs%B0%W0,%1,%0); -#endif -}") - -(define_insn "extendqisi2" - [(set (match_operand:SI 0 "register_operand" "=r") - (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))] - "" - "* -{ -#ifdef INTEL_SYNTAX - return AS2 (movsx,%1,%0); -#else - return AS2 (movs%B0%L0,%1,%0); -#endif -}") - - -;; Truncation of long long -> 32 bit - -(define_expand "truncdisi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m") - (truncate:SI (match_operand:DI 1 "nonimmediate_operand" "ro,r")))] - "" - " -{ - /* Don't generate memory->memory moves, go through a register */ - if (TARGET_MOVE - && (reload_in_progress | reload_completed) == 0 - && GET_CODE (operands[0]) == MEM - && GET_CODE (operands[1]) == MEM) - { - rtx target = gen_reg_rtx (SImode); - emit_insn (gen_truncdisi2 (target, operands[1])); - emit_move_insn (operands[0], target); - DONE; - } -}") - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m") - (truncate:SI (match_operand:DI 1 "nonimmediate_operand" "ro,r")))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" - "* -{ - rtx low[2], high[2], xops[2]; - - split_di (&operands[1], 1, low, high); - xops[0] = operands[0]; - xops[1] = low[0]; - if (!rtx_equal_p (xops[0], xops[1])) - output_asm_insn (AS2 (mov%L0,%1,%0), xops); - - RET; -}") - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,m") - (truncate:SI (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r") - (const_int 32))))] - "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)" - "* -{ - rtx low[2], high[2], xops[2]; - - split_di (&operands[1], 1, low, high); - xops[0] = operands[0]; - xops[1] = high[0]; - if (!rtx_equal_p (xops[0], xops[1])) - output_asm_insn (AS2 (mov%L0,%1,%0), xops); - - RET; -}") - - - -;; Conversions between float and double. - -(define_expand "extendsfdf2" - [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "") - (float_extend:DF - (match_operand:SF 1 "nonimmediate_operand" ""))) - (clobber (match_dup 2)) - (clobber (match_dup 3))])] - "TARGET_80387" - " -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[1] = force_reg (SFmode, operands[1]); - - operands[2] = assign_386_stack_local (SFmode, 0); - operands[3] = assign_386_stack_local (DFmode, 0); -}") - -(define_insn "" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,!f,!*r") - (float_extend:DF - (match_operand:SF 1 "nonimmediate_operand" "fm,f,*r,f"))) - (clobber (match_operand:SF 2 "memory_operand" "m,m,m,m")) - (clobber (match_operand:DF 3 "memory_operand" "m,m,m,o"))] - "TARGET_80387 && (GET_CODE (operands[0]) != MEM - || GET_CODE (operands[1]) != MEM)" - "* -{ - output_float_extend (insn, operands); - return \"\"; -}" - [(set_attr "type" "fld,fpop,fld,fpop")]) - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (float_extend:DF (match_operand:SF 1 "register_operand" ""))) - (clobber (match_operand:SF 2 "memory_operand" "")) - (clobber (match_operand:DF 3 "memory_operand" ""))] - "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[1])" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 0) - (float_extend:DF (match_dup 2)))] - "") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (float_extend:DF (match_operand:SF 1 "register_operand" ""))) - (clobber (match_operand:SF 2 "memory_operand" "")) - (clobber (match_operand:DF 3 "memory_operand" ""))] - "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[0])" - [(set (match_dup 3) - (float_extend:DF (match_dup 1))) - (set (match_dup 0) - (match_dup 3))] - "") - -(define_split - [(set (match_operand:DF 0 "nonimmediate_operand" "") - (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" ""))) - (clobber (match_operand:SF 2 "memory_operand" "")) - (clobber (match_operand:DF 3 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float_extend:DF (match_dup 1)))] - "") - -(define_insn "" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m") - (float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,f")))] - "TARGET_80387 && (GET_CODE (operands[0]) != MEM - || GET_CODE (operands[1]) != MEM)" - "* -{ - output_float_extend (insn, operands); - return \"\"; -}" - [(set_attr "type" "fld,fpop")]) - -(define_expand "extenddfxf2" - [(parallel [(set (match_operand:XF 0 "nonimmediate_operand" "") - (float_extend:XF - (match_operand:DF 1 "nonimmediate_operand" ""))) - (clobber (match_dup 2)) - (clobber (match_dup 3))])] - "TARGET_80387" - " -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[1] = force_reg (DFmode, operands[1]); - - operands[2] = assign_386_stack_local (DFmode, 0); - operands[3] = assign_386_stack_local (XFmode, 0); -}") - -(define_insn "" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,!f,!*r") - (float_extend:XF - (match_operand:DF 1 "nonimmediate_operand" "fm,f,*r,f"))) - (clobber (match_operand:DF 2 "memory_operand" "m,m,o,m")) - (clobber (match_operand:XF 3 "memory_operand" "m,m,m,o"))] - "TARGET_80387 && (GET_CODE (operands[0]) != MEM - || GET_CODE (operands[1]) != MEM)" - "* -{ - output_float_extend (insn, operands); - return \"\"; -}" - [(set_attr "type" "fld,fpop,fld,fpop")]) - -(define_split - [(set (match_operand:XF 0 "register_operand" "") - (float_extend:XF (match_operand:DF 1 "register_operand" ""))) - (clobber (match_operand:DF 2 "memory_operand" "")) - (clobber (match_operand:XF 3 "memory_operand" ""))] - "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[1])" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 0) - (float_extend:XF (match_dup 2)))] - "") - -(define_split - [(set (match_operand:XF 0 "register_operand" "") - (float_extend:XF (match_operand:DF 1 "register_operand" ""))) - (clobber (match_operand:DF 2 "memory_operand" "")) - (clobber (match_operand:XF 3 "memory_operand" ""))] - "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[0])" - [(set (match_dup 3) - (float_extend:XF (match_dup 1))) - (set (match_dup 0) - (match_dup 3))] - "") - -(define_split - [(set (match_operand:XF 0 "nonimmediate_operand" "") - (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" ""))) - (clobber (match_operand:DF 2 "memory_operand" "")) - (clobber (match_operand:XF 3 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float_extend:XF (match_dup 1)))] - "") - -(define_insn "" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m") - (float_extend:XF (match_operand:DF 1 "nonimmediate_operand" "fm,f")))] - "TARGET_80387 && (GET_CODE (operands[0]) != MEM - || GET_CODE (operands[1]) != MEM)" - "* -{ - output_float_extend (insn, operands); - return \"\"; -}" - [(set_attr "type" "fld,fpop")]) - -(define_expand "extendsfxf2" - [(parallel [(set (match_operand:XF 0 "nonimmediate_operand" "") - (float_extend:XF - (match_operand:SF 1 "nonimmediate_operand" ""))) - (clobber (match_dup 2)) - (clobber (match_dup 3))])] - "TARGET_80387" - " -{ - if (GET_CODE (operands[0]) == MEM && GET_CODE (operands[1]) == MEM) - operands[1] = force_reg (SFmode, operands[1]); - - operands[2] = assign_386_stack_local (SFmode, 0); - operands[3] = assign_386_stack_local (XFmode, 0); -}") - -(define_insn "" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m,!f,!*r") - (float_extend:XF - (match_operand:SF 1 "nonimmediate_operand" "fm,f,*r,f"))) - (clobber (match_operand:SF 2 "memory_operand" "m,m,m,m")) - (clobber (match_operand:XF 3 "memory_operand" "m,m,m,o"))] - "TARGET_80387 && (GET_CODE (operands[0]) != MEM - || GET_CODE (operands[1]) != MEM)" - "* -{ - output_float_extend (insn, operands); - return \"\"; -}" - [(set_attr "type" "fld,fpop,fld,fpop")]) - -(define_split - [(set (match_operand:XF 0 "register_operand" "") - (float_extend:XF (match_operand:SF 1 "register_operand" ""))) - (clobber (match_operand:SF 2 "memory_operand" "")) - (clobber (match_operand:XF 3 "memory_operand" ""))] - "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[1])" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 0) - (float_extend:XF (match_dup 2)))] - "") - -(define_split - [(set (match_operand:XF 0 "register_operand" "") - (float_extend:XF (match_operand:SF 1 "register_operand" ""))) - (clobber (match_operand:SF 2 "memory_operand" "")) - (clobber (match_operand:XF 3 "memory_operand" ""))] - "TARGET_80387 && reload_completed && NON_STACK_REG_P (operands[0])" - [(set (match_dup 3) - (float_extend:XF (match_dup 1))) - (set (match_dup 0) - (match_dup 3))] - "") - -(define_split - [(set (match_operand:XF 0 "nonimmediate_operand" "") - (float_extend:XF (match_operand:SF 1 "nonimmediate_operand" ""))) - (clobber (match_operand:SF 2 "memory_operand" "")) - (clobber (match_operand:XF 3 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float_extend:XF (match_dup 1)))] - "") - -(define_insn "" - [(set (match_operand:XF 0 "nonimmediate_operand" "=f,m") - (float_extend:XF - (match_operand:SF 1 "nonimmediate_operand" "fm,f")))] - "TARGET_80387 && (GET_CODE (operands[0]) != MEM - || GET_CODE (operands[1]) != MEM)" - "* -{ - output_float_extend (insn, operands); - return \"\"; -}" - [(set_attr "type" "fld,fpop")]) - -(define_expand "truncdfsf2" - [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "") - (float_truncate:SF - (match_operand:DF 1 "register_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_80387" - " -{ - operands[2] = (rtx) assign_386_stack_local (SFmode, 0); -}") - -(define_insn "" - [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,!*r") - (float_truncate:SF - (match_operand:DF 1 "register_operand" "0,f,f"))) - (clobber (match_operand:SF 2 "memory_operand" "m,m,m"))] - "TARGET_80387" - "* -{ - int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; - rtx xops[1]; - - xops[0] = GET_CODE (operands[0]) == MEM ? operands[0] : operands[2]; - - if (stack_top_dies || STACK_REG_P (operands[0])) - output_asm_insn (AS1 (fstp%z0,%0), xops); - else - output_asm_insn (AS1 (fst%z0,%0), xops); - - if (STACK_REG_P (operands[0])) - return AS1 (fld%z2,%2); - else if (NON_STACK_REG_P (operands[0])) - return AS2 (mov%L0,%2,%0); - - return \"\"; -}" - [(set_attr "type" "fpop")]) - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (float_truncate:SF (match_operand:DF 1 "register_operand" ""))) - (clobber (match_operand:SF 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) - (float_truncate:SF (match_dup 1))) - (set (match_dup 0) - (match_dup 2))] - "") - -(define_split - [(set (match_operand:SF 0 "memory_operand" "") - (float_truncate:SF (match_operand:DF 1 "register_operand" ""))) - (clobber (match_operand:SF 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float_truncate:SF (match_dup 1)))] - "") - -;; This cannot output into an f-reg because there is no way to be sure -;; of truncating in that case. - -(define_insn "" - [(set (match_operand:SF 0 "memory_operand" "=m") - (float_truncate:SF (match_operand:DF 1 "register_operand" "f")))] - "TARGET_80387" - "* -{ - int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; - - if (stack_top_dies) - return AS1 (fstp%z0,%0); - else - return AS1 (fst%z0,%0); -}" - [(set_attr "type" "fpop")]) - -(define_expand "truncxfsf2" - [(parallel [(set (match_operand:SF 0 "nonimmediate_operand" "") - (float_truncate:SF - (match_operand:XF 1 "register_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_80387" - " -{ - operands[2] = (rtx) assign_386_stack_local (SFmode, 0); -}") - -(define_insn "" - [(set (match_operand:SF 0 "nonimmediate_operand" "=f,m,!*r") - (float_truncate:SF - (match_operand:XF 1 "register_operand" "0,f,f"))) - (clobber (match_operand:SF 2 "memory_operand" "m,m,m"))] - "TARGET_80387" - "* -{ - int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; - rtx xops[1]; - - xops[0] = GET_CODE (operands[0]) == MEM ? operands[0] : operands[2]; - - if (stack_top_dies || STACK_REG_P (operands[0])) - output_asm_insn (AS1 (fstp%z0,%0), xops); - else - output_asm_insn (AS1 (fst%z0,%0), xops); - - if (STACK_REG_P (operands[0])) - return AS1 (fld%z2,%2); - else if (NON_STACK_REG_P (operands[0])) - return AS2 (mov%L0,%2,%0); - - return \"\"; -}" - [(set_attr "type" "fpop")]) - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (float_truncate:SF (match_operand:XF 1 "register_operand" ""))) - (clobber (match_operand:SF 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) - (float_truncate:SF (match_dup 1))) - (set (match_dup 0) - (match_dup 2))] - "") - -(define_split - [(set (match_operand:SF 0 "memory_operand" "") - (float_truncate:SF (match_operand:XF 1 "register_operand" ""))) - (clobber (match_operand:SF 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float_truncate:SF (match_dup 1)))] - "") - -(define_insn "" - [(set (match_operand:SF 0 "memory_operand" "=m") - (float_truncate:SF (match_operand:XF 1 "register_operand" "f")))] - "TARGET_80387" - "* -{ - int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; - - if (stack_top_dies) - return AS1 (fstp%z0,%0); - else - return AS1 (fst%z0,%0); -}" - [(set_attr "type" "fpop")]) - -(define_expand "truncxfdf2" - [(parallel [(set (match_operand:DF 0 "nonimmediate_operand" "") - (float_truncate:DF - (match_operand:XF 1 "register_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_80387" - " -{ - operands[2] = (rtx) assign_386_stack_local (DFmode, 0); -}") - -(define_insn "" - [(set (match_operand:DF 0 "nonimmediate_operand" "=f,m,!*r") - (float_truncate:DF - (match_operand:XF 1 "register_operand" "0,f,f"))) - (clobber (match_operand:DF 2 "memory_operand" "m,m,o"))] - "TARGET_80387" - "* -{ - int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; - rtx xops[2]; - - xops[0] = GET_CODE (operands[0]) == MEM ? operands[0] : operands[2]; - - if (stack_top_dies || STACK_REG_P (operands[0])) - output_asm_insn (AS1 (fstp%z0,%0), xops); - else - output_asm_insn (AS1 (fst%z0,%0), xops); - - if (STACK_REG_P (operands[0])) - return AS1 (fld%z2,%2); - else if (NON_STACK_REG_P (operands[0])) - { - xops[0] = operands[0]; - xops[1] = operands[2]; - output_asm_insn (output_move_double (xops), xops); - } - - return \"\"; -}" - [(set_attr "type" "fpop")]) - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (float_truncate:DF (match_operand:XF 1 "register_operand" ""))) - (clobber (match_operand:DF 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) - (float_truncate:DF (match_dup 1))) - (set (match_dup 0) - (match_dup 2))] - "") - -(define_split - [(set (match_operand:DF 0 "memory_operand" "") - (float_truncate:DF (match_operand:XF 1 "register_operand" ""))) - (clobber (match_operand:DF 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float_truncate:DF (match_dup 1)))] - "") - -(define_insn "" - [(set (match_operand:DF 0 "memory_operand" "=m") - (float_truncate:DF (match_operand:XF 1 "register_operand" "f")))] - "TARGET_80387" - "* -{ - int stack_top_dies = find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != 0; - - if (stack_top_dies) - return AS1 (fstp%z0,%0); - else - return AS1 (fst%z0,%0); -}" - [(set_attr "type" "fpop")]) - -;; Conversions between floating point and fix point. - -(define_expand "fix_truncsfsi2" - [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "") - (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "")))) - (clobber (match_dup 2)) - (clobber (match_dup 3)) - (clobber (match_dup 4)) - (clobber (match_scratch:HI 5 ""))])] - "TARGET_80387" - " -{ - operands[2] = (rtx) assign_386_stack_local (HImode, 0); - operands[3] = (rtx) assign_386_stack_local (HImode, 1); - operands[4] = (rtx) assign_386_stack_local (SImode, 0); -}") - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=m,!&r") - (fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f,f")))) - (clobber (match_operand:HI 2 "memory_operand" "m,m")) - (clobber (match_operand:HI 3 "memory_operand" "m,m")) - (clobber (match_operand:SI 4 "memory_operand" "m,m")) - (clobber (match_scratch:HI 5 "=&r,&r"))] - "TARGET_80387" - "* return output_fix_trunc (insn, operands);" - [(set_attr "type" "fpop")]) - -(define_expand "fix_truncsfdi2" - [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "") - (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "")))) - (clobber (match_dup 1)) - (clobber (match_dup 2)) - (clobber (match_dup 3)) - (clobber (match_dup 4)) - (clobber (match_scratch:HI 5 ""))])] - "TARGET_80387" - " -{ - operands[1] = copy_to_mode_reg (SFmode, operands[1]); - operands[2] = (rtx) assign_386_stack_local (HImode, 0); - operands[3] = (rtx) assign_386_stack_local (HImode, 1); - operands[4] = (rtx) assign_386_stack_local (DImode, 0); -}") - -(define_insn "" - [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!&r") - (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f,f")))) - (clobber (match_dup 1)) - (clobber (match_operand:HI 2 "memory_operand" "m,m")) - (clobber (match_operand:HI 3 "memory_operand" "m,m")) - (clobber (match_operand:DI 4 "memory_operand" "m,o")) - (clobber (match_scratch:HI 5 "=&r,&r"))] - "TARGET_80387" - "* return output_fix_trunc (insn, operands);" - [(set_attr "type" "fpop")]) - -(define_expand "fix_truncdfsi2" - [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "") - (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "")))) - (clobber (match_dup 2)) - (clobber (match_dup 3)) - (clobber (match_dup 4)) - (clobber (match_scratch:HI 5 ""))])] - "TARGET_80387" - " -{ - operands[2] = (rtx) assign_386_stack_local (HImode, 0); - operands[3] = (rtx) assign_386_stack_local (HImode, 1); - operands[4] = (rtx) assign_386_stack_local (SImode, 0); -}") - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=m,!&r") - (fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f,f")))) - (clobber (match_operand:HI 2 "memory_operand" "m,m")) - (clobber (match_operand:HI 3 "memory_operand" "m,m")) - (clobber (match_operand:SI 4 "memory_operand" "m,m")) - (clobber (match_scratch:HI 5 "=&r,&r"))] - "TARGET_80387" - "* return output_fix_trunc (insn, operands);" - [(set_attr "type" "fpop")]) - -(define_expand "fix_truncdfdi2" - [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "") - (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "")))) - (clobber (match_dup 1)) - (clobber (match_dup 2)) - (clobber (match_dup 3)) - (clobber (match_dup 4)) - (clobber (match_scratch:HI 5 ""))])] - "TARGET_80387" - " -{ - operands[1] = copy_to_mode_reg (DFmode, operands[1]); - operands[2] = (rtx) assign_386_stack_local (HImode, 0); - operands[3] = (rtx) assign_386_stack_local (HImode, 1); - operands[4] = (rtx) assign_386_stack_local (DImode, 0); -}") - -(define_insn "" - [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!&r") - (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f,f")))) - (clobber (match_dup 1)) - (clobber (match_operand:HI 2 "memory_operand" "m,m")) - (clobber (match_operand:HI 3 "memory_operand" "m,m")) - (clobber (match_operand:DI 4 "memory_operand" "m,o")) - (clobber (match_scratch:HI 5 "=&r,&r"))] - "TARGET_80387" - "* return output_fix_trunc (insn, operands);" - [(set_attr "type" "fpop")]) - -(define_expand "fix_truncxfsi2" - [(parallel [(set (match_operand:SI 0 "nonimmediate_operand" "") - (fix:SI (fix:XF (match_operand:XF 1 "register_operand" "")))) - (clobber (match_dup 2)) - (clobber (match_dup 3)) - (clobber (match_dup 4)) - (clobber (match_scratch:HI 5 ""))])] - "TARGET_80387" - " -{ - operands[2] = (rtx) assign_386_stack_local (HImode, 0); - operands[3] = (rtx) assign_386_stack_local (HImode, 1); - operands[4] = (rtx) assign_386_stack_local (SImode, 0); -}") - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=m,!&r") - (fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f,f")))) - (clobber (match_operand:HI 2 "memory_operand" "m,m")) - (clobber (match_operand:HI 3 "memory_operand" "m,m")) - (clobber (match_operand:SI 4 "memory_operand" "m,m")) - (clobber (match_scratch:HI 5 "=&r,&r"))] - "TARGET_80387" - "* return output_fix_trunc (insn, operands);" - [(set_attr "type" "fpop")]) - -(define_expand "fix_truncxfdi2" - [(parallel [(set (match_operand:DI 0 "nonimmediate_operand" "") - (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "")))) - (clobber (match_dup 1)) - (clobber (match_dup 2)) - (clobber (match_dup 3)) - (clobber (match_dup 4)) - (clobber (match_scratch:HI 5 ""))])] - "TARGET_80387" - " -{ - operands[1] = copy_to_mode_reg (XFmode, operands[1]); - operands[2] = (rtx) assign_386_stack_local (HImode, 0); - operands[3] = (rtx) assign_386_stack_local (HImode, 1); - operands[4] = (rtx) assign_386_stack_local (DImode, 0); -}") - -(define_insn "" - [(set (match_operand:DI 0 "nonimmediate_operand" "=m,!&r") - (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "f,f")))) - (clobber (match_dup 1)) - (clobber (match_operand:HI 2 "memory_operand" "m,m")) - (clobber (match_operand:HI 3 "memory_operand" "m,m")) - (clobber (match_operand:DI 4 "memory_operand" "m,o")) - (clobber (match_scratch:HI 5 "=&r,&r"))] - "TARGET_80387" - "* return output_fix_trunc (insn, operands);" - [(set_attr "type" "fpop")]) - -;; Conversion between fixed point and floating point. - -;; ??? Possibly represent floatunssidf2 here in gcc2. - -(define_expand "floatsisf2" - [(parallel [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:SI 1 "nonimmediate_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_80387" - "operands[2] = assign_386_stack_local (SImode, 0);") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f,f") - (float:SF (match_operand:SI 1 "nonimmediate_operand" "m,!r"))) - (clobber (match_operand:SI 2 "memory_operand" "m,m"))] - "TARGET_80387" - "#") - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:SI 1 "memory_operand" ""))) - (clobber (match_operand:SI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float:SF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:SI 1 "register_operand" ""))) - (clobber (match_operand:SI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 0) - (float:SF (match_dup 2)))] - "") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (float:SF (match_operand:SI 1 "memory_operand" "m")))] - "TARGET_80387" - "* return AS1 (fild%z1,%1);" - [(set_attr "type" "fpop")]) - -(define_expand "floathisf2" - [(parallel [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:HI 1 "nonimmediate_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_80387" - "operands[2] = assign_386_stack_local (HImode, 0);") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f,f") - (float:SF (match_operand:HI 1 "nonimmediate_operand" "m,!r"))) - (clobber (match_operand:HI 2 "memory_operand" "m,m"))] - "TARGET_80387" - "#") - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:HI 1 "memory_operand" ""))) - (clobber (match_operand:HI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float:SF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:HI 1 "register_operand" ""))) - (clobber (match_operand:HI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 0) - (float:SF (match_dup 2)))] - "") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (float:SF (match_operand:HI 1 "memory_operand" "m")))] - "TARGET_80387" - "* return AS1 (fild%z1,%1);" - [(set_attr "type" "fpop")]) - -(define_expand "floatdisf2" - [(parallel [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:DI 1 "nonimmediate_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_80387" - "operands[2] = assign_386_stack_local (DImode, 0);") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f,f") - (float:SF (match_operand:DI 1 "nonimmediate_operand" "m,!r"))) - (clobber (match_operand:DI 2 "memory_operand" "m,o"))] - "TARGET_80387" - "#") - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:DI 1 "memory_operand" ""))) - (clobber (match_operand:DI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float:SF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (float:SF (match_operand:DI 1 "register_operand" ""))) - (clobber (match_operand:DI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 0) - (float:SF (match_dup 2)))] - "") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f") - (float:SF (match_operand:DI 1 "memory_operand" "m")))] - "TARGET_80387" - "* return AS1 (fild%z1,%1);" - [(set_attr "type" "fpop")]) - -(define_expand "floatsidf2" - [(parallel [(set (match_operand:DF 0 "register_operand" "") - (float:DF (match_operand:SI 1 "nonimmediate_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_80387" - "operands[2] = assign_386_stack_local (SImode, 0);") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (float:DF (match_operand:SI 1 "nonimmediate_operand" "m,!r"))) - (clobber (match_operand:SI 2 "memory_operand" "m,m"))] - "TARGET_80387" - "#") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (float:DF (match_operand:SI 1 "memory_operand" ""))) - (clobber (match_operand:SI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float:DF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (float:DF (match_operand:SI 1 "register_operand" ""))) - (clobber (match_operand:SI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 0) - (float:DF (match_dup 2)))] - "") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (float:DF (match_operand:SI 1 "memory_operand" "m")))] - "TARGET_80387" - "* return AS1 (fild%z1,%1);" - [(set_attr "type" "fpop")]) - -(define_expand "floathidf2" - [(parallel [(set (match_operand:DF 0 "register_operand" "") - (float:DF (match_operand:HI 1 "nonimmediate_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_80387" - "operands[2] = assign_386_stack_local (HImode, 0);") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (float:DF (match_operand:HI 1 "nonimmediate_operand" "m,!r"))) - (clobber (match_operand:HI 2 "memory_operand" "m,m"))] - "TARGET_80387" - "#") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (float:DF (match_operand:HI 1 "memory_operand" ""))) - (clobber (match_operand:HI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float:DF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (float:DF (match_operand:HI 1 "register_operand" ""))) - (clobber (match_operand:HI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 0) - (float:DF (match_dup 2)))] - "") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (float:DF (match_operand:HI 1 "memory_operand" "m")))] - "TARGET_80387" - "* return AS1 (fild%z1,%1);" - [(set_attr "type" "fpop")]) - -(define_expand "floatdidf2" - [(parallel [(set (match_operand:DF 0 "register_operand" "") - (float:DF (match_operand:DI 1 "nonimmediate_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_80387" - "operands[2] = assign_386_stack_local (DImode, 0);") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (float:DF (match_operand:DI 1 "nonimmediate_operand" "m,!r"))) - (clobber (match_operand:DI 2 "memory_operand" "m,o"))] - "TARGET_80387" - "#") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (float:DF (match_operand:DI 1 "memory_operand" ""))) - (clobber (match_operand:DI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float:DF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (float:DF (match_operand:DI 1 "register_operand" ""))) - (clobber (match_operand:DI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 0) - (float:DF (match_dup 2)))] - "") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (float:DF (match_operand:DI 1 "memory_operand" "m")))] - "TARGET_80387" - "* return AS1 (fild%z1,%1);" - [(set_attr "type" "fpop")]) - -(define_expand "floatsixf2" - [(parallel [(set (match_operand:XF 0 "register_operand" "") - (float:XF (match_operand:SI 1 "nonimmediate_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_80387" - "operands[2] = assign_386_stack_local (SImode, 0);") - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f,f") - (float:XF (match_operand:SI 1 "nonimmediate_operand" "m,!r"))) - (clobber (match_operand:SI 2 "memory_operand" "m,m"))] - "TARGET_80387" - "#") - -(define_split - [(set (match_operand:XF 0 "register_operand" "") - (float:XF (match_operand:SI 1 "memory_operand" ""))) - (clobber (match_operand:SI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float:XF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:XF 0 "register_operand" "") - (float:XF (match_operand:SI 1 "register_operand" ""))) - (clobber (match_operand:SI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 0) - (float:XF (match_dup 2)))] - "") - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f") - (float:XF (match_operand:SI 1 "memory_operand" "m")))] - "TARGET_80387" - "* return AS1 (fild%z1,%1);" - [(set_attr "type" "fpop")]) - -(define_expand "floathixf2" - [(parallel [(set (match_operand:XF 0 "register_operand" "") - (float:XF (match_operand:HI 1 "nonimmediate_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_80387" - "operands[2] = assign_386_stack_local (HImode, 0);") - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f,f") - (float:XF (match_operand:HI 1 "nonimmediate_operand" "m,!r"))) - (clobber (match_operand:HI 2 "memory_operand" "m,m"))] - "TARGET_80387" - "#") - -(define_split - [(set (match_operand:XF 0 "register_operand" "") - (float:XF (match_operand:HI 1 "memory_operand" ""))) - (clobber (match_operand:HI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float:XF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:XF 0 "register_operand" "") - (float:XF (match_operand:HI 1 "register_operand" ""))) - (clobber (match_operand:HI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 0) - (float:XF (match_dup 2)))] - "") - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f") - (float:XF (match_operand:HI 1 "memory_operand" "m")))] - "TARGET_80387" - "* return AS1 (fild%z1,%1);" - [(set_attr "type" "fpop")]) - -(define_expand "floatdixf2" - [(parallel [(set (match_operand:XF 0 "register_operand" "") - (float:XF (match_operand:DI 1 "nonimmediate_operand" ""))) - (clobber (match_dup 2))])] - "TARGET_80387" - "operands[2] = assign_386_stack_local (DImode, 0);") - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f,f") - (float:XF (match_operand:DI 1 "nonimmediate_operand" "m,!r"))) - (clobber (match_operand:DI 2 "memory_operand" "m,o"))] - "TARGET_80387" - "#") - -(define_split - [(set (match_operand:XF 0 "register_operand" "") - (float:XF (match_operand:DI 1 "memory_operand" ""))) - (clobber (match_operand:DI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 0) - (float:XF (match_dup 1)))] - "") - -(define_split - [(set (match_operand:XF 0 "register_operand" "") - (float:XF (match_operand:DI 1 "register_operand" ""))) - (clobber (match_operand:DI 2 "memory_operand" ""))] - "TARGET_80387 && reload_completed" - [(set (match_dup 2) - (match_dup 1)) - (set (match_dup 0) - (float:XF (match_dup 2)))] - "") - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f") - (float:XF (match_operand:DI 1 "memory_operand" "m")))] - "TARGET_80387" - "* return AS1 (fild%z1,%1);" - [(set_attr "type" "fpop")]) - -;;- add instructions - -(define_insn "*addsidi3_1" - [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,!&r,!r,o,!o") - (plus:DI (match_operand:DI 1 "general_operand" "0,0,0,o,riF,riF,o") - (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,roi,roi,ri,ri")))) - (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,&r"))] - "" - "* -{ - rtx low[3], high[3], xops[7]; - - CC_STATUS_INIT; - - split_di (operands, 2, low, high); - high[2] = const0_rtx; - low[2] = operands[2]; - - if (!rtx_equal_p (operands[0], operands[1])) - { - xops[0] = high[0]; - xops[1] = low[0]; - xops[2] = high[1]; - xops[3] = low[1]; - - if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) - { - output_asm_insn (AS2 (mov%L1,%3,%1), xops); - output_asm_insn (AS2 (mov%L0,%2,%0), xops); - } - else - { - xops[4] = high[2]; - xops[5] = low[2]; - xops[6] = operands[3]; - output_asm_insn (AS2 (mov%L6,%3,%6), xops); - output_asm_insn (AS2 (add%L6,%5,%6), xops); - output_asm_insn (AS2 (mov%L1,%6,%1), xops); - output_asm_insn (AS2 (mov%L6,%2,%6), xops); - output_asm_insn (AS2 (adc%L6,%4,%6), xops); - output_asm_insn (AS2 (mov%L0,%6,%0), xops); - RET; - } - } - - output_asm_insn (AS2 (add%L0,%2,%0), low); - output_asm_insn (AS2 (adc%L0,%2,%0), high); - cc_status.value1 = high[0]; - cc_status.flags = CC_NO_OVERFLOW; - RET; -}" - [(set_attr "type" "binary")]) - -(define_insn "addsidi3_2" - [(set (match_operand:DI 0 "nonimmediate_operand" "=&r,r,o,&r,!&r,&r,o,o,!o") - (plus:DI (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,o,o,ri,ri,i,r")) - (match_operand:DI 1 "general_operand" "0,0,0,iF,ro,roiF,riF,o,o"))) - (clobber (match_scratch:SI 3 "=X,X,X,X,X,X,X,&r,&r"))] - "" - "* -{ - rtx low[3], high[3], xops[7]; - - CC_STATUS_INIT; - - split_di (operands, 2, low, high); - high[2] = const0_rtx; - low[2] = operands[2]; - - if (!rtx_equal_p (operands[0], operands[1])) - { - xops[0] = high[0]; - xops[1] = low[0]; - xops[2] = high[1]; - xops[3] = low[1]; - - if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) - { - if (rtx_equal_p (low[0], operands[2])) - { - output_asm_insn (AS2 (mov%L0,%2,%0), high); - output_asm_insn (AS2 (add%L0,%1,%0), low); - output_asm_insn (AS2 (adc%L0,%1,%0), high); - RET; - } - if (rtx_equal_p (high[0], operands[2])) - { - if (GET_CODE (operands[0]) != MEM) - { - output_asm_insn (AS2 (mov%L0,%2,%0), low); - output_asm_insn (AS2 (mov%L0,%2,%0), high); - output_asm_insn (AS2 (add%L0,%1,%0), low); - output_asm_insn (AS2 (adc%L0,%1,%0), high); - } - else - { - /* It's too late to ask for a scratch now - but this - will probably not happen too often. */ - output_asm_insn (AS2 (add%L1,%2,%1), low); - output_asm_insn (AS2 (mov%L0,%1,%0), low); - output_asm_insn (AS2 (mov%L1,%2,%1), low); - output_asm_insn (AS2 (mov%L0,%2,%0), high); - output_asm_insn (AS2 (adc%L0,%1,%0), high); - output_asm_insn (AS2 (sub%L1,%0,%1), low); - output_asm_insn (AS1 (neg%L1,%1), low); - } - RET; - } - output_asm_insn (AS2 (mov%L1,%3,%1), xops); - output_asm_insn (AS2 (mov%L0,%2,%0), xops); - } - else - { - xops[4] = high[2]; - xops[5] = low[2]; - xops[6] = operands[3]; - output_asm_insn (AS2 (mov%L6,%3,%6), xops); - output_asm_insn (AS2 (add%L6,%5,%6), xops); - output_asm_insn (AS2 (mov%L1,%6,%1), xops); - output_asm_insn (AS2 (mov%L6,%2,%6), xops); - output_asm_insn (AS2 (adc%L6,%4,%6), xops); - output_asm_insn (AS2 (mov%L0,%6,%0), xops); - RET; - } - } - - output_asm_insn (AS2 (add%L0,%2,%0), low); - output_asm_insn (AS2 (adc%L0,%2,%0), high); - cc_status.value1 = high[0]; - cc_status.flags = CC_NO_OVERFLOW; - RET; -}" - [(set_attr "type" "binary")]) - -(define_insn "adddi3" - [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o") - (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,0iF,or,riF,o") - (match_operand:DI 2 "general_operand" "o,riF,0,or,or,oriF,o"))) - (clobber (match_scratch:SI 3 "=X,X,X,&r,X,&r,&r"))] - "" - "* -{ - rtx low[3], high[3], xops[7], temp; - - CC_STATUS_INIT; - - if (rtx_equal_p (operands[0], operands[2])) - { - temp = operands[1]; - operands[1] = operands[2]; - operands[2] = temp; - } - - split_di (operands, 3, low, high); - if (!rtx_equal_p (operands[0], operands[1])) - { - xops[0] = high[0]; - xops[1] = low[0]; - xops[2] = high[1]; - xops[3] = low[1]; - - if (GET_CODE (operands[0]) != MEM) - { - output_asm_insn (AS2 (mov%L1,%3,%1), xops); - output_asm_insn (AS2 (mov%L0,%2,%0), xops); - } - else - { - xops[4] = high[2]; - xops[5] = low[2]; - xops[6] = operands[3]; - output_asm_insn (AS2 (mov%L6,%3,%6), xops); - output_asm_insn (AS2 (add%L6,%5,%6), xops); - output_asm_insn (AS2 (mov%L1,%6,%1), xops); - output_asm_insn (AS2 (mov%L6,%2,%6), xops); - output_asm_insn (AS2 (adc%L6,%4,%6), xops); - output_asm_insn (AS2 (mov%L0,%6,%0), xops); - RET; - } - } - - cc_status.value1 = high[0]; - cc_status.flags = CC_NO_OVERFLOW; - - if (GET_CODE (operands[3]) == REG && GET_CODE (operands[2]) != REG) - { - xops[0] = high[0]; - xops[1] = low[0]; - xops[2] = high[2]; - xops[3] = low[2]; - xops[4] = operands[3]; - - output_asm_insn (AS2 (mov%L4,%3,%4), xops); - output_asm_insn (AS2 (add%L1,%4,%1), xops); - output_asm_insn (AS2 (mov%L4,%2,%4), xops); - output_asm_insn (AS2 (adc%L0,%4,%0), xops); - } - - else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0) - { - output_asm_insn (AS2 (add%L0,%2,%0), low); - output_asm_insn (AS2 (adc%L0,%2,%0), high); - } - - else - output_asm_insn (AS2 (add%L0,%2,%0), high); - - RET; -}" - [(set_attr "type" "binary")]) - -;; On a 486, it is faster to do movl/addl than to do a single leal if -;; operands[1] and operands[2] are both registers. - -(define_expand "addsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - "IX86_EXPAND_BINARY_OPERATOR (PLUS, SImode, operands);") - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm,r") - (plus:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0,r") - (match_operand:SI 2 "general_operand" "rmi,ri,ri")))] - "ix86_binary_operator_ok (PLUS, SImode, operands)" - "* -{ - if (REG_P (operands[0]) && REG_P (operands[1]) - && (REG_P (operands[2]) || CONSTANT_P (operands[2])) - && REGNO (operands[0]) != REGNO (operands[1])) - { - if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2])) - return AS2 (add%L0,%1,%0); - - if (operands[2] == stack_pointer_rtx) - { - rtx temp; - - temp = operands[1]; - operands[1] = operands[2]; - operands[2] = temp; - } - - if (operands[2] != stack_pointer_rtx) - { - CC_STATUS_INIT; - operands[1] = SET_SRC (PATTERN (insn)); - return AS2 (lea%L0,%a1,%0); - } - } - - if (!rtx_equal_p (operands[0], operands[1])) - output_asm_insn (AS2 (mov%L0,%1,%0), operands); - - if (operands[2] == const1_rtx) - return AS1 (inc%L0,%0); - - if (operands[2] == constm1_rtx) - return AS1 (dec%L0,%0); - - /* subl $-128,%ebx is smaller than addl $128,%ebx. */ - if (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 128) - { - /* This doesn't compute the carry bit in the same way - * as add%L0, but we use inc and dec above and they - * don't set the carry bit at all. If inc/dec don't need - * a CC_STATUS_INIT, this doesn't either... */ - operands[2] = GEN_INT (-128); - return AS2 (sub%L0,%2,%0); - } - - return AS2 (add%L0,%2,%0); -}" - [(set_attr "type" "binary")]) - -;; addsi3 is faster, so put this after. - -(define_insn "movsi_lea" - [(set (match_operand:SI 0 "register_operand" "=r") - (match_operand:QI 1 "address_operand" "p"))] - "" - "* -{ - /* Adding a constant to a register is faster with an add. */ - /* ??? can this ever happen? */ - if (GET_CODE (operands[1]) == PLUS - && GET_CODE (XEXP (operands[1], 1)) == CONST_INT - && rtx_equal_p (operands[0], XEXP (operands[1], 0))) - { - operands[1] = XEXP (operands[1], 1); - - if (operands[1] == const1_rtx) - return AS1 (inc%L0,%0); - - if (operands[1] == constm1_rtx) - return AS1 (dec%L0,%0); - - return AS2 (add%L0,%1,%0); - } - - CC_STATUS_INIT; - return AS2 (lea%L0,%a1,%0); -}" - [(set_attr "type" "lea")]) - -;; ??? `lea' here, for three operand add? If leaw is used, only %bx, -;; %si and %di can appear in SET_SRC, and output_asm_insn might not be -;; able to handle the operand. But leal always works? - -(define_expand "addhi3" - [(set (match_operand:HI 0 "general_operand" "") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:HI 2 "general_operand" "")))] - "" - "IX86_EXPAND_BINARY_OPERATOR (PLUS, HImode, operands);") - -(define_insn "" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r,?r") - (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0,r") - (match_operand:HI 2 "general_operand" "ri,rm,ri")))] - "ix86_binary_operator_ok (PLUS, HImode, operands)" - "* -{ - if (REG_P (operands[0]) && REG_P (operands[1]) - && (REG_P (operands[2]) || CONSTANT_P (operands[2])) - && REGNO (operands[0]) != REGNO (operands[1])) - { - if (operands[2] == stack_pointer_rtx) - abort (); - - CC_STATUS_INIT; - operands[1] - = gen_rtx_PLUS (SImode, - gen_rtx_REG (SImode, REGNO (operands[1])), - (! REG_P (operands[2]) - ? operands[2] - : gen_rtx_REG (SImode, REGNO (operands[2])))); - operands[0] = gen_rtx_REG (SImode, REGNO (operands[0])); - return AS2 (lea%L0,%a1,%0); - } - - /* ??? what about offsettable memory references? */ - if (!TARGET_PENTIUMPRO /* partial stalls are just too painful to risk. */ - && QI_REG_P (operands[0]) - && GET_CODE (operands[2]) == CONST_INT - && (INTVAL (operands[2]) & 0xff) == 0 - && i386_cc_probably_useless_p (insn)) - { - int byteval = (INTVAL (operands[2]) >> 8) & 0xff; - CC_STATUS_INIT; - - if (byteval == 1) - return AS1 (inc%B0,%h0); - else if (byteval == 255) - return AS1 (dec%B0,%h0); - - operands[2] = GEN_INT (byteval); - return AS2 (add%B0,%2,%h0); - } - - /* Use a 32-bit operation when possible, to avoid the prefix penalty. */ - if (REG_P (operands[0]) - && i386_aligned_p (operands[2]) - && i386_cc_probably_useless_p (insn)) - { - CC_STATUS_INIT; - - if (GET_CODE (operands[2]) == CONST_INT) - { - HOST_WIDE_INT intval = 0xffff & INTVAL (operands[2]); - - if (intval == 1) - return AS1 (inc%L0,%k0); - - if (intval == 0xffff) - return AS1 (dec%L0,%k0); - - operands[2] = i386_sext16_if_const (operands[2]); - } - return AS2 (add%L0,%k2,%k0); - } - - if (operands[2] == const1_rtx) - return AS1 (inc%W0,%0); - - if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 65535)) - return AS1 (dec%W0,%0); - - return AS2 (add%W0,%2,%0); -}" - [(set_attr "type" "binary")]) - -(define_expand "addqi3" - [(set (match_operand:QI 0 "general_operand" "") - (plus:QI (match_operand:QI 1 "general_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "" - "IX86_EXPAND_BINARY_OPERATOR (PLUS, QImode, operands);") - -(define_insn "" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q,?q") - (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0,q") - (match_operand:QI 2 "general_operand" "qn,qmn,qn")))] - "ix86_binary_operator_ok (PLUS, QImode, operands)" - "* -{ - if (REG_P (operands[0]) && REG_P (operands[1]) - && (REG_P (operands[2]) || CONSTANT_P (operands[2])) - && (REGNO (operands[0]) != REGNO (operands[1]) - || NON_QI_REG_P (operands[1]) - || (REG_P (operands[2]) && NON_QI_REG_P (operands[2])))) - { - if (operands[2] == stack_pointer_rtx) - abort (); - - CC_STATUS_INIT; - operands[1] - = gen_rtx_PLUS (SImode, - gen_rtx_REG (SImode, REGNO (operands[1])), - (! REG_P (operands[2]) - ? operands[2] - : gen_rtx_REG (SImode, REGNO (operands[2])))); - operands[0] = gen_rtx_REG (SImode, REGNO (operands[0])); - return AS2 (lea%L0,%a1,%0); - } - if (operands[2] == const1_rtx) - return AS1 (inc%B0,%0); - - if (operands[2] == constm1_rtx - || (GET_CODE (operands[2]) == CONST_INT - && INTVAL (operands[2]) == 255)) - return AS1 (dec%B0,%0); - - return AS2 (add%B0,%2,%0); -}" - [(set_attr "type" "binary")]) - -;Lennart Augustsson <augustss@cs.chalmers.se> -;says this pattern just makes slower code: -; pushl %ebp -; addl $-80,(%esp) -;instead of -; leal -80(%ebp),%eax -; pushl %eax -; -;(define_insn "" -; [(set (match_operand:SI 0 "push_operand" "=<") -; (plus:SI (match_operand:SI 1 "register_operand" "%r") -; (match_operand:SI 2 "nonmemory_operand" "ri")))] -; "" -; "* -;{ -; rtx xops[4]; -; xops[0] = operands[0]; -; xops[1] = operands[1]; -; xops[2] = operands[2]; -; xops[3] = gen_rtx_MEM (SImode, stack_pointer_rtx); -; output_asm_insn (\"push%z1 %1\", xops); -; output_asm_insn (AS2 (add%z3,%2,%3), xops); -; RET; -;}") - -;; The patterns that match these are at the end of this file. - -(define_expand "addxf3" - [(set (match_operand:XF 0 "register_operand" "") - (plus:XF (match_operand:XF 1 "register_operand" "") - (match_operand:XF 2 "register_operand" "")))] - "TARGET_80387" - "") - -(define_expand "adddf3" - [(set (match_operand:DF 0 "register_operand" "") - (plus:DF (match_operand:DF 1 "nonimmediate_operand" "") - (match_operand:DF 2 "nonimmediate_operand" "")))] - "TARGET_80387" - "") - -(define_expand "addsf3" - [(set (match_operand:SF 0 "register_operand" "") - (plus:SF (match_operand:SF 1 "nonimmediate_operand" "") - (match_operand:SF 2 "nonimmediate_operand" "")))] - "TARGET_80387" - "") - -;;- subtract instructions - -(define_insn "subsidi3" - [(set (match_operand:DI 0 "general_operand" "=&r,&ro,&r,!&r,o,o,!o") - (minus:DI (match_operand:DI 1 "general_operand" "0iF,0,roiF,roiF,riF,o,o") - (zero_extend:DI (match_operand:SI 2 "general_operand" "o,ri,ri,o,ri,i,r")))) - (clobber (match_scratch:SI 3 "=X,X,X,X,X,&r,&r"))] - "" - "* -{ - rtx low[3], high[3], xops[7]; - - CC_STATUS_INIT; - - split_di (operands, 2, low, high); - high[2] = const0_rtx; - low[2] = operands[2]; - - if (!rtx_equal_p (operands[0], operands[1])) - { - xops[0] = high[0]; - xops[1] = low[0]; - xops[2] = high[1]; - xops[3] = low[1]; - - if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM) - { - output_asm_insn (AS2 (mov%L1,%3,%1), xops); - output_asm_insn (AS2 (mov%L0,%2,%0), xops); - } - else - { - xops[4] = high[2]; - xops[5] = low[2]; - xops[6] = operands[3]; - output_asm_insn (AS2 (mov%L6,%3,%6), xops); - output_asm_insn (AS2 (sub%L6,%5,%6), xops); - output_asm_insn (AS2 (mov%L1,%6,%1), xops); - output_asm_insn (AS2 (mov%L6,%2,%6), xops); - output_asm_insn (AS2 (sbb%L6,%4,%6), xops); - output_asm_insn (AS2 (mov%L0,%6,%0), xops); - RET; - } - } - - output_asm_insn (AS2 (sub%L0,%2,%0), low); - output_asm_insn (AS2 (sbb%L0,%2,%0), high); - cc_status.value1 = high[0]; - cc_status.flags = CC_NO_OVERFLOW; - - RET; -}" - [(set_attr "type" "binary")]) - -(define_insn "subdi3" - [(set (match_operand:DI 0 "general_operand" "=&r,&ro,o,o,!&r,!o") - (minus:DI (match_operand:DI 1 "general_operand" "0,0,0iF,or,roiF,roiF") - (match_operand:DI 2 "general_operand" "or,riF,or,iF,roiF,roiF"))) - (clobber (match_scratch:SI 3 "=X,X,&r,&r,X,&r"))] - "" - "* -{ - rtx low[3], high[3], xops[7]; - - CC_STATUS_INIT; - - split_di (operands, 3, low, high); - - if (!rtx_equal_p (operands[0], operands[1])) - { - xops[0] = high[0]; - xops[1] = low[0]; - xops[2] = high[1]; - xops[3] = low[1]; - - if (GET_CODE (operands[0]) != MEM) - { - output_asm_insn (AS2 (mov%L1,%3,%1), xops); - output_asm_insn (AS2 (mov%L0,%2,%0), xops); - } - else - { - xops[4] = high[2]; - xops[5] = low[2]; - xops[6] = operands[3]; - output_asm_insn (AS2 (mov%L6,%3,%6), xops); - output_asm_insn (AS2 (sub%L6,%5,%6), xops); - output_asm_insn (AS2 (mov%L1,%6,%1), xops); - output_asm_insn (AS2 (mov%L6,%2,%6), xops); - output_asm_insn (AS2 (sbb%L6,%4,%6), xops); - output_asm_insn (AS2 (mov%L0,%6,%0), xops); - RET; - } - } - - cc_status.value1 = high[0]; - cc_status.flags = CC_NO_OVERFLOW; - - if (GET_CODE (operands[3]) == REG) - { - xops[0] = high[0]; - xops[1] = low[0]; - xops[2] = high[2]; - xops[3] = low[2]; - xops[4] = operands[3]; - - output_asm_insn (AS2 (mov%L4,%3,%4), xops); - output_asm_insn (AS2 (sub%L1,%4,%1), xops); - output_asm_insn (AS2 (mov%L4,%2,%4), xops); - output_asm_insn (AS2 (sbb%L0,%4,%0), xops); - } - - else if (GET_CODE (low[2]) != CONST_INT || INTVAL (low[2]) != 0) - { - output_asm_insn (AS2 (sub%L0,%2,%0), low); - output_asm_insn (AS2 (sbb%L0,%2,%0), high); - } - - else - output_asm_insn (AS2 (sub%L0,%2,%0), high); - - - RET; -}" - [(set_attr "type" "binary")]) - -(define_expand "subsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (minus:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:SI 2 "general_operand" "")))] - "" - "IX86_EXPAND_BINARY_OPERATOR (MINUS, SImode, operands);") - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (minus:SI (match_operand:SI 1 "nonimmediate_operand" "0,0") - (match_operand:SI 2 "general_operand" "ri,rm")))] - "ix86_binary_operator_ok (MINUS, SImode, operands)" - "* return AS2 (sub%L0,%2,%0);" - [(set_attr "type" "binary")]) - -(define_expand "subhi3" - [(set (match_operand:HI 0 "general_operand" "") - (minus:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:HI 2 "general_operand" "")))] - "" - "IX86_EXPAND_BINARY_OPERATOR (MINUS, HImode, operands);") - -(define_insn "" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (minus:HI (match_operand:HI 1 "nonimmediate_operand" "0,0") - (match_operand:HI 2 "general_operand" "ri,rm")))] - "ix86_binary_operator_ok (MINUS, HImode, operands)" - "* -{ - if (REG_P (operands[0]) - && i386_aligned_p (operands[2]) - && i386_cc_probably_useless_p (insn)) - { - CC_STATUS_INIT; - operands[2] = i386_sext16_if_const (operands[2]); - return AS2 (sub%L0,%k2,%k0); - } - return AS2 (sub%W0,%2,%0); -}" - [(set_attr "type" "binary")]) - -(define_expand "subqi3" - [(set (match_operand:QI 0 "general_operand" "") - (minus:QI (match_operand:QI 1 "general_operand" "") - (match_operand:QI 2 "general_operand" "")))] - "" - "IX86_EXPAND_BINARY_OPERATOR (MINUS, QImode, operands);") - -(define_insn "" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (minus:QI (match_operand:QI 1 "nonimmediate_operand" "0,0") - (match_operand:QI 2 "general_operand" "qn,qmn")))] - "ix86_binary_operator_ok (MINUS, QImode, operands)" - "* return AS2 (sub%B0,%2,%0);" - [(set_attr "type" "binary")]) - -;; The patterns that match these are at the end of this file. - -(define_expand "subxf3" - [(set (match_operand:XF 0 "register_operand" "") - (minus:XF (match_operand:XF 1 "register_operand" "") - (match_operand:XF 2 "register_operand" "")))] - "TARGET_80387" - "") - -(define_expand "subdf3" - [(set (match_operand:DF 0 "register_operand" "") - (minus:DF (match_operand:DF 1 "nonimmediate_operand" "") - (match_operand:DF 2 "nonimmediate_operand" "")))] - "TARGET_80387" - "") - -(define_expand "subsf3" - [(set (match_operand:SF 0 "register_operand" "") - (minus:SF (match_operand:SF 1 "nonimmediate_operand" "") - (match_operand:SF 2 "nonimmediate_operand" "")))] - "TARGET_80387" - "") - -;;- multiply instructions - -;(define_insn "mulqi3" -; [(set (match_operand:QI 0 "register_operand" "=a") -; (mult:QI (match_operand:QI 1 "register_operand" "%0") -; (match_operand:QI 2 "nonimmediate_operand" "qm")))] -; "" -; "imul%B0 %2,%0") - -(define_insn "mulhi3" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (mult:HI (match_operand:HI 1 "nonimmediate_operand" "%0,rm") - (match_operand:HI 2 "general_operand" "g,i")))] - "" - "* -{ - if (GET_CODE (operands[1]) == REG - && REGNO (operands[1]) == REGNO (operands[0]) - && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG)) - /* Assembler has weird restrictions. */ - return AS2 (imul%W0,%2,%0); - return AS3 (imul%W0,%2,%1,%0); -}" - [(set_attr "type" "imul")]) - -(define_insn "mulsi3" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (mult:SI (match_operand:SI 1 "nonimmediate_operand" "%0,rm") - (match_operand:SI 2 "general_operand" "g,i")))] - "" - "* -{ - if (GET_CODE (operands[1]) == REG - && REGNO (operands[1]) == REGNO (operands[0]) - && (GET_CODE (operands[2]) == MEM || GET_CODE (operands[2]) == REG)) - /* Assembler has weird restrictions. */ - return AS2 (imul%L0,%2,%0); - return AS3 (imul%L0,%2,%1,%0); -}" - [(set_attr "type" "imul")]) - -(define_insn "umulqihi3" - [(set (match_operand:HI 0 "register_operand" "=a") - (mult:HI (zero_extend:HI (match_operand:QI 1 "register_operand" "%0")) - (zero_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))] - "" - "mul%B0 %2" - [(set_attr "type" "imul")]) - -(define_insn "mulqihi3" - [(set (match_operand:HI 0 "register_operand" "=a") - (mult:HI (sign_extend:HI (match_operand:QI 1 "register_operand" "%0")) - (sign_extend:HI (match_operand:QI 2 "nonimmediate_operand" "qm"))))] - "" - "imul%B0 %2" - [(set_attr "type" "imul")]) - -(define_insn "umulsidi3" - [(set (match_operand:DI 0 "register_operand" "=A") - (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%0")) - (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))] - "TARGET_WIDE_MULTIPLY" - "mul%L0 %2" - [(set_attr "type" "imul")]) - -(define_insn "mulsidi3" - [(set (match_operand:DI 0 "register_operand" "=A") - (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%0")) - (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))))] - "TARGET_WIDE_MULTIPLY" - "imul%L0 %2" - [(set_attr "type" "imul")]) - -(define_insn "umulsi3_highpart" - [(set (match_operand:SI 0 "register_operand" "=d") - (truncate:SI (lshiftrt:DI (mult:DI (zero_extend:DI (match_operand:SI 1 "register_operand" "%a")) - (zero_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (const_int 32)))) - (clobber (match_scratch:SI 3 "=a"))] - "TARGET_WIDE_MULTIPLY" - "mul%L0 %2" - [(set_attr "type" "imul")]) - -(define_insn "smulsi3_highpart" - [(set (match_operand:SI 0 "register_operand" "=d") - (truncate:SI (lshiftrt:DI (mult:DI (sign_extend:DI (match_operand:SI 1 "register_operand" "%a")) - (sign_extend:DI (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (const_int 32)))) - (clobber (match_scratch:SI 3 "=a"))] - "TARGET_WIDE_MULTIPLY" - "imul%L0 %2" - [(set_attr "type" "imul")]) - -;; The patterns that match these are at the end of this file. - -(define_expand "mulxf3" - [(set (match_operand:XF 0 "register_operand" "") - (mult:XF (match_operand:XF 1 "register_operand" "") - (match_operand:XF 2 "register_operand" "")))] - "TARGET_80387" - "") - -(define_expand "muldf3" - [(set (match_operand:DF 0 "register_operand" "") - (mult:DF (match_operand:DF 1 "register_operand" "") - (match_operand:DF 2 "nonimmediate_operand" "")))] - "TARGET_80387" - "") - -(define_expand "mulsf3" - [(set (match_operand:SF 0 "register_operand" "") - (mult:SF (match_operand:SF 1 "register_operand" "") - (match_operand:SF 2 "nonimmediate_operand" "")))] - "TARGET_80387" - "") - -;;- divide instructions - -(define_insn "divqi3" - [(set (match_operand:QI 0 "register_operand" "=a") - (div:QI (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "nonimmediate_operand" "qm")))] - "" - "idiv%B0 %2") - -(define_insn "udivqi3" - [(set (match_operand:QI 0 "register_operand" "=a") - (udiv:QI (match_operand:HI 1 "register_operand" "0") - (match_operand:QI 2 "nonimmediate_operand" "qm")))] - "" - "div%B0 %2" - [(set_attr "type" "idiv")]) - -;; The patterns that match these are at the end of this file. - -(define_expand "divxf3" - [(set (match_operand:XF 0 "register_operand" "") - (div:XF (match_operand:XF 1 "register_operand" "") - (match_operand:XF 2 "register_operand" "")))] - "TARGET_80387" - "") - -(define_expand "divdf3" - [(set (match_operand:DF 0 "register_operand" "") - (div:DF (match_operand:DF 1 "register_operand" "") - (match_operand:DF 2 "nonimmediate_operand" "")))] - "TARGET_80387" - "") - -(define_expand "divsf3" - [(set (match_operand:SF 0 "register_operand" "") - (div:SF (match_operand:SF 1 "register_operand" "") - (match_operand:SF 2 "nonimmediate_operand" "")))] - "TARGET_80387" - "") - -;; Remainder instructions. - -(define_insn "divmodsi4" - [(set (match_operand:SI 0 "register_operand" "=a") - (div:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (set (match_operand:SI 3 "register_operand" "=&d") - (mod:SI (match_dup 1) (match_dup 2)))] - "" - "* -{ -#ifdef INTEL_SYNTAX - output_asm_insn (\"cdq\", operands); -#else - output_asm_insn (\"cltd\", operands); -#endif - return AS1 (idiv%L0,%2); -}" - [(set_attr "type" "idiv")]) - -(define_insn "divmodhi4" - [(set (match_operand:HI 0 "register_operand" "=a") - (div:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "nonimmediate_operand" "rm"))) - (set (match_operand:HI 3 "register_operand" "=&d") - (mod:HI (match_dup 1) (match_dup 2)))] - "" - "cwtd\;idiv%W0 %2" - [(set_attr "type" "idiv")]) - -;; ??? Can we make gcc zero extend operand[0]? -(define_insn "udivmodsi4" - [(set (match_operand:SI 0 "register_operand" "=a") - (udiv:SI (match_operand:SI 1 "register_operand" "0") - (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (set (match_operand:SI 3 "register_operand" "=&d") - (umod:SI (match_dup 1) (match_dup 2)))] - "" - "* -{ - output_asm_insn (AS2 (xor%L3,%3,%3), operands); - return AS1 (div%L0,%2); -}" - [(set_attr "type" "idiv")]) - -;; ??? Can we make gcc zero extend operand[0]? -(define_insn "udivmodhi4" - [(set (match_operand:HI 0 "register_operand" "=a") - (udiv:HI (match_operand:HI 1 "register_operand" "0") - (match_operand:HI 2 "nonimmediate_operand" "rm"))) - (set (match_operand:HI 3 "register_operand" "=&d") - (umod:HI (match_dup 1) (match_dup 2)))] - "" - "* -{ - output_asm_insn (AS2 (xor%W0,%3,%3), operands); - return AS1 (div%W0,%2); -}" - [(set_attr "type" "idiv")]) - -/* -;;this should be a valid double division which we may want to add - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=a") - (udiv:DI (match_operand:DI 1 "register_operand" "a") - (match_operand:SI 2 "nonimmediate_operand" "rm"))) - (set (match_operand:SI 3 "register_operand" "=d") - (umod:SI (match_dup 1) (match_dup 2)))] - "" - "div%L0 %2,%0" - [(set_attr "type" "idiv")]) -*/ - -;;- and instructions - -;; On i386, -;; movzbl %bl,%ebx -;; is faster than -;; andl $255,%ebx -;; -;; but if the reg is %eax, then the "andl" is faster. -;; -;; On i486, the "andl" is always faster than the "movzbl". -;; -;; On both i386 and i486, a three operand AND is as fast with movzbl or -;; movzwl as with andl, if operands[0] != operands[1]. - -;; The `r' in `rm' for operand 3 looks redundant, but it causes -;; optional reloads to be generated if op 3 is a pseudo in a stack slot. - -(define_insn "andsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (and:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") - (match_operand:SI 2 "general_operand" "ri,rm")))] - "" - "* -{ - HOST_WIDE_INT intval; - if (!rtx_equal_p (operands[0], operands[1]) - && rtx_equal_p (operands[0], operands[2])) - { - rtx tmp; - tmp = operands[1]; - operands[1] = operands[2]; - operands[2] = tmp; - } - switch (GET_CODE (operands[2])) - { - case CONST_INT: - if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) - break; - intval = INTVAL (operands[2]); - /* zero-extend 16->32? */ - if (intval == 0xffff && REG_P (operands[0]) - && (! REG_P (operands[1]) - || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0) - && (!TARGET_ZERO_EXTEND_WITH_AND || ! rtx_equal_p (operands[0], operands[1]))) - { - /* ??? tege: Should forget CC_STATUS only if we clobber a - remembered operand. Fix that later. */ - CC_STATUS_INIT; -#ifdef INTEL_SYNTAX - return AS2 (movzx,%w1,%0); -#else - return AS2 (movz%W0%L0,%w1,%0); -#endif - } - - /* zero extend 8->32? */ - if (intval == 0xff && REG_P (operands[0]) - && !(REG_P (operands[1]) && NON_QI_REG_P (operands[1])) - && (! REG_P (operands[1]) - || REGNO (operands[0]) != 0 || REGNO (operands[1]) != 0) - && (!TARGET_ZERO_EXTEND_WITH_AND || ! rtx_equal_p (operands[0], operands[1]))) - { - /* ??? tege: Should forget CC_STATUS only if we clobber a - remembered operand. Fix that later. */ - CC_STATUS_INIT; -#ifdef INTEL_SYNTAX - return AS2 (movzx,%b1,%0); -#else - return AS2 (movz%B0%L0,%b1,%0); -#endif - } - - /* Check partial bytes.. non-QI-regs are not available */ - if (REG_P (operands[0]) && ! QI_REG_P (operands[0])) - break; - - /* only low byte has zero bits? */ - if (~(intval | 0xff) == 0) - { - intval &= 0xff; - if (REG_P (operands[0])) - { - if (intval == 0) - { - CC_STATUS_INIT; - return AS2 (xor%B0,%b0,%b0); - } - - /* we're better off with the 32-bit version if reg != EAX */ - /* the value is sign-extended in 8 bits */ - if (REGNO (operands[0]) != 0 && (intval & 0x80)) - break; - } - - CC_STATUS_INIT; - - operands[2] = GEN_INT (intval); - - if (intval == 0) - return AS2 (mov%B0,%2,%b0); - - return AS2 (and%B0,%2,%b0); - } - - /* only second byte has zero? */ - if (~(intval | 0xff00) == 0) - { - CC_STATUS_INIT; - - intval = (intval >> 8) & 0xff; - operands[2] = GEN_INT (intval); - if (intval == 0) - { - if (REG_P (operands[0])) - return AS2 (xor%B0,%h0,%h0); - operands[0] = adj_offsettable_operand (operands[0], 1); - return AS2 (mov%B0,%2,%b0); - } - - if (REG_P (operands[0])) - return AS2 (and%B0,%2,%h0); - - operands[0] = adj_offsettable_operand (operands[0], 1); - return AS2 (and%B0,%2,%b0); - } - - if (REG_P (operands[0])) - break; - - /* third byte has zero bits? */ - if (~(intval | 0xff0000) == 0) - { - intval = (intval >> 16) & 0xff; - operands[0] = adj_offsettable_operand (operands[0], 2); -byte_and_operation: - CC_STATUS_INIT; - operands[2] = GEN_INT (intval); - if (intval == 0) - return AS2 (mov%B0,%2,%b0); - return AS2 (and%B0,%2,%b0); - } - - /* fourth byte has zero bits? */ - if (~(intval | 0xff000000) == 0) - { - intval = (intval >> 24) & 0xff; - operands[0] = adj_offsettable_operand (operands[0], 3); - goto byte_and_operation; - } - - /* Low word is zero? */ - if (intval == 0xffff0000) - { -word_zero_and_operation: - CC_STATUS_INIT; - operands[2] = const0_rtx; - return AS2 (mov%W0,%2,%w0); - } - - /* High word is zero? */ - if (intval == 0x0000ffff) - { - operands[0] = adj_offsettable_operand (operands[0], 2); - goto word_zero_and_operation; - } - - default: - break; - } - - return AS2 (and%L0,%2,%0); -}" - [(set_attr "type" "binary")]) - -(define_insn "andhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (and:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") - (match_operand:HI 2 "general_operand" "ri,rm")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT - && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) - { - /* Can we ignore the upper byte? */ - if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) - && (INTVAL (operands[2]) & 0xff00) == 0xff00) - { - CC_STATUS_INIT; - - if ((INTVAL (operands[2]) & 0xff) == 0) - { - operands[2] = const0_rtx; - return AS2 (mov%B0,%2,%b0); - } - - operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff); - return AS2 (and%B0,%2,%b0); - } - - /* Can we ignore the lower byte? */ - /* ??? what about offsettable memory references? */ - if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & 0xff) == 0xff) - { - CC_STATUS_INIT; - - if ((INTVAL (operands[2]) & 0xff00) == 0) - { - operands[2] = const0_rtx; - return AS2 (mov%B0,%2,%h0); - } - - operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); - return AS2 (and%B0,%2,%h0); - } - - /* use 32-bit ops on registers when there are no sign issues.. */ - if (REG_P (operands[0])) - { - if (!(INTVAL (operands[2]) & ~0x7fff)) - return AS2 (and%L0,%2,%k0); - } - } - - if (REG_P (operands[0]) - && i386_aligned_p (operands[2])) - { - CC_STATUS_INIT; - /* If op[2] is constant, we should zero-extend it and */ - /* make a note that op[0] has been zero-extended, so */ - /* that we could use 32-bit ops on it forthwith, but */ - /* there is no such reg-note available. Instead we do */ - /* a sign extension as that can result in shorter asm */ - operands[2] = i386_sext16_if_const (operands[2]); - return AS2 (and%L0,%k2,%k0); - } - - /* Use a 32-bit word with the upper bits set, invalidate CC */ - if (GET_CODE (operands[2]) == CONST_INT - && i386_aligned_p (operands[0])) - { - HOST_WIDE_INT val = INTVAL (operands[2]); - CC_STATUS_INIT; - val |= ~0xffff; - if (val != INTVAL (operands[2])) - operands[2] = GEN_INT (val); - return AS2 (and%L0,%k2,%k0); - } - - return AS2 (and%W0,%2,%0); -}" - [(set_attr "type" "binary")]) - -(define_insn "andqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (and:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qn,qmn")))] - "" - "* return AS2 (and%B0,%2,%0);" - [(set_attr "type" "binary")]) - -/* I am nervous about these two.. add them later.. -;I presume this means that we have something in say op0= eax which is small -;and we want to and it with memory so we can do this by just an -;andb m,%al and have success. -(define_insn "" - [(set (match_operand:SI 0 "general_operand" "=r") - (and:SI (zero_extend:SI - (match_operand:HI 1 "nonimmediate_operand" "rm")) - (match_operand:SI 2 "general_operand" "0")))] - "GET_CODE (operands[2]) == CONST_INT - && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (HImode))" - "and%W0 %1,%0") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=q") - (and:SI - (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")) - (match_operand:SI 2 "register_operand" "0")))] - "GET_CODE (operands[2]) == CONST_INT - && (unsigned int) INTVAL (operands[2]) < (1 << GET_MODE_BITSIZE (QImode))" - "and%L0 %1,%0") - -*/ - -;;- Bit set (inclusive or) instructions - -;; This optimizes known byte-wide operations to memory, and in some cases -;; to QI registers.. Note that we don't want to use the QI registers too -;; aggressively, because often the 32-bit register instruction is the same -;; size, and likely to be faster on PentiumPro. -(define_insn "iorsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (ior:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") - (match_operand:SI 2 "general_operand" "ri,rm")))] - "" - "* -{ - HOST_WIDE_INT intval; - switch (GET_CODE (operands[2])) - { - case CONST_INT: - - if (REG_P (operands[0]) && ! QI_REG_P (operands[0])) - break; - - /* don't try to optimize volatile accesses */ - if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) - break; - - intval = INTVAL (operands[2]); - if ((intval & ~0xff) == 0) - { - if (REG_P (operands[0])) - { - /* Do low byte access only for %eax or when high bit is set */ - if (REGNO (operands[0]) != 0 && !(intval & 0x80)) - break; - } - -byte_or_operation: - CC_STATUS_INIT; - - if (intval != INTVAL (operands[2])) - operands[2] = GEN_INT (intval); - - if (intval == 0xff) - return AS2 (mov%B0,%2,%b0); - - return AS2 (or%B0,%2,%b0); - } - - /* second byte? */ - if ((intval & ~0xff00) == 0) - { - intval >>= 8; - - if (REG_P (operands[0])) - { - CC_STATUS_INIT; - operands[2] = GEN_INT (intval); - if (intval == 0xff) - return AS2 (mov%B0,%2,%h0); - - return AS2 (or%B0,%2,%h0); - } - - operands[0] = adj_offsettable_operand (operands[0], 1); - goto byte_or_operation; - } - - if (REG_P (operands[0])) - break; - - /* third byte? */ - if ((intval & ~0xff0000) == 0) - { - intval >>= 16; - operands[0] = adj_offsettable_operand (operands[0], 2); - goto byte_or_operation; - } - - /* fourth byte? */ - if ((intval & ~0xff000000) == 0) - { - intval = (intval >> 24) & 0xff; - operands[0] = adj_offsettable_operand (operands[0], 3); - goto byte_or_operation; - } - - default: - break; - } - - return AS2 (or%L0,%2,%0); -}" - [(set_attr "type" "binary")]) - -(define_insn "iorhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (ior:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") - (match_operand:HI 2 "general_operand" "ri,rm")))] - "" - "* -{ - HOST_WIDE_INT intval; - switch (GET_CODE (operands[2])) - { - case CONST_INT: - - if (REG_P (operands[0]) && ! QI_REG_P (operands[0])) - break; - - /* don't try to optimize volatile accesses */ - if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) - break; - - intval = 0xffff & INTVAL (operands[2]); - - if ((intval & 0xff00) == 0) - { - if (REG_P (operands[0])) - { - /* Do low byte access only for %eax or when high bit is set */ - if (REGNO (operands[0]) != 0 && !(intval & 0x80)) - break; - } - -byte_or_operation: - CC_STATUS_INIT; - - if (intval == 0xff) - return AS2 (mov%B0,%2,%b0); - - return AS2 (or%B0,%2,%b0); - } - - /* high byte? */ - if ((intval & 0xff) == 0) - { - intval >>= 8; - operands[2] = GEN_INT (intval); - - if (REG_P (operands[0])) - { - CC_STATUS_INIT; - if (intval == 0xff) - return AS2 (mov%B0,%2,%h0); - - return AS2 (or%B0,%2,%h0); - } - - operands[0] = adj_offsettable_operand (operands[0], 1); - - goto byte_or_operation; - } - - default: - break; - } - - if (REG_P (operands[0]) - && i386_aligned_p (operands[2])) - { - CC_STATUS_INIT; - operands[2] = i386_sext16_if_const (operands[2]); - return AS2 (or%L0,%k2,%k0); - } - - if (GET_CODE (operands[2]) == CONST_INT - && i386_aligned_p (operands[0])) - { - CC_STATUS_INIT; - intval = 0xffff & INTVAL (operands[2]); - if (intval != INTVAL (operands[2])) - operands[2] = GEN_INT (intval); - return AS2 (or%L0,%2,%k0); - } - - return AS2 (or%W0,%2,%0); -}" - [(set_attr "type" "binary")]) - -(define_insn "iorqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (ior:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qn,qmn")))] - "" - "* return AS2 (or%B0,%2,%0);" - [(set_attr "type" "binary")]) - -;;- xor instructions - -(define_insn "xorsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,r") - (xor:SI (match_operand:SI 1 "nonimmediate_operand" "%0,0") - (match_operand:SI 2 "general_operand" "ri,rm")))] - "" - "* -{ - HOST_WIDE_INT intval; - switch (GET_CODE (operands[2])) - { - case CONST_INT: - - if (REG_P (operands[0]) && ! QI_REG_P (operands[0])) - break; - - /* don't try to optimize volatile accesses */ - if (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])) - break; - - intval = INTVAL (operands[2]); - if ((intval & ~0xff) == 0) - { - if (REG_P (operands[0])) - { - /* Do low byte access only for %eax or when high bit is set */ - if (REGNO (operands[0]) != 0 && !(intval & 0x80)) - break; - } - -byte_xor_operation: - CC_STATUS_INIT; - - if (intval == 0xff - && (!TARGET_PENTIUM || optimize_size - || (GET_CODE (operands[0]) == MEM - && memory_address_info (XEXP (operands[0], 0), 1)))) - return AS1 (not%B0,%b0); - - if (intval != INTVAL (operands[2])) - operands[2] = GEN_INT (intval); - return AS2 (xor%B0,%2,%b0); - } - - /* second byte? */ - if ((intval & ~0xff00) == 0) - { - intval >>= 8; - - if (REG_P (operands[0])) - { - CC_STATUS_INIT; - if (intval == 0xff - && (!TARGET_PENTIUM || optimize_size - || (GET_CODE (operands[0]) == MEM - && memory_address_info (XEXP (operands[0], 0), 1)))) - return AS1 (not%B0,%h0); - - operands[2] = GEN_INT (intval); - return AS2 (xor%B0,%2,%h0); - } - - operands[0] = adj_offsettable_operand (operands[0], 1); - - goto byte_xor_operation; - } - - if (REG_P (operands[0])) - break; - - /* third byte? */ - if ((intval & ~0xff0000) == 0) - { - intval >>= 16; - operands[0] = adj_offsettable_operand (operands[0], 2); - goto byte_xor_operation; - } - - /* fourth byte? */ - if ((intval & ~0xff000000) == 0) - { - intval = (intval >> 24) & 0xff; - operands[0] = adj_offsettable_operand (operands[0], 3); - goto byte_xor_operation; - } - - default: - break; - } - - return AS2 (xor%L0,%2,%0); -}" - [(set_attr "type" "binary")]) - -(define_insn "xorhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm,r") - (xor:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0") - (match_operand:HI 2 "general_operand" "ri,rm")))] - "" - "* -{ - if (GET_CODE (operands[2]) == CONST_INT - && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0]))) - { - /* Can we ignore the upper byte? */ - if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) - && (INTVAL (operands[2]) & 0xff00) == 0) - { - CC_STATUS_INIT; - if (INTVAL (operands[2]) & 0xffff0000) - operands[2] = GEN_INT (INTVAL (operands[2]) & 0xffff); - - if (INTVAL (operands[2]) == 0xff - && (!TARGET_PENTIUM || optimize_size - || (GET_CODE (operands[0]) == MEM - && memory_address_info (XEXP (operands[0], 0), 1)))) - return AS1 (not%B0,%b0); - - return AS2 (xor%B0,%2,%b0); - } - - /* Can we ignore the lower byte? */ - /* ??? what about offsettable memory references? */ - if (QI_REG_P (operands[0]) - && (INTVAL (operands[2]) & 0xff) == 0) - { - CC_STATUS_INIT; - operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff); - - if (INTVAL (operands[2]) == 0xff - && (!TARGET_PENTIUM || optimize_size - || (GET_CODE (operands[0]) == MEM - && memory_address_info (XEXP (operands[0], 0), 1)))) - return AS1 (not%B0,%h0); - - return AS2 (xor%B0,%2,%h0); - } - } - - if (REG_P (operands[0]) - && i386_aligned_p (operands[2])) - { - CC_STATUS_INIT; - operands[2] = i386_sext16_if_const (operands[2]); - return AS2 (xor%L0,%k2,%k0); - } - - if (GET_CODE (operands[2]) == CONST_INT - && i386_aligned_p (operands[0])) - { - HOST_WIDE_INT intval; - CC_STATUS_INIT; - intval = 0xffff & INTVAL (operands[2]); - if (intval != INTVAL (operands[2])) - operands[2] = GEN_INT (intval); - return AS2 (xor%L0,%2,%k0); - } - - return AS2 (xor%W0,%2,%0); -}" - [(set_attr "type" "binary")]) - -(define_insn "xorqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm,q") - (xor:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0") - (match_operand:QI 2 "general_operand" "qn,qm")))] - "" - "* return AS2 (xor%B0,%2,%0);" - [(set_attr "type" "binary")]) - -;; logical operations for DImode - -(define_insn "anddi3" - [(set (match_operand:DI 0 "general_operand" "=&r,&ro") - (and:DI (match_operand:DI 1 "general_operand" "%0,0") - (match_operand:DI 2 "general_operand" "oriF,riF")))] - "" - "#" - [(set_attr "type" "binary")]) - - -(define_insn "iordi3" - [(set (match_operand:DI 0 "general_operand" "=&r,&ro") - (ior:DI (match_operand:DI 1 "general_operand" "%0,0") - (match_operand:DI 2 "general_operand" "oriF,riF")))] - "" - "#" - [(set_attr "type" "binary")]) - -(define_insn "xordi3" - [(set (match_operand:DI 0 "general_operand" "=&r,&ro") - (xor:DI (match_operand:DI 1 "general_operand" "%0,0") - (match_operand:DI 2 "general_operand" "oriF,riF")))] - "" - "#" - [(set_attr "type" "binary")]) - -(define_split - [(set (match_operand:DI 0 "general_operand" "") - (match_operator:DI 3 "ix86_logical_operator" - [(match_operand:DI 1 "general_operand" "") - (match_operand:DI 2 "general_operand" "")]))] - "" - [(set (match_dup 4) (match_op_dup:SI 3 [(match_dup 6) (match_dup 8)])) - (set (match_dup 5) (match_op_dup:SI 3 [(match_dup 7) (match_dup 9)]))] - "split_di (&operands[0], 1, &operands[4], &operands[5]); - split_di (&operands[1], 1, &operands[6], &operands[7]); - split_di (&operands[2], 1, &operands[8], &operands[9]);") - -;;- negation instructions - -(define_insn "negdi2" - [(set (match_operand:DI 0 "general_operand" "=&ro") - (neg:DI (match_operand:DI 1 "general_operand" "0")))] - "" - "* -{ - rtx xops[2], low[1], high[1]; - - CC_STATUS_INIT; - - split_di (operands, 1, low, high); - xops[0] = const0_rtx; - xops[1] = high[0]; - - output_asm_insn (AS1 (neg%L0,%0), low); - output_asm_insn (AS2 (adc%L1,%0,%1), xops); - output_asm_insn (AS1 (neg%L0,%0), high); - RET; -}") - -(define_insn "negsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (neg:SI (match_operand:SI 1 "nonimmediate_operand" "0")))] - "" - "neg%L0 %0") - -(define_insn "neghi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")))] - "" - "* - if (REG_P (operands[0]) && i386_cc_probably_useless_p (insn)) - { - CC_STATUS_INIT; - return AS1(neg%L0,%k0); - } - return AS1(neg%W0,%0);") - -(define_insn "negqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (neg:QI (match_operand:QI 1 "nonimmediate_operand" "0")))] - "" - "neg%B0 %0") - -(define_insn "negsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (neg:SF (match_operand:SF 1 "register_operand" "0")))] - "TARGET_80387" - "fchs" - [(set_attr "type" "fpop")]) - -(define_insn "negdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (match_operand:DF 1 "register_operand" "0")))] - "TARGET_80387" - "fchs" - [(set_attr "type" "fpop")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (neg:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))] - "TARGET_80387" - "fchs" - [(set_attr "type" "fpop")]) - -(define_insn "negxf2" - [(set (match_operand:XF 0 "register_operand" "=f") - (neg:XF (match_operand:XF 1 "register_operand" "0")))] - "TARGET_80387" - "fchs" - [(set_attr "type" "fpop")]) - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f") - (neg:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))] - "TARGET_80387" - "fchs" - [(set_attr "type" "fpop")]) - -;; Absolute value instructions - -(define_insn "abssf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (abs:SF (match_operand:SF 1 "register_operand" "0")))] - "TARGET_80387" - "fabs" - [(set_attr "type" "fpop")]) - -(define_insn "absdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (abs:DF (match_operand:DF 1 "register_operand" "0")))] - "TARGET_80387" - "fabs" - [(set_attr "type" "fpop")]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (abs:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))] - "TARGET_80387" - "fabs" - [(set_attr "type" "fpop")]) - -(define_insn "absxf2" - [(set (match_operand:XF 0 "register_operand" "=f") - (abs:XF (match_operand:XF 1 "register_operand" "0")))] - "TARGET_80387" - "fabs" - [(set_attr "type" "fpop")]) - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f") - (abs:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))] - "TARGET_80387" - "fabs" - [(set_attr "type" "fpop")]) - -(define_insn "sqrtsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (sqrt:SF (match_operand:SF 1 "register_operand" "0")))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387" - "fsqrt") - -(define_insn "sqrtdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (sqrt:DF (match_operand:DF 1 "register_operand" "0")))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " - "fsqrt") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (sqrt:DF (float_extend:DF - (match_operand:SF 1 "register_operand" "0"))))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387" - "fsqrt") - -(define_insn "sqrtxf2" - [(set (match_operand:XF 0 "register_operand" "=f") - (sqrt:XF (match_operand:XF 1 "register_operand" "0")))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 - && (TARGET_IEEE_FP || flag_fast_math) " - "fsqrt") - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f") - (sqrt:XF (float_extend:XF - (match_operand:DF 1 "register_operand" "0"))))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387" - "fsqrt") - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f") - (sqrt:XF (float_extend:XF - (match_operand:SF 1 "register_operand" "0"))))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387" - "fsqrt") - -(define_insn "sindf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 1))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" - "fsin") - -(define_insn "sinsf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 1))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" - "fsin") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (unspec:DF [(float_extend:DF - (match_operand:SF 1 "register_operand" "0"))] 1))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" - "fsin") - -(define_insn "sinxf2" - [(set (match_operand:XF 0 "register_operand" "=f") - (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 1))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" - "fsin") - -(define_insn "cosdf2" - [(set (match_operand:DF 0 "register_operand" "=f") - (unspec:DF [(match_operand:DF 1 "register_operand" "0")] 2))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" - "fcos") - -(define_insn "cossf2" - [(set (match_operand:SF 0 "register_operand" "=f") - (unspec:SF [(match_operand:SF 1 "register_operand" "0")] 2))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" - "fcos") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f") - (unspec:DF [(float_extend:DF - (match_operand:SF 1 "register_operand" "0"))] 2))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" - "fcos") - -(define_insn "cosxf2" - [(set (match_operand:XF 0 "register_operand" "=f") - (unspec:XF [(match_operand:XF 1 "register_operand" "0")] 2))] - "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math" - "fcos") - -;;- one complement instructions - -(define_insn "one_cmplsi2" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))] - "" - "* -{ - /* A Pentium NOT is not pariable. Output it only in case of complex - memory address, because XOR will be inpariable anyway because - of immediate/displacement rule. */ - - if (TARGET_PENTIUM && !optimize_size - && (GET_CODE (operands[0]) != MEM - || memory_address_info (XEXP (operands[0], 0), 1) == 0)) - { - rtx xops[2]; - xops[0] = operands[0]; - xops[1] = GEN_INT (0xffffffff); - output_asm_insn (AS2 (xor%L0,%1,%0), xops); - RET; - } - else - return AS1 (not%L0,%0); -}") - -(define_insn "one_cmplhi2" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))] - "" - "* -{ - /* A Pentium NOT is not pariable. Output it only in case of complex - memory address, because XOR will be inpariable anyway because - of immediate/displacement rule. */ - - if (TARGET_PENTIUM && !optimize_size - && (GET_CODE (operands[0]) != MEM - || memory_address_info (XEXP (operands[0], 0), 1) == 0)) - { - rtx xops[2]; - xops[0] = operands[0]; - xops[1] = GEN_INT (0xffff); - if (REG_P (operands[0]) - && i386_cc_probably_useless_p (insn)) - { - CC_STATUS_INIT; - output_asm_insn (AS2 (xor%L0,%1,%k0), xops); - } - else - output_asm_insn (AS2 (xor%W0,%1,%0), xops); - RET; - } - else - { - if (REG_P (operands[0]) - && i386_cc_probably_useless_p (insn)) - { - CC_STATUS_INIT; - return AS1 (not%L0,%k0); - } - return AS1 (not%W0,%0); - } -}") - -(define_insn "one_cmplqi2" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (not:QI (match_operand:QI 1 "nonimmediate_operand" "0")))] - "" - "* -{ - /* A Pentium NOT is not pariable. Output it only in case of complex - memory address, because XOR will be inpariable anyway because - of immediate/displacement rule. */ - - if (TARGET_PENTIUM && !optimize_size - && (GET_CODE (operands[0]) != MEM - || memory_address_info (XEXP (operands[0], 0), 1) == 0)) - { - rtx xops[2]; - xops[0] = operands[0]; - xops[1] = GEN_INT (0xff); - output_asm_insn (AS2 (xor%B0,%1,%0), xops); - RET; - } - else - return AS1 (not%B0,%0); -}") - -;;- arithmetic shift instructions - -;; DImode shifts are implemented using the i386 "shift double" opcode, -;; which is written as "sh[lr]d[lw] imm,reg,reg/mem". If the shift count -;; is variable, then the count is in %cl and the "imm" operand is dropped -;; from the assembler input. - -;; This instruction shifts the target reg/mem as usual, but instead of -;; shifting in zeros, bits are shifted in from reg operand. If the insn -;; is a left shift double, bits are taken from the high order bits of -;; reg, else if the insn is a shift right double, bits are taken from the -;; low order bits of reg. So if %eax is "1234" and %edx is "5678", -;; "shldl $8,%edx,%eax" leaves %edx unchanged and sets %eax to "2345". - -;; Since sh[lr]d does not change the `reg' operand, that is done -;; separately, making all shifts emit pairs of shift double and normal -;; shift. Since sh[lr]d does not shift more than 31 bits, and we wish to -;; support a 63 bit shift, each shift where the count is in a reg expands -;; to a pair of shifts, a branch, a shift by 32 and a label. - -;; If the shift count is a constant, we need never emit more than one -;; shift pair, instead using moves and sign extension for counts greater -;; than 31. - -(define_expand "ashldi3" - [(set (match_operand:DI 0 "register_operand" "") - (ashift:DI (match_operand:DI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT - || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')) - { - operands[2] = copy_to_mode_reg (QImode, operands[2]); - emit_insn (gen_ashldi3_non_const_int (operands[0], operands[1], - operands[2])); - } - else - emit_insn (gen_ashldi3_const_int (operands[0], operands[1], operands[2])); - - DONE; -}") - -(define_insn "ashldi3_const_int" - [(set (match_operand:DI 0 "register_operand" "=&r") - (ashift:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "const_int_operand" "J")))] - "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')" - "* -{ - rtx xops[4], low[1], high[1]; - - CC_STATUS_INIT; - - split_di (operands, 1, low, high); - xops[0] = operands[2]; - xops[1] = const1_rtx; - xops[2] = low[0]; - xops[3] = high[0]; - - if (INTVAL (xops[0]) > 31) - { - output_asm_insn (AS2 (mov%L3,%2,%3), xops); /* Fast shift by 32 */ - output_asm_insn (AS2 (xor%L2,%2,%2), xops); - - if (INTVAL (xops[0]) > 32) - { - xops[0] = GEN_INT (INTVAL (xops[0]) - 32); - output_asm_insn (AS2 (sal%L3,%0,%3), xops); /* Remaining shift */ - } - } - else - { - output_asm_insn (AS3 (shld%L3,%0,%2,%3), xops); - output_asm_insn (AS2 (sal%L2,%0,%2), xops); - } - RET; -}") - -(define_insn "ashldi3_non_const_int" - [(set (match_operand:DI 0 "register_operand" "=&r") - (ashift:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "register_operand" "c")))] - "" - "* -{ - rtx xops[5], low[1], high[1]; - - CC_STATUS_INIT; - - split_di (operands, 1, low, high); - xops[0] = operands[2]; - xops[1] = GEN_INT (32); - xops[2] = low[0]; - xops[3] = high[0]; - xops[4] = gen_label_rtx (); - - output_asm_insn (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops); - output_asm_insn (AS2 (sal%L2,%0,%2), xops); - output_asm_insn (AS2 (test%B0,%1,%b0), xops); - output_asm_insn (AS1 (je,%X4), xops); - output_asm_insn (AS2 (mov%L3,%2,%3), xops); /* Fast shift by 32 */ - output_asm_insn (AS2 (xor%L2,%2,%2), xops); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", - CODE_LABEL_NUMBER (xops[4])); - RET; -}") - -(define_expand "ashlsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "") - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "") - (match_operand:SI 2 "nonmemory_operand" "")))] - "" - "") - -(define_expand "ashlhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "") - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "") - (match_operand:HI 2 "nonmemory_operand" "")))] - "" - "") - -(define_expand "ashlqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "") - (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - "") - -;; Pattern for shifts which can be encoded into an lea instruction. -;; This is kept as a separate pattern so that regmove can optimize cases -;; where we know the source and destination must match. -;; -;; Do not expose this pattern when optimizing for size since we never want -;; to use lea when optimizing for size since mov+sal is smaller than lea. - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=r,r") - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0,r") - (match_operand:SI 2 "small_shift_operand" "M,M")))] - "! optimize_size" - "* return output_ashl (insn, operands);") - -;; Generic left shift pattern to catch all cases not handled by the -;; shift pattern above. -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "cI")))] - "" - "* return output_ashl (insn, operands);") - -(define_insn "" - [(set (match_operand:HI 0 "nonimmediate_operand" "=r,r") - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0,r") - (match_operand:HI 2 "small_shift_operand" "M,M")))] - "! optimize_size" - "* return output_ashl (insn, operands);") - -(define_insn "" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:HI 2 "nonmemory_operand" "cI")))] - "" - "* return output_ashl (insn, operands);") - -(define_insn "" - [(set (match_operand:QI 0 "nonimmediate_operand" "=q,q") - (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0,q") - (match_operand:QI 2 "small_shift_operand" "M,M")))] - "! optimize_size" - "* return output_ashl (insn, operands);") - -;; Generic left shift pattern to catch all cases not handled by the -;; shift pattern above. -(define_insn "" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "cI")))] - "" - "* return output_ashl (insn, operands);") - -;; See comment above `ashldi3' about how this works. - -(define_expand "ashrdi3" - [(set (match_operand:DI 0 "register_operand" "") - (ashiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT - || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')) - { - operands[2] = copy_to_mode_reg (QImode, operands[2]); - emit_insn (gen_ashrdi3_non_const_int (operands[0], operands[1], - operands[2])); - } - else - emit_insn (gen_ashrdi3_const_int (operands[0], operands[1], operands[2])); - - DONE; -}") - -(define_insn "ashldi3_32" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,m") - (ashift:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r") - (const_int 32)))] - "" - "* -{ - rtx low[2], high[2], xops[4]; - - split_di (operands, 2, low, high); - xops[0] = high[0]; - xops[1] = low[1]; - xops[2] = low[0]; - xops[3] = const0_rtx; - if (!rtx_equal_p (xops[0], xops[1])) - output_asm_insn (AS2 (mov%L0,%1,%0), xops); - - if (GET_CODE (low[0]) == MEM) - output_asm_insn (AS2 (mov%L2,%3,%2), xops); - else - output_asm_insn (AS2 (xor%L2,%2,%2), xops); - - RET; -}") - -(define_insn "ashrdi3_const_int" - [(set (match_operand:DI 0 "register_operand" "=&r") - (ashiftrt:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "const_int_operand" "J")))] - "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')" - "* -{ - rtx xops[4], low[1], high[1]; - - CC_STATUS_INIT; - - split_di (operands, 1, low, high); - xops[0] = operands[2]; - xops[1] = const1_rtx; - xops[2] = low[0]; - xops[3] = high[0]; - - if (INTVAL (xops[0]) > 31) - { - xops[1] = GEN_INT (31); - output_asm_insn (AS2 (mov%L2,%3,%2), xops); - output_asm_insn (AS2 (sar%L3,%1,%3), xops); /* shift by 32 */ - - if (INTVAL (xops[0]) > 32) - { - xops[0] = GEN_INT (INTVAL (xops[0]) - 32); - output_asm_insn (AS2 (sar%L2,%0,%2), xops); /* Remaining shift */ - } - } - else - { - output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops); - output_asm_insn (AS2 (sar%L3,%0,%3), xops); - } - - RET; -}") - -(define_insn "ashrdi3_non_const_int" - [(set (match_operand:DI 0 "register_operand" "=&r") - (ashiftrt:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "register_operand" "c")))] - "" - "* -{ - rtx xops[5], low[1], high[1]; - - CC_STATUS_INIT; - - split_di (operands, 1, low, high); - xops[0] = operands[2]; - xops[1] = GEN_INT (32); - xops[2] = low[0]; - xops[3] = high[0]; - xops[4] = gen_label_rtx (); - - output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); - output_asm_insn (AS2 (sar%L3,%0,%3), xops); - output_asm_insn (AS2 (test%B0,%1,%b0), xops); - output_asm_insn (AS1 (je,%X4), xops); - xops[1] = GEN_INT (31); - output_asm_insn (AS2 (mov%L2,%3,%2), xops); - output_asm_insn (AS2 (sar%L3,%1,%3), xops); /* shift by 32 */ - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", - CODE_LABEL_NUMBER (xops[4])); - RET; -}") - -(define_insn "ashrsi3_31" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm,d") - (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0,a") - (const_int 31)))] - "!TARGET_PENTIUM || optimize_size" - "@ - sar%L0 $31,%0 - cltd") - -(define_insn "ashrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "cI")))] - "" - "* -{ - if (REG_P (operands[2])) - return AS2 (sar%L0,%b2,%0); - else - return AS2 (sar%L0,%2,%0); -}") - -(define_insn "ashrhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:HI 2 "nonmemory_operand" "cI")))] - "" - "* -{ - if (REG_P (operands[2])) - return AS2 (sar%W0,%b2,%0); - else - return AS2 (sar%W0,%2,%0); -}") - -(define_insn "ashrqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "cI")))] - "" - "* -{ - if (REG_P (operands[2])) - return AS2 (sar%B0,%b2,%0); - else - return AS2 (sar%B0,%2,%0); -}") - -;;- logical shift instructions - -;; See comment above `ashldi3' about how this works. - -(define_expand "lshrdi3" - [(set (match_operand:DI 0 "register_operand" "") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "") - (match_operand:QI 2 "nonmemory_operand" "")))] - "" - " -{ - if (GET_CODE (operands[2]) != CONST_INT - || ! CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')) - { - operands[2] = copy_to_mode_reg (QImode, operands[2]); - emit_insn (gen_lshrdi3_non_const_int (operands[0], operands[1], - operands[2])); - } - else - emit_insn (gen_lshrdi3_const_int (operands[0], operands[1], operands[2])); - - DONE; -}") - -(define_insn "lshrdi3_32" - [(set (match_operand:DI 0 "nonimmediate_operand" "=r,m") - (lshiftrt:DI (match_operand:DI 1 "nonimmediate_operand" "ro,r") - (const_int 32)))] - "" - "* -{ - rtx low[2], high[2], xops[4]; - - split_di (operands, 2, low, high); - xops[0] = low[0]; - xops[1] = high[1]; - xops[2] = high[0]; - xops[3] = const0_rtx; - if (!rtx_equal_p (xops[0], xops[1])) - output_asm_insn (AS2 (mov%L0,%1,%0), xops); - - if (GET_CODE (low[0]) == MEM) - output_asm_insn (AS2 (mov%L2,%3,%2), xops); - else - output_asm_insn (AS2 (xor%L2,%2,%2), xops); - - RET; -}") - -(define_insn "lshrdi3_const_int" - [(set (match_operand:DI 0 "register_operand" "=&r") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "const_int_operand" "J")))] - "CONST_OK_FOR_LETTER_P (INTVAL (operands[2]), 'J')" - "* -{ - rtx xops[4], low[1], high[1]; - - CC_STATUS_INIT; - - split_di (operands, 1, low, high); - xops[0] = operands[2]; - xops[1] = const1_rtx; - xops[2] = low[0]; - xops[3] = high[0]; - - if (INTVAL (xops[0]) > 31) - { - output_asm_insn (AS2 (mov%L2,%3,%2), xops); /* Fast shift by 32 */ - output_asm_insn (AS2 (xor%L3,%3,%3), xops); - - if (INTVAL (xops[0]) > 32) - { - xops[0] = GEN_INT (INTVAL (xops[0]) - 32); - output_asm_insn (AS2 (shr%L2,%0,%2), xops); /* Remaining shift */ - } - } - else - { - output_asm_insn (AS3 (shrd%L2,%0,%3,%2), xops); - output_asm_insn (AS2 (shr%L3,%0,%3), xops); - } - - RET; -}") - -(define_insn "lshrdi3_non_const_int" - [(set (match_operand:DI 0 "register_operand" "=&r") - (lshiftrt:DI (match_operand:DI 1 "register_operand" "0") - (match_operand:QI 2 "register_operand" "c")))] - "" - "* -{ - rtx xops[5], low[1], high[1]; - - CC_STATUS_INIT; - - split_di (operands, 1, low, high); - xops[0] = operands[2]; - xops[1] = GEN_INT (32); - xops[2] = low[0]; - xops[3] = high[0]; - xops[4] = gen_label_rtx (); - - output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops); - output_asm_insn (AS2 (shr%L3,%0,%3), xops); - output_asm_insn (AS2 (test%B0,%1,%b0), xops); - output_asm_insn (AS1 (je,%X4), xops); - output_asm_insn (AS2 (mov%L2,%3,%2), xops); /* Fast shift by 32 */ - output_asm_insn (AS2 (xor%L3,%3,%3), xops); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", - CODE_LABEL_NUMBER (xops[4])); - RET; -}") - -(define_insn "lshrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "cI")))] - "" - "* -{ - if (REG_P (operands[2])) - return AS2 (shr%L0,%b2,%0); - else - return AS2 (shr%L0,%2,%1); -}") - -(define_insn "lshrhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:HI 2 "nonmemory_operand" "cI")))] - "" - "* -{ - if (REG_P (operands[2])) - return AS2 (shr%W0,%b2,%0); - else - return AS2 (shr%W0,%2,%0); -}") - -(define_insn "lshrqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "cI")))] - "" - "* -{ - if (REG_P (operands[2])) - return AS2 (shr%B0,%b2,%0); - else - return AS2 (shr%B0,%2,%0); -}") - -;;- rotate instructions - -(define_insn "rotlsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "cI")))] - "" - "* -{ - if (REG_P (operands[2])) - return AS2 (rol%L0,%b2,%0); - else - return AS2 (rol%L0,%2,%0); -}") - -(define_insn "rotlhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:HI 2 "nonmemory_operand" "cI")))] - "" - "* -{ - if (REG_P (operands[2])) - return AS2 (rol%W0,%b2,%0); - else - return AS2 (rol%W0,%2,%0); -}") - -(define_insn "rotlqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "cI")))] - "" - "* -{ - if (REG_P (operands[2])) - return AS2 (rol%B0,%b2,%0); - else - return AS2 (rol%B0,%2,%0); -}") - -(define_insn "rotrsi3" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (match_operand:SI 2 "nonmemory_operand" "cI")))] - "" - "* -{ - if (REG_P (operands[2])) - return AS2 (ror%L0,%b2,%0); - else - return AS2 (ror%L0,%2,%0); -}") - -(define_insn "rotrhi3" - [(set (match_operand:HI 0 "nonimmediate_operand" "=rm") - (rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0") - (match_operand:HI 2 "nonmemory_operand" "cI")))] - "" - "* -{ - if (REG_P (operands[2])) - return AS2 (ror%W0,%b2,%0); - else - return AS2 (ror%W0,%2,%0); -}") - -(define_insn "rotrqi3" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0") - (match_operand:QI 2 "nonmemory_operand" "cI")))] - "" - "* -{ - if (REG_P (operands[2])) - return AS2 (ror%B0,%b2,%0); - else - return AS2 (ror%B0,%2,%0); -}") - -/* -;; This usually looses. But try a define_expand to recognize a few case -;; we can do efficiently, such as accessing the "high" QImode registers, -;; %ah, %bh, %ch, %dh. -;; ??? Note this has a botch on the mode of operand 0, which needs to be -;; fixed if this is ever enabled. -(define_insn "insv" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+&r") - (match_operand:SI 1 "immediate_operand" "i") - (match_operand:SI 2 "immediate_operand" "i")) - (match_operand:SI 3 "nonmemory_operand" "ri"))] - "" - "* -{ - if (INTVAL (operands[1]) + INTVAL (operands[2]) > GET_MODE_BITSIZE (SImode)) - abort (); - if (GET_CODE (operands[3]) == CONST_INT) - { - unsigned int mask = (1 << INTVAL (operands[1])) - 1; - operands[1] = GEN_INT (~(mask << INTVAL (operands[2]))); - output_asm_insn (AS2 (and%L0,%1,%0), operands); - operands[3] = GEN_INT (INTVAL (operands[3]) << INTVAL (operands[2])); - output_asm_insn (AS2 (or%L0,%3,%0), operands); - } - else - { - operands[0] = gen_rtx_REG (SImode, REGNO (operands[0])); - if (INTVAL (operands[2])) - output_asm_insn (AS2 (ror%L0,%2,%0), operands); - output_asm_insn (AS3 (shrd%L0,%1,%3,%0), operands); - operands[2] = GEN_INT (BITS_PER_WORD - - INTVAL (operands[1]) - INTVAL (operands[2])); - if (INTVAL (operands[2])) - output_asm_insn (AS2 (ror%L0,%2,%0), operands); - } - RET; -}") -*/ -/* -;; ??? There are problems with the mode of operand[3]. The point of this -;; is to represent an HImode move to a "high byte" register. - -(define_expand "insv" - [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "") - (match_operand:SI 1 "immediate_operand" "") - (match_operand:SI 2 "immediate_operand" "")) - (match_operand:QI 3 "nonmemory_operand" "ri"))] - "" - " -{ - if (GET_CODE (operands[1]) != CONST_INT - || GET_CODE (operands[2]) != CONST_INT) - FAIL; - - if (! (INTVAL (operands[1]) == 8 - && (INTVAL (operands[2]) == 8 || INTVAL (operands[2]) == 0)) - && ! INTVAL (operands[1]) == 1) - FAIL; -}") -*/ - -;; On i386, the register count for a bit operation is *not* truncated, -;; so SHIFT_COUNT_TRUNCATED must not be defined. - -;; On i486, the shift & or/and code is faster than bts or btr. If -;; operands[0] is a MEM, the bt[sr] is half as fast as the normal code. - -;; On i386, bts is a little faster if operands[0] is a reg, and a -;; little slower if operands[0] is a MEM, than the shift & or/and code. -;; Use bts & btr, since they reload better. - -;; General bit set and clear. -(define_insn "" - [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+rm") - (const_int 1) - (match_operand:SI 2 "register_operand" "r")) - (match_operand:SI 3 "const_int_operand" "n"))] - "TARGET_USE_BIT_TEST && GET_CODE (operands[2]) != CONST_INT" - "* -{ - CC_STATUS_INIT; - - if (INTVAL (operands[3]) == 1) - return AS2 (bts%L0,%2,%0); - else - return AS2 (btr%L0,%2,%0); -}") - -;; Bit complement. See comments on previous pattern. -;; ??? Is this really worthwhile? -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (xor:SI (ashift:SI (const_int 1) - (match_operand:SI 1 "register_operand" "r")) - (match_operand:SI 2 "nonimmediate_operand" "0")))] - "TARGET_USE_BIT_TEST && GET_CODE (operands[1]) != CONST_INT" - "* -{ - CC_STATUS_INIT; - - return AS2 (btc%L0,%1,%0); -}") - -(define_insn "" - [(set (match_operand:SI 0 "nonimmediate_operand" "=rm") - (xor:SI (match_operand:SI 1 "nonimmediate_operand" "0") - (ashift:SI (const_int 1) - (match_operand:SI 2 "register_operand" "r"))))] - "TARGET_USE_BIT_TEST && GET_CODE (operands[2]) != CONST_INT" - "* -{ - CC_STATUS_INIT; - - return AS2 (btc%L0,%2,%0); -}") - -;; Recognizers for bit-test instructions. - -;; The bt opcode allows a MEM in operands[0]. But on both i386 and -;; i486, it is faster to copy a MEM to REG and then use bt, than to use -;; bt on the MEM directly. - -;; ??? The first argument of a zero_extract must not be reloaded, so -;; don't allow a MEM in the operand predicate without allowing it in the -;; constraint. - -(define_insn "" - [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r") - (const_int 1) - (match_operand:SI 1 "register_operand" "r")))] - "GET_CODE (operands[1]) != CONST_INT" - "* -{ - cc_status.flags |= CC_Z_IN_NOT_C; - return AS2 (bt%L0,%1,%0); -}") - -(define_insn "" - [(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r") - (match_operand:SI 1 "const_int_operand" "n") - (match_operand:SI 2 "const_int_operand" "n")))] - "" - "* -{ - unsigned int mask; - - mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]); - operands[1] = GEN_INT (mask); - - if (QI_REG_P (operands[0]) - /* A Pentium test is pairable only with eax. Not with ah or al. */ - && (! REG_P (operands[0]) || REGNO (operands[0]) || !TARGET_PENTIUM - || optimize_size)) - { - if ((mask & ~0xff) == 0) - { - cc_status.flags |= CC_NOT_NEGATIVE; - return AS2 (test%B0,%1,%b0); - } - - if ((mask & ~0xff00) == 0) - { - cc_status.flags |= CC_NOT_NEGATIVE; - operands[1] = GEN_INT (mask >> 8); - return AS2 (test%B0,%1,%h0); - } - } - - return AS2 (test%L0,%1,%0); -}") - -;; ??? All bets are off if operand 0 is a volatile MEM reference. -;; The CPU may access unspecified bytes around the actual target byte. - -(define_insn "" - [(set (cc0) (zero_extract (match_operand:QI 0 "memory_operand" "m") - (match_operand:SI 1 "const_int_operand" "n") - (match_operand:SI 2 "const_int_operand" "n")))] - "GET_CODE (operands[0]) != MEM || ! MEM_VOLATILE_P (operands[0])" - "* -{ - unsigned int mask; - - mask = ((1 << INTVAL (operands[1])) - 1) << INTVAL (operands[2]); - operands[1] = GEN_INT (mask); - - if ((! REG_P (operands[0]) || QI_REG_P (operands[0])) - /* A Pentium test is pairable only with eax. Not with ah or al. */ - && (! REG_P (operands[0]) || REGNO (operands[0]) || !TARGET_PENTIUM - || optimize_size)) - { - if ((mask & ~0xff) == 0) - { - cc_status.flags |= CC_NOT_NEGATIVE; - return AS2 (test%B0,%1,%b0); - } - - if ((mask & ~0xff00) == 0) - { - cc_status.flags |= CC_NOT_NEGATIVE; - operands[1] = GEN_INT (mask >> 8); - - if (QI_REG_P (operands[0])) - return AS2 (test%B0,%1,%h0); - else - { - operands[0] = adj_offsettable_operand (operands[0], 1); - return AS2 (test%B0,%1,%b0); - } - } - - if (GET_CODE (operands[0]) == MEM && (mask & ~0xff0000) == 0) - { - cc_status.flags |= CC_NOT_NEGATIVE; - operands[1] = GEN_INT (mask >> 16); - operands[0] = adj_offsettable_operand (operands[0], 2); - return AS2 (test%B0,%1,%b0); - } - - if (GET_CODE (operands[0]) == MEM && (mask & ~0xff000000) == 0) - { - cc_status.flags |= CC_NOT_NEGATIVE; - operands[1] = GEN_INT (mask >> 24); - operands[0] = adj_offsettable_operand (operands[0], 3); - return AS2 (test%B0,%1,%b0); - } - } - - if (CONSTANT_P (operands[1]) || GET_CODE (operands[0]) == MEM) - return AS2 (test%L0,%1,%0); - - return AS2 (test%L1,%0,%1); -}") - -;; Store-flag instructions. - -;; For all sCOND expanders, also expand the compare or test insn that -;; generates cc0. Generate an equality comparison if `seq' or `sne'. - -(define_expand "seq" - [(match_dup 1) - (set (match_operand:QI 0 "register_operand" "") - (eq:QI (cc0) (const_int 0)))] - "" - " -{ - if (TARGET_IEEE_FP - && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT) - operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1); - else - operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1); -}") - -(define_expand "sne" - [(match_dup 1) - (set (match_operand:QI 0 "register_operand" "") - (ne:QI (cc0) (const_int 0)))] - "" - " -{ - if (TARGET_IEEE_FP - && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT) - operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1); - else - operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1); -}") - -(define_expand "sgt" - [(match_dup 1) - (set (match_operand:QI 0 "register_operand" "") - (gt:QI (cc0) (const_int 0)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -(define_expand "sgtu" - [(match_dup 1) - (set (match_operand:QI 0 "register_operand" "") - (gtu:QI (cc0) (const_int 0)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -(define_expand "slt" - [(match_dup 1) - (set (match_operand:QI 0 "register_operand" "") - (lt:QI (cc0) (const_int 0)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -(define_expand "sltu" - [(match_dup 1) - (set (match_operand:QI 0 "register_operand" "") - (ltu:QI (cc0) (const_int 0)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -(define_expand "sge" - [(match_dup 1) - (set (match_operand:QI 0 "register_operand" "") - (ge:QI (cc0) (const_int 0)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -(define_expand "sgeu" - [(match_dup 1) - (set (match_operand:QI 0 "register_operand" "") - (geu:QI (cc0) (const_int 0)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -(define_expand "sle" - [(match_dup 1) - (set (match_operand:QI 0 "register_operand" "") - (le:QI (cc0) (const_int 0)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -(define_expand "sleu" - [(match_dup 1) - (set (match_operand:QI 0 "register_operand" "") - (leu:QI (cc0) (const_int 0)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -;; The 386 sCOND opcodes can write to memory. But a gcc sCOND insn may -;; not have any input reloads. A MEM write might need an input reload -;; for the address of the MEM. So don't allow MEM as the SET_DEST. - -(define_insn "*setcc" - [(set (match_operand:QI 0 "nonimmediate_operand" "=qm") - (match_operator:QI 1 "comparison_operator" [(cc0) (const_int 0)]))] - "reload_completed || register_operand (operands[0], QImode)" - "* -{ - enum rtx_code code = GET_CODE (operands[1]); - if (cc_prev_status.flags & CC_TEST_AX) - { - int eq; - HOST_WIDE_INT c; - operands[2] = gen_rtx_REG (SImode, 0); - switch (code) - { - case EQ: - c = 0x4000; - eq = 0; - break; - case NE: - c = 0x4000; - eq = 1; - break; - case GT: - c = 0x4100; - eq = 1; - break; - case LT: - c = 0x100; - eq = 0; - break; - case GE: - c = 0x100; - eq = 1; - break; - case LE: - c = 0x4100; - eq = 0; - break; - default: - abort (); - } - if (!TARGET_PENTIUM || optimize_size) - { - operands[3] = GEN_INT (c >> 8); - output_asm_insn (AS2 (test%B0,%3,%h2), operands); - } - else - { - operands[3] = GEN_INT (c); - output_asm_insn (AS2 (test%L0,%3,%2), operands); - } - return eq ? AS1 (sete,%0) : AS1 (setne, %0); - } - - if ((cc_status.flags & CC_NO_OVERFLOW) && (code == LE || code == GT)) - return (char *)0; - return AS1(set%D1,%0); -}") - - -;; Basic conditional jump instructions. -;; We ignore the overflow flag for signed branch instructions. - -;; For all bCOND expanders, also expand the compare or test insn that -;; generates cc0. Generate an equality comparison if `beq' or `bne'. - -(define_expand "beq" - [(match_dup 1) - (set (pc) - (if_then_else (eq (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_IEEE_FP - && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT) - operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1); - else - operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1); -}") - -(define_expand "bne" - [(match_dup 1) - (set (pc) - (if_then_else (ne (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - " -{ - if (TARGET_IEEE_FP - && GET_MODE_CLASS (GET_MODE (i386_compare_op0)) == MODE_FLOAT) - operands[1] = (*i386_compare_gen_eq)(i386_compare_op0, i386_compare_op1); - else - operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1); -}") - - -(define_expand "bgt" - [(match_dup 1) - (set (pc) - (if_then_else (gt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -(define_expand "bgtu" - [(match_dup 1) - (set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -(define_expand "blt" - [(match_dup 1) - (set (pc) - (if_then_else (lt (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - - -(define_expand "bltu" - [(match_dup 1) - (set (pc) - (if_then_else (ltu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -(define_expand "bge" - [(match_dup 1) - (set (pc) - (if_then_else (ge (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -(define_expand "bgeu" - [(match_dup 1) - (set (pc) - (if_then_else (geu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -(define_expand "ble" - [(match_dup 1) - (set (pc) - (if_then_else (le (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -(define_expand "bleu" - [(match_dup 1) - (set (pc) - (if_then_else (leu (cc0) - (const_int 0)) - (label_ref (match_operand 0 "" "")) - (pc)))] - "" - "operands[1] = (*i386_compare_gen)(i386_compare_op0, i386_compare_op1);") - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(cc0) (const_int 0)]) - (label_ref (match_operand 1 "" "")) - (pc)))] - "" - "* -{ - enum rtx_code code = GET_CODE (operands[0]); - if (cc_prev_status.flags & CC_TEST_AX) - { - int eq; - HOST_WIDE_INT c; - operands[2] = gen_rtx_REG (SImode, 0); - switch (code) - { - case EQ: - c = 0x4000; - eq = 0; - break; - case NE: - c = 0x4000; - eq = 1; - break; - case GT: - c = 0x4100; - eq = 1; - break; - case LT: - c = 0x100; - eq = 0; - break; - case GE: - c = 0x100; - eq = 1; - break; - case LE: - c = 0x4100; - eq = 0; - break; - default: - abort (); - } - if (!TARGET_PENTIUM || optimize_size) - { - operands[3] = GEN_INT (c >> 8); - output_asm_insn (AS2 (test%B0,%3,%h2), operands); - } - else - { - operands[3] = GEN_INT (c); - output_asm_insn (AS2 (test%L0,%3,%2), operands); - } - return eq ? AS1 (je,%l1) : AS1 (jne, %l1); - } - if ((cc_status.flags & CC_NO_OVERFLOW) && (code == LE || code == GT)) - return (char *)0; - - return AS1(j%D0,%l1); -}") - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "comparison_operator" - [(cc0) (const_int 0)]) - (pc) - (label_ref (match_operand 1 "" ""))))] - "" - "* -{ - enum rtx_code code = GET_CODE (operands[0]); - if (cc_prev_status.flags & CC_TEST_AX) - { - int eq; - HOST_WIDE_INT c; - operands[2] = gen_rtx_REG (SImode, 0); - switch (code) - { - case EQ: - c = 0x4000; - eq = 1; - break; - case NE: - c = 0x4000; - eq = 0; - break; - case GT: - c = 0x4100; - eq = 0; - break; - case LT: - c = 0x100; - eq = 1; - break; - case GE: - c = 0x100; - eq = 0; - break; - case LE: - c = 0x4100; - eq = 1; - break; - default: - abort (); - } - if (!TARGET_PENTIUM || optimize_size) - { - operands[3] = GEN_INT (c >> 8); - output_asm_insn (AS2 (test%B0,%3,%h2), operands); - } - else - { - operands[3] = GEN_INT (c); - output_asm_insn (AS2 (test%L0,%3,%2), operands); - } - return eq ? AS1 (je,%l1) : AS1 (jne, %l1); - } - if ((cc_status.flags & CC_NO_OVERFLOW) && (code == LE || code == GT)) - return (char *)0; - - return AS1(j%d0,%l1); -}") - -;; Unconditional and other jump instructions - -(define_insn "jump" - [(set (pc) - (label_ref (match_operand 0 "" "")))] - "" - "jmp %l0" - [(set_attr "memory" "none")]) - -(define_insn "indirect_jump" - [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))] - "" - "* -{ - CC_STATUS_INIT; - - return AS1 (jmp,%*%0); -}" - [(set_attr "memory" "none")]) - -;; ??? could transform while(--i > 0) S; to if (--i > 0) do S; while(--i); -;; if S does not change i - -(define_expand "decrement_and_branch_until_zero" - [(parallel [(set (pc) - (if_then_else (ge (plus:SI (match_operand:SI 0 "general_operand" "") - (const_int -1)) - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1)))])] - "" - "") - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "arithmetic_comparison_operator" - [(plus:SI (match_operand:SI 1 "nonimmediate_operand" "+c*r,m") - (match_operand:SI 2 "general_operand" "rmi,ri")) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc))) - (set (match_dup 1) - (plus:SI (match_dup 1) - (match_dup 2)))] - "" - "* -{ - CC_STATUS_INIT; - - if (GET_CODE (operands[1]) == REG && REGNO (operands[2]) == 2 && - operands[2] == constm1_rtx && ix86_cpu == PROCESSOR_K6) - return \"loop %l3\"; - - if (operands[2] == constm1_rtx) - output_asm_insn (AS1 (dec%L1,%1), operands); - - else if (operands[2] == const1_rtx) - output_asm_insn (AS1 (inc%L1,%1), operands); - - else - output_asm_insn (AS2 (add%L1,%2,%1), operands); - - return AS1 (%J0,%l3); -}") - -(define_insn "" - [(set (pc) - (if_then_else (match_operator 0 "arithmetic_comparison_operator" - [(minus:SI (match_operand:SI 1 "nonimmediate_operand" "+r,m") - (match_operand:SI 2 "general_operand" "rmi,ri")) - (const_int 0)]) - (label_ref (match_operand 3 "" "")) - (pc))) - (set (match_dup 1) - (minus:SI (match_dup 1) - (match_dup 2)))] - "" - "* -{ - CC_STATUS_INIT; - if (operands[2] == const1_rtx) - output_asm_insn (AS1 (dec%L1,%1), operands); - - else if (operands[1] == constm1_rtx) - output_asm_insn (AS1 (inc%L1,%1), operands); - - else - output_asm_insn (AS2 (sub%L1,%2,%1), operands); - - return AS1 (%J0,%l3); -}") - -(define_insn "" - [(set (pc) - (if_then_else (ne (match_operand:SI 0 "general_operand" "+g") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1)))] - "" - "* -{ - CC_STATUS_INIT; - operands[2] = const1_rtx; - output_asm_insn (AS2 (sub%L0,%2,%0), operands); - return \"jnc %l1\"; -}") - -(define_insn "" - [(set (pc) - (if_then_else (eq (match_operand:SI 0 "general_operand" "+g") - (const_int 0)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1)))] - "" - "* -{ - CC_STATUS_INIT; - operands[2] = const1_rtx; - output_asm_insn (AS2 (sub%L0,%2,%0), operands); - return \"jc %l1\"; -}") - -(define_insn "" - [(set (pc) - (if_then_else (ne (match_operand:SI 0 "general_operand" "+g") - (const_int 1)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1)))] - "" - "* -{ - CC_STATUS_INIT; - output_asm_insn (AS1 (dec%L0,%0), operands); - return \"jnz %l1\"; -}") - -(define_insn "" - [(set (pc) - (if_then_else (eq (match_operand:SI 0 "general_operand" "+g") - (const_int 1)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int -1)))] - "" - "* -{ - CC_STATUS_INIT; - output_asm_insn (AS1 (dec%L0,%0), operands); - return \"jz %l1\"; -}") - -(define_insn "" - [(set (pc) - (if_then_else (ne (match_operand:SI 0 "general_operand" "+g") - (const_int -1)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int 1)))] - "" - "* -{ - CC_STATUS_INIT; - output_asm_insn (AS1 (inc%L0,%0), operands); - return \"jnz %l1\"; -}") - -(define_insn "" - [(set (pc) - (if_then_else (eq (match_operand:SI 0 "general_operand" "+g") - (const_int -1)) - (label_ref (match_operand 1 "" "")) - (pc))) - (set (match_dup 0) - (plus:SI (match_dup 0) - (const_int 1)))] - "" - "* -{ - CC_STATUS_INIT; - output_asm_insn (AS1 (inc%L0,%0), operands); - return \"jz %l1\"; -}") - -;; Implement switch statements when generating PIC code. Switches are -;; implemented by `tablejump' when not using -fpic. - -;; Emit code here to do the range checking and make the index zero based. - -(define_expand "casesi" - [(set (match_dup 5) - (match_operand:SI 0 "general_operand" "")) - (set (match_dup 6) - (minus:SI (match_dup 5) - (match_operand:SI 1 "general_operand" ""))) - (set (cc0) - (compare:CC (match_dup 6) - (match_operand:SI 2 "general_operand" ""))) - (set (pc) - (if_then_else (gtu (cc0) - (const_int 0)) - (label_ref (match_operand 4 "" "")) - (pc))) - (parallel - [(set (pc) - (minus:SI (reg:SI 3) - (mem:SI (plus:SI (mult:SI (match_dup 6) - (const_int 4)) - (label_ref (match_operand 3 "" "")))))) - (clobber (match_scratch:SI 7 ""))])] - "flag_pic" - " -{ - operands[5] = gen_reg_rtx (SImode); - operands[6] = gen_reg_rtx (SImode); - current_function_uses_pic_offset_table = 1; -}") - -;; Implement a casesi insn. - -;; Each entry in the "addr_diff_vec" looks like this as the result of the -;; two rules below: -;; -;; .long _GLOBAL_OFFSET_TABLE_+[.-.L2] -;; -;; 1. An expression involving an external reference may only use the -;; addition operator, and only with an assembly-time constant. -;; The example above satisfies this because ".-.L2" is a constant. -;; -;; 2. The symbol _GLOBAL_OFFSET_TABLE_ is magic, and at link time is -;; given the value of "GOT - .", where GOT is the actual address of -;; the Global Offset Table. Therefore, the .long above actually -;; stores the value "( GOT - . ) + [ . - .L2 ]", or "GOT - .L2". The -;; expression "GOT - .L2" by itself would generate an error from as(1). -;; -;; The pattern below emits code that looks like this: -;; -;; movl %ebx,reg -;; subl TABLE@GOTOFF(%ebx,index,4),reg -;; jmp reg -;; -;; The addr_diff_vec contents may be directly referenced with @GOTOFF, since -;; the addr_diff_vec is known to be part of this module. -;; -;; The subl above calculates "GOT - (( GOT - . ) + [ . - .L2 ])", which -;; evaluates to just ".L2". - -(define_insn "" - [(set (pc) - (minus:SI (reg:SI 3) - (mem:SI (plus:SI - (mult:SI (match_operand:SI 0 "register_operand" "r") - (const_int 4)) - (label_ref (match_operand 1 "" "")))))) - (clobber (match_scratch:SI 2 "=&r"))] - "" - "* -{ - rtx xops[4]; - - xops[0] = operands[0]; - xops[1] = operands[1]; - xops[2] = operands[2]; - xops[3] = pic_offset_table_rtx; - - output_asm_insn (AS2 (mov%L2,%3,%2), xops); - output_asm_insn (\"sub%L2 %l1@GOTOFF(%3,%0,4),%2\", xops); - output_asm_insn (AS1 (jmp,%*%2), xops); - ASM_OUTPUT_ALIGN (asm_out_file, i386_align_jumps); - RET; -}") - -(define_insn "tablejump" - [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm")) - (use (label_ref (match_operand 1 "" "")))] - "" - "* -{ - CC_STATUS_INIT; - - return AS1 (jmp,%*%0); -}") - -;; Call insns. - -;; If generating PIC code, the predicate indirect_operand will fail -;; for operands[0] containing symbolic references on all of the named -;; call* patterns. Each named pattern is followed by an unnamed pattern -;; that matches any call to a symbolic CONST (ie, a symbol_ref). The -;; unnamed patterns are only used while generating PIC code, because -;; otherwise the named patterns match. - -;; Call subroutine returning no value. - -(define_expand "call_pop" - [(parallel [(call (match_operand:QI 0 "indirect_operand" "") - (match_operand:SI 1 "general_operand" "")) - (set (reg:SI 7) - (plus:SI (reg:SI 7) - (match_operand:SI 3 "immediate_operand" "")))])] - "" - " -{ - rtx addr; - - if (operands[3] == const0_rtx) - { - emit_insn (gen_call (operands[0], operands[1])); - DONE; - } - - if (flag_pic) - current_function_uses_pic_offset_table = 1; - - /* With half-pic, force the address into a register. */ - addr = XEXP (operands[0], 0); - if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) - XEXP (operands[0], 0) = force_reg (Pmode, addr); - - if (! expander_call_insn_operand (operands[0], QImode)) - operands[0] - = change_address (operands[0], VOIDmode, - copy_to_mode_reg (Pmode, XEXP (operands[0], 0))); -}") - -(define_insn "" - [(call (match_operand:QI 0 "call_insn_operand" "m") - (match_operand:SI 1 "general_operand" "g")) - (set (reg:SI 7) (plus:SI (reg:SI 7) - (match_operand:SI 3 "immediate_operand" "i")))] - "" - "* -{ - if (GET_CODE (operands[0]) == MEM - && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - { - operands[0] = XEXP (operands[0], 0); - return AS1 (call,%*%0); - } - else - return AS1 (call,%P0); -}") - -(define_insn "" - [(call (mem:QI (match_operand:SI 0 "symbolic_operand" "")) - (match_operand:SI 1 "general_operand" "g")) - (set (reg:SI 7) (plus:SI (reg:SI 7) - (match_operand:SI 3 "immediate_operand" "i")))] - "!HALF_PIC_P ()" - "call %P0") - -(define_expand "call" - [(call (match_operand:QI 0 "indirect_operand" "") - (match_operand:SI 1 "general_operand" ""))] - ;; Operand 1 not used on the i386. - "" - " -{ - rtx addr; - - if (flag_pic) - current_function_uses_pic_offset_table = 1; - - /* With half-pic, force the address into a register. */ - addr = XEXP (operands[0], 0); - if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) - XEXP (operands[0], 0) = force_reg (Pmode, addr); - - if (! expander_call_insn_operand (operands[0], QImode)) - operands[0] - = change_address (operands[0], VOIDmode, - copy_to_mode_reg (Pmode, XEXP (operands[0], 0))); -}") - -(define_insn "" - [(call (match_operand:QI 0 "call_insn_operand" "m") - (match_operand:SI 1 "general_operand" "g"))] - ;; Operand 1 not used on the i386. - "" - "* -{ - if (GET_CODE (operands[0]) == MEM - && ! CONSTANT_ADDRESS_P (XEXP (operands[0], 0))) - { - operands[0] = XEXP (operands[0], 0); - return AS1 (call,%*%0); - } - else - return AS1 (call,%P0); -}") - -(define_insn "" - [(call (mem:QI (match_operand:SI 0 "symbolic_operand" "")) - (match_operand:SI 1 "general_operand" "g"))] - ;; Operand 1 not used on the i386. - "!HALF_PIC_P ()" - "call %P0") - -;; Call subroutine, returning value in operand 0 -;; (which must be a hard register). - -(define_expand "call_value_pop" - [(parallel [(set (match_operand 0 "" "") - (call (match_operand:QI 1 "indirect_operand" "") - (match_operand:SI 2 "general_operand" ""))) - (set (reg:SI 7) - (plus:SI (reg:SI 7) - (match_operand:SI 4 "immediate_operand" "")))])] - "" - " -{ - rtx addr; - - if (operands[4] == const0_rtx) - { - emit_insn (gen_call_value (operands[0], operands[1], operands[2])); - DONE; - } - - if (flag_pic) - current_function_uses_pic_offset_table = 1; - - /* With half-pic, force the address into a register. */ - addr = XEXP (operands[1], 0); - if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) - XEXP (operands[1], 0) = force_reg (Pmode, addr); - - if (! expander_call_insn_operand (operands[1], QImode)) - operands[1] - = change_address (operands[1], VOIDmode, - copy_to_mode_reg (Pmode, XEXP (operands[1], 0))); -}") - -(define_insn "" - [(set (match_operand 0 "" "=rf") - (call (match_operand:QI 1 "call_insn_operand" "m") - (match_operand:SI 2 "general_operand" "g"))) - (set (reg:SI 7) (plus:SI (reg:SI 7) - (match_operand:SI 4 "immediate_operand" "i")))] - "" - "* -{ - if (GET_CODE (operands[1]) == MEM - && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - { - operands[1] = XEXP (operands[1], 0); - output_asm_insn (AS1 (call,%*%1), operands); - } - else - output_asm_insn (AS1 (call,%P1), operands); - - RET; -}") - -(define_insn "" - [(set (match_operand 0 "" "=rf") - (call (mem:QI (match_operand:SI 1 "symbolic_operand" "")) - (match_operand:SI 2 "general_operand" "g"))) - (set (reg:SI 7) (plus:SI (reg:SI 7) - (match_operand:SI 4 "immediate_operand" "i")))] - "!HALF_PIC_P ()" - "call %P1") - -(define_expand "call_value" - [(set (match_operand 0 "" "") - (call (match_operand:QI 1 "indirect_operand" "") - (match_operand:SI 2 "general_operand" "")))] - ;; Operand 2 not used on the i386. - "" - " -{ - rtx addr; - - if (flag_pic) - current_function_uses_pic_offset_table = 1; - - /* With half-pic, force the address into a register. */ - addr = XEXP (operands[1], 0); - if (GET_CODE (addr) != REG && HALF_PIC_P () && !CONSTANT_ADDRESS_P (addr)) - XEXP (operands[1], 0) = force_reg (Pmode, addr); - - if (! expander_call_insn_operand (operands[1], QImode)) - operands[1] - = change_address (operands[1], VOIDmode, - copy_to_mode_reg (Pmode, XEXP (operands[1], 0))); -}") - -(define_insn "" - [(set (match_operand 0 "" "=rf") - (call (match_operand:QI 1 "call_insn_operand" "m") - (match_operand:SI 2 "general_operand" "g")))] - ;; Operand 2 not used on the i386. - "" - "* -{ - if (GET_CODE (operands[1]) == MEM - && ! CONSTANT_ADDRESS_P (XEXP (operands[1], 0))) - { - operands[1] = XEXP (operands[1], 0); - output_asm_insn (AS1 (call,%*%1), operands); - } - else - output_asm_insn (AS1 (call,%P1), operands); - - RET; -}") - -(define_insn "" - [(set (match_operand 0 "" "=rf") - (call (mem:QI (match_operand:SI 1 "symbolic_operand" "")) - (match_operand:SI 2 "general_operand" "g")))] - ;; Operand 2 not used on the i386. - "!HALF_PIC_P ()" - "call %P1") - -;; Call subroutine returning any type. - -(define_expand "untyped_call" - [(parallel [(call (match_operand 0 "" "") - (const_int 0)) - (match_operand 1 "" "") - (match_operand 2 "" "")])] - "" - " -{ - int i; - - /* In order to give reg-stack an easier job in validating two - coprocessor registers as containing a possible return value, - simply pretend the untyped call returns a complex long double - value. */ - - emit_call_insn (TARGET_80387 - ? gen_call_value (gen_rtx_REG (XCmode, FIRST_FLOAT_REG), - operands[0], const0_rtx) - : gen_call (operands[0], const0_rtx)); - - for (i = 0; i < XVECLEN (operands[2], 0); i++) - { - rtx set = XVECEXP (operands[2], 0, i); - emit_move_insn (SET_DEST (set), SET_SRC (set)); - } - - /* The optimizer does not know that the call sets the function value - registers we stored in the result block. We avoid problems by - claiming that all hard registers are used and clobbered at this - point. */ - emit_insn (gen_blockage ()); - - DONE; -}") - -;; UNSPEC_VOLATILE is considered to use and clobber all hard registers and -;; all of memory. This blocks insns from being moved across this point. - -(define_insn "blockage" - [(unspec_volatile [(const_int 0)] 0)] - "" - "" - [(set_attr "memory" "none")]) - -;; Insn emitted into the body of a function to return from a function. -;; This is only done if the function's epilogue is known to be simple. -;; See comments for simple_386_epilogue in i386.c. - -(define_expand "return" - [(return)] - "ix86_can_use_return_insn_p ()" - "") - -(define_insn "return_internal" - [(return)] - "reload_completed" - "ret" - [(set_attr "memory" "none")]) - -(define_insn "return_pop_internal" - [(return) - (use (match_operand:SI 0 "const_int_operand" ""))] - "reload_completed" - "ret %0" - [(set_attr "memory" "none")]) - -(define_insn "nop" - [(const_int 0)] - "" - "nop" - [(set_attr "memory" "none")]) - -(define_expand "prologue" - [(const_int 1)] - "" - " -{ - ix86_expand_prologue (); - DONE; -}") - -;; The use of UNSPEC here is currently not necessary - a simple SET of ebp -;; to itself would be enough. But this way we are safe even if some optimizer -;; becomes too clever in the future. -(define_insn "prologue_set_stack_ptr" - [(set (reg:SI 7) - (minus:SI (reg:SI 7) (match_operand:SI 0 "immediate_operand" "i"))) - (set (reg:SI 6) (unspec:SI [(reg:SI 6)] 4))] - "" - "* -{ - rtx xops [2]; - - xops[0] = operands[0]; - xops[1] = stack_pointer_rtx; - output_asm_insn (AS2 (sub%L1,%0,%1), xops); - RET; -}" - [(set_attr "memory" "none")]) - -(define_insn "prologue_set_got" - [(set (match_operand:SI 0 "" "") - (unspec_volatile - [(plus:SI (match_dup 0) - (plus:SI (match_operand:SI 1 "symbolic_operand" "") - (minus:SI (pc) (match_operand 2 "" ""))))] 1))] - "" - "* -{ - char buffer[64]; - - if (TARGET_DEEP_BRANCH_PREDICTION) - { - sprintf (buffer, \"addl %s,%%0\", XSTR (operands[1], 0)); - output_asm_insn (buffer, operands); - } - else - { - sprintf (buffer, \"addl %s+[.-%%X2],%%0\", XSTR (operands[1], 0)); - output_asm_insn (buffer, operands); - } - RET; -}") - -(define_insn "prologue_get_pc" - [(set (match_operand:SI 0 "" "") - (unspec_volatile [(plus:SI (pc) (match_operand 1 "" ""))] 2))] - "" - "* -{ - output_asm_insn (AS1 (call,%X1), operands); - if (! TARGET_DEEP_BRANCH_PREDICTION) - { - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (operands[1])); - } - RET; -}" - [(set_attr "memory" "none")]) - -(define_insn "prologue_get_pc_and_set_got" - [(unspec_volatile [(match_operand:SI 0 "" "")] 3)] - "" - "* -{ - operands[1] = gen_label_rtx (); - output_asm_insn (AS1 (call,%X1), operands); - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", - CODE_LABEL_NUMBER (operands[1])); - output_asm_insn (AS1 (pop%L0,%0), operands); - output_asm_insn (\"addl $%__GLOBAL_OFFSET_TABLE_+[.-%X1],%0\", operands); - RET; -}" - [(set_attr "memory" "none")]) - -(define_expand "epilogue" - [(const_int 1)] - "" - " -{ - ix86_expand_epilogue (); - DONE; -}") - -(define_insn "epilogue_set_stack_ptr" - [(set (reg:SI 7) (reg:SI 6)) - (clobber (reg:SI 6))] - "" - "* -{ - rtx xops [2]; - - xops[0] = frame_pointer_rtx; - xops[1] = stack_pointer_rtx; - output_asm_insn (AS2 (mov%L0,%0,%1), xops); - RET; -}" - [(set_attr "memory" "none")]) - -(define_insn "leave" - [(const_int 2) - (clobber (reg:SI 6)) - (clobber (reg:SI 7))] - "" - "leave" - [(set_attr "memory" "none")]) - -(define_insn "pop" - [(set (match_operand:SI 0 "register_operand" "r") - (mem:SI (reg:SI 7))) - (set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))] - "" - "* -{ - output_asm_insn (AS1 (pop%L0,%P0), operands); - RET; -}" - [(set_attr "memory" "load")]) - -(define_expand "movstrsi" - [(parallel [(set (match_operand:BLK 0 "memory_operand" "") - (match_operand:BLK 1 "memory_operand" "")) - (use (match_operand:SI 2 "const_int_operand" "")) - (use (match_operand:SI 3 "const_int_operand" "")) - (clobber (match_scratch:SI 4 "")) - (clobber (match_dup 5)) - (clobber (match_dup 6))])] - "" - " -{ - rtx addr0, addr1; - - if (GET_CODE (operands[2]) != CONST_INT) - FAIL; - - addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); - addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); - - operands[5] = addr0; - operands[6] = addr1; - - operands[0] = change_address (operands[0], VOIDmode, addr0); - operands[1] = change_address (operands[1], VOIDmode, addr1); -}") - -;; It might seem that operands 0 & 1 could use predicate register_operand. -;; But strength reduction might offset the MEM expression. So we let -;; reload put the address into %edi & %esi. - -(define_insn "" - [(set (mem:BLK (match_operand:SI 0 "address_operand" "D")) - (mem:BLK (match_operand:SI 1 "address_operand" "S"))) - (use (match_operand:SI 2 "const_int_operand" "n")) - (use (match_operand:SI 3 "immediate_operand" "i")) - (clobber (match_scratch:SI 4 "=&c")) - (clobber (match_dup 0)) - (clobber (match_dup 1))] - "" - "* -{ - rtx xops[2]; - - output_asm_insn (\"cld\", operands); - if (GET_CODE (operands[2]) == CONST_INT) - { - if (INTVAL (operands[2]) & ~0x03) - { - xops[0] = GEN_INT ((INTVAL (operands[2]) >> 2) & 0x3fffffff); - xops[1] = operands[4]; - - output_asm_insn (AS2 (mov%L1,%0,%1), xops); -#ifdef INTEL_SYNTAX - output_asm_insn (\"rep movsd\", xops); -#else - output_asm_insn (\"rep\;movsl\", xops); -#endif - } - if (INTVAL (operands[2]) & 0x02) - output_asm_insn (\"movsw\", operands); - if (INTVAL (operands[2]) & 0x01) - output_asm_insn (\"movsb\", operands); - } - else - abort (); - RET; -}") - -(define_expand "clrstrsi" - [(set (match_dup 3) (const_int 0)) - (parallel [(set (match_operand:BLK 0 "memory_operand" "") - (const_int 0)) - (use (match_operand:SI 1 "const_int_operand" "")) - (use (match_operand:SI 2 "const_int_operand" "")) - (use (match_dup 3)) - (clobber (match_scratch:SI 4 "")) - (clobber (match_dup 5))])] - "" - " -{ - rtx addr0; - - if (GET_CODE (operands[1]) != CONST_INT) - FAIL; - - addr0 = copy_to_mode_reg (Pmode, XEXP (operands[0], 0)); - - operands[3] = gen_reg_rtx (SImode); - operands[5] = addr0; - - operands[0] = gen_rtx_MEM (BLKmode, addr0); -}") - -;; It might seem that operand 0 could use predicate register_operand. -;; But strength reduction might offset the MEM expression. So we let -;; reload put the address into %edi. - -(define_insn "*bzero" - [(set (mem:BLK (match_operand:SI 0 "address_operand" "D")) - (const_int 0)) - (use (match_operand:SI 1 "const_int_operand" "n")) - (use (match_operand:SI 2 "immediate_operand" "i")) - (use (match_operand:SI 3 "register_operand" "a")) - (clobber (match_scratch:SI 4 "=&c")) - (clobber (match_dup 0))] - "" - "* -{ - rtx xops[2]; - - output_asm_insn (\"cld\", operands); - if (GET_CODE (operands[1]) == CONST_INT) - { - unsigned int count = INTVAL (operands[1]) & 0xffffffff; - if (count & ~0x03) - { - xops[0] = GEN_INT (count / 4); - xops[1] = operands[4]; - - /* K6: stos takes 1 cycle, rep stos takes 8 + %ecx cycles. - 80386: 4/5+5n (+2 for set of ecx) - 80486: 5/7+5n (+1 for set of ecx) - */ - if (count / 4 < ((int) ix86_cpu < (int)PROCESSOR_PENTIUM ? 4 : 6)) - { - do -#ifdef INTEL_SYNTAX - output_asm_insn (\"stosd\", xops); -#else - output_asm_insn (\"stosl\", xops); -#endif - while ((count -= 4) > 3); - } - else - { - output_asm_insn (AS2 (mov%L1,%0,%1), xops); -#ifdef INTEL_SYNTAX - output_asm_insn (\"rep stosd\", xops); -#else - output_asm_insn (\"rep\;stosl\", xops); -#endif - } - } - if (INTVAL (operands[1]) & 0x02) - output_asm_insn (\"stosw\", operands); - if (INTVAL (operands[1]) & 0x01) - output_asm_insn (\"stosb\", operands); - } - else - abort (); - RET; -}") - -(define_expand "cmpstrsi" - [(parallel [(set (match_operand:SI 0 "general_operand" "") - (compare:SI (match_operand:BLK 1 "general_operand" "") - (match_operand:BLK 2 "general_operand" ""))) - (use (match_operand:SI 3 "general_operand" "")) - (use (match_operand:SI 4 "immediate_operand" "")) - (clobber (match_dup 5)) - (clobber (match_dup 6)) - (clobber (match_dup 3))])] - "" - " -{ - rtx addr1, addr2; - - addr1 = copy_to_mode_reg (Pmode, XEXP (operands[1], 0)); - addr2 = copy_to_mode_reg (Pmode, XEXP (operands[2], 0)); - operands[3] = copy_to_mode_reg (SImode, operands[3]); - - operands[5] = addr1; - operands[6] = addr2; - - operands[1] = gen_rtx_MEM (BLKmode, addr1); - operands[2] = gen_rtx_MEM (BLKmode, addr2); - -}") - -;; memcmp recognizers. The `cmpsb' opcode does nothing if the count is -;; zero. Emit extra code to make sure that a zero-length compare is EQ. - -;; It might seem that operands 0 & 1 could use predicate register_operand. -;; But strength reduction might offset the MEM expression. So we let -;; reload put the address into %edi & %esi. - -;; ??? Most comparisons have a constant length, and it's therefore -;; possible to know that the length is non-zero, and to avoid the extra -;; code to handle zero-length compares. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=&r") - (compare:SI (mem:BLK (match_operand:SI 1 "address_operand" "S")) - (mem:BLK (match_operand:SI 2 "address_operand" "D")))) - (use (match_operand:SI 3 "register_operand" "c")) - (use (match_operand:SI 4 "immediate_operand" "i")) - (clobber (match_dup 1)) - (clobber (match_dup 2)) - (clobber (match_dup 3))] - "" - "* -{ - rtx xops[2], label; - - label = gen_label_rtx (); - - output_asm_insn (\"cld\", operands); - output_asm_insn (AS2 (xor%L0,%0,%0), operands); - output_asm_insn (\"repz\;cmps%B2\", operands); - output_asm_insn (\"je %l0\", &label); - - xops[0] = operands[0]; - xops[1] = const1_rtx; - output_asm_insn (AS2 (sbb%L0,%0,%0), xops); - if (QI_REG_P (xops[0])) - output_asm_insn (AS2 (or%B0,%1,%b0), xops); - else - output_asm_insn (AS2 (or%L0,%1,%0), xops); - - ASM_OUTPUT_INTERNAL_LABEL (asm_out_file, \"L\", CODE_LABEL_NUMBER (label)); - RET; -}") - -(define_insn "" - [(set (cc0) - (compare:SI (mem:BLK (match_operand:SI 0 "address_operand" "S")) - (mem:BLK (match_operand:SI 1 "address_operand" "D")))) - (use (match_operand:SI 2 "register_operand" "c")) - (use (match_operand:SI 3 "immediate_operand" "i")) - (clobber (match_dup 0)) - (clobber (match_dup 1)) - (clobber (match_dup 2))] - "" - "* -{ - rtx xops[2]; - - cc_status.flags |= CC_NOT_SIGNED; - - xops[0] = gen_rtx_REG (QImode, 0); - xops[1] = CONST0_RTX (QImode); - - output_asm_insn (\"cld\", operands); - output_asm_insn (AS2 (test%B0,%1,%0), xops); - return \"repz\;cmps%B2\"; -}") - - -;; Note, you cannot optimize away the branch following the bsfl by assuming -;; that the destination is not modified if the input is 0, since not all -;; x86 implementations do this. - -(define_expand "ffssi2" - [(set (match_operand:SI 0 "general_operand" "") - (ffs:SI (match_operand:SI 1 "general_operand" "")))] - "" - " -{ - rtx label = gen_label_rtx (), temp = gen_reg_rtx (SImode); - - emit_insn (gen_ffssi_1 (temp, operands[1])); - emit_cmp_insn (operands[1], const0_rtx, NE, NULL_RTX, SImode, 0, 0); - emit_jump_insn (gen_bne (label)); - emit_move_insn (temp, constm1_rtx); - emit_label (label); - temp = expand_binop (SImode, add_optab, temp, const1_rtx, - operands[0], 0, OPTAB_WIDEN); - - if (temp != operands[0]) - emit_move_insn (operands[0], temp); - DONE; -}") - -(define_insn "ffssi_1" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(match_operand:SI 1 "nonimmediate_operand" "rm")] 5))] - "" - "* return AS2 (bsf%L0,%1,%0);") - -(define_expand "ffshi2" - [(set (match_operand:SI 0 "general_operand" "") - (ffs:HI (match_operand:HI 1 "general_operand" "")))] - "" - " -{ - rtx label = gen_label_rtx (), temp = gen_reg_rtx (HImode); - - emit_insn (gen_ffshi_1 (temp, operands[1])); - emit_cmp_insn (operands[1], const0_rtx, NE, NULL_RTX, HImode, 0, 0); - emit_jump_insn (gen_bne (label)); - emit_move_insn (temp, constm1_rtx); - emit_label (label); - temp = expand_binop (HImode, add_optab, temp, const1_rtx, - operands[0], 0, OPTAB_WIDEN); - - if (temp != operands[0]) - emit_move_insn (operands[0], temp); - DONE; -}") - -(define_insn "ffshi_1" - [(set (match_operand:HI 0 "register_operand" "=r") - (unspec:HI [(match_operand:SI 1 "nonimmediate_operand" "rm")] 5))] - "" - "* return AS2 (bsf%W0,%1,%0);") - -;; These patterns match the binary 387 instructions for addM3, subM3, -;; mulM3 and divM3. There are three patterns for each of DFmode and -;; SFmode. The first is the normal insn, the second the same insn but -;; with one operand a conversion, and the third the same insn but with -;; the other operand a conversion. - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (match_operator:DF 3 "binary_387_op" - [(match_operand:DF 1 "nonimmediate_operand" "0,fm") - (match_operand:DF 2 "nonimmediate_operand" "fm,0")]))] - "TARGET_80387" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:DF 3 "is_mul" "") - (const_string "fpmul") - (match_operand:DF 3 "is_div" "") - (const_string "fpdiv") - ] - (const_string "fpop") - ) - )]) - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f,f") - (match_operator:XF 3 "binary_387_op" - [(match_operand:XF 1 "register_operand" "0,f") - (match_operand:XF 2 "register_operand" "f,0")]))] - "TARGET_80387" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:DF 3 "is_mul" "") - (const_string "fpmul") - (match_operand:DF 3 "is_div" "") - (const_string "fpdiv") - ] - (const_string "fpop") - ) - )]) - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f,f") - (match_operator:XF 3 "binary_387_op" - [(float_extend:XF (match_operand:SF 1 "nonimmediate_operand" "fm,0")) - (match_operand:XF 2 "register_operand" "0,f")]))] - "TARGET_80387" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:DF 3 "is_mul" "") - (const_string "fpmul") - (match_operand:DF 3 "is_div" "") - (const_string "fpdiv") - ] - (const_string "fpop") - ) - )]) - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f,f") - (match_operator:XF 3 "binary_387_op" - [(match_operand:XF 1 "register_operand" "0,f") - (float_extend:XF - (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))] - "TARGET_80387" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:DF 3 "is_mul" "") - (const_string "fpmul") - (match_operand:DF 3 "is_div" "") - (const_string "fpdiv") - ] - (const_string "fpop") - ) - )]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (match_operator:DF 3 "binary_387_op" - [(float_extend:DF (match_operand:SF 1 "nonimmediate_operand" "fm,0")) - (match_operand:DF 2 "register_operand" "0,f")]))] - "TARGET_80387" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:DF 3 "is_mul" "") - (const_string "fpmul") - (match_operand:DF 3 "is_div" "") - (const_string "fpdiv") - ] - (const_string "fpop") - ) - )]) - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (match_operator:DF 3 "binary_387_op" - [(match_operand:DF 1 "register_operand" "0,f") - (float_extend:DF - (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))] - "TARGET_80387" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:DF 3 "is_mul" "") - (const_string "fpmul") - (match_operand:DF 3 "is_div" "") - (const_string "fpdiv") - ] - (const_string "fpop") - ) - )]) - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f,f") - (match_operator:SF 3 "binary_387_op" - [(match_operand:SF 1 "nonimmediate_operand" "0,fm") - (match_operand:SF 2 "nonimmediate_operand" "fm,0")]))] - "TARGET_80387" - "* return output_387_binary_op (insn, operands);" - [(set (attr "type") - (cond [(match_operand:DF 3 "is_mul" "") - (const_string "fpmul") - (match_operand:DF 3 "is_div" "") - (const_string "fpdiv") - ] - (const_string "fpop") - ) - )]) - -(define_expand "strlensi" - [(parallel [(set (match_dup 4) - (unspec:SI [(mem:BLK (match_operand:BLK 1 "general_operand" "")) - (match_operand:QI 2 "immediate_operand" "") - (match_operand:SI 3 "immediate_operand" "")] 0)) - (clobber (match_dup 1))]) - (set (match_dup 5) - (not:SI (match_dup 4))) - (set (match_operand:SI 0 "register_operand" "") - (plus:SI (match_dup 5) - (const_int -1)))] - "" - " -{ - if (TARGET_UNROLL_STRLEN && operands[2] == const0_rtx && optimize > 1) - { - rtx address; - rtx scratch; - - /* well it seems that some optimizer does not combine a call like - foo(strlen(bar), strlen(bar)); - when the move and the subtraction is done here. It does calculate - the length just once when these instructions are done inside of - output_strlen_unroll(). But I think since &bar[strlen(bar)] is - often used and I use one fewer register for the lifetime of - output_strlen_unroll() this is better. */ - scratch = gen_reg_rtx (SImode); - address = force_reg (SImode, XEXP (operands[1], 0)); - - /* move address to scratch-register - this is done here because the i586 can do the following and - in the same cycle with the following move. */ - if (GET_CODE (operands[3]) != CONST_INT || INTVAL (operands[3]) < 4) - emit_insn (gen_movsi (scratch, address)); - - emit_insn (gen_movsi (operands[0], address)); - - if(TARGET_USE_Q_REG) - emit_insn (gen_strlensi_unroll5 (operands[0], - operands[3], - scratch, - operands[0])); - else - emit_insn (gen_strlensi_unroll4 (operands[0], - operands[3], - scratch, - operands[0])); - - /* gen_strlensi_unroll[45] returns the address of the zero - at the end of the string, like memchr(), so compute the - length by subtracting the startaddress. */ - emit_insn (gen_subsi3 (operands[0], operands[0], address)); - DONE; - } - - operands[1] = copy_to_mode_reg (SImode, XEXP (operands[1], 0)); - operands[4] = gen_reg_rtx (SImode); - operands[5] = gen_reg_rtx (SImode); -}") - -;; It might seem that operands 0 & 1 could use predicate register_operand. -;; But strength reduction might offset the MEM expression. So we let -;; reload put the address into %edi. - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=&c") - (unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "D")) - (match_operand:QI 2 "immediate_operand" "a") - (match_operand:SI 3 "immediate_operand" "i")] 0)) - (clobber (match_dup 1))] - "" - "* -{ - rtx xops[2]; - - xops[0] = operands[0]; - xops[1] = constm1_rtx; - output_asm_insn (\"cld\", operands); - output_asm_insn (AS2 (mov%L0,%1,%0), xops); - return \"repnz\;scas%B2\"; -}") - -/* Conditional move define_insns. */ - -(define_expand "movsicc" - [(set (match_operand:SI 0 "register_operand" "") - (if_then_else:SI (match_operand 1 "comparison_operator" "") - (match_operand:SI 2 "nonimmediate_operand" "") - (match_operand:SI 3 "nonimmediate_operand" "")))] - "TARGET_CMOVE" - " -{ - if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) - FAIL; - - operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), - GET_MODE (i386_compare_op0), - i386_compare_op0, i386_compare_op1); -}") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (if_then_else:SI (match_operator 1 "comparison_operator" - [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") - (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) - (match_operand:SI 4 "nonimmediate_operand" "rm,rm,0,0") - (match_operand:SI 5 "nonimmediate_operand" "0,0,rm,rm")))] - "TARGET_CMOVE" - "#") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r,r,r") - (if_then_else:SI (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "r,m,r,m") - (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) - (match_operand:SI 4 "nonimmediate_operand" "rm,rm,0,0") - (match_operand:SI 5 "nonimmediate_operand" "0,0,rm,rm")))] - "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT" - "#") - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (if_then_else:SI (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "") - (const_int 0)]) - (match_operand:SI 3 "nonimmediate_operand" "") - (match_operand:SI 4 "nonimmediate_operand" "")))] - "TARGET_CMOVE && reload_completed" - [(set (cc0) - (match_dup 2)) - (set (match_dup 0) - (if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)]) - (match_dup 3) (match_dup 4)))] - "") - -(define_split - [(set (match_operand:SI 0 "register_operand" "") - (if_then_else:SI (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "") - (match_operand 3 "general_operand" "")]) - (match_operand:SI 4 "nonimmediate_operand" "") - (match_operand:SI 5 "nonimmediate_operand" "")))] - "TARGET_CMOVE && reload_completed" - [(set (cc0) (compare (match_dup 2) (match_dup 3))) - (set (match_dup 0) - (if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)]) - (match_dup 4) (match_dup 5)))] - "") - -(define_insn "" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (if_then_else:SI (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (match_operand:SI 2 "nonimmediate_operand" "rm,0") - (match_operand:SI 3 "nonimmediate_operand" "0,rm")))] - "TARGET_CMOVE && reload_completed" - "* return output_int_conditional_move (which_alternative, operands);") - -(define_expand "movhicc" - [(set (match_operand:HI 0 "register_operand" "") - (if_then_else:HI (match_operand 1 "comparison_operator" "") - (match_operand:HI 2 "nonimmediate_operand" "") - (match_operand:HI 3 "nonimmediate_operand" "")))] - "TARGET_CMOVE" - " -{ - if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) - FAIL; - - operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), - GET_MODE (i386_compare_op0), - i386_compare_op0, i386_compare_op1); -}") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") - (if_then_else:HI (match_operator 1 "comparison_operator" - [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") - (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) - (match_operand:HI 4 "nonimmediate_operand" "rm,rm,0,0") - (match_operand:HI 5 "nonimmediate_operand" "0,0,rm,rm")))] - "TARGET_CMOVE" - "#") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r,r,r,r") - (if_then_else:HI (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "r,m,r,m") - (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) - (match_operand:HI 4 "nonimmediate_operand" "rm,rm,0,0") - (match_operand:HI 5 "nonimmediate_operand" "0,0,rm,rm")))] - "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT" - "#") - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (if_then_else:HI (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "") - (const_int 0)]) - (match_operand:HI 3 "nonimmediate_operand" "") - (match_operand:HI 4 "nonimmediate_operand" "")))] - "TARGET_CMOVE && reload_completed" - [(set (cc0) - (match_dup 2)) - (set (match_dup 0) - (if_then_else:HI (match_op_dup 1 [(cc0) (const_int 0)]) - (match_dup 3) (match_dup 4)))] - "") - -(define_split - [(set (match_operand:HI 0 "register_operand" "") - (if_then_else:HI (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "") - (match_operand 3 "general_operand" "")]) - (match_operand:HI 4 "nonimmediate_operand" "") - (match_operand:HI 5 "nonimmediate_operand" "")))] - "TARGET_CMOVE && reload_completed" - [(set (cc0) - (compare (match_dup 2) (match_dup 3))) - (set (match_dup 0) - (if_then_else:HI (match_op_dup 1 [(cc0) (const_int 0)]) - (match_dup 4) (match_dup 5)))] - "") - -(define_insn "" - [(set (match_operand:HI 0 "register_operand" "=r,r") - (if_then_else:HI (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (match_operand:HI 2 "nonimmediate_operand" "rm,0") - (match_operand:HI 3 "nonimmediate_operand" "0,rm")))] - "TARGET_CMOVE && reload_completed" - "* return output_int_conditional_move (which_alternative, operands);") - -(define_expand "movsfcc" - [(set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (match_operand 1 "comparison_operator" "") - (match_operand:SF 2 "register_operand" "") - (match_operand:SF 3 "register_operand" "")))] - "TARGET_CMOVE" - " -{ - rtx temp; - - if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) - FAIL; - - /* The floating point conditional move instructions don't directly - support conditions resulting from a signed integer comparison. */ - - switch (GET_CODE (operands[1])) - { - case LT: - case LE: - case GE: - case GT: - temp = emit_store_flag (gen_reg_rtx (QImode), - GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1, - VOIDmode, 0, 0); - - if (!temp) - FAIL; - - operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx); - break; - - default: - operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), - GET_MODE (i386_compare_op0), - i386_compare_op0, i386_compare_op1); - break; - } -}") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f,f,f,f") - (if_then_else:SF (match_operator 1 "comparison_operator" - [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") - (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) - (match_operand:SF 4 "register_operand" "f,f,0,0") - (match_operand:SF 5 "register_operand" "0,0,f,f")))] - "TARGET_CMOVE - && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE - && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" - "#") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f,f,f,f") - (if_then_else:SF (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "r,m,r,m") - (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) - (match_operand:SF 4 "register_operand" "f,f,0,0") - (match_operand:SF 5 "register_operand" "0,0,f,f")))] - "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT - && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE - && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" - "#") - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "") - (const_int 0)]) - (match_operand:SF 3 "register_operand" "") - (match_operand:SF 4 "register_operand" "")))] - "TARGET_CMOVE && reload_completed" - [(set (cc0) - (match_dup 2)) - (set (match_dup 0) - (if_then_else:SF (match_op_dup 1 [(cc0) (const_int 0)]) - (match_dup 3) (match_dup 4)))] - "") - -(define_split - [(set (match_operand:SF 0 "register_operand" "") - (if_then_else:SF (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "") - (match_operand 3 "general_operand" "")]) - (match_operand:SF 4 "register_operand" "") - (match_operand:SF 5 "register_operand" "")))] - "TARGET_CMOVE && reload_completed" - [(set (cc0) (compare (match_dup 2) (match_dup 3))) - (set (match_dup 0) - (if_then_else:SF (match_op_dup 1 [(cc0) (const_int 0)]) - (match_dup 4) (match_dup 5)))] - "") - -(define_insn "" - [(set (match_operand:SF 0 "register_operand" "=f,f") - (if_then_else:SF (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (match_operand:SF 2 "register_operand" "f,0") - (match_operand:SF 3 "register_operand" "0,f")))] - "TARGET_CMOVE && reload_completed" - "* return output_fp_conditional_move (which_alternative, operands);") - -(define_expand "movdfcc" - [(set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (match_operand 1 "comparison_operator" "") - (match_operand:DF 2 "register_operand" "") - (match_operand:DF 3 "register_operand" "")))] - "TARGET_CMOVE" - " -{ - rtx temp; - - if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) - FAIL; - - /* The floating point conditional move instructions don't directly - support conditions resulting from a signed integer comparison. */ - - switch (GET_CODE (operands[1])) - { - case LT: - case LE: - case GE: - case GT: - temp = emit_store_flag (gen_reg_rtx (QImode), - GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1, - VOIDmode, 0, 0); - - if (!temp) - FAIL; - - operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx); - break; - - default: - operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), - GET_MODE (i386_compare_op0), - i386_compare_op0, i386_compare_op1); - break; - } -}") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f,f,f") - (if_then_else:DF (match_operator 1 "comparison_operator" - [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") - (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) - (match_operand:DF 4 "register_operand" "f,f,0,0") - (match_operand:DF 5 "register_operand" "0,0,f,f")))] - "TARGET_CMOVE - && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE - && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" - "#") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f,f,f") - (if_then_else:DF (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "r,m,r,m") - (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) - (match_operand:DF 4 "register_operand" "f,f,0,0") - (match_operand:DF 5 "register_operand" "0,0,f,f")))] - "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT - && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE - && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" - "#") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "") - (const_int 0)]) - (match_operand:DF 3 "register_operand" "") - (match_operand:DF 4 "register_operand" "")))] - "TARGET_CMOVE && reload_completed" - [(set (cc0) - (match_dup 2)) - (set (match_dup 0) - (if_then_else:DF (match_op_dup 1 [(cc0) (const_int 0)]) - (match_dup 3) (match_dup 4)))] - "") - -(define_split - [(set (match_operand:DF 0 "register_operand" "") - (if_then_else:DF (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "") - (match_operand 3 "general_operand" "")]) - (match_operand:DF 4 "register_operand" "") - (match_operand:DF 5 "register_operand" "")))] - "TARGET_CMOVE && reload_completed" - [(set (cc0) (compare (match_dup 2) (match_dup 3))) - (set (match_dup 0) - (if_then_else:DF (match_op_dup 1 [(cc0) (const_int 0)]) - (match_dup 4) (match_dup 5)))] - "") - -(define_insn "" - [(set (match_operand:DF 0 "register_operand" "=f,f") - (if_then_else:DF (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (match_operand:DF 2 "register_operand" "f,0") - (match_operand:DF 3 "register_operand" "0,f")))] - "TARGET_CMOVE && reload_completed" - "* return output_fp_conditional_move (which_alternative, operands);") - -(define_expand "movxfcc" - [(set (match_operand:XF 0 "register_operand" "") - (if_then_else:XF (match_operand 1 "comparison_operator" "") - (match_operand:XF 2 "register_operand" "") - (match_operand:XF 3 "register_operand" "")))] - "TARGET_CMOVE" - " -{ - rtx temp; - - if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) - FAIL; - - /* The floating point conditional move instructions don't directly - support conditions resulting from a signed integer comparison. */ - - switch (GET_CODE (operands[1])) - { - case LT: - case LE: - case GE: - case GT: - temp = emit_store_flag (gen_reg_rtx (QImode), - GET_CODE (operands[1]), i386_compare_op0, i386_compare_op1, - VOIDmode, 0, 0); - - if (!temp) - FAIL; - - operands[1] = gen_rtx_fmt_ee (NE, QImode, temp, const0_rtx); - break; - - default: - operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), - GET_MODE (i386_compare_op0), - i386_compare_op0, i386_compare_op1); - break; - } -}") - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f,f,f,f") - (if_then_else:XF (match_operator 1 "comparison_operator" - [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") - (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) - (match_operand:XF 4 "register_operand" "f,f,0,0") - (match_operand:XF 5 "register_operand" "0,0,f,f")))] - "TARGET_CMOVE - && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE - && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" - "#") - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f,f,f,f") - (if_then_else:XF (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "r,m,r,m") - (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) - (match_operand:XF 4 "register_operand" "f,f,0,0") - (match_operand:XF 5 "register_operand" "0,0,f,f")))] - "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT - && GET_CODE (operands[1]) != LT && GET_CODE (operands[1]) != LE - && GET_CODE (operands[1]) != GE && GET_CODE (operands[1]) != GT" - "#") - -(define_split - [(set (match_operand:XF 0 "register_operand" "") - (if_then_else:XF (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "") - (const_int 0)]) - (match_operand:XF 3 "register_operand" "") - (match_operand:XF 4 "register_operand" "")))] - "TARGET_CMOVE && reload_completed" - [(set (cc0) - (match_dup 2)) - (set (match_dup 0) - (if_then_else:XF (match_op_dup 1 [(cc0) (const_int 0)]) - (match_dup 3) (match_dup 4)))] - "") - -(define_split - [(set (match_operand:XF 0 "register_operand" "") - (if_then_else:XF (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "") - (match_operand 3 "general_operand" "")]) - (match_operand:XF 4 "register_operand" "") - (match_operand:XF 5 "register_operand" "")))] - "TARGET_CMOVE && reload_completed" - [(set (cc0) (compare (match_dup 2) (match_dup 3))) - (set (match_dup 0) - (if_then_else:XF (match_op_dup 1 [(cc0) (const_int 0)]) - (match_dup 4) (match_dup 5)))] - "") - -(define_insn "" - [(set (match_operand:XF 0 "register_operand" "=f,f") - (if_then_else:XF (match_operator 1 "comparison_operator" - [(cc0) (const_int 0)]) - (match_operand:XF 2 "register_operand" "f,0") - (match_operand:XF 3 "register_operand" "0,f")))] - "TARGET_CMOVE && reload_completed" - "* return output_fp_conditional_move (which_alternative, operands);") - -(define_expand "movdicc" - [(set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI (match_operand 1 "comparison_operator" "") - (match_operand:DI 2 "nonimmediate_operand" "") - (match_operand:DI 3 "nonimmediate_operand" "")))] - "TARGET_CMOVE" - " -{ - if (GET_MODE_CLASS (GET_MODE (i386_compare_op0)) != MODE_INT) - FAIL; - - operands[1] = gen_rtx_fmt_ee (GET_CODE (operands[1]), - GET_MODE (i386_compare_op0), - i386_compare_op0, i386_compare_op1); -}") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=&r,&r,&r,&r") - (if_then_else:DI (match_operator 1 "comparison_operator" - [(match_operand:QI 2 "nonimmediate_operand" "q,m,q,m") - (match_operand:QI 3 "general_operand" "qmn,qn,qmn,qn")]) - (match_operand:DI 4 "nonimmediate_operand" "ro,ro,0,0") - (match_operand:DI 5 "nonimmediate_operand" "0,0,ro,ro")))] - "TARGET_CMOVE" - "#") - -(define_insn "" - [(set (match_operand:DI 0 "register_operand" "=&r,&r,&r,&r") - (if_then_else:DI (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "r,m,r,m") - (match_operand 3 "general_operand" "rmi,ri,rmi,ri")]) - (match_operand:DI 4 "nonimmediate_operand" "ro,ro,0,0") - (match_operand:DI 5 "nonimmediate_operand" "0,0,ro,ro")))] - "TARGET_CMOVE && GET_MODE_CLASS (GET_MODE (operands[2])) == MODE_INT" - "#") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "") - (const_int 0)]) - (match_operand:DI 3 "nonimmediate_operand" "") - (match_operand:DI 4 "nonimmediate_operand" "")))] - "TARGET_CMOVE && reload_completed" - [(set (cc0) - (match_dup 2)) - (set (match_dup 5) - (if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)]) - (match_dup 7) (match_dup 9))) - (set (match_dup 6) - (if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)]) - (match_dup 8) (match_dup 10)))] - "split_di (&operands[0], 1, &operands[5], &operands[6]); - split_di (&operands[3], 1, &operands[7], &operands[8]); - split_di (&operands[4], 1, &operands[9], &operands[10]);") - -(define_split - [(set (match_operand:DI 0 "register_operand" "") - (if_then_else:DI (match_operator 1 "comparison_operator" - [(match_operand 2 "nonimmediate_operand" "") - (match_operand 3 "general_operand" "")]) - (match_operand:DI 4 "nonimmediate_operand" "") - (match_operand:DI 5 "nonimmediate_operand" "")))] - "TARGET_CMOVE && reload_completed" - [(set (cc0) (compare (match_dup 2) (match_dup 3))) - (set (match_dup 6) - (if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)]) - (match_dup 8) (match_dup 10))) - (set (match_dup 7) - (if_then_else:SI (match_op_dup 1 [(cc0) (const_int 0)]) - (match_dup 9) (match_dup 11)))] - "split_di (&operands[0], 1, &operands[6], &operands[7]); - split_di (&operands[4], 1, &operands[8], &operands[9]); - split_di (&operands[5], 1, &operands[10], &operands[11]);") - -(define_insn "strlensi_unroll" - [(set (match_operand:SI 0 "register_operand" "=&r,&r") - (unspec:SI [(mem:BLK (match_operand:SI 1 "address_operand" "r,r")) - (match_operand:SI 2 "immediate_operand" "i,i")] 0)) - (clobber (match_scratch:SI 3 "=&q,&r"))] - "optimize > 1" - "* return output_strlen_unroll (operands);") - -;; the only difference between the following patterns is the register preference -;; on a pentium using a q-register saves one clock cycle per 4 characters - -(define_insn "strlensi_unroll4" - [(set (match_operand:SI 0 "register_operand" "=r,r") - (unspec:SI [(mem:BLK (match_operand:SI 3 "register_operand" "0,0")) - (match_operand:SI 1 "immediate_operand" "i,i") - (match_operand:SI 2 "register_operand" "+q,!r")] 0)) - (clobber (match_dup 2))] - "(TARGET_USE_ANY_REG && optimize > 1)" - "* return output_strlen_unroll (operands);") - -(define_insn "strlensi_unroll5" - [(set (match_operand:SI 0 "register_operand" "=r") - (unspec:SI [(mem:BLK (match_operand:SI 3 "register_operand" "0")) - (match_operand:SI 1 "immediate_operand" "i") - (match_operand:SI 2 "register_operand" "+q")] 0)) - (clobber (match_dup 2))] - "(TARGET_USE_Q_REG && optimize > 1)" - "* return output_strlen_unroll (operands);" -) - -(define_insn "allocate_stack_worker" - [(unspec:SI [(match_operand:SI 0 "register_operand" "a")] 3) - (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 0))) - (clobber (match_dup 0))] - "TARGET_STACK_PROBE" - "* return AS1(call,__alloca);" - [(set_attr "memory" "none")]) - -(define_expand "allocate_stack" - [(set (match_operand:SI 0 "register_operand" "=r") - (minus:SI (reg:SI 7) (match_operand:SI 1 "general_operand" ""))) - (set (reg:SI 7) (minus:SI (reg:SI 7) (match_dup 1)))] - "TARGET_STACK_PROBE" - " -{ -#ifdef CHECK_STACK_LIMIT - if (GET_CODE (operands[1]) == CONST_INT - && INTVAL (operands[1]) < CHECK_STACK_LIMIT) - emit_insn (gen_subsi3 (stack_pointer_rtx, stack_pointer_rtx, - operands[1])); - else -#endif - emit_insn (gen_allocate_stack_worker (copy_to_mode_reg (SImode, - operands[1]))); - - emit_move_insn (operands[0], virtual_stack_dynamic_rtx); - DONE; -}") - -(define_expand "exception_receiver" - [(const_int 0)] - "flag_pic" - " -{ - load_pic_register (1); - DONE; -}") |