xref: /freebsd/contrib/llvm-project/compiler-rt/lib/builtins/arm/sync-ops.h (revision 81ad626541db97eb356e2c1d4a20eb2a26a766ab)
10b57cec5SDimitry Andric //===-- sync-ops.h - --===//
20b57cec5SDimitry Andric //
30b57cec5SDimitry Andric // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
40b57cec5SDimitry Andric // See https://llvm.org/LICENSE.txt for license information.
50b57cec5SDimitry Andric // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
60b57cec5SDimitry Andric //
70b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
80b57cec5SDimitry Andric //
90b57cec5SDimitry Andric // This file implements outline macros for the __sync_fetch_and_*
100b57cec5SDimitry Andric // operations. Different instantiations will generate appropriate assembly for
110b57cec5SDimitry Andric // ARM and Thumb-2 versions of the functions.
120b57cec5SDimitry Andric //
130b57cec5SDimitry Andric //===----------------------------------------------------------------------===//
140b57cec5SDimitry Andric 
150b57cec5SDimitry Andric #include "../assembly.h"
160b57cec5SDimitry Andric 
17*81ad6265SDimitry Andric #if __ARM_ARCH >= 7
18*81ad6265SDimitry Andric #define DMB dmb
19*81ad6265SDimitry Andric #elif __ARM_ARCH >= 6
20*81ad6265SDimitry Andric #define DMB mcr p15, #0, r0, c7, c10, #5
21*81ad6265SDimitry Andric #else
22*81ad6265SDimitry Andric #error DMB is only supported on ARMv6+
23*81ad6265SDimitry Andric #endif
24*81ad6265SDimitry Andric 
250b57cec5SDimitry Andric #define SYNC_OP_4(op)                                                          \
260b57cec5SDimitry Andric   .p2align 2;                                                                  \
270b57cec5SDimitry Andric   .syntax unified;                                                             \
28*81ad6265SDimitry Andric   DEFINE_COMPILERRT_FUNCTION(__sync_fetch_and_##op)                            \
29*81ad6265SDimitry Andric   DMB;                                                                         \
300b57cec5SDimitry Andric   mov r12, r0;                                                                 \
310b57cec5SDimitry Andric   LOCAL_LABEL(tryatomic_##op) : ldrex r0, [r12];                               \
320b57cec5SDimitry Andric   op(r2, r0, r1);                                                              \
330b57cec5SDimitry Andric   strex r3, r2, [r12];                                                         \
340b57cec5SDimitry Andric   cmp r3, #0;                                                                  \
350b57cec5SDimitry Andric   bne LOCAL_LABEL(tryatomic_##op);                                             \
36*81ad6265SDimitry Andric   DMB;                                                                         \
370b57cec5SDimitry Andric   bx lr
380b57cec5SDimitry Andric 
390b57cec5SDimitry Andric #define SYNC_OP_8(op)                                                          \
400b57cec5SDimitry Andric   .p2align 2;                                                                  \
410b57cec5SDimitry Andric   .syntax unified;                                                             \
42*81ad6265SDimitry Andric   DEFINE_COMPILERRT_FUNCTION(__sync_fetch_and_##op)                            \
430b57cec5SDimitry Andric   push {r4, r5, r6, lr};                                                       \
44*81ad6265SDimitry Andric   DMB;                                                                         \
450b57cec5SDimitry Andric   mov r12, r0;                                                                 \
460b57cec5SDimitry Andric   LOCAL_LABEL(tryatomic_##op) : ldrexd r0, r1, [r12];                          \
470b57cec5SDimitry Andric   op(r4, r5, r0, r1, r2, r3);                                                  \
480b57cec5SDimitry Andric   strexd r6, r4, r5, [r12];                                                    \
490b57cec5SDimitry Andric   cmp r6, #0;                                                                  \
500b57cec5SDimitry Andric   bne LOCAL_LABEL(tryatomic_##op);                                             \
51*81ad6265SDimitry Andric   DMB;                                                                         \
520b57cec5SDimitry Andric   pop { r4, r5, r6, pc }
530b57cec5SDimitry Andric 
540b57cec5SDimitry Andric #define MINMAX_4(rD, rN, rM, cmp_kind)                                         \
550b57cec5SDimitry Andric   cmp rN, rM;                                                                  \
560b57cec5SDimitry Andric   mov rD, rM;                                                                  \
570b57cec5SDimitry Andric   it cmp_kind;                                                                 \
580b57cec5SDimitry Andric   mov##cmp_kind rD, rN
590b57cec5SDimitry Andric 
600b57cec5SDimitry Andric #define MINMAX_8(rD_LO, rD_HI, rN_LO, rN_HI, rM_LO, rM_HI, cmp_kind)           \
610b57cec5SDimitry Andric   cmp rN_LO, rM_LO;                                                            \
620b57cec5SDimitry Andric   sbcs rN_HI, rM_HI;                                                           \
630b57cec5SDimitry Andric   mov rD_LO, rM_LO;                                                            \
640b57cec5SDimitry Andric   mov rD_HI, rM_HI;                                                            \
650b57cec5SDimitry Andric   itt cmp_kind;                                                                \
660b57cec5SDimitry Andric   mov##cmp_kind rD_LO, rN_LO;                                                  \
670b57cec5SDimitry Andric   mov##cmp_kind rD_HI, rN_HI
68