1;; GCC machine description for IA-64 synchronization instructions. 2;; Copyright (C) 2005-2013 Free Software Foundation, Inc. 3;; 4;; This file is part of GCC. 5;; 6;; GCC is free software; you can redistribute it and/or modify 7;; it under the terms of the GNU General Public License as published by 8;; the Free Software Foundation; either version 3, or (at your option) 9;; any later version. 10;; 11;; GCC is distributed in the hope that it will be useful, 12;; but WITHOUT ANY WARRANTY; without even the implied warranty of 13;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14;; GNU General Public License for more details. 15;; 16;; You should have received a copy of the GNU General Public License 17;; along with GCC; see the file COPYING3. If not see 18;; <http://www.gnu.org/licenses/>. 19 20;; Conversion to C++11 memory model based on 21;; http://www.cl.cam.ac.uk/~pes20/cpp/cpp0xmappings.html 22 23(define_mode_iterator IMODE [QI HI SI DI]) 24(define_mode_iterator I124MODE [QI HI SI]) 25(define_mode_iterator I48MODE [SI DI]) 26(define_mode_attr modesuffix [(QI "1") (HI "2") (SI "4") (DI "8")]) 27 28(define_code_iterator FETCHOP [plus minus ior xor and]) 29(define_code_attr fetchop_name 30 [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")]) 31 32(define_expand "mem_thread_fence" 33 [(match_operand:SI 0 "const_int_operand" "")] ;; model 34 "" 35{ 36 if (INTVAL (operands[0]) == MEMMODEL_SEQ_CST) 37 emit_insn (gen_memory_barrier ()); 38 DONE; 39}) 40 41(define_expand "memory_barrier" 42 [(set (match_dup 0) 43 (unspec:BLK [(match_dup 0)] UNSPEC_MF))] 44 "" 45{ 46 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); 47 MEM_VOLATILE_P (operands[0]) = 1; 48}) 49 50(define_insn "*memory_barrier" 51 [(set (match_operand:BLK 0 "" "") 52 (unspec:BLK [(match_dup 0)] UNSPEC_MF))] 53 "" 54 "mf" 55 [(set_attr "itanium_class" "syst_m")]) 56 57(define_expand "atomic_load<mode>" 58 [(match_operand:IMODE 0 "gr_register_operand" "") ;; output 59 (match_operand:IMODE 1 "memory_operand" "") ;; memory 60 (match_operand:SI 2 "const_int_operand" "")] ;; model 61 "" 62{ 63 enum memmodel model = (enum memmodel) INTVAL (operands[2]); 64 65 /* Unless the memory model is relaxed, we want to emit ld.acq, which 66 will happen automatically for volatile memories. */ 67 gcc_assert (model == MEMMODEL_RELAXED || MEM_VOLATILE_P (operands[1])); 68 emit_move_insn (operands[0], operands[1]); 69 DONE; 70}) 71 72(define_expand "atomic_store<mode>" 73 [(match_operand:IMODE 0 "memory_operand" "") ;; memory 74 (match_operand:IMODE 1 "gr_reg_or_0_operand" "") ;; input 75 (match_operand:SI 2 "const_int_operand" "")] ;; model 76 "" 77{ 78 enum memmodel model = (enum memmodel) INTVAL (operands[2]); 79 80 /* Unless the memory model is relaxed, we want to emit st.rel, which 81 will happen automatically for volatile memories. */ 82 gcc_assert (model == MEMMODEL_RELAXED || MEM_VOLATILE_P (operands[0])); 83 emit_move_insn (operands[0], operands[1]); 84 85 /* Sequentially consistent stores need a subsequent MF. See 86 http://www.decadent.org.uk/pipermail/cpp-threads/2008-December/001952.html 87 for a discussion of why a MF is needed here, but not for atomic_load. */ 88 if (model == MEMMODEL_SEQ_CST) 89 emit_insn (gen_memory_barrier ()); 90 DONE; 91}) 92 93(define_expand "atomic_compare_and_swap<mode>" 94 [(match_operand:DI 0 "gr_register_operand" "") ;; bool out 95 (match_operand:IMODE 1 "gr_register_operand" "") ;; val out 96 (match_operand:IMODE 2 "not_postinc_memory_operand" "") ;; memory 97 (match_operand:IMODE 3 "gr_register_operand" "") ;; expected 98 (match_operand:IMODE 4 "gr_reg_or_0_operand" "") ;; desired 99 (match_operand:SI 5 "const_int_operand" "") ;; is_weak 100 (match_operand:SI 6 "const_int_operand" "") ;; succ model 101 (match_operand:SI 7 "const_int_operand" "")] ;; fail model 102 "" 103{ 104 enum memmodel model = (enum memmodel) INTVAL (operands[6]); 105 rtx ccv = gen_rtx_REG (DImode, AR_CCV_REGNUM); 106 rtx dval, eval; 107 108 eval = gen_reg_rtx (DImode); 109 convert_move (eval, operands[3], 1); 110 emit_move_insn (ccv, eval); 111 112 if (<MODE>mode == DImode) 113 dval = operands[1]; 114 else 115 dval = gen_reg_rtx (DImode); 116 117 switch (model) 118 { 119 case MEMMODEL_RELAXED: 120 case MEMMODEL_ACQUIRE: 121 case MEMMODEL_CONSUME: 122 emit_insn (gen_cmpxchg_acq_<mode> (dval, operands[2], ccv, operands[4])); 123 break; 124 case MEMMODEL_RELEASE: 125 emit_insn (gen_cmpxchg_rel_<mode> (dval, operands[2], ccv, operands[4])); 126 break; 127 case MEMMODEL_ACQ_REL: 128 case MEMMODEL_SEQ_CST: 129 emit_insn (gen_cmpxchg_rel_<mode> (dval, operands[2], ccv, operands[4])); 130 emit_insn (gen_memory_barrier ()); 131 break; 132 default: 133 gcc_unreachable (); 134 } 135 136 if (<MODE>mode != DImode) 137 emit_move_insn (operands[1], gen_lowpart (<MODE>mode, dval)); 138 139 emit_insn (gen_cstoredi4 (operands[0], gen_rtx_EQ (DImode, dval, eval), 140 dval, eval)); 141 DONE; 142}) 143 144(define_insn "cmpxchg_acq_<mode>" 145 [(set (match_operand:DI 0 "gr_register_operand" "=r") 146 (zero_extend:DI 147 (match_operand:I124MODE 1 "not_postinc_memory_operand" "+S"))) 148 (set (match_dup 1) 149 (unspec:I124MODE 150 [(match_dup 1) 151 (match_operand:DI 2 "ar_ccv_reg_operand" "") 152 (match_operand:I124MODE 3 "gr_reg_or_0_operand" "rO")] 153 UNSPEC_CMPXCHG_ACQ))] 154 "" 155 "cmpxchg<modesuffix>.acq %0 = %1, %r3, %2" 156 [(set_attr "itanium_class" "sem")]) 157 158(define_insn "cmpxchg_rel_<mode>" 159 [(set (match_operand:DI 0 "gr_register_operand" "=r") 160 (zero_extend:DI 161 (match_operand:I124MODE 1 "not_postinc_memory_operand" "+S"))) 162 (set (match_dup 1) 163 (unspec:I124MODE 164 [(match_dup 1) 165 (match_operand:DI 2 "ar_ccv_reg_operand" "") 166 (match_operand:I124MODE 3 "gr_reg_or_0_operand" "rO")] 167 UNSPEC_CMPXCHG_REL))] 168 "" 169 "cmpxchg<modesuffix>.rel %0 = %1, %r3, %2" 170 [(set_attr "itanium_class" "sem")]) 171 172(define_insn "cmpxchg_acq_di" 173 [(set (match_operand:DI 0 "gr_register_operand" "=r") 174 (match_operand:DI 1 "not_postinc_memory_operand" "+S")) 175 (set (match_dup 1) 176 (unspec:DI [(match_dup 1) 177 (match_operand:DI 2 "ar_ccv_reg_operand" "") 178 (match_operand:DI 3 "gr_reg_or_0_operand" "rO")] 179 UNSPEC_CMPXCHG_ACQ))] 180 "" 181 "cmpxchg8.acq %0 = %1, %r3, %2" 182 [(set_attr "itanium_class" "sem")]) 183 184(define_insn "cmpxchg_rel_di" 185 [(set (match_operand:DI 0 "gr_register_operand" "=r") 186 (match_operand:DI 1 "not_postinc_memory_operand" "+S")) 187 (set (match_dup 1) 188 (unspec:DI [(match_dup 1) 189 (match_operand:DI 2 "ar_ccv_reg_operand" "") 190 (match_operand:DI 3 "gr_reg_or_0_operand" "rO")] 191 UNSPEC_CMPXCHG_REL))] 192 "" 193 "cmpxchg8.rel %0 = %1, %r3, %2" 194 [(set_attr "itanium_class" "sem")]) 195 196(define_expand "atomic_exchange<mode>" 197 [(match_operand:IMODE 0 "gr_register_operand" "") ;; output 198 (match_operand:IMODE 1 "not_postinc_memory_operand" "") ;; memory 199 (match_operand:IMODE 2 "gr_reg_or_0_operand" "") ;; input 200 (match_operand:SI 3 "const_int_operand" "")] ;; succ model 201 "" 202{ 203 enum memmodel model = (enum memmodel) INTVAL (operands[3]); 204 205 switch (model) 206 { 207 case MEMMODEL_RELAXED: 208 case MEMMODEL_ACQUIRE: 209 case MEMMODEL_CONSUME: 210 break; 211 case MEMMODEL_RELEASE: 212 case MEMMODEL_ACQ_REL: 213 case MEMMODEL_SEQ_CST: 214 emit_insn (gen_memory_barrier ()); 215 break; 216 default: 217 gcc_unreachable (); 218 } 219 emit_insn (gen_xchg_acq_<mode> (operands[0], operands[1], operands[2])); 220 DONE; 221}) 222 223;; Note that XCHG is always memory model acquire. 224(define_insn "xchg_acq_<mode>" 225 [(set (match_operand:IMODE 0 "gr_register_operand" "=r") 226 (match_operand:IMODE 1 "not_postinc_memory_operand" "+S")) 227 (set (match_dup 1) 228 (match_operand:IMODE 2 "gr_reg_or_0_operand" "rO"))] 229 "" 230 "xchg<modesuffix> %0 = %1, %r2" 231 [(set_attr "itanium_class" "sem")]) 232 233(define_expand "atomic_<fetchop_name><mode>" 234 [(set (match_operand:IMODE 0 "memory_operand" "") 235 (FETCHOP:IMODE (match_dup 0) 236 (match_operand:IMODE 1 "nonmemory_operand" ""))) 237 (use (match_operand:SI 2 "const_int_operand" ""))] 238 "" 239{ 240 ia64_expand_atomic_op (<CODE>, operands[0], operands[1], NULL, NULL, 241 (enum memmodel) INTVAL (operands[2])); 242 DONE; 243}) 244 245(define_expand "atomic_nand<mode>" 246 [(set (match_operand:IMODE 0 "memory_operand" "") 247 (not:IMODE 248 (and:IMODE (match_dup 0) 249 (match_operand:IMODE 1 "nonmemory_operand" "")))) 250 (use (match_operand:SI 2 "const_int_operand" ""))] 251 "" 252{ 253 ia64_expand_atomic_op (NOT, operands[0], operands[1], NULL, NULL, 254 (enum memmodel) INTVAL (operands[2])); 255 DONE; 256}) 257 258(define_expand "atomic_fetch_<fetchop_name><mode>" 259 [(set (match_operand:IMODE 0 "gr_register_operand" "") 260 (FETCHOP:IMODE 261 (match_operand:IMODE 1 "memory_operand" "") 262 (match_operand:IMODE 2 "nonmemory_operand" ""))) 263 (use (match_operand:SI 3 "const_int_operand" ""))] 264 "" 265{ 266 ia64_expand_atomic_op (<CODE>, operands[1], operands[2], operands[0], NULL, 267 (enum memmodel) INTVAL (operands[3])); 268 DONE; 269}) 270 271(define_expand "atomic_fetch_nand<mode>" 272 [(set (match_operand:IMODE 0 "gr_register_operand" "") 273 (not:IMODE 274 (and:IMODE (match_operand:IMODE 1 "memory_operand" "") 275 (match_operand:IMODE 2 "nonmemory_operand" "")))) 276 (use (match_operand:SI 3 "const_int_operand" ""))] 277 "" 278{ 279 ia64_expand_atomic_op (NOT, operands[1], operands[2], operands[0], NULL, 280 (enum memmodel) INTVAL (operands[3])); 281 DONE; 282}) 283 284(define_expand "atomic_<fetchop_name>_fetch<mode>" 285 [(set (match_operand:IMODE 0 "gr_register_operand" "") 286 (FETCHOP:IMODE 287 (match_operand:IMODE 1 "memory_operand" "") 288 (match_operand:IMODE 2 "nonmemory_operand" ""))) 289 (use (match_operand:SI 3 "const_int_operand" ""))] 290 "" 291{ 292 ia64_expand_atomic_op (<CODE>, operands[1], operands[2], NULL, operands[0], 293 (enum memmodel) INTVAL (operands[3])); 294 DONE; 295}) 296 297(define_expand "atomic_nand_fetch<mode>" 298 [(set (match_operand:IMODE 0 "gr_register_operand" "") 299 (not:IMODE 300 (and:IMODE (match_operand:IMODE 1 "memory_operand" "") 301 (match_operand:IMODE 2 "nonmemory_operand" "")))) 302 (use (match_operand:SI 3 "const_int_operand" ""))] 303 "" 304{ 305 ia64_expand_atomic_op (NOT, operands[1], operands[2], NULL, operands[0], 306 (enum memmodel) INTVAL (operands[3])); 307 DONE; 308}) 309 310(define_insn "fetchadd_acq_<mode>" 311 [(set (match_operand:I48MODE 0 "gr_register_operand" "=r") 312 (match_operand:I48MODE 1 "not_postinc_memory_operand" "+S")) 313 (set (match_dup 1) 314 (unspec:I48MODE [(match_dup 1) 315 (match_operand:I48MODE 2 "fetchadd_operand" "n")] 316 UNSPEC_FETCHADD_ACQ))] 317 "" 318 "fetchadd<modesuffix>.acq %0 = %1, %2" 319 [(set_attr "itanium_class" "sem")]) 320 321(define_insn "fetchadd_rel_<mode>" 322 [(set (match_operand:I48MODE 0 "gr_register_operand" "=r") 323 (match_operand:I48MODE 1 "not_postinc_memory_operand" "+S")) 324 (set (match_dup 1) 325 (unspec:I48MODE [(match_dup 1) 326 (match_operand:I48MODE 2 "fetchadd_operand" "n")] 327 UNSPEC_FETCHADD_REL))] 328 "" 329 "fetchadd<modesuffix>.rel %0 = %1, %2" 330 [(set_attr "itanium_class" "sem")]) 331