1;; Machine Description for MIPS based processor synchronization 2;; instructions. 3;; Copyright (C) 2007-2015 Free Software Foundation, Inc. 4 5;; This file is part of GCC. 6 7;; GCC is free software; you can redistribute it and/or modify 8;; it under the terms of the GNU General Public License as published by 9;; the Free Software Foundation; either version 3, or (at your option) 10;; any later version. 11 12;; GCC is distributed in the hope that it will be useful, 13;; but WITHOUT ANY WARRANTY; without even the implied warranty of 14;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15;; GNU General Public License for more details. 16 17;; You should have received a copy of the GNU General Public License 18;; along with GCC; see the file COPYING3. If not see 19;; <http://www.gnu.org/licenses/>. 20 21(define_c_enum "unspec" [ 22 UNSPEC_COMPARE_AND_SWAP 23 UNSPEC_COMPARE_AND_SWAP_12 24 UNSPEC_SYNC_OLD_OP 25 UNSPEC_SYNC_NEW_OP 26 UNSPEC_SYNC_NEW_OP_12 27 UNSPEC_SYNC_OLD_OP_12 28 UNSPEC_SYNC_EXCHANGE 29 UNSPEC_SYNC_EXCHANGE_12 30 UNSPEC_MEMORY_BARRIER 31 UNSPEC_ATOMIC_COMPARE_AND_SWAP 32 UNSPEC_ATOMIC_EXCHANGE 33 UNSPEC_ATOMIC_FETCH_OP 34]) 35 36;; Atomic fetch bitwise operations. 37(define_code_iterator fetchop_bit [ior xor and]) 38 39;; Atomic HI and QI operations 40(define_code_iterator atomic_hiqi_op [plus minus ior xor and]) 41 42;; Atomic memory operations. 43 44(define_expand "memory_barrier" 45 [(set (match_dup 0) 46 (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))] 47 "GENERATE_SYNC" 48{ 49 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); 50 MEM_VOLATILE_P (operands[0]) = 1; 51}) 52 53(define_insn "*memory_barrier" 54 [(set (match_operand:BLK 0 "" "") 55 (unspec:BLK [(match_dup 0)] UNSPEC_MEMORY_BARRIER))] 56 "GENERATE_SYNC" 57 { return mips_output_sync (); }) 58 59;; Can be removed in favor of atomic_compare_and_swap below. 60(define_insn "sync_compare_and_swap<mode>" 61 [(set (match_operand:GPR 0 "register_operand" "=&d,&d") 62 (match_operand:GPR 1 "memory_operand" "+ZC,ZC")) 63 (set (match_dup 1) 64 (unspec_volatile:GPR [(match_operand:GPR 2 "reg_or_0_operand" "dJ,dJ") 65 (match_operand:GPR 3 "arith_operand" "I,d")] 66 UNSPEC_COMPARE_AND_SWAP))] 67 "GENERATE_LL_SC" 68 { return mips_output_sync_loop (insn, operands); } 69 [(set_attr "sync_insn1" "li,move") 70 (set_attr "sync_oldval" "0") 71 (set_attr "sync_mem" "1") 72 (set_attr "sync_required_oldval" "2") 73 (set_attr "sync_insn1_op2" "3")]) 74 75(define_expand "sync_compare_and_swap<mode>" 76 [(match_operand:SHORT 0 "register_operand") 77 (match_operand:SHORT 1 "memory_operand") 78 (match_operand:SHORT 2 "general_operand") 79 (match_operand:SHORT 3 "general_operand")] 80 "GENERATE_LL_SC" 81{ 82 union mips_gen_fn_ptrs generator; 83 generator.fn_6 = gen_compare_and_swap_12; 84 mips_expand_atomic_qihi (generator, 85 operands[0], operands[1], operands[2], operands[3]); 86 DONE; 87}) 88 89;; Helper insn for mips_expand_atomic_qihi. 90(define_insn "compare_and_swap_12" 91 [(set (match_operand:SI 0 "register_operand" "=&d,&d") 92 (match_operand:SI 1 "memory_operand" "+ZC,ZC")) 93 (set (match_dup 1) 94 (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d,d") 95 (match_operand:SI 3 "register_operand" "d,d") 96 (match_operand:SI 4 "reg_or_0_operand" "dJ,dJ") 97 (match_operand:SI 5 "reg_or_0_operand" "d,J")] 98 UNSPEC_COMPARE_AND_SWAP_12))] 99 "GENERATE_LL_SC" 100 { return mips_output_sync_loop (insn, operands); } 101 [(set_attr "sync_oldval" "0") 102 (set_attr "sync_mem" "1") 103 (set_attr "sync_inclusive_mask" "2") 104 (set_attr "sync_exclusive_mask" "3") 105 (set_attr "sync_required_oldval" "4") 106 (set_attr "sync_insn1_op2" "5")]) 107 108(define_insn "sync_add<mode>" 109 [(set (match_operand:GPR 0 "memory_operand" "+ZC,ZC") 110 (unspec_volatile:GPR 111 [(plus:GPR (match_dup 0) 112 (match_operand:GPR 1 "arith_operand" "I,d"))] 113 UNSPEC_SYNC_OLD_OP))] 114 "GENERATE_LL_SC" 115 { return mips_output_sync_loop (insn, operands); } 116 [(set_attr "sync_insn1" "addiu,addu") 117 (set_attr "sync_mem" "0") 118 (set_attr "sync_insn1_op2" "1")]) 119 120(define_expand "sync_<optab><mode>" 121 [(set (match_operand:SHORT 0 "memory_operand") 122 (unspec_volatile:SHORT 123 [(atomic_hiqi_op:SHORT (match_dup 0) 124 (match_operand:SHORT 1 "general_operand"))] 125 UNSPEC_SYNC_OLD_OP))] 126 "GENERATE_LL_SC" 127{ 128 union mips_gen_fn_ptrs generator; 129 generator.fn_4 = gen_sync_<optab>_12; 130 mips_expand_atomic_qihi (generator, 131 NULL, operands[0], operands[1], NULL); 132 DONE; 133}) 134 135;; Helper insn for sync_<optab><mode> 136(define_insn "sync_<optab>_12" 137 [(set (match_operand:SI 0 "memory_operand" "+ZC") 138 (unspec_volatile:SI 139 [(match_operand:SI 1 "register_operand" "d") 140 (match_operand:SI 2 "register_operand" "d") 141 (atomic_hiqi_op:SI (match_dup 0) 142 (match_operand:SI 3 "reg_or_0_operand" "dJ"))] 143 UNSPEC_SYNC_OLD_OP_12)) 144 (clobber (match_scratch:SI 4 "=&d"))] 145 "GENERATE_LL_SC" 146 { return mips_output_sync_loop (insn, operands); } 147 [(set_attr "sync_insn1" "<insn>") 148 (set_attr "sync_insn2" "and") 149 (set_attr "sync_mem" "0") 150 (set_attr "sync_inclusive_mask" "1") 151 (set_attr "sync_exclusive_mask" "2") 152 (set_attr "sync_insn1_op2" "3") 153 (set_attr "sync_oldval" "4") 154 (set_attr "sync_newval" "4")]) 155 156(define_expand "sync_old_<optab><mode>" 157 [(parallel [ 158 (set (match_operand:SHORT 0 "register_operand") 159 (match_operand:SHORT 1 "memory_operand")) 160 (set (match_dup 1) 161 (unspec_volatile:SHORT [(atomic_hiqi_op:SHORT 162 (match_dup 1) 163 (match_operand:SHORT 2 "general_operand"))] 164 UNSPEC_SYNC_OLD_OP))])] 165 "GENERATE_LL_SC" 166{ 167 union mips_gen_fn_ptrs generator; 168 generator.fn_5 = gen_sync_old_<optab>_12; 169 mips_expand_atomic_qihi (generator, 170 operands[0], operands[1], operands[2], NULL); 171 DONE; 172}) 173 174;; Helper insn for sync_old_<optab><mode> 175(define_insn "sync_old_<optab>_12" 176 [(set (match_operand:SI 0 "register_operand" "=&d") 177 (match_operand:SI 1 "memory_operand" "+ZC")) 178 (set (match_dup 1) 179 (unspec_volatile:SI 180 [(match_operand:SI 2 "register_operand" "d") 181 (match_operand:SI 3 "register_operand" "d") 182 (atomic_hiqi_op:SI (match_dup 0) 183 (match_operand:SI 4 "reg_or_0_operand" "dJ"))] 184 UNSPEC_SYNC_OLD_OP_12)) 185 (clobber (match_scratch:SI 5 "=&d"))] 186 "GENERATE_LL_SC" 187 { return mips_output_sync_loop (insn, operands); } 188 [(set_attr "sync_insn1" "<insn>") 189 (set_attr "sync_insn2" "and") 190 (set_attr "sync_oldval" "0") 191 (set_attr "sync_mem" "1") 192 (set_attr "sync_inclusive_mask" "2") 193 (set_attr "sync_exclusive_mask" "3") 194 (set_attr "sync_insn1_op2" "4") 195 (set_attr "sync_newval" "5")]) 196 197(define_expand "sync_new_<optab><mode>" 198 [(parallel [ 199 (set (match_operand:SHORT 0 "register_operand") 200 (unspec_volatile:SHORT [(atomic_hiqi_op:SHORT 201 (match_operand:SHORT 1 "memory_operand") 202 (match_operand:SHORT 2 "general_operand"))] 203 UNSPEC_SYNC_NEW_OP)) 204 (set (match_dup 1) 205 (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)] 206 UNSPEC_SYNC_NEW_OP))])] 207 "GENERATE_LL_SC" 208{ 209 union mips_gen_fn_ptrs generator; 210 generator.fn_5 = gen_sync_new_<optab>_12; 211 mips_expand_atomic_qihi (generator, 212 operands[0], operands[1], operands[2], NULL); 213 DONE; 214}) 215 216;; Helper insn for sync_new_<optab><mode> 217(define_insn "sync_new_<optab>_12" 218 [(set (match_operand:SI 0 "register_operand" "=&d") 219 (unspec_volatile:SI 220 [(match_operand:SI 1 "memory_operand" "+ZC") 221 (match_operand:SI 2 "register_operand" "d") 222 (match_operand:SI 3 "register_operand" "d") 223 (atomic_hiqi_op:SI (match_dup 0) 224 (match_operand:SI 4 "reg_or_0_operand" "dJ"))] 225 UNSPEC_SYNC_NEW_OP_12)) 226 (set (match_dup 1) 227 (unspec_volatile:SI 228 [(match_dup 1) 229 (match_dup 2) 230 (match_dup 3) 231 (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))] 232 "GENERATE_LL_SC" 233 { return mips_output_sync_loop (insn, operands); } 234 [(set_attr "sync_insn1" "<insn>") 235 (set_attr "sync_insn2" "and") 236 (set_attr "sync_oldval" "0") 237 (set_attr "sync_newval" "0") 238 (set_attr "sync_mem" "1") 239 (set_attr "sync_inclusive_mask" "2") 240 (set_attr "sync_exclusive_mask" "3") 241 (set_attr "sync_insn1_op2" "4")]) 242 243(define_expand "sync_nand<mode>" 244 [(set (match_operand:SHORT 0 "memory_operand") 245 (unspec_volatile:SHORT 246 [(match_dup 0) 247 (match_operand:SHORT 1 "general_operand")] 248 UNSPEC_SYNC_OLD_OP))] 249 "GENERATE_LL_SC" 250{ 251 union mips_gen_fn_ptrs generator; 252 generator.fn_4 = gen_sync_nand_12; 253 mips_expand_atomic_qihi (generator, 254 NULL, operands[0], operands[1], NULL); 255 DONE; 256}) 257 258;; Helper insn for sync_nand<mode> 259(define_insn "sync_nand_12" 260 [(set (match_operand:SI 0 "memory_operand" "+ZC") 261 (unspec_volatile:SI 262 [(match_operand:SI 1 "register_operand" "d") 263 (match_operand:SI 2 "register_operand" "d") 264 (match_dup 0) 265 (match_operand:SI 3 "reg_or_0_operand" "dJ")] 266 UNSPEC_SYNC_OLD_OP_12)) 267 (clobber (match_scratch:SI 4 "=&d"))] 268 "GENERATE_LL_SC" 269 { return mips_output_sync_loop (insn, operands); } 270 [(set_attr "sync_insn1" "and") 271 (set_attr "sync_insn2" "xor") 272 (set_attr "sync_mem" "0") 273 (set_attr "sync_inclusive_mask" "1") 274 (set_attr "sync_exclusive_mask" "2") 275 (set_attr "sync_insn1_op2" "3") 276 (set_attr "sync_oldval" "4") 277 (set_attr "sync_newval" "4")]) 278 279(define_expand "sync_old_nand<mode>" 280 [(parallel [ 281 (set (match_operand:SHORT 0 "register_operand") 282 (match_operand:SHORT 1 "memory_operand")) 283 (set (match_dup 1) 284 (unspec_volatile:SHORT [(match_dup 1) 285 (match_operand:SHORT 2 "general_operand")] 286 UNSPEC_SYNC_OLD_OP))])] 287 "GENERATE_LL_SC" 288{ 289 union mips_gen_fn_ptrs generator; 290 generator.fn_5 = gen_sync_old_nand_12; 291 mips_expand_atomic_qihi (generator, 292 operands[0], operands[1], operands[2], NULL); 293 DONE; 294}) 295 296;; Helper insn for sync_old_nand<mode> 297(define_insn "sync_old_nand_12" 298 [(set (match_operand:SI 0 "register_operand" "=&d") 299 (match_operand:SI 1 "memory_operand" "+ZC")) 300 (set (match_dup 1) 301 (unspec_volatile:SI 302 [(match_operand:SI 2 "register_operand" "d") 303 (match_operand:SI 3 "register_operand" "d") 304 (match_operand:SI 4 "reg_or_0_operand" "dJ")] 305 UNSPEC_SYNC_OLD_OP_12)) 306 (clobber (match_scratch:SI 5 "=&d"))] 307 "GENERATE_LL_SC" 308 { return mips_output_sync_loop (insn, operands); } 309 [(set_attr "sync_insn1" "and") 310 (set_attr "sync_insn2" "xor") 311 (set_attr "sync_oldval" "0") 312 (set_attr "sync_mem" "1") 313 (set_attr "sync_inclusive_mask" "2") 314 (set_attr "sync_exclusive_mask" "3") 315 (set_attr "sync_insn1_op2" "4") 316 (set_attr "sync_newval" "5")]) 317 318(define_expand "sync_new_nand<mode>" 319 [(parallel [ 320 (set (match_operand:SHORT 0 "register_operand") 321 (unspec_volatile:SHORT [(match_operand:SHORT 1 "memory_operand") 322 (match_operand:SHORT 2 "general_operand")] 323 UNSPEC_SYNC_NEW_OP)) 324 (set (match_dup 1) 325 (unspec_volatile:SHORT [(match_dup 1) (match_dup 2)] 326 UNSPEC_SYNC_NEW_OP))])] 327 "GENERATE_LL_SC" 328{ 329 union mips_gen_fn_ptrs generator; 330 generator.fn_5 = gen_sync_new_nand_12; 331 mips_expand_atomic_qihi (generator, 332 operands[0], operands[1], operands[2], NULL); 333 DONE; 334}) 335 336;; Helper insn for sync_new_nand<mode> 337(define_insn "sync_new_nand_12" 338 [(set (match_operand:SI 0 "register_operand" "=&d") 339 (unspec_volatile:SI 340 [(match_operand:SI 1 "memory_operand" "+ZC") 341 (match_operand:SI 2 "register_operand" "d") 342 (match_operand:SI 3 "register_operand" "d") 343 (match_operand:SI 4 "reg_or_0_operand" "dJ")] 344 UNSPEC_SYNC_NEW_OP_12)) 345 (set (match_dup 1) 346 (unspec_volatile:SI 347 [(match_dup 1) 348 (match_dup 2) 349 (match_dup 3) 350 (match_dup 4)] UNSPEC_SYNC_NEW_OP_12))] 351 "GENERATE_LL_SC" 352 { return mips_output_sync_loop (insn, operands); } 353 [(set_attr "sync_insn1" "and") 354 (set_attr "sync_insn2" "xor") 355 (set_attr "sync_oldval" "0") 356 (set_attr "sync_newval" "0") 357 (set_attr "sync_mem" "1") 358 (set_attr "sync_inclusive_mask" "2") 359 (set_attr "sync_exclusive_mask" "3") 360 (set_attr "sync_insn1_op2" "4")]) 361 362(define_insn "sync_sub<mode>" 363 [(set (match_operand:GPR 0 "memory_operand" "+ZC") 364 (unspec_volatile:GPR 365 [(minus:GPR (match_dup 0) 366 (match_operand:GPR 1 "register_operand" "d"))] 367 UNSPEC_SYNC_OLD_OP))] 368 "GENERATE_LL_SC" 369 { return mips_output_sync_loop (insn, operands); } 370 [(set_attr "sync_insn1" "subu") 371 (set_attr "sync_mem" "0") 372 (set_attr "sync_insn1_op2" "1")]) 373 374;; Can be removed in favor of atomic_fetch_add below. 375(define_insn "sync_old_add<mode>" 376 [(set (match_operand:GPR 0 "register_operand" "=&d,&d") 377 (match_operand:GPR 1 "memory_operand" "+ZC,ZC")) 378 (set (match_dup 1) 379 (unspec_volatile:GPR 380 [(plus:GPR (match_dup 1) 381 (match_operand:GPR 2 "arith_operand" "I,d"))] 382 UNSPEC_SYNC_OLD_OP))] 383 "GENERATE_LL_SC" 384 { return mips_output_sync_loop (insn, operands); } 385 [(set_attr "sync_insn1" "addiu,addu") 386 (set_attr "sync_oldval" "0") 387 (set_attr "sync_mem" "1") 388 (set_attr "sync_insn1_op2" "2")]) 389 390(define_insn "sync_old_sub<mode>" 391 [(set (match_operand:GPR 0 "register_operand" "=&d") 392 (match_operand:GPR 1 "memory_operand" "+ZC")) 393 (set (match_dup 1) 394 (unspec_volatile:GPR 395 [(minus:GPR (match_dup 1) 396 (match_operand:GPR 2 "register_operand" "d"))] 397 UNSPEC_SYNC_OLD_OP))] 398 "GENERATE_LL_SC" 399 { return mips_output_sync_loop (insn, operands); } 400 [(set_attr "sync_insn1" "subu") 401 (set_attr "sync_oldval" "0") 402 (set_attr "sync_mem" "1") 403 (set_attr "sync_insn1_op2" "2")]) 404 405(define_insn "sync_new_add<mode>" 406 [(set (match_operand:GPR 0 "register_operand" "=&d,&d") 407 (plus:GPR (match_operand:GPR 1 "memory_operand" "+ZC,ZC") 408 (match_operand:GPR 2 "arith_operand" "I,d"))) 409 (set (match_dup 1) 410 (unspec_volatile:GPR 411 [(plus:GPR (match_dup 1) (match_dup 2))] 412 UNSPEC_SYNC_NEW_OP))] 413 "GENERATE_LL_SC" 414 { return mips_output_sync_loop (insn, operands); } 415 [(set_attr "sync_insn1" "addiu,addu") 416 (set_attr "sync_oldval" "0") 417 (set_attr "sync_newval" "0") 418 (set_attr "sync_mem" "1") 419 (set_attr "sync_insn1_op2" "2")]) 420 421(define_insn "sync_new_sub<mode>" 422 [(set (match_operand:GPR 0 "register_operand" "=&d") 423 (minus:GPR (match_operand:GPR 1 "memory_operand" "+ZC") 424 (match_operand:GPR 2 "register_operand" "d"))) 425 (set (match_dup 1) 426 (unspec_volatile:GPR 427 [(minus:GPR (match_dup 1) (match_dup 2))] 428 UNSPEC_SYNC_NEW_OP))] 429 "GENERATE_LL_SC" 430 { return mips_output_sync_loop (insn, operands); } 431 [(set_attr "sync_insn1" "subu") 432 (set_attr "sync_oldval" "0") 433 (set_attr "sync_newval" "0") 434 (set_attr "sync_mem" "1") 435 (set_attr "sync_insn1_op2" "2")]) 436 437(define_insn "sync_<optab><mode>" 438 [(set (match_operand:GPR 0 "memory_operand" "+ZC,ZC") 439 (unspec_volatile:GPR 440 [(fetchop_bit:GPR (match_operand:GPR 1 "uns_arith_operand" "K,d") 441 (match_dup 0))] 442 UNSPEC_SYNC_OLD_OP))] 443 "GENERATE_LL_SC" 444 { return mips_output_sync_loop (insn, operands); } 445 [(set_attr "sync_insn1" "<immediate_insn>,<insn>") 446 (set_attr "sync_mem" "0") 447 (set_attr "sync_insn1_op2" "1")]) 448 449(define_insn "sync_old_<optab><mode>" 450 [(set (match_operand:GPR 0 "register_operand" "=&d,&d") 451 (match_operand:GPR 1 "memory_operand" "+ZC,ZC")) 452 (set (match_dup 1) 453 (unspec_volatile:GPR 454 [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d") 455 (match_dup 1))] 456 UNSPEC_SYNC_OLD_OP))] 457 "GENERATE_LL_SC" 458 { return mips_output_sync_loop (insn, operands); } 459 [(set_attr "sync_insn1" "<immediate_insn>,<insn>") 460 (set_attr "sync_oldval" "0") 461 (set_attr "sync_mem" "1") 462 (set_attr "sync_insn1_op2" "2")]) 463 464(define_insn "sync_new_<optab><mode>" 465 [(set (match_operand:GPR 0 "register_operand" "=&d,&d") 466 (match_operand:GPR 1 "memory_operand" "+ZC,ZC")) 467 (set (match_dup 1) 468 (unspec_volatile:GPR 469 [(fetchop_bit:GPR (match_operand:GPR 2 "uns_arith_operand" "K,d") 470 (match_dup 1))] 471 UNSPEC_SYNC_NEW_OP))] 472 "GENERATE_LL_SC" 473 { return mips_output_sync_loop (insn, operands); } 474 [(set_attr "sync_insn1" "<immediate_insn>,<insn>") 475 (set_attr "sync_oldval" "0") 476 (set_attr "sync_newval" "0") 477 (set_attr "sync_mem" "1") 478 (set_attr "sync_insn1_op2" "2")]) 479 480(define_insn "sync_nand<mode>" 481 [(set (match_operand:GPR 0 "memory_operand" "+ZC,ZC") 482 (unspec_volatile:GPR [(match_operand:GPR 1 "uns_arith_operand" "K,d")] 483 UNSPEC_SYNC_OLD_OP))] 484 "GENERATE_LL_SC" 485 { return mips_output_sync_loop (insn, operands); } 486 [(set_attr "sync_insn1" "andi,and") 487 (set_attr "sync_insn2" "not") 488 (set_attr "sync_mem" "0") 489 (set_attr "sync_insn1_op2" "1")]) 490 491(define_insn "sync_old_nand<mode>" 492 [(set (match_operand:GPR 0 "register_operand" "=&d,&d") 493 (match_operand:GPR 1 "memory_operand" "+ZC,ZC")) 494 (set (match_dup 1) 495 (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")] 496 UNSPEC_SYNC_OLD_OP))] 497 "GENERATE_LL_SC" 498 { return mips_output_sync_loop (insn, operands); } 499 [(set_attr "sync_insn1" "andi,and") 500 (set_attr "sync_insn2" "not") 501 (set_attr "sync_oldval" "0") 502 (set_attr "sync_mem" "1") 503 (set_attr "sync_insn1_op2" "2")]) 504 505(define_insn "sync_new_nand<mode>" 506 [(set (match_operand:GPR 0 "register_operand" "=&d,&d") 507 (match_operand:GPR 1 "memory_operand" "+ZC,ZC")) 508 (set (match_dup 1) 509 (unspec_volatile:GPR [(match_operand:GPR 2 "uns_arith_operand" "K,d")] 510 UNSPEC_SYNC_NEW_OP))] 511 "GENERATE_LL_SC" 512 { return mips_output_sync_loop (insn, operands); } 513 [(set_attr "sync_insn1" "andi,and") 514 (set_attr "sync_insn2" "not") 515 (set_attr "sync_oldval" "0") 516 (set_attr "sync_newval" "0") 517 (set_attr "sync_mem" "1") 518 (set_attr "sync_insn1_op2" "2")]) 519 520(define_insn "sync_lock_test_and_set<mode>" 521 [(set (match_operand:GPR 0 "register_operand" "=&d,&d") 522 (match_operand:GPR 1 "memory_operand" "+ZC,ZC")) 523 (set (match_dup 1) 524 (unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "I,d")] 525 UNSPEC_SYNC_EXCHANGE))] 526 "GENERATE_LL_SC" 527 { return mips_output_sync_loop (insn, operands); } 528 [(set_attr "sync_memmodel" "11") 529 (set_attr "sync_insn1" "li,move") 530 (set_attr "sync_oldval" "0") 531 (set_attr "sync_mem" "1") 532 (set_attr "sync_insn1_op2" "2")]) 533 534(define_expand "sync_lock_test_and_set<mode>" 535 [(match_operand:SHORT 0 "register_operand") 536 (match_operand:SHORT 1 "memory_operand") 537 (match_operand:SHORT 2 "general_operand")] 538 "GENERATE_LL_SC" 539{ 540 union mips_gen_fn_ptrs generator; 541 generator.fn_5 = gen_test_and_set_12; 542 mips_expand_atomic_qihi (generator, 543 operands[0], operands[1], operands[2], NULL); 544 DONE; 545}) 546 547(define_insn "test_and_set_12" 548 [(set (match_operand:SI 0 "register_operand" "=&d") 549 (match_operand:SI 1 "memory_operand" "+ZC")) 550 (set (match_dup 1) 551 (unspec_volatile:SI [(match_operand:SI 2 "register_operand" "d") 552 (match_operand:SI 3 "register_operand" "d") 553 (match_operand:SI 4 "reg_or_0_operand" "dJ")] 554 UNSPEC_SYNC_EXCHANGE_12))] 555 "GENERATE_LL_SC" 556 { return mips_output_sync_loop (insn, operands); } 557 [(set_attr "sync_memmodel" "11") 558 (set_attr "sync_oldval" "0") 559 (set_attr "sync_mem" "1") 560 ;; Unused, but needed to give the number of operands expected by 561 ;; the expander. 562 (set_attr "sync_inclusive_mask" "2") 563 (set_attr "sync_exclusive_mask" "3") 564 (set_attr "sync_insn1_op2" "4")]) 565 566(define_insn "atomic_compare_and_swap<mode>" 567 [(set (match_operand:GPR 0 "register_operand" "=&d,&d") 568 ;; Logically this unspec is an "eq" operator, but we need to obscure 569 ;; reads and writes from/to memory with an unspec to prevent 570 ;; optimizations on shared memory locations. Otherwise, comparison in 571 ;; { mem = 2; if (atomic_cmp_swap(mem,...) == 2) ...; } 572 ;; would be optimized away. In addition to that we need to use 573 ;; unspec_volatile, not just plain unspec -- for the sake of other 574 ;; threads -- to make sure we don't remove the entirety of the pattern 575 ;; just because current thread doesn't observe any effect from it. 576 ;; TODO: the obscuring unspec can be relaxed for permissive memory 577 ;; models. 578 ;; Same applies to other atomic_* patterns. 579 (unspec_volatile:GPR [(match_operand:GPR 2 "memory_operand" "+ZC,ZC") 580 (match_operand:GPR 3 "reg_or_0_operand" "dJ,dJ")] 581 UNSPEC_ATOMIC_COMPARE_AND_SWAP)) 582 (set (match_operand:GPR 1 "register_operand" "=&d,&d") 583 (unspec_volatile:GPR [(match_dup 2)] 584 UNSPEC_ATOMIC_COMPARE_AND_SWAP)) 585 (set (match_dup 2) 586 (unspec_volatile:GPR [(match_dup 2) 587 (match_dup 3) 588 (match_operand:GPR 4 "arith_operand" "I,d")] 589 UNSPEC_ATOMIC_COMPARE_AND_SWAP)) 590 (unspec_volatile:GPR [(match_operand:SI 5 "const_int_operand") 591 (match_operand:SI 6 "const_int_operand") 592 (match_operand:SI 7 "const_int_operand")] 593 UNSPEC_ATOMIC_COMPARE_AND_SWAP)] 594 "GENERATE_LL_SC" 595 { return mips_output_sync_loop (insn, operands); } 596 [(set_attr "sync_insn1" "li,move") 597 (set_attr "sync_oldval" "1") 598 (set_attr "sync_cmp" "0") 599 (set_attr "sync_mem" "2") 600 (set_attr "sync_required_oldval" "3") 601 (set_attr "sync_insn1_op2" "4") 602 (set_attr "sync_memmodel" "6")]) 603 604(define_expand "atomic_exchange<mode>" 605 [(match_operand:GPR 0 "register_operand") 606 (match_operand:GPR 1 "memory_operand") 607 (match_operand:GPR 2 "arith_operand") 608 (match_operand:SI 3 "const_int_operand")] 609 "GENERATE_LL_SC || ISA_HAS_SWAP" 610{ 611 if (ISA_HAS_SWAP) 612 { 613 if (!mem_noofs_operand (operands[1], <MODE>mode)) 614 { 615 rtx addr; 616 617 addr = force_reg (Pmode, XEXP (operands[1], 0)); 618 operands[1] = replace_equiv_address (operands[1], addr); 619 } 620 operands[2] = force_reg (<MODE>mode, operands[2]); 621 emit_insn (gen_atomic_exchange<mode>_swap (operands[0], operands[1], 622 operands[2])); 623 } 624 else 625 emit_insn (gen_atomic_exchange<mode>_llsc (operands[0], operands[1], 626 operands[2], operands[3])); 627 DONE; 628}) 629 630(define_insn "atomic_exchange<mode>_llsc" 631 [(set (match_operand:GPR 0 "register_operand" "=&d,&d") 632 (unspec_volatile:GPR [(match_operand:GPR 1 "memory_operand" "+ZC,ZC")] 633 UNSPEC_ATOMIC_EXCHANGE)) 634 (set (match_dup 1) 635 (unspec_volatile:GPR [(match_operand:GPR 2 "arith_operand" "I,d")] 636 UNSPEC_ATOMIC_EXCHANGE)) 637 (unspec_volatile:GPR [(match_operand:SI 3 "const_int_operand")] 638 UNSPEC_ATOMIC_EXCHANGE)] 639 "GENERATE_LL_SC && !ISA_HAS_SWAP" 640 { return mips_output_sync_loop (insn, operands); } 641 [(set_attr "sync_insn1" "li,move") 642 (set_attr "sync_oldval" "0") 643 (set_attr "sync_mem" "1") 644 (set_attr "sync_insn1_op2" "2") 645 (set_attr "sync_memmodel" "3")]) 646 647;; XLP issues implicit sync for SWAP/LDADD, so no need for an explicit one. 648(define_insn "atomic_exchange<mode>_swap" 649 [(set (match_operand:GPR 0 "register_operand" "=d") 650 (unspec_volatile:GPR [(match_operand:GPR 1 "mem_noofs_operand" "+ZR")] 651 UNSPEC_ATOMIC_EXCHANGE)) 652 (set (match_dup 1) 653 (unspec_volatile:GPR [(match_operand:GPR 2 "register_operand" "0")] 654 UNSPEC_ATOMIC_EXCHANGE))] 655 "ISA_HAS_SWAP" 656 "swap<size>\t%0,%b1" 657 [(set_attr "type" "atomic")]) 658 659(define_expand "atomic_fetch_add<mode>" 660 [(match_operand:GPR 0 "register_operand") 661 (match_operand:GPR 1 "memory_operand") 662 (match_operand:GPR 2 "arith_operand") 663 (match_operand:SI 3 "const_int_operand")] 664 "GENERATE_LL_SC || ISA_HAS_LDADD" 665{ 666 if (ISA_HAS_LDADD) 667 { 668 if (!mem_noofs_operand (operands[1], <MODE>mode)) 669 { 670 rtx addr; 671 672 addr = force_reg (Pmode, XEXP (operands[1], 0)); 673 operands[1] = replace_equiv_address (operands[1], addr); 674 } 675 operands[2] = force_reg (<MODE>mode, operands[2]); 676 emit_insn (gen_atomic_fetch_add<mode>_ldadd (operands[0], operands[1], 677 operands[2])); 678 } 679 else 680 emit_insn (gen_atomic_fetch_add<mode>_llsc (operands[0], operands[1], 681 operands[2], operands[3])); 682 DONE; 683}) 684 685(define_insn "atomic_fetch_add<mode>_llsc" 686 [(set (match_operand:GPR 0 "register_operand" "=&d,&d") 687 (unspec_volatile:GPR [(match_operand:GPR 1 "memory_operand" "+ZC,ZC")] 688 UNSPEC_ATOMIC_FETCH_OP)) 689 (set (match_dup 1) 690 (unspec_volatile:GPR 691 [(plus:GPR (match_dup 1) 692 (match_operand:GPR 2 "arith_operand" "I,d"))] 693 UNSPEC_ATOMIC_FETCH_OP)) 694 (unspec_volatile:GPR [(match_operand:SI 3 "const_int_operand")] 695 UNSPEC_ATOMIC_FETCH_OP)] 696 "GENERATE_LL_SC && !ISA_HAS_LDADD" 697 { return mips_output_sync_loop (insn, operands); } 698 [(set_attr "sync_insn1" "addiu,addu") 699 (set_attr "sync_oldval" "0") 700 (set_attr "sync_mem" "1") 701 (set_attr "sync_insn1_op2" "2") 702 (set_attr "sync_memmodel" "3")]) 703 704;; XLP issues implicit sync for SWAP/LDADD, so no need for an explicit one. 705(define_insn "atomic_fetch_add<mode>_ldadd" 706 [(set (match_operand:GPR 0 "register_operand" "=d") 707 (unspec_volatile:GPR [(match_operand:GPR 1 "mem_noofs_operand" "+ZR")] 708 UNSPEC_ATOMIC_FETCH_OP)) 709 (set (match_dup 1) 710 (unspec_volatile:GPR 711 [(plus:GPR (match_dup 1) 712 (match_operand:GPR 2 "register_operand" "0"))] 713 UNSPEC_ATOMIC_FETCH_OP))] 714 "ISA_HAS_LDADD" 715 "ldadd<size>\t%0,%b1" 716 [(set_attr "type" "atomic")]) 717