blob: 4a1662183dd39d7f2836758a89e9b4381d5ed7ca [file] [log] [blame]
/*
* SPDX-License-Identifier: GPL-2.0-or-later
* Atomic store insert into 128-bit, generic version.
*
* Copyright (C) 2023 Linaro, Ltd.
*/
#ifndef HOST_STORE_INSERT_AL16_H
#define HOST_STORE_INSERT_AL16_H
/**
* store_atom_insert_al16:
* @p: host address
* @val: shifted value to store
* @msk: mask for value to store
*
* Atomically store @val to @p masked by @msk.
*/
static inline void ATTRIBUTE_ATOMIC128_OPT
store_atom_insert_al16(Int128 *ps, Int128 val, Int128 msk)
{
#if defined(CONFIG_ATOMIC128)
__uint128_t *pu;
Int128Alias old, new;
/* With CONFIG_ATOMIC128, we can avoid the memory barriers. */
pu = __builtin_assume_aligned(ps, 16);
old.u = *pu;
msk = int128_not(msk);
do {
new.s = int128_and(old.s, msk);
new.s = int128_or(new.s, val);
} while (!__atomic_compare_exchange_n(pu, &old.u, new.u, true,
__ATOMIC_RELAXED, __ATOMIC_RELAXED));
#else
Int128 old, new, cmp;
ps = __builtin_assume_aligned(ps, 16);
old = *ps;
msk = int128_not(msk);
do {
cmp = old;
new = int128_and(old, msk);
new = int128_or(new, val);
old = atomic16_cmpxchg(ps, cmp, new);
} while (int128_ne(cmp, old));
#endif
}
#endif /* HOST_STORE_INSERT_AL16_H */