Path: blob/main/contrib/llvm-project/compiler-rt/lib/builtins/aarch64/lse.S
35291 views
// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.1// See https://llvm.org/LICENSE.txt for license information.2// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception34#include "assembly.h"56// Out-of-line LSE atomics helpers. Ported from libgcc library.7// N = {1, 2, 4, 8}8// M = {1, 2, 4, 8, 16}9// ORDER = {'relax', 'acq', 'rel', 'acq_rel', 'sync'}10// Routines implemented:11//12// iM __aarch64_casM_ORDER(iM expected, iM desired, iM *ptr)13// iN __aarch64_swpN_ORDER(iN val, iN *ptr)14// iN __aarch64_ldaddN_ORDER(iN val, iN *ptr)15// iN __aarch64_ldclrN_ORDER(iN val, iN *ptr)16// iN __aarch64_ldeorN_ORDER(iN val, iN *ptr)17// iN __aarch64_ldsetN_ORDER(iN val, iN *ptr)18//19// Routines may modify temporary registers tmp0, tmp1, tmp2,20// return value x0 and the flags only.2122#ifdef __aarch64__2324#ifdef HAS_ASM_LSE25.arch armv8-a+lse26#else27.arch armv8-a28#endif2930#if !defined(__APPLE__)31HIDDEN(__aarch64_have_lse_atomics)32#else33HIDDEN(___aarch64_have_lse_atomics)34#endif3536// Generate mnemonics for37// L_cas: SIZE: 1,2,4,8,16 MODEL: 1,2,3,4,538// L_swp L_ldadd L_ldclr L_ldeor L_ldset: SIZE: 1,2,4,8 MODEL: 1,2,3,4,53940#if SIZE == 141#define S b42#define UXT uxtb43#define B 0x0000000044#elif SIZE == 245#define S h46#define UXT uxth47#define B 0x4000000048#elif SIZE == 4 || SIZE == 8 || SIZE == 1649#define S50#define UXT mov51#if SIZE == 452#define B 0x8000000053#elif SIZE == 854#define B 0xc000000055#endif56#else57#error58#endif // SIZE5960#if MODEL == 161#define SUFF _relax62#define A63#define L64#define M 0x00000065#define N 0x00000066#define BARRIER67#elif MODEL == 268#define SUFF _acq69#define A a70#define L71#define M 0x40000072#define N 0x80000073#define BARRIER74#elif MODEL == 375#define SUFF _rel76#define A77#define L l78#define M 0x00800079#define N 0x40000080#define BARRIER81#elif MODEL == 482#define SUFF _acq_rel83#define A a84#define L l85#define M 0x40800086#define N 0xc0000087#define BARRIER88#elif MODEL == 589#define SUFF _sync90#ifdef L_swp91// swp has _acq semantics.92#define A a93#define L94#define M 0x40000095#define N 0x80000096#else97// All other _sync functions have _seq semantics.98#define A a99#define L l100#define M 0x408000101#define N 0xc00000102#endif103#define BARRIER dmb ish104#else105#error106#endif // MODEL107108// Define register size.109#define x(N) GLUE2(x, N)110#define w(N) GLUE2(w, N)111#if SIZE < 8112#define s(N) w(N)113#else114#define s(N) x(N)115#endif116117#define NAME(BASE) GLUE4(__aarch64_, BASE, SIZE, SUFF)118#if MODEL == 5119// Drop A for _sync functions.120#define LDXR GLUE3(ld, xr, S)121#else122#define LDXR GLUE4(ld, A, xr, S)123#endif124#define STXR GLUE4(st, L, xr, S)125126// Define temporary registers.127#define tmp0 16128#define tmp1 17129#define tmp2 15130131// Macro for branch to label if no LSE available132.macro JUMP_IF_NOT_LSE label133#if !defined(__APPLE__)134adrp x(tmp0), __aarch64_have_lse_atomics135ldrb w(tmp0), [x(tmp0), :lo12:__aarch64_have_lse_atomics]136#else137adrp x(tmp0), ___aarch64_have_lse_atomics@page138ldrb w(tmp0), [x(tmp0), ___aarch64_have_lse_atomics@pageoff]139#endif140cbz w(tmp0), \label141.endm142143#ifdef L_cas144DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(NAME(cas))145JUMP_IF_NOT_LSE 8f146#if SIZE < 16147#ifdef HAS_ASM_LSE148#define CAS GLUE4(cas, A, L, S) s(0), s(1), [x2]149#else150#define CAS .inst 0x08a07c41 + B + M151#endif152CAS // s(0), s(1), [x2]153ret1548:155UXT s(tmp0), s(0)1560:157LDXR s(0), [x2]158cmp s(0), s(tmp0)159bne 1f160STXR w(tmp1), s(1), [x2]161cbnz w(tmp1), 0b1621:163BARRIER164ret165#else166#if MODEL == 5167// Drop A for _sync functions.168#define LDXP GLUE2(ld, xp)169#else170#define LDXP GLUE3(ld, A, xp)171#endif172#define STXP GLUE3(st, L, xp)173#ifdef HAS_ASM_LSE174#define CASP GLUE3(casp, A, L) x0, x1, x2, x3, [x4]175#else176#define CASP .inst 0x48207c82 + M177#endif178179CASP // x0, x1, x2, x3, [x4]180ret1818:182mov x(tmp0), x0183mov x(tmp1), x11840:185LDXP x0, x1, [x4]186cmp x0, x(tmp0)187ccmp x1, x(tmp1), #0, eq188bne 1f189STXP w(tmp2), x2, x3, [x4]190cbnz w(tmp2), 0b1911:192BARRIER193ret194#endif195END_COMPILERRT_OUTLINE_FUNCTION(NAME(cas))196#endif // L_cas197198#ifdef L_swp199#ifdef HAS_ASM_LSE200#define SWP GLUE4(swp, A, L, S) s(0), s(0), [x1]201#else202#define SWP .inst 0x38208020 + B + N203#endif204DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(NAME(swp))205JUMP_IF_NOT_LSE 8f206SWP // s(0), s(0), [x1]207ret2088:209mov s(tmp0), s(0)2100:211LDXR s(0), [x1]212STXR w(tmp1), s(tmp0), [x1]213cbnz w(tmp1), 0b214BARRIER215ret216END_COMPILERRT_OUTLINE_FUNCTION(NAME(swp))217#endif // L_swp218219#if defined(L_ldadd) || defined(L_ldclr) || \220defined(L_ldeor) || defined(L_ldset)221222#ifdef L_ldadd223#define LDNM ldadd224#define OP add225#define OPN 0x0000226#elif defined(L_ldclr)227#define LDNM ldclr228#define OP bic229#define OPN 0x1000230#elif defined(L_ldeor)231#define LDNM ldeor232#define OP eor233#define OPN 0x2000234#elif defined(L_ldset)235#define LDNM ldset236#define OP orr237#define OPN 0x3000238#else239#error240#endif241242#ifdef HAS_ASM_LSE243#define LDOP GLUE4(LDNM, A, L, S) s(0), s(0), [x1]244#else245#define LDOP .inst 0x38200020 + OPN + B + N246#endif247248DEFINE_COMPILERRT_OUTLINE_FUNCTION_UNMANGLED(NAME(LDNM))249JUMP_IF_NOT_LSE 8f250LDOP // s(0), s(0), [x1]251ret2528:253mov s(tmp0), s(0)2540:255LDXR s(0), [x1]256OP s(tmp1), s(0), s(tmp0)257STXR w(tmp2), s(tmp1), [x1]258cbnz w(tmp2), 0b259BARRIER260ret261END_COMPILERRT_OUTLINE_FUNCTION(NAME(LDNM))262#endif // L_ldadd L_ldclr L_ldeor L_ldset263264NO_EXEC_STACK_DIRECTIVE265266// GNU property note for BTI and PAC267GNU_PROPERTY_BTI_PAC268269#endif // __aarch64__270271272