Home | History | Annotate | Line # | Download | only in i386
      1   1.1  mrg ;; GCC machine description for i386 synchronization instructions.
      2  1.12  mrg ;; Copyright (C) 2005-2022 Free Software Foundation, Inc.
      3   1.1  mrg ;;
      4   1.1  mrg ;; This file is part of GCC.
      5   1.1  mrg ;;
      6   1.1  mrg ;; GCC is free software; you can redistribute it and/or modify
      7   1.1  mrg ;; it under the terms of the GNU General Public License as published by
      8   1.1  mrg ;; the Free Software Foundation; either version 3, or (at your option)
      9   1.1  mrg ;; any later version.
     10   1.1  mrg ;;
     11   1.1  mrg ;; GCC is distributed in the hope that it will be useful,
     12   1.1  mrg ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
     13   1.1  mrg ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     14   1.1  mrg ;; GNU General Public License for more details.
     15   1.1  mrg ;;
     16   1.1  mrg ;; You should have received a copy of the GNU General Public License
     17   1.1  mrg ;; along with GCC; see the file COPYING3.  If not see
     18   1.1  mrg ;; <http://www.gnu.org/licenses/>.
     19   1.1  mrg 
     20   1.3  mrg (define_c_enum "unspec" [
     21   1.3  mrg   UNSPEC_LFENCE
     22   1.3  mrg   UNSPEC_SFENCE
     23   1.3  mrg   UNSPEC_MFENCE
     24   1.5  mrg 
     25   1.5  mrg   UNSPEC_FILD_ATOMIC
     26   1.5  mrg   UNSPEC_FIST_ATOMIC
     27   1.5  mrg 
     28   1.8  mrg   UNSPEC_LDX_ATOMIC
     29   1.8  mrg   UNSPEC_STX_ATOMIC
     30   1.8  mrg 
     31   1.5  mrg   ;; __atomic support
     32   1.3  mrg   UNSPEC_LDA
     33   1.3  mrg   UNSPEC_STA
     34   1.3  mrg ])
     35   1.3  mrg 
     36   1.3  mrg (define_c_enum "unspecv" [
     37   1.3  mrg   UNSPECV_CMPXCHG
     38   1.3  mrg   UNSPECV_XCHG
     39   1.3  mrg   UNSPECV_LOCK
     40   1.3  mrg ])
     41   1.3  mrg 
     42   1.3  mrg (define_expand "sse2_lfence"
     43   1.3  mrg   [(set (match_dup 0)
     44   1.3  mrg 	(unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
     45   1.3  mrg   "TARGET_SSE2"
     46   1.3  mrg {
     47   1.3  mrg   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
     48   1.3  mrg   MEM_VOLATILE_P (operands[0]) = 1;
     49   1.3  mrg })
     50   1.3  mrg 
     51   1.3  mrg (define_insn "*sse2_lfence"
     52   1.3  mrg   [(set (match_operand:BLK 0)
     53   1.3  mrg 	(unspec:BLK [(match_dup 0)] UNSPEC_LFENCE))]
     54   1.3  mrg   "TARGET_SSE2"
     55   1.3  mrg   "lfence"
     56   1.3  mrg   [(set_attr "type" "sse")
     57   1.3  mrg    (set_attr "length_address" "0")
     58   1.3  mrg    (set_attr "atom_sse_attr" "lfence")
     59   1.3  mrg    (set_attr "memory" "unknown")])
     60   1.3  mrg 
     61   1.3  mrg (define_expand "sse_sfence"
     62   1.3  mrg   [(set (match_dup 0)
     63   1.3  mrg 	(unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
     64   1.3  mrg   "TARGET_SSE || TARGET_3DNOW_A"
     65   1.3  mrg {
     66   1.3  mrg   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
     67   1.3  mrg   MEM_VOLATILE_P (operands[0]) = 1;
     68   1.3  mrg })
     69   1.3  mrg 
     70   1.3  mrg (define_insn "*sse_sfence"
     71   1.3  mrg   [(set (match_operand:BLK 0)
     72   1.3  mrg 	(unspec:BLK [(match_dup 0)] UNSPEC_SFENCE))]
     73   1.3  mrg   "TARGET_SSE || TARGET_3DNOW_A"
     74   1.3  mrg   "sfence"
     75   1.3  mrg   [(set_attr "type" "sse")
     76   1.3  mrg    (set_attr "length_address" "0")
     77   1.3  mrg    (set_attr "atom_sse_attr" "fence")
     78   1.3  mrg    (set_attr "memory" "unknown")])
     79   1.1  mrg 
     80   1.3  mrg (define_expand "sse2_mfence"
     81   1.1  mrg   [(set (match_dup 0)
     82   1.1  mrg 	(unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
     83   1.3  mrg   "TARGET_SSE2"
     84   1.1  mrg {
     85   1.1  mrg   operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
     86   1.1  mrg   MEM_VOLATILE_P (operands[0]) = 1;
     87   1.3  mrg })
     88   1.1  mrg 
     89   1.3  mrg (define_insn "mfence_sse2"
     90   1.3  mrg   [(set (match_operand:BLK 0)
     91   1.3  mrg 	(unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))]
     92   1.3  mrg   "TARGET_64BIT || TARGET_SSE2"
     93   1.3  mrg   "mfence"
     94   1.3  mrg   [(set_attr "type" "sse")
     95   1.3  mrg    (set_attr "length_address" "0")
     96   1.3  mrg    (set_attr "atom_sse_attr" "fence")
     97   1.3  mrg    (set_attr "memory" "unknown")])
     98   1.1  mrg 
     99   1.3  mrg (define_insn "mfence_nosse"
    100   1.3  mrg   [(set (match_operand:BLK 0)
    101   1.1  mrg 	(unspec:BLK [(match_dup 0)] UNSPEC_MFENCE))
    102   1.1  mrg    (clobber (reg:CC FLAGS_REG))]
    103  1.12  mrg   ""
    104  1.12  mrg {
    105  1.12  mrg   rtx mem = gen_rtx_MEM (word_mode, stack_pointer_rtx);
    106  1.12  mrg 
    107  1.12  mrg   output_asm_insn ("lock{%;} or%z0\t{$0, %0|%0, 0}", &mem);
    108  1.12  mrg   return "";
    109  1.12  mrg }
    110   1.1  mrg   [(set_attr "memory" "unknown")])
    111   1.1  mrg 
    112   1.3  mrg (define_expand "mem_thread_fence"
    113   1.3  mrg   [(match_operand:SI 0 "const_int_operand")]		;; model
    114   1.3  mrg   ""
    115   1.3  mrg {
    116   1.5  mrg   enum memmodel model = memmodel_from_int (INTVAL (operands[0]));
    117   1.3  mrg 
    118   1.3  mrg   /* Unless this is a SEQ_CST fence, the i386 memory model is strong
    119   1.3  mrg      enough not to require barriers of any kind.  */
    120   1.5  mrg   if (is_mm_seq_cst (model))
    121   1.3  mrg     {
    122   1.3  mrg       rtx (*mfence_insn)(rtx);
    123   1.3  mrg       rtx mem;
    124   1.3  mrg 
    125  1.12  mrg       if ((TARGET_64BIT || TARGET_SSE2)
    126  1.12  mrg 	  && (optimize_function_for_size_p (cfun)
    127  1.12  mrg 	      || !TARGET_AVOID_MFENCE))
    128   1.3  mrg 	mfence_insn = gen_mfence_sse2;
    129   1.3  mrg       else
    130   1.3  mrg 	mfence_insn = gen_mfence_nosse;
    131   1.3  mrg 
    132   1.3  mrg       mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
    133   1.3  mrg       MEM_VOLATILE_P (mem) = 1;
    134   1.3  mrg 
    135   1.3  mrg       emit_insn (mfence_insn (mem));
    136   1.3  mrg     }
    137   1.3  mrg   DONE;
    138   1.3  mrg })
    139   1.3  mrg 
    140   1.3  mrg ;; ??? From volume 3 section 8.1.1 Guaranteed Atomic Operations,
    141   1.3  mrg ;; Only beginning at Pentium family processors do we get any guarantee of
    142   1.3  mrg ;; atomicity in aligned 64-bit quantities.  Beginning at P6, we get a
    143   1.3  mrg ;; guarantee for 64-bit accesses that do not cross a cacheline boundary.
    144   1.3  mrg ;;
    145   1.3  mrg ;; Note that the TARGET_CMPXCHG8B test below is a stand-in for "Pentium".
    146   1.3  mrg ;;
    147   1.3  mrg ;; Importantly, *no* processor makes atomicity guarantees for larger
    148   1.3  mrg ;; accesses.  In particular, there's no way to perform an atomic TImode
    149   1.3  mrg ;; move, despite the apparent applicability of MOVDQA et al.
    150   1.3  mrg 
    151   1.3  mrg (define_mode_iterator ATOMIC
    152   1.3  mrg    [QI HI SI
    153   1.3  mrg     (DI "TARGET_64BIT || (TARGET_CMPXCHG8B && (TARGET_80387 || TARGET_SSE))")
    154   1.3  mrg    ])
    155   1.3  mrg 
    156   1.3  mrg (define_expand "atomic_load<mode>"
    157   1.5  mrg   [(set (match_operand:ATOMIC 0 "nonimmediate_operand")
    158   1.3  mrg 	(unspec:ATOMIC [(match_operand:ATOMIC 1 "memory_operand")
    159   1.3  mrg 			(match_operand:SI 2 "const_int_operand")]
    160   1.5  mrg 		       UNSPEC_LDA))]
    161   1.3  mrg   ""
    162   1.3  mrg {
    163   1.3  mrg   /* For DImode on 32-bit, we can use the FPU to perform the load.  */
    164   1.3  mrg   if (<MODE>mode == DImode && !TARGET_64BIT)
    165   1.3  mrg     emit_insn (gen_atomic_loaddi_fpu
    166   1.3  mrg 	       (operands[0], operands[1],
    167   1.3  mrg 	        assign_386_stack_local (DImode, SLOT_TEMP)));
    168   1.3  mrg   else
    169   1.5  mrg     {
    170   1.5  mrg       rtx dst = operands[0];
    171   1.5  mrg 
    172   1.5  mrg       if (MEM_P (dst))
    173   1.5  mrg 	dst = gen_reg_rtx (<MODE>mode);
    174   1.5  mrg 
    175   1.5  mrg       emit_move_insn (dst, operands[1]);
    176   1.5  mrg 
    177   1.5  mrg       /* Fix up the destination if needed.  */
    178   1.5  mrg       if (dst != operands[0])
    179   1.5  mrg 	emit_move_insn (operands[0], dst);
    180   1.5  mrg     }
    181   1.3  mrg   DONE;
    182   1.3  mrg })
    183   1.3  mrg 
    184   1.3  mrg (define_insn_and_split "atomic_loaddi_fpu"
    185   1.3  mrg   [(set (match_operand:DI 0 "nonimmediate_operand" "=x,m,?r")
    186   1.3  mrg 	(unspec:DI [(match_operand:DI 1 "memory_operand" "m,m,m")]
    187   1.5  mrg 		   UNSPEC_LDA))
    188   1.3  mrg    (clobber (match_operand:DI 2 "memory_operand" "=X,X,m"))
    189   1.3  mrg    (clobber (match_scratch:DF 3 "=X,xf,xf"))]
    190   1.3  mrg   "!TARGET_64BIT && (TARGET_80387 || TARGET_SSE)"
    191   1.3  mrg   "#"
    192   1.3  mrg   "&& reload_completed"
    193   1.3  mrg   [(const_int 0)]
    194   1.3  mrg {
    195   1.3  mrg   rtx dst = operands[0], src = operands[1];
    196   1.3  mrg   rtx mem = operands[2], tmp = operands[3];
    197   1.3  mrg 
    198   1.3  mrg   if (SSE_REG_P (dst))
    199   1.3  mrg     emit_move_insn (dst, src);
    200   1.3  mrg   else
    201   1.3  mrg     {
    202   1.3  mrg       if (MEM_P (dst))
    203   1.3  mrg 	mem = dst;
    204   1.3  mrg 
    205   1.3  mrg       if (STACK_REG_P (tmp))
    206   1.3  mrg         {
    207   1.3  mrg 	  emit_insn (gen_loaddi_via_fpu (tmp, src));
    208   1.3  mrg 	  emit_insn (gen_storedi_via_fpu (mem, tmp));
    209   1.3  mrg 	}
    210   1.3  mrg       else
    211   1.3  mrg 	{
    212   1.8  mrg 	  emit_insn (gen_loaddi_via_sse (tmp, src));
    213   1.8  mrg 	  emit_insn (gen_storedi_via_sse (mem, tmp));
    214   1.3  mrg 	}
    215   1.3  mrg 
    216   1.3  mrg       if (mem != dst)
    217   1.3  mrg 	emit_move_insn (dst, mem);
    218   1.3  mrg     }
    219   1.3  mrg   DONE;
    220   1.3  mrg })
    221   1.3  mrg 
    222   1.3  mrg (define_expand "atomic_store<mode>"
    223   1.3  mrg   [(set (match_operand:ATOMIC 0 "memory_operand")
    224   1.5  mrg 	(unspec:ATOMIC [(match_operand:ATOMIC 1 "nonimmediate_operand")
    225   1.3  mrg 			(match_operand:SI 2 "const_int_operand")]
    226   1.5  mrg 		       UNSPEC_STA))]
    227   1.3  mrg   ""
    228   1.3  mrg {
    229   1.5  mrg   enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
    230   1.3  mrg 
    231   1.3  mrg   if (<MODE>mode == DImode && !TARGET_64BIT)
    232   1.3  mrg     {
    233   1.3  mrg       /* For DImode on 32-bit, we can use the FPU to perform the store.  */
    234   1.3  mrg       /* Note that while we could perform a cmpxchg8b loop, that turns
    235   1.3  mrg 	 out to be significantly larger than this plus a barrier.  */
    236   1.3  mrg       emit_insn (gen_atomic_storedi_fpu
    237   1.3  mrg 		 (operands[0], operands[1],
    238   1.3  mrg 	          assign_386_stack_local (DImode, SLOT_TEMP)));
    239   1.3  mrg     }
    240   1.3  mrg   else
    241   1.3  mrg     {
    242   1.5  mrg       operands[1] = force_reg (<MODE>mode, operands[1]);
    243   1.5  mrg 
    244  1.11  mrg       /* For seq-cst stores, use XCHG when we lack MFENCE.  */
    245  1.11  mrg       if (is_mm_seq_cst (model)
    246  1.11  mrg 	  && (!(TARGET_64BIT || TARGET_SSE2)
    247  1.11  mrg 	      || TARGET_AVOID_MFENCE))
    248   1.3  mrg 	{
    249   1.3  mrg 	  emit_insn (gen_atomic_exchange<mode> (gen_reg_rtx (<MODE>mode),
    250   1.3  mrg 						operands[0], operands[1],
    251   1.3  mrg 						operands[2]));
    252   1.3  mrg 	  DONE;
    253   1.3  mrg 	}
    254   1.3  mrg 
    255   1.3  mrg       /* Otherwise use a store.  */
    256   1.3  mrg       emit_insn (gen_atomic_store<mode>_1 (operands[0], operands[1],
    257   1.3  mrg 					   operands[2]));
    258   1.3  mrg     }
    259   1.3  mrg   /* ... followed by an MFENCE, if required.  */
    260   1.5  mrg   if (is_mm_seq_cst (model))
    261   1.3  mrg     emit_insn (gen_mem_thread_fence (operands[2]));
    262   1.3  mrg   DONE;
    263   1.3  mrg })
    264   1.3  mrg 
    265   1.3  mrg (define_insn "atomic_store<mode>_1"
    266   1.3  mrg   [(set (match_operand:SWI 0 "memory_operand" "=m")
    267   1.3  mrg 	(unspec:SWI [(match_operand:SWI 1 "<nonmemory_operand>" "<r><i>")
    268   1.3  mrg 		     (match_operand:SI 2 "const_int_operand")]
    269   1.5  mrg 		    UNSPEC_STA))]
    270   1.3  mrg   ""
    271   1.3  mrg   "%K2mov{<imodesuffix>}\t{%1, %0|%0, %1}")
    272   1.3  mrg 
    273   1.3  mrg (define_insn_and_split "atomic_storedi_fpu"
    274   1.3  mrg   [(set (match_operand:DI 0 "memory_operand" "=m,m,m")
    275   1.5  mrg 	(unspec:DI [(match_operand:DI 1 "nonimmediate_operand" "x,m,?r")]
    276   1.5  mrg 		   UNSPEC_STA))
    277   1.3  mrg    (clobber (match_operand:DI 2 "memory_operand" "=X,X,m"))
    278   1.3  mrg    (clobber (match_scratch:DF 3 "=X,xf,xf"))]
    279   1.3  mrg   "!TARGET_64BIT && (TARGET_80387 || TARGET_SSE)"
    280   1.3  mrg   "#"
    281   1.3  mrg   "&& reload_completed"
    282   1.3  mrg   [(const_int 0)]
    283   1.3  mrg {
    284   1.3  mrg   rtx dst = operands[0], src = operands[1];
    285   1.3  mrg   rtx mem = operands[2], tmp = operands[3];
    286   1.3  mrg 
    287   1.8  mrg   if (SSE_REG_P (src))
    288   1.8  mrg     emit_move_insn (dst, src);
    289   1.8  mrg   else
    290   1.3  mrg     {
    291   1.3  mrg       if (REG_P (src))
    292   1.3  mrg 	{
    293   1.3  mrg 	  emit_move_insn (mem, src);
    294   1.3  mrg 	  src = mem;
    295   1.3  mrg 	}
    296   1.3  mrg 
    297   1.3  mrg       if (STACK_REG_P (tmp))
    298   1.3  mrg 	{
    299   1.3  mrg 	  emit_insn (gen_loaddi_via_fpu (tmp, src));
    300   1.3  mrg 	  emit_insn (gen_storedi_via_fpu (dst, tmp));
    301   1.3  mrg 	}
    302   1.3  mrg       else
    303   1.3  mrg 	{
    304   1.8  mrg 	  emit_insn (gen_loaddi_via_sse (tmp, src));
    305   1.8  mrg 	  emit_insn (gen_storedi_via_sse (dst, tmp));
    306   1.3  mrg 	}
    307   1.3  mrg     }
    308   1.3  mrg   DONE;
    309   1.3  mrg })
    310   1.3  mrg 
    311   1.3  mrg ;; ??? You'd think that we'd be able to perform this via FLOAT + FIX_TRUNC
    312   1.3  mrg ;; operations.  But the fix_trunc patterns want way more setup than we want
    313   1.3  mrg ;; to provide.  Note that the scratch is DFmode instead of XFmode in order
    314   1.3  mrg ;; to make it easy to allocate a scratch in either SSE or FP_REGs above.
    315   1.3  mrg 
    316   1.3  mrg (define_insn "loaddi_via_fpu"
    317   1.3  mrg   [(set (match_operand:DF 0 "register_operand" "=f")
    318   1.5  mrg 	(unspec:DF [(match_operand:DI 1 "memory_operand" "m")]
    319   1.5  mrg 		   UNSPEC_FILD_ATOMIC))]
    320   1.3  mrg   "TARGET_80387"
    321   1.3  mrg   "fild%Z1\t%1"
    322   1.3  mrg   [(set_attr "type" "fmov")
    323   1.3  mrg    (set_attr "mode" "DF")
    324   1.3  mrg    (set_attr "fp_int_src" "true")])
    325   1.3  mrg 
    326   1.3  mrg (define_insn "storedi_via_fpu"
    327   1.3  mrg   [(set (match_operand:DI 0 "memory_operand" "=m")
    328   1.5  mrg 	(unspec:DI [(match_operand:DF 1 "register_operand" "f")]
    329   1.5  mrg 		   UNSPEC_FIST_ATOMIC))]
    330   1.3  mrg   "TARGET_80387"
    331   1.3  mrg {
    332   1.3  mrg   gcc_assert (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != NULL_RTX);
    333   1.3  mrg 
    334   1.3  mrg   return "fistp%Z0\t%0";
    335   1.3  mrg }
    336   1.3  mrg   [(set_attr "type" "fmov")
    337   1.3  mrg    (set_attr "mode" "DI")])
    338   1.3  mrg 
    339   1.8  mrg (define_insn "loaddi_via_sse"
    340   1.8  mrg   [(set (match_operand:DF 0 "register_operand" "=x")
    341   1.8  mrg 	(unspec:DF [(match_operand:DI 1 "memory_operand" "m")]
    342   1.8  mrg 		   UNSPEC_LDX_ATOMIC))]
    343   1.8  mrg   "TARGET_SSE"
    344   1.8  mrg {
    345   1.8  mrg   if (TARGET_SSE2)
    346   1.8  mrg     return "%vmovq\t{%1, %0|%0, %1}";
    347   1.8  mrg   return "movlps\t{%1, %0|%0, %1}";
    348   1.8  mrg }
    349   1.8  mrg   [(set_attr "type" "ssemov")
    350   1.8  mrg    (set_attr "mode" "DI")])
    351   1.8  mrg 
    352   1.8  mrg (define_insn "storedi_via_sse"
    353   1.8  mrg   [(set (match_operand:DI 0 "memory_operand" "=m")
    354   1.8  mrg 	(unspec:DI [(match_operand:DF 1 "register_operand" "x")]
    355   1.8  mrg 		   UNSPEC_STX_ATOMIC))]
    356   1.8  mrg   "TARGET_SSE"
    357   1.8  mrg {
    358   1.8  mrg   if (TARGET_SSE2)
    359   1.8  mrg     return "%vmovq\t{%1, %0|%0, %1}";
    360   1.8  mrg   return "movlps\t{%1, %0|%0, %1}";
    361   1.8  mrg }
    362   1.8  mrg   [(set_attr "type" "ssemov")
    363   1.8  mrg    (set_attr "mode" "DI")])
    364   1.8  mrg 
    365   1.3  mrg (define_expand "atomic_compare_and_swap<mode>"
    366   1.3  mrg   [(match_operand:QI 0 "register_operand")	;; bool success output
    367   1.3  mrg    (match_operand:SWI124 1 "register_operand")	;; oldval output
    368   1.3  mrg    (match_operand:SWI124 2 "memory_operand")	;; memory
    369   1.3  mrg    (match_operand:SWI124 3 "register_operand")	;; expected input
    370   1.3  mrg    (match_operand:SWI124 4 "register_operand")	;; newval input
    371   1.3  mrg    (match_operand:SI 5 "const_int_operand")	;; is_weak
    372   1.3  mrg    (match_operand:SI 6 "const_int_operand")	;; success model
    373   1.3  mrg    (match_operand:SI 7 "const_int_operand")]	;; failure model
    374   1.3  mrg   "TARGET_CMPXCHG"
    375   1.3  mrg {
    376  1.12  mrg   if (TARGET_RELAX_CMPXCHG_LOOP)
    377  1.12  mrg   {
    378  1.12  mrg     ix86_expand_cmpxchg_loop (&operands[0], operands[1], operands[2],
    379  1.12  mrg 			      operands[3], operands[4], operands[6],
    380  1.12  mrg 			      false, NULL);
    381  1.12  mrg   }
    382  1.12  mrg   else
    383  1.12  mrg   {
    384  1.12  mrg     emit_insn
    385  1.12  mrg       (gen_atomic_compare_and_swap<mode>_1
    386  1.12  mrg 	(operands[1], operands[2], operands[3], operands[4], operands[6]));
    387  1.12  mrg       ix86_expand_setcc (operands[0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
    388  1.12  mrg 			const0_rtx);
    389  1.12  mrg   }
    390   1.3  mrg   DONE;
    391   1.3  mrg })
    392   1.3  mrg 
    393   1.3  mrg (define_mode_iterator CASMODE
    394   1.3  mrg   [(DI "TARGET_64BIT || TARGET_CMPXCHG8B")
    395   1.3  mrg    (TI "TARGET_64BIT && TARGET_CMPXCHG16B")])
    396   1.3  mrg (define_mode_attr CASHMODE [(DI "SI") (TI "DI")])
    397   1.3  mrg 
    398   1.3  mrg (define_expand "atomic_compare_and_swap<mode>"
    399   1.3  mrg   [(match_operand:QI 0 "register_operand")	;; bool success output
    400   1.3  mrg    (match_operand:CASMODE 1 "register_operand")	;; oldval output
    401   1.3  mrg    (match_operand:CASMODE 2 "memory_operand")	;; memory
    402   1.3  mrg    (match_operand:CASMODE 3 "register_operand")	;; expected input
    403   1.3  mrg    (match_operand:CASMODE 4 "register_operand")	;; newval input
    404   1.3  mrg    (match_operand:SI 5 "const_int_operand")	;; is_weak
    405   1.3  mrg    (match_operand:SI 6 "const_int_operand")	;; success model
    406   1.3  mrg    (match_operand:SI 7 "const_int_operand")]	;; failure model
    407   1.1  mrg   "TARGET_CMPXCHG"
    408   1.1  mrg {
    409  1.12  mrg   int doubleword = !(<MODE>mode == DImode && TARGET_64BIT);
    410  1.12  mrg   if (TARGET_RELAX_CMPXCHG_LOOP)
    411  1.12  mrg   {
    412  1.12  mrg     ix86_expand_cmpxchg_loop (&operands[0], operands[1], operands[2],
    413  1.12  mrg 			      operands[3], operands[4], operands[6],
    414  1.12  mrg 			      doubleword, NULL);
    415  1.12  mrg   }
    416   1.3  mrg   else
    417  1.12  mrg   {
    418  1.12  mrg     if (!doubleword)
    419  1.12  mrg       {
    420  1.12  mrg 	emit_insn
    421  1.12  mrg 	  (gen_atomic_compare_and_swapdi_1
    422  1.12  mrg 	   (operands[1], operands[2], operands[3], operands[4], operands[6]));
    423  1.12  mrg       }
    424  1.12  mrg     else
    425  1.12  mrg       {
    426  1.12  mrg 	machine_mode hmode = <CASHMODE>mode;
    427  1.12  mrg 
    428  1.12  mrg 	emit_insn
    429  1.12  mrg 	  (gen_atomic_compare_and_swap<mode>_doubleword
    430  1.12  mrg 	   (operands[1], operands[2], operands[3],
    431  1.12  mrg 	    gen_lowpart (hmode, operands[4]), gen_highpart (hmode, operands[4]),
    432  1.12  mrg 	    operands[6]));
    433  1.12  mrg       }
    434  1.12  mrg 
    435  1.12  mrg     ix86_expand_setcc (operands[0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
    436  1.12  mrg 		       const0_rtx);
    437  1.12  mrg   }
    438   1.3  mrg   DONE;
    439   1.1  mrg })
    440   1.1  mrg 
    441   1.5  mrg ;; For double-word compare and swap, we are obliged to play tricks with
    442   1.5  mrg ;; the input newval (op3:op4) because the Intel register numbering does
    443   1.5  mrg ;; not match the gcc register numbering, so the pair must be CX:BX.
    444   1.5  mrg 
    445   1.5  mrg (define_mode_attr doublemodesuffix [(SI "8") (DI "16")])
    446   1.5  mrg 
    447   1.5  mrg (define_insn "atomic_compare_and_swap<dwi>_doubleword"
    448   1.5  mrg   [(set (match_operand:<DWI> 0 "register_operand" "=A")
    449   1.5  mrg 	(unspec_volatile:<DWI>
    450   1.5  mrg 	  [(match_operand:<DWI> 1 "memory_operand" "+m")
    451   1.5  mrg 	   (match_operand:<DWI> 2 "register_operand" "0")
    452   1.5  mrg 	   (match_operand:DWIH 3 "register_operand" "b")
    453   1.5  mrg 	   (match_operand:DWIH 4 "register_operand" "c")
    454   1.5  mrg 	   (match_operand:SI 5 "const_int_operand")]
    455   1.5  mrg 	  UNSPECV_CMPXCHG))
    456   1.5  mrg    (set (match_dup 1)
    457   1.5  mrg 	(unspec_volatile:<DWI> [(const_int 0)] UNSPECV_CMPXCHG))
    458   1.5  mrg    (set (reg:CCZ FLAGS_REG)
    459   1.5  mrg         (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))]
    460   1.5  mrg   "TARGET_CMPXCHG<doublemodesuffix>B"
    461   1.5  mrg   "lock{%;} %K5cmpxchg<doublemodesuffix>b\t%1")
    462   1.5  mrg 
    463   1.3  mrg (define_insn "atomic_compare_and_swap<mode>_1"
    464   1.1  mrg   [(set (match_operand:SWI 0 "register_operand" "=a")
    465   1.1  mrg 	(unspec_volatile:SWI
    466   1.3  mrg 	  [(match_operand:SWI 1 "memory_operand" "+m")
    467   1.3  mrg 	   (match_operand:SWI 2 "register_operand" "0")
    468   1.3  mrg 	   (match_operand:SWI 3 "register_operand" "<r>")
    469   1.3  mrg 	   (match_operand:SI 4 "const_int_operand")]
    470   1.1  mrg 	  UNSPECV_CMPXCHG))
    471   1.3  mrg    (set (match_dup 1)
    472   1.3  mrg 	(unspec_volatile:SWI [(const_int 0)] UNSPECV_CMPXCHG))
    473   1.1  mrg    (set (reg:CCZ FLAGS_REG)
    474   1.3  mrg         (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))]
    475   1.1  mrg   "TARGET_CMPXCHG"
    476   1.3  mrg   "lock{%;} %K4cmpxchg{<imodesuffix>}\t{%3, %1|%1, %3}")
    477   1.1  mrg 
    478  1.12  mrg (define_peephole2
    479  1.12  mrg   [(set (match_operand:SWI 0 "register_operand")
    480  1.12  mrg 	(match_operand:SWI 1 "general_operand"))
    481  1.12  mrg    (parallel [(set (match_dup 0)
    482  1.12  mrg 		   (unspec_volatile:SWI
    483  1.12  mrg 		     [(match_operand:SWI 2 "memory_operand")
    484  1.12  mrg 		      (match_dup 0)
    485  1.12  mrg 		      (match_operand:SWI 3 "register_operand")
    486  1.12  mrg 		      (match_operand:SI 4 "const_int_operand")]
    487  1.12  mrg 		     UNSPECV_CMPXCHG))
    488  1.12  mrg 	      (set (match_dup 2)
    489  1.12  mrg 		   (unspec_volatile:SWI [(const_int 0)] UNSPECV_CMPXCHG))
    490  1.12  mrg 	      (set (reg:CCZ FLAGS_REG)
    491  1.12  mrg 		   (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))])
    492  1.12  mrg    (set (reg:CCZ FLAGS_REG)
    493  1.12  mrg 	(compare:CCZ (match_operand:SWI 5 "register_operand")
    494  1.12  mrg 		     (match_operand:SWI 6 "general_operand")))]
    495  1.12  mrg   "(rtx_equal_p (operands[0], operands[5])
    496  1.12  mrg     && rtx_equal_p (operands[1], operands[6]))
    497  1.12  mrg    || (rtx_equal_p (operands[0], operands[6])
    498  1.12  mrg        && rtx_equal_p (operands[1], operands[5]))"
    499  1.12  mrg   [(set (match_dup 0)
    500  1.12  mrg 	(match_dup 1))
    501  1.12  mrg    (parallel [(set (match_dup 0)
    502  1.12  mrg 		   (unspec_volatile:SWI
    503  1.12  mrg 		     [(match_dup 2)
    504  1.12  mrg 		      (match_dup 0)
    505  1.12  mrg 		      (match_dup 3)
    506  1.12  mrg 		      (match_dup 4)]
    507  1.12  mrg 		     UNSPECV_CMPXCHG))
    508  1.12  mrg 	      (set (match_dup 2)
    509  1.12  mrg 		   (unspec_volatile:SWI [(const_int 0)] UNSPECV_CMPXCHG))
    510  1.12  mrg 	      (set (reg:CCZ FLAGS_REG)
    511  1.12  mrg 		   (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))])])
    512  1.12  mrg 
    513  1.12  mrg (define_peephole2
    514  1.12  mrg   [(parallel [(set (match_operand:SWI48 0 "register_operand")
    515  1.12  mrg 		   (match_operand:SWI48 1 "const_int_operand"))
    516  1.12  mrg 	      (clobber (reg:CC FLAGS_REG))])
    517  1.12  mrg    (parallel [(set (match_operand:SWI 2 "register_operand")
    518  1.12  mrg 		   (unspec_volatile:SWI
    519  1.12  mrg 		     [(match_operand:SWI 3 "memory_operand")
    520  1.12  mrg 		      (match_dup 2)
    521  1.12  mrg 		      (match_operand:SWI 4 "register_operand")
    522  1.12  mrg 		      (match_operand:SI 5 "const_int_operand")]
    523  1.12  mrg 		     UNSPECV_CMPXCHG))
    524  1.12  mrg 	      (set (match_dup 3)
    525  1.12  mrg 		   (unspec_volatile:SWI [(const_int 0)] UNSPECV_CMPXCHG))
    526  1.12  mrg 	      (set (reg:CCZ FLAGS_REG)
    527  1.12  mrg 		   (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))])
    528  1.12  mrg    (set (reg:CCZ FLAGS_REG)
    529  1.12  mrg 	(compare:CCZ (match_dup 2)
    530  1.12  mrg 		     (match_dup 1)))]
    531  1.12  mrg   "REGNO (operands[0]) == REGNO (operands[2])"
    532  1.12  mrg   [(parallel [(set (match_dup 0)
    533  1.12  mrg 		   (match_dup 1))
    534  1.12  mrg 	      (clobber (reg:CC FLAGS_REG))])
    535  1.12  mrg    (parallel [(set (match_dup 2)
    536  1.12  mrg 		   (unspec_volatile:SWI
    537  1.12  mrg 		     [(match_dup 3)
    538  1.12  mrg 		      (match_dup 2)
    539  1.12  mrg 		      (match_dup 4)
    540  1.12  mrg 		      (match_dup 5)]
    541  1.12  mrg 		     UNSPECV_CMPXCHG))
    542  1.12  mrg 	      (set (match_dup 3)
    543  1.12  mrg 		   (unspec_volatile:SWI [(const_int 0)] UNSPECV_CMPXCHG))
    544  1.12  mrg 	      (set (reg:CCZ FLAGS_REG)
    545  1.12  mrg 		   (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))])])
    546  1.12  mrg 
    547  1.12  mrg (define_expand "atomic_fetch_<logic><mode>"
    548  1.12  mrg   [(match_operand:SWI124 0 "register_operand")
    549  1.12  mrg    (any_logic:SWI124
    550  1.12  mrg     (match_operand:SWI124 1 "memory_operand")
    551  1.12  mrg     (match_operand:SWI124 2 "register_operand"))
    552  1.12  mrg    (match_operand:SI 3 "const_int_operand")]
    553  1.12  mrg   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    554  1.12  mrg {
    555  1.12  mrg   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    556  1.12  mrg 				    operands[2], <CODE>, false,
    557  1.12  mrg 				    false);
    558  1.12  mrg   DONE;
    559  1.12  mrg })
    560  1.12  mrg 
    561  1.12  mrg (define_expand "atomic_<logic>_fetch<mode>"
    562  1.12  mrg   [(match_operand:SWI124 0 "register_operand")
    563  1.12  mrg    (any_logic:SWI124
    564  1.12  mrg     (match_operand:SWI124 1 "memory_operand")
    565  1.12  mrg     (match_operand:SWI124 2 "register_operand"))
    566  1.12  mrg    (match_operand:SI 3 "const_int_operand")]
    567  1.12  mrg   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    568  1.12  mrg {
    569  1.12  mrg   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    570  1.12  mrg 				    operands[2], <CODE>, true,
    571  1.12  mrg 				    false);
    572  1.12  mrg   DONE;
    573  1.12  mrg })
    574  1.12  mrg 
    575  1.12  mrg (define_expand "atomic_fetch_nand<mode>"
    576  1.12  mrg   [(match_operand:SWI124 0 "register_operand")
    577  1.12  mrg    (match_operand:SWI124 1 "memory_operand")
    578  1.12  mrg    (match_operand:SWI124 2 "register_operand")
    579  1.12  mrg    (match_operand:SI 3 "const_int_operand")]
    580  1.12  mrg   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    581  1.12  mrg {
    582  1.12  mrg   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    583  1.12  mrg 				    operands[2], NOT, false,
    584  1.12  mrg 				    false);
    585  1.12  mrg   DONE;
    586  1.12  mrg })
    587  1.12  mrg 
    588  1.12  mrg (define_expand "atomic_nand_fetch<mode>"
    589  1.12  mrg   [(match_operand:SWI124 0 "register_operand")
    590  1.12  mrg    (match_operand:SWI124 1 "memory_operand")
    591  1.12  mrg    (match_operand:SWI124 2 "register_operand")
    592  1.12  mrg    (match_operand:SI 3 "const_int_operand")]
    593  1.12  mrg   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    594  1.12  mrg {
    595  1.12  mrg   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    596  1.12  mrg 				    operands[2], NOT, true,
    597  1.12  mrg 				    false);
    598  1.12  mrg   DONE;
    599  1.12  mrg })
    600  1.12  mrg 
    601  1.12  mrg (define_expand "atomic_fetch_<logic><mode>"
    602  1.12  mrg   [(match_operand:CASMODE 0 "register_operand")
    603  1.12  mrg    (any_logic:CASMODE
    604  1.12  mrg     (match_operand:CASMODE 1 "memory_operand")
    605  1.12  mrg     (match_operand:CASMODE 2 "register_operand"))
    606  1.12  mrg    (match_operand:SI 3 "const_int_operand")]
    607  1.12  mrg   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    608  1.12  mrg {
    609  1.12  mrg   bool doubleword = (<MODE>mode == DImode && !TARGET_64BIT)
    610  1.12  mrg 		    || (<MODE>mode == TImode);
    611  1.12  mrg   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    612  1.12  mrg 				    operands[2], <CODE>, false,
    613  1.12  mrg 				    doubleword);
    614  1.12  mrg   DONE;
    615  1.12  mrg })
    616  1.12  mrg 
    617  1.12  mrg (define_expand "atomic_<logic>_fetch<mode>"
    618  1.12  mrg   [(match_operand:CASMODE 0 "register_operand")
    619  1.12  mrg    (any_logic:CASMODE
    620  1.12  mrg     (match_operand:CASMODE 1 "memory_operand")
    621  1.12  mrg     (match_operand:CASMODE 2 "register_operand"))
    622  1.12  mrg    (match_operand:SI 3 "const_int_operand")]
    623  1.12  mrg   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    624  1.12  mrg {
    625  1.12  mrg   bool doubleword = (<MODE>mode == DImode && !TARGET_64BIT)
    626  1.12  mrg 		    || (<MODE>mode == TImode);
    627  1.12  mrg   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    628  1.12  mrg 				    operands[2], <CODE>, true,
    629  1.12  mrg 				    doubleword);
    630  1.12  mrg   DONE;
    631  1.12  mrg })
    632  1.12  mrg 
    633  1.12  mrg (define_expand "atomic_fetch_nand<mode>"
    634  1.12  mrg   [(match_operand:CASMODE 0 "register_operand")
    635  1.12  mrg    (match_operand:CASMODE 1 "memory_operand")
    636  1.12  mrg    (match_operand:CASMODE 2 "register_operand")
    637  1.12  mrg    (match_operand:SI 3 "const_int_operand")]
    638  1.12  mrg   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    639  1.12  mrg {
    640  1.12  mrg   bool doubleword = (<MODE>mode == DImode && !TARGET_64BIT)
    641  1.12  mrg 		    || (<MODE>mode == TImode);
    642  1.12  mrg   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    643  1.12  mrg 				    operands[2], NOT, false,
    644  1.12  mrg 				    doubleword);
    645  1.12  mrg   DONE;
    646  1.12  mrg })
    647  1.12  mrg 
    648  1.12  mrg (define_expand "atomic_nand_fetch<mode>"
    649  1.12  mrg   [(match_operand:CASMODE 0 "register_operand")
    650  1.12  mrg    (match_operand:CASMODE 1 "memory_operand")
    651  1.12  mrg    (match_operand:CASMODE 2 "register_operand")
    652  1.12  mrg    (match_operand:SI 3 "const_int_operand")]
    653  1.12  mrg   "TARGET_CMPXCHG && TARGET_RELAX_CMPXCHG_LOOP"
    654  1.12  mrg {
    655  1.12  mrg   bool doubleword = (<MODE>mode == DImode && !TARGET_64BIT)
    656  1.12  mrg 		    || (<MODE>mode == TImode);
    657  1.12  mrg   ix86_expand_atomic_fetch_op_loop (operands[0], operands[1],
    658  1.12  mrg 				    operands[2], NOT, true,
    659  1.12  mrg 				    doubleword);
    660  1.12  mrg   DONE;
    661  1.12  mrg })
    662  1.12  mrg 
    663  1.12  mrg 
    664   1.3  mrg ;; For operand 2 nonmemory_operand predicate is used instead of
    665   1.3  mrg ;; register_operand to allow combiner to better optimize atomic
    666   1.3  mrg ;; additions of constants.
    667   1.3  mrg (define_insn "atomic_fetch_add<mode>"
    668   1.1  mrg   [(set (match_operand:SWI 0 "register_operand" "=<r>")
    669   1.1  mrg 	(unspec_volatile:SWI
    670   1.3  mrg 	  [(match_operand:SWI 1 "memory_operand" "+m")
    671   1.3  mrg 	   (match_operand:SI 3 "const_int_operand")]		;; model
    672   1.3  mrg 	  UNSPECV_XCHG))
    673   1.1  mrg    (set (match_dup 1)
    674   1.1  mrg 	(plus:SWI (match_dup 1)
    675   1.3  mrg 		  (match_operand:SWI 2 "nonmemory_operand" "0")))
    676   1.1  mrg    (clobber (reg:CC FLAGS_REG))]
    677   1.1  mrg   "TARGET_XADD"
    678   1.3  mrg   "lock{%;} %K3xadd{<imodesuffix>}\t{%0, %1|%1, %0}")
    679   1.3  mrg 
    680   1.3  mrg ;; This peephole2 and following insn optimize
    681   1.3  mrg ;; __sync_fetch_and_add (x, -N) == N into just lock {add,sub,inc,dec}
    682   1.3  mrg ;; followed by testing of flags instead of lock xadd and comparisons.
    683   1.3  mrg (define_peephole2
    684   1.3  mrg   [(set (match_operand:SWI 0 "register_operand")
    685   1.3  mrg 	(match_operand:SWI 2 "const_int_operand"))
    686   1.3  mrg    (parallel [(set (match_dup 0)
    687   1.3  mrg 		   (unspec_volatile:SWI
    688   1.3  mrg 		     [(match_operand:SWI 1 "memory_operand")
    689   1.3  mrg 		      (match_operand:SI 4 "const_int_operand")]
    690   1.3  mrg 		     UNSPECV_XCHG))
    691   1.3  mrg 	      (set (match_dup 1)
    692   1.3  mrg 		   (plus:SWI (match_dup 1)
    693   1.3  mrg 			     (match_dup 0)))
    694   1.3  mrg 	      (clobber (reg:CC FLAGS_REG))])
    695   1.3  mrg    (set (reg:CCZ FLAGS_REG)
    696   1.3  mrg 	(compare:CCZ (match_dup 0)
    697   1.3  mrg 		     (match_operand:SWI 3 "const_int_operand")))]
    698   1.3  mrg   "peep2_reg_dead_p (3, operands[0])
    699   1.3  mrg    && (unsigned HOST_WIDE_INT) INTVAL (operands[2])
    700   1.3  mrg       == -(unsigned HOST_WIDE_INT) INTVAL (operands[3])
    701   1.3  mrg    && !reg_overlap_mentioned_p (operands[0], operands[1])"
    702   1.3  mrg   [(parallel [(set (reg:CCZ FLAGS_REG)
    703   1.3  mrg 		   (compare:CCZ
    704   1.3  mrg 		     (unspec_volatile:SWI [(match_dup 1) (match_dup 4)]
    705   1.3  mrg 					  UNSPECV_XCHG)
    706   1.3  mrg 		     (match_dup 3)))
    707   1.3  mrg 	      (set (match_dup 1)
    708   1.3  mrg 		   (plus:SWI (match_dup 1)
    709   1.3  mrg 			     (match_dup 2)))])])
    710   1.3  mrg 
    711   1.8  mrg ;; Likewise, but for the -Os special case of *mov<mode>_or.
    712   1.8  mrg (define_peephole2
    713   1.8  mrg   [(parallel [(set (match_operand:SWI 0 "register_operand")
    714   1.8  mrg 		   (match_operand:SWI 2 "constm1_operand"))
    715   1.8  mrg 	      (clobber (reg:CC FLAGS_REG))])
    716   1.8  mrg    (parallel [(set (match_dup 0)
    717   1.8  mrg 		   (unspec_volatile:SWI
    718   1.8  mrg 		     [(match_operand:SWI 1 "memory_operand")
    719   1.8  mrg 		      (match_operand:SI 4 "const_int_operand")]
    720   1.8  mrg 		     UNSPECV_XCHG))
    721   1.8  mrg 	      (set (match_dup 1)
    722   1.8  mrg 		   (plus:SWI (match_dup 1)
    723   1.8  mrg 			     (match_dup 0)))
    724   1.8  mrg 	      (clobber (reg:CC FLAGS_REG))])
    725   1.8  mrg    (set (reg:CCZ FLAGS_REG)
    726   1.8  mrg 	(compare:CCZ (match_dup 0)
    727   1.8  mrg 		     (match_operand:SWI 3 "const_int_operand")))]
    728   1.8  mrg   "peep2_reg_dead_p (3, operands[0])
    729   1.8  mrg    && (unsigned HOST_WIDE_INT) INTVAL (operands[2])
    730   1.8  mrg       == -(unsigned HOST_WIDE_INT) INTVAL (operands[3])
    731   1.8  mrg    && !reg_overlap_mentioned_p (operands[0], operands[1])"
    732   1.8  mrg   [(parallel [(set (reg:CCZ FLAGS_REG)
    733   1.8  mrg 		   (compare:CCZ
    734   1.8  mrg 		     (unspec_volatile:SWI [(match_dup 1) (match_dup 4)]
    735   1.8  mrg 					  UNSPECV_XCHG)
    736   1.8  mrg 		     (match_dup 3)))
    737   1.8  mrg 	      (set (match_dup 1)
    738   1.8  mrg 		   (plus:SWI (match_dup 1)
    739   1.8  mrg 			     (match_dup 2)))])])
    740   1.8  mrg 
    741   1.3  mrg (define_insn "*atomic_fetch_add_cmp<mode>"
    742   1.3  mrg   [(set (reg:CCZ FLAGS_REG)
    743   1.3  mrg 	(compare:CCZ
    744   1.3  mrg 	  (unspec_volatile:SWI
    745   1.3  mrg 	    [(match_operand:SWI 0 "memory_operand" "+m")
    746   1.3  mrg 	     (match_operand:SI 3 "const_int_operand")]		;; model
    747   1.3  mrg 	    UNSPECV_XCHG)
    748   1.3  mrg 	  (match_operand:SWI 2 "const_int_operand" "i")))
    749   1.3  mrg    (set (match_dup 0)
    750   1.3  mrg 	(plus:SWI (match_dup 0)
    751   1.3  mrg 		  (match_operand:SWI 1 "const_int_operand" "i")))]
    752   1.3  mrg   "(unsigned HOST_WIDE_INT) INTVAL (operands[1])
    753   1.3  mrg    == -(unsigned HOST_WIDE_INT) INTVAL (operands[2])"
    754   1.3  mrg {
    755   1.3  mrg   if (incdec_operand (operands[1], <MODE>mode))
    756   1.3  mrg     {
    757   1.3  mrg       if (operands[1] == const1_rtx)
    758   1.3  mrg 	return "lock{%;} %K3inc{<imodesuffix>}\t%0";
    759   1.3  mrg       else
    760   1.3  mrg 	{
    761   1.3  mrg 	  gcc_assert (operands[1] == constm1_rtx);
    762   1.3  mrg 	  return "lock{%;} %K3dec{<imodesuffix>}\t%0";
    763   1.3  mrg 	}
    764   1.3  mrg     }
    765   1.3  mrg 
    766   1.3  mrg   if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
    767   1.3  mrg     return "lock{%;} %K3sub{<imodesuffix>}\t{%1, %0|%0, %1}";
    768   1.3  mrg 
    769   1.3  mrg   return "lock{%;} %K3add{<imodesuffix>}\t{%1, %0|%0, %1}";
    770   1.3  mrg })
    771   1.1  mrg 
    772   1.1  mrg ;; Recall that xchg implicitly sets LOCK#, so adding it again wastes space.
    773   1.3  mrg ;; In addition, it is always a full barrier, so we can ignore the memory model.
    774   1.3  mrg (define_insn "atomic_exchange<mode>"
    775   1.3  mrg   [(set (match_operand:SWI 0 "register_operand" "=<r>")		;; output
    776   1.1  mrg 	(unspec_volatile:SWI
    777   1.3  mrg 	  [(match_operand:SWI 1 "memory_operand" "+m")		;; memory
    778   1.3  mrg 	   (match_operand:SI 3 "const_int_operand")]		;; model
    779   1.3  mrg 	  UNSPECV_XCHG))
    780   1.1  mrg    (set (match_dup 1)
    781   1.3  mrg 	(match_operand:SWI 2 "register_operand" "0"))]		;; input
    782   1.1  mrg   ""
    783   1.3  mrg   "%K3xchg{<imodesuffix>}\t{%1, %0|%0, %1}")
    784   1.1  mrg 
    785   1.3  mrg (define_insn "atomic_add<mode>"
    786   1.1  mrg   [(set (match_operand:SWI 0 "memory_operand" "+m")
    787   1.1  mrg 	(unspec_volatile:SWI
    788   1.1  mrg 	  [(plus:SWI (match_dup 0)
    789   1.3  mrg 		     (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
    790   1.3  mrg 	   (match_operand:SI 2 "const_int_operand")]		;; model
    791   1.1  mrg 	  UNSPECV_LOCK))
    792   1.1  mrg    (clobber (reg:CC FLAGS_REG))]
    793   1.1  mrg   ""
    794   1.1  mrg {
    795   1.3  mrg   if (incdec_operand (operands[1], <MODE>mode))
    796   1.1  mrg     {
    797   1.1  mrg       if (operands[1] == const1_rtx)
    798   1.3  mrg 	return "lock{%;} %K2inc{<imodesuffix>}\t%0";
    799   1.3  mrg       else
    800   1.3  mrg 	{
    801   1.3  mrg 	  gcc_assert (operands[1] == constm1_rtx);
    802   1.3  mrg 	  return "lock{%;} %K2dec{<imodesuffix>}\t%0";
    803   1.3  mrg 	}
    804   1.1  mrg     }
    805   1.1  mrg 
    806   1.3  mrg   if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
    807   1.3  mrg     return "lock{%;} %K2sub{<imodesuffix>}\t{%1, %0|%0, %1}";
    808   1.3  mrg 
    809   1.3  mrg   return "lock{%;} %K2add{<imodesuffix>}\t{%1, %0|%0, %1}";
    810   1.1  mrg })
    811   1.1  mrg 
    812   1.3  mrg (define_insn "atomic_sub<mode>"
    813   1.1  mrg   [(set (match_operand:SWI 0 "memory_operand" "+m")
    814   1.1  mrg 	(unspec_volatile:SWI
    815   1.1  mrg 	  [(minus:SWI (match_dup 0)
    816   1.3  mrg 		      (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
    817   1.3  mrg 	   (match_operand:SI 2 "const_int_operand")]		;; model
    818   1.1  mrg 	  UNSPECV_LOCK))
    819   1.1  mrg    (clobber (reg:CC FLAGS_REG))]
    820   1.1  mrg   ""
    821   1.1  mrg {
    822   1.3  mrg   if (incdec_operand (operands[1], <MODE>mode))
    823   1.1  mrg     {
    824   1.1  mrg       if (operands[1] == const1_rtx)
    825   1.3  mrg 	return "lock{%;} %K2dec{<imodesuffix>}\t%0";
    826   1.3  mrg       else
    827   1.3  mrg 	{
    828   1.3  mrg 	  gcc_assert (operands[1] == constm1_rtx);
    829   1.3  mrg 	  return "lock{%;} %K2inc{<imodesuffix>}\t%0";
    830   1.3  mrg 	}
    831   1.1  mrg     }
    832   1.1  mrg 
    833   1.3  mrg   if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
    834   1.3  mrg     return "lock{%;} %K2add{<imodesuffix>}\t{%1, %0|%0, %1}";
    835   1.3  mrg 
    836   1.3  mrg   return "lock{%;} %K2sub{<imodesuffix>}\t{%1, %0|%0, %1}";
    837   1.1  mrg })
    838   1.1  mrg 
    839   1.3  mrg (define_insn "atomic_<logic><mode>"
    840   1.1  mrg   [(set (match_operand:SWI 0 "memory_operand" "+m")
    841   1.1  mrg 	(unspec_volatile:SWI
    842   1.1  mrg 	  [(any_logic:SWI (match_dup 0)
    843   1.3  mrg 			  (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
    844   1.3  mrg 	   (match_operand:SI 2 "const_int_operand")]		;; model
    845   1.1  mrg 	  UNSPECV_LOCK))
    846   1.1  mrg    (clobber (reg:CC FLAGS_REG))]
    847   1.1  mrg   ""
    848   1.3  mrg   "lock{%;} %K2<logic>{<imodesuffix>}\t{%1, %0|%0, %1}")
    849   1.8  mrg 
    850   1.8  mrg (define_expand "atomic_bit_test_and_set<mode>"
    851   1.8  mrg   [(match_operand:SWI248 0 "register_operand")
    852   1.8  mrg    (match_operand:SWI248 1 "memory_operand")
    853   1.8  mrg    (match_operand:SWI248 2 "nonmemory_operand")
    854   1.8  mrg    (match_operand:SI 3 "const_int_operand") ;; model
    855   1.8  mrg    (match_operand:SI 4 "const_int_operand")]
    856   1.8  mrg   ""
    857   1.8  mrg {
    858   1.8  mrg   emit_insn (gen_atomic_bit_test_and_set<mode>_1 (operands[1], operands[2],
    859   1.8  mrg 						  operands[3]));
    860   1.8  mrg   rtx tem = gen_reg_rtx (QImode);
    861   1.8  mrg   ix86_expand_setcc (tem, EQ, gen_rtx_REG (CCCmode, FLAGS_REG), const0_rtx);
    862   1.8  mrg   rtx result = convert_modes (<MODE>mode, QImode, tem, 1);
    863   1.8  mrg   if (operands[4] == const0_rtx)
    864   1.8  mrg     result = expand_simple_binop (<MODE>mode, ASHIFT, result,
    865  1.11  mrg 				  operands[2], operands[0], 0, OPTAB_WIDEN);
    866   1.8  mrg   if (result != operands[0])
    867   1.8  mrg     emit_move_insn (operands[0], result);
    868   1.8  mrg   DONE;
    869   1.8  mrg })
    870   1.8  mrg 
    871   1.8  mrg (define_insn "atomic_bit_test_and_set<mode>_1"
    872   1.8  mrg   [(set (reg:CCC FLAGS_REG)
    873   1.8  mrg 	(compare:CCC
    874   1.8  mrg 	  (unspec_volatile:SWI248
    875   1.8  mrg 	    [(match_operand:SWI248 0 "memory_operand" "+m")
    876   1.8  mrg 	     (match_operand:SI 2 "const_int_operand")]		;; model
    877   1.8  mrg 	    UNSPECV_XCHG)
    878   1.8  mrg 	  (const_int 0)))
    879   1.8  mrg    (set (zero_extract:SWI248 (match_dup 0)
    880   1.8  mrg 			     (const_int 1)
    881   1.8  mrg 			     (match_operand:SWI248 1 "nonmemory_operand" "rN"))
    882   1.8  mrg 	(const_int 1))]
    883   1.8  mrg   ""
    884   1.8  mrg   "lock{%;} %K2bts{<imodesuffix>}\t{%1, %0|%0, %1}")
    885   1.8  mrg 
    886   1.8  mrg (define_expand "atomic_bit_test_and_complement<mode>"
    887   1.8  mrg   [(match_operand:SWI248 0 "register_operand")
    888   1.8  mrg    (match_operand:SWI248 1 "memory_operand")
    889   1.8  mrg    (match_operand:SWI248 2 "nonmemory_operand")
    890   1.8  mrg    (match_operand:SI 3 "const_int_operand") ;; model
    891   1.8  mrg    (match_operand:SI 4 "const_int_operand")]
    892   1.8  mrg   ""
    893   1.8  mrg {
    894   1.8  mrg   emit_insn (gen_atomic_bit_test_and_complement<mode>_1 (operands[1],
    895   1.8  mrg 							 operands[2],
    896   1.8  mrg 							 operands[3]));
    897   1.8  mrg   rtx tem = gen_reg_rtx (QImode);
    898   1.8  mrg   ix86_expand_setcc (tem, EQ, gen_rtx_REG (CCCmode, FLAGS_REG), const0_rtx);
    899   1.8  mrg   rtx result = convert_modes (<MODE>mode, QImode, tem, 1);
    900   1.8  mrg   if (operands[4] == const0_rtx)
    901   1.8  mrg     result = expand_simple_binop (<MODE>mode, ASHIFT, result,
    902  1.11  mrg 				  operands[2], operands[0], 0, OPTAB_WIDEN);
    903   1.8  mrg   if (result != operands[0])
    904   1.8  mrg     emit_move_insn (operands[0], result);
    905   1.8  mrg   DONE;
    906   1.8  mrg })
    907   1.8  mrg 
    908   1.8  mrg (define_insn "atomic_bit_test_and_complement<mode>_1"
    909   1.8  mrg   [(set (reg:CCC FLAGS_REG)
    910   1.8  mrg 	(compare:CCC
    911   1.8  mrg 	  (unspec_volatile:SWI248
    912   1.8  mrg 	    [(match_operand:SWI248 0 "memory_operand" "+m")
    913   1.8  mrg 	     (match_operand:SI 2 "const_int_operand")]		;; model
    914   1.8  mrg 	    UNSPECV_XCHG)
    915   1.8  mrg 	  (const_int 0)))
    916   1.8  mrg    (set (zero_extract:SWI248 (match_dup 0)
    917   1.8  mrg 			     (const_int 1)
    918   1.8  mrg 			     (match_operand:SWI248 1 "nonmemory_operand" "rN"))
    919   1.8  mrg 	(not:SWI248 (zero_extract:SWI248 (match_dup 0)
    920   1.8  mrg 					 (const_int 1)
    921   1.8  mrg 					 (match_dup 1))))]
    922   1.8  mrg   ""
    923   1.8  mrg   "lock{%;} %K2btc{<imodesuffix>}\t{%1, %0|%0, %1}")
    924   1.8  mrg 
    925   1.8  mrg (define_expand "atomic_bit_test_and_reset<mode>"
    926   1.8  mrg   [(match_operand:SWI248 0 "register_operand")
    927   1.8  mrg    (match_operand:SWI248 1 "memory_operand")
    928   1.8  mrg    (match_operand:SWI248 2 "nonmemory_operand")
    929   1.8  mrg    (match_operand:SI 3 "const_int_operand") ;; model
    930   1.8  mrg    (match_operand:SI 4 "const_int_operand")]
    931   1.8  mrg   ""
    932   1.8  mrg {
    933   1.8  mrg   emit_insn (gen_atomic_bit_test_and_reset<mode>_1 (operands[1], operands[2],
    934   1.8  mrg 						    operands[3]));
    935   1.8  mrg   rtx tem = gen_reg_rtx (QImode);
    936   1.8  mrg   ix86_expand_setcc (tem, EQ, gen_rtx_REG (CCCmode, FLAGS_REG), const0_rtx);
    937   1.8  mrg   rtx result = convert_modes (<MODE>mode, QImode, tem, 1);
    938   1.8  mrg   if (operands[4] == const0_rtx)
    939   1.8  mrg     result = expand_simple_binop (<MODE>mode, ASHIFT, result,
    940  1.11  mrg 				  operands[2], operands[0], 0, OPTAB_WIDEN);
    941   1.8  mrg   if (result != operands[0])
    942   1.8  mrg     emit_move_insn (operands[0], result);
    943   1.8  mrg   DONE;
    944   1.8  mrg })
    945   1.8  mrg 
    946   1.8  mrg (define_insn "atomic_bit_test_and_reset<mode>_1"
    947   1.8  mrg   [(set (reg:CCC FLAGS_REG)
    948   1.8  mrg 	(compare:CCC
    949   1.8  mrg 	  (unspec_volatile:SWI248
    950   1.8  mrg 	    [(match_operand:SWI248 0 "memory_operand" "+m")
    951   1.8  mrg 	     (match_operand:SI 2 "const_int_operand")]		;; model
    952   1.8  mrg 	    UNSPECV_XCHG)
    953   1.8  mrg 	  (const_int 0)))
    954   1.8  mrg    (set (zero_extract:SWI248 (match_dup 0)
    955   1.8  mrg 			     (const_int 1)
    956   1.8  mrg 			     (match_operand:SWI248 1 "nonmemory_operand" "rN"))
    957   1.8  mrg 	(const_int 0))]
    958   1.8  mrg   ""
    959   1.8  mrg   "lock{%;} %K2btr{<imodesuffix>}\t{%1, %0|%0, %1}")
    960  1.12  mrg 
    961  1.12  mrg (define_expand "atomic_<plusminus_mnemonic>_fetch_cmp_0<mode>"
    962  1.12  mrg   [(match_operand:QI 0 "register_operand")
    963  1.12  mrg    (plusminus:SWI (match_operand:SWI 1 "memory_operand")
    964  1.12  mrg 		  (match_operand:SWI 2 "nonmemory_operand"))
    965  1.12  mrg    (match_operand:SI 3 "const_int_operand") ;; model
    966  1.12  mrg    (match_operand:SI 4 "const_int_operand")]
    967  1.12  mrg   ""
    968  1.12  mrg {
    969  1.12  mrg   if (INTVAL (operands[4]) == GT || INTVAL (operands[4]) == LE)
    970  1.12  mrg     FAIL;
    971  1.12  mrg   emit_insn (gen_atomic_<plusminus_mnemonic>_fetch_cmp_0<mode>_1 (operands[1],
    972  1.12  mrg 								  operands[2],
    973  1.12  mrg 								  operands[3]));
    974  1.12  mrg   ix86_expand_setcc (operands[0], (enum rtx_code) INTVAL (operands[4]),
    975  1.12  mrg 		     gen_rtx_REG (CCGOCmode, FLAGS_REG), const0_rtx);
    976  1.12  mrg   DONE;
    977  1.12  mrg })
    978  1.12  mrg 
    979  1.12  mrg (define_insn "atomic_add_fetch_cmp_0<mode>_1"
    980  1.12  mrg   [(set (reg:CCGOC FLAGS_REG)
    981  1.12  mrg 	(compare:CCGOC
    982  1.12  mrg 	  (plus:SWI
    983  1.12  mrg 	    (unspec_volatile:SWI
    984  1.12  mrg 	      [(match_operand:SWI 0 "memory_operand" "+m")
    985  1.12  mrg 	       (match_operand:SI 2 "const_int_operand")]		;; model
    986  1.12  mrg 	      UNSPECV_XCHG)
    987  1.12  mrg 	    (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
    988  1.12  mrg 	  (const_int 0)))
    989  1.12  mrg    (set (match_dup 0)
    990  1.12  mrg 	(plus:SWI (match_dup 0) (match_dup 1)))]
    991  1.12  mrg   ""
    992  1.12  mrg {
    993  1.12  mrg   if (incdec_operand (operands[1], <MODE>mode))
    994  1.12  mrg     {
    995  1.12  mrg       if (operands[1] == const1_rtx)
    996  1.12  mrg 	return "lock{%;} %K2inc{<imodesuffix>}\t%0";
    997  1.12  mrg       else
    998  1.12  mrg 	return "lock{%;} %K2dec{<imodesuffix>}\t%0";
    999  1.12  mrg     }
   1000  1.12  mrg 
   1001  1.12  mrg   if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
   1002  1.12  mrg     return "lock{%;} %K2sub{<imodesuffix>}\t{%1, %0|%0, %1}";
   1003  1.12  mrg 
   1004  1.12  mrg   return "lock{%;} %K2add{<imodesuffix>}\t{%1, %0|%0, %1}";
   1005  1.12  mrg })
   1006  1.12  mrg 
   1007  1.12  mrg (define_insn "atomic_sub_fetch_cmp_0<mode>_1"
   1008  1.12  mrg   [(set (reg:CCGOC FLAGS_REG)
   1009  1.12  mrg 	(compare:CCGOC
   1010  1.12  mrg 	  (minus:SWI
   1011  1.12  mrg 	    (unspec_volatile:SWI
   1012  1.12  mrg 	      [(match_operand:SWI 0 "memory_operand" "+m")
   1013  1.12  mrg 	       (match_operand:SI 2 "const_int_operand")]		;; model
   1014  1.12  mrg 	      UNSPECV_XCHG)
   1015  1.12  mrg 	    (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
   1016  1.12  mrg 	  (const_int 0)))
   1017  1.12  mrg    (set (match_dup 0)
   1018  1.12  mrg 	(minus:SWI (match_dup 0) (match_dup 1)))]
   1019  1.12  mrg   ""
   1020  1.12  mrg {
   1021  1.12  mrg   if (incdec_operand (operands[1], <MODE>mode))
   1022  1.12  mrg     {
   1023  1.12  mrg       if (operands[1] != const1_rtx)
   1024  1.12  mrg 	return "lock{%;} %K2inc{<imodesuffix>}\t%0";
   1025  1.12  mrg       else
   1026  1.12  mrg 	return "lock{%;} %K2dec{<imodesuffix>}\t%0";
   1027  1.12  mrg     }
   1028  1.12  mrg 
   1029  1.12  mrg   if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
   1030  1.12  mrg     return "lock{%;} %K2add{<imodesuffix>}\t{%1, %0|%0, %1}";
   1031  1.12  mrg 
   1032  1.12  mrg   return "lock{%;} %K2sub{<imodesuffix>}\t{%1, %0|%0, %1}";
   1033  1.12  mrg })
   1034  1.12  mrg 
   1035  1.12  mrg (define_expand "atomic_<logic>_fetch_cmp_0<mode>"
   1036  1.12  mrg   [(match_operand:QI 0 "register_operand")
   1037  1.12  mrg    (any_logic:SWI (match_operand:SWI 1 "memory_operand")
   1038  1.12  mrg 		  (match_operand:SWI 2 "nonmemory_operand"))
   1039  1.12  mrg    (match_operand:SI 3 "const_int_operand") ;; model
   1040  1.12  mrg    (match_operand:SI 4 "const_int_operand")]
   1041  1.12  mrg   ""
   1042  1.12  mrg {
   1043  1.12  mrg   emit_insn (gen_atomic_<logic>_fetch_cmp_0<mode>_1 (operands[1], operands[2],
   1044  1.12  mrg 						     operands[3]));
   1045  1.12  mrg   ix86_expand_setcc (operands[0], (enum rtx_code) INTVAL (operands[4]),
   1046  1.12  mrg 		     gen_rtx_REG (CCNOmode, FLAGS_REG), const0_rtx);
   1047  1.12  mrg   DONE;
   1048  1.12  mrg })
   1049  1.12  mrg 
   1050  1.12  mrg (define_insn "atomic_<logic>_fetch_cmp_0<mode>_1"
   1051  1.12  mrg   [(set (reg:CCNO FLAGS_REG)
   1052  1.12  mrg 	(compare:CCNO
   1053  1.12  mrg 	  (any_logic:SWI
   1054  1.12  mrg 	    (unspec_volatile:SWI
   1055  1.12  mrg 	      [(match_operand:SWI 0 "memory_operand" "+m")
   1056  1.12  mrg 	       (match_operand:SI 2 "const_int_operand")]		;; model
   1057  1.12  mrg 	      UNSPECV_XCHG)
   1058  1.12  mrg 	    (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
   1059  1.12  mrg 	  (const_int 0)))
   1060  1.12  mrg    (set (match_dup 0)
   1061  1.12  mrg 	(any_logic:SWI (match_dup 0) (match_dup 1)))]
   1062  1.12  mrg   ""
   1063  1.12  mrg   "lock{%;} %K2<logic>{<imodesuffix>}\t{%1, %0|%0, %1}")
   1064