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