xref: /freebsd/sys/contrib/ck/include/gcc/sparcv9/ck_pr.h (revision 67350cb56a69468c118bd4ccf6e361b7ebfa9eb4)
11fb62fb0SOlivier Houchard /*
21fb62fb0SOlivier Houchard  * Copyright 2009, 2010 Samy Al Bahra.
31fb62fb0SOlivier Houchard  * All rights reserved.
41fb62fb0SOlivier Houchard  *
51fb62fb0SOlivier Houchard  * Redistribution and use in source and binary forms, with or without
61fb62fb0SOlivier Houchard  * modification, are permitted provided that the following conditions
71fb62fb0SOlivier Houchard  * are met:
81fb62fb0SOlivier Houchard  * 1. Redistributions of source code must retain the above copyright
91fb62fb0SOlivier Houchard  *    notice, this list of conditions and the following disclaimer.
101fb62fb0SOlivier Houchard  * 2. Redistributions in binary form must reproduce the above copyright
111fb62fb0SOlivier Houchard  *    notice, this list of conditions and the following disclaimer in the
121fb62fb0SOlivier Houchard  *    documentation and/or other materials provided with the distribution.
131fb62fb0SOlivier Houchard  *
141fb62fb0SOlivier Houchard  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
151fb62fb0SOlivier Houchard  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
161fb62fb0SOlivier Houchard  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
171fb62fb0SOlivier Houchard  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
181fb62fb0SOlivier Houchard  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
191fb62fb0SOlivier Houchard  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
201fb62fb0SOlivier Houchard  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
211fb62fb0SOlivier Houchard  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
221fb62fb0SOlivier Houchard  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
231fb62fb0SOlivier Houchard  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
241fb62fb0SOlivier Houchard  * SUCH DAMAGE.
251fb62fb0SOlivier Houchard  */
261fb62fb0SOlivier Houchard 
271fb62fb0SOlivier Houchard #ifndef CK_PR_SPARCV9_H
281fb62fb0SOlivier Houchard #define CK_PR_SPARCV9_H
291fb62fb0SOlivier Houchard 
301fb62fb0SOlivier Houchard #ifndef CK_PR_H
311fb62fb0SOlivier Houchard #error Do not include this file directly, use ck_pr.h
321fb62fb0SOlivier Houchard #endif
331fb62fb0SOlivier Houchard 
341fb62fb0SOlivier Houchard #include <ck_cc.h>
351fb62fb0SOlivier Houchard #include <ck_md.h>
361fb62fb0SOlivier Houchard 
371fb62fb0SOlivier Houchard /*
381fb62fb0SOlivier Houchard  * The following represent supported atomic operations.
391fb62fb0SOlivier Houchard  * These operations may be emulated.
401fb62fb0SOlivier Houchard  */
411fb62fb0SOlivier Houchard #include "ck_f_pr.h"
421fb62fb0SOlivier Houchard 
431fb62fb0SOlivier Houchard /*
441fb62fb0SOlivier Houchard  * Minimum interface requirement met.
451fb62fb0SOlivier Houchard  */
461fb62fb0SOlivier Houchard #define CK_F_PR
471fb62fb0SOlivier Houchard 
481fb62fb0SOlivier Houchard /*
491fb62fb0SOlivier Houchard  * Order loads at the least.
501fb62fb0SOlivier Houchard  */
511fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_pr_stall(void)521fb62fb0SOlivier Houchard ck_pr_stall(void)
531fb62fb0SOlivier Houchard {
541fb62fb0SOlivier Houchard 
551fb62fb0SOlivier Houchard 	__asm__ __volatile__("membar #LoadLoad" ::: "memory");
561fb62fb0SOlivier Houchard 	return;
571fb62fb0SOlivier Houchard }
581fb62fb0SOlivier Houchard 
591fb62fb0SOlivier Houchard #define CK_PR_FENCE(T, I)				\
601fb62fb0SOlivier Houchard 	CK_CC_INLINE static void			\
611fb62fb0SOlivier Houchard 	ck_pr_fence_strict_##T(void)			\
621fb62fb0SOlivier Houchard 	{						\
631fb62fb0SOlivier Houchard 		__asm__ __volatile__(I ::: "memory");   \
641fb62fb0SOlivier Houchard 	}
651fb62fb0SOlivier Houchard 
661fb62fb0SOlivier Houchard /*
671fb62fb0SOlivier Houchard  * Atomic operations are treated as both load and store
681fb62fb0SOlivier Houchard  * operations on SPARCv9.
691fb62fb0SOlivier Houchard  */
701fb62fb0SOlivier Houchard CK_PR_FENCE(atomic, "membar #StoreStore")
711fb62fb0SOlivier Houchard CK_PR_FENCE(atomic_store, "membar #StoreStore")
721fb62fb0SOlivier Houchard CK_PR_FENCE(atomic_load, "membar #StoreLoad")
731fb62fb0SOlivier Houchard CK_PR_FENCE(store_atomic, "membar #StoreStore")
741fb62fb0SOlivier Houchard CK_PR_FENCE(load_atomic, "membar #LoadStore")
751fb62fb0SOlivier Houchard CK_PR_FENCE(store, "membar #StoreStore")
761fb62fb0SOlivier Houchard CK_PR_FENCE(store_load, "membar #StoreLoad")
771fb62fb0SOlivier Houchard CK_PR_FENCE(load, "membar #LoadLoad")
781fb62fb0SOlivier Houchard CK_PR_FENCE(load_store, "membar #LoadStore")
79271ce402SOlivier Houchard CK_PR_FENCE(memory, "membar #MemIssue")
801fb62fb0SOlivier Houchard CK_PR_FENCE(acquire, "membar #LoadLoad | #LoadStore")
811fb62fb0SOlivier Houchard CK_PR_FENCE(release, "membar #LoadStore | #StoreStore")
821fb62fb0SOlivier Houchard CK_PR_FENCE(acqrel, "membar #LoadLoad | #LoadStore | #StoreStore")
831fb62fb0SOlivier Houchard CK_PR_FENCE(lock, "membar #LoadLoad | #LoadStore | #StoreStore | #StoreLoad")
841fb62fb0SOlivier Houchard CK_PR_FENCE(unlock, "membar #LoadStore | #StoreStore")
851fb62fb0SOlivier Houchard 
861fb62fb0SOlivier Houchard #undef CK_PR_FENCE
871fb62fb0SOlivier Houchard 
881fb62fb0SOlivier Houchard #define CK_PR_LOAD(S, M, T, C, I)				\
891fb62fb0SOlivier Houchard 	CK_CC_INLINE static T					\
901fb62fb0SOlivier Houchard 	ck_pr_md_load_##S(const M *target)			\
911fb62fb0SOlivier Houchard 	{							\
921fb62fb0SOlivier Houchard 		T r;						\
931fb62fb0SOlivier Houchard 		__asm__ __volatile__(I " [%1], %0"		\
941fb62fb0SOlivier Houchard 					: "=&r" (r)		\
951fb62fb0SOlivier Houchard 					: "r"   (target)	\
961fb62fb0SOlivier Houchard 					: "memory");		\
971fb62fb0SOlivier Houchard 		return (r);					\
981fb62fb0SOlivier Houchard 	}
991fb62fb0SOlivier Houchard 
1001fb62fb0SOlivier Houchard CK_PR_LOAD(ptr, void, void *, uint64_t, "ldx")
1011fb62fb0SOlivier Houchard 
1021fb62fb0SOlivier Houchard #define CK_PR_LOAD_S(S, T, I) CK_PR_LOAD(S, T, T, T, I)
1031fb62fb0SOlivier Houchard 
1041fb62fb0SOlivier Houchard CK_PR_LOAD_S(64, uint64_t, "ldx")
1051fb62fb0SOlivier Houchard CK_PR_LOAD_S(32, uint32_t, "lduw")
1061fb62fb0SOlivier Houchard CK_PR_LOAD_S(uint, unsigned int, "lduw")
1071fb62fb0SOlivier Houchard CK_PR_LOAD_S(double, double, "ldx")
1081fb62fb0SOlivier Houchard CK_PR_LOAD_S(int, int, "ldsw")
1091fb62fb0SOlivier Houchard 
1101fb62fb0SOlivier Houchard #undef CK_PR_LOAD_S
1111fb62fb0SOlivier Houchard #undef CK_PR_LOAD
1121fb62fb0SOlivier Houchard 
1131fb62fb0SOlivier Houchard #define CK_PR_STORE(S, M, T, C, I)				\
1141fb62fb0SOlivier Houchard 	CK_CC_INLINE static void				\
1151fb62fb0SOlivier Houchard 	ck_pr_md_store_##S(M *target, T v)			\
1161fb62fb0SOlivier Houchard 	{							\
1171fb62fb0SOlivier Houchard 		__asm__ __volatile__(I " %0, [%1]"		\
1181fb62fb0SOlivier Houchard 					:			\
1191fb62fb0SOlivier Houchard 					: "r" (v),		\
1201fb62fb0SOlivier Houchard 					  "r" (target)		\
1211fb62fb0SOlivier Houchard 					: "memory");		\
1221fb62fb0SOlivier Houchard 		return;						\
1231fb62fb0SOlivier Houchard 	}
1241fb62fb0SOlivier Houchard 
1251fb62fb0SOlivier Houchard CK_PR_STORE(ptr, void, const void *, uint64_t, "stx")
1261fb62fb0SOlivier Houchard 
1271fb62fb0SOlivier Houchard #define CK_PR_STORE_S(S, T, I) CK_PR_STORE(S, T, T, T, I)
1281fb62fb0SOlivier Houchard 
1291fb62fb0SOlivier Houchard CK_PR_STORE_S(8, uint8_t, "stub")
1301fb62fb0SOlivier Houchard CK_PR_STORE_S(64, uint64_t, "stx")
1311fb62fb0SOlivier Houchard CK_PR_STORE_S(32, uint32_t, "stuw")
1321fb62fb0SOlivier Houchard CK_PR_STORE_S(uint, unsigned int, "stuw")
1331fb62fb0SOlivier Houchard CK_PR_STORE_S(double, double, "stx")
1341fb62fb0SOlivier Houchard CK_PR_STORE_S(int, int, "stsw")
1351fb62fb0SOlivier Houchard 
1361fb62fb0SOlivier Houchard #undef CK_PR_STORE_S
1371fb62fb0SOlivier Houchard #undef CK_PR_STORE
1381fb62fb0SOlivier Houchard 
139*f9931172SMarius Strobl /* Use the appropriate address space for atomics within the FreeBSD kernel. */
140*f9931172SMarius Strobl #if defined(__FreeBSD__) && defined(_KERNEL)
141*f9931172SMarius Strobl #include <sys/cdefs.h>
142*f9931172SMarius Strobl #include <machine/atomic.h>
143*f9931172SMarius Strobl #define CK_PR_INS_CAS "casa"
144*f9931172SMarius Strobl #define CK_PR_INS_CASX "casxa"
145*f9931172SMarius Strobl #define CK_PR_INS_SWAP "swapa"
146*f9931172SMarius Strobl #define CK_PR_ASI_ATOMIC __XSTRING(__ASI_ATOMIC)
147*f9931172SMarius Strobl #else
148*f9931172SMarius Strobl #define CK_PR_INS_CAS "cas"
149*f9931172SMarius Strobl #define CK_PR_INS_CASX "casx"
150*f9931172SMarius Strobl #define CK_PR_INS_SWAP "swap"
151*f9931172SMarius Strobl #define CK_PR_ASI_ATOMIC ""
152*f9931172SMarius Strobl #endif
153*f9931172SMarius Strobl 
1541fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_pr_cas_64_value(uint64_t * target,uint64_t compare,uint64_t set,uint64_t * value)1551fb62fb0SOlivier Houchard ck_pr_cas_64_value(uint64_t *target, uint64_t compare, uint64_t set, uint64_t *value)
1561fb62fb0SOlivier Houchard {
1571fb62fb0SOlivier Houchard 
158*f9931172SMarius Strobl 	__asm__ __volatile__(CK_PR_INS_CASX " [%1] " CK_PR_ASI_ATOMIC ", %2, %0"
1591fb62fb0SOlivier Houchard 				: "+&r" (set)
1601fb62fb0SOlivier Houchard 				: "r"   (target),
1611fb62fb0SOlivier Houchard 				  "r"   (compare)
1621fb62fb0SOlivier Houchard 				: "memory");
1631fb62fb0SOlivier Houchard 
1641fb62fb0SOlivier Houchard 	*value = set;
1651fb62fb0SOlivier Houchard 	return (compare == set);
1661fb62fb0SOlivier Houchard }
1671fb62fb0SOlivier Houchard 
1681fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_pr_cas_64(uint64_t * target,uint64_t compare,uint64_t set)1691fb62fb0SOlivier Houchard ck_pr_cas_64(uint64_t *target, uint64_t compare, uint64_t set)
1701fb62fb0SOlivier Houchard {
1711fb62fb0SOlivier Houchard 
172*f9931172SMarius Strobl 	__asm__ __volatile__(CK_PR_INS_CASX " [%1] " CK_PR_ASI_ATOMIC ", %2, %0"
1731fb62fb0SOlivier Houchard 				: "+&r" (set)
1741fb62fb0SOlivier Houchard 				: "r" (target),
1751fb62fb0SOlivier Houchard 				  "r" (compare)
1761fb62fb0SOlivier Houchard 				: "memory");
1771fb62fb0SOlivier Houchard 
1781fb62fb0SOlivier Houchard 	return (compare == set);
1791fb62fb0SOlivier Houchard }
1801fb62fb0SOlivier Houchard 
1811fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_pr_cas_ptr(void * target,void * compare,void * set)1821fb62fb0SOlivier Houchard ck_pr_cas_ptr(void *target, void *compare, void *set)
1831fb62fb0SOlivier Houchard {
1841fb62fb0SOlivier Houchard 
1851fb62fb0SOlivier Houchard 	return ck_pr_cas_64(target, (uint64_t)compare, (uint64_t)set);
1861fb62fb0SOlivier Houchard }
1871fb62fb0SOlivier Houchard 
1881fb62fb0SOlivier Houchard CK_CC_INLINE static bool
ck_pr_cas_ptr_value(void * target,void * compare,void * set,void * previous)1891fb62fb0SOlivier Houchard ck_pr_cas_ptr_value(void *target, void *compare, void *set, void *previous)
1901fb62fb0SOlivier Houchard {
1911fb62fb0SOlivier Houchard 
1921fb62fb0SOlivier Houchard 	return ck_pr_cas_64_value(target, (uint64_t)compare, (uint64_t)set, previous);
1931fb62fb0SOlivier Houchard }
1941fb62fb0SOlivier Houchard 
1951fb62fb0SOlivier Houchard #define CK_PR_CAS(N, T)							\
1961fb62fb0SOlivier Houchard 	CK_CC_INLINE static bool					\
1971fb62fb0SOlivier Houchard 	ck_pr_cas_##N##_value(T *target, T compare, T set, T *value)	\
1981fb62fb0SOlivier Houchard 	{								\
199*f9931172SMarius Strobl 		__asm__ __volatile__(CK_PR_INS_CAS " [%1] " CK_PR_ASI_ATOMIC ", %2, %0" \
2001fb62fb0SOlivier Houchard 					: "+&r" (set)			\
2011fb62fb0SOlivier Houchard 					: "r"   (target),		\
2021fb62fb0SOlivier Houchard 					  "r"   (compare)		\
2031fb62fb0SOlivier Houchard 					: "memory");			\
2041fb62fb0SOlivier Houchard 		*value = set;						\
2051fb62fb0SOlivier Houchard 		return (compare == set);				\
2061fb62fb0SOlivier Houchard 	} 								\
2071fb62fb0SOlivier Houchard 	CK_CC_INLINE static bool					\
2081fb62fb0SOlivier Houchard 	ck_pr_cas_##N(T *target, T compare, T set)			\
2091fb62fb0SOlivier Houchard 	{								\
210*f9931172SMarius Strobl 		__asm__ __volatile__(CK_PR_INS_CAS " [%1] " CK_PR_ASI_ATOMIC ", %2, %0" \
2111fb62fb0SOlivier Houchard 					: "+&r" (set)			\
2121fb62fb0SOlivier Houchard 					: "r" (target),			\
2131fb62fb0SOlivier Houchard 					  "r" (compare)			\
2141fb62fb0SOlivier Houchard 					: "memory");			\
2151fb62fb0SOlivier Houchard 		return (compare == set);				\
2161fb62fb0SOlivier Houchard 	}
2171fb62fb0SOlivier Houchard 
2181fb62fb0SOlivier Houchard CK_PR_CAS(32, uint32_t)
2191fb62fb0SOlivier Houchard CK_PR_CAS(uint, unsigned int)
2201fb62fb0SOlivier Houchard CK_PR_CAS(int, int)
2211fb62fb0SOlivier Houchard 
2221fb62fb0SOlivier Houchard #undef CK_PR_CAS
2231fb62fb0SOlivier Houchard 
2241fb62fb0SOlivier Houchard #define CK_PR_FAS(N, T)						\
2251fb62fb0SOlivier Houchard 	CK_CC_INLINE static T 					\
2261fb62fb0SOlivier Houchard 	ck_pr_fas_##N(T *target, T update)			\
2271fb62fb0SOlivier Houchard 	{							\
2281fb62fb0SOlivier Houchard 								\
229*f9931172SMarius Strobl 		__asm__ __volatile__(CK_PR_INS_SWAP " [%1] " CK_PR_ASI_ATOMIC ", %0"		\
2301fb62fb0SOlivier Houchard 					: "+&r" (update)	\
2311fb62fb0SOlivier Houchard 					: "r"   (target)	\
2321fb62fb0SOlivier Houchard 					: "memory");		\
2331fb62fb0SOlivier Houchard 		return (update);				\
2341fb62fb0SOlivier Houchard 	}
2351fb62fb0SOlivier Houchard 
2361fb62fb0SOlivier Houchard CK_PR_FAS(int, int)
2371fb62fb0SOlivier Houchard CK_PR_FAS(uint, unsigned int)
2381fb62fb0SOlivier Houchard CK_PR_FAS(32, uint32_t)
2391fb62fb0SOlivier Houchard 
2401fb62fb0SOlivier Houchard #undef CK_PR_FAS
2411fb62fb0SOlivier Houchard 
242*f9931172SMarius Strobl #undef CK_PR_INS_CAS
243*f9931172SMarius Strobl #undef CK_PR_INS_CASX
244*f9931172SMarius Strobl #undef CK_PR_INS_SWAP
245*f9931172SMarius Strobl #undef CK_PR_ASI_ATOMIC
246*f9931172SMarius Strobl 
2471fb62fb0SOlivier Houchard #endif /* CK_PR_SPARCV9_H */
2481fb62fb0SOlivier Houchard 
249