1;; GCC machine description for C6X synchronization instructions. 2;; Copyright (C) 2011-2022 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;; C64X+ has atomic instructions, but they are not atomic on all 21;; devices and have other problems. We use normal loads and stores, 22;; and place them in overlapping branch shadows to ensure interrupts 23;; are disabled during the sequence, which guarantees atomicity on all 24;; single-core systems. 25 26(define_code_iterator FETCHOP [plus minus ior xor and]) 27(define_code_attr fetchop_name 28 [(plus "add") (minus "sub") (ior "ior") (xor "xor") (and "and")]) 29(define_code_attr fetchop_pred 30 [(plus "reg_or_scst5_operand") (minus "register_operand") 31 (ior "reg_or_scst5_operand") (xor "reg_or_scst5_operand") 32 (and "reg_or_scst5_operand")]) 33(define_code_attr fetchop_constr 34 [(plus "bIs5") (minus "b") (ior "bIs5") (xor "bIs5") (and "bIs5")]) 35(define_code_attr fetchop_opcode 36 [(plus "add") (minus "sub") (ior "or") (xor "xor") (and "and")]) 37(define_code_attr fetchop_inops02 38 [(plus "%2, %0") (minus "%0, %2") (ior "%2, %0") (xor "%2, %0") 39 (and "%2, %0")]) 40(define_code_attr fetchop_inops21 41 [(plus "%1, %2") (minus "%2, %1") (ior "%1, %2") (xor "%1, %2") 42 (and "%1, %2")]) 43 44(define_expand "sync_compare_and_swapsi" 45 [(parallel 46 [(set (match_operand:SI 0 "register_operand" "") 47 (match_operand:SI 1 "memory_operand" "")) 48 (set (match_dup 1) 49 (unspec_volatile:SI 50 [(match_operand:SI 2 "register_operand" "") 51 (match_operand:SI 3 "register_operand" "")] 52 UNSPECV_CAS)) 53 (clobber (match_scratch:SI 4 ""))])] 54 "" 55{ 56}) 57 58(define_expand "sync_<fetchop_name>si" 59 [(parallel 60 [(set (match_operand:SI 0 "memory_operand" "") 61 (unspec:SI 62 [(FETCHOP:SI (match_dup 0) 63 (match_operand:SI 1 "<fetchop_pred>" ""))] 64 UNSPEC_ATOMIC)) 65 (clobber (match_scratch:SI 2 ""))])] 66 "" 67{ 68}) 69 70(define_expand "sync_old_<fetchop_name>si" 71 [(parallel 72 [(set (match_operand:SI 0 "register_operand" "") 73 (match_operand:SI 1 "memory_operand" "")) 74 (set (match_dup 1) 75 (unspec:SI 76 [(FETCHOP:SI (match_dup 1) 77 (match_operand:SI 2 "<fetchop_pred>" ""))] 78 UNSPEC_ATOMIC)) 79 (clobber (match_scratch:SI 3 ""))])] 80 "" 81{ 82}) 83 84(define_expand "sync_new_<fetchop_name>si" 85 [(parallel 86 [(set (match_operand:SI 0 "register_operand" "") 87 (FETCHOP:SI (match_operand:SI 1 "memory_operand" "") 88 (match_operand:SI 2 "<fetchop_pred>" ""))) 89 (set (match_dup 1) 90 (unspec:SI [(FETCHOP:SI (match_dup 1) (match_dup 2))] 91 UNSPEC_ATOMIC)) 92 (clobber (match_scratch:SI 3 ""))])] 93 "" 94{ 95}) 96 97(define_expand "sync_nandsi" 98 [(parallel 99 [(set (match_operand:SI 0 "memory_operand" "") 100 (unspec:SI 101 [(not:SI (and:SI (match_dup 0) 102 (match_operand:SI 1 "reg_or_scst5_operand" "")))] 103 UNSPEC_ATOMIC)) 104 (clobber (match_scratch:SI 2 ""))])] 105 "" 106{ 107}) 108 109(define_expand "sync_old_nandsi" 110 [(parallel 111 [(set (match_operand:SI 0 "register_operand" "") 112 (match_operand:SI 1 "memory_operand" "")) 113 (set (match_dup 1) 114 (unspec:SI 115 [(not:SI (and:SI (match_dup 1) 116 (match_operand:SI 2 "reg_or_scst5_operand" "")))] 117 UNSPEC_ATOMIC)) 118 (clobber (match_scratch:SI 3 ""))])] 119 "" 120{ 121}) 122 123(define_expand "sync_new_nandsi" 124 [(parallel 125 [(set (match_operand:SI 0 "register_operand" "") 126 (not:SI (and:SI (match_operand:SI 1 "memory_operand" "") 127 (match_operand:SI 2 "reg_or_scst5_operand" "")))) 128 (set (match_dup 1) 129 (unspec:SI [(not:SI (and:SI (match_dup 1) (match_dup 2)))] 130 UNSPEC_ATOMIC)) 131 (clobber (match_scratch:SI 3 ""))])] 132 "" 133{ 134}) 135 136(define_insn "*sync_compare_and_swapsi" 137 [(set (match_operand:SI 0 "register_operand" "=&b") 138 (match_operand:SI 1 "memory_operand" "+m")) 139 (set (match_dup 1) 140 (unspec_volatile:SI 141 [(match_operand:SI 2 "register_operand" "B") 142 (match_operand:SI 3 "register_operand" "b")] 143 UNSPECV_CAS)) 144 (clobber (match_scratch:SI 4 "=&B"))] 145 "" 146 "0: b .s2 1f ; 0\n\\ 147 || ldw .d%U1t%U0 %1, %0\n\\ 148 nop 4\n\\ 149|| b .s2 2f ; 1\n\\ 150 cmpeq .l2 %0, %2, %2 ; 5\n\\ 1511: [%2] stw .d%U1t%U3 %3, %1 ; 6\n\\ 1522:" 153 [(set_attr "type" "atomic")]) 154 155(define_insn "sync_<fetchop_name>si_insn" 156 [(set (match_operand:SI 0 "memory_operand" "+m") 157 (unspec:SI 158 [(FETCHOP:SI (match_dup 0) 159 (match_operand:SI 1 "<fetchop_pred>" "<fetchop_constr>"))] 160 UNSPEC_ATOMIC)) 161 (clobber (match_scratch:SI 2 "=&B"))] 162 "" 163 "0: b .s2 1f ; 0\n\\ 164|| ldw .d%U0t%U2 %0, %2\n\\ 165 nop 4\n\\ 166|| b .s2 2f ; 1\n\\ 167 <fetchop_opcode> .l2 <fetchop_inops21>, %2 ; 5\n\\ 1681: stw .d%U0t%U2 %2, %0 ; 6\n\\ 1692:" 170 [(set_attr "type" "atomic")]) 171 172(define_insn "sync_old_<fetchop_name>si_insn" 173 [(set (match_operand:SI 0 "register_operand" "=&b") 174 (match_operand:SI 1 "memory_operand" "+m")) 175 (set (match_dup 1) 176 (unspec:SI 177 [(FETCHOP:SI (match_dup 1) 178 (match_operand:SI 2 "<fetchop_pred>" "<fetchop_constr>"))] 179 UNSPEC_ATOMIC)) 180 (clobber (match_scratch:SI 3 "=&B"))] 181 "" 182 "0: b .s2 1f ; 0\n\\ 183|| ldw .d%U1t%U0 %1, %0\n\\ 184 nop 4\n\\ 185|| b .s2 2f ; 1\n\\ 186 <fetchop_opcode> .l2 <fetchop_inops02>, %3 ; 5\n\\ 1871: stw .d%U1t%U3 %3, %1 ; 6\n\\ 1882:" 189 [(set_attr "type" "atomic")]) 190 191(define_insn "sync_new_<fetchop_name>si_insn" 192 [(set (match_operand:SI 0 "register_operand" "=&b") 193 (FETCHOP:SI (match_operand:SI 1 "memory_operand" "+m") 194 (match_operand:SI 2 "<fetchop_pred>" "<fetchop_constr>"))) 195 (set (match_dup 1) 196 (unspec:SI 197 [(FETCHOP:SI (match_dup 1) 198 (match_dup 2))] 199 UNSPEC_ATOMIC)) 200 (clobber (match_scratch:SI 3 "=&B"))] 201 "" 202 "0: b .s2 1f ; 0\n\\ 203|| ldw .d%U1t%U0 %1, %0\n\\ 204 nop 4\n\\ 205|| b .s2 2f ; 1\n\\ 206 <fetchop_opcode> .l2 <fetchop_inops02>, %0 ; 5\n\\ 2071: stw .d%U1t%U0 %0, %1 ; 6\n\\ 2082:" 209 [(set_attr "type" "atomic")]) 210 211(define_insn "sync_nandsi_insn" 212 [(set (match_operand:SI 0 "memory_operand" "+m") 213 (unspec:SI 214 [(not:SI (and:SI (match_dup 0) 215 (match_operand:SI 1 "reg_or_scst5_operand" "bIs5")))] 216 UNSPEC_ATOMIC)) 217 (clobber (match_scratch:SI 2 "=&B"))] 218 "" 219 "0: b .s2 1f ; 0\n\\ 220|| ldw .d%U0t%U2 %0, %2\n\\ 221 nop 1\n\\ 222 nop 3\n\\ 223|| b .s2 2f ; 2\n\\ 224 and .l2 %1, %2, %2 ; 5\n\\ 2251: not .l2 %2, %2 ; 6\n\\ 226 stw .d%U0t%U2 %2, %0 ; 7\n\\ 2272:" 228 [(set_attr "type" "atomic")]) 229 230(define_insn "sync_old_nandsi_insn" 231 [(set (match_operand:SI 0 "register_operand" "=&b") 232 (match_operand:SI 1 "memory_operand" "+m")) 233 (set (match_dup 1) 234 (unspec:SI 235 [(not:SI (and:SI (match_dup 1) 236 (match_operand:SI 2 "reg_or_scst5_operand" "bIs5")))] 237 UNSPEC_ATOMIC)) 238 (clobber (match_scratch:SI 3 "=&B"))] 239 "" 240 "0: b .s2 1f ; 0\n\\ 241|| ldw .d%U1t%U0 %1, %0\n\\ 242 nop 1\n\\ 243 nop 3\n\\ 244|| b .s2 2f ; 2\n\\ 245 and .l2 %2, %0, %3 ; 5\n\\ 2461: not .l2 %3, %3 ; 6\n\\ 247 stw .d%U1t%U3 %3, %1 ; 7\n\\ 2482:" 249 [(set_attr "type" "atomic")]) 250 251(define_insn "sync_new_nandsi_insn" 252 [(set (match_operand:SI 0 "register_operand" "=&b") 253 (not:SI (and:SI (match_operand:SI 1 "memory_operand" "+m") 254 (match_operand:SI 2 "reg_or_scst5_operand" "bIs5")))) 255 (set (match_dup 1) 256 (unspec:SI 257 [(not:SI (and:SI (match_dup 1) (match_dup 2)))] 258 UNSPEC_ATOMIC)) 259 (clobber (match_scratch:SI 3 "=&B"))] 260 "" 261 "0: b .s2 1f ; 0\n\\ 262|| ldw .d%U1t%U0 %1, %0\n\\ 263 nop 1\n\\ 264 nop 3\n\\ 265|| b .s2 2f ; 2\n\\ 266 and .l2 %2, %0, %0 ; 5\n\\ 2671: not .l2 %0, %0 ; 6\n\\ 268 stw .d%U1t%U0 %0, %1 ; 7\n\\ 2692:" 270 [(set_attr "type" "atomic")]) 271