/* * SPDX-License-Identifier: GPL-2.0-or-later * Load/store for 128-bit atomic operations, LoongArch version. * * See docs/devel/atomics.rst for discussion about the guarantees each * atomic primitive is meant to provide. */ #ifndef LOONGARCH_ATOMIC128_LDST_H #define LOONGARCH_ATOMIC128_LDST_H #include "host/cpuinfo.h" #include "tcg/debug-assert.h" #define HAVE_ATOMIC128_RO likely(cpuinfo & CPUINFO_LSX) #define HAVE_ATOMIC128_RW HAVE_ATOMIC128_RO /* * As of gcc 13 and clang 16, there is no compiler support for LSX at all. * Use inline assembly throughout. */ static inline Int128 atomic16_read_ro(const Int128 *ptr) { uint64_t l, h; tcg_debug_assert(HAVE_ATOMIC128_RO); asm("vld $vr0, %2, 0\n\t" "vpickve2gr.d %0, $vr0, 0\n\t" "vpickve2gr.d %1, $vr0, 1" : "=r"(l), "=r"(h) : "r"(ptr), "m"(*ptr) : "f0"); return int128_make128(l, h); } static inline Int128 atomic16_read_rw(Int128 *ptr) { return atomic16_read_ro(ptr); } static inline void atomic16_set(Int128 *ptr, Int128 val) { uint64_t l = int128_getlo(val), h = int128_gethi(val); tcg_debug_assert(HAVE_ATOMIC128_RW); asm("vinsgr2vr.d $vr0, %1, 0\n\t" "vinsgr2vr.d $vr0, %2, 1\n\t" "vst $vr0, %3, 0" : "=m"(*ptr) : "r"(l), "r"(h), "r"(ptr) : "f0"); } #endif /* LOONGARCH_ATOMIC128_LDST_H */