| /* |
| * 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 */ |