18f87df16SOlivier Houchard /*
28f87df16SOlivier Houchard  * Copyright 2009-2016 Samy Al Bahra.
38f87df16SOlivier Houchard  * Copyright 2013-2016 Olivier Houchard.
48f87df16SOlivier Houchard  * All rights reserved.
58f87df16SOlivier Houchard  *
68f87df16SOlivier Houchard  * Redistribution and use in source and binary forms, with or without
78f87df16SOlivier Houchard  * modification, are permitted provided that the following conditions
88f87df16SOlivier Houchard  * are met:
98f87df16SOlivier Houchard  * 1. Redistributions of source code must retain the above copyright
108f87df16SOlivier Houchard  *    notice, this list of conditions and the following disclaimer.
118f87df16SOlivier Houchard  * 2. Redistributions in binary form must reproduce the above copyright
128f87df16SOlivier Houchard  *    notice, this list of conditions and the following disclaimer in the
138f87df16SOlivier Houchard  *    documentation and/or other materials provided with the distribution.
148f87df16SOlivier Houchard  *
158f87df16SOlivier Houchard  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
168f87df16SOlivier Houchard  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
178f87df16SOlivier Houchard  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
188f87df16SOlivier Houchard  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
198f87df16SOlivier Houchard  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
208f87df16SOlivier Houchard  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
218f87df16SOlivier Houchard  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
228f87df16SOlivier Houchard  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
238f87df16SOlivier Houchard  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
248f87df16SOlivier Houchard  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
258f87df16SOlivier Houchard  * SUCH DAMAGE.
268f87df16SOlivier Houchard  */
278f87df16SOlivier Houchard 
288f87df16SOlivier Houchard #ifndef CK_PR_AARCH64_LLSC_H
298f87df16SOlivier Houchard #define CK_PR_AARCH64_LLSC_H
308f87df16SOlivier Houchard 
318f87df16SOlivier Houchard #ifndef CK_PR_H
328f87df16SOlivier Houchard #error Do not include this file directly, use ck_pr.h
338f87df16SOlivier Houchard #endif
348f87df16SOlivier Houchard 
358f87df16SOlivier Houchard CK_CC_INLINE static bool
ck_pr_cas_64_2_value(uint64_t target[2],uint64_t compare[2],uint64_t set[2],uint64_t value[2])368f87df16SOlivier Houchard ck_pr_cas_64_2_value(uint64_t target[2], uint64_t compare[2], uint64_t set[2], uint64_t value[2])
378f87df16SOlivier Houchard {
388f87df16SOlivier Houchard         uint64_t tmp1, tmp2;
398f87df16SOlivier Houchard 
408f87df16SOlivier Houchard         __asm__ __volatile__("1:"
41*74e9b5f2SOlivier Houchard                              "ldxp %0, %1, [%4]\n"
42*74e9b5f2SOlivier Houchard                              "mov %2, %0\n"
43*74e9b5f2SOlivier Houchard                              "mov %3, %1\n"
44*74e9b5f2SOlivier Houchard                              "eor %0, %0, %5\n"
45*74e9b5f2SOlivier Houchard                              "eor %1, %1, %6\n"
46*74e9b5f2SOlivier Houchard                              "orr %1, %0, %1\n"
47*74e9b5f2SOlivier Houchard                              "mov %w0, #0\n"
48*74e9b5f2SOlivier Houchard                              "cbnz %1, 2f\n"
49*74e9b5f2SOlivier Houchard                              "stxp %w0, %7, %8, [%4]\n"
50*74e9b5f2SOlivier Houchard                              "cbnz %w0, 1b\n"
51*74e9b5f2SOlivier Houchard                              "mov %w0, #1\n"
528f87df16SOlivier Houchard                              "2:"
538f87df16SOlivier Houchard                              : "=&r" (tmp1), "=&r" (tmp2), "=&r" (value[0]), "=&r" (value[1])
548f87df16SOlivier Houchard                              : "r" (target), "r" (compare[0]), "r" (compare[1]), "r" (set[0]), "r" (set[1])
558f87df16SOlivier Houchard                              : "cc", "memory");
568f87df16SOlivier Houchard 
578f87df16SOlivier Houchard         return (tmp1);
588f87df16SOlivier Houchard }
598f87df16SOlivier Houchard 
608f87df16SOlivier Houchard CK_CC_INLINE static bool
ck_pr_cas_ptr_2_value(void * target,void * compare,void * set,void * value)618f87df16SOlivier Houchard ck_pr_cas_ptr_2_value(void *target, void *compare, void *set, void *value)
628f87df16SOlivier Houchard {
638f87df16SOlivier Houchard         return (ck_pr_cas_64_2_value(CK_CPP_CAST(uint64_t *, target),
648f87df16SOlivier Houchard                                    CK_CPP_CAST(uint64_t *, compare),
658f87df16SOlivier Houchard                                    CK_CPP_CAST(uint64_t *, set),
668f87df16SOlivier Houchard                                    CK_CPP_CAST(uint64_t *, value)));
678f87df16SOlivier Houchard }
688f87df16SOlivier Houchard 
698f87df16SOlivier Houchard CK_CC_INLINE static bool
ck_pr_cas_64_2(uint64_t target[2],uint64_t compare[2],uint64_t set[2])708f87df16SOlivier Houchard ck_pr_cas_64_2(uint64_t target[2], uint64_t compare[2], uint64_t set[2])
718f87df16SOlivier Houchard {
728f87df16SOlivier Houchard         uint64_t tmp1, tmp2;
738f87df16SOlivier Houchard 
748f87df16SOlivier Houchard         __asm__ __volatile__("1:"
75*74e9b5f2SOlivier Houchard                              "ldxp %0, %1, [%2]\n"
76*74e9b5f2SOlivier Houchard                              "eor %0, %0, %3\n"
77*74e9b5f2SOlivier Houchard                              "eor %1, %1, %4\n"
78*74e9b5f2SOlivier Houchard                              "orr %1, %0, %1\n"
79*74e9b5f2SOlivier Houchard                              "mov %w0, #0\n"
80*74e9b5f2SOlivier Houchard                              "cbnz %1, 2f\n"
81*74e9b5f2SOlivier Houchard                              "stxp %w0, %5, %6, [%2]\n"
82*74e9b5f2SOlivier Houchard                              "cbnz %w0, 1b\n"
83*74e9b5f2SOlivier Houchard                              "mov %w0, #1\n"
848f87df16SOlivier Houchard                              "2:"
858f87df16SOlivier Houchard                              : "=&r" (tmp1), "=&r" (tmp2)
868f87df16SOlivier Houchard                              : "r" (target), "r" (compare[0]), "r" (compare[1]), "r" (set[0]), "r" (set[1])
878f87df16SOlivier Houchard                              : "cc", "memory");
888f87df16SOlivier Houchard 
898f87df16SOlivier Houchard         return (tmp1);
908f87df16SOlivier Houchard }
918f87df16SOlivier Houchard CK_CC_INLINE static bool
ck_pr_cas_ptr_2(void * target,void * compare,void * set)928f87df16SOlivier Houchard ck_pr_cas_ptr_2(void *target, void *compare, void *set)
938f87df16SOlivier Houchard {
948f87df16SOlivier Houchard         return (ck_pr_cas_64_2(CK_CPP_CAST(uint64_t *, target),
958f87df16SOlivier Houchard                              CK_CPP_CAST(uint64_t *, compare),
968f87df16SOlivier Houchard                              CK_CPP_CAST(uint64_t *, set)));
978f87df16SOlivier Houchard }
988f87df16SOlivier Houchard 
998f87df16SOlivier Houchard 
1008f87df16SOlivier Houchard #define CK_PR_CAS(N, M, T, W, R)					\
1018f87df16SOlivier Houchard         CK_CC_INLINE static bool					\
1028f87df16SOlivier Houchard         ck_pr_cas_##N##_value(M *target, T compare, T set, M *value)	\
1038f87df16SOlivier Houchard         {								\
1048f87df16SOlivier Houchard                 T previous;						\
1058f87df16SOlivier Houchard                 T tmp;							\
106*74e9b5f2SOlivier Houchard                 __asm__ __volatile__("1:\n"				\
107*74e9b5f2SOlivier Houchard                                      "ldxr" W " %" R "0, [%2]\n"	\
108*74e9b5f2SOlivier Houchard                                      "cmp  %" R "0, %" R "4\n"		\
109*74e9b5f2SOlivier Houchard                                      "b.ne 2f\n"			\
110*74e9b5f2SOlivier Houchard                                      "stxr" W " %w1, %" R "3, [%2]\n"	\
111*74e9b5f2SOlivier Houchard                                      "cbnz %w1, 1b\n"			\
1128f87df16SOlivier Houchard                                      "2:"				\
1138f87df16SOlivier Houchard                     : "=&r" (previous),					\
1148f87df16SOlivier Houchard                     "=&r" (tmp)						\
1158f87df16SOlivier Houchard                     : "r"   (target),					\
1168f87df16SOlivier Houchard                     "r"   (set),					\
1178f87df16SOlivier Houchard                     "r"   (compare)					\
1188f87df16SOlivier Houchard                     : "memory", "cc");					\
1198f87df16SOlivier Houchard                 *(T *)value = previous;					\
1208f87df16SOlivier Houchard                 return (previous == compare);				\
1218f87df16SOlivier Houchard         }								\
1228f87df16SOlivier Houchard         CK_CC_INLINE static bool					\
1238f87df16SOlivier Houchard         ck_pr_cas_##N(M *target, T compare, T set)			\
1248f87df16SOlivier Houchard         {								\
1258f87df16SOlivier Houchard                 T previous;						\
1268f87df16SOlivier Houchard                 T tmp;							\
1278f87df16SOlivier Houchard                 __asm__ __volatile__(					\
1288f87df16SOlivier Houchard                                      "1:"				\
129*74e9b5f2SOlivier Houchard                                      "ldxr" W " %" R "0, [%2]\n"	\
130*74e9b5f2SOlivier Houchard                                      "cmp  %" R "0, %" R "4\n"		\
131*74e9b5f2SOlivier Houchard                                      "b.ne 2f\n"			\
132*74e9b5f2SOlivier Houchard                                      "stxr" W " %w1, %" R "3, [%2]\n"	\
133*74e9b5f2SOlivier Houchard                                      "cbnz %w1, 1b\n"			\
1348f87df16SOlivier Houchard                                      "2:"				\
1358f87df16SOlivier Houchard                     : "=&r" (previous),					\
1368f87df16SOlivier Houchard                     "=&r" (tmp)						\
1378f87df16SOlivier Houchard                     : "r"   (target),					\
1388f87df16SOlivier Houchard                     "r"   (set),					\
1398f87df16SOlivier Houchard                     "r"   (compare)					\
1408f87df16SOlivier Houchard                     : "memory", "cc");					\
1418f87df16SOlivier Houchard                 return (previous == compare);				\
1428f87df16SOlivier Houchard         }
1438f87df16SOlivier Houchard 
1448f87df16SOlivier Houchard CK_PR_CAS(ptr, void, void *, "", "")
1458f87df16SOlivier Houchard 
1468f87df16SOlivier Houchard #define CK_PR_CAS_S(N, M, W, R)	CK_PR_CAS(N, M, M, W, R)
1478f87df16SOlivier Houchard CK_PR_CAS_S(64, uint64_t, "", "")
1488f87df16SOlivier Houchard #ifndef CK_PR_DISABLE_DOUBLE
1498f87df16SOlivier Houchard CK_PR_CAS_S(double, double, "", "")
1508f87df16SOlivier Houchard #endif
1518f87df16SOlivier Houchard CK_PR_CAS_S(32, uint32_t, "", "w")
1528f87df16SOlivier Houchard CK_PR_CAS_S(uint, unsigned int, "", "w")
1538f87df16SOlivier Houchard CK_PR_CAS_S(int, int, "", "w")
1548f87df16SOlivier Houchard CK_PR_CAS_S(16, uint16_t, "h", "w")
1558f87df16SOlivier Houchard CK_PR_CAS_S(8, uint8_t, "b", "w")
1568f87df16SOlivier Houchard CK_PR_CAS_S(short, short, "h", "w")
1578f87df16SOlivier Houchard CK_PR_CAS_S(char, char, "b", "w")
1588f87df16SOlivier Houchard 
1598f87df16SOlivier Houchard 
1608f87df16SOlivier Houchard #undef CK_PR_CAS_S
1618f87df16SOlivier Houchard #undef CK_PR_CAS
1628f87df16SOlivier Houchard 
1638f87df16SOlivier Houchard #define CK_PR_FAS(N, M, T, W, R)				\
1648f87df16SOlivier Houchard         CK_CC_INLINE static T					\
1658f87df16SOlivier Houchard         ck_pr_fas_##N(M *target, T v)				\
1668f87df16SOlivier Houchard         {							\
1678f87df16SOlivier Houchard                 T previous;					\
1688f87df16SOlivier Houchard                 T tmp;						\
1698f87df16SOlivier Houchard                 __asm__ __volatile__("1:"			\
170*74e9b5f2SOlivier Houchard                                      "ldxr" W " %" R "0, [%2]\n"\
171*74e9b5f2SOlivier Houchard                                      "stxr" W " %w1, %" R "3, [%2]\n"\
172*74e9b5f2SOlivier Houchard                                      "cbnz %w1, 1b\n"		\
1738f87df16SOlivier Houchard                                         : "=&r" (previous),	\
1748f87df16SOlivier Houchard                                           "=&r" (tmp) 		\
1758f87df16SOlivier Houchard                                         : "r"   (target),	\
1768f87df16SOlivier Houchard                                           "r"   (v)		\
1778f87df16SOlivier Houchard                                         : "memory", "cc");	\
1788f87df16SOlivier Houchard                 return (previous);				\
1798f87df16SOlivier Houchard         }
1808f87df16SOlivier Houchard 
1818f87df16SOlivier Houchard CK_PR_FAS(64, uint64_t, uint64_t, "", "")
1828f87df16SOlivier Houchard CK_PR_FAS(32, uint32_t, uint32_t, "", "w")
1838f87df16SOlivier Houchard CK_PR_FAS(ptr, void, void *, "", "")
1848f87df16SOlivier Houchard CK_PR_FAS(int, int, int, "", "w")
1858f87df16SOlivier Houchard CK_PR_FAS(uint, unsigned int, unsigned int, "", "w")
1868f87df16SOlivier Houchard CK_PR_FAS(16, uint16_t, uint16_t, "h", "w")
1878f87df16SOlivier Houchard CK_PR_FAS(8, uint8_t, uint8_t, "b", "w")
1888f87df16SOlivier Houchard CK_PR_FAS(short, short, short, "h", "w")
1898f87df16SOlivier Houchard CK_PR_FAS(char, char, char, "b", "w")
1908f87df16SOlivier Houchard 
1918f87df16SOlivier Houchard 
1928f87df16SOlivier Houchard #undef CK_PR_FAS
1938f87df16SOlivier Houchard 
1948f87df16SOlivier Houchard #define CK_PR_UNARY(O, N, M, T, I, W, R)			\
1958f87df16SOlivier Houchard         CK_CC_INLINE static void				\
1968f87df16SOlivier Houchard         ck_pr_##O##_##N(M *target)				\
1978f87df16SOlivier Houchard         {							\
1988f87df16SOlivier Houchard                 T previous = 0;					\
1998f87df16SOlivier Houchard                 T tmp = 0;					\
2008f87df16SOlivier Houchard                 __asm__ __volatile__("1:"			\
201*74e9b5f2SOlivier Houchard                                      "ldxr" W " %" R "0, [%2]\n"\
202*74e9b5f2SOlivier Houchard                                       I "\n"			\
203*74e9b5f2SOlivier Houchard                                      "stxr" W " %w1, %" R "0, [%2]\n"	\
204*74e9b5f2SOlivier Houchard                                      "cbnz %w1, 1b\n"		\
2058f87df16SOlivier Houchard                                         : "=&r" (previous),	\
2068f87df16SOlivier Houchard                                           "=&r" (tmp)		\
2078f87df16SOlivier Houchard                                         : "r"   (target)	\
2088f87df16SOlivier Houchard                                         : "memory", "cc");	\
2098f87df16SOlivier Houchard                 return;						\
2108f87df16SOlivier Houchard         }
2118f87df16SOlivier Houchard 
2128f87df16SOlivier Houchard CK_PR_UNARY(inc, ptr, void, void *, "add %0, %0, #1", "", "")
2138f87df16SOlivier Houchard CK_PR_UNARY(dec, ptr, void, void *, "sub %0, %0, #1", "", "")
2148f87df16SOlivier Houchard CK_PR_UNARY(not, ptr, void, void *, "mvn %0, %0", "", "")
2158f87df16SOlivier Houchard CK_PR_UNARY(inc, 64, uint64_t, uint64_t, "add %0, %0, #1", "", "")
2168f87df16SOlivier Houchard CK_PR_UNARY(dec, 64, uint64_t, uint64_t, "sub %0, %0, #1", "", "")
2178f87df16SOlivier Houchard CK_PR_UNARY(not, 64, uint64_t, uint64_t, "mvn %0, %0", "", "")
2188f87df16SOlivier Houchard 
2198f87df16SOlivier Houchard #define CK_PR_UNARY_S(S, T, W)					\
2208f87df16SOlivier Houchard         CK_PR_UNARY(inc, S, T, T, "add %w0, %w0, #1", W, "w")	\
2218f87df16SOlivier Houchard         CK_PR_UNARY(dec, S, T, T, "sub %w0, %w0, #1", W, "w")	\
2228f87df16SOlivier Houchard         CK_PR_UNARY(not, S, T, T, "mvn %w0, %w0", W, "w")	\
2238f87df16SOlivier Houchard 
2248f87df16SOlivier Houchard CK_PR_UNARY_S(32, uint32_t, "")
2258f87df16SOlivier Houchard CK_PR_UNARY_S(uint, unsigned int, "")
2268f87df16SOlivier Houchard CK_PR_UNARY_S(int, int, "")
2278f87df16SOlivier Houchard CK_PR_UNARY_S(16, uint16_t, "h")
2288f87df16SOlivier Houchard CK_PR_UNARY_S(8, uint8_t, "b")
2298f87df16SOlivier Houchard CK_PR_UNARY_S(short, short, "h")
2308f87df16SOlivier Houchard CK_PR_UNARY_S(char, char, "b")
2318f87df16SOlivier Houchard 
2328f87df16SOlivier Houchard #undef CK_PR_UNARY_S
2338f87df16SOlivier Houchard #undef CK_PR_UNARY
2348f87df16SOlivier Houchard 
2358f87df16SOlivier Houchard #define CK_PR_BINARY(O, N, M, T, I, W, R)			\
2368f87df16SOlivier Houchard         CK_CC_INLINE static void				\
2378f87df16SOlivier Houchard         ck_pr_##O##_##N(M *target, T delta)			\
2388f87df16SOlivier Houchard         {							\
2398f87df16SOlivier Houchard                 T previous;					\
2408f87df16SOlivier Houchard                 T tmp;						\
2418f87df16SOlivier Houchard                 __asm__ __volatile__("1:"			\
242*74e9b5f2SOlivier Houchard                                      "ldxr" W " %" R "0, [%2]\n"\
243*74e9b5f2SOlivier Houchard                                       I " %" R "0, %" R "0, %" R "3\n"	\
244*74e9b5f2SOlivier Houchard                                      "stxr" W " %w1, %" R "0, [%2]\n"	\
245*74e9b5f2SOlivier Houchard                                      "cbnz %w1, 1b\n"		\
2468f87df16SOlivier Houchard                                         : "=&r" (previous),	\
2478f87df16SOlivier Houchard                                           "=&r" (tmp)		\
2488f87df16SOlivier Houchard                                         : "r"   (target),	\
2498f87df16SOlivier Houchard                                           "r"   (delta)		\
2508f87df16SOlivier Houchard                                         : "memory", "cc");	\
2518f87df16SOlivier Houchard                 return;						\
2528f87df16SOlivier Houchard         }
2538f87df16SOlivier Houchard 
2548f87df16SOlivier Houchard CK_PR_BINARY(and, ptr, void, uintptr_t, "and", "", "")
2558f87df16SOlivier Houchard CK_PR_BINARY(add, ptr, void, uintptr_t, "add", "", "")
2568f87df16SOlivier Houchard CK_PR_BINARY(or, ptr, void, uintptr_t, "orr", "", "")
2578f87df16SOlivier Houchard CK_PR_BINARY(sub, ptr, void, uintptr_t, "sub", "", "")
2588f87df16SOlivier Houchard CK_PR_BINARY(xor, ptr, void, uintptr_t, "eor", "", "")
2598f87df16SOlivier Houchard CK_PR_BINARY(and, 64, uint64_t, uint64_t, "and", "", "")
2608f87df16SOlivier Houchard CK_PR_BINARY(add, 64, uint64_t, uint64_t, "add", "", "")
2618f87df16SOlivier Houchard CK_PR_BINARY(or, 64, uint64_t, uint64_t, "orr", "", "")
2628f87df16SOlivier Houchard CK_PR_BINARY(sub, 64, uint64_t, uint64_t, "sub", "", "")
2638f87df16SOlivier Houchard CK_PR_BINARY(xor, 64, uint64_t, uint64_t, "eor", "", "")
2648f87df16SOlivier Houchard 
2658f87df16SOlivier Houchard #define CK_PR_BINARY_S(S, T, W)				\
2668f87df16SOlivier Houchard         CK_PR_BINARY(and, S, T, T, "and", W, "w")	\
2678f87df16SOlivier Houchard         CK_PR_BINARY(add, S, T, T, "add", W, "w")	\
2688f87df16SOlivier Houchard         CK_PR_BINARY(or, S, T, T, "orr", W, "w")	\
2698f87df16SOlivier Houchard         CK_PR_BINARY(sub, S, T, T, "sub", W, "w")	\
2708f87df16SOlivier Houchard         CK_PR_BINARY(xor, S, T, T, "eor", W, "w")
2718f87df16SOlivier Houchard 
2728f87df16SOlivier Houchard CK_PR_BINARY_S(32, uint32_t, "")
2738f87df16SOlivier Houchard CK_PR_BINARY_S(uint, unsigned int, "")
2748f87df16SOlivier Houchard CK_PR_BINARY_S(int, int, "")
2758f87df16SOlivier Houchard CK_PR_BINARY_S(16, uint16_t, "h")
2768f87df16SOlivier Houchard CK_PR_BINARY_S(8, uint8_t, "b")
2778f87df16SOlivier Houchard CK_PR_BINARY_S(short, short, "h")
2788f87df16SOlivier Houchard CK_PR_BINARY_S(char, char, "b")
2798f87df16SOlivier Houchard 
2808f87df16SOlivier Houchard #undef CK_PR_BINARY_S
2818f87df16SOlivier Houchard #undef CK_PR_BINARY
2828f87df16SOlivier Houchard 
2838f87df16SOlivier Houchard CK_CC_INLINE static void *
ck_pr_faa_ptr(void * target,uintptr_t delta)2848f87df16SOlivier Houchard ck_pr_faa_ptr(void *target, uintptr_t delta)
2858f87df16SOlivier Houchard {
2868f87df16SOlivier Houchard         uintptr_t previous, r, tmp;
2878f87df16SOlivier Houchard 
2888f87df16SOlivier Houchard         __asm__ __volatile__("1:"
289*74e9b5f2SOlivier Houchard                              "ldxr %0, [%3]\n"
290*74e9b5f2SOlivier Houchard                              "add %1, %4, %0\n"
291*74e9b5f2SOlivier Houchard                              "stxr %w2, %1, [%3]\n"
292*74e9b5f2SOlivier Houchard                              "cbnz %w2, 1b\n"
2938f87df16SOlivier Houchard                                 : "=&r" (previous),
2948f87df16SOlivier Houchard                                   "=&r" (r),
2958f87df16SOlivier Houchard                                   "=&r" (tmp)
2968f87df16SOlivier Houchard                                 : "r"   (target),
2978f87df16SOlivier Houchard                                   "r"   (delta)
2988f87df16SOlivier Houchard                                 : "memory", "cc");
2998f87df16SOlivier Houchard 
3008f87df16SOlivier Houchard         return (void *)(previous);
3018f87df16SOlivier Houchard }
3028f87df16SOlivier Houchard 
3038f87df16SOlivier Houchard CK_CC_INLINE static uint64_t
ck_pr_faa_64(uint64_t * target,uint64_t delta)3048f87df16SOlivier Houchard ck_pr_faa_64(uint64_t *target, uint64_t delta)
3058f87df16SOlivier Houchard {
3068f87df16SOlivier Houchard         uint64_t previous, r, tmp;
3078f87df16SOlivier Houchard 
3088f87df16SOlivier Houchard         __asm__ __volatile__("1:"
309*74e9b5f2SOlivier Houchard                              "ldxr %0, [%3]\n"
310*74e9b5f2SOlivier Houchard                              "add %1, %4, %0\n"
311*74e9b5f2SOlivier Houchard                              "stxr %w2, %1, [%3]\n"
3128f87df16SOlivier Houchard                              "cbnz %w2, 1b;"
3138f87df16SOlivier Houchard                                 : "=&r" (previous),
3148f87df16SOlivier Houchard                                   "=&r" (r),
3158f87df16SOlivier Houchard                                   "=&r" (tmp)
3168f87df16SOlivier Houchard                                 : "r"   (target),
3178f87df16SOlivier Houchard                                   "r"   (delta)
3188f87df16SOlivier Houchard                                 : "memory", "cc");
3198f87df16SOlivier Houchard 
3208f87df16SOlivier Houchard         return (previous);
3218f87df16SOlivier Houchard }
3228f87df16SOlivier Houchard 
3238f87df16SOlivier Houchard #define CK_PR_FAA(S, T, W)						\
3248f87df16SOlivier Houchard         CK_CC_INLINE static T						\
3258f87df16SOlivier Houchard         ck_pr_faa_##S(T *target, T delta)				\
3268f87df16SOlivier Houchard         {								\
3278f87df16SOlivier Houchard                 T previous, r, tmp;					\
3288f87df16SOlivier Houchard                 __asm__ __volatile__("1:"				\
329*74e9b5f2SOlivier Houchard                                      "ldxr" W " %w0, [%3]\n"		\
330*74e9b5f2SOlivier Houchard                                      "add %w1, %w4, %w0\n"		\
331*74e9b5f2SOlivier Houchard                                      "stxr" W " %w2, %w1, [%3]\n"	\
332*74e9b5f2SOlivier Houchard                                      "cbnz %w2, 1b\n"			\
3338f87df16SOlivier Houchard                                         : "=&r" (previous),		\
3348f87df16SOlivier Houchard                                           "=&r" (r),			\
3358f87df16SOlivier Houchard                                           "=&r" (tmp)			\
3368f87df16SOlivier Houchard                                         : "r"   (target),		\
3378f87df16SOlivier Houchard                                           "r"   (delta)			\
3388f87df16SOlivier Houchard                                         : "memory", "cc");		\
3398f87df16SOlivier Houchard                 return (previous);					\
3408f87df16SOlivier Houchard         }
3418f87df16SOlivier Houchard 
3428f87df16SOlivier Houchard CK_PR_FAA(32, uint32_t, "")
3438f87df16SOlivier Houchard CK_PR_FAA(uint, unsigned int, "")
3448f87df16SOlivier Houchard CK_PR_FAA(int, int, "")
3458f87df16SOlivier Houchard CK_PR_FAA(16, uint16_t, "h")
3468f87df16SOlivier Houchard CK_PR_FAA(8, uint8_t, "b")
3478f87df16SOlivier Houchard CK_PR_FAA(short, short, "h")
3488f87df16SOlivier Houchard CK_PR_FAA(char, char, "b")
3498f87df16SOlivier Houchard 
3508f87df16SOlivier Houchard #undef CK_PR_FAA
3518f87df16SOlivier Houchard 
3528f87df16SOlivier Houchard #endif /* CK_PR_AARCH64_LLSC_H */
353