diff --git a/Add-AArch64-clang-longjmp-support.patch b/Add-AArch64-clang-longjmp-support.patch
index 3627aa6104c5aca92b56660849bbd13c72116818..6c9c4696a16ac4cf0485ae695998b76944f4d834 100644
--- a/Add-AArch64-clang-longjmp-support.patch
+++ b/Add-AArch64-clang-longjmp-support.patch
@@ -1,10 +1,10 @@
diff --git a/include/pub_tool_libcsetjmp.h b/include/pub_tool_libcsetjmp.h
-index 681450cef..ccdf295df 100644
+index e9638c3..1a52715 100644
--- a/include/pub_tool_libcsetjmp.h
+++ b/include/pub_tool_libcsetjmp.h
-@@ -134,6 +134,111 @@
+@@ -150,6 +150,111 @@ UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
__attribute__((noreturn))
- void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
+ void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
+#elif defined __aarch64__ && defined __clang__
+
@@ -114,3 +114,178 @@ index 681450cef..ccdf295df 100644
#else
/* The default implementation. */
+diff --git a/include/pub_tool_libcsetjmp.h.orig b/include/pub_tool_libcsetjmp.h.orig
+new file mode 100644
+index 0000000..e9638c3
+--- /dev/null
++++ b/include/pub_tool_libcsetjmp.h.orig
+@@ -0,0 +1,166 @@
++
++/*--------------------------------------------------------------------*/
++/*--- A minimal setjmp/longjmp facility. pub_tool_libcsetjmp.h ---*/
++/*--------------------------------------------------------------------*/
++
++/*
++ This file is part of Valgrind, a dynamic binary instrumentation
++ framework.
++
++ Copyright (C) 2010-2017 Mozilla Foundation
++
++ This program is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License as
++ published by the Free Software Foundation; either version 2 of the
++ License, or (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, see .
++
++ The GNU General Public License is contained in the file COPYING.
++*/
++
++/* Contributed by Julian Seward */
++
++#ifndef __PUB_TOOL_LIBCSETJMP_H
++#define __PUB_TOOL_LIBCSETJMP_H
++
++#include "pub_tool_basics.h" // UWord
++
++//--------------------------------------------------------------------
++// PURPOSE: Provides a minimal setjmp/longjmp facility, that saves/
++// restores integer registers, but not necessarily anything more.
++//--------------------------------------------------------------------
++
++
++/* This provides an extremely minimal setjmp/longjmp facility, in
++ which only the host's integer registers are saved/restored. Or at
++ least, that is the minimal guaranteed functionality.
++
++ Until Apr 2011 we used __builtin_setjmp and __builtin_longjmp, but
++ it appears that that is not always correctly implemented. See
++ https://bugs.kde.org/show_bug.cgi?id=259977. So this module wraps
++ those functions up and facilitates replacing them with our own
++ implementations where necessary.
++*/
++
++/* --- !!! --- EXTERNAL HEADERS start --- !!! --- */
++#include
++/* --- !!! --- EXTERNAL HEADERS end --- !!! --- */
++
++
++/* Don't use jmp_buf, __builtin_setjmp or __builtin_longjmp directly.
++ They don't always work reliably. Instead use these macros, which
++ provide the opportunity to supply alternative implementations as
++ necessary.
++
++ Note that the abstraction is done with macros (ick) rather than
++ functions and typedefs, since wrapping __builtin_setjmp up in a
++ second function (eg, VG_(minimal_setjmp)) doesn't seem to work for
++ whatever reason -- returns via a VG_(minimal_longjmp) go wrong.
++
++ VG_MINIMAL_SETJMP stores the current integer register state in the
++ supplied argument, and returns zero. VG_MINIMAL_LONGJMP resumes
++ with the previously saved state, and returns a nonzero, word-sized
++ value. The caller must test all bits of the value in order to make
++ a zero/non-zero determination.
++*/
++
++#if defined(VGP_ppc32_linux)
++
++#define VG_MINIMAL_JMP_BUF(_name) UInt _name [32+1+1]
++__attribute__((returns_twice))
++UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
++__attribute__((noreturn))
++void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
++
++
++#elif defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux)
++
++#define VG_MINIMAL_JMP_BUF(_name) ULong _name [32+1+1]
++__attribute__((returns_twice))
++UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
++__attribute__((noreturn))
++void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
++
++
++#elif defined(VGP_amd64_linux) || defined(VGP_amd64_darwin) || \
++ defined(VGP_amd64_solaris) || defined(VGP_amd64_freebsd)
++
++#define VG_MINIMAL_JMP_BUF(_name) ULong _name [16+1]
++__attribute__((returns_twice))
++UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
++__attribute__((noreturn))
++void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
++
++
++#elif defined(VGP_x86_linux) || defined(VGP_x86_darwin) || \
++ defined(VGP_x86_solaris) || defined(VGP_x86_freebsd)
++
++#define VG_MINIMAL_JMP_BUF(_name) UInt _name [8+1]
++__attribute__((returns_twice))
++__attribute__((regparm(1))) // this is critical; don't delete
++UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
++__attribute__((noreturn))
++__attribute__((regparm(1))) // ditto
++void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
++
++#elif defined(VGP_mips32_linux) || defined(VGP_nanomips_linux)
++
++#define VG_MINIMAL_JMP_BUF(_name) ULong _name [104 / sizeof(ULong)]
++__attribute__((returns_twice))
++UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
++__attribute__((noreturn))
++void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
++
++#elif defined(VGP_mips64_linux)
++
++#define VG_MINIMAL_JMP_BUF(_name) ULong _name [168 / sizeof(ULong)]
++__attribute__((returns_twice))
++UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
++__attribute__((noreturn))
++void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
++
++#elif defined(VGP_s390x_linux)
++
++#define VG_MINIMAL_JMP_BUF(_name) ULong _name [10 + 8]
++__attribute__((returns_twice))
++UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
++__attribute__((noreturn))
++void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
++
++#elif defined(__clang__) && defined(VGP_arm64_linux)
++
++#define VG_MINIMAL_JMP_BUF(_name) UWord _name [13]
++__attribute__((returns_twice))
++UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
++__attribute__((noreturn))
++void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
++
++#elif defined(VGP_arm64_freebsd)
++
++#define VG_MINIMAL_JMP_BUF(_name) UWord _name [22]
++__attribute__((returns_twice))
++UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
++__attribute__((noreturn))
++void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
++
++#else
++
++/* The default implementation. */
++#define VG_MINIMAL_JMP_BUF(_name) jmp_buf _name
++#define VG_MINIMAL_SETJMP(_env) ((UWord)(__builtin_setjmp((_env))))
++#define VG_MINIMAL_LONGJMP(_env) __builtin_longjmp((_env),1)
++
++#endif
++
++#endif // __PUB_TOOL_LIBCSETJMP_H
++
++/*--------------------------------------------------------------------*/
++/*--- end pub_tool_libcsetjmp.h ---*/
++/*--------------------------------------------------------------------*/
+--
+2.48.1
+
diff --git a/Add-LOONGARCH64-Linux-support.patch b/Add-LOONGARCH64-Linux-support.patch
index 506aa585c088bf6eeaf119ee24f2cd61645f3f9f..bad1c17e76ae6db6ec2576e3ada7ebf1b216799e 100644
--- a/Add-LOONGARCH64-Linux-support.patch
+++ b/Add-LOONGARCH64-Linux-support.patch
@@ -1,54 +1,43 @@
-From 957c59b751202c6235da4c00389dce67fd5730e8 Mon Sep 17 00:00:00 2001
+From 9d7a65c6b332bc49686476468a47f7a45eeade18 Mon Sep 17 00:00:00 2001
From: Binbin Zhou
-Date: Thu, 19 May 2022 10:18:14 +0800
+Date: Tue, 25 Mar 2025 19:56:27 +0800
Subject: [PATCH] Add LoongArch64 Linux support
+Signed-off-by: Binbin Zhou
---
Makefile.all.am | 7 +
- Makefile.in | 9 +-
Makefile.tool.am | 12 +
Makefile.vex.am | 14 +-
- Makefile.vex.in | 199 +-
README | 1 +
- README.loongarch64 | 51 +
+ README.loongarch64 | 63 +
VEX/auxprogs/genoffsets.c | 36 +
VEX/priv/guest_loongarch64_defs.h | 131 +
- VEX/priv/guest_loongarch64_helpers.c | 905 +
- VEX/priv/guest_loongarch64_toIR.c | 12086 ++++
- VEX/priv/host_loongarch64_defs.c | 3929 ++
- VEX/priv/host_loongarch64_defs.h | 919 +
- VEX/priv/host_loongarch64_isel.c | 3748 ++
- VEX/priv/ir_defs.c | 55 +-
+ VEX/priv/guest_loongarch64_helpers.c | 908 +
+ VEX/priv/guest_loongarch64_toIR.c | 18325 ++++++
+ VEX/priv/host_loongarch64_defs.c | 3953 ++
+ VEX/priv/host_loongarch64_defs.h | 927 +
+ VEX/priv/host_loongarch64_isel.c | 4120 ++
+ VEX/priv/ir_defs.c | 269 +-
VEX/priv/main_main.c | 109 +
VEX/pub/libvex.h | 22 +
VEX/pub/libvex_basictypes.h | 4 +
- VEX/pub/libvex_guest_loongarch64.h | 172 +
- VEX/pub/libvex_guest_offsets.h | 33 +
- VEX/pub/libvex_ir.h | 36 +-
+ VEX/pub/libvex_guest_loongarch64.h | 173 +
+ VEX/pub/libvex_ir.h | 111 +-
VEX/pub/libvex_trc_values.h | 1 +
- auxprogs/Makefile.in | 7 +
- cachegrind/Makefile.in | 19 +
cachegrind/cg_arch.c | 7 +
cachegrind/cg_branchpred.c | 2 +-
- cachegrind/tests/Makefile.in | 7 +
- cachegrind/tests/x86/Makefile.in | 7 +
- callgrind/Makefile.in | 19 +
- callgrind/tests/Makefile.in | 7 +
- config.h | 2 +-
- configure | 56 +-
configure.ac | 28 +-
coregrind/Makefile.am | 15 +-
- coregrind/Makefile.in | 252 +-
coregrind/launcher-linux.c | 11 +-
coregrind/m_aspacemgr/aspacemgr-common.c | 9 +-
coregrind/m_aspacemgr/aspacemgr-linux.c | 3 +-
coregrind/m_cache.c | 233 +
coregrind/m_coredump/coredump-elf.c | 42 +
coregrind/m_debuginfo/d3basics.c | 3 +
- coregrind/m_debuginfo/debuginfo.c | 30 +-
+ coregrind/m_debuginfo/debuginfo.c | 31 +-
coregrind/m_debuginfo/priv_storage.h | 19 +-
coregrind/m_debuginfo/readdwarf.c | 47 +-
- coregrind/m_debuginfo/readelf.c | 6 +-
+ coregrind/m_debuginfo/readelf.c | 4 +-
coregrind/m_debuginfo/storage.c | 9 +
coregrind/m_debuglog.c | 35 +
.../m_dispatch/dispatch-loongarch64-linux.S | 314 +
@@ -81,9 +70,9 @@ Subject: [PATCH] Add LoongArch64 Linux support
coregrind/m_syswrap/priv_types_n_macros.h | 3 +-
.../m_syswrap/syscall-loongarch64-linux.S | 143 +
coregrind/m_syswrap/syswrap-generic.c | 2 +-
- coregrind/m_syswrap/syswrap-linux.c | 36 +-
- .../m_syswrap/syswrap-loongarch64-linux.c | 644 +
- coregrind/m_syswrap/syswrap-main.c | 93 +-
+ coregrind/m_syswrap/syswrap-linux.c | 38 +-
+ .../m_syswrap/syswrap-loongarch64-linux.c | 648 +
+ coregrind/m_syswrap/syswrap-main.c | 94 +-
coregrind/m_trampoline.S | 48 +
coregrind/m_translate.c | 5 +
coregrind/m_vki.c | 6 +-
@@ -98,106 +87,55 @@ Subject: [PATCH] Add LoongArch64 Linux support
coregrind/pub_core_transtab.h | 3 +-
coregrind/pub_core_transtab_asm.h | 2 +-
coregrind/vgdb-invoker-ptrace.c | 19 +-
- dhat/Makefile.in | 19 +
- dhat/tests/Makefile.in | 7 +
- drd/Makefile.in | 19 +
drd/drd_bitmap.h | 2 +-
drd/drd_load_store.c | 4 +
- drd/tests/Makefile.in | 7 +
drd/tests/pth_barrier_thr_cr.supp | 11 +
- exp-bbv/Makefile.in | 19 +
- exp-bbv/tests/Makefile.in | 7 +
- exp-bbv/tests/amd64-linux/Makefile.in | 7 +
- exp-bbv/tests/arm-linux/Makefile.in | 7 +
- exp-bbv/tests/ppc32-linux/Makefile.in | 7 +
- exp-bbv/tests/x86-linux/Makefile.in | 7 +
- exp-bbv/tests/x86/Makefile.in | 7 +
gdbserver_tests/Makefile.am | 1 +
- gdbserver_tests/Makefile.in | 8 +
gdbserver_tests/filter_helgrind_monitor | 2 +
.../filter_helgrind_monitor_loongarch64 | 43 +
- gdbserver_tests/solaris/Makefile.in | 7 +
- helgrind/Makefile.in | 19 +
helgrind/hg_main.c | 1 +
- helgrind/tests/Makefile.in | 7 +
helgrind/tests/annotate_hbefore.c | 30 +
helgrind/tests/tc07_hbl1.c | 17 +
helgrind/tests/tc08_hbl2.c | 17 +
helgrind/tests/tc11_XCHG.c | 18 +
include/Makefile.am | 3 +
- include/Makefile.in | 3 +
include/pub_tool_basics.h | 6 +-
include/pub_tool_guest.h | 3 +
include/pub_tool_libcsetjmp.h | 8 +
include/pub_tool_machine.h | 6 +
include/pub_tool_redir.h | 2 +
include/pub_tool_vkiscnums_asm.h | 4 +
- include/valgrind.h | 525 +-
include/valgrind.h.in | 525 +-
include/vki/vki-linux.h | 5 +
include/vki/vki-loongarch64-linux.h | 811 +
.../vki/vki-posixtypes-loongarch64-linux.h | 76 +
- include/vki/vki-scnums-loongarch64-linux.h | 356 +
- lackey/Makefile.in | 19 +
- massif/Makefile.in | 19 +
+ include/vki/vki-scnums-loongarch64-linux.h | 330 +
massif/tests/Makefile.am | 1 +
- massif/tests/Makefile.in | 8 +
massif/tests/big-alloc.post.exp-loongarch64 | 54 +
- memcheck/Makefile.in | 19 +
memcheck/mc_machine.c | 119 +
- memcheck/mc_translate.c | 17 +
- memcheck/tests/Makefile.am | 5 +-
- memcheck/tests/Makefile.in | 65 +-
- memcheck/tests/amd64-freebsd/Makefile.in | 7 +
- memcheck/tests/amd64-linux/Makefile.in | 7 +
- memcheck/tests/amd64-solaris/Makefile.in | 7 +
- memcheck/tests/amd64/Makefile.in | 7 +
- memcheck/tests/arm64-linux/Makefile.in | 7 +
+ memcheck/mc_translate.c | 207 +-
+ memcheck/tests/Makefile.am | 7 +-
memcheck/tests/atomic_incs.c | 84 +-
- memcheck/tests/common/Makefile.in | 7 +
- memcheck/tests/darwin/Makefile.in | 7 +
- memcheck/tests/freebsd/Makefile.in | 7 +
memcheck/tests/leak-segv-jmp.c | 15 +-
memcheck/tests/leak-segv-jmp.stderr.exp | 20 +-
memcheck/tests/leak.h | 21 +
- memcheck/tests/linux/Makefile.in | 7 +
+ memcheck/tests/long_namespace_xml.supp | 13 +
+ memcheck/tests/long_namespace_xml.vgtest | 2 +-
memcheck/tests/loongarch64-linux/Makefile.am | 17 +
.../tests/loongarch64-linux/filter_stderr | 3 +
memcheck/tests/loongarch64-linux/scalar.c | 1296 +
memcheck/tests/loongarch64-linux/scalar.h | 62 +
- .../tests/loongarch64-linux/scalar.stderr.exp | 2716 +
+ .../tests/loongarch64-linux/scalar.stderr.exp | 2728 +
.../tests/loongarch64-linux/scalar.vgtest | 5 +
- memcheck/tests/mips32/Makefile.in | 7 +
- memcheck/tests/mips64/Makefile.in | 7 +
- memcheck/tests/ppc32/Makefile.in | 7 +
- memcheck/tests/ppc64/Makefile.in | 7 +
- memcheck/tests/s390x/Makefile.in | 7 +
- memcheck/tests/solaris/Makefile.in | 7 +
memcheck/tests/unit_libcbase.c | 4 +-
- memcheck/tests/vbit-test/Makefile.in | 7 +
- memcheck/tests/vbit-test/irops.c | 526 +-
+ memcheck/tests/vbit-test/irops.c | 614 +-
memcheck/tests/vbit-test/vtest.h | 19 +-
- memcheck/tests/x86-freebsd/Makefile.in | 7 +
- memcheck/tests/x86-linux/Makefile.in | 7 +
- memcheck/tests/x86-solaris/Makefile.in | 7 +
- memcheck/tests/x86/Makefile.in | 7 +
- mpi/Makefile.in | 7 +
nightly/conf/loongarch64.conf | 3 +
nightly/conf/loongarch64.sendemail | 7 +
- none/Makefile.in | 19 +
none/tests/Makefile.am | 9 +-
- none/tests/Makefile.in | 56 +-
none/tests/allexec_prepare_prereq | 13 +-
- none/tests/amd64-darwin/Makefile.in | 7 +
- none/tests/amd64-linux/Makefile.in | 7 +
- none/tests/amd64-solaris/Makefile.in | 7 +
- none/tests/amd64/Makefile.in | 7 +
- none/tests/arm/Makefile.in | 7 +
- none/tests/arm64/Makefile.in | 7 +
- none/tests/darwin/Makefile.in | 7 +
- none/tests/freebsd/Makefile.in | 7 +
+ none/tests/filter_fdleak | 5 +-
none/tests/libvex_test.c | 7 +-
- none/tests/linux/Makefile.in | 7 +
none/tests/loongarch64/Makefile.am | 43 +
none/tests/loongarch64/allexec.c | 56 +
none/tests/loongarch64/atomic.c | 75 +
@@ -257,26 +195,11 @@ Subject: [PATCH] Add LoongArch64 Linux support
none/tests/loongarch64/vector256.stderr.exp | 0
none/tests/loongarch64/vector256.stdout.exp | 0
none/tests/loongarch64/vector256.vgtest | 3 +
- none/tests/mips32/Makefile.in | 7 +
- none/tests/mips64/Makefile.in | 7 +
- none/tests/nanomips/Makefile.in | 7 +
- none/tests/ppc32/Makefile.in | 7 +
- none/tests/ppc64/Makefile.in | 7 +
- none/tests/s390x/Makefile.in | 7 +
- none/tests/scripts/Makefile.in | 7 +
- none/tests/solaris/Makefile.in | 7 +
- none/tests/x86-darwin/Makefile.in | 7 +
- none/tests/x86-freebsd/Makefile.in | 7 +
- none/tests/x86-linux/Makefile.in | 7 +
- none/tests/x86-solaris/Makefile.in | 7 +
- none/tests/x86/Makefile.in | 7 +
- perf/Makefile.in | 7 +
tests/Makefile.am | 3 +-
- tests/Makefile.in | 30 +-
tests/arch_test.c | 5 +
tests/loongarch64_features.c | 81 +
tests/platform_test | 1 +
- 272 files changed, 95890 insertions(+), 475 deletions(-)
+ 194 files changed, 101309 insertions(+), 454 deletions(-)
create mode 100644 README.loongarch64
create mode 100644 VEX/priv/guest_loongarch64_defs.h
create mode 100644 VEX/priv/guest_loongarch64_helpers.c
@@ -303,6 +226,7 @@ Subject: [PATCH] Add LoongArch64 Linux support
create mode 100644 include/vki/vki-posixtypes-loongarch64-linux.h
create mode 100644 include/vki/vki-scnums-loongarch64-linux.h
create mode 100644 massif/tests/big-alloc.post.exp-loongarch64
+ create mode 100644 memcheck/tests/long_namespace_xml.supp
create mode 100644 memcheck/tests/loongarch64-linux/Makefile.am
create mode 100755 memcheck/tests/loongarch64-linux/filter_stderr
create mode 100644 memcheck/tests/loongarch64-linux/scalar.c
@@ -373,10 +297,10 @@ Subject: [PATCH] Add LoongArch64 Linux support
create mode 100644 tests/loongarch64_features.c
diff --git a/Makefile.all.am b/Makefile.all.am
-index 94d65f2..eca59dc 100755
+index dcea269..3d91d40 100755
--- a/Makefile.all.am
+++ b/Makefile.all.am
-@@ -290,6 +290,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
+@@ -291,6 +291,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
$(AM_CFLAGS_PSO_BASE)
AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
@@ -389,7 +313,7 @@ index 94d65f2..eca59dc 100755
AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
$(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -350,6 +356,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
+@@ -352,6 +358,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
@@ -397,45 +321,11 @@ index 94d65f2..eca59dc 100755
PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
-diff --git a/Makefile.in b/Makefile.in
-index 56751f4..81dcc71 100644
---- a/Makefile.in
-+++ b/Makefile.in
-@@ -219,7 +219,7 @@ am__DIST_COMMON = $(srcdir)/Makefile.in $(srcdir)/config.h.in \
- $(top_srcdir)/docs/xml/vg-entities.xml.in \
- $(top_srcdir)/drd/scripts/download-and-build-splash2.in \
- AUTHORS COPYING NEWS README compile config.guess config.sub \
-- install-sh missing
-+ depcomp install-sh missing
- DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
- distdir = $(PACKAGE)-$(VERSION)
- top_distdir = $(distdir)
-@@ -635,6 +635,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -682,6 +688,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- TOOLS = \
diff --git a/Makefile.tool.am b/Makefile.tool.am
-index 4ce6d5a..7dbfbd8 100644
+index c779596..f5f2bc6 100644
--- a/Makefile.tool.am
+++ b/Makefile.tool.am
-@@ -99,6 +99,10 @@ TOOL_LDFLAGS_MIPS64_LINUX = \
+@@ -110,6 +110,10 @@ TOOL_LDFLAGS_MIPS64_LINUX = \
-static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
@FLAG_M64@
@@ -446,7 +336,7 @@ index 4ce6d5a..7dbfbd8 100644
TOOL_LDFLAGS_X86_SOLARIS = \
$(TOOL_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
-@@ -167,6 +171,9 @@ LIBREPLACEMALLOC_MIPS32_LINUX = \
+@@ -181,6 +185,9 @@ LIBREPLACEMALLOC_MIPS32_LINUX = \
LIBREPLACEMALLOC_MIPS64_LINUX = \
$(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips64-linux.a
@@ -456,7 +346,7 @@ index 4ce6d5a..7dbfbd8 100644
LIBREPLACEMALLOC_X86_SOLARIS = \
$(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-solaris.a
-@@ -239,6 +246,11 @@ LIBREPLACEMALLOC_LDFLAGS_MIPS64_LINUX = \
+@@ -258,6 +265,11 @@ LIBREPLACEMALLOC_LDFLAGS_MIPS64_LINUX = \
$(LIBREPLACEMALLOC_MIPS64_LINUX) \
-Wl,--no-whole-archive
@@ -469,7 +359,7 @@ index 4ce6d5a..7dbfbd8 100644
-Wl,--whole-archive \
$(LIBREPLACEMALLOC_X86_SOLARIS) \
diff --git a/Makefile.vex.am b/Makefile.vex.am
-index 98d8483..009d93b 100644
+index c1244a6..8137bee 100644
--- a/Makefile.vex.am
+++ b/Makefile.vex.am
@@ -26,6 +26,7 @@ pkginclude_HEADERS = \
@@ -488,7 +378,7 @@ index 98d8483..009d93b 100644
priv/host_generic_regs.h \
priv/host_generic_simd64.h \
priv/host_generic_simd128.h \
-@@ -64,7 +66,8 @@ noinst_HEADERS = \
+@@ -65,7 +67,8 @@ noinst_HEADERS = \
priv/s390_defs.h \
priv/host_mips_defs.h \
priv/host_nanomips_defs.h \
@@ -498,7 +388,7 @@ index 98d8483..009d93b 100644
BUILT_SOURCES = pub/libvex_guest_offsets.h
CLEANFILES = pub/libvex_guest_offsets.h
-@@ -93,7 +96,8 @@ pub/libvex_guest_offsets.h: auxprogs/genoffsets.c \
+@@ -94,7 +97,8 @@ pub/libvex_guest_offsets.h: auxprogs/genoffsets.c \
pub/libvex_guest_arm64.h \
pub/libvex_guest_s390x.h \
pub/libvex_guest_mips32.h \
@@ -508,174 +398,7 @@ index 98d8483..009d93b 100644
rm -f auxprogs/genoffsets.s
$(mkdir_p) auxprogs pub
$(CC) $(CFLAGS_FOR_GENOFFSETS) \
-@@ -151,6 +155,8 @@ LIBVEX_SOURCES_COMMON = \
- priv/guest_mips_toIR.c \
- priv/guest_nanomips_helpers.c \
- priv/guest_nanomips_toIR.c \
-+ priv/guest_loongarch64_helpers.c \
-+ priv/guest_loongarch64_toIR.c \
- priv/host_generic_regs.c \
- priv/host_generic_simd64.c \
- priv/host_generic_simd128.c \
-@@ -174,7 +180,9 @@ LIBVEX_SOURCES_COMMON = \
- priv/host_mips_defs.c \
- priv/host_nanomips_defs.c \
- priv/host_mips_isel.c \
-- priv/host_nanomips_isel.c
-+ priv/host_nanomips_isel.c \
-+ priv/host_loongarch64_defs.c \
-+ priv/host_loongarch64_isel.c
-
- LIBVEXMULTIARCH_SOURCES = priv/multiarch_main_main.c
-
-diff --git a/Makefile.vex.in b/Makefile.vex.in
-index b0380a6..61f439b 100644
---- a/Makefile.vex.in
-+++ b/Makefile.vex.in
-@@ -188,6 +188,8 @@ am__objects_1 = priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-main_globals.$(OBJEX
- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_mips_toIR.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_nanomips_helpers.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_nanomips_toIR.$(OBJEXT) \
-+ priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.$(OBJEXT) \
-+ priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_regs.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd64.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd128.$(OBJEXT) \
-@@ -211,7 +213,9 @@ am__objects_1 = priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-main_globals.$(OBJEX
- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_mips_defs.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_nanomips_defs.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_mips_isel.$(OBJEXT) \
-- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_nanomips_isel.$(OBJEXT)
-+ priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_nanomips_isel.$(OBJEXT) \
-+ priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.$(OBJEXT) \
-+ priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.$(OBJEXT)
- am_libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_OBJECTS = $(am__objects_1)
- libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_OBJECTS = \
- $(am_libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_OBJECTS)
-@@ -229,7 +233,8 @@ am__libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_SOURCES_DIST = \
- priv/guest_s390_helpers.c priv/guest_s390_toIR.c \
- priv/guest_mips_helpers.c priv/guest_mipsdsp_toIR.c \
- priv/guest_mips_toIR.c priv/guest_nanomips_helpers.c \
-- priv/guest_nanomips_toIR.c priv/host_generic_regs.c \
-+ priv/guest_nanomips_toIR.c priv/guest_loongarch64_helpers.c \
-+ priv/guest_loongarch64_toIR.c priv/host_generic_regs.c \
- priv/host_generic_simd64.c priv/host_generic_simd128.c \
- priv/host_generic_simd256.c priv/host_generic_maddf.c \
- priv/host_generic_reg_alloc2.c priv/host_generic_reg_alloc3.c \
-@@ -240,7 +245,8 @@ am__libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_SOURCES_DIST = \
- priv/host_arm64_isel.c priv/host_s390_defs.c \
- priv/host_s390_isel.c priv/s390_disasm.c priv/host_mips_defs.c \
- priv/host_nanomips_defs.c priv/host_mips_isel.c \
-- priv/host_nanomips_isel.c
-+ priv/host_nanomips_isel.c priv/host_loongarch64_defs.c \
-+ priv/host_loongarch64_isel.c
- am__objects_2 = priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-main_globals.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-main_main.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-main_util.$(OBJEXT) \
-@@ -267,6 +273,8 @@ am__objects_2 = priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-main_globals.$(OBJEX
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_mips_toIR.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_nanomips_helpers.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_nanomips_toIR.$(OBJEXT) \
-+ priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.$(OBJEXT) \
-+ priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_regs.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd64.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd128.$(OBJEXT) \
-@@ -290,7 +298,9 @@ am__objects_2 = priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-main_globals.$(OBJEX
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_mips_defs.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_nanomips_defs.$(OBJEXT) \
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_mips_isel.$(OBJEXT) \
-- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_nanomips_isel.$(OBJEXT)
-+ priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_nanomips_isel.$(OBJEXT) \
-+ priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.$(OBJEXT) \
-+ priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.$(OBJEXT)
- @VGCONF_HAVE_PLATFORM_SEC_TRUE@am_libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_OBJECTS = \
- @VGCONF_HAVE_PLATFORM_SEC_TRUE@ $(am__objects_2)
- libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_OBJECTS = \
-@@ -334,6 +344,8 @@ am__depfiles_remade = priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-gues
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_arm_toIR.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_generic_bb_to_IR.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_generic_x87.Po \
-+ priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.Po \
-+ priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_mips_helpers.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_mips_toIR.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_mipsdsp_toIR.Po \
-@@ -358,6 +370,8 @@ am__depfiles_remade = priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-gues
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd128.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd256.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd64.Po \
-+ priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.Po \
-+ priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_mips_defs.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_mips_isel.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_nanomips_defs.Po \
-@@ -384,6 +398,8 @@ am__depfiles_remade = priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-gues
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_arm_toIR.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_generic_bb_to_IR.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_generic_x87.Po \
-+ priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.Po \
-+ priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_mips_helpers.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_mips_toIR.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_mipsdsp_toIR.Po \
-@@ -408,6 +424,8 @@ am__depfiles_remade = priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-gues
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd128.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd256.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd64.Po \
-+ priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.Po \
-+ priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_mips_defs.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_mips_isel.Po \
- priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_nanomips_defs.Po \
-@@ -851,6 +869,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -898,6 +922,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
-
-@@ -924,6 +949,7 @@ pkginclude_HEADERS = \
- pub/libvex_guest_s390x.h \
- pub/libvex_guest_mips32.h \
- pub/libvex_guest_mips64.h \
-+ pub/libvex_guest_loongarch64.h \
- pub/libvex_s390x_common.h \
- pub/libvex_ir.h \
- pub/libvex_trc_values.h \
-@@ -947,6 +973,7 @@ noinst_HEADERS = \
- priv/guest_mips_defs.h \
- priv/mips_defs.h \
- priv/guest_nanomips_defs.h \
-+ priv/guest_loongarch64_defs.h \
- priv/host_generic_regs.h \
- priv/host_generic_simd64.h \
- priv/host_generic_simd128.h \
-@@ -962,7 +989,8 @@ noinst_HEADERS = \
- priv/s390_defs.h \
- priv/host_mips_defs.h \
- priv/host_nanomips_defs.h \
-- priv/common_nanomips_defs.h
-+ priv/common_nanomips_defs.h \
-+ priv/host_loongarch64_defs.h
-
- BUILT_SOURCES = pub/libvex_guest_offsets.h
- CLEANFILES = pub/libvex_guest_offsets.h
-@@ -1006,6 +1034,8 @@ LIBVEX_SOURCES_COMMON = \
+@@ -152,6 +156,8 @@ LIBVEX_SOURCES_COMMON = \
priv/guest_mips_toIR.c \
priv/guest_nanomips_helpers.c \
priv/guest_nanomips_toIR.c \
@@ -684,7 +407,7 @@ index b0380a6..61f439b 100644
priv/host_generic_regs.c \
priv/host_generic_simd64.c \
priv/host_generic_simd128.c \
-@@ -1029,7 +1059,9 @@ LIBVEX_SOURCES_COMMON = \
+@@ -176,7 +182,9 @@ LIBVEX_SOURCES_COMMON = \
priv/host_mips_defs.c \
priv/host_nanomips_defs.c \
priv/host_mips_isel.c \
@@ -694,311 +417,9 @@ index b0380a6..61f439b 100644
+ priv/host_loongarch64_isel.c
LIBVEXMULTIARCH_SOURCES = priv/multiarch_main_main.c
- LIBVEX_CFLAGS_NO_LTO = \
-@@ -1195,6 +1227,10 @@ priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_nanomips_helpers.$(OBJEXT): \
- priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_nanomips_toIR.$(OBJEXT): \
- priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
-+priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.$(OBJEXT): \
-+ priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
-+priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.$(OBJEXT): \
-+ priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_regs.$(OBJEXT): \
- priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd64.$(OBJEXT): \
-@@ -1243,6 +1279,10 @@ priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_mips_isel.$(OBJEXT): \
- priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_nanomips_isel.$(OBJEXT): \
- priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
-+priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.$(OBJEXT): \
-+ priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
-+priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.$(OBJEXT): \
-+ priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
-
- libvex-@VGCONF_ARCH_PRI@-@VGCONF_OS@.a: $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_OBJECTS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_DEPENDENCIES) $(EXTRA_libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_DEPENDENCIES)
- $(AM_V_at)-rm -f libvex-@VGCONF_ARCH_PRI@-@VGCONF_OS@.a
-@@ -1300,6 +1340,10 @@ priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_nanomips_helpers.$(OBJEXT): \
- priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_nanomips_toIR.$(OBJEXT): \
- priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
-+priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.$(OBJEXT): \
-+ priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
-+priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.$(OBJEXT): \
-+ priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_regs.$(OBJEXT): \
- priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd64.$(OBJEXT): \
-@@ -1348,6 +1392,10 @@ priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_mips_isel.$(OBJEXT): \
- priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_nanomips_isel.$(OBJEXT): \
- priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
-+priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.$(OBJEXT): \
-+ priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
-+priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.$(OBJEXT): \
-+ priv/$(am__dirstamp) priv/$(DEPDIR)/$(am__dirstamp)
-
- libvex-@VGCONF_ARCH_SEC@-@VGCONF_OS@.a: $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_OBJECTS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_DEPENDENCIES) $(EXTRA_libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_DEPENDENCIES)
- $(AM_V_at)-rm -f libvex-@VGCONF_ARCH_SEC@-@VGCONF_OS@.a
-@@ -1383,6 +1431,8 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_arm_toIR.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_generic_bb_to_IR.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_generic_x87.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_mips_helpers.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_mips_toIR.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_mipsdsp_toIR.Po@am__quote@ # am--include-marker
-@@ -1407,6 +1457,8 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd128.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd256.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd64.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_mips_defs.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_mips_isel.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_nanomips_defs.Po@am__quote@ # am--include-marker
-@@ -1433,6 +1485,8 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_arm_toIR.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_generic_bb_to_IR.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_generic_x87.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_mips_helpers.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_mips_toIR.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_mipsdsp_toIR.Po@am__quote@ # am--include-marker
-@@ -1457,6 +1511,8 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd128.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd256.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd64.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_mips_defs.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_mips_isel.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_nanomips_defs.Po@am__quote@ # am--include-marker
-@@ -1864,6 +1920,34 @@ priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_nanomips_toIR.obj: priv/guest_
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_nanomips_toIR.obj `if test -f 'priv/guest_nanomips_toIR.c'; then $(CYGPATH_W) 'priv/guest_nanomips_toIR.c'; else $(CYGPATH_W) '$(srcdir)/priv/guest_nanomips_toIR.c'; fi`
-+priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.o: priv/guest_loongarch64_helpers.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.o -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.Tpo -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.o `test -f 'priv/guest_loongarch64_helpers.c' || echo '$(srcdir)/'`priv/guest_loongarch64_helpers.c
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/guest_loongarch64_helpers.c' object='priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.o `test -f 'priv/guest_loongarch64_helpers.c' || echo '$(srcdir)/'`priv/guest_loongarch64_helpers.c
-+
-+priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.obj: priv/guest_loongarch64_helpers.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.obj -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.Tpo -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.obj `if test -f 'priv/guest_loongarch64_helpers.c'; then $(CYGPATH_W) 'priv/guest_loongarch64_helpers.c'; else $(CYGPATH_W) '$(srcdir)/priv/guest_loongarch64_helpers.c'; fi`
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/guest_loongarch64_helpers.c' object='priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.obj `if test -f 'priv/guest_loongarch64_helpers.c'; then $(CYGPATH_W) 'priv/guest_loongarch64_helpers.c'; else $(CYGPATH_W) '$(srcdir)/priv/guest_loongarch64_helpers.c'; fi`
-+
-+priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.o: priv/guest_loongarch64_toIR.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.o -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.Tpo -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.o `test -f 'priv/guest_loongarch64_toIR.c' || echo '$(srcdir)/'`priv/guest_loongarch64_toIR.c
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/guest_loongarch64_toIR.c' object='priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.o `test -f 'priv/guest_loongarch64_toIR.c' || echo '$(srcdir)/'`priv/guest_loongarch64_toIR.c
-+
-+priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.obj: priv/guest_loongarch64_toIR.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.obj -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.Tpo -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.obj `if test -f 'priv/guest_loongarch64_toIR.c'; then $(CYGPATH_W) 'priv/guest_loongarch64_toIR.c'; else $(CYGPATH_W) '$(srcdir)/priv/guest_loongarch64_toIR.c'; fi`
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/guest_loongarch64_toIR.c' object='priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.obj `if test -f 'priv/guest_loongarch64_toIR.c'; then $(CYGPATH_W) 'priv/guest_loongarch64_toIR.c'; else $(CYGPATH_W) '$(srcdir)/priv/guest_loongarch64_toIR.c'; fi`
-+
- priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_regs.o: priv/host_generic_regs.c
- @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_regs.o -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_regs.Tpo -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_regs.o `test -f 'priv/host_generic_regs.c' || echo '$(srcdir)/'`priv/host_generic_regs.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_regs.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_regs.Po
-@@ -2200,6 +2284,34 @@ priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_nanomips_isel.obj: priv/host_na
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_nanomips_isel.obj `if test -f 'priv/host_nanomips_isel.c'; then $(CYGPATH_W) 'priv/host_nanomips_isel.c'; else $(CYGPATH_W) '$(srcdir)/priv/host_nanomips_isel.c'; fi`
-
-+priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.o: priv/host_loongarch64_defs.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.o -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.Tpo -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.o `test -f 'priv/host_loongarch64_defs.c' || echo '$(srcdir)/'`priv/host_loongarch64_defs.c
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/host_loongarch64_defs.c' object='priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.o `test -f 'priv/host_loongarch64_defs.c' || echo '$(srcdir)/'`priv/host_loongarch64_defs.c
-+
-+priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.obj: priv/host_loongarch64_defs.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.obj -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.Tpo -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.obj `if test -f 'priv/host_loongarch64_defs.c'; then $(CYGPATH_W) 'priv/host_loongarch64_defs.c'; else $(CYGPATH_W) '$(srcdir)/priv/host_loongarch64_defs.c'; fi`
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/host_loongarch64_defs.c' object='priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.obj `if test -f 'priv/host_loongarch64_defs.c'; then $(CYGPATH_W) 'priv/host_loongarch64_defs.c'; else $(CYGPATH_W) '$(srcdir)/priv/host_loongarch64_defs.c'; fi`
-+
-+priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.o: priv/host_loongarch64_isel.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.o -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.Tpo -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.o `test -f 'priv/host_loongarch64_isel.c' || echo '$(srcdir)/'`priv/host_loongarch64_isel.c
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/host_loongarch64_isel.c' object='priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.o `test -f 'priv/host_loongarch64_isel.c' || echo '$(srcdir)/'`priv/host_loongarch64_isel.c
-+
-+priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.obj: priv/host_loongarch64_isel.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.obj -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.Tpo -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.obj `if test -f 'priv/host_loongarch64_isel.c'; then $(CYGPATH_W) 'priv/host_loongarch64_isel.c'; else $(CYGPATH_W) '$(srcdir)/priv/host_loongarch64_isel.c'; fi`
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/host_loongarch64_isel.c' object='priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.obj `if test -f 'priv/host_loongarch64_isel.c'; then $(CYGPATH_W) 'priv/host_loongarch64_isel.c'; else $(CYGPATH_W) '$(srcdir)/priv/host_loongarch64_isel.c'; fi`
-+
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-main_globals.o: priv/main_globals.c
- @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-main_globals.o -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-main_globals.Tpo -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-main_globals.o `test -f 'priv/main_globals.c' || echo '$(srcdir)/'`priv/main_globals.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-main_globals.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-main_globals.Po
-@@ -2564,6 +2676,34 @@ priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_nanomips_toIR.obj: priv/guest_
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_nanomips_toIR.obj `if test -f 'priv/guest_nanomips_toIR.c'; then $(CYGPATH_W) 'priv/guest_nanomips_toIR.c'; else $(CYGPATH_W) '$(srcdir)/priv/guest_nanomips_toIR.c'; fi`
-
-+priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.o: priv/guest_loongarch64_helpers.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.o -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.Tpo -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.o `test -f 'priv/guest_loongarch64_helpers.c' || echo '$(srcdir)/'`priv/guest_loongarch64_helpers.c
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/guest_loongarch64_helpers.c' object='priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.o `test -f 'priv/guest_loongarch64_helpers.c' || echo '$(srcdir)/'`priv/guest_loongarch64_helpers.c
-+
-+priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.obj: priv/guest_loongarch64_helpers.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.obj -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.Tpo -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.obj `if test -f 'priv/guest_loongarch64_helpers.c'; then $(CYGPATH_W) 'priv/guest_loongarch64_helpers.c'; else $(CYGPATH_W) '$(srcdir)/priv/guest_loongarch64_helpers.c'; fi`
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/guest_loongarch64_helpers.c' object='priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.obj `if test -f 'priv/guest_loongarch64_helpers.c'; then $(CYGPATH_W) 'priv/guest_loongarch64_helpers.c'; else $(CYGPATH_W) '$(srcdir)/priv/guest_loongarch64_helpers.c'; fi`
-+
-+priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.o: priv/guest_loongarch64_toIR.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.o -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.Tpo -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.o `test -f 'priv/guest_loongarch64_toIR.c' || echo '$(srcdir)/'`priv/guest_loongarch64_toIR.c
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/guest_loongarch64_toIR.c' object='priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.o `test -f 'priv/guest_loongarch64_toIR.c' || echo '$(srcdir)/'`priv/guest_loongarch64_toIR.c
-+
-+priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.obj: priv/guest_loongarch64_toIR.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.obj -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.Tpo -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.obj `if test -f 'priv/guest_loongarch64_toIR.c'; then $(CYGPATH_W) 'priv/guest_loongarch64_toIR.c'; else $(CYGPATH_W) '$(srcdir)/priv/guest_loongarch64_toIR.c'; fi`
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/guest_loongarch64_toIR.c' object='priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.obj `if test -f 'priv/guest_loongarch64_toIR.c'; then $(CYGPATH_W) 'priv/guest_loongarch64_toIR.c'; else $(CYGPATH_W) '$(srcdir)/priv/guest_loongarch64_toIR.c'; fi`
-+
- priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_regs.o: priv/host_generic_regs.c
- @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_regs.o -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_regs.Tpo -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_regs.o `test -f 'priv/host_generic_regs.c' || echo '$(srcdir)/'`priv/host_generic_regs.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_regs.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_regs.Po
-@@ -2900,6 +3040,34 @@ priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_nanomips_isel.obj: priv/host_na
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_nanomips_isel.obj `if test -f 'priv/host_nanomips_isel.c'; then $(CYGPATH_W) 'priv/host_nanomips_isel.c'; else $(CYGPATH_W) '$(srcdir)/priv/host_nanomips_isel.c'; fi`
-
-+priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.o: priv/host_loongarch64_defs.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.o -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.Tpo -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.o `test -f 'priv/host_loongarch64_defs.c' || echo '$(srcdir)/'`priv/host_loongarch64_defs.c
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/host_loongarch64_defs.c' object='priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.o `test -f 'priv/host_loongarch64_defs.c' || echo '$(srcdir)/'`priv/host_loongarch64_defs.c
-+
-+priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.obj: priv/host_loongarch64_defs.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.obj -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.Tpo -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.obj `if test -f 'priv/host_loongarch64_defs.c'; then $(CYGPATH_W) 'priv/host_loongarch64_defs.c'; else $(CYGPATH_W) '$(srcdir)/priv/host_loongarch64_defs.c'; fi`
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/host_loongarch64_defs.c' object='priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.obj `if test -f 'priv/host_loongarch64_defs.c'; then $(CYGPATH_W) 'priv/host_loongarch64_defs.c'; else $(CYGPATH_W) '$(srcdir)/priv/host_loongarch64_defs.c'; fi`
-+
-+priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.o: priv/host_loongarch64_isel.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.o -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.Tpo -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.o `test -f 'priv/host_loongarch64_isel.c' || echo '$(srcdir)/'`priv/host_loongarch64_isel.c
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/host_loongarch64_isel.c' object='priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.o `test -f 'priv/host_loongarch64_isel.c' || echo '$(srcdir)/'`priv/host_loongarch64_isel.c
-+
-+priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.obj: priv/host_loongarch64_isel.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.obj -MD -MP -MF priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.Tpo -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.obj `if test -f 'priv/host_loongarch64_isel.c'; then $(CYGPATH_W) 'priv/host_loongarch64_isel.c'; else $(CYGPATH_W) '$(srcdir)/priv/host_loongarch64_isel.c'; fi`
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.Tpo priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='priv/host_loongarch64_isel.c' object='priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o priv/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.obj `if test -f 'priv/host_loongarch64_isel.c'; then $(CYGPATH_W) 'priv/host_loongarch64_isel.c'; else $(CYGPATH_W) '$(srcdir)/priv/host_loongarch64_isel.c'; fi`
-+
- priv/libvexmultiarch_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-multiarch_main_main.o: priv/multiarch_main_main.c
- @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libvexmultiarch_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libvexmultiarch_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT priv/libvexmultiarch_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-multiarch_main_main.o -MD -MP -MF priv/$(DEPDIR)/libvexmultiarch_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-multiarch_main_main.Tpo -c -o priv/libvexmultiarch_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-multiarch_main_main.o `test -f 'priv/multiarch_main_main.c' || echo '$(srcdir)/'`priv/multiarch_main_main.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) priv/$(DEPDIR)/libvexmultiarch_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-multiarch_main_main.Tpo priv/$(DEPDIR)/libvexmultiarch_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-multiarch_main_main.Po
-@@ -3090,6 +3258,8 @@ distclean: distclean-am
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_arm_toIR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_generic_bb_to_IR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_generic_x87.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_mips_helpers.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_mips_toIR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_mipsdsp_toIR.Po
-@@ -3114,6 +3284,8 @@ distclean: distclean-am
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd128.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd256.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd64.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_mips_defs.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_mips_isel.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_nanomips_defs.Po
-@@ -3140,6 +3312,8 @@ distclean: distclean-am
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_arm_toIR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_generic_bb_to_IR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_generic_x87.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_mips_helpers.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_mips_toIR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_mipsdsp_toIR.Po
-@@ -3164,6 +3338,8 @@ distclean: distclean-am
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd128.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd256.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd64.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_mips_defs.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_mips_isel.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_nanomips_defs.Po
-@@ -3237,6 +3413,8 @@ maintainer-clean: maintainer-clean-am
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_arm_toIR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_generic_bb_to_IR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_generic_x87.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_helpers.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_loongarch64_toIR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_mips_helpers.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_mips_toIR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-guest_mipsdsp_toIR.Po
-@@ -3261,6 +3439,8 @@ maintainer-clean: maintainer-clean-am
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd128.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd256.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_generic_simd64.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_defs.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_loongarch64_isel.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_mips_defs.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_mips_isel.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-host_nanomips_defs.Po
-@@ -3287,6 +3467,8 @@ maintainer-clean: maintainer-clean-am
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_arm_toIR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_generic_bb_to_IR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_generic_x87.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_helpers.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_loongarch64_toIR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_mips_helpers.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_mips_toIR.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-guest_mipsdsp_toIR.Po
-@@ -3311,6 +3493,8 @@ maintainer-clean: maintainer-clean-am
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd128.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd256.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_generic_simd64.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_defs.Po
-+ -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_loongarch64_isel.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_mips_defs.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_mips_isel.Po
- -rm -f priv/$(DEPDIR)/libvex_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-host_nanomips_defs.Po
-@@ -3461,7 +3645,8 @@ pub/libvex_guest_offsets.h: auxprogs/genoffsets.c \
- pub/libvex_guest_arm64.h \
- pub/libvex_guest_s390x.h \
- pub/libvex_guest_mips32.h \
-- pub/libvex_guest_mips64.h
-+ pub/libvex_guest_mips64.h \
-+ pub/libvex_guest_loongarch64.h
- rm -f auxprogs/genoffsets.s
- $(mkdir_p) auxprogs pub
- $(CC) $(CFLAGS_FOR_GENOFFSETS) \
diff --git a/README b/README
-index 8423880..1a88d1d 100644
+index eabcc6a..27491d2 100644
--- a/README
+++ b/README
@@ -41,6 +41,7 @@ platforms:
@@ -1011,10 +432,10 @@ index 8423880..1a88d1d 100644
- X86/FreeBSD
diff --git a/README.loongarch64 b/README.loongarch64
new file mode 100644
-index 0000000..742bca0
+index 0000000..8e3fce1
--- /dev/null
+++ b/README.loongarch64
-@@ -0,0 +1,51 @@
+@@ -0,0 +1,63 @@
+Status
+~~~~~~
+
@@ -1038,6 +459,18 @@ index 0000000..742bca0
+* Iop_Max64Ux4
+* Iop_Min64Sx4
+* Iop_Min64Ux4
++* Iop_RoundF64x2_RM
++* Iop_RoundF64x2_RP
++* Iop_RoundF64x2_RN
++* Iop_RoundF64x2_RZ
++* Iop_WidenHIto16Sx8
++* Iop_WidenHIto32Sx4
++* Iop_WidenHIto64Sx2
++* Iop_WidenHIto128Sx1
++* Iop_WidenHIto16Ux8
++* Iop_WidenHIto32Ux4
++* Iop_WidenHIto64Ux2
++* Iop_WidenHIto128Ux1
+
+A new IRMBusEvent:
+
@@ -1067,7 +500,7 @@ index 0000000..742bca0
+ https://loongson.github.io/LoongArch-Documentation/LoongArch-toolchain-conventions-EN.html
+
diff --git a/VEX/auxprogs/genoffsets.c b/VEX/auxprogs/genoffsets.c
-index 54376dc..89edf52 100644
+index 6b70cd0..9f4b237 100644
--- a/VEX/auxprogs/genoffsets.c
+++ b/VEX/auxprogs/genoffsets.c
@@ -53,6 +53,7 @@
@@ -1078,7 +511,7 @@ index 54376dc..89edf52 100644
#define VG_STRINGIFZ(__str) #__str
#define VG_STRINGIFY(__str) VG_STRINGIFZ(__str)
-@@ -262,6 +263,41 @@ void foo ( void )
+@@ -265,6 +266,41 @@ void foo ( void )
GENOFFSET(MIPS64,mips64,PC);
GENOFFSET(MIPS64,mips64,HI);
GENOFFSET(MIPS64,mips64,LO);
@@ -1259,10 +692,10 @@ index 0000000..c3b572c
+/*---------------------------------------------------------------*/
diff --git a/VEX/priv/guest_loongarch64_helpers.c b/VEX/priv/guest_loongarch64_helpers.c
new file mode 100644
-index 0000000..e761539
+index 0000000..8d9594b
--- /dev/null
+++ b/VEX/priv/guest_loongarch64_helpers.c
-@@ -0,0 +1,905 @@
+@@ -0,0 +1,908 @@
+
+/*---------------------------------------------------------------*/
+/*--- begin guest_loongarch64_helpers.c ---*/
@@ -1420,6 +853,8 @@ index 0000000..e761539
+ Note, this is only set for wrap-style redirects, not for
+ replace-style ones. */
+ vex_state->guest_NRADDR = 0;
++
++ vex_state->guest_IP_AT_SYSCALL = 0;
+}
+
+
@@ -1488,7 +923,7 @@ index 0000000..e761539
+ .sizeof_IP = 8,
+ /* Describe any sections to be regarded by Memcheck as
+ 'always-defined'. */
-+ .n_alwaysDefd = 6,
++ .n_alwaysDefd = 7,
+ /* ? :( */
+ .alwaysDefd = {
+ /* 0 */ ALWAYSDEFD64(guest_R0),
@@ -1497,6 +932,7 @@ index 0000000..e761539
+ /* 3 */ ALWAYSDEFD64(guest_CMSTART),
+ /* 4 */ ALWAYSDEFD64(guest_CMLEN),
+ /* 5 */ ALWAYSDEFD64(guest_NRADDR),
++ /* 6 */ ALWAYSDEFD64(guest_IP_AT_SYSCALL),
+ }
+};
+
@@ -2170,10 +1606,10 @@ index 0000000..e761539
+/*---------------------------------------------------------------*/
diff --git a/VEX/priv/guest_loongarch64_toIR.c b/VEX/priv/guest_loongarch64_toIR.c
new file mode 100644
-index 0000000..50c24f1
+index 0000000..8860fc7
--- /dev/null
+++ b/VEX/priv/guest_loongarch64_toIR.c
-@@ -0,0 +1,12086 @@
+@@ -0,0 +1,18325 @@
+
+/*--------------------------------------------------------------------*/
+/*--- begin guest_loongarch64_toIR.c ---*/
@@ -2377,13 +1813,21 @@ index 0000000..50c24f1
+}
+
+/* Get the suffix of the insn */
-+static const HChar *mkInsSize ( UInt size ) {
++static const HChar *mkInsSize ( UInt size )
++{
+ const HChar *insSize[8]
+ = { "b", "h", "w", "d", "bu", "hu", "wu", "du" };
+ vassert(size < 8);
+ return insSize[size];
+}
+
++static const HChar *mkInsExtSize ( UInt size ) {
++ const HChar *insSize[8]
++ = { "h.b", "w.h", "d.w", "q.d", "hu.bu", "wu.hu", "du.wu", "qu.du" };
++ vassert(size < 8);
++ return insSize[size];
++}
++
+
+/*------------------------------------------------------------*/
+/*--- Helper bits and pieces for creating IR fragments. ---*/
@@ -2429,6 +1873,11 @@ index 0000000..50c24f1
+ return IRExpr_Const(IRConst_V128(i));
+}
+
++static inline IRExpr* mkV256 ( UShort i )
++{
++ return IRExpr_Const(IRConst_V256(i));
++}
++
+static inline IRExpr* mkexpr ( IRTemp tmp )
+{
+ return IRExpr_RdTmp(tmp);
@@ -2609,6 +2058,62 @@ index 0000000..50c24f1
+ breakupV128to32s(t128_0, t3, t2, t1, t0);
+}
+
++/* Construct a V128-bit value from 16 8-bit ints. */
++static IRExpr* mkV128from8s ( IRTemp t15, IRTemp t14, IRTemp t13, IRTemp t12,
++ IRTemp t11, IRTemp t10, IRTemp t9, IRTemp t8,
++ IRTemp t7, IRTemp t6, IRTemp t5, IRTemp t4,
++ IRTemp t3, IRTemp t2, IRTemp t1, IRTemp t0 )
++{
++ return binop(Iop_64HLtoV128,
++ binop(Iop_32HLto64,
++ binop(Iop_16HLto32,
++ binop(Iop_8HLto16, mkexpr(t15), mkexpr(t14)),
++ binop(Iop_8HLto16, mkexpr(t13), mkexpr(t12))),
++ binop(Iop_16HLto32,
++ binop(Iop_8HLto16, mkexpr(t11), mkexpr(t10)),
++ binop(Iop_8HLto16, mkexpr(t9), mkexpr(t8)))),
++ binop(Iop_32HLto64,
++ binop(Iop_16HLto32,
++ binop(Iop_8HLto16, mkexpr(t7), mkexpr(t6)),
++ binop(Iop_8HLto16, mkexpr(t5), mkexpr(t4))),
++ binop(Iop_16HLto32,
++ binop(Iop_8HLto16, mkexpr(t3), mkexpr(t2)),
++ binop(Iop_8HLto16, mkexpr(t1), mkexpr(t0)))));
++}
++
++/* Construct a V128-bit value from 8 16-bit ints. */
++static IRExpr* mkV128from16s ( IRTemp t7, IRTemp t6, IRTemp t5, IRTemp t4,
++ IRTemp t3, IRTemp t2, IRTemp t1, IRTemp t0 )
++{
++ return binop(Iop_64HLtoV128,
++ binop(Iop_32HLto64,
++ binop(Iop_16HLto32, mkexpr(t7), mkexpr(t6)),
++ binop(Iop_16HLto32, mkexpr(t5), mkexpr(t4))),
++ binop(Iop_32HLto64,
++ binop(Iop_16HLto32, mkexpr(t3), mkexpr(t2)),
++ binop(Iop_16HLto32, mkexpr(t1), mkexpr(t0))));
++}
++
++/* Construct a V128-bit value from 4 32-bit ints. */
++static IRExpr* mkV128from32s ( IRTemp t3, IRTemp t2, IRTemp t1, IRTemp t0 )
++{
++ return binop(Iop_64HLtoV128,
++ binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
++ binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0)));
++}
++
++/* Construct a V128-bit value from 2 64-bit ints. */
++static IRExpr* mkV128from64s ( IRTemp t1, IRTemp t0 )
++{
++ return binop(Iop_64HLtoV128, mkexpr(t1), mkexpr(t0));
++}
++
++/* Construct a V256-bit value from two V128 ints. */
++static IRExpr* mkV256from128s ( IRTemp t1, IRTemp t0 )
++{
++ return binop(Iop_V128HLtoV256, mkexpr(t1), mkexpr(t0));
++}
++
+/* Construct a V256-bit value from four 64-bit ints. */
+static IRExpr* mkV256from64s ( IRTemp t3, IRTemp t2,
+ IRTemp t1, IRTemp t0 )
@@ -2630,11 +2135,10 @@ index 0000000..50c24f1
+ binop(Iop_32HLto64, mkexpr(t5), mkexpr(t4))),
+ binop(Iop_64HLtoV128,
+ binop(Iop_32HLto64, mkexpr(t3), mkexpr(t2)),
-+ binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0)))
-+ );
++ binop(Iop_32HLto64, mkexpr(t1), mkexpr(t0))));
+}
+
-+static IROp mkVecGetElem ( UInt size ) {
++static IROp mkV128GetElem ( UInt size ) {
+ const IROp ops[4]
+ = { Iop_GetElem8x16, Iop_GetElem16x8,
+ Iop_GetElem32x4, Iop_GetElem64x2 };
@@ -2642,6 +2146,481 @@ index 0000000..50c24f1
+ return ops[size];
+}
+
++static IROp mkV128ADD ( UInt size ) {
++ const IROp ops[5]
++ = { Iop_Add8x16, Iop_Add16x8, Iop_Add32x4, Iop_Add64x2, Iop_Add128x1 };
++ vassert(size < 5);
++ return ops[size];
++}
++
++static IROp mkV128SUB ( UInt size ) {
++ const IROp ops[5]
++ = { Iop_Sub8x16, Iop_Sub16x8, Iop_Sub32x4, Iop_Sub64x2, Iop_Sub128x1 };
++ vassert(size < 5);
++ return ops[size];
++}
++
++static IROp mkV128QADDU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_QAdd8Ux16, Iop_QAdd16Ux8, Iop_QAdd32Ux4, Iop_QAdd64Ux2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128QADDS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_QAdd8Sx16, Iop_QAdd16Sx8, Iop_QAdd32Sx4, Iop_QAdd64Sx2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128QSUBU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_QSub8Ux16, Iop_QSub16Ux8, Iop_QSub32Ux4, Iop_QSub64Ux2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128QSUBS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_QSub8Sx16, Iop_QSub16Sx8, Iop_QSub32Sx4, Iop_QSub64Sx2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128MUL ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Mul8x16, Iop_Mul16x8, Iop_Mul32x4, Iop_INVALID };
++ vassert(size < 3);
++ return ops[size];
++}
++
++static IROp mkV128MUHS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_MulHi8Sx16, Iop_MulHi16Sx8, Iop_MulHi32Sx4, Iop_INVALID };
++ vassert(size < 3);
++ return ops[size];
++}
++
++static IROp mkV128MUHU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_MulHi8Ux16, Iop_MulHi16Ux8, Iop_MulHi32Ux4, Iop_INVALID };
++ vassert(size < 3);
++ return ops[size];
++}
++
++static IROp mkV128ABS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Abs8x16, Iop_Abs16x8, Iop_Abs32x4, Iop_Abs64x2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128AVGU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Avg8Ux16, Iop_Avg16Ux8, Iop_Avg32Ux4, Iop_Avg64Ux2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128AVGS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Avg8Sx16, Iop_Avg16Sx8, Iop_Avg32Sx4, Iop_Avg64Sx2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128CLS ( UInt size ) {
++ const IROp ops[3]
++ = { Iop_Cls8x16, Iop_Cls16x8, Iop_Cls32x4 };
++ vassert(size < 3);
++ return ops[size];
++}
++
++static IROp mkV128CLZ ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Clz8x16, Iop_Clz16x8, Iop_Clz32x4, Iop_Clz64x2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128MAXU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Max8Ux16, Iop_Max16Ux8, Iop_Max32Ux4, Iop_Max64Ux2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128MAXS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Max8Sx16, Iop_Max16Sx8, Iop_Max32Sx4, Iop_Max64Sx2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128MINU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Min8Ux16, Iop_Min16Ux8, Iop_Min32Ux4, Iop_Min64Ux2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128MINS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Min8Sx16, Iop_Min16Sx8, Iop_Min32Sx4, Iop_Min64Sx2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128CMPEQ ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_CmpEQ8x16, Iop_CmpEQ16x8, Iop_CmpEQ32x4, Iop_CmpEQ64x2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128CMPGTU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_CmpGT8Ux16, Iop_CmpGT16Ux8, Iop_CmpGT32Ux4, Iop_CmpGT64Ux2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128CMPGTS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_CmpGT8Sx16, Iop_CmpGT16Sx8, Iop_CmpGT32Sx4, Iop_CmpGT64Sx2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128SHL ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Shl8x16, Iop_Shl16x8, Iop_Shl32x4, Iop_Shl64x2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128SHR ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Shr8x16, Iop_Shr16x8, Iop_Shr32x4, Iop_Shr64x2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128SAR ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Sar8x16, Iop_Sar16x8, Iop_Sar32x4, Iop_Sar64x2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128SHLN ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_ShlN8x16, Iop_ShlN16x8, Iop_ShlN32x4, Iop_ShlN64x2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128SHRN ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_ShrN8x16, Iop_ShrN16x8, Iop_ShrN32x4, Iop_ShrN64x2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128SARN ( UInt size )
++{
++ const IROp ops[4]
++ = { Iop_SarN8x16, Iop_SarN16x8, Iop_SarN32x4, Iop_SarN64x2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256MUL ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Mul8x32, Iop_Mul16x16, Iop_Mul32x8, Iop_INVALID };
++ vassert(size < 3);
++ return ops[size];
++}
++
++static IROp mkV256MUHS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_MulHi8Sx32, Iop_MulHi16Sx16, Iop_MulHi32Sx8, Iop_INVALID };
++ vassert(size < 3);
++ return ops[size];
++}
++
++static IROp mkV256MUHU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_MulHi8Ux32, Iop_MulHi16Ux16, Iop_MulHi32Ux8, Iop_INVALID };
++ vassert(size < 3);
++ return ops[size];
++}
++
++static IROp mkV256ABS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Abs8x32, Iop_Abs16x16, Iop_Abs32x8, Iop_Abs64x4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256CMPEQ ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_CmpEQ8x32, Iop_CmpEQ16x16, Iop_CmpEQ32x8, Iop_CmpEQ64x4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128PACKOD ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_PackOddLanes8x16, Iop_PackOddLanes16x8,
++ Iop_PackOddLanes32x4, Iop_InterleaveHI64x2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128PACKEV ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_PackEvenLanes8x16, Iop_PackEvenLanes16x8,
++ Iop_PackEvenLanes32x4, Iop_InterleaveLO64x2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128INTERLEAVELO ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_InterleaveLO8x16, Iop_InterleaveLO16x8,
++ Iop_InterleaveLO32x4, Iop_InterleaveLO64x2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128INTERLEAVEHI ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_InterleaveHI8x16, Iop_InterleaveHI16x8,
++ Iop_InterleaveHI32x4, Iop_InterleaveHI64x2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128EXTHTS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_WidenHIto16Sx8, Iop_WidenHIto32Sx4,
++ Iop_WidenHIto64Sx2, Iop_WidenHIto128Sx1 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV128EXTHTU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_WidenHIto16Ux8, Iop_WidenHIto32Ux4,
++ Iop_WidenHIto64Ux2, Iop_WidenHIto128Ux1 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256ADD ( UInt size ) {
++ const IROp ops[5]
++ = { Iop_Add8x32, Iop_Add16x16, Iop_Add32x8, Iop_Add64x4, Iop_Add128x2 };
++ vassert(size < 5);
++ return ops[size];
++}
++
++static IROp mkV256SUB ( UInt size ) {
++ const IROp ops[5]
++ = { Iop_Sub8x32, Iop_Sub16x16, Iop_Sub32x8, Iop_Sub64x4, Iop_Sub128x2 };
++ vassert(size < 5);
++ return ops[size];
++}
++
++static IROp mkV256QADDU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_QAdd8Ux32, Iop_QAdd16Ux16, Iop_QAdd32Ux8, Iop_QAdd64Ux4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256QADDS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_QAdd8Sx32, Iop_QAdd16Sx16, Iop_QAdd32Sx8, Iop_QAdd64Sx4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256QSUBU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_QSub8Ux32, Iop_QSub16Ux16, Iop_QSub32Ux8, Iop_QSub64Ux4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256QSUBS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_QSub8Sx32, Iop_QSub16Sx16, Iop_QSub32Sx8, Iop_QSub64Sx4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256CMPGTU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_CmpGT8Ux32, Iop_CmpGT16Ux16, Iop_CmpGT32Ux8, Iop_CmpGT64Ux4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256CMPGTS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_CmpGT8Sx32, Iop_CmpGT16Sx16, Iop_CmpGT32Sx8, Iop_CmpGT64Sx4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256MAXU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Max8Ux32, Iop_Max16Ux16, Iop_Max32Ux8, Iop_Max64Ux4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256MAXS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Max8Sx32, Iop_Max16Sx16, Iop_Max32Sx8, Iop_Max64Sx4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256MINU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Min8Ux32, Iop_Min16Ux16, Iop_Min32Ux8, Iop_Min64Ux4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256MINS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Min8Sx32, Iop_Min16Sx16, Iop_Min32Sx8, Iop_Min64Sx4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256SHL ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Shl8x32, Iop_Shl16x16, Iop_Shl32x8, Iop_Shl64x4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256SHR ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Shr8x32, Iop_Shr16x16, Iop_Shr32x8, Iop_Shr64x4};
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256SAR ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Sar8x32, Iop_Sar16x16, Iop_Sar32x8, Iop_Sar64x4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256SHLN ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_ShlN8x32, Iop_ShlN16x16, Iop_ShlN32x8, Iop_ShlN64x4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256SHRN ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_ShrN8x32, Iop_ShrN16x16, Iop_ShrN32x8, Iop_ShrN64x4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256SARN ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_SarN8x32, Iop_SarN16x16, Iop_SarN32x8, Iop_SarN64x4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256AVGU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Avg8Ux32, Iop_Avg16Ux16, Iop_Avg32Ux8, Iop_Avg64Ux4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256AVGS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_Avg8Sx32, Iop_Avg16Sx16, Iop_Avg32Sx8, Iop_Avg64Sx4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256PACKOD ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_PackOddLanes8x32, Iop_PackOddLanes16x16,
++ Iop_PackOddLanes32x8, Iop_InterleaveHI64x4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256PACKEV ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_PackEvenLanes8x32, Iop_PackEvenLanes16x16,
++ Iop_PackEvenLanes32x8, Iop_InterleaveLO64x4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256INTERLEAVELO ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_InterleaveLO8x32, Iop_InterleaveLO16x16,
++ Iop_InterleaveLO32x8, Iop_InterleaveLO64x4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256INTERLEAVEHI ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_InterleaveHI8x32, Iop_InterleaveHI16x16,
++ Iop_InterleaveHI32x8, Iop_InterleaveHI64x4 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256EXTHTS ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_WidenHIto16Sx16, Iop_WidenHIto32Sx8,
++ Iop_WidenHIto64Sx4, Iop_WidenHIto128Sx2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++static IROp mkV256EXTHTU ( UInt size ) {
++ const IROp ops[4]
++ = { Iop_WidenHIto16Ux16, Iop_WidenHIto32Ux8,
++ Iop_WidenHIto64Ux4, Iop_WidenHIto128Ux2 };
++ vassert(size < 4);
++ return ops[size];
++}
++
++#define EX(_tmp) \
++ mkexpr(_tmp)
++
++#define VMUD(_argL, _argR, _mulOp, _narOp) \
++ binop(Iop_64HLtoV128, \
++ unop(_narOp, \
++ binop(_mulOp, \
++ unop(Iop_V128HIto64, _argL), \
++ unop(Iop_V128HIto64, _argR))), \
++ unop(_narOp, \
++ binop(_mulOp, \
++ unop(Iop_V128to64, _argL), \
++ unop(Iop_V128to64, _argR))))
++
+
+/*------------------------------------------------------------*/
+/*--- Helpers for accessing guest registers. ---*/
@@ -10297,97 +10276,6 @@ index 0000000..50c24f1
+/*--- Helpers for vector integer arithmetic insns ---*/
+/*------------------------------------------------------------*/
+
-+static IROp mkVecADD ( UInt size ) {
-+ const IROp ops[5]
-+ = { Iop_Add8x16, Iop_Add16x8, Iop_Add32x4, Iop_Add64x2, Iop_Add128x1 };
-+ vassert(size < 5);
-+ return ops[size];
-+}
-+
-+static IROp mkVecSUB ( UInt size ) {
-+ const IROp ops[5]
-+ = { Iop_Sub8x16, Iop_Sub16x8, Iop_Sub32x4, Iop_Sub64x2, Iop_Sub128x1 };
-+ vassert(size < 5);
-+ return ops[size];
-+}
-+
-+static IROp mkVecMAXU ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_Max8Ux16, Iop_Max16Ux8, Iop_Max32Ux4, Iop_Max64Ux2 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
-+
-+static IROp mkVecMAXS ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_Max8Sx16, Iop_Max16Sx8, Iop_Max32Sx4, Iop_Max64Sx2 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
-+
-+static IROp mkVecMINU ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_Min8Ux16, Iop_Min16Ux8, Iop_Min32Ux4, Iop_Min64Ux2 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
-+
-+static IROp mkVecMINS ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_Min8Sx16, Iop_Min16Sx8, Iop_Min32Sx4, Iop_Min64Sx2 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
-+
-+static IROp mkV256MAXU ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_Max8Ux32, Iop_Max16Ux16, Iop_Max32Ux8, Iop_Max64Ux4 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
-+
-+static IROp mkV256MAXS ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_Max8Sx32, Iop_Max16Sx16, Iop_Max32Sx8, Iop_Max64Sx4 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
-+
-+static IROp mkV256MINU ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_Min8Ux32, Iop_Min16Ux16, Iop_Min32Ux8, Iop_Min64Ux4 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
-+
-+static IROp mkV256MINS ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_Min8Sx32, Iop_Min16Sx16, Iop_Min32Sx8, Iop_Min64Sx4 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
-+
-+static IROp mkVecCMPGTS ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_CmpGT8Sx16, Iop_CmpGT16Sx8, Iop_CmpGT32Sx4, Iop_CmpGT64Sx2 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
-+
-+static IROp mkVecSHLN ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_ShlN8x16, Iop_ShlN16x8, Iop_ShlN32x4, Iop_ShlN64x2 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
-+
-+static IROp mkVecSHRN ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_ShrN8x16, Iop_ShrN16x8, Iop_ShrN32x4, Iop_ShrN64x2 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
-+
+static Bool gen_vadd_vsub ( DisResult* dres, UInt insn,
+ const VexArchInfo* archinfo,
+ const VexAbiInfo* abiinfo )
@@ -10399,7 +10287,7 @@ index 0000000..50c24f1
+ UInt isAdd = SLICE(insn, 17, 17);
+
+ const HChar *nm[2] = { "vsub", "vadd" };
-+ IROp mathOp = isAdd ? mkVecADD(insSz): mkVecSUB(insSz);
++ IROp mathOp = isAdd ? mkV128ADD(insSz): mkV128SUB(insSz);
+
+ DIP("%s.%s %s, %s, %s\n", nm[isAdd], mkInsSize(insSz),
+ nameVReg(vd), nameVReg(vj), nameVReg(vk));
@@ -10415,794 +10303,998 @@ index 0000000..50c24f1
+ return True;
+}
+
-+static Bool gen_vaddi_vsubi ( DisResult* dres, UInt insn,
++static Bool gen_xvadd_xvsub ( DisResult* dres, UInt insn,
+ const VexArchInfo* archinfo,
+ const VexAbiInfo* abiinfo )
+{
-+ UInt vd = SLICE(insn, 4, 0);
-+ UInt vj = SLICE(insn, 9, 5);
-+ UInt ui5 = SLICE(insn, 14, 10);
-+ UInt insSz = SLICE(insn, 16, 15);
-+ UInt isAdd = SLICE(insn, 17, 17);
-+
-+ IRTemp res = newTemp(Ity_V128);
-+ IROp mathOp = isAdd ? mkVecADD(insSz) : mkVecSUB(insSz);
-+
-+ switch (insSz) {
-+ case 0b00: assign(res, unop(Iop_Dup8x16, mkU8(ui5))); break;
-+ case 0b01: assign(res, unop(Iop_Dup16x8, mkU16(ui5))); break;
-+ case 0b10: assign(res, unop(Iop_Dup32x4, mkU32(ui5))); break;
-+ case 0b11: assign(res, binop(Iop_64HLtoV128, mkU64(ui5), mkU64(ui5))); break;
-+ default: vassert(0); break;
-+ }
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isAdd = SLICE(insn, 17, 17);
+
-+ const HChar *nm[2] = { "vsubi", "vaddi" };
++ const HChar *nm[2] = { "xvsub", "xvadd" };
++ IROp mathOp = isAdd ? mkV256ADD(insSz): mkV256SUB(insSz);
+
-+ DIP("%s.%s %s, %s, %u\n", nm[isAdd], mkInsSize(insSz + 4),
-+ nameVReg(vd), nameVReg(vj), ui5);
++ DIP("%s.%s %s, %s, %s\n", nm[isAdd], mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
+ dres->jk_StopHere = Ijk_SigILL;
+ dres->whatNext = Dis_StopHere;
+ return True;
+ }
+
-+ putVReg(vd, binop(mathOp, getVReg(vj), mkexpr(res)));
-+
++ putXReg(xd, binop(mathOp, getXReg(xj), getXReg(xk)));
+ return True;
+}
+
-+static Bool gen_vmax_vmin ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vadd_vsub_q ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
+ UInt vd = SLICE(insn, 4, 0);
+ UInt vj = SLICE(insn, 9, 5);
+ UInt vk = SLICE(insn, 14, 10);
-+ UInt insSz = SLICE(insn, 16, 15);
-+ UInt isMin = SLICE(insn, 17, 17);
-+ UInt isU = SLICE(insn, 18, 18);
-+
-+ IROp op = isMin ? isU ? mkVecMINU(insSz) : mkVecMINS(insSz) :
-+ isU ? mkVecMAXU(insSz) : mkVecMAXS(insSz);
-+ UInt id = isU ? (insSz + 4) : insSz;
-+ const HChar *nm[2] = { "vmax", "vmin" };
-+
-+ DIP("%s.%s %s, %s, %s\n", nm[isMin], mkInsSize(id),
-+ nameVReg(vd), nameVReg(vj), nameVReg(vk));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
++ UInt isSub = SLICE(insn, 15, 15);
+
++ IROp op = isSub ? Iop_Sub128x1 : Iop_Add128x1;
++ const HChar *nm[2] = { "vadd.q", "vsub.q" };
++ DIP("%s %s, %s, %s\n", nm[isSub], nameVReg(vd),
++ nameVReg(vj), nameVReg(vk));
+ putVReg(vd, binop(op, getVReg(vj), getVReg(vk)));
-+
+ return True;
+}
+
-+static Bool gen_xvmax_xvmin ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvadd_xvsub_q ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
+ UInt xd = SLICE(insn, 4, 0);
+ UInt xj = SLICE(insn, 9, 5);
+ UInt xk = SLICE(insn, 14, 10);
-+ UInt insSz = SLICE(insn, 16, 15);
-+ UInt isMin = SLICE(insn, 17, 17);
-+ UInt isU = SLICE(insn, 18, 18);
-+
-+ IROp op = isMin ? isU ? mkV256MINU(insSz) : mkV256MINS(insSz) :
-+ isU ? mkV256MAXU(insSz) : mkV256MAXS(insSz);
-+ UInt id = isU ? (insSz + 4) : insSz;
-+ const HChar *nm[2] = { "xvmax", "xvmin" };
-+
-+ DIP("%s.%s %s, %s, %s\n", nm[isMin], mkInsSize(id),
-+ nameXReg(xd), nameXReg(xj), nameXReg(xk));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
++ UInt isSub = SLICE(insn, 15, 15);
+
++ IROp op = isSub ? Iop_Sub128x2 : Iop_Add128x2;
++ const HChar *nm[2] = { "xvadd.q", "xvsub.q" };
++ DIP("%s %s, %s, %s\n", nm[isSub], nameXReg(xd),
++ nameVReg(xj), nameXReg(xk));
+ putXReg(xd, binop(op, getXReg(xj), getXReg(xk)));
-+
+ return True;
+}
+
-+static IRTemp gen_vmsk_b ( IRTemp shr )
++static Bool gen_vaddi_vsubi ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ UInt i;
-+ IRTemp tmp[16];
-+ IRTemp tOr = newTemp(Ity_I32);
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt ui5 = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isAdd = SLICE(insn, 17, 17);
++
+ IRTemp res = newTemp(Ity_V128);
++ IROp mathOp = isAdd ? mkV128ADD(insSz) : mkV128SUB(insSz);
+
-+ for (i = 0; i < 16; i++) {
-+ tmp[i] = newTemp(Ity_I32);
-+ assign(tmp[i], binop(Iop_Shl32,
-+ unop(Iop_8Uto32,
-+ binop(Iop_GetElem8x16,
-+ mkexpr(shr), mkU8(i))),
-+ mkU8(i)));
++ switch (insSz) {
++ case 0b00: assign(res, unop(Iop_Dup8x16, mkU8(ui5))); break;
++ case 0b01: assign(res, unop(Iop_Dup16x8, mkU16(ui5))); break;
++ case 0b10: assign(res, unop(Iop_Dup32x4, mkU32(ui5))); break;
++ case 0b11: assign(res, binop(Iop_64HLtoV128, mkU64(ui5), mkU64(ui5))); break;
++ default: vassert(0);
+ }
+
-+ assign(tOr, binop(Iop_Or32,
-+ binop(Iop_Or32,
-+ binop(Iop_Or32,
-+ binop(Iop_Or32, mkexpr(tmp[15]), mkexpr(tmp[14])),
-+ binop(Iop_Or32, mkexpr(tmp[13]), mkexpr(tmp[12]))),
-+ binop(Iop_Or32,
-+ binop(Iop_Or32, mkexpr(tmp[11]), mkexpr(tmp[10])),
-+ binop(Iop_Or32, mkexpr(tmp[9]), mkexpr(tmp[8])))),
-+ binop(Iop_Or32,
-+ binop(Iop_Or32,
-+ binop(Iop_Or32, mkexpr(tmp[7]), mkexpr(tmp[6])),
-+ binop(Iop_Or32, mkexpr(tmp[5]), mkexpr(tmp[4]))),
-+ binop(Iop_Or32,
-+ binop(Iop_Or32, mkexpr(tmp[3]), mkexpr(tmp[2])),
-+ binop(Iop_Or32, mkexpr(tmp[1]), mkexpr(tmp[0]))))));
-+ assign(res, unop(Iop_64UtoV128, extendU(Ity_I32, mkexpr(tOr))));
-+
-+ return res;
-+}
-+
-+static IRTemp gen_vmsk_h ( IRTemp shr )
-+{
-+ UInt i;
-+ IRTemp tmp[8];
-+ IRTemp tOr = newTemp(Ity_I32);
-+ IRTemp res = newTemp(Ity_V128);
++ const HChar *nm[2] = { "vsubi", "vaddi" };
++ DIP("%s.%s %s, %s, %u\n", nm[isAdd], mkInsSize(insSz + 4),
++ nameVReg(vd), nameVReg(vj), ui5);
+
-+ for (i = 0; i < 8; i++) {
-+ tmp[i] = newTemp(Ity_I32);
-+ assign(tmp[i], binop(Iop_Shl32,
-+ unop(Iop_16Uto32,
-+ binop(Iop_GetElem16x8,
-+ mkexpr(shr), mkU8(i))),
-+ mkU8(i)));
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
+
-+ assign(tOr, binop(Iop_Or32,
-+ binop(Iop_Or32,
-+ binop(Iop_Or32, mkexpr(tmp[7]), mkexpr(tmp[6])),
-+ binop(Iop_Or32, mkexpr(tmp[5]), mkexpr(tmp[4]))),
-+ binop(Iop_Or32,
-+ binop(Iop_Or32, mkexpr(tmp[3]), mkexpr(tmp[2])),
-+ binop(Iop_Or32, mkexpr(tmp[1]), mkexpr(tmp[0])))));
-+ assign(res, unop(Iop_64UtoV128, extendU(Ity_I32, mkexpr(tOr))));
-+
-+ return res;
++ putVReg(vd, binop(mathOp, getVReg(vj), mkexpr(res)));
++ return True;
+}
+
-+static IRTemp gen_vmsk_w ( IRTemp shr )
++static Bool gen_xvaddi_xvsubi ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ UInt i;
-+ IRTemp tmp[4];
-+ IRTemp tOr = newTemp(Ity_I32);
-+ IRTemp res = newTemp(Ity_V128);
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt ui5 = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isAdd = SLICE(insn, 17, 17);
+
-+ for (i = 0; i < 4; i++) {
-+ tmp[i] = newTemp(Ity_I32);
-+ assign(tmp[i], binop(Iop_Shl32,
-+ binop(Iop_GetElem32x4,
-+ mkexpr(shr), mkU8(i)),
-+ mkU8(i)));
++ IRTemp dup = newTemp(Ity_V128);
++ IROp mathOp = isAdd ? mkV256ADD(insSz) : mkV256SUB(insSz);
++
++ switch (insSz) {
++ case 0b00: assign(dup, unop(Iop_Dup8x16, mkU8(ui5))); break;
++ case 0b01: assign(dup, unop(Iop_Dup16x8, mkU16(ui5))); break;
++ case 0b10: assign(dup, unop(Iop_Dup32x4, mkU32(ui5))); break;
++ case 0b11: assign(dup, binop(Iop_64HLtoV128, mkU64(ui5), mkU64(ui5))); break;
++ default: vassert(0);
+ }
-+ assign(tOr, binop(Iop_Or32,
-+ binop(Iop_Or32, mkexpr(tmp[3]), mkexpr(tmp[2])),
-+ binop(Iop_Or32, mkexpr(tmp[1]), mkexpr(tmp[0]))));
+
-+ assign(res, unop(Iop_64UtoV128, extendU(Ity_I32, mkexpr(tOr))));
++ const HChar *nm[2] = { "xvsubi", "xvaddi" };
++ DIP("%s.%s %s, %s, %u\n", nm[isAdd], mkInsSize(insSz + 4),
++ nameXReg(xd), nameXReg(xj), ui5);
+
-+ return res;
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
++
++ putXReg(xd, binop(mathOp, getXReg(xj), mkV256from128s(dup, dup)));
++ return True;
+}
+
-+static IRTemp gen_vmsk_d ( IRTemp shr )
++static void gen_vpcnt ( UInt insSz, IRTemp *res, IRExpr *src )
+{
-+ UInt i;
-+ IRTemp tmp[2];
-+ IRTemp res = newTemp(Ity_V128);
++ IRTemp cnt8 = newTemp(Ity_V128);
++ IRTemp add16 = newTemp(Ity_V128);
++ IRTemp add32 = newTemp(Ity_V128);
+
-+ for (i = 0; i < 2; i++) {
-+ tmp[i] = newTemp(Ity_I64);
-+ assign(tmp[i], binop(Iop_Shl64,
-+ binop(Iop_GetElem64x2,
-+ mkexpr(shr), mkU8(i)),
-+ mkU8(i)));
++ switch (insSz) {
++ case 0b00: {
++ assign(*res, unop(Iop_Cnt8x16, src));
++ break;
++ }
++ case 0b01: {
++ assign(cnt8, unop(Iop_Cnt8x16, src));
++ assign(*res, binop(Iop_Add16x8,
++ unop(Iop_WidenHIto16Ux8,
++ binop(Iop_PackEvenLanes8x16,
++ mkexpr(cnt8), mkV128(0x0000))),
++ unop(Iop_WidenHIto16Ux8,
++ binop(Iop_PackOddLanes8x16,
++ mkexpr(cnt8), mkV128(0x0000)))));
++ break;
++ }
++ case 0b10: {
++ assign(cnt8, unop(Iop_Cnt8x16, src));
++ assign(add16, binop(Iop_Add16x8,
++ unop(Iop_WidenHIto16Ux8,
++ binop(Iop_PackEvenLanes8x16,
++ mkexpr(cnt8), mkV128(0x0000))),
++ unop(Iop_WidenHIto16Ux8,
++ binop(Iop_PackOddLanes8x16,
++ mkexpr(cnt8), mkV128(0x0000)))));
++ assign(*res, binop(Iop_Add32x4,
++ unop(Iop_WidenHIto32Ux4,
++ binop(Iop_PackEvenLanes16x8,
++ mkexpr(add16), mkV128(0x0000))),
++ unop(Iop_WidenHIto32Ux4,
++ binop(Iop_PackOddLanes16x8,
++ mkexpr(add16), mkV128(0x0000)))));
++ break;
++ }
++ case 0b11: {
++ assign(cnt8, unop(Iop_Cnt8x16, src));
++ assign(add16, binop(Iop_Add16x8,
++ unop(Iop_WidenHIto16Ux8,
++ binop(Iop_PackEvenLanes8x16,
++ mkexpr(cnt8), mkV128(0x0000))),
++ unop(Iop_WidenHIto16Ux8,
++ binop(Iop_PackOddLanes8x16,
++ mkexpr(cnt8), mkV128(0x0000)))));
++ assign(add32, binop(Iop_Add32x4,
++ unop(Iop_WidenHIto32Ux4,
++ binop(Iop_PackEvenLanes16x8,
++ mkexpr(add16), mkV128(0x0000))),
++ unop(Iop_WidenHIto32Ux4,
++ binop(Iop_PackOddLanes16x8,
++ mkexpr(add16), mkV128(0x0000)))));
++ assign(*res, binop(Iop_Add64x2,
++ unop(Iop_WidenHIto64Ux2,
++ binop(Iop_PackEvenLanes32x4,
++ mkexpr(add32), mkV128(0x0000))),
++ unop(Iop_WidenHIto64Ux2,
++ binop(Iop_PackOddLanes32x4,
++ mkexpr(add32), mkV128(0x0000)))));
++ break;
++ }
++ default: vassert(0);
+ }
-+ assign(res, unop(Iop_64UtoV128,
-+ binop(Iop_Or64,mkexpr(tmp[1]), mkexpr(tmp[0]))));
-+
-+ return res;
+}
+
-+static Bool gen_vmsk ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vcount ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
+ UInt vd = SLICE(insn, 4, 0);
+ UInt vj = SLICE(insn, 9, 5);
+ UInt insSz = SLICE(insn, 11, 10);
+ UInt insTy = SLICE(insn, 13, 12);
+
-+ IRTemp shr = newTemp(Ity_V128);
-+ IRTemp cmp = newTemp(Ity_V128);
+ IRTemp res = newTemp(Ity_V128);
-+ IRTemp src = newTemp(Ity_V128);
-+ assign(src, getVReg(vj));
-+
+ switch (insTy) {
+ case 0b00: {
-+ UInt shrNum[4] = {7, 15, 31, 63};
-+
-+ DIP("vmskltz.%s %s, %s\n", mkInsSize(insSz), nameVReg(vd), nameVReg(vj));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
-+
-+ assign(cmp, binop(mkVecCMPGTS(insSz), mkV128(0x0000), mkexpr(src)));
-+ assign(shr, binop(mkVecSHRN(insSz), mkexpr(cmp), mkU8(shrNum[insSz])));
-+
-+ switch(insSz) {
-+ case 0b00: res = gen_vmsk_b(shr); break;
-+ case 0b01: res = gen_vmsk_h(shr); break;
-+ case 0b10: res = gen_vmsk_w(shr); break;
-+ case 0b11: res = gen_vmsk_d(shr); break;
-+ default: vassert(0); break;
++ if (insSz == 0b11) {
++ assign(res, unop(Iop_Clz64x2,
++ unop(Iop_NotV128, getVReg(vj))));
++ } else {
++ assign(res, unop(mkV128CLS(insSz), getVReg(vj)));
+ }
+ break;
+ }
-+
+ case 0b01: {
-+ DIP("vmskgez.b %s, %s\n", nameVReg(vd), nameVReg(vj));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
-+
-+ assign(cmp, binop(Iop_OrV128,
-+ binop(Iop_CmpGT8Sx16, mkexpr(src), mkV128(0x0000)),
-+ binop(Iop_CmpEQ8x16, mkV128(0x0000), mkexpr(src))));
-+ assign(shr, binop(Iop_ShrN8x16, mkexpr(cmp), mkU8(7)));
-+ res = gen_vmsk_b(shr);
++ assign(res, unop(mkV128CLZ(insSz), getVReg(vj)));
+ break;
+ }
-+
+ case 0b10: {
-+ DIP("vmsknz.b %s, %s\n", nameVReg(vd), nameVReg(vj));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
-+ assign(cmp, unop(Iop_NotV128,
-+ binop(Iop_CmpEQ8x16, mkV128(0x0000), mkexpr(src))));
-+ assign(shr, binop(Iop_ShrN8x16, mkexpr(cmp), mkU8(7)));
-+ res = gen_vmsk_b(shr);
++ gen_vpcnt(insSz, &res, getVReg(vj));
+ break;
+ }
-+
-+ default:
-+ return False;
++ case 0b11: {
++ assign(res, binop(mkV128SUB(insSz),
++ mkV128(0x0000), getVReg(vj)));
++ break;
++ }
++ default: vassert(0);
+ }
+
++ const HChar *nm[4] = { "vclo", "vclz", "vpcnt", "vneg" };
++ DIP("%s.%s %s, %s\n", nm[insTy], mkInsSize(insSz),
++ nameVReg(vd), nameVReg(vj));
+ putVReg(vd, mkexpr(res));
-+
+ return True;
+}
+
-+static Bool gen_xvmsk ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvcount ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
+ UInt xd = SLICE(insn, 4, 0);
+ UInt xj = SLICE(insn, 9, 5);
++ UInt insSz = SLICE(insn, 11, 10);
+ UInt insTy = SLICE(insn, 13, 12);
+
-+ IRTemp shrHi = newTemp(Ity_V128);
-+ IRTemp shrLo = newTemp(Ity_V128);
-+ IRTemp cmpHi = newTemp(Ity_V128);
-+ IRTemp cmpLo = newTemp(Ity_V128);
+ IRTemp res = newTemp(Ity_V256);
+ IRTemp src = newTemp(Ity_V256);
-+ assign(src, getXReg(xj));
++ IRTemp sHi = IRTemp_INVALID;
++ IRTemp sLo = IRTemp_INVALID;
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
+
++ assign(src, getXReg(xj));
++ breakupV256toV128s(src, &sHi, &sLo);
+ switch (insTy) {
-+ case 0b10: {
-+ DIP("xvmsknz.b %s, %s\n", nameXReg(xd), nameXReg(xj));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
++ case 0b00: {
++ if (insSz == 0b11) {
++ assign(rHi, unop(Iop_Clz64x2,
++ unop(Iop_NotV128, EX(sHi))));
++ assign(rLo, unop(Iop_Clz64x2,
++ unop(Iop_NotV128, EX(sLo))));
++ } else {
++ assign(rHi, unop(mkV128CLS(insSz), EX(sHi)));
++ assign(rLo, unop(mkV128CLS(insSz), EX(sLo)));
+ }
-+
-+ IRTemp hi, lo;
-+ hi = lo = IRTemp_INVALID;
-+ breakupV256toV128s(src, &hi, &lo);
-+ assign(cmpHi, unop(Iop_NotV128,
-+ binop(Iop_CmpEQ8x16, mkV128(0x0000), mkexpr(hi))));
-+ assign(shrHi, binop(Iop_ShrN8x16, mkexpr(cmpHi), mkU8(7)));
-+ assign(cmpLo, unop(Iop_NotV128,
-+ binop(Iop_CmpEQ8x16, mkV128(0x0000), mkexpr(lo))));
-+ assign(shrLo, binop(Iop_ShrN8x16, mkexpr(cmpLo), mkU8(7)));
-+ assign(res, binop(Iop_V128HLtoV256, mkexpr(gen_vmsk_b(shrHi)), mkexpr(gen_vmsk_b(shrLo))));
++ assign(res, mkV256from128s(rHi, rLo));
+ break;
+ }
-+
-+ default:
-+ return False;
++ case 0b01: {
++ assign(rHi, unop(mkV128CLZ(insSz), EX(sHi)));
++ assign(rLo, unop(mkV128CLZ(insSz), EX(sLo)));
++ assign(res, mkV256from128s(rHi, rLo));
++ break;
++ }
++ case 0b10: {
++ gen_vpcnt(insSz, &rHi, EX(sHi));
++ gen_vpcnt(insSz, &rLo, EX(sLo));
++ assign(res, mkV256from128s(rHi, rLo));
++ break;
++ }
++ case 0b11: {
++ assign(res, binop(mkV256SUB(insSz),
++ mkV256(0x0000), EX(src)));
++ break;
++ }
++ default: vassert(0);
+ }
+
++ const HChar *nm[4] = { "xvclo", "xvclz", "xvpcnt", "xvneg" };
++ DIP("%s.%s %s, %s\n", nm[insTy], mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj));
+ putXReg(xd, mkexpr(res));
-+
+ return True;
+}
+
-+
-+/*------------------------------------------------------------*/
-+/*--- Helpers for vector bit operation insns ---*/
-+/*------------------------------------------------------------*/
-+
-+static Bool gen_logical_v ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vsadd_vssub ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
+ UInt vd = SLICE(insn, 4, 0);
+ UInt vj = SLICE(insn, 9, 5);
+ UInt vk = SLICE(insn, 14, 10);
-+ UInt insTy = SLICE(insn, 17, 15);
-+
-+ IRTemp res = newTemp(Ity_V128);
-+ IRTemp srcL = newTemp(Ity_V128);
-+ IRTemp srcR = newTemp(Ity_V128);
-+ assign(srcL, getVReg(vj));
-+ assign(srcR, getVReg(vk));
-+
-+ switch (insTy) {
-+ case 0b100:
-+ assign(res, binop(Iop_AndV128, mkexpr(srcL), mkexpr(srcR)));
-+ break;
-+ case 0b101:
-+ assign(res, binop(Iop_OrV128, mkexpr(srcL), mkexpr(srcR)));
-+ break;
-+ case 0b110:
-+ assign(res, binop(Iop_XorV128, mkexpr(srcL), mkexpr(srcR)));
-+ break;
-+ case 0b111:
-+ assign(res, unop(Iop_NotV128, binop(Iop_OrV128,
-+ mkexpr(srcL), mkexpr(srcR))));
-+ break;
-+ case 0b000:
-+ assign(res, binop(Iop_AndV128,
-+ unop(Iop_NotV128, mkexpr(srcL)),
-+ mkexpr(srcR)));
-+ break;
-+ case 0b001:
-+ assign(res, binop(Iop_OrV128,
-+ mkexpr(srcL),
-+ unop(Iop_NotV128, mkexpr(srcR))));
-+ break;
-+ default:
-+ return False;
-+ }
-+
-+ const HChar *nm[8] = { "vandn.v", "vorn.v", "", "",
-+ "vand.v", "vor.v", "vxor.v", "vnor.v" };
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isAdd = SLICE(insn, 17, 17);
+
-+ DIP("%s %s, %s, %s\n", nm[insTy], nameVReg(vd), nameVReg(vj), nameVReg(vk));
++ UInt id = insSz;
++ IROp mathOp = Iop_INVALID;
+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
++ switch (SLICE(insn, 19, 17)) {
++ case 0b011: mathOp = mkV128QADDS(insSz); break;
++ case 0b100: mathOp = mkV128QSUBS(insSz); break;
++ case 0b101: mathOp = mkV128QADDU(insSz); id = insSz + 4; break;
++ case 0b110: mathOp = mkV128QSUBU(insSz); id = insSz + 4; break;
++ default: vassert(0);
+ }
+
-+ putVReg(vd, mkexpr(res));
-+
++ const HChar *name[2] = { "vssub", "vsadd" };
++ DIP("%s.%s %s, %s, %s\n", name[isAdd], mkInsSize(id),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++ putVReg(vd, binop(mathOp, getVReg(vj), getVReg(vk)));
+ return True;
+}
+
-+static Bool gen_logical_xv ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvsadd_xvssub ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
+ UInt xd = SLICE(insn, 4, 0);
+ UInt xj = SLICE(insn, 9, 5);
+ UInt xk = SLICE(insn, 14, 10);
-+ UInt insTy = SLICE(insn, 17, 15);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isAdd = SLICE(insn, 17, 17);
+
-+ IRTemp res = newTemp(Ity_V256);
-+ IRTemp sL = newTemp(Ity_V256);
-+ IRTemp sR = newTemp(Ity_V256);
-+ assign(sL, getXReg(xj));
-+ assign(sR, getXReg(xk));
++ UInt id = insSz;
++ IROp mathOp = Iop_INVALID;
+
-+ switch (insTy) {
-+ case 0b110:
-+ assign(res, binop(Iop_XorV256, mkexpr(sL), mkexpr(sR)));
-+ break;
-+ default:
-+ return False;
++ switch (SLICE(insn, 19, 17)) {
++ case 0b011: mathOp = mkV256QADDS(insSz); break;
++ case 0b100: mathOp = mkV256QSUBS(insSz); break;
++ case 0b101: mathOp = mkV256QADDU(insSz); id = insSz + 4; break;
++ case 0b110: mathOp = mkV256QSUBU(insSz); id = insSz + 4; break;
++ default: vassert(0);
+ }
+
-+ const HChar *nm[8] = { "xvandn.v", "xvorn.v", "", "",
-+ "xvand.v", "xvor.v", "xvxor.v", "xvnor.v" };
++ const HChar *name[2] = { "xvssub", "xvsadd" };
++ DIP("%s.%s %s, %s, %s\n", name[isAdd], mkInsSize(id),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, binop(mathOp, getXReg(xj), getXReg(xk)));
++ return True;
++}
+
-+ DIP("%s %s, %s, %s\n", nm[insTy], nameXReg(xd), nameXReg(xj), nameXReg(xk));
++static Bool gen_vhaddw_vhsubw ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isSub = SLICE(insn, 17, 17);
++ UInt isU = SLICE(insn, 19, 19);
+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
++ IRTemp tmpOd = newTemp(Ity_V128);
++ IRTemp tmpEv = newTemp(Ity_V128);
++ IROp widenOp = isU ? mkV128EXTHTU(insSz) : mkV128EXTHTS(insSz);
++ IROp mathOp = isSub ? mkV128SUB(insSz + 1) : mkV128ADD(insSz + 1);
++ UInt id = isU ? (insSz + 4) : insSz;
+
-+ putXReg(xd, mkexpr(res));
++ assign(tmpOd, unop(widenOp, binop(mkV128PACKOD(insSz),
++ getVReg(vj), mkV128(0x0000))));
++ assign(tmpEv, unop(widenOp, binop(mkV128PACKEV(insSz),
++ getVReg(vk), mkV128(0x0000))));
++ const HChar *nm[2] = { "vhaddw", "vhsubw" };
++ DIP("%s.%s %s, %s, %s\n", nm[isSub], mkInsExtSize(id),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++ putVReg(vd, binop(mathOp, mkexpr(tmpOd), mkexpr(tmpEv)));
++ return True;
++}
++
++static Bool gen_xvhaddw_xvhsubw ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isSub = SLICE(insn, 17, 17);
++ UInt isU = SLICE(insn, 19, 19);
++
++ IRTemp tmpOd = newTemp(Ity_V256);
++ IRTemp tmpEv = newTemp(Ity_V256);
++ IROp widenOp = isU ? mkV256EXTHTU(insSz) : mkV256EXTHTS(insSz);
++ IROp mathOp = isSub ? mkV256SUB(insSz + 1) : mkV256ADD(insSz + 1);
++ UInt id = isU ? (insSz + 4) : insSz;
+
++ assign(tmpOd, unop(widenOp, binop(mkV256PACKOD(insSz),
++ getXReg(xj), mkV256(0x0000))));
++ assign(tmpEv, unop(widenOp, binop(mkV256PACKEV(insSz),
++ getXReg(xk), mkV256(0x0000))));
++ const HChar *nm[2] = { "xvhaddw", "xvhsubw" };
++ DIP("%s.%s %s, %s, %s\n", nm[isSub], mkInsExtSize(id),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, binop(mathOp, mkexpr(tmpOd), mkexpr(tmpEv)));
+ return True;
+}
+
-+static Bool gen_vlogical_u8 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vaddw_vsubw_x_x ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
+ UInt vd = SLICE(insn, 4, 0);
+ UInt vj = SLICE(insn, 9, 5);
-+ UInt ui8 = SLICE(insn, 17, 10);
-+ UInt insTy = SLICE(insn, 19, 18);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
+
-+ IRTemp res = newTemp(Ity_V128);
-+ switch (insTy) {
-+ case 0b00:
-+ assign(res, binop(Iop_AndV128,
-+ getVReg(vj),
-+ unop(Iop_Dup8x16, mkU8(ui8))));
++ UInt id = insSz;
++ IROp mathOp = Iop_INVALID;
++ IROp packOp = Iop_INVALID;
++ IROp widenOp = Iop_INVALID;
++ IRTemp argL = newTemp(Ity_V128);
++ IRTemp argR = newTemp(Ity_V128);
++ const HChar *nm;
++
++ switch (SLICE(insn, 21, 17)) {
++ case 0b01111: {
++ nm = "vaddwev";
++ packOp = mkV128PACKEV(insSz);
++ mathOp = mkV128ADD(insSz + 1);
++ widenOp = mkV128EXTHTS(insSz);
+ break;
-+ case 0b01:
-+ assign(res, binop(Iop_OrV128,
-+ getVReg(vj),
-+ unop(Iop_Dup8x16, mkU8(ui8))));
++ }
++ case 0b10000: {
++ nm = "vsubwev";
++ packOp = mkV128PACKEV(insSz);
++ mathOp = mkV128SUB(insSz + 1);
++ widenOp = mkV128EXTHTS(insSz);
+ break;
-+ case 0b10:
-+ assign(res, binop(Iop_XorV128,
-+ getVReg(vj),
-+ unop(Iop_Dup8x16, mkU8(ui8))));
++ }
++ case 0b10001: {
++ nm = "vaddwod";
++ packOp = mkV128PACKOD(insSz);
++ mathOp = mkV128ADD(insSz + 1);
++ widenOp = mkV128EXTHTS(insSz);
+ break;
-+ case 0b11:
-+ assign(res, unop(Iop_NotV128,
-+ binop(Iop_OrV128,
-+ getVReg(vj),
-+ unop(Iop_Dup8x16, mkU8(ui8)))));
++ }
++ case 0b10010: {
++ nm = "vsubwod";
++ packOp = mkV128PACKOD(insSz);
++ mathOp = mkV128SUB(insSz + 1);
++ widenOp = mkV128EXTHTS(insSz);
+ break;
-+ default:
-+ vassert(0);
++ }
++ case 0b10111: {
++ nm ="vaddwev";
++ packOp = mkV128PACKEV(insSz);
++ mathOp = mkV128ADD(insSz + 1);
++ widenOp = mkV128EXTHTU(insSz);
++ id = insSz + 4;
+ break;
++ }
++ case 0b11000: {
++ nm = "vsubwev";
++ packOp = mkV128PACKEV(insSz);
++ mathOp = mkV128SUB(insSz + 1);
++ widenOp = mkV128EXTHTU(insSz);
++ id = insSz + 4;
++ break;
++ }
++ case 0b11001: {
++ nm = "vaddwod";
++ packOp = mkV128PACKOD(insSz);
++ mathOp = mkV128ADD(insSz + 1);
++ widenOp = mkV128EXTHTU(insSz);
++ id = insSz + 4;
++ break;
++ }
++ case 0b11010: {
++ nm = "vsubwod";
++ packOp = mkV128PACKOD(insSz);
++ mathOp = mkV128SUB(insSz + 1);
++ widenOp = mkV128EXTHTU(insSz);
++ id = insSz + 4;
++ break;
++ }
++ default: vassert(0);
+ }
+
-+ const HChar *nm[4] = { "vandi.b", "vori.b", "vxori.b", "vnori.b" };
-+
-+ DIP("%s %s, %s, %u\n", nm[insTy], nameVReg(vd), nameVReg(vj), ui8);
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
-+
-+ putVReg(vd, mkexpr(res));
-+
++ assign(argL, unop(widenOp, binop(packOp, getVReg(vj), mkV128(0x0000))));
++ assign(argR, unop(widenOp, binop(packOp, getVReg(vk), mkV128(0x0000))));
++ DIP("%s.%s %s, %s, %s\n", nm, mkInsSize(id), nameVReg(vd),
++ nameVReg(vj), nameVReg(vk));
++ putVReg(vd, binop(mathOp, mkexpr(argL), mkexpr(argR)));
+ return True;
+}
+
-+static Bool gen_vbiti ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvaddw_xvsubw_x_x ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ UInt vd = SLICE(insn, 4, 0);
-+ UInt vj = SLICE(insn, 9, 5);
-+ UInt insImm = SLICE(insn, 17, 10);
-+ UInt insTy = SLICE(insn, 19, 18);
-+
-+ IRTemp c1 = newTemp(Ity_V128);
-+ IRTemp argR = newTemp(Ity_V128);
-+ IRTemp res = newTemp(Ity_V128);
-+ UInt insSz, uImm;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
+
-+ if ((insImm & 0xf8) == 0x8) { // 00001mmm; b
-+ uImm = insImm & 0x07;
-+ insSz = 0;
-+ } else if ((insImm & 0xf0) == 0x10) { // 0001mmmm; h
-+ uImm = insImm & 0x0f;
-+ insSz = 1;
-+ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; w
-+ uImm = insImm & 0x1f;
-+ insSz = 2;
-+ } else if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; d
-+ uImm = insImm & 0x3f;
-+ insSz = 3;
-+ } else {
-+ vassert(0);
-+ }
++ UInt id = insSz;
++ IROp mathOp = Iop_INVALID;
++ IROp packOp = Iop_INVALID;
++ IROp widenOp = Iop_INVALID;
++ IRTemp argL = newTemp(Ity_V256);
++ IRTemp argR = newTemp(Ity_V256);
++ const HChar *nm;
+
-+ switch (insSz) {
-+ case 0b00:
-+ assign(c1, unop(Iop_Dup8x16, mkU8(1)));
-+ break;
-+ case 0b01:
-+ assign(c1, unop(Iop_Dup16x8, mkU16(1)));
++ switch (SLICE(insn, 21, 17)) {
++ case 0b01111: {
++ nm = "xvaddwev";
++ packOp = mkV256PACKEV(insSz);
++ mathOp = mkV256ADD(insSz + 1);
++ widenOp = mkV256EXTHTS(insSz);
+ break;
-+ case 0b10:
-+ assign(c1, unop(Iop_Dup32x4, mkU32(1)));
++ }
++ case 0b10000: {
++ nm = "xvsubwev";
++ packOp = mkV256PACKEV(insSz);
++ mathOp = mkV256SUB(insSz + 1);
++ widenOp = mkV256EXTHTS(insSz);
+ break;
-+ case 0b11:
-+ assign(c1, binop(Iop_64HLtoV128, mkU64(1), mkU64(1)));
++ }
++ case 0b10001: {
++ nm = "xvaddwod";
++ packOp = mkV256PACKOD(insSz);
++ mathOp = mkV256ADD(insSz + 1);
++ widenOp = mkV256EXTHTS(insSz);
+ break;
-+ default:
-+ vassert(0);
++ }
++ case 0b10010: {
++ nm = "xvsubwod";
++ packOp = mkV256PACKOD(insSz);
++ mathOp = mkV256SUB(insSz + 1);
++ widenOp = mkV256EXTHTS(insSz);
+ break;
-+ }
-+
-+ assign(argR, binop(mkVecSHLN(insSz), mkexpr(c1), mkU8(uImm)));
-+ switch (insTy) {
-+ case 0b00:
-+ assign(res, binop(Iop_AndV128,
-+ getVReg(vj), unop(Iop_NotV128, mkexpr(argR))));
++ }
++ case 0b10111: {
++ nm ="xvaddwev";
++ packOp = mkV256PACKEV(insSz);
++ mathOp = mkV256ADD(insSz + 1);
++ widenOp = mkV256EXTHTU(insSz);
++ id = insSz + 4;
+ break;
-+ case 0b01:
-+ assign(res, binop(Iop_OrV128, getVReg(vj), mkexpr(argR)));
++ }
++ case 0b11000: {
++ nm = "xvsubwev";
++ packOp = mkV256PACKEV(insSz);
++ mathOp = mkV256SUB(insSz + 1);
++ widenOp = mkV256EXTHTU(insSz);
++ id = insSz + 4;
+ break;
-+ case 0b10:
-+ assign(res, binop(Iop_XorV128, getVReg(vj), mkexpr(argR)));
++ }
++ case 0b11001: {
++ nm = "xvaddwod";
++ packOp = mkV256PACKOD(insSz);
++ mathOp = mkV256ADD(insSz + 1);
++ widenOp = mkV256EXTHTU(insSz);
++ id = insSz + 4;
+ break;
-+ default:
-+ vassert(0);
++ }
++ case 0b11010: {
++ nm = "xvsubwod";
++ packOp = mkV256PACKOD(insSz);
++ mathOp = mkV256SUB(insSz + 1);
++ widenOp = mkV256EXTHTU(insSz);
++ id = insSz + 4;
+ break;
++ }
++ default: vassert(0);
+ }
+
-+ const HChar *nm[3] = { "vbitrevi", "vbitclri", "vbitseti" };
-+
-+ DIP("%s.%s %s, %u\n", nm[insTy], mkInsSize(insSz), nameVReg(vd), uImm);
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
++ assign(argL, unop(widenOp, binop(packOp, getXReg(xj), mkV256(0x0000))));
++ assign(argR, unop(widenOp, binop(packOp, getXReg(xk), mkV256(0x0000))));
++ DIP("%s.%s %s, %s, %s\n", nm, mkInsSize(id), nameXReg(xd),
++ nameXReg(xj), nameXReg(xk));
++ putXReg(xd, binop(mathOp, mkexpr(argL), mkexpr(argR)));
++ return True;
++}
+
-+ putVReg(vd, mkexpr(res));
++static Bool gen_vaddw_vsubw_x_x_x ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isOd = SLICE(insn, 22, 22);
+
++ IRTemp argL = newTemp(Ity_V128);
++ IRTemp argR = newTemp(Ity_V128);
++ IROp packOp = isOd ? mkV128PACKOD(insSz): mkV128PACKEV(insSz);
++
++ assign(argL, unop(mkV128EXTHTU(insSz), binop(packOp,
++ getVReg(vj), mkV128(0x0000))));
++ assign(argR, unop(mkV128EXTHTS(insSz), binop(packOp,
++ getVReg(vk), mkV128(0x0000))));
++ const HChar *nm[2] = { "vaddwev", "vaddwod" };
++ const HChar *ns[4] = { "h.bu.b", "w.hu.h", "d.wu.w", "q.du.d" };
++ DIP("%s.%s %s, %s, %s\n", nm[isOd], ns[insSz], nameVReg(vd),
++ nameVReg(vj), nameVReg(vk));
++ putVReg(vd, binop(mkV128ADD(insSz + 1), mkexpr(argL), mkexpr(argR)));
+ return True;
+}
+
++static Bool gen_xvaddw_xvsubw_x_x_x ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isOd = SLICE(insn, 22, 22);
+
-+/*------------------------------------------------------------*/
-+/*--- Helpers for vector string processing insns ---*/
-+/*------------------------------------------------------------*/
++ IRTemp argL = newTemp(Ity_V256);
++ IRTemp argR = newTemp(Ity_V256);
++ IROp packOp = isOd ? mkV256PACKOD(insSz): mkV256PACKEV(insSz);
++
++ assign(argL, unop(mkV256EXTHTU(insSz), binop(packOp,
++ getXReg(xj), mkV256(0x0000))));
++ assign(argR, unop(mkV256EXTHTS(insSz), binop(packOp,
++ getXReg(xk), mkV256(0x0000))));
++ const HChar *nm[2] = { "xvaddwev", "xvaddwod" };
++ const HChar *ns[4] = { "h.bu.b", "w.hu.h", "d.wu.w", "q.du.d" };
++ DIP("%s.%s %s, %s, %s\n", nm[isOd], ns[insSz], nameXReg(xd),
++ nameXReg(xj), nameXReg(xk));
++ putXReg(xd, binop(mkV256ADD(insSz + 1), mkexpr(argL), mkexpr(argR)));
++ return True;
++}
+
-+static Bool gen_vfrstpi ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vavg ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
+ UInt vd = SLICE(insn, 4, 0);
+ UInt vj = SLICE(insn, 9, 5);
-+ UInt ui5 = SLICE(insn, 14, 10);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isU = SLICE(insn, 17, 17);
++ UInt isR = SLICE(insn, 19, 19);
++
++ IRTemp srcL = newTemp(Ity_V128);
++ IRTemp srcR = newTemp(Ity_V128);
++ IRTemp res = newTemp(Ity_V128);
++ IROp avgOp = isU ? mkV128AVGU(insSz) : mkV128AVGS(insSz);
++ IROp shrOp = isU ? mkV128SHRN(insSz) : mkV128SARN(insSz);
++ UInt id = isU ? (insSz + 4) : insSz;
++ UInt shlNum[4] = { 7, 15, 31, 63 };
++
++ assign(srcL, getVReg(vj));
++ assign(srcR, getVReg(vk));
++
++ if (isR) {
++ assign(res, binop(avgOp, mkexpr(srcL), mkexpr(srcR)));
++ } else {
++ assign(res, binop(mkV128ADD(insSz),
++ binop(mkV128ADD(insSz),
++ binop(shrOp, mkexpr(srcL), mkU8(1)),
++ binop(shrOp, mkexpr(srcR), mkU8(1))),
++ binop(mkV128SHRN(insSz),
++ binop(mkV128SHLN(insSz),
++ binop(Iop_AndV128,
++ mkexpr(srcL),
++ mkexpr(srcR)),
++ mkU8(shlNum[insSz])),
++ mkU8(shlNum[insSz]))));
++ }
++
++ const HChar *nm[2] = { "vavg", "vavgr" };
++ DIP("%s.%s %s, %s, %s\n", nm[isR], mkInsSize(id),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++ putVReg(vd, mkexpr(res));
++ return True;
++}
++
++static Bool gen_xvavg ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
+ UInt insSz = SLICE(insn, 16, 15);
++ UInt isU = SLICE(insn, 17, 17);
++ UInt isR = SLICE(insn, 19, 19);
++
++ IRTemp srcL = newTemp(Ity_V256);
++ IRTemp srcR = newTemp(Ity_V256);
++ IRTemp res = newTemp(Ity_V256);
++ IROp avgOp = isU ? mkV256AVGU(insSz) : mkV256AVGS(insSz);
++ IROp shrOp = isU ? mkV256SHRN(insSz) : mkV256SARN(insSz);
++ UInt id = isU ? (insSz + 4) : insSz;
++ UInt shlNum[4] = { 7, 15, 31, 63 };
++
++ assign(srcL, getXReg(xj));
++ assign(srcR, getXReg(xk));
++
++ if (isR) {
++ assign(res, binop(avgOp, mkexpr(srcL), mkexpr(srcR)));
++ } else {
++ assign(res, binop(mkV256ADD(insSz),
++ binop(mkV256ADD(insSz),
++ binop(shrOp, mkexpr(srcL), mkU8(1)),
++ binop(shrOp, mkexpr(srcR), mkU8(1))),
++ binop(mkV256SHRN(insSz),
++ binop(mkV256SHLN(insSz),
++ binop(Iop_AndV256,
++ mkexpr(srcL),
++ mkexpr(srcR)),
++ mkU8(shlNum[insSz])),
++ mkU8(shlNum[insSz]))));
++ }
++
++ const HChar *nm[2] = { "xvavg", "xvavgr" };
++ DIP("%s.%s %s, %s, %s\n", nm[isR], mkInsSize(id),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, mkexpr(res));
++ return True;
++}
+
++static IRTemp gen_vabsd_b ( IRTemp sJ, IRTemp sK, UInt isU )
++{
+ UInt i;
-+ IRTemp data[2];
++ IRTemp argL[16];
++ IRTemp argR[16];
++ IRTemp arg[16];
+ IRTemp res = newTemp(Ity_V128);
++ IROp cmpOp = isU ? Iop_CmpLT64U: Iop_CmpLT64S;
+
-+ for (i = 0; i < 2; i++) {
-+ data[i] = newTemp(Ity_I64);
-+ assign(data[i], binop(Iop_GetElem64x2, getVReg(vj), mkU8(i)));
-+ }
-+
-+ IRExpr** arg = mkIRExprVec_3(mkU64(insSz), mkexpr(data[1]), mkexpr(data[0]));
-+ IRExpr* call = mkIRExprCCall(Ity_I64, 0/*regparms*/,
-+ "loongarch64_calculate_negative_id",
-+ &loongarch64_calculate_negative_id,
-+ arg);
++ for (i = 0; i < 16; i++) {
++ argL[i] = newTemp(Ity_I64);
++ argR[i] = newTemp(Ity_I64);
++ arg[i] = newTemp(Ity_I8);
++ if (isU) {
++ assign(argL[i], extendU(Ity_I8, binop(Iop_GetElem8x16, mkexpr(sJ), mkU8(i))));
++ assign(argR[i], extendU(Ity_I8, binop(Iop_GetElem8x16, mkexpr(sK), mkU8(i))));
++ } else {
++ assign(argL[i], extendS(Ity_I8, binop(Iop_GetElem8x16, mkexpr(sJ), mkU8(i))));
++ assign(argR[i], extendS(Ity_I8, binop(Iop_GetElem8x16, mkexpr(sK), mkU8(i))));
++ }
+
-+ switch (insSz) {
-+ case 0b00:
-+ assign(res, triop(Iop_SetElem8x16,
-+ getVReg(vd),
-+ mkU8(ui5 % 16),
-+ unop(Iop_64to8, call)));
-+ break;
-+ case 0b01:
-+ assign(res, triop(Iop_SetElem16x8,
-+ getVReg(vd),
-+ mkU8(ui5 % 8),
-+ unop(Iop_64to16, call)));
-+ break;
-+ default:
-+ return False;
++ assign(arg[i], IRExpr_ITE(binop(cmpOp, mkexpr(argR[i]), mkexpr(argL[i])),
++ unop(Iop_64to8, binop(Iop_Sub64,
++ mkexpr(argL[i]), mkexpr(argR[i]))),
++ unop(Iop_64to8, binop(Iop_Sub64,
++ mkexpr(argR[i]), mkexpr(argL[i])))));
+ }
+
-+ DIP("vfrstpi.%s %s, %s, %u\n", mkInsSize(insSz), nameVReg(vd), nameVReg(vj), ui5);
++ assign(res, mkV128from8s(arg[15], arg[14], arg[13], arg[12],
++ arg[11], arg[10], arg[9], arg[8],
++ arg[7], arg[6], arg[5], arg[4],
++ arg[3], arg[2], arg[1], arg[0]));
++ return res;
++}
+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
++static IRTemp gen_vabsd_h ( IRTemp sJ, IRTemp sK, UInt isU )
++{
++ UInt i;
++ IRTemp argL[8];
++ IRTemp argR[8];
++ IRTemp arg[8];
++ IRTemp res = newTemp(Ity_V128);
++ IROp cmpOp = isU ? Iop_CmpLT64U: Iop_CmpLT64S;
+
-+ putVReg(vd, mkexpr(res));
++ for (i = 0; i < 8; i++) {
++ argL[i] = newTemp(Ity_I64);
++ argR[i] = newTemp(Ity_I64);
++ arg[i] = newTemp(Ity_I16);
++ if (isU) {
++ assign(argL[i], extendU(Ity_I16, binop(Iop_GetElem16x8, mkexpr(sJ), mkU8(i))));
++ assign(argR[i], extendU(Ity_I16, binop(Iop_GetElem16x8, mkexpr(sK), mkU8(i))));
++ } else {
++ assign(argL[i], extendS(Ity_I16, binop(Iop_GetElem16x8, mkexpr(sJ), mkU8(i))));
++ assign(argR[i], extendS(Ity_I16, binop(Iop_GetElem16x8, mkexpr(sK), mkU8(i))));
++ }
++ assign(arg[i], IRExpr_ITE(binop(cmpOp, mkexpr(argR[i]), mkexpr(argL[i])),
++ unop(Iop_64to16, binop(Iop_Sub64,
++ mkexpr(argL[i]), mkexpr(argR[i]))),
++ unop(Iop_64to16, binop(Iop_Sub64,
++ mkexpr(argR[i]), mkexpr(argL[i])))));
++ }
+
-+ return True;
++ assign(res, mkV128from16s(arg[7], arg[6], arg[5], arg[4],
++ arg[3], arg[2], arg[1], arg[0]));
++ return res;
+}
+
++static IRTemp gen_vabsd_w ( IRTemp sJ, IRTemp sK, UInt isU )
++{
++ UInt i;
++ IRTemp argL[4];
++ IRTemp argR[4];
++ IRTemp arg[4];
++ IRTemp res = newTemp(Ity_V128);
++ IROp cmpOp = isU ? Iop_CmpLT64U: Iop_CmpLT64S;
+
-+/*------------------------------------------------------------*/
-+/*--- Helpers for vector comparison and selection insns ---*/
-+/*------------------------------------------------------------*/
++ for (i = 0; i < 4; i++) {
++ argL[i] = newTemp(Ity_I64);
++ argR[i] = newTemp(Ity_I64);
++ arg[i] = newTemp(Ity_I32);
++ if (isU) {
++ assign(argL[i], extendU(Ity_I32, binop(Iop_GetElem32x4, mkexpr(sJ), mkU8(i))));
++ assign(argR[i], extendU(Ity_I32, binop(Iop_GetElem32x4, mkexpr(sK), mkU8(i))));
++ } else {
++ assign(argL[i], extendS(Ity_I32, binop(Iop_GetElem32x4, mkexpr(sJ), mkU8(i))));
++ assign(argR[i], extendS(Ity_I32, binop(Iop_GetElem32x4, mkexpr(sK), mkU8(i))));
++ }
++ assign(arg[i], IRExpr_ITE(binop(cmpOp, mkexpr(argR[i]), mkexpr(argL[i])),
++ unop(Iop_64to32, binop(Iop_Sub64,
++ mkexpr(argL[i]), mkexpr(argR[i]))),
++ unop(Iop_64to32, binop(Iop_Sub64,
++ mkexpr(argR[i]), mkexpr(argL[i])))));
++ }
+
-+static IROp mkVecCMPEQ ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_CmpEQ8x16, Iop_CmpEQ16x8, Iop_CmpEQ32x4, Iop_CmpEQ64x2 };
-+ vassert(size < 4);
-+ return ops[size];
++ assign(res, mkV128from32s(arg[3], arg[2], arg[1], arg[0]));
++ return res;
+}
+
-+static IROp mkV256CMPEQ ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_CmpEQ8x32, Iop_CmpEQ16x16, Iop_CmpEQ32x8, Iop_CmpEQ64x4 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
++static IRTemp gen_vabsd_d ( IRTemp sJ, IRTemp sK, UInt isU )
++{
++ UInt i;
++ IRTemp argL[2];
++ IRTemp argR[2];
++ IRTemp arg[2];
++ IRTemp res = newTemp(Ity_V128);
++ IROp cmpOp = isU ? Iop_CmpLT64U: Iop_CmpLT64S;
+
-+static IROp mkVecCMPGTU ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_CmpGT8Ux16, Iop_CmpGT16Ux8, Iop_CmpGT32Ux4, Iop_CmpGT64Ux2 };
-+ vassert(size < 4);
-+ return ops[size];
++ for (i = 0; i < 2; i++) {
++ argL[i] = newTemp(Ity_I64);
++ argR[i] = newTemp(Ity_I64);
++ arg[i] = newTemp(Ity_I64);
++ assign(argL[i], binop(Iop_GetElem64x2, mkexpr(sJ), mkU8(i)));
++ assign(argR[i], binop(Iop_GetElem64x2, mkexpr(sK), mkU8(i)));
++ assign(arg[i], IRExpr_ITE(binop(cmpOp, mkexpr(argR[i]), mkexpr(argL[i])),
++ binop(Iop_Sub64, mkexpr(argL[i]), mkexpr(argR[i])),
++ binop(Iop_Sub64, mkexpr(argR[i]), mkexpr(argL[i]))));
++ }
++ assign(res, mkV128from64s(arg[1], arg[0]));
++
++ return res;
+}
+
-+static Bool gen_vcmp_integer ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vabsd ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
+ UInt vd = SLICE(insn, 4, 0);
+ UInt vj = SLICE(insn, 9, 5);
+ UInt vk = SLICE(insn, 14, 10);
+ UInt insSz = SLICE(insn, 16, 15);
-+ UInt insTy = SLICE(insn, 19, 17);
-+
-+ UInt szId = insSz;
-+ IRTemp res = newTemp(Ity_V128);
-+ IRTemp argL = newTemp(Ity_V128);
-+ IRTemp argR = newTemp(Ity_V128);
-+ assign(argL, getVReg(vj));
-+ assign(argR, getVReg(vk));
-+
-+ switch (insTy) {
-+ case 0b000:
-+ assign(res, binop(mkVecCMPEQ(insSz), mkexpr(argL), mkexpr(argR)));
-+ break;
-+ case 0b001:
-+ assign(res, binop(Iop_OrV128,
-+ binop(mkVecCMPGTS(insSz), mkexpr(argR), mkexpr(argL)),
-+ binop(mkVecCMPEQ(insSz), mkexpr(argL), mkexpr(argR))));
-+ break;
-+ case 0b010:
-+ assign(res, binop(Iop_OrV128,
-+ binop(mkVecCMPGTU(insSz), mkexpr(argR), mkexpr(argL)),
-+ binop(mkVecCMPEQ(insSz), mkexpr(argL), mkexpr(argR))));
-+ szId = insSz + 4;
-+ break;
-+ case 0b011:
-+ assign(res, binop(mkVecCMPGTS(insSz), mkexpr(argR), mkexpr(argL)));
-+ break;
-+ case 0b100:
-+ assign(res, binop(mkVecCMPGTU(insSz), mkexpr(argR), mkexpr(argL)));
-+ szId = insSz + 4;
-+ break;
-+ default:
-+ return False;
-+ }
++ UInt isU = SLICE(insn, 17, 17);
+
-+ const HChar *nm[5] = { "vseq", "vsle", "vsle", "vslt", "vslt" };
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp sK = newTemp(Ity_V128);
+
-+ DIP("%s.%s %s, %s, %s\n", nm[insTy], mkInsSize(szId),
-+ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++ assign(sJ, getVReg(vj));
++ assign(sK, getVReg(vk));
+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
++ switch (insSz) {
++ case 0b00:
++ res = gen_vabsd_b(sJ, sK, isU); break;
++ case 0b01:
++ res = gen_vabsd_h(sJ, sK, isU); break;
++ case 0b10:
++ res = gen_vabsd_w(sJ, sK, isU); break;
++ case 0b11:
++ res = gen_vabsd_d(sJ, sK, isU); break;
++ default: vassert(0);
+ }
+
++ DIP("vabsd.%s %s, %s, %s\n", mkInsSize(insSz),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
+ putVReg(vd, mkexpr(res));
-+
+ return True;
+}
+
-+static Bool gen_vcmpi_integer ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvabsd ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ UInt vd = SLICE(insn, 4, 0);
-+ UInt vj = SLICE(insn, 9, 5);
-+ UInt si5 = SLICE(insn, 14, 10);
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
+ UInt insSz = SLICE(insn, 16, 15);
-+ UInt isS = SLICE(insn, 17, 17);
-+ UInt insTy = SLICE(insn, 19, 17);
-+
-+ UInt szId = insSz;
-+ IRTemp res = newTemp(Ity_V128);
-+ IRTemp argL = newTemp(Ity_V128);
-+ IRTemp argR = newTemp(Ity_V128);
-+ assign(argL, getVReg(vj));
++ UInt isU = SLICE(insn, 17, 17);
+
-+ IRExpr *si5Expr;
-+ IRTemp s64 = newTemp(Ity_I64);
-+ assign(s64, mkU64(extend64(si5, 5)));
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sK = newTemp(Ity_V256);
++ IRTemp jHi = IRTemp_INVALID;
++ IRTemp jLo = IRTemp_INVALID;
++ IRTemp kHi = IRTemp_INVALID;
++ IRTemp kLo = IRTemp_INVALID;
+
-+ if (insTy == 0b000)
-+ isS = 1;
++ assign(sJ, getXReg(xj));
++ assign(sK, getXReg(xk));
++ breakupV256toV128s(sJ, &jHi, &jLo);
++ breakupV256toV128s(sK, &kHi, &kLo);
+
+ switch (insSz) {
+ case 0b00:
-+ si5Expr = isS ? unop(Iop_64to8, mkexpr(s64)) : mkU8(si5);
-+ assign(argR, unop(Iop_Dup8x16, si5Expr));
++ rHi = gen_vabsd_b(jHi, kHi, isU);
++ rLo = gen_vabsd_b(jLo, kLo, isU);
+ break;
+ case 0b01:
-+ si5Expr = isS ? unop(Iop_64to16, mkexpr(s64)) : mkU16(si5);
-+ assign(argR, unop(Iop_Dup16x8, si5Expr));
++ rHi = gen_vabsd_h(jHi, kHi, isU);
++ rLo = gen_vabsd_h(jLo, kLo, isU);
+ break;
+ case 0b10:
-+ si5Expr = isS ? unop(Iop_64to32, mkexpr(s64)) : mkU32(si5);
-+ assign(argR, unop(Iop_Dup32x4, si5Expr));
++ rHi = gen_vabsd_w(jHi, kHi, isU);
++ rLo = gen_vabsd_w(jLo, kLo, isU);
+ break;
+ case 0b11:
-+ si5Expr = isS ? mkexpr(s64) : mkU64(si5);
-+ assign(argR, binop(Iop_64HLtoV128, si5Expr, si5Expr));
-+ break;
-+ default:
-+ vassert(0);
++ rHi = gen_vabsd_d(jHi, kHi, isU);
++ rLo = gen_vabsd_d(jLo, kLo, isU);
+ break;
++ default: vassert(0);
+ }
+
-+ switch (insTy) {
-+ case 0b000:
-+ assign(res, binop(mkVecCMPEQ(insSz), mkexpr(argL), mkexpr(argR)));
-+ break;
-+ case 0b001:
-+ assign(res, binop(Iop_OrV128,
-+ binop(mkVecCMPGTS(insSz), mkexpr(argR), mkexpr(argL)),
-+ binop(mkVecCMPEQ(insSz), mkexpr(argL), mkexpr(argR))));
-+ break;
-+ case 0b010:
-+ assign(res, binop(Iop_OrV128,
-+ binop(mkVecCMPGTU(insSz), mkexpr(argR), mkexpr(argL)),
-+ binop(mkVecCMPEQ(insSz), mkexpr(argL), mkexpr(argR))));
-+ szId = insSz + 4;
-+ break;
-+ case 0b011:
-+ assign(res, binop(mkVecCMPGTS(insSz), mkexpr(argR), mkexpr(argL)));
-+ break;
-+ case 0b100:
-+ assign(res, binop(mkVecCMPGTU(insSz), mkexpr(argR), mkexpr(argL)));
-+ szId = insSz + 4;
-+ break;
-+ default:
-+ vassert(0);
-+ break;
-+ }
++ DIP("xvabsd.%s %s, %s, %s\n", mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, mkV256from128s(rHi, rLo));
++ return True;
++}
+
-+ const HChar *nm[10] = { "vseqi", "vslei", "vslei", "vslti", "vslti" };
++static Bool gen_vadda ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
+
-+ DIP("%s.%s %s, %s, %d\n", nm[insTy], mkInsSize(szId), nameVReg(vd),
-+ nameVReg(vj), (Int)extend32(si5, 5));
++ DIP("vadda.%s %s, %s, %s\n", mkInsSize(insSz), nameVReg(vd),
++ nameVReg(vj), nameVReg(vk));
++ putVReg(vd, binop(mkV128ADD(insSz),
++ unop(mkV128ABS(insSz), getVReg(vj)),
++ unop(mkV128ABS(insSz), getVReg(vk))));
++ return True;
++}
++
++static Bool gen_xvadda ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++
++ DIP("xvadda.%s %s, %s, %s\n", mkInsSize(insSz), nameXReg(xd),
++ nameXReg(xj), nameXReg(xk));
++ putXReg(xd, binop(mkV256ADD(insSz),
++ unop(mkV256ABS(insSz), getXReg(xj)),
++ unop(mkV256ABS(insSz), getXReg(xk))));
++ return True;
++}
++
++static Bool gen_vmax_vmin ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isMin = SLICE(insn, 17, 17);
++ UInt isU = SLICE(insn, 18, 18);
++
++ IROp op = isMin ? isU ? mkV128MINU(insSz) : mkV128MINS(insSz) :
++ isU ? mkV128MAXU(insSz) : mkV128MAXS(insSz);
++ UInt id = isU ? (insSz + 4) : insSz;
++ const HChar *nm[2] = { "vmax", "vmin" };
++
++ DIP("%s.%s %s, %s, %s\n", nm[isMin], mkInsSize(id),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
+
+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
+ dres->jk_StopHere = Ijk_SigILL;
@@ -11210,39 +11302,28 @@ index 0000000..50c24f1
+ return True;
+ }
+
-+ putVReg(vd, mkexpr(res));
++ putVReg(vd, binop(op, getVReg(vj), getVReg(vk)));
+
+ return True;
+}
+
-+static Bool gen_xvcmp_integer ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvmax_xvmin ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
+ UInt xd = SLICE(insn, 4, 0);
+ UInt xj = SLICE(insn, 9, 5);
+ UInt xk = SLICE(insn, 14, 10);
+ UInt insSz = SLICE(insn, 16, 15);
-+ UInt insTy = SLICE(insn, 19, 17);
-+
-+ UInt szId = insSz;
-+ IRTemp res = newTemp(Ity_V256);
-+ IRTemp argL = newTemp(Ity_V256);
-+ IRTemp argR = newTemp(Ity_V256);
-+ assign(argL, getXReg(xj));
-+ assign(argR, getXReg(xk));
-+
-+ switch (insTy) {
-+ case 0b000:
-+ assign(res, binop(mkV256CMPEQ(insSz), mkexpr(argL), mkexpr(argR)));
-+ break;
-+ default:
-+ return False;
-+ }
++ UInt isMin = SLICE(insn, 17, 17);
++ UInt isU = SLICE(insn, 18, 18);
+
-+ const HChar *nm[5] = { "xvseq", "xvsle", "xvsle", "xvslt", "xvslt" };
++ IROp op = isMin ? isU ? mkV256MINU(insSz) : mkV256MINS(insSz) :
++ isU ? mkV256MAXU(insSz) : mkV256MAXS(insSz);
++ UInt id = isU ? (insSz + 4) : insSz;
++ const HChar *nm[2] = { "xvmax", "xvmin" };
+
-+ DIP("%s.%s %s, %s, %s\n", nm[insTy], mkInsSize(szId),
++ DIP("%s.%s %s, %s, %s\n", nm[isMin], mkInsSize(id),
+ nameXReg(xd), nameXReg(xj), nameXReg(xk));
+
+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
@@ -11251,10295 +11332,14338 @@ index 0000000..50c24f1
+ return True;
+ }
+
-+ putXReg(xd, mkexpr(res));
++ putXReg(xd, binop(op, getXReg(xj), getXReg(xk)));
+
+ return True;
+}
+
-+static Bool gen_vset ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vmaxi_vmini ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ UInt cd = SLICE(insn, 2, 0);
++ UInt vd = SLICE(insn, 4, 0);
+ UInt vj = SLICE(insn, 9, 5);
-+ UInt insSz = SLICE(insn, 11, 10);
-+ UInt insTy = SLICE(insn, 13, 12);
++ UInt si5 = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isMin = SLICE(insn, 17, 17);
++ UInt isU = SLICE(insn, 18, 18);
+
-+ IROp ops64;
-+ IRTemp resHi = newTemp(Ity_I64);
-+ IRTemp resLo = newTemp(Ity_I64);
-+ IRTemp res = newTemp(Ity_V128);
-+ IRTemp eq = newTemp(Ity_V128);
-+ IRTemp z128 = newTemp(Ity_V128);
-+ assign(z128, mkV128(0x0000));
++ IRExpr *si5Expr;
++ IRTemp argR = newTemp(Ity_V128);
++ IRTemp s64 = newTemp(Ity_I64);
++ IROp op = isMin ? isU ? mkV128MINU(insSz) : mkV128MINS(insSz) :
++ isU ? mkV128MAXU(insSz) : mkV128MAXS(insSz);
+
-+ switch (insTy) {
++ assign(s64, mkU64(extend64(si5, 5)));
++ switch (insSz) {
++ case 0b00: {
++ si5Expr = isU ? mkU8(si5) : unop(Iop_64to8, mkexpr(s64));
++ assign(argR, unop(Iop_Dup8x16, si5Expr));
++ break;
++ }
+ case 0b01: {
-+ if (SLICE(insn, 10, 10) == 0b0) {
-+ DIP("vseteqz.v %u, %s", cd, nameVReg(vj));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
-+
-+ assign(res, binop(Iop_CmpEQ64x2, getVReg(vj), mkexpr(z128)));
-+ ops64 = Iop_And64;
-+ } else {
-+ DIP("vsetnez.v %u, %s", cd, nameVReg(vj));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
-+
-+ assign(res, unop(Iop_NotV128,
-+ binop(Iop_CmpEQ64x2, getVReg(vj), mkexpr(z128))));
-+ ops64 = Iop_Or64;
-+ }
++ si5Expr = isU ? mkU16(si5) : unop(Iop_64to16, mkexpr(s64));
++ assign(argR, unop(Iop_Dup16x8, si5Expr));
+ break;
+ }
-+
+ case 0b10: {
-+ DIP("vsetanyeqz.%s %u, %s", mkInsSize(insSz), cd, nameVReg(vj));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
-+
-+ assign(eq, binop(mkVecCMPEQ(insSz), getVReg(vj), mkexpr(z128)));
-+ assign(res, unop(Iop_NotV128,
-+ binop(Iop_CmpEQ64x2, mkexpr(eq), mkexpr(z128))));
-+ ops64 = Iop_Or64;
++ si5Expr = isU ? mkU32(si5) : unop(Iop_64to32, mkexpr(s64));
++ assign(argR, unop(Iop_Dup32x4, si5Expr));
+ break;
+ }
-+
+ case 0b11: {
-+ DIP("vsetqllnez.%s %u, %s", mkInsSize(insSz), cd, nameVReg(vj));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
-+
-+ assign(eq, binop(mkVecCMPEQ(insSz), getVReg(vj), mkexpr(z128)));
-+ assign(res, binop(Iop_CmpEQ64x2, mkexpr(eq), mkexpr(z128)));
-+ ops64 = Iop_And64;
++ si5Expr = isU ? mkU64(si5) : mkexpr(s64);
++ assign(argR, binop(Iop_64HLtoV128, si5Expr, si5Expr));
+ break;
+ }
-+
-+ default:
-+ return False;
++ default: vassert(0);
+ }
+
-+ assign(resHi, binop(Iop_GetElem64x2, mkexpr(res), mkU8(1)));
-+ assign(resLo, binop(Iop_GetElem64x2, mkexpr(res), mkU8(0)));
-+ putFCC(cd, unop(Iop_64to8, binop(ops64, mkexpr(resHi), mkexpr(resLo))));
-+
++ UInt id = isU ? (insSz + 4) : insSz;
++ const HChar *nm[2] = { "vmaxi", "vmini" };
++ DIP("%s.%s %s, %s, %d\n", nm[isMin], mkInsSize(id), nameVReg(vd),
++ nameVReg(vj), (Int)extend32(si5, 5));
++ putVReg(vd, binop(op, getVReg(vj), mkexpr(argR)));
+ return True;
+}
+
-+static Bool gen_xvset ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvmaxi_xvmini ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ UInt cd = SLICE(insn, 2, 0);
++ UInt xd = SLICE(insn, 4, 0);
+ UInt xj = SLICE(insn, 9, 5);
-+ UInt insSz = SLICE(insn, 11, 10);
-+ UInt insTy = SLICE(insn, 13, 12);
++ UInt si5 = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isMin = SLICE(insn, 17, 17);
++ UInt isU = SLICE(insn, 18, 18);
+
-+ IROp ops64 = Iop_INVALID;
-+ IRTemp res = newTemp(Ity_V256);
-+ IRTemp z128 = newTemp(Ity_V128);
-+ IRTemp src = newTemp(Ity_V256);
-+ assign(z128, mkV128(0x0000));
-+ assign(src, getXReg(xj));
++ IRExpr *si5Expr;
++ IRTemp dup = newTemp(Ity_V128);
++ IRTemp s64 = newTemp(Ity_I64);
++ IROp op = isMin ? isU ? mkV256MINU(insSz) : mkV256MINS(insSz) :
++ isU ? mkV256MAXU(insSz) : mkV256MAXS(insSz);
+
-+ switch (insTy) {
++ assign(s64, mkU64(extend64(si5, 5)));
++ switch (insSz) {
++ case 0b00: {
++ si5Expr = isU ? mkU8(si5) : unop(Iop_64to8, mkexpr(s64));
++ assign(dup, unop(Iop_Dup8x16, si5Expr));
++ break;
++ }
+ case 0b01: {
-+ if (SLICE(insn, 10, 10) == 0b0) {
-+ DIP("xvseteqz.v %u, %s", cd, nameXReg(xj));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
-+
-+ IRTemp hi, lo;
-+ hi = lo = IRTemp_INVALID;
-+ breakupV256toV128s(src, &hi, &lo);
-+ assign(res, binop(Iop_V128HLtoV256,
-+ binop(Iop_CmpEQ64x2, mkexpr(hi), mkexpr(z128)),
-+ binop(Iop_CmpEQ64x2, mkexpr(hi), mkexpr(z128))));
-+ ops64 = Iop_And64;
-+ } else {
-+ return False;
-+ }
++ si5Expr = isU ? mkU16(si5) : unop(Iop_64to16, mkexpr(s64));
++ assign(dup, unop(Iop_Dup16x8, si5Expr));
+ break;
+ }
-+
+ case 0b10: {
-+ DIP("xvsetanyeqz.%s %u, %s", mkInsSize(insSz), cd, nameXReg(xj));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
-+
-+ IRTemp eqHi = newTemp(Ity_V128);
-+ IRTemp eqLo = newTemp(Ity_V128);
-+ IRTemp hi, lo;
-+ hi = lo = IRTemp_INVALID;
-+ breakupV256toV128s(src, &hi, &lo);
-+ assign(eqHi, binop(mkVecCMPEQ(insSz), mkexpr(hi), mkexpr(z128)));
-+ assign(eqLo, binop(mkVecCMPEQ(insSz), mkexpr(lo), mkexpr(z128)));
-+ assign(res, binop(Iop_V128HLtoV256,
-+ unop(Iop_NotV128,
-+ binop(Iop_CmpEQ64x2, mkexpr(eqHi), mkexpr(z128))),
-+ unop(Iop_NotV128,
-+ binop(Iop_CmpEQ64x2, mkexpr(eqLo), mkexpr(z128)))));
-+ ops64 = Iop_Or64;
++ si5Expr = isU ? mkU32(si5) : unop(Iop_64to32, mkexpr(s64));
++ assign(dup, unop(Iop_Dup32x4, si5Expr));
+ break;
+ }
-+
-+ default:
-+ return False;
++ case 0b11: {
++ si5Expr = isU ? mkU64(si5) : mkexpr(s64);
++ assign(dup, binop(Iop_64HLtoV128, si5Expr, si5Expr));
++ break;
++ }
++ default: vassert(0);
+ }
+
-+ IRTemp r1, r2, r3, r4;
-+ r1 = r2 = r3 = r4 = IRTemp_INVALID;
-+ breakupV256to64s(res, &r1, &r2, &r3, &r4);
-+ putFCC(cd, unop(Iop_64to8, binop(ops64,
-+ binop(ops64, mkexpr(r1), mkexpr(r2)),
-+ binop(ops64, mkexpr(r3), mkexpr(r4)))));
-+
++ UInt id = isU ? (insSz + 4) : insSz;
++ const HChar *nm[2] = { "xvmaxi", "xvmini" };
++ DIP("%s.%s %s, %s, %d\n", nm[isMin], mkInsSize(id), nameXReg(xd),
++ nameXReg(xj), (Int)extend32(si5, 5));
++ putXReg(xd, binop(op, getXReg(xj), mkV256from128s(dup, dup)));
+ return True;
+}
+
-+/*------------------------------------------------------------*/
-+/*--- Helpers for vector moving and shuffling insns ---*/
-+/*------------------------------------------------------------*/
++static Bool gen_vmu ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
+
-+static IROp mkVecPACKOD ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_PackOddLanes8x16, Iop_PackOddLanes16x8,
-+ Iop_PackOddLanes32x4, Iop_InterleaveHI64x2 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp argL = newTemp(Ity_V128);
++ IRTemp argR = newTemp(Ity_V128);
++ assign(argL, getVReg(vj));
++ assign(argR, getVReg(vk));
+
-+static IROp mkVecPACKEV ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_PackEvenLanes8x16, Iop_PackEvenLanes16x8,
-+ Iop_PackEvenLanes32x4, Iop_InterleaveLO64x2 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
++ switch (SLICE(insn, 18, 17)) {
++ case 0b10: {
++ DIP("vmul.%s %s, %s, %s\n", mkInsSize(insSz),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
+
-+static IROp mkVecINTERLEAVELO ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_InterleaveLO8x16, Iop_InterleaveLO16x8,
-+ Iop_InterleaveLO32x4, Iop_InterleaveLO64x2 };
-+ vassert(size < 4);
-+ return ops[size];
-+}
++ if (insSz != 0b11) {
++ assign(res, binop(mkV128MUL(insSz), EX(argL), EX(argR)));
++ } else {
++ assign(res, VMUD(EX(argL), EX(argR), Iop_MullS64, Iop_128to64));
++ }
++ break;
++ }
++ case 0b11: {
++ DIP("vmuh.%s %s, %s, %s\n", mkInsSize(insSz),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
+
-+static IROp mkVecINTERLEAVEHI ( UInt size ) {
-+ const IROp ops[4]
-+ = { Iop_InterleaveHI8x16, Iop_InterleaveHI16x8,
-+ Iop_InterleaveHI32x4, Iop_InterleaveHI64x2 };
-+ vassert(size < 4);
-+ return ops[size];
++ if (insSz != 0b11) {
++ assign(res, binop(mkV128MUHS(insSz), EX(argL), EX(argR)));
++ } else {
++ assign(res, VMUD(EX(argL), EX(argR), Iop_MullS64, Iop_128HIto64));
++ }
++ break;
++ }
++ case 0b00: {
++ DIP("vmuh.%s %s, %s, %s\n", mkInsSize(insSz + 4),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++
++ if (insSz != 0b11) {
++ assign(res, binop(mkV128MUHU(insSz), EX(argL), EX(argR)));
++ } else {
++ assign(res, VMUD(EX(argL), EX(argR), Iop_MullU64, Iop_128HIto64));
++ }
++ break;
++ }
++ default: vassert(0);
++ }
++
++ putVReg(vd, mkexpr(res));
++ return True;
+}
+
-+static Bool gen_vpickve2gr ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvmu ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ UInt rd = SLICE(insn, 4, 0);
-+ UInt vj = SLICE(insn, 9, 5);
-+ UInt insImm = SLICE(insn, 15, 10);
-+ UInt isS = SLICE(insn, 18, 18);
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
+
-+ UInt uImm, insSz;
-+ IRExpr *immExpr;
-+ IRType extTy = Ity_INVALID;
-+ IRTemp res = newTemp(Ity_I64);
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sK = newTemp(Ity_V256);
++ IRTemp jHi = IRTemp_INVALID;
++ IRTemp jLo = IRTemp_INVALID;
++ IRTemp kHi = IRTemp_INVALID;
++ IRTemp kLo = IRTemp_INVALID;
+
-+ if ((insImm & 0x30) == 0x20) { // 10mmmm; b
-+ uImm = insImm & 0xf;
-+ insSz = 0;
-+ extTy = Ity_I8;
-+ } else if ((insImm & 0x38) == 0x30) { // 110mmm; h
-+ uImm = insImm & 0x7;
-+ insSz = 1;
-+ extTy = Ity_I16;
-+ } else if ((insImm & 0x3c) == 0x38) { // 1110mm; w
-+ uImm = insImm & 0x3;
-+ insSz = 2;
-+ extTy = Ity_I32;
-+ } else if ((insImm & 0x3e) == 0x3c) { // 11110m; d
-+ uImm = insImm & 0x1;
-+ insSz = 3;
-+ } else {
-+ vassert(0);
-+ }
++ assign(sJ, getXReg(xj));
++ assign(sK, getXReg(xk));
++ breakupV256toV128s(sJ, &jHi, &jLo);
++ breakupV256toV128s(sK, &kHi, &kLo);
+
-+ immExpr = binop(mkVecGetElem(insSz), getVReg(vj), mkU8(uImm));
-+ if (insSz != 3)
-+ assign(res, isS ? extendS(extTy, immExpr) :
-+ extendU(extTy, immExpr));
-+ else
-+ assign(res, binop(Iop_Or64, mkU64(0), immExpr));
++ switch (SLICE(insn, 18, 17)) {
++ case 0b10: {
++ DIP("xvmul.%s %s, %s, %s\n", mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
+
-+ UInt nmId = isS ? insSz : (insSz + 4);
++ if (insSz != 0b11) {
++ assign(res, binop(mkV256MUL(insSz), EX(sJ), EX(sK)));
++ } else {
++ assign(rHi, VMUD(EX(jHi), EX(kHi), Iop_MullS64, Iop_128to64));
++ assign(rLo, VMUD(EX(jLo), EX(kLo), Iop_MullS64, Iop_128to64));
++ assign(res, mkV256from128s(rHi, rLo));
++ }
++ break;
++ }
++ case 0b11: {
++ DIP("vmuh.%s %s, %s, %s\n", mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
+
-+ DIP("vpickve2gr.%s %s, %s", mkInsSize(nmId),
-+ nameIReg(rd), nameVReg(vj));
++ if (insSz != 0b11) {
++ assign(res, binop(mkV256MUHS(insSz), EX(sJ), EX(sK)));
++ } else {
++ assign(rHi, VMUD(EX(jHi), EX(kHi), Iop_MullS64, Iop_128HIto64));
++ assign(rLo, VMUD(EX(jLo), EX(kLo), Iop_MullS64, Iop_128HIto64));
++ assign(res, mkV256from128s(rHi, rLo));
++ }
++ break;
++ }
++ case 0b00: {
++ DIP("vmuh.%s %s, %s, %s\n", mkInsSize(insSz + 4),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
++ if (insSz != 0b11) {
++ assign(res, binop(mkV256MUHU(insSz), EX(sJ), EX(sK)));
++ } else {
++ assign(rHi, VMUD(EX(jHi), EX(kHi), Iop_MullU64, Iop_128HIto64));
++ assign(rLo, VMUD(EX(jLo), EX(kLo), Iop_MullU64, Iop_128HIto64));
++ assign(res, mkV256from128s(rHi, rLo));
++ }
++ break;
++ }
++ default: vassert(0);
+ }
+
-+ putIReg(rd, mkexpr(res));
-+
++ putXReg(xd, mkexpr(res));
+ return True;
+}
+
-+static Bool gen_vreplgr2vr ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static IRTemp gen_vmulw_d ( IRTemp argL, IRTemp argR, IROp mathOp )
++{
++ IRTemp tI128 = newTemp(Ity_I128);
++ IRTemp res = newTemp(Ity_V128);
++
++ assign(tI128, binop(mathOp,
++ unop(Iop_V128HIto64, EX(argL)),
++ unop(Iop_V128HIto64, EX(argR)))),
++ assign(res, binop(Iop_64HLtoV128,
++ unop(Iop_128HIto64, EX(tI128)),
++ unop(Iop_128to64, EX(tI128))));
++ return res;
++}
++
++static Bool gen_vmulw ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
+ UInt vd = SLICE(insn, 4, 0);
-+ UInt rj = SLICE(insn, 9, 5);
-+ UInt insSz = SLICE(insn, 11, 10);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isOd = SLICE(insn, 17, 17);
++ UInt isU = SLICE(insn, 19, 19);
++
++ IRTemp wJ = newTemp(Ity_V128);
++ IRTemp wK = newTemp(Ity_V128);
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp z128 = newTemp(Ity_V128);
++ IROp mathOp = Iop_INVALID;
++ IROp widenOp = isU ? mkV128EXTHTU(insSz) : mkV128EXTHTS(insSz);
++ IROp packOp = isOd ? mkV128PACKOD(insSz) : mkV128PACKEV(insSz);
++ assign(z128, mkV128(0x0000));
+
-+ IRTemp res = newTemp(Ity_V128);
+ switch (insSz) {
+ case 0b00:
-+ assign(res, unop(Iop_Dup8x16, getIReg8(rj)));
-+ break;
-+ case 0b01:
-+ assign(res, unop(Iop_Dup16x8, getIReg16(rj)));
-+ break;
-+ case 0b10:
-+ assign(res, unop(Iop_Dup32x4, getIReg32(rj)));
++ case 0b01: {
++ mathOp = mkV128MUL(insSz + 1);
++ assign(wJ, unop(widenOp, binop(packOp, getVReg(vj), EX(z128))));
++ assign(wK, unop(widenOp, binop(packOp, getVReg(vk), EX(z128))));
++ assign(res, binop(mathOp, EX(wJ), EX(wK)));
+ break;
-+ case 0b11:
-+ assign(res, binop(Iop_64HLtoV128, getIReg64(rj), getIReg64(rj)));
++ }
++ case 0b10: {
++ mathOp = isU ? Iop_MullU64 : Iop_MullS64;
++ assign(wJ, unop(widenOp, binop(packOp, getVReg(vj), EX(z128))));
++ assign(wK, unop(widenOp, binop(packOp, getVReg(vk), EX(z128))));
++ assign(res, VMUD(EX(wJ), EX(wK), mathOp, Iop_128to64));
+ break;
-+ default:
-+ vassert(0);
++ }
++ case 0b11: {
++ mathOp = isU ? Iop_MullU64 : Iop_MullS64;
++ assign(wJ, binop(packOp, getVReg(vj), EX(z128)));
++ assign(wK, binop(packOp, getVReg(vk), EX(z128)));
++ res = gen_vmulw_d(wJ, wK, mathOp);
+ break;
++ }
++ default: vassert(0);
+ }
+
-+ DIP("vreplgr2vr.%s %s, %s", mkInsSize(insSz),
-+ nameVReg(vd), nameIReg(rj));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
-+
++ UInt id = isU ? (insSz + 4) : insSz;
++ const HChar *nm[2] = { "vmulwev", "vmulwod" };
++ DIP("%s.%s %s, %s, %s\n", nm[isOd], mkInsSize(id),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
+ putVReg(vd, mkexpr(res));
-+
+ return True;
+}
+
-+static Bool gen_xvreplgr2vr ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvmulw ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
+ UInt xd = SLICE(insn, 4, 0);
-+ UInt rj = SLICE(insn, 9, 5);
-+ UInt insSz = SLICE(insn, 11, 10);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isOd = SLICE(insn, 17, 17);
++ UInt isU = SLICE(insn, 19, 19);
++
++ IRTemp wJ = newTemp(Ity_V256);
++ IRTemp wK = newTemp(Ity_V256);
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp z256 = newTemp(Ity_V256);
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp jHi = IRTemp_INVALID;
++ IRTemp jLo = IRTemp_INVALID;
++ IRTemp kHi = IRTemp_INVALID;
++ IRTemp kLo = IRTemp_INVALID;
++ IROp mathOp = Iop_INVALID;
++ IROp widenOp = isU ? mkV256EXTHTU(insSz) : mkV256EXTHTS(insSz);
++ IROp packOp = isOd ? mkV256PACKOD(insSz) : mkV256PACKEV(insSz);
++ assign(z256, mkV256(0x0000));
+
-+ IRTemp res = newTemp(Ity_V128);
+ switch (insSz) {
-+ case 0b00:
-+ assign(res, unop(Iop_Dup8x16, getIReg8(rj)));
-+ break;
-+ case 0b01:
-+ assign(res, unop(Iop_Dup16x8, getIReg16(rj)));
-+ break;
-+ case 0b10:
-+ assign(res, unop(Iop_Dup32x4, getIReg32(rj)));
++ case 0b00: case 0b01: {
++ mathOp = mkV256MUL(insSz + 1);
++ assign(wJ, unop(widenOp, binop(packOp, getXReg(xj), EX(z256))));
++ assign(wK, unop(widenOp, binop(packOp, getXReg(xk), EX(z256))));
++ assign(res, binop(mathOp, EX(wJ), EX(wK)));
+ break;
-+ case 0b11:
-+ assign(res, binop(Iop_64HLtoV128, getIReg64(rj), getIReg64(rj)));
++ }
++ case 0b10: {
++ mathOp = isU ? Iop_MullU64 : Iop_MullS64;
++ assign(wJ, unop(widenOp, binop(packOp, getXReg(xj), EX(z256))));
++ assign(wK, unop(widenOp, binop(packOp, getXReg(xk), EX(z256))));
++ breakupV256toV128s(wJ, &jHi, &jLo);
++ breakupV256toV128s(wK, &kHi, &kLo);
++ assign(rHi, VMUD(EX(jHi), EX(kHi), mathOp, Iop_128to64));
++ assign(rLo, VMUD(EX(jLo), EX(kLo), mathOp, Iop_128to64));
++ assign(res, mkV256from128s(rHi, rLo));
+ break;
-+ default:
-+ vassert(0);
++ }
++ case 0b11: {
++ mathOp = isU ? Iop_MullU64 : Iop_MullS64;
++ assign(wJ, binop(packOp, getXReg(xj), EX(z256)));
++ assign(wK, binop(packOp, getXReg(xk), EX(z256)));
++ breakupV256toV128s(wJ, &jHi, &jLo);
++ breakupV256toV128s(wK, &kHi, &kLo);
++ rHi = gen_vmulw_d(jHi, kHi, mathOp);
++ rLo = gen_vmulw_d(jLo, kLo, mathOp);
++ assign(res, mkV256from128s(rHi, rLo));
+ break;
++ }
++ default: vassert(0);
+ }
+
-+ DIP("xvreplgr2vr.%s %s, %s", mkInsSize(insSz),
-+ nameXReg(xd), nameIReg(rj));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
-+
-+ putXReg(xd, binop(Iop_V128HLtoV256, mkexpr(res), mkexpr(res)));
-+
++ UInt id = isU ? (insSz + 4) : insSz;
++ const HChar *nm[2] = { "xvmulwev", "xvmulwod" };
++ DIP("%s.%s %s, %s, %s\n", nm[isOd], mkInsSize(id),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, mkexpr(res));
+ return True;
+}
+
-+static Bool gen_vreplve ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vmulw_x_x_x ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
+ UInt vd = SLICE(insn, 4, 0);
+ UInt vj = SLICE(insn, 9, 5);
-+ UInt rk = SLICE(insn, 14, 10);
++ UInt vk = SLICE(insn, 14, 10);
+ UInt insSz = SLICE(insn, 16, 15);
++ UInt isOd = SLICE(insn, 17, 17);
+
-+ IRExpr *elem;
-+ IRTemp mod = newTemp(Ity_I8);
++ IRTemp wJ = newTemp(Ity_V128);
++ IRTemp wK = newTemp(Ity_V128);
+ IRTemp res = newTemp(Ity_V128);
-+ UInt div[4] = { 0x10, 0x8, 0x4, 0x2 };
-+
-+ assign(mod, unop(Iop_64to8,
-+ unop(Iop_128HIto64,
-+ binop(Iop_DivModU64to64,
-+ getIReg64(rk),
-+ mkU64(div[insSz])))));
++ IRTemp z128 = newTemp(Ity_V128);
++ IROp packOp = isOd ? mkV128PACKOD(insSz): mkV128PACKEV(insSz);
++ assign(z128, mkV128(0x0000));
+
-+ elem = binop(mkVecGetElem(insSz), getVReg(vj), mkexpr(mod));
+ switch (insSz) {
+ case 0b00:
-+ assign(res, unop(Iop_Dup8x16, elem));
-+ break;
-+ case 0b01:
-+ assign(res, unop(Iop_Dup16x8, elem));
-+ break;
-+ case 0b10:
-+ assign(res, unop(Iop_Dup32x4, elem));
++ case 0b01: {
++ assign(wJ, unop(mkV128EXTHTU(insSz), binop(packOp, getVReg(vj), EX(z128))));
++ assign(wK, unop(mkV128EXTHTS(insSz), binop(packOp, getVReg(vk), EX(z128))));
++ assign(res, binop(mkV128MUL(insSz + 1), EX(wJ), EX(wK)));
+ break;
-+ case 0b11:
-+ assign(res, binop(Iop_64HLtoV128, elem, elem));
++ }
++ case 0b10: {
++ assign(wJ, unop(mkV128EXTHTU(insSz), binop(packOp, getVReg(vj), EX(z128))));
++ assign(wK, unop(mkV128EXTHTS(insSz), binop(packOp, getVReg(vk), EX(z128))));
++ assign(res, VMUD(EX(wJ), EX(wK), Iop_MullU64, Iop_128to64));
+ break;
-+ default:
-+ vassert(0);
++ }
++ case 0b11: {
++ assign(wJ, binop(packOp, getVReg(vj), EX(z128)));
++ assign(wK, binop(packOp, getVReg(vk), EX(z128)));
++ res = gen_vmulw_d(wJ, wK, Iop_MullU64);
+ break;
++ }
++ default: vassert(0);
+ }
+
-+ DIP("vreplve.%s %s, %s, %s", mkInsSize(insSz),
-+ nameVReg(vd), nameVReg(vj), nameIReg(rk));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
-+
++ const HChar *nm[2] = { "vmulwev", "vmulwod" };
++ const HChar *ns[4] = { "h.bu.b", "w.hu.h", "d.wu.w", "q.du.d" };
++ DIP("%s.%s %s, %s, %s\n", nm[isOd], ns[insSz], nameVReg(vd),
++ nameVReg(vj), nameVReg(vk));
+ putVReg(vd, mkexpr(res));
-+
+ return True;
+}
+
-+static Bool gen_xvpickve ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvmulw_x_x_x ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ UInt xd = SLICE(insn, 4, 0);
-+ UInt xj = SLICE(insn, 9, 5);
-+ UInt insImm = SLICE(insn, 15, 10);
-+
-+ UInt sImm, insSz;
-+ IRTemp res = newTemp(Ity_I64);
-+ IRTemp z64 = newTemp(Ity_I64);
-+ IRTemp src = newTemp(Ity_V256);
-+ assign(z64, mkU64(0));
-+ assign(src, getXReg(xj));
-+
-+ if ((insImm & 0x38) == 0x30) { // 110ui3; w
-+ IRTemp s[8];
-+ s[7] = s[6] = s[5] = s[4] = s[3] = s[2] = s[1] = s[0] = IRTemp_INVALID;
-+ breakupV256to32s(src, &s[7], &s[6], &s[5], &s[4],
-+ &s[3], &s[2], &s[1], &s[0]);
-+ sImm = insImm & 0x7;
-+ insSz = 0;
-+ assign(res, extendU(Ity_I32, mkexpr(s[sImm])));
-+ } else if ((insImm & 0x3c) == 0x38) { // 1110ui2; d
-+ IRTemp s[4];
-+ s[3] = s[2] = s[1] = s[0] = IRTemp_INVALID;
-+ breakupV256to64s(src, &s[3], &s[2], &s[1], &s[0]);
-+ sImm = insImm & 0x3;
-+ insSz = 1;
-+ assign(res, mkexpr(s[sImm]));
-+ } else {
-+ vassert(0);
-+ }
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isOd = SLICE(insn, 17, 17);
+
-+ const HChar arr = "wd"[insSz];
-+ DIP("xvpickve.%c %s, %s, %u", arr, nameXReg(xd), nameXReg(xj), sImm);
++ IRTemp wJ = newTemp(Ity_V256);
++ IRTemp wK = newTemp(Ity_V256);
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp z256 = newTemp(Ity_V256);
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp jHi = IRTemp_INVALID;
++ IRTemp jLo = IRTemp_INVALID;
++ IRTemp kHi = IRTemp_INVALID;
++ IRTemp kLo = IRTemp_INVALID;
++ IROp packOp = isOd ? mkV256PACKOD(insSz) : mkV256PACKEV(insSz);
++ assign(z256, mkV256(0x0000));
+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
++ switch (insSz) {
++ case 0b00:
++ case 0b01: {
++ assign(wJ, unop(mkV256EXTHTU(insSz), binop(packOp, getXReg(xj), EX(z256))));
++ assign(wK, unop(mkV256EXTHTS(insSz), binop(packOp, getXReg(xk), EX(z256))));
++ assign(res, binop(mkV256MUL(insSz + 1), EX(wJ), EX(wK)));
++ break;
++ }
++ case 0b10: {
++ assign(wJ, unop(mkV256EXTHTU(insSz), binop(packOp, getXReg(xj), EX(z256))));
++ assign(wK, unop(mkV256EXTHTS(insSz), binop(packOp, getXReg(xk), EX(z256))));
++ breakupV256toV128s(wJ, &jHi, &jLo);
++ breakupV256toV128s(wK, &kHi, &kLo);
++ assign(rHi, VMUD(EX(jHi), EX(kHi), Iop_MullU64, Iop_128to64));
++ assign(rLo, VMUD(EX(jLo), EX(kLo), Iop_MullU64, Iop_128to64));
++ assign(res, mkV256from128s(rHi, rLo));
++ break;
++ }
++ case 0b11: {
++ assign(wJ, binop(packOp, getXReg(xj), EX(z256)));
++ assign(wK, binop(packOp, getXReg(xk), EX(z256)));
++ breakupV256toV128s(wJ, &jHi, &jLo);
++ breakupV256toV128s(wK, &kHi, &kLo);
++ rHi = gen_vmulw_d(jHi, kHi, Iop_MullU64);
++ rLo = gen_vmulw_d(jLo, kLo, Iop_MullU64);
++ assign(res, mkV256from128s(rHi, rLo));
++ break;
++ }
++ default: vassert(0);
+ }
+
-+ putXReg(xd, mkV256from64s(z64, z64, z64, res));
-+
++ const HChar *nm[2] = { "xvmulwev", "xvmulwod" };
++ const HChar *ns[4] = { "h.bu.b", "w.hu.h", "d.wu.w", "q.du.d" };
++ DIP("%s.%s %s, %s, %s\n", nm[isOd], ns[insSz], nameXReg(xd),
++ nameXReg(xj), nameXReg(xk));
++ putXReg(xd, mkexpr(res));
+ return True;
+}
+
-+static Bool gen_evod ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vmadd_vmsub ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
+ UInt vd = SLICE(insn, 4, 0);
+ UInt vj = SLICE(insn, 9, 5);
+ UInt vk = SLICE(insn, 14, 10);
+ UInt insSz = SLICE(insn, 16, 15);
++ UInt isSub = SLICE(insn, 17, 17);
+
-+ const HChar *nm;
-+ IRTemp argL = newTemp(Ity_V128);
-+ IRTemp argR = newTemp(Ity_V128);
-+ IRTemp res = newTemp(Ity_V128);
-+
-+ switch (SLICE(insn, 19, 17)) {
-+ case 0b011:
-+ nm = "vpackev";
-+ assign(argL, binop(mkVecPACKEV(insSz),
-+ getVReg(vj),
-+ mkV128(0x0000)));
-+ assign(argR, binop(mkVecPACKEV(insSz),
-+ getVReg(vk),
-+ mkV128(0x0000)));
-+ assign(res, binop(mkVecINTERLEAVEHI(insSz),
-+ mkexpr(argL),
-+ mkexpr(argR)));
-+ break;
-+ case 0b100:
-+ nm = "vpackod";
-+ assign(argL, binop(mkVecPACKOD(insSz),
-+ getVReg(vj),
-+ mkV128(0x0000)));
-+ assign(argR, binop(mkVecPACKOD(insSz),
-+ getVReg(vk),
-+ mkV128(0x0000)));
-+ assign(res, binop(mkVecINTERLEAVEHI(insSz),
-+ mkexpr(argL),
-+ mkexpr(argR)));
-+ break;
-+ case 0b101:
-+ nm = "vilvl";
-+ assign(res, binop(mkVecINTERLEAVELO(insSz),
-+ getVReg(vj),
-+ getVReg(vk)));
-+ break;
-+ case 0b110:
-+ nm = "vilvh";
-+ assign(res, binop(mkVecINTERLEAVEHI(insSz),
-+ getVReg(vj),
-+ getVReg(vk)));
-+ break;
-+ case 0b111:
-+ nm = "vpickev";
-+ assign(res, binop(mkVecPACKEV(insSz),
-+ getVReg(vj),
-+ getVReg(vk)));
-+ break;
-+ case 0b000:
-+ nm = "vpickod";
-+ assign(res, binop(mkVecPACKOD(insSz),
-+ getVReg(vj),
-+ getVReg(vk)));
-+ break;
-+ default:
-+ return False;
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp sK = newTemp(Ity_V128);
++ IROp addOp = isSub ? mkV128SUB(insSz) : mkV128ADD(insSz);
++ assign(sJ, getVReg(vj));
++ assign(sK, getVReg(vk));
++
++ if (insSz == 0b11) {
++ assign(res, VMUD(EX(sJ), EX(sK), Iop_MullS64, Iop_128to64));
++ } else {
++ assign(res, binop(mkV128MUL(insSz), EX(sJ), EX(sK)));
+ }
+
-+ DIP("%s.%s %s, %s, %s\n", nm, mkInsSize(insSz),
++ const HChar *nm[2] = { "vmadd", "vmsub" };
++ DIP("%s.%s %s, %s, %s\n", nm[isSub], mkInsSize(insSz),
+ nameVReg(vd), nameVReg(vj), nameVReg(vk));
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
-+
-+ putVReg(vd, mkexpr(res));
++ putVReg(vd, binop(addOp, getVReg(vd), EX(res)));
+ return True;
+}
+
-+static Bool gen_vshuf_b ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvmadd_xvmsub ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ UInt va = SLICE(insn, 19, 15);
-+ UInt vk = SLICE(insn, 14, 10);
-+ UInt vj = SLICE(insn, 9, 5);
-+ UInt vd = SLICE(insn, 4, 0);
-+
-+ DIP("vshuf.b %s, %s, %s, %s\n", nameVReg(vd), nameVReg(vj), nameVReg(vk),
-+ nameVReg(va));
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isSub = SLICE(insn, 17, 17);
+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sK = newTemp(Ity_V256);
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp jHi = IRTemp_INVALID;
++ IRTemp jLo = IRTemp_INVALID;
++ IRTemp kHi = IRTemp_INVALID;
++ IRTemp kLo = IRTemp_INVALID;
++ IROp addOp = isSub ? mkV256SUB(insSz) : mkV256ADD(insSz);
++ assign(sJ, getXReg(xj));
++ assign(sK, getXReg(xk));
++
++ if (insSz == 0b11) {
++ breakupV256toV128s(sJ, &jHi, &jLo);
++ breakupV256toV128s(sK, &kHi, &kLo);
++ assign(rHi, VMUD(EX(jHi), EX(kHi), Iop_MullS64, Iop_128to64));
++ assign(rLo, VMUD(EX(jLo), EX(kLo), Iop_MullS64, Iop_128to64));
++ assign(res, mkV256from128s(rHi, rLo));
++ } else {
++ assign(res, binop(mkV256MUL(insSz), EX(sJ), EX(sK)));
+ }
+
-+ IRTemp sHi = newTemp(Ity_V128);
-+ IRTemp sLo = newTemp(Ity_V128);
-+ IRTemp sId = newTemp(Ity_V128);
-+ assign(sHi, getVReg(vj));
-+ assign(sLo, getVReg(vk));
-+ assign(sId, getVReg(va));
-+ UInt i;
-+ IRTemp id[16], res[16];
++ const HChar *nm[2] = { "xvmadd", "xvmsub" };
++ DIP("%s.%s %s, %s, %s\n", nm[isSub], mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, binop(addOp, getXReg(xd), EX(res)));
++ return True;
++}
+
-+ for (i = 0; i < 16; i++) {
-+ id[i] = newTemp(Ity_I8);
-+ res[i] = newTemp(Ity_I8);
++static Bool gen_vmaddw ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isOd = SLICE(insn, 17, 17);
++ UInt isU = SLICE(insn, 20, 20);
+
-+ assign(id[i], binop(Iop_GetElem8x16, mkexpr(sId), mkU8(i)));
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp wJ = newTemp(Ity_V128);
++ IRTemp wK = newTemp(Ity_V128);
++ IRTemp z128 = newTemp(Ity_V128);
++ IROp mulOp = isU ? Iop_MullU64 : Iop_MullS64;
++ IROp widenOp = isU ? mkV128EXTHTU(insSz) : mkV128EXTHTS(insSz);
++ IROp packOp = isOd ? mkV128PACKOD(insSz) : mkV128PACKEV(insSz);
++ assign(z128, mkV128(0x0000));
+
-+ assign(res[i], IRExpr_ITE(
-+ binop(Iop_CmpEQ64,
-+ extendU(Ity_I8, binop(Iop_And8,
-+ mkexpr(id[i]),
-+ mkU8(0xC0))),
-+ mkU64(0x0)),
-+ IRExpr_ITE(
-+ binop(Iop_CmpLT64U,
-+ extendU(Ity_I8, binop(Iop_And8,
-+ mkexpr(id[i]),
-+ mkU8(0x1F))),
-+ mkU64(0x10)),
-+ binop(Iop_GetElem8x16,
-+ mkexpr(sLo),
-+ mkexpr(id[i])),
-+ binop(Iop_GetElem8x16,
-+ mkexpr(sHi),
-+ unop(Iop_64to8,
-+ binop(Iop_Sub64,
-+ extendU(Ity_I8, mkexpr(id[i])),
-+ mkU64(0x10))))),
-+ mkU8(0x0)));
++ switch (insSz) {
++ case 0b00: case 0b01: {
++ assign(wJ, unop(widenOp, binop(packOp, getVReg(vj), EX(z128))));
++ assign(wK, unop(widenOp, binop(packOp, getVReg(vk), EX(z128))));
++ assign(res, binop(mkV128MUL(insSz + 1), mkexpr(wJ), mkexpr(wK)));
++ break;
++ }
++ case 0b10: {
++ assign(wJ, unop(widenOp, binop(packOp, getVReg(vj), EX(z128))));
++ assign(wK, unop(widenOp, binop(packOp, getVReg(vk), EX(z128))));
++ assign(res, VMUD(EX(wJ), EX(wK), mulOp, Iop_128to64));
++ break;
++ }
++ case 0b11: {
++ assign(wJ, binop(packOp, getVReg(vj), EX(z128)));
++ assign(wK, binop(packOp, getVReg(vk), EX(z128)));
++ res = gen_vmulw_d(wJ, wK, mulOp);
++ break;
++ }
++ default: vassert(0);
+ }
+
-+ putVReg(vd,
-+ binop(Iop_64HLtoV128,
-+ binop(Iop_32HLto64,
-+ binop(Iop_16HLto32,
-+ binop(Iop_8HLto16, mkexpr(res[15]), mkexpr(res[14])),
-+ binop(Iop_8HLto16, mkexpr(res[13]), mkexpr(res[12]))),
-+ binop(Iop_16HLto32,
-+ binop(Iop_8HLto16, mkexpr(res[11]), mkexpr(res[10])),
-+ binop(Iop_8HLto16, mkexpr(res[9]), mkexpr(res[8])))),
-+ binop(Iop_32HLto64,
-+ binop(Iop_16HLto32,
-+ binop(Iop_8HLto16, mkexpr(res[7]), mkexpr(res[6])),
-+ binop(Iop_8HLto16, mkexpr(res[5]), mkexpr(res[4]))),
-+ binop(Iop_16HLto32,
-+ binop(Iop_8HLto16, mkexpr(res[3]), mkexpr(res[2])),
-+ binop(Iop_8HLto16, mkexpr(res[1]), mkexpr(res[0]))))));
-+
++ UInt id = isU ? (insSz + 4) : insSz;
++ const HChar *nm[2] = { "vmaddwev", "vmaddwod" };
++ DIP("%s.%s %s, %s, %s\n", nm[isOd], mkInsSize(id),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++ putVReg(vd, binop(mkV128ADD(insSz + 1), getVReg(vd), EX(res)));
+ return True;
+}
+
-+static Bool gen_xvpermi ( DisResult* dres, UInt insn,
++static Bool gen_xvmaddw ( DisResult* dres, UInt insn,
+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++ const VexAbiInfo* abiinfo )
+{
+ UInt xd = SLICE(insn, 4, 0);
+ UInt xj = SLICE(insn, 9, 5);
-+ UInt ui8 = SLICE(insn, 17, 10);
-+ UInt InsSz = SLICE(insn, 19, 18);
-+
-+ UInt id0 = ui8 & 0x03;
-+ UInt id1 = (ui8 & 0x0c) >> 2;
-+ UInt id2 = (ui8 & 0x30) >> 4;
-+ UInt id3 = (ui8 & 0xc0) >> 6;
-+
-+ IRTemp res = newTemp(Ity_V256);
-+ IRTemp sJ = newTemp(Ity_V256);
-+ assign(sJ, getXReg(xj));
-+ IRTemp sD = newTemp(Ity_V256);
-+ assign(sD, getXReg(xd));
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isOd = SLICE(insn, 17, 17);
++ UInt isU = SLICE(insn, 20, 20);
++
++ IRTemp wJ = newTemp(Ity_V256);
++ IRTemp wK = newTemp(Ity_V256);
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp z256 = newTemp(Ity_V256);
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp jHi = IRTemp_INVALID;
++ IRTemp jLo = IRTemp_INVALID;
++ IRTemp kHi = IRTemp_INVALID;
++ IRTemp kLo = IRTemp_INVALID;
++ IROp mulOp = isU ? Iop_MullU64 : Iop_MullS64;
++ IROp widenOp = isU ? mkV256EXTHTU(insSz) : mkV256EXTHTS(insSz);
++ IROp packOp = isOd ? mkV256PACKOD(insSz) : mkV256PACKEV(insSz);
++ assign(z256, mkV256(0x0000));
+
-+ switch (InsSz) {
-+ case 0b01: {
-+ IRTemp s[16];
-+ s[7] = s[6] = s[5] = s[4] = s[3] = s[2] = s[1] = s[0] = IRTemp_INVALID;
-+ s[15] = s[14] = s[13] = s[12] = s[11] = s[10] = s[9] = s[8] = IRTemp_INVALID;
-+ breakupV256to32s(sJ, &s[7], &s[6], &s[5], &s[4],
-+ &s[3], &s[2], &s[1], &s[0]);
-+ breakupV256to32s(sD, &s[15], &s[14], &s[13], &s[12],
-+ &s[11], &s[10], &s[9], &s[8]);
-+ assign(res, mkV256from32s(s[id0], s[id1], s[id2], s[id3],
-+ s[id0 + 4], s[id1 + 4], s[id2 + 4], s[id3 + 4]));
++ switch (insSz) {
++ case 0b00: case 0b01: {
++ assign(wJ, unop(widenOp, binop(packOp, getXReg(xj), EX(z256))));
++ assign(wK, unop(widenOp, binop(packOp, getXReg(xk), EX(z256))));
++ assign(res, binop(mkV256MUL(insSz + 1), mkexpr(wJ), mkexpr(wK)));
+ break;
+ }
+ case 0b10: {
-+ IRTemp s[4];
-+ s[3] = s[2] = s[1] = s[0] = IRTemp_INVALID;
-+ breakupV256to64s(sJ, &s[3], &s[2], &s[1], &s[0]);
-+ assign(res, mkV256from64s(s[id0], s[id1], s[id2], s[id3]));
++ assign(wJ, unop(widenOp, binop(packOp, getXReg(xj), EX(z256))));
++ assign(wK, unop(widenOp, binop(packOp, getXReg(xk), EX(z256))));
++ breakupV256toV128s(wJ, &jHi, &jLo);
++ breakupV256toV128s(wK, &kHi, &kLo);
++ assign(rHi, VMUD(EX(jHi), EX(kHi), mulOp, Iop_128to64));
++ assign(rLo, VMUD(EX(jLo), EX(kLo), mulOp, Iop_128to64));
++ assign(res, mkV256from128s(rHi, rLo));
+ break;
+ }
+ case 0b11: {
-+ IRTemp s[4];
-+ s[3] = s[2] = s[1] = s[0] = IRTemp_INVALID;
-+ breakupV256toV128s(sJ, &s[1], &s[0]);
-+ breakupV256toV128s(sD, &s[3], &s[2]);
-+ assign(res, binop(Iop_V128HLtoV256, mkexpr(s[id2]), mkexpr(s[id0])));
++ assign(wJ, binop(packOp, getXReg(xj), EX(z256)));
++ assign(wK, binop(packOp, getXReg(xk), EX(z256)));
++ breakupV256toV128s(wJ, &jHi, &jLo);
++ breakupV256toV128s(wK, &kHi, &kLo);
++ rHi = gen_vmulw_d(jHi, kHi, mulOp);
++ rLo = gen_vmulw_d(jLo, kLo, mulOp);
++ assign(res, mkV256from128s(rHi, rLo));
+ break;
+ }
-+ default:
-+ vassert(0);
-+ break;
-+ }
-+
-+ DIP("xvpermi.%s %s, %s, %u\n", mkInsSize(InsSz), nameXReg(xd), nameXReg(xj), ui8);
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
++ default: vassert(0);
+ }
+
-+ putXReg(xd, mkexpr(res));
-+
++ UInt id = isU ? (insSz + 4) : insSz;
++ const HChar *nm[2] = { "xvmaddwev", "xvmaddwod" };
++ DIP("%s.%s %s, %s, %s\n", nm[isOd], mkInsSize(id),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, binop(mkV256ADD(insSz + 1), getXReg(xd), EX(res)));
+ return True;
+}
+
-+
-+/*------------------------------------------------------------*/
-+/*--- Helpers for vector load/store insns ---*/
-+/*------------------------------------------------------------*/
-+
-+static Bool gen_vld ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vmaddw_x_x_x ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ UInt si12 = SLICE(insn, 21, 10);
-+ UInt rj = SLICE(insn, 9, 5);
-+ UInt vd = SLICE(insn, 4, 0);
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isOd = SLICE(insn, 17, 17);
+
-+ DIP("vld %s, %s, %d\n", nameVReg(vd), nameIReg(rj),
-+ (Int)extend32(si12, 12));
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp wJ = newTemp(Ity_V128);
++ IRTemp wK = newTemp(Ity_V128);
++ IRTemp z128 = newTemp(Ity_V128);
++ IROp packOp = isOd ? mkV128PACKOD(insSz) : mkV128PACKEV(insSz);
++ assign(z128, mkV128(0x0000));
+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
++ switch (insSz) {
++ case 0b00:
++ case 0b01: {
++ assign(wJ, unop(mkV128EXTHTU(insSz), binop(packOp, getVReg(vj), EX(z128))));
++ assign(wK, unop(mkV128EXTHTS(insSz), binop(packOp, getVReg(vk), EX(z128))));
++ assign(res, binop(mkV128MUL(insSz + 1), EX(wJ), EX(wK)));
++ break;
++ }
++ case 0b10: {
++ assign(wJ, unop(mkV128EXTHTU(insSz), binop(packOp, getVReg(vj), EX(z128))));
++ assign(wK, unop(mkV128EXTHTS(insSz), binop(packOp, getVReg(vk), EX(z128))));
++ assign(res, VMUD(EX(wJ), EX(wK), Iop_MullU64, Iop_128to64));
++ break;
++ }
++ case 0b11: {
++ assign(wJ, binop(packOp, getVReg(vj), EX(z128)));
++ assign(wK, binop(packOp, getVReg(vk), EX(z128)));
++ res = gen_vmulw_d(wJ, wK, Iop_MullS64);
++ break;
++ }
++ default: vassert(0);
+ }
+
-+ IRExpr* addr = binop(Iop_Add64, getIReg64(rj), mkU64(extend64(si12, 12)));
-+ putVReg(vd, load(Ity_V128, addr));
-+
++ const HChar *nm[2] = { "vmaddwev", "vmaddwod" };
++ const HChar *ns[4] = { "h.bu.b", "w.hu.h", "d.wu.w", "q.du.d" };
++ DIP("%s.%s %s, %s, %s\n", nm[isOd], ns[insSz],
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++ putVReg(vd, binop(mkV128ADD(insSz + 1), getVReg(vd), mkexpr(res)));
+ return True;
+}
+
-+static Bool gen_vldrepl ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvmaddw_x_x_x ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ UInt vd = SLICE(insn, 4, 0);
-+ UInt rj = SLICE(insn, 9, 5);
-+ UInt insImm = SLICE(insn, 23, 10);
-+
-+ UInt sImm, insSz;
-+ IRTemp res = newTemp(Ity_V128);
-+ IRTemp addr = newTemp(Ity_I64);
-+
-+ if ((insImm & 0x3000) == 0x2000) { // 10si12; b
-+ sImm = insImm & 0xfff;
-+ insSz = 0;
-+ } else if ((insImm & 0x3800) == 0x1000) { // 010si11; h
-+ sImm = insImm & 0x7ff;
-+ insSz = 1;
-+ } else if ((insImm & 0x3c00) == 0x800) { // 0010si10; w
-+ sImm = insImm & 0x3ff;
-+ insSz = 2;
-+ } else if ((insImm & 0x3e00) == 0x400) { // 00010si9; d
-+ sImm = insImm & 0x1ff;
-+ insSz = 3;
-+ } else {
-+ return False;
-+ }
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isOd = SLICE(insn, 17, 17);
++
++ IRTemp wJ = newTemp(Ity_V256);
++ IRTemp wK = newTemp(Ity_V256);
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp z256 = newTemp(Ity_V256);
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp jHi = IRTemp_INVALID;
++ IRTemp jLo = IRTemp_INVALID;
++ IRTemp kHi = IRTemp_INVALID;
++ IRTemp kLo = IRTemp_INVALID;
++ IROp packOp = isOd ? mkV256PACKOD(insSz) : mkV256PACKEV(insSz);
++ assign(z256, mkV256(0x0000));
+
+ switch (insSz) {
-+ case 0b00: {
-+ assign(addr, binop(Iop_Add64,
-+ getIReg64(rj),
-+ mkU64(extend64(sImm, 12))));
-+ assign(res, unop(Iop_Dup8x16, load(Ity_I8, mkexpr(addr))));
-+ break;
-+ }
-+ case 0b01: {
-+ assign(addr, binop(Iop_Add64,
-+ getIReg64(rj),
-+ mkU64(extend64(sImm << 1, 12))));
-+ assign(res, unop(Iop_Dup16x8, load(Ity_I16, mkexpr(addr))));
++ case 0b00: case 0b01: {
++ assign(wJ, unop(mkV256EXTHTU(insSz), binop(packOp, getXReg(xj), EX(z256))));
++ assign(wK, unop(mkV256EXTHTS(insSz), binop(packOp, getXReg(xk), EX(z256))));
++ assign(res, binop(mkV256MUL(insSz + 1), EX(wJ), EX(wK)));
+ break;
+ }
+ case 0b10: {
-+ assign(addr, binop(Iop_Add64,
-+ getIReg64(rj),
-+ mkU64(extend64(sImm << 2, 12))));
-+ assign(res, unop(Iop_Dup32x4, load(Ity_I32, mkexpr(addr))));
++ assign(wJ, unop(mkV256EXTHTU(insSz), binop(packOp, getXReg(xj), EX(z256))));
++ assign(wK, unop(mkV256EXTHTS(insSz), binop(packOp, getXReg(xk), EX(z256))));
++ breakupV256toV128s(wJ, &jHi, &jLo);
++ breakupV256toV128s(wK, &kHi, &kLo);
++ assign(rHi, VMUD(EX(jHi), EX(kHi), Iop_MullU64, Iop_128to64));
++ assign(rLo, VMUD(EX(jLo), EX(kLo), Iop_MullU64, Iop_128to64));
++ assign(res, mkV256from128s(rHi, rLo));
+ break;
+ }
+ case 0b11: {
-+ assign(addr, binop(Iop_Add64,
-+ getIReg64(rj),
-+ mkU64(extend64(sImm << 3, 12))));
-+ assign(res, binop(Iop_64HLtoV128,
-+ load(Ity_I64, mkexpr(addr)),
-+ load(Ity_I64, mkexpr(addr))));
++ assign(wJ, binop(packOp, getXReg(xj), EX(z256)));
++ assign(wK, binop(packOp, getXReg(xk), EX(z256)));
++ res = gen_vmulw_d(wJ, wK, Iop_MullS64);
+ break;
+ }
-+ default:
-+ vassert(0);
-+ break;
++ default: vassert(0);
+ }
+
-+ DIP("vldrepl.%s %s, %s, %u\n", mkInsSize(insSz),
-+ nameVReg(vd), nameIReg(rj), sImm);
++ const HChar *nm[2] = { "xvmaddwev", "xvmaddwod" };
++ const HChar *ns[4] = { "h.bu.b", "w.hu.h", "d.wu.w", "q.du.d" };
++ DIP("%s.%s %s, %s, %s\n", nm[isOd], ns[insSz],
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, binop(mkV256ADD(insSz + 1), getXReg(xd), mkexpr(res)));
++ return True;
++}
+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
++static IRTemp gen_vdiv_b ( IRTemp argL, IRTemp argR, UInt isMod, UInt isU )
++{
++ UInt i;
++ IRTemp tI8[16];
++ IRTemp math[16];
++ IRTemp res = newTemp(Ity_V128);
++ IROp wideOp = isU ? Iop_8Uto32 : Iop_8Sto32;
++ IROp mathOp = isMod ? isU ? Iop_DivModU32to32 : Iop_DivModS32to32 :
++ isU ? Iop_DivU32 : Iop_DivS32;
++
++ if (isMod) {
++ for (i = 0; i < 16; i++) {
++ tI8[i] = newTemp(Ity_I8);
++ math[i] = newTemp(Ity_I64);
++ assign(math[i],
++ binop(mathOp,
++ unop(wideOp,
++ binop(Iop_GetElem8x16, EX(argL), mkU8(i))),
++ unop(wideOp,
++ binop(Iop_GetElem8x16, EX(argR), mkU8(i)))));
++ assign(tI8[i],
++ unop(Iop_32to8,
++ unop(Iop_64HIto32, mkexpr(math[i]))));
++ }
++ } else {
++ for (i = 0; i < 16; i++) {
++ tI8[i] = newTemp(Ity_I8);
++ math[i] = newTemp(Ity_I32);
++ assign(math[i],
++ binop(mathOp,
++ unop(wideOp,
++ binop(Iop_GetElem8x16, EX(argL), mkU8(i))),
++ unop(wideOp,
++ binop(Iop_GetElem8x16, EX(argR), mkU8(i)))));
++ assign(tI8[i], unop(Iop_32to8, mkexpr(math[i])));
++ }
+ }
+
-+ putVReg(vd, mkexpr(res));
-+
-+ return True;
++ assign(res, mkV128from8s(tI8[15], tI8[14], tI8[13], tI8[12],
++ tI8[11], tI8[10], tI8[9], tI8[8],
++ tI8[7], tI8[6], tI8[5], tI8[4],
++ tI8[3], tI8[2], tI8[1], tI8[0]));
++ return res;
+}
+
-+static Bool gen_vst ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static IRTemp gen_vdiv_h ( IRTemp argL, IRTemp argR, UInt isMod, UInt isU )
+{
-+ UInt si12 = SLICE(insn, 21, 10);
-+ UInt rj = SLICE(insn, 9, 5);
-+ UInt vd = SLICE(insn, 4, 0);
++ UInt i;
++ IRTemp tI16[8];
++ IRTemp math[8];
++ IRTemp res = newTemp(Ity_V128);
++ IROp wideOp = isU ? Iop_16Uto32 : Iop_16Sto32;
++ IROp mathOp = isMod ? isU ? Iop_DivModU32to32 : Iop_DivModS32to32 :
++ isU ? Iop_DivU32 : Iop_DivS32;
++
++ if (isMod) {
++ for (i = 0; i < 8; i++) {
++ tI16[i] = newTemp(Ity_I16);
++ math[i] = newTemp(Ity_I64);
++ assign(math[i],
++ binop(mathOp,
++ unop(wideOp,
++ binop(Iop_GetElem16x8, mkexpr(argL), mkU8(i))),
++ unop(wideOp,
++ binop(Iop_GetElem16x8, mkexpr(argR), mkU8(i)))));
++ assign(tI16[i],
++ unop(Iop_32to16,
++ unop(Iop_64HIto32, mkexpr(math[i]))));
++ }
++ } else {
++ for (i = 0; i < 8; i++) {
++ tI16[i] = newTemp(Ity_I16);
++ math[i] = newTemp(Ity_I32);
++ assign(math[i],
++ binop(mathOp,
++ unop(wideOp,
++ binop(Iop_GetElem16x8, mkexpr(argL), mkU8(i))),
++ unop(wideOp,
++ binop(Iop_GetElem16x8, mkexpr(argR), mkU8(i)))));
++ assign(tI16[i], unop(Iop_32to16, mkexpr(math[i])));
++ }
++ }
+
-+ DIP("vst %s, %s, %d\n", nameVReg(vd), nameIReg(rj),
-+ (Int)extend32(si12, 12));
++ assign(res, mkV128from16s(tI16[7], tI16[6], tI16[5], tI16[4],
++ tI16[3], tI16[2], tI16[1], tI16[0]));
++ return res;
++}
+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
++static IRTemp gen_vdiv_w ( IRTemp argL, IRTemp argR, UInt isMod, UInt isU )
++{
++ UInt i;
++ IRTemp tI32[4];
++ IRTemp math[4];
++ IRTemp res = newTemp(Ity_V128);
++ IROp mathOp = isMod ? isU ? Iop_DivModU32to32 : Iop_DivModS32to32 :
++ isU ? Iop_DivU32 : Iop_DivS32;
++
++ if (isMod) {
++ for (i = 0; i < 4; i++) {
++ tI32[i] = newTemp(Ity_I32);
++ math[i] = newTemp(Ity_I64);
++ assign(math[i], binop(mathOp,
++ binop(Iop_GetElem32x4, mkexpr(argL), mkU8(i)),
++ binop(Iop_GetElem32x4, mkexpr(argR), mkU8(i))));
++ assign(tI32[i], unop(Iop_64HIto32, mkexpr(math[i])));
++ }
++ } else {
++ for (i = 0; i < 4; i++) {
++ tI32[i] = newTemp(Ity_I32);
++ assign(tI32[i], binop(mathOp,
++ binop(Iop_GetElem32x4, mkexpr(argL), mkU8(i)),
++ binop(Iop_GetElem32x4, mkexpr(argR), mkU8(i))));
++ }
+ }
+
-+ IRExpr* addr = binop(Iop_Add64, getIReg64(rj), mkU64(extend64(si12, 12)));
-+ store(addr, getVReg(vd));
++ assign(res, mkV128from32s(tI32[3], tI32[2], tI32[1], tI32[0]));
++ return res;
++}
+
-+ return True;
++static IRTemp gen_vdiv_d ( IRTemp argL, IRTemp argR, UInt isMod, UInt isU )
++{
++ IRTemp lHi = newTemp(Ity_I64);
++ IRTemp rHi = newTemp(Ity_I64);
++ IRTemp lLo = newTemp(Ity_I64);
++ IRTemp rLo = newTemp(Ity_I64);
++ assign(lHi, unop(Iop_V128HIto64, EX(argL)));
++ assign(rHi, unop(Iop_V128HIto64, EX(argR)));
++ assign(lLo, unop(Iop_V128to64, EX(argL)));
++ assign(rLo, unop(Iop_V128to64, EX(argR)));
++ IRTemp res = newTemp(Ity_V128);
++ IROp mathOp = isMod ? isU ? Iop_DivModU64to64 : Iop_DivModS64to64 :
++ isU ? Iop_DivU64 : Iop_DivS64;
++
++ if (isMod) {
++ assign(res,
++ binop(Iop_64HLtoV128,
++ unop(Iop_128HIto64, binop(mathOp, EX(lHi), EX(rHi))),
++ unop(Iop_128HIto64, binop(mathOp, EX(lLo), EX(rLo)))));
++ } else {
++ assign(res,
++ binop(Iop_64HLtoV128,
++ binop(mathOp, EX(lHi), EX(rHi)),
++ binop(mathOp, EX(lLo), EX(rLo))));
++ }
++
++ return res;
+}
+
-+static Bool gen_xvld ( DisResult* dres, UInt insn,
++static Bool gen_vdiv ( DisResult* dres, UInt insn,
+ const VexArchInfo* archinfo,
+ const VexAbiInfo* abiinfo )
+{
-+ UInt si12 = SLICE(insn, 21, 10);
-+ UInt rj = SLICE(insn, 9, 5);
-+ UInt xd = SLICE(insn, 4, 0);
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isMod = SLICE(insn, 17, 17);
++ UInt isU = SLICE(insn, 18, 18);
+
-+ DIP("xvld %s, %s, %d\n", nameXReg(xd), nameIReg(rj),
-+ (Int)extend32(si12, 12));
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp sK = newTemp(Ity_V128);
++ assign(sJ, getVReg(vj));
++ assign(sK, getVReg(vk));
+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
++ switch (insSz) {
++ case 0b00: res = gen_vdiv_b(sJ, sK, isMod, isU); break;
++ case 0b01: res = gen_vdiv_h(sJ, sK, isMod, isU); break;
++ case 0b10: res = gen_vdiv_w(sJ, sK, isMod, isU); break;
++ case 0b11: res = gen_vdiv_d(sJ, sK, isMod, isU); break;
++ default: vassert(0);
+ }
+
-+ IRExpr* addr = binop(Iop_Add64, getIReg64(rj), mkU64(extend64(si12, 12)));
-+ putXReg(xd, load(Ity_V256, addr));
++ UInt id = isU ? (insSz + 4) : insSz;
++ const HChar *nm[2] = { "vdiv", "vmod" };
++ DIP("%s.%s %s, %s\n", nm[isMod], mkInsSize(id),
++ nameVReg(vd), nameVReg(vj));
++ putVReg(vd, mkexpr(res));
++ return True;
++}
++
++static Bool gen_xvdiv ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isMod = SLICE(insn, 17, 17);
++ UInt isU = SLICE(insn, 18, 18);
++
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sK = newTemp(Ity_V256);
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp jHi = IRTemp_INVALID;
++ IRTemp jLo = IRTemp_INVALID;
++ IRTemp kHi = IRTemp_INVALID;
++ IRTemp kLo = IRTemp_INVALID;
++
++ assign(sJ, getXReg(xj));
++ assign(sK, getXReg(xk));
++ breakupV256toV128s(sJ, &jHi, &jLo);
++ breakupV256toV128s(sK, &kHi, &kLo);
++
++ switch (insSz) {
++ case 0b00: {
++ rHi = gen_vdiv_b(jHi, kHi, isMod, isU);
++ rLo = gen_vdiv_b(jLo, kLo, isMod, isU);
++ break;
++ }
++ case 0b01: {
++ rHi = gen_vdiv_h(jHi, kHi, isMod, isU);
++ rLo = gen_vdiv_h(jLo, kLo, isMod, isU);
++ break;
++ }
++ case 0b10: {
++ rHi = gen_vdiv_w(jHi, kHi, isMod, isU);
++ rLo = gen_vdiv_w(jLo, kLo, isMod, isU);
++ break;
++ }
++ case 0b11: {
++ rHi = gen_vdiv_d(jHi, kHi, isMod, isU);
++ rLo = gen_vdiv_d(jLo, kLo, isMod, isU);
++ break;
++ }
++ default: vassert(0);
++ }
+
++ UInt id = isU ? (insSz + 4) : insSz;
++ const HChar *nm[2] = { "xvdiv", "xvmod" };
++ DIP("%s.%s %s, %s\n", nm[isMod], mkInsSize(id),
++ nameXReg(xd), nameXReg(xj));
++ putXReg(xd, mkV256from128s(rHi, rLo));
+ return True;
+}
+
-+static Bool gen_xvst ( DisResult* dres, UInt insn,
++static IRTemp vsat_u ( IRTemp src, UInt insSz, UInt uImm )
++{
++ IRTemp val = newTemp(Ity_V128);
++ IRTemp res = newTemp(Ity_V128);
++ UInt sarNum[4] = {7, 15, 31, 63};
++
++ if (uImm == sarNum[insSz])
++ return src;
++
++ assign(val, binop(mkV128CMPEQ(insSz),
++ binop(mkV128SHRN(insSz),
++ EX(src), mkU8(uImm + 1)),
++ mkV128(0x0000)));
++ assign(res, binop(Iop_OrV128,
++ binop(Iop_AndV128, EX(val), EX(src)),
++ binop(mkV128SHRN(insSz),
++ unop(Iop_NotV128, EX(val)),
++ mkU8(sarNum[insSz] - uImm))));
++ return res;
++}
++
++static IRTemp vsat_s ( IRTemp src, UInt insSz, UInt uImm )
++{
++ IRTemp val = newTemp(Ity_V128);
++ IRTemp tmp = newTemp(Ity_V128);
++ IRTemp res = newTemp(Ity_V128);
++ UInt shrNum[4] = {8, 16, 32, 64};
++ UInt sarNum[4] = {7, 15, 31, 63};
++
++ assign(val, binop(mkV128SARN(insSz),
++ EX(src), mkU8(sarNum[insSz])));
++
++ if (uImm == 0)
++ return val;
++
++ assign(tmp, binop(mkV128SARN(insSz), EX(src), mkU8(uImm)));
++ assign(res, binop(Iop_OrV128,
++ binop(Iop_OrV128,
++ binop(Iop_AndV128,
++ binop(mkV128CMPEQ(insSz),
++ EX(val), EX(tmp)),
++ EX(src)),
++ binop(mkV128SHLN(insSz),
++ binop(mkV128CMPGTS(insSz),
++ EX(val), EX(tmp)),
++ mkU8(uImm))),
++ binop(mkV128SHRN(insSz),
++ binop(mkV128CMPGTS(insSz),
++ EX(tmp), EX(val)),
++ mkU8(shrNum[insSz] - uImm))));
++ return res;
++}
++
++static Bool gen_vsat ( DisResult* dres, UInt insn,
+ const VexArchInfo* archinfo,
+ const VexAbiInfo* abiinfo )
+{
-+ UInt si12 = SLICE(insn, 21, 10);
-+ UInt rj = SLICE(insn, 9, 5);
-+ UInt xd = SLICE(insn, 4, 0);
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
++ UInt isS = SLICE(insn, 18, 18);
+
-+ DIP("xvst %s, %s, %d\n", nameXReg(xd), nameIReg(rj),
-+ (Int)extend32(si12, 12));
++ UInt insSz, uImm;
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp arg = newTemp(Ity_V128);
++ assign(arg, getVReg(vj));
+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
++ if ((insImm & 0xf8) == 0x8) { // 00001mmm; b
++ uImm = insImm & 0x07;
++ insSz = 0;
++ } else if ((insImm & 0xf0) == 0x10) { // 0001mmmm; h
++ uImm = insImm & 0x0f;
++ insSz = 1;
++ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; w
++ uImm = insImm & 0x1f;
++ insSz = 2;
++ } else if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; d
++ uImm = insImm & 0x3f;
++ insSz = 3;
++ } else {
++ vassert(0);
+ }
+
-+ IRExpr* addr = binop(Iop_Add64, getIReg64(rj), mkU64(extend64(si12, 12)));
-+ store(addr, getXReg(xd));
-+
++ res = isS ? vsat_s(arg, insSz, uImm) : vsat_u(arg, insSz, uImm);
++ UInt nmId = isS ? insSz : (insSz + 4);
++ DIP("vsat.%s %s, %u\n", mkInsSize(nmId), nameVReg(vd), uImm);
++ putVReg(vd, EX(res));
+ return True;
+}
+
-+static Bool gen_vstelm ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvsat ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ UInt vd = SLICE(insn, 4, 0);
-+ UInt rj = SLICE(insn, 9, 5);
-+ UInt si8 = SLICE(insn, 17, 10);
-+ UInt insImm = SLICE(insn, 23, 18);
-+
-+ IRExpr* addr;
-+ UInt idx, insSz;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
++ UInt isS = SLICE(insn, 18, 18);
+
-+ if ((insImm & 0x30) == 0x20) { // 10_idx; b
-+ idx = insImm & 0xf;
++ UInt insSz, uImm;
++ if ((insImm & 0xf8) == 0x8) { // 00001mmm; b
++ uImm = insImm & 0x07;
+ insSz = 0;
-+ } else if ((insImm & 0x38) == 0x10) { // 01_idx; h
-+ idx = insImm & 0x7;
++ } else if ((insImm & 0xf0) == 0x10) { // 0001mmmm; h
++ uImm = insImm & 0x0f;
+ insSz = 1;
-+ } else if ((insImm & 0x3c) == 0x8) { // 001_idx; w
-+ idx = insImm & 0x3;
++ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; w
++ uImm = insImm & 0x1f;
+ insSz = 2;
-+ } else if ((insImm & 0x3e) == 0x4) { // 0001_idx; d
-+ idx = insImm & 0x1;
++ } else if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; d
++ uImm = insImm & 0x3f;
+ insSz = 3;
+ } else {
-+ return False;
++ vassert(0);
+ }
+
-+ switch (insSz) {
-+ case 0b00:
-+ addr = binop(Iop_Add64,
-+ getIReg64(rj),
-+ mkU64(extend64(si8, 8)));
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp jHi = IRTemp_INVALID;
++ IRTemp jLo = IRTemp_INVALID;
++ assign(sJ, getXReg(xj));
++ breakupV256toV128s(sJ, &jHi, &jLo);
++
++ rHi = isS ? vsat_s(jHi, insSz, uImm) : vsat_u(jHi, insSz, uImm);
++ rLo = isS ? vsat_s(jLo, insSz, uImm) : vsat_u(jLo, insSz, uImm);
++ UInt nmId = isS ? insSz : (insSz + 4);
++ DIP("xvsat.%s %s, %u\n", mkInsSize(nmId), nameXReg(xd), uImm);
++ putXReg(xd, mkV256from128s(rHi, rLo));
++ return True;
++}
++
++static Bool gen_vexth ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt insSz = SLICE(insn, 11, 10);
++ UInt isU = SLICE(insn, 12, 12);
++
++ IROp op = isU ? mkV128EXTHTU(insSz) : mkV128EXTHTS(insSz);
++ UInt id = isU ? (insSz + 4) : insSz;
++ DIP("vexth.%s %s, %s\n", mkInsSize(id), nameVReg(vd), nameVReg(vj));
++ putVReg(vd, unop(op, getVReg(vj)));
++ return True;
++}
++
++static Bool gen_xvexth ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insSz = SLICE(insn, 11, 10);
++ UInt isU = SLICE(insn, 12, 12);
++
++ IROp op = isU ? mkV256EXTHTU(insSz) : mkV256EXTHTS(insSz);
++ UInt id = isU ? (insSz + 4) : insSz;
++ DIP("xvexth.%s %s, %s\n", mkInsSize(id), nameXReg(xd), nameXReg(xj));
++ putXReg(xd, unop(op, getXReg(xj)));
++ return True;
++}
++
++static Bool gen_vext2xv ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insTy = SLICE(insn, 13, 10);
++
++ const HChar *ns;
++ IROp w128 = Iop_INVALID;
++ IROp w256 = Iop_INVALID;
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp sLo = newTemp(Ity_V128);
++ IRTemp z128 = newTemp(Ity_V128);
++ IRTemp sL64 = newTemp(Ity_V128);
++ IRTemp sH64 = newTemp(Ity_V128);
++ assign(z128, mkV128(0x0000));
++ assign(sLo, unop(Iop_V256toV128_0, getXReg(xj)));
++ assign(sL64, binop(Iop_InterleaveLO64x2, EX(sLo), EX(z128)));
++ assign(sH64, binop(Iop_InterleaveHI64x2, EX(sLo), EX(z128)));
++
++ switch (insTy) {
++ case 0b0100: case 0b1010: {
++ ns = (insTy == 0b0100) ? "h.b" : "hu.bu";
++ w256 = (insTy == 0b0100) ? Iop_WidenHIto16Sx16 : Iop_WidenHIto16Ux16;
++ assign(res, unop(w256, mkV256from128s(sH64, sL64)));
+ break;
-+ case 0b01:
-+ addr = binop(Iop_Add64,
-+ getIReg64(rj),
-+ mkU64(extend64(si8 << 1, 9)));
++ }
++ case 0b0101: case 0b1011: {
++ IRTemp t1 = newTemp(Ity_V128);
++ IRTemp t1Lo = newTemp(Ity_V128);
++ IRTemp t1Hi = newTemp(Ity_V128);
++ ns = (insTy == 0b0101) ? "w.b" : "wu.bu";
++ w128 = (insTy == 0b0101) ? Iop_WidenHIto16Sx8 : Iop_WidenHIto16Ux8;
++ w256 = (insTy == 0b0101) ? Iop_WidenHIto32Sx8 : Iop_WidenHIto32Ux8;
++ assign(t1, unop(w128, EX(sL64)));
++ assign(t1Lo, binop(Iop_InterleaveLO64x2, EX(t1), EX(z128)));
++ assign(t1Hi, binop(Iop_InterleaveHI64x2, EX(t1), EX(z128)));
++ assign(res, unop(w256, mkV256from128s(t1Hi, t1Lo)));
+ break;
-+ case 0b10:
-+ addr = binop(Iop_Add64,
-+ getIReg64(rj),
-+ mkU64(extend64(si8 << 2, 10)));
++ }
++ case 0b0110: case 0b1100: {
++ IRTemp t1 = newTemp(Ity_V128);
++ IRTemp t2 = newTemp(Ity_V128);
++ IRTemp t2Lo = newTemp(Ity_V128);
++ IRTemp t2Hi = newTemp(Ity_V128);
++ ns = (insTy == 0b0110) ? "d.b" : "du.bu";
++ w128 = (insTy == 0b0110) ? Iop_WidenHIto16Sx8 : Iop_WidenHIto16Ux8;
++ w256 = (insTy == 0b0110) ? Iop_WidenHIto64Sx4 : Iop_WidenHIto64Ux4;
++ assign(t1, binop(Iop_InterleaveLO64x2,
++ unop(w128, EX(sL64)), EX(z128)));
++ assign(t2, unop(w128, EX(t1)));
++ assign(t2Lo, binop(Iop_InterleaveLO64x2, EX(t2), EX(z128)));
++ assign(t2Hi, binop(Iop_InterleaveHI64x2, EX(t2), EX(z128)));
++ assign(res, unop(w256, mkV256from128s(t2Hi, t2Lo)));
+ break;
-+ case 0b11:
-+ addr = binop(Iop_Add64,
-+ getIReg64(rj),
-+ mkU64(extend64(si8 << 3, 11)));
++ }
++ case 0b0111: case 0b1101: {
++ ns = (insTy == 0b0111) ? "w.h" : "wu.hu";
++ w256 = (insTy == 0b0111) ? Iop_WidenHIto32Sx8 : Iop_WidenHIto32Ux8;
++ assign(res, unop(w256, mkV256from128s(sH64, sL64)));
+ break;
-+ default:
-+ vassert(0);
++ }
++ case 0b1000: case 0b1110: {
++ IRTemp t1 = newTemp(Ity_V128);
++ IRTemp t1Lo = newTemp(Ity_V128);
++ IRTemp t1Hi = newTemp(Ity_V128);
++ ns = (insTy == 0b1000) ? "d.h" : "du.hu";
++ w128 = (insTy == 0b1000) ? Iop_WidenHIto32Sx4 : Iop_WidenHIto32Ux4;
++ w256 = (insTy == 0b1000) ? Iop_WidenHIto64Sx4 : Iop_WidenHIto64Ux4;
++ assign(t1, unop(w128, EX(sL64)));
++ assign(t1Lo, binop(Iop_InterleaveLO64x2, EX(t1), EX(z128)));
++ assign(t1Hi, binop(Iop_InterleaveHI64x2, EX(t1), EX(z128)));
++ assign(res, unop(w256, mkV256from128s(t1Hi, t1Lo)));
++ break;
++ }
++ case 0b1001: case 0b1111: {
++ ns = (insTy == 0b1001) ? "d.w" : "du.wu";
++ w256 = (insTy == 0b1001) ? Iop_WidenHIto64Sx4 : Iop_WidenHIto64Ux4;
++ assign(res, unop(w256, mkV256from128s(sH64, sL64)));
+ break;
++ }
++ default: vassert(0);
+ }
+
-+ DIP("vstelm.%s %s, %s, %d, %u\n", mkInsSize(insSz), nameVReg(vd), nameIReg(rj),
-+ (Int)extend32(si8, 8), idx);
++ DIP("vext2xv.%s %s, %s\n", ns, nameXReg(xd), nameXReg(xj));
++ putXReg(xd, EX(res));
++ return True;
++}
+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
++static Bool gen_vsigncov ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++
++ IRTemp eq = newTemp(Ity_V128);
++ IRTemp lt = newTemp(Ity_V128);
++ IRTemp gt = newTemp(Ity_V128);
++ IRTemp z128 = newTemp(Ity_V128);
++ assign(z128, mkV128(0x0000));
++ UInt sarNum[4] = {7, 15, 31, 63};
++
++ assign(eq, unop(Iop_NotV128,
++ binop(mkV128CMPEQ(insSz), getVReg(vj), EX(z128))));
++ assign(lt, binop(Iop_AndV128,
++ binop(mkV128SARN(insSz), getVReg(vj), mkU8(sarNum[insSz])),
++ binop(mkV128SUB(insSz), EX(z128), getVReg(vk))));
++ assign(gt, binop(Iop_AndV128,
++ binop(mkV128CMPEQ(insSz),
++ binop(mkV128SARN(insSz), getVReg(vj), mkU8(sarNum[insSz])),
++ EX(z128)),
++ getVReg(vk)));
++
++ DIP("vsigncov.%s %s, %s, %s\n", mkInsSize(insSz), nameVReg(vd),
++ nameVReg(vj), nameVReg(vk));
++ putVReg(vd, binop(Iop_AndV128,
++ binop(Iop_OrV128, mkexpr(lt), mkexpr(gt)),
++ mkexpr(eq)));
++ return True;
++}
+
-+ store(addr, binop(mkVecGetElem(insSz), getVReg(vd), mkU8(idx)));
++static Bool gen_xvsigncov ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
+
++ IRTemp eq = newTemp(Ity_V256);
++ IRTemp lt = newTemp(Ity_V256);
++ IRTemp gt = newTemp(Ity_V256);
++ IRTemp z256 = newTemp(Ity_V256);
++ assign(z256, mkV256(0x0000));
++ UInt sarNum[4] = {7, 15, 31, 63};
++
++ assign(eq, unop(Iop_NotV256,
++ binop(mkV256CMPEQ(insSz), getXReg(xj), EX(z256))));
++ assign(lt, binop(Iop_AndV256,
++ binop(mkV256SARN(insSz), getXReg(xj), mkU8(sarNum[insSz])),
++ binop(mkV256SUB(insSz), EX(z256), getXReg(xk))));
++ assign(gt, binop(Iop_AndV256,
++ binop(mkV256CMPEQ(insSz),
++ binop(mkV256SARN(insSz), getXReg(xj), mkU8(sarNum[insSz])),
++ EX(z256)),
++ getXReg(xk)));
++
++ DIP("xvsigncov.%s %s, %s, %s\n", mkInsSize(insSz), nameXReg(xd),
++ nameXReg(xj), nameXReg(xk));
++ putXReg(xd, binop(Iop_AndV256,
++ binop(Iop_OrV256, mkexpr(lt), mkexpr(gt)),
++ EX(eq)));
+ return True;
+}
+
++static IRTemp gen_vmsk_b ( IRTemp shr )
++{
++ UInt i;
++ IRTemp tmp[16];
++ IRTemp tOr = newTemp(Ity_I32);
++ IRTemp res = newTemp(Ity_V128);
+
-+/*------------------------------------------------------------*/
-+/*--- Disassemble a single LOONGARCH64 instruction ---*/
-+/*------------------------------------------------------------*/
++ for (i = 0; i < 16; i++) {
++ tmp[i] = newTemp(Ity_I32);
++ assign(tmp[i], binop(Iop_Shl32,
++ unop(Iop_8Uto32,
++ binop(Iop_GetElem8x16,
++ mkexpr(shr), mkU8(i))),
++ mkU8(i)));
++ }
+
-+/* Disassemble a single LOONGARCH64 instruction into IR. The instruction
-+ has is located at |guest_instr| and has guest IP of |guest_PC_curr_instr|,
-+ which will have been set before the call here. Returns True iff the
-+ instruction was decoded, in which case *dres will be set accordingly,
-+ or False, in which case *dres should be ignored by the caller. */
++ assign(tOr, binop(Iop_Or32,
++ binop(Iop_Or32,
++ binop(Iop_Or32,
++ binop(Iop_Or32, mkexpr(tmp[15]), mkexpr(tmp[14])),
++ binop(Iop_Or32, mkexpr(tmp[13]), mkexpr(tmp[12]))),
++ binop(Iop_Or32,
++ binop(Iop_Or32, mkexpr(tmp[11]), mkexpr(tmp[10])),
++ binop(Iop_Or32, mkexpr(tmp[9]), mkexpr(tmp[8])))),
++ binop(Iop_Or32,
++ binop(Iop_Or32,
++ binop(Iop_Or32, mkexpr(tmp[7]), mkexpr(tmp[6])),
++ binop(Iop_Or32, mkexpr(tmp[5]), mkexpr(tmp[4]))),
++ binop(Iop_Or32,
++ binop(Iop_Or32, mkexpr(tmp[3]), mkexpr(tmp[2])),
++ binop(Iop_Or32, mkexpr(tmp[1]), mkexpr(tmp[0]))))));
++ assign(res, unop(Iop_64UtoV128, extendU(Ity_I32, mkexpr(tOr))));
+
-+static Bool disInstr_LOONGARCH64_WRK_special ( DisResult* dres,
-+ const UChar* guest_instr )
++ return res;
++}
++
++static IRTemp gen_vmsk_h ( IRTemp shr )
+{
-+ const UChar* code = guest_instr;
-+ /* Spot the 16-byte preamble:
-+ 00450c00 srli.d $zero, $zero, 3
-+ 00453400 srli.d $zero, $zero, 13
-+ 00457400 srli.d $zero, $zero, 29
-+ 00454c00 srli.d $zero, $zero, 19
-+ */
-+ if (getUInt(code + 0) == 0x00450c00 &&
-+ getUInt(code + 4) == 0x00453400 &&
-+ getUInt(code + 8) == 0x00457400 &&
-+ getUInt(code + 12) == 0x00454c00) {
-+ /* Got a "Special" instruction preamble. Which one is it? */
-+ if (getUInt(code + 16) == 0x001535ad) { /* or $t1, $t1, $t1 */
-+ DIP("$a7 = client_request ( $t0 )\n");
-+ putPC(mkU64(guest_PC_curr_instr + 20));
-+ dres->whatNext = Dis_StopHere;
-+ dres->len = 20;
-+ dres->jk_StopHere = Ijk_ClientReq;
-+ return True;
-+ } else if (getUInt(code + 16) == 0x001539ce) { /* or $t2, $t2, $t2 */
-+ DIP("$a7 = guest_NRADDR\n");
-+ putIReg(11, IRExpr_Get(offsetof(VexGuestLOONGARCH64State, guest_NRADDR),
-+ Ity_I64));
-+ dres->len = 20;
-+ return True;
-+ } else if (getUInt(code + 16) == 0x00153def) { /* or $t3, $t3, $t3 */
-+ DIP("branch-and-link-to-noredir $t8\n");
-+ putIReg(1, mkU64(guest_PC_curr_instr + 20));
-+ putPC(getIReg64(20));
-+ dres->whatNext = Dis_StopHere;
-+ dres->len = 20;
-+ dres->jk_StopHere = Ijk_NoRedir;
-+ return True;
-+ } else if (getUInt(code + 16) == 0x00154210) { /* or $t4, $t4, $t4 */
-+ DIP("IR injection\n");
-+ vex_inject_ir(irsb, Iend_LE);
-+ /* Invalidate the current insn. The reason is that the IRop we're
-+ injecting here can change. In which case the translation has to
-+ be redone. For ease of handling, we simply invalidate all the
-+ time.
-+ */
-+ stmt(IRStmt_Put(offsetof(VexGuestLOONGARCH64State, guest_CMSTART),
-+ mkU64(guest_PC_curr_instr)));
-+ stmt(IRStmt_Put(offsetof(VexGuestLOONGARCH64State, guest_CMLEN),
-+ mkU64(20)));
-+ putPC(mkU64(guest_PC_curr_instr + 20));
-+ dres->whatNext = Dis_StopHere;
-+ dres->len = 20;
-+ dres->jk_StopHere = Ijk_InvalICache;
-+ return True;
-+ }
-+ /* We don't know what it is. */
-+ vassert(0);
-+ /*NOTREACHED*/
++ UInt i;
++ IRTemp tmp[8];
++ IRTemp tOr = newTemp(Ity_I32);
++ IRTemp res = newTemp(Ity_V128);
++
++ for (i = 0; i < 8; i++) {
++ tmp[i] = newTemp(Ity_I32);
++ assign(tmp[i], binop(Iop_Shl32,
++ unop(Iop_16Uto32,
++ binop(Iop_GetElem16x8,
++ mkexpr(shr), mkU8(i))),
++ mkU8(i)));
+ }
-+ return False;
++
++ assign(tOr, binop(Iop_Or32,
++ binop(Iop_Or32,
++ binop(Iop_Or32, mkexpr(tmp[7]), mkexpr(tmp[6])),
++ binop(Iop_Or32, mkexpr(tmp[5]), mkexpr(tmp[4]))),
++ binop(Iop_Or32,
++ binop(Iop_Or32, mkexpr(tmp[3]), mkexpr(tmp[2])),
++ binop(Iop_Or32, mkexpr(tmp[1]), mkexpr(tmp[0])))));
++ assign(res, unop(Iop_64UtoV128, extendU(Ity_I32, mkexpr(tOr))));
++
++ return res;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_00_0000_0000 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static IRTemp gen_vmsk_w ( IRTemp shr )
+{
-+ Bool ok;
++ UInt i;
++ IRTemp tmp[4];
++ IRTemp tOr = newTemp(Ity_I32);
++ IRTemp res = newTemp(Ity_V128);
+
-+ switch (SLICE(insn, 21, 15)) {
-+ case 0b0000000:
-+ switch (SLICE(insn, 14, 10)) {
-+ case 0b00100:
-+ ok = gen_clo_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b00101:
-+ ok = gen_clz_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b00110:
-+ ok = gen_cto_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b00111:
-+ ok = gen_ctz_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01000:
-+ ok = gen_clo_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01001:
-+ ok = gen_clz_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01010:
-+ ok = gen_cto_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01011:
-+ ok = gen_ctz_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01100:
-+ ok = gen_revb_2h(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01101:
-+ ok = gen_revb_4h(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01110:
-+ ok = gen_revb_2w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01111:
-+ ok = gen_revb_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10000:
-+ ok = gen_revh_2w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10001:
-+ ok = gen_revh_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10010:
-+ ok = gen_bitrev_4b(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10011:
-+ ok = gen_bitrev_8b(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10100:
-+ ok = gen_bitrev_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10101:
-+ ok = gen_bitrev_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10110:
-+ ok = gen_ext_w_h(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10111:
-+ ok = gen_ext_w_b(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b11000:
-+ ok = gen_rdtimel_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b11001:
-+ ok = gen_rdtimeh_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b11010:
-+ ok = gen_rdtime_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b11011:
-+ ok = gen_cpucfg(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ for (i = 0; i < 4; i++) {
++ tmp[i] = newTemp(Ity_I32);
++ assign(tmp[i], binop(Iop_Shl32,
++ binop(Iop_GetElem32x4,
++ mkexpr(shr), mkU8(i)),
++ mkU8(i)));
++ }
++ assign(tOr, binop(Iop_Or32,
++ binop(Iop_Or32, mkexpr(tmp[3]), mkexpr(tmp[2])),
++ binop(Iop_Or32, mkexpr(tmp[1]), mkexpr(tmp[0]))));
++
++ assign(res, unop(Iop_64UtoV128, extendU(Ity_I32, mkexpr(tOr))));
++
++ return res;
++}
++
++static IRTemp gen_vmsk_d ( IRTemp shr )
++{
++ UInt i;
++ IRTemp tmp[2];
++ IRTemp res = newTemp(Ity_V128);
++
++ for (i = 0; i < 2; i++) {
++ tmp[i] = newTemp(Ity_I64);
++ assign(tmp[i], binop(Iop_Shl64,
++ binop(Iop_GetElem64x2,
++ mkexpr(shr), mkU8(i)),
++ mkU8(i)));
++ }
++ assign(res, unop(Iop_64UtoV128,
++ binop(Iop_Or64,mkexpr(tmp[1]), mkexpr(tmp[0]))));
++
++ return res;
++}
++
++static Bool gen_vmsk ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt insSz = SLICE(insn, 11, 10);
++ UInt insTy = SLICE(insn, 13, 12);
++
++ IRTemp shr = newTemp(Ity_V128);
++ IRTemp cmp = newTemp(Ity_V128);
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp src = newTemp(Ity_V128);
++ assign(src, getVReg(vj));
++
++ switch (insTy) {
++ case 0b00: {
++ UInt shrNum[4] = {7, 15, 31, 63};
++
++ DIP("vmskltz.%s %s, %s\n", mkInsSize(insSz), nameVReg(vd), nameVReg(vj));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
++
++ assign(cmp, binop(mkV128CMPGTS(insSz), mkV128(0x0000), mkexpr(src)));
++ assign(shr, binop(mkV128SHRN(insSz), mkexpr(cmp), mkU8(shrNum[insSz])));
++
++ switch(insSz) {
++ case 0b00: res = gen_vmsk_b(shr); break;
++ case 0b01: res = gen_vmsk_h(shr); break;
++ case 0b10: res = gen_vmsk_w(shr); break;
++ case 0b11: res = gen_vmsk_d(shr); break;
++ default: vassert(0); break;
+ }
+ break;
-+ case 0b0000010:
-+ ok = gen_asrtle_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0000011:
-+ ok = gen_asrtgt_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100000:
-+ ok = gen_add_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100001:
-+ ok = gen_add_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100010:
-+ ok = gen_sub_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100011:
-+ ok = gen_sub_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100100:
-+ ok = gen_slt(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100101:
-+ ok = gen_sltu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100110:
-+ ok = gen_maskeqz(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100111:
-+ ok = gen_masknez(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0101000:
-+ ok = gen_nor(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0101001:
-+ ok = gen_and(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0101010:
-+ ok = gen_or(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0101011:
-+ ok = gen_xor(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0101100:
-+ ok = gen_orn(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0101101:
-+ ok = gen_andn(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0101110:
-+ ok = gen_sll_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0101111:
-+ ok = gen_srl_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0110000:
-+ ok = gen_sra_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0110001:
-+ ok = gen_sll_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0110010:
-+ ok = gen_srl_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0110011:
-+ ok = gen_sra_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0110110:
-+ ok = gen_rotr_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0110111:
-+ ok = gen_rotr_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0111000:
-+ ok = gen_mul_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0111001:
-+ ok = gen_mulh_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0111010:
-+ ok = gen_mulh_wu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0111011:
-+ ok = gen_mul_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0111100:
-+ ok = gen_mulh_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0111101:
-+ ok = gen_mulh_du(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0111110:
-+ ok = gen_mulw_d_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0111111:
-+ ok = gen_mulw_d_wu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000000:
-+ ok = gen_div_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000001:
-+ ok = gen_mod_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000010:
-+ ok = gen_div_wu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000011:
-+ ok = gen_mod_wu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000100:
-+ ok = gen_div_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000101:
-+ ok = gen_mod_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000110:
-+ ok = gen_div_du(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000111:
-+ ok = gen_mod_du(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001000:
-+ ok = gen_crc_w_b_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001001:
-+ ok = gen_crc_w_h_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001010:
-+ ok = gen_crc_w_w_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001011:
-+ ok = gen_crc_w_d_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001100:
-+ ok = gen_crcc_w_b_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001101:
-+ ok = gen_crcc_w_h_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001110:
-+ ok = gen_crcc_w_w_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001111:
-+ ok = gen_crcc_w_d_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1010100:
-+ ok = gen_break(dres, insn, archinfo, abiinfo);
++ }
++
++ case 0b01: {
++ DIP("vmskgez.b %s, %s\n", nameVReg(vd), nameVReg(vj));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
++
++ assign(cmp, binop(Iop_OrV128,
++ binop(Iop_CmpGT8Sx16, mkexpr(src), mkV128(0x0000)),
++ binop(Iop_CmpEQ8x16, mkV128(0x0000), mkexpr(src))));
++ assign(shr, binop(Iop_ShrN8x16, mkexpr(cmp), mkU8(7)));
++ res = gen_vmsk_b(shr);
+ break;
-+ case 0b1010110:
-+ ok = gen_syscall(dres, insn, archinfo, abiinfo);
++ }
++
++ case 0b10: {
++ DIP("vmsknz.b %s, %s\n", nameVReg(vd), nameVReg(vj));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
++ assign(cmp, unop(Iop_NotV128,
++ binop(Iop_CmpEQ8x16, mkV128(0x0000), mkexpr(src))));
++ assign(shr, binop(Iop_ShrN8x16, EX(cmp), mkU8(7)));
++ res = gen_vmsk_b(shr);
+ break;
++ }
++
+ default:
-+ ok = False;
-+ break;
++ return False;
+ }
+
-+ if (ok)
-+ return ok;
++ putVReg(vd, mkexpr(res));
+
-+ switch (SLICE(insn, 21, 18)) {
-+ case 0b0001:
-+ if (SLICE(insn, 17, 17) == 0) {
-+ ok = gen_alsl_w(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = gen_alsl_wu(dres, insn, archinfo, abiinfo);
++ return True;
++}
++
++static Bool gen_xvmsk ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insSz = SLICE(insn, 11, 10);
++ UInt insTy = SLICE(insn, 13, 12);
++
++ IRTemp shr = newTemp(Ity_V256);
++ IRTemp cmp = newTemp(Ity_V256);
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp src = newTemp(Ity_V256);
++ assign(src, getXReg(xj));
++
++ switch (insTy) {
++ case 0b00: {
++ UInt shrNum[4] = {7, 15, 31, 63};
++
++ DIP("xvmskltz.%s %s, %s\n", mkInsSize(insSz), nameXReg(xd), nameXReg(xj));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
-+ break;
-+ case 0b0010:
-+ if (SLICE(insn, 17, 17) == 0) {
-+ ok = gen_bytepick_w(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = False;
++
++ assign(cmp, binop(mkV256CMPGTS(insSz), mkV256(0x0000), EX(src)));
++ assign(shr, binop(mkV256SHRN(insSz), EX(cmp), mkU8(shrNum[insSz])));
++ IRTemp hi, lo;
++ hi = lo = IRTemp_INVALID;
++ breakupV256toV128s(shr, &hi, &lo);
++
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ switch(insSz) {
++ case 0b00: {
++ rHi = gen_vmsk_b(hi);
++ rLo = gen_vmsk_b(lo);
++ break;
++ }
++ case 0b01: {
++ rHi = gen_vmsk_h(hi);
++ rLo = gen_vmsk_h(lo);
++ break;
++ }
++ case 0b10: {
++ rHi = gen_vmsk_w(hi);
++ rLo = gen_vmsk_w(lo);
++ break;
++ }
++ case 0b11: {
++ rHi = gen_vmsk_d(hi);
++ rLo = gen_vmsk_d(lo);
++ break;
++ }
++ default: vassert(0);
+ }
++
++ assign(res, mkV256from128s(rHi, rLo));
+ break;
-+ case 0b0011:
-+ ok = gen_bytepick_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1011:
-+ if (SLICE(insn, 17, 17) == 0) {
-+ ok = gen_alsl_d(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = False;
++ }
++ case 0b01: {
++ DIP("xvmskgez.b %s, %s\n", nameXReg(xd), nameXReg(xj));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
++
++ assign(cmp, binop(Iop_OrV256,
++ binop(Iop_CmpGT8Sx32, EX(src), mkV256(0x0000)),
++ binop(Iop_CmpEQ8x32, mkV256(0x0000), EX(src))));
++ assign(shr, binop(Iop_ShrN8x32, EX(cmp), mkU8(7)));
++ IRTemp hi, lo;
++ hi = lo = IRTemp_INVALID;
++ breakupV256toV128s(shr, &hi, &lo);
++ assign(res, mkV256from128s(gen_vmsk_b(hi), gen_vmsk_b(lo)));
+ break;
-+ default:
-+ ok = False;
++ }
++ case 0b10: {
++ DIP("xvmsknz.b %s, %s\n", nameXReg(xd), nameXReg(xj));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
++
++ assign(cmp, unop(Iop_NotV256,
++ binop(Iop_CmpEQ8x32, mkV256(0x0000), EX(src))));
++ assign(shr, binop(Iop_ShrN8x32, EX(cmp), mkU8(7)));
++
++ IRTemp hi, lo;
++ hi = lo = IRTemp_INVALID;
++ breakupV256toV128s(shr, &hi, &lo);
++ assign(res, mkV256from128s(gen_vmsk_b(hi), gen_vmsk_b(lo)));
+ break;
++ }
++ default: vassert(0);
+ }
+
-+ return ok;
++ putXReg(xd, mkexpr(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_00_0000_0001 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vldi ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt vd = SLICE(insn, 4, 0);
++ Int i13 = SLICE(insn, 17, 5);
++ UInt isX = SLICE(insn, 26, 26);
+
-+ if (SLICE(insn, 21, 21) == 0) {
-+ switch (SLICE(insn, 20, 16)) {
-+ case 0b00000:
-+ if (SLICE(insn, 15, 15) == 1) {
-+ ok = gen_slli_w(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = False;
-+ }
++ UInt i;
++ IRExpr *irex;
++ IRTemp data = newTemp(Ity_I64);
++ UInt immX = SLICE(i13, 5, 0);
++ UChar imm8 = SLICE(i13, 7, 0);
++ UShort imm10 = (SLICE(i13, 9, 9) == 0b1) ?
++ (SLICE(i13, 9, 0) | 0xfc00): SLICE(i13, 9, 0);
++
++ if (SLICE(i13, 12, 12) == 0) {
++ switch (SLICE(i13, 11, 10)) {
++ case 0b00: {
++ irex = binop(Iop_8HLto16, mkU8(imm8), mkU8(imm8));
++ assign(data, binop(Iop_32HLto64,
++ binop(Iop_16HLto32, irex, irex),
++ binop(Iop_16HLto32, irex, irex)));
+ break;
-+ case 0b00001:
-+ ok = gen_slli_d(dres, insn, archinfo, abiinfo);
++ }
++ case 0b01: {
++ irex = binop(Iop_16HLto32, mkU16(imm10), mkU16(imm10));
++ assign(data, binop(Iop_32HLto64, irex, irex));
+ break;
-+ case 0b00100:
-+ if (SLICE(insn, 15, 15) == 1) {
-+ ok = gen_srli_w(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = False;
-+ }
++ }
++ case 0b10: {
++ irex = unop(Iop_16Sto32, mkU16(imm10));
++ assign(data, binop(Iop_32HLto64, irex, irex));
+ break;
-+ case 0b00101:
-+ ok = gen_srli_d(dres, insn, archinfo, abiinfo);
++ }
++ case 0b11: {
++ assign(data, extendS(Ity_I16, mkU16(imm10)));
+ break;
-+ case 0b01000:
-+ if (SLICE(insn, 15, 15) == 1) {
-+ ok = gen_srai_w(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = False;
-+ }
++ }
++ default: vassert(0);
++ }
++ } else {
++ switch (SLICE(i13, 11, 8)) {
++ case 0b0000: {
++ assign(data, binop(Iop_32HLto64,
++ unop(Iop_8Uto32, mkU8(imm8)),
++ unop(Iop_8Uto32, mkU8(imm8))));
+ break;
-+ case 0b01001:
-+ ok = gen_srai_d(dres, insn, archinfo, abiinfo);
++ }
++ case 0b0001: {
++ irex = binop(Iop_Shl32, unop(Iop_8Uto32, mkU8(imm8)), mkU8(0x8));
++ assign(data, binop(Iop_32HLto64, irex, irex));
+ break;
-+ case 0b01100:
-+ if (SLICE(insn, 15, 15) == 1) {
-+ ok = gen_rotri_w(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = False;
-+ }
++ }
++ case 0b0010: {
++ irex = binop(Iop_Shl32, unop(Iop_8Uto32, mkU8(imm8)), mkU8(0x10));
++ assign(data, binop(Iop_32HLto64, irex, irex));
+ break;
-+ case 0b01101:
-+ ok = gen_rotri_d(dres, insn, archinfo, abiinfo);
++ }
++ case 0b0011: {
++ irex = binop(Iop_Shl32, unop(Iop_8Uto32, mkU8(imm8)), mkU8(0x18));
++ assign(data, binop(Iop_32HLto64, irex, irex));
+ break;
-+ default:
-+ ok = False;
++ }
++ case 0b0100: {
++ irex = unop(Iop_8Uto16, mkU8(imm8));
++ assign(data, binop(Iop_32HLto64,
++ binop(Iop_16HLto32, irex, irex),
++ binop(Iop_16HLto32, irex, irex)));
+ break;
-+ }
-+ } else {
-+ if (SLICE(insn, 15, 15) == 0) {
-+ ok = gen_bstrins_w(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = gen_bstrpick_w(dres, insn, archinfo, abiinfo);
++ }
++ case 0b0101: {
++ irex = binop(Iop_Shl16, unop(Iop_8Uto16, mkU8(imm8)), mkU8(0x8));
++ assign(data, binop(Iop_32HLto64,
++ binop(Iop_16HLto32, irex, irex),
++ binop(Iop_16HLto32, irex, irex)));
++ break;
++ }
++ case 0b0110: {
++ irex = binop(Iop_Or16,
++ binop(Iop_Shl16,
++ unop(Iop_8Uto16, mkU8(imm8)),
++ mkU8(0x8)),
++ mkU16(0xff));
++ assign(data, binop(Iop_32HLto64,
++ binop(Iop_16HLto32, mkU16(0), irex),
++ binop(Iop_16HLto32, mkU16(0), irex)));
++ break;
++ }
++ case 0b0111: {
++ irex = binop(Iop_16HLto32,
++ unop(Iop_8Uto16, mkU8(imm8)),
++ mkU16(0xffff));
++ assign(data, binop(Iop_32HLto64, irex, irex));
++ break;
++ }
++ case 0b1000: {
++ irex = binop(Iop_8HLto16, mkU8(imm8), mkU8(imm8));
++ assign(data, binop(Iop_32HLto64,
++ binop(Iop_16HLto32, irex, irex),
++ binop(Iop_16HLto32, irex, irex)));
++ break;
++ }
++ case 0b1001: {
++ assign(data,
++ binop(Iop_32HLto64,
++ binop(Iop_16HLto32,
++ binop(Iop_8HLto16,
++ unop(Iop_1Sto8, mkU1(SLICE(i13, 7, 7))),
++ unop(Iop_1Sto8, mkU1(SLICE(i13, 6, 6)))),
++ binop(Iop_8HLto16,
++ unop(Iop_1Sto8, mkU1(SLICE(i13, 5, 5))),
++ unop(Iop_1Sto8, mkU1(SLICE(i13, 4, 4))))),
++ binop(Iop_16HLto32,
++ binop(Iop_8HLto16,
++ unop(Iop_1Sto8, mkU1(SLICE(i13, 3, 3))),
++ unop(Iop_1Sto8, mkU1(SLICE(i13, 2, 2)))),
++ binop(Iop_8HLto16,
++ unop(Iop_1Sto8, mkU1(SLICE(i13, 1, 1))),
++ unop(Iop_1Sto8, mkU1(SLICE(i13, 0, 0)))))));
++ break;
++ }
++ case 0b1010: {
++ for (i = 6; i < 11; i++)
++ immX |= SLICE(i13, 6, 6) << i;
++ immX |= !SLICE(i13, 6, 6) << 11 | SLICE(i13, 7, 7) << 12;
++ immX <<= 19;
++ assign(data, binop(Iop_32HLto64, mkU32(immX), mkU32(immX)));
++ break;
++ }
++ case 0b1011: {
++ for (i = 6; i < 11; i++)
++ immX |= SLICE(i13, 6, 6) << i;
++ immX |= !SLICE(i13, 6, 6) << 11 | SLICE(i13, 7, 7) << 12;
++ immX <<= 19;
++ assign(data, extendU(Ity_I32, mkU32(immX)));
++ break;
++ }
++ case 0b1100: {
++ for (i = 6; i < 14; i++)
++ immX |= SLICE(i13, 6, 6) << i;
++ immX |= !SLICE(i13, 6, 6) << 14 | SLICE(i13, 7, 7) << 15;
++ assign(data, binop(Iop_Shl64, extendU(Ity_I32, mkU32(immX)), mkU8(0x30)));
++ break;
++ }
++ default: vassert(0);
+ }
+ }
+
-+ return ok;
++ if (isX) {
++ DIP("xvldi %s, %d\n", nameXReg(vd), i13);
++ putXReg(vd, mkV256from64s(data, data, data, data));
++ } else {
++ DIP("vldi %s, %d\n", nameVReg(vd), i13);
++ putVReg(vd, mkV128from64s(data, data));
++ }
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_00_0000_0100 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++/*------------------------------------------------------------*/
++/*--- Helpers for vector bit operation insns ---*/
++/*------------------------------------------------------------*/
++
++static Bool gen_logical_v ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insTy = SLICE(insn, 17, 15);
+
-+ switch (SLICE(insn, 21, 15)) {
-+ case 0b0000001:
-+ ok = gen_fadd_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0000010:
-+ ok = gen_fadd_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0000101:
-+ ok = gen_fsub_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0000110:
-+ ok = gen_fsub_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0001001:
-+ ok = gen_fmul_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0001010:
-+ ok = gen_fmul_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0001101:
-+ ok = gen_fdiv_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0001110:
-+ ok = gen_fdiv_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0010001:
-+ ok = gen_fmax_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0010010:
-+ ok = gen_fmax_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0010101:
-+ ok = gen_fmin_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0010110:
-+ ok = gen_fmin_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0011001:
-+ ok = gen_fmaxa_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0011010:
-+ ok = gen_fmaxa_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0011101:
-+ ok = gen_fmina_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0011110:
-+ ok = gen_fmina_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100001:
-+ ok = gen_fscaleb_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100010:
-+ ok = gen_fscaleb_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100101:
-+ ok = gen_fcopysign_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100110:
-+ ok = gen_fcopysign_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0101000:
-+ switch (SLICE(insn, 14, 10)) {
-+ case 0b00001:
-+ ok = gen_fabs_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b00010:
-+ ok = gen_fabs_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b00101:
-+ ok = gen_fneg_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b00110:
-+ ok = gen_fneg_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01001:
-+ ok = gen_flogb_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01010:
-+ ok = gen_flogb_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01101:
-+ ok = gen_fclass_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01110:
-+ ok = gen_fclass_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10001:
-+ ok = gen_fsqrt_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10010:
-+ ok = gen_fsqrt_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10101:
-+ ok = gen_frecip_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10110:
-+ ok = gen_frecip_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b11001:
-+ ok = gen_frsqrt_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b11010:
-+ ok = gen_frsqrt_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
-+ break;
-+ case 0b0101001:
-+ switch (SLICE(insn, 14, 10)) {
-+ case 0b00101:
-+ ok = gen_fmov_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b00110:
-+ ok = gen_fmov_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01001:
-+ ok = gen_movgr2fr_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01010:
-+ ok = gen_movgr2fr_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01011:
-+ ok = gen_movgr2frh_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01101:
-+ ok = gen_movfr2gr_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01110:
-+ ok = gen_movfr2gr_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01111:
-+ ok = gen_movfrh2gr_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10000:
-+ ok = gen_movgr2fcsr(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10010:
-+ ok = gen_movfcsr2gr(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10100:
-+ if (SLICE(insn, 4, 3) == 0b00) {
-+ ok = gen_movfr2cf(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = False;
-+ }
-+ break;
-+ case 0b10101:
-+ if (SLICE(insn, 9, 8) == 0b00) {
-+ ok = gen_movcf2fr(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = False;
-+ }
-+ break;
-+ case 0b10110:
-+ if (SLICE(insn, 4, 3) == 0b00) {
-+ ok = gen_movgr2cf(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = False;
-+ }
-+ break;
-+ case 0b10111:
-+ if (SLICE(insn, 9, 8) == 0b00) {
-+ ok = gen_movcf2gr(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = False;
-+ }
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
-+ break;
-+ case 0b0110010:
-+ switch (SLICE(insn, 14, 10)) {
-+ case 0b00110:
-+ ok = gen_fcvt_s_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01001:
-+ ok = gen_fcvt_d_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp srcL = newTemp(Ity_V128);
++ IRTemp srcR = newTemp(Ity_V128);
++ assign(srcL, getVReg(vj));
++ assign(srcR, getVReg(vk));
++
++ switch (insTy) {
++ case 0b100:
++ assign(res, binop(Iop_AndV128, mkexpr(srcL), mkexpr(srcR)));
+ break;
-+ case 0b0110100:
-+ switch (SLICE(insn, 14, 10)) {
-+ case 0b00001:
-+ ok = gen_ftintrm_w_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b00010:
-+ ok = gen_ftintrm_w_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01001:
-+ ok = gen_ftintrm_l_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01010:
-+ ok = gen_ftintrm_l_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10001:
-+ ok = gen_ftintrp_w_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10010:
-+ ok = gen_ftintrp_w_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b11001:
-+ ok = gen_ftintrp_l_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b11010:
-+ ok = gen_ftintrp_l_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
++ case 0b101:
++ assign(res, binop(Iop_OrV128, mkexpr(srcL), mkexpr(srcR)));
+ break;
-+ case 0b0110101:
-+ switch (SLICE(insn, 14, 10)) {
-+ case 0b00001:
-+ ok = gen_ftintrz_w_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b00010:
-+ ok = gen_ftintrz_w_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01001:
-+ ok = gen_ftintrz_l_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01010:
-+ ok = gen_ftintrz_l_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10001:
-+ ok = gen_ftintrne_w_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10010:
-+ ok = gen_ftintrne_w_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b11001:
-+ ok = gen_ftintrne_l_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b11010:
-+ ok = gen_ftintrne_l_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
++ case 0b110:
++ assign(res, binop(Iop_XorV128, mkexpr(srcL), mkexpr(srcR)));
+ break;
-+ case 0b0110110:
-+ switch (SLICE(insn, 14, 10)) {
-+ case 0b00001:
-+ ok = gen_ftint_w_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b00010:
-+ ok = gen_ftint_w_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01001:
-+ ok = gen_ftint_l_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01010:
-+ ok = gen_ftint_l_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
++ case 0b111:
++ assign(res, unop(Iop_NotV128, binop(Iop_OrV128,
++ mkexpr(srcL), mkexpr(srcR))));
+ break;
-+ case 0b0111010:
-+ switch (SLICE(insn, 14, 10)) {
-+ case 0b00100:
-+ ok = gen_ffint_s_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b00110:
-+ ok = gen_ffint_s_l(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01000:
-+ ok = gen_ffint_d_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01010:
-+ ok = gen_ffint_d_l(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
++ case 0b000:
++ assign(res, binop(Iop_AndV128,
++ unop(Iop_NotV128, mkexpr(srcL)),
++ mkexpr(srcR)));
+ break;
-+ case 0b0111100:
-+ switch (SLICE(insn, 14, 10)) {
-+ case 0b10001:
-+ ok = gen_frint_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10010:
-+ ok = gen_frint_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
++ case 0b001:
++ assign(res, binop(Iop_OrV128,
++ mkexpr(srcL),
++ unop(Iop_NotV128, mkexpr(srcR))));
+ break;
+ default:
-+ ok = False;
-+ break;
++ return False;
+ }
+
-+ return ok;
-+}
++ const HChar *nm[8] = { "vandn.v", "vorn.v", "", "",
++ "vand.v", "vor.v", "vxor.v", "vnor.v" };
+
-+static Bool disInstr_LOONGARCH64_WRK_00_0000 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
-+{
-+ Bool ok;
++ DIP("%s %s, %s, %s\n", nm[insTy], nameVReg(vd), nameVReg(vj), nameVReg(vk));
+
-+ switch (SLICE(insn, 25, 22)) {
-+ case 0b0000:
-+ ok = disInstr_LOONGARCH64_WRK_00_0000_0000(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0001:
-+ ok = disInstr_LOONGARCH64_WRK_00_0000_0001(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0010:
-+ ok = gen_bstrins_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0011:
-+ ok = gen_bstrpick_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100:
-+ ok = disInstr_LOONGARCH64_WRK_00_0000_0100(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000:
-+ ok = gen_slti(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001:
-+ ok = gen_sltui(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1010:
-+ ok = gen_addi_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1011:
-+ ok = gen_addi_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1100:
-+ ok = gen_lu52i_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1101:
-+ ok = gen_andi(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1110:
-+ ok = gen_ori(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1111:
-+ ok = gen_xori(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
+
-+ return ok;
++ putVReg(vd, mkexpr(res));
++
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_00_1010 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_logical_xv ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insTy = SLICE(insn, 17, 15);
+
-+ switch (SLICE(insn, 25, 22)) {
-+ case 0b0000:
-+ ok = gen_ld_b(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0001:
-+ ok = gen_ld_h(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0010:
-+ ok = gen_ld_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0011:
-+ ok = gen_ld_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100:
-+ ok = gen_st_b(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0101:
-+ ok = gen_st_h(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0110:
-+ ok = gen_st_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0111:
-+ ok = gen_st_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000:
-+ ok = gen_ld_bu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001:
-+ ok = gen_ld_hu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1010:
-+ ok = gen_ld_wu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1011:
-+ ok = gen_preld(dres, insn, archinfo, abiinfo);
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sK = newTemp(Ity_V256);
++ assign(sJ, getXReg(xj));
++ assign(sK, getXReg(xk));
++
++ switch (insTy) {
++ case 0b100:
++ assign(res, binop(Iop_AndV256, EX(sJ), EX(sK)));
+ break;
-+ case 0b1100:
-+ ok = gen_fld_s(dres, insn, archinfo, abiinfo);
++ case 0b101:
++ assign(res, binop(Iop_OrV256, EX(sJ), EX(sK)));
+ break;
-+ case 0b1101:
-+ ok = gen_fst_s(dres, insn, archinfo, abiinfo);
++ case 0b110:
++ assign(res, binop(Iop_XorV256, EX(sJ), EX(sK)));
+ break;
-+ case 0b1110:
-+ ok = gen_fld_d(dres, insn, archinfo, abiinfo);
++ case 0b111:
++ assign(res, unop(Iop_NotV256, binop(Iop_OrV256,
++ EX(sJ), EX(sK))));
+ break;
-+ case 0b1111:
-+ ok = gen_fst_d(dres, insn, archinfo, abiinfo);
++ case 0b000:
++ assign(res, binop(Iop_AndV256,
++ unop(Iop_NotV256, EX(sJ)),
++ EX(sK)));
+ break;
-+ default:
-+ ok = False;
++ case 0b001:
++ assign(res, binop(Iop_OrV256,
++ EX(sJ),
++ unop(Iop_NotV256, EX(sK))));
+ break;
++ default: vassert(0);
+ }
+
-+ return ok;
++ const HChar *nm[8] = { "xvandn.v", "xvorn.v", "", "",
++ "xvand.v", "xvor.v", "xvxor.v", "xvnor.v" };
++
++ DIP("%s %s, %s, %s\n", nm[insTy], nameXReg(xd), nameXReg(xj), nameXReg(xk));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
++
++ putXReg(xd, EX(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_00_1011 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vlogical_u8 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt ui8 = SLICE(insn, 17, 10);
++ UInt insTy = SLICE(insn, 19, 18);
+
-+ switch (SLICE(insn, 23, 22)) {
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp dup = newTemp(Ity_V128);
++ assign(dup, unop(Iop_Dup8x16, mkU8(ui8)));
++ switch (insTy) {
+ case 0b00:
-+ ok = gen_vld(dres, insn, archinfo, abiinfo);
++ assign(res, binop(Iop_AndV128, getVReg(vj), EX(dup)));
+ break;
+ case 0b01:
-+ ok = gen_vst(dres, insn, archinfo, abiinfo);
++ assign(res, binop(Iop_OrV128, getVReg(vj), EX(dup)));
+ break;
+ case 0b10:
-+ ok = gen_xvld(dres, insn, archinfo, abiinfo);
++ assign(res, binop(Iop_XorV128, getVReg(vj), EX(dup)));
+ break;
+ case 0b11:
-+ ok = gen_xvst(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
++ assign(res, unop(Iop_NotV128,
++ binop(Iop_OrV128,
++ getVReg(vj), EX(dup))));
+ break;
++ default: vassert(0);
+ }
+
-+ return ok;
++ const HChar *nm[4] = { "vandi.b", "vori.b", "vxori.b", "vnori.b" };
++ DIP("%s %s, %s, %u\n", nm[insTy], nameVReg(vd), nameVReg(vj), ui8);
++ putVReg(vd, mkexpr(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_00_1100 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvlogical_u8 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
-+
-+ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
-+ dres->jk_StopHere = Ijk_SigILL;
-+ dres->whatNext = Dis_StopHere;
-+ return True;
-+ }
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt ui8 = SLICE(insn, 17, 10);
++ UInt insTy = SLICE(insn, 19, 18);
+
-+ switch (SLICE(insn, 25, 24)) {
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp dup = newTemp(Ity_V128);
++ assign(dup, unop(Iop_Dup8x16, mkU8(ui8)));
++ switch (insTy) {
+ case 0b00:
-+ ok = gen_vldrepl(dres, insn, archinfo, abiinfo);
++ assign(res, binop(Iop_AndV256,
++ getXReg(xj),
++ mkV256from128s(dup, dup)));
+ break;
+ case 0b01:
-+ ok = gen_vstelm(dres, insn, archinfo, abiinfo);
++ assign(res, binop(Iop_OrV256,
++ getXReg(xj),
++ mkV256from128s(dup, dup)));
+ break;
-+ default:
-+ ok = False;
++ case 0b10:
++ assign(res, binop(Iop_XorV256,
++ getXReg(xj),
++ mkV256from128s(dup, dup)));
++ break;
++ case 0b11:
++ assign(res, unop(Iop_NotV256,
++ binop(Iop_OrV256,
++ getXReg(xj),
++ mkV256from128s(dup, dup))));
+ break;
++ default: vassert(0);
+ }
+
-+ return ok;
++ const HChar *nm[4] = { "xvandi.b", "xvori.b", "xvxori.b", "xvnori.b" };
++ DIP("%s %s, %s, %u\n", nm[insTy], nameXReg(xd), nameXReg(xj), ui8);
++ putXReg(xd, EX(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_00_1110_0000 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static IRTemp gen_vrotr ( IRTemp sJ, IRTemp sK, UInt insSz )
+{
-+ Bool ok;
++ IRTemp dup = newTemp(Ity_V128);
++ IRTemp div = newTemp(Ity_V128);
++ IRTemp sub = newTemp(Ity_V128);
++ IRTemp res = newTemp(Ity_V128);
+
-+ switch (SLICE(insn, 21, 15)) {
-+ case 0b0000000:
-+ ok = gen_ldx_b(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0001000:
-+ ok = gen_ldx_h(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0010000:
-+ ok = gen_ldx_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0011000:
-+ ok = gen_ldx_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100000:
-+ ok = gen_stx_b(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0101000:
-+ ok = gen_stx_h(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0110000:
-+ ok = gen_stx_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0111000:
-+ ok = gen_stx_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000000:
-+ ok = gen_ldx_bu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001000:
-+ ok = gen_ldx_hu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1010000:
-+ ok = gen_ldx_wu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1011000:
-+ ok = gen_preldx(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1100000:
-+ ok = gen_fldx_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1101000:
-+ ok = gen_fldx_d(dres, insn, archinfo, abiinfo);
++ switch (insSz) {
++ case 0b00: {
++ assign(dup, unop(Iop_Dup8x16, mkU8(8)));
++ div = gen_vdiv_b(sK, dup, 1, 1);
+ break;
-+ case 0b1110000:
-+ ok = gen_fstx_s(dres, insn, archinfo, abiinfo);
++ }
++ case 0b01: {
++ assign(dup, unop(Iop_Dup16x8, mkU16(16)));
++ div = gen_vdiv_h(sK, dup, 1, 1);
+ break;
-+ case 0b1111000:
-+ ok = gen_fstx_d(dres, insn, archinfo, abiinfo);
++ }
++ case 0b10: {
++ assign(dup, unop(Iop_Dup32x4, mkU32(32)));
++ div = gen_vdiv_w(sK, dup, 1, 1);
+ break;
-+ default:
-+ ok = False;
++ }
++ case 0b11: {
++ assign(dup, binop(Iop_64HLtoV128, mkU64(64), mkU64(64)));
++ div = gen_vdiv_d(sK, dup, 1, 1);
+ break;
++ }
++ default: vassert(0);
+ }
+
-+ return ok;
++ assign(sub, binop(mkV128SUB(insSz), EX(dup), EX(div)));
++ assign(res, binop(Iop_OrV128,
++ binop(mkV128SHR(insSz), EX(sJ), EX(sK)),
++ binop(mkV128SHL(insSz), EX(sJ), EX(sub))));
++ return res;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_00_1110_0001 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vshift ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt insTy = SLICE(insn, 18, 17);
+
-+ switch (SLICE(insn, 21, 15)) {
-+ case 0b1000000:
-+ ok = gen_amswap_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000001:
-+ ok = gen_amswap_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000010:
-+ ok = gen_amadd_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000011:
-+ ok = gen_amadd_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000100:
-+ ok = gen_amand_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000101:
-+ ok = gen_amand_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000110:
-+ ok = gen_amor_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1000111:
-+ ok = gen_amor_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001000:
-+ ok = gen_amxor_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001001:
-+ ok = gen_amxor_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001010:
-+ ok = gen_ammax_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001011:
-+ ok = gen_ammax_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001100:
-+ ok = gen_ammin_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001101:
-+ ok = gen_ammin_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001110:
-+ ok = gen_ammax_wu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1001111:
-+ ok = gen_ammax_du(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1010000:
-+ ok = gen_ammin_wu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1010001:
-+ ok = gen_ammin_du(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1010010:
-+ ok = gen_amswap_db_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1010011:
-+ ok = gen_amswap_db_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1010100:
-+ ok = gen_amadd_db_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1010101:
-+ ok = gen_amadd_db_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1010110:
-+ ok = gen_amand_db_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1010111:
-+ ok = gen_amand_db_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1011000:
-+ ok = gen_amor_db_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1011001:
-+ ok = gen_amor_db_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1011010:
-+ ok = gen_amxor_db_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1011011:
-+ ok = gen_amxor_db_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1011100:
-+ ok = gen_ammax_db_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1011101:
-+ ok = gen_ammax_db_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1011110:
-+ ok = gen_ammin_db_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1011111:
-+ ok = gen_ammin_db_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1100000:
-+ ok = gen_ammax_db_wu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1100001:
-+ ok = gen_ammax_db_du(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1100010:
-+ ok = gen_ammin_db_wu(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1100011:
-+ ok = gen_ammin_db_du(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1100100:
-+ ok = gen_dbar(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1100101:
-+ ok = gen_ibar(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1101000:
-+ ok = gen_fldgt_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1101001:
-+ ok = gen_fldgt_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1101010:
-+ ok = gen_fldle_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1101011:
-+ ok = gen_fldle_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1101100:
-+ ok = gen_fstgt_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1101101:
-+ ok = gen_fstgt_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1101110:
-+ ok = gen_fstle_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1101111:
-+ ok = gen_fstle_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1110000:
-+ ok = gen_ldgt_b(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1110001:
-+ ok = gen_ldgt_h(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1110010:
-+ ok = gen_ldgt_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1110011:
-+ ok = gen_ldgt_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1110100:
-+ ok = gen_ldle_b(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1110101:
-+ ok = gen_ldle_h(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1110110:
-+ ok = gen_ldle_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1110111:
-+ ok = gen_ldle_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1111000:
-+ ok = gen_stgt_b(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1111001:
-+ ok = gen_stgt_h(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1111010:
-+ ok = gen_stgt_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1111011:
-+ ok = gen_stgt_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1111100:
-+ ok = gen_stle_b(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1111101:
-+ ok = gen_stle_h(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1111110:
-+ ok = gen_stle_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1111111:
-+ ok = gen_stle_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp sK = newTemp(Ity_V128);
++ assign(sJ, getVReg(vj));
++ assign(sK, getVReg(vk));
++
++ switch (insTy) {
++ case 0b00:
++ assign(res, binop(mkV128SHL(insSz), EX(sJ), EX(sK))); break;
++ case 0b01:
++ assign(res, binop(mkV128SHR(insSz), EX(sJ), EX(sK))); break;
++ case 0b10:
++ assign(res, binop(mkV128SAR(insSz), EX(sJ), EX(sK))); break;
++ case 0b11:
++ res = gen_vrotr(sJ, sK, insSz); break;
++ default: vassert(0);
+ }
+
-+ return ok;
++ const HChar *nm[4] = { "vsll", "vsrl", "vsra", "vrotr" };
++ DIP("%s.%s %s, %s, %s\n", nm[insTy], mkInsSize(insSz),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++ putVReg(vd, mkexpr(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_FCMP_S ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvshift ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt insTy = SLICE(insn, 18, 17);
+
-+ switch (SLICE(insn, 19, 15)) {
-+ case 0x0:
-+ ok = gen_fcmp_caf_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x1:
-+ ok = gen_fcmp_saf_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x2:
-+ ok = gen_fcmp_clt_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x3:
-+ ok = gen_fcmp_slt_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x4:
-+ ok = gen_fcmp_ceq_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x5:
-+ ok = gen_fcmp_seq_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x6:
-+ ok = gen_fcmp_cle_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x7:
-+ ok = gen_fcmp_sle_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x8:
-+ ok = gen_fcmp_cun_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x9:
-+ ok = gen_fcmp_sun_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0xa:
-+ ok = gen_fcmp_cult_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0xb:
-+ ok = gen_fcmp_sult_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0xc:
-+ ok = gen_fcmp_cueq_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0xd:
-+ ok = gen_fcmp_sueq_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0xe:
-+ ok = gen_fcmp_cule_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0xf:
-+ ok = gen_fcmp_sule_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x10:
-+ ok = gen_fcmp_cne_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x11:
-+ ok = gen_fcmp_sne_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x14:
-+ ok = gen_fcmp_cor_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x15:
-+ ok = gen_fcmp_sor_s(dres, insn, archinfo, abiinfo);
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sK = newTemp(Ity_V256);
++ assign(sJ, getXReg(xj));
++ assign(sK, getXReg(xk));
++
++ switch (insTy) {
++ case 0b00: {
++ assign(res, binop(mkV256SHL(insSz), EX(sJ), EX(sK)));
+ break;
-+ case 0x18:
-+ ok = gen_fcmp_cune_s(dres, insn, archinfo, abiinfo);
++ }
++ case 0b01: {
++ assign(res, binop(mkV256SHR(insSz), EX(sJ), EX(sK)));
+ break;
-+ case 0x19:
-+ ok = gen_fcmp_sune_s(dres, insn, archinfo, abiinfo);
++ }
++ case 0b10: {
++ assign(res, binop(mkV256SAR(insSz), EX(sJ), EX(sK)));
+ break;
-+ default:
-+ ok = False;
++ }
++ case 0b11: {
++ IRTemp jHi = IRTemp_INVALID;
++ IRTemp jLo = IRTemp_INVALID;
++ IRTemp kHi = IRTemp_INVALID;
++ IRTemp kLo = IRTemp_INVALID;
++ breakupV256toV128s(sJ, &jHi, &jLo);
++ breakupV256toV128s(sK, &kHi, &kLo);
++ assign(res, mkV256from128s(gen_vrotr(jHi, kHi, insSz),
++ gen_vrotr(jLo, kLo, insSz)));
+ break;
++ }
++ default: vassert(0);
+ }
+
-+ return ok;
++ const HChar *nm[4] = { "xvsll", "xvsrl", "xvsra", "xvrotr" };
++ DIP("%s.%s %s, %s, %s\n", nm[insTy], mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, EX(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_FCMP_D ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vshift_imm ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
++ UInt insTy = SLICE(insn, 19, 18);
+
-+ switch (SLICE(insn, 19, 15)) {
-+ case 0x0:
-+ ok = gen_fcmp_caf_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x1:
-+ ok = gen_fcmp_saf_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x2:
-+ ok = gen_fcmp_clt_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x3:
-+ ok = gen_fcmp_slt_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x4:
-+ ok = gen_fcmp_ceq_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x5:
-+ ok = gen_fcmp_seq_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x6:
-+ ok = gen_fcmp_cle_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x7:
-+ ok = gen_fcmp_sle_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x8:
-+ ok = gen_fcmp_cun_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x9:
-+ ok = gen_fcmp_sun_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0xa:
-+ ok = gen_fcmp_cult_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0xb:
-+ ok = gen_fcmp_sult_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0xc:
-+ ok = gen_fcmp_cueq_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0xd:
-+ ok = gen_fcmp_sueq_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0xe:
-+ ok = gen_fcmp_cule_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0xf:
-+ ok = gen_fcmp_sule_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x10:
-+ ok = gen_fcmp_cne_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x11:
-+ ok = gen_fcmp_sne_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x14:
-+ ok = gen_fcmp_cor_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x15:
-+ ok = gen_fcmp_sor_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x18:
-+ ok = gen_fcmp_cune_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0x19:
-+ ok = gen_fcmp_sune_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ UInt insSz, uImm;
++ if ((insImm & 0xf8) == 0x8) { // 00001mmm; b
++ uImm = insImm & 0x07;
++ insSz = 0;
++ } else if ((insImm & 0xf0) == 0x10) { // 0001mmmm; h
++ uImm = insImm & 0x0f;
++ insSz = 1;
++ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; w
++ uImm = insImm & 0x1f;
++ insSz = 2;
++ } else if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; d
++ uImm = insImm & 0x3f;
++ insSz = 3;
++ } else {
++ vassert(0);
+ }
+
-+ return ok;
++ IROp op = Iop_INVALID;
++ switch (insTy) {
++ case 0b11: op = mkV128SHLN(insSz); break;
++ case 0b00: op = mkV128SHRN(insSz); break;
++ case 0b01: op = mkV128SARN(insSz); break;
++ default: vassert(0);
++ }
++
++ const HChar *nm[4] = { "vsrli", "vsrai", "", "vslli" };
++ DIP("%s.%s %s, %s, %u\n", nm[insTy], mkInsSize(insSz),
++ nameVReg(vd), nameVReg(vj), uImm);
++ putVReg(vd, binop(op, getVReg(vj), mkU8(uImm)));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_00 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvshift_imm ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
++ UInt insTy = SLICE(insn, 19, 18);
+
-+ switch (SLICE(insn, 29, 26)) {
-+ case 0b0000:
-+ ok = disInstr_LOONGARCH64_WRK_00_0000(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0010:
-+ switch (SLICE(insn, 25, 20)) {
-+ case 0b000001:
-+ ok = gen_fmadd_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b000010:
-+ ok = gen_fmadd_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b000101:
-+ ok = gen_fmsub_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b000110:
-+ ok = gen_fmsub_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b001001:
-+ ok = gen_fnmadd_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b001010:
-+ ok = gen_fnmadd_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b001101:
-+ ok = gen_fnmsub_s(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b001110:
-+ ok = gen_fnmsub_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
-+ break;
-+ case 0b0011:
-+ switch (SLICE(insn, 25, 20)) {
-+ case 0b000001:
-+ if (SLICE(insn, 4, 3) == 0b00) {
-+ ok = disInstr_LOONGARCH64_WRK_FCMP_S(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = False;
-+ }
-+ break;
-+ case 0b000010:
-+ if (SLICE(insn, 4, 3) == 0b00) {
-+ ok = disInstr_LOONGARCH64_WRK_FCMP_D(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = False;
-+ }
-+ break;
-+ case 0b010000:
-+ if (SLICE(insn, 19, 18) == 0b00) {
-+ ok = gen_fsel(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = False;
-+ }
-+ break;
-+ case 0b010101:
-+ ok = gen_vshuf_b(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
-+ break;
-+ case 0b0100:
-+ ok = gen_addu16i_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0101:
-+ if (SLICE(insn, 25, 25) == 0) {
-+ ok = gen_lu12i_w(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = gen_lu32i_d(dres, insn, archinfo, abiinfo);
-+ }
-+ break;
-+ case 0b0110:
-+ if (SLICE(insn, 25, 25) == 0) {
-+ ok = gen_pcaddi(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = gen_pcalau12i(dres, insn, archinfo, abiinfo);
-+ }
-+ break;
-+ case 0b0111:
-+ if (SLICE(insn, 25, 25) == 0) {
-+ ok = gen_pcaddu12i(dres, insn, archinfo, abiinfo);
-+ } else {
-+ ok = gen_pcaddu18i(dres, insn, archinfo, abiinfo);
-+ }
-+ break;
-+ case 0b1000:
-+ switch (SLICE(insn, 25, 24)) {
-+ case 0b00:
-+ ok = gen_ll_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01:
-+ ok = gen_sc_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10:
-+ ok = gen_ll_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b11:
-+ ok = gen_sc_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
-+ break;
-+ case 0b1001:
-+ switch (SLICE(insn, 25, 24)) {
-+ case 0b00:
-+ ok = gen_ldptr_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01:
-+ ok = gen_stptr_w(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10:
-+ ok = gen_ldptr_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b11:
-+ ok = gen_stptr_d(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
-+ break;
-+ case 0b1010:
-+ ok = disInstr_LOONGARCH64_WRK_00_1010(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1011:
-+ ok = disInstr_LOONGARCH64_WRK_00_1011(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1100:
-+ ok = disInstr_LOONGARCH64_WRK_00_1100(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1110:
-+ switch (SLICE(insn, 25, 22)) {
-+ case 0b0000:
-+ ok = disInstr_LOONGARCH64_WRK_00_1110_0000(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0001:
-+ ok = disInstr_LOONGARCH64_WRK_00_1110_0001(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ UInt insSz, uImm;
++ if ((insImm & 0xf8) == 0x8) { // 00001mmm; b
++ uImm = insImm & 0x07;
++ insSz = 0;
++ } else if ((insImm & 0xf0) == 0x10) { // 0001mmmm; h
++ uImm = insImm & 0x0f;
++ insSz = 1;
++ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; w
++ uImm = insImm & 0x1f;
++ insSz = 2;
++ } else if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; d
++ uImm = insImm & 0x3f;
++ insSz = 3;
++ } else {
++ vassert(0);
+ }
+
-+ return ok;
++ IROp op = Iop_INVALID;
++ switch (insTy) {
++ case 0b11: op = mkV256SHLN(insSz); break;
++ case 0b00: op = mkV256SHRN(insSz); break;
++ case 0b01: op = mkV256SARN(insSz); break;
++ default: vassert(0);
++ }
++
++ const HChar *nm[4] = { "xvsrli", "xvsrai", "", "xvslli" };
++ DIP("%s.%s %s, %s, %u\n", nm[insTy], mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj), uImm);
++ putXReg(xd, binop(op, getXReg(xj), mkU8(uImm)));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1100_0000 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vsllwil ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
++ UInt isU = SLICE(insn, 18, 18);
+
-+ switch (SLICE(insn, 21, 17)) {
-+ case 0b00000:
-+ case 0b00001:
-+ case 0b00010:
-+ case 0b00011:
-+ case 0b00100:
-+ ok = gen_vcmp_integer(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b00101:
-+ case 0b00110:
-+ ok = gen_vadd_vsub(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ IRTemp sLo = newTemp(Ity_V128);
++ assign(sLo, binop(Iop_InterleaveLO64x2,
++ getVReg(vj),
++ mkV128(0x0000)));
++
++ UInt uImm, insSz, szId;
++ IROp widenOp = Iop_INVALID;
++ if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; d
++ widenOp = isU ? Iop_WidenHIto128Ux1 : Iop_WidenHIto128Sx1;
++ szId = isU ? 7 : 3;
++ DIP("extl.%s %s, %s\n", mkInsExtSize(szId),
++ nameVReg(vd), nameVReg(vj));
++ putVReg(vd, unop(widenOp, EX(sLo)));
++ return True;
+ }
+
-+ return ok;
++ if ((insImm & 0xf8) == 0x8) { // 00001mmm; b
++ uImm = insImm & 0x07;
++ insSz = 0;
++ } else if ((insImm & 0xf0) == 0x10) { // 0001mmmm; h
++ uImm = insImm & 0x0F;
++ insSz = 1;
++ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; w
++ uImm = insImm & 0x1F;
++ insSz = 2;
++ } else {
++ vassert(0);
++ }
++
++ szId = isU ? (insSz + 4) : insSz;
++ widenOp = isU ? mkV128EXTHTU(insSz): mkV128EXTHTS(insSz);
++ DIP("vsllwil.%s %s, %s, %u\n", mkInsExtSize(szId),
++ nameVReg(vd), nameVReg(vj), uImm);
++ putVReg(vd, binop(mkV128SHLN(insSz + 1),
++ unop(widenOp, EX(sLo)),
++ mkU8(uImm)));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1100_0001 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvsllwil ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
++ UInt isU = SLICE(insn, 18, 18);
++
++ IRTemp sLo = newTemp(Ity_V256);
++ assign(sLo, binop(Iop_InterleaveLO64x4,
++ getXReg(xj),
++ mkV256(0x0000)));
++
++ UInt uImm, insSz, szId;
++ IROp widenOp = Iop_INVALID;
++ if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; d
++ widenOp = isU ? Iop_WidenHIto128Ux2 : Iop_WidenHIto128Sx2;
++ szId = isU ? 7 : 3;
++ DIP("xextl.%s %s, %s\n", mkInsExtSize(szId),
++ nameXReg(xd), nameXReg(xj));
++ putXReg(xd, unop(widenOp, EX(sLo)));
++ return True;
++ }
+
-+ switch (SLICE(insn, 21, 18)) {
-+ case 0b1100:
-+ case 0b1101:
-+ ok = gen_vmax_vmin(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ if ((insImm & 0xf8) == 0x8) { // 00001mmm; b
++ uImm = insImm & 0x07;
++ insSz = 0;
++ } else if ((insImm & 0xf0) == 0x10) { // 0001mmmm; h
++ uImm = insImm & 0x0f;
++ insSz = 1;
++ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; w
++ uImm = insImm & 0x1f;
++ insSz = 2;
++ } else {
++ vassert(0);
+ }
+
-+ return ok;
++ szId = isU ? (insSz + 4) : insSz;
++ widenOp = isU ? mkV256EXTHTU(insSz): mkV256EXTHTS(insSz);
++ DIP("xvsllwil.%s %s, %s, %u\n", mkInsExtSize(szId),
++ nameXReg(xd), nameXReg(xj), uImm);
++ putXReg(xd, binop(mkV256SHLN(insSz + 1),
++ unop(widenOp, EX(sLo)),
++ mkU8(uImm)));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1100_0100 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static IRTemp vsrlr_ops ( IRTemp sJ, IRTemp sK, IROp shrOp, UInt insSz )
+{
-+ Bool ok;
++ IRTemp argL = newTemp(Ity_V128);
++ IRTemp argR = newTemp(Ity_V128);
++ IRTemp subRes = newTemp(Ity_V128);
++ IRTemp notRes = newTemp(Ity_V128);
++ IRTemp subR = newTemp(Ity_V128);
++ IRTemp res = newTemp(Ity_V128);
++ UInt shlNum[4] = { 5, 12, 27, 58 };
++ UInt shrNum[4] = { 7, 15, 31, 63 };
++ IRTemp imm = newTemp(Ity_I64);
+
-+ switch (SLICE(insn, 21, 17)) {
-+ case 0b01011:
-+ case 0b01100:
-+ case 0b01101:
-+ case 0b01110:
-+ case 0b01111:
-+ case 0b10000:
-+ ok = gen_evod(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10001:
-+ ok = gen_vreplve(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b10011:
-+ case 0b10100:
-+ ok = gen_logical_v(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ switch (insSz) {
++ case 0b00: assign(imm, mkU64(0x808080808080808ull)); break;
++ case 0b01: assign(imm, mkU64(0x10001000100010ul)); break;
++ case 0b10: assign(imm, mkU64(0x2000000020ul)); break;
++ case 0b11: assign(imm, mkU64(64ul)); break;
++ default: vassert(0);
+ }
+
-+ return ok;
++ assign(subR, mkV128from64s(imm, imm));
++ assign(argL, binop(shrOp, EX(sJ), EX(sK)));
++ assign(subRes, binop(mkV128SUB(insSz), EX(subR),EX(sK)));
++ assign(notRes, unop(Iop_NotV128, binop(mkV128CMPEQ(insSz),
++ binop(mkV128SHLN(insSz),
++ EX(sK),
++ mkU8(shlNum[insSz])),
++ mkV128(0x0000))));
++ assign(argR, binop(mkV128SHRN(insSz),
++ binop(Iop_AndV128,
++ binop(mkV128SHL(insSz),
++ EX(sJ), EX(subRes)),
++ EX(notRes)),
++ mkU8(shrNum[insSz])));
++ assign(res, binop(mkV128ADD(insSz), EX(argL), EX(argR)));
++ return res;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1100_1010_01110 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vsrlr ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt insTy = SLICE(insn, 17, 17);
+
-+ switch (SLICE(insn, 16, 14)) {
-+ case 0b001:
-+ ok = gen_vmsk(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b010:
-+ ok = gen_vset(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ IROp shrOp = insTy ? mkV128SAR(insSz) : mkV128SHR(insSz);
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp sK = newTemp(Ity_V128);
++ assign(sJ, getVReg(vj));
++ assign(sK, getVReg(vk));
++ res = vsrlr_ops(sJ, sK, shrOp, insSz);
++
++ const HChar *nm[2] = { "vsrlr", "vsrar" };
++ DIP("%s.%s %s, %s, %s\n", nm[insTy], mkInsExtSize(insSz),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++ putVReg(vd, mkexpr(res));
++ return True;
++}
++
++static IRTemp xvsrlr_ops ( IRTemp sJ, IRTemp sK, IROp shrOp, UInt insSz )
++{
++ IRTemp argL = newTemp(Ity_V256);
++ IRTemp argR = newTemp(Ity_V256);
++ IRTemp subRes = newTemp(Ity_V256);
++ IRTemp notRes = newTemp(Ity_V256);
++ IRTemp subR = newTemp(Ity_V256);
++ IRTemp res = newTemp(Ity_V256);
++ UInt shlNum[4] = { 5, 12, 27, 58 };
++ UInt shrNum[4] = { 7, 15, 31, 63 };
++ IRTemp imm = newTemp(Ity_I64);
++
++ switch (insSz) {
++ case 0b00: assign(imm, mkU64(0x808080808080808ull)); break;
++ case 0b01: assign(imm, mkU64(0x10001000100010ul)); break;
++ case 0b10: assign(imm, mkU64(0x2000000020ul)); break;
++ case 0b11: assign(imm, mkU64(64ul)); break;
++ default: vassert(0);
+ }
+
-+ return ok;
++ assign(subR, mkV256from64s(imm, imm, imm, imm));
++ assign(argL, binop(shrOp, EX(sJ), EX(sK)));
++ assign(subRes, binop(mkV256SUB(insSz), EX(subR),EX(sK)));
++ assign(notRes, unop(Iop_NotV256, binop(mkV256CMPEQ(insSz),
++ binop(mkV256SHLN(insSz),
++ EX(sK),
++ mkU8(shlNum[insSz])),
++ mkV256(0x0000))));
++ assign(argR, binop(mkV256SHRN(insSz),
++ binop(Iop_AndV256,
++ binop(mkV256SHL(insSz),
++ EX(sJ), EX(subRes)),
++ EX(notRes)),
++ mkU8(shrNum[insSz])));
++ assign(res, binop(mkV256ADD(insSz), EX(argL), EX(argR)));
++ return res;
+}
+
-+
-+static Bool disInstr_LOONGARCH64_WRK_01_1100_1010_01111 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvsrlr ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt insTy = SLICE(insn, 17, 17);
+
-+ switch (SLICE(insn, 16, 14)) {
-+ case 0b100:
-+ ok = gen_vreplgr2vr(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
++ IROp shrOp = insTy ? mkV256SAR(insSz) : mkV256SHR(insSz);
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sK = newTemp(Ity_V256);
++ assign(sJ, getXReg(xj));
++ assign(sK, getXReg(xk));
++ res = xvsrlr_ops(sJ, sK, shrOp, insSz);
+
-+ return ok;
++ const HChar *nm[2] = { "xvsrlr", "xvsrar" };
++ DIP("%s.%s %s, %s, %s\n", nm[insTy], mkInsExtSize(insSz),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, EX(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1100_1010 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static IRTemp gen_vrotri ( UInt insSz, IRTemp src, Bool isV128, UInt imm )
+{
-+ Bool ok;
++ IRTemp shrR = newTemp(Ity_V128);
++ IRTemp shlR = newTemp(Ity_V128);
++ IRTemp res = isV128 ? newTemp(Ity_V128) : newTemp(Ity_V256);
++ IRExpr* sub;
+
-+ switch (SLICE(insn, 21, 17)) {
-+ case 0b00000:
-+ case 0b00001:
-+ case 0b00010:
-+ case 0b00011:
-+ case 0b00100:
-+ ok = gen_vcmpi_integer(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b00101:
-+ case 0b00110:
-+ ok = gen_vaddi_vsubi(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01101:
-+ ok = gen_vfrstpi(dres, insn, archinfo, abiinfo);
++ switch (insSz) {
++ case 0b00: {
++ sub = unop(Iop_64to8, binop(Iop_Sub64, mkU64(8), mkU64(imm)));
++ assign(shlR, unop(Iop_Dup8x16, sub));
++ assign(shrR, unop(Iop_Dup8x16, mkU8(imm)));
+ break;
-+ case 0b01110:
-+ ok = disInstr_LOONGARCH64_WRK_01_1100_1010_01110(dres, insn, archinfo, abiinfo);
++ }
++ case 0b01: {
++ sub = unop(Iop_64to16, binop(Iop_Sub64, mkU64(16), mkU64(imm)));
++ assign(shlR, unop(Iop_Dup16x8, sub));
++ assign(shrR, unop(Iop_Dup16x8, mkU16(imm)));
+ break;
-+ case 0b01111:
-+ ok = disInstr_LOONGARCH64_WRK_01_1100_1010_01111(dres, insn, archinfo, abiinfo);
++ }
++ case 0b10: {
++ sub = unop(Iop_64to32, binop(Iop_Sub64, mkU64(32), mkU64(imm)));
++ assign(shlR, unop(Iop_Dup32x4, sub));
++ assign(shrR, unop(Iop_Dup32x4, mkU32(imm)));
+ break;
-+ default:
-+ ok = False;
++ }
++ case 0b11: {
++ sub = binop(Iop_Sub64, mkU64(64), mkU64(imm));
++ assign(shlR, binop(Iop_64HLtoV128, sub, sub));
++ assign(shrR, binop(Iop_64HLtoV128, mkU64(imm), mkU64(imm)));
+ break;
++ }
++ default: vassert(0);
+ }
+
-+ return ok;
++ if (isV128)
++ assign(res, binop(Iop_OrV128,
++ binop(mkV128SHR(insSz), EX(src), EX(shrR)),
++ binop(mkV128SHL(insSz), EX(src), EX(shlR))));
++ else
++ assign(res, binop(Iop_OrV256,
++ binop(mkV256SHR(insSz), EX(src), mkV256from128s(shrR, shrR)),
++ binop(mkV256SHL(insSz), EX(src), mkV256from128s(shlR, shlR))));
++ return res;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1100_1011 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static IRTemp vsrlari_ops ( IRTemp src, IROp shOp, UInt insSz, UInt imm , Bool isV128 )
+{
-+ Bool ok;
++ IRTemp argL = isV128 ? newTemp(Ity_V128) : newTemp(Ity_V256);
++ IRTemp argR = isV128 ? newTemp(Ity_V128) : newTemp(Ity_V256);
++ IRTemp res = isV128 ? newTemp(Ity_V128) : newTemp(Ity_V256);
++ IROp shr = isV128 ? mkV128SHRN(insSz) : mkV256SHRN(insSz);
++ IROp shl = isV128 ? mkV128SHLN(insSz) : mkV256SHLN(insSz);
++ IROp add = isV128 ? mkV128ADD(insSz) : mkV256ADD(insSz);
++ UInt shlNum[4] = { 8, 16, 32, 64 };
++ UInt shrNum[4] = { 7, 15, 31, 63 };
+
-+ switch (SLICE(insn, 21, 16)) {
-+ case 0b101111:
-+ case 0b110011:
-+ ok = gen_vpickve2gr(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
++ assign(argL, binop(shOp, EX(src), mkU8(imm)));
++ assign(argR, binop(shr,
++ binop(shl,
++ EX(src), mkU8(shlNum[insSz] - imm)),
++ mkU8(shrNum[insSz])));
+
-+ return ok;
++ if (imm)
++ assign(res, binop(add, EX(argL), EX(argR)));
++ else
++ assign(res, EX(argL));
++
++ return res;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1100_1100 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vsrlari ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
++ UInt insTy = SLICE(insn, 19, 18);
+
-+ switch (SLICE(insn, 21, 18)) {
-+ case 0b0100:
-+ case 0b0101:
-+ case 0b0110:
-+ ok = gen_vbiti(dres, insn, archinfo, abiinfo);
++ IRTemp src = newTemp(Ity_V128);
++ IRTemp res = newTemp(Ity_V128);
++ UInt uImm, insSz;
++
++ if ((insImm & 0xf8) == 0x8) { // 00001mmm; b
++ uImm = insImm & 0x07;
++ insSz = 0;
++ } else if ((insImm & 0xf0) == 0x10) { // 0001mmmm; h
++ uImm = insImm & 0x0f;
++ insSz = 1;
++ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; w
++ uImm = insImm & 0x1f;
++ insSz = 2;
++ } else if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; d
++ uImm = insImm & 0x3f;
++ insSz = 3;
++ } else {
++ vassert(0);
++ }
++
++ assign(src, getVReg(vj));
++ switch (insTy) {
++ case 0b00: {
++ res = gen_vrotri(insSz, src, True, uImm);
+ break;
-+ default:
-+ ok = False;
++ }
++ case 0b01: case 0b10: {
++ IROp shOp = (insTy == 0b10) ? mkV128SARN(insSz) : mkV128SHRN(insSz);
++ res = vsrlari_ops(src, shOp, insSz, uImm, True);
+ break;
++ }
++ default: vassert(0);
+ }
+
-+ return ok;
++ const HChar *nm[3] = { "vrotri", "vsrlri", "vsrari" };
++ DIP("%s.%s %s, %s, %u\n", nm[insTy], mkInsExtSize(insSz),
++ nameVReg(vd), nameVReg(vj), uImm);
++ putVReg(vd, mkexpr(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1100_1111 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvsrlri ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
++ UInt insTy = SLICE(insn, 19, 18);
+
-+ switch (SLICE(insn, 21, 18)) {
-+ case 0b0100:
-+ case 0b0101:
-+ case 0b0110:
-+ case 0b0111:
-+ ok = gen_vlogical_u8(dres, insn, archinfo, abiinfo);
++ IRTemp src = newTemp(Ity_V256);
++ IRTemp res = newTemp(Ity_V256);
++ UInt uImm, insSz;
++
++ if ((insImm & 0xf8) == 0x8) { // 00001mmm; b
++ uImm = insImm & 0x07;
++ insSz = 0;
++ } else if ((insImm & 0xf0) == 0x10) { // 0001mmmm; h
++ uImm = insImm & 0x0f;
++ insSz = 1;
++ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; w
++ uImm = insImm & 0x1f;
++ insSz = 2;
++ } else if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; d
++ uImm = insImm & 0x3f;
++ insSz = 3;
++ } else {
++ vassert(0);
++ }
++
++ assign(src, getXReg(xj));
++ switch (insTy) {
++ case 0b00: {
++ res = gen_vrotri(insSz, src, False, uImm);
+ break;
-+ default:
-+ ok = False;
++ }
++ case 0b01: case 0b10: {
++ IROp shOp = (insTy == 0b10) ? mkV256SARN(insSz) : mkV256SHRN(insSz);
++ res = vsrlari_ops(src, shOp, insSz, uImm, False);
+ break;
++ }
++ default: vassert(0);
+ }
+
-+ return ok;
++ const HChar *nm[3] = { "xvrotri", "xvsrlri", "xvsrari" };
++ DIP("%s.%s %s, %s, %u\n", nm[insTy], mkInsExtSize(insSz),
++ nameXReg(xd), nameXReg(xj), uImm);
++ putXReg(xd, EX(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1100 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vsrlan ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isSAR = SLICE(insn, 17, 17);
+
-+ switch (SLICE(insn, 25, 22)) {
-+ case 0b0000:
-+ ok = disInstr_LOONGARCH64_WRK_01_1100_0000(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0001:
-+ ok = disInstr_LOONGARCH64_WRK_01_1100_0001(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100:
-+ ok = disInstr_LOONGARCH64_WRK_01_1100_0100(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1010:
-+ ok = disInstr_LOONGARCH64_WRK_01_1100_1010(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1011:
-+ ok = disInstr_LOONGARCH64_WRK_01_1100_1011(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1100:
-+ ok = disInstr_LOONGARCH64_WRK_01_1100_1100(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1111:
-+ ok = disInstr_LOONGARCH64_WRK_01_1100_1111(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
++ IRTemp arg = newTemp(Ity_V128);
++ IRTemp res = newTemp(Ity_V128);
++ IROp shOp = isSAR ? mkV128SAR(insSz) : mkV128SHR(insSz);
++ const HChar *nm = isSAR ? "vsran" : "vsrln";
+
-+ return ok;
++ assign(arg, binop(shOp, getVReg(vj), getVReg(vk)));
++ assign(res, binop(mkV128PACKEV(insSz - 1),
++ mkV128(0x0000), EX(arg)));
++
++ DIP("%s.%s %s, %s, %s\n", nm, mkInsExtSize(insSz),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++ putVReg(vd, EX(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1101_0000 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvsrlan ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isSAR = SLICE(insn, 17, 17);
+
-+ switch (SLICE(insn, 21, 18)) {
-+ case 0b0000:
-+ ok = gen_xvcmp_integer(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
++ IRTemp arg = newTemp(Ity_V256);
++ IRTemp res = newTemp(Ity_V256);
++ IROp shOp = isSAR ? mkV256SAR(insSz) : mkV256SHR(insSz);
++ const HChar *nm = isSAR ? "xvsran" : "xvsrln";
+
-+ return ok;
++ assign(arg, binop(shOp, getXReg(xj), getXReg(xk)));
++ assign(res, binop(mkV256PACKEV(insSz - 1),
++ mkV256(0x0000), EX(arg)));
++
++ DIP("%s.%s %s, %s, %s\n", nm, mkInsExtSize(insSz),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, EX(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1101_0001 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static IRTemp gen_vsrlan_d_q ( IRTemp src, UInt isSAR, UInt uImm )
+{
-+ Bool ok;
-+
-+ switch (SLICE(insn, 21, 18)) {
-+ case 0b1101:
-+ ok = gen_xvmax_xvmin(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ IRTemp sHi = newTemp(Ity_I64);
++ IRTemp sLo = newTemp(Ity_I64);
++ IRTemp res = newTemp(Ity_I64);
++ IROp shOp = isSAR ? Iop_Sar64 : Iop_Shr64;
++
++ assign(sHi, unop(Iop_V128HIto64, EX(src)));
++ assign(sLo, unop(Iop_V128to64, EX(src)));
++
++ if (uImm == 0)
++ return sLo;
++
++ if (uImm < 64) {
++ assign(res, binop(Iop_Or64, binop(Iop_Shl64,
++ EX(sHi), mkU8(64 - uImm)),
++ binop(Iop_Shr64,
++ EX(sLo), mkU8(uImm))));
++ } else {
++ assign(res, binop(shOp, EX(sHi), mkU8(uImm - 64)));
+ }
+
-+ return ok;
++ return res;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1101_0100 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
-+{
-+ Bool ok;
++static Bool gen_vsrlani ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
++ UInt isSAR = SLICE(insn, 19, 19);
+
-+ switch (SLICE(insn, 21, 18)) {
-+ case 0b1001:
-+ ok = gen_logical_xv(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ UInt uImm, insSz;
++ if ((insImm & 0xf0) == 0x10) { // 0001mmmm; b
++ uImm = insImm & 0x0f;
++ insSz = 0;
++ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; h
++ uImm = insImm & 0x1f;
++ insSz = 1;
++ } else if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; w
++ uImm = insImm & 0x3f;
++ insSz = 2;
++ } else if ((insImm & 0x80) == 0x80) { // 1mmmmmmm; d
++ uImm = insImm & 0x7f;
++ insSz = 3;
++ } else {
++ vassert(0);
+ }
+
-+ return ok;
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp sD = newTemp(Ity_V128);
++ assign(sJ, getVReg(vj));
++ assign(sD, getVReg(vd));
++
++ if (insSz == 3) {
++ IRTemp rHi = newTemp(Ity_I64);
++ IRTemp rLo = newTemp(Ity_I64);
++ rHi = gen_vsrlan_d_q(sD, isSAR, uImm);
++ rLo = gen_vsrlan_d_q(sJ, isSAR, uImm);
++ assign(res, binop(Iop_64HLtoV128, EX(rHi), EX(rLo)));
++ } else {
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IROp shOp = isSAR ? mkV128SARN(insSz + 1) : mkV128SHRN(insSz + 1);
++ assign(rLo, binop(mkV128PACKEV(insSz),
++ mkV128(0x0000),
++ binop(shOp, EX(sJ), mkU8(uImm))));
++ assign(rHi, binop(mkV128PACKEV(insSz),
++ mkV128(0x0000),
++ binop(shOp, EX(sD), mkU8(uImm))));
++ assign(res, binop(Iop_InterleaveLO64x2, EX(rHi), EX(rLo)));
++ }
++
++ const HChar *nm = isSAR ? "vsrani" : "vsrlni";
++ DIP("%s.%s %s, %s, %u\n", nm, mkInsExtSize(insSz),
++ nameVReg(vd), nameVReg(vj), uImm);
++ putVReg(vd, EX(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1101_1010_0111 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvsrlani ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
++ UInt isSAR = SLICE(insn, 19, 19);
+
-+ switch (SLICE(insn, 17, 14)) {
-+ case 0b0001:
-+ ok = gen_xvmsk(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0010:
-+ ok = gen_xvset(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b1100:
-+ ok = gen_xvreplgr2vr(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ UInt uImm, insSz;
++ if ((insImm & 0xf0) == 0x10) { // 0001mmmm; b
++ uImm = insImm & 0x0f;
++ insSz = 0;
++ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; h
++ uImm = insImm & 0x1f;
++ insSz = 1;
++ } else if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; w
++ uImm = insImm & 0x3f;
++ insSz = 2;
++ } else if ((insImm & 0x80) == 0x80) { // 1mmmmmmm; d
++ uImm = insImm & 0x7f;
++ insSz = 3;
++ } else {
++ vassert(0);
+ }
+
-+ return ok;
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sD = newTemp(Ity_V256);
++ assign(sJ, getXReg(xj));
++ assign(sD, getXReg(xd));
++
++ if (insSz == 3) {
++ IRTemp jHi, jLo, dHi, dLo;
++ jHi = jLo = dHi = dLo = IRTemp_INVALID;
++ breakupV256toV128s(sJ, &jHi, &jLo);
++ breakupV256toV128s(sD, &dHi, &dLo);
++ IRTemp rjHi, rjLo, rdHi, rdLo;
++ rjHi = rjLo = rdHi = rdLo = newTemp(Ity_I64);
++ rjHi = gen_vsrlan_d_q(jHi, isSAR, uImm);
++ rjLo = gen_vsrlan_d_q(jLo, isSAR, uImm);
++ rdHi = gen_vsrlan_d_q(dHi, isSAR, uImm);
++ rdLo = gen_vsrlan_d_q(dLo, isSAR, uImm);
++ assign(res, mkV256from64s(rdHi, rjHi, rdLo, rjLo));
++ } else {
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IROp shOp = isSAR ? mkV256SARN(insSz + 1) : mkV256SHRN(insSz + 1);
++ assign(rLo, binop(mkV256PACKEV(insSz),
++ mkV256(0x0000),
++ binop(shOp, EX(sJ), mkU8(uImm))));
++ assign(rHi, binop(mkV256PACKEV(insSz),
++ mkV256(0x0000),
++ binop(shOp, EX(sD), mkU8(uImm))));
++ assign(res, binop(Iop_InterleaveLO64x4, EX(rHi), EX(rLo)));
++ }
++
++ const HChar *nm = isSAR ? "xvsrani" : "xvsrlni";
++ DIP("%s.%s %s, %s, %u\n", nm, mkInsExtSize(insSz),
++ nameXReg(xd), nameXReg(xj), uImm);
++ putXReg(xd, EX(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1101_1010 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vsrlarn ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isSAR = SLICE(insn, 17, 17);
+
-+ switch (SLICE(insn, 21, 18)) {
-+ case 0b0111:
-+ ok = disInstr_LOONGARCH64_WRK_01_1101_1010_0111(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ IRTemp arg = newTemp(Ity_V128);
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp sK = newTemp(Ity_V128);
++ IROp shOp = isSAR ? mkV128SAR(insSz) : mkV128SHR(insSz);
++ const HChar *nm = isSAR ? "vsrarn" : "vsrlrn";
++
++ assign(sJ, getVReg(vj));
++ assign(sK, getVReg(vk));
++ arg = vsrlr_ops(sJ, sK, shOp, insSz);
++ assign(res, binop(mkV128PACKEV(insSz - 1),
++ mkV128(0x0000),
++ EX(arg)));
++
++ DIP("%s.%s %s, %s, %s\n", nm, mkInsExtSize(insSz),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++ putVReg(vd, EX(res));
++ return True;
++}
++
++static Bool gen_xvsrlarn ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isSAR = SLICE(insn, 17, 17);
++
++ IRTemp arg = newTemp(Ity_V256);
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sK = newTemp(Ity_V256);
++ IROp shOp = isSAR ? mkV256SAR(insSz) : mkV256SHR(insSz);
++ const HChar *nm = isSAR ? "vsrarn" : "vsrlrn";
++
++ assign(sJ, getXReg(xj));
++ assign(sK, getXReg(xk));
++ arg = xvsrlr_ops(sJ, sK, shOp, insSz);
++ assign(res, binop(mkV256PACKEV(insSz - 1),
++ mkV256(0x0000),
++ EX(arg)));
++
++ DIP("%s.%s %s, %s, %s\n", nm, mkInsExtSize(insSz),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, EX(res));
++ return True;
++}
++
++static IRTemp gen_vsrlarn_d_q ( IRTemp src, UInt isSAR, UInt imm )
++{
++ IRTemp sHi = newTemp(Ity_I64);
++ IRTemp sLo = newTemp(Ity_I64);
++ IRTemp rHi = newTemp(Ity_I64);
++ IRTemp rLo = newTemp(Ity_I64);
++ IRTemp ro = newTemp(Ity_I64);
++ IRTemp z64 = newTemp(Ity_I64);
++ IRTemp res = newTemp(Ity_V128);
++ IROp shOp = isSAR ? Iop_Sar64 : Iop_Shr64;
++ assign(z64, mkU64(0));
++
++ assign(sHi, unop(Iop_V128HIto64, EX(src)));
++ assign(sLo, unop(Iop_V128to64, EX(src)));
++
++ if (imm == 0)
++ return src;
++
++ if (imm < 64) {
++ assign(rLo, binop(Iop_Or64, binop(Iop_Shl64,
++ EX(sHi), mkU8(64 - imm)),
++ binop(Iop_Shr64,
++ EX(sLo), mkU8(imm))));
++ assign(rHi, binop(shOp, EX(sHi), mkU8(imm)));
++
++ assign(ro, binop(Iop_Shr64,
++ binop(Iop_Shl64,
++ EX(sLo), mkU8(64 - imm)),
++ mkU8(63)));
++ } else if (imm == 64) {
++ assign(rLo, EX(sHi));
++ if (isSAR)
++ assign(rHi, binop(Iop_Sar64, EX(sHi), mkU8(63)));
++ else
++ assign(rHi, EX(z64));
++ assign(ro, binop(Iop_Shr64, EX(sLo), mkU8(63)));
++
++ } else {
++ assign(rLo, binop(shOp, EX(sHi), mkU8(imm - 64)));
++ assign(rHi, binop(shOp, EX(sHi), mkU8(63)));
++ assign(ro, binop(Iop_Shr64,
++ binop(Iop_Shl64,
++ EX(sHi), mkU8(128 - imm)),
++ mkU8(63)));
+ }
+
-+ return ok;
++ assign(res, binop(Iop_Add128x1,
++ mkV128from64s(rHi, rLo),
++ mkV128from64s(z64, ro)));
++ return res;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1101_1100 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vsrlarni ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
++ UInt isSAR = SLICE(insn, 19, 19);
+
-+ switch (SLICE(insn, 21, 18)) {
-+ case 0b0000:
-+ ok = gen_xvpickve(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ UInt uImm, insSz;
++ if ((insImm & 0xf0) == 0x10) { // 0001mmmm; b
++ uImm = insImm & 0x0f;
++ insSz = 0;
++ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; h
++ uImm = insImm & 0x1f;
++ insSz = 1;
++ } else if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; w
++ uImm = insImm & 0x3f;
++ insSz = 2;
++ } else if ((insImm & 0x80) == 0x80) { // 1mmmmmmm; d
++ uImm = insImm & 0x7f;
++ insSz = 3;
++ } else {
++ vassert(0);
+ }
+
-+ return ok;
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp sD = newTemp(Ity_V128);
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp jr = newTemp(Ity_V128);
++ IRTemp dr = newTemp(Ity_V128);
++ assign(sJ, getVReg(vj));
++ assign(sD, getVReg(vd));
++
++ if (insSz == 3) {
++ jr = gen_vsrlarn_d_q(sJ, isSAR, uImm);
++ dr = gen_vsrlarn_d_q(sD, isSAR, uImm);
++ } else {
++ IROp shOp = isSAR ? mkV128SARN(insSz + 1) : mkV128SHRN(insSz + 1);
++ jr = vsrlari_ops(sJ, shOp, insSz + 1, uImm, True);
++ dr = vsrlari_ops(sD, shOp, insSz + 1, uImm, True);
++ }
++
++ assign(rLo, binop(mkV128PACKEV(insSz), mkV128(0x0000), EX(jr)));
++ assign(rHi, binop(mkV128PACKEV(insSz), mkV128(0x0000), EX(dr)));
++ const HChar *nm = isSAR ? "vsrarni" : "vsrlrni";
++ DIP("%s.%s %s, %s, %u\n", nm, mkInsExtSize(insSz),
++ nameVReg(vd), nameVReg(vj), uImm);
++ putVReg(vd, binop(Iop_InterleaveLO64x2, EX(rHi), EX(rLo)));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1101_1111 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvsrlarni ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
++ UInt isSAR = SLICE(insn, 19, 19);
+
-+ switch (SLICE(insn, 21, 18)) {
-+ case 0b1001:
-+ case 0b1010:
-+ case 0b1011:
-+ ok = gen_xvpermi(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
++ UInt uImm, insSz;
++ if ((insImm & 0xf0) == 0x10) { // 0001mmmm; b
++ uImm = insImm & 0x0f;
++ insSz = 0;
++ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; h
++ uImm = insImm & 0x1f;
++ insSz = 1;
++ } else if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; w
++ uImm = insImm & 0x3f;
++ insSz = 2;
++ } else if ((insImm & 0x80) == 0x80) { // 1mmmmmmm; d
++ uImm = insImm & 0x7f;
++ insSz = 3;
++ } else {
++ vassert(0);
+ }
+
-+ return ok;
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sD = newTemp(Ity_V256);
++ IRTemp rHi = newTemp(Ity_V256);
++ IRTemp rLo = newTemp(Ity_V256);
++ IRTemp jr = newTemp(Ity_V256);
++ IRTemp dr = newTemp(Ity_V256);
++ assign(sJ, getXReg(xj));
++ assign(sD, getXReg(xd));
++
++ if (insSz == 3) {
++ IRTemp jHi, jLo, dHi, dLo;
++ jHi = jLo = dHi = dLo = IRTemp_INVALID;
++ breakupV256toV128s(sJ, &jHi, &jLo);
++ breakupV256toV128s(sD, &dHi, &dLo);
++ IRTemp rjHi, rjLo, rdHi, rdLo;
++ rjHi = rjLo = rdHi = rdLo = newTemp(Ity_V128);
++ rjHi = gen_vsrlarn_d_q(jHi, isSAR, uImm);
++ rjLo = gen_vsrlarn_d_q(jLo, isSAR, uImm);
++ rdHi = gen_vsrlarn_d_q(dHi, isSAR, uImm);
++ rdLo = gen_vsrlarn_d_q(dLo, isSAR, uImm);
++ assign(jr, mkV256from128s(rjHi, rjLo));
++ assign(dr, mkV256from128s(rdHi, rdLo));
++ } else {
++ IROp shOp = isSAR ? mkV256SARN(insSz + 1) : mkV256SHRN(insSz + 1);
++ jr = vsrlari_ops(sJ, shOp, insSz + 1, uImm, False);
++ dr = vsrlari_ops(sD, shOp, insSz + 1, uImm, False);
++ }
++
++ assign(rLo, binop(mkV256PACKEV(insSz), mkV256(0x0000), EX(jr)));
++ assign(rHi, binop(mkV256PACKEV(insSz), mkV256(0x0000), EX(dr)));
++ const HChar *nm = isSAR ? "xvsrarni" : "xvsrlrni";
++ DIP("%s.%s %s, %s, %u\n", nm, mkInsExtSize(insSz),
++ nameXReg(xd), nameXReg(xj), uImm);
++ putXReg(xd, binop(Iop_InterleaveLO64x4, EX(rHi), EX(rLo)));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01_1101 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_vbitops ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt insTy = SLICE(insn, 18, 17);
+
-+ switch (SLICE(insn, 25, 22)) {
-+ case 0b0000:
-+ ok = disInstr_LOONGARCH64_WRK_01_1101_0000(dres, insn, archinfo, abiinfo);
++ IRTemp dup = newTemp(Ity_V128);
++ IRTemp argR = newTemp(Ity_V128);
++ IRTemp res = newTemp(Ity_V128);
++
++ switch (insSz) {
++ case 0b00:
++ assign(dup, unop(Iop_Dup8x16, mkU8(1)));
+ break;
-+ case 0b0001:
-+ ok = disInstr_LOONGARCH64_WRK_01_1101_0001(dres, insn, archinfo, abiinfo);
++ case 0b01:
++ assign(dup, unop(Iop_Dup16x8, mkU16(1)));
+ break;
-+ case 0b0100:
-+ ok = disInstr_LOONGARCH64_WRK_01_1101_0100(dres, insn, archinfo, abiinfo);
++ case 0b10:
++ assign(dup, unop(Iop_Dup32x4, mkU32(1)));
+ break;
-+ case 0b1010:
-+ ok = disInstr_LOONGARCH64_WRK_01_1101_1010(dres, insn, archinfo, abiinfo);
++ case 0b11:
++ assign(dup, binop(Iop_64HLtoV128, mkU64(1), mkU64(1)));
+ break;
-+ case 0b1100:
-+ ok = disInstr_LOONGARCH64_WRK_01_1101_1100(dres, insn, archinfo, abiinfo);
++ default: vassert(0);
++ }
++
++ assign(argR, binop(mkV128SHL(insSz), EX(dup), getVReg(vk)));
++ switch (insTy) {
++ case 0b10:
++ assign(res, binop(Iop_AndV128,
++ getVReg(vj), unop(Iop_NotV128, EX(argR))));
+ break;
-+ case 0b1111:
-+ ok = disInstr_LOONGARCH64_WRK_01_1101_1111(dres, insn, archinfo, abiinfo);
++ case 0b11:
++ assign(res, binop(Iop_OrV128, getVReg(vj), EX(argR)));
+ break;
-+ default:
-+ ok = False;
++ case 0b00:
++ assign(res, binop(Iop_XorV128, getVReg(vj), EX(argR)));
+ break;
++ default: vassert(0);
+ }
+
-+ return ok;
++ const HChar *nm[4] = { "vbitrev", "", "vbitclr", "vbitset" };
++ DIP("%s.%s %s, %s, %s\n", nm[insTy], mkInsSize(insSz),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++ putVReg(vd, EX(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK_01 ( DisResult* dres, UInt insn,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo )
++static Bool gen_xvbitops ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Bool ok;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt insTy = SLICE(insn, 18, 17);
+
-+ switch (SLICE(insn, 29, 26)) {
-+ case 0b0000:
-+ ok = gen_beqz(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0001:
-+ ok = gen_bnez(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0010:
-+ switch (SLICE(insn, 9, 8)) {
-+ case 0b00:
-+ ok = gen_bceqz(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b01:
-+ ok = gen_bcnez(dres, insn, archinfo, abiinfo);
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
-+ break;
-+ case 0b0011:
-+ ok = gen_jirl(dres, insn, archinfo, abiinfo);
-+ break;
-+ case 0b0100:
-+ ok = gen_b(dres, insn, archinfo, abiinfo);
++ IRTemp dup = newTemp(Ity_V128);
++ IRTemp shl = newTemp(Ity_V256);
++ IRTemp res = newTemp(Ity_V256);
++
++ switch (insSz) {
++ case 0b00:
++ assign(dup, unop(Iop_Dup8x16, mkU8(1)));
+ break;
-+ case 0b0101:
-+ ok = gen_bl(dres, insn, archinfo, abiinfo);
++ case 0b01:
++ assign(dup, unop(Iop_Dup16x8, mkU16(1)));
+ break;
-+ case 0b0110:
-+ ok = gen_beq(dres, insn, archinfo, abiinfo);
++ case 0b10:
++ assign(dup, unop(Iop_Dup32x4, mkU32(1)));
+ break;
-+ case 0b0111:
-+ ok = gen_bne(dres, insn, archinfo, abiinfo);
++ case 0b11:
++ assign(dup, binop(Iop_64HLtoV128, mkU64(1), mkU64(1)));
+ break;
-+ case 0b1000:
-+ ok = gen_blt(dres, insn, archinfo, abiinfo);
++ default: vassert(0);
++ }
++
++ assign(shl, binop(mkV256SHL(insSz),
++ mkV256from128s(dup, dup),
++ getXReg(xk)));
++ switch (insTy) {
++ case 0b10:
++ assign(res, binop(Iop_AndV256,
++ getXReg(xj),
++ unop(Iop_NotV256, EX(shl))));
+ break;
-+ case 0b1001:
-+ ok = gen_bge(dres, insn, archinfo, abiinfo);
++ case 0b11:
++ assign(res, binop(Iop_OrV256, getXReg(xj), EX(shl)));
+ break;
-+ case 0b1010:
-+ ok = gen_bltu(dres, insn, archinfo, abiinfo);
++ case 0b00:
++ assign(res, binop(Iop_XorV256, getXReg(xj), EX(shl)));
+ break;
-+ case 0b1011:
-+ ok = gen_bgeu(dres, insn, archinfo, abiinfo);
++ default: vassert(0);
++ }
++
++ const HChar *nm[4] = { "xvbitrev", "", "xvbitclr", "xvbitset" };
++ DIP("%s.%s %s, %s, %s\n", nm[insTy], mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, EX(res));
++ return True;
++}
++
++static Bool gen_vbitops_imm ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
++ UInt insTy = SLICE(insn, 19, 18);
++
++ UInt insSz, uImm;
++ if ((insImm & 0xf8) == 0x8) { // 00001mmm; b
++ uImm = insImm & 0x07;
++ insSz = 0;
++ } else if ((insImm & 0xf0) == 0x10) { // 0001mmmm; h
++ uImm = insImm & 0x0f;
++ insSz = 1;
++ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; w
++ uImm = insImm & 0x1f;
++ insSz = 2;
++ } else if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; d
++ uImm = insImm & 0x3f;
++ insSz = 3;
++ } else {
++ vassert(0);
++ }
++
++ IRTemp dup = newTemp(Ity_V128);
++ IRTemp shl = newTemp(Ity_V128);
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp src = newTemp(Ity_V128);
++ switch (insSz) {
++ case 0b00: assign(dup, unop(Iop_Dup8x16, mkU8(1))); break;
++ case 0b01: assign(dup, unop(Iop_Dup16x8, mkU16(1))); break;
++ case 0b10: assign(dup, unop(Iop_Dup32x4, mkU32(1))); break;
++ case 0b11:
++ assign(dup, binop(Iop_64HLtoV128, mkU64(1), mkU64(1)));
+ break;
-+ case 0b1100:
-+ ok = disInstr_LOONGARCH64_WRK_01_1100(dres, insn, archinfo, abiinfo);
++ default: vassert(0);
++ }
++
++ assign(src, getVReg(vj));
++ assign(shl, binop(mkV128SHLN(insSz), EX(dup), mkU8(uImm)));
++ switch (insTy) {
++ case 0b00:
++ assign(res, binop(Iop_AndV128,
++ EX(src),
++ unop(Iop_NotV128, EX(shl))));
+ break;
-+ case 0b1101:
-+ ok = disInstr_LOONGARCH64_WRK_01_1101(dres, insn, archinfo, abiinfo);
++ case 0b01:
++ assign(res, binop(Iop_OrV128, EX(src), EX(shl)));
+ break;
-+ default:
-+ ok = False;
++ case 0b10:
++ assign(res, binop(Iop_XorV128, EX(src), EX(shl)));
+ break;
++ default: vassert(0);
+ }
+
-+ return ok;
++ const HChar *nm[3] = { "vbitrevi", "vbitclri", "vbitseti" };
++ DIP("%s.%s %s, %u\n", nm[insTy], mkInsSize(insSz), nameVReg(vd), uImm);
++ putVReg(vd, mkexpr(res));
++ return True;
+}
+
-+static Bool disInstr_LOONGARCH64_WRK ( /*MB_OUT*/DisResult* dres,
-+ const UChar* guest_instr,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo,
-+ Bool sigill_diag )
++static Bool gen_xvbitops_imm ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ /* Set result defaults. */
-+ dres->whatNext = Dis_Continue;
-+ dres->len = 4;
-+ dres->jk_StopHere = Ijk_INVALID;
-+ dres->hint = Dis_HintNone;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
++ UInt insTy = SLICE(insn, 19, 18);
+
-+ /* At least this is simple on LOONGARCH64: insns are all 4 bytes long,
-+ and 4-aligned. So just fish the whole thing out of memory right now
-+ and have done. */
-+ UInt insn = getUInt(guest_instr);
-+ DIP("\t0x%llx:\t0x%08x\t", (Addr64)guest_PC_curr_instr, insn);
-+ vassert((guest_PC_curr_instr & 3ULL) == 0);
++ UInt insSz, uImm;
++ if ((insImm & 0xf8) == 0x8) { // 00001mmm; b
++ uImm = insImm & 0x07;
++ insSz = 0;
++ } else if ((insImm & 0xf0) == 0x10) { // 0001mmmm; h
++ uImm = insImm & 0x0f;
++ insSz = 1;
++ } else if ((insImm & 0xe0) == 0x20) { // 001mmmmm; w
++ uImm = insImm & 0x1f;
++ insSz = 2;
++ } else if ((insImm & 0xc0) == 0x40) { // 01mmmmmm; d
++ uImm = insImm & 0x3f;
++ insSz = 3;
++ } else {
++ vassert(0);
++ }
+
-+ /* Spot "Special" instructions (see comment at top of file). */
-+ Bool ok = disInstr_LOONGARCH64_WRK_special(dres, guest_instr);
-+ if (ok)
-+ return ok;
++ IRTemp dup = newTemp(Ity_V128);
++ IRTemp shl = newTemp(Ity_V256);
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp src = newTemp(Ity_V256);
++ switch (insSz) {
++ case 0b00: assign(dup, unop(Iop_Dup8x16, mkU8(1))); break;
++ case 0b01: assign(dup, unop(Iop_Dup16x8, mkU16(1))); break;
++ case 0b10: assign(dup, unop(Iop_Dup32x4, mkU32(1))); break;
++ case 0b11:
++ assign(dup, binop(Iop_64HLtoV128, mkU64(1), mkU64(1)));
++ break;
++ default: vassert(0);
++ }
+
-+ /* Main LOONGARCH64 instruction decoder starts here. */
-+ switch (SLICE(insn, 31, 30)) {
++ assign(src, getXReg(xj));
++ assign(shl, binop(mkV256SHLN(insSz),
++ mkV256from128s(dup, dup),
++ mkU8(uImm)));
++ switch (insTy) {
+ case 0b00:
-+ ok = disInstr_LOONGARCH64_WRK_00(dres, insn, archinfo, abiinfo);
++ assign(res, binop(Iop_AndV256,
++ EX(src),
++ unop(Iop_NotV256, EX(shl))));
+ break;
+ case 0b01:
-+ ok = disInstr_LOONGARCH64_WRK_01(dres, insn, archinfo, abiinfo);
++ assign(res, binop(Iop_OrV256, EX(src), EX(shl)));
+ break;
-+ default:
-+ ok = False;
++ case 0b10:
++ assign(res, binop(Iop_XorV256, EX(src), EX(shl)));
+ break;
++ default: vassert(0);
+ }
+
-+ /* If the next-level down decoders failed, make sure |dres| didn't
-+ get changed. */
-+ if (!ok) {
-+ vassert(dres->whatNext == Dis_Continue);
-+ vassert(dres->len == 4);
-+ vassert(dres->jk_StopHere == Ijk_INVALID);
-+ }
-+ return ok;
++ const HChar *nm[3] = { "xvbitrevi", "xvbitclri", "xvbitseti" };
++ DIP("%s.%s %s, %u\n", nm[insTy], mkInsSize(insSz), nameXReg(xd), uImm);
++ putXReg(xd, mkexpr(res));
++ return True;
+}
+
+
+/*------------------------------------------------------------*/
-+/*--- Top-level fn ---*/
++/*--- Helpers for vector string processing insns ---*/
+/*------------------------------------------------------------*/
+
-+/* Disassemble a single instruction into IR. The instruction
-+ is located in host memory at &guest_code[delta]. */
-+
-+DisResult disInstr_LOONGARCH64 ( IRSB* irsb_IN,
-+ const UChar* guest_code_IN,
-+ Long delta_IN,
-+ Addr guest_IP,
-+ VexArch guest_arch,
-+ const VexArchInfo* archinfo,
-+ const VexAbiInfo* abiinfo,
-+ VexEndness host_endness_IN,
-+ Bool sigill_diag_IN )
++static IRTemp calculate_vfrstp ( IRTemp src, IRTemp dst, UInt insSz, IRExpr* index )
+{
-+ DisResult dres;
-+ vex_bzero(&dres, sizeof(dres));
-+
-+ /* Set globals (see top of this file) */
-+ vassert(guest_arch == VexArchLOONGARCH64);
-+
-+ irsb = irsb_IN;
-+ host_endness = host_endness_IN;
-+ guest_PC_curr_instr = (Addr64)guest_IP;
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp data[2];
++ UInt i;
+
-+ /* Try to decode */
-+ Bool ok = disInstr_LOONGARCH64_WRK(&dres,
-+ &guest_code_IN[delta_IN],
-+ archinfo, abiinfo, sigill_diag_IN);
++ for (i = 0; i < 2; i++) {
++ data[i] = newTemp(Ity_I64);
++ assign(data[i], binop(Iop_GetElem64x2, EX(src), mkU8(i)));
++ }
+
-+ if (ok) {
-+ /* All decode successes end up here. */
-+ vassert(dres.len == 4 || dres.len == 20);
-+ switch (dres.whatNext) {
-+ case Dis_Continue:
-+ putPC(mkU64(dres.len + guest_PC_curr_instr));
-+ break;
-+ case Dis_StopHere:
-+ break;
-+ default:
-+ vassert(0);
-+ break;
-+ }
-+ DIP("\n");
-+ } else {
-+ /* All decode failures end up here. */
-+ if (sigill_diag_IN) {
-+ Int i, j;
-+ UChar buf[64];
-+ UInt insn = getUInt(&guest_code_IN[delta_IN]);
-+ vex_bzero(buf, sizeof(buf));
-+ for (i = j = 0; i < 32; i++) {
-+ if (i > 0 && (i & 3) == 0)
-+ buf[j++] = ' ';
-+ buf[j++] = (insn & (1 << (31 - i))) ? '1' : '0';
-+ }
-+ vex_printf("disInstr(loongarch64): unhandled instruction 0x%08x\n", insn);
-+ vex_printf("disInstr(loongarch64): %s\n", buf);
-+ }
++ IRExpr** arg = mkIRExprVec_3(mkU64(insSz), mkexpr(data[1]), mkexpr(data[0]));
++ IRExpr* call = mkIRExprCCall(Ity_I64, 0/*regparms*/,
++ "loongarch64_calculate_negative_id",
++ &loongarch64_calculate_negative_id,
++ arg);
+
-+ /* Tell the dispatcher that this insn cannot be decoded, and so
-+ has not been executed, and (is currently) the next to be
-+ executed. PC should be up-to-date since it is made so at the
-+ start of each insn, but nevertheless be paranoid and update
-+ it again right now. */
-+ putPC(mkU64(guest_PC_curr_instr));
-+ dres.len = 0;
-+ dres.whatNext = Dis_StopHere;
-+ dres.jk_StopHere = Ijk_NoDecode;
++ switch (insSz) {
++ case 0b00:
++ assign(res, triop(Iop_SetElem8x16,
++ EX(dst), index, unop(Iop_64to8, call)));
++ break;
++ case 0b01:
++ assign(res, triop(Iop_SetElem16x8,
++ EX(dst), index, unop(Iop_64to16, call)));
++ break;
++ default: vassert(0);
+ }
+
-+ return dres;
++ return res;
+}
+
++static Bool gen_vfrstp ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 15, 15);
+
-+/*--------------------------------------------------------------------*/
-+/*--- end guest_loongarch64_toIR.c ---*/
-+/*--------------------------------------------------------------------*/
-diff --git a/VEX/priv/host_loongarch64_defs.c b/VEX/priv/host_loongarch64_defs.c
-new file mode 100644
-index 0000000..6b50970
---- /dev/null
-+++ b/VEX/priv/host_loongarch64_defs.c
-@@ -0,0 +1,3929 @@
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp sK = newTemp(Ity_V128);
++ IRExpr* index;
++ assign(sJ, getVReg(vj));
++ assign(sK, getVReg(vd));
++
++ if (insSz == 0) {
++ index = binop(Iop_And8, binop(Iop_GetElem8x16, getVReg(vk), mkU8(0)), mkU8(0xf));
++ } else {
++ index = binop(Iop_And16, binop(Iop_GetElem16x8, getVReg(vk), mkU8(0)), mkU16(0x7));
++ }
+
-+/*---------------------------------------------------------------*/
-+/*--- begin host_loongarch64_defs.c ---*/
-+/*---------------------------------------------------------------*/
++ res = calculate_vfrstp(sJ, sK, insSz, index);
++ DIP("vfrstp.%s %s, %s, %s\n", mkInsSize(insSz),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++ putVReg(vd, mkexpr(res));
++ return True;
++}
+
-+/*
-+ This file is part of Valgrind, a dynamic binary instrumentation
-+ framework.
++static Bool gen_vfrstpi ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt ui5 = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
+
-+ Copyright (C) 2021-2022 Loongson Technology Corporation Limited
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp sK = newTemp(Ity_V128);
++ IRExpr* index = (insSz == 0b00) ? mkU8(ui5 % 16) : mkU8(ui5 % 8);
++ assign(sJ, getVReg(vj));
++ assign(sK, getVReg(vd));
++ res = calculate_vfrstp(sJ, sK, insSz, index);
++
++ DIP("vfrstpi.%s %s, %s, %u\n", mkInsSize(insSz),
++ nameVReg(vd), nameVReg(vj), ui5);
++ putVReg(vd, EX(res));
++ return True;
++}
+
-+ This program is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License as
-+ published by the Free Software Foundation; either version 2 of the
-+ License, or (at your option) any later version.
++static Bool gen_xvfrstpi ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt ui5 = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
+
-+ This program is distributed in the hope that it will be useful, but
-+ WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ General Public License for more details.
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sK = newTemp(Ity_V256);
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp jHi = IRTemp_INVALID;
++ IRTemp jLo = IRTemp_INVALID;
++ IRTemp kHi = IRTemp_INVALID;
++ IRTemp kLo = IRTemp_INVALID;
++ IRExpr* index = (insSz == 0b00) ? mkU8(ui5 % 16) : mkU8(ui5 % 8);
++ assign(sJ, getXReg(xj));
++ assign(sK, getXReg(xd));
++ breakupV256toV128s(sJ, &jHi, &jLo);
++ breakupV256toV128s(sK, &kHi, &kLo);
++ rHi = calculate_vfrstp(jHi, kHi, insSz, index);
++ rLo = calculate_vfrstp(jLo, kLo, insSz, index);
++
++ DIP("xvfrstpi.%s %s, %s, %u\n", mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj), ui5);
++ putXReg(xd, mkV256from128s(rHi, rLo));
++ return True;
++}
+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, see .
++/*------------------------------------------------------------*/
++/*--- Helpers for vector floating point conversion insns ---*/
++/*------------------------------------------------------------*/
+
-+ The GNU General Public License is contained in the file COPYING.
-+*/
++static Bool gen_vfrintrm_s ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
+
-+#include "libvex_basictypes.h"
-+#include "libvex.h"
-+#include "libvex_trc_values.h"
++ DIP("vfrintrm.s %s, %s\n", nameVReg(vd), nameVReg(vj));
+
-+#include "main_util.h"
-+#include "host_generic_regs.h"
-+#include "host_loongarch64_defs.h"
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
++ UInt i;
+
-+/* --------- Local helpers. --------- */
++ for (i = 0; i < 4; i++) {
++ putVReg(vd, unop(Iop_RoundF32x4_RM, getVReg(vj)));
++ }
+
-+static inline void mapReg ( HRegRemap* m, HReg* r )
-+{
-+ *r = lookupHRegRemap(m, *r);
++ return True;
+}
+
-+static inline Int extend ( UInt imm, UInt size )
++static Bool gen_vfrintrm_d ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ UInt shift = 32 - size;
-+ return (((Int)imm << shift) >> shift);
-+}
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
+
++ DIP("vfrintrm.s %s, %s\n", nameVReg(vd), nameVReg(vj));
+
-+/* --------- Registers. --------- */
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+const RRegUniverse* getRRegUniverse_LOONGARCH64 ( void )
++ UInt i;
++
++ for (i = 0; i < 2; i++) {
++ putVReg(vd, unop(Iop_RoundF64x2_RM, getVReg(vj)));
++ }
++
++ return True;
++}
++
++static Bool gen_vfrintrp_s ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ /* The real-register universe is a big constant, so we just want to
-+ initialise it once. */
-+ static RRegUniverse rRegUniverse_LOONGARCH64;
-+ static Bool rRegUniverse_LOONGARCH64_initted = False;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
+
-+ /* Handy shorthand, nothing more */
-+ RRegUniverse* ru = &rRegUniverse_LOONGARCH64;
++ DIP("vfrintrp.s %s, %s\n", nameVReg(vd), nameVReg(vj));
+
-+ /* This isn't thread-safe. Sigh. */
-+ if (LIKELY(rRegUniverse_LOONGARCH64_initted == True))
-+ return ru;
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+ RRegUniverse__init(ru);
++ UInt i;
+
-+ /* Add the registers. The initial segment of this array must be
-+ those available for allocation by reg-alloc, and those that
-+ follow are not available for allocation. */
-+ ru->allocable_start[HRcInt64] = ru->size;
-+ ru->regs[ru->size++] = hregLOONGARCH64_R23();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R24();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R25();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R26();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R27();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R28();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R29();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R30();
-+ // $r31 is used as guest stack pointer, not available to regalloc.
++ for (i = 0; i < 4; i++) {
++ putVReg(vd, unop(Iop_RoundF32x4_RP, getVReg(vj)));
++ }
+
-+ // $r12 is used as a chaining/ProfInc/Cmove/genSpill/genReload temporary
-+ // $r13 is used as a ProfInc temporary
-+ ru->regs[ru->size++] = hregLOONGARCH64_R14();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R15();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R16();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R17();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R18();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R19();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R20();
-+ ru->allocable_end[HRcInt64] = ru->size - 1;
++ return True;
++}
+
-+ ru->allocable_start[HRcFlt64] = ru->size;
-+ ru->regs[ru->size++] = hregLOONGARCH64_F24();
-+ ru->regs[ru->size++] = hregLOONGARCH64_F25();
-+ ru->regs[ru->size++] = hregLOONGARCH64_F26();
-+ ru->regs[ru->size++] = hregLOONGARCH64_F27();
-+ ru->regs[ru->size++] = hregLOONGARCH64_F28();
-+ ru->regs[ru->size++] = hregLOONGARCH64_F29();
-+ ru->regs[ru->size++] = hregLOONGARCH64_F30();
-+ ru->regs[ru->size++] = hregLOONGARCH64_F31();
-+ ru->allocable_end[HRcFlt64] = ru->size - 1;
++static Bool gen_vfrintrp_d ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
+
-+ ru->allocable_start[HRcVec128] = ru->size;
-+ ru->regs[ru->size++] = hregLOONGARCH64_V24();
-+ ru->regs[ru->size++] = hregLOONGARCH64_V25();
-+ ru->regs[ru->size++] = hregLOONGARCH64_V26();
-+ ru->regs[ru->size++] = hregLOONGARCH64_V27();
-+ ru->regs[ru->size++] = hregLOONGARCH64_V28();
-+ ru->regs[ru->size++] = hregLOONGARCH64_V29();
-+ ru->regs[ru->size++] = hregLOONGARCH64_V30();
-+ ru->regs[ru->size++] = hregLOONGARCH64_V31();
-+ ru->allocable_end[HRcVec128] = ru->size - 1;
++ DIP("vfrintrp.s %s, %s\n", nameVReg(vd), nameVReg(vj));
+
-+ ru->allocable = ru->size;
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+ /* And other regs, not available to the allocator. */
-+ ru->regs[ru->size++] = hregLOONGARCH64_R0();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R1();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R2();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R3();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R4();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R5();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R6();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R7();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R8();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R9();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R10();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R11();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R12();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R13();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R21();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R22();
-+ ru->regs[ru->size++] = hregLOONGARCH64_R31();
-+ ru->regs[ru->size++] = hregLOONGARCH64_FCSR3();
++ UInt i;
+
-+ rRegUniverse_LOONGARCH64_initted = True;
++ for (i = 0; i < 2; i++) {
++ putVReg(vd, unop(Iop_RoundF64x2_RP, getVReg(vj)));
++ }
+
-+ RRegUniverse__check_is_sane(ru);
-+ return ru;
++ return True;
+}
+
-+UInt ppHRegLOONGARCH64 ( HReg reg )
++static Bool gen_vfrintrz_s ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ Int r;
-+ Int ret = 0;
-+ static const HChar* ireg_names[32] = {
-+ "$zero",
-+ "$ra",
-+ "$tp",
-+ "$sp",
-+ "$a0", "$a1", "$a2", "$a3", "$a4", "$a5", "$a6", "$a7",
-+ "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8",
-+ "$r21", /* Reserved */
-+ "$fp",
-+ "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7", "$s8"
-+ };
-+ static const HChar* freg_names[32] = {
-+ "$fa0", "$fa1", "$fa2", "$fa3", "$fa4", "$fa5", "$fa6", "$fa7",
-+ "$ft0", "$ft1", "$ft2", "$ft3", "$ft4", "$ft5", "$ft6", "$ft7",
-+ "$ft8", "$ft9", "$ft10", "$ft11", "$ft12", "$ft13", "$ft14", "$ft15",
-+ "$fs0", "$fs1", "$fs2", "$fs3", "$fs4", "$fs5", "$fs6", "$fs7"
-+ };
-+ static const HChar* vreg_names[32] = {
-+ "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6", "$vr7",
-+ "$vr8", "$vr9", "$vr10", "$vr11", "$vr12", "$vr13", "$vr14", "$vr15",
-+ "$vr16", "$vr17", "$vr18", "$vr19", "$vr20", "$vr21", "$vr22", "$vr23",
-+ "$vr24", "$vr25", "$vr26", "$vr27", "$vr28", "$vr29", "$vr30", "$vr31"
-+ };
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
+
-+ /* Be generic for all virtual regs. */
-+ if (hregIsVirtual(reg)) {
-+ return ppHReg(reg);
++ DIP("vfrintrz.s %s, %s\n", nameVReg(vd), nameVReg(vj));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
+
-+ /* But specific for real regs. */
-+ switch (hregClass(reg)) {
-+ case HRcInt32:
-+ r = hregEncoding(reg);
-+ vassert(r < 4);
-+ ret = vex_printf("$fcsr%d", r);
-+ break;
-+ case HRcInt64:
-+ r = hregEncoding(reg);
-+ vassert(r < 32);
-+ ret = vex_printf("%s", ireg_names[r]);
-+ break;
-+ case HRcFlt64:
-+ r = hregEncoding(reg);
-+ vassert(r < 32);
-+ ret = vex_printf("%s", freg_names[r]);
-+ break;
-+ case HRcVec128:
-+ r = hregEncoding(reg);
-+ vassert(r < 32);
-+ ret = vex_printf("%s", vreg_names[r]);
-+ break;
-+ default:
-+ vpanic("ppHRegLOONGARCH64");
-+ break;
++ UInt i;
++
++ for (i = 0; i < 4; i++) {
++ putVReg(vd, unop(Iop_RoundF32x4_RZ, getVReg(vj)));
+ }
+
-+ return ret;
++ return True;
+}
+
++static Bool gen_vfrintrz_d ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
+
-+/* --------- Condition codes, LOONGARCH64 encoding. --------- */
++ DIP("vfrintrz.s %s, %s\n", nameVReg(vd), nameVReg(vj));
+
-+static inline const HChar* showLOONGARCH64CondCode ( LOONGARCH64CondCode cond )
-+{
-+ const HChar* ret;
-+ switch (cond) {
-+ case LAcc_EQ:
-+ ret = "eq"; /* equal */
-+ break;
-+ case LAcc_NE:
-+ ret = "ne"; /* not equal */
-+ break;
-+ case LAcc_LT:
-+ ret = "lt"; /* less than (signed) */
-+ break;
-+ case LAcc_GE:
-+ ret = "ge"; /* great equal (signed) */
-+ break;
-+ case LAcc_LTU:
-+ ret = "ltu"; /* less than (unsigned) */
-+ break;
-+ case LAcc_GEU:
-+ ret = "geu"; /* great equal (unsigned) */
-+ break;
-+ case LAcc_AL:
-+ ret = "al"; /* always (unconditional) */
-+ break;
-+ default:
-+ vpanic("showLOONGARCH64CondCode");
-+ break;
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
-+ return ret;
-+}
+
++ UInt i;
+
-+/* --------- Memory address expressions (amodes). --------- */
++ for (i = 0; i < 2; i++) {
++ putVReg(vd, unop(Iop_RoundF64x2_RZ, getVReg(vj)));
++ }
+
-+LOONGARCH64AMode* LOONGARCH64AMode_RI ( HReg reg, UShort imm )
-+{
-+ LOONGARCH64AMode* am = LibVEX_Alloc_inline(sizeof(LOONGARCH64AMode));
-+ am->tag = LAam_RI;
-+ am->LAam.RI.base = reg;
-+ am->LAam.RI.index = imm;
-+ return am;
++ return True;
+}
+
-+LOONGARCH64AMode* LOONGARCH64AMode_RR ( HReg base, HReg index )
++static Bool gen_vfrintrne_s ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ LOONGARCH64AMode* am = LibVEX_Alloc_inline(sizeof(LOONGARCH64AMode));
-+ am->tag = LAam_RR;
-+ am->LAam.RR.base = base;
-+ am->LAam.RR.index = index;
-+ return am;
-+}
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
+
-+static inline void ppLOONGARCH64AMode ( LOONGARCH64AMode* am )
-+{
-+ switch (am->tag) {
-+ case LAam_RI:
-+ ppHRegLOONGARCH64(am->LAam.RI.base);
-+ vex_printf(", ");
-+ vex_printf("%d", extend((UInt)am->LAam.RI.index, 12));
-+ break;
-+ case LAam_RR:
-+ ppHRegLOONGARCH64(am->LAam.RR.base);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(am->LAam.RR.index);
-+ break;
-+ default:
-+ vpanic("ppLOONGARCH64AMode");
-+ break;
++ DIP("vfrintrne.s %s, %s\n", nameVReg(vd), nameVReg(vj));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
-+}
+
-+static inline void addRegUsage_LOONGARCH64AMode( HRegUsage* u,
-+ LOONGARCH64AMode* am )
-+{
-+ switch (am->tag) {
-+ case LAam_RI:
-+ addHRegUse(u, HRmRead, am->LAam.RI.base);
-+ break;
-+ case LAam_RR:
-+ addHRegUse(u, HRmRead, am->LAam.RR.base);
-+ addHRegUse(u, HRmRead, am->LAam.RR.index);
-+ break;
-+ default:
-+ vpanic("addRegUsage_LOONGARCH64AMode");
-+ break;
++ UInt i;
++
++ for (i = 0; i < 4; i++) {
++ putVReg(vd, unop(Iop_RoundF32x4_RN, getVReg(vj)));
+ }
++
++ return True;
+}
+
-+static inline void mapRegs_LOONGARCH64AMode( HRegRemap* m,
-+ LOONGARCH64AMode* am )
++static Bool gen_vfrintrne_d ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (am->tag) {
-+ case LAam_RI:
-+ mapReg(m, &am->LAam.RI.base);
-+ break;
-+ case LAam_RR:
-+ mapReg(m, &am->LAam.RR.base);
-+ mapReg(m, &am->LAam.RR.index);
-+ break;
-+ default:
-+ vpanic("mapRegs_LOONGARCH64AMode");
-+ break;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++
++ DIP("vfrintrne.s %s, %s\n", nameVReg(vd), nameVReg(vj));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
-+}
+
++ UInt i;
+
-+/* --------- Operand, which can be reg or imm. --------- */
++ for (i = 0; i < 2; i++) {
++ putVReg(vd, unop(Iop_RoundF64x2_RN, getVReg(vj)));
++ }
+
-+LOONGARCH64RI* LOONGARCH64RI_R ( HReg reg )
-+{
-+ LOONGARCH64RI* op = LibVEX_Alloc_inline(sizeof(LOONGARCH64RI));
-+ op->tag = LAri_Reg;
-+ op->LAri.R.reg = reg;
-+ return op;
++ return True;
+}
+
-+LOONGARCH64RI* LOONGARCH64RI_I ( UShort imm, UChar size, Bool isSigned )
-+{
-+ LOONGARCH64RI* op = LibVEX_Alloc_inline(sizeof(LOONGARCH64RI));
-+ op->tag = LAri_Imm;
-+ op->LAri.I.imm = imm;
-+ op->LAri.I.size = size;
-+ op->LAri.I.isSigned = isSigned;
-+ return op;
-+}
+
-+static inline void ppLOONGARCH64RI ( LOONGARCH64RI* ri )
++/*------------------------------------------------------------*/
++/*--- Helpers for vector comparison and selection insns ---*/
++/*------------------------------------------------------------*/
++
++static Bool gen_vcmp ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (ri->tag) {
-+ case LAri_Reg:
-+ ppHRegLOONGARCH64(ri->LAri.R.reg);
-+ break;
-+ case LAri_Imm:
-+ if (ri->LAri.I.isSigned) {
-+ vex_printf("%d", extend((UInt)ri->LAri.I.imm, ri->LAri.I.size));
-+ } else {
-+ vex_printf("%u", (UInt)ri->LAri.I.imm);
-+ }
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt insTy = SLICE(insn, 19, 17);
++
++ UInt szId = insSz;
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp sK = newTemp(Ity_V128);
++ assign(sJ, getVReg(vj));
++ assign(sK, getVReg(vk));
++
++ switch (insTy) {
++ case 0b000: {
++ assign(res, binop(mkV128CMPEQ(insSz), EX(sJ), EX(sK)));
+ break;
-+ default:
-+ vpanic("ppLOONGARCH64RI");
++ }
++ case 0b001: {
++ assign(res, binop(Iop_OrV128,
++ binop(mkV128CMPGTS(insSz), EX(sK), EX(sJ)),
++ binop(mkV128CMPEQ(insSz), EX(sJ), EX(sK))));
+ break;
-+ }
-+}
-+
-+static inline void addRegUsage_LOONGARCH64RI( HRegUsage* u, LOONGARCH64RI* ri )
-+{
-+ switch (ri->tag) {
-+ case LAri_Reg:
-+ addHRegUse(u, HRmRead, ri->LAri.R.reg);
++ }
++ case 0b010: {
++ assign(res, binop(Iop_OrV128,
++ binop(mkV128CMPGTU(insSz), EX(sK), EX(sJ)),
++ binop(mkV128CMPEQ(insSz), EX(sJ), EX(sK))));
++ szId = insSz + 4;
+ break;
-+ case LAri_Imm:
++ }
++ case 0b011: {
++ assign(res, binop(mkV128CMPGTS(insSz), EX(sK), EX(sJ)));
+ break;
-+ default:
-+ vpanic("addRegUsage_LOONGARCH64RI");
++ }
++ case 0b100: {
++ assign(res, binop(mkV128CMPGTU(insSz), EX(sK), EX(sJ)));
++ szId = insSz + 4;
+ break;
++ }
++ default: vassert(0);
++ }
++
++ const HChar *nm[5] = { "vseq", "vsle", "vsle", "vslt", "vslt" };
++ DIP("%s.%s %s, %s, %s\n", nm[insTy], mkInsSize(szId),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
++
++ putVReg(vd, mkexpr(res));
++ return True;
+}
+
-+static inline void mapRegs_LOONGARCH64RI( HRegRemap* m, LOONGARCH64RI* ri )
++static Bool gen_xvcmp ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (ri->tag) {
-+ case LAri_Reg:
-+ mapReg(m, &ri->LAri.R.reg);
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt insTy = SLICE(insn, 19, 17);
++
++ UInt szId = insSz;
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sK = newTemp(Ity_V256);
++ assign(sJ, getXReg(xj));
++ assign(sK, getXReg(xk));
++
++ switch (insTy) {
++ case 0b000: {
++ assign(res, binop(mkV256CMPEQ(insSz), EX(sJ), EX(sK)));
+ break;
-+ case LAri_Imm:
++ }
++ case 0b001: {
++ assign(res, binop(Iop_OrV256,
++ binop(mkV256CMPGTS(insSz), EX(sK), EX(sJ)),
++ binop(mkV256CMPEQ(insSz), EX(sJ), EX(sK))));
+ break;
-+ default:
-+ vpanic("mapRegs_LOONGARCH64RI");
++ }
++ case 0b010: {
++ assign(res, binop(Iop_OrV256,
++ binop(mkV256CMPGTU(insSz), EX(sK), EX(sJ)),
++ binop(mkV256CMPEQ(insSz), EX(sJ), EX(sK))));
++ szId = insSz + 4;
++ break;
++ }
++ case 0b011: {
++ assign(res, binop(mkV256CMPGTS(insSz), EX(sK), EX(sJ)));
+ break;
++ }
++ case 0b100: {
++ assign(res, binop(mkV256CMPGTU(insSz), EX(sK), EX(sJ)));
++ szId = insSz + 4;
++ break;
++ }
++ default: vassert(0);
+ }
-+}
+
++ const HChar *nm[5] = { "xvseq", "xvsle", "xvsle", "xvslt", "xvslt" };
++ DIP("%s.%s %s, %s, %s\n", nm[insTy], mkInsSize(szId),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
+
-+/* --------- Instructions. --------- */
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+static inline const HChar* showLOONGARCH64UnOp ( LOONGARCH64UnOp op )
-+{
-+ switch (op) {
-+ case LAun_CLZ_W:
-+ return "clz.w";
-+ case LAun_CTZ_W:
-+ return "ctz.w";
-+ case LAun_CLZ_D:
-+ return "clz.d";
-+ case LAun_CTZ_D:
-+ return "ctz.w";
-+ case LAun_EXT_W_H:
-+ return "ext.w.h";
-+ case LAun_EXT_W_B:
-+ return "ext.w.b";
-+ default:
-+ vpanic("showLOONGARCH64UnOp");
-+ break;
-+ }
++ putXReg(xd, EX(res));
++ return True;
+}
+
-+static inline const HChar* showLOONGARCH64BinOp ( LOONGARCH64BinOp op )
++static Bool gen_vcmpi ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (op) {
-+ case LAbin_ADD_W:
-+ return "add.w";
-+ case LAbin_ADD_D:
-+ return "add.d";
-+ case LAbin_SUB_W:
-+ return "sub.w";
-+ case LAbin_SUB_D:
-+ return "sub.d";
-+ case LAbin_NOR:
-+ return "nor";
-+ case LAbin_AND:
-+ return "and";
-+ case LAbin_OR:
-+ return "or";
-+ case LAbin_XOR:
-+ return "xor";
-+ case LAbin_SLL_W:
-+ return "sll.w";
-+ case LAbin_SRL_W:
-+ return "srl.w";
-+ case LAbin_SRA_W:
-+ return "sra.w";
-+ case LAbin_SLL_D:
-+ return "sll.d";
-+ case LAbin_SRL_D:
-+ return "srl.d";
-+ case LAbin_SRA_D:
-+ return "sra.d";
-+ case LAbin_MUL_W:
-+ return "mul.w";
-+ case LAbin_MUL_D:
-+ return "mul.d";
-+ case LAbin_MULH_W:
-+ return "mulh.w";
-+ case LAbin_MULH_WU:
-+ return "mulh.wu";
-+ case LAbin_MULH_D:
-+ return "mulh.d";
-+ case LAbin_MULH_DU:
-+ return "mulh.du";
-+ case LAbin_MULW_D_W:
-+ return "mulw.d.w";
-+ case LAbin_MULW_D_WU:
-+ return "mulw.d.wu";
-+ case LAbin_DIV_W:
-+ return "div.w";
-+ case LAbin_MOD_W:
-+ return "mod.w";
-+ case LAbin_DIV_WU:
-+ return "div.wu";
-+ case LAbin_MOD_WU:
-+ return "mod.wu";
-+ case LAbin_DIV_D:
-+ return "div.d";
-+ case LAbin_MOD_D:
-+ return "mod.d";
-+ case LAbin_DIV_DU:
-+ return "div.du";
-+ case LAbin_MOD_DU:
-+ return "mod.du";
-+ case LAbin_SLLI_W:
-+ return "slli.w";
-+ case LAbin_SLLI_D:
-+ return "slli.d";
-+ case LAbin_SRLI_W:
-+ return "srli.w";
-+ case LAbin_SRLI_D:
-+ return "srli.d";
-+ case LAbin_SRAI_W:
-+ return "srai.w";
-+ case LAbin_SRAI_D:
-+ return "srai.d";
-+ case LAbin_ADDI_W:
-+ return "addi.w";
-+ case LAbin_ADDI_D:
-+ return "addi.d";
-+ case LAbin_ANDI:
-+ return "andi";
-+ case LAbin_ORI:
-+ return "ori";
-+ case LAbin_XORI:
-+ return "xori";
-+ default:
-+ vpanic("showLOONGARCH64BinOp");
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt si5 = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isS = SLICE(insn, 17, 17);
++ UInt insTy = SLICE(insn, 19, 17);
++
++ UInt szId = insSz;
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp dup = newTemp(Ity_V128);
++ assign(sJ, getVReg(vj));
++
++ IRExpr *si5Expr;
++ IRTemp s64 = newTemp(Ity_I64);
++ assign(s64, mkU64(extend64(si5, 5)));
++
++ if (insTy == 0b000)
++ isS = 1;
++
++ switch (insSz) {
++ case 0b00: {
++ si5Expr = isS ? unop(Iop_64to8, mkexpr(s64)) : mkU8(si5);
++ assign(dup, unop(Iop_Dup8x16, si5Expr));
++ break;
++ }
++ case 0b01: {
++ si5Expr = isS ? unop(Iop_64to16, mkexpr(s64)) : mkU16(si5);
++ assign(dup, unop(Iop_Dup16x8, si5Expr));
++ break;
++ }
++ case 0b10: {
++ si5Expr = isS ? unop(Iop_64to32, mkexpr(s64)) : mkU32(si5);
++ assign(dup, unop(Iop_Dup32x4, si5Expr));
++ break;
++ }
++ case 0b11: {
++ si5Expr = isS ? mkexpr(s64) : mkU64(si5);
++ assign(dup, binop(Iop_64HLtoV128, si5Expr, si5Expr));
+ break;
++ }
++ default: vassert(0);
+ }
-+}
+
-+static inline const HChar* showLOONGARCH64LoadOp ( LOONGARCH64LoadOp op )
-+{
-+ switch (op) {
-+ case LAload_LD_D:
-+ return "ld.d";
-+ case LAload_LD_BU:
-+ return "ld.bu";
-+ case LAload_LD_HU:
-+ return "ld.hu";
-+ case LAload_LD_WU:
-+ return "ld.wu";
-+ case LAload_LDX_D:
-+ return "ldx.d";
-+ case LAload_LDX_BU:
-+ return "ldx.bu";
-+ case LAload_LDX_HU:
-+ return "ldx.hu";
-+ case LAload_LDX_WU:
-+ return "ldx.wu";
-+ default:
-+ vpanic("LOONGARCH64LoadOp");
++ switch (insTy) {
++ case 0b000: {
++ assign(res, binop(mkV128CMPEQ(insSz), EX(sJ), EX(dup)));
++ break;
++ }
++ case 0b001: {
++ assign(res, binop(Iop_OrV128,
++ binop(mkV128CMPGTS(insSz), EX(dup), EX(sJ)),
++ binop(mkV128CMPEQ(insSz), EX(sJ), EX(dup))));
++ break;
++ }
++ case 0b010: {
++ assign(res, binop(Iop_OrV128,
++ binop(mkV128CMPGTU(insSz), EX(dup), EX(sJ)),
++ binop(mkV128CMPEQ(insSz), EX(sJ), EX(dup))));
++ szId = insSz + 4;
++ break;
++ }
++ case 0b011: {
++ assign(res, binop(mkV128CMPGTS(insSz), EX(dup), EX(sJ)));
+ break;
++ }
++ case 0b100: {
++ assign(res, binop(mkV128CMPGTU(insSz), EX(dup), EX(sJ)));
++ szId = insSz + 4;
++ break;
++ }
++ default: vassert(0);
+ }
-+}
+
-+static inline const HChar* showLOONGARCH64StoreOp ( LOONGARCH64StoreOp op )
-+{
-+ switch (op) {
-+ case LAstore_ST_B:
-+ return "st.b";
-+ case LAstore_ST_H:
-+ return "st.h";
-+ case LAstore_ST_W:
-+ return "st.w";
-+ case LAstore_ST_D:
-+ return "st.d";
-+ case LAstore_STX_B:
-+ return "stx.b";
-+ case LAstore_STX_H:
-+ return "stx.h";
-+ case LAstore_STX_W:
-+ return "stx.w";
-+ case LAstore_STX_D:
-+ return "stx.d";
-+ default:
-+ vpanic("LOONGARCH64StoreOp");
-+ break;
++ const HChar *nm[10] = { "vseqi", "vslei", "vslei", "vslti", "vslti" };
++ DIP("%s.%s %s, %s, %d\n", nm[insTy], mkInsSize(szId), nameVReg(vd),
++ nameVReg(vj), (Int)extend32(si5, 5));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
++
++ putVReg(vd, EX(res));
++ return True;
+}
+
-+static inline const HChar* showLOONGARCH64LLSCOp ( LOONGARCH64LLSCOp op )
++static Bool gen_xvcmpi ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (op) {
-+ case LAllsc_LL_W:
-+ return "ll.w";
-+ case LAllsc_SC_W:
-+ return "sc.w";
-+ case LAllsc_LL_D:
-+ return "ll.d";
-+ case LAllsc_SC_D:
-+ return "sc.d";
-+ default:
-+ vpanic("LOONGARCH64LLSCOp");
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt si5 = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++ UInt isS = SLICE(insn, 17, 17);
++ UInt insTy = SLICE(insn, 19, 17);
++
++ UInt szId = insSz;
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp dup128 = newTemp(Ity_V128);
++ IRTemp dup256 = newTemp(Ity_V256);
++ assign(sJ, getXReg(xj));
++
++ IRExpr *si5Expr;
++ IRTemp s64 = newTemp(Ity_I64);
++ assign(s64, mkU64(extend64(si5, 5)));
++
++ if (insTy == 0b000)
++ isS = 1;
++
++ switch (insSz) {
++ case 0b00: {
++ si5Expr = isS ? unop(Iop_64to8, mkexpr(s64)) : mkU8(si5);
++ assign(dup128, unop(Iop_Dup8x16, si5Expr));
++ break;
++ }
++ case 0b01: {
++ si5Expr = isS ? unop(Iop_64to16, mkexpr(s64)) : mkU16(si5);
++ assign(dup128, unop(Iop_Dup16x8, si5Expr));
++ break;
++ }
++ case 0b10: {
++ si5Expr = isS ? unop(Iop_64to32, mkexpr(s64)) : mkU32(si5);
++ assign(dup128, unop(Iop_Dup32x4, si5Expr));
++ break;
++ }
++ case 0b11: {
++ si5Expr = isS ? mkexpr(s64) : mkU64(si5);
++ assign(dup128, binop(Iop_64HLtoV128, si5Expr, si5Expr));
+ break;
++ }
++ default: vassert(0);
+ }
-+}
+
-+static inline const HChar* showLOONGARCH64BarOp ( LOONGARCH64BarOp op )
-+{
-+ const HChar* ret;
-+ switch (op) {
-+ case LAbar_DBAR:
-+ return "dbar";
-+ case LAbar_IBAR:
-+ return "ibar";
-+ default:
-+ vpanic("showLOONGARCH64BarOp");
++ assign(dup256, mkV256from128s(dup128, dup128));
++ switch (insTy) {
++ case 0b000: {
++ assign(res, binop(mkV256CMPEQ(insSz), EX(sJ), EX(dup256)));
++ break;
++ }
++ case 0b001: {
++ assign(res, binop(Iop_OrV256,
++ binop(mkV256CMPGTS(insSz), EX(dup256), EX(sJ)),
++ binop(mkV256CMPEQ(insSz), EX(sJ), EX(dup256))));
++ break;
++ }
++ case 0b010: {
++ assign(res, binop(Iop_OrV256,
++ binop(mkV256CMPGTU(insSz), EX(dup256), EX(sJ)),
++ binop(mkV256CMPEQ(insSz), EX(sJ), EX(dup256))));
++ szId = insSz + 4;
++ break;
++ }
++ case 0b011: {
++ assign(res, binop(mkV256CMPGTS(insSz), EX(dup256), EX(sJ)));
+ break;
++ }
++ case 0b100: {
++ assign(res, binop(mkV256CMPGTU(insSz), EX(dup256), EX(sJ)));
++ szId = insSz + 4;
++ break;
++ }
++ default: vassert(0);
+ }
-+ return ret;
++
++ const HChar *nm[10] = { "xvseqi", "xvslei", "xvslei", "xvslti", "xvslti" };
++ DIP("%s.%s %s, %s, %d\n", nm[insTy], mkInsSize(szId), nameXReg(xd),
++ nameXReg(xj), (Int)extend32(si5, 5));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
++
++ putXReg(xd, EX(res));
++ return True;
+}
+
-+static inline const HChar* showLOONGARCH64FpUnOp ( LOONGARCH64FpUnOp op )
++static Bool gen_vbitsel ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ const HChar* ret;
-+ switch (op) {
-+ case LAfpun_FABS_S:
-+ return "fabs.s";
-+ case LAfpun_FABS_D:
-+ return "fabs.d";
-+ case LAfpun_FNEG_S:
-+ return "fneg.s";
-+ case LAfpun_FNEG_D:
-+ return "fneg.d";
-+ case LAfpun_FLOGB_S:
-+ return "flogb.s";
-+ case LAfpun_FLOGB_D:
-+ return "flogb.d";
-+ case LAfpun_FSQRT_S:
-+ return "fsqrt.s";
-+ case LAfpun_FSQRT_D:
-+ return "fsqrt.d";
-+ case LAfpun_FRSQRT_S:
-+ return "frsqrt.s";
-+ case LAfpun_FRSQRT_D:
-+ return "frsqrt.d";
-+ case LAfpun_FCVT_S_D:
-+ return "fcvt.s.d";
-+ case LAfpun_FCVT_D_S:
-+ return "fcvt.d.s";
-+ case LAfpun_FTINT_W_S:
-+ return "ftint.w.s";
-+ case LAfpun_FTINT_W_D:
-+ return "ftint.w.d";
-+ case LAfpun_FTINT_L_S:
-+ return "ftint.l.s";
-+ case LAfpun_FTINT_L_D:
-+ return "ftint.l.d";
-+ case LAfpun_FFINT_S_W:
-+ return "ffint.s.w";
-+ case LAfpun_FFINT_S_L:
-+ return "ffint.s.l";
-+ case LAfpun_FFINT_D_W:
-+ return "ffint.d.w";
-+ case LAfpun_FFINT_D_L:
-+ return "ffint.d.l";
-+ case LAfpun_FRINT_S:
-+ return "frint.s";
-+ case LAfpun_FRINT_D:
-+ return "frint.d";
-+ default:
-+ vpanic("showLOONGARCH64FpUnOp");
-+ break;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt va = SLICE(insn, 19, 15);
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
-+ return ret;
++
++ IRTemp argL = newTemp(Ity_V128);
++ IRTemp argR = newTemp(Ity_V128);
++ assign(argL, binop(Iop_AndV128, getVReg(vk), getVReg(va)));
++ assign(argR, binop(Iop_AndV128, getVReg(vj), unop(Iop_NotV128, getVReg(va))));
++ DIP("vbitsel.v %s, %s, %s, %s", nameVReg(vd), nameVReg(vj),
++ nameVReg(vk), nameVReg(va));
++ putVReg(vd, binop(Iop_OrV128, EX(argL), EX(argR)));
++ return True;
+}
+
-+static inline const HChar* showLOONGARCH64FpBinOp ( LOONGARCH64FpBinOp op )
++static Bool gen_xvbitsel ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ const HChar* ret;
-+ switch (op) {
-+ case LAfpbin_FADD_S:
-+ return "fadd.s";
-+ case LAfpbin_FADD_D:
-+ return "fadd.d";
-+ case LAfpbin_FSUB_S:
-+ return "fsub.s";
-+ case LAfpbin_FSUB_D:
-+ return "fsub.d";
-+ case LAfpbin_FMUL_S:
-+ return "fmul.s";
-+ case LAfpbin_FMUL_D:
-+ return "fmul.d";
-+ case LAfpbin_FDIV_S:
-+ return "fdiv.s";
-+ case LAfpbin_FDIV_D:
-+ return "fdiv.d";
-+ case LAfpbin_FMAX_S:
-+ return "fmax.s";
-+ case LAfpbin_FMAX_D:
-+ return "fmax.d";
-+ case LAfpbin_FMIN_S:
-+ return "fmin.s";
-+ case LAfpbin_FMIN_D:
-+ return "fmin.d";
-+ case LAfpbin_FMAXA_S:
-+ return "fmaxa.s";
-+ case LAfpbin_FMAXA_D:
-+ return "fmaxa.d";
-+ case LAfpbin_FMINA_S:
-+ return "fmina.s";
-+ case LAfpbin_FMINA_D:
-+ return "fmina.d";
-+ case LAfpbin_FSCALEB_S:
-+ return "fscaleb.s";
-+ case LAfpbin_FSCALEB_D:
-+ return "fscaleb.d";
-+ default:
-+ vpanic("showLOONGARCH64FpBinOp");
-+ break;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt xa = SLICE(insn, 19, 15);
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
-+ return ret;
++
++ IRTemp argL = newTemp(Ity_V256);
++ IRTemp argR = newTemp(Ity_V256);
++ assign(argL, binop(Iop_AndV256, getXReg(xk), getXReg(xa)));
++ assign(argR, binop(Iop_AndV256, getXReg(xj), unop(Iop_NotV256, getXReg(xa))));
++ DIP("vbitsel.v %s, %s, %s, %s", nameXReg(xd), nameXReg(xj),
++ nameXReg(xk), nameXReg(xa));
++ putXReg(xd, binop(Iop_OrV256, EX(argL), EX(argR)));
++ return True;
+}
+
-+static inline const HChar* showLOONGARCH64FpTriOp ( LOONGARCH64FpTriOp op )
++static Bool gen_vbitseli ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ const HChar* ret;
-+ switch (op) {
-+ case LAfpbin_FMADD_S:
-+ return "fmadd.s";
-+ case LAfpbin_FMADD_D:
-+ return "fmadd.d";
-+ case LAfpbin_FMSUB_S:
-+ return "fmsub.s";
-+ case LAfpbin_FMSUB_D:
-+ return "fmsub.d";
-+ default:
-+ vpanic("showLOONGARCH64FpTriOp");
-+ break;
-+ }
-+ return ret;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt ui8 = SLICE(insn, 17, 10);
++
++ IRTemp argL = newTemp(Ity_V128);
++ IRTemp argR = newTemp(Ity_V128);
++ assign(argL, binop(Iop_AndV128, getVReg(vd), unop(Iop_Dup8x16, mkU8(ui8))));
++ assign(argR, binop(Iop_AndV128, getVReg(vj), unop(Iop_NotV128, getVReg(vd))));
++ DIP("vbitseli.b %s, %s, %u", nameVReg(vd), nameVReg(vj), ui8);
++ putVReg(vd, binop(Iop_OrV128, EX(argL), EX(argR)));
++ return True;
+}
+
-+static inline const HChar* showLOONGARCH64FpLoadOp ( LOONGARCH64FpLoadOp op )
++static Bool gen_xvbitseli ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (op) {
-+ case LAfpload_FLD_S:
-+ return "fld.s";
-+ case LAfpload_FLD_D:
-+ return "fld.d";
-+ case LAfpload_FLDX_S:
-+ return "fldx.s";
-+ case LAfpload_FLDX_D:
-+ return "fldx.d";
-+ default:
-+ vpanic("LOONGARCH64FpLoadOp");
-+ break;
-+ }
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt ui8 = SLICE(insn, 17, 10);
++
++ IRTemp argL = newTemp(Ity_V256);
++ IRTemp argR = newTemp(Ity_V256);
++ IRTemp dup = newTemp(Ity_V128);
++ assign(dup, unop(Iop_Dup8x16, mkU8(ui8)));
++ assign(argL, binop(Iop_AndV256, getXReg(xd), mkV256from128s(dup, dup)));
++ assign(argR, binop(Iop_AndV256, getXReg(xj), unop(Iop_NotV256, getXReg(xd))));
++ DIP("xvbitseli.b %s, %s, %u", nameXReg(xd), nameXReg(xj), ui8);
++ putXReg(xd, binop(Iop_OrV256, EX(argL), EX(argR)));
++ return True;
+}
+
-+static inline const HChar* showLOONGARCH64FpStoreOp ( LOONGARCH64FpStoreOp op )
++static Bool gen_vset ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (op) {
-+ case LAfpstore_FST_S:
-+ return "fst.s";
-+ case LAfpstore_FST_D:
-+ return "fst.d";
-+ case LAfpstore_FSTX_S:
-+ return "fstx.s";
-+ case LAfpstore_FSTX_D:
-+ return "fstx.d";
-+ default:
-+ vpanic("LOONGARCH64FpStoreOp");
++ UInt cd = SLICE(insn, 2, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt insSz = SLICE(insn, 11, 10);
++ UInt insTy = SLICE(insn, 13, 12);
++
++ IROp ops64;
++ IRTemp rHi = newTemp(Ity_I64);
++ IRTemp rLo = newTemp(Ity_I64);
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp eq = newTemp(Ity_V128);
++ IRTemp z128 = newTemp(Ity_V128);
++ assign(z128, mkV128(0x0000));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
++
++ switch (insTy) {
++ case 0b01: {
++ if (SLICE(insn, 10, 10) == 0b0) {
++ DIP("vseteqz.v %u, %s", cd, nameVReg(vj));
++ assign(res, binop(Iop_CmpEQ64x2, getVReg(vj), EX(z128)));
++ ops64 = Iop_And64;
++ } else {
++ DIP("vsetnez.v %u, %s", cd, nameVReg(vj));
++ assign(res, unop(Iop_NotV128,
++ binop(Iop_CmpEQ64x2, getVReg(vj), EX(z128))));
++ ops64 = Iop_Or64;
++ }
++ break;
++ }
++ case 0b10: {
++ DIP("vsetanyeqz.%s %u, %s", mkInsSize(insSz), cd, nameVReg(vj));
++ assign(eq, binop(mkV128CMPEQ(insSz), getVReg(vj), EX(z128)));
++ assign(res, unop(Iop_NotV128,
++ binop(Iop_CmpEQ64x2, EX(eq), EX(z128))));
++ ops64 = Iop_Or64;
++ break;
++ }
++ case 0b11: {
++ DIP("vsetqllnez.%s %u, %s", mkInsSize(insSz), cd, nameVReg(vj));
++ assign(eq, binop(mkV128CMPEQ(insSz), getVReg(vj), EX(z128)));
++ assign(res, binop(Iop_CmpEQ64x2, EX(eq), EX(z128)));
++ ops64 = Iop_And64;
+ break;
++ }
++ default: vassert(0);
+ }
++
++ assign(rHi, binop(Iop_GetElem64x2, EX(res), mkU8(1)));
++ assign(rLo, binop(Iop_GetElem64x2, EX(res), mkU8(0)));
++ putFCC(cd, unop(Iop_64to8, binop(ops64, EX(rHi), EX(rLo))));
++ return True;
+}
+
-+static inline const HChar* showLOONGARCH64FpMoveOp ( LOONGARCH64FpMoveOp op )
++static Bool gen_xvset ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (op) {
-+ case LAfpmove_FMOV_S:
-+ return "fmov.s";
-+ case LAfpmove_FMOV_D:
-+ return "fmov.d";
-+ case LAfpmove_MOVGR2FR_W:
-+ return "movgr2fr.w";
-+ case LAfpmove_MOVGR2FR_D:
-+ return "movgr2fr.d";
-+ case LAfpmove_MOVFR2GR_S:
-+ return "movfr2gr.s";
-+ case LAfpmove_MOVFR2GR_D:
-+ return "movfr2gr.d";
-+ case LAfpmove_MOVGR2FCSR:
-+ return "movgr2fcsr";
-+ case LAfpmove_MOVFCSR2GR:
-+ return "movfcsr2gr";
-+ default:
-+ vpanic("showLOONGARCH64FpMoveOp");
-+ break;
++ UInt cd = SLICE(insn, 2, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insSz = SLICE(insn, 11, 10);
++ UInt insTy = SLICE(insn, 13, 12);
++
++ IROp ops64 = Iop_INVALID;
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp eq = newTemp(Ity_V256);
++ IRTemp z256 = newTemp(Ity_V256);
++ assign(z256, mkV256(0x0000));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
-+}
+
-+static inline const HChar* showLOONGARCH64FpCmpOp ( LOONGARCH64FpCmpOp op )
-+{
-+ const HChar* ret;
-+ switch (op) {
-+ case LAfpcmp_FCMP_CLT_S:
-+ return "fcmp.clt.s";
-+ case LAfpcmp_FCMP_CLT_D:
-+ return "fcmp.clt.d";
-+ case LAfpcmp_FCMP_CEQ_S:
-+ return "fcmp.ceq.s";
-+ case LAfpcmp_FCMP_CEQ_D:
-+ return "fcmp.ceq.d";
-+ case LAfpcmp_FCMP_CUN_S:
-+ return "fcmp.cun.s";
-+ case LAfpcmp_FCMP_CUN_D:
-+ return "fcmp.cun.d";
-+ default:
-+ vpanic("showLOONGARCH64FpCmpOp");
++ switch (insTy) {
++ case 0b01: {
++ if (SLICE(insn, 10, 10) == 0b0) {
++ DIP("xvseteqz.v %u, %s", cd, nameXReg(xj));
++ assign(res, binop(Iop_CmpEQ64x4, getXReg(xj), EX(z256)));
++ ops64 = Iop_And64;
++ } else {
++ DIP("xvsetnez.v %u, %s", cd, nameXReg(xj));
++ assign(res, unop(Iop_NotV256,
++ binop(Iop_CmpEQ64x4, getXReg(xj), EX(z256))));
++ ops64 = Iop_Or64;
++ }
++ break;
++ }
++ case 0b10: {
++ DIP("xvsetanyeqz.%s %u, %s", mkInsSize(insSz), cd, nameXReg(xj));
++ assign(eq, binop(mkV256CMPEQ(insSz), getXReg(xj), EX(z256)));
++ assign(res, unop(Iop_NotV256,
++ binop(Iop_CmpEQ64x4, EX(eq), EX(z256))));
++ ops64 = Iop_Or64;
+ break;
++ }
++ case 0b11: {
++ DIP("xvsetqllnez.%s %u, %s", mkInsSize(insSz), cd, nameXReg(xj));
++ assign(eq, binop(mkV256CMPEQ(insSz), getXReg(xj), EX(z256)));
++ assign(res, binop(Iop_CmpEQ64x4, EX(eq), EX(z256)));
++ ops64 = Iop_And64;
++ break;
++ }
++ default: vassert(0);
+ }
-+ return ret;
++
++ IRTemp r1, r2, r3, r4;
++ r1 = r2 = r3 = r4 = IRTemp_INVALID;
++ breakupV256to64s(res, &r1, &r2, &r3, &r4);
++ putFCC(cd, unop(Iop_64to8, binop(ops64,
++ binop(ops64, EX(r1), EX(r2)),
++ binop(ops64, EX(r3), EX(r4)))));
++ return True;
+}
+
-+static inline const HChar* showLOONGARCH64VecUnOp ( LOONGARCH64VecUnOp op )
++
++/*------------------------------------------------------------*/
++/*--- Helpers for vector moving and shuffling insns ---*/
++/*------------------------------------------------------------*/
++
++static Bool gen_vinsgr2vr ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (op) {
-+ case LAvecun_VCLO_B:
-+ return "vclo.b";
-+ case LAvecun_VCLO_H:
-+ return "vclo.h";
-+ case LAvecun_VCLO_W:
-+ return "vclo.w";
-+ case LAvecun_VCLZ_B:
-+ return "vclz.b";
-+ case LAvecun_VCLZ_H:
-+ return "vclz.h";
-+ case LAvecun_VCLZ_W:
-+ return "vclz.w";
-+ case LAvecun_VCLZ_D:
-+ return "vclz.d";
-+ case LAvecun_VPCNT_B:
-+ return "vpcnt.b";
-+ case LAvecun_VEXTH_H_B:
-+ return "vexth.h.b";
-+ case LAvecun_VEXTH_W_H:
-+ return "vexth.w.h";
-+ case LAvecun_VEXTH_D_W:
-+ return "vexth.d.w";
-+ case LAvecun_VEXTH_Q_D:
-+ return "vexth.q.d";
-+ case LAvecun_VEXTH_HU_BU:
-+ return "vexth.hu.bu";
-+ case LAvecun_VEXTH_WU_HU:
-+ return "vexth.wu.hu";
-+ case LAvecun_VEXTH_DU_WU:
-+ return "vexth.du.wu";
-+ case LAvecun_VEXTH_QU_DU:
-+ return "vexth.qu.du";
-+ case LAvecun_VREPLGR2VR_B:
-+ return "vreplgr2vr.b";
-+ case LAvecun_VREPLGR2VR_H:
-+ return "vreplgr2vr.h";
-+ case LAvecun_VREPLGR2VR_W:
-+ return "vreplgr2vr.w";
-+ case LAvecun_VREPLGR2VR_D:
-+ return "vreplgr2vr.d";
-+ default:
-+ vpanic("showLOONGARCH64VecUnOp");
-+ break;
++ UInt vd = SLICE(insn, 4, 0);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 15, 10);
++ UInt uImm, insSz;
++ IRTemp res = newTemp(Ity_V128);
++
++ if ((insImm & 0x30) == 0x20) { // 10mmmm; b
++ insSz = 0;
++ uImm = insImm & 0xf;
++ assign(res, triop(Iop_SetElem8x16,
++ getVReg(vd),
++ mkU8(uImm),
++ getIReg8(rj)));
++ } else if ((insImm & 0x38) == 0x30) { // 110mmm; h
++ insSz = 1;
++ uImm = insImm & 0x7;
++ assign(res, triop(Iop_SetElem16x8,
++ getVReg(vd),
++ mkU8(uImm),
++ getIReg16(rj)));
++ } else if ((insImm & 0x3c) == 0x38) { // 1110mm; w
++ insSz = 2;
++ uImm = insImm & 0x3;
++ assign(res, triop(Iop_SetElem32x4,
++ getVReg(vd),
++ mkU8(uImm),
++ getIReg32(rj)));
++ } else if ((insImm & 0x3e) == 0x3c) { // 11110m; d
++ insSz = 3;
++ uImm = insImm & 0x1;
++ if (uImm == 0) {
++ assign(res, binop(Iop_64HLtoV128,
++ unop(Iop_V128HIto64, getVReg(vd)),
++ getIReg64(rj)));
++ } else {
++ assign(res, binop(Iop_64HLtoV128,
++ getIReg64(rj),
++ unop(Iop_V128to64, getVReg(vd))));
++ }
++ } else {
++ vassert(0);
+ }
++
++ DIP("vinsgr2vr.%s %s, %s, %u\n", mkInsSize(insSz),
++ nameVReg(vd), nameIReg(rj), uImm);
++ putVReg(vd, mkexpr(res));
++ return True;
+}
+
-+static inline const HChar* showLOONGARCH64VecBinOp ( LOONGARCH64VecBinOp op )
++static IRTemp gen_xvins2vr_w(IRTemp dHi, IRTemp dLo, UInt uImm, IRExpr *val)
+{
-+ switch (op) {
-+ case LAvecbin_VSEQ_B:
-+ return "vseq.b";
-+ case LAvecbin_VSEQ_H:
-+ return "vseq.h";
-+ case LAvecbin_VSEQ_W:
-+ return "vseq.w";
-+ case LAvecbin_VSEQ_D:
-+ return "vseq.d";
-+ case LAvecbin_VSLT_B:
-+ return "vslt.b";
-+ case LAvecbin_VSLT_H:
-+ return "vslt.h";
-+ case LAvecbin_VSLT_W:
-+ return "vslt.w";
-+ case LAvecbin_VSLT_D:
-+ return "vslt.d";
-+ case LAvecbin_VSLT_BU:
-+ return "vslt.bu";
-+ case LAvecbin_VSLT_HU:
-+ return "vslt.hu";
-+ case LAvecbin_VSLT_WU:
-+ return "vslt.wu";
-+ case LAvecbin_VSLT_DU:
-+ return "vslt.du";
-+ case LAvecbin_VADD_B:
-+ return "vadd.b";
-+ case LAvecbin_VADD_H:
-+ return "vadd.h";
-+ case LAvecbin_VADD_W:
-+ return "vadd.w";
-+ case LAvecbin_VADD_D:
-+ return "vadd.d";
-+ case LAvecbin_VSUB_B:
-+ return "vsub.b";
-+ case LAvecbin_VSUB_H:
-+ return "vsub.h";
-+ case LAvecbin_VSUB_W:
-+ return "vsub.w";
-+ case LAvecbin_VSUB_D:
-+ return "vsub.d";
-+ case LAvecbin_VSADD_B:
-+ return "vsadd.b";
-+ case LAvecbin_VSADD_H:
-+ return "vsadd.h";
-+ case LAvecbin_VSADD_W:
-+ return "vsadd.w";
-+ case LAvecbin_VSADD_D:
-+ return "vsadd.d";
-+ case LAvecbin_VSSUB_B:
-+ return "vssub.b";
-+ case LAvecbin_VSSUB_H:
-+ return "vssub.h";
-+ case LAvecbin_VSSUB_W:
-+ return "vssub.w";
-+ case LAvecbin_VSSUB_D:
-+ return "vssub.d";
-+ case LAvecbin_VSADD_BU:
-+ return "vsadd.bu";
-+ case LAvecbin_VSADD_HU:
-+ return "vsadd.hu";
-+ case LAvecbin_VSADD_WU:
-+ return "vsadd.wu";
-+ case LAvecbin_VSADD_DU:
-+ return "vsadd.du";
-+ case LAvecbin_VSSUB_BU:
-+ return "vssub.bu";
-+ case LAvecbin_VSSUB_HU:
-+ return "vssub.hu";
-+ case LAvecbin_VSSUB_WU:
-+ return "vssub.wu";
-+ case LAvecbin_VSSUB_DU:
-+ return "vssub.du";
-+ case LAvecbin_VADDA_B:
-+ return "vadda.b";
-+ case LAvecbin_VADDA_H:
-+ return "vadda.h";
-+ case LAvecbin_VADDA_W:
-+ return "vadda.w";
-+ case LAvecbin_VADDA_D:
-+ return "vadda.d";
-+ case LAvecbin_VAVGR_B:
-+ return "vavgr.b";
-+ case LAvecbin_VAVGR_H:
-+ return "vavgr.h";
-+ case LAvecbin_VAVGR_W:
-+ return "vavgr.w";
-+ case LAvecbin_VAVGR_D:
-+ return "vavgr.d";
-+ case LAvecbin_VAVGR_BU:
-+ return "vavgr.bu";
-+ case LAvecbin_VAVGR_HU:
-+ return "vavgr.hu";
-+ case LAvecbin_VAVGR_WU:
-+ return "vavgr.wu";
-+ case LAvecbin_VAVGR_DU:
-+ return "vavgr.du";
-+ case LAvecbin_VMAX_B:
-+ return "vmax.b";
-+ case LAvecbin_VMAX_H:
-+ return "vmax.h";
-+ case LAvecbin_VMAX_W:
-+ return "vmax.w";
-+ case LAvecbin_VMAX_D:
-+ return "vmax.d";
-+ case LAvecbin_VMIN_B:
-+ return "vmin.b";
-+ case LAvecbin_VMIN_H:
-+ return "vmin.h";
-+ case LAvecbin_VMIN_W:
-+ return "vmin.w";
-+ case LAvecbin_VMIN_D:
-+ return "vmin.d";
-+ case LAvecbin_VMAX_BU:
-+ return "vmax.bu";
-+ case LAvecbin_VMAX_HU:
-+ return "vmax.hu";
-+ case LAvecbin_VMAX_WU:
-+ return "vmax.wu";
-+ case LAvecbin_VMAX_DU:
-+ return "vmax.du";
-+ case LAvecbin_VMIN_BU:
-+ return "vmin.bu";
-+ case LAvecbin_VMIN_HU:
-+ return "vmin.hu";
-+ case LAvecbin_VMIN_WU:
-+ return "vmin.wu";
-+ case LAvecbin_VMIN_DU:
-+ return "vmin.du";
-+ case LAvecbin_VMUL_B:
-+ return "vmul.b";
-+ case LAvecbin_VMUL_H:
-+ return "vmul.h";
-+ case LAvecbin_VMUL_W:
-+ return "vmul.w";
-+ case LAvecbin_VMUH_B:
-+ return "vmuh.b";
-+ case LAvecbin_VMUH_H:
-+ return "vmuh.h";
-+ case LAvecbin_VMUH_W:
-+ return "vmuh.w";
-+ case LAvecbin_VMUH_BU:
-+ return "vmuh.bu";
-+ case LAvecbin_VMUH_HU:
-+ return "vmuh.hu";
-+ case LAvecbin_VMUH_WU:
-+ return "vmuh.wu";
-+ case LAvecbin_VSLL_B:
-+ return "vsll.b";
-+ case LAvecbin_VSLL_H:
-+ return "vsll.h";
-+ case LAvecbin_VSLL_W:
-+ return "vsll.w";
-+ case LAvecbin_VSLL_D:
-+ return "vsll.d";
-+ case LAvecbin_VSRL_B:
-+ return "vsrl.b";
-+ case LAvecbin_VSRL_H:
-+ return "vsrl.h";
-+ case LAvecbin_VSRL_W:
-+ return "vsrl.w";
-+ case LAvecbin_VSRL_D:
-+ return "vsrl.d";
-+ case LAvecbin_VSRA_B:
-+ return "vsra.b";
-+ case LAvecbin_VSRA_H:
-+ return "vsra.h";
-+ case LAvecbin_VSRA_W:
-+ return "vsra.w";
-+ case LAvecbin_VSRA_D:
-+ return "vsra.d";
-+ case LAvecbin_VILVL_B:
-+ return "vilvl.b";
-+ case LAvecbin_VILVL_H:
-+ return "vilvl.h";
-+ case LAvecbin_VILVL_W:
-+ return "vilvl.w";
-+ case LAvecbin_VILVL_D:
-+ return "vilvl.d";
-+ case LAvecbin_VILVH_B:
-+ return "vilvh.b";
-+ case LAvecbin_VILVH_H:
-+ return "vilvh.h";
-+ case LAvecbin_VILVH_W:
-+ return "vilvh.w";
-+ case LAvecbin_VILVH_D:
-+ return "vilvh.d";
-+ case LAvecbin_VPICKEV_B:
-+ return "vpickev.b";
-+ case LAvecbin_VPICKEV_H:
-+ return "vpickev.h";
-+ case LAvecbin_VPICKEV_W:
-+ return "vpickev.w";
-+ case LAvecbin_VPICKOD_B:
-+ return "vpickod.b";
-+ case LAvecbin_VPICKOD_H:
-+ return "vpickod.h";
-+ case LAvecbin_VPICKOD_W:
-+ return "vpickod.w";
-+ case LAvecbin_VREPLVE_B:
-+ return "vreplve.b";
-+ case LAvecbin_VREPLVE_H:
-+ return "vreplve.h";
-+ case LAvecbin_VREPLVE_W:
-+ return "vreplve.w";
-+ case LAvecbin_VREPLVE_D:
-+ return "vreplve.d";
-+ case LAvecbin_VAND_V:
-+ return "vand.v";
-+ case LAvecbin_VOR_V:
-+ return "vor.v";
-+ case LAvecbin_VXOR_V:
-+ return "vxor.v";
-+ case LAvecbin_VNOR_V:
-+ return "vnor.v";
-+ case LAvecbin_VADD_Q:
-+ return "vadd.q";
-+ case LAvecbin_VSUB_Q:
-+ return "vsub.q";
-+ case LAvecbin_VFADD_S:
-+ return "vfadd.s";
-+ case LAvecbin_VFADD_D:
-+ return "vfadd.d";
-+ case LAvecbin_VFSUB_S:
-+ return "vfsub.s";
-+ case LAvecbin_VFSUB_D:
-+ return "vfsub.d";
-+ case LAvecbin_VFMUL_S:
-+ return "vfmul.s";
-+ case LAvecbin_VFMUL_D:
-+ return "vfmul.d";
-+ case LAvecbin_VFDIV_S:
-+ return "vfdiv.s";
-+ case LAvecbin_VFDIV_D:
-+ return "vfdiv.d";
-+ case LAvecbin_VFMAX_S:
-+ return "vfmax.s";
-+ case LAvecbin_VFMAX_D:
-+ return "vfmax.d";
-+ case LAvecbin_VFMIN_S:
-+ return "vfmin.s";
-+ case LAvecbin_VFMIN_D:
-+ return "vfmin.d";
-+ case LAvecbin_VBSLL_V:
-+ return "vbsll.v";
-+ case LAvecbin_VBSRL_V:
-+ return "vbsrl.v";
-+ case LAvecbin_VINSGR2VR_B:
-+ return "vinsgr2vr.b";
-+ case LAvecbin_VINSGR2VR_H:
-+ return "vinsgr2vr.h";
-+ case LAvecbin_VINSGR2VR_W:
-+ return "vinsgr2vr.w";
-+ case LAvecbin_VINSGR2VR_D:
-+ return "vinsgr2vr.d";
-+ case LAvecbin_VPICKVE2GR_W:
-+ return "vpickve2gr.w";
-+ case LAvecbin_VPICKVE2GR_D:
-+ return "vpickve2gr.d";
-+ case LAvecbin_VPICKVE2GR_BU:
-+ return "vpickve2gr.bu";
-+ case LAvecbin_VPICKVE2GR_HU:
-+ return "vpickve2gr.hu";
-+ case LAvecbin_VPICKVE2GR_WU:
-+ return "vpickve2gr.wu";
-+ case LAvecbin_VPICKVE2GR_DU:
-+ return "vpickve2gr.du";
-+ case LAvecbin_VSLLI_B:
-+ return "vslli.b";
-+ case LAvecbin_VSLLI_H:
-+ return "vslli.h";
-+ case LAvecbin_VSLLI_W:
-+ return "vslli.w";
-+ case LAvecbin_VSLLI_D:
-+ return "vslli.d";
-+ case LAvecbin_VSRLI_B:
-+ return "vsrli.b";
-+ case LAvecbin_VSRLI_H:
-+ return "vsrli.h";
-+ case LAvecbin_VSRLI_W:
-+ return "vsrli.w";
-+ case LAvecbin_VSRLI_D:
-+ return "vsrli.d";
-+ case LAvecbin_VSRAI_B:
-+ return "vsrai.b";
-+ case LAvecbin_VSRAI_H:
-+ return "vsrai.h";
-+ case LAvecbin_VSRAI_W:
-+ return "vsrai.w";
-+ case LAvecbin_VSRAI_D:
-+ return "vsrai.d";
-+ case LAvecbin_VORI_B:
-+ return "vori.b";
-+ default:
-+ vpanic("showLOONGARCH64VecBinOp");
-+ break;
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp rT = newTemp(Ity_V128);
++
++ if (uImm < 4) {
++ assign(rT, triop(Iop_SetElem32x4,
++ EX(dLo), mkU8(uImm), val));
++ assign(res, mkV256from128s(dHi, rT));
++ } else {
++ assign(rT, triop(Iop_SetElem32x4,
++ EX(dHi), mkU8(uImm - 4), val));
++ assign(res, mkV256from128s(rT, dLo));
+ }
++
++ return res;
+}
+
-+static inline const HChar* showLOONGARCH64VecLoadOp ( LOONGARCH64VecLoadOp op )
++static IRTemp gen_xvins2vr_d(IRTemp dHi, IRTemp dLo, UInt uImm, IRExpr *val)
+{
-+ switch (op) {
-+ case LAvecload_VLD:
-+ return "vld";
-+ case LAvecload_VLDX:
-+ return "vldx";
-+ default:
-+ vpanic("showLOONGARCH64VecLoadOp");
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp rT = newTemp(Ity_V128);
++
++ switch (uImm) {
++ case 0: {
++ assign(rT, binop(Iop_64HLtoV128,
++ unop(Iop_V128HIto64, EX(dLo)), val));
++ assign(res, mkV256from128s(dHi, rT));
++ break;
++ }
++ case 1: {
++ assign(rT, binop(Iop_64HLtoV128,
++ val, unop(Iop_V128to64, EX(dLo))));
++ assign(res, mkV256from128s(dHi, rT));
++ break;
++ }
++ case 2: {
++ assign(rT, binop(Iop_64HLtoV128,
++ unop(Iop_V128HIto64, EX(dHi)), val));
++ assign(res, mkV256from128s(rT, dLo));
+ break;
++ }
++ case 3: {
++ assign(rT, binop(Iop_64HLtoV128,
++ val, unop(Iop_V128to64, EX(dHi))));
++ assign(res, mkV256from128s(rT, dLo));
++ break;
++ }
++ default: vassert(0);
+ }
++
++ return res;
+}
+
-+static inline const HChar* showLOONGARCH64VecStoreOp ( LOONGARCH64VecStoreOp op )
++static Bool gen_xvinsgr2vr ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (op) {
-+ case LAvecstore_VST:
-+ return "vst";
-+ case LAvecstore_VSTX:
-+ return "vstx";
-+ default:
-+ vpanic("showLOONGARCH64VecStoreOp");
-+ break;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 15, 10);
++
++ IRExpr *val;
++ UInt uImm, insSz;
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp sD = newTemp(Ity_V256);
++ IRTemp dHi, dLo;
++ dHi = dLo = IRTemp_INVALID;
++ assign(sD, getXReg(xd));
++ breakupV256toV128s(sD, &dHi, &dLo);
++
++ if ((insImm & 0x38) == 0x30) { // 110mmm; w
++ insSz = 2;
++ uImm = insImm & 0x7;
++ val = getIReg32(rj);
++ res = gen_xvins2vr_w(dHi, dLo, uImm, val);
++ } else if ((insImm & 0x3c) == 0x38) { // 1110mm; d
++ insSz = 3;
++ uImm = insImm & 0x3;
++ val = getIReg64(rj);
++ res = gen_xvins2vr_d(dHi, dLo, uImm, val);
++ } else {
++ vassert(0);
+ }
-+}
+
-+LOONGARCH64Instr* LOONGARCH64Instr_LI ( ULong imm, HReg dst )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_LI;
-+ i->LAin.LI.imm = imm;
-+ i->LAin.LI.dst = dst;
-+ return i;
++ DIP("xvinsgr2vr.%s %s, %s, %u\n", mkInsSize(insSz),
++ nameXReg(xd), nameIReg(rj), uImm);
++ putXReg(xd, EX(res));
++ return True;
+}
+
-+LOONGARCH64Instr* LOONGARCH64Instr_Unary ( LOONGARCH64UnOp op,
-+ HReg src, HReg dst )
++static Bool gen_vpickve2gr ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_Un;
-+ i->LAin.Unary.op = op;
-+ i->LAin.Unary.src = src;
-+ i->LAin.Unary.dst = dst;
-+ return i;
-+}
++ UInt rd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 15, 10);
++ UInt isS = SLICE(insn, 18, 18);
+
-+LOONGARCH64Instr* LOONGARCH64Instr_Binary ( LOONGARCH64BinOp op,
-+ LOONGARCH64RI* src2,
-+ HReg src1, HReg dst )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_Bin;
-+ i->LAin.Binary.op = op;
-+ i->LAin.Binary.src2 = src2;
-+ i->LAin.Binary.src1 = src1;
-+ i->LAin.Binary.dst = dst;
-+ return i;
-+}
++ UInt uImm, insSz;
++ IRExpr *immExpr;
++ IRType extTy = Ity_INVALID;
++ IRTemp res = newTemp(Ity_I64);
+
-+LOONGARCH64Instr* LOONGARCH64Instr_Load ( LOONGARCH64LoadOp op,
-+ LOONGARCH64AMode* src, HReg dst )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_Load;
-+ i->LAin.Load.op = op;
-+ i->LAin.Load.src = src;
-+ i->LAin.Load.dst = dst;
-+ return i;
-+}
++ if ((insImm & 0x30) == 0x20) { // 10mmmm; b
++ uImm = insImm & 0xf;
++ insSz = 0;
++ extTy = Ity_I8;
++ } else if ((insImm & 0x38) == 0x30) { // 110mmm; h
++ uImm = insImm & 0x7;
++ insSz = 1;
++ extTy = Ity_I16;
++ } else if ((insImm & 0x3c) == 0x38) { // 1110mm; w
++ uImm = insImm & 0x3;
++ insSz = 2;
++ extTy = Ity_I32;
++ } else if ((insImm & 0x3e) == 0x3c) { // 11110m; d
++ uImm = insImm & 0x1;
++ insSz = 3;
++ } else {
++ vassert(0);
++ }
+
-+LOONGARCH64Instr* LOONGARCH64Instr_Store ( LOONGARCH64StoreOp op,
-+ LOONGARCH64AMode* dst, HReg src )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_Store;
-+ i->LAin.Store.op = op;
-+ i->LAin.Store.dst = dst;
-+ i->LAin.Store.src = src;
-+ return i;
-+}
++ immExpr = binop(mkV128GetElem(insSz), getVReg(vj), mkU8(uImm));
++ if (insSz != 3)
++ assign(res, isS ? extendS(extTy, immExpr) :
++ extendU(extTy, immExpr));
++ else
++ assign(res, binop(Iop_Or64, mkU64(0), immExpr));
+
-+LOONGARCH64Instr* LOONGARCH64Instr_LLSC ( LOONGARCH64LLSCOp op, Bool isLoad,
-+ LOONGARCH64AMode* addr, HReg val )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_LLSC;
-+ i->LAin.LLSC.op = op;
-+ i->LAin.LLSC.isLoad = isLoad;
-+ i->LAin.LLSC.addr = addr;
-+ i->LAin.LLSC.val = val;
-+ return i;
-+}
++ UInt nmId = isS ? insSz : (insSz + 4);
+
-+LOONGARCH64Instr* LOONGARCH64Instr_Bar ( LOONGARCH64BarOp op, UShort hint )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_Bar;
-+ i->LAin.Bar.op = op;
-+ i->LAin.Bar.hint = hint;
-+ return i;
-+}
++ DIP("vpickve2gr.%s %s, %s", mkInsSize(nmId),
++ nameIReg(rd), nameVReg(vj));
+
-+LOONGARCH64Instr* LOONGARCH64Instr_FpUnary ( LOONGARCH64FpUnOp op,
-+ HReg src, HReg dst )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_FpUn;
-+ i->LAin.FpUnary.op = op;
-+ i->LAin.FpUnary.src = src;
-+ i->LAin.FpUnary.dst = dst;
-+ return i;
-+}
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+LOONGARCH64Instr* LOONGARCH64Instr_FpBinary ( LOONGARCH64FpBinOp op, HReg src2,
-+ HReg src1, HReg dst )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_FpBin;
-+ i->LAin.FpBinary.op = op;
-+ i->LAin.FpBinary.src2 = src2;
-+ i->LAin.FpBinary.src1 = src1;
-+ i->LAin.FpBinary.dst = dst;
-+ return i;
-+}
++ putIReg(rd, mkexpr(res));
+
-+LOONGARCH64Instr* LOONGARCH64Instr_FpTrinary ( LOONGARCH64FpTriOp op,
-+ HReg src3, HReg src2,
-+ HReg src1, HReg dst )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_FpTri;
-+ i->LAin.FpTrinary.op = op;
-+ i->LAin.FpTrinary.src3 = src3;
-+ i->LAin.FpTrinary.src2 = src2;
-+ i->LAin.FpTrinary.src1 = src1;
-+ i->LAin.FpTrinary.dst = dst;
-+ return i;
++ return True;
+}
+
-+LOONGARCH64Instr* LOONGARCH64Instr_FpLoad ( LOONGARCH64FpLoadOp op,
-+ LOONGARCH64AMode* src, HReg dst )
++static Bool gen_xvpickve2gr ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_FpLoad;
-+ i->LAin.FpLoad.op = op;
-+ i->LAin.FpLoad.src = src;
-+ i->LAin.FpLoad.dst = dst;
-+ return i;
-+}
++ UInt rd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 15, 10);
++ UInt isS = SLICE(insn, 18, 18);
+
-+LOONGARCH64Instr* LOONGARCH64Instr_FpStore ( LOONGARCH64FpStoreOp op,
-+ LOONGARCH64AMode* dst, HReg src )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_FpStore;
-+ i->LAin.FpStore.op = op;
-+ i->LAin.FpStore.dst = dst;
-+ i->LAin.FpStore.src = src;
-+ return i;
-+}
++ UInt uImm, insSz;
++ IRExpr *immExpr;
++ IRExpr *vExpr;
++ IRType extTy = Ity_INVALID;
++ IRTemp res = newTemp(Ity_I64);
++ IRTemp sJ = newTemp(Ity_V256);
++ assign(sJ, getXReg(xj));
++ IRTemp jHi, jLo;
++ jHi = jLo = IRTemp_INVALID;
++ breakupV256toV128s(sJ, &jHi, &jLo);
+
-+LOONGARCH64Instr* LOONGARCH64Instr_FpMove ( LOONGARCH64FpMoveOp op,
-+ HReg src, HReg dst )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_FpMove;
-+ i->LAin.FpMove.op = op;
-+ i->LAin.FpMove.src = src;
-+ i->LAin.FpMove.dst = dst;
-+ return i;
-+}
++ if ((insImm & 0x38) == 0x30) { // 110mmm; w
++ uImm = (insImm & 0x7) < 4 ? (insImm & 0x7) : (insImm & 0x7) - 4;
++ vExpr = (insImm & 0x7) < 4 ? EX(jLo) : EX(jHi);
++ insSz = 2;
++ extTy = Ity_I32;
++ } else if ((insImm & 0x3c) == 0x38) { // 1110mm; d
++ uImm = (insImm & 0x3) < 2 ? (insImm & 0x3) : (insImm & 0x3) - 2;
++ vExpr = (insImm & 0x3) < 2 ? EX(jLo) : EX(jHi);
++ insSz = 3;
++ } else {
++ vassert(0);
++ }
+
-+LOONGARCH64Instr* LOONGARCH64Instr_FpCmp ( LOONGARCH64FpCmpOp op, HReg src2,
-+ HReg src1, HReg dst )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_FpCmp;
-+ i->LAin.FpCmp.op = op;
-+ i->LAin.FpCmp.src2 = src2;
-+ i->LAin.FpCmp.src1 = src1;
-+ i->LAin.FpCmp.dst = dst;
-+ return i;
-+}
++ immExpr = binop(mkV128GetElem(insSz), vExpr, mkU8(uImm));
++ if (insSz != 3)
++ assign(res, isS ? extendS(extTy, immExpr) :
++ extendU(extTy, immExpr));
++ else
++ assign(res, binop(Iop_Or64, mkU64(0), immExpr));
+
-+LOONGARCH64Instr* LOONGARCH64Instr_VecUnary ( LOONGARCH64VecUnOp op,
-+ HReg src, HReg dst )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_VecUn;
-+ i->LAin.VecUnary.op = op;
-+ i->LAin.VecUnary.src = src;
-+ i->LAin.VecUnary.dst = dst;
-+ return i;
++ UInt nmId = isS ? insSz : (insSz + 4);
++ DIP("xvpickve2gr.%s %s, %s", mkInsSize(nmId),
++ nameIReg(rd), nameXReg(xj));
++ putIReg(rd, EX(res));
++ return True;
+}
+
-+LOONGARCH64Instr* LOONGARCH64Instr_VecBinary ( LOONGARCH64VecBinOp op,
-+ LOONGARCH64RI* src2,
-+ HReg src1, HReg dst )
++static Bool gen_vreplgr2vr ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_VecBin;
-+ i->LAin.VecBinary.op = op;
-+ i->LAin.VecBinary.src2 = src2;
-+ i->LAin.VecBinary.src1 = src1;
-+ i->LAin.VecBinary.dst = dst;
-+ return i;
-+}
++ UInt vd = SLICE(insn, 4, 0);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt insSz = SLICE(insn, 11, 10);
+
-+LOONGARCH64Instr* LOONGARCH64Instr_VecLoad ( LOONGARCH64VecLoadOp op,
-+ LOONGARCH64AMode* src, HReg dst )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_VecLoad;
-+ i->LAin.VecLoad.op = op;
-+ i->LAin.VecLoad.src = src;
-+ i->LAin.VecLoad.dst = dst;
-+ return i;
-+}
++ IRTemp res = newTemp(Ity_V128);
++ switch (insSz) {
++ case 0b00:
++ assign(res, unop(Iop_Dup8x16, getIReg8(rj)));
++ break;
++ case 0b01:
++ assign(res, unop(Iop_Dup16x8, getIReg16(rj)));
++ break;
++ case 0b10:
++ assign(res, unop(Iop_Dup32x4, getIReg32(rj)));
++ break;
++ case 0b11:
++ assign(res, binop(Iop_64HLtoV128, getIReg64(rj), getIReg64(rj)));
++ break;
++ default:
++ vassert(0);
++ break;
++ }
+
-+LOONGARCH64Instr* LOONGARCH64Instr_VecStore ( LOONGARCH64VecStoreOp op,
-+ LOONGARCH64AMode* dst, HReg src)
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_VecStore;
-+ i->LAin.VecStore.op = op;
-+ i->LAin.VecStore.dst = dst;
-+ i->LAin.VecStore.src = src;
-+ return i;
-+}
++ DIP("vreplgr2vr.%s %s, %s", mkInsSize(insSz),
++ nameVReg(vd), nameIReg(rj));
+
-+LOONGARCH64Instr* LOONGARCH64Instr_Cas ( HReg old, HReg addr, HReg expd,
-+ HReg data, Bool size64 )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_Cas;
-+ i->LAin.Cas.old = old;
-+ i->LAin.Cas.addr = addr;
-+ i->LAin.Cas.expd = expd;
-+ i->LAin.Cas.data = data;
-+ i->LAin.Cas.size64 = size64;
-+ return i;
-+}
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+LOONGARCH64Instr* LOONGARCH64Instr_Cmp ( LOONGARCH64CondCode cond,
-+ HReg src2, HReg src1, HReg dst )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_Cmp;
-+ i->LAin.Cmp.cond = cond;
-+ i->LAin.Cmp.src2 = src2;
-+ i->LAin.Cmp.src1 = src1;
-+ i->LAin.Cmp.dst = dst;
-+ return i;
-+}
++ putVReg(vd, mkexpr(res));
+
-+LOONGARCH64Instr* LOONGARCH64Instr_CMove ( HReg cond, HReg r0, HReg r1,
-+ HReg dst, Bool isInt )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_CMove;
-+ i->LAin.CMove.cond = cond;
-+ i->LAin.CMove.r0 = r0;
-+ i->LAin.CMove.r1 = r1;
-+ i->LAin.CMove.dst = dst;
-+ i->LAin.CMove.isInt = isInt;
-+ return i;
++ return True;
+}
+
-+LOONGARCH64Instr* LOONGARCH64Instr_Call ( HReg cond, Addr64 target,
-+ UInt nArgRegs, RetLoc rloc )
++static Bool gen_xvreplgr2vr ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_Call;
-+ i->LAin.Call.cond = cond;
-+ i->LAin.Call.target = target;
-+ i->LAin.Call.nArgRegs = nArgRegs;
-+ i->LAin.Call.rloc = rloc;
-+ return i;
-+}
++ UInt xd = SLICE(insn, 4, 0);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt insSz = SLICE(insn, 11, 10);
+
-+LOONGARCH64Instr* LOONGARCH64Instr_XDirect ( Addr64 dstGA,
-+ LOONGARCH64AMode* amPC,
-+ HReg cond, Bool toFastEP )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_XDirect;
-+ i->LAin.XDirect.dstGA = dstGA;
-+ i->LAin.XDirect.amPC = amPC;
-+ i->LAin.XDirect.cond = cond;
-+ i->LAin.XDirect.toFastEP = toFastEP;
-+ return i;
-+}
++ IRTemp res = newTemp(Ity_V128);
++ switch (insSz) {
++ case 0b00:
++ assign(res, unop(Iop_Dup8x16, getIReg8(rj)));
++ break;
++ case 0b01:
++ assign(res, unop(Iop_Dup16x8, getIReg16(rj)));
++ break;
++ case 0b10:
++ assign(res, unop(Iop_Dup32x4, getIReg32(rj)));
++ break;
++ case 0b11:
++ assign(res, binop(Iop_64HLtoV128, getIReg64(rj), getIReg64(rj)));
++ break;
++ default:
++ vassert(0);
++ break;
++ }
+
-+LOONGARCH64Instr* LOONGARCH64Instr_XIndir ( HReg dstGA, LOONGARCH64AMode* amPC,
-+ HReg cond )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_XIndir;
-+ i->LAin.XIndir.dstGA = dstGA;
-+ i->LAin.XIndir.amPC = amPC;
-+ i->LAin.XIndir.cond = cond;
-+ return i;
-+}
++ DIP("xvreplgr2vr.%s %s, %s", mkInsSize(insSz),
++ nameXReg(xd), nameIReg(rj));
+
-+LOONGARCH64Instr* LOONGARCH64Instr_XAssisted ( HReg dstGA,
-+ LOONGARCH64AMode* amPC,
-+ HReg cond, IRJumpKind jk )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_XAssisted;
-+ i->LAin.XAssisted.dstGA = dstGA;
-+ i->LAin.XAssisted.amPC = amPC;
-+ i->LAin.XAssisted.cond = cond;
-+ i->LAin.XAssisted.jk = jk;
-+ return i;
-+}
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+LOONGARCH64Instr* LOONGARCH64Instr_EvCheck ( LOONGARCH64AMode* amCounter,
-+ LOONGARCH64AMode* amFailAddr )
-+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_EvCheck;
-+ i->LAin.EvCheck.amCounter = amCounter;
-+ i->LAin.EvCheck.amFailAddr = amFailAddr;
-+ return i;
++ putXReg(xd, binop(Iop_V128HLtoV256, mkexpr(res), mkexpr(res)));
++
++ return True;
+}
+
-+LOONGARCH64Instr* LOONGARCH64Instr_ProfInc ( void )
++static Bool gen_vreplve ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
-+ i->tag = LAin_ProfInc;
-+ return i;
-+}
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt rk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
+
++ IRExpr *elem;
++ IRTemp mod = newTemp(Ity_I8);
++ IRTemp res = newTemp(Ity_V128);
++ UInt div[4] = { 0x10, 0x8, 0x4, 0x2 };
+
-+/* -------- Pretty Print instructions ------------- */
++ assign(mod, unop(Iop_64to8,
++ unop(Iop_128HIto64,
++ binop(Iop_DivModU64to64,
++ getIReg64(rk),
++ mkU64(div[insSz])))));
+
-+static inline void ppLI ( ULong imm, HReg dst )
-+{
-+ vex_printf("li ");
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", 0x%llx", imm);
-+}
++ elem = binop(mkV128GetElem(insSz), getVReg(vj), mkexpr(mod));
++ switch (insSz) {
++ case 0b00:
++ assign(res, unop(Iop_Dup8x16, elem));
++ break;
++ case 0b01:
++ assign(res, unop(Iop_Dup16x8, elem));
++ break;
++ case 0b10:
++ assign(res, unop(Iop_Dup32x4, elem));
++ break;
++ case 0b11:
++ assign(res, binop(Iop_64HLtoV128, elem, elem));
++ break;
++ default:
++ vassert(0);
++ break;
++ }
+
-+static inline void ppUnary ( LOONGARCH64UnOp op, HReg src, HReg dst )
-+{
-+ vex_printf("%s ", showLOONGARCH64UnOp(op));
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(src);
-+}
++ DIP("vreplve.%s %s, %s, %s", mkInsSize(insSz),
++ nameVReg(vd), nameVReg(vj), nameIReg(rk));
+
-+static inline void ppBinary ( LOONGARCH64BinOp op, LOONGARCH64RI* src2,
-+ HReg src1, HReg dst )
-+{
-+ vex_printf("%s ", showLOONGARCH64BinOp(op));
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(src1);
-+ vex_printf(", ");
-+ ppLOONGARCH64RI(src2);
-+}
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+static inline void ppLoad ( LOONGARCH64LoadOp op, LOONGARCH64AMode* src,
-+ HReg dst )
-+{
-+ vex_printf("%s ", showLOONGARCH64LoadOp(op));
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", ");
-+ ppLOONGARCH64AMode(src);
-+}
++ putVReg(vd, mkexpr(res));
+
-+static inline void ppStore ( LOONGARCH64StoreOp op, LOONGARCH64AMode* dst,
-+ HReg src )
-+{
-+ vex_printf("%s ", showLOONGARCH64StoreOp(op));
-+ ppHRegLOONGARCH64(src);
-+ vex_printf(", ");
-+ ppLOONGARCH64AMode(dst);
++ return True;
+}
+
-+static inline void ppLLSC ( LOONGARCH64LLSCOp op, LOONGARCH64AMode* addr,
-+ HReg val )
++static Bool gen_xvreplve ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vex_printf("%s ", showLOONGARCH64LLSCOp(op));
-+ ppHRegLOONGARCH64(val);
-+ vex_printf(", ");
-+ ppLOONGARCH64AMode(addr);
-+}
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt rk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
+
-+static inline void ppBar ( LOONGARCH64BarOp op, UShort hint )
-+{
-+ vex_printf("%s %u", showLOONGARCH64BarOp(op), (UInt)hint);
-+}
++ IRExpr *irLo, *irHi;
++ IRTemp mod = newTemp(Ity_I8);
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp jHi = IRTemp_INVALID;
++ IRTemp jLo = IRTemp_INVALID;
++ assign(sJ, getXReg(xj));
++ breakupV256toV128s(sJ, &jHi, &jLo);
+
-+static inline void ppFpUnary ( LOONGARCH64FpUnOp op, HReg src, HReg dst )
-+{
-+ vex_printf("%s ", showLOONGARCH64FpUnOp(op));
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(src);
-+}
++ UInt div[4] = { 0x10, 0x8, 0x4, 0x2 };
++ assign(mod, unop(Iop_64to8,
++ unop(Iop_128HIto64,
++ binop(Iop_DivModU64to64,
++ getIReg64(rk),
++ mkU64(div[insSz])))));
+
-+static inline void ppFpBinary ( LOONGARCH64FpBinOp op, HReg src2,
-+ HReg src1, HReg dst )
-+{
-+ vex_printf("%s ", showLOONGARCH64FpBinOp(op));
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(src1);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(src2);
-+}
++ irLo = binop(mkV128GetElem(insSz), EX(jLo), EX(mod));
++ irHi = binop(mkV128GetElem(insSz), EX(jHi), EX(mod));
++ switch (insSz) {
++ case 0b00:
++ assign(rHi, unop(Iop_Dup8x16, irHi));
++ assign(rLo, unop(Iop_Dup8x16, irLo));
++ break;
++ case 0b01:
++ assign(rHi, unop(Iop_Dup16x8, irHi));
++ assign(rLo, unop(Iop_Dup16x8, irLo));
++ break;
++ case 0b10:
++ assign(rHi, unop(Iop_Dup32x4, irHi));
++ assign(rLo, unop(Iop_Dup32x4, irLo));
++ break;
++ case 0b11:
++ assign(rHi, binop(Iop_64HLtoV128, irHi, irHi));
++ assign(rLo, binop(Iop_64HLtoV128, irLo, irLo));
++ break;
++ default: vassert(0);
++ }
+
-+static inline void ppFpTrinary ( LOONGARCH64FpTriOp op, HReg src3,
-+ HReg src2, HReg src1, HReg dst )
-+{
-+ vex_printf("%s ", showLOONGARCH64FpTriOp(op));
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(src1);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(src2);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(src3);
-+}
++ DIP("xvreplve.%s %s, %s, %s", mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj), nameIReg(rk));
+
-+static inline void ppFpLoad ( LOONGARCH64FpLoadOp op, LOONGARCH64AMode* src,
-+ HReg dst )
-+{
-+ vex_printf("%s ", showLOONGARCH64FpLoadOp(op));
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", ");
-+ ppLOONGARCH64AMode(src);
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
++ putXReg(xd, mkV256from128s(rHi, rLo));
++ return True;
+}
+
-+static inline void ppFpStore ( LOONGARCH64FpStoreOp op, LOONGARCH64AMode* dst,
-+ HReg src )
++static Bool gen_vreplvei ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vex_printf("%s ", showLOONGARCH64FpStoreOp(op));
-+ ppHRegLOONGARCH64(src);
-+ vex_printf(", ");
-+ ppLOONGARCH64AMode(dst);
-+}
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
+
-+static inline void ppFpMove ( LOONGARCH64FpMoveOp op, HReg src, HReg dst )
-+{
-+ vex_printf("%s ", showLOONGARCH64FpMoveOp(op));
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(src);
-+}
++ IRExpr *elem;
++ UInt uImm, insSz;
++ IRTemp res = newTemp(Ity_V128);
+
-+static inline void ppFpCmp ( LOONGARCH64FpCmpOp op, HReg src2,
-+ HReg src1, HReg dst )
-+{
-+ vex_printf("%s ", showLOONGARCH64FpCmpOp(op));
-+ vex_printf("$fcc0, ");
-+ ppHRegLOONGARCH64(src1);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(src2);
-+ vex_printf("; movcf2gr ");
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", $fcc0");
-+}
++ if ((insImm & 0xf0) == 0xe0) { // 1110mmmm; b
++ uImm = insImm & 0xf;
++ insSz = 0;
++ } else if ((insImm & 0xf8) == 0xf0) { // 11110mmm; h
++ uImm = insImm & 0x7;
++ insSz = 1;
++ } else if ((insImm & 0xfc) == 0xf8) { // 111110mm; w
++ uImm = insImm & 0x3;
++ insSz = 2;
++ } else if ((insImm & 0xfe) == 0xfc) { // 1111110m; d
++ uImm = insImm & 0x1;
++ insSz = 3;
++ } else {
++ vassert(0);
++ }
+
-+static inline void ppVecUnary ( LOONGARCH64VecUnOp op, HReg src, HReg dst )
-+{
-+ vex_printf("%s ", showLOONGARCH64VecUnOp(op));
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(src);
-+}
++ elem = binop(mkV128GetElem(insSz), getVReg(vj), mkU8(uImm));
++ switch (insSz) {
++ case 0:
++ assign(res, unop(Iop_Dup8x16, elem));
++ break;
++ case 1:
++ assign(res, unop(Iop_Dup16x8, elem));
++ break;
++ case 2:
++ assign(res, unop(Iop_Dup32x4, elem));
++ break;
++ case 3:
++ assign(res, binop(Iop_64HLtoV128, elem, elem));
++ break;
++ default: vassert(0);
++ }
+
-+static inline void ppVecBinary ( LOONGARCH64VecBinOp op, LOONGARCH64RI* src2,
-+ HReg src1, HReg dst )
-+{
-+ vex_printf("%s ", showLOONGARCH64VecBinOp(op));
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(src1);
-+ vex_printf(", ");
-+ ppLOONGARCH64RI(src2);
++ DIP("vreplvei.%s %s, %s, %u", mkInsSize(insSz),
++ nameVReg(vd), nameVReg(vj), uImm);
++ putVReg(vd, mkexpr(res));
++ return True;
+}
+
-+static inline void ppVecLoad ( LOONGARCH64VecLoadOp op, LOONGARCH64AMode* src,
-+ HReg dst )
++static Bool gen_xvrepl128vei ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vex_printf("%s ", showLOONGARCH64VecLoadOp(op));
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", ");
-+ ppLOONGARCH64AMode(src);
-+}
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 17, 10);
+
-+static inline void ppVecStore ( LOONGARCH64VecStoreOp op, LOONGARCH64AMode* dst,
-+ HReg src )
-+{
-+ vex_printf("%s ", showLOONGARCH64VecStoreOp(op));
-+ ppHRegLOONGARCH64(src);
-+ vex_printf(", ");
-+ ppLOONGARCH64AMode(dst);
++ IRExpr *irLo, *irHi;
++ UInt uImm, insSz;
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp jHi = IRTemp_INVALID;
++ IRTemp jLo = IRTemp_INVALID;
++ assign(sJ, getXReg(xj));
++ breakupV256toV128s(sJ, &jHi, &jLo);
++
++
++ if ((insImm & 0xf0) == 0xe0) { // 1110mmmm; b
++ uImm = insImm & 0xf;
++ insSz = 0;
++ } else if ((insImm & 0xf8) == 0xf0) { // 11110mmm; h
++ uImm = insImm & 0x7;
++ insSz = 1;
++ } else if ((insImm & 0xfc) == 0xf8) { // 111110mm; w
++ uImm = insImm & 0x3;
++ insSz = 2;
++ } else if ((insImm & 0xfe) == 0xfc) { // 1111110m; d
++ uImm = insImm & 0x1;
++ insSz = 3;
++ } else {
++ vassert(0);
++ }
++
++ irLo = binop(mkV128GetElem(insSz), EX(jLo), mkU8(uImm));
++ irHi = binop(mkV128GetElem(insSz), EX(jHi), mkU8(uImm));
++ switch (insSz) {
++ case 0b00:
++ assign(rHi, unop(Iop_Dup8x16, irHi));
++ assign(rLo, unop(Iop_Dup8x16, irLo));
++ break;
++ case 0b01:
++ assign(rHi, unop(Iop_Dup16x8, irHi));
++ assign(rLo, unop(Iop_Dup16x8, irLo));
++ break;
++ case 0b10:
++ assign(rHi, unop(Iop_Dup32x4, irHi));
++ assign(rLo, unop(Iop_Dup32x4, irLo));
++ break;
++ case 0b11:
++ assign(rHi, binop(Iop_64HLtoV128, irHi, irHi));
++ assign(rLo, binop(Iop_64HLtoV128, irLo, irLo));
++ break;
++ default: vassert(0);
++ }
++
++ DIP("xvrepl128vei.%s %s, %s, %u", mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj), uImm);
++ putXReg(xd, mkV256from128s(rHi, rLo));
++ return True;
+}
+
-+static inline void ppCas ( HReg old, HReg addr, HReg expd,
-+ HReg data, Bool size64)
++static Bool gen_xvreplve0 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ ppHRegLOONGARCH64(old);
-+ vex_printf(" = cas(%dbit)(", size64 ? 64 : 32);
-+ ppHRegLOONGARCH64(expd);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(data);
-+ vex_printf(" -> ");
-+ ppHRegLOONGARCH64(addr);
-+ vex_printf(")");
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insSz = SLICE(insn, 15, 12);
++
++ IRExpr *ir0;
++ IRTemp dup = newTemp(Ity_V128);
++ IRTemp jLo = newTemp(Ity_V128);
++ assign(jLo, unop(Iop_V256toV128_0, getXReg(xj)));
++
++ switch (insSz) {
++ case 0b0:
++ ir0 = binop(Iop_GetElem8x16, EX(jLo), mkU8(0));
++ assign(dup, unop(Iop_Dup8x16, ir0));
++ break;
++ case 0b1000:
++ ir0 = binop(Iop_GetElem16x8, EX(jLo), mkU8(0));
++ assign(dup, unop(Iop_Dup16x8, ir0));
++ break;
++ case 0b1100:
++ ir0 = binop(Iop_GetElem32x4, EX(jLo), mkU8(0));
++ assign(dup, unop(Iop_Dup32x4, ir0));
++ break;
++ case 0b1110:
++ ir0 = binop(Iop_GetElem64x2, EX(jLo), mkU8(0));
++ assign(dup, binop(Iop_64HLtoV128, ir0, ir0));
++ break;
++ case 0b1111:
++ assign(dup, binop(Iop_OrV128, EX(jLo), mkV128(0x0000)));
++ break;
++ default: vassert(0);
++ }
++
++ DIP("xvreplve0.%s %s, %s", mkInsSize(insSz), nameXReg(xd), nameXReg(xj));
++ putXReg(xd, mkV256from128s(dup, dup));
++ return True;
+}
+
-+static inline void ppCmp ( LOONGARCH64CondCode cond, HReg src2,
-+ HReg src1, HReg dst )
++static Bool gen_xvinsve0 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(" = cmp%s(", showLOONGARCH64CondCode(cond));
-+ ppHRegLOONGARCH64(src1);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(src2);
-+ vex_printf(")");
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 15, 10);
++
++ IRExpr *ir0;
++ UInt uImm, insSz;
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp jLo = newTemp(Ity_V128);
++ IRTemp sD = newTemp(Ity_V256);
++ IRTemp dHi, dLo;
++ dHi = dLo = IRTemp_INVALID;
++ assign(jLo, unop(Iop_V256toV128_0, getXReg(xj)));
++ assign(sD, getXReg(xd));
++ breakupV256toV128s(sD, &dHi, &dLo);
++
++ if ((insImm & 0x38) == 0x30) { // 110mmm; w
++ insSz = 2;
++ uImm = insImm & 0x7;
++ ir0 = binop(Iop_GetElem32x4, EX(jLo), mkU8(0));
++ res = gen_xvins2vr_w(dHi, dLo, uImm, ir0);
++ } else if ((insImm & 0x3c) == 0x38) { // 1110mm; d
++ insSz = 3;
++ uImm = insImm & 0x3;
++ ir0 = binop(Iop_GetElem64x2, EX(jLo), mkU8(0));
++ res = gen_xvins2vr_d(dHi, dLo, uImm, ir0);
++ } else {
++ vassert(0);
++ }
++
++ DIP("xvinsve0.%s %s, %s, %u", mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj), uImm);
++ putXReg(xd, EX(res));
++ return True;
+}
+
-+static inline void ppCMove ( HReg cond, HReg r0, HReg r1,
-+ HReg dst, Bool isInt )
++static Bool gen_xvpickve ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ if (isInt) {
-+ vex_printf("masknez $t0, ");
-+ ppHRegLOONGARCH64(r0);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(cond);
-+ vex_printf("; maskeqz ");
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(r1);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(cond);
-+ vex_printf("; or ");
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", $t0, ");
-+ ppHRegLOONGARCH64(dst);
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 15, 10);
++
++ UInt sImm, insSz;
++ IRTemp res = newTemp(Ity_I64);
++ IRTemp z64 = newTemp(Ity_I64);
++ IRTemp src = newTemp(Ity_V256);
++ assign(z64, mkU64(0));
++ assign(src, getXReg(xj));
++
++ if ((insImm & 0x38) == 0x30) { // 110ui3; w
++ IRTemp s[8];
++ s[7] = s[6] = s[5] = s[4] = s[3] = s[2] = s[1] = s[0] = IRTemp_INVALID;
++ breakupV256to32s(src, &s[7], &s[6], &s[5], &s[4],
++ &s[3], &s[2], &s[1], &s[0]);
++ sImm = insImm & 0x7;
++ insSz = 0;
++ assign(res, extendU(Ity_I32, mkexpr(s[sImm])));
++ } else if ((insImm & 0x3c) == 0x38) { // 1110ui2; d
++ IRTemp s[4];
++ s[3] = s[2] = s[1] = s[0] = IRTemp_INVALID;
++ breakupV256to64s(src, &s[3], &s[2], &s[1], &s[0]);
++ sImm = insImm & 0x3;
++ insSz = 1;
++ assign(res, mkexpr(s[sImm]));
+ } else {
-+ vex_printf("movgr2cf ");
-+ ppHRegLOONGARCH64(cond);
-+ vex_printf(", $fcc0; fsel ");
-+ ppHRegLOONGARCH64(dst);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(r0);
-+ vex_printf(", ");
-+ ppHRegLOONGARCH64(r1);
-+ vex_printf(", $fcc0");
++ vassert(0);
++ }
++
++ const HChar arr = "wd"[insSz];
++ DIP("xvpickve.%c %s, %s, %u", arr, nameXReg(xd), nameXReg(xj), sImm);
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
++
++ putXReg(xd, mkV256from64s(z64, z64, z64, res));
++
++ return True;
+}
+
-+static inline void ppCall ( HReg cond, Addr64 target,
-+ UInt nArgRegs, RetLoc rloc )
++static Bool gen_evod ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ if (!hregIsInvalid(cond)) {
-+ vex_printf("if (");
-+ ppHRegLOONGARCH64(cond);
-+ vex_printf(") { ");
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++
++ const HChar *nm;
++ IRTemp argL = newTemp(Ity_V128);
++ IRTemp argR = newTemp(Ity_V128);
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp sK = newTemp(Ity_V128);
++ IRTemp z128 = newTemp(Ity_V128);
++ assign(sJ, getVReg(vj));
++ assign(sK, getVReg(vk));
++ assign(z128, mkV128(0x0000));
++
++ switch (SLICE(insn, 19, 17)) {
++ case 0b011: {
++ nm = "xvpackev";
++ assign(argL, binop(mkV128PACKEV(insSz),
++ EX(sJ), EX(z128)));
++ assign(argR, binop(mkV128PACKEV(insSz),
++ EX(sK), EX(z128)));
++ assign(res, binop(mkV128INTERLEAVEHI(insSz),
++ EX(argL), EX(argR)));
++ break;
++ }
++ case 0b100: {
++ nm = "xvpackod";
++ assign(argL, binop(mkV128PACKOD(insSz),
++ EX(sJ), EX(z128)));
++ assign(argR, binop(mkV128PACKOD(insSz),
++ EX(sK), EX(z128)));
++ assign(res, binop(mkV128INTERLEAVEHI(insSz),
++ EX(argL), EX(argR)));
++ break;
++ }
++ case 0b101: {
++ nm = "xvilvl";
++ assign(res, binop(mkV128INTERLEAVELO(insSz),
++ EX(sJ), EX(sK)));
++ break;
++ }
++ case 0b110: {
++ nm = "xvilvh";
++ assign(res, binop(mkV128INTERLEAVEHI(insSz),
++ EX(sJ), EX(sK)));
++ break;
++ }
++ case 0b111: {
++ nm = "xvpickev";
++ assign(res, binop(mkV128PACKEV(insSz),
++ EX(sJ), EX(sK)));
++ break;
++ }
++ case 0b000: {
++ nm = "xvpickod";
++ assign(res, binop(mkV128PACKOD(insSz),
++ EX(sJ), EX(sK)));
++ break;
++ }
++ default: vassert(0);
+ }
-+ vex_printf("call 0x%llx [nArgRegs=%u, ", target, nArgRegs);
-+ ppRetLoc(rloc);
-+ vex_printf("]");
-+ if (!hregIsInvalid(cond))
-+ vex_printf(" }");
++
++ DIP("%s.%s %s, %s, %s\n", nm, mkInsSize(insSz),
++ nameVReg(vd), nameVReg(vj), nameVReg(vk));
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
++
++ putVReg(vd, EX(res));
++ return True;
+}
+
-+static inline void ppXDirect ( Addr64 dstGA, LOONGARCH64AMode* amPC,
-+ HReg cond, Bool toFastEP )
++static Bool gen_xevod ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vex_printf("(xDirect) ");
-+ if (!hregIsInvalid(cond)) {
-+ vex_printf("if (");
-+ ppHRegLOONGARCH64(cond);
-+ vex_printf(") { ");
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++
++ const HChar *nm;
++ IRTemp argL = newTemp(Ity_V256);
++ IRTemp argR = newTemp(Ity_V256);
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sK = newTemp(Ity_V256);
++ IRTemp z256 = newTemp(Ity_V256);
++ assign(sJ, getXReg(xj));
++ assign(sK, getXReg(xk));
++ assign(z256, mkV256(0x0000));
++
++ switch (SLICE(insn, 19, 17)) {
++ case 0b011: {
++ nm = "xvpackev";
++ assign(argL, binop(mkV256PACKEV(insSz),
++ EX(sJ), EX(z256)));
++ assign(argR, binop(mkV256PACKEV(insSz),
++ EX(sK), EX(z256)));
++ assign(res, binop(mkV256INTERLEAVEHI(insSz),
++ EX(argL), EX(argR)));
++ break;
++ }
++ case 0b100: {
++ nm = "xvpackod";
++ assign(argL, binop(mkV256PACKOD(insSz),
++ EX(sJ), EX(z256)));
++ assign(argR, binop(mkV256PACKOD(insSz),
++ EX(sK), EX(z256)));
++ assign(res, binop(mkV256INTERLEAVEHI(insSz),
++ EX(argL), EX(argR)));
++ break;
++ }
++ case 0b101: {
++ nm = "xvilvl";
++ assign(res, binop(mkV256INTERLEAVELO(insSz),
++ EX(sJ), EX(sK)));
++ break;
++ }
++ case 0b110: {
++ nm = "xvilvh";
++ assign(res, binop(mkV256INTERLEAVEHI(insSz),
++ EX(sJ), EX(sK)));
++ break;
++ }
++ case 0b111: {
++ nm = "xvpickev";
++ assign(res, binop(mkV256PACKEV(insSz),
++ EX(sJ), EX(sK)));
++ break;
++ }
++ case 0b000: {
++ nm = "xvpickod";
++ assign(res, binop(mkV256PACKOD(insSz),
++ EX(sJ), EX(sK)));
++ break;
++ }
++ default: vassert(0);
+ }
-+ vex_printf("li $t0, 0x%llx; ", (ULong)dstGA);
-+ vex_printf("st.w $t0, ");
-+ ppLOONGARCH64AMode(amPC);
-+ vex_printf("; li $t0, $disp_cp_chain_me_to_%sEP; ",
-+ toFastEP ? "fast" : "slow");
-+ vex_printf("jirl $ra, $t0, 0");
-+ if (!hregIsInvalid(cond))
-+ vex_printf(" }");
++
++ DIP("%s.%s %s, %s, %s\n", nm, mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, EX(res));
++ return True;
+}
+
-+static inline void ppXIndir ( HReg dstGA, LOONGARCH64AMode* amPC,
-+ HReg cond )
++static IRTemp get_vshuf_b ( IRTemp sHi, IRTemp sLo, IRTemp sId )
+{
-+ vex_printf("(xIndir) ");
-+ if (!hregIsInvalid(cond)) {
-+ vex_printf("if (");
-+ ppHRegLOONGARCH64(cond);
-+ vex_printf(") { ");
++ UInt i;
++ IRTemp id[16], r[16];
++ IRTemp res = newTemp(Ity_V128);
++
++ for (i = 0; i < 16; i++) {
++ id[i] = newTemp(Ity_I8);
++ r[i] = newTemp(Ity_I8);
++
++ assign(id[i], binop(Iop_GetElem8x16, EX(sId), mkU8(i)));
++
++ assign(r[i], IRExpr_ITE(
++ binop(Iop_CmpEQ64,
++ extendU(Ity_I8, binop(Iop_And8,
++ EX(id[i]),
++ mkU8(0xc0))),
++ mkU64(0x0)),
++ IRExpr_ITE(
++ binop(Iop_CmpLT64U,
++ extendU(Ity_I8, binop(Iop_And8,
++ EX(id[i]),
++ mkU8(0x1f))),
++ mkU64(0x10)),
++ binop(Iop_GetElem8x16,
++ EX(sLo), EX(id[i])),
++ binop(Iop_GetElem8x16,
++ EX(sHi),
++ unop(Iop_64to8,
++ binop(Iop_Sub64,
++ extendU(Ity_I8, EX(id[i])),
++ mkU64(0x10))))),
++ mkU8(0x0)));
+ }
-+ vex_printf("st.w ");
-+ ppHRegLOONGARCH64(dstGA);
-+ vex_printf(", ");
-+ ppLOONGARCH64AMode(amPC);
-+ vex_printf("; la $t0, disp_indir; ");
-+ vex_printf("jirl $ra, $t0, 0");
-+ if (!hregIsInvalid(cond))
-+ vex_printf(" }");
++
++ assign(res, mkV128from8s(r[15], r[14], r[13], r[12],
++ r[11], r[10], r[9], r[8],
++ r[7], r[6], r[5], r[4],
++ r[3], r[2], r[1], r[0]));
++
++ return res;
+}
+
-+static inline void ppXAssisted ( HReg dstGA, LOONGARCH64AMode* amPC,
-+ HReg cond, IRJumpKind jk)
++static Bool gen_vshuf_b ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vex_printf("(xAssisted) ");
-+ if (!hregIsInvalid(cond)) {
-+ vex_printf("if (");
-+ ppHRegLOONGARCH64(cond);
-+ vex_printf(") { ");
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt va = SLICE(insn, 19, 15);
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
-+ vex_printf("st.w ");
-+ ppHRegLOONGARCH64(dstGA);
-+ vex_printf(", ");
-+ ppLOONGARCH64AMode(amPC);
-+ vex_printf("; li.w $s8, IRJumpKind_to_TRCVAL(%d); ", (Int)jk);
-+ vex_printf("la $t0, disp_assisted; ");
-+ vex_printf("jirl $ra, $t0, 0");
-+ if (!hregIsInvalid(cond))
-+ vex_printf(" }");
++
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sHi = newTemp(Ity_V128);
++ IRTemp sLo = newTemp(Ity_V128);
++ IRTemp sId = newTemp(Ity_V128);
++ assign(sHi, getVReg(vj));
++ assign(sLo, getVReg(vk));
++ assign(sId, getVReg(va));
++
++ res = get_vshuf_b(sHi, sLo, sId);
++ DIP("vshuf.b %s, %s, %s, %s\n", nameVReg(vd), nameVReg(vj),
++ nameVReg(vk), nameVReg(va));
++ putVReg(vd, EX(res));
++ return True;
+}
+
-+static inline void ppEvCheck ( LOONGARCH64AMode* amCounter,
-+ LOONGARCH64AMode* amFailAddr )
++static Bool gen_xvshuf_b ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vex_printf("(evCheck) ");
-+ vex_printf("ld.w $t0, ");
-+ ppLOONGARCH64AMode(amCounter);
-+ vex_printf("; addi.d $t0, $t0, -1; ");
-+ vex_printf("st.w $t0, ");
-+ ppLOONGARCH64AMode(amCounter);
-+ vex_printf("; bge $t0, $zero, nofail; ");
-+ vex_printf("ld.d $t0, ");
-+ ppLOONGARCH64AMode(amFailAddr);
-+ vex_printf("; jirl $ra, $t0, 0");
-+ vex_printf("; nofail:");
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt xa = SLICE(insn, 19, 15);
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
++
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sK = newTemp(Ity_V256);
++ IRTemp sA = newTemp(Ity_V256);
++ assign(sJ, getXReg(xj));
++ assign(sK, getXReg(xk));
++ assign(sA, getXReg(xa));
++
++ IRTemp jHi, jLo, kHi, kLo, aHi, aLo;
++ jHi = jLo = kHi = kLo = aHi = aLo = IRTemp_INVALID;
++ breakupV256toV128s(sJ, &jHi, &jLo);
++ breakupV256toV128s(sK, &kHi, &kLo);
++ breakupV256toV128s(sA, &aHi, &aLo);
++
++ rHi = get_vshuf_b(jHi, kHi, aHi);
++ rLo = get_vshuf_b(jLo, kLo, aLo);
++ DIP("xvshuf.b %s, %s, %s, %s\n", nameXReg(xd), nameXReg(xj),
++ nameXReg(xk), nameXReg(xa));
++ putXReg(xd, mkV256from128s(rHi, rLo));
++ return True;
+}
+
-+static inline void ppProfInc ( void )
++static IRTemp get_vshuf_h ( IRTemp sHi, IRTemp sLo, IRTemp sId )
+{
-+ vex_printf("(profInc) ");
-+ vex_printf("li $t0, NotKnownYet; ");
-+ vex_printf("ld.d $t1, $t0, 0; ");
-+ vex_printf("addi.d $t1, $t1, 1; ");
-+ vex_printf("st.d $t1, $t0, 0;");
++ UInt i;
++ IRTemp id[8], arg[8];
++ IRTemp res = newTemp(Ity_V128);
++
++ for (i = 0; i < 8; i++) {
++ id[i] = newTemp(Ity_I16);
++ arg[i] = newTemp(Ity_I16);
++
++ assign(id[i], binop(Iop_GetElem16x8, EX(sId), mkU8(i)));
++ assign(arg[i], IRExpr_ITE(
++ binop(Iop_CmpEQ64,
++ extendU(Ity_I16, binop(Iop_And16,
++ EX(id[i]),
++ mkU16(0xC0))),
++ mkU64(0x0)),
++ IRExpr_ITE(
++ binop(Iop_CmpLT64U,
++ extendU(Ity_I16, binop(Iop_And16,
++ EX(id[i]),
++ mkU16(0xf))),
++ mkU64(0x8)),
++ binop(Iop_GetElem16x8,
++ EX(sLo),
++ unop(Iop_16to8, EX(id[i]))),
++ binop(Iop_GetElem16x8,
++ EX(sHi),
++ unop(Iop_64to8,
++ binop(Iop_Sub64,
++ extendU(Ity_I16, EX(id[i])),
++ mkU64(0x8))))),
++ mkU16(0x0)));
++ }
++
++ assign(res, mkV128from16s(arg[7], arg[6], arg[5], arg[4],
++ arg[3], arg[2], arg[1], arg[0]));
++ return res;
+}
+
-+void ppLOONGARCH64Instr ( const LOONGARCH64Instr* i, Bool mode64 )
++static IRTemp get_vshuf_w ( IRTemp sHi, IRTemp sLo, IRTemp sId )
+{
-+ vassert(mode64 == True);
-+ switch (i->tag) {
-+ case LAin_LI:
-+ ppLI(i->LAin.LI.imm, i->LAin.LI.dst);
-+ break;
-+ case LAin_Un:
-+ ppUnary(i->LAin.Unary.op, i->LAin.Unary.src, i->LAin.Unary.dst);
-+ break;
-+ case LAin_Bin:
-+ ppBinary(i->LAin.Binary.op, i->LAin.Binary.src2,
-+ i->LAin.Binary.src1, i->LAin.Binary.dst);
-+ break;
-+ case LAin_Load:
-+ ppLoad(i->LAin.Load.op, i->LAin.Load.src, i->LAin.Load.dst);
-+ break;
-+ case LAin_Store:
-+ ppStore(i->LAin.Store.op, i->LAin.Store.dst, i->LAin.Store.src);
-+ break;
-+ case LAin_LLSC:
-+ ppLLSC(i->LAin.LLSC.op, i->LAin.LLSC.addr, i->LAin.LLSC.val);
-+ break;
-+ case LAin_Bar:
-+ ppBar(i->LAin.Bar.op, i->LAin.Bar.hint);
-+ break;
-+ case LAin_FpUn:
-+ ppFpUnary(i->LAin.FpUnary.op, i->LAin.FpUnary.src,
-+ i->LAin.FpUnary.dst);
-+ break;
-+ case LAin_FpBin:
-+ ppFpBinary(i->LAin.FpBinary.op, i->LAin.FpBinary.src2,
-+ i->LAin.FpBinary.src1, i->LAin.FpBinary.dst);
-+ break;
-+ case LAin_FpTri:
-+ ppFpTrinary(i->LAin.FpTrinary.op, i->LAin.FpTrinary.src3,
-+ i->LAin.FpTrinary.src2, i->LAin.FpTrinary.src1,
-+ i->LAin.FpTrinary.dst);
-+ break;
-+ case LAin_FpLoad:
-+ ppFpLoad(i->LAin.FpLoad.op, i->LAin.FpLoad.src, i->LAin.FpLoad.dst);
-+ break;
-+ case LAin_FpStore:
-+ ppFpStore(i->LAin.FpStore.op, i->LAin.FpStore.dst,
-+ i->LAin.FpStore.src);
-+ break;
-+ case LAin_FpMove:
-+ ppFpMove(i->LAin.FpMove.op, i->LAin.FpMove.src,
-+ i->LAin.FpMove.dst);
-+ break;
-+ case LAin_FpCmp:
-+ ppFpCmp(i->LAin.FpCmp.op, i->LAin.FpCmp.src2,
-+ i->LAin.FpCmp.src1, i->LAin.FpCmp.dst);
-+ break;
-+ case LAin_VecUn:
-+ ppVecUnary(i->LAin.VecUnary.op, i->LAin.VecUnary.src,
-+ i->LAin.VecUnary.dst);
-+ break;
-+ case LAin_VecBin:
-+ ppVecBinary(i->LAin.VecBinary.op, i->LAin.VecBinary.src2,
-+ i->LAin.VecBinary.src1, i->LAin.VecBinary.dst);
-+ break;
-+ case LAin_VecLoad:
-+ ppVecLoad(i->LAin.VecLoad.op, i->LAin.VecLoad.src,
-+ i->LAin.VecLoad.dst);
-+ break;
-+ case LAin_VecStore:
-+ ppVecStore(i->LAin.VecStore.op, i->LAin.VecStore.dst,
-+ i->LAin.VecStore.src);
-+ break;
-+ case LAin_Cas:
-+ ppCas(i->LAin.Cas.old, i->LAin.Cas.addr, i->LAin.Cas.expd,
-+ i->LAin.Cas.data, i->LAin.Cas.size64);
-+ break;
-+ case LAin_Cmp:
-+ ppCmp(i->LAin.Cmp.cond, i->LAin.Cmp.src2,
-+ i->LAin.Cmp.src1, i->LAin.Cmp.dst);
-+ break;
-+ case LAin_CMove:
-+ ppCMove(i->LAin.CMove.cond, i->LAin.CMove.r0,
-+ i->LAin.CMove.r1, i->LAin.CMove.dst,
-+ i->LAin.CMove.isInt);
-+ break;
-+ case LAin_Call:
-+ ppCall(i->LAin.Call.cond, i->LAin.Call.target,
-+ i->LAin.Call.nArgRegs, i->LAin.Call.rloc);
-+ break;
-+ case LAin_XDirect:
-+ ppXDirect(i->LAin.XDirect.dstGA, i->LAin.XDirect.amPC,
-+ i->LAin.XDirect.cond, i->LAin.XDirect.toFastEP);
-+ break;
-+ case LAin_XIndir:
-+ ppXIndir(i->LAin.XIndir.dstGA, i->LAin.XIndir.amPC,
-+ i->LAin.XIndir.cond);
-+ break;
-+ case LAin_XAssisted:
-+ ppXAssisted(i->LAin.XAssisted.dstGA, i->LAin.XAssisted.amPC,
-+ i->LAin.XAssisted.cond, i->LAin.XAssisted.jk);
-+ break;
-+ case LAin_EvCheck:
-+ ppEvCheck(i->LAin.EvCheck.amCounter, i->LAin.EvCheck.amFailAddr);
-+ break;
-+ case LAin_ProfInc:
-+ ppProfInc();
-+ break;
-+ default:
-+ vpanic("ppLOONGARCH64Instr");
-+ break;
++ UInt i;
++ IRTemp id[4], arg[4];
++ IRTemp res = newTemp(Ity_V128);
++
++ for (i = 0; i < 4; i++) {
++ id[i] = newTemp(Ity_I32);
++ arg[i] = newTemp(Ity_I32);
++
++ assign(id[i], binop(Iop_GetElem32x4, EX(sId), mkU8(i)));
++ assign(arg[i], IRExpr_ITE(
++ binop(Iop_CmpEQ64,
++ extendU(Ity_I32, binop(Iop_And32,
++ EX(id[i]),
++ mkU32(0xC0))),
++ mkU64(0x0)),
++ IRExpr_ITE(
++ binop(Iop_CmpLT64U,
++ extendU(Ity_I32, binop(Iop_And32,
++ EX(id[i]),
++ mkU32(0x7))),
++ mkU64(0x4)),
++ binop(Iop_GetElem32x4,
++ EX(sLo),
++ unop(Iop_32to8, EX(id[i]))),
++ binop(Iop_GetElem32x4,
++ EX(sHi),
++ unop(Iop_64to8,
++ binop(Iop_Sub64,
++ extendU(Ity_I32, EX(id[i])),
++ mkU64(0x4))))),
++ mkU32(0x0)));
+ }
++
++ assign(res, mkV128from32s(arg[3], arg[2], arg[1], arg[0]));
++ return res;
+}
+
++static IRTemp get_vshuf_d ( IRTemp sHi, IRTemp sLo, IRTemp sId )
++{
++ UInt i;
++ IRTemp id[2], arg[2];
++ IRTemp res = newTemp(Ity_V128);
+
-+/* --------- Helpers for register allocation. --------- */
++ for (i = 0; i < 2; i++) {
++ id[i] = newTemp(Ity_I64);
++ arg[i] = newTemp(Ity_I64);
++
++ assign(id[i], binop(Iop_GetElem64x2, mkexpr(sId), mkU8(i)));
++
++ assign(arg[i], IRExpr_ITE(
++ binop(Iop_CmpEQ64,
++ binop(Iop_And64,
++ mkexpr(id[i]),
++ mkU64(0xC0)),
++ mkU64(0x0)),
++ IRExpr_ITE(
++ binop(Iop_CmpLT64U,
++ binop(Iop_And64,
++ mkexpr(id[i]),
++ mkU64(0x3)),
++ mkU64(0x2)),
++ binop(Iop_GetElem64x2,
++ mkexpr(sLo),
++ unop(Iop_64to8, mkexpr(id[i]))),
++ binop(Iop_GetElem64x2,
++ mkexpr(sHi),
++ unop(Iop_64to8,
++ binop(Iop_Sub64,
++ mkexpr(id[i]),
++ mkU64(0x2))))),
++ mkU64(0x0)));
++ }
+
-+void getRegUsage_LOONGARCH64Instr ( HRegUsage* u, const LOONGARCH64Instr* i,
-+ Bool mode64 )
++ assign(res, mkV128from64s(arg[1], arg[0]));
++ return res;
++}
++
++static Bool gen_vshuf ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(mode64 == True);
-+ initHRegUsage(u);
-+ switch (i->tag) {
-+ case LAin_LI:
-+ addHRegUse(u, HRmWrite, i->LAin.LI.dst);
-+ break;
-+ case LAin_Un:
-+ addHRegUse(u, HRmRead, i->LAin.Unary.src);
-+ addHRegUse(u, HRmWrite, i->LAin.Unary.dst);
-+ break;
-+ case LAin_Bin:
-+ addRegUsage_LOONGARCH64RI(u, i->LAin.Binary.src2);
-+ addHRegUse(u, HRmRead, i->LAin.Binary.src1);
-+ addHRegUse(u, HRmWrite, i->LAin.Binary.dst);
-+ break;
-+ case LAin_Load:
-+ addRegUsage_LOONGARCH64AMode(u, i->LAin.Load.src);
-+ addHRegUse(u, HRmWrite, i->LAin.Load.dst);
-+ break;
-+ case LAin_Store:
-+ addRegUsage_LOONGARCH64AMode(u, i->LAin.Store.dst);
-+ addHRegUse(u, HRmRead, i->LAin.Store.src);
-+ break;
-+ case LAin_LLSC:
-+ addRegUsage_LOONGARCH64AMode(u, i->LAin.LLSC.addr);
-+ if (i->LAin.LLSC.isLoad)
-+ addHRegUse(u, HRmWrite, i->LAin.LLSC.val);
-+ else
-+ addHRegUse(u, HRmRead, i->LAin.LLSC.val);
-+ break;
-+ case LAin_Bar:
-+ /* No regs. */
-+ break;
-+ case LAin_FpUn:
-+ addHRegUse(u, HRmRead, i->LAin.FpUnary.src);
-+ addHRegUse(u, HRmWrite, i->LAin.FpUnary.dst);
-+ break;
-+ case LAin_FpBin:
-+ addHRegUse(u, HRmRead, i->LAin.FpBinary.src2);
-+ addHRegUse(u, HRmRead, i->LAin.FpBinary.src1);
-+ addHRegUse(u, HRmWrite, i->LAin.FpBinary.dst);
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt vk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++
++ IRTemp sHi = newTemp(Ity_V128);
++ IRTemp sLo = newTemp(Ity_V128);
++ IRTemp sId = newTemp(Ity_V128);
++ IRTemp res = newTemp(Ity_V128);
++ assign(sHi, getVReg(vj));
++ assign(sLo, getVReg(vk));
++ assign(sId, getVReg(vd));
++
++ switch (insSz) {
++ case 0b01: res = get_vshuf_h(sHi, sLo, sId); break;
++ case 0b10: res = get_vshuf_w(sHi, sLo, sId); break;
++ case 0b11: res = get_vshuf_d(sHi, sLo, sId); break;
++ default: vassert(0);
++ }
++
++ DIP("vshuf.%s %s, %s, %s\n", mkInsSize(insSz), nameVReg(vd),
++ nameVReg(vj), nameVReg(vk));
++ putVReg(vd, EX(res));
++ return True;
++}
++
++static Bool gen_xvshuf ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++ UInt insSz = SLICE(insn, 16, 15);
++
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sK = newTemp(Ity_V256);
++ IRTemp sD = newTemp(Ity_V256);
++ assign(sJ, getXReg(xj));
++ assign(sK, getXReg(xk));
++ assign(sD, getXReg(xd));
++
++ IRTemp jHi, jLo, kHi, kLo, dHi, dLo;
++ jHi = jLo = kHi = kLo = dHi = dLo = IRTemp_INVALID;
++ breakupV256toV128s(sJ, &jHi, &jLo);
++ breakupV256toV128s(sK, &kHi, &kLo);
++ breakupV256toV128s(sD, &dHi, &dLo);
++
++ switch (insSz) {
++ case 0b01: {
++ rHi = get_vshuf_h(jHi, kHi, dHi);
++ rLo = get_vshuf_h(jLo, kLo, dLo);
+ break;
-+ case LAin_FpTri:
-+ addHRegUse(u, HRmRead, i->LAin.FpTrinary.src3);
-+ addHRegUse(u, HRmRead, i->LAin.FpTrinary.src2);
-+ addHRegUse(u, HRmRead, i->LAin.FpTrinary.src1);
-+ addHRegUse(u, HRmWrite, i->LAin.FpTrinary.dst);
++ }
++ case 0b10: {
++ rHi = get_vshuf_w(jHi, kHi, dHi);
++ rLo = get_vshuf_w(jLo, kLo, dLo);
+ break;
-+ case LAin_FpLoad:
-+ addRegUsage_LOONGARCH64AMode(u, i->LAin.FpLoad.src);
-+ addHRegUse(u, HRmWrite, i->LAin.FpLoad.dst);
++ }
++ case 0b11: {
++ rHi = get_vshuf_d(jHi, kHi, dHi);
++ rLo = get_vshuf_d(jLo, kLo, dLo);
+ break;
-+ case LAin_FpStore:
-+ addRegUsage_LOONGARCH64AMode(u, i->LAin.FpStore.dst);
-+ addHRegUse(u, HRmRead, i->LAin.FpStore.src);
++ }
++ default: vassert(0);
++ }
++
++ DIP("xvshuf.%s %s, %s, %s\n", mkInsSize(insSz), nameXReg(xd),
++ nameXReg(xj), nameXReg(xk));
++ putXReg(xd, mkV256from128s(rHi, rLo));
++ return True;
++}
++
++static Bool gen_xvperm_w ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt xk = SLICE(insn, 14, 10);
++
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sK = newTemp(Ity_V256);
++ IRTemp jHi, jLo, kHi, kLo;
++ jHi = jLo = kHi = kLo = IRTemp_INVALID;
++ assign(sJ, getXReg(xj));
++ assign(sK, getXReg(xk));
++ breakupV256toV128s(sJ, &jHi, &jLo);
++ breakupV256toV128s(sK, &kHi, &kLo);
++
++ UInt i;
++ IRTemp id[8];
++ IRTemp r[8];
++
++ for (i = 0; i < 4; i++) {
++ id[i] = newTemp(Ity_I32);
++ r[i] = newTemp(Ity_I32);
++ assign(id[i], binop(Iop_And32,
++ binop(Iop_GetElem32x4, EX(kLo), mkU8(i)),
++ mkU32(0x7)));
++ assign(r[i], IRExpr_ITE(binop(Iop_CmpLT32U, EX(id[i]), mkU32(0x4)),
++ binop(Iop_GetElem32x4,
++ EX(jLo),
++ unop(Iop_32to8, EX(id[i]))),
++ binop(Iop_GetElem32x4,
++ EX(jHi),
++ unop(Iop_32to8,
++ binop(Iop_Sub32, EX(id[i]), mkU32(0x4))))));
++
++ id[i + 4] = newTemp(Ity_I32);
++ r[i + 4] = newTemp(Ity_I32);
++ assign(id[i + 4], binop(Iop_And32,
++ binop(Iop_GetElem32x4, EX(kHi), mkU8(i)),
++ mkU32(0x7)));
++ assign(r[i + 4], IRExpr_ITE(binop(Iop_CmpLT32U, EX(id[i + 4]), mkU32(0x4)),
++ binop(Iop_GetElem32x4,
++ EX(jLo),
++ unop(Iop_32to8, EX(id[i + 4]))),
++ binop(Iop_GetElem32x4,
++ EX(jHi),
++ unop(Iop_32to8,
++ binop(Iop_Sub32, EX(id[i + 4]), mkU32(0x4))))));
++ }
++
++ DIP("xvperm.w %s, %s, %s\n", nameXReg(xd), nameXReg(xj), nameXReg(xk));
++ putXReg(xd, mkV256from32s(r[7], r[6], r[5], r[4],
++ r[3], r[2], r[1], r[0]));
++ return True;
++}
++
++static IRTemp gen_vshuf4i_b ( IRTemp sJ, UInt id0, UInt id1, UInt id2, UInt id3 )
++{
++ UInt i;
++ IRTemp vec[16];
++ IRTemp res = newTemp(Ity_V128);
++
++ for (i = 0; i < 16; i++) {
++ vec[i] = newTemp(Ity_I8);
++ assign(vec[i], binop(Iop_GetElem8x16, EX(sJ), mkU8(i)));
++ }
++
++ assign(res, mkV128from8s(vec[id3 + 12], vec[id2 + 12], vec[id1 + 12], vec[id0 + 12],
++ vec[id3 + 8], vec[id2 + 8], vec[id1 + 8], vec[id0 + 8],
++ vec[id3 + 4], vec[id2 + 4], vec[id1 + 4], vec[id0 + 4],
++ vec[id3], vec[id2], vec[id1], vec[id0]));
++ return res;
++}
++
++static IRTemp gen_vshuf4i_h ( IRTemp sJ, UInt id0, UInt id1, UInt id2, UInt id3 )
++{
++ UInt i;
++ IRTemp vec[8];
++ IRTemp res = newTemp(Ity_V128);
++
++ for (i = 0; i < 8; i++) {
++ vec[i] = newTemp(Ity_I16);
++ assign(vec[i], binop(Iop_GetElem16x8, EX(sJ), mkU8(i)));
++ }
++
++ assign(res, mkV128from16s(vec[id3 + 4], vec[id2 + 4], vec[id1 + 4], vec[id0 + 4],
++ vec[id3], vec[id2], vec[id1], vec[id0]));
++ return res;
++}
++
++static IRTemp gen_vshuf4i_w ( IRTemp sJ, UInt id0, UInt id1, UInt id2, UInt id3 )
++{
++ UInt i;
++ IRTemp vec[4];
++ IRTemp res = newTemp(Ity_V128);
++
++ for (i = 0; i < 4; i ++) {
++ vec[i] = newTemp(Ity_I32);
++ assign(vec[i], binop(Iop_GetElem32x4, EX(sJ), mkU8(i)));
++ }
++
++ assign(res, mkV128from32s(vec[id3], vec[id2], vec[id1], vec[id0]));
++ return res;
++}
++
++static IRTemp gen_vshuf4i_d ( IRTemp sJ, IRTemp sD, UInt id0, UInt id1 )
++{
++ UInt i;
++ IRTemp vec[4];
++ IRTemp res = newTemp(Ity_V128);
++
++ for (i = 0; i < 4; i ++)
++ vec[i] = newTemp(Ity_I64);
++
++ assign(vec[0], unop(Iop_V128to64, EX(sD)));
++ assign(vec[1], unop(Iop_V128HIto64, EX(sD)));
++ assign(vec[2], unop(Iop_V128to64, EX(sJ)));
++ assign(vec[3], unop(Iop_V128HIto64, EX(sJ)));
++ assign(res, mkV128from64s(vec[id1], vec[id0]));
++ return res;
++}
++
++static Bool gen_vshuf4i ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt ui8 = SLICE(insn, 17, 10);
++ UInt insSz = SLICE(insn, 19, 18);
++
++ UInt id0 = ui8 & 0x03;
++ UInt id1 = (ui8 & 0x0c) >> 2;
++ UInt id2 = (ui8 & 0x30) >> 4;
++ UInt id3 = (ui8 & 0xc0) >> 6;
++
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp sD = newTemp(Ity_V128);
++ assign(sJ, getVReg(vj));
++ assign(sD, getVReg(vd));
++
++ switch (insSz) {
++ case 0b00:
++ res = gen_vshuf4i_b(sJ, id0, id1, id2, id3); break;
++ case 0b01:
++ res = gen_vshuf4i_h(sJ, id0, id1, id2, id3); break;
++ case 0b10:
++ res = gen_vshuf4i_w(sJ, id0, id1, id2, id3); break;
++ case 0b11:
++ res = gen_vshuf4i_d(sJ, sD, id0, id1); break;
++ default: vassert(0);
++ }
++
++ DIP("vshuf4i.%s %s, %s, %u\n", mkInsSize(insSz),
++ nameVReg(vd), nameVReg(vj), ui8);
++ putVReg(vd, EX(res));
++ return True;
++}
++
++static Bool gen_xvshuf4i ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt ui8 = SLICE(insn, 17, 10);
++ UInt insSz = SLICE(insn, 19, 18);
++
++ UInt id0 = ui8 & 0x03;
++ UInt id1 = (ui8 & 0x0c) >> 2;
++ UInt id2 = (ui8 & 0x30) >> 4;
++ UInt id3 = (ui8 & 0xc0) >> 6;
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sD = newTemp(Ity_V256);
++ IRTemp jHi, jLo, dHi, dLo;
++ jHi = jLo = dHi = dLo = IRTemp_INVALID;
++ assign(sJ, getXReg(xj));
++ assign(sD, getXReg(xd));
++ breakupV256toV128s(sJ, &jHi, &jLo);
++ breakupV256toV128s(sD, &dHi, &dLo);
++
++ switch (insSz) {
++ case 0b00: {
++ rHi = gen_vshuf4i_b(jHi, id0, id1, id2, id3);
++ rLo = gen_vshuf4i_b(jLo, id0, id1, id2, id3);
+ break;
-+ case LAin_FpMove:
-+ addHRegUse(u, HRmRead, i->LAin.FpMove.src);
-+ addHRegUse(u, HRmWrite, i->LAin.FpMove.dst);
++ }
++ case 0b01: {
++ rHi = gen_vshuf4i_h(jHi, id0, id1, id2, id3);
++ rLo = gen_vshuf4i_h(jLo, id0, id1, id2, id3);
+ break;
-+ case LAin_FpCmp:
-+ addHRegUse(u, HRmRead, i->LAin.FpCmp.src2);
-+ addHRegUse(u, HRmRead, i->LAin.FpCmp.src1);
-+ addHRegUse(u, HRmWrite, i->LAin.FpCmp.dst);
++ }
++ case 0b10: {
++ rHi = gen_vshuf4i_w(jHi, id0, id1, id2, id3);
++ rLo = gen_vshuf4i_w(jLo, id0, id1, id2, id3);
+ break;
-+ case LAin_VecUn:
-+ addHRegUse(u, HRmRead, i->LAin.VecUnary.src);
-+ addHRegUse(u, HRmWrite, i->LAin.VecUnary.dst);
++ }
++ case 0b11: {
++ rHi = gen_vshuf4i_d(jHi, dHi, id0, id1);
++ rLo = gen_vshuf4i_d(jLo, dLo, id0, id1);
+ break;
-+ case LAin_VecBin:
-+ addRegUsage_LOONGARCH64RI(u, i->LAin.VecBinary.src2);
-+ addHRegUse(u, HRmRead, i->LAin.VecBinary.src1);
-+ addHRegUse(u, HRmWrite, i->LAin.VecBinary.dst);
++ }
++ default: vassert(0);
++ }
++
++ DIP("vshuf4i.%s %s, %s, %u\n", mkInsSize(insSz),
++ nameXReg(xd), nameXReg(xj), ui8);
++ putXReg(xd, mkV256from128s(rHi, rLo));
++ return True;
++}
++
++static Bool gen_vpermi ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt ui8 = SLICE(insn, 17, 10);
++
++ UInt i;
++ UInt id0 = ui8 & 0x03;
++ UInt id1 = (ui8 & 0x0c) >> 2;
++ UInt id2 = (ui8 & 0x30) >> 4;
++ UInt id3 = (ui8 & 0xc0) >> 6;
++
++ IRTemp s[8];
++ for (i = 0; i < 4; i ++) {
++ s[i] = newTemp(Ity_I32);
++ assign(s[i], binop(Iop_GetElem32x4, getVReg(vj), mkU8(i)));
++
++ s[i + 4] = newTemp(Ity_I32);
++ assign(s[i + 4], binop(Iop_GetElem32x4, getVReg(vd), mkU8(i)));
++ }
++
++ DIP("vpermi.w %s, %s, %u\n", nameVReg(vd), nameVReg(vj), ui8);
++ putVReg(vd, mkV128from32s(s[id3 + 4], s[id2 + 4], s[id1], s[id0]));
++ return True;
++}
++
++static Bool gen_xvpermi ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt ui8 = SLICE(insn, 17, 10);
++ UInt InsSz = SLICE(insn, 19, 18);
++
++ UInt id0 = ui8 & 0x03;
++ UInt id1 = (ui8 & 0x0c) >> 2;
++ UInt id2 = (ui8 & 0x30) >> 4;
++ UInt id3 = (ui8 & 0xc0) >> 6;
++
++ IRTemp res = newTemp(Ity_V256);
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sD = newTemp(Ity_V256);
++ assign(sJ, getXReg(xj));
++ assign(sD, getXReg(xd));
++
++ switch (InsSz) {
++ case 0b01: {
++ IRTemp s[16];
++ s[7] = s[6] = s[5] = s[4] = s[3] = s[2] = s[1] = s[0] = IRTemp_INVALID;
++ s[15] = s[14] = s[13] = s[12] = s[11] = s[10] = s[9] = s[8] = IRTemp_INVALID;
++ breakupV256to32s(sJ, &s[7], &s[6], &s[5], &s[4],
++ &s[3], &s[2], &s[1], &s[0]);
++ breakupV256to32s(sD, &s[15], &s[14], &s[13], &s[12],
++ &s[11], &s[10], &s[9], &s[8]);
++ assign(res, mkV256from32s(s[id3 + 12], s[id2 + 12], s[id1 + 4], s[id0 + 4],
++ s[id3 + 8], s[id2 + 8], s[id1], s[id0]));
+ break;
-+ case LAin_VecLoad:
-+ addRegUsage_LOONGARCH64AMode(u, i->LAin.VecLoad.src);
-+ addHRegUse(u, HRmWrite, i->LAin.VecLoad.dst);
++ }
++ case 0b10: {
++ IRTemp s[4];
++ s[3] = s[2] = s[1] = s[0] = IRTemp_INVALID;
++ breakupV256to64s(sJ, &s[3], &s[2], &s[1], &s[0]);
++ assign(res, mkV256from64s(s[id3], s[id2], s[id1], s[id0]));
+ break;
-+ case LAin_VecStore:
-+ addRegUsage_LOONGARCH64AMode(u, i->LAin.VecStore.dst);
-+ addHRegUse(u, HRmRead, i->LAin.VecStore.src);
++ }
++ case 0b11: {
++ IRTemp s[4];
++ s[3] = s[2] = s[1] = s[0] = IRTemp_INVALID;
++ breakupV256toV128s(sJ, &s[1], &s[0]);
++ breakupV256toV128s(sD, &s[3], &s[2]);
++ assign(res, mkV256from128s(s[id2], s[id0]));
+ break;
-+ case LAin_Cas:
-+ addHRegUse(u, HRmWrite, i->LAin.Cas.old);
-+ addHRegUse(u, HRmRead, i->LAin.Cas.addr);
-+ addHRegUse(u, HRmRead, i->LAin.Cas.expd);
-+ addHRegUse(u, HRmModify, i->LAin.Cas.data);
++ }
++ default: vassert(0);
++ }
++
++ DIP("xvpermi.%s %s, %s, %u\n", mkInsSize(InsSz), nameXReg(xd), nameXReg(xj), ui8);
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
++
++ putXReg(xd, EX(res));
++ return True;
++}
++
++static IRTemp cal_vextrins ( IRTemp sJ, IRTemp sD, UInt ui8, UInt insSz )
++{
++ UInt idS, idD;
++ IRTemp res = newTemp(Ity_V128);
++
++ switch (insSz) {
++ case 0b11: {
++ idS = ui8 & 0x0f;
++ idD = (ui8 & 0xf0) >> 4;
++ assign(res, triop(Iop_SetElem8x16,
++ EX(sD),
++ mkU8(idD),
++ binop(Iop_GetElem8x16,
++ EX(sJ),
++ mkU8(idS))));
+ break;
-+ case LAin_Cmp:
-+ addHRegUse(u, HRmRead, i->LAin.Cmp.src2);
-+ addHRegUse(u, HRmRead, i->LAin.Cmp.src1);
-+ addHRegUse(u, HRmWrite, i->LAin.Cmp.dst);
++ }
++ case 0b10: {
++ idS = ui8 & 0x07;
++ idD = (ui8 & 0x70) >> 4;
++ assign(res, triop(Iop_SetElem16x8,
++ EX(sD),
++ mkU8(idD),
++ binop(Iop_GetElem16x8,
++ EX(sJ),
++ mkU8(idS))));
+ break;
-+ case LAin_CMove:
-+ addHRegUse(u, HRmRead, i->LAin.CMove.cond);
-+ addHRegUse(u, HRmRead, i->LAin.CMove.r0);
-+ addHRegUse(u, HRmRead, i->LAin.CMove.r1);
-+ addHRegUse(u, HRmWrite, i->LAin.CMove.dst);
++ }
++ case 0b01: {
++ idS = ui8 & 0x03;
++ idD = (ui8 & 0x30) >> 4;
++ assign(res, triop(Iop_SetElem32x4,
++ EX(sD),
++ mkU8(idD),
++ binop(Iop_GetElem32x4,
++ EX(sJ),
++ mkU8(idS))));
+ break;
-+ case LAin_Call:
-+ /* logic and comments copied/modified from mips and arm64 back end */
-+ /* This is a bit subtle. */
-+ /* First off, we need to consider the cond register. */
-+ if (!hregIsInvalid(i->LAin.Call.cond))
-+ addHRegUse(u, HRmRead, i->LAin.Call.cond);
-+ /* Then, claim it trashes all the caller-saved regs
-+ which fall within the register allocator's jurisdiction. */
-+ addHRegUse(u, HRmWrite, hregLOONGARCH64_R14());
-+ addHRegUse(u, HRmWrite, hregLOONGARCH64_R15());
-+ addHRegUse(u, HRmWrite, hregLOONGARCH64_R16());
-+ addHRegUse(u, HRmWrite, hregLOONGARCH64_R17());
-+ addHRegUse(u, HRmWrite, hregLOONGARCH64_R18());
-+ addHRegUse(u, HRmWrite, hregLOONGARCH64_R19());
-+ addHRegUse(u, HRmWrite, hregLOONGARCH64_R20());
-+ /* Now we have to state any parameter-carrying registers
-+ which might be read. This depends on nArgRegs. */
-+ switch (i->LAin.Call.nArgRegs) {
-+ case 8: addHRegUse(u, HRmRead, hregLOONGARCH64_R11()); /* fallthrough */
-+ case 7: addHRegUse(u, HRmRead, hregLOONGARCH64_R10()); /* fallthrough */
-+ case 6: addHRegUse(u, HRmRead, hregLOONGARCH64_R9()); /* fallthrough */
-+ case 5: addHRegUse(u, HRmRead, hregLOONGARCH64_R8()); /* fallthrough */
-+ case 4: addHRegUse(u, HRmRead, hregLOONGARCH64_R7()); /* fallthrough */
-+ case 3: addHRegUse(u, HRmRead, hregLOONGARCH64_R6()); /* fallthrough */
-+ case 2: addHRegUse(u, HRmRead, hregLOONGARCH64_R5()); /* fallthrough */
-+ case 1: addHRegUse(u, HRmRead, hregLOONGARCH64_R4()); /* fallthrough */
-+ case 0: break;
-+ default: vpanic("getRegUsage_LOONGARCH64:Call:regparms"); break;
++ }
++ case 0b00: {
++ idS = ui8 & 0x01;
++ idD = (ui8 & 0x10) >> 4;
++ if (idD == 0) {
++ assign(res, binop(Iop_64HLtoV128,
++ unop(Iop_V128HIto64, EX(sD)),
++ binop(Iop_GetElem64x2,
++ EX(sJ), mkU8(idS))));
++ } else {
++ assign(res, binop(Iop_64HLtoV128,
++ binop(Iop_GetElem64x2,
++ EX(sJ), mkU8(idS)),
++ unop(Iop_V128to64, EX(sD))));
+ }
-+ /* Finally, there is the issue that the insn trashes a
-+ register because the literal target address has to be
-+ loaded into a register. However, we reserve $t0 for that
-+ purpose so there's no further complexity here. Stating $t0
-+ as trashed is pointless since it's not under the control
-+ of the allocator, but what the hell. */
-+ addHRegUse(u, HRmWrite, hregT0());
-+ break;
-+ /* XDirect/XIndir/XAssisted are also a bit subtle. They
-+ conditionally exit the block. Hence we only need to list (1)
-+ the registers that they read, and (2) the registers that they
-+ write in the case where the block is not exited. (2) is
-+ empty, hence only (1) is relevant here. */
-+ case LAin_XDirect:
-+ addRegUsage_LOONGARCH64AMode(u, i->LAin.XDirect.amPC);
-+ if (!hregIsInvalid(i->LAin.XDirect.cond))
-+ addHRegUse(u, HRmRead, i->LAin.XDirect.cond);
-+ addHRegUse(u, HRmWrite, hregT0()); /* unavail to RA */
-+ break;
-+ case LAin_XIndir:
-+ addHRegUse(u, HRmRead, i->LAin.XIndir.dstGA);
-+ addRegUsage_LOONGARCH64AMode(u, i->LAin.XIndir.amPC);
-+ if (!hregIsInvalid(i->LAin.XIndir.cond))
-+ addHRegUse(u, HRmRead, i->LAin.XIndir.cond);
-+ addHRegUse(u, HRmWrite, hregT0()); /* unavail to RA */
-+ break;
-+ case LAin_XAssisted:
-+ addHRegUse(u, HRmRead, i->LAin.XAssisted.dstGA);
-+ addRegUsage_LOONGARCH64AMode(u, i->LAin.XAssisted.amPC);
-+ if (!hregIsInvalid(i->LAin.XAssisted.cond))
-+ addHRegUse(u, HRmRead, i->LAin.XAssisted.cond);
-+ addHRegUse(u, HRmWrite, hregT0()); /* unavail to RA */
-+ break;
-+ case LAin_EvCheck:
-+ /* We expect both amodes only to mention $r31, so this is in
-+ fact pointless, since $r31 isn't allocatable, but anyway.. */
-+ addRegUsage_LOONGARCH64AMode(u, i->LAin.EvCheck.amCounter);
-+ addRegUsage_LOONGARCH64AMode(u, i->LAin.EvCheck.amFailAddr);
-+ addHRegUse(u, HRmWrite, hregT0()); /* unavail to RA */
-+ break;
-+ case LAin_ProfInc:
-+ /* Again, pointless to actually state these since neither
-+ is available to RA. */
-+ addHRegUse(u, HRmWrite, hregT0()); /* unavail to RA */
-+ addHRegUse(u, HRmWrite, hregT1()); /* unavail to RA */
-+ break;
-+ default:
-+ ppLOONGARCH64Instr(i, mode64);
-+ vpanic("getRegUsage_LOONGARCH64Instr");
+ break;
++ }
++ default: vassert(0);
+ }
++
++ return res;
+}
+
-+void mapRegs_LOONGARCH64Instr ( HRegRemap* m, LOONGARCH64Instr* i,
-+ Bool mode64 )
++static Bool gen_vextrins ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(mode64 == True);
-+ switch (i->tag) {
-+ case LAin_LI:
-+ mapReg(m, &i->LAin.LI.dst);
-+ break;
-+ case LAin_Un:
-+ mapReg(m, &i->LAin.Unary.src);
-+ mapReg(m, &i->LAin.Unary.dst);
-+ break;
-+ case LAin_Bin:
-+ mapRegs_LOONGARCH64RI(m, i->LAin.Binary.src2);
-+ mapReg(m, &i->LAin.Binary.src1);
-+ mapReg(m, &i->LAin.Binary.dst);
-+ break;
-+ case LAin_Load:
-+ mapRegs_LOONGARCH64AMode(m, i->LAin.Load.src);
-+ mapReg(m, &i->LAin.Load.dst);
-+ break;
-+ case LAin_Store:
-+ mapRegs_LOONGARCH64AMode(m, i->LAin.Store.dst);
-+ mapReg(m, &i->LAin.Store.src);
-+ break;
-+ case LAin_LLSC:
-+ mapRegs_LOONGARCH64AMode(m, i->LAin.LLSC.addr);
-+ mapReg(m, &i->LAin.LLSC.val);
-+ break;
-+ case LAin_Bar:
-+ /* No regs. */
-+ break;
-+ case LAin_FpUn:
-+ mapReg(m, &i->LAin.FpUnary.src);
-+ mapReg(m, &i->LAin.FpUnary.dst);
-+ break;
-+ case LAin_FpBin:
-+ mapReg(m, &i->LAin.FpBinary.src2);
-+ mapReg(m, &i->LAin.FpBinary.src1);
-+ mapReg(m, &i->LAin.FpBinary.dst);
-+ break;
-+ case LAin_FpTri:
-+ mapReg(m, &i->LAin.FpTrinary.src3);
-+ mapReg(m, &i->LAin.FpTrinary.src2);
-+ mapReg(m, &i->LAin.FpTrinary.src1);
-+ mapReg(m, &i->LAin.FpTrinary.dst);
-+ break;
-+ case LAin_FpLoad:
-+ mapRegs_LOONGARCH64AMode(m, i->LAin.FpLoad.src);
-+ mapReg(m, &i->LAin.FpLoad.dst);
-+ break;
-+ case LAin_FpStore:
-+ mapRegs_LOONGARCH64AMode(m, i->LAin.FpStore.dst);
-+ mapReg(m, &i->LAin.FpStore.src);
-+ break;
-+ case LAin_FpMove:
-+ mapReg(m, &i->LAin.FpMove.src);
-+ mapReg(m, &i->LAin.FpMove.dst);
-+ break;
-+ case LAin_FpCmp:
-+ mapReg(m, &i->LAin.FpCmp.src2);
-+ mapReg(m, &i->LAin.FpCmp.src1);
-+ mapReg(m, &i->LAin.FpCmp.dst);
-+ break;
-+ case LAin_VecUn:
-+ mapReg(m, &i->LAin.VecUnary.src);
-+ mapReg(m, &i->LAin.VecUnary.dst);
-+ break;
-+ case LAin_VecBin:
-+ mapRegs_LOONGARCH64RI(m, i->LAin.VecBinary.src2);
-+ mapReg(m, &i->LAin.VecBinary.src1);
-+ mapReg(m, &i->LAin.VecBinary.dst);
-+ break;
-+ case LAin_VecLoad:
-+ mapRegs_LOONGARCH64AMode(m, i->LAin.VecLoad.src);
-+ mapReg(m, &i->LAin.VecLoad.dst);
-+ break;
-+ case LAin_VecStore:
-+ mapRegs_LOONGARCH64AMode(m, i->LAin.VecStore.dst);
-+ mapReg(m, &i->LAin.VecStore.src);
-+ break;
-+ case LAin_Cas:
-+ mapReg(m, &i->LAin.Cas.old);
-+ mapReg(m, &i->LAin.Cas.addr);
-+ mapReg(m, &i->LAin.Cas.expd);
-+ mapReg(m, &i->LAin.Cas.data);
-+ break;
-+ case LAin_Cmp:
-+ mapReg(m, &i->LAin.Cmp.src2);
-+ mapReg(m, &i->LAin.Cmp.src1);
-+ mapReg(m, &i->LAin.Cmp.dst);
-+ break;
-+ case LAin_CMove:
-+ mapReg(m, &i->LAin.CMove.cond);
-+ mapReg(m, &i->LAin.CMove.r0);
-+ mapReg(m, &i->LAin.CMove.r1);
-+ mapReg(m, &i->LAin.CMove.dst);
-+ break;
-+ case LAin_Call:
-+ if (!hregIsInvalid(i->LAin.Call.cond))
-+ mapReg(m, &i->LAin.Call.cond);
-+ /* Hardwires $r12. */
-+ break;
-+ /* XDirect/XIndir/XAssisted are also a bit subtle. They
-+ conditionally exit the block. Hence we only need to list (1)
-+ the registers that they read, and (2) the registers that they
-+ write in the case where the block is not exited. (2) is
-+ empty, hence only (1) is relevant here. */
-+ case LAin_XDirect:
-+ mapRegs_LOONGARCH64AMode(m, i->LAin.XDirect.amPC);
-+ if (!hregIsInvalid(i->LAin.XDirect.cond))
-+ mapReg(m, &i->LAin.XDirect.cond);
-+ break;
-+ case LAin_XIndir:
-+ mapReg(m, &i->LAin.XIndir.dstGA);
-+ mapRegs_LOONGARCH64AMode(m, i->LAin.XIndir.amPC);
-+ if (!hregIsInvalid(i->LAin.XIndir.cond))
-+ mapReg(m, &i->LAin.XIndir.cond);
-+ break;
-+ case LAin_XAssisted:
-+ mapReg(m, &i->LAin.XAssisted.dstGA);
-+ mapRegs_LOONGARCH64AMode(m, i->LAin.XAssisted.amPC);
-+ if (!hregIsInvalid(i->LAin.XAssisted.cond))
-+ mapReg(m, &i->LAin.XAssisted.cond);
-+ break;
-+ case LAin_EvCheck:
-+ /* We expect both amodes only to mention $r31, so this is in
-+ fact pointless, since $r31 isn't allocatable, but anyway.. */
-+ mapRegs_LOONGARCH64AMode(m, i->LAin.EvCheck.amCounter);
-+ mapRegs_LOONGARCH64AMode(m, i->LAin.EvCheck.amFailAddr);
-+ break;
-+ case LAin_ProfInc:
-+ /* Hardwires $r12 and $r13 -- nothing to modify. */
-+ break;
-+ default:
-+ ppLOONGARCH64Instr(i, mode64);
-+ vpanic("mapRegs_LOONGARCH64Instr");
-+ break;
-+ }
++ UInt vd = SLICE(insn, 4, 0);
++ UInt vj = SLICE(insn, 9, 5);
++ UInt ui8 = SLICE(insn, 17, 10);
++ UInt insSz = SLICE(insn, 19, 18);
++
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp sJ = newTemp(Ity_V128);
++ IRTemp sD = newTemp(Ity_V128);
++ assign(sJ, getVReg(vj));
++ assign(sD, getVReg(vd));
++
++ res = cal_vextrins(sJ, sD, ui8, insSz);
++ DIP("vextrins.%s %s, %s, %u\n", mkInsSize(3 - insSz),
++ nameVReg(vd), nameVReg(vj), ui8);
++ putVReg(vd, EX(res));
++ return True;
+}
+
-+/* Generate loongarch64 spill instructions under the direction of the
-+ register allocator. */
-+void genSpill_LOONGARCH64 ( /*OUT*/ HInstr** i1, /*OUT*/ HInstr** i2,
-+ HReg rreg, Int offsetB, Bool mode64 )
++static Bool gen_xvextrins ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(mode64 == True);
-+ vassert(offsetB >= 0);
-+ vassert(!hregIsVirtual(rreg));
++ UInt xd = SLICE(insn, 4, 0);
++ UInt xj = SLICE(insn, 9, 5);
++ UInt ui8 = SLICE(insn, 17, 10);
++ UInt insSz = SLICE(insn, 19, 18);
++
++ IRTemp sJ = newTemp(Ity_V256);
++ IRTemp sD = newTemp(Ity_V256);
++ IRTemp rHi = newTemp(Ity_V128);
++ IRTemp rLo = newTemp(Ity_V128);
++ IRTemp jHi = IRTemp_INVALID;
++ IRTemp jLo = IRTemp_INVALID;
++ IRTemp dHi = IRTemp_INVALID;
++ IRTemp dLo = IRTemp_INVALID;
++ assign(sJ, getXReg(xj));
++ assign(sD, getXReg(xd));
++ breakupV256toV128s(sJ, &jHi, &jLo);
++ breakupV256toV128s(sD, &dHi, &dLo);
++
++ rHi = cal_vextrins(jHi, dHi, ui8, insSz);
++ rLo = cal_vextrins(jLo, dLo, ui8, insSz);
++ DIP("xvextrins.%s %s, %s, %u\n", mkInsSize(3 - insSz),
++ nameXReg(xd), nameXReg(xj), ui8);
++ putXReg(xd, mkV256from128s(rHi, rLo));
++ return True;
++}
+
-+ LOONGARCH64AMode* am;
-+ *i1 = *i2 = NULL;
+
-+ switch (hregClass(rreg)) {
-+ case HRcInt64:
-+ if (offsetB < 1024) {
-+ am = LOONGARCH64AMode_RI(hregGSP(), offsetB);
-+ *i1 = LOONGARCH64Instr_Store(LAstore_ST_D, am, rreg);
-+ } else {
-+ *i1 = LOONGARCH64Instr_LI(offsetB, hregT0());
-+ am = LOONGARCH64AMode_RR(hregGSP(), hregT0());
-+ *i2 = LOONGARCH64Instr_Store(LAstore_STX_D, am, rreg);
-+ }
-+ break;
-+ case HRcFlt64:
-+ if (offsetB < 1024) {
-+ am = LOONGARCH64AMode_RI(hregGSP(), offsetB);
-+ *i1 = LOONGARCH64Instr_FpStore(LAfpstore_FST_D, am, rreg);
-+ } else {
-+ *i1 = LOONGARCH64Instr_LI(offsetB, hregT0());
-+ am = LOONGARCH64AMode_RR(hregGSP(), hregT0());
-+ *i2 = LOONGARCH64Instr_FpStore(LAfpstore_FSTX_D, am, rreg);
-+ }
-+ break;
-+ case HRcVec128:
-+ if (offsetB < 1024) {
-+ am = LOONGARCH64AMode_RI(hregGSP(), offsetB);
-+ *i1 = LOONGARCH64Instr_VecStore(LAvecstore_VST, am, rreg);
-+ } else {
-+ am = LOONGARCH64AMode_RR(hregGSP(), hregT0());
-+ *i1 = LOONGARCH64Instr_LI(offsetB, hregT0());
-+ *i2 = LOONGARCH64Instr_VecStore(LAvecstore_VSTX, am, rreg);
-+ }
-+ break;
-+ default:
-+ ppHRegClass(hregClass(rreg));
-+ vpanic("genSpill_LOONGARCH64: unimplemented regclass");
-+ break;
-+ }
-+}
++/*------------------------------------------------------------*/
++/*--- Helpers for vector load/store insns ---*/
++/*------------------------------------------------------------*/
+
-+/* Generate loongarch64 reload instructions under the direction of the
-+ register allocator. */
-+void genReload_LOONGARCH64 ( /*OUT*/ HInstr** i1, /*OUT*/ HInstr** i2,
-+ HReg rreg, Int offsetB, Bool mode64 )
++static Bool gen_vld ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(mode64 == True);
-+ vassert(offsetB >= 0);
-+ vassert(!hregIsVirtual(rreg));
++ UInt si12 = SLICE(insn, 21, 10);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt vd = SLICE(insn, 4, 0);
+
-+ LOONGARCH64AMode* am;
-+ *i1 = *i2 = NULL;
++ DIP("vld %s, %s, %d\n", nameVReg(vd), nameIReg(rj),
++ (Int)extend32(si12, 12));
+
-+ switch (hregClass(rreg)) {
-+ case HRcInt64:
-+ if (offsetB < 1024) {
-+ am = LOONGARCH64AMode_RI(hregGSP(), offsetB);
-+ *i1 = LOONGARCH64Instr_Load(LAload_LD_D, am, rreg);
-+ } else {
-+ *i1 = LOONGARCH64Instr_LI(offsetB, hregT0());
-+ am = LOONGARCH64AMode_RR(hregGSP(), hregT0());
-+ *i2 = LOONGARCH64Instr_Load(LAload_LDX_D, am, rreg);
-+ }
-+ break;
-+ case HRcFlt64:
-+ if (offsetB < 1024) {
-+ am = LOONGARCH64AMode_RI(hregGSP(), offsetB);
-+ *i1 = LOONGARCH64Instr_FpLoad(LAfpload_FLD_D, am, rreg);
-+ } else {
-+ *i1 = LOONGARCH64Instr_LI(offsetB, hregT0());
-+ am = LOONGARCH64AMode_RR(hregGSP(), hregT0());
-+ *i2 = LOONGARCH64Instr_FpLoad(LAfpload_FLDX_D, am, rreg);
-+ }
-+ break;
-+ case HRcVec128:
-+ if (offsetB < 1024) {
-+ am = LOONGARCH64AMode_RI(hregGSP(), offsetB);
-+ *i1 = LOONGARCH64Instr_VecLoad(LAvecload_VLD, am, rreg);
-+ } else {
-+ am = LOONGARCH64AMode_RR(hregGSP(), hregT0());
-+ *i1 = LOONGARCH64Instr_LI(offsetB, hregT0());
-+ *i2 = LOONGARCH64Instr_VecLoad(LAvecload_VLDX, am, rreg);
-+ }
-+ break;
-+ default:
-+ ppHRegClass(hregClass(rreg));
-+ vpanic("genReload_LOONGARCH64: unimplemented regclass");
-+ break;
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
++
++ IRExpr* addr = binop(Iop_Add64, getIReg64(rj), mkU64(extend64(si12, 12)));
++ putVReg(vd, load(Ity_V128, addr));
++
++ return True;
+}
+
-+/* Generate loongarch64 move instructions under the direction of the
-+ register allocator. */
-+LOONGARCH64Instr* genMove_LOONGARCH64 ( HReg from, HReg to, Bool mode64 )
++static Bool gen_vldx ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(mode64 == True);
-+ switch (hregClass(from)) {
-+ case HRcInt64:
-+ return LOONGARCH64Instr_Binary(LAbin_OR,
-+ LOONGARCH64RI_R(hregZERO()),
-+ from, to);
-+ case HRcFlt64:
-+ return LOONGARCH64Instr_FpMove(LAfpmove_FMOV_D, from, to);
-+ case HRcVec128:
-+ return LOONGARCH64Instr_VecBinary(LAvecbin_VORI_B,
-+ LOONGARCH64RI_I(0, 8, False),
-+ from, to);
-+ default:
-+ ppHRegClass(hregClass(from));
-+ vpanic("genMove_LOONGARCH64: unimplemented regclass");
++ UInt vd = SLICE(insn, 4, 0);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt rk = SLICE(insn, 15, 10);
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
++
++ IRExpr* addr = binop(Iop_Add64, getIReg64(rj), getIReg64(rk));
++ DIP("vldx %s, %s, %s\n", nameVReg(vd), nameIReg(rj), nameIReg(rk));
++ putVReg(vd, load(Ity_V128, addr));
++ return True;
+}
+
++static Bool gen_xvld ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ UInt si12 = SLICE(insn, 21, 10);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt xd = SLICE(insn, 4, 0);
+
-+/* --------- The loongarch64 assembler --------- */
++ DIP("xvld %s, %s, %d\n", nameXReg(xd), nameIReg(rj),
++ (Int)extend32(si12, 12));
+
-+static inline UInt iregEnc ( HReg r )
-+{
-+ vassert(hregClass(r) == HRcInt64);
-+ vassert(!hregIsVirtual(r));
-+ UInt n = hregEncoding(r);
-+ vassert(n < 32);
-+ return n;
-+}
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+static inline UInt fregEnc ( HReg r )
-+{
-+ vassert(hregClass(r) == HRcFlt64);
-+ vassert(!hregIsVirtual(r));
-+ UInt n = hregEncoding(r);
-+ vassert(n < 32);
-+ return n;
-+}
++ IRExpr* addr = binop(Iop_Add64, getIReg64(rj), mkU64(extend64(si12, 12)));
++ putXReg(xd, load(Ity_V256, addr));
+
-+static inline UInt vregEnc ( HReg r )
-+{
-+ vassert(hregClass(r) == HRcVec128);
-+ vassert(!hregIsVirtual(r));
-+ UInt n = hregEncoding(r);
-+ vassert(n < 32);
-+ return n;
++ return True;
+}
+
-+static inline UInt fcsrEnc ( HReg r )
++static Bool gen_xvldx ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(hregClass(r) == HRcInt32);
-+ vassert(!hregIsVirtual(r));
-+ UInt n = hregEncoding(r);
-+ vassert(n < 32);
-+ return n;
-+}
++ UInt xd = SLICE(insn, 4, 0);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt rk = SLICE(insn, 15, 10);
+
-+static inline UInt emit_op_rj_rd ( UInt op, UInt rj, UInt rd )
-+{
-+ vassert(rj < (1 << 5));
-+ vassert(rd < (1 << 5));
-+ return op | (rj << 5) | rd;
-+}
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+static inline UInt emit_op_rk_rj_rd ( UInt op, UInt rk, UInt rj, UInt rd )
-+{
-+ vassert(rk < (1 << 5));
-+ vassert(rj < (1 << 5));
-+ vassert(rd < (1 << 5));
-+ return op | (rk << 10) | (rj << 5) | rd;
++ IRExpr* addr = binop(Iop_Add64, getIReg64(rj), getIReg64(rk));
++ DIP("xvldx %s, %s, %s\n", nameXReg(xd), nameIReg(rj), nameIReg(rk));
++ putXReg(xd, load(Ity_V256, addr));
++ return True;
+}
+
-+static inline UInt emit_op_fj_fd ( UInt op, UInt fj, UInt fd )
++static Bool gen_vst ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(fj < (1 << 5));
-+ vassert(fd < (1 << 5));
-+ return op | (fj << 5) | fd;
-+}
++ UInt si12 = SLICE(insn, 21, 10);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt vd = SLICE(insn, 4, 0);
+
-+static inline UInt emit_op_fa_fk_fj_fd ( UInt op, UInt fa, UInt fk, UInt fj, UInt fd )
-+{
-+ vassert(fa < (1 << 5));
-+ vassert(fk < (1 << 5));
-+ vassert(fj < (1 << 5));
-+ vassert(fd < (1 << 5));
-+ return op | (fa << 15) | (fk << 10) | (fj << 5) | fd;
-+}
++ DIP("vst %s, %s, %d\n", nameVReg(vd), nameIReg(rj),
++ (Int)extend32(si12, 12));
+
-+static inline UInt emit_op_fk_fj_fd ( UInt op, UInt fk, UInt fj, UInt fd )
-+{
-+ vassert(fk < (1 << 5));
-+ vassert(fj < (1 << 5));
-+ vassert(fd < (1 << 5));
-+ return op | (fk << 10) | (fj << 5) | fd;
-+}
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+static inline UInt emit_op_ca_fk_fj_fd ( UInt op, UInt ca, UInt fk, UInt fj, UInt fd )
-+{
-+ vassert(ca < (1 << 3));
-+ vassert(fk < (1 << 5));
-+ vassert(fj < (1 << 5));
-+ vassert(fd < (1 << 5));
-+ return op | (ca << 15) | (fk << 10) | (fj << 5) | fd;
-+}
++ IRExpr* addr = binop(Iop_Add64, getIReg64(rj), mkU64(extend64(si12, 12)));
++ store(addr, getVReg(vd));
+
-+static inline UInt emit_op_fk_fj_cd ( UInt op, UInt fk, UInt fj, UInt cd )
-+{
-+ vassert(fk < (1 << 5));
-+ vassert(fj < (1 << 5));
-+ vassert(cd < (1 << 3));
-+ return op | (fk << 10) | (fj << 5) | cd;
++ return True;
+}
+
-+static inline UInt emit_op_cj_rd ( UInt op, UInt cj, UInt rd )
++static Bool gen_vstx ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(cj < (1 << 3));
-+ vassert(rd < (1 << 5));
-+ return op | (cj << 5) | rd;
-+}
++ UInt vd = SLICE(insn, 4, 0);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt rk = SLICE(insn, 15, 10);
+
-+static inline UInt emit_op_rj_cd ( UInt op, UInt rj, UInt cd )
-+{
-+ vassert(rj < (1 << 5));
-+ vassert(cd < (1 << 3));
-+ return op | (rj << 5) | cd;
-+}
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+static inline UInt emit_op_rj_fd ( UInt op, UInt rj, UInt fd )
-+{
-+ vassert(rj < (1 << 5));
-+ vassert(fd < (1 << 5));
-+ return op | (rj << 5) | fd;
++ IRExpr* addr = binop(Iop_Add64, getIReg64(rj), getIReg64(rk));
++ DIP("vstx %s, %s, %s\n", nameVReg(vd), nameIReg(rj), nameIReg(rk));
++ store(addr, getVReg(vd));
++ return True;
+}
+
-+static inline UInt emit_op_fj_rd ( UInt op, UInt fj, UInt rd )
++static Bool gen_xvst ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(fj < (1 << 5));
-+ vassert(rd < (1 << 5));
-+ return op | (fj << 5) | rd;
-+}
++ UInt si12 = SLICE(insn, 21, 10);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt xd = SLICE(insn, 4, 0);
+
-+static inline UInt emit_op_rj_fcsr ( UInt op, UInt rj, UInt fcsr )
-+{
-+ vassert(rj < (1 << 5));
-+ vassert(fcsr < (1 << 5));
-+ return op | (rj << 5) | fcsr;
-+}
++ DIP("xvst %s, %s, %d\n", nameXReg(xd), nameIReg(rj),
++ (Int)extend32(si12, 12));
+
-+static inline UInt emit_op_fcsr_rd ( UInt op, UInt fcsr, UInt rd )
-+{
-+ vassert(fcsr < (1 << 5));
-+ vassert(rd < (1 << 5));
-+ return op | (fcsr << 5) | rd;
-+}
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+static inline UInt emit_op_ui5_rj_rd ( UInt op, UInt ui5, UInt rj, UInt rd )
-+{
-+ vassert(ui5 < (1 << 5));
-+ vassert(rj < (1 << 5));
-+ vassert(rd < (1 << 5));
-+ return op | (ui5 << 10) | (rj << 5) | rd;
-+}
++ IRExpr* addr = binop(Iop_Add64, getIReg64(rj), mkU64(extend64(si12, 12)));
++ store(addr, getXReg(xd));
+
-+static inline UInt emit_op_ui6_rj_rd ( UInt op, UInt ui6, UInt rj, UInt rd )
-+{
-+ vassert(ui6 < (1 << 6));
-+ vassert(rj < (1 << 5));
-+ vassert(rd < (1 << 5));
-+ return op | (ui6 << 10) | (rj << 5) | rd;
++ return True;
+}
+
-+static inline UInt emit_op_ui12_rj_rd ( UInt op, UInt ui12, UInt rj, UInt rd )
++static Bool gen_xvstx ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(ui12 < (1 << 12));
-+ vassert(rj < (1 << 5));
-+ vassert(rd < (1 << 5));
-+ return op | (ui12 << 10) | (rj << 5) | rd;
-+}
++ UInt xd = SLICE(insn, 4, 0);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt rk = SLICE(insn, 15, 10);
+
-+static inline UInt emit_op_si12_rj_rd ( UInt op, UInt si12, UInt rj, UInt rd )
-+{
-+ vassert(si12 < (1 << 12));
-+ vassert(rj < (1 << 5));
-+ vassert(rd < (1 << 5));
-+ return op | (si12 << 10) | (rj << 5) | rd;
-+}
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+static inline UInt emit_op_si14_rj_rd ( UInt op, UInt si14, UInt rj, UInt rd )
-+{
-+ vassert(si14 < (1 << 14));
-+ vassert(rj < (1 << 5));
-+ vassert(rd < (1 << 5));
-+ return op | (si14 << 10) | (rj << 5) | rd;
++ IRExpr* addr = binop(Iop_Add64, getIReg64(rj), getIReg64(rk));
++ DIP("xvstx %s, %s, %s\n", nameXReg(xd), nameIReg(rj), nameIReg(rk));
++ store(addr, getXReg(xd));
++ return True;
+}
+
-+static inline UInt emit_op_si20_rd ( UInt op, UInt si20, UInt rd )
++static Bool gen_vldrepl ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(si20 < (1 << 20));
-+ vassert(rd < (1 << 5));
-+ return op | (si20 << 5) | rd;
-+}
++ UInt vd = SLICE(insn, 4, 0);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 23, 10);
+
-+static inline UInt emit_op_offs16_rj_rd ( UInt op, UInt offs16, UInt rj, UInt rd )
-+{
-+ vassert(offs16 < (1 << 16));
-+ vassert(rj < (1 << 5));
-+ vassert(rd < (1 << 5));
-+ return op | (offs16 << 10) | (rj << 5) | rd;
-+}
++ UInt sImm, insSz;
++ IRTemp res = newTemp(Ity_V128);
++ IRTemp addr = newTemp(Ity_I64);
+
-+static inline UInt emit_op_offs26 ( UInt op, UInt offs26 )
-+{
-+ vassert(offs26 < (1 << 26));
-+ return op | ((offs26 & 0xffff) << 10) | (offs26 >> 16);
-+}
++ if ((insImm & 0x3000) == 0x2000) { // 10si12; b
++ sImm = insImm & 0xfff;
++ insSz = 0;
++ } else if ((insImm & 0x3800) == 0x1000) { // 010si11; h
++ sImm = insImm & 0x7ff;
++ insSz = 1;
++ } else if ((insImm & 0x3c00) == 0x800) { // 0010si10; w
++ sImm = insImm & 0x3ff;
++ insSz = 2;
++ } else if ((insImm & 0x3e00) == 0x400) { // 00010si9; d
++ sImm = insImm & 0x1ff;
++ insSz = 3;
++ } else {
++ vassert(0);
++ }
+
-+static inline UInt emit_op_hint15 ( UInt op, UInt hint )
-+{
-+ vassert(hint < (1 << 15));
-+ return op | hint;
-+}
++ switch (insSz) {
++ case 0b00: {
++ assign(addr, binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(sImm, 12))));
++ assign(res, unop(Iop_Dup8x16, load(Ity_I8, EX(addr))));
++ break;
++ }
++ case 0b01: {
++ assign(addr, binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(sImm << 1, 12))));
++ assign(res, unop(Iop_Dup16x8, load(Ity_I16, EX(addr))));
++ break;
++ }
++ case 0b10: {
++ assign(addr, binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(sImm << 2, 12))));
++ assign(res, unop(Iop_Dup32x4, load(Ity_I32, EX(addr))));
++ break;
++ }
++ case 0b11: {
++ assign(addr, binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(sImm << 3, 12))));
++ assign(res, binop(Iop_64HLtoV128,
++ load(Ity_I64, EX(addr)),
++ load(Ity_I64, EX(addr))));
++ break;
++ }
++ default: vassert(0);
++ }
+
-+static inline UInt emit_op_si12_rj_vd ( UInt op, UInt si12, UInt rj, UInt vd )
-+{
-+ vassert(si12 < (1 << 12));
-+ vassert(rj < (1 << 5));
-+ vassert(vd < (1 << 5));
-+ return op | (si12 << 10) | (rj << 5) | vd;
-+}
++ DIP("vldrepl.%s %s, %s, %u\n", mkInsSize(insSz),
++ nameVReg(vd), nameIReg(rj), sImm);
+
-+static inline UInt emit_op_rk_rj_vd ( UInt op, UInt rk, UInt rj, UInt vd )
-+{
-+ vassert(rk < (1 << 5));
-+ vassert(rj < (1 << 5));
-+ vassert(vd < (1 << 5));
-+ return op | (rk << 10) | (rj << 5) | vd;
-+}
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
+
-+static inline UInt emit_unop_r ( UInt op, Int src, UInt dst, UInt dst_size)
-+{
-+ vassert(src < (1 << 5));
-+ vassert(dst < (1 << dst_size));
-+ return op | (src << 5) | dst;
++ putVReg(vd, EX(res));
++ return True;
+}
+
-+static inline UInt emit_binop_rr ( UInt op, UInt src2, UInt src1, UInt dst )
++static Bool gen_xvldrepl ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(src2 < (1 << 5));
-+ vassert(src1 < (1 << 5));
-+ vassert(dst < (1 << 5));
-+ return op | (src2 << 10) | (src1 << 5) | dst;
-+}
++ UInt xd = SLICE(insn, 4, 0);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt insImm = SLICE(insn, 23, 10);
+
-+static inline UInt emit_binop_ri ( UInt op, UInt imm, UInt size, UInt src, UInt dst )
-+{
-+ vassert(imm < (1 << size));
-+ vassert(src < (1 << 5));
-+ vassert(dst < (1 << 5));
-+ return op | (imm << 10) | (src << 5) | dst;
-+}
++ UInt sImm, insSz;
++ IRTemp dup = newTemp(Ity_V128);
++ IRTemp addr = newTemp(Ity_I64);
+
++ if ((insImm & 0x3000) == 0x2000) { // 10si12; b
++ sImm = insImm & 0xfff;
++ insSz = 0;
++ } else if ((insImm & 0x3800) == 0x1000) { // 010si11; h
++ sImm = insImm & 0x7ff;
++ insSz = 1;
++ } else if ((insImm & 0x3c00) == 0x800) { // 0010si10; w
++ sImm = insImm & 0x3ff;
++ insSz = 2;
++ } else if ((insImm & 0x3e00) == 0x400) { // 00010si9; d
++ sImm = insImm & 0x1ff;
++ insSz = 3;
++ } else {
++ vassert(0);
++ }
+
-+static UInt* mkLoadImm_EXACTLY4 ( UInt* p, HReg dst, ULong imm )
-+{
-+ /*
-+ lu12i.w dst, imm[31:12]
-+ ori dst, dst, imm[11:0]
-+ lu32i.d dst, imm[51:32]
-+ lu52i.d dst, dst, imm[63:52]
-+ */
-+ UInt d = iregEnc(dst);
-+ *p++ = emit_op_si20_rd(LAextra_LU12I_W, (imm >> 12) & 0xfffff, d);
-+ *p++ = emit_op_si12_rj_rd(LAbin_ORI, imm & 0xfff, d, d);
-+ *p++ = emit_op_si20_rd(LAextra_LU32I_D, (imm >> 32) & 0xfffff, d);
-+ *p++ = emit_op_si12_rj_rd(LAextra_LU52I_D, (imm >> 52) & 0xfff, d, d);
-+ return p;
-+}
++ switch (insSz) {
++ case 0b00: {
++ assign(addr, binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(sImm, 12))));
++ assign(dup, unop(Iop_Dup8x16, load(Ity_I8, EX(addr))));
++ break;
++ }
++ case 0b01: {
++ assign(addr, binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(sImm << 1, 12))));
++ assign(dup, unop(Iop_Dup16x8, load(Ity_I16, EX(addr))));
++ break;
++ }
++ case 0b10: {
++ assign(addr, binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(sImm << 2, 12))));
++ assign(dup, unop(Iop_Dup32x4, load(Ity_I32, EX(addr))));
++ break;
++ }
++ case 0b11: {
++ assign(addr, binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(sImm << 3, 12))));
++ assign(dup, binop(Iop_64HLtoV128,
++ load(Ity_I64, EX(addr)),
++ load(Ity_I64, EX(addr))));
++ break;
++ }
++ default: vassert(0);
++ }
+
-+static inline UInt* mkLoadImm_EXACTLY2 ( UInt* p, HReg dst, ULong imm )
-+{
-+ /*
-+ lu12i.w dst, imm[31:12]
-+ ori dst, dst, imm[11:0]
-+ */
-+ UInt d = iregEnc(dst);
-+ *p++ = emit_op_si20_rd(LAextra_LU12I_W, (imm >> 12) & 0xfffff, d);
-+ *p++ = emit_op_si12_rj_rd(LAbin_ORI, imm & 0xfff, d, d);
-+ return p;
++ DIP("xvldrepl.%s %s, %s, %u\n", mkInsSize(insSz),
++ nameXReg(xd), nameIReg(rj), sImm);
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
++ }
++ putXReg(xd, mkV256from128s(dup, dup));
++ return True;
+}
+
-+static inline UInt* mkLoadImm_EXACTLY1 ( UInt* p, HReg dst, ULong imm )
++static Bool gen_vstelm ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ /* ori dst, $zero, imm[11:0] */
-+ *p++ = emit_op_si12_rj_rd(LAbin_ORI, imm, 0, iregEnc(dst));
-+ return p;
-+}
++ UInt vd = SLICE(insn, 4, 0);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt si8 = SLICE(insn, 17, 10);
++ UInt insImm = SLICE(insn, 23, 18);
+
-+static UInt* mkLoadImm ( UInt* p, HReg dst, ULong imm )
-+{
-+ if ((imm >> 12) == 0)
-+ p = mkLoadImm_EXACTLY1(p, dst, imm);
-+ else if (imm < 0x80000000 || (imm >> 31) == 0x1ffffffffUL)
-+ p = mkLoadImm_EXACTLY2(p, dst, imm);
-+ else
-+ p = mkLoadImm_EXACTLY4(p, dst, imm);
-+ return p;
-+}
++ IRExpr* addr;
++ UInt idx, insSz;
+
-+static Bool is_LoadImm_EXACTLY4 ( UInt* p, HReg dst, ULong imm )
-+{
-+ UInt expect[4];
-+ mkLoadImm_EXACTLY4(expect, dst, imm);
-+ return toBool(p[0] == expect[0] && p[1] == expect[1] &&
-+ p[2] == expect[2] && p[3] == expect[3]);
-+}
++ if ((insImm & 0x30) == 0x20) { // 10_idx; b
++ idx = insImm & 0xf;
++ insSz = 0;
++ } else if ((insImm & 0x38) == 0x10) { // 010_idx; h
++ idx = insImm & 0x7;
++ insSz = 1;
++ } else if ((insImm & 0x3c) == 0x8) { // 000_idx; w
++ idx = insImm & 0x3;
++ insSz = 2;
++ } else if ((insImm & 0x3e) == 0x4) { // 00010_idx; d
++ idx = insImm & 0x1;
++ insSz = 3;
++ } else {
++ return False;
++ }
+
-+static inline UInt* mkUnary ( UInt* p, LOONGARCH64UnOp op, HReg src, HReg dst )
-+{
-+ switch (op) {
-+ case LAun_CLZ_W:
-+ case LAun_CTZ_W:
-+ case LAun_CLZ_D:
-+ case LAun_CTZ_D:
-+ case LAun_EXT_W_H:
-+ case LAun_EXT_W_B:
-+ *p++ = emit_op_rj_rd(op, iregEnc(src), iregEnc(dst));
-+ return p;
-+ default:
-+ return NULL;
++ switch (insSz) {
++ case 0b00:
++ addr = binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(si8, 8)));
++ break;
++ case 0b01:
++ addr = binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(si8 << 1, 9)));
++ break;
++ case 0b10:
++ addr = binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(si8 << 2, 10)));
++ break;
++ case 0b11:
++ addr = binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(si8 << 3, 11)));
++ break;
++ default: vassert(0);
+ }
-+}
+
-+static inline UInt* mkBinary ( UInt* p, LOONGARCH64BinOp op,
-+ LOONGARCH64RI* src2, HReg src1, HReg dst )
-+{
-+ switch (op) {
-+ case LAbin_ADD_W:
-+ case LAbin_ADD_D:
-+ case LAbin_SUB_W:
-+ case LAbin_SUB_D:
-+ case LAbin_NOR:
-+ case LAbin_AND:
-+ case LAbin_OR:
-+ case LAbin_XOR:
-+ case LAbin_SLL_W:
-+ case LAbin_SRL_W:
-+ case LAbin_SRA_W:
-+ case LAbin_SLL_D:
-+ case LAbin_SRL_D:
-+ case LAbin_SRA_D:
-+ case LAbin_MUL_W:
-+ case LAbin_MUL_D:
-+ case LAbin_MULH_W:
-+ case LAbin_MULH_WU:
-+ case LAbin_MULH_D:
-+ case LAbin_MULH_DU:
-+ case LAbin_MULW_D_W:
-+ case LAbin_MULW_D_WU:
-+ case LAbin_DIV_W:
-+ case LAbin_MOD_W:
-+ case LAbin_DIV_WU:
-+ case LAbin_MOD_WU:
-+ case LAbin_DIV_D:
-+ case LAbin_MOD_D:
-+ case LAbin_DIV_DU:
-+ case LAbin_MOD_DU:
-+ vassert(src2->tag == LAri_Reg);
-+ *p++ = emit_op_rk_rj_rd(op, iregEnc(src2->LAri.R.reg),
-+ iregEnc(src1), iregEnc(dst));
-+ return p;
-+ case LAbin_SLLI_W:
-+ case LAbin_SRLI_W:
-+ case LAbin_SRAI_W:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_op_ui5_rj_rd(op, src2->LAri.I.imm,
-+ iregEnc(src1), iregEnc(dst));
-+ return p;
-+ case LAbin_SLLI_D:
-+ case LAbin_SRLI_D:
-+ case LAbin_SRAI_D:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_op_ui6_rj_rd(op, src2->LAri.I.imm,
-+ iregEnc(src1), iregEnc(dst));
-+ return p;
-+ case LAbin_ADDI_W:
-+ case LAbin_ADDI_D:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_op_si12_rj_rd(op, src2->LAri.I.imm,
-+ iregEnc(src1), iregEnc(dst));
-+ return p;
-+ case LAbin_ANDI:
-+ case LAbin_ORI:
-+ case LAbin_XORI:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_op_ui12_rj_rd(op, src2->LAri.I.imm,
-+ iregEnc(src1), iregEnc(dst));
-+ return p;
-+ default:
-+ return NULL;
++ DIP("vstelm.%s %s, %s, %d, %u\n", mkInsSize(insSz), nameVReg(vd), nameIReg(rj),
++ (Int)extend32(si8, 8), idx);
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LSX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
++
++ store(addr, binop(mkV128GetElem(insSz), getVReg(vd), mkU8(idx)));
++
++ return True;
+}
+
-+static UInt* mkLoad ( UInt* p, LOONGARCH64LoadOp op,
-+ LOONGARCH64AMode* src, HReg dst )
++static Bool gen_xvstelm ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (op) {
-+ case LAload_LD_W:
-+ case LAload_LD_D:
-+ case LAload_LD_BU:
-+ case LAload_LD_HU:
-+ case LAload_LD_WU:
-+ vassert(src->tag == LAam_RI);
-+ *p++ = emit_op_si12_rj_rd(op, src->LAam.RI.index,
-+ iregEnc(src->LAam.RI.base), iregEnc(dst));
-+ return p;
-+ case LAload_LDX_D:
-+ case LAload_LDX_BU:
-+ case LAload_LDX_HU:
-+ case LAload_LDX_WU:
-+ vassert(src->tag == LAam_RR);
-+ *p++ = emit_op_rk_rj_rd(op, iregEnc(src->LAam.RR.index),
-+ iregEnc(src->LAam.RR.base), iregEnc(dst));
-+ return p;
-+ default:
-+ return NULL;
++ UInt xd = SLICE(insn, 4, 0);
++ UInt rj = SLICE(insn, 9, 5);
++ UInt si8 = SLICE(insn, 17, 10);
++ UInt insImm = SLICE(insn, 23, 18);
++
++ IRExpr* addr;
++ UInt idx, insSz;
++ IRTemp res = newTemp(Ity_V128);
++ UInt half[4] = { 16, 8, 4, 2 };
++
++ if ((insImm & 0x20) == 0x20) { // 1_idx; b
++ idx = insImm & 0x1f;
++ insSz = 0;
++ } else if ((insImm & 0x30) == 0x10) { // 01_idx; h
++ idx = insImm & 0xf;
++ insSz = 1;
++ } else if ((insImm & 0x38) == 0x8) { // 001_idx; w
++ idx = insImm & 0x7;
++ insSz = 2;
++ } else if ((insImm & 0x3c) == 0x4) { // 0001_idx; d
++ idx = insImm & 0x3;
++ insSz = 3;
++ } else {
++ return False;
+ }
-+}
+
-+static UInt* mkStore ( UInt* p, LOONGARCH64StoreOp op,
-+ LOONGARCH64AMode* dst, HReg src )
-+{
-+ switch (op) {
-+ case LAstore_ST_B:
-+ case LAstore_ST_H:
-+ case LAstore_ST_W:
-+ case LAstore_ST_D:
-+ vassert(dst->tag == LAam_RI);
-+ *p++ = emit_op_si12_rj_rd(op, dst->LAam.RI.index,
-+ iregEnc(dst->LAam.RI.base), iregEnc(src));
-+ return p;
-+ case LAstore_STX_B:
-+ case LAstore_STX_H:
-+ case LAstore_STX_W:
-+ case LAstore_STX_D:
-+ vassert(dst->tag == LAam_RR);
-+ *p++ = emit_op_rk_rj_rd(op, iregEnc(dst->LAam.RR.index),
-+ iregEnc(dst->LAam.RR.base), iregEnc(src));
-+ return p;
-+ default:
-+ return NULL;
++ if (idx < half[insSz]) {
++ assign(res, unop(Iop_V256toV128_0, getXReg(xd)));
++ } else {
++ assign(res, unop(Iop_V256toV128_1, getXReg(xd)));
++ idx = idx - half[insSz];
+ }
-+}
+
-+static inline UInt* mkLLSC ( UInt* p, LOONGARCH64LLSCOp op,
-+ LOONGARCH64AMode* addr, HReg val )
-+{
-+ switch (op) {
-+ case LAllsc_LL_W:
-+ case LAllsc_SC_W:
-+ case LAllsc_LL_D:
-+ case LAllsc_SC_D:
-+ vassert(addr->tag == LAam_RI);
-+ *p++ = emit_op_si14_rj_rd(op, addr->LAam.RI.index,
-+ iregEnc(addr->LAam.RI.base), iregEnc(val));
-+ return p;
-+ default:
-+ return NULL;
++ switch (insSz) {
++ case 0b00:
++ addr = binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(si8, 8)));
++ break;
++ case 0b01:
++ addr = binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(si8 << 1, 9)));
++ break;
++ case 0b10:
++ addr = binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(si8 << 2, 10)));
++ break;
++ case 0b11:
++ addr = binop(Iop_Add64,
++ getIReg64(rj),
++ mkU64(extend64(si8 << 3, 11)));
++ break;
++ default: vassert(0);
+ }
-+}
+
-+static inline UInt* mkBar ( UInt* p, LOONGARCH64BarOp op, UShort hint )
-+{
-+ switch (op) {
-+ case LAbar_DBAR:
-+ case LAbar_IBAR:
-+ *p++ = emit_op_hint15(op, hint);
-+ return p;
-+ default:
-+ return NULL;
++ DIP("xvstelm.%s %s, %s, %d, %u\n", mkInsSize(insSz), nameXReg(xd), nameIReg(rj),
++ (Int)extend32(si8, 8), idx);
++
++ if (!(archinfo->hwcaps & VEX_HWCAPS_LOONGARCH_LASX)) {
++ dres->jk_StopHere = Ijk_SigILL;
++ dres->whatNext = Dis_StopHere;
++ return True;
+ }
++
++ store(addr, binop(mkV128GetElem(insSz), EX(res), mkU8(idx)));
++ return True;
+}
+
-+static inline UInt* mkFpUnary ( UInt* p, LOONGARCH64FpUnOp op, HReg src, HReg dst )
++
++/*------------------------------------------------------------*/
++/*--- Disassemble a single LOONGARCH64 instruction ---*/
++/*------------------------------------------------------------*/
++
++/* Disassemble a single LOONGARCH64 instruction into IR. The instruction
++ has is located at |guest_instr| and has guest IP of |guest_PC_curr_instr|,
++ which will have been set before the call here. Returns True iff the
++ instruction was decoded, in which case *dres will be set accordingly,
++ or False, in which case *dres should be ignored by the caller. */
++
++static Bool disInstr_LOONGARCH64_WRK_special ( DisResult* dres,
++ const UChar* guest_instr )
+{
-+ switch (op) {
-+ case LAfpun_FABS_S:
-+ case LAfpun_FABS_D:
-+ case LAfpun_FNEG_S:
-+ case LAfpun_FNEG_D:
-+ case LAfpun_FLOGB_S:
-+ case LAfpun_FLOGB_D:
-+ case LAfpun_FSQRT_S:
-+ case LAfpun_FSQRT_D:
-+ case LAfpun_FRSQRT_S:
-+ case LAfpun_FRSQRT_D:
-+ case LAfpun_FCVT_S_D:
-+ case LAfpun_FCVT_D_S:
-+ case LAfpun_FTINT_W_S:
-+ case LAfpun_FTINT_W_D:
-+ case LAfpun_FTINT_L_S:
-+ case LAfpun_FTINT_L_D:
-+ case LAfpun_FFINT_S_W:
-+ case LAfpun_FFINT_S_L:
-+ case LAfpun_FFINT_D_W:
-+ case LAfpun_FFINT_D_L:
-+ case LAfpun_FRINT_S:
-+ case LAfpun_FRINT_D:
-+ *p++ = emit_op_fj_fd(op, fregEnc(src), fregEnc(dst));
-+ return p;
-+ default:
-+ return NULL;
++ const UChar* code = guest_instr;
++ /* Spot the 16-byte preamble:
++ 00450c00 srli.d $zero, $zero, 3
++ 00453400 srli.d $zero, $zero, 13
++ 00457400 srli.d $zero, $zero, 29
++ 00454c00 srli.d $zero, $zero, 19
++ */
++ if (getUInt(code + 0) == 0x00450c00 &&
++ getUInt(code + 4) == 0x00453400 &&
++ getUInt(code + 8) == 0x00457400 &&
++ getUInt(code + 12) == 0x00454c00) {
++ /* Got a "Special" instruction preamble. Which one is it? */
++ if (getUInt(code + 16) == 0x001535ad) { /* or $t1, $t1, $t1 */
++ DIP("$a7 = client_request ( $t0 )\n");
++ putPC(mkU64(guest_PC_curr_instr + 20));
++ dres->whatNext = Dis_StopHere;
++ dres->len = 20;
++ dres->jk_StopHere = Ijk_ClientReq;
++ return True;
++ } else if (getUInt(code + 16) == 0x001539ce) { /* or $t2, $t2, $t2 */
++ DIP("$a7 = guest_NRADDR\n");
++ putIReg(11, IRExpr_Get(offsetof(VexGuestLOONGARCH64State, guest_NRADDR),
++ Ity_I64));
++ dres->len = 20;
++ return True;
++ } else if (getUInt(code + 16) == 0x00153def) { /* or $t3, $t3, $t3 */
++ DIP("branch-and-link-to-noredir $t8\n");
++ putIReg(1, mkU64(guest_PC_curr_instr + 20));
++ putPC(getIReg64(20));
++ dres->whatNext = Dis_StopHere;
++ dres->len = 20;
++ dres->jk_StopHere = Ijk_NoRedir;
++ return True;
++ } else if (getUInt(code + 16) == 0x00154210) { /* or $t4, $t4, $t4 */
++ DIP("IR injection\n");
++ vex_inject_ir(irsb, Iend_LE);
++ /* Invalidate the current insn. The reason is that the IRop we're
++ injecting here can change. In which case the translation has to
++ be redone. For ease of handling, we simply invalidate all the
++ time.
++ */
++ stmt(IRStmt_Put(offsetof(VexGuestLOONGARCH64State, guest_CMSTART),
++ mkU64(guest_PC_curr_instr)));
++ stmt(IRStmt_Put(offsetof(VexGuestLOONGARCH64State, guest_CMLEN),
++ mkU64(20)));
++ putPC(mkU64(guest_PC_curr_instr + 20));
++ dres->whatNext = Dis_StopHere;
++ dres->len = 20;
++ dres->jk_StopHere = Ijk_InvalICache;
++ return True;
++ }
++ /* We don't know what it is. */
++ vassert(0);
++ /*NOTREACHED*/
+ }
++ return False;
+}
+
-+static inline UInt* mkFpBinary ( UInt* p, LOONGARCH64FpBinOp op, HReg src2,
-+ HReg src1, HReg dst )
++static Bool disInstr_LOONGARCH64_WRK_00_0000_0000 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (op) {
-+ case LAfpbin_FADD_S:
-+ case LAfpbin_FADD_D:
-+ case LAfpbin_FSUB_S:
-+ case LAfpbin_FSUB_D:
-+ case LAfpbin_FMUL_S:
-+ case LAfpbin_FMUL_D:
-+ case LAfpbin_FDIV_S:
-+ case LAfpbin_FDIV_D:
-+ case LAfpbin_FMAX_S:
-+ case LAfpbin_FMAX_D:
-+ case LAfpbin_FMIN_S:
-+ case LAfpbin_FMIN_D:
-+ case LAfpbin_FMAXA_S:
-+ case LAfpbin_FMAXA_D:
-+ case LAfpbin_FMINA_S:
-+ case LAfpbin_FMINA_D:
-+ case LAfpbin_FSCALEB_S:
-+ case LAfpbin_FSCALEB_D:
-+ *p++ = emit_op_fk_fj_fd(op, fregEnc(src2), fregEnc(src1), fregEnc(dst));
-+ return p;
-+ default:
-+ return NULL;
-+ }
-+}
++ Bool ok;
+
-+static inline UInt* mkFpTrinary ( UInt* p, LOONGARCH64FpTriOp op, HReg src3,
-+ HReg src2, HReg src1, HReg dst )
-+{
-+ switch (op) {
-+ case LAfpbin_FMADD_S:
-+ case LAfpbin_FMADD_D:
-+ case LAfpbin_FMSUB_S:
-+ case LAfpbin_FMSUB_D:
-+ *p++ = emit_op_fa_fk_fj_fd(op, fregEnc(src3), fregEnc(src2),
-+ fregEnc(src1), fregEnc(dst));
-+ return p;
++ switch (SLICE(insn, 21, 15)) {
++ case 0b0000000:
++ switch (SLICE(insn, 14, 10)) {
++ case 0b00100:
++ ok = gen_clo_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b00101:
++ ok = gen_clz_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b00110:
++ ok = gen_cto_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b00111:
++ ok = gen_ctz_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01000:
++ ok = gen_clo_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01001:
++ ok = gen_clz_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01010:
++ ok = gen_cto_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01011:
++ ok = gen_ctz_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01100:
++ ok = gen_revb_2h(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01101:
++ ok = gen_revb_4h(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01110:
++ ok = gen_revb_2w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01111:
++ ok = gen_revb_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10000:
++ ok = gen_revh_2w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10001:
++ ok = gen_revh_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10010:
++ ok = gen_bitrev_4b(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10011:
++ ok = gen_bitrev_8b(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10100:
++ ok = gen_bitrev_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10101:
++ ok = gen_bitrev_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10110:
++ ok = gen_ext_w_h(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10111:
++ ok = gen_ext_w_b(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b11000:
++ ok = gen_rdtimel_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b11001:
++ ok = gen_rdtimeh_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b11010:
++ ok = gen_rdtime_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b11011:
++ ok = gen_cpucfg(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
++ case 0b0000010:
++ ok = gen_asrtle_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0000011:
++ ok = gen_asrtgt_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100000:
++ ok = gen_add_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100001:
++ ok = gen_add_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100010:
++ ok = gen_sub_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100011:
++ ok = gen_sub_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100100:
++ ok = gen_slt(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100101:
++ ok = gen_sltu(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100110:
++ ok = gen_maskeqz(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100111:
++ ok = gen_masknez(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101000:
++ ok = gen_nor(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101001:
++ ok = gen_and(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101010:
++ ok = gen_or(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101011:
++ ok = gen_xor(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101100:
++ ok = gen_orn(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101101:
++ ok = gen_andn(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101110:
++ ok = gen_sll_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101111:
++ ok = gen_srl_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0110000:
++ ok = gen_sra_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0110001:
++ ok = gen_sll_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0110010:
++ ok = gen_srl_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0110011:
++ ok = gen_sra_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0110110:
++ ok = gen_rotr_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0110111:
++ ok = gen_rotr_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0111000:
++ ok = gen_mul_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0111001:
++ ok = gen_mulh_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0111010:
++ ok = gen_mulh_wu(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0111011:
++ ok = gen_mul_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0111100:
++ ok = gen_mulh_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0111101:
++ ok = gen_mulh_du(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0111110:
++ ok = gen_mulw_d_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0111111:
++ ok = gen_mulw_d_wu(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1000000:
++ ok = gen_div_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1000001:
++ ok = gen_mod_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1000010:
++ ok = gen_div_wu(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1000011:
++ ok = gen_mod_wu(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1000100:
++ ok = gen_div_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1000101:
++ ok = gen_mod_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1000110:
++ ok = gen_div_du(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1000111:
++ ok = gen_mod_du(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1001000:
++ ok = gen_crc_w_b_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1001001:
++ ok = gen_crc_w_h_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1001010:
++ ok = gen_crc_w_w_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1001011:
++ ok = gen_crc_w_d_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1001100:
++ ok = gen_crcc_w_b_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1001101:
++ ok = gen_crcc_w_h_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1001110:
++ ok = gen_crcc_w_w_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1001111:
++ ok = gen_crcc_w_d_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1010100:
++ ok = gen_break(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1010110:
++ ok = gen_syscall(dres, insn, archinfo, abiinfo);
++ break;
+ default:
-+ return NULL;
++ ok = False;
++ break;
+ }
-+}
+
-+static inline UInt* mkFpLoad ( UInt* p, LOONGARCH64FpLoadOp op,
-+ LOONGARCH64AMode* src, HReg dst )
-+{
-+ switch (op) {
-+ case LAfpload_FLD_S:
-+ case LAfpload_FLD_D:
-+ vassert(src->tag == LAam_RI);
-+ *p++ = emit_op_si12_rj_rd(op, src->LAam.RI.index,
-+ iregEnc(src->LAam.RI.base), fregEnc(dst));
-+ return p;
-+ case LAfpload_FLDX_S:
-+ case LAfpload_FLDX_D:
-+ vassert(src->tag == LAam_RR);
-+ *p++ = emit_op_rk_rj_rd(op, iregEnc(src->LAam.RR.index),
-+ iregEnc(src->LAam.RR.base), fregEnc(dst));
-+ return p;
-+ default:
-+ return NULL;
-+ }
-+}
++ if (ok)
++ return ok;
+
-+static inline UInt* mkFpStore ( UInt* p, LOONGARCH64FpStoreOp op,
-+ LOONGARCH64AMode* dst, HReg src )
-+{
-+ switch (op) {
-+ case LAfpstore_FST_S:
-+ case LAfpstore_FST_D:
-+ vassert(dst->tag == LAam_RI);
-+ *p++ = emit_op_si12_rj_rd(op, dst->LAam.RI.index,
-+ iregEnc(dst->LAam.RI.base), fregEnc(src));
-+ return p;
-+ case LAfpstore_FSTX_S:
-+ case LAfpstore_FSTX_D:
-+ vassert(dst->tag == LAam_RR);
-+ *p++ = emit_op_rk_rj_rd(op, iregEnc(dst->LAam.RR.index),
-+ iregEnc(dst->LAam.RR.base), fregEnc(src));
-+ return p;
++ switch (SLICE(insn, 21, 18)) {
++ case 0b0001:
++ if (SLICE(insn, 17, 17) == 0) {
++ ok = gen_alsl_w(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = gen_alsl_wu(dres, insn, archinfo, abiinfo);
++ }
++ break;
++ case 0b0010:
++ if (SLICE(insn, 17, 17) == 0) {
++ ok = gen_bytepick_w(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = False;
++ }
++ break;
++ case 0b0011:
++ ok = gen_bytepick_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1011:
++ if (SLICE(insn, 17, 17) == 0) {
++ ok = gen_alsl_d(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = False;
++ }
++ break;
+ default:
-+ return NULL;
++ ok = False;
++ break;
+ }
++
++ return ok;
+}
+
-+static inline UInt* mkFpMove ( UInt* p, LOONGARCH64FpMoveOp op, HReg src, HReg dst )
++static Bool disInstr_LOONGARCH64_WRK_00_0000_0001 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (op) {
-+ case LAfpmove_FMOV_S:
-+ case LAfpmove_FMOV_D:
-+ *p++ = emit_op_fj_fd(op, fregEnc(src), fregEnc(dst));
-+ return p;
-+ case LAfpmove_MOVGR2FR_W:
-+ case LAfpmove_MOVGR2FR_D:
-+ *p++ = emit_op_rj_fd(op, iregEnc(src), fregEnc(dst));
-+ return p;
-+ case LAfpmove_MOVFR2GR_S:
-+ case LAfpmove_MOVFR2GR_D:
-+ *p++ = emit_op_fj_rd(op, fregEnc(src), iregEnc(dst));
-+ return p;
-+ case LAfpmove_MOVGR2FCSR:
-+ *p++ = emit_op_rj_fcsr(op, iregEnc(src), fcsrEnc(dst));
-+ return p;
-+ case LAfpmove_MOVFCSR2GR:
-+ *p++ = emit_op_fcsr_rd(op, fcsrEnc(src), iregEnc(dst));
-+ return p;
-+ default:
-+ return NULL;
++ Bool ok;
++
++ if (SLICE(insn, 21, 21) == 0) {
++ switch (SLICE(insn, 20, 16)) {
++ case 0b00000:
++ if (SLICE(insn, 15, 15) == 1) {
++ ok = gen_slli_w(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = False;
++ }
++ break;
++ case 0b00001:
++ ok = gen_slli_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b00100:
++ if (SLICE(insn, 15, 15) == 1) {
++ ok = gen_srli_w(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = False;
++ }
++ break;
++ case 0b00101:
++ ok = gen_srli_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01000:
++ if (SLICE(insn, 15, 15) == 1) {
++ ok = gen_srai_w(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = False;
++ }
++ break;
++ case 0b01001:
++ ok = gen_srai_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01100:
++ if (SLICE(insn, 15, 15) == 1) {
++ ok = gen_rotri_w(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = False;
++ }
++ break;
++ case 0b01101:
++ ok = gen_rotri_d(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ } else {
++ if (SLICE(insn, 15, 15) == 0) {
++ ok = gen_bstrins_w(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = gen_bstrpick_w(dres, insn, archinfo, abiinfo);
++ }
+ }
++
++ return ok;
+}
+
-+static inline UInt* mkFpCmp ( UInt* p, LOONGARCH64FpCmpOp op, HReg src2,
-+ HReg src1, HReg dst )
++static Bool disInstr_LOONGARCH64_WRK_00_0000_0100 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ /*
-+ fcmp.cond.[sd] $fcc0, src1, src2
-+ movcf2gr dst, $fcc0
-+ */
-+ switch (op) {
-+ case LAfpcmp_FCMP_CLT_S:
-+ case LAfpcmp_FCMP_CLT_D:
-+ case LAfpcmp_FCMP_CEQ_S:
-+ case LAfpcmp_FCMP_CEQ_D:
-+ case LAfpcmp_FCMP_CUN_S:
-+ case LAfpcmp_FCMP_CUN_D:
-+ *p++ = emit_op_fk_fj_cd(op, fregEnc(src2), fregEnc(src1), 0);
-+ *p++ = emit_op_cj_rd(LAextra_MOVCF2GR, 0, iregEnc(dst));
-+ return p;
++ Bool ok;
++
++ switch (SLICE(insn, 21, 15)) {
++ case 0b0000001:
++ ok = gen_fadd_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0000010:
++ ok = gen_fadd_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0000101:
++ ok = gen_fsub_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0000110:
++ ok = gen_fsub_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0001001:
++ ok = gen_fmul_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0001010:
++ ok = gen_fmul_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0001101:
++ ok = gen_fdiv_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0001110:
++ ok = gen_fdiv_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0010001:
++ ok = gen_fmax_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0010010:
++ ok = gen_fmax_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0010101:
++ ok = gen_fmin_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0010110:
++ ok = gen_fmin_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0011001:
++ ok = gen_fmaxa_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0011010:
++ ok = gen_fmaxa_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0011101:
++ ok = gen_fmina_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0011110:
++ ok = gen_fmina_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100001:
++ ok = gen_fscaleb_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100010:
++ ok = gen_fscaleb_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100101:
++ ok = gen_fcopysign_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100110:
++ ok = gen_fcopysign_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101000:
++ switch (SLICE(insn, 14, 10)) {
++ case 0b00001:
++ ok = gen_fabs_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b00010:
++ ok = gen_fabs_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b00101:
++ ok = gen_fneg_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b00110:
++ ok = gen_fneg_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01001:
++ ok = gen_flogb_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01010:
++ ok = gen_flogb_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01101:
++ ok = gen_fclass_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01110:
++ ok = gen_fclass_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10001:
++ ok = gen_fsqrt_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10010:
++ ok = gen_fsqrt_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10101:
++ ok = gen_frecip_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10110:
++ ok = gen_frecip_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b11001:
++ ok = gen_frsqrt_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b11010:
++ ok = gen_frsqrt_d(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
++ case 0b0101001:
++ switch (SLICE(insn, 14, 10)) {
++ case 0b00101:
++ ok = gen_fmov_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b00110:
++ ok = gen_fmov_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01001:
++ ok = gen_movgr2fr_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01010:
++ ok = gen_movgr2fr_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01011:
++ ok = gen_movgr2frh_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01101:
++ ok = gen_movfr2gr_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01110:
++ ok = gen_movfr2gr_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01111:
++ ok = gen_movfrh2gr_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10000:
++ ok = gen_movgr2fcsr(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10010:
++ ok = gen_movfcsr2gr(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10100:
++ if (SLICE(insn, 4, 3) == 0b00) {
++ ok = gen_movfr2cf(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = False;
++ }
++ break;
++ case 0b10101:
++ if (SLICE(insn, 9, 8) == 0b00) {
++ ok = gen_movcf2fr(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = False;
++ }
++ break;
++ case 0b10110:
++ if (SLICE(insn, 4, 3) == 0b00) {
++ ok = gen_movgr2cf(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = False;
++ }
++ break;
++ case 0b10111:
++ if (SLICE(insn, 9, 8) == 0b00) {
++ ok = gen_movcf2gr(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = False;
++ }
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
++ case 0b0110010:
++ switch (SLICE(insn, 14, 10)) {
++ case 0b00110:
++ ok = gen_fcvt_s_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01001:
++ ok = gen_fcvt_d_s(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
++ case 0b0110100:
++ switch (SLICE(insn, 14, 10)) {
++ case 0b00001:
++ ok = gen_ftintrm_w_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b00010:
++ ok = gen_ftintrm_w_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01001:
++ ok = gen_ftintrm_l_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01010:
++ ok = gen_ftintrm_l_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10001:
++ ok = gen_ftintrp_w_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10010:
++ ok = gen_ftintrp_w_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b11001:
++ ok = gen_ftintrp_l_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b11010:
++ ok = gen_ftintrp_l_d(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
++ case 0b0110101:
++ switch (SLICE(insn, 14, 10)) {
++ case 0b00001:
++ ok = gen_ftintrz_w_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b00010:
++ ok = gen_ftintrz_w_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01001:
++ ok = gen_ftintrz_l_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01010:
++ ok = gen_ftintrz_l_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10001:
++ ok = gen_ftintrne_w_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10010:
++ ok = gen_ftintrne_w_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b11001:
++ ok = gen_ftintrne_l_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b11010:
++ ok = gen_ftintrne_l_d(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
++ case 0b0110110:
++ switch (SLICE(insn, 14, 10)) {
++ case 0b00001:
++ ok = gen_ftint_w_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b00010:
++ ok = gen_ftint_w_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01001:
++ ok = gen_ftint_l_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01010:
++ ok = gen_ftint_l_d(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
++ case 0b0111010:
++ switch (SLICE(insn, 14, 10)) {
++ case 0b00100:
++ ok = gen_ffint_s_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b00110:
++ ok = gen_ffint_s_l(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01000:
++ ok = gen_ffint_d_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01010:
++ ok = gen_ffint_d_l(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
++ case 0b0111100:
++ switch (SLICE(insn, 14, 10)) {
++ case 0b10001:
++ ok = gen_frint_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10010:
++ ok = gen_frint_d(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
+ default:
-+ return NULL;
++ ok = False;
++ break;
+ }
++
++ return ok;
+}
+
-+static inline UInt* mkVecUnary ( UInt* p, LOONGARCH64VecUnOp op, HReg src, HReg dst )
++static Bool disInstr_LOONGARCH64_WRK_00_0000 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (op) {
-+ case LAvecun_VCLO_B:
-+ case LAvecun_VCLO_H:
-+ case LAvecun_VCLO_W:
-+ case LAvecun_VCLZ_B:
-+ case LAvecun_VCLZ_H:
-+ case LAvecun_VCLZ_W:
-+ case LAvecun_VCLZ_D:
-+ case LAvecun_VPCNT_B:
-+ case LAvecun_VEXTH_H_B:
-+ case LAvecun_VEXTH_W_H:
-+ case LAvecun_VEXTH_D_W:
-+ case LAvecun_VEXTH_Q_D:
-+ case LAvecun_VEXTH_HU_BU:
-+ case LAvecun_VEXTH_WU_HU:
-+ case LAvecun_VEXTH_DU_WU:
-+ case LAvecun_VEXTH_QU_DU:
-+ *p++ = emit_unop_r(op, vregEnc(src), vregEnc(dst), 5);
-+ return p;
-+ case LAvecun_VREPLGR2VR_B:
-+ case LAvecun_VREPLGR2VR_H:
-+ case LAvecun_VREPLGR2VR_W:
-+ case LAvecun_VREPLGR2VR_D:
-+ *p++ = emit_unop_r(op, iregEnc(src), vregEnc(dst), 5);
-+ return p;
++ Bool ok;
++
++ switch (SLICE(insn, 25, 22)) {
++ case 0b0000:
++ ok = disInstr_LOONGARCH64_WRK_00_0000_0000(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0001:
++ ok = disInstr_LOONGARCH64_WRK_00_0000_0001(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0010:
++ ok = gen_bstrins_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0011:
++ ok = gen_bstrpick_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100:
++ ok = disInstr_LOONGARCH64_WRK_00_0000_0100(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1000:
++ ok = gen_slti(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1001:
++ ok = gen_sltui(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1010:
++ ok = gen_addi_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1011:
++ ok = gen_addi_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1100:
++ ok = gen_lu52i_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101:
++ ok = gen_andi(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1110:
++ ok = gen_ori(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1111:
++ ok = gen_xori(dres, insn, archinfo, abiinfo);
++ break;
+ default:
-+ return NULL;
++ ok = False;
++ break;
+ }
++
++ return ok;
+}
+
-+static inline UInt* mkVecBinary ( UInt* p, LOONGARCH64VecBinOp op,
-+ LOONGARCH64RI* src2, HReg src1, HReg dst )
++static Bool disInstr_LOONGARCH64_WRK_00_1010 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ switch (op) {
-+ case LAvecbin_VSEQ_B:
-+ case LAvecbin_VSEQ_H:
-+ case LAvecbin_VSEQ_W:
-+ case LAvecbin_VSEQ_D:
-+ case LAvecbin_VSLT_B:
-+ case LAvecbin_VSLT_H:
-+ case LAvecbin_VSLT_W:
-+ case LAvecbin_VSLT_D:
-+ case LAvecbin_VSLT_BU:
-+ case LAvecbin_VSLT_HU:
-+ case LAvecbin_VSLT_WU:
-+ case LAvecbin_VSLT_DU:
-+ case LAvecbin_VADD_B:
-+ case LAvecbin_VADD_H:
-+ case LAvecbin_VADD_D:
-+ case LAvecbin_VADD_W:
-+ case LAvecbin_VSUB_B:
-+ case LAvecbin_VSUB_H:
-+ case LAvecbin_VSUB_W:
-+ case LAvecbin_VSUB_D:
-+ case LAvecbin_VSADD_B:
-+ case LAvecbin_VSADD_H:
-+ case LAvecbin_VSADD_W:
-+ case LAvecbin_VSADD_D:
-+ case LAvecbin_VSSUB_B:
-+ case LAvecbin_VSSUB_H:
-+ case LAvecbin_VSSUB_W:
-+ case LAvecbin_VSSUB_D:
-+ case LAvecbin_VSADD_BU:
-+ case LAvecbin_VSADD_HU:
-+ case LAvecbin_VSADD_WU:
-+ case LAvecbin_VSADD_DU:
-+ case LAvecbin_VSSUB_BU:
-+ case LAvecbin_VSSUB_HU:
-+ case LAvecbin_VSSUB_WU:
-+ case LAvecbin_VSSUB_DU:
-+ case LAvecbin_VADDA_B:
-+ case LAvecbin_VADDA_H:
-+ case LAvecbin_VADDA_W:
-+ case LAvecbin_VADDA_D:
-+ case LAvecbin_VAVGR_B:
-+ case LAvecbin_VAVGR_H:
-+ case LAvecbin_VAVGR_W:
-+ case LAvecbin_VAVGR_D:
-+ case LAvecbin_VAVGR_BU:
-+ case LAvecbin_VAVGR_HU:
-+ case LAvecbin_VAVGR_WU:
-+ case LAvecbin_VAVGR_DU:
-+ case LAvecbin_VMAX_B:
-+ case LAvecbin_VMAX_H:
-+ case LAvecbin_VMAX_W:
-+ case LAvecbin_VMAX_D:
-+ case LAvecbin_VMIN_B:
-+ case LAvecbin_VMIN_H:
-+ case LAvecbin_VMIN_W:
-+ case LAvecbin_VMIN_D:
-+ case LAvecbin_VMAX_BU:
-+ case LAvecbin_VMAX_HU:
-+ case LAvecbin_VMAX_WU:
-+ case LAvecbin_VMAX_DU:
-+ case LAvecbin_VMIN_BU:
-+ case LAvecbin_VMIN_HU:
-+ case LAvecbin_VMIN_WU:
-+ case LAvecbin_VMIN_DU:
-+ case LAvecbin_VMUL_B:
-+ case LAvecbin_VMUL_H:
-+ case LAvecbin_VMUL_W:
-+ case LAvecbin_VMUH_B:
-+ case LAvecbin_VMUH_H:
-+ case LAvecbin_VMUH_W:
-+ case LAvecbin_VMUH_BU:
-+ case LAvecbin_VMUH_HU:
-+ case LAvecbin_VMUH_WU:
-+ case LAvecbin_VSLL_B:
-+ case LAvecbin_VSLL_H:
-+ case LAvecbin_VSLL_W:
-+ case LAvecbin_VSLL_D:
-+ case LAvecbin_VSRL_B:
-+ case LAvecbin_VSRL_H:
-+ case LAvecbin_VSRL_W:
-+ case LAvecbin_VSRL_D:
-+ case LAvecbin_VSRA_B:
-+ case LAvecbin_VSRA_H:
-+ case LAvecbin_VSRA_W:
-+ case LAvecbin_VSRA_D:
-+ case LAvecbin_VILVL_B:
-+ case LAvecbin_VILVL_H:
-+ case LAvecbin_VILVL_W:
-+ case LAvecbin_VILVL_D:
-+ case LAvecbin_VILVH_B:
-+ case LAvecbin_VILVH_H:
-+ case LAvecbin_VILVH_W:
-+ case LAvecbin_VILVH_D:
-+ case LAvecbin_VPICKEV_B:
-+ case LAvecbin_VPICKEV_H:
-+ case LAvecbin_VPICKEV_W:
-+ case LAvecbin_VPICKOD_B:
-+ case LAvecbin_VPICKOD_H:
-+ case LAvecbin_VPICKOD_W:
-+ case LAvecbin_VAND_V:
-+ case LAvecbin_VOR_V:
-+ case LAvecbin_VXOR_V:
-+ case LAvecbin_VNOR_V:
-+ case LAvecbin_VADD_Q:
-+ case LAvecbin_VSUB_Q:
-+ case LAvecbin_VFADD_S:
-+ case LAvecbin_VFADD_D:
-+ case LAvecbin_VFSUB_S:
-+ case LAvecbin_VFSUB_D:
-+ case LAvecbin_VFMUL_S:
-+ case LAvecbin_VFMUL_D:
-+ case LAvecbin_VFDIV_S:
-+ case LAvecbin_VFDIV_D:
-+ case LAvecbin_VFMAX_S:
-+ case LAvecbin_VFMAX_D:
-+ case LAvecbin_VFMIN_S:
-+ case LAvecbin_VFMIN_D:
-+ vassert(src2->tag == LAri_Reg);
-+ *p++ = emit_binop_rr(op, vregEnc(src2->LAri.R.reg), vregEnc(src1), vregEnc(dst));
-+ return p;
-+ case LAvecbin_VREPLVE_B:
-+ case LAvecbin_VREPLVE_H:
-+ case LAvecbin_VREPLVE_W:
-+ case LAvecbin_VREPLVE_D:
-+ vassert(src2->tag == LAri_Reg);
-+ *p++ = emit_binop_rr(op, iregEnc(src2->LAri.R.reg), vregEnc(src1), vregEnc(dst));
-+ return p;
-+ case LAvecbin_VINSGR2VR_D:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 1, iregEnc(src1), vregEnc(dst));
-+ return p;
-+ case LAvecbin_VPICKVE2GR_D:
-+ case LAvecbin_VPICKVE2GR_DU:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 1, vregEnc(src1), iregEnc(dst));
-+ return p;
-+ case LAvecbin_VINSGR2VR_W:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 2, iregEnc(src1), vregEnc(dst));
-+ return p;
-+ case LAvecbin_VPICKVE2GR_W:
-+ case LAvecbin_VPICKVE2GR_WU:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 2, vregEnc(src1), iregEnc(dst));
-+ return p;
-+ case LAvecbin_VSLLI_B:
-+ case LAvecbin_VSRLI_B:
-+ case LAvecbin_VSRAI_B:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 3, vregEnc(src1), vregEnc(dst));
-+ return p;
-+ case LAvecbin_VINSGR2VR_H:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 3, iregEnc(src1), vregEnc(dst));
-+ return p;
-+ case LAvecbin_VPICKVE2GR_HU:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 3, vregEnc(src1), iregEnc(dst));
-+ return p;
-+ case LAvecbin_VSLLI_H:
-+ case LAvecbin_VSRLI_H:
-+ case LAvecbin_VSRAI_H:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 4, vregEnc(src1), vregEnc(dst));
-+ return p;
-+ case LAvecbin_VINSGR2VR_B:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 4, iregEnc(src1), vregEnc(dst));
-+ return p;
-+ case LAvecbin_VPICKVE2GR_BU:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 4, vregEnc(src1), iregEnc(dst));
-+ return p;
-+ case LAvecbin_VBSLL_V:
-+ case LAvecbin_VBSRL_V:
-+ case LAvecbin_VSLLI_W:
-+ case LAvecbin_VSRLI_W:
-+ case LAvecbin_VSRAI_W:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 5, vregEnc(src1), vregEnc(dst));
-+ return p;
-+ case LAvecbin_VSLLI_D:
-+ case LAvecbin_VSRLI_D:
-+ case LAvecbin_VSRAI_D:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 6, vregEnc(src1), vregEnc(dst));
-+ return p;
-+ case LAvecbin_VORI_B:
-+ vassert(src2->tag == LAri_Imm);
-+ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 8, vregEnc(src1), vregEnc(dst));
-+ return p;
-+ default:
-+ return NULL;
-+ }
-+}
-+
-+static inline UInt* mkVecLoad ( UInt* p, LOONGARCH64VecLoadOp op,
-+ LOONGARCH64AMode* src, HReg dst )
-+{
-+ switch (op) {
-+ case LAvecload_VLD:
-+ vassert(src->tag == LAam_RI);
-+ *p++ = emit_op_si12_rj_vd(op, src->LAam.RI.index,
-+ iregEnc(src->LAam.RI.base), vregEnc(dst));
-+ return p;
-+ case LAvecload_VLDX:
-+ vassert(src->tag == LAam_RR);
-+ *p++ = emit_op_rk_rj_rd(op, iregEnc(src->LAam.RR.index),
-+ iregEnc(src->LAam.RR.base), vregEnc(dst));
-+ return p;
-+ default:
-+ return NULL;
-+ }
-+}
++ Bool ok;
+
-+static inline UInt* mkVecStore ( UInt* p, LOONGARCH64VecStoreOp op,
-+ LOONGARCH64AMode* dst, HReg src )
-+{
-+ switch (op) {
-+ case LAvecstore_VST:
-+ vassert(dst->tag == LAam_RI);
-+ *p++ = emit_op_si12_rj_vd(op, dst->LAam.RI.index,
-+ iregEnc(dst->LAam.RI.base), vregEnc(src));
-+ return p;
-+ case LAvecstore_VSTX:
-+ vassert(dst->tag == LAam_RR);
-+ *p++ = emit_op_rk_rj_vd(op, iregEnc(dst->LAam.RR.index),
-+ iregEnc(dst->LAam.RR.base), vregEnc(src));
-+ return p;
++ switch (SLICE(insn, 25, 22)) {
++ case 0b0000:
++ ok = gen_ld_b(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0001:
++ ok = gen_ld_h(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0010:
++ ok = gen_ld_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0011:
++ ok = gen_ld_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100:
++ ok = gen_st_b(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101:
++ ok = gen_st_h(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0110:
++ ok = gen_st_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0111:
++ ok = gen_st_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1000:
++ ok = gen_ld_bu(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1001:
++ ok = gen_ld_hu(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1010:
++ ok = gen_ld_wu(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1011:
++ ok = gen_preld(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1100:
++ ok = gen_fld_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101:
++ ok = gen_fst_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1110:
++ ok = gen_fld_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1111:
++ ok = gen_fst_d(dres, insn, archinfo, abiinfo);
++ break;
+ default:
-+ return NULL;
++ ok = False;
++ break;
+ }
-+}
-+
-+static inline UInt* mkCas ( UInt* p, HReg old, HReg addr, HReg expd,
-+ HReg data, Bool size64 )
-+{
-+ /*
-+ ll.[wd] old, addr, 0
-+ bne old, expd, barrier
-+ or $t0, data, $zero
-+ sc.[wd] $t0, addr, 0
-+ beq $t0, zero, fail
-+ or old, expd, $zero
-+ b end
-+ barrier:
-+ dbar 0
-+ fail:
-+ or old, data, $zero
-+ end:
-+ */
-+ UInt o = iregEnc(old);
-+ UInt a = iregEnc(addr);
-+ UInt e = iregEnc(expd);
-+ UInt d = iregEnc(data);
-+ UInt t = 12;
-+ UInt z = 0;
+
-+ if (size64) {
-+ *p++ = emit_op_si14_rj_rd(LAllsc_LL_D, 0, a, o);
-+ } else {
-+ *p++ = emit_op_ui6_rj_rd(LAbin_SLLI_W, 0, e, e); // Sign-extend expd
-+ *p++ = emit_op_si14_rj_rd(LAllsc_LL_W, 0, a, o);
-+ }
-+ *p++ = emit_op_offs16_rj_rd(LAextra_BNE, 6, o, e);
-+ *p++ = emit_op_rk_rj_rd(LAbin_OR, z, d, t);
-+ if (size64) {
-+ *p++ = emit_op_si14_rj_rd(LAllsc_SC_D, 0, a, t);
-+ } else {
-+ *p++ = emit_op_si14_rj_rd(LAllsc_SC_W, 0, a, t);
-+ }
-+ *p++ = emit_op_offs16_rj_rd(LAextra_BEQ, 4, t, z);
-+ *p++ = emit_op_rk_rj_rd(LAbin_OR, z, e, o);
-+ *p++ = emit_op_offs26(LAextra_B, 3);
-+ *p++ = emit_op_hint15(LAbar_DBAR, 0);
-+ *p++ = emit_op_rk_rj_rd(LAbin_OR, z, d, o);
-+ return p;
++ return ok;
+}
+
-+static inline UInt* mkCmp ( UInt* p, LOONGARCH64CondCode cond,
-+ HReg src2, HReg src1, HReg dst )
++static Bool disInstr_LOONGARCH64_WRK_00_1011 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ UInt d = iregEnc(dst);
-+ UInt s1 = iregEnc(src1);
-+ UInt s2 = iregEnc(src2);
++ Bool ok;
+
-+ switch (cond) {
-+ case LAcc_EQ:
-+ /*
-+ xor dst, src1, src2
-+ sltui dst, dst, 1
-+ */
-+ *p++ = emit_op_rk_rj_rd(LAbin_XOR, s2, s1, d);
-+ *p++ = emit_op_si12_rj_rd(LAextra_SLTUI, 1, d, d);
-+ return p;
-+ case LAcc_NE:
-+ /*
-+ xor dst, src1, src2
-+ sltu dst, $zero, dst
-+ */
-+ *p++ = emit_op_rk_rj_rd(LAbin_XOR, s2, s1, d);
-+ *p++ = emit_op_rk_rj_rd(LAextra_SLTU, d, 0, d);
-+ return p;
-+ case LAcc_LT:
-+ /* slt dst, src1, src2 */
-+ *p++ = emit_op_rk_rj_rd(LAextra_SLT, s2, s1, d);
-+ return p;
-+ case LAcc_GE:
-+ /*
-+ slt dst, src1, src2
-+ sltui dst, dst, 1
-+ */
-+ *p++ = emit_op_rk_rj_rd(LAextra_SLT, s2, s1, d);
-+ *p++ = emit_op_si12_rj_rd(LAextra_SLTUI, 1, d, d);
-+ return p;
-+ case LAcc_LTU:
-+ /* sltu dst, src1, src2 */
-+ *p++ = emit_op_rk_rj_rd(LAextra_SLTU, s2, s1, d);
-+ return p;
-+ case LAcc_GEU:
-+ /*
-+ sltu dst, src1, src2
-+ sltui dst, dst, 1
-+ */
-+ *p++ = emit_op_rk_rj_rd(LAextra_SLTU, s2, s1, d);
-+ *p++ = emit_op_si12_rj_rd(LAextra_SLTUI, 1, d, d);
-+ return p;
-+ /* No LAcc_AL here.
-+ case LAcc_AL:
-+ break;
-+ */
++ switch (SLICE(insn, 23, 22)) {
++ case 0b00:
++ ok = gen_vld(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01:
++ ok = gen_vst(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10:
++ ok = gen_xvld(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b11:
++ ok = gen_xvst(dres, insn, archinfo, abiinfo);
++ break;
+ default:
-+ return NULL;
-+ }
-+}
-+
-+static inline UInt* mkCMove ( UInt* p, HReg cond, HReg r0,
-+ HReg r1, HReg dst, Bool isInt )
-+{
-+ if (isInt) {
-+ /*
-+ masknez $t0, r0, cond
-+ maskeqz dst, r1, cond
-+ or dst, $t0, dst
-+ */
-+ UInt c = iregEnc(cond);
-+ UInt d = iregEnc(dst);
-+ *p++ = emit_op_rk_rj_rd(LAextra_MASKNEZ, c, iregEnc(r0), 12);
-+ *p++ = emit_op_rk_rj_rd(LAextra_MASKEQZ, c, iregEnc(r1), d);
-+ *p++ = emit_op_rk_rj_rd(LAbin_OR, d, 12, d);
-+ } else {
-+ /*
-+ movgr2cf $fcc0, cond
-+ fsel dst, r0, r1, $fcc0
-+ */
-+ *p++ = emit_op_rj_cd(LAextra_MOVGR2CF, iregEnc(cond), 0);
-+ *p++ = emit_op_ca_fk_fj_fd(LAextra_FSEL, 0, fregEnc(r1),
-+ fregEnc(r0), fregEnc(dst));
-+ }
-+ return p;
-+}
-+
-+static inline UInt* mkCall ( UInt* p, HReg cond, Addr64 target, RetLoc rloc )
-+{
-+ if (!hregIsInvalid(cond) && rloc.pri != RLPri_None) {
-+ /* The call might not happen (it isn't unconditional) and
-+ it returns a result. In this case we will need to
-+ generate a control flow diamond to put 0x555..555 in
-+ the return register(s) in the case where the call
-+ doesn't happen. If this ever becomes necessary, maybe
-+ copy code from the 32-bit ARM equivalent. Until that
-+ day, just give up. */
-+ return NULL;
-+ }
-+
-+ UInt* ptmp = NULL;
-+ if (!hregIsInvalid(cond)) {
-+ /* Create a hole to put a conditional branch in. We'll
-+ patch it once we know the branch length. */
-+ ptmp = p;
-+ p++;
-+ }
-+
-+ /*
-+ $t0 = target
-+ jirl $ra, $t0, 0
-+ */
-+ p = mkLoadImm(p, hregT0(), target);
-+ *p++ = emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1);
-+
-+ /* Patch the hole if necessary */
-+ if (!hregIsInvalid(cond)) {
-+ vassert(ptmp != NULL);
-+ UInt offs = (UInt)(p - ptmp);
-+ vassert(offs >= 3 && offs <= 6);
-+ /* beq cond, $zero, offs */
-+ *ptmp++ = emit_op_offs16_rj_rd(LAextra_BEQ, offs, iregEnc(cond), 0);
-+ }
-+
-+ return p;
-+}
-+
-+static inline UInt* mkXDirect ( UInt* p, Addr64 dstGA,
-+ LOONGARCH64AMode* amPC,
-+ HReg cond, Bool toFastEP,
-+ const void* disp_cp_chain_me_to_slowEP,
-+ const void* disp_cp_chain_me_to_fastEP )
-+{
-+ /* NB: what goes on here has to be very closely coordinated
-+ with chainXDirect_LOONGARCH64 and unchainXDirect_LOONGARCH64 below. */
-+ /* We're generating chain-me requests here, so we need to be
-+ sure this is actually allowed -- no-redir translations
-+ can't use chain-me's. Hence: */
-+ vassert(disp_cp_chain_me_to_slowEP != NULL);
-+ vassert(disp_cp_chain_me_to_fastEP != NULL);
-+
-+ /* Use ptmp for backpatching conditional jumps. */
-+ UInt* ptmp = NULL;
-+
-+ /* First off, if this is conditional, create a conditional
-+ jump over the rest of it. Or at least, leave a space for
-+ it that we will shortly fill in. */
-+ if (!hregIsInvalid(cond)) {
-+ ptmp = p;
-+ p++;
-+ }
-+
-+ /* Update the guest PC.
-+ $t0 = dstGA
-+ st.d $t0, amPC
-+ */
-+ p = mkLoadImm(p, hregT0(), (ULong)dstGA);
-+ p = mkStore(p, LAstore_ST_D, amPC, hregT0());
-+
-+ /* --- FIRST PATCHABLE BYTE follows --- */
-+ /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're
-+ calling to) backs up the return address, so as to find the
-+ address of the first patchable byte. So: don't change the
-+ number of instructions (5) below. */
-+ /*
-+ la $t0, VG_(disp_cp_chain_me_to_{slowEP,fastEP})
-+ jirl $ra, $t0, 0
-+ */
-+ const void* disp_cp_chain_me = toFastEP ? disp_cp_chain_me_to_fastEP
-+ : disp_cp_chain_me_to_slowEP;
-+ p = mkLoadImm_EXACTLY4(p, hregT0(), (ULong)(Addr)disp_cp_chain_me);
-+ *p++ = emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1);
-+ /* --- END of PATCHABLE BYTES --- */
-+
-+ /* Fix up the conditional jump, if there was one. */
-+ if (!hregIsInvalid(cond)) {
-+ vassert(ptmp != NULL);
-+ UInt offs = (UInt)(p - ptmp);
-+ vassert(offs >= 8 && offs <= 11);
-+ /* beq cond, $zero, offs */
-+ *ptmp++ = emit_op_offs16_rj_rd(LAextra_BEQ, offs, iregEnc(cond), 0);
++ ok = False;
++ break;
+ }
+
-+ return p;
++ return ok;
+}
+
-+static inline UInt* mkXIndir ( UInt* p, HReg dstGA, LOONGARCH64AMode* amPC,
-+ HReg cond, const void* disp_cp_xindir )
++static Bool disInstr_LOONGARCH64_WRK_00_1100 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ /* We're generating transfers that could lead indirectly to a
-+ chain-me, so we need to be sure this is actually allowed --
-+ no-redir translations are not allowed to reach normal
-+ translations without going through the scheduler. That means
-+ no XDirects or XIndirs out from no-redir translations.
-+ Hence: */
-+ vassert(disp_cp_xindir != NULL);
-+
-+ /* Use ptmp for backpatching conditional jumps. */
-+ UInt* ptmp = NULL;
-+
-+ /* First off, if this is conditional, create a conditional
-+ jump over the rest of it. */
-+ if (!hregIsInvalid(cond)) {
-+ ptmp = p;
-+ p++;
-+ }
-+
-+ /* Update the guest PC.
-+ or $t0, dstGA, $zero
-+ st.d $t0, amPC
-+ */
-+ *p++ = emit_op_rk_rj_rd(LAbin_OR, 0, iregEnc(dstGA), 12);
-+ p = mkStore(p, LAstore_ST_D, amPC, hregT0());
-+
-+ /*
-+ la $t0, VG_(disp_cp_xindir)
-+ jirl $ra, $t0, 0
-+ */
-+ p = mkLoadImm(p, hregT0(), (ULong)(Addr)disp_cp_xindir);
-+ *p++ = emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1);
++ Bool ok;
+
-+ /* Fix up the conditional jump, if there was one. */
-+ if (!hregIsInvalid(cond)) {
-+ vassert(ptmp != NULL);
-+ UInt offs = (UInt)(p - ptmp);
-+ vassert(offs >= 5 && offs <= 8);
-+ /* beq cond, $zero, offs */
-+ *ptmp++ = emit_op_offs16_rj_rd(LAextra_BEQ, offs, iregEnc(cond), 0);
++ switch (SLICE(insn, 25, 24)) {
++ case 0b00:
++ ok = gen_vldrepl(dres, insn, archinfo, abiinfo); break;
++ case 0b01:
++ ok = gen_vstelm(dres, insn, archinfo, abiinfo); break;
++ case 0b10:
++ ok = gen_xvldrepl(dres, insn, archinfo, abiinfo); break;
++ case 0b11:
++ ok = gen_xvstelm(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
+ }
+
-+ return p;
++ return ok;
+}
+
-+static inline UInt* mkXAssisted ( UInt* p, HReg dstGA, LOONGARCH64AMode* amPC,
-+ HReg cond, IRJumpKind jk,
-+ const void* disp_cp_xassisted )
++static Bool disInstr_LOONGARCH64_WRK_00_1110_0000 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ /* First off, if this is conditional, create a conditional jump
-+ over the rest of it. Or at least, leave a space for it that
-+ we will shortly fill in. */
-+ UInt* ptmp = NULL;
-+ if (!hregIsInvalid(cond)) {
-+ ptmp = p;
-+ p++;
-+ }
-+
-+ /* Update the guest PC.
-+ or $t0, dstGA, $zero
-+ st.d $t0, amPC
-+ */
-+ *p++ = emit_op_rk_rj_rd(LAbin_OR, 0, iregEnc(dstGA), 12);
-+ p = mkStore(p, LAstore_ST_D, amPC, hregT0());
++ Bool ok;
+
-+ /* li.w $s8, magic_number */
-+ UInt trcval = 0;
-+ switch (jk) {
-+ case Ijk_Boring:
-+ trcval = VEX_TRC_JMP_BORING;
-+ break;
-+ case Ijk_ClientReq:
-+ trcval = VEX_TRC_JMP_CLIENTREQ;
++ switch (SLICE(insn, 21, 15)) {
++ case 0b0000000:
++ ok = gen_ldx_b(dres, insn, archinfo, abiinfo);
+ break;
-+ case Ijk_NoDecode:
-+ trcval = VEX_TRC_JMP_NODECODE;
++ case 0b0001000:
++ ok = gen_ldx_h(dres, insn, archinfo, abiinfo);
+ break;
-+ case Ijk_InvalICache:
-+ trcval = VEX_TRC_JMP_INVALICACHE;
++ case 0b0010000:
++ ok = gen_ldx_w(dres, insn, archinfo, abiinfo);
+ break;
-+ case Ijk_NoRedir:
-+ trcval = VEX_TRC_JMP_NOREDIR;
++ case 0b0011000:
++ ok = gen_ldx_d(dres, insn, archinfo, abiinfo);
+ break;
-+ case Ijk_SigTRAP:
-+ trcval = VEX_TRC_JMP_SIGTRAP;
++ case 0b0100000:
++ ok = gen_stx_b(dres, insn, archinfo, abiinfo);
+ break;
-+ case Ijk_SigSEGV:
-+ trcval = VEX_TRC_JMP_SIGSEGV;
++ case 0b0101000:
++ ok = gen_stx_h(dres, insn, archinfo, abiinfo);
+ break;
-+ case Ijk_SigBUS:
-+ trcval = VEX_TRC_JMP_SIGBUS;
++ case 0b0110000:
++ ok = gen_stx_w(dres, insn, archinfo, abiinfo);
+ break;
-+ case Ijk_SigFPE_IntDiv:
-+ trcval = VEX_TRC_JMP_SIGFPE_INTDIV;
++ case 0b0111000:
++ ok = gen_stx_d(dres, insn, archinfo, abiinfo);
+ break;
-+ case Ijk_SigFPE_IntOvf:
-+ trcval = VEX_TRC_JMP_SIGFPE_INTOVF;
++ case 0b1000000:
++ ok = gen_ldx_bu(dres, insn, archinfo, abiinfo);
+ break;
-+ case Ijk_SigSYS:
-+ trcval = VEX_TRC_JMP_SIGSYS;
++ case 0b1001000:
++ ok = gen_ldx_hu(dres, insn, archinfo, abiinfo);
+ break;
-+ case Ijk_Sys_syscall:
-+ trcval = VEX_TRC_JMP_SYS_SYSCALL;
++ case 0b1010000:
++ ok = gen_ldx_wu(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1011000:
++ ok = gen_preldx(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1100000:
++ ok = gen_fldx_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101000:
++ ok = gen_fldx_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1110000:
++ ok = gen_fstx_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1111000:
++ ok = gen_fstx_d(dres, insn, archinfo, abiinfo);
+ break;
-+ /* We don't expect to see the following being assisted.
-+ case Ijk_Call:
-+ case Ijk_Ret:
-+ case Ijk_Yield:
-+ case Ijk_EmWarn:
-+ case Ijk_EmFail:
-+ case Ijk_MapFail:
-+ case Ijk_FlushDCache:
-+ case Ijk_SigILL:
-+ case Ijk_SigFPE:
-+ case Ijk_Sys_int32:
-+ case Ijk_Sys_int128:
-+ case Ijk_Sys_int129:
-+ case Ijk_Sys_int130:
-+ case Ijk_Sys_int145:
-+ case Ijk_Sys_int210:
-+ case Ijk_Sys_sysenter:
-+ */
+ default:
-+ ppIRJumpKind(jk);
-+ vpanic("emit_LOONGARCH64Instr.LAin_XAssisted: unexpected jump kind");
-+ }
-+ vassert(trcval != 0);
-+ p = mkLoadImm(p, hregGSP(), trcval);
-+
-+ /*
-+ la $t0, VG_(disp_cp_xassisted)
-+ jirl $ra, $t0, 0
-+ */
-+ p = mkLoadImm(p, hregT0(), (ULong)(Addr)disp_cp_xassisted);
-+ *p++ = emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1);
-+
-+ /* Fix up the conditional jump, if there was one. */
-+ if (!hregIsInvalid(cond)) {
-+ vassert(ptmp != NULL);
-+ UInt offs = (UInt)(p - ptmp);
-+ vassert(offs >= 6 && offs <= 12);
-+ /* beq cond, $zero, offs */
-+ *ptmp++ = emit_op_offs16_rj_rd(LAextra_BEQ, offs, iregEnc(cond), 0);
++ ok = False;
++ break;
+ }
+
-+ return p;
-+}
-+
-+static inline UInt* mkEvCheck ( UInt* p, LOONGARCH64AMode* amCounter,
-+ LOONGARCH64AMode* amFailAddr )
-+{
-+ UInt* p0 = p;
-+
-+ /*
-+ ld.w $t0, amCounter
-+ addi.d $t0, $t0, -1
-+ st.w $t0, amCounter
-+ bge $t0, $zero, nofail
-+ ld.d $t0, amFailAddr
-+ jirl $ra, $t0, 0
-+ nofail:
-+ */
-+ p = mkLoad(p, LAload_LD_W, amCounter, hregT0());
-+ *p++ = emit_op_si12_rj_rd(LAbin_ADDI_D, -1 & 0xfff, 12, 12);
-+ p = mkStore(p, LAstore_ST_W, amCounter, hregT0());
-+ *p++ = emit_op_offs16_rj_rd(LAextra_BGE, 3, 12, 0);
-+ p = mkLoad(p, LAload_LD_W, amFailAddr, hregT0());
-+ *p++ = emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1);
-+
-+ /* Crosscheck */
-+ vassert(evCheckSzB_LOONGARCH64() == (UChar*)p - (UChar*)p0);
-+ return p;
-+}
-+
-+static inline UInt* mkProfInc ( UInt* p )
-+{
-+ /*
-+ li $t0, 0x6555755585559555UL
-+ ld.d $t1, $t0, 0
-+ addi.d $t1, $t1, 1
-+ st.d $t1, $t0, 0
-+ */
-+ p = mkLoadImm_EXACTLY4(p, hregT0(), 0x6555755585559555UL);
-+ *p++ = emit_op_si12_rj_rd(LAload_LD_D, 0, 12, 13);
-+ *p++ = emit_op_si12_rj_rd(LAbin_ADDI_D, 1, 13, 13);
-+ *p++ = emit_op_si12_rj_rd(LAstore_ST_D, 0, 12, 13);
-+ return p;
++ return ok;
+}
+
-+/* Emit an instruction into buf and return the number of bytes used.
-+ Note that buf is not the insn's final place, and therefore it is
-+ imperative to emit position-independent code. If the emitted
-+ instruction was a profiler inc, set *is_profInc to True, else
-+ leave it unchanged. */
-+Int emit_LOONGARCH64Instr ( /*MB_MOD*/Bool* is_profInc,
-+ UChar* buf,
-+ Int nbuf,
-+ const LOONGARCH64Instr* i,
-+ Bool mode64,
-+ VexEndness endness_host,
-+ const void* disp_cp_chain_me_to_slowEP,
-+ const void* disp_cp_chain_me_to_fastEP,
-+ const void* disp_cp_xindir,
-+ const void* disp_cp_xassisted )
++static Bool disInstr_LOONGARCH64_WRK_00_1110_0001 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(mode64 == True);
-+
-+ UInt* p = (UInt*)buf;
-+ vassert(nbuf >= 32);
-+ vassert((((HWord)buf) & 3) == 0);
++ Bool ok;
+
-+ switch (i->tag) {
-+ case LAin_LI:
-+ p = mkLoadImm(p, i->LAin.LI.dst, i->LAin.LI.imm);
++ switch (SLICE(insn, 21, 15)) {
++ case 0b0000000: ok = gen_vldx(dres, insn, archinfo, abiinfo); break;
++ case 0b0001000: ok = gen_vstx(dres, insn, archinfo, abiinfo); break;
++ case 0b0010000: ok = gen_xvldx(dres, insn, archinfo, abiinfo); break;
++ case 0b0011000: ok = gen_xvstx(dres, insn, archinfo, abiinfo); break;
++ case 0b1000000:
++ ok = gen_amswap_w(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_Un:
-+ p = mkUnary(p, i->LAin.Unary.op, i->LAin.Unary.src,
-+ i->LAin.Unary.dst);
++ case 0b1000001:
++ ok = gen_amswap_d(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_Bin:
-+ p = mkBinary(p, i->LAin.Binary.op, i->LAin.Binary.src2,
-+ i->LAin.Binary.src1, i->LAin.Binary.dst);
++ case 0b1000010:
++ ok = gen_amadd_w(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_Load:
-+ p = mkLoad(p, i->LAin.Load.op, i->LAin.Load.src,
-+ i->LAin.Load.dst);
++ case 0b1000011:
++ ok = gen_amadd_d(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_Store:
-+ p = mkStore(p, i->LAin.Store.op, i->LAin.Store.dst,
-+ i->LAin.Store.src);
++ case 0b1000100:
++ ok = gen_amand_w(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_LLSC:
-+ p = mkLLSC(p, i->LAin.LLSC.op, i->LAin.LLSC.addr, i->LAin.LLSC.val);
++ case 0b1000101:
++ ok = gen_amand_d(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_Bar:
-+ p = mkBar(p, i->LAin.Bar.op, i->LAin.Bar.hint);
++ case 0b1000110:
++ ok = gen_amor_w(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_FpUn:
-+ p = mkFpUnary(p, i->LAin.FpUnary.op, i->LAin.FpUnary.src,
-+ i->LAin.FpUnary.dst);
++ case 0b1000111:
++ ok = gen_amor_d(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_FpBin:
-+ p = mkFpBinary(p, i->LAin.FpBinary.op, i->LAin.FpBinary.src2,
-+ i->LAin.FpBinary.src1, i->LAin.FpBinary.dst);
++ case 0b1001000:
++ ok = gen_amxor_w(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_FpTri:
-+ p = mkFpTrinary(p, i->LAin.FpTrinary.op, i->LAin.FpTrinary.src3,
-+ i->LAin.FpTrinary.src2, i->LAin.FpTrinary.src1,
-+ i->LAin.FpTrinary.dst);
++ case 0b1001001:
++ ok = gen_amxor_d(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_FpLoad:
-+ p = mkFpLoad(p, i->LAin.FpLoad.op, i->LAin.FpLoad.src,
-+ i->LAin.FpLoad.dst);
++ case 0b1001010:
++ ok = gen_ammax_w(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_FpStore:
-+ p = mkFpStore(p, i->LAin.FpStore.op, i->LAin.FpStore.dst,
-+ i->LAin.FpStore.src);
++ case 0b1001011:
++ ok = gen_ammax_d(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_FpMove:
-+ p = mkFpMove(p, i->LAin.FpMove.op, i->LAin.FpMove.src,
-+ i->LAin.FpMove.dst);
++ case 0b1001100:
++ ok = gen_ammin_w(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_FpCmp:
-+ p = mkFpCmp(p, i->LAin.FpCmp.op, i->LAin.FpCmp.src2,
-+ i->LAin.FpCmp.src1, i->LAin.FpCmp.dst);
++ case 0b1001101:
++ ok = gen_ammin_d(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_VecUn:
-+ p = mkVecUnary(p, i->LAin.VecUnary.op, i->LAin.VecUnary.src,
-+ i->LAin.VecUnary.dst);
++ case 0b1001110:
++ ok = gen_ammax_wu(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_VecBin:
-+ p = mkVecBinary(p, i->LAin.VecBinary.op, i->LAin.VecBinary.src2,
-+ i->LAin.VecBinary.src1, i->LAin.VecBinary.dst);
++ case 0b1001111:
++ ok = gen_ammax_du(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_VecLoad:
-+ p = mkVecLoad(p, i->LAin.VecLoad.op, i->LAin.VecLoad.src,
-+ i->LAin.VecLoad.dst);
++ case 0b1010000:
++ ok = gen_ammin_wu(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_VecStore:
-+ p = mkVecStore(p, i->LAin.VecStore.op, i->LAin.VecStore.dst,
-+ i->LAin.VecStore.src);
++ case 0b1010001:
++ ok = gen_ammin_du(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_Cas:
-+ p = mkCas(p, i->LAin.Cas.old, i->LAin.Cas.addr, i->LAin.Cas.expd,
-+ i->LAin.Cas.data, i->LAin.Cas.size64);
++ case 0b1010010:
++ ok = gen_amswap_db_w(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_Cmp:
-+ p = mkCmp(p, i->LAin.Cmp.cond, i->LAin.Cmp.src2,
-+ i->LAin.Cmp.src1, i->LAin.Cmp.dst);
++ case 0b1010011:
++ ok = gen_amswap_db_d(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_CMove:
-+ p = mkCMove(p, i->LAin.CMove.cond, i->LAin.CMove.r0,
-+ i->LAin.CMove.r1, i->LAin.CMove.dst,
-+ i->LAin.CMove.isInt);
++ case 0b1010100:
++ ok = gen_amadd_db_w(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_Call:
-+ p = mkCall(p, i->LAin.Call.cond, i->LAin.Call.target,
-+ i->LAin.Call.rloc);
++ case 0b1010101:
++ ok = gen_amadd_db_d(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_XDirect:
-+ p = mkXDirect(p, i->LAin.XDirect.dstGA, i->LAin.XDirect.amPC,
-+ i->LAin.XDirect.cond, i->LAin.XDirect.toFastEP,
-+ disp_cp_chain_me_to_slowEP,
-+ disp_cp_chain_me_to_fastEP);
++ case 0b1010110:
++ ok = gen_amand_db_w(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_XIndir:
-+ p = mkXIndir(p, i->LAin.XIndir.dstGA, i->LAin.XIndir.amPC,
-+ i->LAin.XIndir.cond, disp_cp_xindir);
++ case 0b1010111:
++ ok = gen_amand_db_d(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_XAssisted:
-+ p = mkXAssisted(p, i->LAin.XAssisted.dstGA, i->LAin.XAssisted.amPC,
-+ i->LAin.XAssisted.cond, i->LAin.XAssisted.jk,
-+ disp_cp_xassisted);
++ case 0b1011000:
++ ok = gen_amor_db_w(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_EvCheck:
-+ p = mkEvCheck(p, i->LAin.EvCheck.amCounter,
-+ i->LAin.EvCheck.amFailAddr);
++ case 0b1011001:
++ ok = gen_amor_db_d(dres, insn, archinfo, abiinfo);
+ break;
-+ case LAin_ProfInc:
-+ p = mkProfInc(p);
++ case 0b1011010:
++ ok = gen_amxor_db_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1011011:
++ ok = gen_amxor_db_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1011100:
++ ok = gen_ammax_db_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1011101:
++ ok = gen_ammax_db_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1011110:
++ ok = gen_ammin_db_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1011111:
++ ok = gen_ammin_db_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1100000:
++ ok = gen_ammax_db_wu(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1100001:
++ ok = gen_ammax_db_du(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1100010:
++ ok = gen_ammin_db_wu(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1100011:
++ ok = gen_ammin_db_du(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1100100:
++ ok = gen_dbar(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1100101:
++ ok = gen_ibar(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101000:
++ ok = gen_fldgt_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101001:
++ ok = gen_fldgt_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101010:
++ ok = gen_fldle_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101011:
++ ok = gen_fldle_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101100:
++ ok = gen_fstgt_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101101:
++ ok = gen_fstgt_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101110:
++ ok = gen_fstle_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101111:
++ ok = gen_fstle_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1110000:
++ ok = gen_ldgt_b(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1110001:
++ ok = gen_ldgt_h(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1110010:
++ ok = gen_ldgt_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1110011:
++ ok = gen_ldgt_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1110100:
++ ok = gen_ldle_b(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1110101:
++ ok = gen_ldle_h(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1110110:
++ ok = gen_ldle_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1110111:
++ ok = gen_ldle_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1111000:
++ ok = gen_stgt_b(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1111001:
++ ok = gen_stgt_h(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1111010:
++ ok = gen_stgt_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1111011:
++ ok = gen_stgt_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1111100:
++ ok = gen_stle_b(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1111101:
++ ok = gen_stle_h(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1111110:
++ ok = gen_stle_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1111111:
++ ok = gen_stle_d(dres, insn, archinfo, abiinfo);
+ break;
+ default:
-+ p = NULL;
++ ok = False;
+ break;
+ }
+
-+ if (p == NULL) {
-+ ppLOONGARCH64Instr(i, True);
-+ vpanic("emit_LOONGARCH64Instr");
-+ /*NOTREACHED*/
-+ }
-+
-+ vassert(((UChar*)p) - &buf[0] <= 48);
-+ return ((UChar*)p) - &buf[0];
-+}
-+
-+/* How big is an event check? See case for mkEvCheck just above. That
-+ crosschecks what this returns, so we can tell if we're inconsistent. */
-+Int evCheckSzB_LOONGARCH64 ( void )
-+{
-+ return 6 * 4; // 6 insns
++ return ok;
+}
+
-+/* NB: what goes on here has to be very closely coordinated with the
-+ emitInstr case for XDirect, above. */
-+VexInvalRange chainXDirect_LOONGARCH64 ( VexEndness endness_host,
-+ void* place_to_chain,
-+ const void* disp_cp_chain_me_EXPECTED,
-+ const void* place_to_jump_to )
++static Bool disInstr_LOONGARCH64_WRK_FCMP_S ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(endness_host == VexEndnessLE);
-+
-+ /* What we're expecting to see is:
-+ * la $t0, disp_cp_chain_me_to_EXPECTED
-+ * jirl $ra, $t0, 0
-+ * viz
-+ * <16 bytes generated by mkLoadImm_EXACTLY4>
-+ * jirl $ra, $t0, 0
-+ */
-+ UInt* p = (UInt*)place_to_chain;
-+ vassert(((HWord)p & 3) == 0);
-+ vassert(is_LoadImm_EXACTLY4(p, hregT0(), (ULong)(Addr)disp_cp_chain_me_EXPECTED));
-+ vassert(p[4] == emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1));
++ Bool ok;
+
-+ /* And what we want to change it to is:
-+ * la $t0, place_to_jump_to
-+ * jirl $ra, $t0, 0
-+ * viz
-+ * <16 bytes generated by mkLoadImm_EXACTLY4>
-+ * jirl $ra, $t0, 0
-+ *
-+ * The replacement has the same length as the original.
-+ */
-+ p = mkLoadImm_EXACTLY4(p, hregT0(), (ULong)(Addr)place_to_jump_to);
-+ *p++ = emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1);
++ switch (SLICE(insn, 19, 15)) {
++ case 0x0:
++ ok = gen_fcmp_caf_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x1:
++ ok = gen_fcmp_saf_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x2:
++ ok = gen_fcmp_clt_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x3:
++ ok = gen_fcmp_slt_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x4:
++ ok = gen_fcmp_ceq_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x5:
++ ok = gen_fcmp_seq_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x6:
++ ok = gen_fcmp_cle_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x7:
++ ok = gen_fcmp_sle_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x8:
++ ok = gen_fcmp_cun_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x9:
++ ok = gen_fcmp_sun_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0xa:
++ ok = gen_fcmp_cult_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0xb:
++ ok = gen_fcmp_sult_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0xc:
++ ok = gen_fcmp_cueq_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0xd:
++ ok = gen_fcmp_sueq_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0xe:
++ ok = gen_fcmp_cule_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0xf:
++ ok = gen_fcmp_sule_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x10:
++ ok = gen_fcmp_cne_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x11:
++ ok = gen_fcmp_sne_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x14:
++ ok = gen_fcmp_cor_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x15:
++ ok = gen_fcmp_sor_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x18:
++ ok = gen_fcmp_cune_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x19:
++ ok = gen_fcmp_sune_s(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
+
-+ VexInvalRange vir = { (HWord)place_to_chain, 4 * 4 + 4 };
-+ return vir;
++ return ok;
+}
+
-+/* NB: what goes on here has to be very closely coordinated with the
-+ emitInstr case for XDirect, above. */
-+VexInvalRange unchainXDirect_LOONGARCH64 ( VexEndness endness_host,
-+ void* place_to_unchain,
-+ const void* place_to_jump_to_EXPECTED,
-+ const void* disp_cp_chain_me )
++static Bool disInstr_LOONGARCH64_WRK_FCMP_D ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(endness_host == VexEndnessLE);
-+
-+ /* What we're expecting to see is:
-+ * la $t0, place_to_jump_to_EXPECTED
-+ * jirl $ra, $t0, 0
-+ * viz
-+ * <16 bytes generated by mkLoadImm_EXACTLY4>
-+ * jirl $ra, $t0, 0
-+ */
-+ UInt* p = (UInt*)place_to_unchain;
-+ vassert(((HWord)p & 3) == 0);
-+ vassert(is_LoadImm_EXACTLY4(p, hregT0(), (ULong)(Addr)place_to_jump_to_EXPECTED));
-+ vassert(p[4] == emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1));
++ Bool ok;
+
-+ /* And what we want to change it to is:
-+ * la $t0, disp_cp_chain_me
-+ * jirl $ra, $t0, 0
-+ * viz
-+ * <16 bytes generated by mkLoadImm_EXACTLY4>
-+ * jirl $ra, $t0, 0
-+ *
-+ * The replacement has the same length as the original.
-+ */
-+ p = mkLoadImm_EXACTLY4(p, hregT0(), (ULong)(Addr)disp_cp_chain_me);
-+ *p++ = emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1);
++ switch (SLICE(insn, 19, 15)) {
++ case 0x0:
++ ok = gen_fcmp_caf_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x1:
++ ok = gen_fcmp_saf_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x2:
++ ok = gen_fcmp_clt_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x3:
++ ok = gen_fcmp_slt_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x4:
++ ok = gen_fcmp_ceq_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x5:
++ ok = gen_fcmp_seq_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x6:
++ ok = gen_fcmp_cle_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x7:
++ ok = gen_fcmp_sle_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x8:
++ ok = gen_fcmp_cun_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x9:
++ ok = gen_fcmp_sun_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0xa:
++ ok = gen_fcmp_cult_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0xb:
++ ok = gen_fcmp_sult_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0xc:
++ ok = gen_fcmp_cueq_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0xd:
++ ok = gen_fcmp_sueq_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0xe:
++ ok = gen_fcmp_cule_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0xf:
++ ok = gen_fcmp_sule_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x10:
++ ok = gen_fcmp_cne_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x11:
++ ok = gen_fcmp_sne_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x14:
++ ok = gen_fcmp_cor_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x15:
++ ok = gen_fcmp_sor_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x18:
++ ok = gen_fcmp_cune_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0x19:
++ ok = gen_fcmp_sune_d(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
+
-+ VexInvalRange vir = { (HWord)place_to_unchain, 4 * 4 + 4 };
-+ return vir;
++ return ok;
+}
+
-+/* Patch the counter address into a profile inc point, as previously
-+ created by the mkProfInc. */
-+VexInvalRange patchProfInc_LOONGARCH64 ( VexEndness endness_host,
-+ void* place_to_patch,
-+ const ULong* location_of_counter )
++static Bool disInstr_LOONGARCH64_WRK_00 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
+{
-+ vassert(endness_host == VexEndnessLE);
-+ vassert(sizeof(ULong*) == 8);
-+
-+ /*
-+ $t0 = NotKnownYet
-+ ld.d $t1, $t0, 0
-+ addi.d $t1, $t1, 1
-+ st.d $t1, $t0, 0
-+ */
-+ UInt* p = (UInt*)place_to_patch;
-+ vassert(((HWord)p & 3) == 0);
-+ vassert(is_LoadImm_EXACTLY4(p, hregT0(), 0x6555755585559555UL));
-+ vassert(p[4] == emit_op_si12_rj_rd(LAload_LD_D, 0, 12, 13));
-+ vassert(p[5] == emit_op_si12_rj_rd(LAbin_ADDI_D, 1, 13, 13));
-+ vassert(p[6] == emit_op_si12_rj_rd(LAstore_ST_D, 0, 12, 13));
++ Bool ok;
+
-+ p = mkLoadImm_EXACTLY4(p, hregT0(), (ULong)(Addr)location_of_counter);
++ switch (SLICE(insn, 29, 26)) {
++ case 0b0000:
++ ok = disInstr_LOONGARCH64_WRK_00_0000(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0010:
++ switch (SLICE(insn, 25, 20)) {
++ case 0b000001:
++ ok = gen_fmadd_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b000010:
++ ok = gen_fmadd_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b000101:
++ ok = gen_fmsub_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b000110:
++ ok = gen_fmsub_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b001001:
++ ok = gen_fnmadd_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b001010:
++ ok = gen_fnmadd_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b001101:
++ ok = gen_fnmsub_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b001110:
++ ok = gen_fnmsub_d(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
++ case 0b0011:
++ switch (SLICE(insn, 25, 20)) {
++ case 0b000001:
++ if (SLICE(insn, 4, 3) == 0b00) {
++ ok = disInstr_LOONGARCH64_WRK_FCMP_S(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = False;
++ }
++ break;
++ case 0b000010:
++ if (SLICE(insn, 4, 3) == 0b00) {
++ ok = disInstr_LOONGARCH64_WRK_FCMP_D(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = False;
++ }
++ break;
++ case 0b010000:
++ if (SLICE(insn, 19, 18) == 0b00) {
++ ok = gen_fsel(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = False;
++ }
++ break;
++ case 0b010001:
++ ok = gen_vbitsel(dres, insn, archinfo, abiinfo); break;
++ case 0b010010:
++ ok = gen_xvbitsel(dres, insn, archinfo, abiinfo); break;
++ case 0b010101:
++ ok = gen_vshuf_b(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b010110:
++ ok = gen_xvshuf_b(dres, insn, archinfo, abiinfo); break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
++ case 0b0100:
++ ok = gen_addu16i_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101:
++ if (SLICE(insn, 25, 25) == 0) {
++ ok = gen_lu12i_w(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = gen_lu32i_d(dres, insn, archinfo, abiinfo);
++ }
++ break;
++ case 0b0110:
++ if (SLICE(insn, 25, 25) == 0) {
++ ok = gen_pcaddi(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = gen_pcalau12i(dres, insn, archinfo, abiinfo);
++ }
++ break;
++ case 0b0111:
++ if (SLICE(insn, 25, 25) == 0) {
++ ok = gen_pcaddu12i(dres, insn, archinfo, abiinfo);
++ } else {
++ ok = gen_pcaddu18i(dres, insn, archinfo, abiinfo);
++ }
++ break;
++ case 0b1000:
++ switch (SLICE(insn, 25, 24)) {
++ case 0b00:
++ ok = gen_ll_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01:
++ ok = gen_sc_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10:
++ ok = gen_ll_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b11:
++ ok = gen_sc_d(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
++ case 0b1001:
++ switch (SLICE(insn, 25, 24)) {
++ case 0b00:
++ ok = gen_ldptr_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01:
++ ok = gen_stptr_w(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10:
++ ok = gen_ldptr_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b11:
++ ok = gen_stptr_d(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
++ case 0b1010:
++ ok = disInstr_LOONGARCH64_WRK_00_1010(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1011:
++ ok = disInstr_LOONGARCH64_WRK_00_1011(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1100:
++ ok = disInstr_LOONGARCH64_WRK_00_1100(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1110:
++ switch (SLICE(insn, 25, 22)) {
++ case 0b0000:
++ ok = disInstr_LOONGARCH64_WRK_00_1110_0000(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0001:
++ ok = disInstr_LOONGARCH64_WRK_00_1110_0001(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
++ default:
++ ok = False;
++ break;
++ }
+
-+ VexInvalRange vir = { (HWord)place_to_patch, 4 * 4 };
-+ return vir;
++ return ok;
+}
+
++static Bool disInstr_LOONGARCH64_WRK_01_1100_0000 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+/*---------------------------------------------------------------*/
-+/*--- end host_loongarch64_defs.c ---*/
-+/*---------------------------------------------------------------*/
-diff --git a/VEX/priv/host_loongarch64_defs.h b/VEX/priv/host_loongarch64_defs.h
-new file mode 100644
-index 0000000..acf38b1
---- /dev/null
-+++ b/VEX/priv/host_loongarch64_defs.h
-@@ -0,0 +1,919 @@
-+
-+/*---------------------------------------------------------------*/
-+/*--- begin host_loongarch64_defs.h ---*/
-+/*---------------------------------------------------------------*/
-+
-+/*
-+ This file is part of Valgrind, a dynamic binary instrumentation
-+ framework.
-+
-+ Copyright (C) 2021-2022 Loongson Technology Corporation Limited
++ switch (SLICE(insn, 21, 17)) {
++ case 0b00000: case 0b00001:
++ case 0b00010: case 0b00011:
++ case 0b00100:
++ ok = gen_vcmp(dres, insn, archinfo, abiinfo); break;
++ case 0b00101:
++ case 0b00110:
++ ok = gen_vadd_vsub(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01111:
++ case 0b10000: case 0b10001: case 0b10010: case 0b10111:
++ case 0b11000: case 0b11001: case 0b11010:
++ ok = gen_vaddw_vsubw_x_x(dres, insn, archinfo, abiinfo); break;
++ case 0b11111:
++ ok = gen_vaddw_vsubw_x_x_x(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
-+ This program is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License as
-+ published by the Free Software Foundation; either version 2 of the
-+ License, or (at your option) any later version.
++ return ok;
++}
+
-+ This program is distributed in the hope that it will be useful, but
-+ WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ General Public License for more details.
++static Bool disInstr_LOONGARCH64_WRK_01_1100_0001 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, see .
++ switch (SLICE(insn, 21, 18)) {
++ case 0b0000:
++ ok = gen_vaddw_vsubw_x_x_x(dres, insn, archinfo, abiinfo); break;
++ case 0b0001: case 0b0010:
++ case 0b0011:
++ ok = gen_vsadd_vssub(dres, insn, archinfo, abiinfo); break;
++ case 0b0101: case 0b0110:
++ ok = gen_vhaddw_vhsubw(dres, insn, archinfo, abiinfo); break;
++ case 0b1000:
++ ok = gen_vabsd(dres, insn, archinfo, abiinfo); break;
++ case 0b0111:
++ ok = gen_vadda(dres, insn, archinfo, abiinfo); break;
++ case 0b1001: case 0b1010:
++ ok = gen_vavg(dres, insn, archinfo, abiinfo); break;
++ case 0b1100:
++ case 0b1101:
++ ok = gen_vmax_vmin(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
+
-+ The GNU General Public License is contained in the file COPYING.
-+*/
++ return ok;
++}
+
-+#ifndef __VEX_HOST_LOONGARCH64_DEFS_H
-+#define __VEX_HOST_LOONGARCH64_DEFS_H
++static Bool disInstr_LOONGARCH64_WRK_01_1100_0010 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+#include "libvex_basictypes.h"
-+#include "libvex.h" /* VexArch */
-+#include "host_generic_regs.h" /* HReg */
++ switch (SLICE(insn, 21, 18)) {
++ case 0b0001: case 0b0010:
++ ok = gen_vmu(dres, insn, archinfo, abiinfo); break;
++ case 0b0100: case 0b0110:
++ ok = gen_vmulw(dres, insn, archinfo, abiinfo); break;
++ case 0b1000:
++ ok = gen_vmulw_x_x_x(dres, insn, archinfo, abiinfo); break;
++ case 0b1010:
++ ok = gen_vmadd_vmsub(dres, insn, archinfo, abiinfo); break;
++ case 0b1011: case 0b1101:
++ ok = gen_vmaddw(dres, insn, archinfo, abiinfo); break;
++ case 0b1111:
++ ok = gen_vmaddw_x_x_x(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
++ return ok;
++}
+
-+/* --------- Registers. --------- */
++static Bool disInstr_LOONGARCH64_WRK_01_1100_0011 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+#define ST_IN static inline
++ switch (SLICE(insn, 21, 18)) {
++ case 0b1000: case 0b1001:
++ ok = gen_vdiv(dres, insn, archinfo, abiinfo); break;
++ case 0b1010: case 0b1011:
++ ok = gen_vshift(dres, insn, archinfo, abiinfo); break;
++ case 0b1100:
++ ok = gen_vsrlr(dres, insn, archinfo, abiinfo); break;
++ break;
++ case 0b1101:
++ ok = gen_vsrlan(dres, insn, archinfo, abiinfo); break;
++ case 0b1110:
++ ok = gen_vsrlarn(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
-+/* Integer static registers */
-+ST_IN HReg hregLOONGARCH64_R23 ( void ) { return mkHReg(False, HRcInt64, 23, 0); }
-+ST_IN HReg hregLOONGARCH64_R24 ( void ) { return mkHReg(False, HRcInt64, 24, 1); }
-+ST_IN HReg hregLOONGARCH64_R25 ( void ) { return mkHReg(False, HRcInt64, 25, 2); }
-+ST_IN HReg hregLOONGARCH64_R26 ( void ) { return mkHReg(False, HRcInt64, 26, 3); }
-+ST_IN HReg hregLOONGARCH64_R27 ( void ) { return mkHReg(False, HRcInt64, 27, 4); }
-+ST_IN HReg hregLOONGARCH64_R28 ( void ) { return mkHReg(False, HRcInt64, 28, 5); }
-+ST_IN HReg hregLOONGARCH64_R29 ( void ) { return mkHReg(False, HRcInt64, 29, 6); }
-+ST_IN HReg hregLOONGARCH64_R30 ( void ) { return mkHReg(False, HRcInt64, 30, 7); }
-+/* $r31 is used as guest stack pointer */
++ return ok;
++}
+
-+/* Integer temporary registers */
-+/* $r12 is used as a chaining/ProfInc/Cmove/genSpill/genReload temporary */
-+/* $r13 is used as a ProfInc temporary */
-+ST_IN HReg hregLOONGARCH64_R14 ( void ) { return mkHReg(False, HRcInt64, 14, 8); }
-+ST_IN HReg hregLOONGARCH64_R15 ( void ) { return mkHReg(False, HRcInt64, 15, 9); }
-+ST_IN HReg hregLOONGARCH64_R16 ( void ) { return mkHReg(False, HRcInt64, 16, 10); }
-+ST_IN HReg hregLOONGARCH64_R17 ( void ) { return mkHReg(False, HRcInt64, 17, 11); }
-+ST_IN HReg hregLOONGARCH64_R18 ( void ) { return mkHReg(False, HRcInt64, 18, 12); }
-+ST_IN HReg hregLOONGARCH64_R19 ( void ) { return mkHReg(False, HRcInt64, 19, 13); }
-+ST_IN HReg hregLOONGARCH64_R20 ( void ) { return mkHReg(False, HRcInt64, 20, 14); }
++static Bool disInstr_LOONGARCH64_WRK_01_1100_0100 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+/* Floating point static registers */
-+ST_IN HReg hregLOONGARCH64_F24 ( void ) { return mkHReg(False, HRcFlt64, 24, 15); }
-+ST_IN HReg hregLOONGARCH64_F25 ( void ) { return mkHReg(False, HRcFlt64, 25, 16); }
-+ST_IN HReg hregLOONGARCH64_F26 ( void ) { return mkHReg(False, HRcFlt64, 26, 17); }
-+ST_IN HReg hregLOONGARCH64_F27 ( void ) { return mkHReg(False, HRcFlt64, 27, 18); }
-+ST_IN HReg hregLOONGARCH64_F28 ( void ) { return mkHReg(False, HRcFlt64, 28, 19); }
-+ST_IN HReg hregLOONGARCH64_F29 ( void ) { return mkHReg(False, HRcFlt64, 29, 20); }
-+ST_IN HReg hregLOONGARCH64_F30 ( void ) { return mkHReg(False, HRcFlt64, 30, 21); }
-+ST_IN HReg hregLOONGARCH64_F31 ( void ) { return mkHReg(False, HRcFlt64, 31, 22); }
++ switch (SLICE(insn, 21, 17)) {
++ case 0b00110: case 0b00111: case 0b01000:
++ ok = gen_vbitops(dres, insn, archinfo, abiinfo); break;
++ case 0b01011:
++ case 0b01100:
++ case 0b01101:
++ case 0b01110:
++ case 0b01111:
++ case 0b10000:
++ ok = gen_evod(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10001:
++ ok = gen_vreplve(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10011:
++ case 0b10100:
++ ok = gen_logical_v(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10101:
++ ok = gen_vfrstp(dres, insn, archinfo, abiinfo); break;
++ case 0b10110:
++ ok = gen_vadd_vsub_q(dres, insn, archinfo, abiinfo); break;
++ case 0b10111:
++ ok = gen_vsigncov(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
-+/* Vector static registers */
-+ST_IN HReg hregLOONGARCH64_V24 ( void ) { return mkHReg(False, HRcVec128, 24, 23); }
-+ST_IN HReg hregLOONGARCH64_V25 ( void ) { return mkHReg(False, HRcVec128, 25, 24); }
-+ST_IN HReg hregLOONGARCH64_V26 ( void ) { return mkHReg(False, HRcVec128, 26, 25); }
-+ST_IN HReg hregLOONGARCH64_V27 ( void ) { return mkHReg(False, HRcVec128, 27, 26); }
-+ST_IN HReg hregLOONGARCH64_V28 ( void ) { return mkHReg(False, HRcVec128, 28, 27); }
-+ST_IN HReg hregLOONGARCH64_V29 ( void ) { return mkHReg(False, HRcVec128, 29, 28); }
-+ST_IN HReg hregLOONGARCH64_V30 ( void ) { return mkHReg(False, HRcVec128, 30, 29); }
-+ST_IN HReg hregLOONGARCH64_V31 ( void ) { return mkHReg(False, HRcVec128, 31, 30); }
++ return ok;
++}
+
-+/* Other Integer registers */
-+ST_IN HReg hregLOONGARCH64_R0 ( void ) { return mkHReg(False, HRcInt64, 0, 31); }
-+ST_IN HReg hregLOONGARCH64_R1 ( void ) { return mkHReg(False, HRcInt64, 1, 32); }
-+ST_IN HReg hregLOONGARCH64_R2 ( void ) { return mkHReg(False, HRcInt64, 2, 33); }
-+ST_IN HReg hregLOONGARCH64_R3 ( void ) { return mkHReg(False, HRcInt64, 3, 34); }
-+ST_IN HReg hregLOONGARCH64_R4 ( void ) { return mkHReg(False, HRcInt64, 4, 35); }
-+ST_IN HReg hregLOONGARCH64_R5 ( void ) { return mkHReg(False, HRcInt64, 5, 36); }
-+ST_IN HReg hregLOONGARCH64_R6 ( void ) { return mkHReg(False, HRcInt64, 6, 37); }
-+ST_IN HReg hregLOONGARCH64_R7 ( void ) { return mkHReg(False, HRcInt64, 7, 38); }
-+ST_IN HReg hregLOONGARCH64_R8 ( void ) { return mkHReg(False, HRcInt64, 8, 39); }
-+ST_IN HReg hregLOONGARCH64_R9 ( void ) { return mkHReg(False, HRcInt64, 9, 40); }
-+ST_IN HReg hregLOONGARCH64_R10 ( void ) { return mkHReg(False, HRcInt64, 10, 41); }
-+ST_IN HReg hregLOONGARCH64_R11 ( void ) { return mkHReg(False, HRcInt64, 11, 42); }
-+ST_IN HReg hregLOONGARCH64_R12 ( void ) { return mkHReg(False, HRcInt64, 12, 43); }
-+ST_IN HReg hregLOONGARCH64_R13 ( void ) { return mkHReg(False, HRcInt64, 13, 44); }
-+ST_IN HReg hregLOONGARCH64_R21 ( void ) { return mkHReg(False, HRcInt64, 21, 45); }
-+ST_IN HReg hregLOONGARCH64_R22 ( void ) { return mkHReg(False, HRcInt64, 22, 46); }
-+ST_IN HReg hregLOONGARCH64_R31 ( void ) { return mkHReg(False, HRcInt64, 31, 47); }
++static Bool disInstr_LOONGARCH64_WRK_01_1100_1010_01110_101 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+/* Special registers */
-+ST_IN HReg hregLOONGARCH64_FCSR3 ( void ) { return mkHReg(False, HRcInt32, 3, 48); }
++ switch (SLICE(insn, 13, 10)) {
++ case 0b0001:
++ ok = gen_vfrintrm_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0010:
++ ok = gen_vfrintrm_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101:
++ ok = gen_vfrintrp_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0110:
++ ok = gen_vfrintrp_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1001:
++ ok = gen_vfrintrz_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1010:
++ ok = gen_vfrintrz_d(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101:
++ ok = gen_vfrintrne_s(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1110:
++ ok = gen_vfrintrne_d(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
+
-+#undef ST_IN
++ return ok;
++}
+
-+#define hregZERO() hregLOONGARCH64_R0()
-+#define hregSP() hregLOONGARCH64_R3()
-+#define hregT0() hregLOONGARCH64_R12()
-+#define hregT1() hregLOONGARCH64_R13()
-+#define hregGSP() hregLOONGARCH64_R31()
++static Bool disInstr_LOONGARCH64_WRK_01_1100_0101 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+extern UInt ppHRegLOONGARCH64 ( HReg reg );
++ switch (SLICE(insn, 21, 18)) {
++ case 0b1110:
++ ok = gen_vshuf(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
-+/* Number of registers used arg passing in function calls */
-+#define LOONGARCH64_N_ARGREGS 8 /* a0 ... a7 */
++ return ok;
++}
+
++static Bool disInstr_LOONGARCH64_WRK_01_1100_1010_01110 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+/* --------- Condition codes, LOONGARCH64 encoding. --------- */
-+typedef enum {
-+ LAcc_EQ = 0, /* equal */
-+ LAcc_NE = 1, /* not equal */
++ switch (SLICE(insn, 16, 14)) {
++ case 0b000:
++ ok = gen_vcount(dres, insn, archinfo, abiinfo); break;
++ case 0b001:
++ ok = gen_vmsk(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b010:
++ ok = gen_vset(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b101:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_1010_01110_101(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
+
-+ LAcc_LT = 2, /* less than (signed) */
-+ LAcc_GE = 3, /* great equal (signed) */
++ return ok;
++}
+
-+ LAcc_LTU = 4, /* less than (unsigned) */
-+ LAcc_GEU = 5, /* great equal (unsigned) */
+
-+ LAcc_AL = 6 /* always (unconditional) */
-+} LOONGARCH64CondCode;
++static Bool disInstr_LOONGARCH64_WRK_01_1100_1010_01111 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
++ switch (SLICE(insn, 16, 14)) {
++ case 0b011:
++ ok = gen_vexth(dres, insn, archinfo, abiinfo); break;
++ case 0b100:
++ ok = gen_vreplgr2vr(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
+
-+/* --------- Memory address expressions (amodes). --------- */
++ return ok;
++}
+
-+typedef enum {
-+ LAam_RI, /* Reg + Imm (signed 12-bit) */
-+ LAam_RR /* Reg1 + Reg2 */
-+} LOONGARCH64AModeTag;
++static Bool disInstr_LOONGARCH64_WRK_01_1100_1010 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+typedef struct {
-+ LOONGARCH64AModeTag tag;
-+ union {
-+ struct {
-+ HReg base;
-+ UShort index;
-+ } RI;
-+ struct {
-+ HReg base;
-+ HReg index;
-+ } RR;
-+ } LAam;
-+} LOONGARCH64AMode;
++ switch (SLICE(insn, 21, 17)) {
++ case 0b00000: case 0b00001:
++ case 0b00010: case 0b00011:
++ case 0b00100:
++ ok = gen_vcmpi(dres, insn, archinfo, abiinfo); break;
++ case 0b00101:
++ case 0b00110:
++ ok = gen_vaddi_vsubi(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01000: case 0b01001: case 0b01010: case 0b01011:
++ ok = gen_vmaxi_vmini(dres, insn, archinfo, abiinfo); break;
++ case 0b01101:
++ ok = gen_vfrstpi(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01110:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_1010_01110(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01111:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_1010_01111(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10000: case 0b10010: case 0b10100:
++ ok = gen_vsrlari(dres, insn, archinfo, abiinfo); break;
++ default:
++ ok = False;
++ break;
++ }
+
-+extern LOONGARCH64AMode* LOONGARCH64AMode_RI ( HReg reg, UShort imm );
-+extern LOONGARCH64AMode* LOONGARCH64AMode_RR ( HReg base, HReg index );
++ return ok;
++}
+
++static Bool disInstr_LOONGARCH64_WRK_01_1100_1011 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+/* --------- Operand, which can be reg or imm. --------- */
++ switch (SLICE(insn, 21, 16)) {
++ case 0b101011:
++ ok = gen_vinsgr2vr(dres, insn, archinfo, abiinfo); break;
++ case 0b101111:
++ case 0b110011:
++ ok = gen_vpickve2gr(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b110111:
++ ok = gen_vreplvei(dres, insn, archinfo, abiinfo); break;
++ default:
++ ok = False;
++ break;
++ }
+
-+typedef enum {
-+ LAri_Reg,
-+ LAri_Imm
-+} LOONGARCH64RITag;
++ return ok;
++}
+
-+typedef struct {
-+ LOONGARCH64RITag tag;
-+ union {
-+ struct {
-+ HReg reg;
-+ } R;
-+ struct {
-+ UShort imm;
-+ UChar size; // size == 5 || size == 6 || size == 12
-+ Bool isSigned;
-+ } I;
-+ } LAri;
-+} LOONGARCH64RI;
++static Bool disInstr_LOONGARCH64_WRK_01_1100_1100 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+extern LOONGARCH64RI* LOONGARCH64RI_R ( HReg reg );
-+extern LOONGARCH64RI* LOONGARCH64RI_I ( UShort imm, UChar size, Bool isSigned );
++ switch (SLICE(insn, 21, 18)) {
++ case 0b0010: case 0b0011:
++ ok = gen_vsllwil(dres, insn, archinfo, abiinfo); break;
++ case 0b0100: case 0b0101: case 0b0110:
++ ok = gen_vbitops_imm(dres, insn, archinfo, abiinfo); break;
++ case 0b1001: case 0b1010:
++ ok = gen_vsat(dres, insn, archinfo, abiinfo); break;
++ case 0b1011: case 0b1100:
++ case 0b1101:
++ ok = gen_vshift_imm(dres, insn, archinfo, abiinfo); break;
++ default:
++ ok = False;
++ break;
++ }
+
++ return ok;
++}
+
-+/* --------- Instructions. --------- */
++static Bool disInstr_LOONGARCH64_WRK_01_1100_1101 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+/* Tags for unary operations */
-+typedef enum {
-+ LAun_CLZ_W = 0x00001400,
-+ LAun_CTZ_W = 0x00001c00,
-+ LAun_CLZ_D = 0x00002400,
-+ LAun_CTZ_D = 0x00002c00,
-+ LAun_EXT_W_H = 0x00005800,
-+ LAun_EXT_W_B = 0x00005c00
-+} LOONGARCH64UnOp;
++ switch (SLICE(insn, 21, 18)) {
++ case 0b0000: case 0b0110:
++ ok = gen_vsrlani(dres, insn, archinfo, abiinfo); break;
++ case 0b0001: case 0b0111:
++ ok = gen_vsrlarni(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
-+/* Tags for binary operations */
-+typedef enum {
-+ LAbin_ADD_W = 0x00100000,
-+ LAbin_ADD_D = 0x00108000,
-+ LAbin_SUB_W = 0x00110000,
-+ LAbin_SUB_D = 0x00118000,
-+ LAbin_NOR = 0x00140000,
-+ LAbin_AND = 0x00148000,
-+ LAbin_OR = 0x00150000,
-+ LAbin_XOR = 0x00158000,
-+ LAbin_SLL_W = 0x00170000,
-+ LAbin_SRL_W = 0x00178000,
-+ LAbin_SRA_W = 0x00180000,
-+ LAbin_SLL_D = 0x00188000,
-+ LAbin_SRL_D = 0x00190000,
-+ LAbin_SRA_D = 0x00198000,
-+ LAbin_MUL_W = 0x001c0000,
-+ LAbin_MUL_D = 0x001d8000,
-+ LAbin_MULH_W = 0x001c8000,
-+ LAbin_MULH_WU = 0x001d0000,
-+ LAbin_MULH_D = 0x001e0000,
-+ LAbin_MULH_DU = 0x001e8000,
-+ LAbin_MULW_D_W = 0x001f0000,
-+ LAbin_MULW_D_WU = 0x001f8000,
-+ LAbin_DIV_W = 0x00200000,
-+ LAbin_MOD_W = 0x00208000,
-+ LAbin_DIV_WU = 0x00210000,
-+ LAbin_MOD_WU = 0x00218000,
-+ LAbin_DIV_D = 0x00220000,
-+ LAbin_MOD_D = 0x00228000,
-+ LAbin_DIV_DU = 0x00230000,
-+ LAbin_MOD_DU = 0x00238000,
-+ LAbin_SLLI_W = 0x00408000,
-+ LAbin_SLLI_D = 0x00410000,
-+ LAbin_SRLI_W = 0x00448000,
-+ LAbin_SRLI_D = 0x00450000,
-+ LAbin_SRAI_W = 0x00488000,
-+ LAbin_SRAI_D = 0x00490000,
-+ LAbin_ADDI_W = 0x02800000,
-+ LAbin_ADDI_D = 0x02c00000,
-+ LAbin_ANDI = 0x03400000,
-+ LAbin_ORI = 0x03800000,
-+ LAbin_XORI = 0x03c00000
-+} LOONGARCH64BinOp;
++ return ok;
++}
+
-+/* Tags for load operations */
-+typedef enum {
-+ LAload_LD_W = 0x28800000,
-+ LAload_LD_D = 0x28c00000,
-+ LAload_LD_BU = 0x2a000000,
-+ LAload_LD_HU = 0x2a400000,
-+ LAload_LD_WU = 0x2a800000,
-+ LAload_LDX_D = 0x380c0000,
-+ LAload_LDX_BU = 0x38200000,
-+ LAload_LDX_HU = 0x38240000,
-+ LAload_LDX_WU = 0x38280000
-+} LOONGARCH64LoadOp;
++static Bool disInstr_LOONGARCH64_WRK_01_1100_1110 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+/* Tags for store operations */
-+typedef enum {
-+ LAstore_ST_B = 0x29000000,
-+ LAstore_ST_H = 0x29400000,
-+ LAstore_ST_W = 0x29800000,
-+ LAstore_ST_D = 0x29c00000,
-+ LAstore_STX_B = 0x38100000,
-+ LAstore_STX_H = 0x38140000,
-+ LAstore_STX_W = 0x38180000,
-+ LAstore_STX_D = 0x381c0000
-+} LOONGARCH64StoreOp;
++ switch (SLICE(insn, 21, 20)) {
++ case 0b00:
++ ok = gen_vextrins(dres, insn, archinfo, abiinfo); break;
++ case 0b01:
++ ok = gen_vshuf4i(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
-+/* Tags for ll/sc operations */
-+typedef enum {
-+ LAllsc_LL_W = 0x20000000,
-+ LAllsc_SC_W = 0x21000000,
-+ LAllsc_LL_D = 0x22000000,
-+ LAllsc_SC_D = 0x23000000
-+} LOONGARCH64LLSCOp;
++ return ok;
++}
+
-+/* Tags for barrier operations */
-+typedef enum {
-+ LAbar_DBAR = 0x38720000,
-+ LAbar_IBAR = 0x38728000
-+} LOONGARCH64BarOp;
++static Bool disInstr_LOONGARCH64_WRK_01_1100_1111 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+/* Tags for floating point unary operations */
-+typedef enum {
-+ LAfpun_FABS_S = 0x01140400,
-+ LAfpun_FABS_D = 0x01140800,
-+ LAfpun_FNEG_S = 0x01141400,
-+ LAfpun_FNEG_D = 0x01141800,
-+ LAfpun_FLOGB_S = 0x01142400,
-+ LAfpun_FLOGB_D = 0x01142800,
-+ LAfpun_FSQRT_S = 0x01144400,
-+ LAfpun_FSQRT_D = 0x01144800,
-+ LAfpun_FRSQRT_S = 0x01146400,
-+ LAfpun_FRSQRT_D = 0x01146800,
-+ LAfpun_FCVT_S_D = 0x01191800,
-+ LAfpun_FCVT_D_S = 0x01192400,
-+ LAfpun_FTINT_W_S = 0x011b0400,
-+ LAfpun_FTINT_W_D = 0x011b0800,
-+ LAfpun_FTINT_L_S = 0x011b2400,
-+ LAfpun_FTINT_L_D = 0x011b2800,
-+ LAfpun_FFINT_S_W = 0x011d1000,
-+ LAfpun_FFINT_S_L = 0x011d1800,
-+ LAfpun_FFINT_D_W = 0x011d2000,
-+ LAfpun_FFINT_D_L = 0x011d2800,
-+ LAfpun_FRINT_S = 0x011e4400,
-+ LAfpun_FRINT_D = 0x011e4800
-+} LOONGARCH64FpUnOp;
++ switch (SLICE(insn, 21, 18)) {
++ case 0b0001:
++ ok = gen_vbitseli(dres, insn, archinfo, abiinfo); break;
++ case 0b0100:
++ case 0b0101:
++ case 0b0110:
++ case 0b0111:
++ ok = gen_vlogical_u8(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1000:
++ ok = gen_vldi(dres, insn, archinfo, abiinfo); break;
++ case 0b1001:
++ ok = gen_vpermi(dres, insn, archinfo, abiinfo); break;
++ default:
++ ok = False;
++ break;
++ }
+
-+/* Tags for floating point binary operations */
-+typedef enum {
-+ LAfpbin_FADD_S = 0x01008000,
-+ LAfpbin_FADD_D = 0x01010000,
-+ LAfpbin_FSUB_S = 0x01028000,
-+ LAfpbin_FSUB_D = 0x01030000,
-+ LAfpbin_FMUL_S = 0x01048000,
-+ LAfpbin_FMUL_D = 0x01050000,
-+ LAfpbin_FDIV_S = 0x01068000,
-+ LAfpbin_FDIV_D = 0x01070000,
-+ LAfpbin_FMAX_S = 0x01088000,
-+ LAfpbin_FMAX_D = 0x01090000,
-+ LAfpbin_FMIN_S = 0x010a8000,
-+ LAfpbin_FMIN_D = 0x010b0000,
-+ LAfpbin_FMAXA_S = 0x010c8000,
-+ LAfpbin_FMAXA_D = 0x010d0000,
-+ LAfpbin_FMINA_S = 0x010e8000,
-+ LAfpbin_FMINA_D = 0x010f0000,
-+ LAfpbin_FSCALEB_S = 0x01108000,
-+ LAfpbin_FSCALEB_D = 0x01110000
-+} LOONGARCH64FpBinOp;
++ return ok;
++}
+
-+/* Tags for floating point trinary operations */
-+typedef enum {
-+ LAfpbin_FMADD_S = 0x08100000,
-+ LAfpbin_FMADD_D = 0x08200000,
-+ LAfpbin_FMSUB_S = 0x08500000,
-+ LAfpbin_FMSUB_D = 0x08600000
-+} LOONGARCH64FpTriOp;
++static Bool disInstr_LOONGARCH64_WRK_01_1100 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+/* Tags for floating point load operations */
-+typedef enum {
-+ LAfpload_FLD_S = 0x2b000000,
-+ LAfpload_FLD_D = 0x2b800000,
-+ LAfpload_FLDX_S = 0x38300000,
-+ LAfpload_FLDX_D = 0x38340000
-+} LOONGARCH64FpLoadOp;
++ switch (SLICE(insn, 25, 22)) {
++ case 0b0000:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_0000(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0001:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_0001(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0010:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_0010(dres, insn, archinfo, abiinfo); break;
++ case 0b0011:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_0011(dres, insn, archinfo, abiinfo); break;
++ case 0b0100:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_0100(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_0101(dres, insn, archinfo, abiinfo); break;
++ case 0b1010:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_1010(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1011:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_1011(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1100:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_1100(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_1101(dres, insn, archinfo, abiinfo); break;
++ case 0b1110:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_1110(dres, insn, archinfo, abiinfo); break;
++ case 0b1111:
++ ok = disInstr_LOONGARCH64_WRK_01_1100_1111(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
+
-+/* Tags for floating point store operations */
-+typedef enum {
-+ LAfpstore_FST_S = 0x2b400000,
-+ LAfpstore_FST_D = 0x2bc00000,
-+ LAfpstore_FSTX_S = 0x38380000,
-+ LAfpstore_FSTX_D = 0x383c0000
-+} LOONGARCH64FpStoreOp;
++ return ok;
++}
+
-+/* Tags for floating point move operations */
-+typedef enum {
-+ LAfpmove_FMOV_S = 0x01149400,
-+ LAfpmove_FMOV_D = 0x01149800,
-+ LAfpmove_MOVGR2FR_W = 0x0114a400,
-+ LAfpmove_MOVGR2FR_D = 0x0114a800,
-+ LAfpmove_MOVFR2GR_S = 0x0114b400,
-+ LAfpmove_MOVFR2GR_D = 0x0114b800,
-+ LAfpmove_MOVGR2FCSR = 0x0114c000,
-+ LAfpmove_MOVFCSR2GR = 0x0114c800
-+} LOONGARCH64FpMoveOp;
++static Bool disInstr_LOONGARCH64_WRK_01_1101_0000 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+/* Tags for floating point compare operations */
-+typedef enum {
-+ LAfpcmp_FCMP_CLT_S = 0x0c110000,
-+ LAfpcmp_FCMP_CLT_D = 0x0c210000,
-+ LAfpcmp_FCMP_CEQ_S = 0x0c120000,
-+ LAfpcmp_FCMP_CEQ_D = 0x0c220000,
-+ LAfpcmp_FCMP_CUN_S = 0x0c140000,
-+ LAfpcmp_FCMP_CUN_D = 0x0c240000
-+} LOONGARCH64FpCmpOp;
++ switch (SLICE(insn, 21, 17)) {
++ case 0b00000: case 0b00001:
++ case 0b00010: case 0b00011:
++ case 0b00100:
++ ok = gen_xvcmp(dres, insn, archinfo, abiinfo); break;
++ case 0b00101:
++ case 0b00110:
++ ok = gen_xvadd_xvsub(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01111:
++ case 0b10000: case 0b10001: case 0b10010: case 0b10111:
++ case 0b11000: case 0b11001: case 0b11010:
++ ok = gen_xvaddw_xvsubw_x_x(dres, insn, archinfo, abiinfo); break;
++ case 0b11111:
++ ok = gen_xvaddw_xvsubw_x_x_x(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
-+/* Tags for vector unary operations */
-+typedef enum {
-+ LAvecun_VCLO_B = 0x729c0000,
-+ LAvecun_VCLO_H = 0x729c0400,
-+ LAvecun_VCLO_W = 0x729c0800,
-+ LAvecun_VCLZ_B = 0x729c1000,
-+ LAvecun_VCLZ_H = 0x729c1400,
-+ LAvecun_VCLZ_W = 0x729c1800,
-+ LAvecun_VCLZ_D = 0x729c1c00,
-+ LAvecun_VPCNT_B = 0x729c2000,
-+ LAvecun_VEXTH_H_B = 0x729ee000,
-+ LAvecun_VEXTH_W_H = 0x729ee400,
-+ LAvecun_VEXTH_D_W = 0x729ee800,
-+ LAvecun_VEXTH_Q_D = 0x729eec00,
-+ LAvecun_VEXTH_HU_BU = 0x729ef000,
-+ LAvecun_VEXTH_WU_HU = 0x729ef400,
-+ LAvecun_VEXTH_DU_WU = 0x729ef800,
-+ LAvecun_VEXTH_QU_DU = 0x729efc00,
-+ LAvecun_VREPLGR2VR_B = 0x729f0000,
-+ LAvecun_VREPLGR2VR_H = 0x729f0400,
-+ LAvecun_VREPLGR2VR_W = 0x729f0800,
-+ LAvecun_VREPLGR2VR_D = 0x729f0c00
-+} LOONGARCH64VecUnOp;
++ return ok;
++}
+
-+/* Tags for vector binary operations */
-+typedef enum {
-+ LAvecbin_VSEQ_B = 0x70000000,
-+ LAvecbin_VSEQ_H = 0x70008000,
-+ LAvecbin_VSEQ_W = 0x70010000,
-+ LAvecbin_VSEQ_D = 0x70018000,
-+ LAvecbin_VSLT_B = 0x70060000,
-+ LAvecbin_VSLT_H = 0x70068000,
-+ LAvecbin_VSLT_W = 0x70070000,
-+ LAvecbin_VSLT_D = 0x70078000,
-+ LAvecbin_VSLT_BU = 0x70080000,
-+ LAvecbin_VSLT_HU = 0x70088000,
-+ LAvecbin_VSLT_WU = 0x70090000,
-+ LAvecbin_VSLT_DU = 0x70098000,
-+ LAvecbin_VADD_B = 0x700a0000,
-+ LAvecbin_VADD_H = 0x700a8000,
-+ LAvecbin_VADD_W = 0x700b0000,
-+ LAvecbin_VADD_D = 0x700b8000,
-+ LAvecbin_VSUB_B = 0x700c0000,
-+ LAvecbin_VSUB_H = 0x700c8000,
-+ LAvecbin_VSUB_W = 0x700d0000,
-+ LAvecbin_VSUB_D = 0x700d8000,
-+ LAvecbin_VSADD_B = 0x70460000,
-+ LAvecbin_VSADD_H = 0x70468000,
-+ LAvecbin_VSADD_W = 0x70470000,
-+ LAvecbin_VSADD_D = 0x70478000,
-+ LAvecbin_VSSUB_B = 0x70480000,
-+ LAvecbin_VSSUB_H = 0x70488000,
-+ LAvecbin_VSSUB_W = 0x70490000,
-+ LAvecbin_VSSUB_D = 0x70498000,
-+ LAvecbin_VSADD_BU = 0x704a0000,
-+ LAvecbin_VSADD_HU = 0x704a8000,
-+ LAvecbin_VSADD_WU = 0x704b0000,
-+ LAvecbin_VSADD_DU = 0x704b8000,
-+ LAvecbin_VSSUB_BU = 0x704c0000,
-+ LAvecbin_VSSUB_HU = 0x704c8000,
-+ LAvecbin_VSSUB_WU = 0x704d0000,
-+ LAvecbin_VSSUB_DU = 0x704d8000,
-+ LAvecbin_VADDA_B = 0x705c0000,
-+ LAvecbin_VADDA_H = 0x705c8000,
-+ LAvecbin_VADDA_W = 0x705d0000,
-+ LAvecbin_VADDA_D = 0x705d8000,
-+ LAvecbin_VAVGR_B = 0x70680000,
-+ LAvecbin_VAVGR_H = 0x70688000,
-+ LAvecbin_VAVGR_W = 0x70690000,
-+ LAvecbin_VAVGR_D = 0x70698000,
-+ LAvecbin_VAVGR_BU = 0x706a0000,
-+ LAvecbin_VAVGR_HU = 0x706a8000,
-+ LAvecbin_VAVGR_WU = 0x706b0000,
-+ LAvecbin_VAVGR_DU = 0x706b8000,
-+ LAvecbin_VMAX_B = 0x70700000,
-+ LAvecbin_VMAX_H = 0x70708000,
-+ LAvecbin_VMAX_W = 0x70710000,
-+ LAvecbin_VMAX_D = 0x70718000,
-+ LAvecbin_VMIN_B = 0x70720000,
-+ LAvecbin_VMIN_H = 0x70728000,
-+ LAvecbin_VMIN_W = 0x70730000,
-+ LAvecbin_VMIN_D = 0x70738000,
-+ LAvecbin_VMAX_BU = 0x70740000,
-+ LAvecbin_VMAX_HU = 0x70748000,
-+ LAvecbin_VMAX_WU = 0x70750000,
-+ LAvecbin_VMAX_DU = 0x70758000,
-+ LAvecbin_VMIN_BU = 0x70760000,
-+ LAvecbin_VMIN_HU = 0x70768000,
-+ LAvecbin_VMIN_WU = 0x70770000,
-+ LAvecbin_VMIN_DU = 0x70778000,
-+ LAvecbin_VMUL_B = 0x70840000,
-+ LAvecbin_VMUL_H = 0x70848000,
-+ LAvecbin_VMUL_W = 0x70850000,
-+ LAvecbin_VMUH_B = 0x70860000,
-+ LAvecbin_VMUH_H = 0x70868000,
-+ LAvecbin_VMUH_W = 0x70870000,
-+ LAvecbin_VMUH_BU = 0x70880000,
-+ LAvecbin_VMUH_HU = 0x70888000,
-+ LAvecbin_VMUH_WU = 0x70890000,
-+ LAvecbin_VSLL_B = 0x70e80000,
-+ LAvecbin_VSLL_H = 0x70e88000,
-+ LAvecbin_VSLL_W = 0x70e90000,
-+ LAvecbin_VSLL_D = 0x70e98000,
-+ LAvecbin_VSRL_B = 0x70ea0000,
-+ LAvecbin_VSRL_H = 0x70ea8000,
-+ LAvecbin_VSRL_W = 0x70eb0000,
-+ LAvecbin_VSRL_D = 0x70eb8000,
-+ LAvecbin_VSRA_B = 0x70ec0000,
-+ LAvecbin_VSRA_H = 0x70ec8000,
-+ LAvecbin_VSRA_W = 0x70ed0000,
-+ LAvecbin_VSRA_D = 0x70ed8000,
-+ LAvecbin_VILVL_B = 0x711a0000,
-+ LAvecbin_VILVL_H = 0x711a8000,
-+ LAvecbin_VILVL_W = 0x711b0000,
-+ LAvecbin_VILVL_D = 0x711b8000,
-+ LAvecbin_VILVH_B = 0x711c0000,
-+ LAvecbin_VILVH_H = 0x711c8000,
-+ LAvecbin_VILVH_W = 0x711d0000,
-+ LAvecbin_VILVH_D = 0x711d8000,
-+ LAvecbin_VPICKEV_B = 0x711e0000,
-+ LAvecbin_VPICKEV_H = 0x711e8000,
-+ LAvecbin_VPICKEV_W = 0x711f0000,
-+ LAvecbin_VPICKOD_B = 0x71200000,
-+ LAvecbin_VPICKOD_H = 0x71208000,
-+ LAvecbin_VPICKOD_W = 0x71210000,
-+ LAvecbin_VREPLVE_B = 0x71220000,
-+ LAvecbin_VREPLVE_H = 0x71228000,
-+ LAvecbin_VREPLVE_W = 0x71230000,
-+ LAvecbin_VREPLVE_D = 0x71238000,
-+ LAvecbin_VAND_V = 0x71260000,
-+ LAvecbin_VOR_V = 0x71268000,
-+ LAvecbin_VXOR_V = 0x71270000,
-+ LAvecbin_VNOR_V = 0x71278000,
-+ LAvecbin_VADD_Q = 0x712d0000,
-+ LAvecbin_VSUB_Q = 0x712d8000,
-+ LAvecbin_VFADD_S = 0x71308000,
-+ LAvecbin_VFADD_D = 0x71310000,
-+ LAvecbin_VFSUB_S = 0x71328000,
-+ LAvecbin_VFSUB_D = 0x71330000,
-+ LAvecbin_VFMUL_S = 0x71388000,
-+ LAvecbin_VFMUL_D = 0x71390000,
-+ LAvecbin_VFDIV_S = 0x713a8000,
-+ LAvecbin_VFDIV_D = 0x713b0000,
-+ LAvecbin_VFMAX_S = 0x713c8000,
-+ LAvecbin_VFMAX_D = 0x713d0000,
-+ LAvecbin_VFMIN_S = 0x713e8000,
-+ LAvecbin_VFMIN_D = 0x713f0000,
-+ LAvecbin_VBSLL_V = 0x728e0000,
-+ LAvecbin_VBSRL_V = 0x728e8000,
-+ LAvecbin_VINSGR2VR_B = 0x72eb8000,
-+ LAvecbin_VINSGR2VR_H = 0x72ebc000,
-+ LAvecbin_VINSGR2VR_W = 0x72ebe000,
-+ LAvecbin_VINSGR2VR_D = 0x72ebf000,
-+ LAvecbin_VPICKVE2GR_W = 0x72efe000,
-+ LAvecbin_VPICKVE2GR_D = 0x72eff000,
-+ LAvecbin_VPICKVE2GR_BU = 0x72f38000,
-+ LAvecbin_VPICKVE2GR_HU = 0x72f3c000,
-+ LAvecbin_VPICKVE2GR_WU = 0x72f3e000,
-+ LAvecbin_VPICKVE2GR_DU = 0x72f3f000,
-+ LAvecbin_VSLLI_B = 0x732c2000,
-+ LAvecbin_VSLLI_H = 0x732c4000,
-+ LAvecbin_VSLLI_W = 0x732c8000,
-+ LAvecbin_VSLLI_D = 0x732d0000,
-+ LAvecbin_VSRLI_B = 0x73302000,
-+ LAvecbin_VSRLI_H = 0x73304000,
-+ LAvecbin_VSRLI_W = 0x73308000,
-+ LAvecbin_VSRLI_D = 0x73310000,
-+ LAvecbin_VSRAI_B = 0x73342000,
-+ LAvecbin_VSRAI_H = 0x73344000,
-+ LAvecbin_VSRAI_W = 0x73348000,
-+ LAvecbin_VSRAI_D = 0x73350000,
-+ LAvecbin_VORI_B = 0x73d40000
-+} LOONGARCH64VecBinOp;
++static Bool disInstr_LOONGARCH64_WRK_01_1101_0001 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+/* Tags for vector load operations */
-+typedef enum {
-+ LAvecload_VLD = 0x2c000000,
-+ LAvecload_VLDX = 0x38400000
-+} LOONGARCH64VecLoadOp;
++ switch (SLICE(insn, 21, 18)) {
++ case 0b0000:
++ ok = gen_xvaddw_xvsubw_x_x_x(dres, insn, archinfo, abiinfo); break;
++ case 0b0001: case 0b0010:
++ case 0b0011:
++ ok = gen_xvsadd_xvssub(dres, insn, archinfo, abiinfo); break;
++ case 0b0101: case 0b0110:
++ ok = gen_xvhaddw_xvhsubw(dres, insn, archinfo, abiinfo); break;
++ case 0b1000:
++ ok = gen_xvabsd(dres, insn, archinfo, abiinfo); break;
++ case 0b0111:
++ ok = gen_xvadda(dres, insn, archinfo, abiinfo); break;
++ case 0b1001: case 0b1010:
++ ok = gen_xvavg(dres, insn, archinfo, abiinfo); break;
++ case 0b1100: case 0b1101:
++ ok = gen_xvmax_xvmin(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
+
-+/* Tags for vector store operations */
-+typedef enum {
-+ LAvecstore_VST = 0x2c400000,
-+ LAvecstore_VSTX = 0x38440000
-+} LOONGARCH64VecStoreOp;
++ return ok;
++}
+
-+/* Tags for extra operations, we only use them when emiting code directly */
-+typedef enum {
-+ LAextra_MOVGR2CF = 0x0114d800,
-+ LAextra_MOVCF2GR = 0x0114dc00,
-+ LAextra_SLT = 0x00120000,
-+ LAextra_SLTU = 0x00128000,
-+ LAextra_MASKEQZ = 0x00130000,
-+ LAextra_MASKNEZ = 0x00138000,
-+ LAextra_SLTI = 0x02000000,
-+ LAextra_SLTUI = 0x02400000,
-+ LAextra_LU52I_D = 0x03000000,
-+ LAextra_FSEL = 0x0d000000,
-+ LAextra_LU12I_W = 0x14000000,
-+ LAextra_LU32I_D = 0x16000000,
-+ LAextra_JIRL = 0x4c000000,
-+ LAextra_B = 0x50000000,
-+ LAextra_BEQ = 0x58000000,
-+ LAextra_BNE = 0x5c000000,
-+ LAextra_BGE = 0x64000000
-+} LOONGARCH64ExtraOp;
++static Bool disInstr_LOONGARCH64_WRK_01_1101_0010 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+/* Tags for instructions */
-+typedef enum {
-+ /* Pseudo-insn, used for generating a 64-bit
-+ literal to register */
-+ LAin_LI, /* load imm */
++ switch (SLICE(insn, 21, 18)) {
++ case 0b0001: case 0b0010:
++ ok = gen_xvmu(dres, insn, archinfo, abiinfo); break;
++ case 0b0100: case 0b0110:
++ ok = gen_xvmulw(dres, insn, archinfo, abiinfo); break;
++ case 0b1000:
++ ok = gen_xvmulw_x_x_x(dres, insn, archinfo, abiinfo); break;
++ case 0b1010:
++ ok = gen_xvmadd_xvmsub(dres, insn, archinfo, abiinfo); break;
++ case 0b1011: case 0b1101:
++ ok = gen_xvmaddw(dres, insn, archinfo, abiinfo); break;
++ case 0b1111:
++ ok = gen_xvmaddw_x_x_x(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
-+ /* Integer insns */
-+ LAin_Un, /* unary */
-+ LAin_Bin, /* binary */
-+ LAin_Load, /* load */
-+ LAin_Store, /* store */
-+ LAin_LLSC, /* ll/sc */
-+ LAin_Bar, /* barrier */
++ return ok;
++}
+
-+ /* Floating point insns */
-+ LAin_FpUn, /* floating point unary */
-+ LAin_FpBin, /* floating point binary */
-+ LAin_FpTri, /* floating point trinary */
-+ LAin_FpLoad, /* floating point load */
-+ LAin_FpStore, /* floating point store */
-+ LAin_FpMove, /* floating point move */
-+ LAin_FpCmp, /* floating point compare */
++static Bool disInstr_LOONGARCH64_WRK_01_1101_0011 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+ /* Vector insns */
-+ LAin_VecUn, /* vector unary */
-+ LAin_VecBin, /* vector binary */
-+ LAin_VecLoad, /* vector load */
-+ LAin_VecStore, /* vector store */
++ switch (SLICE(insn, 21, 18)) {
++ case 0b1000: case 0b1001:
++ ok = gen_xvdiv(dres, insn, archinfo, abiinfo); break;
++ case 0b1010: case 0b1011:
++ ok = gen_xvshift(dres, insn, archinfo, abiinfo); break;
++ case 0b1100:
++ ok = gen_xvsrlr(dres, insn, archinfo, abiinfo); break;
++ case 0b1101:
++ ok = gen_xvsrlan(dres, insn, archinfo, abiinfo); break;
++ case 0b1110:
++ ok = gen_xvsrlarn(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
-+ /* Pseudo-insn */
-+ LAin_Cas, /* compare and swap */
-+ LAin_Cmp, /* word compare */
-+ LAin_CMove, /* condition move */
++ return ok;
++}
+
-+ /* Call target (an absolute address), on given
-+ condition (which could be LAcc_AL). */
-+ LAin_Call, /* call */
++static Bool disInstr_LOONGARCH64_WRK_01_1101_0100 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+ /* The following 5 insns are mandated by translation chaining */
-+ LAin_XDirect, /* direct transfer to GA */
-+ LAin_XIndir, /* indirect transfer to GA */
-+ LAin_XAssisted, /* assisted transfer to GA */
-+ LAin_EvCheck, /* Event check */
-+ LAin_ProfInc /* 64-bit profile counter increment */
-+} LOONGARCH64InstrTag;
++ switch (SLICE(insn, 21, 17)) {
++ case 0b00110: case 0b00111: case 0b01000:
++ ok = gen_xvbitops(dres, insn, archinfo, abiinfo); break;
++ case 0b01011: case 0b01100:
++ case 0b01101: case 0b01110:
++ case 0b01111: case 0b10000:
++ ok = gen_xevod(dres, insn, archinfo, abiinfo); break;
++ case 0b10001:
++ ok = gen_xvreplve(dres, insn, archinfo, abiinfo); break;
++ case 0b10011: case 0b10100:
++ ok = gen_logical_xv(dres, insn, archinfo, abiinfo); break;
++ case 0b10110:
++ ok = gen_xvadd_xvsub_q(dres, insn, archinfo, abiinfo); break;
++ case 0b10111:
++ ok = gen_xvsigncov(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
-+typedef struct {
-+ LOONGARCH64InstrTag tag;
-+ union {
-+ struct {
-+ ULong imm;
-+ HReg dst;
-+ } LI;
-+ struct {
-+ LOONGARCH64UnOp op;
-+ HReg src;
-+ HReg dst;
-+ } Unary;
-+ struct {
-+ LOONGARCH64BinOp op;
-+ LOONGARCH64RI* src2;
-+ HReg src1;
-+ HReg dst;
-+ } Binary;
-+ struct {
-+ LOONGARCH64LoadOp op;
-+ LOONGARCH64AMode* src;
-+ HReg dst;
-+ } Load;
-+ struct {
-+ LOONGARCH64StoreOp op;
-+ LOONGARCH64AMode* dst;
-+ HReg src;
-+ } Store;
-+ struct {
-+ LOONGARCH64LLSCOp op;
-+ Bool isLoad;
-+ LOONGARCH64AMode* addr;
-+ HReg val;
-+ } LLSC;
-+ struct {
-+ LOONGARCH64BarOp op;
-+ UShort hint;
-+ } Bar;
-+ struct {
-+ LOONGARCH64FpUnOp op;
-+ HReg src;
-+ HReg dst;
-+ } FpUnary;
-+ struct {
-+ LOONGARCH64FpBinOp op;
-+ HReg src2;
-+ HReg src1;
-+ HReg dst;
-+ } FpBinary;
-+ struct {
-+ LOONGARCH64FpTriOp op;
-+ HReg src3;
-+ HReg src2;
-+ HReg src1;
-+ HReg dst;
-+ } FpTrinary;
-+ struct {
-+ LOONGARCH64FpLoadOp op;
-+ LOONGARCH64AMode* src;
-+ HReg dst;
-+ } FpLoad;
-+ struct {
-+ LOONGARCH64FpStoreOp op;
-+ LOONGARCH64AMode* dst;
-+ HReg src;
-+ } FpStore;
-+ struct {
-+ LOONGARCH64FpMoveOp op;
-+ HReg src;
-+ HReg dst;
-+ } FpMove;
-+ struct {
-+ LOONGARCH64FpCmpOp op;
-+ HReg src2;
-+ HReg src1;
-+ HReg dst;
-+ } FpCmp;
-+ struct {
-+ LOONGARCH64VecUnOp op;
-+ HReg src;
-+ HReg dst;
-+ } VecUnary;
-+ struct {
-+ LOONGARCH64VecBinOp op;
-+ LOONGARCH64RI* src2;
-+ HReg src1;
-+ HReg dst;
-+ } VecBinary;
-+ struct {
-+ LOONGARCH64VecLoadOp op;
-+ LOONGARCH64AMode* src;
-+ HReg dst;
-+ } VecLoad;
-+ struct {
-+ LOONGARCH64VecStoreOp op;
-+ LOONGARCH64AMode* dst;
-+ HReg src;
-+ } VecStore;
-+ struct {
-+ HReg old;
-+ HReg addr;
-+ HReg expd;
-+ HReg data;
-+ Bool size64;
-+ } Cas;
-+ struct {
-+ LOONGARCH64CondCode cond;
-+ HReg dst;
-+ HReg src1;
-+ HReg src2;
-+ } Cmp;
-+ struct {
-+ HReg cond;
-+ HReg r0;
-+ HReg r1;
-+ HReg dst;
-+ Bool isInt;
-+ } CMove;
-+ struct {
-+ HReg cond;
-+ Addr64 target;
-+ UInt nArgRegs;
-+ RetLoc rloc;
-+ } Call;
-+ struct {
-+ Addr64 dstGA;
-+ LOONGARCH64AMode* amPC;
-+ HReg cond;
-+ Bool toFastEP;
-+ } XDirect;
-+ struct {
-+ HReg dstGA;
-+ LOONGARCH64AMode* amPC;
-+ HReg cond;
-+ } XIndir;
-+ struct {
-+ HReg dstGA;
-+ LOONGARCH64AMode* amPC;
-+ HReg cond;
-+ IRJumpKind jk;
-+ } XAssisted;
-+ struct {
-+ LOONGARCH64AMode* amCounter;
-+ LOONGARCH64AMode* amFailAddr;
-+ } EvCheck;
-+ struct {
-+ /* No fields. The address of the counter to inc is
-+ installed later, post-translation, by patching it in,
-+ as it is not known at translation time. */
-+ } ProfInc;
-+ } LAin;
-+} LOONGARCH64Instr;
++ return ok;
++}
+
-+extern LOONGARCH64Instr* LOONGARCH64Instr_LI ( ULong imm, HReg dst );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_Unary ( LOONGARCH64UnOp op,
-+ HReg src, HReg dst );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_Binary ( LOONGARCH64BinOp op,
-+ LOONGARCH64RI* src2,
-+ HReg src1, HReg dst );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_Load ( LOONGARCH64LoadOp op,
-+ LOONGARCH64AMode* src,
-+ HReg dst );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_Store ( LOONGARCH64StoreOp op,
-+ LOONGARCH64AMode* dst,
-+ HReg src );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_LLSC ( LOONGARCH64LLSCOp op,
-+ Bool isLoad,
-+ LOONGARCH64AMode* addr,
-+ HReg val );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_Bar ( LOONGARCH64BarOp op,
-+ UShort hint );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_FpUnary ( LOONGARCH64FpUnOp op,
-+ HReg src, HReg dst );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_FpBinary ( LOONGARCH64FpBinOp op,
-+ HReg src2, HReg src1,
-+ HReg dst );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_FpTrinary ( LOONGARCH64FpTriOp op,
-+ HReg src3, HReg src2,
-+ HReg src1, HReg dst );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_FpLoad ( LOONGARCH64FpLoadOp op,
-+ LOONGARCH64AMode* src,
-+ HReg dst );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_FpStore ( LOONGARCH64FpStoreOp op,
-+ LOONGARCH64AMode* dst,
-+ HReg src );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_FpMove ( LOONGARCH64FpMoveOp op,
-+ HReg src, HReg dst );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_FpCmp ( LOONGARCH64FpCmpOp op,
-+ HReg src2, HReg src1,
-+ HReg dst );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_VecUnary ( LOONGARCH64VecUnOp op,
-+ HReg src, HReg dst );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_VecBinary ( LOONGARCH64VecBinOp op,
-+ LOONGARCH64RI* src2,
-+ HReg src1, HReg dst );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_VecLoad ( LOONGARCH64VecLoadOp op,
-+ LOONGARCH64AMode* src,
-+ HReg dst );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_VecStore ( LOONGARCH64VecStoreOp op,
-+ LOONGARCH64AMode* dst,
-+ HReg src );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_Cas ( HReg old, HReg addr,
-+ HReg expd, HReg data,
-+ Bool size64 );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_Cmp ( LOONGARCH64CondCode cond,
-+ HReg src2, HReg src1,
-+ HReg dst );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_CMove ( HReg cond, HReg r0, HReg r1,
-+ HReg dst, Bool isInt );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_Call ( HReg cond, Addr64 target,
-+ UInt nArgRegs, RetLoc rloc );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_XDirect ( Addr64 dstGA,
-+ LOONGARCH64AMode* amPC,
-+ HReg cond, Bool toFastEP );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_XIndir ( HReg dstGA,
-+ LOONGARCH64AMode* amPC,
-+ HReg cond );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_XAssisted ( HReg dstGA,
-+ LOONGARCH64AMode* amPC,
-+ HReg cond, IRJumpKind jk );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_EvCheck ( LOONGARCH64AMode* amCounter,
-+ LOONGARCH64AMode* amFailAddr );
-+extern LOONGARCH64Instr* LOONGARCH64Instr_ProfInc ( void );
++static Bool disInstr_LOONGARCH64_WRK_01_1101_0101 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+extern void ppLOONGARCH64Instr ( const LOONGARCH64Instr* i, Bool mode64 );
++ switch (SLICE(insn, 21, 18)) {
++ case 0b1110:
++ ok = gen_xvshuf(dres, insn, archinfo, abiinfo); break;
++ case 0b1111:
++ ok = gen_xvperm_w(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
-+/* Some functions that insulate the register allocator from details
-+ of the underlying instruction set. */
-+extern void getRegUsage_LOONGARCH64Instr ( HRegUsage* u,
-+ const LOONGARCH64Instr* i,
-+ Bool mode64 );
-+extern void mapRegs_LOONGARCH64Instr ( HRegRemap* m, LOONGARCH64Instr* i,
-+ Bool mode64 );
-+extern Int emit_LOONGARCH64Instr (/*MB_MOD*/Bool* is_profInc,
-+ UChar* buf,
-+ Int nbuf,
-+ const LOONGARCH64Instr* i,
-+ Bool mode64,
-+ VexEndness endness_host,
-+ const void* disp_cp_chain_me_to_slowEP,
-+ const void* disp_cp_chain_me_to_fastEP,
-+ const void* disp_cp_xindir,
-+ const void* disp_cp_xassisted );
++ return ok;
++}
+
-+extern void genSpill_LOONGARCH64 ( /*OUT*/ HInstr** i1, /*OUT*/ HInstr** i2,
-+ HReg rreg, Int offsetB, Bool mode64);
-+extern void genReload_LOONGARCH64 ( /*OUT*/ HInstr** i1, /*OUT*/ HInstr** i2,
-+ HReg rreg, Int offsetB, Bool mode64);
-+extern LOONGARCH64Instr* genMove_LOONGARCH64 ( HReg from, HReg to,
-+ Bool mode64 );
++static Bool disInstr_LOONGARCH64_WRK_01_1101_1010_0111 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+extern const RRegUniverse* getRRegUniverse_LOONGARCH64 ( void );
++ switch (SLICE(insn, 17, 14)) {
++ case 0b0000:
++ ok = gen_xvcount(dres, insn, archinfo, abiinfo); break;
++ case 0b0001:
++ ok = gen_xvmsk(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0010:
++ ok = gen_xvset(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1011:
++ ok = gen_xvexth(dres, insn, archinfo, abiinfo); break;
++ case 0b1100:
++ if (SLICE(insn, 13, 12) == 0b00)
++ ok = gen_xvreplgr2vr(dres, insn, archinfo, abiinfo);
++ else
++ ok = gen_vext2xv(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
+
-+extern HInstrArray* iselSB_LOONGARCH64 ( const IRSB*,
-+ VexArch,
-+ const VexArchInfo*,
-+ const VexAbiInfo*,
-+ Int offs_Host_EvC_Counter,
-+ Int offs_Host_EvC_FailAddr,
-+ Bool chainingAllowed,
-+ Bool addProfInc,
-+ Addr max_ga );
++ return ok;
++}
+
-+/* How big is an event check? See case for Min_EvCheck in
-+ emit_LOONGARCH64Instr just above. That crosschecks what this returns,
-+ so we can tell if we're inconsistent. */
-+extern Int evCheckSzB_LOONGARCH64 ( void );
++static Bool disInstr_LOONGARCH64_WRK_01_1101_1010 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+/* NB: what goes on here has to be very closely coordinated with the
-+ emitInstr case for XDirect, above. */
-+extern VexInvalRange chainXDirect_LOONGARCH64 ( VexEndness endness_host,
-+ void* place_to_chain,
-+ const void* disp_cp_chain_me_EXPECTED,
-+ const void* place_to_jump_to );
++ switch (SLICE(insn, 21, 17)) {
++ case 0b00000: case 0b00001:
++ case 0b00010: case 0b00011:
++ case 0b00100:
++ ok = gen_xvcmpi(dres, insn, archinfo, abiinfo); break;
++ case 0b00101: case 0b00110:
++ ok = gen_xvaddi_xvsubi(dres, insn, archinfo, abiinfo); break;
++ case 0b01000: case 0b01001:
++ case 0b01010: case 0b01011:
++ ok = gen_xvmaxi_xvmini(dres, insn, archinfo, abiinfo); break;
++ case 0b01101:
++ ok = gen_xvfrstpi(dres, insn, archinfo, abiinfo); break;
++ case 0b01110: case 0b01111:
++ ok = disInstr_LOONGARCH64_WRK_01_1101_1010_0111(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b10000: case 0b10010: case 0b10100:
++ ok = gen_xvsrlri(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
-+/* NB: what goes on here has to be very closely coordinated with the
-+ emitInstr case for XDirect, above. */
-+extern VexInvalRange unchainXDirect_LOONGARCH64 ( VexEndness endness_host,
-+ void* place_to_unchain,
-+ const void* place_to_jump_to_EXPECTED,
-+ const void* disp_cp_chain_me );
++ return ok;
++}
+
-+/* Patch the counter address into a profile inc point, as previously
-+ created by the Min_ProfInc case for emit_LOONGARCH64Instr. */
-+extern VexInvalRange patchProfInc_LOONGARCH64 ( VexEndness endness_host,
-+ void* place_to_patch,
-+ const ULong* location_of_counter );
++static Bool disInstr_LOONGARCH64_WRK_01_1101_1011 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+#endif /* ndef __VEX_HOST_LOONGARCH64_DEFS_H */
++ switch (SLICE(insn, 21, 18)) {
++ case 0b1010:
++ ok = gen_xvinsgr2vr(dres, insn, archinfo, abiinfo); break;
++ case 0b1011: case 0b1100:
++ ok = gen_xvpickve2gr(dres, insn, archinfo, abiinfo); break;
++ case 0b1101:
++ ok = gen_xvrepl128vei(dres, insn, archinfo, abiinfo); break;
++ case 0b1111:
++ ok = gen_xvinsve0(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
++ return ok;
++}
+
-+/*---------------------------------------------------------------*/
-+/*--- end host-loongarch64_defs.h ---*/
-+/*---------------------------------------------------------------*/
-diff --git a/VEX/priv/host_loongarch64_isel.c b/VEX/priv/host_loongarch64_isel.c
-new file mode 100644
-index 0000000..d60a2b3
---- /dev/null
-+++ b/VEX/priv/host_loongarch64_isel.c
-@@ -0,0 +1,3748 @@
++static Bool disInstr_LOONGARCH64_WRK_01_1101_1100 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+/*---------------------------------------------------------------*/
-+/*--- begin host_loongarch64_isel.c ---*/
-+/*---------------------------------------------------------------*/
++ switch (SLICE(insn, 21, 18)) {
++ case 0b0000:
++ ok = gen_xvpickve(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0001:
++ ok = gen_xvreplve0(dres, insn, archinfo, abiinfo); break;
++ case 0b0010: case 0b0011:
++ ok = gen_xvsllwil(dres, insn, archinfo, abiinfo); break;
++ case 0b0100: case 0b0101: case 0b0110:
++ ok = gen_xvbitops_imm(dres, insn, archinfo, abiinfo); break;
++ case 0b1001: case 0b1010:
++ ok = gen_xvsat(dres, insn, archinfo, abiinfo); break;
++ case 0b1011: case 0b1100:
++ case 0b1101:
++ ok = gen_xvshift_imm(dres, insn, archinfo, abiinfo); break;
++ default:
++ ok = False;
++ break;
++ }
+
-+/*
-+ This file is part of Valgrind, a dynamic binary instrumentation
-+ framework.
++ return ok;
++}
+
-+ Copyright (C) 2021-2022 Loongson Technology Corporation Limited
++static Bool disInstr_LOONGARCH64_WRK_01_1101_1101 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+ This program is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License as
-+ published by the Free Software Foundation; either version 2 of the
-+ License, or (at your option) any later version.
++ switch (SLICE(insn, 21, 18)) {
++ case 0b0000: case 0b0110:
++ ok = gen_xvsrlani(dres, insn, archinfo, abiinfo); break;
++ case 0b0001: case 0b0111:
++ ok = gen_xvsrlarni(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
-+ This program is distributed in the hope that it will be useful, but
-+ WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ General Public License for more details->
++ return ok;
++}
+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, see .
++static Bool disInstr_LOONGARCH64_WRK_01_1101_1110 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+ The GNU General Public License is contained in the file COPYING.
-+*/
++ switch (SLICE(insn, 21, 20)) {
++ case 0b00:
++ ok = gen_xvextrins(dres, insn, archinfo, abiinfo); break;
++ case 0b01:
++ ok = gen_xvshuf4i(dres, insn, archinfo, abiinfo); break;
++ default: ok = False; break;
++ }
+
-+#include "libvex_basictypes.h"
-+#include "libvex_ir.h"
-+#include "libvex.h"
++ return ok;
++}
+
-+#include "main_util.h"
-+#include "main_globals.h"
-+#include "host_generic_regs.h"
-+#include "host_loongarch64_defs.h"
++static Bool disInstr_LOONGARCH64_WRK_01_1101_1111 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
++ switch (SLICE(insn, 21, 18)) {
++ case 0b0001:
++ ok = gen_xvbitseli(dres, insn, archinfo, abiinfo); break;
++ case 0b0100: case 0b0101:
++ case 0b0110: case 0b0111:
++ ok = gen_xvlogical_u8(dres, insn, archinfo, abiinfo); break;
++ case 0b1001:
++ case 0b1010:
++ case 0b1011:
++ ok = gen_xvpermi(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1000:
++ ok = gen_vldi(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
+
-+/*---------------------------------------------------------*/
-+/*--- ISelEnv ---*/
-+/*---------------------------------------------------------*/
++ return ok;
++}
+
-+/* This carries around:
++static Bool disInstr_LOONGARCH64_WRK_01_1101 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+ - A mapping from IRTemp to IRType, giving the type of any IRTemp we
-+ might encounter. This is computed before insn selection starts,
-+ and does not change.
++ switch (SLICE(insn, 25, 22)) {
++ case 0b0000:
++ ok = disInstr_LOONGARCH64_WRK_01_1101_0000(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0001:
++ ok = disInstr_LOONGARCH64_WRK_01_1101_0001(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0010:
++ ok = disInstr_LOONGARCH64_WRK_01_1101_0010(dres, insn, archinfo, abiinfo); break;
++ case 0b0011:
++ ok = disInstr_LOONGARCH64_WRK_01_1101_0011(dres, insn, archinfo, abiinfo); break;
++ case 0b0100:
++ ok = disInstr_LOONGARCH64_WRK_01_1101_0100(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101:
++ ok = disInstr_LOONGARCH64_WRK_01_1101_0101(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1010:
++ ok = disInstr_LOONGARCH64_WRK_01_1101_1010(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1011:
++ ok = disInstr_LOONGARCH64_WRK_01_1101_1011(dres, insn, archinfo, abiinfo); break;
++ case 0b1100:
++ ok = disInstr_LOONGARCH64_WRK_01_1101_1100(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101:
++ ok = disInstr_LOONGARCH64_WRK_01_1101_1101(dres, insn, archinfo, abiinfo); break;
++ case 0b1110:
++ ok = disInstr_LOONGARCH64_WRK_01_1101_1110(dres, insn, archinfo, abiinfo); break;
++ case 0b1111:
++ ok = disInstr_LOONGARCH64_WRK_01_1101_1111(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
+
-+ - A mapping from IRTemp to HReg. This tells the insn selector
-+ which virtual register is associated with each IRTemp temporary.
-+ This is computed before insn selection starts, and does not
-+ change. We expect this mapping to map precisely the same set of
-+ IRTemps as the type mapping does.
++ return ok;
++}
+
-+ |vregmap| holds the primary register for the IRTemp.
-+ |vregmapHI| is only used for 128-bit integer-typed
-+ IRTemps. It holds the identity of a second
-+ 64-bit virtual HReg, which holds the high half
-+ of the value.
++static Bool disInstr_LOONGARCH64_WRK_01 ( DisResult* dres, UInt insn,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo )
++{
++ Bool ok;
+
-+ - The code array, that is, the insns selected so far.
++ switch (SLICE(insn, 29, 26)) {
++ case 0b0000:
++ ok = gen_beqz(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0001:
++ ok = gen_bnez(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0010:
++ switch (SLICE(insn, 9, 8)) {
++ case 0b00:
++ ok = gen_bceqz(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01:
++ ok = gen_bcnez(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ break;
++ case 0b0011:
++ ok = gen_jirl(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0100:
++ ok = gen_b(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0101:
++ ok = gen_bl(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0110:
++ ok = gen_beq(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b0111:
++ ok = gen_bne(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1000:
++ ok = gen_blt(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1001:
++ ok = gen_bge(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1010:
++ ok = gen_bltu(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1011:
++ ok = gen_bgeu(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1100:
++ ok = disInstr_LOONGARCH64_WRK_01_1100(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b1101:
++ ok = disInstr_LOONGARCH64_WRK_01_1101(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
+
-+ - A counter, for generating new virtual registers.
++ return ok;
++}
+
-+ - The host hardware capabilities word. This is set at the start
-+ and does not change.
++static Bool disInstr_LOONGARCH64_WRK ( /*MB_OUT*/DisResult* dres,
++ const UChar* guest_instr,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo,
++ Bool sigill_diag )
++{
++ /* Set result defaults. */
++ dres->whatNext = Dis_Continue;
++ dres->len = 4;
++ dres->jk_StopHere = Ijk_INVALID;
++ dres->hint = Dis_HintNone;
+
-+ - A Bool for indicating whether we may generate chain-me
-+ instructions for control flow transfers, or whether we must use
-+ XAssisted.
++ /* At least this is simple on LOONGARCH64: insns are all 4 bytes long,
++ and 4-aligned. So just fish the whole thing out of memory right now
++ and have done. */
++ UInt insn = getUInt(guest_instr);
++ DIP("\t0x%llx:\t0x%08x\t", (Addr64)guest_PC_curr_instr, insn);
++ vassert((guest_PC_curr_instr & 3ULL) == 0);
+
-+ - The maximum guest address of any guest insn in this block.
-+ Actually, the address of the highest-addressed byte from any insn
-+ in this block. Is set at the start and does not change. This is
-+ used for detecting jumps which are definitely forward-edges from
-+ this block, and therefore can be made (chained) to the fast entry
-+ point of the destination, thereby avoiding the destination's
-+ event check.
++ /* Spot "Special" instructions (see comment at top of file). */
++ Bool ok = disInstr_LOONGARCH64_WRK_special(dres, guest_instr);
++ if (ok)
++ return ok;
+
-+ - An IRExpr*, which may be NULL, holding the IR expression (an
-+ IRRoundingMode-encoded value) to which the FPU's rounding mode
-+ was most recently set. Setting to NULL is always safe. Used to
-+ avoid redundant settings of the FPU's rounding mode, as
-+ described in set_FPCR_rounding_mode below.
++ /* Main LOONGARCH64 instruction decoder starts here. */
++ switch (SLICE(insn, 31, 30)) {
++ case 0b00:
++ ok = disInstr_LOONGARCH64_WRK_00(dres, insn, archinfo, abiinfo);
++ break;
++ case 0b01:
++ ok = disInstr_LOONGARCH64_WRK_01(dres, insn, archinfo, abiinfo);
++ break;
++ default:
++ ok = False;
++ break;
++ }
+
-+ Note, this is all (well, mostly) host-independent.
-+*/
++ /* If the next-level down decoders failed, make sure |dres| didn't
++ get changed. */
++ if (!ok) {
++ vassert(dres->whatNext == Dis_Continue);
++ vassert(dres->len == 4);
++ vassert(dres->jk_StopHere == Ijk_INVALID);
++ }
++ return ok;
++}
+
-+typedef
-+ struct {
-+ /* Constant -- are set at the start and do not change. */
-+ IRTypeEnv* type_env;
+
-+ HReg* vregmap;
-+ HReg* vregmapHI;
-+ Int n_vregmap;
++/*------------------------------------------------------------*/
++/*--- Top-level fn ---*/
++/*------------------------------------------------------------*/
+
-+ UInt hwcaps;
++/* Disassemble a single instruction into IR. The instruction
++ is located in host memory at &guest_code[delta]. */
+
-+ Bool chainingAllowed;
-+ Addr64 max_ga;
++DisResult disInstr_LOONGARCH64 ( IRSB* irsb_IN,
++ const UChar* guest_code_IN,
++ Long delta_IN,
++ Addr guest_IP,
++ VexArch guest_arch,
++ const VexArchInfo* archinfo,
++ const VexAbiInfo* abiinfo,
++ VexEndness host_endness_IN,
++ Bool sigill_diag_IN )
++{
++ DisResult dres;
++ vex_bzero(&dres, sizeof(dres));
+
-+ /* These are modified as we go along. */
-+ HInstrArray* code;
-+ Int vreg_ctr;
-+ }
-+ ISelEnv;
++ /* Set globals (see top of this file) */
++ vassert(guest_arch == VexArchLOONGARCH64);
+
++ irsb = irsb_IN;
++ host_endness = host_endness_IN;
++ guest_PC_curr_instr = (Addr64)guest_IP;
+
-+static HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp )
-+{
-+ vassert(tmp < env->n_vregmap);
-+ return env->vregmap[tmp];
-+}
++ /* Try to decode */
++ Bool ok = disInstr_LOONGARCH64_WRK(&dres,
++ &guest_code_IN[delta_IN],
++ archinfo, abiinfo, sigill_diag_IN);
+
-+static void lookupIRTempPair ( HReg* vrHI, HReg* vrLO,
-+ ISelEnv* env, IRTemp tmp )
-+{
-+ vassert(tmp < env->n_vregmap);
-+ vassert(!hregIsInvalid(env->vregmapHI[tmp]));
-+ *vrLO = env->vregmap[tmp];
-+ *vrHI = env->vregmapHI[tmp];
-+}
++ if (ok) {
++ /* All decode successes end up here. */
++ vassert(dres.len == 4 || dres.len == 20);
++ switch (dres.whatNext) {
++ case Dis_Continue:
++ putPC(mkU64(dres.len + guest_PC_curr_instr));
++ break;
++ case Dis_StopHere:
++ break;
++ default:
++ vassert(0);
++ break;
++ }
++ DIP("\n");
++ } else {
++ /* All decode failures end up here. */
++ if (sigill_diag_IN) {
++ Int i, j;
++ UChar buf[64];
++ UInt insn = getUInt(&guest_code_IN[delta_IN]);
++ vex_bzero(buf, sizeof(buf));
++ for (i = j = 0; i < 32; i++) {
++ if (i > 0 && (i & 3) == 0)
++ buf[j++] = ' ';
++ buf[j++] = (insn & (1 << (31 - i))) ? '1' : '0';
++ }
++ vex_printf("disInstr(loongarch64): unhandled instruction 0x%08x\n", insn);
++ vex_printf("disInstr(loongarch64): %s\n", buf);
++ }
+
-+static void addInstr ( ISelEnv* env, LOONGARCH64Instr* instr )
-+{
-+ addHInstr(env->code, instr);
-+ if (vex_traceflags & VEX_TRACE_VCODE) {
-+ ppLOONGARCH64Instr(instr, True);
-+ vex_printf("\n");
++ /* Tell the dispatcher that this insn cannot be decoded, and so
++ has not been executed, and (is currently) the next to be
++ executed. PC should be up-to-date since it is made so at the
++ start of each insn, but nevertheless be paranoid and update
++ it again right now. */
++ putPC(mkU64(guest_PC_curr_instr));
++ dres.len = 0;
++ dres.whatNext = Dis_StopHere;
++ dres.jk_StopHere = Ijk_NoDecode;
+ }
-+}
-+
-+static HReg newVRegI ( ISelEnv* env )
-+{
-+ HReg reg = mkHReg(True/*virtual reg*/, HRcInt64, 0, env->vreg_ctr);
-+ env->vreg_ctr++;
-+ return reg;
-+}
-+
-+static HReg newVRegF ( ISelEnv* env )
-+{
-+ HReg reg = mkHReg(True/*virtual reg*/, HRcFlt64, 0, env->vreg_ctr);
-+ env->vreg_ctr++;
-+ return reg;
-+}
+
-+static HReg newVRegV ( ISelEnv* env )
-+{
-+ HReg reg = mkHReg(True/*virtual reg*/, HRcVec128, 0, env->vreg_ctr);
-+ env->vreg_ctr++;
-+ return reg;
++ return dres;
+}
+
+
-+/*---------------------------------------------------------*/
-+/*--- ISEL: Forward declarations ---*/
-+/*---------------------------------------------------------*/
++/*--------------------------------------------------------------------*/
++/*--- end guest_loongarch64_toIR.c ---*/
++/*--------------------------------------------------------------------*/
+diff --git a/VEX/priv/host_loongarch64_defs.c b/VEX/priv/host_loongarch64_defs.c
+new file mode 100644
+index 0000000..269b910
+--- /dev/null
++++ b/VEX/priv/host_loongarch64_defs.c
+@@ -0,0 +1,3953 @@
+
-+/* These are organised as iselXXX and iselXXX_wrk pairs. The
-+ iselXXX_wrk do the real work, but are not to be called directly.
-+ For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
-+ checks that all returned registers are virtual. You should not
-+ call the _wrk version directly.
-+*/
++/*---------------------------------------------------------------*/
++/*--- begin host_loongarch64_defs.c ---*/
++/*---------------------------------------------------------------*/
+
-+static LOONGARCH64AMode* iselIntExpr_AMode_wrk ( ISelEnv* env,
-+ IRExpr* e, IRType dty );
-+static LOONGARCH64AMode* iselIntExpr_AMode ( ISelEnv* env,
-+ IRExpr* e, IRType dty );
++/*
++ This file is part of Valgrind, a dynamic binary instrumentation
++ framework.
+
-+static LOONGARCH64RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e,
-+ UChar size, Bool isSigned );
-+static LOONGARCH64RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e,
-+ UChar size, Bool isSigned );
++ Copyright (C) 2021-2022 Loongson Technology Corporation Limited
+
-+static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e );
-+static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e );
++ This program is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License as
++ published by the Free Software Foundation; either version 2 of the
++ License, or (at your option) any later version.
+
-+static HReg iselCondCode_R_wrk ( ISelEnv* env, IRExpr* e );
-+static HReg iselCondCode_R ( ISelEnv* env, IRExpr* e );
++ This program is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ General Public License for more details.
+
-+static void iselInt128Expr_wrk ( HReg* hi, HReg* lo,
-+ ISelEnv* env, IRExpr* e );
-+static void iselInt128Expr ( HReg* hi, HReg* lo,
-+ ISelEnv* env, IRExpr* e );
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, see .
+
-+static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e );
-+static HReg iselFltExpr ( ISelEnv* env, IRExpr* e );
++ The GNU General Public License is contained in the file COPYING.
++*/
+
-+static HReg iselV128Expr_wrk ( ISelEnv* env, IRExpr* e );
-+static HReg iselV128Expr ( ISelEnv* env, IRExpr* e );
++#include "libvex_basictypes.h"
++#include "libvex.h"
++#include "libvex_trc_values.h"
+
-+static void iselV256Expr_wrk ( HReg* hi, HReg* lo,
-+ ISelEnv* env, IRExpr* e );
-+static void iselV256Expr ( HReg* hi, HReg* lo,
-+ ISelEnv* env, IRExpr* e );
++#include "main_util.h"
++#include "host_generic_regs.h"
++#include "host_loongarch64_defs.h"
+
+
-+/*---------------------------------------------------------*/
-+/*--- ISEL: Misc helpers ---*/
-+/*---------------------------------------------------------*/
++/* --------- Local helpers. --------- */
+
-+/* Generate move insn */
-+static LOONGARCH64Instr* LOONGARCH64Instr_Move ( HReg to, HReg from )
++static inline void mapReg ( HRegRemap* m, HReg* r )
+{
-+ LOONGARCH64RI *ri = LOONGARCH64RI_R(hregZERO());
-+ return LOONGARCH64Instr_Binary(LAbin_OR, ri, from, to);
++ *r = lookupHRegRemap(m, *r);
+}
+
-+/* Generate vector move insn */
-+static LOONGARCH64Instr* LOONGARCH64Instr_VecMove ( HReg to, HReg from )
++static inline Int extend ( UInt imm, UInt size )
+{
-+ LOONGARCH64RI *ri = LOONGARCH64RI_I(0, 8, False);
-+ return LOONGARCH64Instr_VecBinary(LAvecbin_VORI_B, ri, from, to);
++ UInt shift = 32 - size;
++ return (((Int)imm << shift) >> shift);
+}
+
-+/* Generate LOONGARCH64AMode from HReg and UInt */
-+static LOONGARCH64AMode* mkLOONGARCH64AMode_RI ( HReg reg, UInt imm )
-+{
-+ vassert(imm < (1 << 12));
-+ return LOONGARCH64AMode_RI(reg, (UShort)imm);
-+}
+
-+/* Set floating point rounding mode */
-+static void set_rounding_mode ( ISelEnv* env, IRExpr* mode )
++/* --------- Registers. --------- */
++
++const RRegUniverse* getRRegUniverse_LOONGARCH64 ( void )
+{
-+ /*
-+ rounding mode | LOONGARCH | IR
-+ ------------------------------
-+ to nearest | 00 | 00
-+ to zero | 01 | 11
-+ to +infinity | 10 | 10
-+ to -infinity | 11 | 01
-+ */
++ /* The real-register universe is a big constant, so we just want to
++ initialise it once. */
++ static RRegUniverse rRegUniverse_LOONGARCH64;
++ static Bool rRegUniverse_LOONGARCH64_initted = False;
+
-+ /* rm = XOR(rm, (rm << 1)) & 3 */
-+ HReg rm = iselIntExpr_R(env, mode);
-+ HReg tmp = newVRegI(env);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(1, 5, False);
-+ LOONGARCH64RI* ri2 = LOONGARCH64RI_R(rm);
-+ LOONGARCH64RI* ri3 = LOONGARCH64RI_I(3, 12, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri, rm, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_XOR, ri2, tmp, rm));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri3, rm, rm));
++ /* Handy shorthand, nothing more */
++ RRegUniverse* ru = &rRegUniverse_LOONGARCH64;
+
-+ /* Save old value of FCSR3 */
-+ HReg fcsr = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVFCSR2GR,
-+ hregLOONGARCH64_FCSR3(), fcsr));
++ /* This isn't thread-safe. Sigh. */
++ if (LIKELY(rRegUniverse_LOONGARCH64_initted == True))
++ return ru;
+
-+ /* Store old FCSR3 to stack */
-+ LOONGARCH64RI* ri4 = LOONGARCH64RI_I(-4 & 0xfff, 12, True);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D, ri4, hregSP(), hregSP()));
-+ LOONGARCH64AMode* am = LOONGARCH64AMode_RI(hregSP(), 0);
-+ addInstr(env, LOONGARCH64Instr_Store(LAstore_ST_W, am, fcsr));
-+
-+ /* Set new value of FCSR3 */
-+ LOONGARCH64RI* ri5 = LOONGARCH64RI_I(8, 5, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri5, rm, rm));
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FCSR,
-+ rm, hregLOONGARCH64_FCSR3()));
-+}
++ RRegUniverse__init(ru);
+
-+static void set_rounding_mode_default ( ISelEnv* env )
-+{
-+ /* Load old FCSR3 from stack */
-+ HReg fcsr = newVRegI(env);
-+ LOONGARCH64AMode* am = LOONGARCH64AMode_RI(hregSP(), 0);
-+ addInstr(env, LOONGARCH64Instr_Load(LAload_LD_WU, am, fcsr));
++ /* Add the registers. The initial segment of this array must be
++ those available for allocation by reg-alloc, and those that
++ follow are not available for allocation. */
++ ru->allocable_start[HRcInt64] = ru->size;
++ ru->regs[ru->size++] = hregLOONGARCH64_R23();
++ ru->regs[ru->size++] = hregLOONGARCH64_R24();
++ ru->regs[ru->size++] = hregLOONGARCH64_R25();
++ ru->regs[ru->size++] = hregLOONGARCH64_R26();
++ ru->regs[ru->size++] = hregLOONGARCH64_R27();
++ ru->regs[ru->size++] = hregLOONGARCH64_R28();
++ ru->regs[ru->size++] = hregLOONGARCH64_R29();
++ ru->regs[ru->size++] = hregLOONGARCH64_R30();
++ // $r31 is used as guest stack pointer, not available to regalloc.
+
-+ /* Restore SP */
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(4, 12, True);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D, ri, hregSP(), hregSP()));
++ // $r12 is used as a chaining/ProfInc/Cmove/genSpill/genReload temporary
++ // $r13 is used as a ProfInc temporary
++ ru->regs[ru->size++] = hregLOONGARCH64_R14();
++ ru->regs[ru->size++] = hregLOONGARCH64_R15();
++ ru->regs[ru->size++] = hregLOONGARCH64_R16();
++ ru->regs[ru->size++] = hregLOONGARCH64_R17();
++ ru->regs[ru->size++] = hregLOONGARCH64_R18();
++ ru->regs[ru->size++] = hregLOONGARCH64_R19();
++ ru->regs[ru->size++] = hregLOONGARCH64_R20();
++ ru->allocable_end[HRcInt64] = ru->size - 1;
+
-+ /* Set new value of FCSR3 */
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FCSR,
-+ fcsr, hregLOONGARCH64_FCSR3()));
-+}
++ ru->allocable_start[HRcFlt64] = ru->size;
++ ru->regs[ru->size++] = hregLOONGARCH64_F24();
++ ru->regs[ru->size++] = hregLOONGARCH64_F25();
++ ru->regs[ru->size++] = hregLOONGARCH64_F26();
++ ru->regs[ru->size++] = hregLOONGARCH64_F27();
++ ru->regs[ru->size++] = hregLOONGARCH64_F28();
++ ru->regs[ru->size++] = hregLOONGARCH64_F29();
++ ru->regs[ru->size++] = hregLOONGARCH64_F30();
++ ru->regs[ru->size++] = hregLOONGARCH64_F31();
++ ru->allocable_end[HRcFlt64] = ru->size - 1;
+
-+/* Convert LOONGARCH FCMP cond to IR result */
-+static HReg convert_cond_to_IR ( ISelEnv* env, HReg src2, HReg src1, Bool size64 )
-+{
-+ HReg tmp = newVRegI(env);
-+ HReg dst = newVRegI(env);
++ ru->allocable_start[HRcVec128] = ru->size;
++ ru->regs[ru->size++] = hregLOONGARCH64_V24();
++ ru->regs[ru->size++] = hregLOONGARCH64_V25();
++ ru->regs[ru->size++] = hregLOONGARCH64_V26();
++ ru->regs[ru->size++] = hregLOONGARCH64_V27();
++ ru->regs[ru->size++] = hregLOONGARCH64_V28();
++ ru->regs[ru->size++] = hregLOONGARCH64_V29();
++ ru->regs[ru->size++] = hregLOONGARCH64_V30();
++ ru->regs[ru->size++] = hregLOONGARCH64_V31();
++ ru->allocable_end[HRcVec128] = ru->size - 1;
+
-+ LOONGARCH64RI* ri1 = LOONGARCH64RI_I(63, 6, False);
-+ LOONGARCH64RI* ri2 = LOONGARCH64RI_I(0x45, 12, False);
-+ if (size64)
-+ addInstr(env, LOONGARCH64Instr_FpCmp(LAfpcmp_FCMP_CUN_D, src2, src1, tmp));
-+ else
-+ addInstr(env, LOONGARCH64Instr_FpCmp(LAfpcmp_FCMP_CUN_S, src2, src1, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri1, tmp, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri1, tmp, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri2, tmp, dst));
++ ru->allocable = ru->size;
+
-+ LOONGARCH64RI* ri3 = LOONGARCH64RI_I(0x1, 12, False);
-+ LOONGARCH64RI* ri4 = LOONGARCH64RI_R(tmp);
-+ if (size64)
-+ addInstr(env, LOONGARCH64Instr_FpCmp(LAfpcmp_FCMP_CLT_D, src2, src1, tmp));
-+ else
-+ addInstr(env, LOONGARCH64Instr_FpCmp(LAfpcmp_FCMP_CLT_S, src2, src1, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri1, tmp, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri1, tmp, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri3, tmp, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri4, dst, dst));
++ /* And other regs, not available to the allocator. */
++ ru->regs[ru->size++] = hregLOONGARCH64_R0();
++ ru->regs[ru->size++] = hregLOONGARCH64_R1();
++ ru->regs[ru->size++] = hregLOONGARCH64_R2();
++ ru->regs[ru->size++] = hregLOONGARCH64_R3();
++ ru->regs[ru->size++] = hregLOONGARCH64_R4();
++ ru->regs[ru->size++] = hregLOONGARCH64_R5();
++ ru->regs[ru->size++] = hregLOONGARCH64_R6();
++ ru->regs[ru->size++] = hregLOONGARCH64_R7();
++ ru->regs[ru->size++] = hregLOONGARCH64_R8();
++ ru->regs[ru->size++] = hregLOONGARCH64_R9();
++ ru->regs[ru->size++] = hregLOONGARCH64_R10();
++ ru->regs[ru->size++] = hregLOONGARCH64_R11();
++ ru->regs[ru->size++] = hregLOONGARCH64_R12();
++ ru->regs[ru->size++] = hregLOONGARCH64_R13();
++ ru->regs[ru->size++] = hregLOONGARCH64_R21();
++ ru->regs[ru->size++] = hregLOONGARCH64_R22();
++ ru->regs[ru->size++] = hregLOONGARCH64_R31();
++ ru->regs[ru->size++] = hregLOONGARCH64_FCSR3();
+
-+ LOONGARCH64RI* ri5 = LOONGARCH64RI_I(0x40, 12, False);
-+ if (size64)
-+ addInstr(env, LOONGARCH64Instr_FpCmp(LAfpcmp_FCMP_CEQ_D, src2, src1, tmp));
-+ else
-+ addInstr(env, LOONGARCH64Instr_FpCmp(LAfpcmp_FCMP_CEQ_S, src2, src1, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri1, tmp, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri1, tmp, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri5, tmp, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri4, dst, dst));
++ rRegUniverse_LOONGARCH64_initted = True;
+
-+ return dst;
++ RRegUniverse__check_is_sane(ru);
++ return ru;
+}
+
-+
-+/*---------------------------------------------------------*/
-+/*--- ISEL: Function call helpers ---*/
-+/*---------------------------------------------------------*/
-+
-+/* Used only in doHelperCall. See big comment in doHelperCall re
-+ handling of register-parameter args. This function figures out
-+ whether evaluation of an expression might require use of a fixed
-+ register. If in doubt return True (safe but suboptimal).
-+*/
-+static Bool mightRequireFixedRegs ( IRExpr* e )
++UInt ppHRegLOONGARCH64 ( HReg reg )
+{
-+ if (UNLIKELY(is_IRExpr_VECRET_or_GSPTR(e))) {
-+ // These are always "safe" -- either a copy of SP in some
-+ // arbitrary vreg, or a copy of $r31, respectively.
-+ return False;
++ Int r;
++ Int ret = 0;
++ static const HChar* ireg_names[32] = {
++ "$zero",
++ "$ra",
++ "$tp",
++ "$sp",
++ "$a0", "$a1", "$a2", "$a3", "$a4", "$a5", "$a6", "$a7",
++ "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8",
++ "$r21", /* Reserved */
++ "$fp",
++ "$s0", "$s1", "$s2", "$s3", "$s4", "$s5", "$s6", "$s7", "$s8"
++ };
++ static const HChar* freg_names[32] = {
++ "$fa0", "$fa1", "$fa2", "$fa3", "$fa4", "$fa5", "$fa6", "$fa7",
++ "$ft0", "$ft1", "$ft2", "$ft3", "$ft4", "$ft5", "$ft6", "$ft7",
++ "$ft8", "$ft9", "$ft10", "$ft11", "$ft12", "$ft13", "$ft14", "$ft15",
++ "$fs0", "$fs1", "$fs2", "$fs3", "$fs4", "$fs5", "$fs6", "$fs7"
++ };
++ static const HChar* vreg_names[32] = {
++ "$vr0", "$vr1", "$vr2", "$vr3", "$vr4", "$vr5", "$vr6", "$vr7",
++ "$vr8", "$vr9", "$vr10", "$vr11", "$vr12", "$vr13", "$vr14", "$vr15",
++ "$vr16", "$vr17", "$vr18", "$vr19", "$vr20", "$vr21", "$vr22", "$vr23",
++ "$vr24", "$vr25", "$vr26", "$vr27", "$vr28", "$vr29", "$vr30", "$vr31"
++ };
++
++ /* Be generic for all virtual regs. */
++ if (hregIsVirtual(reg)) {
++ return ppHReg(reg);
+ }
-+ /* Else it's a "normal" expression. */
-+ switch (e->tag) {
-+ case Iex_RdTmp: case Iex_Const: case Iex_Get:
-+ return False;
++
++ /* But specific for real regs. */
++ switch (hregClass(reg)) {
++ case HRcInt32:
++ r = hregEncoding(reg);
++ vassert(r < 4);
++ ret = vex_printf("$fcsr%d", r);
++ break;
++ case HRcInt64:
++ r = hregEncoding(reg);
++ vassert(r < 32);
++ ret = vex_printf("%s", ireg_names[r]);
++ break;
++ case HRcFlt64:
++ r = hregEncoding(reg);
++ vassert(r < 32);
++ ret = vex_printf("%s", freg_names[r]);
++ break;
++ case HRcVec128:
++ r = hregEncoding(reg);
++ vassert(r < 32);
++ ret = vex_printf("%s", vreg_names[r]);
++ break;
+ default:
-+ return True;
++ vpanic("ppHRegLOONGARCH64");
++ break;
+ }
-+}
-+
-+/* Do a complete function call. |guard| is a Ity_Bit expression
-+ indicating whether or not the call happens. If guard==NULL, the
-+ call is unconditional. |retloc| is set to indicate where the
-+ return value is after the call. The caller (of this fn) must
-+ generate code to add |stackAdjustAfterCall| to the stack pointer
-+ after the call is done. Returns True iff it managed to handle this
-+ combination of arg/return types, else returns False. */
-+static Bool doHelperCall( /*OUT*/UInt* stackAdjustAfterCall,
-+ /*OUT*/RetLoc* retloc,
-+ ISelEnv* env,
-+ IRExpr* guard,
-+ IRCallee* cee, IRType retTy, IRExpr** args )
-+{
-+ HReg cond;
-+ HReg argregs[LOONGARCH64_N_ARGREGS];
-+ HReg tmpregs[LOONGARCH64_N_ARGREGS];
-+ Bool go_fast;
-+ Int n_args, i, nextArgReg;
-+ Addr64 target;
-+
-+ vassert(LOONGARCH64_N_ARGREGS == 8);
-+
-+ /* Set default returns. We'll update them later if needed. */
-+ *stackAdjustAfterCall = 0;
-+ *retloc = mk_RetLoc_INVALID();
-+
-+ /* These are used for cross-checking that IR-level constraints on
-+ the use of IRExpr_VECRET() and IRExpr_GSPTR() are observed. */
-+ UInt nVECRETs = 0;
-+ UInt nGSPTRs = 0;
-+
-+ /* Marshal args for a call and do the call.
-+
-+ This function only deals with a tiny set of possibilities, which
-+ cover all helpers in practice. The restrictions are that only
-+ arguments in registers are supported, hence only
-+ LOONGARCH64_N_ARGREGS x 64 integer bits in total can be passed.
-+ In fact the only supported arg type is I64.
+
-+ The return type can be I{64,32} or V{128,256}. In the latter two
-+ cases, it is expected that |args| will contain the special node
-+ IRExpr_VECRET(), in which case this routine generates code to
-+ allocate space on the stack for the vector return value. Since
-+ we are not passing any scalars on the stack, it is enough to
-+ preallocate the return space before marshalling any arguments,
-+ in this case.
++ return ret;
++}
+
-+ |args| may also contain IRExpr_GSPTR(), in which case the
-+ value in $r31 is passed as the corresponding argument.
+
-+ Generating code which is both efficient and correct when
-+ parameters are to be passed in registers is difficult, for the
-+ reasons elaborated in detail in comments attached to
-+ doHelperCall() in priv/host_x86_isel.c. Here, we use a variant
-+ of the method described in those comments.
++/* --------- Condition codes, LOONGARCH64 encoding. --------- */
+
-+ The problem is split into two cases: the fast scheme and the
-+ slow scheme. In the fast scheme, arguments are computed
-+ directly into the target (real) registers. This is only safe
-+ when we can be sure that computation of each argument will not
-+ trash any real registers set by computation of any other
-+ argument.
++static inline const HChar* showLOONGARCH64CondCode ( LOONGARCH64CondCode cond )
++{
++ const HChar* ret;
++ switch (cond) {
++ case LAcc_EQ:
++ ret = "eq"; /* equal */
++ break;
++ case LAcc_NE:
++ ret = "ne"; /* not equal */
++ break;
++ case LAcc_LT:
++ ret = "lt"; /* less than (signed) */
++ break;
++ case LAcc_GE:
++ ret = "ge"; /* great equal (signed) */
++ break;
++ case LAcc_LTU:
++ ret = "ltu"; /* less than (unsigned) */
++ break;
++ case LAcc_GEU:
++ ret = "geu"; /* great equal (unsigned) */
++ break;
++ case LAcc_AL:
++ ret = "al"; /* always (unconditional) */
++ break;
++ default:
++ vpanic("showLOONGARCH64CondCode");
++ break;
++ }
++ return ret;
++}
+
-+ In the slow scheme, all args are first computed into vregs, and
-+ once they are all done, they are moved to the relevant real
-+ regs. This always gives correct code, but it also gives a bunch
-+ of vreg-to-rreg moves which are usually redundant but are hard
-+ for the register allocator to get rid of.
+
-+ To decide which scheme to use, all argument expressions are
-+ first examined. If they are all so simple that it is clear they
-+ will be evaluated without use of any fixed registers, use the
-+ fast scheme, else use the slow scheme. Note also that only
-+ unconditional calls may use the fast scheme, since having to
-+ compute a condition expression could itself trash real
-+ registers.
++/* --------- Memory address expressions (amodes). --------- */
+
-+ Note this requires being able to examine an expression and
-+ determine whether or not evaluation of it might use a fixed
-+ register. That requires knowledge of how the rest of this insn
-+ selector works. Currently just the following 3 are regarded as
-+ safe -- hopefully they cover the majority of arguments in
-+ practice: IRExpr_Tmp IRExpr_Const IRExpr_Get.
-+ */
++LOONGARCH64AMode* LOONGARCH64AMode_RI ( HReg reg, UShort imm )
++{
++ LOONGARCH64AMode* am = LibVEX_Alloc_inline(sizeof(LOONGARCH64AMode));
++ am->tag = LAam_RI;
++ am->LAam.RI.base = reg;
++ am->LAam.RI.index = imm;
++ return am;
++}
+
-+ /* LOONGARCH64 calling convention: up to eight registers ($a0 ... $a7)
-+ are allowed to be used for passing integer arguments. They correspond
-+ to regs $r4 ... $r11. Note that the cee->regparms field is meaningless
-+ on LOONGARCH64 host (since we only implement one calling convention)
-+ and so we always ignore it. */
++LOONGARCH64AMode* LOONGARCH64AMode_RR ( HReg base, HReg index )
++{
++ LOONGARCH64AMode* am = LibVEX_Alloc_inline(sizeof(LOONGARCH64AMode));
++ am->tag = LAam_RR;
++ am->LAam.RR.base = base;
++ am->LAam.RR.index = index;
++ return am;
++}
+
-+ n_args = 0;
-+ for (i = 0; args[i]; i++) {
-+ IRExpr* arg = args[i];
-+ if (UNLIKELY(arg->tag == Iex_VECRET)) {
-+ nVECRETs++;
-+ } else if (UNLIKELY(arg->tag == Iex_GSPTR)) {
-+ nGSPTRs++;
-+ }
-+ n_args++;
++static inline void ppLOONGARCH64AMode ( LOONGARCH64AMode* am )
++{
++ switch (am->tag) {
++ case LAam_RI:
++ ppHRegLOONGARCH64(am->LAam.RI.base);
++ vex_printf(", ");
++ vex_printf("%d", extend((UInt)am->LAam.RI.index, 12));
++ break;
++ case LAam_RR:
++ ppHRegLOONGARCH64(am->LAam.RR.base);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(am->LAam.RR.index);
++ break;
++ default:
++ vpanic("ppLOONGARCH64AMode");
++ break;
+ }
++}
+
-+ /* If this fails, the IR is ill-formed */
-+ vassert(nGSPTRs == 0 || nGSPTRs == 1);
-+
-+ /* If we have a VECRET, allocate space on the stack for the return
-+ value, and record the stack pointer after that. */
-+ HReg r_vecRetAddr = INVALID_HREG;
-+ LOONGARCH64RI* ri;
-+ if (nVECRETs == 1) {
-+ vassert(retTy == Ity_V128 || retTy == Ity_V256);
-+ r_vecRetAddr = newVRegI(env);
-+ if (retTy == Ity_V128)
-+ ri = LOONGARCH64RI_I(-16 & 0xfff, 12, True);
-+ else // retTy == Ity_V256
-+ ri = LOONGARCH64RI_I(-32 & 0xfff, 12, True);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D, ri, hregSP(), hregSP()));
-+ addInstr(env, LOONGARCH64Instr_Move(r_vecRetAddr, hregSP()));
-+ } else {
-+ // If either of these fail, the IR is ill-formed
-+ vassert(retTy != Ity_V128 && retTy != Ity_V256);
-+ vassert(nVECRETs == 0);
++static inline void addRegUsage_LOONGARCH64AMode( HRegUsage* u,
++ LOONGARCH64AMode* am )
++{
++ switch (am->tag) {
++ case LAam_RI:
++ addHRegUse(u, HRmRead, am->LAam.RI.base);
++ break;
++ case LAam_RR:
++ addHRegUse(u, HRmRead, am->LAam.RR.base);
++ addHRegUse(u, HRmRead, am->LAam.RR.index);
++ break;
++ default:
++ vpanic("addRegUsage_LOONGARCH64AMode");
++ break;
+ }
++}
+
-+ if (n_args > LOONGARCH64_N_ARGREGS) {
-+ vpanic("doHelperCall(loongarch64): cannot currently handle > 8 args");
++static inline void mapRegs_LOONGARCH64AMode( HRegRemap* m,
++ LOONGARCH64AMode* am )
++{
++ switch (am->tag) {
++ case LAam_RI:
++ mapReg(m, &am->LAam.RI.base);
++ break;
++ case LAam_RR:
++ mapReg(m, &am->LAam.RR.base);
++ mapReg(m, &am->LAam.RR.index);
++ break;
++ default:
++ vpanic("mapRegs_LOONGARCH64AMode");
++ break;
+ }
++}
+
-+ argregs[0] = hregLOONGARCH64_R4();
-+ argregs[1] = hregLOONGARCH64_R5();
-+ argregs[2] = hregLOONGARCH64_R6();
-+ argregs[3] = hregLOONGARCH64_R7();
-+ argregs[4] = hregLOONGARCH64_R8();
-+ argregs[5] = hregLOONGARCH64_R9();
-+ argregs[6] = hregLOONGARCH64_R10();
-+ argregs[7] = hregLOONGARCH64_R11();
-+
-+ tmpregs[0] = tmpregs[1] = tmpregs[2] = tmpregs[3] = INVALID_HREG;
-+ tmpregs[4] = tmpregs[5] = tmpregs[6] = tmpregs[7] = INVALID_HREG;
+
-+ /* First decide which scheme (slow or fast) is to be used. First assume the
-+ fast scheme, and select slow if any contraindications (wow) appear. */
++/* --------- Operand, which can be reg or imm. --------- */
+
-+ go_fast = True;
++LOONGARCH64RI* LOONGARCH64RI_R ( HReg reg )
++{
++ LOONGARCH64RI* op = LibVEX_Alloc_inline(sizeof(LOONGARCH64RI));
++ op->tag = LAri_Reg;
++ op->LAri.R.reg = reg;
++ return op;
++}
+
-+ if (guard) {
-+ if (guard->tag == Iex_Const
-+ && guard->Iex.Const.con->tag == Ico_U1
-+ && guard->Iex.Const.con->Ico.U1 == True) {
-+ /* unconditional */
-+ } else {
-+ /* Not manifestly unconditional -- be conservative. */
-+ go_fast = False;
-+ }
-+ }
++LOONGARCH64RI* LOONGARCH64RI_I ( UShort imm, UChar size, Bool isSigned )
++{
++ LOONGARCH64RI* op = LibVEX_Alloc_inline(sizeof(LOONGARCH64RI));
++ op->tag = LAri_Imm;
++ op->LAri.I.imm = imm;
++ op->LAri.I.size = size;
++ op->LAri.I.isSigned = isSigned;
++ return op;
++}
+
-+ if (go_fast) {
-+ for (i = 0; i < n_args; i++) {
-+ if (mightRequireFixedRegs(args[i])) {
-+ go_fast = False;
-+ break;
++static inline void ppLOONGARCH64RI ( LOONGARCH64RI* ri )
++{
++ switch (ri->tag) {
++ case LAri_Reg:
++ ppHRegLOONGARCH64(ri->LAri.R.reg);
++ break;
++ case LAri_Imm:
++ if (ri->LAri.I.isSigned) {
++ vex_printf("%d", extend((UInt)ri->LAri.I.imm, ri->LAri.I.size));
++ } else {
++ vex_printf("%u", (UInt)ri->LAri.I.imm);
+ }
-+ }
++ break;
++ default:
++ vpanic("ppLOONGARCH64RI");
++ break;
+ }
++}
+
-+ if (go_fast) {
-+ if (retTy == Ity_V128 || retTy == Ity_V256)
-+ go_fast = False;
++static inline void addRegUsage_LOONGARCH64RI( HRegUsage* u, LOONGARCH64RI* ri )
++{
++ switch (ri->tag) {
++ case LAri_Reg:
++ addHRegUse(u, HRmRead, ri->LAri.R.reg);
++ break;
++ case LAri_Imm:
++ break;
++ default:
++ vpanic("addRegUsage_LOONGARCH64RI");
++ break;
+ }
++}
+
-+ /* At this point the scheme to use has been established. Generate
-+ code to get the arg values into the argument rregs. If we run
-+ out of arg regs, give up. */
++static inline void mapRegs_LOONGARCH64RI( HRegRemap* m, LOONGARCH64RI* ri )
++{
++ switch (ri->tag) {
++ case LAri_Reg:
++ mapReg(m, &ri->LAri.R.reg);
++ break;
++ case LAri_Imm:
++ break;
++ default:
++ vpanic("mapRegs_LOONGARCH64RI");
++ break;
++ }
++}
+
-+ if (go_fast) {
-+ /* FAST SCHEME */
-+ nextArgReg = 0;
+
-+ for (i = 0; i < n_args; i++) {
-+ IRExpr* arg = args[i];
++/* --------- Instructions. --------- */
+
-+ IRType aTy = Ity_INVALID;
-+ if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg)))
-+ aTy = typeOfIRExpr(env->type_env, args[i]);
-+
-+ if (nextArgReg >= LOONGARCH64_N_ARGREGS)
-+ return False; /* out of argregs */
-+
-+ if (aTy == Ity_I64) {
-+ addInstr(env, LOONGARCH64Instr_Move(argregs[nextArgReg],
-+ iselIntExpr_R(env, args[i])));
-+ nextArgReg++;
-+ } else if (arg->tag == Iex_GSPTR) {
-+ addInstr(env, LOONGARCH64Instr_Move(argregs[nextArgReg], hregGSP()));
-+ nextArgReg++;
-+ } else if (arg->tag == Iex_VECRET) {
-+ // because of the go_fast logic above, we can't get here,
-+ // since vector return values makes us use the slow path
-+ // instead.
-+ vassert(0);
-+ } else
-+ return False; /* unhandled arg type */
-+ }
-+
-+ /* Fast scheme only applies for unconditional calls. Hence: */
-+ cond = INVALID_HREG;
-+ } else {
-+ /* SLOW SCHEME; move via temporaries */
-+ nextArgReg = 0;
-+
-+ for (i = 0; i < n_args; i++) {
-+ IRExpr* arg = args[i];
-+
-+ IRType aTy = Ity_INVALID;
-+ if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg)))
-+ aTy = typeOfIRExpr(env->type_env, args[i]);
-+
-+ if (nextArgReg >= LOONGARCH64_N_ARGREGS)
-+ return False; /* out of argregs */
-+
-+ if (aTy == Ity_I64) {
-+ tmpregs[nextArgReg] = iselIntExpr_R(env, args[i]);
-+ nextArgReg++;
-+ } else if (arg->tag == Iex_GSPTR) {
-+ tmpregs[nextArgReg] = hregGSP();
-+ nextArgReg++;
-+ } else if (arg->tag == Iex_VECRET) {
-+ vassert(!hregIsInvalid(r_vecRetAddr));
-+ tmpregs[nextArgReg] = r_vecRetAddr;
-+ nextArgReg++;
-+ } else
-+ return False; /* unhandled arg type */
-+ }
-+
-+ /* Now we can compute the condition. We can't do it earlier
-+ because the argument computations could trash the condition
-+ codes. Be a bit clever to handle the common case where the
-+ guard is 1:Bit. */
-+ cond = INVALID_HREG;
-+ if (guard) {
-+ if (guard->tag == Iex_Const
-+ && guard->Iex.Const.con->tag == Ico_U1
-+ && guard->Iex.Const.con->Ico.U1 == True) {
-+ /* unconditional -- do nothing */
-+ } else {
-+ cond = iselCondCode_R(env, guard);
-+ }
-+ }
-+
-+ /* Move the args to their final destinations. */
-+ for (i = 0; i < nextArgReg; i++) {
-+ vassert(!(hregIsInvalid(tmpregs[i])));
-+ /* None of these insns, including any spill code that might
-+ be generated, may alter the condition codes. */
-+ addInstr(env, LOONGARCH64Instr_Move(argregs[i], tmpregs[i]));
-+ }
-+ }
-+
-+ /* Should be assured by checks above */
-+ vassert(nextArgReg <= LOONGARCH64_N_ARGREGS);
-+
-+ /* Do final checks, set the return values, and generate the call
-+ instruction proper. */
-+ vassert(nGSPTRs == 0 || nGSPTRs == 1);
-+ vassert(nVECRETs == ((retTy == Ity_V128 || retTy == Ity_V256) ? 1 : 0));
-+ vassert(*stackAdjustAfterCall == 0);
-+ vassert(is_RetLoc_INVALID(*retloc));
-+ switch (retTy) {
-+ case Ity_INVALID:
-+ /* Function doesn't return a value. */
-+ *retloc = mk_RetLoc_simple(RLPri_None);
-+ break;
-+ case Ity_I8: case Ity_I16: case Ity_I32: case Ity_I64:
-+ *retloc = mk_RetLoc_simple(RLPri_Int);
-+ break;
-+ case Ity_V128:
-+ *retloc = mk_RetLoc_spRel(RLPri_V128SpRel, 0);
-+ *stackAdjustAfterCall = 16;
-+ break;
-+ case Ity_V256:
-+ *retloc = mk_RetLoc_spRel(RLPri_V256SpRel, 0);
-+ *stackAdjustAfterCall = 32;
-+ break;
++static inline const HChar* showLOONGARCH64UnOp ( LOONGARCH64UnOp op )
++{
++ switch (op) {
++ case LAun_CLZ_W:
++ return "clz.w";
++ case LAun_CTZ_W:
++ return "ctz.w";
++ case LAun_CLZ_D:
++ return "clz.d";
++ case LAun_CTZ_D:
++ return "ctz.w";
++ case LAun_EXT_W_H:
++ return "ext.w.h";
++ case LAun_EXT_W_B:
++ return "ext.w.b";
+ default:
-+ /* IR can denote other possible return types, but we don't
-+ handle those here. */
-+ vassert(0);
++ vpanic("showLOONGARCH64UnOp");
+ break;
+ }
-+
-+ /* Finally, generate the call itself. This needs the *retloc value
-+ set in the switch above, which is why it's at the end. */
-+
-+ /* nextArgReg doles out argument registers. Since these are
-+ assigned in the order $a0 .. $a7, its numeric value at this point,
-+ which must be between 0 and 8 inclusive, is going to be equal to
-+ the number of arg regs in use for the call. Hence bake that
-+ number into the call (we'll need to know it when doing register
-+ allocation, to know what regs the call reads.) */
-+
-+ target = (Addr)cee->addr;
-+ addInstr(env, LOONGARCH64Instr_Call(cond, target, nextArgReg, *retloc));
-+
-+ return True; /* success */
+}
+
-+
-+/*---------------------------------------------------------*/
-+/*--- ISEL: Integer expressions (64/32/16/8 bit) ---*/
-+/*---------------------------------------------------------*/
-+
-+/* Select insns for an integer-typed expression, and add them to the
-+ code list. Return a reg holding the result. This reg will be a
-+ virtual register. THE RETURNED REG MUST NOT BE MODIFIED. If you
-+ want to modify it, ask for a new vreg, copy it in there, and modify
-+ the copy. The register allocator will do its best to map both
-+ vregs to the same real register, so the copies will often disappear
-+ later in the game.
-+
-+ This should handle expressions of 64, 32, 16 and 8-bit type.
-+ All results are returned in a (mode64 ? 64bit : 32bit) register.
-+ For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
-+ are arbitrary, so you should mask or sign extend partial values
-+ if necessary.
-+*/
-+
-+/* --------------------- AMode --------------------- */
-+
-+static LOONGARCH64AMode* iselIntExpr_AMode ( ISelEnv* env,
-+ IRExpr* e, IRType dty )
++static inline const HChar* showLOONGARCH64BinOp ( LOONGARCH64BinOp op )
+{
-+ LOONGARCH64AMode* am = iselIntExpr_AMode_wrk(env, e, dty);
-+
-+ /* sanity checks ... */
-+ switch (am->tag) {
-+ case LAam_RI:
-+ vassert(am->LAam.RI.index < (1 << 12));
-+ vassert(hregClass(am->LAam.RI.base) == HRcInt64);
-+ vassert(hregIsVirtual(am->LAam.RI.base));
-+ break;
-+ case LAam_RR:
-+ vassert(hregClass(am->LAam.RR.base) == HRcInt64);
-+ vassert(hregIsVirtual(am->LAam.RR.base));
-+ vassert(hregClass(am->LAam.RR.index) == HRcInt64);
-+ vassert(hregIsVirtual(am->LAam.RR.index));
-+ break;
++ switch (op) {
++ case LAbin_ADD_W:
++ return "add.w";
++ case LAbin_ADD_D:
++ return "add.d";
++ case LAbin_SUB_W:
++ return "sub.w";
++ case LAbin_SUB_D:
++ return "sub.d";
++ case LAbin_NOR:
++ return "nor";
++ case LAbin_AND:
++ return "and";
++ case LAbin_OR:
++ return "or";
++ case LAbin_XOR:
++ return "xor";
++ case LAbin_SLL_W:
++ return "sll.w";
++ case LAbin_SRL_W:
++ return "srl.w";
++ case LAbin_SRA_W:
++ return "sra.w";
++ case LAbin_SLL_D:
++ return "sll.d";
++ case LAbin_SRL_D:
++ return "srl.d";
++ case LAbin_SRA_D:
++ return "sra.d";
++ case LAbin_MUL_W:
++ return "mul.w";
++ case LAbin_MUL_D:
++ return "mul.d";
++ case LAbin_MULH_W:
++ return "mulh.w";
++ case LAbin_MULH_WU:
++ return "mulh.wu";
++ case LAbin_MULH_D:
++ return "mulh.d";
++ case LAbin_MULH_DU:
++ return "mulh.du";
++ case LAbin_MULW_D_W:
++ return "mulw.d.w";
++ case LAbin_MULW_D_WU:
++ return "mulw.d.wu";
++ case LAbin_DIV_W:
++ return "div.w";
++ case LAbin_MOD_W:
++ return "mod.w";
++ case LAbin_DIV_WU:
++ return "div.wu";
++ case LAbin_MOD_WU:
++ return "mod.wu";
++ case LAbin_DIV_D:
++ return "div.d";
++ case LAbin_MOD_D:
++ return "mod.d";
++ case LAbin_DIV_DU:
++ return "div.du";
++ case LAbin_MOD_DU:
++ return "mod.du";
++ case LAbin_SLLI_W:
++ return "slli.w";
++ case LAbin_SLLI_D:
++ return "slli.d";
++ case LAbin_SRLI_W:
++ return "srli.w";
++ case LAbin_SRLI_D:
++ return "srli.d";
++ case LAbin_SRAI_W:
++ return "srai.w";
++ case LAbin_SRAI_D:
++ return "srai.d";
++ case LAbin_ADDI_W:
++ return "addi.w";
++ case LAbin_ADDI_D:
++ return "addi.d";
++ case LAbin_ANDI:
++ return "andi";
++ case LAbin_ORI:
++ return "ori";
++ case LAbin_XORI:
++ return "xori";
+ default:
-+ vpanic("iselIntExpr_AMode: unknown LOONGARCH64 AMode tag");
++ vpanic("showLOONGARCH64BinOp");
+ break;
+ }
-+
-+ return am;
+}
+
-+/* DO NOT CALL THIS DIRECTLY ! */
-+static LOONGARCH64AMode* iselIntExpr_AMode_wrk ( ISelEnv* env,
-+ IRExpr* e, IRType dty )
++static inline const HChar* showLOONGARCH64LoadOp ( LOONGARCH64LoadOp op )
+{
-+ IRType ty = typeOfIRExpr(env->type_env, e);
-+ vassert(e);
-+ vassert(ty == Ity_I64);
-+
-+ /* Add64(expr, i), where i <= 0x7ff */
-+ if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add64
-+ && e->Iex.Binop.arg2->tag == Iex_Const
-+ && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64
-+ && e->Iex.Binop.arg2->Iex.Const.con->Ico.U64 <= 0x7ff) {
-+ return LOONGARCH64AMode_RI(iselIntExpr_R(env, e->Iex.Binop.arg1),
-+ (UShort)e->Iex.Binop.arg2->Iex.Const.con->Ico.U64);
-+ }
-+
-+ /* Add64(expr, expr) */
-+ if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add64) {
-+ HReg base = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ HReg index = iselIntExpr_R(env, e->Iex.Binop.arg2);
-+ return LOONGARCH64AMode_RR(base, index);
++ switch (op) {
++ case LAload_LD_D:
++ return "ld.d";
++ case LAload_LD_BU:
++ return "ld.bu";
++ case LAload_LD_HU:
++ return "ld.hu";
++ case LAload_LD_WU:
++ return "ld.wu";
++ case LAload_LDX_D:
++ return "ldx.d";
++ case LAload_LDX_BU:
++ return "ldx.bu";
++ case LAload_LDX_HU:
++ return "ldx.hu";
++ case LAload_LDX_WU:
++ return "ldx.wu";
++ default:
++ vpanic("LOONGARCH64LoadOp");
++ break;
+ }
-+
-+ /* Doesn't match anything in particular. Generate it into
-+ a register and use that. */
-+ return LOONGARCH64AMode_RI(iselIntExpr_R(env, e), 0);
+}
+
-+/* --------------------- RI --------------------- */
-+
-+static LOONGARCH64RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e,
-+ UChar size, Bool isSigned )
++static inline const HChar* showLOONGARCH64StoreOp ( LOONGARCH64StoreOp op )
+{
-+ LOONGARCH64RI* ri = iselIntExpr_RI_wrk(env, e, size, isSigned);
-+
-+ /* sanity checks ... */
-+ switch (ri->tag) {
-+ case LAri_Imm:
-+ switch (ri->LAri.I.size) {
-+ case 0 ... 4:
-+ case 6 ... 7:
-+ vassert(ri->LAri.I.isSigned == False);
-+ break;
-+ case 9 ... 11:
-+ vassert(ri->LAri.I.isSigned == True);
-+ break;
-+ case 5: case 8: case 12:
-+ break;
-+ default:
-+ break;
-+ vassert(0);
-+ }
-+ vassert(ri->LAri.I.imm < (1 << ri->LAri.I.size));
-+ break;
-+ case LAri_Reg:
-+ vassert(hregClass(ri->LAri.R.reg) == HRcInt64);
-+ vassert(hregIsVirtual(ri->LAri.R.reg));
-+ break;
++ switch (op) {
++ case LAstore_ST_B:
++ return "st.b";
++ case LAstore_ST_H:
++ return "st.h";
++ case LAstore_ST_W:
++ return "st.w";
++ case LAstore_ST_D:
++ return "st.d";
++ case LAstore_STX_B:
++ return "stx.b";
++ case LAstore_STX_H:
++ return "stx.h";
++ case LAstore_STX_W:
++ return "stx.w";
++ case LAstore_STX_D:
++ return "stx.d";
+ default:
-+ vpanic("iselIntExpr_RI: unknown LOONGARCH64 RI tag");
++ vpanic("LOONGARCH64StoreOp");
+ break;
+ }
-+
-+ return ri;
+}
+
-+/* DO NOT CALL THIS DIRECTLY ! */
-+static LOONGARCH64RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e,
-+ UChar size, Bool isSigned )
++static inline const HChar* showLOONGARCH64LLSCOp ( LOONGARCH64LLSCOp op )
+{
-+ IRType ty = typeOfIRExpr(env->type_env, e);
-+ vassert(e);
-+ vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
-+
-+ LOONGARCH64RI *ri = NULL;
-+
-+ /* special case: immediate */
-+ if (e->tag == Iex_Const) {
-+ switch (e->Iex.Const.con->tag) {
-+ case Ico_U8:
-+ if (!isSigned && e->Iex.Const.con->Ico.U8 < (1 << size)) {
-+ UShort imm = e->Iex.Const.con->Ico.U8;
-+ ri = LOONGARCH64RI_I(imm, size, isSigned);
-+ }
-+ break;
-+ case Ico_U32:
-+ if (!isSigned && e->Iex.Const.con->Ico.U32 < (1 << size)) {
-+ UShort imm = e->Iex.Const.con->Ico.U32;
-+ ri = LOONGARCH64RI_I(imm, size, isSigned);
-+ }
-+ break;
-+ case Ico_U64:
-+ if (!isSigned && e->Iex.Const.con->Ico.U64 < (1 << size)) {
-+ UShort imm = e->Iex.Const.con->Ico.U64;
-+ ri = LOONGARCH64RI_I(imm, size, isSigned);
-+ }
-+ break;
-+ default:
-+ break;
-+ }
-+ /* else fail, fall through to default case */
++ switch (op) {
++ case LAllsc_LL_W:
++ return "ll.w";
++ case LAllsc_SC_W:
++ return "sc.w";
++ case LAllsc_LL_D:
++ return "ll.d";
++ case LAllsc_SC_D:
++ return "sc.d";
++ default:
++ vpanic("LOONGARCH64LLSCOp");
++ break;
+ }
++}
+
-+ if (ri == NULL) {
-+ /* default case: calculate into a register and return that */
-+ HReg reg = iselIntExpr_R(env, e);
-+ ri = LOONGARCH64RI_R(reg);
++static inline const HChar* showLOONGARCH64BarOp ( LOONGARCH64BarOp op )
++{
++ const HChar* ret;
++ switch (op) {
++ case LAbar_DBAR:
++ return "dbar";
++ case LAbar_IBAR:
++ return "ibar";
++ default:
++ vpanic("showLOONGARCH64BarOp");
++ break;
+ }
-+
-+ return ri;
++ return ret;
+}
+
-+/* --------------------- Reg --------------------- */
-+
-+static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
++static inline const HChar* showLOONGARCH64FpUnOp ( LOONGARCH64FpUnOp op )
+{
-+ HReg r = iselIntExpr_R_wrk(env, e);
-+
-+ /* sanity checks ... */
-+ vassert(hregClass(r) == HRcInt64);
-+ vassert(hregIsVirtual(r));
-+
-+ return r;
++ const HChar* ret;
++ switch (op) {
++ case LAfpun_FABS_S:
++ return "fabs.s";
++ case LAfpun_FABS_D:
++ return "fabs.d";
++ case LAfpun_FNEG_S:
++ return "fneg.s";
++ case LAfpun_FNEG_D:
++ return "fneg.d";
++ case LAfpun_FLOGB_S:
++ return "flogb.s";
++ case LAfpun_FLOGB_D:
++ return "flogb.d";
++ case LAfpun_FSQRT_S:
++ return "fsqrt.s";
++ case LAfpun_FSQRT_D:
++ return "fsqrt.d";
++ case LAfpun_FRSQRT_S:
++ return "frsqrt.s";
++ case LAfpun_FRSQRT_D:
++ return "frsqrt.d";
++ case LAfpun_FCVT_S_D:
++ return "fcvt.s.d";
++ case LAfpun_FCVT_D_S:
++ return "fcvt.d.s";
++ case LAfpun_FTINT_W_S:
++ return "ftint.w.s";
++ case LAfpun_FTINT_W_D:
++ return "ftint.w.d";
++ case LAfpun_FTINT_L_S:
++ return "ftint.l.s";
++ case LAfpun_FTINT_L_D:
++ return "ftint.l.d";
++ case LAfpun_FFINT_S_W:
++ return "ffint.s.w";
++ case LAfpun_FFINT_S_L:
++ return "ffint.s.l";
++ case LAfpun_FFINT_D_W:
++ return "ffint.d.w";
++ case LAfpun_FFINT_D_L:
++ return "ffint.d.l";
++ case LAfpun_FRINT_S:
++ return "frint.s";
++ case LAfpun_FRINT_D:
++ return "frint.d";
++ default:
++ vpanic("showLOONGARCH64FpUnOp");
++ break;
++ }
++ return ret;
+}
+
-+/* DO NOT CALL THIS DIRECTLY ! */
-+static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
++static inline const HChar* showLOONGARCH64FpBinOp ( LOONGARCH64FpBinOp op )
+{
-+ IRType ty = typeOfIRExpr(env->type_env, e);
-+ vassert(e);
-+ vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
-+
-+ switch (e->tag) {
-+ /* --------- TEMP --------- */
-+ case Iex_RdTmp:
-+ return lookupIRTemp(env, e->Iex.RdTmp.tmp);
-+
-+ /* --------- LOAD --------- */
-+ case Iex_Load: {
-+ if (e->Iex.Load.end != Iend_LE)
-+ goto irreducible;
-+
-+ LOONGARCH64AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr, ty);
-+ HReg dst = newVRegI(env);
-+ LOONGARCH64LoadOp op;
-+ switch (ty) {
-+ case Ity_I8:
-+ op = (am->tag == LAam_RI) ? LAload_LD_BU : LAload_LDX_BU;
-+ break;
-+ case Ity_I16:
-+ op = (am->tag == LAam_RI) ? LAload_LD_HU : LAload_LDX_HU;
-+ break;
-+ case Ity_I32:
-+ op = (am->tag == LAam_RI) ? LAload_LD_WU : LAload_LDX_WU;
-+ break;
-+ case Ity_I64:
-+ op = (am->tag == LAam_RI) ? LAload_LD_D : LAload_LDX_D;
-+ break;
-+ default:
-+ goto irreducible;
++ const HChar* ret;
++ switch (op) {
++ case LAfpbin_FADD_S:
++ return "fadd.s";
++ case LAfpbin_FADD_D:
++ return "fadd.d";
++ case LAfpbin_FSUB_S:
++ return "fsub.s";
++ case LAfpbin_FSUB_D:
++ return "fsub.d";
++ case LAfpbin_FMUL_S:
++ return "fmul.s";
++ case LAfpbin_FMUL_D:
++ return "fmul.d";
++ case LAfpbin_FDIV_S:
++ return "fdiv.s";
++ case LAfpbin_FDIV_D:
++ return "fdiv.d";
++ case LAfpbin_FMAX_S:
++ return "fmax.s";
++ case LAfpbin_FMAX_D:
++ return "fmax.d";
++ case LAfpbin_FMIN_S:
++ return "fmin.s";
++ case LAfpbin_FMIN_D:
++ return "fmin.d";
++ case LAfpbin_FMAXA_S:
++ return "fmaxa.s";
++ case LAfpbin_FMAXA_D:
++ return "fmaxa.d";
++ case LAfpbin_FMINA_S:
++ return "fmina.s";
++ case LAfpbin_FMINA_D:
++ return "fmina.d";
++ case LAfpbin_FSCALEB_S:
++ return "fscaleb.s";
++ case LAfpbin_FSCALEB_D:
++ return "fscaleb.d";
++ default:
++ vpanic("showLOONGARCH64FpBinOp");
++ break;
++ }
++ return ret;
++}
++
++static inline const HChar* showLOONGARCH64FpTriOp ( LOONGARCH64FpTriOp op )
++{
++ const HChar* ret;
++ switch (op) {
++ case LAfpbin_FMADD_S:
++ return "fmadd.s";
++ case LAfpbin_FMADD_D:
++ return "fmadd.d";
++ case LAfpbin_FMSUB_S:
++ return "fmsub.s";
++ case LAfpbin_FMSUB_D:
++ return "fmsub.d";
++ default:
++ vpanic("showLOONGARCH64FpTriOp");
++ break;
++ }
++ return ret;
++}
++
++static inline const HChar* showLOONGARCH64FpLoadOp ( LOONGARCH64FpLoadOp op )
++{
++ switch (op) {
++ case LAfpload_FLD_S:
++ return "fld.s";
++ case LAfpload_FLD_D:
++ return "fld.d";
++ case LAfpload_FLDX_S:
++ return "fldx.s";
++ case LAfpload_FLDX_D:
++ return "fldx.d";
++ default:
++ vpanic("LOONGARCH64FpLoadOp");
++ break;
++ }
++}
++
++static inline const HChar* showLOONGARCH64FpStoreOp ( LOONGARCH64FpStoreOp op )
++{
++ switch (op) {
++ case LAfpstore_FST_S:
++ return "fst.s";
++ case LAfpstore_FST_D:
++ return "fst.d";
++ case LAfpstore_FSTX_S:
++ return "fstx.s";
++ case LAfpstore_FSTX_D:
++ return "fstx.d";
++ default:
++ vpanic("LOONGARCH64FpStoreOp");
++ break;
++ }
++}
++
++static inline const HChar* showLOONGARCH64FpMoveOp ( LOONGARCH64FpMoveOp op )
++{
++ switch (op) {
++ case LAfpmove_FMOV_S:
++ return "fmov.s";
++ case LAfpmove_FMOV_D:
++ return "fmov.d";
++ case LAfpmove_MOVGR2FR_W:
++ return "movgr2fr.w";
++ case LAfpmove_MOVGR2FR_D:
++ return "movgr2fr.d";
++ case LAfpmove_MOVFR2GR_S:
++ return "movfr2gr.s";
++ case LAfpmove_MOVFR2GR_D:
++ return "movfr2gr.d";
++ case LAfpmove_MOVGR2FCSR:
++ return "movgr2fcsr";
++ case LAfpmove_MOVFCSR2GR:
++ return "movfcsr2gr";
++ default:
++ vpanic("showLOONGARCH64FpMoveOp");
++ break;
++ }
++}
++
++static inline const HChar* showLOONGARCH64FpCmpOp ( LOONGARCH64FpCmpOp op )
++{
++ const HChar* ret;
++ switch (op) {
++ case LAfpcmp_FCMP_CLT_S:
++ return "fcmp.clt.s";
++ case LAfpcmp_FCMP_CLT_D:
++ return "fcmp.clt.d";
++ case LAfpcmp_FCMP_CEQ_S:
++ return "fcmp.ceq.s";
++ case LAfpcmp_FCMP_CEQ_D:
++ return "fcmp.ceq.d";
++ case LAfpcmp_FCMP_CUN_S:
++ return "fcmp.cun.s";
++ case LAfpcmp_FCMP_CUN_D:
++ return "fcmp.cun.d";
++ default:
++ vpanic("showLOONGARCH64FpCmpOp");
++ break;
++ }
++ return ret;
++}
++
++static inline const HChar* showLOONGARCH64VecUnOp ( LOONGARCH64VecUnOp op )
++{
++ switch (op) {
++ case LAvecun_VCLO_B:
++ return "vclo.b";
++ case LAvecun_VCLO_H:
++ return "vclo.h";
++ case LAvecun_VCLO_W:
++ return "vclo.w";
++ case LAvecun_VCLZ_B:
++ return "vclz.b";
++ case LAvecun_VCLZ_H:
++ return "vclz.h";
++ case LAvecun_VCLZ_W:
++ return "vclz.w";
++ case LAvecun_VCLZ_D:
++ return "vclz.d";
++ case LAvecun_VPCNT_B:
++ return "vpcnt.b";
++ case LAvecun_VFRINTRM_S:
++ return "vfrintrm.s";
++ case LAvecun_VFRINTRM_D:
++ return "vfrintrm.d";
++ case LAvecun_VFRINTRP_S:
++ return "vfrintrp.s";
++ case LAvecun_VFRINTRP_D:
++ return "vfrintrp.d";
++ case LAvecun_VFRINTRZ_S:
++ return "vfrintrz.s";
++ case LAvecun_VFRINTRZ_D:
++ return "vfrintrz.d";
++ case LAvecun_VFRINTRNE_S:
++ return "vfrintrne.s";
++ case LAvecun_VFRINTRNE_D:
++ return "vfrintrne.d";
++ case LAvecun_VEXTH_H_B:
++ return "vexth.h.b";
++ case LAvecun_VEXTH_W_H:
++ return "vexth.w.h";
++ case LAvecun_VEXTH_D_W:
++ return "vexth.d.w";
++ case LAvecun_VEXTH_Q_D:
++ return "vexth.q.d";
++ case LAvecun_VEXTH_HU_BU:
++ return "vexth.hu.bu";
++ case LAvecun_VEXTH_WU_HU:
++ return "vexth.wu.hu";
++ case LAvecun_VEXTH_DU_WU:
++ return "vexth.du.wu";
++ case LAvecun_VEXTH_QU_DU:
++ return "vexth.qu.du";
++ case LAvecun_VREPLGR2VR_B:
++ return "vreplgr2vr.b";
++ case LAvecun_VREPLGR2VR_H:
++ return "vreplgr2vr.h";
++ case LAvecun_VREPLGR2VR_W:
++ return "vreplgr2vr.w";
++ case LAvecun_VREPLGR2VR_D:
++ return "vreplgr2vr.d";
++ default:
++ vpanic("showLOONGARCH64VecUnOp");
++ break;
++ }
++}
++
++static inline const HChar* showLOONGARCH64VecBinOp ( LOONGARCH64VecBinOp op )
++{
++ switch (op) {
++ case LAvecbin_VSEQ_B:
++ return "vseq.b";
++ case LAvecbin_VSEQ_H:
++ return "vseq.h";
++ case LAvecbin_VSEQ_W:
++ return "vseq.w";
++ case LAvecbin_VSEQ_D:
++ return "vseq.d";
++ case LAvecbin_VSLT_B:
++ return "vslt.b";
++ case LAvecbin_VSLT_H:
++ return "vslt.h";
++ case LAvecbin_VSLT_W:
++ return "vslt.w";
++ case LAvecbin_VSLT_D:
++ return "vslt.d";
++ case LAvecbin_VSLT_BU:
++ return "vslt.bu";
++ case LAvecbin_VSLT_HU:
++ return "vslt.hu";
++ case LAvecbin_VSLT_WU:
++ return "vslt.wu";
++ case LAvecbin_VSLT_DU:
++ return "vslt.du";
++ case LAvecbin_VADD_B:
++ return "vadd.b";
++ case LAvecbin_VADD_H:
++ return "vadd.h";
++ case LAvecbin_VADD_W:
++ return "vadd.w";
++ case LAvecbin_VADD_D:
++ return "vadd.d";
++ case LAvecbin_VSUB_B:
++ return "vsub.b";
++ case LAvecbin_VSUB_H:
++ return "vsub.h";
++ case LAvecbin_VSUB_W:
++ return "vsub.w";
++ case LAvecbin_VSUB_D:
++ return "vsub.d";
++ case LAvecbin_VSADD_B:
++ return "vsadd.b";
++ case LAvecbin_VSADD_H:
++ return "vsadd.h";
++ case LAvecbin_VSADD_W:
++ return "vsadd.w";
++ case LAvecbin_VSADD_D:
++ return "vsadd.d";
++ case LAvecbin_VSSUB_B:
++ return "vssub.b";
++ case LAvecbin_VSSUB_H:
++ return "vssub.h";
++ case LAvecbin_VSSUB_W:
++ return "vssub.w";
++ case LAvecbin_VSSUB_D:
++ return "vssub.d";
++ case LAvecbin_VSADD_BU:
++ return "vsadd.bu";
++ case LAvecbin_VSADD_HU:
++ return "vsadd.hu";
++ case LAvecbin_VSADD_WU:
++ return "vsadd.wu";
++ case LAvecbin_VSADD_DU:
++ return "vsadd.du";
++ case LAvecbin_VSSUB_BU:
++ return "vssub.bu";
++ case LAvecbin_VSSUB_HU:
++ return "vssub.hu";
++ case LAvecbin_VSSUB_WU:
++ return "vssub.wu";
++ case LAvecbin_VSSUB_DU:
++ return "vssub.du";
++ case LAvecbin_VADDA_B:
++ return "vadda.b";
++ case LAvecbin_VADDA_H:
++ return "vadda.h";
++ case LAvecbin_VADDA_W:
++ return "vadda.w";
++ case LAvecbin_VADDA_D:
++ return "vadda.d";
++ case LAvecbin_VAVGR_B:
++ return "vavgr.b";
++ case LAvecbin_VAVGR_H:
++ return "vavgr.h";
++ case LAvecbin_VAVGR_W:
++ return "vavgr.w";
++ case LAvecbin_VAVGR_D:
++ return "vavgr.d";
++ case LAvecbin_VAVGR_BU:
++ return "vavgr.bu";
++ case LAvecbin_VAVGR_HU:
++ return "vavgr.hu";
++ case LAvecbin_VAVGR_WU:
++ return "vavgr.wu";
++ case LAvecbin_VAVGR_DU:
++ return "vavgr.du";
++ case LAvecbin_VMAX_B:
++ return "vmax.b";
++ case LAvecbin_VMAX_H:
++ return "vmax.h";
++ case LAvecbin_VMAX_W:
++ return "vmax.w";
++ case LAvecbin_VMAX_D:
++ return "vmax.d";
++ case LAvecbin_VMIN_B:
++ return "vmin.b";
++ case LAvecbin_VMIN_H:
++ return "vmin.h";
++ case LAvecbin_VMIN_W:
++ return "vmin.w";
++ case LAvecbin_VMIN_D:
++ return "vmin.d";
++ case LAvecbin_VMAX_BU:
++ return "vmax.bu";
++ case LAvecbin_VMAX_HU:
++ return "vmax.hu";
++ case LAvecbin_VMAX_WU:
++ return "vmax.wu";
++ case LAvecbin_VMAX_DU:
++ return "vmax.du";
++ case LAvecbin_VMIN_BU:
++ return "vmin.bu";
++ case LAvecbin_VMIN_HU:
++ return "vmin.hu";
++ case LAvecbin_VMIN_WU:
++ return "vmin.wu";
++ case LAvecbin_VMIN_DU:
++ return "vmin.du";
++ case LAvecbin_VMUL_B:
++ return "vmul.b";
++ case LAvecbin_VMUL_H:
++ return "vmul.h";
++ case LAvecbin_VMUL_W:
++ return "vmul.w";
++ case LAvecbin_VMUH_B:
++ return "vmuh.b";
++ case LAvecbin_VMUH_H:
++ return "vmuh.h";
++ case LAvecbin_VMUH_W:
++ return "vmuh.w";
++ case LAvecbin_VMUH_BU:
++ return "vmuh.bu";
++ case LAvecbin_VMUH_HU:
++ return "vmuh.hu";
++ case LAvecbin_VMUH_WU:
++ return "vmuh.wu";
++ case LAvecbin_VSLL_B:
++ return "vsll.b";
++ case LAvecbin_VSLL_H:
++ return "vsll.h";
++ case LAvecbin_VSLL_W:
++ return "vsll.w";
++ case LAvecbin_VSLL_D:
++ return "vsll.d";
++ case LAvecbin_VSRL_B:
++ return "vsrl.b";
++ case LAvecbin_VSRL_H:
++ return "vsrl.h";
++ case LAvecbin_VSRL_W:
++ return "vsrl.w";
++ case LAvecbin_VSRL_D:
++ return "vsrl.d";
++ case LAvecbin_VSRA_B:
++ return "vsra.b";
++ case LAvecbin_VSRA_H:
++ return "vsra.h";
++ case LAvecbin_VSRA_W:
++ return "vsra.w";
++ case LAvecbin_VSRA_D:
++ return "vsra.d";
++ case LAvecbin_VILVL_B:
++ return "vilvl.b";
++ case LAvecbin_VILVL_H:
++ return "vilvl.h";
++ case LAvecbin_VILVL_W:
++ return "vilvl.w";
++ case LAvecbin_VILVL_D:
++ return "vilvl.d";
++ case LAvecbin_VILVH_B:
++ return "vilvh.b";
++ case LAvecbin_VILVH_H:
++ return "vilvh.h";
++ case LAvecbin_VILVH_W:
++ return "vilvh.w";
++ case LAvecbin_VILVH_D:
++ return "vilvh.d";
++ case LAvecbin_VPICKEV_B:
++ return "vpickev.b";
++ case LAvecbin_VPICKEV_H:
++ return "vpickev.h";
++ case LAvecbin_VPICKEV_W:
++ return "vpickev.w";
++ case LAvecbin_VPICKOD_B:
++ return "vpickod.b";
++ case LAvecbin_VPICKOD_H:
++ return "vpickod.h";
++ case LAvecbin_VPICKOD_W:
++ return "vpickod.w";
++ case LAvecbin_VREPLVE_B:
++ return "vreplve.b";
++ case LAvecbin_VREPLVE_H:
++ return "vreplve.h";
++ case LAvecbin_VREPLVE_W:
++ return "vreplve.w";
++ case LAvecbin_VREPLVE_D:
++ return "vreplve.d";
++ case LAvecbin_VAND_V:
++ return "vand.v";
++ case LAvecbin_VOR_V:
++ return "vor.v";
++ case LAvecbin_VXOR_V:
++ return "vxor.v";
++ case LAvecbin_VNOR_V:
++ return "vnor.v";
++ case LAvecbin_VADD_Q:
++ return "vadd.q";
++ case LAvecbin_VSUB_Q:
++ return "vsub.q";
++ case LAvecbin_VFADD_S:
++ return "vfadd.s";
++ case LAvecbin_VFADD_D:
++ return "vfadd.d";
++ case LAvecbin_VFSUB_S:
++ return "vfsub.s";
++ case LAvecbin_VFSUB_D:
++ return "vfsub.d";
++ case LAvecbin_VFMUL_S:
++ return "vfmul.s";
++ case LAvecbin_VFMUL_D:
++ return "vfmul.d";
++ case LAvecbin_VFDIV_S:
++ return "vfdiv.s";
++ case LAvecbin_VFDIV_D:
++ return "vfdiv.d";
++ case LAvecbin_VFMAX_S:
++ return "vfmax.s";
++ case LAvecbin_VFMAX_D:
++ return "vfmax.d";
++ case LAvecbin_VFMIN_S:
++ return "vfmin.s";
++ case LAvecbin_VFMIN_D:
++ return "vfmin.d";
++ case LAvecbin_VBSLL_V:
++ return "vbsll.v";
++ case LAvecbin_VBSRL_V:
++ return "vbsrl.v";
++ case LAvecbin_VINSGR2VR_B:
++ return "vinsgr2vr.b";
++ case LAvecbin_VINSGR2VR_H:
++ return "vinsgr2vr.h";
++ case LAvecbin_VINSGR2VR_W:
++ return "vinsgr2vr.w";
++ case LAvecbin_VINSGR2VR_D:
++ return "vinsgr2vr.d";
++ case LAvecbin_VPICKVE2GR_W:
++ return "vpickve2gr.w";
++ case LAvecbin_VPICKVE2GR_D:
++ return "vpickve2gr.d";
++ case LAvecbin_VPICKVE2GR_BU:
++ return "vpickve2gr.bu";
++ case LAvecbin_VPICKVE2GR_HU:
++ return "vpickve2gr.hu";
++ case LAvecbin_VPICKVE2GR_WU:
++ return "vpickve2gr.wu";
++ case LAvecbin_VPICKVE2GR_DU:
++ return "vpickve2gr.du";
++ case LAvecbin_VSLLI_B:
++ return "vslli.b";
++ case LAvecbin_VSLLI_H:
++ return "vslli.h";
++ case LAvecbin_VSLLI_W:
++ return "vslli.w";
++ case LAvecbin_VSLLI_D:
++ return "vslli.d";
++ case LAvecbin_VSRLI_B:
++ return "vsrli.b";
++ case LAvecbin_VSRLI_H:
++ return "vsrli.h";
++ case LAvecbin_VSRLI_W:
++ return "vsrli.w";
++ case LAvecbin_VSRLI_D:
++ return "vsrli.d";
++ case LAvecbin_VSRAI_B:
++ return "vsrai.b";
++ case LAvecbin_VSRAI_H:
++ return "vsrai.h";
++ case LAvecbin_VSRAI_W:
++ return "vsrai.w";
++ case LAvecbin_VSRAI_D:
++ return "vsrai.d";
++ case LAvecbin_VORI_B:
++ return "vori.b";
++ default:
++ vpanic("showLOONGARCH64VecBinOp");
++ break;
++ }
++}
++
++static inline const HChar* showLOONGARCH64VecLoadOp ( LOONGARCH64VecLoadOp op )
++{
++ switch (op) {
++ case LAvecload_VLD:
++ return "vld";
++ case LAvecload_VLDX:
++ return "vldx";
++ default:
++ vpanic("showLOONGARCH64VecLoadOp");
++ break;
++ }
++}
++
++static inline const HChar* showLOONGARCH64VecStoreOp ( LOONGARCH64VecStoreOp op )
++{
++ switch (op) {
++ case LAvecstore_VST:
++ return "vst";
++ case LAvecstore_VSTX:
++ return "vstx";
++ default:
++ vpanic("showLOONGARCH64VecStoreOp");
++ break;
++ }
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_LI ( ULong imm, HReg dst )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_LI;
++ i->LAin.LI.imm = imm;
++ i->LAin.LI.dst = dst;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_Unary ( LOONGARCH64UnOp op,
++ HReg src, HReg dst )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_Un;
++ i->LAin.Unary.op = op;
++ i->LAin.Unary.src = src;
++ i->LAin.Unary.dst = dst;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_Binary ( LOONGARCH64BinOp op,
++ LOONGARCH64RI* src2,
++ HReg src1, HReg dst )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_Bin;
++ i->LAin.Binary.op = op;
++ i->LAin.Binary.src2 = src2;
++ i->LAin.Binary.src1 = src1;
++ i->LAin.Binary.dst = dst;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_Load ( LOONGARCH64LoadOp op,
++ LOONGARCH64AMode* src, HReg dst )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_Load;
++ i->LAin.Load.op = op;
++ i->LAin.Load.src = src;
++ i->LAin.Load.dst = dst;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_Store ( LOONGARCH64StoreOp op,
++ LOONGARCH64AMode* dst, HReg src )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_Store;
++ i->LAin.Store.op = op;
++ i->LAin.Store.dst = dst;
++ i->LAin.Store.src = src;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_LLSC ( LOONGARCH64LLSCOp op, Bool isLoad,
++ LOONGARCH64AMode* addr, HReg val )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_LLSC;
++ i->LAin.LLSC.op = op;
++ i->LAin.LLSC.isLoad = isLoad;
++ i->LAin.LLSC.addr = addr;
++ i->LAin.LLSC.val = val;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_Bar ( LOONGARCH64BarOp op, UShort hint )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_Bar;
++ i->LAin.Bar.op = op;
++ i->LAin.Bar.hint = hint;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_FpUnary ( LOONGARCH64FpUnOp op,
++ HReg src, HReg dst )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_FpUn;
++ i->LAin.FpUnary.op = op;
++ i->LAin.FpUnary.src = src;
++ i->LAin.FpUnary.dst = dst;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_FpBinary ( LOONGARCH64FpBinOp op, HReg src2,
++ HReg src1, HReg dst )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_FpBin;
++ i->LAin.FpBinary.op = op;
++ i->LAin.FpBinary.src2 = src2;
++ i->LAin.FpBinary.src1 = src1;
++ i->LAin.FpBinary.dst = dst;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_FpTrinary ( LOONGARCH64FpTriOp op,
++ HReg src3, HReg src2,
++ HReg src1, HReg dst )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_FpTri;
++ i->LAin.FpTrinary.op = op;
++ i->LAin.FpTrinary.src3 = src3;
++ i->LAin.FpTrinary.src2 = src2;
++ i->LAin.FpTrinary.src1 = src1;
++ i->LAin.FpTrinary.dst = dst;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_FpLoad ( LOONGARCH64FpLoadOp op,
++ LOONGARCH64AMode* src, HReg dst )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_FpLoad;
++ i->LAin.FpLoad.op = op;
++ i->LAin.FpLoad.src = src;
++ i->LAin.FpLoad.dst = dst;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_FpStore ( LOONGARCH64FpStoreOp op,
++ LOONGARCH64AMode* dst, HReg src )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_FpStore;
++ i->LAin.FpStore.op = op;
++ i->LAin.FpStore.dst = dst;
++ i->LAin.FpStore.src = src;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_FpMove ( LOONGARCH64FpMoveOp op,
++ HReg src, HReg dst )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_FpMove;
++ i->LAin.FpMove.op = op;
++ i->LAin.FpMove.src = src;
++ i->LAin.FpMove.dst = dst;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_FpCmp ( LOONGARCH64FpCmpOp op, HReg src2,
++ HReg src1, HReg dst )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_FpCmp;
++ i->LAin.FpCmp.op = op;
++ i->LAin.FpCmp.src2 = src2;
++ i->LAin.FpCmp.src1 = src1;
++ i->LAin.FpCmp.dst = dst;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_VecUnary ( LOONGARCH64VecUnOp op,
++ HReg src, HReg dst )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_VecUn;
++ i->LAin.VecUnary.op = op;
++ i->LAin.VecUnary.src = src;
++ i->LAin.VecUnary.dst = dst;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_VecBinary ( LOONGARCH64VecBinOp op,
++ LOONGARCH64RI* src2,
++ HReg src1, HReg dst )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_VecBin;
++ i->LAin.VecBinary.op = op;
++ i->LAin.VecBinary.src2 = src2;
++ i->LAin.VecBinary.src1 = src1;
++ i->LAin.VecBinary.dst = dst;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_VecLoad ( LOONGARCH64VecLoadOp op,
++ LOONGARCH64AMode* src, HReg dst )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_VecLoad;
++ i->LAin.VecLoad.op = op;
++ i->LAin.VecLoad.src = src;
++ i->LAin.VecLoad.dst = dst;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_VecStore ( LOONGARCH64VecStoreOp op,
++ LOONGARCH64AMode* dst, HReg src)
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_VecStore;
++ i->LAin.VecStore.op = op;
++ i->LAin.VecStore.dst = dst;
++ i->LAin.VecStore.src = src;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_Cas ( HReg old, HReg addr, HReg expd,
++ HReg data, Bool size64 )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_Cas;
++ i->LAin.Cas.old = old;
++ i->LAin.Cas.addr = addr;
++ i->LAin.Cas.expd = expd;
++ i->LAin.Cas.data = data;
++ i->LAin.Cas.size64 = size64;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_Cmp ( LOONGARCH64CondCode cond,
++ HReg src2, HReg src1, HReg dst )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_Cmp;
++ i->LAin.Cmp.cond = cond;
++ i->LAin.Cmp.src2 = src2;
++ i->LAin.Cmp.src1 = src1;
++ i->LAin.Cmp.dst = dst;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_CMove ( HReg cond, HReg r0, HReg r1,
++ HReg dst, Bool isInt )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_CMove;
++ i->LAin.CMove.cond = cond;
++ i->LAin.CMove.r0 = r0;
++ i->LAin.CMove.r1 = r1;
++ i->LAin.CMove.dst = dst;
++ i->LAin.CMove.isInt = isInt;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_Call ( HReg cond, Addr64 target,
++ UInt nArgRegs, RetLoc rloc )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_Call;
++ i->LAin.Call.cond = cond;
++ i->LAin.Call.target = target;
++ i->LAin.Call.nArgRegs = nArgRegs;
++ i->LAin.Call.rloc = rloc;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_XDirect ( Addr64 dstGA,
++ LOONGARCH64AMode* amPC,
++ HReg cond, Bool toFastEP )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_XDirect;
++ i->LAin.XDirect.dstGA = dstGA;
++ i->LAin.XDirect.amPC = amPC;
++ i->LAin.XDirect.cond = cond;
++ i->LAin.XDirect.toFastEP = toFastEP;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_XIndir ( HReg dstGA, LOONGARCH64AMode* amPC,
++ HReg cond )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_XIndir;
++ i->LAin.XIndir.dstGA = dstGA;
++ i->LAin.XIndir.amPC = amPC;
++ i->LAin.XIndir.cond = cond;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_XAssisted ( HReg dstGA,
++ LOONGARCH64AMode* amPC,
++ HReg cond, IRJumpKind jk )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_XAssisted;
++ i->LAin.XAssisted.dstGA = dstGA;
++ i->LAin.XAssisted.amPC = amPC;
++ i->LAin.XAssisted.cond = cond;
++ i->LAin.XAssisted.jk = jk;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_EvCheck ( LOONGARCH64AMode* amCounter,
++ LOONGARCH64AMode* amFailAddr )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_EvCheck;
++ i->LAin.EvCheck.amCounter = amCounter;
++ i->LAin.EvCheck.amFailAddr = amFailAddr;
++ return i;
++}
++
++LOONGARCH64Instr* LOONGARCH64Instr_ProfInc ( void )
++{
++ LOONGARCH64Instr* i = LibVEX_Alloc_inline(sizeof(LOONGARCH64Instr));
++ i->tag = LAin_ProfInc;
++ return i;
++}
++
++
++/* -------- Pretty Print instructions ------------- */
++
++static inline void ppLI ( ULong imm, HReg dst )
++{
++ vex_printf("li ");
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", 0x%llx", imm);
++}
++
++static inline void ppUnary ( LOONGARCH64UnOp op, HReg src, HReg dst )
++{
++ vex_printf("%s ", showLOONGARCH64UnOp(op));
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(src);
++}
++
++static inline void ppBinary ( LOONGARCH64BinOp op, LOONGARCH64RI* src2,
++ HReg src1, HReg dst )
++{
++ vex_printf("%s ", showLOONGARCH64BinOp(op));
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(src1);
++ vex_printf(", ");
++ ppLOONGARCH64RI(src2);
++}
++
++static inline void ppLoad ( LOONGARCH64LoadOp op, LOONGARCH64AMode* src,
++ HReg dst )
++{
++ vex_printf("%s ", showLOONGARCH64LoadOp(op));
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", ");
++ ppLOONGARCH64AMode(src);
++}
++
++static inline void ppStore ( LOONGARCH64StoreOp op, LOONGARCH64AMode* dst,
++ HReg src )
++{
++ vex_printf("%s ", showLOONGARCH64StoreOp(op));
++ ppHRegLOONGARCH64(src);
++ vex_printf(", ");
++ ppLOONGARCH64AMode(dst);
++}
++
++static inline void ppLLSC ( LOONGARCH64LLSCOp op, LOONGARCH64AMode* addr,
++ HReg val )
++{
++ vex_printf("%s ", showLOONGARCH64LLSCOp(op));
++ ppHRegLOONGARCH64(val);
++ vex_printf(", ");
++ ppLOONGARCH64AMode(addr);
++}
++
++static inline void ppBar ( LOONGARCH64BarOp op, UShort hint )
++{
++ vex_printf("%s %u", showLOONGARCH64BarOp(op), (UInt)hint);
++}
++
++static inline void ppFpUnary ( LOONGARCH64FpUnOp op, HReg src, HReg dst )
++{
++ vex_printf("%s ", showLOONGARCH64FpUnOp(op));
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(src);
++}
++
++static inline void ppFpBinary ( LOONGARCH64FpBinOp op, HReg src2,
++ HReg src1, HReg dst )
++{
++ vex_printf("%s ", showLOONGARCH64FpBinOp(op));
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(src1);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(src2);
++}
++
++static inline void ppFpTrinary ( LOONGARCH64FpTriOp op, HReg src3,
++ HReg src2, HReg src1, HReg dst )
++{
++ vex_printf("%s ", showLOONGARCH64FpTriOp(op));
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(src1);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(src2);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(src3);
++}
++
++static inline void ppFpLoad ( LOONGARCH64FpLoadOp op, LOONGARCH64AMode* src,
++ HReg dst )
++{
++ vex_printf("%s ", showLOONGARCH64FpLoadOp(op));
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", ");
++ ppLOONGARCH64AMode(src);
++}
++
++static inline void ppFpStore ( LOONGARCH64FpStoreOp op, LOONGARCH64AMode* dst,
++ HReg src )
++{
++ vex_printf("%s ", showLOONGARCH64FpStoreOp(op));
++ ppHRegLOONGARCH64(src);
++ vex_printf(", ");
++ ppLOONGARCH64AMode(dst);
++}
++
++static inline void ppFpMove ( LOONGARCH64FpMoveOp op, HReg src, HReg dst )
++{
++ vex_printf("%s ", showLOONGARCH64FpMoveOp(op));
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(src);
++}
++
++static inline void ppFpCmp ( LOONGARCH64FpCmpOp op, HReg src2,
++ HReg src1, HReg dst )
++{
++ vex_printf("%s ", showLOONGARCH64FpCmpOp(op));
++ vex_printf("$fcc0, ");
++ ppHRegLOONGARCH64(src1);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(src2);
++ vex_printf("; movcf2gr ");
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", $fcc0");
++}
++
++static inline void ppVecUnary ( LOONGARCH64VecUnOp op, HReg src, HReg dst )
++{
++ vex_printf("%s ", showLOONGARCH64VecUnOp(op));
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(src);
++}
++
++static inline void ppVecBinary ( LOONGARCH64VecBinOp op, LOONGARCH64RI* src2,
++ HReg src1, HReg dst )
++{
++ vex_printf("%s ", showLOONGARCH64VecBinOp(op));
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(src1);
++ vex_printf(", ");
++ ppLOONGARCH64RI(src2);
++}
++
++static inline void ppVecLoad ( LOONGARCH64VecLoadOp op, LOONGARCH64AMode* src,
++ HReg dst )
++{
++ vex_printf("%s ", showLOONGARCH64VecLoadOp(op));
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", ");
++ ppLOONGARCH64AMode(src);
++}
++
++static inline void ppVecStore ( LOONGARCH64VecStoreOp op, LOONGARCH64AMode* dst,
++ HReg src )
++{
++ vex_printf("%s ", showLOONGARCH64VecStoreOp(op));
++ ppHRegLOONGARCH64(src);
++ vex_printf(", ");
++ ppLOONGARCH64AMode(dst);
++}
++
++static inline void ppCas ( HReg old, HReg addr, HReg expd,
++ HReg data, Bool size64)
++{
++ ppHRegLOONGARCH64(old);
++ vex_printf(" = cas(%dbit)(", size64 ? 64 : 32);
++ ppHRegLOONGARCH64(expd);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(data);
++ vex_printf(" -> ");
++ ppHRegLOONGARCH64(addr);
++ vex_printf(")");
++}
++
++static inline void ppCmp ( LOONGARCH64CondCode cond, HReg src2,
++ HReg src1, HReg dst )
++{
++ ppHRegLOONGARCH64(dst);
++ vex_printf(" = cmp%s(", showLOONGARCH64CondCode(cond));
++ ppHRegLOONGARCH64(src1);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(src2);
++ vex_printf(")");
++}
++
++static inline void ppCMove ( HReg cond, HReg r0, HReg r1,
++ HReg dst, Bool isInt )
++{
++ if (isInt) {
++ vex_printf("masknez $t0, ");
++ ppHRegLOONGARCH64(r0);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(cond);
++ vex_printf("; maskeqz ");
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(r1);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(cond);
++ vex_printf("; or ");
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", $t0, ");
++ ppHRegLOONGARCH64(dst);
++ } else {
++ vex_printf("movgr2cf ");
++ ppHRegLOONGARCH64(cond);
++ vex_printf(", $fcc0; fsel ");
++ ppHRegLOONGARCH64(dst);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(r0);
++ vex_printf(", ");
++ ppHRegLOONGARCH64(r1);
++ vex_printf(", $fcc0");
++ }
++}
++
++static inline void ppCall ( HReg cond, Addr64 target,
++ UInt nArgRegs, RetLoc rloc )
++{
++ if (!hregIsInvalid(cond)) {
++ vex_printf("if (");
++ ppHRegLOONGARCH64(cond);
++ vex_printf(") { ");
++ }
++ vex_printf("call 0x%llx [nArgRegs=%u, ", target, nArgRegs);
++ ppRetLoc(rloc);
++ vex_printf("]");
++ if (!hregIsInvalid(cond))
++ vex_printf(" }");
++}
++
++static inline void ppXDirect ( Addr64 dstGA, LOONGARCH64AMode* amPC,
++ HReg cond, Bool toFastEP )
++{
++ vex_printf("(xDirect) ");
++ if (!hregIsInvalid(cond)) {
++ vex_printf("if (");
++ ppHRegLOONGARCH64(cond);
++ vex_printf(") { ");
++ }
++ vex_printf("li $t0, 0x%llx; ", (ULong)dstGA);
++ vex_printf("st.w $t0, ");
++ ppLOONGARCH64AMode(amPC);
++ vex_printf("; li $t0, $disp_cp_chain_me_to_%sEP; ",
++ toFastEP ? "fast" : "slow");
++ vex_printf("jirl $ra, $t0, 0");
++ if (!hregIsInvalid(cond))
++ vex_printf(" }");
++}
++
++static inline void ppXIndir ( HReg dstGA, LOONGARCH64AMode* amPC,
++ HReg cond )
++{
++ vex_printf("(xIndir) ");
++ if (!hregIsInvalid(cond)) {
++ vex_printf("if (");
++ ppHRegLOONGARCH64(cond);
++ vex_printf(") { ");
++ }
++ vex_printf("st.w ");
++ ppHRegLOONGARCH64(dstGA);
++ vex_printf(", ");
++ ppLOONGARCH64AMode(amPC);
++ vex_printf("; la $t0, disp_indir; ");
++ vex_printf("jirl $ra, $t0, 0");
++ if (!hregIsInvalid(cond))
++ vex_printf(" }");
++}
++
++static inline void ppXAssisted ( HReg dstGA, LOONGARCH64AMode* amPC,
++ HReg cond, IRJumpKind jk)
++{
++ vex_printf("(xAssisted) ");
++ if (!hregIsInvalid(cond)) {
++ vex_printf("if (");
++ ppHRegLOONGARCH64(cond);
++ vex_printf(") { ");
++ }
++ vex_printf("st.w ");
++ ppHRegLOONGARCH64(dstGA);
++ vex_printf(", ");
++ ppLOONGARCH64AMode(amPC);
++ vex_printf("; li.w $s8, IRJumpKind_to_TRCVAL(%d); ", (Int)jk);
++ vex_printf("la $t0, disp_assisted; ");
++ vex_printf("jirl $ra, $t0, 0");
++ if (!hregIsInvalid(cond))
++ vex_printf(" }");
++}
++
++static inline void ppEvCheck ( LOONGARCH64AMode* amCounter,
++ LOONGARCH64AMode* amFailAddr )
++{
++ vex_printf("(evCheck) ");
++ vex_printf("ld.w $t0, ");
++ ppLOONGARCH64AMode(amCounter);
++ vex_printf("; addi.d $t0, $t0, -1; ");
++ vex_printf("st.w $t0, ");
++ ppLOONGARCH64AMode(amCounter);
++ vex_printf("; bge $t0, $zero, nofail; ");
++ vex_printf("ld.d $t0, ");
++ ppLOONGARCH64AMode(amFailAddr);
++ vex_printf("; jirl $ra, $t0, 0");
++ vex_printf("; nofail:");
++}
++
++static inline void ppProfInc ( void )
++{
++ vex_printf("(profInc) ");
++ vex_printf("li $t0, NotKnownYet; ");
++ vex_printf("ld.d $t1, $t0, 0; ");
++ vex_printf("addi.d $t1, $t1, 1; ");
++ vex_printf("st.d $t1, $t0, 0;");
++}
++
++void ppLOONGARCH64Instr ( const LOONGARCH64Instr* i, Bool mode64 )
++{
++ vassert(mode64 == True);
++ switch (i->tag) {
++ case LAin_LI:
++ ppLI(i->LAin.LI.imm, i->LAin.LI.dst);
++ break;
++ case LAin_Un:
++ ppUnary(i->LAin.Unary.op, i->LAin.Unary.src, i->LAin.Unary.dst);
++ break;
++ case LAin_Bin:
++ ppBinary(i->LAin.Binary.op, i->LAin.Binary.src2,
++ i->LAin.Binary.src1, i->LAin.Binary.dst);
++ break;
++ case LAin_Load:
++ ppLoad(i->LAin.Load.op, i->LAin.Load.src, i->LAin.Load.dst);
++ break;
++ case LAin_Store:
++ ppStore(i->LAin.Store.op, i->LAin.Store.dst, i->LAin.Store.src);
++ break;
++ case LAin_LLSC:
++ ppLLSC(i->LAin.LLSC.op, i->LAin.LLSC.addr, i->LAin.LLSC.val);
++ break;
++ case LAin_Bar:
++ ppBar(i->LAin.Bar.op, i->LAin.Bar.hint);
++ break;
++ case LAin_FpUn:
++ ppFpUnary(i->LAin.FpUnary.op, i->LAin.FpUnary.src,
++ i->LAin.FpUnary.dst);
++ break;
++ case LAin_FpBin:
++ ppFpBinary(i->LAin.FpBinary.op, i->LAin.FpBinary.src2,
++ i->LAin.FpBinary.src1, i->LAin.FpBinary.dst);
++ break;
++ case LAin_FpTri:
++ ppFpTrinary(i->LAin.FpTrinary.op, i->LAin.FpTrinary.src3,
++ i->LAin.FpTrinary.src2, i->LAin.FpTrinary.src1,
++ i->LAin.FpTrinary.dst);
++ break;
++ case LAin_FpLoad:
++ ppFpLoad(i->LAin.FpLoad.op, i->LAin.FpLoad.src, i->LAin.FpLoad.dst);
++ break;
++ case LAin_FpStore:
++ ppFpStore(i->LAin.FpStore.op, i->LAin.FpStore.dst,
++ i->LAin.FpStore.src);
++ break;
++ case LAin_FpMove:
++ ppFpMove(i->LAin.FpMove.op, i->LAin.FpMove.src,
++ i->LAin.FpMove.dst);
++ break;
++ case LAin_FpCmp:
++ ppFpCmp(i->LAin.FpCmp.op, i->LAin.FpCmp.src2,
++ i->LAin.FpCmp.src1, i->LAin.FpCmp.dst);
++ break;
++ case LAin_VecUn:
++ ppVecUnary(i->LAin.VecUnary.op, i->LAin.VecUnary.src,
++ i->LAin.VecUnary.dst);
++ break;
++ case LAin_VecBin:
++ ppVecBinary(i->LAin.VecBinary.op, i->LAin.VecBinary.src2,
++ i->LAin.VecBinary.src1, i->LAin.VecBinary.dst);
++ break;
++ case LAin_VecLoad:
++ ppVecLoad(i->LAin.VecLoad.op, i->LAin.VecLoad.src,
++ i->LAin.VecLoad.dst);
++ break;
++ case LAin_VecStore:
++ ppVecStore(i->LAin.VecStore.op, i->LAin.VecStore.dst,
++ i->LAin.VecStore.src);
++ break;
++ case LAin_Cas:
++ ppCas(i->LAin.Cas.old, i->LAin.Cas.addr, i->LAin.Cas.expd,
++ i->LAin.Cas.data, i->LAin.Cas.size64);
++ break;
++ case LAin_Cmp:
++ ppCmp(i->LAin.Cmp.cond, i->LAin.Cmp.src2,
++ i->LAin.Cmp.src1, i->LAin.Cmp.dst);
++ break;
++ case LAin_CMove:
++ ppCMove(i->LAin.CMove.cond, i->LAin.CMove.r0,
++ i->LAin.CMove.r1, i->LAin.CMove.dst,
++ i->LAin.CMove.isInt);
++ break;
++ case LAin_Call:
++ ppCall(i->LAin.Call.cond, i->LAin.Call.target,
++ i->LAin.Call.nArgRegs, i->LAin.Call.rloc);
++ break;
++ case LAin_XDirect:
++ ppXDirect(i->LAin.XDirect.dstGA, i->LAin.XDirect.amPC,
++ i->LAin.XDirect.cond, i->LAin.XDirect.toFastEP);
++ break;
++ case LAin_XIndir:
++ ppXIndir(i->LAin.XIndir.dstGA, i->LAin.XIndir.amPC,
++ i->LAin.XIndir.cond);
++ break;
++ case LAin_XAssisted:
++ ppXAssisted(i->LAin.XAssisted.dstGA, i->LAin.XAssisted.amPC,
++ i->LAin.XAssisted.cond, i->LAin.XAssisted.jk);
++ break;
++ case LAin_EvCheck:
++ ppEvCheck(i->LAin.EvCheck.amCounter, i->LAin.EvCheck.amFailAddr);
++ break;
++ case LAin_ProfInc:
++ ppProfInc();
++ break;
++ default:
++ vpanic("ppLOONGARCH64Instr");
++ break;
++ }
++}
++
++
++/* --------- Helpers for register allocation. --------- */
++
++void getRegUsage_LOONGARCH64Instr ( HRegUsage* u, const LOONGARCH64Instr* i,
++ Bool mode64 )
++{
++ vassert(mode64 == True);
++ initHRegUsage(u);
++ switch (i->tag) {
++ case LAin_LI:
++ addHRegUse(u, HRmWrite, i->LAin.LI.dst);
++ break;
++ case LAin_Un:
++ addHRegUse(u, HRmRead, i->LAin.Unary.src);
++ addHRegUse(u, HRmWrite, i->LAin.Unary.dst);
++ break;
++ case LAin_Bin:
++ addRegUsage_LOONGARCH64RI(u, i->LAin.Binary.src2);
++ addHRegUse(u, HRmRead, i->LAin.Binary.src1);
++ addHRegUse(u, HRmWrite, i->LAin.Binary.dst);
++ break;
++ case LAin_Load:
++ addRegUsage_LOONGARCH64AMode(u, i->LAin.Load.src);
++ addHRegUse(u, HRmWrite, i->LAin.Load.dst);
++ break;
++ case LAin_Store:
++ addRegUsage_LOONGARCH64AMode(u, i->LAin.Store.dst);
++ addHRegUse(u, HRmRead, i->LAin.Store.src);
++ break;
++ case LAin_LLSC:
++ addRegUsage_LOONGARCH64AMode(u, i->LAin.LLSC.addr);
++ if (i->LAin.LLSC.isLoad)
++ addHRegUse(u, HRmWrite, i->LAin.LLSC.val);
++ else
++ addHRegUse(u, HRmRead, i->LAin.LLSC.val);
++ break;
++ case LAin_Bar:
++ /* No regs. */
++ break;
++ case LAin_FpUn:
++ addHRegUse(u, HRmRead, i->LAin.FpUnary.src);
++ addHRegUse(u, HRmWrite, i->LAin.FpUnary.dst);
++ break;
++ case LAin_FpBin:
++ addHRegUse(u, HRmRead, i->LAin.FpBinary.src2);
++ addHRegUse(u, HRmRead, i->LAin.FpBinary.src1);
++ addHRegUse(u, HRmWrite, i->LAin.FpBinary.dst);
++ break;
++ case LAin_FpTri:
++ addHRegUse(u, HRmRead, i->LAin.FpTrinary.src3);
++ addHRegUse(u, HRmRead, i->LAin.FpTrinary.src2);
++ addHRegUse(u, HRmRead, i->LAin.FpTrinary.src1);
++ addHRegUse(u, HRmWrite, i->LAin.FpTrinary.dst);
++ break;
++ case LAin_FpLoad:
++ addRegUsage_LOONGARCH64AMode(u, i->LAin.FpLoad.src);
++ addHRegUse(u, HRmWrite, i->LAin.FpLoad.dst);
++ break;
++ case LAin_FpStore:
++ addRegUsage_LOONGARCH64AMode(u, i->LAin.FpStore.dst);
++ addHRegUse(u, HRmRead, i->LAin.FpStore.src);
++ break;
++ case LAin_FpMove:
++ addHRegUse(u, HRmRead, i->LAin.FpMove.src);
++ addHRegUse(u, HRmWrite, i->LAin.FpMove.dst);
++ break;
++ case LAin_FpCmp:
++ addHRegUse(u, HRmRead, i->LAin.FpCmp.src2);
++ addHRegUse(u, HRmRead, i->LAin.FpCmp.src1);
++ addHRegUse(u, HRmWrite, i->LAin.FpCmp.dst);
++ break;
++ case LAin_VecUn:
++ addHRegUse(u, HRmRead, i->LAin.VecUnary.src);
++ addHRegUse(u, HRmWrite, i->LAin.VecUnary.dst);
++ break;
++ case LAin_VecBin:
++ addRegUsage_LOONGARCH64RI(u, i->LAin.VecBinary.src2);
++ addHRegUse(u, HRmRead, i->LAin.VecBinary.src1);
++ addHRegUse(u, HRmWrite, i->LAin.VecBinary.dst);
++ break;
++ case LAin_VecLoad:
++ addRegUsage_LOONGARCH64AMode(u, i->LAin.VecLoad.src);
++ addHRegUse(u, HRmWrite, i->LAin.VecLoad.dst);
++ break;
++ case LAin_VecStore:
++ addRegUsage_LOONGARCH64AMode(u, i->LAin.VecStore.dst);
++ addHRegUse(u, HRmRead, i->LAin.VecStore.src);
++ break;
++ case LAin_Cas:
++ addHRegUse(u, HRmWrite, i->LAin.Cas.old);
++ addHRegUse(u, HRmRead, i->LAin.Cas.addr);
++ addHRegUse(u, HRmRead, i->LAin.Cas.expd);
++ addHRegUse(u, HRmModify, i->LAin.Cas.data);
++ break;
++ case LAin_Cmp:
++ addHRegUse(u, HRmRead, i->LAin.Cmp.src2);
++ addHRegUse(u, HRmRead, i->LAin.Cmp.src1);
++ addHRegUse(u, HRmWrite, i->LAin.Cmp.dst);
++ break;
++ case LAin_CMove:
++ addHRegUse(u, HRmRead, i->LAin.CMove.cond);
++ addHRegUse(u, HRmRead, i->LAin.CMove.r0);
++ addHRegUse(u, HRmRead, i->LAin.CMove.r1);
++ addHRegUse(u, HRmWrite, i->LAin.CMove.dst);
++ break;
++ case LAin_Call:
++ /* logic and comments copied/modified from mips and arm64 back end */
++ /* This is a bit subtle. */
++ /* First off, we need to consider the cond register. */
++ if (!hregIsInvalid(i->LAin.Call.cond))
++ addHRegUse(u, HRmRead, i->LAin.Call.cond);
++ /* Then, claim it trashes all the caller-saved regs
++ which fall within the register allocator's jurisdiction. */
++ addHRegUse(u, HRmWrite, hregLOONGARCH64_R14());
++ addHRegUse(u, HRmWrite, hregLOONGARCH64_R15());
++ addHRegUse(u, HRmWrite, hregLOONGARCH64_R16());
++ addHRegUse(u, HRmWrite, hregLOONGARCH64_R17());
++ addHRegUse(u, HRmWrite, hregLOONGARCH64_R18());
++ addHRegUse(u, HRmWrite, hregLOONGARCH64_R19());
++ addHRegUse(u, HRmWrite, hregLOONGARCH64_R20());
++ /* Now we have to state any parameter-carrying registers
++ which might be read. This depends on nArgRegs. */
++ switch (i->LAin.Call.nArgRegs) {
++ case 8: addHRegUse(u, HRmRead, hregLOONGARCH64_R11()); /* fallthrough */
++ case 7: addHRegUse(u, HRmRead, hregLOONGARCH64_R10()); /* fallthrough */
++ case 6: addHRegUse(u, HRmRead, hregLOONGARCH64_R9()); /* fallthrough */
++ case 5: addHRegUse(u, HRmRead, hregLOONGARCH64_R8()); /* fallthrough */
++ case 4: addHRegUse(u, HRmRead, hregLOONGARCH64_R7()); /* fallthrough */
++ case 3: addHRegUse(u, HRmRead, hregLOONGARCH64_R6()); /* fallthrough */
++ case 2: addHRegUse(u, HRmRead, hregLOONGARCH64_R5()); /* fallthrough */
++ case 1: addHRegUse(u, HRmRead, hregLOONGARCH64_R4()); /* fallthrough */
++ case 0: break;
++ default: vpanic("getRegUsage_LOONGARCH64:Call:regparms"); break;
++ }
++ /* Finally, there is the issue that the insn trashes a
++ register because the literal target address has to be
++ loaded into a register. However, we reserve $t0 for that
++ purpose so there's no further complexity here. Stating $t0
++ as trashed is pointless since it's not under the control
++ of the allocator, but what the hell. */
++ addHRegUse(u, HRmWrite, hregT0());
++ break;
++ /* XDirect/XIndir/XAssisted are also a bit subtle. They
++ conditionally exit the block. Hence we only need to list (1)
++ the registers that they read, and (2) the registers that they
++ write in the case where the block is not exited. (2) is
++ empty, hence only (1) is relevant here. */
++ case LAin_XDirect:
++ addRegUsage_LOONGARCH64AMode(u, i->LAin.XDirect.amPC);
++ if (!hregIsInvalid(i->LAin.XDirect.cond))
++ addHRegUse(u, HRmRead, i->LAin.XDirect.cond);
++ addHRegUse(u, HRmWrite, hregT0()); /* unavail to RA */
++ break;
++ case LAin_XIndir:
++ addHRegUse(u, HRmRead, i->LAin.XIndir.dstGA);
++ addRegUsage_LOONGARCH64AMode(u, i->LAin.XIndir.amPC);
++ if (!hregIsInvalid(i->LAin.XIndir.cond))
++ addHRegUse(u, HRmRead, i->LAin.XIndir.cond);
++ addHRegUse(u, HRmWrite, hregT0()); /* unavail to RA */
++ break;
++ case LAin_XAssisted:
++ addHRegUse(u, HRmRead, i->LAin.XAssisted.dstGA);
++ addRegUsage_LOONGARCH64AMode(u, i->LAin.XAssisted.amPC);
++ if (!hregIsInvalid(i->LAin.XAssisted.cond))
++ addHRegUse(u, HRmRead, i->LAin.XAssisted.cond);
++ addHRegUse(u, HRmWrite, hregT0()); /* unavail to RA */
++ break;
++ case LAin_EvCheck:
++ /* We expect both amodes only to mention $r31, so this is in
++ fact pointless, since $r31 isn't allocatable, but anyway.. */
++ addRegUsage_LOONGARCH64AMode(u, i->LAin.EvCheck.amCounter);
++ addRegUsage_LOONGARCH64AMode(u, i->LAin.EvCheck.amFailAddr);
++ addHRegUse(u, HRmWrite, hregT0()); /* unavail to RA */
++ break;
++ case LAin_ProfInc:
++ /* Again, pointless to actually state these since neither
++ is available to RA. */
++ addHRegUse(u, HRmWrite, hregT0()); /* unavail to RA */
++ addHRegUse(u, HRmWrite, hregT1()); /* unavail to RA */
++ break;
++ default:
++ ppLOONGARCH64Instr(i, mode64);
++ vpanic("getRegUsage_LOONGARCH64Instr");
++ break;
++ }
++}
++
++void mapRegs_LOONGARCH64Instr ( HRegRemap* m, LOONGARCH64Instr* i,
++ Bool mode64 )
++{
++ vassert(mode64 == True);
++ switch (i->tag) {
++ case LAin_LI:
++ mapReg(m, &i->LAin.LI.dst);
++ break;
++ case LAin_Un:
++ mapReg(m, &i->LAin.Unary.src);
++ mapReg(m, &i->LAin.Unary.dst);
++ break;
++ case LAin_Bin:
++ mapRegs_LOONGARCH64RI(m, i->LAin.Binary.src2);
++ mapReg(m, &i->LAin.Binary.src1);
++ mapReg(m, &i->LAin.Binary.dst);
++ break;
++ case LAin_Load:
++ mapRegs_LOONGARCH64AMode(m, i->LAin.Load.src);
++ mapReg(m, &i->LAin.Load.dst);
++ break;
++ case LAin_Store:
++ mapRegs_LOONGARCH64AMode(m, i->LAin.Store.dst);
++ mapReg(m, &i->LAin.Store.src);
++ break;
++ case LAin_LLSC:
++ mapRegs_LOONGARCH64AMode(m, i->LAin.LLSC.addr);
++ mapReg(m, &i->LAin.LLSC.val);
++ break;
++ case LAin_Bar:
++ /* No regs. */
++ break;
++ case LAin_FpUn:
++ mapReg(m, &i->LAin.FpUnary.src);
++ mapReg(m, &i->LAin.FpUnary.dst);
++ break;
++ case LAin_FpBin:
++ mapReg(m, &i->LAin.FpBinary.src2);
++ mapReg(m, &i->LAin.FpBinary.src1);
++ mapReg(m, &i->LAin.FpBinary.dst);
++ break;
++ case LAin_FpTri:
++ mapReg(m, &i->LAin.FpTrinary.src3);
++ mapReg(m, &i->LAin.FpTrinary.src2);
++ mapReg(m, &i->LAin.FpTrinary.src1);
++ mapReg(m, &i->LAin.FpTrinary.dst);
++ break;
++ case LAin_FpLoad:
++ mapRegs_LOONGARCH64AMode(m, i->LAin.FpLoad.src);
++ mapReg(m, &i->LAin.FpLoad.dst);
++ break;
++ case LAin_FpStore:
++ mapRegs_LOONGARCH64AMode(m, i->LAin.FpStore.dst);
++ mapReg(m, &i->LAin.FpStore.src);
++ break;
++ case LAin_FpMove:
++ mapReg(m, &i->LAin.FpMove.src);
++ mapReg(m, &i->LAin.FpMove.dst);
++ break;
++ case LAin_FpCmp:
++ mapReg(m, &i->LAin.FpCmp.src2);
++ mapReg(m, &i->LAin.FpCmp.src1);
++ mapReg(m, &i->LAin.FpCmp.dst);
++ break;
++ case LAin_VecUn:
++ mapReg(m, &i->LAin.VecUnary.src);
++ mapReg(m, &i->LAin.VecUnary.dst);
++ break;
++ case LAin_VecBin:
++ mapRegs_LOONGARCH64RI(m, i->LAin.VecBinary.src2);
++ mapReg(m, &i->LAin.VecBinary.src1);
++ mapReg(m, &i->LAin.VecBinary.dst);
++ break;
++ case LAin_VecLoad:
++ mapRegs_LOONGARCH64AMode(m, i->LAin.VecLoad.src);
++ mapReg(m, &i->LAin.VecLoad.dst);
++ break;
++ case LAin_VecStore:
++ mapRegs_LOONGARCH64AMode(m, i->LAin.VecStore.dst);
++ mapReg(m, &i->LAin.VecStore.src);
++ break;
++ case LAin_Cas:
++ mapReg(m, &i->LAin.Cas.old);
++ mapReg(m, &i->LAin.Cas.addr);
++ mapReg(m, &i->LAin.Cas.expd);
++ mapReg(m, &i->LAin.Cas.data);
++ break;
++ case LAin_Cmp:
++ mapReg(m, &i->LAin.Cmp.src2);
++ mapReg(m, &i->LAin.Cmp.src1);
++ mapReg(m, &i->LAin.Cmp.dst);
++ break;
++ case LAin_CMove:
++ mapReg(m, &i->LAin.CMove.cond);
++ mapReg(m, &i->LAin.CMove.r0);
++ mapReg(m, &i->LAin.CMove.r1);
++ mapReg(m, &i->LAin.CMove.dst);
++ break;
++ case LAin_Call:
++ if (!hregIsInvalid(i->LAin.Call.cond))
++ mapReg(m, &i->LAin.Call.cond);
++ /* Hardwires $r12. */
++ break;
++ /* XDirect/XIndir/XAssisted are also a bit subtle. They
++ conditionally exit the block. Hence we only need to list (1)
++ the registers that they read, and (2) the registers that they
++ write in the case where the block is not exited. (2) is
++ empty, hence only (1) is relevant here. */
++ case LAin_XDirect:
++ mapRegs_LOONGARCH64AMode(m, i->LAin.XDirect.amPC);
++ if (!hregIsInvalid(i->LAin.XDirect.cond))
++ mapReg(m, &i->LAin.XDirect.cond);
++ break;
++ case LAin_XIndir:
++ mapReg(m, &i->LAin.XIndir.dstGA);
++ mapRegs_LOONGARCH64AMode(m, i->LAin.XIndir.amPC);
++ if (!hregIsInvalid(i->LAin.XIndir.cond))
++ mapReg(m, &i->LAin.XIndir.cond);
++ break;
++ case LAin_XAssisted:
++ mapReg(m, &i->LAin.XAssisted.dstGA);
++ mapRegs_LOONGARCH64AMode(m, i->LAin.XAssisted.amPC);
++ if (!hregIsInvalid(i->LAin.XAssisted.cond))
++ mapReg(m, &i->LAin.XAssisted.cond);
++ break;
++ case LAin_EvCheck:
++ /* We expect both amodes only to mention $r31, so this is in
++ fact pointless, since $r31 isn't allocatable, but anyway.. */
++ mapRegs_LOONGARCH64AMode(m, i->LAin.EvCheck.amCounter);
++ mapRegs_LOONGARCH64AMode(m, i->LAin.EvCheck.amFailAddr);
++ break;
++ case LAin_ProfInc:
++ /* Hardwires $r12 and $r13 -- nothing to modify. */
++ break;
++ default:
++ ppLOONGARCH64Instr(i, mode64);
++ vpanic("mapRegs_LOONGARCH64Instr");
++ break;
++ }
++}
++
++/* Generate loongarch64 spill instructions under the direction of the
++ register allocator. */
++void genSpill_LOONGARCH64 ( /*OUT*/ HInstr** i1, /*OUT*/ HInstr** i2,
++ HReg rreg, Int offsetB, Bool mode64 )
++{
++ vassert(mode64 == True);
++ vassert(offsetB >= 0);
++ vassert(!hregIsVirtual(rreg));
++
++ LOONGARCH64AMode* am;
++ *i1 = *i2 = NULL;
++
++ switch (hregClass(rreg)) {
++ case HRcInt64:
++ if (offsetB < 1024) {
++ am = LOONGARCH64AMode_RI(hregGSP(), offsetB);
++ *i1 = LOONGARCH64Instr_Store(LAstore_ST_D, am, rreg);
++ } else {
++ *i1 = LOONGARCH64Instr_LI(offsetB, hregT0());
++ am = LOONGARCH64AMode_RR(hregGSP(), hregT0());
++ *i2 = LOONGARCH64Instr_Store(LAstore_STX_D, am, rreg);
++ }
++ break;
++ case HRcFlt64:
++ if (offsetB < 1024) {
++ am = LOONGARCH64AMode_RI(hregGSP(), offsetB);
++ *i1 = LOONGARCH64Instr_FpStore(LAfpstore_FST_D, am, rreg);
++ } else {
++ *i1 = LOONGARCH64Instr_LI(offsetB, hregT0());
++ am = LOONGARCH64AMode_RR(hregGSP(), hregT0());
++ *i2 = LOONGARCH64Instr_FpStore(LAfpstore_FSTX_D, am, rreg);
++ }
++ break;
++ case HRcVec128:
++ if (offsetB < 1024) {
++ am = LOONGARCH64AMode_RI(hregGSP(), offsetB);
++ *i1 = LOONGARCH64Instr_VecStore(LAvecstore_VST, am, rreg);
++ } else {
++ am = LOONGARCH64AMode_RR(hregGSP(), hregT0());
++ *i1 = LOONGARCH64Instr_LI(offsetB, hregT0());
++ *i2 = LOONGARCH64Instr_VecStore(LAvecstore_VSTX, am, rreg);
++ }
++ break;
++ default:
++ ppHRegClass(hregClass(rreg));
++ vpanic("genSpill_LOONGARCH64: unimplemented regclass");
++ break;
++ }
++}
++
++/* Generate loongarch64 reload instructions under the direction of the
++ register allocator. */
++void genReload_LOONGARCH64 ( /*OUT*/ HInstr** i1, /*OUT*/ HInstr** i2,
++ HReg rreg, Int offsetB, Bool mode64 )
++{
++ vassert(mode64 == True);
++ vassert(offsetB >= 0);
++ vassert(!hregIsVirtual(rreg));
++
++ LOONGARCH64AMode* am;
++ *i1 = *i2 = NULL;
++
++ switch (hregClass(rreg)) {
++ case HRcInt64:
++ if (offsetB < 1024) {
++ am = LOONGARCH64AMode_RI(hregGSP(), offsetB);
++ *i1 = LOONGARCH64Instr_Load(LAload_LD_D, am, rreg);
++ } else {
++ *i1 = LOONGARCH64Instr_LI(offsetB, hregT0());
++ am = LOONGARCH64AMode_RR(hregGSP(), hregT0());
++ *i2 = LOONGARCH64Instr_Load(LAload_LDX_D, am, rreg);
++ }
++ break;
++ case HRcFlt64:
++ if (offsetB < 1024) {
++ am = LOONGARCH64AMode_RI(hregGSP(), offsetB);
++ *i1 = LOONGARCH64Instr_FpLoad(LAfpload_FLD_D, am, rreg);
++ } else {
++ *i1 = LOONGARCH64Instr_LI(offsetB, hregT0());
++ am = LOONGARCH64AMode_RR(hregGSP(), hregT0());
++ *i2 = LOONGARCH64Instr_FpLoad(LAfpload_FLDX_D, am, rreg);
+ }
-+ addInstr(env, LOONGARCH64Instr_Load(op, am, dst));
-+ return dst;
-+ }
++ break;
++ case HRcVec128:
++ if (offsetB < 1024) {
++ am = LOONGARCH64AMode_RI(hregGSP(), offsetB);
++ *i1 = LOONGARCH64Instr_VecLoad(LAvecload_VLD, am, rreg);
++ } else {
++ am = LOONGARCH64AMode_RR(hregGSP(), hregT0());
++ *i1 = LOONGARCH64Instr_LI(offsetB, hregT0());
++ *i2 = LOONGARCH64Instr_VecLoad(LAvecload_VLDX, am, rreg);
++ }
++ break;
++ default:
++ ppHRegClass(hregClass(rreg));
++ vpanic("genReload_LOONGARCH64: unimplemented regclass");
++ break;
++ }
++}
++
++/* Generate loongarch64 move instructions under the direction of the
++ register allocator. */
++LOONGARCH64Instr* genMove_LOONGARCH64 ( HReg from, HReg to, Bool mode64 )
++{
++ vassert(mode64 == True);
++ switch (hregClass(from)) {
++ case HRcInt64:
++ return LOONGARCH64Instr_Binary(LAbin_OR,
++ LOONGARCH64RI_R(hregZERO()),
++ from, to);
++ case HRcFlt64:
++ return LOONGARCH64Instr_FpMove(LAfpmove_FMOV_D, from, to);
++ case HRcVec128:
++ return LOONGARCH64Instr_VecBinary(LAvecbin_VORI_B,
++ LOONGARCH64RI_I(0, 8, False),
++ from, to);
++ default:
++ ppHRegClass(hregClass(from));
++ vpanic("genMove_LOONGARCH64: unimplemented regclass");
++ }
++}
++
++
++/* --------- The loongarch64 assembler --------- */
++
++static inline UInt iregEnc ( HReg r )
++{
++ vassert(hregClass(r) == HRcInt64);
++ vassert(!hregIsVirtual(r));
++ UInt n = hregEncoding(r);
++ vassert(n < 32);
++ return n;
++}
++
++static inline UInt fregEnc ( HReg r )
++{
++ vassert(hregClass(r) == HRcFlt64);
++ vassert(!hregIsVirtual(r));
++ UInt n = hregEncoding(r);
++ vassert(n < 32);
++ return n;
++}
++
++static inline UInt vregEnc ( HReg r )
++{
++ vassert(hregClass(r) == HRcVec128);
++ vassert(!hregIsVirtual(r));
++ UInt n = hregEncoding(r);
++ vassert(n < 32);
++ return n;
++}
++
++static inline UInt fcsrEnc ( HReg r )
++{
++ vassert(hregClass(r) == HRcInt32);
++ vassert(!hregIsVirtual(r));
++ UInt n = hregEncoding(r);
++ vassert(n < 32);
++ return n;
++}
++
++static inline UInt emit_op_rj_rd ( UInt op, UInt rj, UInt rd )
++{
++ vassert(rj < (1 << 5));
++ vassert(rd < (1 << 5));
++ return op | (rj << 5) | rd;
++}
++
++static inline UInt emit_op_rk_rj_rd ( UInt op, UInt rk, UInt rj, UInt rd )
++{
++ vassert(rk < (1 << 5));
++ vassert(rj < (1 << 5));
++ vassert(rd < (1 << 5));
++ return op | (rk << 10) | (rj << 5) | rd;
++}
++
++static inline UInt emit_op_fj_fd ( UInt op, UInt fj, UInt fd )
++{
++ vassert(fj < (1 << 5));
++ vassert(fd < (1 << 5));
++ return op | (fj << 5) | fd;
++}
++
++static inline UInt emit_op_fa_fk_fj_fd ( UInt op, UInt fa, UInt fk, UInt fj, UInt fd )
++{
++ vassert(fa < (1 << 5));
++ vassert(fk < (1 << 5));
++ vassert(fj < (1 << 5));
++ vassert(fd < (1 << 5));
++ return op | (fa << 15) | (fk << 10) | (fj << 5) | fd;
++}
++
++static inline UInt emit_op_fk_fj_fd ( UInt op, UInt fk, UInt fj, UInt fd )
++{
++ vassert(fk < (1 << 5));
++ vassert(fj < (1 << 5));
++ vassert(fd < (1 << 5));
++ return op | (fk << 10) | (fj << 5) | fd;
++}
++
++static inline UInt emit_op_ca_fk_fj_fd ( UInt op, UInt ca, UInt fk, UInt fj, UInt fd )
++{
++ vassert(ca < (1 << 3));
++ vassert(fk < (1 << 5));
++ vassert(fj < (1 << 5));
++ vassert(fd < (1 << 5));
++ return op | (ca << 15) | (fk << 10) | (fj << 5) | fd;
++}
++
++static inline UInt emit_op_fk_fj_cd ( UInt op, UInt fk, UInt fj, UInt cd )
++{
++ vassert(fk < (1 << 5));
++ vassert(fj < (1 << 5));
++ vassert(cd < (1 << 3));
++ return op | (fk << 10) | (fj << 5) | cd;
++}
++
++static inline UInt emit_op_cj_rd ( UInt op, UInt cj, UInt rd )
++{
++ vassert(cj < (1 << 3));
++ vassert(rd < (1 << 5));
++ return op | (cj << 5) | rd;
++}
++
++static inline UInt emit_op_rj_cd ( UInt op, UInt rj, UInt cd )
++{
++ vassert(rj < (1 << 5));
++ vassert(cd < (1 << 3));
++ return op | (rj << 5) | cd;
++}
++
++static inline UInt emit_op_rj_fd ( UInt op, UInt rj, UInt fd )
++{
++ vassert(rj < (1 << 5));
++ vassert(fd < (1 << 5));
++ return op | (rj << 5) | fd;
++}
++
++static inline UInt emit_op_fj_rd ( UInt op, UInt fj, UInt rd )
++{
++ vassert(fj < (1 << 5));
++ vassert(rd < (1 << 5));
++ return op | (fj << 5) | rd;
++}
++
++static inline UInt emit_op_rj_fcsr ( UInt op, UInt rj, UInt fcsr )
++{
++ vassert(rj < (1 << 5));
++ vassert(fcsr < (1 << 5));
++ return op | (rj << 5) | fcsr;
++}
++
++static inline UInt emit_op_fcsr_rd ( UInt op, UInt fcsr, UInt rd )
++{
++ vassert(fcsr < (1 << 5));
++ vassert(rd < (1 << 5));
++ return op | (fcsr << 5) | rd;
++}
++
++static inline UInt emit_op_ui5_rj_rd ( UInt op, UInt ui5, UInt rj, UInt rd )
++{
++ vassert(ui5 < (1 << 5));
++ vassert(rj < (1 << 5));
++ vassert(rd < (1 << 5));
++ return op | (ui5 << 10) | (rj << 5) | rd;
++}
++
++static inline UInt emit_op_ui6_rj_rd ( UInt op, UInt ui6, UInt rj, UInt rd )
++{
++ vassert(ui6 < (1 << 6));
++ vassert(rj < (1 << 5));
++ vassert(rd < (1 << 5));
++ return op | (ui6 << 10) | (rj << 5) | rd;
++}
++
++static inline UInt emit_op_ui12_rj_rd ( UInt op, UInt ui12, UInt rj, UInt rd )
++{
++ vassert(ui12 < (1 << 12));
++ vassert(rj < (1 << 5));
++ vassert(rd < (1 << 5));
++ return op | (ui12 << 10) | (rj << 5) | rd;
++}
++
++static inline UInt emit_op_si12_rj_rd ( UInt op, UInt si12, UInt rj, UInt rd )
++{
++ vassert(si12 < (1 << 12));
++ vassert(rj < (1 << 5));
++ vassert(rd < (1 << 5));
++ return op | (si12 << 10) | (rj << 5) | rd;
++}
++
++static inline UInt emit_op_si14_rj_rd ( UInt op, UInt si14, UInt rj, UInt rd )
++{
++ vassert(si14 < (1 << 14));
++ vassert(rj < (1 << 5));
++ vassert(rd < (1 << 5));
++ return op | (si14 << 10) | (rj << 5) | rd;
++}
++
++static inline UInt emit_op_si20_rd ( UInt op, UInt si20, UInt rd )
++{
++ vassert(si20 < (1 << 20));
++ vassert(rd < (1 << 5));
++ return op | (si20 << 5) | rd;
++}
++
++static inline UInt emit_op_offs16_rj_rd ( UInt op, UInt offs16, UInt rj, UInt rd )
++{
++ vassert(offs16 < (1 << 16));
++ vassert(rj < (1 << 5));
++ vassert(rd < (1 << 5));
++ return op | (offs16 << 10) | (rj << 5) | rd;
++}
++
++static inline UInt emit_op_offs26 ( UInt op, UInt offs26 )
++{
++ vassert(offs26 < (1 << 26));
++ return op | ((offs26 & 0xffff) << 10) | (offs26 >> 16);
++}
++
++static inline UInt emit_op_hint15 ( UInt op, UInt hint )
++{
++ vassert(hint < (1 << 15));
++ return op | hint;
++}
++
++static inline UInt emit_op_si12_rj_vd ( UInt op, UInt si12, UInt rj, UInt vd )
++{
++ vassert(si12 < (1 << 12));
++ vassert(rj < (1 << 5));
++ vassert(vd < (1 << 5));
++ return op | (si12 << 10) | (rj << 5) | vd;
++}
++
++static inline UInt emit_op_rk_rj_vd ( UInt op, UInt rk, UInt rj, UInt vd )
++{
++ vassert(rk < (1 << 5));
++ vassert(rj < (1 << 5));
++ vassert(vd < (1 << 5));
++ return op | (rk << 10) | (rj << 5) | vd;
++}
++
++static inline UInt emit_unop_r ( UInt op, Int src, UInt dst, UInt dst_size)
++{
++ vassert(src < (1 << 5));
++ vassert(dst < (1 << dst_size));
++ return op | (src << 5) | dst;
++}
++
++static inline UInt emit_binop_rr ( UInt op, UInt src2, UInt src1, UInt dst )
++{
++ vassert(src2 < (1 << 5));
++ vassert(src1 < (1 << 5));
++ vassert(dst < (1 << 5));
++ return op | (src2 << 10) | (src1 << 5) | dst;
++}
++
++static inline UInt emit_binop_ri ( UInt op, UInt imm, UInt size, UInt src, UInt dst )
++{
++ vassert(imm < (1 << size));
++ vassert(src < (1 << 5));
++ vassert(dst < (1 << 5));
++ return op | (imm << 10) | (src << 5) | dst;
++}
++
++
++static UInt* mkLoadImm_EXACTLY4 ( UInt* p, HReg dst, ULong imm )
++{
++ /*
++ lu12i.w dst, imm[31:12]
++ ori dst, dst, imm[11:0]
++ lu32i.d dst, imm[51:32]
++ lu52i.d dst, dst, imm[63:52]
++ */
++ UInt d = iregEnc(dst);
++ *p++ = emit_op_si20_rd(LAextra_LU12I_W, (imm >> 12) & 0xfffff, d);
++ *p++ = emit_op_si12_rj_rd(LAbin_ORI, imm & 0xfff, d, d);
++ *p++ = emit_op_si20_rd(LAextra_LU32I_D, (imm >> 32) & 0xfffff, d);
++ *p++ = emit_op_si12_rj_rd(LAextra_LU52I_D, (imm >> 52) & 0xfff, d, d);
++ return p;
++}
++
++static inline UInt* mkLoadImm_EXACTLY2 ( UInt* p, HReg dst, ULong imm )
++{
++ /*
++ lu12i.w dst, imm[31:12]
++ ori dst, dst, imm[11:0]
++ */
++ UInt d = iregEnc(dst);
++ *p++ = emit_op_si20_rd(LAextra_LU12I_W, (imm >> 12) & 0xfffff, d);
++ *p++ = emit_op_si12_rj_rd(LAbin_ORI, imm & 0xfff, d, d);
++ return p;
++}
++
++static inline UInt* mkLoadImm_EXACTLY1 ( UInt* p, HReg dst, ULong imm )
++{
++ /* ori dst, $zero, imm[11:0] */
++ *p++ = emit_op_si12_rj_rd(LAbin_ORI, imm, 0, iregEnc(dst));
++ return p;
++}
++
++static UInt* mkLoadImm ( UInt* p, HReg dst, ULong imm )
++{
++ if ((imm >> 12) == 0)
++ p = mkLoadImm_EXACTLY1(p, dst, imm);
++ else if (imm < 0x80000000 || (imm >> 31) == 0x1ffffffffUL)
++ p = mkLoadImm_EXACTLY2(p, dst, imm);
++ else
++ p = mkLoadImm_EXACTLY4(p, dst, imm);
++ return p;
++}
++
++static Bool is_LoadImm_EXACTLY4 ( UInt* p, HReg dst, ULong imm )
++{
++ UInt expect[4];
++ mkLoadImm_EXACTLY4(expect, dst, imm);
++ return toBool(p[0] == expect[0] && p[1] == expect[1] &&
++ p[2] == expect[2] && p[3] == expect[3]);
++}
++
++static inline UInt* mkUnary ( UInt* p, LOONGARCH64UnOp op, HReg src, HReg dst )
++{
++ switch (op) {
++ case LAun_CLZ_W:
++ case LAun_CTZ_W:
++ case LAun_CLZ_D:
++ case LAun_CTZ_D:
++ case LAun_EXT_W_H:
++ case LAun_EXT_W_B:
++ *p++ = emit_op_rj_rd(op, iregEnc(src), iregEnc(dst));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkBinary ( UInt* p, LOONGARCH64BinOp op,
++ LOONGARCH64RI* src2, HReg src1, HReg dst )
++{
++ switch (op) {
++ case LAbin_ADD_W:
++ case LAbin_ADD_D:
++ case LAbin_SUB_W:
++ case LAbin_SUB_D:
++ case LAbin_NOR:
++ case LAbin_AND:
++ case LAbin_OR:
++ case LAbin_XOR:
++ case LAbin_SLL_W:
++ case LAbin_SRL_W:
++ case LAbin_SRA_W:
++ case LAbin_SLL_D:
++ case LAbin_SRL_D:
++ case LAbin_SRA_D:
++ case LAbin_MUL_W:
++ case LAbin_MUL_D:
++ case LAbin_MULH_W:
++ case LAbin_MULH_WU:
++ case LAbin_MULH_D:
++ case LAbin_MULH_DU:
++ case LAbin_MULW_D_W:
++ case LAbin_MULW_D_WU:
++ case LAbin_DIV_W:
++ case LAbin_MOD_W:
++ case LAbin_DIV_WU:
++ case LAbin_MOD_WU:
++ case LAbin_DIV_D:
++ case LAbin_MOD_D:
++ case LAbin_DIV_DU:
++ case LAbin_MOD_DU:
++ vassert(src2->tag == LAri_Reg);
++ *p++ = emit_op_rk_rj_rd(op, iregEnc(src2->LAri.R.reg),
++ iregEnc(src1), iregEnc(dst));
++ return p;
++ case LAbin_SLLI_W:
++ case LAbin_SRLI_W:
++ case LAbin_SRAI_W:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_op_ui5_rj_rd(op, src2->LAri.I.imm,
++ iregEnc(src1), iregEnc(dst));
++ return p;
++ case LAbin_SLLI_D:
++ case LAbin_SRLI_D:
++ case LAbin_SRAI_D:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_op_ui6_rj_rd(op, src2->LAri.I.imm,
++ iregEnc(src1), iregEnc(dst));
++ return p;
++ case LAbin_ADDI_W:
++ case LAbin_ADDI_D:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_op_si12_rj_rd(op, src2->LAri.I.imm,
++ iregEnc(src1), iregEnc(dst));
++ return p;
++ case LAbin_ANDI:
++ case LAbin_ORI:
++ case LAbin_XORI:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_op_ui12_rj_rd(op, src2->LAri.I.imm,
++ iregEnc(src1), iregEnc(dst));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static UInt* mkLoad ( UInt* p, LOONGARCH64LoadOp op,
++ LOONGARCH64AMode* src, HReg dst )
++{
++ switch (op) {
++ case LAload_LD_W:
++ case LAload_LD_D:
++ case LAload_LD_BU:
++ case LAload_LD_HU:
++ case LAload_LD_WU:
++ vassert(src->tag == LAam_RI);
++ *p++ = emit_op_si12_rj_rd(op, src->LAam.RI.index,
++ iregEnc(src->LAam.RI.base), iregEnc(dst));
++ return p;
++ case LAload_LDX_D:
++ case LAload_LDX_BU:
++ case LAload_LDX_HU:
++ case LAload_LDX_WU:
++ vassert(src->tag == LAam_RR);
++ *p++ = emit_op_rk_rj_rd(op, iregEnc(src->LAam.RR.index),
++ iregEnc(src->LAam.RR.base), iregEnc(dst));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static UInt* mkStore ( UInt* p, LOONGARCH64StoreOp op,
++ LOONGARCH64AMode* dst, HReg src )
++{
++ switch (op) {
++ case LAstore_ST_B:
++ case LAstore_ST_H:
++ case LAstore_ST_W:
++ case LAstore_ST_D:
++ vassert(dst->tag == LAam_RI);
++ *p++ = emit_op_si12_rj_rd(op, dst->LAam.RI.index,
++ iregEnc(dst->LAam.RI.base), iregEnc(src));
++ return p;
++ case LAstore_STX_B:
++ case LAstore_STX_H:
++ case LAstore_STX_W:
++ case LAstore_STX_D:
++ vassert(dst->tag == LAam_RR);
++ *p++ = emit_op_rk_rj_rd(op, iregEnc(dst->LAam.RR.index),
++ iregEnc(dst->LAam.RR.base), iregEnc(src));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkLLSC ( UInt* p, LOONGARCH64LLSCOp op,
++ LOONGARCH64AMode* addr, HReg val )
++{
++ switch (op) {
++ case LAllsc_LL_W:
++ case LAllsc_SC_W:
++ case LAllsc_LL_D:
++ case LAllsc_SC_D:
++ vassert(addr->tag == LAam_RI);
++ *p++ = emit_op_si14_rj_rd(op, addr->LAam.RI.index,
++ iregEnc(addr->LAam.RI.base), iregEnc(val));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkBar ( UInt* p, LOONGARCH64BarOp op, UShort hint )
++{
++ switch (op) {
++ case LAbar_DBAR:
++ case LAbar_IBAR:
++ *p++ = emit_op_hint15(op, hint);
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkFpUnary ( UInt* p, LOONGARCH64FpUnOp op, HReg src, HReg dst )
++{
++ switch (op) {
++ case LAfpun_FABS_S:
++ case LAfpun_FABS_D:
++ case LAfpun_FNEG_S:
++ case LAfpun_FNEG_D:
++ case LAfpun_FLOGB_S:
++ case LAfpun_FLOGB_D:
++ case LAfpun_FSQRT_S:
++ case LAfpun_FSQRT_D:
++ case LAfpun_FRSQRT_S:
++ case LAfpun_FRSQRT_D:
++ case LAfpun_FCVT_S_D:
++ case LAfpun_FCVT_D_S:
++ case LAfpun_FTINT_W_S:
++ case LAfpun_FTINT_W_D:
++ case LAfpun_FTINT_L_S:
++ case LAfpun_FTINT_L_D:
++ case LAfpun_FFINT_S_W:
++ case LAfpun_FFINT_S_L:
++ case LAfpun_FFINT_D_W:
++ case LAfpun_FFINT_D_L:
++ case LAfpun_FRINT_S:
++ case LAfpun_FRINT_D:
++ *p++ = emit_op_fj_fd(op, fregEnc(src), fregEnc(dst));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkFpBinary ( UInt* p, LOONGARCH64FpBinOp op, HReg src2,
++ HReg src1, HReg dst )
++{
++ switch (op) {
++ case LAfpbin_FADD_S:
++ case LAfpbin_FADD_D:
++ case LAfpbin_FSUB_S:
++ case LAfpbin_FSUB_D:
++ case LAfpbin_FMUL_S:
++ case LAfpbin_FMUL_D:
++ case LAfpbin_FDIV_S:
++ case LAfpbin_FDIV_D:
++ case LAfpbin_FMAX_S:
++ case LAfpbin_FMAX_D:
++ case LAfpbin_FMIN_S:
++ case LAfpbin_FMIN_D:
++ case LAfpbin_FMAXA_S:
++ case LAfpbin_FMAXA_D:
++ case LAfpbin_FMINA_S:
++ case LAfpbin_FMINA_D:
++ case LAfpbin_FSCALEB_S:
++ case LAfpbin_FSCALEB_D:
++ *p++ = emit_op_fk_fj_fd(op, fregEnc(src2), fregEnc(src1), fregEnc(dst));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkFpTrinary ( UInt* p, LOONGARCH64FpTriOp op, HReg src3,
++ HReg src2, HReg src1, HReg dst )
++{
++ switch (op) {
++ case LAfpbin_FMADD_S:
++ case LAfpbin_FMADD_D:
++ case LAfpbin_FMSUB_S:
++ case LAfpbin_FMSUB_D:
++ *p++ = emit_op_fa_fk_fj_fd(op, fregEnc(src3), fregEnc(src2),
++ fregEnc(src1), fregEnc(dst));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkFpLoad ( UInt* p, LOONGARCH64FpLoadOp op,
++ LOONGARCH64AMode* src, HReg dst )
++{
++ switch (op) {
++ case LAfpload_FLD_S:
++ case LAfpload_FLD_D:
++ vassert(src->tag == LAam_RI);
++ *p++ = emit_op_si12_rj_rd(op, src->LAam.RI.index,
++ iregEnc(src->LAam.RI.base), fregEnc(dst));
++ return p;
++ case LAfpload_FLDX_S:
++ case LAfpload_FLDX_D:
++ vassert(src->tag == LAam_RR);
++ *p++ = emit_op_rk_rj_rd(op, iregEnc(src->LAam.RR.index),
++ iregEnc(src->LAam.RR.base), fregEnc(dst));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkFpStore ( UInt* p, LOONGARCH64FpStoreOp op,
++ LOONGARCH64AMode* dst, HReg src )
++{
++ switch (op) {
++ case LAfpstore_FST_S:
++ case LAfpstore_FST_D:
++ vassert(dst->tag == LAam_RI);
++ *p++ = emit_op_si12_rj_rd(op, dst->LAam.RI.index,
++ iregEnc(dst->LAam.RI.base), fregEnc(src));
++ return p;
++ case LAfpstore_FSTX_S:
++ case LAfpstore_FSTX_D:
++ vassert(dst->tag == LAam_RR);
++ *p++ = emit_op_rk_rj_rd(op, iregEnc(dst->LAam.RR.index),
++ iregEnc(dst->LAam.RR.base), fregEnc(src));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkFpMove ( UInt* p, LOONGARCH64FpMoveOp op, HReg src, HReg dst )
++{
++ switch (op) {
++ case LAfpmove_FMOV_S:
++ case LAfpmove_FMOV_D:
++ *p++ = emit_op_fj_fd(op, fregEnc(src), fregEnc(dst));
++ return p;
++ case LAfpmove_MOVGR2FR_W:
++ case LAfpmove_MOVGR2FR_D:
++ *p++ = emit_op_rj_fd(op, iregEnc(src), fregEnc(dst));
++ return p;
++ case LAfpmove_MOVFR2GR_S:
++ case LAfpmove_MOVFR2GR_D:
++ *p++ = emit_op_fj_rd(op, fregEnc(src), iregEnc(dst));
++ return p;
++ case LAfpmove_MOVGR2FCSR:
++ *p++ = emit_op_rj_fcsr(op, iregEnc(src), fcsrEnc(dst));
++ return p;
++ case LAfpmove_MOVFCSR2GR:
++ *p++ = emit_op_fcsr_rd(op, fcsrEnc(src), iregEnc(dst));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkFpCmp ( UInt* p, LOONGARCH64FpCmpOp op, HReg src2,
++ HReg src1, HReg dst )
++{
++ /*
++ fcmp.cond.[sd] $fcc0, src1, src2
++ movcf2gr dst, $fcc0
++ */
++ switch (op) {
++ case LAfpcmp_FCMP_CLT_S:
++ case LAfpcmp_FCMP_CLT_D:
++ case LAfpcmp_FCMP_CEQ_S:
++ case LAfpcmp_FCMP_CEQ_D:
++ case LAfpcmp_FCMP_CUN_S:
++ case LAfpcmp_FCMP_CUN_D:
++ *p++ = emit_op_fk_fj_cd(op, fregEnc(src2), fregEnc(src1), 0);
++ *p++ = emit_op_cj_rd(LAextra_MOVCF2GR, 0, iregEnc(dst));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkVecUnary ( UInt* p, LOONGARCH64VecUnOp op, HReg src, HReg dst )
++{
++ switch (op) {
++ case LAvecun_VCLO_B:
++ case LAvecun_VCLO_H:
++ case LAvecun_VCLO_W:
++ case LAvecun_VCLZ_B:
++ case LAvecun_VCLZ_H:
++ case LAvecun_VCLZ_W:
++ case LAvecun_VCLZ_D:
++ case LAvecun_VPCNT_B:
++ case LAvecun_VFRINTRM_S:
++ case LAvecun_VFRINTRM_D:
++ case LAvecun_VFRINTRP_S:
++ case LAvecun_VFRINTRP_D:
++ case LAvecun_VFRINTRZ_S:
++ case LAvecun_VFRINTRZ_D:
++ case LAvecun_VFRINTRNE_S:
++ case LAvecun_VFRINTRNE_D:
++ case LAvecun_VEXTH_H_B:
++ case LAvecun_VEXTH_W_H:
++ case LAvecun_VEXTH_D_W:
++ case LAvecun_VEXTH_Q_D:
++ case LAvecun_VEXTH_HU_BU:
++ case LAvecun_VEXTH_WU_HU:
++ case LAvecun_VEXTH_DU_WU:
++ case LAvecun_VEXTH_QU_DU:
++ *p++ = emit_unop_r(op, vregEnc(src), vregEnc(dst), 5);
++ return p;
++ case LAvecun_VREPLGR2VR_B:
++ case LAvecun_VREPLGR2VR_H:
++ case LAvecun_VREPLGR2VR_W:
++ case LAvecun_VREPLGR2VR_D:
++ *p++ = emit_unop_r(op, iregEnc(src), vregEnc(dst), 5);
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkVecBinary ( UInt* p, LOONGARCH64VecBinOp op,
++ LOONGARCH64RI* src2, HReg src1, HReg dst )
++{
++ switch (op) {
++ case LAvecbin_VSEQ_B:
++ case LAvecbin_VSEQ_H:
++ case LAvecbin_VSEQ_W:
++ case LAvecbin_VSEQ_D:
++ case LAvecbin_VSLT_B:
++ case LAvecbin_VSLT_H:
++ case LAvecbin_VSLT_W:
++ case LAvecbin_VSLT_D:
++ case LAvecbin_VSLT_BU:
++ case LAvecbin_VSLT_HU:
++ case LAvecbin_VSLT_WU:
++ case LAvecbin_VSLT_DU:
++ case LAvecbin_VADD_B:
++ case LAvecbin_VADD_H:
++ case LAvecbin_VADD_D:
++ case LAvecbin_VADD_W:
++ case LAvecbin_VSUB_B:
++ case LAvecbin_VSUB_H:
++ case LAvecbin_VSUB_W:
++ case LAvecbin_VSUB_D:
++ case LAvecbin_VSADD_B:
++ case LAvecbin_VSADD_H:
++ case LAvecbin_VSADD_W:
++ case LAvecbin_VSADD_D:
++ case LAvecbin_VSSUB_B:
++ case LAvecbin_VSSUB_H:
++ case LAvecbin_VSSUB_W:
++ case LAvecbin_VSSUB_D:
++ case LAvecbin_VSADD_BU:
++ case LAvecbin_VSADD_HU:
++ case LAvecbin_VSADD_WU:
++ case LAvecbin_VSADD_DU:
++ case LAvecbin_VSSUB_BU:
++ case LAvecbin_VSSUB_HU:
++ case LAvecbin_VSSUB_WU:
++ case LAvecbin_VSSUB_DU:
++ case LAvecbin_VADDA_B:
++ case LAvecbin_VADDA_H:
++ case LAvecbin_VADDA_W:
++ case LAvecbin_VADDA_D:
++ case LAvecbin_VAVGR_B:
++ case LAvecbin_VAVGR_H:
++ case LAvecbin_VAVGR_W:
++ case LAvecbin_VAVGR_D:
++ case LAvecbin_VAVGR_BU:
++ case LAvecbin_VAVGR_HU:
++ case LAvecbin_VAVGR_WU:
++ case LAvecbin_VAVGR_DU:
++ case LAvecbin_VMAX_B:
++ case LAvecbin_VMAX_H:
++ case LAvecbin_VMAX_W:
++ case LAvecbin_VMAX_D:
++ case LAvecbin_VMIN_B:
++ case LAvecbin_VMIN_H:
++ case LAvecbin_VMIN_W:
++ case LAvecbin_VMIN_D:
++ case LAvecbin_VMAX_BU:
++ case LAvecbin_VMAX_HU:
++ case LAvecbin_VMAX_WU:
++ case LAvecbin_VMAX_DU:
++ case LAvecbin_VMIN_BU:
++ case LAvecbin_VMIN_HU:
++ case LAvecbin_VMIN_WU:
++ case LAvecbin_VMIN_DU:
++ case LAvecbin_VMUL_B:
++ case LAvecbin_VMUL_H:
++ case LAvecbin_VMUL_W:
++ case LAvecbin_VMUH_B:
++ case LAvecbin_VMUH_H:
++ case LAvecbin_VMUH_W:
++ case LAvecbin_VMUH_BU:
++ case LAvecbin_VMUH_HU:
++ case LAvecbin_VMUH_WU:
++ case LAvecbin_VSLL_B:
++ case LAvecbin_VSLL_H:
++ case LAvecbin_VSLL_W:
++ case LAvecbin_VSLL_D:
++ case LAvecbin_VSRL_B:
++ case LAvecbin_VSRL_H:
++ case LAvecbin_VSRL_W:
++ case LAvecbin_VSRL_D:
++ case LAvecbin_VSRA_B:
++ case LAvecbin_VSRA_H:
++ case LAvecbin_VSRA_W:
++ case LAvecbin_VSRA_D:
++ case LAvecbin_VILVL_B:
++ case LAvecbin_VILVL_H:
++ case LAvecbin_VILVL_W:
++ case LAvecbin_VILVL_D:
++ case LAvecbin_VILVH_B:
++ case LAvecbin_VILVH_H:
++ case LAvecbin_VILVH_W:
++ case LAvecbin_VILVH_D:
++ case LAvecbin_VPICKEV_B:
++ case LAvecbin_VPICKEV_H:
++ case LAvecbin_VPICKEV_W:
++ case LAvecbin_VPICKOD_B:
++ case LAvecbin_VPICKOD_H:
++ case LAvecbin_VPICKOD_W:
++ case LAvecbin_VAND_V:
++ case LAvecbin_VOR_V:
++ case LAvecbin_VXOR_V:
++ case LAvecbin_VNOR_V:
++ case LAvecbin_VADD_Q:
++ case LAvecbin_VSUB_Q:
++ case LAvecbin_VFADD_S:
++ case LAvecbin_VFADD_D:
++ case LAvecbin_VFSUB_S:
++ case LAvecbin_VFSUB_D:
++ case LAvecbin_VFMUL_S:
++ case LAvecbin_VFMUL_D:
++ case LAvecbin_VFDIV_S:
++ case LAvecbin_VFDIV_D:
++ case LAvecbin_VFMAX_S:
++ case LAvecbin_VFMAX_D:
++ case LAvecbin_VFMIN_S:
++ case LAvecbin_VFMIN_D:
++ vassert(src2->tag == LAri_Reg);
++ *p++ = emit_binop_rr(op, vregEnc(src2->LAri.R.reg), vregEnc(src1), vregEnc(dst));
++ return p;
++ case LAvecbin_VREPLVE_B:
++ case LAvecbin_VREPLVE_H:
++ case LAvecbin_VREPLVE_W:
++ case LAvecbin_VREPLVE_D:
++ vassert(src2->tag == LAri_Reg);
++ *p++ = emit_binop_rr(op, iregEnc(src2->LAri.R.reg), vregEnc(src1), vregEnc(dst));
++ return p;
++ case LAvecbin_VINSGR2VR_D:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 1, iregEnc(src1), vregEnc(dst));
++ return p;
++ case LAvecbin_VPICKVE2GR_D:
++ case LAvecbin_VPICKVE2GR_DU:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 1, vregEnc(src1), iregEnc(dst));
++ return p;
++ case LAvecbin_VINSGR2VR_W:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 2, iregEnc(src1), vregEnc(dst));
++ return p;
++ case LAvecbin_VPICKVE2GR_W:
++ case LAvecbin_VPICKVE2GR_WU:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 2, vregEnc(src1), iregEnc(dst));
++ return p;
++ case LAvecbin_VSLLI_B:
++ case LAvecbin_VSRLI_B:
++ case LAvecbin_VSRAI_B:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 3, vregEnc(src1), vregEnc(dst));
++ return p;
++ case LAvecbin_VINSGR2VR_H:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 3, iregEnc(src1), vregEnc(dst));
++ return p;
++ case LAvecbin_VPICKVE2GR_HU:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 3, vregEnc(src1), iregEnc(dst));
++ return p;
++ case LAvecbin_VSLLI_H:
++ case LAvecbin_VSRLI_H:
++ case LAvecbin_VSRAI_H:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 4, vregEnc(src1), vregEnc(dst));
++ return p;
++ case LAvecbin_VINSGR2VR_B:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 4, iregEnc(src1), vregEnc(dst));
++ return p;
++ case LAvecbin_VPICKVE2GR_BU:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 4, vregEnc(src1), iregEnc(dst));
++ return p;
++ case LAvecbin_VBSLL_V:
++ case LAvecbin_VBSRL_V:
++ case LAvecbin_VSLLI_W:
++ case LAvecbin_VSRLI_W:
++ case LAvecbin_VSRAI_W:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 5, vregEnc(src1), vregEnc(dst));
++ return p;
++ case LAvecbin_VSLLI_D:
++ case LAvecbin_VSRLI_D:
++ case LAvecbin_VSRAI_D:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 6, vregEnc(src1), vregEnc(dst));
++ return p;
++ case LAvecbin_VORI_B:
++ vassert(src2->tag == LAri_Imm);
++ *p++ = emit_binop_ri(op, src2->LAri.I.imm, 8, vregEnc(src1), vregEnc(dst));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkVecLoad ( UInt* p, LOONGARCH64VecLoadOp op,
++ LOONGARCH64AMode* src, HReg dst )
++{
++ switch (op) {
++ case LAvecload_VLD:
++ vassert(src->tag == LAam_RI);
++ *p++ = emit_op_si12_rj_vd(op, src->LAam.RI.index,
++ iregEnc(src->LAam.RI.base), vregEnc(dst));
++ return p;
++ case LAvecload_VLDX:
++ vassert(src->tag == LAam_RR);
++ *p++ = emit_op_rk_rj_rd(op, iregEnc(src->LAam.RR.index),
++ iregEnc(src->LAam.RR.base), vregEnc(dst));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkVecStore ( UInt* p, LOONGARCH64VecStoreOp op,
++ LOONGARCH64AMode* dst, HReg src )
++{
++ switch (op) {
++ case LAvecstore_VST:
++ vassert(dst->tag == LAam_RI);
++ *p++ = emit_op_si12_rj_vd(op, dst->LAam.RI.index,
++ iregEnc(dst->LAam.RI.base), vregEnc(src));
++ return p;
++ case LAvecstore_VSTX:
++ vassert(dst->tag == LAam_RR);
++ *p++ = emit_op_rk_rj_vd(op, iregEnc(dst->LAam.RR.index),
++ iregEnc(dst->LAam.RR.base), vregEnc(src));
++ return p;
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkCas ( UInt* p, HReg old, HReg addr, HReg expd,
++ HReg data, Bool size64 )
++{
++ /*
++ ll.[wd] old, addr, 0
++ bne old, expd, barrier
++ or $t0, data, $zero
++ sc.[wd] $t0, addr, 0
++ beq $t0, zero, fail
++ or old, expd, $zero
++ b end
++ barrier:
++ dbar 0
++ fail:
++ or old, data, $zero
++ end:
++ */
++ UInt o = iregEnc(old);
++ UInt a = iregEnc(addr);
++ UInt e = iregEnc(expd);
++ UInt d = iregEnc(data);
++ UInt t = 12;
++ UInt z = 0;
++
++ if (size64) {
++ *p++ = emit_op_si14_rj_rd(LAllsc_LL_D, 0, a, o);
++ } else {
++ *p++ = emit_op_ui6_rj_rd(LAbin_SLLI_W, 0, e, e); // Sign-extend expd
++ *p++ = emit_op_si14_rj_rd(LAllsc_LL_W, 0, a, o);
++ }
++ *p++ = emit_op_offs16_rj_rd(LAextra_BNE, 6, o, e);
++ *p++ = emit_op_rk_rj_rd(LAbin_OR, z, d, t);
++ if (size64) {
++ *p++ = emit_op_si14_rj_rd(LAllsc_SC_D, 0, a, t);
++ } else {
++ *p++ = emit_op_si14_rj_rd(LAllsc_SC_W, 0, a, t);
++ }
++ *p++ = emit_op_offs16_rj_rd(LAextra_BEQ, 4, t, z);
++ *p++ = emit_op_rk_rj_rd(LAbin_OR, z, e, o);
++ *p++ = emit_op_offs26(LAextra_B, 3);
++ *p++ = emit_op_hint15(LAbar_DBAR, 0);
++ *p++ = emit_op_rk_rj_rd(LAbin_OR, z, d, o);
++ return p;
++}
++
++static inline UInt* mkCmp ( UInt* p, LOONGARCH64CondCode cond,
++ HReg src2, HReg src1, HReg dst )
++{
++ UInt d = iregEnc(dst);
++ UInt s1 = iregEnc(src1);
++ UInt s2 = iregEnc(src2);
++
++ switch (cond) {
++ case LAcc_EQ:
++ /*
++ xor dst, src1, src2
++ sltui dst, dst, 1
++ */
++ *p++ = emit_op_rk_rj_rd(LAbin_XOR, s2, s1, d);
++ *p++ = emit_op_si12_rj_rd(LAextra_SLTUI, 1, d, d);
++ return p;
++ case LAcc_NE:
++ /*
++ xor dst, src1, src2
++ sltu dst, $zero, dst
++ */
++ *p++ = emit_op_rk_rj_rd(LAbin_XOR, s2, s1, d);
++ *p++ = emit_op_rk_rj_rd(LAextra_SLTU, d, 0, d);
++ return p;
++ case LAcc_LT:
++ /* slt dst, src1, src2 */
++ *p++ = emit_op_rk_rj_rd(LAextra_SLT, s2, s1, d);
++ return p;
++ case LAcc_GE:
++ /*
++ slt dst, src1, src2
++ sltui dst, dst, 1
++ */
++ *p++ = emit_op_rk_rj_rd(LAextra_SLT, s2, s1, d);
++ *p++ = emit_op_si12_rj_rd(LAextra_SLTUI, 1, d, d);
++ return p;
++ case LAcc_LTU:
++ /* sltu dst, src1, src2 */
++ *p++ = emit_op_rk_rj_rd(LAextra_SLTU, s2, s1, d);
++ return p;
++ case LAcc_GEU:
++ /*
++ sltu dst, src1, src2
++ sltui dst, dst, 1
++ */
++ *p++ = emit_op_rk_rj_rd(LAextra_SLTU, s2, s1, d);
++ *p++ = emit_op_si12_rj_rd(LAextra_SLTUI, 1, d, d);
++ return p;
++ /* No LAcc_AL here.
++ case LAcc_AL:
++ break;
++ */
++ default:
++ return NULL;
++ }
++}
++
++static inline UInt* mkCMove ( UInt* p, HReg cond, HReg r0,
++ HReg r1, HReg dst, Bool isInt )
++{
++ if (isInt) {
++ /*
++ masknez $t0, r0, cond
++ maskeqz dst, r1, cond
++ or dst, $t0, dst
++ */
++ UInt c = iregEnc(cond);
++ UInt d = iregEnc(dst);
++ *p++ = emit_op_rk_rj_rd(LAextra_MASKNEZ, c, iregEnc(r0), 12);
++ *p++ = emit_op_rk_rj_rd(LAextra_MASKEQZ, c, iregEnc(r1), d);
++ *p++ = emit_op_rk_rj_rd(LAbin_OR, d, 12, d);
++ } else {
++ /*
++ movgr2cf $fcc0, cond
++ fsel dst, r0, r1, $fcc0
++ */
++ *p++ = emit_op_rj_cd(LAextra_MOVGR2CF, iregEnc(cond), 0);
++ *p++ = emit_op_ca_fk_fj_fd(LAextra_FSEL, 0, fregEnc(r1),
++ fregEnc(r0), fregEnc(dst));
++ }
++ return p;
++}
++
++static inline UInt* mkCall ( UInt* p, HReg cond, Addr64 target, RetLoc rloc )
++{
++ if (!hregIsInvalid(cond) && rloc.pri != RLPri_None) {
++ /* The call might not happen (it isn't unconditional) and
++ it returns a result. In this case we will need to
++ generate a control flow diamond to put 0x555..555 in
++ the return register(s) in the case where the call
++ doesn't happen. If this ever becomes necessary, maybe
++ copy code from the 32-bit ARM equivalent. Until that
++ day, just give up. */
++ return NULL;
++ }
++
++ UInt* ptmp = NULL;
++ if (!hregIsInvalid(cond)) {
++ /* Create a hole to put a conditional branch in. We'll
++ patch it once we know the branch length. */
++ ptmp = p;
++ p++;
++ }
++
++ /*
++ $t0 = target
++ jirl $ra, $t0, 0
++ */
++ p = mkLoadImm(p, hregT0(), target);
++ *p++ = emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1);
++
++ /* Patch the hole if necessary */
++ if (!hregIsInvalid(cond)) {
++ vassert(ptmp != NULL);
++ UInt offs = (UInt)(p - ptmp);
++ vassert(offs >= 3 && offs <= 6);
++ /* beq cond, $zero, offs */
++ *ptmp++ = emit_op_offs16_rj_rd(LAextra_BEQ, offs, iregEnc(cond), 0);
++ }
++
++ return p;
++}
++
++static inline UInt* mkXDirect ( UInt* p, Addr64 dstGA,
++ LOONGARCH64AMode* amPC,
++ HReg cond, Bool toFastEP,
++ const void* disp_cp_chain_me_to_slowEP,
++ const void* disp_cp_chain_me_to_fastEP )
++{
++ /* NB: what goes on here has to be very closely coordinated
++ with chainXDirect_LOONGARCH64 and unchainXDirect_LOONGARCH64 below. */
++ /* We're generating chain-me requests here, so we need to be
++ sure this is actually allowed -- no-redir translations
++ can't use chain-me's. Hence: */
++ vassert(disp_cp_chain_me_to_slowEP != NULL);
++ vassert(disp_cp_chain_me_to_fastEP != NULL);
++
++ /* Use ptmp for backpatching conditional jumps. */
++ UInt* ptmp = NULL;
++
++ /* First off, if this is conditional, create a conditional
++ jump over the rest of it. Or at least, leave a space for
++ it that we will shortly fill in. */
++ if (!hregIsInvalid(cond)) {
++ ptmp = p;
++ p++;
++ }
++
++ /* Update the guest PC.
++ $t0 = dstGA
++ st.d $t0, amPC
++ */
++ p = mkLoadImm(p, hregT0(), (ULong)dstGA);
++ p = mkStore(p, LAstore_ST_D, amPC, hregT0());
++
++ /* --- FIRST PATCHABLE BYTE follows --- */
++ /* VG_(disp_cp_chain_me_to_{slowEP,fastEP}) (where we're
++ calling to) backs up the return address, so as to find the
++ address of the first patchable byte. So: don't change the
++ number of instructions (5) below. */
++ /*
++ la $t0, VG_(disp_cp_chain_me_to_{slowEP,fastEP})
++ jirl $ra, $t0, 0
++ */
++ const void* disp_cp_chain_me = toFastEP ? disp_cp_chain_me_to_fastEP
++ : disp_cp_chain_me_to_slowEP;
++ p = mkLoadImm_EXACTLY4(p, hregT0(), (ULong)(Addr)disp_cp_chain_me);
++ *p++ = emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1);
++ /* --- END of PATCHABLE BYTES --- */
++
++ /* Fix up the conditional jump, if there was one. */
++ if (!hregIsInvalid(cond)) {
++ vassert(ptmp != NULL);
++ UInt offs = (UInt)(p - ptmp);
++ vassert(offs >= 8 && offs <= 11);
++ /* beq cond, $zero, offs */
++ *ptmp++ = emit_op_offs16_rj_rd(LAextra_BEQ, offs, iregEnc(cond), 0);
++ }
++
++ return p;
++}
++
++static inline UInt* mkXIndir ( UInt* p, HReg dstGA, LOONGARCH64AMode* amPC,
++ HReg cond, const void* disp_cp_xindir )
++{
++ /* We're generating transfers that could lead indirectly to a
++ chain-me, so we need to be sure this is actually allowed --
++ no-redir translations are not allowed to reach normal
++ translations without going through the scheduler. That means
++ no XDirects or XIndirs out from no-redir translations.
++ Hence: */
++ vassert(disp_cp_xindir != NULL);
++
++ /* Use ptmp for backpatching conditional jumps. */
++ UInt* ptmp = NULL;
++
++ /* First off, if this is conditional, create a conditional
++ jump over the rest of it. */
++ if (!hregIsInvalid(cond)) {
++ ptmp = p;
++ p++;
++ }
++
++ /* Update the guest PC.
++ or $t0, dstGA, $zero
++ st.d $t0, amPC
++ */
++ *p++ = emit_op_rk_rj_rd(LAbin_OR, 0, iregEnc(dstGA), 12);
++ p = mkStore(p, LAstore_ST_D, amPC, hregT0());
++
++ /*
++ la $t0, VG_(disp_cp_xindir)
++ jirl $ra, $t0, 0
++ */
++ p = mkLoadImm(p, hregT0(), (ULong)(Addr)disp_cp_xindir);
++ *p++ = emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1);
++
++ /* Fix up the conditional jump, if there was one. */
++ if (!hregIsInvalid(cond)) {
++ vassert(ptmp != NULL);
++ UInt offs = (UInt)(p - ptmp);
++ vassert(offs >= 5 && offs <= 8);
++ /* beq cond, $zero, offs */
++ *ptmp++ = emit_op_offs16_rj_rd(LAextra_BEQ, offs, iregEnc(cond), 0);
++ }
++
++ return p;
++}
++
++static inline UInt* mkXAssisted ( UInt* p, HReg dstGA, LOONGARCH64AMode* amPC,
++ HReg cond, IRJumpKind jk,
++ const void* disp_cp_xassisted )
++{
++ /* First off, if this is conditional, create a conditional jump
++ over the rest of it. Or at least, leave a space for it that
++ we will shortly fill in. */
++ UInt* ptmp = NULL;
++ if (!hregIsInvalid(cond)) {
++ ptmp = p;
++ p++;
++ }
++
++ /* Update the guest PC.
++ or $t0, dstGA, $zero
++ st.d $t0, amPC
++ */
++ *p++ = emit_op_rk_rj_rd(LAbin_OR, 0, iregEnc(dstGA), 12);
++ p = mkStore(p, LAstore_ST_D, amPC, hregT0());
++
++ /* li.w $s8, magic_number */
++ UInt trcval = 0;
++ switch (jk) {
++ case Ijk_Boring:
++ trcval = VEX_TRC_JMP_BORING;
++ break;
++ case Ijk_ClientReq:
++ trcval = VEX_TRC_JMP_CLIENTREQ;
++ break;
++ case Ijk_NoDecode:
++ trcval = VEX_TRC_JMP_NODECODE;
++ break;
++ case Ijk_InvalICache:
++ trcval = VEX_TRC_JMP_INVALICACHE;
++ break;
++ case Ijk_NoRedir:
++ trcval = VEX_TRC_JMP_NOREDIR;
++ break;
++ case Ijk_SigTRAP:
++ trcval = VEX_TRC_JMP_SIGTRAP;
++ break;
++ case Ijk_SigSEGV:
++ trcval = VEX_TRC_JMP_SIGSEGV;
++ break;
++ case Ijk_SigBUS:
++ trcval = VEX_TRC_JMP_SIGBUS;
++ break;
++ case Ijk_SigFPE_IntDiv:
++ trcval = VEX_TRC_JMP_SIGFPE_INTDIV;
++ break;
++ case Ijk_SigFPE_IntOvf:
++ trcval = VEX_TRC_JMP_SIGFPE_INTOVF;
++ break;
++ case Ijk_SigSYS:
++ trcval = VEX_TRC_JMP_SIGSYS;
++ break;
++ case Ijk_Sys_syscall:
++ trcval = VEX_TRC_JMP_SYS_SYSCALL;
++ break;
++ /* We don't expect to see the following being assisted.
++ case Ijk_Call:
++ case Ijk_Ret:
++ case Ijk_Yield:
++ case Ijk_EmWarn:
++ case Ijk_EmFail:
++ case Ijk_MapFail:
++ case Ijk_FlushDCache:
++ case Ijk_SigILL:
++ case Ijk_SigFPE:
++ case Ijk_Sys_int32:
++ case Ijk_Sys_int128:
++ case Ijk_Sys_int129:
++ case Ijk_Sys_int130:
++ case Ijk_Sys_int145:
++ case Ijk_Sys_int210:
++ case Ijk_Sys_sysenter:
++ */
++ default:
++ ppIRJumpKind(jk);
++ vpanic("emit_LOONGARCH64Instr.LAin_XAssisted: unexpected jump kind");
++ }
++ vassert(trcval != 0);
++ p = mkLoadImm(p, hregGSP(), trcval);
++
++ /*
++ la $t0, VG_(disp_cp_xassisted)
++ jirl $ra, $t0, 0
++ */
++ p = mkLoadImm(p, hregT0(), (ULong)(Addr)disp_cp_xassisted);
++ *p++ = emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1);
++
++ /* Fix up the conditional jump, if there was one. */
++ if (!hregIsInvalid(cond)) {
++ vassert(ptmp != NULL);
++ UInt offs = (UInt)(p - ptmp);
++ vassert(offs >= 6 && offs <= 12);
++ /* beq cond, $zero, offs */
++ *ptmp++ = emit_op_offs16_rj_rd(LAextra_BEQ, offs, iregEnc(cond), 0);
++ }
++
++ return p;
++}
++
++static inline UInt* mkEvCheck ( UInt* p, LOONGARCH64AMode* amCounter,
++ LOONGARCH64AMode* amFailAddr )
++{
++ UInt* p0 = p;
++
++ /*
++ ld.w $t0, amCounter
++ addi.d $t0, $t0, -1
++ st.w $t0, amCounter
++ bge $t0, $zero, nofail
++ ld.d $t0, amFailAddr
++ jirl $ra, $t0, 0
++ nofail:
++ */
++ p = mkLoad(p, LAload_LD_W, amCounter, hregT0());
++ *p++ = emit_op_si12_rj_rd(LAbin_ADDI_D, -1 & 0xfff, 12, 12);
++ p = mkStore(p, LAstore_ST_W, amCounter, hregT0());
++ *p++ = emit_op_offs16_rj_rd(LAextra_BGE, 3, 12, 0);
++ p = mkLoad(p, LAload_LD_W, amFailAddr, hregT0());
++ *p++ = emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1);
++
++ /* Crosscheck */
++ vassert(evCheckSzB_LOONGARCH64() == (UChar*)p - (UChar*)p0);
++ return p;
++}
++
++static inline UInt* mkProfInc ( UInt* p )
++{
++ /*
++ li $t0, 0x6555755585559555UL
++ ld.d $t1, $t0, 0
++ addi.d $t1, $t1, 1
++ st.d $t1, $t0, 0
++ */
++ p = mkLoadImm_EXACTLY4(p, hregT0(), 0x6555755585559555UL);
++ *p++ = emit_op_si12_rj_rd(LAload_LD_D, 0, 12, 13);
++ *p++ = emit_op_si12_rj_rd(LAbin_ADDI_D, 1, 13, 13);
++ *p++ = emit_op_si12_rj_rd(LAstore_ST_D, 0, 12, 13);
++ return p;
++}
++
++/* Emit an instruction into buf and return the number of bytes used.
++ Note that buf is not the insn's final place, and therefore it is
++ imperative to emit position-independent code. If the emitted
++ instruction was a profiler inc, set *is_profInc to True, else
++ leave it unchanged. */
++Int emit_LOONGARCH64Instr ( /*MB_MOD*/Bool* is_profInc,
++ UChar* buf,
++ Int nbuf,
++ const LOONGARCH64Instr* i,
++ Bool mode64,
++ VexEndness endness_host,
++ const void* disp_cp_chain_me_to_slowEP,
++ const void* disp_cp_chain_me_to_fastEP,
++ const void* disp_cp_xindir,
++ const void* disp_cp_xassisted )
++{
++ vassert(mode64 == True);
++
++ UInt* p = (UInt*)buf;
++ vassert(nbuf >= 32);
++ vassert((((HWord)buf) & 3) == 0);
++
++ switch (i->tag) {
++ case LAin_LI:
++ p = mkLoadImm(p, i->LAin.LI.dst, i->LAin.LI.imm);
++ break;
++ case LAin_Un:
++ p = mkUnary(p, i->LAin.Unary.op, i->LAin.Unary.src,
++ i->LAin.Unary.dst);
++ break;
++ case LAin_Bin:
++ p = mkBinary(p, i->LAin.Binary.op, i->LAin.Binary.src2,
++ i->LAin.Binary.src1, i->LAin.Binary.dst);
++ break;
++ case LAin_Load:
++ p = mkLoad(p, i->LAin.Load.op, i->LAin.Load.src,
++ i->LAin.Load.dst);
++ break;
++ case LAin_Store:
++ p = mkStore(p, i->LAin.Store.op, i->LAin.Store.dst,
++ i->LAin.Store.src);
++ break;
++ case LAin_LLSC:
++ p = mkLLSC(p, i->LAin.LLSC.op, i->LAin.LLSC.addr, i->LAin.LLSC.val);
++ break;
++ case LAin_Bar:
++ p = mkBar(p, i->LAin.Bar.op, i->LAin.Bar.hint);
++ break;
++ case LAin_FpUn:
++ p = mkFpUnary(p, i->LAin.FpUnary.op, i->LAin.FpUnary.src,
++ i->LAin.FpUnary.dst);
++ break;
++ case LAin_FpBin:
++ p = mkFpBinary(p, i->LAin.FpBinary.op, i->LAin.FpBinary.src2,
++ i->LAin.FpBinary.src1, i->LAin.FpBinary.dst);
++ break;
++ case LAin_FpTri:
++ p = mkFpTrinary(p, i->LAin.FpTrinary.op, i->LAin.FpTrinary.src3,
++ i->LAin.FpTrinary.src2, i->LAin.FpTrinary.src1,
++ i->LAin.FpTrinary.dst);
++ break;
++ case LAin_FpLoad:
++ p = mkFpLoad(p, i->LAin.FpLoad.op, i->LAin.FpLoad.src,
++ i->LAin.FpLoad.dst);
++ break;
++ case LAin_FpStore:
++ p = mkFpStore(p, i->LAin.FpStore.op, i->LAin.FpStore.dst,
++ i->LAin.FpStore.src);
++ break;
++ case LAin_FpMove:
++ p = mkFpMove(p, i->LAin.FpMove.op, i->LAin.FpMove.src,
++ i->LAin.FpMove.dst);
++ break;
++ case LAin_FpCmp:
++ p = mkFpCmp(p, i->LAin.FpCmp.op, i->LAin.FpCmp.src2,
++ i->LAin.FpCmp.src1, i->LAin.FpCmp.dst);
++ break;
++ case LAin_VecUn:
++ p = mkVecUnary(p, i->LAin.VecUnary.op, i->LAin.VecUnary.src,
++ i->LAin.VecUnary.dst);
++ break;
++ case LAin_VecBin:
++ p = mkVecBinary(p, i->LAin.VecBinary.op, i->LAin.VecBinary.src2,
++ i->LAin.VecBinary.src1, i->LAin.VecBinary.dst);
++ break;
++ case LAin_VecLoad:
++ p = mkVecLoad(p, i->LAin.VecLoad.op, i->LAin.VecLoad.src,
++ i->LAin.VecLoad.dst);
++ break;
++ case LAin_VecStore:
++ p = mkVecStore(p, i->LAin.VecStore.op, i->LAin.VecStore.dst,
++ i->LAin.VecStore.src);
++ break;
++ case LAin_Cas:
++ p = mkCas(p, i->LAin.Cas.old, i->LAin.Cas.addr, i->LAin.Cas.expd,
++ i->LAin.Cas.data, i->LAin.Cas.size64);
++ break;
++ case LAin_Cmp:
++ p = mkCmp(p, i->LAin.Cmp.cond, i->LAin.Cmp.src2,
++ i->LAin.Cmp.src1, i->LAin.Cmp.dst);
++ break;
++ case LAin_CMove:
++ p = mkCMove(p, i->LAin.CMove.cond, i->LAin.CMove.r0,
++ i->LAin.CMove.r1, i->LAin.CMove.dst,
++ i->LAin.CMove.isInt);
++ break;
++ case LAin_Call:
++ p = mkCall(p, i->LAin.Call.cond, i->LAin.Call.target,
++ i->LAin.Call.rloc);
++ break;
++ case LAin_XDirect:
++ p = mkXDirect(p, i->LAin.XDirect.dstGA, i->LAin.XDirect.amPC,
++ i->LAin.XDirect.cond, i->LAin.XDirect.toFastEP,
++ disp_cp_chain_me_to_slowEP,
++ disp_cp_chain_me_to_fastEP);
++ break;
++ case LAin_XIndir:
++ p = mkXIndir(p, i->LAin.XIndir.dstGA, i->LAin.XIndir.amPC,
++ i->LAin.XIndir.cond, disp_cp_xindir);
++ break;
++ case LAin_XAssisted:
++ p = mkXAssisted(p, i->LAin.XAssisted.dstGA, i->LAin.XAssisted.amPC,
++ i->LAin.XAssisted.cond, i->LAin.XAssisted.jk,
++ disp_cp_xassisted);
++ break;
++ case LAin_EvCheck:
++ p = mkEvCheck(p, i->LAin.EvCheck.amCounter,
++ i->LAin.EvCheck.amFailAddr);
++ break;
++ case LAin_ProfInc:
++ p = mkProfInc(p);
++ break;
++ default:
++ p = NULL;
++ break;
++ }
++
++ if (p == NULL) {
++ ppLOONGARCH64Instr(i, True);
++ vpanic("emit_LOONGARCH64Instr");
++ /*NOTREACHED*/
++ }
++
++ vassert(((UChar*)p) - &buf[0] <= 48);
++ return ((UChar*)p) - &buf[0];
++}
++
++/* How big is an event check? See case for mkEvCheck just above. That
++ crosschecks what this returns, so we can tell if we're inconsistent. */
++Int evCheckSzB_LOONGARCH64 ( void )
++{
++ return 6 * 4; // 6 insns
++}
++
++/* NB: what goes on here has to be very closely coordinated with the
++ emitInstr case for XDirect, above. */
++VexInvalRange chainXDirect_LOONGARCH64 ( VexEndness endness_host,
++ void* place_to_chain,
++ const void* disp_cp_chain_me_EXPECTED,
++ const void* place_to_jump_to )
++{
++ vassert(endness_host == VexEndnessLE);
++
++ /* What we're expecting to see is:
++ * la $t0, disp_cp_chain_me_to_EXPECTED
++ * jirl $ra, $t0, 0
++ * viz
++ * <16 bytes generated by mkLoadImm_EXACTLY4>
++ * jirl $ra, $t0, 0
++ */
++ UInt* p = (UInt*)place_to_chain;
++ vassert(((HWord)p & 3) == 0);
++ vassert(is_LoadImm_EXACTLY4(p, hregT0(), (ULong)(Addr)disp_cp_chain_me_EXPECTED));
++ vassert(p[4] == emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1));
++
++ /* And what we want to change it to is:
++ * la $t0, place_to_jump_to
++ * jirl $ra, $t0, 0
++ * viz
++ * <16 bytes generated by mkLoadImm_EXACTLY4>
++ * jirl $ra, $t0, 0
++ *
++ * The replacement has the same length as the original.
++ */
++ p = mkLoadImm_EXACTLY4(p, hregT0(), (ULong)(Addr)place_to_jump_to);
++ *p++ = emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1);
++
++ VexInvalRange vir = { (HWord)place_to_chain, 4 * 4 + 4 };
++ return vir;
++}
++
++/* NB: what goes on here has to be very closely coordinated with the
++ emitInstr case for XDirect, above. */
++VexInvalRange unchainXDirect_LOONGARCH64 ( VexEndness endness_host,
++ void* place_to_unchain,
++ const void* place_to_jump_to_EXPECTED,
++ const void* disp_cp_chain_me )
++{
++ vassert(endness_host == VexEndnessLE);
++
++ /* What we're expecting to see is:
++ * la $t0, place_to_jump_to_EXPECTED
++ * jirl $ra, $t0, 0
++ * viz
++ * <16 bytes generated by mkLoadImm_EXACTLY4>
++ * jirl $ra, $t0, 0
++ */
++ UInt* p = (UInt*)place_to_unchain;
++ vassert(((HWord)p & 3) == 0);
++ vassert(is_LoadImm_EXACTLY4(p, hregT0(), (ULong)(Addr)place_to_jump_to_EXPECTED));
++ vassert(p[4] == emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1));
++
++ /* And what we want to change it to is:
++ * la $t0, disp_cp_chain_me
++ * jirl $ra, $t0, 0
++ * viz
++ * <16 bytes generated by mkLoadImm_EXACTLY4>
++ * jirl $ra, $t0, 0
++ *
++ * The replacement has the same length as the original.
++ */
++ p = mkLoadImm_EXACTLY4(p, hregT0(), (ULong)(Addr)disp_cp_chain_me);
++ *p++ = emit_op_offs16_rj_rd(LAextra_JIRL, 0, 12, 1);
++
++ VexInvalRange vir = { (HWord)place_to_unchain, 4 * 4 + 4 };
++ return vir;
++}
++
++/* Patch the counter address into a profile inc point, as previously
++ created by the mkProfInc. */
++VexInvalRange patchProfInc_LOONGARCH64 ( VexEndness endness_host,
++ void* place_to_patch,
++ const ULong* location_of_counter )
++{
++ vassert(endness_host == VexEndnessLE);
++ vassert(sizeof(ULong*) == 8);
++
++ /*
++ $t0 = NotKnownYet
++ ld.d $t1, $t0, 0
++ addi.d $t1, $t1, 1
++ st.d $t1, $t0, 0
++ */
++ UInt* p = (UInt*)place_to_patch;
++ vassert(((HWord)p & 3) == 0);
++ vassert(is_LoadImm_EXACTLY4(p, hregT0(), 0x6555755585559555UL));
++ vassert(p[4] == emit_op_si12_rj_rd(LAload_LD_D, 0, 12, 13));
++ vassert(p[5] == emit_op_si12_rj_rd(LAbin_ADDI_D, 1, 13, 13));
++ vassert(p[6] == emit_op_si12_rj_rd(LAstore_ST_D, 0, 12, 13));
++
++ p = mkLoadImm_EXACTLY4(p, hregT0(), (ULong)(Addr)location_of_counter);
++
++ VexInvalRange vir = { (HWord)place_to_patch, 4 * 4 };
++ return vir;
++}
++
++
++/*---------------------------------------------------------------*/
++/*--- end host_loongarch64_defs.c ---*/
++/*---------------------------------------------------------------*/
+diff --git a/VEX/priv/host_loongarch64_defs.h b/VEX/priv/host_loongarch64_defs.h
+new file mode 100644
+index 0000000..5b6bc96
+--- /dev/null
++++ b/VEX/priv/host_loongarch64_defs.h
+@@ -0,0 +1,927 @@
++
++/*---------------------------------------------------------------*/
++/*--- begin host_loongarch64_defs.h ---*/
++/*---------------------------------------------------------------*/
++
++/*
++ This file is part of Valgrind, a dynamic binary instrumentation
++ framework.
++
++ Copyright (C) 2021-2022 Loongson Technology Corporation Limited
++
++ This program is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License as
++ published by the Free Software Foundation; either version 2 of the
++ License, or (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, see .
++
++ The GNU General Public License is contained in the file COPYING.
++*/
++
++#ifndef __VEX_HOST_LOONGARCH64_DEFS_H
++#define __VEX_HOST_LOONGARCH64_DEFS_H
++
++#include "libvex_basictypes.h"
++#include "libvex.h" /* VexArch */
++#include "host_generic_regs.h" /* HReg */
++
++
++/* --------- Registers. --------- */
++
++#define ST_IN static inline
++
++/* Integer static registers */
++ST_IN HReg hregLOONGARCH64_R23 ( void ) { return mkHReg(False, HRcInt64, 23, 0); }
++ST_IN HReg hregLOONGARCH64_R24 ( void ) { return mkHReg(False, HRcInt64, 24, 1); }
++ST_IN HReg hregLOONGARCH64_R25 ( void ) { return mkHReg(False, HRcInt64, 25, 2); }
++ST_IN HReg hregLOONGARCH64_R26 ( void ) { return mkHReg(False, HRcInt64, 26, 3); }
++ST_IN HReg hregLOONGARCH64_R27 ( void ) { return mkHReg(False, HRcInt64, 27, 4); }
++ST_IN HReg hregLOONGARCH64_R28 ( void ) { return mkHReg(False, HRcInt64, 28, 5); }
++ST_IN HReg hregLOONGARCH64_R29 ( void ) { return mkHReg(False, HRcInt64, 29, 6); }
++ST_IN HReg hregLOONGARCH64_R30 ( void ) { return mkHReg(False, HRcInt64, 30, 7); }
++/* $r31 is used as guest stack pointer */
++
++/* Integer temporary registers */
++/* $r12 is used as a chaining/ProfInc/Cmove/genSpill/genReload temporary */
++/* $r13 is used as a ProfInc temporary */
++ST_IN HReg hregLOONGARCH64_R14 ( void ) { return mkHReg(False, HRcInt64, 14, 8); }
++ST_IN HReg hregLOONGARCH64_R15 ( void ) { return mkHReg(False, HRcInt64, 15, 9); }
++ST_IN HReg hregLOONGARCH64_R16 ( void ) { return mkHReg(False, HRcInt64, 16, 10); }
++ST_IN HReg hregLOONGARCH64_R17 ( void ) { return mkHReg(False, HRcInt64, 17, 11); }
++ST_IN HReg hregLOONGARCH64_R18 ( void ) { return mkHReg(False, HRcInt64, 18, 12); }
++ST_IN HReg hregLOONGARCH64_R19 ( void ) { return mkHReg(False, HRcInt64, 19, 13); }
++ST_IN HReg hregLOONGARCH64_R20 ( void ) { return mkHReg(False, HRcInt64, 20, 14); }
++
++/* Floating point static registers */
++ST_IN HReg hregLOONGARCH64_F24 ( void ) { return mkHReg(False, HRcFlt64, 24, 15); }
++ST_IN HReg hregLOONGARCH64_F25 ( void ) { return mkHReg(False, HRcFlt64, 25, 16); }
++ST_IN HReg hregLOONGARCH64_F26 ( void ) { return mkHReg(False, HRcFlt64, 26, 17); }
++ST_IN HReg hregLOONGARCH64_F27 ( void ) { return mkHReg(False, HRcFlt64, 27, 18); }
++ST_IN HReg hregLOONGARCH64_F28 ( void ) { return mkHReg(False, HRcFlt64, 28, 19); }
++ST_IN HReg hregLOONGARCH64_F29 ( void ) { return mkHReg(False, HRcFlt64, 29, 20); }
++ST_IN HReg hregLOONGARCH64_F30 ( void ) { return mkHReg(False, HRcFlt64, 30, 21); }
++ST_IN HReg hregLOONGARCH64_F31 ( void ) { return mkHReg(False, HRcFlt64, 31, 22); }
++
++/* Vector static registers */
++ST_IN HReg hregLOONGARCH64_V24 ( void ) { return mkHReg(False, HRcVec128, 24, 23); }
++ST_IN HReg hregLOONGARCH64_V25 ( void ) { return mkHReg(False, HRcVec128, 25, 24); }
++ST_IN HReg hregLOONGARCH64_V26 ( void ) { return mkHReg(False, HRcVec128, 26, 25); }
++ST_IN HReg hregLOONGARCH64_V27 ( void ) { return mkHReg(False, HRcVec128, 27, 26); }
++ST_IN HReg hregLOONGARCH64_V28 ( void ) { return mkHReg(False, HRcVec128, 28, 27); }
++ST_IN HReg hregLOONGARCH64_V29 ( void ) { return mkHReg(False, HRcVec128, 29, 28); }
++ST_IN HReg hregLOONGARCH64_V30 ( void ) { return mkHReg(False, HRcVec128, 30, 29); }
++ST_IN HReg hregLOONGARCH64_V31 ( void ) { return mkHReg(False, HRcVec128, 31, 30); }
++
++/* Other Integer registers */
++ST_IN HReg hregLOONGARCH64_R0 ( void ) { return mkHReg(False, HRcInt64, 0, 31); }
++ST_IN HReg hregLOONGARCH64_R1 ( void ) { return mkHReg(False, HRcInt64, 1, 32); }
++ST_IN HReg hregLOONGARCH64_R2 ( void ) { return mkHReg(False, HRcInt64, 2, 33); }
++ST_IN HReg hregLOONGARCH64_R3 ( void ) { return mkHReg(False, HRcInt64, 3, 34); }
++ST_IN HReg hregLOONGARCH64_R4 ( void ) { return mkHReg(False, HRcInt64, 4, 35); }
++ST_IN HReg hregLOONGARCH64_R5 ( void ) { return mkHReg(False, HRcInt64, 5, 36); }
++ST_IN HReg hregLOONGARCH64_R6 ( void ) { return mkHReg(False, HRcInt64, 6, 37); }
++ST_IN HReg hregLOONGARCH64_R7 ( void ) { return mkHReg(False, HRcInt64, 7, 38); }
++ST_IN HReg hregLOONGARCH64_R8 ( void ) { return mkHReg(False, HRcInt64, 8, 39); }
++ST_IN HReg hregLOONGARCH64_R9 ( void ) { return mkHReg(False, HRcInt64, 9, 40); }
++ST_IN HReg hregLOONGARCH64_R10 ( void ) { return mkHReg(False, HRcInt64, 10, 41); }
++ST_IN HReg hregLOONGARCH64_R11 ( void ) { return mkHReg(False, HRcInt64, 11, 42); }
++ST_IN HReg hregLOONGARCH64_R12 ( void ) { return mkHReg(False, HRcInt64, 12, 43); }
++ST_IN HReg hregLOONGARCH64_R13 ( void ) { return mkHReg(False, HRcInt64, 13, 44); }
++ST_IN HReg hregLOONGARCH64_R21 ( void ) { return mkHReg(False, HRcInt64, 21, 45); }
++ST_IN HReg hregLOONGARCH64_R22 ( void ) { return mkHReg(False, HRcInt64, 22, 46); }
++ST_IN HReg hregLOONGARCH64_R31 ( void ) { return mkHReg(False, HRcInt64, 31, 47); }
++
++/* Special registers */
++ST_IN HReg hregLOONGARCH64_FCSR3 ( void ) { return mkHReg(False, HRcInt32, 3, 48); }
++
++#undef ST_IN
++
++#define hregZERO() hregLOONGARCH64_R0()
++#define hregSP() hregLOONGARCH64_R3()
++#define hregT0() hregLOONGARCH64_R12()
++#define hregT1() hregLOONGARCH64_R13()
++#define hregGSP() hregLOONGARCH64_R31()
++
++extern UInt ppHRegLOONGARCH64 ( HReg reg );
++
++/* Number of registers used arg passing in function calls */
++#define LOONGARCH64_N_ARGREGS 8 /* a0 ... a7 */
++
++
++/* --------- Condition codes, LOONGARCH64 encoding. --------- */
++typedef enum {
++ LAcc_EQ = 0, /* equal */
++ LAcc_NE = 1, /* not equal */
++
++ LAcc_LT = 2, /* less than (signed) */
++ LAcc_GE = 3, /* great equal (signed) */
++
++ LAcc_LTU = 4, /* less than (unsigned) */
++ LAcc_GEU = 5, /* great equal (unsigned) */
++
++ LAcc_AL = 6 /* always (unconditional) */
++} LOONGARCH64CondCode;
++
++
++/* --------- Memory address expressions (amodes). --------- */
++
++typedef enum {
++ LAam_RI, /* Reg + Imm (signed 12-bit) */
++ LAam_RR /* Reg1 + Reg2 */
++} LOONGARCH64AModeTag;
++
++typedef struct {
++ LOONGARCH64AModeTag tag;
++ union {
++ struct {
++ HReg base;
++ UShort index;
++ } RI;
++ struct {
++ HReg base;
++ HReg index;
++ } RR;
++ } LAam;
++} LOONGARCH64AMode;
++
++extern LOONGARCH64AMode* LOONGARCH64AMode_RI ( HReg reg, UShort imm );
++extern LOONGARCH64AMode* LOONGARCH64AMode_RR ( HReg base, HReg index );
++
++
++/* --------- Operand, which can be reg or imm. --------- */
++
++typedef enum {
++ LAri_Reg,
++ LAri_Imm
++} LOONGARCH64RITag;
++
++typedef struct {
++ LOONGARCH64RITag tag;
++ union {
++ struct {
++ HReg reg;
++ } R;
++ struct {
++ UShort imm;
++ UChar size; // size == 5 || size == 6 || size == 12
++ Bool isSigned;
++ } I;
++ } LAri;
++} LOONGARCH64RI;
++
++extern LOONGARCH64RI* LOONGARCH64RI_R ( HReg reg );
++extern LOONGARCH64RI* LOONGARCH64RI_I ( UShort imm, UChar size, Bool isSigned );
++
++
++/* --------- Instructions. --------- */
++
++/* Tags for unary operations */
++typedef enum {
++ LAun_CLZ_W = 0x00001400,
++ LAun_CTZ_W = 0x00001c00,
++ LAun_CLZ_D = 0x00002400,
++ LAun_CTZ_D = 0x00002c00,
++ LAun_EXT_W_H = 0x00005800,
++ LAun_EXT_W_B = 0x00005c00
++} LOONGARCH64UnOp;
++
++/* Tags for binary operations */
++typedef enum {
++ LAbin_ADD_W = 0x00100000,
++ LAbin_ADD_D = 0x00108000,
++ LAbin_SUB_W = 0x00110000,
++ LAbin_SUB_D = 0x00118000,
++ LAbin_NOR = 0x00140000,
++ LAbin_AND = 0x00148000,
++ LAbin_OR = 0x00150000,
++ LAbin_XOR = 0x00158000,
++ LAbin_SLL_W = 0x00170000,
++ LAbin_SRL_W = 0x00178000,
++ LAbin_SRA_W = 0x00180000,
++ LAbin_SLL_D = 0x00188000,
++ LAbin_SRL_D = 0x00190000,
++ LAbin_SRA_D = 0x00198000,
++ LAbin_MUL_W = 0x001c0000,
++ LAbin_MUL_D = 0x001d8000,
++ LAbin_MULH_W = 0x001c8000,
++ LAbin_MULH_WU = 0x001d0000,
++ LAbin_MULH_D = 0x001e0000,
++ LAbin_MULH_DU = 0x001e8000,
++ LAbin_MULW_D_W = 0x001f0000,
++ LAbin_MULW_D_WU = 0x001f8000,
++ LAbin_DIV_W = 0x00200000,
++ LAbin_MOD_W = 0x00208000,
++ LAbin_DIV_WU = 0x00210000,
++ LAbin_MOD_WU = 0x00218000,
++ LAbin_DIV_D = 0x00220000,
++ LAbin_MOD_D = 0x00228000,
++ LAbin_DIV_DU = 0x00230000,
++ LAbin_MOD_DU = 0x00238000,
++ LAbin_SLLI_W = 0x00408000,
++ LAbin_SLLI_D = 0x00410000,
++ LAbin_SRLI_W = 0x00448000,
++ LAbin_SRLI_D = 0x00450000,
++ LAbin_SRAI_W = 0x00488000,
++ LAbin_SRAI_D = 0x00490000,
++ LAbin_ADDI_W = 0x02800000,
++ LAbin_ADDI_D = 0x02c00000,
++ LAbin_ANDI = 0x03400000,
++ LAbin_ORI = 0x03800000,
++ LAbin_XORI = 0x03c00000
++} LOONGARCH64BinOp;
++
++/* Tags for load operations */
++typedef enum {
++ LAload_LD_W = 0x28800000,
++ LAload_LD_D = 0x28c00000,
++ LAload_LD_BU = 0x2a000000,
++ LAload_LD_HU = 0x2a400000,
++ LAload_LD_WU = 0x2a800000,
++ LAload_LDX_D = 0x380c0000,
++ LAload_LDX_BU = 0x38200000,
++ LAload_LDX_HU = 0x38240000,
++ LAload_LDX_WU = 0x38280000
++} LOONGARCH64LoadOp;
++
++/* Tags for store operations */
++typedef enum {
++ LAstore_ST_B = 0x29000000,
++ LAstore_ST_H = 0x29400000,
++ LAstore_ST_W = 0x29800000,
++ LAstore_ST_D = 0x29c00000,
++ LAstore_STX_B = 0x38100000,
++ LAstore_STX_H = 0x38140000,
++ LAstore_STX_W = 0x38180000,
++ LAstore_STX_D = 0x381c0000
++} LOONGARCH64StoreOp;
++
++/* Tags for ll/sc operations */
++typedef enum {
++ LAllsc_LL_W = 0x20000000,
++ LAllsc_SC_W = 0x21000000,
++ LAllsc_LL_D = 0x22000000,
++ LAllsc_SC_D = 0x23000000
++} LOONGARCH64LLSCOp;
++
++/* Tags for barrier operations */
++typedef enum {
++ LAbar_DBAR = 0x38720000,
++ LAbar_IBAR = 0x38728000
++} LOONGARCH64BarOp;
++
++/* Tags for floating point unary operations */
++typedef enum {
++ LAfpun_FABS_S = 0x01140400,
++ LAfpun_FABS_D = 0x01140800,
++ LAfpun_FNEG_S = 0x01141400,
++ LAfpun_FNEG_D = 0x01141800,
++ LAfpun_FLOGB_S = 0x01142400,
++ LAfpun_FLOGB_D = 0x01142800,
++ LAfpun_FSQRT_S = 0x01144400,
++ LAfpun_FSQRT_D = 0x01144800,
++ LAfpun_FRSQRT_S = 0x01146400,
++ LAfpun_FRSQRT_D = 0x01146800,
++ LAfpun_FCVT_S_D = 0x01191800,
++ LAfpun_FCVT_D_S = 0x01192400,
++ LAfpun_FTINT_W_S = 0x011b0400,
++ LAfpun_FTINT_W_D = 0x011b0800,
++ LAfpun_FTINT_L_S = 0x011b2400,
++ LAfpun_FTINT_L_D = 0x011b2800,
++ LAfpun_FFINT_S_W = 0x011d1000,
++ LAfpun_FFINT_S_L = 0x011d1800,
++ LAfpun_FFINT_D_W = 0x011d2000,
++ LAfpun_FFINT_D_L = 0x011d2800,
++ LAfpun_FRINT_S = 0x011e4400,
++ LAfpun_FRINT_D = 0x011e4800
++} LOONGARCH64FpUnOp;
++
++/* Tags for floating point binary operations */
++typedef enum {
++ LAfpbin_FADD_S = 0x01008000,
++ LAfpbin_FADD_D = 0x01010000,
++ LAfpbin_FSUB_S = 0x01028000,
++ LAfpbin_FSUB_D = 0x01030000,
++ LAfpbin_FMUL_S = 0x01048000,
++ LAfpbin_FMUL_D = 0x01050000,
++ LAfpbin_FDIV_S = 0x01068000,
++ LAfpbin_FDIV_D = 0x01070000,
++ LAfpbin_FMAX_S = 0x01088000,
++ LAfpbin_FMAX_D = 0x01090000,
++ LAfpbin_FMIN_S = 0x010a8000,
++ LAfpbin_FMIN_D = 0x010b0000,
++ LAfpbin_FMAXA_S = 0x010c8000,
++ LAfpbin_FMAXA_D = 0x010d0000,
++ LAfpbin_FMINA_S = 0x010e8000,
++ LAfpbin_FMINA_D = 0x010f0000,
++ LAfpbin_FSCALEB_S = 0x01108000,
++ LAfpbin_FSCALEB_D = 0x01110000
++} LOONGARCH64FpBinOp;
++
++/* Tags for floating point trinary operations */
++typedef enum {
++ LAfpbin_FMADD_S = 0x08100000,
++ LAfpbin_FMADD_D = 0x08200000,
++ LAfpbin_FMSUB_S = 0x08500000,
++ LAfpbin_FMSUB_D = 0x08600000
++} LOONGARCH64FpTriOp;
++
++/* Tags for floating point load operations */
++typedef enum {
++ LAfpload_FLD_S = 0x2b000000,
++ LAfpload_FLD_D = 0x2b800000,
++ LAfpload_FLDX_S = 0x38300000,
++ LAfpload_FLDX_D = 0x38340000
++} LOONGARCH64FpLoadOp;
++
++/* Tags for floating point store operations */
++typedef enum {
++ LAfpstore_FST_S = 0x2b400000,
++ LAfpstore_FST_D = 0x2bc00000,
++ LAfpstore_FSTX_S = 0x38380000,
++ LAfpstore_FSTX_D = 0x383c0000
++} LOONGARCH64FpStoreOp;
++
++/* Tags for floating point move operations */
++typedef enum {
++ LAfpmove_FMOV_S = 0x01149400,
++ LAfpmove_FMOV_D = 0x01149800,
++ LAfpmove_MOVGR2FR_W = 0x0114a400,
++ LAfpmove_MOVGR2FR_D = 0x0114a800,
++ LAfpmove_MOVFR2GR_S = 0x0114b400,
++ LAfpmove_MOVFR2GR_D = 0x0114b800,
++ LAfpmove_MOVGR2FCSR = 0x0114c000,
++ LAfpmove_MOVFCSR2GR = 0x0114c800
++} LOONGARCH64FpMoveOp;
++
++/* Tags for floating point compare operations */
++typedef enum {
++ LAfpcmp_FCMP_CLT_S = 0x0c110000,
++ LAfpcmp_FCMP_CLT_D = 0x0c210000,
++ LAfpcmp_FCMP_CEQ_S = 0x0c120000,
++ LAfpcmp_FCMP_CEQ_D = 0x0c220000,
++ LAfpcmp_FCMP_CUN_S = 0x0c140000,
++ LAfpcmp_FCMP_CUN_D = 0x0c240000
++} LOONGARCH64FpCmpOp;
++
++/* Tags for vector unary operations */
++typedef enum {
++ LAvecun_VCLO_B = 0x729c0000,
++ LAvecun_VCLO_H = 0x729c0400,
++ LAvecun_VCLO_W = 0x729c0800,
++ LAvecun_VCLZ_B = 0x729c1000,
++ LAvecun_VCLZ_H = 0x729c1400,
++ LAvecun_VCLZ_W = 0x729c1800,
++ LAvecun_VCLZ_D = 0x729c1c00,
++ LAvecun_VPCNT_B = 0x729c2000,
++ LAvecun_VFRINTRM_S = 0x729d4400,
++ LAvecun_VFRINTRM_D = 0x729d4800,
++ LAvecun_VFRINTRP_S = 0x729d5400,
++ LAvecun_VFRINTRP_D = 0x729d5800,
++ LAvecun_VFRINTRZ_S = 0x729d6400,
++ LAvecun_VFRINTRZ_D = 0x729d6800,
++ LAvecun_VFRINTRNE_S = 0x729d7400,
++ LAvecun_VFRINTRNE_D = 0x729d7800,
++ LAvecun_VEXTH_H_B = 0x729ee000,
++ LAvecun_VEXTH_W_H = 0x729ee400,
++ LAvecun_VEXTH_D_W = 0x729ee800,
++ LAvecun_VEXTH_Q_D = 0x729eec00,
++ LAvecun_VEXTH_HU_BU = 0x729ef000,
++ LAvecun_VEXTH_WU_HU = 0x729ef400,
++ LAvecun_VEXTH_DU_WU = 0x729ef800,
++ LAvecun_VEXTH_QU_DU = 0x729efc00,
++ LAvecun_VREPLGR2VR_B = 0x729f0000,
++ LAvecun_VREPLGR2VR_H = 0x729f0400,
++ LAvecun_VREPLGR2VR_W = 0x729f0800,
++ LAvecun_VREPLGR2VR_D = 0x729f0c00
++} LOONGARCH64VecUnOp;
++
++/* Tags for vector binary operations */
++typedef enum {
++ LAvecbin_VSEQ_B = 0x70000000,
++ LAvecbin_VSEQ_H = 0x70008000,
++ LAvecbin_VSEQ_W = 0x70010000,
++ LAvecbin_VSEQ_D = 0x70018000,
++ LAvecbin_VSLT_B = 0x70060000,
++ LAvecbin_VSLT_H = 0x70068000,
++ LAvecbin_VSLT_W = 0x70070000,
++ LAvecbin_VSLT_D = 0x70078000,
++ LAvecbin_VSLT_BU = 0x70080000,
++ LAvecbin_VSLT_HU = 0x70088000,
++ LAvecbin_VSLT_WU = 0x70090000,
++ LAvecbin_VSLT_DU = 0x70098000,
++ LAvecbin_VADD_B = 0x700a0000,
++ LAvecbin_VADD_H = 0x700a8000,
++ LAvecbin_VADD_W = 0x700b0000,
++ LAvecbin_VADD_D = 0x700b8000,
++ LAvecbin_VSUB_B = 0x700c0000,
++ LAvecbin_VSUB_H = 0x700c8000,
++ LAvecbin_VSUB_W = 0x700d0000,
++ LAvecbin_VSUB_D = 0x700d8000,
++ LAvecbin_VSADD_B = 0x70460000,
++ LAvecbin_VSADD_H = 0x70468000,
++ LAvecbin_VSADD_W = 0x70470000,
++ LAvecbin_VSADD_D = 0x70478000,
++ LAvecbin_VSSUB_B = 0x70480000,
++ LAvecbin_VSSUB_H = 0x70488000,
++ LAvecbin_VSSUB_W = 0x70490000,
++ LAvecbin_VSSUB_D = 0x70498000,
++ LAvecbin_VSADD_BU = 0x704a0000,
++ LAvecbin_VSADD_HU = 0x704a8000,
++ LAvecbin_VSADD_WU = 0x704b0000,
++ LAvecbin_VSADD_DU = 0x704b8000,
++ LAvecbin_VSSUB_BU = 0x704c0000,
++ LAvecbin_VSSUB_HU = 0x704c8000,
++ LAvecbin_VSSUB_WU = 0x704d0000,
++ LAvecbin_VSSUB_DU = 0x704d8000,
++ LAvecbin_VADDA_B = 0x705c0000,
++ LAvecbin_VADDA_H = 0x705c8000,
++ LAvecbin_VADDA_W = 0x705d0000,
++ LAvecbin_VADDA_D = 0x705d8000,
++ LAvecbin_VAVGR_B = 0x70680000,
++ LAvecbin_VAVGR_H = 0x70688000,
++ LAvecbin_VAVGR_W = 0x70690000,
++ LAvecbin_VAVGR_D = 0x70698000,
++ LAvecbin_VAVGR_BU = 0x706a0000,
++ LAvecbin_VAVGR_HU = 0x706a8000,
++ LAvecbin_VAVGR_WU = 0x706b0000,
++ LAvecbin_VAVGR_DU = 0x706b8000,
++ LAvecbin_VMAX_B = 0x70700000,
++ LAvecbin_VMAX_H = 0x70708000,
++ LAvecbin_VMAX_W = 0x70710000,
++ LAvecbin_VMAX_D = 0x70718000,
++ LAvecbin_VMIN_B = 0x70720000,
++ LAvecbin_VMIN_H = 0x70728000,
++ LAvecbin_VMIN_W = 0x70730000,
++ LAvecbin_VMIN_D = 0x70738000,
++ LAvecbin_VMAX_BU = 0x70740000,
++ LAvecbin_VMAX_HU = 0x70748000,
++ LAvecbin_VMAX_WU = 0x70750000,
++ LAvecbin_VMAX_DU = 0x70758000,
++ LAvecbin_VMIN_BU = 0x70760000,
++ LAvecbin_VMIN_HU = 0x70768000,
++ LAvecbin_VMIN_WU = 0x70770000,
++ LAvecbin_VMIN_DU = 0x70778000,
++ LAvecbin_VMUL_B = 0x70840000,
++ LAvecbin_VMUL_H = 0x70848000,
++ LAvecbin_VMUL_W = 0x70850000,
++ LAvecbin_VMUH_B = 0x70860000,
++ LAvecbin_VMUH_H = 0x70868000,
++ LAvecbin_VMUH_W = 0x70870000,
++ LAvecbin_VMUH_BU = 0x70880000,
++ LAvecbin_VMUH_HU = 0x70888000,
++ LAvecbin_VMUH_WU = 0x70890000,
++ LAvecbin_VSLL_B = 0x70e80000,
++ LAvecbin_VSLL_H = 0x70e88000,
++ LAvecbin_VSLL_W = 0x70e90000,
++ LAvecbin_VSLL_D = 0x70e98000,
++ LAvecbin_VSRL_B = 0x70ea0000,
++ LAvecbin_VSRL_H = 0x70ea8000,
++ LAvecbin_VSRL_W = 0x70eb0000,
++ LAvecbin_VSRL_D = 0x70eb8000,
++ LAvecbin_VSRA_B = 0x70ec0000,
++ LAvecbin_VSRA_H = 0x70ec8000,
++ LAvecbin_VSRA_W = 0x70ed0000,
++ LAvecbin_VSRA_D = 0x70ed8000,
++ LAvecbin_VILVL_B = 0x711a0000,
++ LAvecbin_VILVL_H = 0x711a8000,
++ LAvecbin_VILVL_W = 0x711b0000,
++ LAvecbin_VILVL_D = 0x711b8000,
++ LAvecbin_VILVH_B = 0x711c0000,
++ LAvecbin_VILVH_H = 0x711c8000,
++ LAvecbin_VILVH_W = 0x711d0000,
++ LAvecbin_VILVH_D = 0x711d8000,
++ LAvecbin_VPICKEV_B = 0x711e0000,
++ LAvecbin_VPICKEV_H = 0x711e8000,
++ LAvecbin_VPICKEV_W = 0x711f0000,
++ LAvecbin_VPICKOD_B = 0x71200000,
++ LAvecbin_VPICKOD_H = 0x71208000,
++ LAvecbin_VPICKOD_W = 0x71210000,
++ LAvecbin_VREPLVE_B = 0x71220000,
++ LAvecbin_VREPLVE_H = 0x71228000,
++ LAvecbin_VREPLVE_W = 0x71230000,
++ LAvecbin_VREPLVE_D = 0x71238000,
++ LAvecbin_VAND_V = 0x71260000,
++ LAvecbin_VOR_V = 0x71268000,
++ LAvecbin_VXOR_V = 0x71270000,
++ LAvecbin_VNOR_V = 0x71278000,
++ LAvecbin_VADD_Q = 0x712d0000,
++ LAvecbin_VSUB_Q = 0x712d8000,
++ LAvecbin_VFADD_S = 0x71308000,
++ LAvecbin_VFADD_D = 0x71310000,
++ LAvecbin_VFSUB_S = 0x71328000,
++ LAvecbin_VFSUB_D = 0x71330000,
++ LAvecbin_VFMUL_S = 0x71388000,
++ LAvecbin_VFMUL_D = 0x71390000,
++ LAvecbin_VFDIV_S = 0x713a8000,
++ LAvecbin_VFDIV_D = 0x713b0000,
++ LAvecbin_VFMAX_S = 0x713c8000,
++ LAvecbin_VFMAX_D = 0x713d0000,
++ LAvecbin_VFMIN_S = 0x713e8000,
++ LAvecbin_VFMIN_D = 0x713f0000,
++ LAvecbin_VBSLL_V = 0x728e0000,
++ LAvecbin_VBSRL_V = 0x728e8000,
++ LAvecbin_VINSGR2VR_B = 0x72eb8000,
++ LAvecbin_VINSGR2VR_H = 0x72ebc000,
++ LAvecbin_VINSGR2VR_W = 0x72ebe000,
++ LAvecbin_VINSGR2VR_D = 0x72ebf000,
++ LAvecbin_VPICKVE2GR_W = 0x72efe000,
++ LAvecbin_VPICKVE2GR_D = 0x72eff000,
++ LAvecbin_VPICKVE2GR_BU = 0x72f38000,
++ LAvecbin_VPICKVE2GR_HU = 0x72f3c000,
++ LAvecbin_VPICKVE2GR_WU = 0x72f3e000,
++ LAvecbin_VPICKVE2GR_DU = 0x72f3f000,
++ LAvecbin_VSLLI_B = 0x732c2000,
++ LAvecbin_VSLLI_H = 0x732c4000,
++ LAvecbin_VSLLI_W = 0x732c8000,
++ LAvecbin_VSLLI_D = 0x732d0000,
++ LAvecbin_VSRLI_B = 0x73302000,
++ LAvecbin_VSRLI_H = 0x73304000,
++ LAvecbin_VSRLI_W = 0x73308000,
++ LAvecbin_VSRLI_D = 0x73310000,
++ LAvecbin_VSRAI_B = 0x73342000,
++ LAvecbin_VSRAI_H = 0x73344000,
++ LAvecbin_VSRAI_W = 0x73348000,
++ LAvecbin_VSRAI_D = 0x73350000,
++ LAvecbin_VORI_B = 0x73d40000
++} LOONGARCH64VecBinOp;
++
++/* Tags for vector load operations */
++typedef enum {
++ LAvecload_VLD = 0x2c000000,
++ LAvecload_VLDX = 0x38400000
++} LOONGARCH64VecLoadOp;
++
++/* Tags for vector store operations */
++typedef enum {
++ LAvecstore_VST = 0x2c400000,
++ LAvecstore_VSTX = 0x38440000
++} LOONGARCH64VecStoreOp;
++
++/* Tags for extra operations, we only use them when emiting code directly */
++typedef enum {
++ LAextra_MOVGR2CF = 0x0114d800,
++ LAextra_MOVCF2GR = 0x0114dc00,
++ LAextra_SLT = 0x00120000,
++ LAextra_SLTU = 0x00128000,
++ LAextra_MASKEQZ = 0x00130000,
++ LAextra_MASKNEZ = 0x00138000,
++ LAextra_SLTI = 0x02000000,
++ LAextra_SLTUI = 0x02400000,
++ LAextra_LU52I_D = 0x03000000,
++ LAextra_FSEL = 0x0d000000,
++ LAextra_LU12I_W = 0x14000000,
++ LAextra_LU32I_D = 0x16000000,
++ LAextra_JIRL = 0x4c000000,
++ LAextra_B = 0x50000000,
++ LAextra_BEQ = 0x58000000,
++ LAextra_BNE = 0x5c000000,
++ LAextra_BGE = 0x64000000
++} LOONGARCH64ExtraOp;
++
++/* Tags for instructions */
++typedef enum {
++ /* Pseudo-insn, used for generating a 64-bit
++ literal to register */
++ LAin_LI, /* load imm */
++
++ /* Integer insns */
++ LAin_Un, /* unary */
++ LAin_Bin, /* binary */
++ LAin_Load, /* load */
++ LAin_Store, /* store */
++ LAin_LLSC, /* ll/sc */
++ LAin_Bar, /* barrier */
++
++ /* Floating point insns */
++ LAin_FpUn, /* floating point unary */
++ LAin_FpBin, /* floating point binary */
++ LAin_FpTri, /* floating point trinary */
++ LAin_FpLoad, /* floating point load */
++ LAin_FpStore, /* floating point store */
++ LAin_FpMove, /* floating point move */
++ LAin_FpCmp, /* floating point compare */
++
++ /* Vector insns */
++ LAin_VecUn, /* vector unary */
++ LAin_VecBin, /* vector binary */
++ LAin_VecLoad, /* vector load */
++ LAin_VecStore, /* vector store */
++
++ /* Pseudo-insn */
++ LAin_Cas, /* compare and swap */
++ LAin_Cmp, /* word compare */
++ LAin_CMove, /* condition move */
++
++ /* Call target (an absolute address), on given
++ condition (which could be LAcc_AL). */
++ LAin_Call, /* call */
++
++ /* The following 5 insns are mandated by translation chaining */
++ LAin_XDirect, /* direct transfer to GA */
++ LAin_XIndir, /* indirect transfer to GA */
++ LAin_XAssisted, /* assisted transfer to GA */
++ LAin_EvCheck, /* Event check */
++ LAin_ProfInc /* 64-bit profile counter increment */
++} LOONGARCH64InstrTag;
++
++typedef struct {
++ LOONGARCH64InstrTag tag;
++ union {
++ struct {
++ ULong imm;
++ HReg dst;
++ } LI;
++ struct {
++ LOONGARCH64UnOp op;
++ HReg src;
++ HReg dst;
++ } Unary;
++ struct {
++ LOONGARCH64BinOp op;
++ LOONGARCH64RI* src2;
++ HReg src1;
++ HReg dst;
++ } Binary;
++ struct {
++ LOONGARCH64LoadOp op;
++ LOONGARCH64AMode* src;
++ HReg dst;
++ } Load;
++ struct {
++ LOONGARCH64StoreOp op;
++ LOONGARCH64AMode* dst;
++ HReg src;
++ } Store;
++ struct {
++ LOONGARCH64LLSCOp op;
++ Bool isLoad;
++ LOONGARCH64AMode* addr;
++ HReg val;
++ } LLSC;
++ struct {
++ LOONGARCH64BarOp op;
++ UShort hint;
++ } Bar;
++ struct {
++ LOONGARCH64FpUnOp op;
++ HReg src;
++ HReg dst;
++ } FpUnary;
++ struct {
++ LOONGARCH64FpBinOp op;
++ HReg src2;
++ HReg src1;
++ HReg dst;
++ } FpBinary;
++ struct {
++ LOONGARCH64FpTriOp op;
++ HReg src3;
++ HReg src2;
++ HReg src1;
++ HReg dst;
++ } FpTrinary;
++ struct {
++ LOONGARCH64FpLoadOp op;
++ LOONGARCH64AMode* src;
++ HReg dst;
++ } FpLoad;
++ struct {
++ LOONGARCH64FpStoreOp op;
++ LOONGARCH64AMode* dst;
++ HReg src;
++ } FpStore;
++ struct {
++ LOONGARCH64FpMoveOp op;
++ HReg src;
++ HReg dst;
++ } FpMove;
++ struct {
++ LOONGARCH64FpCmpOp op;
++ HReg src2;
++ HReg src1;
++ HReg dst;
++ } FpCmp;
++ struct {
++ LOONGARCH64VecUnOp op;
++ HReg src;
++ HReg dst;
++ } VecUnary;
++ struct {
++ LOONGARCH64VecBinOp op;
++ LOONGARCH64RI* src2;
++ HReg src1;
++ HReg dst;
++ } VecBinary;
++ struct {
++ LOONGARCH64VecLoadOp op;
++ LOONGARCH64AMode* src;
++ HReg dst;
++ } VecLoad;
++ struct {
++ LOONGARCH64VecStoreOp op;
++ LOONGARCH64AMode* dst;
++ HReg src;
++ } VecStore;
++ struct {
++ HReg old;
++ HReg addr;
++ HReg expd;
++ HReg data;
++ Bool size64;
++ } Cas;
++ struct {
++ LOONGARCH64CondCode cond;
++ HReg dst;
++ HReg src1;
++ HReg src2;
++ } Cmp;
++ struct {
++ HReg cond;
++ HReg r0;
++ HReg r1;
++ HReg dst;
++ Bool isInt;
++ } CMove;
++ struct {
++ HReg cond;
++ Addr64 target;
++ UInt nArgRegs;
++ RetLoc rloc;
++ } Call;
++ struct {
++ Addr64 dstGA;
++ LOONGARCH64AMode* amPC;
++ HReg cond;
++ Bool toFastEP;
++ } XDirect;
++ struct {
++ HReg dstGA;
++ LOONGARCH64AMode* amPC;
++ HReg cond;
++ } XIndir;
++ struct {
++ HReg dstGA;
++ LOONGARCH64AMode* amPC;
++ HReg cond;
++ IRJumpKind jk;
++ } XAssisted;
++ struct {
++ LOONGARCH64AMode* amCounter;
++ LOONGARCH64AMode* amFailAddr;
++ } EvCheck;
++ struct {
++ /* No fields. The address of the counter to inc is
++ installed later, post-translation, by patching it in,
++ as it is not known at translation time. */
++ } ProfInc;
++ } LAin;
++} LOONGARCH64Instr;
++
++extern LOONGARCH64Instr* LOONGARCH64Instr_LI ( ULong imm, HReg dst );
++extern LOONGARCH64Instr* LOONGARCH64Instr_Unary ( LOONGARCH64UnOp op,
++ HReg src, HReg dst );
++extern LOONGARCH64Instr* LOONGARCH64Instr_Binary ( LOONGARCH64BinOp op,
++ LOONGARCH64RI* src2,
++ HReg src1, HReg dst );
++extern LOONGARCH64Instr* LOONGARCH64Instr_Load ( LOONGARCH64LoadOp op,
++ LOONGARCH64AMode* src,
++ HReg dst );
++extern LOONGARCH64Instr* LOONGARCH64Instr_Store ( LOONGARCH64StoreOp op,
++ LOONGARCH64AMode* dst,
++ HReg src );
++extern LOONGARCH64Instr* LOONGARCH64Instr_LLSC ( LOONGARCH64LLSCOp op,
++ Bool isLoad,
++ LOONGARCH64AMode* addr,
++ HReg val );
++extern LOONGARCH64Instr* LOONGARCH64Instr_Bar ( LOONGARCH64BarOp op,
++ UShort hint );
++extern LOONGARCH64Instr* LOONGARCH64Instr_FpUnary ( LOONGARCH64FpUnOp op,
++ HReg src, HReg dst );
++extern LOONGARCH64Instr* LOONGARCH64Instr_FpBinary ( LOONGARCH64FpBinOp op,
++ HReg src2, HReg src1,
++ HReg dst );
++extern LOONGARCH64Instr* LOONGARCH64Instr_FpTrinary ( LOONGARCH64FpTriOp op,
++ HReg src3, HReg src2,
++ HReg src1, HReg dst );
++extern LOONGARCH64Instr* LOONGARCH64Instr_FpLoad ( LOONGARCH64FpLoadOp op,
++ LOONGARCH64AMode* src,
++ HReg dst );
++extern LOONGARCH64Instr* LOONGARCH64Instr_FpStore ( LOONGARCH64FpStoreOp op,
++ LOONGARCH64AMode* dst,
++ HReg src );
++extern LOONGARCH64Instr* LOONGARCH64Instr_FpMove ( LOONGARCH64FpMoveOp op,
++ HReg src, HReg dst );
++extern LOONGARCH64Instr* LOONGARCH64Instr_FpCmp ( LOONGARCH64FpCmpOp op,
++ HReg src2, HReg src1,
++ HReg dst );
++extern LOONGARCH64Instr* LOONGARCH64Instr_VecUnary ( LOONGARCH64VecUnOp op,
++ HReg src, HReg dst );
++extern LOONGARCH64Instr* LOONGARCH64Instr_VecBinary ( LOONGARCH64VecBinOp op,
++ LOONGARCH64RI* src2,
++ HReg src1, HReg dst );
++extern LOONGARCH64Instr* LOONGARCH64Instr_VecLoad ( LOONGARCH64VecLoadOp op,
++ LOONGARCH64AMode* src,
++ HReg dst );
++extern LOONGARCH64Instr* LOONGARCH64Instr_VecStore ( LOONGARCH64VecStoreOp op,
++ LOONGARCH64AMode* dst,
++ HReg src );
++extern LOONGARCH64Instr* LOONGARCH64Instr_Cas ( HReg old, HReg addr,
++ HReg expd, HReg data,
++ Bool size64 );
++extern LOONGARCH64Instr* LOONGARCH64Instr_Cmp ( LOONGARCH64CondCode cond,
++ HReg src2, HReg src1,
++ HReg dst );
++extern LOONGARCH64Instr* LOONGARCH64Instr_CMove ( HReg cond, HReg r0, HReg r1,
++ HReg dst, Bool isInt );
++extern LOONGARCH64Instr* LOONGARCH64Instr_Call ( HReg cond, Addr64 target,
++ UInt nArgRegs, RetLoc rloc );
++extern LOONGARCH64Instr* LOONGARCH64Instr_XDirect ( Addr64 dstGA,
++ LOONGARCH64AMode* amPC,
++ HReg cond, Bool toFastEP );
++extern LOONGARCH64Instr* LOONGARCH64Instr_XIndir ( HReg dstGA,
++ LOONGARCH64AMode* amPC,
++ HReg cond );
++extern LOONGARCH64Instr* LOONGARCH64Instr_XAssisted ( HReg dstGA,
++ LOONGARCH64AMode* amPC,
++ HReg cond, IRJumpKind jk );
++extern LOONGARCH64Instr* LOONGARCH64Instr_EvCheck ( LOONGARCH64AMode* amCounter,
++ LOONGARCH64AMode* amFailAddr );
++extern LOONGARCH64Instr* LOONGARCH64Instr_ProfInc ( void );
++
++extern void ppLOONGARCH64Instr ( const LOONGARCH64Instr* i, Bool mode64 );
++
++/* Some functions that insulate the register allocator from details
++ of the underlying instruction set. */
++extern void getRegUsage_LOONGARCH64Instr ( HRegUsage* u,
++ const LOONGARCH64Instr* i,
++ Bool mode64 );
++extern void mapRegs_LOONGARCH64Instr ( HRegRemap* m, LOONGARCH64Instr* i,
++ Bool mode64 );
++extern Int emit_LOONGARCH64Instr (/*MB_MOD*/Bool* is_profInc,
++ UChar* buf,
++ Int nbuf,
++ const LOONGARCH64Instr* i,
++ Bool mode64,
++ VexEndness endness_host,
++ const void* disp_cp_chain_me_to_slowEP,
++ const void* disp_cp_chain_me_to_fastEP,
++ const void* disp_cp_xindir,
++ const void* disp_cp_xassisted );
++
++extern void genSpill_LOONGARCH64 ( /*OUT*/ HInstr** i1, /*OUT*/ HInstr** i2,
++ HReg rreg, Int offsetB, Bool mode64);
++extern void genReload_LOONGARCH64 ( /*OUT*/ HInstr** i1, /*OUT*/ HInstr** i2,
++ HReg rreg, Int offsetB, Bool mode64);
++extern LOONGARCH64Instr* genMove_LOONGARCH64 ( HReg from, HReg to,
++ Bool mode64 );
++
++extern const RRegUniverse* getRRegUniverse_LOONGARCH64 ( void );
++
++extern HInstrArray* iselSB_LOONGARCH64 ( const IRSB*,
++ VexArch,
++ const VexArchInfo*,
++ const VexAbiInfo*,
++ Int offs_Host_EvC_Counter,
++ Int offs_Host_EvC_FailAddr,
++ Bool chainingAllowed,
++ Bool addProfInc,
++ Addr max_ga );
++
++/* How big is an event check? See case for Min_EvCheck in
++ emit_LOONGARCH64Instr just above. That crosschecks what this returns,
++ so we can tell if we're inconsistent. */
++extern Int evCheckSzB_LOONGARCH64 ( void );
++
++/* NB: what goes on here has to be very closely coordinated with the
++ emitInstr case for XDirect, above. */
++extern VexInvalRange chainXDirect_LOONGARCH64 ( VexEndness endness_host,
++ void* place_to_chain,
++ const void* disp_cp_chain_me_EXPECTED,
++ const void* place_to_jump_to );
++
++/* NB: what goes on here has to be very closely coordinated with the
++ emitInstr case for XDirect, above. */
++extern VexInvalRange unchainXDirect_LOONGARCH64 ( VexEndness endness_host,
++ void* place_to_unchain,
++ const void* place_to_jump_to_EXPECTED,
++ const void* disp_cp_chain_me );
++
++/* Patch the counter address into a profile inc point, as previously
++ created by the Min_ProfInc case for emit_LOONGARCH64Instr. */
++extern VexInvalRange patchProfInc_LOONGARCH64 ( VexEndness endness_host,
++ void* place_to_patch,
++ const ULong* location_of_counter );
++
++#endif /* ndef __VEX_HOST_LOONGARCH64_DEFS_H */
++
++
++/*---------------------------------------------------------------*/
++/*--- end host-loongarch64_defs.h ---*/
++/*---------------------------------------------------------------*/
+diff --git a/VEX/priv/host_loongarch64_isel.c b/VEX/priv/host_loongarch64_isel.c
+new file mode 100644
+index 0000000..b490fbd
+--- /dev/null
++++ b/VEX/priv/host_loongarch64_isel.c
+@@ -0,0 +1,4120 @@
++
++/*---------------------------------------------------------------*/
++/*--- begin host_loongarch64_isel.c ---*/
++/*---------------------------------------------------------------*/
++
++/*
++ This file is part of Valgrind, a dynamic binary instrumentation
++ framework.
++
++ Copyright (C) 2021-2022 Loongson Technology Corporation Limited
+
-+ /* --------- BINARY OP --------- */
-+ case Iex_Binop: {
-+ switch (e->Iex.Binop.op) {
-+ case Iop_8HLto16: {
-+ HReg dst = newVRegI(env);
-+ HReg tHi = newVRegI(env);
-+ HReg tLow = newVRegI(env);
-+ HReg sHi = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ HReg sLow = iselIntExpr_R(env, e->Iex.Binop.arg2);
-+ LOONGARCH64RI* ui5 = LOONGARCH64RI_I(8, 5, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ui5, sHi, tHi));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ui5, sLow, tLow));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_W, ui5, tLow, tLow));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, LOONGARCH64RI_R(tHi), tLow, dst));
-+ return dst;
-+ }
-+ case Iop_16HLto32: {
-+ HReg dst = newVRegI(env);
-+ HReg tHi = newVRegI(env);
-+ HReg tLow = newVRegI(env);
-+ HReg sHi = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ HReg sLow = iselIntExpr_R(env, e->Iex.Binop.arg2);
-+ LOONGARCH64RI* ui5 = LOONGARCH64RI_I(16, 5, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ui5, sHi, tHi));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ui5, sLow, tLow));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_W, ui5, tLow, tLow));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, LOONGARCH64RI_R(tHi), tLow, dst));
-+ return dst;
-+ }
-+ case Iop_32HLto64: {
-+ HReg dst = newVRegI(env);
-+ HReg hi = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* lo = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(32, 6, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, hi, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, lo, dst, dst));
-+ return dst;
-+ }
-+ case Iop_Add32: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, True);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_ADD_W : LAbin_ADDI_W;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_Add64: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, True);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_ADD_D : LAbin_ADDI_D;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_And8: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, False);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_AND : LAbin_ANDI;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_And32: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, False);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_AND : LAbin_ANDI;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_And64: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, False);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_AND : LAbin_ANDI;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_DivModS32to32: {
-+ HReg dst = newVRegI(env);
-+ HReg tmp = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2);
-+ LOONGARCH64RI* ri1 = LOONGARCH64RI_I(0, 5, False);
-+ LOONGARCH64RI* ri2 = LOONGARCH64RI_R(src2);
-+ LOONGARCH64RI* ri3 = LOONGARCH64RI_I(32, 6, False);
-+ LOONGARCH64RI* ri4 = LOONGARCH64RI_R(tmp);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src1, src1));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src2, src2));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_W, ri2, src1, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MOD_W, ri2, src1, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri3, tmp, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri3, dst, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri3, dst, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri4, dst, dst));
-+ return dst;
-+ }
-+ case Iop_DivModU32to32: {
-+ HReg dst = newVRegI(env);
-+ HReg tmp = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2);
-+ LOONGARCH64RI* ri1 = LOONGARCH64RI_I(0, 5, False);
-+ LOONGARCH64RI* ri2 = LOONGARCH64RI_R(src2);
-+ LOONGARCH64RI* ri3 = LOONGARCH64RI_I(32, 6, False);
-+ LOONGARCH64RI* ri4 = LOONGARCH64RI_R(tmp);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src1, src1));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src2, src2));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_WU, ri2, src1, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MOD_WU, ri2, src1, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri3, tmp, tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri3, dst, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri3, dst, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri4, dst, dst));
-+ return dst;
-+ }
-+ case Iop_DivS32: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2);
-+ LOONGARCH64RI* ri1 = LOONGARCH64RI_I(0, 5, False);
-+ LOONGARCH64RI* ri2 = LOONGARCH64RI_R(src2);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src1, src1));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src2, src2));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_W, ri2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_DivS64: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_D, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_DivU32: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2);
-+ LOONGARCH64RI* ri1 = LOONGARCH64RI_I(0, 5, False);
-+ LOONGARCH64RI* ri2 = LOONGARCH64RI_R(src2);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src1, src1));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src2, src2));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_WU, ri2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_DivU64: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_DU, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_CmpF32: {
-+ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
-+ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
-+ return convert_cond_to_IR(env, src2, src1, False);
-+ }
-+ case Iop_CmpF64: {
-+ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
-+ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
-+ return convert_cond_to_IR(env, src2, src1, True);
-+ }
-+ case Iop_F32toI32S: {
-+ HReg tmp = newVRegF(env);
-+ HReg dst = newVRegI(env);
-+ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FTINT_W_S, src, tmp));
-+ set_rounding_mode_default(env);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVFR2GR_S, tmp, dst));
-+ return dst;
-+ }
-+ case Iop_F32toI64S: {
-+ HReg tmp = newVRegF(env);
-+ HReg dst = newVRegI(env);
-+ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FTINT_L_S, src, tmp));
-+ set_rounding_mode_default(env);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVFR2GR_D, tmp, dst));
-+ return dst;
-+ }
-+ case Iop_F64toI32S: {
-+ HReg tmp = newVRegF(env);
-+ HReg dst = newVRegI(env);
-+ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FTINT_W_D, src, tmp));
-+ set_rounding_mode_default(env);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVFR2GR_S, tmp, dst));
-+ return dst;
-+ }
-+ case Iop_F64toI64S: {
-+ HReg tmp = newVRegF(env);
-+ HReg dst = newVRegI(env);
-+ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FTINT_L_D, src, tmp));
-+ set_rounding_mode_default(env);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVFR2GR_D, tmp, dst));
-+ return dst;
-+ }
-+ case Iop_GetElem16x8:
-+ case Iop_GetElem32x4:
-+ case Iop_GetElem64x2:
-+ case Iop_GetElem8x16: {
-+ UChar size;
-+ LOONGARCH64VecBinOp pickOp, veplOp;
-+ switch (e->Iex.Binop.op) {
-+ case Iop_GetElem8x16:
-+ size = 4;
-+ pickOp = LAvecbin_VPICKVE2GR_BU;
-+ veplOp = LAvecbin_VREPLVE_B;
-+ break;
-+ case Iop_GetElem16x8:
-+ size = 3;
-+ pickOp = LAvecbin_VPICKVE2GR_HU;
-+ veplOp = LAvecbin_VREPLVE_H;
-+ break;
-+ case Iop_GetElem32x4:
-+ size = 2;
-+ pickOp = LAvecbin_VPICKVE2GR_WU;
-+ veplOp = LAvecbin_VREPLVE_W;
-+ break;
-+ case Iop_GetElem64x2:
-+ size = 1;
-+ pickOp = LAvecbin_VPICKVE2GR_DU;
-+ veplOp = LAvecbin_VREPLVE_D;
-+ break;
-+ default:
-+ vassert(0);
-+ break;
-+ }
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselV128Expr(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, size, False);
-+ if (src2->tag == LAri_Imm) {
-+ addInstr(env, LOONGARCH64Instr_VecBinary(pickOp, src2, src1, dst));
-+ } else {
-+ HReg v_tmp = newVRegV(env);
-+ addInstr(env, LOONGARCH64Instr_VecBinary(veplOp, src2, src1, v_tmp));
-+ addInstr(env, LOONGARCH64Instr_VecBinary(pickOp, LOONGARCH64RI_I(0, size, False), v_tmp, dst));
-+ }
++ This program is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License as
++ published by the Free Software Foundation; either version 2 of the
++ License, or (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ General Public License for more details->
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, see .
++
++ The GNU General Public License is contained in the file COPYING.
++*/
++
++#include "libvex_basictypes.h"
++#include "libvex_ir.h"
++#include "libvex.h"
++
++#include "main_util.h"
++#include "main_globals.h"
++#include "host_generic_regs.h"
++#include "host_loongarch64_defs.h"
++
++
++/*---------------------------------------------------------*/
++/*--- ISelEnv ---*/
++/*---------------------------------------------------------*/
++
++/* This carries around:
++
++ - A mapping from IRTemp to IRType, giving the type of any IRTemp we
++ might encounter. This is computed before insn selection starts,
++ and does not change.
++
++ - A mapping from IRTemp to HReg. This tells the insn selector
++ which virtual register is associated with each IRTemp temporary.
++ This is computed before insn selection starts, and does not
++ change. We expect this mapping to map precisely the same set of
++ IRTemps as the type mapping does.
++
++ |vregmap| holds the primary register for the IRTemp.
++ |vregmapHI| is only used for 128-bit integer-typed
++ IRTemps. It holds the identity of a second
++ 64-bit virtual HReg, which holds the high half
++ of the value.
++
++ - The code array, that is, the insns selected so far.
++
++ - A counter, for generating new virtual registers.
++
++ - The host hardware capabilities word. This is set at the start
++ and does not change.
++
++ - A Bool for indicating whether we may generate chain-me
++ instructions for control flow transfers, or whether we must use
++ XAssisted.
++
++ - The maximum guest address of any guest insn in this block.
++ Actually, the address of the highest-addressed byte from any insn
++ in this block. Is set at the start and does not change. This is
++ used for detecting jumps which are definitely forward-edges from
++ this block, and therefore can be made (chained) to the fast entry
++ point of the destination, thereby avoiding the destination's
++ event check.
++
++ - An IRExpr*, which may be NULL, holding the IR expression (an
++ IRRoundingMode-encoded value) to which the FPU's rounding mode
++ was most recently set. Setting to NULL is always safe. Used to
++ avoid redundant settings of the FPU's rounding mode, as
++ described in set_FPCR_rounding_mode below.
++
++ Note, this is all (well, mostly) host-independent.
++*/
++
++typedef
++ struct {
++ /* Constant -- are set at the start and do not change. */
++ IRTypeEnv* type_env;
++
++ HReg* vregmap;
++ HReg* vregmapHI;
++ Int n_vregmap;
++
++ UInt hwcaps;
++
++ Bool chainingAllowed;
++ Addr64 max_ga;
++
++ /* These are modified as we go along. */
++ HInstrArray* code;
++ Int vreg_ctr;
++ }
++ ISelEnv;
++
++
++static HReg lookupIRTemp ( ISelEnv* env, IRTemp tmp )
++{
++ vassert(tmp < env->n_vregmap);
++ return env->vregmap[tmp];
++}
++
++static void lookupIRTempPair ( HReg* vrHI, HReg* vrLO,
++ ISelEnv* env, IRTemp tmp )
++{
++ vassert(tmp < env->n_vregmap);
++ vassert(!hregIsInvalid(env->vregmapHI[tmp]));
++ *vrLO = env->vregmap[tmp];
++ *vrHI = env->vregmapHI[tmp];
++}
++
++static void addInstr ( ISelEnv* env, LOONGARCH64Instr* instr )
++{
++ addHInstr(env->code, instr);
++ if (vex_traceflags & VEX_TRACE_VCODE) {
++ ppLOONGARCH64Instr(instr, True);
++ vex_printf("\n");
++ }
++}
++
++static HReg newVRegI ( ISelEnv* env )
++{
++ HReg reg = mkHReg(True/*virtual reg*/, HRcInt64, 0, env->vreg_ctr);
++ env->vreg_ctr++;
++ return reg;
++}
++
++static HReg newVRegF ( ISelEnv* env )
++{
++ HReg reg = mkHReg(True/*virtual reg*/, HRcFlt64, 0, env->vreg_ctr);
++ env->vreg_ctr++;
++ return reg;
++}
++
++static HReg newVRegV ( ISelEnv* env )
++{
++ HReg reg = mkHReg(True/*virtual reg*/, HRcVec128, 0, env->vreg_ctr);
++ env->vreg_ctr++;
++ return reg;
++}
++
++
++/*---------------------------------------------------------*/
++/*--- ISEL: Forward declarations ---*/
++/*---------------------------------------------------------*/
++
++/* These are organised as iselXXX and iselXXX_wrk pairs. The
++ iselXXX_wrk do the real work, but are not to be called directly.
++ For each XXX, iselXXX calls its iselXXX_wrk counterpart, then
++ checks that all returned registers are virtual. You should not
++ call the _wrk version directly.
++*/
++
++static LOONGARCH64AMode* iselIntExpr_AMode_wrk ( ISelEnv* env,
++ IRExpr* e, IRType dty );
++static LOONGARCH64AMode* iselIntExpr_AMode ( ISelEnv* env,
++ IRExpr* e, IRType dty );
++
++static LOONGARCH64RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e,
++ UChar size, Bool isSigned );
++static LOONGARCH64RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e,
++ UChar size, Bool isSigned );
++
++static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e );
++static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e );
++
++static HReg iselCondCode_R_wrk ( ISelEnv* env, IRExpr* e );
++static HReg iselCondCode_R ( ISelEnv* env, IRExpr* e );
++
++static void iselInt128Expr_wrk ( HReg* hi, HReg* lo,
++ ISelEnv* env, IRExpr* e );
++static void iselInt128Expr ( HReg* hi, HReg* lo,
++ ISelEnv* env, IRExpr* e );
++
++static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e );
++static HReg iselFltExpr ( ISelEnv* env, IRExpr* e );
++
++static HReg iselV128Expr_wrk ( ISelEnv* env, IRExpr* e );
++static HReg iselV128Expr ( ISelEnv* env, IRExpr* e );
++
++static void iselV256Expr_wrk ( HReg* hi, HReg* lo,
++ ISelEnv* env, IRExpr* e );
++static void iselV256Expr ( HReg* hi, HReg* lo,
++ ISelEnv* env, IRExpr* e );
++
++
++/*---------------------------------------------------------*/
++/*--- ISEL: Misc helpers ---*/
++/*---------------------------------------------------------*/
++
++/* Generate move insn */
++static LOONGARCH64Instr* LOONGARCH64Instr_Move ( HReg to, HReg from )
++{
++ LOONGARCH64RI *ri = LOONGARCH64RI_R(hregZERO());
++ return LOONGARCH64Instr_Binary(LAbin_OR, ri, from, to);
++}
++
++/* Generate vector move insn */
++static LOONGARCH64Instr* LOONGARCH64Instr_VecMove ( HReg to, HReg from )
++{
++ LOONGARCH64RI *ri = LOONGARCH64RI_I(0, 8, False);
++ return LOONGARCH64Instr_VecBinary(LAvecbin_VORI_B, ri, from, to);
++}
++
++/* Generate LOONGARCH64AMode from HReg and UInt */
++static LOONGARCH64AMode* mkLOONGARCH64AMode_RI ( HReg reg, UInt imm )
++{
++ vassert(imm < (1 << 12));
++ return LOONGARCH64AMode_RI(reg, (UShort)imm);
++}
++
++/* Set floating point rounding mode */
++static void set_rounding_mode ( ISelEnv* env, IRExpr* mode )
++{
++ /*
++ rounding mode | LOONGARCH | IR
++ ------------------------------
++ to nearest | 00 | 00
++ to zero | 01 | 11
++ to +infinity | 10 | 10
++ to -infinity | 11 | 01
++ */
++
++ /* rm = XOR(rm, (rm << 1)) & 3 */
++ HReg rm = iselIntExpr_R(env, mode);
++ HReg tmp = newVRegI(env);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(1, 5, False);
++ LOONGARCH64RI* ri2 = LOONGARCH64RI_R(rm);
++ LOONGARCH64RI* ri3 = LOONGARCH64RI_I(3, 12, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri, rm, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_XOR, ri2, tmp, rm));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri3, rm, rm));
++
++ /* Save old value of FCSR3 */
++ HReg fcsr = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVFCSR2GR,
++ hregLOONGARCH64_FCSR3(), fcsr));
++
++ /* Store old FCSR3 to stack */
++ LOONGARCH64RI* ri4 = LOONGARCH64RI_I(-4 & 0xfff, 12, True);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D, ri4, hregSP(), hregSP()));
++ LOONGARCH64AMode* am = LOONGARCH64AMode_RI(hregSP(), 0);
++ addInstr(env, LOONGARCH64Instr_Store(LAstore_ST_W, am, fcsr));
++
++ /* Set new value of FCSR3 */
++ LOONGARCH64RI* ri5 = LOONGARCH64RI_I(8, 5, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri5, rm, rm));
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FCSR,
++ rm, hregLOONGARCH64_FCSR3()));
++}
++
++static void set_rounding_mode_default ( ISelEnv* env )
++{
++ /* Load old FCSR3 from stack */
++ HReg fcsr = newVRegI(env);
++ LOONGARCH64AMode* am = LOONGARCH64AMode_RI(hregSP(), 0);
++ addInstr(env, LOONGARCH64Instr_Load(LAload_LD_WU, am, fcsr));
++
++ /* Restore SP */
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(4, 12, True);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D, ri, hregSP(), hregSP()));
++
++ /* Set new value of FCSR3 */
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FCSR,
++ fcsr, hregLOONGARCH64_FCSR3()));
++}
++
++/* Convert LOONGARCH FCMP cond to IR result */
++static HReg convert_cond_to_IR ( ISelEnv* env, HReg src2, HReg src1, Bool size64 )
++{
++ HReg tmp = newVRegI(env);
++ HReg dst = newVRegI(env);
+
-+ return dst;
-+ }
-+ case Iop_Max32U: {
-+ HReg cond = newVRegI(env);
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2);
-+ addInstr(env, LOONGARCH64Instr_Cmp(LAcc_LTU, src2, src1, cond));
-+ addInstr(env, LOONGARCH64Instr_CMove(cond, src1, src2, dst, True));
-+ return dst;
-+ }
-+ case Iop_MullS32: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MULW_D_W, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_MullU32: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MULW_D_WU, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_Or32: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, False);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_OR : LAbin_ORI;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_Or64: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, False);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_OR : LAbin_ORI;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_Sar32: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 5, False);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_SRA_W : LAbin_SRAI_W;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_Sar64: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 6, False);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_SRA_D : LAbin_SRAI_D;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_Shl32: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 5, False);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_SLL_W : LAbin_SLLI_W;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_Shl64: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 6, False);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_SLL_D : LAbin_SLLI_D;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_Shr32: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 5, False);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_SRL_W : LAbin_SRLI_W;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_Shr64: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 6, False);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_SRL_D : LAbin_SRLI_D;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_Sub32: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SUB_W, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_Sub64: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SUB_D, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_Xor32: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, False);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_XOR : LAbin_XORI;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_Xor64: {
-+ HReg dst = newVRegI(env);
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, False);
-+ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_XOR : LAbin_XORI;
-+ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_64HLtoV128: {
-+ HReg dst = newVRegV(env);
-+ HReg sHi = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ HReg sLow = iselIntExpr_R(env, e->Iex.Binop.arg2);
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_D,
-+ LOONGARCH64RI_I(0, 1, False), sLow, dst));
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_D,
-+ LOONGARCH64RI_I(1, 1, False), sHi, dst));
-+ return dst;
-+ }
-+ default:
-+ goto irreducible;
-+ }
-+ }
++ LOONGARCH64RI* ri1 = LOONGARCH64RI_I(63, 6, False);
++ LOONGARCH64RI* ri2 = LOONGARCH64RI_I(0x45, 12, False);
++ if (size64)
++ addInstr(env, LOONGARCH64Instr_FpCmp(LAfpcmp_FCMP_CUN_D, src2, src1, tmp));
++ else
++ addInstr(env, LOONGARCH64Instr_FpCmp(LAfpcmp_FCMP_CUN_S, src2, src1, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri1, tmp, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri1, tmp, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri2, tmp, dst));
+
-+ /* --------- UNARY OP --------- */
-+ case Iex_Unop: {
-+ switch (e->Iex.Unop.op) {
-+ case Iop_128HIto64: {
-+ HReg hi, lo;
-+ iselInt128Expr(&hi, &lo, env, e->Iex.Unop.arg);
-+ return hi;
-+ }
-+ case Iop_128to64: {
-+ HReg hi, lo;
-+ iselInt128Expr(&hi, &lo, env, e->Iex.Unop.arg);
-+ return lo;
-+ }
-+ case Iop_16Sto64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_Unary(LAun_EXT_W_H, src, dst));
-+ return dst;
-+ }
-+ case Iop_16Uto32: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(48, 6, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri, dst, dst));
-+ return dst;
-+ }
-+ case Iop_16Uto64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(48, 6, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri, dst, dst));
-+ return dst;
-+ }
-+ case Iop_1Sto32: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselCondCode_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(63, 6, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri, dst, dst));
-+ return dst;
-+ }
-+ case Iop_1Sto64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselCondCode_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(63, 6, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri, dst, dst));
-+ return dst;
-+ }
-+ case Iop_1Uto64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselCondCode_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(0x1, 12, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri, src, dst));
-+ return dst;
-+ }
-+ case Iop_1Uto8: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselCondCode_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(0x1, 12, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri, src, dst));
-+ return dst;
-+ }
-+ case Iop_32Sto64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(0, 5, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri, src, dst));
-+ return dst;
-+ }
-+ case Iop_32Uto64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(32, 6, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri, dst, dst));
-+ return dst;
-+ }
-+ case Iop_32to8: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(0xff, 12, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri, src, dst));
-+ return dst;
-+ }
-+ case Iop_64HIto32: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(32, 6, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri, src, dst));
-+ return dst;
-+ }
-+ case Iop_64to32: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(32, 6, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri, dst, dst));
-+ return dst;
-+ }
-+ case Iop_64to8: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(0xff, 12, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri, src, dst));
-+ return dst;
-+ }
-+ case Iop_8Sto64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_Unary(LAun_EXT_W_B, src, dst));
-+ return dst;
-+ }
-+ case Iop_8Uto32: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(0xff, 12, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri, src, dst));
-+ return dst;
-+ }
-+ case Iop_8Uto64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(0xff, 12, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri, src, dst));
-+ return dst;
-+ }
-+ case Iop_CmpwNEZ32: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(63, 6, False);
-+ addInstr(env, LOONGARCH64Instr_Cmp(LAcc_NE, hregZERO(), src, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, dst, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri, dst, dst));
-+ return dst;
-+ }
-+ case Iop_CmpwNEZ64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(63, 6, False);
-+ addInstr(env, LOONGARCH64Instr_Cmp(LAcc_NE, hregZERO(), src, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, dst, dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri, dst, dst));
-+ return dst;
-+ }
-+ case Iop_Clz32: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_Unary(LAun_CLZ_W, src, dst));
-+ return dst;
-+ }
-+ case Iop_Clz64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_Unary(LAun_CLZ_D, src, dst));
-+ return dst;
-+ }
-+ case Iop_Ctz32: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_Unary(LAun_CTZ_W, src, dst));
-+ return dst;
-+ }
-+ case Iop_Ctz64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_Unary(LAun_CTZ_D, src, dst));
-+ return dst;
-+ }
-+ case Iop_Left16: {
-+ HReg tmp = newVRegI(env);
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_R(src);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SUB_D, ri, hregZERO(), tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri, tmp, dst));
-+ return dst;
-+ }
-+ case Iop_Left32: {
-+ HReg tmp = newVRegI(env);
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_R(src);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SUB_D, ri, hregZERO(), tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri, tmp, dst));
-+ return dst;
-+ }
-+ case Iop_Left64: {
-+ HReg tmp = newVRegI(env);
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_R(src);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SUB_D, ri, hregZERO(), tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri, tmp, dst));
-+ return dst;
-+ }
-+ case Iop_Left8: {
-+ HReg tmp = newVRegI(env);
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_R(src);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SUB_D, ri, hregZERO(), tmp));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri, tmp, dst));
-+ return dst;
-+ }
-+ case Iop_ReinterpF32asI32: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselFltExpr(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVFR2GR_S, src, dst));
-+ return dst;
-+ }
-+ case Iop_ReinterpF64asI64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselFltExpr(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVFR2GR_D, src, dst));
-+ return dst;
-+ }
-+ case Iop_Not32: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_R(hregZERO());
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_NOR, ri, src, dst));
-+ return dst;
-+ }
-+ case Iop_Not64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_R(hregZERO());
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_NOR, ri, src, dst));
-+ return dst;
-+ }
-+ case Iop_V128to32: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselV128Expr(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VPICKVE2GR_W,
-+ LOONGARCH64RI_I(0, 2, False), src, dst));
-+ return dst;
-+ }
-+ case Iop_V128to64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselV128Expr(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VPICKVE2GR_D,
-+ LOONGARCH64RI_I(0, 1, False), src, dst));
-+ return dst;
-+ }
-+ case Iop_V128HIto64: {
-+ HReg dst = newVRegI(env);
-+ HReg src = iselV128Expr(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VPICKVE2GR_D,
-+ LOONGARCH64RI_I(1, 1, False), src, dst));
-+ return dst;
-+ }
-+ case Iop_V256to64_0: case Iop_V256to64_1:
-+ case Iop_V256to64_2: case Iop_V256to64_3: {
-+ UShort id;
-+ HReg vHi, vLo, vec;
-+ iselV256Expr(&vHi, &vLo, env, e->Iex.Unop.arg);
-+ switch (e->Iex.Unop.op) {
-+ case Iop_V256to64_0: vec = vLo; id = 0; break;
-+ case Iop_V256to64_1: vec = vLo; id = 1; break;
-+ case Iop_V256to64_2: vec = vHi; id = 0; break;
-+ case Iop_V256to64_3: vec = vHi; id = 1; break;
-+ default: vassert(0); break;
-+ }
-+ HReg dst = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VPICKVE2GR_D,
-+ LOONGARCH64RI_I(id, 1, False), vec, dst));
-+ return dst;
-+ }
-+ default:
-+ goto irreducible;
-+ }
-+ }
++ LOONGARCH64RI* ri3 = LOONGARCH64RI_I(0x1, 12, False);
++ LOONGARCH64RI* ri4 = LOONGARCH64RI_R(tmp);
++ if (size64)
++ addInstr(env, LOONGARCH64Instr_FpCmp(LAfpcmp_FCMP_CLT_D, src2, src1, tmp));
++ else
++ addInstr(env, LOONGARCH64Instr_FpCmp(LAfpcmp_FCMP_CLT_S, src2, src1, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri1, tmp, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri1, tmp, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri3, tmp, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri4, dst, dst));
+
-+ /* --------- GET --------- */
-+ case Iex_Get: {
-+ Bool ri = e->Iex.Get.offset < 1024;
-+ HReg dst = newVRegI(env);
-+ HReg tmp;
-+ LOONGARCH64AMode* am;
-+ LOONGARCH64LoadOp op;
-+ switch (ty) {
-+ case Ity_I8:
-+ op = ri ? LAload_LD_BU : LAload_LDX_BU;
-+ break;
-+ case Ity_I16:
-+ op = ri ? LAload_LD_HU : LAload_LDX_HU;
-+ break;
-+ case Ity_I32:
-+ op = ri ? LAload_LD_WU : LAload_LDX_WU;
-+ break;
-+ case Ity_I64:
-+ op = ri ? LAload_LD_D : LAload_LDX_D;
-+ break;
-+ default:
-+ goto irreducible;
-+ }
-+ if (ri) {
-+ am = LOONGARCH64AMode_RI(hregGSP(), e->Iex.Get.offset);
-+ } else {
-+ tmp = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_LI(e->Iex.Get.offset, tmp));
-+ am = LOONGARCH64AMode_RR(hregGSP(), tmp);
-+ }
-+ addInstr(env, LOONGARCH64Instr_Load(op, am, dst));
-+ return dst;
-+ }
++ LOONGARCH64RI* ri5 = LOONGARCH64RI_I(0x40, 12, False);
++ if (size64)
++ addInstr(env, LOONGARCH64Instr_FpCmp(LAfpcmp_FCMP_CEQ_D, src2, src1, tmp));
++ else
++ addInstr(env, LOONGARCH64Instr_FpCmp(LAfpcmp_FCMP_CEQ_S, src2, src1, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri1, tmp, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri1, tmp, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri5, tmp, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri4, dst, dst));
++
++ return dst;
++}
++
++
++/*---------------------------------------------------------*/
++/*--- ISEL: Function call helpers ---*/
++/*---------------------------------------------------------*/
++
++/* Used only in doHelperCall. See big comment in doHelperCall re
++ handling of register-parameter args. This function figures out
++ whether evaluation of an expression might require use of a fixed
++ register. If in doubt return True (safe but suboptimal).
++*/
++static Bool mightRequireFixedRegs ( IRExpr* e )
++{
++ if (UNLIKELY(is_IRExpr_VECRET_or_GSPTR(e))) {
++ // These are always "safe" -- either a copy of SP in some
++ // arbitrary vreg, or a copy of $r31, respectively.
++ return False;
++ }
++ /* Else it's a "normal" expression. */
++ switch (e->tag) {
++ case Iex_RdTmp: case Iex_Const: case Iex_Get:
++ return False;
++ default:
++ return True;
++ }
++}
++
++/* Do a complete function call. |guard| is a Ity_Bit expression
++ indicating whether or not the call happens. If guard==NULL, the
++ call is unconditional. |retloc| is set to indicate where the
++ return value is after the call. The caller (of this fn) must
++ generate code to add |stackAdjustAfterCall| to the stack pointer
++ after the call is done. Returns True iff it managed to handle this
++ combination of arg/return types, else returns False. */
++static Bool doHelperCall( /*OUT*/UInt* stackAdjustAfterCall,
++ /*OUT*/RetLoc* retloc,
++ ISelEnv* env,
++ IRExpr* guard,
++ IRCallee* cee, IRType retTy, IRExpr** args )
++{
++ HReg cond;
++ HReg argregs[LOONGARCH64_N_ARGREGS];
++ HReg tmpregs[LOONGARCH64_N_ARGREGS];
++ Bool go_fast;
++ Int n_args, i, nextArgReg;
++ Addr64 target;
+
-+ /* --------- CCALL --------- */
-+ case Iex_CCall: {
-+ HReg dst = newVRegI(env);
-+ vassert(ty == e->Iex.CCall.retty);
++ vassert(LOONGARCH64_N_ARGREGS == 8);
+
-+ /* be very restrictive for now. Only 64-bit ints allowed for
-+ args, and 64 bits for return type. Don't forget to change
-+ the RetLoc if more types are allowed in future. */
-+ if (e->Iex.CCall.retty != Ity_I64)
-+ goto irreducible;
++ /* Set default returns. We'll update them later if needed. */
++ *stackAdjustAfterCall = 0;
++ *retloc = mk_RetLoc_INVALID();
+
-+ /* Marshal args, do the call, clear stack. */
-+ UInt addToSp = 0;
-+ RetLoc rloc = mk_RetLoc_INVALID();
-+ Bool ok = doHelperCall(&addToSp, &rloc, env, NULL,
-+ e->Iex.CCall.cee, e->Iex.CCall.retty,
-+ e->Iex.CCall.args);
++ /* These are used for cross-checking that IR-level constraints on
++ the use of IRExpr_VECRET() and IRExpr_GSPTR() are observed. */
++ UInt nVECRETs = 0;
++ UInt nGSPTRs = 0;
+
-+ if (ok) {
-+ vassert(is_sane_RetLoc(rloc));
-+ vassert(rloc.pri == RLPri_Int);
-+ vassert(addToSp == 0);
-+ addInstr(env, LOONGARCH64Instr_Move(dst, hregLOONGARCH64_R4()));
-+ return dst;
-+ }
-+ goto irreducible;
-+ }
++ /* Marshal args for a call and do the call.
+
-+ /* --------- LITERAL --------- */
-+ /* 64-bit literals */
-+ case Iex_Const: {
-+ ULong imm = 0;
-+ HReg dst = newVRegI(env);
-+ switch (e->Iex.Const.con->tag) {
-+ case Ico_U64:
-+ imm = e->Iex.Const.con->Ico.U64;
-+ break;
-+ case Ico_U32:
-+ imm = e->Iex.Const.con->Ico.U32;
-+ break;
-+ case Ico_U16:
-+ imm = e->Iex.Const.con->Ico.U16;
-+ break;
-+ case Ico_U8:
-+ imm = e->Iex.Const.con->Ico.U8;
-+ break;
-+ default:
-+ ppIRExpr(e);
-+ vpanic("iselIntExpr_R.Iex_Const(loongarch64)");
-+ }
-+ addInstr(env, LOONGARCH64Instr_LI(imm, dst));
-+ return dst;
-+ }
++ This function only deals with a tiny set of possibilities, which
++ cover all helpers in practice. The restrictions are that only
++ arguments in registers are supported, hence only
++ LOONGARCH64_N_ARGREGS x 64 integer bits in total can be passed.
++ In fact the only supported arg type is I64.
+
-+ case Iex_ITE: {
-+ HReg r0 = iselIntExpr_R(env, e->Iex.ITE.iffalse);
-+ HReg r1 = iselIntExpr_R(env, e->Iex.ITE.iftrue);
-+ HReg cond = iselCondCode_R(env, e->Iex.ITE.cond);
-+ HReg dst = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_CMove(cond, r0, r1, dst, True));
-+ return dst;
-+ }
++ The return type can be I{64,32} or V{128,256}. In the latter two
++ cases, it is expected that |args| will contain the special node
++ IRExpr_VECRET(), in which case this routine generates code to
++ allocate space on the stack for the vector return value. Since
++ we are not passing any scalars on the stack, it is enough to
++ preallocate the return space before marshalling any arguments,
++ in this case.
+
-+ default:
-+ break;
-+ }
++ |args| may also contain IRExpr_GSPTR(), in which case the
++ value in $r31 is passed as the corresponding argument.
+
-+ /* We get here if no pattern matched. */
-+irreducible:
-+ ppIRExpr(e);
-+ vpanic("iselIntExpr_R(loongarch64): cannot reduce tree");
-+}
++ Generating code which is both efficient and correct when
++ parameters are to be passed in registers is difficult, for the
++ reasons elaborated in detail in comments attached to
++ doHelperCall() in priv/host_x86_isel.c. Here, we use a variant
++ of the method described in those comments.
+
-+/* ------------------- CondCode ------------------- */
++ The problem is split into two cases: the fast scheme and the
++ slow scheme. In the fast scheme, arguments are computed
++ directly into the target (real) registers. This is only safe
++ when we can be sure that computation of each argument will not
++ trash any real registers set by computation of any other
++ argument.
+
-+/* Generate code to evaluated a bit-typed expression, returning the
-+ condition code which would correspond when the expression would
-+ notionally have returned 1. */
++ In the slow scheme, all args are first computed into vregs, and
++ once they are all done, they are moved to the relevant real
++ regs. This always gives correct code, but it also gives a bunch
++ of vreg-to-rreg moves which are usually redundant but are hard
++ for the register allocator to get rid of.
+
-+static HReg iselCondCode_R ( ISelEnv* env, IRExpr* e )
-+{
-+ HReg r = iselCondCode_R_wrk(env, e);
++ To decide which scheme to use, all argument expressions are
++ first examined. If they are all so simple that it is clear they
++ will be evaluated without use of any fixed registers, use the
++ fast scheme, else use the slow scheme. Note also that only
++ unconditional calls may use the fast scheme, since having to
++ compute a condition expression could itself trash real
++ registers.
+
-+ /* sanity checks ... */
-+ vassert(hregClass(r) == HRcInt64);
-+ vassert(hregIsVirtual(r));
++ Note this requires being able to examine an expression and
++ determine whether or not evaluation of it might use a fixed
++ register. That requires knowledge of how the rest of this insn
++ selector works. Currently just the following 3 are regarded as
++ safe -- hopefully they cover the majority of arguments in
++ practice: IRExpr_Tmp IRExpr_Const IRExpr_Get.
++ */
+
-+ return r;
-+}
++ /* LOONGARCH64 calling convention: up to eight registers ($a0 ... $a7)
++ are allowed to be used for passing integer arguments. They correspond
++ to regs $r4 ... $r11. Note that the cee->regparms field is meaningless
++ on LOONGARCH64 host (since we only implement one calling convention)
++ and so we always ignore it. */
+
-+/* DO NOT CALL THIS DIRECTLY ! */
-+static HReg iselCondCode_R_wrk ( ISelEnv* env, IRExpr* e )
-+{
-+ vassert(e);
-+ vassert(typeOfIRExpr(env->type_env, e) == Ity_I1);
++ n_args = 0;
++ for (i = 0; args[i]; i++) {
++ IRExpr* arg = args[i];
++ if (UNLIKELY(arg->tag == Iex_VECRET)) {
++ nVECRETs++;
++ } else if (UNLIKELY(arg->tag == Iex_GSPTR)) {
++ nGSPTRs++;
++ }
++ n_args++;
++ }
+
-+ HReg dst = newVRegI(env);
++ /* If this fails, the IR is ill-formed */
++ vassert(nGSPTRs == 0 || nGSPTRs == 1);
+
-+ /* var */
-+ if (e->tag == Iex_RdTmp) {
-+ HReg tmp = newVRegI(env);
-+ dst = lookupIRTemp(env, e->Iex.RdTmp.tmp);
-+ addInstr(env, LOONGARCH64Instr_LI(1, tmp));
-+ addInstr(env, LOONGARCH64Instr_Cmp(LAcc_EQ, dst, tmp, dst));
-+ return dst;
++ /* If we have a VECRET, allocate space on the stack for the return
++ value, and record the stack pointer after that. */
++ HReg r_vecRetAddr = INVALID_HREG;
++ LOONGARCH64RI* ri;
++ if (nVECRETs == 1) {
++ vassert(retTy == Ity_V128 || retTy == Ity_V256);
++ r_vecRetAddr = newVRegI(env);
++ if (retTy == Ity_V128)
++ ri = LOONGARCH64RI_I(-16 & 0xfff, 12, True);
++ else // retTy == Ity_V256
++ ri = LOONGARCH64RI_I(-32 & 0xfff, 12, True);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D, ri, hregSP(), hregSP()));
++ addInstr(env, LOONGARCH64Instr_Move(r_vecRetAddr, hregSP()));
++ } else {
++ // If either of these fail, the IR is ill-formed
++ vassert(retTy != Ity_V128 && retTy != Ity_V256);
++ vassert(nVECRETs == 0);
+ }
+
-+ /* const */
-+ if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U1) {
-+ UInt imm = e->Iex.Const.con->Ico.U1;
-+ addInstr(env, LOONGARCH64Instr_LI(imm, dst));
-+ return dst;
++ if (n_args > LOONGARCH64_N_ARGREGS) {
++ vpanic("doHelperCall(loongarch64): cannot currently handle > 8 args");
+ }
+
-+ if (e->tag == Iex_Unop) {
-+ if (e->Iex.Unop.op == Iop_Not1) {
-+ HReg src = iselCondCode_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_R(hregZERO());
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_NOR, ri, src, dst));
-+ return dst;
-+ }
++ argregs[0] = hregLOONGARCH64_R4();
++ argregs[1] = hregLOONGARCH64_R5();
++ argregs[2] = hregLOONGARCH64_R6();
++ argregs[3] = hregLOONGARCH64_R7();
++ argregs[4] = hregLOONGARCH64_R8();
++ argregs[5] = hregLOONGARCH64_R9();
++ argregs[6] = hregLOONGARCH64_R10();
++ argregs[7] = hregLOONGARCH64_R11();
+
-+ LOONGARCH64CondCode cc;
-+ switch (e->Iex.Unop.op) {
-+ case Iop_CmpNEZ16:
-+ cc = LAcc_NE;
-+ break;
-+ case Iop_CmpNEZ32:
-+ cc = LAcc_NE;
-+ break;
-+ case Iop_CmpNEZ64:
-+ cc = LAcc_NE;
-+ break;
-+ case Iop_CmpNEZ8:
-+ cc = LAcc_NE;
-+ break;
-+ default:
-+ goto irreducible;
-+ }
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_Cmp(cc, hregZERO(), src, dst));
-+ return dst;
-+ }
++ tmpregs[0] = tmpregs[1] = tmpregs[2] = tmpregs[3] = INVALID_HREG;
++ tmpregs[4] = tmpregs[5] = tmpregs[6] = tmpregs[7] = INVALID_HREG;
+
-+ if (e->tag == Iex_Binop) {
-+ if (e->Iex.Binop.op == Iop_And1) {
-+ HReg src1 = iselCondCode_R(env, e->Iex.Binop.arg1);
-+ HReg src2 = iselCondCode_R(env, e->Iex.Binop.arg2);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_R(src2);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_AND, ri, src1, dst));
-+ return dst;
-+ } else if (e->Iex.Binop.op == Iop_Or1) {
-+ HReg src1 = iselCondCode_R(env, e->Iex.Binop.arg1);
-+ HReg src2 = iselCondCode_R(env, e->Iex.Binop.arg2);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_R(src2);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri, src1, dst));
-+ return dst;
++ /* First decide which scheme (slow or fast) is to be used. First assume the
++ fast scheme, and select slow if any contraindications (wow) appear. */
++
++ go_fast = True;
++
++ if (guard) {
++ if (guard->tag == Iex_Const
++ && guard->Iex.Const.con->tag == Ico_U1
++ && guard->Iex.Const.con->Ico.U1 == True) {
++ /* unconditional */
++ } else {
++ /* Not manifestly unconditional -- be conservative. */
++ go_fast = False;
+ }
++ }
+
-+ Bool extend = False;
-+ Bool reverse = False;
-+ LOONGARCH64CondCode cc;
-+ switch (e->Iex.Binop.op) {
-+ case Iop_CasCmpEQ32:
-+ cc = LAcc_EQ;
-+ break;
-+ case Iop_CasCmpEQ64:
-+ cc = LAcc_EQ;
-+ break;
-+ case Iop_CasCmpNE32:
-+ cc = LAcc_NE;
-+ break;
-+ case Iop_CasCmpNE64:
-+ cc = LAcc_NE;
-+ break;
-+ case Iop_CmpEQ32:
-+ cc = LAcc_EQ;
-+ break;
-+ case Iop_CmpEQ64:
-+ cc = LAcc_EQ;
-+ break;
-+ case Iop_CmpLE32S:
-+ cc = LAcc_GE;
-+ reverse = True;
-+ break;
-+ case Iop_CmpLE32U:
-+ cc = LAcc_GEU;
-+ reverse = True;
-+ break;
-+ case Iop_CmpLE64S:
-+ cc = LAcc_GE;
-+ reverse = True;
-+ break;
-+ case Iop_CmpLE64U:
-+ cc = LAcc_GEU;
-+ reverse = True;
-+ break;
-+ case Iop_CmpLT32S:
-+ cc = LAcc_LT;
-+ extend = True;
-+ break;
-+ case Iop_CmpLT32U:
-+ cc = LAcc_LTU;
-+ extend = True;
-+ break;
-+ case Iop_CmpLT64S:
-+ cc = LAcc_LT;
-+ break;
-+ case Iop_CmpLT64U:
-+ cc = LAcc_LTU;
-+ break;
-+ case Iop_CmpNE32:
-+ cc = LAcc_NE;
-+ break;
-+ case Iop_CmpNE64:
-+ cc = LAcc_NE;
++ if (go_fast) {
++ for (i = 0; i < n_args; i++) {
++ if (mightRequireFixedRegs(args[i])) {
++ go_fast = False;
+ break;
-+ default:
-+ goto irreducible;
-+ }
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2);
-+ if (extend) {
-+ /* Sign-extend */
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(0, 5, False);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri, src1, src1));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri, src2, src2));
-+ }
-+ if (reverse) {
-+ addInstr(env, LOONGARCH64Instr_Cmp(cc, src1, src2, dst));
-+ } else {
-+ addInstr(env, LOONGARCH64Instr_Cmp(cc, src2, src1, dst));
++ }
+ }
-+ return dst;
+ }
+
-+ /* We get here if no pattern matched. */
-+irreducible:
-+ ppIRExpr(e);
-+ vpanic("iselCondCode(loongarch64): cannot reduce tree");
-+}
++ if (go_fast) {
++ if (retTy == Ity_V128 || retTy == Ity_V256)
++ go_fast = False;
++ }
+
++ /* At this point the scheme to use has been established. Generate
++ code to get the arg values into the argument rregs. If we run
++ out of arg regs, give up. */
+
-+/*---------------------------------------------------------*/
-+/*--- ISEL: Integer expressions (128 bit) ---*/
-+/*---------------------------------------------------------*/
++ if (go_fast) {
++ /* FAST SCHEME */
++ nextArgReg = 0;
+
-+/* Compute a 128-bit value into a register pair, which is returned as
-+ the first two parameters. As with iselIntExpr_R, these may be
-+ either real or virtual regs; in any case they must not be changed
-+ by subsequent code emitted by the caller. */
++ for (i = 0; i < n_args; i++) {
++ IRExpr* arg = args[i];
+
-+static void iselInt128Expr (HReg* hi, HReg* lo, ISelEnv* env, IRExpr* e)
-+{
-+ iselInt128Expr_wrk(hi, lo, env, e);
++ IRType aTy = Ity_INVALID;
++ if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg)))
++ aTy = typeOfIRExpr(env->type_env, args[i]);
+
-+ /* sanity checks ... */
-+ vassert(hregClass(*hi) == HRcInt64);
-+ vassert(hregIsVirtual(*hi));
-+ vassert(hregClass(*lo) == HRcInt64);
-+ vassert(hregIsVirtual(*lo));
-+}
++ if (nextArgReg >= LOONGARCH64_N_ARGREGS)
++ return False; /* out of argregs */
+
-+/* DO NOT CALL THIS DIRECTLY ! */
-+static void iselInt128Expr_wrk (HReg* hi, HReg* lo, ISelEnv* env, IRExpr* e)
-+{
-+ vassert(e);
-+ vassert(typeOfIRExpr(env->type_env, e) == Ity_I128);
++ if (aTy == Ity_I64) {
++ addInstr(env, LOONGARCH64Instr_Move(argregs[nextArgReg],
++ iselIntExpr_R(env, args[i])));
++ nextArgReg++;
++ } else if (arg->tag == Iex_GSPTR) {
++ addInstr(env, LOONGARCH64Instr_Move(argregs[nextArgReg], hregGSP()));
++ nextArgReg++;
++ } else if (arg->tag == Iex_VECRET) {
++ // because of the go_fast logic above, we can't get here,
++ // since vector return values makes us use the slow path
++ // instead.
++ vassert(0);
++ } else
++ return False; /* unhandled arg type */
++ }
+
-+ /* --------- TEMP --------- */
-+ if (e->tag == Iex_RdTmp) {
-+ lookupIRTempPair(hi, lo, env, e->Iex.RdTmp.tmp);
-+ return;
-+ }
++ /* Fast scheme only applies for unconditional calls. Hence: */
++ cond = INVALID_HREG;
++ } else {
++ /* SLOW SCHEME; move via temporaries */
++ nextArgReg = 0;
+
-+ /* --------- BINARY OP --------- */
-+ if (e->tag == Iex_Binop) {
-+ switch (e->Iex.Binop.op) {
-+ case Iop_64HLto128: {
-+ *hi = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ *lo = iselIntExpr_R(env, e->Iex.Binop.arg2);
-+ return;
-+ }
-+ case Iop_DivModS64to64: {
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
-+ HReg dstLo = newVRegI(env);
-+ HReg dstHi = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_D, src2, src1, dstLo));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MOD_D, src2, src1, dstHi));
-+ *hi = dstHi;
-+ *lo = dstLo;
-+ return;
-+ }
-+ case Iop_DivModU64to64: {
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
-+ HReg dstLo = newVRegI(env);
-+ HReg dstHi = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_DU, src2, src1, dstLo));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MOD_DU, src2, src1, dstHi));
-+ *hi = dstHi;
-+ *lo = dstLo;
-+ return;
-+ }
-+ case Iop_MullS64: {
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
-+ HReg dstLo = newVRegI(env);
-+ HReg dstHi = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MUL_D, src2, src1, dstLo));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MULH_D, src2, src1, dstHi));
-+ *hi = dstHi;
-+ *lo = dstLo;
-+ return;
-+ }
-+ case Iop_MullU64: {
-+ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
-+ HReg dstLo = newVRegI(env);
-+ HReg dstHi = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MUL_D, src2, src1, dstLo));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MULH_DU, src2, src1, dstHi));
-+ *hi = dstHi;
-+ *lo = dstLo;
-+ return;
++ for (i = 0; i < n_args; i++) {
++ IRExpr* arg = args[i];
++
++ IRType aTy = Ity_INVALID;
++ if (LIKELY(!is_IRExpr_VECRET_or_GSPTR(arg)))
++ aTy = typeOfIRExpr(env->type_env, args[i]);
++
++ if (nextArgReg >= LOONGARCH64_N_ARGREGS)
++ return False; /* out of argregs */
++
++ if (aTy == Ity_I64) {
++ tmpregs[nextArgReg] = iselIntExpr_R(env, args[i]);
++ nextArgReg++;
++ } else if (arg->tag == Iex_GSPTR) {
++ tmpregs[nextArgReg] = hregGSP();
++ nextArgReg++;
++ } else if (arg->tag == Iex_VECRET) {
++ vassert(!hregIsInvalid(r_vecRetAddr));
++ tmpregs[nextArgReg] = r_vecRetAddr;
++ nextArgReg++;
++ } else
++ return False; /* unhandled arg type */
++ }
++
++ /* Now we can compute the condition. We can't do it earlier
++ because the argument computations could trash the condition
++ codes. Be a bit clever to handle the common case where the
++ guard is 1:Bit. */
++ cond = INVALID_HREG;
++ if (guard) {
++ if (guard->tag == Iex_Const
++ && guard->Iex.Const.con->tag == Ico_U1
++ && guard->Iex.Const.con->Ico.U1 == True) {
++ /* unconditional -- do nothing */
++ } else {
++ cond = iselCondCode_R(env, guard);
+ }
-+ default:
-+ goto irreducible;
+ }
++
++ /* Move the args to their final destinations. */
++ for (i = 0; i < nextArgReg; i++) {
++ vassert(!(hregIsInvalid(tmpregs[i])));
++ /* None of these insns, including any spill code that might
++ be generated, may alter the condition codes. */
++ addInstr(env, LOONGARCH64Instr_Move(argregs[i], tmpregs[i]));
++ }
++ }
++
++ /* Should be assured by checks above */
++ vassert(nextArgReg <= LOONGARCH64_N_ARGREGS);
++
++ /* Do final checks, set the return values, and generate the call
++ instruction proper. */
++ vassert(nGSPTRs == 0 || nGSPTRs == 1);
++ vassert(nVECRETs == ((retTy == Ity_V128 || retTy == Ity_V256) ? 1 : 0));
++ vassert(*stackAdjustAfterCall == 0);
++ vassert(is_RetLoc_INVALID(*retloc));
++ switch (retTy) {
++ case Ity_INVALID:
++ /* Function doesn't return a value. */
++ *retloc = mk_RetLoc_simple(RLPri_None);
++ break;
++ case Ity_I8: case Ity_I16: case Ity_I32: case Ity_I64:
++ *retloc = mk_RetLoc_simple(RLPri_Int);
++ break;
++ case Ity_V128:
++ *retloc = mk_RetLoc_spRel(RLPri_V128SpRel, 0);
++ *stackAdjustAfterCall = 16;
++ break;
++ case Ity_V256:
++ *retloc = mk_RetLoc_spRel(RLPri_V256SpRel, 0);
++ *stackAdjustAfterCall = 32;
++ break;
++ default:
++ /* IR can denote other possible return types, but we don't
++ handle those here. */
++ vassert(0);
++ break;
+ }
+
-+ /* We get here if no pattern matched. */
-+irreducible:
-+ ppIRExpr(e);
-+ vpanic("iselInt128Expr(loongarch64): cannot reduce tree");
++ /* Finally, generate the call itself. This needs the *retloc value
++ set in the switch above, which is why it's at the end. */
++
++ /* nextArgReg doles out argument registers. Since these are
++ assigned in the order $a0 .. $a7, its numeric value at this point,
++ which must be between 0 and 8 inclusive, is going to be equal to
++ the number of arg regs in use for the call. Hence bake that
++ number into the call (we'll need to know it when doing register
++ allocation, to know what regs the call reads.) */
++
++ target = (Addr)cee->addr;
++ addInstr(env, LOONGARCH64Instr_Call(cond, target, nextArgReg, *retloc));
++
++ return True; /* success */
+}
+
+
+/*---------------------------------------------------------*/
-+/*--- ISEL: Floating point expressions (64/32 bit) ---*/
++/*--- ISEL: Integer expressions (64/32/16/8 bit) ---*/
+/*---------------------------------------------------------*/
+
-+/* Compute a floating point value into a register, the identity of
-+ which is returned. As with iselIntExpr_R, the reg may be either
-+ real or virtual; in any case it must not be changed by subsequent
-+ code emitted by the caller. */
++/* Select insns for an integer-typed expression, and add them to the
++ code list. Return a reg holding the result. This reg will be a
++ virtual register. THE RETURNED REG MUST NOT BE MODIFIED. If you
++ want to modify it, ask for a new vreg, copy it in there, and modify
++ the copy. The register allocator will do its best to map both
++ vregs to the same real register, so the copies will often disappear
++ later in the game.
+
-+static HReg iselFltExpr ( ISelEnv* env, IRExpr* e )
++ This should handle expressions of 64, 32, 16 and 8-bit type.
++ All results are returned in a (mode64 ? 64bit : 32bit) register.
++ For 16- and 8-bit expressions, the upper (32/48/56 : 16/24) bits
++ are arbitrary, so you should mask or sign extend partial values
++ if necessary.
++*/
++
++/* --------------------- AMode --------------------- */
++
++static LOONGARCH64AMode* iselIntExpr_AMode ( ISelEnv* env,
++ IRExpr* e, IRType dty )
+{
-+ HReg r = iselFltExpr_wrk(env, e);
++ LOONGARCH64AMode* am = iselIntExpr_AMode_wrk(env, e, dty);
+
+ /* sanity checks ... */
-+ vassert(hregClass(r) == HRcFlt64);
-+ vassert(hregIsVirtual(r));
++ switch (am->tag) {
++ case LAam_RI:
++ vassert(am->LAam.RI.index < (1 << 12));
++ vassert(hregClass(am->LAam.RI.base) == HRcInt64);
++ vassert(hregIsVirtual(am->LAam.RI.base));
++ break;
++ case LAam_RR:
++ vassert(hregClass(am->LAam.RR.base) == HRcInt64);
++ vassert(hregIsVirtual(am->LAam.RR.base));
++ vassert(hregClass(am->LAam.RR.index) == HRcInt64);
++ vassert(hregIsVirtual(am->LAam.RR.index));
++ break;
++ default:
++ vpanic("iselIntExpr_AMode: unknown LOONGARCH64 AMode tag");
++ break;
++ }
+
-+ return r;
++ return am;
+}
+
-+/* DO NOT CALL THIS DIRECTLY */
-+static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
++/* DO NOT CALL THIS DIRECTLY ! */
++static LOONGARCH64AMode* iselIntExpr_AMode_wrk ( ISelEnv* env,
++ IRExpr* e, IRType dty )
+{
+ IRType ty = typeOfIRExpr(env->type_env, e);
+ vassert(e);
-+ vassert(ty == Ity_F32 || ty == Ity_F64);
-+
-+ switch (e->tag) {
-+ /* --------- TEMP --------- */
-+ case Iex_RdTmp:
-+ return lookupIRTemp(env, e->Iex.RdTmp.tmp);
-+
-+ /* --------- LOAD --------- */
-+ case Iex_Load: {
-+ if (e->Iex.Load.end != Iend_LE)
-+ goto irreducible;
-+
-+ LOONGARCH64AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr, ty);
-+ HReg dst = newVRegF(env);
-+ LOONGARCH64FpLoadOp op;
-+ switch (ty) {
-+ case Ity_F32:
-+ op = (am->tag == LAam_RI) ? LAfpload_FLD_S : LAfpload_FLDX_S;
-+ break;
-+ case Ity_F64:
-+ op = (am->tag == LAam_RI) ? LAfpload_FLD_D : LAfpload_FLDX_D;
-+ break;
-+ default:
-+ goto irreducible;
-+ }
-+ addInstr(env, LOONGARCH64Instr_FpLoad(op, am, dst));
-+ return dst;
-+ }
-+
-+ /* --------- GET --------- */
-+ case Iex_Get: {
-+ Bool ri = e->Iex.Get.offset < 1024;
-+ HReg dst = newVRegF(env);
-+ HReg tmp;
-+ LOONGARCH64AMode* am;
-+ LOONGARCH64FpLoadOp op;
-+ switch (ty) {
-+ case Ity_F32:
-+ op = ri ? LAfpload_FLD_S : LAfpload_FLDX_S;
-+ break;
-+ case Ity_F64:
-+ op = ri ? LAfpload_FLD_D : LAfpload_FLDX_D;
-+ break;
-+ default:
-+ goto irreducible;
-+ }
-+ if (ri) {
-+ am = LOONGARCH64AMode_RI(hregGSP(), e->Iex.Get.offset);
-+ } else {
-+ tmp = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_LI(e->Iex.Get.offset, tmp));
-+ am = LOONGARCH64AMode_RR(hregGSP(), tmp);
-+ }
-+ addInstr(env, LOONGARCH64Instr_FpLoad(op, am, dst));
-+ return dst;
-+ }
-+
-+ /* --------- QUATERNARY OP --------- */
-+ case Iex_Qop: {
-+ switch (e->Iex.Qop.details->op) {
-+ case Iop_MAddF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src1 = iselFltExpr(env, e->Iex.Qop.details->arg2);
-+ HReg src2 = iselFltExpr(env, e->Iex.Qop.details->arg3);
-+ HReg src3 = iselFltExpr(env, e->Iex.Qop.details->arg4);
-+ set_rounding_mode(env, e->Iex.Qop.details->arg1);
-+ addInstr(env, LOONGARCH64Instr_FpTrinary(LAfpbin_FMADD_S, src3, src2, src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_MAddF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src1 = iselFltExpr(env, e->Iex.Qop.details->arg2);
-+ HReg src2 = iselFltExpr(env, e->Iex.Qop.details->arg3);
-+ HReg src3 = iselFltExpr(env, e->Iex.Qop.details->arg4);
-+ set_rounding_mode(env, e->Iex.Qop.details->arg1);
-+ addInstr(env, LOONGARCH64Instr_FpTrinary(LAfpbin_FMADD_D, src3, src2, src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_MSubF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src1 = iselFltExpr(env, e->Iex.Qop.details->arg2);
-+ HReg src2 = iselFltExpr(env, e->Iex.Qop.details->arg3);
-+ HReg src3 = iselFltExpr(env, e->Iex.Qop.details->arg4);
-+ set_rounding_mode(env, e->Iex.Qop.details->arg1);
-+ addInstr(env, LOONGARCH64Instr_FpTrinary(LAfpbin_FMSUB_S, src3, src2, src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_MSubF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src1 = iselFltExpr(env, e->Iex.Qop.details->arg2);
-+ HReg src2 = iselFltExpr(env, e->Iex.Qop.details->arg3);
-+ HReg src3 = iselFltExpr(env, e->Iex.Qop.details->arg4);
-+ set_rounding_mode(env, e->Iex.Qop.details->arg1);
-+ addInstr(env, LOONGARCH64Instr_FpTrinary(LAfpbin_FMSUB_D, src3, src2, src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ default:
-+ goto irreducible;
-+ }
-+ }
-+
-+ /* --------- TERNARY OP --------- */
-+ case Iex_Triop: {
-+ switch (e->Iex.Triop.details->op) {
-+ case Iop_AddF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
-+ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
-+ set_rounding_mode(env, e->Iex.Triop.details->arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FADD_S, src2, src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_AddF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
-+ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
-+ set_rounding_mode(env, e->Iex.Triop.details->arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FADD_D, src2, src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_DivF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
-+ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
-+ set_rounding_mode(env, e->Iex.Triop.details->arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FDIV_S, src2, src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_DivF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
-+ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
-+ set_rounding_mode(env, e->Iex.Triop.details->arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FDIV_D, src2, src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_MulF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
-+ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
-+ set_rounding_mode(env, e->Iex.Triop.details->arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMUL_S, src2, src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_MulF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
-+ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
-+ set_rounding_mode(env, e->Iex.Triop.details->arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMUL_D, src2, src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_ScaleBF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
-+ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
-+ set_rounding_mode(env, e->Iex.Triop.details->arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FSCALEB_S, src2, src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_ScaleBF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
-+ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
-+ set_rounding_mode(env, e->Iex.Triop.details->arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FSCALEB_D, src2, src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_SubF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
-+ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
-+ set_rounding_mode(env, e->Iex.Triop.details->arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FSUB_S, src2, src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_SubF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
-+ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
-+ set_rounding_mode(env, e->Iex.Triop.details->arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FSUB_D, src2, src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ default:
-+ goto irreducible;
-+ }
-+ }
-+
-+ /* --------- BINARY OP --------- */
-+ case Iex_Binop: {
-+ switch (e->Iex.Binop.op) {
-+ case Iop_F64toF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FCVT_S_D, src, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_I32StoF32: {
-+ HReg tmp = newVRegF(env);
-+ HReg dst = newVRegF(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Binop.arg2);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_D, src, tmp));
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FFINT_S_W, tmp, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_I64StoF32: {
-+ HReg tmp = newVRegF(env);
-+ HReg dst = newVRegF(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Binop.arg2);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_D, src, tmp));
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FFINT_S_L, tmp, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_I64StoF64: {
-+ HReg tmp = newVRegF(env);
-+ HReg dst = newVRegF(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Binop.arg2);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_D, src, tmp));
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FFINT_D_L, tmp, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_LogBF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FLOGB_S, src, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_LogBF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FLOGB_D, src, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_MaxNumAbsF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
-+ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMAXA_S, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_MaxNumF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
-+ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMAX_S, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_MaxNumAbsF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
-+ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMAXA_D, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_MaxNumF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
-+ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMAX_D, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_MinNumAbsF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
-+ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMINA_S, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_MinNumF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
-+ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMIN_S, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_MinNumAbsF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
-+ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMINA_D, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_MinNumF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
-+ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMIN_D, src2, src1, dst));
-+ return dst;
-+ }
-+ case Iop_RoundF32toInt: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FRINT_S, src, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_RoundF64toInt: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FRINT_D, src, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_RSqrtF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FRSQRT_S, src, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_RSqrtF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FRSQRT_D, src, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_SqrtF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FSQRT_S, src, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ case Iop_SqrtF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
-+ set_rounding_mode(env, e->Iex.Binop.arg1);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FSQRT_D, src, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ default:
-+ goto irreducible;
-+ }
-+ }
++ vassert(ty == Ity_I64);
+
-+ /* --------- UNARY OP --------- */
-+ case Iex_Unop: {
-+ switch (e->Iex.Unop.op) {
-+ case Iop_AbsF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselFltExpr(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FABS_S, src, dst));
-+ return dst;
-+ }
-+ case Iop_AbsF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselFltExpr(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FABS_D, src, dst));
-+ return dst;
-+ }
-+ case Iop_F32toF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselFltExpr(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FCVT_D_S, src, dst));
-+ return dst;
-+ }
-+ case Iop_I32StoF64: {
-+ HReg tmp = newVRegF(env);
-+ HReg dst = newVRegF(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_D, src, tmp));
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FFINT_D_W, tmp, dst));
-+ return dst;
-+ }
-+ case Iop_NegF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselFltExpr(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FNEG_S, src, dst));
-+ return dst;
-+ }
-+ case Iop_NegF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselFltExpr(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FNEG_D, src, dst));
-+ return dst;
-+ }
-+ case Iop_ReinterpI32asF32: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_W, src, dst));
-+ return dst;
-+ }
-+ case Iop_ReinterpI64asF64: {
-+ HReg dst = newVRegF(env);
-+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_D, src, dst));
-+ return dst;
-+ }
-+ default:
-+ goto irreducible;
-+ }
-+ }
++ /* Add64(expr, i), where i <= 0x7ff */
++ if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add64
++ && e->Iex.Binop.arg2->tag == Iex_Const
++ && e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U64
++ && e->Iex.Binop.arg2->Iex.Const.con->Ico.U64 <= 0x7ff) {
++ return LOONGARCH64AMode_RI(iselIntExpr_R(env, e->Iex.Binop.arg1),
++ (UShort)e->Iex.Binop.arg2->Iex.Const.con->Ico.U64);
++ }
+
-+ /* --------- LITERAL --------- */
-+ case Iex_Const: {
-+ /* Just handle the one case. */
-+ IRConst* con = e->Iex.Const.con;
-+ if (con->tag == Ico_F32i && con->Ico.F32i == 1) {
-+ HReg tmp = newVRegI(env);
-+ HReg dst = newVRegF(env);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(1, 12, True);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_W, ri, hregZERO(), tmp));
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_W, tmp, dst));
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FFINT_S_W, dst, dst));
-+ return dst;
-+ } else if (con->tag == Ico_F64i && con->Ico.F64i == 1) {
-+ HReg tmp = newVRegI(env);
-+ HReg dst = newVRegF(env);
-+ LOONGARCH64RI* ri = LOONGARCH64RI_I(1, 12, True);
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D, ri, hregZERO(), tmp));
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_D, tmp, dst));
-+ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FFINT_D_L, dst, dst));
-+ return dst;
-+ } else {
-+ goto irreducible;
-+ }
-+ }
++ /* Add64(expr, expr) */
++ if (e->tag == Iex_Binop && e->Iex.Binop.op == Iop_Add64) {
++ HReg base = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ HReg index = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ return LOONGARCH64AMode_RR(base, index);
++ }
+
-+ case Iex_ITE: {
-+ HReg r0 = iselFltExpr(env, e->Iex.ITE.iffalse);
-+ HReg r1 = iselFltExpr(env, e->Iex.ITE.iftrue);
-+ HReg cond = iselCondCode_R(env, e->Iex.ITE.cond);
-+ HReg dst = newVRegF(env);
-+ addInstr(env, LOONGARCH64Instr_CMove(cond, r0, r1, dst, False));
-+ return dst;
-+ }
++ /* Doesn't match anything in particular. Generate it into
++ a register and use that. */
++ return LOONGARCH64AMode_RI(iselIntExpr_R(env, e), 0);
++}
+
++/* --------------------- RI --------------------- */
++
++static LOONGARCH64RI* iselIntExpr_RI ( ISelEnv* env, IRExpr* e,
++ UChar size, Bool isSigned )
++{
++ LOONGARCH64RI* ri = iselIntExpr_RI_wrk(env, e, size, isSigned);
++
++ /* sanity checks ... */
++ switch (ri->tag) {
++ case LAri_Imm:
++ switch (ri->LAri.I.size) {
++ case 0 ... 4:
++ case 6 ... 7:
++ vassert(ri->LAri.I.isSigned == False);
++ break;
++ case 9 ... 11:
++ vassert(ri->LAri.I.isSigned == True);
++ break;
++ case 5: case 8: case 12:
++ break;
++ default:
++ break;
++ vassert(0);
++ }
++ vassert(ri->LAri.I.imm < (1 << ri->LAri.I.size));
++ break;
++ case LAri_Reg:
++ vassert(hregClass(ri->LAri.R.reg) == HRcInt64);
++ vassert(hregIsVirtual(ri->LAri.R.reg));
++ break;
+ default:
++ vpanic("iselIntExpr_RI: unknown LOONGARCH64 RI tag");
+ break;
+ }
+
-+ /* We get here if no pattern matched. */
-+irreducible:
-+ ppIRExpr(e);
-+ vpanic("iselFltExpr(loongarch64): cannot reduce tree");
++ return ri;
+}
+
-+/*---------------------------------------------------------*/
-+/*--- ISEL: Vector expressions (128 bit) ---*/
-+/*---------------------------------------------------------*/
++/* DO NOT CALL THIS DIRECTLY ! */
++static LOONGARCH64RI* iselIntExpr_RI_wrk ( ISelEnv* env, IRExpr* e,
++ UChar size, Bool isSigned )
++{
++ IRType ty = typeOfIRExpr(env->type_env, e);
++ vassert(e);
++ vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
+
-+/* Compute a vector value into a register, the identity of
-+ which is returned. As with iselIntExpr_R, the reg may be either
-+ real or virtual; in any case it must not be changed by subsequent
-+ code emitted by the caller. */
++ LOONGARCH64RI *ri = NULL;
+
-+static HReg iselV128Expr ( ISelEnv* env, IRExpr* e )
++ /* special case: immediate */
++ if (e->tag == Iex_Const) {
++ switch (e->Iex.Const.con->tag) {
++ case Ico_U8:
++ if (!isSigned && e->Iex.Const.con->Ico.U8 < (1 << size)) {
++ UShort imm = e->Iex.Const.con->Ico.U8;
++ ri = LOONGARCH64RI_I(imm, size, isSigned);
++ }
++ break;
++ case Ico_U32:
++ if (!isSigned && e->Iex.Const.con->Ico.U32 < (1 << size)) {
++ UShort imm = e->Iex.Const.con->Ico.U32;
++ ri = LOONGARCH64RI_I(imm, size, isSigned);
++ }
++ break;
++ case Ico_U64:
++ if (!isSigned && e->Iex.Const.con->Ico.U64 < (1 << size)) {
++ UShort imm = e->Iex.Const.con->Ico.U64;
++ ri = LOONGARCH64RI_I(imm, size, isSigned);
++ }
++ break;
++ default:
++ break;
++ }
++ /* else fail, fall through to default case */
++ }
++
++ if (ri == NULL) {
++ /* default case: calculate into a register and return that */
++ HReg reg = iselIntExpr_R(env, e);
++ ri = LOONGARCH64RI_R(reg);
++ }
++
++ return ri;
++}
++
++/* --------------------- Reg --------------------- */
++
++static HReg iselIntExpr_R ( ISelEnv* env, IRExpr* e )
+{
-+ HReg r = iselV128Expr_wrk(env, e);
++ HReg r = iselIntExpr_R_wrk(env, e);
+
+ /* sanity checks ... */
-+ vassert(hregClass(r) == HRcVec128);
++ vassert(hregClass(r) == HRcInt64);
+ vassert(hregIsVirtual(r));
+
+ return r;
+}
+
-+/* DO NOT CALL THIS DIRECTLY */
-+static HReg iselV128Expr_wrk ( ISelEnv* env, IRExpr* e )
++/* DO NOT CALL THIS DIRECTLY ! */
++static HReg iselIntExpr_R_wrk ( ISelEnv* env, IRExpr* e )
+{
+ IRType ty = typeOfIRExpr(env->type_env, e);
+ vassert(e);
-+ vassert(ty == Ity_V128);
++ vassert(ty == Ity_I8 || ty == Ity_I16 || ty == Ity_I32 || ty == Ity_I64);
+
+ switch (e->tag) {
+ /* --------- TEMP --------- */
@@ -21551,261 +25675,394 @@ index 0000000..d60a2b3
+ if (e->Iex.Load.end != Iend_LE)
+ goto irreducible;
+
-+ HReg dst = newVRegV(env);
-+ LOONGARCH64AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr, ty);
-+ LOONGARCH64VecLoadOp op = (am->tag == LAam_RI) ? LAvecload_VLD : LAvecload_VLDX;
-+ addInstr(env, LOONGARCH64Instr_VecLoad(op, am, dst));
-+ return dst;
-+ }
-+
-+ /* --------- GET --------- */
-+ case Iex_Get: {
-+ Bool ri = e->Iex.Get.offset < 1024;
-+ HReg dst = newVRegV(env);
-+ HReg tmp;
-+ LOONGARCH64AMode* am;
-+ LOONGARCH64VecLoadOp op;
-+ if (ri) {
-+ op = LAvecload_VLD;
-+ am = LOONGARCH64AMode_RI(hregGSP(), e->Iex.Get.offset);
-+ } else {
-+ op = LAvecload_VLDX;
-+ tmp = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_LI(e->Iex.Get.offset, tmp));
-+ am = LOONGARCH64AMode_RR(hregGSP(), tmp);
++ LOONGARCH64AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr, ty);
++ HReg dst = newVRegI(env);
++ LOONGARCH64LoadOp op;
++ switch (ty) {
++ case Ity_I8:
++ op = (am->tag == LAam_RI) ? LAload_LD_BU : LAload_LDX_BU;
++ break;
++ case Ity_I16:
++ op = (am->tag == LAam_RI) ? LAload_LD_HU : LAload_LDX_HU;
++ break;
++ case Ity_I32:
++ op = (am->tag == LAam_RI) ? LAload_LD_WU : LAload_LDX_WU;
++ break;
++ case Ity_I64:
++ op = (am->tag == LAam_RI) ? LAload_LD_D : LAload_LDX_D;
++ break;
++ default:
++ goto irreducible;
+ }
-+ addInstr(env, LOONGARCH64Instr_VecLoad(op, am, dst));
++ addInstr(env, LOONGARCH64Instr_Load(op, am, dst));
+ return dst;
+ }
+
-+ /* --------- TERNARY OP --------- */
-+ case Iex_Triop: {
-+ IRTriop *triop = e->Iex.Triop.details;
-+ switch (triop->op) {
-+ case Iop_SetElem8x16: case Iop_SetElem16x8: case Iop_SetElem32x4: {
-+ LOONGARCH64VecBinOp op;
-+ UChar size;
-+ switch (triop->op) {
-+ case Iop_SetElem8x16: op = LAvecbin_VINSGR2VR_B; size = 4; break;
-+ case Iop_SetElem16x8: op = LAvecbin_VINSGR2VR_H; size = 3; break;
-+ case Iop_SetElem32x4: op = LAvecbin_VINSGR2VR_W; size = 2; break;
-+ default: vassert(0); break;
-+ }
-+ HReg dst = newVRegV(env);
-+ HReg src1 = iselV128Expr(env, triop->arg1);
-+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, triop->arg2, size, False);
-+ HReg src3 = iselIntExpr_R(env, triop->arg3);
-+ addInstr(env, LOONGARCH64Instr_VecMove(dst, src1));
-+ addInstr(env, LOONGARCH64Instr_VecBinary(op, src2, src3, dst));
-+ return dst;
-+ }
-+ case Iop_Add32Fx4: case Iop_Add64Fx2:
-+ case Iop_Sub32Fx4: case Iop_Sub64Fx2:
-+ case Iop_Mul32Fx4: case Iop_Mul64Fx2:
-+ case Iop_Div32Fx4: case Iop_Div64Fx2: {
-+ LOONGARCH64VecBinOp op;
-+ switch (triop->op) {
-+ case Iop_Add32Fx4: op = LAvecbin_VFADD_S; break;
-+ case Iop_Add64Fx2: op = LAvecbin_VFADD_D; break;
-+ case Iop_Sub32Fx4: op = LAvecbin_VFSUB_S; break;
-+ case Iop_Sub64Fx2: op = LAvecbin_VFSUB_D; break;
-+ case Iop_Mul32Fx4: op = LAvecbin_VFMUL_S; break;
-+ case Iop_Mul64Fx2: op = LAvecbin_VFMUL_D; break;
-+ case Iop_Div32Fx4: op = LAvecbin_VFDIV_S; break;
-+ case Iop_Div64Fx2: op = LAvecbin_VFDIV_D; break;
-+ default: vassert(0); break;
-+ }
-+ HReg dst = newVRegV(env);
-+ HReg src1 = iselV128Expr(env, triop->arg2);
-+ HReg src2 = iselV128Expr(env, triop->arg3);
-+ set_rounding_mode(env, triop->arg1);
-+ addInstr(env, LOONGARCH64Instr_VecBinary(op, LOONGARCH64RI_R(src2), src1, dst));
-+ set_rounding_mode_default(env);
-+ return dst;
-+ }
-+ default: goto irreducible;
-+ }
-+ }
-+
+ /* --------- BINARY OP --------- */
+ case Iex_Binop: {
+ switch (e->Iex.Binop.op) {
-+ case Iop_AndV128: case Iop_OrV128: case Iop_XorV128:
-+ case Iop_Add8x16: case Iop_Add16x8: case Iop_Add32x4: case Iop_Add64x2: case Iop_Add128x1:
-+ case Iop_Sub8x16: case Iop_Sub16x8: case Iop_Sub32x4: case Iop_Sub64x2: case Iop_Sub128x1:
-+ case Iop_QAdd8Sx16: case Iop_QAdd16Sx8: case Iop_QAdd32Sx4: case Iop_QAdd64Sx2:
-+ case Iop_QAdd8Ux16: case Iop_QAdd16Ux8: case Iop_QAdd32Ux4: case Iop_QAdd64Ux2:
-+ case Iop_QSub8Sx16: case Iop_QSub16Sx8: case Iop_QSub32Sx4: case Iop_QSub64Sx2:
-+ case Iop_QSub8Ux16: case Iop_QSub16Ux8: case Iop_QSub32Ux4: case Iop_QSub64Ux2:
-+ case Iop_InterleaveHI8x16: case Iop_InterleaveHI16x8: case Iop_InterleaveHI32x4: case Iop_InterleaveHI64x2:
-+ case Iop_InterleaveLO8x16: case Iop_InterleaveLO16x8: case Iop_InterleaveLO32x4: case Iop_InterleaveLO64x2:
-+ case Iop_Max8Sx16: case Iop_Max16Sx8: case Iop_Max32Sx4: case Iop_Max64Sx2:
-+ case Iop_Max8Ux16: case Iop_Max16Ux8: case Iop_Max32Ux4: case Iop_Max64Ux2:
-+ case Iop_Min8Sx16: case Iop_Min16Sx8: case Iop_Min32Sx4: case Iop_Min64Sx2:
-+ case Iop_Min8Ux16: case Iop_Min16Ux8: case Iop_Min32Ux4: case Iop_Min64Ux2:
-+ case Iop_CmpEQ8x16: case Iop_CmpEQ16x8: case Iop_CmpEQ32x4: case Iop_CmpEQ64x2:
-+ case Iop_PackOddLanes8x16: case Iop_PackOddLanes16x8: case Iop_PackOddLanes32x4:
-+ case Iop_PackEvenLanes8x16: case Iop_PackEvenLanes16x8: case Iop_PackEvenLanes32x4:
-+ case Iop_Avg8Ux16: case Iop_Avg16Ux8: case Iop_Avg32Ux4: case Iop_Avg64Ux2:
-+ case Iop_Avg8Sx16: case Iop_Avg16Sx8: case Iop_Avg32Sx4: case Iop_Avg64Sx2:
-+ case Iop_Mul8x16: case Iop_Mul16x8: case Iop_Mul32x4:
-+ case Iop_MulHi8Ux16: case Iop_MulHi16Ux8: case Iop_MulHi32Ux4:
-+ case Iop_MulHi8Sx16: case Iop_MulHi16Sx8: case Iop_MulHi32Sx4:
-+ case Iop_Shl8x16: case Iop_Shl16x8: case Iop_Shl32x4: case Iop_Shl64x2:
-+ case Iop_Shr8x16: case Iop_Shr16x8: case Iop_Shr32x4: case Iop_Shr64x2:
-+ case Iop_Sar8x16: case Iop_Sar16x8: case Iop_Sar32x4: case Iop_Sar64x2:
-+ case Iop_CmpGT8Sx16: case Iop_CmpGT16Sx8: case Iop_CmpGT32Sx4: case Iop_CmpGT64Sx2:
-+ case Iop_CmpGT8Ux16: case Iop_CmpGT16Ux8: case Iop_CmpGT32Ux4: case Iop_CmpGT64Ux2:
-+ case Iop_Max32Fx4: case Iop_Max64Fx2:
-+ case Iop_Min32Fx4: case Iop_Min64Fx2: {
-+ LOONGARCH64VecBinOp op;
-+ Bool reverse = False;
-+ switch (e->Iex.Binop.op) {
-+ case Iop_AndV128: op = LAvecbin_VAND_V; break;
-+ case Iop_OrV128: op = LAvecbin_VOR_V; break;
-+ case Iop_XorV128: op = LAvecbin_VXOR_V; break;
-+ case Iop_Add8x16: op = LAvecbin_VADD_B; break;
-+ case Iop_Add16x8: op = LAvecbin_VADD_H; break;
-+ case Iop_Add32x4: op = LAvecbin_VADD_W; break;
-+ case Iop_Add64x2: op = LAvecbin_VADD_D; break;
-+ case Iop_Add128x1: op = LAvecbin_VADD_Q; break;
-+ case Iop_Sub8x16: op = LAvecbin_VSUB_B; break;
-+ case Iop_Sub16x8: op = LAvecbin_VSUB_H; break;
-+ case Iop_Sub32x4: op = LAvecbin_VSUB_W; break;
-+ case Iop_Sub64x2: op = LAvecbin_VSUB_D; break;
-+ case Iop_Sub128x1: op = LAvecbin_VSUB_Q; break;
-+ case Iop_QAdd8Sx16: op = LAvecbin_VSADD_B; break;
-+ case Iop_QAdd16Sx8: op = LAvecbin_VSADD_H; break;
-+ case Iop_QAdd32Sx4: op = LAvecbin_VSADD_W; break;
-+ case Iop_QAdd64Sx2: op = LAvecbin_VSADD_D; break;
-+ case Iop_QAdd8Ux16: op = LAvecbin_VSADD_BU; break;
-+ case Iop_QAdd16Ux8: op = LAvecbin_VSADD_HU; break;
-+ case Iop_QAdd32Ux4: op = LAvecbin_VSADD_WU; break;
-+ case Iop_QAdd64Ux2: op = LAvecbin_VSADD_DU; break;
-+ case Iop_QSub8Sx16: op = LAvecbin_VSSUB_B; break;
-+ case Iop_QSub16Sx8: op = LAvecbin_VSSUB_H; break;
-+ case Iop_QSub32Sx4: op = LAvecbin_VSSUB_W; break;
-+ case Iop_QSub64Sx2: op = LAvecbin_VSSUB_D; break;
-+ case Iop_QSub8Ux16: op = LAvecbin_VSSUB_BU; break;
-+ case Iop_QSub16Ux8: op = LAvecbin_VSSUB_HU; break;
-+ case Iop_QSub32Ux4: op = LAvecbin_VSSUB_WU; break;
-+ case Iop_QSub64Ux2: op = LAvecbin_VSSUB_DU; break;
-+ case Iop_InterleaveHI8x16: op = LAvecbin_VILVH_B; break;
-+ case Iop_InterleaveHI16x8: op = LAvecbin_VILVH_H; break;
-+ case Iop_InterleaveHI32x4: op = LAvecbin_VILVH_W; break;
-+ case Iop_InterleaveHI64x2: op = LAvecbin_VILVH_D; break;
-+ case Iop_InterleaveLO8x16: op = LAvecbin_VILVL_B; break;
-+ case Iop_InterleaveLO16x8: op = LAvecbin_VILVL_H; break;
-+ case Iop_InterleaveLO32x4: op = LAvecbin_VILVL_W; break;
-+ case Iop_InterleaveLO64x2: op = LAvecbin_VILVL_D; break;
-+ case Iop_Max8Sx16: op = LAvecbin_VMAX_B; break;
-+ case Iop_Max16Sx8: op = LAvecbin_VMAX_H; break;
-+ case Iop_Max32Sx4: op = LAvecbin_VMAX_W; break;
-+ case Iop_Max64Sx2: op = LAvecbin_VMAX_D; break;
-+ case Iop_Max8Ux16: op = LAvecbin_VMAX_BU; break;
-+ case Iop_Max16Ux8: op = LAvecbin_VMAX_HU; break;
-+ case Iop_Max32Ux4: op = LAvecbin_VMAX_WU; break;
-+ case Iop_Max64Ux2: op = LAvecbin_VMAX_DU; break;
-+ case Iop_Min8Sx16: op = LAvecbin_VMIN_B; break;
-+ case Iop_Min16Sx8: op = LAvecbin_VMIN_H; break;
-+ case Iop_Min32Sx4: op = LAvecbin_VMIN_W; break;
-+ case Iop_Min64Sx2: op = LAvecbin_VMIN_D; break;
-+ case Iop_Min8Ux16: op = LAvecbin_VMIN_BU; break;
-+ case Iop_Min16Ux8: op = LAvecbin_VMIN_HU; break;
-+ case Iop_Min32Ux4: op = LAvecbin_VMIN_WU; break;
-+ case Iop_Min64Ux2: op = LAvecbin_VMIN_DU; break;
-+ case Iop_CmpEQ8x16: op = LAvecbin_VSEQ_B; break;
-+ case Iop_CmpEQ16x8: op = LAvecbin_VSEQ_H; break;
-+ case Iop_CmpEQ32x4: op = LAvecbin_VSEQ_W; break;
-+ case Iop_CmpEQ64x2: op = LAvecbin_VSEQ_D; break;
-+ case Iop_PackOddLanes8x16: op = LAvecbin_VPICKOD_B; break;
-+ case Iop_PackOddLanes16x8: op = LAvecbin_VPICKOD_H; break;
-+ case Iop_PackOddLanes32x4: op = LAvecbin_VPICKOD_W; break;
-+ case Iop_PackEvenLanes8x16: op = LAvecbin_VPICKEV_B; break;
-+ case Iop_PackEvenLanes16x8: op = LAvecbin_VPICKEV_H; break;
-+ case Iop_PackEvenLanes32x4: op = LAvecbin_VPICKEV_W; break;
-+ case Iop_Avg8Ux16: op = LAvecbin_VAVGR_BU; break;
-+ case Iop_Avg16Ux8: op = LAvecbin_VAVGR_HU; break;
-+ case Iop_Avg32Ux4: op = LAvecbin_VAVGR_WU; break;
-+ case Iop_Avg64Ux2: op = LAvecbin_VAVGR_DU; break;
-+ case Iop_Avg8Sx16: op = LAvecbin_VAVGR_B; break;
-+ case Iop_Avg16Sx8: op = LAvecbin_VAVGR_H; break;
-+ case Iop_Avg32Sx4: op = LAvecbin_VAVGR_W; break;
-+ case Iop_Avg64Sx2: op = LAvecbin_VAVGR_D; break;
-+ case Iop_Mul8x16: op = LAvecbin_VMUL_B; break;
-+ case Iop_Mul16x8: op = LAvecbin_VMUL_H; break;
-+ case Iop_Mul32x4: op = LAvecbin_VMUL_W; break;
-+ case Iop_MulHi8Ux16: op = LAvecbin_VMUH_BU; break;
-+ case Iop_MulHi16Ux8: op = LAvecbin_VMUH_HU; break;
-+ case Iop_MulHi32Ux4: op = LAvecbin_VMUH_WU; break;
-+ case Iop_MulHi8Sx16: op = LAvecbin_VMUH_B; break;
-+ case Iop_MulHi16Sx8: op = LAvecbin_VMUH_H; break;
-+ case Iop_MulHi32Sx4: op = LAvecbin_VMUH_W; break;
-+ case Iop_Shl8x16: op = LAvecbin_VSLL_B; break;
-+ case Iop_Shl16x8: op = LAvecbin_VSLL_H; break;
-+ case Iop_Shl32x4: op = LAvecbin_VSLL_W; break;
-+ case Iop_Shl64x2: op = LAvecbin_VSLL_D; break;
-+ case Iop_Shr8x16: op = LAvecbin_VSRL_B; break;
-+ case Iop_Shr16x8: op = LAvecbin_VSRL_H; break;
-+ case Iop_Shr32x4: op = LAvecbin_VSRL_W; break;
-+ case Iop_Shr64x2: op = LAvecbin_VSRL_D; break;
-+ case Iop_Sar8x16: op = LAvecbin_VSRA_B; break;
-+ case Iop_Sar16x8: op = LAvecbin_VSRA_H; break;
-+ case Iop_Sar32x4: op = LAvecbin_VSRA_W; break;
-+ case Iop_Sar64x2: op = LAvecbin_VSRA_D; break;
-+ case Iop_CmpGT8Sx16: op = LAvecbin_VSLT_B; reverse = True; break;
-+ case Iop_CmpGT16Sx8: op = LAvecbin_VSLT_H; reverse = True; break;
-+ case Iop_CmpGT32Sx4: op = LAvecbin_VSLT_W; reverse = True; break;
-+ case Iop_CmpGT64Sx2: op = LAvecbin_VSLT_D; reverse = True; break;
-+ case Iop_CmpGT8Ux16: op = LAvecbin_VSLT_BU; reverse = True; break;
-+ case Iop_CmpGT16Ux8: op = LAvecbin_VSLT_HU; reverse = True; break;
-+ case Iop_CmpGT32Ux4: op = LAvecbin_VSLT_WU; reverse = True; break;
-+ case Iop_CmpGT64Ux2: op = LAvecbin_VSLT_DU; reverse = True; break;
-+ case Iop_Max32Fx4: op = LAvecbin_VFMAX_S; break;
-+ case Iop_Max64Fx2: op = LAvecbin_VFMAX_D; break;
-+ case Iop_Min32Fx4: op = LAvecbin_VFMIN_S; break;
-+ case Iop_Min64Fx2: op = LAvecbin_VFMIN_D; break;
-+ default: vassert(0); break;
-+ }
-+ HReg dst = newVRegV(env);
-+ HReg src1 = iselV128Expr(env, e->Iex.Binop.arg1);
-+ HReg src2 = iselV128Expr(env, e->Iex.Binop.arg2);
-+ if (reverse)
-+ addInstr(env, LOONGARCH64Instr_VecBinary(op, LOONGARCH64RI_R(src1), src2, dst));
-+ else
-+ addInstr(env, LOONGARCH64Instr_VecBinary(op, LOONGARCH64RI_R(src2), src1, dst));
++ case Iop_8HLto16: {
++ HReg dst = newVRegI(env);
++ HReg tHi = newVRegI(env);
++ HReg tLow = newVRegI(env);
++ HReg sHi = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ HReg sLow = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ LOONGARCH64RI* ui5 = LOONGARCH64RI_I(8, 5, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ui5, sHi, tHi));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ui5, sLow, tLow));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_W, ui5, tLow, tLow));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, LOONGARCH64RI_R(tHi), tLow, dst));
++ return dst;
++ }
++ case Iop_16HLto32: {
++ HReg dst = newVRegI(env);
++ HReg tHi = newVRegI(env);
++ HReg tLow = newVRegI(env);
++ HReg sHi = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ HReg sLow = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ LOONGARCH64RI* ui5 = LOONGARCH64RI_I(16, 5, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ui5, sHi, tHi));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ui5, sLow, tLow));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_W, ui5, tLow, tLow));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, LOONGARCH64RI_R(tHi), tLow, dst));
++ return dst;
++ }
++ case Iop_32HLto64: {
++ HReg dst = newVRegI(env);
++ HReg tHi = newVRegI(env);
++ HReg tLow = newVRegI(env);
++ HReg sHi = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ HReg sLow = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ LOONGARCH64RI* ui6 = LOONGARCH64RI_I(32, 6, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ui6, sHi, tHi));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ui6, sLow, tLow));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ui6, tLow, tLow));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, LOONGARCH64RI_R(tHi), tLow, dst));
++ return dst;
++ }
++ case Iop_Add32: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, True);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_ADD_W : LAbin_ADDI_W;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_Add64: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, True);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_ADD_D : LAbin_ADDI_D;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_And8: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, False);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_AND : LAbin_ANDI;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_And16: case Iop_And32: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, False);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_AND : LAbin_ANDI;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_And64: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, False);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_AND : LAbin_ANDI;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_DivModS32to32: {
++ HReg dst = newVRegI(env);
++ HReg tmp = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ LOONGARCH64RI* ri1 = LOONGARCH64RI_I(0, 5, False);
++ LOONGARCH64RI* ri2 = LOONGARCH64RI_R(src2);
++ LOONGARCH64RI* ri3 = LOONGARCH64RI_I(32, 6, False);
++ LOONGARCH64RI* ri4 = LOONGARCH64RI_R(tmp);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src1, src1));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src2, src2));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_W, ri2, src1, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MOD_W, ri2, src1, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri3, tmp, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri3, dst, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri3, dst, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri4, dst, dst));
++ return dst;
++ }
++ case Iop_DivModU32to32: {
++ HReg dst = newVRegI(env);
++ HReg tmp = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ LOONGARCH64RI* ri1 = LOONGARCH64RI_I(0, 5, False);
++ LOONGARCH64RI* ri2 = LOONGARCH64RI_R(src2);
++ LOONGARCH64RI* ri3 = LOONGARCH64RI_I(32, 6, False);
++ LOONGARCH64RI* ri4 = LOONGARCH64RI_R(tmp);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src1, src1));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src2, src2));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_WU, ri2, src1, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MOD_WU, ri2, src1, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri3, tmp, tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri3, dst, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri3, dst, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri4, dst, dst));
++ return dst;
++ }
++ case Iop_DivS32: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ LOONGARCH64RI* ri1 = LOONGARCH64RI_I(0, 5, False);
++ LOONGARCH64RI* ri2 = LOONGARCH64RI_R(src2);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src1, src1));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src2, src2));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_W, ri2, src1, dst));
++ return dst;
++ }
++ case Iop_DivS64: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_D, src2, src1, dst));
++ return dst;
++ }
++ case Iop_DivU32: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ LOONGARCH64RI* ri1 = LOONGARCH64RI_I(0, 5, False);
++ LOONGARCH64RI* ri2 = LOONGARCH64RI_R(src2);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src1, src1));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri1, src2, src2));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_WU, ri2, src1, dst));
+ return dst;
+ }
-+ case Iop_ShlN8x16: case Iop_ShlN16x8: case Iop_ShlN32x4: case Iop_ShlN64x2:
-+ case Iop_ShrN8x16: case Iop_ShrN16x8: case Iop_ShrN32x4: case Iop_ShrN64x2:
-+ case Iop_SarN8x16: case Iop_SarN16x8: case Iop_SarN32x4: case Iop_SarN64x2:
-+ case Iop_ShlV128: case Iop_ShrV128: {
-+ UChar size;
-+ LOONGARCH64VecBinOp op;
++ case Iop_DivU64: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_DU, src2, src1, dst));
++ return dst;
++ }
++ case Iop_CmpF32: {
++ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
++ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
++ return convert_cond_to_IR(env, src2, src1, False);
++ }
++ case Iop_CmpF64: {
++ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
++ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
++ return convert_cond_to_IR(env, src2, src1, True);
++ }
++ case Iop_F32toI32S: {
++ HReg tmp = newVRegF(env);
++ HReg dst = newVRegI(env);
++ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FTINT_W_S, src, tmp));
++ set_rounding_mode_default(env);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVFR2GR_S, tmp, dst));
++ return dst;
++ }
++ case Iop_F32toI64S: {
++ HReg tmp = newVRegF(env);
++ HReg dst = newVRegI(env);
++ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FTINT_L_S, src, tmp));
++ set_rounding_mode_default(env);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVFR2GR_D, tmp, dst));
++ return dst;
++ }
++ case Iop_F64toI32S: {
++ HReg tmp = newVRegF(env);
++ HReg dst = newVRegI(env);
++ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FTINT_W_D, src, tmp));
++ set_rounding_mode_default(env);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVFR2GR_S, tmp, dst));
++ return dst;
++ }
++ case Iop_F64toI64S: {
++ HReg tmp = newVRegF(env);
++ HReg dst = newVRegI(env);
++ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FTINT_L_D, src, tmp));
++ set_rounding_mode_default(env);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVFR2GR_D, tmp, dst));
++ return dst;
++ }
++ case Iop_GetElem16x8:
++ case Iop_GetElem32x4:
++ case Iop_GetElem64x2:
++ case Iop_GetElem8x16: {
++ UChar size;
++ LOONGARCH64VecBinOp pickOp, veplOp;
+ switch (e->Iex.Binop.op) {
-+ case Iop_ShlN8x16: op = LAvecbin_VSLLI_B; size = 3; break;
-+ case Iop_ShlN16x8: op = LAvecbin_VSLLI_H; size = 4; break;
-+ case Iop_ShlN32x4: op = LAvecbin_VSLLI_W; size = 5; break;
-+ case Iop_ShlN64x2: op = LAvecbin_VSLLI_D; size = 6; break;
-+ case Iop_ShrN8x16: op = LAvecbin_VSRLI_B; size = 3; break;
-+ case Iop_ShrN16x8: op = LAvecbin_VSRLI_H; size = 4; break;
-+ case Iop_ShrN32x4: op = LAvecbin_VSRLI_W; size = 5; break;
-+ case Iop_ShrN64x2: op = LAvecbin_VSRLI_D; size = 6; break;
-+ case Iop_SarN8x16: op = LAvecbin_VSRAI_B; size = 3; break;
-+ case Iop_SarN16x8: op = LAvecbin_VSRAI_H; size = 4; break;
-+ case Iop_SarN32x4: op = LAvecbin_VSRAI_W; size = 5; break;
-+ case Iop_SarN64x2: op = LAvecbin_VSRAI_D; size = 6; break;
-+ case Iop_ShlV128: op = LAvecbin_VBSLL_V; size = 5; break;
-+ case Iop_ShrV128: op = LAvecbin_VBSRL_V; size = 5; break;
-+ default: vassert(0); break;
++ case Iop_GetElem8x16:
++ size = 4;
++ pickOp = LAvecbin_VPICKVE2GR_BU;
++ veplOp = LAvecbin_VREPLVE_B;
++ break;
++ case Iop_GetElem16x8:
++ size = 3;
++ pickOp = LAvecbin_VPICKVE2GR_HU;
++ veplOp = LAvecbin_VREPLVE_H;
++ break;
++ case Iop_GetElem32x4:
++ size = 2;
++ pickOp = LAvecbin_VPICKVE2GR_WU;
++ veplOp = LAvecbin_VREPLVE_W;
++ break;
++ case Iop_GetElem64x2:
++ size = 1;
++ pickOp = LAvecbin_VPICKVE2GR_DU;
++ veplOp = LAvecbin_VREPLVE_D;
++ break;
++ default:
++ vassert(0);
++ break;
+ }
-+ HReg dst = newVRegV(env);
-+ HReg src1 = iselV128Expr(env, e->Iex.Binop.arg1);
++ HReg dst = newVRegI(env);
++ HReg src1 = iselV128Expr(env, e->Iex.Binop.arg1);
+ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, size, False);
-+ vassert(e->Iex.Binop.arg2->tag == Iex_Const);
-+ vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
-+ vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
-+ addInstr(env, LOONGARCH64Instr_VecBinary(op, src2, src1, dst));
++ if (src2->tag == LAri_Imm) {
++ addInstr(env, LOONGARCH64Instr_VecBinary(pickOp, src2, src1, dst));
++ } else {
++ HReg v_tmp = newVRegV(env);
++ addInstr(env, LOONGARCH64Instr_VecBinary(veplOp, src2, src1, v_tmp));
++ addInstr(env, LOONGARCH64Instr_VecBinary(pickOp, LOONGARCH64RI_I(0, size, False), v_tmp, dst));
++ }
++
++ return dst;
++ }
++ case Iop_Max32U: {
++ HReg cond = newVRegI(env);
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ addInstr(env, LOONGARCH64Instr_Cmp(LAcc_LTU, src2, src1, cond));
++ addInstr(env, LOONGARCH64Instr_CMove(cond, src1, src2, dst, True));
++ return dst;
++ }
++ case Iop_MullS32: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MULW_D_W, src2, src1, dst));
++ return dst;
++ }
++ case Iop_MullU32: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MULW_D_WU, src2, src1, dst));
++ return dst;
++ }
++ case Iop_Or16: case Iop_Or32: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, False);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_OR : LAbin_ORI;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_Or64: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, False);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_OR : LAbin_ORI;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_Sar32: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 5, False);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_SRA_W : LAbin_SRAI_W;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_Sar64: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 6, False);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_SRA_D : LAbin_SRAI_D;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_Shl16: case Iop_Shl32: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 5, False);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_SLL_W : LAbin_SLLI_W;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_Shl64: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 6, False);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_SLL_D : LAbin_SLLI_D;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_Shr32: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 5, False);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_SRL_W : LAbin_SRLI_W;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_Shr64: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 6, False);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_SRL_D : LAbin_SRLI_D;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_Sub32: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SUB_W, src2, src1, dst));
++ return dst;
++ }
++ case Iop_Sub64: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SUB_D, src2, src1, dst));
++ return dst;
++ }
++ case Iop_Xor32: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, False);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_XOR : LAbin_XORI;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_Xor64: {
++ HReg dst = newVRegI(env);
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 12, False);
++ LOONGARCH64BinOp op = (src2->tag == LAri_Reg) ? LAbin_XOR : LAbin_XORI;
++ addInstr(env, LOONGARCH64Instr_Binary(op, src2, src1, dst));
+ return dst;
+ }
+ case Iop_64HLtoV128: {
@@ -21818,6771 +26075,6793 @@ index 0000000..d60a2b3
+ LOONGARCH64RI_I(1, 1, False), sHi, dst));
+ return dst;
+ }
-+ default: goto irreducible;
++ default:
++ goto irreducible;
+ }
+ }
+
+ /* --------- UNARY OP --------- */
+ case Iex_Unop: {
+ switch (e->Iex.Unop.op) {
-+ case Iop_32UtoV128: {
-+ HReg dst = newVRegV(env);
++ case Iop_128HIto64: {
++ HReg hi, lo;
++ iselInt128Expr(&hi, &lo, env, e->Iex.Unop.arg);
++ return hi;
++ }
++ case Iop_128to64: {
++ HReg hi, lo;
++ iselInt128Expr(&hi, &lo, env, e->Iex.Unop.arg);
++ return lo;
++ }
++ case Iop_16Sto64: {
++ HReg dst = newVRegI(env);
+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_W,
-+ LOONGARCH64RI_I(0, 2, False), src, dst));
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_W,
-+ LOONGARCH64RI_I(1, 2, False), hregZERO(), dst));
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_W,
-+ LOONGARCH64RI_I(2, 2, False), hregZERO(), dst));
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_W,
-+ LOONGARCH64RI_I(3, 2, False), hregZERO(), dst));
-+ return dst;
++ addInstr(env, LOONGARCH64Instr_Unary(LAun_EXT_W_H, src, dst));
++ return dst;
+ }
-+ case Iop_64UtoV128: {
-+ HReg dst = newVRegV(env);
++ case Iop_16Uto32: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(48, 6, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri, dst, dst));
++ return dst;
++ }
++ case Iop_16Uto64: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(48, 6, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri, dst, dst));
++ return dst;
++ }
++ case Iop_1Sto8: case Iop_1Sto32: {
++ HReg dst = newVRegI(env);
++ HReg src = iselCondCode_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(63, 6, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri, dst, dst));
++ return dst;
++ }
++ case Iop_1Sto64: {
++ HReg dst = newVRegI(env);
++ HReg src = iselCondCode_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(63, 6, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri, dst, dst));
++ return dst;
++ }
++ case Iop_1Uto64: {
++ HReg dst = newVRegI(env);
++ HReg src = iselCondCode_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(0x1, 12, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri, src, dst));
++ return dst;
++ }
++ case Iop_1Uto8: {
++ HReg dst = newVRegI(env);
++ HReg src = iselCondCode_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(0x1, 12, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri, src, dst));
++ return dst;
++ }
++ case Iop_32Sto64: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(0, 5, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri, src, dst));
++ return dst;
++ }
++ case Iop_32Uto64: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(32, 6, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri, dst, dst));
++ return dst;
++ }
++ case Iop_16to8: case Iop_32to8: {
++ HReg dst = newVRegI(env);
+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_D,
-+ LOONGARCH64RI_I(0, 1, False), src, dst));
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_D,
-+ LOONGARCH64RI_I(1, 1, False), hregZERO(), dst));
-+ return dst;
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(0xff, 12, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri, src, dst));
++ return dst;
+ }
-+ case Iop_NotV128: {
-+ HReg dst = newVRegV(env);
-+ HReg src = iselV128Expr(env, e->Iex.Unop.arg);
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VNOR_V,
-+ LOONGARCH64RI_R(src), src, dst));
-+ return dst;
++ case Iop_64HIto32: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(32, 6, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri, src, dst));
++ return dst;
+ }
-+ case Iop_Abs8x16: case Iop_Abs16x8:
-+ case Iop_Abs32x4: case Iop_Abs64x2: {
-+ LOONGARCH64VecBinOp subOp, addOp;
-+ switch (e->Iex.Unop.op) {
-+ case Iop_Abs8x16:
-+ subOp = LAvecbin_VSUB_B;
-+ addOp = LAvecbin_VADDA_B;
-+ break;
-+ case Iop_Abs16x8:
-+ subOp = LAvecbin_VSUB_H;
-+ addOp = LAvecbin_VADDA_H;
-+ break;
-+ case Iop_Abs32x4:
-+ subOp = LAvecbin_VSUB_W;
-+ addOp = LAvecbin_VADDA_W;
-+ break;
-+ case Iop_Abs64x2:
-+ subOp = LAvecbin_VSUB_D;
-+ addOp = LAvecbin_VADDA_D;
-+ break;
-+ default:
-+ vassert(0);
-+ break;
-+ };
-+ HReg dst = newVRegV(env);
-+ HReg src = iselV128Expr(env, e->Iex.Unop.arg);
-+ HReg sub = newVRegV(env);
-+ addInstr(env, LOONGARCH64Instr_VecBinary(subOp, LOONGARCH64RI_R(src), src, sub));
-+ addInstr(env, LOONGARCH64Instr_VecBinary(addOp, LOONGARCH64RI_R(src), sub, dst));
++ case Iop_64to32: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(32, 6, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri, dst, dst));
+ return dst;
+ }
-+ case Iop_Dup8x16: case Iop_Dup16x8: case Iop_Dup32x4: {
-+ HReg dst = newVRegV(env);
++ case Iop_32to16:
++ case Iop_64to16: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(48, 6, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRLI_D, ri, dst, dst));
++ return dst;
++ }
++ case Iop_64to8: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(0xff, 12, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri, src, dst));
++ return dst;
++ }
++ case Iop_8Sto32: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(56, 6, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri, dst, dst));
++ return dst;
++ }
++ case Iop_8Sto64: {
++ HReg dst = newVRegI(env);
+ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
-+ LOONGARCH64VecUnOp op;
-+ switch (e->Iex.Unop.op) {
-+ case Iop_Dup8x16: op = LAvecun_VREPLGR2VR_B; break;
-+ case Iop_Dup16x8: op = LAvecun_VREPLGR2VR_H; break;
-+ case Iop_Dup32x4: op = LAvecun_VREPLGR2VR_W; break;
-+ default: vassert(0); break;
-+ }
-+ addInstr(env, LOONGARCH64Instr_VecUnary(op, src, dst));
++ addInstr(env, LOONGARCH64Instr_Unary(LAun_EXT_W_B, src, dst));
+ return dst;
+ }
-+ case Iop_V256toV128_0:
-+ case Iop_V256toV128_1: {
-+ HReg vHi, vLo;
-+ iselV256Expr(&vHi, &vLo, env, e->Iex.Unop.arg);
-+ return (e->Iex.Unop.op == Iop_V256toV128_1) ? vHi : vLo;
++ case Iop_8Uto32: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(0xff, 12, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri, src, dst));
++ return dst;
+ }
-+ default:
-+ goto irreducible;
-+ }
-+ }
-+
-+ case Iex_Const: {
-+ IRConst *con = e->Iex.Const.con;
-+
-+ if (con->tag != Ico_V128) {
-+ vpanic("iselV128Expr.const(LoongArch)");
-+ goto irreducible;
-+ }
-+
-+ HReg dst = newVRegV(env);
-+ UShort val = con->Ico.V128;
-+
-+ if (val == 0) {
-+ addInstr(env, LOONGARCH64Instr_VecUnary(LAvecun_VREPLGR2VR_D, hregZERO(), dst));
-+ } else {
-+ HReg r_tmp = newVRegI(env);
-+ UInt i;
-+ addInstr(env, LOONGARCH64Instr_LI(0xfful, r_tmp));
-+ if (val & 1) {
-+ addInstr(env, LOONGARCH64Instr_VecUnary(LAvecun_VREPLGR2VR_B, r_tmp, dst));
-+ } else {
-+ addInstr(env, LOONGARCH64Instr_VecUnary(LAvecun_VREPLGR2VR_B, hregZERO(), dst));
++ case Iop_8Uto64: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(0xff, 12, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ANDI, ri, src, dst));
++ return dst;
++ }
++ case Iop_16Sto32: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(48, 6, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, src, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri, dst, dst));
++ return dst;
++ }
++ case Iop_CmpwNEZ32: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(63, 6, False);
++ addInstr(env, LOONGARCH64Instr_Cmp(LAcc_NE, hregZERO(), src, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, dst, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri, dst, dst));
++ return dst;
++ }
++ case Iop_CmpwNEZ64: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(63, 6, False);
++ addInstr(env, LOONGARCH64Instr_Cmp(LAcc_NE, hregZERO(), src, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_D, ri, dst, dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SRAI_D, ri, dst, dst));
++ return dst;
++ }
++ case Iop_Clz32: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_Unary(LAun_CLZ_W, src, dst));
++ return dst;
++ }
++ case Iop_Clz64: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_Unary(LAun_CLZ_D, src, dst));
++ return dst;
++ }
++ case Iop_Ctz32: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_Unary(LAun_CTZ_W, src, dst));
++ return dst;
++ }
++ case Iop_Ctz64: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_Unary(LAun_CTZ_D, src, dst));
++ return dst;
++ }
++ case Iop_Left16: {
++ HReg tmp = newVRegI(env);
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_R(src);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SUB_D, ri, hregZERO(), tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri, tmp, dst));
++ return dst;
+ }
-+ for (i = 1; i < 16; i++) {
-+ val >>= 1;
-+ if (val & 1) {
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_B,
-+ LOONGARCH64RI_I(i, 4, False),
-+ r_tmp, dst));
-+ } else {
-+ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_B,
-+ LOONGARCH64RI_I(i, 4, False),
-+ hregZERO(), dst));
-+ }
++ case Iop_Left32: {
++ HReg tmp = newVRegI(env);
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_R(src);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SUB_D, ri, hregZERO(), tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri, tmp, dst));
++ return dst;
+ }
-+ }
-+
-+ return dst;
-+ }
-+
-+ default:
-+ break;
-+ }
-+
-+ /* We get here if no pattern matched. */
-+irreducible:
-+ ppIRExpr(e);
-+ vpanic("iselV128Expr(loongarch64): cannot reduce tree");
-+}
-+
-+
-+/*---------------------------------------------------------*/
-+/*--- ISEL: Vector expressions (256 bit) ---*/
-+/*---------------------------------------------------------*/
-+
-+/* Compute a vector value into a register, the identity of
-+ which is returned. As with iselIntExpr_R, the reg may be either
-+ real or virtual; in any case it must not be changed by subsequent
-+ code emitted by the caller. */
-+
-+static void iselV256Expr ( HReg* hi, HReg* lo,
-+ ISelEnv* env, IRExpr* e )
-+{
-+ iselV256Expr_wrk( hi, lo, env, e );
-+
-+ /* sanity checks ... */
-+ vassert(hregClass(*hi) == HRcVec128);
-+ vassert(hregIsVirtual(*hi));
-+ vassert(hregClass(*lo) == HRcVec128);
-+ vassert(hregIsVirtual(*lo));
-+}
-+
-+/* DO NOT CALL THIS DIRECTLY */
-+static void iselV256Expr_wrk ( HReg* hi, HReg* lo,
-+ ISelEnv* env, IRExpr* e )
-+{
-+ IRType ty = typeOfIRExpr(env->type_env, e);
-+ vassert(e);
-+ vassert(ty == Ity_V256);
-+
-+ switch (e->tag) {
-+ /* --------- TEMP --------- */
-+ case Iex_RdTmp: {
-+ lookupIRTempPair(hi, lo, env, e->Iex.RdTmp.tmp);
-+ return;
-+ }
-+
-+ /* --------- LOAD --------- */
-+ case Iex_Load: {
-+ if (e->Iex.Load.end != Iend_LE)
-+ goto irreducible;
-+
-+ HReg dstHi = newVRegV(env);
-+ HReg dstLo = newVRegV(env);
-+ LOONGARCH64AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr, ty);
-+ LOONGARCH64VecLoadOp op = (am->tag == LAam_RI) ? LAvecload_VLD : LAvecload_VLDX;
-+ HReg addr = iselIntExpr_R(env, e->Iex.Load.addr);
-+ LOONGARCH64AMode* am16 = LOONGARCH64AMode_RI(addr, 16);
-+ addInstr(env, LOONGARCH64Instr_VecLoad(op, am, dstLo));
-+ addInstr(env, LOONGARCH64Instr_VecLoad(LAvecload_VLD, am16, dstHi));
-+ *hi = dstHi;
-+ *lo = dstLo;
-+ return;
-+ }
-+
-+ /* --------- GET --------- */
-+ case Iex_Get: {
-+ Bool ri = e->Iex.Get.offset < 1024;
-+ HReg dstHi = newVRegV(env);
-+ HReg dstLo = newVRegV(env);
-+ LOONGARCH64VecLoadOp op, op2;
-+ HReg tmp, tmp2;
-+ LOONGARCH64AMode* am;
-+ LOONGARCH64AMode* am2;
-+ if (ri) {
-+ op = LAvecload_VLD;
-+ am = LOONGARCH64AMode_RI(hregGSP(), e->Iex.Get.offset);
-+ } else {
-+ op = LAvecload_VLDX;
-+ tmp = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_LI(e->Iex.Get.offset, tmp));
-+ am = LOONGARCH64AMode_RR(hregGSP(), tmp);
-+ }
-+ if (e->Iex.Get.offset + 16 < 1024) {
-+ op2 = LAvecload_VLD;
-+ am2 = LOONGARCH64AMode_RI(hregGSP(), e->Iex.Get.offset + 16);
-+ } else {
-+ op2 = LAvecload_VLDX;
-+ tmp2 = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_LI(e->Iex.Get.offset + 16, tmp2));
-+ am2 = LOONGARCH64AMode_RR(hregGSP(), tmp2);
-+ }
-+ addInstr(env, LOONGARCH64Instr_VecLoad(op, am, dstLo));
-+ addInstr(env, LOONGARCH64Instr_VecLoad(op2, am2, dstHi));
-+ *hi = dstHi;
-+ *lo = dstLo;
-+ return;
-+ }
-+
-+ /* --------- BINARY OP --------- */
-+ case Iex_Binop: {
-+ switch (e->Iex.Binop.op) {
-+ case Iop_V128HLtoV256: {
-+ *hi = iselV128Expr(env, e->Iex.Binop.arg1);
-+ *lo = iselV128Expr(env, e->Iex.Binop.arg2);
-+ return;
++ case Iop_Left64: {
++ HReg tmp = newVRegI(env);
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_R(src);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SUB_D, ri, hregZERO(), tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri, tmp, dst));
++ return dst;
+ }
-+ case Iop_XorV256:
-+ case Iop_CmpEQ8x32: case Iop_CmpEQ16x16: case Iop_CmpEQ32x8: case Iop_CmpEQ64x4:
-+ case Iop_Max8Sx32: case Iop_Max16Sx16: case Iop_Max32Sx8: case Iop_Max64Sx4:
-+ case Iop_Max8Ux32: case Iop_Max16Ux16: case Iop_Max32Ux8: case Iop_Max64Ux4:
-+ case Iop_Min8Sx32: case Iop_Min16Sx16: case Iop_Min32Sx8: case Iop_Min64Sx4:
-+ case Iop_Min8Ux32: case Iop_Min16Ux16: case Iop_Min32Ux8: case Iop_Min64Ux4: {
-+ LOONGARCH64VecBinOp op;
-+ switch (e->Iex.Binop.op) {
-+ case Iop_XorV256: op = LAvecbin_VXOR_V; break;
-+ case Iop_CmpEQ8x32: op = LAvecbin_VSEQ_B; break;
-+ case Iop_CmpEQ16x16: op = LAvecbin_VSEQ_H; break;
-+ case Iop_CmpEQ32x8: op = LAvecbin_VSEQ_W; break;
-+ case Iop_CmpEQ64x4: op = LAvecbin_VSEQ_D; break;
-+ case Iop_Max8Sx32: op = LAvecbin_VMAX_B; break;
-+ case Iop_Max16Sx16: op = LAvecbin_VMAX_H; break;
-+ case Iop_Max32Sx8: op = LAvecbin_VMAX_W; break;
-+ case Iop_Max64Sx4: op = LAvecbin_VMAX_D; break;
-+ case Iop_Max8Ux32: op = LAvecbin_VMAX_BU; break;
-+ case Iop_Max16Ux16: op = LAvecbin_VMAX_HU; break;
-+ case Iop_Max32Ux8: op = LAvecbin_VMAX_WU; break;
-+ case Iop_Max64Ux4: op = LAvecbin_VMAX_DU; break;
-+ case Iop_Min8Sx32: op = LAvecbin_VMIN_B; break;
-+ case Iop_Min16Sx16: op = LAvecbin_VMIN_H; break;
-+ case Iop_Min32Sx8: op = LAvecbin_VMIN_W; break;
-+ case Iop_Min64Sx4: op = LAvecbin_VMIN_D; break;
-+ case Iop_Min8Ux32: op = LAvecbin_VMIN_BU; break;
-+ case Iop_Min16Ux16: op = LAvecbin_VMIN_HU; break;
-+ case Iop_Min32Ux8: op = LAvecbin_VMIN_WU; break;
-+ case Iop_Min64Ux4: op = LAvecbin_VMIN_DU; break;
-+ default: vassert(0); break;
-+ }
-+ HReg src1Hi, src1Lo, src2Hi, src2Lo;
-+ iselV256Expr(&src1Hi, &src1Lo, env, e->Iex.Binop.arg1);
-+ iselV256Expr(&src2Hi, &src2Lo, env, e->Iex.Binop.arg2);
-+ HReg dstHi = newVRegV(env);
-+ HReg dstLo = newVRegV(env);
-+ addInstr(env, LOONGARCH64Instr_VecBinary(op, LOONGARCH64RI_R(src2Hi), src1Hi, dstHi));
-+ addInstr(env, LOONGARCH64Instr_VecBinary(op, LOONGARCH64RI_R(src2Lo), src1Lo, dstLo));
-+ *hi = dstHi;
-+ *lo = dstLo;
-+ return;
++ case Iop_Left8: {
++ HReg tmp = newVRegI(env);
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_R(src);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SUB_D, ri, hregZERO(), tmp));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri, tmp, dst));
++ return dst;
+ }
-+ default: goto irreducible;
-+ }
-+ }
-+
-+ default:
-+ break;
-+ }
-+
-+ /* We get here if no pattern matched. */
-+irreducible:
-+ ppIRExpr(e);
-+ vpanic("iselV256Expr(loongarch64): cannot reduce tree");
-+}
-+
-+
-+/*---------------------------------------------------------*/
-+/*--- ISEL: Statements ---*/
-+/*---------------------------------------------------------*/
-+
-+static void iselStmtStore ( ISelEnv* env, IRStmt* stmt )
-+{
-+ IRType tya = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
-+ IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
-+
-+ if (tya != Ity_I64 || stmt->Ist.Store.end != Iend_LE)
-+ vpanic("iselStmt(loongarch64): Ist_Store");
-+
-+ LOONGARCH64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr, tyd);
-+ LOONGARCH64StoreOp op;
-+ Bool ok = True;
-+ switch (tyd) {
-+ case Ity_I8:
-+ op = (am->tag == LAam_RI) ? LAstore_ST_B : LAstore_STX_B;
-+ break;
-+ case Ity_I16:
-+ op = (am->tag == LAam_RI) ? LAstore_ST_H : LAstore_STX_H;
-+ break;
-+ case Ity_I32:
-+ op = (am->tag == LAam_RI) ? LAstore_ST_W : LAstore_STX_W;
-+ break;
-+ case Ity_I64:
-+ op = (am->tag == LAam_RI) ? LAstore_ST_D : LAstore_STX_D;
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
-+ if (ok) {
-+ HReg src = iselIntExpr_R(env, stmt->Ist.Store.data);
-+ addInstr(env, LOONGARCH64Instr_Store(op, am, src));
-+ return;
-+ }
-+
-+ LOONGARCH64FpStoreOp fop;
-+ ok = True;
-+ switch (tyd) {
-+ case Ity_F32:
-+ fop = (am->tag == LAam_RI) ? LAfpstore_FST_S : LAfpstore_FSTX_S;
-+ break;
-+ case Ity_F64:
-+ fop = (am->tag == LAam_RI) ? LAfpstore_FST_D : LAfpstore_FSTX_D;
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
-+ if (ok) {
-+ HReg src = iselFltExpr(env, stmt->Ist.Store.data);
-+ addInstr(env, LOONGARCH64Instr_FpStore(fop, am, src));
-+ return;
-+ }
-+
-+ if (tyd == Ity_V128) {
-+ LOONGARCH64VecStoreOp vop = (am->tag == LAam_RI) ? LAvecstore_VST : LAvecstore_VSTX;
-+ HReg src = iselV128Expr(env, stmt->Ist.Store.data);
-+ addInstr(env, LOONGARCH64Instr_VecStore(vop, am, src));
-+ } else if (tyd == Ity_V256) {
-+ LOONGARCH64VecStoreOp vop = (am->tag == LAam_RI) ? LAvecstore_VST : LAvecstore_VSTX;
-+ HReg addr = iselIntExpr_R(env, stmt->Ist.Store.addr);
-+ LOONGARCH64AMode* am16 = LOONGARCH64AMode_RI(addr, 16);
-+ HReg hi, lo;
-+ iselV256Expr(&hi, &lo, env, stmt->Ist.Store.data);
-+ addInstr(env, LOONGARCH64Instr_VecStore(vop, am, lo));
-+ addInstr(env, LOONGARCH64Instr_VecStore(LAvecstore_VST, am16, hi));
-+ } else {
-+ vpanic("iselStmt(loongarch64): Ist_Store");
-+ }
-+}
-+
-+static void iselStmtPut ( ISelEnv* env, IRStmt* stmt )
-+{
-+ IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
-+
-+ Bool ri = stmt->Ist.Put.offset < 1024;
-+ HReg tmp;
-+ LOONGARCH64AMode* am;
-+
-+ if (ri) {
-+ am = LOONGARCH64AMode_RI(hregGSP(), stmt->Ist.Put.offset);
-+ } else {
-+ tmp = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_LI(stmt->Ist.Put.offset, tmp));
-+ am = LOONGARCH64AMode_RR(hregGSP(), tmp);
-+ }
-+
-+ LOONGARCH64StoreOp op;
-+ Bool ok = True;
-+ switch (ty) {
-+ case Ity_I8:
-+ op = ri ? LAstore_ST_B : LAstore_STX_B;
-+ break;
-+ case Ity_I16:
-+ op = ri ? LAstore_ST_H : LAstore_STX_H;
-+ break;
-+ case Ity_I32:
-+ op = ri ? LAstore_ST_W : LAstore_STX_W;
-+ break;
-+ case Ity_I64:
-+ op = ri ? LAstore_ST_D : LAstore_STX_D;
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
-+ if (ok) {
-+ HReg src = iselIntExpr_R(env, stmt->Ist.Put.data);
-+ addInstr(env, LOONGARCH64Instr_Store(op, am, src));
-+ return;
-+ }
-+
-+ LOONGARCH64FpStoreOp fop;
-+ ok = True;
-+ switch (ty) {
-+ case Ity_F32:
-+ fop = ri ? LAfpstore_FST_S : LAfpstore_FSTX_S;
-+ break;
-+ case Ity_F64:
-+ fop = ri ? LAfpstore_FST_D : LAfpstore_FSTX_D;
-+ break;
-+ default:
-+ ok = False;
-+ break;
-+ }
-+ if (ok) {
-+ HReg src = iselFltExpr(env, stmt->Ist.Put.data);
-+ addInstr(env, LOONGARCH64Instr_FpStore(fop, am, src));
-+ return;
-+ }
-+
-+ if (ty == Ity_V128) {
-+ LOONGARCH64VecStoreOp vop = ri ? LAvecstore_VST : LAvecstore_VSTX;
-+ HReg src = iselV128Expr(env, stmt->Ist.Put.data);
-+ addInstr(env, LOONGARCH64Instr_VecStore(vop, am, src));
-+ } else if (ty == Ity_V256) {
-+ LOONGARCH64VecStoreOp vop = ri ? LAvecstore_VST : LAvecstore_VSTX;
-+ LOONGARCH64VecStoreOp vop2;
-+ HReg hi, lo;
-+ HReg tmp2;
-+ LOONGARCH64AMode* am2;
-+ if (stmt->Ist.Put.offset + 16 < 1024) {
-+ vop2 = LAvecstore_VST;
-+ am2 = LOONGARCH64AMode_RI(hregGSP(), stmt->Ist.Put.offset + 16);
-+ } else {
-+ vop2 = LAvecstore_VSTX;
-+ tmp2 = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_LI(stmt->Ist.Put.offset + 16, tmp2));
-+ am2 = LOONGARCH64AMode_RR(hregGSP(), tmp2);
-+ }
-+ iselV256Expr(&hi, &lo, env, stmt->Ist.Put.data);
-+ addInstr(env, LOONGARCH64Instr_VecStore(vop, am, lo));
-+ addInstr(env, LOONGARCH64Instr_VecStore(vop2, am2, hi));
-+ } else {
-+ vpanic("iselStmt(loongarch64): Ist_Put");
-+ }
-+}
-+
-+static void iselStmtTmp ( ISelEnv* env, IRStmt* stmt )
-+{
-+ IRTemp tmp = stmt->Ist.WrTmp.tmp;
-+ IRType ty = typeOfIRTemp(env->type_env, tmp);
-+
-+ switch (ty) {
-+ case Ity_I8:
-+ case Ity_I16:
-+ case Ity_I32:
-+ case Ity_I64: {
-+ HReg dst = lookupIRTemp(env, tmp);
-+ HReg src = iselIntExpr_R(env, stmt->Ist.WrTmp.data);
-+ addInstr(env, LOONGARCH64Instr_Move(dst, src));
-+ break;
-+ }
-+ case Ity_I1: {
-+ HReg dst = lookupIRTemp(env, tmp);
-+ HReg src = iselCondCode_R(env, stmt->Ist.WrTmp.data);
-+ addInstr(env, LOONGARCH64Instr_Move(dst, src));
-+ break;
-+ }
-+ case Ity_F32: {
-+ HReg dst = lookupIRTemp(env, tmp);
-+ HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_FMOV_S, src, dst));
-+ break;
-+ }
-+ case Ity_F64: {
-+ HReg dst = lookupIRTemp(env, tmp);
-+ HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data);
-+ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_FMOV_D, src, dst));
-+ break;
-+ }
-+ case Ity_V128: {
-+ HReg dst = lookupIRTemp(env, tmp);
-+ HReg src = iselV128Expr(env, stmt->Ist.WrTmp.data);
-+ addInstr(env, LOONGARCH64Instr_VecMove(dst, src));
-+ break;
-+ }
-+ case Ity_V256: {
-+ HReg hi, lo, dstHi, dstLo;
-+ lookupIRTempPair(&dstHi, &dstLo, env, tmp);
-+ iselV256Expr(&hi, &lo, env, stmt->Ist.WrTmp.data);
-+ addInstr(env, LOONGARCH64Instr_VecMove(dstHi, hi));
-+ addInstr(env, LOONGARCH64Instr_VecMove(dstLo, lo));
-+ break;
-+ }
-+ default:
-+ vpanic("iselStmt(loongarch64): Ist_WrTmp");
-+ break;
-+ }
-+}
-+
-+static void iselStmtDirty ( ISelEnv* env, IRStmt* stmt )
-+{
-+ IRDirty* d = stmt->Ist.Dirty.details;
-+
-+ /* Figure out the return type, if any. */
-+ IRType retty = Ity_INVALID;
-+ if (d->tmp != IRTemp_INVALID)
-+ retty = typeOfIRTemp(env->type_env, d->tmp);
-+
-+ Bool retty_ok = False;
-+ switch (retty) {
-+ case Ity_INVALID: /* function doesn't return anything */
-+ case Ity_I8: case Ity_I16: case Ity_I32: case Ity_I64:
-+ case Ity_V128: case Ity_V256:
-+ retty_ok = True;
-+ break;
-+ default:
-+ break;
-+ }
-+ if (!retty_ok)
-+ vpanic("iselStmt(loongarch64): Ist_Dirty");
-+
-+ /* Marshal args, do the call, and set the return value to 0x555..555
-+ if this is a conditional call that returns a value and the
-+ call is skipped. */
-+ UInt addToSp = 0;
-+ RetLoc rloc = mk_RetLoc_INVALID();
-+ doHelperCall(&addToSp, &rloc, env, d->guard, d->cee, retty, d->args);
-+ vassert(is_sane_RetLoc(rloc));
-+
-+ /* Now figure out what to do with the returned value, if any. */
-+ switch (retty) {
-+ case Ity_INVALID: {
-+ /* No return value. Nothing to do. */
-+ vassert(d->tmp == IRTemp_INVALID);
-+ vassert(rloc.pri == RLPri_None);
-+ vassert(addToSp == 0);
-+ break;
-+ }
-+ case Ity_I8: case Ity_I16: case Ity_I32: case Ity_I64: {
-+ vassert(rloc.pri == RLPri_Int);
-+ vassert(addToSp == 0);
-+ /* The returned value is in $a0. Park it in the register
-+ associated with tmp. */
-+ HReg dst = lookupIRTemp(env, d->tmp);
-+ addInstr(env, LOONGARCH64Instr_Move(dst, hregLOONGARCH64_R4()));
-+ break;
-+ }
-+ case Ity_V128: {
-+ /* The returned value is on the stack, and *retloc tells
-+ us where. Fish it off the stack and then move the
-+ stack pointer upwards to clear it, as directed by
-+ doHelperCall. */
-+ vassert(rloc.pri == RLPri_V128SpRel);
-+ vassert((rloc.spOff < 512) && (rloc.spOff > -512));
-+ vassert(addToSp >= 16);
-+ HReg dst = lookupIRTemp(env, d->tmp);
-+ HReg tmp = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_Move(tmp, hregSP()));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D,
-+ LOONGARCH64RI_I(rloc.spOff, 12, True),
-+ tmp, tmp));
-+ addInstr(env, LOONGARCH64Instr_VecLoad(LAvecload_VLD,
-+ LOONGARCH64AMode_RI(tmp, 0),
-+ dst));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D,
-+ LOONGARCH64RI_I(addToSp, 12, True),
-+ hregSP(), hregSP()));
-+ break;
-+ }
-+ case Ity_V256: {
-+ /* See comments for Ity_V128. */
-+ vassert(rloc.pri == RLPri_V256SpRel);
-+ vassert((rloc.spOff + 16 < 512) && (rloc.spOff > -512));
-+ vassert(addToSp >= 32);
-+ HReg dstLo, dstHi;
-+ lookupIRTempPair(&dstHi, &dstLo, env, d->tmp);
-+ HReg tmp = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_Move(tmp, hregSP()));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D,
-+ LOONGARCH64RI_I(rloc.spOff, 12, True),
-+ tmp, tmp));
-+ addInstr(env, LOONGARCH64Instr_VecLoad(LAvecload_VLD,
-+ LOONGARCH64AMode_RI(tmp, 0),
-+ dstLo));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D,
-+ LOONGARCH64RI_I(16, 12, True),
-+ tmp, tmp));
-+ addInstr(env, LOONGARCH64Instr_VecLoad(LAvecload_VLD,
-+ LOONGARCH64AMode_RI(tmp, 0),
-+ dstHi));
-+ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D,
-+ LOONGARCH64RI_I(addToSp, 12, True),
-+ hregSP(), hregSP()));
-+ break;
++ case Iop_ReinterpF32asI32: {
++ HReg dst = newVRegI(env);
++ HReg src = iselFltExpr(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVFR2GR_S, src, dst));
++ return dst;
++ }
++ case Iop_ReinterpF64asI64: {
++ HReg dst = newVRegI(env);
++ HReg src = iselFltExpr(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVFR2GR_D, src, dst));
++ return dst;
++ }
++ case Iop_Not32: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_R(hregZERO());
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_NOR, ri, src, dst));
++ return dst;
++ }
++ case Iop_Not64: {
++ HReg dst = newVRegI(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_R(hregZERO());
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_NOR, ri, src, dst));
++ return dst;
++ }
++ case Iop_V128to32: {
++ HReg dst = newVRegI(env);
++ HReg src = iselV128Expr(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VPICKVE2GR_W,
++ LOONGARCH64RI_I(0, 2, False), src, dst));
++ return dst;
++ }
++ case Iop_V128to64: {
++ HReg dst = newVRegI(env);
++ HReg src = iselV128Expr(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VPICKVE2GR_D,
++ LOONGARCH64RI_I(0, 1, False), src, dst));
++ return dst;
++ }
++ case Iop_V128HIto64: {
++ HReg dst = newVRegI(env);
++ HReg src = iselV128Expr(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VPICKVE2GR_D,
++ LOONGARCH64RI_I(1, 1, False), src, dst));
++ return dst;
++ }
++ case Iop_V256to64_0: case Iop_V256to64_1:
++ case Iop_V256to64_2: case Iop_V256to64_3: {
++ UShort id;
++ HReg vHi, vLo, vec;
++ iselV256Expr(&vHi, &vLo, env, e->Iex.Unop.arg);
++ switch (e->Iex.Unop.op) {
++ case Iop_V256to64_0: vec = vLo; id = 0; break;
++ case Iop_V256to64_1: vec = vLo; id = 1; break;
++ case Iop_V256to64_2: vec = vHi; id = 0; break;
++ case Iop_V256to64_3: vec = vHi; id = 1; break;
++ default: vassert(0); break;
++ }
++ HReg dst = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VPICKVE2GR_D,
++ LOONGARCH64RI_I(id, 1, False), vec, dst));
++ return dst;
++ }
++ default:
++ goto irreducible;
++ }
+ }
-+ default:
-+ /*NOTREACHED*/
-+ vassert(0);
-+ break;
-+ }
-+}
-+
-+static void iselStmtLLSC ( ISelEnv* env, IRStmt* stmt )
-+{
-+ IRTemp res = stmt->Ist.LLSC.result;
-+ IRType tya = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
+
-+ /* Temporary solution; this need to be rewritten again for LOONGARCH64.
-+ On LOONGARCH64 you can not read from address that is locked with LL
-+ before SC. If you read from address that is locked than SC will fall.
-+ */
-+ if (stmt->Ist.LLSC.storedata == NULL) {
-+ /* LL */
-+ IRType ty = typeOfIRTemp(env->type_env, res);
-+ LOONGARCH64LLSCOp op;
-+ switch (ty) {
-+ case Ity_I32:
-+ op = LAllsc_LL_W;
-+ break;
-+ case Ity_I64:
-+ op = LAllsc_LL_D;
-+ break;
-+ default:
-+ vpanic("iselStmt(loongarch64): Ist_LLSC");
-+ break;
-+ }
-+ LOONGARCH64AMode* addr = iselIntExpr_AMode(env, stmt->Ist.LLSC.addr, tya);
-+ HReg val = lookupIRTemp(env, res);
-+ addInstr(env, LOONGARCH64Instr_LLSC(op, True, addr, val));
-+ } else {
-+ /* SC */
-+ IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.storedata);
-+ LOONGARCH64LLSCOp op;
-+ switch (tyd) {
-+ case Ity_I32:
-+ op = LAllsc_SC_W;
-+ break;
-+ case Ity_I64:
-+ op = LAllsc_SC_D;
-+ break;
-+ default:
-+ vpanic("iselStmt(loongarch64): Ist_LLSC");
-+ break;
++ /* --------- GET --------- */
++ case Iex_Get: {
++ Bool ri = e->Iex.Get.offset < 1024;
++ HReg dst = newVRegI(env);
++ HReg tmp;
++ LOONGARCH64AMode* am;
++ LOONGARCH64LoadOp op;
++ switch (ty) {
++ case Ity_I8:
++ op = ri ? LAload_LD_BU : LAload_LDX_BU;
++ break;
++ case Ity_I16:
++ op = ri ? LAload_LD_HU : LAload_LDX_HU;
++ break;
++ case Ity_I32:
++ op = ri ? LAload_LD_WU : LAload_LDX_WU;
++ break;
++ case Ity_I64:
++ op = ri ? LAload_LD_D : LAload_LDX_D;
++ break;
++ default:
++ goto irreducible;
++ }
++ if (ri) {
++ am = LOONGARCH64AMode_RI(hregGSP(), e->Iex.Get.offset);
++ } else {
++ tmp = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_LI(e->Iex.Get.offset, tmp));
++ am = LOONGARCH64AMode_RR(hregGSP(), tmp);
++ }
++ addInstr(env, LOONGARCH64Instr_Load(op, am, dst));
++ return dst;
+ }
-+ LOONGARCH64AMode* addr = iselIntExpr_AMode(env, stmt->Ist.LLSC.addr, tya);
-+ HReg val = iselIntExpr_R(env, stmt->Ist.LLSC.storedata);
-+ HReg dst = lookupIRTemp(env, res);
-+ HReg tmp = newVRegI(env);
-+ addInstr(env, LOONGARCH64Instr_Move(tmp, val));
-+ addInstr(env, LOONGARCH64Instr_LLSC(op, False, addr, tmp));
-+ addInstr(env, LOONGARCH64Instr_Move(dst, tmp));
-+ }
-+}
+
-+static void iselStmtCas ( ISelEnv* env, IRStmt* stmt )
-+{
-+ IRCAS* cas = stmt->Ist.CAS.details;
-+ if (cas->oldHi == IRTemp_INVALID && cas->end == Iend_LE) {
-+ /* "normal" singleton CAS */
-+ HReg old = lookupIRTemp(env, cas->oldLo);
-+ HReg addr = iselIntExpr_R(env, cas->addr);
-+ HReg expd = iselIntExpr_R(env, cas->expdLo);
-+ HReg data = iselIntExpr_R(env, cas->dataLo);
-+ IRType ty = typeOfIRTemp(env->type_env, cas->oldLo);
-+ Bool size64;
-+ switch (ty) {
-+ case Ity_I32:
-+ size64 = False;
-+ break;
-+ case Ity_I64:
-+ size64 = True;
-+ break;
-+ default:
-+ vpanic("iselStmt(loongarch64): Ist_CAS");
-+ break;
-+ }
-+ addInstr(env, LOONGARCH64Instr_Cas(old, addr, expd, data, size64));
-+ } else {
-+ vpanic("iselStmt(loongarch64): Ist_CAS");
-+ }
-+}
++ /* --------- CCALL --------- */
++ case Iex_CCall: {
++ HReg dst = newVRegI(env);
++ vassert(ty == e->Iex.CCall.retty);
+
-+static void iselStmtMBE ( ISelEnv* env, IRStmt* stmt )
-+{
-+ switch (stmt->Ist.MBE.event) {
-+ case Imbe_Fence:
-+ case Imbe_CancelReservation:
-+ addInstr(env, LOONGARCH64Instr_Bar(LAbar_DBAR, 0));
-+ break;
-+ case Imbe_InsnFence:
-+ addInstr(env, LOONGARCH64Instr_Bar(LAbar_IBAR, 0));
-+ break;
-+ default:
-+ vpanic("iselStmt(loongarch64): Ist_MBE");
-+ break;
-+ }
-+}
++ /* be very restrictive for now. Only 64-bit ints allowed for
++ args, and 64 bits for return type. Don't forget to change
++ the RetLoc if more types are allowed in future. */
++ if (e->Iex.CCall.retty != Ity_I64)
++ goto irreducible;
+
-+static void iselStmtExit ( ISelEnv* env, IRStmt* stmt )
-+{
-+ if (stmt->Ist.Exit.dst->tag != Ico_U64)
-+ vpanic("iselStmt(loongarch64): Ist_Exit: dst is not a 64-bit value");
++ /* Marshal args, do the call, clear stack. */
++ UInt addToSp = 0;
++ RetLoc rloc = mk_RetLoc_INVALID();
++ Bool ok = doHelperCall(&addToSp, &rloc, env, NULL,
++ e->Iex.CCall.cee, e->Iex.CCall.retty,
++ e->Iex.CCall.args);
+
-+ HReg cond = iselCondCode_R(env, stmt->Ist.Exit.guard);
-+ LOONGARCH64AMode* am = mkLOONGARCH64AMode_RI(hregGSP(), stmt->Ist.Exit.offsIP);
++ if (ok) {
++ vassert(is_sane_RetLoc(rloc));
++ vassert(rloc.pri == RLPri_Int);
++ vassert(addToSp == 0);
++ addInstr(env, LOONGARCH64Instr_Move(dst, hregLOONGARCH64_R4()));
++ return dst;
++ }
++ goto irreducible;
++ }
+
-+ /* Case: boring transfer to known address */
-+ if (stmt->Ist.Exit.jk == Ijk_Boring || stmt->Ist.Exit.jk == Ijk_Call) {
-+ if (env->chainingAllowed) {
-+ /* .. almost always true .. */
-+ /* Skip the event check at the dst if this is a forwards edge. */
-+ Bool toFastEP = ((Addr64)stmt->Ist.Exit.dst->Ico.U64) > env->max_ga;
-+ addInstr(env, LOONGARCH64Instr_XDirect(stmt->Ist.Exit.dst->Ico.U64,
-+ am, cond, toFastEP));
-+ } else {
-+ /* .. very occasionally .. */
-+ /* We can't use chaining, so ask for an assisted transfer,
-+ as that's the only alternative that is allowable. */
-+ HReg dst = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
-+ addInstr(env, LOONGARCH64Instr_XAssisted(dst, am, cond, Ijk_Boring));
++ /* --------- LITERAL --------- */
++ /* 64-bit literals */
++ case Iex_Const: {
++ ULong imm = 0;
++ HReg dst = newVRegI(env);
++ switch (e->Iex.Const.con->tag) {
++ case Ico_U64:
++ imm = e->Iex.Const.con->Ico.U64;
++ break;
++ case Ico_U32:
++ imm = e->Iex.Const.con->Ico.U32;
++ break;
++ case Ico_U16:
++ imm = e->Iex.Const.con->Ico.U16;
++ break;
++ case Ico_U8:
++ imm = e->Iex.Const.con->Ico.U8;
++ break;
++ default:
++ ppIRExpr(e);
++ vpanic("iselIntExpr_R.Iex_Const(loongarch64)");
++ }
++ addInstr(env, LOONGARCH64Instr_LI(imm, dst));
++ return dst;
+ }
-+ return;
-+ }
+
-+ /* Case: assisted transfer to arbitrary address */
-+ switch (stmt->Ist.Exit.jk) {
-+ /* Keep this list in sync with that for iselNext below */
-+ case Ijk_ClientReq:
-+ case Ijk_Yield:
-+ case Ijk_NoDecode:
-+ case Ijk_InvalICache:
-+ case Ijk_NoRedir:
-+ case Ijk_SigILL:
-+ case Ijk_SigTRAP:
-+ case Ijk_SigSEGV:
-+ case Ijk_SigBUS:
-+ case Ijk_SigFPE_IntDiv:
-+ case Ijk_SigFPE_IntOvf:
-+ case Ijk_SigSYS:
-+ case Ijk_Sys_syscall: {
-+ HReg dst = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
-+ addInstr(env, LOONGARCH64Instr_XAssisted(dst, am, cond, stmt->Ist.Exit.jk));
-+ break;
++ case Iex_ITE: {
++ HReg r0 = iselIntExpr_R(env, e->Iex.ITE.iffalse);
++ HReg r1 = iselIntExpr_R(env, e->Iex.ITE.iftrue);
++ HReg cond = iselCondCode_R(env, e->Iex.ITE.cond);
++ HReg dst = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_CMove(cond, r0, r1, dst, True));
++ return dst;
+ }
++
+ default:
-+ /* Do we ever expect to see any other kind? */
-+ ppIRJumpKind(stmt->Ist.Exit.jk);
-+ vpanic("iselStmt(loongarch64): Ist_Exit: unexpected jump kind");
+ break;
+ }
-+}
-+
-+static void iselStmt(ISelEnv* env, IRStmt* stmt)
-+{
-+ if (vex_traceflags & VEX_TRACE_VCODE) {
-+ vex_printf("\n-- ");
-+ ppIRStmt(stmt);
-+ vex_printf("\n");
-+ }
-+
-+ switch (stmt->tag) {
-+ /* --------- STORE --------- */
-+ /* little-endian write to memory */
-+ case Ist_Store:
-+ iselStmtStore(env, stmt);
-+ break;
-+
-+ /* --------- PUT --------- */
-+ /* write guest state, fixed offset */
-+ case Ist_Put:
-+ iselStmtPut(env, stmt);
-+ break;
-+
-+ /* --------- TMP --------- */
-+ /* assign value to temporary */
-+ case Ist_WrTmp:
-+ iselStmtTmp(env, stmt);
-+ break;
+
-+ /* --------- Call to DIRTY helper --------- */
-+ /* call complex ("dirty") helper function */
-+ case Ist_Dirty:
-+ iselStmtDirty(env, stmt);
-+ break;
++ /* We get here if no pattern matched. */
++irreducible:
++ ppIRExpr(e);
++ vpanic("iselIntExpr_R(loongarch64): cannot reduce tree");
++}
+
-+ /* --------- Load Linked and Store Conditional --------- */
-+ case Ist_LLSC:
-+ iselStmtLLSC(env, stmt);
-+ break;
++/* ------------------- CondCode ------------------- */
+
-+ /* --------- CAS --------- */
-+ case Ist_CAS:
-+ iselStmtCas(env, stmt);
-+ break;
++/* Generate code to evaluated a bit-typed expression, returning the
++ condition code which would correspond when the expression would
++ notionally have returned 1. */
+
-+ /* --------- MEM FENCE --------- */
-+ case Ist_MBE:
-+ iselStmtMBE(env, stmt);
-+ break;
++static HReg iselCondCode_R ( ISelEnv* env, IRExpr* e )
++{
++ HReg r = iselCondCode_R_wrk(env, e);
+
-+ /* --------- INSTR MARK --------- */
-+ /* Doesn't generate any executable code ... */
-+ case Ist_IMark:
-+ break;
++ /* sanity checks ... */
++ vassert(hregClass(r) == HRcInt64);
++ vassert(hregIsVirtual(r));
+
-+ /* --------- ABI HINT --------- */
-+ /* These have no meaning (denotation in the IR) and so we ignore
-+ them ... if any actually made it this far. */
-+ case Ist_AbiHint:
-+ break;
++ return r;
++}
+
-+ /* --------- NO-OP --------- */
-+ case Ist_NoOp:
-+ break;
++/* DO NOT CALL THIS DIRECTLY ! */
++static HReg iselCondCode_R_wrk ( ISelEnv* env, IRExpr* e )
++{
++ vassert(e);
++ vassert(typeOfIRExpr(env->type_env, e) == Ity_I1);
+
-+ /* --------- EXIT --------- */
-+ case Ist_Exit:
-+ iselStmtExit(env, stmt);
-+ break;
++ HReg dst = newVRegI(env);
+
-+ default:
-+ ppIRStmt(stmt);
-+ vpanic("iselStmt(loongarch64)");
-+ break;
++ /* var */
++ if (e->tag == Iex_RdTmp) {
++ HReg tmp = newVRegI(env);
++ dst = lookupIRTemp(env, e->Iex.RdTmp.tmp);
++ addInstr(env, LOONGARCH64Instr_LI(1, tmp));
++ addInstr(env, LOONGARCH64Instr_Cmp(LAcc_EQ, dst, tmp, dst));
++ return dst;
+ }
-+}
+
++ /* const */
++ if (e->tag == Iex_Const && e->Iex.Const.con->tag == Ico_U1) {
++ UInt imm = e->Iex.Const.con->Ico.U1;
++ addInstr(env, LOONGARCH64Instr_LI(imm, dst));
++ return dst;
++ }
+
-+/*---------------------------------------------------------*/
-+/*--- ISEL: Basic block terminators (Nexts) ---*/
-+/*---------------------------------------------------------*/
++ if (e->tag == Iex_Unop) {
++ if (e->Iex.Unop.op == Iop_Not1) {
++ HReg src = iselCondCode_R(env, e->Iex.Unop.arg);
++ LOONGARCH64RI* ri = LOONGARCH64RI_R(hregZERO());
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_NOR, ri, src, dst));
++ return dst;
++ }
+
-+static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk, Int offsIP )
-+{
-+ if (vex_traceflags & VEX_TRACE_VCODE) {
-+ vex_printf("\n-- PUT(%d) = ", offsIP);
-+ ppIRExpr(next);
-+ vex_printf("; exit-");
-+ ppIRJumpKind(jk);
-+ vex_printf("\n");
++ LOONGARCH64CondCode cc;
++ switch (e->Iex.Unop.op) {
++ case Iop_CmpNEZ16:
++ cc = LAcc_NE;
++ break;
++ case Iop_CmpNEZ32:
++ cc = LAcc_NE;
++ break;
++ case Iop_CmpNEZ64:
++ cc = LAcc_NE;
++ break;
++ case Iop_CmpNEZ8:
++ cc = LAcc_NE;
++ break;
++ default:
++ goto irreducible;
++ }
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_Cmp(cc, hregZERO(), src, dst));
++ return dst;
+ }
+
-+ /* Case: boring transfer to known address */
-+ if (next->tag == Iex_Const) {
-+ IRConst* cdst = next->Iex.Const.con;
-+ vassert(cdst->tag == Ico_U64);
-+ if (jk == Ijk_Boring || jk == Ijk_Call) {
-+ /* Boring transfer to known address */
-+ LOONGARCH64AMode* am = mkLOONGARCH64AMode_RI(hregGSP(), offsIP);
-+ if (env->chainingAllowed) {
-+ /* .. almost always true .. */
-+ /* Skip the event check at the dst if this is a forwards edge. */
-+ Bool toFastEP = ((Addr64)cdst->Ico.U64) > env->max_ga;
-+ addInstr(env, LOONGARCH64Instr_XDirect(cdst->Ico.U64, am,
-+ INVALID_HREG, toFastEP));
-+ } else {
-+ /* .. very occasionally .. */
-+ /* We can't use chaining, so ask for an assisted transfer,
-+ as that's the only alternative that is allowable. */
-+ HReg dst = iselIntExpr_R(env, next);
-+ addInstr(env, LOONGARCH64Instr_XAssisted(dst, am, INVALID_HREG, Ijk_Boring));
-+ }
-+ return;
++ if (e->tag == Iex_Binop) {
++ if (e->Iex.Binop.op == Iop_And1) {
++ HReg src1 = iselCondCode_R(env, e->Iex.Binop.arg1);
++ HReg src2 = iselCondCode_R(env, e->Iex.Binop.arg2);
++ LOONGARCH64RI* ri = LOONGARCH64RI_R(src2);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_AND, ri, src1, dst));
++ return dst;
++ } else if (e->Iex.Binop.op == Iop_Or1) {
++ HReg src1 = iselCondCode_R(env, e->Iex.Binop.arg1);
++ HReg src2 = iselCondCode_R(env, e->Iex.Binop.arg2);
++ LOONGARCH64RI* ri = LOONGARCH64RI_R(src2);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_OR, ri, src1, dst));
++ return dst;
++ }
++
++ Bool extend = False;
++ Bool reverse = False;
++ LOONGARCH64CondCode cc;
++ switch (e->Iex.Binop.op) {
++ case Iop_CasCmpEQ32:
++ cc = LAcc_EQ;
++ break;
++ case Iop_CasCmpEQ64:
++ cc = LAcc_EQ;
++ break;
++ case Iop_CasCmpNE32:
++ cc = LAcc_NE;
++ break;
++ case Iop_CasCmpNE64:
++ cc = LAcc_NE;
++ break;
++ case Iop_CmpEQ32:
++ cc = LAcc_EQ;
++ break;
++ case Iop_CmpEQ64:
++ cc = LAcc_EQ;
++ break;
++ case Iop_CmpLE32S:
++ cc = LAcc_GE;
++ reverse = True;
++ break;
++ case Iop_CmpLE32U:
++ cc = LAcc_GEU;
++ reverse = True;
++ break;
++ case Iop_CmpLE64S:
++ cc = LAcc_GE;
++ reverse = True;
++ break;
++ case Iop_CmpLE64U:
++ cc = LAcc_GEU;
++ reverse = True;
++ break;
++ case Iop_CmpLT32S:
++ cc = LAcc_LT;
++ extend = True;
++ break;
++ case Iop_CmpLT32U:
++ cc = LAcc_LTU;
++ extend = True;
++ break;
++ case Iop_CmpLT64S:
++ cc = LAcc_LT;
++ break;
++ case Iop_CmpLT64U:
++ cc = LAcc_LTU;
++ break;
++ case Iop_CmpNE32:
++ cc = LAcc_NE;
++ break;
++ case Iop_CmpNE64:
++ cc = LAcc_NE;
++ break;
++ default:
++ goto irreducible;
+ }
-+ }
-+
-+ /* Case: call/return (==boring) transfer to any address */
-+ switch (jk) {
-+ case Ijk_Boring:
-+ case Ijk_Ret:
-+ case Ijk_Call: {
-+ HReg dst = iselIntExpr_R(env, next);
-+ LOONGARCH64AMode* am = mkLOONGARCH64AMode_RI(hregGSP(), offsIP);
-+ if (env->chainingAllowed) {
-+ addInstr(env, LOONGARCH64Instr_XIndir(dst, am, INVALID_HREG));
-+ } else {
-+ addInstr(env, LOONGARCH64Instr_XAssisted(dst, am,
-+ INVALID_HREG, Ijk_Boring));
-+ }
-+ return;
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ HReg src2 = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ if (extend) {
++ /* Sign-extend */
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(0, 5, False);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri, src1, src1));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_SLLI_W, ri, src2, src2));
+ }
-+ default:
-+ break;
-+ }
-+
-+ /* Case: assisted transfer to arbitrary address */
-+ switch (jk) {
-+ /* Keep this list in sync with that for Ist_Exit above */
-+ case Ijk_ClientReq:
-+ case Ijk_Yield:
-+ case Ijk_NoDecode:
-+ case Ijk_InvalICache:
-+ case Ijk_NoRedir:
-+ case Ijk_SigILL:
-+ case Ijk_SigTRAP:
-+ case Ijk_SigSEGV:
-+ case Ijk_SigBUS:
-+ case Ijk_SigFPE_IntDiv:
-+ case Ijk_SigFPE_IntOvf:
-+ case Ijk_SigSYS:
-+ case Ijk_Sys_syscall: {
-+ HReg dst = iselIntExpr_R(env, next);
-+ LOONGARCH64AMode* am = mkLOONGARCH64AMode_RI(hregGSP(), offsIP);
-+ addInstr(env, LOONGARCH64Instr_XAssisted(dst, am, INVALID_HREG, jk));
-+ return;
++ if (reverse) {
++ addInstr(env, LOONGARCH64Instr_Cmp(cc, src1, src2, dst));
++ } else {
++ addInstr(env, LOONGARCH64Instr_Cmp(cc, src2, src1, dst));
+ }
-+ default:
-+ break;
++ return dst;
+ }
+
-+ vex_printf("\n-- PUT(%d) = ", offsIP);
-+ ppIRExpr(next);
-+ vex_printf("; exit-");
-+ ppIRJumpKind(jk);
-+ vex_printf("\n");
-+ vassert(0); // are we expecting any other kind?
++ /* We get here if no pattern matched. */
++irreducible:
++ ppIRExpr(e);
++ vpanic("iselCondCode(loongarch64): cannot reduce tree");
+}
+
+
+/*---------------------------------------------------------*/
-+/*--- Insn selector top-level ---*/
++/*--- ISEL: Integer expressions (128 bit) ---*/
+/*---------------------------------------------------------*/
+
-+/* Translate an entire BB to LOONGARCH64 code. */
-+HInstrArray* iselSB_LOONGARCH64 ( const IRSB* bb,
-+ VexArch arch_host,
-+ const VexArchInfo* archinfo_host,
-+ const VexAbiInfo* vbi,
-+ Int offs_Host_EvC_Counter,
-+ Int offs_Host_EvC_FailAddr,
-+ Bool chainingAllowed,
-+ Bool addProfInc,
-+ Addr max_ga )
-+{
-+ Int i, j;
-+ HReg hreg, hregHI;
-+ ISelEnv* env;
-+ UInt hwcaps_host = archinfo_host->hwcaps;
-+ LOONGARCH64AMode *amCounter, *amFailAddr;
-+
-+ /* sanity ... */
-+ vassert(arch_host == VexArchLOONGARCH64);
-+ vassert((hwcaps_host & ~(VEX_HWCAPS_LOONGARCH_CPUCFG
-+ | VEX_HWCAPS_LOONGARCH_LAM
-+ | VEX_HWCAPS_LOONGARCH_UAL
-+ | VEX_HWCAPS_LOONGARCH_FP
-+ | VEX_HWCAPS_LOONGARCH_LSX
-+ | VEX_HWCAPS_LOONGARCH_LASX
-+ | VEX_HWCAPS_LOONGARCH_COMPLEX
-+ | VEX_HWCAPS_LOONGARCH_CRYPTO
-+ | VEX_HWCAPS_LOONGARCH_LVZP
-+ | VEX_HWCAPS_LOONGARCH_X86BT
-+ | VEX_HWCAPS_LOONGARCH_ARMBT
-+ | VEX_HWCAPS_LOONGARCH_MIPSBT
-+ | VEX_HWCAPS_LOONGARCH_ISA_32BIT
-+ | VEX_HWCAPS_LOONGARCH_ISA_64BIT)) == 0);
-+
-+ /* Check that the host's endianness is as expected. */
-+ vassert(archinfo_host->endness == VexEndnessLE);
-+
-+ /* Make up an initial environment to use. */
-+ env = LibVEX_Alloc_inline(sizeof(ISelEnv));
-+ env->vreg_ctr = 0;
++/* Compute a 128-bit value into a register pair, which is returned as
++ the first two parameters. As with iselIntExpr_R, these may be
++ either real or virtual regs; in any case they must not be changed
++ by subsequent code emitted by the caller. */
+
-+ /* Set up output code array. */
-+ env->code = newHInstrArray();
++static void iselInt128Expr (HReg* hi, HReg* lo, ISelEnv* env, IRExpr* e)
++{
++ iselInt128Expr_wrk(hi, lo, env, e);
+
-+ /* Copy BB's type env. */
-+ env->type_env = bb->tyenv;
++ /* sanity checks ... */
++ vassert(hregClass(*hi) == HRcInt64);
++ vassert(hregIsVirtual(*hi));
++ vassert(hregClass(*lo) == HRcInt64);
++ vassert(hregIsVirtual(*lo));
++}
+
-+ /* Make up an IRTemp -> virtual HReg mapping. This doesn't
-+ change as we go along. */
-+ env->n_vregmap = bb->tyenv->types_used;
-+ env->vregmap = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
-+ env->vregmapHI = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
++/* DO NOT CALL THIS DIRECTLY ! */
++static void iselInt128Expr_wrk (HReg* hi, HReg* lo, ISelEnv* env, IRExpr* e)
++{
++ vassert(e);
++ vassert(typeOfIRExpr(env->type_env, e) == Ity_I128);
+
-+ /* and finally ... */
-+ env->chainingAllowed = chainingAllowed;
-+ env->hwcaps = hwcaps_host;
-+ env->max_ga = max_ga;
++ /* --------- TEMP --------- */
++ if (e->tag == Iex_RdTmp) {
++ lookupIRTempPair(hi, lo, env, e->Iex.RdTmp.tmp);
++ return;
++ }
+
-+ /* For each IR temporary, allocate a suitably-kinded virtual register. */
-+ j = 0;
-+ for (i = 0; i < env->n_vregmap; i++) {
-+ hregHI = hreg = INVALID_HREG;
-+ switch (bb->tyenv->types[i]) {
-+ case Ity_I1:
-+ case Ity_I8:
-+ case Ity_I16:
-+ case Ity_I32:
-+ case Ity_I64:
-+ hreg = mkHReg(True, HRcInt64, 0, j++);
-+ break;
-+ case Ity_I128:
-+ hreg = mkHReg(True, HRcInt64, 0, j++);
-+ hregHI = mkHReg(True, HRcInt64, 0, j++);
-+ break;
-+ case Ity_F16: // we'll use HRcFlt64 regs for F16 too
-+ case Ity_F32: // we'll use HRcFlt64 regs for F32 too
-+ case Ity_F64:
-+ hreg = mkHReg(True, HRcFlt64, 0, j++);
-+ break;
-+ case Ity_V128:
-+ hreg = mkHReg(True, HRcVec128, 0, j++);
-+ break;
-+ case Ity_V256:
-+ hreg = mkHReg(True, HRcVec128, 0, j++);
-+ hregHI = mkHReg(True, HRcVec128, 0, j++);
-+ break;
++ /* --------- BINARY OP --------- */
++ if (e->tag == Iex_Binop) {
++ switch (e->Iex.Binop.op) {
++ case Iop_64HLto128: {
++ *hi = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ *lo = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ return;
++ }
++ case Iop_DivModS64to64: {
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
++ HReg dstLo = newVRegI(env);
++ HReg dstHi = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_D, src2, src1, dstLo));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MOD_D, src2, src1, dstHi));
++ *hi = dstHi;
++ *lo = dstLo;
++ return;
++ }
++ case Iop_DivModU64to64: {
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
++ HReg dstLo = newVRegI(env);
++ HReg dstHi = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_DIV_DU, src2, src1, dstLo));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MOD_DU, src2, src1, dstHi));
++ *hi = dstHi;
++ *lo = dstLo;
++ return;
++ }
++ case Iop_MullS64: {
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
++ HReg dstLo = newVRegI(env);
++ HReg dstHi = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MUL_D, src2, src1, dstLo));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MULH_D, src2, src1, dstHi));
++ *hi = dstHi;
++ *lo = dstLo;
++ return;
++ }
++ case Iop_MullU64: {
++ HReg src1 = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, 0, False);
++ HReg dstLo = newVRegI(env);
++ HReg dstHi = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MUL_D, src2, src1, dstLo));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_MULH_DU, src2, src1, dstHi));
++ *hi = dstHi;
++ *lo = dstLo;
++ return;
++ }
+ default:
-+ ppIRType(bb->tyenv->types[i]);
-+ vpanic("iselBB(loongarch64): IRTemp type");
-+ break;
++ goto irreducible;
+ }
-+ env->vregmap[i] = hreg;
-+ env->vregmapHI[i] = hregHI;
+ }
-+ env->vreg_ctr = j;
+
-+ /* The very first instruction must be an event check. */
-+ amCounter = mkLOONGARCH64AMode_RI(hregGSP(), offs_Host_EvC_Counter);
-+ amFailAddr = mkLOONGARCH64AMode_RI(hregGSP(), offs_Host_EvC_FailAddr);
-+ addInstr(env, LOONGARCH64Instr_EvCheck(amCounter, amFailAddr));
++ /* We get here if no pattern matched. */
++irreducible:
++ ppIRExpr(e);
++ vpanic("iselInt128Expr(loongarch64): cannot reduce tree");
++}
+
-+ /* Possibly a block counter increment (for profiling). At this
-+ point we don't know the address of the counter, so just pretend
-+ it is zero. It will have to be patched later, but before this
-+ translation is used, by a call to LibVEX_patchProfCtr. */
-+ if (addProfInc) {
-+ addInstr(env, LOONGARCH64Instr_ProfInc());
-+ }
+
-+ /* Ok, finally we can iterate over the statements. */
-+ for (i = 0; i < bb->stmts_used; i++)
-+ iselStmt(env, bb->stmts[i]);
++/*---------------------------------------------------------*/
++/*--- ISEL: Floating point expressions (64/32 bit) ---*/
++/*---------------------------------------------------------*/
+
-+ iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
++/* Compute a floating point value into a register, the identity of
++ which is returned. As with iselIntExpr_R, the reg may be either
++ real or virtual; in any case it must not be changed by subsequent
++ code emitted by the caller. */
+
-+ /* record the number of vregs we used. */
-+ env->code->n_vregs = env->vreg_ctr;
-+ return env->code;
++static HReg iselFltExpr ( ISelEnv* env, IRExpr* e )
++{
++ HReg r = iselFltExpr_wrk(env, e);
++
++ /* sanity checks ... */
++ vassert(hregClass(r) == HRcFlt64);
++ vassert(hregIsVirtual(r));
++
++ return r;
+}
+
++/* DO NOT CALL THIS DIRECTLY */
++static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
++{
++ IRType ty = typeOfIRExpr(env->type_env, e);
++ vassert(e);
++ vassert(ty == Ity_F32 || ty == Ity_F64);
+
-+/*---------------------------------------------------------------*/
-+/*--- end host_loongarch64_isel.c ---*/
-+/*---------------------------------------------------------------*/
-diff --git a/VEX/priv/ir_defs.c b/VEX/priv/ir_defs.c
-index 31710eb..d6b245f 100644
---- a/VEX/priv/ir_defs.c
-+++ b/VEX/priv/ir_defs.c
-@@ -280,6 +280,8 @@ void ppIROp ( IROp op )
- case Iop_SubF64: vex_printf("SubF64"); return;
- case Iop_MulF64: vex_printf("MulF64"); return;
- case Iop_DivF64: vex_printf("DivF64"); return;
-+ case Iop_ScaleBF64: vex_printf("ScaleBF64"); return;
-+ case Iop_ScaleBF32: vex_printf("ScaleBF32"); return;
- case Iop_AddF64r32: vex_printf("AddF64r32"); return;
- case Iop_SubF64r32: vex_printf("SubF64r32"); return;
- case Iop_MulF64r32: vex_printf("MulF64r32"); return;
-@@ -356,6 +358,10 @@ void ppIROp ( IROp op )
- case Iop_SqrtF64: vex_printf("SqrtF64"); return;
- case Iop_SqrtF32: vex_printf("SqrtF32"); return;
- case Iop_SqrtF16: vex_printf("SqrtF16"); return;
-+ case Iop_RSqrtF32: vex_printf("RSqrtF32"); return;
-+ case Iop_RSqrtF64: vex_printf("RSqrtF64"); return;
-+ case Iop_LogBF32: vex_printf("LogBF32"); return;
-+ case Iop_LogBF64: vex_printf("LogBF64"); return;
- case Iop_SinF64: vex_printf("SinF64"); return;
- case Iop_CosF64: vex_printf("CosF64"); return;
- case Iop_TanF64: vex_printf("TanF64"); return;
-@@ -379,8 +385,12 @@ void ppIROp ( IROp op )
-
- case Iop_MaxNumF64: vex_printf("MaxNumF64"); return;
- case Iop_MinNumF64: vex_printf("MinNumF64"); return;
-+ case Iop_MaxNumAbsF64: vex_printf("MaxNumAbsF64"); return;
-+ case Iop_MinNumAbsF64: vex_printf("MinNumAbsF64"); return;
- case Iop_MaxNumF32: vex_printf("MaxNumF32"); return;
- case Iop_MinNumF32: vex_printf("MinNumF32"); return;
-+ case Iop_MaxNumAbsF32: vex_printf("MaxNumAbsF32"); return;
-+ case Iop_MinNumAbsF32: vex_printf("MinNumAbsF32"); return;
-
- case Iop_F16toF64: vex_printf("F16toF64"); return;
- case Iop_F64toF16: vex_printf("F64toF16"); return;
-@@ -1307,16 +1317,20 @@ void ppIROp ( IROp op )
- case Iop_Max8Sx32: vex_printf("Max8Sx32"); return;
- case Iop_Max16Sx16: vex_printf("Max16Sx16"); return;
- case Iop_Max32Sx8: vex_printf("Max32Sx8"); return;
-+ case Iop_Max64Sx4: vex_printf("Max64Sx4"); return;
- case Iop_Max8Ux32: vex_printf("Max8Ux32"); return;
- case Iop_Max16Ux16: vex_printf("Max16Ux16"); return;
- case Iop_Max32Ux8: vex_printf("Max32Ux8"); return;
-+ case Iop_Max64Ux4: vex_printf("Max64Ux4"); return;
-
- case Iop_Min8Sx32: vex_printf("Min8Sx32"); return;
- case Iop_Min16Sx16: vex_printf("Min16Sx16"); return;
- case Iop_Min32Sx8: vex_printf("Min32Sx8"); return;
-+ case Iop_Min64Sx4: vex_printf("Min64Sx4"); return;
- case Iop_Min8Ux32: vex_printf("Min8Ux32"); return;
- case Iop_Min16Ux16: vex_printf("Min16Ux16"); return;
- case Iop_Min32Ux8: vex_printf("Min32Ux8"); return;
-+ case Iop_Min64Ux4: vex_printf("Min64Ux4"); return;
-
- case Iop_CmpEQ8x32: vex_printf("CmpEQ8x32"); return;
- case Iop_CmpEQ16x16: vex_printf("CmpEQ16x16"); return;
-@@ -1434,10 +1448,13 @@ Bool primopMightTrap ( IROp op )
- case Iop_1Uto8: case Iop_1Uto32: case Iop_1Uto64: case Iop_1Sto8:
- case Iop_1Sto16: case Iop_1Sto32: case Iop_1Sto64:
- case Iop_AddF64: case Iop_SubF64: case Iop_MulF64: case Iop_DivF64:
-+ case Iop_ScaleBF64: case Iop_ScaleBF32:
- case Iop_AddF32: case Iop_SubF32: case Iop_MulF32: case Iop_DivF32:
- case Iop_AddF64r32: case Iop_SubF64r32: case Iop_MulF64r32:
- case Iop_DivF64r32: case Iop_NegF64: case Iop_AbsF64:
- case Iop_NegF32: case Iop_AbsF32: case Iop_SqrtF64: case Iop_SqrtF32:
-+ case Iop_RSqrtF64: case Iop_RSqrtF32:
-+ case Iop_LogBF64: case Iop_LogBF32:
- case Iop_NegF16: case Iop_AbsF16: case Iop_SqrtF16: case Iop_SubF16:
- case Iop_AddF16:
- case Iop_CmpF64: case Iop_CmpF32: case Iop_CmpF16: case Iop_CmpF128:
-@@ -1477,8 +1494,11 @@ Bool primopMightTrap ( IROp op )
- case Iop_RSqrtEst5GoodF64: case Iop_RoundF64toF64_NEAREST:
- case Iop_RoundF64toF64_NegINF: case Iop_RoundF64toF64_PosINF:
- case Iop_RoundF64toF64_ZERO: case Iop_TruncF64asF32: case Iop_RoundF64toF32:
-- case Iop_RecpExpF64: case Iop_RecpExpF32: case Iop_MaxNumF64:
-- case Iop_MinNumF64: case Iop_MaxNumF32: case Iop_MinNumF32:
-+ case Iop_RecpExpF64: case Iop_RecpExpF32:
-+ case Iop_MaxNumF64: case Iop_MinNumF64:
-+ case Iop_MaxNumAbsF64: case Iop_MinNumAbsF64:
-+ case Iop_MaxNumF32: case Iop_MinNumF32:
-+ case Iop_MaxNumAbsF32: case Iop_MinNumAbsF32:
- case Iop_F16toF64: case Iop_F64toF16: case Iop_F16toF32:
- case Iop_F32toF16: case Iop_QAdd32S: case Iop_QSub32S:
- case Iop_Add16x2: case Iop_Sub16x2:
-@@ -1786,10 +1806,10 @@ Bool primopMightTrap ( IROp op )
- case Iop_ShlN16x16: case Iop_ShlN32x8: case Iop_ShlN64x4:
- case Iop_ShrN16x16: case Iop_ShrN32x8: case Iop_ShrN64x4:
- case Iop_SarN16x16: case Iop_SarN32x8:
-- case Iop_Max8Sx32: case Iop_Max16Sx16: case Iop_Max32Sx8:
-- case Iop_Max8Ux32: case Iop_Max16Ux16: case Iop_Max32Ux8:
-- case Iop_Min8Sx32: case Iop_Min16Sx16: case Iop_Min32Sx8:
-- case Iop_Min8Ux32: case Iop_Min16Ux16: case Iop_Min32Ux8:
-+ case Iop_Max8Sx32: case Iop_Max16Sx16: case Iop_Max32Sx8: case Iop_Max64Sx4:
-+ case Iop_Max8Ux32: case Iop_Max16Ux16: case Iop_Max32Ux8: case Iop_Max64Ux4:
-+ case Iop_Min8Sx32: case Iop_Min16Sx16: case Iop_Min32Sx8: case Iop_Min64Sx4:
-+ case Iop_Min8Ux32: case Iop_Min16Ux16: case Iop_Min32Ux8: case Iop_Min64Ux4:
- case Iop_Mul16x16: case Iop_Mul32x8:
- case Iop_MulHi16Ux16: case Iop_MulHi16Sx16:
- case Iop_QAdd8Ux32: case Iop_QAdd16Ux16:
-@@ -2075,6 +2095,7 @@ void ppIRJumpKind ( IRJumpKind kind )
- case Ijk_SigFPE: vex_printf("SigFPE"); break;
- case Ijk_SigFPE_IntDiv: vex_printf("SigFPE_IntDiv"); break;
- case Ijk_SigFPE_IntOvf: vex_printf("SigFPE_IntOvf"); break;
-+ case Ijk_SigSYS: vex_printf("SigSYS"); break;
- case Ijk_Sys_syscall: vex_printf("Sys_syscall"); break;
- case Ijk_Sys_int32: vex_printf("Sys_int32"); break;
- case Ijk_Sys_int128: vex_printf("Sys_int128"); break;
-@@ -2094,6 +2115,8 @@ void ppIRMBusEvent ( IRMBusEvent event )
- vex_printf("Fence"); break;
- case Imbe_CancelReservation:
- vex_printf("CancelReservation"); break;
-+ case Imbe_InsnFence:
-+ vex_printf("InsnFence"); break;
- default:
- vpanic("ppIRMBusEvent");
- }
-@@ -3372,12 +3395,14 @@ void typeOfPrimop ( IROp op,
-
- case Iop_AddF64: case Iop_SubF64:
- case Iop_MulF64: case Iop_DivF64:
-+ case Iop_ScaleBF64:
- case Iop_AddF64r32: case Iop_SubF64r32:
- case Iop_MulF64r32: case Iop_DivF64r32:
- TERNARY(ity_RMode,Ity_F64,Ity_F64, Ity_F64);
-
- case Iop_AddF32: case Iop_SubF32:
- case Iop_MulF32: case Iop_DivF32:
-+ case Iop_ScaleBF32:
- TERNARY(ity_RMode,Ity_F32,Ity_F32, Ity_F32);
-
- case Iop_AddF16:
-@@ -3394,10 +3419,14 @@ void typeOfPrimop ( IROp op,
- UNARY(Ity_F16, Ity_F16);
-
- case Iop_SqrtF64:
-+ case Iop_RSqrtF64:
-+ case Iop_LogBF64:
- case Iop_RecpExpF64:
- BINARY(ity_RMode,Ity_F64, Ity_F64);
-
- case Iop_SqrtF32:
-+ case Iop_RSqrtF32:
-+ case Iop_LogBF32:
- case Iop_RoundF32toInt:
- case Iop_RecpExpF32:
- BINARY(ity_RMode,Ity_F32, Ity_F32);
-@@ -3406,9 +3435,11 @@ void typeOfPrimop ( IROp op,
- BINARY(ity_RMode, Ity_F16, Ity_F16);
-
- case Iop_MaxNumF64: case Iop_MinNumF64:
-+ case Iop_MaxNumAbsF64: case Iop_MinNumAbsF64:
- BINARY(Ity_F64,Ity_F64, Ity_F64);
-
- case Iop_MaxNumF32: case Iop_MinNumF32:
-+ case Iop_MaxNumAbsF32: case Iop_MinNumAbsF32:
- BINARY(Ity_F32,Ity_F32, Ity_F32);
-
- case Iop_CmpF16:
-@@ -4098,10 +4129,10 @@ void typeOfPrimop ( IROp op,
- case Iop_Mul16x16: case Iop_Mul32x8:
- case Iop_MulHi16Ux16: case Iop_MulHi16Sx16:
- case Iop_Avg8Ux32: case Iop_Avg16Ux16:
-- case Iop_Max8Sx32: case Iop_Max16Sx16: case Iop_Max32Sx8:
-- case Iop_Max8Ux32: case Iop_Max16Ux16: case Iop_Max32Ux8:
-- case Iop_Min8Sx32: case Iop_Min16Sx16: case Iop_Min32Sx8:
-- case Iop_Min8Ux32: case Iop_Min16Ux16: case Iop_Min32Ux8:
-+ case Iop_Max8Sx32: case Iop_Max16Sx16: case Iop_Max32Sx8: case Iop_Max64Sx4:
-+ case Iop_Max8Ux32: case Iop_Max16Ux16: case Iop_Max32Ux8: case Iop_Max64Ux4:
-+ case Iop_Min8Sx32: case Iop_Min16Sx16: case Iop_Min32Sx8: case Iop_Min64Sx4:
-+ case Iop_Min8Ux32: case Iop_Min16Ux16: case Iop_Min32Ux8: case Iop_Min64Ux4:
- case Iop_CmpEQ8x32: case Iop_CmpEQ16x16:
- case Iop_CmpEQ32x8: case Iop_CmpEQ64x4:
- case Iop_CmpGT8Sx32: case Iop_CmpGT16Sx16:
-@@ -5245,7 +5276,9 @@ void tcStmt ( const IRSB* bb, const IRStmt* stmt, IRType gWordTy )
- break;
- case Ist_MBE:
- switch (stmt->Ist.MBE.event) {
-- case Imbe_Fence: case Imbe_CancelReservation:
-+ case Imbe_Fence:
-+ case Imbe_CancelReservation:
-+ case Imbe_InsnFence:
- break;
- default: sanityCheckFail(bb,stmt,"IRStmt.MBE.event: unknown");
- break;
-diff --git a/VEX/priv/main_main.c b/VEX/priv/main_main.c
-index 482047c..98d4a81 100644
---- a/VEX/priv/main_main.c
-+++ b/VEX/priv/main_main.c
-@@ -43,6 +43,7 @@
- #include "libvex_guest_s390x.h"
- #include "libvex_guest_mips32.h"
- #include "libvex_guest_mips64.h"
-+#include "libvex_guest_loongarch64.h"
-
- #include "main_globals.h"
- #include "main_util.h"
-@@ -57,6 +58,7 @@
- #include "host_s390_defs.h"
- #include "host_mips_defs.h"
- #include "host_nanomips_defs.h"
-+#include "host_loongarch64_defs.h"
-
- #include "guest_generic_bb_to_IR.h"
- #include "guest_x86_defs.h"
-@@ -67,6 +69,7 @@
- #include "guest_s390_defs.h"
- #include "guest_mips_defs.h"
- #include "guest_nanomips_defs.h"
-+#include "guest_loongarch64_defs.h"
-
- #include "host_generic_simd128.h"
-
-@@ -163,6 +166,14 @@
- #define NANOMIPSST(f) vassert(0)
- #endif
-
-+#if defined(VGA_loongarch64) || defined(VEXMULTIARCH)
-+#define LOONGARCH64FN(f) f
-+#define LOONGARCH64ST(f) f
-+#else
-+#define LOONGARCH64FN(f) NULL
-+#define LOONGARCH64ST(f) vassert(0)
-+#endif
++ switch (e->tag) {
++ /* --------- TEMP --------- */
++ case Iex_RdTmp:
++ return lookupIRTemp(env, e->Iex.RdTmp.tmp);
++
++ /* --------- LOAD --------- */
++ case Iex_Load: {
++ if (e->Iex.Load.end != Iend_LE)
++ goto irreducible;
++
++ LOONGARCH64AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr, ty);
++ HReg dst = newVRegF(env);
++ LOONGARCH64FpLoadOp op;
++ switch (ty) {
++ case Ity_F32:
++ op = (am->tag == LAam_RI) ? LAfpload_FLD_S : LAfpload_FLDX_S;
++ break;
++ case Ity_F64:
++ op = (am->tag == LAam_RI) ? LAfpload_FLD_D : LAfpload_FLDX_D;
++ break;
++ default:
++ goto irreducible;
++ }
++ addInstr(env, LOONGARCH64Instr_FpLoad(op, am, dst));
++ return dst;
++ }
+
- /* This file contains the top level interface to the library. */
-
- /* --------- fwds ... --------- */
-@@ -541,6 +552,23 @@ IRSB* LibVEX_FrontEnd ( /*MOD*/ VexTranslateArgs* vta,
- vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4);
- break;
-
-+ case VexArchLOONGARCH64:
-+ preciseMemExnsFn
-+ = LOONGARCH64FN(guest_loongarch64_state_requires_precise_mem_exns);
-+ disInstrFn = LOONGARCH64FN(disInstr_LOONGARCH64);
-+ specHelper = LOONGARCH64FN(guest_loongarch64_spechelper);
-+ guest_layout = LOONGARCH64FN(&loongarch64Guest_layout);
-+ offB_CMSTART = offsetof(VexGuestLOONGARCH64State, guest_CMSTART);
-+ offB_CMLEN = offsetof(VexGuestLOONGARCH64State, guest_CMLEN);
-+ offB_GUEST_IP = offsetof(VexGuestLOONGARCH64State, guest_PC);
-+ szB_GUEST_IP = sizeof( ((VexGuestLOONGARCH64State*)0)->guest_PC );
-+ vassert(vta->archinfo_guest.endness == VexEndnessLE);
-+ vassert(sizeof(VexGuestLOONGARCH64State) % LibVEX_GUEST_STATE_ALIGN == 0);
-+ vassert(sizeof( ((VexGuestLOONGARCH64State*)0)->guest_CMSTART) == 8);
-+ vassert(sizeof( ((VexGuestLOONGARCH64State*)0)->guest_CMLEN ) == 8);
-+ vassert(sizeof( ((VexGuestLOONGARCH64State*)0)->guest_NRADDR ) == 8);
-+ break;
++ /* --------- GET --------- */
++ case Iex_Get: {
++ Bool ri = e->Iex.Get.offset < 1024;
++ HReg dst = newVRegF(env);
++ HReg tmp;
++ LOONGARCH64AMode* am;
++ LOONGARCH64FpLoadOp op;
++ switch (ty) {
++ case Ity_F32:
++ op = ri ? LAfpload_FLD_S : LAfpload_FLDX_S;
++ break;
++ case Ity_F64:
++ op = ri ? LAfpload_FLD_D : LAfpload_FLDX_D;
++ break;
++ default:
++ goto irreducible;
++ }
++ if (ri) {
++ am = LOONGARCH64AMode_RI(hregGSP(), e->Iex.Get.offset);
++ } else {
++ tmp = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_LI(e->Iex.Get.offset, tmp));
++ am = LOONGARCH64AMode_RR(hregGSP(), tmp);
++ }
++ addInstr(env, LOONGARCH64Instr_FpLoad(op, am, dst));
++ return dst;
++ }
+
- default:
- vpanic("LibVEX_Translate: unsupported guest insn set");
- }
-@@ -878,6 +906,14 @@ static void libvex_BackEnd ( const VexTranslateArgs *vta,
- offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR);
- break;
-
-+ case VexArchLOONGARCH64:
-+ preciseMemExnsFn
-+ = LOONGARCH64FN(guest_loongarch64_state_requires_precise_mem_exns);
-+ guest_sizeB = sizeof(VexGuestLOONGARCH64State);
-+ offB_HOST_EvC_COUNTER = offsetof(VexGuestLOONGARCH64State, host_EvC_COUNTER);
-+ offB_HOST_EvC_FAILADDR = offsetof(VexGuestLOONGARCH64State, host_EvC_FAILADDR);
-+ break;
++ /* --------- QUATERNARY OP --------- */
++ case Iex_Qop: {
++ switch (e->Iex.Qop.details->op) {
++ case Iop_MAddF32: {
++ HReg dst = newVRegF(env);
++ HReg src1 = iselFltExpr(env, e->Iex.Qop.details->arg2);
++ HReg src2 = iselFltExpr(env, e->Iex.Qop.details->arg3);
++ HReg src3 = iselFltExpr(env, e->Iex.Qop.details->arg4);
++ set_rounding_mode(env, e->Iex.Qop.details->arg1);
++ addInstr(env, LOONGARCH64Instr_FpTrinary(LAfpbin_FMADD_S, src3, src2, src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_MAddF64: {
++ HReg dst = newVRegF(env);
++ HReg src1 = iselFltExpr(env, e->Iex.Qop.details->arg2);
++ HReg src2 = iselFltExpr(env, e->Iex.Qop.details->arg3);
++ HReg src3 = iselFltExpr(env, e->Iex.Qop.details->arg4);
++ set_rounding_mode(env, e->Iex.Qop.details->arg1);
++ addInstr(env, LOONGARCH64Instr_FpTrinary(LAfpbin_FMADD_D, src3, src2, src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_MSubF32: {
++ HReg dst = newVRegF(env);
++ HReg src1 = iselFltExpr(env, e->Iex.Qop.details->arg2);
++ HReg src2 = iselFltExpr(env, e->Iex.Qop.details->arg3);
++ HReg src3 = iselFltExpr(env, e->Iex.Qop.details->arg4);
++ set_rounding_mode(env, e->Iex.Qop.details->arg1);
++ addInstr(env, LOONGARCH64Instr_FpTrinary(LAfpbin_FMSUB_S, src3, src2, src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_MSubF64: {
++ HReg dst = newVRegF(env);
++ HReg src1 = iselFltExpr(env, e->Iex.Qop.details->arg2);
++ HReg src2 = iselFltExpr(env, e->Iex.Qop.details->arg3);
++ HReg src3 = iselFltExpr(env, e->Iex.Qop.details->arg4);
++ set_rounding_mode(env, e->Iex.Qop.details->arg1);
++ addInstr(env, LOONGARCH64Instr_FpTrinary(LAfpbin_FMSUB_D, src3, src2, src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ default:
++ goto irreducible;
++ }
++ }
+
- default:
- vpanic("LibVEX_Codegen: unsupported guest insn set");
- }
-@@ -1052,6 +1088,23 @@ static void libvex_BackEnd ( const VexTranslateArgs *vta,
- || vta->archinfo_host.endness == VexEndnessBE);
- break;
-
-+ case VexArchLOONGARCH64:
-+ mode64 = True;
-+ rRegUniv = LOONGARCH64FN(getRRegUniverse_LOONGARCH64());
-+ getRegUsage
-+ = CAST_TO_TYPEOF(getRegUsage) LOONGARCH64FN(getRegUsage_LOONGARCH64Instr);
-+ mapRegs = CAST_TO_TYPEOF(mapRegs) LOONGARCH64FN(mapRegs_LOONGARCH64Instr);
-+ genSpill = CAST_TO_TYPEOF(genSpill) LOONGARCH64FN(genSpill_LOONGARCH64);
-+ genReload = CAST_TO_TYPEOF(genReload) LOONGARCH64FN(genReload_LOONGARCH64);
-+ genMove = CAST_TO_TYPEOF(genMove) LOONGARCH64FN(genMove_LOONGARCH64);
-+ ppInstr = CAST_TO_TYPEOF(ppInstr) LOONGARCH64FN(ppLOONGARCH64Instr);
-+ ppReg = CAST_TO_TYPEOF(ppReg) LOONGARCH64FN(ppHRegLOONGARCH64);
-+ iselSB = LOONGARCH64FN(iselSB_LOONGARCH64);
-+ emit = CAST_TO_TYPEOF(emit) LOONGARCH64FN(emit_LOONGARCH64Instr);
-+ vassert(vta->archinfo_host.endness == VexEndnessLE
-+ || vta->archinfo_host.endness == VexEndnessBE);
-+ break;
++ /* --------- TERNARY OP --------- */
++ case Iex_Triop: {
++ switch (e->Iex.Triop.details->op) {
++ case Iop_AddF32: {
++ HReg dst = newVRegF(env);
++ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
++ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
++ set_rounding_mode(env, e->Iex.Triop.details->arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FADD_S, src2, src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_AddF64: {
++ HReg dst = newVRegF(env);
++ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
++ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
++ set_rounding_mode(env, e->Iex.Triop.details->arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FADD_D, src2, src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_DivF32: {
++ HReg dst = newVRegF(env);
++ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
++ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
++ set_rounding_mode(env, e->Iex.Triop.details->arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FDIV_S, src2, src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_DivF64: {
++ HReg dst = newVRegF(env);
++ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
++ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
++ set_rounding_mode(env, e->Iex.Triop.details->arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FDIV_D, src2, src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_MulF32: {
++ HReg dst = newVRegF(env);
++ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
++ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
++ set_rounding_mode(env, e->Iex.Triop.details->arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMUL_S, src2, src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_MulF64: {
++ HReg dst = newVRegF(env);
++ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
++ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
++ set_rounding_mode(env, e->Iex.Triop.details->arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMUL_D, src2, src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_ScaleBF32: {
++ HReg dst = newVRegF(env);
++ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
++ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
++ set_rounding_mode(env, e->Iex.Triop.details->arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FSCALEB_S, src2, src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_ScaleBF64: {
++ HReg dst = newVRegF(env);
++ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
++ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
++ set_rounding_mode(env, e->Iex.Triop.details->arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FSCALEB_D, src2, src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_SubF32: {
++ HReg dst = newVRegF(env);
++ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
++ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
++ set_rounding_mode(env, e->Iex.Triop.details->arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FSUB_S, src2, src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_SubF64: {
++ HReg dst = newVRegF(env);
++ HReg src1 = iselFltExpr(env, e->Iex.Triop.details->arg2);
++ HReg src2 = iselFltExpr(env, e->Iex.Triop.details->arg3);
++ set_rounding_mode(env, e->Iex.Triop.details->arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FSUB_D, src2, src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ default:
++ goto irreducible;
++ }
++ }
+
- default:
- vpanic("LibVEX_Translate: unsupported host insn set");
- }
-@@ -1297,6 +1350,11 @@ VexInvalRange LibVEX_Chain ( VexArch arch_host,
- place_to_chain,
- disp_cp_chain_me_EXPECTED,
- place_to_jump_to));
-+ case VexArchLOONGARCH64:
-+ LOONGARCH64ST(return chainXDirect_LOONGARCH64(endness_host,
-+ place_to_chain,
-+ disp_cp_chain_me_EXPECTED,
-+ place_to_jump_to));
- default:
- vassert(0);
- }
-@@ -1359,6 +1417,11 @@ VexInvalRange LibVEX_UnChain ( VexArch arch_host,
- place_to_unchain,
- place_to_jump_to_EXPECTED,
- disp_cp_chain_me));
-+ case VexArchLOONGARCH64:
-+ LOONGARCH64ST(return unchainXDirect_LOONGARCH64(endness_host,
-+ place_to_unchain,
-+ place_to_jump_to_EXPECTED,
-+ disp_cp_chain_me));
- default:
- vassert(0);
- }
-@@ -1389,6 +1452,8 @@ Int LibVEX_evCheckSzB ( VexArch arch_host )
- MIPS64ST(cached = evCheckSzB_MIPS()); break;
- case VexArchNANOMIPS:
- NANOMIPSST(cached = evCheckSzB_NANOMIPS()); break;
-+ case VexArchLOONGARCH64:
-+ LOONGARCH64ST(cached = evCheckSzB_LOONGARCH64()); break;
- default:
- vassert(0);
- }
-@@ -1432,6 +1497,10 @@ VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
- case VexArchNANOMIPS:
- NANOMIPSST(return patchProfInc_NANOMIPS(endness_host, place_to_patch,
- location_of_counter));
-+ case VexArchLOONGARCH64:
-+ LOONGARCH64ST(return patchProfInc_LOONGARCH64(endness_host,
-+ place_to_patch,
-+ location_of_counter));
- default:
- vassert(0);
- }
-@@ -1515,6 +1584,7 @@ const HChar* LibVEX_ppVexArch ( VexArch arch )
- case VexArchMIPS32: return "MIPS32";
- case VexArchMIPS64: return "MIPS64";
- case VexArchNANOMIPS: return "NANOMIPS";
-+ case VexArchLOONGARCH64: return "LOONGARCH64";
- default: return "VexArch???";
- }
- }
-@@ -1585,6 +1655,7 @@ static IRType arch_word_size (VexArch arch) {
- case VexArchMIPS64:
- case VexArchPPC64:
- case VexArchS390X:
-+ case VexArchLOONGARCH64:
- return Ity_I64;
-
- default:
-@@ -1925,6 +1996,38 @@ static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
- return "Unsupported baseline";
- }
-
-+static const HChar* show_hwcaps_loongarch64 ( UInt hwcaps )
-+{
-+ static const HChar prefix[] = "loongarch64";
-+ static const struct {
-+ UInt hwcaps_bit;
-+ HChar name[16];
-+ } hwcaps_list[] = {
-+ { VEX_HWCAPS_LOONGARCH_CPUCFG, "cpucfg" },
-+ { VEX_HWCAPS_LOONGARCH_LAM, "lam" },
-+ { VEX_HWCAPS_LOONGARCH_UAL, "ual" },
-+ { VEX_HWCAPS_LOONGARCH_FP, "fpu" },
-+ { VEX_HWCAPS_LOONGARCH_LSX, "lsx" },
-+ { VEX_HWCAPS_LOONGARCH_LASX, "lasx" },
-+ { VEX_HWCAPS_LOONGARCH_COMPLEX, "complex" },
-+ { VEX_HWCAPS_LOONGARCH_CRYPTO, "crypto" },
-+ { VEX_HWCAPS_LOONGARCH_LVZP, "lvz" },
-+ { VEX_HWCAPS_LOONGARCH_X86BT, "lbt_x86" },
-+ { VEX_HWCAPS_LOONGARCH_ARMBT, "lbt_arm" },
-+ { VEX_HWCAPS_LOONGARCH_MIPSBT, "lbt_mips" }
-+ };
-+ static HChar buf[sizeof(prefix) +
-+ NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
++ /* --------- BINARY OP --------- */
++ case Iex_Binop: {
++ switch (e->Iex.Binop.op) {
++ case Iop_F64toF32: {
++ HReg dst = newVRegF(env);
++ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FCVT_S_D, src, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_I32StoF32: {
++ HReg tmp = newVRegF(env);
++ HReg dst = newVRegF(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_D, src, tmp));
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FFINT_S_W, tmp, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_I64StoF32: {
++ HReg tmp = newVRegF(env);
++ HReg dst = newVRegF(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_D, src, tmp));
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FFINT_S_L, tmp, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_I64StoF64: {
++ HReg tmp = newVRegF(env);
++ HReg dst = newVRegF(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_D, src, tmp));
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FFINT_D_L, tmp, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_LogBF32: {
++ HReg dst = newVRegF(env);
++ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FLOGB_S, src, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_LogBF64: {
++ HReg dst = newVRegF(env);
++ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FLOGB_D, src, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_MaxNumAbsF32: {
++ HReg dst = newVRegF(env);
++ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
++ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMAXA_S, src2, src1, dst));
++ return dst;
++ }
++ case Iop_MaxNumF32: {
++ HReg dst = newVRegF(env);
++ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
++ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMAX_S, src2, src1, dst));
++ return dst;
++ }
++ case Iop_MaxNumAbsF64: {
++ HReg dst = newVRegF(env);
++ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
++ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMAXA_D, src2, src1, dst));
++ return dst;
++ }
++ case Iop_MaxNumF64: {
++ HReg dst = newVRegF(env);
++ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
++ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMAX_D, src2, src1, dst));
++ return dst;
++ }
++ case Iop_MinNumAbsF32: {
++ HReg dst = newVRegF(env);
++ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
++ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMINA_S, src2, src1, dst));
++ return dst;
++ }
++ case Iop_MinNumF32: {
++ HReg dst = newVRegF(env);
++ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
++ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMIN_S, src2, src1, dst));
++ return dst;
++ }
++ case Iop_MinNumAbsF64: {
++ HReg dst = newVRegF(env);
++ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
++ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMINA_D, src2, src1, dst));
++ return dst;
++ }
++ case Iop_MinNumF64: {
++ HReg dst = newVRegF(env);
++ HReg src2 = iselFltExpr(env, e->Iex.Binop.arg2);
++ HReg src1 = iselFltExpr(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpBinary(LAfpbin_FMIN_D, src2, src1, dst));
++ return dst;
++ }
++ case Iop_RoundF32toInt: {
++ HReg dst = newVRegF(env);
++ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FRINT_S, src, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_RoundF64toInt: {
++ HReg dst = newVRegF(env);
++ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FRINT_D, src, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_RSqrtF32: {
++ HReg dst = newVRegF(env);
++ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FRSQRT_S, src, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_RSqrtF64: {
++ HReg dst = newVRegF(env);
++ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FRSQRT_D, src, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_SqrtF32: {
++ HReg dst = newVRegF(env);
++ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FSQRT_S, src, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ case Iop_SqrtF64: {
++ HReg dst = newVRegF(env);
++ HReg src = iselFltExpr(env, e->Iex.Binop.arg2);
++ set_rounding_mode(env, e->Iex.Binop.arg1);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FSQRT_D, src, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ default:
++ goto irreducible;
++ }
++ }
++
++ /* --------- UNARY OP --------- */
++ case Iex_Unop: {
++ switch (e->Iex.Unop.op) {
++ case Iop_AbsF32: {
++ HReg dst = newVRegF(env);
++ HReg src = iselFltExpr(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FABS_S, src, dst));
++ return dst;
++ }
++ case Iop_AbsF64: {
++ HReg dst = newVRegF(env);
++ HReg src = iselFltExpr(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FABS_D, src, dst));
++ return dst;
++ }
++ case Iop_F32toF64: {
++ HReg dst = newVRegF(env);
++ HReg src = iselFltExpr(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FCVT_D_S, src, dst));
++ return dst;
++ }
++ case Iop_I32StoF64: {
++ HReg tmp = newVRegF(env);
++ HReg dst = newVRegF(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_D, src, tmp));
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FFINT_D_W, tmp, dst));
++ return dst;
++ }
++ case Iop_NegF32: {
++ HReg dst = newVRegF(env);
++ HReg src = iselFltExpr(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FNEG_S, src, dst));
++ return dst;
++ }
++ case Iop_NegF64: {
++ HReg dst = newVRegF(env);
++ HReg src = iselFltExpr(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FNEG_D, src, dst));
++ return dst;
++ }
++ case Iop_ReinterpI32asF32: {
++ HReg dst = newVRegF(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_W, src, dst));
++ return dst;
++ }
++ case Iop_ReinterpI64asF64: {
++ HReg dst = newVRegF(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_D, src, dst));
++ return dst;
++ }
++ default:
++ goto irreducible;
++ }
++ }
+
-+ HChar *p = buf + vex_sprintf(buf, "%s", prefix);
-+ UInt i;
-+ for (i = 0 ; i < NUM_HWCAPS; ++i) {
-+ if (hwcaps & hwcaps_list[i].hwcaps_bit)
-+ p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
++ /* --------- LITERAL --------- */
++ case Iex_Const: {
++ /* Just handle the one case. */
++ IRConst* con = e->Iex.Const.con;
++ if (con->tag == Ico_F32i && con->Ico.F32i == 1) {
++ HReg tmp = newVRegI(env);
++ HReg dst = newVRegF(env);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(1, 12, True);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_W, ri, hregZERO(), tmp));
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_W, tmp, dst));
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FFINT_S_W, dst, dst));
++ return dst;
++ } else if (con->tag == Ico_F64i && con->Ico.F64i == 1) {
++ HReg tmp = newVRegI(env);
++ HReg dst = newVRegF(env);
++ LOONGARCH64RI* ri = LOONGARCH64RI_I(1, 12, True);
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D, ri, hregZERO(), tmp));
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_MOVGR2FR_D, tmp, dst));
++ addInstr(env, LOONGARCH64Instr_FpUnary(LAfpun_FFINT_D_L, dst, dst));
++ return dst;
++ } else {
++ goto irreducible;
++ }
++ }
++
++ case Iex_ITE: {
++ HReg r0 = iselFltExpr(env, e->Iex.ITE.iffalse);
++ HReg r1 = iselFltExpr(env, e->Iex.ITE.iftrue);
++ HReg cond = iselCondCode_R(env, e->Iex.ITE.cond);
++ HReg dst = newVRegF(env);
++ addInstr(env, LOONGARCH64Instr_CMove(cond, r0, r1, dst, False));
++ return dst;
++ }
++
++ default:
++ break;
+ }
-+ return buf;
++
++ /* We get here if no pattern matched. */
++irreducible:
++ ppIRExpr(e);
++ vpanic("iselFltExpr(loongarch64): cannot reduce tree");
+}
+
- #undef NUM_HWCAPS
-
- /* Thie function must not return NULL. */
-@@ -1941,6 +2044,7 @@ static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
- case VexArchS390X: return show_hwcaps_s390x(hwcaps);
- case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
- case VexArchMIPS64: return show_hwcaps_mips64(hwcaps);
-+ case VexArchLOONGARCH64: return show_hwcaps_loongarch64(hwcaps);
- default: return NULL;
- }
- }
-@@ -2203,6 +2307,11 @@ static void check_hwcaps ( VexArch arch, UInt hwcaps )
- return;
- invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
-
-+ case VexArchLOONGARCH64:
-+ if (!(hwcaps & VEX_HWCAPS_LOONGARCH_ISA_64BIT))
-+ invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
-+ return;
++/*---------------------------------------------------------*/
++/*--- ISEL: Vector expressions (128 bit) ---*/
++/*---------------------------------------------------------*/
+
- default:
- vpanic("unknown architecture");
- }
-diff --git a/VEX/pub/libvex.h b/VEX/pub/libvex.h
-index 27bb6e0..5ed24bd 100644
---- a/VEX/pub/libvex.h
-+++ b/VEX/pub/libvex.h
-@@ -60,6 +60,7 @@ typedef
- VexArchMIPS32,
- VexArchMIPS64,
- VexArchNANOMIPS,
-+ VexArchLOONGARCH64,
- }
- VexArch;
-
-@@ -300,6 +301,22 @@ typedef
- (VEX_MIPS_PROC_ID(x) == VEX_PRID_IMP_P5600) && \
- (VEX_MIPS_HOST_FP_MODE(x)))
-
-+/* LoongArch baseline capability */
-+#define VEX_HWCAPS_LOONGARCH_CPUCFG (1 << 0) /* CPU has CPUCFG */
-+#define VEX_HWCAPS_LOONGARCH_LAM (1 << 1) /* CPU has Atomic instructions */
-+#define VEX_HWCAPS_LOONGARCH_UAL (1 << 2) /* CPU has Unaligned Access support */
-+#define VEX_HWCAPS_LOONGARCH_FP (1 << 3) /* CPU has FPU */
-+#define VEX_HWCAPS_LOONGARCH_LSX (1 << 4) /* CPU has 128-bit SIMD instructions */
-+#define VEX_HWCAPS_LOONGARCH_LASX (1 << 5) /* CPU has 256-bit SIMD instructions */
-+#define VEX_HWCAPS_LOONGARCH_COMPLEX (1 << 6) /* CPU has Complex instructions */
-+#define VEX_HWCAPS_LOONGARCH_CRYPTO (1 << 7) /* CPU has Crypto instructions */
-+#define VEX_HWCAPS_LOONGARCH_LVZP (1 << 8) /* CPU has Virtualization extension */
-+#define VEX_HWCAPS_LOONGARCH_X86BT (1 << 9) /* CPU has X86 Binary Translation */
-+#define VEX_HWCAPS_LOONGARCH_ARMBT (1 << 10) /* CPU has ARM Binary Translation */
-+#define VEX_HWCAPS_LOONGARCH_MIPSBT (1 << 11) /* CPU has MIPS Binary Translation */
-+#define VEX_HWCAPS_LOONGARCH_ISA_32BIT (1 << 30) /* 32-bit ISA */
-+#define VEX_HWCAPS_LOONGARCH_ISA_64BIT (1 << 31) /* 64-bit ISA */
++/* Compute a vector value into a register, the identity of
++ which is returned. As with iselIntExpr_R, the reg may be either
++ real or virtual; in any case it must not be changed by subsequent
++ code emitted by the caller. */
+
- /* These return statically allocated strings. */
-
- extern const HChar* LibVEX_ppVexArch ( VexArch );
-@@ -420,6 +437,7 @@ void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai );
- guest is mips32 ==> applicable, default True
- guest is mips64 ==> applicable, default True
- guest is arm64 ==> applicable, default False
-+ guest is loongarch64 ==> const True
-
- host_ppc_calls_use_fndescrs:
- host is ppc32-linux ==> False
-@@ -1026,6 +1044,10 @@ extern void LibVEX_InitIRI ( const IRICB * );
- ~~~~~
- r21 is GSP.
-
-+ loongarch64
-+ ~~~~~
-+ r31 is GSP.
++static HReg iselV128Expr ( ISelEnv* env, IRExpr* e )
++{
++ HReg r = iselV128Expr_wrk(env, e);
+
- ALL GUEST ARCHITECTURES
- ~~~~~~~~~~~~~~~~~~~~~~~
- The guest state must contain two pseudo-registers, guest_CMSTART
-diff --git a/VEX/pub/libvex_basictypes.h b/VEX/pub/libvex_basictypes.h
-index e3f1485..b4c81bf 100644
---- a/VEX/pub/libvex_basictypes.h
-+++ b/VEX/pub/libvex_basictypes.h
-@@ -198,6 +198,10 @@ typedef unsigned long HWord;
- # define VEX_HOST_WORDSIZE 4
- # define VEX_REGPARM(_n) /* */
-
-+#elif defined(__loongarch__) && (__loongarch_grlen == 64)
-+# define VEX_HOST_WORDSIZE 8
-+# define VEX_REGPARM(_n) /* */
++ /* sanity checks ... */
++ vassert(hregClass(r) == HRcVec128);
++ vassert(hregIsVirtual(r));
+
- #else
- # error "Vex: Fatal: Can't establish the host architecture"
- #endif
-diff --git a/VEX/pub/libvex_guest_loongarch64.h b/VEX/pub/libvex_guest_loongarch64.h
-new file mode 100644
-index 0000000..fde111f
---- /dev/null
-+++ b/VEX/pub/libvex_guest_loongarch64.h
-@@ -0,0 +1,172 @@
++ return r;
++}
+
-+/*---------------------------------------------------------------*/
-+/*--- begin libvex_guest_loongarch64.h ---*/
-+/*---------------------------------------------------------------*/
++/* DO NOT CALL THIS DIRECTLY */
++static HReg iselV128Expr_wrk ( ISelEnv* env, IRExpr* e )
++{
++ IRType ty = typeOfIRExpr(env->type_env, e);
++ vassert(e);
++ vassert(ty == Ity_V128);
+
-+/*
-+ This file is part of Valgrind, a dynamic binary instrumentation
-+ framework.
++ switch (e->tag) {
++ /* --------- TEMP --------- */
++ case Iex_RdTmp:
++ return lookupIRTemp(env, e->Iex.RdTmp.tmp);
+
-+ Copyright (C) 2021-2022 Loongson Technology Corporation Limited
++ /* --------- LOAD --------- */
++ case Iex_Load: {
++ if (e->Iex.Load.end != Iend_LE)
++ goto irreducible;
+
-+ This program is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License as
-+ published by the Free Software Foundation; either version 2 of the
-+ License, or (at your option) any later version.
++ HReg dst = newVRegV(env);
++ LOONGARCH64AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr, ty);
++ LOONGARCH64VecLoadOp op = (am->tag == LAam_RI) ? LAvecload_VLD : LAvecload_VLDX;
++ addInstr(env, LOONGARCH64Instr_VecLoad(op, am, dst));
++ return dst;
++ }
+
-+ This program is distributed in the hope that it will be useful, but
-+ WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ General Public License for more details.
++ /* --------- GET --------- */
++ case Iex_Get: {
++ Bool ri = e->Iex.Get.offset < 1024;
++ HReg dst = newVRegV(env);
++ HReg tmp;
++ LOONGARCH64AMode* am;
++ LOONGARCH64VecLoadOp op;
++ if (ri) {
++ op = LAvecload_VLD;
++ am = LOONGARCH64AMode_RI(hregGSP(), e->Iex.Get.offset);
++ } else {
++ op = LAvecload_VLDX;
++ tmp = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_LI(e->Iex.Get.offset, tmp));
++ am = LOONGARCH64AMode_RR(hregGSP(), tmp);
++ }
++ addInstr(env, LOONGARCH64Instr_VecLoad(op, am, dst));
++ return dst;
++ }
+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, see .
++ /* --------- TERNARY OP --------- */
++ case Iex_Triop: {
++ IRTriop *triop = e->Iex.Triop.details;
++ switch (triop->op) {
++ case Iop_SetElem8x16: case Iop_SetElem16x8: case Iop_SetElem32x4: {
++ LOONGARCH64VecBinOp op;
++ UChar size;
++ switch (triop->op) {
++ case Iop_SetElem8x16: op = LAvecbin_VINSGR2VR_B; size = 4; break;
++ case Iop_SetElem16x8: op = LAvecbin_VINSGR2VR_H; size = 3; break;
++ case Iop_SetElem32x4: op = LAvecbin_VINSGR2VR_W; size = 2; break;
++ default: vassert(0); break;
++ }
++ HReg dst = newVRegV(env);
++ HReg src1 = iselV128Expr(env, triop->arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, triop->arg2, size, False);
++ HReg src3 = iselIntExpr_R(env, triop->arg3);
++ addInstr(env, LOONGARCH64Instr_VecMove(dst, src1));
++ addInstr(env, LOONGARCH64Instr_VecBinary(op, src2, src3, dst));
++ return dst;
++ }
++ case Iop_Add32Fx4: case Iop_Add64Fx2:
++ case Iop_Sub32Fx4: case Iop_Sub64Fx2:
++ case Iop_Mul32Fx4: case Iop_Mul64Fx2:
++ case Iop_Div32Fx4: case Iop_Div64Fx2: {
++ LOONGARCH64VecBinOp op;
++ switch (triop->op) {
++ case Iop_Add32Fx4: op = LAvecbin_VFADD_S; break;
++ case Iop_Add64Fx2: op = LAvecbin_VFADD_D; break;
++ case Iop_Sub32Fx4: op = LAvecbin_VFSUB_S; break;
++ case Iop_Sub64Fx2: op = LAvecbin_VFSUB_D; break;
++ case Iop_Mul32Fx4: op = LAvecbin_VFMUL_S; break;
++ case Iop_Mul64Fx2: op = LAvecbin_VFMUL_D; break;
++ case Iop_Div32Fx4: op = LAvecbin_VFDIV_S; break;
++ case Iop_Div64Fx2: op = LAvecbin_VFDIV_D; break;
++ default: vassert(0); break;
++ }
++ HReg dst = newVRegV(env);
++ HReg src1 = iselV128Expr(env, triop->arg2);
++ HReg src2 = iselV128Expr(env, triop->arg3);
++ set_rounding_mode(env, triop->arg1);
++ addInstr(env, LOONGARCH64Instr_VecBinary(op, LOONGARCH64RI_R(src2), src1, dst));
++ set_rounding_mode_default(env);
++ return dst;
++ }
++ default: goto irreducible;
++ }
++ }
++
++ /* --------- BINARY OP --------- */
++ case Iex_Binop: {
++ switch (e->Iex.Binop.op) {
++ case Iop_AndV128: case Iop_OrV128: case Iop_XorV128:
++ case Iop_Add8x16: case Iop_Add16x8: case Iop_Add32x4: case Iop_Add64x2: case Iop_Add128x1:
++ case Iop_Sub8x16: case Iop_Sub16x8: case Iop_Sub32x4: case Iop_Sub64x2: case Iop_Sub128x1:
++ case Iop_QAdd8Sx16: case Iop_QAdd16Sx8: case Iop_QAdd32Sx4: case Iop_QAdd64Sx2:
++ case Iop_QAdd8Ux16: case Iop_QAdd16Ux8: case Iop_QAdd32Ux4: case Iop_QAdd64Ux2:
++ case Iop_QSub8Sx16: case Iop_QSub16Sx8: case Iop_QSub32Sx4: case Iop_QSub64Sx2:
++ case Iop_QSub8Ux16: case Iop_QSub16Ux8: case Iop_QSub32Ux4: case Iop_QSub64Ux2:
++ case Iop_InterleaveHI8x16: case Iop_InterleaveHI16x8: case Iop_InterleaveHI32x4: case Iop_InterleaveHI64x2:
++ case Iop_InterleaveLO8x16: case Iop_InterleaveLO16x8: case Iop_InterleaveLO32x4: case Iop_InterleaveLO64x2:
++ case Iop_Max8Sx16: case Iop_Max16Sx8: case Iop_Max32Sx4: case Iop_Max64Sx2:
++ case Iop_Max8Ux16: case Iop_Max16Ux8: case Iop_Max32Ux4: case Iop_Max64Ux2:
++ case Iop_Min8Sx16: case Iop_Min16Sx8: case Iop_Min32Sx4: case Iop_Min64Sx2:
++ case Iop_Min8Ux16: case Iop_Min16Ux8: case Iop_Min32Ux4: case Iop_Min64Ux2:
++ case Iop_CmpEQ8x16: case Iop_CmpEQ16x8: case Iop_CmpEQ32x4: case Iop_CmpEQ64x2:
++ case Iop_PackOddLanes8x16: case Iop_PackOddLanes16x8: case Iop_PackOddLanes32x4:
++ case Iop_PackEvenLanes8x16: case Iop_PackEvenLanes16x8: case Iop_PackEvenLanes32x4:
++ case Iop_Avg8Ux16: case Iop_Avg16Ux8: case Iop_Avg32Ux4: case Iop_Avg64Ux2:
++ case Iop_Avg8Sx16: case Iop_Avg16Sx8: case Iop_Avg32Sx4: case Iop_Avg64Sx2:
++ case Iop_Mul8x16: case Iop_Mul16x8: case Iop_Mul32x4:
++ case Iop_MulHi8Ux16: case Iop_MulHi16Ux8: case Iop_MulHi32Ux4:
++ case Iop_MulHi8Sx16: case Iop_MulHi16Sx8: case Iop_MulHi32Sx4:
++ case Iop_Shl8x16: case Iop_Shl16x8: case Iop_Shl32x4: case Iop_Shl64x2:
++ case Iop_Shr8x16: case Iop_Shr16x8: case Iop_Shr32x4: case Iop_Shr64x2:
++ case Iop_Sar8x16: case Iop_Sar16x8: case Iop_Sar32x4: case Iop_Sar64x2:
++ case Iop_CmpGT8Sx16: case Iop_CmpGT16Sx8: case Iop_CmpGT32Sx4: case Iop_CmpGT64Sx2:
++ case Iop_CmpGT8Ux16: case Iop_CmpGT16Ux8: case Iop_CmpGT32Ux4: case Iop_CmpGT64Ux2:
++ case Iop_Max32Fx4: case Iop_Max64Fx2:
++ case Iop_Min32Fx4: case Iop_Min64Fx2: {
++ LOONGARCH64VecBinOp op;
++ Bool reverse = False;
++ switch (e->Iex.Binop.op) {
++ case Iop_AndV128: op = LAvecbin_VAND_V; break;
++ case Iop_OrV128: op = LAvecbin_VOR_V; break;
++ case Iop_XorV128: op = LAvecbin_VXOR_V; break;
++ case Iop_Add8x16: op = LAvecbin_VADD_B; break;
++ case Iop_Add16x8: op = LAvecbin_VADD_H; break;
++ case Iop_Add32x4: op = LAvecbin_VADD_W; break;
++ case Iop_Add64x2: op = LAvecbin_VADD_D; break;
++ case Iop_Add128x1: op = LAvecbin_VADD_Q; break;
++ case Iop_Sub8x16: op = LAvecbin_VSUB_B; break;
++ case Iop_Sub16x8: op = LAvecbin_VSUB_H; break;
++ case Iop_Sub32x4: op = LAvecbin_VSUB_W; break;
++ case Iop_Sub64x2: op = LAvecbin_VSUB_D; break;
++ case Iop_Sub128x1: op = LAvecbin_VSUB_Q; break;
++ case Iop_QAdd8Sx16: op = LAvecbin_VSADD_B; break;
++ case Iop_QAdd16Sx8: op = LAvecbin_VSADD_H; break;
++ case Iop_QAdd32Sx4: op = LAvecbin_VSADD_W; break;
++ case Iop_QAdd64Sx2: op = LAvecbin_VSADD_D; break;
++ case Iop_QAdd8Ux16: op = LAvecbin_VSADD_BU; break;
++ case Iop_QAdd16Ux8: op = LAvecbin_VSADD_HU; break;
++ case Iop_QAdd32Ux4: op = LAvecbin_VSADD_WU; break;
++ case Iop_QAdd64Ux2: op = LAvecbin_VSADD_DU; break;
++ case Iop_QSub8Sx16: op = LAvecbin_VSSUB_B; break;
++ case Iop_QSub16Sx8: op = LAvecbin_VSSUB_H; break;
++ case Iop_QSub32Sx4: op = LAvecbin_VSSUB_W; break;
++ case Iop_QSub64Sx2: op = LAvecbin_VSSUB_D; break;
++ case Iop_QSub8Ux16: op = LAvecbin_VSSUB_BU; break;
++ case Iop_QSub16Ux8: op = LAvecbin_VSSUB_HU; break;
++ case Iop_QSub32Ux4: op = LAvecbin_VSSUB_WU; break;
++ case Iop_QSub64Ux2: op = LAvecbin_VSSUB_DU; break;
++ case Iop_InterleaveHI8x16: op = LAvecbin_VILVH_B; break;
++ case Iop_InterleaveHI16x8: op = LAvecbin_VILVH_H; break;
++ case Iop_InterleaveHI32x4: op = LAvecbin_VILVH_W; break;
++ case Iop_InterleaveHI64x2: op = LAvecbin_VILVH_D; break;
++ case Iop_InterleaveLO8x16: op = LAvecbin_VILVL_B; break;
++ case Iop_InterleaveLO16x8: op = LAvecbin_VILVL_H; break;
++ case Iop_InterleaveLO32x4: op = LAvecbin_VILVL_W; break;
++ case Iop_InterleaveLO64x2: op = LAvecbin_VILVL_D; break;
++ case Iop_Max8Sx16: op = LAvecbin_VMAX_B; break;
++ case Iop_Max16Sx8: op = LAvecbin_VMAX_H; break;
++ case Iop_Max32Sx4: op = LAvecbin_VMAX_W; break;
++ case Iop_Max64Sx2: op = LAvecbin_VMAX_D; break;
++ case Iop_Max8Ux16: op = LAvecbin_VMAX_BU; break;
++ case Iop_Max16Ux8: op = LAvecbin_VMAX_HU; break;
++ case Iop_Max32Ux4: op = LAvecbin_VMAX_WU; break;
++ case Iop_Max64Ux2: op = LAvecbin_VMAX_DU; break;
++ case Iop_Min8Sx16: op = LAvecbin_VMIN_B; break;
++ case Iop_Min16Sx8: op = LAvecbin_VMIN_H; break;
++ case Iop_Min32Sx4: op = LAvecbin_VMIN_W; break;
++ case Iop_Min64Sx2: op = LAvecbin_VMIN_D; break;
++ case Iop_Min8Ux16: op = LAvecbin_VMIN_BU; break;
++ case Iop_Min16Ux8: op = LAvecbin_VMIN_HU; break;
++ case Iop_Min32Ux4: op = LAvecbin_VMIN_WU; break;
++ case Iop_Min64Ux2: op = LAvecbin_VMIN_DU; break;
++ case Iop_CmpEQ8x16: op = LAvecbin_VSEQ_B; break;
++ case Iop_CmpEQ16x8: op = LAvecbin_VSEQ_H; break;
++ case Iop_CmpEQ32x4: op = LAvecbin_VSEQ_W; break;
++ case Iop_CmpEQ64x2: op = LAvecbin_VSEQ_D; break;
++ case Iop_PackOddLanes8x16: op = LAvecbin_VPICKOD_B; break;
++ case Iop_PackOddLanes16x8: op = LAvecbin_VPICKOD_H; break;
++ case Iop_PackOddLanes32x4: op = LAvecbin_VPICKOD_W; break;
++ case Iop_PackEvenLanes8x16: op = LAvecbin_VPICKEV_B; break;
++ case Iop_PackEvenLanes16x8: op = LAvecbin_VPICKEV_H; break;
++ case Iop_PackEvenLanes32x4: op = LAvecbin_VPICKEV_W; break;
++ case Iop_Avg8Ux16: op = LAvecbin_VAVGR_BU; break;
++ case Iop_Avg16Ux8: op = LAvecbin_VAVGR_HU; break;
++ case Iop_Avg32Ux4: op = LAvecbin_VAVGR_WU; break;
++ case Iop_Avg64Ux2: op = LAvecbin_VAVGR_DU; break;
++ case Iop_Avg8Sx16: op = LAvecbin_VAVGR_B; break;
++ case Iop_Avg16Sx8: op = LAvecbin_VAVGR_H; break;
++ case Iop_Avg32Sx4: op = LAvecbin_VAVGR_W; break;
++ case Iop_Avg64Sx2: op = LAvecbin_VAVGR_D; break;
++ case Iop_Mul8x16: op = LAvecbin_VMUL_B; break;
++ case Iop_Mul16x8: op = LAvecbin_VMUL_H; break;
++ case Iop_Mul32x4: op = LAvecbin_VMUL_W; break;
++ case Iop_MulHi8Ux16: op = LAvecbin_VMUH_BU; break;
++ case Iop_MulHi16Ux8: op = LAvecbin_VMUH_HU; break;
++ case Iop_MulHi32Ux4: op = LAvecbin_VMUH_WU; break;
++ case Iop_MulHi8Sx16: op = LAvecbin_VMUH_B; break;
++ case Iop_MulHi16Sx8: op = LAvecbin_VMUH_H; break;
++ case Iop_MulHi32Sx4: op = LAvecbin_VMUH_W; break;
++ case Iop_Shl8x16: op = LAvecbin_VSLL_B; break;
++ case Iop_Shl16x8: op = LAvecbin_VSLL_H; break;
++ case Iop_Shl32x4: op = LAvecbin_VSLL_W; break;
++ case Iop_Shl64x2: op = LAvecbin_VSLL_D; break;
++ case Iop_Shr8x16: op = LAvecbin_VSRL_B; break;
++ case Iop_Shr16x8: op = LAvecbin_VSRL_H; break;
++ case Iop_Shr32x4: op = LAvecbin_VSRL_W; break;
++ case Iop_Shr64x2: op = LAvecbin_VSRL_D; break;
++ case Iop_Sar8x16: op = LAvecbin_VSRA_B; break;
++ case Iop_Sar16x8: op = LAvecbin_VSRA_H; break;
++ case Iop_Sar32x4: op = LAvecbin_VSRA_W; break;
++ case Iop_Sar64x2: op = LAvecbin_VSRA_D; break;
++ case Iop_CmpGT8Sx16: op = LAvecbin_VSLT_B; reverse = True; break;
++ case Iop_CmpGT16Sx8: op = LAvecbin_VSLT_H; reverse = True; break;
++ case Iop_CmpGT32Sx4: op = LAvecbin_VSLT_W; reverse = True; break;
++ case Iop_CmpGT64Sx2: op = LAvecbin_VSLT_D; reverse = True; break;
++ case Iop_CmpGT8Ux16: op = LAvecbin_VSLT_BU; reverse = True; break;
++ case Iop_CmpGT16Ux8: op = LAvecbin_VSLT_HU; reverse = True; break;
++ case Iop_CmpGT32Ux4: op = LAvecbin_VSLT_WU; reverse = True; break;
++ case Iop_CmpGT64Ux2: op = LAvecbin_VSLT_DU; reverse = True; break;
++ case Iop_Max32Fx4: op = LAvecbin_VFMAX_S; break;
++ case Iop_Max64Fx2: op = LAvecbin_VFMAX_D; break;
++ case Iop_Min32Fx4: op = LAvecbin_VFMIN_S; break;
++ case Iop_Min64Fx2: op = LAvecbin_VFMIN_D; break;
++ default: vassert(0); break;
++ }
++ HReg dst = newVRegV(env);
++ HReg src1 = iselV128Expr(env, e->Iex.Binop.arg1);
++ HReg src2 = iselV128Expr(env, e->Iex.Binop.arg2);
++ if (reverse)
++ addInstr(env, LOONGARCH64Instr_VecBinary(op, LOONGARCH64RI_R(src1), src2, dst));
++ else
++ addInstr(env, LOONGARCH64Instr_VecBinary(op, LOONGARCH64RI_R(src2), src1, dst));
++ return dst;
++ }
++ case Iop_ShlN8x16: case Iop_ShlN16x8: case Iop_ShlN32x4: case Iop_ShlN64x2:
++ case Iop_ShrN8x16: case Iop_ShrN16x8: case Iop_ShrN32x4: case Iop_ShrN64x2:
++ case Iop_SarN8x16: case Iop_SarN16x8: case Iop_SarN32x4: case Iop_SarN64x2:
++ case Iop_ShlV128: case Iop_ShrV128: {
++ UChar size;
++ LOONGARCH64VecBinOp op;
++ switch (e->Iex.Binop.op) {
++ case Iop_ShlN8x16: op = LAvecbin_VSLLI_B; size = 3; break;
++ case Iop_ShlN16x8: op = LAvecbin_VSLLI_H; size = 4; break;
++ case Iop_ShlN32x4: op = LAvecbin_VSLLI_W; size = 5; break;
++ case Iop_ShlN64x2: op = LAvecbin_VSLLI_D; size = 6; break;
++ case Iop_ShrN8x16: op = LAvecbin_VSRLI_B; size = 3; break;
++ case Iop_ShrN16x8: op = LAvecbin_VSRLI_H; size = 4; break;
++ case Iop_ShrN32x4: op = LAvecbin_VSRLI_W; size = 5; break;
++ case Iop_ShrN64x2: op = LAvecbin_VSRLI_D; size = 6; break;
++ case Iop_SarN8x16: op = LAvecbin_VSRAI_B; size = 3; break;
++ case Iop_SarN16x8: op = LAvecbin_VSRAI_H; size = 4; break;
++ case Iop_SarN32x4: op = LAvecbin_VSRAI_W; size = 5; break;
++ case Iop_SarN64x2: op = LAvecbin_VSRAI_D; size = 6; break;
++ case Iop_ShlV128: op = LAvecbin_VBSLL_V; size = 5; break;
++ case Iop_ShrV128: op = LAvecbin_VBSRL_V; size = 5; break;
++ default: vassert(0); break;
++ }
++ HReg dst = newVRegV(env);
++ HReg src1 = iselV128Expr(env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, size, False);
++ vassert(e->Iex.Binop.arg2->tag == Iex_Const);
++ vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
++ vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
++ addInstr(env, LOONGARCH64Instr_VecBinary(op, src2, src1, dst));
++ return dst;
++ }
++ case Iop_64HLtoV128: {
++ HReg dst = newVRegV(env);
++ HReg sHi = iselIntExpr_R(env, e->Iex.Binop.arg1);
++ HReg sLow = iselIntExpr_R(env, e->Iex.Binop.arg2);
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_D,
++ LOONGARCH64RI_I(0, 1, False), sLow, dst));
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_D,
++ LOONGARCH64RI_I(1, 1, False), sHi, dst));
++ return dst;
++ }
++ default: goto irreducible;
++ }
++ }
++
++ /* --------- UNARY OP --------- */
++ case Iex_Unop: {
++ switch (e->Iex.Unop.op) {
++ case Iop_32UtoV128: {
++ HReg dst = newVRegV(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_W,
++ LOONGARCH64RI_I(0, 2, False), src, dst));
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_W,
++ LOONGARCH64RI_I(1, 2, False), hregZERO(), dst));
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_W,
++ LOONGARCH64RI_I(2, 2, False), hregZERO(), dst));
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_W,
++ LOONGARCH64RI_I(3, 2, False), hregZERO(), dst));
++ return dst;
++ }
++ case Iop_64UtoV128: {
++ HReg dst = newVRegV(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_D,
++ LOONGARCH64RI_I(0, 1, False), src, dst));
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_D,
++ LOONGARCH64RI_I(1, 1, False), hregZERO(), dst));
++ return dst;
++ }
++ case Iop_Abs8x16: case Iop_Abs16x8:
++ case Iop_Abs32x4: case Iop_Abs64x2: {
++ LOONGARCH64VecBinOp subOp, addOp;
++ switch (e->Iex.Unop.op) {
++ case Iop_Abs8x16:
++ subOp = LAvecbin_VSUB_B;
++ addOp = LAvecbin_VADDA_B;
++ break;
++ case Iop_Abs16x8:
++ subOp = LAvecbin_VSUB_H;
++ addOp = LAvecbin_VADDA_H;
++ break;
++ case Iop_Abs32x4:
++ subOp = LAvecbin_VSUB_W;
++ addOp = LAvecbin_VADDA_W;
++ break;
++ case Iop_Abs64x2:
++ subOp = LAvecbin_VSUB_D;
++ addOp = LAvecbin_VADDA_D;
++ break;
++ default:
++ vassert(0);
++ break;
++ };
++ HReg dst = newVRegV(env);
++ HReg src = iselV128Expr(env, e->Iex.Unop.arg);
++ HReg sub = newVRegV(env);
++ addInstr(env, LOONGARCH64Instr_VecBinary(subOp, LOONGARCH64RI_R(src), src, sub));
++ addInstr(env, LOONGARCH64Instr_VecBinary(addOp, LOONGARCH64RI_R(src), sub, dst));
++ return dst;
++ }
++ case Iop_CmpNEZ16x8: case Iop_CmpNEZ8x16:
++ case Iop_CmpNEZ32x4: case Iop_CmpNEZ64x2: {
++ HReg dst = newVRegV(env);
++ HReg src = iselV128Expr(env, e->Iex.Unop.arg);
++ LOONGARCH64VecBinOp op;
++ switch (e->Iex.Unop.op) {
++ case Iop_CmpNEZ64x2: op = LAvecbin_VSEQ_D; break;
++ case Iop_CmpNEZ32x4: op = LAvecbin_VSEQ_W; break;
++ case Iop_CmpNEZ16x8: op = LAvecbin_VSEQ_H; break;
++ case Iop_CmpNEZ8x16: op = LAvecbin_VSEQ_B; break;
++ default: vassert(0); break;
++ }
++ addInstr(env, LOONGARCH64Instr_VecUnary(LAvecun_VREPLGR2VR_D, hregZERO(), dst));
++ addInstr(env, LOONGARCH64Instr_VecBinary(op, LOONGARCH64RI_R(dst), src, dst));
++ return dst;
++ }
++ case Iop_WidenHIto16Sx8: case Iop_WidenHIto16Ux8:
++ case Iop_WidenHIto32Sx4: case Iop_WidenHIto32Ux4:
++ case Iop_WidenHIto64Sx2: case Iop_WidenHIto64Ux2:
++ case Iop_WidenHIto128Sx1: case Iop_WidenHIto128Ux1:
++ case Iop_Cls8x16: case Iop_Cls16x8: case Iop_Cls32x4:
++ case Iop_Clz8x16: case Iop_Clz16x8: case Iop_Clz32x4: case Iop_Clz64x2:
++ case Iop_Cnt8x16: {
++ HReg dst = newVRegV(env);
++ HReg src = iselV128Expr(env, e->Iex.Unop.arg);
++ LOONGARCH64VecUnOp op;
++ switch (e->Iex.Unop.op) {
++ case Iop_WidenHIto16Sx8: op = LAvecun_VEXTH_H_B; break;
++ case Iop_WidenHIto16Ux8: op = LAvecun_VEXTH_HU_BU; break;
++ case Iop_WidenHIto32Sx4: op = LAvecun_VEXTH_W_H; break;
++ case Iop_WidenHIto32Ux4: op = LAvecun_VEXTH_WU_HU; break;
++ case Iop_WidenHIto64Sx2: op = LAvecun_VEXTH_D_W; break;
++ case Iop_WidenHIto64Ux2: op = LAvecun_VEXTH_DU_WU; break;
++ case Iop_WidenHIto128Sx1: op = LAvecun_VEXTH_Q_D; break;
++ case Iop_WidenHIto128Ux1: op = LAvecun_VEXTH_QU_DU; break;
++ case Iop_Cls8x16: op = LAvecun_VCLO_B; break;
++ case Iop_Cls16x8: op = LAvecun_VCLO_H; break;
++ case Iop_Cls32x4: op = LAvecun_VCLO_W; break;
++ case Iop_Clz8x16: op = LAvecun_VCLZ_B; break;
++ case Iop_Clz16x8: op = LAvecun_VCLZ_H; break;
++ case Iop_Clz32x4: op = LAvecun_VCLZ_W; break;
++ case Iop_Clz64x2: op = LAvecun_VCLZ_D; break;
++ case Iop_Cnt8x16: op = LAvecun_VPCNT_B; break;
++ default: vassert(0);
++ }
++ addInstr(env, LOONGARCH64Instr_VecUnary(op, src, dst));
++ return dst;
++ }
++ case Iop_Dup8x16: case Iop_Dup16x8: case Iop_Dup32x4: {
++ HReg dst = newVRegV(env);
++ HReg src = iselIntExpr_R(env, e->Iex.Unop.arg);
++ LOONGARCH64VecUnOp op;
++ switch (e->Iex.Unop.op) {
++ case Iop_Dup8x16: op = LAvecun_VREPLGR2VR_B; break;
++ case Iop_Dup16x8: op = LAvecun_VREPLGR2VR_H; break;
++ case Iop_Dup32x4: op = LAvecun_VREPLGR2VR_W; break;
++ default: vassert(0); break;
++ }
++ addInstr(env, LOONGARCH64Instr_VecUnary(op, src, dst));
++ return dst;
++ }
++ case Iop_NotV128: {
++ HReg dst = newVRegV(env);
++ HReg src = iselV128Expr(env, e->Iex.Unop.arg);
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VNOR_V,
++ LOONGARCH64RI_R(src), src, dst));
++ return dst;
++ }
++ case Iop_RoundF32x4_RM: case Iop_RoundF32x4_RN:
++ case Iop_RoundF32x4_RP: case Iop_RoundF32x4_RZ:
++ case Iop_RoundF64x2_RM: case Iop_RoundF64x2_RN:
++ case Iop_RoundF64x2_RP: case Iop_RoundF64x2_RZ: {
++ HReg dst = newVRegV(env);
++ HReg src = iselV128Expr(env, e->Iex.Unop.arg);
++ LOONGARCH64VecUnOp op;
++ switch (e->Iex.Unop.op) {
++ case Iop_RoundF32x4_RM: op = LAvecun_VFRINTRM_S; break;
++ case Iop_RoundF32x4_RN: op = LAvecun_VFRINTRNE_S; break;
++ case Iop_RoundF32x4_RP: op = LAvecun_VFRINTRP_S; break;
++ case Iop_RoundF32x4_RZ: op = LAvecun_VFRINTRZ_S; break;
++ case Iop_RoundF64x2_RM: op = LAvecun_VFRINTRM_D; break;
++ case Iop_RoundF64x2_RN: op = LAvecun_VFRINTRNE_D; break;
++ case Iop_RoundF64x2_RP: op = LAvecun_VFRINTRP_D; break;
++ case Iop_RoundF64x2_RZ: op = LAvecun_VFRINTRZ_D; break;
++ default: vassert(0); break;
++ }
++ addInstr(env, LOONGARCH64Instr_VecUnary(op, src, dst));
++ return dst;
++ }
++ case Iop_V256toV128_0: case Iop_V256toV128_1: {
++ HReg vHi, vLo;
++ iselV256Expr(&vHi, &vLo, env, e->Iex.Unop.arg);
++ return (e->Iex.Unop.op == Iop_V256toV128_1) ? vHi : vLo;
++ }
++ default:
++ goto irreducible;
++ }
++ }
+
-+ The GNU General Public License is contained in the file COPYING.
++ case Iex_Const: {
++ IRConst *con = e->Iex.Const.con;
+
-+ Neither the names of the U.S. Department of Energy nor the
-+ University of California nor the names of its contributors may be
-+ used to endorse or promote products derived from this software
-+ without prior written permission.
-+*/
++ if (con->tag != Ico_V128) {
++ vpanic("iselV128Expr.const(LoongArch)");
++ goto irreducible;
++ }
+
-+#ifndef __LIBVEX_PUB_GUEST_LOONGARCH64_H
-+#define __LIBVEX_PUB_GUEST_LOONGARCH64_H
++ HReg dst = newVRegV(env);
++ UShort val = con->Ico.V128;
+
-+#include "libvex_basictypes.h"
++ if (val == 0) {
++ addInstr(env, LOONGARCH64Instr_VecUnary(LAvecun_VREPLGR2VR_D, hregZERO(), dst));
++ } else {
++ HReg r_tmp = newVRegI(env);
++ UInt i;
++ addInstr(env, LOONGARCH64Instr_LI(0xfful, r_tmp));
++ if (val & 1) {
++ addInstr(env, LOONGARCH64Instr_VecUnary(LAvecun_VREPLGR2VR_B, r_tmp, dst));
++ } else {
++ addInstr(env, LOONGARCH64Instr_VecUnary(LAvecun_VREPLGR2VR_B, hregZERO(), dst));
++ }
++ for (i = 1; i < 16; i++) {
++ val >>= 1;
++ if (val & 1) {
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_B,
++ LOONGARCH64RI_I(i, 4, False),
++ r_tmp, dst));
++ } else {
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_B,
++ LOONGARCH64RI_I(i, 4, False),
++ hregZERO(), dst));
++ }
++ }
++ }
+
++ return dst;
++ }
+
-+/*---------------------------------------------------------------*/
-+/*--- Vex's representation of the LOONGARCH64 CPU state. ---*/
-+/*---------------------------------------------------------------*/
++ default:
++ break;
++ }
+
-+typedef
-+ struct {
-+ /* Event check fail addr and counter. */
-+ /* 0 */ ULong host_EvC_FAILADDR;
-+ /* 8 */ UInt host_EvC_COUNTER;
-+ /* 12 */ UInt _padding0;
++ /* We get here if no pattern matched. */
++irreducible:
++ ppIRExpr(e);
++ vpanic("iselV128Expr(loongarch64): cannot reduce tree");
++}
+
-+ /* CPU Registers */
-+ /* 16 */ ULong guest_R0; /* Constant zero */
-+ /* 24 */ ULong guest_R1; /* Return address */
-+ /* 32 */ ULong guest_R2; /* Thread pointer */
-+ /* 40 */ ULong guest_R3; /* Stack pointer */
-+ /* 48 */ ULong guest_R4; /* Argument registers / Return value */
-+ /* 56 */ ULong guest_R5;
-+ /* 64 */ ULong guest_R6; /* Argument registers */
-+ /* 72 */ ULong guest_R7;
-+ /* 80 */ ULong guest_R8;
-+ /* 88 */ ULong guest_R9;
-+ /* 96 */ ULong guest_R10;
-+ /* 104 */ ULong guest_R11;
-+ /* 112 */ ULong guest_R12; /* Temporary registers */
-+ /* 120 */ ULong guest_R13;
-+ /* 128 */ ULong guest_R14;
-+ /* 136 */ ULong guest_R15;
-+ /* 144 */ ULong guest_R16;
-+ /* 152 */ ULong guest_R17;
-+ /* 160 */ ULong guest_R18;
-+ /* 168 */ ULong guest_R19;
-+ /* 176 */ ULong guest_R20;
-+ /* 184 */ ULong guest_R21; /* Reserved */
-+ /* 192 */ ULong guest_R22; /* Frame pointer / Static register */
-+ /* 200 */ ULong guest_R23; /* Static registers */
-+ /* 208 */ ULong guest_R24;
-+ /* 216 */ ULong guest_R25;
-+ /* 224 */ ULong guest_R26;
-+ /* 232 */ ULong guest_R27;
-+ /* 240 */ ULong guest_R28;
-+ /* 248 */ ULong guest_R29;
-+ /* 256 */ ULong guest_R30;
-+ /* 264 */ ULong guest_R31;
+
-+ /* 272 */ ULong guest_PC; /* Program counter */
++/*---------------------------------------------------------*/
++/*--- ISEL: Vector expressions (256 bit) ---*/
++/*---------------------------------------------------------*/
+
-+ /* 280 */ UChar guest_FCC0; /* Condition Flag Registers */
-+ /* 281 */ UChar guest_FCC1;
-+ /* 282 */ UChar guest_FCC2;
-+ /* 283 */ UChar guest_FCC3;
-+ /* 284 */ UChar guest_FCC4;
-+ /* 285 */ UChar guest_FCC5;
-+ /* 286 */ UChar guest_FCC6;
-+ /* 287 */ UChar guest_FCC7;
-+ /* 288 */ UInt guest_FCSR; /* FP/SIMD Control and Status Register */
++/* Compute a vector value into a register, the identity of
++ which is returned. As with iselIntExpr_R, the reg may be either
++ real or virtual; in any case it must not be changed by subsequent
++ code emitted by the caller. */
+
-+ /* Various pseudo-regs mandated by Vex or Valgrind. */
-+ /* Emulation notes */
-+ /* 292 */ UInt guest_EMNOTE;
++static void iselV256Expr ( HReg* hi, HReg* lo,
++ ISelEnv* env, IRExpr* e )
++{
++ iselV256Expr_wrk( hi, lo, env, e );
+
-+ /* For clflush: record start and length of area to invalidate */
-+ /* 296 */ ULong guest_CMSTART;
-+ /* 304 */ ULong guest_CMLEN;
++ /* sanity checks ... */
++ vassert(hregClass(*hi) == HRcVec128);
++ vassert(hregIsVirtual(*hi));
++ vassert(hregClass(*lo) == HRcVec128);
++ vassert(hregIsVirtual(*lo));
++}
+
-+ /* Used to record the unredirected guest address at the start of
-+ a translation whose start has been redirected. By reading
-+ this pseudo-register shortly afterwards, the translation can
-+ find out what the corresponding no-redirection address was.
-+ Note, this is only set for wrap-style redirects, not for
-+ replace-style ones. */
-+ /* 312 */ ULong guest_NRADDR;
++/* DO NOT CALL THIS DIRECTLY */
++static void iselV256Expr_wrk ( HReg* hi, HReg* lo,
++ ISelEnv* env, IRExpr* e )
++{
++ IRType ty = typeOfIRExpr(env->type_env, e);
++ vassert(e);
++ vassert(ty == Ity_V256);
+
-+ /* Fallback LL/SC support. */
-+ /* 320 */ ULong guest_LLSC_SIZE; /* 0==no transaction, else 4 or 8. */
-+ /* 328 */ ULong guest_LLSC_ADDR; /* Address of the transaction. */
-+ /* 336 */ ULong guest_LLSC_DATA; /* Original value at ADDR. */
++ switch (e->tag) {
++ /* --------- TEMP --------- */
++ case Iex_RdTmp: {
++ lookupIRTempPair(hi, lo, env, e->Iex.RdTmp.tmp);
++ return;
++ }
+
-+ /* 344 */ ULong _padding1;
++ /* --------- LOAD --------- */
++ case Iex_Load: {
++ if (e->Iex.Load.end != Iend_LE)
++ goto irreducible;
+
-+ /* FPU/SIMD Registers */
-+ /* 352 */ U256 guest_X0;
-+ /* 384 */ U256 guest_X1;
-+ /* 416 */ U256 guest_X2;
-+ /* 448 */ U256 guest_X3;
-+ /* 480 */ U256 guest_X4;
-+ /* 512 */ U256 guest_X5;
-+ /* 544 */ U256 guest_X6;
-+ /* 576 */ U256 guest_X7;
-+ /* 608 */ U256 guest_X8;
-+ /* 640 */ U256 guest_X9;
-+ /* 672 */ U256 guest_X10;
-+ /* 704 */ U256 guest_X11;
-+ /* 736 */ U256 guest_X12;
-+ /* 768 */ U256 guest_X13;
-+ /* 800 */ U256 guest_X14;
-+ /* 832 */ U256 guest_X15;
-+ /* 864 */ U256 guest_X16;
-+ /* 896 */ U256 guest_X17;
-+ /* 928 */ U256 guest_X18;
-+ /* 960 */ U256 guest_X19;
-+ /* 992 */ U256 guest_X20;
-+ /* 1024 */ U256 guest_X21;
-+ /* 1056 */ U256 guest_X22;
-+ /* 1088 */ U256 guest_X23;
-+ /* 1120 */ U256 guest_X24;
-+ /* 1152 */ U256 guest_X25;
-+ /* 1184 */ U256 guest_X26;
-+ /* 1216 */ U256 guest_X27;
-+ /* 1248 */ U256 guest_X28;
-+ /* 1280 */ U256 guest_X29;
-+ /* 1312 */ U256 guest_X30;
-+ /* 1244 */ U256 guest_X31;
++ HReg dstHi = newVRegV(env);
++ HReg dstLo = newVRegV(env);
++ LOONGARCH64AMode* am = iselIntExpr_AMode(env, e->Iex.Load.addr, ty);
++ LOONGARCH64VecLoadOp op = (am->tag == LAam_RI) ? LAvecload_VLD : LAvecload_VLDX;
++ HReg addr = iselIntExpr_R(env, e->Iex.Load.addr);
++ LOONGARCH64AMode* am16 = LOONGARCH64AMode_RI(addr, 16);
++ addInstr(env, LOONGARCH64Instr_VecLoad(op, am, dstLo));
++ addInstr(env, LOONGARCH64Instr_VecLoad(LAvecload_VLD, am16, dstHi));
++ *hi = dstHi;
++ *lo = dstLo;
++ return;
++ }
+
-+ /* 1376 */ /* VexGuestLOONGARCH64State should have a 16-aligned size */
-+} VexGuestLOONGARCH64State;
++ /* --------- GET --------- */
++ case Iex_Get: {
++ Bool ri = e->Iex.Get.offset < 1024;
++ HReg dstHi = newVRegV(env);
++ HReg dstLo = newVRegV(env);
++ LOONGARCH64VecLoadOp op, op2;
++ HReg tmp, tmp2;
++ LOONGARCH64AMode* am;
++ LOONGARCH64AMode* am2;
++ if (ri) {
++ op = LAvecload_VLD;
++ am = LOONGARCH64AMode_RI(hregGSP(), e->Iex.Get.offset);
++ } else {
++ op = LAvecload_VLDX;
++ tmp = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_LI(e->Iex.Get.offset, tmp));
++ am = LOONGARCH64AMode_RR(hregGSP(), tmp);
++ }
++ if (e->Iex.Get.offset + 16 < 1024) {
++ op2 = LAvecload_VLD;
++ am2 = LOONGARCH64AMode_RI(hregGSP(), e->Iex.Get.offset + 16);
++ } else {
++ op2 = LAvecload_VLDX;
++ tmp2 = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_LI(e->Iex.Get.offset + 16, tmp2));
++ am2 = LOONGARCH64AMode_RR(hregGSP(), tmp2);
++ }
++ addInstr(env, LOONGARCH64Instr_VecLoad(op, am, dstLo));
++ addInstr(env, LOONGARCH64Instr_VecLoad(op2, am2, dstHi));
++ *hi = dstHi;
++ *lo = dstLo;
++ return;
++ }
+
-+/*---------------------------------------------------------------*/
-+/*--- Utility functions for LOONGARCH64 guest stuff. ---*/
-+/*---------------------------------------------------------------*/
++ /* --------- UNARY OP --------- */
++ case Iex_Unop: {
++ switch (e->Iex.Unop.op) {
++ case Iop_NotV256: {
++ HReg sHi, sLo;
++ iselV256Expr(&sHi, &sLo, env, e->Iex.Unop.arg);
++ HReg dHi = newVRegV(env);
++ HReg dLo = newVRegV(env);
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VNOR_V,
++ LOONGARCH64RI_R(sHi), sHi, dHi));
++ addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VNOR_V,
++ LOONGARCH64RI_R(sLo), sLo, dLo));
++ *hi = dHi;
++ *lo = dLo;
++ return;
++ }
++ case Iop_WidenHIto16Sx16: case Iop_WidenHIto16Ux16:
++ case Iop_WidenHIto32Sx8: case Iop_WidenHIto32Ux8:
++ case Iop_WidenHIto64Sx4: case Iop_WidenHIto64Ux4:
++ case Iop_WidenHIto128Sx2: case Iop_WidenHIto128Ux2: {
++ LOONGARCH64VecUnOp op;
++ switch (e->Iex.Unop.op) {
++ case Iop_WidenHIto16Sx16: op = LAvecun_VEXTH_H_B; break;
++ case Iop_WidenHIto16Ux16: op = LAvecun_VEXTH_HU_BU; break;
++ case Iop_WidenHIto32Sx8: op = LAvecun_VEXTH_W_H; break;
++ case Iop_WidenHIto32Ux8: op = LAvecun_VEXTH_WU_HU; break;
++ case Iop_WidenHIto64Sx4: op = LAvecun_VEXTH_D_W; break;
++ case Iop_WidenHIto64Ux4: op = LAvecun_VEXTH_DU_WU; break;
++ case Iop_WidenHIto128Sx2: op = LAvecun_VEXTH_Q_D; break;
++ case Iop_WidenHIto128Ux2: op = LAvecun_VEXTH_QU_DU; break;
++ default: vassert(0);
++ }
++ HReg sHi, sLo;
++ iselV256Expr(&sHi, &sLo, env, e->Iex.Unop.arg);
++ HReg dHi = newVRegV(env);
++ HReg dLo = newVRegV(env);
++ addInstr(env, LOONGARCH64Instr_VecUnary(op, sHi, dHi));
++ addInstr(env, LOONGARCH64Instr_VecUnary(op, sLo, dLo));
++ *hi = dHi;
++ *lo = dLo;
++ return;
++ }
++ case Iop_Abs8x32: case Iop_Abs16x16:
++ case Iop_Abs32x8: case Iop_Abs64x4: {
++ LOONGARCH64VecBinOp subOp, addOp;
++ switch (e->Iex.Unop.op) {
++ case Iop_Abs8x32:
++ subOp = LAvecbin_VSUB_B;
++ addOp = LAvecbin_VADDA_B;
++ break;
++ case Iop_Abs16x16:
++ subOp = LAvecbin_VSUB_H;
++ addOp = LAvecbin_VADDA_H;
++ break;
++ case Iop_Abs32x8:
++ subOp = LAvecbin_VSUB_W;
++ addOp = LAvecbin_VADDA_W;
++ break;
++ case Iop_Abs64x4:
++ subOp = LAvecbin_VSUB_D;
++ addOp = LAvecbin_VADDA_D;
++ break;
++ default: vassert(0);
++ };
++ HReg sHi, sLo;
++ iselV256Expr(&sHi, &sLo, env, e->Iex.Unop.arg);
++ HReg dHi = newVRegV(env);
++ HReg dLo = newVRegV(env);
++ HReg sub = newVRegV(env);
++ addInstr(env, LOONGARCH64Instr_VecBinary(subOp, LOONGARCH64RI_R(sHi), sHi, sub));
++ addInstr(env, LOONGARCH64Instr_VecBinary(addOp, LOONGARCH64RI_R(sHi), sub, dHi));
++ addInstr(env, LOONGARCH64Instr_VecBinary(addOp, LOONGARCH64RI_R(sLo), sub, dLo));
++ *hi = dHi;
++ *lo = dLo;
++ return;
++ }
++ default: goto irreducible;
++ }
++ }
+
-+/* ALL THE FOLLOWING ARE VISIBLE TO LIBRARY CLIENT. */
++ /* --------- BINARY OP --------- */
++ case Iex_Binop: {
++ switch (e->Iex.Binop.op) {
++ case Iop_V128HLtoV256: {
++ *hi = iselV128Expr(env, e->Iex.Binop.arg1);
++ *lo = iselV128Expr(env, e->Iex.Binop.arg2);
++ return;
++ }
++ case Iop_AndV256: case Iop_XorV256: case Iop_OrV256:
++ case Iop_CmpEQ8x32: case Iop_CmpEQ16x16: case Iop_CmpEQ32x8: case Iop_CmpEQ64x4:
++ case Iop_CmpGT8Ux32: case Iop_CmpGT16Ux16: case Iop_CmpGT32Ux8: case Iop_CmpGT64Ux4:
++ case Iop_CmpGT8Sx32: case Iop_CmpGT16Sx16: case Iop_CmpGT32Sx8: case Iop_CmpGT64Sx4:
++ case Iop_Max8Sx32: case Iop_Max16Sx16: case Iop_Max32Sx8: case Iop_Max64Sx4:
++ case Iop_Max8Ux32: case Iop_Max16Ux16: case Iop_Max32Ux8: case Iop_Max64Ux4:
++ case Iop_Min8Sx32: case Iop_Min16Sx16: case Iop_Min32Sx8: case Iop_Min64Sx4:
++ case Iop_Min8Ux32: case Iop_Min16Ux16: case Iop_Min32Ux8: case Iop_Min64Ux4:
++ case Iop_Add8x32: case Iop_Add16x16: case Iop_Add32x8: case Iop_Add64x4: case Iop_Add128x2:
++ case Iop_Sub8x32: case Iop_Sub16x16: case Iop_Sub32x8: case Iop_Sub64x4: case Iop_Sub128x2:
++ case Iop_QAdd8Ux32: case Iop_QAdd16Ux16: case Iop_QAdd32Ux8: case Iop_QAdd64Ux4:
++ case Iop_QAdd8Sx32: case Iop_QAdd16Sx16: case Iop_QAdd32Sx8: case Iop_QAdd64Sx4:
++ case Iop_QSub8Ux32: case Iop_QSub16Ux16: case Iop_QSub32Ux8: case Iop_QSub64Ux4:
++ case Iop_QSub8Sx32: case Iop_QSub16Sx16: case Iop_QSub32Sx8: case Iop_QSub64Sx4:
++ case Iop_InterleaveHI8x32: case Iop_InterleaveHI16x16: case Iop_InterleaveHI32x8: case Iop_InterleaveHI64x4:
++ case Iop_InterleaveLO8x32: case Iop_InterleaveLO16x16: case Iop_InterleaveLO32x8: case Iop_InterleaveLO64x4:
++ case Iop_PackOddLanes8x32: case Iop_PackOddLanes16x16: case Iop_PackOddLanes32x8:
++ case Iop_PackEvenLanes8x32: case Iop_PackEvenLanes16x16: case Iop_PackEvenLanes32x8:
++ case Iop_Avg8Ux32: case Iop_Avg16Ux16: case Iop_Avg32Ux8: case Iop_Avg64Ux4:
++ case Iop_Avg8Sx32: case Iop_Avg16Sx16: case Iop_Avg32Sx8: case Iop_Avg64Sx4:
++ case Iop_Shl8x32: case Iop_Shl16x16: case Iop_Shl32x8: case Iop_Shl64x4:
++ case Iop_Shr8x32: case Iop_Shr16x16: case Iop_Shr32x8: case Iop_Shr64x4:
++ case Iop_Sar8x32: case Iop_Sar16x16: case Iop_Sar32x8: case Iop_Sar64x4:
++ case Iop_Mul8x32: case Iop_Mul16x16: case Iop_Mul32x8:
++ case Iop_MulHi8Ux32: case Iop_MulHi16Ux16: case Iop_MulHi32Ux8:
++ case Iop_MulHi8Sx32: case Iop_MulHi16Sx16: case Iop_MulHi32Sx8: {
++ LOONGARCH64VecBinOp op;
++ Bool reverse = False;
++ switch (e->Iex.Binop.op) {
++ case Iop_AndV256: op = LAvecbin_VAND_V; break;
++ case Iop_XorV256: op = LAvecbin_VXOR_V; break;
++ case Iop_OrV256: op = LAvecbin_VOR_V; break;
++ case Iop_CmpEQ8x32: op = LAvecbin_VSEQ_B; break;
++ case Iop_CmpEQ16x16: op = LAvecbin_VSEQ_H; break;
++ case Iop_CmpEQ32x8: op = LAvecbin_VSEQ_W; break;
++ case Iop_CmpEQ64x4: op = LAvecbin_VSEQ_D; break;
++ case Iop_CmpGT8Sx32: op = LAvecbin_VSLT_B; reverse = True; break;
++ case Iop_CmpGT16Sx16:op = LAvecbin_VSLT_H; reverse = True; break;
++ case Iop_CmpGT32Sx8: op = LAvecbin_VSLT_W; reverse = True; break;
++ case Iop_CmpGT64Sx4: op = LAvecbin_VSLT_D; reverse = True; break;
++ case Iop_CmpGT8Ux32: op = LAvecbin_VSLT_BU; reverse = True; break;
++ case Iop_CmpGT16Ux16:op = LAvecbin_VSLT_HU; reverse = True; break;
++ case Iop_CmpGT32Ux8: op = LAvecbin_VSLT_WU; reverse = True; break;
++ case Iop_CmpGT64Ux4: op = LAvecbin_VSLT_DU; reverse = True; break;
++ case Iop_Max8Sx32: op = LAvecbin_VMAX_B; break;
++ case Iop_Max16Sx16: op = LAvecbin_VMAX_H; break;
++ case Iop_Max32Sx8: op = LAvecbin_VMAX_W; break;
++ case Iop_Max64Sx4: op = LAvecbin_VMAX_D; break;
++ case Iop_Max8Ux32: op = LAvecbin_VMAX_BU; break;
++ case Iop_Max16Ux16: op = LAvecbin_VMAX_HU; break;
++ case Iop_Max32Ux8: op = LAvecbin_VMAX_WU; break;
++ case Iop_Max64Ux4: op = LAvecbin_VMAX_DU; break;
++ case Iop_Min8Sx32: op = LAvecbin_VMIN_B; break;
++ case Iop_Min16Sx16: op = LAvecbin_VMIN_H; break;
++ case Iop_Min32Sx8: op = LAvecbin_VMIN_W; break;
++ case Iop_Min64Sx4: op = LAvecbin_VMIN_D; break;
++ case Iop_Min8Ux32: op = LAvecbin_VMIN_BU; break;
++ case Iop_Min16Ux16: op = LAvecbin_VMIN_HU; break;
++ case Iop_Min32Ux8: op = LAvecbin_VMIN_WU; break;
++ case Iop_Min64Ux4: op = LAvecbin_VMIN_DU; break;
++ case Iop_Add8x32: op = LAvecbin_VADD_B; break;
++ case Iop_Add16x16: op = LAvecbin_VADD_H; break;
++ case Iop_Add32x8: op = LAvecbin_VADD_W; break;
++ case Iop_Add64x4: op = LAvecbin_VADD_D; break;
++ case Iop_Add128x2: op = LAvecbin_VADD_Q; break;
++ case Iop_Sub8x32: op = LAvecbin_VSUB_B; break;
++ case Iop_Sub16x16: op = LAvecbin_VSUB_H; break;
++ case Iop_Sub32x8: op = LAvecbin_VSUB_W; break;
++ case Iop_Sub64x4: op = LAvecbin_VSUB_D; break;
++ case Iop_Sub128x2: op = LAvecbin_VSUB_Q; break;
++ case Iop_QAdd8Sx32: op = LAvecbin_VSADD_B; break;
++ case Iop_QAdd16Sx16: op = LAvecbin_VSADD_H; break;
++ case Iop_QAdd32Sx8: op = LAvecbin_VSADD_W; break;
++ case Iop_QAdd64Sx4: op = LAvecbin_VSADD_D; break;
++ case Iop_QAdd8Ux32: op = LAvecbin_VSADD_BU; break;
++ case Iop_QAdd16Ux16: op = LAvecbin_VSADD_HU; break;
++ case Iop_QAdd32Ux8: op = LAvecbin_VSADD_WU; break;
++ case Iop_QAdd64Ux4: op = LAvecbin_VSADD_DU; break;
++ case Iop_QSub8Sx32: op = LAvecbin_VSSUB_B; break;
++ case Iop_QSub16Sx16: op = LAvecbin_VSSUB_H; break;
++ case Iop_QSub32Sx8: op = LAvecbin_VSSUB_W; break;
++ case Iop_QSub64Sx4: op = LAvecbin_VSSUB_D; break;
++ case Iop_QSub8Ux32: op = LAvecbin_VSSUB_BU; break;
++ case Iop_QSub16Ux16: op = LAvecbin_VSSUB_HU; break;
++ case Iop_QSub32Ux8: op = LAvecbin_VSSUB_WU; break;
++ case Iop_QSub64Ux4: op = LAvecbin_VSSUB_DU; break;
++ case Iop_InterleaveHI8x32: op = LAvecbin_VILVH_B; break;
++ case Iop_InterleaveHI16x16: op = LAvecbin_VILVH_H; break;
++ case Iop_InterleaveHI32x8: op = LAvecbin_VILVH_W; break;
++ case Iop_InterleaveHI64x4: op = LAvecbin_VILVH_D; break;
++ case Iop_InterleaveLO8x32: op = LAvecbin_VILVL_B; break;
++ case Iop_InterleaveLO16x16: op = LAvecbin_VILVL_H; break;
++ case Iop_InterleaveLO32x8: op = LAvecbin_VILVL_W; break;
++ case Iop_InterleaveLO64x4: op = LAvecbin_VILVL_D; break;
++ case Iop_PackOddLanes8x32: op = LAvecbin_VPICKOD_B; break;
++ case Iop_PackOddLanes16x16: op = LAvecbin_VPICKOD_H; break;
++ case Iop_PackOddLanes32x8: op = LAvecbin_VPICKOD_W; break;
++ case Iop_PackEvenLanes8x32: op = LAvecbin_VPICKEV_B; break;
++ case Iop_PackEvenLanes16x16: op = LAvecbin_VPICKEV_H; break;
++ case Iop_PackEvenLanes32x8: op = LAvecbin_VPICKEV_W; break;
++ case Iop_Avg8Ux32: op = LAvecbin_VAVGR_BU; break;
++ case Iop_Avg16Ux16: op = LAvecbin_VAVGR_HU; break;
++ case Iop_Avg32Ux8: op = LAvecbin_VAVGR_WU; break;
++ case Iop_Avg64Ux4: op = LAvecbin_VAVGR_DU; break;
++ case Iop_Avg8Sx32: op = LAvecbin_VAVGR_B; break;
++ case Iop_Avg16Sx16: op = LAvecbin_VAVGR_H; break;
++ case Iop_Avg32Sx8: op = LAvecbin_VAVGR_W; break;
++ case Iop_Avg64Sx4: op = LAvecbin_VAVGR_D; break;
++ case Iop_Shl8x32: op = LAvecbin_VSLL_B; break;
++ case Iop_Shl16x16: op = LAvecbin_VSLL_H; break;
++ case Iop_Shl32x8: op = LAvecbin_VSLL_W; break;
++ case Iop_Shl64x4: op = LAvecbin_VSLL_D; break;
++ case Iop_Shr8x32: op = LAvecbin_VSRL_B; break;
++ case Iop_Shr16x16: op = LAvecbin_VSRL_H; break;
++ case Iop_Shr32x8: op = LAvecbin_VSRL_W; break;
++ case Iop_Shr64x4: op = LAvecbin_VSRL_D; break;
++ case Iop_Sar8x32: op = LAvecbin_VSRA_B; break;
++ case Iop_Sar16x16: op = LAvecbin_VSRA_H; break;
++ case Iop_Sar32x8: op = LAvecbin_VSRA_W; break;
++ case Iop_Sar64x4: op = LAvecbin_VSRA_D; break;
++ case Iop_Mul8x32: op = LAvecbin_VMUL_B; break;
++ case Iop_Mul16x16: op = LAvecbin_VMUL_H; break;
++ case Iop_Mul32x8: op = LAvecbin_VMUL_W; break;
++ case Iop_MulHi8Ux32: op = LAvecbin_VMUH_BU; break;
++ case Iop_MulHi16Ux16: op = LAvecbin_VMUH_HU; break;
++ case Iop_MulHi32Ux8: op = LAvecbin_VMUH_WU; break;
++ case Iop_MulHi8Sx32: op = LAvecbin_VMUH_B; break;
++ case Iop_MulHi16Sx16: op = LAvecbin_VMUH_H; break;
++ case Iop_MulHi32Sx8: op = LAvecbin_VMUH_W; break;
++ default: vassert(0);
++ }
++ HReg s1Hi, s1Lo, s2Hi, s2Lo;
++ iselV256Expr(&s1Hi, &s1Lo, env, e->Iex.Binop.arg1);
++ iselV256Expr(&s2Hi, &s2Lo, env, e->Iex.Binop.arg2);
++ HReg dHi = newVRegV(env);
++ HReg dLo = newVRegV(env);
++ if (reverse) {
++ addInstr(env, LOONGARCH64Instr_VecBinary(op, LOONGARCH64RI_R(s1Hi), s2Hi, dHi));
++ addInstr(env, LOONGARCH64Instr_VecBinary(op, LOONGARCH64RI_R(s1Lo), s2Lo, dLo));
++ } else {
++ addInstr(env, LOONGARCH64Instr_VecBinary(op, LOONGARCH64RI_R(s2Hi), s1Hi, dHi));
++ addInstr(env, LOONGARCH64Instr_VecBinary(op, LOONGARCH64RI_R(s2Lo), s1Lo, dLo));
++ }
++ *hi = dHi;
++ *lo = dLo;
++ return;
++ }
++ case Iop_ShlN8x32: case Iop_ShlN16x16: case Iop_ShlN32x8: case Iop_ShlN64x4:
++ case Iop_ShrN8x32: case Iop_ShrN16x16: case Iop_ShrN32x8: case Iop_ShrN64x4:
++ case Iop_SarN8x32: case Iop_SarN16x16: case Iop_SarN32x8: case Iop_SarN64x4: {
++ UChar size;
++ LOONGARCH64VecBinOp op;
++ switch (e->Iex.Binop.op) {
++ case Iop_ShlN8x32: op = LAvecbin_VSLLI_B; size = 3; break;
++ case Iop_ShlN16x16: op = LAvecbin_VSLLI_H; size = 4; break;
++ case Iop_ShlN32x8: op = LAvecbin_VSLLI_W; size = 5; break;
++ case Iop_ShlN64x4: op = LAvecbin_VSLLI_D; size = 6; break;
++ case Iop_ShrN8x32: op = LAvecbin_VSRLI_B; size = 3; break;
++ case Iop_ShrN16x16: op = LAvecbin_VSRLI_H; size = 4; break;
++ case Iop_ShrN32x8: op = LAvecbin_VSRLI_W; size = 5; break;
++ case Iop_ShrN64x4: op = LAvecbin_VSRLI_D; size = 6; break;
++ case Iop_SarN8x32: op = LAvecbin_VSRAI_B; size = 3; break;
++ case Iop_SarN16x16: op = LAvecbin_VSRAI_H; size = 4; break;
++ case Iop_SarN32x8: op = LAvecbin_VSRAI_W; size = 5; break;
++ case Iop_SarN64x4: op = LAvecbin_VSRAI_D; size = 6; break;
++ default: vassert(0);
++ }
++ HReg sHi, sLo;
++ iselV256Expr(&sHi, &sLo, env, e->Iex.Binop.arg1);
++ LOONGARCH64RI* src2 = iselIntExpr_RI(env, e->Iex.Binop.arg2, size, False);
++ vassert(e->Iex.Binop.arg2->tag == Iex_Const);
++ vassert(e->Iex.Binop.arg2->Iex.Const.con->tag == Ico_U8);
++ vassert(e->Iex.Binop.arg2->Iex.Const.con->Ico.U8 <= 63);
++ HReg dHi = newVRegV(env);
++ HReg dLo = newVRegV(env);
++ addInstr(env, LOONGARCH64Instr_VecBinary(op, src2, sHi, dHi));
++ addInstr(env, LOONGARCH64Instr_VecBinary(op, src2, sLo, dLo));
++ *hi = dHi;
++ *lo = dLo;
++ return;
++ }
++ default: goto irreducible;
++ }
++ }
+
-+/* Initialise all guest LOONGARCH64 state. */
++ /* --------- Const OP --------- */
++ case Iex_Const: {
++ IRConst *con = e->Iex.Const.con;
+
-+extern
-+void LibVEX_GuestLOONGARCH64_initialise ( /*OUT*/
-+ VexGuestLOONGARCH64State* vex_state );
++ if (con->tag != Ico_V256) {
++ vpanic("iselV256Expr.const(LoongArch)");
++ goto irreducible;
++ }
+
-+#endif /* ndef __LIBVEX_PUB_GUEST_LOONGARCH64_H */
++ HReg dstHi = newVRegV(env);
++ HReg dstLo = newVRegV(env);
++ UShort val = con->Ico.V256;
+
-+/*---------------------------------------------------------------*/
-+/*--- libvex_guest_loongarch64.h ---*/
-+/*---------------------------------------------------------------*/
-diff --git a/VEX/pub/libvex_guest_offsets.h b/VEX/pub/libvex_guest_offsets.h
-index a456b6d..9faa0ce 100644
---- a/VEX/pub/libvex_guest_offsets.h
-+++ b/VEX/pub/libvex_guest_offsets.h
-@@ -162,3 +162,36 @@
- #define OFFSET_mips64_PC 272
- #define OFFSET_mips64_HI 280
- #define OFFSET_mips64_LO 288
-+#define OFFSET_loongarch64_R0 16
-+#define OFFSET_loongarch64_R1 24
-+#define OFFSET_loongarch64_R2 32
-+#define OFFSET_loongarch64_R3 40
-+#define OFFSET_loongarch64_R4 48
-+#define OFFSET_loongarch64_R5 56
-+#define OFFSET_loongarch64_R6 64
-+#define OFFSET_loongarch64_R7 72
-+#define OFFSET_loongarch64_R8 80
-+#define OFFSET_loongarch64_R9 88
-+#define OFFSET_loongarch64_R10 96
-+#define OFFSET_loongarch64_R11 104
-+#define OFFSET_loongarch64_R12 112
-+#define OFFSET_loongarch64_R13 120
-+#define OFFSET_loongarch64_R14 128
-+#define OFFSET_loongarch64_R15 136
-+#define OFFSET_loongarch64_R16 144
-+#define OFFSET_loongarch64_R17 152
-+#define OFFSET_loongarch64_R18 160
-+#define OFFSET_loongarch64_R19 168
-+#define OFFSET_loongarch64_R20 176
-+#define OFFSET_loongarch64_R21 184
-+#define OFFSET_loongarch64_R22 192
-+#define OFFSET_loongarch64_R23 200
-+#define OFFSET_loongarch64_R24 208
-+#define OFFSET_loongarch64_R25 216
-+#define OFFSET_loongarch64_R26 224
-+#define OFFSET_loongarch64_R27 232
-+#define OFFSET_loongarch64_R28 240
-+#define OFFSET_loongarch64_R29 248
-+#define OFFSET_loongarch64_R30 256
-+#define OFFSET_loongarch64_R31 264
-+#define OFFSET_loongarch64_PC 272
-diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h
-index 85805bb..c8b2e8f 100644
---- a/VEX/pub/libvex_ir.h
-+++ b/VEX/pub/libvex_ir.h
-@@ -588,10 +588,10 @@ typedef
-
- /* Binary operations, with rounding. */
- /* :: IRRoundingMode(I32) x F64 x F64 -> F64 */
-- Iop_AddF64, Iop_SubF64, Iop_MulF64, Iop_DivF64,
-+ Iop_AddF64, Iop_SubF64, Iop_MulF64, Iop_DivF64, Iop_ScaleBF64,
-
- /* :: IRRoundingMode(I32) x F32 x F32 -> F32 */
-- Iop_AddF32, Iop_SubF32, Iop_MulF32, Iop_DivF32,
-+ Iop_AddF32, Iop_SubF32, Iop_MulF32, Iop_DivF32, Iop_ScaleBF32,
-
- /* Variants of the above which produce a 64-bit result but which
- round their result to a IEEE float range first. */
-@@ -610,10 +610,10 @@ typedef
-
- /* Unary operations, with rounding. */
- /* :: IRRoundingMode(I32) x F64 -> F64 */
-- Iop_SqrtF64,
-+ Iop_SqrtF64, Iop_RSqrtF64, Iop_LogBF64,
-
- /* :: IRRoundingMode(I32) x F32 -> F32 */
-- Iop_SqrtF32,
-+ Iop_SqrtF32, Iop_RSqrtF32, Iop_LogBF32,
-
- /* :: IRRoundingMode(I32) x F16 -> F16 */
- Iop_SqrtF16,
-@@ -829,10 +829,14 @@ typedef
-
- /* --------- Possibly required by IEEE 754-2008. --------- */
-
-- Iop_MaxNumF64, /* max, F64, numerical operand if other is a qNaN */
-- Iop_MinNumF64, /* min, F64, ditto */
-- Iop_MaxNumF32, /* max, F32, ditto */
-- Iop_MinNumF32, /* min, F32, ditto */
-+ Iop_MaxNumF64, /* max, F64, numerical operand if other is a qNaN */
-+ Iop_MinNumF64, /* min, F64, ditto */
-+ Iop_MaxNumAbsF64, /* max abs, F64, ditto */
-+ Iop_MinNumAbsF64, /* min abs, F64, ditto */
-+ Iop_MaxNumF32, /* max, F32, ditto */
-+ Iop_MinNumF32, /* min, F32, ditto */
-+ Iop_MaxNumAbsF32, /* max abs, F32, ditto */
-+ Iop_MinNumAbsF32, /* min abs, F32, ditto */
-
- /* ------------------ 16-bit scalar FP ------------------ */
-
-@@ -2006,10 +2010,10 @@ typedef
- Iop_ShrN16x16, Iop_ShrN32x8, Iop_ShrN64x4,
- Iop_SarN16x16, Iop_SarN32x8,
-
-- Iop_Max8Sx32, Iop_Max16Sx16, Iop_Max32Sx8,
-- Iop_Max8Ux32, Iop_Max16Ux16, Iop_Max32Ux8,
-- Iop_Min8Sx32, Iop_Min16Sx16, Iop_Min32Sx8,
-- Iop_Min8Ux32, Iop_Min16Ux16, Iop_Min32Ux8,
-+ Iop_Max8Sx32, Iop_Max16Sx16, Iop_Max32Sx8, Iop_Max64Sx4,
-+ Iop_Max8Ux32, Iop_Max16Ux16, Iop_Max32Ux8, Iop_Max64Ux4,
-+ Iop_Min8Sx32, Iop_Min16Sx16, Iop_Min32Sx8, Iop_Min64Sx4,
-+ Iop_Min8Ux32, Iop_Min16Ux16, Iop_Min32Ux8, Iop_Min64Ux4,
-
- Iop_Mul16x16, Iop_Mul32x8,
- Iop_MulHi16Ux16, Iop_MulHi16Sx16,
-@@ -2503,6 +2507,7 @@ typedef
- Ijk_SigFPE, /* current instruction synths generic SIGFPE */
- Ijk_SigFPE_IntDiv, /* current instruction synths SIGFPE - IntDiv */
- Ijk_SigFPE_IntOvf, /* current instruction synths SIGFPE - IntOvf */
-+ Ijk_SigSYS, /* current instruction synths SIGSYS */
- /* Unfortunately, various guest-dependent syscall kinds. They
- all mean: do a syscall before continuing. */
- Ijk_Sys_syscall, /* amd64/x86 'syscall', ppc 'sc', arm 'svc #0' */
-@@ -2662,7 +2667,12 @@ typedef
- /* Needed only on ARM. It cancels a reservation made by a
- preceding Linked-Load, and needs to be handed through to the
- back end, just as LL and SC themselves are. */
-- Imbe_CancelReservation
-+ Imbe_CancelReservation,
-+ /* Needed only on LOONGARCH64. It completes the synchronization
-+ between the store operation and the instruction fetch operation
-+ within a single processor core, and needs to be handed through
-+ to the back end. */
-+ Imbe_InsnFence
- }
- IRMBusEvent;
-
-diff --git a/VEX/pub/libvex_trc_values.h b/VEX/pub/libvex_trc_values.h
-index cfd54de..90e2b60 100644
---- a/VEX/pub/libvex_trc_values.h
-+++ b/VEX/pub/libvex_trc_values.h
-@@ -57,6 +57,7 @@
- continuing */
- #define VEX_TRC_JMP_SIGBUS 93 /* deliver SIGBUS before continuing */
- #define VEX_TRC_JMP_SIGFPE 105 /* deliver SIGFPE before continuing */
-+#define VEX_TRC_JMP_SIGSYS 115 /* deliver SIGSYS before continuing */
-
- #define VEX_TRC_JMP_SIGFPE_INTDIV 97 /* deliver SIGFPE (integer divide
- by zero) before continuing */
-diff --git a/auxprogs/Makefile.in b/auxprogs/Makefile.in
-index cabc2bf..d9481c3 100644
---- a/auxprogs/Makefile.in
-+++ b/auxprogs/Makefile.in
-@@ -613,6 +613,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++ switch (val) {
++ case 0: { /* likely */
++ addInstr(env, LOONGARCH64Instr_VecUnary(LAvecun_VREPLGR2VR_D, hregZERO(), dstHi));
++ addInstr(env, LOONGARCH64Instr_VecUnary(LAvecun_VREPLGR2VR_D, hregZERO(), dstLo));
++ break;
++ }
++ // default: {
++ // HReg r_tmp = newVRegI(env);
++ // UInt i;
++ // addInstr(env, LOONGARCH64Instr_LI(0xfful, r_tmp));
++
++ // if (val & 1) {
++ // addInstr(env, LOONGARCH64Instr_VecUnary(LAvecun_VREPLGR2VR_B, r_tmp, dst));
++ // } else {
++ // addInstr(env, LOONGARCH64Instr_VecUnary(LAvecun_VREPLGR2VR_B, hregZERO(), dst));
++ // }
++
++ // for (i = 1; i < 16; i++) {
++ // val >>= 1;
++
++ // if (val & 1) {
++ // addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_B,
++ // LOONGARCH64RI_I(i, 4, False), r_tmp, dst));
++ // } else {
++ // addInstr(env, LOONGARCH64Instr_VecBinary(LAvecbin_VINSGR2VR_B,
++ // LOONGARCH64RI_I(i, 4, False), hregZERO(), dst));
++ // }
++ // }
++ // break;
++ // }
++ }
++ *hi = dstHi;
++ *lo = dstLo;
++ return;
++ }
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -660,6 +666,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- dist_noinst_SCRIPTS = \
-diff --git a/cachegrind/Makefile.in b/cachegrind/Makefile.in
-index 1363cc6..3fc4a88 100644
---- a/cachegrind/Makefile.in
-+++ b/cachegrind/Makefile.in
-@@ -661,6 +661,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++ default: break;
++ }
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -708,6 +714,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
-
-@@ -798,6 +805,10 @@ TOOL_LDFLAGS_MIPS64_LINUX = \
- -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
- @FLAG_M64@
-
-+TOOL_LDFLAGS_LOONGARCH64_LINUX = \
-+ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
-+ @FLAG_M64@
++ /* We get here if no pattern matched. */
++irreducible:
++ ppIRExpr(e);
++ vpanic("iselV256Expr(loongarch64): cannot reduce tree");
++}
+
- TOOL_LDFLAGS_X86_SOLARIS = \
- $(TOOL_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
-
-@@ -858,6 +869,9 @@ LIBREPLACEMALLOC_MIPS32_LINUX = \
- LIBREPLACEMALLOC_MIPS64_LINUX = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips64-linux.a
-
-+LIBREPLACEMALLOC_LOONGARCH64_LINUX = \
-+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-loongarch64-linux.a
+
- LIBREPLACEMALLOC_X86_SOLARIS = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-solaris.a
-
-@@ -930,6 +944,11 @@ LIBREPLACEMALLOC_LDFLAGS_MIPS64_LINUX = \
- $(LIBREPLACEMALLOC_MIPS64_LINUX) \
- -Wl,--no-whole-archive
-
-+LIBREPLACEMALLOC_LDFLAGS_LOONGARCH64_LINUX = \
-+ -Wl,--whole-archive \
-+ $(LIBREPLACEMALLOC_LOONGARCH64_LINUX) \
-+ -Wl,--no-whole-archive
++/*---------------------------------------------------------*/
++/*--- ISEL: Statements ---*/
++/*---------------------------------------------------------*/
+
- LIBREPLACEMALLOC_LDFLAGS_X86_SOLARIS = \
- -Wl,--whole-archive \
- $(LIBREPLACEMALLOC_X86_SOLARIS) \
-diff --git a/cachegrind/cg_arch.c b/cachegrind/cg_arch.c
-index 68314c9..55f7585 100644
---- a/cachegrind/cg_arch.c
-+++ b/cachegrind/cg_arch.c
-@@ -484,6 +484,13 @@ configure_caches(cache_t *I1c, cache_t *D1c, cache_t *LLc,
- *D1c = (cache_t) { 65536, 2, 64 };
- *LLc = (cache_t) { 262144, 8, 64 };
-
-+#elif defined(VGA_loongarch64)
++static void iselStmtStore ( ISelEnv* env, IRStmt* stmt )
++{
++ IRType tya = typeOfIRExpr(env->type_env, stmt->Ist.Store.addr);
++ IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.Store.data);
+
-+ // Set caches to default (for LOONGARCH64 - 3A5000)
-+ *I1c = (cache_t) { 65536, 4, 64 };
-+ *D1c = (cache_t) { 65536, 4, 64 };
-+ *LLc = (cache_t) { 262144, 16, 64 };
++ if (tya != Ity_I64 || stmt->Ist.Store.end != Iend_LE)
++ vpanic("iselStmt(loongarch64): Ist_Store");
+
- #else
-
- #error "Unknown arch"
-diff --git a/cachegrind/cg_branchpred.c b/cachegrind/cg_branchpred.c
-index 927b7bf..6a97209 100644
---- a/cachegrind/cg_branchpred.c
-+++ b/cachegrind/cg_branchpred.c
-@@ -44,7 +44,7 @@
- guaranteed to be zero? */
- #if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
- || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips) \
-- || defined(VGA_arm64)
-+ || defined(VGA_arm64) || defined(VGA_loongarch64)
- # define N_IADDR_LO_ZERO_BITS 2
- #elif defined(VGA_x86) || defined(VGA_amd64)
- # define N_IADDR_LO_ZERO_BITS 0
-diff --git a/cachegrind/tests/Makefile.in b/cachegrind/tests/Makefile.in
-index 722b1e7..7bb020e 100644
---- a/cachegrind/tests/Makefile.in
-+++ b/cachegrind/tests/Makefile.in
-@@ -629,6 +629,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++ LOONGARCH64AMode* am = iselIntExpr_AMode(env, stmt->Ist.Store.addr, tyd);
++ LOONGARCH64StoreOp op;
++ Bool ok = True;
++ switch (tyd) {
++ case Ity_I8:
++ op = (am->tag == LAam_RI) ? LAstore_ST_B : LAstore_STX_B;
++ break;
++ case Ity_I16:
++ op = (am->tag == LAam_RI) ? LAstore_ST_H : LAstore_STX_H;
++ break;
++ case Ity_I32:
++ op = (am->tag == LAam_RI) ? LAstore_ST_W : LAstore_STX_W;
++ break;
++ case Ity_I64:
++ op = (am->tag == LAam_RI) ? LAstore_ST_D : LAstore_STX_D;
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ if (ok) {
++ HReg src = iselIntExpr_R(env, stmt->Ist.Store.data);
++ addInstr(env, LOONGARCH64Instr_Store(op, am, src));
++ return;
++ }
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -676,6 +682,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/cachegrind/tests/x86/Makefile.in b/cachegrind/tests/x86/Makefile.in
-index 1f7c820..6fcfd84 100644
---- a/cachegrind/tests/x86/Makefile.in
-+++ b/cachegrind/tests/x86/Makefile.in
-@@ -572,6 +572,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++ LOONGARCH64FpStoreOp fop;
++ ok = True;
++ switch (tyd) {
++ case Ity_F32:
++ fop = (am->tag == LAam_RI) ? LAfpstore_FST_S : LAfpstore_FSTX_S;
++ break;
++ case Ity_F64:
++ fop = (am->tag == LAam_RI) ? LAfpstore_FST_D : LAfpstore_FSTX_D;
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ if (ok) {
++ HReg src = iselFltExpr(env, stmt->Ist.Store.data);
++ addInstr(env, LOONGARCH64Instr_FpStore(fop, am, src));
++ return;
++ }
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -619,6 +625,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/callgrind/Makefile.in b/callgrind/Makefile.in
-index 0c33846..a74dfa5 100644
---- a/callgrind/Makefile.in
-+++ b/callgrind/Makefile.in
-@@ -708,6 +708,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++ if (tyd == Ity_V128) {
++ LOONGARCH64VecStoreOp vop = (am->tag == LAam_RI) ? LAvecstore_VST : LAvecstore_VSTX;
++ HReg src = iselV128Expr(env, stmt->Ist.Store.data);
++ addInstr(env, LOONGARCH64Instr_VecStore(vop, am, src));
++ } else if (tyd == Ity_V256) {
++ LOONGARCH64VecStoreOp vop = (am->tag == LAam_RI) ? LAvecstore_VST : LAvecstore_VSTX;
++ HReg addr = iselIntExpr_R(env, stmt->Ist.Store.addr);
++ LOONGARCH64AMode* am16 = LOONGARCH64AMode_RI(addr, 16);
++ HReg hi, lo;
++ iselV256Expr(&hi, &lo, env, stmt->Ist.Store.data);
++ addInstr(env, LOONGARCH64Instr_VecStore(vop, am, lo));
++ addInstr(env, LOONGARCH64Instr_VecStore(LAvecstore_VST, am16, hi));
++ } else {
++ vpanic("iselStmt(loongarch64): Ist_Store");
++ }
++}
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -755,6 +761,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
-
-@@ -845,6 +852,10 @@ TOOL_LDFLAGS_MIPS64_LINUX = \
- -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
- @FLAG_M64@
-
-+TOOL_LDFLAGS_LOONGARCH64_LINUX = \
-+ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
-+ @FLAG_M64@
++static void iselStmtPut ( ISelEnv* env, IRStmt* stmt )
++{
++ IRType ty = typeOfIRExpr(env->type_env, stmt->Ist.Put.data);
+
- TOOL_LDFLAGS_X86_SOLARIS = \
- $(TOOL_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
-
-@@ -905,6 +916,9 @@ LIBREPLACEMALLOC_MIPS32_LINUX = \
- LIBREPLACEMALLOC_MIPS64_LINUX = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips64-linux.a
-
-+LIBREPLACEMALLOC_LOONGARCH64_LINUX = \
-+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-loongarch64-linux.a
++ Bool ri = stmt->Ist.Put.offset < 1024;
++ HReg tmp;
++ LOONGARCH64AMode* am;
+
- LIBREPLACEMALLOC_X86_SOLARIS = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-solaris.a
-
-@@ -977,6 +991,11 @@ LIBREPLACEMALLOC_LDFLAGS_MIPS64_LINUX = \
- $(LIBREPLACEMALLOC_MIPS64_LINUX) \
- -Wl,--no-whole-archive
-
-+LIBREPLACEMALLOC_LDFLAGS_LOONGARCH64_LINUX = \
-+ -Wl,--whole-archive \
-+ $(LIBREPLACEMALLOC_LOONGARCH64_LINUX) \
-+ -Wl,--no-whole-archive
++ if (ri) {
++ am = LOONGARCH64AMode_RI(hregGSP(), stmt->Ist.Put.offset);
++ } else {
++ tmp = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_LI(stmt->Ist.Put.offset, tmp));
++ am = LOONGARCH64AMode_RR(hregGSP(), tmp);
++ }
+
- LIBREPLACEMALLOC_LDFLAGS_X86_SOLARIS = \
- -Wl,--whole-archive \
- $(LIBREPLACEMALLOC_X86_SOLARIS) \
-diff --git a/callgrind/tests/Makefile.in b/callgrind/tests/Makefile.in
-index 5268175..9a98624 100644
---- a/callgrind/tests/Makefile.in
-+++ b/callgrind/tests/Makefile.in
-@@ -614,6 +614,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++ LOONGARCH64StoreOp op;
++ Bool ok = True;
++ switch (ty) {
++ case Ity_I8:
++ op = ri ? LAstore_ST_B : LAstore_STX_B;
++ break;
++ case Ity_I16:
++ op = ri ? LAstore_ST_H : LAstore_STX_H;
++ break;
++ case Ity_I32:
++ op = ri ? LAstore_ST_W : LAstore_STX_W;
++ break;
++ case Ity_I64:
++ op = ri ? LAstore_ST_D : LAstore_STX_D;
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ if (ok) {
++ HReg src = iselIntExpr_R(env, stmt->Ist.Put.data);
++ addInstr(env, LOONGARCH64Instr_Store(op, am, src));
++ return;
++ }
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -661,6 +667,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/config.h b/config.h
-index 34b8917..9bdf4ff 100644
---- a/config.h
-+++ b/config.h
-@@ -96,7 +96,7 @@
- #define HAVE_ASM_UNISTD_H 1
-
- /* Define to 1 if as supports fxsave64/fxrstor64. */
--#define HAVE_AS_AMD64_FXSAVE64 1
-+/* #undef HAVE_AS_AMD64_FXSAVE64 */
-
- /* Define to 1 if as supports floating point phased out category. */
- /* #undef HAVE_AS_PPC_FPPO */
-diff --git a/configure b/configure
-index 26f7d89..9d6deb1 100755
---- a/configure
-+++ b/configure
-@@ -1003,6 +1003,8 @@ VGCONF_PLATFORMS_INCLUDE_AMD64_FREEBSD_FALSE
- VGCONF_PLATFORMS_INCLUDE_AMD64_FREEBSD_TRUE
- VGCONF_PLATFORMS_INCLUDE_X86_FREEBSD_FALSE
- VGCONF_PLATFORMS_INCLUDE_X86_FREEBSD_TRUE
-+VGCONF_PLATFORMS_INCLUDE_LOONGARCH64_LINUX_FALSE
-+VGCONF_PLATFORMS_INCLUDE_LOONGARCH64_LINUX_TRUE
- VGCONF_PLATFORMS_INCLUDE_NANOMIPS_LINUX_FALSE
- VGCONF_PLATFORMS_INCLUDE_NANOMIPS_LINUX_TRUE
- VGCONF_PLATFORMS_INCLUDE_MIPS64_LINUX_FALSE
-@@ -1025,6 +1027,8 @@ VGCONF_PLATFORMS_INCLUDE_AMD64_LINUX_FALSE
- VGCONF_PLATFORMS_INCLUDE_AMD64_LINUX_TRUE
- VGCONF_PLATFORMS_INCLUDE_X86_LINUX_FALSE
- VGCONF_PLATFORMS_INCLUDE_X86_LINUX_TRUE
-+VGCONF_ARCHS_INCLUDE_LOONGARCH64_FALSE
-+VGCONF_ARCHS_INCLUDE_LOONGARCH64_TRUE
- VGCONF_ARCHS_INCLUDE_NANOMIPS_FALSE
- VGCONF_ARCHS_INCLUDE_NANOMIPS_TRUE
- VGCONF_ARCHS_INCLUDE_MIPS64_FALSE
-@@ -6938,6 +6942,12 @@ printf "%s\n" "ok (${host_cpu})" >&6; }
- ARCH_MAX="nanomips"
- ;;
-
-+ loongarch64*)
-+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok (${host_cpu})" >&5
-+printf "%s\n" "ok (${host_cpu})" >&6; }
-+ ARCH_MAX="loongarch64"
-+ ;;
++ LOONGARCH64FpStoreOp fop;
++ ok = True;
++ switch (ty) {
++ case Ity_F32:
++ fop = ri ? LAfpstore_FST_S : LAfpstore_FSTX_S;
++ break;
++ case Ity_F64:
++ fop = ri ? LAfpstore_FST_D : LAfpstore_FSTX_D;
++ break;
++ default:
++ ok = False;
++ break;
++ }
++ if (ok) {
++ HReg src = iselFltExpr(env, stmt->Ist.Put.data);
++ addInstr(env, LOONGARCH64Instr_FpStore(fop, am, src));
++ return;
++ }
+
- *)
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: no (${host_cpu})" >&5
- printf "%s\n" "no (${host_cpu})" >&6; }
-@@ -7764,6 +7774,18 @@ printf "%s\n" "ok (${ARCH_MAX}-${VGCONF_OS})" >&6; }
- valt_load_address_sec_norml="0xUNSET"
- valt_load_address_sec_inner="0xUNSET"
- { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok (${ARCH_MAX}-${VGCONF_OS})" >&5
-+printf "%s\n" "ok (${ARCH_MAX}-${VGCONF_OS})" >&6; }
-+ ;;
-+ loongarch64-linux)
-+ VGCONF_ARCH_PRI="loongarch64"
-+ VGCONF_ARCH_SEC=""
-+ VGCONF_PLATFORM_PRI_CAPS="LOONGARCH64_LINUX"
-+ VGCONF_PLATFORM_SEC_CAPS=""
-+ valt_load_address_pri_norml="0x58000000"
-+ valt_load_address_pri_inner="0x38000000"
-+ valt_load_address_sec_norml="0xUNSET"
-+ valt_load_address_sec_inner="0xUNSET"
-+ { printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: ok (${ARCH_MAX}-${VGCONF_OS})" >&5
- printf "%s\n" "ok (${ARCH_MAX}-${VGCONF_OS})" >&6; }
- ;;
- x86-solaris)
-@@ -7921,6 +7943,14 @@ else
- VGCONF_ARCHS_INCLUDE_NANOMIPS_FALSE=
- fi
-
-+ if test x$VGCONF_PLATFORM_PRI_CAPS = xLOONGARCH64_LINUX ; then
-+ VGCONF_ARCHS_INCLUDE_LOONGARCH64_TRUE=
-+ VGCONF_ARCHS_INCLUDE_LOONGARCH64_FALSE='#'
-+else
-+ VGCONF_ARCHS_INCLUDE_LOONGARCH64_TRUE='#'
-+ VGCONF_ARCHS_INCLUDE_LOONGARCH64_FALSE=
-+fi
++ if (ty == Ity_V128) {
++ LOONGARCH64VecStoreOp vop = ri ? LAvecstore_VST : LAvecstore_VSTX;
++ HReg src = iselV128Expr(env, stmt->Ist.Put.data);
++ addInstr(env, LOONGARCH64Instr_VecStore(vop, am, src));
++ } else if (ty == Ity_V256) {
++ LOONGARCH64VecStoreOp vop = ri ? LAvecstore_VST : LAvecstore_VSTX;
++ LOONGARCH64VecStoreOp vop2;
++ HReg hi, lo;
++ HReg tmp2;
++ LOONGARCH64AMode* am2;
++ if (stmt->Ist.Put.offset + 16 < 1024) {
++ vop2 = LAvecstore_VST;
++ am2 = LOONGARCH64AMode_RI(hregGSP(), stmt->Ist.Put.offset + 16);
++ } else {
++ vop2 = LAvecstore_VSTX;
++ tmp2 = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_LI(stmt->Ist.Put.offset + 16, tmp2));
++ am2 = LOONGARCH64AMode_RR(hregGSP(), tmp2);
++ }
++ iselV256Expr(&hi, &lo, env, stmt->Ist.Put.data);
++ addInstr(env, LOONGARCH64Instr_VecStore(vop, am, lo));
++ addInstr(env, LOONGARCH64Instr_VecStore(vop2, am2, hi));
++ } else {
++ vpanic("iselStmt(loongarch64): Ist_Put");
++ }
++}
+
-
- # Set up VGCONF_PLATFORMS_INCLUDE_. Either one or two of these
- # become defined.
-@@ -8017,6 +8047,14 @@ else
- VGCONF_PLATFORMS_INCLUDE_NANOMIPS_LINUX_FALSE=
- fi
-
-+ if test x$VGCONF_PLATFORM_PRI_CAPS = xLOONGARCH64_LINUX; then
-+ VGCONF_PLATFORMS_INCLUDE_LOONGARCH64_LINUX_TRUE=
-+ VGCONF_PLATFORMS_INCLUDE_LOONGARCH64_LINUX_FALSE='#'
-+else
-+ VGCONF_PLATFORMS_INCLUDE_LOONGARCH64_LINUX_TRUE='#'
-+ VGCONF_PLATFORMS_INCLUDE_LOONGARCH64_LINUX_FALSE=
-+fi
-+
- if test x$VGCONF_PLATFORM_PRI_CAPS = xX86_FREEBSD \
- -o x$VGCONF_PLATFORM_SEC_CAPS = xX86_FREEBSD; then
- VGCONF_PLATFORMS_INCLUDE_X86_FREEBSD_TRUE=
-@@ -8083,7 +8121,8 @@ fi
- -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \
- -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \
- -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX \
-- -o x$VGCONF_PLATFORM_PRI_CAPS = xNANOMIPS_LINUX; then
-+ -o x$VGCONF_PLATFORM_PRI_CAPS = xNANOMIPS_LINUX \
-+ -o x$VGCONF_PLATFORM_PRI_CAPS = xLOONGARCH64_LINUX; then
- VGCONF_OS_IS_LINUX_TRUE=
- VGCONF_OS_IS_LINUX_FALSE='#'
- else
-@@ -18254,7 +18293,8 @@ elif test x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_LINUX \
- -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \
- -o x$VGCONF_PLATFORM_PRI_CAPS = xARM64_LINUX \
- -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX \
-- -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX ; then
-+ -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \
-+ -o x$VGCONF_PLATFORM_PRI_CAPS = xLOONGARCH64_LINUX; then
- mflag_primary=$FLAG_M64
- elif test x$VGCONF_PLATFORM_PRI_CAPS = xX86_DARWIN ; then
- mflag_primary="$FLAG_M32 -arch i386"
-@@ -19213,7 +19253,7 @@ fi
- #----------------------------------------------------------------------------
-
- # Nb: VEX/Makefile is generated from Makefile.vex.in.
--ac_config_files="$ac_config_files Makefile VEX/Makefile:Makefile.vex.in valgrind.spec valgrind.pc glibc-2.X.supp glibc-2.X-helgrind.supp glibc-2.X-drd.supp include/valgrind.h docs/Makefile docs/xml/vg-entities.xml tests/Makefile tests/vg_regtest perf/Makefile perf/vg_perf gdbserver_tests/Makefile gdbserver_tests/solaris/Makefile include/Makefile auxprogs/Makefile mpi/Makefile coregrind/Makefile memcheck/Makefile memcheck/tests/Makefile memcheck/tests/common/Makefile memcheck/tests/amd64/Makefile memcheck/tests/x86/Makefile memcheck/tests/linux/Makefile memcheck/tests/linux/debuginfod-check.vgtest memcheck/tests/darwin/Makefile memcheck/tests/solaris/Makefile memcheck/tests/freebsd/Makefile memcheck/tests/amd64-linux/Makefile memcheck/tests/arm64-linux/Makefile memcheck/tests/x86-linux/Makefile memcheck/tests/amd64-solaris/Makefile memcheck/tests/x86-solaris/Makefile memcheck/tests/amd64-freebsd/Makefile memcheck/tests/x86-freebsd/Makefile memcheck/tests/ppc32/Makefile memcheck/tests/ppc64/Makefile memcheck/tests/s390x/Makefile memcheck/tests/mips32/Makefile memcheck/tests/mips64/Makefile memcheck/tests/vbit-test/Makefile cachegrind/Makefile cachegrind/tests/Makefile cachegrind/tests/x86/Makefile cachegrind/cg_annotate cachegrind/cg_diff cachegrind/cg_merge callgrind/Makefile callgrind/callgrind_annotate callgrind/callgrind_control callgrind/tests/Makefile helgrind/Makefile helgrind/tests/Makefile drd/Makefile drd/scripts/download-and-build-splash2 drd/tests/Makefile massif/Makefile massif/tests/Makefile massif/ms_print dhat/Makefile dhat/tests/Makefile lackey/Makefile lackey/tests/Makefile none/Makefile none/tests/Makefile none/tests/scripts/Makefile none/tests/amd64/Makefile none/tests/ppc32/Makefile none/tests/ppc64/Makefile none/tests/x86/Makefile none/tests/arm/Makefile none/tests/arm64/Makefile none/tests/s390x/Makefile none/tests/mips32/Makefile none/tests/mips64/Makefile none/tests/nanomips/Makefile none/tests/linux/Makefile none/tests/darwin/Makefile none/tests/solaris/Makefile none/tests/freebsd/Makefile none/tests/amd64-linux/Makefile none/tests/x86-linux/Makefile none/tests/amd64-darwin/Makefile none/tests/x86-darwin/Makefile none/tests/amd64-solaris/Makefile none/tests/x86-solaris/Makefile none/tests/x86-freebsd/Makefile exp-bbv/Makefile exp-bbv/tests/Makefile exp-bbv/tests/x86/Makefile exp-bbv/tests/x86-linux/Makefile exp-bbv/tests/amd64-linux/Makefile exp-bbv/tests/ppc32-linux/Makefile exp-bbv/tests/arm-linux/Makefile shared/Makefile solaris/Makefile"
-+ac_config_files="$ac_config_files Makefile VEX/Makefile:Makefile.vex.in valgrind.spec valgrind.pc glibc-2.X.supp glibc-2.X-helgrind.supp glibc-2.X-drd.supp include/valgrind.h docs/Makefile docs/xml/vg-entities.xml tests/Makefile tests/vg_regtest perf/Makefile perf/vg_perf gdbserver_tests/Makefile gdbserver_tests/solaris/Makefile include/Makefile auxprogs/Makefile mpi/Makefile coregrind/Makefile memcheck/Makefile memcheck/tests/Makefile memcheck/tests/common/Makefile memcheck/tests/amd64/Makefile memcheck/tests/x86/Makefile memcheck/tests/linux/Makefile memcheck/tests/linux/debuginfod-check.vgtest memcheck/tests/darwin/Makefile memcheck/tests/solaris/Makefile memcheck/tests/freebsd/Makefile memcheck/tests/amd64-linux/Makefile memcheck/tests/arm64-linux/Makefile memcheck/tests/x86-linux/Makefile memcheck/tests/loongarch64-linux/Makefile memcheck/tests/amd64-solaris/Makefile memcheck/tests/x86-solaris/Makefile memcheck/tests/amd64-freebsd/Makefile memcheck/tests/x86-freebsd/Makefile memcheck/tests/ppc32/Makefile memcheck/tests/ppc64/Makefile memcheck/tests/s390x/Makefile memcheck/tests/mips32/Makefile memcheck/tests/mips64/Makefile memcheck/tests/vbit-test/Makefile cachegrind/Makefile cachegrind/tests/Makefile cachegrind/tests/x86/Makefile cachegrind/cg_annotate cachegrind/cg_diff cachegrind/cg_merge callgrind/Makefile callgrind/callgrind_annotate callgrind/callgrind_control callgrind/tests/Makefile helgrind/Makefile helgrind/tests/Makefile drd/Makefile drd/scripts/download-and-build-splash2 drd/tests/Makefile massif/Makefile massif/tests/Makefile massif/ms_print dhat/Makefile dhat/tests/Makefile lackey/Makefile lackey/tests/Makefile none/Makefile none/tests/Makefile none/tests/scripts/Makefile none/tests/amd64/Makefile none/tests/ppc32/Makefile none/tests/ppc64/Makefile none/tests/x86/Makefile none/tests/arm/Makefile none/tests/arm64/Makefile none/tests/s390x/Makefile none/tests/mips32/Makefile none/tests/mips64/Makefile none/tests/nanomips/Makefile none/tests/loongarch64/Makefile none/tests/linux/Makefile none/tests/darwin/Makefile none/tests/solaris/Makefile none/tests/freebsd/Makefile none/tests/amd64-linux/Makefile none/tests/x86-linux/Makefile none/tests/amd64-darwin/Makefile none/tests/x86-darwin/Makefile none/tests/amd64-solaris/Makefile none/tests/x86-solaris/Makefile none/tests/x86-freebsd/Makefile exp-bbv/Makefile exp-bbv/tests/Makefile exp-bbv/tests/x86/Makefile exp-bbv/tests/x86-linux/Makefile exp-bbv/tests/amd64-linux/Makefile exp-bbv/tests/ppc32-linux/Makefile exp-bbv/tests/arm-linux/Makefile shared/Makefile solaris/Makefile"
-
- ac_config_files="$ac_config_files coregrind/link_tool_exe_linux"
-
-@@ -19450,6 +19490,10 @@ if test -z "${VGCONF_ARCHS_INCLUDE_NANOMIPS_TRUE}" && test -z "${VGCONF_ARCHS_IN
- as_fn_error $? "conditional \"VGCONF_ARCHS_INCLUDE_NANOMIPS\" was never defined.
- Usually this means the macro was only invoked conditionally." "$LINENO" 5
- fi
-+if test -z "${VGCONF_ARCHS_INCLUDE_LOONGARCH64_TRUE}" && test -z "${VGCONF_ARCHS_INCLUDE_LOONGARCH64_FALSE}"; then
-+ as_fn_error $? "conditional \"VGCONF_ARCHS_INCLUDE_LOONGARCH64\" was never defined.
-+Usually this means the macro was only invoked conditionally." "$LINENO" 5
-+fi
- if test -z "${VGCONF_PLATFORMS_INCLUDE_X86_LINUX_TRUE}" && test -z "${VGCONF_PLATFORMS_INCLUDE_X86_LINUX_FALSE}"; then
- as_fn_error $? "conditional \"VGCONF_PLATFORMS_INCLUDE_X86_LINUX\" was never defined.
- Usually this means the macro was only invoked conditionally." "$LINENO" 5
-@@ -19494,6 +19538,10 @@ if test -z "${VGCONF_PLATFORMS_INCLUDE_NANOMIPS_LINUX_TRUE}" && test -z "${VGCON
- as_fn_error $? "conditional \"VGCONF_PLATFORMS_INCLUDE_NANOMIPS_LINUX\" was never defined.
- Usually this means the macro was only invoked conditionally." "$LINENO" 5
- fi
-+if test -z "${VGCONF_PLATFORMS_INCLUDE_LOONGARCH64_LINUX_TRUE}" && test -z "${VGCONF_PLATFORMS_INCLUDE_LOONGARCH64_LINUX_FALSE}"; then
-+ as_fn_error $? "conditional \"VGCONF_PLATFORMS_INCLUDE_LOONGARCH64_LINUX\" was never defined.
-+Usually this means the macro was only invoked conditionally." "$LINENO" 5
-+fi
- if test -z "${VGCONF_PLATFORMS_INCLUDE_X86_FREEBSD_TRUE}" && test -z "${VGCONF_PLATFORMS_INCLUDE_X86_FREEBSD_FALSE}"; then
- as_fn_error $? "conditional \"VGCONF_PLATFORMS_INCLUDE_X86_FREEBSD\" was never defined.
- Usually this means the macro was only invoked conditionally." "$LINENO" 5
-@@ -20752,6 +20800,7 @@ do
- "memcheck/tests/amd64-linux/Makefile") CONFIG_FILES="$CONFIG_FILES memcheck/tests/amd64-linux/Makefile" ;;
- "memcheck/tests/arm64-linux/Makefile") CONFIG_FILES="$CONFIG_FILES memcheck/tests/arm64-linux/Makefile" ;;
- "memcheck/tests/x86-linux/Makefile") CONFIG_FILES="$CONFIG_FILES memcheck/tests/x86-linux/Makefile" ;;
-+ "memcheck/tests/loongarch64-linux/Makefile") CONFIG_FILES="$CONFIG_FILES memcheck/tests/loongarch64-linux/Makefile" ;;
- "memcheck/tests/amd64-solaris/Makefile") CONFIG_FILES="$CONFIG_FILES memcheck/tests/amd64-solaris/Makefile" ;;
- "memcheck/tests/x86-solaris/Makefile") CONFIG_FILES="$CONFIG_FILES memcheck/tests/x86-solaris/Makefile" ;;
- "memcheck/tests/amd64-freebsd/Makefile") CONFIG_FILES="$CONFIG_FILES memcheck/tests/amd64-freebsd/Makefile" ;;
-@@ -20797,6 +20846,7 @@ do
- "none/tests/mips32/Makefile") CONFIG_FILES="$CONFIG_FILES none/tests/mips32/Makefile" ;;
- "none/tests/mips64/Makefile") CONFIG_FILES="$CONFIG_FILES none/tests/mips64/Makefile" ;;
- "none/tests/nanomips/Makefile") CONFIG_FILES="$CONFIG_FILES none/tests/nanomips/Makefile" ;;
-+ "none/tests/loongarch64/Makefile") CONFIG_FILES="$CONFIG_FILES none/tests/loongarch64/Makefile" ;;
- "none/tests/linux/Makefile") CONFIG_FILES="$CONFIG_FILES none/tests/linux/Makefile" ;;
- "none/tests/darwin/Makefile") CONFIG_FILES="$CONFIG_FILES none/tests/darwin/Makefile" ;;
- "none/tests/solaris/Makefile") CONFIG_FILES="$CONFIG_FILES none/tests/solaris/Makefile" ;;
-diff --git a/configure.ac b/configure.ac
-index bf024ac..47485d1 100755
---- a/configure.ac
-+++ b/configure.ac
-@@ -310,6 +310,11 @@ case "${host_cpu}" in
- ARCH_MAX="nanomips"
- ;;
-
-+ loongarch64*)
-+ AC_MSG_RESULT([ok (${host_cpu})])
-+ ARCH_MAX="loongarch64"
-+ ;;
++static void iselStmtTmp ( ISelEnv* env, IRStmt* stmt )
++{
++ IRTemp tmp = stmt->Ist.WrTmp.tmp;
++ IRType ty = typeOfIRTemp(env->type_env, tmp);
++
++ switch (ty) {
++ case Ity_I8:
++ case Ity_I16:
++ case Ity_I32:
++ case Ity_I64: {
++ HReg dst = lookupIRTemp(env, tmp);
++ HReg src = iselIntExpr_R(env, stmt->Ist.WrTmp.data);
++ addInstr(env, LOONGARCH64Instr_Move(dst, src));
++ break;
++ }
++ case Ity_I1: {
++ HReg dst = lookupIRTemp(env, tmp);
++ HReg src = iselCondCode_R(env, stmt->Ist.WrTmp.data);
++ addInstr(env, LOONGARCH64Instr_Move(dst, src));
++ break;
++ }
++ case Ity_I128: {
++ HReg rHi, rLo, dstHi, dstLo;
++ iselInt128Expr(&rHi, &rLo, env, stmt->Ist.WrTmp.data);
++ lookupIRTempPair(&dstHi, &dstLo, env, tmp);
++ addInstr(env, LOONGARCH64Instr_Move(dstHi, rHi));
++ addInstr(env, LOONGARCH64Instr_Move(dstLo, rLo));
++ break;
++ }
++ case Ity_F32: {
++ HReg dst = lookupIRTemp(env, tmp);
++ HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_FMOV_S, src, dst));
++ break;
++ }
++ case Ity_F64: {
++ HReg dst = lookupIRTemp(env, tmp);
++ HReg src = iselFltExpr(env, stmt->Ist.WrTmp.data);
++ addInstr(env, LOONGARCH64Instr_FpMove(LAfpmove_FMOV_D, src, dst));
++ break;
++ }
++ case Ity_V128: {
++ HReg dst = lookupIRTemp(env, tmp);
++ HReg src = iselV128Expr(env, stmt->Ist.WrTmp.data);
++ addInstr(env, LOONGARCH64Instr_VecMove(dst, src));
++ break;
++ }
++ case Ity_V256: {
++ HReg hi, lo, dstHi, dstLo;
++ lookupIRTempPair(&dstHi, &dstLo, env, tmp);
++ iselV256Expr(&hi, &lo, env, stmt->Ist.WrTmp.data);
++ addInstr(env, LOONGARCH64Instr_VecMove(dstHi, hi));
++ addInstr(env, LOONGARCH64Instr_VecMove(dstLo, lo));
++ break;
++ }
++ default:
++ vpanic("iselStmt(loongarch64): Ist_WrTmp");
++ break;
++ }
++}
++
++static void iselStmtDirty ( ISelEnv* env, IRStmt* stmt )
++{
++ IRDirty* d = stmt->Ist.Dirty.details;
++
++ /* Figure out the return type, if any. */
++ IRType retty = Ity_INVALID;
++ if (d->tmp != IRTemp_INVALID)
++ retty = typeOfIRTemp(env->type_env, d->tmp);
++
++ Bool retty_ok = False;
++ switch (retty) {
++ case Ity_INVALID: /* function doesn't return anything */
++ case Ity_I8: case Ity_I16: case Ity_I32: case Ity_I64:
++ case Ity_V128: case Ity_V256:
++ retty_ok = True;
++ break;
++ default:
++ break;
++ }
++ if (!retty_ok)
++ vpanic("iselStmt(loongarch64): Ist_Dirty");
++
++ /* Marshal args, do the call, and set the return value to 0x555..555
++ if this is a conditional call that returns a value and the
++ call is skipped. */
++ UInt addToSp = 0;
++ RetLoc rloc = mk_RetLoc_INVALID();
++ doHelperCall(&addToSp, &rloc, env, d->guard, d->cee, retty, d->args);
++ vassert(is_sane_RetLoc(rloc));
++
++ /* Now figure out what to do with the returned value, if any. */
++ switch (retty) {
++ case Ity_INVALID: {
++ /* No return value. Nothing to do. */
++ vassert(d->tmp == IRTemp_INVALID);
++ vassert(rloc.pri == RLPri_None);
++ vassert(addToSp == 0);
++ break;
++ }
++ case Ity_I8: case Ity_I16: case Ity_I32: case Ity_I64: {
++ vassert(rloc.pri == RLPri_Int);
++ vassert(addToSp == 0);
++ /* The returned value is in $a0. Park it in the register
++ associated with tmp. */
++ HReg dst = lookupIRTemp(env, d->tmp);
++ addInstr(env, LOONGARCH64Instr_Move(dst, hregLOONGARCH64_R4()));
++ break;
++ }
++ case Ity_V128: {
++ /* The returned value is on the stack, and *retloc tells
++ us where. Fish it off the stack and then move the
++ stack pointer upwards to clear it, as directed by
++ doHelperCall. */
++ vassert(rloc.pri == RLPri_V128SpRel);
++ vassert((rloc.spOff < 512) && (rloc.spOff > -512));
++ vassert(addToSp >= 16);
++ HReg dst = lookupIRTemp(env, d->tmp);
++ HReg tmp = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_Move(tmp, hregSP()));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D,
++ LOONGARCH64RI_I(rloc.spOff, 12, True),
++ tmp, tmp));
++ addInstr(env, LOONGARCH64Instr_VecLoad(LAvecload_VLD,
++ LOONGARCH64AMode_RI(tmp, 0),
++ dst));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D,
++ LOONGARCH64RI_I(addToSp, 12, True),
++ hregSP(), hregSP()));
++ break;
++ }
++ case Ity_V256: {
++ /* See comments for Ity_V128. */
++ vassert(rloc.pri == RLPri_V256SpRel);
++ vassert((rloc.spOff + 16 < 512) && (rloc.spOff > -512));
++ vassert(addToSp >= 32);
++ HReg dstLo, dstHi;
++ lookupIRTempPair(&dstHi, &dstLo, env, d->tmp);
++ HReg tmp = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_Move(tmp, hregSP()));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D,
++ LOONGARCH64RI_I(rloc.spOff, 12, True),
++ tmp, tmp));
++ addInstr(env, LOONGARCH64Instr_VecLoad(LAvecload_VLD,
++ LOONGARCH64AMode_RI(tmp, 0),
++ dstLo));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D,
++ LOONGARCH64RI_I(16, 12, True),
++ tmp, tmp));
++ addInstr(env, LOONGARCH64Instr_VecLoad(LAvecload_VLD,
++ LOONGARCH64AMode_RI(tmp, 0),
++ dstHi));
++ addInstr(env, LOONGARCH64Instr_Binary(LAbin_ADDI_D,
++ LOONGARCH64RI_I(addToSp, 12, True),
++ hregSP(), hregSP()));
++ break;
++ }
++ default:
++ /*NOTREACHED*/
++ vassert(0);
++ break;
++ }
++}
++
++static void iselStmtLLSC ( ISelEnv* env, IRStmt* stmt )
++{
++ IRTemp res = stmt->Ist.LLSC.result;
++ IRType tya = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.addr);
++
++ /* Temporary solution; this need to be rewritten again for LOONGARCH64.
++ On LOONGARCH64 you can not read from address that is locked with LL
++ before SC. If you read from address that is locked than SC will fall.
++ */
++ if (stmt->Ist.LLSC.storedata == NULL) {
++ /* LL */
++ IRType ty = typeOfIRTemp(env->type_env, res);
++ LOONGARCH64LLSCOp op;
++ switch (ty) {
++ case Ity_I32:
++ op = LAllsc_LL_W;
++ break;
++ case Ity_I64:
++ op = LAllsc_LL_D;
++ break;
++ default:
++ vpanic("iselStmt(loongarch64): Ist_LLSC");
++ break;
++ }
++ LOONGARCH64AMode* addr = iselIntExpr_AMode(env, stmt->Ist.LLSC.addr, tya);
++ HReg val = lookupIRTemp(env, res);
++ addInstr(env, LOONGARCH64Instr_LLSC(op, True, addr, val));
++ } else {
++ /* SC */
++ IRType tyd = typeOfIRExpr(env->type_env, stmt->Ist.LLSC.storedata);
++ LOONGARCH64LLSCOp op;
++ switch (tyd) {
++ case Ity_I32:
++ op = LAllsc_SC_W;
++ break;
++ case Ity_I64:
++ op = LAllsc_SC_D;
++ break;
++ default:
++ vpanic("iselStmt(loongarch64): Ist_LLSC");
++ break;
++ }
++ LOONGARCH64AMode* addr = iselIntExpr_AMode(env, stmt->Ist.LLSC.addr, tya);
++ HReg val = iselIntExpr_R(env, stmt->Ist.LLSC.storedata);
++ HReg dst = lookupIRTemp(env, res);
++ HReg tmp = newVRegI(env);
++ addInstr(env, LOONGARCH64Instr_Move(tmp, val));
++ addInstr(env, LOONGARCH64Instr_LLSC(op, False, addr, tmp));
++ addInstr(env, LOONGARCH64Instr_Move(dst, tmp));
++ }
++}
+
- *)
- AC_MSG_RESULT([no (${host_cpu})])
- AC_MSG_ERROR([Unsupported host architecture. Sorry])
-@@ -952,6 +957,17 @@ case "$ARCH_MAX-$VGCONF_OS" in
- valt_load_address_sec_inner="0xUNSET"
- AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})])
- ;;
-+ loongarch64-linux)
-+ VGCONF_ARCH_PRI="loongarch64"
-+ VGCONF_ARCH_SEC=""
-+ VGCONF_PLATFORM_PRI_CAPS="LOONGARCH64_LINUX"
-+ VGCONF_PLATFORM_SEC_CAPS=""
-+ valt_load_address_pri_norml="0x58000000"
-+ valt_load_address_pri_inner="0x38000000"
-+ valt_load_address_sec_norml="0xUNSET"
-+ valt_load_address_sec_inner="0xUNSET"
-+ AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})])
-+ ;;
- x86-solaris)
- VGCONF_ARCH_PRI="x86"
- VGCONF_ARCH_SEC=""
-@@ -1044,6 +1060,8 @@ AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_MIPS64,
- test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX )
- AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_NANOMIPS,
- test x$VGCONF_PLATFORM_PRI_CAPS = xNANOMIPS_LINUX )
-+AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_LOONGARCH64,
-+ test x$VGCONF_PLATFORM_PRI_CAPS = xLOONGARCH64_LINUX )
-
- # Set up VGCONF_PLATFORMS_INCLUDE_. Either one or two of these
- # become defined.
-@@ -1074,6 +1092,8 @@ AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_MIPS64_LINUX,
- test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX)
- AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_NANOMIPS_LINUX,
- test x$VGCONF_PLATFORM_PRI_CAPS = xNANOMIPS_LINUX)
-+AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_LOONGARCH64_LINUX,
-+ test x$VGCONF_PLATFORM_PRI_CAPS = xLOONGARCH64_LINUX)
- AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_X86_FREEBSD,
- test x$VGCONF_PLATFORM_PRI_CAPS = xX86_FREEBSD \
- -o x$VGCONF_PLATFORM_SEC_CAPS = xX86_FREEBSD)
-@@ -1105,7 +1125,8 @@ AM_CONDITIONAL(VGCONF_OS_IS_LINUX,
- -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \
- -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \
- -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX \
-- -o x$VGCONF_PLATFORM_PRI_CAPS = xNANOMIPS_LINUX)
-+ -o x$VGCONF_PLATFORM_PRI_CAPS = xNANOMIPS_LINUX \
-+ -o x$VGCONF_PLATFORM_PRI_CAPS = xLOONGARCH64_LINUX)
- AM_CONDITIONAL(VGCONF_OS_IS_FREEBSD,
- test x$VGCONF_PLATFORM_PRI_CAPS = xX86_FREEBSD \
- -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_FREEBSD)
-@@ -4979,7 +5000,8 @@ elif test x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_LINUX \
- -o x$VGCONF_PLATFORM_PRI_CAPS = xPPC64_LINUX \
- -o x$VGCONF_PLATFORM_PRI_CAPS = xARM64_LINUX \
- -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX \
-- -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX ; then
-+ -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \
-+ -o x$VGCONF_PLATFORM_PRI_CAPS = xLOONGARCH64_LINUX; then
- mflag_primary=$FLAG_M64
- elif test x$VGCONF_PLATFORM_PRI_CAPS = xX86_DARWIN ; then
- mflag_primary="$FLAG_M32 -arch i386"
-@@ -5505,6 +5527,7 @@ AC_CONFIG_FILES([
- memcheck/tests/amd64-linux/Makefile
- memcheck/tests/arm64-linux/Makefile
- memcheck/tests/x86-linux/Makefile
-+ memcheck/tests/loongarch64-linux/Makefile
- memcheck/tests/amd64-solaris/Makefile
- memcheck/tests/x86-solaris/Makefile
- memcheck/tests/amd64-freebsd/Makefile
-@@ -5550,6 +5573,7 @@ AC_CONFIG_FILES([
- none/tests/mips32/Makefile
- none/tests/mips64/Makefile
- none/tests/nanomips/Makefile
-+ none/tests/loongarch64/Makefile
- none/tests/linux/Makefile
- none/tests/darwin/Makefile
- none/tests/solaris/Makefile
-diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
-index 8a7f753..54c4824 100644
---- a/coregrind/Makefile.am
-+++ b/coregrind/Makefile.am
-@@ -386,6 +386,7 @@ COREGRIND_SOURCES_COMMON = \
- m_dispatch/dispatch-mips32-linux.S \
- m_dispatch/dispatch-mips64-linux.S \
- m_dispatch/dispatch-nanomips-linux.S \
-+ m_dispatch/dispatch-loongarch64-linux.S \
- m_dispatch/dispatch-x86-freebsd.S \
- m_dispatch/dispatch-amd64-freebsd.S \
- m_dispatch/dispatch-x86-darwin.S \
-@@ -409,6 +410,7 @@ COREGRIND_SOURCES_COMMON = \
- m_gdbserver/valgrind-low-mips32.c \
- m_gdbserver/valgrind-low-mips64.c \
- m_gdbserver/valgrind-low-nanomips.c \
-+ m_gdbserver/valgrind-low-loongarch64.c \
- m_gdbserver/version.c \
- m_initimg/initimg-linux.c \
- m_initimg/initimg-freebsd.c \
-@@ -436,6 +438,7 @@ COREGRIND_SOURCES_COMMON = \
- m_sigframe/sigframe-mips32-linux.c \
- m_sigframe/sigframe-mips64-linux.c \
- m_sigframe/sigframe-nanomips-linux.c \
-+ m_sigframe/sigframe-loongarch64-linux.c \
- m_sigframe/sigframe-x86-darwin.c \
- m_sigframe/sigframe-amd64-darwin.c \
- m_sigframe/sigframe-solaris.c \
-@@ -450,6 +453,7 @@ COREGRIND_SOURCES_COMMON = \
- m_syswrap/syscall-mips32-linux.S \
- m_syswrap/syscall-mips64-linux.S \
- m_syswrap/syscall-nanomips-linux.S \
-+ m_syswrap/syscall-loongarch64-linux.S \
- m_syswrap/syscall-x86-freebsd.S \
- m_syswrap/syscall-amd64-freebsd.S \
- m_syswrap/syscall-x86-darwin.S \
-@@ -475,6 +479,7 @@ COREGRIND_SOURCES_COMMON = \
- m_syswrap/syswrap-mips32-linux.c \
- m_syswrap/syswrap-mips64-linux.c \
- m_syswrap/syswrap-nanomips-linux.c \
-+ m_syswrap/syswrap-loongarch64-linux.c \
- m_syswrap/syswrap-x86-darwin.c \
- m_syswrap/syswrap-amd64-darwin.c \
- m_syswrap/syswrap-xen.c \
-@@ -767,7 +772,15 @@ GDBSERVER_XML_FILES = \
- m_gdbserver/mips64-linux-valgrind.xml \
- m_gdbserver/mips64-fpu-valgrind-s1.xml \
- m_gdbserver/mips64-fpu-valgrind-s2.xml \
-- m_gdbserver/mips64-fpu.xml
-+ m_gdbserver/mips64-fpu.xml \
-+ m_gdbserver/loongarch-base64.xml \
-+ m_gdbserver/loongarch-fpu64.xml \
-+ m_gdbserver/loongarch64-linux.xml \
-+ m_gdbserver/loongarch-base64-valgrind-s1.xml \
-+ m_gdbserver/loongarch-base64-valgrind-s2.xml \
-+ m_gdbserver/loongarch-fpu64-valgrind-s1.xml \
-+ m_gdbserver/loongarch-fpu64-valgrind-s2.xml \
-+ m_gdbserver/loongarch64-linux-valgrind.xml
-
- # so as to make sure these get copied into the install tree
- vglibdir = $(pkglibexecdir)
-diff --git a/coregrind/Makefile.in b/coregrind/Makefile.in
-index 554ee94..a14da8d 100644
---- a/coregrind/Makefile.in
-+++ b/coregrind/Makefile.in
-@@ -280,6 +280,7 @@ am__libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_SOURCES_DIST = \
- m_dispatch/dispatch-mips32-linux.S \
- m_dispatch/dispatch-mips64-linux.S \
- m_dispatch/dispatch-nanomips-linux.S \
-+ m_dispatch/dispatch-loongarch64-linux.S \
- m_dispatch/dispatch-x86-freebsd.S \
- m_dispatch/dispatch-amd64-freebsd.S \
- m_dispatch/dispatch-x86-darwin.S \
-@@ -298,7 +299,8 @@ am__libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_SOURCES_DIST = \
- m_gdbserver/valgrind-low-s390x.c \
- m_gdbserver/valgrind-low-mips32.c \
- m_gdbserver/valgrind-low-mips64.c \
-- m_gdbserver/valgrind-low-nanomips.c m_gdbserver/version.c \
-+ m_gdbserver/valgrind-low-nanomips.c \
-+ m_gdbserver/valgrind-low-loongarch64.c m_gdbserver/version.c \
- m_initimg/initimg-linux.c m_initimg/initimg-freebsd.c \
- m_initimg/initimg-darwin.c m_initimg/initimg-solaris.c \
- m_mach/mach_basics.c m_mach/mach_msg.c \
-@@ -319,6 +321,7 @@ am__libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_SOURCES_DIST = \
- m_sigframe/sigframe-mips32-linux.c \
- m_sigframe/sigframe-mips64-linux.c \
- m_sigframe/sigframe-nanomips-linux.c \
-+ m_sigframe/sigframe-loongarch64-linux.c \
- m_sigframe/sigframe-x86-darwin.c \
- m_sigframe/sigframe-amd64-darwin.c \
- m_sigframe/sigframe-solaris.c m_syswrap/syscall-x86-linux.S \
-@@ -331,6 +334,7 @@ am__libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_SOURCES_DIST = \
- m_syswrap/syscall-mips32-linux.S \
- m_syswrap/syscall-mips64-linux.S \
- m_syswrap/syscall-nanomips-linux.S \
-+ m_syswrap/syscall-loongarch64-linux.S \
- m_syswrap/syscall-x86-freebsd.S \
- m_syswrap/syscall-amd64-freebsd.S \
- m_syswrap/syscall-x86-darwin.S \
-@@ -350,6 +354,7 @@ am__libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_SOURCES_DIST = \
- m_syswrap/syswrap-mips32-linux.c \
- m_syswrap/syswrap-mips64-linux.c \
- m_syswrap/syswrap-nanomips-linux.c \
-+ m_syswrap/syswrap-loongarch64-linux.c \
- m_syswrap/syswrap-x86-darwin.c \
- m_syswrap/syswrap-amd64-darwin.c m_syswrap/syswrap-xen.c \
- m_syswrap/syswrap-x86-solaris.c \
-@@ -437,6 +442,7 @@ am__objects_1 = libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m_addrinfo.$(OBJEXT
- m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-mips32-linux.$(OBJEXT) \
- m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-mips64-linux.$(OBJEXT) \
- m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-nanomips-linux.$(OBJEXT) \
-+ m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.$(OBJEXT) \
- m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-x86-freebsd.$(OBJEXT) \
- m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-amd64-freebsd.$(OBJEXT) \
- m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-x86-darwin.$(OBJEXT) \
-@@ -460,6 +466,7 @@ am__objects_1 = libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m_addrinfo.$(OBJEXT
- m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-mips32.$(OBJEXT) \
- m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-mips64.$(OBJEXT) \
- m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-nanomips.$(OBJEXT) \
-+ m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.$(OBJEXT) \
- m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-version.$(OBJEXT) \
- m_initimg/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-initimg-linux.$(OBJEXT) \
- m_initimg/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-initimg-freebsd.$(OBJEXT) \
-@@ -487,6 +494,7 @@ am__objects_1 = libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m_addrinfo.$(OBJEXT
- m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-mips32-linux.$(OBJEXT) \
- m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-mips64-linux.$(OBJEXT) \
- m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-nanomips-linux.$(OBJEXT) \
-+ m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.$(OBJEXT) \
- m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-x86-darwin.$(OBJEXT) \
- m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-amd64-darwin.$(OBJEXT) \
- m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-solaris.$(OBJEXT) \
-@@ -501,6 +509,7 @@ am__objects_1 = libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m_addrinfo.$(OBJEXT
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-mips32-linux.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-mips64-linux.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-nanomips-linux.$(OBJEXT) \
-+ m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-x86-freebsd.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-amd64-freebsd.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-x86-darwin.$(OBJEXT) \
-@@ -526,6 +535,7 @@ am__objects_1 = libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m_addrinfo.$(OBJEXT
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-mips32-linux.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-mips64-linux.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-nanomips-linux.$(OBJEXT) \
-+ m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-x86-darwin.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-amd64-darwin.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-xen.$(OBJEXT) \
-@@ -587,6 +597,7 @@ am__libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_SOURCES_DIST = \
- m_dispatch/dispatch-mips32-linux.S \
- m_dispatch/dispatch-mips64-linux.S \
- m_dispatch/dispatch-nanomips-linux.S \
-+ m_dispatch/dispatch-loongarch64-linux.S \
- m_dispatch/dispatch-x86-freebsd.S \
- m_dispatch/dispatch-amd64-freebsd.S \
- m_dispatch/dispatch-x86-darwin.S \
-@@ -605,7 +616,8 @@ am__libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_SOURCES_DIST = \
- m_gdbserver/valgrind-low-s390x.c \
- m_gdbserver/valgrind-low-mips32.c \
- m_gdbserver/valgrind-low-mips64.c \
-- m_gdbserver/valgrind-low-nanomips.c m_gdbserver/version.c \
-+ m_gdbserver/valgrind-low-nanomips.c \
-+ m_gdbserver/valgrind-low-loongarch64.c m_gdbserver/version.c \
- m_initimg/initimg-linux.c m_initimg/initimg-freebsd.c \
- m_initimg/initimg-darwin.c m_initimg/initimg-solaris.c \
- m_mach/mach_basics.c m_mach/mach_msg.c \
-@@ -626,6 +638,7 @@ am__libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_SOURCES_DIST = \
- m_sigframe/sigframe-mips32-linux.c \
- m_sigframe/sigframe-mips64-linux.c \
- m_sigframe/sigframe-nanomips-linux.c \
-+ m_sigframe/sigframe-loongarch64-linux.c \
- m_sigframe/sigframe-x86-darwin.c \
- m_sigframe/sigframe-amd64-darwin.c \
- m_sigframe/sigframe-solaris.c m_syswrap/syscall-x86-linux.S \
-@@ -638,6 +651,7 @@ am__libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_SOURCES_DIST = \
- m_syswrap/syscall-mips32-linux.S \
- m_syswrap/syscall-mips64-linux.S \
- m_syswrap/syscall-nanomips-linux.S \
-+ m_syswrap/syscall-loongarch64-linux.S \
- m_syswrap/syscall-x86-freebsd.S \
- m_syswrap/syscall-amd64-freebsd.S \
- m_syswrap/syscall-x86-darwin.S \
-@@ -657,6 +671,7 @@ am__libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_SOURCES_DIST = \
- m_syswrap/syswrap-mips32-linux.c \
- m_syswrap/syswrap-mips64-linux.c \
- m_syswrap/syswrap-nanomips-linux.c \
-+ m_syswrap/syswrap-loongarch64-linux.c \
- m_syswrap/syswrap-x86-darwin.c \
- m_syswrap/syswrap-amd64-darwin.c m_syswrap/syswrap-xen.c \
- m_syswrap/syswrap-x86-solaris.c \
-@@ -743,6 +758,7 @@ am__objects_7 = libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-m_addrinfo.$(OBJEXT
- m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-mips32-linux.$(OBJEXT) \
- m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-mips64-linux.$(OBJEXT) \
- m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-nanomips-linux.$(OBJEXT) \
-+ m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.$(OBJEXT) \
- m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-x86-freebsd.$(OBJEXT) \
- m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-amd64-freebsd.$(OBJEXT) \
- m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-x86-darwin.$(OBJEXT) \
-@@ -766,6 +782,7 @@ am__objects_7 = libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-m_addrinfo.$(OBJEXT
- m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-mips32.$(OBJEXT) \
- m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-mips64.$(OBJEXT) \
- m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-nanomips.$(OBJEXT) \
-+ m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.$(OBJEXT) \
- m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-version.$(OBJEXT) \
- m_initimg/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-initimg-linux.$(OBJEXT) \
- m_initimg/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-initimg-freebsd.$(OBJEXT) \
-@@ -793,6 +810,7 @@ am__objects_7 = libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-m_addrinfo.$(OBJEXT
- m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-mips32-linux.$(OBJEXT) \
- m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-mips64-linux.$(OBJEXT) \
- m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-nanomips-linux.$(OBJEXT) \
-+ m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.$(OBJEXT) \
- m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-x86-darwin.$(OBJEXT) \
- m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-amd64-darwin.$(OBJEXT) \
- m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-solaris.$(OBJEXT) \
-@@ -807,6 +825,7 @@ am__objects_7 = libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-m_addrinfo.$(OBJEXT
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-mips32-linux.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-mips64-linux.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-nanomips-linux.$(OBJEXT) \
-+ m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-x86-freebsd.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-amd64-freebsd.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-x86-darwin.$(OBJEXT) \
-@@ -832,6 +851,7 @@ am__objects_7 = libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-m_addrinfo.$(OBJEXT
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-mips32-linux.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-mips64-linux.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-nanomips-linux.$(OBJEXT) \
-+ m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-x86-darwin.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-amd64-darwin.$(OBJEXT) \
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-xen.$(OBJEXT) \
-@@ -1133,6 +1153,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m
- m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-amd64-solaris.Po \
- m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-arm-linux.Po \
- m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-arm64-linux.Po \
-+ m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Po \
- m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-mips32-linux.Po \
- m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-mips64-linux.Po \
- m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-nanomips-linux.Po \
-@@ -1150,6 +1171,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m
- m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-amd64-solaris.Po \
- m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-arm-linux.Po \
- m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-arm64-linux.Po \
-+ m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Po \
- m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-mips32-linux.Po \
- m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-mips64-linux.Po \
- m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-nanomips-linux.Po \
-@@ -1171,6 +1193,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m
- m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-amd64.Po \
- m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-arm.Po \
- m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-arm64.Po \
-+ m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.Po \
- m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-mips32.Po \
- m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-mips64.Po \
- m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-nanomips.Po \
-@@ -1189,6 +1212,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m
- m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-amd64.Po \
- m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-arm.Po \
- m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-arm64.Po \
-+ m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.Po \
- m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-mips32.Po \
- m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-mips64.Po \
- m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-nanomips.Po \
-@@ -1243,6 +1267,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m
- m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-arm-linux.Po \
- m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-arm64-linux.Po \
- m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-common.Po \
-+ m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Po \
- m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-mips32-linux.Po \
- m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-mips64-linux.Po \
- m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-nanomips-linux.Po \
-@@ -1259,6 +1284,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m
- m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-arm-linux.Po \
- m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-arm64-linux.Po \
- m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-common.Po \
-+ m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Po \
- m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-mips32-linux.Po \
- m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-mips64-linux.Po \
- m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-nanomips-linux.Po \
-@@ -1275,6 +1301,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-amd64-solaris.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-arm-linux.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-arm64-linux.Po \
-+ m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-mips32-linux.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-mips64-linux.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-nanomips-linux.Po \
-@@ -1297,6 +1324,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-generic.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-linux-variants.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-linux.Po \
-+ m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-main.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-mips32-linux.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-mips64-linux.Po \
-@@ -1316,6 +1344,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-amd64-solaris.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-arm-linux.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-arm64-linux.Po \
-+ m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-mips32-linux.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-mips64-linux.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-nanomips-linux.Po \
-@@ -1338,6 +1367,7 @@ am__depfiles_remade = ./$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-m
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-generic.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-linux-variants.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-linux.Po \
-+ m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-main.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-mips32-linux.Po \
- m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-mips64-linux.Po \
-@@ -1818,6 +1848,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++static void iselStmtCas ( ISelEnv* env, IRStmt* stmt )
++{
++ IRCAS* cas = stmt->Ist.CAS.details;
++ if (cas->oldHi == IRTemp_INVALID && cas->end == Iend_LE) {
++ /* "normal" singleton CAS */
++ HReg old = lookupIRTemp(env, cas->oldLo);
++ HReg addr = iselIntExpr_R(env, cas->addr);
++ HReg expd = iselIntExpr_R(env, cas->expdLo);
++ HReg data = iselIntExpr_R(env, cas->dataLo);
++ IRType ty = typeOfIRTemp(env->type_env, cas->oldLo);
++ Bool size64;
++ switch (ty) {
++ case Ity_I32:
++ size64 = False;
++ break;
++ case Ity_I64:
++ size64 = True;
++ break;
++ default:
++ vpanic("iselStmt(loongarch64): Ist_CAS");
++ break;
++ }
++ addInstr(env, LOONGARCH64Instr_Cas(old, addr, expd, data, size64));
++ } else {
++ vpanic("iselStmt(loongarch64): Ist_CAS");
++ }
++}
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -1865,6 +1901,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
-
-@@ -2144,6 +2181,7 @@ COREGRIND_SOURCES_COMMON = \
- m_dispatch/dispatch-mips32-linux.S \
- m_dispatch/dispatch-mips64-linux.S \
- m_dispatch/dispatch-nanomips-linux.S \
-+ m_dispatch/dispatch-loongarch64-linux.S \
- m_dispatch/dispatch-x86-freebsd.S \
- m_dispatch/dispatch-amd64-freebsd.S \
- m_dispatch/dispatch-x86-darwin.S \
-@@ -2167,6 +2205,7 @@ COREGRIND_SOURCES_COMMON = \
- m_gdbserver/valgrind-low-mips32.c \
- m_gdbserver/valgrind-low-mips64.c \
- m_gdbserver/valgrind-low-nanomips.c \
-+ m_gdbserver/valgrind-low-loongarch64.c \
- m_gdbserver/version.c \
- m_initimg/initimg-linux.c \
- m_initimg/initimg-freebsd.c \
-@@ -2194,6 +2233,7 @@ COREGRIND_SOURCES_COMMON = \
- m_sigframe/sigframe-mips32-linux.c \
- m_sigframe/sigframe-mips64-linux.c \
- m_sigframe/sigframe-nanomips-linux.c \
-+ m_sigframe/sigframe-loongarch64-linux.c \
- m_sigframe/sigframe-x86-darwin.c \
- m_sigframe/sigframe-amd64-darwin.c \
- m_sigframe/sigframe-solaris.c \
-@@ -2208,6 +2248,7 @@ COREGRIND_SOURCES_COMMON = \
- m_syswrap/syscall-mips32-linux.S \
- m_syswrap/syscall-mips64-linux.S \
- m_syswrap/syscall-nanomips-linux.S \
-+ m_syswrap/syscall-loongarch64-linux.S \
- m_syswrap/syscall-x86-freebsd.S \
- m_syswrap/syscall-amd64-freebsd.S \
- m_syswrap/syscall-x86-darwin.S \
-@@ -2233,6 +2274,7 @@ COREGRIND_SOURCES_COMMON = \
- m_syswrap/syswrap-mips32-linux.c \
- m_syswrap/syswrap-mips64-linux.c \
- m_syswrap/syswrap-nanomips-linux.c \
-+ m_syswrap/syswrap-loongarch64-linux.c \
- m_syswrap/syswrap-x86-darwin.c \
- m_syswrap/syswrap-amd64-darwin.c \
- m_syswrap/syswrap-xen.c \
-@@ -2487,7 +2529,15 @@ GDBSERVER_XML_FILES = \
- m_gdbserver/mips64-linux-valgrind.xml \
- m_gdbserver/mips64-fpu-valgrind-s1.xml \
- m_gdbserver/mips64-fpu-valgrind-s2.xml \
-- m_gdbserver/mips64-fpu.xml
-+ m_gdbserver/mips64-fpu.xml \
-+ m_gdbserver/loongarch-base64.xml \
-+ m_gdbserver/loongarch-fpu64.xml \
-+ m_gdbserver/loongarch64-linux.xml \
-+ m_gdbserver/loongarch-base64-valgrind-s1.xml \
-+ m_gdbserver/loongarch-base64-valgrind-s2.xml \
-+ m_gdbserver/loongarch-fpu64-valgrind-s1.xml \
-+ m_gdbserver/loongarch-fpu64-valgrind-s2.xml \
-+ m_gdbserver/loongarch64-linux-valgrind.xml
-
-
- # so as to make sure these get copied into the install tree
-@@ -2762,6 +2812,9 @@ m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-mips64-linux.$(
- m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-nanomips-linux.$(OBJEXT): \
- m_dispatch/$(am__dirstamp) \
- m_dispatch/$(DEPDIR)/$(am__dirstamp)
-+m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.$(OBJEXT): \
-+ m_dispatch/$(am__dirstamp) \
-+ m_dispatch/$(DEPDIR)/$(am__dirstamp)
- m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-x86-freebsd.$(OBJEXT): \
- m_dispatch/$(am__dirstamp) \
- m_dispatch/$(DEPDIR)/$(am__dirstamp)
-@@ -2837,6 +2890,9 @@ m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-mips64.$(O
- m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-nanomips.$(OBJEXT): \
- m_gdbserver/$(am__dirstamp) \
- m_gdbserver/$(DEPDIR)/$(am__dirstamp)
-+m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.$(OBJEXT): \
-+ m_gdbserver/$(am__dirstamp) \
-+ m_gdbserver/$(DEPDIR)/$(am__dirstamp)
- m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-version.$(OBJEXT): \
- m_gdbserver/$(am__dirstamp) \
- m_gdbserver/$(DEPDIR)/$(am__dirstamp)
-@@ -2940,6 +2996,9 @@ m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-mips64-linux.$(
- m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-nanomips-linux.$(OBJEXT): \
- m_sigframe/$(am__dirstamp) \
- m_sigframe/$(DEPDIR)/$(am__dirstamp)
-+m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.$(OBJEXT): \
-+ m_sigframe/$(am__dirstamp) \
-+ m_sigframe/$(DEPDIR)/$(am__dirstamp)
- m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-x86-darwin.$(OBJEXT): \
- m_sigframe/$(am__dirstamp) \
- m_sigframe/$(DEPDIR)/$(am__dirstamp)
-@@ -2977,6 +3036,8 @@ m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-mips64-linux.$(OB
- m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-nanomips-linux.$(OBJEXT): \
- m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
-+m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.$(OBJEXT): \
-+ m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-x86-freebsd.$(OBJEXT): \
- m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-amd64-freebsd.$(OBJEXT): \
-@@ -3027,6 +3088,8 @@ m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-mips64-linux.$(OB
- m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-nanomips-linux.$(OBJEXT): \
- m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
-+m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.$(OBJEXT): \
-+ m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-x86-darwin.$(OBJEXT): \
- m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-amd64-darwin.$(OBJEXT): \
-@@ -3181,6 +3244,9 @@ m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-mips64-linux.$(
- m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-nanomips-linux.$(OBJEXT): \
- m_dispatch/$(am__dirstamp) \
- m_dispatch/$(DEPDIR)/$(am__dirstamp)
-+m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.$(OBJEXT): \
-+ m_dispatch/$(am__dirstamp) \
-+ m_dispatch/$(DEPDIR)/$(am__dirstamp)
- m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-x86-freebsd.$(OBJEXT): \
- m_dispatch/$(am__dirstamp) \
- m_dispatch/$(DEPDIR)/$(am__dirstamp)
-@@ -3250,6 +3316,9 @@ m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-mips64.$(O
- m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-nanomips.$(OBJEXT): \
- m_gdbserver/$(am__dirstamp) \
- m_gdbserver/$(DEPDIR)/$(am__dirstamp)
-+m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.$(OBJEXT): \
-+ m_gdbserver/$(am__dirstamp) \
-+ m_gdbserver/$(DEPDIR)/$(am__dirstamp)
- m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-version.$(OBJEXT): \
- m_gdbserver/$(am__dirstamp) \
- m_gdbserver/$(DEPDIR)/$(am__dirstamp)
-@@ -3323,6 +3392,9 @@ m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-mips64-linux.$(
- m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-nanomips-linux.$(OBJEXT): \
- m_sigframe/$(am__dirstamp) \
- m_sigframe/$(DEPDIR)/$(am__dirstamp)
-+m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.$(OBJEXT): \
-+ m_sigframe/$(am__dirstamp) \
-+ m_sigframe/$(DEPDIR)/$(am__dirstamp)
- m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-x86-darwin.$(OBJEXT): \
- m_sigframe/$(am__dirstamp) \
- m_sigframe/$(DEPDIR)/$(am__dirstamp)
-@@ -3354,6 +3426,8 @@ m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-mips64-linux.$(OB
- m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-nanomips-linux.$(OBJEXT): \
- m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
-+m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.$(OBJEXT): \
-+ m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-x86-freebsd.$(OBJEXT): \
- m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-amd64-freebsd.$(OBJEXT): \
-@@ -3404,6 +3478,8 @@ m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-mips64-linux.$(OB
- m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-nanomips-linux.$(OBJEXT): \
- m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
-+m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.$(OBJEXT): \
-+ m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-x86-darwin.$(OBJEXT): \
- m_syswrap/$(am__dirstamp) m_syswrap/$(DEPDIR)/$(am__dirstamp)
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-amd64-darwin.$(OBJEXT): \
-@@ -3681,6 +3757,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-amd64-solaris.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-arm-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-arm64-linux.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-mips32-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-mips64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-nanomips-linux.Po@am__quote@ # am--include-marker
-@@ -3698,6 +3775,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-amd64-solaris.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-arm-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-arm64-linux.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-mips32-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-mips64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-nanomips-linux.Po@am__quote@ # am--include-marker
-@@ -3719,6 +3797,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-amd64.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-arm.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-arm64.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-mips32.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-mips64.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-nanomips.Po@am__quote@ # am--include-marker
-@@ -3737,6 +3816,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-amd64.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-arm.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-arm64.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-mips32.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-mips64.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-nanomips.Po@am__quote@ # am--include-marker
-@@ -3791,6 +3871,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-arm-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-arm64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-common.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-mips32-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-mips64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-nanomips-linux.Po@am__quote@ # am--include-marker
-@@ -3807,6 +3888,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-arm-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-arm64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-common.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-mips32-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-mips64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-nanomips-linux.Po@am__quote@ # am--include-marker
-@@ -3823,6 +3905,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-amd64-solaris.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-arm-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-arm64-linux.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-mips32-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-mips64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-nanomips-linux.Po@am__quote@ # am--include-marker
-@@ -3845,6 +3928,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-generic.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-linux-variants.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-linux.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-main.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-mips32-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-mips64-linux.Po@am__quote@ # am--include-marker
-@@ -3864,6 +3948,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-amd64-solaris.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-arm-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-arm64-linux.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-mips32-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-mips64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-nanomips-linux.Po@am__quote@ # am--include-marker
-@@ -3886,6 +3971,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-generic.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-linux-variants.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-linux.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-main.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-mips32-linux.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-mips64-linux.Po@am__quote@ # am--include-marker
-@@ -4112,6 +4198,20 @@ m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-nanomips-linux.
- @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -c -o m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-nanomips-linux.obj `if test -f 'm_dispatch/dispatch-nanomips-linux.S'; then $(CYGPATH_W) 'm_dispatch/dispatch-nanomips-linux.S'; else $(CYGPATH_W) '$(srcdir)/m_dispatch/dispatch-nanomips-linux.S'; fi`
-
-+m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.o: m_dispatch/dispatch-loongarch64-linux.S
-+@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -MT m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.o -MD -MP -MF m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Tpo -c -o m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.o `test -f 'm_dispatch/dispatch-loongarch64-linux.S' || echo '$(srcdir)/'`m_dispatch/dispatch-loongarch64-linux.S
-+@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Tpo m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='m_dispatch/dispatch-loongarch64-linux.S' object='m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -c -o m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.o `test -f 'm_dispatch/dispatch-loongarch64-linux.S' || echo '$(srcdir)/'`m_dispatch/dispatch-loongarch64-linux.S
-+
-+m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.obj: m_dispatch/dispatch-loongarch64-linux.S
-+@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -MT m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.obj -MD -MP -MF m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Tpo -c -o m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.obj `if test -f 'm_dispatch/dispatch-loongarch64-linux.S'; then $(CYGPATH_W) 'm_dispatch/dispatch-loongarch64-linux.S'; else $(CYGPATH_W) '$(srcdir)/m_dispatch/dispatch-loongarch64-linux.S'; fi`
-+@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Tpo m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='m_dispatch/dispatch-loongarch64-linux.S' object='m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -c -o m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.obj `if test -f 'm_dispatch/dispatch-loongarch64-linux.S'; then $(CYGPATH_W) 'm_dispatch/dispatch-loongarch64-linux.S'; else $(CYGPATH_W) '$(srcdir)/m_dispatch/dispatch-loongarch64-linux.S'; fi`
-+
- m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-x86-freebsd.o: m_dispatch/dispatch-x86-freebsd.S
- @am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -MT m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-x86-freebsd.o -MD -MP -MF m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-x86-freebsd.Tpo -c -o m_dispatch/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-x86-freebsd.o `test -f 'm_dispatch/dispatch-x86-freebsd.S' || echo '$(srcdir)/'`m_dispatch/dispatch-x86-freebsd.S
- @am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-x86-freebsd.Tpo m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-x86-freebsd.Po
-@@ -4378,6 +4478,20 @@ m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-nanomips-linux.ob
- @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-nanomips-linux.obj `if test -f 'm_syswrap/syscall-nanomips-linux.S'; then $(CYGPATH_W) 'm_syswrap/syscall-nanomips-linux.S'; else $(CYGPATH_W) '$(srcdir)/m_syswrap/syscall-nanomips-linux.S'; fi`
-
-+m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.o: m_syswrap/syscall-loongarch64-linux.S
-+@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -MT m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.o -MD -MP -MF m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.Tpo -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.o `test -f 'm_syswrap/syscall-loongarch64-linux.S' || echo '$(srcdir)/'`m_syswrap/syscall-loongarch64-linux.S
-+@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.Tpo m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='m_syswrap/syscall-loongarch64-linux.S' object='m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.o `test -f 'm_syswrap/syscall-loongarch64-linux.S' || echo '$(srcdir)/'`m_syswrap/syscall-loongarch64-linux.S
-+
-+m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.obj: m_syswrap/syscall-loongarch64-linux.S
-+@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -MT m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.obj -MD -MP -MF m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.Tpo -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.obj `if test -f 'm_syswrap/syscall-loongarch64-linux.S'; then $(CYGPATH_W) 'm_syswrap/syscall-loongarch64-linux.S'; else $(CYGPATH_W) '$(srcdir)/m_syswrap/syscall-loongarch64-linux.S'; fi`
-+@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.Tpo m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='m_syswrap/syscall-loongarch64-linux.S' object='m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.obj `if test -f 'm_syswrap/syscall-loongarch64-linux.S'; then $(CYGPATH_W) 'm_syswrap/syscall-loongarch64-linux.S'; else $(CYGPATH_W) '$(srcdir)/m_syswrap/syscall-loongarch64-linux.S'; fi`
-+
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-x86-freebsd.o: m_syswrap/syscall-x86-freebsd.S
- @am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -MT m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-x86-freebsd.o -MD -MP -MF m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-x86-freebsd.Tpo -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-x86-freebsd.o `test -f 'm_syswrap/syscall-x86-freebsd.S' || echo '$(srcdir)/'`m_syswrap/syscall-x86-freebsd.S
- @am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-x86-freebsd.Tpo m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-x86-freebsd.Po
-@@ -4644,6 +4758,20 @@ m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-nanomips-linux.
- @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -c -o m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-nanomips-linux.obj `if test -f 'm_dispatch/dispatch-nanomips-linux.S'; then $(CYGPATH_W) 'm_dispatch/dispatch-nanomips-linux.S'; else $(CYGPATH_W) '$(srcdir)/m_dispatch/dispatch-nanomips-linux.S'; fi`
-
-+m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.o: m_dispatch/dispatch-loongarch64-linux.S
-+@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -MT m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.o -MD -MP -MF m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Tpo -c -o m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.o `test -f 'm_dispatch/dispatch-loongarch64-linux.S' || echo '$(srcdir)/'`m_dispatch/dispatch-loongarch64-linux.S
-+@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Tpo m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='m_dispatch/dispatch-loongarch64-linux.S' object='m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -c -o m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.o `test -f 'm_dispatch/dispatch-loongarch64-linux.S' || echo '$(srcdir)/'`m_dispatch/dispatch-loongarch64-linux.S
-+
-+m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.obj: m_dispatch/dispatch-loongarch64-linux.S
-+@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -MT m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.obj -MD -MP -MF m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Tpo -c -o m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.obj `if test -f 'm_dispatch/dispatch-loongarch64-linux.S'; then $(CYGPATH_W) 'm_dispatch/dispatch-loongarch64-linux.S'; else $(CYGPATH_W) '$(srcdir)/m_dispatch/dispatch-loongarch64-linux.S'; fi`
-+@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Tpo m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='m_dispatch/dispatch-loongarch64-linux.S' object='m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -c -o m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.obj `if test -f 'm_dispatch/dispatch-loongarch64-linux.S'; then $(CYGPATH_W) 'm_dispatch/dispatch-loongarch64-linux.S'; else $(CYGPATH_W) '$(srcdir)/m_dispatch/dispatch-loongarch64-linux.S'; fi`
-+
- m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-x86-freebsd.o: m_dispatch/dispatch-x86-freebsd.S
- @am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -MT m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-x86-freebsd.o -MD -MP -MF m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-x86-freebsd.Tpo -c -o m_dispatch/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-x86-freebsd.o `test -f 'm_dispatch/dispatch-x86-freebsd.S' || echo '$(srcdir)/'`m_dispatch/dispatch-x86-freebsd.S
- @am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-x86-freebsd.Tpo m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-x86-freebsd.Po
-@@ -4910,6 +5038,20 @@ m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-nanomips-linux.ob
- @AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-nanomips-linux.obj `if test -f 'm_syswrap/syscall-nanomips-linux.S'; then $(CYGPATH_W) 'm_syswrap/syscall-nanomips-linux.S'; else $(CYGPATH_W) '$(srcdir)/m_syswrap/syscall-nanomips-linux.S'; fi`
-
-+m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.o: m_syswrap/syscall-loongarch64-linux.S
-+@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -MT m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.o -MD -MP -MF m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.Tpo -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.o `test -f 'm_syswrap/syscall-loongarch64-linux.S' || echo '$(srcdir)/'`m_syswrap/syscall-loongarch64-linux.S
-+@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.Tpo m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='m_syswrap/syscall-loongarch64-linux.S' object='m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.o `test -f 'm_syswrap/syscall-loongarch64-linux.S' || echo '$(srcdir)/'`m_syswrap/syscall-loongarch64-linux.S
-+
-+m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.obj: m_syswrap/syscall-loongarch64-linux.S
-+@am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -MT m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.obj -MD -MP -MF m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.Tpo -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.obj `if test -f 'm_syswrap/syscall-loongarch64-linux.S'; then $(CYGPATH_W) 'm_syswrap/syscall-loongarch64-linux.S'; else $(CYGPATH_W) '$(srcdir)/m_syswrap/syscall-loongarch64-linux.S'; fi`
-+@am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.Tpo m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS)source='m_syswrap/syscall-loongarch64-linux.S' object='m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCCAS_FALSE@ DEPDIR=$(DEPDIR) $(CCASDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCCAS_FALSE@ $(AM_V_CPPAS@am__nodep@)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.obj `if test -f 'm_syswrap/syscall-loongarch64-linux.S'; then $(CYGPATH_W) 'm_syswrap/syscall-loongarch64-linux.S'; else $(CYGPATH_W) '$(srcdir)/m_syswrap/syscall-loongarch64-linux.S'; fi`
-+
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-x86-freebsd.o: m_syswrap/syscall-x86-freebsd.S
- @am__fastdepCCAS_TRUE@ $(AM_V_CPPAS)$(CCAS) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CCASFLAGS) $(CCASFLAGS) -MT m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-x86-freebsd.o -MD -MP -MF m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-x86-freebsd.Tpo -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-x86-freebsd.o `test -f 'm_syswrap/syscall-x86-freebsd.S' || echo '$(srcdir)/'`m_syswrap/syscall-x86-freebsd.S
- @am__fastdepCCAS_TRUE@ $(AM_V_at)$(am__mv) m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-x86-freebsd.Tpo m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-x86-freebsd.Po
-@@ -6200,6 +6342,20 @@ m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-nanomips.o
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-nanomips.obj `if test -f 'm_gdbserver/valgrind-low-nanomips.c'; then $(CYGPATH_W) 'm_gdbserver/valgrind-low-nanomips.c'; else $(CYGPATH_W) '$(srcdir)/m_gdbserver/valgrind-low-nanomips.c'; fi`
-
-+m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.o: m_gdbserver/valgrind-low-loongarch64.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.o -MD -MP -MF m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.Tpo -c -o m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.o `test -f 'm_gdbserver/valgrind-low-loongarch64.c' || echo '$(srcdir)/'`m_gdbserver/valgrind-low-loongarch64.c
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.Tpo m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='m_gdbserver/valgrind-low-loongarch64.c' object='m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.o `test -f 'm_gdbserver/valgrind-low-loongarch64.c' || echo '$(srcdir)/'`m_gdbserver/valgrind-low-loongarch64.c
-+
-+m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.obj: m_gdbserver/valgrind-low-loongarch64.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.obj -MD -MP -MF m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.Tpo -c -o m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.obj `if test -f 'm_gdbserver/valgrind-low-loongarch64.c'; then $(CYGPATH_W) 'm_gdbserver/valgrind-low-loongarch64.c'; else $(CYGPATH_W) '$(srcdir)/m_gdbserver/valgrind-low-loongarch64.c'; fi`
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.Tpo m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='m_gdbserver/valgrind-low-loongarch64.c' object='m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.obj `if test -f 'm_gdbserver/valgrind-low-loongarch64.c'; then $(CYGPATH_W) 'm_gdbserver/valgrind-low-loongarch64.c'; else $(CYGPATH_W) '$(srcdir)/m_gdbserver/valgrind-low-loongarch64.c'; fi`
-+
- m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-version.o: m_gdbserver/version.c
- @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-version.o -MD -MP -MF m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-version.Tpo -c -o m_gdbserver/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-version.o `test -f 'm_gdbserver/version.c' || echo '$(srcdir)/'`m_gdbserver/version.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-version.Tpo m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-version.Po
-@@ -6550,6 +6706,20 @@ m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-nanomips-linux.
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-nanomips-linux.obj `if test -f 'm_sigframe/sigframe-nanomips-linux.c'; then $(CYGPATH_W) 'm_sigframe/sigframe-nanomips-linux.c'; else $(CYGPATH_W) '$(srcdir)/m_sigframe/sigframe-nanomips-linux.c'; fi`
-
-+m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.o: m_sigframe/sigframe-loongarch64-linux.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.o -MD -MP -MF m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Tpo -c -o m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.o `test -f 'm_sigframe/sigframe-loongarch64-linux.c' || echo '$(srcdir)/'`m_sigframe/sigframe-loongarch64-linux.c
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Tpo m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='m_sigframe/sigframe-loongarch64-linux.c' object='m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.o `test -f 'm_sigframe/sigframe-loongarch64-linux.c' || echo '$(srcdir)/'`m_sigframe/sigframe-loongarch64-linux.c
-+
-+m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.obj: m_sigframe/sigframe-loongarch64-linux.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.obj -MD -MP -MF m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Tpo -c -o m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.obj `if test -f 'm_sigframe/sigframe-loongarch64-linux.c'; then $(CYGPATH_W) 'm_sigframe/sigframe-loongarch64-linux.c'; else $(CYGPATH_W) '$(srcdir)/m_sigframe/sigframe-loongarch64-linux.c'; fi`
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Tpo m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='m_sigframe/sigframe-loongarch64-linux.c' object='m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.obj `if test -f 'm_sigframe/sigframe-loongarch64-linux.c'; then $(CYGPATH_W) 'm_sigframe/sigframe-loongarch64-linux.c'; else $(CYGPATH_W) '$(srcdir)/m_sigframe/sigframe-loongarch64-linux.c'; fi`
-+
- m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-x86-darwin.o: m_sigframe/sigframe-x86-darwin.c
- @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-x86-darwin.o -MD -MP -MF m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-x86-darwin.Tpo -c -o m_sigframe/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-x86-darwin.o `test -f 'm_sigframe/sigframe-x86-darwin.c' || echo '$(srcdir)/'`m_sigframe/sigframe-x86-darwin.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-x86-darwin.Tpo m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-x86-darwin.Po
-@@ -6858,6 +7028,20 @@ m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-nanomips-linux.ob
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-nanomips-linux.obj `if test -f 'm_syswrap/syswrap-nanomips-linux.c'; then $(CYGPATH_W) 'm_syswrap/syswrap-nanomips-linux.c'; else $(CYGPATH_W) '$(srcdir)/m_syswrap/syswrap-nanomips-linux.c'; fi`
-
-+m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.o: m_syswrap/syswrap-loongarch64-linux.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.o -MD -MP -MF m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Tpo -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.o `test -f 'm_syswrap/syswrap-loongarch64-linux.c' || echo '$(srcdir)/'`m_syswrap/syswrap-loongarch64-linux.c
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Tpo m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='m_syswrap/syswrap-loongarch64-linux.c' object='m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.o `test -f 'm_syswrap/syswrap-loongarch64-linux.c' || echo '$(srcdir)/'`m_syswrap/syswrap-loongarch64-linux.c
-+
-+m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.obj: m_syswrap/syswrap-loongarch64-linux.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.obj -MD -MP -MF m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Tpo -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.obj `if test -f 'm_syswrap/syswrap-loongarch64-linux.c'; then $(CYGPATH_W) 'm_syswrap/syswrap-loongarch64-linux.c'; else $(CYGPATH_W) '$(srcdir)/m_syswrap/syswrap-loongarch64-linux.c'; fi`
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Tpo m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='m_syswrap/syswrap-loongarch64-linux.c' object='m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.obj `if test -f 'm_syswrap/syswrap-loongarch64-linux.c'; then $(CYGPATH_W) 'm_syswrap/syswrap-loongarch64-linux.c'; else $(CYGPATH_W) '$(srcdir)/m_syswrap/syswrap-loongarch64-linux.c'; fi`
-+
- m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-x86-darwin.o: m_syswrap/syswrap-x86-darwin.c
- @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-x86-darwin.o -MD -MP -MF m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-x86-darwin.Tpo -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-x86-darwin.o `test -f 'm_syswrap/syswrap-x86-darwin.c' || echo '$(srcdir)/'`m_syswrap/syswrap-x86-darwin.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-x86-darwin.Tpo m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-x86-darwin.Po
-@@ -8244,6 +8428,20 @@ m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-nanomips.o
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-nanomips.obj `if test -f 'm_gdbserver/valgrind-low-nanomips.c'; then $(CYGPATH_W) 'm_gdbserver/valgrind-low-nanomips.c'; else $(CYGPATH_W) '$(srcdir)/m_gdbserver/valgrind-low-nanomips.c'; fi`
-
-+m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.o: m_gdbserver/valgrind-low-loongarch64.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.o -MD -MP -MF m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.Tpo -c -o m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.o `test -f 'm_gdbserver/valgrind-low-loongarch64.c' || echo '$(srcdir)/'`m_gdbserver/valgrind-low-loongarch64.c
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.Tpo m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='m_gdbserver/valgrind-low-loongarch64.c' object='m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.o `test -f 'm_gdbserver/valgrind-low-loongarch64.c' || echo '$(srcdir)/'`m_gdbserver/valgrind-low-loongarch64.c
-+
-+m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.obj: m_gdbserver/valgrind-low-loongarch64.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.obj -MD -MP -MF m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.Tpo -c -o m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.obj `if test -f 'm_gdbserver/valgrind-low-loongarch64.c'; then $(CYGPATH_W) 'm_gdbserver/valgrind-low-loongarch64.c'; else $(CYGPATH_W) '$(srcdir)/m_gdbserver/valgrind-low-loongarch64.c'; fi`
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.Tpo m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='m_gdbserver/valgrind-low-loongarch64.c' object='m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.obj `if test -f 'm_gdbserver/valgrind-low-loongarch64.c'; then $(CYGPATH_W) 'm_gdbserver/valgrind-low-loongarch64.c'; else $(CYGPATH_W) '$(srcdir)/m_gdbserver/valgrind-low-loongarch64.c'; fi`
-+
- m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-version.o: m_gdbserver/version.c
- @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-version.o -MD -MP -MF m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-version.Tpo -c -o m_gdbserver/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-version.o `test -f 'm_gdbserver/version.c' || echo '$(srcdir)/'`m_gdbserver/version.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-version.Tpo m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-version.Po
-@@ -8594,6 +8792,20 @@ m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-nanomips-linux.
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-nanomips-linux.obj `if test -f 'm_sigframe/sigframe-nanomips-linux.c'; then $(CYGPATH_W) 'm_sigframe/sigframe-nanomips-linux.c'; else $(CYGPATH_W) '$(srcdir)/m_sigframe/sigframe-nanomips-linux.c'; fi`
-
-+m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.o: m_sigframe/sigframe-loongarch64-linux.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.o -MD -MP -MF m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Tpo -c -o m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.o `test -f 'm_sigframe/sigframe-loongarch64-linux.c' || echo '$(srcdir)/'`m_sigframe/sigframe-loongarch64-linux.c
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Tpo m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='m_sigframe/sigframe-loongarch64-linux.c' object='m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.o `test -f 'm_sigframe/sigframe-loongarch64-linux.c' || echo '$(srcdir)/'`m_sigframe/sigframe-loongarch64-linux.c
-+
-+m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.obj: m_sigframe/sigframe-loongarch64-linux.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.obj -MD -MP -MF m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Tpo -c -o m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.obj `if test -f 'm_sigframe/sigframe-loongarch64-linux.c'; then $(CYGPATH_W) 'm_sigframe/sigframe-loongarch64-linux.c'; else $(CYGPATH_W) '$(srcdir)/m_sigframe/sigframe-loongarch64-linux.c'; fi`
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Tpo m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='m_sigframe/sigframe-loongarch64-linux.c' object='m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.obj `if test -f 'm_sigframe/sigframe-loongarch64-linux.c'; then $(CYGPATH_W) 'm_sigframe/sigframe-loongarch64-linux.c'; else $(CYGPATH_W) '$(srcdir)/m_sigframe/sigframe-loongarch64-linux.c'; fi`
-+
- m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-x86-darwin.o: m_sigframe/sigframe-x86-darwin.c
- @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-x86-darwin.o -MD -MP -MF m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-x86-darwin.Tpo -c -o m_sigframe/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-x86-darwin.o `test -f 'm_sigframe/sigframe-x86-darwin.c' || echo '$(srcdir)/'`m_sigframe/sigframe-x86-darwin.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-x86-darwin.Tpo m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-x86-darwin.Po
-@@ -8902,6 +9114,20 @@ m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-nanomips-linux.ob
- @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
- @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-nanomips-linux.obj `if test -f 'm_syswrap/syswrap-nanomips-linux.c'; then $(CYGPATH_W) 'm_syswrap/syswrap-nanomips-linux.c'; else $(CYGPATH_W) '$(srcdir)/m_syswrap/syswrap-nanomips-linux.c'; fi`
-
-+m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.o: m_syswrap/syswrap-loongarch64-linux.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.o -MD -MP -MF m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Tpo -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.o `test -f 'm_syswrap/syswrap-loongarch64-linux.c' || echo '$(srcdir)/'`m_syswrap/syswrap-loongarch64-linux.c
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Tpo m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='m_syswrap/syswrap-loongarch64-linux.c' object='m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.o' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.o `test -f 'm_syswrap/syswrap-loongarch64-linux.c' || echo '$(srcdir)/'`m_syswrap/syswrap-loongarch64-linux.c
-+
-+m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.obj: m_syswrap/syswrap-loongarch64-linux.c
-+@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.obj -MD -MP -MF m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Tpo -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.obj `if test -f 'm_syswrap/syswrap-loongarch64-linux.c'; then $(CYGPATH_W) 'm_syswrap/syswrap-loongarch64-linux.c'; else $(CYGPATH_W) '$(srcdir)/m_syswrap/syswrap-loongarch64-linux.c'; fi`
-+@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Tpo m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Po
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='m_syswrap/syswrap-loongarch64-linux.c' object='m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.obj' libtool=no @AMDEPBACKSLASH@
-+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
-+@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.obj `if test -f 'm_syswrap/syswrap-loongarch64-linux.c'; then $(CYGPATH_W) 'm_syswrap/syswrap-loongarch64-linux.c'; else $(CYGPATH_W) '$(srcdir)/m_syswrap/syswrap-loongarch64-linux.c'; fi`
-+
- m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-x86-darwin.o: m_syswrap/syswrap-x86-darwin.c
- @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CPPFLAGS) $(CPPFLAGS) $(libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a_CFLAGS) $(CFLAGS) -MT m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-x86-darwin.o -MD -MP -MF m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-x86-darwin.Tpo -c -o m_syswrap/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-x86-darwin.o `test -f 'm_syswrap/syswrap-x86-darwin.c' || echo '$(srcdir)/'`m_syswrap/syswrap-x86-darwin.c
- @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-x86-darwin.Tpo m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-x86-darwin.Po
-@@ -9786,6 +10012,7 @@ distclean: distclean-am
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-amd64-solaris.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-arm-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-arm64-linux.Po
-+ -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-mips32-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-mips64-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-nanomips-linux.Po
-@@ -9803,6 +10030,7 @@ distclean: distclean-am
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-amd64-solaris.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-arm-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-arm64-linux.Po
-+ -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-mips32-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-mips64-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-nanomips-linux.Po
-@@ -9824,6 +10052,7 @@ distclean: distclean-am
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-amd64.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-arm.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-arm64.Po
-+ -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-mips32.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-mips64.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-nanomips.Po
-@@ -9842,6 +10071,7 @@ distclean: distclean-am
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-amd64.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-arm.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-arm64.Po
-+ -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-mips32.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-mips64.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-nanomips.Po
-@@ -9896,6 +10126,7 @@ distclean: distclean-am
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-arm-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-arm64-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-common.Po
-+ -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-mips32-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-mips64-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-nanomips-linux.Po
-@@ -9912,6 +10143,7 @@ distclean: distclean-am
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-arm-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-arm64-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-common.Po
-+ -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-mips32-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-mips64-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-nanomips-linux.Po
-@@ -9928,6 +10160,7 @@ distclean: distclean-am
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-amd64-solaris.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-arm-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-arm64-linux.Po
-+ -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-mips32-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-mips64-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-nanomips-linux.Po
-@@ -9950,6 +10183,7 @@ distclean: distclean-am
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-generic.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-linux-variants.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-linux.Po
-+ -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-main.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-mips32-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-mips64-linux.Po
-@@ -9969,6 +10203,7 @@ distclean: distclean-am
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-amd64-solaris.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-arm-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-arm64-linux.Po
-+ -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-mips32-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-mips64-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-nanomips-linux.Po
-@@ -9991,6 +10226,7 @@ distclean: distclean-am
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-generic.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-linux-variants.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-linux.Po
-+ -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-main.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-mips32-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-mips64-linux.Po
-@@ -10223,6 +10459,7 @@ maintainer-clean: maintainer-clean-am
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-amd64-solaris.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-arm-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-arm64-linux.Po
-+ -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-mips32-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-mips64-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-dispatch-nanomips-linux.Po
-@@ -10240,6 +10477,7 @@ maintainer-clean: maintainer-clean-am
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-amd64-solaris.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-arm-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-arm64-linux.Po
-+ -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-loongarch64-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-mips32-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-mips64-linux.Po
- -rm -f m_dispatch/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-dispatch-nanomips-linux.Po
-@@ -10261,6 +10499,7 @@ maintainer-clean: maintainer-clean-am
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-amd64.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-arm.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-arm64.Po
-+ -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-loongarch64.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-mips32.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-mips64.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-valgrind-low-nanomips.Po
-@@ -10279,6 +10518,7 @@ maintainer-clean: maintainer-clean-am
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-amd64.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-arm.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-arm64.Po
-+ -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-loongarch64.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-mips32.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-mips64.Po
- -rm -f m_gdbserver/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-valgrind-low-nanomips.Po
-@@ -10333,6 +10573,7 @@ maintainer-clean: maintainer-clean-am
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-arm-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-arm64-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-common.Po
-+ -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-mips32-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-mips64-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-sigframe-nanomips-linux.Po
-@@ -10349,6 +10590,7 @@ maintainer-clean: maintainer-clean-am
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-arm-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-arm64-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-common.Po
-+ -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-loongarch64-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-mips32-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-mips64-linux.Po
- -rm -f m_sigframe/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-sigframe-nanomips-linux.Po
-@@ -10365,6 +10607,7 @@ maintainer-clean: maintainer-clean-am
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-amd64-solaris.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-arm-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-arm64-linux.Po
-+ -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-loongarch64-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-mips32-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-mips64-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syscall-nanomips-linux.Po
-@@ -10387,6 +10630,7 @@ maintainer-clean: maintainer-clean-am
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-generic.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-linux-variants.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-linux.Po
-+ -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-main.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-mips32-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_PRI@_@VGCONF_OS@_a-syswrap-mips64-linux.Po
-@@ -10406,6 +10650,7 @@ maintainer-clean: maintainer-clean-am
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-amd64-solaris.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-arm-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-arm64-linux.Po
-+ -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-loongarch64-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-mips32-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-mips64-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syscall-nanomips-linux.Po
-@@ -10428,6 +10673,7 @@ maintainer-clean: maintainer-clean-am
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-generic.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-linux-variants.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-linux.Po
-+ -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-loongarch64-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-main.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-mips32-linux.Po
- -rm -f m_syswrap/$(DEPDIR)/libcoregrind_@VGCONF_ARCH_SEC@_@VGCONF_OS@_a-syswrap-mips64-linux.Po
-diff --git a/coregrind/launcher-linux.c b/coregrind/launcher-linux.c
-index bc95e3c..5307fd1 100644
---- a/coregrind/launcher-linux.c
-+++ b/coregrind/launcher-linux.c
-@@ -67,6 +67,10 @@
- #define EM_NANOMIPS 249
- #endif
-
-+#ifndef EM_LOONGARCH
-+#define EM_LOONGARCH 258
-+#endif
++static void iselStmtMBE ( ISelEnv* env, IRStmt* stmt )
++{
++ switch (stmt->Ist.MBE.event) {
++ case Imbe_Fence:
++ case Imbe_CancelReservation:
++ addInstr(env, LOONGARCH64Instr_Bar(LAbar_DBAR, 0));
++ break;
++ case Imbe_InsnFence:
++ addInstr(env, LOONGARCH64Instr_Bar(LAbar_IBAR, 0));
++ break;
++ default:
++ vpanic("iselStmt(loongarch64): Ist_MBE");
++ break;
++ }
++}
+
- #ifndef E_MIPS_ABI_O32
- #define E_MIPS_ABI_O32 0x00001000
- #endif
-@@ -314,6 +318,10 @@ static const char *select_platform(const char *clientname)
- (header.ehdr64.e_ident[EI_OSABI] == ELFOSABI_SYSV ||
- header.ehdr64.e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
- platform = "ppc64le-linux";
-+ } else if (header.ehdr64.e_machine == EM_LOONGARCH &&
-+ (header.ehdr64.e_ident[EI_OSABI] == ELFOSABI_SYSV ||
-+ header.ehdr64.e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
-+ platform = "loongarch64-linux";
- }
- } else if (header.c[EI_DATA] == ELFDATA2MSB) {
- # if !defined(VGPV_arm_linux_android) \
-@@ -415,7 +423,8 @@ int main(int argc, char** argv, char** envp)
- (0==strcmp(VG_PLATFORM,"s390x-linux")) ||
- (0==strcmp(VG_PLATFORM,"mips32-linux")) ||
- (0==strcmp(VG_PLATFORM,"mips64-linux")) ||
-- (0==strcmp(VG_PLATFORM,"nanomips-linux")))
-+ (0==strcmp(VG_PLATFORM,"nanomips-linux")) ||
-+ (0==strcmp(VG_PLATFORM,"loongarch64-linux")))
- default_platform = VG_PLATFORM;
- # elif defined(VGO_solaris)
- if ((0==strcmp(VG_PLATFORM,"x86-solaris")) ||
-diff --git a/coregrind/m_aspacemgr/aspacemgr-common.c b/coregrind/m_aspacemgr/aspacemgr-common.c
-index 816d227..0e79d3f 100644
---- a/coregrind/m_aspacemgr/aspacemgr-common.c
-+++ b/coregrind/m_aspacemgr/aspacemgr-common.c
-@@ -157,7 +157,8 @@ SysRes VG_(am_do_mmap_NO_NOTIFY)( Addr start, SizeT length, UInt prot,
- # elif defined(VGP_amd64_linux) \
- || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
- || defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \
-- || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
-+ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
-+ || defined(VGP_loongarch64_linux)
- res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length,
- prot, flags, fd, offset);
- # elif defined(VGP_x86_darwin)
-@@ -262,7 +263,8 @@ SysRes ML_(am_do_relocate_nooverlap_mapping_NO_NOTIFY)(
-
- SysRes ML_(am_open) ( const HChar* pathname, Int flags, Int mode )
- {
--# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- /* ARM64 wants to use __NR_openat rather than __NR_open. */
- SysRes res = VG_(do_syscall4)(__NR_openat,
- VKI_AT_FDCWD, (UWord)pathname, flags, mode);
-@@ -291,7 +293,8 @@ void ML_(am_close) ( Int fd )
- Int ML_(am_readlink)(const HChar* path, HChar* buf, UInt bufsiz)
- {
- SysRes res;
--# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
- (UWord)path, (UWord)buf, bufsiz);
- # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
-diff --git a/coregrind/m_aspacemgr/aspacemgr-linux.c b/coregrind/m_aspacemgr/aspacemgr-linux.c
-index 232401e..a88412d 100644
---- a/coregrind/m_aspacemgr/aspacemgr-linux.c
-+++ b/coregrind/m_aspacemgr/aspacemgr-linux.c
-@@ -2777,7 +2777,8 @@ static SysRes VG_(am_mmap_file_float_valgrind_flags) ( SizeT length, UInt prot,
- req.rkind = MAny;
- req.start = 0;
- #if defined(VGA_arm) || defined(VGA_arm64) \
-- || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips)
-+ || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips) \
-+ || defined(VGA_loongarch64)
- aspacem_assert(VKI_SHMLBA >= VKI_PAGE_SIZE);
- #else
- aspacem_assert(VKI_SHMLBA == VKI_PAGE_SIZE);
-diff --git a/coregrind/m_cache.c b/coregrind/m_cache.c
-index 428a4df..38fa44e 100644
---- a/coregrind/m_cache.c
-+++ b/coregrind/m_cache.c
-@@ -660,6 +660,239 @@ get_cache_info(VexArchInfo *vai)
- return True;
- }
-
-+#elif defined(VGA_loongarch64)
++static void iselStmtExit ( ISelEnv* env, IRStmt* stmt )
++{
++ if (stmt->Ist.Exit.dst->tag != Ico_U64)
++ vpanic("iselStmt(loongarch64): Ist_Exit: dst is not a 64-bit value");
+
-+/*
-+ * LoongArch method is straightforward, just extract appropriate bits via
-+ * cpucfg instruction (__builtin_loongarch_cpucfg).
-+ *
-+ * 1. Get the properties of the cache from cpucfg16.
-+ * 2. For each level of cache, get the properties from cpucfg17/18/19/20.
-+ *
-+ * It's a bit nasty since we have to get the total number of caches first.
-+ * To avoid duplicating reads, I use "struct cache_status" to store some
-+ * necessary information.
-+ */
++ HReg cond = iselCondCode_R(env, stmt->Ist.Exit.guard);
++ LOONGARCH64AMode* am = mkLOONGARCH64AMode_RI(hregGSP(), stmt->Ist.Exit.offsIP);
+
-+#define BIT(x) (1UL << (x))
-+#define GENMASK(h, l) (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (64 - 1 - (h))))
++ /* Case: boring transfer to known address */
++ if (stmt->Ist.Exit.jk == Ijk_Boring || stmt->Ist.Exit.jk == Ijk_Call) {
++ if (env->chainingAllowed) {
++ /* .. almost always true .. */
++ /* Skip the event check at the dst if this is a forwards edge. */
++ Bool toFastEP = ((Addr64)stmt->Ist.Exit.dst->Ico.U64) > env->max_ga;
++ addInstr(env, LOONGARCH64Instr_XDirect(stmt->Ist.Exit.dst->Ico.U64,
++ am, cond, toFastEP));
++ } else {
++ /* .. very occasionally .. */
++ /* We can't use chaining, so ask for an assisted transfer,
++ as that's the only alternative that is allowable. */
++ HReg dst = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
++ addInstr(env, LOONGARCH64Instr_XAssisted(dst, am, cond, Ijk_Boring));
++ }
++ return;
++ }
+
-+#define LOONGARCH_CPUCFG16 0x10
-+#define CPUCFG16_L1_IUPRE BIT(0)
-+#define CPUCFG16_L1_IUUNIFY BIT(1)
-+#define CPUCFG16_L1_DPRE BIT(2)
-+#define CPUCFG16_L2_IUPRE BIT(3)
-+#define CPUCFG16_L2_IUUNIFY BIT(4)
-+#define CPUCFG16_L2_DPRE BIT(7)
-+#define CPUCFG16_L3_IUPRE BIT(10)
-+#define CPUCFG16_L3_IUUNIFY BIT(11)
-+#define CPUCFG16_L3_DPRE BIT(14)
++ /* Case: assisted transfer to arbitrary address */
++ switch (stmt->Ist.Exit.jk) {
++ /* Keep this list in sync with that for iselNext below */
++ case Ijk_ClientReq:
++ case Ijk_Yield:
++ case Ijk_NoDecode:
++ case Ijk_InvalICache:
++ case Ijk_NoRedir:
++ case Ijk_SigILL:
++ case Ijk_SigTRAP:
++ case Ijk_SigSEGV:
++ case Ijk_SigBUS:
++ case Ijk_SigFPE_IntDiv:
++ case Ijk_SigFPE_IntOvf:
++ case Ijk_SigSYS:
++ case Ijk_Sys_syscall: {
++ HReg dst = iselIntExpr_R(env, IRExpr_Const(stmt->Ist.Exit.dst));
++ addInstr(env, LOONGARCH64Instr_XAssisted(dst, am, cond, stmt->Ist.Exit.jk));
++ break;
++ }
++ default:
++ /* Do we ever expect to see any other kind? */
++ ppIRJumpKind(stmt->Ist.Exit.jk);
++ vpanic("iselStmt(loongarch64): Ist_Exit: unexpected jump kind");
++ break;
++ }
++}
+
-+#define LOONGARCH_CPUCFG17 0x11
-+#define CPUCFG17_L1I_WAYS_M GENMASK(15, 0)
-+#define CPUCFG17_L1I_SETS_M GENMASK(23, 16)
-+#define CPUCFG17_L1I_SIZE_M GENMASK(30, 24)
-+#define CPUCFG17_L1I_WAYS 0
-+#define CPUCFG17_L1I_SETS 16
-+#define CPUCFG17_L1I_SIZE 24
++static void iselStmt(ISelEnv* env, IRStmt* stmt)
++{
++ if (vex_traceflags & VEX_TRACE_VCODE) {
++ vex_printf("\n-- ");
++ ppIRStmt(stmt);
++ vex_printf("\n");
++ }
+
-+#define LOONGARCH_CPUCFG18 0x12
-+#define CPUCFG18_L1D_WAYS_M GENMASK(15, 0)
-+#define CPUCFG18_L1D_SETS_M GENMASK(23, 16)
-+#define CPUCFG18_L1D_SIZE_M GENMASK(30, 24)
-+#define CPUCFG18_L1D_WAYS 0
-+#define CPUCFG18_L1D_SETS 16
-+#define CPUCFG18_L1D_SIZE 24
++ switch (stmt->tag) {
++ /* --------- STORE --------- */
++ /* little-endian write to memory */
++ case Ist_Store:
++ iselStmtStore(env, stmt);
++ break;
+
-+#define LOONGARCH_CPUCFG19 0x13
-+#define CPUCFG19_L2_WAYS_M GENMASK(15, 0)
-+#define CPUCFG19_L2_SETS_M GENMASK(23, 16)
-+#define CPUCFG19_L2_SIZE_M GENMASK(30, 24)
-+#define CPUCFG19_L2_WAYS 0
-+#define CPUCFG19_L2_SETS 16
-+#define CPUCFG19_L2_SIZE 24
++ /* --------- PUT --------- */
++ /* write guest state, fixed offset */
++ case Ist_Put:
++ iselStmtPut(env, stmt);
++ break;
+
-+#define LOONGARCH_CPUCFG20 0x14
-+#define CPUCFG20_L3_WAYS_M GENMASK(15, 0)
-+#define CPUCFG20_L3_SETS_M GENMASK(23, 16)
-+#define CPUCFG20_L3_SIZE_M GENMASK(30, 24)
-+#define CPUCFG20_L3_WAYS 0
-+#define CPUCFG20_L3_SETS 16
-+#define CPUCFG20_L3_SIZE 24
++ /* --------- TMP --------- */
++ /* assign value to temporary */
++ case Ist_WrTmp:
++ iselStmtTmp(env, stmt);
++ break;
+
-+struct cache_status {
-+ Bool has_iu;
-+ Bool is_u;
-+ Bool has_d;
-+ Bool exist;
-+ UInt num;
-+};
++ /* --------- Call to DIRTY helper --------- */
++ /* call complex ("dirty") helper function */
++ case Ist_Dirty:
++ iselStmtDirty(env, stmt);
++ break;
+
-+static inline UInt
-+cpucfg(UInt reg)
-+{
-+ return (UInt)__builtin_loongarch_cpucfg(reg);
-+}
++ /* --------- Load Linked and Store Conditional --------- */
++ case Ist_LLSC:
++ iselStmtLLSC(env, stmt);
++ break;
+
-+static void
-+get_status(struct cache_status status[], UInt n)
-+{
-+ Bool has_iu = status[n].has_iu;
-+ Bool is_u = status[n].is_u;
-+ Bool has_d = status[n].has_d;
++ /* --------- CAS --------- */
++ case Ist_CAS:
++ iselStmtCas(env, stmt);
++ break;
+
-+ /* has_d only works with no ucache */
-+ status[n].has_d = has_d = toBool(!(has_iu && is_u) && has_d);
++ /* --------- MEM FENCE --------- */
++ case Ist_MBE:
++ iselStmtMBE(env, stmt);
++ break;
+
-+ status[n].exist = toBool(has_iu || has_d);
-+ status[n].num = has_iu + has_d;
-+}
++ /* --------- INSTR MARK --------- */
++ /* Doesn't generate any executable code ... */
++ case Ist_IMark:
++ break;
+
-+static void
-+get_cache(VexCacheInfo *ci, VexCacheKind kind, UInt level,
-+ UInt line_size, UInt sets, UInt ways, UInt index)
-+{
-+ UInt assoc = ways;
-+ UInt size = sets * ways * line_size;
-+ ci->caches[index] = VEX_CACHE_INIT(kind, level, size, line_size, assoc);
-+}
++ /* --------- ABI HINT --------- */
++ /* These have no meaning (denotation in the IR) and so we ignore
++ them ... if any actually made it this far. */
++ case Ist_AbiHint:
++ break;
+
-+static void
-+get_cache_info_for_l1(VexCacheInfo *ci, struct cache_status status[])
-+{
-+ UInt config;
-+ UInt line_size, sets, ways;
-+ UInt index = 0;
++ /* --------- NO-OP --------- */
++ case Ist_NoOp:
++ break;
+
-+ if (!status[0].exist)
-+ return;
++ /* --------- EXIT --------- */
++ case Ist_Exit:
++ iselStmtExit(env, stmt);
++ break;
+
-+ if (status[0].has_iu) {
-+ config = cpucfg(LOONGARCH_CPUCFG17);
-+ line_size = 1 << ((config & CPUCFG17_L1I_SIZE_M) >> CPUCFG17_L1I_SIZE);
-+ sets = 1 << ((config & CPUCFG17_L1I_SETS_M) >> CPUCFG17_L1I_SETS);
-+ ways = ((config & CPUCFG17_L1I_WAYS_M) >> CPUCFG17_L1I_WAYS) + 1;
-+ get_cache(ci, status[0].is_u ? UNIFIED_CACHE : INSN_CACHE,
-+ 1, line_size, sets, ways, index++);
++ default:
++ ppIRStmt(stmt);
++ vpanic("iselStmt(loongarch64)");
++ break;
+ }
++}
+
-+ if (status[0].has_d) {
-+ config = cpucfg(LOONGARCH_CPUCFG18);
-+ line_size = 1 << ((config & CPUCFG18_L1D_SIZE_M) >> CPUCFG18_L1D_SIZE);
-+ sets = 1 << ((config & CPUCFG18_L1D_SETS_M) >> CPUCFG18_L1D_SETS);
-+ ways = ((config & CPUCFG18_L1D_WAYS_M) >> CPUCFG18_L1D_WAYS) + 1;
-+ get_cache(ci, DATA_CACHE, 1, line_size, sets, ways, index++);
-+ }
+
-+ /* Sanity check */
-+ vg_assert(index == status[0].num);
-+}
++/*---------------------------------------------------------*/
++/*--- ISEL: Basic block terminators (Nexts) ---*/
++/*---------------------------------------------------------*/
+
-+static void
-+get_cache_info_for_l2(VexCacheInfo *ci, struct cache_status status[])
++static void iselNext ( ISelEnv* env, IRExpr* next, IRJumpKind jk, Int offsIP )
+{
-+ UInt config;
-+ UInt line_size, sets, ways;
-+ UInt index = status[0].num;
-+
-+ if (!status[1].exist)
-+ return;
++ if (vex_traceflags & VEX_TRACE_VCODE) {
++ vex_printf("\n-- PUT(%d) = ", offsIP);
++ ppIRExpr(next);
++ vex_printf("; exit-");
++ ppIRJumpKind(jk);
++ vex_printf("\n");
++ }
+
-+ config = cpucfg(LOONGARCH_CPUCFG19);
-+ line_size = 1 << ((config & CPUCFG19_L2_SIZE_M) >> CPUCFG19_L2_SIZE);
-+ sets = 1 << ((config & CPUCFG19_L2_SETS_M) >> CPUCFG19_L2_SETS);
-+ ways = ((config & CPUCFG19_L2_WAYS_M) >> CPUCFG19_L2_WAYS) + 1;
++ /* Case: boring transfer to known address */
++ if (next->tag == Iex_Const) {
++ IRConst* cdst = next->Iex.Const.con;
++ vassert(cdst->tag == Ico_U64);
++ if (jk == Ijk_Boring || jk == Ijk_Call) {
++ /* Boring transfer to known address */
++ LOONGARCH64AMode* am = mkLOONGARCH64AMode_RI(hregGSP(), offsIP);
++ if (env->chainingAllowed) {
++ /* .. almost always true .. */
++ /* Skip the event check at the dst if this is a forwards edge. */
++ Bool toFastEP = ((Addr64)cdst->Ico.U64) > env->max_ga;
++ addInstr(env, LOONGARCH64Instr_XDirect(cdst->Ico.U64, am,
++ INVALID_HREG, toFastEP));
++ } else {
++ /* .. very occasionally .. */
++ /* We can't use chaining, so ask for an assisted transfer,
++ as that's the only alternative that is allowable. */
++ HReg dst = iselIntExpr_R(env, next);
++ addInstr(env, LOONGARCH64Instr_XAssisted(dst, am, INVALID_HREG, Ijk_Boring));
++ }
++ return;
++ }
++ }
+
-+ if (status[1].has_iu)
-+ get_cache(ci, status[1].is_u ? UNIFIED_CACHE : INSN_CACHE,
-+ 2, line_size, sets, ways, index++);
++ /* Case: call/return (==boring) transfer to any address */
++ switch (jk) {
++ case Ijk_Boring:
++ case Ijk_Ret:
++ case Ijk_Call: {
++ HReg dst = iselIntExpr_R(env, next);
++ LOONGARCH64AMode* am = mkLOONGARCH64AMode_RI(hregGSP(), offsIP);
++ if (env->chainingAllowed) {
++ addInstr(env, LOONGARCH64Instr_XIndir(dst, am, INVALID_HREG));
++ } else {
++ addInstr(env, LOONGARCH64Instr_XAssisted(dst, am,
++ INVALID_HREG, Ijk_Boring));
++ }
++ return;
++ }
++ default:
++ break;
++ }
+
-+ if (status[1].has_d)
-+ get_cache(ci, DATA_CACHE, 2, line_size, sets, ways, index++);
++ /* Case: assisted transfer to arbitrary address */
++ switch (jk) {
++ /* Keep this list in sync with that for Ist_Exit above */
++ case Ijk_ClientReq:
++ case Ijk_Yield:
++ case Ijk_NoDecode:
++ case Ijk_InvalICache:
++ case Ijk_NoRedir:
++ case Ijk_SigILL:
++ case Ijk_SigTRAP:
++ case Ijk_SigSEGV:
++ case Ijk_SigBUS:
++ case Ijk_SigFPE_IntDiv:
++ case Ijk_SigFPE_IntOvf:
++ case Ijk_SigSYS:
++ case Ijk_Sys_syscall: {
++ HReg dst = iselIntExpr_R(env, next);
++ LOONGARCH64AMode* am = mkLOONGARCH64AMode_RI(hregGSP(), offsIP);
++ addInstr(env, LOONGARCH64Instr_XAssisted(dst, am, INVALID_HREG, jk));
++ return;
++ }
++ default:
++ break;
++ }
+
-+ /* Sanity check */
-+ vg_assert(index == status[0].num + status[1].num);
++ vex_printf("\n-- PUT(%d) = ", offsIP);
++ ppIRExpr(next);
++ vex_printf("; exit-");
++ ppIRJumpKind(jk);
++ vex_printf("\n");
++ vassert(0); // are we expecting any other kind?
+}
+
-+static void
-+get_cache_info_for_l3(VexCacheInfo *ci, struct cache_status status[])
-+{
-+ UInt config;
-+ UInt line_size, sets, ways;
-+ UInt index = status[0].num + status[1].num;
+
-+ if (!status[2].exist)
-+ return;
++/*---------------------------------------------------------*/
++/*--- Insn selector top-level ---*/
++/*---------------------------------------------------------*/
+
-+ config = cpucfg(LOONGARCH_CPUCFG20);
-+ line_size = 1 << ((config & CPUCFG20_L3_SIZE_M) >> CPUCFG20_L3_SIZE);
-+ sets = 1 << ((config & CPUCFG20_L3_SETS_M) >> CPUCFG20_L3_SETS);
-+ ways = ((config & CPUCFG20_L3_WAYS_M) >> CPUCFG20_L3_WAYS) + 1;
++/* Translate an entire BB to LOONGARCH64 code. */
++HInstrArray* iselSB_LOONGARCH64 ( const IRSB* bb,
++ VexArch arch_host,
++ const VexArchInfo* archinfo_host,
++ const VexAbiInfo* vbi,
++ Int offs_Host_EvC_Counter,
++ Int offs_Host_EvC_FailAddr,
++ Bool chainingAllowed,
++ Bool addProfInc,
++ Addr max_ga )
++{
++ Int i, j;
++ HReg hreg, hregHI;
++ ISelEnv* env;
++ UInt hwcaps_host = archinfo_host->hwcaps;
++ LOONGARCH64AMode *amCounter, *amFailAddr;
+
-+ if (status[2].has_iu)
-+ get_cache(ci, status[2].is_u ? UNIFIED_CACHE : INSN_CACHE,
-+ 3, line_size, sets, ways, index++);
++ /* sanity ... */
++ vassert(arch_host == VexArchLOONGARCH64);
++ vassert((hwcaps_host & ~(VEX_HWCAPS_LOONGARCH_CPUCFG
++ | VEX_HWCAPS_LOONGARCH_LAM
++ | VEX_HWCAPS_LOONGARCH_UAL
++ | VEX_HWCAPS_LOONGARCH_FP
++ | VEX_HWCAPS_LOONGARCH_LSX
++ | VEX_HWCAPS_LOONGARCH_LASX
++ | VEX_HWCAPS_LOONGARCH_COMPLEX
++ | VEX_HWCAPS_LOONGARCH_CRYPTO
++ | VEX_HWCAPS_LOONGARCH_LVZP
++ | VEX_HWCAPS_LOONGARCH_X86BT
++ | VEX_HWCAPS_LOONGARCH_ARMBT
++ | VEX_HWCAPS_LOONGARCH_MIPSBT
++ | VEX_HWCAPS_LOONGARCH_ISA_32BIT
++ | VEX_HWCAPS_LOONGARCH_ISA_64BIT)) == 0);
+
-+ if (status[2].has_d)
-+ get_cache(ci, DATA_CACHE, 3, line_size, sets, ways, index++);
++ /* Check that the host's endianness is as expected. */
++ vassert(archinfo_host->endness == VexEndnessLE);
+
-+ /* Sanity check */
-+ vg_assert(index == status[0].num + status[1].num + status[2].num);
-+}
++ /* Make up an initial environment to use. */
++ env = LibVEX_Alloc_inline(sizeof(ISelEnv));
++ env->vreg_ctr = 0;
+
-+static Bool
-+get_cache_info_from_cpucfg(VexCacheInfo *ci)
-+{
-+ Int i;
-+ struct cache_status status[3];
-+ UInt config = cpucfg(LOONGARCH_CPUCFG16);
++ /* Set up output code array. */
++ env->code = newHInstrArray();
+
-+ /* NB: Bool is unsigned char! */
-+ /* For l1 */
-+ status[0].has_iu = toBool(config & CPUCFG16_L1_IUPRE);
-+ status[0].is_u = toBool(config & CPUCFG16_L1_IUUNIFY);
-+ status[0].has_d = toBool(config & CPUCFG16_L1_DPRE);
-+ get_status(status, 0);
++ /* Copy BB's type env. */
++ env->type_env = bb->tyenv;
+
-+ /* For l2 */
-+ status[1].has_iu = toBool(config & CPUCFG16_L2_IUPRE);
-+ status[1].is_u = toBool(config & CPUCFG16_L2_IUUNIFY);
-+ status[1].has_d = toBool(config & CPUCFG16_L2_DPRE);
-+ get_status(status, 1);
++ /* Make up an IRTemp -> virtual HReg mapping. This doesn't
++ change as we go along. */
++ env->n_vregmap = bb->tyenv->types_used;
++ env->vregmap = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
++ env->vregmapHI = LibVEX_Alloc_inline(env->n_vregmap * sizeof(HReg));
+
-+ /* For l3 */
-+ status[2].has_iu = toBool(config & CPUCFG16_L3_IUPRE);
-+ status[2].is_u = toBool(config & CPUCFG16_L3_IUUNIFY);
-+ status[2].has_d = toBool(config & CPUCFG16_L3_DPRE);
-+ get_status(status, 2);
++ /* and finally ... */
++ env->chainingAllowed = chainingAllowed;
++ env->hwcaps = hwcaps_host;
++ env->max_ga = max_ga;
+
-+ ci->num_levels = 0;
-+ ci->num_caches = 0;
-+ for (i = 0; i < 3; i++) {
-+ ci->num_levels += status[i].exist;
-+ ci->num_caches += status[i].num;
++ /* For each IR temporary, allocate a suitably-kinded virtual register. */
++ j = 0;
++ for (i = 0; i < env->n_vregmap; i++) {
++ hregHI = hreg = INVALID_HREG;
++ switch (bb->tyenv->types[i]) {
++ case Ity_I1:
++ case Ity_I8:
++ case Ity_I16:
++ case Ity_I32:
++ case Ity_I64:
++ hreg = mkHReg(True, HRcInt64, 0, j++);
++ break;
++ case Ity_I128:
++ hreg = mkHReg(True, HRcInt64, 0, j++);
++ hregHI = mkHReg(True, HRcInt64, 0, j++);
++ break;
++ case Ity_F16: // we'll use HRcFlt64 regs for F16 too
++ case Ity_F32: // we'll use HRcFlt64 regs for F32 too
++ case Ity_F64:
++ hreg = mkHReg(True, HRcFlt64, 0, j++);
++ break;
++ case Ity_V128:
++ hreg = mkHReg(True, HRcVec128, 0, j++);
++ break;
++ case Ity_V256:
++ hreg = mkHReg(True, HRcVec128, 0, j++);
++ hregHI = mkHReg(True, HRcVec128, 0, j++);
++ break;
++ default:
++ ppIRType(bb->tyenv->types[i]);
++ vpanic("iselBB(loongarch64): IRTemp type");
++ break;
++ }
++ env->vregmap[i] = hreg;
++ env->vregmapHI[i] = hregHI;
+ }
++ env->vreg_ctr = j;
+
-+ if (ci->num_caches == 0) {
-+ VG_(debugLog)(1, "cache", "Autodetect failed\n");
-+ return False;
++ /* The very first instruction must be an event check. */
++ amCounter = mkLOONGARCH64AMode_RI(hregGSP(), offs_Host_EvC_Counter);
++ amFailAddr = mkLOONGARCH64AMode_RI(hregGSP(), offs_Host_EvC_FailAddr);
++ addInstr(env, LOONGARCH64Instr_EvCheck(amCounter, amFailAddr));
++
++ /* Possibly a block counter increment (for profiling). At this
++ point we don't know the address of the counter, so just pretend
++ it is zero. It will have to be patched later, but before this
++ translation is used, by a call to LibVEX_patchProfCtr. */
++ if (addProfInc) {
++ addInstr(env, LOONGARCH64Instr_ProfInc());
+ }
+
-+ ci->caches = VG_(malloc)("m_cache", ci->num_caches * sizeof(VexCache));
-+ get_cache_info_for_l1(ci, status);
-+ get_cache_info_for_l2(ci, status);
-+ get_cache_info_for_l3(ci, status);
-+ return True;
-+}
++ /* Ok, finally we can iterate over the statements. */
++ for (i = 0; i < bb->stmts_used; i++)
++ iselStmt(env, bb->stmts[i]);
+
-+static Bool
-+get_cache_info(VexArchInfo *vai)
-+{
-+ VexCacheInfo *ci = &vai->hwcache_info;
-+ ci->icaches_maintain_coherence = True;
-+ return get_cache_info_from_cpucfg(ci);
++ iselNext(env, bb->next, bb->jumpkind, bb->offsIP);
++
++ /* record the number of vregs we used. */
++ env->code->n_vregs = env->vreg_ctr;
++ return env->code;
+}
+
- #else
++
++/*---------------------------------------------------------------*/
++/*--- end host_loongarch64_isel.c ---*/
++/*---------------------------------------------------------------*/
+diff --git a/VEX/priv/ir_defs.c b/VEX/priv/ir_defs.c
+index 9e7fbf9..26fc323 100644
+--- a/VEX/priv/ir_defs.c
++++ b/VEX/priv/ir_defs.c
+@@ -280,6 +280,8 @@ void ppIROp ( IROp op )
+ case Iop_SubF64: vex_printf("SubF64"); return;
+ case Iop_MulF64: vex_printf("MulF64"); return;
+ case Iop_DivF64: vex_printf("DivF64"); return;
++ case Iop_ScaleBF64: vex_printf("ScaleBF64"); return;
++ case Iop_ScaleBF32: vex_printf("ScaleBF32"); return;
+ case Iop_AddF64r32: vex_printf("AddF64r32"); return;
+ case Iop_SubF64r32: vex_printf("SubF64r32"); return;
+ case Iop_MulF64r32: vex_printf("MulF64r32"); return;
+@@ -356,6 +358,10 @@ void ppIROp ( IROp op )
+ case Iop_SqrtF64: vex_printf("SqrtF64"); return;
+ case Iop_SqrtF32: vex_printf("SqrtF32"); return;
+ case Iop_SqrtF16: vex_printf("SqrtF16"); return;
++ case Iop_RSqrtF32: vex_printf("RSqrtF32"); return;
++ case Iop_RSqrtF64: vex_printf("RSqrtF64"); return;
++ case Iop_LogBF32: vex_printf("LogBF32"); return;
++ case Iop_LogBF64: vex_printf("LogBF64"); return;
+ case Iop_SinF64: vex_printf("SinF64"); return;
+ case Iop_CosF64: vex_printf("CosF64"); return;
+ case Iop_TanF64: vex_printf("TanF64"); return;
+@@ -379,8 +385,12 @@ void ppIROp ( IROp op )
+
+ case Iop_MaxNumF64: vex_printf("MaxNumF64"); return;
+ case Iop_MinNumF64: vex_printf("MinNumF64"); return;
++ case Iop_MaxNumAbsF64: vex_printf("MaxNumAbsF64"); return;
++ case Iop_MinNumAbsF64: vex_printf("MinNumAbsF64"); return;
+ case Iop_MaxNumF32: vex_printf("MaxNumF32"); return;
+ case Iop_MinNumF32: vex_printf("MinNumF32"); return;
++ case Iop_MaxNumAbsF32: vex_printf("MaxNumAbsF32"); return;
++ case Iop_MinNumAbsF32: vex_printf("MinNumAbsF32"); return;
+
+ case Iop_F16toF64: vex_printf("F16toF64"); return;
+ case Iop_F64toF16: vex_printf("F64toF16"); return;
+@@ -774,6 +784,11 @@ void ppIROp ( IROp op )
+ case Iop_F32x4_2toQ16x8: vex_printf("F32x4_2toQ16x8"); return;
+ case Iop_F64x2_2toQ32x4: vex_printf("F64x2_2toQ32x4"); return;
+
++ case Iop_RoundF64x2_RM: vex_printf("RoundF64x2_RM"); return;
++ case Iop_RoundF64x2_RP: vex_printf("RoundF64x2_RP"); return;
++ case Iop_RoundF64x2_RN: vex_printf("RoundF64x2_RN"); return;
++ case Iop_RoundF64x2_RZ: vex_printf("RoundF64x2_RZ"); return;
++
+ case Iop_V128to64: vex_printf("V128to64"); return;
+ case Iop_V128HIto64: vex_printf("V128HIto64"); return;
+ case Iop_64HLtoV128: vex_printf("64HLtoV128"); return;
+@@ -1108,6 +1123,14 @@ void ppIROp ( IROp op )
+ case Iop_Widen8Sto16x8: vex_printf("Widen8Sto16x8"); return;
+ case Iop_Widen16Sto32x4: vex_printf("Widen16Sto32x4"); return;
+ case Iop_Widen32Sto64x2: vex_printf("Widen32Sto64x2"); return;
++ case Iop_WidenHIto16Sx8: vex_printf("WidenHIto16Sx8"); return;
++ case Iop_WidenHIto32Sx4: vex_printf("WidenHIto32Sx4"); return;
++ case Iop_WidenHIto64Sx2: vex_printf("WidenHIto64Sx2"); return;
++ case Iop_WidenHIto128Sx1: vex_printf("WidenHIto128Sx1"); return;
++ case Iop_WidenHIto16Ux8: vex_printf("WidenHIto16Ux8"); return;
++ case Iop_WidenHIto32Ux4: vex_printf("WidenHIto32Ux4"); return;
++ case Iop_WidenHIto64Ux2: vex_printf("WidenHIto64Ux2"); return;
++ case Iop_WidenHIto128Ux1: vex_printf("WidenHIto128Ux1"); return;
+
+ case Iop_InterleaveHI8x16: vex_printf("InterleaveHI8x16"); return;
+ case Iop_InterleaveHI16x8: vex_printf("InterleaveHI16x8"); return;
+@@ -1278,67 +1301,148 @@ void ppIROp ( IROp op )
+ case Iop_OrV256: vex_printf("OrV256"); return;
+ case Iop_XorV256: vex_printf("XorV256"); return;
+ case Iop_NotV256: vex_printf("NotV256"); return;
++ case Iop_CmpNEZ128x2: vex_printf("CmpNEZ128x2"); return;
+ case Iop_CmpNEZ64x4: vex_printf("CmpNEZ64x4"); return;
+ case Iop_CmpNEZ32x8: vex_printf("CmpNEZ32x8"); return;
+ case Iop_CmpNEZ16x16: vex_printf("CmpNEZ16x16"); return;
+ case Iop_CmpNEZ8x32: vex_printf("CmpNEZ8x32"); return;
+
++ case Iop_WidenHIto16Sx16: vex_printf("WidenHIto16Sx16"); return;
++ case Iop_WidenHIto32Sx8: vex_printf("WidenHIto32Sx8"); return;
++ case Iop_WidenHIto64Sx4: vex_printf("WidenHIto64Sx4"); return;
++ case Iop_WidenHIto128Sx2: vex_printf("WidenHIto128Sx2"); return;
++ case Iop_WidenHIto16Ux16: vex_printf("WidenHIto16Ux16"); return;
++ case Iop_WidenHIto32Ux8: vex_printf("WidenHIto32Ux8"); return;
++ case Iop_WidenHIto64Ux4: vex_printf("WidenHIto64Ux4"); return;
++ case Iop_WidenHIto128Ux2: vex_printf("WidenHIto128Ux2"); return;
++ case Iop_InterleaveHI8x32: vex_printf("InterleaveHI8x32"); return;
++ case Iop_InterleaveHI16x16: vex_printf("InterleaveHI16x16"); return;
++ case Iop_InterleaveHI32x8: vex_printf("InterleaveHI32x8"); return;
++ case Iop_InterleaveHI64x4: vex_printf("InterleaveHI64x4"); return;
++ case Iop_InterleaveLO8x32: vex_printf("InterleaveLO8x32"); return;
++ case Iop_InterleaveLO16x16: vex_printf("InterleaveLO16x16"); return;
++ case Iop_InterleaveLO32x8: vex_printf("InterleaveLO32x8"); return;
++ case Iop_InterleaveLO64x4: vex_printf("InterleaveLO64x4"); return;
++ case Iop_InterleaveOddLanes8x32: vex_printf("InterleaveOddLanes8x32"); return;
++ case Iop_InterleaveOddLanes16x16: vex_printf("InterleaveOddLanes16x16"); return;
++ case Iop_InterleaveOddLanes32x8: vex_printf("InterleaveOddLanes32x8"); return;
++ case Iop_InterleaveEvenLanes8x32: vex_printf("InterleaveEvenLanes8x32"); return;
++ case Iop_InterleaveEvenLanes16x16: vex_printf("InterleaveEvenLanes16x16"); return;
++ case Iop_InterleaveEvenLanes32x8: vex_printf("InterleaveEvenLanes32x8"); return;
++ case Iop_PackOddLanes8x32: vex_printf("PackOddLanes8x32"); return;
++ case Iop_PackOddLanes16x16: vex_printf("PackOddLanes16x16"); return;
++ case Iop_PackOddLanes32x8: vex_printf("PackOddLanes32x8"); return;
++ case Iop_PackEvenLanes8x32: vex_printf("PackEvenLanes8x32"); return;
++ case Iop_PackEvenLanes16x16: vex_printf("PackEvenLanes16x16"); return;
++ case Iop_PackEvenLanes32x8: vex_printf("PackEvenLanes32x8"); return;
++
+ case Iop_Add8x32: vex_printf("Add8x32"); return;
+ case Iop_Add16x16: vex_printf("Add16x16"); return;
+ case Iop_Add32x8: vex_printf("Add32x8"); return;
+ case Iop_Add64x4: vex_printf("Add64x4"); return;
++ case Iop_Add128x2: vex_printf("Add128x2"); return;
+ case Iop_Sub8x32: vex_printf("Sub8x32"); return;
+ case Iop_Sub16x16: vex_printf("Sub16x16"); return;
+ case Iop_Sub32x8: vex_printf("Sub32x8"); return;
+ case Iop_Sub64x4: vex_printf("Sub64x4"); return;
++ case Iop_Sub128x2: vex_printf("Sub128x2"); return;
+ case Iop_QAdd8Ux32: vex_printf("QAdd8Ux32"); return;
+ case Iop_QAdd16Ux16: vex_printf("QAdd16Ux16"); return;
++ case Iop_QAdd32Ux8: vex_printf("QAdd32Ux8"); return;
++ case Iop_QAdd64Ux4: vex_printf("QAdd64Ux4"); return;
+ case Iop_QAdd8Sx32: vex_printf("QAdd8Sx32"); return;
+ case Iop_QAdd16Sx16: vex_printf("QAdd16Sx16"); return;
++ case Iop_QAdd32Sx8: vex_printf("QAdd32Sx8"); return;
++ case Iop_QAdd64Sx4: vex_printf("QAdd64Sx4"); return;
+ case Iop_QSub8Ux32: vex_printf("QSub8Ux32"); return;
+ case Iop_QSub16Ux16: vex_printf("QSub16Ux16"); return;
++ case Iop_QSub32Ux8: vex_printf("QSub32Ux8"); return;
++ case Iop_QSub64Ux4: vex_printf("QSub64Ux4"); return;
+ case Iop_QSub8Sx32: vex_printf("QSub8Sx32"); return;
+ case Iop_QSub16Sx16: vex_printf("QSub16Sx16"); return;
++ case Iop_QSub32Sx8: vex_printf("QSub32Sx8"); return;
++ case Iop_QSub64Sx4: vex_printf("QSub64Sx4"); return;
+
+- case Iop_Mul16x16: vex_printf("Mul16x16"); return;
+- case Iop_Mul32x8: vex_printf("Mul32x8"); return;
++ case Iop_Mul8x32: vex_printf("Mul8x32"); return;
++ case Iop_Mul16x16: vex_printf("Mul16x16"); return;
++ case Iop_Mul32x8: vex_printf("Mul32x8"); return;
++ case Iop_MulHi8Ux32: vex_printf("MulHi8Ux32"); return;
+ case Iop_MulHi16Ux16: vex_printf("MulHi16Ux16"); return;
++ case Iop_MulHi32Ux8: vex_printf("MulHi32Ux8"); return;
++ case Iop_MulHi8Sx32: vex_printf("MulHi8Sx32"); return;
+ case Iop_MulHi16Sx16: vex_printf("MulHi16Sx16"); return;
++ case Iop_MulHi32Sx8: vex_printf("MulHi32Sx8"); return;
+
+ case Iop_Avg8Ux32: vex_printf("Avg8Ux32"); return;
+ case Iop_Avg16Ux16: vex_printf("Avg16Ux16"); return;
++ case Iop_Avg32Ux8: vex_printf("Avg32Ux8"); return;
++ case Iop_Avg64Ux4: vex_printf("Avg64Ux4"); return;
++ case Iop_Avg8Sx32: vex_printf("Avg8Sx32"); return;
++ case Iop_Avg16Sx16: vex_printf("Avg16Sx16"); return;
++ case Iop_Avg32Sx8: vex_printf("Avg32Sx8"); return;
++ case Iop_Avg64Sx4: vex_printf("Avg64Sx4"); return;
++
++ case Iop_Shl8x32: vex_printf("Shl8x32"); return;
++ case Iop_Shl16x16: vex_printf("Shl16x16"); return;
++ case Iop_Shl32x8: vex_printf("Shl32x8"); return;
++ case Iop_Shl64x4: vex_printf("Shl64x4"); return;
++ case Iop_Shr8x32: vex_printf("Shr8x32"); return;
++ case Iop_Shr16x16: vex_printf("Shr16x16"); return;
++ case Iop_Shr32x8: vex_printf("Shr32x8"); return;
++ case Iop_Shr64x4: vex_printf("Shr64x4"); return;
++ case Iop_Sar8x32: vex_printf("Sar8x32"); return;
++ case Iop_Sar16x16: vex_printf("Sar16x16"); return;
++ case Iop_Sar32x8: vex_printf("Sar32x8"); return;
++ case Iop_Sar64x4: vex_printf("Sar64x4"); return;
++
++ case Iop_Abs8x32: vex_printf("Abs8x32"); return;
++ case Iop_Abs16x16: vex_printf("Abs16x16"); return;
++ case Iop_Abs32x8: vex_printf("Abs32x8"); return;
++ case Iop_Abs64x4: vex_printf("Abs64x4"); return;
+
+ case Iop_Max8Sx32: vex_printf("Max8Sx32"); return;
+ case Iop_Max16Sx16: vex_printf("Max16Sx16"); return;
+ case Iop_Max32Sx8: vex_printf("Max32Sx8"); return;
++ case Iop_Max64Sx4: vex_printf("Max64Sx4"); return;
+ case Iop_Max8Ux32: vex_printf("Max8Ux32"); return;
+ case Iop_Max16Ux16: vex_printf("Max16Ux16"); return;
+ case Iop_Max32Ux8: vex_printf("Max32Ux8"); return;
++ case Iop_Max64Ux4: vex_printf("Max64Ux4"); return;
+
+ case Iop_Min8Sx32: vex_printf("Min8Sx32"); return;
+ case Iop_Min16Sx16: vex_printf("Min16Sx16"); return;
+ case Iop_Min32Sx8: vex_printf("Min32Sx8"); return;
++ case Iop_Min64Sx4: vex_printf("Min64Sx4"); return;
+ case Iop_Min8Ux32: vex_printf("Min8Ux32"); return;
+ case Iop_Min16Ux16: vex_printf("Min16Ux16"); return;
+ case Iop_Min32Ux8: vex_printf("Min32Ux8"); return;
++ case Iop_Min64Ux4: vex_printf("Min64Ux4"); return;
+
+ case Iop_CmpEQ8x32: vex_printf("CmpEQ8x32"); return;
+ case Iop_CmpEQ16x16: vex_printf("CmpEQ16x16"); return;
+ case Iop_CmpEQ32x8: vex_printf("CmpEQ32x8"); return;
+ case Iop_CmpEQ64x4: vex_printf("CmpEQ64x4"); return;
++ case Iop_CmpGT8Ux32: vex_printf("CmpGT8Ux32"); return;
++ case Iop_CmpGT16Ux16: vex_printf("CmpGT16Ux16"); return;
++ case Iop_CmpGT32Ux8: vex_printf("CmpGT32Ux8"); return;
++ case Iop_CmpGT64Ux4: vex_printf("CmpGT64Ux4"); return;
+ case Iop_CmpGT8Sx32: vex_printf("CmpGT8Sx32"); return;
+ case Iop_CmpGT16Sx16: vex_printf("CmpGT16Sx16"); return;
+ case Iop_CmpGT32Sx8: vex_printf("CmpGT32Sx8"); return;
+ case Iop_CmpGT64Sx4: vex_printf("CmpGT64Sx4"); return;
+
++ case Iop_ShlN8x32: vex_printf("ShlN8x32"); return;
+ case Iop_ShlN16x16: vex_printf("ShlN16x16"); return;
+ case Iop_ShlN32x8: vex_printf("ShlN32x8"); return;
+ case Iop_ShlN64x4: vex_printf("ShlN64x4"); return;
++ case Iop_ShrN8x32: vex_printf("ShrN8x32"); return;
+ case Iop_ShrN16x16: vex_printf("ShrN16x16"); return;
+ case Iop_ShrN32x8: vex_printf("ShrN32x8"); return;
+ case Iop_ShrN64x4: vex_printf("ShrN64x4"); return;
++ case Iop_SarN8x32: vex_printf("SarN8x32"); return;
+ case Iop_SarN16x16: vex_printf("SarN16x16"); return;
+ case Iop_SarN32x8: vex_printf("SarN32x8"); return;
++ case Iop_SarN64x4: vex_printf("SarN64x4"); return;
+
+ case Iop_Perm32x8: vex_printf("Perm32x8"); return;
+
+@@ -1438,10 +1542,13 @@ Bool primopMightTrap ( IROp op )
+ case Iop_1Uto8: case Iop_1Uto32: case Iop_1Uto64: case Iop_1Sto8:
+ case Iop_1Sto16: case Iop_1Sto32: case Iop_1Sto64:
+ case Iop_AddF64: case Iop_SubF64: case Iop_MulF64: case Iop_DivF64:
++ case Iop_ScaleBF64: case Iop_ScaleBF32:
+ case Iop_AddF32: case Iop_SubF32: case Iop_MulF32: case Iop_DivF32:
+ case Iop_AddF64r32: case Iop_SubF64r32: case Iop_MulF64r32:
+ case Iop_DivF64r32: case Iop_NegF64: case Iop_AbsF64:
+ case Iop_NegF32: case Iop_AbsF32: case Iop_SqrtF64: case Iop_SqrtF32:
++ case Iop_RSqrtF64: case Iop_RSqrtF32:
++ case Iop_LogBF64: case Iop_LogBF32:
+ case Iop_NegF16: case Iop_AbsF16: case Iop_SqrtF16: case Iop_SubF16:
+ case Iop_AddF16:
+ case Iop_CmpF64: case Iop_CmpF32: case Iop_CmpF16: case Iop_CmpF128:
+@@ -1483,8 +1590,11 @@ Bool primopMightTrap ( IROp op )
+ case Iop_RSqrtEst5GoodF64: case Iop_RoundF64toF64_NEAREST:
+ case Iop_RoundF64toF64_NegINF: case Iop_RoundF64toF64_PosINF:
+ case Iop_RoundF64toF64_ZERO: case Iop_TruncF64asF32: case Iop_RoundF64toF32:
+- case Iop_RecpExpF64: case Iop_RecpExpF32: case Iop_MaxNumF64:
+- case Iop_MinNumF64: case Iop_MaxNumF32: case Iop_MinNumF32:
++ case Iop_RecpExpF64: case Iop_RecpExpF32:
++ case Iop_MaxNumF64: case Iop_MinNumF64:
++ case Iop_MaxNumAbsF64: case Iop_MinNumAbsF64:
++ case Iop_MaxNumF32: case Iop_MinNumF32:
++ case Iop_MaxNumAbsF32: case Iop_MinNumAbsF32:
+ case Iop_F16toF64: case Iop_F64toF16: case Iop_F16toF32:
+ case Iop_F32toF16: case Iop_QAdd32S: case Iop_QSub32S:
+ case Iop_Add16x2: case Iop_Sub16x2:
+@@ -1631,6 +1741,8 @@ Bool primopMightTrap ( IROp op )
+ case Iop_Sqrt64Fx2: case Iop_Scale2_64Fx2: case Iop_Log2_64Fx2:
+ case Iop_RecipEst64Fx2: case Iop_RecipStep64Fx2: case Iop_RSqrtEst64Fx2:
+ case Iop_RSqrtStep64Fx2: case Iop_F64x2_2toQ32x4:
++ case Iop_RoundF64x2_RM: case Iop_RoundF64x2_RP:
++ case Iop_RoundF64x2_RN: case Iop_RoundF64x2_RZ:
+ case Iop_Add64F0x2: case Iop_Sub64F0x2: case Iop_Mul64F0x2:
+ case Iop_Div64F0x2: case Iop_Max64F0x2: case Iop_Min64F0x2:
+ case Iop_CmpEQ64F0x2: case Iop_CmpLT64F0x2: case Iop_CmpLE64F0x2:
+@@ -1751,6 +1863,10 @@ Bool primopMightTrap ( IROp op )
+ case Iop_QNarrowUn64Uto32Ux2:
+ case Iop_Widen8Uto16x8: case Iop_Widen16Uto32x4: case Iop_Widen32Uto64x2:
+ case Iop_Widen8Sto16x8: case Iop_Widen16Sto32x4: case Iop_Widen32Sto64x2:
++ case Iop_WidenHIto16Sx8: case Iop_WidenHIto32Sx4:
++ case Iop_WidenHIto64Sx2: case Iop_WidenHIto128Sx1:
++ case Iop_WidenHIto16Ux8: case Iop_WidenHIto32Ux4:
++ case Iop_WidenHIto64Ux2: case Iop_WidenHIto128Ux1:
+ case Iop_InterleaveHI8x16: case Iop_InterleaveHI16x8:
+ case Iop_InterleaveHI32x4: case Iop_InterleaveHI64x2:
+ case Iop_InterleaveLO8x16: case Iop_InterleaveLO16x8:
+@@ -1782,31 +1898,51 @@ Bool primopMightTrap ( IROp op )
+ case Iop_AndV256: case Iop_OrV256: case Iop_XorV256:
+ case Iop_NotV256:
+ case Iop_CmpNEZ8x32: case Iop_CmpNEZ16x16: case Iop_CmpNEZ32x8:
+- case Iop_CmpNEZ64x4:
+- case Iop_Add8x32: case Iop_Add16x16: case Iop_Add32x8: case Iop_Add64x4:
+- case Iop_Sub8x32: case Iop_Sub16x16: case Iop_Sub32x8: case Iop_Sub64x4:
++ case Iop_CmpNEZ64x4: case Iop_CmpNEZ128x2:
++ case Iop_Add8x32: case Iop_Add16x16: case Iop_Add32x8: case Iop_Add64x4: case Iop_Add128x2:
++ case Iop_Sub8x32: case Iop_Sub16x16: case Iop_Sub32x8: case Iop_Sub64x4: case Iop_Sub128x2:
+ case Iop_CmpEQ8x32: case Iop_CmpEQ16x16: case Iop_CmpEQ32x8:
+ case Iop_CmpEQ64x4:
+- case Iop_CmpGT8Sx32: case Iop_CmpGT16Sx16: case Iop_CmpGT32Sx8:
+- case Iop_CmpGT64Sx4:
+- case Iop_ShlN16x16: case Iop_ShlN32x8: case Iop_ShlN64x4:
+- case Iop_ShrN16x16: case Iop_ShrN32x8: case Iop_ShrN64x4:
+- case Iop_SarN16x16: case Iop_SarN32x8:
+- case Iop_Max8Sx32: case Iop_Max16Sx16: case Iop_Max32Sx8:
+- case Iop_Max8Ux32: case Iop_Max16Ux16: case Iop_Max32Ux8:
+- case Iop_Min8Sx32: case Iop_Min16Sx16: case Iop_Min32Sx8:
+- case Iop_Min8Ux32: case Iop_Min16Ux16: case Iop_Min32Ux8:
+- case Iop_Mul16x16: case Iop_Mul32x8:
+- case Iop_MulHi16Ux16: case Iop_MulHi16Sx16:
+- case Iop_QAdd8Ux32: case Iop_QAdd16Ux16:
+- case Iop_QAdd8Sx32: case Iop_QAdd16Sx16:
+- case Iop_QSub8Ux32: case Iop_QSub16Ux16:
+- case Iop_QSub8Sx32: case Iop_QSub16Sx16:
+- case Iop_Avg8Ux32: case Iop_Avg16Ux16:
++ case Iop_CmpGT8Ux32: case Iop_CmpGT16Ux16: case Iop_CmpGT32Ux8: case Iop_CmpGT64Ux4:
++ case Iop_CmpGT8Sx32: case Iop_CmpGT16Sx16: case Iop_CmpGT32Sx8: case Iop_CmpGT64Sx4:
++ case Iop_ShlN8x32: case Iop_ShlN16x16: case Iop_ShlN32x8: case Iop_ShlN64x4:
++ case Iop_ShrN8x32: case Iop_ShrN16x16: case Iop_ShrN32x8: case Iop_ShrN64x4:
++ case Iop_SarN8x32: case Iop_SarN16x16: case Iop_SarN32x8: case Iop_SarN64x4:
++ case Iop_Shl8x32: case Iop_Shl16x16: case Iop_Shl32x8: case Iop_Shl64x4:
++ case Iop_Shr8x32: case Iop_Shr16x16: case Iop_Shr32x8: case Iop_Shr64x4:
++ case Iop_Sar8x32: case Iop_Sar16x16: case Iop_Sar32x8: case Iop_Sar64x4:
++ case Iop_Max8Sx32: case Iop_Max16Sx16: case Iop_Max32Sx8: case Iop_Max64Sx4:
++ case Iop_Max8Ux32: case Iop_Max16Ux16: case Iop_Max32Ux8: case Iop_Max64Ux4:
++ case Iop_Min8Sx32: case Iop_Min16Sx16: case Iop_Min32Sx8: case Iop_Min64Sx4:
++ case Iop_Min8Ux32: case Iop_Min16Ux16: case Iop_Min32Ux8: case Iop_Min64Ux4:
++ case Iop_Mul8x32: case Iop_Mul16x16: case Iop_Mul32x8:
++ case Iop_MulHi8Ux32: case Iop_MulHi16Ux16: case Iop_MulHi32Ux8:
++ case Iop_MulHi8Sx32: case Iop_MulHi16Sx16: case Iop_MulHi32Sx8:
++ case Iop_QAdd8Ux32: case Iop_QAdd16Ux16: case Iop_QAdd32Ux8: case Iop_QAdd64Ux4:
++ case Iop_QAdd8Sx32: case Iop_QAdd16Sx16: case Iop_QAdd32Sx8: case Iop_QAdd64Sx4:
++ case Iop_QSub8Ux32: case Iop_QSub16Ux16: case Iop_QSub32Ux8: case Iop_QSub64Ux4:
++ case Iop_QSub8Sx32: case Iop_QSub16Sx16: case Iop_QSub32Sx8: case Iop_QSub64Sx4:
++ case Iop_Avg8Ux32: case Iop_Avg16Ux16: case Iop_Avg32Ux8: case Iop_Avg64Ux4:
++ case Iop_Avg8Sx32: case Iop_Avg16Sx16: case Iop_Avg32Sx8: case Iop_Avg64Sx4:
++ case Iop_Abs8x32: case Iop_Abs16x16: case Iop_Abs32x8: case Iop_Abs64x4:
+ case Iop_Perm32x8:
+ case Iop_CipherV128: case Iop_CipherLV128: case Iop_CipherSV128:
+ case Iop_NCipherV128: case Iop_NCipherLV128:
+ case Iop_SHA512: case Iop_SHA256:
++ case Iop_WidenHIto16Sx16: case Iop_WidenHIto32Sx8:
++ case Iop_WidenHIto64Sx4: case Iop_WidenHIto128Sx2:
++ case Iop_WidenHIto16Ux16: case Iop_WidenHIto32Ux8:
++ case Iop_WidenHIto64Ux4: case Iop_WidenHIto128Ux2:
++ case Iop_InterleaveHI8x32: case Iop_InterleaveHI16x16:
++ case Iop_InterleaveHI32x8: case Iop_InterleaveHI64x4:
++ case Iop_InterleaveLO8x32: case Iop_InterleaveLO16x16:
++ case Iop_InterleaveLO32x8: case Iop_InterleaveLO64x4:
++ case Iop_InterleaveOddLanes8x32: case Iop_InterleaveEvenLanes8x32:
++ case Iop_InterleaveOddLanes16x16: case Iop_InterleaveEvenLanes16x16:
++ case Iop_InterleaveOddLanes32x8: case Iop_InterleaveEvenLanes32x8:
++ case Iop_PackOddLanes8x32: case Iop_PackEvenLanes8x32:
++ case Iop_PackOddLanes16x16: case Iop_PackEvenLanes16x16:
++ case Iop_PackOddLanes32x8: case Iop_PackEvenLanes32x8:
+ case Iop_Add64Fx4: case Iop_Sub64Fx4: case Iop_Mul64Fx4: case Iop_Div64Fx4:
+ case Iop_Add32Fx8: case Iop_Sub32Fx8: case Iop_Mul32Fx8: case Iop_Div32Fx8:
+ case Iop_I32StoF32x8: case Iop_F32toI32Sx8: case Iop_F32toF16x8:
+@@ -2081,6 +2217,7 @@ void ppIRJumpKind ( IRJumpKind kind )
+ case Ijk_SigFPE: vex_printf("SigFPE"); break;
+ case Ijk_SigFPE_IntDiv: vex_printf("SigFPE_IntDiv"); break;
+ case Ijk_SigFPE_IntOvf: vex_printf("SigFPE_IntOvf"); break;
++ case Ijk_SigSYS: vex_printf("SigSYS"); break;
+ case Ijk_Sys_syscall: vex_printf("Sys_syscall"); break;
+ case Ijk_Sys_int32: vex_printf("Sys_int32"); break;
+ case Ijk_Sys_int128: vex_printf("Sys_int128"); break;
+@@ -2101,6 +2238,8 @@ void ppIRMBusEvent ( IRMBusEvent event )
+ vex_printf("Fence"); break;
+ case Imbe_CancelReservation:
+ vex_printf("CancelReservation"); break;
++ case Imbe_InsnFence:
++ vex_printf("InsnFence"); break;
+ default:
+ vpanic("ppIRMBusEvent");
+ }
+@@ -3379,12 +3518,14 @@ void typeOfPrimop ( IROp op,
+
+ case Iop_AddF64: case Iop_SubF64:
+ case Iop_MulF64: case Iop_DivF64:
++ case Iop_ScaleBF64:
+ case Iop_AddF64r32: case Iop_SubF64r32:
+ case Iop_MulF64r32: case Iop_DivF64r32:
+ TERNARY(ity_RMode,Ity_F64,Ity_F64, Ity_F64);
+
+ case Iop_AddF32: case Iop_SubF32:
+ case Iop_MulF32: case Iop_DivF32:
++ case Iop_ScaleBF32:
+ TERNARY(ity_RMode,Ity_F32,Ity_F32, Ity_F32);
+
+ case Iop_AddF16:
+@@ -3401,10 +3542,14 @@ void typeOfPrimop ( IROp op,
+ UNARY(Ity_F16, Ity_F16);
- #error "Unknown arch"
-diff --git a/coregrind/m_coredump/coredump-elf.c b/coregrind/m_coredump/coredump-elf.c
-index 4a8c29c..82b1b43 100644
---- a/coregrind/m_coredump/coredump-elf.c
-+++ b/coregrind/m_coredump/coredump-elf.c
-@@ -489,6 +489,40 @@ static void fill_prstatus(const ThreadState *tst,
- regs[VKI_MIPS32_EF_CP0_STATUS] = arch->vex.guest_CP0_status;
- regs[VKI_MIPS32_EF_CP0_EPC] = arch->vex.guest_PC;
- # undef DO
-+#elif defined(VGP_loongarch64_linux)
-+ regs->regs[0] = arch->vex.guest_R0;
-+ regs->regs[1] = arch->vex.guest_R1;
-+ regs->regs[2] = arch->vex.guest_R2;
-+ regs->regs[3] = arch->vex.guest_R3;
-+ regs->regs[4] = arch->vex.guest_R4;
-+ regs->regs[5] = arch->vex.guest_R5;
-+ regs->regs[6] = arch->vex.guest_R6;
-+ regs->regs[7] = arch->vex.guest_R7;
-+ regs->regs[8] = arch->vex.guest_R8;
-+ regs->regs[9] = arch->vex.guest_R9;
-+ regs->regs[10] = arch->vex.guest_R10;
-+ regs->regs[11] = arch->vex.guest_R11;
-+ regs->regs[12] = arch->vex.guest_R12;
-+ regs->regs[13] = arch->vex.guest_R13;
-+ regs->regs[14] = arch->vex.guest_R14;
-+ regs->regs[15] = arch->vex.guest_R15;
-+ regs->regs[16] = arch->vex.guest_R16;
-+ regs->regs[17] = arch->vex.guest_R17;
-+ regs->regs[18] = arch->vex.guest_R18;
-+ regs->regs[19] = arch->vex.guest_R19;
-+ regs->regs[20] = arch->vex.guest_R20;
-+ regs->regs[21] = arch->vex.guest_R21;
-+ regs->regs[22] = arch->vex.guest_R22;
-+ regs->regs[23] = arch->vex.guest_R23;
-+ regs->regs[24] = arch->vex.guest_R24;
-+ regs->regs[25] = arch->vex.guest_R25;
-+ regs->regs[26] = arch->vex.guest_R26;
-+ regs->regs[27] = arch->vex.guest_R27;
-+ regs->regs[28] = arch->vex.guest_R28;
-+ regs->regs[29] = arch->vex.guest_R29;
-+ regs->regs[30] = arch->vex.guest_R30;
-+ regs->regs[31] = arch->vex.guest_R31;
-+ regs->csr_era = arch->vex.guest_PC;
- #elif defined(VGP_amd64_freebsd)
- regs->rflags = LibVEX_GuestAMD64_get_rflags( &arch->vex );
- regs->rsp = arch->vex.guest_RSP;
-@@ -654,6 +688,14 @@ static void fill_fpu(const ThreadState *tst, vki_elf_fpregset_t *fpu)
- # undef DO
- #elif defined(VGP_nanomips_linux)
+ case Iop_SqrtF64:
++ case Iop_RSqrtF64:
++ case Iop_LogBF64:
+ case Iop_RecpExpF64:
+ BINARY(ity_RMode,Ity_F64, Ity_F64);
-+#elif defined(VGP_loongarch64_linux)
-+# define DO(n) (*fpu)[n] = *(const double*)(&arch->vex.guest_X##n)
-+ DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
-+ DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
-+ DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
-+ DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
-+# undef DO
-+
- #elif defined(VGP_x86_freebsd)
+ case Iop_SqrtF32:
++ case Iop_RSqrtF32:
++ case Iop_LogBF32:
+ case Iop_RoundF32toInt:
+ case Iop_RecpExpF32:
+ BINARY(ity_RMode,Ity_F32, Ity_F32);
+@@ -3417,9 +3562,11 @@ void typeOfPrimop ( IROp op,
+ BINARY(ity_RMode, Ity_F16, Ity_F16);
- #elif defined(VGP_amd64_freebsd)
-diff --git a/coregrind/m_debuginfo/d3basics.c b/coregrind/m_debuginfo/d3basics.c
-index bcfd456..222496e 100644
---- a/coregrind/m_debuginfo/d3basics.c
-+++ b/coregrind/m_debuginfo/d3basics.c
-@@ -555,6 +555,9 @@ static Bool get_Dwarf_Reg( /*OUT*/Addr* a, Word regno, const RegSummary* regs )
- # elif defined(VGP_arm64_linux)
- if (regno == 31) { *a = regs->sp; return True; }
- if (regno == 29) { *a = regs->fp; return True; }
-+# elif defined(VGP_loongarch64_linux)
-+ if (regno == 3) { *a = regs->sp; return True; }
-+ if (regno == 22) { *a = regs->fp; return True; }
- # else
- # error "Unknown platform"
- # endif
-diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c
-index eed134b..32ac008 100644
---- a/coregrind/m_debuginfo/debuginfo.c
-+++ b/coregrind/m_debuginfo/debuginfo.c
-@@ -1300,7 +1300,7 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd )
- is_ro_map = False;
+ case Iop_MaxNumF64: case Iop_MinNumF64:
++ case Iop_MaxNumAbsF64: case Iop_MinNumAbsF64:
+ BINARY(Ity_F64,Ity_F64, Ity_F64);
- # if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32) \
-- || defined(VGA_mips64) || defined(VGA_nanomips)
-+ || defined(VGA_mips64) || defined(VGA_nanomips) || defined(VGA_loongarch64)
- is_rx_map = seg->hasR && seg->hasX;
- is_rw_map = seg->hasR && seg->hasW;
- # elif defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
-@@ -3116,6 +3116,11 @@ UWord evalCfiExpr ( const XArray* exprs, Int ix,
- case Creg_ARM64_SP: return eec->uregs->sp;
- case Creg_ARM64_X30: return eec->uregs->x30;
- case Creg_ARM64_X29: return eec->uregs->x29;
-+# elif defined(VGA_loongarch64)
-+ case Creg_LOONGARCH64_PC: return eec->uregs->pc;
-+ case Creg_LOONGARCH64_RA: return eec->uregs->ra;
-+ case Creg_LOONGARCH64_SP: return eec->uregs->sp;
-+ case Creg_LOONGARCH64_FP: return eec->uregs->fp;
- # else
- # error "Unsupported arch"
- # endif
-@@ -3389,6 +3394,13 @@ static Addr compute_cfa ( const D3UnwindRegs* uregs,
- case CFIC_ARM64_X29REL:
- cfa = cfsi_m->cfa_off + uregs->x29;
+ case Iop_MaxNumF32: case Iop_MinNumF32:
++ case Iop_MaxNumAbsF32: case Iop_MinNumAbsF32:
+ BINARY(Ity_F32,Ity_F32, Ity_F32);
+
+ case Iop_CmpF16:
+@@ -3519,6 +3666,10 @@ void typeOfPrimop ( IROp op,
+ case Iop_Abs64Fx2: case Iop_Abs32Fx4: case Iop_Abs16Fx8:
+ case Iop_RSqrtEst32Fx4:
+ case Iop_RSqrtEst32Ux4:
++ case Iop_RoundF64x2_RM:
++ case Iop_RoundF64x2_RP:
++ case Iop_RoundF64x2_RN:
++ case Iop_RoundF64x2_RZ:
+ UNARY(Ity_V128, Ity_V128);
+
+ case Iop_Sqrt64Fx2:
+@@ -3567,6 +3718,16 @@ void typeOfPrimop ( IROp op,
+ case Iop_F16toF32x4:
+ UNARY(Ity_I64, Ity_V128);
+
++ case Iop_WidenHIto16Sx8:
++ case Iop_WidenHIto32Sx4:
++ case Iop_WidenHIto64Sx2:
++ case Iop_WidenHIto128Sx1:
++ case Iop_WidenHIto16Ux8:
++ case Iop_WidenHIto32Ux4:
++ case Iop_WidenHIto64Ux2:
++ case Iop_WidenHIto128Ux1:
++ UNARY(Ity_V128, Ity_V128);
++
+ case Iop_V128to32: UNARY(Ity_V128, Ity_I32);
+ case Iop_32UtoV128: UNARY(Ity_I32, Ity_V128);
+ case Iop_64UtoV128: UNARY(Ity_I64, Ity_V128);
+@@ -4106,25 +4267,42 @@ void typeOfPrimop ( IROp op,
+ case Iop_Max32Fx8: case Iop_Min32Fx8:
+ case Iop_Max64Fx4: case Iop_Min64Fx4:
+ case Iop_Add8x32: case Iop_Add16x16:
+- case Iop_Add32x8: case Iop_Add64x4:
++ case Iop_Add32x8: case Iop_Add64x4: case Iop_Add128x2:
+ case Iop_Sub8x32: case Iop_Sub16x16:
+- case Iop_Sub32x8: case Iop_Sub64x4:
+- case Iop_Mul16x16: case Iop_Mul32x8:
+- case Iop_MulHi16Ux16: case Iop_MulHi16Sx16:
+- case Iop_Avg8Ux32: case Iop_Avg16Ux16:
+- case Iop_Max8Sx32: case Iop_Max16Sx16: case Iop_Max32Sx8:
+- case Iop_Max8Ux32: case Iop_Max16Ux16: case Iop_Max32Ux8:
+- case Iop_Min8Sx32: case Iop_Min16Sx16: case Iop_Min32Sx8:
+- case Iop_Min8Ux32: case Iop_Min16Ux16: case Iop_Min32Ux8:
++ case Iop_Sub32x8: case Iop_Sub64x4: case Iop_Sub128x2:
++ case Iop_Mul8x32: case Iop_Mul16x16: case Iop_Mul32x8:
++ case Iop_MulHi8Ux32: case Iop_MulHi16Ux16: case Iop_MulHi32Ux8:
++ case Iop_MulHi8Sx32: case Iop_MulHi16Sx16: case Iop_MulHi32Sx8:
++ case Iop_Avg8Ux32: case Iop_Avg16Ux16: case Iop_Avg32Ux8: case Iop_Avg64Ux4:
++ case Iop_Avg8Sx32: case Iop_Avg16Sx16: case Iop_Avg32Sx8: case Iop_Avg64Sx4:
++ case Iop_Shl8x32: case Iop_Shl16x16: case Iop_Shl32x8: case Iop_Shl64x4:
++ case Iop_Shr8x32: case Iop_Shr16x16: case Iop_Shr32x8: case Iop_Shr64x4:
++ case Iop_Sar8x32: case Iop_Sar16x16: case Iop_Sar32x8: case Iop_Sar64x4:
++ case Iop_Max8Sx32: case Iop_Max16Sx16: case Iop_Max32Sx8: case Iop_Max64Sx4:
++ case Iop_Max8Ux32: case Iop_Max16Ux16: case Iop_Max32Ux8: case Iop_Max64Ux4:
++ case Iop_Min8Sx32: case Iop_Min16Sx16: case Iop_Min32Sx8: case Iop_Min64Sx4:
++ case Iop_Min8Ux32: case Iop_Min16Ux16: case Iop_Min32Ux8: case Iop_Min64Ux4:
+ case Iop_CmpEQ8x32: case Iop_CmpEQ16x16:
+ case Iop_CmpEQ32x8: case Iop_CmpEQ64x4:
++ case Iop_CmpGT8Ux32: case Iop_CmpGT16Ux16:
++ case Iop_CmpGT32Ux8: case Iop_CmpGT64Ux4:
+ case Iop_CmpGT8Sx32: case Iop_CmpGT16Sx16:
+ case Iop_CmpGT32Sx8: case Iop_CmpGT64Sx4:
+- case Iop_QAdd8Ux32: case Iop_QAdd16Ux16:
+- case Iop_QAdd8Sx32: case Iop_QAdd16Sx16:
+- case Iop_QSub8Ux32: case Iop_QSub16Ux16:
+- case Iop_QSub8Sx32: case Iop_QSub16Sx16:
++ case Iop_QAdd8Ux32: case Iop_QAdd16Ux16: case Iop_QAdd32Ux8: case Iop_QAdd64Ux4:
++ case Iop_QAdd8Sx32: case Iop_QAdd16Sx16: case Iop_QAdd32Sx8: case Iop_QAdd64Sx4:
++ case Iop_QSub8Ux32: case Iop_QSub16Ux16: case Iop_QSub32Ux8: case Iop_QSub64Ux4:
++ case Iop_QSub8Sx32: case Iop_QSub16Sx16: case Iop_QSub32Sx8: case Iop_QSub64Sx4:
+ case Iop_Perm32x8:
++ case Iop_InterleaveHI8x32: case Iop_InterleaveHI16x16:
++ case Iop_InterleaveHI32x8: case Iop_InterleaveHI64x4:
++ case Iop_InterleaveLO8x32: case Iop_InterleaveLO16x16:
++ case Iop_InterleaveLO32x8: case Iop_InterleaveLO64x4:
++ case Iop_InterleaveOddLanes8x32: case Iop_InterleaveEvenLanes8x32:
++ case Iop_InterleaveOddLanes16x16: case Iop_InterleaveEvenLanes16x16:
++ case Iop_InterleaveOddLanes32x8: case Iop_InterleaveEvenLanes32x8:
++ case Iop_PackOddLanes8x32: case Iop_PackEvenLanes8x32:
++ case Iop_PackOddLanes16x16: case Iop_PackEvenLanes16x16:
++ case Iop_PackOddLanes32x8: case Iop_PackEvenLanes32x8:
+ BINARY(Ity_V256,Ity_V256, Ity_V256);
+
+ case Iop_I32StoF32x8:
+@@ -4157,14 +4335,17 @@ void typeOfPrimop ( IROp op,
+ case Iop_Sqrt64Fx4:
+ case Iop_RecipEst32Fx8:
+ case Iop_CmpNEZ8x32: case Iop_CmpNEZ16x16:
+- case Iop_CmpNEZ64x4: case Iop_CmpNEZ32x8:
++ case Iop_CmpNEZ64x4: case Iop_CmpNEZ32x8: case Iop_CmpNEZ128x2:
++ case Iop_WidenHIto16Sx16: case Iop_WidenHIto32Sx8:
++ case Iop_WidenHIto64Sx4: case Iop_WidenHIto128Sx2:
++ case Iop_WidenHIto16Ux16: case Iop_WidenHIto32Ux8:
++ case Iop_WidenHIto64Ux4: case Iop_WidenHIto128Ux2:
++ case Iop_Abs8x32: case Iop_Abs16x16: case Iop_Abs32x8: case Iop_Abs64x4:
+ UNARY(Ity_V256, Ity_V256);
+
+- case Iop_ShlN16x16: case Iop_ShlN32x8:
+- case Iop_ShlN64x4:
+- case Iop_ShrN16x16: case Iop_ShrN32x8:
+- case Iop_ShrN64x4:
+- case Iop_SarN16x16: case Iop_SarN32x8:
++ case Iop_ShlN8x32: case Iop_ShlN16x16: case Iop_ShlN32x8: case Iop_ShlN64x4:
++ case Iop_ShrN8x32: case Iop_ShrN16x16: case Iop_ShrN32x8: case Iop_ShrN64x4:
++ case Iop_SarN8x32: case Iop_SarN16x16: case Iop_SarN32x8: case Iop_SarN64x4:
+ BINARY(Ity_V256,Ity_I8, Ity_V256);
+ case Iop_Rotx32:
+ QUATERNARY(Ity_I32, Ity_I8, Ity_I8, Ity_I8, Ity_I32);
+@@ -5259,7 +5440,9 @@ void tcStmt ( const IRSB* bb, const IRStmt* stmt, IRType gWordTy )
break;
-+# elif defined(VGA_loongarch64)
-+ case CFIC_IA_SPREL:
-+ cfa = cfsi_m->cfa_off + uregs->sp;
-+ break;
-+ case CFIC_IA_BPREL:
-+ cfa = cfsi_m->cfa_off + uregs->fp;
-+ break;
- # else
- # error "Unsupported arch"
- # endif
-@@ -3460,6 +3472,14 @@ Addr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
- return compute_cfa(&uregs,
- min_accessible, max_accessible, ce->di, ce->cfsi_m);
- }
-+#elif defined(VGA_loongarch64)
-+ { D3UnwindRegs uregs;
-+ uregs.pc = ip;
-+ uregs.sp = sp;
-+ uregs.fp = fp;
-+ return compute_cfa(&uregs,
-+ min_accessible, max_accessible, ce->di, ce->cfsi_m);
-+ }
+ case Ist_MBE:
+ switch (stmt->Ist.MBE.event) {
+- case Imbe_Fence: case Imbe_CancelReservation:
++ case Imbe_Fence:
++ case Imbe_CancelReservation:
++ case Imbe_InsnFence:
+ break;
+ default: sanityCheckFail(bb,stmt,"IRStmt.MBE.event: unknown");
+ break;
+diff --git a/VEX/priv/main_main.c b/VEX/priv/main_main.c
+index e6c788d..23988fb 100644
+--- a/VEX/priv/main_main.c
++++ b/VEX/priv/main_main.c
+@@ -43,6 +43,7 @@
+ #include "libvex_guest_s390x.h"
+ #include "libvex_guest_mips32.h"
+ #include "libvex_guest_mips64.h"
++#include "libvex_guest_loongarch64.h"
- # else
- return 0; /* indicates failure */
-@@ -3511,6 +3531,8 @@ void VG_(ppUnwindInfo) (Addr from, Addr to)
- For arm64, the unwound registers are: X29(FP) X30(LR) SP PC.
+ #include "main_globals.h"
+ #include "main_util.h"
+@@ -57,6 +58,7 @@
+ #include "host_s390_defs.h"
+ #include "host_mips_defs.h"
+ #include "host_nanomips_defs.h"
++#include "host_loongarch64_defs.h"
- For s390, the unwound registers are: R11(FP) R14(LR) R15(SP) F0..F7 PC.
-+
-+ For loongarch64, the unwound registers are: FP SP PC
- */
- Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
- Addr min_accessible,
-@@ -3534,6 +3556,8 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
- # elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
- # elif defined(VGP_arm64_linux)
- ipHere = uregsHere->pc;
-+# elif defined(VGA_loongarch64)
-+ ipHere = uregsHere->pc;
- # else
- # error "Unknown arch"
- # endif
-@@ -3679,6 +3703,10 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
- COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi_m->sp_how, cfsi_m->sp_off);
- COMPUTE(uregsPrev.x30, uregsHere->x30, cfsi_m->x30_how, cfsi_m->x30_off);
- COMPUTE(uregsPrev.x29, uregsHere->x29, cfsi_m->x29_how, cfsi_m->x29_off);
-+# elif defined(VGA_loongarch64)
-+ COMPUTE(uregsPrev.pc, uregsHere->ra, cfsi_m->ra_how, cfsi_m->ra_off);
-+ COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi_m->sp_how, cfsi_m->sp_off);
-+ COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi_m->fp_how, cfsi_m->fp_off);
- # else
- # error "Unknown arch"
- # endif
-diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h
-index 441b379..41224a8 100644
---- a/coregrind/m_debuginfo/priv_storage.h
-+++ b/coregrind/m_debuginfo/priv_storage.h
-@@ -367,6 +367,19 @@ typedef
- Int fp_off;
- }
- DiCfSI_m;
-+#elif defined(VGA_loongarch64)
-+typedef
-+ struct {
-+ UChar cfa_how; /* a CFIC_ value */
-+ UChar ra_how; /* a CFIR_ value */
-+ UChar sp_how; /* a CFIR_ value */
-+ UChar fp_how; /* a CFIR_ value */
-+ Int cfa_off;
-+ Int ra_off;
-+ Int sp_off;
-+ Int fp_off;
-+ }
-+ DiCfSI_m;
- #else
- # error "Unknown arch"
- #endif
-@@ -422,7 +435,11 @@ typedef
- Creg_S390_SP,
- Creg_S390_FP,
- Creg_S390_LR,
-- Creg_MIPS_RA
-+ Creg_MIPS_RA,
-+ Creg_LOONGARCH64_PC,
-+ Creg_LOONGARCH64_RA,
-+ Creg_LOONGARCH64_SP,
-+ Creg_LOONGARCH64_FP
- }
- CfiReg;
+ #include "guest_generic_bb_to_IR.h"
+ #include "guest_x86_defs.h"
+@@ -67,6 +69,7 @@
+ #include "guest_s390_defs.h"
+ #include "guest_mips_defs.h"
+ #include "guest_nanomips_defs.h"
++#include "guest_loongarch64_defs.h"
-diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c
-index 7b8187e..13363ae 100644
---- a/coregrind/m_debuginfo/readdwarf.c
-+++ b/coregrind/m_debuginfo/readdwarf.c
-@@ -2066,6 +2066,10 @@ void ML_(read_debuginfo_dwarf1) (
- # define FP_REG 30
- # define SP_REG 29
- # define RA_REG_DEFAULT 31
-+#elif defined(VGP_loongarch64_linux)
-+# define FP_REG 22
-+# define SP_REG 3
-+# define RA_REG_DEFAULT 1
- #else
- # error "Unknown platform"
- #endif
-@@ -2084,6 +2088,8 @@ void ML_(read_debuginfo_dwarf1) (
- # define N_CFI_REGS 128
- #elif defined(VGP_s390x_linux)
- # define N_CFI_REGS 66
-+#elif defined(VGP_loongarch64_linux)
-+# define N_CFI_REGS 32
- #else
- # define N_CFI_REGS 20
+ #include "host_generic_simd128.h"
+
+@@ -163,6 +166,14 @@
+ #define NANOMIPSST(f) vassert(0)
#endif
-@@ -2310,6 +2316,10 @@ static void initUnwindContext ( /*OUT*/UnwindContext* ctx )
- start out as RR_Same. */
- ctx->state[j].reg[29/*FP*/].tag = RR_Same;
- ctx->state[j].reg[30/*LR*/].tag = RR_Same;
-+# elif defined(VGA_loongarch64)
-+ /* Registers fp and ra start out implicitly as RR_Same. */
-+ ctx->state[j].reg[FP_REG].tag = RR_Same;
-+ ctx->state[j].reg[RA_REG_DEFAULT].tag = RR_Same;
- # endif
- }
- }
-@@ -2392,7 +2402,8 @@ static Bool summarise_context(/*OUT*/Addr* base,
- if (ctxs->cfa_is_regoff && ctxs->cfa_reg == SP_REG) {
- si_m->cfa_off = ctxs->cfa_off;
- # if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \
-- || defined(VGA_mips32) || defined(VGA_nanomips) || defined(VGA_mips64)
-+ || defined(VGA_mips32) || defined(VGA_nanomips) || defined(VGA_mips64) \
-+ || defined(VGA_loongarch64)
- si_m->cfa_how = CFIC_IA_SPREL;
- # elif defined(VGA_arm)
- si_m->cfa_how = CFIC_ARM_R13REL;
-@@ -2406,7 +2417,8 @@ static Bool summarise_context(/*OUT*/Addr* base,
- if (ctxs->cfa_is_regoff && ctxs->cfa_reg == FP_REG) {
- si_m->cfa_off = ctxs->cfa_off;
- # if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \
-- || defined(VGA_mips32) || defined(VGA_nanomips) || defined(VGA_mips64)
-+ || defined(VGA_mips32) || defined(VGA_nanomips) || defined(VGA_mips64) \
-+ || defined(VGA_loongarch64)
- si_m->cfa_how = CFIC_IA_BPREL;
- # elif defined(VGA_arm)
- si_m->cfa_how = CFIC_ARM_R12REL;
-@@ -2786,6 +2798,30 @@ static Bool summarise_context(/*OUT*/Addr* base,
- # elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
- /* These don't use CFI based unwinding (is that really true?) */
-+# elif defined(VGA_loongarch64)
-+
-+ /* --- entire tail of this fn specialised for loongarch64 --- */
-+
-+ SUMMARISE_HOW(si_m->ra_how, si_m->ra_off, ctxs->reg[ctx->ra_reg]);
-+ SUMMARISE_HOW(si_m->fp_how, si_m->fp_off, ctxs->reg[FP_REG]);
-+
-+ /* on loongarch64, it seems the old sp value before the call is always
-+ the same as the CFA. Therefore ... */
-+ si_m->sp_how = CFIR_CFAREL;
-+ si_m->sp_off = 0;
-+
-+ /* bogus looking range? Note, we require that the difference is
-+ representable in 32 bits. */
-+ if (loc_start >= ctx->loc)
-+ { why = 4; goto failed; }
-+ if (ctx->loc - loc_start > 10000000 /* let's say */)
-+ { why = 5; goto failed; }
++#if defined(VGA_loongarch64) || defined(VEXMULTIARCH)
++#define LOONGARCH64FN(f) f
++#define LOONGARCH64ST(f) f
++#else
++#define LOONGARCH64FN(f) NULL
++#define LOONGARCH64ST(f) vassert(0)
++#endif
+
-+ *base = loc_start + ctx->initloc;
-+ *len = (UInt)(ctx->loc - loc_start);
+ /* This file contains the top level interface to the library. */
+
+ /* --------- fwds ... --------- */
+@@ -541,6 +552,23 @@ IRSB* LibVEX_FrontEnd ( /*MOD*/ VexTranslateArgs* vta,
+ vassert(sizeof( ((VexGuestMIPS32State*)0)->guest_NRADDR ) == 4);
+ break;
+
++ case VexArchLOONGARCH64:
++ preciseMemExnsFn
++ = LOONGARCH64FN(guest_loongarch64_state_requires_precise_mem_exns);
++ disInstrFn = LOONGARCH64FN(disInstr_LOONGARCH64);
++ specHelper = LOONGARCH64FN(guest_loongarch64_spechelper);
++ guest_layout = LOONGARCH64FN(&loongarch64Guest_layout);
++ offB_CMSTART = offsetof(VexGuestLOONGARCH64State, guest_CMSTART);
++ offB_CMLEN = offsetof(VexGuestLOONGARCH64State, guest_CMLEN);
++ offB_GUEST_IP = offsetof(VexGuestLOONGARCH64State, guest_PC);
++ szB_GUEST_IP = sizeof( ((VexGuestLOONGARCH64State*)0)->guest_PC );
++ vassert(vta->archinfo_guest.endness == VexEndnessLE);
++ vassert(sizeof(VexGuestLOONGARCH64State) % LibVEX_GUEST_STATE_ALIGN == 0);
++ vassert(sizeof( ((VexGuestLOONGARCH64State*)0)->guest_CMSTART) == 8);
++ vassert(sizeof( ((VexGuestLOONGARCH64State*)0)->guest_CMLEN ) == 8);
++ vassert(sizeof( ((VexGuestLOONGARCH64State*)0)->guest_NRADDR ) == 8);
++ break;
+
-+ return True;
+ default:
+ vpanic("LibVEX_Translate: unsupported guest insn set");
+ }
+@@ -878,6 +906,14 @@ static void libvex_BackEnd ( const VexTranslateArgs *vta,
+ offB_HOST_EvC_FAILADDR = offsetof(VexGuestMIPS32State,host_EvC_FAILADDR);
+ break;
+
++ case VexArchLOONGARCH64:
++ preciseMemExnsFn
++ = LOONGARCH64FN(guest_loongarch64_state_requires_precise_mem_exns);
++ guest_sizeB = sizeof(VexGuestLOONGARCH64State);
++ offB_HOST_EvC_COUNTER = offsetof(VexGuestLOONGARCH64State, host_EvC_COUNTER);
++ offB_HOST_EvC_FAILADDR = offsetof(VexGuestLOONGARCH64State, host_EvC_FAILADDR);
++ break;
+
- # else
- # error "Unknown arch"
- # endif
-@@ -2885,6 +2921,13 @@ static Int copy_convert_CfiExpr_tree ( XArray* dstxa,
- return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM64_X30 );
- # elif defined(VGA_ppc32) || defined(VGA_ppc64be) \
- || defined(VGA_ppc64le)
-+# elif defined(VGA_loongarch64)
-+ if (dwreg == SP_REG)
-+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_LOONGARCH64_SP );
-+ if (dwreg == FP_REG)
-+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_LOONGARCH64_FP );
-+ if (dwreg == srcuc->ra_reg)
-+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_LOONGARCH64_RA );
- # else
- # error "Unknown arch"
- # endif
-diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c
-index fb64ed9..5e77c79 100644
---- a/coregrind/m_debuginfo/readelf.c
-+++ b/coregrind/m_debuginfo/readelf.c
-@@ -1781,7 +1781,8 @@ static HChar* readlink_path (const HChar *path)
+ default:
+ vpanic("LibVEX_Codegen: unsupported guest insn set");
+ }
+@@ -1052,6 +1088,23 @@ static void libvex_BackEnd ( const VexTranslateArgs *vta,
+ || vta->archinfo_host.endness == VexEndnessBE);
+ break;
- while (tries > 0) {
- SysRes res;
--#if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+#if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
- (UWord)path, (UWord)buf, bufsiz);
- #elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
-@@ -2702,8 +2703,9 @@ Bool ML_(read_elf_object) ( struct _DebugInfo* di )
- || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
- || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux) \
- || defined(VGP_x86_solaris) || defined(VGP_amd64_solaris) \
-- || defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd)
-+ || defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd) \
- /* Accept .plt where mapped as rx (code) */
- if (0 == VG_(strcmp)(name, ".plt")) {
- if (inrx && !di->plt_present) {
-diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c
-index 961d767..fbfe027 100644
---- a/coregrind/m_debuginfo/storage.c
-+++ b/coregrind/m_debuginfo/storage.c
-@@ -260,6 +260,11 @@ void ML_(ppDiCfSI) ( const XArray* /* of CfiExpr */ exprs,
- SHOW_HOW(si_m->x30_how, si_m->x30_off);
- VG_(printf)(" X29=");
- SHOW_HOW(si_m->x29_how, si_m->x29_off);
-+# elif defined(VGP_loongarch64_linux)
-+ VG_(printf)(" SP=");
-+ SHOW_HOW(si_m->sp_how, si_m->sp_off);
-+ VG_(printf)(" FP=");
-+ SHOW_HOW(si_m->fp_how, si_m->fp_off);
- # else
- # error "Unknown arch"
- # endif
-@@ -1010,6 +1015,10 @@ static void ppCfiReg ( CfiReg reg )
- case Creg_S390_SP: VG_(printf)("SP"); break;
- case Creg_S390_FP: VG_(printf)("FP"); break;
- case Creg_S390_LR: VG_(printf)("LR"); break;
-+ case Creg_LOONGARCH64_PC: VG_(printf)("PC"); break;
-+ case Creg_LOONGARCH64_RA: VG_(printf)("RA"); break;
-+ case Creg_LOONGARCH64_SP: VG_(printf)("SP"); break;
-+ case Creg_LOONGARCH64_FP: VG_(printf)("FP"); break;
- default: vg_assert(0);
++ case VexArchLOONGARCH64:
++ mode64 = True;
++ rRegUniv = LOONGARCH64FN(getRRegUniverse_LOONGARCH64());
++ getRegUsage
++ = CAST_TO_TYPEOF(getRegUsage) LOONGARCH64FN(getRegUsage_LOONGARCH64Instr);
++ mapRegs = CAST_TO_TYPEOF(mapRegs) LOONGARCH64FN(mapRegs_LOONGARCH64Instr);
++ genSpill = CAST_TO_TYPEOF(genSpill) LOONGARCH64FN(genSpill_LOONGARCH64);
++ genReload = CAST_TO_TYPEOF(genReload) LOONGARCH64FN(genReload_LOONGARCH64);
++ genMove = CAST_TO_TYPEOF(genMove) LOONGARCH64FN(genMove_LOONGARCH64);
++ ppInstr = CAST_TO_TYPEOF(ppInstr) LOONGARCH64FN(ppLOONGARCH64Instr);
++ ppReg = CAST_TO_TYPEOF(ppReg) LOONGARCH64FN(ppHRegLOONGARCH64);
++ iselSB = LOONGARCH64FN(iselSB_LOONGARCH64);
++ emit = CAST_TO_TYPEOF(emit) LOONGARCH64FN(emit_LOONGARCH64Instr);
++ vassert(vta->archinfo_host.endness == VexEndnessLE
++ || vta->archinfo_host.endness == VexEndnessBE);
++ break;
++
+ default:
+ vpanic("LibVEX_Translate: unsupported host insn set");
+ }
+@@ -1297,6 +1350,11 @@ VexInvalRange LibVEX_Chain ( VexArch arch_host,
+ place_to_chain,
+ disp_cp_chain_me_EXPECTED,
+ place_to_jump_to));
++ case VexArchLOONGARCH64:
++ LOONGARCH64ST(return chainXDirect_LOONGARCH64(endness_host,
++ place_to_chain,
++ disp_cp_chain_me_EXPECTED,
++ place_to_jump_to));
+ default:
+ vassert(0);
+ }
+@@ -1359,6 +1417,11 @@ VexInvalRange LibVEX_UnChain ( VexArch arch_host,
+ place_to_unchain,
+ place_to_jump_to_EXPECTED,
+ disp_cp_chain_me));
++ case VexArchLOONGARCH64:
++ LOONGARCH64ST(return unchainXDirect_LOONGARCH64(endness_host,
++ place_to_unchain,
++ place_to_jump_to_EXPECTED,
++ disp_cp_chain_me));
+ default:
+ vassert(0);
+ }
+@@ -1389,6 +1452,8 @@ Int LibVEX_evCheckSzB ( VexArch arch_host )
+ MIPS64ST(cached = evCheckSzB_MIPS()); break;
+ case VexArchNANOMIPS:
+ NANOMIPSST(cached = evCheckSzB_NANOMIPS()); break;
++ case VexArchLOONGARCH64:
++ LOONGARCH64ST(cached = evCheckSzB_LOONGARCH64()); break;
+ default:
+ vassert(0);
+ }
+@@ -1432,6 +1497,10 @@ VexInvalRange LibVEX_PatchProfInc ( VexArch arch_host,
+ case VexArchNANOMIPS:
+ NANOMIPSST(return patchProfInc_NANOMIPS(endness_host, place_to_patch,
+ location_of_counter));
++ case VexArchLOONGARCH64:
++ LOONGARCH64ST(return patchProfInc_LOONGARCH64(endness_host,
++ place_to_patch,
++ location_of_counter));
+ default:
+ vassert(0);
+ }
+@@ -1515,6 +1584,7 @@ const HChar* LibVEX_ppVexArch ( VexArch arch )
+ case VexArchMIPS32: return "MIPS32";
+ case VexArchMIPS64: return "MIPS64";
+ case VexArchNANOMIPS: return "NANOMIPS";
++ case VexArchLOONGARCH64: return "LOONGARCH64";
+ default: return "VexArch???";
}
}
-diff --git a/coregrind/m_debuglog.c b/coregrind/m_debuglog.c
-index fd6db4b..eacc73b 100644
---- a/coregrind/m_debuglog.c
-+++ b/coregrind/m_debuglog.c
-@@ -601,6 +601,41 @@ static UInt local_sys_getpid ( void )
- return a0;
+@@ -1586,6 +1656,7 @@ static IRType arch_word_size (VexArch arch) {
+ case VexArchMIPS64:
+ case VexArchPPC64:
+ case VexArchS390X:
++ case VexArchLOONGARCH64:
+ return Ity_I64;
+
+ default:
+@@ -1929,6 +2000,38 @@ static const HChar* show_hwcaps_mips64 ( UInt hwcaps )
+ return "Unsupported baseline";
}
-+#elif defined(VGP_loongarch64_linux)
-+
-+static UInt local_sys_write_stderr ( const HChar* buf, Int n )
++static const HChar* show_hwcaps_loongarch64 ( UInt hwcaps )
+{
-+ ULong ret;
-+ __asm__ volatile (
-+ "li.w $a0, 2 \n\t" // stderr
-+ "move $a1, %1 \n\t"
-+ "move $a2, %2 \n\t"
-+ "li.w $a7, " VG_STRINGIFY(__NR_write) " \n\t"
-+ "syscall 0 \n\t"
-+ "move %0, $a0 \n\t"
-+ : "=r" (ret)
-+ : "r" (buf), "r" (n)
-+ : "memory", "$a0", "$a1", "$a2", "$a3", "$a4", "$a5", "$a6", "$a7",
-+ "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8"
-+ );
-+ return ret >= 0 ? (UInt)ret : -1;
-+}
++ static const HChar prefix[] = "loongarch64";
++ static const struct {
++ UInt hwcaps_bit;
++ HChar name[16];
++ } hwcaps_list[] = {
++ { VEX_HWCAPS_LOONGARCH_CPUCFG, "cpucfg" },
++ { VEX_HWCAPS_LOONGARCH_LAM, "lam" },
++ { VEX_HWCAPS_LOONGARCH_UAL, "ual" },
++ { VEX_HWCAPS_LOONGARCH_FP, "fpu" },
++ { VEX_HWCAPS_LOONGARCH_LSX, "lsx" },
++ { VEX_HWCAPS_LOONGARCH_LASX, "lasx" },
++ { VEX_HWCAPS_LOONGARCH_COMPLEX, "complex" },
++ { VEX_HWCAPS_LOONGARCH_CRYPTO, "crypto" },
++ { VEX_HWCAPS_LOONGARCH_LVZP, "lvz" },
++ { VEX_HWCAPS_LOONGARCH_X86BT, "lbt_x86" },
++ { VEX_HWCAPS_LOONGARCH_ARMBT, "lbt_arm" },
++ { VEX_HWCAPS_LOONGARCH_MIPSBT, "lbt_mips" }
++ };
++ static HChar buf[sizeof(prefix) +
++ NUM_HWCAPS * (sizeof hwcaps_list[0].name + 1) + 1]; // '\0'
+
-+static UInt local_sys_getpid ( void )
-+{
-+ ULong ret;
-+ __asm__ volatile (
-+ "li.w $a7, " VG_STRINGIFY(__NR_getpid) " \n\t"
-+ "syscall 0 \n\t"
-+ "move %0, $a0 \n\t"
-+ : "=r" (ret)
-+ :
-+ : "memory", "$a0", "$a1", "$a2", "$a3", "$a4", "$a5", "$a6", "$a7",
-+ "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8"
-+ );
-+ return (UInt)ret;
++ HChar *p = buf + vex_sprintf(buf, "%s", prefix);
++ UInt i;
++ for (i = 0 ; i < NUM_HWCAPS; ++i) {
++ if (hwcaps & hwcaps_list[i].hwcaps_bit)
++ p = p + vex_sprintf(p, "-%s", hwcaps_list[i].name);
++ }
++ return buf;
+}
+
- #elif defined(VGP_x86_solaris)
- static UInt local_sys_write_stderr ( const HChar* buf, Int n )
- {
-diff --git a/coregrind/m_dispatch/dispatch-loongarch64-linux.S b/coregrind/m_dispatch/dispatch-loongarch64-linux.S
+ #undef NUM_HWCAPS
+
+ /* Thie function must not return NULL. */
+@@ -1945,6 +2048,7 @@ static const HChar* show_hwcaps ( VexArch arch, UInt hwcaps )
+ case VexArchS390X: return show_hwcaps_s390x(hwcaps);
+ case VexArchMIPS32: return show_hwcaps_mips32(hwcaps);
+ case VexArchMIPS64: return show_hwcaps_mips64(hwcaps);
++ case VexArchLOONGARCH64: return show_hwcaps_loongarch64(hwcaps);
+ default: return NULL;
+ }
+ }
+@@ -2207,6 +2311,11 @@ static void check_hwcaps ( VexArch arch, UInt hwcaps )
+ return;
+ invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
+
++ case VexArchLOONGARCH64:
++ if (!(hwcaps & VEX_HWCAPS_LOONGARCH_ISA_64BIT))
++ invalid_hwcaps(arch, hwcaps, "Unsupported baseline\n");
++ return;
++
+ default:
+ vpanic("unknown architecture");
+ }
+diff --git a/VEX/pub/libvex.h b/VEX/pub/libvex.h
+index 1681077..b23b80d 100644
+--- a/VEX/pub/libvex.h
++++ b/VEX/pub/libvex.h
+@@ -60,6 +60,7 @@ typedef
+ VexArchMIPS32,
+ VexArchMIPS64,
+ VexArchNANOMIPS,
++ VexArchLOONGARCH64,
+ }
+ VexArch;
+
+@@ -306,6 +307,22 @@ typedef
+ (VEX_MIPS_PROC_ID(x) == VEX_PRID_IMP_P5600) && \
+ (VEX_MIPS_HOST_FP_MODE(x)))
+
++/* LoongArch baseline capability */
++#define VEX_HWCAPS_LOONGARCH_CPUCFG (1 << 0) /* CPU has CPUCFG */
++#define VEX_HWCAPS_LOONGARCH_LAM (1 << 1) /* CPU has Atomic instructions */
++#define VEX_HWCAPS_LOONGARCH_UAL (1 << 2) /* CPU has Unaligned Access support */
++#define VEX_HWCAPS_LOONGARCH_FP (1 << 3) /* CPU has FPU */
++#define VEX_HWCAPS_LOONGARCH_LSX (1 << 4) /* CPU has 128-bit SIMD instructions */
++#define VEX_HWCAPS_LOONGARCH_LASX (1 << 5) /* CPU has 256-bit SIMD instructions */
++#define VEX_HWCAPS_LOONGARCH_COMPLEX (1 << 6) /* CPU has Complex instructions */
++#define VEX_HWCAPS_LOONGARCH_CRYPTO (1 << 7) /* CPU has Crypto instructions */
++#define VEX_HWCAPS_LOONGARCH_LVZP (1 << 8) /* CPU has Virtualization extension */
++#define VEX_HWCAPS_LOONGARCH_X86BT (1 << 9) /* CPU has X86 Binary Translation */
++#define VEX_HWCAPS_LOONGARCH_ARMBT (1 << 10) /* CPU has ARM Binary Translation */
++#define VEX_HWCAPS_LOONGARCH_MIPSBT (1 << 11) /* CPU has MIPS Binary Translation */
++#define VEX_HWCAPS_LOONGARCH_ISA_32BIT (1 << 30) /* 32-bit ISA */
++#define VEX_HWCAPS_LOONGARCH_ISA_64BIT (1 << 31) /* 64-bit ISA */
++
+ /* These return statically allocated strings. */
+
+ extern const HChar* LibVEX_ppVexArch ( VexArch );
+@@ -427,6 +444,7 @@ void LibVEX_default_VexArchInfo ( /*OUT*/VexArchInfo* vai );
+ guest is mips32 ==> applicable, default True
+ guest is mips64 ==> applicable, default True
+ guest is arm64 ==> applicable, default False
++ guest is loongarch64 ==> const True
+
+ host_ppc_calls_use_fndescrs:
+ host is ppc32-linux ==> False
+@@ -1033,6 +1051,10 @@ extern void LibVEX_InitIRI ( const IRICB * );
+ ~~~~~
+ r21 is GSP.
+
++ loongarch64
++ ~~~~~
++ r31 is GSP.
++
+ ALL GUEST ARCHITECTURES
+ ~~~~~~~~~~~~~~~~~~~~~~~
+ The guest state must contain two pseudo-registers, guest_CMSTART
+diff --git a/VEX/pub/libvex_basictypes.h b/VEX/pub/libvex_basictypes.h
+index e3f1485..b4c81bf 100644
+--- a/VEX/pub/libvex_basictypes.h
++++ b/VEX/pub/libvex_basictypes.h
+@@ -198,6 +198,10 @@ typedef unsigned long HWord;
+ # define VEX_HOST_WORDSIZE 4
+ # define VEX_REGPARM(_n) /* */
+
++#elif defined(__loongarch__) && (__loongarch_grlen == 64)
++# define VEX_HOST_WORDSIZE 8
++# define VEX_REGPARM(_n) /* */
++
+ #else
+ # error "Vex: Fatal: Can't establish the host architecture"
+ #endif
+diff --git a/VEX/pub/libvex_guest_loongarch64.h b/VEX/pub/libvex_guest_loongarch64.h
new file mode 100644
-index 0000000..dec1652
+index 0000000..a1ef044
--- /dev/null
-+++ b/coregrind/m_dispatch/dispatch-loongarch64-linux.S
-@@ -0,0 +1,314 @@
++++ b/VEX/pub/libvex_guest_loongarch64.h
+@@ -0,0 +1,173 @@
+
-+/*--------------------------------------------------------------------*/
-+/*--- The core dispatch loop, for jumping to a code address. ---*/
-+/*--- dispatch-loongarch64-linux.S ---*/
-+/*--------------------------------------------------------------------*/
++/*---------------------------------------------------------------*/
++/*--- begin libvex_guest_loongarch64.h ---*/
++/*---------------------------------------------------------------*/
+
+/*
-+ This file is part of Valgrind, a dynamic binary instrumentation
-+ framework.
++ This file is part of Valgrind, a dynamic binary instrumentation
++ framework.
+
-+ Copyright (C) 2021-2022 Loongson Technology Corporation Limited
++ Copyright (C) 2021-2022 Loongson Technology Corporation Limited
+
-+ This program is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License as
-+ published by the Free Software Foundation; either version 2 of the
-+ License, or (at your option) any later version.
++ This program is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License as
++ published by the Free Software Foundation; either version 2 of the
++ License, or (at your option) any later version.
+
-+ This program is distributed in the hope that it will be useful, but
-+ WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ General Public License for more details.
++ This program is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, see .
+
-+ The GNU General Public License is contained in the file COPYING.
-+*/
-+
-+#include "pub_core_basics_asm.h"
-+
-+#if defined(VGP_loongarch64_linux)
-+
-+#include "pub_core_dispatch_asm.h"
-+#include "pub_core_transtab_asm.h"
-+#include "libvex_guest_offsets.h" /* for OFFSET_loongarch64_* */
-+
-+
-+/*------------------------------------------------------------*/
-+/*--- ---*/
-+/*--- The dispatch loop. VG_(disp_run_translations) is ---*/
-+/*--- used to run all translations, ---*/
-+/*--- including no-redir ones. ---*/
-+/*--- ---*/
-+/*------------------------------------------------------------*/
-+
-+/*----------------------------------------------------*/
-+/*--- Entry and preamble (set everything up) ---*/
-+/*----------------------------------------------------*/
++ The GNU General Public License is contained in the file COPYING.
+
-+/* signature:
-+void VG_(disp_run_translations)( UWord* two_words,
-+ void* guest_state,
-+ Addr host_addr );
++ Neither the names of the U.S. Department of Energy nor the
++ University of California nor the names of its contributors may be
++ used to endorse or promote products derived from this software
++ without prior written permission.
+*/
+
-+.text
-+.globl VG_(disp_run_translations)
-+VG_(disp_run_translations):
-+ /* a0 holds two_words */
-+ /* a1 holds guest_state */
-+ /* a2 holds host_addr */
-+
-+ /* New stack frame. Stack must remain 16 aligned (at least) */
-+ addi.d $sp, $sp, -96
-+
-+ /* Save ra */
-+ st.d $ra, $sp, 0
-+
-+ /* .. and s0 - s8 */
-+ st.d $s0, $sp, 8
-+ st.d $s1, $sp, 16
-+ st.d $s2, $sp, 24
-+ st.d $s3, $sp, 32
-+ st.d $s4, $sp, 40
-+ st.d $s5, $sp, 48
-+ st.d $s6, $sp, 56
-+ st.d $s7, $sp, 64
-+ st.d $s8, $sp, 72
-+
-+ /* ... and fp */
-+ st.d $fp, $sp, 80
-+
-+ /* and a0. In postamble it will be restored such that the
-+ return values can be written */
-+ st.d $a0, $sp, 88
-+
-+ /* Load address of guest state into s8 */
-+ move $s8, $a1
-+
-+ /* and jump into the code cache. Chained translations in
-+ the code cache run, until for whatever reason, they can't
-+ continue. When that happens, the translation in question
-+ will jump (or call) to one of the continuation points
-+ VG_(cp_...) below. */
-+ ibar 0 /* Insn sync barrier */
-+ jr $a2
-+ /*NOTREACHED*/
-+
-+/*----------------------------------------------------*/
-+/*--- Postamble and exit. ---*/
-+/*----------------------------------------------------*/
-+
-+postamble:
-+ /* At this point, a0 and a1 contain two
-+ words to be returned to the caller. a0
-+ holds a TRC value, and a1 optionally may
-+ hold another word (for CHAIN_ME exits, the
-+ address of the place to patch.) */
-+
-+ /* Restore a0 from stack to t0; holds address of two_words */
-+ ld.d $t0, $sp, 88
-+ st.d $a0, $t0, 0 /* Store a0 to two_words[0] */
-+ st.d $a1, $t0, 8 /* Store a1 to two_words[1] */
-+
-+ /* Restore ra */
-+ ld.d $ra, $sp, 0
-+
-+ /* ... and s0 - s8 */
-+ ld.d $s0, $sp, 8
-+ ld.d $s1, $sp, 16
-+ ld.d $s2, $sp, 24
-+ ld.d $s3, $sp, 32
-+ ld.d $s4, $sp, 40
-+ ld.d $s5, $sp, 48
-+ ld.d $s6, $sp, 56
-+ ld.d $s7, $sp, 64
-+ ld.d $s8, $sp, 72
-+
-+ /* ... and fp */
-+ ld.d $fp, $sp, 80
-+
-+ addi.d $sp, $sp, 96 /* Restore sp */
-+ jr $ra
-+ /*NOTREACHED*/
-+
-+/*----------------------------------------------------*/
-+/*--- Continuation points ---*/
-+/*----------------------------------------------------*/
-+
-+/* ------ Chain me to slow entry point ------ */
-+.globl VG_(disp_cp_chain_me_to_slowEP)
-+VG_(disp_cp_chain_me_to_slowEP):
-+ /* We got called. The return address indicates
-+ where the patching needs to happen. Collect
-+ the return address and, exit back to C land,
-+ handing the caller the pair (Chain_me_S, RA) */
-+ li.w $a0, VG_TRC_CHAIN_ME_TO_SLOW_EP
-+ move $a1, $ra
-+ /* 4 * 4 = mkLoadImm_EXACTLY4
-+ 4 = jirl $ra, $t0, 0 */
-+ addi.d $a1, $a1, -20
-+ b postamble
-+ /*NOTREACHED*/
-+
-+/* ------ Chain me to fast entry point ------ */
-+.globl VG_(disp_cp_chain_me_to_fastEP)
-+VG_(disp_cp_chain_me_to_fastEP):
-+ /* We got called. The return address indicates
-+ where the patching needs to happen. Collect
-+ the return address and, exit back to C land,
-+ handing the caller the pair (Chain_me_S, RA) */
-+ li.w $a0, VG_TRC_CHAIN_ME_TO_FAST_EP
-+ move $a1, $ra
-+ /* 4 * 4 = mkLoadImm_EXACTLY4
-+ 4 = jirl $ra, $t0, 0 */
-+ addi.d $a1, $a1, -20
-+ b postamble
-+ /*NOTREACHED*/
-+
-+/* ------ Indirect but boring jump ------ */
-+.globl VG_(disp_cp_xindir)
-+VG_(disp_cp_xindir):
-+ /* Where are we going? */
-+ ld.d $t0, $s8, OFFSET_loongarch64_PC
-+
-+ /* Stats only */
-+ la.local $t4, VG_(stats__n_xIndirs_32)
-+ ld.d $t1, $t4, 0
-+ addi.d $t1, $t1, 1
-+ st.w $t1, $t4, 0
-+
-+ /* LIVE: s8 (guest state ptr), t0 (guest address to go to).
-+ We use 6 temporaries:
-+ t6 (to point at the relevant FastCacheSet),
-+ t1, t2, t3 (scratch, for swapping entries within a set)
-+ t4, t5 (other scratch)
-+ */
-+
-+ /* Try a fast lookup in the translation cache. This is pretty much
-+ a handcoded version of VG_(lookupInFastCache). */
-+
-+ // Compute t6 = VG_TT_FAST_HASH(guest)
-+ srli.d $t6, $t0, 2 // g2 = guest >> 2
-+ srli.d $t5, $t0, (VG_TT_FAST_BITS + 2) // (g2 >> VG_TT_FAST_BITS)
-+ xor $t6, $t6, $t5 // (g2 >> VG_TT_FAST_BITS) ^ g2
-+ li.w $t5, VG_TT_FAST_MASK
-+ and $t6, $t6, $t5 // setNo
-+
-+ // Compute t6 = &VG_(tt_fast)[t6]
-+ la.local $t5, VG_(tt_fast)
-+ slli.d $t6, $t6, VG_FAST_CACHE_SET_BITS
-+ add.d $t6, $t6, $t5
++#ifndef __LIBVEX_PUB_GUEST_LOONGARCH64_H
++#define __LIBVEX_PUB_GUEST_LOONGARCH64_H
+
-+ /* LIVE: s8 (guest state ptr), t0 (guest addr), t6 (cache set) */
-+0: // try way 0
-+ ld.d $t4, $t6, FCS_g0 // .guest0
-+ ld.d $t5, $t6, FCS_h0 // .host0
-+ bne $t4, $t0, 1f // cmp against .guest0
-+ // hit at way 0
-+ // goto .host0
-+ jr $t5
-+ /*NOTREACHED*/
++#include "libvex_basictypes.h"
+
-+1: // try way 1
-+ ld.d $t4, $t6, FCS_g1
-+ bne $t4, $t0, 2f // cmp against .guest1
-+ // hit at way 1; swap upwards
-+ ld.d $t1, $t6, FCS_g0 // $t1 = old .guest0
-+ ld.d $t2, $t6, FCS_h0 // $t2 = old .host0
-+ ld.d $t3, $t6, FCS_h1 // $t3 = old .host1
-+ st.d $t0, $t6, FCS_g0 // new .guest0 = guest
-+ st.d $t3, $t6, FCS_h0 // new .host0 = old .host1
-+ st.d $t1, $t6, FCS_g1 // new .guest1 = old .guest0
-+ st.d $t2, $t6, FCS_h1 // new .host1 = old .host0
+
-+ // stats only
-+ la.local $t4, VG_(stats__n_xIndir_hits1_32)
-+ ld.d $t5, $t4, 0
-+ addi.d $t5, $t5, 1
-+ st.w $t5, $t4, 0
-+ // goto old .host1 a.k.a. new .host0
-+ jr $t3
-+ /*NOTREACHED*/
++/*---------------------------------------------------------------*/
++/*--- Vex's representation of the LOONGARCH64 CPU state. ---*/
++/*---------------------------------------------------------------*/
+
-+2: // try way 2
-+ ld.d $t4, $t6, FCS_g2
-+ bne $t4, $t0, 3f // cmp against .guest2
-+ // hit at way 2; swap upwards
-+ ld.d $t1, $t6, FCS_g1
-+ ld.d $t2, $t6, FCS_h1
-+ ld.d $t3, $t6, FCS_h2
-+ st.d $t0, $t6, FCS_g1
-+ st.d $t3, $t6, FCS_h1
-+ st.d $t1, $t6, FCS_g2
-+ st.d $t2, $t6, FCS_h2
++typedef
++ struct {
++ /* Event check fail addr and counter. */
++ /* 0 */ ULong host_EvC_FAILADDR;
++ /* 8 */ UInt host_EvC_COUNTER;
++ /* 12 */ UInt _padding0;
+
-+ // stats only
-+ la.local $t4, VG_(stats__n_xIndir_hits2_32)
-+ ld.d $t5, $t4, 0
-+ addi.d $t5, $t5, 1
-+ st.w $t5, $t4, 0
-+ // goto old .host2 a.k.a. new .host1
-+ jr $t3
-+ /*NOTREACHED*/
++ /* CPU Registers */
++ /* 16 */ ULong guest_R0; /* Constant zero */
++ /* 24 */ ULong guest_R1; /* Return address */
++ /* 32 */ ULong guest_R2; /* Thread pointer */
++ /* 40 */ ULong guest_R3; /* Stack pointer */
++ /* 48 */ ULong guest_R4; /* Argument registers / Return value */
++ /* 56 */ ULong guest_R5;
++ /* 64 */ ULong guest_R6; /* Argument registers */
++ /* 72 */ ULong guest_R7;
++ /* 80 */ ULong guest_R8;
++ /* 88 */ ULong guest_R9;
++ /* 96 */ ULong guest_R10;
++ /* 104 */ ULong guest_R11;
++ /* 112 */ ULong guest_R12; /* Temporary registers */
++ /* 120 */ ULong guest_R13;
++ /* 128 */ ULong guest_R14;
++ /* 136 */ ULong guest_R15;
++ /* 144 */ ULong guest_R16;
++ /* 152 */ ULong guest_R17;
++ /* 160 */ ULong guest_R18;
++ /* 168 */ ULong guest_R19;
++ /* 176 */ ULong guest_R20;
++ /* 184 */ ULong guest_R21; /* Reserved */
++ /* 192 */ ULong guest_R22; /* Frame pointer / Static register */
++ /* 200 */ ULong guest_R23; /* Static registers */
++ /* 208 */ ULong guest_R24;
++ /* 216 */ ULong guest_R25;
++ /* 224 */ ULong guest_R26;
++ /* 232 */ ULong guest_R27;
++ /* 240 */ ULong guest_R28;
++ /* 248 */ ULong guest_R29;
++ /* 256 */ ULong guest_R30;
++ /* 264 */ ULong guest_R31;
+
-+3: // try way 3
-+ ld.d $t4, $t6, FCS_g3
-+ bne $t4, $t0, 4f // cmp against .guest3
-+ // hit at way 3; swap upwards
-+ ld.d $t1, $t6, FCS_g2
-+ ld.d $t2, $t6, FCS_h2
-+ ld.d $t3, $t6, FCS_h3
-+ st.d $t0, $t6, FCS_g2
-+ st.d $t3, $t6, FCS_h2
-+ st.d $t1, $t6, FCS_g3
-+ st.d $t2, $t6, FCS_h3
++ /* 272 */ ULong guest_PC; /* Program counter */
+
-+ // stats only
-+ la.local $t4, VG_(stats__n_xIndir_hits3_32)
-+ ld.d $t5, $t4, 0
-+ addi.d $t5, $t5, 1
-+ st.w $t5, $t4, 0
-+ // goto old .host3 a.k.a. new .host2
-+ jr $t3
-+ /*NOTREACHED*/
++ /* 280 */ UChar guest_FCC0; /* Condition Flag Registers */
++ /* 281 */ UChar guest_FCC1;
++ /* 282 */ UChar guest_FCC2;
++ /* 283 */ UChar guest_FCC3;
++ /* 284 */ UChar guest_FCC4;
++ /* 285 */ UChar guest_FCC5;
++ /* 286 */ UChar guest_FCC6;
++ /* 287 */ UChar guest_FCC7;
++ /* 288 */ UInt guest_FCSR; /* FP/SIMD Control and Status Register */
+
-+4: // fast lookup failed:
-+ /* stats only */
-+ la.local $t4, VG_(stats__n_xIndir_misses_32)
-+ ld.d $t5, $t4, 0
-+ addi.d $t5, $t5, 1
-+ st.w $t5, $t4, 0
++ /* Various pseudo-regs mandated by Vex or Valgrind. */
++ /* Emulation notes */
++ /* 292 */ UInt guest_EMNOTE;
+
-+ li.w $a0, VG_TRC_INNER_FASTMISS
-+ move $a1, $zero
-+ b postamble
-+ /*NOTREACHED*/
++ /* For clflush: record start and length of area to invalidate */
++ /* 296 */ ULong guest_CMSTART;
++ /* 304 */ ULong guest_CMLEN;
+
-+/* ------ Assisted jump ------ */
-+.globl VG_(disp_cp_xassisted)
-+VG_(disp_cp_xassisted):
-+ /* guest-state-pointer contains the TRC. Put the value into the
-+ return register */
-+ move $a0, $s8
-+ move $a1, $zero
-+ b postamble
++ /* Used to record the unredirected guest address at the start of
++ a translation whose start has been redirected. By reading
++ this pseudo-register shortly afterwards, the translation can
++ find out what the corresponding no-redirection address was.
++ Note, this is only set for wrap-style redirects, not for
++ replace-style ones. */
++ /* 312 */ ULong guest_NRADDR;
+
-+/* ------ Event check failed ------ */
-+.globl VG_(disp_cp_evcheck_fail)
-+VG_(disp_cp_evcheck_fail):
-+ li.w $a0, VG_TRC_INNER_COUNTERZERO
-+ move $a1, $zero
-+ b postamble
++ /* Needed for Darwin (but mandated for all guest architectures) */
++ /* 320 */ ULong guest_IP_AT_SYSCALL;
+
-+.size VG_(disp_run_translations), .-VG_(disp_run_translations)
++ /* Fallback LL/SC support. */
++ /* 328 */ ULong guest_LLSC_SIZE; /* 0==no transaction, else 4 or 8. */
++ /* 336 */ ULong guest_LLSC_ADDR; /* Address of the transaction. */
++ /* 344 */ ULong guest_LLSC_DATA; /* Original value at ADDR. */
+
-+#endif // defined(VGP_loongarch64_linux)
++ /* FPU/SIMD Registers */
++ /* 352 */ U256 guest_X0;
++ /* 384 */ U256 guest_X1;
++ /* 416 */ U256 guest_X2;
++ /* 448 */ U256 guest_X3;
++ /* 480 */ U256 guest_X4;
++ /* 512 */ U256 guest_X5;
++ /* 544 */ U256 guest_X6;
++ /* 576 */ U256 guest_X7;
++ /* 608 */ U256 guest_X8;
++ /* 640 */ U256 guest_X9;
++ /* 672 */ U256 guest_X10;
++ /* 704 */ U256 guest_X11;
++ /* 736 */ U256 guest_X12;
++ /* 768 */ U256 guest_X13;
++ /* 800 */ U256 guest_X14;
++ /* 832 */ U256 guest_X15;
++ /* 864 */ U256 guest_X16;
++ /* 896 */ U256 guest_X17;
++ /* 928 */ U256 guest_X18;
++ /* 960 */ U256 guest_X19;
++ /* 992 */ U256 guest_X20;
++ /* 1024 */ U256 guest_X21;
++ /* 1056 */ U256 guest_X22;
++ /* 1088 */ U256 guest_X23;
++ /* 1120 */ U256 guest_X24;
++ /* 1152 */ U256 guest_X25;
++ /* 1184 */ U256 guest_X26;
++ /* 1216 */ U256 guest_X27;
++ /* 1248 */ U256 guest_X28;
++ /* 1280 */ U256 guest_X29;
++ /* 1312 */ U256 guest_X30;
++ /* 1244 */ U256 guest_X31;
+
-+/* Let the linker know we don't need an executable stack */
-+MARK_STACK_NO_EXEC
++ /* 1376 */ /* VexGuestLOONGARCH64State should have a 16-aligned size */
++} VexGuestLOONGARCH64State;
+
-+/*--------------------------------------------------------------------*/
-+/*--- end dispatch-loongarch64-linux.S ---*/
-+/*--------------------------------------------------------------------*/
-diff --git a/coregrind/m_gdbserver/loongarch-base64-valgrind-s1.xml b/coregrind/m_gdbserver/loongarch-base64-valgrind-s1.xml
-new file mode 100644
-index 0000000..cab700c
---- /dev/null
-+++ b/coregrind/m_gdbserver/loongarch-base64-valgrind-s1.xml
-@@ -0,0 +1,45 @@
-+
-+
++/* ALL THE FOLLOWING ARE VISIBLE TO LIBRARY CLIENT. */
+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-diff --git a/coregrind/m_gdbserver/loongarch-base64-valgrind-s2.xml b/coregrind/m_gdbserver/loongarch-base64-valgrind-s2.xml
-new file mode 100644
-index 0000000..cbacbbb
---- /dev/null
-+++ b/coregrind/m_gdbserver/loongarch-base64-valgrind-s2.xml
-@@ -0,0 +1,45 @@
-+
-+
++extern
++void LibVEX_GuestLOONGARCH64_initialise ( /*OUT*/
++ VexGuestLOONGARCH64State* vex_state );
+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-diff --git a/coregrind/m_gdbserver/loongarch-base64.xml b/coregrind/m_gdbserver/loongarch-base64.xml
-new file mode 100644
-index 0000000..fadca8b
---- /dev/null
-+++ b/coregrind/m_gdbserver/loongarch-base64.xml
-@@ -0,0 +1,45 @@
-+
-+
++/*---------------------------------------------------------------*/
++/*--- libvex_guest_loongarch64.h ---*/
++/*---------------------------------------------------------------*/
+diff --git a/VEX/pub/libvex_ir.h b/VEX/pub/libvex_ir.h
+index f6f347a..45475df 100644
+--- a/VEX/pub/libvex_ir.h
++++ b/VEX/pub/libvex_ir.h
+@@ -588,10 +588,10 @@ typedef
+
+ /* Binary operations, with rounding. */
+ /* :: IRRoundingMode(I32) x F64 x F64 -> F64 */
+- Iop_AddF64, Iop_SubF64, Iop_MulF64, Iop_DivF64,
++ Iop_AddF64, Iop_SubF64, Iop_MulF64, Iop_DivF64, Iop_ScaleBF64,
+
+ /* :: IRRoundingMode(I32) x F32 x F32 -> F32 */
+- Iop_AddF32, Iop_SubF32, Iop_MulF32, Iop_DivF32,
++ Iop_AddF32, Iop_SubF32, Iop_MulF32, Iop_DivF32, Iop_ScaleBF32,
+
+ /* Variants of the above which produce a 64-bit result but which
+ round their result to a IEEE float range first. */
+@@ -610,10 +610,10 @@ typedef
+
+ /* Unary operations, with rounding. */
+ /* :: IRRoundingMode(I32) x F64 -> F64 */
+- Iop_SqrtF64,
++ Iop_SqrtF64, Iop_RSqrtF64, Iop_LogBF64,
+
+ /* :: IRRoundingMode(I32) x F32 -> F32 */
+- Iop_SqrtF32,
++ Iop_SqrtF32, Iop_RSqrtF32, Iop_LogBF32,
+
+ /* :: IRRoundingMode(I32) x F16 -> F16 */
+ Iop_SqrtF16,
+@@ -834,10 +834,14 @@ typedef
+
+ /* --------- Possibly required by IEEE 754-2008. --------- */
+
+- Iop_MaxNumF64, /* max, F64, numerical operand if other is a qNaN */
+- Iop_MinNumF64, /* min, F64, ditto */
+- Iop_MaxNumF32, /* max, F32, ditto */
+- Iop_MinNumF32, /* min, F32, ditto */
++ Iop_MaxNumF64, /* max, F64, numerical operand if other is a qNaN */
++ Iop_MinNumF64, /* min, F64, ditto */
++ Iop_MaxNumAbsF64, /* max abs, F64, ditto */
++ Iop_MinNumAbsF64, /* min abs, F64, ditto */
++ Iop_MaxNumF32, /* max, F32, ditto */
++ Iop_MinNumF32, /* min, F32, ditto */
++ Iop_MaxNumAbsF32, /* max abs, F32, ditto */
++ Iop_MinNumAbsF32, /* min abs, F32, ditto */
+
+ /* ------------------ 16-bit scalar FP ------------------ */
+
+@@ -1533,6 +1537,10 @@ typedef
+ IRRoundingMode(I32) x (F64x2 | F64x2) -> Q32x4 */
+ Iop_F64x2_2toQ32x4,
+
++ /* --- Int to/from FP conversion --- */
++ Iop_RoundF64x2_RM, Iop_RoundF64x2_RP, /* round to fp integer */
++ Iop_RoundF64x2_RN, Iop_RoundF64x2_RZ, /* round to fp integer */
+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-diff --git a/coregrind/m_gdbserver/loongarch-fpu64-valgrind-s1.xml b/coregrind/m_gdbserver/loongarch-fpu64-valgrind-s1.xml
-new file mode 100644
-index 0000000..b5c7cab
---- /dev/null
-+++ b/coregrind/m_gdbserver/loongarch-fpu64-valgrind-s1.xml
-@@ -0,0 +1,57 @@
-+
-+
++ Iop_Max8Sx32, Iop_Max16Sx16, Iop_Max32Sx8, Iop_Max64Sx4,
++ Iop_Max8Ux32, Iop_Max16Ux16, Iop_Max32Ux8, Iop_Max64Ux4,
++ Iop_Min8Sx32, Iop_Min16Sx16, Iop_Min32Sx8, Iop_Min64Sx4,
++ Iop_Min8Ux32, Iop_Min16Ux16, Iop_Min32Ux8, Iop_Min64Ux4,
+
+- Iop_Mul16x16, Iop_Mul32x8,
+- Iop_MulHi16Ux16, Iop_MulHi16Sx16,
++ /* ABSOLUTE VALUE */
++ Iop_Abs8x32, Iop_Abs16x16, Iop_Abs32x8, Iop_Abs64x4,
+
+- Iop_QAdd8Ux32, Iop_QAdd16Ux16,
+- Iop_QAdd8Sx32, Iop_QAdd16Sx16,
+- Iop_QSub8Ux32, Iop_QSub16Ux16,
+- Iop_QSub8Sx32, Iop_QSub16Sx16,
++ Iop_Mul8x32, Iop_Mul16x16, Iop_Mul32x8,
++ Iop_MulHi8Ux32, Iop_MulHi16Ux16, Iop_MulHi32Ux8,
++ Iop_MulHi8Sx32, Iop_MulHi16Sx16, Iop_MulHi32Sx8,
+
+- Iop_Avg8Ux32, Iop_Avg16Ux16,
++ Iop_QAdd8Ux32, Iop_QAdd16Ux16, Iop_QAdd32Ux8, Iop_QAdd64Ux4,
++ Iop_QAdd8Sx32, Iop_QAdd16Sx16, Iop_QAdd32Sx8, Iop_QAdd64Sx4,
++ Iop_QSub8Ux32, Iop_QSub16Ux16, Iop_QSub32Ux8, Iop_QSub64Ux4,
++ Iop_QSub8Sx32, Iop_QSub16Sx16, Iop_QSub32Sx8, Iop_QSub64Sx4,
++
++ /* AVERAGING: note: (arg1 + arg2 + 1) >>u 1 */
++ Iop_Avg8Ux32, Iop_Avg16Ux16, Iop_Avg32Ux8, Iop_Avg64Ux4,
++ Iop_Avg8Sx32, Iop_Avg16Sx16, Iop_Avg32Sx8, Iop_Avg64Sx4,
+
+ Iop_Perm32x8,
+
+@@ -2039,6 +2070,28 @@ typedef
+ * vshasigmad and vshasigmaw insns.*/
+ Iop_SHA512, Iop_SHA256,
+
++ Iop_WidenHIto16Sx16, Iop_WidenHIto32Sx8, Iop_WidenHIto64Sx4, Iop_WidenHIto128Sx2,
++ Iop_WidenHIto16Ux16, Iop_WidenHIto32Ux8, Iop_WidenHIto64Ux4, Iop_WidenHIto128Ux2,
++
++ /* INTERLEAVING */
++ /* Interleave lanes from low or high halves of
++ operands. Most-significant result lane is from the left
++ arg. */
++ Iop_InterleaveHI8x32, Iop_InterleaveHI16x16,
++ Iop_InterleaveHI32x8, Iop_InterleaveHI64x4,
++ Iop_InterleaveLO8x32, Iop_InterleaveLO16x16,
++ Iop_InterleaveLO32x8, Iop_InterleaveLO64x4,
++ /* Interleave odd/even lanes of operands. Most-significant result lane
++ is from the left arg. */
++ Iop_InterleaveOddLanes8x32, Iop_InterleaveEvenLanes8x32,
++ Iop_InterleaveOddLanes16x16, Iop_InterleaveEvenLanes16x16,
++ Iop_InterleaveOddLanes32x8, Iop_InterleaveEvenLanes32x8,
++
++ /* Pack even/odd lanes. */
++ Iop_PackOddLanes8x32, Iop_PackEvenLanes8x32,
++ Iop_PackOddLanes16x16, Iop_PackEvenLanes16x16,
++ Iop_PackOddLanes32x8, Iop_PackEvenLanes32x8,
++
+ /* ------------------ 256-bit SIMD FP. ------------------ */
+
+ /* ternary :: IRRoundingMode(I32) x V256 x V256 -> V256 */
+@@ -2513,6 +2566,7 @@ typedef
+ Ijk_SigFPE, /* current instruction synths generic SIGFPE */
+ Ijk_SigFPE_IntDiv, /* current instruction synths SIGFPE - IntDiv */
+ Ijk_SigFPE_IntOvf, /* current instruction synths SIGFPE - IntOvf */
++ Ijk_SigSYS, /* current instruction synths SIGSYS */
+ /* Unfortunately, various guest-dependent syscall kinds. They
+ all mean: do a syscall before continuing. */
+ Ijk_Sys_syscall, /* amd64/x86 'syscall', ppc 'sc', arm 'svc #0' */
+@@ -2673,7 +2727,12 @@ typedef
+ /* Needed only on ARM. It cancels a reservation made by a
+ preceding Linked-Load, and needs to be handed through to the
+ back end, just as LL and SC themselves are. */
+- Imbe_CancelReservation
++ Imbe_CancelReservation,
++ /* Needed only on LOONGARCH64. It completes the synchronization
++ between the store operation and the instruction fetch operation
++ within a single processor core, and needs to be handed through
++ to the back end. */
++ Imbe_InsnFence
+ }
+ IRMBusEvent;
+
+diff --git a/VEX/pub/libvex_trc_values.h b/VEX/pub/libvex_trc_values.h
+index c9adcb7..987d5cc 100644
+--- a/VEX/pub/libvex_trc_values.h
++++ b/VEX/pub/libvex_trc_values.h
+@@ -57,6 +57,7 @@
+ continuing */
+ #define VEX_TRC_JMP_SIGBUS 93 /* deliver SIGBUS before continuing */
+ #define VEX_TRC_JMP_SIGFPE 105 /* deliver SIGFPE before continuing */
++#define VEX_TRC_JMP_SIGSYS 115 /* deliver SIGSYS before continuing */
+
+ #define VEX_TRC_JMP_SIGFPE_INTDIV 97 /* deliver SIGFPE (integer divide
+ by zero) before continuing */
+diff --git a/cachegrind/cg_arch.c b/cachegrind/cg_arch.c
+index 68314c9..55f7585 100644
+--- a/cachegrind/cg_arch.c
++++ b/cachegrind/cg_arch.c
+@@ -484,6 +484,13 @@ configure_caches(cache_t *I1c, cache_t *D1c, cache_t *LLc,
+ *D1c = (cache_t) { 65536, 2, 64 };
+ *LLc = (cache_t) { 262144, 8, 64 };
+
++#elif defined(VGA_loongarch64)
+
-+
-+
++ // Set caches to default (for LOONGARCH64 - 3A5000)
++ *I1c = (cache_t) { 65536, 4, 64 };
++ *D1c = (cache_t) { 65536, 4, 64 };
++ *LLc = (cache_t) { 262144, 16, 64 };
+
-+
-+
-+
-+
+ #else
+
+ #error "Unknown arch"
+diff --git a/cachegrind/cg_branchpred.c b/cachegrind/cg_branchpred.c
+index 927b7bf..6a97209 100644
+--- a/cachegrind/cg_branchpred.c
++++ b/cachegrind/cg_branchpred.c
+@@ -44,7 +44,7 @@
+ guaranteed to be zero? */
+ #if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
+ || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips) \
+- || defined(VGA_arm64)
++ || defined(VGA_arm64) || defined(VGA_loongarch64)
+ # define N_IADDR_LO_ZERO_BITS 2
+ #elif defined(VGA_x86) || defined(VGA_amd64)
+ # define N_IADDR_LO_ZERO_BITS 0
+diff --git a/configure.ac b/configure.ac
+index 095659a..9322d64 100755
+--- a/configure.ac
++++ b/configure.ac
+@@ -325,6 +325,11 @@ case "${host_cpu}" in
+ ARCH_MAX="nanomips"
+ ;;
+
++ loongarch64*)
++ AC_MSG_RESULT([ok (${host_cpu})])
++ ARCH_MAX="loongarch64"
++ ;;
++
+ *)
+ AC_MSG_RESULT([no (${host_cpu})])
+ AC_MSG_ERROR([Unsupported host architecture. Sorry])
+@@ -897,6 +902,17 @@ case "$ARCH_MAX-$VGCONF_OS" in
+ valt_load_address_sec_inner="0xUNSET"
+ AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})])
+ ;;
++ loongarch64-linux)
++ VGCONF_ARCH_PRI="loongarch64"
++ VGCONF_ARCH_SEC=""
++ VGCONF_PLATFORM_PRI_CAPS="LOONGARCH64_LINUX"
++ VGCONF_PLATFORM_SEC_CAPS=""
++ valt_load_address_pri_norml="0x58000000"
++ valt_load_address_pri_inner="0x38000000"
++ valt_load_address_sec_norml="0xUNSET"
++ valt_load_address_sec_inner="0xUNSET"
++ AC_MSG_RESULT([ok (${ARCH_MAX}-${VGCONF_OS})])
++ ;;
+ x86-solaris)
+ VGCONF_ARCH_PRI="x86"
+ VGCONF_ARCH_SEC=""
+@@ -990,6 +1006,8 @@ AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_MIPS64,
+ test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX )
+ AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_NANOMIPS,
+ test x$VGCONF_PLATFORM_PRI_CAPS = xNANOMIPS_LINUX )
++AM_CONDITIONAL(VGCONF_ARCHS_INCLUDE_LOONGARCH64,
++ test x$VGCONF_PLATFORM_PRI_CAPS = xLOONGARCH64_LINUX )
+
+ # Set up VGCONF_PLATFORMS_INCLUDE_. Either one or two of these
+ # become defined.
+@@ -1020,6 +1038,8 @@ AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_MIPS64_LINUX,
+ test x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX)
+ AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_NANOMIPS_LINUX,
+ test x$VGCONF_PLATFORM_PRI_CAPS = xNANOMIPS_LINUX)
++AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_LOONGARCH64_LINUX,
++ test x$VGCONF_PLATFORM_PRI_CAPS = xLOONGARCH64_LINUX)
+ AM_CONDITIONAL(VGCONF_PLATFORMS_INCLUDE_X86_FREEBSD,
+ test x$VGCONF_PLATFORM_PRI_CAPS = xX86_FREEBSD \
+ -o x$VGCONF_PLATFORM_SEC_CAPS = xX86_FREEBSD)
+@@ -1053,7 +1073,8 @@ AM_CONDITIONAL(VGCONF_OS_IS_LINUX,
+ -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \
+ -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS32_LINUX \
+ -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX \
+- -o x$VGCONF_PLATFORM_PRI_CAPS = xNANOMIPS_LINUX)
++ -o x$VGCONF_PLATFORM_PRI_CAPS = xNANOMIPS_LINUX \
++ -o x$VGCONF_PLATFORM_PRI_CAPS = xLOONGARCH64_LINUX)
+ AM_CONDITIONAL(VGCONF_OS_IS_FREEBSD,
+ test x$VGCONF_PLATFORM_PRI_CAPS = xX86_FREEBSD \
+ -o x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_FREEBSD \
+@@ -5043,7 +5064,8 @@ elif test x$VGCONF_PLATFORM_PRI_CAPS = xAMD64_LINUX \
+ -o x$VGCONF_PLATFORM_PRI_CAPS = xARM64_LINUX \
+ -o x$VGCONF_PLATFORM_PRI_CAPS = xARM64_FREEBSD \
+ -o x$VGCONF_PLATFORM_PRI_CAPS = xMIPS64_LINUX \
+- -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX ; then
++ -o x$VGCONF_PLATFORM_PRI_CAPS = xS390X_LINUX \
++ -o x$VGCONF_PLATFORM_PRI_CAPS = xLOONGARCH64_LINUX; then
+ mflag_primary=$FLAG_M64
+ elif test x$VGCONF_PLATFORM_PRI_CAPS = xX86_DARWIN ; then
+ mflag_primary="$FLAG_M32 -arch i386"
+@@ -5651,6 +5673,7 @@ AC_CONFIG_FILES([
+ memcheck/tests/amd64-linux/Makefile
+ memcheck/tests/arm64-linux/Makefile
+ memcheck/tests/x86-linux/Makefile
++ memcheck/tests/loongarch64-linux/Makefile
+ memcheck/tests/amd64-solaris/Makefile
+ memcheck/tests/x86-solaris/Makefile
+ memcheck/tests/amd64-freebsd/Makefile
+@@ -5696,6 +5719,7 @@ AC_CONFIG_FILES([
+ none/tests/mips32/Makefile
+ none/tests/mips64/Makefile
+ none/tests/nanomips/Makefile
++ none/tests/loongarch64/Makefile
+ none/tests/linux/Makefile
+ none/tests/darwin/Makefile
+ none/tests/solaris/Makefile
+diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
+index e3e31a7..40206f6 100644
+--- a/coregrind/Makefile.am
++++ b/coregrind/Makefile.am
+@@ -390,6 +390,7 @@ COREGRIND_SOURCES_COMMON = \
+ m_dispatch/dispatch-mips32-linux.S \
+ m_dispatch/dispatch-mips64-linux.S \
+ m_dispatch/dispatch-nanomips-linux.S \
++ m_dispatch/dispatch-loongarch64-linux.S \
+ m_dispatch/dispatch-x86-freebsd.S \
+ m_dispatch/dispatch-amd64-freebsd.S \
+ m_dispatch/dispatch-arm64-freebsd.S \
+@@ -417,6 +418,7 @@ COREGRIND_SOURCES_COMMON = \
+ m_gdbserver/valgrind-low-mips32.c \
+ m_gdbserver/valgrind-low-mips64.c \
+ m_gdbserver/valgrind-low-nanomips.c \
++ m_gdbserver/valgrind-low-loongarch64.c \
+ m_gdbserver/version.c \
+ m_initimg/initimg-linux.c \
+ m_initimg/initimg-freebsd.c \
+@@ -445,6 +447,7 @@ COREGRIND_SOURCES_COMMON = \
+ m_sigframe/sigframe-mips32-linux.c \
+ m_sigframe/sigframe-mips64-linux.c \
+ m_sigframe/sigframe-nanomips-linux.c \
++ m_sigframe/sigframe-loongarch64-linux.c \
+ m_sigframe/sigframe-x86-darwin.c \
+ m_sigframe/sigframe-amd64-darwin.c \
+ m_sigframe/sigframe-solaris.c \
+@@ -459,6 +462,7 @@ COREGRIND_SOURCES_COMMON = \
+ m_syswrap/syscall-mips32-linux.S \
+ m_syswrap/syscall-mips64-linux.S \
+ m_syswrap/syscall-nanomips-linux.S \
++ m_syswrap/syscall-loongarch64-linux.S \
+ m_syswrap/syscall-x86-freebsd.S \
+ m_syswrap/syscall-amd64-freebsd.S \
+ m_syswrap/syscall-arm64-freebsd.S \
+@@ -486,6 +490,7 @@ COREGRIND_SOURCES_COMMON = \
+ m_syswrap/syswrap-mips32-linux.c \
+ m_syswrap/syswrap-mips64-linux.c \
+ m_syswrap/syswrap-nanomips-linux.c \
++ m_syswrap/syswrap-loongarch64-linux.c \
+ m_syswrap/syswrap-x86-darwin.c \
+ m_syswrap/syswrap-amd64-darwin.c \
+ m_syswrap/syswrap-xen.c \
+@@ -778,7 +783,15 @@ GDBSERVER_XML_FILES = \
+ m_gdbserver/mips64-linux-valgrind.xml \
+ m_gdbserver/mips64-fpu-valgrind-s1.xml \
+ m_gdbserver/mips64-fpu-valgrind-s2.xml \
+- m_gdbserver/mips64-fpu.xml
++ m_gdbserver/mips64-fpu.xml \
++ m_gdbserver/loongarch-base64.xml \
++ m_gdbserver/loongarch-fpu64.xml \
++ m_gdbserver/loongarch64-linux.xml \
++ m_gdbserver/loongarch-base64-valgrind-s1.xml \
++ m_gdbserver/loongarch-base64-valgrind-s2.xml \
++ m_gdbserver/loongarch-fpu64-valgrind-s1.xml \
++ m_gdbserver/loongarch-fpu64-valgrind-s2.xml \
++ m_gdbserver/loongarch64-linux-valgrind.xml
+
+ # so as to make sure these get copied into the install tree
+ vglibdir = $(pkglibexecdir)
+diff --git a/coregrind/launcher-linux.c b/coregrind/launcher-linux.c
+index 715fdab..d392cf5 100644
+--- a/coregrind/launcher-linux.c
++++ b/coregrind/launcher-linux.c
+@@ -67,6 +67,10 @@
+ #define EM_NANOMIPS 249
+ #endif
+
++#ifndef EM_LOONGARCH
++#define EM_LOONGARCH 258
++#endif
++
+ #ifndef E_MIPS_ABI_O32
+ #define E_MIPS_ABI_O32 0x00001000
+ #endif
+@@ -316,6 +320,10 @@ static const char *select_platform(const char *clientname)
+ (header.ehdr64.e_ident[EI_OSABI] == ELFOSABI_SYSV ||
+ header.ehdr64.e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
+ platform = "ppc64le-linux";
++ } else if (header.ehdr64.e_machine == EM_LOONGARCH &&
++ (header.ehdr64.e_ident[EI_OSABI] == ELFOSABI_SYSV ||
++ header.ehdr64.e_ident[EI_OSABI] == ELFOSABI_LINUX)) {
++ platform = "loongarch64-linux";
+ }
+ } else if (header.c[EI_DATA] == ELFDATA2MSB) {
+ # if !defined(VGPV_arm_linux_android) \
+@@ -417,7 +425,8 @@ int main(int argc, char** argv, char** envp)
+ (0==strcmp(VG_PLATFORM,"s390x-linux")) ||
+ (0==strcmp(VG_PLATFORM,"mips32-linux")) ||
+ (0==strcmp(VG_PLATFORM,"mips64-linux")) ||
+- (0==strcmp(VG_PLATFORM,"nanomips-linux")))
++ (0==strcmp(VG_PLATFORM,"nanomips-linux")) ||
++ (0==strcmp(VG_PLATFORM,"loongarch64-linux")))
+ default_platform = VG_PLATFORM;
+ # elif defined(VGO_solaris)
+ if ((0==strcmp(VG_PLATFORM,"x86-solaris")) ||
+diff --git a/coregrind/m_aspacemgr/aspacemgr-common.c b/coregrind/m_aspacemgr/aspacemgr-common.c
+index 68bc5b4..7c57ce3 100644
+--- a/coregrind/m_aspacemgr/aspacemgr-common.c
++++ b/coregrind/m_aspacemgr/aspacemgr-common.c
+@@ -157,7 +157,8 @@ SysRes VG_(am_do_mmap_NO_NOTIFY)( Addr start, SizeT length, UInt prot,
+ # elif defined(VGP_amd64_linux) \
+ || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
+ || defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \
+- || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
++ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
++ || defined(VGP_loongarch64_linux)
+ res = VG_(do_syscall6)(__NR_mmap, (UWord)start, length,
+ prot, flags, fd, offset);
+ # elif defined(VGP_x86_darwin)
+@@ -262,7 +263,8 @@ SysRes ML_(am_do_relocate_nooverlap_mapping_NO_NOTIFY)(
+
+ SysRes ML_(am_open) ( const HChar* pathname, Int flags, Int mode )
+ {
+-# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ /* ARM64 wants to use __NR_openat rather than __NR_open. */
+ SysRes res = VG_(do_syscall4)(__NR_openat,
+ VKI_AT_FDCWD, (UWord)pathname, flags, mode);
+@@ -291,7 +293,8 @@ void ML_(am_close) ( Int fd )
+ Int ML_(am_readlink)(const HChar* path, HChar* buf, UInt bufsiz)
+ {
+ SysRes res;
+-# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
+ (UWord)path, (UWord)buf, bufsiz);
+ # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
+diff --git a/coregrind/m_aspacemgr/aspacemgr-linux.c b/coregrind/m_aspacemgr/aspacemgr-linux.c
+index bae4f78..0082dac 100644
+--- a/coregrind/m_aspacemgr/aspacemgr-linux.c
++++ b/coregrind/m_aspacemgr/aspacemgr-linux.c
+@@ -2799,7 +2799,8 @@ static SysRes VG_(am_mmap_file_float_valgrind_flags) ( SizeT length, UInt prot,
+ req.rkind = MAny;
+ req.start = 0;
+ #if defined(VGA_arm) || defined(VGA_arm64) \
+- || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips)
++ || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips) \
++ || defined(VGA_loongarch64)
+ aspacem_assert(VKI_SHMLBA >= VKI_PAGE_SIZE);
+ #else
+ aspacem_assert(VKI_SHMLBA == VKI_PAGE_SIZE);
+diff --git a/coregrind/m_cache.c b/coregrind/m_cache.c
+index 565aa41..fcb9d8b 100644
+--- a/coregrind/m_cache.c
++++ b/coregrind/m_cache.c
+@@ -668,6 +668,239 @@ get_cache_info(VexArchInfo *vai)
+ return True;
+ }
+
++#elif defined(VGA_loongarch64)
+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-diff --git a/coregrind/m_gdbserver/loongarch-fpu64-valgrind-s2.xml b/coregrind/m_gdbserver/loongarch-fpu64-valgrind-s2.xml
-new file mode 100644
-index 0000000..501660e
---- /dev/null
-+++ b/coregrind/m_gdbserver/loongarch-fpu64-valgrind-s2.xml
-@@ -0,0 +1,57 @@
-+
-+
++#define BIT(x) (1UL << (x))
++#define GENMASK(h, l) (((~0UL) - (1UL << (l)) + 1) & (~0UL >> (64 - 1 - (h))))
+
-+
-+
++#define LOONGARCH_CPUCFG16 0x10
++#define CPUCFG16_L1_IUPRE BIT(0)
++#define CPUCFG16_L1_IUUNIFY BIT(1)
++#define CPUCFG16_L1_DPRE BIT(2)
++#define CPUCFG16_L2_IUPRE BIT(3)
++#define CPUCFG16_L2_IUUNIFY BIT(4)
++#define CPUCFG16_L2_DPRE BIT(7)
++#define CPUCFG16_L3_IUPRE BIT(10)
++#define CPUCFG16_L3_IUUNIFY BIT(11)
++#define CPUCFG16_L3_DPRE BIT(14)
+
-+
-+
-+
-+
++#define LOONGARCH_CPUCFG17 0x11
++#define CPUCFG17_L1I_WAYS_M GENMASK(15, 0)
++#define CPUCFG17_L1I_SETS_M GENMASK(23, 16)
++#define CPUCFG17_L1I_SIZE_M GENMASK(30, 24)
++#define CPUCFG17_L1I_WAYS 0
++#define CPUCFG17_L1I_SETS 16
++#define CPUCFG17_L1I_SIZE 24
+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-diff --git a/coregrind/m_gdbserver/loongarch-fpu64.xml b/coregrind/m_gdbserver/loongarch-fpu64.xml
-new file mode 100644
-index 0000000..74ab55a
---- /dev/null
-+++ b/coregrind/m_gdbserver/loongarch-fpu64.xml
-@@ -0,0 +1,57 @@
-+
-+
++#define LOONGARCH_CPUCFG19 0x13
++#define CPUCFG19_L2_WAYS_M GENMASK(15, 0)
++#define CPUCFG19_L2_SETS_M GENMASK(23, 16)
++#define CPUCFG19_L2_SIZE_M GENMASK(30, 24)
++#define CPUCFG19_L2_WAYS 0
++#define CPUCFG19_L2_SETS 16
++#define CPUCFG19_L2_SIZE 24
+
-+
-+
++#define LOONGARCH_CPUCFG20 0x14
++#define CPUCFG20_L3_WAYS_M GENMASK(15, 0)
++#define CPUCFG20_L3_SETS_M GENMASK(23, 16)
++#define CPUCFG20_L3_SIZE_M GENMASK(30, 24)
++#define CPUCFG20_L3_WAYS 0
++#define CPUCFG20_L3_SETS 16
++#define CPUCFG20_L3_SIZE 24
+
-+
-+
-+
-+
++struct cache_status {
++ Bool has_iu;
++ Bool is_u;
++ Bool has_d;
++ Bool exist;
++ UInt num;
++};
+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-+
-diff --git a/coregrind/m_gdbserver/loongarch64-linux-valgrind.xml b/coregrind/m_gdbserver/loongarch64-linux-valgrind.xml
-new file mode 100644
-index 0000000..8915a72
---- /dev/null
-+++ b/coregrind/m_gdbserver/loongarch64-linux-valgrind.xml
-@@ -0,0 +1,18 @@
-+
-+
++static void
++get_status(struct cache_status status[], UInt n)
++{
++ Bool has_iu = status[n].has_iu;
++ Bool is_u = status[n].is_u;
++ Bool has_d = status[n].has_d;
+
-+
-+
-+ loongarch
-+ GNU/Linux
-+
-+
-+
-+
-+
-+
-+
-diff --git a/coregrind/m_gdbserver/loongarch64-linux.xml b/coregrind/m_gdbserver/loongarch64-linux.xml
-new file mode 100644
-index 0000000..f1eed83
---- /dev/null
-+++ b/coregrind/m_gdbserver/loongarch64-linux.xml
-@@ -0,0 +1,14 @@
-+
-+
++ status[n].exist = toBool(has_iu || has_d);
++ status[n].num = has_iu + has_d;
++}
+
-+
-+
-+ loongarch
-+ GNU/Linux
-+
-+
-+
-diff --git a/coregrind/m_gdbserver/target.c b/coregrind/m_gdbserver/target.c
-index f9f32f4..e97bd64 100644
---- a/coregrind/m_gdbserver/target.c
-+++ b/coregrind/m_gdbserver/target.c
-@@ -867,6 +867,8 @@ void valgrind_initialize_target(void)
- mips64_init_architecture(&the_low_target);
- #elif defined(VGA_nanomips)
- nanomips_init_architecture(&the_low_target);
-+#elif defined(VGA_loongarch64)
-+ loongarch64_init_architecture(&the_low_target);
- #else
- #error "architecture missing in target.c valgrind_initialize_target"
- #endif
-diff --git a/coregrind/m_gdbserver/valgrind-low-loongarch64.c b/coregrind/m_gdbserver/valgrind-low-loongarch64.c
-new file mode 100644
-index 0000000..6021c79
---- /dev/null
-+++ b/coregrind/m_gdbserver/valgrind-low-loongarch64.c
-@@ -0,0 +1,272 @@
-+/* Low level interface to valgrind, for the remote server for GDB integrated
-+ in valgrind.
-+ Copyright (C) 2021
-+ Free Software Foundation, Inc.
++static void
++get_cache(VexCacheInfo *ci, VexCacheKind kind, UInt level,
++ UInt line_size, UInt sets, UInt ways, UInt index)
++{
++ UInt assoc = ways;
++ UInt size = sets * ways * line_size;
++ ci->caches[index] = VEX_CACHE_INIT(kind, level, size, line_size, assoc);
++}
+
-+ This file is part of VALGRIND.
-+ It has been inspired from files from gdbserver in gdb 13.
++static void
++get_cache_info_for_l1(VexCacheInfo *ci, struct cache_status status[])
++{
++ UInt config;
++ UInt line_size, sets, ways;
++ UInt index = 0;
+
-+ This program is free software; you can redistribute it and/or modify
-+ it under the terms of the GNU General Public License as published by
-+ the Free Software Foundation; either version 2 of the License, or
-+ (at your option) any later version.
++ if (!status[0].exist)
++ return;
+
-+ This program is distributed in the hope that it will be useful,
-+ but WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-+ GNU General Public License for more details.
++ if (status[0].has_iu) {
++ config = cpucfg(LOONGARCH_CPUCFG17);
++ line_size = 1 << ((config & CPUCFG17_L1I_SIZE_M) >> CPUCFG17_L1I_SIZE);
++ sets = 1 << ((config & CPUCFG17_L1I_SETS_M) >> CPUCFG17_L1I_SETS);
++ ways = ((config & CPUCFG17_L1I_WAYS_M) >> CPUCFG17_L1I_WAYS) + 1;
++ get_cache(ci, status[0].is_u ? UNIFIED_CACHE : INSN_CACHE,
++ 1, line_size, sets, ways, index++);
++ }
+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, write to the Free Software
-+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
-+ Boston, MA 02110-1301, USA. */
++ if (status[0].has_d) {
++ config = cpucfg(LOONGARCH_CPUCFG18);
++ line_size = 1 << ((config & CPUCFG18_L1D_SIZE_M) >> CPUCFG18_L1D_SIZE);
++ sets = 1 << ((config & CPUCFG18_L1D_SETS_M) >> CPUCFG18_L1D_SETS);
++ ways = ((config & CPUCFG18_L1D_WAYS_M) >> CPUCFG18_L1D_WAYS) + 1;
++ get_cache(ci, DATA_CACHE, 1, line_size, sets, ways, index++);
++ }
+
-+#include "server.h"
-+#include "target.h"
-+#include "regdef.h"
-+#include "regcache.h"
++ /* Sanity check */
++ vg_assert(index == status[0].num);
++}
+
-+#include "pub_core_machine.h"
-+#include "pub_core_debuginfo.h"
-+#include "pub_core_threadstate.h"
-+#include "pub_core_transtab.h"
-+#include "pub_core_gdbserver.h"
++static void
++get_cache_info_for_l2(VexCacheInfo *ci, struct cache_status status[])
++{
++ UInt config;
++ UInt line_size, sets, ways;
++ UInt index = status[0].num;
+
-+#include "valgrind_low.h"
++ if (!status[1].exist)
++ return;
+
-+#include "libvex_guest_loongarch64.h"
++ config = cpucfg(LOONGARCH_CPUCFG19);
++ line_size = 1 << ((config & CPUCFG19_L2_SIZE_M) >> CPUCFG19_L2_SIZE);
++ sets = 1 << ((config & CPUCFG19_L2_SETS_M) >> CPUCFG19_L2_SETS);
++ ways = ((config & CPUCFG19_L2_WAYS_M) >> CPUCFG19_L2_WAYS) + 1;
+
-+static struct reg regs[] = {
-+ { "r0", 0, 64 },
-+ { "r1", 64, 64 },
-+ { "r2", 128, 64 },
-+ { "r3", 192, 64 },
-+ { "r4", 256, 64 },
-+ { "r5", 320, 64 },
-+ { "r6", 384, 64 },
-+ { "r7", 448, 64 },
-+ { "r8", 512, 64 },
-+ { "r9", 576, 64 },
-+ { "r10", 640, 64 },
-+ { "r11", 704, 64 },
-+ { "r12", 768, 64 },
-+ { "r13", 832, 64 },
-+ { "r14", 896, 64 },
-+ { "r15", 960, 64 },
-+ { "r16", 1024, 64 },
-+ { "r17", 1088, 64 },
-+ { "r18", 1152, 64 },
-+ { "r19", 1216, 64 },
-+ { "r20", 1280, 64 },
-+ { "r21", 1344, 64 },
-+ { "r22", 1408, 64 },
-+ { "r23", 1472, 64 },
-+ { "r24", 1536, 64 },
-+ { "r25", 1600, 64 },
-+ { "r26", 1664, 64 },
-+ { "r27", 1728, 64 },
-+ { "r28", 1792, 64 },
-+ { "r29", 1856, 64 },
-+ { "r30", 1920, 64 },
-+ { "r31", 1984, 64 },
-+ { "orig_a0", 2048, 64 },
-+ { "pc", 2112, 64 },
-+ { "badv", 2176, 64 },
-+ { "f0", 2240, 64 },
-+ { "f1", 2304, 64 },
-+ { "f2", 2368, 64 },
-+ { "f3", 2432, 64 },
-+ { "f4", 2496, 64 },
-+ { "f5", 2560, 64 },
-+ { "f6", 2624, 64 },
-+ { "f7", 2688, 64 },
-+ { "f8", 2752, 64 },
-+ { "f9", 2816, 64 },
-+ { "f10", 2880, 64 },
-+ { "f11", 2944, 64 },
-+ { "f12", 3008, 64 },
-+ { "f13", 3072, 64 },
-+ { "f14", 3136, 64 },
-+ { "f15", 3200, 64 },
-+ { "f16", 3264, 64 },
-+ { "f17", 3328, 64 },
-+ { "f18", 3392, 64 },
-+ { "f19", 3456, 64 },
-+ { "f20", 3520, 64 },
-+ { "f21", 3584, 64 },
-+ { "f22", 3648, 64 },
-+ { "f23", 3712, 64 },
-+ { "f24", 3776, 64 },
-+ { "f25", 3840, 64 },
-+ { "f26", 3904, 64 },
-+ { "f27", 3968, 64 },
-+ { "f28", 4032, 64 },
-+ { "f29", 4096, 64 },
-+ { "f30", 4160, 64 },
-+ { "f31", 4224, 64 },
-+ { "fcc0", 4288, 8 },
-+ { "fcc1", 4296, 8 },
-+ { "fcc2", 4304, 8 },
-+ { "fcc3", 4312, 8 },
-+ { "fcc4", 4320, 8 },
-+ { "fcc5", 4328, 8 },
-+ { "fcc6", 4336, 8 },
-+ { "fcc7", 4344, 8 },
-+ { "fcsr", 4352, 32 }
-+};
++ if (status[1].has_iu)
++ get_cache(ci, status[1].is_u ? UNIFIED_CACHE : INSN_CACHE,
++ 2, line_size, sets, ways, index++);
+
-+#define num_regs (sizeof (regs) / sizeof (regs[0]))
++ if (status[1].has_d)
++ get_cache(ci, DATA_CACHE, 2, line_size, sets, ways, index++);
+
-+static const char* expedite_regs[] = { "r3", "pc", NULL };
++ /* Sanity check */
++ vg_assert(index == status[0].num + status[1].num);
++}
+
-+static
-+CORE_ADDR get_pc (void)
++static void
++get_cache_info_for_l3(VexCacheInfo *ci, struct cache_status status[])
+{
-+ unsigned long pc;
++ UInt config;
++ UInt line_size, sets, ways;
++ UInt index = status[0].num + status[1].num;
+
-+ collect_register_by_name ("pc", &pc);
++ if (!status[2].exist)
++ return;
+
-+ dlog(1, "stop pc is %p\n", (void*) pc);
-+ return pc;
-+}
++ config = cpucfg(LOONGARCH_CPUCFG20);
++ line_size = 1 << ((config & CPUCFG20_L3_SIZE_M) >> CPUCFG20_L3_SIZE);
++ sets = 1 << ((config & CPUCFG20_L3_SETS_M) >> CPUCFG20_L3_SETS);
++ ways = ((config & CPUCFG20_L3_WAYS_M) >> CPUCFG20_L3_WAYS) + 1;
+
-+static
-+void set_pc (CORE_ADDR newpc)
-+{
-+ supply_register_by_name ("pc", &newpc);
++ if (status[2].has_iu)
++ get_cache(ci, status[2].is_u ? UNIFIED_CACHE : INSN_CACHE,
++ 3, line_size, sets, ways, index++);
++
++ if (status[2].has_d)
++ get_cache(ci, DATA_CACHE, 3, line_size, sets, ways, index++);
++
++ /* Sanity check */
++ vg_assert(index == status[0].num + status[1].num + status[2].num);
+}
+
-+/* store registers in the guest state (gdbserver_to_valgrind)
-+ or fetch register from the guest state (valgrind_to_gdbserver). */
-+static
-+void transfer_register (ThreadId tid, int abs_regno, void* buf,
-+ transfer_direction dir, int size, Bool* mod)
++static Bool
++get_cache_info_from_cpucfg(VexCacheInfo *ci)
+{
-+ ThreadState* tst = VG_(get_ThreadState)(tid);
-+ int set = abs_regno / num_regs;
-+ int regno = abs_regno % num_regs;
-+ *mod = False;
++ Int i;
++ struct cache_status status[3];
++ UInt config = cpucfg(LOONGARCH_CPUCFG16);
+
-+ VexGuestLOONGARCH64State* loongarch64 = (VexGuestLOONGARCH64State*) get_arch (set, tst);
++ /* NB: Bool is unsigned char! */
++ /* For l1 */
++ status[0].has_iu = toBool(config & CPUCFG16_L1_IUPRE);
++ status[0].is_u = toBool(config & CPUCFG16_L1_IUUNIFY);
++ status[0].has_d = toBool(config & CPUCFG16_L1_DPRE);
++ get_status(status, 0);
+
-+ switch (regno) {
-+ // numbers here have to match the order of regs above
-+ // Attention: gdb order does not match valgrind order.
-+ case 0: VG_(transfer) (&loongarch64->guest_R0, buf, dir, size, mod); break;
-+ case 1: VG_(transfer) (&loongarch64->guest_R1, buf, dir, size, mod); break;
-+ case 2: VG_(transfer) (&loongarch64->guest_R2, buf, dir, size, mod); break;
-+ case 3: VG_(transfer) (&loongarch64->guest_R3, buf, dir, size, mod); break;
-+ case 4: VG_(transfer) (&loongarch64->guest_R4, buf, dir, size, mod); break;
-+ case 5: VG_(transfer) (&loongarch64->guest_R5, buf, dir, size, mod); break;
-+ case 6: VG_(transfer) (&loongarch64->guest_R6, buf, dir, size, mod); break;
-+ case 7: VG_(transfer) (&loongarch64->guest_R7, buf, dir, size, mod); break;
-+ case 8: VG_(transfer) (&loongarch64->guest_R8, buf, dir, size, mod); break;
-+ case 9: VG_(transfer) (&loongarch64->guest_R9, buf, dir, size, mod); break;
-+ case 10: VG_(transfer) (&loongarch64->guest_R10, buf, dir, size, mod); break;
-+ case 11: VG_(transfer) (&loongarch64->guest_R11, buf, dir, size, mod); break;
-+ case 12: VG_(transfer) (&loongarch64->guest_R12, buf, dir, size, mod); break;
-+ case 13: VG_(transfer) (&loongarch64->guest_R13, buf, dir, size, mod); break;
-+ case 14: VG_(transfer) (&loongarch64->guest_R14, buf, dir, size, mod); break;
-+ case 15: VG_(transfer) (&loongarch64->guest_R15, buf, dir, size, mod); break;
-+ case 16: VG_(transfer) (&loongarch64->guest_R16, buf, dir, size, mod); break;
-+ case 17: VG_(transfer) (&loongarch64->guest_R17, buf, dir, size, mod); break;
-+ case 18: VG_(transfer) (&loongarch64->guest_R18, buf, dir, size, mod); break;
-+ case 19: VG_(transfer) (&loongarch64->guest_R19, buf, dir, size, mod); break;
-+ case 20: VG_(transfer) (&loongarch64->guest_R20, buf, dir, size, mod); break;
-+ case 21: VG_(transfer) (&loongarch64->guest_R21, buf, dir, size, mod); break;
-+ case 22: VG_(transfer) (&loongarch64->guest_R22, buf, dir, size, mod); break;
-+ case 23: VG_(transfer) (&loongarch64->guest_R23, buf, dir, size, mod); break;
-+ case 24: VG_(transfer) (&loongarch64->guest_R24, buf, dir, size, mod); break;
-+ case 25: VG_(transfer) (&loongarch64->guest_R25, buf, dir, size, mod); break;
-+ case 26: VG_(transfer) (&loongarch64->guest_R26, buf, dir, size, mod); break;
-+ case 27: VG_(transfer) (&loongarch64->guest_R27, buf, dir, size, mod); break;
-+ case 28: VG_(transfer) (&loongarch64->guest_R28, buf, dir, size, mod); break;
-+ case 29: VG_(transfer) (&loongarch64->guest_R29, buf, dir, size, mod); break;
-+ case 30: VG_(transfer) (&loongarch64->guest_R30, buf, dir, size, mod); break;
-+ case 31: VG_(transfer) (&loongarch64->guest_R31, buf, dir, size, mod); break;
-+ case 32: *mod = False; break; // GDBTD?? arg0
-+ case 33: VG_(transfer) (&loongarch64->guest_PC, buf, dir, size, mod); break;
-+ case 34: *mod = False; break; // GDBTD?? badvaddr
-+ case 35: VG_(transfer) (&loongarch64->guest_X0, buf, dir, size, mod); break;
-+ case 36: VG_(transfer) (&loongarch64->guest_X1, buf, dir, size, mod); break;
-+ case 37: VG_(transfer) (&loongarch64->guest_X2, buf, dir, size, mod); break;
-+ case 38: VG_(transfer) (&loongarch64->guest_X3, buf, dir, size, mod); break;
-+ case 39: VG_(transfer) (&loongarch64->guest_X4, buf, dir, size, mod); break;
-+ case 40: VG_(transfer) (&loongarch64->guest_X5, buf, dir, size, mod); break;
-+ case 41: VG_(transfer) (&loongarch64->guest_X6, buf, dir, size, mod); break;
-+ case 42: VG_(transfer) (&loongarch64->guest_X7, buf, dir, size, mod); break;
-+ case 43: VG_(transfer) (&loongarch64->guest_X8, buf, dir, size, mod); break;
-+ case 44: VG_(transfer) (&loongarch64->guest_X9, buf, dir, size, mod); break;
-+ case 45: VG_(transfer) (&loongarch64->guest_X10, buf, dir, size, mod); break;
-+ case 46: VG_(transfer) (&loongarch64->guest_X11, buf, dir, size, mod); break;
-+ case 47: VG_(transfer) (&loongarch64->guest_X12, buf, dir, size, mod); break;
-+ case 48: VG_(transfer) (&loongarch64->guest_X13, buf, dir, size, mod); break;
-+ case 49: VG_(transfer) (&loongarch64->guest_X14, buf, dir, size, mod); break;
-+ case 50: VG_(transfer) (&loongarch64->guest_X15, buf, dir, size, mod); break;
-+ case 51: VG_(transfer) (&loongarch64->guest_X16, buf, dir, size, mod); break;
-+ case 52: VG_(transfer) (&loongarch64->guest_X17, buf, dir, size, mod); break;
-+ case 53: VG_(transfer) (&loongarch64->guest_X18, buf, dir, size, mod); break;
-+ case 54: VG_(transfer) (&loongarch64->guest_X19, buf, dir, size, mod); break;
-+ case 55: VG_(transfer) (&loongarch64->guest_X20, buf, dir, size, mod); break;
-+ case 56: VG_(transfer) (&loongarch64->guest_X21, buf, dir, size, mod); break;
-+ case 57: VG_(transfer) (&loongarch64->guest_X22, buf, dir, size, mod); break;
-+ case 58: VG_(transfer) (&loongarch64->guest_X23, buf, dir, size, mod); break;
-+ case 59: VG_(transfer) (&loongarch64->guest_X24, buf, dir, size, mod); break;
-+ case 60: VG_(transfer) (&loongarch64->guest_X25, buf, dir, size, mod); break;
-+ case 61: VG_(transfer) (&loongarch64->guest_X26, buf, dir, size, mod); break;
-+ case 62: VG_(transfer) (&loongarch64->guest_X27, buf, dir, size, mod); break;
-+ case 63: VG_(transfer) (&loongarch64->guest_X28, buf, dir, size, mod); break;
-+ case 64: VG_(transfer) (&loongarch64->guest_X29, buf, dir, size, mod); break;
-+ case 65: VG_(transfer) (&loongarch64->guest_X30, buf, dir, size, mod); break;
-+ case 66: VG_(transfer) (&loongarch64->guest_X31, buf, dir, size, mod); break;
-+ case 67: VG_(transfer) (&loongarch64->guest_FCC0, buf, dir, size, mod); break;
-+ case 68: VG_(transfer) (&loongarch64->guest_FCC1, buf, dir, size, mod); break;
-+ case 69: VG_(transfer) (&loongarch64->guest_FCC2, buf, dir, size, mod); break;
-+ case 70: VG_(transfer) (&loongarch64->guest_FCC3, buf, dir, size, mod); break;
-+ case 71: VG_(transfer) (&loongarch64->guest_FCC4, buf, dir, size, mod); break;
-+ case 72: VG_(transfer) (&loongarch64->guest_FCC5, buf, dir, size, mod); break;
-+ case 73: VG_(transfer) (&loongarch64->guest_FCC6, buf, dir, size, mod); break;
-+ case 74: VG_(transfer) (&loongarch64->guest_FCC7, buf, dir, size, mod); break;
-+ case 75: VG_(transfer) (&loongarch64->guest_FCSR, buf, dir, size, mod); break;
-+ default: vg_assert(0);
++ /* For l2 */
++ status[1].has_iu = toBool(config & CPUCFG16_L2_IUPRE);
++ status[1].is_u = toBool(config & CPUCFG16_L2_IUUNIFY);
++ status[1].has_d = toBool(config & CPUCFG16_L2_DPRE);
++ get_status(status, 1);
++
++ /* For l3 */
++ status[2].has_iu = toBool(config & CPUCFG16_L3_IUPRE);
++ status[2].is_u = toBool(config & CPUCFG16_L3_IUUNIFY);
++ status[2].has_d = toBool(config & CPUCFG16_L3_DPRE);
++ get_status(status, 2);
++
++ ci->num_levels = 0;
++ ci->num_caches = 0;
++ for (i = 0; i < 3; i++) {
++ ci->num_levels += status[i].exist;
++ ci->num_caches += status[i].num;
+ }
-+}
+
-+static
-+const char* target_xml (Bool shadow_mode)
-+{
-+ if (shadow_mode) {
-+ return "loongarch64-linux-valgrind.xml";
-+ } else {
-+ return "loongarch64-linux.xml";
++ if (ci->num_caches == 0) {
++ VG_(debugLog)(1, "cache", "Autodetect failed\n");
++ return False;
+ }
-+}
+
-+static CORE_ADDR** target_get_dtv (ThreadState* tst)
-+{
-+ VexGuestLOONGARCH64State* loongarch64 = (VexGuestLOONGARCH64State*)&tst->arch.vex;
-+ // Top of LoongArch tcbhead structure is located 0x0 bytes before the value
-+ // of $r2. Dtv is the first of two pointers in tcbhead structure.
-+ // More details can be found in GLIBC/sysdeps/nptl/tls.h.
-+ return (CORE_ADDR**)((CORE_ADDR)loongarch64->guest_R2
-+ - 0x0 - 2 * sizeof(CORE_ADDR));
++ ci->caches = VG_(malloc)("m_cache", ci->num_caches * sizeof(VexCache));
++ get_cache_info_for_l1(ci, status);
++ get_cache_info_for_l2(ci, status);
++ get_cache_info_for_l3(ci, status);
++ return True;
+}
+
-+static struct valgrind_target_ops low_target = {
-+ num_regs,
-+ 3, // SP
-+ regs,
-+ transfer_register,
-+ get_pc,
-+ set_pc,
-+ "loongarch64",
-+ target_xml,
-+ target_get_dtv
-+};
-+
-+void loongarch64_init_architecture (struct valgrind_target_ops* target)
++static Bool
++get_cache_info(VexArchInfo *vai)
+{
-+ *target = low_target;
-+ set_register_cache (regs, num_regs);
-+ gdbserver_expedite_regs = expedite_regs;
++ VexCacheInfo *ci = &vai->hwcache_info;
++ ci->icaches_maintain_coherence = True;
++ return get_cache_info_from_cpucfg(ci);
+}
-diff --git a/coregrind/m_gdbserver/valgrind_low.h b/coregrind/m_gdbserver/valgrind_low.h
-index d8ae3c9..3393c32 100644
---- a/coregrind/m_gdbserver/valgrind_low.h
-+++ b/coregrind/m_gdbserver/valgrind_low.h
-@@ -109,5 +109,6 @@ extern void s390x_init_architecture (struct valgrind_target_ops *target);
- extern void mips32_init_architecture (struct valgrind_target_ops *target);
- extern void mips64_init_architecture (struct valgrind_target_ops *target);
- extern void nanomips_init_architecture (struct valgrind_target_ops *target);
-+extern void loongarch64_init_architecture (struct valgrind_target_ops *target);
-
- #endif
-diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c
-index 7a7d453..237a11f 100644
---- a/coregrind/m_initimg/initimg-linux.c
-+++ b/coregrind/m_initimg/initimg-linux.c
-@@ -913,7 +913,8 @@ Addr setup_client_stack( void* init_sp,
- && !defined(VGP_ppc64le_linux) \
- && !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux) \
- && !defined(VGP_nanomips_linux) \
-- && !defined(VGP_s390x_linux)
-+ && !defined(VGP_s390x_linux) \
-+ && !defined(VGP_loongarch64_linux)
- case AT_SYSINFO_EHDR: {
- /* Trash this, because we don't reproduce it */
- const NSegment* ehdrseg = VG_(am_find_nsegment)((Addr)auxv->u.a_ptr);
-@@ -1344,6 +1345,20 @@ void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii )
- arch->vex.guest_PC = iifii.initial_client_IP;
- arch->vex.guest_r31 = iifii.initial_client_SP;
-
-+# elif defined(VGP_loongarch64_linux)
-+ vg_assert(0 == sizeof(VexGuestLOONGARCH64State) % LibVEX_GUEST_STATE_ALIGN);
-+
-+ /* Zero out the initial state, and set up the simulated FPU in a
-+ sane way. */
-+ LibVEX_GuestLOONGARCH64_initialise(&arch->vex);
+
-+ /* Zero out the shadow areas. */
-+ VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestLOONGARCH64State));
-+ VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestLOONGARCH64State));
-+
-+ arch->vex.guest_R3 = iifii.initial_client_SP;
-+ arch->vex.guest_PC = iifii.initial_client_IP;
-+
- # else
- # error Unknown platform
- # endif
-diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c
-index 0b04bfc..c95253d 100644
---- a/coregrind/m_libcassert.c
-+++ b/coregrind/m_libcassert.c
-@@ -264,6 +264,26 @@
- (srP)->misc.MIPS32.r31 = (UInt)ra; \
- (srP)->misc.MIPS32.r28 = (UInt)gp; \
- }
-+#elif defined(VGP_loongarch64_linux)
-+# define GET_STARTREGS(srP) \
-+ { \
-+ ULong pc, sp, fp, ra; \
-+ __asm__ __volatile__( \
-+ "pcaddi %0, 0 \n\t" \
-+ "move %1, $sp \n\t" \
-+ "move %2, $fp \n\t" \
-+ "move %3, $ra \n\t" \
-+ : "=r" (pc), \
-+ "=r" (sp), \
-+ "=r" (fp), \
-+ "=r" (ra) \
-+ : /* reads none */ \
-+ : /* no trashed */ ); \
-+ (srP)->r_pc = (ULong)pc; \
-+ (srP)->r_sp = (ULong)sp; \
-+ (srP)->misc.LOONGARCH64.r_fp = (ULong)fp; \
-+ (srP)->misc.LOONGARCH64.r_ra = (ULong)ra; \
-+ }
#else
- # error Unknown platform
- #endif
-diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c
-index 5d3a349..bbbd4e7 100644
---- a/coregrind/m_libcfile.c
-+++ b/coregrind/m_libcfile.c
-@@ -264,7 +264,8 @@ Bool VG_(resolve_filemode) ( Int fd, Int * result )
-
- SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev )
- {
--# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- /* ARM64 wants to use __NR_mknodat rather than __NR_mknod. */
- SysRes res = VG_(do_syscall4)(__NR_mknodat,
- VKI_AT_FDCWD, (UWord)pathname, mode, dev);
-@@ -290,7 +291,8 @@ SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev )
-
- SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode )
- {
--# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- /* ARM64 wants to use __NR_openat rather than __NR_open. */
- SysRes res = VG_(do_syscall4)(__NR_openat,
- VKI_AT_FDCWD, (UWord)pathname, flags, mode);
-@@ -384,7 +386,8 @@ Int VG_(pipe) ( Int fd[2] )
- } else {
- return -1;
- }
--# elif defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+# elif defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- SysRes res = VG_(do_syscall2)(__NR_pipe2, (UWord)fd, 0);
- return sr_isError(res) ? -1 : 0;
- # elif defined(VGO_linux)
-@@ -517,12 +520,19 @@ SysRes VG_(stat) ( const HChar* file_name, struct vg_stat* vgbuf )
- { struct vki_statx buf;
- res = VG_(do_syscall5)(__NR_statx, VKI_AT_FDCWD, (UWord)file_name, 0,
- VKI_STATX_ALL, (UWord)&buf);
-+# if defined(VGP_loongarch64_linux)
-+ /* On LoongArch64 Linux platform, only statx is available. */
-+ if (!sr_isError(res))
-+ TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
-+ return res;
-+# else
- if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
- /* Success, or any failure except ENOSYS */
- if (!sr_isError(res))
- TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
- return res;
- }
-+# endif
- }
- # endif
- # if defined(VGO_linux) || defined(VGO_darwin)
-@@ -602,12 +612,19 @@ Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
- const char* file_name = "";
- res = VG_(do_syscall5)(__NR_statx, fd, (RegWord)file_name,
- VKI_AT_EMPTY_PATH, VKI_STATX_ALL, (RegWord)&buf);
-+# if defined(VGP_loongarch64_linux)
-+ /* On LoongArch64 Linux platform, only statx is available. */
-+ if (!sr_isError(res))
-+ TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
-+ return sr_isError(res) ? (-1) : 0;
-+# else
- if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
- /* Success, or any failure except ENOSYS */
- if (!sr_isError(res))
- TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
- return sr_isError(res) ? (-1) : 0;
- }
-+# endif
- }
- #endif
- # if defined(VGO_linux) || defined(VGO_darwin)
-@@ -731,7 +748,8 @@ SysRes VG_(dup) ( Int oldfd )
-
- SysRes VG_(dup2) ( Int oldfd, Int newfd )
- {
--# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- /* We only have dup3, that means we have to mimic dup2.
- The only real difference is when oldfd == newfd.
- dup3 always returns an error, but dup2 returns only an
-@@ -777,7 +795,7 @@ Int VG_(rename) ( const HChar* old_name, const HChar* new_name )
- # if defined(VGO_solaris) || defined(VGP_arm64_linux)
- SysRes res = VG_(do_syscall4)(__NR_renameat, VKI_AT_FDCWD, (UWord)old_name,
- VKI_AT_FDCWD, (UWord)new_name);
--# elif defined(VGP_nanomips_linux)
-+# elif defined(VGP_nanomips_linux) || defined(VGP_loongarch64_linux)
- SysRes res = VG_(do_syscall5)(__NR_renameat2, VKI_AT_FDCWD, (UWord)old_name,
- VKI_AT_FDCWD, (UWord)new_name, 0);
-
-@@ -791,7 +809,8 @@ Int VG_(rename) ( const HChar* old_name, const HChar* new_name )
-
- Int VG_(unlink) ( const HChar* file_name )
- {
--# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- SysRes res = VG_(do_syscall2)(__NR_unlinkat, VKI_AT_FDCWD,
- (UWord)file_name);
- # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
-@@ -870,7 +889,8 @@ const HChar *VG_(get_startup_wd) ( void )
- SysRes VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout)
- {
- SysRes res;
--# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- /* ARM64 wants to use __NR_ppoll rather than __NR_poll. */
- struct vki_timespec timeout_ts;
- if (timeout >= 0) {
-@@ -915,7 +935,8 @@ SSizeT VG_(readlink) (const HChar* path, HChar* buf, SizeT bufsiz)
- {
- SysRes res;
- /* res = readlink( path, buf, bufsiz ); */
--# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
- (UWord)path, (UWord)buf, bufsiz);
- # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
-@@ -994,7 +1015,8 @@ Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
- UWord w = (irusr ? VKI_R_OK : 0)
- | (iwusr ? VKI_W_OK : 0)
- | (ixusr ? VKI_X_OK : 0);
--# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- SysRes res = VG_(do_syscall3)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, w);
- # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
- SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
-@@ -1140,7 +1162,8 @@ SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset )
- return res;
- # elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \
- || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
-- || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
-+ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
-+ || defined(VGP_loongarch64_linux)
- res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
- return res;
- # elif defined(VGP_amd64_freebsd)
-@@ -1404,7 +1427,8 @@ Int VG_(socket) ( Int domain, Int type, Int protocol )
-
- # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
-- || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
-+ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGO_freebsd) || defined(VGP_loongarch64_linux)
- SysRes res;
- res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
- return sr_isError(res) ? -1 : sr_Res(res);
-@@ -1459,7 +1483,8 @@ Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
-
- # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
-- || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
-+ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGO_freebsd) || defined(VGP_loongarch64_linux)
- SysRes res;
- res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
- return sr_isError(res) ? -1 : sr_Res(res);
-@@ -1506,7 +1531,8 @@ Int VG_(write_socket)( Int sd, const void *msg, Int count )
- # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
-- || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
-+ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGO_freebsd) || defined(VGP_loongarch64_linux)
- SysRes res;
- res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
- count, VKI_MSG_NOSIGNAL, 0,0);
-@@ -1544,7 +1570,8 @@ Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
- # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
- || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
- || defined(VGP_nanomips_linux) || defined(VGO_freebsd) \
-- || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
-+ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
-+ || defined(VGP_loongarch64_linux)
- SysRes res;
- res = VG_(do_syscall3)( __NR_getsockname,
- (UWord)sd, (UWord)name, (UWord)namelen );
-@@ -1583,7 +1610,8 @@ Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
+ #error "Unknown arch"
+diff --git a/coregrind/m_coredump/coredump-elf.c b/coregrind/m_coredump/coredump-elf.c
+index a4632d9..7d92aa8 100644
+--- a/coregrind/m_coredump/coredump-elf.c
++++ b/coregrind/m_coredump/coredump-elf.c
+@@ -489,6 +489,40 @@ static void fill_prstatus(const ThreadState *tst,
+ regs[VKI_MIPS32_EF_CP0_STATUS] = arch->vex.guest_CP0_status;
+ regs[VKI_MIPS32_EF_CP0_EPC] = arch->vex.guest_PC;
+ # undef DO
++#elif defined(VGP_loongarch64_linux)
++ regs->regs[0] = arch->vex.guest_R0;
++ regs->regs[1] = arch->vex.guest_R1;
++ regs->regs[2] = arch->vex.guest_R2;
++ regs->regs[3] = arch->vex.guest_R3;
++ regs->regs[4] = arch->vex.guest_R4;
++ regs->regs[5] = arch->vex.guest_R5;
++ regs->regs[6] = arch->vex.guest_R6;
++ regs->regs[7] = arch->vex.guest_R7;
++ regs->regs[8] = arch->vex.guest_R8;
++ regs->regs[9] = arch->vex.guest_R9;
++ regs->regs[10] = arch->vex.guest_R10;
++ regs->regs[11] = arch->vex.guest_R11;
++ regs->regs[12] = arch->vex.guest_R12;
++ regs->regs[13] = arch->vex.guest_R13;
++ regs->regs[14] = arch->vex.guest_R14;
++ regs->regs[15] = arch->vex.guest_R15;
++ regs->regs[16] = arch->vex.guest_R16;
++ regs->regs[17] = arch->vex.guest_R17;
++ regs->regs[18] = arch->vex.guest_R18;
++ regs->regs[19] = arch->vex.guest_R19;
++ regs->regs[20] = arch->vex.guest_R20;
++ regs->regs[21] = arch->vex.guest_R21;
++ regs->regs[22] = arch->vex.guest_R22;
++ regs->regs[23] = arch->vex.guest_R23;
++ regs->regs[24] = arch->vex.guest_R24;
++ regs->regs[25] = arch->vex.guest_R25;
++ regs->regs[26] = arch->vex.guest_R26;
++ regs->regs[27] = arch->vex.guest_R27;
++ regs->regs[28] = arch->vex.guest_R28;
++ regs->regs[29] = arch->vex.guest_R29;
++ regs->regs[30] = arch->vex.guest_R30;
++ regs->regs[31] = arch->vex.guest_R31;
++ regs->csr_era = arch->vex.guest_PC;
+ #elif defined(VGP_amd64_freebsd)
+ regs->rflags = LibVEX_GuestAMD64_get_rflags( &arch->vex );
+ regs->rsp = arch->vex.guest_RSP;
+@@ -691,6 +725,14 @@ static void fill_fpu(const ThreadState *tst, vki_elf_fpregset_t *fpu)
+ # undef DO
+ #elif defined(VGP_nanomips_linux)
- # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
- || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
-- || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
-+ || defined(VGP_nanomips_linux) || defined(VGO_freebsd) \
-+ || defined(VGP_loongarch64_linux)
- SysRes res;
- res = VG_(do_syscall3)( __NR_getpeername,
- (UWord)sd, (UWord)name, (UWord)namelen );
-@@ -1625,7 +1653,7 @@ Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
- # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
- || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-- || defined(VGO_freebsd)
-+ || defined(VGO_freebsd) || defined(VGP_loongarch64_linux)
- SysRes res;
- res = VG_(do_syscall5)( __NR_getsockopt,
- (UWord)sd, (UWord)level, (UWord)optname,
-@@ -1669,7 +1697,8 @@ Int VG_(setsockopt) ( Int sd, Int level, Int optname, void *optval,
++#elif defined(VGP_loongarch64_linux)
++# define DO(n) (*fpu)[n] = *(const double*)(&arch->vex.guest_X##n)
++ DO(0); DO(1); DO(2); DO(3); DO(4); DO(5); DO(6); DO(7);
++ DO(8); DO(9); DO(10); DO(11); DO(12); DO(13); DO(14); DO(15);
++ DO(16); DO(17); DO(18); DO(19); DO(20); DO(21); DO(22); DO(23);
++ DO(24); DO(25); DO(26); DO(27); DO(28); DO(29); DO(30); DO(31);
++# undef DO
++
+ #elif defined(VGP_x86_freebsd)
- # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
-- || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- SysRes res;
- res = VG_(do_syscall5)( __NR_setsockopt,
- (UWord)sd, (UWord)level, (UWord)optname,
-diff --git a/coregrind/m_libcproc.c b/coregrind/m_libcproc.c
-index 592d69b..61827cb 100644
---- a/coregrind/m_libcproc.c
-+++ b/coregrind/m_libcproc.c
-@@ -698,7 +698,8 @@ Int VG_(gettid)(void)
- * the /proc/self link is pointing...
- */
+ #elif defined(VGP_amd64_freebsd)
+diff --git a/coregrind/m_debuginfo/d3basics.c b/coregrind/m_debuginfo/d3basics.c
+index 97ecbda..546cd2f 100644
+--- a/coregrind/m_debuginfo/d3basics.c
++++ b/coregrind/m_debuginfo/d3basics.c
+@@ -555,6 +555,9 @@ static Bool get_Dwarf_Reg( /*OUT*/Addr* a, Word regno, const RegSummary* regs )
+ # elif defined(VGP_arm64_linux) || defined(VGP_arm64_freebsd)
+ if (regno == 31) { *a = regs->sp; return True; }
+ if (regno == 29) { *a = regs->fp; return True; }
++# elif defined(VGP_loongarch64_linux)
++ if (regno == 3) { *a = regs->sp; return True; }
++ if (regno == 22) { *a = regs->fp; return True; }
+ # else
+ # error "Unknown platform"
+ # endif
+diff --git a/coregrind/m_debuginfo/debuginfo.c b/coregrind/m_debuginfo/debuginfo.c
+index ad05b99..5aef8fe 100644
+--- a/coregrind/m_debuginfo/debuginfo.c
++++ b/coregrind/m_debuginfo/debuginfo.c
+@@ -1270,7 +1270,7 @@ ULong VG_(di_notify_mmap)( Addr a, Bool allow_SkFileV, Int use_fd )
+ is_ro_map = False;
--# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
- (UWord)"/proc/self",
- (UWord)pid, sizeof(pid));
-@@ -753,7 +754,8 @@ Int VG_(getpid) ( void )
- Int VG_(getpgrp) ( void )
- {
- /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
--# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- return sr_Res( VG_(do_syscall1)(__NR_getpgid, 0) );
- # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
- return sr_Res( VG_(do_syscall0)(__NR_getpgrp) );
-@@ -850,7 +852,7 @@ Int VG_(getgroups)( Int size, UInt* list )
- || defined(VGO_darwin) || defined(VGP_s390x_linux) \
- || defined(VGP_mips32_linux) || defined(VGP_arm64_linux) \
- || defined(VGO_solaris) || defined(VGP_nanomips_linux) \
-- || defined(VGO_freebsd)
-+ || defined(VGO_freebsd) || defined(VGP_loongarch64_linux)
- SysRes sres;
- sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list);
- if (sr_isError(sres))
-@@ -944,7 +946,8 @@ Int VG_(fork) ( void )
- fds[0] = fds[1] = -1;
+ # if defined(VGA_x86) || defined(VGA_ppc32) || defined(VGA_mips32) \
+- || defined(VGA_mips64) || defined(VGA_nanomips)
++ || defined(VGA_mips64) || defined(VGA_nanomips) || defined(VGA_loongarch64)
+ is_rx_map = seg->hasR && seg->hasX;
+ is_rw_map = seg->hasR && seg->hasW;
+ # elif defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
+@@ -3095,6 +3095,11 @@ UWord evalCfiExpr ( const XArray* exprs, Int ix,
+ case Creg_ARM64_SP: return eec->uregs->sp;
+ case Creg_ARM64_X30: return eec->uregs->x30;
+ case Creg_ARM64_X29: return eec->uregs->x29;
++# elif defined(VGA_loongarch64)
++ case Creg_LOONGARCH64_PC: return eec->uregs->pc;
++ case Creg_LOONGARCH64_RA: return eec->uregs->ra;
++ case Creg_LOONGARCH64_SP: return eec->uregs->sp;
++ case Creg_LOONGARCH64_FP: return eec->uregs->fp;
+ # else
+ # error "Unsupported arch"
+ # endif
+@@ -3368,6 +3373,13 @@ static Addr compute_cfa ( const D3UnwindRegs* uregs,
+ case CFIC_ARM64_X29REL:
+ cfa = cfsi_m->cfa_off + uregs->x29;
+ break;
++# elif defined(VGA_loongarch64)
++ case CFIC_IA_SPREL:
++ cfa = cfsi_m->cfa_off + uregs->sp;
++ break;
++ case CFIC_IA_BPREL:
++ cfa = cfsi_m->cfa_off + uregs->fp;
++ break;
+ # elif defined(VGP_arm64_freebsd)
+ case CFIC_ARM64_SPREL:
+ cfa = cfsi_m->cfa_off + uregs->sp;
+@@ -3375,7 +3387,6 @@ static Addr compute_cfa ( const D3UnwindRegs* uregs,
+ case CFIC_ARM64_X29REL:
+ cfa = cfsi_m->cfa_off + uregs->x29;
+ break;
+-
+ # else
+ # error "Unsupported arch"
+ # endif
+@@ -3447,6 +3458,14 @@ Addr ML_(get_CFA) ( Addr ip, Addr sp, Addr fp,
+ return compute_cfa(&uregs,
+ min_accessible, max_accessible, ce->di, ce->cfsi_m);
}
++#elif defined(VGA_loongarch64)
++ { D3UnwindRegs uregs;
++ uregs.pc = ip;
++ uregs.sp = sp;
++ uregs.fp = fp;
++ return compute_cfa(&uregs,
++ min_accessible, max_accessible, ce->di, ce->cfsi_m);
++ }
--# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- SysRes res;
- res = VG_(do_syscall5)(__NR_clone, VKI_SIGCHLD,
- (UWord)NULL, (UWord)NULL, (UWord)NULL, (UWord)NULL);
-diff --git a/coregrind/m_libcsetjmp.c b/coregrind/m_libcsetjmp.c
-index f53a223..400f68a 100644
---- a/coregrind/m_libcsetjmp.c
-+++ b/coregrind/m_libcsetjmp.c
-@@ -781,6 +781,72 @@ __asm__(
- );
- #endif /* VGP_s390x_linux */
+ # else
+ return 0; /* indicates failure */
+@@ -3498,6 +3517,8 @@ void VG_(ppUnwindInfo) (Addr from, Addr to)
+ For arm64, the unwound registers are: X29(FP) X30(LR) SP PC.
-+#if defined(VGP_loongarch64_linux)
-+
-+__asm__(
-+".text \n\t"
-+".globl VG_MINIMAL_SETJMP; \n\t"
-+"VG_MINIMAL_SETJMP: \n\t"
-+" st.d $ra, $a0, 0 \n\t"
-+" st.d $sp, $a0, 8 \n\t"
-+" st.d $r21, $a0, 16 \n\t"
-+" st.d $fp, $a0, 24 \n\t"
-+" st.d $s0, $a0, 32 \n\t"
-+" st.d $s1, $a0, 40 \n\t"
-+" st.d $s2, $a0, 48 \n\t"
-+" st.d $s3, $a0, 56 \n\t"
-+" st.d $s4, $a0, 64 \n\t"
-+" st.d $s5, $a0, 72 \n\t"
-+" st.d $s6, $a0, 80 \n\t"
-+" st.d $s7, $a0, 88 \n\t"
-+" st.d $s8, $a0, 96 \n\t"
-+#if !defined(__loongarch_soft_float)
-+" fst.d $f24, $a0, 104 \n\t"
-+" fst.d $f25, $a0, 112 \n\t"
-+" fst.d $f26, $a0, 120 \n\t"
-+" fst.d $f27, $a0, 128 \n\t"
-+" fst.d $f28, $a0, 136 \n\t"
-+" fst.d $f29, $a0, 144 \n\t"
-+" fst.d $f30, $a0, 152 \n\t"
-+" fst.d $f30, $a0, 160 \n\t"
-+#endif
-+" move $a0, $zero \n\t"
-+" jr $ra \n\t"
-+" \n\t"
-+".text \n\t"
-+".globl VG_MINIMAL_LONGJMP; \n\t"
-+"VG_MINIMAL_LONGJMP: \n\t"
-+" ld.d $ra, $a0, 0 \n\t"
-+" ld.d $sp, $a0, 8 \n\t"
-+" ld.d $r21, $a0, 16 \n\t"
-+" ld.d $fp, $a0, 24 \n\t"
-+" ld.d $s0, $a0, 32 \n\t"
-+" ld.d $s1, $a0, 40 \n\t"
-+" ld.d $s2, $a0, 48 \n\t"
-+" ld.d $s3, $a0, 56 \n\t"
-+" ld.d $s4, $a0, 64 \n\t"
-+" ld.d $s5, $a0, 72 \n\t"
-+" ld.d $s6, $a0, 80 \n\t"
-+" ld.d $s7, $a0, 88 \n\t"
-+" ld.d $s8, $a0, 96 \n\t"
-+#if !defined(__loongarch_soft_float)
-+" fld.d $f24, $a0, 104 \n\t"
-+" fld.d $f25, $a0, 112 \n\t"
-+" fld.d $f26, $a0, 120 \n\t"
-+" fld.d $f27, $a0, 128 \n\t"
-+" fld.d $f28, $a0, 136 \n\t"
-+" fld.d $f29, $a0, 144 \n\t"
-+" fld.d $f30, $a0, 152 \n\t"
-+" fld.d $f30, $a0, 160 \n\t"
-+#endif
-+" bnez $a1, 1f \n\t"
-+" addi.d $a1, $a1, 1 \n\t"
-+"1: \n\t"
-+" move $a0, $a1 \n\t"
-+" jr $ra \n\t"
-+);
-+#endif /* VGP_loongarch64_linux */
+ For s390, the unwound registers are: R11(FP) R14(LR) R15(SP) F0..F7 PC.
+
- /*--------------------------------------------------------------------*/
- /*--- end ---*/
- /*--------------------------------------------------------------------*/
-diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c
-index a4c2218..5cfca01 100644
---- a/coregrind/m_machine.c
-+++ b/coregrind/m_machine.c
-@@ -152,6 +152,13 @@ void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs,
- = VG_(threads)[tid].arch.vex.guest_r31;
- regs->misc.MIPS64.r28
- = VG_(threads)[tid].arch.vex.guest_r28;
++ For loongarch64, the unwound registers are: FP SP PC
+ */
+ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
+ Addr min_accessible,
+@@ -3521,6 +3542,8 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
+ # elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
+ # elif defined(VGP_arm64_linux)
+ ipHere = uregsHere->pc;
+# elif defined(VGA_loongarch64)
-+ regs->r_pc = VG_(threads)[tid].arch.vex.guest_PC;
-+ regs->r_sp = VG_(threads)[tid].arch.vex.guest_R3;
-+ regs->misc.LOONGARCH64.r_fp
-+ = VG_(threads)[tid].arch.vex.guest_R22;
-+ regs->misc.LOONGARCH64.r_ra
-+ = VG_(threads)[tid].arch.vex.guest_R1;
++ ipHere = uregsHere->pc;
+ # elif defined(VGP_arm64_freebsd)
+ ipHere = uregsHere->pc;
+ # else
+@@ -3668,6 +3691,10 @@ Bool VG_(use_CF_info) ( /*MOD*/D3UnwindRegs* uregsHere,
+ COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi_m->sp_how, cfsi_m->sp_off);
+ COMPUTE(uregsPrev.x30, uregsHere->x30, cfsi_m->x30_how, cfsi_m->x30_off);
+ COMPUTE(uregsPrev.x29, uregsHere->x29, cfsi_m->x29_how, cfsi_m->x29_off);
++# elif defined(VGA_loongarch64)
++ COMPUTE(uregsPrev.pc, uregsHere->ra, cfsi_m->ra_how, cfsi_m->ra_off);
++ COMPUTE(uregsPrev.sp, uregsHere->sp, cfsi_m->sp_how, cfsi_m->sp_off);
++ COMPUTE(uregsPrev.fp, uregsHere->fp, cfsi_m->fp_how, cfsi_m->fp_off);
# else
# error "Unknown arch"
# endif
-@@ -369,6 +376,39 @@ static void apply_to_GPs_of_tid(ThreadId tid, void (*f)(ThreadId,
- (*f)(tid, "x28", vex->guest_X28);
- (*f)(tid, "x29", vex->guest_X29);
- (*f)(tid, "x30", vex->guest_X30);
+diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h
+index 441b379..41224a8 100644
+--- a/coregrind/m_debuginfo/priv_storage.h
++++ b/coregrind/m_debuginfo/priv_storage.h
+@@ -367,6 +367,19 @@ typedef
+ Int fp_off;
+ }
+ DiCfSI_m;
+#elif defined(VGA_loongarch64)
-+ (*f)(tid, "r0" , vex->guest_R0 );
-+ (*f)(tid, "r1" , vex->guest_R1 );
-+ (*f)(tid, "r2" , vex->guest_R2 );
-+ (*f)(tid, "r3" , vex->guest_R3 );
-+ (*f)(tid, "r4" , vex->guest_R4 );
-+ (*f)(tid, "r5" , vex->guest_R5 );
-+ (*f)(tid, "r6" , vex->guest_R6 );
-+ (*f)(tid, "r7" , vex->guest_R7 );
-+ (*f)(tid, "r8" , vex->guest_R8 );
-+ (*f)(tid, "r9" , vex->guest_R9 );
-+ (*f)(tid, "r10", vex->guest_R10);
-+ (*f)(tid, "r11", vex->guest_R11);
-+ (*f)(tid, "r12", vex->guest_R12);
-+ (*f)(tid, "r13", vex->guest_R13);
-+ (*f)(tid, "r14", vex->guest_R14);
-+ (*f)(tid, "r15", vex->guest_R15);
-+ (*f)(tid, "r16", vex->guest_R16);
-+ (*f)(tid, "r17", vex->guest_R17);
-+ (*f)(tid, "r18", vex->guest_R18);
-+ (*f)(tid, "r19", vex->guest_R19);
-+ (*f)(tid, "r20", vex->guest_R20);
-+ (*f)(tid, "r21", vex->guest_R21);
-+ (*f)(tid, "r22", vex->guest_R22);
-+ (*f)(tid, "r23", vex->guest_R23);
-+ (*f)(tid, "r24", vex->guest_R24);
-+ (*f)(tid, "r25", vex->guest_R25);
-+ (*f)(tid, "r26", vex->guest_R26);
-+ (*f)(tid, "r27", vex->guest_R27);
-+ (*f)(tid, "r28", vex->guest_R28);
-+ (*f)(tid, "r29", vex->guest_R29);
-+ (*f)(tid, "r30", vex->guest_R30);
-+ (*f)(tid, "r31", vex->guest_R31);
++typedef
++ struct {
++ UChar cfa_how; /* a CFIC_ value */
++ UChar ra_how; /* a CFIR_ value */
++ UChar sp_how; /* a CFIR_ value */
++ UChar fp_how; /* a CFIR_ value */
++ Int cfa_off;
++ Int ra_off;
++ Int sp_off;
++ Int fp_off;
++ }
++ DiCfSI_m;
#else
- # error Unknown arch
+ # error "Unknown arch"
#endif
-@@ -479,7 +519,7 @@ Int VG_(machine_arm_archlevel) = 4;
- testing, so we need a VG_MINIMAL_JMP_BUF. */
- #if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
- || defined(VGA_arm) || defined(VGA_s390x) || defined(VGA_mips32) \
-- || defined(VGA_mips64) || defined(VGA_arm64)
-+ || defined(VGA_mips64) || defined(VGA_arm64) || defined(VGA_loongarch64)
- #include "pub_core_libcsetjmp.h"
- static VG_MINIMAL_JMP_BUF(env_unsup_insn);
- static void handler_unsup_insn ( Int x ) {
-@@ -861,6 +901,105 @@ static Bool VG_(parse_cpuinfo)(void)
+@@ -422,7 +435,11 @@ typedef
+ Creg_S390_SP,
+ Creg_S390_FP,
+ Creg_S390_LR,
+- Creg_MIPS_RA
++ Creg_MIPS_RA,
++ Creg_LOONGARCH64_PC,
++ Creg_LOONGARCH64_RA,
++ Creg_LOONGARCH64_SP,
++ Creg_LOONGARCH64_FP
+ }
+ CfiReg;
- #endif /* defined(VGP_arm64_linux) */
+diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c
+index 48df2e7..75a2b23 100644
+--- a/coregrind/m_debuginfo/readdwarf.c
++++ b/coregrind/m_debuginfo/readdwarf.c
+@@ -2066,6 +2066,10 @@ void ML_(read_debuginfo_dwarf1) (
+ # define FP_REG 30
+ # define SP_REG 29
+ # define RA_REG_DEFAULT 31
++#elif defined(VGP_loongarch64_linux)
++# define FP_REG 22
++# define SP_REG 3
++# define RA_REG_DEFAULT 1
+ #else
+ # error "Unknown platform"
+ #endif
+@@ -2084,6 +2088,8 @@ void ML_(read_debuginfo_dwarf1) (
+ # define N_CFI_REGS 128
+ #elif defined(VGP_s390x_linux)
+ # define N_CFI_REGS 66
++#elif defined(VGP_loongarch64_linux)
++# define N_CFI_REGS 32
+ #else
+ # define N_CFI_REGS 20
+ #endif
+@@ -2310,6 +2316,10 @@ static void initUnwindContext ( /*OUT*/UnwindContext* ctx )
+ start out as RR_Same. */
+ ctx->state[j].reg[29/*FP*/].tag = RR_Same;
+ ctx->state[j].reg[30/*LR*/].tag = RR_Same;
++# elif defined(VGA_loongarch64)
++ /* Registers fp and ra start out implicitly as RR_Same. */
++ ctx->state[j].reg[FP_REG].tag = RR_Same;
++ ctx->state[j].reg[RA_REG_DEFAULT].tag = RR_Same;
+ # endif
+ }
+ }
+@@ -2392,7 +2402,8 @@ static Bool summarise_context(/*OUT*/Addr* base,
+ if (ctxs->cfa_is_regoff && ctxs->cfa_reg == SP_REG) {
+ si_m->cfa_off = ctxs->cfa_off;
+ # if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \
+- || defined(VGA_mips32) || defined(VGA_nanomips) || defined(VGA_mips64)
++ || defined(VGA_mips32) || defined(VGA_nanomips) || defined(VGA_mips64) \
++ || defined(VGA_loongarch64)
+ si_m->cfa_how = CFIC_IA_SPREL;
+ # elif defined(VGA_arm)
+ si_m->cfa_how = CFIC_ARM_R13REL;
+@@ -2406,7 +2417,8 @@ static Bool summarise_context(/*OUT*/Addr* base,
+ if (ctxs->cfa_is_regoff && ctxs->cfa_reg == FP_REG) {
+ si_m->cfa_off = ctxs->cfa_off;
+ # if defined(VGA_x86) || defined(VGA_amd64) || defined(VGA_s390x) \
+- || defined(VGA_mips32) || defined(VGA_nanomips) || defined(VGA_mips64)
++ || defined(VGA_mips32) || defined(VGA_nanomips) || defined(VGA_mips64) \
++ || defined(VGA_loongarch64)
+ si_m->cfa_how = CFIC_IA_BPREL;
+ # elif defined(VGA_arm)
+ si_m->cfa_how = CFIC_ARM_R12REL;
+@@ -2786,6 +2798,30 @@ static Bool summarise_context(/*OUT*/Addr* base,
+ # elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le)
+ /* These don't use CFI based unwinding (is that really true?) */
-+#if defined(VGA_loongarch64)
++# elif defined(VGA_loongarch64)
++
++ /* --- entire tail of this fn specialised for loongarch64 --- */
++
++ SUMMARISE_HOW(si_m->ra_how, si_m->ra_off, ctxs->reg[ctx->ra_reg]);
++ SUMMARISE_HOW(si_m->fp_how, si_m->fp_off, ctxs->reg[FP_REG]);
++
++ /* on loongarch64, it seems the old sp value before the call is always
++ the same as the CFA. Therefore ... */
++ si_m->sp_how = CFIR_CFAREL;
++ si_m->sp_off = 0;
++
++ /* bogus looking range? Note, we require that the difference is
++ representable in 32 bits. */
++ if (loc_start >= ctx->loc)
++ { why = 4; goto failed; }
++ if (ctx->loc - loc_start > 10000000 /* let's say */)
++ { why = 5; goto failed; }
++
++ *base = loc_start + ctx->initloc;
++ *len = (UInt)(ctx->loc - loc_start);
++
++ return True;
++
+ # else
+ # error "Unknown arch"
+ # endif
+@@ -2885,6 +2921,13 @@ static Int copy_convert_CfiExpr_tree ( XArray* dstxa,
+ return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM64_X30 );
+ # elif defined(VGA_ppc32) || defined(VGA_ppc64be) \
+ || defined(VGA_ppc64le)
++# elif defined(VGA_loongarch64)
++ if (dwreg == SP_REG)
++ return ML_(CfiExpr_CfiReg)( dstxa, Creg_LOONGARCH64_SP );
++ if (dwreg == FP_REG)
++ return ML_(CfiExpr_CfiReg)( dstxa, Creg_LOONGARCH64_FP );
++ if (dwreg == srcuc->ra_reg)
++ return ML_(CfiExpr_CfiReg)( dstxa, Creg_LOONGARCH64_RA );
+ # else
+ # error "Unknown arch"
+ # endif
+diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c
+index da54804..9979ba1 100644
+--- a/coregrind/m_debuginfo/readelf.c
++++ b/coregrind/m_debuginfo/readelf.c
+@@ -1780,7 +1780,8 @@ static HChar* readlink_path (const HChar *path)
+
+ while (tries > 0) {
+ SysRes res;
+-#if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++#if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
+ (UWord)path, (UWord)buf, bufsiz);
+ #elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
+@@ -2705,6 +2706,7 @@ Bool ML_(read_elf_object) ( struct _DebugInfo* di )
+ || defined(VGP_arm_linux) || defined (VGP_s390x_linux) \
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
+ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux) \
+ || defined(VGP_x86_solaris) || defined(VGP_amd64_solaris) \
+ || defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd) \
+ || defined(VGP_arm64_freebsd)
+diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c
+index ef6a400..88eb1d6 100644
+--- a/coregrind/m_debuginfo/storage.c
++++ b/coregrind/m_debuginfo/storage.c
+@@ -260,6 +260,11 @@ void ML_(ppDiCfSI) ( const XArray* /* of CfiExpr */ exprs,
+ SHOW_HOW(si_m->x30_how, si_m->x30_off);
+ VG_(printf)(" X29=");
+ SHOW_HOW(si_m->x29_how, si_m->x29_off);
++# elif defined(VGP_loongarch64_linux)
++ VG_(printf)(" SP=");
++ SHOW_HOW(si_m->sp_how, si_m->sp_off);
++ VG_(printf)(" FP=");
++ SHOW_HOW(si_m->fp_how, si_m->fp_off);
+ # else
+ # error "Unknown arch"
+ # endif
+@@ -1010,6 +1015,10 @@ static void ppCfiReg ( CfiReg reg )
+ case Creg_S390_SP: VG_(printf)("SP"); break;
+ case Creg_S390_FP: VG_(printf)("FP"); break;
+ case Creg_S390_LR: VG_(printf)("LR"); break;
++ case Creg_LOONGARCH64_PC: VG_(printf)("PC"); break;
++ case Creg_LOONGARCH64_RA: VG_(printf)("RA"); break;
++ case Creg_LOONGARCH64_SP: VG_(printf)("SP"); break;
++ case Creg_LOONGARCH64_FP: VG_(printf)("FP"); break;
+ default: vg_assert(0);
+ }
+ }
+diff --git a/coregrind/m_debuglog.c b/coregrind/m_debuglog.c
+index cad95bc..eedfde7 100644
+--- a/coregrind/m_debuglog.c
++++ b/coregrind/m_debuglog.c
+@@ -637,6 +637,41 @@ static UInt local_sys_getpid ( void )
+ return a0;
+ }
+
++#elif defined(VGP_loongarch64_linux)
++
++static UInt local_sys_write_stderr ( const HChar* buf, Int n )
++{
++ ULong ret;
++ __asm__ volatile (
++ "li.w $a0, 2 \n\t" // stderr
++ "move $a1, %1 \n\t"
++ "move $a2, %2 \n\t"
++ "li.w $a7, " VG_STRINGIFY(__NR_write) " \n\t"
++ "syscall 0 \n\t"
++ "move %0, $a0 \n\t"
++ : "=r" (ret)
++ : "r" (buf), "r" (n)
++ : "memory", "$a0", "$a1", "$a2", "$a3", "$a4", "$a5", "$a6", "$a7",
++ "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8"
++ );
++ return ret >= 0 ? (UInt)ret : -1;
++}
++
++static UInt local_sys_getpid ( void )
++{
++ ULong ret;
++ __asm__ volatile (
++ "li.w $a7, " VG_STRINGIFY(__NR_getpid) " \n\t"
++ "syscall 0 \n\t"
++ "move %0, $a0 \n\t"
++ : "=r" (ret)
++ :
++ : "memory", "$a0", "$a1", "$a2", "$a3", "$a4", "$a5", "$a6", "$a7",
++ "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8"
++ );
++ return (UInt)ret;
++}
++
+ #elif defined(VGP_x86_solaris)
+ static UInt local_sys_write_stderr ( const HChar* buf, Int n )
+ {
+diff --git a/coregrind/m_dispatch/dispatch-loongarch64-linux.S b/coregrind/m_dispatch/dispatch-loongarch64-linux.S
+new file mode 100644
+index 0000000..dec1652
+--- /dev/null
++++ b/coregrind/m_dispatch/dispatch-loongarch64-linux.S
+@@ -0,0 +1,314 @@
++
++/*--------------------------------------------------------------------*/
++/*--- The core dispatch loop, for jumping to a code address. ---*/
++/*--- dispatch-loongarch64-linux.S ---*/
++/*--------------------------------------------------------------------*/
++
++/*
++ This file is part of Valgrind, a dynamic binary instrumentation
++ framework.
++
++ Copyright (C) 2021-2022 Loongson Technology Corporation Limited
++
++ This program is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License as
++ published by the Free Software Foundation; either version 2 of the
++ License, or (at your option) any later version.
++
++ This program is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, see .
+
-+/*
-+ * Initialize hwcaps by parsing /proc/cpuinfo. Returns False if it can not
-+ * determine what CPU it is (it searches only for the models that are or may be
-+ * supported by Valgrind).
-+ */
-+static Bool VG_(parse_cpuinfo)(void)
-+{
-+ Int n, fh;
-+ SysRes fd;
-+ SizeT num_bytes, file_buf_size;
-+ HChar *file_buf;
++ The GNU General Public License is contained in the file COPYING.
++*/
+
-+ const char *search_Loongson_str = "Model Name\t\t: Loongson";
++#include "pub_core_basics_asm.h"
+
-+ /* Slurp contents of /proc/cpuinfo into FILE_BUF */
-+ fd = VG_(open)("/proc/cpuinfo", 0, VKI_S_IRUSR);
-+ if (sr_isError(fd))
-+ return False;
++#if defined(VGP_loongarch64_linux)
+
-+ fh = sr_Res(fd);
++#include "pub_core_dispatch_asm.h"
++#include "pub_core_transtab_asm.h"
++#include "libvex_guest_offsets.h" /* for OFFSET_loongarch64_* */
+
-+ /* Determine the size of /proc/cpuinfo.
-+ Work around broken-ness in /proc file system implementation.
-+ fstat returns a zero size for /proc/cpuinfo although it is
-+ claimed to be a regular file. */
-+ num_bytes = 0;
-+ file_buf_size = 1000;
-+ file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1);
-+ while (True) {
-+ n = VG_(read)(fh, file_buf, file_buf_size);
-+ if (n < 0)
-+ break;
+
-+ num_bytes += n;
-+ if (n < file_buf_size)
-+ break; /* reached EOF */
-+ }
++/*------------------------------------------------------------*/
++/*--- ---*/
++/*--- The dispatch loop. VG_(disp_run_translations) is ---*/
++/*--- used to run all translations, ---*/
++/*--- including no-redir ones. ---*/
++/*--- ---*/
++/*------------------------------------------------------------*/
+
-+ if (n < 0)
-+ num_bytes = 0; /* read error; ignore contents */
++/*----------------------------------------------------*/
++/*--- Entry and preamble (set everything up) ---*/
++/*----------------------------------------------------*/
+
-+ if (num_bytes > file_buf_size) {
-+ VG_(free)(file_buf);
-+ VG_(lseek)(fh, 0, VKI_SEEK_SET);
-+ file_buf = VG_(malloc)("cpuinfo", num_bytes + 1);
-+ n = VG_(read)(fh, file_buf, num_bytes);
-+ if (n < 0)
-+ num_bytes = 0;
-+ }
++/* signature:
++void VG_(disp_run_translations)( UWord* two_words,
++ void* guest_state,
++ Addr host_addr );
++*/
+
-+ file_buf[num_bytes] = '\0';
-+ VG_(close)(fh);
++.text
++.globl VG_(disp_run_translations)
++VG_(disp_run_translations):
++ /* a0 holds two_words */
++ /* a1 holds guest_state */
++ /* a2 holds host_addr */
+
-+ /* Parse file */
-+ vai.hwcaps = 0;
-+ if (VG_(strstr)(file_buf, search_Loongson_str) == NULL) {
-+ /* Did not find string in the proc file. */
-+ VG_(free)(file_buf);
-+ return False;
-+ }
++ /* New stack frame. Stack must remain 16 aligned (at least) */
++ addi.d $sp, $sp, -96
+
-+ if (VG_(strstr)(file_buf, "loongarch32") != NULL)
-+ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_ISA_32BIT;
-+ if (VG_(strstr)(file_buf, "loongarch64") != NULL)
-+ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_ISA_64BIT;
++ /* Save ra */
++ st.d $ra, $sp, 0
+
-+ if (VG_(strstr)(file_buf, "cpucfg") != NULL)
-+ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_CPUCFG;
-+ if (VG_(strstr)(file_buf, "lam") != NULL)
-+ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_LAM;
-+ if (VG_(strstr)(file_buf, "ual") != NULL)
-+ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_UAL;
-+ if (VG_(strstr)(file_buf, "fpu") != NULL)
-+ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_FP;
-+ if (VG_(strstr)(file_buf, "lsx") != NULL)
-+ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_LSX;
-+ if (VG_(strstr)(file_buf, "lasx") != NULL)
-+ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_LASX;
-+ if (VG_(strstr)(file_buf, "complex") != NULL)
-+ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_COMPLEX;
-+ if (VG_(strstr)(file_buf, "crypto") != NULL)
-+ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_CRYPTO;
-+ if (VG_(strstr)(file_buf, "lvz") != NULL)
-+ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_LVZP;
-+ if (VG_(strstr)(file_buf, "lbt_x86") != NULL)
-+ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_X86BT;
-+ if (VG_(strstr)(file_buf, "lbt_arm") != NULL)
-+ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_ARMBT;
-+ if (VG_(strstr)(file_buf, "lbt_mips") != NULL)
-+ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_MIPSBT;
++ /* .. and s0 - s8 */
++ st.d $s0, $sp, 8
++ st.d $s1, $sp, 16
++ st.d $s2, $sp, 24
++ st.d $s3, $sp, 32
++ st.d $s4, $sp, 40
++ st.d $s5, $sp, 48
++ st.d $s6, $sp, 56
++ st.d $s7, $sp, 64
++ st.d $s8, $sp, 72
+
-+ VG_(free)(file_buf);
-+ return True;
-+}
++ /* ... and fp */
++ st.d $fp, $sp, 80
+
-+#endif /* defined(VGP_loongarch64) */
++ /* and a0. In postamble it will be restored such that the
++ return values can be written */
++ st.d $a0, $sp, 88
+
- Bool VG_(machine_get_hwcaps)( void )
- {
- vg_assert(hwcaps_done == False);
-@@ -2230,6 +2369,54 @@ Bool VG_(machine_get_hwcaps)( void )
-
- return True;
- }
++ /* Load address of guest state into s8 */
++ move $s8, $a1
+
-+#elif defined(VGA_loongarch64)
-+ {
-+ va = VexArchLOONGARCH64;
-+ vai.endness = VexEndnessLE;
-+ vai.hwcaps = 0;
++ /* and jump into the code cache. Chained translations in
++ the code cache run, until for whatever reason, they can't
++ continue. When that happens, the translation in question
++ will jump (or call) to one of the continuation points
++ VG_(cp_...) below. */
++ ibar 0 /* Insn sync barrier */
++ jr $a2
++ /*NOTREACHED*/
+
-+ if (!VG_(parse_cpuinfo)())
-+ return False;
++/*----------------------------------------------------*/
++/*--- Postamble and exit. ---*/
++/*----------------------------------------------------*/
+
-+ /* Same instruction set detection algorithm as for ppc32/arm... */
-+ vki_sigset_t saved_set, tmp_set;
-+ vki_sigaction_fromK_t saved_sigill_act;
-+ vki_sigaction_toK_t tmp_sigill_act;
++postamble:
++ /* At this point, a0 and a1 contain two
++ words to be returned to the caller. a0
++ holds a TRC value, and a1 optionally may
++ hold another word (for CHAIN_ME exits, the
++ address of the place to patch.) */
+
-+ vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
++ /* Restore a0 from stack to t0; holds address of two_words */
++ ld.d $t0, $sp, 88
++ st.d $a0, $t0, 0 /* Store a0 to two_words[0] */
++ st.d $a1, $t0, 8 /* Store a1 to two_words[1] */
+
-+ VG_(sigemptyset)(&tmp_set);
-+ VG_(sigaddset)(&tmp_set, VKI_SIGILL);
++ /* Restore ra */
++ ld.d $ra, $sp, 0
+
-+ Int r;
-+ r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
-+ vg_assert(r == 0);
++ /* ... and s0 - s8 */
++ ld.d $s0, $sp, 8
++ ld.d $s1, $sp, 16
++ ld.d $s2, $sp, 24
++ ld.d $s3, $sp, 32
++ ld.d $s4, $sp, 40
++ ld.d $s5, $sp, 48
++ ld.d $s6, $sp, 56
++ ld.d $s7, $sp, 64
++ ld.d $s8, $sp, 72
+
-+ r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
-+ vg_assert(r == 0);
-+ tmp_sigill_act = saved_sigill_act;
++ /* ... and fp */
++ ld.d $fp, $sp, 80
+
-+ /* NODEFER: signal handler does not return (from the kernel's point of
-+ view), hence if it is to successfully catch a signal more than once,
-+ we need the NODEFER flag. */
-+ tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
-+ tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
-+ tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
-+ tmp_sigill_act.ksa_handler = handler_unsup_insn;
-+ VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
++ addi.d $sp, $sp, 96 /* Restore sp */
++ jr $ra
++ /*NOTREACHED*/
+
-+ VG_(convert_sigaction_fromK_to_toK)(&saved_sigill_act, &tmp_sigill_act);
-+ VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
-+ VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
++/*----------------------------------------------------*/
++/*--- Continuation points ---*/
++/*----------------------------------------------------*/
+
-+ VG_(debugLog)(1, "machine", "hwcaps = 0x%x\n", vai.hwcaps);
++/* ------ Chain me to slow entry point ------ */
++.globl VG_(disp_cp_chain_me_to_slowEP)
++VG_(disp_cp_chain_me_to_slowEP):
++ /* We got called. The return address indicates
++ where the patching needs to happen. Collect
++ the return address and, exit back to C land,
++ handing the caller the pair (Chain_me_S, RA) */
++ li.w $a0, VG_TRC_CHAIN_ME_TO_SLOW_EP
++ move $a1, $ra
++ /* 4 * 4 = mkLoadImm_EXACTLY4
++ 4 = jirl $ra, $t0, 0 */
++ addi.d $a1, $a1, -20
++ b postamble
++ /*NOTREACHED*/
+
-+ VG_(machine_get_cache_info)(&vai);
++/* ------ Chain me to fast entry point ------ */
++.globl VG_(disp_cp_chain_me_to_fastEP)
++VG_(disp_cp_chain_me_to_fastEP):
++ /* We got called. The return address indicates
++ where the patching needs to happen. Collect
++ the return address and, exit back to C land,
++ handing the caller the pair (Chain_me_S, RA) */
++ li.w $a0, VG_TRC_CHAIN_ME_TO_FAST_EP
++ move $a1, $ra
++ /* 4 * 4 = mkLoadImm_EXACTLY4
++ 4 = jirl $ra, $t0, 0 */
++ addi.d $a1, $a1, -20
++ b postamble
++ /*NOTREACHED*/
+
-+ return True;
-+ }
++/* ------ Indirect but boring jump ------ */
++.globl VG_(disp_cp_xindir)
++VG_(disp_cp_xindir):
++ /* Where are we going? */
++ ld.d $t0, $s8, OFFSET_loongarch64_PC
+
- #else
- # error "Unknown arch"
- #endif
-@@ -2370,6 +2557,9 @@ Int VG_(machine_get_size_of_largest_guest_register) ( void )
- # elif defined(VGA_mips64)
- return 8;
-
-+# elif defined(VGA_loongarch64)
-+ return 8;
++ /* Stats only */
++ la.local $t4, VG_(stats__n_xIndirs_32)
++ ld.d $t1, $t4, 0
++ addi.d $t1, $t1, 1
++ st.w $t1, $t4, 0
+
- # else
- # error "Unknown arch"
- # endif
-@@ -2386,7 +2576,7 @@ void* VG_(fnptr_to_fnentry)( void* f )
- || defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \
- || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
- || defined(VGP_x86_solaris) || defined(VGP_amd64_solaris) \
-- || defined(VGP_nanomips_linux)
-+ || defined(VGP_nanomips_linux) || defined(VGP_loongarch64_linux)
- return f;
- # elif defined(VGP_ppc64be_linux)
- /* ppc64-linux uses the AIX scheme, in which f is a pointer to a
-diff --git a/coregrind/m_main.c b/coregrind/m_main.c
-index bb4a0ca..b2b7415 100644
---- a/coregrind/m_main.c
-+++ b/coregrind/m_main.c
-@@ -1481,6 +1481,7 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp )
- "AMD Athlon or above)\n");
- VG_(printf)(" * AMD Athlon64/Opteron\n");
- VG_(printf)(" * ARM (armv7)\n");
-+ VG_(printf)(" * LoongArch (3A5000 and above)\n");
- VG_(printf)(" * MIPS (mips32 and above; mips64 and above)\n");
- VG_(printf)(" * PowerPC (most; ppc405 and above)\n");
- VG_(printf)(" * System z (64bit only - s390x; z990 and above)\n");
-@@ -2536,6 +2537,11 @@ static void final_tidyup(ThreadId tid)
- VG_TRACK(post_reg_write, Vg_CoreClientReq, tid,
- offsetof(VexGuestS390XState, guest_r2),
- sizeof(VG_(threads)[tid].arch.vex.guest_r2));
-+# elif defined(VGA_loongarch64)
-+ VG_(threads)[tid].arch.vex.guest_R4 = to_run;
-+ VG_TRACK(post_reg_write, Vg_CoreClientReq, tid,
-+ offsetof(VexGuestLOONGARCH64State, guest_R4),
-+ sizeof(VG_(threads)[tid].arch.vex.guest_R4));
- #else
- I_die_here : architecture missing in m_main.c
- #endif
-@@ -3064,6 +3070,29 @@ asm(
- ".set pop \n\t"
- ".previous \n\t"
- );
-+#elif defined(VGP_loongarch64_linux)
-+asm(" \n\t"
-+ ".text \n\t"
-+ ".globl _start \n\t"
-+ ".type _start,@function \n\t"
-+ "_start: \n\t"
-+ /* t0 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
-+ VG_DEFAULT_STACK_ACTIVE_SZB */
-+ "la.local $t0, vgPlain_interim_stack \n\t"
-+ "li.w $t1, "VG_STRINGIFY(VG_STACK_GUARD_SZB)" \n\t"
-+ "add.d $t0, $t0, $t1 \n\t"
-+ "li.w $t2, "VG_STRINGIFY(VG_DEFAULT_STACK_ACTIVE_SZB)" \n\t"
-+ "add.d $t0, $t0, $t2 \n\t"
-+ /* allocate 16 bytes on the new stack in t0, and aligned */
-+ "addi.d $t0, $t0, -16 \n\t"
-+ "bstrins.d $t0, $zero, 3, 0 \n\t"
-+ /* a0 = sp, sp = t0, and then call _start_in_C_linux */
-+ "move $a0, $sp \n\t"
-+ "move $sp, $t0 \n\t"
-+ "la.local $t0, _start_in_C_linux \n\t"
-+ "jr $t0 \n\t"
-+ ".previous \n\t"
-+);
- #else
- # error "Unknown platform"
- #endif
-@@ -3109,11 +3138,11 @@ void _start_in_C_linux ( UWord* pArgc )
- # if defined(VGP_ppc32_linux) || defined(VGP_ppc64be_linux) \
- || defined(VGP_ppc64le_linux) || defined(VGP_arm64_linux) \
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
-- || defined(VGP_nanomips_linux)
-+ || defined(VGP_nanomips_linux) || defined(VGP_loongarch64_linux)
- {
-- /* ppc32/ppc64, arm64, mips32/64 can be configured with different
-- page sizes. Determine this early. This is an ugly hack and really
-- should be moved into valgrind_main. */
-+ /* ppc32/ppc64, arm64, mips32/64, loongarch64 can be configured with
-+ different page sizes. Determine this early. This is an ugly hack
-+ and really should be moved into valgrind_main. */
- UWord *sp = &pArgc[1+argc+1];
- while (*sp++ != 0)
- ;
-diff --git a/coregrind/m_options.c b/coregrind/m_options.c
-index 1483af2..640af71 100644
---- a/coregrind/m_options.c
-+++ b/coregrind/m_options.c
-@@ -203,7 +203,8 @@ UInt VG_(clo_unw_stack_scan_frames) = 5;
- VgSmc VG_(clo_smc_check) = Vg_SmcAllNonFile;
- #elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
- || defined(VGA_arm) || defined(VGA_arm64) \
-- || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips)
-+ || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips) \
-+ || defined(VGA_loongarch64)
- VgSmc VG_(clo_smc_check) = Vg_SmcStack;
- #else
- # error "Unknown arch"
-diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c
-index cef241b..fa513a0 100644
---- a/coregrind/m_redir.c
-+++ b/coregrind/m_redir.c
-@@ -1240,6 +1240,7 @@ Bool VG_(is_soname_ld_so) (const HChar *soname)
- if (VG_STREQ(soname, VG_U_LD_LINUX_AARCH64_SO_1)) return True;
- if (VG_STREQ(soname, VG_U_LD_LINUX_ARMHF_SO_3)) return True;
- if (VG_STREQ(soname, VG_U_LD_LINUX_MIPSN8_S0_1)) return True;
-+ if (VG_STREQ(soname, VG_U_LD_LINUX_LOONGARCH_LP64D_SO_1)) return True;
- # elif defined(VGO_freebsd)
- if (VG_STREQ(soname, VG_U_LD_ELF_SO_1)) return True;
- if (VG_STREQ(soname, VG_U_LD_ELF32_SO_1)) return True;
-@@ -1679,6 +1680,22 @@ void VG_(redir_initialise) ( void )
- );
- }
-
-+#elif defined(VGP_loongarch64_linux)
-+ /* If we're using memcheck, use these intercepts right from
-+ the start, otherwise ld.so makes a lot of noise. */
-+ if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
-+ add_hardwired_spec(
-+ "ld-linux-loongarch-lp64d.so.1", "strlen",
-+ (Addr)&VG_(loongarch64_linux_REDIR_FOR_strlen),
-+ complain_about_stripped_glibc_ldso
-+ );
-+ add_hardwired_spec(
-+ "ld-linux-loongarch-lp64d.so.1", "strchr",
-+ (Addr)&VG_(loongarch64_linux_REDIR_FOR_strchr),
-+ complain_about_stripped_glibc_ldso
-+ );
-+ }
++ /* LIVE: s8 (guest state ptr), t0 (guest address to go to).
++ We use 6 temporaries:
++ t6 (to point at the relevant FastCacheSet),
++ t1, t2, t3 (scratch, for swapping entries within a set)
++ t4, t5 (other scratch)
++ */
+
- # elif defined(VGP_x86_solaris)
- /* If we're using memcheck, use these intercepts right from
- the start, otherwise ld.so makes a lot of noise. */
-diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c
-index f8b3b46..e3b3b63 100644
---- a/coregrind/m_scheduler/scheduler.c
-+++ b/coregrind/m_scheduler/scheduler.c
-@@ -271,6 +271,7 @@ const HChar* name_of_sched_event ( UInt event )
- case VEX_TRC_JMP_SIGBUS: return "SIGBUS";
- case VEX_TRC_JMP_SIGFPE_INTOVF:
- case VEX_TRC_JMP_SIGFPE_INTDIV: return "SIGFPE";
-+ case VEX_TRC_JMP_SIGSYS: return "SIGSYS";
- case VEX_TRC_JMP_EMWARN: return "EMWARN";
- case VEX_TRC_JMP_EMFAIL: return "EMFAIL";
- case VEX_TRC_JMP_CLIENTREQ: return "CLIENTREQ";
-@@ -1657,6 +1658,10 @@ VgSchedReturnCode VG_(scheduler) ( ThreadId tid )
- VG_(synth_sigfpe)(tid, VKI_FPE_INTOVF);
- break;
-
-+ case VEX_TRC_JMP_SIGSYS:
-+ VG_(synth_sigsys)(tid);
-+ break;
++ /* Try a fast lookup in the translation cache. This is pretty much
++ a handcoded version of VG_(lookupInFastCache). */
++
++ // Compute t6 = VG_TT_FAST_HASH(guest)
++ srli.d $t6, $t0, 2 // g2 = guest >> 2
++ srli.d $t5, $t0, (VG_TT_FAST_BITS + 2) // (g2 >> VG_TT_FAST_BITS)
++ xor $t6, $t6, $t5 // (g2 >> VG_TT_FAST_BITS) ^ g2
++ li.w $t5, VG_TT_FAST_MASK
++ and $t6, $t6, $t5 // setNo
++
++ // Compute t6 = &VG_(tt_fast)[t6]
++ la.local $t5, VG_(tt_fast)
++ slli.d $t6, $t6, VG_FAST_CACHE_SET_BITS
++ add.d $t6, $t6, $t5
++
++ /* LIVE: s8 (guest state ptr), t0 (guest addr), t6 (cache set) */
++0: // try way 0
++ ld.d $t4, $t6, FCS_g0 // .guest0
++ ld.d $t5, $t6, FCS_h0 // .host0
++ bne $t4, $t0, 1f // cmp against .guest0
++ // hit at way 0
++ // goto .host0
++ jr $t5
++ /*NOTREACHED*/
++
++1: // try way 1
++ ld.d $t4, $t6, FCS_g1
++ bne $t4, $t0, 2f // cmp against .guest1
++ // hit at way 1; swap upwards
++ ld.d $t1, $t6, FCS_g0 // $t1 = old .guest0
++ ld.d $t2, $t6, FCS_h0 // $t2 = old .host0
++ ld.d $t3, $t6, FCS_h1 // $t3 = old .host1
++ st.d $t0, $t6, FCS_g0 // new .guest0 = guest
++ st.d $t3, $t6, FCS_h0 // new .host0 = old .host1
++ st.d $t1, $t6, FCS_g1 // new .guest1 = old .guest0
++ st.d $t2, $t6, FCS_h1 // new .host1 = old .host0
++
++ // stats only
++ la.local $t4, VG_(stats__n_xIndir_hits1_32)
++ ld.d $t5, $t4, 0
++ addi.d $t5, $t5, 1
++ st.w $t5, $t4, 0
++ // goto old .host1 a.k.a. new .host0
++ jr $t3
++ /*NOTREACHED*/
++
++2: // try way 2
++ ld.d $t4, $t6, FCS_g2
++ bne $t4, $t0, 3f // cmp against .guest2
++ // hit at way 2; swap upwards
++ ld.d $t1, $t6, FCS_g1
++ ld.d $t2, $t6, FCS_h1
++ ld.d $t3, $t6, FCS_h2
++ st.d $t0, $t6, FCS_g1
++ st.d $t3, $t6, FCS_h1
++ st.d $t1, $t6, FCS_g2
++ st.d $t2, $t6, FCS_h2
++
++ // stats only
++ la.local $t4, VG_(stats__n_xIndir_hits2_32)
++ ld.d $t5, $t4, 0
++ addi.d $t5, $t5, 1
++ st.w $t5, $t4, 0
++ // goto old .host2 a.k.a. new .host1
++ jr $t3
++ /*NOTREACHED*/
++
++3: // try way 3
++ ld.d $t4, $t6, FCS_g3
++ bne $t4, $t0, 4f // cmp against .guest3
++ // hit at way 3; swap upwards
++ ld.d $t1, $t6, FCS_g2
++ ld.d $t2, $t6, FCS_h2
++ ld.d $t3, $t6, FCS_h3
++ st.d $t0, $t6, FCS_g2
++ st.d $t3, $t6, FCS_h2
++ st.d $t1, $t6, FCS_g3
++ st.d $t2, $t6, FCS_h3
++
++ // stats only
++ la.local $t4, VG_(stats__n_xIndir_hits3_32)
++ ld.d $t5, $t4, 0
++ addi.d $t5, $t5, 1
++ st.w $t5, $t4, 0
++ // goto old .host3 a.k.a. new .host2
++ jr $t3
++ /*NOTREACHED*/
++
++4: // fast lookup failed:
++ /* stats only */
++ la.local $t4, VG_(stats__n_xIndir_misses_32)
++ ld.d $t5, $t4, 0
++ addi.d $t5, $t5, 1
++ st.w $t5, $t4, 0
++
++ li.w $a0, VG_TRC_INNER_FASTMISS
++ move $a1, $zero
++ b postamble
++ /*NOTREACHED*/
++
++/* ------ Assisted jump ------ */
++.globl VG_(disp_cp_xassisted)
++VG_(disp_cp_xassisted):
++ /* guest-state-pointer contains the TRC. Put the value into the
++ return register */
++ move $a0, $s8
++ move $a1, $zero
++ b postamble
+
- case VEX_TRC_JMP_NODECODE: {
- Addr addr = VG_(get_IP)(tid);
-
-@@ -1821,6 +1826,9 @@ void VG_(nuke_all_threads_except) ( ThreadId me, VgSchedReturnCode src )
- #elif defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips)
- # define VG_CLREQ_ARGS guest_r12
- # define VG_CLREQ_RET guest_r11
-+#elif defined(VGA_loongarch64)
-+# define VG_CLREQ_ARGS guest_R12
-+# define VG_CLREQ_RET guest_R11
- #else
- # error Unknown arch
- #endif
-diff --git a/coregrind/m_sigframe/sigframe-loongarch64-linux.c b/coregrind/m_sigframe/sigframe-loongarch64-linux.c
-new file mode 100644
-index 0000000..eda6c88
---- /dev/null
-+++ b/coregrind/m_sigframe/sigframe-loongarch64-linux.c
-@@ -0,0 +1,285 @@
++/* ------ Event check failed ------ */
++.globl VG_(disp_cp_evcheck_fail)
++VG_(disp_cp_evcheck_fail):
++ li.w $a0, VG_TRC_INNER_COUNTERZERO
++ move $a1, $zero
++ b postamble
++
++.size VG_(disp_run_translations), .-VG_(disp_run_translations)
++
++#endif // defined(VGP_loongarch64_linux)
++
++/* Let the linker know we don't need an executable stack */
++MARK_STACK_NO_EXEC
+
+/*--------------------------------------------------------------------*/
-+/*--- Create/destroy signal delivery frames. ---*/
-+/*--- sigframe-loongarch64-linux.c ---*/
++/*--- end dispatch-loongarch64-linux.S ---*/
+/*--------------------------------------------------------------------*/
+diff --git a/coregrind/m_gdbserver/loongarch-base64-valgrind-s1.xml b/coregrind/m_gdbserver/loongarch-base64-valgrind-s1.xml
+new file mode 100644
+index 0000000..cab700c
+--- /dev/null
++++ b/coregrind/m_gdbserver/loongarch-base64-valgrind-s1.xml
+@@ -0,0 +1,45 @@
++
++
+
-+ Copyright (C) 2021-2022 Loongson Technology Corporation Limited
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
+diff --git a/coregrind/m_gdbserver/loongarch-base64-valgrind-s2.xml b/coregrind/m_gdbserver/loongarch-base64-valgrind-s2.xml
+new file mode 100644
+index 0000000..cbacbbb
+--- /dev/null
++++ b/coregrind/m_gdbserver/loongarch-base64-valgrind-s2.xml
+@@ -0,0 +1,45 @@
++
++
+
-+ This program is distributed in the hope that it will be useful, but
-+ WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ General Public License for more details.
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
+diff --git a/coregrind/m_gdbserver/loongarch-base64.xml b/coregrind/m_gdbserver/loongarch-base64.xml
+new file mode 100644
+index 0000000..fadca8b
+--- /dev/null
++++ b/coregrind/m_gdbserver/loongarch-base64.xml
+@@ -0,0 +1,45 @@
++
++
+
-+ The GNU General Public License is contained in the file COPYING.
-+*/
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
+diff --git a/coregrind/m_gdbserver/loongarch-fpu64-valgrind-s1.xml b/coregrind/m_gdbserver/loongarch-fpu64-valgrind-s1.xml
+new file mode 100644
+index 0000000..b5c7cab
+--- /dev/null
++++ b/coregrind/m_gdbserver/loongarch-fpu64-valgrind-s1.xml
+@@ -0,0 +1,57 @@
++
++
+
-+#include "pub_core_basics.h"
-+#include "pub_core_vki.h"
-+#include "pub_core_vkiscnums.h"
-+#include "pub_core_threadstate.h"
-+#include "pub_core_aspacemgr.h"
-+#include "pub_core_libcbase.h"
-+#include "pub_core_libcassert.h"
-+#include "pub_core_libcprint.h"
-+#include "pub_core_machine.h"
-+#include "pub_core_options.h"
-+#include "pub_core_sigframe.h"
-+#include "pub_core_signals.h"
-+#include "pub_core_tooliface.h"
-+#include "pub_core_trampoline.h"
-+#include "priv_sigframe.h"
++
++
+
++
++
++
++
+
-+/*------------------------------------------------------------*/
-+/*--- Signal frame layouts ---*/
-+/*------------------------------------------------------------*/
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
+diff --git a/coregrind/m_gdbserver/loongarch-fpu64-valgrind-s2.xml b/coregrind/m_gdbserver/loongarch-fpu64-valgrind-s2.xml
+new file mode 100644
+index 0000000..501660e
+--- /dev/null
++++ b/coregrind/m_gdbserver/loongarch-fpu64-valgrind-s2.xml
+@@ -0,0 +1,57 @@
++
++
+
-+struct rt_sigframe {
-+ struct vki_siginfo rs_info;
-+ struct vki_ucontext rs_uctx;
-+ struct vg_sig_private priv;
-+};
++
++
+
++
++
++
++
+
-+/*------------------------------------------------------------*/
-+/*--- Creating signal frames ---*/
-+/*------------------------------------------------------------*/
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
+diff --git a/coregrind/m_gdbserver/loongarch-fpu64.xml b/coregrind/m_gdbserver/loongarch-fpu64.xml
+new file mode 100644
+index 0000000..74ab55a
+--- /dev/null
++++ b/coregrind/m_gdbserver/loongarch-fpu64.xml
+@@ -0,0 +1,57 @@
++
++
+
-+ VG_(memcpy)(&frame->rs_info, si, sizeof(vki_siginfo_t));
++
++
+
-+ VG_TRACK(post_mem_write, Vg_CoreSignal, tid,
-+ (Addr)&frame->rs_info, sizeof(frame->rs_info));
-+}
++
++
++
++
+
-+static void create_sigcontext ( ThreadState *tst,
-+ struct vki_sigcontext **sc)
-+{
-+ struct vki_sigcontext *sctx = *sc;
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
++
+diff --git a/coregrind/m_gdbserver/loongarch64-linux-valgrind.xml b/coregrind/m_gdbserver/loongarch64-linux-valgrind.xml
+new file mode 100644
+index 0000000..8915a72
+--- /dev/null
++++ b/coregrind/m_gdbserver/loongarch64-linux-valgrind.xml
+@@ -0,0 +1,18 @@
++
++
+
-+ sctx->sc_regs[1] = tst->arch.vex.guest_R1;
-+ sctx->sc_regs[2] = tst->arch.vex.guest_R2;
-+ sctx->sc_regs[3] = tst->arch.vex.guest_R3;
-+ sctx->sc_regs[4] = tst->arch.vex.guest_R4;
-+ sctx->sc_regs[5] = tst->arch.vex.guest_R5;
-+ sctx->sc_regs[6] = tst->arch.vex.guest_R6;
-+ sctx->sc_regs[7] = tst->arch.vex.guest_R7;
-+ sctx->sc_regs[8] = tst->arch.vex.guest_R8;
-+ sctx->sc_regs[9] = tst->arch.vex.guest_R9;
-+ sctx->sc_regs[10] = tst->arch.vex.guest_R10;
-+ sctx->sc_regs[11] = tst->arch.vex.guest_R11;
-+ sctx->sc_regs[12] = tst->arch.vex.guest_R12;
-+ sctx->sc_regs[13] = tst->arch.vex.guest_R13;
-+ sctx->sc_regs[14] = tst->arch.vex.guest_R14;
-+ sctx->sc_regs[15] = tst->arch.vex.guest_R15;
-+ sctx->sc_regs[16] = tst->arch.vex.guest_R16;
-+ sctx->sc_regs[17] = tst->arch.vex.guest_R17;
-+ sctx->sc_regs[18] = tst->arch.vex.guest_R18;
-+ sctx->sc_regs[19] = tst->arch.vex.guest_R19;
-+ sctx->sc_regs[20] = tst->arch.vex.guest_R20;
-+ sctx->sc_regs[21] = tst->arch.vex.guest_R21;
-+ sctx->sc_regs[22] = tst->arch.vex.guest_R22;
-+ sctx->sc_regs[23] = tst->arch.vex.guest_R23;
-+ sctx->sc_regs[24] = tst->arch.vex.guest_R24;
-+ sctx->sc_regs[25] = tst->arch.vex.guest_R25;
-+ sctx->sc_regs[26] = tst->arch.vex.guest_R26;
-+ sctx->sc_regs[27] = tst->arch.vex.guest_R27;
-+ sctx->sc_regs[28] = tst->arch.vex.guest_R28;
-+ sctx->sc_regs[29] = tst->arch.vex.guest_R29;
-+ sctx->sc_regs[30] = tst->arch.vex.guest_R30;
-+ sctx->sc_regs[31] = tst->arch.vex.guest_R31;
-+ sctx->sc_pc = tst->arch.vex.guest_PC;
-+}
++
++
++ loongarch
++ GNU/Linux
++
++
++
++
++
++
++
+diff --git a/coregrind/m_gdbserver/loongarch64-linux.xml b/coregrind/m_gdbserver/loongarch64-linux.xml
+new file mode 100644
+index 0000000..f1eed83
+--- /dev/null
++++ b/coregrind/m_gdbserver/loongarch64-linux.xml
+@@ -0,0 +1,14 @@
++
++
+
-+ uc->uc_flags = 0;
-+ uc->uc_link = 0;
-+ uc->uc_stack = tst->altstack;
-+ uc->uc_sigmask = *mask;
++
++
++ loongarch
++ GNU/Linux
++
++
++
+diff --git a/coregrind/m_gdbserver/target.c b/coregrind/m_gdbserver/target.c
+index f9f32f4..e97bd64 100644
+--- a/coregrind/m_gdbserver/target.c
++++ b/coregrind/m_gdbserver/target.c
+@@ -867,6 +867,8 @@ void valgrind_initialize_target(void)
+ mips64_init_architecture(&the_low_target);
+ #elif defined(VGA_nanomips)
+ nanomips_init_architecture(&the_low_target);
++#elif defined(VGA_loongarch64)
++ loongarch64_init_architecture(&the_low_target);
+ #else
+ #error "architecture missing in target.c valgrind_initialize_target"
+ #endif
+diff --git a/coregrind/m_gdbserver/valgrind-low-loongarch64.c b/coregrind/m_gdbserver/valgrind-low-loongarch64.c
+new file mode 100644
+index 0000000..6021c79
+--- /dev/null
++++ b/coregrind/m_gdbserver/valgrind-low-loongarch64.c
+@@ -0,0 +1,272 @@
++/* Low level interface to valgrind, for the remote server for GDB integrated
++ in valgrind.
++ Copyright (C) 2021
++ Free Software Foundation, Inc.
+
-+ VG_TRACK(post_mem_write, Vg_CoreSignal, tid, (Addr)uc,
-+ offsetof(struct vki_ucontext, uc_mcontext));
++ This file is part of VALGRIND.
++ It has been inspired from files from gdbserver in gdb 13.
+
-+ create_sigcontext(tst, sc);
-+}
++ This program is free software; you can redistribute it and/or modify
++ it under the terms of the GNU General Public License as published by
++ the Free Software Foundation; either version 2 of the License, or
++ (at your option) any later version.
+
-+/* EXPORTED */
-+void VG_(sigframe_create) ( ThreadId tid,
-+ Bool on_altstack,
-+ Addr sp_top_of_frame,
-+ const vki_siginfo_t *siginfo,
-+ const struct vki_ucontext *siguc,
-+ void *handler,
-+ UInt flags,
-+ const vki_sigset_t *mask,
-+ void *restorer )
-+{
-+ UInt size = sizeof(struct rt_sigframe);
-+ Addr sp = VG_ROUNDDN(sp_top_of_frame - size, 16);
++ This program is distributed in the hope that it will be useful,
++ but WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ GNU General Public License for more details.
+
-+ ThreadState *tst = VG_(get_ThreadState)(tid);
-+ if (! ML_(sf_maybe_extend_stack)(tst, sp, size, flags))
-+ return;
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, write to the Free Software
++ Foundation, Inc., 51 Franklin Street, Fifth Floor,
++ Boston, MA 02110-1301, USA. */
+
-+ struct rt_sigframe *frame = (struct rt_sigframe *)sp;
-+ create_siginfo(tid, frame, siginfo);
++#include "server.h"
++#include "target.h"
++#include "regdef.h"
++#include "regcache.h"
+
-+ struct vki_ucontext *uctx = &frame->rs_uctx;
-+ struct vki_sigcontext *sctx = &(frame->rs_uctx.uc_mcontext);
-+ create_ucontext(tst, tid, uctx, mask, &sctx, siginfo);
++#include "pub_core_machine.h"
++#include "pub_core_debuginfo.h"
++#include "pub_core_threadstate.h"
++#include "pub_core_transtab.h"
++#include "pub_core_gdbserver.h"
+
-+ /*
-+ Arguments to signal handler:
++#include "valgrind_low.h"
+
-+ a0 = signal number
-+ a1 = pointer to siginfo
-+ a2 = pointer to ucontext
++#include "libvex_guest_loongarch64.h"
+
-+ csr_era point to the signal handler, $r3 (sp) points to
-+ the struct rt_sigframe.
-+ */
++static struct reg regs[] = {
++ { "r0", 0, 64 },
++ { "r1", 64, 64 },
++ { "r2", 128, 64 },
++ { "r3", 192, 64 },
++ { "r4", 256, 64 },
++ { "r5", 320, 64 },
++ { "r6", 384, 64 },
++ { "r7", 448, 64 },
++ { "r8", 512, 64 },
++ { "r9", 576, 64 },
++ { "r10", 640, 64 },
++ { "r11", 704, 64 },
++ { "r12", 768, 64 },
++ { "r13", 832, 64 },
++ { "r14", 896, 64 },
++ { "r15", 960, 64 },
++ { "r16", 1024, 64 },
++ { "r17", 1088, 64 },
++ { "r18", 1152, 64 },
++ { "r19", 1216, 64 },
++ { "r20", 1280, 64 },
++ { "r21", 1344, 64 },
++ { "r22", 1408, 64 },
++ { "r23", 1472, 64 },
++ { "r24", 1536, 64 },
++ { "r25", 1600, 64 },
++ { "r26", 1664, 64 },
++ { "r27", 1728, 64 },
++ { "r28", 1792, 64 },
++ { "r29", 1856, 64 },
++ { "r30", 1920, 64 },
++ { "r31", 1984, 64 },
++ { "orig_a0", 2048, 64 },
++ { "pc", 2112, 64 },
++ { "badv", 2176, 64 },
++ { "f0", 2240, 64 },
++ { "f1", 2304, 64 },
++ { "f2", 2368, 64 },
++ { "f3", 2432, 64 },
++ { "f4", 2496, 64 },
++ { "f5", 2560, 64 },
++ { "f6", 2624, 64 },
++ { "f7", 2688, 64 },
++ { "f8", 2752, 64 },
++ { "f9", 2816, 64 },
++ { "f10", 2880, 64 },
++ { "f11", 2944, 64 },
++ { "f12", 3008, 64 },
++ { "f13", 3072, 64 },
++ { "f14", 3136, 64 },
++ { "f15", 3200, 64 },
++ { "f16", 3264, 64 },
++ { "f17", 3328, 64 },
++ { "f18", 3392, 64 },
++ { "f19", 3456, 64 },
++ { "f20", 3520, 64 },
++ { "f21", 3584, 64 },
++ { "f22", 3648, 64 },
++ { "f23", 3712, 64 },
++ { "f24", 3776, 64 },
++ { "f25", 3840, 64 },
++ { "f26", 3904, 64 },
++ { "f27", 3968, 64 },
++ { "f28", 4032, 64 },
++ { "f29", 4096, 64 },
++ { "f30", 4160, 64 },
++ { "f31", 4224, 64 },
++ { "fcc0", 4288, 8 },
++ { "fcc1", 4296, 8 },
++ { "fcc2", 4304, 8 },
++ { "fcc3", 4312, 8 },
++ { "fcc4", 4320, 8 },
++ { "fcc5", 4328, 8 },
++ { "fcc6", 4336, 8 },
++ { "fcc7", 4344, 8 },
++ { "fcsr", 4352, 32 }
++};
+
-+ Int sigNo = siginfo->si_signo;
-+ tst->arch.vex.guest_R4 = sigNo;
-+ tst->arch.vex.guest_R5 = (Addr) &frame->rs_info;
-+ tst->arch.vex.guest_R6 = (Addr) &frame->rs_uctx;
-+ tst->arch.vex.guest_R3 = (Addr) frame;
-+ tst->arch.vex.guest_R1 = (Addr) &VG_(loongarch64_linux_SUBST_FOR_rt_sigreturn);
++#define num_regs (sizeof (regs) / sizeof (regs[0]))
+
-+ struct vg_sig_private *priv = &frame->priv;
-+ priv->magicPI = 0x31415927;
-+ priv->sigNo_private = sigNo;
-+ priv->vex_shadow1 = tst->arch.vex_shadow1;
-+ priv->vex_shadow2 = tst->arch.vex_shadow2;
++static const char* expedite_regs[] = { "r3", "pc", NULL };
+
-+ /* Set the thread so it will next run the handler. */
-+ VG_TRACK(post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
++static
++CORE_ADDR get_pc (void)
++{
++ unsigned long pc;
+
-+ if (VG_(clo_trace_signals))
-+ VG_(printf)("handler = %p\n", handler);
++ collect_register_by_name ("pc", &pc);
+
-+ tst->arch.vex.guest_PC = (Addr) handler;
-+ /* This thread needs to be marked runnable, but we leave that
-+ the caller to do. */
++ dlog(1, "stop pc is %p\n", (void*) pc);
++ return pc;
+}
+
-+
-+/*------------------------------------------------------------*/
-+/*--- Destroying signal frames ---*/
-+/*------------------------------------------------------------*/
-+
-+static void restore_regs ( ThreadState *tst,
-+ struct vki_sigcontext *mc)
++static
++void set_pc (CORE_ADDR newpc)
+{
-+ tst->arch.vex.guest_R1 = mc->sc_regs[1];
-+ tst->arch.vex.guest_R2 = mc->sc_regs[2];
-+ tst->arch.vex.guest_R3 = mc->sc_regs[3];
-+ tst->arch.vex.guest_R4 = mc->sc_regs[4];
-+ tst->arch.vex.guest_R5 = mc->sc_regs[5];
-+ tst->arch.vex.guest_R6 = mc->sc_regs[6];
-+ tst->arch.vex.guest_R7 = mc->sc_regs[7];
-+ tst->arch.vex.guest_R8 = mc->sc_regs[8];
-+ tst->arch.vex.guest_R9 = mc->sc_regs[9];
-+ tst->arch.vex.guest_R10 = mc->sc_regs[10];
-+ tst->arch.vex.guest_R11 = mc->sc_regs[11];
-+ tst->arch.vex.guest_R12 = mc->sc_regs[12];
-+ tst->arch.vex.guest_R13 = mc->sc_regs[13];
-+ tst->arch.vex.guest_R14 = mc->sc_regs[14];
-+ tst->arch.vex.guest_R15 = mc->sc_regs[15];
-+ tst->arch.vex.guest_R16 = mc->sc_regs[16];
-+ tst->arch.vex.guest_R17 = mc->sc_regs[17];
-+ tst->arch.vex.guest_R18 = mc->sc_regs[18];
-+ tst->arch.vex.guest_R19 = mc->sc_regs[19];
-+ tst->arch.vex.guest_R20 = mc->sc_regs[20];
-+ tst->arch.vex.guest_R21 = mc->sc_regs[21];
-+ tst->arch.vex.guest_R22 = mc->sc_regs[22];
-+ tst->arch.vex.guest_R23 = mc->sc_regs[23];
-+ tst->arch.vex.guest_R24 = mc->sc_regs[24];
-+ tst->arch.vex.guest_R25 = mc->sc_regs[25];
-+ tst->arch.vex.guest_R26 = mc->sc_regs[26];
-+ tst->arch.vex.guest_R27 = mc->sc_regs[27];
-+ tst->arch.vex.guest_R28 = mc->sc_regs[28];
-+ tst->arch.vex.guest_R29 = mc->sc_regs[29];
-+ tst->arch.vex.guest_R30 = mc->sc_regs[30];
-+ tst->arch.vex.guest_R31 = mc->sc_regs[31];
-+ tst->arch.vex.guest_PC = mc->sc_pc;
++ supply_register_by_name ("pc", &newpc);
+}
+
-+/* EXPORTED */
-+void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
++/* store registers in the guest state (gdbserver_to_valgrind)
++ or fetch register from the guest state (valgrind_to_gdbserver). */
++static
++void transfer_register (ThreadId tid, int abs_regno, void* buf,
++ transfer_direction dir, int size, Bool* mod)
+{
-+ vg_assert(VG_(is_valid_tid)(tid));
-+
-+ ThreadState *tst = VG_(get_ThreadState)(tid);
-+ Addr sp = tst->arch.vex.guest_R3;
-+ struct rt_sigframe *frame = (struct rt_sigframe *)sp;
-+ struct vki_ucontext *uc = &frame->rs_uctx;
++ ThreadState* tst = VG_(get_ThreadState)(tid);
++ int set = abs_regno / num_regs;
++ int regno = abs_regno % num_regs;
++ *mod = False;
+
-+ tst->sig_mask = uc->uc_sigmask;
-+ tst->tmp_sig_mask = uc->uc_sigmask;
++ VexGuestLOONGARCH64State* loongarch64 = (VexGuestLOONGARCH64State*) get_arch (set, tst);
+
-+ struct vki_sigcontext *mc = &uc->uc_mcontext;
-+ restore_regs(tst, mc);
++ switch (regno) {
++ // numbers here have to match the order of regs above
++ // Attention: gdb order does not match valgrind order.
++ case 0: VG_(transfer) (&loongarch64->guest_R0, buf, dir, size, mod); break;
++ case 1: VG_(transfer) (&loongarch64->guest_R1, buf, dir, size, mod); break;
++ case 2: VG_(transfer) (&loongarch64->guest_R2, buf, dir, size, mod); break;
++ case 3: VG_(transfer) (&loongarch64->guest_R3, buf, dir, size, mod); break;
++ case 4: VG_(transfer) (&loongarch64->guest_R4, buf, dir, size, mod); break;
++ case 5: VG_(transfer) (&loongarch64->guest_R5, buf, dir, size, mod); break;
++ case 6: VG_(transfer) (&loongarch64->guest_R6, buf, dir, size, mod); break;
++ case 7: VG_(transfer) (&loongarch64->guest_R7, buf, dir, size, mod); break;
++ case 8: VG_(transfer) (&loongarch64->guest_R8, buf, dir, size, mod); break;
++ case 9: VG_(transfer) (&loongarch64->guest_R9, buf, dir, size, mod); break;
++ case 10: VG_(transfer) (&loongarch64->guest_R10, buf, dir, size, mod); break;
++ case 11: VG_(transfer) (&loongarch64->guest_R11, buf, dir, size, mod); break;
++ case 12: VG_(transfer) (&loongarch64->guest_R12, buf, dir, size, mod); break;
++ case 13: VG_(transfer) (&loongarch64->guest_R13, buf, dir, size, mod); break;
++ case 14: VG_(transfer) (&loongarch64->guest_R14, buf, dir, size, mod); break;
++ case 15: VG_(transfer) (&loongarch64->guest_R15, buf, dir, size, mod); break;
++ case 16: VG_(transfer) (&loongarch64->guest_R16, buf, dir, size, mod); break;
++ case 17: VG_(transfer) (&loongarch64->guest_R17, buf, dir, size, mod); break;
++ case 18: VG_(transfer) (&loongarch64->guest_R18, buf, dir, size, mod); break;
++ case 19: VG_(transfer) (&loongarch64->guest_R19, buf, dir, size, mod); break;
++ case 20: VG_(transfer) (&loongarch64->guest_R20, buf, dir, size, mod); break;
++ case 21: VG_(transfer) (&loongarch64->guest_R21, buf, dir, size, mod); break;
++ case 22: VG_(transfer) (&loongarch64->guest_R22, buf, dir, size, mod); break;
++ case 23: VG_(transfer) (&loongarch64->guest_R23, buf, dir, size, mod); break;
++ case 24: VG_(transfer) (&loongarch64->guest_R24, buf, dir, size, mod); break;
++ case 25: VG_(transfer) (&loongarch64->guest_R25, buf, dir, size, mod); break;
++ case 26: VG_(transfer) (&loongarch64->guest_R26, buf, dir, size, mod); break;
++ case 27: VG_(transfer) (&loongarch64->guest_R27, buf, dir, size, mod); break;
++ case 28: VG_(transfer) (&loongarch64->guest_R28, buf, dir, size, mod); break;
++ case 29: VG_(transfer) (&loongarch64->guest_R29, buf, dir, size, mod); break;
++ case 30: VG_(transfer) (&loongarch64->guest_R30, buf, dir, size, mod); break;
++ case 31: VG_(transfer) (&loongarch64->guest_R31, buf, dir, size, mod); break;
++ case 32: *mod = False; break; // GDBTD?? arg0
++ case 33: VG_(transfer) (&loongarch64->guest_PC, buf, dir, size, mod); break;
++ case 34: *mod = False; break; // GDBTD?? badvaddr
++ case 35: VG_(transfer) (&loongarch64->guest_X0, buf, dir, size, mod); break;
++ case 36: VG_(transfer) (&loongarch64->guest_X1, buf, dir, size, mod); break;
++ case 37: VG_(transfer) (&loongarch64->guest_X2, buf, dir, size, mod); break;
++ case 38: VG_(transfer) (&loongarch64->guest_X3, buf, dir, size, mod); break;
++ case 39: VG_(transfer) (&loongarch64->guest_X4, buf, dir, size, mod); break;
++ case 40: VG_(transfer) (&loongarch64->guest_X5, buf, dir, size, mod); break;
++ case 41: VG_(transfer) (&loongarch64->guest_X6, buf, dir, size, mod); break;
++ case 42: VG_(transfer) (&loongarch64->guest_X7, buf, dir, size, mod); break;
++ case 43: VG_(transfer) (&loongarch64->guest_X8, buf, dir, size, mod); break;
++ case 44: VG_(transfer) (&loongarch64->guest_X9, buf, dir, size, mod); break;
++ case 45: VG_(transfer) (&loongarch64->guest_X10, buf, dir, size, mod); break;
++ case 46: VG_(transfer) (&loongarch64->guest_X11, buf, dir, size, mod); break;
++ case 47: VG_(transfer) (&loongarch64->guest_X12, buf, dir, size, mod); break;
++ case 48: VG_(transfer) (&loongarch64->guest_X13, buf, dir, size, mod); break;
++ case 49: VG_(transfer) (&loongarch64->guest_X14, buf, dir, size, mod); break;
++ case 50: VG_(transfer) (&loongarch64->guest_X15, buf, dir, size, mod); break;
++ case 51: VG_(transfer) (&loongarch64->guest_X16, buf, dir, size, mod); break;
++ case 52: VG_(transfer) (&loongarch64->guest_X17, buf, dir, size, mod); break;
++ case 53: VG_(transfer) (&loongarch64->guest_X18, buf, dir, size, mod); break;
++ case 54: VG_(transfer) (&loongarch64->guest_X19, buf, dir, size, mod); break;
++ case 55: VG_(transfer) (&loongarch64->guest_X20, buf, dir, size, mod); break;
++ case 56: VG_(transfer) (&loongarch64->guest_X21, buf, dir, size, mod); break;
++ case 57: VG_(transfer) (&loongarch64->guest_X22, buf, dir, size, mod); break;
++ case 58: VG_(transfer) (&loongarch64->guest_X23, buf, dir, size, mod); break;
++ case 59: VG_(transfer) (&loongarch64->guest_X24, buf, dir, size, mod); break;
++ case 60: VG_(transfer) (&loongarch64->guest_X25, buf, dir, size, mod); break;
++ case 61: VG_(transfer) (&loongarch64->guest_X26, buf, dir, size, mod); break;
++ case 62: VG_(transfer) (&loongarch64->guest_X27, buf, dir, size, mod); break;
++ case 63: VG_(transfer) (&loongarch64->guest_X28, buf, dir, size, mod); break;
++ case 64: VG_(transfer) (&loongarch64->guest_X29, buf, dir, size, mod); break;
++ case 65: VG_(transfer) (&loongarch64->guest_X30, buf, dir, size, mod); break;
++ case 66: VG_(transfer) (&loongarch64->guest_X31, buf, dir, size, mod); break;
++ case 67: VG_(transfer) (&loongarch64->guest_FCC0, buf, dir, size, mod); break;
++ case 68: VG_(transfer) (&loongarch64->guest_FCC1, buf, dir, size, mod); break;
++ case 69: VG_(transfer) (&loongarch64->guest_FCC2, buf, dir, size, mod); break;
++ case 70: VG_(transfer) (&loongarch64->guest_FCC3, buf, dir, size, mod); break;
++ case 71: VG_(transfer) (&loongarch64->guest_FCC4, buf, dir, size, mod); break;
++ case 72: VG_(transfer) (&loongarch64->guest_FCC5, buf, dir, size, mod); break;
++ case 73: VG_(transfer) (&loongarch64->guest_FCC6, buf, dir, size, mod); break;
++ case 74: VG_(transfer) (&loongarch64->guest_FCC7, buf, dir, size, mod); break;
++ case 75: VG_(transfer) (&loongarch64->guest_FCSR, buf, dir, size, mod); break;
++ default: vg_assert(0);
++ }
++}
+
-+ struct vg_sig_private *priv = &frame->priv;
-+ vg_assert(priv->magicPI == 0x31415927);
-+ tst->arch.vex_shadow1 = priv->vex_shadow1;
-+ tst->arch.vex_shadow2 = priv->vex_shadow2;
++static
++const char* target_xml (Bool shadow_mode)
++{
++ if (shadow_mode) {
++ return "loongarch64-linux-valgrind.xml";
++ } else {
++ return "loongarch64-linux.xml";
++ }
++}
+
-+ UInt frame_size = sizeof(*frame);
-+ VG_TRACK(die_mem_stack_signal, sp, frame_size);
++static CORE_ADDR** target_get_dtv (ThreadState* tst)
++{
++ VexGuestLOONGARCH64State* loongarch64 = (VexGuestLOONGARCH64State*)&tst->arch.vex;
++ // Top of LoongArch tcbhead structure is located 0x0 bytes before the value
++ // of $r2. Dtv is the first of two pointers in tcbhead structure.
++ // More details can be found in GLIBC/sysdeps/nptl/tls.h.
++ return (CORE_ADDR**)((CORE_ADDR)loongarch64->guest_R2
++ - 0x0 - 2 * sizeof(CORE_ADDR));
++}
+
-+ if (VG_(clo_trace_signals))
-+ VG_(message)(Vg_DebugMsg,
-+ "VG_(signal_return) (thread %u): isRT=%d valid magic; PC=%#llx\n",
-+ tid, isRT, tst->arch.vex.guest_PC);
++static struct valgrind_target_ops low_target = {
++ num_regs,
++ 3, // SP
++ regs,
++ transfer_register,
++ get_pc,
++ set_pc,
++ "loongarch64",
++ target_xml,
++ target_get_dtv
++};
+
-+ Int sigNo = priv->sigNo_private;
-+ VG_TRACK( post_deliver_signal, tid, sigNo );
++void loongarch64_init_architecture (struct valgrind_target_ops* target)
++{
++ *target = low_target;
++ set_register_cache (regs, num_regs);
++ gdbserver_expedite_regs = expedite_regs;
+}
+diff --git a/coregrind/m_gdbserver/valgrind_low.h b/coregrind/m_gdbserver/valgrind_low.h
+index d8ae3c9..3393c32 100644
+--- a/coregrind/m_gdbserver/valgrind_low.h
++++ b/coregrind/m_gdbserver/valgrind_low.h
+@@ -109,5 +109,6 @@ extern void s390x_init_architecture (struct valgrind_target_ops *target);
+ extern void mips32_init_architecture (struct valgrind_target_ops *target);
+ extern void mips64_init_architecture (struct valgrind_target_ops *target);
+ extern void nanomips_init_architecture (struct valgrind_target_ops *target);
++extern void loongarch64_init_architecture (struct valgrind_target_ops *target);
+
+ #endif
+diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c
+index 5359189..61e284b 100644
+--- a/coregrind/m_initimg/initimg-linux.c
++++ b/coregrind/m_initimg/initimg-linux.c
+@@ -917,7 +917,8 @@ Addr setup_client_stack( void* init_sp,
+ && !defined(VGP_ppc64le_linux) \
+ && !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux) \
+ && !defined(VGP_nanomips_linux) \
+- && !defined(VGP_s390x_linux)
++ && !defined(VGP_s390x_linux) \
++ && !defined(VGP_loongarch64_linux)
+ case AT_SYSINFO_EHDR: {
+ /* Trash this, because we don't reproduce it */
+ const NSegment* ehdrseg = VG_(am_find_nsegment)((Addr)auxv->u.a_ptr);
+@@ -1348,6 +1349,20 @@ void VG_(ii_finalise_image)( IIFinaliseImageInfo iifii )
+ arch->vex.guest_PC = iifii.initial_client_IP;
+ arch->vex.guest_r31 = iifii.initial_client_SP;
+
++# elif defined(VGP_loongarch64_linux)
++ vg_assert(0 == sizeof(VexGuestLOONGARCH64State) % LibVEX_GUEST_STATE_ALIGN);
+
-+#endif /* defined(VGP_loongarch64_linux) */
++ /* Zero out the initial state, and set up the simulated FPU in a
++ sane way. */
++ LibVEX_GuestLOONGARCH64_initialise(&arch->vex);
+
-+/*--------------------------------------------------------------------*/
-+/*--- end sigframe-loongarch64-linux.c ---*/
-+/*--------------------------------------------------------------------*/
-diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c
-index b3c94fc..62c689b 100644
---- a/coregrind/m_signals.c
-+++ b/coregrind/m_signals.c
-@@ -628,6 +628,22 @@ VgHashTable *ht_sigchld_ignore = NULL;
- (srP)->misc.MIPS32.r28 = (uc)->uc_mcontext.sc_regs[28]; \
++ /* Zero out the shadow areas. */
++ VG_(memset)(&arch->vex_shadow1, 0, sizeof(VexGuestLOONGARCH64State));
++ VG_(memset)(&arch->vex_shadow2, 0, sizeof(VexGuestLOONGARCH64State));
++
++ arch->vex.guest_R3 = iifii.initial_client_SP;
++ arch->vex.guest_PC = iifii.initial_client_IP;
++
+ # else
+ # error Unknown platform
+ # endif
+diff --git a/coregrind/m_libcassert.c b/coregrind/m_libcassert.c
+index 257c26b..7ecd771 100644
+--- a/coregrind/m_libcassert.c
++++ b/coregrind/m_libcassert.c
+@@ -264,6 +264,26 @@
+ (srP)->misc.MIPS32.r31 = (UInt)ra; \
+ (srP)->misc.MIPS32.r28 = (UInt)gp; \
}
++#elif defined(VGP_loongarch64_linux)
++# define GET_STARTREGS(srP) \
++ { \
++ ULong pc, sp, fp, ra; \
++ __asm__ __volatile__( \
++ "pcaddi %0, 0 \n\t" \
++ "move %1, $sp \n\t" \
++ "move %2, $fp \n\t" \
++ "move %3, $ra \n\t" \
++ : "=r" (pc), \
++ "=r" (sp), \
++ "=r" (fp), \
++ "=r" (ra) \
++ : /* reads none */ \
++ : /* no trashed */ ); \
++ (srP)->r_pc = (ULong)pc; \
++ (srP)->r_sp = (ULong)sp; \
++ (srP)->misc.LOONGARCH64.r_fp = (ULong)fp; \
++ (srP)->misc.LOONGARCH64.r_ra = (ULong)ra; \
++ }
+ #else
+ # error Unknown platform
+ #endif
+diff --git a/coregrind/m_libcfile.c b/coregrind/m_libcfile.c
+index fb93b48..294339f 100644
+--- a/coregrind/m_libcfile.c
++++ b/coregrind/m_libcfile.c
+@@ -264,7 +264,8 @@ Bool VG_(resolve_filemode) ( Int fd, Int * result )
+
+ SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev )
+ {
+-# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ /* ARM64 wants to use __NR_mknodat rather than __NR_mknod. */
+ SysRes res = VG_(do_syscall4)(__NR_mknodat,
+ VKI_AT_FDCWD, (UWord)pathname, mode, dev);
+@@ -290,7 +291,8 @@ SysRes VG_(mknod) ( const HChar* pathname, Int mode, UWord dev )
+
+ SysRes VG_(open) ( const HChar* pathname, Int flags, Int mode )
+ {
+-# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ /* ARM64 wants to use __NR_openat rather than __NR_open. */
+ SysRes res = VG_(do_syscall4)(__NR_openat,
+ VKI_AT_FDCWD, (UWord)pathname, flags, mode);
+@@ -384,7 +386,8 @@ Int VG_(pipe) ( Int fd[2] )
+ } else {
+ return -1;
+ }
+-# elif defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++# elif defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ SysRes res = VG_(do_syscall2)(__NR_pipe2, (UWord)fd, 0);
+ return sr_isError(res) ? -1 : 0;
+ # elif defined(VGO_linux)
+@@ -517,12 +520,19 @@ SysRes VG_(stat) ( const HChar* file_name, struct vg_stat* vgbuf )
+ { struct vki_statx buf;
+ res = VG_(do_syscall5)(__NR_statx, VKI_AT_FDCWD, (UWord)file_name, 0,
+ VKI_STATX_ALL, (UWord)&buf);
++# if defined(VGP_loongarch64_linux)
++ /* On LoongArch64 Linux platform, only statx is available. */
++ if (!sr_isError(res))
++ TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
++ return res;
++# else
+ if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
+ /* Success, or any failure except ENOSYS */
+ if (!sr_isError(res))
+ TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
+ return res;
+ }
++# endif
+ }
+ # endif
+ # if defined(VGO_linux) || defined(VGO_darwin)
+@@ -602,12 +612,19 @@ Int VG_(fstat) ( Int fd, struct vg_stat* vgbuf )
+ const char* file_name = "";
+ res = VG_(do_syscall5)(__NR_statx, fd, (RegWord)file_name,
+ VKI_AT_EMPTY_PATH, VKI_STATX_ALL, (RegWord)&buf);
++# if defined(VGP_loongarch64_linux)
++ /* On LoongArch64 Linux platform, only statx is available. */
++ if (!sr_isError(res))
++ TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
++ return sr_isError(res) ? (-1) : 0;
++# else
+ if (!(sr_isError(res) && sr_Err(res) == VKI_ENOSYS)) {
+ /* Success, or any failure except ENOSYS */
+ if (!sr_isError(res))
+ TRANSLATE_statx_TO_vg_stat(vgbuf, &buf);
+ return sr_isError(res) ? (-1) : 0;
+ }
++# endif
+ }
+ #endif
+ # if defined(VGO_linux) || defined(VGO_darwin)
+@@ -731,7 +748,8 @@ SysRes VG_(dup) ( Int oldfd )
-+#elif defined(VGP_loongarch64_linux)
-+# define VG_UCONTEXT_INSTR_PTR(uc) (((uc)->uc_mcontext.sc_pc))
-+# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.sc_regs[3])
-+# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.sc_regs[22])
-+# define VG_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.sc_regs[11])
-+# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \
-+ /* Convert the value in uc_mcontext.regs[4] into a SysRes. */ \
-+ VG_(mk_SysRes_loongarch64_linux)((uc)->uc_mcontext.sc_regs[4])
-+
-+# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \
-+ { (srP)->r_pc = (uc)->uc_mcontext.sc_pc; \
-+ (srP)->r_sp = (uc)->uc_mcontext.sc_regs[3]; \
-+ (srP)->misc.LOONGARCH64.r_fp = (uc)->uc_mcontext.sc_regs[22]; \
-+ (srP)->misc.LOONGARCH64.r_ra = (uc)->uc_mcontext.sc_regs[1]; \
-+ }
-+
- #elif defined(VGP_x86_solaris)
- # define VG_UCONTEXT_INSTR_PTR(uc) ((Addr)(uc)->uc_mcontext.gregs[VKI_EIP])
- # define VG_UCONTEXT_STACK_PTR(uc) ((Addr)(uc)->uc_mcontext.gregs[VKI_UESP])
-@@ -899,8 +915,10 @@ void calculate_SKSS_from_SCSS ( SKSS* dst )
- if (skss_handler != VKI_SIG_IGN && skss_handler != VKI_SIG_DFL)
- skss_flags |= VKI_SA_SIGINFO;
+ SysRes VG_(dup2) ( Int oldfd, Int newfd )
+ {
+-# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ /* We only have dup3, that means we have to mimic dup2.
+ The only real difference is when oldfd == newfd.
+ dup3 always returns an error, but dup2 returns only an
+@@ -777,7 +795,7 @@ Int VG_(rename) ( const HChar* old_name, const HChar* new_name )
+ # if defined(VGO_solaris) || defined(VGP_arm64_linux)
+ SysRes res = VG_(do_syscall4)(__NR_renameat, VKI_AT_FDCWD, (UWord)old_name,
+ VKI_AT_FDCWD, (UWord)new_name);
+-# elif defined(VGP_nanomips_linux)
++# elif defined(VGP_nanomips_linux) || defined(VGP_loongarch64_linux)
+ SysRes res = VG_(do_syscall5)(__NR_renameat2, VKI_AT_FDCWD, (UWord)old_name,
+ VKI_AT_FDCWD, (UWord)new_name, 0);
-+# if !defined(VGP_loongarch64_linux)
- /* use our own restorer */
- skss_flags |= VKI_SA_RESTORER;
-+# endif
+@@ -791,7 +809,8 @@ Int VG_(rename) ( const HChar* old_name, const HChar* new_name )
- /* Create SKSS entry for this signal. */
- if (sig != VKI_SIGKILL && sig != VKI_SIGSTOP)
-@@ -1052,6 +1070,15 @@ extern void my_sigreturn(void);
- " li $t4, " #name "\n" \
- " syscall[32]\n" \
- ".previous\n"
-+
-+#elif defined(VGP_loongarch64_linux)
-+# define _MY_SIGRETURN(name) \
-+ ".text\n" \
-+ "my_sigreturn:\n" \
-+ " li.w $a7, " #name "\n" \
-+ " syscall 0\n" \
-+ ".previous\n"
-+
- #elif defined(VGP_x86_solaris) || defined(VGP_amd64_solaris)
- /* Not used on Solaris. */
- # define _MY_SIGRETURN(name) \
-@@ -1111,7 +1138,8 @@ static void handle_SCSS_change ( Bool force_update )
- ksa.sa_flags = skss.skss_per_sig[sig].skss_flags;
- # if !defined(VGP_ppc32_linux) && \
- !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
-- !defined(VGP_mips32_linux) && !defined(VGO_solaris) && !defined(VGO_freebsd)
-+ !defined(VGP_mips32_linux) && !defined(VGO_solaris) && \
-+ !defined(VGO_freebsd) && !defined(VGP_loongarch64_linux)
- ksa.sa_restorer = my_sigreturn;
- # endif
- /* Re above ifdef (also the assertion below), PaulM says:
-@@ -1159,7 +1187,7 @@ static void handle_SCSS_change ( Bool force_update )
- !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
- !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux) && \
- !defined(VGP_nanomips_linux) && !defined(VGO_solaris) && \
-- !defined(VGO_freebsd)
-+ !defined(VGO_freebsd) && !defined(VGP_loongarch64_linux)
- vg_assert(ksa_old.sa_restorer == my_sigreturn);
- # endif
- VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGKILL );
-@@ -1280,7 +1308,7 @@ SysRes VG_(do_sys_sigaction) ( Int signo,
- old_act->sa_flags = scss.scss_per_sig[signo].scss_flags;
- old_act->sa_mask = scss.scss_per_sig[signo].scss_mask;
- # if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
-- !defined(VGO_solaris)
-+ !defined(VGO_solaris) && !defined(VGP_loongarch64_linux)
- old_act->sa_restorer = scss.scss_per_sig[signo].scss_restorer;
- # endif
- }
-@@ -1293,7 +1321,7 @@ SysRes VG_(do_sys_sigaction) ( Int signo,
+ Int VG_(unlink) ( const HChar* file_name )
+ {
+-# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ SysRes res = VG_(do_syscall2)(__NR_unlinkat, VKI_AT_FDCWD,
+ (UWord)file_name);
+ # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
+@@ -870,7 +889,8 @@ const HChar *VG_(get_startup_wd) ( void )
+ SysRes VG_(poll) (struct vki_pollfd *fds, Int nfds, Int timeout)
+ {
+ SysRes res;
+-# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ /* ARM64 wants to use __NR_ppoll rather than __NR_poll. */
+ struct vki_timespec timeout_ts;
+ if (timeout >= 0) {
+@@ -915,7 +935,8 @@ SSizeT VG_(readlink) (const HChar* path, HChar* buf, SizeT bufsiz)
+ {
+ SysRes res;
+ /* res = readlink( path, buf, bufsiz ); */
+-# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
+ (UWord)path, (UWord)buf, bufsiz);
+ # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
+@@ -994,7 +1015,8 @@ Int VG_(access) ( const HChar* path, Bool irusr, Bool iwusr, Bool ixusr )
+ UWord w = (irusr ? VKI_R_OK : 0)
+ | (iwusr ? VKI_W_OK : 0)
+ | (ixusr ? VKI_X_OK : 0);
+-# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ SysRes res = VG_(do_syscall3)(__NR_faccessat, VKI_AT_FDCWD, (UWord)path, w);
+ # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
+ SysRes res = VG_(do_syscall2)(__NR_access, (UWord)path, w);
+@@ -1140,7 +1162,8 @@ SysRes VG_(pread) ( Int fd, void* buf, Int count, OffT offset )
+ return res;
+ # elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \
+ || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
+- || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
++ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
++ || defined(VGP_loongarch64_linux)
+ res = VG_(do_syscall4)(__NR_pread64, fd, (UWord)buf, count, offset);
+ return res;
+ # elif defined(VGP_amd64_freebsd) || defined(VGP_arm64_freebsd)
+@@ -1405,7 +1428,8 @@ Int VG_(socket) ( Int domain, Int type, Int protocol )
- scss.scss_per_sig[signo].scss_restorer = NULL;
- # if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
-- !defined(VGO_solaris)
-+ !defined(VGO_solaris) && !defined(VGP_loongarch64_linux)
- scss.scss_per_sig[signo].scss_restorer = new_act->sa_restorer;
- # endif
+ # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
+- || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
++ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGO_freebsd) || defined(VGP_loongarch64_linux)
+ SysRes res;
+ res = VG_(do_syscall3)(__NR_socket, domain, type, protocol );
+ return sr_isError(res) ? -1 : sr_Res(res);
+@@ -1460,7 +1484,8 @@ Int my_connect ( Int sockfd, struct vki_sockaddr_in* serv_addr, Int addrlen )
-@@ -1653,7 +1681,7 @@ void VG_(kill_self)(Int sigNo)
- sa.ksa_handler = VKI_SIG_DFL;
- sa.sa_flags = 0;
- # if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
-- !defined(VGO_solaris)
-+ !defined(VGO_solaris) && !defined(VGP_loongarch64_linux)
- sa.sa_restorer = 0;
- # endif
- VG_(sigemptyset)(&sa.sa_mask);
-@@ -2296,8 +2324,9 @@ void VG_(synth_sigtrap)(ThreadId tid)
- // Synthesise a SIGFPE.
- void VG_(synth_sigfpe)(ThreadId tid, UInt code)
- {
--// Only tested on mips32, mips64, s390x and nanomips.
--#if !defined(VGA_mips32) && !defined(VGA_mips64) && !defined(VGA_s390x) && !defined(VGA_nanomips)
-+// Only tested on mips32, mips64, s390x, nanomips and loongarch64.
-+#if !defined(VGA_mips32) && !defined(VGA_mips64) && !defined(VGA_s390x) \
-+ && !defined(VGA_nanomips) && !defined(VGA_loongarch64)
- vg_assert(0);
- #else
- vki_siginfo_t info;
-@@ -2319,6 +2348,30 @@ void VG_(synth_sigfpe)(ThreadId tid, UInt code)
- #endif
- }
+ # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
+- || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
++ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGO_freebsd) || defined(VGP_loongarch64_linux)
+ SysRes res;
+ res = VG_(do_syscall3)(__NR_connect, sockfd, (UWord)serv_addr, addrlen);
+ return sr_isError(res) ? -1 : sr_Res(res);
+@@ -1507,7 +1532,8 @@ Int VG_(write_socket)( Int sd, const void *msg, Int count )
-+// Synthesise a SIGSYS.
-+void VG_(synth_sigsys)(ThreadId tid)
-+{
-+// Only tested on loongarch64-linux.
-+#if !defined(VGP_loongarch64_linux)
-+ vg_assert(0);
-+#else
-+ vki_siginfo_t info;
-+
-+ vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
-+
-+ VG_(memset)(&info, 0, sizeof(info));
-+ info.si_signo = VKI_SIGSYS;
-+ info.si_code = VKI_SI_KERNEL;
-+
-+ if (VG_(gdbserver_report_signal) (&info, tid)) {
-+ resume_scheduler(tid);
-+ deliver_signal(tid, &info, NULL);
-+ }
-+ else
-+ resume_scheduler(tid);
-+#endif
-+}
-+
- /* Make a signal pending for a thread, for later delivery.
- VG_(poll_signals) will arrange for it to be delivered at the right
- time.
-@@ -3043,7 +3096,7 @@ void pp_ksigaction ( vki_sigaction_toK_t* sa )
- sa->ksa_handler,
- (UInt)sa->sa_flags,
- # if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
-- !defined(VGO_solaris)
-+ !defined(VGO_solaris) && !defined(VGP_loongarch64_linux)
- sa->sa_restorer
- # else
- (void*)0
-@@ -3066,7 +3119,7 @@ void VG_(set_default_handler)(Int signo)
- sa.ksa_handler = VKI_SIG_DFL;
- sa.sa_flags = 0;
- # if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
-- !defined(VGO_solaris)
-+ !defined(VGO_solaris) && !defined(VGP_loongarch64_linux)
- sa.sa_restorer = 0;
- # endif
- VG_(sigemptyset)(&sa.sa_mask);
-@@ -3188,7 +3241,7 @@ void VG_(sigstartup_actions) ( void )
- tsa.ksa_handler = (void *)sync_signalhandler;
- tsa.sa_flags = VKI_SA_SIGINFO;
- # if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
-- !defined(VGO_solaris)
-+ !defined(VGO_solaris) && !defined(VGP_loongarch64_linux)
- tsa.sa_restorer = 0;
- # endif
- VG_(sigfillset)(&tsa.sa_mask);
-@@ -3216,7 +3269,7 @@ void VG_(sigstartup_actions) ( void )
+ # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
+- || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
++ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGO_freebsd) || defined(VGP_loongarch64_linux)
+ SysRes res;
+ res = VG_(do_syscall6)(__NR_sendto, sd, (UWord)msg,
+ count, VKI_MSG_NOSIGNAL, 0,0);
+@@ -1545,7 +1571,8 @@ Int VG_(getsockname) ( Int sd, struct vki_sockaddr *name, Int *namelen)
+ # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
+ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
+ || defined(VGP_nanomips_linux) || defined(VGO_freebsd) \
+- || defined(VGP_mips64_linux) || defined(VGP_arm64_linux)
++ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
++ || defined(VGP_loongarch64_linux)
+ SysRes res;
+ res = VG_(do_syscall3)( __NR_getsockname,
+ (UWord)sd, (UWord)name, (UWord)namelen );
+@@ -1584,7 +1611,8 @@ Int VG_(getpeername) ( Int sd, struct vki_sockaddr *name, Int *namelen)
- scss.scss_per_sig[i].scss_restorer = NULL;
- # if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
-- !defined(VGO_solaris)
-+ !defined(VGO_solaris) && !defined(VGP_loongarch64_linux)
- scss.scss_per_sig[i].scss_restorer = sa.sa_restorer;
- # endif
+ # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
+ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
+- || defined(VGP_nanomips_linux) || defined(VGO_freebsd)
++ || defined(VGP_nanomips_linux) || defined(VGO_freebsd) \
++ || defined(VGP_loongarch64_linux)
+ SysRes res;
+ res = VG_(do_syscall3)( __NR_getpeername,
+ (UWord)sd, (UWord)name, (UWord)namelen );
+@@ -1626,7 +1654,7 @@ Int VG_(getsockopt) ( Int sd, Int level, Int optname, void *optval,
+ # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
+ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
+- || defined(VGO_freebsd)
++ || defined(VGO_freebsd) || defined(VGP_loongarch64_linux)
+ SysRes res;
+ res = VG_(do_syscall5)( __NR_getsockopt,
+ (UWord)sd, (UWord)level, (UWord)optname,
+@@ -1670,7 +1698,8 @@ Int VG_(setsockopt) ( Int sd, Int level, Int optname, void *optval,
-diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c
-index 0ec6f59..0f89b63 100644
---- a/coregrind/m_stacktrace.c
-+++ b/coregrind/m_stacktrace.c
-@@ -1505,6 +1505,100 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
+ # elif defined(VGP_amd64_linux) || defined(VGP_arm_linux) \
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
+- || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ SysRes res;
+ res = VG_(do_syscall5)( __NR_setsockopt,
+ (UWord)sd, (UWord)level, (UWord)optname,
+diff --git a/coregrind/m_libcproc.c b/coregrind/m_libcproc.c
+index 280ab1c..1fcc6dc 100644
+--- a/coregrind/m_libcproc.c
++++ b/coregrind/m_libcproc.c
+@@ -698,7 +698,8 @@ Int VG_(gettid)(void)
+ * the /proc/self link is pointing...
+ */
+
+-# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ res = VG_(do_syscall4)(__NR_readlinkat, VKI_AT_FDCWD,
+ (UWord)"/proc/self",
+ (UWord)pid, sizeof(pid));
+@@ -753,7 +754,8 @@ Int VG_(getpid) ( void )
+ Int VG_(getpgrp) ( void )
+ {
+ /* ASSUMES SYSCALL ALWAYS SUCCEEDS */
+-# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ return sr_Res( VG_(do_syscall1)(__NR_getpgid, 0) );
+ # elif defined(VGO_linux) || defined(VGO_darwin) || defined(VGO_freebsd)
+ return sr_Res( VG_(do_syscall0)(__NR_getpgrp) );
+@@ -850,7 +852,7 @@ Int VG_(getgroups)( Int size, UInt* list )
+ || defined(VGO_darwin) || defined(VGP_s390x_linux) \
+ || defined(VGP_mips32_linux) || defined(VGP_arm64_linux) \
+ || defined(VGO_solaris) || defined(VGP_nanomips_linux) \
+- || defined(VGO_freebsd)
++ || defined(VGO_freebsd) || defined(VGP_loongarch64_linux)
+ SysRes sres;
+ sres = VG_(do_syscall2)(__NR_getgroups, size, (Addr)list);
+ if (sr_isError(sres))
+@@ -951,7 +953,8 @@ Int VG_(fork) ( void )
+ fds[0] = fds[1] = -1;
+ }
+
+-# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++# if defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ SysRes res;
+ res = VG_(do_syscall5)(__NR_clone, VKI_SIGCHLD,
+ (UWord)NULL, (UWord)NULL, (UWord)NULL, (UWord)NULL);
+diff --git a/coregrind/m_libcsetjmp.c b/coregrind/m_libcsetjmp.c
+index 02324da..cebe3fd 100644
+--- a/coregrind/m_libcsetjmp.c
++++ b/coregrind/m_libcsetjmp.c
+@@ -887,6 +887,72 @@ void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env))
#endif
-+/* ---------------------- loongarch64 ----------------------- */
-+
+#if defined(VGP_loongarch64_linux)
-+UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
-+ /*OUT*/Addr* ips, UInt max_n_ips,
-+ /*OUT*/Addr* sps, /*OUT*/Addr* fps,
-+ const UnwindStartRegs* startRegs,
-+ Addr fp_max_orig )
-+{
-+ Bool debug = False;
-+ Int i;
-+ Addr fp_max;
-+ UInt n_found = 0;
-+ const Int cmrf = VG_(clo_merge_recursive_frames);
-+
-+ vg_assert(sizeof(Addr) == sizeof(UWord));
-+ vg_assert(sizeof(Addr) == sizeof(void*));
-+
-+ D3UnwindRegs uregs;
-+ uregs.pc = startRegs->r_pc;
-+ uregs.sp = startRegs->r_sp;
-+ uregs.fp = startRegs->misc.LOONGARCH64.r_fp;
-+ uregs.ra = startRegs->misc.LOONGARCH64.r_ra;
-+ Addr fp_min = uregs.sp - VG_STACK_REDZONE_SZB;
-+
-+ /* Snaffle IPs from the client's stack into ips[0 .. max_n_ips-1],
-+ stopping when the trail goes cold, which we guess to be
-+ when FP is not a reasonable stack location. */
-+
-+ fp_max = VG_PGROUNDUP(fp_max_orig);
-+ if (fp_max >= sizeof(Addr))
-+ fp_max -= sizeof(Addr);
-+
-+ if (debug)
-+ VG_(printf)("\nmax_n_ips=%u fp_min=0x%lx fp_max_orig=0x%lx, "
-+ "fp_max=0x%lx pc=0x%lx sp=0x%lx fp=0x%lx ra=0x%lx\n",
-+ max_n_ips, fp_min, fp_max_orig, fp_max,
-+ uregs.pc, uregs.sp, uregs.fp, uregs.ra);
-+
-+ if (sps) sps[0] = uregs.sp;
-+ if (fps) fps[0] = uregs.fp;
-+ ips[0] = uregs.pc;
-+ i = 1;
-+
-+ /* Loop unwinding the stack, using CFI. */
-+ while (True) {
-+ if (debug)
-+ VG_(printf)("i: %d, pc: 0x%lx, sp: 0x%lx, fp: 0x%lx, ra: 0x%lx\n",
-+ i, uregs.pc, uregs.sp, uregs.fp, uregs.ra);
-+ if (i >= max_n_ips)
-+ break;
-+
-+ if (VG_(use_CF_info)( &uregs, fp_min, fp_max )) {
-+ if (sps) sps[i] = uregs.sp;
-+ if (fps) fps[i] = uregs.fp;
-+ ips[i++] = uregs.pc - 1;
-+ if (debug)
-+ VG_(printf)(
-+ "USING CFI: pc: 0x%lx, sp: 0x%lx, fp: 0x%lx, ra: 0x%lx\n",
-+ uregs.pc, uregs.sp, uregs.fp, uregs.ra);
-+ uregs.pc = uregs.pc - 1;
-+ RECURSIVE_MERGE(cmrf,ips,i);
-+ continue;
-+ }
-+
-+ /* A problem on the first frame? Lets assume it was a bad jump.
-+ We will use the link register and the current stack and frame
-+ pointers and see if we can use the CFI in the next round. */
-+ if (i == 1) {
-+ uregs.pc = uregs.ra;
-+ uregs.ra = 0;
-+
-+ if (sps) sps[i] = uregs.sp;
-+ if (fps) fps[i] = uregs.fp;
-+ ips[i++] = uregs.pc - 1;
-+ if (debug)
-+ VG_(printf)(
-+ "USING bad-jump: pc: 0x%lx, sp: 0x%lx, fp: 0x%lx, ra: 0x%lx\n",
-+ uregs.pc, uregs.sp, uregs.fp, uregs.ra);
-+ uregs.pc = uregs.pc - 1;
-+ RECURSIVE_MERGE(cmrf,ips,i);
-+ continue;
-+ }
-+
-+ /* No luck. We have to give up. */
-+ break;
-+ }
-+
-+ n_found = i;
-+ return n_found;
-+}
+
++__asm__(
++".text \n\t"
++".globl VG_MINIMAL_SETJMP; \n\t"
++"VG_MINIMAL_SETJMP: \n\t"
++" st.d $ra, $a0, 0 \n\t"
++" st.d $sp, $a0, 8 \n\t"
++" st.d $r21, $a0, 16 \n\t"
++" st.d $fp, $a0, 24 \n\t"
++" st.d $s0, $a0, 32 \n\t"
++" st.d $s1, $a0, 40 \n\t"
++" st.d $s2, $a0, 48 \n\t"
++" st.d $s3, $a0, 56 \n\t"
++" st.d $s4, $a0, 64 \n\t"
++" st.d $s5, $a0, 72 \n\t"
++" st.d $s6, $a0, 80 \n\t"
++" st.d $s7, $a0, 88 \n\t"
++" st.d $s8, $a0, 96 \n\t"
++#if !defined(__loongarch_soft_float)
++" fst.d $f24, $a0, 104 \n\t"
++" fst.d $f25, $a0, 112 \n\t"
++" fst.d $f26, $a0, 120 \n\t"
++" fst.d $f27, $a0, 128 \n\t"
++" fst.d $f28, $a0, 136 \n\t"
++" fst.d $f29, $a0, 144 \n\t"
++" fst.d $f30, $a0, 152 \n\t"
++" fst.d $f30, $a0, 160 \n\t"
+#endif
-+
- /*------------------------------------------------------------*/
- /*--- ---*/
- /*--- END platform-dependent unwinder worker functions ---*/
-diff --git a/coregrind/m_syscall.c b/coregrind/m_syscall.c
-index 1e49ed4..84d30b9 100644
---- a/coregrind/m_syscall.c
-+++ b/coregrind/m_syscall.c
-@@ -204,6 +204,17 @@ SysRes VG_(mk_SysRes_arm64_linux) ( Long val ) {
- return res;
- }
-
-+SysRes VG_(mk_SysRes_loongarch64_linux) ( UWord val ) {
-+ SysRes res;
-+ res._isError = val >= -4095 && val <= -1;
-+ if (res._isError) {
-+ res._val = (UWord)(-val);
-+ } else {
-+ res._val = (UWord)val;
-+ }
-+ return res;
-+}
-+
- /* Generic constructors. */
- SysRes VG_(mk_SysRes_Success) ( UWord res ) {
- SysRes r;
-@@ -1034,6 +1045,22 @@ asm (
- ".previous \n\t"
- );
-
-+#elif defined(VGP_loongarch64_linux)
-+extern UWord do_syscall_WRK (UWord a1, UWord a2, UWord a3, /* $a0, $a1, $a2 */
-+ UWord a4, UWord a5, UWord a6, /* $a3, $a4, $a5 */
-+ UWord syscall_no); /* $a6 */
-+asm (
-+ ".text \n\t"
-+ ".globl do_syscall_WRK \n\t"
-+ ".type do_syscall_WRK, @function \n\t"
-+ "do_syscall_WRK: \n\t"
-+ " move $a7, $a6 \n\t" /* a7 = syscall_no */
-+ " syscall 0 \n\t"
-+ " jr $ra \n\t"
-+ ".size do_syscall_WRK, .-do_syscall_WRK \n\t"
-+ ".previous \n\t"
++" move $a0, $zero \n\t"
++" jr $ra \n\t"
++" \n\t"
++".text \n\t"
++".globl VG_MINIMAL_LONGJMP; \n\t"
++"VG_MINIMAL_LONGJMP: \n\t"
++" ld.d $ra, $a0, 0 \n\t"
++" ld.d $sp, $a0, 8 \n\t"
++" ld.d $r21, $a0, 16 \n\t"
++" ld.d $fp, $a0, 24 \n\t"
++" ld.d $s0, $a0, 32 \n\t"
++" ld.d $s1, $a0, 40 \n\t"
++" ld.d $s2, $a0, 48 \n\t"
++" ld.d $s3, $a0, 56 \n\t"
++" ld.d $s4, $a0, 64 \n\t"
++" ld.d $s5, $a0, 72 \n\t"
++" ld.d $s6, $a0, 80 \n\t"
++" ld.d $s7, $a0, 88 \n\t"
++" ld.d $s8, $a0, 96 \n\t"
++#if !defined(__loongarch_soft_float)
++" fld.d $f24, $a0, 104 \n\t"
++" fld.d $f25, $a0, 112 \n\t"
++" fld.d $f26, $a0, 120 \n\t"
++" fld.d $f27, $a0, 128 \n\t"
++" fld.d $f28, $a0, 136 \n\t"
++" fld.d $f29, $a0, 144 \n\t"
++" fld.d $f30, $a0, 152 \n\t"
++" fld.d $f30, $a0, 160 \n\t"
++#endif
++" bnez $a1, 1f \n\t"
++" addi.d $a1, $a1, 1 \n\t"
++"1: \n\t"
++" move $a0, $a1 \n\t"
++" jr $ra \n\t"
+);
++#endif /* VGP_loongarch64_linux */
+
- #elif defined(VGP_x86_solaris)
+ #if defined(VGP_arm64_freebsd)
- extern ULong
-@@ -1274,6 +1301,11 @@ SysRes VG_(do_syscall) ( UWord sysno, RegWord a1, RegWord a2, RegWord a3,
- do_syscall_WRK(a1, a2, a3, a4, a5, a6, sysno, ®_a0);
- return VG_(mk_SysRes_nanomips_linux)(reg_a0);
+ __asm__(
+diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c
+index 234efb3..18f62c7 100644
+--- a/coregrind/m_machine.c
++++ b/coregrind/m_machine.c
+@@ -152,6 +152,13 @@ void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs,
+ = VG_(threads)[tid].arch.vex.guest_r31;
+ regs->misc.MIPS64.r28
+ = VG_(threads)[tid].arch.vex.guest_r28;
++# elif defined(VGA_loongarch64)
++ regs->r_pc = VG_(threads)[tid].arch.vex.guest_PC;
++ regs->r_sp = VG_(threads)[tid].arch.vex.guest_R3;
++ regs->misc.LOONGARCH64.r_fp
++ = VG_(threads)[tid].arch.vex.guest_R22;
++ regs->misc.LOONGARCH64.r_ra
++ = VG_(threads)[tid].arch.vex.guest_R1;
+ # else
+ # error "Unknown arch"
+ # endif
+@@ -369,6 +376,39 @@ static void apply_to_GPs_of_tid(ThreadId tid, void (*f)(ThreadId,
+ (*f)(tid, "x28", vex->guest_X28);
+ (*f)(tid, "x29", vex->guest_X29);
+ (*f)(tid, "x30", vex->guest_X30);
++#elif defined(VGA_loongarch64)
++ (*f)(tid, "r0" , vex->guest_R0 );
++ (*f)(tid, "r1" , vex->guest_R1 );
++ (*f)(tid, "r2" , vex->guest_R2 );
++ (*f)(tid, "r3" , vex->guest_R3 );
++ (*f)(tid, "r4" , vex->guest_R4 );
++ (*f)(tid, "r5" , vex->guest_R5 );
++ (*f)(tid, "r6" , vex->guest_R6 );
++ (*f)(tid, "r7" , vex->guest_R7 );
++ (*f)(tid, "r8" , vex->guest_R8 );
++ (*f)(tid, "r9" , vex->guest_R9 );
++ (*f)(tid, "r10", vex->guest_R10);
++ (*f)(tid, "r11", vex->guest_R11);
++ (*f)(tid, "r12", vex->guest_R12);
++ (*f)(tid, "r13", vex->guest_R13);
++ (*f)(tid, "r14", vex->guest_R14);
++ (*f)(tid, "r15", vex->guest_R15);
++ (*f)(tid, "r16", vex->guest_R16);
++ (*f)(tid, "r17", vex->guest_R17);
++ (*f)(tid, "r18", vex->guest_R18);
++ (*f)(tid, "r19", vex->guest_R19);
++ (*f)(tid, "r20", vex->guest_R20);
++ (*f)(tid, "r21", vex->guest_R21);
++ (*f)(tid, "r22", vex->guest_R22);
++ (*f)(tid, "r23", vex->guest_R23);
++ (*f)(tid, "r24", vex->guest_R24);
++ (*f)(tid, "r25", vex->guest_R25);
++ (*f)(tid, "r26", vex->guest_R26);
++ (*f)(tid, "r27", vex->guest_R27);
++ (*f)(tid, "r28", vex->guest_R28);
++ (*f)(tid, "r29", vex->guest_R29);
++ (*f)(tid, "r30", vex->guest_R30);
++ (*f)(tid, "r31", vex->guest_R31);
+ #else
+ # error Unknown arch
+ #endif
+@@ -479,7 +519,7 @@ Int VG_(machine_arm_archlevel) = 4;
+ testing, so we need a VG_MINIMAL_JMP_BUF. */
+ #if defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
+ || defined(VGA_arm) || defined(VGA_s390x) || defined(VGA_mips32) \
+- || defined(VGA_mips64) || defined(VGA_arm64)
++ || defined(VGA_mips64) || defined(VGA_arm64) || defined(VGA_loongarch64)
+ #include "pub_core_libcsetjmp.h"
+ static VG_MINIMAL_JMP_BUF(env_unsup_insn);
+ static void handler_unsup_insn ( Int x ) {
+@@ -861,6 +901,105 @@ static Bool VG_(parse_cpuinfo)(void)
-+#elif defined(VGP_loongarch64_linux)
-+ UWord val = 0;
-+ val = do_syscall_WRK(a1, a2, a3, a4, a5, a6, sysno);
-+ return VG_(mk_SysRes_loongarch64_linux)(val);
-+
- # elif defined(VGP_x86_solaris)
- UInt val, val2, err = False;
- Bool restart;
-diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h
-index 7c9decf..a247334 100644
---- a/coregrind/m_syswrap/priv_syswrap-linux.h
-+++ b/coregrind/m_syswrap/priv_syswrap-linux.h
-@@ -509,6 +509,13 @@ extern UInt do_syscall_clone_nanomips_linux ( Word (*fn) (void *), /* a0 - 4 */
- Int* child_tid, /* a4 - 8 */
- Int* parent_tid, /* a5 - 9 */
- void* tls_ptr); /* a6 - 10 */
-+extern UInt do_syscall_clone_loongarch64_linux ( Word (*fn) (void *), /* a0 */
-+ void* stack, /* a1 */
-+ Int flags, /* a2 */
-+ void* arg, /* a3 */
-+ Int* child_tid, /* a4 */
-+ Int* parent_tid, /* a5 */
-+ void* tls_ptr); /* a6 */
- #endif // __PRIV_SYSWRAP_LINUX_H
+ #endif /* defined(VGP_arm64_linux) */
- /*--------------------------------------------------------------------*/
-diff --git a/coregrind/m_syswrap/priv_types_n_macros.h b/coregrind/m_syswrap/priv_types_n_macros.h
-index dd24183..11a9d5e 100644
---- a/coregrind/m_syswrap/priv_types_n_macros.h
-+++ b/coregrind/m_syswrap/priv_types_n_macros.h
-@@ -94,7 +94,8 @@ typedef
- || defined(VGP_ppc32_linux) \
- || defined(VGP_arm_linux) || defined(VGP_s390x_linux) \
- || defined(VGP_arm64_linux) \
-- || defined(VGP_nanomips_linux)
-+ || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- Int o_arg1;
- Int o_arg2;
- Int o_arg3;
-diff --git a/coregrind/m_syswrap/syscall-loongarch64-linux.S b/coregrind/m_syswrap/syscall-loongarch64-linux.S
-new file mode 100644
-index 0000000..5c18041
---- /dev/null
-+++ b/coregrind/m_syswrap/syscall-loongarch64-linux.S
-@@ -0,0 +1,143 @@
-+
-+/*--------------------------------------------------------------------*/
-+/*--- Support for doing system calls. syscall-loongarch64-linux.S ---*/
-+/*--------------------------------------------------------------------*/
++#if defined(VGA_loongarch64)
+
+/*
-+ This file is part of Valgrind, a dynamic binary instrumentation
-+ framework.
-+
-+ Copyright (C) 2021-2022 Loongson Technology Corporation Limited
-+
-+ This program is free software; you can redistribute it and/or
-+ modify it under the terms of the GNU General Public License as
-+ published by the Free Software Foundation; either version 2 of the
-+ License, or (at your option) any later version.
-+
-+ This program is distributed in the hope that it will be useful, but
-+ WITHOUT ANY WARRANTY; without even the implied warranty of
-+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-+ General Public License for more details.
-+
-+ You should have received a copy of the GNU General Public License
-+ along with this program; if not, see .
-+
-+ The GNU General Public License is contained in the file COPYING.
-+*/
-+
-+#include "pub_core_basics_asm.h"
++ * Initialize hwcaps by parsing /proc/cpuinfo. Returns False if it can not
++ * determine what CPU it is (it searches only for the models that are or may be
++ * supported by Valgrind).
++ */
++static Bool VG_(parse_cpuinfo)(void)
++{
++ Int n, fh;
++ SysRes fd;
++ SizeT num_bytes, file_buf_size;
++ HChar *file_buf;
+
-+#if defined(VGP_loongarch64_linux)
++ const char *search_Loongson_str = "Model Name\t\t: Loongson";
+
-+#include "pub_core_vkiscnums_asm.h"
-+#include "libvex_guest_offsets.h"
++ /* Slurp contents of /proc/cpuinfo into FILE_BUF */
++ fd = VG_(open)("/proc/cpuinfo", 0, VKI_S_IRUSR);
++ if (sr_isError(fd))
++ return False;
+
-+/*----------------------------------------------------------------*/
-+/*
-+ Perform a syscall for the client. This will run a syscall
-+ with the client's specific per-thread signal mask.
++ fh = sr_Res(fd);
+
-+ The structure of this function is such that, if the syscall is
-+ interrupted by a signal, we can determine exactly what
-+ execution state we were in with respect to the execution of
-+ the syscall by examining the value of PC in the signal
-+ handler. This means that we can always do the appropriate
-+ thing to precisely emulate the kernel's signal/syscall
-+ interactions.
++ /* Determine the size of /proc/cpuinfo.
++ Work around broken-ness in /proc file system implementation.
++ fstat returns a zero size for /proc/cpuinfo although it is
++ claimed to be a regular file. */
++ num_bytes = 0;
++ file_buf_size = 1000;
++ file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1);
++ while (True) {
++ n = VG_(read)(fh, file_buf, file_buf_size);
++ if (n < 0)
++ break;
+
-+ The syscall number is taken from the argument, even though it
-+ should also be in guest_state->guest_R11. The syscall result
-+ is written back to guest_state->guest_R4 on completion.
++ num_bytes += n;
++ if (n < file_buf_size)
++ break; /* reached EOF */
++ }
+
-+ VG_(fixup_guest_state_after_syscall_interrupted) does the
-+ thread state fixup in the case where we were interrupted by a
-+ signal.
++ if (n < 0)
++ num_bytes = 0; /* read error; ignore contents */
+
-+ Prototype:
++ if (num_bytes > file_buf_size) {
++ VG_(free)(file_buf);
++ VG_(lseek)(fh, 0, VKI_SEEK_SET);
++ file_buf = VG_(malloc)("cpuinfo", num_bytes + 1);
++ n = VG_(read)(fh, file_buf, num_bytes);
++ if (n < 0)
++ num_bytes = 0;
++ }
+
-+ UWord ML_(do_syscall_for_client_WRK)(
-+ Int syscallno, // $r4 - a0
-+ void* guest_state, // $r5 - a1
-+ const vki_sigset_t *sysmask, // $r6 - a2
-+ const vki_sigset_t *postmask, // $r7 - a3
-+ Int nsigwords) // $r8 - a4
-+*/
++ file_buf[num_bytes] = '\0';
++ VG_(close)(fh);
+
-+/* from vki-loongarch64-linux.h */
-+#define VKI_SIG_SETMASK 2
++ /* Parse file */
++ vai.hwcaps = 0;
++ if (VG_(strstr)(file_buf, search_Loongson_str) == NULL) {
++ /* Did not find string in the proc file. */
++ VG_(free)(file_buf);
++ return False;
++ }
+
-+.globl ML_(do_syscall_for_client_WRK)
-+ML_(do_syscall_for_client_WRK):
++ if (VG_(strstr)(file_buf, "loongarch32") != NULL)
++ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_ISA_32BIT;
++ if (VG_(strstr)(file_buf, "loongarch64") != NULL)
++ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_ISA_64BIT;
+
-+ /* Save regs on stack */
-+ addi.d $sp, $sp, -24
-+ st.d $a1, $sp, 0 /* guest_state */
-+ st.d $a3, $sp, 8 /* postmask */
-+ st.d $a4, $sp, 16 /* sigsetSzB */
++ if (VG_(strstr)(file_buf, "cpucfg") != NULL)
++ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_CPUCFG;
++ if (VG_(strstr)(file_buf, "lam") != NULL)
++ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_LAM;
++ if (VG_(strstr)(file_buf, "ual") != NULL)
++ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_UAL;
++ if (VG_(strstr)(file_buf, "fpu") != NULL)
++ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_FP;
++ if (VG_(strstr)(file_buf, "lsx") != NULL)
++ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_LSX;
++ if (VG_(strstr)(file_buf, "lasx") != NULL)
++ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_LASX;
++ if (VG_(strstr)(file_buf, "complex") != NULL)
++ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_COMPLEX;
++ if (VG_(strstr)(file_buf, "crypto") != NULL)
++ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_CRYPTO;
++ if (VG_(strstr)(file_buf, "lvz") != NULL)
++ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_LVZP;
++ if (VG_(strstr)(file_buf, "lbt_x86") != NULL)
++ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_X86BT;
++ if (VG_(strstr)(file_buf, "lbt_arm") != NULL)
++ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_ARMBT;
++ if (VG_(strstr)(file_buf, "lbt_mips") != NULL)
++ vai.hwcaps |= VEX_HWCAPS_LOONGARCH_MIPSBT;
+
-+1: li.w $a7, __NR_rt_sigprocmask
-+ li.w $a0, VKI_SIG_SETMASK
-+ move $a1, $a2 /* syscall_mask */
-+ move $a2, $a3 /* postmask */
-+ move $a3, $a4 /* sigsetSzB */
-+ syscall 0
++ VG_(free)(file_buf);
++ return True;
++}
+
-+ bnez $a0, 5f
++#endif /* defined(VGP_loongarch64) */
+
-+ /* Actually do the client syscall */
-+ ld.d $a6, $sp, 0 /* guest_state */
+ Bool VG_(machine_get_hwcaps)( void )
+ {
+ vg_assert(hwcaps_done == False);
+@@ -2241,6 +2380,54 @@ Bool VG_(machine_get_hwcaps)( void )
+
+ return True;
+ }
+
-+ ld.d $a0, $a6, OFFSET_loongarch64_R4 /* a0 */
-+ ld.d $a1, $a6, OFFSET_loongarch64_R5 /* a1 */
-+ ld.d $a2, $a6, OFFSET_loongarch64_R6 /* a2 */
-+ ld.d $a3, $a6, OFFSET_loongarch64_R7 /* a3 */
-+ ld.d $a4, $a6, OFFSET_loongarch64_R8 /* a4 */
-+ ld.d $a5, $a6, OFFSET_loongarch64_R9 /* a5 */
++#elif defined(VGA_loongarch64)
++ {
++ va = VexArchLOONGARCH64;
++ vai.endness = VexEndnessLE;
++ vai.hwcaps = 0;
+
-+ ld.d $a7, $a6, OFFSET_loongarch64_R11 /* syscallno */
++ if (!VG_(parse_cpuinfo)())
++ return False;
+
-+2: syscall 0
++ /* Same instruction set detection algorithm as for ppc32/arm... */
++ vki_sigset_t saved_set, tmp_set;
++ vki_sigaction_fromK_t saved_sigill_act;
++ vki_sigaction_toK_t tmp_sigill_act;
+
-+ /* Saving return values into guest state */
-+3: st.d $a0, $a6, OFFSET_loongarch64_R4 /* a0 */
++ vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
+
-+4: li.w $a7, __NR_rt_sigprocmask
-+ li.w $a0, VKI_SIG_SETMASK
-+ ld.d $a1, $sp, 8 /* postmask */
-+ move $a2, $zero /* 0 (zero) */
-+ ld.d $a3, $sp, 16 /* sigsetSzB */
-+ syscall 0
++ VG_(sigemptyset)(&tmp_set);
++ VG_(sigaddset)(&tmp_set, VKI_SIGILL);
+
-+ beqz $a0, 6f
++ Int r;
++ r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
++ vg_assert(r == 0);
+
-+5: /* error */
-+ li.w $a0, 0x8000
++ r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
++ vg_assert(r == 0);
++ tmp_sigill_act = saved_sigill_act;
+
-+6: /* Restore sp and return */
-+ addi.d $sp, $sp, 24
-+ jr $ra
++ /* NODEFER: signal handler does not return (from the kernel's point of
++ view), hence if it is to successfully catch a signal more than once,
++ we need the NODEFER flag. */
++ tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
++ tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
++ tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
++ tmp_sigill_act.ksa_handler = handler_unsup_insn;
++ VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
+
-+.section .rodata
-+/* export the ranges so that
-+ VG_(fixup_guest_state_after_syscall_interrupted) can do the
-+ right thing */
++ VG_(convert_sigaction_fromK_to_toK)(&saved_sigill_act, &tmp_sigill_act);
++ VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
++ VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
+
-+.globl ML_(blksys_setup)
-+.globl ML_(blksys_restart)
-+.globl ML_(blksys_complete)
-+.globl ML_(blksys_committed)
-+.globl ML_(blksys_finished)
-+ML_(blksys_setup): .quad 1b
-+ML_(blksys_restart): .quad 2b
-+ML_(blksys_complete): .quad 3b
-+ML_(blksys_committed): .quad 4b
-+ML_(blksys_finished): .quad 5b
++ VG_(debugLog)(1, "machine", "hwcaps = 0x%x\n", vai.hwcaps);
+
-+#endif // defined(VGP_loongarch64_linux)
++ VG_(machine_get_cache_info)(&vai);
+
-+/* Let the linker know we don't need an executable stack */
-+MARK_STACK_NO_EXEC
++ return True;
++ }
+
-+/*--------------------------------------------------------------------*/
-+/*--- end syscall-loongarch64-linux.S ---*/
-+/*--------------------------------------------------------------------*/
-diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c
-index d2ff8c0..f3c2317 100644
---- a/coregrind/m_syswrap/syswrap-generic.c
-+++ b/coregrind/m_syswrap/syswrap-generic.c
-@@ -3440,7 +3440,7 @@ POST(sys_newfstat)
- #endif
-
- #if !defined(VGO_solaris) && !defined(VGP_arm64_linux) && \
-- !defined(VGP_nanomips_linux)
-+ !defined(VGP_nanomips_linux) && !defined(VGP_loongarch64_linux)
- static vki_sigset_t fork_saved_mask;
-
- // In Linux, the sys_fork() function varies across architectures, but we
-diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
-index d571fc3..02a62e4 100644
---- a/coregrind/m_syswrap/syswrap-linux.c
-+++ b/coregrind/m_syswrap/syswrap-linux.c
-@@ -310,6 +310,16 @@ static void run_a_thread_NORETURN ( Word tidW )
- : "r" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)
- : "memory" , "$t4", "$a0"
- );
-+#elif defined(VGP_loongarch64_linux)
-+ asm volatile (
-+ "st.w %1, %0 \n\t" /* set tst->status = VgTs_Empty */
-+ "li.w $a7, %2 \n\t" /* set a7 = __NR_exit */
-+ "ld.w $a0, %3 \n\t" /* set a0 = tst->os_state.exitcode */
-+ "syscall 0 \n\t" /* exit(tst->os_state.exitcode) */
-+ : "=m" (tst->status)
-+ : "r" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)
-+ : "memory", "a0", "a7"
-+ );
#else
- # error Unknown platform
+ # error "Unknown arch"
#endif
-@@ -535,6 +545,13 @@ static SysRes clone_new_thread ( Word (*fn)(void *),
- (ML_(start_thread_NORETURN), stack, flags, ctst,
- child_tidptr, parent_tidptr, NULL);
- res = VG_ (mk_SysRes_nanomips_linux) (ret);
-+#elif defined(VGP_loongarch64_linux)
-+ UInt ret = 0;
-+ ctst->arch.vex.guest_R4 = 0;
-+ ret = do_syscall_clone_loongarch64_linux
-+ (ML_(start_thread_NORETURN), stack, flags, ctst,
-+ child_tidptr, parent_tidptr, NULL);
-+ res = VG_(mk_SysRes_loongarch64_linux)(ret);
+@@ -2381,6 +2568,9 @@ Int VG_(machine_get_size_of_largest_guest_register) ( void )
+ # elif defined(VGA_mips64)
+ return 8;
+
++# elif defined(VGA_loongarch64)
++ return 8;
++
+ # else
+ # error "Unknown arch"
+ # endif
+@@ -2397,7 +2587,7 @@ void* VG_(fnptr_to_fnentry)( void* f )
+ || defined(VGP_s390x_linux) || defined(VGP_mips32_linux) \
+ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
+ || defined(VGP_x86_solaris) || defined(VGP_amd64_solaris) \
+- || defined(VGP_nanomips_linux)
++ || defined(VGP_nanomips_linux) || defined(VGP_loongarch64_linux)
+ return f;
+ # elif defined(VGP_ppc64be_linux)
+ /* ppc64-linux uses the AIX scheme, in which f is a pointer to a
+diff --git a/coregrind/m_main.c b/coregrind/m_main.c
+index 22b4fea..fffe3c9 100644
+--- a/coregrind/m_main.c
++++ b/coregrind/m_main.c
+@@ -1502,6 +1502,7 @@ Int valgrind_main ( Int argc, HChar **argv, HChar **envp )
+ "AMD Athlon or above)\n");
+ VG_(printf)(" * AMD Athlon64/Opteron\n");
+ VG_(printf)(" * ARM (armv7)\n");
++ VG_(printf)(" * LoongArch (3A5000 and above)\n");
+ VG_(printf)(" * MIPS (mips32 and above; mips64 and above)\n");
+ VG_(printf)(" * PowerPC (most; ppc405 and above)\n");
+ VG_(printf)(" * System z (64bit only - s390x; z990 and above)\n");
+@@ -2558,6 +2559,11 @@ static void final_tidyup(ThreadId tid)
+ VG_TRACK(post_reg_write, Vg_CoreClientReq, tid,
+ offsetof(VexGuestS390XState, guest_r2),
+ sizeof(VG_(threads)[tid].arch.vex.guest_r2));
++# elif defined(VGA_loongarch64)
++ VG_(threads)[tid].arch.vex.guest_R4 = to_run;
++ VG_TRACK(post_reg_write, Vg_CoreClientReq, tid,
++ offsetof(VexGuestLOONGARCH64State, guest_R4),
++ sizeof(VG_(threads)[tid].arch.vex.guest_R4));
#else
- # error Unknown platform
+ I_die_here : architecture missing in m_main.c
#endif
-@@ -597,6 +614,8 @@ static SysRes setup_child_tls (ThreadId ctid, Addr tlsaddr)
- #elif defined(VGP_mips32_linux) || defined(VGP_nanomips_linux)
- ctst->arch.vex.guest_ULR = tlsaddr;
- ctst->arch.vex.guest_r27 = tlsaddr;
+@@ -3086,6 +3092,29 @@ asm(
+ ".set pop \n\t"
+ ".previous \n\t"
+ );
+#elif defined(VGP_loongarch64_linux)
-+ ctst->arch.vex.guest_R2 = tlsaddr;
++asm(" \n\t"
++ ".text \n\t"
++ ".globl _start \n\t"
++ ".type _start,@function \n\t"
++ "_start: \n\t"
++ /* t0 = &vgPlain_interim_stack + VG_STACK_GUARD_SZB +
++ VG_DEFAULT_STACK_ACTIVE_SZB */
++ "la.local $t0, vgPlain_interim_stack \n\t"
++ "li.w $t1, "VG_STRINGIFY(VG_STACK_GUARD_SZB)" \n\t"
++ "add.d $t0, $t0, $t1 \n\t"
++ "li.w $t2, "VG_STRINGIFY(VG_DEFAULT_STACK_ACTIVE_SZB)" \n\t"
++ "add.d $t0, $t0, $t2 \n\t"
++ /* allocate 16 bytes on the new stack in t0, and aligned */
++ "addi.d $t0, $t0, -16 \n\t"
++ "bstrins.d $t0, $zero, 3, 0 \n\t"
++ /* a0 = sp, sp = t0, and then call _start_in_C_linux */
++ "move $a0, $sp \n\t"
++ "move $sp, $t0 \n\t"
++ "la.local $t0, _start_in_C_linux \n\t"
++ "jr $t0 \n\t"
++ ".previous \n\t"
++);
#else
- # error Unknown platform
+ # error "Unknown platform"
#endif
-@@ -755,7 +774,7 @@ static SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
- || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
- || defined(VGP_arm_linux) || defined(VGP_mips32_linux) \
- || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
-- || defined(VGP_nanomips_linux)
-+ || defined(VGP_nanomips_linux) || defined(VGP_loongarch64_linux)
- res = VG_(do_syscall5)( __NR_clone, flags,
- (UWord)NULL, (UWord)parent_tidptr,
- (UWord)NULL, (UWord)child_tidptr );
-@@ -828,7 +847,8 @@ PRE(sys_clone)
- #define PRA_CHILD_TIDPTR PRA5
- #define ARG_TLS ARG4
- #define PRA_TLS PRA4
--#elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux)
-+#elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \
-+ || defined(VGP_loongarch64_linux)
- #define ARG_CHILD_TIDPTR ARG4
- #define PRA_CHILD_TIDPTR PRA4
- #define ARG_TLS ARG5
-@@ -4342,9 +4362,11 @@ PRE(sys_sigaction)
- PRE_MEM_READ( "sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
- PRE_MEM_READ( "sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
- PRE_MEM_READ( "sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
-+#if !defined(VGP_loongarch64_linux)
- if (ML_(safe_to_deref)(sa,sizeof(struct vki_old_sigaction))
- && (sa->sa_flags & VKI_SA_RESTORER))
- PRE_MEM_READ( "sigaction(act->sa_restorer)", (Addr)&sa->sa_restorer, sizeof(sa->sa_restorer));
-+#endif
+@@ -3131,11 +3160,11 @@ void _start_in_C_linux ( UWord* pArgc )
+ # if defined(VGP_ppc32_linux) || defined(VGP_ppc64be_linux) \
+ || defined(VGP_ppc64le_linux) || defined(VGP_arm64_linux) \
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
+- || defined(VGP_nanomips_linux)
++ || defined(VGP_nanomips_linux) || defined(VGP_loongarch64_linux)
+ {
+- /* ppc32/ppc64, arm64, mips32/64 can be configured with different
+- page sizes. Determine this early. This is an ugly hack and really
+- should be moved into valgrind_main. */
++ /* ppc32/ppc64, arm64, mips32/64, loongarch64 can be configured with
++ different page sizes. Determine this early. This is an ugly hack
++ and really should be moved into valgrind_main. */
+ UWord *sp = &pArgc[1+argc+1];
+ while (*sp++ != 0)
+ ;
+diff --git a/coregrind/m_options.c b/coregrind/m_options.c
+index ecbe9fc..76a689d 100644
+--- a/coregrind/m_options.c
++++ b/coregrind/m_options.c
+@@ -203,7 +203,8 @@ UInt VG_(clo_unw_stack_scan_frames) = 5;
+ VgSmc VG_(clo_smc_check) = Vg_SmcAllNonFile;
+ #elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
+ || defined(VGA_arm) || defined(VGA_arm64) \
+- || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips)
++ || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips) \
++ || defined(VGA_loongarch64)
+ VgSmc VG_(clo_smc_check) = Vg_SmcStack;
+ #else
+ # error "Unknown arch"
+diff --git a/coregrind/m_redir.c b/coregrind/m_redir.c
+index f9e8d88..3f71d2e 100644
+--- a/coregrind/m_redir.c
++++ b/coregrind/m_redir.c
+@@ -1248,6 +1248,7 @@ Bool VG_(is_soname_ld_so) (const HChar *soname)
+ if (VG_STREQ(soname, VG_U_LD_LINUX_AARCH64_SO_1)) return True;
+ if (VG_STREQ(soname, VG_U_LD_LINUX_ARMHF_SO_3)) return True;
+ if (VG_STREQ(soname, VG_U_LD_LINUX_MIPSN8_S0_1)) return True;
++ if (VG_STREQ(soname, VG_U_LD_LINUX_LOONGARCH_LP64D_SO_1)) return True;
+ # elif defined(VGO_freebsd)
+ if (VG_STREQ(soname, VG_U_LD_ELF_SO_1)) return True;
+ if (VG_STREQ(soname, VG_U_LD_ELF32_SO_1)) return True;
+@@ -1696,6 +1697,22 @@ void VG_(redir_initialise) ( void )
+ );
}
- if (ARG3 != 0) {
-@@ -4374,7 +4396,9 @@ PRE(sys_sigaction)
-
- new.ksa_handler = oldnew->ksa_handler;
- new.sa_flags = oldnew->sa_flags;
-+#if !defined(VGP_loongarch64_linux)
- new.sa_restorer = oldnew->sa_restorer;
-+#endif
- convert_sigset_to_rt(&oldnew->sa_mask, &new.sa_mask);
- newp = &new;
- }
-@@ -4387,7 +4411,9 @@ PRE(sys_sigaction)
++#elif defined(VGP_loongarch64_linux)
++ /* If we're using memcheck, use these intercepts right from
++ the start, otherwise ld.so makes a lot of noise. */
++ if (0==VG_(strcmp)("Memcheck", VG_(details).name)) {
++ add_hardwired_spec(
++ "ld-linux-loongarch-lp64d.so.1", "strlen",
++ (Addr)&VG_(loongarch64_linux_REDIR_FOR_strlen),
++ complain_about_stripped_glibc_ldso
++ );
++ add_hardwired_spec(
++ "ld-linux-loongarch-lp64d.so.1", "strchr",
++ (Addr)&VG_(loongarch64_linux_REDIR_FOR_strchr),
++ complain_about_stripped_glibc_ldso
++ );
++ }
++
+ # elif defined(VGP_x86_solaris)
+ /* If we're using memcheck, use these intercepts right from
+ the start, otherwise ld.so makes a lot of noise. */
+diff --git a/coregrind/m_scheduler/scheduler.c b/coregrind/m_scheduler/scheduler.c
+index cc8d070..8a1e9cb 100644
+--- a/coregrind/m_scheduler/scheduler.c
++++ b/coregrind/m_scheduler/scheduler.c
+@@ -272,6 +272,7 @@ const HChar* name_of_sched_event ( UInt event )
+ case VEX_TRC_JMP_SIGBUS: return "SIGBUS";
+ case VEX_TRC_JMP_SIGFPE_INTOVF:
+ case VEX_TRC_JMP_SIGFPE_INTDIV: return "SIGFPE";
++ case VEX_TRC_JMP_SIGSYS: return "SIGSYS";
+ case VEX_TRC_JMP_EMWARN: return "EMWARN";
+ case VEX_TRC_JMP_EMFAIL: return "EMFAIL";
+ case VEX_TRC_JMP_CLIENTREQ: return "CLIENTREQ";
+@@ -1687,6 +1688,10 @@ VgSchedReturnCode VG_(scheduler) ( ThreadId tid )
+ VG_(synth_sigfpe)(tid, VKI_FPE_INTOVF);
+ break;
- oldold->ksa_handler = oldp->ksa_handler;
- oldold->sa_flags = oldp->sa_flags;
-+#if !defined(VGP_loongarch64_linux)
- oldold->sa_restorer = oldp->sa_restorer;
-+#endif
- oldold->sa_mask = oldp->sa_mask.sig[0];
- }
- }
-@@ -4460,10 +4486,13 @@ PRE(sys_rt_sigaction)
- PRE_MEM_READ( "rt_sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
- PRE_MEM_READ( "rt_sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
- PRE_MEM_READ( "rt_sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
-+#if !defined(VGP_loongarch64_linux)
- if (ML_(safe_to_deref)(sa,sizeof(vki_sigaction_toK_t))
- && (sa->sa_flags & VKI_SA_RESTORER))
- PRE_MEM_READ( "rt_sigaction(act->sa_restorer)", (Addr)&sa->sa_restorer, sizeof(sa->sa_restorer));
-+#endif
- }
++ case VEX_TRC_JMP_SIGSYS:
++ VG_(synth_sigsys)(tid);
++ break;
+
- if (ARG3 != 0)
- PRE_MEM_WRITE( "rt_sigaction(oldact)", ARG3, sizeof(vki_sigaction_fromK_t));
+ case VEX_TRC_JMP_NODECODE: {
+ Addr addr = VG_(get_IP)(tid);
-@@ -6815,7 +6844,8 @@ POST(sys_lookup_dcookie)
+@@ -1851,6 +1856,9 @@ void VG_(nuke_all_threads_except) ( ThreadId me, VgSchedReturnCode src )
+ #elif defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips)
+ # define VG_CLREQ_ARGS guest_r12
+ # define VG_CLREQ_RET guest_r11
++#elif defined(VGA_loongarch64)
++# define VG_CLREQ_ARGS guest_R12
++# define VG_CLREQ_RET guest_R11
+ #else
+ # error Unknown arch
#endif
-
- #if defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \
-- || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- PRE(sys_lookup_dcookie)
- {
- *flags |= SfMayBlock;
-diff --git a/coregrind/m_syswrap/syswrap-loongarch64-linux.c b/coregrind/m_syswrap/syswrap-loongarch64-linux.c
+diff --git a/coregrind/m_sigframe/sigframe-loongarch64-linux.c b/coregrind/m_sigframe/sigframe-loongarch64-linux.c
new file mode 100644
-index 0000000..c684112
+index 0000000..eda6c88
--- /dev/null
-+++ b/coregrind/m_syswrap/syswrap-loongarch64-linux.c
-@@ -0,0 +1,644 @@
++++ b/coregrind/m_sigframe/sigframe-loongarch64-linux.c
+@@ -0,0 +1,285 @@
+
-+/*---------------------------------------------------------------------*/
-+/*--- Platform-specific syscalls stuff. syswrap-loongarch64-linux.c ---*/
-+/*---------------------------------------------------------------------*/
++/*--------------------------------------------------------------------*/
++/*--- Create/destroy signal delivery frames. ---*/
++/*--- sigframe-loongarch64-linux.c ---*/
++/*--------------------------------------------------------------------*/
+
+/*
+ This file is part of Valgrind, a dynamic binary instrumentation
@@ -28616,2655 +32895,2506 @@ index 0000000..c684112
+#include "pub_core_libcbase.h"
+#include "pub_core_libcassert.h"
+#include "pub_core_libcprint.h"
-+#include "pub_core_libcsignal.h"
++#include "pub_core_machine.h"
+#include "pub_core_options.h"
-+#include "pub_core_scheduler.h"
-+#include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
-+#include "pub_core_syscall.h"
-+#include "pub_core_syswrap.h"
++#include "pub_core_sigframe.h"
++#include "pub_core_signals.h"
+#include "pub_core_tooliface.h"
++#include "pub_core_trampoline.h"
++#include "priv_sigframe.h"
+
-+#include "priv_types_n_macros.h"
-+#include "priv_syswrap-generic.h" /* for decls of generic wrappers */
-+#include "priv_syswrap-linux.h" /* for decls of linux-ish wrappers */
-+#include "priv_syswrap-main.h"
+
++/*------------------------------------------------------------*/
++/*--- Signal frame layouts ---*/
++/*------------------------------------------------------------*/
+
-+/* ---------------------------------------------------------------------
-+ clone() handling
-+ ------------------------------------------------------------------ */
++struct vg_sig_private {
++ UInt magicPI;
++ UInt sigNo_private;
++ VexGuestLOONGARCH64State vex_shadow1;
++ VexGuestLOONGARCH64State vex_shadow2;
++};
+
-+/* Call f(arg1), but first switch stacks, using 'stack' as the new
-+ stack, and use 'retaddr' as f's return-to address. Also, clear all
-+ the integer registers before entering f. */
-+__attribute__((noreturn))
-+void ML_(call_on_new_stack_0_1) ( Addr stack,
-+ Addr retaddr,
-+ void (*f) (Word),
-+ Word arg1 );
-+asm (
-+".text\n"
-+".globl vgModuleLocal_call_on_new_stack_0_1 \n\t"
-+"vgModuleLocal_call_on_new_stack_0_1: \n\t"
-+" move $sp, $a0 \n\t" /* sp = stack */
-+" move $ra, $a1 \n\t" /* ra = retaddr */
-+" move $t0, $a2 \n\t" /* t0 = f */
-+" move $a0, $a3 \n\t" /* a0 = arg1 */
-+" move $a1, $zero \n\t" /* zero all GP regs */
-+" move $a2, $zero \n\t"
-+" move $a3, $zero \n\t"
-+" move $a4, $zero \n\t"
-+" move $a5, $zero \n\t"
-+" move $a6, $zero \n\t"
-+" move $a7, $zero \n\t"
-+/* don't zero out t0 */
-+" move $t1, $zero \n\t"
-+" move $t2, $zero \n\t"
-+" move $t3, $zero \n\t"
-+" move $t4, $zero \n\t"
-+" move $t5, $zero \n\t"
-+" move $t6, $zero \n\t"
-+" move $t7, $zero \n\t"
-+" move $t8, $zero \n\t"
-+" jr $t0 \n\t" /* jump to f */
-+".previous \n\t"
-+);
++struct rt_sigframe {
++ struct vki_siginfo rs_info;
++ struct vki_ucontext rs_uctx;
++ struct vg_sig_private priv;
++};
+
-+/*
-+ Perform a clone system call. clone is strange because it has
-+ fork()-like return-twice semantics, so it needs special
-+ handling here.
+
-+ Upon entry, we have:
++/*------------------------------------------------------------*/
++/*--- Creating signal frames ---*/
++/*------------------------------------------------------------*/
+
-+ Word (*fn)(void*) in a0
-+ void* child_stack in a1
-+ int flags in a2
-+ void* arg in a3
-+ pid_t* child_tid in a4
-+ pid_t* parent_tid in a5
-+ void* tls_ptr in a6
++static void create_siginfo ( ThreadId tid,
++ struct rt_sigframe *frame,
++ const vki_siginfo_t *si)
++{
++ VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame siginfo",
++ (Addr)&frame->rs_info, sizeof(frame->rs_info));
+
-+ System call requires:
++ VG_(memcpy)(&frame->rs_info, si, sizeof(vki_siginfo_t));
+
-+ unsigned long clone_flags in a0
-+ unsigned long newsp in a1
-+ int* parent_tidptr in a2
-+ int* child_tidptr in a3
-+ unsigned long tls in a4
-+ int __NR_clone in a7
-+*/
++ VG_TRACK(post_mem_write, Vg_CoreSignal, tid,
++ (Addr)&frame->rs_info, sizeof(frame->rs_info));
++}
+
-+#define __NR_CLONE VG_STRINGIFY(__NR_clone)
-+#define __NR_EXIT VG_STRINGIFY(__NR_exit)
++static void create_sigcontext ( ThreadState *tst,
++ struct vki_sigcontext **sc)
++{
++ struct vki_sigcontext *sctx = *sc;
+
-+// See priv_syswrap-linux.h for arg profile.
-+asm(
-+".text \n\t"
-+".globl do_syscall_clone_loongarch64_linux \n\t"
-+"do_syscall_clone_loongarch64_linux: \n\t"
-+/* Save ra */
-+" addi.d $sp, $sp, -16 \n\t"
-+" st.d $ra, $sp, 0 \n\t"
++ VG_TRACK(pre_mem_write, Vg_CoreSignal, tst->tid, "signal frame mcontext",
++ (Addr)sctx, sizeof(ULong) * 32);
+
-+/* Save fn and arg */
-+" addi.d $a1, $a1, -16 \n\t"
-+" st.d $a0, $a1, 0 \n\t" /* fn */
-+" st.d $a3, $a1, 8 \n\t" /* arg */
++ sctx->sc_regs[1] = tst->arch.vex.guest_R1;
++ sctx->sc_regs[2] = tst->arch.vex.guest_R2;
++ sctx->sc_regs[3] = tst->arch.vex.guest_R3;
++ sctx->sc_regs[4] = tst->arch.vex.guest_R4;
++ sctx->sc_regs[5] = tst->arch.vex.guest_R5;
++ sctx->sc_regs[6] = tst->arch.vex.guest_R6;
++ sctx->sc_regs[7] = tst->arch.vex.guest_R7;
++ sctx->sc_regs[8] = tst->arch.vex.guest_R8;
++ sctx->sc_regs[9] = tst->arch.vex.guest_R9;
++ sctx->sc_regs[10] = tst->arch.vex.guest_R10;
++ sctx->sc_regs[11] = tst->arch.vex.guest_R11;
++ sctx->sc_regs[12] = tst->arch.vex.guest_R12;
++ sctx->sc_regs[13] = tst->arch.vex.guest_R13;
++ sctx->sc_regs[14] = tst->arch.vex.guest_R14;
++ sctx->sc_regs[15] = tst->arch.vex.guest_R15;
++ sctx->sc_regs[16] = tst->arch.vex.guest_R16;
++ sctx->sc_regs[17] = tst->arch.vex.guest_R17;
++ sctx->sc_regs[18] = tst->arch.vex.guest_R18;
++ sctx->sc_regs[19] = tst->arch.vex.guest_R19;
++ sctx->sc_regs[20] = tst->arch.vex.guest_R20;
++ sctx->sc_regs[21] = tst->arch.vex.guest_R21;
++ sctx->sc_regs[22] = tst->arch.vex.guest_R22;
++ sctx->sc_regs[23] = tst->arch.vex.guest_R23;
++ sctx->sc_regs[24] = tst->arch.vex.guest_R24;
++ sctx->sc_regs[25] = tst->arch.vex.guest_R25;
++ sctx->sc_regs[26] = tst->arch.vex.guest_R26;
++ sctx->sc_regs[27] = tst->arch.vex.guest_R27;
++ sctx->sc_regs[28] = tst->arch.vex.guest_R28;
++ sctx->sc_regs[29] = tst->arch.vex.guest_R29;
++ sctx->sc_regs[30] = tst->arch.vex.guest_R30;
++ sctx->sc_regs[31] = tst->arch.vex.guest_R31;
++ sctx->sc_pc = tst->arch.vex.guest_PC;
++}
+
-+/* Call sys_clone */
-+" move $a0, $a2 \n\t" /* flags */
-+" move $a2, $a5 \n\t" /* parent */
-+" move $a3, $a4 \n\t" /* child */
-+" move $a4, $a6 \n\t" /* tls */
-+" li.w $a7, " __NR_CLONE " \n\t"
-+" syscall 0 \n\t"
++static void create_ucontext ( ThreadState *tst,
++ ThreadId tid,
++ struct vki_ucontext *uc,
++ const vki_sigset_t *mask,
++ struct vki_sigcontext **sc,
++ const vki_siginfo_t *siginfo)
++{
++ VG_TRACK(pre_mem_write, Vg_CoreSignal, tid, "signal frame ucontext",
++ (Addr)uc, offsetof(struct vki_ucontext, uc_mcontext));
+
-+/* If we are a child? */
-+" bnez $a0, 1f \n\t"
++ uc->uc_flags = 0;
++ uc->uc_link = 0;
++ uc->uc_stack = tst->altstack;
++ uc->uc_sigmask = *mask;
+
-+/* Restore fn and arg */
-+" ld.d $a1, $sp, 0 \n\t" /* fn */
-+" ld.d $a0, $sp, 8 \n\t" /* arg */
++ VG_TRACK(post_mem_write, Vg_CoreSignal, tid, (Addr)uc,
++ offsetof(struct vki_ucontext, uc_mcontext));
+
-+/* Call fn(arg) */
-+" jr $a1 \n\t"
++ create_sigcontext(tst, sc);
++}
+
-+/* Call exit(a0) */
-+" li.w $a7, " __NR_EXIT" \n\t"
-+" syscall 0 \n\t"
++/* EXPORTED */
++void VG_(sigframe_create) ( ThreadId tid,
++ Bool on_altstack,
++ Addr sp_top_of_frame,
++ const vki_siginfo_t *siginfo,
++ const struct vki_ucontext *siguc,
++ void *handler,
++ UInt flags,
++ const vki_sigset_t *mask,
++ void *restorer )
++{
++ UInt size = sizeof(struct rt_sigframe);
++ Addr sp = VG_ROUNDDN(sp_top_of_frame - size, 16);
+
-+/* If we are parent or error, just return to caller */
-+"1: \n\t"
-+" ld.d $ra, $sp, 0 \n\t"
-+" addi.d $sp, $sp, 16 \n\t"
-+" jr $ra \n\t"
-+".previous \n\t"
-+);
++ ThreadState *tst = VG_(get_ThreadState)(tid);
++ if (! ML_(sf_maybe_extend_stack)(tst, sp, size, flags))
++ return;
+
-+#undef __NR_CLONE
-+#undef __NR_EXIT
++ struct rt_sigframe *frame = (struct rt_sigframe *)sp;
++ create_siginfo(tid, frame, siginfo);
+
-+/* ---------------------------------------------------------------------
-+ More thread stuff
-+ ------------------------------------------------------------------ */
++ struct vki_ucontext *uctx = &frame->rs_uctx;
++ struct vki_sigcontext *sctx = &(frame->rs_uctx.uc_mcontext);
++ create_ucontext(tst, tid, uctx, mask, &sctx, siginfo);
+
-+// loongarch64 doesn't have any architecture specific thread stuff that
-+// needs to be cleaned up
-+void VG_(cleanup_thread) ( ThreadArchState* arch )
-+{
-+}
++ /*
++ Arguments to signal handler:
+
-+/* ---------------------------------------------------------------------
-+ PRE/POST wrappers for loongarch64/Linux-specific syscalls
-+ ------------------------------------------------------------------ */
++ a0 = signal number
++ a1 = pointer to siginfo
++ a2 = pointer to ucontext
+
-+#define PRE(name) DEFN_PRE_TEMPLATE(loongarch64_linux, name)
-+#define POST(name) DEFN_POST_TEMPLATE(loongarch64_linux, name)
++ csr_era point to the signal handler, $r3 (sp) points to
++ the struct rt_sigframe.
++ */
+
-+/* Add prototypes for the wrappers declared here, so that gcc doesn't
-+ harass us for not having prototypes. Really this is a kludge --
-+ the right thing to do is to make these wrappers 'static' since they
-+ aren't visible outside this file, but that requires even more macro
-+ magic. */
-+DECL_TEMPLATE(loongarch64_linux, sys_ptrace);
-+DECL_TEMPLATE(loongarch64_linux, sys_mmap);
-+DECL_TEMPLATE(loongarch64_linux, sys_rt_sigreturn);
++ Int sigNo = siginfo->si_signo;
++ tst->arch.vex.guest_R4 = sigNo;
++ tst->arch.vex.guest_R5 = (Addr) &frame->rs_info;
++ tst->arch.vex.guest_R6 = (Addr) &frame->rs_uctx;
++ tst->arch.vex.guest_R3 = (Addr) frame;
++ tst->arch.vex.guest_R1 = (Addr) &VG_(loongarch64_linux_SUBST_FOR_rt_sigreturn);
+
-+PRE(sys_ptrace)
++ struct vg_sig_private *priv = &frame->priv;
++ priv->magicPI = 0x31415927;
++ priv->sigNo_private = sigNo;
++ priv->vex_shadow1 = tst->arch.vex_shadow1;
++ priv->vex_shadow2 = tst->arch.vex_shadow2;
++
++ /* Set the thread so it will next run the handler. */
++ VG_TRACK(post_reg_write, Vg_CoreSignal, tid, VG_O_STACK_PTR, sizeof(Addr));
++
++ if (VG_(clo_trace_signals))
++ VG_(printf)("handler = %p\n", handler);
++
++ tst->arch.vex.guest_PC = (Addr) handler;
++ /* This thread needs to be marked runnable, but we leave that
++ the caller to do. */
++}
++
++
++/*------------------------------------------------------------*/
++/*--- Destroying signal frames ---*/
++/*------------------------------------------------------------*/
++
++static void restore_regs ( ThreadState *tst,
++ struct vki_sigcontext *mc)
+{
-+ PRINT("sys_ptrace ( %ld, %ld, %lx, %lx )",
-+ SARG1, SARG2, ARG3, ARG4);
-+ PRE_REG_READ4(int, "ptrace",
-+ long, request,
-+ long, pid,
-+ unsigned long, addr,
-+ unsigned long, data);
-+ switch (ARG1) {
-+ case VKI_PTRACE_PEEKTEXT:
-+ case VKI_PTRACE_PEEKDATA:
-+ case VKI_PTRACE_PEEKUSR:
-+ PRE_MEM_WRITE("ptrace(peek)", ARG4, sizeof(long));
-+ break;
-+ case VKI_PTRACE_GETEVENTMSG:
-+ PRE_MEM_WRITE("ptrace(geteventmsg)", ARG4, sizeof(unsigned long));
-+ break;
-+ case VKI_PTRACE_GETSIGINFO:
-+ PRE_MEM_WRITE("ptrace(getsiginfo)", ARG4, sizeof(vki_siginfo_t));
-+ break;
-+ case VKI_PTRACE_SETSIGINFO:
-+ PRE_MEM_READ("ptrace(setsiginfo)", ARG4, sizeof(vki_siginfo_t));
-+ break;
-+ case VKI_PTRACE_GETREGSET:
-+ ML_(linux_PRE_getregset)(tid, ARG3, ARG4);
-+ break;
-+ default:
-+ break;
-+ }
++ tst->arch.vex.guest_R1 = mc->sc_regs[1];
++ tst->arch.vex.guest_R2 = mc->sc_regs[2];
++ tst->arch.vex.guest_R3 = mc->sc_regs[3];
++ tst->arch.vex.guest_R4 = mc->sc_regs[4];
++ tst->arch.vex.guest_R5 = mc->sc_regs[5];
++ tst->arch.vex.guest_R6 = mc->sc_regs[6];
++ tst->arch.vex.guest_R7 = mc->sc_regs[7];
++ tst->arch.vex.guest_R8 = mc->sc_regs[8];
++ tst->arch.vex.guest_R9 = mc->sc_regs[9];
++ tst->arch.vex.guest_R10 = mc->sc_regs[10];
++ tst->arch.vex.guest_R11 = mc->sc_regs[11];
++ tst->arch.vex.guest_R12 = mc->sc_regs[12];
++ tst->arch.vex.guest_R13 = mc->sc_regs[13];
++ tst->arch.vex.guest_R14 = mc->sc_regs[14];
++ tst->arch.vex.guest_R15 = mc->sc_regs[15];
++ tst->arch.vex.guest_R16 = mc->sc_regs[16];
++ tst->arch.vex.guest_R17 = mc->sc_regs[17];
++ tst->arch.vex.guest_R18 = mc->sc_regs[18];
++ tst->arch.vex.guest_R19 = mc->sc_regs[19];
++ tst->arch.vex.guest_R20 = mc->sc_regs[20];
++ tst->arch.vex.guest_R21 = mc->sc_regs[21];
++ tst->arch.vex.guest_R22 = mc->sc_regs[22];
++ tst->arch.vex.guest_R23 = mc->sc_regs[23];
++ tst->arch.vex.guest_R24 = mc->sc_regs[24];
++ tst->arch.vex.guest_R25 = mc->sc_regs[25];
++ tst->arch.vex.guest_R26 = mc->sc_regs[26];
++ tst->arch.vex.guest_R27 = mc->sc_regs[27];
++ tst->arch.vex.guest_R28 = mc->sc_regs[28];
++ tst->arch.vex.guest_R29 = mc->sc_regs[29];
++ tst->arch.vex.guest_R30 = mc->sc_regs[30];
++ tst->arch.vex.guest_R31 = mc->sc_regs[31];
++ tst->arch.vex.guest_PC = mc->sc_pc;
+}
+
-+POST(sys_ptrace)
++/* EXPORTED */
++void VG_(sigframe_destroy)( ThreadId tid, Bool isRT )
+{
-+ switch (ARG1) {
-+ case VKI_PTRACE_TRACEME:
-+ ML_(linux_POST_traceme)(tid);
-+ break;
-+ case VKI_PTRACE_PEEKTEXT:
-+ case VKI_PTRACE_PEEKDATA:
-+ case VKI_PTRACE_PEEKUSR:
-+ POST_MEM_WRITE (ARG4, sizeof(long));
-+ break;
-+ case VKI_PTRACE_GETEVENTMSG:
-+ POST_MEM_WRITE (ARG4, sizeof(unsigned long));
-+ break;
-+ case VKI_PTRACE_GETSIGINFO:
-+ POST_MEM_WRITE (ARG4, sizeof(vki_siginfo_t));
-+ break;
-+ case VKI_PTRACE_GETREGSET:
-+ ML_(linux_POST_getregset)(tid, ARG3, ARG4);
-+ break;
-+ default:
-+ break;
-+ }
++ vg_assert(VG_(is_valid_tid)(tid));
++
++ ThreadState *tst = VG_(get_ThreadState)(tid);
++ Addr sp = tst->arch.vex.guest_R3;
++ struct rt_sigframe *frame = (struct rt_sigframe *)sp;
++ struct vki_ucontext *uc = &frame->rs_uctx;
++
++ tst->sig_mask = uc->uc_sigmask;
++ tst->tmp_sig_mask = uc->uc_sigmask;
++
++ struct vki_sigcontext *mc = &uc->uc_mcontext;
++ restore_regs(tst, mc);
++
++ struct vg_sig_private *priv = &frame->priv;
++ vg_assert(priv->magicPI == 0x31415927);
++ tst->arch.vex_shadow1 = priv->vex_shadow1;
++ tst->arch.vex_shadow2 = priv->vex_shadow2;
++
++ UInt frame_size = sizeof(*frame);
++ VG_TRACK(die_mem_stack_signal, sp, frame_size);
++
++ if (VG_(clo_trace_signals))
++ VG_(message)(Vg_DebugMsg,
++ "VG_(signal_return) (thread %u): isRT=%d valid magic; PC=%#llx\n",
++ tid, isRT, tst->arch.vex.guest_PC);
++
++ Int sigNo = priv->sigNo_private;
++ VG_TRACK( post_deliver_signal, tid, sigNo );
+}
+
-+PRE(sys_mmap)
-+{
-+ SysRes r;
-+
-+ PRINT("sys_mmap ( %#lx, %lu, %lu, %#lx, %lu, %lu )",
-+ ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
-+ PRE_REG_READ6(long, "mmap",
-+ unsigned long, addr, unsigned long, len,
-+ unsigned long, prot, unsigned long, flags,
-+ unsigned long, fd, vki_off_t, offset);
++#endif /* defined(VGP_loongarch64_linux) */
+
-+ r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
-+ SET_STATUS_from_SysRes(r);
-+}
++/*--------------------------------------------------------------------*/
++/*--- end sigframe-loongarch64-linux.c ---*/
++/*--------------------------------------------------------------------*/
+diff --git a/coregrind/m_signals.c b/coregrind/m_signals.c
+index 66fbbfe..9b801f7 100644
+--- a/coregrind/m_signals.c
++++ b/coregrind/m_signals.c
+@@ -643,6 +643,22 @@ VgHashTable *ht_sigchld_ignore = NULL;
+ (srP)->misc.MIPS32.r28 = (uc)->uc_mcontext.sc_regs[28]; \
+ }
+
++#elif defined(VGP_loongarch64_linux)
++# define VG_UCONTEXT_INSTR_PTR(uc) (((uc)->uc_mcontext.sc_pc))
++# define VG_UCONTEXT_STACK_PTR(uc) ((uc)->uc_mcontext.sc_regs[3])
++# define VG_UCONTEXT_FRAME_PTR(uc) ((uc)->uc_mcontext.sc_regs[22])
++# define VG_UCONTEXT_SYSCALL_NUM(uc) ((uc)->uc_mcontext.sc_regs[11])
++# define VG_UCONTEXT_SYSCALL_SYSRES(uc) \
++ /* Convert the value in uc_mcontext.regs[4] into a SysRes. */ \
++ VG_(mk_SysRes_loongarch64_linux)((uc)->uc_mcontext.sc_regs[4])
+
-+PRE(sys_rt_sigreturn)
-+{
-+ /* See comments on PRE(sys_rt_sigreturn) in syswrap-loongarch64-linux.c for
-+ an explanation of what follows. */
-+ ThreadState* tst;
-+ PRINT("rt_sigreturn ( )");
++# define VG_UCONTEXT_TO_UnwindStartRegs(srP, uc) \
++ { (srP)->r_pc = (uc)->uc_mcontext.sc_pc; \
++ (srP)->r_sp = (uc)->uc_mcontext.sc_regs[3]; \
++ (srP)->misc.LOONGARCH64.r_fp = (uc)->uc_mcontext.sc_regs[22]; \
++ (srP)->misc.LOONGARCH64.r_ra = (uc)->uc_mcontext.sc_regs[1]; \
++ }
+
-+ vg_assert(VG_(is_valid_tid)(tid));
-+ vg_assert(tid >= 1 && tid < VG_N_THREADS);
-+ vg_assert(VG_(is_running_thread)(tid));
+ #elif defined(VGP_x86_solaris)
+ # define VG_UCONTEXT_INSTR_PTR(uc) ((Addr)(uc)->uc_mcontext.gregs[VKI_EIP])
+ # define VG_UCONTEXT_STACK_PTR(uc) ((Addr)(uc)->uc_mcontext.gregs[VKI_UESP])
+@@ -914,8 +930,10 @@ void calculate_SKSS_from_SCSS ( SKSS* dst )
+ if (skss_handler != VKI_SIG_IGN && skss_handler != VKI_SIG_DFL)
+ skss_flags |= VKI_SA_SIGINFO;
+
++# if !defined(VGP_loongarch64_linux)
+ /* use our own restorer */
+ skss_flags |= VKI_SA_RESTORER;
++# endif
+
+ /* Create SKSS entry for this signal. */
+ if (sig != VKI_SIGKILL && sig != VKI_SIGSTOP)
+@@ -1067,6 +1085,15 @@ extern void my_sigreturn(void);
+ " li $t4, " #name "\n" \
+ " syscall[32]\n" \
+ ".previous\n"
+
-+ tst = VG_(get_ThreadState)(tid);
++#elif defined(VGP_loongarch64_linux)
++# define _MY_SIGRETURN(name) \
++ ".text\n" \
++ "my_sigreturn:\n" \
++ " li.w $a7, " #name "\n" \
++ " syscall 0\n" \
++ ".previous\n"
+
-+ /* This is only so that the PC is (might be) useful to report if
-+ something goes wrong in the sigreturn */
-+ ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
+ #elif defined(VGP_x86_solaris) || defined(VGP_amd64_solaris)
+ /* Not used on Solaris. */
+ # define _MY_SIGRETURN(name) \
+@@ -1134,7 +1161,8 @@ static void handle_SCSS_change ( Bool force_update )
+ ksa.sa_flags = skss.skss_per_sig[sig].skss_flags;
+ # if !defined(VGP_ppc32_linux) && \
+ !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
+- !defined(VGP_mips32_linux) && !defined(VGO_solaris) && !defined(VGO_freebsd)
++ !defined(VGP_mips32_linux) && !defined(VGO_solaris) && \
++ !defined(VGO_freebsd) && !defined(VGP_loongarch64_linux)
+ ksa.sa_restorer = my_sigreturn;
+ # endif
+ /* Re above ifdef (also the assertion below), PaulM says:
+@@ -1182,7 +1210,7 @@ static void handle_SCSS_change ( Bool force_update )
+ !defined(VGP_x86_darwin) && !defined(VGP_amd64_darwin) && \
+ !defined(VGP_mips32_linux) && !defined(VGP_mips64_linux) && \
+ !defined(VGP_nanomips_linux) && !defined(VGO_solaris) && \
+- !defined(VGO_freebsd)
++ !defined(VGO_freebsd) && !defined(VGP_loongarch64_linux)
+ vg_assert(ksa_old.sa_restorer == my_sigreturn);
+ # endif
+ VG_(sigaddset)( &ksa_old.sa_mask, VKI_SIGKILL );
+@@ -1303,7 +1331,7 @@ SysRes VG_(do_sys_sigaction) ( Int signo,
+ old_act->sa_flags = scss.scss_per_sig[signo].scss_flags;
+ old_act->sa_mask = scss.scss_per_sig[signo].scss_mask;
+ # if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
+- !defined(VGO_solaris)
++ !defined(VGO_solaris) && !defined(VGP_loongarch64_linux)
+ old_act->sa_restorer = scss.scss_per_sig[signo].scss_restorer;
+ # endif
+ }
+@@ -1316,7 +1344,7 @@ SysRes VG_(do_sys_sigaction) ( Int signo,
+
+ scss.scss_per_sig[signo].scss_restorer = NULL;
+ # if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
+- !defined(VGO_solaris)
++ !defined(VGO_solaris) && !defined(VGP_loongarch64_linux)
+ scss.scss_per_sig[signo].scss_restorer = new_act->sa_restorer;
+ # endif
+
+@@ -1676,7 +1704,7 @@ void VG_(kill_self)(Int sigNo)
+ sa.ksa_handler = VKI_SIG_DFL;
+ sa.sa_flags = 0;
+ # if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
+- !defined(VGO_solaris)
++ !defined(VGO_solaris) && !defined(VGP_loongarch64_linux)
+ sa.sa_restorer = 0;
+ # endif
+ VG_(sigemptyset)(&sa.sa_mask);
+@@ -2319,8 +2347,9 @@ void VG_(synth_sigtrap)(ThreadId tid)
+ // Synthesise a SIGFPE.
+ void VG_(synth_sigfpe)(ThreadId tid, UInt code)
+ {
+-// Only tested on mips32, mips64, s390x and nanomips.
+-#if !defined(VGA_mips32) && !defined(VGA_mips64) && !defined(VGA_s390x) && !defined(VGA_nanomips)
++// Only tested on mips32, mips64, s390x, nanomips and loongarch64.
++#if !defined(VGA_mips32) && !defined(VGA_mips64) && !defined(VGA_s390x) \
++ && !defined(VGA_nanomips) && !defined(VGA_loongarch64)
+ vg_assert(0);
+ #else
+ vki_siginfo_t info;
+@@ -2342,6 +2371,30 @@ void VG_(synth_sigfpe)(ThreadId tid, UInt code)
+ #endif
+ }
+
++// Synthesise a SIGSYS.
++void VG_(synth_sigsys)(ThreadId tid)
++{
++// Only tested on loongarch64-linux.
++#if !defined(VGP_loongarch64_linux)
++ vg_assert(0);
++#else
++ vki_siginfo_t info;
+
-+ /* Restore register state from frame and remove it */
-+ VG_(sigframe_destroy)(tid, True);
++ vg_assert(VG_(threads)[tid].status == VgTs_Runnable);
+
-+ /* Tell the driver not to update the guest state with the "result",
-+ and set a bogus result to keep it happy. */
-+ *flags |= SfNoWriteResult;
-+ SET_STATUS_Success(0);
++ VG_(memset)(&info, 0, sizeof(info));
++ info.si_signo = VKI_SIGSYS;
++ info.si_code = VKI_SI_KERNEL;
+
-+ /* Check to see if any signals arose as a result of this. */
-+ *flags |= SfPollAfter;
++ if (VG_(gdbserver_report_signal) (&info, tid)) {
++ resume_scheduler(tid);
++ deliver_signal(tid, &info, NULL);
++ }
++ else
++ resume_scheduler(tid);
++#endif
+}
+
-+#undef PRE
-+#undef POST
+ /* Make a signal pending for a thread, for later delivery.
+ VG_(poll_signals) will arrange for it to be delivered at the right
+ time.
+@@ -3068,7 +3121,7 @@ void pp_ksigaction ( vki_sigaction_toK_t* sa )
+ sa->ksa_handler,
+ (UInt)sa->sa_flags,
+ # if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
+- !defined(VGO_solaris)
++ !defined(VGO_solaris) && !defined(VGP_loongarch64_linux)
+ sa->sa_restorer
+ # else
+ (void*)0
+@@ -3091,7 +3144,7 @@ void VG_(set_default_handler)(Int signo)
+ sa.ksa_handler = VKI_SIG_DFL;
+ sa.sa_flags = 0;
+ # if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
+- !defined(VGO_solaris)
++ !defined(VGO_solaris) && !defined(VGP_loongarch64_linux)
+ sa.sa_restorer = 0;
+ # endif
+ VG_(sigemptyset)(&sa.sa_mask);
+@@ -3213,7 +3266,7 @@ void VG_(sigstartup_actions) ( void )
+ tsa.ksa_handler = (void *)sync_signalhandler;
+ tsa.sa_flags = VKI_SA_SIGINFO;
+ # if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
+- !defined(VGO_solaris)
++ !defined(VGO_solaris) && !defined(VGP_loongarch64_linux)
+ tsa.sa_restorer = 0;
+ # endif
+ VG_(sigfillset)(&tsa.sa_mask);
+@@ -3241,7 +3294,7 @@ void VG_(sigstartup_actions) ( void )
+
+ scss.scss_per_sig[i].scss_restorer = NULL;
+ # if !defined(VGO_darwin) && !defined(VGO_freebsd) && \
+- !defined(VGO_solaris)
++ !defined(VGO_solaris) && !defined(VGP_loongarch64_linux)
+ scss.scss_per_sig[i].scss_restorer = sa.sa_restorer;
+ # endif
+
+diff --git a/coregrind/m_stacktrace.c b/coregrind/m_stacktrace.c
+index 630b5b8..b368448 100644
+--- a/coregrind/m_stacktrace.c
++++ b/coregrind/m_stacktrace.c
+@@ -1529,6 +1529,100 @@ UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
+
+ #endif
+
++/* ---------------------- loongarch64 ----------------------- */
+
-+/* ---------------------------------------------------------------------
-+ The loongarch64/Linux syscall table
-+ ------------------------------------------------------------------ */
++#if defined(VGP_loongarch64_linux)
++UInt VG_(get_StackTrace_wrk) ( ThreadId tid_if_known,
++ /*OUT*/Addr* ips, UInt max_n_ips,
++ /*OUT*/Addr* sps, /*OUT*/Addr* fps,
++ const UnwindStartRegs* startRegs,
++ Addr fp_max_orig )
++{
++ Bool debug = False;
++ Int i;
++ Addr fp_max;
++ UInt n_found = 0;
++ const Int cmrf = VG_(clo_merge_recursive_frames);
+
-+#define PLAX_(sysno, name) WRAPPER_ENTRY_X_(loongarch64_linux, sysno, name)
-+#define PLAXY(sysno, name) WRAPPER_ENTRY_XY(loongarch64_linux, sysno, name)
++ vg_assert(sizeof(Addr) == sizeof(UWord));
++ vg_assert(sizeof(Addr) == sizeof(void*));
+
-+// This table maps from __NR_xxx syscall numbers (from
-+// linux/include/uapi/asm-generic/unistd.h) to the appropriate PRE/POST
-+// sys_foo() wrappers on loongarch64 (as per sys_call_table in
-+// linux/arch/loongarch/kernel/syscall.c).
-+//
-+// For those syscalls not handled by Valgrind, the annotation indicate its
-+// arch/OS combination, eg. */* (generic), */Linux (Linux only), ?/?
-+// (unknown).
++ D3UnwindRegs uregs;
++ uregs.pc = startRegs->r_pc;
++ uregs.sp = startRegs->r_sp;
++ uregs.fp = startRegs->misc.LOONGARCH64.r_fp;
++ uregs.ra = startRegs->misc.LOONGARCH64.r_ra;
++ Addr fp_min = uregs.sp - VG_STACK_REDZONE_SZB;
+
-+static SyscallTableEntry syscall_main_table[] = {
-+ LINXY(__NR_io_setup, sys_io_setup), // 0
-+ LINX_(__NR_io_destroy, sys_io_destroy), // 1
-+ LINX_(__NR_io_submit, sys_io_submit), // 2
-+ LINXY(__NR_io_cancel, sys_io_cancel), // 3
-+ LINXY(__NR_io_getevents, sys_io_getevents), // 4
-+ LINX_(__NR_setxattr, sys_setxattr), // 5
-+ LINX_(__NR_lsetxattr, sys_lsetxattr), // 6
-+ LINX_(__NR_fsetxattr, sys_fsetxattr), // 7
-+ LINXY(__NR_getxattr, sys_getxattr), // 8
-+ LINXY(__NR_lgetxattr, sys_lgetxattr), // 9
-+ LINXY(__NR_fgetxattr, sys_fgetxattr), // 10
-+ LINXY(__NR_listxattr, sys_listxattr), // 11
-+ LINXY(__NR_llistxattr, sys_llistxattr), // 12
-+ LINXY(__NR_flistxattr, sys_flistxattr), // 13
-+ LINX_(__NR_removexattr, sys_removexattr), // 14
-+ LINX_(__NR_lremovexattr, sys_lremovexattr), // 15
-+ LINX_(__NR_fremovexattr, sys_fremovexattr), // 16
-+ GENXY(__NR_getcwd, sys_getcwd), // 17
-+ LINXY(__NR_lookup_dcookie, sys_lookup_dcookie), // 18
-+ LINXY(__NR_eventfd2, sys_eventfd2), // 19
-+ LINXY(__NR_epoll_create1, sys_epoll_create1), // 20
-+ LINX_(__NR_epoll_ctl, sys_epoll_ctl), // 21
-+ LINXY(__NR_epoll_pwait, sys_epoll_pwait), // 22
-+ GENXY(__NR_dup, sys_dup), // 23
-+ LINXY(__NR_dup3, sys_dup3), // 24
-+ LINXY(__NR3264_fcntl, sys_fcntl), // 25
-+ LINXY(__NR_inotify_init1, sys_inotify_init1), // 26
-+ LINX_(__NR_inotify_add_watch, sys_inotify_add_watch), // 27
-+ LINX_(__NR_inotify_rm_watch, sys_inotify_rm_watch), // 28
-+ LINXY(__NR_ioctl, sys_ioctl), // 29
-+ LINX_(__NR_ioprio_set, sys_ioprio_set), // 30
-+ LINX_(__NR_ioprio_get, sys_ioprio_get), // 31
-+ GENX_(__NR_flock, sys_flock), // 32
-+ LINX_(__NR_mknodat, sys_mknodat), // 33
-+ LINX_(__NR_mkdirat, sys_mkdirat), // 34
-+ LINX_(__NR_unlinkat, sys_unlinkat), // 35
-+ LINX_(__NR_symlinkat, sys_symlinkat), // 36
-+ LINX_(__NR_linkat, sys_linkat), // 37
-+ // (__NR_renameat, sys_renameat), // 38
-+ LINX_(__NR_umount2, sys_umount), // 39
-+ LINX_(__NR_mount, sys_mount), // 40
-+ LINX_(__NR_pivot_root, sys_pivot_root), // 41
-+ // (__NR_nfsservctl, sys_ni_syscall), // 42
-+ GENXY(__NR3264_statfs, sys_statfs), // 43
-+ GENXY(__NR3264_fstatfs, sys_fstatfs), // 44
-+ GENX_(__NR3264_truncate, sys_truncate), // 45
-+ GENX_(__NR3264_ftruncate, sys_ftruncate), // 46
-+ LINX_(__NR_fallocate, sys_fallocate), // 47
-+ LINX_(__NR_faccessat, sys_faccessat), // 48
-+ GENX_(__NR_chdir, sys_chdir), // 49
-+ GENX_(__NR_fchdir, sys_fchdir), // 50
-+ GENX_(__NR_chroot, sys_chroot), // 51
-+ GENX_(__NR_fchmod, sys_fchmod), // 52
-+ LINX_(__NR_fchmodat, sys_fchmodat), // 53
-+ LINX_(__NR_fchownat, sys_fchownat), // 54
-+ GENX_(__NR_fchown, sys_fchown), // 55
-+ LINXY(__NR_openat, sys_openat), // 56
-+ GENXY(__NR_close, sys_close), // 57
-+ LINX_(__NR_vhangup, sys_vhangup), // 58
-+ LINXY(__NR_pipe2, sys_pipe2), // 59
-+ LINX_(__NR_quotactl, sys_quotactl), // 60
-+ GENXY(__NR_getdents64, sys_getdents64), // 61
-+ LINX_(__NR3264_lseek, sys_lseek), // 62
-+ GENXY(__NR_read, sys_read), // 63
-+ GENX_(__NR_write, sys_write), // 64
-+ GENXY(__NR_readv, sys_readv), // 65
-+ GENX_(__NR_writev, sys_writev), // 66
-+ GENXY(__NR_pread64, sys_pread64), // 67
-+ GENX_(__NR_pwrite64, sys_pwrite64), // 68
-+ LINXY(__NR_preadv, sys_preadv), // 69
-+ LINX_(__NR_pwritev, sys_pwritev), // 70
-+ LINXY(__NR3264_sendfile, sys_sendfile), // 71
-+ LINXY(__NR_pselect6, sys_pselect6), // 72
-+ LINXY(__NR_ppoll, sys_ppoll), // 73
-+ LINXY(__NR_signalfd4, sys_signalfd4), // 74
-+ LINX_(__NR_vmsplice, sys_vmsplice), // 75
-+ LINX_(__NR_splice, sys_splice), // 76
-+ LINX_(__NR_tee, sys_tee), // 77
-+ LINX_(__NR_readlinkat, sys_readlinkat), // 78
-+ LINXY(__NR3264_fstatat, sys_newfstatat), // 79
-+ GENXY(__NR3264_fstat, sys_newfstat), // 80
-+ GENX_(__NR_sync, sys_sync), // 81
-+ GENX_(__NR_fsync, sys_fsync), // 82
-+ GENX_(__NR_fdatasync, sys_fdatasync), // 83
-+ LINX_(__NR_sync_file_range, sys_sync_file_range), // 84
-+ LINXY(__NR_timerfd_create, sys_timerfd_create), // 85
-+ LINXY(__NR_timerfd_settime, sys_timerfd_settime), // 86
-+ LINXY(__NR_timerfd_gettime, sys_timerfd_gettime), // 87
-+ LINX_(__NR_utimensat, sys_utimensat), // 88
-+ GENX_(__NR_acct, sys_acct), // 89
-+ LINXY(__NR_capget, sys_capget), // 90
-+ LINX_(__NR_capset, sys_capset), // 91
-+ LINX_(__NR_personality, sys_personality), // 92
-+ GENX_(__NR_exit, sys_exit), // 93
-+ LINX_(__NR_exit_group, sys_exit_group), // 94
-+ LINXY(__NR_waitid, sys_waitid), // 95
-+ LINX_(__NR_set_tid_address, sys_set_tid_address), // 96
-+ LINX_(__NR_unshare, sys_unshare), // 97
-+ LINXY(__NR_futex, sys_futex), // 98
-+ LINX_(__NR_set_robust_list, sys_set_robust_list), // 99
-+ LINXY(__NR_get_robust_list, sys_get_robust_list), // 100
-+ GENXY(__NR_nanosleep, sys_nanosleep), // 101
-+ GENXY(__NR_getitimer, sys_getitimer), // 102
-+ GENXY(__NR_setitimer, sys_setitimer), // 103
-+ // (__NR_kexec_load, sys_kexec_load), // 104
-+ LINX_(__NR_init_module, sys_init_module), // 105
-+ LINX_(__NR_delete_module, sys_delete_module), // 106
-+ LINXY(__NR_timer_create, sys_timer_create), // 107
-+ LINXY(__NR_timer_gettime, sys_timer_gettime), // 108
-+ LINX_(__NR_timer_getoverrun, sys_timer_getoverrun), // 109
-+ LINXY(__NR_timer_settime, sys_timer_settime), // 110
-+ LINX_(__NR_timer_delete, sys_timer_delete), // 111
-+ LINX_(__NR_clock_settime, sys_clock_settime), // 112
-+ LINXY(__NR_clock_gettime, sys_clock_gettime), // 113
-+ LINXY(__NR_clock_getres, sys_clock_getres), // 114
-+ LINXY(__NR_clock_nanosleep, sys_clock_nanosleep), // 115
-+ LINXY(__NR_syslog, sys_syslog), // 116
-+ PLAXY(__NR_ptrace, sys_ptrace), // 117
-+ LINXY(__NR_sched_setparam, sys_sched_setparam), // 118
-+ LINX_(__NR_sched_setscheduler, sys_sched_setscheduler), // 119
-+ LINX_(__NR_sched_getscheduler, sys_sched_getscheduler), // 120
-+ LINXY(__NR_sched_getparam, sys_sched_getparam), // 121
-+ LINX_(__NR_sched_setaffinity, sys_sched_setaffinity), // 122
-+ LINXY(__NR_sched_getaffinity, sys_sched_getaffinity), // 123
-+ LINX_(__NR_sched_yield, sys_sched_yield), // 124
-+ LINX_(__NR_sched_get_priority_max, sys_sched_get_priority_max), // 125
-+ LINX_(__NR_sched_get_priority_min, sys_sched_get_priority_min), // 126
-+ LINXY(__NR_sched_rr_get_interval, sys_sched_rr_get_interval), // 127
-+ // (__NR_restart_syscall, sys_restart_syscall), // 128
-+ GENX_(__NR_kill, sys_kill), // 129
-+ LINXY(__NR_tkill, sys_tkill), // 130
-+ LINX_(__NR_tgkill, sys_tgkill), // 131
-+ GENXY(__NR_sigaltstack, sys_sigaltstack), // 132
-+ LINX_(__NR_rt_sigsuspend, sys_rt_sigsuspend), // 133
-+ LINXY(__NR_rt_sigaction, sys_rt_sigaction), // 134
-+ LINXY(__NR_rt_sigprocmask, sys_rt_sigprocmask), // 135
-+ LINXY(__NR_rt_sigpending, sys_rt_sigpending), // 136
-+ LINXY(__NR_rt_sigtimedwait, sys_rt_sigtimedwait), // 137
-+ LINXY(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo), // 138
-+ PLAX_(__NR_rt_sigreturn, sys_rt_sigreturn), // 139
-+ GENX_(__NR_setpriority, sys_setpriority), // 140
-+ GENX_(__NR_getpriority, sys_getpriority), // 141
-+ // (__NR_reboot, sys_reboot), // 142
-+ GENX_(__NR_setregid, sys_setregid), // 143
-+ GENX_(__NR_setgid, sys_setgid), // 144
-+ GENX_(__NR_setreuid, sys_setreuid), // 145
-+ GENX_(__NR_setuid, sys_setuid), // 146
-+ LINX_(__NR_setresuid, sys_setresuid), // 147
-+ LINXY(__NR_getresuid, sys_getresuid), // 148
-+ LINX_(__NR_setresgid, sys_setresgid), // 149
-+ LINXY(__NR_getresgid, sys_getresgid), // 150
-+ LINX_(__NR_setfsuid, sys_setfsuid), // 151
-+ LINX_(__NR_setfsgid, sys_setfsgid), // 152
-+ GENXY(__NR_times, sys_times), // 153
-+ GENX_(__NR_setpgid, sys_setpgid), // 154
-+ GENX_(__NR_getpgid, sys_getpgid), // 155
-+ GENX_(__NR_getsid, sys_getsid), // 156
-+ GENX_(__NR_setsid, sys_setsid), // 157
-+ GENXY(__NR_getgroups, sys_getgroups), // 158
-+ GENX_(__NR_setgroups, sys_setgroups), // 159
-+ GENXY(__NR_uname, sys_newuname), // 160
-+ GENX_(__NR_sethostname, sys_sethostname), // 161
-+ // (__NR_setdomainname, sys_setdomainname), // 162
-+ // (__NR_getrlimit, sys_old_getrlimit), // 163
-+ // (__NR_setrlimit, sys_setrlimit), // 164
-+ GENXY(__NR_getrusage, sys_getrusage), // 165
-+ GENX_(__NR_umask, sys_umask), // 166
-+ LINXY(__NR_prctl, sys_prctl), // 167
-+ LINXY(__NR_getcpu, sys_getcpu), // 168
-+ GENXY(__NR_gettimeofday, sys_gettimeofday), // 169
-+ GENX_(__NR_settimeofday, sys_settimeofday), // 170
-+ LINXY(__NR_adjtimex, sys_adjtimex), // 171
-+ GENX_(__NR_getpid, sys_getpid), // 172
-+ GENX_(__NR_getppid, sys_getppid), // 173
-+ GENX_(__NR_getuid, sys_getuid), // 174
-+ GENX_(__NR_geteuid, sys_geteuid), // 175
-+ GENX_(__NR_getgid, sys_getgid), // 176
-+ GENX_(__NR_getegid, sys_getegid), // 177
-+ LINX_(__NR_gettid, sys_gettid), // 178
-+ LINXY(__NR_sysinfo, sys_sysinfo), // 179
-+ LINXY(__NR_mq_open, sys_mq_open), // 180
-+ LINX_(__NR_mq_unlink, sys_mq_unlink), // 181
-+ LINX_(__NR_mq_timedsend, sys_mq_timedsend), // 182
-+ LINXY(__NR_mq_timedreceive, sys_mq_timedreceive), // 183
-+ LINX_(__NR_mq_notify, sys_mq_notify), // 184
-+ LINXY(__NR_mq_getsetattr, sys_mq_getsetattr), // 185
-+ LINX_(__NR_msgget, sys_msgget), // 186
-+ LINXY(__NR_msgctl, sys_msgctl), // 187
-+ LINXY(__NR_msgrcv, sys_msgrcv), // 188
-+ LINX_(__NR_msgsnd, sys_msgsnd), // 189
-+ LINX_(__NR_semget, sys_semget), // 190
-+ LINXY(__NR_semctl, sys_semctl), // 191
-+ LINX_(__NR_semtimedop, sys_semtimedop), // 192
-+ LINX_(__NR_semop, sys_semop), // 193
-+ LINX_(__NR_shmget, sys_shmget), // 194
-+ LINXY(__NR_shmctl, sys_shmctl), // 195
-+ LINXY(__NR_shmat, sys_shmat), // 196
-+ LINXY(__NR_shmdt, sys_shmdt), // 197
-+ LINXY(__NR_socket, sys_socket), // 198
-+ LINXY(__NR_socketpair, sys_socketpair), // 199
-+ LINX_(__NR_bind, sys_bind), // 200
-+ LINX_(__NR_listen, sys_listen), // 201
-+ LINXY(__NR_accept, sys_accept), // 202
-+ LINX_(__NR_connect, sys_connect), // 203
-+ LINXY(__NR_getsockname, sys_getsockname), // 204
-+ LINXY(__NR_getpeername, sys_getpeername), // 205
-+ LINX_(__NR_sendto, sys_sendto), // 206
-+ LINXY(__NR_recvfrom, sys_recvfrom), // 207
-+ LINX_(__NR_setsockopt, sys_setsockopt), // 208
-+ LINXY(__NR_getsockopt, sys_getsockopt), // 209
-+ LINX_(__NR_shutdown, sys_shutdown), // 210
-+ LINX_(__NR_sendmsg, sys_sendmsg), // 211
-+ LINXY(__NR_recvmsg, sys_recvmsg), // 212
-+ LINX_(__NR_readahead, sys_readahead), // 213
-+ GENX_(__NR_brk, sys_brk), // 214
-+ GENXY(__NR_munmap, sys_munmap), // 215
-+ GENX_(__NR_mremap, sys_mremap), // 216
-+ LINX_(__NR_add_key, sys_add_key), // 217
-+ LINX_(__NR_request_key, sys_request_key), // 218
-+ LINXY(__NR_keyctl, sys_keyctl), // 219
-+ LINX_(__NR_clone, sys_clone), // 220
-+ GENX_(__NR_execve, sys_execve), // 221
-+ PLAX_(__NR3264_mmap, sys_mmap), // 222
-+ LINX_(__NR3264_fadvise64, sys_fadvise64), // 223
-+ // (__NR_swapon, sys_swapon), // 224
-+ // (__NR_swapoff, sys_swapoff), // 225
-+ GENXY(__NR_mprotect, sys_mprotect), // 226
-+ GENX_(__NR_msync, sys_msync), // 227
-+ GENX_(__NR_mlock, sys_mlock), // 228
-+ GENX_(__NR_munlock, sys_munlock), // 229
-+ GENX_(__NR_mlockall, sys_mlockall), // 230
-+ LINX_(__NR_munlockall, sys_munlockall), // 231
-+ GENXY(__NR_mincore, sys_mincore), // 232
-+ GENX_(__NR_madvise, sys_madvise), // 233
-+ // (__NR_remap_file_pages, sys_remap_file_pages), // 234
-+ LINX_(__NR_mbind, sys_mbind), // 235
-+ LINXY(__NR_get_mempolicy, sys_get_mempolicy), // 236
-+ LINX_(__NR_set_mempolicy, sys_set_mempolicy), // 237
-+ // (__NR_migrate_pages, sys_migrate_pages), // 238
-+ LINXY(__NR_move_pages, sys_move_pages), // 239
-+ LINXY(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo), // 240
-+ LINXY(__NR_perf_event_open, sys_perf_event_open), // 241
-+ LINXY(__NR_accept4, sys_accept4), // 242
-+ LINXY(__NR_recvmmsg, sys_recvmmsg), // 243
++ /* Snaffle IPs from the client's stack into ips[0 .. max_n_ips-1],
++ stopping when the trail goes cold, which we guess to be
++ when FP is not a reasonable stack location. */
+
-+ GENXY(__NR_wait4, sys_wait4), // 260
-+ LINXY(__NR_prlimit64, sys_prlimit64), // 261
-+ LINXY(__NR_fanotify_init, sys_fanotify_init), // 262
-+ LINX_(__NR_fanotify_mark, sys_fanotify_mark), // 263
-+ LINXY(__NR_name_to_handle_at, sys_name_to_handle_at), // 264
-+ LINXY(__NR_open_by_handle_at, sys_open_by_handle_at), // 265
-+ LINXY(__NR_clock_adjtime, sys_clock_adjtime), // 266
-+ LINX_(__NR_syncfs, sys_syncfs), // 267
-+ LINX_(__NR_setns, sys_setns), // 268
-+ LINXY(__NR_sendmmsg, sys_sendmmsg), // 269
-+ LINXY(__NR_process_vm_readv, sys_process_vm_readv), // 270
-+ LINX_(__NR_process_vm_writev, sys_process_vm_writev), // 271
-+ LINX_(__NR_kcmp, sys_kcmp), // 272
-+ LINX_(__NR_finit_module, sys_finit_module), // 273
-+ // (__NR_sched_setattr, sys_sched_setattr), // 274
-+ // (__NR_sched_getattr, sys_sched_getattr), // 275
-+ LINX_(__NR_renameat2, sys_renameat2), // 276
-+ // (__NR_seccomp, sys_seccomp), // 277
-+ LINXY(__NR_getrandom, sys_getrandom), // 278
-+ LINXY(__NR_memfd_create, sys_memfd_create), // 279
-+ LINXY(__NR_bpf, sys_bpf), // 280
-+ // (__NR_execveat, sys_execveat), // 281
-+ // (__NR_userfaultfd, sys_userfaultfd), // 282
-+ LINX_(__NR_membarrier, sys_membarrier), // 283
-+ // (__NR_mlock2, sys_mlock2), // 284
-+ LINX_(__NR_copy_file_range, sys_copy_file_range), // 285
-+ LINXY(__NR_preadv2, sys_preadv2), // 286
-+ LINX_(__NR_pwritev2, sys_pwritev2), // 287
-+ // (__NR_pkey_mprotect, sys_pkey_mprotect), // 288
-+ // (__NR_pkey_alloc, sys_pkey_alloc), // 289
-+ // (__NR_pkey_free, sys_pkey_free), // 290
-+ LINXY(__NR_statx, sys_statx), // 291
-+ // (__NR_io_pgetevents, sys_io_pgetevents), // 292
-+ // (__NR_rseq, sys_rseq), // 293
-+ // (__NR_kexec_file_load, sys_kexec_file_load), // 294
++ fp_max = VG_PGROUNDUP(fp_max_orig);
++ if (fp_max >= sizeof(Addr))
++ fp_max -= sizeof(Addr);
+
-+ // (__NR_pidfd_send_signal, sys_pidfd_send_signal), // 424
-+ LINXY(__NR_io_uring_setup, sys_io_uring_setup), // 425
-+ LINXY(__NR_io_uring_enter, sys_io_uring_enter), // 426
-+ LINXY(__NR_io_uring_register, sys_io_uring_register), // 427
-+ // (__NR_open_tree, sys_open_tree), // 428
-+ // (__NR_move_mount, sys_move_mount), // 429
-+ // (__NR_fsopen, sys_fsopen), // 430
-+ // (__NR_fsconfig, sys_fsconfig), // 431
-+ // (__NR_fsmount, sys_fsmount), // 432
-+ // (__NR_fspick, sys_fspick), // 433
-+ // (__NR_pidfd_open, sys_pidfd_open), // 434
-+ GENX_(__NR_clone3, sys_ni_syscall), // 435
-+ // (__NR_close_range, sys_close_range), // 436
-+ // (__NR_openat2, sys_openat2), // 437
-+ // (__NR_pidfd_getfd, sys_pidfd_getfd), // 438
-+ // (__NR_faccessat2, sys_faccessat2), // 439
-+ // (__NR_process_madvise, sys_process_madvise), // 440
-+ // (__NR_epoll_pwait2, sys_epoll_pwait2), // 441
-+ // (__NR_mount_setattr, sys_mount_setattr), // 442
-+ // (__NR_quotactl_fd, sys_quotactl_fd), // 443
-+ // (__NR_landlock_create_ruleset, sys_landlock_create_ruleset), // 444
-+ // (__NR_landlock_add_rule, sys_landlock_add_rule), // 445
-+ // (__NR_landlock_restrict_self, sys_landlock_restrict_self), // 446
-+ // (__NR_memfd_secret, sys_memfd_secret), // 447
-+ // (__NR_process_mrelease, sys_process_mrelease), // 448
-+};
++ if (debug)
++ VG_(printf)("\nmax_n_ips=%u fp_min=0x%lx fp_max_orig=0x%lx, "
++ "fp_max=0x%lx pc=0x%lx sp=0x%lx fp=0x%lx ra=0x%lx\n",
++ max_n_ips, fp_min, fp_max_orig, fp_max,
++ uregs.pc, uregs.sp, uregs.fp, uregs.ra);
+
-+SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )
-+{
-+ const UInt syscall_main_table_size
-+ = sizeof(syscall_main_table) / sizeof(syscall_main_table[0]);
++ if (sps) sps[0] = uregs.sp;
++ if (fps) fps[0] = uregs.fp;
++ ips[0] = uregs.pc;
++ i = 1;
+
-+ /* Is it in the contiguous initial section of the table? */
-+ if (sysno < syscall_main_table_size) {
-+ SyscallTableEntry* sys = &syscall_main_table[sysno];
-+ if (sys->before == NULL)
-+ return NULL; /* no entry */
-+ else
-+ return sys;
++ /* Loop unwinding the stack, using CFI. */
++ while (True) {
++ if (debug)
++ VG_(printf)("i: %d, pc: 0x%lx, sp: 0x%lx, fp: 0x%lx, ra: 0x%lx\n",
++ i, uregs.pc, uregs.sp, uregs.fp, uregs.ra);
++ if (i >= max_n_ips)
++ break;
++
++ if (VG_(use_CF_info)( &uregs, fp_min, fp_max )) {
++ if (sps) sps[i] = uregs.sp;
++ if (fps) fps[i] = uregs.fp;
++ ips[i++] = uregs.pc - 1;
++ if (debug)
++ VG_(printf)(
++ "USING CFI: pc: 0x%lx, sp: 0x%lx, fp: 0x%lx, ra: 0x%lx\n",
++ uregs.pc, uregs.sp, uregs.fp, uregs.ra);
++ uregs.pc = uregs.pc - 1;
++ RECURSIVE_MERGE(cmrf,ips,i);
++ continue;
++ }
++
++ /* A problem on the first frame? Lets assume it was a bad jump.
++ We will use the link register and the current stack and frame
++ pointers and see if we can use the CFI in the next round. */
++ if (i == 1) {
++ uregs.pc = uregs.ra;
++ uregs.ra = 0;
++
++ if (sps) sps[i] = uregs.sp;
++ if (fps) fps[i] = uregs.fp;
++ ips[i++] = uregs.pc - 1;
++ if (debug)
++ VG_(printf)(
++ "USING bad-jump: pc: 0x%lx, sp: 0x%lx, fp: 0x%lx, ra: 0x%lx\n",
++ uregs.pc, uregs.sp, uregs.fp, uregs.ra);
++ uregs.pc = uregs.pc - 1;
++ RECURSIVE_MERGE(cmrf,ips,i);
++ continue;
++ }
++
++ /* No luck. We have to give up. */
++ break;
+ }
+
-+ /* Can't find a wrapper */
-+ return NULL;
++ n_found = i;
++ return n_found;
+}
+
-+#endif /* defined(VGP_loongarch64_linux) */
++#endif
+
-+/*--------------------------------------------------------------------*/
-+/*--- end syswrap-loongarch64-linux.c ---*/
-+/*--------------------------------------------------------------------*/
-diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c
-index 91a1f7e..cd32e39 100644
---- a/coregrind/m_syswrap/syswrap-main.c
-+++ b/coregrind/m_syswrap/syswrap-main.c
-@@ -60,20 +60,21 @@
- /* Useful info which needs to be recorded somewhere:
- Use of registers in syscalls is:
-
-- NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT
-+ NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT
- LINUX:
-- x86 eax ebx ecx edx esi edi ebp n/a n/a eax (== NUM)
-- amd64 rax rdi rsi rdx r10 r8 r9 n/a n/a rax (== NUM)
-- ppc32 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
-- ppc64 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
-- arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1)
-- mips32 v0 a0 a1 a2 a3 stack stack n/a n/a v0 (== NUM)
-- mips64 v0 a0 a1 a2 a3 a4 a5 a6 a7 v0 (== NUM)
-- arm64 x8 x0 x1 x2 x3 x4 x5 n/a n/a x0 ?? (== ARG1??)
-+ x86 eax ebx ecx edx esi edi ebp n/a n/a eax (== NUM)
-+ amd64 rax rdi rsi rdx r10 r8 r9 n/a n/a rax (== NUM)
-+ ppc32 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
-+ ppc64 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
-+ arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1)
-+ mips32 v0 a0 a1 a2 a3 stack stack n/a n/a v0 (== NUM)
-+ mips64 v0 a0 a1 a2 a3 a4 a5 a6 a7 v0 (== NUM)
-+ arm64 x8 x0 x1 x2 x3 x4 x5 n/a n/a x0 ?? (== ARG1??)
-+ loongarch64 r11 r4 r5 r6 r7 r8 r9 n/a n/a r4 (== ARG1)
-
- FreeBSD:
-- x86 eax +4 +8 +12 +16 +20 +24 +28 +32 edx:eax, eflags.c
-- amd64 rax rdi rsi rdx rcx r8 r9 +8 +16 rdx:rax, rflags.c
-+ x86 eax +4 +8 +12 +16 +20 +24 +28 +32 edx:eax, eflags.c
-+ amd64 rax rdi rsi rdx rcx r8 r9 +8 +16 rdx:rax, rflags.c
+ /*------------------------------------------------------------*/
+ /*--- ---*/
+ /*--- END platform-dependent unwinder worker functions ---*/
+diff --git a/coregrind/m_syscall.c b/coregrind/m_syscall.c
+index 6ab2069..9867f00 100644
+--- a/coregrind/m_syscall.c
++++ b/coregrind/m_syscall.c
+@@ -204,6 +204,17 @@ SysRes VG_(mk_SysRes_arm64_linux) ( Long val ) {
+ return res;
+ }
- On s390x the svc instruction is used for system calls. The system call
- number is encoded in the instruction (8 bit immediate field). Since Linux
-@@ -703,6 +704,17 @@ void getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs* canonical,
- canonical->arg6 = gst->guest_r9; // a5
- canonical->arg7 = gst->guest_r10; // a6
- canonical->arg8 = gst->guest_r11; // a7
-+
-+#elif defined(VGP_loongarch64_linux)
-+ VexGuestLOONGARCH64State* gst = (VexGuestLOONGARCH64State*)gst_vanilla;
-+ canonical->sysno = gst->guest_R11; // a7
-+ canonical->arg1 = gst->guest_R4; // a0
-+ canonical->arg2 = gst->guest_R5; // a1
-+ canonical->arg3 = gst->guest_R6; // a2
-+ canonical->arg4 = gst->guest_R7; // a3
-+ canonical->arg5 = gst->guest_R8; // a4
-+ canonical->arg6 = gst->guest_R9; // a5
++SysRes VG_(mk_SysRes_loongarch64_linux) ( UWord val ) {
++ SysRes res;
++ res._isError = val >= -4095 && val <= -1;
++ if (res._isError) {
++ res._val = (UWord)(-val);
++ } else {
++ res._val = (UWord)val;
++ }
++ return res;
++}
+
- #elif defined(VGP_x86_darwin)
- VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
- UWord *stack = (UWord *)gst->guest_ESP;
-@@ -1126,6 +1138,16 @@ void putSyscallArgsIntoGuestState ( /*IN*/ SyscallArgs* canonical,
- gst->guest_r10 = canonical->arg7;
- gst->guest_r11 = canonical->arg8;
+ /* Generic constructors. */
+ SysRes VG_(mk_SysRes_Success) ( UWord res ) {
+ SysRes r;
+@@ -1076,6 +1087,22 @@ asm (
+ ".previous \n\t"
+ );
+#elif defined(VGP_loongarch64_linux)
-+ VexGuestLOONGARCH64State* gst = (VexGuestLOONGARCH64State*)gst_vanilla;
-+ gst->guest_R11 = canonical->sysno;
-+ gst->guest_R4 = canonical->arg1;
-+ gst->guest_R5 = canonical->arg2;
-+ gst->guest_R6 = canonical->arg3;
-+ gst->guest_R7 = canonical->arg4;
-+ gst->guest_R8 = canonical->arg5;
-+ gst->guest_R9 = canonical->arg6;
++extern UWord do_syscall_WRK (UWord a1, UWord a2, UWord a3, /* $a0, $a1, $a2 */
++ UWord a4, UWord a5, UWord a6, /* $a3, $a4, $a5 */
++ UWord syscall_no); /* $a6 */
++asm (
++ ".text \n\t"
++ ".globl do_syscall_WRK \n\t"
++ ".type do_syscall_WRK, @function \n\t"
++ "do_syscall_WRK: \n\t"
++ " move $a7, $a6 \n\t" /* a7 = syscall_no */
++ " syscall 0 \n\t"
++ " jr $ra \n\t"
++ ".size do_syscall_WRK, .-do_syscall_WRK \n\t"
++ ".previous \n\t"
++);
+
#elif defined(VGP_x86_solaris)
- VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
- UWord *stack = (UWord *)gst->guest_ESP;
-@@ -1240,6 +1262,13 @@ void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus* canonical,
- RegWord a0 = gst->guest_r4; // a0
- canonical->sres = VG_(mk_SysRes_nanomips_linux)(a0);
- canonical->what = SsComplete;
-+
-+# elif defined(VGP_loongarch64_linux)
-+ VexGuestLOONGARCH64State* gst = (VexGuestLOONGARCH64State*)gst_vanilla;
-+ ULong a0 = gst->guest_R4; // a0
-+ canonical->sres = VG_(mk_SysRes_loongarch64_linux)(a0);
-+ canonical->what = SsComplete;
-+
- # elif defined(VGP_amd64_freebsd)
- /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */
- VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
-@@ -1606,6 +1635,20 @@ void putSyscallStatusIntoGuestState ( /*IN*/ ThreadId tid,
- VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
- OFFSET_mips32_r4, sizeof(UWord) );
-+# elif defined(VGP_loongarch64_linux)
-+ VexGuestLOONGARCH64State* gst = (VexGuestLOONGARCH64State*)gst_vanilla;
-+ vg_assert(canonical->what == SsComplete);
-+ if (sr_isError(canonical->sres)) {
-+ /* This isn't exactly right, in that really a Failure with res
-+ not in the range 1 .. 4095 is unrepresentable in the
-+ Linux-loongarch64 scheme. Oh well. */
-+ gst->guest_R4 = - (Long)sr_Err(canonical->sres);
-+ } else {
-+ gst->guest_R4 = sr_Res(canonical->sres);
-+ }
-+ VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
-+ OFFSET_loongarch64_R4, sizeof(UWord) );
+ extern ULong
+@@ -1324,6 +1351,11 @@ SysRes VG_(do_syscall) ( UWord sysno, RegWord a1, RegWord a2, RegWord a3,
+ do_syscall_WRK(a1, a2, a3, a4, a5, a6, sysno, ®_a0);
+ return VG_(mk_SysRes_nanomips_linux)(reg_a0);
+
++#elif defined(VGP_loongarch64_linux)
++ UWord val = 0;
++ val = do_syscall_WRK(a1, a2, a3, a4, a5, a6, sysno);
++ return VG_(mk_SysRes_loongarch64_linux)(val);
+
# elif defined(VGP_x86_solaris)
- VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
- SysRes sres = canonical->sres;
-@@ -1855,6 +1898,15 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout )
- layout->s_arg7 = sizeof(UWord) * 1;
- layout->s_arg8 = sizeof(UWord) * 2;
+ UInt val, val2, err = False;
+ Bool restart;
+diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h
+index 1bdd9a9..d0c48e0 100644
+--- a/coregrind/m_syswrap/priv_syswrap-linux.h
++++ b/coregrind/m_syswrap/priv_syswrap-linux.h
+@@ -528,6 +528,13 @@ extern UInt do_syscall_clone_nanomips_linux ( Word (*fn) (void *), /* a0 - 4 */
+ Int* child_tid, /* a4 - 8 */
+ Int* parent_tid, /* a5 - 9 */
+ void* tls_ptr); /* a6 - 10 */
++extern UInt do_syscall_clone_loongarch64_linux ( Word (*fn) (void *), /* a0 */
++ void* stack, /* a1 */
++ Int flags, /* a2 */
++ void* arg, /* a3 */
++ Int* child_tid, /* a4 */
++ Int* parent_tid, /* a5 */
++ void* tls_ptr); /* a6 */
+ #endif // __PRIV_SYSWRAP_LINUX_H
-+#elif defined(VGP_loongarch64_linux)
-+ layout->o_sysno = OFFSET_loongarch64_R11;
-+ layout->o_arg1 = OFFSET_loongarch64_R4;
-+ layout->o_arg2 = OFFSET_loongarch64_R5;
-+ layout->o_arg3 = OFFSET_loongarch64_R6;
-+ layout->o_arg4 = OFFSET_loongarch64_R7;
-+ layout->o_arg5 = OFFSET_loongarch64_R8;
-+ layout->o_arg6 = OFFSET_loongarch64_R9;
+ /*--------------------------------------------------------------------*/
+diff --git a/coregrind/m_syswrap/priv_types_n_macros.h b/coregrind/m_syswrap/priv_types_n_macros.h
+index 6be22f8..c02eb3d 100644
+--- a/coregrind/m_syswrap/priv_types_n_macros.h
++++ b/coregrind/m_syswrap/priv_types_n_macros.h
+@@ -94,7 +94,8 @@ typedef
+ || defined(VGP_ppc32_linux) \
+ || defined(VGP_arm_linux) || defined(VGP_s390x_linux) \
+ || defined(VGP_arm64_linux) \
+- || defined(VGP_nanomips_linux)
++ || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ Int o_arg1;
+ Int o_arg2;
+ Int o_arg3;
+diff --git a/coregrind/m_syswrap/syscall-loongarch64-linux.S b/coregrind/m_syswrap/syscall-loongarch64-linux.S
+new file mode 100644
+index 0000000..5c18041
+--- /dev/null
++++ b/coregrind/m_syswrap/syscall-loongarch64-linux.S
+@@ -0,0 +1,143 @@
+
- #else
- # error "getSyscallLayout: unknown arch"
- #endif
-@@ -2899,6 +2951,25 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch )
- arch->vex.guest_PC -= 2;
- }
- }
++/*--------------------------------------------------------------------*/
++/*--- Support for doing system calls. syscall-loongarch64-linux.S ---*/
++/*--------------------------------------------------------------------*/
+
-+#elif defined(VGP_loongarch64_linux)
-+ arch->vex.guest_PC -= 4; // sizeof(loongarch instr)
++/*
++ This file is part of Valgrind, a dynamic binary instrumentation
++ framework.
+
-+ /* Make sure our caller is actually sane, and we're really backing
-+ back over a syscall.
++ Copyright (C) 2021-2022 Loongson Technology Corporation Limited
+
-+ syscall 0 == 00 2B 00 00
-+ */
-+ {
-+ UChar *p = (UChar *)(Addr)(arch->vex.guest_PC);
-+ if (p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x2B || p[3] != 0x00)
-+ VG_(message)(Vg_DebugMsg,
-+ "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
-+ (ULong)arch->vex.guest_PC, p[0], p[1], p[2], p[3]);
++ This program is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License as
++ published by the Free Software Foundation; either version 2 of the
++ License, or (at your option) any later version.
+
-+ vg_assert(p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x2B && p[3] == 0x00);
-+ }
++ This program is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, see .
++
++ The GNU General Public License is contained in the file COPYING.
++*/
++
++#include "pub_core_basics_asm.h"
+
- #elif defined(VGP_x86_solaris)
- arch->vex.guest_EIP -= 2; // sizeof(int $0x91) or sizeof(syscall)
-
-diff --git a/coregrind/m_trampoline.S b/coregrind/m_trampoline.S
-index da96972..f02d53f 100644
---- a/coregrind/m_trampoline.S
-+++ b/coregrind/m_trampoline.S
-@@ -1520,6 +1520,53 @@ VG_(trampoline_stuff_end):
- # undef UD2_1024
- # undef UD2_PAGE
-
-+/*------------------- loongarch64-linux -------------------*/
-+#else
+#if defined(VGP_loongarch64_linux)
+
-+.global VG_(trampoline_stuff_start)
-+VG_(trampoline_stuff_start):
++#include "pub_core_vkiscnums_asm.h"
++#include "libvex_guest_offsets.h"
+
-+.global VG_(loongarch64_linux_SUBST_FOR_rt_sigreturn)
-+VG_(loongarch64_linux_SUBST_FOR_rt_sigreturn):
-+ li.w $a7, __NR_rt_sigreturn
-+ syscall 0
-+ .long 0 /*illegal insn*/
++/*----------------------------------------------------------------*/
++/*
++ Perform a syscall for the client. This will run a syscall
++ with the client's specific per-thread signal mask.
+
-+/* There's no particular reason that this needs to be handwritten
-+ assembly, but since that's what this file contains, here's a
-+ simple strlen() and strchr() implementations.
++ The structure of this function is such that, if the syscall is
++ interrupted by a signal, we can determine exactly what
++ execution state we were in with respect to the execution of
++ the syscall by examining the value of PC in the signal
++ handler. This means that we can always do the appropriate
++ thing to precisely emulate the kernel's signal/syscall
++ interactions.
++
++ The syscall number is taken from the argument, even though it
++ should also be in guest_state->guest_R11. The syscall result
++ is written back to guest_state->guest_R4 on completion.
++
++ VG_(fixup_guest_state_after_syscall_interrupted) does the
++ thread state fixup in the case where we were interrupted by a
++ signal.
++
++ Prototype:
++
++ UWord ML_(do_syscall_for_client_WRK)(
++ Int syscallno, // $r4 - a0
++ void* guest_state, // $r5 - a1
++ const vki_sigset_t *sysmask, // $r6 - a2
++ const vki_sigset_t *postmask, // $r7 - a3
++ Int nsigwords) // $r8 - a4
+*/
+
-+.global VG_(loongarch64_linux_REDIR_FOR_strlen)
-+.type VG_(loongarch64_linux_REDIR_FOR_strlen), @function
-+VG_(loongarch64_linux_REDIR_FOR_strlen):
-+ move $t0, $a0
-+ strlen_loop:
-+ ld.bu $t1, $a0, 0
-+ addi.d $a0, $a0, 1
-+ bne $t1, $zero, strlen_loop
-+ sub.d $a0, $a0, $t0
-+ addi.d $a0, $a0, -1
-+ jr $ra
-+.size VG_(loongarch64_linux_REDIR_FOR_strlen), .-VG_(loongarch64_linux_REDIR_FOR_strlen)
++/* from vki-loongarch64-linux.h */
++#define VKI_SIG_SETMASK 2
+
-+.global VG_(loongarch64_linux_REDIR_FOR_strchr)
-+.type VG_(loongarch64_linux_REDIR_FOR_strchr), @function
-+VG_(loongarch64_linux_REDIR_FOR_strchr):
-+ strchr_loop:
-+ ld.bu $t0, $a0, 0
-+ beq $t0, $a1, strchr_end
-+ addi.d $a0, $a0, 1
-+ bne $t0, $zero, strchr_loop
-+ move $a0, $zero
-+ strchr_end:
-+ jr $ra
-+.size VG_(loongarch64_linux_REDIR_FOR_strchr), .-VG_(loongarch64_linux_REDIR_FOR_strchr)
++.globl ML_(do_syscall_for_client_WRK)
++ML_(do_syscall_for_client_WRK):
+
-+.global VG_(trampoline_stuff_end)
-+VG_(trampoline_stuff_end):
++ /* Save regs on stack */
++ addi.d $sp, $sp, -24
++ st.d $a1, $sp, 0 /* guest_state */
++ st.d $a3, $sp, 8 /* postmask */
++ st.d $a4, $sp, 16 /* sigsetSzB */
+
- /*---------------- x86-solaris ----------------*/
- #else
- #if defined(VGP_x86_solaris)
-@@ -1719,6 +1766,7 @@ VG_(trampoline_stuff_end):
- #endif
- #endif
- #endif
-+#endif
-
- /* Let the linker know we don't need an executable stack */
- MARK_STACK_NO_EXEC
-diff --git a/coregrind/m_translate.c b/coregrind/m_translate.c
-index 0dd3608..1ae200b 100644
---- a/coregrind/m_translate.c
-+++ b/coregrind/m_translate.c
-@@ -1750,6 +1750,11 @@ Bool VG_(translate) ( ThreadId tid,
- vex_archinfo.arm64_requires_fallback_LLSC;
- # endif
-
-+# if defined(VGP_loongarch64_linux)
-+ /* For now, we only use fallback LLSC */
-+ vex_abiinfo.guest__use_fallback_LLSC = True;
-+# endif
++1: li.w $a7, __NR_rt_sigprocmask
++ li.w $a0, VKI_SIG_SETMASK
++ move $a1, $a2 /* syscall_mask */
++ move $a2, $a3 /* postmask */
++ move $a3, $a4 /* sigsetSzB */
++ syscall 0
+
- /* Set up closure args. */
- closure.tid = tid;
- closure.nraddr = nraddr;
-diff --git a/coregrind/m_vki.c b/coregrind/m_vki.c
-index 0cc1882..11c5fe3 100644
---- a/coregrind/m_vki.c
-+++ b/coregrind/m_vki.c
-@@ -37,13 +37,13 @@
- describing the kernel interface, so this file is nearly empty. */
-
-
--/* ppc32/64, arm64 and mips32/64 (linux) determine page size at startup,
-- hence m_vki is the logical place to store that info. */
-+/* ppc32/64, arm64, mips32/64 and loongarch64 (linux) determine page size
-+ at startup, hence m_vki is the logical place to store that info. */
-
- #if defined(VGP_ppc32_linux) || defined(VGP_ppc64be_linux) \
- || defined(VGP_ppc64le_linux) || defined(VGP_arm64_linux) \
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
-- || defined(VGP_nanomips_linux)
-+ || defined(VGP_nanomips_linux) || defined(VGP_loongarch64_linux)
- unsigned long VKI_PAGE_SHIFT = 12;
- unsigned long VKI_PAGE_SIZE = 1UL << 12;
++ bnez $a0, 5f
++
++ /* Actually do the client syscall */
++ ld.d $a6, $sp, 0 /* guest_state */
++
++ ld.d $a0, $a6, OFFSET_loongarch64_R4 /* a0 */
++ ld.d $a1, $a6, OFFSET_loongarch64_R5 /* a1 */
++ ld.d $a2, $a6, OFFSET_loongarch64_R6 /* a2 */
++ ld.d $a3, $a6, OFFSET_loongarch64_R7 /* a3 */
++ ld.d $a4, $a6, OFFSET_loongarch64_R8 /* a4 */
++ ld.d $a5, $a6, OFFSET_loongarch64_R9 /* a5 */
++
++ ld.d $a7, $a6, OFFSET_loongarch64_R11 /* syscallno */
++
++2: syscall 0
++
++ /* Saving return values into guest state */
++3: st.d $a0, $a6, OFFSET_loongarch64_R4 /* a0 */
++
++4: li.w $a7, __NR_rt_sigprocmask
++ li.w $a0, VKI_SIG_SETMASK
++ ld.d $a1, $sp, 8 /* postmask */
++ move $a2, $zero /* 0 (zero) */
++ ld.d $a3, $sp, 16 /* sigsetSzB */
++ syscall 0
++
++ beqz $a0, 6f
++
++5: /* error */
++ li.w $a0, 0x8000
++
++6: /* Restore sp and return */
++ addi.d $sp, $sp, 24
++ jr $ra
++
++.section .rodata
++/* export the ranges so that
++ VG_(fixup_guest_state_after_syscall_interrupted) can do the
++ right thing */
++
++.globl ML_(blksys_setup)
++.globl ML_(blksys_restart)
++.globl ML_(blksys_complete)
++.globl ML_(blksys_committed)
++.globl ML_(blksys_finished)
++ML_(blksys_setup): .quad 1b
++ML_(blksys_restart): .quad 2b
++ML_(blksys_complete): .quad 3b
++ML_(blksys_committed): .quad 4b
++ML_(blksys_finished): .quad 5b
++
++#endif // defined(VGP_loongarch64_linux)
++
++/* Let the linker know we don't need an executable stack */
++MARK_STACK_NO_EXEC
++
++/*--------------------------------------------------------------------*/
++/*--- end syscall-loongarch64-linux.S ---*/
++/*--------------------------------------------------------------------*/
+diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c
+index 1d80d09..ba8075d 100644
+--- a/coregrind/m_syswrap/syswrap-generic.c
++++ b/coregrind/m_syswrap/syswrap-generic.c
+@@ -3733,7 +3733,7 @@ POST(sys_newfstat)
#endif
-diff --git a/coregrind/pub_core_aspacemgr.h b/coregrind/pub_core_aspacemgr.h
-index b867108..a2b41f3 100644
---- a/coregrind/pub_core_aspacemgr.h
-+++ b/coregrind/pub_core_aspacemgr.h
-@@ -335,7 +335,8 @@ extern Bool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard,
- #if defined(VGP_ppc32_linux) \
- || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
- || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
-- || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
-+ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
-+ || defined(VGP_loongarch64_linux)
- # define VG_STACK_GUARD_SZB 65536 // 1 or 16 pages
- #else
- # define VG_STACK_GUARD_SZB 8192 // 2 pages
-diff --git a/coregrind/pub_core_basics.h b/coregrind/pub_core_basics.h
-index abc5a06..1325451 100644
---- a/coregrind/pub_core_basics.h
-+++ b/coregrind/pub_core_basics.h
-@@ -55,8 +55,8 @@
- typedef
- struct {
-- ULong r_pc; /* x86:EIP, amd64:RIP, ppc:CIA, arm:R15, mips:pc */
-- ULong r_sp; /* x86:ESP, amd64:RSP, ppc:R1, arm:R13, mips:sp */
-+ ULong r_pc; /* x86:EIP, amd64:RIP, ppc:CIA, arm:R15, mips:pc, loongarch64:pc */
-+ ULong r_sp; /* x86:ESP, amd64:RSP, ppc:R1, arm:R13, mips:sp, loongarch64:sp */
- union {
- struct {
- UInt r_ebp;
-@@ -102,6 +102,10 @@ typedef
- ULong r31; /* Return address of the last subroutine call */
- ULong r28;
- } MIPS64;
-+ struct {
-+ ULong r_fp; /* Stack frame pointer or static variable */
-+ ULong r_ra; /* Return address of the last subroutine call */
-+ } LOONGARCH64;
- } misc;
- }
- UnwindStartRegs;
-diff --git a/coregrind/pub_core_debuginfo.h b/coregrind/pub_core_debuginfo.h
-index 4d6ebda..115afff 100644
---- a/coregrind/pub_core_debuginfo.h
-+++ b/coregrind/pub_core_debuginfo.h
-@@ -137,6 +137,10 @@ typedef
- typedef
- struct { Addr pc; Addr sp; Addr fp; Addr ra; }
- D3UnwindRegs;
-+#elif defined(VGA_loongarch64)
-+typedef
-+ struct { Addr pc; Addr ra; Addr sp; Addr fp; }
-+ D3UnwindRegs;
+ #if !defined(VGO_solaris) && !defined(VGP_arm64_linux) && \
+- !defined(VGP_nanomips_linux)
++ !defined(VGP_nanomips_linux) && !defined(VGP_loongarch64_linux)
+ static vki_sigset_t fork_saved_mask;
+
+ // In Linux, the sys_fork() function varies across architectures, but we
+diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
+index 87ab82e..425b936 100644
+--- a/coregrind/m_syswrap/syswrap-linux.c
++++ b/coregrind/m_syswrap/syswrap-linux.c
+@@ -310,6 +310,16 @@ static void run_a_thread_NORETURN ( Word tidW )
+ : "r" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)
+ : "memory" , "$t4", "$a0"
+ );
++#elif defined(VGP_loongarch64_linux)
++ asm volatile (
++ "st.w %1, %0 \n\t" /* set tst->status = VgTs_Empty */
++ "li.w $a7, %2 \n\t" /* set a7 = __NR_exit */
++ "ld.w $a0, %3 \n\t" /* set a0 = tst->os_state.exitcode */
++ "syscall 0 \n\t" /* exit(tst->os_state.exitcode) */
++ : "=m" (tst->status)
++ : "r" (VgTs_Empty), "n" (__NR_exit), "m" (tst->os_state.exitcode)
++ : "memory", "a0", "a7"
++ );
#else
- # error "Unsupported arch"
+ # error Unknown platform
#endif
-diff --git a/coregrind/pub_core_machine.h b/coregrind/pub_core_machine.h
-index a9b7dd8..4793d59 100644
---- a/coregrind/pub_core_machine.h
-+++ b/coregrind/pub_core_machine.h
-@@ -126,6 +126,11 @@
- # define VG_ELF_MACHINE EM_NANOMIPS
- # define VG_ELF_CLASS ELFCLASS32
- # undef VG_PLAT_USES_PPCTOC
+@@ -535,6 +545,13 @@ static SysRes clone_new_thread ( Word (*fn)(void *),
+ (ML_(start_thread_NORETURN), stack, flags, ctst,
+ child_tidptr, parent_tidptr, NULL);
+ res = VG_ (mk_SysRes_nanomips_linux) (ret);
+#elif defined(VGP_loongarch64_linux)
-+# define VG_ELF_DATA2XXX ELFDATA2LSB
-+# define VG_ELF_MACHINE EM_LOONGARCH
-+# define VG_ELF_CLASS ELFCLASS64
-+# undef VG_PLAT_USES_PPCTOC
++ UInt ret = 0;
++ ctst->arch.vex.guest_R4 = 0;
++ ret = do_syscall_clone_loongarch64_linux
++ (ML_(start_thread_NORETURN), stack, flags, ctst,
++ child_tidptr, parent_tidptr, NULL);
++ res = VG_(mk_SysRes_loongarch64_linux)(ret);
#else
- # error Unknown platform
+ # error Unknown platform
#endif
-@@ -163,6 +168,10 @@
- # define VG_INSTR_PTR guest_PC
- # define VG_STACK_PTR guest_r29
- # define VG_FRAME_PTR guest_r30
-+#elif defined(VGA_loongarch64)
-+# define VG_INSTR_PTR guest_PC
-+# define VG_STACK_PTR guest_R3
-+# define VG_FRAME_PTR guest_R22
+@@ -597,6 +614,8 @@ static SysRes setup_child_tls (ThreadId ctid, Addr tlsaddr)
+ #elif defined(VGP_mips32_linux) || defined(VGP_nanomips_linux)
+ ctst->arch.vex.guest_ULR = tlsaddr;
+ ctst->arch.vex.guest_r27 = tlsaddr;
++#elif defined(VGP_loongarch64_linux)
++ ctst->arch.vex.guest_R2 = tlsaddr;
#else
- # error Unknown arch
+ # error Unknown platform
#endif
-@@ -234,6 +243,10 @@ void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs,
- s390x: initially: call VG_(machine_get_hwcaps)
-
- then safe to use VG_(machine_get_VexArchInfo)
-+ -------------
-+ loongarch64: initially: call VG_(machine_get_hwcaps)
-+
-+ then safe to use VG_(machine_get_VexArchInfo)
+@@ -755,7 +774,7 @@ static SysRes ML_(do_fork_clone) ( ThreadId tid, UInt flags,
+ || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
+ || defined(VGP_arm_linux) || defined(VGP_mips32_linux) \
+ || defined(VGP_mips64_linux) || defined(VGP_arm64_linux) \
+- || defined(VGP_nanomips_linux)
++ || defined(VGP_nanomips_linux) || defined(VGP_loongarch64_linux)
+ res = VG_(do_syscall5)( __NR_clone, flags,
+ (UWord)NULL, (UWord)parent_tidptr,
+ (UWord)NULL, (UWord)child_tidptr );
+@@ -828,7 +847,8 @@ PRE(sys_clone)
+ #define PRA_CHILD_TIDPTR PRA5
+ #define ARG_TLS ARG4
+ #define PRA_TLS PRA4
+-#elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux)
++#elif defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \
++ || defined(VGP_loongarch64_linux)
+ #define ARG_CHILD_TIDPTR ARG4
+ #define PRA_CHILD_TIDPTR PRA4
+ #define ARG_TLS ARG5
+@@ -4412,9 +4432,11 @@ PRE(sys_sigaction)
+ PRE_MEM_READ( "sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
+ PRE_MEM_READ( "sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
+ PRE_MEM_READ( "sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
++#if !defined(VGP_loongarch64_linux)
+ if (ML_(safe_to_deref)(sa,sizeof(struct vki_old_sigaction))
+ && (sa->sa_flags & VKI_SA_RESTORER))
+ PRE_MEM_READ( "sigaction(act->sa_restorer)", (Addr)&sa->sa_restorer, sizeof(sa->sa_restorer));
++#endif
+ }
- VG_(machine_get_hwcaps) may use signals (although it attempts to
- leave signal state unchanged) and therefore should only be
-diff --git a/coregrind/pub_core_mallocfree.h b/coregrind/pub_core_mallocfree.h
-index b5922ca..d285caa 100644
---- a/coregrind/pub_core_mallocfree.h
-+++ b/coregrind/pub_core_mallocfree.h
-@@ -78,6 +78,7 @@ typedef Int ArenaId;
- defined(VGP_ppc64le_linux) || \
- defined(VGP_s390x_linux) || \
- (defined(VGP_mips64_linux) && !defined(VGABI_N32)) || \
-+ defined(VGP_loongarch64_linux) || \
- defined(VGP_x86_freebsd) || \
- defined(VGP_amd64_freebsd) || \
- defined(VGP_x86_darwin) || \
-diff --git a/coregrind/pub_core_signals.h b/coregrind/pub_core_signals.h
-index ae8555b..c53323f 100644
---- a/coregrind/pub_core_signals.h
-+++ b/coregrind/pub_core_signals.h
-@@ -77,6 +77,7 @@ extern void VG_(synth_sigill) (ThreadId tid, Addr addr);
- extern void VG_(synth_sigtrap) (ThreadId tid);
- extern void VG_(synth_sigbus) (ThreadId tid);
- extern void VG_(synth_sigfpe) (ThreadId tid, UInt code);
-+extern void VG_(synth_sigsys) (ThreadId tid);
+ if (ARG3 != 0) {
+@@ -4444,7 +4466,9 @@ PRE(sys_sigaction)
- /* Extend the stack to cover addr, if possible */
- extern Bool VG_(extend_stack)(ThreadId tid, Addr addr);
-diff --git a/coregrind/pub_core_syscall.h b/coregrind/pub_core_syscall.h
-index 6c4f825..5d7ff44 100644
---- a/coregrind/pub_core_syscall.h
-+++ b/coregrind/pub_core_syscall.h
-@@ -105,6 +105,7 @@ extern SysRes VG_(mk_SysRes_mips32_linux)( UWord v0, UWord v1,
- extern SysRes VG_(mk_SysRes_mips64_linux)( ULong v0, ULong v1,
- ULong a3 );
- extern SysRes VG_(mk_SysRes_nanomips_linux)( UWord a0);
-+extern SysRes VG_(mk_SysRes_loongarch64_linux)( UWord a0 );
- extern SysRes VG_(mk_SysRes_x86_solaris) ( Bool isErr, UInt val, UInt val2 );
- extern SysRes VG_(mk_SysRes_amd64_solaris) ( Bool isErr, ULong val, ULong val2 );
- extern SysRes VG_(mk_SysRes_Error) ( UWord val );
-diff --git a/coregrind/pub_core_trampoline.h b/coregrind/pub_core_trampoline.h
-index 54c575a..3700acb 100644
---- a/coregrind/pub_core_trampoline.h
-+++ b/coregrind/pub_core_trampoline.h
-@@ -171,6 +171,12 @@ extern Char* VG_(nanomips_linux_REDIR_FOR_index)( const Char*, Int );
- extern UInt VG_(nanomips_linux_REDIR_FOR_strlen)( void* );
- #endif
+ new.ksa_handler = oldnew->ksa_handler;
+ new.sa_flags = oldnew->sa_flags;
++#if !defined(VGP_loongarch64_linux)
+ new.sa_restorer = oldnew->sa_restorer;
++#endif
+ convert_sigset_to_rt(&oldnew->sa_mask, &new.sa_mask);
+ newp = &new;
+ }
+@@ -4457,7 +4481,9 @@ PRE(sys_sigaction)
-+#if defined(VGP_loongarch64_linux)
-+extern Addr VG_(loongarch64_linux_SUBST_FOR_rt_sigreturn);
-+extern UInt VG_(loongarch64_linux_REDIR_FOR_strlen)( void* );
-+extern Char* VG_(loongarch64_linux_REDIR_FOR_strchr)( const Char*, Int );
+ oldold->ksa_handler = oldp->ksa_handler;
+ oldold->sa_flags = oldp->sa_flags;
++#if !defined(VGP_loongarch64_linux)
+ oldold->sa_restorer = oldp->sa_restorer;
++#endif
+ oldold->sa_mask = oldp->sa_mask.sig[0];
+ }
+ }
+@@ -4530,10 +4556,13 @@ PRE(sys_rt_sigaction)
+ PRE_MEM_READ( "rt_sigaction(act->sa_handler)", (Addr)&sa->ksa_handler, sizeof(sa->ksa_handler));
+ PRE_MEM_READ( "rt_sigaction(act->sa_mask)", (Addr)&sa->sa_mask, sizeof(sa->sa_mask));
+ PRE_MEM_READ( "rt_sigaction(act->sa_flags)", (Addr)&sa->sa_flags, sizeof(sa->sa_flags));
++#if !defined(VGP_loongarch64_linux)
+ if (ML_(safe_to_deref)(sa,sizeof(vki_sigaction_toK_t))
+ && (sa->sa_flags & VKI_SA_RESTORER))
+ PRE_MEM_READ( "rt_sigaction(act->sa_restorer)", (Addr)&sa->sa_restorer, sizeof(sa->sa_restorer));
+#endif
+ }
+
- #if defined(VGP_x86_solaris)
- extern SizeT VG_(x86_solaris_REDIR_FOR_strcmp)(const HChar *, const HChar *);
- extern SizeT VG_(x86_solaris_REDIR_FOR_strlen)(const HChar *);
-diff --git a/coregrind/pub_core_transtab.h b/coregrind/pub_core_transtab.h
-index 6cc11f6..fe93926 100644
---- a/coregrind/pub_core_transtab.h
-+++ b/coregrind/pub_core_transtab.h
-@@ -81,7 +81,8 @@ static inline UWord VG_TT_FAST_HASH ( Addr guest ) {
- }
-
- #elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
-- || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_arm64)
-+ || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_arm64) \
-+ || defined(VGA_loongarch64)
- static inline UWord VG_TT_FAST_HASH ( Addr guest ) {
- // Instructions are 4-byte aligned.
- UWord merged = ((UWord)guest) >> 2;
-diff --git a/coregrind/pub_core_transtab_asm.h b/coregrind/pub_core_transtab_asm.h
-index 8b585f1..e73c89a 100644
---- a/coregrind/pub_core_transtab_asm.h
-+++ b/coregrind/pub_core_transtab_asm.h
-@@ -83,7 +83,7 @@
- #if defined(VGA_amd64) || defined(VGA_arm64) \
- || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
- || (defined(VGA_mips64) && defined(VGABI_64)) \
-- || defined(VGA_s390x)
-+ || defined(VGA_s390x) || defined(VGA_loongarch64)
- // And all other 64-bit hosts
- # define VG_FAST_CACHE_SET_BITS 6
- // These FCS_{g,h}{0,1,2,3} are the values of
-diff --git a/coregrind/vgdb-invoker-ptrace.c b/coregrind/vgdb-invoker-ptrace.c
-index 78a6a16..798fe5f 100644
---- a/coregrind/vgdb-invoker-ptrace.c
-+++ b/coregrind/vgdb-invoker-ptrace.c
-@@ -50,9 +50,10 @@
- // Rather we use PTRACE_GETREGS or PTRACE_PEEKUSER.
+ if (ARG3 != 0)
+ PRE_MEM_WRITE( "rt_sigaction(oldact)", ARG3, sizeof(vki_sigaction_fromK_t));
- // The only platform on which we must use PTRACE_GETREGSET is arm64.
-+// We use PTRACE_GETREGSET on loongarch64 as well.
- // The resulting vgdb cannot work in a bi-arch setup.
- // -1 means we will check that PTRACE_GETREGSET works.
--# if defined(VGA_arm64)
-+# if defined(VGA_arm64) || defined(VGA_loongarch64)
- #define USE_PTRACE_GETREGSET
- # endif
- #endif
-@@ -529,6 +530,9 @@ static struct user_regs_struct user_save;
- # else
- static struct user_pt_regs user_save;
- # endif
-+# elif defined(VGA_loongarch64)
-+/* loongarch64 is extra special, glibc only defined user_regs_struct. */
-+static struct user_regs_struct user_save;
- # else
- static struct user user_save;
- # endif
-@@ -805,6 +809,9 @@ Bool invoker_invoke_gdbserver (pid_t pid)
- # else
- struct user_pt_regs user_mod;
- # endif
-+# elif defined(VGA_loongarch64)
-+/* loongarch64 is extra special, glibc only defined user_regs_struct. */
-+ struct user_regs_struct user_mod;
- # else
- struct user user_mod;
- # endif
-@@ -874,6 +881,8 @@ Bool invoker_invoke_gdbserver (pid_t pid)
- sp = p[29];
- #elif defined(VGA_mips64)
- sp = user_mod.regs[29];
-+#elif defined(VGA_loongarch64)
-+ sp = user_mod.regs[3];
- #else
- I_die_here : (sp) architecture missing in vgdb-invoker-ptrace.c
+@@ -6908,7 +6937,8 @@ POST(sys_lookup_dcookie)
#endif
-@@ -961,6 +970,8 @@ Bool invoker_invoke_gdbserver (pid_t pid)
- #elif defined(VGA_mips64)
- assert(0); // cannot vgdb a 32 bits executable with a 64 bits exe
-+#elif defined(VGA_loongarch64)
-+ assert(0); // cannot vgdb a 32 bits executable with a 64 bits exe
- #else
- I_die_here : architecture missing in vgdb-invoker-ptrace.c
- #endif
-@@ -1068,6 +1079,12 @@ Bool invoker_invoke_gdbserver (pid_t pid)
- user_mod.regs[31] = bad_return;
- user_mod.regs[34] = shared64->invoke_gdbserver;
- user_mod.regs[25] = shared64->invoke_gdbserver;
-+#elif defined(VGA_loongarch64)
-+ /* put check arg in register a0 */
-+ user_mod.regs[4] = check;
-+ /* put NULL return address in ra */
-+ user_mod.regs[1] = bad_return;
-+ user_mod.csr_era = shared64->invoke_gdbserver;
- #else
- I_die_here: architecture missing in vgdb-invoker-ptrace.c
- #endif
-diff --git a/dhat/Makefile.in b/dhat/Makefile.in
-index 9b9f943..ee93cc5 100644
---- a/dhat/Makefile.in
-+++ b/dhat/Makefile.in
-@@ -686,6 +686,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
+ #if defined(VGP_amd64_linux) || defined(VGP_s390x_linux) \
+- || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ PRE(sys_lookup_dcookie)
+ {
+ *flags |= SfMayBlock;
+@@ -13680,7 +13710,7 @@ POST(sys_close_range)
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
+ /* If the close_range range is too wide, we don't want to loop
+ through the whole range. */
+- if (ARG2 == ~0U)
++ if ((UInt)ARG2 == ~0U)
+ ML_(record_fd_close_range)(tid, ARG1);
+ else {
+ for (fd = ARG1; fd <= last; fd++)
+diff --git a/coregrind/m_syswrap/syswrap-loongarch64-linux.c b/coregrind/m_syswrap/syswrap-loongarch64-linux.c
+new file mode 100644
+index 0000000..7014b58
+--- /dev/null
++++ b/coregrind/m_syswrap/syswrap-loongarch64-linux.c
+@@ -0,0 +1,648 @@
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -733,6 +739,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
-
-@@ -823,6 +830,10 @@ TOOL_LDFLAGS_MIPS64_LINUX = \
- -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
- @FLAG_M64@
-
-+TOOL_LDFLAGS_LOONGARCH64_LINUX = \
-+ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
-+ @FLAG_M64@
++/*---------------------------------------------------------------------*/
++/*--- Platform-specific syscalls stuff. syswrap-loongarch64-linux.c ---*/
++/*---------------------------------------------------------------------*/
+
- TOOL_LDFLAGS_X86_SOLARIS = \
- $(TOOL_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
-
-@@ -883,6 +894,9 @@ LIBREPLACEMALLOC_MIPS32_LINUX = \
- LIBREPLACEMALLOC_MIPS64_LINUX = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips64-linux.a
-
-+LIBREPLACEMALLOC_LOONGARCH64_LINUX = \
-+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-loongarch64-linux.a
++/*
++ This file is part of Valgrind, a dynamic binary instrumentation
++ framework.
+
- LIBREPLACEMALLOC_X86_SOLARIS = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-solaris.a
-
-@@ -955,6 +969,11 @@ LIBREPLACEMALLOC_LDFLAGS_MIPS64_LINUX = \
- $(LIBREPLACEMALLOC_MIPS64_LINUX) \
- -Wl,--no-whole-archive
-
-+LIBREPLACEMALLOC_LDFLAGS_LOONGARCH64_LINUX = \
-+ -Wl,--whole-archive \
-+ $(LIBREPLACEMALLOC_LOONGARCH64_LINUX) \
-+ -Wl,--no-whole-archive
++ Copyright (C) 2021-2022 Loongson Technology Corporation Limited
+
- LIBREPLACEMALLOC_LDFLAGS_X86_SOLARIS = \
- -Wl,--whole-archive \
- $(LIBREPLACEMALLOC_X86_SOLARIS) \
-diff --git a/dhat/tests/Makefile.in b/dhat/tests/Makefile.in
-index 433a72b..58ee764 100644
---- a/dhat/tests/Makefile.in
-+++ b/dhat/tests/Makefile.in
-@@ -623,6 +623,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++ This program is free software; you can redistribute it and/or
++ modify it under the terms of the GNU General Public License as
++ published by the Free Software Foundation; either version 2 of the
++ License, or (at your option) any later version.
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -670,6 +676,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/drd/Makefile.in b/drd/Makefile.in
-index 989dcae..cb7f41a 100644
---- a/drd/Makefile.in
-+++ b/drd/Makefile.in
-@@ -767,6 +767,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++ This program is distributed in the hope that it will be useful, but
++ WITHOUT ANY WARRANTY; without even the implied warranty of
++ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
++ General Public License for more details.
++
++ You should have received a copy of the GNU General Public License
++ along with this program; if not, see .
++
++ The GNU General Public License is contained in the file COPYING.
++*/
++
++#if defined(VGP_loongarch64_linux)
++
++#include "pub_core_basics.h"
++#include "pub_core_vki.h"
++#include "pub_core_vkiscnums.h"
++#include "pub_core_threadstate.h"
++#include "pub_core_aspacemgr.h"
++#include "pub_core_libcbase.h"
++#include "pub_core_libcassert.h"
++#include "pub_core_libcprint.h"
++#include "pub_core_libcsignal.h"
++#include "pub_core_options.h"
++#include "pub_core_scheduler.h"
++#include "pub_core_sigframe.h" // For VG_(sigframe_destroy)()
++#include "pub_core_syscall.h"
++#include "pub_core_syswrap.h"
++#include "pub_core_tooliface.h"
++
++#include "priv_types_n_macros.h"
++#include "priv_syswrap-generic.h" /* for decls of generic wrappers */
++#include "priv_syswrap-linux.h" /* for decls of linux-ish wrappers */
++#include "priv_syswrap-main.h"
++
++
++/* ---------------------------------------------------------------------
++ clone() handling
++ ------------------------------------------------------------------ */
++
++/* Call f(arg1), but first switch stacks, using 'stack' as the new
++ stack, and use 'retaddr' as f's return-to address. Also, clear all
++ the integer registers before entering f. */
++__attribute__((noreturn))
++void ML_(call_on_new_stack_0_1) ( Addr stack,
++ Addr retaddr,
++ void (*f) (Word),
++ Word arg1 );
++asm (
++".text\n"
++".globl vgModuleLocal_call_on_new_stack_0_1 \n\t"
++"vgModuleLocal_call_on_new_stack_0_1: \n\t"
++" move $sp, $a0 \n\t" /* sp = stack */
++" move $ra, $a1 \n\t" /* ra = retaddr */
++" move $t0, $a2 \n\t" /* t0 = f */
++" move $a0, $a3 \n\t" /* a0 = arg1 */
++" move $a1, $zero \n\t" /* zero all GP regs */
++" move $a2, $zero \n\t"
++" move $a3, $zero \n\t"
++" move $a4, $zero \n\t"
++" move $a5, $zero \n\t"
++" move $a6, $zero \n\t"
++" move $a7, $zero \n\t"
++/* don't zero out t0 */
++" move $t1, $zero \n\t"
++" move $t2, $zero \n\t"
++" move $t3, $zero \n\t"
++" move $t4, $zero \n\t"
++" move $t5, $zero \n\t"
++" move $t6, $zero \n\t"
++" move $t7, $zero \n\t"
++" move $t8, $zero \n\t"
++" jr $t0 \n\t" /* jump to f */
++".previous \n\t"
++);
++
++/*
++ Perform a clone system call. clone is strange because it has
++ fork()-like return-twice semantics, so it needs special
++ handling here.
++
++ Upon entry, we have:
++
++ Word (*fn)(void*) in a0
++ void* child_stack in a1
++ int flags in a2
++ void* arg in a3
++ pid_t* child_tid in a4
++ pid_t* parent_tid in a5
++ void* tls_ptr in a6
++
++ System call requires:
++
++ unsigned long clone_flags in a0
++ unsigned long newsp in a1
++ int* parent_tidptr in a2
++ int* child_tidptr in a3
++ unsigned long tls in a4
++ int __NR_clone in a7
++*/
++
++#define __NR_CLONE VG_STRINGIFY(__NR_clone)
++#define __NR_EXIT VG_STRINGIFY(__NR_exit)
++
++// See priv_syswrap-linux.h for arg profile.
++asm(
++".text \n\t"
++".globl do_syscall_clone_loongarch64_linux \n\t"
++"do_syscall_clone_loongarch64_linux: \n\t"
++/* Save ra */
++" addi.d $sp, $sp, -16 \n\t"
++" st.d $ra, $sp, 0 \n\t"
++
++/* Save fn and arg */
++" addi.d $a1, $a1, -16 \n\t"
++" st.d $a0, $a1, 0 \n\t" /* fn */
++" st.d $a3, $a1, 8 \n\t" /* arg */
++
++/* Call sys_clone */
++" move $a0, $a2 \n\t" /* flags */
++" move $a2, $a5 \n\t" /* parent */
++" move $a3, $a4 \n\t" /* child */
++" move $a4, $a6 \n\t" /* tls */
++" li.w $a7, " __NR_CLONE " \n\t"
++" syscall 0 \n\t"
++
++/* If we are a child? */
++" bnez $a0, 1f \n\t"
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -814,6 +820,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
-
-@@ -904,6 +911,10 @@ TOOL_LDFLAGS_MIPS64_LINUX = \
- -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
- @FLAG_M64@
-
-+TOOL_LDFLAGS_LOONGARCH64_LINUX = \
-+ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
-+ @FLAG_M64@
++/* Restore fn and arg */
++" ld.d $a1, $sp, 0 \n\t" /* fn */
++" ld.d $a0, $sp, 8 \n\t" /* arg */
+
- TOOL_LDFLAGS_X86_SOLARIS = \
- $(TOOL_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
-
-@@ -964,6 +975,9 @@ LIBREPLACEMALLOC_MIPS32_LINUX = \
- LIBREPLACEMALLOC_MIPS64_LINUX = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips64-linux.a
-
-+LIBREPLACEMALLOC_LOONGARCH64_LINUX = \
-+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-loongarch64-linux.a
++/* Call fn(arg) */
++" jr $a1 \n\t"
+
- LIBREPLACEMALLOC_X86_SOLARIS = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-solaris.a
-
-@@ -1036,6 +1050,11 @@ LIBREPLACEMALLOC_LDFLAGS_MIPS64_LINUX = \
- $(LIBREPLACEMALLOC_MIPS64_LINUX) \
- -Wl,--no-whole-archive
-
-+LIBREPLACEMALLOC_LDFLAGS_LOONGARCH64_LINUX = \
-+ -Wl,--whole-archive \
-+ $(LIBREPLACEMALLOC_LOONGARCH64_LINUX) \
-+ -Wl,--no-whole-archive
++/* Call exit(a0) */
++" li.w $a7, " __NR_EXIT" \n\t"
++" syscall 0 \n\t"
+
- LIBREPLACEMALLOC_LDFLAGS_X86_SOLARIS = \
- -Wl,--whole-archive \
- $(LIBREPLACEMALLOC_X86_SOLARIS) \
-diff --git a/drd/drd_bitmap.h b/drd/drd_bitmap.h
-index 3b71d74..1f11f23 100644
---- a/drd/drd_bitmap.h
-+++ b/drd/drd_bitmap.h
-@@ -140,7 +140,7 @@ Addr make_address(const UWord a1, const UWord a0)
- #define BITS_PER_BITS_PER_UWORD 5
- #elif defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
- || defined(VGA_s390x) || (defined(VGA_mips64) && !defined(VGABI_N32)) \
-- || defined(VGA_arm64)
-+ || defined(VGA_arm64) || defined(VGA_loongarch64)
- #define BITS_PER_BITS_PER_UWORD 6
- #else
- #error Unknown platform.
-diff --git a/drd/drd_load_store.c b/drd/drd_load_store.c
-index 80d326a..da6283b 100644
---- a/drd/drd_load_store.c
-+++ b/drd/drd_load_store.c
-@@ -53,6 +53,8 @@
- #define STACK_POINTER_OFFSET OFFSET_mips32_r29
- #elif defined(VGA_mips64)
- #define STACK_POINTER_OFFSET OFFSET_mips64_r29
-+#elif defined(VGA_loongarch64)
-+#define STACK_POINTER_OFFSET OFFSET_loongarch64_R3
- #else
- #error Unknown architecture.
- #endif
-@@ -634,6 +636,8 @@ IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
- break; /* not interesting to DRD */
- case Imbe_CancelReservation:
- break; /* not interesting to DRD */
-+ case Imbe_InsnFence:
-+ break; /* not interesting to DRD */
- default:
- tl_assert(0);
- }
-diff --git a/drd/tests/Makefile.in b/drd/tests/Makefile.in
-index 80833e7..320e589 100644
---- a/drd/tests/Makefile.in
-+++ b/drd/tests/Makefile.in
-@@ -1195,6 +1195,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++/* If we are parent or error, just return to caller */
++"1: \n\t"
++" ld.d $ra, $sp, 0 \n\t"
++" addi.d $sp, $sp, 16 \n\t"
++" jr $ra \n\t"
++".previous \n\t"
++);
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -1242,6 +1248,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/drd/tests/pth_barrier_thr_cr.supp b/drd/tests/pth_barrier_thr_cr.supp
-index 653b2d2..34482cc 100644
---- a/drd/tests/pth_barrier_thr_cr.supp
-+++ b/drd/tests/pth_barrier_thr_cr.supp
-@@ -9,3 +9,14 @@
- fun:pthread_barrier_wait_intercept
- fun:pthread_barrier_wait
- }
-+{
-+ number-of-concurrent-pthead_barrier_wait()-calls-exceeds-barrier-count
-+ drd:BarrierErr
-+ fun:pthread_barrier_wait@*
-+}
++#undef __NR_CLONE
++#undef __NR_EXIT
++
++/* ---------------------------------------------------------------------
++ More thread stuff
++ ------------------------------------------------------------------ */
++
++// loongarch64 doesn't have any architecture specific thread stuff that
++// needs to be cleaned up
++void VG_(cleanup_thread) ( ThreadArchState* arch )
+{
-+ number-of-concurrent-pthead_barrier_wait()-calls-exceeds-barrier-count
-+ drd:BarrierErr
-+ fun:pthread_barrier_wait_intercept
-+ fun:pthread_barrier_wait@*
+}
-diff --git a/exp-bbv/Makefile.in b/exp-bbv/Makefile.in
-index 39f9cf9..d79f54f 100644
---- a/exp-bbv/Makefile.in
-+++ b/exp-bbv/Makefile.in
-@@ -621,6 +621,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -668,6 +674,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
-
-@@ -758,6 +765,10 @@ TOOL_LDFLAGS_MIPS64_LINUX = \
- -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
- @FLAG_M64@
-
-+TOOL_LDFLAGS_LOONGARCH64_LINUX = \
-+ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
-+ @FLAG_M64@
++/* ---------------------------------------------------------------------
++ PRE/POST wrappers for loongarch64/Linux-specific syscalls
++ ------------------------------------------------------------------ */
+
- TOOL_LDFLAGS_X86_SOLARIS = \
- $(TOOL_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
-
-@@ -818,6 +829,9 @@ LIBREPLACEMALLOC_MIPS32_LINUX = \
- LIBREPLACEMALLOC_MIPS64_LINUX = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips64-linux.a
-
-+LIBREPLACEMALLOC_LOONGARCH64_LINUX = \
-+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-loongarch64-linux.a
++#define PRE(name) DEFN_PRE_TEMPLATE(loongarch64_linux, name)
++#define POST(name) DEFN_POST_TEMPLATE(loongarch64_linux, name)
+
- LIBREPLACEMALLOC_X86_SOLARIS = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-solaris.a
-
-@@ -890,6 +904,11 @@ LIBREPLACEMALLOC_LDFLAGS_MIPS64_LINUX = \
- $(LIBREPLACEMALLOC_MIPS64_LINUX) \
- -Wl,--no-whole-archive
-
-+LIBREPLACEMALLOC_LDFLAGS_LOONGARCH64_LINUX = \
-+ -Wl,--whole-archive \
-+ $(LIBREPLACEMALLOC_LOONGARCH64_LINUX) \
-+ -Wl,--no-whole-archive
++/* Add prototypes for the wrappers declared here, so that gcc doesn't
++ harass us for not having prototypes. Really this is a kludge --
++ the right thing to do is to make these wrappers 'static' since they
++ aren't visible outside this file, but that requires even more macro
++ magic. */
++DECL_TEMPLATE(loongarch64_linux, sys_ptrace);
++DECL_TEMPLATE(loongarch64_linux, sys_mmap);
++DECL_TEMPLATE(loongarch64_linux, sys_rt_sigreturn);
+
- LIBREPLACEMALLOC_LDFLAGS_X86_SOLARIS = \
- -Wl,--whole-archive \
- $(LIBREPLACEMALLOC_X86_SOLARIS) \
-diff --git a/exp-bbv/tests/Makefile.in b/exp-bbv/tests/Makefile.in
-index 686a369..d36f4ee 100644
---- a/exp-bbv/tests/Makefile.in
-+++ b/exp-bbv/tests/Makefile.in
-@@ -594,6 +594,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++PRE(sys_ptrace)
++{
++ PRINT("sys_ptrace ( %ld, %ld, %lx, %lx )",
++ SARG1, SARG2, ARG3, ARG4);
++ PRE_REG_READ4(int, "ptrace",
++ long, request,
++ long, pid,
++ unsigned long, addr,
++ unsigned long, data);
++ switch (ARG1) {
++ case VKI_PTRACE_PEEKTEXT:
++ case VKI_PTRACE_PEEKDATA:
++ case VKI_PTRACE_PEEKUSR:
++ PRE_MEM_WRITE("ptrace(peek)", ARG4, sizeof(long));
++ break;
++ case VKI_PTRACE_GETEVENTMSG:
++ PRE_MEM_WRITE("ptrace(geteventmsg)", ARG4, sizeof(unsigned long));
++ break;
++ case VKI_PTRACE_GETSIGINFO:
++ PRE_MEM_WRITE("ptrace(getsiginfo)", ARG4, sizeof(vki_siginfo_t));
++ break;
++ case VKI_PTRACE_SETSIGINFO:
++ PRE_MEM_READ("ptrace(setsiginfo)", ARG4, sizeof(vki_siginfo_t));
++ break;
++ case VKI_PTRACE_GETREGSET:
++ ML_(linux_PRE_getregset)(tid, ARG3, ARG4);
++ break;
++ default:
++ break;
++ }
++}
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -641,6 +647,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/exp-bbv/tests/amd64-linux/Makefile.in b/exp-bbv/tests/amd64-linux/Makefile.in
-index f9a6cc7..a5e711a 100644
---- a/exp-bbv/tests/amd64-linux/Makefile.in
-+++ b/exp-bbv/tests/amd64-linux/Makefile.in
-@@ -615,6 +615,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++POST(sys_ptrace)
++{
++ switch (ARG1) {
++ case VKI_PTRACE_TRACEME:
++ ML_(linux_POST_traceme)(tid);
++ break;
++ case VKI_PTRACE_PEEKTEXT:
++ case VKI_PTRACE_PEEKDATA:
++ case VKI_PTRACE_PEEKUSR:
++ POST_MEM_WRITE (ARG4, sizeof(long));
++ break;
++ case VKI_PTRACE_GETEVENTMSG:
++ POST_MEM_WRITE (ARG4, sizeof(unsigned long));
++ break;
++ case VKI_PTRACE_GETSIGINFO:
++ POST_MEM_WRITE (ARG4, sizeof(vki_siginfo_t));
++ break;
++ case VKI_PTRACE_GETREGSET:
++ ML_(linux_POST_getregset)(tid, ARG3, ARG4);
++ break;
++ default:
++ break;
++ }
++}
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -662,6 +668,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/exp-bbv/tests/arm-linux/Makefile.in b/exp-bbv/tests/arm-linux/Makefile.in
-index 911a02c..a8886b9 100644
---- a/exp-bbv/tests/arm-linux/Makefile.in
-+++ b/exp-bbv/tests/arm-linux/Makefile.in
-@@ -575,6 +575,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++PRE(sys_mmap)
++{
++ SysRes r;
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -622,6 +628,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/exp-bbv/tests/ppc32-linux/Makefile.in b/exp-bbv/tests/ppc32-linux/Makefile.in
-index f5bd96b..7d6107c 100644
---- a/exp-bbv/tests/ppc32-linux/Makefile.in
-+++ b/exp-bbv/tests/ppc32-linux/Makefile.in
-@@ -575,6 +575,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++ PRINT("sys_mmap ( %#lx, %lu, %lu, %#lx, %lu, %lu )",
++ ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
++ PRE_REG_READ6(long, "mmap",
++ unsigned long, addr, unsigned long, len,
++ unsigned long, prot, unsigned long, flags,
++ unsigned long, fd, vki_off_t, offset);
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -622,6 +628,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/exp-bbv/tests/x86-linux/Makefile.in b/exp-bbv/tests/x86-linux/Makefile.in
-index ee3baa5..702f33f 100644
---- a/exp-bbv/tests/x86-linux/Makefile.in
-+++ b/exp-bbv/tests/x86-linux/Makefile.in
-@@ -575,6 +575,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++ r = ML_(generic_PRE_sys_mmap)( tid, ARG1, ARG2, ARG3, ARG4, ARG5, ARG6 );
++ SET_STATUS_from_SysRes(r);
++}
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -622,6 +628,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/exp-bbv/tests/x86/Makefile.in b/exp-bbv/tests/x86/Makefile.in
-index b1557c3..dbecbe3 100644
---- a/exp-bbv/tests/x86/Makefile.in
-+++ b/exp-bbv/tests/x86/Makefile.in
-@@ -586,6 +586,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++PRE(sys_rt_sigreturn)
++{
++ /* See comments on PRE(sys_rt_sigreturn) in syswrap-loongarch64-linux.c for
++ an explanation of what follows. */
++ ThreadState* tst;
++ PRINT("rt_sigreturn ( )");
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -633,6 +639,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/gdbserver_tests/Makefile.am b/gdbserver_tests/Makefile.am
-index fbcb659..30e17c0 100755
---- a/gdbserver_tests/Makefile.am
-+++ b/gdbserver_tests/Makefile.am
-@@ -15,6 +15,7 @@ dist_noinst_SCRIPTS = \
- filter_gdb filter_make_empty \
- filter_memcheck_monitor filter_stderr filter_vgdb \
- filter_helgrind_monitor filter_helgrind_monitor_solaris \
-+ filter_helgrind_monitor_loongarch64 \
- filter_passsigalrm \
- send_signal
-
-diff --git a/gdbserver_tests/Makefile.in b/gdbserver_tests/Makefile.in
-index 712e8b2..7c9a353 100644
---- a/gdbserver_tests/Makefile.in
-+++ b/gdbserver_tests/Makefile.in
-@@ -664,6 +664,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++ vg_assert(VG_(is_valid_tid)(tid));
++ vg_assert(tid >= 1 && tid < VG_N_THREADS);
++ vg_assert(VG_(is_running_thread)(tid));
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -711,6 +717,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-@@ -740,6 +747,7 @@ dist_noinst_SCRIPTS = \
- filter_gdb filter_make_empty \
- filter_memcheck_monitor filter_stderr filter_vgdb \
- filter_helgrind_monitor filter_helgrind_monitor_solaris \
-+ filter_helgrind_monitor_loongarch64 \
- filter_passsigalrm \
- send_signal
-
-diff --git a/gdbserver_tests/filter_helgrind_monitor b/gdbserver_tests/filter_helgrind_monitor
-index 4fc2e9a..21bf6be 100755
---- a/gdbserver_tests/filter_helgrind_monitor
-+++ b/gdbserver_tests/filter_helgrind_monitor
-@@ -14,6 +14,8 @@ if $dir/../tests/os_test solaris; then
- $dir/filter_helgrind_monitor_solaris
- elif $dir/../tests/os_test freebsd; then
- gsed -e '/\(rtld_start.S\|kill.S\|_exit.S\|_select.S\): No such file or directory/d'
-+elif $dir/../tests/arch_test loongarch64; then
-+ $dir/filter_helgrind_monitor_loongarch64
- else
- cat
- fi |
-diff --git a/gdbserver_tests/filter_helgrind_monitor_loongarch64 b/gdbserver_tests/filter_helgrind_monitor_loongarch64
-new file mode 100755
-index 0000000..cda73e4
---- /dev/null
-+++ b/gdbserver_tests/filter_helgrind_monitor_loongarch64
-@@ -0,0 +1,43 @@
-+#!/usr/bin/env perl
-+# From gdbserver_tests/filter_helgrind_monitor_solaris
++ tst = VG_(get_ThreadState)(tid);
+
-+#
-+# Filter out all helgrind information about locks except the one named "mx".
-+# One lock record looks like:
-+# Lock ga 0x........ {
-+# Address 0x........ is 2648 bytes inside data symbol "_rtld_local"
-+# kind mbRec
-+# }
++ /* This is only so that the PC is (might be) useful to report if
++ something goes wrong in the sigreturn */
++ ML_(fixup_guest_state_to_restart_syscall)(&tst->arch);
+
-+use strict;
-+use warnings;
++ /* Restore register state from frame and remove it */
++ VG_(sigframe_destroy)(tid, True);
+
-+my $lock_start_line = undef;
-+my $skip_to_closing_line = 0;
-+while () {
-+ my $line = $_;
-+ chomp($line);
-+ if ($line =~ /^Lock ga 0x[\.]+\s+{$/) {
-+ $lock_start_line = $line;
-+ $skip_to_closing_line = 1;
-+ } elsif (($lock_start_line) &&
-+ ($line =~ /\s*Address 0x[\.]+ is \d+ bytes inside data symbol "(\S+)"/)) {
-+ if ($1 eq "mx") {
-+ print "$lock_start_line\n";
-+ print "$line\n";
-+ $skip_to_closing_line = 0;
-+ }
-+ } elsif ($line =~ /^}$/) {
-+ if ($skip_to_closing_line == 0) {
-+ print "$line\n";
-+ }
-+ undef($lock_start_line);
-+ $skip_to_closing_line = 0;
-+ } else {
-+ if ($skip_to_closing_line == 0) {
-+ print "$line\n";
-+ }
-+ }
++ /* Tell the driver not to update the guest state with the "result",
++ and set a bogus result to keep it happy. */
++ *flags |= SfNoWriteResult;
++ SET_STATUS_Success(0);
++
++ /* Check to see if any signals arose as a result of this. */
++ *flags |= SfPollAfter;
+}
+
-+exit 0;
-diff --git a/gdbserver_tests/solaris/Makefile.in b/gdbserver_tests/solaris/Makefile.in
-index 374e279..341f7bf 100644
---- a/gdbserver_tests/solaris/Makefile.in
-+++ b/gdbserver_tests/solaris/Makefile.in
-@@ -529,6 +529,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++#undef PRE
++#undef POST
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -576,6 +582,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/helgrind/Makefile.in b/helgrind/Makefile.in
-index bd6cfdb..a85320e 100644
---- a/helgrind/Makefile.in
-+++ b/helgrind/Makefile.in
-@@ -709,6 +709,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++/* ---------------------------------------------------------------------
++ The loongarch64/Linux syscall table
++ ------------------------------------------------------------------ */
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -756,6 +762,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
-
-@@ -846,6 +853,10 @@ TOOL_LDFLAGS_MIPS64_LINUX = \
- -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
- @FLAG_M64@
-
-+TOOL_LDFLAGS_LOONGARCH64_LINUX = \
-+ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
-+ @FLAG_M64@
++#define PLAX_(sysno, name) WRAPPER_ENTRY_X_(loongarch64_linux, sysno, name)
++#define PLAXY(sysno, name) WRAPPER_ENTRY_XY(loongarch64_linux, sysno, name)
+
- TOOL_LDFLAGS_X86_SOLARIS = \
- $(TOOL_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
-
-@@ -906,6 +917,9 @@ LIBREPLACEMALLOC_MIPS32_LINUX = \
- LIBREPLACEMALLOC_MIPS64_LINUX = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips64-linux.a
-
-+LIBREPLACEMALLOC_LOONGARCH64_LINUX = \
-+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-loongarch64-linux.a
++// This table maps from __NR_xxx syscall numbers (from
++// linux/include/uapi/asm-generic/unistd.h) to the appropriate PRE/POST
++// sys_foo() wrappers on loongarch64 (as per sys_call_table in
++// linux/arch/loongarch/kernel/syscall.c).
++//
++// For those syscalls not handled by Valgrind, the annotation indicate its
++// arch/OS combination, eg. */* (generic), */Linux (Linux only), ?/?
++// (unknown).
+
- LIBREPLACEMALLOC_X86_SOLARIS = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-solaris.a
-
-@@ -978,6 +992,11 @@ LIBREPLACEMALLOC_LDFLAGS_MIPS64_LINUX = \
- $(LIBREPLACEMALLOC_MIPS64_LINUX) \
- -Wl,--no-whole-archive
-
-+LIBREPLACEMALLOC_LDFLAGS_LOONGARCH64_LINUX = \
-+ -Wl,--whole-archive \
-+ $(LIBREPLACEMALLOC_LOONGARCH64_LINUX) \
-+ -Wl,--no-whole-archive
++static SyscallTableEntry syscall_main_table[] = {
++ LINXY(__NR_io_setup, sys_io_setup), // 0
++ LINX_(__NR_io_destroy, sys_io_destroy), // 1
++ LINX_(__NR_io_submit, sys_io_submit), // 2
++ LINXY(__NR_io_cancel, sys_io_cancel), // 3
++ LINXY(__NR_io_getevents, sys_io_getevents), // 4
++ LINX_(__NR_setxattr, sys_setxattr), // 5
++ LINX_(__NR_lsetxattr, sys_lsetxattr), // 6
++ LINX_(__NR_fsetxattr, sys_fsetxattr), // 7
++ LINXY(__NR_getxattr, sys_getxattr), // 8
++ LINXY(__NR_lgetxattr, sys_lgetxattr), // 9
++ LINXY(__NR_fgetxattr, sys_fgetxattr), // 10
++ LINXY(__NR_listxattr, sys_listxattr), // 11
++ LINXY(__NR_llistxattr, sys_llistxattr), // 12
++ LINXY(__NR_flistxattr, sys_flistxattr), // 13
++ LINX_(__NR_removexattr, sys_removexattr), // 14
++ LINX_(__NR_lremovexattr, sys_lremovexattr), // 15
++ LINX_(__NR_fremovexattr, sys_fremovexattr), // 16
++ GENXY(__NR_getcwd, sys_getcwd), // 17
++ LINXY(__NR_lookup_dcookie, sys_lookup_dcookie), // 18
++ LINXY(__NR_eventfd2, sys_eventfd2), // 19
++ LINXY(__NR_epoll_create1, sys_epoll_create1), // 20
++ LINX_(__NR_epoll_ctl, sys_epoll_ctl), // 21
++ LINXY(__NR_epoll_pwait, sys_epoll_pwait), // 22
++ GENXY(__NR_dup, sys_dup), // 23
++ LINXY(__NR_dup3, sys_dup3), // 24
++ LINXY(__NR3264_fcntl, sys_fcntl), // 25
++ LINXY(__NR_inotify_init1, sys_inotify_init1), // 26
++ LINX_(__NR_inotify_add_watch, sys_inotify_add_watch), // 27
++ LINX_(__NR_inotify_rm_watch, sys_inotify_rm_watch), // 28
++ LINXY(__NR_ioctl, sys_ioctl), // 29
++ LINX_(__NR_ioprio_set, sys_ioprio_set), // 30
++ LINX_(__NR_ioprio_get, sys_ioprio_get), // 31
++ GENX_(__NR_flock, sys_flock), // 32
++ LINX_(__NR_mknodat, sys_mknodat), // 33
++ LINX_(__NR_mkdirat, sys_mkdirat), // 34
++ LINX_(__NR_unlinkat, sys_unlinkat), // 35
++ LINX_(__NR_symlinkat, sys_symlinkat), // 36
++ LINX_(__NR_linkat, sys_linkat), // 37
++ // (__NR_renameat, sys_renameat), // 38
++ LINX_(__NR_umount2, sys_umount), // 39
++ LINX_(__NR_mount, sys_mount), // 40
++ LINX_(__NR_pivot_root, sys_pivot_root), // 41
++ // (__NR_nfsservctl, sys_ni_syscall), // 42
++ GENXY(__NR3264_statfs, sys_statfs), // 43
++ GENXY(__NR3264_fstatfs, sys_fstatfs), // 44
++ GENX_(__NR3264_truncate, sys_truncate), // 45
++ GENX_(__NR3264_ftruncate, sys_ftruncate), // 46
++ LINX_(__NR_fallocate, sys_fallocate), // 47
++ LINX_(__NR_faccessat, sys_faccessat), // 48
++ GENX_(__NR_chdir, sys_chdir), // 49
++ GENX_(__NR_fchdir, sys_fchdir), // 50
++ GENX_(__NR_chroot, sys_chroot), // 51
++ GENX_(__NR_fchmod, sys_fchmod), // 52
++ LINX_(__NR_fchmodat, sys_fchmodat), // 53
++ LINX_(__NR_fchownat, sys_fchownat), // 54
++ GENX_(__NR_fchown, sys_fchown), // 55
++ LINXY(__NR_openat, sys_openat), // 56
++ GENX_(__NR_close, sys_close), // 57
++ LINX_(__NR_vhangup, sys_vhangup), // 58
++ LINXY(__NR_pipe2, sys_pipe2), // 59
++ LINX_(__NR_quotactl, sys_quotactl), // 60
++ GENXY(__NR_getdents64, sys_getdents64), // 61
++ LINX_(__NR3264_lseek, sys_lseek), // 62
++ GENXY(__NR_read, sys_read), // 63
++ GENX_(__NR_write, sys_write), // 64
++ GENXY(__NR_readv, sys_readv), // 65
++ GENX_(__NR_writev, sys_writev), // 66
++ GENXY(__NR_pread64, sys_pread64), // 67
++ GENX_(__NR_pwrite64, sys_pwrite64), // 68
++ LINXY(__NR_preadv, sys_preadv), // 69
++ LINX_(__NR_pwritev, sys_pwritev), // 70
++ LINXY(__NR3264_sendfile, sys_sendfile), // 71
++ LINXY(__NR_pselect6, sys_pselect6), // 72
++ LINXY(__NR_ppoll, sys_ppoll), // 73
++ LINXY(__NR_signalfd4, sys_signalfd4), // 74
++ LINX_(__NR_vmsplice, sys_vmsplice), // 75
++ LINX_(__NR_splice, sys_splice), // 76
++ LINX_(__NR_tee, sys_tee), // 77
++ LINXY(__NR_readlinkat, sys_readlinkat), // 78
++ // (__NR3264_fstatat, sys_newfstatat), // 79
++ // (__NR3264_fstat, sys_newfstat), // 80
++ GENX_(__NR_sync, sys_sync), // 81
++ GENX_(__NR_fsync, sys_fsync), // 82
++ GENX_(__NR_fdatasync, sys_fdatasync), // 83
++ LINX_(__NR_sync_file_range, sys_sync_file_range), // 84
++ LINXY(__NR_timerfd_create, sys_timerfd_create), // 85
++ LINXY(__NR_timerfd_settime, sys_timerfd_settime), // 86
++ LINXY(__NR_timerfd_gettime, sys_timerfd_gettime), // 87
++ LINX_(__NR_utimensat, sys_utimensat), // 88
++ GENX_(__NR_acct, sys_acct), // 89
++ LINXY(__NR_capget, sys_capget), // 90
++ LINX_(__NR_capset, sys_capset), // 91
++ LINX_(__NR_personality, sys_personality), // 92
++ GENX_(__NR_exit, sys_exit), // 93
++ LINX_(__NR_exit_group, sys_exit_group), // 94
++ LINXY(__NR_waitid, sys_waitid), // 95
++ LINX_(__NR_set_tid_address, sys_set_tid_address), // 96
++ LINX_(__NR_unshare, sys_unshare), // 97
++ LINXY(__NR_futex, sys_futex), // 98
++ LINX_(__NR_set_robust_list, sys_set_robust_list), // 99
++ LINXY(__NR_get_robust_list, sys_get_robust_list), // 100
++ GENXY(__NR_nanosleep, sys_nanosleep), // 101
++ GENXY(__NR_getitimer, sys_getitimer), // 102
++ GENXY(__NR_setitimer, sys_setitimer), // 103
++ // (__NR_kexec_load, sys_kexec_load), // 104
++ LINX_(__NR_init_module, sys_init_module), // 105
++ LINX_(__NR_delete_module, sys_delete_module), // 106
++ LINXY(__NR_timer_create, sys_timer_create), // 107
++ LINXY(__NR_timer_gettime, sys_timer_gettime), // 108
++ LINX_(__NR_timer_getoverrun, sys_timer_getoverrun), // 109
++ LINXY(__NR_timer_settime, sys_timer_settime), // 110
++ LINX_(__NR_timer_delete, sys_timer_delete), // 111
++ LINX_(__NR_clock_settime, sys_clock_settime), // 112
++ LINXY(__NR_clock_gettime, sys_clock_gettime), // 113
++ LINXY(__NR_clock_getres, sys_clock_getres), // 114
++ LINXY(__NR_clock_nanosleep, sys_clock_nanosleep), // 115
++ LINXY(__NR_syslog, sys_syslog), // 116
++ PLAXY(__NR_ptrace, sys_ptrace), // 117
++ LINXY(__NR_sched_setparam, sys_sched_setparam), // 118
++ LINX_(__NR_sched_setscheduler, sys_sched_setscheduler), // 119
++ LINX_(__NR_sched_getscheduler, sys_sched_getscheduler), // 120
++ LINXY(__NR_sched_getparam, sys_sched_getparam), // 121
++ LINX_(__NR_sched_setaffinity, sys_sched_setaffinity), // 122
++ LINXY(__NR_sched_getaffinity, sys_sched_getaffinity), // 123
++ LINX_(__NR_sched_yield, sys_sched_yield), // 124
++ LINX_(__NR_sched_get_priority_max, sys_sched_get_priority_max), // 125
++ LINX_(__NR_sched_get_priority_min, sys_sched_get_priority_min), // 126
++ LINXY(__NR_sched_rr_get_interval, sys_sched_rr_get_interval), // 127
++ // (__NR_restart_syscall, sys_restart_syscall), // 128
++ GENX_(__NR_kill, sys_kill), // 129
++ LINXY(__NR_tkill, sys_tkill), // 130
++ LINXY(__NR_tgkill, sys_tgkill), // 131
++ GENXY(__NR_sigaltstack, sys_sigaltstack), // 132
++ LINX_(__NR_rt_sigsuspend, sys_rt_sigsuspend), // 133
++ LINXY(__NR_rt_sigaction, sys_rt_sigaction), // 134
++ LINXY(__NR_rt_sigprocmask, sys_rt_sigprocmask), // 135
++ LINXY(__NR_rt_sigpending, sys_rt_sigpending), // 136
++ LINXY(__NR_rt_sigtimedwait, sys_rt_sigtimedwait), // 137
++ LINXY(__NR_rt_sigqueueinfo, sys_rt_sigqueueinfo), // 138
++ PLAX_(__NR_rt_sigreturn, sys_rt_sigreturn), // 139
++ GENX_(__NR_setpriority, sys_setpriority), // 140
++ GENX_(__NR_getpriority, sys_getpriority), // 141
++ // (__NR_reboot, sys_reboot), // 142
++ GENX_(__NR_setregid, sys_setregid), // 143
++ GENX_(__NR_setgid, sys_setgid), // 144
++ GENX_(__NR_setreuid, sys_setreuid), // 145
++ GENX_(__NR_setuid, sys_setuid), // 146
++ LINX_(__NR_setresuid, sys_setresuid), // 147
++ LINXY(__NR_getresuid, sys_getresuid), // 148
++ LINX_(__NR_setresgid, sys_setresgid), // 149
++ LINXY(__NR_getresgid, sys_getresgid), // 150
++ LINX_(__NR_setfsuid, sys_setfsuid), // 151
++ LINX_(__NR_setfsgid, sys_setfsgid), // 152
++ GENXY(__NR_times, sys_times), // 153
++ GENX_(__NR_setpgid, sys_setpgid), // 154
++ GENX_(__NR_getpgid, sys_getpgid), // 155
++ GENX_(__NR_getsid, sys_getsid), // 156
++ GENX_(__NR_setsid, sys_setsid), // 157
++ GENXY(__NR_getgroups, sys_getgroups), // 158
++ GENX_(__NR_setgroups, sys_setgroups), // 159
++ GENXY(__NR_uname, sys_newuname), // 160
++ GENX_(__NR_sethostname, sys_sethostname), // 161
++ // (__NR_setdomainname, sys_setdomainname), // 162
++ // (__NR_getrlimit, sys_old_getrlimit), // 163
++ // (__NR_setrlimit, sys_setrlimit), // 164
++ GENXY(__NR_getrusage, sys_getrusage), // 165
++ GENX_(__NR_umask, sys_umask), // 166
++ LINXY(__NR_prctl, sys_prctl), // 167
++ LINXY(__NR_getcpu, sys_getcpu), // 168
++ GENXY(__NR_gettimeofday, sys_gettimeofday), // 169
++ GENX_(__NR_settimeofday, sys_settimeofday), // 170
++ LINXY(__NR_adjtimex, sys_adjtimex), // 171
++ GENX_(__NR_getpid, sys_getpid), // 172
++ GENX_(__NR_getppid, sys_getppid), // 173
++ GENX_(__NR_getuid, sys_getuid), // 174
++ GENX_(__NR_geteuid, sys_geteuid), // 175
++ GENX_(__NR_getgid, sys_getgid), // 176
++ GENX_(__NR_getegid, sys_getegid), // 177
++ LINX_(__NR_gettid, sys_gettid), // 178
++ LINXY(__NR_sysinfo, sys_sysinfo), // 179
++ LINXY(__NR_mq_open, sys_mq_open), // 180
++ LINX_(__NR_mq_unlink, sys_mq_unlink), // 181
++ LINX_(__NR_mq_timedsend, sys_mq_timedsend), // 182
++ LINXY(__NR_mq_timedreceive, sys_mq_timedreceive), // 183
++ LINX_(__NR_mq_notify, sys_mq_notify), // 184
++ LINXY(__NR_mq_getsetattr, sys_mq_getsetattr), // 185
++ LINX_(__NR_msgget, sys_msgget), // 186
++ LINXY(__NR_msgctl, sys_msgctl), // 187
++ LINXY(__NR_msgrcv, sys_msgrcv), // 188
++ LINX_(__NR_msgsnd, sys_msgsnd), // 189
++ LINX_(__NR_semget, sys_semget), // 190
++ LINXY(__NR_semctl, sys_semctl), // 191
++ LINX_(__NR_semtimedop, sys_semtimedop), // 192
++ LINX_(__NR_semop, sys_semop), // 193
++ LINX_(__NR_shmget, sys_shmget), // 194
++ LINXY(__NR_shmctl, sys_shmctl), // 195
++ LINXY(__NR_shmat, sys_shmat), // 196
++ LINXY(__NR_shmdt, sys_shmdt), // 197
++ LINXY(__NR_socket, sys_socket), // 198
++ LINXY(__NR_socketpair, sys_socketpair), // 199
++ LINX_(__NR_bind, sys_bind), // 200
++ LINX_(__NR_listen, sys_listen), // 201
++ LINXY(__NR_accept, sys_accept), // 202
++ LINX_(__NR_connect, sys_connect), // 203
++ LINXY(__NR_getsockname, sys_getsockname), // 204
++ LINXY(__NR_getpeername, sys_getpeername), // 205
++ LINX_(__NR_sendto, sys_sendto), // 206
++ LINXY(__NR_recvfrom, sys_recvfrom), // 207
++ LINX_(__NR_setsockopt, sys_setsockopt), // 208
++ LINXY(__NR_getsockopt, sys_getsockopt), // 209
++ LINX_(__NR_shutdown, sys_shutdown), // 210
++ LINX_(__NR_sendmsg, sys_sendmsg), // 211
++ LINXY(__NR_recvmsg, sys_recvmsg), // 212
++ LINX_(__NR_readahead, sys_readahead), // 213
++ GENX_(__NR_brk, sys_brk), // 214
++ GENXY(__NR_munmap, sys_munmap), // 215
++ GENX_(__NR_mremap, sys_mremap), // 216
++ LINX_(__NR_add_key, sys_add_key), // 217
++ LINX_(__NR_request_key, sys_request_key), // 218
++ LINXY(__NR_keyctl, sys_keyctl), // 219
++ LINX_(__NR_clone, sys_clone), // 220
++ GENX_(__NR_execve, sys_execve), // 221
++ PLAX_(__NR3264_mmap, sys_mmap), // 222
++ LINX_(__NR3264_fadvise64, sys_fadvise64), // 223
++ // (__NR_swapon, sys_swapon), // 224
++ // (__NR_swapoff, sys_swapoff), // 225
++ GENXY(__NR_mprotect, sys_mprotect), // 226
++ GENX_(__NR_msync, sys_msync), // 227
++ GENX_(__NR_mlock, sys_mlock), // 228
++ GENX_(__NR_munlock, sys_munlock), // 229
++ GENX_(__NR_mlockall, sys_mlockall), // 230
++ LINX_(__NR_munlockall, sys_munlockall), // 231
++ GENXY(__NR_mincore, sys_mincore), // 232
++ GENX_(__NR_madvise, sys_madvise), // 233
++ // (__NR_remap_file_pages, sys_remap_file_pages), // 234
++ LINX_(__NR_mbind, sys_mbind), // 235
++ LINXY(__NR_get_mempolicy, sys_get_mempolicy), // 236
++ LINX_(__NR_set_mempolicy, sys_set_mempolicy), // 237
++ // (__NR_migrate_pages, sys_migrate_pages), // 238
++ LINXY(__NR_move_pages, sys_move_pages), // 239
++ LINXY(__NR_rt_tgsigqueueinfo, sys_rt_tgsigqueueinfo), // 240
++ LINXY(__NR_perf_event_open, sys_perf_event_open), // 241
++ LINXY(__NR_accept4, sys_accept4), // 242
++ LINXY(__NR_recvmmsg, sys_recvmmsg), // 243
+
- LIBREPLACEMALLOC_LDFLAGS_X86_SOLARIS = \
- -Wl,--whole-archive \
- $(LIBREPLACEMALLOC_X86_SOLARIS) \
-diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c
-index 3146cc4..ee80472 100644
---- a/helgrind/hg_main.c
-+++ b/helgrind/hg_main.c
-@@ -4870,6 +4870,7 @@ IRSB* hg_instrument ( VgCallbackClosure* closure,
- switch (st->Ist.MBE.event) {
- case Imbe_Fence:
- case Imbe_CancelReservation:
-+ case Imbe_InsnFence:
- break; /* not interesting */
- default:
- goto unhandled;
-diff --git a/helgrind/tests/Makefile.in b/helgrind/tests/Makefile.in
-index 8f23215..e011962 100644
---- a/helgrind/tests/Makefile.in
-+++ b/helgrind/tests/Makefile.in
-@@ -920,6 +920,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
++ GENXY(__NR_wait4, sys_wait4), // 260
++ LINXY(__NR_prlimit64, sys_prlimit64), // 261
++ LINXY(__NR_fanotify_init, sys_fanotify_init), // 262
++ LINX_(__NR_fanotify_mark, sys_fanotify_mark), // 263
++ LINXY(__NR_name_to_handle_at, sys_name_to_handle_at), // 264
++ LINXY(__NR_open_by_handle_at, sys_open_by_handle_at), // 265
++ LINXY(__NR_clock_adjtime, sys_clock_adjtime), // 266
++ LINX_(__NR_syncfs, sys_syncfs), // 267
++ LINX_(__NR_setns, sys_setns), // 268
++ LINXY(__NR_sendmmsg, sys_sendmmsg), // 269
++ LINXY(__NR_process_vm_readv, sys_process_vm_readv), // 270
++ LINX_(__NR_process_vm_writev, sys_process_vm_writev), // 271
++ LINX_(__NR_kcmp, sys_kcmp), // 272
++ LINX_(__NR_finit_module, sys_finit_module), // 273
++ LINX_(__NR_sched_setattr, sys_sched_setattr), // 274
++ LINXY(__NR_sched_getattr, sys_sched_getattr), // 275
++ LINX_(__NR_renameat2, sys_renameat2), // 276
++ // (__NR_seccomp, sys_seccomp), // 277
++ LINXY(__NR_getrandom, sys_getrandom), // 278
++ LINXY(__NR_memfd_create, sys_memfd_create), // 279
++ LINXY(__NR_bpf, sys_bpf), // 280
++ LINX_(__NR_execveat, sys_execveat), // 281
++ // (__NR_userfaultfd, sys_userfaultfd), // 282
++ LINX_(__NR_membarrier, sys_membarrier), // 283
++ GENX_(__NR_mlock2, sys_mlock2), // 284
++ LINX_(__NR_copy_file_range, sys_copy_file_range), // 285
++ LINXY(__NR_preadv2, sys_preadv2), // 286
++ LINX_(__NR_pwritev2, sys_pwritev2), // 287
++ // (__NR_pkey_mprotect, sys_pkey_mprotect), // 288
++ // (__NR_pkey_alloc, sys_pkey_alloc), // 289
++ // (__NR_pkey_free, sys_pkey_free), // 290
++ LINXY(__NR_statx, sys_statx), // 291
++ // (__NR_io_pgetevents, sys_io_pgetevents), // 292
++ // (__NR_rseq, sys_rseq), // 293
++ // (__NR_kexec_file_load, sys_kexec_file_load), // 294
+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -967,6 +973,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/helgrind/tests/annotate_hbefore.c b/helgrind/tests/annotate_hbefore.c
-index 259d3b6..3200c6c 100644
---- a/helgrind/tests/annotate_hbefore.c
-+++ b/helgrind/tests/annotate_hbefore.c
-@@ -314,6 +314,36 @@ UWord do_acasW ( UWord* addr, UWord expected, UWord nyu )
- return success;
- }
-
-+#elif defined(VGA_loongarch64)
++ // (__NR_pidfd_send_signal, sys_pidfd_send_signal), // 424
++ LINXY(__NR_io_uring_setup, sys_io_uring_setup), // 425
++ LINXY(__NR_io_uring_enter, sys_io_uring_enter), // 426
++ LINXY(__NR_io_uring_register, sys_io_uring_register), // 427
++ // (__NR_open_tree, sys_open_tree), // 428
++ // (__NR_move_mount, sys_move_mount), // 429
++ // (__NR_fsopen, sys_fsopen), // 430
++ // (__NR_fsconfig, sys_fsconfig), // 431
++ // (__NR_fsmount, sys_fsmount), // 432
++ // (__NR_fspick, sys_fspick), // 433
++ // (__NR_pidfd_open, sys_pidfd_open), // 434
++ GENX_(__NR_clone3, sys_ni_syscall), // 435
++ LINXY(__NR_close_range, sys_close_range), // 436
++ LINXY(__NR_openat2, sys_openat2), // 437
++ LINXY(__NR_pidfd_getfd, sys_pidfd_getfd), // 438
++ LINX_(__NR_faccessat2, sys_faccessat2), // 439
++ // (__NR_process_madvise, sys_process_madvise), // 440
++ LINXY(__NR_epoll_pwait2, sys_epoll_pwait2), // 441
++ // (__NR_mount_setattr, sys_mount_setattr), // 442
++ // (__NR_quotactl_fd, sys_quotactl_fd), // 443
++ // (__NR_landlock_create_ruleset, sys_landlock_create_ruleset), // 444
++ // (__NR_landlock_add_rule, sys_landlock_add_rule), // 445
++ // (__NR_landlock_restrict_self, sys_landlock_restrict_self), // 446
++ // (__NR_memfd_secret, sys_memfd_secret), // 447
++ // (__NR_process_mrelease, sys_process_mrelease), // 448
++ // (__NR_futex_waitv, sys_futex_waitv) // 449
++ // (__NR_set_mempolicy_home_node, sys_set_mempolicy_home_node) // 450
++ // (__NR_cachestat, sys_cachestat) // 451
++ LINX_(__NR_fchmodat2, sys_fchmodat2) // 452
++};
+
-+// loongarch64
-+/* return 1 if success, 0 if failure */
-+UWord do_acasW ( UWord* addr, UWord expected, UWord nyu )
++SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )
+{
-+ UWord success;
-+ UWord block[3] = { (UWord)addr, nyu, expected };
++ const UInt syscall_main_table_size
++ = sizeof(syscall_main_table) / sizeof(syscall_main_table[0]);
+
-+ __asm__ __volatile__(
-+ " ld.d $t0, %1, 0 \n\t"
-+ " ld.d $t2, %1, 16 \n\t"
-+ " ld.d $t3, %1, 8 \n\t"
-+ " ll.d $t1, $t0, 0 \n\t"
-+ " bne $t1, $t2, 1f \n\t"
-+ " sc.d $t3, $t0, 0 \n\t"
-+ " move %0, $t3 \n\t"
-+ " b 2f \n\t"
-+ "1: \n\t"
-+ " move %0, $zero \n\t"
-+ "2: \n\t"
-+ : /*out*/ "=r" (success)
-+ : /*in*/ "r" (&block[0])
-+ : /*trash*/ "t0", "t1", "t2", "t3", "memory"
-+ );
++ /* Is it in the contiguous initial section of the table? */
++ if (sysno < syscall_main_table_size) {
++ SyscallTableEntry* sys = &syscall_main_table[sysno];
++ if (sys->before == NULL)
++ return NULL; /* no entry */
++ else
++ return sys;
++ }
+
-+ assert(success == 0 || success == 1);
-+ return success;
++ /* Can't find a wrapper */
++ return NULL;
+}
+
- #endif
-
- void atomic_incW ( UWord* w )
-diff --git a/helgrind/tests/tc07_hbl1.c b/helgrind/tests/tc07_hbl1.c
-index 54297de..246d13c 100644
---- a/helgrind/tests/tc07_hbl1.c
-+++ b/helgrind/tests/tc07_hbl1.c
-@@ -18,6 +18,7 @@
- #undef PLAT_arm64_linux
- #undef PLAT_s390x_linux
- #undef PLAT_mips32_linux
-+#undef PLAT_loongarch64_linux
- #undef PLAT_x86_solaris
- #undef PLAT_amd64_solaris
-
-@@ -47,6 +48,8 @@
- # define PLAT_mips32_linux 1
- #elif defined(__linux__) && defined(__nanomips__)
- # define PLAT_nanomips_linux 1
-+#elif defined(__linux__) && defined(__loongarch__) && (__loongarch_grlen == 64)
-+# define PLAT_loongarch64_linux 1
- #elif defined(__sun__) && defined(__i386__)
- # define PLAT_x86_solaris 1
- #elif defined(__sun__) && defined(__x86_64__)
-@@ -131,6 +134,20 @@
- : /*out*/ : /*in*/ "r"(&(_lval)) \
- : /*trash*/ "$t0", "$t1", "memory" \
- )
-+#elif defined(PLAT_loongarch64_linux)
-+# define INC(_lval,_lqual) \
-+ __asm__ __volatile__ ( \
-+ "1: \n" \
-+ " move $t0, %0 \n" \
-+ " ll.w $t1, $t0, 0 \n" \
-+ " addi.w $t1, $t1, 1 \n" \
-+ " sc.w $t1, $t0, 0 \n" \
-+ " li.w $t2, 1 \n" \
-+ " bne $t1, $t2, 1b \n" \
-+ : /*out*/ \
-+ : /*in*/ "r" (&(_lval)) \
-+ : /*trash*/ "$t0", "$t1", "$t2", "memory" \
-+ )
- #else
- # error "Fix Me for this platform"
- #endif
-diff --git a/helgrind/tests/tc08_hbl2.c b/helgrind/tests/tc08_hbl2.c
-index c3a2ec7..8683168 100644
---- a/helgrind/tests/tc08_hbl2.c
-+++ b/helgrind/tests/tc08_hbl2.c
-@@ -35,6 +35,7 @@
- #undef PLAT_s390x_linux
- #undef PLAT_mips32_linux
- #undef PLAT_mips64_linux
-+#undef PLAT_loongarch64_linux
- #undef PLAT_x86_solaris
- #undef PLAT_amd64_solaris
-
-@@ -68,6 +69,8 @@
- #endif
- #elif defined(__linux__) && defined(__nanomips__)
- # define PLAT_nanomips_linux 1
-+#elif defined(__linux__) && defined(__loongarch__) && (__loongarch_grlen == 64)
-+# define PLAT_loongarch64_linux 1
- #elif defined(__sun__) && defined(__i386__)
- # define PLAT_x86_solaris 1
- #elif defined(__sun__) && defined(__x86_64__)
-@@ -151,6 +154,20 @@
- : /*out*/ : /*in*/ "r"(&(_lval)) \
- : /*trash*/ "$t0", "$t1", "memory" \
- )
-+#elif defined(PLAT_loongarch64_linux)
-+# define INC(_lval,_lqual) \
-+ __asm__ __volatile__ ( \
-+ "1: \n" \
-+ " move $t0, %0 \n" \
-+ " ll.w $t1, $t0, 0 \n" \
-+ " addi.w $t1, $t1, 1 \n" \
-+ " sc.w $t1, $t0, 0 \n" \
-+ " li.w $t2, 1 \n" \
-+ " bne $t1, $t2, 1b \n" \
-+ : /*out*/ \
-+ : /*in*/ "r" (&(_lval)) \
-+ : /*trash*/ "$t0", "$t1", "$t2", "memory" \
-+ )
- #else
- # error "Fix Me for this platform"
- #endif
-diff --git a/helgrind/tests/tc11_XCHG.c b/helgrind/tests/tc11_XCHG.c
-index 08e34a0..64b3d2b 100644
---- a/helgrind/tests/tc11_XCHG.c
-+++ b/helgrind/tests/tc11_XCHG.c
-@@ -20,6 +20,7 @@
- #undef PLAT_arm_linux
- #undef PLAT_s390x_linux
- #undef PLAT_mips32_linux
-+#undef PLAT_loongarch64_linux
- #undef PLAT_x86_solaris
- #undef PLAT_amd64_solaris
-
-@@ -49,6 +50,8 @@
- # define PLAT_mips32_linux 1
- #elif defined(__linux__) && defined(__nanomips__)
- # define PLAT_nanomips_linux 1
-+#elif defined(__linux__) && defined(__loongarch__) && (__loongarch_grlen == 64)
-+# define PLAT_loongarch64_linux 1
- #elif defined(__sun__) && defined(__i386__)
- # define PLAT_x86_solaris 1
- #elif defined(__sun__) && defined(__x86_64__)
-@@ -146,6 +149,21 @@
- # define XCHG_M_R_with_redundant_LOCK(_addr,_lval) \
- XCHG_M_R(_addr,_lval)
-
-+#elif defined(PLAT_loongarch64_linux)
-+# define XCHG_M_R(_addr,_lval) \
-+ __asm__ __volatile__( \
-+ "move $t0, %2 \n\t" \
-+ "ll.w $t1, %1 \n\t" \
-+ "sc.w $t0, %1 \n\t" \
-+ "move %0, $t1 \n\t" \
-+ : /*out*/ "=r"(_lval), "+ZC"(_addr) \
-+ : /*in*/ "r"(_lval) \
-+ : "$t0", "$t1", "memory" \
-+ )
-+
-+# define XCHG_M_R_with_redundant_LOCK(_addr,_lval) \
-+ XCHG_M_R(_addr,_lval)
-+
- #else
- # error "Unsupported architecture"
-
-diff --git a/include/Makefile.am b/include/Makefile.am
-index 972d394..abfa2c9 100644
---- a/include/Makefile.am
-+++ b/include/Makefile.am
-@@ -63,6 +63,7 @@ nobase_pkginclude_HEADERS = \
- vki/vki-posixtypes-mips32-linux.h \
- vki/vki-posixtypes-mips64-linux.h \
- vki/vki-posixtypes-nanomips-linux.h \
-+ vki/vki-posixtypes-loongarch64-linux.h \
- vki/vki-amd64-linux.h \
- vki/vki-arm64-linux.h \
- vki/vki-ppc32-linux.h \
-@@ -75,6 +76,7 @@ nobase_pkginclude_HEADERS = \
- vki/vki-mips32-linux.h \
- vki/vki-mips64-linux.h \
- vki/vki-nanomips-linux.h \
-+ vki/vki-loongarch64-linux.h \
- vki/vki-scnums-amd64-linux.h \
- vki/vki-scnums-arm64-linux.h \
- vki/vki-scnums-ppc32-linux.h \
-@@ -86,6 +88,7 @@ nobase_pkginclude_HEADERS = \
- vki/vki-scnums-mips32-linux.h \
- vki/vki-scnums-mips64-linux.h \
- vki/vki-scnums-nanomips-linux.h \
-+ vki/vki-scnums-loongarch64-linux.h \
- vki/vki-scnums-darwin.h \
- vki/vki-scnums-solaris.h \
- vki/vki-scnums-shared-linux.h \
-diff --git a/include/Makefile.in b/include/Makefile.in
-index e292939..0653f8f 100644
---- a/include/Makefile.in
-+++ b/include/Makefile.in
-@@ -449,6 +449,7 @@ nobase_pkginclude_HEADERS = \
- vki/vki-posixtypes-mips32-linux.h \
- vki/vki-posixtypes-mips64-linux.h \
- vki/vki-posixtypes-nanomips-linux.h \
-+ vki/vki-posixtypes-loongarch64-linux.h \
- vki/vki-amd64-linux.h \
- vki/vki-arm64-linux.h \
- vki/vki-ppc32-linux.h \
-@@ -461,6 +462,7 @@ nobase_pkginclude_HEADERS = \
- vki/vki-mips32-linux.h \
- vki/vki-mips64-linux.h \
- vki/vki-nanomips-linux.h \
-+ vki/vki-loongarch64-linux.h \
- vki/vki-scnums-amd64-linux.h \
- vki/vki-scnums-arm64-linux.h \
- vki/vki-scnums-ppc32-linux.h \
-@@ -472,6 +474,7 @@ nobase_pkginclude_HEADERS = \
- vki/vki-scnums-mips32-linux.h \
- vki/vki-scnums-mips64-linux.h \
- vki/vki-scnums-nanomips-linux.h \
-+ vki/vki-scnums-loongarch64-linux.h \
- vki/vki-scnums-darwin.h \
- vki/vki-scnums-solaris.h \
- vki/vki-scnums-shared-linux.h \
-diff --git a/include/pub_tool_basics.h b/include/pub_tool_basics.h
-index bf5a5ba..da90ea7 100644
---- a/include/pub_tool_basics.h
-+++ b/include/pub_tool_basics.h
-@@ -437,7 +437,8 @@ static inline Bool sr_EQ ( UInt sysno, SysRes sr1, SysRes sr2 ) {
-
- #if defined(VGA_x86) || defined(VGA_amd64) || defined (VGA_arm) \
- || ((defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips)) \
-- && defined (_MIPSEL)) || defined(VGA_arm64) || defined(VGA_ppc64le)
-+ && defined (_MIPSEL)) || defined(VGA_arm64) || defined(VGA_ppc64le) \
-+ || defined (VGA_loongarch64)
- # define VG_LITTLEENDIAN 1
- #elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_s390x) \
- || ((defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips)) \
-@@ -485,7 +486,8 @@ static inline Bool sr_EQ ( UInt sysno, SysRes sr1, SysRes sr2 ) {
- || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
- || defined(VGA_arm) || defined(VGA_s390x) \
- || defined(VGA_mips32) || defined(VGA_mips64) \
-- || defined(VGA_arm64) || defined(VGA_nanomips)
-+ || defined(VGA_arm64) || defined(VGA_nanomips) \
-+ || defined(VGA_loongarch64)
- # define VG_REGPARM(n) /* */
- #else
- # error Unknown arch
-diff --git a/include/pub_tool_guest.h b/include/pub_tool_guest.h
-index 08a72ef..87e8cc2 100644
---- a/include/pub_tool_guest.h
-+++ b/include/pub_tool_guest.h
-@@ -62,6 +62,9 @@
- #elif defined(VGA_mips64)
- # include "libvex_guest_mips64.h"
- typedef VexGuestMIPS64State VexGuestArchState;
-+#elif defined(VGA_loongarch64)
-+# include "libvex_guest_loongarch64.h"
-+ typedef VexGuestLOONGARCH64State VexGuestArchState;
- #else
- # error Unknown arch
- #endif
-diff --git a/include/pub_tool_libcsetjmp.h b/include/pub_tool_libcsetjmp.h
-index a3a386f..69bed7c 100644
---- a/include/pub_tool_libcsetjmp.h
-+++ b/include/pub_tool_libcsetjmp.h
-@@ -134,6 +134,14 @@ UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
- __builtin_unreachable();
- }
-
-+#elif defined(VGP_loongarch64_linux)
-+
-+#define VG_MINIMAL_JMP_BUF(_name) ULong _name [13+8+1]
-+__attribute__((returns_twice))
-+UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
-+__attribute__((noreturn))
-+void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
++#endif /* defined(VGP_loongarch64_linux) */
+
- #else
-
- /* The default implementation. */
-diff --git a/include/pub_tool_machine.h b/include/pub_tool_machine.h
-index 9bdd4f5..12377f9 100644
---- a/include/pub_tool_machine.h
-+++ b/include/pub_tool_machine.h
-@@ -108,6 +108,12 @@
- # define VG_CLREQ_SZB 20
- # define VG_STACK_REDZONE_SZB 0
++/*--------------------------------------------------------------------*/
++/*--- end syswrap-loongarch64-linux.c ---*/
++/*--------------------------------------------------------------------*/
+diff --git a/coregrind/m_syswrap/syswrap-main.c b/coregrind/m_syswrap/syswrap-main.c
+index be4ac0f..8f593ca 100644
+--- a/coregrind/m_syswrap/syswrap-main.c
++++ b/coregrind/m_syswrap/syswrap-main.c
+@@ -60,20 +60,21 @@
+ /* Useful info which needs to be recorded somewhere:
+ Use of registers in syscalls is:
-+#elif defined(VGP_loongarch64_linux)
-+# define VG_MIN_INSTR_SZB 4
-+# define VG_MAX_INSTR_SZB 8
-+# define VG_CLREQ_SZB 20
-+# define VG_STACK_REDZONE_SZB 0
-+
- #else
- # error Unknown platform
- #endif
-diff --git a/include/pub_tool_redir.h b/include/pub_tool_redir.h
-index f88d3b5..d1bb8cb 100644
---- a/include/pub_tool_redir.h
-+++ b/include/pub_tool_redir.h
-@@ -321,6 +321,8 @@
+- NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT
++ NUM ARG1 ARG2 ARG3 ARG4 ARG5 ARG6 ARG7 ARG8 RESULT
+ LINUX:
+- x86 eax ebx ecx edx esi edi ebp n/a n/a eax (== NUM)
+- amd64 rax rdi rsi rdx r10 r8 r9 n/a n/a rax (== NUM)
+- ppc32 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
+- ppc64 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
+- arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1)
+- mips32 v0 a0 a1 a2 a3 stack stack n/a n/a v0 (== NUM)
+- mips64 v0 a0 a1 a2 a3 a4 a5 a6 a7 v0 (== NUM)
+- arm64 x8 x0 x1 x2 x3 x4 x5 n/a n/a x0 ?? (== ARG1??)
++ x86 eax ebx ecx edx esi edi ebp n/a n/a eax (== NUM)
++ amd64 rax rdi rsi rdx r10 r8 r9 n/a n/a rax (== NUM)
++ ppc32 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
++ ppc64 r0 r3 r4 r5 r6 r7 r8 n/a n/a r3+CR0.SO (== ARG1)
++ arm r7 r0 r1 r2 r3 r4 r5 n/a n/a r0 (== ARG1)
++ mips32 v0 a0 a1 a2 a3 stack stack n/a n/a v0 (== NUM)
++ mips64 v0 a0 a1 a2 a3 a4 a5 a6 a7 v0 (== NUM)
++ arm64 x8 x0 x1 x2 x3 x4 x5 n/a n/a x0 ?? (== ARG1??)
++ loongarch64 r11 r4 r5 r6 r7 r8 r9 n/a n/a r4 (== ARG1)
- #define VG_U_LD_LINUX_MIPSN8_S0_1 "ld-linux-mipsn8.so.1"
+ FreeBSD:
+- x86 eax +4 +8 +12 +16 +20 +24 +28 +32 edx:eax, eflags.c
+- amd64 rax rdi rsi rdx rcx r8 r9 +8 +16 rdx:rax, rflags.c
++ x86 eax +4 +8 +12 +16 +20 +24 +28 +32 edx:eax, eflags.c
++ amd64 rax rdi rsi rdx rcx r8 r9 +8 +16 rdx:rax, rflags.c
-+#define VG_U_LD_LINUX_LOONGARCH_LP64D_SO_1 "ld-linux-loongarch-lp64d.so.1"
+ On s390x the svc instruction is used for system calls. The system call
+ number is encoded in the instruction (8 bit immediate field). Since Linux
+@@ -737,6 +738,17 @@ void getSyscallArgsFromGuestState ( /*OUT*/SyscallArgs* canonical,
+ canonical->arg6 = gst->guest_r9; // a5
+ canonical->arg7 = gst->guest_r10; // a6
+ canonical->arg8 = gst->guest_r11; // a7
+
- #endif
-
- /* --- Sonames for FreeBSD ELF linkers, plus unencoded versions. --- */
-diff --git a/include/pub_tool_vkiscnums_asm.h b/include/pub_tool_vkiscnums_asm.h
-index 14b483c..b2222aa 100644
---- a/include/pub_tool_vkiscnums_asm.h
-+++ b/include/pub_tool_vkiscnums_asm.h
-@@ -74,6 +74,10 @@
- # include "vki/vki-scnums-shared-linux.h"
- # include "vki/vki-scnums-mips64-linux.h"
-
+#elif defined(VGP_loongarch64_linux)
-+# include "vki/vki-scnums-shared-linux.h"
-+# include "vki/vki-scnums-loongarch64-linux.h"
++ VexGuestLOONGARCH64State* gst = (VexGuestLOONGARCH64State*)gst_vanilla;
++ canonical->sysno = gst->guest_R11; // a7
++ canonical->arg1 = gst->guest_R4; // a0
++ canonical->arg2 = gst->guest_R5; // a1
++ canonical->arg3 = gst->guest_R6; // a2
++ canonical->arg4 = gst->guest_R7; // a3
++ canonical->arg5 = gst->guest_R8; // a4
++ canonical->arg6 = gst->guest_R9; // a5
+
- #elif defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd)
- # include "vki/vki-scnums-freebsd.h"
+ #elif defined(VGP_x86_darwin)
+ VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
+ UWord *stack = (UWord *)gst->guest_ESP;
+@@ -1192,6 +1204,16 @@ void putSyscallArgsIntoGuestState ( /*IN*/ SyscallArgs* canonical,
+ gst->guest_r10 = canonical->arg7;
+ gst->guest_r11 = canonical->arg8;
-diff --git a/include/valgrind.h b/include/valgrind.h
-index bd63d55..ce89195 100644
---- a/include/valgrind.h
-+++ b/include/valgrind.h
-@@ -125,6 +125,7 @@
- #undef PLAT_mips32_linux
- #undef PLAT_mips64_linux
- #undef PLAT_nanomips_linux
-+#undef PLAT_loongarch64_linux
- #undef PLAT_x86_solaris
- #undef PLAT_amd64_solaris
++#elif defined(VGP_loongarch64_linux)
++ VexGuestLOONGARCH64State* gst = (VexGuestLOONGARCH64State*)gst_vanilla;
++ gst->guest_R11 = canonical->sysno;
++ gst->guest_R4 = canonical->arg1;
++ gst->guest_R5 = canonical->arg2;
++ gst->guest_R6 = canonical->arg3;
++ gst->guest_R7 = canonical->arg4;
++ gst->guest_R8 = canonical->arg5;
++ gst->guest_R9 = canonical->arg6;
++
+ #elif defined(VGP_x86_solaris)
+ VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
+ UWord *stack = (UWord *)gst->guest_ESP;
+@@ -1307,6 +1329,12 @@ void getSyscallStatusFromGuestState ( /*OUT*/SyscallStatus* canonical,
+ canonical->sres = VG_(mk_SysRes_nanomips_linux)(a0);
+ canonical->what = SsComplete;
-@@ -169,6 +170,8 @@
- # define PLAT_mips32_linux 1
- #elif defined(__linux__) && defined(__nanomips__)
- # define PLAT_nanomips_linux 1
-+#elif defined(__linux__) && defined(__loongarch__) && (__loongarch_grlen == 64)
-+# define PLAT_loongarch64_linux 1
- #elif defined(__sun) && defined(__i386__)
- # define PLAT_x86_solaris 1
- #elif defined(__sun) && defined(__x86_64__)
-@@ -1125,7 +1128,75 @@ typedef
- ); \
- } while (0)
++# elif defined(VGP_loongarch64_linux)
++ VexGuestLOONGARCH64State* gst = (VexGuestLOONGARCH64State*)gst_vanilla;
++ ULong a0 = gst->guest_R4; // a0
++ canonical->sres = VG_(mk_SysRes_loongarch64_linux)(a0);
++ canonical->what = SsComplete;
++
+ # elif defined(VGP_amd64_freebsd)
+ /* duplicates logic in m_signals.VG_UCONTEXT_SYSCALL_SYSRES */
+ VexGuestAMD64State* gst = (VexGuestAMD64State*)gst_vanilla;
+@@ -1702,6 +1730,20 @@ void putSyscallStatusIntoGuestState ( /*IN*/ ThreadId tid,
+ VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
+ OFFSET_mips32_r4, sizeof(UWord) );
--#endif
-+#endif /* PLAT_nanomips_linux */
++# elif defined(VGP_loongarch64_linux)
++ VexGuestLOONGARCH64State* gst = (VexGuestLOONGARCH64State*)gst_vanilla;
++ vg_assert(canonical->what == SsComplete);
++ if (sr_isError(canonical->sres)) {
++ /* This isn't exactly right, in that really a Failure with res
++ not in the range 1 .. 4095 is unrepresentable in the
++ Linux-loongarch64 scheme. Oh well. */
++ gst->guest_R4 = - (Long)sr_Err(canonical->sres);
++ } else {
++ gst->guest_R4 = sr_Res(canonical->sres);
++ }
++ VG_TRACK( post_reg_write, Vg_CoreSysCall, tid,
++ OFFSET_loongarch64_R4, sizeof(UWord) );
+
-+/* --------------------- loongarch64-linux --------------------- */
-+#if defined(PLAT_loongarch64_linux)
+ # elif defined(VGP_x86_solaris)
+ VexGuestX86State* gst = (VexGuestX86State*)gst_vanilla;
+ SysRes sres = canonical->sres;
+@@ -1916,7 +1958,16 @@ void getSyscallArgLayout ( /*OUT*/SyscallArgLayout* layout )
+ layout->s_arg6 = sizeof(UWord) * 6;
+ layout->s_arg7 = sizeof(UWord) * 7;
+ layout->s_arg8 = sizeof(UWord) * 8;
+-
+
-+typedef
-+ struct {
-+ unsigned long nraddr; /* where's the code? */
-+ }
-+ OrigFn;
++#elif defined(VGP_loongarch64_linux)
++ layout->o_sysno = OFFSET_loongarch64_R11;
++ layout->o_arg1 = OFFSET_loongarch64_R4;
++ layout->o_arg2 = OFFSET_loongarch64_R5;
++ layout->o_arg3 = OFFSET_loongarch64_R6;
++ layout->o_arg4 = OFFSET_loongarch64_R7;
++ layout->o_arg5 = OFFSET_loongarch64_R8;
++ layout->o_arg6 = OFFSET_loongarch64_R9;
+
-+#define __SPECIAL_INSTRUCTION_PREAMBLE \
-+ "srli.d $zero, $zero, 3 \n\t" \
-+ "srli.d $zero, $zero, 13 \n\t" \
-+ "srli.d $zero, $zero, 29 \n\t" \
-+ "srli.d $zero, $zero, 19 \n\t"
+ #elif defined(VGP_amd64_darwin)
+ layout->o_sysno = OFFSET_amd64_RAX;
+ layout->o_arg1 = OFFSET_amd64_RDI;
+@@ -3038,6 +3089,25 @@ void ML_(fixup_guest_state_to_restart_syscall) ( ThreadArchState* arch )
+ arch->vex.guest_PC -= 2;
+ }
+ }
+
-+#define VALGRIND_DO_CLIENT_REQUEST_EXPR( \
-+ _zzq_default, _zzq_request, \
-+ _zzq_arg1, _zzq_arg2, _zzq_arg3, _zzq_arg4, _zzq_arg5) \
-+ __extension__ \
-+ ({ \
-+ volatile unsigned long int _zzq_args[6]; \
-+ volatile unsigned long int _zzq_result; \
-+ _zzq_args[0] = (unsigned long int)(_zzq_request); \
-+ _zzq_args[1] = (unsigned long int)(_zzq_arg1); \
-+ _zzq_args[2] = (unsigned long int)(_zzq_arg2); \
-+ _zzq_args[3] = (unsigned long int)(_zzq_arg3); \
-+ _zzq_args[4] = (unsigned long int)(_zzq_arg4); \
-+ _zzq_args[5] = (unsigned long int)(_zzq_arg5); \
-+ __asm__ volatile("move $a7, %1 \n\t" /*default*/ \
-+ "move $t0, %2 \n\t" /*ptr*/ \
-+ __SPECIAL_INSTRUCTION_PREAMBLE \
-+ /* $a7 = client_request ( $t0 ) */ \
-+ "or $t1, $t1, $t1 \n\t" \
-+ "move %0, $a7 \n\t" /*result*/ \
-+ : "=r" (_zzq_result) \
-+ : "r" (_zzq_default), "r" (&_zzq_args[0]) \
-+ : "$a7", "$t0", "memory"); \
-+ _zzq_result; \
-+ })
++#elif defined(VGP_loongarch64_linux)
++ arch->vex.guest_PC -= 4; // sizeof(loongarch instr)
+
-+#define VALGRIND_GET_NR_CONTEXT(_zzq_rlval) \
-+ { \
-+ volatile OrigFn* _zzq_orig = &(_zzq_rlval); \
-+ volatile unsigned long int __addr; \
-+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
-+ /* $a7 = guest_NRADDR */ \
-+ "or $t2, $t2, $t2 \n\t" \
-+ "move %0, $a7 \n\t" /*result*/ \
-+ : "=r" (__addr) \
-+ : \
-+ : "$a7"); \
-+ _zzq_orig->nraddr = __addr; \
-+ }
++ /* Make sure our caller is actually sane, and we're really backing
++ back over a syscall.
+
-+#define VALGRIND_CALL_NOREDIR_T8 \
-+ __SPECIAL_INSTRUCTION_PREAMBLE \
-+ /* call-noredir $t8 */ \
-+ "or $t3, $t3, $t3 \n\t"
++ syscall 0 == 00 2B 00 00
++ */
++ {
++ UChar *p = (UChar *)(Addr)(arch->vex.guest_PC);
++ if (p[0] != 0x00 || p[1] != 0x00 || p[2] != 0x2B || p[3] != 0x00)
++ VG_(message)(Vg_DebugMsg,
++ "?! restarting over syscall at %#llx %02x %02x %02x %02x\n",
++ (ULong)arch->vex.guest_PC, p[0], p[1], p[2], p[3]);
+
-+#define VALGRIND_VEX_INJECT_IR() \
-+ do { \
-+ __asm__ volatile(__SPECIAL_INSTRUCTION_PREAMBLE \
-+ "or $t4, $t4, $t4 \n\t" \
-+ ); \
-+ } while (0)
++ vg_assert(p[0] == 0x00 && p[1] == 0x00 && p[2] == 0x2B && p[3] == 0x00);
++ }
+
-+#endif /* PLAT_loongarch64_linux */
- /* Insert assembly code for other platforms here... */
-
- #endif /* NVALGRIND */
-@@ -6603,6 +6674,457 @@ typedef
+ #elif defined(VGP_x86_solaris)
+ arch->vex.guest_EIP -= 2; // sizeof(int $0x91) or sizeof(syscall)
- #endif /* PLAT_mips64_linux */
+diff --git a/coregrind/m_trampoline.S b/coregrind/m_trampoline.S
+index e897963..252719b 100644
+--- a/coregrind/m_trampoline.S
++++ b/coregrind/m_trampoline.S
+@@ -1585,6 +1585,53 @@ VG_(trampoline_stuff_end):
+ # undef UD2_1024
+ # undef UD2_PAGE
-+/* --------------------- loongarch64-linux --------------------- */
-+
-+#if defined(PLAT_loongarch64_linux)
-+
-+/* These regs are trashed by the hidden call. */
-+#define __CALLER_SAVED_REGS \
-+ "$ra", "$a0", "$a1", "$a2", "$a3", "$a4", "$a5", "$a6", "$a7", \
-+ "$t0", "$t1", "$t2", "$t3", "$t4", "$t5", "$t6", "$t7", "$t8", \
-+ "$f0", "$f1", "$f2", "$f3", "$f4", "$f5", "$f6", "$f7", \
-+ "$f8", "$f9", "$f10", "$f11", "$f12", "$f13", "$f14", "$f15", \
-+ "$f16", "$f17", "$f18", "$f19", "$f20", "$f21", "$f22", "$f23"
-+
-+/* $s0 is callee-saved, so we can use it to save and restore SP around
-+ the hidden call. */
-+#define VALGRIND_ALIGN_STACK \
-+ "move $s0, $sp \n\t" \
-+ "bstrins.d $sp, $zero, 3, 0 \n\t"
-+#define VALGRIND_RESTORE_STACK \
-+ "move $sp, $s0 \n\t"
++/*------------------- loongarch64-linux -------------------*/
++#else
++#if defined(VGP_loongarch64_linux)
+
-+/* These CALL_FN_ macros assume that on loongarch64-linux,
-+ sizeof(unsigned long) == 8. */
++.global VG_(trampoline_stuff_start)
++VG_(trampoline_stuff_start):
+
-+#define CALL_FN_W_v(lval, orig) \
-+ do { \
-+ volatile OrigFn _orig = (orig); \
-+ volatile unsigned long _argvec[1]; \
-+ volatile unsigned long _res; \
-+ _argvec[0] = (unsigned long)_orig.nraddr; \
-+ __asm__ volatile( \
-+ VALGRIND_ALIGN_STACK \
-+ "ld.d $t8, %1, 0 \n\t" /* target->t8 */ \
-+ VALGRIND_CALL_NOREDIR_T8 \
-+ VALGRIND_RESTORE_STACK \
-+ "move %0, $a0 \n\t" \
-+ : /*out*/ "=r" (_res) \
-+ : /*in*/ "r" (&_argvec[0]) \
-+ : /*trash*/ "memory", __CALLER_SAVED_REGS, "$s0" \
-+ ); \
-+ lval = (__typeof__(lval)) _res; \
-+ } while (0)
++.global VG_(loongarch64_linux_SUBST_FOR_rt_sigreturn)
++VG_(loongarch64_linux_SUBST_FOR_rt_sigreturn):
++ li.w $a7, __NR_rt_sigreturn
++ syscall 0
++ .long 0 /*illegal insn*/
+
-+#define CALL_FN_W_W(lval, orig, arg1) \
-+ do { \
-+ volatile OrigFn _orig = (orig); \
-+ volatile unsigned long _argvec[2]; \
-+ volatile unsigned long _res; \
-+ _argvec[0] = (unsigned long)_orig.nraddr; \
-+ _argvec[1] = (unsigned long)(arg1); \
-+ __asm__ volatile( \
-+ VALGRIND_ALIGN_STACK \
-+ "ld.d $a0, %1, 8 \n\t" /* arg1 */ \
-+ "ld.d $t8, %1, 0 \n\t" /* target->t8 */ \
-+ VALGRIND_CALL_NOREDIR_T8 \
-+ VALGRIND_RESTORE_STACK \
-+ "move %0, $a0 \n\t" \
-+ : /*out*/ "=r" (_res) \
-+ : /*in*/ "r" (&_argvec[0]) \
-+ : /*trash*/ "memory", __CALLER_SAVED_REGS, "$s0" \
-+ ); \
-+ lval = (__typeof__(lval)) _res; \
-+ } while (0)
++/* There's no particular reason that this needs to be handwritten
++ assembly, but since that's what this file contains, here's a
++ simple strlen() and strchr() implementations.
++*/
+
-+#define CALL_FN_W_WW(lval, orig, arg1, arg2) \
-+ do { \
-+ volatile OrigFn _orig = (orig); \
-+ volatile unsigned long _argvec[3]; \
-+ volatile unsigned long _res; \
-+ _argvec[0] = (unsigned long)_orig.nraddr; \
-+ _argvec[1] = (unsigned long)(arg1); \
-+ _argvec[2] = (unsigned long)(arg2); \
-+ __asm__ volatile( \
-+ VALGRIND_ALIGN_STACK \
-+ "ld.d $a0, %1, 8 \n\t" /* arg1 */ \
-+ "ld.d $a1, %1, 16 \n\t" /* arg2 */ \
-+ "ld.d $t8, %1, 0 \n\t" /* target->t8 */ \
-+ VALGRIND_CALL_NOREDIR_T8 \
-+ VALGRIND_RESTORE_STACK \
-+ "move %0, $a0 \n\t" \
-+ : /*out*/ "=r" (_res) \
-+ : /*in*/ "r" (&_argvec[0]) \
-+ : /*trash*/ "memory", __CALLER_SAVED_REGS, "$s0" \
-+ ); \
-+ lval = (__typeof__(lval)) _res; \
-+ } while (0)
++.global VG_(loongarch64_linux_REDIR_FOR_strlen)
++.type VG_(loongarch64_linux_REDIR_FOR_strlen), @function
++VG_(loongarch64_linux_REDIR_FOR_strlen):
++ move $t0, $a0
++ strlen_loop:
++ ld.bu $t1, $a0, 0
++ addi.d $a0, $a0, 1
++ bne $t1, $zero, strlen_loop
++ sub.d $a0, $a0, $t0
++ addi.d $a0, $a0, -1
++ jr $ra
++.size VG_(loongarch64_linux_REDIR_FOR_strlen), .-VG_(loongarch64_linux_REDIR_FOR_strlen)
+
-+#define CALL_FN_W_WWW(lval, orig, arg1, arg2, arg3) \
-+ do { \
-+ volatile OrigFn _orig = (orig); \
-+ volatile unsigned long _argvec[4]; \
-+ volatile unsigned long _res; \
-+ _argvec[0] = (unsigned long)_orig.nraddr; \
-+ _argvec[1] = (unsigned long)(arg1); \
-+ _argvec[2] = (unsigned long)(arg2); \
-+ _argvec[3] = (unsigned long)(arg3); \
-+ __asm__ volatile( \
-+ VALGRIND_ALIGN_STACK \
-+ "ld.d $a0, %1, 8 \n\t" /* arg1 */ \
-+ "ld.d $a1, %1, 16 \n\t" /* arg2 */ \
-+ "ld.d $a2, %1, 24 \n\t" /* arg3 */ \
-+ "ld.d $t8, %1, 0 \n\t" /* target->t8 */ \
-+ VALGRIND_CALL_NOREDIR_T8 \
-+ VALGRIND_RESTORE_STACK \
-+ "move %0, $a0 \n\t" \
-+ : /*out*/ "=r" (_res) \
-+ : /*in*/ "r" (&_argvec[0]) \
-+ : /*trash*/ "memory", __CALLER_SAVED_REGS, "$s0" \
-+ ); \
-+ lval = (__typeof__(lval)) _res; \
-+ } while (0)
++.global VG_(loongarch64_linux_REDIR_FOR_strchr)
++.type VG_(loongarch64_linux_REDIR_FOR_strchr), @function
++VG_(loongarch64_linux_REDIR_FOR_strchr):
++ strchr_loop:
++ ld.bu $t0, $a0, 0
++ beq $t0, $a1, strchr_end
++ addi.d $a0, $a0, 1
++ bne $t0, $zero, strchr_loop
++ move $a0, $zero
++ strchr_end:
++ jr $ra
++.size VG_(loongarch64_linux_REDIR_FOR_strchr), .-VG_(loongarch64_linux_REDIR_FOR_strchr)
+
-+#define CALL_FN_W_WWWW(lval, orig, arg1, arg2, arg3, arg4) \
-+ do { \
-+ volatile OrigFn _orig = (orig); \
-+ volatile unsigned long _argvec[5]; \
-+ volatile unsigned long _res; \
-+ _argvec[0] = (unsigned long)_orig.nraddr; \
-+ _argvec[1] = (unsigned long)(arg1); \
-+ _argvec[2] = (unsigned long)(arg2); \
-+ _argvec[3] = (unsigned long)(arg3); \
-+ _argvec[4] = (unsigned long)(arg4); \
-+ __asm__ volatile( \
-+ VALGRIND_ALIGN_STACK \
-+ "ld.d $a0, %1, 8 \n\t" /* arg1 */ \
-+ "ld.d $a1, %1, 16 \n\t" /* arg2 */ \
-+ "ld.d $a2, %1, 24 \n\t" /* arg3 */ \
-+ "ld.d $a3, %1, 32 \n\t" /* arg4 */ \
-+ "ld.d $t8, %1, 0 \n\t" /* target->t8 */ \
-+ VALGRIND_CALL_NOREDIR_T8 \
-+ VALGRIND_RESTORE_STACK \
-+ "move %0, $a0 \n\t" \
-+ : /*out*/ "=r" (_res) \
-+ : /*in*/ "r" (&_argvec[0]) \
-+ : /*trash*/ "memory", __CALLER_SAVED_REGS, "$s0" \
-+ ); \
-+ lval = (__typeof__(lval)) _res; \
-+ } while (0)
++.global VG_(trampoline_stuff_end)
++VG_(trampoline_stuff_end):
+
-+#define CALL_FN_W_5W(lval, orig, arg1, arg2, arg3, arg4, arg5) \
-+ do { \
-+ volatile OrigFn _orig = (orig); \
-+ volatile unsigned long _argvec[6]; \
-+ volatile unsigned long _res; \
-+ _argvec[0] = (unsigned long)_orig.nraddr; \
-+ _argvec[1] = (unsigned long)(arg1); \
-+ _argvec[2] = (unsigned long)(arg2); \
-+ _argvec[3] = (unsigned long)(arg3); \
-+ _argvec[4] = (unsigned long)(arg4); \
-+ _argvec[5] = (unsigned long)(arg5); \
-+ __asm__ volatile( \
-+ VALGRIND_ALIGN_STACK \
-+ "ld.d $a0, %1, 8 \n\t" /* arg1 */ \
-+ "ld.d $a1, %1, 16 \n\t" /* arg2 */ \
-+ "ld.d $a2, %1, 24 \n\t" /* arg3 */ \
-+ "ld.d $a3, %1, 32 \n\t" /* arg4 */ \
-+ "ld.d $a4, %1, 40 \n\t" /* arg5 */ \
-+ "ld.d $t8, %1, 0 \n\t" /* target->t8 */ \
-+ VALGRIND_CALL_NOREDIR_T8 \
-+ VALGRIND_RESTORE_STACK \
-+ "move %0, $a0 \n\t" \
-+ : /*out*/ "=r" (_res) \
-+ : /*in*/ "r" (&_argvec[0]) \
-+ : /*trash*/ "memory", __CALLER_SAVED_REGS, "$s0" \
-+ ); \
-+ lval = (__typeof__(lval)) _res; \
-+ } while (0)
+ /*---------------- x86-solaris ----------------*/
+ #else
+ #if defined(VGP_x86_solaris)
+@@ -1785,6 +1832,7 @@ VG_(trampoline_stuff_end):
+ #endif
+ #endif
+ #endif
++#endif
+
+ /* Let the linker know we don't need an executable stack */
+ MARK_STACK_NO_EXEC
+diff --git a/coregrind/m_translate.c b/coregrind/m_translate.c
+index 5696dc4..0044cc6 100644
+--- a/coregrind/m_translate.c
++++ b/coregrind/m_translate.c
+@@ -1750,6 +1750,11 @@ Bool VG_(translate) ( ThreadId tid,
+ vex_archinfo.arm64_requires_fallback_LLSC;
+ # endif
+
++# if defined(VGP_loongarch64_linux)
++ /* For now, we only use fallback LLSC */
++ vex_abiinfo.guest__use_fallback_LLSC = True;
++# endif
+
-+#define CALL_FN_W_6W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
-+ arg6) \
-+ do { \
-+ volatile OrigFn _orig = (orig); \
-+ volatile unsigned long _argvec[7]; \
-+ volatile unsigned long _res; \
-+ _argvec[0] = (unsigned long)_orig.nraddr; \
-+ _argvec[1] = (unsigned long)(arg1); \
-+ _argvec[2] = (unsigned long)(arg2); \
-+ _argvec[3] = (unsigned long)(arg3); \
-+ _argvec[4] = (unsigned long)(arg4); \
-+ _argvec[5] = (unsigned long)(arg5); \
-+ _argvec[6] = (unsigned long)(arg6); \
-+ __asm__ volatile( \
-+ VALGRIND_ALIGN_STACK \
-+ "ld.d $a0, %1, 8 \n\t" /* arg1 */ \
-+ "ld.d $a1, %1, 16 \n\t" /* arg2 */ \
-+ "ld.d $a2, %1, 24 \n\t" /* arg3 */ \
-+ "ld.d $a3, %1, 32 \n\t" /* arg4 */ \
-+ "ld.d $a4, %1, 40 \n\t" /* arg5 */ \
-+ "ld.d $a5, %1, 48 \n\t" /* arg6 */ \
-+ "ld.d $t8, %1, 0 \n\t" /* target->t8 */ \
-+ VALGRIND_CALL_NOREDIR_T8 \
-+ VALGRIND_RESTORE_STACK \
-+ "move %0, $a0 \n\t" \
-+ : /*out*/ "=r" (_res) \
-+ : /*in*/ "r" (&_argvec[0]) \
-+ : /*trash*/ "memory", __CALLER_SAVED_REGS, "$s0" \
-+ ); \
-+ lval = (__typeof__(lval)) _res; \
-+ } while (0)
+ /* Set up closure args. */
+ closure.tid = tid;
+ closure.nraddr = nraddr;
+diff --git a/coregrind/m_vki.c b/coregrind/m_vki.c
+index 0cc1882..11c5fe3 100644
+--- a/coregrind/m_vki.c
++++ b/coregrind/m_vki.c
+@@ -37,13 +37,13 @@
+ describing the kernel interface, so this file is nearly empty. */
+
+
+-/* ppc32/64, arm64 and mips32/64 (linux) determine page size at startup,
+- hence m_vki is the logical place to store that info. */
++/* ppc32/64, arm64, mips32/64 and loongarch64 (linux) determine page size
++ at startup, hence m_vki is the logical place to store that info. */
+
+ #if defined(VGP_ppc32_linux) || defined(VGP_ppc64be_linux) \
+ || defined(VGP_ppc64le_linux) || defined(VGP_arm64_linux) \
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
+- || defined(VGP_nanomips_linux)
++ || defined(VGP_nanomips_linux) || defined(VGP_loongarch64_linux)
+ unsigned long VKI_PAGE_SHIFT = 12;
+ unsigned long VKI_PAGE_SIZE = 1UL << 12;
+ #endif
+diff --git a/coregrind/pub_core_aspacemgr.h b/coregrind/pub_core_aspacemgr.h
+index b867108..a2b41f3 100644
+--- a/coregrind/pub_core_aspacemgr.h
++++ b/coregrind/pub_core_aspacemgr.h
+@@ -335,7 +335,8 @@ extern Bool VG_(am_relocate_nooverlap_client)( /*OUT*/Bool* need_discard,
+ #if defined(VGP_ppc32_linux) \
+ || defined(VGP_ppc64be_linux) || defined(VGP_ppc64le_linux) \
+ || defined(VGP_mips32_linux) || defined(VGP_mips64_linux) \
+- || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux)
++ || defined(VGP_arm64_linux) || defined(VGP_nanomips_linux) \
++ || defined(VGP_loongarch64_linux)
+ # define VG_STACK_GUARD_SZB 65536 // 1 or 16 pages
+ #else
+ # define VG_STACK_GUARD_SZB 8192 // 2 pages
+diff --git a/coregrind/pub_core_basics.h b/coregrind/pub_core_basics.h
+index abc5a06..1325451 100644
+--- a/coregrind/pub_core_basics.h
++++ b/coregrind/pub_core_basics.h
+@@ -55,8 +55,8 @@
+
+ typedef
+ struct {
+- ULong r_pc; /* x86:EIP, amd64:RIP, ppc:CIA, arm:R15, mips:pc */
+- ULong r_sp; /* x86:ESP, amd64:RSP, ppc:R1, arm:R13, mips:sp */
++ ULong r_pc; /* x86:EIP, amd64:RIP, ppc:CIA, arm:R15, mips:pc, loongarch64:pc */
++ ULong r_sp; /* x86:ESP, amd64:RSP, ppc:R1, arm:R13, mips:sp, loongarch64:sp */
+ union {
+ struct {
+ UInt r_ebp;
+@@ -102,6 +102,10 @@ typedef
+ ULong r31; /* Return address of the last subroutine call */
+ ULong r28;
+ } MIPS64;
++ struct {
++ ULong r_fp; /* Stack frame pointer or static variable */
++ ULong r_ra; /* Return address of the last subroutine call */
++ } LOONGARCH64;
+ } misc;
+ }
+ UnwindStartRegs;
+diff --git a/coregrind/pub_core_debuginfo.h b/coregrind/pub_core_debuginfo.h
+index 4d6ebda..115afff 100644
+--- a/coregrind/pub_core_debuginfo.h
++++ b/coregrind/pub_core_debuginfo.h
+@@ -137,6 +137,10 @@ typedef
+ typedef
+ struct { Addr pc; Addr sp; Addr fp; Addr ra; }
+ D3UnwindRegs;
++#elif defined(VGA_loongarch64)
++typedef
++ struct { Addr pc; Addr ra; Addr sp; Addr fp; }
++ D3UnwindRegs;
+ #else
+ # error "Unsupported arch"
+ #endif
+diff --git a/coregrind/pub_core_machine.h b/coregrind/pub_core_machine.h
+index a1afbe6..de00e09 100644
+--- a/coregrind/pub_core_machine.h
++++ b/coregrind/pub_core_machine.h
+@@ -126,6 +126,11 @@
+ # define VG_ELF_MACHINE EM_NANOMIPS
+ # define VG_ELF_CLASS ELFCLASS32
+ # undef VG_PLAT_USES_PPCTOC
++#elif defined(VGP_loongarch64_linux)
++# define VG_ELF_DATA2XXX ELFDATA2LSB
++# define VG_ELF_MACHINE EM_LOONGARCH
++# define VG_ELF_CLASS ELFCLASS64
++# undef VG_PLAT_USES_PPCTOC
+ #else
+ # error Unknown platform
+ #endif
+@@ -163,6 +168,10 @@
+ # define VG_INSTR_PTR guest_PC
+ # define VG_STACK_PTR guest_r29
+ # define VG_FRAME_PTR guest_r30
++#elif defined(VGA_loongarch64)
++# define VG_INSTR_PTR guest_PC
++# define VG_STACK_PTR guest_R3
++# define VG_FRAME_PTR guest_R22
+ #else
+ # error Unknown arch
+ #endif
+@@ -234,6 +243,10 @@ void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs,
+ s390x: initially: call VG_(machine_get_hwcaps)
+
+ then safe to use VG_(machine_get_VexArchInfo)
++ -------------
++ loongarch64: initially: call VG_(machine_get_hwcaps)
+
-+#define CALL_FN_W_7W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
-+ arg6, arg7) \
-+ do { \
-+ volatile OrigFn _orig = (orig); \
-+ volatile unsigned long _argvec[8]; \
-+ volatile unsigned long _res; \
-+ _argvec[0] = (unsigned long)_orig.nraddr; \
-+ _argvec[1] = (unsigned long)(arg1); \
-+ _argvec[2] = (unsigned long)(arg2); \
-+ _argvec[3] = (unsigned long)(arg3); \
-+ _argvec[4] = (unsigned long)(arg4); \
-+ _argvec[5] = (unsigned long)(arg5); \
-+ _argvec[6] = (unsigned long)(arg6); \
-+ _argvec[7] = (unsigned long)(arg7); \
-+ __asm__ volatile( \
-+ VALGRIND_ALIGN_STACK \
-+ "ld.d $a0, %1, 8 \n\t" /* arg1 */ \
-+ "ld.d $a1, %1, 16 \n\t" /* arg2 */ \
-+ "ld.d $a2, %1, 24 \n\t" /* arg3 */ \
-+ "ld.d $a3, %1, 32 \n\t" /* arg4 */ \
-+ "ld.d $a4, %1, 40 \n\t" /* arg5 */ \
-+ "ld.d $a5, %1, 48 \n\t" /* arg6 */ \
-+ "ld.d $a6, %1, 56 \n\t" /* arg7 */ \
-+ "ld.d $t8, %1, 0 \n\t" /* target->t8 */ \
-+ VALGRIND_CALL_NOREDIR_T8 \
-+ VALGRIND_RESTORE_STACK \
-+ "move %0, $a0 \n\t" \
-+ : /*out*/ "=r" (_res) \
-+ : /*in*/ "r" (&_argvec[0]) \
-+ : /*trash*/ "memory", __CALLER_SAVED_REGS, "$s0" \
-+ ); \
-+ lval = (__typeof__(lval)) _res; \
-+ } while (0)
++ then safe to use VG_(machine_get_VexArchInfo)
+
+ VG_(machine_get_hwcaps) may use signals (although it attempts to
+ leave signal state unchanged) and therefore should only be
+diff --git a/coregrind/pub_core_mallocfree.h b/coregrind/pub_core_mallocfree.h
+index 6f0cd29..c0bf40a 100644
+--- a/coregrind/pub_core_mallocfree.h
++++ b/coregrind/pub_core_mallocfree.h
+@@ -78,6 +78,7 @@ typedef Int ArenaId;
+ defined(VGP_ppc64le_linux) || \
+ defined(VGP_s390x_linux) || \
+ (defined(VGP_mips64_linux) && !defined(VGABI_N32)) || \
++ defined(VGP_loongarch64_linux) || \
+ defined(VGP_x86_freebsd) || \
+ defined(VGP_amd64_freebsd) || \
+ defined(VGP_arm64_freebsd) || \
+diff --git a/coregrind/pub_core_signals.h b/coregrind/pub_core_signals.h
+index ae8555b..c53323f 100644
+--- a/coregrind/pub_core_signals.h
++++ b/coregrind/pub_core_signals.h
+@@ -77,6 +77,7 @@ extern void VG_(synth_sigill) (ThreadId tid, Addr addr);
+ extern void VG_(synth_sigtrap) (ThreadId tid);
+ extern void VG_(synth_sigbus) (ThreadId tid);
+ extern void VG_(synth_sigfpe) (ThreadId tid, UInt code);
++extern void VG_(synth_sigsys) (ThreadId tid);
+
+ /* Extend the stack to cover addr, if possible */
+ extern Bool VG_(extend_stack)(ThreadId tid, Addr addr);
+diff --git a/coregrind/pub_core_syscall.h b/coregrind/pub_core_syscall.h
+index 5c42821..81bda22 100644
+--- a/coregrind/pub_core_syscall.h
++++ b/coregrind/pub_core_syscall.h
+@@ -106,6 +106,7 @@ extern SysRes VG_(mk_SysRes_mips32_linux)( UWord v0, UWord v1,
+ extern SysRes VG_(mk_SysRes_mips64_linux)( ULong v0, ULong v1,
+ ULong a3 );
+ extern SysRes VG_(mk_SysRes_nanomips_linux)( UWord a0);
++extern SysRes VG_(mk_SysRes_loongarch64_linux)( UWord a0 );
+ extern SysRes VG_(mk_SysRes_x86_solaris) ( Bool isErr, UInt val, UInt val2 );
+ extern SysRes VG_(mk_SysRes_amd64_solaris) ( Bool isErr, ULong val, ULong val2 );
+ extern SysRes VG_(mk_SysRes_Error) ( UWord val );
+diff --git a/coregrind/pub_core_trampoline.h b/coregrind/pub_core_trampoline.h
+index d0bd6b8..4490d75 100644
+--- a/coregrind/pub_core_trampoline.h
++++ b/coregrind/pub_core_trampoline.h
+@@ -176,6 +176,12 @@ extern Char* VG_(nanomips_linux_REDIR_FOR_index)( const Char*, Int );
+ extern UInt VG_(nanomips_linux_REDIR_FOR_strlen)( void* );
+ #endif
+
++#if defined(VGP_loongarch64_linux)
++extern Addr VG_(loongarch64_linux_SUBST_FOR_rt_sigreturn);
++extern UInt VG_(loongarch64_linux_REDIR_FOR_strlen)( void* );
++extern Char* VG_(loongarch64_linux_REDIR_FOR_strchr)( const Char*, Int );
++#endif
+
-+#define CALL_FN_W_8W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
-+ arg6, arg7, arg8) \
-+ do { \
-+ volatile OrigFn _orig = (orig); \
-+ volatile unsigned long _argvec[9]; \
-+ volatile unsigned long _res; \
-+ _argvec[0] = (unsigned long)_orig.nraddr; \
-+ _argvec[1] = (unsigned long)(arg1); \
-+ _argvec[2] = (unsigned long)(arg2); \
-+ _argvec[3] = (unsigned long)(arg3); \
-+ _argvec[4] = (unsigned long)(arg4); \
-+ _argvec[5] = (unsigned long)(arg5); \
-+ _argvec[6] = (unsigned long)(arg6); \
-+ _argvec[7] = (unsigned long)(arg7); \
-+ _argvec[8] = (unsigned long)(arg8); \
-+ __asm__ volatile( \
-+ VALGRIND_ALIGN_STACK \
-+ "ld.d $a0, %1, 8 \n\t" /* arg1 */ \
-+ "ld.d $a1, %1, 16 \n\t" /* arg2 */ \
-+ "ld.d $a2, %1, 24 \n\t" /* arg3 */ \
-+ "ld.d $a3, %1, 32 \n\t" /* arg4 */ \
-+ "ld.d $a4, %1, 40 \n\t" /* arg5 */ \
-+ "ld.d $a5, %1, 48 \n\t" /* arg6 */ \
-+ "ld.d $a6, %1, 56 \n\t" /* arg7 */ \
-+ "ld.d $a7, %1, 64 \n\t" /* arg8 */ \
-+ "ld.d $t8, %1, 0 \n\t" /* target->t8 */ \
-+ VALGRIND_CALL_NOREDIR_T8 \
-+ VALGRIND_RESTORE_STACK \
-+ "move %0, $a0 \n\t" \
-+ : /*out*/ "=r" (_res) \
-+ : /*in*/ "r" (&_argvec[0]) \
-+ : /*trash*/ "memory", __CALLER_SAVED_REGS, "$s0" \
-+ ); \
-+ lval = (__typeof__(lval)) _res; \
-+ } while (0)
+ #if defined(VGP_x86_solaris)
+ extern SizeT VG_(x86_solaris_REDIR_FOR_strcmp)(const HChar *, const HChar *);
+ extern SizeT VG_(x86_solaris_REDIR_FOR_strlen)(const HChar *);
+diff --git a/coregrind/pub_core_transtab.h b/coregrind/pub_core_transtab.h
+index 6cc11f6..fe93926 100644
+--- a/coregrind/pub_core_transtab.h
++++ b/coregrind/pub_core_transtab.h
+@@ -81,7 +81,8 @@ static inline UWord VG_TT_FAST_HASH ( Addr guest ) {
+ }
+
+ #elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
+- || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_arm64)
++ || defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_arm64) \
++ || defined(VGA_loongarch64)
+ static inline UWord VG_TT_FAST_HASH ( Addr guest ) {
+ // Instructions are 4-byte aligned.
+ UWord merged = ((UWord)guest) >> 2;
+diff --git a/coregrind/pub_core_transtab_asm.h b/coregrind/pub_core_transtab_asm.h
+index 8b585f1..e73c89a 100644
+--- a/coregrind/pub_core_transtab_asm.h
++++ b/coregrind/pub_core_transtab_asm.h
+@@ -83,7 +83,7 @@
+ #if defined(VGA_amd64) || defined(VGA_arm64) \
+ || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
+ || (defined(VGA_mips64) && defined(VGABI_64)) \
+- || defined(VGA_s390x)
++ || defined(VGA_s390x) || defined(VGA_loongarch64)
+ // And all other 64-bit hosts
+ # define VG_FAST_CACHE_SET_BITS 6
+ // These FCS_{g,h}{0,1,2,3} are the values of
+diff --git a/coregrind/vgdb-invoker-ptrace.c b/coregrind/vgdb-invoker-ptrace.c
+index 78a6a16..798fe5f 100644
+--- a/coregrind/vgdb-invoker-ptrace.c
++++ b/coregrind/vgdb-invoker-ptrace.c
+@@ -50,9 +50,10 @@
+ // Rather we use PTRACE_GETREGS or PTRACE_PEEKUSER.
+
+ // The only platform on which we must use PTRACE_GETREGSET is arm64.
++// We use PTRACE_GETREGSET on loongarch64 as well.
+ // The resulting vgdb cannot work in a bi-arch setup.
+ // -1 means we will check that PTRACE_GETREGSET works.
+-# if defined(VGA_arm64)
++# if defined(VGA_arm64) || defined(VGA_loongarch64)
+ #define USE_PTRACE_GETREGSET
+ # endif
+ #endif
+@@ -529,6 +530,9 @@ static struct user_regs_struct user_save;
+ # else
+ static struct user_pt_regs user_save;
+ # endif
++# elif defined(VGA_loongarch64)
++/* loongarch64 is extra special, glibc only defined user_regs_struct. */
++static struct user_regs_struct user_save;
+ # else
+ static struct user user_save;
+ # endif
+@@ -805,6 +809,9 @@ Bool invoker_invoke_gdbserver (pid_t pid)
+ # else
+ struct user_pt_regs user_mod;
+ # endif
++# elif defined(VGA_loongarch64)
++/* loongarch64 is extra special, glibc only defined user_regs_struct. */
++ struct user_regs_struct user_mod;
+ # else
+ struct user user_mod;
+ # endif
+@@ -874,6 +881,8 @@ Bool invoker_invoke_gdbserver (pid_t pid)
+ sp = p[29];
+ #elif defined(VGA_mips64)
+ sp = user_mod.regs[29];
++#elif defined(VGA_loongarch64)
++ sp = user_mod.regs[3];
+ #else
+ I_die_here : (sp) architecture missing in vgdb-invoker-ptrace.c
+ #endif
+@@ -961,6 +970,8 @@ Bool invoker_invoke_gdbserver (pid_t pid)
+
+ #elif defined(VGA_mips64)
+ assert(0); // cannot vgdb a 32 bits executable with a 64 bits exe
++#elif defined(VGA_loongarch64)
++ assert(0); // cannot vgdb a 32 bits executable with a 64 bits exe
+ #else
+ I_die_here : architecture missing in vgdb-invoker-ptrace.c
+ #endif
+@@ -1068,6 +1079,12 @@ Bool invoker_invoke_gdbserver (pid_t pid)
+ user_mod.regs[31] = bad_return;
+ user_mod.regs[34] = shared64->invoke_gdbserver;
+ user_mod.regs[25] = shared64->invoke_gdbserver;
++#elif defined(VGA_loongarch64)
++ /* put check arg in register a0 */
++ user_mod.regs[4] = check;
++ /* put NULL return address in ra */
++ user_mod.regs[1] = bad_return;
++ user_mod.csr_era = shared64->invoke_gdbserver;
+ #else
+ I_die_here: architecture missing in vgdb-invoker-ptrace.c
+ #endif
+diff --git a/drd/drd_bitmap.h b/drd/drd_bitmap.h
+index 3b71d74..1f11f23 100644
+--- a/drd/drd_bitmap.h
++++ b/drd/drd_bitmap.h
+@@ -140,7 +140,7 @@ Addr make_address(const UWord a1, const UWord a0)
+ #define BITS_PER_BITS_PER_UWORD 5
+ #elif defined(VGA_amd64) || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
+ || defined(VGA_s390x) || (defined(VGA_mips64) && !defined(VGABI_N32)) \
+- || defined(VGA_arm64)
++ || defined(VGA_arm64) || defined(VGA_loongarch64)
+ #define BITS_PER_BITS_PER_UWORD 6
+ #else
+ #error Unknown platform.
+diff --git a/drd/drd_load_store.c b/drd/drd_load_store.c
+index 80d326a..da6283b 100644
+--- a/drd/drd_load_store.c
++++ b/drd/drd_load_store.c
+@@ -53,6 +53,8 @@
+ #define STACK_POINTER_OFFSET OFFSET_mips32_r29
+ #elif defined(VGA_mips64)
+ #define STACK_POINTER_OFFSET OFFSET_mips64_r29
++#elif defined(VGA_loongarch64)
++#define STACK_POINTER_OFFSET OFFSET_loongarch64_R3
+ #else
+ #error Unknown architecture.
+ #endif
+@@ -634,6 +636,8 @@ IRSB* DRD_(instrument)(VgCallbackClosure* const closure,
+ break; /* not interesting to DRD */
+ case Imbe_CancelReservation:
+ break; /* not interesting to DRD */
++ case Imbe_InsnFence:
++ break; /* not interesting to DRD */
+ default:
+ tl_assert(0);
+ }
+diff --git a/drd/tests/pth_barrier_thr_cr.supp b/drd/tests/pth_barrier_thr_cr.supp
+index 653b2d2..34482cc 100644
+--- a/drd/tests/pth_barrier_thr_cr.supp
++++ b/drd/tests/pth_barrier_thr_cr.supp
+@@ -9,3 +9,14 @@
+ fun:pthread_barrier_wait_intercept
+ fun:pthread_barrier_wait
+ }
++{
++ number-of-concurrent-pthead_barrier_wait()-calls-exceeds-barrier-count
++ drd:BarrierErr
++ fun:pthread_barrier_wait@*
++}
++{
++ number-of-concurrent-pthead_barrier_wait()-calls-exceeds-barrier-count
++ drd:BarrierErr
++ fun:pthread_barrier_wait_intercept
++ fun:pthread_barrier_wait@*
++}
+diff --git a/gdbserver_tests/Makefile.am b/gdbserver_tests/Makefile.am
+index 6b73a24..55cbd9e 100755
+--- a/gdbserver_tests/Makefile.am
++++ b/gdbserver_tests/Makefile.am
+@@ -16,6 +16,7 @@ dist_noinst_SCRIPTS = \
+ filter_make_empty \
+ filter_helgrind_monitor \
+ filter_helgrind_monitor_solaris \
++ filter_helgrind_monitor_loongarch64 \
+ filter_passsigalrm \
+ send_signal
+
+diff --git a/gdbserver_tests/filter_helgrind_monitor b/gdbserver_tests/filter_helgrind_monitor
+index 4fc2e9a..21bf6be 100755
+--- a/gdbserver_tests/filter_helgrind_monitor
++++ b/gdbserver_tests/filter_helgrind_monitor
+@@ -14,6 +14,8 @@ if $dir/../tests/os_test solaris; then
+ $dir/filter_helgrind_monitor_solaris
+ elif $dir/../tests/os_test freebsd; then
+ gsed -e '/\(rtld_start.S\|kill.S\|_exit.S\|_select.S\): No such file or directory/d'
++elif $dir/../tests/arch_test loongarch64; then
++ $dir/filter_helgrind_monitor_loongarch64
+ else
+ cat
+ fi |
+diff --git a/gdbserver_tests/filter_helgrind_monitor_loongarch64 b/gdbserver_tests/filter_helgrind_monitor_loongarch64
+new file mode 100755
+index 0000000..cda73e4
+--- /dev/null
++++ b/gdbserver_tests/filter_helgrind_monitor_loongarch64
+@@ -0,0 +1,43 @@
++#!/usr/bin/env perl
++# From gdbserver_tests/filter_helgrind_monitor_solaris
+
-+#define CALL_FN_W_9W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
-+ arg6, arg7, arg8, arg9) \
-+ do { \
-+ volatile OrigFn _orig = (orig); \
-+ volatile unsigned long _argvec[10]; \
-+ volatile unsigned long _res; \
-+ _argvec[0] = (unsigned long)_orig.nraddr; \
-+ _argvec[1] = (unsigned long)(arg1); \
-+ _argvec[2] = (unsigned long)(arg2); \
-+ _argvec[3] = (unsigned long)(arg3); \
-+ _argvec[4] = (unsigned long)(arg4); \
-+ _argvec[5] = (unsigned long)(arg5); \
-+ _argvec[6] = (unsigned long)(arg6); \
-+ _argvec[7] = (unsigned long)(arg7); \
-+ _argvec[8] = (unsigned long)(arg8); \
-+ _argvec[9] = (unsigned long)(arg9); \
-+ __asm__ volatile( \
-+ VALGRIND_ALIGN_STACK \
-+ "addi.d $sp, $sp, -8 \n\t" \
-+ "ld.d $a0, %1, 72 \n\t" \
-+ "st.d $a0, $sp, 0 \n\t" /* arg9 */ \
-+ "ld.d $a0, %1, 8 \n\t" /* arg1 */ \
-+ "ld.d $a1, %1, 16 \n\t" /* arg2 */ \
-+ "ld.d $a2, %1, 24 \n\t" /* arg3 */ \
-+ "ld.d $a3, %1, 32 \n\t" /* arg4 */ \
-+ "ld.d $a4, %1, 40 \n\t" /* arg5 */ \
-+ "ld.d $a5, %1, 48 \n\t" /* arg6 */ \
-+ "ld.d $a6, %1, 56 \n\t" /* arg7 */ \
-+ "ld.d $a7, %1, 64 \n\t" /* arg8 */ \
-+ "ld.d $t8, %1, 0 \n\t" /* target->t8 */ \
-+ VALGRIND_CALL_NOREDIR_T8 \
-+ VALGRIND_RESTORE_STACK \
-+ "move %0, $a0 \n\t" \
-+ : /*out*/ "=r" (_res) \
-+ : /*in*/ "r" (&_argvec[0]) \
-+ : /*trash*/ "memory", __CALLER_SAVED_REGS, "$s0" \
-+ ); \
-+ lval = (__typeof__(lval)) _res; \
-+ } while (0)
++#
++# Filter out all helgrind information about locks except the one named "mx".
++# One lock record looks like:
++# Lock ga 0x........ {
++# Address 0x........ is 2648 bytes inside data symbol "_rtld_local"
++# kind mbRec
++# }
+
-+#define CALL_FN_W_10W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
-+ arg6, arg7, arg8, arg9, arg10) \
-+ do { \
-+ volatile OrigFn _orig = (orig); \
-+ volatile unsigned long _argvec[11]; \
-+ volatile unsigned long _res; \
-+ _argvec[0] = (unsigned long)_orig.nraddr; \
-+ _argvec[1] = (unsigned long)(arg1); \
-+ _argvec[2] = (unsigned long)(arg2); \
-+ _argvec[3] = (unsigned long)(arg3); \
-+ _argvec[4] = (unsigned long)(arg4); \
-+ _argvec[5] = (unsigned long)(arg5); \
-+ _argvec[6] = (unsigned long)(arg6); \
-+ _argvec[7] = (unsigned long)(arg7); \
-+ _argvec[8] = (unsigned long)(arg8); \
-+ _argvec[9] = (unsigned long)(arg9); \
-+ _argvec[10] = (unsigned long)(arg10); \
-+ __asm__ volatile( \
-+ VALGRIND_ALIGN_STACK \
-+ "addi.d $sp, $sp, -16 \n\t" \
-+ "ld.d $a0, %1, 72 \n\t" \
-+ "st.d $a0, $sp, 0 \n\t" /* arg9 */ \
-+ "ld.d $a0, %1, 80 \n\t" \
-+ "st.d $a0, $sp, 8 \n\t" /* arg10 */ \
-+ "ld.d $a0, %1, 8 \n\t" /* arg1 */ \
-+ "ld.d $a1, %1, 16 \n\t" /* arg2 */ \
-+ "ld.d $a2, %1, 24 \n\t" /* arg3 */ \
-+ "ld.d $a3, %1, 32 \n\t" /* arg4 */ \
-+ "ld.d $a4, %1, 40 \n\t" /* arg5 */ \
-+ "ld.d $a5, %1, 48 \n\t" /* arg6 */ \
-+ "ld.d $a6, %1, 56 \n\t" /* arg7 */ \
-+ "ld.d $a7, %1, 64 \n\t" /* arg8 */ \
-+ "ld.d $t8, %1, 0 \n\t" /* target->t8 */ \
-+ VALGRIND_CALL_NOREDIR_T8 \
-+ VALGRIND_RESTORE_STACK \
-+ "move %0, $a0 \n\t" \
-+ : /*out*/ "=r" (_res) \
-+ : /*in*/ "r" (&_argvec[0]) \
-+ : /*trash*/ "memory", __CALLER_SAVED_REGS, "$s0" \
-+ ); \
-+ lval = (__typeof__(lval)) _res; \
-+ } while (0)
++use strict;
++use warnings;
+
-+#define CALL_FN_W_11W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
-+ arg6, arg7, arg8, arg9, arg10, \
-+ arg11) \
-+ do { \
-+ volatile OrigFn _orig = (orig); \
-+ volatile unsigned long _argvec[12]; \
-+ volatile unsigned long _res; \
-+ _argvec[0] = (unsigned long)_orig.nraddr; \
-+ _argvec[1] = (unsigned long)(arg1); \
-+ _argvec[2] = (unsigned long)(arg2); \
-+ _argvec[3] = (unsigned long)(arg3); \
-+ _argvec[4] = (unsigned long)(arg4); \
-+ _argvec[5] = (unsigned long)(arg5); \
-+ _argvec[6] = (unsigned long)(arg6); \
-+ _argvec[7] = (unsigned long)(arg7); \
-+ _argvec[8] = (unsigned long)(arg8); \
-+ _argvec[9] = (unsigned long)(arg9); \
-+ _argvec[10] = (unsigned long)(arg10); \
-+ _argvec[11] = (unsigned long)(arg11); \
-+ __asm__ volatile( \
-+ VALGRIND_ALIGN_STACK \
-+ "addi.d $sp, $sp, -24 \n\t" \
-+ "ld.d $a0, %1, 72 \n\t" \
-+ "st.d $a0, $sp, 0 \n\t" /* arg9 */ \
-+ "ld.d $a0, %1, 80 \n\t" \
-+ "st.d $a0, $sp, 8 \n\t" /* arg10 */ \
-+ "ld.d $a0, %1, 88 \n\t" \
-+ "st.d $a0, $sp, 16 \n\t" /* arg11 */ \
-+ "ld.d $a0, %1, 8 \n\t" /* arg1 */ \
-+ "ld.d $a1, %1, 16 \n\t" /* arg2 */ \
-+ "ld.d $a2, %1, 24 \n\t" /* arg3 */ \
-+ "ld.d $a3, %1, 32 \n\t" /* arg4 */ \
-+ "ld.d $a4, %1, 40 \n\t" /* arg5 */ \
-+ "ld.d $a5, %1, 48 \n\t" /* arg6 */ \
-+ "ld.d $a6, %1, 56 \n\t" /* arg7 */ \
-+ "ld.d $a7, %1, 64 \n\t" /* arg8 */ \
-+ "ld.d $t8, %1, 0 \n\t" /* target->t8 */ \
-+ VALGRIND_CALL_NOREDIR_T8 \
-+ VALGRIND_RESTORE_STACK \
-+ "move %0, $a0 \n\t" \
-+ : /*out*/ "=r" (_res) \
-+ : /*in*/ "r" (&_argvec[0]) \
-+ : /*trash*/ "memory", __CALLER_SAVED_REGS, "$s0" \
-+ ); \
-+ lval = (__typeof__(lval)) _res; \
-+ } while (0)
++my $lock_start_line = undef;
++my $skip_to_closing_line = 0;
++while () {
++ my $line = $_;
++ chomp($line);
++ if ($line =~ /^Lock ga 0x[\.]+\s+{$/) {
++ $lock_start_line = $line;
++ $skip_to_closing_line = 1;
++ } elsif (($lock_start_line) &&
++ ($line =~ /\s*Address 0x[\.]+ is \d+ bytes inside data symbol "(\S+)"/)) {
++ if ($1 eq "mx") {
++ print "$lock_start_line\n";
++ print "$line\n";
++ $skip_to_closing_line = 0;
++ }
++ } elsif ($line =~ /^}$/) {
++ if ($skip_to_closing_line == 0) {
++ print "$line\n";
++ }
++ undef($lock_start_line);
++ $skip_to_closing_line = 0;
++ } else {
++ if ($skip_to_closing_line == 0) {
++ print "$line\n";
++ }
++ }
++}
+
-+#define CALL_FN_W_12W(lval, orig, arg1, arg2, arg3, arg4, arg5, \
-+ arg6, arg7, arg8, arg9, arg10, \
-+ arg11, arg12) \
-+ do { \
-+ volatile OrigFn _orig = (orig); \
-+ volatile unsigned long _argvec[13]; \
-+ volatile unsigned long _res; \
-+ _argvec[0] = (unsigned long)_orig.nraddr; \
-+ _argvec[1] = (unsigned long)(arg1); \
-+ _argvec[2] = (unsigned long)(arg2); \
-+ _argvec[3] = (unsigned long)(arg3); \
-+ _argvec[4] = (unsigned long)(arg4); \
-+ _argvec[5] = (unsigned long)(arg5); \
-+ _argvec[6] = (unsigned long)(arg6); \
-+ _argvec[7] = (unsigned long)(arg7); \
-+ _argvec[8] = (unsigned long)(arg8); \
-+ _argvec[9] = (unsigned long)(arg9); \
-+ _argvec[10] = (unsigned long)(arg10); \
-+ _argvec[11] = (unsigned long)(arg11); \
-+ _argvec[12] = (unsigned long)(arg12); \
-+ __asm__ volatile( \
-+ VALGRIND_ALIGN_STACK \
-+ "addi.d $sp, $sp, -32 \n\t" \
-+ "ld.d $a0, %1, 72 \n\t" \
-+ "st.d $a0, $sp, 0 \n\t" /* arg9 */ \
-+ "ld.d $a0, %1, 80 \n\t" \
-+ "st.d $a0, $sp, 8 \n\t" /* arg10 */ \
-+ "ld.d $a0, %1, 88 \n\t" \
-+ "st.d $a0, $sp, 16 \n\t" /* arg11 */ \
-+ "ld.d $a0, %1, 96 \n\t" \
-+ "st.d $a0, $sp, 24 \n\t" /* arg12 */ \
-+ "ld.d $a0, %1, 8 \n\t" /* arg1 */ \
-+ "ld.d $a1, %1, 16 \n\t" /* arg2 */ \
-+ "ld.d $a2, %1, 24 \n\t" /* arg3 */ \
-+ "ld.d $a3, %1, 32 \n\t" /* arg4 */ \
-+ "ld.d $a4, %1, 40 \n\t" /* arg5 */ \
-+ "ld.d $a5, %1, 48 \n\t" /* arg6 */ \
-+ "ld.d $a6, %1, 56 \n\t" /* arg7 */ \
-+ "ld.d $a7, %1, 64 \n\t" /* arg8 */ \
-+ "ld.d $t8, %1, 0 \n\t" /* target->t8 */ \
-+ VALGRIND_CALL_NOREDIR_T8 \
-+ VALGRIND_RESTORE_STACK \
-+ "move %0, $a0 \n\t" \
-+ : /*out*/ "=r" (_res) \
-+ : /*in*/ "r" (&_argvec[0]) \
-+ : /*trash*/ "memory", __CALLER_SAVED_REGS, "$s0" \
-+ ); \
-+ lval = (__typeof__(lval)) _res; \
-+ } while (0)
++exit 0;
+diff --git a/helgrind/hg_main.c b/helgrind/hg_main.c
+index bbf95c0..a32e4d8 100644
+--- a/helgrind/hg_main.c
++++ b/helgrind/hg_main.c
+@@ -4888,6 +4888,7 @@ IRSB* hg_instrument ( VgCallbackClosure* closure,
+ switch (st->Ist.MBE.event) {
+ case Imbe_Fence:
+ case Imbe_CancelReservation:
++ case Imbe_InsnFence:
+ break; /* not interesting */
+ default:
+ goto unhandled;
+diff --git a/helgrind/tests/annotate_hbefore.c b/helgrind/tests/annotate_hbefore.c
+index 259d3b6..3200c6c 100644
+--- a/helgrind/tests/annotate_hbefore.c
++++ b/helgrind/tests/annotate_hbefore.c
+@@ -314,6 +314,36 @@ UWord do_acasW ( UWord* addr, UWord expected, UWord nyu )
+ return success;
+ }
+
++#elif defined(VGA_loongarch64)
+
-+#endif /* PLAT_loongarch64_linux */
++// loongarch64
++/* return 1 if success, 0 if failure */
++UWord do_acasW ( UWord* addr, UWord expected, UWord nyu )
++{
++ UWord success;
++ UWord block[3] = { (UWord)addr, nyu, expected };
+
- /* ------------------------------------------------------------------ */
- /* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
- /* */
-@@ -7159,6 +7681,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
++ __asm__ __volatile__(
++ " ld.d $t0, %1, 0 \n\t"
++ " ld.d $t2, %1, 16 \n\t"
++ " ld.d $t3, %1, 8 \n\t"
++ " ll.d $t1, $t0, 0 \n\t"
++ " bne $t1, $t2, 1f \n\t"
++ " sc.d $t3, $t0, 0 \n\t"
++ " move %0, $t3 \n\t"
++ " b 2f \n\t"
++ "1: \n\t"
++ " move %0, $zero \n\t"
++ "2: \n\t"
++ : /*out*/ "=r" (success)
++ : /*in*/ "r" (&block[0])
++ : /*trash*/ "t0", "t1", "t2", "t3", "memory"
++ );
++
++ assert(success == 0 || success == 1);
++ return success;
++}
++
+ #endif
+
+ void atomic_incW ( UWord* w )
+diff --git a/helgrind/tests/tc07_hbl1.c b/helgrind/tests/tc07_hbl1.c
+index a4250c6..0adb558 100644
+--- a/helgrind/tests/tc07_hbl1.c
++++ b/helgrind/tests/tc07_hbl1.c
+@@ -19,6 +19,7 @@
+ #undef PLAT_arm64_linux
+ #undef PLAT_s390x_linux
+ #undef PLAT_mips32_linux
++#undef PLAT_loongarch64_linux
+ #undef PLAT_x86_solaris
+ #undef PLAT_amd64_solaris
+
+@@ -50,6 +51,8 @@
+ # define PLAT_mips32_linux 1
+ #elif defined(__linux__) && defined(__nanomips__)
+ # define PLAT_nanomips_linux 1
++#elif defined(__linux__) && defined(__loongarch__) && (__loongarch_grlen == 64)
++# define PLAT_loongarch64_linux 1
+ #elif defined(__sun__) && defined(__i386__)
+ # define PLAT_x86_solaris 1
+ #elif defined(__sun__) && defined(__x86_64__)
+@@ -134,6 +137,20 @@
+ : /*out*/ : /*in*/ "r"(&(_lval)) \
+ : /*trash*/ "$t0", "$t1", "memory" \
+ )
++#elif defined(PLAT_loongarch64_linux)
++# define INC(_lval,_lqual) \
++ __asm__ __volatile__ ( \
++ "1: \n" \
++ " move $t0, %0 \n" \
++ " ll.w $t1, $t0, 0 \n" \
++ " addi.w $t1, $t1, 1 \n" \
++ " sc.w $t1, $t0, 0 \n" \
++ " li.w $t2, 1 \n" \
++ " bne $t1, $t2, 1b \n" \
++ : /*out*/ \
++ : /*in*/ "r" (&(_lval)) \
++ : /*trash*/ "$t0", "$t1", "$t2", "memory" \
++ )
+ #else
+ # error "Fix Me for this platform"
+ #endif
+diff --git a/helgrind/tests/tc08_hbl2.c b/helgrind/tests/tc08_hbl2.c
+index 6a8543f..3c6ff3f 100644
+--- a/helgrind/tests/tc08_hbl2.c
++++ b/helgrind/tests/tc08_hbl2.c
+@@ -36,6 +36,7 @@
+ #undef PLAT_s390x_linux
#undef PLAT_mips32_linux
#undef PLAT_mips64_linux
- #undef PLAT_nanomips_linux
+#undef PLAT_loongarch64_linux
#undef PLAT_x86_solaris
#undef PLAT_amd64_solaris
+@@ -71,6 +72,8 @@
+ #endif
+ #elif defined(__linux__) && defined(__nanomips__)
+ # define PLAT_nanomips_linux 1
++#elif defined(__linux__) && defined(__loongarch__) && (__loongarch_grlen == 64)
++# define PLAT_loongarch64_linux 1
+ #elif defined(__sun__) && defined(__i386__)
+ # define PLAT_x86_solaris 1
+ #elif defined(__sun__) && defined(__x86_64__)
+@@ -154,6 +157,20 @@
+ : /*out*/ : /*in*/ "r"(&(_lval)) \
+ : /*trash*/ "$t0", "$t1", "memory" \
+ )
++#elif defined(PLAT_loongarch64_linux)
++# define INC(_lval,_lqual) \
++ __asm__ __volatile__ ( \
++ "1: \n" \
++ " move $t0, %0 \n" \
++ " ll.w $t1, $t0, 0 \n" \
++ " addi.w $t1, $t1, 1 \n" \
++ " sc.w $t1, $t0, 0 \n" \
++ " li.w $t2, 1 \n" \
++ " bne $t1, $t2, 1b \n" \
++ : /*out*/ \
++ : /*in*/ "r" (&(_lval)) \
++ : /*trash*/ "$t0", "$t1", "$t2", "memory" \
++ )
+ #else
+ # error "Fix Me for this platform"
+ #endif
+diff --git a/helgrind/tests/tc11_XCHG.c b/helgrind/tests/tc11_XCHG.c
+index cc00ba3..c52fe4e 100644
+--- a/helgrind/tests/tc11_XCHG.c
++++ b/helgrind/tests/tc11_XCHG.c
+@@ -21,6 +21,7 @@
+ #undef PLAT_arm_linux
+ #undef PLAT_s390x_linux
+ #undef PLAT_mips32_linux
++#undef PLAT_loongarch64_linux
+ #undef PLAT_x86_solaris
+ #undef PLAT_amd64_solaris
+
+@@ -52,6 +53,8 @@
+ # define PLAT_mips32_linux 1
+ #elif defined(__linux__) && defined(__nanomips__)
+ # define PLAT_nanomips_linux 1
++#elif defined(__linux__) && defined(__loongarch__) && (__loongarch_grlen == 64)
++# define PLAT_loongarch64_linux 1
+ #elif defined(__sun__) && defined(__i386__)
+ # define PLAT_x86_solaris 1
+ #elif defined(__sun__) && defined(__x86_64__)
+@@ -150,6 +153,21 @@
+ # define XCHG_M_R_with_redundant_LOCK(_addr,_lval) \
+ XCHG_M_R(_addr,_lval)
+
++#elif defined(PLAT_loongarch64_linux)
++# define XCHG_M_R(_addr,_lval) \
++ __asm__ __volatile__( \
++ "move $t0, %2 \n\t" \
++ "ll.w $t1, %1 \n\t" \
++ "sc.w $t0, %1 \n\t" \
++ "move %0, $t1 \n\t" \
++ : /*out*/ "=r"(_lval), "+ZC"(_addr) \
++ : /*in*/ "r"(_lval) \
++ : "$t0", "$t1", "memory" \
++ )
++
++# define XCHG_M_R_with_redundant_LOCK(_addr,_lval) \
++ XCHG_M_R(_addr,_lval)
++
+ #else
+ # error "Unsupported architecture"
+
+diff --git a/include/Makefile.am b/include/Makefile.am
+index 5d5162a..fb3e353 100644
+--- a/include/Makefile.am
++++ b/include/Makefile.am
+@@ -64,6 +64,7 @@ nobase_pkginclude_HEADERS = \
+ vki/vki-posixtypes-mips32-linux.h \
+ vki/vki-posixtypes-mips64-linux.h \
+ vki/vki-posixtypes-nanomips-linux.h \
++ vki/vki-posixtypes-loongarch64-linux.h \
+ vki/vki-amd64-linux.h \
+ vki/vki-arm64-linux.h \
+ vki/vki-ppc32-linux.h \
+@@ -77,6 +78,7 @@ nobase_pkginclude_HEADERS = \
+ vki/vki-mips32-linux.h \
+ vki/vki-mips64-linux.h \
+ vki/vki-nanomips-linux.h \
++ vki/vki-loongarch64-linux.h \
+ vki/vki-scnums-amd64-linux.h \
+ vki/vki-scnums-arm64-linux.h \
+ vki/vki-scnums-ppc32-linux.h \
+@@ -88,6 +90,7 @@ nobase_pkginclude_HEADERS = \
+ vki/vki-scnums-mips32-linux.h \
+ vki/vki-scnums-mips64-linux.h \
+ vki/vki-scnums-nanomips-linux.h \
++ vki/vki-scnums-loongarch64-linux.h \
+ vki/vki-scnums-darwin.h \
+ vki/vki-scnums-solaris.h \
+ vki/vki-scnums-shared-linux.h \
+diff --git a/include/pub_tool_basics.h b/include/pub_tool_basics.h
+index bf5a5ba..da90ea7 100644
+--- a/include/pub_tool_basics.h
++++ b/include/pub_tool_basics.h
+@@ -437,7 +437,8 @@ static inline Bool sr_EQ ( UInt sysno, SysRes sr1, SysRes sr2 ) {
+
+ #if defined(VGA_x86) || defined(VGA_amd64) || defined (VGA_arm) \
+ || ((defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips)) \
+- && defined (_MIPSEL)) || defined(VGA_arm64) || defined(VGA_ppc64le)
++ && defined (_MIPSEL)) || defined(VGA_arm64) || defined(VGA_ppc64le) \
++ || defined (VGA_loongarch64)
+ # define VG_LITTLEENDIAN 1
+ #elif defined(VGA_ppc32) || defined(VGA_ppc64be) || defined(VGA_s390x) \
+ || ((defined(VGA_mips32) || defined(VGA_mips64) || defined(VGA_nanomips)) \
+@@ -485,7 +486,8 @@ static inline Bool sr_EQ ( UInt sysno, SysRes sr1, SysRes sr2 ) {
+ || defined(VGA_ppc64be) || defined(VGA_ppc64le) \
+ || defined(VGA_arm) || defined(VGA_s390x) \
+ || defined(VGA_mips32) || defined(VGA_mips64) \
+- || defined(VGA_arm64) || defined(VGA_nanomips)
++ || defined(VGA_arm64) || defined(VGA_nanomips) \
++ || defined(VGA_loongarch64)
+ # define VG_REGPARM(n) /* */
+ #else
+ # error Unknown arch
+diff --git a/include/pub_tool_guest.h b/include/pub_tool_guest.h
+index 08a72ef..87e8cc2 100644
+--- a/include/pub_tool_guest.h
++++ b/include/pub_tool_guest.h
+@@ -62,6 +62,9 @@
+ #elif defined(VGA_mips64)
+ # include "libvex_guest_mips64.h"
+ typedef VexGuestMIPS64State VexGuestArchState;
++#elif defined(VGA_loongarch64)
++# include "libvex_guest_loongarch64.h"
++ typedef VexGuestLOONGARCH64State VexGuestArchState;
+ #else
+ # error Unknown arch
+ #endif
+diff --git a/include/pub_tool_libcsetjmp.h b/include/pub_tool_libcsetjmp.h
+index e9638c3..26330a0 100644
+--- a/include/pub_tool_libcsetjmp.h
++++ b/include/pub_tool_libcsetjmp.h
+@@ -142,6 +142,14 @@ UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
+ __attribute__((noreturn))
+ void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
+
++#elif defined(VGP_loongarch64_linux)
++
++#define VG_MINIMAL_JMP_BUF(_name) ULong _name [13+8+1]
++__attribute__((returns_twice))
++UWord VG_MINIMAL_SETJMP(VG_MINIMAL_JMP_BUF(_env));
++__attribute__((noreturn))
++void VG_MINIMAL_LONGJMP(VG_MINIMAL_JMP_BUF(_env));
++
+ #elif defined(VGP_arm64_freebsd)
+
+ #define VG_MINIMAL_JMP_BUF(_name) UWord _name [22]
+diff --git a/include/pub_tool_machine.h b/include/pub_tool_machine.h
+index f462072..27ea69c 100644
+--- a/include/pub_tool_machine.h
++++ b/include/pub_tool_machine.h
+@@ -108,6 +108,12 @@
+ # define VG_CLREQ_SZB 20
+ # define VG_STACK_REDZONE_SZB 0
+
++#elif defined(VGP_loongarch64_linux)
++# define VG_MIN_INSTR_SZB 4
++# define VG_MAX_INSTR_SZB 8
++# define VG_CLREQ_SZB 20
++# define VG_STACK_REDZONE_SZB 0
++
+ #else
+ # error Unknown platform
+ #endif
+diff --git a/include/pub_tool_redir.h b/include/pub_tool_redir.h
+index f88d3b5..d1bb8cb 100644
+--- a/include/pub_tool_redir.h
++++ b/include/pub_tool_redir.h
+@@ -321,6 +321,8 @@
+
+ #define VG_U_LD_LINUX_MIPSN8_S0_1 "ld-linux-mipsn8.so.1"
+
++#define VG_U_LD_LINUX_LOONGARCH_LP64D_SO_1 "ld-linux-loongarch-lp64d.so.1"
++
+ #endif
+
+ /* --- Sonames for FreeBSD ELF linkers, plus unencoded versions. --- */
+diff --git a/include/pub_tool_vkiscnums_asm.h b/include/pub_tool_vkiscnums_asm.h
+index f97a3af..f2c0f56 100644
+--- a/include/pub_tool_vkiscnums_asm.h
++++ b/include/pub_tool_vkiscnums_asm.h
+@@ -72,6 +72,10 @@
+ #elif defined(VGP_mips64_linux)
+ # include "vki/vki-scnums-mips64-linux.h"
+
++#elif defined(VGP_loongarch64_linux)
++# include "vki/vki-scnums-shared-linux.h"
++# include "vki/vki-scnums-loongarch64-linux.h"
++
+ #elif defined(VGP_x86_freebsd) || defined(VGP_amd64_freebsd) || defined(VGP_arm64_freebsd)
+ # include "vki/vki-scnums-freebsd.h"
+
diff --git a/include/valgrind.h.in b/include/valgrind.h.in
-index 45f6522..3e1967a 100644
+index bc18f40..f53f34e 100644
--- a/include/valgrind.h.in
+++ b/include/valgrind.h.in
-@@ -125,6 +125,7 @@
+@@ -126,6 +126,7 @@
#undef PLAT_mips32_linux
#undef PLAT_mips64_linux
#undef PLAT_nanomips_linux
@@ -31272,7 +35402,7 @@ index 45f6522..3e1967a 100644
#undef PLAT_x86_solaris
#undef PLAT_amd64_solaris
-@@ -169,6 +170,8 @@
+@@ -172,6 +173,8 @@
# define PLAT_mips32_linux 1
#elif defined(__linux__) && defined(__nanomips__)
# define PLAT_nanomips_linux 1
@@ -31281,7 +35411,7 @@ index 45f6522..3e1967a 100644
#elif defined(__sun) && defined(__i386__)
# define PLAT_x86_solaris 1
#elif defined(__sun) && defined(__x86_64__)
-@@ -1125,7 +1128,75 @@ typedef
+@@ -1128,7 +1131,75 @@ typedef
); \
} while (0)
@@ -31358,7 +35488,7 @@ index 45f6522..3e1967a 100644
/* Insert assembly code for other platforms here... */
#endif /* NVALGRIND */
-@@ -6603,6 +6674,457 @@ typedef
+@@ -6606,6 +6677,457 @@ typedef
#endif /* PLAT_mips64_linux */
@@ -31816,7 +35946,7 @@ index 45f6522..3e1967a 100644
/* ------------------------------------------------------------------ */
/* ARCHITECTURE INDEPENDENT MACROS for CLIENT REQUESTS. */
/* */
-@@ -7159,6 +7681,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
+@@ -7162,6 +7684,7 @@ VALGRIND_PRINTF_BACKTRACE(const char *format, ...)
#undef PLAT_mips32_linux
#undef PLAT_mips64_linux
#undef PLAT_nanomips_linux
@@ -31825,7 +35955,7 @@ index 45f6522..3e1967a 100644
#undef PLAT_amd64_solaris
diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h
-index be3d766..0a60c0a 100644
+index d4e1908..7f23b5e 100644
--- a/include/vki/vki-linux.h
+++ b/include/vki/vki-linux.h
@@ -97,6 +97,8 @@
@@ -32755,10 +36885,10 @@ index 0000000..0282a2a
+/*--------------------------------------------------------------------*/
diff --git a/include/vki/vki-scnums-loongarch64-linux.h b/include/vki/vki-scnums-loongarch64-linux.h
new file mode 100644
-index 0000000..b7ac621
+index 0000000..552824f
--- /dev/null
+++ b/include/vki/vki-scnums-loongarch64-linux.h
-@@ -0,0 +1,356 @@
+@@ -0,0 +1,330 @@
+/*--------------------------------------------------------------------*/
+/*--- System call numbers for loongarch-linux. ---*/
+/*--- vki-scnums-loongarch64-linux.h ---*/
@@ -32872,8 +37002,8 @@ index 0000000..b7ac621
+#define __NR_splice 76
+#define __NR_tee 77
+#define __NR_readlinkat 78
-+#define __NR3264_fstatat 79
-+#define __NR3264_fstat 80
++// #define __NR3264_fstatat 79
++// #define __NR3264_fstat 80
+#define __NR_sync 81
+#define __NR_fsync 82
+#define __NR_fdatasync 83
@@ -33074,32 +37204,6 @@ index 0000000..b7ac621
+#define __NR_rseq 293
+#define __NR_kexec_file_load 294
+
-+#define __NR_pidfd_send_signal 424
-+#define __NR_io_uring_setup 425
-+#define __NR_io_uring_enter 426
-+#define __NR_io_uring_register 427
-+#define __NR_open_tree 428
-+#define __NR_move_mount 429
-+#define __NR_fsopen 430
-+#define __NR_fsconfig 431
-+#define __NR_fsmount 432
-+#define __NR_fspick 433
-+#define __NR_pidfd_open 434
-+#define __NR_clone3 435
-+#define __NR_close_range 436
-+#define __NR_openat2 437
-+#define __NR_pidfd_getfd 438
-+#define __NR_faccessat2 439
-+#define __NR_process_madvise 440
-+#define __NR_epoll_pwait2 441
-+#define __NR_mount_setattr 442
-+#define __NR_quotactl_fd 443
-+#define __NR_landlock_create_ruleset 444
-+#define __NR_landlock_add_rule 445
-+#define __NR_landlock_restrict_self 446
-+// #define __NR_memfd_secret 447
-+#define __NR_process_mrelease 448
-+
+#define __NR_fcntl __NR3264_fcntl
+#define __NR_statfs __NR3264_statfs
+#define __NR_fstatfs __NR3264_fstatfs
@@ -33115,124 +37219,8 @@ index 0000000..b7ac621
+/*--------------------------------------------------------------------*/
+/*--- end vki-scnums-loongarch64-linux.h ---*/
+/*--------------------------------------------------------------------*/
-diff --git a/lackey/Makefile.in b/lackey/Makefile.in
-index f08a302..39e01ca 100644
---- a/lackey/Makefile.in
-+++ b/lackey/Makefile.in
-@@ -621,6 +621,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -668,6 +674,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
-
-@@ -758,6 +765,10 @@ TOOL_LDFLAGS_MIPS64_LINUX = \
- -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
- @FLAG_M64@
-
-+TOOL_LDFLAGS_LOONGARCH64_LINUX = \
-+ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
-+ @FLAG_M64@
-+
- TOOL_LDFLAGS_X86_SOLARIS = \
- $(TOOL_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
-
-@@ -818,6 +829,9 @@ LIBREPLACEMALLOC_MIPS32_LINUX = \
- LIBREPLACEMALLOC_MIPS64_LINUX = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips64-linux.a
-
-+LIBREPLACEMALLOC_LOONGARCH64_LINUX = \
-+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-loongarch64-linux.a
-+
- LIBREPLACEMALLOC_X86_SOLARIS = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-solaris.a
-
-@@ -890,6 +904,11 @@ LIBREPLACEMALLOC_LDFLAGS_MIPS64_LINUX = \
- $(LIBREPLACEMALLOC_MIPS64_LINUX) \
- -Wl,--no-whole-archive
-
-+LIBREPLACEMALLOC_LDFLAGS_LOONGARCH64_LINUX = \
-+ -Wl,--whole-archive \
-+ $(LIBREPLACEMALLOC_LOONGARCH64_LINUX) \
-+ -Wl,--no-whole-archive
-+
- LIBREPLACEMALLOC_LDFLAGS_X86_SOLARIS = \
- -Wl,--whole-archive \
- $(LIBREPLACEMALLOC_X86_SOLARIS) \
-diff --git a/massif/Makefile.in b/massif/Makefile.in
-index ddedba7..8f983c1 100644
---- a/massif/Makefile.in
-+++ b/massif/Makefile.in
-@@ -676,6 +676,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -723,6 +729,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
-
-@@ -813,6 +820,10 @@ TOOL_LDFLAGS_MIPS64_LINUX = \
- -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
- @FLAG_M64@
-
-+TOOL_LDFLAGS_LOONGARCH64_LINUX = \
-+ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
-+ @FLAG_M64@
-+
- TOOL_LDFLAGS_X86_SOLARIS = \
- $(TOOL_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
-
-@@ -873,6 +884,9 @@ LIBREPLACEMALLOC_MIPS32_LINUX = \
- LIBREPLACEMALLOC_MIPS64_LINUX = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips64-linux.a
-
-+LIBREPLACEMALLOC_LOONGARCH64_LINUX = \
-+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-loongarch64-linux.a
-+
- LIBREPLACEMALLOC_X86_SOLARIS = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-solaris.a
-
-@@ -945,6 +959,11 @@ LIBREPLACEMALLOC_LDFLAGS_MIPS64_LINUX = \
- $(LIBREPLACEMALLOC_MIPS64_LINUX) \
- -Wl,--no-whole-archive
-
-+LIBREPLACEMALLOC_LDFLAGS_LOONGARCH64_LINUX = \
-+ -Wl,--whole-archive \
-+ $(LIBREPLACEMALLOC_LOONGARCH64_LINUX) \
-+ -Wl,--no-whole-archive
-+
- LIBREPLACEMALLOC_LDFLAGS_X86_SOLARIS = \
- -Wl,--whole-archive \
- $(LIBREPLACEMALLOC_X86_SOLARIS) \
diff --git a/massif/tests/Makefile.am b/massif/tests/Makefile.am
-index 636bc8f..b16d73d 100644
+index ab781fa..43498f5 100644
--- a/massif/tests/Makefile.am
+++ b/massif/tests/Makefile.am
@@ -11,6 +11,7 @@ EXTRA_DIST = \
@@ -33243,39 +37231,6 @@ index 636bc8f..b16d73d 100644
bug469146.post.exp bug469146.stderr.exp bug469146.vgtest \
deep-A.post.exp deep-A.stderr.exp deep-A.vgtest \
deep-B.post.exp deep-B.stderr.exp deep-B.vgtest \
-diff --git a/massif/tests/Makefile.in b/massif/tests/Makefile.in
-index 0e20293..3ee79f4 100644
---- a/massif/tests/Makefile.in
-+++ b/massif/tests/Makefile.in
-@@ -717,6 +717,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -764,6 +770,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-@@ -795,6 +802,7 @@ EXTRA_DIST = \
- big-alloc.post.exp big-alloc.post.exp-64bit big-alloc.post.exp-ppc64 \
- big-alloc.stderr.exp big-alloc.vgtest \
- big-alloc.post.exp-x86-freebsd \
-+ big-alloc.post.exp-loongarch64 \
- bug469146.post.exp bug469146.stderr.exp bug469146.vgtest \
- deep-A.post.exp deep-A.stderr.exp deep-A.vgtest \
- deep-B.post.exp deep-B.stderr.exp deep-B.vgtest \
diff --git a/massif/tests/big-alloc.post.exp-loongarch64 b/massif/tests/big-alloc.post.exp-loongarch64
new file mode 100644
index 0000000..4dac2a6
@@ -33336,64 +37291,6 @@ index 0000000..4dac2a6
+ n time(B) total(B) useful-heap(B) extra-heap(B) stacks(B)
+--------------------------------------------------------------------------------
+ 10 105,020,880 105,020,880 104,857,600 163,280 0
-diff --git a/memcheck/Makefile.in b/memcheck/Makefile.in
-index 39b34c9..cc8fd2b 100644
---- a/memcheck/Makefile.in
-+++ b/memcheck/Makefile.in
-@@ -709,6 +709,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -756,6 +762,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
-
-@@ -846,6 +853,10 @@ TOOL_LDFLAGS_MIPS64_LINUX = \
- -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
- @FLAG_M64@
-
-+TOOL_LDFLAGS_LOONGARCH64_LINUX = \
-+ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
-+ @FLAG_M64@
-+
- TOOL_LDFLAGS_X86_SOLARIS = \
- $(TOOL_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
-
-@@ -906,6 +917,9 @@ LIBREPLACEMALLOC_MIPS32_LINUX = \
- LIBREPLACEMALLOC_MIPS64_LINUX = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips64-linux.a
-
-+LIBREPLACEMALLOC_LOONGARCH64_LINUX = \
-+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-loongarch64-linux.a
-+
- LIBREPLACEMALLOC_X86_SOLARIS = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-solaris.a
-
-@@ -978,6 +992,11 @@ LIBREPLACEMALLOC_LDFLAGS_MIPS64_LINUX = \
- $(LIBREPLACEMALLOC_MIPS64_LINUX) \
- -Wl,--no-whole-archive
-
-+LIBREPLACEMALLOC_LDFLAGS_LOONGARCH64_LINUX = \
-+ -Wl,--whole-archive \
-+ $(LIBREPLACEMALLOC_LOONGARCH64_LINUX) \
-+ -Wl,--no-whole-archive
-+
- LIBREPLACEMALLOC_LDFLAGS_X86_SOLARIS = \
- -Wl,--whole-archive \
- $(LIBREPLACEMALLOC_X86_SOLARIS) \
diff --git a/memcheck/mc_machine.c b/memcheck/mc_machine.c
index 176c8e5..49f9894 100644
--- a/memcheck/mc_machine.c
@@ -33532,10 +37429,98 @@ index 176c8e5..49f9894 100644
# error "FIXME: not implemented for this architecture"
# endif
diff --git a/memcheck/mc_translate.c b/memcheck/mc_translate.c
-index ec8ac53..fa58fc5 100644
+index 05e6d59..e811d6d 100644
--- a/memcheck/mc_translate.c
+++ b/memcheck/mc_translate.c
-@@ -3505,6 +3505,7 @@ IRAtom* expr2vbits_Triop ( MCEnv* mce,
+@@ -2652,6 +2652,11 @@ static IRAtom* mkPCast128x1 ( MCEnv* mce, IRAtom* at )
+ return assignNew('V', mce, Ity_V128, unop(Iop_CmpNEZ128x1, at));
+ }
+
++static IRAtom* mkPCast128x2 ( MCEnv* mce, IRAtom* at )
++{
++ return assignNew('V', mce, Ity_V256, unop(Iop_CmpNEZ128x2, at));
++}
++
+ static IRAtom* mkPCast64x4 ( MCEnv* mce, IRAtom* at )
+ {
+ return assignNew('V', mce, Ity_V256, unop(Iop_CmpNEZ64x4, at));
+@@ -3252,6 +3257,51 @@ IRAtom* vectorWidenI64 ( MCEnv* mce, IROp longen_op,
+ return at2;
+ }
+
++static
++IRAtom* vectorWidenUnV128 ( MCEnv* mce, IROp longen_op,
++ IRAtom* vatom1)
++{
++ IRAtom *at1, *at2;
++ IRAtom* (*pcast)( MCEnv*, IRAtom* );
++ switch (longen_op) {
++ case Iop_WidenHIto16Sx8: pcast = mkPCast16x8; break;
++ case Iop_WidenHIto16Ux8: pcast = mkPCast16x8; break;
++ case Iop_WidenHIto32Sx4: pcast = mkPCast32x4; break;
++ case Iop_WidenHIto32Ux4: pcast = mkPCast32x4; break;
++ case Iop_WidenHIto64Sx2: pcast = mkPCast64x2; break;
++ case Iop_WidenHIto64Ux2: pcast = mkPCast64x2; break;
++ case Iop_WidenHIto128Sx1: pcast = mkPCast128x1; break;
++ case Iop_WidenHIto128Ux1: pcast = mkPCast128x1; break;
++ default: VG_(tool_panic)("vectorWidenUnV128");
++ }
++ tl_assert(isShadowAtom(mce,vatom1));
++ at1 = assignNew('V', mce, Ity_V128, unop(longen_op, vatom1));
++ at2 = assignNew('V', mce, Ity_V128, pcast(mce, at1));
++ return at2;
++}
++
++static
++IRAtom* vectorWidenUnV256 ( MCEnv* mce, IROp longen_op,
++ IRAtom* vatom1)
++{
++ IRAtom *at1, *at2;
++ IRAtom* (*pcast)( MCEnv*, IRAtom* );
++ switch (longen_op) {
++ case Iop_WidenHIto16Sx16: pcast = mkPCast16x16; break;
++ case Iop_WidenHIto16Ux16: pcast = mkPCast16x16; break;
++ case Iop_WidenHIto32Sx8: pcast = mkPCast32x8; break;
++ case Iop_WidenHIto32Ux8: pcast = mkPCast32x8; break;
++ case Iop_WidenHIto64Sx4: pcast = mkPCast64x4; break;
++ case Iop_WidenHIto64Ux4: pcast = mkPCast64x4; break;
++ case Iop_WidenHIto128Sx2: pcast = mkPCast128x2; break;
++ case Iop_WidenHIto128Ux2: pcast = mkPCast128x2; break;
++ default: VG_(tool_panic)("vectorWidenUnV256");
++ }
++ tl_assert(isShadowAtom(mce,vatom1));
++ at1 = assignNew('V', mce, Ity_V256, unop(longen_op, vatom1));
++ at2 = assignNew('V', mce, Ity_V256, pcast(mce, at1));
++ return at2;
++}
+
+ /* --- --- Vector integer arithmetic --- --- */
+
+@@ -3295,6 +3345,15 @@ IRAtom* binary64Ix4 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
+ return at;
+ }
+
++static
++IRAtom* binary128Ix2 ( MCEnv* mce, IRAtom* vatom1, IRAtom* vatom2 )
++{
++ IRAtom* at;
++ at = mkUifUV256(mce, vatom1, vatom2);
++ at = mkPCast128x2(mce, at);
++ return at;
++}
++
+ /* --- V128-bit versions --- */
+
+ static
+@@ -3448,7 +3507,6 @@ IRAtom* expr2vbits_Qop ( MCEnv* mce,
+ /* I32(rm) x F128 x F128 x F128 -> F128 */
+ return mkLazy4(mce, Ity_I128, vatom1, vatom2, vatom3, vatom4);
+
+- /* V256-bit data-steering */
+ case Iop_64x4toV256:
+ return assignNew('V', mce, Ity_V256,
+ IRExpr_Qop(op, vatom1, vatom2, vatom3, vatom4));
+@@ -3505,6 +3563,7 @@ IRAtom* expr2vbits_Triop ( MCEnv* mce,
case Iop_MulD64:
case Iop_MulF64r32:
case Iop_DivF64:
@@ -33543,7 +37528,7 @@ index ec8ac53..fa58fc5 100644
case Iop_DivD64:
case Iop_DivF64r32:
case Iop_ScaleF64:
-@@ -3524,6 +3525,7 @@ IRAtom* expr2vbits_Triop ( MCEnv* mce,
+@@ -3524,6 +3583,7 @@ IRAtom* expr2vbits_Triop ( MCEnv* mce,
case Iop_SubF32:
case Iop_MulF32:
case Iop_DivF32:
@@ -33551,7 +37536,37 @@ index ec8ac53..fa58fc5 100644
/* I32(rm) x F32 x F32 -> I32 */
return mkLazy3(mce, Ity_I32, vatom1, vatom2, vatom3);
case Iop_AddF16:
-@@ -4532,6 +4534,8 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
+@@ -4507,6 +4567,29 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
+ return binary32Fx8(mce, vatom1, vatom2);
+
+ /* V256-bit data-steering */
++
++ case Iop_InterleaveLO64x4:
++ case Iop_InterleaveLO32x8:
++ case Iop_InterleaveLO16x16:
++ case Iop_InterleaveLO8x32:
++ case Iop_InterleaveHI64x4:
++ case Iop_InterleaveHI32x8:
++ case Iop_InterleaveHI16x16:
++ case Iop_InterleaveHI8x32:
++ case Iop_InterleaveOddLanes8x32:
++ case Iop_InterleaveOddLanes16x16:
++ case Iop_InterleaveOddLanes32x8:
++ case Iop_InterleaveEvenLanes8x32:
++ case Iop_InterleaveEvenLanes16x16:
++ case Iop_InterleaveEvenLanes32x8:
++ case Iop_PackOddLanes8x32:
++ case Iop_PackOddLanes16x16:
++ case Iop_PackOddLanes32x8:
++ case Iop_PackEvenLanes8x32:
++ case Iop_PackEvenLanes16x16:
++ case Iop_PackEvenLanes32x8:
++ return assignNew('V', mce, Ity_V256, binop(op, vatom1, atom2));
++
+ case Iop_V128HLtoV256:
+ return assignNew('V', mce, Ity_V256, binop(op, vatom1, vatom2));
+
+@@ -4532,6 +4615,8 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
case Iop_TanF64:
case Iop_2xm1F64:
case Iop_SqrtF64:
@@ -33560,7 +37575,7 @@ index ec8ac53..fa58fc5 100644
case Iop_RecpExpF64:
/* I32(rm) x I64/F64 -> I64/F64 */
return mkLazy2(mce, Ity_I64, vatom1, vatom2);
-@@ -4593,6 +4597,8 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
+@@ -4593,6 +4678,8 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
case Iop_RoundF32toInt:
case Iop_SqrtF32:
@@ -33569,7 +37584,7 @@ index ec8ac53..fa58fc5 100644
case Iop_RecpExpF32:
/* I32(rm) x I32/F32 -> I32/F32 */
return mkLazy2(mce, Ity_I32, vatom1, vatom2);
-@@ -4675,11 +4681,15 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
+@@ -4675,11 +4762,15 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
case Iop_MaxNumF32:
case Iop_MinNumF32:
@@ -33585,18 +37600,221 @@ index ec8ac53..fa58fc5 100644
/* F64 x F64 -> F64 */
return mkLazy2(mce, Ity_I64, vatom1, vatom2);
-@@ -5026,6 +5036,10 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
+@@ -4964,11 +5055,15 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
+
+ /* V256-bit SIMD */
+
++ case Iop_ShrN8x32:
+ case Iop_ShrN16x16:
+ case Iop_ShrN32x8:
+ case Iop_ShrN64x4:
++ case Iop_SarN8x32:
+ case Iop_SarN16x16:
+ case Iop_SarN32x8:
++ case Iop_SarN64x4:
++ case Iop_ShlN8x32:
+ case Iop_ShlN16x16:
+ case Iop_ShlN32x8:
+ case Iop_ShlN64x4:
+@@ -4978,16 +5073,61 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
+ complainIfUndefined(mce, atom2, NULL);
+ return assignNew('V', mce, Ity_V256, binop(op, vatom1, atom2));
+
++ /* V x V shifts/rotates are done using the standard lazy scheme. */
++ /* For the non-rounding variants of bi-di vector x vector
++ shifts (the Iop_Sh.. ops, that is) we use the lazy scheme.
++ But note that this is overly pessimistic, because in fact only
++ the bottom 8 bits of each lane of the second argument are taken
++ into account when shifting. So really we ought to ignore
++ undefinedness in bits 8 and above of each lane in the
++ second argument. */
++ case Iop_Shl8x32:
++ case Iop_Shr8x32:
++ case Iop_Sar8x32:
++ return mkUifUV256(mce,
++ assignNew('V', mce, Ity_V256, binop(op, vatom1, atom2)),
++ mkPCast8x32(mce,vatom2)
++ );
++
++ case Iop_Shl16x16:
++ case Iop_Shr16x16:
++ case Iop_Sar16x16:
++ return mkUifUV256(mce,
++ assignNew('V', mce, Ity_V256, binop(op, vatom1, atom2)),
++ mkPCast16x16(mce,vatom2)
++ );
++
++ case Iop_Shl32x8:
++ case Iop_Shr32x8:
++ case Iop_Sar32x8:
++ return mkUifUV256(mce,
++ assignNew('V', mce, Ity_V256, binop(op, vatom1, atom2)),
++ mkPCast32x8(mce,vatom2)
++ );
++
++ case Iop_Shl64x4:
++ case Iop_Shr64x4:
++ case Iop_Sar64x4:
++ return mkUifUV256(mce,
++ assignNew('V', mce, Ity_V256, binop(op, vatom1, atom2)),
++ mkPCast64x4(mce,vatom2)
++ );
++
+ case Iop_QSub8Ux32:
+ case Iop_QSub8Sx32:
+ case Iop_Sub8x32:
++ case Iop_Mul8x32:
++ case Iop_MulHi8Sx32:
++ case Iop_MulHi8Ux32:
+ case Iop_Min8Ux32:
+ case Iop_Min8Sx32:
+ case Iop_Max8Ux32:
+ case Iop_Max8Sx32:
++ case Iop_CmpGT8Ux32:
+ case Iop_CmpGT8Sx32:
+ case Iop_CmpEQ8x32:
+ case Iop_Avg8Ux32:
++ case Iop_Avg8Sx32:
+ case Iop_QAdd8Ux32:
+ case Iop_QAdd8Sx32:
+ case Iop_Add8x32:
+@@ -5003,31 +5143,57 @@ IRAtom* expr2vbits_Binop ( MCEnv* mce,
+ case Iop_Min16Ux16:
+ case Iop_Max16Sx16:
+ case Iop_Max16Ux16:
++ case Iop_CmpGT16Ux16:
+ case Iop_CmpGT16Sx16:
+ case Iop_CmpEQ16x16:
+ case Iop_Avg16Ux16:
++ case Iop_Avg16Sx16:
+ case Iop_QAdd16Ux16:
+ case Iop_QAdd16Sx16:
+ case Iop_Add16x16:
+ return binary16Ix16(mce, vatom1, vatom2);
+
++ case Iop_QSub32Ux8:
++ case Iop_QSub32Sx8:
+ case Iop_Sub32x8:
++ case Iop_CmpGT32Ux8:
+ case Iop_CmpGT32Sx8:
+ case Iop_CmpEQ32x8:
++ case Iop_QAdd32Ux8:
++ case Iop_QAdd32Sx8:
+ case Iop_Add32x8:
+ case Iop_Max32Ux8:
+ case Iop_Max32Sx8:
+ case Iop_Min32Ux8:
+ case Iop_Min32Sx8:
+ case Iop_Mul32x8:
++ case Iop_MulHi32Sx8:
++ case Iop_MulHi32Ux8:
++ case Iop_Avg32Ux8:
++ case Iop_Avg32Sx8:
+ return binary32Ix8(mce, vatom1, vatom2);
+
++ case Iop_QSub64Ux4:
++ case Iop_QSub64Sx4:
+ case Iop_Sub64x4:
++ case Iop_QAdd64Ux4:
++ case Iop_QAdd64Sx4:
case Iop_Add64x4:
case Iop_CmpEQ64x4:
++ case Iop_CmpGT64Ux4:
case Iop_CmpGT64Sx4:
+ case Iop_Max64Sx4:
+ case Iop_Max64Ux4:
+ case Iop_Min64Sx4:
+ case Iop_Min64Ux4:
++ case Iop_Avg64Ux4:
++ case Iop_Avg64Sx4:
return binary64Ix4(mce, vatom1, vatom2);
++ case Iop_Sub128x2:
++ case Iop_Add128x2:
++ return binary128Ix2(mce, vatom1, vatom2);
++
case Iop_I32StoF32x8:
-@@ -8763,6 +8777,9 @@ IRSB* MC_(instrument) ( VgCallbackClosure* closure,
+ case Iop_F32toI32Sx8:
+ return unary32Fx8_w_rm(mce, vatom1, vatom2);
+@@ -5160,6 +5326,10 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
+ case Iop_RSqrtEst64Fx2:
+ case Iop_RecipEst64Fx2:
+ case Iop_Log2_64Fx2:
++ case Iop_RoundF64x2_RM:
++ case Iop_RoundF64x2_RP:
++ case Iop_RoundF64x2_RN:
++ case Iop_RoundF64x2_RZ:
+ return unary64Fx2(mce, vatom);
+
+ case Iop_Sqrt64F0x2:
+@@ -5425,6 +5595,9 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
+ case Iop_Ctz8x16:
+ return mkPCast8x16(mce, vatom);
+
++ case Iop_Abs8x32:
++ return mkPCast8x32(mce, vatom);
++
+ case Iop_CmpNEZ16x4:
+ case Iop_Clz16x4:
+ case Iop_Cls16x4:
+@@ -5438,6 +5611,9 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
+ case Iop_Ctz16x8:
+ return mkPCast16x8(mce, vatom);
+
++ case Iop_Abs16x16:
++ return mkPCast16x16(mce, vatom);
++
+ case Iop_CmpNEZ32x2:
+ case Iop_Clz32x2:
+ case Iop_Cls32x2:
+@@ -5456,6 +5632,9 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
+ case Iop_Ctz32x4:
+ return mkPCast32x4(mce, vatom);
+
++ case Iop_Abs32x8:
++ return mkPCast32x8(mce, vatom);
++
+ case Iop_TruncF128toI32S: /* F128 -> I32S (result stored in 64-bits) */
+ case Iop_TruncF128toI32U: /* F128 -> I32U (result stored in 64-bits) */
+ case Iop_CmpwNEZ32:
+@@ -5473,6 +5652,9 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
+ case Iop_Ctz64x2:
+ return mkPCast64x2(mce, vatom);
+
++ case Iop_Abs64x4:
++ return mkPCast64x4(mce, vatom);
++
+ // This is self-shadowing.
+ case Iop_PwBitMtxXpose64x2:
+ return assignNew('V', mce, Ity_V128, unop(op, vatom));
+@@ -5504,6 +5686,26 @@ IRExpr* expr2vbits_Unop ( MCEnv* mce, IROp op, IRAtom* atom )
+ case Iop_Widen32Uto64x2:
+ return vectorWidenI64(mce, op, vatom);
+
++ case Iop_WidenHIto16Sx8:
++ case Iop_WidenHIto32Sx4:
++ case Iop_WidenHIto64Sx2:
++ case Iop_WidenHIto128Sx1:
++ case Iop_WidenHIto16Ux8:
++ case Iop_WidenHIto32Ux4:
++ case Iop_WidenHIto64Ux2:
++ case Iop_WidenHIto128Ux1:
++ return vectorWidenUnV128(mce, op, vatom);
++
++ case Iop_WidenHIto16Sx16:
++ case Iop_WidenHIto32Sx8:
++ case Iop_WidenHIto64Sx4:
++ case Iop_WidenHIto128Sx2:
++ case Iop_WidenHIto16Ux16:
++ case Iop_WidenHIto32Ux8:
++ case Iop_WidenHIto64Ux4:
++ case Iop_WidenHIto128Ux2:
++ return vectorWidenUnV256(mce, op, vatom);
++
+ case Iop_F16toF32x4:
+ // JRS 2019 Mar 17: this definitely isn't right, but it probably works
+ // OK by accident if -- as seems likely -- the F16 to F32 conversion
+@@ -8767,6 +8969,9 @@ IRSB* MC_(instrument) ( VgCallbackClosure* closure,
mce.dlbo.dl_CmpEQ64_CmpNE64 = DLexpensive;
# elif defined(VGA_arm)
mce.dlbo.dl_CmpEQ32_CmpNE32 = DLexpensive;
@@ -33607,10 +37825,10 @@ index ec8ac53..fa58fc5 100644
/* preInstrumentationAnalysis() will allocate &mce.tmpHowUsed and then
diff --git a/memcheck/tests/Makefile.am b/memcheck/tests/Makefile.am
-index 47b5384..c9710e9 100644
+index c3b5fdb..63584a7 100644
--- a/memcheck/tests/Makefile.am
+++ b/memcheck/tests/Makefile.am
-@@ -50,6 +50,9 @@ endif
+@@ -53,6 +53,9 @@ endif
if VGCONF_PLATFORMS_INCLUDE_ARM64_LINUX
SUBDIRS += arm64-linux
endif
@@ -33620,301 +37838,24 @@ index 47b5384..c9710e9 100644
if VGCONF_PLATFORMS_INCLUDE_X86_SOLARIS
SUBDIRS += x86-solaris
endif
-@@ -65,7 +68,7 @@ endif
+@@ -68,7 +71,7 @@ endif
- DIST_SUBDIRS = x86 amd64 ppc32 ppc64 s390x linux \
+ DIST_SUBDIRS = x86 amd64 arm64 ppc32 ppc64 s390x linux \
darwin solaris x86-linux amd64-linux arm64-linux \
- x86-solaris amd64-solaris mips32 mips64 \
+ loongarch64-linux x86-solaris amd64-solaris mips32 mips64 \
freebsd amd64-freebsd x86-freebsd \
common .
-diff --git a/memcheck/tests/Makefile.in b/memcheck/tests/Makefile.in
-index f992408..3fe71b6 100644
---- a/memcheck/tests/Makefile.in
-+++ b/memcheck/tests/Makefile.in
-@@ -145,10 +145,11 @@ host_triplet = @host@
- @VGCONF_PLATFORMS_INCLUDE_X86_LINUX_TRUE@am__append_23 = x86-linux
- @VGCONF_PLATFORMS_INCLUDE_AMD64_LINUX_TRUE@am__append_24 = amd64-linux
- @VGCONF_PLATFORMS_INCLUDE_ARM64_LINUX_TRUE@am__append_25 = arm64-linux
--@VGCONF_PLATFORMS_INCLUDE_X86_SOLARIS_TRUE@am__append_26 = x86-solaris
--@VGCONF_PLATFORMS_INCLUDE_AMD64_SOLARIS_TRUE@am__append_27 = amd64-solaris
--@VGCONF_PLATFORMS_INCLUDE_X86_FREEBSD_TRUE@am__append_28 = x86-freebsd
--@VGCONF_PLATFORMS_INCLUDE_AMD64_FREEBSD_TRUE@am__append_29 = amd64-freebsd
-+@VGCONF_PLATFORMS_INCLUDE_LOONGARCH64_LINUX_TRUE@am__append_26 = loongarch64-linux
-+@VGCONF_PLATFORMS_INCLUDE_X86_SOLARIS_TRUE@am__append_27 = x86-solaris
-+@VGCONF_PLATFORMS_INCLUDE_AMD64_SOLARIS_TRUE@am__append_28 = amd64-solaris
-+@VGCONF_PLATFORMS_INCLUDE_X86_FREEBSD_TRUE@am__append_29 = x86-freebsd
-+@VGCONF_PLATFORMS_INCLUDE_AMD64_FREEBSD_TRUE@am__append_30 = amd64-freebsd
- check_PROGRAMS = accounting$(EXEEXT) addressable$(EXEEXT) \
- atomic_incs$(EXEEXT) badaddrvalue$(EXEEXT) badfree$(EXEEXT) \
- badjump$(EXEEXT) badjump2$(EXEEXT) badloop$(EXEEXT) \
-@@ -215,31 +216,31 @@ check_PROGRAMS = accounting$(EXEEXT) addressable$(EXEEXT) \
- $(am__EXEEXT_9) $(am__EXEEXT_10)
-
- # Sun Studio assembler fails on "IDENT too long"
--@SOLARIS_SUN_STUDIO_AS_FALSE@am__append_30 = long_namespace_xml
--@DWARF4_TRUE@am__append_31 = dw4
--@GZ_ZLIB_TRUE@am__append_32 = cdebug_zlib
--@GZ_ZLIB_GNU_TRUE@am__append_33 = cdebug_zlib_gnu
--@HAVE_ALIGNED_CXX_ALLOC_TRUE@am__append_34 = cxx17_aligned_new sized_aligned_new_delete_args \
-+@SOLARIS_SUN_STUDIO_AS_FALSE@am__append_31 = long_namespace_xml
-+@DWARF4_TRUE@am__append_32 = dw4
-+@GZ_ZLIB_TRUE@am__append_33 = cdebug_zlib
-+@GZ_ZLIB_GNU_TRUE@am__append_34 = cdebug_zlib_gnu
-+@HAVE_ALIGNED_CXX_ALLOC_TRUE@am__append_35 = cxx17_aligned_new sized_aligned_new_delete_args \
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@ new_aligned_delete_default \
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@ sized_aligned_new_delete_misaligned1 \
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@ sized_aligned_new_delete_misaligned2 \
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@ sized_aligned_new_delete_misaligned3
-
--@HAVE_PTHREAD_BARRIER_TRUE@am__append_35 = reach_thread_register
--@HAVE_FSIZED_DEALLOCATION_TRUE@am__append_36 = sized_delete new_delete_mismatch_size
--@HAVE_GNU_STPNCPY_TRUE@am__append_37 = stpncpy
--@HAVE_PTHREAD_SETNAME_NP_TRUE@am__append_38 = threadname
-+@HAVE_PTHREAD_BARRIER_TRUE@am__append_36 = reach_thread_register
-+@HAVE_FSIZED_DEALLOCATION_TRUE@am__append_37 = sized_delete new_delete_mismatch_size
-+@HAVE_GNU_STPNCPY_TRUE@am__append_38 = stpncpy
-+@HAVE_PTHREAD_SETNAME_NP_TRUE@am__append_39 = threadname
-
- # are there still pre-C99 C compilers?
--@HAVE_WCSNCPY_TRUE@am__append_39 = wcsncpy
--@COMPILER_IS_CLANG_TRUE@@HAVE_ALIGNED_CXX_ALLOC_TRUE@am__append_40 = -fsized-deallocation
-+@HAVE_WCSNCPY_TRUE@am__append_40 = wcsncpy
- @COMPILER_IS_CLANG_TRUE@@HAVE_ALIGNED_CXX_ALLOC_TRUE@am__append_41 = -fsized-deallocation
- @COMPILER_IS_CLANG_TRUE@@HAVE_ALIGNED_CXX_ALLOC_TRUE@am__append_42 = -fsized-deallocation
- @COMPILER_IS_CLANG_TRUE@@HAVE_ALIGNED_CXX_ALLOC_TRUE@am__append_43 = -fsized-deallocation
- @COMPILER_IS_CLANG_TRUE@@HAVE_ALIGNED_CXX_ALLOC_TRUE@am__append_44 = -fsized-deallocation
--@VGCONF_OS_IS_SOLARIS_TRUE@am__append_45 = -D_XOPEN_SOURCE=600
--@VGCONF_OS_IS_SOLARIS_TRUE@am__append_46 = -D__EXTENSIONS__
--@VGCONF_OS_IS_SOLARIS_TRUE@am__append_47 = -D_XOPEN_SOURCE=600
-+@COMPILER_IS_CLANG_TRUE@@HAVE_ALIGNED_CXX_ALLOC_TRUE@am__append_45 = -fsized-deallocation
-+@VGCONF_OS_IS_SOLARIS_TRUE@am__append_46 = -D_XOPEN_SOURCE=600
-+@VGCONF_OS_IS_SOLARIS_TRUE@am__append_47 = -D__EXTENSIONS__
-+@VGCONF_OS_IS_SOLARIS_TRUE@am__append_48 = -D_XOPEN_SOURCE=600
- subdir = memcheck/tests
- ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
- am__aclocal_m4_deps = $(top_srcdir)/configure.ac
-@@ -1687,6 +1688,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -1734,6 +1741,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-@@ -1761,10 +1769,11 @@ SUBDIRS = . $(am__append_12) $(am__append_13) $(am__append_14) \
- $(am__append_18) $(am__append_19) $(am__append_20) \
- $(am__append_21) $(am__append_22) $(am__append_23) \
- $(am__append_24) $(am__append_25) $(am__append_26) \
-- $(am__append_27) $(am__append_28) $(am__append_29)
-+ $(am__append_27) $(am__append_28) $(am__append_29) \
-+ $(am__append_30)
- DIST_SUBDIRS = x86 amd64 ppc32 ppc64 s390x linux \
- darwin solaris x86-linux amd64-linux arm64-linux \
-- x86-solaris amd64-solaris mips32 mips64 \
-+ loongarch64-linux x86-solaris amd64-solaris mips32 mips64 \
- freebsd amd64-freebsd x86-freebsd \
- common .
-
-@@ -2174,27 +2183,27 @@ bug340392_CFLAGS = $(AM_CFLAGS) -O3 @FLAG_W_NO_MAYBE_UNINITIALIZED@
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@cxx17_aligned_new_SOURCES = cxx17_aligned_new.cpp
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@cxx17_aligned_new_CXXFLAGS = -std=c++17 \
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@ @FLAG_W_NO_MISMATCHED_NEW_DELETE@ \
--@HAVE_ALIGNED_CXX_ALLOC_TRUE@ $(am__append_40)
-+@HAVE_ALIGNED_CXX_ALLOC_TRUE@ $(am__append_41)
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@new_aligned_delete_default_SOURCES = new_aligned_delete_default.cpp
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@new_aligned_delete_default_CXXFLAGS = ${AM_CXXFLAGS} -std=c++17
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@sized_aligned_new_delete_args_SOURCES = sized_aligned_new_delete_args.cpp
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@sized_aligned_new_delete_args_CXXFLAGS = \
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@ ${AM_CXXFLAGS} -std=c++17 \
--@HAVE_ALIGNED_CXX_ALLOC_TRUE@ $(am__append_41)
-+@HAVE_ALIGNED_CXX_ALLOC_TRUE@ $(am__append_42)
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@sized_aligned_new_delete_misaligned1_SOURCES = sized_aligned_new_delete_misaligned1.cpp
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@sized_aligned_new_delete_misaligned1_CXXFLAGS = \
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@ ${AM_CXXFLAGS} -std=c++17 \
--@HAVE_ALIGNED_CXX_ALLOC_TRUE@ $(am__append_42)
-+@HAVE_ALIGNED_CXX_ALLOC_TRUE@ $(am__append_43)
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@sized_aligned_new_delete_misaligned2_SOURCES = sized_aligned_new_delete_misaligned2.cpp
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@sized_aligned_new_delete_misaligned2_CXXFLAGS = \
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@ ${AM_CXXFLAGS} -std=c++17 \
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@ @FLAG_W_NO_UNUSED_VARIABLE@ \
--@HAVE_ALIGNED_CXX_ALLOC_TRUE@ $(am__append_43)
-+@HAVE_ALIGNED_CXX_ALLOC_TRUE@ $(am__append_44)
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@sized_aligned_new_delete_misaligned3_SOURCES = sized_aligned_new_delete_misaligned3.cpp
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@sized_aligned_new_delete_misaligned3_CXXFLAGS = \
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@ ${AM_CXXFLAGS} -std=c++17 \
- @HAVE_ALIGNED_CXX_ALLOC_TRUE@ @FLAG_W_NO_UNUSED_VARIABLE@ \
--@HAVE_ALIGNED_CXX_ALLOC_TRUE@ $(am__append_44)
-+@HAVE_ALIGNED_CXX_ALLOC_TRUE@ $(am__append_45)
- demangle_SOURCES = demangle.cpp
- demangle_rust_SOURCES = demangle-rust.c
- demangle_rust_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_USE_AFTER_FREE@
-@@ -2202,7 +2211,7 @@ dw4_CFLAGS = $(AM_CFLAGS) -gdwarf-4 -fdebug-types-section
- descr_belowsp_LDADD = -lpthread
- err_disable3_LDADD = -lpthread
- err_disable4_LDADD = -lpthread
--err_disable4_CFLAGS = $(AM_CFLAGS) $(am__append_45)
-+err_disable4_CFLAGS = $(AM_CFLAGS) $(am__append_46)
- error_counts_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_UNINITIALIZED@ @FLAG_W_NO_UNUSED_BUT_SET_VARIABLE@
- execve1_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_NONNULL@
- execve2_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_NONNULL@
-@@ -2217,7 +2226,7 @@ malloc1_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_USE_AFTER_FREE@
- manuel1_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_UNINITIALIZED@
- manuel3_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_UNINITIALIZED@
- memalign2_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_NON_POWER_OF_TWO_ALIGNMENT@ \
-- $(am__append_46)
-+ $(am__append_47)
- memcmptest_CFLAGS = $(AM_CFLAGS) -fno-builtin-memcmp
- mismatches_SOURCES = mismatches.cpp
- mismatches_CXXFLAGS = $(AM_CXXFLAGS) @FLAG_W_NO_MISMATCHED_NEW_DELETE@
-@@ -2250,7 +2259,7 @@ realloc_size_zero_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_INCOMPATIBLE_POINTER_TYPES_DI
- realloc_size_zero_mismatch_SOURCES = realloc_size_zero_mismatch.cpp
- realloc_size_zero_mismatch_CXXFLAGS = $(AM_CXXFLAGS) @FLAG_W_NO_MISMATCHED_NEW_DELETE@
- resvn_stack_CFLAGS = $(AM_CFLAGS) @FLAG_W_NO_UNINITIALIZED@
--sendmsg_CFLAGS = $(AM_CFLAGS) $(am__append_47)
-+sendmsg_CFLAGS = $(AM_CFLAGS) $(am__append_48)
- @VGCONF_OS_IS_SOLARIS_TRUE@sendmsg_LDADD = -lsocket -lnsl
- @HAVE_FSIZED_DEALLOCATION_TRUE@sized_delete_SOURCES = sized_delete.cpp
- @HAVE_FSIZED_DEALLOCATION_TRUE@sized_delete_CXXFLAGS = $(AM_CXXFLAGS) @FLAG_FSIZED_DEALLOCATION@
-diff --git a/memcheck/tests/amd64-freebsd/Makefile.in b/memcheck/tests/amd64-freebsd/Makefile.in
-index 2d1b884..5fa1665 100644
---- a/memcheck/tests/amd64-freebsd/Makefile.in
-+++ b/memcheck/tests/amd64-freebsd/Makefile.in
-@@ -583,6 +583,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -630,6 +636,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/memcheck/tests/amd64-linux/Makefile.in b/memcheck/tests/amd64-linux/Makefile.in
-index 1b3d479..8e273ea 100644
---- a/memcheck/tests/amd64-linux/Makefile.in
-+++ b/memcheck/tests/amd64-linux/Makefile.in
-@@ -582,6 +582,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -629,6 +635,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/memcheck/tests/amd64-solaris/Makefile.in b/memcheck/tests/amd64-solaris/Makefile.in
-index 8d2cc23..f497e2b 100644
---- a/memcheck/tests/amd64-solaris/Makefile.in
-+++ b/memcheck/tests/amd64-solaris/Makefile.in
-@@ -597,6 +597,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -644,6 +650,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/memcheck/tests/amd64/Makefile.in b/memcheck/tests/amd64/Makefile.in
-index 0a89e7e..045a9d8 100644
---- a/memcheck/tests/amd64/Makefile.in
-+++ b/memcheck/tests/amd64/Makefile.in
-@@ -668,6 +668,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -715,6 +721,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/memcheck/tests/arm64-linux/Makefile.in b/memcheck/tests/arm64-linux/Makefile.in
-index 20084ba..361c356 100644
---- a/memcheck/tests/arm64-linux/Makefile.in
-+++ b/memcheck/tests/arm64-linux/Makefile.in
-@@ -568,6 +568,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -615,6 +621,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
+@@ -252,7 +255,7 @@ EXTRA_DIST = \
+ leak-segv-jmp.vgtest leak-segv-jmp.stderr.exp \
+ lks.vgtest lks.stdout.exp lks.supp lks.stderr.exp \
+ long_namespace_xml.vgtest long_namespace_xml.stdout.exp \
+- long_namespace_xml.stderr.exp \
++ long_namespace_xml.stderr.exp long_namespace_xml.supp \
+ long-supps.vgtest long-supps.stderr.exp long-supps.supp \
+ mallinfo.stderr.exp mallinfo.vgtest \
+ malloc_free_fill.vgtest \
diff --git a/memcheck/tests/atomic_incs.c b/memcheck/tests/atomic_incs.c
index 1c738c5..8c00550 100644
--- a/memcheck/tests/atomic_incs.c
@@ -34038,86 +37979,11 @@ index 1c738c5..8c00550 100644
/* do nothing; is not supported */
#elif defined(VGA_arm64)
unsigned long long int block[3]
-diff --git a/memcheck/tests/common/Makefile.in b/memcheck/tests/common/Makefile.in
-index 71f2d86..3b6e554 100644
---- a/memcheck/tests/common/Makefile.in
-+++ b/memcheck/tests/common/Makefile.in
-@@ -526,6 +526,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -573,6 +579,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/memcheck/tests/darwin/Makefile.in b/memcheck/tests/darwin/Makefile.in
-index 9886522..9f0df9d 100644
---- a/memcheck/tests/darwin/Makefile.in
-+++ b/memcheck/tests/darwin/Makefile.in
-@@ -614,6 +614,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -661,6 +667,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/memcheck/tests/freebsd/Makefile.in b/memcheck/tests/freebsd/Makefile.in
-index 87c2a15..d391d1d 100644
---- a/memcheck/tests/freebsd/Makefile.in
-+++ b/memcheck/tests/freebsd/Makefile.in
-@@ -824,6 +824,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -871,6 +877,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
diff --git a/memcheck/tests/leak-segv-jmp.c b/memcheck/tests/leak-segv-jmp.c
-index 97bddaf..4890f5b 100644
+index 30fe2a1..4cc33ba 100644
--- a/memcheck/tests/leak-segv-jmp.c
+++ b/memcheck/tests/leak-segv-jmp.c
-@@ -182,6 +182,19 @@ extern UWord do_syscall_WRK (
+@@ -183,6 +183,19 @@ extern UWord do_syscall_WRK (
return out;
}
@@ -34137,7 +38003,7 @@ index 97bddaf..4890f5b 100644
#elif defined(VGP_x86_solaris)
extern ULong
do_syscall_WRK(UWord a1, UWord a2, UWord a3,
-@@ -338,7 +351,7 @@ static void non_simd_mprotect (long tid, void* addr, long len)
+@@ -369,7 +382,7 @@ static void non_simd_mprotect (long tid, void* addr, long len)
&err);
if (err)
mprotect_result = -1;
@@ -34147,17 +38013,17 @@ index 97bddaf..4890f5b 100644
0, 0, 0,
__NR_mprotect);
diff --git a/memcheck/tests/leak-segv-jmp.stderr.exp b/memcheck/tests/leak-segv-jmp.stderr.exp
-index b30fd76..0eea178 100644
+index 147bdf8..39149ea 100644
--- a/memcheck/tests/leak-segv-jmp.stderr.exp
+++ b/memcheck/tests/leak-segv-jmp.stderr.exp
@@ -14,8 +14,8 @@ To see them, rerun with: --leak-check=full --show-leak-kinds=all
expecting a leak
1,000 bytes in 1 blocks are definitely lost in loss record ... of ...
at 0x........: malloc (vg_replace_malloc.c:...)
-- by 0x........: f (leak-segv-jmp.c:389)
-- by 0x........: main (leak-segv-jmp.c:464)
-+ by 0x........: f (leak-segv-jmp.c:402)
-+ by 0x........: main (leak-segv-jmp.c:477)
+- by 0x........: f (leak-segv-jmp.c:420)
+- by 0x........: main (leak-segv-jmp.c:495)
++ by 0x........: f (leak-segv-jmp.c:433)
++ by 0x........: main (leak-segv-jmp.c:508)
LEAK SUMMARY:
definitely lost: 1,000 bytes in 1 blocks
@@ -34165,10 +38031,10 @@ index b30fd76..0eea178 100644
expecting a leak again
1,000 bytes in 1 blocks are definitely lost in loss record ... of ...
at 0x........: malloc (vg_replace_malloc.c:...)
-- by 0x........: f (leak-segv-jmp.c:389)
-- by 0x........: main (leak-segv-jmp.c:464)
-+ by 0x........: f (leak-segv-jmp.c:402)
-+ by 0x........: main (leak-segv-jmp.c:477)
+- by 0x........: f (leak-segv-jmp.c:420)
+- by 0x........: main (leak-segv-jmp.c:495)
++ by 0x........: f (leak-segv-jmp.c:433)
++ by 0x........: main (leak-segv-jmp.c:508)
LEAK SUMMARY:
definitely lost: 1,000 bytes in 1 blocks
@@ -34176,10 +38042,10 @@ index b30fd76..0eea178 100644
expecting a leak again after full mprotect
1,000 bytes in 1 blocks are definitely lost in loss record ... of ...
at 0x........: malloc (vg_replace_malloc.c:...)
-- by 0x........: f (leak-segv-jmp.c:389)
-- by 0x........: main (leak-segv-jmp.c:464)
-+ by 0x........: f (leak-segv-jmp.c:402)
-+ by 0x........: main (leak-segv-jmp.c:477)
+- by 0x........: f (leak-segv-jmp.c:420)
+- by 0x........: main (leak-segv-jmp.c:495)
++ by 0x........: f (leak-segv-jmp.c:433)
++ by 0x........: main (leak-segv-jmp.c:508)
LEAK SUMMARY:
definitely lost: 1,000 bytes in 1 blocks
@@ -34187,29 +38053,29 @@ index b30fd76..0eea178 100644
expecting heuristic not to crash after full mprotect
1,000 bytes in 1 blocks are definitely lost in loss record ... of ...
at 0x........: malloc (vg_replace_malloc.c:...)
-- by 0x........: f (leak-segv-jmp.c:389)
-- by 0x........: main (leak-segv-jmp.c:464)
-+ by 0x........: f (leak-segv-jmp.c:402)
-+ by 0x........: main (leak-segv-jmp.c:477)
+- by 0x........: f (leak-segv-jmp.c:420)
+- by 0x........: main (leak-segv-jmp.c:495)
++ by 0x........: f (leak-segv-jmp.c:433)
++ by 0x........: main (leak-segv-jmp.c:508)
200,000 bytes in 1 blocks are possibly lost in loss record ... of ...
at 0x........: calloc (vg_replace_malloc.c:...)
-- by 0x........: f (leak-segv-jmp.c:436)
-- by 0x........: main (leak-segv-jmp.c:464)
-+ by 0x........: f (leak-segv-jmp.c:449)
-+ by 0x........: main (leak-segv-jmp.c:477)
+- by 0x........: f (leak-segv-jmp.c:467)
+- by 0x........: main (leak-segv-jmp.c:495)
++ by 0x........: f (leak-segv-jmp.c:480)
++ by 0x........: main (leak-segv-jmp.c:508)
LEAK SUMMARY:
definitely lost: 1,000 bytes in 1 blocks
diff --git a/memcheck/tests/leak.h b/memcheck/tests/leak.h
-index 79e3cd6..df9d2e7 100644
+index bf78d58..fe79c8a 100644
--- a/memcheck/tests/leak.h
+++ b/memcheck/tests/leak.h
-@@ -148,6 +148,27 @@
- do { \
- __asm__ __volatile__ ("movl $0, %ecx\n\t"); \
+@@ -181,6 +181,27 @@
+ __asm__ __volatile__ ("mov x17, 0\n\t"); \
+ __asm__ __volatile__ ("mov x18, 0\n\t"); \
} while (0)
-+#elif defined (VGA_loongarch64)
++#elif defined (__loongarch__)
+#define CLEAR_CALLER_SAVED_REGS \
+ do { \
+ __asm__ __volatile__ ("move $a0, $zero \n\t" \
@@ -34233,31 +38099,34 @@ index 79e3cd6..df9d2e7 100644
#else
#define CLEAR_CALLER_SAVED_REGS /*nothing*/
#endif
-diff --git a/memcheck/tests/linux/Makefile.in b/memcheck/tests/linux/Makefile.in
-index 2631f0e..86eedbb 100644
---- a/memcheck/tests/linux/Makefile.in
-+++ b/memcheck/tests/linux/Makefile.in
-@@ -723,6 +723,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -770,6 +776,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
+diff --git a/memcheck/tests/long_namespace_xml.supp b/memcheck/tests/long_namespace_xml.supp
+new file mode 100644
+index 0000000..b26252b
+--- /dev/null
++++ b/memcheck/tests/long_namespace_xml.supp
+@@ -0,0 +1,13 @@
++# Conditional jump or move depends on uninitialised value(s)
++# at 0x40624F4: bcmp (vg_replace_strmem.c:1233)
++# by 0x415E1DB: std::ctype::_M_widen_init() const (in /usr/lib64/libstdc++.so.6.0.33)
++# by 0x41D9067: std::basic_ostream >& std::endl >(std::basic_ostream >&) (in /usr/lib64/libstdc++.so.6.0.33)
++# by 0x12000426B: _ZN5304abcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyzabcdefghijklmnopqrstuvwxyz5304ABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZABCDEFGHIJKLMNOPQRSTUVWXYZ1fEv (long_namespace_xml.cpp:36)
++# by 0x1200042BF: main (long_namespace_xml.cpp:45)
++{
++ long_namespace_xml_supp
++ Memcheck:Cond
++ fun:bcmp
++ ...
++ obj:*lib*/libstdc++.so*
++}
+diff --git a/memcheck/tests/long_namespace_xml.vgtest b/memcheck/tests/long_namespace_xml.vgtest
+index e367a0a..e57a150 100644
+--- a/memcheck/tests/long_namespace_xml.vgtest
++++ b/memcheck/tests/long_namespace_xml.vgtest
+@@ -1,3 +1,3 @@
+ prog: long_namespace_xml
+-vgopts: --xml=yes --xml-fd=2 --log-file=/dev/null
++vgopts: --xml=yes --xml-fd=2 --log-file=/dev/null --suppressions=long_namespace_xml.supp
+ stderr_filter: filter_xml
diff --git a/memcheck/tests/loongarch64-linux/Makefile.am b/memcheck/tests/loongarch64-linux/Makefile.am
new file mode 100644
index 0000000..5afcaa4
@@ -35662,10 +39531,10 @@ index 0000000..4d86d2c
+ } while (0);
diff --git a/memcheck/tests/loongarch64-linux/scalar.stderr.exp b/memcheck/tests/loongarch64-linux/scalar.stderr.exp
new file mode 100644
-index 0000000..a90b90a
+index 0000000..a0e7b13
--- /dev/null
+++ b/memcheck/tests/loongarch64-linux/scalar.stderr.exp
-@@ -0,0 +1,2716 @@
+@@ -0,0 +1,2728 @@
+-----------------------------------------------------
+128:__NR_restart_syscall n/a
+-----------------------------------------------------
@@ -37295,7 +41164,19 @@ index 0000000..a90b90a
+ ...
+ by 0x........: main (scalar.c:853)
+
-+Syscall param sigaltstack(ss) points to unaddressable byte(s)
++Syscall param sigaltstack(ss->ss_sp) points to unaddressable byte(s)
++ ...
++ by 0x........: main (scalar.c:853)
++ Address 0x........ is on thread 1's stack
++ in frame #1, created by main (scalar.c:28)
++
++Syscall param sigaltstack(ss->ss_size) points to unaddressable byte(s)
++ ...
++ by 0x........: main (scalar.c:853)
++ Address 0x........ is on thread 1's stack
++ in frame #1, created by main (scalar.c:28)
++
++Syscall param sigaltstack(ss->ss_flags) points to unaddressable byte(s)
+ ...
+ by 0x........: main (scalar.c:853)
+ Address 0x........ is on thread 1's stack
@@ -38393,156 +42274,6 @@ index 0000000..53e87e8
+prereq: [ `id -u` -ne 0 ]
+vgopts: -q --error-limit=no
+args: < scalar.c
-diff --git a/memcheck/tests/mips32/Makefile.in b/memcheck/tests/mips32/Makefile.in
-index b20c604..01519ab 100644
---- a/memcheck/tests/mips32/Makefile.in
-+++ b/memcheck/tests/mips32/Makefile.in
-@@ -576,6 +576,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -623,6 +629,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/memcheck/tests/mips64/Makefile.in b/memcheck/tests/mips64/Makefile.in
-index c481d0e..138de75 100644
---- a/memcheck/tests/mips64/Makefile.in
-+++ b/memcheck/tests/mips64/Makefile.in
-@@ -576,6 +576,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -623,6 +629,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/memcheck/tests/ppc32/Makefile.in b/memcheck/tests/ppc32/Makefile.in
-index 615b1cd..92cd288 100644
---- a/memcheck/tests/ppc32/Makefile.in
-+++ b/memcheck/tests/ppc32/Makefile.in
-@@ -578,6 +578,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -625,6 +631,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/memcheck/tests/ppc64/Makefile.in b/memcheck/tests/ppc64/Makefile.in
-index 0d12344..84b272d 100644
---- a/memcheck/tests/ppc64/Makefile.in
-+++ b/memcheck/tests/ppc64/Makefile.in
-@@ -578,6 +578,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -625,6 +631,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/memcheck/tests/s390x/Makefile.in b/memcheck/tests/s390x/Makefile.in
-index 17cbd0c..af85cdb 100644
---- a/memcheck/tests/s390x/Makefile.in
-+++ b/memcheck/tests/s390x/Makefile.in
-@@ -610,6 +610,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -657,6 +663,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/memcheck/tests/solaris/Makefile.in b/memcheck/tests/solaris/Makefile.in
-index 52c57a1..34783f2 100644
---- a/memcheck/tests/solaris/Makefile.in
-+++ b/memcheck/tests/solaris/Makefile.in
-@@ -844,6 +844,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -891,6 +897,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
diff --git a/memcheck/tests/unit_libcbase.c b/memcheck/tests/unit_libcbase.c
index 0ce65be..4803603 100644
--- a/memcheck/tests/unit_libcbase.c
@@ -38564,36 +42295,11 @@ index 0ce65be..4803603 100644
#include
unsigned long VKI_PAGE_SIZE;
#endif
-diff --git a/memcheck/tests/vbit-test/Makefile.in b/memcheck/tests/vbit-test/Makefile.in
-index 5fef578..eeb4e09 100644
---- a/memcheck/tests/vbit-test/Makefile.in
-+++ b/memcheck/tests/vbit-test/Makefile.in
-@@ -627,6 +627,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -674,6 +680,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- EXTRA_DIST = vbit-test.vgtest vbit-test.stderr.exp \
diff --git a/memcheck/tests/vbit-test/irops.c b/memcheck/tests/vbit-test/irops.c
-index 24f258b..89370f7 100644
+index 4755ce4..72a5558 100644
--- a/memcheck/tests/vbit-test/irops.c
+++ b/memcheck/tests/vbit-test/irops.c
-@@ -34,287 +34,297 @@
+@@ -34,291 +34,301 @@
That is not necessary but helpful when supporting a new architecture.
*/
static irop_t irops[] = {
@@ -39053,20 +42759,6 @@ index 24f258b..89370f7 100644
- { DEFOP(Iop_2xm1F64, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0 },
- { DEFOP(Iop_RoundF128toInt, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0 },
- { DEFOP(Iop_RoundF64toInt, UNDEF_ALL), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1 },
-- { DEFOP(Iop_RoundF32toInt, UNDEF_ALL), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 1, .mips64 = 1 },
-- { DEFOP(Iop_MAddF32, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1 },
-- { DEFOP(Iop_MSubF32, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1 },
-- { DEFOP(Iop_MAddF64, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1 },
-- { DEFOP(Iop_MSubF64, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1 },
-- { DEFOP(Iop_MAddF64r32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 0 },
-- { DEFOP(Iop_MSubF64r32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 0 },
-- { DEFOP(Iop_RSqrtEst5GoodF64, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 0 },
-- { DEFOP(Iop_RoundF64toF64_NEAREST, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1 },
-- { DEFOP(Iop_RoundF64toF64_NegINF, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1 },
-- { DEFOP(Iop_RoundF64toF64_PosINF, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1 },
-- { DEFOP(Iop_RoundF64toF64_ZERO, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1 },
-- { DEFOP(Iop_TruncF64asF32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1 }, // mips asserts
-- { DEFOP(Iop_RoundF64toF32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 0 },
+ { DEFOP(Iop_ReinterpI32asF32, UNDEF_SAME), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 1, .ppc64 = 0, .ppc32 = 0, .mips32 = 1, .mips64 = 1, .loongarch64 = 1 },
+ { DEFOP(Iop_F64HLtoF128, UNDEF_CONCAT), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .loongarch64 = 0 },
+ { DEFOP(Iop_F128HItoF64, UNDEF_UPPER), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .loongarch64 = 0 },
@@ -39114,7 +42806,25 @@ index 24f258b..89370f7 100644
+ { DEFOP(Iop_2xm1F64, UNDEF_ALL), .s390x = 0, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .loongarch64 = 0 },
+ { DEFOP(Iop_RoundF128toInt, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 0, .loongarch64 = 0 },
+ { DEFOP(Iop_RoundF64toInt, UNDEF_ALL), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1, .loongarch64 = 1 },
+ { DEFOP(Iop_RoundF64toIntA0, UNDEF_ALL), .arm64 = 1 },
+ { DEFOP(Iop_RoundF64toIntE, UNDEF_ALL), .arm64 = 1 },
+- { DEFOP(Iop_RoundF32toInt, UNDEF_ALL), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 1, .mips64 = 1 },
+ { DEFOP(Iop_RoundF32toInt, UNDEF_ALL), .s390x = 1, .amd64 = 1, .x86 = 1, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 1, .mips64 = 1, .loongarch64 = 1 },
+ { DEFOP(Iop_RoundF32toIntA0, UNDEF_ALL), .arm64 = 1 },
+ { DEFOP(Iop_RoundF32toIntE, UNDEF_ALL), .arm64 = 1 },
+- { DEFOP(Iop_MAddF32, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1 },
+- { DEFOP(Iop_MSubF32, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1 },
+- { DEFOP(Iop_MAddF64, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1 },
+- { DEFOP(Iop_MSubF64, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1 },
+- { DEFOP(Iop_MAddF64r32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 0 },
+- { DEFOP(Iop_MSubF64r32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 0 },
+- { DEFOP(Iop_RSqrtEst5GoodF64, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 0 },
+- { DEFOP(Iop_RoundF64toF64_NEAREST, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1 },
+- { DEFOP(Iop_RoundF64toF64_NegINF, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1 },
+- { DEFOP(Iop_RoundF64toF64_PosINF, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1 },
+- { DEFOP(Iop_RoundF64toF64_ZERO, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1 },
+- { DEFOP(Iop_TruncF64asF32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1 }, // mips asserts
+- { DEFOP(Iop_RoundF64toF32, UNDEF_ALL), .s390x = 0, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 0 },
+ { DEFOP(Iop_MAddF32, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1, .loongarch64 = 1 },
+ { DEFOP(Iop_MSubF32, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 0, .ppc32 = 0, .mips32 = 0, .mips64 = 1, .loongarch64 = 1 },
+ { DEFOP(Iop_MAddF64, UNDEF_ALL), .s390x = 1, .amd64 = 0, .x86 = 0, .arm = 0, .ppc64 = 1, .ppc32 = 1, .mips32 = 0, .mips64 = 1, .loongarch64 = 1 },
@@ -39147,7 +42857,118 @@ index 24f258b..89370f7 100644
/* ------------------ 16-bit scalar FP ------------------ */
{ DEFOP(Iop_F16toF64, UNDEF_ALL), .arm64 = 1 },
-@@ -1109,15 +1119,19 @@ static irop_t irops[] = {
+@@ -677,6 +687,10 @@ static irop_t irops[] = {
+ { DEFOP(Iop_F16toF64x2, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_F32x4_2toQ16x8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_F64x2_2toQ32x4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_RoundF64x2_RM, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_RoundF64x2_RP, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_RoundF64x2_RN, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_RoundF64x2_RZ, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Add32F0x4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Sub32F0x4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Mul32F0x4, UNDEF_UNKNOWN), },
+@@ -1011,6 +1025,14 @@ static irop_t irops[] = {
+ { DEFOP(Iop_Widen8Sto16x8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Widen16Sto32x4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Widen32Sto64x2, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto16Sx8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto16Ux8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto32Sx4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto32Ux4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto64Sx2, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto64Ux2, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto128Sx1, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto128Ux1, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_InterleaveHI8x16, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_InterleaveHI16x8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_InterleaveHI32x4, UNDEF_UNKNOWN), },
+@@ -1081,61 +1103,141 @@ static irop_t irops[] = {
+ { DEFOP(Iop_OrV256, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_XorV256, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_NotV256, UNDEF_UNKNOWN), },
++
++ { DEFOP(Iop_WidenHIto16Sx16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto16Ux16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto32Sx8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto32Ux8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto64Sx4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto64Ux4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto128Sx2, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_WidenHIto128Ux2, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_InterleaveLO64x4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_InterleaveLO32x8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_InterleaveLO16x16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_InterleaveLO8x32, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_InterleaveHI64x4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_InterleaveHI32x8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_InterleaveHI16x16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_InterleaveHI8x32, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_InterleaveOddLanes8x32, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_InterleaveOddLanes16x16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_InterleaveOddLanes32x8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_InterleaveEvenLanes8x32, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_InterleaveEvenLanes16x16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_InterleaveEvenLanes32x8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_PackOddLanes8x32, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_PackOddLanes16x16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_PackOddLanes32x8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_PackEvenLanes8x32, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_PackEvenLanes16x16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_PackEvenLanes32x8, UNDEF_UNKNOWN), },
++
+ /* --------------- MISC (vector integer cmp != 0) -------------*/
+ { DEFOP(Iop_CmpNEZ8x32, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_CmpNEZ16x16, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_CmpNEZ32x8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_CmpNEZ64x4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_CmpNEZ128x2, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Add8x32, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Add16x16, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Add32x8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Add64x4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Add128x2, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Sub8x32, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Sub16x16, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Sub32x8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Sub64x4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Sub128x2, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_CmpEQ8x32, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_CmpEQ16x16, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_CmpEQ32x8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_CmpEQ64x4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_CmpGT8Ux32, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_CmpGT16Ux16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_CmpGT32Ux8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_CmpGT64Ux4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_CmpGT8Sx32, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_CmpGT16Sx16, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_CmpGT32Sx8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_CmpGT64Sx4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_ShlN8x32, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_ShlN16x16, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_ShlN32x8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_ShlN64x4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_ShrN8x32, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_ShrN16x16, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_ShrN32x8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_ShrN64x4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_SarN8x32, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_SarN16x16, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_SarN32x8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_SarN64x4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Shl8x32, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Shl16x16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Shl32x8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Shl64x4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Shr8x32, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Shr16x16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Shr32x8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Shr64x4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Sar8x32, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Sar16x16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Sar32x8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Sar64x4, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Max8Sx32, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Max16Sx16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Max32Sx8, UNDEF_UNKNOWN), },
@@ -39164,14 +42985,51 @@ index 24f258b..89370f7 100644
{ DEFOP(Iop_Min16Ux16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Min32Ux8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Min64Ux4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Mul8x32, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Mul16x16, UNDEF_UNKNOWN), },
{ DEFOP(Iop_Mul32x8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_MulHi8Ux32, UNDEF_UNKNOWN), },
{ DEFOP(Iop_MulHi16Ux16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_MulHi32Ux8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_MulHi8Sx32, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_MulHi16Sx16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_MulHi32Sx8, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_QAdd8Ux32, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_QAdd16Ux16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_QAdd32Ux8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_QAdd64Ux4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_QAdd8Sx32, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_QAdd16Sx16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_QAdd32Sx8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_QAdd64Sx4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_QSub8Ux32, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_QSub16Ux16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_QSub32Ux8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_QSub64Ux4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_QSub8Sx32, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_QSub16Sx16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_QSub32Sx8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_QSub64Sx4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Avg8Ux32, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Avg16Ux16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Avg32Ux8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Avg64Ux4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Avg8Sx32, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Avg16Sx16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Avg32Sx8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Avg64Sx4, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Abs8x32, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Abs16x16, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Abs32x8, UNDEF_UNKNOWN), },
++ { DEFOP(Iop_Abs64x4, UNDEF_UNKNOWN), },
+ { DEFOP(Iop_Perm32x8, UNDEF_UNKNOWN), },
+ /* ------------------ 256-bit SIMD FP. ------------------ */
+ { DEFOP(Iop_Add64Fx4, UNDEF_UNKNOWN), },
diff --git a/memcheck/tests/vbit-test/vtest.h b/memcheck/tests/vbit-test/vtest.h
-index c724f41..fe17f67 100644
+index 5f2b2e0..33eaf3c 100644
--- a/memcheck/tests/vbit-test/vtest.h
+++ b/memcheck/tests/vbit-test/vtest.h
-@@ -179,15 +179,16 @@ typedef struct {
+@@ -188,15 +188,16 @@ typedef struct {
unsigned immediate_type;
// Indicate whether IROp can be tested on a particular architecture
@@ -39197,131 +43055,6 @@ index c724f41..fe17f67 100644
} irop_t;
-diff --git a/memcheck/tests/x86-freebsd/Makefile.in b/memcheck/tests/x86-freebsd/Makefile.in
-index 5bcbb87..9bcd33d 100644
---- a/memcheck/tests/x86-freebsd/Makefile.in
-+++ b/memcheck/tests/x86-freebsd/Makefile.in
-@@ -578,6 +578,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -625,6 +631,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/memcheck/tests/x86-linux/Makefile.in b/memcheck/tests/x86-linux/Makefile.in
-index 48dd441..168a21b 100644
---- a/memcheck/tests/x86-linux/Makefile.in
-+++ b/memcheck/tests/x86-linux/Makefile.in
-@@ -614,6 +614,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -661,6 +667,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/memcheck/tests/x86-solaris/Makefile.in b/memcheck/tests/x86-solaris/Makefile.in
-index 03dabc3..3762dd9 100644
---- a/memcheck/tests/x86-solaris/Makefile.in
-+++ b/memcheck/tests/x86-solaris/Makefile.in
-@@ -606,6 +606,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -653,6 +659,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/memcheck/tests/x86/Makefile.in b/memcheck/tests/x86/Makefile.in
-index 897ebd6..e4636dc 100644
---- a/memcheck/tests/x86/Makefile.in
-+++ b/memcheck/tests/x86/Makefile.in
-@@ -654,6 +654,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -701,6 +707,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/mpi/Makefile.in b/mpi/Makefile.in
-index 6d0024e..46bddc4 100644
---- a/mpi/Makefile.in
-+++ b/mpi/Makefile.in
-@@ -567,6 +567,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -614,6 +620,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- DEFAULT_INCLUDES =
diff --git a/nightly/conf/loongarch64.conf b/nightly/conf/loongarch64.conf
new file mode 100644
index 0000000..8603671
@@ -39344,66 +43077,8 @@ index 0000000..d784da3
+file=$3
+
+(cat "$body" "$file") | /usr/bin/mail -s "$subject" valgrind-testresults@lists.sourceforge.net -r "Feiyang Chen "
-diff --git a/none/Makefile.in b/none/Makefile.in
-index a8368f2..4d0c5c8 100644
---- a/none/Makefile.in
-+++ b/none/Makefile.in
-@@ -619,6 +619,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -666,6 +672,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
-
-@@ -756,6 +763,10 @@ TOOL_LDFLAGS_MIPS64_LINUX = \
- -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
- @FLAG_M64@
-
-+TOOL_LDFLAGS_LOONGARCH64_LINUX = \
-+ -static -nodefaultlibs -nostartfiles -u __start @FLAG_NO_BUILD_ID@ \
-+ @FLAG_M64@
-+
- TOOL_LDFLAGS_X86_SOLARIS = \
- $(TOOL_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
-
-@@ -816,6 +827,9 @@ LIBREPLACEMALLOC_MIPS32_LINUX = \
- LIBREPLACEMALLOC_MIPS64_LINUX = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-mips64-linux.a
-
-+LIBREPLACEMALLOC_LOONGARCH64_LINUX = \
-+ $(top_builddir)/coregrind/libreplacemalloc_toolpreload-loongarch64-linux.a
-+
- LIBREPLACEMALLOC_X86_SOLARIS = \
- $(top_builddir)/coregrind/libreplacemalloc_toolpreload-x86-solaris.a
-
-@@ -888,6 +902,11 @@ LIBREPLACEMALLOC_LDFLAGS_MIPS64_LINUX = \
- $(LIBREPLACEMALLOC_MIPS64_LINUX) \
- -Wl,--no-whole-archive
-
-+LIBREPLACEMALLOC_LDFLAGS_LOONGARCH64_LINUX = \
-+ -Wl,--whole-archive \
-+ $(LIBREPLACEMALLOC_LOONGARCH64_LINUX) \
-+ -Wl,--no-whole-archive
-+
- LIBREPLACEMALLOC_LDFLAGS_X86_SOLARIS = \
- -Wl,--whole-archive \
- $(LIBREPLACEMALLOC_X86_SOLARIS) \
diff --git a/none/tests/Makefile.am b/none/tests/Makefile.am
-index 253d4a1..c5943a0 100644
+index 53a6e1f..e3f52f2 100644
--- a/none/tests/Makefile.am
+++ b/none/tests/Makefile.am
@@ -35,7 +35,9 @@ endif
@@ -39429,118 +43104,6 @@ index 253d4a1..c5943a0 100644
dist_noinst_SCRIPTS = \
filter_cmdline0 \
-diff --git a/none/tests/Makefile.in b/none/tests/Makefile.in
-index c86429e..f33c222 100644
---- a/none/tests/Makefile.in
-+++ b/none/tests/Makefile.in
-@@ -137,21 +137,22 @@ host_triplet = @host@
- @VGCONF_ARCHS_INCLUDE_MIPS32_TRUE@am__append_19 = mips32
- @VGCONF_ARCHS_INCLUDE_MIPS64_TRUE@am__append_20 = mips64
- @VGCONF_ARCHS_INCLUDE_NANOMIPS_TRUE@am__append_21 = nanomips
-+@VGCONF_ARCHS_INCLUDE_LOONGARCH64_TRUE@am__append_22 = loongarch64
-
- # OS-specific tests
--@VGCONF_OS_IS_LINUX_TRUE@am__append_22 = linux
--@VGCONF_OS_IS_DARWIN_TRUE@am__append_23 = darwin
--@VGCONF_OS_IS_SOLARIS_TRUE@am__append_24 = solaris
--@VGCONF_OS_IS_FREEBSD_TRUE@am__append_25 = freebsd
-+@VGCONF_OS_IS_LINUX_TRUE@am__append_23 = linux
-+@VGCONF_OS_IS_DARWIN_TRUE@am__append_24 = darwin
-+@VGCONF_OS_IS_SOLARIS_TRUE@am__append_25 = solaris
-+@VGCONF_OS_IS_FREEBSD_TRUE@am__append_26 = freebsd
-
- # Platform-specific tests
--@VGCONF_PLATFORMS_INCLUDE_AMD64_LINUX_TRUE@am__append_26 = amd64-linux
--@VGCONF_PLATFORMS_INCLUDE_X86_LINUX_TRUE@am__append_27 = x86-linux
--@VGCONF_PLATFORMS_INCLUDE_AMD64_DARWIN_TRUE@am__append_28 = amd64-darwin
--@VGCONF_PLATFORMS_INCLUDE_X86_DARWIN_TRUE@am__append_29 = x86-darwin
--@VGCONF_PLATFORMS_INCLUDE_AMD64_SOLARIS_TRUE@am__append_30 = amd64-solaris
--@VGCONF_PLATFORMS_INCLUDE_X86_SOLARIS_TRUE@am__append_31 = x86-solaris
--@VGCONF_PLATFORMS_INCLUDE_X86_FREEBSD_TRUE@am__append_32 = x86-freebsd
-+@VGCONF_PLATFORMS_INCLUDE_AMD64_LINUX_TRUE@am__append_27 = amd64-linux
-+@VGCONF_PLATFORMS_INCLUDE_X86_LINUX_TRUE@am__append_28 = x86-linux
-+@VGCONF_PLATFORMS_INCLUDE_AMD64_DARWIN_TRUE@am__append_29 = amd64-darwin
-+@VGCONF_PLATFORMS_INCLUDE_X86_DARWIN_TRUE@am__append_30 = x86-darwin
-+@VGCONF_PLATFORMS_INCLUDE_AMD64_SOLARIS_TRUE@am__append_31 = amd64-solaris
-+@VGCONF_PLATFORMS_INCLUDE_X86_SOLARIS_TRUE@am__append_32 = x86-solaris
-+@VGCONF_PLATFORMS_INCLUDE_X86_FREEBSD_TRUE@am__append_33 = x86-freebsd
- check_PROGRAMS = args$(EXEEXT) async-sigs$(EXEEXT) bitfield1$(EXEEXT) \
- bug129866$(EXEEXT) bug234814$(EXEEXT) closeall$(EXEEXT) \
- coolo_strlen$(EXEEXT) discard$(EXEEXT) exec-sigmask$(EXEEXT) \
-@@ -188,17 +189,17 @@ check_PROGRAMS = args$(EXEEXT) async-sigs$(EXEEXT) bitfield1$(EXEEXT) \
- gxx304$(EXEEXT) process_vm_readv_writev$(EXEEXT) \
- sigprocmask$(EXEEXT) $(am__EXEEXT_1) $(am__EXEEXT_2) \
- $(am__EXEEXT_3) $(am__EXEEXT_4) $(am__EXEEXT_5)
--@HAVE_NESTED_FUNCTIONS_TRUE@am__append_33 = nestedfns
-+@HAVE_NESTED_FUNCTIONS_TRUE@am__append_34 = nestedfns
-
- # This doesn't appear to be compilable on Darwin.
--@VGCONF_OS_IS_DARWIN_OR_FREEBSD_FALSE@am__append_34 = rlimit64_nofile
--@VGCONF_OS_IS_DARWIN_FALSE@am__append_35 = ppoll_alarm
-+@VGCONF_OS_IS_DARWIN_OR_FREEBSD_FALSE@am__append_35 = rlimit64_nofile
-+@VGCONF_OS_IS_DARWIN_FALSE@am__append_36 = ppoll_alarm
-
- # older (?) clang does not know -ansi
--@HAVE_ANSI_TRUE@am__append_36 = ansi
--@BUILD_IFUNC_TESTS_TRUE@am__append_37 = ifunc
--@VGCONF_OS_IS_SOLARIS_TRUE@am__append_38 = -U_REENTRANT
--@VGCONF_OS_IS_SOLARIS_TRUE@am__append_39 = -Du_int32_t=uint32_t
-+@HAVE_ANSI_TRUE@am__append_37 = ansi
-+@BUILD_IFUNC_TESTS_TRUE@am__append_38 = ifunc
-+@VGCONF_OS_IS_SOLARIS_TRUE@am__append_39 = -U_REENTRANT
-+@VGCONF_OS_IS_SOLARIS_TRUE@am__append_40 = -Du_int32_t=uint32_t
- subdir = none/tests
- ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
- am__aclocal_m4_deps = $(top_srcdir)/configure.ac
-@@ -1109,6 +1110,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -1156,6 +1163,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-@@ -1184,10 +1192,12 @@ SUBDIRS = . scripts $(am__append_12) $(am__append_13) $(am__append_14) \
- $(am__append_21) $(am__append_22) $(am__append_23) \
- $(am__append_24) $(am__append_25) $(am__append_26) \
- $(am__append_27) $(am__append_28) $(am__append_29) \
-- $(am__append_30) $(am__append_31) $(am__append_32)
-+ $(am__append_30) $(am__append_31) $(am__append_32) \
-+ $(am__append_33)
- DIST_SUBDIRS = x86 amd64 ppc32 ppc64 arm arm64 s390x mips32 mips64 nanomips \
-- linux darwin solaris freebsd amd64-linux x86-linux amd64-darwin \
-- x86-darwin amd64-solaris x86-solaris x86-freebsd scripts .
-+ loongarch64 linux darwin solaris freebsd amd64-linux x86-linux \
-+ amd64-darwin x86-darwin amd64-solaris x86-solaris x86-freebsd \
-+ scripts .
-
- dist_noinst_SCRIPTS = \
- filter_cmdline0 \
-@@ -1386,9 +1396,9 @@ pth_term_signal_LDADD = -lpthread
- @VGCONF_OS_IS_FREEBSD_TRUE@res_search_LDADD = -lpthread
- @VGCONF_OS_IS_FREEBSD_FALSE@resolv_LDADD = -lresolv -lpthread
- @VGCONF_OS_IS_FREEBSD_TRUE@resolv_LDADD = -lpthread
--resolv_CFLAGS = $(AM_CFLAGS) $(am__append_38)
-+resolv_CFLAGS = $(AM_CFLAGS) $(am__append_39)
- semlimit_LDADD = -lpthread
--sha1_test_CFLAGS = $(AM_CFLAGS) $(am__append_39)
-+sha1_test_CFLAGS = $(AM_CFLAGS) $(am__append_40)
- sigsusp_LDADD = -lpthread
- thread_exits_LDADD = -lpthread
- threaded_fork_LDADD = -lpthread
diff --git a/none/tests/allexec_prepare_prereq b/none/tests/allexec_prepare_prereq
index a541f42..49c45c7 100755
--- a/none/tests/allexec_prepare_prereq
@@ -39564,206 +43127,22 @@ index a541f42..49c45c7 100755
+pair loongarch_unexisting_in_32bits loongarch64
exit 0
-diff --git a/none/tests/amd64-darwin/Makefile.in b/none/tests/amd64-darwin/Makefile.in
-index 053b4b0..06e8bda 100644
---- a/none/tests/amd64-darwin/Makefile.in
-+++ b/none/tests/amd64-darwin/Makefile.in
-@@ -570,6 +570,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -617,6 +623,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/amd64-linux/Makefile.in b/none/tests/amd64-linux/Makefile.in
-index 1bd04dc..ba1810a 100644
---- a/none/tests/amd64-linux/Makefile.in
-+++ b/none/tests/amd64-linux/Makefile.in
-@@ -578,6 +578,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -625,6 +631,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/amd64-solaris/Makefile.in b/none/tests/amd64-solaris/Makefile.in
-index 6d942c7..a86893a 100644
---- a/none/tests/amd64-solaris/Makefile.in
-+++ b/none/tests/amd64-solaris/Makefile.in
-@@ -583,6 +583,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -630,6 +636,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/amd64/Makefile.in b/none/tests/amd64/Makefile.in
-index 5f37f72..e1bcf12 100644
---- a/none/tests/amd64/Makefile.in
-+++ b/none/tests/amd64/Makefile.in
-@@ -913,6 +913,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -960,6 +966,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/arm/Makefile.in b/none/tests/arm/Makefile.in
-index ad8ba1a..f17f02f 100644
---- a/none/tests/arm/Makefile.in
-+++ b/none/tests/arm/Makefile.in
-@@ -680,6 +680,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -727,6 +733,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/arm64/Makefile.in b/none/tests/arm64/Makefile.in
-index 2ece958..652d21b 100644
---- a/none/tests/arm64/Makefile.in
-+++ b/none/tests/arm64/Makefile.in
-@@ -635,6 +635,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -682,6 +688,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/darwin/Makefile.in b/none/tests/darwin/Makefile.in
-index ed42225..9818e4b 100644
---- a/none/tests/darwin/Makefile.in
-+++ b/none/tests/darwin/Makefile.in
-@@ -583,6 +583,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
+diff --git a/none/tests/filter_fdleak b/none/tests/filter_fdleak
+index 72923aa..da6453b 100755
+--- a/none/tests/filter_fdleak
++++ b/none/tests/filter_fdleak
+@@ -46,8 +46,9 @@ sed "s/by 0x........: (below main)/by 0x........: main/" |
+ sed "s/by 0x........: main (.*)/by 0x........: main/" |
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -630,6 +636,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/freebsd/Makefile.in b/none/tests/freebsd/Makefile.in
-index 077b910..59d4d05 100644
---- a/none/tests/freebsd/Makefile.in
-+++ b/none/tests/freebsd/Makefile.in
-@@ -617,6 +617,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -664,6 +670,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
+ # With glibc debuginfo installed we might see syscall-template.S,
+-# dup2.c close.c or creat64.c
++# dup2.c close.c creat64.c or write.c
+ perl -p -e "s/\(syscall-template.S:[0-9]*\)/(in \/...libc...)/" |
+ perl -p -e "s/\(close.c:[0-9]*\)/(in \/...libc...)/" |
+ perl -p -e "s/\(creat(?:64)?.c:[0-9]*\)/(in \/...libc...)/" |
+-perl -p -e "s/\(dup2.c:[0-9]*\)/(in \/...libc...)/"
++perl -p -e "s/\(dup2.c:[0-9]*\)/(in \/...libc...)/" |
++perl -p -e "s/\(write.c:[0-9]*\)/(in \/...libc...)/"
diff --git a/none/tests/libvex_test.c b/none/tests/libvex_test.c
index 5b57a4c..3080ce6 100644
--- a/none/tests/libvex_test.c
@@ -39810,31 +43189,6 @@ index 5b57a4c..3080ce6 100644
vta.arch_host = va;
vta.archinfo_host.endness = arch_endness (vta.arch_host);
vta.archinfo_host.hwcaps = arch_hwcaps (vta.arch_host);
-diff --git a/none/tests/linux/Makefile.in b/none/tests/linux/Makefile.in
-index 38d0563..8dd49c1 100644
---- a/none/tests/linux/Makefile.in
-+++ b/none/tests/linux/Makefile.in
-@@ -625,6 +625,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -672,6 +678,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
diff --git a/none/tests/loongarch64/Makefile.am b/none/tests/loongarch64/Makefile.am
new file mode 100644
index 0000000..01ec3e6
@@ -101972,361 +105326,11 @@ index 0000000..2b32ff1
+prereq: ../../../tests/loongarch64_features lasx
+prog: vector256
+vgopts: -q
-diff --git a/none/tests/mips32/Makefile.in b/none/tests/mips32/Makefile.in
-index 6ed6e3a..1bb4622 100644
---- a/none/tests/mips32/Makefile.in
-+++ b/none/tests/mips32/Makefile.in
-@@ -742,6 +742,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -789,6 +795,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/mips64/Makefile.in b/none/tests/mips64/Makefile.in
-index de13b52..e0a325b 100644
---- a/none/tests/mips64/Makefile.in
-+++ b/none/tests/mips64/Makefile.in
-@@ -813,6 +813,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -860,6 +866,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/nanomips/Makefile.in b/none/tests/nanomips/Makefile.in
-index 3bf14c7..7d38dd9 100644
---- a/none/tests/nanomips/Makefile.in
-+++ b/none/tests/nanomips/Makefile.in
-@@ -607,6 +607,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -654,6 +660,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/ppc32/Makefile.in b/none/tests/ppc32/Makefile.in
-index 6e855d4..0c5fc01 100644
---- a/none/tests/ppc32/Makefile.in
-+++ b/none/tests/ppc32/Makefile.in
-@@ -742,6 +742,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -789,6 +795,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/ppc64/Makefile.in b/none/tests/ppc64/Makefile.in
-index e9e4390..43ac01f 100644
---- a/none/tests/ppc64/Makefile.in
-+++ b/none/tests/ppc64/Makefile.in
-@@ -845,6 +845,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -892,6 +898,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/s390x/Makefile.in b/none/tests/s390x/Makefile.in
-index b90cb39..72dce45 100644
---- a/none/tests/s390x/Makefile.in
-+++ b/none/tests/s390x/Makefile.in
-@@ -1152,6 +1152,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -1199,6 +1205,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/scripts/Makefile.in b/none/tests/scripts/Makefile.in
-index e032753..95567b7 100644
---- a/none/tests/scripts/Makefile.in
-+++ b/none/tests/scripts/Makefile.in
-@@ -529,6 +529,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -576,6 +582,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/solaris/Makefile.in b/none/tests/solaris/Makefile.in
-index 46f5282..e1f441e 100644
---- a/none/tests/solaris/Makefile.in
-+++ b/none/tests/solaris/Makefile.in
-@@ -673,6 +673,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -720,6 +726,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/x86-darwin/Makefile.in b/none/tests/x86-darwin/Makefile.in
-index 6b943b3..2bc0b24 100644
---- a/none/tests/x86-darwin/Makefile.in
-+++ b/none/tests/x86-darwin/Makefile.in
-@@ -574,6 +574,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -621,6 +627,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/x86-freebsd/Makefile.in b/none/tests/x86-freebsd/Makefile.in
-index 58e1161..38d9646 100644
---- a/none/tests/x86-freebsd/Makefile.in
-+++ b/none/tests/x86-freebsd/Makefile.in
-@@ -566,6 +566,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -613,6 +619,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/x86-linux/Makefile.in b/none/tests/x86-linux/Makefile.in
-index 0c55ea2..2d79442 100644
---- a/none/tests/x86-linux/Makefile.in
-+++ b/none/tests/x86-linux/Makefile.in
-@@ -588,6 +588,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -635,6 +641,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/x86-solaris/Makefile.in b/none/tests/x86-solaris/Makefile.in
-index a008c19..f4c7fd3 100644
---- a/none/tests/x86-solaris/Makefile.in
-+++ b/none/tests/x86-solaris/Makefile.in
-@@ -582,6 +582,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -629,6 +635,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/none/tests/x86/Makefile.in b/none/tests/x86/Makefile.in
-index ead5ce4..c43ae96 100644
---- a/none/tests/x86/Makefile.in
-+++ b/none/tests/x86/Makefile.in
-@@ -813,6 +813,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -860,6 +866,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-diff --git a/perf/Makefile.in b/perf/Makefile.in
-index aa93d3b..5809ff6 100644
---- a/perf/Makefile.in
-+++ b/perf/Makefile.in
-@@ -616,6 +616,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -663,6 +669,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
diff --git a/tests/Makefile.am b/tests/Makefile.am
-index 916e508..e21f68b 100644
+index efe3546..778cd99 100644
--- a/tests/Makefile.am
+++ b/tests/Makefile.am
-@@ -52,7 +52,8 @@ check_PROGRAMS = \
+@@ -55,7 +55,8 @@ check_PROGRAMS = \
power_insn_available \
is_ppc64_BE \
min_power_isa \
@@ -102336,114 +105340,8 @@ index 916e508..e21f68b 100644
AM_CFLAGS += $(AM_FLAG_M3264_PRI)
-diff --git a/tests/Makefile.in b/tests/Makefile.in
-index bf7d5a1..846b98c 100644
---- a/tests/Makefile.in
-+++ b/tests/Makefile.in
-@@ -129,7 +129,8 @@ check_PROGRAMS = arch_test$(EXEEXT) os_test$(EXEEXT) \
- libc_test$(EXEEXT) true$(EXEEXT) x86_amd64_features$(EXEEXT) \
- s390x_features$(EXEEXT) mips_features$(EXEEXT) \
- power_insn_available$(EXEEXT) is_ppc64_BE$(EXEEXT) \
-- min_power_isa$(EXEEXT) arm64_features$(EXEEXT)
-+ min_power_isa$(EXEEXT) arm64_features$(EXEEXT) \
-+ loongarch64_features$(EXEEXT)
- subdir = tests
- ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
- am__aclocal_m4_deps = $(top_srcdir)/configure.ac
-@@ -153,6 +154,9 @@ is_ppc64_BE_LDADD = $(LDADD)
- libc_test_SOURCES = libc_test.c
- libc_test_OBJECTS = libc_test.$(OBJEXT)
- libc_test_LDADD = $(LDADD)
-+loongarch64_features_SOURCES = loongarch64_features.c
-+loongarch64_features_OBJECTS = loongarch64_features.$(OBJEXT)
-+loongarch64_features_LDADD = $(LDADD)
- min_power_isa_SOURCES = min_power_isa.c
- min_power_isa_OBJECTS = min_power_isa-min_power_isa.$(OBJEXT)
- min_power_isa_LDADD = $(LDADD)
-@@ -197,7 +201,7 @@ depcomp = $(SHELL) $(top_srcdir)/depcomp
- am__maybe_remake_depfiles = depfiles
- am__depfiles_remade = ./$(DEPDIR)/arch_test.Po \
- ./$(DEPDIR)/arm64_features.Po ./$(DEPDIR)/is_ppc64_BE.Po \
-- ./$(DEPDIR)/libc_test.Po \
-+ ./$(DEPDIR)/libc_test.Po ./$(DEPDIR)/loongarch64_features.Po \
- ./$(DEPDIR)/min_power_isa-min_power_isa.Po \
- ./$(DEPDIR)/mips_features.Po ./$(DEPDIR)/os_test.Po \
- ./$(DEPDIR)/power_insn_available.Po \
-@@ -221,12 +225,12 @@ am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
- am__v_CCLD_0 = @echo " CCLD " $@;
- am__v_CCLD_1 =
- SOURCES = arch_test.c arm64_features.c is_ppc64_BE.c libc_test.c \
-- min_power_isa.c mips_features.c os_test.c \
-- power_insn_available.c s390x_features.c true.c \
-+ loongarch64_features.c min_power_isa.c mips_features.c \
-+ os_test.c power_insn_available.c s390x_features.c true.c \
- x86_amd64_features.c
- DIST_SOURCES = arch_test.c arm64_features.c is_ppc64_BE.c libc_test.c \
-- min_power_isa.c mips_features.c os_test.c \
-- power_insn_available.c s390x_features.c true.c \
-+ loongarch64_features.c min_power_isa.c mips_features.c \
-+ os_test.c power_insn_available.c s390x_features.c true.c \
- x86_amd64_features.c
- am__can_run_installinfo = \
- case $$AM_UPDATE_INFO_DIR in \
-@@ -626,6 +630,12 @@ AM_CFLAGS_PSO_MIPS64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
- $(AM_CFLAGS_PSO_BASE)
-
- AM_CCASFLAGS_MIPS64_LINUX = @FLAG_M64@ -g
-+AM_FLAG_M3264_LOONGARCH64_LINUX = @FLAG_M64@
-+AM_CFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE)
-+AM_CFLAGS_PSO_LOONGARCH64_LINUX = @FLAG_M64@ $(AM_CFLAGS_BASE) \
-+ $(AM_CFLAGS_PSO_BASE)
-+
-+AM_CCASFLAGS_LOONGARCH64_LINUX = @FLAG_M64@ -g
- AM_FLAG_M3264_X86_SOLARIS = @FLAG_M32@
- AM_CFLAGS_X86_SOLARIS = @FLAG_M32@ @PREFERRED_STACK_BOUNDARY_2@ \
- $(AM_CFLAGS_BASE) -fomit-frame-pointer @SOLARIS_UNDEF_LARGESOURCE@
-@@ -673,6 +683,7 @@ PRELOAD_LDFLAGS_S390X_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_MIPS32_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_NANOMIPS_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M32@
- PRELOAD_LDFLAGS_MIPS64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
-+PRELOAD_LDFLAGS_LOONGARCH64_LINUX = $(PRELOAD_LDFLAGS_COMMON_LINUX) @FLAG_M64@
- PRELOAD_LDFLAGS_X86_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M32@
- PRELOAD_LDFLAGS_AMD64_SOLARIS = $(PRELOAD_LDFLAGS_COMMON_SOLARIS) @FLAG_M64@
- AM_CPPFLAGS = -I$(top_srcdir) -I$(top_srcdir)/include \
-@@ -785,6 +796,10 @@ libc_test$(EXEEXT): $(libc_test_OBJECTS) $(libc_test_DEPENDENCIES) $(EXTRA_libc_
- @rm -f libc_test$(EXEEXT)
- $(AM_V_CCLD)$(LINK) $(libc_test_OBJECTS) $(libc_test_LDADD) $(LIBS)
-
-+loongarch64_features$(EXEEXT): $(loongarch64_features_OBJECTS) $(loongarch64_features_DEPENDENCIES) $(EXTRA_loongarch64_features_DEPENDENCIES)
-+ @rm -f loongarch64_features$(EXEEXT)
-+ $(AM_V_CCLD)$(LINK) $(loongarch64_features_OBJECTS) $(loongarch64_features_LDADD) $(LIBS)
-+
- min_power_isa$(EXEEXT): $(min_power_isa_OBJECTS) $(min_power_isa_DEPENDENCIES) $(EXTRA_min_power_isa_DEPENDENCIES)
- @rm -f min_power_isa$(EXEEXT)
- $(AM_V_CCLD)$(min_power_isa_LINK) $(min_power_isa_OBJECTS) $(min_power_isa_LDADD) $(LIBS)
-@@ -823,6 +838,7 @@ distclean-compile:
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/arm64_features.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/is_ppc64_BE.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libc_test.Po@am__quote@ # am--include-marker
-+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/loongarch64_features.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/min_power_isa-min_power_isa.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/mips_features.Po@am__quote@ # am--include-marker
- @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/os_test.Po@am__quote@ # am--include-marker
-@@ -1010,6 +1026,7 @@ distclean: distclean-am
- -rm -f ./$(DEPDIR)/arm64_features.Po
- -rm -f ./$(DEPDIR)/is_ppc64_BE.Po
- -rm -f ./$(DEPDIR)/libc_test.Po
-+ -rm -f ./$(DEPDIR)/loongarch64_features.Po
- -rm -f ./$(DEPDIR)/min_power_isa-min_power_isa.Po
- -rm -f ./$(DEPDIR)/mips_features.Po
- -rm -f ./$(DEPDIR)/os_test.Po
-@@ -1066,6 +1083,7 @@ maintainer-clean: maintainer-clean-am
- -rm -f ./$(DEPDIR)/arm64_features.Po
- -rm -f ./$(DEPDIR)/is_ppc64_BE.Po
- -rm -f ./$(DEPDIR)/libc_test.Po
-+ -rm -f ./$(DEPDIR)/loongarch64_features.Po
- -rm -f ./$(DEPDIR)/min_power_isa-min_power_isa.Po
- -rm -f ./$(DEPDIR)/mips_features.Po
- -rm -f ./$(DEPDIR)/os_test.Po
diff --git a/tests/arch_test.c b/tests/arch_test.c
-index 37cc1bc..97b6bc7 100644
+index 4dbb8ca..322df71 100644
--- a/tests/arch_test.c
+++ b/tests/arch_test.c
@@ -34,6 +34,7 @@ char* all_archs[] = {
@@ -102565,5 +105463,5 @@ index c23a4f6..a1eaf8f 100644
all_platforms="$all_platforms x86-solaris amd64-solaris"
all_platforms="$all_platforms x86-freebsd amd64-freebsd"
--
-2.33.0
+2.41.0
diff --git a/valgrind-3.22.0-fchmodat2.patch b/valgrind-3.22.0-fchmodat2.patch
deleted file mode 100644
index b1ba313b1805cd41e42f1b833ea139d5de15cd95..0000000000000000000000000000000000000000
--- a/valgrind-3.22.0-fchmodat2.patch
+++ /dev/null
@@ -1,206 +0,0 @@
-From a43e62dddcf51ec6578a90c5988a41e856b44b05 Mon Sep 17 00:00:00 2001
-From: Mark Wielaard
-Date: Sat, 18 Nov 2023 21:17:02 +0100
-Subject: [PATCH] Add fchmodat2 syscall on linux
-
-fchmodat2 is a new syscall on linux 6.6. It is a variant of fchmodat
-that takes an extra flags argument.
-
-https://bugs.kde.org/show_bug.cgi?id=477198
-
-(cherry picked from commit 372d09fd9a8d76847c81092ebff71c80fd6c145d)
----
- NEWS | 1 +
- coregrind/m_syswrap/priv_syswrap-linux.h | 3 +++
- coregrind/m_syswrap/syswrap-amd64-linux.c | 2 ++
- coregrind/m_syswrap/syswrap-arm-linux.c | 2 ++
- coregrind/m_syswrap/syswrap-arm64-linux.c | 2 ++
- coregrind/m_syswrap/syswrap-linux.c | 11 +++++++++++
- coregrind/m_syswrap/syswrap-mips32-linux.c | 2 ++
- coregrind/m_syswrap/syswrap-mips64-linux.c | 1 +
- coregrind/m_syswrap/syswrap-nanomips-linux.c | 1 +
- coregrind/m_syswrap/syswrap-ppc32-linux.c | 2 ++
- coregrind/m_syswrap/syswrap-ppc64-linux.c | 2 ++
- coregrind/m_syswrap/syswrap-s390x-linux.c | 2 ++
- coregrind/m_syswrap/syswrap-x86-linux.c | 2 ++
- include/vki/vki-scnums-shared-linux.h | 2 ++
- 14 files changed, 35 insertions(+)
-
-diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h
-index 7c9decf5a..798c456c9 100644
---- a/coregrind/m_syswrap/priv_syswrap-linux.h
-+++ b/coregrind/m_syswrap/priv_syswrap-linux.h
-@@ -331,6 +331,9 @@ DECL_TEMPLATE(linux, sys_openat2);
- // Linux-specific (new in Linux 5.14)
- DECL_TEMPLATE(linux, sys_memfd_secret);
-
-+// Since Linux 6.6
-+DECL_TEMPLATE(linux, sys_fchmodat2);
-+
- /* ---------------------------------------------------------------------
- Wrappers for sockets and ipc-ery. These are split into standalone
- procedures because x86-linux hides them inside multiplexors
-diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c
-index 008600798..fe17d118b 100644
---- a/coregrind/m_syswrap/syswrap-amd64-linux.c
-+++ b/coregrind/m_syswrap/syswrap-amd64-linux.c
-@@ -886,6 +886,8 @@ static SyscallTableEntry syscall_table[] = {
- LINXY(__NR_epoll_pwait2, sys_epoll_pwait2), // 441
-
- LINXY(__NR_memfd_secret, sys_memfd_secret), // 447
-+
-+ LINX_(__NR_fchmodat2, sys_fchmodat2), // 452
- };
-
- SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )
-diff --git a/coregrind/m_syswrap/syswrap-arm-linux.c b/coregrind/m_syswrap/syswrap-arm-linux.c
-index 9a7a1e0d2..811931d3b 100644
---- a/coregrind/m_syswrap/syswrap-arm-linux.c
-+++ b/coregrind/m_syswrap/syswrap-arm-linux.c
-@@ -1059,6 +1059,8 @@ static SyscallTableEntry syscall_main_table[] = {
- LINX_(__NR_faccessat2, sys_faccessat2), // 439
-
- LINXY(__NR_epoll_pwait2, sys_epoll_pwait2), // 441
-+
-+ LINX_(__NR_fchmodat2, sys_fchmodat2), // 452
- };
-
-
-diff --git a/coregrind/m_syswrap/syswrap-arm64-linux.c b/coregrind/m_syswrap/syswrap-arm64-linux.c
-index 6af7bab83..3307bc2ca 100644
---- a/coregrind/m_syswrap/syswrap-arm64-linux.c
-+++ b/coregrind/m_syswrap/syswrap-arm64-linux.c
-@@ -840,6 +840,8 @@ static SyscallTableEntry syscall_main_table[] = {
- LINXY(__NR_epoll_pwait2, sys_epoll_pwait2), // 441
-
- LINXY(__NR_memfd_secret, sys_memfd_secret), // 447
-+
-+ LINX_(__NR_fchmodat2, sys_fchmodat2), // 452
- };
-
-
-diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
-index d571fc327..efa47f2e6 100644
---- a/coregrind/m_syswrap/syswrap-linux.c
-+++ b/coregrind/m_syswrap/syswrap-linux.c
-@@ -6059,6 +6059,17 @@ PRE(sys_fchmodat)
- PRE_MEM_RASCIIZ( "fchmodat(path)", ARG2 );
- }
-
-+PRE(sys_fchmodat2)
-+{
-+ PRINT("sys_fchmodat2 ( %ld, %#" FMT_REGWORD "x(%s), %" FMT_REGWORD "u, %"
-+ FMT_REGWORD "u )",
-+ SARG1, ARG2, (HChar*)(Addr)ARG2, ARG3, ARG4);
-+ PRE_REG_READ4(long, "fchmodat2",
-+ int, dfd, const char *, path, vki_mode_t, mode,
-+ unsigned int, flags);
-+ PRE_MEM_RASCIIZ( "fchmodat2(pathname)", ARG2 );
-+}
-+
- PRE(sys_faccessat)
- {
- PRINT("sys_faccessat ( %ld, %#" FMT_REGWORD "x(%s), %ld )",
-diff --git a/coregrind/m_syswrap/syswrap-mips32-linux.c b/coregrind/m_syswrap/syswrap-mips32-linux.c
-index 6268a00dd..74a1f6eac 100644
---- a/coregrind/m_syswrap/syswrap-mips32-linux.c
-+++ b/coregrind/m_syswrap/syswrap-mips32-linux.c
-@@ -1143,6 +1143,8 @@ static SyscallTableEntry syscall_main_table[] = {
- LINX_ (__NR_faccessat2, sys_faccessat2), // 439
-
- LINXY(__NR_epoll_pwait2, sys_epoll_pwait2), // 441
-+
-+ LINX_(__NR_fchmodat2, sys_fchmodat2), // 452
- };
-
- SyscallTableEntry* ML_(get_linux_syscall_entry) (UInt sysno)
-diff --git a/coregrind/m_syswrap/syswrap-mips64-linux.c b/coregrind/m_syswrap/syswrap-mips64-linux.c
-index 6cdf25893..4e8508b7a 100644
---- a/coregrind/m_syswrap/syswrap-mips64-linux.c
-+++ b/coregrind/m_syswrap/syswrap-mips64-linux.c
-@@ -820,6 +820,7 @@ static SyscallTableEntry syscall_main_table[] = {
- LINXY (__NR_close_range, sys_close_range),
- LINX_ (__NR_faccessat2, sys_faccessat2),
- LINXY(__NR_epoll_pwait2, sys_epoll_pwait2),
-+ LINX_ (__NR_fchmodat2, sys_fchmodat2),
- };
-
- SyscallTableEntry * ML_(get_linux_syscall_entry) ( UInt sysno )
-diff --git a/coregrind/m_syswrap/syswrap-nanomips-linux.c b/coregrind/m_syswrap/syswrap-nanomips-linux.c
-index d724cde74..7859900c1 100644
---- a/coregrind/m_syswrap/syswrap-nanomips-linux.c
-+++ b/coregrind/m_syswrap/syswrap-nanomips-linux.c
-@@ -829,6 +829,7 @@ static SyscallTableEntry syscall_main_table[] = {
- LINXY (__NR_close_range, sys_close_range),
- LINX_ (__NR_faccessat2, sys_faccessat2),
- LINXY (__NR_epoll_pwait2, sys_epoll_pwait2),
-+ LINX_ (__NR_fchmodat2, sys_fchmodat2),
- };
-
- SyscallTableEntry* ML_(get_linux_syscall_entry) (UInt sysno)
-diff --git a/coregrind/m_syswrap/syswrap-ppc32-linux.c b/coregrind/m_syswrap/syswrap-ppc32-linux.c
-index c0cfef235..1e19116ee 100644
---- a/coregrind/m_syswrap/syswrap-ppc32-linux.c
-+++ b/coregrind/m_syswrap/syswrap-ppc32-linux.c
-@@ -1063,6 +1063,8 @@ static SyscallTableEntry syscall_table[] = {
- LINX_(__NR_faccessat2, sys_faccessat2), // 439
-
- LINXY (__NR_epoll_pwait2, sys_epoll_pwait2), // 441
-+
-+ LINX_ (__NR_fchmodat2, sys_fchmodat2), // 452
- };
-
- SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )
-diff --git a/coregrind/m_syswrap/syswrap-ppc64-linux.c b/coregrind/m_syswrap/syswrap-ppc64-linux.c
-index f5976f30c..1097212a4 100644
---- a/coregrind/m_syswrap/syswrap-ppc64-linux.c
-+++ b/coregrind/m_syswrap/syswrap-ppc64-linux.c
-@@ -1032,6 +1032,8 @@ static SyscallTableEntry syscall_table[] = {
- LINX_(__NR_faccessat2, sys_faccessat2), // 439
-
- LINXY (__NR_epoll_pwait2, sys_epoll_pwait2), // 441
-+
-+ LINX_ (__NR_fchmodat2, sys_fchmodat2), // 452
- };
-
- SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )
-diff --git a/coregrind/m_syswrap/syswrap-s390x-linux.c b/coregrind/m_syswrap/syswrap-s390x-linux.c
-index afba154e7..3588672c7 100644
---- a/coregrind/m_syswrap/syswrap-s390x-linux.c
-+++ b/coregrind/m_syswrap/syswrap-s390x-linux.c
-@@ -873,6 +873,8 @@ static SyscallTableEntry syscall_table[] = {
- LINX_(__NR_faccessat2, sys_faccessat2), // 439
-
- LINXY(__NR_epoll_pwait2, sys_epoll_pwait2), // 441
-+
-+ LINX_ (__NR_fchmodat2, sys_fchmodat2), // 452
- };
-
- SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )
-diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c
-index da4fd8fa2..58badc6b0 100644
---- a/coregrind/m_syswrap/syswrap-x86-linux.c
-+++ b/coregrind/m_syswrap/syswrap-x86-linux.c
-@@ -1658,6 +1658,8 @@ static SyscallTableEntry syscall_table[] = {
- LINXY(__NR_epoll_pwait2, sys_epoll_pwait2), // 441
-
- LINXY(__NR_memfd_secret, sys_memfd_secret), // 447
-+
-+ LINX_(__NR_fchmodat2, sys_fchmodat2), // 452
- };
-
- SyscallTableEntry* ML_(get_linux_syscall_entry) ( UInt sysno )
-diff --git a/include/vki/vki-scnums-shared-linux.h b/include/vki/vki-scnums-shared-linux.h
-index 542382b53..a4cd87149 100644
---- a/include/vki/vki-scnums-shared-linux.h
-+++ b/include/vki/vki-scnums-shared-linux.h
-@@ -50,4 +50,6 @@
-
- #define __NR_memfd_secret 447
-
-+#define __NR_fchmodat2 452
-+
- #endif
---
-2.39.3
-
diff --git a/valgrind-3.22.0-rodata.patch b/valgrind-3.22.0-rodata.patch
deleted file mode 100644
index 47f31edebe292c87991213cafa49a5e2d62c0306..0000000000000000000000000000000000000000
--- a/valgrind-3.22.0-rodata.patch
+++ /dev/null
@@ -1,122 +0,0 @@
-commit 1d00e5ce0fb069911c4b525ec38289fb5d9021b0
-Author: Paul Floyd
-Date: Sat Nov 18 08:49:34 2023 +0100
-
- Bug 476548 - valgrind 3.22.0 fails on assertion when loading debuginfo file produced by mold
-
- (cherry picked from commit 9ea4ae66707a4dcc6f4328e11911652e4418c585)
-
-diff --git a/coregrind/m_debuginfo/image.c b/coregrind/m_debuginfo/image.c
-index 02e509071..445f95555 100644
---- a/coregrind/m_debuginfo/image.c
-+++ b/coregrind/m_debuginfo/image.c
-@@ -1221,6 +1221,20 @@ Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2)
- }
- }
-
-+Int ML_(img_strcmp_n)(DiImage* img, DiOffT off1, const HChar* str2, Word n)
-+{
-+ ensure_valid(img, off1, 1, "ML_(img_strcmp_c)");
-+ while (n) {
-+ UChar c1 = get(img, off1);
-+ UChar c2 = *(const UChar*)str2;
-+ if (c1 < c2) return -1;
-+ if (c1 > c2) return 1;
-+ if (c1 == 0) return 0;
-+ off1++; str2++; --n;
-+ }
-+ return 0;
-+}
-+
- UChar ML_(img_get_UChar)(DiImage* img, DiOffT offset)
- {
- ensure_valid(img, offset, 1, "ML_(img_get_UChar)");
-diff --git a/coregrind/m_debuginfo/priv_image.h b/coregrind/m_debuginfo/priv_image.h
-index a49846f14..c91e49f01 100644
---- a/coregrind/m_debuginfo/priv_image.h
-+++ b/coregrind/m_debuginfo/priv_image.h
-@@ -115,6 +115,10 @@ Int ML_(img_strcmp)(DiImage* img, DiOffT off1, DiOffT off2);
- cast to HChar before comparison. */
- Int ML_(img_strcmp_c)(DiImage* img, DiOffT off1, const HChar* str2);
-
-+/* Do strncmp of a C string in the image vs a normal one. Chars are
-+ cast to HChar before comparison. */
-+Int ML_(img_strcmp_n)(DiImage* img, DiOffT off1, const HChar* str2, Word n);
-+
- /* Do strlen of a C string in the image. */
- SizeT ML_(img_strlen)(DiImage* img, DiOffT off);
-
-diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c
-index fb64ed976..46f8c8343 100644
---- a/coregrind/m_debuginfo/readelf.c
-+++ b/coregrind/m_debuginfo/readelf.c
-@@ -2501,8 +2501,7 @@ Bool ML_(read_elf_object) ( struct _DebugInfo* di )
- di->rodata_avma += inrw1->bias;
- di->rodata_bias = inrw1->bias;
- di->rodata_debug_bias = inrw1->bias;
-- }
-- else {
-+ } else {
- BAD(".rodata"); /* should not happen? */
- }
- di->rodata_present = True;
-@@ -2977,6 +2976,46 @@ Bool ML_(read_elf_object) ( struct _DebugInfo* di )
- return retval;
- }
-
-+static void find_rodata(Word i, Word shnum, DiImage* dimg, struct _DebugInfo* di, DiOffT shdr_dioff,
-+ UWord shdr_dent_szB, DiOffT shdr_strtab_dioff, PtrdiffT rw_dbias)
-+{
-+ ElfXX_Shdr a_shdr;
-+ ElfXX_Shdr a_extra_shdr;
-+ ML_(img_get)(&a_shdr, dimg,
-+ INDEX_BIS(shdr_dioff, i, shdr_dent_szB),
-+ sizeof(a_shdr));
-+ if (di->rodata_present &&
-+ 0 == ML_(img_strcmp_c)(dimg, shdr_strtab_dioff
-+ + a_shdr.sh_name, ".rodata")) {
-+ Word sh_size = a_shdr.sh_size;
-+ Word j;
-+ Word next_addr = a_shdr.sh_addr + a_shdr.sh_size;
-+ for (j = i + 1; j < shnum; ++j) {
-+ ML_(img_get)(&a_extra_shdr, dimg,
-+ INDEX_BIS(shdr_dioff, j, shdr_dent_szB),
-+ sizeof(a_shdr));
-+ if (0 == ML_(img_strcmp_n)(dimg, shdr_strtab_dioff
-+ + a_extra_shdr.sh_name, ".rodata", 7)) {
-+ if (a_extra_shdr.sh_addr ==
-+ VG_ROUNDUP(next_addr, a_extra_shdr.sh_addralign)) {
-+ sh_size = VG_ROUNDUP(sh_size, a_extra_shdr.sh_addralign) + a_extra_shdr.sh_size;
-+ }
-+ next_addr = a_extra_shdr.sh_addr + a_extra_shdr.sh_size;
-+ } else {
-+ break;
-+ }
-+ }
-+ vg_assert(di->rodata_size == sh_size);
-+ vg_assert(di->rodata_avma + a_shdr.sh_addr + rw_dbias);
-+ di->rodata_debug_svma = a_shdr.sh_addr;
-+ di->rodata_debug_bias = di->rodata_bias +
-+ di->rodata_svma - di->rodata_debug_svma;
-+ TRACE_SYMTAB("acquiring .rodata debug svma = %#lx .. %#lx\n",
-+ di->rodata_debug_svma,
-+ di->rodata_debug_svma + di->rodata_size - 1);
-+ TRACE_SYMTAB("acquiring .rodata debug bias = %#lx\n", (UWord)di->rodata_debug_bias);
-+ }
-+}
- Bool ML_(read_elf_debug) ( struct _DebugInfo* di )
- {
- Word i, j;
-@@ -3391,7 +3430,11 @@ Bool ML_(read_elf_debug) ( struct _DebugInfo* di )
- FIND(text, rx)
- FIND(data, rw)
- FIND(sdata, rw)
-- FIND(rodata, rw)
-+ // https://bugs.kde.org/show_bug.cgi?id=476548
-+ // special handling for rodata as adjacent
-+ // rodata sections may have been merged in ML_(read_elf_object)
-+ //FIND(rodata, rw)
-+ find_rodata(i, ehdr_dimg.e_shnum, dimg, di, shdr_dioff, shdr_dent_szB, shdr_strtab_dioff, rw_dbias);
- FIND(bss, rw)
- FIND(sbss, rw)
-
diff --git a/valgrind-3.22.0-valgrind-monitor-python-re.patch b/valgrind-3.22.0-valgrind-monitor-python-re.patch
deleted file mode 100644
index 61d26cd660211a7675708c7354c4b4d8a269c0e2..0000000000000000000000000000000000000000
--- a/valgrind-3.22.0-valgrind-monitor-python-re.patch
+++ /dev/null
@@ -1,32 +0,0 @@
-commit 0fbfbe05028ad18efda786a256a2738d2c231ed4
-Author: Mark Wielaard
-Date: Fri Nov 17 13:31:52 2023 +0100
-
- valgrind-monitor.py regular expressions should use raw strings
-
- With python 3.12 gdb will produce the following SyntaxWarning when
- loading valgrind-monitor-def.py:
-
- /usr/share/gdb/auto-load/valgrind-monitor-def.py:214:
- SyntaxWarning: invalid escape sequence '\['
- if re.fullmatch("^0x[0123456789ABCDEFabcdef]+\[[^\[\]]+\]$", arg_str):
-
- In a future python version this will become an SyntaxError.
-
- Use a raw strings for the regular expression.
-
- https://bugs.kde.org/show_bug.cgi?id=476708
-
-diff --git a/coregrind/m_gdbserver/valgrind-monitor-def.py b/coregrind/m_gdbserver/valgrind-monitor-def.py
-index b4e7b992d..d74b1590c 100644
---- a/coregrind/m_gdbserver/valgrind-monitor-def.py
-+++ b/coregrind/m_gdbserver/valgrind-monitor-def.py
-@@ -211,7 +211,7 @@ class Valgrind_ADDR_LEN_opt(Valgrind_Command):
- For compatibility reason with the Valgrind gdbserver monitor command,
- we detect and accept usages such as 0x1234ABCD[10]."""
- def invoke(self, arg_str : str, from_tty : bool) -> None:
-- if re.fullmatch("^0x[0123456789ABCDEFabcdef]+\[[^\[\]]+\]$", arg_str):
-+ if re.fullmatch(r"^0x[0123456789ABCDEFabcdef]+\[[^\[\]]+\]$", arg_str):
- arg_str = arg_str.replace("[", " ")
- arg_str = arg_str.replace("]", " ")
- eval_execute_2(self, arg_str,
diff --git a/valgrind-3.22.0.tar.bz2 b/valgrind-3.24.0.tar.bz2
similarity index 64%
rename from valgrind-3.22.0.tar.bz2
rename to valgrind-3.24.0.tar.bz2
index 1ed54bd50d6c370f818eefd08a4c8f18efba7b62..ca58b33b9652a9fcedb85b32929d165c43337d8f 100644
Binary files a/valgrind-3.22.0.tar.bz2 and b/valgrind-3.24.0.tar.bz2 differ
diff --git a/valgrind.spec b/valgrind.spec
index e208d8cd5fcb472da0e9ca8f939cc618a34db933..0f5d5253c5d91dfb691fa13cbda5eea4590fe9bd 100644
--- a/valgrind.spec
+++ b/valgrind.spec
@@ -24,8 +24,8 @@
%endif
Name: valgrind
-Version: 3.22.0
-Release: 4
+Version: 3.24.0
+Release: 1
Epoch: 1
Summary: An instrumentation framework for building dynamic analysis tools
License: GPL-2.0-or-later
@@ -37,15 +37,6 @@ Patch2: valgrind-3.9.0-ldso-supp.patch
Patch3: Add-AArch64-clang-longjmp-support.patch
# Add LOONGARCH64 support
Patch4: Add-LOONGARCH64-Linux-support.patch
-# valgrind-monitor.py regular expressions should use raw strings
-# https://bugs.kde.org/show_bug.cgi?id=476708
-Patch5: valgrind-3.22.0-valgrind-monitor-python-re.patch
-# valgrind 3.22.0 fails on assertion when loading debuginfo
-# https://bugs.kde.org/show_bug.cgi?id=476548
-Patch6: valgrind-3.22.0-rodata.patch
-# Add fchmodat2 syscall on linux
-# https://bugs.kde.org/show_bug.cgi?id=477198
-Patch7: valgrind-3.22.0-fchmodat2.patch
BuildRequires: glibc glibc-devel gdb procps gcc-c++ perl(Getopt::Long)
BuildRequires: automake autoconf
@@ -120,6 +111,9 @@ popd
%{_mandir}/man1/*
%changelog
+* Fri Apr 11 2025 Ge Wang - 1:3.24.0-1
+- Upgrade to 3.24.0
+
* Tue Jan 14 2025 Ge Wang - 1:3.22.0-4
- Remove empty soft link file