1/*
2 * SPDX-License-Identifier: GPL-2.0-or-later
3 * Atomic store insert into 128-bit, generic version.
4 *
5 * Copyright (C) 2023 Linaro, Ltd.
6 */
7
8#ifndef HOST_STORE_INSERT_AL16_H
9#define HOST_STORE_INSERT_AL16_H
10
11/**
12 * store_atom_insert_al16:
13 * @p: host address
14 * @val: shifted value to store
15 * @msk: mask for value to store
16 *
17 * Atomically store @val to @p masked by @msk.
18 */
19static inline void ATTRIBUTE_ATOMIC128_OPT
20store_atom_insert_al16(Int128 *ps, Int128 val, Int128 msk)
21{
22#if defined(CONFIG_ATOMIC128)
23    __uint128_t *pu;
24    Int128Alias old, new;
25
26    /* With CONFIG_ATOMIC128, we can avoid the memory barriers. */
27    pu = __builtin_assume_aligned(ps, 16);
28    old.u = *pu;
29    msk = int128_not(msk);
30    do {
31        new.s = int128_and(old.s, msk);
32        new.s = int128_or(new.s, val);
33    } while (!__atomic_compare_exchange_n(pu, &old.u, new.u, true,
34                                          __ATOMIC_RELAXED, __ATOMIC_RELAXED));
35#else
36    Int128 old, new, cmp;
37
38    ps = __builtin_assume_aligned(ps, 16);
39    old = *ps;
40    msk = int128_not(msk);
41    do {
42        cmp = old;
43        new = int128_and(old, msk);
44        new = int128_or(new, val);
45        old = atomic16_cmpxchg(ps, cmp, new);
46    } while (int128_ne(cmp, old));
47#endif
48}
49
50#endif /* HOST_STORE_INSERT_AL16_H */
51