summaryrefslogtreecommitdiffstats
path: root/contrib/gcc/config
diff options
context:
space:
mode:
authorobrien <obrien@FreeBSD.org>1999-08-30 10:27:11 +0000
committerobrien <obrien@FreeBSD.org>1999-08-30 10:27:11 +0000
commitba9b2147f2de90df0db9e851b738a856dd742995 (patch)
tree2fbaa18158f179b2df94297c91651ed26c38b684 /contrib/gcc/config
parentb337d66e78675eac351358bf6f2d3a4d91a42d26 (diff)
downloadFreeBSD-src-ba9b2147f2de90df0db9e851b738a856dd742995.zip
FreeBSD-src-ba9b2147f2de90df0db9e851b738a856dd742995.tar.gz
Use the stock EGCS 1.1.2 file here. I cannot determine if our previous
changes for ObjC are still appropriate.
Diffstat (limited to 'contrib/gcc/config')
-rw-r--r--contrib/gcc/config/i386/i386.md4056
1 files changed, 3046 insertions, 1010 deletions
diff --git a/contrib/gcc/config/i386/i386.md b/contrib/gcc/config/i386/i386.md
index 090baa1..f85992f 100644
--- a/contrib/gcc/config/i386/i386.md
+++ b/contrib/gcc/config/i386/i386.md
@@ -1,5 +1,5 @@
-;; GCC machine description for Intel X86.
-;; Copyright (C) 1988, 1994, 1995 Free Software Foundation, Inc.
+; 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.
@@ -17,8 +17,7 @@
;; 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.
-
+;; Boston, MA 02111-1307, USA. */
;; The original PO technology requires these to be ordered by speed,
;; so that assigner will pick the fastest.
@@ -37,8 +36,8 @@
;; '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.
-;; 'S' Print the opcode suffix for a 32-bit float 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.
@@ -59,6 +58,72 @@
;; 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.
+
+;; This shadows the processor_type enumeration, so changes must be made
+;; to i386.h at the same time.
+
+(define_attr "type" "integer,idiv,imul,fld,fpop,fpdiv,fpmul"
+ (const_string "integer"))
+
+;; 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") (eq_attr "cpu" "i386,i486"))
+ 5 5)
+
+(define_function_unit "fp" 1 0
+ (and (eq_attr "type" "fpop") (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
+ (eq_attr "type" "fld")
+ 1 0)
+
+(define_function_unit "integer" 1 0
+ (and (eq_attr "type" "integer") (eq_attr "cpu" "!i386"))
+ 2 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
@@ -72,6 +137,12 @@
;; 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"
+ (const (symbol_ref "ix86_cpu")))
+
(define_insn "tstsi_1"
[(set (cc0)
(match_operand:SI 0 "nonimmediate_operand" "rm"))]
@@ -93,6 +164,7 @@
{
i386_compare_gen = gen_tstsi_1;
i386_compare_op0 = operands[0];
+ i386_compare_op1 = const0_rtx;
DONE;
}")
@@ -117,6 +189,7 @@
{
i386_compare_gen = gen_tsthi_1;
i386_compare_op0 = operands[0];
+ i386_compare_op1 = const0_rtx;
DONE;
}")
@@ -141,6 +214,7 @@
{
i386_compare_gen = gen_tstqi_1;
i386_compare_op0 = operands[0];
+ i386_compare_op1 = const0_rtx;
DONE;
}")
@@ -174,6 +248,7 @@
{
i386_compare_gen = gen_tstsf_cc;
i386_compare_op0 = operands[0];
+ i386_compare_op1 = const0_rtx;
DONE;
}")
@@ -207,6 +282,7 @@
{
i386_compare_gen = gen_tstdf_cc;
i386_compare_op0 = operands[0];
+ i386_compare_op1 = const0_rtx;
DONE;
}")
@@ -228,7 +304,7 @@
return output_fp_cc0_set (insn);
}")
-;; Don't generate tstdf if generating IEEE code, since the `ftst' opcode
+;; Don't generate tstxf if generating IEEE code, since the `ftst' opcode
;; isn't IEEE compliant.
(define_expand "tstxf"
@@ -240,6 +316,7 @@
{
i386_compare_gen = gen_tstxf_cc;
i386_compare_op0 = operands[0];
+ i386_compare_op1 = const0_rtx;
DONE;
}")
@@ -251,15 +328,7 @@
(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"
- "*
-{
- if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
- {
- cc_status.flags |= CC_REVERSED;
- return AS2 (cmp%L0,%0,%1);
- }
- return AS2 (cmp%L0,%1,%0);
-}")
+ "* return AS2 (cmp%L0,%1,%0);")
(define_expand "cmpsi"
[(set (cc0)
@@ -282,15 +351,7 @@
(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"
- "*
-{
- if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
- {
- cc_status.flags |= CC_REVERSED;
- return AS2 (cmp%W0,%0,%1);
- }
- return AS2 (cmp%W0,%1,%0);
-}")
+ "* return AS2 (cmp%W0,%1,%0);")
(define_expand "cmphi"
[(set (cc0)
@@ -313,15 +374,7 @@
(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"
- "*
-{
- if (CONSTANT_P (operands[0]) || GET_CODE (operands[1]) == MEM)
- {
- cc_status.flags |= CC_REVERSED;
- return AS2 (cmp%B0,%0,%1);
- }
- return AS2 (cmp%B0,%1,%0);
-}")
+ "* return AS2 (cmp%B0,%1,%0);")
(define_expand "cmpqi"
[(set (cc0)
@@ -346,11 +399,10 @@
(define_insn ""
[(set (cc0)
(match_operator 2 "VOIDmode_compare_op"
- [(match_operand:XF 0 "nonimmediate_operand" "f")
- (match_operand:XF 1 "nonimmediate_operand" "f")]))
+ [(match_operand:XF 0 "register_operand" "f")
+ (match_operand:XF 1 "register_operand" "f")]))
(clobber (match_scratch:HI 3 "=a"))]
- "TARGET_80387
- && (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)"
+ "TARGET_80387"
"* return output_float_compare (insn, operands);")
(define_insn ""
@@ -386,6 +438,16 @@
(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);")
+
+(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"))]))
@@ -395,6 +457,16 @@
(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);")
+
+(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"))]
@@ -453,6 +525,16 @@
(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);")
+
+(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"))]
@@ -520,7 +602,7 @@
(define_expand "cmpxf"
[(set (cc0)
(compare (match_operand:XF 0 "register_operand" "")
- (match_operand:XF 1 "nonimmediate_operand" "")))]
+ (match_operand:XF 1 "register_operand" "")))]
"TARGET_80387"
"
{
@@ -534,28 +616,30 @@
(define_expand "cmpdf"
[(set (cc0)
(compare (match_operand:DF 0 "register_operand" "")
- (match_operand:DF 1 "nonimmediate_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 = operands[1];
+ 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 "nonimmediate_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 = operands[1];
+ i386_compare_op1 = (immediate_operand (operands[1], SFmode))
+ ? copy_to_mode_reg (SFmode, operands[1]) : operands[1];
DONE;
}")
@@ -573,11 +657,7 @@
(match_operand:XF 1 "register_operand" "")))
(clobber (match_scratch:HI 2 ""))])]
"TARGET_80387"
- "
-{
- if (! register_operand (operands[1], XFmode))
- operands[1] = copy_to_mode_reg (XFmode, operands[1]);
-}")
+ "")
(define_expand "cmpdf_cc"
[(parallel [(set (cc0)
@@ -624,7 +704,7 @@
(define_insn ""
[(set (cc0)
(and:SI (match_operand:SI 0 "general_operand" "%ro")
- (match_operand:SI 1 "general_operand" "ri")))]
+ (match_operand:SI 1 "nonmemory_operand" "ri")))]
""
"*
{
@@ -682,7 +762,7 @@
(define_insn ""
[(set (cc0)
(and:HI (match_operand:HI 0 "general_operand" "%ro")
- (match_operand:HI 1 "general_operand" "ri")))]
+ (match_operand:HI 1 "nonmemory_operand" "ri")))]
""
"*
{
@@ -715,6 +795,12 @@
}
}
+ /* 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);
@@ -723,8 +809,8 @@
(define_insn ""
[(set (cc0)
- (and:QI (match_operand:QI 0 "general_operand" "%qm")
- (match_operand:QI 1 "general_operand" "qi")))]
+ (and:QI (match_operand:QI 0 "nonimmediate_operand" "%qm")
+ (match_operand:QI 1 "nonmemory_operand" "qi")))]
""
"*
{
@@ -741,24 +827,23 @@
(define_insn ""
[(set (match_operand:SI 0 "push_operand" "=<")
- (match_operand:SI 1 "general_operand" "g"))]
- "TARGET_386"
- "push%L0 %1")
-
-;; On a 486, it is faster to move MEM to a REG and then push, rather than
-;; push MEM directly.
+ (match_operand:SI 1 "nonmemory_operand" "rn"))]
+ "flag_pic"
+ "* return AS1 (push%L0,%1);")
(define_insn ""
[(set (match_operand:SI 0 "push_operand" "=<")
(match_operand:SI 1 "nonmemory_operand" "ri"))]
- "!TARGET_386 && TARGET_MOVE"
- "push%L0 %1")
+ "!flag_pic"
+ "* return AS1 (push%L0,%1);")
+
+;; On a 386, it is faster to push MEM directly.
(define_insn ""
[(set (match_operand:SI 0 "push_operand" "=<")
- (match_operand:SI 1 "general_operand" "ri"))]
- "!TARGET_386 && !TARGET_MOVE"
- "push%L0 %1")
+ (match_operand:SI 1 "memory_operand" "m"))]
+ "TARGET_PUSH_MEMORY"
+ "* return AS1 (push%L0,%1);")
;; General case of fullword move.
@@ -790,8 +875,10 @@
(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)"
+ (match_operand:SI 1 "general_operand" "rn,im"))]
+ "((!TARGET_MOVE || GET_CODE (operands[0]) != MEM)
+ || (GET_CODE (operands[1]) != MEM))
+ && flag_pic"
"*
{
rtx link;
@@ -810,29 +897,50 @@
/* Fastest way to change a 0 to a 1. */
return AS1 (inc%L0,%0);
- if (flag_pic && SYMBOLIC_CONST (operands[1]))
+ if (SYMBOLIC_CONST (operands[1]))
return AS2 (lea%L0,%a1,%0);
return AS2 (mov%L0,%1,%0);
}")
(define_insn ""
- [(set (match_operand:HI 0 "push_operand" "=<")
- (match_operand:HI 1 "general_operand" "g"))]
- "TARGET_386"
- "push%W0 %1")
+ [(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;
+ if (operands[1] == const0_rtx && REG_P (operands[0]))
+ return AS2 (xor%L0,%0,%0);
+
+ if (operands[1] == const1_rtx
+ && (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);
+}")
(define_insn ""
[(set (match_operand:HI 0 "push_operand" "=<")
(match_operand:HI 1 "nonmemory_operand" "ri"))]
- "!TARGET_386 && TARGET_MOVE"
- "push%W0 %1")
+ ""
+ "* return AS1 (push%W0,%1);")
(define_insn ""
[(set (match_operand:HI 0 "push_operand" "=<")
- (match_operand:HI 1 "general_operand" "ri"))]
- "!TARGET_386 && !TARGET_MOVE"
- "push%W0 %1")
+ (match_operand:HI 1 "memory_operand" "m"))]
+ "TARGET_PUSH_MEMORY"
+ "* return AS1 (push%W0,%1);")
;; On i486, an incl and movl are both faster than incw and movw.
@@ -876,10 +984,21 @@
if (REG_P (operands[0]))
{
- if (REG_P (operands[1]))
- return AS2 (mov%L0,%k1,%k0);
- else if (CONSTANT_P (operands[1]))
- return AS2 (mov%L0,%1,%k0);
+ if (i386_aligned_p (operands[1]))
+ {
+ operands[1] = i386_sext16_if_const (operands[1]);
+ return AS2 (mov%L0,%k1,%k0);
+ }
+ if (TARGET_PENTIUMPRO)
+ {
+ /* 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);
@@ -932,27 +1051,17 @@
;; the amount pushed up to a halfword.
(define_insn ""
[(set (match_operand:QI 0 "push_operand" "=<")
- (match_operand:QI 1 "immediate_operand" "n"))]
+ (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 "nonimmediate_operand" "q"))]
- "!TARGET_MOVE"
- "*
-{
- operands[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
- return AS1 (push%W0,%1);
-}")
+ "* return AS1(push%W0,%1);")
(define_insn ""
[(set (match_operand:QI 0 "push_operand" "=<")
(match_operand:QI 1 "register_operand" "q"))]
- "TARGET_MOVE"
+ ""
"*
{
- operands[1] = gen_rtx (REG, HImode, REGNO (operands[1]));
+ operands[1] = gen_rtx_REG (HImode, REGNO (operands[1]));
return AS1 (push%W0,%1);
}")
@@ -978,14 +1087,14 @@
}")
(define_insn ""
- [(set (match_operand:QI 0 "general_operand" "=q,*r,qm")
- (match_operand:QI 1 "general_operand" "*g,q,qn"))]
+ [(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;
if (operands[1] == const0_rtx && REG_P (operands[0]))
- return AS2 (xor%B0,%0,%0);
+ return AS2 (xor%L0,%k0,%k0);
if (operands[1] == const1_rtx
&& (link = find_reg_note (insn, REG_WAS_0, 0))
@@ -996,8 +1105,14 @@
&& 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);
+ {
+ /* 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]))
@@ -1032,7 +1147,7 @@
}")
(define_insn ""
- [(set (strict_low_part (match_operand:QI 0 "general_operand" "+qm,q"))
+ [(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)"
"*
@@ -1042,6 +1157,7 @@
return AS2 (xor%B0,%0,%0);
if (operands[1] == const1_rtx
+ && ! 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))
@@ -1063,43 +1179,10 @@
return AS2 (mov%B0,%1,%0);
}")
-(define_expand "movsf"
- [(set (match_operand:SF 0 "general_operand" "")
- (match_operand:SF 1 "general_operand" ""))]
- ""
- "
-{
- /* Special case memory->memory moves and pushes */
- if (TARGET_MOVE
- && (reload_in_progress | reload_completed) == 0
- && GET_CODE (operands[0]) == MEM
- && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], SFmode)))
- {
- rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], SFmode))
- ? gen_movsf_push
- : gen_movsf_mem;
-
- emit_insn ((*genfunc) (operands[0], operands[1]));
- DONE;
- }
-
- /* 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. */
- if (flag_pic
- && GET_CODE (operands[0]) != MEM
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && !standard_80387_constant_p (operands[1]))
- {
- current_function_uses_pic_offset_table = 1;
- }
-}")
-
-(define_insn "movsf_push_nomove"
+(define_insn "movsf_push"
[(set (match_operand:SF 0 "push_operand" "=<,<")
- (match_operand:SF 1 "general_operand" "gF,f"))]
- "!TARGET_MOVE"
+ (match_operand:SF 1 "general_operand" "*rfF,m"))]
+ "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed"
"*
{
if (STACK_REG_P (operands[1]))
@@ -1119,64 +1202,62 @@
output_asm_insn (AS1 (fstp%S0,%0), xops);
else
output_asm_insn (AS1 (fst%S0,%0), xops);
+
RET;
}
- return AS1 (push%L1,%1);
+
+ return AS1 (push%L0,%1);
}")
-(define_insn "movsf_push"
- [(set (match_operand:SF 0 "push_operand" "=<,<,<,<")
- (match_operand:SF 1 "general_operand" "rF,f,m,m"))
- (clobber (match_scratch:SI 2 "=X,X,r,X"))]
+(define_insn "movsf_push_memory"
+ [(set (match_operand:SF 0 "push_operand" "=<")
+ (match_operand:SF 1 "memory_operand" "m"))]
+ "TARGET_PUSH_MEMORY"
+ "* return AS1 (push%L0,%1);")
+
+(define_expand "movsf"
+ [(set (match_operand:SF 0 "general_operand" "")
+ (match_operand:SF 1 "general_operand" ""))]
""
- "*
+ "
{
- if (STACK_REG_P (operands[1]))
+ /* 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 xops[3];
+ operands[1] = force_reg (SFmode, operands[1]);
+ }
- if (! STACK_TOP_P (operands[1]))
- abort ();
+ /* 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]))
+ {
+ rtx insn, note, fp_const;
- xops[0] = AT_SP (SFmode);
- xops[1] = GEN_INT (4);
- xops[2] = stack_pointer_rtx;
+ fp_const = force_const_mem (SFmode, operands[1]);
+ if (flag_pic)
+ current_function_uses_pic_offset_table = 1;
- output_asm_insn (AS2 (sub%L2,%1,%2), xops);
+ insn = emit_insn (gen_rtx_SET (SFmode, operands[0], fp_const));
+ note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
- if (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG))
- output_asm_insn (AS1 (fstp%S0,%0), xops);
+ if (note)
+ XEXP (note, 0) = operands[1];
else
- output_asm_insn (AS1 (fst%S0,%0), xops);
- RET;
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn));
}
-
- else if (GET_CODE (operands[1]) != MEM || GET_CODE (operands[2]) != REG)
- return AS1 (push%L1,%1);
-
- else
- {
- output_asm_insn (AS2 (mov%L2,%1,%2), operands);
- return AS1 (push%L2,%2);
- }
-}")
-
-;; Special memory<->memory pattern that combine will recreate from the
-;; moves to pseudos.
-(define_insn "movsf_mem"
- [(set (match_operand:SF 0 "memory_operand" "=m")
- (match_operand:SF 1 "memory_operand" "m"))
- (clobber (match_scratch:SI 2 "=&r"))]
- ""
- "*
-{
- output_asm_insn (AS2 (mov%L2,%1,%2), operands);
- return AS2 (mov%L0,%2,%0);
}")
;; For the purposes of regclass, prefer FLOAT_REGS.
-(define_insn "movsf_normal"
- [(set (match_operand:SF 0 "general_operand" "=*rfm,*rf,f,!*rm")
+(define_insn ""
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=*rfm,*rf,f,!*rm")
(match_operand:SF 1 "general_operand" "*rf,*rfm,fG,fF"))]
"(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
"*
@@ -1203,7 +1284,7 @@
if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
{
- output_to_reg (operands[0], stack_top_dies);
+ output_to_reg (operands[0], stack_top_dies, 0);
RET;
}
@@ -1228,7 +1309,9 @@
/* 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")
@@ -1244,50 +1327,17 @@
return AS1 (fxch,%0);
}")
-(define_expand "movdf"
- [(set (match_operand:DF 0 "general_operand" "")
- (match_operand:DF 1 "general_operand" ""))]
- ""
- "
-{
- /* Special case memory->memory moves and pushes */
- if (TARGET_MOVE
- && (reload_in_progress | reload_completed) == 0
- && GET_CODE (operands[0]) == MEM
- && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], DFmode)))
- {
- rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], DFmode))
- ? gen_movdf_push
- : gen_movdf_mem;
-
- emit_insn ((*genfunc) (operands[0], operands[1]));
- DONE;
- }
-
- /* 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. */
- if (flag_pic
- && GET_CODE (operands[0]) != MEM
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && !standard_80387_constant_p (operands[1]))
- {
- current_function_uses_pic_offset_table = 1;
- }
-}")
-
-(define_insn "movdf_push_nomove"
+(define_insn "movdf_push"
[(set (match_operand:DF 0 "push_operand" "=<,<")
- (match_operand:DF 1 "general_operand" "gF,f"))]
- "!TARGET_MOVE"
+ (match_operand:DF 1 "general_operand" "*rfF,o"))]
+ "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed"
"*
{
if (STACK_REG_P (operands[1]))
{
rtx xops[3];
- xops[0] = AT_SP (SFmode);
+ xops[0] = AT_SP (DFmode);
xops[1] = GEN_INT (8);
xops[2] = stack_pointer_rtx;
@@ -1300,56 +1350,65 @@
RET;
}
- else
- return output_move_double (operands);
+
+ if (which_alternative == 1)
+ return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 0, 0);
+
+ return output_move_double (operands);
}")
-(define_insn "movdf_push"
- [(set (match_operand:DF 0 "push_operand" "=<,<,<,<,<")
- (match_operand:DF 1 "general_operand" "rF,f,o,o,o"))
- (clobber (match_scratch:SI 2 "=X,X,&r,&r,X"))
- (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))]
+(define_insn "movdf_push_memory"
+ [(set (match_operand:DF 0 "push_operand" "=<")
+ (match_operand:DF 1 "memory_operand" "o"))]
+ "TARGET_PUSH_MEMORY"
+ "* return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode),0,0);")
+
+(define_expand "movdf"
+ [(set (match_operand:DF 0 "general_operand" "")
+ (match_operand:DF 1 "general_operand" ""))]
""
- "*
+ "
{
- if (STACK_REG_P (operands[1]))
+ /* 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 xops[3];
+ operands[1] = force_reg (DFmode, operands[1]);
+ }
- xops[0] = AT_SP (SFmode);
- xops[1] = GEN_INT (8);
- xops[2] = stack_pointer_rtx;
+ /* 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]))
+ {
+ rtx insn, note, fp_const;
- output_asm_insn (AS2 (sub%L2,%1,%2), xops);
+ fp_const = force_const_mem (DFmode, operands[1]);
+ if (flag_pic)
+ current_function_uses_pic_offset_table = 1;
- 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);
+ insn = emit_insn (gen_rtx_SET (DFmode, operands[0], fp_const));
+ note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
- RET;
+ if (note)
+ XEXP (note, 0) = operands[1];
+ else
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn));
}
-
- else if (GET_CODE (operands[1]) != MEM)
- return output_move_double (operands);
-
- else
- return output_move_pushmem (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);
}")
-(define_insn "movdf_mem"
- [(set (match_operand:DF 0 "memory_operand" "=o,o")
- (match_operand:DF 1 "memory_operand" "o,o"))
- (clobber (match_scratch:SI 2 "=&r,&r"))
- (clobber (match_scratch:SI 3 "=&r,X"))]
- ""
- "* return output_move_memory (operands, insn, GET_MODE_SIZE (DFmode), 2, 4);")
-
;; For the purposes of regclass, prefer FLOAT_REGS.
-(define_insn "movdf_normal"
- [(set (match_operand:DF 0 "general_operand" "=f,fm,!*rf,!*rm")
+(define_insn ""
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=f,fm,!*rf,!*rm")
(match_operand:DF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
- "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
+ "(!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;
@@ -1374,7 +1433,7 @@
if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
{
- output_to_reg (operands[0], stack_top_dies);
+ output_to_reg (operands[0], stack_top_dies, 0);
RET;
}
@@ -1399,7 +1458,10 @@
/* 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")
@@ -1415,109 +1477,87 @@
return AS1 (fxch,%0);
}")
-(define_expand "movxf"
- [(set (match_operand:XF 0 "general_operand" "")
- (match_operand:XF 1 "general_operand" ""))]
- ""
- "
-{
- /* Special case memory->memory moves and pushes */
- if (TARGET_MOVE
- && (reload_in_progress | reload_completed) == 0
- && GET_CODE (operands[0]) == MEM
- && (GET_CODE (operands[1]) == MEM || push_operand (operands[0], XFmode)))
- {
- rtx (*genfunc) PROTO((rtx, rtx)) = (push_operand (operands[0], XFmode))
- ? gen_movxf_push
- : gen_movxf_mem;
-
- emit_insn ((*genfunc) (operands[0], operands[1]));
- DONE;
- }
-
- /* 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. */
- if (flag_pic
- && GET_CODE (operands[0]) != MEM
- && GET_CODE (operands[1]) == CONST_DOUBLE
- && !standard_80387_constant_p (operands[1]))
- {
- current_function_uses_pic_offset_table = 1;
- }
-}")
-
-
-(define_insn "movxf_push_nomove"
+(define_insn "movxf_push"
[(set (match_operand:XF 0 "push_operand" "=<,<")
- (match_operand:XF 1 "general_operand" "gF,f"))]
- "!TARGET_MOVE"
+ (match_operand:XF 1 "general_operand" "*rfF,o"))]
+ "GET_CODE (operands[1]) != MEM || reload_in_progress || reload_completed"
"*
{
if (STACK_REG_P (operands[1]))
{
rtx xops[3];
- xops[0] = AT_SP (SFmode);
+ 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;
}
- else
- return output_move_double (operands);
+
+ if (which_alternative == 1)
+ return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 0, 0);
+
+ return output_move_double (operands);
}")
-(define_insn "movxf_push"
- [(set (match_operand:XF 0 "push_operand" "=<,<,<,<,<")
- (match_operand:XF 1 "general_operand" "rF,f,o,o,o"))
- (clobber (match_scratch:SI 2 "=X,X,&r,&r,X"))
- (clobber (match_scratch:SI 3 "=X,X,&r,X,X"))]
+(define_insn "movxf_push_memory"
+ [(set (match_operand:XF 0 "push_operand" "=<")
+ (match_operand:XF 1 "memory_operand" "o"))]
+ "TARGET_PUSH_MEMORY"
+ "* return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode),0,0);")
+
+(define_expand "movxf"
+ [(set (match_operand:XF 0 "general_operand" "")
+ (match_operand:XF 1 "general_operand" ""))]
""
- "*
+ "
{
- if (STACK_REG_P (operands[1]))
+ /* 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 xops[3];
-
- xops[0] = AT_SP (SFmode);
- xops[1] = GEN_INT (12);
- xops[2] = stack_pointer_rtx;
+ operands[1] = force_reg (XFmode, operands[1]);
+ }
- 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);
+ /* 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]))
+ {
+ rtx insn, note, fp_const;
- RET;
- }
+ fp_const = force_const_mem (XFmode, operands[1]);
+ if (flag_pic)
+ current_function_uses_pic_offset_table = 1;
- else if (GET_CODE (operands[1]) != MEM
- || GET_CODE (operands[2]) != REG)
- return output_move_double (operands);
+ insn = emit_insn (gen_rtx_SET (XFmode, operands[0], fp_const));
+ note = find_reg_note (insn, REG_EQUAL, NULL_RTX);
- else
- return output_move_pushmem (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);
+ if (note)
+ XEXP (note, 0) = operands[1];
+ else
+ REG_NOTES (insn) = gen_rtx_EXPR_LIST (REG_EQUAL, operands[1], REG_NOTES (insn));
+ }
}")
-(define_insn "movxf_mem"
- [(set (match_operand:XF 0 "memory_operand" "=o,o")
- (match_operand:XF 1 "memory_operand" "o,o"))
- (clobber (match_scratch:SI 2 "=&r,&r"))
- (clobber (match_scratch:SI 3 "=&r,X"))]
- ""
- "* return output_move_memory (operands, insn, GET_MODE_SIZE (XFmode), 2, 4);")
-(define_insn "movxf_normal"
- [(set (match_operand:XF 0 "general_operand" "=f,fm,!*rf,!*rm")
+(define_insn ""
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=f,fm,!*rf,!*rm")
(match_operand:XF 1 "general_operand" "fmG,f,*rfm,*rfF"))]
- "(!TARGET_MOVE || GET_CODE (operands[0]) != MEM) || (GET_CODE (operands[1]) != MEM)"
+ "(!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;
@@ -1542,7 +1582,7 @@
if (STACK_TOP_P (operands[1]) && NON_STACK_REG_P (operands[0]))
{
- output_to_reg (operands[0], stack_top_dies);
+ output_to_reg (operands[0], stack_top_dies, 0);
RET;
}
@@ -1570,7 +1610,7 @@
return output_move_double (operands);
}")
-(define_insn "swapxf"
+(define_insn "swapxf"
[(set (match_operand:XF 0 "register_operand" "f")
(match_operand:XF 1 "register_operand" "f"))
(set (match_dup 1)
@@ -1585,36 +1625,40 @@
}")
(define_insn ""
- [(set (match_operand:DI 0 "push_operand" "=<,<,<,<")
- (match_operand:DI 1 "general_operand" "riF,o,o,o"))
- (clobber (match_scratch:SI 2 "=X,&r,&r,X"))
- (clobber (match_scratch:SI 3 "=X,&r,X,X"))]
+ [(set (match_operand:DI 0 "push_operand" "=<")
+ (match_operand:DI 1 "general_operand" "riF"))]
""
- "*
-{
- if (GET_CODE (operands[1]) != MEM)
- return output_move_double (operands);
+ "* return output_move_double (operands);")
- else
- return output_move_pushmem (operands, insn, GET_MODE_SIZE (DImode), 2, 4);
-}")
+(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_insn "movdi"
- [(set (match_operand:DI 0 "general_operand" "=o,o,r,rm")
- (match_operand:DI 1 "general_operand" "o,o,m,riF"))
- (clobber (match_scratch:SI 2 "=&r,&r,X,X"))
- (clobber (match_scratch:SI 3 "=&r,X,X,X"))]
+(define_expand "movdi"
+ [(set (match_operand:DI 0 "general_operand" "")
+ (match_operand:DI 1 "general_operand" ""))]
""
- "*
+ "
{
- rtx low[2], high[2], xop[6];
-
- if (GET_CODE (operands[0]) != MEM || GET_CODE (operands[1]) != MEM)
- return output_move_double (operands);
- else
- return output_move_memory (operands, insn, GET_MODE_SIZE (DImode), 2, 4);
+ /* 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)
+ {
+ 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);")
+
;;- conversion instructions
;;- NONE
@@ -1623,21 +1667,39 @@
;; See comments by `andsi' for when andl is faster than movzx.
(define_insn "zero_extendhisi2"
- [(set (match_operand:SI 0 "general_operand" "=r")
- (zero_extend:SI
- (match_operand:HI 1 "nonimmediate_operand" "rm")))]
+ [(set (match_operand:SI 0 "register_operand" "=r,&r,?r")
+ (zero_extend:SI (match_operand:HI 1 "nonimmediate_operand" "0,rm,rm")))]
""
"*
-{
- if ((!TARGET_386 || REGNO (operands[0]) == 0)
+ {
+ rtx xops[2];
+
+ if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0)
&& REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
{
- rtx xops[2];
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);
@@ -1646,23 +1708,62 @@
#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_insn "zero_extendqihi2"
- [(set (match_operand:HI 0 "general_operand" "=r")
- (zero_extend:HI
- (match_operand:QI 1 "nonimmediate_operand" "qm")))]
+ [(set (match_operand:HI 0 "register_operand" "=q,&q,?r")
+ (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))]
""
"*
-{
- if ((!TARGET_386 || REGNO (operands[0]) == 0)
- && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
+ {
+ rtx xops[2];
+
+ if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0)
+ && REG_P (operands[1])
+ && REGNO (operands[0]) == REGNO (operands[1]))
{
- rtx xops[2];
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
@@ -1670,22 +1771,89 @@
#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_insn "zero_extendqisi2"
- [(set (match_operand:SI 0 "general_operand" "=r")
- (zero_extend:SI
- (match_operand:QI 1 "nonimmediate_operand" "qm")))]
+ [(set (match_operand:SI 0 "register_operand" "=q,&q,?r")
+ (zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "0,qm,qm")))]
""
"*
-{
- if ((!TARGET_386 || REGNO (operands[0]) == 0)
- && REG_P (operands[1]) && REGNO (operands[0]) == REGNO (operands[1]))
+ {
+ rtx xops[2];
+
+ if ((TARGET_ZERO_EXTEND_WITH_AND || REGNO (operands[0]) == 0)
+ && REG_P (operands[1])
+ && REGNO (operands[0]) == REGNO (operands[1]))
{
- rtx xops[2];
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);
@@ -1694,23 +1862,77 @@
#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 "register_operand" "=r")
- (zero_extend:DI
- (match_operand:SI 1 "register_operand" "0")))]
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=r,?r,?m")
+ (zero_extend:DI (match_operand:SI 1 "register_operand" "0,rm,r")))]
""
"*
-{
- operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
- return AS2 (xor%L0,%0,%0);
+ {
+ rtx high[2], low[2], xops[4];
+
+ if (REG_P (operands[0]) && REG_P (operands[1])
+ && REGNO (operands[0]) == REGNO (operands[1]))
+ {
+ operands[0] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
+ return AS2 (xor%L0,%0,%0);
+ }
+
+ split_di (operands, 1, low, high);
+ xops[0] = low[0];
+ xops[1] = operands[1];
+ xops[2] = high[0];
+ xops[3] = const0_rtx;
+
+ 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;
}")
;;- sign extension instructions
(define_insn "extendsidi2"
[(set (match_operand:DI 0 "register_operand" "=r")
- (sign_extend:DI
- (match_operand:SI 1 "register_operand" "0")))]
+ (sign_extend:DI (match_operand:SI 1 "register_operand" "0")))]
""
"*
{
@@ -1724,7 +1946,7 @@
#endif
}
- operands[1] = gen_rtx (REG, SImode, REGNO (operands[0]) + 1);
+ operands[1] = gen_rtx_REG (SImode, REGNO (operands[0]) + 1);
output_asm_insn (AS2 (mov%L0,%0,%1), operands);
operands[0] = GEN_INT (31);
@@ -1736,9 +1958,8 @@
;; We use what the Unix assembler expects.
(define_insn "extendhisi2"
- [(set (match_operand:SI 0 "general_operand" "=r")
- (sign_extend:SI
- (match_operand:HI 1 "nonimmediate_operand" "rm")))]
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:HI 1 "nonimmediate_operand" "rm")))]
""
"*
{
@@ -1758,9 +1979,8 @@
}")
(define_insn "extendqihi2"
- [(set (match_operand:HI 0 "general_operand" "=r")
- (sign_extend:HI
- (match_operand:QI 1 "nonimmediate_operand" "qm")))]
+ [(set (match_operand:HI 0 "register_operand" "=r")
+ (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
""
"*
{
@@ -1776,9 +1996,8 @@
}")
(define_insn "extendqisi2"
- [(set (match_operand:SI 0 "general_operand" "=r")
- (sign_extend:SI
- (match_operand:QI 1 "nonimmediate_operand" "qm")))]
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (sign_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm")))]
""
"*
{
@@ -1788,13 +2007,72 @@
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_insn "extendsfdf2"
- [(set (match_operand:DF 0 "general_operand" "=fm,f")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=fm,f")
(float_extend:DF
- (match_operand:SF 1 "general_operand" "f,fm")))]
+ (match_operand:SF 1 "nonimmediate_operand" "f,fm")))]
"TARGET_80387"
"*
{
@@ -1808,7 +2086,7 @@
if (NON_STACK_REG_P (operands[0]))
{
- output_to_reg (operands[0], stack_top_dies);
+ output_to_reg (operands[0], stack_top_dies, 0);
RET;
}
@@ -1827,9 +2105,9 @@
}")
(define_insn "extenddfxf2"
- [(set (match_operand:XF 0 "general_operand" "=fm,f,f,!*r")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f,f,!*r")
(float_extend:XF
- (match_operand:DF 1 "general_operand" "f,fm,!*r,f")))]
+ (match_operand:DF 1 "nonimmediate_operand" "f,fm,!*r,f")))]
"TARGET_80387"
"*
{
@@ -1843,7 +2121,7 @@
if (NON_STACK_REG_P (operands[0]))
{
- output_to_reg (operands[0], stack_top_dies);
+ output_to_reg (operands[0], stack_top_dies, 0);
RET;
}
@@ -1862,9 +2140,9 @@
}")
(define_insn "extendsfxf2"
- [(set (match_operand:XF 0 "general_operand" "=fm,f,f,!*r")
+ [(set (match_operand:XF 0 "nonimmediate_operand" "=fm,f,f,!*r")
(float_extend:XF
- (match_operand:SF 1 "general_operand" "f,fm,!*r,f")))]
+ (match_operand:SF 1 "nonimmediate_operand" "f,fm,!*r,f")))]
"TARGET_80387"
"*
{
@@ -1878,7 +2156,7 @@
if (NON_STACK_REG_P (operands[0]))
{
- output_to_reg (operands[0], stack_top_dies);
+ output_to_reg (operands[0], stack_top_dies, 0);
RET;
}
@@ -1939,7 +2217,7 @@
}")
(define_insn "truncxfsf2"
- [(set (match_operand:SF 0 "general_operand" "=m,!*r")
+ [(set (match_operand:SF 0 "nonimmediate_operand" "=m,!*r")
(float_truncate:SF
(match_operand:XF 1 "register_operand" "f,f")))]
"TARGET_80387"
@@ -1954,7 +2232,7 @@
output_asm_insn (AS1 (fld,%y1), operands);
stack_top_dies = 1;
}
- output_to_reg (operands[0], stack_top_dies);
+ output_to_reg (operands[0], stack_top_dies, 0);
RET;
}
else if (GET_CODE (operands[0]) == MEM)
@@ -1972,7 +2250,7 @@
}")
(define_insn "truncxfdf2"
- [(set (match_operand:DF 0 "general_operand" "=m,!*r")
+ [(set (match_operand:DF 0 "nonimmediate_operand" "=m,!*r")
(float_truncate:DF
(match_operand:XF 1 "register_operand" "f,f")))]
"TARGET_80387"
@@ -1987,7 +2265,7 @@
output_asm_insn (AS1 (fld,%y1), operands);
stack_top_dies = 1;
}
- output_to_reg (operands[0], stack_top_dies);
+ output_to_reg (operands[0], stack_top_dies, 0);
RET;
}
else if (GET_CODE (operands[0]) == MEM)
@@ -2029,7 +2307,7 @@
operands[3] = gen_lowpart (SImode, operands[2]);
operands[4] = gen_reg_rtx (XFmode);
operands[5] = (rtx) assign_386_stack_local (SImode, 0);
- operands[6] = (rtx) assign_386_stack_local (SImode, 1);
+ operands[6] = (rtx) assign_386_stack_local (DImode, 1);
}")
(define_expand "fixuns_truncdfsi2"
@@ -2050,7 +2328,7 @@
operands[3] = gen_lowpart (SImode, operands[2]);
operands[4] = gen_reg_rtx (DFmode);
operands[5] = (rtx) assign_386_stack_local (SImode, 0);
- operands[6] = (rtx) assign_386_stack_local (SImode, 1);
+ operands[6] = (rtx) assign_386_stack_local (DImode, 1);
}")
(define_expand "fixuns_truncsfsi2"
@@ -2071,7 +2349,7 @@
operands[3] = gen_lowpart (SImode, operands[2]);
operands[4] = gen_reg_rtx (SFmode);
operands[5] = (rtx) assign_386_stack_local (SImode, 0);
- operands[6] = (rtx) assign_386_stack_local (SImode, 1);
+ operands[6] = (rtx) assign_386_stack_local (DImode, 1);
}")
;; Signed conversion to DImode.
@@ -2091,7 +2369,7 @@
operands[1] = copy_to_mode_reg (XFmode, operands[1]);
operands[2] = gen_reg_rtx (XFmode);
operands[3] = (rtx) assign_386_stack_local (SImode, 0);
- operands[4] = (rtx) assign_386_stack_local (SImode, 1);
+ operands[4] = (rtx) assign_386_stack_local (DImode, 1);
}")
(define_expand "fix_truncdfdi2"
@@ -2109,7 +2387,7 @@
operands[1] = copy_to_mode_reg (DFmode, operands[1]);
operands[2] = gen_reg_rtx (DFmode);
operands[3] = (rtx) assign_386_stack_local (SImode, 0);
- operands[4] = (rtx) assign_386_stack_local (SImode, 1);
+ operands[4] = (rtx) assign_386_stack_local (DImode, 1);
}")
(define_expand "fix_truncsfdi2"
@@ -2127,37 +2405,37 @@
operands[1] = copy_to_mode_reg (SFmode, operands[1]);
operands[2] = gen_reg_rtx (SFmode);
operands[3] = (rtx) assign_386_stack_local (SImode, 0);
- operands[4] = (rtx) assign_386_stack_local (SImode, 1);
+ operands[4] = (rtx) assign_386_stack_local (DImode, 1);
}")
;; These match a signed conversion of either DFmode or SFmode to DImode.
(define_insn ""
- [(set (match_operand:DI 0 "general_operand" "=rm")
- (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+ (fix:DI (fix:XF (match_operand:XF 1 "register_operand" "+f"))))
(clobber (match_dup 1))
(clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:SI 3 "memory_operand" "m"))
+ (clobber (match_operand:DI 3 "memory_operand" "m"))
(clobber (match_scratch:SI 4 "=&q"))]
"TARGET_80387"
"* return output_fix_trunc (insn, operands);")
(define_insn ""
- [(set (match_operand:DI 0 "general_operand" "=rm")
- (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+ (fix:DI (fix:DF (match_operand:DF 1 "register_operand" "+f"))))
(clobber (match_dup 1))
(clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:SI 3 "memory_operand" "m"))
+ (clobber (match_operand:DI 3 "memory_operand" "m"))
(clobber (match_scratch:SI 4 "=&q"))]
"TARGET_80387"
"* return output_fix_trunc (insn, operands);")
(define_insn ""
- [(set (match_operand:DI 0 "general_operand" "=rm")
- (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
+ [(set (match_operand:DI 0 "nonimmediate_operand" "=rm")
+ (fix:DI (fix:SF (match_operand:SF 1 "register_operand" "+f"))))
(clobber (match_dup 1))
(clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:SI 3 "memory_operand" "m"))
+ (clobber (match_operand:DI 3 "memory_operand" "m"))
(clobber (match_scratch:SI 4 "=&q"))]
"TARGET_80387"
"* return output_fix_trunc (insn, operands);")
@@ -2175,7 +2453,7 @@
"
{
operands[2] = (rtx) assign_386_stack_local (SImode, 0);
- operands[3] = (rtx) assign_386_stack_local (SImode, 1);
+ operands[3] = (rtx) assign_386_stack_local (DImode, 1);
}")
(define_expand "fix_truncdfsi2"
@@ -2189,7 +2467,7 @@
"
{
operands[2] = (rtx) assign_386_stack_local (SImode, 0);
- operands[3] = (rtx) assign_386_stack_local (SImode, 1);
+ operands[3] = (rtx) assign_386_stack_local (DImode, 1);
}")
(define_expand "fix_truncsfsi2"
@@ -2203,32 +2481,32 @@
"
{
operands[2] = (rtx) assign_386_stack_local (SImode, 0);
- operands[3] = (rtx) assign_386_stack_local (SImode, 1);
+ operands[3] = (rtx) assign_386_stack_local (DImode, 1);
}")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=rm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(fix:SI (fix:XF (match_operand:XF 1 "register_operand" "f"))))
(clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:SI 3 "memory_operand" "m"))
+ (clobber (match_operand:DI 3 "memory_operand" "m"))
(clobber (match_scratch:SI 4 "=&q"))]
"TARGET_80387"
"* return output_fix_trunc (insn, operands);")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=rm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(fix:SI (fix:DF (match_operand:DF 1 "register_operand" "f"))))
(clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:SI 3 "memory_operand" "m"))
+ (clobber (match_operand:DI 3 "memory_operand" "m"))
(clobber (match_scratch:SI 4 "=&q"))]
"TARGET_80387"
"* return output_fix_trunc (insn, operands);")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=rm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(fix:SI (fix:SF (match_operand:SF 1 "register_operand" "f"))))
(clobber (match_operand:SI 2 "memory_operand" "m"))
- (clobber (match_operand:SI 3 "memory_operand" "m"))
+ (clobber (match_operand:DI 3 "memory_operand" "m"))
(clobber (match_scratch:SI 4 "=&q"))]
"TARGET_80387"
"* return output_fix_trunc (insn, operands);")
@@ -2271,14 +2549,14 @@
(define_expand "floatdixf2"
[(set (match_operand:XF 0 "register_operand" "")
(float:XF (match_operand:DI 1 "nonimmediate_operand" "")))]
- "TARGET_80387"
+ "TARGET_80387 && LONG_DOUBLE_TYPE_SIZE == 96"
"")
;; This will convert from SImode or DImode to MODE_FLOAT.
(define_insn ""
[(set (match_operand:XF 0 "register_operand" "=f")
- (float:XF (match_operand:DI 1 "general_operand" "rm")))]
+ (float:XF (match_operand:DI 1 "nonimmediate_operand" "rm")))]
"TARGET_80387"
"*
{
@@ -2346,7 +2624,7 @@
(define_insn ""
[(set (match_operand:XF 0 "register_operand" "=f,f")
- (float:XF (match_operand:SI 1 "general_operand" "m,!*r")))]
+ (float:XF (match_operand:SI 1 "nonimmediate_operand" "m,!*r")))]
"TARGET_80387"
"*
{
@@ -2380,11 +2658,137 @@
;;- 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], temp;
+
+ 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);
+ RET;
+}")
+
+(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], temp;
+
+ 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);
+ RET;
+}")
+
(define_insn "adddi3"
- [(set (match_operand:DI 0 "general_operand" "=&r,ro,o,&r,ro,o,&r,o,o,o")
- (plus:DI (match_operand:DI 1 "general_operand" "%0,0,0,o,riF,o,or,riF,riF,o")
- (match_operand:DI 2 "general_operand" "o,riF,o,0,0,0,oriF,riF,o,o")))
- (clobber (match_scratch:SI 3 "=X,X,&r,X,&r,&r,X,&r,&r,&r"))]
+ [(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"))]
""
"*
{
@@ -2456,14 +2860,23 @@
;; 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_insn "addsi3"
- [(set (match_operand:SI 0 "general_operand" "=?r,rm,r")
- (plus:SI (match_operand:SI 1 "general_operand" "%r,0,0")
- (match_operand:SI 2 "general_operand" "ri,ri,rm")))]
+(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]) && REGNO (operands[0]) != REGNO (operands[1]))
+ if (REG_P (operands[0]) && REG_P (operands[1])
+ && (REG_P (operands[2]) || GET_CODE (operands[2]) == CONST_INT)
+ && REGNO (operands[0]) != REGNO (operands[1]))
{
if (REG_P (operands[2]) && REGNO (operands[0]) == REGNO (operands[2]))
return AS2 (add%L0,%1,%0);
@@ -2483,34 +2896,85 @@
operands[1] = SET_SRC (PATTERN (insn));
return AS2 (lea%L0,%a1,%0);
}
-
- output_asm_insn (AS2 (mov%L0,%1,%0), operands);
}
+ 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);
}")
+;; 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);
+}")
+
;; ??? `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_insn "addhi3"
- [(set (match_operand:HI 0 "general_operand" "=rm,r")
- (plus:HI (match_operand:HI 1 "general_operand" "%0,0")
- (match_operand:HI 2 "general_operand" "ri,rm")))]
+(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")
+ (plus:HI (match_operand:HI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:HI 2 "general_operand" "ri,rm")))]
+ "ix86_binary_operator_ok (PLUS, HImode, operands)"
"*
{
/* ??? what about offsettable memory references? */
- if (QI_REG_P (operands[0])
+ 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)
+ && (INTVAL (operands[2]) & 0xff) == 0
+ && i386_cc_probably_useless_p (insn))
{
int byteval = (INTVAL (operands[2]) >> 8) & 0xff;
CC_STATUS_INIT;
@@ -2524,6 +2988,28 @@
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);
@@ -2535,11 +3021,18 @@
return AS2 (add%W0,%2,%0);
}")
-(define_insn "addqi3"
- [(set (match_operand:QI 0 "general_operand" "=qm,q")
- (plus:QI (match_operand:QI 1 "general_operand" "%0,0")
- (match_operand:QI 2 "general_operand" "qn,qmn")))]
+(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")
+ (plus:QI (match_operand:QI 1 "nonimmediate_operand" "%0,0")
+ (match_operand:QI 2 "general_operand" "qn,qmn")))]
+ "ix86_binary_operator_ok (PLUS, QImode, operands)"
"*
{
if (operands[2] == const1_rtx)
@@ -2563,8 +3056,8 @@
;
;(define_insn ""
; [(set (match_operand:SI 0 "push_operand" "=<")
-; (plus:SI (match_operand:SI 1 "general_operand" "%r")
-; (match_operand:SI 2 "general_operand" "ri")))]
+; (plus:SI (match_operand:SI 1 "register_operand" "%r")
+; (match_operand:SI 2 "nonmemory_operand" "ri")))]
; ""
; "*
;{
@@ -2572,46 +3065,18 @@
; xops[0] = operands[0];
; xops[1] = operands[1];
; xops[2] = operands[2];
-; xops[3] = gen_rtx (MEM, SImode, stack_pointer_rtx);
+; 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;
;}")
-;; 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"))]
- ""
- "*
-{
- CC_STATUS_INIT;
- /* 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);
- }
- return AS2 (lea%L0,%a1,%0);
-}")
-
;; 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 "nonimmediate_operand" "")
- (match_operand:XF 2 "nonimmediate_operand" "")))]
+ (plus:XF (match_operand:XF 1 "register_operand" "")
+ (match_operand:XF 2 "register_operand" "")))]
"TARGET_80387"
"")
@@ -2631,11 +3096,59 @@
;;- 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);
+ RET;
+}")
+
(define_insn "subdi3"
- [(set (match_operand:DI 0 "general_operand" "=&r,ro,&r,o,o")
- (minus:DI (match_operand:DI 1 "general_operand" "0,0,roiF,riF,o")
- (match_operand:DI 2 "general_operand" "o,riF,roiF,riF,o")))
- (clobber (match_scratch:SI 3 "=X,X,X,&r,&r"))]
+ [(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"))]
""
"*
{
@@ -2698,33 +3211,65 @@
RET;
}")
-(define_insn "subsi3"
- [(set (match_operand:SI 0 "general_operand" "=rm,r")
- (minus:SI (match_operand:SI 1 "general_operand" "0,0")
- (match_operand:SI 2 "general_operand" "ri,rm")))]
+(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);")
-(define_insn "subhi3"
- [(set (match_operand:HI 0 "general_operand" "=rm,r")
- (minus:HI (match_operand:HI 1 "general_operand" "0,0")
+(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);
+}")
+
+(define_expand "subqi3"
+ [(set (match_operand:QI 0 "general_operand" "")
+ (minus:QI (match_operand:QI 1 "general_operand" "")
+ (match_operand:QI 2 "general_operand" "")))]
""
- "* return AS2 (sub%W0,%2,%0);")
+ "IX86_EXPAND_BINARY_OPERATOR (MINUS, QImode, operands);")
-(define_insn "subqi3"
- [(set (match_operand:QI 0 "general_operand" "=qm,q")
- (minus:QI (match_operand:QI 1 "general_operand" "0,0")
+(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);")
;; 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 "nonimmediate_operand" "")
- (match_operand:XF 2 "nonimmediate_operand" "")))]
+ (minus:XF (match_operand:XF 1 "register_operand" "")
+ (match_operand:XF 2 "register_operand" "")))]
"TARGET_80387"
"")
@@ -2745,22 +3290,15 @@
;;- multiply instructions
;(define_insn "mulqi3"
-; [(set (match_operand:QI 0 "general_operand" "=a")
-; (mult:QI (match_operand:QI 1 "general_operand" "%0")
-; (match_operand:QI 2 "general_operand" "qm")))]
+; [(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 ""
- [(set (match_operand:HI 0 "general_operand" "=r")
- (mult:HI (match_operand:HI 1 "general_operand" "%0")
- (match_operand:HI 2 "general_operand" "r")))]
- "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80"
- "* return AS2 (imul%W0,%2,%0);")
-
(define_insn "mulhi3"
- [(set (match_operand:HI 0 "general_operand" "=r,r")
- (mult:HI (match_operand:HI 1 "general_operand" "%0,rm")
+ [(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")))]
""
"*
@@ -2771,18 +3309,12 @@
/* Assembler has weird restrictions. */
return AS2 (imul%W0,%2,%0);
return AS3 (imul%W0,%2,%1,%0);
-}")
-
-(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=r")
- (mult:SI (match_operand:SI 1 "general_operand" "%0")
- (match_operand:SI 2 "general_operand" "r")))]
- "GET_CODE (operands[2]) == CONST_INT && INTVAL (operands[2]) == 0x80"
- "* return AS2 (imul%L0,%2,%0);")
+}"
+ [(set_attr "type" "imul")])
(define_insn "mulsi3"
- [(set (match_operand:SI 0 "general_operand" "=r,r")
- (mult:SI (match_operand:SI 1 "general_operand" "%0,rm")
+ [(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")))]
""
"*
@@ -2793,35 +3325,40 @@
/* 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 "general_operand" "=a")
- (mult:HI (zero_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
+ [(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")
+ "mul%B0 %2"
+ [(set_attr "type" "imul")])
(define_insn "mulqihi3"
- [(set (match_operand:HI 0 "general_operand" "=a")
- (mult:HI (sign_extend:HI (match_operand:QI 1 "nonimmediate_operand" "%0"))
+ [(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")
+ "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")
+ "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")
+ "imul%L0 %2"
+ [(set_attr "type" "imul")])
(define_insn "umulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=d")
@@ -2830,7 +3367,8 @@
(const_int 32))))
(clobber (match_scratch:SI 3 "=a"))]
"TARGET_WIDE_MULTIPLY"
- "mul%L0 %2")
+ "mul%L0 %2"
+ [(set_attr "type" "imul")])
(define_insn "smulsi3_highpart"
[(set (match_operand:SI 0 "register_operand" "=d")
@@ -2839,27 +3377,28 @@
(const_int 32))))
(clobber (match_scratch:SI 3 "=a"))]
"TARGET_WIDE_MULTIPLY"
- "imul%L0 %2")
+ "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 "nonimmediate_operand" "")
- (match_operand:XF 2 "nonimmediate_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 "nonimmediate_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 "nonimmediate_operand" "")
+ (mult:SF (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "nonimmediate_operand" "")))]
"TARGET_80387"
"")
@@ -2867,38 +3406,39 @@
;;- divide instructions
(define_insn "divqi3"
- [(set (match_operand:QI 0 "general_operand" "=a")
- (div:QI (match_operand:HI 1 "general_operand" "0")
- (match_operand:QI 2 "general_operand" "qm")))]
+ [(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 "general_operand" "=a")
- (udiv:QI (match_operand:HI 1 "general_operand" "0")
- (match_operand:QI 2 "general_operand" "qm")))]
+ [(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")
+ "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 "nonimmediate_operand" "")
- (match_operand:XF 2 "nonimmediate_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 "nonimmediate_operand" "")
- (match_operand:DF 2 "nonimmediate_operand" "")))]
- "TARGET_80387"
- "")
-
+ (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 "nonimmediate_operand" "")
+ (div:SF (match_operand:SF 1 "register_operand" "")
(match_operand:SF 2 "nonimmediate_operand" "")))]
"TARGET_80387"
"")
@@ -2908,7 +3448,7 @@
(define_insn "divmodsi4"
[(set (match_operand:SI 0 "register_operand" "=a")
(div:SI (match_operand:SI 1 "register_operand" "0")
- (match_operand:SI 2 "general_operand" "rm")))
+ (match_operand:SI 2 "nonimmediate_operand" "rm")))
(set (match_operand:SI 3 "register_operand" "=&d")
(mod:SI (match_dup 1) (match_dup 2)))]
""
@@ -2920,22 +3460,24 @@
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 "general_operand" "rm")))
+ (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")
+ "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 "general_operand" "rm")))
+ (match_operand:SI 2 "nonimmediate_operand" "rm")))
(set (match_operand:SI 3 "register_operand" "=&d")
(umod:SI (match_dup 1) (match_dup 2)))]
""
@@ -2943,13 +3485,14 @@
{
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 "general_operand" "rm")))
+ (match_operand:HI 2 "nonimmediate_operand" "rm")))
(set (match_operand:HI 3 "register_operand" "=&d")
(umod:HI (match_dup 1) (match_dup 2)))]
""
@@ -2957,7 +3500,8 @@
{
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
@@ -2965,11 +3509,12 @@
(define_insn ""
[(set (match_operand:SI 0 "register_operand" "=a")
(udiv:DI (match_operand:DI 1 "register_operand" "a")
- (match_operand:SI 2 "general_operand" "rm")))
+ (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")
+ "div%L0 %2,%0"
+ [(set_attr "type" "idiv")])
*/
;;- and instructions
@@ -2989,21 +3534,33 @@
;; 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.
-;; ??? What if we only change one byte of an offsettable memory reference?
(define_insn "andsi3"
- [(set (match_operand:SI 0 "general_operand" "=r,r,rm,r")
- (and:SI (match_operand:SI 1 "general_operand" "%rm,qm,0,0")
- (match_operand:SI 2 "general_operand" "L,K,ri,rm")))]
+ [(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")))]
""
"*
{
- if (GET_CODE (operands[2]) == CONST_INT
- && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
+ 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]))
{
- if (INTVAL (operands[2]) == 0xffff && REG_P (operands[0])
+ 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_386 || ! rtx_equal_p (operands[0], operands[1])))
+ && (!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. */
@@ -3015,11 +3572,12 @@
#endif
}
- if (INTVAL (operands[2]) == 0xff && REG_P (operands[0])
+ /* 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_386 || ! rtx_equal_p (operands[0], operands[1])))
+ && (!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. */
@@ -3031,47 +3589,110 @@
#endif
}
- if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff) == 0)
- {
- CC_STATUS_INIT;
+ /* Check partial bytes.. non-QI-regs are not available */
+ if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
+ break;
- if (INTVAL (operands[2]) == 0xffffff00)
+ /* only low byte has zero bits? */
+ if (~(intval | 0xff) == 0)
+ {
+ intval &= 0xff;
+ if (REG_P (operands[0]))
{
- operands[2] = const0_rtx;
- return AS2 (mov%B0,%2,%b0);
+ 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;
}
- operands[2] = GEN_INT (INTVAL (operands[2]) & 0xff);
+ CC_STATUS_INIT;
+
+ operands[2] = GEN_INT (intval);
+
+ if (intval == 0)
+ return AS2 (mov%B0,%2,%b0);
+
return AS2 (and%B0,%2,%b0);
}
- if (QI_REG_P (operands[0]) && ~(INTVAL (operands[2]) | 0xff00) == 0)
+ /* only second byte has zero? */
+ if (~(intval | 0xff00) == 0)
{
CC_STATUS_INIT;
- if (INTVAL (operands[2]) == 0xffff00ff)
+ intval = (intval >> 8) & 0xff;
+ operands[2] = GEN_INT (intval);
+ if (intval == 0)
{
- operands[2] = const0_rtx;
- return AS2 (mov%B0,%2,%h0);
+ 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);
}
- operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
- return AS2 (and%B0,%2,%h0);
+ 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);
}
- if (GET_CODE (operands[0]) == MEM && INTVAL (operands[2]) == 0xffff0000)
+ /* 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);
}")
(define_insn "andhi3"
- [(set (match_operand:HI 0 "general_operand" "=rm,r")
- (and:HI (match_operand:HI 1 "general_operand" "%0,0")
+ [(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")))]
""
"*
@@ -3110,14 +3731,46 @@
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);
}")
(define_insn "andqi3"
- [(set (match_operand:QI 0 "general_operand" "=qm,q")
- (and:QI (match_operand:QI 1 "general_operand" "%0,0")
+ [(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);")
@@ -3136,10 +3789,10 @@
"and%W0 %1,%0")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=q")
+ [(set (match_operand:SI 0 "register_operand" "=q")
(and:SI
(zero_extend:SI (match_operand:QI 1 "nonimmediate_operand" "qm"))
- (match_operand:SI 2 "general_operand" "0")))]
+ (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")
@@ -3148,134 +3801,278 @@
;;- Bit set (inclusive or) instructions
-;; ??? What if we only change one byte of an offsettable memory reference?
+;; 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 "general_operand" "=rm,r")
- (ior:SI (match_operand:SI 1 "general_operand" "%0,0")
+ [(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")))]
""
"*
{
- if (GET_CODE (operands[2]) == CONST_INT
- && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
+ HOST_WIDE_INT intval;
+ switch (GET_CODE (operands[2]))
{
- if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
- && (INTVAL (operands[2]) & ~0xff) == 0)
- {
- CC_STATUS_INIT;
+ case CONST_INT:
- if (INTVAL (operands[2]) == 0xff)
- return AS2 (mov%B0,%2,%b0);
+ 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;
- return AS2 (or%B0,%2,%b0);
+ 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);
}
- if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0)
+ /* second byte? */
+ if ((intval & ~0xff00) == 0)
{
- CC_STATUS_INIT;
- operands[2] = GEN_INT (INTVAL (operands[2]) >> 8);
+ intval >>= 8;
- if (INTVAL (operands[2]) == 0xff)
- return AS2 (mov%B0,%2,%h0);
+ 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);
+ }
- 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);
}")
(define_insn "iorhi3"
- [(set (match_operand:HI 0 "general_operand" "=rm,r")
- (ior:HI (match_operand:HI 1 "general_operand" "%0,0")
+ [(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")))]
""
"*
{
- if (GET_CODE (operands[2]) == CONST_INT
- && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
+ HOST_WIDE_INT intval;
+ switch (GET_CODE (operands[2]))
{
- /* 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);
+ case CONST_INT:
- if (INTVAL (operands[2]) == 0xff)
- return AS2 (mov%B0,%2,%b0);
+ if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
+ break;
- return AS2 (or%B0,%2,%b0);
+ /* 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);
}
- /* Can we ignore the lower byte? */
- /* ??? what about offsettable memory references? */
- if (QI_REG_P (operands[0])
- && (INTVAL (operands[2]) & 0xff) == 0)
+ /* high byte? */
+ if ((intval & 0xff) == 0)
{
- CC_STATUS_INIT;
- operands[2] = GEN_INT ((INTVAL (operands[2]) >> 8) & 0xff);
+ intval >>= 8;
+ operands[2] = GEN_INT (intval);
- if (INTVAL (operands[2]) == 0xff)
- return AS2 (mov%B0,%2,%h0);
+ if (REG_P (operands[0]))
+ {
+ CC_STATUS_INIT;
+ if (intval == 0xff)
+ return AS2 (mov%B0,%2,%h0);
- return AS2 (or%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);
}")
(define_insn "iorqi3"
- [(set (match_operand:QI 0 "general_operand" "=qm,q")
- (ior:QI (match_operand:QI 1 "general_operand" "%0,0")
+ [(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);")
;;- xor instructions
-;; ??? What if we only change one byte of an offsettable memory reference?
(define_insn "xorsi3"
- [(set (match_operand:SI 0 "general_operand" "=rm,r")
- (xor:SI (match_operand:SI 1 "general_operand" "%0,0")
+ [(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")))]
""
"*
{
- if (GET_CODE (operands[2]) == CONST_INT
- && ! (GET_CODE (operands[0]) == MEM && MEM_VOLATILE_P (operands[0])))
+ HOST_WIDE_INT intval;
+ switch (GET_CODE (operands[2]))
{
- if ((! REG_P (operands[0]) || QI_REG_P (operands[0]))
- && (INTVAL (operands[2]) & ~0xff) == 0)
- {
- CC_STATUS_INIT;
+ case CONST_INT:
- if (INTVAL (operands[2]) == 0xff)
- return AS1 (not%B0,%b0);
+ if (REG_P (operands[0]) && ! QI_REG_P (operands[0]))
+ break;
- return AS2 (xor%B0,%2,%b0);
+ /* 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)
+ return AS1 (not%B0,%b0);
+
+ if (intval != INTVAL (operands[2]))
+ operands[2] = GEN_INT (intval);
+ return AS2 (xor%B0,%2,%b0);
}
- if (QI_REG_P (operands[0]) && (INTVAL (operands[2]) & ~0xff00) == 0)
+ /* second byte? */
+ if ((intval & ~0xff00) == 0)
{
- CC_STATUS_INIT;
- operands[2] = GEN_INT (INTVAL (operands[2]) >> 8);
+ intval >>= 8;
- if (INTVAL (operands[2]) == 0xff)
- return AS1 (not%B0,%h0);
+ if (REG_P (operands[0]))
+ {
+ CC_STATUS_INIT;
+ if (intval == 0xff)
+ return AS1 (not%B0,%h0);
- return AS2 (xor%B0,%2,%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);
}")
(define_insn "xorhi3"
- [(set (match_operand:HI 0 "general_operand" "=rm,r")
- (xor:HI (match_operand:HI 1 "general_operand" "%0,0")
+ [(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")))]
""
"*
@@ -3312,16 +4109,136 @@
}
}
+ 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);
}")
(define_insn "xorqi3"
- [(set (match_operand:QI 0 "general_operand" "=qm,q")
- (xor:QI (match_operand:QI 1 "general_operand" "%0,0")
+ [(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);")
+;; logical operations for DImode
+
+
+(define_insn "anddi3"
+ [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
+ (and: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"))]
+ ""
+ "#")
+
+(define_insn "iordi3"
+ [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
+ (ior: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"))]
+ ""
+ "#")
+
+(define_insn "xordi3"
+ [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
+ (xor: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"))]
+ ""
+ "#")
+
+(define_split
+ [(set (match_operand:DI 0 "general_operand" "=&r,&ro,!r,o,!&r,!o,!o")
+ (match_operator:DI 4 "ix86_logical_operator"
+ [(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"))]
+ "reload_completed"
+ [(const_int 0)]
+ "
+{
+ rtx low[3], high[3], xops[7], temp;
+ rtx (*genfunc)() = (GET_CODE (operands[4]) == AND ? gen_andsi3
+ : GET_CODE (operands[4]) == IOR ? gen_iorsi3
+ : GET_CODE (operands[4]) == XOR ? gen_xorsi3
+ : 0);
+
+ 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)
+ {
+ emit_insn (gen_movsi (xops[1], xops[3]));
+ emit_insn (gen_movsi (xops[0], xops[2]));
+ }
+ else
+ {
+ xops[4] = high[2];
+ xops[5] = low[2];
+ xops[6] = operands[3];
+ emit_insn (gen_movsi (xops[6], xops[3]));
+ emit_insn ((*genfunc) (xops[6], xops[6], xops[5]));
+ emit_insn (gen_movsi (xops[1], xops[6]));
+ emit_insn (gen_movsi (xops[6], xops[2]));
+ emit_insn ((*genfunc) (xops[6], xops[6], xops[4]));
+ emit_insn (gen_movsi (xops[0], xops[6]));
+ DONE;
+ }
+ }
+
+ 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];
+
+ emit_insn (gen_movsi (xops[4], xops[3]));
+ emit_insn ((*genfunc) (xops[1], xops[1], xops[4]));
+ emit_insn (gen_movsi (xops[4], xops[2]));
+ emit_insn ((*genfunc) (xops[0], xops[0], xops[4]));
+ }
+
+ else
+ {
+ emit_insn ((*genfunc) (low[0], low[0], low[2]));
+ emit_insn ((*genfunc) (high[0], high[0], high[2]));
+ }
+
+ DONE;
+}")
+
;;- negation instructions
(define_insn "negdi2"
@@ -3345,50 +4262,50 @@
}")
(define_insn "negsi2"
- [(set (match_operand:SI 0 "general_operand" "=rm")
- (neg:SI (match_operand:SI 1 "general_operand" "0")))]
+ [(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 "general_operand" "=rm")
- (neg:HI (match_operand:HI 1 "general_operand" "0")))]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
+ (neg:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
""
"neg%W0 %0")
(define_insn "negqi2"
- [(set (match_operand:QI 0 "general_operand" "=qm")
- (neg:QI (match_operand:QI 1 "general_operand" "0")))]
+ [(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 "general_operand" "0")))]
+ (neg:SF (match_operand:SF 1 "register_operand" "0")))]
"TARGET_80387"
"fchs")
(define_insn "negdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
- (neg:DF (match_operand:DF 1 "general_operand" "0")))]
+ (neg:DF (match_operand:DF 1 "register_operand" "0")))]
"TARGET_80387"
"fchs")
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f")
- (neg:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))]
+ (neg:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))]
"TARGET_80387"
"fchs")
(define_insn "negxf2"
[(set (match_operand:XF 0 "register_operand" "=f")
- (neg:XF (match_operand:XF 1 "general_operand" "0")))]
+ (neg:XF (match_operand:XF 1 "register_operand" "0")))]
"TARGET_80387"
"fchs")
(define_insn ""
[(set (match_operand:XF 0 "register_operand" "=f")
- (neg:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))]
+ (neg:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))]
"TARGET_80387"
"fchs")
@@ -3396,44 +4313,48 @@
(define_insn "abssf2"
[(set (match_operand:SF 0 "register_operand" "=f")
- (abs:SF (match_operand:SF 1 "general_operand" "0")))]
+ (abs:SF (match_operand:SF 1 "register_operand" "0")))]
"TARGET_80387"
- "fabs")
+ "fabs"
+ [(set_attr "type" "fpop")])
(define_insn "absdf2"
[(set (match_operand:DF 0 "register_operand" "=f")
- (abs:DF (match_operand:DF 1 "general_operand" "0")))]
+ (abs:DF (match_operand:DF 1 "register_operand" "0")))]
"TARGET_80387"
- "fabs")
+ "fabs"
+ [(set_attr "type" "fpop")])
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f")
- (abs:DF (float_extend:DF (match_operand:SF 1 "general_operand" "0"))))]
+ (abs:DF (float_extend:DF (match_operand:SF 1 "register_operand" "0"))))]
"TARGET_80387"
- "fabs")
+ "fabs"
+ [(set_attr "type" "fpop")])
(define_insn "absxf2"
[(set (match_operand:XF 0 "register_operand" "=f")
- (abs:XF (match_operand:XF 1 "general_operand" "0")))]
+ (abs:XF (match_operand:XF 1 "register_operand" "0")))]
"TARGET_80387"
- "fabs")
+ "fabs"
+ [(set_attr "type" "fpop")])
(define_insn ""
[(set (match_operand:XF 0 "register_operand" "=f")
- (abs:XF (float_extend:XF (match_operand:DF 1 "general_operand" "0"))))]
+ (abs:XF (float_extend:XF (match_operand:DF 1 "register_operand" "0"))))]
"TARGET_80387"
- "fabs")
+ "fabs"
+ [(set_attr "type" "fpop")])
(define_insn "sqrtsf2"
[(set (match_operand:SF 0 "register_operand" "=f")
- (sqrt:SF (match_operand:SF 1 "general_operand" "0")))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- && (TARGET_IEEE_FP || flag_fast_math) "
+ (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 "general_operand" "0")))]
+ (sqrt:DF (match_operand:DF 1 "register_operand" "0")))]
"! TARGET_NO_FANCY_MATH_387 && TARGET_80387
&& (TARGET_IEEE_FP || flag_fast_math) "
"fsqrt")
@@ -3441,14 +4362,13 @@
(define_insn ""
[(set (match_operand:DF 0 "register_operand" "=f")
(sqrt:DF (float_extend:DF
- (match_operand:SF 1 "general_operand" "0"))))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- && (TARGET_IEEE_FP || flag_fast_math) "
+ (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 "general_operand" "0")))]
+ (sqrt:XF (match_operand:XF 1 "register_operand" "0")))]
"! TARGET_NO_FANCY_MATH_387 && TARGET_80387
&& (TARGET_IEEE_FP || flag_fast_math) "
"fsqrt")
@@ -3456,94 +4376,84 @@
(define_insn ""
[(set (match_operand:XF 0 "register_operand" "=f")
(sqrt:XF (float_extend:XF
- (match_operand:DF 1 "general_operand" "0"))))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- && (TARGET_IEEE_FP || flag_fast_math) "
+ (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 "general_operand" "0"))))]
- "! TARGET_NO_FANCY_MATH_387 && TARGET_80387
- && (TARGET_IEEE_FP || flag_fast_math) "
+ (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
- && (TARGET_IEEE_FP || flag_fast_math) "
+ "! 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
- && (TARGET_IEEE_FP || flag_fast_math) "
+ "! 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
- && (TARGET_IEEE_FP || flag_fast_math) "
+ "! 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
- && (TARGET_IEEE_FP || flag_fast_math) "
+ "! 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
- && (TARGET_IEEE_FP || flag_fast_math) "
+ "! 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
- && (TARGET_IEEE_FP || flag_fast_math) "
+ "! 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
- && (TARGET_IEEE_FP || flag_fast_math) "
+ "! 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
- && (TARGET_IEEE_FP || flag_fast_math) "
+ "! TARGET_NO_FANCY_MATH_387 && TARGET_80387 && flag_fast_math"
"fcos")
;;- one complement instructions
(define_insn "one_cmplsi2"
- [(set (match_operand:SI 0 "general_operand" "=rm")
- (not:SI (match_operand:SI 1 "general_operand" "0")))]
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
+ (not:SI (match_operand:SI 1 "nonimmediate_operand" "0")))]
""
"not%L0 %0")
(define_insn "one_cmplhi2"
- [(set (match_operand:HI 0 "general_operand" "=rm")
- (not:HI (match_operand:HI 1 "general_operand" "0")))]
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
+ (not:HI (match_operand:HI 1 "nonimmediate_operand" "0")))]
""
"not%W0 %0")
(define_insn "one_cmplqi2"
- [(set (match_operand:QI 0 "general_operand" "=qm")
- (not:QI (match_operand:QI 1 "general_operand" "0")))]
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
+ (not:QI (match_operand:QI 1 "nonimmediate_operand" "0")))]
""
"not%B0 %0")
@@ -3565,8 +4475,7 @@
;; 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 three pairs. If the overall shift is by N bits, then the first two
-;; pairs shift by N / 2 and the last pair by N & 1.
+;; 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
@@ -3596,7 +4505,7 @@
[(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];
@@ -3631,35 +4540,29 @@
(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")))
- (clobber (match_dup 2))]
+ (match_operand:QI 2 "register_operand" "c")))]
""
"*
{
- rtx xops[4], low[1], high[1];
+ rtx xops[5], low[1], high[1];
CC_STATUS_INIT;
split_di (operands, 1, low, high);
xops[0] = operands[2];
- xops[1] = const1_rtx;
+ xops[1] = GEN_INT (32);
xops[2] = low[0];
xops[3] = high[0];
-
- output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */
+ 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 (AS3_SHIFT_DOUBLE (shld%L3,%0,%2,%3), xops);
- output_asm_insn (AS2 (sal%L2,%0,%2), xops);
-
- xops[1] = GEN_INT (7); /* shift count & 1 */
-
- output_asm_insn (AS2 (shr%B0,%1,%0), xops);
-
- 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;
}")
@@ -3668,15 +4571,15 @@
;; is smaller - use leal for now unless the shift count is 1.
(define_insn "ashlsi3"
- [(set (match_operand:SI 0 "general_operand" "=r,rm")
- (ashift:SI (match_operand:SI 1 "general_operand" "r,0")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=r,rm")
+ (ashift:SI (match_operand:SI 1 "nonimmediate_operand" "r,0")
(match_operand:SI 2 "nonmemory_operand" "M,cI")))]
""
"*
{
if (REG_P (operands[0]) && REGNO (operands[0]) != REGNO (operands[1]))
{
- if (!TARGET_386 && INTVAL (operands[2]) == 1)
+ if (TARGET_DOUBLE_WITH_ADD && INTVAL (operands[2]) == 1)
{
output_asm_insn (AS2 (mov%L0,%1,%0), operands);
return AS2 (add%L0,%1,%0);
@@ -3690,8 +4593,8 @@
output_asm_insn (AS2 (mov%L0,%1,%0), operands);
operands[1] = operands[0];
}
- operands[1] = gen_rtx (MULT, SImode, operands[1],
- GEN_INT (1 << INTVAL (operands[2])));
+ operands[1] = gen_rtx_MULT (SImode, operands[1],
+ GEN_INT (1 << INTVAL (operands[2])));
return AS2 (lea%L0,%a1,%0);
}
}
@@ -3706,8 +4609,8 @@
}")
(define_insn "ashlhi3"
- [(set (match_operand:HI 0 "general_operand" "=rm")
- (ashift:HI (match_operand:HI 1 "general_operand" "0")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
+ (ashift:HI (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:HI 2 "nonmemory_operand" "cI")))]
""
"*
@@ -3722,8 +4625,8 @@
}")
(define_insn "ashlqi3"
- [(set (match_operand:QI 0 "general_operand" "=qm")
- (ashift:QI (match_operand:QI 1 "general_operand" "0")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
+ (ashift:QI (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "cI")))]
""
"*
@@ -3759,11 +4662,36 @@
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];
@@ -3800,41 +4728,36 @@
(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")))
- (clobber (match_dup 2))]
+ (match_operand:QI 2 "register_operand" "c")))]
""
"*
{
- rtx xops[4], low[1], high[1];
+ rtx xops[5], low[1], high[1];
CC_STATUS_INIT;
split_di (operands, 1, low, high);
xops[0] = operands[2];
- xops[1] = const1_rtx;
+ xops[1] = GEN_INT (32);
xops[2] = low[0];
xops[3] = high[0];
-
- output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */
-
- output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
- output_asm_insn (AS2 (sar%L3,%0,%3), xops);
- output_asm_insn (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
- output_asm_insn (AS2 (sar%L3,%0,%3), xops);
-
- xops[1] = GEN_INT (7); /* shift count & 1 */
-
- output_asm_insn (AS2 (shr%B0,%1,%0), xops);
+ 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"
- [(set (match_operand:SI 0 "general_operand" "=rm")
- (ashiftrt:SI (match_operand:SI 1 "general_operand" "0")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
+ (ashiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "cI")))]
""
"*
@@ -3846,8 +4769,8 @@
}")
(define_insn "ashrhi3"
- [(set (match_operand:HI 0 "general_operand" "=rm")
- (ashiftrt:HI (match_operand:HI 1 "general_operand" "0")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
+ (ashiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:HI 2 "nonmemory_operand" "cI")))]
""
"*
@@ -3859,8 +4782,8 @@
}")
(define_insn "ashrqi3"
- [(set (match_operand:QI 0 "general_operand" "=qm")
- (ashiftrt:QI (match_operand:QI 1 "general_operand" "0")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
+ (ashiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "cI")))]
""
"*
@@ -3895,11 +4818,36 @@
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];
@@ -3935,41 +4883,35 @@
(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")))
- (clobber (match_dup 2))]
+ (match_operand:QI 2 "register_operand" "c")))]
""
"*
{
- rtx xops[4], low[1], high[1];
+ rtx xops[5], low[1], high[1];
CC_STATUS_INIT;
split_di (operands, 1, low, high);
xops[0] = operands[2];
- xops[1] = const1_rtx;
+ xops[1] = GEN_INT (32);
xops[2] = low[0];
xops[3] = high[0];
-
- output_asm_insn (AS2 (ror%B0,%1,%0), xops); /* shift count / 2 */
+ 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 (AS3_SHIFT_DOUBLE (shrd%L2,%0,%3,%2), xops);
- output_asm_insn (AS2 (shr%L3,%0,%3), xops);
-
- xops[1] = GEN_INT (7); /* shift count & 1 */
-
- output_asm_insn (AS2 (shr%B0,%1,%0), xops);
-
- 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 "general_operand" "=rm")
- (lshiftrt:SI (match_operand:SI 1 "general_operand" "0")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
+ (lshiftrt:SI (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "cI")))]
""
"*
@@ -3981,8 +4923,8 @@
}")
(define_insn "lshrhi3"
- [(set (match_operand:HI 0 "general_operand" "=rm")
- (lshiftrt:HI (match_operand:HI 1 "general_operand" "0")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
+ (lshiftrt:HI (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:HI 2 "nonmemory_operand" "cI")))]
""
"*
@@ -3994,8 +4936,8 @@
}")
(define_insn "lshrqi3"
- [(set (match_operand:QI 0 "general_operand" "=qm")
- (lshiftrt:QI (match_operand:QI 1 "general_operand" "0")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
+ (lshiftrt:QI (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "cI")))]
""
"*
@@ -4009,8 +4951,8 @@
;;- rotate instructions
(define_insn "rotlsi3"
- [(set (match_operand:SI 0 "general_operand" "=rm")
- (rotate:SI (match_operand:SI 1 "general_operand" "0")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
+ (rotate:SI (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "cI")))]
""
"*
@@ -4022,8 +4964,8 @@
}")
(define_insn "rotlhi3"
- [(set (match_operand:HI 0 "general_operand" "=rm")
- (rotate:HI (match_operand:HI 1 "general_operand" "0")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
+ (rotate:HI (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:HI 2 "nonmemory_operand" "cI")))]
""
"*
@@ -4035,8 +4977,8 @@
}")
(define_insn "rotlqi3"
- [(set (match_operand:QI 0 "general_operand" "=qm")
- (rotate:QI (match_operand:QI 1 "general_operand" "0")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
+ (rotate:QI (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "cI")))]
""
"*
@@ -4048,8 +4990,8 @@
}")
(define_insn "rotrsi3"
- [(set (match_operand:SI 0 "general_operand" "=rm")
- (rotatert:SI (match_operand:SI 1 "general_operand" "0")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
+ (rotatert:SI (match_operand:SI 1 "nonimmediate_operand" "0")
(match_operand:SI 2 "nonmemory_operand" "cI")))]
""
"*
@@ -4061,8 +5003,8 @@
}")
(define_insn "rotrhi3"
- [(set (match_operand:HI 0 "general_operand" "=rm")
- (rotatert:HI (match_operand:HI 1 "general_operand" "0")
+ [(set (match_operand:HI 0 "nonimmediate_operand" "=rm")
+ (rotatert:HI (match_operand:HI 1 "nonimmediate_operand" "0")
(match_operand:HI 2 "nonmemory_operand" "cI")))]
""
"*
@@ -4074,8 +5016,8 @@
}")
(define_insn "rotrqi3"
- [(set (match_operand:QI 0 "general_operand" "=qm")
- (rotatert:QI (match_operand:QI 1 "general_operand" "0")
+ [(set (match_operand:QI 0 "nonimmediate_operand" "=qm")
+ (rotatert:QI (match_operand:QI 1 "nonimmediate_operand" "0")
(match_operand:QI 2 "nonmemory_operand" "cI")))]
""
"*
@@ -4090,11 +5032,13 @@
;; 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 "general_operand" "i")
- (match_operand:SI 2 "general_operand" "i"))
- (match_operand:SI 3 "general_operand" "ri"))]
+ (match_operand:SI 1 "immediate_operand" "i")
+ (match_operand:SI 2 "immediate_operand" "i"))
+ (match_operand:SI 3 "nonmemory_operand" "ri"))]
""
"*
{
@@ -4110,7 +5054,7 @@
}
else
{
- operands[0] = gen_rtx (REG, SImode, REGNO (operands[0]));
+ 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);
@@ -4130,7 +5074,7 @@
[(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 "general_operand" "ri"))]
+ (match_operand:QI 3 "nonmemory_operand" "ri"))]
""
"
{
@@ -4143,22 +5087,6 @@
&& ! INTVAL (operands[1]) == 1)
FAIL;
}")
-
-;; ??? Are these constraints right?
-(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+&qo")
- (const_int 8)
- (const_int 8))
- (match_operand:QI 1 "general_operand" "qn"))]
- ""
- "*
-{
- if (REG_P (operands[0]))
- return AS2 (mov%B0,%1,%h0);
-
- operands[0] = adj_offsettable_operand (operands[0], 1);
- return AS2 (mov%B0,%1,%0);
-}")
*/
;; On i386, the register count for a bit operation is *not* truncated,
@@ -4173,11 +5101,11 @@
;; General bit set and clear.
(define_insn ""
- [(set (zero_extract:SI (match_operand:SI 0 "general_operand" "+rm")
+ [(set (zero_extract:SI (match_operand:SI 0 "register_operand" "+rm")
(const_int 1)
- (match_operand:SI 2 "general_operand" "r"))
+ (match_operand:SI 2 "register_operand" "r"))
(match_operand:SI 3 "const_int_operand" "n"))]
- "TARGET_386 && GET_CODE (operands[2]) != CONST_INT"
+ "TARGET_USE_BIT_TEST && GET_CODE (operands[2]) != CONST_INT"
"*
{
CC_STATUS_INIT;
@@ -4191,11 +5119,11 @@
;; Bit complement. See comments on previous pattern.
;; ??? Is this really worthwhile?
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=rm")
+ [(set (match_operand:SI 0 "nonimmediate_operand" "=rm")
(xor:SI (ashift:SI (const_int 1)
- (match_operand:SI 1 "general_operand" "r"))
- (match_operand:SI 2 "general_operand" "0")))]
- "TARGET_386 && GET_CODE (operands[1]) != CONST_INT"
+ (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;
@@ -4204,11 +5132,11 @@
}")
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=rm")
- (xor:SI (match_operand:SI 1 "general_operand" "0")
+ [(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 "general_operand" "r"))))]
- "TARGET_386 && GET_CODE (operands[2]) != CONST_INT"
+ (match_operand:SI 2 "register_operand" "r"))))]
+ "TARGET_USE_BIT_TEST && GET_CODE (operands[2]) != CONST_INT"
"*
{
CC_STATUS_INIT;
@@ -4229,7 +5157,7 @@
(define_insn ""
[(set (cc0) (zero_extract (match_operand:SI 0 "register_operand" "r")
(const_int 1)
- (match_operand:SI 1 "general_operand" "r")))]
+ (match_operand:SI 1 "register_operand" "r")))]
"GET_CODE (operands[1]) != CONST_INT"
"*
{
@@ -4272,7 +5200,7 @@
;; The CPU may access unspecified bytes around the actual target byte.
(define_insn ""
- [(set (cc0) (zero_extract (match_operand:QI 0 "general_operand" "rm")
+ [(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])"
@@ -4403,7 +5331,8 @@
""
"*
{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
+ if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
+ && ! (cc_prev_status.flags & CC_FCOMI))
return AS1 (sete,%0);
OUTPUT_JUMP (\"setg %0\", \"seta %0\", NULL_PTR);
@@ -4435,7 +5364,8 @@
""
"*
{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
+ if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
+ && ! (cc_prev_status.flags & CC_FCOMI))
return AS1 (sete,%0);
OUTPUT_JUMP (\"setl %0\", \"setb %0\", \"sets %0\");
@@ -4467,7 +5397,8 @@
""
"*
{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
+ if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
+ && ! (cc_prev_status.flags & CC_FCOMI))
return AS1 (sete,%0);
OUTPUT_JUMP (\"setge %0\", \"setae %0\", \"setns %0\");
@@ -4499,7 +5430,8 @@
""
"*
{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
+ if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
+ && ! (cc_prev_status.flags & CC_FCOMI))
return AS1 (setb,%0);
OUTPUT_JUMP (\"setle %0\", \"setbe %0\", NULL_PTR);
@@ -4553,6 +5485,14 @@
if (cc_prev_status.flags & CC_Z_IN_NOT_C)
return \"jnc %l0\";
else
+ if (cc_prev_status.flags & CC_TEST_AX)
+ {
+ operands[1] = gen_rtx_REG (SImode, 0);
+ operands[2] = GEN_INT (0x4000);
+ output_asm_insn (AS2 (testl,%2,%1), operands);
+ return AS1 (jne,%l0);
+ }
+
return \"je %l0\";
}")
@@ -4585,6 +5525,14 @@
if (cc_prev_status.flags & CC_Z_IN_NOT_C)
return \"jc %l0\";
else
+ if (cc_prev_status.flags & CC_TEST_AX)
+ {
+ operands[1] = gen_rtx_REG (SImode, 0);
+ operands[2] = GEN_INT (0x4000);
+ output_asm_insn (AS2 (testl,%2,%1), operands);
+ return AS1 (je,%l0);
+ }
+
return \"jne %l0\";
}")
@@ -4607,9 +5555,17 @@
""
"*
{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
+ if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
+ && ! (cc_prev_status.flags & CC_FCOMI))
return AS1 (je,%l0);
+ if (cc_prev_status.flags & CC_TEST_AX)
+ {
+ operands[1] = gen_rtx_REG (SImode, 0);
+ operands[2] = GEN_INT (0x4100);
+ output_asm_insn (AS2 (testl,%2,%1), operands);
+ return AS1 (je,%l0);
+ }
OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
}")
@@ -4651,9 +5607,17 @@
""
"*
{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
+ if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
+ && ! (cc_prev_status.flags & CC_FCOMI))
return AS1 (je,%l0);
+ if (cc_prev_status.flags & CC_TEST_AX)
+ {
+ operands[1] = gen_rtx_REG (SImode, 0);
+ operands[2] = GEN_INT (0x100);
+ output_asm_insn (AS2 (testl,%2,%1), operands);
+ return AS1 (jne,%l0);
+ }
OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
}")
@@ -4695,9 +5659,16 @@
""
"*
{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
+ if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
+ && ! (cc_prev_status.flags & CC_FCOMI))
return AS1 (je,%l0);
-
+ if (cc_prev_status.flags & CC_TEST_AX)
+ {
+ operands[1] = gen_rtx_REG (SImode, 0);
+ operands[2] = GEN_INT (0x100);
+ output_asm_insn (AS2 (testl,%2,%1), operands);
+ return AS1 (je,%l0);
+ }
OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
}")
@@ -4739,8 +5710,16 @@
""
"*
{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
+ if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
+ && ! (cc_prev_status.flags & CC_FCOMI))
return AS1 (jb,%l0);
+ if (cc_prev_status.flags & CC_TEST_AX)
+ {
+ operands[1] = gen_rtx_REG (SImode, 0);
+ operands[2] = GEN_INT (0x4100);
+ output_asm_insn (AS2 (testl,%2,%1), operands);
+ return AS1 (jne,%l0);
+ }
OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
}")
@@ -4778,6 +5757,13 @@
if (cc_prev_status.flags & CC_Z_IN_NOT_C)
return \"jc %l0\";
else
+ if (cc_prev_status.flags & CC_TEST_AX)
+ {
+ operands[1] = gen_rtx_REG (SImode, 0);
+ operands[2] = GEN_INT (0x4000);
+ output_asm_insn (AS2 (testl,%2,%1), operands);
+ return AS1 (je,%l0);
+ }
return \"jne %l0\";
}")
@@ -4793,6 +5779,13 @@
if (cc_prev_status.flags & CC_Z_IN_NOT_C)
return \"jnc %l0\";
else
+ if (cc_prev_status.flags & CC_TEST_AX)
+ {
+ operands[1] = gen_rtx_REG (SImode, 0);
+ operands[2] = GEN_INT (0x4000);
+ output_asm_insn (AS2 (testl,%2,%1), operands);
+ return AS1 (jne,%l0);
+ }
return \"je %l0\";
}")
@@ -4805,9 +5798,16 @@
""
"*
{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
+ if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
+ && ! (cc_prev_status.flags & CC_FCOMI))
return AS1 (jne,%l0);
-
+ if (cc_prev_status.flags & CC_TEST_AX)
+ {
+ operands[1] = gen_rtx_REG (SImode, 0);
+ operands[2] = GEN_INT (0x4100);
+ output_asm_insn (AS2 (testl,%2,%1), operands);
+ return AS1 (jne,%l0);
+ }
OUTPUT_JUMP (\"jle %l0\", \"jbe %l0\", NULL_PTR);
}")
@@ -4829,8 +5829,16 @@
""
"*
{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
+ if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
+ && ! (cc_prev_status.flags & CC_FCOMI))
return AS1 (jne,%l0);
+ if (cc_prev_status.flags & CC_TEST_AX)
+ {
+ operands[1] = gen_rtx_REG (SImode, 0);
+ operands[2] = GEN_INT (0x100);
+ output_asm_insn (AS2 (testl,%2,%1), operands);
+ return AS1 (je,%l0);
+ }
OUTPUT_JUMP (\"jge %l0\", \"jae %l0\", \"jns %l0\");
}")
@@ -4853,9 +5861,16 @@
""
"*
{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
+ if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
+ && ! (cc_prev_status.flags & CC_FCOMI))
return AS1 (jne,%l0);
-
+ if (cc_prev_status.flags & CC_TEST_AX)
+ {
+ operands[1] = gen_rtx_REG (SImode, 0);
+ operands[2] = GEN_INT (0x100);
+ output_asm_insn (AS2 (testl,%2,%1), operands);
+ return AS1 (jne,%l0);
+ }
OUTPUT_JUMP (\"jl %l0\", \"jb %l0\", \"js %l0\");
}")
@@ -4877,9 +5892,17 @@
""
"*
{
- if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387))
+ if (TARGET_IEEE_FP && (cc_prev_status.flags & CC_IN_80387)
+ && ! (cc_prev_status.flags & CC_FCOMI))
return AS1 (jae,%l0);
+ if (cc_prev_status.flags & CC_TEST_AX)
+ {
+ operands[1] = gen_rtx_REG (SImode, 0);
+ operands[2] = GEN_INT (0x4100);
+ output_asm_insn (AS2 (testl,%2,%1), operands);
+ return AS1 (je,%l0);
+ }
OUTPUT_JUMP (\"jg %l0\", \"ja %l0\", NULL_PTR);
}")
@@ -4901,7 +5924,7 @@
"jmp %l0")
(define_insn "indirect_jump"
- [(set (pc) (match_operand:SI 0 "general_operand" "rm"))]
+ [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))]
""
"*
{
@@ -4929,7 +5952,7 @@
(define_insn ""
[(set (pc)
(if_then_else (match_operator 0 "arithmetic_comparison_operator"
- [(plus:SI (match_operand:SI 1 "general_operand" "+r,m")
+ [(plus: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 "" ""))
@@ -4944,7 +5967,7 @@
if (operands[2] == constm1_rtx)
output_asm_insn (AS1 (dec%L1,%1), operands);
- else if (operands[1] == const1_rtx)
+ else if (operands[2] == const1_rtx)
output_asm_insn (AS1 (inc%L1,%1), operands);
else
@@ -4956,7 +5979,7 @@
(define_insn ""
[(set (pc)
(if_then_else (match_operator 0 "arithmetic_comparison_operator"
- [(minus:SI (match_operand:SI 1 "general_operand" "+r,m")
+ [(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 "" ""))
@@ -4980,6 +6003,110 @@
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.
@@ -4987,10 +6114,12 @@
(define_expand "casesi"
[(set (match_dup 5)
- (minus:SI (match_operand:SI 0 "general_operand" "")
+ (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 5)
+ (compare:CC (match_dup 6)
(match_operand:SI 2 "general_operand" "")))
(set (pc)
(if_then_else (gtu (cc0)
@@ -5000,14 +6129,15 @@
(parallel
[(set (pc)
(minus:SI (reg:SI 3)
- (mem:SI (plus:SI (mult:SI (match_dup 5)
+ (mem:SI (plus:SI (mult:SI (match_dup 6)
(const_int 4))
(label_ref (match_operand 3 "" ""))))))
- (clobber (match_scratch:SI 6 ""))])]
+ (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;
}")
@@ -5061,12 +6191,12 @@
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_CODE (asm_out_file);
+ ASM_OUTPUT_ALIGN (asm_out_file, i386_align_jumps);
RET;
}")
(define_insn "tablejump"
- [(set (pc) (match_operand:SI 0 "general_operand" "rm"))
+ [(set (pc) (match_operand:SI 0 "nonimmediate_operand" "rm"))
(use (label_ref (match_operand 1 "" "")))]
""
"*
@@ -5312,17 +6442,11 @@
coprocessor registers as containing a possible return value,
simply pretend the untyped call returns a complex long double
value. */
-#if 1
- /* this may be part of (set (reg: ..) (call_insn ...)), and we can't
- directly set a fp register from the call. so we revert to the
- old behavior - jlemon@netcom.com (Jonathan Lemon) */
- emit_call_insn (gen_call (operands[0], const0_rtx, NULL, const0_rtx));
-#else
+
emit_call_insn (TARGET_80387
- ? gen_call_value (gen_rtx (REG, XCmode, FIRST_FLOAT_REG),
- operands[0], const0_rtx)
+ ? gen_call_value (gen_rtx_REG (XCmode, FIRST_FLOAT_REG),
+ operands[0], const0_rtx)
: gen_call (operands[0], const0_rtx));
-#endif
for (i = 0; i < XVECLEN (operands[2], 0); i++)
{
@@ -5351,19 +6475,148 @@
;; This is only done if the function's epilogue is known to be simple.
;; See comments for simple_386_epilogue in i386.c.
-(define_insn "return"
+(define_expand "return"
[(return)]
- "simple_386_epilogue ()"
+ "ix86_can_use_return_insn_p ()"
+ "")
+
+(define_insn "return_internal"
+ [(return)]
+ "reload_completed"
+ "ret")
+
+(define_insn "return_pop_internal"
+ [(return)
+ (use (match_operand:SI 0 "const_int_operand" ""))]
+ "reload_completed"
+ "ret %0")
+
+(define_insn "nop"
+ [(const_int 0)]
+ ""
+ "nop")
+
+(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))]
+ ""
"*
{
- function_epilogue (asm_out_file, get_frame_size ());
+ rtx xops [2];
+
+ xops[0] = operands[0];
+ xops[1] = stack_pointer_rtx;
+ output_asm_insn (AS2 (sub%L1,%0,%1), xops);
RET;
}")
-(define_insn "nop"
- [(const_int 0)]
+(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))]
""
- "nop")
+ "*
+{
+ 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))]
+ ""
+ "*
+{
+ char buffer[64];
+
+ 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;
+}")
+
+(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;
+}")
+
+(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;
+}")
+
+(define_insn "leave"
+ [(const_int 2)
+ (clobber (reg:SI 6))
+ (clobber (reg:SI 7))]
+ ""
+ "leave")
+
+(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;
+}")
(define_expand "movstrsi"
[(parallel [(set (match_operand:BLK 0 "memory_operand" "")
@@ -5387,8 +6640,8 @@
operands[5] = addr0;
operands[6] = addr1;
- operands[0] = gen_rtx (MEM, BLKmode, addr0);
- operands[1] = gen_rtx (MEM, BLKmode, 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.
@@ -5433,6 +6686,73 @@
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, addr1;
+
+ 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 ""
+ [(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)
+ {
+ if (INTVAL (operands[1]) & ~0x03)
+ {
+ xops[0] = GEN_INT ((INTVAL (operands[1]) >> 2) & 0x3fffffff);
+ xops[1] = operands[4];
+
+ 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" "")
@@ -5454,8 +6774,8 @@
operands[5] = addr1;
operands[6] = addr2;
- operands[1] = gen_rtx (MEM, BLKmode, addr1);
- operands[2] = gen_rtx (MEM, BLKmode, addr2);
+ operands[1] = gen_rtx_MEM (BLKmode, addr1);
+ operands[2] = gen_rtx_MEM (BLKmode, addr2);
}")
@@ -5471,7 +6791,7 @@
;; code to handle zero-length compares.
(define_insn ""
- [(set (match_operand:SI 0 "general_operand" "=&r")
+ [(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"))
@@ -5482,7 +6802,7 @@
""
"*
{
- rtx xops[4], label;
+ rtx xops[2], label;
label = gen_label_rtx ();
@@ -5492,16 +6812,13 @@
output_asm_insn (\"je %l0\", &label);
xops[0] = operands[0];
- xops[1] = gen_rtx (MEM, QImode,
- gen_rtx (PLUS, SImode, operands[1], constm1_rtx));
- xops[2] = gen_rtx (MEM, QImode,
- gen_rtx (PLUS, SImode, operands[2], constm1_rtx));
- xops[3] = operands[3];
-
- output_asm_insn (AS2 (movz%B1%L0,%1,%0), xops);
- output_asm_insn (AS2 (movz%B2%L3,%2,%3), xops);
-
- output_asm_insn (AS2 (sub%L0,%3,%0), xops);
+ 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;
}")
@@ -5522,7 +6839,7 @@
cc_status.flags |= CC_NOT_SIGNED;
- xops[0] = gen_rtx (REG, QImode, 0);
+ xops[0] = gen_rtx_REG (QImode, 0);
xops[1] = CONST0_RTX (QImode);
output_asm_insn (\"cld\", operands);
@@ -5530,101 +6847,64 @@
return \"repz\;cmps%B2\";
}")
-(define_expand "ffssi2"
- [(set (match_dup 2)
- (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" ""))
- (const_int -1)))
- (set (match_operand:SI 0 "general_operand" "")
- (plus:SI (match_dup 2) (const_int 1)))]
- ""
- "operands[2] = gen_reg_rtx (SImode);")
-
+
;; 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_insn ""
- [(set (match_operand:SI 0 "general_operand" "=&r")
- (plus:SI (ffs:SI (match_operand:SI 1 "general_operand" "rm"))
- (const_int -1)))]
+(define_expand "ffssi2"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (ffs:SI (match_operand:SI 1 "general_operand" "")))]
""
- "*
+ "
{
- rtx xops[3];
- static int ffssi_label_number;
- char buffer[30];
+ rtx label = gen_label_rtx (), temp = gen_reg_rtx (SImode);
- xops[0] = operands[0];
- xops[1] = operands[1];
- xops[2] = constm1_rtx;
- output_asm_insn (AS2 (bsf%L0,%1,%0), xops);
-#ifdef LOCAL_LABEL_PREFIX
- sprintf (buffer, \"jnz %sLFFSSI%d\",
- LOCAL_LABEL_PREFIX, ffssi_label_number);
-#else
- sprintf (buffer, \"jnz %sLFFSSI%d\",
- \"\", ffssi_label_number);
-#endif
- output_asm_insn (buffer, xops);
- output_asm_insn (AS2 (mov%L0,%2,%0), xops);
-#ifdef LOCAL_LABEL_PREFIX
- sprintf (buffer, \"%sLFFSSI%d:\",
- LOCAL_LABEL_PREFIX, ffssi_label_number);
-#else
- sprintf (buffer, \"%sLFFSSI%d:\",
- \"\", ffssi_label_number);
-#endif
- output_asm_insn (buffer, xops);
+ 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);
- ffssi_label_number++;
- return \"\";
+ if (temp != operands[0])
+ emit_move_insn (operands[0], temp);
+ DONE;
}")
-(define_expand "ffshi2"
- [(set (match_dup 2)
- (plus:HI (ffs:HI (match_operand:HI 1 "general_operand" ""))
- (const_int -1)))
- (set (match_operand:HI 0 "general_operand" "")
- (plus:HI (match_dup 2) (const_int 1)))]
+(define_insn "ffssi_1"
+ [(set (match_operand:SI 0 "register_operand" "=r")
+ (unspec:SI [(match_operand:SI 1 "nonimmediate_operand" "rm")] 5))]
""
- "operands[2] = gen_reg_rtx (HImode);")
+ "* return AS2 (bsf%L0,%1,%0);")
-(define_insn ""
- [(set (match_operand:HI 0 "general_operand" "=&r")
- (plus:HI (ffs:HI (match_operand:SI 1 "general_operand" "rm"))
- (const_int -1)))]
+(define_expand "ffshi2"
+ [(set (match_operand:SI 0 "general_operand" "")
+ (ffs:HI (match_operand:HI 1 "general_operand" "")))]
""
- "*
+ "
{
- rtx xops[3];
- static int ffshi_label_number;
- char buffer[30];
+ rtx label = gen_label_rtx (), temp = gen_reg_rtx (HImode);
- xops[0] = operands[0];
- xops[1] = operands[1];
- xops[2] = constm1_rtx;
- output_asm_insn (AS2 (bsf%W0,%1,%0), xops);
-#ifdef LOCAL_LABEL_PREFIX
- sprintf (buffer, \"jnz %sLFFSHI%d\",
- LOCAL_LABEL_PREFIX, ffshi_label_number);
-#else
- sprintf (buffer, \"jnz %sLFFSHI%d\",
- \"\", ffshi_label_number);
-#endif
- output_asm_insn (buffer, xops);
- output_asm_insn (AS2 (mov%W0,%2,%0), xops);
-#ifdef LOCAL_LABEL_PREFIX
- sprintf (buffer, \"%sLFFSHI%d:\",
- LOCAL_LABEL_PREFIX, ffshi_label_number);
-#else
- sprintf (buffer, \"%sLFFSHI%d:\",
- \"\", ffshi_label_number);
-#endif
- output_asm_insn (buffer, xops);
+ 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);
- ffshi_label_number++;
- return \"\";
+ 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
@@ -5640,81 +6920,171 @@
[(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);")
+ "* 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")
(match_operator:DF 3 "binary_387_op"
- [(float:DF (match_operand:SI 1 "general_operand" "rm"))
- (match_operand:DF 2 "general_operand" "0")]))]
+ [(float:DF (match_operand:SI 1 "nonimmediate_operand" "rm"))
+ (match_operand:DF 2 "register_operand" "0")]))]
"TARGET_80387"
- "* return output_387_binary_op (insn, operands);")
+ "* 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 "nonimmediate_operand" "0,f")
- (match_operand:XF 2 "nonimmediate_operand" "f,0")]))]
+ [(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);")
+ "* 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")
(match_operator:XF 3 "binary_387_op"
- [(float:XF (match_operand:SI 1 "general_operand" "rm"))
- (match_operand:XF 2 "general_operand" "0")]))]
+ [(float:XF (match_operand:SI 1 "nonimmediate_operand" "rm"))
+ (match_operand:XF 2 "register_operand" "0")]))]
"TARGET_80387"
- "* return output_387_binary_op (insn, operands);")
+ "* 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 "general_operand" "fm,0"))
- (match_operand:XF 2 "general_operand" "0,f")]))]
+ [(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);")
+ "* 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")
(match_operator:XF 3 "binary_387_op"
- [(match_operand:XF 1 "general_operand" "0")
- (float:XF (match_operand:SI 2 "general_operand" "rm"))]))]
+ [(match_operand:XF 1 "register_operand" "0")
+ (float:XF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))]
"TARGET_80387"
- "* return output_387_binary_op (insn, operands);")
+ "* 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 "general_operand" "0,f")
+ [(match_operand:XF 1 "register_operand" "0,f")
(float_extend:XF
- (match_operand:SF 2 "general_operand" "fm,0"))]))]
+ (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
"TARGET_80387"
- "* return output_387_binary_op (insn, operands);")
+ "* 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 "general_operand" "fm,0"))
- (match_operand:DF 2 "general_operand" "0,f")]))]
+ [(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);")
+ "* 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")
(match_operator:DF 3 "binary_387_op"
- [(match_operand:DF 1 "general_operand" "0")
- (float:DF (match_operand:SI 2 "general_operand" "rm"))]))]
+ [(match_operand:DF 1 "register_operand" "0")
+ (float:DF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))]
"TARGET_80387"
- "* return output_387_binary_op (insn, operands);")
+ "* 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 "general_operand" "0,f")
+ [(match_operand:DF 1 "register_operand" "0,f")
(float_extend:DF
- (match_operand:SF 2 "general_operand" "fm,0"))]))]
+ (match_operand:SF 2 "nonimmediate_operand" "fm,0"))]))]
"TARGET_80387"
- "* return output_387_binary_op (insn, operands);")
+ "* 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")
@@ -5722,38 +7092,106 @@
[(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);")
+ "* 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")
(match_operator:SF 3 "binary_387_op"
- [(float:SF (match_operand:SI 1 "general_operand" "rm"))
- (match_operand:SF 2 "general_operand" "0")]))]
+ [(float:SF (match_operand:SI 1 "nonimmediate_operand" "rm"))
+ (match_operand:SF 2 "register_operand" "0")]))]
"TARGET_80387"
- "* return output_387_binary_op (insn, operands);")
+ "* 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")
(match_operator:SF 3 "binary_387_op"
- [(match_operand:SF 1 "general_operand" "0")
- (float:SF (match_operand:SI 2 "general_operand" "rm"))]))]
+ [(match_operand:SF 1 "register_operand" "0")
+ (float:SF (match_operand:SI 2 "nonimmediate_operand" "rm"))]))]
"TARGET_80387"
- "* return output_387_binary_op (insn, operands);")
+ "* 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 "register_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" "")
- (minus:SI (match_dup 5)
- (const_int 1)))]
+ (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);
@@ -5766,7 +7204,7 @@
(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 "register_operand" "a")
+ (match_operand:QI 2 "immediate_operand" "a")
(match_operand:SI 3 "immediate_operand" "i")] 0))
(clobber (match_dup 1))]
""
@@ -5780,3 +7218,601 @@
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" "=r,r")
+ (if_then_else:SI (match_operator 1 "comparison_operator"
+ [(match_operand 2 "nonimmediate_operand" "")
+ (const_int 0)])
+ (match_operand:SI 3 "nonimmediate_operand" "rm,0")
+ (match_operand:SI 4 "nonimmediate_operand" "0,rm")))]
+ "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" "=r,r")
+ (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" "rm,0")
+ (match_operand:SI 5 "nonimmediate_operand" "0,rm")))]
+ "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" "=r,r")
+ (if_then_else:HI (match_operator 1 "comparison_operator"
+ [(match_operand 2 "nonimmediate_operand" "")
+ (const_int 0)])
+ (match_operand:HI 3 "nonimmediate_operand" "rm,0")
+ (match_operand:HI 4 "nonimmediate_operand" "0,rm")))]
+ "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" "=r,r")
+ (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" "rm,0")
+ (match_operand:HI 5 "nonimmediate_operand" "0,rm")))]
+ "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" "=f,f")
+ (if_then_else:SF (match_operator 1 "comparison_operator"
+ [(match_operand 2 "nonimmediate_operand" "")
+ (const_int 0)])
+ (match_operand:SF 3 "register_operand" "f,0")
+ (match_operand:SF 4 "register_operand" "0,f")))]
+ "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" "=f,f")
+ (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" "f,0")
+ (match_operand:SF 5 "register_operand" "0,f")))]
+ "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" "=f,f")
+ (if_then_else:DF (match_operator 1 "comparison_operator"
+ [(match_operand 2 "nonimmediate_operand" "")
+ (const_int 0)])
+ (match_operand:DF 3 "register_operand" "f,0")
+ (match_operand:DF 4 "register_operand" "0,f")))]
+ "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" "=f,f")
+ (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" "f,0")
+ (match_operand:DF 5 "register_operand" "0,f")))]
+ "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" "=f,f")
+ (if_then_else:XF (match_operator 1 "comparison_operator"
+ [(match_operand 2 "nonimmediate_operand" "")
+ (const_int 0)])
+ (match_operand:XF 3 "register_operand" "f,0")
+ (match_operand:XF 4 "register_operand" "0,f")))]
+ "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" "=f,f")
+ (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" "f,0")
+ (match_operand:XF 5 "register_operand" "0,f")))]
+ "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" "=&r,&r")
+ (if_then_else:DI (match_operator 1 "comparison_operator"
+ [(match_operand 2 "nonimmediate_operand" "")
+ (const_int 0)])
+ (match_operand:DI 3 "nonimmediate_operand" "ro,0")
+ (match_operand:DI 4 "nonimmediate_operand" "0,ro")))]
+ "TARGET_CMOVE && reload_completed"
+ [(set (cc0)
+ (match_dup 2))
+ (set (match_dup 0)
+ (if_then_else:DI (match_op_dup 1 [(cc0) (const_int 0)])
+ (match_dup 3) (match_dup 4)))]
+ "")
+
+(define_split
+ [(set (match_operand:DI 0 "register_operand" "=&r,&r")
+ (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" "ro,0")
+ (match_operand:DI 5 "nonimmediate_operand" "0,ro")))]
+ "TARGET_CMOVE && reload_completed"
+ [(set (cc0) (compare (match_dup 2) (match_dup 3)))
+ (set (match_dup 0)
+ (if_then_else:DI (match_op_dup 1 [(cc0) (const_int 0)])
+ (match_dup 4) (match_dup 5)))]
+ "")
+
+(define_insn ""
+ [(set (match_operand:DI 0 "register_operand" "=&r,&r")
+ (if_then_else:DI (match_operator 1 "comparison_operator"
+ [(cc0) (const_int 0)])
+ (match_operand:DI 2 "nonimmediate_operand" "ro,0")
+ (match_operand:DI 3 "nonimmediate_operand" "0,ro")))]
+ "TARGET_CMOVE && reload_completed"
+ "* return output_int_conditional_move (which_alternative, operands);")
+
+(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);")
+
+(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;
+}")
OpenPOWER on IntegriCloud