blob: 9a4a8f8b9e3193be30aa0ec9e3189279ac665752 [file] [log] [blame]
/*
* 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 */