xref: /freebsd/sys/contrib/ck/include/gcc/aarch64/ck_pr.h (revision b5ed3ef802ebfed6f08008bff602834b18f83a11)
11fb62fb0SOlivier Houchard /*
21fb62fb0SOlivier Houchard  * Copyright 2009-2016 Samy Al Bahra.
31fb62fb0SOlivier Houchard  * Copyright 2013-2016 Olivier Houchard.
41fb62fb0SOlivier Houchard  * All rights reserved.
51fb62fb0SOlivier Houchard  *
61fb62fb0SOlivier Houchard  * Redistribution and use in source and binary forms, with or without
71fb62fb0SOlivier Houchard  * modification, are permitted provided that the following conditions
81fb62fb0SOlivier Houchard  * are met:
91fb62fb0SOlivier Houchard  * 1. Redistributions of source code must retain the above copyright
101fb62fb0SOlivier Houchard  *    notice, this list of conditions and the following disclaimer.
111fb62fb0SOlivier Houchard  * 2. Redistributions in binary form must reproduce the above copyright
121fb62fb0SOlivier Houchard  *    notice, this list of conditions and the following disclaimer in the
131fb62fb0SOlivier Houchard  *    documentation and/or other materials provided with the distribution.
141fb62fb0SOlivier Houchard  *
151fb62fb0SOlivier Houchard  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
161fb62fb0SOlivier Houchard  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
171fb62fb0SOlivier Houchard  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
181fb62fb0SOlivier Houchard  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
191fb62fb0SOlivier Houchard  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
201fb62fb0SOlivier Houchard  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
211fb62fb0SOlivier Houchard  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
221fb62fb0SOlivier Houchard  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
231fb62fb0SOlivier Houchard  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
241fb62fb0SOlivier Houchard  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
251fb62fb0SOlivier Houchard  * SUCH DAMAGE.
261fb62fb0SOlivier Houchard  */
271fb62fb0SOlivier Houchard 
281fb62fb0SOlivier Houchard #ifndef CK_PR_AARCH64_H
291fb62fb0SOlivier Houchard #define CK_PR_AARCH64_H
301fb62fb0SOlivier Houchard 
311fb62fb0SOlivier Houchard #ifndef CK_PR_H
321fb62fb0SOlivier Houchard #error Do not include this file directly, use ck_pr.h
331fb62fb0SOlivier Houchard #endif
341fb62fb0SOlivier Houchard 
351fb62fb0SOlivier Houchard #include <ck_cc.h>
361fb62fb0SOlivier Houchard #include <ck_md.h>
371fb62fb0SOlivier Houchard 
381fb62fb0SOlivier Houchard /*
391fb62fb0SOlivier Houchard  * The following represent supported atomic operations.
401fb62fb0SOlivier Houchard  * These operations may be emulated.
411fb62fb0SOlivier Houchard  */
421fb62fb0SOlivier Houchard #include "ck_f_pr.h"
431fb62fb0SOlivier Houchard 
441fb62fb0SOlivier Houchard /*
451fb62fb0SOlivier Houchard  * Minimum interface requirement met.
461fb62fb0SOlivier Houchard  */
471fb62fb0SOlivier Houchard #define CK_F_PR
481fb62fb0SOlivier Houchard 
491fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_pr_stall(void)501fb62fb0SOlivier Houchard ck_pr_stall(void)
511fb62fb0SOlivier Houchard {
521fb62fb0SOlivier Houchard 
531fb62fb0SOlivier Houchard 	__asm__ __volatile__("" ::: "memory");
541fb62fb0SOlivier Houchard 	return;
551fb62fb0SOlivier Houchard }
561fb62fb0SOlivier Houchard 
571fb62fb0SOlivier Houchard #define CK_DMB_SY __asm __volatile("dmb ish" : : "r" (0) : "memory")
581fb62fb0SOlivier Houchard #define CK_DMB_LD __asm __volatile("dmb ishld" : : "r" (0) : "memory")
591fb62fb0SOlivier Houchard #define CK_DMB_ST __asm __volatile("dmb ishst" : : "r" (0) : "memory")
601fb62fb0SOlivier Houchard 
611fb62fb0SOlivier Houchard #define CK_PR_FENCE(T, I)				\
621fb62fb0SOlivier Houchard 	CK_CC_INLINE static void			\
631fb62fb0SOlivier Houchard 	ck_pr_fence_strict_##T(void)			\
641fb62fb0SOlivier Houchard 	{						\
651fb62fb0SOlivier Houchard 		I;					\
661fb62fb0SOlivier Houchard 	}
671fb62fb0SOlivier Houchard 
681fb62fb0SOlivier Houchard CK_PR_FENCE(atomic, CK_DMB_ST)
691fb62fb0SOlivier Houchard CK_PR_FENCE(atomic_store, CK_DMB_ST)
701fb62fb0SOlivier Houchard CK_PR_FENCE(atomic_load, CK_DMB_SY)
711fb62fb0SOlivier Houchard CK_PR_FENCE(store_atomic, CK_DMB_ST)
721fb62fb0SOlivier Houchard CK_PR_FENCE(load_atomic, CK_DMB_SY)
731fb62fb0SOlivier Houchard CK_PR_FENCE(store, CK_DMB_ST)
741fb62fb0SOlivier Houchard CK_PR_FENCE(store_load, CK_DMB_SY)
751fb62fb0SOlivier Houchard CK_PR_FENCE(load, CK_DMB_LD)
761fb62fb0SOlivier Houchard CK_PR_FENCE(load_store, CK_DMB_SY)
771fb62fb0SOlivier Houchard CK_PR_FENCE(memory, CK_DMB_SY)
781fb62fb0SOlivier Houchard CK_PR_FENCE(acquire, CK_DMB_SY)
791fb62fb0SOlivier Houchard CK_PR_FENCE(release, CK_DMB_SY)
801fb62fb0SOlivier Houchard CK_PR_FENCE(acqrel, CK_DMB_SY)
811fb62fb0SOlivier Houchard CK_PR_FENCE(lock, CK_DMB_SY)
821fb62fb0SOlivier Houchard CK_PR_FENCE(unlock, CK_DMB_SY)
831fb62fb0SOlivier Houchard 
841fb62fb0SOlivier Houchard #undef CK_PR_FENCE
851fb62fb0SOlivier Houchard 
861fb62fb0SOlivier Houchard #undef CK_DMB_SI
871fb62fb0SOlivier Houchard #undef CK_DMB_LD
881fb62fb0SOlivier Houchard #undef CK_DMB_ST
891fb62fb0SOlivier Houchard 
901fb62fb0SOlivier Houchard #define CK_PR_LOAD(S, M, T, I)				\
911fb62fb0SOlivier Houchard 	CK_CC_INLINE static T					\
921fb62fb0SOlivier Houchard 	ck_pr_md_load_##S(const M *target)			\
931fb62fb0SOlivier Houchard 	{							\
941fb62fb0SOlivier Houchard 		long r = 0;					\
9574e9b5f2SOlivier Houchard 		__asm__ __volatile__(I " %w0, [%1]\n"		\
961fb62fb0SOlivier Houchard 					: "=r" (r)		\
971fb62fb0SOlivier Houchard 					: "r"  (target)		\
981fb62fb0SOlivier Houchard 					: "memory");		\
991fb62fb0SOlivier Houchard 		return ((T)r);					\
1001fb62fb0SOlivier Houchard 	}
1011fb62fb0SOlivier Houchard #define CK_PR_LOAD_64(S, M, T, I)				\
1021fb62fb0SOlivier Houchard 	CK_CC_INLINE static T					\
1031fb62fb0SOlivier Houchard 	ck_pr_md_load_##S(const M *target)			\
1041fb62fb0SOlivier Houchard 	{							\
1051fb62fb0SOlivier Houchard 		long r = 0;					\
10674e9b5f2SOlivier Houchard 		__asm__ __volatile__(I " %0, [%1]\n"		\
1071fb62fb0SOlivier Houchard 					: "=r" (r)		\
1081fb62fb0SOlivier Houchard 					: "r"  (target)		\
1091fb62fb0SOlivier Houchard 					: "memory");		\
1101fb62fb0SOlivier Houchard 		return ((T)r);					\
1111fb62fb0SOlivier Houchard 	}
1121fb62fb0SOlivier Houchard 
1131fb62fb0SOlivier Houchard 
1141fb62fb0SOlivier Houchard CK_PR_LOAD_64(ptr, void, void *, "ldr")
1151fb62fb0SOlivier Houchard 
1161fb62fb0SOlivier Houchard #define CK_PR_LOAD_S(S, T, I) CK_PR_LOAD(S, T, T, I)
1171fb62fb0SOlivier Houchard #define CK_PR_LOAD_S_64(S, T, I) CK_PR_LOAD_64(S, T, T, I)
1181fb62fb0SOlivier Houchard 
1191fb62fb0SOlivier Houchard CK_PR_LOAD_S_64(64, uint64_t, "ldr")
1201fb62fb0SOlivier Houchard CK_PR_LOAD_S(32, uint32_t, "ldr")
1211fb62fb0SOlivier Houchard CK_PR_LOAD_S(16, uint16_t, "ldrh")
1221fb62fb0SOlivier Houchard CK_PR_LOAD_S(8, uint8_t, "ldrb")
1231fb62fb0SOlivier Houchard CK_PR_LOAD_S(uint, unsigned int, "ldr")
1241fb62fb0SOlivier Houchard CK_PR_LOAD_S(int, int, "ldr")
1251fb62fb0SOlivier Houchard CK_PR_LOAD_S(short, short, "ldrh")
1261fb62fb0SOlivier Houchard CK_PR_LOAD_S(char, char, "ldrb")
1278f87df16SOlivier Houchard #ifndef CK_PR_DISABLE_DOUBLE
1281fb62fb0SOlivier Houchard CK_PR_LOAD_S_64(double, double, "ldr")
1298f87df16SOlivier Houchard #endif
1301fb62fb0SOlivier Houchard 
1311fb62fb0SOlivier Houchard #undef CK_PR_LOAD_S
1321fb62fb0SOlivier Houchard #undef CK_PR_LOAD_S_64
1331fb62fb0SOlivier Houchard #undef CK_PR_LOAD
1341fb62fb0SOlivier Houchard #undef CK_PR_LAOD_64
1351fb62fb0SOlivier Houchard 
1361fb62fb0SOlivier Houchard #define CK_PR_STORE(S, M, T, I)					\
1371fb62fb0SOlivier Houchard 	CK_CC_INLINE static void				\
1381fb62fb0SOlivier Houchard 	ck_pr_md_store_##S(M *target, T v)			\
1391fb62fb0SOlivier Houchard 	{							\
140*b5ed3ef8SMark Johnston 		__asm__ __volatile__(I " %w2, [%1]"		\
141*b5ed3ef8SMark Johnston 					: "=m" (*(T *)target)	\
1421fb62fb0SOlivier Houchard 					: "r" (target),		\
1431fb62fb0SOlivier Houchard 					  "r" (v)		\
1441fb62fb0SOlivier Houchard 					: "memory");		\
1451fb62fb0SOlivier Houchard 		return;						\
1461fb62fb0SOlivier Houchard 	}
1471fb62fb0SOlivier Houchard #define CK_PR_STORE_64(S, M, T, I)				\
1481fb62fb0SOlivier Houchard 	CK_CC_INLINE static void				\
1491fb62fb0SOlivier Houchard 	ck_pr_md_store_##S(M *target, T v)			\
1501fb62fb0SOlivier Houchard 	{							\
151*b5ed3ef8SMark Johnston 		__asm__ __volatile__(I " %2, [%1]"		\
152*b5ed3ef8SMark Johnston 					: "=m" (*(T *)target)	\
1531fb62fb0SOlivier Houchard 					: "r" (target),		\
1541fb62fb0SOlivier Houchard 					  "r" (v)		\
1551fb62fb0SOlivier Houchard 					: "memory");		\
1561fb62fb0SOlivier Houchard 		return;						\
1571fb62fb0SOlivier Houchard 	}
1581fb62fb0SOlivier Houchard 
1591fb62fb0SOlivier Houchard CK_PR_STORE_64(ptr, void, const void *, "str")
1601fb62fb0SOlivier Houchard 
1611fb62fb0SOlivier Houchard #define CK_PR_STORE_S(S, T, I) CK_PR_STORE(S, T, T, I)
1621fb62fb0SOlivier Houchard #define CK_PR_STORE_S_64(S, T, I) CK_PR_STORE_64(S, T, T, I)
1631fb62fb0SOlivier Houchard 
1641fb62fb0SOlivier Houchard CK_PR_STORE_S_64(64, uint64_t, "str")
1651fb62fb0SOlivier Houchard CK_PR_STORE_S(32, uint32_t, "str")
1661fb62fb0SOlivier Houchard CK_PR_STORE_S(16, uint16_t, "strh")
1671fb62fb0SOlivier Houchard CK_PR_STORE_S(8, uint8_t, "strb")
1681fb62fb0SOlivier Houchard CK_PR_STORE_S(uint, unsigned int, "str")
1691fb62fb0SOlivier Houchard CK_PR_STORE_S(int, int, "str")
1701fb62fb0SOlivier Houchard CK_PR_STORE_S(short, short, "strh")
1711fb62fb0SOlivier Houchard CK_PR_STORE_S(char, char, "strb")
1728f87df16SOlivier Houchard #ifndef CK_PR_DISABLE_DOUBLE
1731fb62fb0SOlivier Houchard CK_PR_STORE_S_64(double, double, "str")
1748f87df16SOlivier Houchard #endif
1751fb62fb0SOlivier Houchard 
1761fb62fb0SOlivier Houchard #undef CK_PR_STORE_S
1771fb62fb0SOlivier Houchard #undef CK_PR_STORE_S_64
1781fb62fb0SOlivier Houchard #undef CK_PR_STORE
1791fb62fb0SOlivier Houchard #undef CK_PR_STORE_64
1801fb62fb0SOlivier Houchard 
1818f87df16SOlivier Houchard #ifdef CK_MD_LSE_ENABLE
1828f87df16SOlivier Houchard #include "ck_pr_lse.h"
1838f87df16SOlivier Houchard #else
1848f87df16SOlivier Houchard #include "ck_pr_llsc.h"
1858f87df16SOlivier Houchard #endif
1861fb62fb0SOlivier Houchard 
1878f87df16SOlivier Houchard /*
1888f87df16SOlivier Houchard  * ck_pr_neg_*() functions can only be implemented via LL/SC, as there are no
1898f87df16SOlivier Houchard  * LSE alternatives.
1908f87df16SOlivier Houchard  */
1918f87df16SOlivier Houchard #define CK_PR_NEG(N, M, T, W, R)				\
1921fb62fb0SOlivier Houchard         CK_CC_INLINE static void				\
1938f87df16SOlivier Houchard         ck_pr_neg_##N(M *target)				\
1941fb62fb0SOlivier Houchard         {							\
1951fb62fb0SOlivier Houchard                 T previous = 0;					\
1961fb62fb0SOlivier Houchard                 T tmp = 0;					\
1971fb62fb0SOlivier Houchard                 __asm__ __volatile__("1:"			\
19874e9b5f2SOlivier Houchard                                      "ldxr" W " %" R "0, [%2]\n"\
19974e9b5f2SOlivier Houchard                                      "neg %" R "0, %" R "0\n"	\
20074e9b5f2SOlivier Houchard                                      "stxr" W " %w1, %" R "0, [%2]\n"	\
20174e9b5f2SOlivier Houchard                                      "cbnz %w1, 1b\n"		\
2021fb62fb0SOlivier Houchard                                         : "=&r" (previous),	\
2031fb62fb0SOlivier Houchard                                           "=&r" (tmp)		\
2041fb62fb0SOlivier Houchard                                         : "r"   (target)	\
2051fb62fb0SOlivier Houchard                                         : "memory", "cc");	\
2061fb62fb0SOlivier Houchard                 return;						\
2071fb62fb0SOlivier Houchard         }
2081fb62fb0SOlivier Houchard 
2098f87df16SOlivier Houchard CK_PR_NEG(ptr, void, void *, "", "")
2108f87df16SOlivier Houchard CK_PR_NEG(64, uint64_t, uint64_t, "", "")
2111fb62fb0SOlivier Houchard 
2128f87df16SOlivier Houchard #define CK_PR_NEG_S(S, T, W)					\
2138f87df16SOlivier Houchard         CK_PR_NEG(S, T, T, W, "w")				\
2141fb62fb0SOlivier Houchard 
2158f87df16SOlivier Houchard CK_PR_NEG_S(32, uint32_t, "")
2168f87df16SOlivier Houchard CK_PR_NEG_S(uint, unsigned int, "")
2178f87df16SOlivier Houchard CK_PR_NEG_S(int, int, "")
2188f87df16SOlivier Houchard CK_PR_NEG_S(16, uint16_t, "h")
2198f87df16SOlivier Houchard CK_PR_NEG_S(8, uint8_t, "b")
2208f87df16SOlivier Houchard CK_PR_NEG_S(short, short, "h")
2218f87df16SOlivier Houchard CK_PR_NEG_S(char, char, "b")
2221fb62fb0SOlivier Houchard 
2238f87df16SOlivier Houchard #undef CK_PR_NEG_S
2248f87df16SOlivier Houchard #undef CK_PR_NEG
2251fb62fb0SOlivier Houchard 
2261fb62fb0SOlivier Houchard #endif /* CK_PR_AARCH64_H */
2271fb62fb0SOlivier Houchard 
228