|
|
@ -133,18 +133,22 @@ CK_PR_LOAD_S(char, char, "ldrb")
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__)
|
|
|
|
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__)
|
|
|
|
|
|
|
|
|
|
|
|
CK_CC_INLINE static uint64_t
|
|
|
|
#define CK_PR_DOUBLE_LOAD(T, N) \
|
|
|
|
ck_pr_md_load_64(const uint64_t *target)
|
|
|
|
CK_CC_INLINE static T \
|
|
|
|
{
|
|
|
|
ck_pr_md_load_##N(const T *target) \
|
|
|
|
register uint64_t ret;
|
|
|
|
{ \
|
|
|
|
|
|
|
|
register T ret; \
|
|
|
|
__asm __volatile("ldrexd %0, [%1]"
|
|
|
|
\
|
|
|
|
: "=&r" (ret)
|
|
|
|
__asm __volatile("ldrexd %0, [%1]" \
|
|
|
|
: "r" (target)
|
|
|
|
: "=&r" (ret) \
|
|
|
|
: "memory", "cc");
|
|
|
|
: "r" (target) \
|
|
|
|
return (ret);
|
|
|
|
: "memory", "cc"); \
|
|
|
|
|
|
|
|
return (ret); \
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CK_PR_DOUBLE_LOAD(uint64_t, 64)
|
|
|
|
|
|
|
|
CK_PR_DOUBLE_LOAD(double, double)
|
|
|
|
|
|
|
|
#undef CK_PR_DOUBLE_LOAD
|
|
|
|
#endif
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
#define CK_PR_STORE(S, M, T, C, I) \
|
|
|
|
#define CK_PR_STORE(S, M, T, C, I) \
|
|
|
@ -176,44 +180,56 @@ CK_PR_STORE_S(char, char, "strb")
|
|
|
|
|
|
|
|
|
|
|
|
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__)
|
|
|
|
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__)
|
|
|
|
|
|
|
|
|
|
|
|
CK_CC_INLINE static void
|
|
|
|
#define CK_PR_DOUBLE_STORE(T, N) \
|
|
|
|
ck_pr_md_store_64(const uint64_t *target, uint64_t value)
|
|
|
|
CK_CC_INLINE static void \
|
|
|
|
{
|
|
|
|
ck_pr_md_store_##N(const T *target, T value) \
|
|
|
|
uint64_t tmp;
|
|
|
|
{ \
|
|
|
|
uint32_t flag;
|
|
|
|
T tmp; \
|
|
|
|
__asm __volatile("1: \n"
|
|
|
|
uint32_t flag; \
|
|
|
|
"ldrexd %0, [%2]\n"
|
|
|
|
__asm __volatile("1: \n" \
|
|
|
|
"strexd %1, %3, [%2]\n"
|
|
|
|
"ldrexd %0, [%2]\n" \
|
|
|
|
"teq %1, #0\n"
|
|
|
|
"strexd %1, %3, [%2]\n" \
|
|
|
|
"it ne \n"
|
|
|
|
"teq %1, #0\n" \
|
|
|
|
"bne 1b\n"
|
|
|
|
"it ne \n" \
|
|
|
|
: "=&r" (tmp), "=&r" (flag)
|
|
|
|
"bne 1b\n" \
|
|
|
|
: "r" (target), "r" (value)
|
|
|
|
: "=&r" (tmp), "=&r" (flag) \
|
|
|
|
: "memory", "cc");
|
|
|
|
: "r" (target), "r" (value) \
|
|
|
|
|
|
|
|
: "memory", "cc"); \
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
CK_CC_INLINE static bool
|
|
|
|
CK_PR_DOUBLE_STORE(uint64_t, 64)
|
|
|
|
ck_pr_cas_64_value(uint64_t *target, uint64_t compare, uint64_t set, uint64_t *value)
|
|
|
|
CK_PR_DOUBLE_STORE(double, double)
|
|
|
|
{
|
|
|
|
|
|
|
|
uint64_t previous;
|
|
|
|
|
|
|
|
int tmp;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
__asm__ __volatile__("1:"
|
|
|
|
#undef CK_PR_DOUBLE_STORE
|
|
|
|
"ldrexd %0, [%4];"
|
|
|
|
|
|
|
|
"cmp %Q0, %Q2;"
|
|
|
|
#define CK_PR_DOUBLE_CAS_VALUE(T, N) \
|
|
|
|
"ittt eq;"
|
|
|
|
CK_CC_INLINE static bool \
|
|
|
|
"cmpeq %R0, %R2;"
|
|
|
|
ck_pr_cas_##N##_value(T *target, T compare, T set, T *value) \
|
|
|
|
"strexdeq %1, %3, [%4];"
|
|
|
|
{ \
|
|
|
|
"cmpeq %1, #1;"
|
|
|
|
T previous; \
|
|
|
|
"beq 1b;"
|
|
|
|
int tmp; \
|
|
|
|
:"=&r" (previous), "=&r" (tmp)
|
|
|
|
\
|
|
|
|
: "r" (compare), "r" (set) ,
|
|
|
|
__asm__ __volatile__("1:" \
|
|
|
|
"r"(target)
|
|
|
|
"ldrexd %0, [%4];" \
|
|
|
|
: "memory", "cc", "r4", "r5", "r6");
|
|
|
|
"cmp %Q0, %Q2;" \
|
|
|
|
*value = previous;
|
|
|
|
"ittt eq;" \
|
|
|
|
return (*value == compare);
|
|
|
|
"cmpeq %R0, %R2;" \
|
|
|
|
|
|
|
|
"strexdeq %1, %3, [%4];" \
|
|
|
|
|
|
|
|
"cmpeq %1, #1;" \
|
|
|
|
|
|
|
|
"beq 1b;" \
|
|
|
|
|
|
|
|
:"=&r" (previous), "=&r" (tmp) \
|
|
|
|
|
|
|
|
: "r" (compare), "r" (set) , \
|
|
|
|
|
|
|
|
"r"(target) \
|
|
|
|
|
|
|
|
: "memory", "cc"); \
|
|
|
|
|
|
|
|
*value = previous; \
|
|
|
|
|
|
|
|
return (*value == compare); \
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CK_PR_DOUBLE_CAS_VALUE(uint64_t, 64)
|
|
|
|
|
|
|
|
CK_PR_DOUBLE_CAS_VALUE(double, double)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#undef CK_PR_DOUBLE_CAS_VALUE
|
|
|
|
|
|
|
|
|
|
|
|
CK_CC_INLINE static bool
|
|
|
|
CK_CC_INLINE static bool
|
|
|
|
ck_pr_cas_ptr_2_value(void *target, void *compare, void *set, void *value)
|
|
|
|
ck_pr_cas_ptr_2_value(void *target, void *compare, void *set, void *value)
|
|
|
|
{
|
|
|
|
{
|
|
|
@ -228,31 +244,33 @@ ck_pr_cas_ptr_2_value(void *target, void *compare, void *set, void *value)
|
|
|
|
CK_CPP_CAST(uint64_t *, value)));
|
|
|
|
CK_CPP_CAST(uint64_t *, value)));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#define CK_PR_DOUBLE_CAS(T, N) \
|
|
|
|
CK_CC_INLINE static bool
|
|
|
|
CK_CC_INLINE static bool \
|
|
|
|
ck_pr_cas_64(uint64_t *target, uint64_t compare, uint64_t set)
|
|
|
|
ck_pr_cas_##N(T *target, T compare, T set) \
|
|
|
|
{
|
|
|
|
{ \
|
|
|
|
int ret;
|
|
|
|
int ret; \
|
|
|
|
uint64_t tmp;
|
|
|
|
T tmp; \
|
|
|
|
|
|
|
|
\
|
|
|
|
__asm__ __volatile__("1:"
|
|
|
|
__asm__ __volatile__("1:" \
|
|
|
|
"mov %0, #0;"
|
|
|
|
"mov %0, #0;" \
|
|
|
|
"ldrexd %1, [%4];"
|
|
|
|
"ldrexd %1, [%4];" \
|
|
|
|
"cmp %Q1, %Q2;"
|
|
|
|
"cmp %Q1, %Q2;" \
|
|
|
|
"itttt eq;"
|
|
|
|
"itttt eq;" \
|
|
|
|
"cmpeq %R1, %R2;"
|
|
|
|
"cmpeq %R1, %R2;" \
|
|
|
|
"strexdeq %1, %3, [%4];"
|
|
|
|
"strexdeq %1, %3, [%4];" \
|
|
|
|
"moveq %0, #1;"
|
|
|
|
"moveq %0, #1;" \
|
|
|
|
"cmpeq %1, #1;"
|
|
|
|
"cmpeq %1, #1;" \
|
|
|
|
"beq 1b;"
|
|
|
|
"beq 1b;" \
|
|
|
|
: "=&r" (ret), "=&r" (tmp)
|
|
|
|
: "=&r" (ret), "=&r" (tmp) \
|
|
|
|
: "r" (compare), "r" (set) ,
|
|
|
|
: "r" (compare), "r" (set) , \
|
|
|
|
"r"(target)
|
|
|
|
"r"(target) \
|
|
|
|
: "memory", "cc");
|
|
|
|
: "memory", "cc"); \
|
|
|
|
|
|
|
|
\
|
|
|
|
return (ret);
|
|
|
|
return (ret); \
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
CK_PR_DOUBLE_CAS(uint64_t, 64)
|
|
|
|
|
|
|
|
CK_PR_DOUBLE_CAS(double, double)
|
|
|
|
CK_CC_INLINE static bool
|
|
|
|
CK_CC_INLINE static bool
|
|
|
|
ck_pr_cas_ptr_2(void *target, void *compare, void *set)
|
|
|
|
ck_pr_cas_ptr_2(void *target, void *compare, void *set)
|
|
|
|
{
|
|
|
|
{
|
|
|
|