diff options
Diffstat (limited to 'gcc/config/i386/i386.md')
-rw-r--r-- | gcc/config/i386/i386.md | 219 |
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")]) |