diff --git a/include/gcc/arm/ck_f_pr.h b/include/gcc/arm/ck_f_pr.h index 5adbaf6..c06684c 100644 --- a/include/gcc/arm/ck_f_pr.h +++ b/include/gcc/arm/ck_f_pr.h @@ -20,6 +20,8 @@ #define CK_F_PR_CAS_16_VALUE #define CK_F_PR_CAS_32 #define CK_F_PR_CAS_32_VALUE +#define CK_F_PR_CAS_64 +#define CK_F_PR_CAS_64_VALUE #define CK_F_PR_CAS_8 #define CK_F_PR_CAS_8_VALUE #define CK_F_PR_CAS_CHAR @@ -27,6 +29,8 @@ #define CK_F_PR_CAS_INT #define CK_F_PR_CAS_INT_VALUE #define CK_F_PR_CAS_PTR +#define CK_F_PR_CAS_PTR_2 +#define CK_F_PR_CAS_PTR_2_VALUE #define CK_F_PR_CAS_PTR_VALUE #define CK_F_PR_CAS_SHORT #define CK_F_PR_CAS_SHORT_VALUE @@ -87,6 +91,7 @@ #define CK_F_PR_INC_UINT #define CK_F_PR_LOAD_16 #define CK_F_PR_LOAD_32 +#define CK_F_PR_LOAD_64 #define CK_F_PR_LOAD_8 #define CK_F_PR_LOAD_CHAR #define CK_F_PR_LOAD_INT @@ -120,6 +125,7 @@ #define CK_F_PR_STALL #define CK_F_PR_STORE_16 #define CK_F_PR_STORE_32 +#define CK_F_PR_STORE_64 #define CK_F_PR_STORE_8 #define CK_F_PR_STORE_CHAR #define CK_F_PR_STORE_INT diff --git a/include/gcc/arm/ck_pr.h b/include/gcc/arm/ck_pr.h index 3a8f566..8989644 100644 --- a/include/gcc/arm/ck_pr.h +++ b/include/gcc/arm/ck_pr.h @@ -117,6 +117,17 @@ CK_PR_LOAD_S(char, char, "ldrb") #undef CK_PR_LOAD_S #undef CK_PR_LOAD +CK_CC_INLINE static uint64_t +ck_pr_load_64(const uint64_t *target) +{ + register uint64_t ret asm("r0"); + + __asm __volatile("ldrd %0, [%1]" : "+r" (ret) + : "r" (target) + : "memory", "cc"); + return (ret); +} + #define CK_PR_STORE(S, M, T, C, I) \ CK_CC_INLINE static void \ ck_pr_store_##S(M *target, T v) \ @@ -144,6 +155,86 @@ CK_PR_STORE_S(char, char, "strb") #undef CK_PR_STORE_S #undef CK_PR_STORE +CK_CC_INLINE static void +ck_pr_store_64(const uint64_t *target, uint64_t value) +{ + register uint64_t tmp asm("r0") = value; + + __asm __volatile("strd %0, [%1]" + : + : "r" (tmp), "r" (target) + : "memory", "cc"); +} + +CK_CC_INLINE static bool +ck_pr_cas_64_value(uint64_t *target, uint64_t compare, uint64_t set, uint64_t *value) +{ + register uint64_t __compare asm("r0") = compare; + register uint64_t __set asm("r2") = set; + + __asm__ __volatile__("1:" + "ldrexd r4, [%3];" + "cmp r4, r0;" + "ittt eq;" + "cmpeq r5, r1;" + "strexdeq r6, r2, [%3];" + "cmpeq r6, #1;" + "beq 1b;" + "strd r4, [%0];" + : "+r" (value) + : "r" (__compare), "r" (__set) , + "r"(target) + : "memory", "cc", "r4", "r5", "r6"); + return (*value == compare); +} + +CK_CC_INLINE static bool +ck_pr_cas_ptr_2_value(void *target, void *compare, void *set, void *value) +{ + uint32_t *_compare = compare; + uint32_t *_set = set; + uint64_t __compare = ((uint64_t)_compare[0]) | ((uint64_t)_compare[1] << 32); + uint64_t __set = ((uint64_t)_set[0]) | ((uint64_t)_set[1] << 32); + + return (ck_pr_cas_64_value(target, __compare, __set, value)); +} + + +CK_CC_INLINE static bool +ck_pr_cas_64(uint64_t *target, uint64_t compare, uint64_t set) +{ + register uint64_t __compare asm("r0") = compare; + register uint64_t __set asm("r2") = set; + int ret; + + __asm__ __volatile__("1:" + "mov %0, #0;" + "ldrexd r4, [%3];" + "cmp r4, r0;" + "itttt eq;" + "cmpeq r5, r1;" + "strexdeq r6, r2, [%3];" + "moveq %0, #1;" + "cmpeq r6, #1;" + "beq 1b;" + : "=&r" (ret) + : "r" (__compare), "r" (__set) , + "r"(target) + : "memory", "cc", "r4", "r5", "r6"); + + return (ret); +} + +CK_CC_INLINE static bool +ck_pr_cas_ptr_2(void *target, void *compare, void *set) +{ + uint32_t *_compare = compare; + uint32_t *_set = set; + uint64_t __compare = ((uint64_t)_compare[0]) | ((uint64_t)_compare[1] << 32); + uint64_t __set = ((uint64_t)_set[0]) | ((uint64_t)_set[1] << 32); + return (ck_pr_cas_64(target, __compare, __set)); +} + CK_CC_INLINE static bool ck_pr_cas_ptr_value(void *target, void *compare, void *set, void *value) {