11fb62fb0SOlivier Houchard /*
21fb62fb0SOlivier Houchard * Copyright 2009-2015 Samy Al Bahra.
31fb62fb0SOlivier Houchard * Copyright 2011 Devon H. O'Dell <devon.odell@gmail.com>
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_X86_H
291fb62fb0SOlivier Houchard #define CK_PR_X86_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 #include <ck_stdint.h>
381fb62fb0SOlivier Houchard
391fb62fb0SOlivier Houchard /*
401fb62fb0SOlivier Houchard * The following represent supported atomic operations.
411fb62fb0SOlivier Houchard * These operations may be emulated.
421fb62fb0SOlivier Houchard */
431fb62fb0SOlivier Houchard #include "ck_f_pr.h"
441fb62fb0SOlivier Houchard
451fb62fb0SOlivier Houchard /* Minimum requirements for the CK_PR interface are met. */
461fb62fb0SOlivier Houchard #define CK_F_PR
471fb62fb0SOlivier Houchard
481fb62fb0SOlivier Houchard /*
49271ce402SOlivier Houchard * Prevent speculative execution in busy-wait loops (P4 <=) or "predefined
50271ce402SOlivier Houchard * delay".
511fb62fb0SOlivier Houchard */
521fb62fb0SOlivier Houchard CK_CC_INLINE static void
ck_pr_stall(void)531fb62fb0SOlivier Houchard ck_pr_stall(void)
541fb62fb0SOlivier Houchard {
551fb62fb0SOlivier Houchard __asm__ __volatile__("pause" ::: "memory");
561fb62fb0SOlivier Houchard return;
571fb62fb0SOlivier Houchard }
581fb62fb0SOlivier Houchard
59271ce402SOlivier Houchard #ifdef CK_MD_UMP
60271ce402SOlivier Houchard #define CK_PR_LOCK_PREFIX
61271ce402SOlivier Houchard #define CK_PR_FENCE(T, I) \
62271ce402SOlivier Houchard CK_CC_INLINE static void \
63271ce402SOlivier Houchard ck_pr_fence_strict_##T(void) \
64271ce402SOlivier Houchard { \
65271ce402SOlivier Houchard __asm__ __volatile__("" ::: "memory"); \
66271ce402SOlivier Houchard return; \
67271ce402SOlivier Houchard }
68271ce402SOlivier Houchard #else
69271ce402SOlivier Houchard #define CK_PR_LOCK_PREFIX "lock "
701fb62fb0SOlivier Houchard #define CK_PR_FENCE(T, I) \
711fb62fb0SOlivier Houchard CK_CC_INLINE static void \
721fb62fb0SOlivier Houchard ck_pr_fence_strict_##T(void) \
731fb62fb0SOlivier Houchard { \
741fb62fb0SOlivier Houchard __asm__ __volatile__(I ::: "memory"); \
75271ce402SOlivier Houchard return; \
761fb62fb0SOlivier Houchard }
77271ce402SOlivier Houchard #endif /* CK_MD_UMP */
781fb62fb0SOlivier Houchard
79271ce402SOlivier Houchard #if defined(CK_MD_SSE_DISABLE)
80271ce402SOlivier Houchard /* If SSE is disabled, then use atomic operations for serialization. */
81271ce402SOlivier Houchard #define CK_MD_X86_MFENCE "lock addl $0, (%%esp)"
82271ce402SOlivier Houchard #define CK_MD_X86_SFENCE CK_MD_X86_MFENCE
83271ce402SOlivier Houchard #define CK_MD_X86_LFENCE CK_MD_X86_MFENCE
84271ce402SOlivier Houchard #else
85271ce402SOlivier Houchard #define CK_MD_X86_SFENCE "sfence"
86271ce402SOlivier Houchard #define CK_MD_X86_LFENCE "lfence"
87271ce402SOlivier Houchard #define CK_MD_X86_MFENCE "mfence"
88271ce402SOlivier Houchard #endif /* !CK_MD_SSE_DISABLE */
89271ce402SOlivier Houchard
90271ce402SOlivier Houchard CK_PR_FENCE(atomic, "")
91271ce402SOlivier Houchard CK_PR_FENCE(atomic_store, "")
92271ce402SOlivier Houchard CK_PR_FENCE(atomic_load, "")
93271ce402SOlivier Houchard CK_PR_FENCE(store_atomic, "")
94271ce402SOlivier Houchard CK_PR_FENCE(load_atomic, "")
95271ce402SOlivier Houchard CK_PR_FENCE(load, CK_MD_X86_LFENCE)
96271ce402SOlivier Houchard CK_PR_FENCE(load_store, CK_MD_X86_MFENCE)
97271ce402SOlivier Houchard CK_PR_FENCE(store, CK_MD_X86_SFENCE)
98271ce402SOlivier Houchard CK_PR_FENCE(store_load, CK_MD_X86_MFENCE)
99271ce402SOlivier Houchard CK_PR_FENCE(memory, CK_MD_X86_MFENCE)
100271ce402SOlivier Houchard CK_PR_FENCE(release, CK_MD_X86_MFENCE)
101271ce402SOlivier Houchard CK_PR_FENCE(acquire, CK_MD_X86_MFENCE)
102271ce402SOlivier Houchard CK_PR_FENCE(acqrel, CK_MD_X86_MFENCE)
103271ce402SOlivier Houchard CK_PR_FENCE(lock, CK_MD_X86_MFENCE)
104271ce402SOlivier Houchard CK_PR_FENCE(unlock, CK_MD_X86_MFENCE)
1051fb62fb0SOlivier Houchard
1061fb62fb0SOlivier Houchard #undef CK_PR_FENCE
1071fb62fb0SOlivier Houchard
1081fb62fb0SOlivier Houchard /*
1091fb62fb0SOlivier Houchard * Atomic fetch-and-store operations.
1101fb62fb0SOlivier Houchard */
1111fb62fb0SOlivier Houchard #define CK_PR_FAS(S, M, T, C, I) \
1121fb62fb0SOlivier Houchard CK_CC_INLINE static T \
1131fb62fb0SOlivier Houchard ck_pr_fas_##S(M *target, T v) \
1141fb62fb0SOlivier Houchard { \
1151fb62fb0SOlivier Houchard __asm__ __volatile__(I " %0, %1" \
1161fb62fb0SOlivier Houchard : "+m" (*(C *)target), \
1171fb62fb0SOlivier Houchard "+q" (v) \
1181fb62fb0SOlivier Houchard : \
1191fb62fb0SOlivier Houchard : "memory"); \
1201fb62fb0SOlivier Houchard return v; \
1211fb62fb0SOlivier Houchard }
1221fb62fb0SOlivier Houchard
123*74e9b5f2SOlivier Houchard CK_PR_FAS(ptr, void, void *, uint32_t, "xchgl")
1241fb62fb0SOlivier Houchard
1251fb62fb0SOlivier Houchard #define CK_PR_FAS_S(S, T, I) CK_PR_FAS(S, T, T, T, I)
1261fb62fb0SOlivier Houchard
1271fb62fb0SOlivier Houchard CK_PR_FAS_S(char, char, "xchgb")
1281fb62fb0SOlivier Houchard CK_PR_FAS_S(uint, unsigned int, "xchgl")
1291fb62fb0SOlivier Houchard CK_PR_FAS_S(int, int, "xchgl")
1301fb62fb0SOlivier Houchard CK_PR_FAS_S(32, uint32_t, "xchgl")
1311fb62fb0SOlivier Houchard CK_PR_FAS_S(16, uint16_t, "xchgw")
1321fb62fb0SOlivier Houchard CK_PR_FAS_S(8, uint8_t, "xchgb")
1331fb62fb0SOlivier Houchard
1341fb62fb0SOlivier Houchard #undef CK_PR_FAS_S
1351fb62fb0SOlivier Houchard #undef CK_PR_FAS
1361fb62fb0SOlivier Houchard
1371fb62fb0SOlivier Houchard #define CK_PR_LOAD(S, M, T, C, I) \
1381fb62fb0SOlivier Houchard CK_CC_INLINE static T \
1391fb62fb0SOlivier Houchard ck_pr_md_load_##S(const M *target) \
1401fb62fb0SOlivier Houchard { \
1411fb62fb0SOlivier Houchard T r; \
1421fb62fb0SOlivier Houchard __asm__ __volatile__(I " %1, %0" \
1431fb62fb0SOlivier Houchard : "=q" (r) \
1441fb62fb0SOlivier Houchard : "m" (*(const C *)target) \
1451fb62fb0SOlivier Houchard : "memory"); \
1461fb62fb0SOlivier Houchard return (r); \
1471fb62fb0SOlivier Houchard }
1481fb62fb0SOlivier Houchard
149*74e9b5f2SOlivier Houchard CK_PR_LOAD(ptr, void, void *, uint32_t, "movl")
1501fb62fb0SOlivier Houchard
1511fb62fb0SOlivier Houchard #define CK_PR_LOAD_S(S, T, I) CK_PR_LOAD(S, T, T, T, I)
1521fb62fb0SOlivier Houchard
1531fb62fb0SOlivier Houchard CK_PR_LOAD_S(char, char, "movb")
1541fb62fb0SOlivier Houchard CK_PR_LOAD_S(uint, unsigned int, "movl")
1551fb62fb0SOlivier Houchard CK_PR_LOAD_S(int, int, "movl")
1561fb62fb0SOlivier Houchard CK_PR_LOAD_S(32, uint32_t, "movl")
1571fb62fb0SOlivier Houchard CK_PR_LOAD_S(16, uint16_t, "movw")
1581fb62fb0SOlivier Houchard CK_PR_LOAD_S(8, uint8_t, "movb")
1591fb62fb0SOlivier Houchard
1601fb62fb0SOlivier Houchard #undef CK_PR_LOAD_S
1611fb62fb0SOlivier Houchard #undef CK_PR_LOAD
1621fb62fb0SOlivier Houchard
1631fb62fb0SOlivier Houchard #define CK_PR_STORE(S, M, T, C, I) \
1641fb62fb0SOlivier Houchard CK_CC_INLINE static void \
1651fb62fb0SOlivier Houchard ck_pr_md_store_##S(M *target, T v) \
1661fb62fb0SOlivier Houchard { \
1671fb62fb0SOlivier Houchard __asm__ __volatile__(I " %1, %0" \
1681fb62fb0SOlivier Houchard : "=m" (*(C *)target) \
1691fb62fb0SOlivier Houchard : CK_CC_IMM "q" (v) \
1701fb62fb0SOlivier Houchard : "memory"); \
1711fb62fb0SOlivier Houchard return; \
1721fb62fb0SOlivier Houchard }
1731fb62fb0SOlivier Houchard
174*74e9b5f2SOlivier Houchard CK_PR_STORE(ptr, void, const void *, uint32_t, "movl")
1751fb62fb0SOlivier Houchard
1761fb62fb0SOlivier Houchard #define CK_PR_STORE_S(S, T, I) CK_PR_STORE(S, T, T, T, I)
1771fb62fb0SOlivier Houchard
1781fb62fb0SOlivier Houchard CK_PR_STORE_S(char, char, "movb")
1791fb62fb0SOlivier Houchard CK_PR_STORE_S(uint, unsigned int, "movl")
1801fb62fb0SOlivier Houchard CK_PR_STORE_S(int, int, "movl")
1811fb62fb0SOlivier Houchard CK_PR_STORE_S(32, uint32_t, "movl")
1821fb62fb0SOlivier Houchard CK_PR_STORE_S(16, uint16_t, "movw")
1831fb62fb0SOlivier Houchard CK_PR_STORE_S(8, uint8_t, "movb")
1841fb62fb0SOlivier Houchard
1851fb62fb0SOlivier Houchard #undef CK_PR_STORE_S
1861fb62fb0SOlivier Houchard #undef CK_PR_STORE
1871fb62fb0SOlivier Houchard
1881fb62fb0SOlivier Houchard /*
1891fb62fb0SOlivier Houchard * Atomic fetch-and-add operations.
1901fb62fb0SOlivier Houchard */
1911fb62fb0SOlivier Houchard #define CK_PR_FAA(S, M, T, C, I) \
1921fb62fb0SOlivier Houchard CK_CC_INLINE static T \
1931fb62fb0SOlivier Houchard ck_pr_faa_##S(M *target, T d) \
1941fb62fb0SOlivier Houchard { \
1951fb62fb0SOlivier Houchard __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %1, %0" \
1961fb62fb0SOlivier Houchard : "+m" (*(C *)target), \
1971fb62fb0SOlivier Houchard "+q" (d) \
1981fb62fb0SOlivier Houchard : \
1991fb62fb0SOlivier Houchard : "memory", "cc"); \
2001fb62fb0SOlivier Houchard return (d); \
2011fb62fb0SOlivier Houchard }
2021fb62fb0SOlivier Houchard
203*74e9b5f2SOlivier Houchard CK_PR_FAA(ptr, void, uintptr_t, uint32_t, "xaddl")
2041fb62fb0SOlivier Houchard
2051fb62fb0SOlivier Houchard #define CK_PR_FAA_S(S, T, I) CK_PR_FAA(S, T, T, T, I)
2061fb62fb0SOlivier Houchard
2071fb62fb0SOlivier Houchard CK_PR_FAA_S(char, char, "xaddb")
2081fb62fb0SOlivier Houchard CK_PR_FAA_S(uint, unsigned int, "xaddl")
2091fb62fb0SOlivier Houchard CK_PR_FAA_S(int, int, "xaddl")
2101fb62fb0SOlivier Houchard CK_PR_FAA_S(32, uint32_t, "xaddl")
2111fb62fb0SOlivier Houchard CK_PR_FAA_S(16, uint16_t, "xaddw")
2121fb62fb0SOlivier Houchard CK_PR_FAA_S(8, uint8_t, "xaddb")
2131fb62fb0SOlivier Houchard
2141fb62fb0SOlivier Houchard #undef CK_PR_FAA_S
2151fb62fb0SOlivier Houchard #undef CK_PR_FAA
2161fb62fb0SOlivier Houchard
2171fb62fb0SOlivier Houchard /*
2181fb62fb0SOlivier Houchard * Atomic store-only unary operations.
2191fb62fb0SOlivier Houchard */
2201fb62fb0SOlivier Houchard #define CK_PR_UNARY(K, S, T, C, I) \
2211fb62fb0SOlivier Houchard CK_PR_UNARY_R(K, S, T, C, I) \
2221fb62fb0SOlivier Houchard CK_PR_UNARY_V(K, S, T, C, I)
2231fb62fb0SOlivier Houchard
2241fb62fb0SOlivier Houchard #define CK_PR_UNARY_R(K, S, T, C, I) \
2251fb62fb0SOlivier Houchard CK_CC_INLINE static void \
2261fb62fb0SOlivier Houchard ck_pr_##K##_##S(T *target) \
2271fb62fb0SOlivier Houchard { \
2281fb62fb0SOlivier Houchard __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %0" \
2291fb62fb0SOlivier Houchard : "+m" (*(C *)target) \
2301fb62fb0SOlivier Houchard : \
2311fb62fb0SOlivier Houchard : "memory", "cc"); \
2321fb62fb0SOlivier Houchard return; \
2331fb62fb0SOlivier Houchard }
2341fb62fb0SOlivier Houchard
2351fb62fb0SOlivier Houchard #define CK_PR_UNARY_V(K, S, T, C, I) \
236725de581SAndriy Gapon CK_CC_INLINE static bool \
237725de581SAndriy Gapon ck_pr_##K##_##S##_is_zero(T *target) \
2381fb62fb0SOlivier Houchard { \
239725de581SAndriy Gapon bool ret; \
2401fb62fb0SOlivier Houchard __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %0; setz %1" \
2411fb62fb0SOlivier Houchard : "+m" (*(C *)target), \
242*74e9b5f2SOlivier Houchard "=qm" (ret) \
2431fb62fb0SOlivier Houchard : \
2441fb62fb0SOlivier Houchard : "memory", "cc"); \
245725de581SAndriy Gapon return ret; \
2461fb62fb0SOlivier Houchard }
2471fb62fb0SOlivier Houchard
2481fb62fb0SOlivier Houchard #define CK_PR_UNARY_S(K, S, T, I) CK_PR_UNARY(K, S, T, T, I)
2491fb62fb0SOlivier Houchard
2501fb62fb0SOlivier Houchard #define CK_PR_GENERATE(K) \
251*74e9b5f2SOlivier Houchard CK_PR_UNARY(K, ptr, void, uint32_t, #K "l") \
2521fb62fb0SOlivier Houchard CK_PR_UNARY_S(K, char, char, #K "b") \
2531fb62fb0SOlivier Houchard CK_PR_UNARY_S(K, int, int, #K "l") \
2541fb62fb0SOlivier Houchard CK_PR_UNARY_S(K, uint, unsigned int, #K "l") \
2551fb62fb0SOlivier Houchard CK_PR_UNARY_S(K, 32, uint32_t, #K "l") \
2561fb62fb0SOlivier Houchard CK_PR_UNARY_S(K, 16, uint16_t, #K "w") \
2571fb62fb0SOlivier Houchard CK_PR_UNARY_S(K, 8, uint8_t, #K "b")
2581fb62fb0SOlivier Houchard
2591fb62fb0SOlivier Houchard CK_PR_GENERATE(inc)
2601fb62fb0SOlivier Houchard CK_PR_GENERATE(dec)
2611fb62fb0SOlivier Houchard CK_PR_GENERATE(neg)
2621fb62fb0SOlivier Houchard
2631fb62fb0SOlivier Houchard /* not does not affect condition flags. */
2641fb62fb0SOlivier Houchard #undef CK_PR_UNARY_V
2651fb62fb0SOlivier Houchard #define CK_PR_UNARY_V(a, b, c, d, e)
2661fb62fb0SOlivier Houchard CK_PR_GENERATE(not)
2671fb62fb0SOlivier Houchard
2681fb62fb0SOlivier Houchard #undef CK_PR_GENERATE
2691fb62fb0SOlivier Houchard #undef CK_PR_UNARY_S
2701fb62fb0SOlivier Houchard #undef CK_PR_UNARY_V
2711fb62fb0SOlivier Houchard #undef CK_PR_UNARY_R
2721fb62fb0SOlivier Houchard #undef CK_PR_UNARY
2731fb62fb0SOlivier Houchard
2741fb62fb0SOlivier Houchard /*
2751fb62fb0SOlivier Houchard * Atomic store-only binary operations.
2761fb62fb0SOlivier Houchard */
2771fb62fb0SOlivier Houchard #define CK_PR_BINARY(K, S, M, T, C, I) \
2781fb62fb0SOlivier Houchard CK_CC_INLINE static void \
2791fb62fb0SOlivier Houchard ck_pr_##K##_##S(M *target, T d) \
2801fb62fb0SOlivier Houchard { \
2811fb62fb0SOlivier Houchard __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %1, %0" \
2821fb62fb0SOlivier Houchard : "+m" (*(C *)target) \
2831fb62fb0SOlivier Houchard : CK_CC_IMM "q" (d) \
2841fb62fb0SOlivier Houchard : "memory", "cc"); \
2851fb62fb0SOlivier Houchard return; \
2861fb62fb0SOlivier Houchard }
2871fb62fb0SOlivier Houchard
2881fb62fb0SOlivier Houchard #define CK_PR_BINARY_S(K, S, T, I) CK_PR_BINARY(K, S, T, T, T, I)
2891fb62fb0SOlivier Houchard
2901fb62fb0SOlivier Houchard #define CK_PR_GENERATE(K) \
291*74e9b5f2SOlivier Houchard CK_PR_BINARY(K, ptr, void, uintptr_t, uint32_t, #K "l") \
2921fb62fb0SOlivier Houchard CK_PR_BINARY_S(K, char, char, #K "b") \
2931fb62fb0SOlivier Houchard CK_PR_BINARY_S(K, int, int, #K "l") \
2941fb62fb0SOlivier Houchard CK_PR_BINARY_S(K, uint, unsigned int, #K "l") \
2951fb62fb0SOlivier Houchard CK_PR_BINARY_S(K, 32, uint32_t, #K "l") \
2961fb62fb0SOlivier Houchard CK_PR_BINARY_S(K, 16, uint16_t, #K "w") \
2971fb62fb0SOlivier Houchard CK_PR_BINARY_S(K, 8, uint8_t, #K "b")
2981fb62fb0SOlivier Houchard
2991fb62fb0SOlivier Houchard CK_PR_GENERATE(add)
3001fb62fb0SOlivier Houchard CK_PR_GENERATE(sub)
3011fb62fb0SOlivier Houchard CK_PR_GENERATE(and)
3021fb62fb0SOlivier Houchard CK_PR_GENERATE(or)
3031fb62fb0SOlivier Houchard CK_PR_GENERATE(xor)
3041fb62fb0SOlivier Houchard
3051fb62fb0SOlivier Houchard #undef CK_PR_GENERATE
3061fb62fb0SOlivier Houchard #undef CK_PR_BINARY_S
3071fb62fb0SOlivier Houchard #undef CK_PR_BINARY
3081fb62fb0SOlivier Houchard
3091fb62fb0SOlivier Houchard /*
310*74e9b5f2SOlivier Houchard * Atomic compare and swap, with a variant that sets *v to the old value of target.
3111fb62fb0SOlivier Houchard */
312*74e9b5f2SOlivier Houchard #ifdef __GCC_ASM_FLAG_OUTPUTS__
313*74e9b5f2SOlivier Houchard #define CK_PR_CAS(S, M, T, C, I) \
314*74e9b5f2SOlivier Houchard CK_CC_INLINE static bool \
315*74e9b5f2SOlivier Houchard ck_pr_cas_##S(M *target, T compare, T set) \
316*74e9b5f2SOlivier Houchard { \
317*74e9b5f2SOlivier Houchard bool z; \
318*74e9b5f2SOlivier Houchard __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %3, %0" \
319*74e9b5f2SOlivier Houchard : "+m" (*(C *)target), \
320*74e9b5f2SOlivier Houchard "=@ccz" (z), \
321*74e9b5f2SOlivier Houchard /* RAX is clobbered by cmpxchg. */ \
322*74e9b5f2SOlivier Houchard "+a" (compare) \
323*74e9b5f2SOlivier Houchard : "q" (set) \
324*74e9b5f2SOlivier Houchard : "memory", "cc"); \
325*74e9b5f2SOlivier Houchard return z; \
326*74e9b5f2SOlivier Houchard } \
327*74e9b5f2SOlivier Houchard \
328*74e9b5f2SOlivier Houchard CK_CC_INLINE static bool \
329*74e9b5f2SOlivier Houchard ck_pr_cas_##S##_value(M *target, T compare, T set, M *v) \
330*74e9b5f2SOlivier Houchard { \
331*74e9b5f2SOlivier Houchard bool z; \
332*74e9b5f2SOlivier Houchard __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %3, %0;" \
333*74e9b5f2SOlivier Houchard : "+m" (*(C *)target), \
334*74e9b5f2SOlivier Houchard "=@ccz" (z), \
335*74e9b5f2SOlivier Houchard "+a" (compare) \
336*74e9b5f2SOlivier Houchard : "q" (set) \
337*74e9b5f2SOlivier Houchard : "memory", "cc"); \
338*74e9b5f2SOlivier Houchard *(T *)v = compare; \
339*74e9b5f2SOlivier Houchard return z; \
340*74e9b5f2SOlivier Houchard }
341*74e9b5f2SOlivier Houchard #else
3421fb62fb0SOlivier Houchard #define CK_PR_CAS(S, M, T, C, I) \
3431fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
3441fb62fb0SOlivier Houchard ck_pr_cas_##S(M *target, T compare, T set) \
3451fb62fb0SOlivier Houchard { \
3461fb62fb0SOlivier Houchard bool z; \
3471fb62fb0SOlivier Houchard __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %2, %0; setz %1" \
3481fb62fb0SOlivier Houchard : "+m" (*(C *)target), \
3491fb62fb0SOlivier Houchard "=a" (z) \
3501fb62fb0SOlivier Houchard : "q" (set), \
3511fb62fb0SOlivier Houchard "a" (compare) \
3521fb62fb0SOlivier Houchard : "memory", "cc"); \
3531fb62fb0SOlivier Houchard return z; \
354*74e9b5f2SOlivier Houchard } \
355*74e9b5f2SOlivier Houchard \
356*74e9b5f2SOlivier Houchard CK_CC_INLINE static bool \
357*74e9b5f2SOlivier Houchard ck_pr_cas_##S##_value(M *target, T compare, T set, M *v) \
358*74e9b5f2SOlivier Houchard { \
359*74e9b5f2SOlivier Houchard bool z; \
360*74e9b5f2SOlivier Houchard __asm__ __volatile__(CK_PR_LOCK_PREFIX I " %3, %0;" \
361*74e9b5f2SOlivier Houchard "setz %1;" \
362*74e9b5f2SOlivier Houchard : "+m" (*(C *)target), \
363*74e9b5f2SOlivier Houchard "=q" (z), \
364*74e9b5f2SOlivier Houchard "+a" (compare) \
365*74e9b5f2SOlivier Houchard : "q" (set) \
366*74e9b5f2SOlivier Houchard : "memory", "cc"); \
367*74e9b5f2SOlivier Houchard *(T *)v = compare; \
368*74e9b5f2SOlivier Houchard return z; \
3691fb62fb0SOlivier Houchard }
370*74e9b5f2SOlivier Houchard #endif
3711fb62fb0SOlivier Houchard
372*74e9b5f2SOlivier Houchard CK_PR_CAS(ptr, void, void *, uint32_t, "cmpxchgl")
3731fb62fb0SOlivier Houchard
3741fb62fb0SOlivier Houchard #define CK_PR_CAS_S(S, T, I) CK_PR_CAS(S, T, T, T, I)
3751fb62fb0SOlivier Houchard
3761fb62fb0SOlivier Houchard CK_PR_CAS_S(char, char, "cmpxchgb")
3771fb62fb0SOlivier Houchard CK_PR_CAS_S(int, int, "cmpxchgl")
3781fb62fb0SOlivier Houchard CK_PR_CAS_S(uint, unsigned int, "cmpxchgl")
3791fb62fb0SOlivier Houchard CK_PR_CAS_S(32, uint32_t, "cmpxchgl")
3801fb62fb0SOlivier Houchard CK_PR_CAS_S(16, uint16_t, "cmpxchgw")
3811fb62fb0SOlivier Houchard CK_PR_CAS_S(8, uint8_t, "cmpxchgb")
3821fb62fb0SOlivier Houchard
3831fb62fb0SOlivier Houchard #undef CK_PR_CAS_S
3841fb62fb0SOlivier Houchard #undef CK_PR_CAS
3851fb62fb0SOlivier Houchard
3861fb62fb0SOlivier Houchard /*
3871fb62fb0SOlivier Houchard * Atomic bit test operations.
3881fb62fb0SOlivier Houchard */
3891fb62fb0SOlivier Houchard #define CK_PR_BT(K, S, T, P, C, I) \
3901fb62fb0SOlivier Houchard CK_CC_INLINE static bool \
3911fb62fb0SOlivier Houchard ck_pr_##K##_##S(T *target, unsigned int b) \
3921fb62fb0SOlivier Houchard { \
3931fb62fb0SOlivier Houchard bool c; \
3941fb62fb0SOlivier Houchard __asm__ __volatile__(CK_PR_LOCK_PREFIX I "; setc %1" \
3951fb62fb0SOlivier Houchard : "+m" (*(C *)target), \
3961fb62fb0SOlivier Houchard "=q" (c) \
3971fb62fb0SOlivier Houchard : "q" ((P)b) \
3981fb62fb0SOlivier Houchard : "memory", "cc"); \
3991fb62fb0SOlivier Houchard return (bool)c; \
4001fb62fb0SOlivier Houchard }
4011fb62fb0SOlivier Houchard
4021fb62fb0SOlivier Houchard #define CK_PR_BT_S(K, S, T, I) CK_PR_BT(K, S, T, T, T, I)
4031fb62fb0SOlivier Houchard
4041fb62fb0SOlivier Houchard #define CK_PR_GENERATE(K) \
405*74e9b5f2SOlivier Houchard CK_PR_BT(K, ptr, void, uint32_t, uint32_t, #K "l %2, %0") \
4061fb62fb0SOlivier Houchard CK_PR_BT_S(K, uint, unsigned int, #K "l %2, %0") \
4071fb62fb0SOlivier Houchard CK_PR_BT_S(K, int, int, #K "l %2, %0") \
4081fb62fb0SOlivier Houchard CK_PR_BT_S(K, 32, uint32_t, #K "l %2, %0") \
4091fb62fb0SOlivier Houchard CK_PR_BT_S(K, 16, uint16_t, #K "w %w2, %0")
4101fb62fb0SOlivier Houchard
4111fb62fb0SOlivier Houchard CK_PR_GENERATE(btc)
4121fb62fb0SOlivier Houchard CK_PR_GENERATE(bts)
4131fb62fb0SOlivier Houchard CK_PR_GENERATE(btr)
4141fb62fb0SOlivier Houchard
4151fb62fb0SOlivier Houchard #undef CK_PR_GENERATE
4161fb62fb0SOlivier Houchard #undef CK_PR_BT
4171fb62fb0SOlivier Houchard
4181fb62fb0SOlivier Houchard #endif /* CK_PR_X86_H */
4191fb62fb0SOlivier Houchard
420