1/* 2 * SPDX-License-Identifier: GPL-2.0-or-later 3 * Atomic store insert into 128-bit, AArch64 version. 4 * 5 * Copyright (C) 2023 Linaro, Ltd. 6 */ 7 8#ifndef AARCH64_STORE_INSERT_AL16_H 9#define AARCH64_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 /* 23 * GCC only implements __sync* primitives for int128 on aarch64. 24 * We can do better without the barriers, and integrating the 25 * arithmetic into the load-exclusive/store-conditional pair. 26 */ 27 uint64_t tl, th, vl, vh, ml, mh; 28 uint32_t fail; 29 30 qemu_build_assert(!HOST_BIG_ENDIAN); 31 vl = int128_getlo(val); 32 vh = int128_gethi(val); 33 ml = int128_getlo(msk); 34 mh = int128_gethi(msk); 35 36 asm("0: ldxp %[l], %[h], %[mem]\n\t" 37 "bic %[l], %[l], %[ml]\n\t" 38 "bic %[h], %[h], %[mh]\n\t" 39 "orr %[l], %[l], %[vl]\n\t" 40 "orr %[h], %[h], %[vh]\n\t" 41 "stxp %w[f], %[l], %[h], %[mem]\n\t" 42 "cbnz %w[f], 0b\n" 43 : [mem] "+Q"(*ps), [f] "=&r"(fail), [l] "=&r"(tl), [h] "=&r"(th) 44 : [vl] "r"(vl), [vh] "r"(vh), [ml] "r"(ml), [mh] "r"(mh)); 45} 46 47#endif /* AARCH64_STORE_INSERT_AL16_H */ 48