1;; GCC machine description for Alpha synchronization instructions. 2;; Copyright (C) 2005-2018 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(define_code_iterator FETCHOP [plus minus ior xor and]) 21(define_code_attr fetchop_name 22 [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")]) 23(define_code_attr fetchop_pred 24 [(plus "add_operand") (minus "reg_or_8bit_operand") 25 (ior "or_operand") (xor "or_operand") (and "and_operand")]) 26(define_code_attr fetchop_constr 27 [(plus "rKL") (minus "rI") (ior "rIN") (xor "rIN") (and "rINM")]) 28 29 30(define_expand "memory_barrier" 31 [(set (match_dup 0) 32 (unspec:BLK [(match_dup 0)] UNSPEC_MB))] 33 "" 34{ 35 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); 36 MEM_VOLATILE_P (operands[0]) = 1; 37}) 38 39(define_insn "*memory_barrier" 40 [(set (match_operand:BLK 0) 41 (unspec:BLK [(match_dup 0)] UNSPEC_MB))] 42 "" 43 "mb" 44 [(set_attr "type" "mb")]) 45 46(define_insn "load_locked_<mode>" 47 [(set (match_operand:I48MODE 0 "register_operand" "=r") 48 (unspec_volatile:I48MODE 49 [(match_operand:I48MODE 1 "memory_operand" "m")] 50 UNSPECV_LL))] 51 "" 52 "ld<modesuffix>_l %0,%1" 53 [(set_attr "type" "ld_l")]) 54 55(define_insn "store_conditional_<mode>" 56 [(set (match_operand:DI 0 "register_operand" "=r") 57 (unspec_volatile:DI [(const_int 0)] UNSPECV_SC)) 58 (set (match_operand:I48MODE 1 "memory_operand" "=m") 59 (match_operand:I48MODE 2 "reg_or_0_operand" "0"))] 60 "" 61 "st<modesuffix>_c %0,%1" 62 [(set_attr "type" "st_c")]) 63 64;; The Alpha Architecture Handbook says that it is UNPREDICTABLE whether 65;; the lock is cleared by a normal load or store. This means we cannot 66;; expand a ll/sc sequence before reload, lest a register spill is 67;; inserted inside the sequence. It is also UNPREDICTABLE whether the 68;; lock is cleared by a TAKEN branch. This means that we can not expand 69;; a ll/sc sequence containing a branch (i.e. compare-and-swap) until after 70;; the final basic-block reordering pass. 71 72(define_expand "atomic_compare_and_swap<mode>" 73 [(parallel 74 [(set (match_operand:DI 0 "register_operand") ;; bool out 75 (unspec_volatile:DI [(const_int 0)] UNSPECV_CMPXCHG)) 76 (set (match_operand:I48MODE 1 "register_operand") ;; val out 77 (unspec_volatile:I48MODE [(const_int 0)] UNSPECV_CMPXCHG)) 78 (set (match_operand:I48MODE 2 "memory_operand") ;; memory 79 (unspec_volatile:I48MODE 80 [(match_dup 2) 81 (match_operand:I48MODE 3 "reg_or_8bit_operand") ;; expected 82 (match_operand:I48MODE 4 "add_operand") ;; desired 83 (match_operand:SI 5 "const_int_operand") ;; is_weak 84 (match_operand:SI 6 "const_int_operand") ;; succ model 85 (match_operand:SI 7 "const_int_operand")] ;; fail model 86 UNSPECV_CMPXCHG))])] 87 "" 88{ 89 if (<MODE>mode == SImode) 90 { 91 operands[3] = convert_modes (DImode, SImode, operands[3], 0); 92 operands[4] = convert_modes (DImode, SImode, operands[4], 0); 93 } 94}) 95 96(define_insn_and_split "*atomic_compare_and_swap<mode>" 97 [(set (match_operand:DI 0 "register_operand" "=&r") ;; bool out 98 (unspec_volatile:DI [(const_int 0)] UNSPECV_CMPXCHG)) 99 (set (match_operand:I48MODE 1 "register_operand" "=&r") ;; val out 100 (unspec_volatile:I48MODE [(const_int 0)] UNSPECV_CMPXCHG)) 101 (set (match_operand:I48MODE 2 "memory_operand" "+m") ;; memory 102 (unspec_volatile:I48MODE 103 [(match_dup 2) 104 (match_operand:DI 3 "reg_or_8bit_operand" "rI") ;; expected 105 (match_operand:DI 4 "add_operand" "rKL") ;; desired 106 (match_operand:SI 5 "const_int_operand") ;; is_weak 107 (match_operand:SI 6 "const_int_operand") ;; succ model 108 (match_operand:SI 7 "const_int_operand")] ;; fail model 109 UNSPECV_CMPXCHG))] 110 "" 111 "#" 112 "epilogue_completed" 113 [(const_int 0)] 114{ 115 alpha_split_compare_and_swap (operands); 116 DONE; 117} 118 [(set_attr "type" "multi")]) 119 120(define_expand "atomic_compare_and_swap<mode>" 121 [(match_operand:DI 0 "register_operand") ;; bool out 122 (match_operand:I12MODE 1 "register_operand") ;; val out 123 (match_operand:I12MODE 2 "mem_noofs_operand") ;; memory 124 (match_operand:I12MODE 3 "register_operand") ;; expected 125 (match_operand:I12MODE 4 "add_operand") ;; desired 126 (match_operand:SI 5 "const_int_operand") ;; is_weak 127 (match_operand:SI 6 "const_int_operand") ;; succ model 128 (match_operand:SI 7 "const_int_operand")] ;; fail model 129 "" 130{ 131 alpha_expand_compare_and_swap_12 (operands); 132 DONE; 133}) 134 135(define_insn_and_split "atomic_compare_and_swap<mode>_1" 136 [(set (match_operand:DI 0 "register_operand" "=&r") ;; bool out 137 (unspec_volatile:DI [(const_int 0)] UNSPECV_CMPXCHG)) 138 (set (match_operand:DI 1 "register_operand" "=&r") ;; val out 139 (zero_extend:DI 140 (unspec_volatile:I12MODE [(const_int 0)] UNSPECV_CMPXCHG))) 141 (set (match_operand:I12MODE 2 "mem_noofs_operand" "+w") ;; memory 142 (unspec_volatile:I12MODE 143 [(match_dup 2) 144 (match_operand:DI 3 "reg_or_8bit_operand" "rI") ;; expected 145 (match_operand:DI 4 "reg_or_0_operand" "rJ") ;; desired 146 (match_operand:DI 5 "register_operand" "r") ;; align 147 (match_operand:SI 6 "const_int_operand") ;; is_weak 148 (match_operand:SI 7 "const_int_operand") ;; succ model 149 (match_operand:SI 8 "const_int_operand")] ;; fail model 150 UNSPECV_CMPXCHG)) 151 (clobber (match_scratch:DI 9 "=&r"))] 152 "" 153 "#" 154 "epilogue_completed" 155 [(const_int 0)] 156{ 157 alpha_split_compare_and_swap_12 (operands); 158 DONE; 159} 160 [(set_attr "type" "multi")]) 161 162(define_insn_and_split "atomic_exchange<mode>" 163 [(set (match_operand:I48MODE 0 "register_operand" "=&r") ;; output 164 (match_operand:I48MODE 1 "memory_operand" "+m")) ;; memory 165 (set (match_dup 1) 166 (unspec:I48MODE 167 [(match_operand:I48MODE 2 "add_operand" "rKL") ;; input 168 (match_operand:SI 3 "const_int_operand")] ;; model 169 UNSPEC_XCHG)) 170 (clobber (match_scratch:I48MODE 4 "=&r"))] 171 "" 172 "#" 173 "epilogue_completed" 174 [(const_int 0)] 175{ 176 alpha_split_atomic_exchange (operands); 177 DONE; 178} 179 [(set_attr "type" "multi")]) 180 181(define_expand "atomic_exchange<mode>" 182 [(match_operand:I12MODE 0 "register_operand") ;; output 183 (match_operand:I12MODE 1 "mem_noofs_operand") ;; memory 184 (match_operand:I12MODE 2 "reg_or_0_operand") ;; input 185 (match_operand:SI 3 "const_int_operand")] ;; model 186 "" 187{ 188 alpha_expand_atomic_exchange_12 (operands); 189 DONE; 190}) 191 192(define_insn_and_split "atomic_exchange<mode>_1" 193 [(set (match_operand:DI 0 "register_operand" "=&r") ;; output 194 (zero_extend:DI 195 (match_operand:I12MODE 1 "mem_noofs_operand" "+w"))) ;; memory 196 (set (match_dup 1) 197 (unspec:I12MODE 198 [(match_operand:DI 2 "reg_or_8bit_operand" "rI") ;; input 199 (match_operand:DI 3 "register_operand" "r") ;; align 200 (match_operand:SI 4 "const_int_operand")] ;; model 201 UNSPEC_XCHG)) 202 (clobber (match_scratch:DI 5 "=&r"))] 203 "" 204 "#" 205 "epilogue_completed" 206 [(const_int 0)] 207{ 208 alpha_split_atomic_exchange_12 (operands); 209 DONE; 210} 211 [(set_attr "type" "multi")]) 212 213(define_insn_and_split "atomic_<fetchop_name><mode>" 214 [(set (match_operand:I48MODE 0 "memory_operand" "+m") 215 (unspec:I48MODE 216 [(FETCHOP:I48MODE (match_dup 0) 217 (match_operand:I48MODE 1 "<fetchop_pred>" "<fetchop_constr>")) 218 (match_operand:SI 2 "const_int_operand")] 219 UNSPEC_ATOMIC)) 220 (clobber (match_scratch:I48MODE 3 "=&r"))] 221 "" 222 "#" 223 "epilogue_completed" 224 [(const_int 0)] 225{ 226 alpha_split_atomic_op (<CODE>, operands[0], operands[1], 227 NULL, NULL, operands[3], 228 (enum memmodel) INTVAL (operands[2])); 229 DONE; 230} 231 [(set_attr "type" "multi")]) 232 233(define_insn_and_split "atomic_nand<mode>" 234 [(set (match_operand:I48MODE 0 "memory_operand" "+m") 235 (unspec:I48MODE 236 [(not:I48MODE 237 (and:I48MODE (match_dup 0) 238 (match_operand:I48MODE 1 "register_operand" "r"))) 239 (match_operand:SI 2 "const_int_operand")] 240 UNSPEC_ATOMIC)) 241 (clobber (match_scratch:I48MODE 3 "=&r"))] 242 "" 243 "#" 244 "epilogue_completed" 245 [(const_int 0)] 246{ 247 alpha_split_atomic_op (NOT, operands[0], operands[1], 248 NULL, NULL, operands[3], 249 (enum memmodel) INTVAL (operands[2])); 250 DONE; 251} 252 [(set_attr "type" "multi")]) 253 254(define_insn_and_split "atomic_fetch_<fetchop_name><mode>" 255 [(set (match_operand:I48MODE 0 "register_operand" "=&r") 256 (match_operand:I48MODE 1 "memory_operand" "+m")) 257 (set (match_dup 1) 258 (unspec:I48MODE 259 [(FETCHOP:I48MODE (match_dup 1) 260 (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>")) 261 (match_operand:SI 3 "const_int_operand")] 262 UNSPEC_ATOMIC)) 263 (clobber (match_scratch:I48MODE 4 "=&r"))] 264 "" 265 "#" 266 "epilogue_completed" 267 [(const_int 0)] 268{ 269 alpha_split_atomic_op (<CODE>, operands[1], operands[2], 270 operands[0], NULL, operands[4], 271 (enum memmodel) INTVAL (operands[3])); 272 DONE; 273} 274 [(set_attr "type" "multi")]) 275 276(define_insn_and_split "atomic_fetch_nand<mode>" 277 [(set (match_operand:I48MODE 0 "register_operand" "=&r") 278 (match_operand:I48MODE 1 "memory_operand" "+m")) 279 (set (match_dup 1) 280 (unspec:I48MODE 281 [(not:I48MODE 282 (and:I48MODE (match_dup 1) 283 (match_operand:I48MODE 2 "register_operand" "r"))) 284 (match_operand:SI 3 "const_int_operand")] 285 UNSPEC_ATOMIC)) 286 (clobber (match_scratch:I48MODE 4 "=&r"))] 287 "" 288 "#" 289 "epilogue_completed" 290 [(const_int 0)] 291{ 292 alpha_split_atomic_op (NOT, operands[1], operands[2], 293 operands[0], NULL, operands[4], 294 (enum memmodel) INTVAL (operands[3])); 295 DONE; 296} 297 [(set_attr "type" "multi")]) 298 299(define_insn_and_split "atomic_<fetchop_name>_fetch<mode>" 300 [(set (match_operand:I48MODE 0 "register_operand" "=&r") 301 (FETCHOP:I48MODE 302 (match_operand:I48MODE 1 "memory_operand" "+m") 303 (match_operand:I48MODE 2 "<fetchop_pred>" "<fetchop_constr>"))) 304 (set (match_dup 1) 305 (unspec:I48MODE 306 [(FETCHOP:I48MODE (match_dup 1) (match_dup 2)) 307 (match_operand:SI 3 "const_int_operand")] 308 UNSPEC_ATOMIC)) 309 (clobber (match_scratch:I48MODE 4 "=&r"))] 310 "" 311 "#" 312 "epilogue_completed" 313 [(const_int 0)] 314{ 315 alpha_split_atomic_op (<CODE>, operands[1], operands[2], 316 NULL, operands[0], operands[4], 317 (enum memmodel) INTVAL (operands[3])); 318 DONE; 319} 320 [(set_attr "type" "multi")]) 321 322(define_insn_and_split "atomic_nand_fetch<mode>" 323 [(set (match_operand:I48MODE 0 "register_operand" "=&r") 324 (not:I48MODE 325 (and:I48MODE (match_operand:I48MODE 1 "memory_operand" "+m") 326 (match_operand:I48MODE 2 "register_operand" "r")))) 327 (set (match_dup 1) 328 (unspec:I48MODE 329 [(not:I48MODE (and:I48MODE (match_dup 1) (match_dup 2))) 330 (match_operand:SI 3 "const_int_operand")] 331 UNSPEC_ATOMIC)) 332 (clobber (match_scratch:I48MODE 4 "=&r"))] 333 "" 334 "#" 335 "epilogue_completed" 336 [(const_int 0)] 337{ 338 alpha_split_atomic_op (NOT, operands[1], operands[2], 339 NULL, operands[0], operands[4], 340 (enum memmodel) INTVAL (operands[3])); 341 DONE; 342} 343 [(set_attr "type" "multi")]) 344