1 /* 2 * SPDX-License-Identifier: GPL-2.0-or-later 3 * Load/store for 128-bit atomic operations, LoongArch version. 4 * 5 * See docs/devel/atomics.rst for discussion about the guarantees each 6 * atomic primitive is meant to provide. 7 */ 8 9 #ifndef LOONGARCH_ATOMIC128_LDST_H 10 #define LOONGARCH_ATOMIC128_LDST_H 11 12 #include "host/cpuinfo.h" 13 #include "tcg/debug-assert.h" 14 15 #define HAVE_ATOMIC128_RO likely(cpuinfo & CPUINFO_LSX) 16 #define HAVE_ATOMIC128_RW HAVE_ATOMIC128_RO 17 18 /* 19 * As of gcc 13 and clang 16, there is no compiler support for LSX at all. 20 * Use inline assembly throughout. 21 */ 22 23 static inline Int128 atomic16_read_ro(const Int128 *ptr) 24 { 25 uint64_t l, h; 26 27 tcg_debug_assert(HAVE_ATOMIC128_RO); 28 asm("vld $vr0, %2, 0\n\t" 29 "vpickve2gr.d %0, $vr0, 0\n\t" 30 "vpickve2gr.d %1, $vr0, 1" 31 : "=r"(l), "=r"(h) : "r"(ptr), "m"(*ptr) : "f0"); 32 33 return int128_make128(l, h); 34 } 35 36 static inline Int128 atomic16_read_rw(Int128 *ptr) 37 { 38 return atomic16_read_ro(ptr); 39 } 40 41 static inline void atomic16_set(Int128 *ptr, Int128 val) 42 { 43 uint64_t l = int128_getlo(val), h = int128_gethi(val); 44 45 tcg_debug_assert(HAVE_ATOMIC128_RW); 46 asm("vinsgr2vr.d $vr0, %1, 0\n\t" 47 "vinsgr2vr.d $vr0, %2, 1\n\t" 48 "vst $vr0, %3, 0" 49 : "=m"(*ptr) : "r"(l), "r"(h), "r"(ptr) : "f0"); 50 } 51 52 #endif /* LOONGARCH_ATOMIC128_LDST_H */ 53