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