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