1 1.7 riastrad /* $NetBSD: __aarch64_lse.S,v 1.7 2022/08/06 21:31:33 riastradh Exp $ */ 2 1.1 skrll 3 1.1 skrll /*- 4 1.1 skrll * Copyright (c) 2021 The NetBSD Foundation, Inc. 5 1.1 skrll * All rights reserved. 6 1.1 skrll * 7 1.1 skrll * This code is derived from software contributed to The NetBSD Foundation 8 1.1 skrll * by Nick Hudson. 9 1.3 skrll * 10 1.1 skrll * Redistribution and use in source and binary forms, with or without 11 1.1 skrll * modification, are permitted provided that the following conditions 12 1.1 skrll * are met: 13 1.1 skrll * 1. Redistributions of source code must retain the above copyright 14 1.1 skrll * notice, this list of conditions and the following disclaimer. 15 1.1 skrll * 2. Redistributions in binary form must reproduce the above copyright 16 1.1 skrll * notice, this list of conditions and the following disclaimer in the 17 1.1 skrll * documentation and/or other materials provided with the distribution. 18 1.1 skrll * 19 1.1 skrll * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 1.1 skrll * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 1.1 skrll * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 1.1 skrll * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 1.1 skrll * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 1.1 skrll * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 1.1 skrll * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 1.1 skrll * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 1.1 skrll * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 1.1 skrll * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 1.1 skrll * POSSIBILITY OF SUCH DAMAGE. 30 1.1 skrll */ 31 1.1 skrll 32 1.1 skrll #include <sys/cdefs.h> 33 1.1 skrll 34 1.1 skrll #include "atomic_op_asm.h" 35 1.1 skrll 36 1.1 skrll #if SZ == 1 37 1.1 skrll #define OPSFX b 38 1.1 skrll #define R0 w0 39 1.1 skrll #define R1 w1 40 1.1 skrll #define R4 w4 41 1.1 skrll #endif 42 1.1 skrll 43 1.1 skrll #if SZ == 2 44 1.1 skrll #define OPSFX h 45 1.1 skrll #define R0 w0 46 1.1 skrll #define R1 w1 47 1.1 skrll #define R4 w4 48 1.1 skrll #endif 49 1.1 skrll 50 1.1 skrll #if SZ == 4 51 1.1 skrll #define OPSFX 52 1.1 skrll #define R0 w0 53 1.1 skrll #define R1 w1 54 1.1 skrll #define R4 w4 55 1.1 skrll #endif 56 1.1 skrll 57 1.1 skrll #if SZ == 8 58 1.1 skrll #define OPSFX 59 1.1 skrll #define R0 x0 60 1.1 skrll #define R1 x1 61 1.1 skrll #define R4 x4 62 1.1 skrll #endif 63 1.1 skrll 64 1.1 skrll #if defined(AR_relax) 65 1.1 skrll #define ACQ 66 1.1 skrll #define REL 67 1.7 riastrad #define DMB 68 1.1 skrll #endif 69 1.1 skrll 70 1.1 skrll #if defined(AR_acq) 71 1.1 skrll #define ACQ a 72 1.1 skrll #define REL 73 1.7 riastrad #define DMB 74 1.1 skrll #endif 75 1.1 skrll 76 1.1 skrll #if defined(AR_rel) 77 1.1 skrll #define ACQ 78 1.1 skrll #define REL l 79 1.7 riastrad #define DMB 80 1.1 skrll #endif 81 1.1 skrll 82 1.1 skrll #if defined(AR_acq_rel) 83 1.1 skrll #define ACQ a 84 1.1 skrll #define REL l 85 1.7 riastrad #define DMB 86 1.7 riastrad #endif 87 1.7 riastrad 88 1.7 riastrad #if defined(AR_sync) 89 1.7 riastrad #define ACQ 90 1.7 riastrad #define REL 91 1.7 riastrad #define DMB dmb ish 92 1.1 skrll #endif 93 1.1 skrll 94 1.1 skrll #if defined(OP_clr) 95 1.1 skrll #define INSNOP bic 96 1.1 skrll #endif 97 1.1 skrll 98 1.1 skrll #if defined(OP_set) 99 1.1 skrll #define INSNOP orr 100 1.1 skrll #endif 101 1.1 skrll 102 1.1 skrll #if defined(OP_add) 103 1.1 skrll #define INSNOP add 104 1.1 skrll #endif 105 1.1 skrll 106 1.1 skrll #if defined(OP_eor) 107 1.1 skrll #define INSNOP eor 108 1.1 skrll #endif 109 1.1 skrll 110 1.1 skrll #define _CONCAT3(A, B, C) __CONCAT3(A,B,C) 111 1.1 skrll #define _CONCAT4(A, B, C, D) __CONCAT4(A,B,C,D) 112 1.1 skrll #define _CONCAT5(A, B, C, D, E) __CONCAT5(A,B,C,D,E) 113 1.1 skrll 114 1.1 skrll #define FUNC2 _CONCAT3(__aarch64_,OP,AR) 115 1.1 skrll #define FUNC3 _CONCAT4(__aarch64_,OP,SZ,AR) 116 1.1 skrll 117 1.1 skrll #define CASP_FUNC FUNC2 118 1.1 skrll #define CAS_FUNC FUNC3 119 1.1 skrll #define SWP_FUNC FUNC3 120 1.1 skrll #define INSN_FUNC FUNC3 121 1.1 skrll 122 1.1 skrll #define LDXR _CONCAT4(ld, ACQ, xr, OPSFX) 123 1.1 skrll #define STXR _CONCAT4(st, REL, xr, OPSFX) 124 1.1 skrll #define LDXP _CONCAT3(ld, ACQ, xp) 125 1.1 skrll #define STXP _CONCAT3(st, REL, xp) 126 1.1 skrll 127 1.1 skrll #ifdef _HAVE_LSE 128 1.1 skrll #define SWP _CONCAT4(swp, ACQ, REL, OPSFX) 129 1.1 skrll #define CAS _CONCAT4(cas, ACQ, REL, OPSFX) 130 1.1 skrll #define CASP _CONCAT3(casp, ACQ, REL) 131 1.1 skrll #define INSN _CONCAT5(ld, OP, ACQ, REL, OPSFX) 132 1.1 skrll 133 1.1 skrll .hidden __aarch64_have_lse_atomics 134 1.1 skrll .arch armv8-a+lse 135 1.1 skrll 136 1.1 skrll #define DO_LSE_INSN_IF_SUPPORTED(label) \ 137 1.1 skrll adrp x4, __aarch64_have_lse_atomics ;\ 138 1.1 skrll ldrb w4, [x4, #:lo12:__aarch64_have_lse_atomics] ;\ 139 1.1 skrll cbnz w4, label 140 1.1 skrll 141 1.1 skrll #endif 142 1.1 skrll 143 1.1 skrll #if defined(OP_swp) 144 1.1 skrll ENTRY_NP(SWP_FUNC) 145 1.1 skrll #ifdef _HAVE_LSE 146 1.1 skrll DO_LSE_INSN_IF_SUPPORTED(99f) 147 1.7 riastrad DMB 148 1.1 skrll SWP R0, R0, [x1] 149 1.7 riastrad DMB 150 1.1 skrll ret 151 1.1 skrll 99: 152 1.1 skrll #endif 153 1.6 skrll mov x4, x0 /* need x0 for return value */ 154 1.7 riastrad DMB /* potential barrier */ 155 1.6 skrll 1: LDXR R0, [x1] /* load old value */ 156 1.6 skrll STXR w3, R4, [x1] /* store new value */ 157 1.6 skrll cbnz w3, 2f /* succeed?? no, try again */ 158 1.7 riastrad DMB /* potential barrier */ 159 1.6 skrll ret /* return old value */ 160 1.1 skrll 2: b 1b 161 1.1 skrll END(SWP_FUNC) 162 1.1 skrll #endif 163 1.1 skrll 164 1.1 skrll #if defined(OP_cas) 165 1.1 skrll ENTRY_NP(CAS_FUNC) 166 1.1 skrll #ifdef _HAVE_LSE 167 1.1 skrll DO_LSE_INSN_IF_SUPPORTED(99f) 168 1.7 riastrad DMB 169 1.1 skrll CAS R0, R1, [x2] 170 1.7 riastrad DMB 171 1.1 skrll ret 172 1.1 skrll 99: 173 1.1 skrll #endif 174 1.1 skrll mov x4, x0 /* need x0 for return value */ 175 1.7 riastrad DMB /* potential barrier */ 176 1.1 skrll 1: LDXR R0, [x2] /* load old value */ 177 1.1 skrll cmp R0, R4 /* compare */ 178 1.1 skrll b.ne 2f /* not equal? return */ 179 1.1 skrll STXR w3, R1, [x2] /* store new value */ 180 1.1 skrll cbnz w3, 3f /* succeed? nope, try again. */ 181 1.7 riastrad DMB /* potential barrier */ 182 1.1 skrll 2: ret /* return. */ 183 1.1 skrll 3: b 1b 184 1.1 skrll END(CAS_FUNC) 185 1.1 skrll #endif 186 1.1 skrll 187 1.1 skrll #if defined(OP_casp) 188 1.1 skrll ENTRY_NP(CASP_FUNC) 189 1.1 skrll #ifdef _HAVE_LSE 190 1.1 skrll DO_LSE_INSN_IF_SUPPORTED(99f) 191 1.7 riastrad DMB 192 1.1 skrll CASP x0, x1, x2, x3, [x4] 193 1.7 riastrad DMB 194 1.1 skrll ret 195 1.1 skrll 99: 196 1.1 skrll #endif 197 1.4 skrll mov x5, x0 /* need x0 for return value */ 198 1.4 skrll mov x6, x1 /* need x1 for return value */ 199 1.7 riastrad DMB /* potential barrier */ 200 1.4 skrll 1: LDXP x0, x1, [x4] /* load old value */ 201 1.5 skrll cmp x0, x5 /* compare */ 202 1.1 skrll b.ne 2f /* not equal? return */ 203 1.5 skrll cmp x1, x6 204 1.1 skrll b.ne 2f /* not equal? return */ 205 1.1 skrll STXP w7, x2, x3, [x4] /* store new value */ 206 1.1 skrll cbnz w7, 3f /* succeed? nope, try again. */ 207 1.7 riastrad DMB /* potential barrier */ 208 1.1 skrll 2: ret /* return. */ 209 1.1 skrll 3: b 1b 210 1.1 skrll END(CASP_FUNC) 211 1.1 skrll #endif 212 1.1 skrll 213 1.1 skrll #if defined(OP_set) || defined(OP_clr) || defined(OP_add) || defined(OP_eor) 214 1.1 skrll ENTRY_NP(INSN_FUNC) 215 1.1 skrll #ifdef _HAVE_LSE 216 1.1 skrll DO_LSE_INSN_IF_SUPPORTED(99f) 217 1.7 riastrad DMB 218 1.1 skrll INSN R0, R0, [x1] 219 1.7 riastrad DMB 220 1.1 skrll ret 221 1.1 skrll 99: 222 1.1 skrll #endif 223 1.6 skrll mov x4, x0 /* need x0 for return value */ 224 1.7 riastrad DMB /* potential barrier */ 225 1.6 skrll 1: LDXR R0, [x1] /* load old value */ 226 1.1 skrll INSNOP R4, R0, R4 227 1.6 skrll STXR w3, R4, [x1] /* store new value */ 228 1.6 skrll cbnz w3, 2f /* succeed?? no, try again */ 229 1.7 riastrad DMB /* potential barrier */ 230 1.6 skrll ret /* return old value */ 231 1.1 skrll 2: b 1b 232 1.1 skrll END(INSN_FUNC) 233 1.1 skrll #endif 234