ck_pr/arm : Add load, store and CAS for double.

ck_pring
Olivier Houchard 9 years ago
parent 7d35185fdd
commit 37d94f4f4e

@ -23,6 +23,8 @@
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__)
#define CK_F_PR_CAS_64 #define CK_F_PR_CAS_64
#define CK_F_PR_CAS_64_VALUE #define CK_F_PR_CAS_64_VALUE
#define CK_F_PR_CAS_DOUBLE
#define CK_F_PR_CAS_DOUBLE_VALUE
#endif #endif
#define CK_F_PR_CAS_8 #define CK_F_PR_CAS_8
#define CK_F_PR_CAS_8_VALUE #define CK_F_PR_CAS_8_VALUE
@ -97,6 +99,7 @@
#define CK_F_PR_LOAD_32 #define CK_F_PR_LOAD_32
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__)
#define CK_F_PR_LOAD_64 #define CK_F_PR_LOAD_64
#define CK_F_PR_LOAD_DOUBLE
#endif #endif
#define CK_F_PR_LOAD_8 #define CK_F_PR_LOAD_8
#define CK_F_PR_LOAD_CHAR #define CK_F_PR_LOAD_CHAR
@ -133,6 +136,7 @@
#define CK_F_PR_STORE_32 #define CK_F_PR_STORE_32
#if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__) #if defined(__ARM_ARCH_7__) || defined(__ARM_ARCH_7A__)
#define CK_F_PR_STORE_64 #define CK_F_PR_STORE_64
#define CK_F_PR_STORE_DOUBLE
#endif #endif
#define CK_F_PR_STORE_8 #define CK_F_PR_STORE_8
#define CK_F_PR_STORE_CHAR #define CK_F_PR_STORE_CHAR

@ -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)
{ {

Loading…
Cancel
Save