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