1/*-------------------------------------------------------------------------
4 * Atomic operations considerations specific to PowerPC
6 * Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
7 * Portions Copyright (c) 1994, Regents of the University of California
11 * src/include/port/atomics/arch-ppc.h
13 *-------------------------------------------------------------------------
19 * lwsync orders loads with respect to each other, and similarly with stores.
20 * But a load can be performed before a subsequent store, so sync must be used
21 * for a full memory barrier.
23#define pg_memory_barrier_impl() __asm__ __volatile__ ("sync" : : : "memory")
24#define pg_read_barrier_impl() __asm__ __volatile__ ("lwsync" : : : "memory")
25#define pg_write_barrier_impl() __asm__ __volatile__ ("lwsync" : : : "memory")
28 #define PG_HAVE_ATOMIC_U32_SUPPORT
34/* 64bit atomics are only supported in 64bit mode */
36#define PG_HAVE_ATOMIC_U64_SUPPORT
45 * This mimics gcc __atomic_compare_exchange_n(..., __ATOMIC_SEQ_CST), but
46 * code generation differs at the end. __atomic_compare_exchange_n():
49 * 108: rlwinm r3,r3,3,31,31
50 * 10c: bne 120 <.eb+0x10>
51 * 110: clrldi r3,r3,63
55 * 120: clrldi r3,r3,63
63 * f8: rldicl. r3,r9,35,63
69 * This implementation may or may not have materially different performance.
70 * It's not exploiting the fact that cr0 still holds the relevant comparison
71 * bits, set during the __asm__. One could fix that by moving more code into
72 * the __asm__. (That would remove the freedom to eliminate dead stores when
73 * the caller ignores "expected", but few callers do.)
75 * Recognizing constant "newval" would be superfluous, because there's no
76 * immediate-operand version of stwcx.
78 #define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U32
87#ifdef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
88 if (__builtin_constant_p(*expected) &&
95 " bne $+12 \n" /* branch to lwsync */
97 " bne $-16 \n" /* branch to lwarx */
100:
"=&r"(found),
"=r"(condition_register),
"+m"(ptr->
value)
105 __asm__ __volatile__(
107 " lwarx %0,0,%5,1 \n"
109 " bne $+12 \n" /* branch to lwsync */
111 " bne $-16 \n" /* branch to lwarx */
114:
"=&r"(found),
"=r"(condition_register),
"+m"(ptr->
value)
118 ret = (condition_register >> 29) & 1;
/* test eq bit of cr0 */
125 * This mirrors gcc __sync_fetch_and_add().
127 * Like tas(), use constraint "=&b" to avoid allocating r0.
129 #define PG_HAVE_ATOMIC_FETCH_ADD_U32
136#ifdef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
137 if (__builtin_constant_p(add_) &&
139 __asm__ __volatile__(
141 " lwarx %1,0,%4,1 \n"
144 " bne $-12 \n" /* branch to lwarx */
146:
"=&r"(_t),
"=&b"(res),
"+m"(ptr->
value)
147:
"i"(add_),
"r"(&ptr->
value)
151 __asm__ __volatile__(
153 " lwarx %1,0,%4,1 \n"
156 " bne $-12 \n" /* branch to lwarx */
158:
"=&r"(_t),
"=&r"(res),
"+m"(ptr->
value)
159:
"r"(add_),
"r"(&ptr->
value)
165#ifdef PG_HAVE_ATOMIC_U64_SUPPORT
167#define PG_HAVE_ATOMIC_COMPARE_EXCHANGE_U64
173 uint32 condition_register;
178 /* Like u32, but s/lwarx/ldarx/; s/stwcx/stdcx/; s/cmpw/cmpd/ */
179#ifdef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
180 if (__builtin_constant_p(*expected) &&
183 __asm__ __volatile__(
185 " ldarx %0,0,%5,1 \n"
187 " bne $+12 \n" /* branch to lwsync */
189 " bne $-16 \n" /* branch to ldarx */
192:
"=&r"(found),
"=r"(condition_register),
"+m"(ptr->
value)
197 __asm__ __volatile__(
199 " ldarx %0,0,%5,1 \n"
201 " bne $+12 \n" /* branch to lwsync */
203 " bne $-16 \n" /* branch to ldarx */
206:
"=&r"(found),
"=r"(condition_register),
"+m"(ptr->
value)
210 ret = (condition_register >> 29) & 1;
/* test eq bit of cr0 */
216#define PG_HAVE_ATOMIC_FETCH_ADD_U64
223 /* Like u32, but s/lwarx/ldarx/; s/stwcx/stdcx/ */
224#ifdef HAVE_I_CONSTRAINT__BUILTIN_CONSTANT_P
225 if (__builtin_constant_p(add_) &&
227 __asm__ __volatile__(
229 " ldarx %1,0,%4,1 \n"
232 " bne $-12 \n" /* branch to ldarx */
234:
"=&r"(_t),
"=&b"(res),
"+m"(ptr->
value)
235:
"i"(add_),
"r"(&ptr->
value)
239 __asm__ __volatile__(
241 " ldarx %1,0,%4,1 \n"
244 " bne $-12 \n" /* branch to ldarx */
246:
"=&r"(_t),
"=&r"(res),
"+m"(ptr->
value)
247:
"r"(add_),
"r"(&ptr->
value)
253#endif /* PG_HAVE_ATOMIC_U64_SUPPORT */
255/* per architecture manual doubleword accesses have single copy atomicity */
256 #define PG_HAVE_8BYTE_SINGLE_COPY_ATOMICITY
static bool pg_atomic_compare_exchange_u32_impl(volatile pg_atomic_uint32 *ptr, uint32 *expected, uint32 newval)
static uint32 pg_atomic_fetch_add_u32_impl(volatile pg_atomic_uint32 *ptr, int32 add_)
struct pg_atomic_uint32 pg_atomic_uint32
uint64 pg_atomic_fetch_add_u64_impl(volatile pg_atomic_uint64 *ptr, int64 add_)
bool pg_atomic_compare_exchange_u64_impl(volatile pg_atomic_uint64 *ptr, uint64 *expected, uint64 newval)
#define AssertPointerAlignment(ptr, bndr)
struct pg_atomic_uint64 pg_atomic_uint64
struct pg_attribute_aligned(8) pg_atomic_uint64