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