1 // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
2 // See https://llvm.org/LICENSE.txt for license information.
3 // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
7 // Out-of-line LSE atomics helpers. Ported from libgcc library.
9 // M = {1, 2, 4, 8, 16}
10 // ORDER = {'relax', 'acq', 'rel', 'acq_rel'}
11 // Routines implemented:
13 // iM __aarch64_casM_ORDER(iM expected, iM desired, iM *ptr)
14 // iN __aarch64_swpN_ORDER(iN val, iN *ptr)
15 // iN __aarch64_ldaddN_ORDER(iN val, iN *ptr)
16 // iN __aarch64_ldclrN_ORDER(iN val, iN *ptr)
17 // iN __aarch64_ldeorN_ORDER(iN val, iN *ptr)
18 // iN __aarch64_ldsetN_ORDER(iN val, iN *ptr)
20 // Routines may modify temporary registers tmp0, tmp1, tmp2,
21 // return value x0 and the flags only.
31 #if !defined(__APPLE__)
32 HIDDEN(__aarch64_have_lse_atomics)
34 HIDDEN(___aarch64_have_lse_atomics)
37 // Generate mnemonics for
38 // L_cas: SIZE: 1,2,4,8,16 MODEL: 1,2,3,4
39 // L_swp L_ldadd L_ldclr L_ldeor L_ldset: SIZE: 1,2,4,8 MODEL: 1,2,3,4
49 #elif SIZE == 4 || SIZE == 8 || SIZE == 16
89 // Define register size.
90 #define x(N) GLUE2(x, N)
91 #define w(N) GLUE2(w, N)
98 #define NAME(BASE) GLUE4(__aarch64_, BASE, SIZE, SUFF)
99 #define LDXR GLUE4(ld, A, xr, S)
100 #define STXR GLUE4(st, L, xr, S)
102 // Define temporary registers.
107 // Macro for branch to label if no LSE available
108 .macro JUMP_IF_NOT_LSE label
109 #if !defined(__APPLE__)
110 adrp x(tmp0), __aarch64_have_lse_atomics
111 ldrb w(tmp0), [x(tmp0), :lo12:__aarch64_have_lse_atomics]
113 adrp x(tmp0), ___aarch64_have_lse_atomics@page
114 ldrb w(tmp0), [x(tmp0), ___aarch64_have_lse_atomics@pageoff]
120 DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(NAME(cas))
124 #define CAS GLUE4(cas, A, L, S) s(0), s(1), [x2]
126 #define CAS .inst 0x08a07c41 + B + M
128 CAS // s(0), s(1), [x2]
136 STXR w(tmp1), s(1), [x2]
141 #define LDXP GLUE3(ld, A, xp)
142 #define STXP GLUE3(st, L, xp)
144 #define CASP GLUE3(casp, A, L) x0, x1, x2, x3, [x4]
146 #define CASP .inst 0x48207c82 + M
149 CASP // x0, x1, x2, x3, [x4]
157 ccmp x1, x(tmp1), #0, eq
159 STXP w(tmp2), x2, x3, [x4]
164 END_COMPILERRT_OUTLINE_FUNCTION(NAME(cas))
169 #define SWP GLUE4(swp, A, L, S) s(0), s(0), [x1]
171 #define SWP .inst 0x38208020 + B + N
173 DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(NAME(swp))
175 SWP // s(0), s(0), [x1]
181 STXR w(tmp1), s(tmp0), [x1]
184 END_COMPILERRT_OUTLINE_FUNCTION(NAME(swp))
187 #if defined(L_ldadd) || defined(L_ldclr) || \
188 defined(L_ldeor) || defined(L_ldset)
194 #elif defined(L_ldclr)
198 #elif defined(L_ldeor)
202 #elif defined(L_ldset)
211 #define LDOP GLUE4(LDNM, A, L, S) s(0), s(0), [x1]
213 #define LDOP .inst 0x38200020 + OPN + B + N
216 DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(NAME(LDNM))
218 LDOP // s(0), s(0), [x1]
224 OP s(tmp1), s(0), s(tmp0)
225 STXR w(tmp2), s(tmp1), [x1]
228 END_COMPILERRT_OUTLINE_FUNCTION(NAME(LDNM))
229 #endif // L_ldadd L_ldclr L_ldeor L_ldset
231 NO_EXEC_STACK_DIRECTIVE
233 // GNU property note for BTI and PAC
236 #endif // __aarch64__