1;; GCC machine description for ARC atomic instructions. 2;; Copyright (C) 2015-2020 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_mode_iterator QHSI [QI HI SI]) 21(define_code_iterator atomicop [plus minus ior xor and]) 22(define_code_attr atomic_optab 23 [(ior "or") (xor "xor") (and "and") (plus "add") (minus "sub")]) 24 25(define_expand "memory_barrier" 26 [(set (match_dup 0) 27 (unspec:BLK [(match_dup 0)] UNSPEC_ARC_MEMBAR))] 28 "" 29{ 30 operands[0] = gen_rtx_MEM (BLKmode, gen_rtx_SCRATCH (Pmode)); 31 MEM_VOLATILE_P (operands[0]) = 1; 32}) 33 34;; A compiler-only memory barrier for ARC700. Generic code, when 35;; checking for the existence of various named patterns, uses 36;; asm("":::"memory") when we don't need an actual instruction. For 37;; ARCHS, we use a hardware data memory barrier that waits for 38;; completion of current data memory operations before initiating 39;; similar data memory operations. 40(define_insn "*memory_barrier" 41 [(set (match_operand:BLK 0 "" "") 42 (unspec:BLK [(match_dup 0)] UNSPEC_ARC_MEMBAR))] 43 "" 44 { 45 if (TARGET_HS) 46 { 47 return "dmb\\t3"; 48 } 49 else 50 { 51 return ""; 52 } 53 } 54 [(set_attr "type" "multi") 55 (set_attr "length" "4")]) 56 57(define_expand "atomic_compare_and_swap<mode>" 58 [(match_operand:SI 0 "register_operand" "") ;; bool out 59 (match_operand:QHSI 1 "register_operand" "") ;; val out 60 (match_operand:QHSI 2 "mem_noofs_operand" "");; memory 61 (match_operand:QHSI 3 "register_operand" "") ;; expected 62 (match_operand:QHSI 4 "register_operand" "") ;; desired 63 (match_operand:SI 5 "const_int_operand") ;; is_weak 64 (match_operand:SI 6 "const_int_operand") ;; mod_s 65 (match_operand:SI 7 "const_int_operand")] ;; mod_f 66 "TARGET_ATOMIC" 67{ 68 arc_expand_compare_and_swap (operands); 69 DONE; 70}) 71 72(define_insn_and_split "atomic_compare_and_swapsi_1" 73 [(set (reg:CC_Z CC_REG) ;; bool out 74 (unspec_volatile:CC_Z [(const_int 0)] VUNSPEC_ARC_CAS)) 75 (set (match_operand:SI 0 "register_operand" "=&r") ;; val out 76 (match_operand:SI 1 "mem_noofs_operand" "+ATO")) ;; memory 77 (set (match_dup 1) 78 (unspec_volatile:SI 79 [(match_operand:SI 2 "register_operand" "r") ;; expect 80 (match_operand:SI 3 "register_operand" "r") ;; desired 81 (match_operand:SI 4 "const_int_operand") ;; is_weak 82 (match_operand:SI 5 "const_int_operand") ;; mod_s 83 (match_operand:SI 6 "const_int_operand")] ;; mod_f 84 VUNSPEC_ARC_CAS))] 85 "TARGET_ATOMIC" 86 "#" 87 "&& reload_completed" 88 [(const_int 0)] 89 { 90 arc_split_compare_and_swap (operands); 91 DONE; 92 }) 93 94(define_insn "arc_load_exclusivesi" 95 [(set (match_operand:SI 0 "register_operand" "=r") 96 (unspec_volatile:SI 97 [(match_operand:SI 1 "mem_noofs_operand" "ATO")] 98 VUNSPEC_ARC_LL))] 99 "TARGET_ATOMIC" 100 "llock %0,%1" 101 [(set_attr "type" "load") 102 (set_attr "iscompact" "false") 103 (set_attr "predicable" "no") 104 (set_attr "length" "*")]) 105 106(define_insn "arc_store_exclusivesi" 107 [(set (match_operand:SI 0 "mem_noofs_operand" "=ATO") 108 (unspec_volatile:SI[(match_operand:SI 1 "register_operand" "r")] 109 VUNSPEC_ARC_SC)) 110 (clobber (reg:CC_Z CC_REG))] 111 "TARGET_ATOMIC" 112 "scond %1,%0" 113 [(set_attr "type" "store") 114 (set_attr "iscompact" "false") 115 (set_attr "predicable" "no") 116 (set_attr "length" "*")]) 117 118(define_expand "atomic_exchangesi" 119 [(match_operand:SI 0 "register_operand" "") 120 (match_operand:SI 1 "mem_noofs_operand" "") 121 (match_operand:SI 2 "register_operand" "") 122 (match_operand:SI 3 "const_int_operand" "")] 123 "TARGET_ARC700 || TARGET_V2" 124{ 125 enum memmodel model = (enum memmodel) INTVAL (operands[3]); 126 127 if (model == MEMMODEL_SEQ_CST) 128 emit_insn (gen_sync (const1_rtx)); 129 emit_insn (gen_exchangesi (operands[0], operands[1], operands[2])); 130 DONE; 131}) 132 133(define_insn "exchangesi" 134 [(set (match_operand:SI 0 "register_operand" "=r") 135 (unspec_volatile:SI [(match_operand:SI 1 "mem_noofs_operand" "+ATO")] 136 VUNSPEC_ARC_EX)) 137 (set (match_dup 1) 138 (match_operand:SI 2 "register_operand" "0"))] 139 "" 140 "ex %0,%1" 141 [(set_attr "type" "load") 142 (set_attr "iscompact" "false") 143 (set_attr "predicable" "no") 144 (set_attr "length" "*")]) 145 146(define_expand "atomic_<atomic_optab>si" 147 [(match_operand:SI 0 "mem_noofs_operand" "") ;; memory 148 (atomicop:SI (match_dup 0) 149 (match_operand:SI 1 "register_operand" "")) ;; operand 150 (match_operand:SI 2 "const_int_operand" "")] ;; model 151 "TARGET_ATOMIC" 152{ 153 arc_expand_atomic_op (<CODE>, operands[0], operands[1], 154 NULL_RTX, NULL_RTX, operands[2]); 155 DONE; 156}) 157 158(define_expand "atomic_nandsi" 159 [(match_operand:SI 0 "mem_noofs_operand" "") ;; memory 160 (match_operand:SI 1 "register_operand" "") ;; operand 161 (match_operand:SI 2 "const_int_operand" "")] ;; model 162 "TARGET_ATOMIC" 163{ 164 arc_expand_atomic_op (NOT, operands[0], operands[1], 165 NULL_RTX, NULL_RTX, operands[2]); 166 DONE; 167}) 168 169(define_expand "atomic_fetch_<atomic_optab>si" 170 [(match_operand:SI 0 "register_operand" "") ;; output 171 (match_operand:SI 1 "mem_noofs_operand" "") ;; memory 172 (atomicop:SI (match_dup 1) 173 (match_operand:SI 2 "register_operand" "")) ;; operand 174 (match_operand:SI 3 "const_int_operand" "")] ;; model 175 "TARGET_ATOMIC" 176{ 177 arc_expand_atomic_op (<CODE>, operands[1], operands[2], 178 operands[0], NULL_RTX, operands[3]); 179 DONE; 180}) 181 182(define_expand "atomic_fetch_nandsi" 183 [(match_operand:SI 0 "register_operand" "") ;; output 184 (match_operand:SI 1 "mem_noofs_operand" "") ;; memory 185 (match_operand:SI 2 "register_operand" "") ;; operand 186 (match_operand:SI 3 "const_int_operand" "")] ;; model 187 "TARGET_ATOMIC" 188{ 189 arc_expand_atomic_op (NOT, operands[1], operands[2], 190 operands[0], NULL_RTX, operands[3]); 191 DONE; 192}) 193 194(define_expand "atomic_<atomic_optab>_fetchsi" 195 [(match_operand:SI 0 "register_operand" "") ;; output 196 (match_operand:SI 1 "mem_noofs_operand" "") ;; memory 197 (atomicop:SI (match_dup 1) 198 (match_operand:SI 2 "register_operand" "")) ;; operand 199 (match_operand:SI 3 "const_int_operand" "")] ;; model 200 "TARGET_ATOMIC" 201{ 202 arc_expand_atomic_op (<CODE>, operands[1], operands[2], 203 NULL_RTX, operands[0], operands[3]); 204 DONE; 205}) 206 207(define_expand "atomic_nand_fetchsi" 208 [(match_operand:SI 0 "register_operand" "") ;; output 209 (match_operand:SI 1 "mem_noofs_operand" "") ;; memory 210 (match_operand:SI 2 "register_operand" "") ;; operand 211 (match_operand:SI 3 "const_int_operand" "")] ;; model 212 "TARGET_ATOMIC" 213{ 214 arc_expand_atomic_op (NOT, operands[1], operands[2], 215 NULL_RTX, operands[0], operands[3]); 216 DONE; 217}) 218 219