1 /*
2 * SPDX-License-Identifier: BSD-3-Clause
3 * SPDX-FileCopyrightText: Copyright TF-RMM Contributors.
4 */
5
6 #ifndef ATOMICS_H
7 #define ATOMICS_H
8
9 #include <stdbool.h>
10 #include <stdint.h>
11
12 /*
13 * Atomically adds @val to the 64-bit value stored at memory location @loc.
14 */
atomic_add_64(uint64_t * loc,long val)15 static inline void atomic_add_64(uint64_t *loc, long val)
16 {
17 asm volatile(
18 " stadd %[val], %[loc]\n"
19 : [loc] "+Q" (*loc)
20 : [val] "r" (val)
21 : "memory");
22 }
23
24 /*
25 * Atomically adds @val to the 64-bit value stored at memory location @loc.
26 * Stores to memory with release semantics.
27 * Returns the old value.
28 */
atomic_load_add_release_64(uint64_t * loc,long val)29 static inline unsigned long atomic_load_add_release_64(uint64_t *loc, long val)
30 {
31 unsigned long old_val;
32
33 asm volatile(
34 " ldaddl %[val], %[old_val], %[loc]\n"
35 : [loc] "+Q" (*loc),
36 [old_val] "=r" (old_val)
37 : [val] "r" (val)
38 : "memory");
39
40 return old_val;
41 }
42
43 /*
44 * Atomically set bit @bit in value pointed to by @loc with release semantics.
45 */
atomic_bit_set_release_64(uint64_t * loc,int bit)46 static inline void atomic_bit_set_release_64(uint64_t *loc, int bit)
47 {
48 uint64_t mask = (1UL << bit);
49
50 asm volatile(
51 " stsetl %[mask], %[loc]\n"
52 : [loc] "+Q" (*loc)
53 : [mask] "r" (mask)
54 : "memory"
55 );
56 }
57
58 /*
59 * Atomically clear bit @bit in value pointed to by @loc with release semantics.
60 */
atomic_bit_clear_release_64(uint64_t * loc,int bit)61 static inline void atomic_bit_clear_release_64(uint64_t *loc, int bit)
62 {
63 uint64_t mask = (1UL << bit);
64
65 asm volatile(
66 " stclrl %[mask], %[loc]\n"
67 : [loc] "+Q" (*loc)
68 : [mask] "r" (mask)
69 : "memory"
70 );
71 }
72
73 /*
74 * Test bit @bit in value pointed to by @loc with acquire semantics.
75 */
atomic_test_bit_acquire_64(uint64_t * loc,int bit)76 static inline bool atomic_test_bit_acquire_64(uint64_t *loc, int bit)
77 {
78 uint64_t val;
79 uint64_t mask = (1UL << bit);
80
81 asm volatile(
82 " ldar %[val], %[loc]\n"
83 : [val] "=r" (val)
84 : [loc] "Q" (*loc)
85 : "memory"
86 );
87
88 return ((val & mask) != 0UL);
89 }
90
91 /*
92 * Atomically set bit @bit in value pointed to by @loc
93 * with acquire and release semantics.
94 * Return True if the previous state of @bit was 1, False otherwise.
95 */
atomic_bit_set_acquire_release_64(uint64_t * loc,int bit)96 static inline bool atomic_bit_set_acquire_release_64(uint64_t *loc, int bit)
97 {
98 uint64_t val;
99 uint64_t mask = (1UL << bit);
100
101 asm volatile(
102 " ldsetal %[mask], %[val], %[loc]\n"
103 : [loc] "+Q" (*loc),
104 [val] "=r" (val)
105 : [mask] "r" (mask)
106 : "memory"
107 );
108
109 return ((val & mask) != 0UL);
110 }
111
112 #endif /* ATOMICS_H */
113