aboutsummaryrefslogtreecommitdiff
path: root/gcc/config/i386/i386.md
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/config/i386/i386.md')
-rw-r--r--gcc/config/i386/i386.md219
1 files changed, 176 insertions, 43 deletions
diff --git a/gcc/config/i386/i386.md b/gcc/config/i386/i386.md
index df16d5b608d..01fa3d465f9 100644
--- a/gcc/config/i386/i386.md
+++ b/gcc/config/i386/i386.md
@@ -1,5 +1,5 @@
;; GCC machine description for IA-32.
-;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000
+;; Copyright (C) 1988, 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001
;; Free Software Foundation, Inc.
;; Mostly by William Schelter.
;;
@@ -72,6 +72,7 @@
;; 10 This is a `sahf' operation.
;; 11 This is a `fstcw' operation
;; 12 This is behaviour of add when setting carry flag.
+;; 13 This is a `eh_return' placeholder.
;; For SSE/MMX support:
;; 30 This is `fix', guaranteed to be truncating.
@@ -1553,7 +1554,7 @@
(define_insn "*pushsi2_prologue"
[(set (match_operand:SI 0 "push_operand" "=<")
(match_operand:SI 1 "general_no_elim_operand" "ri*m"))
- (set (reg:SI 6) (reg:SI 6))]
+ (clobber (mem:BLK (scratch)))]
""
"push{l}\\t%1"
[(set_attr "type" "push")
@@ -1564,7 +1565,7 @@
(mem:SI (reg:SI 7)))
(set (reg:SI 7)
(plus:SI (reg:SI 7) (const_int 4)))
- (set (reg:SI 6) (reg:SI 6))]
+ (clobber (mem:BLK (scratch)))]
""
"pop{l}\\t%0"
[(set_attr "type" "pop")
@@ -3671,7 +3672,7 @@
(set_attr "mode" "SF")])
(define_insn "*truncxfsf2_2"
- [(set (match_operand:SF 0 "nonimmediate_operand" "=m")
+ [(set (match_operand:SF 0 "memory_operand" "=m")
(float_truncate:SF
(match_operand:TF 1 "register_operand" "f")))]
"TARGET_80387"
@@ -9914,9 +9915,39 @@
""
"ix86_expand_epilogue (0); DONE;")
+(define_expand "eh_return"
+ [(use (match_operand 0 "register_operand" ""))
+ (use (match_operand 1 "register_operand" ""))]
+ ""
+ "
+{
+ rtx tmp, sa = operands[0], ra = operands[1];
+
+ /* Tricky bit: we write the address of the handler to which we will
+ be returning into someone else's stack frame, one word below the
+ stack address we wish to restore. */
+ tmp = gen_rtx_PLUS (Pmode, arg_pointer_rtx, sa);
+ tmp = plus_constant (tmp, -UNITS_PER_WORD);
+ tmp = gen_rtx_MEM (Pmode, tmp);
+ emit_move_insn (tmp, ra);
+
+ emit_insn (gen_eh_return_1 (sa));
+ emit_barrier ();
+ DONE;
+}")
+
+(define_insn_and_split "eh_return_1"
+ [(unspec_volatile [(match_operand 0 "register_operand" "c")] 13)]
+ ""
+ "#"
+ "reload_completed"
+ [(const_int 1)]
+ "ix86_expand_epilogue (2); DONE;")
+
(define_insn "leave"
[(set (reg:SI 7) (reg:SI 6))
- (set (reg:SI 6) (mem:SI (pre_dec:SI (reg:SI 7))))]
+ (set (reg:SI 6) (mem:SI (pre_dec:SI (reg:SI 7))))
+ (clobber (mem:BLK (scratch)))]
""
"leave"
[(set_attr "length_immediate" "0")
@@ -10703,6 +10734,9 @@
rtx srcreg, destreg, countreg;
int align = 0;
int count = -1;
+ rtx insns;
+
+ start_sequence ();
if (GET_CODE (operands[3]) == CONST_INT)
align = INTVAL (operands[3]);
@@ -10717,7 +10751,7 @@
destreg = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
srcreg = copy_to_mode_reg (Pmode, XEXP (operands[1], 0));
- emit_insn (gen_cld());
+ emit_insn (gen_cld ());
/* When optimizing for size emit simple rep ; movsb instruction for
counts not divisible by 4. */
@@ -10766,10 +10800,13 @@
library version, since it is usually equally fast and result in
shorter code. */
if (!TARGET_INLINE_ALL_STRINGOPS && align < 4)
- FAIL;
+ {
+ end_sequence ();
+ FAIL;
+ }
if (TARGET_SINGLE_STRINGOP)
- emit_insn (gen_cld());
+ emit_insn (gen_cld ());
countreg2 = gen_reg_rtx (SImode);
countreg = copy_to_mode_reg (SImode, operands[2]);
@@ -10869,6 +10906,12 @@
LABEL_NUSES (label) = 1;
}
}
+
+ insns = get_insns ();
+ end_sequence ();
+
+ ix86_set_move_mem_attrs (insns, operands[0], operands[1], destreg, srcreg);
+ emit_insns (insns);
DONE;
}")
@@ -11039,6 +11082,9 @@
rtx destreg, zeroreg, countreg;
int align = 0;
int count = -1;
+ rtx insns;
+
+ start_sequence ();
if (GET_CODE (operands[2]) == CONST_INT)
align = INTVAL (operands[2]);
@@ -11052,7 +11098,7 @@
destreg = copy_to_mode_reg (Pmode, XEXP (operands[0], 0));
- emit_insn (gen_cld());
+ emit_insn (gen_cld ());
/* When optimizing for size emit simple rep ; movsb instruction for
counts not divisible by 4. */
@@ -11095,10 +11141,13 @@
library version, since it is usually equally fast and result in
shorter code. */
if (!TARGET_INLINE_ALL_STRINGOPS && align < 4)
- FAIL;
+ {
+ end_sequence ();
+ FAIL;
+ }
if (TARGET_SINGLE_STRINGOP)
- emit_insn (gen_cld());
+ emit_insn (gen_cld ());
countreg2 = gen_reg_rtx (SImode);
countreg = copy_to_mode_reg (SImode, operands[1]);
@@ -11192,6 +11241,13 @@
LABEL_NUSES (label) = 1;
}
}
+
+ insns = get_insns ();
+ end_sequence ();
+
+ ix86_set_move_mem_attrs (insns, operands[0], operands[0], destreg, destreg);
+ emit_insns (insns);
+
DONE;
}")
@@ -11504,6 +11560,91 @@
[(set_attr "type" "str")
(set_attr "mode" "QI")
(set_attr "prefix_rep" "1")])
+
+;; Peephole optimizations to clean up after cmpstr*. This should be
+;; handled in combine, but it is not currently up to the task.
+;; When used for their truth value, the cmpstr* expanders generate
+;; code like this:
+;;
+;; repz cmpsb
+;; seta %al
+;; setb %dl
+;; cmpb %al, %dl
+;; jcc label
+;;
+;; The intermediate three instructions are unnecessary.
+
+;; This one handles cmpstr*_nz_1...
+(define_peephole2
+ [(parallel[
+ (set (reg:CC 17)
+ (compare:CC (mem:BLK (match_operand 4 "register_operand" ""))
+ (mem:BLK (match_operand 5 "register_operand" ""))))
+ (use (match_operand 6 "register_operand" ""))
+ (use (match_operand:SI 3 "immediate_operand" ""))
+ (use (reg:SI 19))
+ (clobber (match_operand 0 "register_operand" ""))
+ (clobber (match_operand 1 "register_operand" ""))
+ (clobber (match_operand 2 "register_operand" ""))])
+ (set (match_operand:QI 7 "register_operand" "")
+ (gtu:QI (reg:CC 17) (const_int 0)))
+ (set (match_operand:QI 8 "register_operand" "")
+ (ltu:QI (reg:CC 17) (const_int 0)))
+ (set (reg 17)
+ (compare (match_dup 7) (match_dup 8)))
+ ]
+ "peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])"
+ [(parallel[
+ (set (reg:CC 17)
+ (compare:CC (mem:BLK (match_dup 4))
+ (mem:BLK (match_dup 5))))
+ (use (match_dup 6))
+ (use (match_dup 3))
+ (use (reg:SI 19))
+ (clobber (match_dup 0))
+ (clobber (match_dup 1))
+ (clobber (match_dup 2))])]
+ "")
+
+;; ...and this one handles cmpstr*_1.
+(define_peephole2
+ [(parallel[
+ (set (reg:CC 17)
+ (if_then_else:CC (ne (match_operand 6 "register_operand" "")
+ (const_int 0))
+ (compare:CC (mem:BLK (match_operand 4 "register_operand" ""))
+ (mem:BLK (match_operand 5 "register_operand" "")))
+ (const_int 0)))
+ (use (match_operand:SI 3 "immediate_operand" ""))
+ (use (reg:CC 17))
+ (use (reg:SI 19))
+ (clobber (match_operand 0 "register_operand" ""))
+ (clobber (match_operand 1 "register_operand" ""))
+ (clobber (match_operand 2 "register_operand" ""))])
+ (set (match_operand:QI 7 "register_operand" "")
+ (gtu:QI (reg:CC 17) (const_int 0)))
+ (set (match_operand:QI 8 "register_operand" "")
+ (ltu:QI (reg:CC 17) (const_int 0)))
+ (set (reg 17)
+ (compare (match_dup 7) (match_dup 8)))
+ ]
+ "peep2_reg_dead_p (4, operands[7]) && peep2_reg_dead_p (4, operands[8])"
+ [(parallel[
+ (set (reg:CC 17)
+ (if_then_else:CC (ne (match_dup 6)
+ (const_int 0))
+ (compare:CC (mem:BLK (match_dup 4))
+ (mem:BLK (match_dup 5)))
+ (const_int 0)))
+ (use (match_dup 3))
+ (use (reg:CC 17))
+ (use (reg:SI 19))
+ (clobber (match_dup 0))
+ (clobber (match_dup 1))
+ (clobber (match_dup 2))])]
+ "")
+
+
;; Conditional move instructions.
@@ -11671,9 +11812,8 @@
[(set (match_operand:SI 0 "register_operand" "=r,r")
(plus:SI (match_operand:SI 1 "register_operand" "0,r")
(match_operand:SI 2 "immediate_operand" "i,i")))
- (set (match_operand:SI 3 "register_operand" "+r,r")
- (match_dup 3))
- (clobber (reg:CC 17))]
+ (clobber (reg:CC 17))
+ (clobber (mem:BLK (scratch)))]
""
"*
{
@@ -11745,15 +11885,6 @@
DONE;
}")
-(define_expand "exception_receiver"
- [(const_int 0)]
- "flag_pic"
- "
-{
- load_pic_register ();
- DONE;
-}")
-
(define_expand "builtin_setjmp_receiver"
[(label_ref (match_operand 0 "" ""))]
"flag_pic"
@@ -11784,7 +11915,7 @@
operands[1] = gen_lowpart (SImode, operands[1]);
if (GET_CODE (operands[3]) != ASHIFT)
operands[2] = gen_lowpart (SImode, operands[2]);
- GET_MODE (operands[3]) = SImode;")
+ PUT_MODE (operands[3], SImode);")
(define_split
[(set (reg 17)
@@ -12272,23 +12403,23 @@
(define_peephole2
[(match_scratch:SI 0 "r")
(parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -4)))
- (set (reg:SI 6) (reg:SI 6))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC 17))
+ (clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_SUB_ESP_4"
[(clobber (match_dup 0))
(parallel [(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))
- (set (reg:SI 6) (reg:SI 6))])])
+ (clobber (mem:BLK (scratch)))])])
(define_peephole2
[(match_scratch:SI 0 "r")
(parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int -8)))
- (set (reg:SI 6) (reg:SI 6))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC 17))
+ (clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_SUB_ESP_8"
[(clobber (match_dup 0))
(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))
(parallel [(set (mem:SI (pre_dec:SI (reg:SI 7))) (match_dup 0))
- (set (reg:SI 6) (reg:SI 6))])])
+ (clobber (mem:BLK (scratch)))])])
;; Convert esp substractions to push.
(define_peephole2
@@ -12312,12 +12443,12 @@
(define_peephole2
[(match_scratch:SI 0 "r")
(parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))
- (set (reg:SI 6) (reg:SI 6))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC 17))
+ (clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_ADD_ESP_4"
[(parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))
- (set (reg:SI 6) (reg:SI 6))])]
+ (clobber (mem:BLK (scratch)))])]
"")
;; Two pops case is tricky, since pop causes dependency on destination register.
@@ -12326,12 +12457,12 @@
[(match_scratch:SI 0 "r")
(match_scratch:SI 1 "r")
(parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 8)))
- (set (reg:SI 6) (reg:SI 6))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC 17))
+ (clobber (mem:BLK (scratch)))])]
"optimize_size || !TARGET_ADD_ESP_8"
[(parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))
- (set (reg:SI 6) (reg:SI 6))])
+ (clobber (mem:BLK (scratch)))])
(parallel [(set (match_dup 1) (mem:SI (reg:SI 7)))
(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])]
"")
@@ -12339,12 +12470,12 @@
(define_peephole2
[(match_scratch:SI 0 "r")
(parallel [(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 8)))
- (set (reg:SI 6) (reg:SI 6))
- (clobber (reg:CC 17))])]
+ (clobber (reg:CC 17))
+ (clobber (mem:BLK (scratch)))])]
"optimize_size"
[(parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))
- (set (reg:SI 6) (reg:SI 6))])
+ (clobber (mem:BLK (scratch)))])
(parallel [(set (match_dup 0) (mem:SI (reg:SI 7)))
(set (reg:SI 7) (plus:SI (reg:SI 7) (const_int 4)))])]
"")
@@ -13892,8 +14023,9 @@
;; See logical MMX insns.
(define_insn "mmx_lshrdi3"
[(set (match_operand:DI 0 "register_operand" "=y")
- (lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yi")))]
+ (unspec:DI
+ [(lshiftrt:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "nonmemory_operand" "yi"))] 45))]
"TARGET_MMX"
"psrlq\\t{%2, %0|%0, %2}"
[(set_attr "type" "mmx")])
@@ -13917,8 +14049,9 @@
;; See logical MMX insns.
(define_insn "mmx_ashldi3"
[(set (match_operand:DI 0 "register_operand" "=y")
- (ashift:DI (match_operand:DI 1 "register_operand" "0")
- (match_operand:DI 2 "nonmemory_operand" "yi")))]
+ (unspec:DI
+ [(ashift:DI (match_operand:DI 1 "register_operand" "0")
+ (match_operand:DI 2 "nonmemory_operand" "yi"))] 45))]
"TARGET_MMX"
"psllq\\t{%2, %0|%0, %2}"
[(set_attr "type" "mmx")])