Home | History | Annotate | Line # | Download | only in i386
sync.md revision 1.11
      1   1.1  mrg ;; GCC machine description for i386 synchronization instructions.
      2  1.11  mrg ;; Copyright (C) 2005-2020 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.1  mrg   "!(TARGET_64BIT || TARGET_SSE2)"
    104   1.1  mrg   "lock{%;} or{l}\t{$0, (%%esp)|DWORD PTR [esp], 0}"
    105   1.1  mrg   [(set_attr "memory" "unknown")])
    106   1.1  mrg 
    107   1.3  mrg (define_expand "mem_thread_fence"
    108   1.3  mrg   [(match_operand:SI 0 "const_int_operand")]		;; model
    109   1.3  mrg   ""
    110   1.3  mrg {
    111   1.5  mrg   enum memmodel model = memmodel_from_int (INTVAL (operands[0]));
    112   1.3  mrg 
    113   1.3  mrg   /* Unless this is a SEQ_CST fence, the i386 memory model is strong
    114   1.3  mrg      enough not to require barriers of any kind.  */
    115   1.5  mrg   if (is_mm_seq_cst (model))
    116   1.3  mrg     {
    117   1.3  mrg       rtx (*mfence_insn)(rtx);
    118   1.3  mrg       rtx mem;
    119   1.3  mrg 
    120   1.3  mrg       if (TARGET_64BIT || TARGET_SSE2)
    121   1.3  mrg 	mfence_insn = gen_mfence_sse2;
    122   1.3  mrg       else
    123   1.3  mrg 	mfence_insn = gen_mfence_nosse;
    124   1.3  mrg 
    125   1.3  mrg       mem = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode));
    126   1.3  mrg       MEM_VOLATILE_P (mem) = 1;
    127   1.3  mrg 
    128   1.3  mrg       emit_insn (mfence_insn (mem));
    129   1.3  mrg     }
    130   1.3  mrg   DONE;
    131   1.3  mrg })
    132   1.3  mrg 
    133   1.3  mrg ;; ??? From volume 3 section 8.1.1 Guaranteed Atomic Operations,
    134   1.3  mrg ;; Only beginning at Pentium family processors do we get any guarantee of
    135   1.3  mrg ;; atomicity in aligned 64-bit quantities.  Beginning at P6, we get a
    136   1.3  mrg ;; guarantee for 64-bit accesses that do not cross a cacheline boundary.
    137   1.3  mrg ;;
    138   1.3  mrg ;; Note that the TARGET_CMPXCHG8B test below is a stand-in for "Pentium".
    139   1.3  mrg ;;
    140   1.3  mrg ;; Importantly, *no* processor makes atomicity guarantees for larger
    141   1.3  mrg ;; accesses.  In particular, there's no way to perform an atomic TImode
    142   1.3  mrg ;; move, despite the apparent applicability of MOVDQA et al.
    143   1.3  mrg 
    144   1.3  mrg (define_mode_iterator ATOMIC
    145   1.3  mrg    [QI HI SI
    146   1.3  mrg     (DI "TARGET_64BIT || (TARGET_CMPXCHG8B && (TARGET_80387 || TARGET_SSE))")
    147   1.3  mrg    ])
    148   1.3  mrg 
    149   1.3  mrg (define_expand "atomic_load<mode>"
    150   1.5  mrg   [(set (match_operand:ATOMIC 0 "nonimmediate_operand")
    151   1.3  mrg 	(unspec:ATOMIC [(match_operand:ATOMIC 1 "memory_operand")
    152   1.3  mrg 			(match_operand:SI 2 "const_int_operand")]
    153   1.5  mrg 		       UNSPEC_LDA))]
    154   1.3  mrg   ""
    155   1.3  mrg {
    156   1.3  mrg   /* For DImode on 32-bit, we can use the FPU to perform the load.  */
    157   1.3  mrg   if (<MODE>mode == DImode && !TARGET_64BIT)
    158   1.3  mrg     emit_insn (gen_atomic_loaddi_fpu
    159   1.3  mrg 	       (operands[0], operands[1],
    160   1.3  mrg 	        assign_386_stack_local (DImode, SLOT_TEMP)));
    161   1.3  mrg   else
    162   1.5  mrg     {
    163   1.5  mrg       rtx dst = operands[0];
    164   1.5  mrg 
    165   1.5  mrg       if (MEM_P (dst))
    166   1.5  mrg 	dst = gen_reg_rtx (<MODE>mode);
    167   1.5  mrg 
    168   1.5  mrg       emit_move_insn (dst, operands[1]);
    169   1.5  mrg 
    170   1.5  mrg       /* Fix up the destination if needed.  */
    171   1.5  mrg       if (dst != operands[0])
    172   1.5  mrg 	emit_move_insn (operands[0], dst);
    173   1.5  mrg     }
    174   1.3  mrg   DONE;
    175   1.3  mrg })
    176   1.3  mrg 
    177   1.3  mrg (define_insn_and_split "atomic_loaddi_fpu"
    178   1.3  mrg   [(set (match_operand:DI 0 "nonimmediate_operand" "=x,m,?r")
    179   1.3  mrg 	(unspec:DI [(match_operand:DI 1 "memory_operand" "m,m,m")]
    180   1.5  mrg 		   UNSPEC_LDA))
    181   1.3  mrg    (clobber (match_operand:DI 2 "memory_operand" "=X,X,m"))
    182   1.3  mrg    (clobber (match_scratch:DF 3 "=X,xf,xf"))]
    183   1.3  mrg   "!TARGET_64BIT && (TARGET_80387 || TARGET_SSE)"
    184   1.3  mrg   "#"
    185   1.3  mrg   "&& reload_completed"
    186   1.3  mrg   [(const_int 0)]
    187   1.3  mrg {
    188   1.3  mrg   rtx dst = operands[0], src = operands[1];
    189   1.3  mrg   rtx mem = operands[2], tmp = operands[3];
    190   1.3  mrg 
    191   1.3  mrg   if (SSE_REG_P (dst))
    192   1.3  mrg     emit_move_insn (dst, src);
    193   1.3  mrg   else
    194   1.3  mrg     {
    195   1.3  mrg       if (MEM_P (dst))
    196   1.3  mrg 	mem = dst;
    197   1.3  mrg 
    198   1.3  mrg       if (STACK_REG_P (tmp))
    199   1.3  mrg         {
    200   1.3  mrg 	  emit_insn (gen_loaddi_via_fpu (tmp, src));
    201   1.3  mrg 	  emit_insn (gen_storedi_via_fpu (mem, tmp));
    202   1.3  mrg 	}
    203   1.3  mrg       else
    204   1.3  mrg 	{
    205   1.8  mrg 	  emit_insn (gen_loaddi_via_sse (tmp, src));
    206   1.8  mrg 	  emit_insn (gen_storedi_via_sse (mem, tmp));
    207   1.3  mrg 	}
    208   1.3  mrg 
    209   1.3  mrg       if (mem != dst)
    210   1.3  mrg 	emit_move_insn (dst, mem);
    211   1.3  mrg     }
    212   1.3  mrg   DONE;
    213   1.3  mrg })
    214   1.3  mrg 
    215   1.3  mrg (define_expand "atomic_store<mode>"
    216   1.3  mrg   [(set (match_operand:ATOMIC 0 "memory_operand")
    217   1.5  mrg 	(unspec:ATOMIC [(match_operand:ATOMIC 1 "nonimmediate_operand")
    218   1.3  mrg 			(match_operand:SI 2 "const_int_operand")]
    219   1.5  mrg 		       UNSPEC_STA))]
    220   1.3  mrg   ""
    221   1.3  mrg {
    222   1.5  mrg   enum memmodel model = memmodel_from_int (INTVAL (operands[2]));
    223   1.3  mrg 
    224   1.3  mrg   if (<MODE>mode == DImode && !TARGET_64BIT)
    225   1.3  mrg     {
    226   1.3  mrg       /* For DImode on 32-bit, we can use the FPU to perform the store.  */
    227   1.3  mrg       /* Note that while we could perform a cmpxchg8b loop, that turns
    228   1.3  mrg 	 out to be significantly larger than this plus a barrier.  */
    229   1.3  mrg       emit_insn (gen_atomic_storedi_fpu
    230   1.3  mrg 		 (operands[0], operands[1],
    231   1.3  mrg 	          assign_386_stack_local (DImode, SLOT_TEMP)));
    232   1.3  mrg     }
    233   1.3  mrg   else
    234   1.3  mrg     {
    235   1.5  mrg       operands[1] = force_reg (<MODE>mode, operands[1]);
    236   1.5  mrg 
    237  1.11  mrg       /* For seq-cst stores, use XCHG when we lack MFENCE.  */
    238  1.11  mrg       if (is_mm_seq_cst (model)
    239  1.11  mrg 	  && (!(TARGET_64BIT || TARGET_SSE2)
    240  1.11  mrg 	      || TARGET_AVOID_MFENCE))
    241   1.3  mrg 	{
    242   1.3  mrg 	  emit_insn (gen_atomic_exchange<mode> (gen_reg_rtx (<MODE>mode),
    243   1.3  mrg 						operands[0], operands[1],
    244   1.3  mrg 						operands[2]));
    245   1.3  mrg 	  DONE;
    246   1.3  mrg 	}
    247   1.3  mrg 
    248   1.3  mrg       /* Otherwise use a store.  */
    249   1.3  mrg       emit_insn (gen_atomic_store<mode>_1 (operands[0], operands[1],
    250   1.3  mrg 					   operands[2]));
    251   1.3  mrg     }
    252   1.3  mrg   /* ... followed by an MFENCE, if required.  */
    253   1.5  mrg   if (is_mm_seq_cst (model))
    254   1.3  mrg     emit_insn (gen_mem_thread_fence (operands[2]));
    255   1.3  mrg   DONE;
    256   1.3  mrg })
    257   1.3  mrg 
    258   1.3  mrg (define_insn "atomic_store<mode>_1"
    259   1.3  mrg   [(set (match_operand:SWI 0 "memory_operand" "=m")
    260   1.3  mrg 	(unspec:SWI [(match_operand:SWI 1 "<nonmemory_operand>" "<r><i>")
    261   1.3  mrg 		     (match_operand:SI 2 "const_int_operand")]
    262   1.5  mrg 		    UNSPEC_STA))]
    263   1.3  mrg   ""
    264   1.3  mrg   "%K2mov{<imodesuffix>}\t{%1, %0|%0, %1}")
    265   1.3  mrg 
    266   1.3  mrg (define_insn_and_split "atomic_storedi_fpu"
    267   1.3  mrg   [(set (match_operand:DI 0 "memory_operand" "=m,m,m")
    268   1.5  mrg 	(unspec:DI [(match_operand:DI 1 "nonimmediate_operand" "x,m,?r")]
    269   1.5  mrg 		   UNSPEC_STA))
    270   1.3  mrg    (clobber (match_operand:DI 2 "memory_operand" "=X,X,m"))
    271   1.3  mrg    (clobber (match_scratch:DF 3 "=X,xf,xf"))]
    272   1.3  mrg   "!TARGET_64BIT && (TARGET_80387 || TARGET_SSE)"
    273   1.3  mrg   "#"
    274   1.3  mrg   "&& reload_completed"
    275   1.3  mrg   [(const_int 0)]
    276   1.3  mrg {
    277   1.3  mrg   rtx dst = operands[0], src = operands[1];
    278   1.3  mrg   rtx mem = operands[2], tmp = operands[3];
    279   1.3  mrg 
    280   1.8  mrg   if (SSE_REG_P (src))
    281   1.8  mrg     emit_move_insn (dst, src);
    282   1.8  mrg   else
    283   1.3  mrg     {
    284   1.3  mrg       if (REG_P (src))
    285   1.3  mrg 	{
    286   1.3  mrg 	  emit_move_insn (mem, src);
    287   1.3  mrg 	  src = mem;
    288   1.3  mrg 	}
    289   1.3  mrg 
    290   1.3  mrg       if (STACK_REG_P (tmp))
    291   1.3  mrg 	{
    292   1.3  mrg 	  emit_insn (gen_loaddi_via_fpu (tmp, src));
    293   1.3  mrg 	  emit_insn (gen_storedi_via_fpu (dst, tmp));
    294   1.3  mrg 	}
    295   1.3  mrg       else
    296   1.3  mrg 	{
    297   1.8  mrg 	  emit_insn (gen_loaddi_via_sse (tmp, src));
    298   1.8  mrg 	  emit_insn (gen_storedi_via_sse (dst, tmp));
    299   1.3  mrg 	}
    300   1.3  mrg     }
    301   1.3  mrg   DONE;
    302   1.3  mrg })
    303   1.3  mrg 
    304   1.3  mrg ;; ??? You'd think that we'd be able to perform this via FLOAT + FIX_TRUNC
    305   1.3  mrg ;; operations.  But the fix_trunc patterns want way more setup than we want
    306   1.3  mrg ;; to provide.  Note that the scratch is DFmode instead of XFmode in order
    307   1.3  mrg ;; to make it easy to allocate a scratch in either SSE or FP_REGs above.
    308   1.3  mrg 
    309   1.3  mrg (define_insn "loaddi_via_fpu"
    310   1.3  mrg   [(set (match_operand:DF 0 "register_operand" "=f")
    311   1.5  mrg 	(unspec:DF [(match_operand:DI 1 "memory_operand" "m")]
    312   1.5  mrg 		   UNSPEC_FILD_ATOMIC))]
    313   1.3  mrg   "TARGET_80387"
    314   1.3  mrg   "fild%Z1\t%1"
    315   1.3  mrg   [(set_attr "type" "fmov")
    316   1.3  mrg    (set_attr "mode" "DF")
    317   1.3  mrg    (set_attr "fp_int_src" "true")])
    318   1.3  mrg 
    319   1.3  mrg (define_insn "storedi_via_fpu"
    320   1.3  mrg   [(set (match_operand:DI 0 "memory_operand" "=m")
    321   1.5  mrg 	(unspec:DI [(match_operand:DF 1 "register_operand" "f")]
    322   1.5  mrg 		   UNSPEC_FIST_ATOMIC))]
    323   1.3  mrg   "TARGET_80387"
    324   1.3  mrg {
    325   1.3  mrg   gcc_assert (find_regno_note (insn, REG_DEAD, FIRST_STACK_REG) != NULL_RTX);
    326   1.3  mrg 
    327   1.3  mrg   return "fistp%Z0\t%0";
    328   1.3  mrg }
    329   1.3  mrg   [(set_attr "type" "fmov")
    330   1.3  mrg    (set_attr "mode" "DI")])
    331   1.3  mrg 
    332   1.8  mrg (define_insn "loaddi_via_sse"
    333   1.8  mrg   [(set (match_operand:DF 0 "register_operand" "=x")
    334   1.8  mrg 	(unspec:DF [(match_operand:DI 1 "memory_operand" "m")]
    335   1.8  mrg 		   UNSPEC_LDX_ATOMIC))]
    336   1.8  mrg   "TARGET_SSE"
    337   1.8  mrg {
    338   1.8  mrg   if (TARGET_SSE2)
    339   1.8  mrg     return "%vmovq\t{%1, %0|%0, %1}";
    340   1.8  mrg   return "movlps\t{%1, %0|%0, %1}";
    341   1.8  mrg }
    342   1.8  mrg   [(set_attr "type" "ssemov")
    343   1.8  mrg    (set_attr "mode" "DI")])
    344   1.8  mrg 
    345   1.8  mrg (define_insn "storedi_via_sse"
    346   1.8  mrg   [(set (match_operand:DI 0 "memory_operand" "=m")
    347   1.8  mrg 	(unspec:DI [(match_operand:DF 1 "register_operand" "x")]
    348   1.8  mrg 		   UNSPEC_STX_ATOMIC))]
    349   1.8  mrg   "TARGET_SSE"
    350   1.8  mrg {
    351   1.8  mrg   if (TARGET_SSE2)
    352   1.8  mrg     return "%vmovq\t{%1, %0|%0, %1}";
    353   1.8  mrg   return "movlps\t{%1, %0|%0, %1}";
    354   1.8  mrg }
    355   1.8  mrg   [(set_attr "type" "ssemov")
    356   1.8  mrg    (set_attr "mode" "DI")])
    357   1.8  mrg 
    358   1.3  mrg (define_expand "atomic_compare_and_swap<mode>"
    359   1.3  mrg   [(match_operand:QI 0 "register_operand")	;; bool success output
    360   1.3  mrg    (match_operand:SWI124 1 "register_operand")	;; oldval output
    361   1.3  mrg    (match_operand:SWI124 2 "memory_operand")	;; memory
    362   1.3  mrg    (match_operand:SWI124 3 "register_operand")	;; expected input
    363   1.3  mrg    (match_operand:SWI124 4 "register_operand")	;; newval input
    364   1.3  mrg    (match_operand:SI 5 "const_int_operand")	;; is_weak
    365   1.3  mrg    (match_operand:SI 6 "const_int_operand")	;; success model
    366   1.3  mrg    (match_operand:SI 7 "const_int_operand")]	;; failure model
    367   1.3  mrg   "TARGET_CMPXCHG"
    368   1.3  mrg {
    369   1.3  mrg   emit_insn
    370   1.3  mrg    (gen_atomic_compare_and_swap<mode>_1
    371   1.3  mrg     (operands[1], operands[2], operands[3], operands[4], operands[6]));
    372   1.3  mrg   ix86_expand_setcc (operands[0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
    373   1.3  mrg 		     const0_rtx);
    374   1.3  mrg   DONE;
    375   1.3  mrg })
    376   1.3  mrg 
    377   1.3  mrg (define_mode_iterator CASMODE
    378   1.3  mrg   [(DI "TARGET_64BIT || TARGET_CMPXCHG8B")
    379   1.3  mrg    (TI "TARGET_64BIT && TARGET_CMPXCHG16B")])
    380   1.3  mrg (define_mode_attr CASHMODE [(DI "SI") (TI "DI")])
    381   1.3  mrg 
    382   1.3  mrg (define_expand "atomic_compare_and_swap<mode>"
    383   1.3  mrg   [(match_operand:QI 0 "register_operand")	;; bool success output
    384   1.3  mrg    (match_operand:CASMODE 1 "register_operand")	;; oldval output
    385   1.3  mrg    (match_operand:CASMODE 2 "memory_operand")	;; memory
    386   1.3  mrg    (match_operand:CASMODE 3 "register_operand")	;; expected input
    387   1.3  mrg    (match_operand:CASMODE 4 "register_operand")	;; newval input
    388   1.3  mrg    (match_operand:SI 5 "const_int_operand")	;; is_weak
    389   1.3  mrg    (match_operand:SI 6 "const_int_operand")	;; success model
    390   1.3  mrg    (match_operand:SI 7 "const_int_operand")]	;; failure model
    391   1.1  mrg   "TARGET_CMPXCHG"
    392   1.1  mrg {
    393   1.3  mrg   if (<MODE>mode == DImode && TARGET_64BIT)
    394   1.3  mrg     {
    395   1.3  mrg       emit_insn
    396   1.3  mrg        (gen_atomic_compare_and_swapdi_1
    397   1.3  mrg 	(operands[1], operands[2], operands[3], operands[4], operands[6]));
    398   1.3  mrg     }
    399   1.3  mrg   else
    400   1.1  mrg     {
    401   1.5  mrg       machine_mode hmode = <CASHMODE>mode;
    402   1.3  mrg 
    403   1.3  mrg       emit_insn
    404   1.3  mrg        (gen_atomic_compare_and_swap<mode>_doubleword
    405   1.5  mrg         (operands[1], operands[2], operands[3],
    406   1.5  mrg 	 gen_lowpart (hmode, operands[4]), gen_highpart (hmode, operands[4]),
    407   1.5  mrg 	 operands[6]));
    408   1.1  mrg     }
    409   1.3  mrg 
    410   1.3  mrg   ix86_expand_setcc (operands[0], EQ, gen_rtx_REG (CCZmode, FLAGS_REG),
    411   1.3  mrg 		     const0_rtx);
    412   1.3  mrg   DONE;
    413   1.1  mrg })
    414   1.1  mrg 
    415   1.5  mrg ;; For double-word compare and swap, we are obliged to play tricks with
    416   1.5  mrg ;; the input newval (op3:op4) because the Intel register numbering does
    417   1.5  mrg ;; not match the gcc register numbering, so the pair must be CX:BX.
    418   1.5  mrg 
    419   1.5  mrg (define_mode_attr doublemodesuffix [(SI "8") (DI "16")])
    420   1.5  mrg 
    421   1.5  mrg (define_insn "atomic_compare_and_swap<dwi>_doubleword"
    422   1.5  mrg   [(set (match_operand:<DWI> 0 "register_operand" "=A")
    423   1.5  mrg 	(unspec_volatile:<DWI>
    424   1.5  mrg 	  [(match_operand:<DWI> 1 "memory_operand" "+m")
    425   1.5  mrg 	   (match_operand:<DWI> 2 "register_operand" "0")
    426   1.5  mrg 	   (match_operand:DWIH 3 "register_operand" "b")
    427   1.5  mrg 	   (match_operand:DWIH 4 "register_operand" "c")
    428   1.5  mrg 	   (match_operand:SI 5 "const_int_operand")]
    429   1.5  mrg 	  UNSPECV_CMPXCHG))
    430   1.5  mrg    (set (match_dup 1)
    431   1.5  mrg 	(unspec_volatile:<DWI> [(const_int 0)] UNSPECV_CMPXCHG))
    432   1.5  mrg    (set (reg:CCZ FLAGS_REG)
    433   1.5  mrg         (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))]
    434   1.5  mrg   "TARGET_CMPXCHG<doublemodesuffix>B"
    435   1.5  mrg   "lock{%;} %K5cmpxchg<doublemodesuffix>b\t%1")
    436   1.5  mrg 
    437   1.3  mrg (define_insn "atomic_compare_and_swap<mode>_1"
    438   1.1  mrg   [(set (match_operand:SWI 0 "register_operand" "=a")
    439   1.1  mrg 	(unspec_volatile:SWI
    440   1.3  mrg 	  [(match_operand:SWI 1 "memory_operand" "+m")
    441   1.3  mrg 	   (match_operand:SWI 2 "register_operand" "0")
    442   1.3  mrg 	   (match_operand:SWI 3 "register_operand" "<r>")
    443   1.3  mrg 	   (match_operand:SI 4 "const_int_operand")]
    444   1.1  mrg 	  UNSPECV_CMPXCHG))
    445   1.3  mrg    (set (match_dup 1)
    446   1.3  mrg 	(unspec_volatile:SWI [(const_int 0)] UNSPECV_CMPXCHG))
    447   1.1  mrg    (set (reg:CCZ FLAGS_REG)
    448   1.3  mrg         (unspec_volatile:CCZ [(const_int 0)] UNSPECV_CMPXCHG))]
    449   1.1  mrg   "TARGET_CMPXCHG"
    450   1.3  mrg   "lock{%;} %K4cmpxchg{<imodesuffix>}\t{%3, %1|%1, %3}")
    451   1.1  mrg 
    452   1.3  mrg ;; For operand 2 nonmemory_operand predicate is used instead of
    453   1.3  mrg ;; register_operand to allow combiner to better optimize atomic
    454   1.3  mrg ;; additions of constants.
    455   1.3  mrg (define_insn "atomic_fetch_add<mode>"
    456   1.1  mrg   [(set (match_operand:SWI 0 "register_operand" "=<r>")
    457   1.1  mrg 	(unspec_volatile:SWI
    458   1.3  mrg 	  [(match_operand:SWI 1 "memory_operand" "+m")
    459   1.3  mrg 	   (match_operand:SI 3 "const_int_operand")]		;; model
    460   1.3  mrg 	  UNSPECV_XCHG))
    461   1.1  mrg    (set (match_dup 1)
    462   1.1  mrg 	(plus:SWI (match_dup 1)
    463   1.3  mrg 		  (match_operand:SWI 2 "nonmemory_operand" "0")))
    464   1.1  mrg    (clobber (reg:CC FLAGS_REG))]
    465   1.1  mrg   "TARGET_XADD"
    466   1.3  mrg   "lock{%;} %K3xadd{<imodesuffix>}\t{%0, %1|%1, %0}")
    467   1.3  mrg 
    468   1.3  mrg ;; This peephole2 and following insn optimize
    469   1.3  mrg ;; __sync_fetch_and_add (x, -N) == N into just lock {add,sub,inc,dec}
    470   1.3  mrg ;; followed by testing of flags instead of lock xadd and comparisons.
    471   1.3  mrg (define_peephole2
    472   1.3  mrg   [(set (match_operand:SWI 0 "register_operand")
    473   1.3  mrg 	(match_operand:SWI 2 "const_int_operand"))
    474   1.3  mrg    (parallel [(set (match_dup 0)
    475   1.3  mrg 		   (unspec_volatile:SWI
    476   1.3  mrg 		     [(match_operand:SWI 1 "memory_operand")
    477   1.3  mrg 		      (match_operand:SI 4 "const_int_operand")]
    478   1.3  mrg 		     UNSPECV_XCHG))
    479   1.3  mrg 	      (set (match_dup 1)
    480   1.3  mrg 		   (plus:SWI (match_dup 1)
    481   1.3  mrg 			     (match_dup 0)))
    482   1.3  mrg 	      (clobber (reg:CC FLAGS_REG))])
    483   1.3  mrg    (set (reg:CCZ FLAGS_REG)
    484   1.3  mrg 	(compare:CCZ (match_dup 0)
    485   1.3  mrg 		     (match_operand:SWI 3 "const_int_operand")))]
    486   1.3  mrg   "peep2_reg_dead_p (3, operands[0])
    487   1.3  mrg    && (unsigned HOST_WIDE_INT) INTVAL (operands[2])
    488   1.3  mrg       == -(unsigned HOST_WIDE_INT) INTVAL (operands[3])
    489   1.3  mrg    && !reg_overlap_mentioned_p (operands[0], operands[1])"
    490   1.3  mrg   [(parallel [(set (reg:CCZ FLAGS_REG)
    491   1.3  mrg 		   (compare:CCZ
    492   1.3  mrg 		     (unspec_volatile:SWI [(match_dup 1) (match_dup 4)]
    493   1.3  mrg 					  UNSPECV_XCHG)
    494   1.3  mrg 		     (match_dup 3)))
    495   1.3  mrg 	      (set (match_dup 1)
    496   1.3  mrg 		   (plus:SWI (match_dup 1)
    497   1.3  mrg 			     (match_dup 2)))])])
    498   1.3  mrg 
    499   1.8  mrg ;; Likewise, but for the -Os special case of *mov<mode>_or.
    500   1.8  mrg (define_peephole2
    501   1.8  mrg   [(parallel [(set (match_operand:SWI 0 "register_operand")
    502   1.8  mrg 		   (match_operand:SWI 2 "constm1_operand"))
    503   1.8  mrg 	      (clobber (reg:CC FLAGS_REG))])
    504   1.8  mrg    (parallel [(set (match_dup 0)
    505   1.8  mrg 		   (unspec_volatile:SWI
    506   1.8  mrg 		     [(match_operand:SWI 1 "memory_operand")
    507   1.8  mrg 		      (match_operand:SI 4 "const_int_operand")]
    508   1.8  mrg 		     UNSPECV_XCHG))
    509   1.8  mrg 	      (set (match_dup 1)
    510   1.8  mrg 		   (plus:SWI (match_dup 1)
    511   1.8  mrg 			     (match_dup 0)))
    512   1.8  mrg 	      (clobber (reg:CC FLAGS_REG))])
    513   1.8  mrg    (set (reg:CCZ FLAGS_REG)
    514   1.8  mrg 	(compare:CCZ (match_dup 0)
    515   1.8  mrg 		     (match_operand:SWI 3 "const_int_operand")))]
    516   1.8  mrg   "peep2_reg_dead_p (3, operands[0])
    517   1.8  mrg    && (unsigned HOST_WIDE_INT) INTVAL (operands[2])
    518   1.8  mrg       == -(unsigned HOST_WIDE_INT) INTVAL (operands[3])
    519   1.8  mrg    && !reg_overlap_mentioned_p (operands[0], operands[1])"
    520   1.8  mrg   [(parallel [(set (reg:CCZ FLAGS_REG)
    521   1.8  mrg 		   (compare:CCZ
    522   1.8  mrg 		     (unspec_volatile:SWI [(match_dup 1) (match_dup 4)]
    523   1.8  mrg 					  UNSPECV_XCHG)
    524   1.8  mrg 		     (match_dup 3)))
    525   1.8  mrg 	      (set (match_dup 1)
    526   1.8  mrg 		   (plus:SWI (match_dup 1)
    527   1.8  mrg 			     (match_dup 2)))])])
    528   1.8  mrg 
    529   1.3  mrg (define_insn "*atomic_fetch_add_cmp<mode>"
    530   1.3  mrg   [(set (reg:CCZ FLAGS_REG)
    531   1.3  mrg 	(compare:CCZ
    532   1.3  mrg 	  (unspec_volatile:SWI
    533   1.3  mrg 	    [(match_operand:SWI 0 "memory_operand" "+m")
    534   1.3  mrg 	     (match_operand:SI 3 "const_int_operand")]		;; model
    535   1.3  mrg 	    UNSPECV_XCHG)
    536   1.3  mrg 	  (match_operand:SWI 2 "const_int_operand" "i")))
    537   1.3  mrg    (set (match_dup 0)
    538   1.3  mrg 	(plus:SWI (match_dup 0)
    539   1.3  mrg 		  (match_operand:SWI 1 "const_int_operand" "i")))]
    540   1.3  mrg   "(unsigned HOST_WIDE_INT) INTVAL (operands[1])
    541   1.3  mrg    == -(unsigned HOST_WIDE_INT) INTVAL (operands[2])"
    542   1.3  mrg {
    543   1.3  mrg   if (incdec_operand (operands[1], <MODE>mode))
    544   1.3  mrg     {
    545   1.3  mrg       if (operands[1] == const1_rtx)
    546   1.3  mrg 	return "lock{%;} %K3inc{<imodesuffix>}\t%0";
    547   1.3  mrg       else
    548   1.3  mrg 	{
    549   1.3  mrg 	  gcc_assert (operands[1] == constm1_rtx);
    550   1.3  mrg 	  return "lock{%;} %K3dec{<imodesuffix>}\t%0";
    551   1.3  mrg 	}
    552   1.3  mrg     }
    553   1.3  mrg 
    554   1.3  mrg   if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
    555   1.3  mrg     return "lock{%;} %K3sub{<imodesuffix>}\t{%1, %0|%0, %1}";
    556   1.3  mrg 
    557   1.3  mrg   return "lock{%;} %K3add{<imodesuffix>}\t{%1, %0|%0, %1}";
    558   1.3  mrg })
    559   1.1  mrg 
    560   1.1  mrg ;; Recall that xchg implicitly sets LOCK#, so adding it again wastes space.
    561   1.3  mrg ;; In addition, it is always a full barrier, so we can ignore the memory model.
    562   1.3  mrg (define_insn "atomic_exchange<mode>"
    563   1.3  mrg   [(set (match_operand:SWI 0 "register_operand" "=<r>")		;; output
    564   1.1  mrg 	(unspec_volatile:SWI
    565   1.3  mrg 	  [(match_operand:SWI 1 "memory_operand" "+m")		;; memory
    566   1.3  mrg 	   (match_operand:SI 3 "const_int_operand")]		;; model
    567   1.3  mrg 	  UNSPECV_XCHG))
    568   1.1  mrg    (set (match_dup 1)
    569   1.3  mrg 	(match_operand:SWI 2 "register_operand" "0"))]		;; input
    570   1.1  mrg   ""
    571   1.3  mrg   "%K3xchg{<imodesuffix>}\t{%1, %0|%0, %1}")
    572   1.1  mrg 
    573   1.3  mrg (define_insn "atomic_add<mode>"
    574   1.1  mrg   [(set (match_operand:SWI 0 "memory_operand" "+m")
    575   1.1  mrg 	(unspec_volatile:SWI
    576   1.1  mrg 	  [(plus:SWI (match_dup 0)
    577   1.3  mrg 		     (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
    578   1.3  mrg 	   (match_operand:SI 2 "const_int_operand")]		;; model
    579   1.1  mrg 	  UNSPECV_LOCK))
    580   1.1  mrg    (clobber (reg:CC FLAGS_REG))]
    581   1.1  mrg   ""
    582   1.1  mrg {
    583   1.3  mrg   if (incdec_operand (operands[1], <MODE>mode))
    584   1.1  mrg     {
    585   1.1  mrg       if (operands[1] == const1_rtx)
    586   1.3  mrg 	return "lock{%;} %K2inc{<imodesuffix>}\t%0";
    587   1.3  mrg       else
    588   1.3  mrg 	{
    589   1.3  mrg 	  gcc_assert (operands[1] == constm1_rtx);
    590   1.3  mrg 	  return "lock{%;} %K2dec{<imodesuffix>}\t%0";
    591   1.3  mrg 	}
    592   1.1  mrg     }
    593   1.1  mrg 
    594   1.3  mrg   if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
    595   1.3  mrg     return "lock{%;} %K2sub{<imodesuffix>}\t{%1, %0|%0, %1}";
    596   1.3  mrg 
    597   1.3  mrg   return "lock{%;} %K2add{<imodesuffix>}\t{%1, %0|%0, %1}";
    598   1.1  mrg })
    599   1.1  mrg 
    600   1.3  mrg (define_insn "atomic_sub<mode>"
    601   1.1  mrg   [(set (match_operand:SWI 0 "memory_operand" "+m")
    602   1.1  mrg 	(unspec_volatile:SWI
    603   1.1  mrg 	  [(minus:SWI (match_dup 0)
    604   1.3  mrg 		      (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
    605   1.3  mrg 	   (match_operand:SI 2 "const_int_operand")]		;; model
    606   1.1  mrg 	  UNSPECV_LOCK))
    607   1.1  mrg    (clobber (reg:CC FLAGS_REG))]
    608   1.1  mrg   ""
    609   1.1  mrg {
    610   1.3  mrg   if (incdec_operand (operands[1], <MODE>mode))
    611   1.1  mrg     {
    612   1.1  mrg       if (operands[1] == const1_rtx)
    613   1.3  mrg 	return "lock{%;} %K2dec{<imodesuffix>}\t%0";
    614   1.3  mrg       else
    615   1.3  mrg 	{
    616   1.3  mrg 	  gcc_assert (operands[1] == constm1_rtx);
    617   1.3  mrg 	  return "lock{%;} %K2inc{<imodesuffix>}\t%0";
    618   1.3  mrg 	}
    619   1.1  mrg     }
    620   1.1  mrg 
    621   1.3  mrg   if (x86_maybe_negate_const_int (&operands[1], <MODE>mode))
    622   1.3  mrg     return "lock{%;} %K2add{<imodesuffix>}\t{%1, %0|%0, %1}";
    623   1.3  mrg 
    624   1.3  mrg   return "lock{%;} %K2sub{<imodesuffix>}\t{%1, %0|%0, %1}";
    625   1.1  mrg })
    626   1.1  mrg 
    627   1.3  mrg (define_insn "atomic_<logic><mode>"
    628   1.1  mrg   [(set (match_operand:SWI 0 "memory_operand" "+m")
    629   1.1  mrg 	(unspec_volatile:SWI
    630   1.1  mrg 	  [(any_logic:SWI (match_dup 0)
    631   1.3  mrg 			  (match_operand:SWI 1 "nonmemory_operand" "<r><i>"))
    632   1.3  mrg 	   (match_operand:SI 2 "const_int_operand")]		;; model
    633   1.1  mrg 	  UNSPECV_LOCK))
    634   1.1  mrg    (clobber (reg:CC FLAGS_REG))]
    635   1.1  mrg   ""
    636   1.3  mrg   "lock{%;} %K2<logic>{<imodesuffix>}\t{%1, %0|%0, %1}")
    637   1.8  mrg 
    638   1.8  mrg (define_expand "atomic_bit_test_and_set<mode>"
    639   1.8  mrg   [(match_operand:SWI248 0 "register_operand")
    640   1.8  mrg    (match_operand:SWI248 1 "memory_operand")
    641   1.8  mrg    (match_operand:SWI248 2 "nonmemory_operand")
    642   1.8  mrg    (match_operand:SI 3 "const_int_operand") ;; model
    643   1.8  mrg    (match_operand:SI 4 "const_int_operand")]
    644   1.8  mrg   ""
    645   1.8  mrg {
    646   1.8  mrg   emit_insn (gen_atomic_bit_test_and_set<mode>_1 (operands[1], operands[2],
    647   1.8  mrg 						  operands[3]));
    648   1.8  mrg   rtx tem = gen_reg_rtx (QImode);
    649   1.8  mrg   ix86_expand_setcc (tem, EQ, gen_rtx_REG (CCCmode, FLAGS_REG), const0_rtx);
    650   1.8  mrg   rtx result = convert_modes (<MODE>mode, QImode, tem, 1);
    651   1.8  mrg   if (operands[4] == const0_rtx)
    652   1.8  mrg     result = expand_simple_binop (<MODE>mode, ASHIFT, result,
    653  1.11  mrg 				  operands[2], operands[0], 0, OPTAB_WIDEN);
    654   1.8  mrg   if (result != operands[0])
    655   1.8  mrg     emit_move_insn (operands[0], result);
    656   1.8  mrg   DONE;
    657   1.8  mrg })
    658   1.8  mrg 
    659   1.8  mrg (define_insn "atomic_bit_test_and_set<mode>_1"
    660   1.8  mrg   [(set (reg:CCC FLAGS_REG)
    661   1.8  mrg 	(compare:CCC
    662   1.8  mrg 	  (unspec_volatile:SWI248
    663   1.8  mrg 	    [(match_operand:SWI248 0 "memory_operand" "+m")
    664   1.8  mrg 	     (match_operand:SI 2 "const_int_operand")]		;; model
    665   1.8  mrg 	    UNSPECV_XCHG)
    666   1.8  mrg 	  (const_int 0)))
    667   1.8  mrg    (set (zero_extract:SWI248 (match_dup 0)
    668   1.8  mrg 			     (const_int 1)
    669   1.8  mrg 			     (match_operand:SWI248 1 "nonmemory_operand" "rN"))
    670   1.8  mrg 	(const_int 1))]
    671   1.8  mrg   ""
    672   1.8  mrg   "lock{%;} %K2bts{<imodesuffix>}\t{%1, %0|%0, %1}")
    673   1.8  mrg 
    674   1.8  mrg (define_expand "atomic_bit_test_and_complement<mode>"
    675   1.8  mrg   [(match_operand:SWI248 0 "register_operand")
    676   1.8  mrg    (match_operand:SWI248 1 "memory_operand")
    677   1.8  mrg    (match_operand:SWI248 2 "nonmemory_operand")
    678   1.8  mrg    (match_operand:SI 3 "const_int_operand") ;; model
    679   1.8  mrg    (match_operand:SI 4 "const_int_operand")]
    680   1.8  mrg   ""
    681   1.8  mrg {
    682   1.8  mrg   emit_insn (gen_atomic_bit_test_and_complement<mode>_1 (operands[1],
    683   1.8  mrg 							 operands[2],
    684   1.8  mrg 							 operands[3]));
    685   1.8  mrg   rtx tem = gen_reg_rtx (QImode);
    686   1.8  mrg   ix86_expand_setcc (tem, EQ, gen_rtx_REG (CCCmode, FLAGS_REG), const0_rtx);
    687   1.8  mrg   rtx result = convert_modes (<MODE>mode, QImode, tem, 1);
    688   1.8  mrg   if (operands[4] == const0_rtx)
    689   1.8  mrg     result = expand_simple_binop (<MODE>mode, ASHIFT, result,
    690  1.11  mrg 				  operands[2], operands[0], 0, OPTAB_WIDEN);
    691   1.8  mrg   if (result != operands[0])
    692   1.8  mrg     emit_move_insn (operands[0], result);
    693   1.8  mrg   DONE;
    694   1.8  mrg })
    695   1.8  mrg 
    696   1.8  mrg (define_insn "atomic_bit_test_and_complement<mode>_1"
    697   1.8  mrg   [(set (reg:CCC FLAGS_REG)
    698   1.8  mrg 	(compare:CCC
    699   1.8  mrg 	  (unspec_volatile:SWI248
    700   1.8  mrg 	    [(match_operand:SWI248 0 "memory_operand" "+m")
    701   1.8  mrg 	     (match_operand:SI 2 "const_int_operand")]		;; model
    702   1.8  mrg 	    UNSPECV_XCHG)
    703   1.8  mrg 	  (const_int 0)))
    704   1.8  mrg    (set (zero_extract:SWI248 (match_dup 0)
    705   1.8  mrg 			     (const_int 1)
    706   1.8  mrg 			     (match_operand:SWI248 1 "nonmemory_operand" "rN"))
    707   1.8  mrg 	(not:SWI248 (zero_extract:SWI248 (match_dup 0)
    708   1.8  mrg 					 (const_int 1)
    709   1.8  mrg 					 (match_dup 1))))]
    710   1.8  mrg   ""
    711   1.8  mrg   "lock{%;} %K2btc{<imodesuffix>}\t{%1, %0|%0, %1}")
    712   1.8  mrg 
    713   1.8  mrg (define_expand "atomic_bit_test_and_reset<mode>"
    714   1.8  mrg   [(match_operand:SWI248 0 "register_operand")
    715   1.8  mrg    (match_operand:SWI248 1 "memory_operand")
    716   1.8  mrg    (match_operand:SWI248 2 "nonmemory_operand")
    717   1.8  mrg    (match_operand:SI 3 "const_int_operand") ;; model
    718   1.8  mrg    (match_operand:SI 4 "const_int_operand")]
    719   1.8  mrg   ""
    720   1.8  mrg {
    721   1.8  mrg   emit_insn (gen_atomic_bit_test_and_reset<mode>_1 (operands[1], operands[2],
    722   1.8  mrg 						    operands[3]));
    723   1.8  mrg   rtx tem = gen_reg_rtx (QImode);
    724   1.8  mrg   ix86_expand_setcc (tem, EQ, gen_rtx_REG (CCCmode, FLAGS_REG), const0_rtx);
    725   1.8  mrg   rtx result = convert_modes (<MODE>mode, QImode, tem, 1);
    726   1.8  mrg   if (operands[4] == const0_rtx)
    727   1.8  mrg     result = expand_simple_binop (<MODE>mode, ASHIFT, result,
    728  1.11  mrg 				  operands[2], operands[0], 0, OPTAB_WIDEN);
    729   1.8  mrg   if (result != operands[0])
    730   1.8  mrg     emit_move_insn (operands[0], result);
    731   1.8  mrg   DONE;
    732   1.8  mrg })
    733   1.8  mrg 
    734   1.8  mrg (define_insn "atomic_bit_test_and_reset<mode>_1"
    735   1.8  mrg   [(set (reg:CCC FLAGS_REG)
    736   1.8  mrg 	(compare:CCC
    737   1.8  mrg 	  (unspec_volatile:SWI248
    738   1.8  mrg 	    [(match_operand:SWI248 0 "memory_operand" "+m")
    739   1.8  mrg 	     (match_operand:SI 2 "const_int_operand")]		;; model
    740   1.8  mrg 	    UNSPECV_XCHG)
    741   1.8  mrg 	  (const_int 0)))
    742   1.8  mrg    (set (zero_extract:SWI248 (match_dup 0)
    743   1.8  mrg 			     (const_int 1)
    744   1.8  mrg 			     (match_operand:SWI248 1 "nonmemory_operand" "rN"))
    745   1.8  mrg 	(const_int 0))]
    746   1.8  mrg   ""
    747   1.8  mrg   "lock{%;} %K2btr{<imodesuffix>}\t{%1, %0|%0, %1}")
    748