diff --git a/.gitignore b/.gitignore
index 3a77629..0d362c8 100644
--- a/.gitignore
+++ b/.gitignore
@@ -38,3 +38,4 @@
 /valgrind-3.16.0.RC2.tar.bz2
 /valgrind-3.16.0.tar.bz2
 /valgrind-3.16.1.tar.bz2
+/valgrind-3.17.0.RC1.tar.bz2
diff --git a/sources b/sources
index 0d18846..eec672d 100644
--- a/sources
+++ b/sources
@@ -1 +1 @@
-SHA512 (valgrind-3.16.1.tar.bz2) = 2a4173efe1b6facdd2f5c5ee8ed006704168eba1813736fccc8191d60363afd96197512cf42037e65f18d4ddd49adc74a54c47210df216fba3c46bf68ef0f950
+SHA512 (valgrind-3.17.0.RC1.tar.bz2) = ef71f3fca24466e78bd8a137666722f06cc5744cda5ae608b96d69390a72839e4d7499293872eb797e1c9edbe13ca6cf6147b6eb2491bb455d6696180f9864b7
diff --git a/valgrind-3.16.0-pkglibexecdir.patch b/valgrind-3.16.0-pkglibexecdir.patch
deleted file mode 100644
index cd52729..0000000
--- a/valgrind-3.16.0-pkglibexecdir.patch
+++ /dev/null
@@ -1,117 +0,0 @@
-diff --git a/Makefile.all.am b/Makefile.all.am
-index 3786e34..1befef5 100644
---- a/Makefile.all.am
-+++ b/Makefile.all.am
-@@ -50,20 +50,20 @@ inplace-noinst_DSYMS: build-noinst_DSYMS
- 	done
- 
- # This is used by coregrind/Makefile.am and by <tool>/Makefile.am for doing
--# "make install".  It copies $(noinst_PROGRAMS) into $prefix/lib/valgrind/.
-+# "make install".  It copies $(noinst_PROGRAMS) into $prefix/libexec/valgrind/.
- # It needs to be depended on by an 'install-exec-local' rule.
- install-noinst_PROGRAMS: $(noinst_PROGRAMS)
--	$(mkinstalldirs) $(DESTDIR)$(pkglibdir); \
-+	$(mkinstalldirs) $(DESTDIR)$(pkglibexecdir); \
- 	for f in $(noinst_PROGRAMS); do \
--	  $(INSTALL_PROGRAM) $$f $(DESTDIR)$(pkglibdir); \
-+	  $(INSTALL_PROGRAM) $$f $(DESTDIR)$(pkglibexecdir); \
- 	done
- 
- # This is used by coregrind/Makefile.am and by <tool>/Makefile.am for doing
--# "make uninstall".  It removes $(noinst_PROGRAMS) from $prefix/lib/valgrind/.
-+# "make uninstall".  It removes $(noinst_PROGRAMS) from $prefix/libexec/valgrind/.
- # It needs to be depended on by an 'uninstall-local' rule.
- uninstall-noinst_PROGRAMS:
- 	for f in $(noinst_PROGRAMS); do \
--	  rm -f $(DESTDIR)$(pkglibdir)/$$f; \
-+	  rm -f $(DESTDIR)$(pkglibexecdir)/$$f; \
- 	done
- 
- # Similar to install-noinst_PROGRAMS.
-@@ -71,15 +71,15 @@ uninstall-noinst_PROGRAMS:
- # directories.  XXX: not sure whether the resulting permissions will be
- # correct when using 'cp -R'...
- install-noinst_DSYMS: build-noinst_DSYMS
--	$(mkinstalldirs) $(DESTDIR)$(pkglibdir); \
-+	$(mkinstalldirs) $(DESTDIR)$(pkglibexecdir); \
- 	for f in $(noinst_DSYMS); do \
--	  cp -R $$f.dSYM $(DESTDIR)$(pkglibdir); \
-+	  cp -R $$f.dSYM $(DESTDIR)$(pkglibexecdir); \
- 	done
- 
- # Similar to uninstall-noinst_PROGRAMS.
- uninstall-noinst_DSYMS:
- 	for f in $(noinst_DSYMS); do \
--	  rm -f $(DESTDIR)$(pkglibdir)/$$f.dSYM; \
-+	  rm -f $(DESTDIR)$(pkglibexecdir)/$$f.dSYM; \
- 	done
- 
- # This needs to be depended on by a 'clean-local' rule.
-diff --git a/Makefile.am b/Makefile.am
-index 242b38a..3b7c806 100644
---- a/Makefile.am
-+++ b/Makefile.am
-@@ -58,7 +58,7 @@ DEFAULT_SUPP_FILES = @DEFAULT_SUPP@
- # default.supp, as it is built from the base .supp files at compile-time.
- dist_noinst_DATA = $(SUPP_FILES)
- 
--vglibdir = $(pkglibdir)
-+vglibdir = $(pkglibexecdir)
- vglib_DATA = default.supp
- 
- pkgconfigdir = $(libdir)/pkgconfig
-diff --git a/coregrind/Makefile.am b/coregrind/Makefile.am
-index 94030fd..f09763a 100644
---- a/coregrind/Makefile.am
-+++ b/coregrind/Makefile.am
-@@ -11,12 +11,12 @@ include $(top_srcdir)/Makefile.all.am
- 
- AM_CPPFLAGS_@VGCONF_PLATFORM_PRI_CAPS@ += \
- 	-I$(top_srcdir)/coregrind \
--	-DVG_LIBDIR="\"$(pkglibdir)"\" \
-+	-DVG_LIBDIR="\"$(pkglibexecdir)"\" \
- 	-DVG_PLATFORM="\"@VGCONF_ARCH_PRI@-@VGCONF_OS@\""
- if VGCONF_HAVE_PLATFORM_SEC
- AM_CPPFLAGS_@VGCONF_PLATFORM_SEC_CAPS@ += \
- 	-I$(top_srcdir)/coregrind \
--	-DVG_LIBDIR="\"$(pkglibdir)"\" \
-+	-DVG_LIBDIR="\"$(pkglibexecdir)"\" \
- 	-DVG_PLATFORM="\"@VGCONF_ARCH_SEC@-@VGCONF_OS@\""
- endif
- 
-@@ -714,7 +714,7 @@ GDBSERVER_XML_FILES = \
- 	m_gdbserver/mips64-fpu.xml
- 
- # so as to make sure these get copied into the install tree
--vglibdir = $(pkglibdir)
-+vglibdir = $(pkglibexecdir)
- vglib_DATA  = $(GDBSERVER_XML_FILES)
- 
- # so as to make sure these get copied into the tarball
-diff --git a/mpi/Makefile.am b/mpi/Makefile.am
-index 7ad9a25..471fee0 100644
---- a/mpi/Makefile.am
-+++ b/mpi/Makefile.am
-@@ -18,16 +18,18 @@ EXTRA_DIST = \
- # libmpiwrap-<platform>.so
- #----------------------------------------------------------------------------
- 
--noinst_PROGRAMS  =
-+# These are really real libraries, so they should go to libdir, not libexec.
-+mpidir = $(pkglibdir)
-+mpi_PROGRAMS  =
- if BUILD_MPIWRAP_PRI
--noinst_PROGRAMS += libmpiwrap-@VGCONF_ARCH_PRI@-@VGCONF_OS@.so
-+mpi_PROGRAMS += libmpiwrap-@VGCONF_ARCH_PRI@-@VGCONF_OS@.so
- endif
- if BUILD_MPIWRAP_SEC
--noinst_PROGRAMS += libmpiwrap-@VGCONF_ARCH_SEC@-@VGCONF_OS@.so
-+mpi_PROGRAMS += libmpiwrap-@VGCONF_ARCH_SEC@-@VGCONF_OS@.so
- endif
- 
- if VGCONF_OS_IS_DARWIN
--noinst_DSYMS = $(noinst_PROGRAMS)
-+mpi_DSYMS = $(mpi_PROGRAMS)
- endif
- 
- 
diff --git a/valgrind-3.16.0-shmctl.patch b/valgrind-3.16.0-shmctl.patch
deleted file mode 100644
index 16d9d7c..0000000
--- a/valgrind-3.16.0-shmctl.patch
+++ /dev/null
@@ -1,111 +0,0 @@
-commit 232893d9b3c7d79d018db7f303aee219161a86d0
-Author: Anssi Hannula <anssi.hannula@bitwise.fi>
-Date:   Thu Jul 2 14:49:17 2020 +0300
-
-    Fix shmat() on Linux nanomips and x86
-    
-    On Linux, there are two variants of the direct shmctl syscall:
-    - sys_shmctl: always uses shmid64_ds, does not accept IPC_64
-    - sys_old_shmctl: uses shmid_ds or shmid64_ds depending on IPC_64
-    
-    The following Linux ABIs have the sys_old_shmctl variant:
-      alpha, arm, microblaze, mips n32/n64, xtensa
-    
-    Other ABIs (and future ABIs) have the sys_shmctl variant, including ABIs
-    that only got sys_shmctl in Linux 5.1 (such as x86, mips o32, ppc,
-    s390x).
-    
-    We incorrectly assume the sys_old_shmctl variant on nanomips and x86,
-    causing shmat() calls under valgrind to fail with EINVAL.
-    
-    On x86, the issue was previously masked by the non-existence of
-    __NR_shmctl until a9fc7bceeb0b0 ("Update Linux x86 system call number
-    definitions") in 2019.
-    
-    On mips o32, ppc, and s390x this issue is not visible as our headers do
-    not have __NR_shmctl for those ABIs (396 since Linux 5.1).
-    
-    Fix the issue by correcting the preprocessor check in get_shm_size() to
-    only assume the old Linux sys_old_shmctl behavior on the specific
-    affected platforms.
-    
-    Also, exclude the use of direct shmctl entirely on Linux x86, ppc,
-    mips o32, s390x in order to keep compatibility with pre-5.1 kernel
-    versions that did not yet have direct shmctl for those ABIs.
-    This currently only has actual effect on x86 as only it has __NR_shmctl
-    in our headers.
-    
-    Fixes tests mremap4, mremap5, mremap6.
-    
-    https://bugs.kde.org/show_bug.cgi?id=410743
-
-diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c
-index badb8c778..7d4b385a3 100644
---- a/coregrind/m_syswrap/syswrap-generic.c
-+++ b/coregrind/m_syswrap/syswrap-generic.c
-@@ -1960,11 +1960,27 @@ ML_(generic_POST_sys_semctl) ( ThreadId tid,
- static
- SizeT get_shm_size ( Int shmid )
- {
--#if defined(__NR_shmctl)
-+   /*
-+    * The excluded platforms below gained direct shmctl in Linux 5.1. Keep
-+    * using ipc-multiplexed shmctl to keep compatibility with older kernel
-+    * versions.
-+    */
-+#if defined(__NR_shmctl) && \
-+    !defined(VGP_x86_linux) && !defined(VGP_mips32_linux) && \
-+    !defined(VGP_ppc32_linux) && !defined(VGP_ppc64be_linux) && \
-+    !defined(VGP_ppc64le_linux) && !defined(VGP_s390x_linux)
- #  ifdef VKI_IPC_64
-    struct vki_shmid64_ds buf;
--#    if defined(VGP_amd64_linux) || defined(VGP_arm64_linux)
--     /* See bug 222545 comment 7 */
-+     /*
-+      * On Linux, the following ABIs use old shmid_ds by default with direct
-+      * shmctl and require IPC_64 for shmid64_ds (i.e. the direct syscall is
-+      * mapped to sys_old_shmctl):
-+      *    alpha, arm, microblaze, mips n32/n64, xtensa
-+      * Other Linux ABIs use shmid64_ds by default and do not recognize IPC_64
-+      * with the direct shmctl syscall (but still recognize it for the
-+      * ipc-multiplexed version if that exists for the ABI).
-+      */
-+#    if defined(VGO_linux) && !defined(VGP_arm_linux) && !defined(VGP_mips64_linux)
-      SysRes __res = VG_(do_syscall3)(__NR_shmctl, shmid, 
-                                      VKI_IPC_STAT, (UWord)&buf);
- #    else
-commit 620dba22be67dea2ada9fa825b2ed4d61774af82
-Author: Mark Wielaard <mark@klomp.org>
-Date:   Wed Feb 3 16:56:14 2021 +0100
-
-    syswrap-linux.c: Pass implicit VKI_IPC_64 for shmctl also on arm64.
-    
-    The shmctl syscall on amd64, arm64 and riscv (but we don't have a port
-    for that last one) always use IPC_64. Explicitly pass it to the generic
-    PRE/POST handlers so they select the correct (64bit) data structures on
-    those architectures.
-    
-    https://bugzilla.redhat.com/show_bug.cgi?id=1909548
-
-diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
-index 328e02a98..52074149d 100644
---- a/coregrind/m_syswrap/syswrap-linux.c
-+++ b/coregrind/m_syswrap/syswrap-linux.c
-@@ -5127,7 +5127,7 @@ PRE(sys_shmctl)
-    PRINT("sys_shmctl ( %ld, %ld, %#" FMT_REGWORD "x )", SARG1, SARG2, ARG3);
-    PRE_REG_READ3(long, "shmctl",
-                  int, shmid, int, cmd, struct shmid_ds *, buf);
--#ifdef VGP_amd64_linux
-+#if defined(VGP_amd64_linux) || defined(VGP_arm64_linux)
-    ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2|VKI_IPC_64,ARG3);
- #else
-    ML_(generic_PRE_sys_shmctl)(tid, ARG1,ARG2,ARG3);
-@@ -5136,7 +5136,7 @@ PRE(sys_shmctl)
- 
- POST(sys_shmctl)
- {
--#ifdef VGP_amd64_linux
-+#if defined(VGP_amd64_linux) || defined(VGP_arm64_linux)
-    ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2|VKI_IPC_64,ARG3);
- #else
-    ML_(generic_POST_sys_shmctl)(tid, RES,ARG1,ARG2,ARG3);
diff --git a/valgrind-3.16.0-some-stack-protector.patch b/valgrind-3.16.0-some-stack-protector.patch
index bde2aa5..324c7d3 100644
--- a/valgrind-3.16.0-some-stack-protector.patch
+++ b/valgrind-3.16.0-some-stack-protector.patch
@@ -52,8 +52,8 @@ diff --git a/configure.ac b/configure.ac
 index f8c798b..ccc8f52 100755
 --- a/configure.ac
 +++ b/configure.ac
-@@ -2188,24 +2188,24 @@ AC_LANG(C)
- AC_SUBST(FLAG_FALIGNED_NEW)
+@@ -2352,24 +2352,24 @@
+ AM_CONDITIONAL([HAVE_ALIGNED_CXX_ALLOC], [test x$ac_have_aligned_cxx_alloc = xyes])
  
  # does this compiler support -fno-stack-protector ?
 -AC_MSG_CHECKING([if gcc accepts -fno-stack-protector])
diff --git a/valgrind-3.16.1-PPC64BE-lsw.patch b/valgrind-3.16.1-PPC64BE-lsw.patch
deleted file mode 100644
index 2a1e9c3..0000000
--- a/valgrind-3.16.1-PPC64BE-lsw.patch
+++ /dev/null
@@ -1,34 +0,0 @@
-diff --git a/none/tests/ppc64/ldst_multiple.vgtest b/none/tests/ppc64/ldst_multiple.vgtest
-index 87e668e09..22dd46c99 100644
---- a/none/tests/ppc64/ldst_multiple.vgtest
-+++ b/none/tests/ppc64/ldst_multiple.vgtest
-@@ -1 +1,2 @@
-+prereq: ../../../tests/is_ppc64_BE
- prog: ldst_multiple
---- valgrind-3.16.1/none/tests/ppc64/Makefile.am.orig	2020-10-18 20:43:34.579699246 +0200
-+++ valgrind-3.16.1/none/tests/ppc64/Makefile.am	2020-10-18 20:44:52.950198040 +0200
-@@ -54,17 +54,22 @@
- 
- check_PROGRAMS = \
- 	allexec \
--	lsw jm-insns round \
-+	jm-insns round \
- 	test_isa_2_06_part1 test_isa_2_06_part2 test_isa_2_06_part3 \
- 	test_dfp1 test_dfp2 test_dfp3 test_dfp4 test_dfp5 \
- 	test_isa_2_07_part1 test_isa_2_07_part2 \
- 	test_isa_3_0 \
- 	subnormal_test \
--	test_tm test_touch_tm ldst_multiple data-cache-instructions \
-+	test_tm test_touch_tm data-cache-instructions \
- 	power6_mf_gpr std_reg_imm \
- 	twi_tdi tw_td power6_bcmp
- 
- 
-+# lsw and ldst_multiple compile (and run) only on big endian.
-+if VGCONF_PLATFORMS_INCLUDE_PPC64BE_LINUX
-+check_PROGRAMS += lsw ldst_multiple
-+endif
-+
- AM_CFLAGS    += @FLAG_M64@
- AM_CXXFLAGS  += @FLAG_M64@
- AM_CCASFLAGS += @FLAG_M64@
diff --git a/valgrind-3.16.1-REX-prefix-JMP.patch b/valgrind-3.16.1-REX-prefix-JMP.patch
deleted file mode 100644
index f780fb1..0000000
--- a/valgrind-3.16.1-REX-prefix-JMP.patch
+++ /dev/null
@@ -1,38 +0,0 @@
-commit e2dec0ff9b1e071779bee2c4e6fc82f8194b1c1d
-Author: Mark Wielaard <mark@klomp.org>
-Date:   Sun Jul 26 21:17:23 2020 +0200
-
-    Handle REX prefixed JMP instruction.
-    
-    The NET Core runtime might generate a JMP with a REX prefix.
-    For Jv (32bit offset) and Jb (8bit offset) this is valid.
-    Prefixes that change operand size are ignored for such JMPs.
-    So remove the check for sz == 4 and force sz = 4 for Jv.
-    
-    https://bugs.kde.org/show_bug.cgi?id=422174
-
-diff --git a/VEX/priv/guest_amd64_toIR.c b/VEX/priv/guest_amd64_toIR.c
-index fadf47d41..7888132eb 100644
---- a/VEX/priv/guest_amd64_toIR.c
-+++ b/VEX/priv/guest_amd64_toIR.c
-@@ -21392,8 +21392,8 @@ Long dis_ESC_NONE (
- 
-    case 0xE9: /* Jv (jump, 16/32 offset) */
-       if (haveF3(pfx)) goto decode_failure;
--      if (sz != 4) 
--         goto decode_failure; /* JRS added 2004 July 11 */
-+      sz = 4; /* Prefixes that change operand size are ignored for this
-+                 instruction. Operand size is forced to 32bit. */
-       if (haveF2(pfx)) DIP("bnd ; "); /* MPX bnd prefix. */
-       d64 = (guest_RIP_bbstart+delta+sz) + getSDisp(sz,delta); 
-       delta += sz;
-@@ -21404,8 +21404,7 @@ Long dis_ESC_NONE (
- 
-    case 0xEB: /* Jb (jump, byte offset) */
-       if (haveF3(pfx)) goto decode_failure;
--      if (sz != 4) 
--         goto decode_failure; /* JRS added 2004 July 11 */
-+      /* Prefixes that change operand size are ignored for this instruction. */
-       if (haveF2(pfx)) DIP("bnd ; "); /* MPX bnd prefix. */
-       d64 = (guest_RIP_bbstart+delta+1) + getSDisp8(delta); 
-       delta++;
diff --git a/valgrind-3.16.1-arm64-expensive-cmp.patch b/valgrind-3.16.1-arm64-expensive-cmp.patch
deleted file mode 100644
index b2f8b50..0000000
--- a/valgrind-3.16.1-arm64-expensive-cmp.patch
+++ /dev/null
@@ -1,19 +0,0 @@
-commit 359b98828ced9cfff8c1badfed75c7ef999cfee5
-Author: Julian Seward <jseward@acm.org>
-Date:   Sun Nov 15 18:28:09 2020 +0100
-
-    memcheck: on arm64, use expensive instrumentation for Cmp{EQ,NE}64 by default.
-
-diff --git a/memcheck/mc_translate.c b/memcheck/mc_translate.c
-index b32c9c9c5..e91d51094 100644
---- a/memcheck/mc_translate.c
-+++ b/memcheck/mc_translate.c
-@@ -8485,6 +8485,8 @@ IRSB* MC_(instrument) ( VgCallbackClosure* closure,
- #     elif defined(VGA_ppc64le)
-       // Needed by (at least) set_AV_CR6() in the front end.
-       mce.dlbo.dl_CmpEQ64_CmpNE64 = DLexpensive;
-+#     elif defined(VGA_arm64)
-+      mce.dlbo.dl_CmpEQ64_CmpNE64 = DLexpensive;
- #     endif
- 
-       /* preInstrumentationAnalysis() will allocate &mce.tmpHowUsed and then
diff --git a/valgrind-3.16.1-arm64-fma.patch b/valgrind-3.16.1-arm64-fma.patch
deleted file mode 100644
index c8ef17a..0000000
--- a/valgrind-3.16.1-arm64-fma.patch
+++ /dev/null
@@ -1,729 +0,0 @@
-From 04cdc29b007594a0e58ffef0c9dd87df3ea595ea Mon Sep 17 00:00:00 2001
-From: Mark Wielaard <mark@klomp.org>
-Date: Wed, 14 Oct 2020 06:11:34 -0400
-Subject: [PATCH] arm64 VEX frontend and backend support for
- Iop_M{Add,Sub}F{32,64}
-
-The arm64 frontend used to implement the scalar fmadd, fmsub, fnmadd
-and fnmsub iinstructions into separate addition/substraction and
-multiplication instructions, which caused rounding issues.
-
-This patch turns them into Iop_M{Add,Sub}F{32,64} instructions
-(with some arguments negated). And the backend now emits fmadd or fmsub
-instructions.
-
-Alexandra Hajkova <ahajkova@redhat.com> added tests and fixed up the
-implementation to make sure rounding (and sign) are correct now.
-
-https://bugs.kde.org/show_bug.cgi?id=426014
----
- VEX/priv/guest_arm64_toIR.c           |  58 ++++++++---
- VEX/priv/host_arm64_defs.c            | 136 +++++++++++++++++++++++++-
- VEX/priv/host_arm64_defs.h            |  30 ++++++
- VEX/priv/host_arm64_isel.c            |  39 ++++++++
- none/tests/arm64/Makefile.am          |   6 +-
- none/tests/arm64/fmadd_sub.c          |  98 +++++++++++++++++++
- none/tests/arm64/fmadd_sub.stderr.exp |   0
- none/tests/arm64/fmadd_sub.stdout.exp | 125 +++++++++++++++++++++++
- none/tests/arm64/fmadd_sub.vgtest     |   3 +
- 9 files changed, 479 insertions(+), 16 deletions(-)
- create mode 100644 none/tests/arm64/fmadd_sub.c
- create mode 100644 none/tests/arm64/fmadd_sub.stderr.exp
- create mode 100644 none/tests/arm64/fmadd_sub.stdout.exp
- create mode 100644 none/tests/arm64/fmadd_sub.vgtest
-
-diff --git a/VEX/priv/guest_arm64_toIR.c b/VEX/priv/guest_arm64_toIR.c
-index 556b85a6a..d242d43c0 100644
---- a/VEX/priv/guest_arm64_toIR.c
-+++ b/VEX/priv/guest_arm64_toIR.c
-@@ -286,6 +286,12 @@ static IRExpr* triop ( IROp op, IRExpr* a1, IRExpr* a2, IRExpr* a3 )
-    return IRExpr_Triop(op, a1, a2, a3);
- }
- 
-+static IRExpr* qop ( IROp op, IRExpr* a1, IRExpr* a2,
-+                              IRExpr* a3, IRExpr* a4 )
-+{
-+   return IRExpr_Qop(op, a1, a2, a3, a4);
-+}
-+
- static IRExpr* loadLE ( IRType ty, IRExpr* addr )
- {
-    return IRExpr_Load(Iend_LE, ty, addr);
-@@ -532,6 +538,22 @@ static IROp mkADDF ( IRType ty ) {
-    }
- }
- 
-+static IROp mkFMADDF ( IRType ty ) {
-+   switch (ty) {
-+      case Ity_F32: return Iop_MAddF32;
-+      case Ity_F64: return Iop_MAddF64;
-+      default: vpanic("mkFMADDF");
-+   }
-+}
-+
-+static IROp mkFMSUBF ( IRType ty ) {
-+   switch (ty) {
-+      case Ity_F32: return Iop_MSubF32;
-+      case Ity_F64: return Iop_MSubF64;
-+      default: vpanic("mkFMSUBF");
-+   }
-+}
-+
- static IROp mkSUBF ( IRType ty ) {
-    switch (ty) {
-       case Ity_F32: return Iop_SubF32;
-@@ -14368,30 +14390,40 @@ Bool dis_AdvSIMD_fp_data_proc_3_source(/*MB_OUT*/DisResult* dres, UInt insn)
-          where Fx=Dx when sz=1, Fx=Sx when sz=0
- 
-                   -----SPEC------    ----IMPL----
--         fmadd       a +    n * m    a + n * m
--         fmsub       a + (-n) * m    a - n * m
--         fnmadd   (-a) + (-n) * m    -(a + n * m)
--         fnmsub   (-a) +    n * m    -(a - n * m)
-+         fmadd       a +    n * m    fmadd (a, n, m)
-+         fmsub       a + (-n) * m    fmsub (a, n, m)
-+         fnmadd   (-a) + (-n) * m    fmadd (-a, -n, m)
-+         fnmsub   (-a) +    n * m    fmadd (-a, n, m)
-+
-+         Note Iop_MAdd/SubF32/64 take arguments in the order: rm, N, M, A
-       */
-       Bool    isD   = (ty & 1) == 1;
-       UInt    ix    = (bitO1 << 1) | bitO0;
-       IRType  ity   = isD ? Ity_F64 : Ity_F32;
--      IROp    opADD = mkADDF(ity);
--      IROp    opSUB = mkSUBF(ity);
--      IROp    opMUL = mkMULF(ity);
-+      IROp    opFMADD = mkFMADDF(ity);
-+      IROp    opFMSUB = mkFMSUBF(ity);
-       IROp    opNEG = mkNEGF(ity);
-       IRTemp  res   = newTemp(ity);
-       IRExpr* eA    = getQRegLO(aa, ity);
-       IRExpr* eN    = getQRegLO(nn, ity);
-       IRExpr* eM    = getQRegLO(mm, ity);
-       IRExpr* rm    = mkexpr(mk_get_IR_rounding_mode());
--      IRExpr* eNxM  = triop(opMUL, rm, eN, eM);
-       switch (ix) {
--         case 0:  assign(res, triop(opADD, rm, eA, eNxM)); break;
--         case 1:  assign(res, triop(opSUB, rm, eA, eNxM)); break;
--         case 2:  assign(res, unop(opNEG, triop(opADD, rm, eA, eNxM))); break;
--         case 3:  assign(res, unop(opNEG, triop(opSUB, rm, eA, eNxM))); break;
--         default: vassert(0);
-+         case 0: /* FMADD */
-+            assign(res, qop(opFMADD, rm, eN, eM, eA));
-+            break;
-+         case 1: /* FMSUB */
-+            assign(res, qop(opFMSUB, rm, eN, eM, eA));
-+            break;
-+         case 2: /* FNMADD */
-+            assign(res, qop(opFMADD, rm, unop(opNEG, eN), eM,
-+                            unop(opNEG,eA)));
-+            break;
-+         case 3: /* FNMSUB */
-+            assign(res, qop(opFMADD, rm, eN, eM, unop(opNEG, eA)));
-+            break;
-+         default:
-+            vassert(0);
-       }
-       putQReg128(dd, mkV128(0x0000));
-       putQRegLO(dd, mkexpr(res));
-diff --git a/VEX/priv/host_arm64_defs.c b/VEX/priv/host_arm64_defs.c
-index e4ef56986..13b497f60 100644
---- a/VEX/priv/host_arm64_defs.c
-+++ b/VEX/priv/host_arm64_defs.c
-@@ -546,6 +546,14 @@ static const HChar* showARM64FpBinOp ( ARM64FpBinOp op ) {
-    }
- }
- 
-+static const HChar* showARM64FpTriOp ( ARM64FpTriOp op ) {
-+   switch (op) {
-+      case ARM64fpt_FMADD: return "fmadd";
-+      case ARM64fpt_FMSUB: return "fmsub";
-+      default: vpanic("showARM64FpTriOp");
-+   }
-+}
-+
- static const HChar* showARM64FpUnaryOp ( ARM64FpUnaryOp op ) {
-    switch (op) {
-       case ARM64fpu_NEG:   return "neg  ";
-@@ -1154,6 +1162,28 @@ ARM64Instr* ARM64Instr_VBinS ( ARM64FpBinOp op,
-    i->ARM64in.VBinS.argR = argR;
-    return i;
- }
-+ARM64Instr* ARM64Instr_VTriD ( ARM64FpTriOp op,
-+                               HReg dst, HReg arg1, HReg arg2, HReg arg3 ) {
-+   ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
-+   i->tag                = ARM64in_VTriD;
-+   i->ARM64in.VTriD.op   = op;
-+   i->ARM64in.VTriD.dst  = dst;
-+   i->ARM64in.VTriD.arg1 = arg1;
-+   i->ARM64in.VTriD.arg2 = arg2;
-+   i->ARM64in.VTriD.arg3 = arg3;
-+   return i;
-+}
-+ARM64Instr* ARM64Instr_VTriS ( ARM64FpTriOp op,
-+                               HReg dst, HReg arg1, HReg arg2, HReg arg3 ) {
-+   ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
-+   i->tag                = ARM64in_VTriS;
-+   i->ARM64in.VTriS.op   = op;
-+   i->ARM64in.VTriS.dst  = dst;
-+   i->ARM64in.VTriS.arg1 = arg1;
-+   i->ARM64in.VTriS.arg2 = arg2;
-+   i->ARM64in.VTriS.arg3 = arg3;
-+   return i;
-+}
- ARM64Instr* ARM64Instr_VCmpD ( HReg argL, HReg argR ) {
-    ARM64Instr* i = LibVEX_Alloc_inline(sizeof(ARM64Instr));
-    i->tag                = ARM64in_VCmpD;
-@@ -1756,6 +1786,26 @@ void ppARM64Instr ( const ARM64Instr* i ) {
-          vex_printf(", ");
-          ppHRegARM64asSreg(i->ARM64in.VBinS.argR);
-          return;
-+      case ARM64in_VTriD:
-+         vex_printf("f%s   ", showARM64FpTriOp(i->ARM64in.VTriD.op));
-+         ppHRegARM64(i->ARM64in.VTriD.dst);
-+         vex_printf(", ");
-+         ppHRegARM64(i->ARM64in.VTriD.arg1);
-+         vex_printf(", ");
-+         ppHRegARM64(i->ARM64in.VTriD.arg2);
-+         vex_printf(", ");
-+         ppHRegARM64(i->ARM64in.VTriD.arg3);
-+         return;
-+      case ARM64in_VTriS:
-+         vex_printf("f%s   ", showARM64FpTriOp(i->ARM64in.VTriS.op));
-+         ppHRegARM64asSreg(i->ARM64in.VTriS.dst);
-+         vex_printf(", ");
-+         ppHRegARM64asSreg(i->ARM64in.VTriS.arg1);
-+         vex_printf(", ");
-+         ppHRegARM64asSreg(i->ARM64in.VTriS.arg2);
-+         vex_printf(", ");
-+         ppHRegARM64asSreg(i->ARM64in.VTriS.arg3);
-+         return;
-       case ARM64in_VCmpD:
-          vex_printf("fcmp   ");
-          ppHRegARM64(i->ARM64in.VCmpD.argL);
-@@ -2197,6 +2247,18 @@ void getRegUsage_ARM64Instr ( HRegUsage* u, const ARM64Instr* i, Bool mode64 )
-          addHRegUse(u, HRmRead, i->ARM64in.VBinS.argL);
-          addHRegUse(u, HRmRead, i->ARM64in.VBinS.argR);
-          return;
-+      case ARM64in_VTriD:
-+         addHRegUse(u, HRmWrite, i->ARM64in.VTriD.dst);
-+         addHRegUse(u, HRmRead, i->ARM64in.VTriD.arg1);
-+         addHRegUse(u, HRmRead, i->ARM64in.VTriD.arg2);
-+         addHRegUse(u, HRmRead, i->ARM64in.VTriD.arg3);
-+         return;
-+      case ARM64in_VTriS:
-+         addHRegUse(u, HRmWrite, i->ARM64in.VTriS.dst);
-+         addHRegUse(u, HRmRead, i->ARM64in.VTriS.arg1);
-+         addHRegUse(u, HRmRead, i->ARM64in.VTriS.arg2);
-+         addHRegUse(u, HRmRead, i->ARM64in.VTriS.arg3);
-+         return;
-       case ARM64in_VCmpD:
-          addHRegUse(u, HRmRead, i->ARM64in.VCmpD.argL);
-          addHRegUse(u, HRmRead, i->ARM64in.VCmpD.argR);
-@@ -2454,6 +2516,18 @@ void mapRegs_ARM64Instr ( HRegRemap* m, ARM64Instr* i, Bool mode64 )
-          i->ARM64in.VBinS.argL = lookupHRegRemap(m, i->ARM64in.VBinS.argL);
-          i->ARM64in.VBinS.argR = lookupHRegRemap(m, i->ARM64in.VBinS.argR);
-          return;
-+      case ARM64in_VTriD:
-+         i->ARM64in.VTriD.dst  = lookupHRegRemap(m, i->ARM64in.VTriD.dst);
-+         i->ARM64in.VTriD.arg1 = lookupHRegRemap(m, i->ARM64in.VTriD.arg1);
-+         i->ARM64in.VTriD.arg2 = lookupHRegRemap(m, i->ARM64in.VTriD.arg2);
-+         i->ARM64in.VTriD.arg3 = lookupHRegRemap(m, i->ARM64in.VTriD.arg3);
-+         return;
-+      case ARM64in_VTriS:
-+         i->ARM64in.VTriS.dst  = lookupHRegRemap(m, i->ARM64in.VTriS.dst);
-+         i->ARM64in.VTriS.arg1 = lookupHRegRemap(m, i->ARM64in.VTriS.arg1);
-+         i->ARM64in.VTriS.arg2 = lookupHRegRemap(m, i->ARM64in.VTriS.arg2);
-+         i->ARM64in.VTriS.arg3 = lookupHRegRemap(m, i->ARM64in.VTriS.arg3);
-+         return;
-       case ARM64in_VCmpD:
-          i->ARM64in.VCmpD.argL = lookupHRegRemap(m, i->ARM64in.VCmpD.argL);
-          i->ARM64in.VCmpD.argR = lookupHRegRemap(m, i->ARM64in.VCmpD.argR);
-@@ -2812,7 +2886,8 @@ static inline UInt qregEnc ( HReg r )
- #define X11110011  BITS8(1,1,1,1,0,0,1,1)
- #define X11110101  BITS8(1,1,1,1,0,1,0,1)
- #define X11110111  BITS8(1,1,1,1,0,1,1,1)
--
-+#define X11111000  BITS8(1,1,1,1,1,0,0,0)
-+#define X11111010  BITS8(1,1,1,1,1,0,1,0)
- 
- /* --- 4 fields --- */
- 
-@@ -2972,6 +3047,27 @@ static inline UInt X_3_6_1_6_6_5_5 ( UInt f1, UInt f2, UInt f3,
- }
- 
- 
-+static inline UInt X_3_8_5_1_5_5_5 ( UInt f1, UInt f2, UInt f3, UInt f4,
-+                                     UInt f5, UInt f6, UInt f7 ) {
-+   vassert(3+8+5+1+5+5+5 == 32);
-+   vassert(f1 < (1<<3));
-+   vassert(f2 < (1<<8));
-+   vassert(f3 < (1<<5));
-+   vassert(f4 < (1<<1));
-+   vassert(f5 < (1<<5));
-+   vassert(f6 < (1<<5));
-+   vassert(f7 < (1<<5));
-+   UInt w = 0;
-+   w = (w << 3) | f1;
-+   w = (w << 8) | f2;
-+   w = (w << 5) | f3;
-+   w = (w << 1) | f4;
-+   w = (w << 5) | f5;
-+   w = (w << 5) | f6;
-+   w = (w << 5) | f7;
-+   return w;
-+}
-+
- //ZZ #define X0000  BITS4(0,0,0,0)
- //ZZ #define X0001  BITS4(0,0,0,1)
- //ZZ #define X0010  BITS4(0,0,1,0)
-@@ -4339,6 +4435,44 @@ Int emit_ARM64Instr ( /*MB_MOD*/Bool* is_profInc,
-             = X_3_8_5_6_5_5(X000, X11110001, sM, (b1512 << 2) | X10, sN, sD);
-          goto done;
-       }
-+      case ARM64in_VTriD: {
-+         /* 31            20 15 14 9 4
-+            000 11111 010 m  0  a  n d FMADD  Dd,Dn,Dm,Da
-+            ---------------- 1  ------ FMSUB  -----------
-+         */
-+         UInt dD = dregEnc(i->ARM64in.VTriD.dst);
-+         UInt dN = dregEnc(i->ARM64in.VTriD.arg1);
-+         UInt dM = dregEnc(i->ARM64in.VTriD.arg2);
-+         UInt dA = dregEnc(i->ARM64in.VTriD.arg3);
-+         UInt b15 = 2; /* impossible */
-+         switch (i->ARM64in.VTriD.op) {
-+            case ARM64fpt_FMADD: b15 = 0; break;
-+            case ARM64fpt_FMSUB: b15 = 1; break;
-+            default: goto bad;
-+         }
-+         vassert(b15 < 2);
-+         *p++ = X_3_8_5_1_5_5_5(X000, X11111010, dM, b15, dA, dN, dD);
-+         goto done;
-+      }
-+      case ARM64in_VTriS: {
-+         /* 31            20 15 14 9 4
-+            000 11111 000 m  0  a  n d FMADD  Dd,Dn,Dm,Da
-+            ---------------- 1  ------ FMSUB  -----------
-+         */
-+         UInt dD = dregEnc(i->ARM64in.VTriD.dst);
-+         UInt dN = dregEnc(i->ARM64in.VTriD.arg1);
-+         UInt dM = dregEnc(i->ARM64in.VTriD.arg2);
-+         UInt dA = dregEnc(i->ARM64in.VTriD.arg3);
-+         UInt b15 = 2; /* impossible */
-+         switch (i->ARM64in.VTriD.op) {
-+            case ARM64fpt_FMADD: b15 = 0; break;
-+            case ARM64fpt_FMSUB: b15 = 1; break;
-+            default: goto bad;
-+         }
-+         vassert(b15 < 2);
-+         *p++ = X_3_8_5_1_5_5_5(X000, X11111000, dM, b15, dA, dN, dD);
-+         goto done;
-+      }
-       case ARM64in_VCmpD: {
-          /* 000 11110 01 1 m 00 1000 n 00 000  FCMP Dn, Dm */
-          UInt dN = dregEnc(i->ARM64in.VCmpD.argL);
-diff --git a/VEX/priv/host_arm64_defs.h b/VEX/priv/host_arm64_defs.h
-index 05dba7ab8..5a82564ce 100644
---- a/VEX/priv/host_arm64_defs.h
-+++ b/VEX/priv/host_arm64_defs.h
-@@ -289,6 +289,14 @@ typedef
-    }
-    ARM64FpBinOp;
- 
-+typedef
-+   enum {
-+      ARM64fpt_FMADD=105,
-+      ARM64fpt_FMSUB,
-+      ARM64fpt_INVALID
-+   }
-+   ARM64FpTriOp;
-+
- typedef
-    enum {
-       ARM64fpu_NEG=110,
-@@ -498,6 +506,8 @@ typedef
-       ARM64in_VUnaryS,
-       ARM64in_VBinD,
-       ARM64in_VBinS,
-+      ARM64in_VTriD,
-+      ARM64in_VTriS,
-       ARM64in_VCmpD,
-       ARM64in_VCmpS,
-       ARM64in_VFCSel,
-@@ -799,6 +809,22 @@ typedef
-             HReg         argL;
-             HReg         argR;
-          } VBinS;
-+         /* 64-bit FP ternary arithmetic */
-+         struct {
-+            ARM64FpTriOp op;
-+            HReg         dst;
-+            HReg         arg1;
-+            HReg         arg2;
-+            HReg         arg3;
-+         } VTriD;
-+         /* 32-bit FP ternary arithmetic */
-+         struct {
-+            ARM64FpTriOp op;
-+            HReg         dst;
-+            HReg         arg1;
-+            HReg         arg2;
-+            HReg         arg3;
-+         } VTriS;
-          /* 64-bit FP compare */
-          struct {
-             HReg argL;
-@@ -970,6 +996,10 @@ extern ARM64Instr* ARM64Instr_VUnaryD ( ARM64FpUnaryOp op, HReg dst, HReg src );
- extern ARM64Instr* ARM64Instr_VUnaryS ( ARM64FpUnaryOp op, HReg dst, HReg src );
- extern ARM64Instr* ARM64Instr_VBinD   ( ARM64FpBinOp op, HReg, HReg, HReg );
- extern ARM64Instr* ARM64Instr_VBinS   ( ARM64FpBinOp op, HReg, HReg, HReg );
-+extern ARM64Instr* ARM64Instr_VTriD   ( ARM64FpTriOp op, HReg dst,
-+                                        HReg, HReg, HReg );
-+extern ARM64Instr* ARM64Instr_VTriS   ( ARM64FpTriOp op, HReg dst,
-+                                        HReg, HReg, HReg );
- extern ARM64Instr* ARM64Instr_VCmpD   ( HReg argL, HReg argR );
- extern ARM64Instr* ARM64Instr_VCmpS   ( HReg argL, HReg argR );
- extern ARM64Instr* ARM64Instr_VFCSel  ( HReg dst, HReg argL, HReg argR,
-diff --git a/VEX/priv/host_arm64_isel.c b/VEX/priv/host_arm64_isel.c
-index 2f19eab81..da1218715 100644
---- a/VEX/priv/host_arm64_isel.c
-+++ b/VEX/priv/host_arm64_isel.c
-@@ -3255,6 +3255,25 @@ static HReg iselDblExpr_wrk ( ISelEnv* env, IRExpr* e )
-       }
-    }
- 
-+   if (e->tag == Iex_Qop) {
-+      IRQop*       qop = e->Iex.Qop.details;
-+      ARM64FpTriOp triop = ARM64fpt_INVALID;
-+      switch (qop->op) {
-+         case Iop_MAddF64: triop = ARM64fpt_FMADD; break;
-+         case Iop_MSubF64: triop = ARM64fpt_FMSUB; break;
-+         default: break;
-+      }
-+      if (triop != ARM64fpt_INVALID) {
-+         HReg N = iselDblExpr(env, qop->arg2);
-+         HReg M = iselDblExpr(env, qop->arg3);
-+         HReg A = iselDblExpr(env, qop->arg4);
-+         HReg dst  = newVRegD(env);
-+         set_FPCR_rounding_mode(env, qop->arg1);
-+         addInstr(env, ARM64Instr_VTriD(triop, dst, N, M, A));
-+         return dst;
-+      }
-+   }
-+
-    if (e->tag == Iex_ITE) {
-       /* ITE(ccexpr, iftrue, iffalse) */
-       ARM64CondCode cc;
-@@ -3450,6 +3469,26 @@ static HReg iselFltExpr_wrk ( ISelEnv* env, IRExpr* e )
-       return dst;
-    }
- 
-+   if (e->tag == Iex_Qop) {
-+      IRQop*       qop = e->Iex.Qop.details;
-+      ARM64FpTriOp triop = ARM64fpt_INVALID;
-+      switch (qop->op) {
-+         case Iop_MAddF32: triop = ARM64fpt_FMADD; break;
-+         case Iop_MSubF32: triop = ARM64fpt_FMSUB; break;
-+      default: break;
-+      }
-+
-+      if (triop != ARM64fpt_INVALID) {
-+         HReg N = iselFltExpr(env, qop->arg2);
-+         HReg M = iselFltExpr(env, qop->arg3);
-+         HReg A = iselFltExpr(env, qop->arg4);
-+         HReg dst  = newVRegD(env);
-+         set_FPCR_rounding_mode(env, qop->arg1);
-+         addInstr(env, ARM64Instr_VTriS(triop, dst, N, M, A));
-+         return dst;
-+      }
-+   }
-+
-    ppIRExpr(e);
-    vpanic("iselFltExpr_wrk");
- }
-diff --git a/none/tests/arm64/Makefile.am b/none/tests/arm64/Makefile.am
-index 7b3ebbdca..4ecab36ad 100644
---- a/none/tests/arm64/Makefile.am
-+++ b/none/tests/arm64/Makefile.am
-@@ -10,14 +10,16 @@ EXTRA_DIST = \
- 	integer.stdout.exp integer.stderr.exp integer.vgtest \
- 	memory.stdout.exp memory.stderr.exp memory.vgtest \
- 	atomics_v81.stdout.exp atomics_v81.stderr.exp atomics_v81.vgtest \
--	simd_v81.stdout.exp simd_v81.stderr.exp simd_v81.vgtest
-+	simd_v81.stdout.exp simd_v81.stderr.exp simd_v81.vgtest \
-+        fmadd_sub.stdout.exp fmadd_sub.stderr.exp fmadd_sub.vgtest
- 
- check_PROGRAMS = \
- 	allexec \
-         cvtf_imm \
- 	fp_and_simd \
- 	integer \
--	memory
-+	memory \
-+	fmadd_sub
- 
- if BUILD_ARMV8_CRC_TESTS
-   check_PROGRAMS += crc32
-diff --git a/none/tests/arm64/fmadd_sub.c b/none/tests/arm64/fmadd_sub.c
-new file mode 100644
-index 000000000..dcab22d1b
---- /dev/null
-+++ b/none/tests/arm64/fmadd_sub.c
-@@ -0,0 +1,98 @@
-+#include <math.h>
-+#include <stdint.h>
-+#include <stdio.h>
-+#include <stdlib.h>
-+
-+#define COUNT 5
-+
-+static void
-+print_float(const char *ident, float x)
-+{
-+  union
-+  {
-+    float f;
-+    uint32_t i;
-+  } u;
-+
-+  u.f = x;
-+  printf("%s = %08x = %.17g\n", ident, u.i, x);
-+}
-+
-+static void
-+print_double(const char *ident, double x)
-+{
-+  union
-+  {
-+    double f;
-+    uint64_t i;
-+  } u;
-+
-+  u.f = x;
-+  printf("%s = %016lx = %.17g\n", ident, u.i, x);
-+}
-+
-+int
-+main(int argc, char **argv)
-+{
-+  float x[] = { 55,                  0.98076171874999996, 0, 1, 0xFFFFFFFF } ;
-+  float y[] = { 0.69314718055994529, 1.015625,            0, 1, 0xFFFFFFFF };
-+  float z[] = { 38.123094930796988,  1,                   0, 1, 0xFFFFFFFF };
-+  float dst = -5;
-+
-+  double dx[] = { 55,                  0.98076171874999996, 0, 1, 0xFFFFFFFF } ;
-+  double dy[] = { 0.69314718055994529, 1.015625,            0, 1, 0xFFFFFFFF };
-+  double dz[] = { 38.123094930796988,  1,                   0, 1, 0xFFFFFFFF };
-+  double ddst= -5;
-+
-+  int i;
-+
-+  for (i = 0; i < COUNT; i++) {
-+	  //32bit variant
-+	  asm("fmadd %s0, %s1, %s2, %s3\n;" : "=w"(dst) : "w"(x[i]), "w"(y[i]), "w"(z[i]));
-+	  printf("FMADD 32bit: dst = z + x * y\n");
-+	  printf("%f = %f + %f * %f\n", dst, z[i], x[i], y[i]);
-+	  print_float("dst", dst);
-+
-+	  // Floating-point negated fused multiply-add
-+	  asm("fnmadd %s0, %s1, %s2, %s3\n;" : "=w"(dst) : "w"(x[i]), "w"(y[i]), "w"(z[i]));
-+	  printf("FNMADD 32bit: dst = -z + (-x) * y\n");
-+	  printf("%f = -%f + (-%f) * %f\n", dst, z[i], x[i], y[i]);
-+	  print_float("dst", dst);
-+
-+	  asm("fmsub %s0, %s1, %s2, %s3\n;" : "=w"(dst) : "w"(x[i]), "w"(y[i]), "w"(z[i]));
-+	  printf("FMSUB 32bit: dst = z + (-x) * y\n");
-+	  printf("%f = %f + (-%f) * %f\n", dst, z[i], x[i], y[i]);
-+	  print_float("dst", dst);
-+
-+	  asm("fnmsub %s0, %s1, %s2, %s3\n;" : "=w"(dst) : "w"(x[i]), "w"(y[i]), "w"(z[i]));
-+	  printf("FNMSUB 32bit: dst = -z + x * y\n");
-+	  printf("%f = -%f + %f * %f\n", dst, z[i], x[i], y[i]);
-+	  print_float("dst", dst);
-+
-+	  //64bit variant
-+	  asm("fmadd %d0, %d1, %d2, %d3\n;" : "=w"(ddst) : "w"(dx[i]), "w"(dy[i]), "w"(dz[i]));
-+	  printf("FMADD 64bit: dst = z + x * y\n");
-+	  printf("%f = %f + %f * %f\n", ddst, dz[i], dx[i], dy[i]);
-+	  print_double("dst", ddst);
-+
-+	  asm("fnmadd %d0, %d1, %d2, %d3\n;" : "=w"(ddst) : "w"(dx[i]), "w"(dy[i]), "w"(dz[i]));
-+	  printf("FNMADD 64bit: dst = -z + (-x) * y\n");
-+	  printf("%f = -%f - %f * %f\n", ddst, dz[i], dx[i], dy[i]);
-+	  print_double("dst", ddst);
-+
-+	  asm("fmsub %d0, %d1, %d2, %d3\n;" : "=w"(ddst) : "w"(dx[i]), "w"(dy[i]), "w"(dz[i]));
-+	  printf("FMSUB 64bit: dst = z + (-x) * y\n");
-+	  printf("%f = %f + (-%f) * %f\n", ddst, dz[i], dx[i], dy[i]);
-+	  print_double("dst", ddst);
-+
-+	  asm("fnmsub %d0, %d1, %d2, %d3\n;" : "=w"(ddst) : "w"(dx[i]), "w"(dy[i]), "w"(dz[i]));
-+	  printf("FNMSUB 64bit: dst = -z + x * y\n");
-+	  printf("%f = -%f + %f * %f\n", ddst, dz[i], dx[i], dy[i]);
-+	  print_double("dst", ddst);
-+
-+	  printf("\n");
-+  }
-+
-+  return 0;
-+}
-+
-diff --git a/none/tests/arm64/fmadd_sub.stderr.exp b/none/tests/arm64/fmadd_sub.stderr.exp
-new file mode 100644
-index 000000000..e69de29bb
-diff --git a/none/tests/arm64/fmadd_sub.stdout.exp b/none/tests/arm64/fmadd_sub.stdout.exp
-new file mode 100644
-index 000000000..f1824b12b
---- /dev/null
-+++ b/none/tests/arm64/fmadd_sub.stdout.exp
-@@ -0,0 +1,125 @@
-+FMADD 32bit: dst = z + x * y
-+76.246193 = 38.123096 + 55.000000 * 0.693147
-+dst = 42987e0d = 76.246192932128906
-+FNMADD 32bit: dst = -z + (-x) * y
-+-76.246193 = -38.123096 + (-55.000000) * 0.693147
-+dst = c2987e0d = -76.246192932128906
-+FMSUB 32bit: dst = z + (-x) * y
-+0.000001 = 38.123096 + (-55.000000) * 0.693147
-+dst = 35c00000 = 1.430511474609375e-06
-+FNMSUB 32bit: dst = -z + x * y
-+-0.000001 = -38.123096 + 55.000000 * 0.693147
-+dst = b5c00000 = -1.430511474609375e-06
-+FMADD 64bit: dst = z + x * y
-+76.246190 = 38.123095 + 55.000000 * 0.693147
-+dst = 40530fc1931f09c9 = 76.246189861593976
-+FNMADD 64bit: dst = -z + (-x) * y
-+-76.246190 = -38.123095 - 55.000000 * 0.693147
-+dst = c0530fc1931f09c9 = -76.246189861593976
-+FMSUB 64bit: dst = z + (-x) * y
-+-0.000000 = 38.123095 + (-55.000000) * 0.693147
-+dst = bce9000000000000 = -2.7755575615628914e-15
-+FNMSUB 64bit: dst = -z + x * y
-+0.000000 = -38.123095 + 55.000000 * 0.693147
-+dst = 3ce9000000000000 = 2.7755575615628914e-15
-+
-+FMADD 32bit: dst = z + x * y
-+1.996086 = 1.000000 + 0.980762 * 1.015625
-+dst = 3fff7fc0 = 1.9960861206054688
-+FNMADD 32bit: dst = -z + (-x) * y
-+-1.996086 = -1.000000 + (-0.980762) * 1.015625
-+dst = bfff7fc0 = -1.9960861206054688
-+FMSUB 32bit: dst = z + (-x) * y
-+0.003914 = 1.000000 + (-0.980762) * 1.015625
-+dst = 3b80401a = 0.00391389150172472
-+FNMSUB 32bit: dst = -z + x * y
-+-0.003914 = -1.000000 + 0.980762 * 1.015625
-+dst = bb80401a = -0.00391389150172472
-+FMADD 64bit: dst = z + x * y
-+1.996086 = 1.000000 + 0.980762 * 1.015625
-+dst = 3fffeff800000000 = 1.9960861206054688
-+FNMADD 64bit: dst = -z + (-x) * y
-+-1.996086 = -1.000000 - 0.980762 * 1.015625
-+dst = bfffeff800000000 = -1.9960861206054688
-+FMSUB 64bit: dst = z + (-x) * y
-+0.003914 = 1.000000 + (-0.980762) * 1.015625
-+dst = 3f70080000000034 = 0.0039138793945312951
-+FNMSUB 64bit: dst = -z + x * y
-+-0.003914 = -1.000000 + 0.980762 * 1.015625
-+dst = bf70080000000034 = -0.0039138793945312951
-+
-+FMADD 32bit: dst = z + x * y
-+0.000000 = 0.000000 + 0.000000 * 0.000000
-+dst = 00000000 = 0
-+FNMADD 32bit: dst = -z + (-x) * y
-+-0.000000 = -0.000000 + (-0.000000) * 0.000000
-+dst = 80000000 = -0
-+FMSUB 32bit: dst = z + (-x) * y
-+0.000000 = 0.000000 + (-0.000000) * 0.000000
-+dst = 00000000 = 0
-+FNMSUB 32bit: dst = -z + x * y
-+0.000000 = -0.000000 + 0.000000 * 0.000000
-+dst = 00000000 = 0
-+FMADD 64bit: dst = z + x * y
-+0.000000 = 0.000000 + 0.000000 * 0.000000
-+dst = 0000000000000000 = 0
-+FNMADD 64bit: dst = -z + (-x) * y
-+-0.000000 = -0.000000 - 0.000000 * 0.000000
-+dst = 8000000000000000 = -0
-+FMSUB 64bit: dst = z + (-x) * y
-+0.000000 = 0.000000 + (-0.000000) * 0.000000
-+dst = 0000000000000000 = 0
-+FNMSUB 64bit: dst = -z + x * y
-+0.000000 = -0.000000 + 0.000000 * 0.000000
-+dst = 0000000000000000 = 0
-+
-+FMADD 32bit: dst = z + x * y
-+2.000000 = 1.000000 + 1.000000 * 1.000000
-+dst = 40000000 = 2
-+FNMADD 32bit: dst = -z + (-x) * y
-+-2.000000 = -1.000000 + (-1.000000) * 1.000000
-+dst = c0000000 = -2
-+FMSUB 32bit: dst = z + (-x) * y
-+0.000000 = 1.000000 + (-1.000000) * 1.000000
-+dst = 00000000 = 0
-+FNMSUB 32bit: dst = -z + x * y
-+0.000000 = -1.000000 + 1.000000 * 1.000000
-+dst = 00000000 = 0
-+FMADD 64bit: dst = z + x * y
-+2.000000 = 1.000000 + 1.000000 * 1.000000
-+dst = 4000000000000000 = 2
-+FNMADD 64bit: dst = -z + (-x) * y
-+-2.000000 = -1.000000 - 1.000000 * 1.000000
-+dst = c000000000000000 = -2
-+FMSUB 64bit: dst = z + (-x) * y
-+0.000000 = 1.000000 + (-1.000000) * 1.000000
-+dst = 0000000000000000 = 0
-+FNMSUB 64bit: dst = -z + x * y
-+0.000000 = -1.000000 + 1.000000 * 1.000000
-+dst = 0000000000000000 = 0
-+
-+FMADD 32bit: dst = z + x * y
-+18446744073709551616.000000 = 4294967296.000000 + 4294967296.000000 * 4294967296.000000
-+dst = 5f800000 = 1.8446744073709552e+19
-+FNMADD 32bit: dst = -z + (-x) * y
-+-18446744073709551616.000000 = -4294967296.000000 + (-4294967296.000000) * 4294967296.000000
-+dst = df800000 = -1.8446744073709552e+19
-+FMSUB 32bit: dst = z + (-x) * y
-+-18446744073709551616.000000 = 4294967296.000000 + (-4294967296.000000) * 4294967296.000000
-+dst = df800000 = -1.8446744073709552e+19
-+FNMSUB 32bit: dst = -z + x * y
-+18446744073709551616.000000 = -4294967296.000000 + 4294967296.000000 * 4294967296.000000
-+dst = 5f800000 = 1.8446744073709552e+19
-+FMADD 64bit: dst = z + x * y
-+18446744069414584320.000000 = 4294967295.000000 + 4294967295.000000 * 4294967295.000000
-+dst = 43efffffffe00000 = 1.8446744069414584e+19
-+FNMADD 64bit: dst = -z + (-x) * y
-+-18446744069414584320.000000 = -4294967295.000000 - 4294967295.000000 * 4294967295.000000
-+dst = c3efffffffe00000 = -1.8446744069414584e+19
-+FMSUB 64bit: dst = z + (-x) * y
-+-18446744060824649728.000000 = 4294967295.000000 + (-4294967295.000000) * 4294967295.000000
-+dst = c3efffffffa00000 = -1.844674406082465e+19
-+FNMSUB 64bit: dst = -z + x * y
-+18446744060824649728.000000 = -4294967295.000000 + 4294967295.000000 * 4294967295.000000
-+dst = 43efffffffa00000 = 1.844674406082465e+19
-+
-diff --git a/none/tests/arm64/fmadd_sub.vgtest b/none/tests/arm64/fmadd_sub.vgtest
-new file mode 100644
-index 000000000..b4c53eea4
---- /dev/null
-+++ b/none/tests/arm64/fmadd_sub.vgtest
-@@ -0,0 +1,3 @@
-+prog: fmadd_sub
-+prereq: test -x fmadd_sub
-+vgopts: -q
--- 
-2.18.4
-
-diff --git a/VEX/priv/guest_generic_bb_to_IR.c b/VEX/priv/guest_generic_bb_to_IR.c
-index 0cee970e4..1e72ddacd 100644
---- a/VEX/priv/guest_generic_bb_to_IR.c
-+++ b/VEX/priv/guest_generic_bb_to_IR.c
-@@ -422,6 +422,8 @@ static Bool expr_is_guardable ( const IRExpr* e )
-          return !primopMightTrap(e->Iex.Binop.op);
-       case Iex_Triop:
-          return !primopMightTrap(e->Iex.Triop.details->op);
-+      case Iex_Qop:
-+         return !primopMightTrap(e->Iex.Qop.details->op);
-       case Iex_ITE:
-       case Iex_CCall:
-       case Iex_Get:
diff --git a/valgrind-3.16.1-arm64_sp_lr_fp_DwReg.patch b/valgrind-3.16.1-arm64_sp_lr_fp_DwReg.patch
deleted file mode 100644
index 14b45d4..0000000
--- a/valgrind-3.16.1-arm64_sp_lr_fp_DwReg.patch
+++ /dev/null
@@ -1,72 +0,0 @@
-diff --git a/coregrind/m_debuginfo/d3basics.c b/coregrind/m_debuginfo/d3basics.c
-index e1127ffe2..1bc5f8f05 100644
---- a/coregrind/m_debuginfo/d3basics.c
-+++ b/coregrind/m_debuginfo/d3basics.c
-@@ -523,6 +523,7 @@ static Bool get_Dwarf_Reg( /*OUT*/Addr* a, Word regno, const RegSummary* regs )
-    if (regno == 30) { *a = regs->fp; return True; }
- #  elif defined(VGP_arm64_linux)
-    if (regno == 31) { *a = regs->sp; return True; }
-+   if (regno == 29) { *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 c4a5ea593..bc2578b37 100644
---- a/coregrind/m_debuginfo/debuginfo.c
-+++ b/coregrind/m_debuginfo/debuginfo.c
-@@ -2874,7 +2874,9 @@ UWord evalCfiExpr ( const XArray* exprs, Int ix,
- #           elif defined(VGA_ppc32) || defined(VGA_ppc64be) \
-                || defined(VGA_ppc64le)
- #           elif defined(VGP_arm64_linux)
-+            case Creg_ARM64_SP: return eec->uregs->sp;
-             case Creg_ARM64_X30: return eec->uregs->x30;
-+            case Creg_ARM64_X29: return eec->uregs->x29;
- #           else
- #             error "Unsupported arch"
- #           endif
-diff --git a/coregrind/m_debuginfo/priv_storage.h b/coregrind/m_debuginfo/priv_storage.h
-index 39456eccb..ae44ca34e 100644
---- a/coregrind/m_debuginfo/priv_storage.h
-+++ b/coregrind/m_debuginfo/priv_storage.h
-@@ -415,7 +415,9 @@ typedef
-       Creg_ARM_R15,
-       Creg_ARM_R14,
-       Creg_ARM_R7,
-+      Creg_ARM64_SP,
-       Creg_ARM64_X30,
-+      Creg_ARM64_X29,
-       Creg_S390_IA,
-       Creg_S390_SP,
-       Creg_S390_FP,
-diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c
-index 3996623ed..bcacca4cb 100644
---- a/coregrind/m_debuginfo/readdwarf.c
-+++ b/coregrind/m_debuginfo/readdwarf.c
-@@ -2816,7 +2816,12 @@ static Int copy_convert_CfiExpr_tree ( XArray*        dstxa,
-          if (dwreg == srcuc->ra_reg)
-             return ML_(CfiExpr_CfiReg)( dstxa, Creg_IA_IP );
- #        elif defined(VGA_arm64)
--         I_die_here;
-+         if (dwreg == SP_REG)
-+            return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM64_SP );
-+         if (dwreg == FP_REG)
-+            return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM64_X29 );
-+         if (dwreg == srcuc->ra_reg)
-+            return ML_(CfiExpr_CfiReg)( dstxa, Creg_ARM64_X30 );
- #        elif defined(VGA_ppc32) || defined(VGA_ppc64be) \
-             || defined(VGA_ppc64le)
- #        else
-diff --git a/coregrind/m_debuginfo/storage.c b/coregrind/m_debuginfo/storage.c
-index 8667d123f..48a92b402 100644
---- a/coregrind/m_debuginfo/storage.c
-+++ b/coregrind/m_debuginfo/storage.c
-@@ -1002,7 +1002,9 @@ static void ppCfiReg ( CfiReg reg )
-       case Creg_ARM_R15:   VG_(printf)("R15"); break;
-       case Creg_ARM_R14:   VG_(printf)("R14"); break;
-       case Creg_ARM_R7:    VG_(printf)("R7");  break;
-+      case Creg_ARM64_SP:  VG_(printf)("SP"); break;
-       case Creg_ARM64_X30: VG_(printf)("X30"); break;
-+      case Creg_ARM64_X29: VG_(printf)("X29"); break;
-       case Creg_MIPS_RA:   VG_(printf)("RA"); break;
-       case Creg_S390_IA:   VG_(printf)("IA"); break;
-       case Creg_S390_SP:   VG_(printf)("SP"); break;
diff --git a/valgrind-3.16.1-dl_runtime_resolve.patch b/valgrind-3.16.1-dl_runtime_resolve.patch
deleted file mode 100644
index 0a34759..0000000
--- a/valgrind-3.16.1-dl_runtime_resolve.patch
+++ /dev/null
@@ -1,206 +0,0 @@
-commit f4abcc05fdba3f25890a9b30b71d511ccc906d46
-Author: Mark Wielaard <mark@klomp.org>
-Date:   Mon Jul 27 22:43:28 2020 +0200
-
-    Incorrect call-graph tracking due to new _dl_runtime_resolve_xsave*
-    
-    Newer glibc have alternate ld.so _ld_runtime_resolve functions.
-    Namely _dl_runtime_resolve_xsave and _dl_runtime_resolve_xsave'2
-    
-    This patch recognizes the xsave, xsvec and fxsave variants and
-    changes callgrind so that any variant counts as _dl_runtime_resolve.
-    
-    Original patch by paulo.cesar.pereira.de.andrade@gmail.com
-    https://bugs.kde.org/show_bug.cgi?id=415293
-
-diff --git a/callgrind/fn.c b/callgrind/fn.c
-index e9d8dd214..7cce1a0c7 100644
---- a/callgrind/fn.c
-+++ b/callgrind/fn.c
-@@ -30,8 +30,11 @@
- 
- static fn_array current_fn_active;
- 
--static Addr runtime_resolve_addr = 0;
--static int  runtime_resolve_length = 0;
-+/* x86_64 defines 4 variants.  */
-+#define MAX_RESOLVE_ADDRS 4
-+static int  runtime_resolve_addrs = 0;
-+static Addr runtime_resolve_addr[MAX_RESOLVE_ADDRS];
-+static int  runtime_resolve_length[MAX_RESOLVE_ADDRS];
- 
- // a code pattern is a list of tuples (start offset, length)
- struct chunk_t { int start, len; };
-@@ -56,6 +59,9 @@ static Bool check_code(obj_node* obj,
-     /* first chunk of pattern should always start at offset 0 and
-      * have at least 3 bytes */
-     CLG_ASSERT((pat->chunk[0].start == 0) && (pat->chunk[0].len >2));
-+
-+    /* and we cannot be called more than MAX_RESOLVE_ADDRS times */
-+    CLG_ASSERT(runtime_resolve_addrs < MAX_RESOLVE_ADDRS);
-     
-     CLG_DEBUG(1, "check_code: %s, pattern %s, check %d bytes of [%x %x %x...]\n",
-               obj->name, pat->name, pat->chunk[0].len, code[0], code[1], code[2]);
-@@ -93,8 +99,9 @@ static Bool check_code(obj_node* obj,
- 				 pat->name, obj->name + obj->last_slash_pos,
- 				 addr - obj->start, addr, pat->len);
- 		    
--		runtime_resolve_addr   = addr;
--		runtime_resolve_length = pat->len;
-+		runtime_resolve_addr[runtime_resolve_addrs] = addr;
-+		runtime_resolve_length[runtime_resolve_addrs] = pat->len;
-+		runtime_resolve_addrs++;
- 		return True;
- 	    }
-         }
-@@ -138,8 +145,9 @@ static Bool search_runtime_resolve(obj_node* obj)
- 	"x86-glibc2.8", 30, {{ 0,12 }, { 16,14 }, { 30,0}} };
- 
-     if (VG_(strncmp)(obj->name, "/lib/ld", 7) != 0) return False;
--    if (check_code(obj, code, &pat)) return True;
--    if (check_code(obj, code_28, &pat_28)) return True;
-+    Bool pat_p    = check_code(obj, code, &pat);
-+    Bool pat_28_p = check_code(obj, code_28, &pat_28);
-+    if (pat_p || pat_28_p) return True;
-     return False;
- #endif
- 
-@@ -186,9 +194,98 @@ static Bool search_runtime_resolve(obj_node* obj)
-     static struct pattern pat = {
- 	"amd64-def", 110, {{ 0,62 }, { 66,44 }, { 110,0 }} };
- 
-+    static UChar code_xsavec[] = {
-+	/* 0*/ 0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xe4, 0xc0,
-+	/* 8*/ 0x48, 0x2b, 0x25, 0x00, 0x00, 0x00, 0x00, /* sub <i32>(%rip),%rsp */
-+	/*15*/ 0x48,
-+	/*16*/ 0x89, 0x04, 0x24, 0x48, 0x89, 0x4c, 0x24, 0x08,
-+	/*24*/ 0x48, 0x89, 0x54, 0x24, 0x10, 0x48, 0x89, 0x74,
-+	/*32*/ 0x24, 0x18, 0x48, 0x89, 0x7c, 0x24, 0x20, 0x4c,
-+	/*40*/ 0x89, 0x44, 0x24, 0x28, 0x4c, 0x89, 0x4c, 0x24,
-+	/*48*/ 0x30, 0xb8, 0xee, 0x00, 0x00, 0x00, 0x31, 0xd2,
-+	/*56*/ 0x48, 0x89, 0x94, 0x24, 0x50, 0x02, 0x00, 0x00,
-+	/*64*/ 0x48, 0x89, 0x94, 0x24, 0x58, 0x02, 0x00, 0x00,
-+	/*72*/ 0x48, 0x89, 0x94, 0x24, 0x60, 0x02, 0x00, 0x00,
-+	/*80*/ 0x48, 0x89, 0x94, 0x24, 0x68, 0x02, 0x00, 0x00,
-+	/*88*/ 0x48, 0x89, 0x94, 0x24, 0x70, 0x02, 0x00, 0x00,
-+	/*96*/ 0x48, 0x89, 0x94, 0x24, 0x78, 0x02, 0x00, 0x00,
-+	/*04*/ 0x0f, 0xc7, 0x64, 0x24, 0x40, 0x48, 0x8b, 0x73,
-+	/*112*/0x10, 0x48, 0x8b, 0x7b, 0x08,
-+	/*117*/0xe8, 0x00, 0x00, 0x00, 0x00,		/* callq <_dl_fixup> */
-+	/*122*/0x49, 0x89, 0xc3, 0xb8, 0xee, 0x00,
-+	/*128*/0x00, 0x00, 0x31, 0xd2, 0x0f, 0xae, 0x6c, 0x24,
-+	/*136*/0x40, 0x4c, 0x8b, 0x4c, 0x24, 0x30, 0x4c, 0x8b,
-+	/*144*/0x44, 0x24, 0x28, 0x48, 0x8b, 0x7c, 0x24, 0x20,
-+	/*152*/0x48, 0x8b, 0x74, 0x24, 0x18, 0x48, 0x8b, 0x54,
-+	/*160*/0x24, 0x10, 0x48, 0x8b, 0x4c, 0x24, 0x08, 0x48,
-+	/*168*/0x8b, 0x04, 0x24, 0x48, 0x89, 0xdc, 0x48, 0x8b,
-+	/*176*/0x1c, 0x24, 0x48, 0x83, 0xc4, 0x18, 0xf2, 0x41,
-+	/*184*/0xff, 0xe3 };
-+    static struct pattern pat_xsavec = {
-+	    "amd64-xsavec", 186, {{ 0,11 }, { 15,103 }, {122,64}, { 186,0 }} };
-+
-+    static UChar code_xsave[] = {
-+	/* 0*/ 0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xe4, 0xc0,
-+	/* 8*/ 0x48, 0x2b, 0x25, 0x00, 0x00, 0x00, 0x00, /* sub <i32>(%rip),%rsp */
-+	/*15*/ 0x48,
-+	/*16*/ 0x89, 0x04, 0x24, 0x48, 0x89, 0x4c, 0x24, 0x08,
-+	/*24*/ 0x48, 0x89, 0x54, 0x24, 0x10, 0x48, 0x89, 0x74,
-+	/*32*/ 0x24, 0x18, 0x48, 0x89, 0x7c, 0x24, 0x20, 0x4c,
-+	/*40*/ 0x89, 0x44, 0x24, 0x28, 0x4c, 0x89, 0x4c, 0x24,
-+	/*48*/ 0x30, 0xb8, 0xee, 0x00, 0x00, 0x00, 0x31, 0xd2,
-+	/*56*/ 0x48, 0x89, 0x94, 0x24, 0x40, 0x02, 0x00, 0x00,
-+	/*64*/ 0x48, 0x89, 0x94, 0x24, 0x48, 0x02, 0x00, 0x00,
-+	/*72*/ 0x48, 0x89, 0x94, 0x24, 0x50, 0x02, 0x00, 0x00,
-+	/*80*/ 0x48, 0x89, 0x94, 0x24, 0x58, 0x02, 0x00, 0x00,
-+	/*88*/ 0x48, 0x89, 0x94, 0x24, 0x60, 0x02, 0x00, 0x00,
-+	/*96*/ 0x48, 0x89, 0x94, 0x24, 0x68, 0x02, 0x00, 0x00,
-+	/*104*/0x48, 0x89, 0x94, 0x24, 0x70, 0x02, 0x00, 0x00,
-+	/*112*/0x48, 0x89, 0x94, 0x24, 0x78, 0x02, 0x00, 0x00,
-+	/*120*/0x0f, 0xae, 0x64, 0x24, 0x40, 0x48, 0x8b, 0x73,
-+	/*128*/0x10, 0x48, 0x8b, 0x7b, 0x08,
-+	/*133*/0xe8, 0x00, 0x00, 0x00, 0x00,		/* callq <_dl_fixup> */
-+	/*138*/0x49, 0x89, 0xc3, 0xb8, 0xee, 0x00,
-+	/*144*/0x00, 0x00, 0x31, 0xd2, 0x0f, 0xae, 0x6c, 0x24,
-+	/*152*/0x40, 0x4c, 0x8b, 0x4c, 0x24, 0x30, 0x4c, 0x8b,
-+	/*160*/0x44, 0x24, 0x28, 0x48, 0x8b, 0x7c, 0x24, 0x20,
-+	/*168*/0x48, 0x8b, 0x74, 0x24, 0x18, 0x48, 0x8b, 0x54,
-+	/*176*/0x24, 0x10, 0x48, 0x8b, 0x4c, 0x24, 0x08, 0x48,
-+	/*184*/0x8b, 0x04, 0x24, 0x48, 0x89, 0xdc, 0x48, 0x8b,
-+	/*192*/0x1c, 0x24, 0x48, 0x83, 0xc4, 0x18, 0xf2, 0x41,
-+	/*200*/0xff, 0xe3 };
-+    static struct pattern pat_xsave = {
-+	"amd64-xsave", 202, {{ 0,11 }, { 15,119 }, {138,64}, { 202,0 }} };
-+
-+    static UChar code_fxsave[] = {
-+	/* 0*/ 0x53, 0x48, 0x89, 0xe3, 0x48, 0x83, 0xe4, 0xf0,
-+	/* 8*/ 0x48, 0x81, 0xec, 0x40, 0x02, 0x00, 0x00, 0x48,
-+	/*16*/ 0x89, 0x04, 0x24, 0x48, 0x89, 0x4c, 0x24, 0x08,
-+	/*24*/ 0x48, 0x89, 0x54, 0x24, 0x10, 0x48, 0x89, 0x74,
-+	/*32*/ 0x24, 0x18, 0x48, 0x89, 0x7c, 0x24, 0x20, 0x4c,
-+	/*40*/ 0x89, 0x44, 0x24, 0x28, 0x4c, 0x89, 0x4c, 0x24,
-+	/*48*/ 0x30, 0x0f, 0xae, 0x44, 0x24, 0x40, 0x48, 0x8b,
-+	/*56*/ 0x73, 0x10, 0x48, 0x8b, 0x7b, 0x08,
-+	/*62*/ 0xe8, 0x00, 0x00, 0x00, 0x00,		/* callq <_dl_fixup> */
-+	/*67*/ 0x49, 0x89, 0xc3, 0x0f, 0xae,
-+	/*72*/ 0x4c, 0x24, 0x40, 0x4c, 0x8b, 0x4c, 0x24, 0x30,
-+	/*80*/ 0x4c, 0x8b, 0x44, 0x24, 0x28, 0x48, 0x8b, 0x7c,
-+	/*88*/ 0x24, 0x20, 0x48, 0x8b, 0x74, 0x24, 0x18, 0x48,
-+	/*96*/ 0x8b, 0x54, 0x24, 0x10, 0x48, 0x8b, 0x4c, 0x24,
-+	/*104*/0x08, 0x48, 0x8b, 0x04, 0x24, 0x48, 0x89, 0xdc,
-+	/*112*/0x48, 0x8b, 0x1c, 0x24, 0x48, 0x83, 0xc4, 0x18,
-+	/*120*/0xf2, 0x41, 0xff, 0xe3 };
-+    static struct pattern pat_fxsave = {
-+	"amd64-fxsave", 124, {{ 0,63 }, { 67,57 }, { 124,0 }} };
-+
-     if ((VG_(strncmp)(obj->name, "/lib/ld", 7) != 0) &&
--	(VG_(strncmp)(obj->name, "/lib64/ld", 9) != 0)) return False;
--    return check_code(obj, code, &pat);
-+	(VG_(strncmp)(obj->name, "/lib64/ld", 9) != 0) &&
-+	(VG_(strncmp)(obj->name, "/usr/lib/ld", 11) != 0) &&
-+	(VG_(strncmp)(obj->name, "/usr/lib64/ld", 13) != 0)) return False;
-+    Bool pat_p        = check_code(obj, code, &pat);
-+    Bool pat_xsavec_p = check_code(obj, code_xsavec, &pat_xsavec);
-+    Bool pat_xsave_p  = check_code(obj, code_xsave, &pat_xsave);
-+    Bool pat_fxsave_p = check_code(obj, code_fxsave, &pat_fxsave);
-+    if (pat_p || pat_xsavec_p || pat_xsave_p || pat_fxsave_p) return True;
- #endif
- 
-     /* For other platforms, no patterns known */
-@@ -254,7 +351,7 @@ obj_node* new_obj_node(DebugInfo* di, obj_node* next)
- 	i++;
-    }
- 
--   if (runtime_resolve_addr == 0) search_runtime_resolve(obj);
-+   if (runtime_resolve_addrs == 0) search_runtime_resolve(obj);
- 
-    return obj;
- }
-@@ -490,6 +587,7 @@ fn_node* CLG_(get_fn_node)(BB* bb)
-     DebugInfo* di;
-     UInt       line_num;
-     fn_node*   fn;
-+    Int        i;
- 
-     /* fn from debug info is idempotent for a BB */
-     if (bb->fn) return bb->fn;
-@@ -538,12 +636,14 @@ fn_node* CLG_(get_fn_node)(BB* bb)
-     }
-     if (0 == VG_(strcmp)(fnname, "_exit") && !exit_bb)
- 	exit_bb = bb;
--    
--    if (runtime_resolve_addr && 
--	(bb_addr(bb) >= runtime_resolve_addr) &&
--	(bb_addr(bb) < runtime_resolve_addr + runtime_resolve_length)) {
--	/* BB in runtime_resolve found by code check; use this name */
--      fnname = "_dl_runtime_resolve";
-+
-+    for (i = 0; i < runtime_resolve_addrs; i++) {
-+      if ((bb_addr(bb) >= runtime_resolve_addr[i]) &&
-+	  (bb_addr(bb) < runtime_resolve_addr[i] + runtime_resolve_length[i])) {
-+	  /* BB in runtime_resolve found by code check; use this name */
-+	  fnname = "_dl_runtime_resolve";
-+	  break;
-+      }
-     }
- 
-     /* get fn_node struct for this function */
diff --git a/valgrind-3.16.1-dwarf5.patch b/valgrind-3.16.1-dwarf5.patch
deleted file mode 100644
index 24388cb..0000000
--- a/valgrind-3.16.1-dwarf5.patch
+++ /dev/null
@@ -1,2410 +0,0 @@
-From 256a67e6a5a07e37997d3a5ef64204a99b8e5a50 Mon Sep 17 00:00:00 2001
-From: Mark Wielaard <mark@klomp.org>
-Date: Mon, 25 Jan 2021 15:33:34 +0100
-Subject: [PATCH] DWARF5
-
----
- coregrind/m_debuginfo/d3basics.c        |  99 ++++
- coregrind/m_debuginfo/priv_d3basics.h   | 195 +++++-
- coregrind/m_debuginfo/priv_readdwarf.h  |   3 +-
- coregrind/m_debuginfo/priv_readdwarf3.h |   3 +-
- coregrind/m_debuginfo/readdwarf.c       | 465 ++++++++++++---
- coregrind/m_debuginfo/readdwarf3.c      | 748 +++++++++++++++++++-----
- coregrind/m_debuginfo/readelf.c         |  33 +-
- coregrind/m_debuginfo/readmacho.c       |  14 +-
- 8 files changed, 1304 insertions(+), 256 deletions(-)
-
-diff --git a/coregrind/m_debuginfo/d3basics.c b/coregrind/m_debuginfo/d3basics.c
-index b6d13c118..e1127ffe2 100644
---- a/coregrind/m_debuginfo/d3basics.c
-+++ b/coregrind/m_debuginfo/d3basics.c
-@@ -128,6 +128,16 @@ const HChar* ML_(pp_DW_TAG) ( DW_TAG tag )
-       case DW_TAG_type_unit:          return "DW_TAG_type_unit";
-       case DW_TAG_rvalue_reference_type: return "DW_TAG_rvalue_reference_type";
-       case DW_TAG_template_alias:     return "DW_TAG_template_alias";
-+      /* DWARF 5.  */
-+      case DW_TAG_coarray_type:       return "DW_TAG_coarray_type";
-+      case DW_TAG_generic_subrange:   return "DW_TAG_generic_subrange";
-+      case DW_TAG_dynamic_type:       return "DW_TAG_dynamic_type";
-+      case DW_TAG_atomic_type:        return "DW_TAG_atomic_type";
-+      case DW_TAG_call_site:          return "DW_TAG_call_site";
-+      case DW_TAG_call_site_parameter:
-+         return "DW_TAG_call_site_parameter";
-+      case DW_TAG_skeleton_unit:      return "DW_TAG_skeleton_unit";
-+      case DW_TAG_immutable_type:     return "DW_TAG_immutable_type";
-       /* SGI/MIPS Extensions.  */
-       case DW_TAG_MIPS_loop:          return "DW_TAG_MIPS_loop";
-       /* HP extensions.  See:
-@@ -140,6 +150,16 @@ const HChar* ML_(pp_DW_TAG) ( DW_TAG tag )
-       case DW_TAG_class_template:     return "DW_TAG_class_template";
-       case DW_TAG_GNU_BINCL:          return "DW_TAG_GNU_BINCL";
-       case DW_TAG_GNU_EINCL:          return "DW_TAG_GNU_EINCL";
-+      case DW_TAG_GNU_template_template_param:
-+         return "DW_TAG_GNU_template_template_param";
-+      case DW_TAG_GNU_template_parameter_pack:
-+         return"DW_TAG_GNU_template_parameter_pack";
-+      case DW_TAG_GNU_formal_parameter_pack:
-+         return "DW_TAG_GNU_formal_parameter_pack";
-+      case DW_TAG_GNU_call_site:
-+         return "DW_TAG_GNU_call_site";
-+      case DW_TAG_GNU_call_site_parameter:
-+         return "DW_TAG_GNU_call_site_parameter";
-       /* Extensions for UPC.  See: http://upc.gwu.edu/~upc.  */
-       case DW_TAG_upc_shared_type:    return "DW_TAG_upc_shared_type";
-       case DW_TAG_upc_strict_type:    return "DW_TAG_upc_strict_type";
-@@ -180,6 +200,27 @@ const HChar* ML_(pp_DW_FORM) ( DW_FORM form )
-       case DW_FORM_exprloc:   return "DW_FORM_exprloc";
-       case DW_FORM_flag_present:return "DW_FORM_flag_present";
-       case DW_FORM_ref_sig8:  return "DW_FORM_ref_sig8";
-+      case DW_FORM_strx:      return "DW_FORM_strx";
-+      case DW_FORM_addrx:     return "DW_FORM_addrx";
-+      case DW_FORM_ref_sup4:  return "DW_FORM_ref_sup4";
-+      case DW_FORM_strp_sup:  return "DW_FORM_strp_sup";
-+      case DW_FORM_data16:    return "DW_FORM_data16";
-+      case DW_FORM_line_strp: return "DW_FORM_line_strp";
-+      case DW_FORM_implicit_const:return "DW_FORM_implicit_const";
-+      case DW_FORM_loclistx:  return "DW_FORM_loclistx";
-+      case DW_FORM_rnglistx:  return "DW_FORM_rnglistx";
-+      case DW_FORM_ref_sup8:  return "DW_FORM_ref_sup8";
-+      case DW_FORM_strx1:     return "DW_FORM_strx1";
-+      case DW_FORM_strx2:     return "DW_FORM_strx2";
-+      case DW_FORM_strx3:     return "DW_FORM_strx3";
-+      case DW_FORM_strx4:     return "DW_FORM_strx4";
-+      case DW_FORM_addrx1:    return "DW_FORM_addrx1";
-+      case DW_FORM_addrx2:    return "DW_FORM_addrx2";
-+      case DW_FORM_addrx3:    return "DW_FORM_addrx3";
-+      case DW_FORM_addrx4:    return "DW_FORM_addrx4";
-+      /* GNU Debug Fission extensions.  */
-+      case DW_FORM_GNU_addr_index:return "DW_FORM_GNU_addr_index";
-+      case DW_FORM_GNU_str_index:return "DW_FORM_GNU_str_index";
-       case DW_FORM_GNU_ref_alt:return "DW_FORM_GNU_ref_alt";
-       case DW_FORM_GNU_strp_alt:return "DW_FORM_GNU_strp_alt";
-    }
-@@ -286,6 +327,36 @@ const HChar* ML_(pp_DW_AT) ( DW_AT attr )
-       case DW_AT_const_expr: return "DW_AT_const_expr";
-       case DW_AT_enum_class: return "DW_AT_enum_class";
-       case DW_AT_linkage_name: return "DW_AT_linkage_name";
-+      /* DWARF 5 values.  */
-+      case DW_AT_string_length_bit_size: return "DW_AT_string_length_bit_size";
-+      case DW_AT_string_length_byte_size: return "DW_AT_string_length_byte_size";
-+      case DW_AT_rank: return "DW_AT_rank";
-+      case DW_AT_str_offsets_base: return "DW_AT_str_offsets_base";
-+      case DW_AT_addr_base: return "DW_AT_addr_base";
-+      case DW_AT_rnglists_base: return "DW_AT_rnglists_base";
-+      case DW_AT_dwo_name: return "DW_AT_dwo_name";
-+      case DW_AT_reference: return "DW_AT_reference";
-+      case DW_AT_rvalue_reference: return "DW_AT_rvalue_reference";
-+      case DW_AT_macros: return "DW_AT_macros";
-+      case DW_AT_call_all_calls: return "DW_AT_call_all_calls";
-+      case DW_AT_call_all_source_calls: return "DW_AT_call_all_source_calls";
-+      case DW_AT_call_all_tail_calls: return "DW_AT_call_all_tail_calls";
-+      case DW_AT_call_return_pc: return "DW_AT_call_return_pc";
-+      case DW_AT_call_value: return "DW_AT_call_value";
-+      case DW_AT_call_origin: return "DW_AT_call_origin";
-+      case DW_AT_call_parameter: return "DW_AT_call_parameter";
-+      case DW_AT_call_pc: return "DW_AT_call_pc";
-+      case DW_AT_call_tail_call: return "DW_AT_call_tail_call";
-+      case DW_AT_call_target: return "DW_AT_call_target";
-+      case DW_AT_call_target_clobbered: return "DW_AT_call_target_clobbered";
-+      case DW_AT_call_data_location: return "DW_AT_call_data_location";
-+      case DW_AT_call_data_value: return "DW_AT_call_data_value";
-+      case DW_AT_noreturn: return "DW_AT_noreturn";
-+      case DW_AT_alignment: return "DW_AT_alignment";
-+      case DW_AT_export_symbols: return "DW_AT_export_symbols";
-+      case DW_AT_deleted: return "DW_AT_deleted";
-+      case DW_AT_defaulted: return "DW_AT_defaulted";
-+      case DW_AT_loclists_base: return "DW_AT_loclists_base";
-       /* SGI/MIPS extensions.  */
-       /* case DW_AT_MIPS_fde: return "DW_AT_MIPS_fde"; */
-       /* DW_AT_MIPS_fde == DW_AT_HP_unmodifiable */
-@@ -322,8 +393,36 @@ const HChar* ML_(pp_DW_AT) ( DW_AT attr )
-       case DW_AT_body_begin: return "DW_AT_body_begin";
-       case DW_AT_body_end: return "DW_AT_body_end";
-       case DW_AT_GNU_vector: return "DW_AT_GNU_vector";
-+      case DW_AT_GNU_guarded_by: return "DW_AT_GNU_guarded_by";
-+      case DW_AT_GNU_pt_guarded_by: return "DW_AT_GNU_pt_guarded_by";
-+      case DW_AT_GNU_guarded: return "DW_AT_GNU_guarded";
-+      case DW_AT_GNU_pt_guarded: return "DW_AT_GNU_pt_guarded";
-+      case DW_AT_GNU_locks_excluded: return "DW_AT_GNU_locks_excluded";
-+      case DW_AT_GNU_exclusive_locks_required: return "DW_AT_GNU_exclusive_locks_required";
-+      case DW_AT_GNU_shared_locks_required: return "DW_AT_GNU_shared_locks_required";
-+      case DW_AT_GNU_odr_signature: return "DW_AT_GNU_odr_signature";
-+      case DW_AT_GNU_template_name: return "DW_AT_GNU_template_name";
-+      case DW_AT_GNU_call_site_value: return "DW_AT_GNU_call_site_value";
-+      case DW_AT_GNU_call_site_data_value: return "DW_AT_GNU_call_site_data_value";
-+      case DW_AT_GNU_call_site_target: return "DW_AT_GNU_call_site_target";
-+      case DW_AT_GNU_call_site_target_clobbered: return "DW_AT_GNU_call_site_target_clobbered";
-+      case DW_AT_GNU_tail_call: return "DW_AT_GNU_tail_call";
-       case DW_AT_GNU_all_tail_call_sites: return "DW_AT_GNU_all_tail_call_sites";
-       case DW_AT_GNU_all_call_sites: return "DW_AT_GNU_all_call_sites";
-+      case DW_AT_GNU_all_source_call_sites: return "DW_AT_GNU_all_source_call_sites";
-+      case DW_AT_GNU_locviews: return "DW_AT_GNU_locviews";
-+      case DW_AT_GNU_entry_view: return "DW_AT_GNU_entry_view";
-+      case DW_AT_GNU_macros: return "DW_AT_GNU_macros";
-+      case DW_AT_GNU_deleted: return "DW_AT_GNU_deleted";
-+      case DW_AT_GNU_dwo_name: return "DW_AT_GNU_dwo_name";
-+      case DW_AT_GNU_dwo_id: return "DW_AT_GNU_dwo_id";
-+      case DW_AT_GNU_ranges_base: return "DW_AT_GNU_ranges_base";
-+      case DW_AT_GNU_addr_base: return "DW_AT_GNU_addr_base";
-+      case DW_AT_GNU_pubnames: return "DW_AT_GNU_pubnames";
-+      case DW_AT_GNU_pubtypes: return "DW_AT_GNU_pubtypes";
-+      case DW_AT_GNU_numerator: return "DW_AT_GNU_numerator";
-+      case DW_AT_GNU_denominator: return "DW_AT_GNU_denominator";
-+      case DW_AT_GNU_bias: return "DW_AT_GNU_bias";
-       /* VMS extensions.  */
-       case DW_AT_VMS_rtnbeg_pd_address: return "DW_AT_VMS_rtnbeg_pd_address";
-       /* UPC extension.  */
-diff --git a/coregrind/m_debuginfo/priv_d3basics.h b/coregrind/m_debuginfo/priv_d3basics.h
-index b60e3e8eb..9d825e39e 100644
---- a/coregrind/m_debuginfo/priv_d3basics.h
-+++ b/coregrind/m_debuginfo/priv_d3basics.h
-@@ -108,6 +108,15 @@ typedef enum
-     DW_TAG_type_unit = 0x41,
-     DW_TAG_rvalue_reference_type = 0x42,
-     DW_TAG_template_alias = 0x43,
-+    /* DWARF 5.  */
-+    DW_TAG_coarray_type = 0x44,
-+    DW_TAG_generic_subrange = 0x45,
-+    DW_TAG_dynamic_type = 0x46,
-+    DW_TAG_atomic_type = 0x47,
-+    DW_TAG_call_site = 0x48,
-+    DW_TAG_call_site_parameter = 0x49,
-+    DW_TAG_skeleton_unit = 0x4a,
-+    DW_TAG_immutable_type = 0x4b,
-     /* SGI/MIPS Extensions.  */
-     DW_TAG_MIPS_loop = 0x4081,
-     /* HP extensions.  See: ftp://ftp.hp.com/pub/lang/tools/WDB/wdb-4.0.tar.gz .  */
-@@ -118,6 +127,11 @@ typedef enum
-     DW_TAG_class_template = 0x4103,	/* For C++.  */
-     DW_TAG_GNU_BINCL = 0x4104,
-     DW_TAG_GNU_EINCL = 0x4105,
-+    DW_TAG_GNU_template_template_param = 0x4106,
-+    DW_TAG_GNU_template_parameter_pack = 0x4107,
-+    DW_TAG_GNU_formal_parameter_pack = 0x4108,
-+    DW_TAG_GNU_call_site = 0x4109,
-+    DW_TAG_GNU_call_site_parameter = 0x410a,
-     /* Extensions for UPC.  See: http://upc.gwu.edu/~upc.  */
-     DW_TAG_upc_shared_type = 0x8765,
-     DW_TAG_upc_strict_type = 0x8766,
-@@ -164,13 +178,23 @@ typedef enum dwarf_source_language
-     DW_LANG_D = 0x0013,
-     /* DWARF 4.  */
-     DW_LANG_Python = 0x0014,
--    /* DWARF 5-pre. Only what GCC already outputs. */
-+    /* DWARF 5.  */
-     DW_LANG_Go = 0x0016,
-+    DW_LANG_Modula3 = 0x0017,
-+    DW_LANG_Haskell = 0x0018,
-+    DW_LANG_C_plus_plus_03 = 0x0019,
-     DW_LANG_C_plus_plus_11 = 0x001a,
-+    DW_LANG_OCaml = 0x001b,
-+    DW_LANG_Rust = 0x001c,
-     DW_LANG_C11 = 0x001d,
-+    DW_LANG_Swift = 0x001e,
-+    DW_LANG_Julia = 0x001f,
-+    DW_LANG_Dylan = 0x0020,
-     DW_LANG_C_plus_plus_14 = 0x0021,
-     DW_LANG_Fortran03 = 0x0022,
-     DW_LANG_Fortran08 = 0x0023,
-+    DW_LANG_RenderScript = 0x0024,
-+    DW_LANG_BLISS = 0x0025,
-     /* MIPS.  */
-     DW_LANG_Mips_Assembler = 0x8001,
-     /* UPC.  */
-@@ -207,6 +231,28 @@ typedef enum
-     DW_FORM_exprloc = 0x18,
-     DW_FORM_flag_present = 0x19,
-     DW_FORM_ref_sig8 = 0x20,
-+    /* DWARF 5 values.  */
-+    DW_FORM_strx = 0x1a,
-+    DW_FORM_addrx = 0x1b,
-+    DW_FORM_ref_sup4 = 0x1c,
-+    DW_FORM_strp_sup = 0x1d,
-+    DW_FORM_data16 = 0x1e,
-+    DW_FORM_line_strp = 0x1f,
-+    DW_FORM_implicit_const = 0x21,
-+    DW_FORM_loclistx = 0x22,
-+    DW_FORM_rnglistx = 0x23,
-+    DW_FORM_ref_sup8 = 0x24,
-+    DW_FORM_strx1 = 0x25,
-+    DW_FORM_strx2 = 0x26,
-+    DW_FORM_strx3 = 0x27,
-+    DW_FORM_strx4 = 0x28,
-+    DW_FORM_addrx1 = 0x29,
-+    DW_FORM_addrx2 = 0x2a,
-+    DW_FORM_addrx3 = 0x2b,
-+    DW_FORM_addrx4 = 0x2c,
-+    /* GNU Debug Fission extensions.  */
-+    DW_FORM_GNU_addr_index = 0x1f01,
-+    DW_FORM_GNU_str_index = 0x1f02,
-     /* Extensions for DWZ multifile.
-        See http://www.dwarfstd.org/ShowIssue.php?issue=120604.1&type=open .  */
-     DW_FORM_GNU_ref_alt = 0x1f20,
-@@ -314,6 +360,36 @@ typedef enum
-     DW_AT_const_expr      = 0x6c,
-     DW_AT_enum_class      = 0x6d,
-     DW_AT_linkage_name    = 0x6e,
-+    DW_AT_string_length_bit_size = 0x6f,
-+    DW_AT_string_length_byte_size = 0x70,
-+    DW_AT_rank = 0x71,
-+    DW_AT_str_offsets_base = 0x72,
-+    DW_AT_addr_base = 0x73,
-+    DW_AT_rnglists_base = 0x74,
-+    /* 0x75 reserved.  */
-+    DW_AT_dwo_name = 0x76,
-+    DW_AT_reference = 0x77,
-+    DW_AT_rvalue_reference = 0x78,
-+    DW_AT_macros = 0x79,
-+    DW_AT_call_all_calls = 0x7a,
-+    DW_AT_call_all_source_calls = 0x7b,
-+    DW_AT_call_all_tail_calls = 0x7c,
-+    DW_AT_call_return_pc = 0x7d,
-+    DW_AT_call_value = 0x7e,
-+    DW_AT_call_origin = 0x7f,
-+    DW_AT_call_parameter = 0x80,
-+    DW_AT_call_pc = 0x81,
-+    DW_AT_call_tail_call = 0x82,
-+    DW_AT_call_target = 0x83,
-+    DW_AT_call_target_clobbered = 0x84,
-+    DW_AT_call_data_location = 0x85,
-+    DW_AT_call_data_value = 0x86,
-+    DW_AT_noreturn = 0x87,
-+    DW_AT_alignment = 0x88,
-+    DW_AT_export_symbols = 0x89,
-+    DW_AT_deleted = 0x8a,
-+    DW_AT_defaulted = 0x8b,
-+    DW_AT_loclists_base = 0x8c,
-     /* SGI/MIPS extensions.  */
-     DW_AT_MIPS_fde = 0x2001,
-     DW_AT_MIPS_loop_begin = 0x2002,
-@@ -349,8 +425,39 @@ typedef enum
-     DW_AT_body_begin = 0x2105,
-     DW_AT_body_end   = 0x2106,
-     DW_AT_GNU_vector = 0x2107,
-+    DW_AT_GNU_guarded_by = 0x2108,
-+    DW_AT_GNU_pt_guarded_by = 0x2109,
-+    DW_AT_GNU_guarded = 0x210a,
-+    DW_AT_GNU_pt_guarded = 0x210b,
-+    DW_AT_GNU_locks_excluded = 0x210c,
-+    DW_AT_GNU_exclusive_locks_required = 0x210d,
-+    DW_AT_GNU_shared_locks_required = 0x210e,
-+    DW_AT_GNU_odr_signature = 0x210f,
-+    DW_AT_GNU_template_name = 0x2110,
-+    DW_AT_GNU_call_site_value = 0x2111,
-+    DW_AT_GNU_call_site_data_value = 0x2112,
-+    DW_AT_GNU_call_site_target = 0x2113,
-+    DW_AT_GNU_call_site_target_clobbered = 0x2114,
-+    DW_AT_GNU_tail_call = 0x2115,
-     DW_AT_GNU_all_tail_call_sites = 0x2116,
-     DW_AT_GNU_all_call_sites = 0x2117,
-+    DW_AT_GNU_all_source_call_sites = 0x2118,
-+    DW_AT_GNU_locviews = 0x2137,
-+    DW_AT_GNU_entry_view = 0x2138,
-+    DW_AT_GNU_macros = 0x2119,
-+    DW_AT_GNU_deleted = 0x211a,
-+    /* GNU Debug Fission extensions.  */
-+    DW_AT_GNU_dwo_name = 0x2130,
-+    DW_AT_GNU_dwo_id = 0x2131,
-+    DW_AT_GNU_ranges_base = 0x2132,
-+    DW_AT_GNU_addr_base = 0x2133,
-+    DW_AT_GNU_pubnames = 0x2134,
-+    DW_AT_GNU_pubtypes = 0x2135,
-+    /* https://gcc.gnu.org/wiki/DW_AT_GNU_numerator_denominator  */
-+    DW_AT_GNU_numerator = 0x2303,
-+    DW_AT_GNU_denominator = 0x2304,
-+    /* https://gcc.gnu.org/wiki/DW_AT_GNU_bias  */
-+    DW_AT_GNU_bias = 0x2305,
-     /* VMS extensions.  */
-     DW_AT_VMS_rtnbeg_pd_address = 0x2201,
-     /* UPC extension.  */
-@@ -387,6 +494,9 @@ typedef enum
-     DW_ATE_decimal_float = 0xf,
-     /* DWARF 4.  */
-     DW_ATE_UTF = 0x10,
-+    /* DWARF 5.  */
-+    DW_ATE_UCS = 0x11,
-+    DW_ATE_ASCII = 0x12,
-     /* HP extensions.  */
-     DW_ATE_HP_float80            = 0x80, /* Floating-point (80 bit).  */
-     DW_ATE_HP_complex_float80    = 0x81, /* Complex floating-point (80 bit).  */
-@@ -558,8 +668,35 @@ typedef enum
-     /* DWARF 4 extensions.  */
-     DW_OP_implicit_value = 0x9e,
-     DW_OP_stack_value = 0x9f,
-+    /* DWARF 5 extensions.  */
-+    DW_OP_implicit_pointer = 0xa0,
-+    DW_OP_addrx = 0xa1,
-+    DW_OP_constx = 0xa2,
-+    DW_OP_entry_value = 0xa3,
-+    DW_OP_const_type = 0xa4,
-+    DW_OP_regval_type = 0xa5,
-+    DW_OP_deref_type = 0xa6,
-+    DW_OP_xderef_type = 0xa7,
-+    DW_OP_convert = 0xa8,
-+    DW_OP_reinterpret = 0xa9,
-     /* GNU extensions.  */
-     DW_OP_GNU_push_tls_address = 0xe0,
-+    DW_OP_GNU_uninit = 0xf0,
-+    DW_OP_GNU_encoded_addr = 0xf1,
-+    DW_OP_GNU_implicit_pointer = 0xf2,
-+    DW_OP_GNU_entry_value = 0xf3,
-+    DW_OP_GNU_const_type = 0xf4,
-+    DW_OP_GNU_regval_type = 0xf5,
-+    DW_OP_GNU_deref_type = 0xf6,
-+    DW_OP_GNU_convert = 0xf7,
-+    DW_OP_GNU_reinterpret = 0xf9,
-+    DW_OP_GNU_parameter_ref = 0xfa,
-+    /* GNU Debug Fission extensions.  */
-+    DW_OP_GNU_addr_index = 0xfb,
-+    DW_OP_GNU_const_index = 0xfc,
-+    /* The GNU variable value extension.
-+       See http://dwarfstd.org/ShowIssue.php?issue=161109.2 . */
-+    DW_OP_GNU_variable_value = 0xfd,
-     /* HP extensions.  */
-     DW_OP_HP_unknown     = 0xe0, /* Ouch, the same as GNU_push_tls_address.  */
-     DW_OP_HP_is_value    = 0xe1,
-@@ -571,6 +708,62 @@ typedef enum
-   }
-   DW_OP;
- 
-+typedef enum
-+  {
-+    DW_UT_compile = 0x01,
-+    DW_UT_type = 0x02,
-+    DW_UT_partial = 0x03,
-+    DW_UT_skeleton = 0x04,
-+    DW_UT_split_compile = 0x05,
-+    DW_UT_split_type = 0x06,
-+
-+    DW_UT_lo_user = 0x80,
-+    DW_UT_hi_user = 0xff
-+  }
-+  DW_UT;
-+
-+typedef enum
-+  {
-+    DW_LNCT_path = 0x1,
-+    DW_LNCT_directory_index = 0x2,
-+    DW_LNCT_timestamp = 0x3,
-+    DW_LNCT_size = 0x4,
-+    DW_LNCT_MD5 = 0x5,
-+
-+    DW_LNCT_lo_user = 0x2000,
-+    DW_LNCT_hi_user = 0x3fff
-+  }
-+  DW_LNCT;
-+
-+typedef enum
-+  {
-+    DW_RLE_end_of_list = 0x00,
-+    DW_RLE_base_addressx = 0x01,
-+    DW_RLE_startx_endx = 0x02,
-+    DW_RLE_startx_length = 0x03,
-+    DW_RLE_offset_pair = 0x04,
-+    DW_RLE_base_address = 0x05,
-+    DW_RLE_start_end = 0x06,
-+    DW_RLE_start_length = 0x07
-+  }
-+  DW_RLE;
-+
-+typedef enum
-+  {
-+    DW_LLE_end_of_list = 0x00,
-+    DW_LLE_base_addressx = 0x01,
-+    DW_LLE_startx_endx = 0x02,
-+    DW_LLE_startx_length = 0x03,
-+    DW_LLE_offset_pair = 0x04,
-+    DW_LLE_default_location = 0x05,
-+    DW_LLE_base_address = 0x06,
-+    DW_LLE_start_end = 0x07,
-+    DW_LLE_start_length = 0x08,
-+
-+    DW_LLE_GNU_view_pair = 0x09
-+  }
-+  DW_LLE;
-+
- const HChar* ML_(pp_DW_children) ( DW_children hashch );
- const HChar* ML_(pp_DW_TAG)      ( DW_TAG tag );
- const HChar* ML_(pp_DW_FORM)     ( DW_FORM form );
-diff --git a/coregrind/m_debuginfo/priv_readdwarf.h b/coregrind/m_debuginfo/priv_readdwarf.h
-index 1e3f24c2a..302266924 100644
---- a/coregrind/m_debuginfo/priv_readdwarf.h
-+++ b/coregrind/m_debuginfo/priv_readdwarf.h
-@@ -50,7 +50,8 @@ void ML_(read_debuginfo_dwarf3)
-           DiSlice escn_debug_abbv,      /* .debug_abbrev */
-           DiSlice escn_debug_line,      /* .debug_line */
-           DiSlice escn_debug_str,       /* .debug_str */
--          DiSlice escn_debug_str_alt ); /* .debug_str */
-+          DiSlice escn_debug_str_alt,   /* .debug_str */
-+          DiSlice escn_debug_line_str );/* .debug_line_str */
- 
- /* --------------------
-    DWARF1 reader
-diff --git a/coregrind/m_debuginfo/priv_readdwarf3.h b/coregrind/m_debuginfo/priv_readdwarf3.h
-index 1a5bd61c3..f6d1dd1ee 100644
---- a/coregrind/m_debuginfo/priv_readdwarf3.h
-+++ b/coregrind/m_debuginfo/priv_readdwarf3.h
-@@ -45,9 +45,10 @@ ML_(new_dwarf3_reader) (
-    DiSlice escn_debug_info,      DiSlice escn_debug_types,
-    DiSlice escn_debug_abbv,      DiSlice escn_debug_line,
-    DiSlice escn_debug_str,       DiSlice escn_debug_ranges,
-+   DiSlice escn_debug_rnglists,  DiSlice escn_debug_loclists,
-    DiSlice escn_debug_loc,       DiSlice escn_debug_info_alt,
-    DiSlice escn_debug_abbv_alt,  DiSlice escn_debug_line_alt,
--   DiSlice escn_debug_str_alt
-+   DiSlice escn_debug_str_alt,   DiSlice escn_debug_line_str
- );
- 
- #endif /* ndef __PRIV_READDWARF3_H */
-diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c
-index 5701c504b..88d5d99f1 100644
---- a/coregrind/m_debuginfo/readdwarf.c
-+++ b/coregrind/m_debuginfo/readdwarf.c
-@@ -322,6 +322,123 @@ void process_extended_line_op( struct _DebugInfo* di,
- ////////////////////////////////////////////////////////////////////
- ////////////////////////////////////////////////////////////////////
- 
-+static
-+HChar * get_line_str (struct _DebugInfo* di, const UnitInfo* ui,
-+                      DiCursor *data, const UInt form,
-+                      DiCursor debugstr_img, DiCursor debuglinestr_img)
-+{
-+   HChar *str = NULL;
-+   switch (form) {
-+   case DW_FORM_string:
-+      str = ML_(cur_step_strdup)(data, "di.gls.string");
-+      break;
-+   case DW_FORM_strp:
-+      if (!ui->dw64)
-+         str = ML_(cur_read_strdup)(ML_(cur_plus)(debugstr_img,
-+                                                  ML_(cur_step_UInt)(data)),
-+                                    "di.gls.strp.dw32");
-+      else
-+         str = ML_(cur_read_strdup)(ML_(cur_plus)(debugstr_img,
-+                                                  ML_(cur_step_ULong)(data)),
-+                                    "di.gls.strp.dw64");
-+      break;
-+   case DW_FORM_line_strp:
-+      if (!ui->dw64)
-+         str = ML_(cur_read_strdup)(ML_(cur_plus)(debuglinestr_img,
-+                                                  ML_(cur_step_UInt)(data)),
-+                                    "di.gls.line_strp.dw32");
-+      else
-+         str = ML_(cur_read_strdup)(ML_(cur_plus)(debuglinestr_img,
-+                                                  ML_(cur_step_ULong)(data)),
-+                                    "di.gls.line_strp.dw64");
-+      break;
-+   default:
-+      ML_(symerr)(di, True,
-+                  "Unknown path string FORM in .debug_line");
-+      break;
-+   }
-+   return str;
-+}
-+
-+static
-+Int get_line_ndx (struct _DebugInfo* di,
-+                  DiCursor *data, const UInt form)
-+{
-+   Int res = 0;
-+   switch (form) {
-+   case DW_FORM_data1:
-+      res = ML_(cur_step_UChar)(data);
-+      break;
-+   case DW_FORM_data2:
-+      res = ML_(cur_step_UShort)(data);
-+      break;
-+   case DW_FORM_udata:
-+      res = step_leb128U(data);
-+      break;
-+   default:
-+      ML_(symerr)(di, True,
-+                  "Unknown directory_index value FORM in .debug_line");
-+      break;
-+   }
-+   return res;
-+}
-+
-+static
-+DiCursor skip_line_form (struct _DebugInfo* di, const UnitInfo* ui,
-+                         DiCursor d, const UInt form)
-+{
-+   switch (form) {
-+   case DW_FORM_block: {
-+      ULong len = step_leb128U(&d);
-+      d = ML_(cur_plus)(d, len);
-+      break;
-+   }
-+   case DW_FORM_block1:
-+      d = ML_(cur_plus)(d, ML_(cur_read_UChar)(d) + 1);
-+      break;
-+   case DW_FORM_block2:
-+      d = ML_(cur_plus)(d, ML_(cur_read_UShort)(d) + 2);
-+      break;
-+   case DW_FORM_block4:
-+      d = ML_(cur_plus)(d, ML_(cur_read_UInt)(d) + 4);
-+      break;
-+   case DW_FORM_flag:
-+   case DW_FORM_data1:
-+      d = ML_(cur_plus)(d, 1);
-+      break;
-+   case DW_FORM_data2:
-+      d = ML_(cur_plus)(d, 2);
-+      break;
-+   case DW_FORM_data4:
-+      d = ML_(cur_plus)(d, 4);
-+      break;
-+   case DW_FORM_data8:
-+      d = ML_(cur_plus)(d, 8);
-+      break;
-+   case DW_FORM_data16:
-+      d = ML_(cur_plus)(d, 16);
-+      break;
-+   case DW_FORM_string:
-+      d = ML_(cur_plus)(d, ML_(cur_strlen)(d) + 1);
-+      break;
-+   case DW_FORM_strp:
-+   case DW_FORM_line_strp:
-+   case DW_FORM_sec_offset:
-+      d = ML_(cur_plus)(d, ui->dw64 ? 8 : 4);
-+      break;
-+   case DW_FORM_udata:
-+      (void)step_leb128U(&d);
-+      break;
-+   case DW_FORM_sdata:
-+      (void)step_leb128S(&d);
-+      break;
-+   default:
-+      ML_(symerr)(di, True, "Unknown FORM in .debug_line");
-+      break;
-+   }
-+   return d;
-+}
-+
- /* read a .debug_line section block for a compilation unit
-  *
-  * Input:   - theBlock must point to the start of the block
-@@ -335,7 +452,9 @@ static
- void read_dwarf2_lineblock ( struct _DebugInfo* di,
-                              const UnitInfo* ui, 
-                              DiCursor  theBlock, /* IMAGE */
--                             Int       noLargerThan )
-+                             Int       noLargerThan,
-+                             DiCursor  debugstr_img,
-+                             DiCursor  debuglinestr_img)
- {
-    Int            i;
-    DebugLineInfo  info;
-@@ -348,6 +467,9 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
-    DiCursor       external = theBlock;
-    DiCursor       data = theBlock;
- 
-+   UChar          p_ndx = 0, d_ndx = 0; /* DWARF5 path and dir index. */
-+   UInt           forms[256];           /* DWARF5 forms. */
-+
-    /* fndn_ix_xa is an xarray of fndn_ix (indexes in di->fndnpool) which
-       are build from file names harvested from the DWARF2
-       info.  Entry [0] is the "null" pool index and is never referred to
-@@ -372,17 +494,6 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
-    fndn_ix_xa = VG_(newXA) (ML_(dinfo_zalloc), "di.rd2l.2", ML_(dinfo_free),
-                             sizeof(UInt) );
- 
--   /* DWARF2 starts numbering filename entries at 1, so we need to
--      add a dummy zeroth entry to the table. */
--   fndn_ix = 0; // 0 is the "null" index in a fixed pool.
--   VG_(addToXA) (fndn_ix_xa, &fndn_ix);
--
--   if (ML_(cur_is_valid)(ui->compdir))
--      dirname = ML_(addStrFromCursor)(di, ui->compdir);
--   else
--      dirname = ML_(addStr)(di, ".", -1);
--   VG_(addToXA) (dirname_xa, &dirname);
--
-    info.li_length = step_initial_length_field( &external, &is64 );
-    if (di->ddump_line)
-       VG_(printf)("  Length:                      %llu\n", 
-@@ -402,13 +513,19 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
-       VG_(printf)("  DWARF Version:               %d\n", 
-                   (Int)info.li_version);
- 
--   if (info.li_version != 2 && info.li_version != 3 && info.li_version != 4) {
-+   if (info.li_version != 2 && info.li_version != 3 && info.li_version != 4
-+       && info.li_version != 5) {
-       ML_(symerr)(di, True,
--                  "Only DWARF version 2, 3 and 4 line info "
-+                  "Only DWARF version 2, 3, 4 and 5 line info "
-                   "is currently supported.");
-       goto out;
-    }
- 
-+   if (info.li_version >= 5) {
-+      /* UChar addr_size = */ ML_(cur_step_UChar)(&external);
-+      /* UChar seg_size = */  ML_(cur_step_UChar)(&external);
-+   }
-+
-    info.li_header_length = is64 ? ML_(cur_step_ULong)(&external) 
-                                 : (ULong)(ML_(cur_step_UInt)(&external));
-    if (di->ddump_line)
-@@ -485,60 +602,141 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
-    /* skip over "standard_opcode_lengths" */
-    data = ML_(cur_plus)(standard_opcodes, info.li_opcode_base - 1);
- 
--   /* Read the contents of the Directory table.  */
--   if (di->ddump_line)
--      VG_(printf)(" The Directory Table%s\n", 
--                  ML_(cur_read_UChar)(data) == 0 ? " is empty." : ":" );
--
--   while (ML_(cur_read_UChar)(data) != 0) {
-+   if (ML_(cur_is_valid)(ui->compdir))
-+      dirname = ML_(addStrFromCursor)(di, ui->compdir);
-+   else
-+      dirname = ML_(addStr)(di, ".", -1);
- 
--      HChar* data_str = ML_(cur_read_strdup)(data, "di.rd2l.1");
-+   if (info.li_version < 5) {
-+      /* Read the contents of the Directory table.  */
-       if (di->ddump_line)
--         VG_(printf)("  %s\n", data_str);
--
--      /* If data[0] is '/', then 'data' is an absolute path and we
--         don't mess with it.  Otherwise, construct the
--         path 'ui->compdir' ++ "/" ++ 'data'. */
--
--      if (data_str[0] != '/' 
--          /* not an absolute path */
--          && ML_(cur_is_valid)(ui->compdir)
--          /* actually got something sensible for compdir */
--          && ML_(cur_strlen)(ui->compdir))
--      {
--         HChar* compdir_str = ML_(cur_read_strdup)(ui->compdir, "di.rd2l.1b");
--         SizeT  len = VG_(strlen)(compdir_str) + 1 + VG_(strlen)(data_str);
--         HChar *buf = ML_(dinfo_zalloc)("di.rd2l.1c", len + 1);
--
--         VG_(strcpy)(buf, compdir_str);
--         VG_(strcat)(buf, "/");
--         VG_(strcat)(buf, data_str);
--
--         dirname = ML_(addStr)(di, buf, len);
--         VG_(addToXA) (dirname_xa, &dirname);
--         if (0) VG_(printf)("rel path  %s\n", buf);
--         ML_(dinfo_free)(compdir_str);
--         ML_(dinfo_free)(buf);
--      } else {
--         /* just use 'data'. */
--         dirname = ML_(addStr)(di,data_str,-1);
--         VG_(addToXA) (dirname_xa, &dirname);
--         if (0) VG_(printf)("abs path  %s\n", data_str);
-+         VG_(printf)("The Directory Table%s\n",
-+                     ML_(cur_read_UChar)(data) == 0 ? " is empty." : ":" );
-+
-+      /* DWARF2 starts numbering filename entries at 1, so we need to
-+         add a dummy zeroth entry to the table.  */
-+      fndn_ix = 0; // 0 is the "null" index in a fixed pool.
-+      VG_(addToXA) (fndn_ix_xa, &fndn_ix);
-+      VG_(addToXA) (dirname_xa, &dirname);
-+
-+      while (ML_(cur_read_UChar)(data) != 0) {
-+
-+         HChar* data_str = ML_(cur_read_strdup)(data, "di.rd2l.1");
-+         if (di->ddump_line)
-+            VG_(printf)("  %s\n", data_str);
-+
-+         /* If data[0] is '/', then 'data' is an absolute path and we
-+            don't mess with it.  Otherwise, construct the
-+            path 'ui->compdir' ++ "/" ++ 'data'. */
-+
-+         if (data_str[0] != '/'
-+             /* not an absolute path */
-+             && ML_(cur_is_valid)(ui->compdir)
-+             /* actually got something sensible for compdir */
-+             && ML_(cur_strlen)(ui->compdir))
-+         {
-+            HChar* compdir_str = ML_(cur_read_strdup)(ui->compdir,
-+                                                      "di.rd2l.1b");
-+            SizeT  len = VG_(strlen)(compdir_str) + 1 + VG_(strlen)(data_str);
-+            HChar *buf = ML_(dinfo_zalloc)("di.rd2l.1c", len + 1);
-+
-+            VG_(strcpy)(buf, compdir_str);
-+            VG_(strcat)(buf, "/");
-+            VG_(strcat)(buf, data_str);
-+
-+            dirname = ML_(addStr)(di, buf, len);
-+            VG_(addToXA) (dirname_xa, &dirname);
-+            if (0) VG_(printf)("rel path  %s\n", buf);
-+            ML_(dinfo_free)(compdir_str);
-+            ML_(dinfo_free)(buf);
-+         } else {
-+            /* just use 'data'. */
-+            dirname = ML_(addStr)(di,data_str,-1);
-+            VG_(addToXA) (dirname_xa, &dirname);
-+            if (0) VG_(printf)("abs path  %s\n", data_str);
-+         }
-+
-+         data = ML_(cur_plus)(data, VG_(strlen)(data_str) + 1);
-+         ML_(dinfo_free)(data_str);
-       }
- 
--      data = ML_(cur_plus)(data, VG_(strlen)(data_str) + 1);
--      ML_(dinfo_free)(data_str);
--   }
-+      if (di->ddump_line)
-+         VG_(printf)("\n");
- 
--   if (di->ddump_line)
--      VG_(printf)("\n");
-+      if (ML_(cur_read_UChar)(data) != 0) {
-+         ML_(symerr)(di, True,
-+                     "can't find NUL at end of DWARF2 directory table");
-+         goto out;
-+      }
-+      data = ML_(cur_plus)(data, 1);
-+   } else {
-+      UInt directories_count;
-+      UChar directory_entry_format_count = ML_(cur_step_UChar)(&data);
-+      UInt n;
-+      for (n = 0; n < directory_entry_format_count; n++) {
-+         UInt lnct = step_leb128U(&data);
-+         UInt form = step_leb128U(&data);
-+         if (lnct == DW_LNCT_path)
-+            p_ndx = n;
-+         forms[n] = form;
-+      }
-+      directories_count = step_leb128U(&data);
-+      /* Read the contents of the Directory table.  */
-+      if (di->ddump_line)
-+         VG_(printf)(" dwarf The Directory Table%s\n",
-+                     directories_count == 0 ? " is empty." : ":" );
-+
-+      for (n = 0; n < directories_count; n++) {
-+         UInt f;
-+         for (f = 0; f < directory_entry_format_count; f++) {
-+            UInt form = forms[f];
-+            if (f == p_ndx) {
-+               HChar *data_str = get_line_str (di, ui, &data, form,
-+                                               debugstr_img,
-+                                               debuglinestr_img);
-+               if (di->ddump_line)
-+                  VG_(printf)("  %s\n", data_str);
-+
-+               /* If data[0] is '/', then 'data' is an absolute path and we
-+                  don't mess with it.  Otherwise, construct the
-+                  path 'ui->compdir' ++ "/" ++ 'data'. */
-+
-+               if (data_str[0] != '/'
-+                   /* not an absolute path */
-+                   && ML_(cur_is_valid)(ui->compdir)
-+                   /* actually got something sensible for compdir */
-+                   && ML_(cur_strlen)(ui->compdir))
-+               {
-+                  HChar* compdir_str = ML_(cur_read_strdup)(ui->compdir,
-+                                                            "di.rd2l.1b");
-+                  SizeT  len = VG_(strlen)(compdir_str) + 1
-+                     + VG_(strlen)(data_str);
-+                  HChar *buf = ML_(dinfo_zalloc)("di.rd2l.1c", len + 1);
-+
-+                  VG_(strcpy)(buf, compdir_str);
-+                  VG_(strcat)(buf, "/");
-+                  VG_(strcat)(buf, data_str);
-+
-+                  dirname = ML_(addStr)(di, buf, len);
-+                  VG_(addToXA) (dirname_xa, &dirname);
-+                  if (0) VG_(printf)("rel path  %s\n", buf);
-+                  ML_(dinfo_free)(compdir_str);
-+                  ML_(dinfo_free)(buf);
-+               } else {
-+                  /* just use 'data'. */
-+                  dirname = ML_(addStr)(di,data_str,-1);
-+                  VG_(addToXA) (dirname_xa, &dirname);
-+                  if (0) VG_(printf)("abs path  %s\n", data_str);
-+               }
- 
--   if (ML_(cur_read_UChar)(data) != 0) {
--      ML_(symerr)(di, True,
--                  "can't find NUL at end of DWARF2 directory table");
--      goto out;
-+               ML_(dinfo_free)(data_str);
-+
-+            } else {
-+               data = skip_line_form (di, ui, data, form);
-+            }
-+         }
-+      }
-    }
--   data = ML_(cur_plus)(data, 1);
- 
-    /* Read the contents of the File Name table.  This produces a bunch
-       of fndn_ix in fndn_ix_xa. */
-@@ -547,33 +745,76 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
-       VG_(printf)("  Entry	Dir	Time	Size	Name\n");
-    }
- 
--   i = 1;
--   while (ML_(cur_read_UChar)(data) != 0) {
--      HChar* name    = ML_(cur_step_strdup)(&data, "di.rd2l.2");
--      Int    diridx  = step_leb128U(&data);
--      Int    uu_time = step_leb128U(&data); /* unused */
--      Int    uu_size = step_leb128U(&data); /* unused */
-+   if (info.li_version < 5) {
-+      i = 1;
-+      while (ML_(cur_read_UChar)(data) != 0) {
-+         HChar* name    = ML_(cur_step_strdup)(&data, "di.rd2l.2");
-+         Int    diridx  = step_leb128U(&data);
-+         Int    uu_time = step_leb128U(&data); /* unused */
-+         Int    uu_size = step_leb128U(&data); /* unused */
-+
-+         dirname = safe_dirname_ix( dirname_xa, diridx );
-+         fndn_ix = ML_(addFnDn) (di, name, dirname);
-+         VG_(addToXA) (fndn_ix_xa, &fndn_ix);
-+         if (0) VG_(printf)("file %s diridx %d\n", name, diridx );
-+         if (di->ddump_line)
-+            VG_(printf)("  %d\t%d\t%d\t%d\t%s\n",
-+                        i, diridx, uu_time, uu_size, name);
-+         i++;
-+         ML_(dinfo_free)(name);
-+      }
- 
--      dirname = safe_dirname_ix( dirname_xa, diridx );
--      fndn_ix = ML_(addFnDn) (di, name, dirname);
--      VG_(addToXA) (fndn_ix_xa, &fndn_ix);
--      if (0) VG_(printf)("file %s diridx %d\n", name, diridx );
-       if (di->ddump_line)
--         VG_(printf)("  %d\t%d\t%d\t%d\t%s\n", 
--                     i, diridx, uu_time, uu_size, name);
--      i++;
--      ML_(dinfo_free)(name);
--   }
-+         VG_(printf)("\n");
- 
--   if (di->ddump_line)
--      VG_(printf)("\n");
-+      if (ML_(cur_read_UChar)(data) != 0) {
-+         ML_(symerr)(di, True,
-+                     "can't find NUL at end of DWARF2 file name table");
-+         goto out;
-+      }
-+      data = ML_(cur_plus)(data, 1);
-+   } else {
-+      UInt file_names_count;
-+      UChar file_names_entry_format_count = ML_(cur_step_UChar)(&data);
-+      UInt n;
-+      for (n = 0; n < file_names_entry_format_count; n++) {
-+         UInt lnct = step_leb128U(&data);
-+         UInt form = step_leb128U(&data);
-+         if (lnct == DW_LNCT_path)
-+            p_ndx = n;
-+         if (lnct == DW_LNCT_directory_index)
-+            d_ndx = n;
-+         forms[n] = form;
-+      }
-+      file_names_count = step_leb128U(&data);
-+      for (n = 0; n < file_names_count; n++) {
-+         UInt f;
-+         HChar* name = NULL;
-+         Int diridx  = 0;
-+         for (f = 0; f < file_names_entry_format_count; f++) {
-+            UInt form = forms[f];
-+            if (f == p_ndx)
-+               name = get_line_str (di, ui, &data, form,
-+                                    debugstr_img, debuglinestr_img);
-+            else if (n == d_ndx)
-+               diridx = get_line_ndx (di, &data, form);
-+            else
-+               data = skip_line_form (di, ui, data, form);
-+         }
- 
--   if (ML_(cur_read_UChar)(data) != 0) {
--      ML_(symerr)(di, True,
--                  "can't find NUL at end of DWARF2 file name table");
--      goto out;
-+         dirname = safe_dirname_ix( dirname_xa, diridx );
-+         fndn_ix = ML_(addFnDn) (di, name, dirname);
-+         VG_(addToXA) (fndn_ix_xa, &fndn_ix);
-+         if (0) VG_(printf)("file %s diridx %d\n", name, diridx );
-+         if (di->ddump_line)
-+            VG_(printf)("  %u\t%d\t%d\t%d\t%s\n",
-+                        n, diridx, 0, 0, name);
-+         ML_(dinfo_free)(name);
-+      }
-+
-+      if (di->ddump_line)
-+         VG_(printf)("\n");
-    }
--   data = ML_(cur_plus)(data, 1);
- 
-    if (di->ddump_line)
-       VG_(printf)(" Line Number Statements:\n");
-@@ -772,9 +1013,12 @@ static DiCursor lookup_abbrev( DiCursor p, ULong acode )
-       (void)step_leb128U(&p);  /* skip tag */
-       p = ML_(cur_plus)(p,1);  /* skip has_children flag */
-       ULong name;
-+      ULong form;
-       do {
-          name = step_leb128U(&p); /* name */
--         (void)step_leb128U(&p);  /* form */
-+         form = step_leb128U(&p);  /* form */
-+         if (form == 0x21) /* DW_FORM_implicit_const */
-+            step_leb128S(&p);
-       }
-       while (name != 0); /* until name == form == 0 */
-    }
-@@ -804,13 +1048,14 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui,
-                                   DiCursor  unitblock_img,
-                                   DiCursor  debugabbrev_img,
-                                   DiCursor  debugstr_img,
--                                  DiCursor  debugstr_alt_img )
-+                                  DiCursor  debugstr_alt_img,
-+                                  DiCursor  debuglinestr_img)
- {
-    UInt   acode, abcode;
-    ULong  atoffs, blklen;
-    UShort ver;
- 
--   UChar    addr_size;
-+   UChar    addr_size = 0;
-    DiCursor p = unitblock_img;
-    DiCursor end_img;
-    DiCursor abbrev_img;
-@@ -823,16 +1068,25 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui,
-    /* This block length */
-    blklen = step_initial_length_field( &p, &ui->dw64 );
- 
--   /* version should be 2, 3 or 4 */
-+   /* version should be 2, 3, 4 or 5 */
-    ver = ML_(cur_step_UShort)(&p);
- 
--   /* get offset in abbrev */
--   atoffs = ui->dw64 ? ML_(cur_step_ULong)(&p)
--                     : (ULong)(ML_(cur_step_UInt)(&p));
-+   if (ver >= 5)
-+      /* unit_type for DWARF5 */
-+      /* unit_type = */ ML_(cur_step_UChar)(&p);
-+   else
-+      /* get offset in abbrev */
-+      atoffs = ui->dw64 ? ML_(cur_step_ULong)(&p)
-+                        : (ULong)(ML_(cur_step_UInt)(&p));
- 
-    /* Address size */
-    addr_size = ML_(cur_step_UChar)(&p);
- 
-+   if (ver >= 5)
-+      /* get offset in abbrev */
-+      atoffs = ui->dw64 ? ML_(cur_step_ULong)(&p)
-+                        : (ULong)(ML_(cur_step_UInt)(&p));
-+
-    /* End of this block */
-    end_img = ML_(cur_plus)(unitblock_img, blklen + (ui->dw64 ? 12 : 4)); 
- 
-@@ -909,6 +1163,17 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui,
-                   sval = ML_(cur_plus)(debugstr_img, ML_(cur_read_ULong)(p));
-                p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4);
-                break;
-+            case 0x1f: /* FORM_line_strp */ /* pointer in .debug_line_str */
-+               /* 2006-01-01: only generate a value if a debug_str
-+                  section was found) */
-+               if (ML_(cur_is_valid)(debuglinestr_img) && !ui->dw64)
-+                  sval = ML_(cur_plus)(debuglinestr_img,
-+                                       ML_(cur_read_UInt)(p));
-+               if (ML_(cur_is_valid)(debuglinestr_img) && ui->dw64)
-+                  sval = ML_(cur_plus)(debuglinestr_img,
-+                                       ML_(cur_read_ULong)(p));
-+               p = ML_(cur_plus)(p, ui->dw64 ? 8 : 4);
-+               break;
-             case 0x08: /* FORM_string */
-                sval = p;
-                p = ML_(cur_plus)(p, ML_(cur_strlen)(p) + 1);
-@@ -928,7 +1193,13 @@ void read_unitinfo_dwarf2( /*OUT*/UnitInfo* ui,
-                p = ML_(cur_plus)(p, 8);
-                /* perhaps should assign unconditionally to cval? */
-                break;
-+            case 0x21: /* FORM_implicit_const */
-+               cval = step_leb128S (&abbrev_img);
-+               break;
-             /* TODO : Following ones just skip data - implement if you need */
-+            case 0x1e: /* FORM_data16 */
-+               p = ML_(cur_plus)(p, 16);
-+               break;
-             case 0x01: /* FORM_addr */
-                p = ML_(cur_plus)(p, addr_size);
-                break;
-@@ -1028,7 +1299,8 @@ void ML_(read_debuginfo_dwarf3)
-           DiSlice escn_debug_abbv,      /* .debug_abbrev */
-           DiSlice escn_debug_line,      /* .debug_line */
-           DiSlice escn_debug_str,       /* .debug_str */
--          DiSlice escn_debug_str_alt )  /* .debug_str */
-+          DiSlice escn_debug_str_alt,   /* .debug_str */
-+          DiSlice escn_debug_line_str)  /* .debug_line_str */
- {
-    UnitInfo ui;
-    UShort   ver;
-@@ -1067,9 +1339,9 @@ void ML_(read_debuginfo_dwarf3)
- 
-       /* version should be 2 */
-       ver = ML_(cur_read_UShort)( ML_(cur_plus)(block_img, blklen_len) );
--      if ( ver != 2 && ver != 3 && ver != 4 ) {
-+      if ( ver != 2 && ver != 3 && ver != 4 && ver != 5) {
-          ML_(symerr)( di, True,
--                      "Ignoring non-Dwarf2/3/4 block in .debug_info" );
-+                      "Ignoring non-Dwarf2/3/4/5 block in .debug_info" );
-          continue;
-       }
-       
-@@ -1082,7 +1354,8 @@ void ML_(read_debuginfo_dwarf3)
-       read_unitinfo_dwarf2( &ui, block_img, 
-                                  ML_(cur_from_sli)(escn_debug_abbv),
-                                  ML_(cur_from_sli)(escn_debug_str),
--                                 ML_(cur_from_sli)(escn_debug_str_alt) );
-+                                 ML_(cur_from_sli)(escn_debug_str_alt),
-+                                 ML_(cur_from_sli)(escn_debug_line_str));
-       if (0) {
-          HChar* str_name    = ML_(cur_read_strdup)(ui.name,    "di.rdd3.1");
-          HChar* str_compdir = ML_(cur_read_strdup)(ui.compdir, "di.rdd3.2");
-@@ -1107,7 +1380,9 @@ void ML_(read_debuginfo_dwarf3)
-       read_dwarf2_lineblock(
-          di, &ui,
-          ML_(cur_plus)(ML_(cur_from_sli)(escn_debug_line), ui.stmt_list),
--         escn_debug_line.szB  - ui.stmt_list
-+         escn_debug_line.szB  - ui.stmt_list,
-+         ML_(cur_from_sli)(escn_debug_str),
-+         ML_(cur_from_sli)(escn_debug_line_str)
-       );
-    }
- }
-diff --git a/coregrind/m_debuginfo/readdwarf3.c b/coregrind/m_debuginfo/readdwarf3.c
-index c4d529bc6..82bc8f241 100644
---- a/coregrind/m_debuginfo/readdwarf3.c
-+++ b/coregrind/m_debuginfo/readdwarf3.c
-@@ -384,6 +384,7 @@ typedef
-    struct _name_form {
-       ULong at_name;  // Dwarf Attribute name
-       ULong at_form;  // Dwarf Attribute form
-+      Long  at_val;   // Dwarf Attribute value (for implicit_const)
-       UInt  skip_szB; // Nr of bytes skippable from here ...
-       UInt  next_nf;  // ... to reach this attr/form index in the g_abbv.nf
-    } name_form;
-@@ -423,7 +424,7 @@ typedef
-       void (*barf)( const HChar* ) __attribute__((noreturn));
-       /* Is this 64-bit DWARF ? */
-       Bool   is_dw64;
--      /* Which DWARF version ?  (2, 3 or 4) */
-+      /* Which DWARF version ?  (2, 3, 4 or 5) */
-       UShort version;
-       /* Length of this Compilation Unit, as stated in the
-          .unit_length :: InitialLength field of the CU Header.
-@@ -452,12 +453,15 @@ typedef
-       /* Image information for various sections. */
-       DiSlice escn_debug_str;
-       DiSlice escn_debug_ranges;
-+      DiSlice escn_debug_rnglists;
-+      DiSlice escn_debug_loclists;
-       DiSlice escn_debug_loc;
-       DiSlice escn_debug_line;
-       DiSlice escn_debug_info;
-       DiSlice escn_debug_types;
-       DiSlice escn_debug_info_alt;
-       DiSlice escn_debug_str_alt;
-+      DiSlice escn_debug_line_str;
-       /* How much to add to .debug_types resp. alternate .debug_info offsets
-          in cook_die*.  */
-       UWord  types_cuOff_bias;
-@@ -651,25 +655,35 @@ static GExpr* make_singleton_GX ( DiCursor block, ULong nbytes )
- __attribute__((noinline))
- static GExpr* make_general_GX ( const CUConst* cc,
-                                 Bool     td3,
--                                ULong    debug_loc_offset,
-+                                ULong    offset,
-                                 Addr     svma_of_referencing_CU )
- {
-+   Bool      done;
-    Addr      base;
-    Cursor    loc;
-    XArray*   xa; /* XArray of UChar */
-    GExpr*    gx;
-    Word      nbytes;
-+   Bool      addBase = cc->version < 5;
- 
-    vg_assert(sizeof(UWord) == sizeof(Addr));
--   if (!ML_(sli_is_valid)(cc->escn_debug_loc) || cc->escn_debug_loc.szB == 0)
-+   if (cc->version < 5 && (!ML_(sli_is_valid)(cc->escn_debug_loc)
-+                           || cc->escn_debug_loc.szB == 0))
-       cc->barf("make_general_GX: .debug_loc is empty/missing");
-+   if (cc->version >= 5 && (!ML_(sli_is_valid)(cc->escn_debug_loclists)
-+                           || cc->escn_debug_loclists.szB == 0))
-+      cc->barf("make_general_GX: .debug_loclists is empty/missing");
- 
--   init_Cursor( &loc, cc->escn_debug_loc, 0, cc->barf,
--                "Overrun whilst reading .debug_loc section(2)" );
--   set_position_of_Cursor( &loc, debug_loc_offset );
-+   if (cc->version < 5)
-+      init_Cursor( &loc, cc->escn_debug_loc, 0, cc->barf,
-+                   "Overrun whilst reading .debug_loc section(2)" );
-+   else
-+      init_Cursor( &loc, cc->escn_debug_loclists, 0, cc->barf,
-+                   "Overrun whilst reading .debug_loclists section(2)" );
-+   set_position_of_Cursor( &loc, offset );
- 
--   TRACE_D3("make_general_GX (.debug_loc_offset = %llu, ioff = %llu) {\n",
--            debug_loc_offset, get_DiCursor_from_Cursor(&loc).ioff );
-+   TRACE_D3("make_general_GX (offset = %llu, ioff = %llu) {\n",
-+            offset, get_DiCursor_from_Cursor(&loc).ioff );
- 
-    /* Who frees this xa?  It is freed before this fn exits. */
-    xa = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.mgGX.1", 
-@@ -679,40 +693,86 @@ static GExpr* make_general_GX ( const CUConst* cc,
-    { UChar c = 1; /*biasMe*/ VG_(addBytesToXA)( xa, &c, sizeof(c) ); }
- 
-    base = 0;
--   while (True) {
-+   done = False;
-+   while (!done) {
-       Bool  acquire;
-       UWord len;
--      /* Read a (host-)word pair.  This is something of a hack since
--         the word size to read is really dictated by the ELF file;
--         however, we assume we're reading a file with the same
--         word-sizeness as the host.  Reasonably enough. */
--      UWord w1 = get_UWord( &loc );
--      UWord w2 = get_UWord( &loc );
--
--      TRACE_D3("   %08lx %08lx\n", w1, w2);
--      if (w1 == 0 && w2 == 0)
--         break; /* end of list */
--
--      if (w1 == -1UL) {
--         /* new value for 'base' */
--         base = w2;
--         continue;
-+      UWord w1;
-+      UWord w2;
-+      if (cc->version < 5) {
-+         /* Read a (host-)word pair.  This is something of a hack since
-+            the word size to read is really dictated by the ELF file;
-+            however, we assume we're reading a file with the same
-+            word-sizeness as the host.  Reasonably enough. */
-+         w1 = get_UWord( &loc );
-+         w2 = get_UWord( &loc );
-+
-+         TRACE_D3("   %08lx %08lx\n", w1, w2);
-+         if (w1 == 0 && w2 == 0) {
-+            done = True;
-+            break; /* end of list */
-+         }
-+
-+         if (w1 == -1UL) {
-+            /* new value for 'base' */
-+            base = w2;
-+            continue;
-+         }
-+         /* else a location expression follows */
-+         len = (UWord)get_UShort( &loc );
-+      } else {
-+         w1 = 0;
-+         w2 = 0;
-+         len = 0;
-+         DW_LLE r = get_UChar( &loc );
-+         switch (r) {
-+         case DW_LLE_end_of_list:
-+            done = True;
-+            break;
-+         case DW_LLE_base_address:
-+            base = get_UWord( &loc );
-+            break;
-+         case DW_LLE_start_length:
-+            w1 = get_UWord( &loc );
-+            w2 = w1 + get_ULEB128( &loc );
-+            len = get_ULEB128( &loc );
-+            break;
-+         case DW_LLE_offset_pair:
-+            w1 = base + get_ULEB128( &loc );
-+            w2 = base + get_ULEB128( &loc );
-+            len = get_ULEB128( &loc );
-+            break;
-+         case DW_LLE_start_end:
-+            w1 = get_UWord ( &loc );
-+            w2 = get_UWord ( &loc );
-+            len = get_ULEB128( &loc );
-+            break;
-+         case DW_LLE_GNU_view_pair:
-+            get_ULEB128( &loc );
-+            get_ULEB128( &loc );
-+            break;
-+         case DW_LLE_base_addressx:
-+         case DW_LLE_startx_endx:
-+         case DW_LLE_startx_length:
-+         case DW_LLE_default_location:
-+         default:
-+            cc->barf( "Unhandled or unknown loclists entry" );
-+            done = True;
-+         }
-       }
- 
--      /* else a location expression follows */
-       /* else enumerate [w1+base, w2+base) */
-       /* w2 is 1 past end of range, as per D3 defn for "DW_AT_high_pc"
-          (sec 2.17.2) */
-       if (w1 > w2) {
-          TRACE_D3("negative range is for .debug_loc expr at "
-                   "file offset %llu\n", 
--                  debug_loc_offset);
-+                  offset);
-          cc->barf( "negative range in .debug_loc section" );
-       }
- 
-       /* ignore zero length ranges */
-       acquire = w1 < w2;
--      len     = (UWord)get_UShort( &loc );
- 
-       if (acquire) {
-          UWord  w;
-@@ -720,9 +780,9 @@ static GExpr* make_general_GX ( const CUConst* cc,
-          UChar  c;
-          c = 0; /* !isEnd*/
-          VG_(addBytesToXA)( xa, &c, sizeof(c) );
--         w = w1    + base + svma_of_referencing_CU;
-+         w = w1    + (addBase ? base : 0) + svma_of_referencing_CU;
-          VG_(addBytesToXA)( xa, &w, sizeof(w) );
--         w = w2 -1 + base + svma_of_referencing_CU;
-+         w = w2 -1 + (addBase ? base : 0) + svma_of_referencing_CU;
-          VG_(addBytesToXA)( xa, &w, sizeof(w) );
-          s = (UShort)len;
-          VG_(addBytesToXA)( xa, &s, sizeof(s) );
-@@ -839,45 +899,96 @@ get_range_list ( const CUConst* cc,
-    XArray*   xa; /* XArray of AddrRange */
-    AddrRange pair;
- 
--   if (!ML_(sli_is_valid)(cc->escn_debug_ranges)
--       || cc->escn_debug_ranges.szB == 0)
-+   if (cc->version < 5 && (!ML_(sli_is_valid)(cc->escn_debug_ranges)
-+                           || cc->escn_debug_ranges.szB == 0))
-       cc->barf("get_range_list: .debug_ranges is empty/missing");
-+   if (cc->version >= 5 && (!ML_(sli_is_valid)(cc->escn_debug_rnglists)
-+                            || cc->escn_debug_rnglists.szB == 0))
-+      cc->barf("get_range_list: .debug_rnglists is empty/missing");
-+
-+   if (cc->version < 5)
-+      init_Cursor( &ranges, cc->escn_debug_ranges, 0, cc->barf,
-+                   "Overrun whilst reading .debug_ranges section(2)" );
-+   else
-+      init_Cursor( &ranges, cc->escn_debug_rnglists, 0, cc->barf,
-+                   "Overrun whilst reading .debug_rnglists section(2)" );
- 
--   init_Cursor( &ranges, cc->escn_debug_ranges, 0, cc->barf,
--                "Overrun whilst reading .debug_ranges section(2)" );
-    set_position_of_Cursor( &ranges, debug_ranges_offset );
- 
-    /* Who frees this xa?  varstack_preen() does. */
-    xa = VG_(newXA)( ML_(dinfo_zalloc), "di.readdwarf3.grl.1", ML_(dinfo_free),
-                     sizeof(AddrRange) );
-    base = 0;
--   while (True) {
--      /* Read a (host-)word pair.  This is something of a hack since
--         the word size to read is really dictated by the ELF file;
--         however, we assume we're reading a file with the same
--         word-sizeness as the host.  Reasonably enough. */
--      UWord w1 = get_UWord( &ranges );
--      UWord w2 = get_UWord( &ranges );
--
--      if (w1 == 0 && w2 == 0)
--         break; /* end of list. */
--
--      if (w1 == -1UL) {
--         /* new value for 'base' */
--         base = w2;
--         continue;
--      }
-+   if (cc->version < 5) {
-+      while (True) {
-+         /* Read a (host-)word pair.  This is something of a hack since
-+            the word size to read is really dictated by the ELF file;
-+            however, we assume we're reading a file with the same
-+            word-sizeness as the host.  Reasonably enough. */
-+         UWord w1 = get_UWord( &ranges );
-+         UWord w2 = get_UWord( &ranges );
- 
--      /* else enumerate [w1+base, w2+base) */
--      /* w2 is 1 past end of range, as per D3 defn for "DW_AT_high_pc"
--         (sec 2.17.2) */
--      if (w1 > w2)
--         cc->barf( "negative range in .debug_ranges section" );
--      if (w1 < w2) {
--         pair.aMin = w1     + base + svma_of_referencing_CU;
--         pair.aMax = w2 - 1 + base + svma_of_referencing_CU;
--         vg_assert(pair.aMin <= pair.aMax);
--         VG_(addToXA)( xa, &pair );
-+         if (w1 == 0 && w2 == 0)
-+            break; /* end of list. */
-+
-+         if (w1 == -1UL) {
-+            /* new value for 'base' */
-+            base = w2;
-+            continue;
-+         }
-+
-+         /* else enumerate [w1+base, w2+base) */
-+         /* w2 is 1 past end of range, as per D3 defn for "DW_AT_high_pc"
-+            (sec 2.17.2) */
-+         if (w1 > w2)
-+            cc->barf( "negative range in .debug_ranges section" );
-+         if (w1 < w2) {
-+            pair.aMin = w1     + base + svma_of_referencing_CU;
-+            pair.aMax = w2 - 1 + base + svma_of_referencing_CU;
-+            vg_assert(pair.aMin <= pair.aMax);
-+            VG_(addToXA)( xa, &pair );
-+         }
-+      }
-+   } else {
-+      Bool done = False;
-+      while (!done) {
-+         UWord w1 = 0;
-+         UWord w2 = 0;
-+         DW_RLE r = get_UChar( &ranges );
-+         switch (r) {
-+         case DW_RLE_end_of_list:
-+            done = True;
-+            break;
-+         case DW_RLE_base_address:
-+            base = get_UWord( &ranges );
-+            break;
-+         case DW_RLE_start_length:
-+            w1 = get_UWord( &ranges );
-+            w2 = w1 + get_ULEB128( &ranges );
-+            break;
-+         case DW_RLE_offset_pair:
-+            w1 = base + get_ULEB128( &ranges );
-+            w2 = base + get_ULEB128( &ranges );
-+            break;
-+         case DW_RLE_start_end:
-+            w1 = get_UWord ( &ranges );
-+            w2 = get_UWord ( &ranges );
-+            break;
-+         case DW_RLE_base_addressx:
-+         case DW_RLE_startx_endx:
-+         case DW_RLE_startx_length:
-+         default:
-+            cc->barf( "Unhandled or unknown range list entry" );
-+            done = True;
-+         }
-+         if (w1 > w2)
-+            cc->barf( "negative range in .debug_rnglists section" );
-+         if (w1 < w2) {
-+            pair.aMin = w1     + svma_of_referencing_CU;
-+            pair.aMax = w2 - 1 + svma_of_referencing_CU;
-+            vg_assert(pair.aMin <= pair.aMax);
-+            VG_(addToXA)( xa, &pair );
-+         }
-       }
-    }
-    return xa;
-@@ -930,6 +1041,8 @@ static void init_ht_abbvs (CUConst* cc,
-          }
-          ta->nf[ta_nf_n].at_name = get_ULEB128( &c );
-          ta->nf[ta_nf_n].at_form = get_ULEB128( &c );
-+         if (ta->nf[ta_nf_n].at_form == DW_FORM_implicit_const)
-+            ta->nf[ta_nf_n].at_val = get_SLEB128( &c );
-          if (ta->nf[ta_nf_n].at_name == 0 && ta->nf[ta_nf_n].at_form == 0) {
-             ta_nf_n++;
-             break; 
-@@ -1005,7 +1118,7 @@ void parse_CU_Header ( /*OUT*/CUConst* cc,
- 		       Bool type_unit,
-                        Bool alt_info )
- {
--   UChar  address_size;
-+   UChar  address_size, unit_type;
-    ULong  debug_abbrev_offset;
- 
-    VG_(memset)(cc, 0, sizeof(*cc));
-@@ -1021,10 +1134,21 @@ void parse_CU_Header ( /*OUT*/CUConst* cc,
- 
-    /* version */
-    cc->version = get_UShort( c );
--   if (cc->version != 2 && cc->version != 3 && cc->version != 4)
--      cc->barf( "parse_CU_Header: is neither DWARF2 nor DWARF3 nor DWARF4" );
-+   if (cc->version != 2 && cc->version != 3 && cc->version != 4
-+       && cc->version != 5)
-+      cc->barf( "parse_CU_Header: "
-+                "is neither DWARF2 nor DWARF3 nor DWARF4 nor DWARF5" );
-    TRACE_D3("   Version:       %d\n", (Int)cc->version );
- 
-+   /* unit type */
-+   if (cc->version >= 5) {
-+      unit_type = get_UChar( c );
-+      address_size = get_UChar( c );
-+   } else {
-+      unit_type = type_unit ? DW_UT_type : DW_UT_compile;
-+      address_size = 0; /* Will be read later. */
-+   }
-+
-    /* debug_abbrev_offset */
-    debug_abbrev_offset = get_Dwarfish_UWord( c, cc->is_dw64 );
-    if (debug_abbrev_offset >= escn_debug_abbv.szB)
-@@ -1035,7 +1159,9 @@ void parse_CU_Header ( /*OUT*/CUConst* cc,
-       give up.  This makes it safe to assume elsewhere that
-       DW_FORM_addr and DW_FORM_ref_addr can be treated as a host
-       word. */
--   address_size = get_UChar( c );
-+   if (cc->version < 5)
-+      address_size = get_UChar( c );
-+
-    if (address_size != sizeof(void*))
-       cc->barf( "parse_CU_Header: invalid address_size" );
-    TRACE_D3("   Pointer Size:  %d\n", (Int)address_size );
-@@ -1043,7 +1169,7 @@ void parse_CU_Header ( /*OUT*/CUConst* cc,
-    cc->is_type_unit = type_unit;
-    cc->is_alt_info = alt_info;
- 
--   if (type_unit) {
-+   if (type_unit || (cc->version >= 5 && unit_type == DW_UT_type)) {
-       cc->type_signature = get_ULong( c );
-       cc->type_offset = get_Dwarfish_UWord( c, cc->is_dw64 );
-    }
-@@ -1130,8 +1256,9 @@ typedef
- static
- void get_Form_contents ( /*OUT*/FormContents* cts,
-                          const CUConst* cc, Cursor* c,
--                         Bool td3, DW_FORM form )
-+                         Bool td3, const name_form *abbv )
- {
-+   DW_FORM form = abbv->at_form;
-    VG_(bzero_inline)(cts, sizeof(*cts));
-    // !!! keep switch in sync with get_Form_szB. The nr of characters read below
-    // must be computed similarly in get_Form_szB.
-@@ -1157,6 +1284,19 @@ void get_Form_contents ( /*OUT*/FormContents* cts,
-          cts->szB   = 8;
-          TRACE_D3("%llu", cts->u.val);
-          break;
-+     case DW_FORM_data16: {
-+         /* This is more like a block than an integral value.  */
-+         ULong    u64b;
-+         DiCursor data16 = get_DiCursor_from_Cursor(c);
-+         TRACE_D3("data16: ");
-+         for (u64b = 16; u64b > 0; u64b--) {
-+            UChar u8 = get_UChar(c);
-+            TRACE_D3("%x ", (UInt)u8);
-+         }
-+         cts->u.cur = data16;
-+         cts->szB   = - (Long)16;
-+         break;
-+         }
-       case DW_FORM_sec_offset:
-          cts->u.val = (ULong)get_Dwarfish_UWord( c, cc->is_dw64 );
-          cts->szB   = cc->is_dw64 ? 8 : 4;
-@@ -1242,6 +1382,26 @@ void get_Form_contents ( /*OUT*/FormContents* cts,
-          cts->szB   = - (Long)(1 + (ULong)ML_(cur_strlen)(str));
-          break;
-       }
-+      case DW_FORM_line_strp: {
-+         /* this is an offset into .debug_line_str */
-+         UWord uw = (UWord)get_Dwarfish_UWord( c, cc->is_dw64 );
-+         if (!ML_(sli_is_valid)(cc->escn_debug_line_str)
-+             || uw >= cc->escn_debug_line_str.szB)
-+            cc->barf("get_Form_contents: DW_FORM_line_strp "
-+                     "points outside .debug_line_str");
-+         /* FIXME: check the entire string lies inside debug_line_str,
-+            not just the first byte of it. */
-+         DiCursor line_str
-+            = ML_(cur_plus)( ML_(cur_from_sli)(cc->escn_debug_line_str), uw );
-+         if (TD3) {
-+            HChar* tmp = ML_(cur_read_strdup)(line_str, "di.getFC.1.5");
-+            TRACE_D3("(indirect line string, offset: 0x%lx): %s", uw, tmp);
-+            ML_(dinfo_free)(tmp);
-+         }
-+         cts->u.cur = line_str;
-+         cts->szB   = - (Long)(1 + (ULong)ML_(cur_strlen)(line_str));
-+         break;
-+      }
-       case DW_FORM_string: {
-          DiCursor str = get_AsciiZ(c);
-          if (TD3) {
-@@ -1307,6 +1467,11 @@ void get_Form_contents ( /*OUT*/FormContents* cts,
-          cts->u.val = 1;
-          cts->szB   = 1;
-          break;
-+      case DW_FORM_implicit_const:
-+         cts->u.val = (ULong)abbv->at_val;
-+         cts->szB   = 8;
-+         TRACE_D3("%llu", cts->u.val);
-+         break;
-       case DW_FORM_block1: {
-          ULong    u64b;
-          ULong    u64   = (ULong)get_UChar(c);
-@@ -1396,9 +1561,14 @@ void get_Form_contents ( /*OUT*/FormContents* cts,
-          cts->szB   = sizeof(UWord);
-          break;
-       }
--      case DW_FORM_indirect:
--         get_Form_contents (cts, cc, c, td3, (DW_FORM)get_ULEB128(c));
-+      case DW_FORM_indirect: {
-+         /* Urgh, this is ugly and somewhat unclear how it works
-+            with DW_FORM_implicit_const. HACK.  */
-+         name_form nfi = *abbv;
-+         nfi.at_form = (DW_FORM)get_ULEB128(c);
-+         get_Form_contents (cts, cc, c, td3, &nfi);
-          return;
-+      }
- 
-       case DW_FORM_GNU_ref_alt:
-          cts->u.val = get_Dwarfish_UWord(c, cc->is_dw64);
-@@ -1471,6 +1641,7 @@ UInt get_Form_szB (const CUConst* cc, DW_FORM form )
-       case DW_FORM_data2: return 2;
-       case DW_FORM_data4: return 4;
-       case DW_FORM_data8: return 8;
-+      case DW_FORM_data16: return 16;
-       case DW_FORM_sec_offset:
-          if (cc->is_dw64)
-             return 8;
-@@ -1488,6 +1659,7 @@ UInt get_Form_szB (const CUConst* cc, DW_FORM form )
-          else 
-             return sizeof_Dwarfish_UWord (cc->is_dw64);
-       case DW_FORM_strp:
-+      case DW_FORM_line_strp:
-          return sizeof_Dwarfish_UWord (cc->is_dw64);
-       case DW_FORM_string: 
-          return VARSZ_FORM;
-@@ -1522,6 +1694,8 @@ UInt get_Form_szB (const CUConst* cc, DW_FORM form )
-          return sizeof_Dwarfish_UWord(cc->is_dw64);
-       case DW_FORM_GNU_strp_alt:
-          return sizeof_Dwarfish_UWord(cc->is_dw64);
-+      case DW_FORM_implicit_const:
-+	 return 0; /* Value inside abbrev. */
-       default:
-          VG_(printf)(
-             "get_Form_szB: unhandled %u (%s)\n",
-@@ -1544,13 +1718,13 @@ void skip_DIE (UWord  *sibling,
-    while (True) {
-       if (abbv->nf[nf_i].at_name == DW_AT_sibling) {
-          get_Form_contents( &cts, cc, c_die, False /*td3*/,
--                            (DW_FORM)abbv->nf[nf_i].at_form );
-+                            &abbv->nf[nf_i] );
-          if ( cts.szB > 0 ) 
-             *sibling = cts.u.val;
-          nf_i++;
-       } else if (abbv->nf[nf_i].skip_szB == VARSZ_FORM) {
-          get_Form_contents( &cts, cc, c_die, False /*td3*/,
--                            (DW_FORM)abbv->nf[nf_i].at_form );
-+                            &abbv->nf[nf_i] );
-          nf_i++;
-       } else {
-          advance_position_of_Cursor (c_die, (ULong)abbv->nf[nf_i].skip_szB);
-@@ -1778,6 +1952,124 @@ static GExpr* get_GX ( const CUConst* cc, Bool td3, const FormContents* cts )
-    return gexpr;
- }
- 
-+static
-+HChar * get_line_str (struct _DebugInfo* di, Bool is_dw64,
-+                      Cursor *data, const UInt form,
-+                      DiSlice debugstr_img, DiSlice debuglinestr_img)
-+{
-+   HChar *str = NULL;
-+   switch (form) {
-+   case DW_FORM_string: {
-+      DiCursor distr = get_AsciiZ(data);
-+      str = ML_(cur_step_strdup)(&distr, "di.gls.string");
-+      break;
-+   }
-+   case DW_FORM_strp: {
-+      UWord uw = (UWord)get_Dwarfish_UWord( data, is_dw64 );
-+      DiCursor distr
-+         = ML_(cur_plus)( ML_(cur_from_sli)(debugstr_img), uw );
-+      str = ML_(cur_read_strdup)(distr, "di.gls.strp");
-+      break;
-+   }
-+   case DW_FORM_line_strp: {
-+      UWord uw = (UWord)get_Dwarfish_UWord( data, is_dw64 );
-+      DiCursor distr
-+         = ML_(cur_plus)( ML_(cur_from_sli)(debuglinestr_img), uw );
-+      str = ML_(cur_read_strdup)(distr, "di.gls.line_strp");
-+      break;
-+   }
-+   default:
-+      ML_(symerr)(di, True,
-+                  "Unknown path string FORM in .debug_line");
-+      break;
-+   }
-+   return str;
-+}
-+
-+static
-+Int get_line_ndx (struct _DebugInfo* di,
-+                  Cursor *data, const UInt form)
-+{
-+   Int res = 0;
-+   switch (form) {
-+   case DW_FORM_data1:
-+      res = get_UChar(data);
-+      break;
-+   case DW_FORM_data2:
-+      res = get_UShort(data);
-+      break;
-+   case DW_FORM_udata:
-+      res = get_ULEB128(data);
-+      break;
-+   default:
-+      ML_(symerr)(di, True,
-+                  "Unknown directory_index value FORM in .debug_line");
-+      break;
-+   }
-+   return res;
-+}
-+
-+static
-+void skip_line_form (struct _DebugInfo* di, Bool is_dw64,
-+                         Cursor *d, const UInt form)
-+{
-+   switch (form) {
-+   case DW_FORM_block: {
-+      ULong len = get_ULEB128(d);
-+      advance_position_of_Cursor (d, len);
-+      break;
-+   }
-+   case DW_FORM_block1: {
-+      UChar len = get_UChar(d);
-+      advance_position_of_Cursor (d, len);
-+      break;
-+   }
-+   case DW_FORM_block2: {
-+      UShort len = get_UShort(d);
-+      advance_position_of_Cursor (d, len);
-+      break;
-+   }
-+   case DW_FORM_block4: {
-+      UInt len = get_UInt(d);
-+      advance_position_of_Cursor (d, len);
-+      break;
-+   }
-+   case DW_FORM_flag:
-+   case DW_FORM_data1:
-+      advance_position_of_Cursor (d, 1);
-+      break;
-+   case DW_FORM_data2:
-+      advance_position_of_Cursor (d, 2);
-+      break;
-+   case DW_FORM_data4:
-+      advance_position_of_Cursor (d, 4);
-+      break;
-+   case DW_FORM_data8:
-+      advance_position_of_Cursor (d, 8);
-+      break;
-+   case DW_FORM_data16:
-+      advance_position_of_Cursor (d, 16);
-+      break;
-+   case DW_FORM_string:
-+      (void)get_AsciiZ (d);
-+      break;
-+   case DW_FORM_strp:
-+   case DW_FORM_line_strp:
-+   case DW_FORM_sec_offset:
-+      advance_position_of_Cursor (d, is_dw64 ? 8 : 4);
-+      break;
-+   case DW_FORM_udata:
-+      (void)get_ULEB128(d);
-+      break;
-+   case DW_FORM_sdata:
-+      (void)get_SLEB128(d);
-+      break;
-+   default:
-+      ML_(symerr)(di, True, "Unknown FORM in .debug_line");
-+      break;
-+   }
-+}
-+
- /* Returns an xarray* of directory names (indexed by the dwarf dirname
-    integer).
-    If 'compdir' is NULL, entry [0] will be set to "."
-@@ -1786,8 +2078,8 @@ static GExpr* get_GX ( const CUConst* cc, Bool td3, const FormContents* cts )
-    whatever that means, according to the DWARF3 spec.
-    FIXME??? readdwarf3.c/readdwarf.c have a lot of duplicated code */
- static
--XArray* read_dirname_xa (DebugInfo* di, const HChar *compdir,
--                         Cursor *c,
-+XArray* read_dirname_xa (DebugInfo* di, UShort version, const HChar *compdir,
-+                         Cursor *c, const CUConst *cc,
-                          Bool td3 )
- {
-    XArray*        dirname_xa;   /* xarray of HChar* dirname */
-@@ -1804,51 +2096,121 @@ XArray* read_dirname_xa (DebugInfo* di, const HChar *compdir,
-       dirname = compdir;
-       compdir_len = VG_(strlen)(compdir);
-    }
--   VG_(addToXA) (dirname_xa, &dirname);
--
--   TRACE_D3(" The Directory Table%s\n", 
--            peek_UChar(c) == 0 ? " is empty." : ":" );
--
--   while (peek_UChar(c) != 0) {
--
--      DiCursor cur = get_AsciiZ(c);
--      HChar* data_str = ML_(cur_read_strdup)( cur, "dirname_xa.1" );
--      TRACE_D3("  %s\n", data_str);
--
--      /* If data_str[0] is '/', then 'data' is an absolute path and we
--         don't mess with it.  Otherwise, construct the
--         path 'compdir' ++ "/" ++ 'data'. */
--
--      if (data_str[0] != '/' 
--          /* not an absolute path */
--          && compdir
--          /* actually got something sensible for compdir */
--          && compdir_len)
--      {
--         SizeT  len = compdir_len + 1 + VG_(strlen)(data_str);
--         HChar *buf = ML_(dinfo_zalloc)("dirname_xa.2", len + 1);
--
--         VG_(strcpy)(buf, compdir);
--         VG_(strcat)(buf, "/");
--         VG_(strcat)(buf, data_str);
--
--         dirname = ML_(addStr)(di, buf, len);
--         VG_(addToXA) (dirname_xa, &dirname);
--         if (0) VG_(printf)("rel path  %s\n", buf);
--         ML_(dinfo_free)(buf);
--      } else {
--         /* just use 'data'. */
--         dirname = ML_(addStr)(di,data_str,-1);
--         VG_(addToXA) (dirname_xa, &dirname);
--         if (0) VG_(printf)("abs path  %s\n", data_str);
-+
-+   /* For version 5, the compdir is the first (zero) entry. */
-+   if (version < 5)
-+      VG_(addToXA) (dirname_xa, &dirname);
-+
-+   if (version < 5) {
-+      TRACE_D3("The Directory Table%s\n",
-+               peek_UChar(c) == 0 ? " is empty." : ":" );
-+
-+      while (peek_UChar(c) != 0) {
-+
-+         DiCursor cur = get_AsciiZ(c);
-+         HChar* data_str = ML_(cur_read_strdup)( cur, "dirname_xa.1" );
-+         TRACE_D3("  %s\n", data_str);
-+
-+         /* If data_str[0] is '/', then 'data' is an absolute path and we
-+            don't mess with it.  Otherwise, construct the
-+            path 'compdir' ++ "/" ++ 'data'. */
-+
-+         if (data_str[0] != '/'
-+             /* not an absolute path */
-+             && compdir
-+             /* actually got something sensible for compdir */
-+             && compdir_len)
-+         {
-+            SizeT  len = compdir_len + 1 + VG_(strlen)(data_str);
-+            HChar *buf = ML_(dinfo_zalloc)("dirname_xa.2", len + 1);
-+
-+            VG_(strcpy)(buf, compdir);
-+            VG_(strcat)(buf, "/");
-+            VG_(strcat)(buf, data_str);
-+
-+            dirname = ML_(addStr)(di, buf, len);
-+            VG_(addToXA) (dirname_xa, &dirname);
-+            if (0) VG_(printf)("rel path  %s\n", buf);
-+            ML_(dinfo_free)(buf);
-+         } else {
-+            /* just use 'data'. */
-+            dirname = ML_(addStr)(di,data_str,-1);
-+            VG_(addToXA) (dirname_xa, &dirname);
-+            if (0) VG_(printf)("abs path  %s\n", data_str);
-+         }
-+
-+         ML_(dinfo_free)(data_str);
-+      }
-+   } else {
-+      UChar forms[256];
-+      UChar p_ndx = 0;
-+      UInt directories_count;
-+      UChar directory_entry_format_count;
-+      UInt n;
-+      DiSlice debugstr_img = cc->escn_debug_str;
-+      DiSlice debuglinestr_img = cc->escn_debug_line_str;
-+
-+      directory_entry_format_count = get_UChar(c);
-+      for (n = 0; n < directory_entry_format_count; n++) {
-+         UInt lnct = get_ULEB128(c);
-+         UInt form = get_ULEB128(c);
-+         if (lnct == DW_LNCT_path)
-+            p_ndx = n;
-+         forms[n] = form;
-       }
-+      directories_count = get_ULEB128(c);
-+      TRACE_D3("The Directory Table%s\n",
-+               directories_count == 0 ? " is empty." : ":" );
-+
-+      for (n = 0; n < directories_count; n++) {
-+         UInt f;
-+         for (f = 0; f < directory_entry_format_count; f++) {
-+            UInt form = forms[f];
-+            if (f == p_ndx) {
-+               HChar *data_str = get_line_str (di, cc->is_dw64, c, form,
-+                                               debugstr_img,
-+                                               debuglinestr_img);
-+               TRACE_D3("  %s\n", data_str);
-+
-+               /* If data_str[0] is '/', then 'data' is an absolute path and we
-+                  don't mess with it.  Otherwise, construct the
-+                  path 'compdir' ++ "/" ++ 'data'. */
-+
-+               if (data_str[0] != '/'
-+                   /* not an absolute path */
-+                   && compdir
-+                   /* actually got something sensible for compdir */
-+                   && compdir_len)
-+               {
-+                  SizeT  len = compdir_len + 1 + VG_(strlen)(data_str);
-+                  HChar *buf = ML_(dinfo_zalloc)("dirname_xa.2", len + 1);
-+
-+                  VG_(strcpy)(buf, compdir);
-+                  VG_(strcat)(buf, "/");
-+                  VG_(strcat)(buf, data_str);
-+
-+                  dirname = ML_(addStr)(di, buf, len);
-+                  VG_(addToXA) (dirname_xa, &dirname);
-+                  if (0) VG_(printf)("rel path  %s\n", buf);
-+                  ML_(dinfo_free)(buf);
-+               } else {
-+                  /* just use 'data'. */
-+                  dirname = ML_(addStr)(di,data_str,-1);
-+                  VG_(addToXA) (dirname_xa, &dirname);
-+                  if (0) VG_(printf)("abs path  %s\n", data_str);
-+               }
- 
--      ML_(dinfo_free)(data_str);
-+               ML_(dinfo_free)(data_str);
-+            } else {
-+               skip_line_form (di, cc->is_dw64, c, form);
-+            }
-+         }
-+      }
-    }
- 
-    TRACE_D3 ("\n");
- 
--   if (get_UChar (c) != 0) {
-+   if (version < 5 && get_UChar (c) != 0) {
-       ML_(symerr)(NULL, True,
-                   "could not get NUL at end of DWARF directory table");
-       VG_(deleteXA)(dirname_xa);
-@@ -1888,9 +2250,13 @@ void read_filename_table( /*MOD*/XArray* /* of UInt* */ fndn_ix_Table,
-    get_Initial_Length( &is_dw64, &c,
-                        "read_filename_table: invalid initial-length field" );
-    version = get_UShort( &c );
--   if (version != 2 && version != 3 && version != 4)
--     cc->barf("read_filename_table: Only DWARF version 2, 3 and 4 line info "
--              "is currently supported.");
-+   if (version != 2 && version != 3 && version != 4 && version != 5)
-+     cc->barf("read_filename_table: Only DWARF version 2, 3, 4 and 5 "
-+              "line info is currently supported.");
-+   if (version >= 5) {
-+      /* addrs_size = */ get_UChar( &c );
-+      /* seg_size =   */ get_UChar( &c );
-+   }
-    /*header_length              = (ULong)*/ get_Dwarfish_UWord( &c, is_dw64 );
-    /*minimum_instruction_length = */ get_UChar( &c );
-    if (version >= 4)
-@@ -1903,30 +2269,77 @@ void read_filename_table( /*MOD*/XArray* /* of UInt* */ fndn_ix_Table,
-    for (i = 1; i < (Word)opcode_base; i++)
-      (void)get_UChar( &c );
- 
--   dirname_xa = read_dirname_xa(cc->di, compdir, &c, td3);
-+   dirname_xa = read_dirname_xa(cc->di, version, compdir, &c, cc, td3);
- 
-    /* Read and record the file names table */
-    vg_assert( VG_(sizeXA)( fndn_ix_Table ) == 0 );
--   /* Add a dummy index-zero entry.  DWARF3 numbers its files
--      from 1, for some reason. */
--   fndn_ix = ML_(addFnDn) ( cc->di, "<unknown_file>", NULL );
--   VG_(addToXA)( fndn_ix_Table, &fndn_ix );
--   while (peek_UChar(&c) != 0) {
--      DiCursor cur = get_AsciiZ(&c);
--      str = ML_(addStrFromCursor)( cc->di, cur );
--      dir_xa_ix = get_ULEB128( &c );
--      if (dirname_xa != NULL 
--          && dir_xa_ix >= 0 && dir_xa_ix < VG_(sizeXA) (dirname_xa))
--         dirname = *(HChar**)VG_(indexXA) ( dirname_xa, dir_xa_ix );
--      else
--         dirname = NULL;
--      fndn_ix = ML_(addFnDn)( cc->di, str, dirname);
--      TRACE_D3("  read_filename_table: %ld fndn_ix %u %s %s\n",
--               VG_(sizeXA)(fndn_ix_Table), fndn_ix, 
--               dirname, str);
-+   if (version < 5) {
-+      /* Add a dummy index-zero entry.  DWARF3 numbers its files
-+         from 1, for some reason. */
-+      fndn_ix = ML_(addFnDn) ( cc->di, "<unknown_file>", NULL );
-       VG_(addToXA)( fndn_ix_Table, &fndn_ix );
--      (void)get_ULEB128( &c ); /* skip last mod time */
--      (void)get_ULEB128( &c ); /* file size */
-+      while (peek_UChar(&c) != 0) {
-+         DiCursor cur = get_AsciiZ(&c);
-+         str = ML_(addStrFromCursor)( cc->di, cur );
-+         dir_xa_ix = get_ULEB128( &c );
-+         if (dirname_xa != NULL
-+             && dir_xa_ix >= 0 && dir_xa_ix < VG_(sizeXA) (dirname_xa))
-+            dirname = *(HChar**)VG_(indexXA) ( dirname_xa, dir_xa_ix );
-+         else
-+            dirname = NULL;
-+         fndn_ix = ML_(addFnDn)( cc->di, str, dirname);
-+         TRACE_D3("  read_filename_table: %ld fndn_ix %u %s %s\n",
-+                  VG_(sizeXA)(fndn_ix_Table), fndn_ix,
-+                  dirname, str);
-+         VG_(addToXA)( fndn_ix_Table, &fndn_ix );
-+         (void)get_ULEB128( &c ); /* skip last mod time */
-+         (void)get_ULEB128( &c ); /* file size */
-+      }
-+   } else {
-+      UChar forms[256];
-+      UChar p_ndx = 0, d_ndx = 0;
-+      UInt file_names_count;
-+      UChar file_names_entry_format_count;
-+      UInt n;
-+      DiSlice debugstr_img = cc->escn_debug_str;
-+      DiSlice debuglinestr_img = cc->escn_debug_line_str;
-+      file_names_entry_format_count = get_UChar( &c );
-+      for (n = 0; n < file_names_entry_format_count; n++) {
-+         UInt lnct = get_ULEB128( &c );
-+         UInt form = get_ULEB128( &c );
-+         if (lnct == DW_LNCT_path)
-+            p_ndx = n;
-+         if (lnct == DW_LNCT_directory_index)
-+            d_ndx = n;
-+         forms[n] = form;
-+      }
-+      file_names_count = get_ULEB128( &c );
-+      for (n = 0; n < file_names_count; n++) {
-+         UInt f;
-+         dir_xa_ix  = 0;
-+         str = NULL;
-+         for (f = 0; f < file_names_entry_format_count; f++) {
-+            UInt form = forms[f];
-+            if (f == p_ndx)
-+               str = get_line_str (cc->di, cc->is_dw64, &c, form,
-+                                   debugstr_img, debuglinestr_img);
-+            else if (n == d_ndx)
-+               dir_xa_ix = get_line_ndx (cc->di, &c, form);
-+            else
-+               skip_line_form (cc->di, cc->is_dw64, &c, form);
-+         }
-+
-+         if (dirname_xa != NULL
-+             && dir_xa_ix >= 0 && dir_xa_ix < VG_(sizeXA) (dirname_xa))
-+            dirname = *(HChar**)VG_(indexXA) ( dirname_xa, dir_xa_ix );
-+         else
-+            dirname = NULL;
-+         fndn_ix = ML_(addFnDn)( cc->di, str, dirname);
-+         TRACE_D3("  read_filename_table: %ld fndn_ix %u %s %s\n",
-+                  VG_(sizeXA)(fndn_ix_Table), fndn_ix,
-+                  dirname, str);
-+         VG_(addToXA)( fndn_ix_Table, &fndn_ix );
-+      }
-    }
-    /* We're done!  The rest of it is not interesting. */
-    if (dirname_xa != NULL)
-@@ -2011,11 +2424,12 @@ static void trace_DIE(
-    while (True) {
-       DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-       DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+      const name_form *nf = &abbv->nf[nf_i];
-       nf_i++;
-       if (attr == 0 && form == 0) break;
-       VG_(printf)("     %-18s: ", ML_(pp_DW_AT)(attr));
-       /* Get the form contents, so as to print them */
--      get_Form_contents( &cts, cc, &c, True, form );
-+      get_Form_contents( &cts, cc, &c, True, nf );
-       if (attr == DW_AT_sibling && cts.szB > 0) {
-          sibling = cts.u.val;
-       }
-@@ -2094,9 +2508,10 @@ static void parse_var_DIE (
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr == DW_AT_low_pc && cts.szB > 0) {
-             ip_lo   = cts.u.val;
-             have_lo = True;
-@@ -2196,9 +2611,10 @@ static void parse_var_DIE (
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr == DW_AT_low_pc && cts.szB > 0) {
-             ip_lo   = cts.u.val;
-             have_lo = True;
-@@ -2282,9 +2698,10 @@ static void parse_var_DIE (
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          n_attrs++;
-          if (attr == DW_AT_name && cts.szB < 0) {
-             name = ML_(addStrFromCursor)( cc->di, cts.u.cur );
-@@ -2646,9 +3063,10 @@ static const HChar* get_inlFnName (Int absori, const CUConst* cc, Bool td3)
-    while (True) {
-       DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-       DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+      const name_form *nf = &abbv->nf[nf_i];
-       nf_i++;
-       if (attr == 0 && form == 0) break;
--      get_Form_contents( &cts, cc, &c, False/*td3*/, form );
-+      get_Form_contents( &cts, cc, &c, False/*td3*/, nf );
-       if (attr == DW_AT_name) {
-          HChar *fnname;
-          if (cts.szB >= 0)
-@@ -2720,9 +3138,10 @@ static Bool parse_inl_DIE (
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr == DW_AT_low_pc && cts.szB > 0) {
-             ip_lo   = cts.u.val;
-             have_lo = True;
-@@ -2764,9 +3183,10 @@ static Bool parse_inl_DIE (
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr == DW_AT_call_file && cts.szB > 0) {
-             Int ftabIx = (Int)cts.u.val;
-             if (ftabIx >= 1
-@@ -3090,9 +3510,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents,
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr != DW_AT_language)
-             continue;
-          if (cts.szB <= 0)
-@@ -3132,9 +3553,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents,
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr == DW_AT_name && cts.szB < 0) {
-             typeE.Te.TyBase.name
-                = ML_(cur_read_strdup)( cts.u.cur,
-@@ -3243,9 +3665,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents,
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr == DW_AT_byte_size && cts.szB > 0) {
-             typeE.Te.TyPorR.szB = cts.u.val;
-          }
-@@ -3275,9 +3698,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents,
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr == DW_AT_name && cts.szB < 0) {
-             typeE.Te.TyEnum.name
-                = ML_(cur_read_strdup)( cts.u.cur,
-@@ -3356,9 +3780,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents,
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr == DW_AT_name && cts.szB < 0) {
-             atomE.Te.Atom.name 
-               = ML_(cur_read_strdup)( cts.u.cur,
-@@ -3411,9 +3836,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents,
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr == DW_AT_name && cts.szB < 0) {
-             typeE.Te.TyStOrUn.name
-                = ML_(cur_read_strdup)( cts.u.cur,
-@@ -3498,9 +3924,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents,
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr == DW_AT_name && cts.szB < 0) {
-             fieldE.Te.Field.name
-                = ML_(cur_read_strdup)( cts.u.cur,
-@@ -3585,9 +4012,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents,
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr == DW_AT_type && cts.szB > 0) {
-             typeE.Te.TyArray.typeR
-                = cook_die_using_form( cc, (UWord)cts.u.val, form );
-@@ -3626,9 +4054,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents,
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr == DW_AT_lower_bound && cts.szB > 0 
-              && form_expected_for_bound (form)) {
-             lower      = (Long)cts.u.val;
-@@ -3714,9 +4143,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents,
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr == DW_AT_name && cts.szB < 0) {
-             typeE.Te.TyTyDef.name
-                = ML_(cur_read_strdup)( cts.u.cur,
-@@ -3764,9 +4194,10 @@ static void parse_type_DIE ( /*MOD*/XArray* /* of TyEnt */ tyents,
-       while (True) {
-          DW_AT   attr = (DW_AT)  abbv->nf[nf_i].at_name;
-          DW_FORM form = (DW_FORM)abbv->nf[nf_i].at_form;
-+         const name_form *nf = &abbv->nf[nf_i];
-          nf_i++;
-          if (attr == 0 && form == 0) break;
--         get_Form_contents( &cts, cc, c_die, False/*td3*/, form );
-+         get_Form_contents( &cts, cc, c_die, False/*td3*/, nf );
-          if (attr == DW_AT_type && cts.szB > 0) {
-             typeE.Te.TyQual.typeR
-                = cook_die_using_form( cc, (UWord)cts.u.val, form );
-@@ -4486,6 +4917,9 @@ static void trace_debug_abbrev (const DebugInfo* di,
-             while (True) {
-                ULong at_name = get_ULEB128( &abbv );
-                ULong at_form = get_ULEB128( &abbv );
-+               if (at_form == DW_FORM_implicit_const) {
-+                  /* Long at_val = */ get_SLEB128 ( &abbv );
-+               }
-                if (at_name == 0 && at_form == 0) break;
-                TRACE_D3("    %-18s %s\n", 
-                         ML_(pp_DW_AT)(at_name), ML_(pp_DW_FORM)(at_form));
-@@ -4502,9 +4936,10 @@ void new_dwarf3_reader_wrk (
-    DiSlice escn_debug_info,      DiSlice escn_debug_types,
-    DiSlice escn_debug_abbv,      DiSlice escn_debug_line,
-    DiSlice escn_debug_str,       DiSlice escn_debug_ranges,
-+   DiSlice escn_debug_rnglists,  DiSlice escn_debug_loclists,
-    DiSlice escn_debug_loc,       DiSlice escn_debug_info_alt,
-    DiSlice escn_debug_abbv_alt,  DiSlice escn_debug_line_alt,
--   DiSlice escn_debug_str_alt
-+   DiSlice escn_debug_str_alt,   DiSlice escn_debug_line_str
- )
- {
-    XArray* /* of TyEnt */     tyents = NULL;
-@@ -4738,6 +5173,8 @@ void new_dwarf3_reader_wrk (
-          cc.escn_debug_str      = pass == 0 ? escn_debug_str_alt
-                                             : escn_debug_str;
-          cc.escn_debug_ranges   = escn_debug_ranges;
-+         cc.escn_debug_rnglists = escn_debug_rnglists;
-+         cc.escn_debug_loclists = escn_debug_loclists;
-          cc.escn_debug_loc      = escn_debug_loc;
-          cc.escn_debug_line     = pass == 0 ? escn_debug_line_alt
-                                             : escn_debug_line;
-@@ -4746,6 +5183,7 @@ void new_dwarf3_reader_wrk (
-          cc.escn_debug_types    = escn_debug_types;
-          cc.escn_debug_info_alt = escn_debug_info_alt;
-          cc.escn_debug_str_alt  = escn_debug_str_alt;
-+         cc.escn_debug_line_str = escn_debug_line_str;
-          cc.types_cuOff_bias    = escn_debug_info.szB;
-          cc.alt_cuOff_bias      = escn_debug_info.szB + escn_debug_types.szB;
-          cc.cu_start_offset     = cu_start_offset;
-@@ -5216,9 +5654,10 @@ ML_(new_dwarf3_reader) (
-    DiSlice escn_debug_info,      DiSlice escn_debug_types,
-    DiSlice escn_debug_abbv,      DiSlice escn_debug_line,
-    DiSlice escn_debug_str,       DiSlice escn_debug_ranges,
-+   DiSlice escn_debug_rnglists,  DiSlice escn_debug_loclists,
-    DiSlice escn_debug_loc,       DiSlice escn_debug_info_alt,
-    DiSlice escn_debug_abbv_alt,  DiSlice escn_debug_line_alt,
--   DiSlice escn_debug_str_alt
-+   DiSlice escn_debug_str_alt,   DiSlice escn_debug_line_str
- )
- {
-    volatile Int  jumped;
-@@ -5239,9 +5678,10 @@ ML_(new_dwarf3_reader) (
-                              escn_debug_info,     escn_debug_types,
-                              escn_debug_abbv,     escn_debug_line,
-                              escn_debug_str,      escn_debug_ranges,
-+                             escn_debug_rnglists, escn_debug_loclists,
-                              escn_debug_loc,      escn_debug_info_alt,
-                              escn_debug_abbv_alt, escn_debug_line_alt,
--                             escn_debug_str_alt );
-+                             escn_debug_str_alt,  escn_debug_line_str );
-       d3rd_jmpbuf_valid = False;
-       TRACE_D3("\n------ .debug_info reading was successful ------\n");
-    } else {
-diff --git a/coregrind/m_debuginfo/readelf.c b/coregrind/m_debuginfo/readelf.c
-index bc5a732d7..404034df0 100644
---- a/coregrind/m_debuginfo/readelf.c
-+++ b/coregrind/m_debuginfo/readelf.c
-@@ -2577,7 +2577,10 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
-       DiSlice debug_types_escn    = DiSlice_INVALID; // .debug_types  (dwarf4)
-       DiSlice debug_abbv_escn     = DiSlice_INVALID; // .debug_abbrev (dwarf2)
-       DiSlice debug_str_escn      = DiSlice_INVALID; // .debug_str    (dwarf2)
-+      DiSlice debug_line_str_escn = DiSlice_INVALID; // .debug_line_str(dwarf5)
-       DiSlice debug_ranges_escn   = DiSlice_INVALID; // .debug_ranges (dwarf2)
-+      DiSlice debug_rnglists_escn = DiSlice_INVALID; // .debug_rnglists(dwarf5)
-+      DiSlice debug_loclists_escn = DiSlice_INVALID; // .debug_loclists(dwarf5)
-       DiSlice debug_loc_escn      = DiSlice_INVALID; // .debug_loc    (dwarf2)
-       DiSlice debug_frame_escn    = DiSlice_INVALID; // .debug_frame  (dwarf2)
-       DiSlice debug_line_alt_escn = DiSlice_INVALID; // .debug_line   (alt)
-@@ -2683,10 +2686,22 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
-          if (!ML_(sli_is_valid)(debug_str_escn))
-             FIND(".zdebug_str",        debug_str_escn)
- 
-+         FIND(   ".debug_line_str",    debug_line_str_escn)
-+         if (!ML_(sli_is_valid)(debug_line_str_escn))
-+            FIND(".zdebug_str",        debug_line_str_escn)
-+
-          FIND(   ".debug_ranges",      debug_ranges_escn)
-          if (!ML_(sli_is_valid)(debug_ranges_escn))
-             FIND(".zdebug_ranges",     debug_ranges_escn)
- 
-+         FIND(   ".debug_rnglists",    debug_rnglists_escn)
-+         if (!ML_(sli_is_valid)(debug_rnglists_escn))
-+            FIND(".zdebug_rnglists",   debug_rnglists_escn)
-+
-+         FIND(   ".debug_loclists",    debug_loclists_escn)
-+         if (!ML_(sli_is_valid)(debug_loclists_escn))
-+            FIND(".zdebug_loclists",   debug_loclists_escn)
-+
-          FIND(   ".debug_loc",         debug_loc_escn)
-          if (!ML_(sli_is_valid)(debug_loc_escn))
-             FIND(".zdebug_loc",    debug_loc_escn)
-@@ -2994,10 +3009,22 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
-             if (!ML_(sli_is_valid)(debug_str_escn))
-                FIND(need_dwarf2,     ".zdebug_str",       debug_str_escn)
- 
-+            FIND(   need_dwarf2,     ".debug_line_str",   debug_line_str_escn)
-+            if (!ML_(sli_is_valid)(debug_line_str_escn))
-+               FIND(need_dwarf2,     ".zdebug_line_str",  debug_line_str_escn)
-+
-             FIND(   need_dwarf2,     ".debug_ranges",     debug_ranges_escn)
-             if (!ML_(sli_is_valid)(debug_ranges_escn))
-                FIND(need_dwarf2,     ".zdebug_ranges",    debug_ranges_escn)
- 
-+            FIND(   need_dwarf2,     ".debug_rnglists",   debug_rnglists_escn)
-+            if (!ML_(sli_is_valid)(debug_rnglists_escn))
-+               FIND(need_dwarf2,     ".zdebug_rnglists",  debug_rnglists_escn)
-+
-+            FIND(   need_dwarf2,     ".debug_loclists",   debug_loclists_escn)
-+            if (!ML_(sli_is_valid)(debug_loclists_escn))
-+               FIND(need_dwarf2,     ".zdebug_loclists",  debug_loclists_escn)
-+
-             FIND(   need_dwarf2,     ".debug_loc",        debug_loc_escn)
-             if (!ML_(sli_is_valid)(debug_loc_escn))
-                FIND(need_dwarf2,     ".zdebug_loc",       debug_loc_escn)
-@@ -3231,7 +3258,8 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
-                                       debug_abbv_escn,
-                                       debug_line_escn,
-                                       debug_str_escn,
--                                      debug_str_alt_escn );
-+                                      debug_str_alt_escn,
-+                                      debug_line_str_escn);
-          /* The new reader: read the DIEs in .debug_info to acquire
-             information on variable types and locations or inline info.
-             But only if the tool asks for it, or the user requests it on
-@@ -3242,9 +3270,10 @@ Bool ML_(read_elf_debug_info) ( struct _DebugInfo* di )
-                di, debug_info_escn,     debug_types_escn,
-                    debug_abbv_escn,     debug_line_escn,
-                    debug_str_escn,      debug_ranges_escn,
-+                   debug_rnglists_escn, debug_loclists_escn,
-                    debug_loc_escn,      debug_info_alt_escn,
-                    debug_abbv_alt_escn, debug_line_alt_escn,
--                   debug_str_alt_escn
-+                   debug_str_alt_escn,  debug_line_str_escn
-             );
-          }
-       }
-diff --git a/coregrind/m_debuginfo/readmacho.c b/coregrind/m_debuginfo/readmacho.c
-index f39ee006f..9153a74ca 100644
---- a/coregrind/m_debuginfo/readmacho.c
-+++ b/coregrind/m_debuginfo/readmacho.c
-@@ -1103,8 +1103,14 @@ Bool ML_(read_macho_debug_info)( struct _DebugInfo* di )
-          = getsectdata(dsli, "__DWARF", "__debug_line", NULL);
-       DiSlice debug_str_mscn
-          = getsectdata(dsli, "__DWARF", "__debug_str", NULL);
-+      DiSlice debug_line_str_mscn
-+         = getsectdata(dsli, "__DWARF", "__debug_line_str", NULL);
-       DiSlice debug_ranges_mscn
-          = getsectdata(dsli, "__DWARF", "__debug_ranges", NULL);
-+      DiSlice debug_rnglists_mscn
-+         = getsectdata(dsli, "__DWARF", "__debug_rnglists", NULL);
-+      DiSlice debug_loclists_mscn
-+         = getsectdata(dsli, "__DWARF", "__debug_loclists", NULL);
-       DiSlice debug_loc_mscn
-          = getsectdata(dsli, "__DWARF", "__debug_loc", NULL);
- 
-@@ -1145,7 +1151,8 @@ Bool ML_(read_macho_debug_info)( struct _DebugInfo* di )
-                                       debug_abbv_mscn,
-                                       debug_line_mscn,
-                                       debug_str_mscn,
--                                      DiSlice_INVALID /* ALT .debug_str */ );
-+                                      DiSlice_INVALID, /* ALT .debug_str */
-+                                      debug_line_str );
- 
-          /* The new reader: read the DIEs in .debug_info to acquire
-             information on variable types and locations or inline info.
-@@ -1160,11 +1167,14 @@ Bool ML_(read_macho_debug_info)( struct _DebugInfo* di )
-                    debug_line_mscn,
-                    debug_str_mscn,
-                    debug_ranges_mscn,
-+                   debug_rnglists_mscn,
-+                   debug_loclists_mscn,
-                    debug_loc_mscn,
-                    DiSlice_INVALID, /* ALT .debug_info */
-                    DiSlice_INVALID, /* ALT .debug_abbv */
-                    DiSlice_INVALID, /* ALT .debug_line */
--                   DiSlice_INVALID  /* ALT .debug_str */
-+                   DiSlice_INVALID, /* ALT .debug_str */
-+                   debug_line_str_mscn  /* .debug_line_str */
-             );
-          }
-       }
--- 
-2.18.4
-
diff --git a/valgrind-3.16.1-epoll.patch b/valgrind-3.16.1-epoll.patch
deleted file mode 100644
index c6a0411..0000000
--- a/valgrind-3.16.1-epoll.patch
+++ /dev/null
@@ -1,117 +0,0 @@
-commit f326d68d762edf4b0e9604daa446b6f8ca25725a
-Author: Mark Wielaard <mark@klomp.org>
-Date:   Sun Jul 26 22:40:22 2020 +0200
-
-    epoll_ctl warns for uninitialized padding on non-amd64 64bit arches
-    
-    struct vki_epoll_event is packed on x86_64, but not on other 64bit
-    arches. This means that on 64bit arches there can be padding in the
-    epoll_event struct. Seperately the data field is only used by user
-    space (which might not set the data field if it doesn't need to).
-    
-    Only check the events field on epoll_ctl. But assume both events
-    and data are both written to by epoll_[p]wait (exclude padding).
-    
-    https://bugs.kde.org/show_bug.cgi?id=422623
-
-diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
-index 5b5b7eee6..929a4d9af 100644
---- a/coregrind/m_syswrap/syswrap-linux.c
-+++ b/coregrind/m_syswrap/syswrap-linux.c
-@@ -2099,8 +2099,29 @@ PRE(sys_epoll_ctl)
-          SARG1, ( ARG2<3 ? epoll_ctl_s[ARG2] : "?" ), SARG3, ARG4);
-    PRE_REG_READ4(long, "epoll_ctl",
-                  int, epfd, int, op, int, fd, struct vki_epoll_event *, event);
--   if (ARG2 != VKI_EPOLL_CTL_DEL)
--      PRE_MEM_READ( "epoll_ctl(event)", ARG4, sizeof(struct vki_epoll_event) );
-+   if (ARG2 != VKI_EPOLL_CTL_DEL) {
-+      /* Just check the events field, the data field is for user space and
-+         unused by the kernel.  */
-+      struct vki_epoll_event *event = (struct vki_epoll_event *) ARG4;
-+      PRE_MEM_READ( "epoll_ctl(event)", (Addr) &event->events,
-+                    sizeof(__vki_u32) );
-+   }
-+}
-+
-+/* RES event records have been written (exclude padding).  */
-+static void epoll_post_helper ( ThreadId tid, SyscallArgs* arrghs,
-+                                SyscallStatus* status )
-+{
-+   vg_assert(SUCCESS);
-+   if (RES > 0) {
-+      Int i;
-+      struct vki_epoll_event **events = (struct vki_epoll_event**)(Addr)ARG2;
-+      for (i = 0; i < RES; i++) {
-+         /* Assume both events and data are set (data is user space only). */
-+         POST_FIELD_WRITE(events[i]->events);
-+         POST_FIELD_WRITE(events[i]->data);
-+      }
-+   }
- }
- 
- PRE(sys_epoll_wait)
-@@ -2111,13 +2132,12 @@ PRE(sys_epoll_wait)
-    PRE_REG_READ4(long, "epoll_wait",
-                  int, epfd, struct vki_epoll_event *, events,
-                  int, maxevents, int, timeout);
-+   /* Assume all (maxevents) events records should be (fully) writable. */
-    PRE_MEM_WRITE( "epoll_wait(events)", ARG2, sizeof(struct vki_epoll_event)*ARG3);
- }
- POST(sys_epoll_wait)
- {
--   vg_assert(SUCCESS);
--   if (RES > 0)
--      POST_MEM_WRITE( ARG2, sizeof(struct vki_epoll_event)*RES ) ;
-+   epoll_post_helper (tid, arrghs, status);
- }
- 
- PRE(sys_epoll_pwait)
-@@ -2130,15 +2150,14 @@ PRE(sys_epoll_pwait)
-                  int, epfd, struct vki_epoll_event *, events,
-                  int, maxevents, int, timeout, vki_sigset_t *, sigmask,
-                  vki_size_t, sigsetsize);
-+   /* Assume all (maxevents) events records should be (fully) writable. */
-    PRE_MEM_WRITE( "epoll_pwait(events)", ARG2, sizeof(struct vki_epoll_event)*ARG3);
-    if (ARG5)
-       PRE_MEM_READ( "epoll_pwait(sigmask)", ARG5, sizeof(vki_sigset_t) );
- }
- POST(sys_epoll_pwait)
- {
--   vg_assert(SUCCESS);
--   if (RES > 0)
--      POST_MEM_WRITE( ARG2, sizeof(struct vki_epoll_event)*RES ) ;
-+   epoll_post_helper (tid, arrghs, status);
- }
- 
- PRE(sys_eventfd)
-commit b74f9f23c8758c77367f18368ea95baa858544cb
-Author: Mark Wielaard <mark@klomp.org>
-Date:   Tue Aug 18 23:58:55 2020 +0200
-
-    Fix epoll_ctl setting of array event and data fields.
-    
-    Fix for https://bugs.kde.org/show_bug.cgi?id=422623 in commit ecf5ba119
-    epoll_ctl warns for uninitialized padding on non-amd64 64bit arches
-    contained a bug. A pointer to an array is not a pointer to a pointer to
-    an array. Found by a Fedora user:
-    https://bugzilla.redhat.com/show_bug.cgi?id=1844778#c10
-
-diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
-index 0850487e9..3f488795a 100644
---- a/coregrind/m_syswrap/syswrap-linux.c
-+++ b/coregrind/m_syswrap/syswrap-linux.c
-@@ -2115,11 +2115,11 @@ static void epoll_post_helper ( ThreadId tid, SyscallArgs* arrghs,
-    vg_assert(SUCCESS);
-    if (RES > 0) {
-       Int i;
--      struct vki_epoll_event **events = (struct vki_epoll_event**)(Addr)ARG2;
-+      struct vki_epoll_event *events = (struct vki_epoll_event*)(Addr)ARG2;
-       for (i = 0; i < RES; i++) {
-          /* Assume both events and data are set (data is user space only). */
--         POST_FIELD_WRITE(events[i]->events);
--         POST_FIELD_WRITE(events[i]->data);
-+         POST_FIELD_WRITE(events[i].events);
-+         POST_FIELD_WRITE(events[i].data);
-       }
-    }
- }
diff --git a/valgrind-3.16.1-faccessat2.patch b/valgrind-3.16.1-faccessat2.patch
deleted file mode 100644
index 9751f45..0000000
--- a/valgrind-3.16.1-faccessat2.patch
+++ /dev/null
@@ -1,201 +0,0 @@
-From fe4b349df3d5edc1c849e9890cbc6b191386a03c Mon Sep 17 00:00:00 2001
-From: Mark Wielaard <mark@klomp.org>
-Date: Fri, 16 Oct 2020 02:55:06 +0200
-Subject: [PATCH] Support new faccessat2 linux syscall (439)
-
-faccessat2 is a new syscall in linux 5.8 and will be used by glibc 2.33.
-faccessat2 is simply faccessat with a new flag argument. It has
-a common number across all linux arches.
-
-https://bugs.kde.org/427787
----
- NEWS                                         | 1 +
- coregrind/m_syswrap/priv_syswrap-linux.h     | 1 +
- 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          | 9 +++++++++
- 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, 31 insertions(+)
-
-diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h
-index eb0b320ca..110f7c832 100644
---- a/coregrind/m_syswrap/priv_syswrap-linux.h
-+++ b/coregrind/m_syswrap/priv_syswrap-linux.h
-@@ -180,6 +180,7 @@ DECL_TEMPLATE(linux, sys_symlinkat);
- DECL_TEMPLATE(linux, sys_readlinkat);
- DECL_TEMPLATE(linux, sys_fchmodat);
- DECL_TEMPLATE(linux, sys_faccessat);
-+DECL_TEMPLATE(linux, sys_faccessat2);
- DECL_TEMPLATE(linux, sys_utimensat);
- DECL_TEMPLATE(linux, sys_name_to_handle_at);
- DECL_TEMPLATE(linux, sys_open_by_handle_at);
-diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c
-index d6f3eb910..45e1f3d1b 100644
---- a/coregrind/m_syswrap/syswrap-amd64-linux.c
-+++ b/coregrind/m_syswrap/syswrap-amd64-linux.c
-@@ -873,6 +873,8 @@ static SyscallTableEntry syscall_table[] = {
-    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
-+
-+   LINX_(__NR_faccessat2,	 sys_faccessat2),        // 439
- };
- 
- 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 70700e53f..978aedbe6 100644
---- a/coregrind/m_syswrap/syswrap-arm-linux.c
-+++ b/coregrind/m_syswrap/syswrap-arm-linux.c
-@@ -1046,6 +1046,8 @@ static SyscallTableEntry syscall_main_table[] = {
-    LINXY(__NR_futex_time64,      sys_futex_time64),     // 422
-    LINXY(__NR_sched_rr_get_interval_time64,
-          sys_sched_rr_get_interval_time64),             // 423
-+
-+   LINX_(__NR_faccessat2,    sys_faccessat2),           // 439
- };
- 
- 
-diff --git a/coregrind/m_syswrap/syswrap-arm64-linux.c b/coregrind/m_syswrap/syswrap-arm64-linux.c
-index acca02442..051d84989 100644
---- a/coregrind/m_syswrap/syswrap-arm64-linux.c
-+++ b/coregrind/m_syswrap/syswrap-arm64-linux.c
-@@ -825,6 +825,8 @@ static SyscallTableEntry syscall_main_table[] = {
-    //   (__NR_pkey_free,         sys_ni_syscall),        // 290
- 
-    LINXY(__NR_statx,             sys_statx),             // 397
-+
-+   LINX_(__NR_faccessat2,        sys_faccessat2),        // 439
- };
- 
- 
-diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
-index 3f488795a..41849873e 100644
---- a/coregrind/m_syswrap/syswrap-linux.c
-+++ b/coregrind/m_syswrap/syswrap-linux.c
-@@ -5988,6 +5988,15 @@ PRE(sys_faccessat)
-    PRE_MEM_RASCIIZ( "faccessat(pathname)", ARG2 );
- }
- 
-+PRE(sys_faccessat2)
-+{
-+   PRINT("sys_faccessat2 ( %ld, %#" FMT_REGWORD "x(%s), %ld, %ld )",
-+         SARG1, ARG2, (HChar*)(Addr)ARG2, SARG3, SARG4);
-+   PRE_REG_READ4(long, "faccessat2",
-+                 int, dfd, const char *, pathname, int, mode, int, flags);
-+   PRE_MEM_RASCIIZ( "faccessat2(pathname)", ARG2 );
-+}
-+
- PRE(sys_name_to_handle_at)
- {
-    PRINT("sys_name_to_handle_at ( %ld, %#" FMT_REGWORD "x(%s), %#"
-diff --git a/coregrind/m_syswrap/syswrap-mips32-linux.c b/coregrind/m_syswrap/syswrap-mips32-linux.c
-index 5face576b..f35fb8bbb 100644
---- a/coregrind/m_syswrap/syswrap-mips32-linux.c
-+++ b/coregrind/m_syswrap/syswrap-mips32-linux.c
-@@ -1131,6 +1131,8 @@ static SyscallTableEntry syscall_main_table[] = {
-    LINXY(__NR_futex_time64,            sys_futex_time64),            // 422
-    LINXY(__NR_sched_rr_get_interval_time64,
-          sys_sched_rr_get_interval_time64),                          // 423
-+
-+   LINX_ (__NR_faccessat2,             sys_faccessat2),              // 439
- };
- 
- 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 c64911a50..bd260679c 100644
---- a/coregrind/m_syswrap/syswrap-mips64-linux.c
-+++ b/coregrind/m_syswrap/syswrap-mips64-linux.c
-@@ -812,6 +812,7 @@ static SyscallTableEntry syscall_main_table[] = {
-    LINX_ (__NR_syncfs, sys_syncfs),
-    LINXY (__NR_statx, sys_statx),
-    LINX_ (__NR_setns, sys_setns),
-+   LINX_ (__NR_faccessat2, sys_faccessat2),
- };
- 
- 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 7ceecb6da..a904745ab 100644
---- a/coregrind/m_syswrap/syswrap-nanomips-linux.c
-+++ b/coregrind/m_syswrap/syswrap-nanomips-linux.c
-@@ -821,6 +821,7 @@ static SyscallTableEntry syscall_main_table[] = {
-    //    (__NR_pkey_mprotect,          sys_ni_syscall),
-    //    (__NR_pkey_alloc,             sys_ni_syscall),
-    //    (__NR_pkey_free,              sys_ni_syscall),
-+   LINX_ (__NR_faccessat2,             sys_faccessat2),
- };
- 
- 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 c19cb9e0e..6ddd482d9 100644
---- a/coregrind/m_syswrap/syswrap-ppc32-linux.c
-+++ b/coregrind/m_syswrap/syswrap-ppc32-linux.c
-@@ -1049,6 +1049,8 @@ static SyscallTableEntry syscall_table[] = {
-    LINXY(__NR_futex_time64,      sys_futex_time64),     // 422
-    LINXY(__NR_sched_rr_get_interval_time64,
-          sys_sched_rr_get_interval_time64),             // 423
-+
-+   LINX_(__NR_faccessat2,        sys_faccessat2),       // 439
- };
- 
- 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 b6422a765..7026e4ac6 100644
---- a/coregrind/m_syswrap/syswrap-ppc64-linux.c
-+++ b/coregrind/m_syswrap/syswrap-ppc64-linux.c
-@@ -1014,6 +1014,8 @@ static SyscallTableEntry syscall_table[] = {
-    LINX_(__NR_pwritev2,          sys_pwritev2),         // 381
- 
-    LINXY(__NR_statx,             sys_statx),            // 383
-+
-+   LINX_(__NR_faccessat2,        sys_faccessat2),       // 439
- };
- 
- 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 3427fee16..c5e4bb957 100644
---- a/coregrind/m_syswrap/syswrap-s390x-linux.c
-+++ b/coregrind/m_syswrap/syswrap-s390x-linux.c
-@@ -859,6 +859,8 @@ static SyscallTableEntry syscall_table[] = {
-    LINX_(__NR_pwritev2, sys_pwritev2),                                // 377
- 
-    LINXY(__NR_statx, sys_statx),                                      // 379
-+
-+   LINX_(__NR_faccessat2,  sys_faccessat2),                           // 439
- };
- 
- 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 b59d96f37..67d866497 100644
---- a/coregrind/m_syswrap/syswrap-x86-linux.c
-+++ b/coregrind/m_syswrap/syswrap-x86-linux.c
-@@ -1644,6 +1644,8 @@ static SyscallTableEntry syscall_table[] = {
-    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
-+
-+   LINX_(__NR_faccessat2,	 sys_faccessat2),       // 439
- };
- 
- 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 6221d5a81..c8bc31b4b 100644
---- a/include/vki/vki-scnums-shared-linux.h
-+++ b/include/vki/vki-scnums-shared-linux.h
-@@ -39,4 +39,6 @@
- #define __NR_fsmount		432
- #define __NR_fspick		433
- 
-+#define __NR_faccessat2		439
-+
- #endif
--- 
-2.20.1
-
diff --git a/valgrind-3.16.1-ficlone.patch b/valgrind-3.16.1-ficlone.patch
deleted file mode 100644
index 83b00a3..0000000
--- a/valgrind-3.16.1-ficlone.patch
+++ /dev/null
@@ -1,43 +0,0 @@
-commit 1c49351424f04ee29a5efc054cb08ab3ad22b978
-Author: Laurent Bonnans <laurent.bonnans@here.com>
-Date:   Fri Nov 16 15:22:18 2018 +0100
-
-    Fix 397605 - Add support for Linux FICLONE ioctl
-
-diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
-index 41849873e..328e02a98 100644
---- a/coregrind/m_syswrap/syswrap-linux.c
-+++ b/coregrind/m_syswrap/syswrap-linux.c
-@@ -7961,6 +7961,11 @@ PRE(sys_ioctl)
-    case VKI_FIBMAP:
-       PRE_MEM_READ( "ioctl(FIBMAP)", ARG3, sizeof(int));
-       break;
-+   case VKI_FICLONE:
-+      /* The direction of FICLONE (W) is incorrectly specified
-+       * as it expects a file descriptor and not a pointer to
-+       * user data */
-+      break;
- 
-    case VKI_FBIOGET_VSCREENINFO: /* 0x4600 */
-       PRE_MEM_WRITE( "ioctl(FBIOGET_VSCREENINFO)", ARG3,
-@@ -10898,6 +10903,8 @@ POST(sys_ioctl)
-    case VKI_FIBMAP:
-       POST_MEM_WRITE(ARG3, sizeof(int));
-       break;
-+   case VKI_FICLONE:
-+      break;
- 
-    case VKI_FBIOGET_VSCREENINFO: //0x4600
-       POST_MEM_WRITE(ARG3, sizeof(struct vki_fb_var_screeninfo));
-diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h
-index ef93b9258..3b9dc3779 100644
---- a/include/vki/vki-linux.h
-+++ b/include/vki/vki-linux.h
-@@ -1888,6 +1888,7 @@ struct vki_ppdev_frob_struct {
- 
- #define VKI_FIBMAP	_VKI_IO(0x00,1)	/* bmap access */
- #define VKI_FIGETBSZ    _VKI_IO(0x00,2)	/* get the block size used for bmap */
-+#define VKI_FICLONE     _VKI_IOW(0x94, 9, int)
- 
- //----------------------------------------------------------------------
- // From linux-2.6.8.1/include/scsi/sg.h
diff --git a/valgrind-3.16.1-gdbserver_nlcontrolc.patch b/valgrind-3.16.1-gdbserver_nlcontrolc.patch
deleted file mode 100644
index fbc7854..0000000
--- a/valgrind-3.16.1-gdbserver_nlcontrolc.patch
+++ /dev/null
@@ -1,13 +0,0 @@
-diff --git a/gdbserver_tests/nlcontrolc.vgtest b/gdbserver_tests/nlcontrolc.vgtest
-index bb5308403..4eb479595 100644
---- a/gdbserver_tests/nlcontrolc.vgtest
-+++ b/gdbserver_tests/nlcontrolc.vgtest
-@@ -13,7 +13,7 @@ args: 1000000000 1000000000 1000000000 BSBSBSBS 1
- vgopts: --tool=none --vgdb=yes --vgdb-error=0 --vgdb-prefix=./vgdb-prefix-nlcontrolc
- stderr_filter: filter_stderr
- # Bug 338633 nlcontrol hangs on arm64 currently.
--prereq: test -e gdb -a -f vgdb.invoker && ! ../tests/arch_test arm64 && ! ../tests/os_test solaris
-+prereq: false && test -e gdb -a -f vgdb.invoker && ! ../tests/arch_test arm64 && ! ../tests/os_test solaris
- progB: gdb
- argsB: --quiet -l 60 --nx ./sleepers
- stdinB: nlcontrolc.stdinB.gdb
diff --git a/valgrind-3.16.1-open-proc-self-exe.patch b/valgrind-3.16.1-open-proc-self-exe.patch
deleted file mode 100644
index 343f759..0000000
--- a/valgrind-3.16.1-open-proc-self-exe.patch
+++ /dev/null
@@ -1,98 +0,0 @@
-diff --git a/coregrind/m_syswrap/priv_syswrap-generic.h b/coregrind/m_syswrap/priv_syswrap-generic.h
-index 4717abac6..c50b31399 100644
---- a/coregrind/m_syswrap/priv_syswrap-generic.h
-+++ b/coregrind/m_syswrap/priv_syswrap-generic.h
-@@ -106,6 +106,10 @@ extern Bool
- ML_(handle_auxv_open)(SyscallStatus *status, const HChar *filename,
-                       int flags);
- 
-+extern Bool
-+ML_(handle_self_exe_open)(SyscallStatus *status, const HChar *filename,
-+                          int flags);
-+
- /* Helper function for generic mprotect and linux pkey_mprotect. */
- extern void handle_sys_mprotect (ThreadId tid, SyscallStatus *status,
-                                  Addr *addr, SizeT *len, Int *prot);
-diff --git a/coregrind/m_syswrap/syswrap-generic.c b/coregrind/m_syswrap/syswrap-generic.c
-index 7d4b385a3..3810f7474 100644
---- a/coregrind/m_syswrap/syswrap-generic.c
-+++ b/coregrind/m_syswrap/syswrap-generic.c
-@@ -4078,6 +4078,38 @@ Bool ML_(handle_auxv_open)(SyscallStatus *status, const HChar *filename,
- }
- #endif // defined(VGO_linux) || defined(VGO_solaris)
- 
-+#if defined(VGO_linux)
-+Bool ML_(handle_self_exe_open)(SyscallStatus *status, const HChar *filename,
-+                               int flags)
-+{
-+   HChar  name[30];   // large enough for /proc/<int>/exe
-+
-+   if (!ML_(safe_to_deref)((const void *) filename, 1))
-+      return False;
-+
-+   /* Opening /proc/<pid>/exe or /proc/self/exe? */
-+   VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
-+   if (!VG_STREQ(filename, name) && !VG_STREQ(filename, "/proc/self/exe"))
-+      return False;
-+
-+   /* Allow to open the file only for reading. */
-+   if (flags & (VKI_O_WRONLY | VKI_O_RDWR)) {
-+      SET_STATUS_Failure(VKI_EACCES);
-+      return True;
-+   }
-+
-+   SysRes sres = VG_(dup)(VG_(cl_exec_fd));
-+   SET_STATUS_from_SysRes(sres);
-+   if (!sr_isError(sres)) {
-+      OffT off = VG_(lseek)(sr_Res(sres), 0, VKI_SEEK_SET);
-+      if (off < 0)
-+         SET_STATUS_Failure(VKI_EMFILE);
-+   }
-+
-+   return True;
-+}
-+#endif // defined(VGO_linux)
-+
- PRE(sys_open)
- {
-    if (ARG2 & VKI_O_CREAT) {
-@@ -4119,8 +4151,10 @@ PRE(sys_open)
-       }
-    }
- 
--   /* Handle also the case of /proc/self/auxv or /proc/<pid>/auxv. */
--   if (ML_(handle_auxv_open)(status, (const HChar *)(Addr)ARG1, ARG2))
-+   /* Handle also the case of /proc/self/auxv or /proc/<pid>/auxv
-+      or /proc/self/exe or /proc/<pid>/exe. */
-+   if (ML_(handle_auxv_open)(status, (const HChar *)(Addr)ARG1, ARG2)
-+       || ML_(handle_self_exe_open)(status, (const HChar *)(Addr)ARG1, ARG2))
-       return;
- #endif // defined(VGO_linux)
- 
-diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
-index 52074149d..fcc534454 100644
---- a/coregrind/m_syswrap/syswrap-linux.c
-+++ b/coregrind/m_syswrap/syswrap-linux.c
-@@ -5745,6 +5745,22 @@ PRE(sys_openat)
-       return;
-    }
- 
-+   /* And for /proc/self/exe or /proc/<pid>/exe case. */
-+
-+   VG_(sprintf)(name, "/proc/%d/exe", VG_(getpid)());
-+   if (ML_(safe_to_deref)( (void*)(Addr)ARG2, 1 )
-+       && (VG_(strcmp)((HChar *)(Addr)ARG2, name) == 0 
-+           || VG_(strcmp)((HChar *)(Addr)ARG2, "/proc/self/exe") == 0)) {
-+      sres = VG_(dup)( VG_(cl_exec_fd) );
-+      SET_STATUS_from_SysRes( sres );
-+      if (!sr_isError(sres)) {
-+         OffT off = VG_(lseek)( sr_Res(sres), 0, VKI_SEEK_SET );
-+         if (off < 0)
-+            SET_STATUS_Failure( VKI_EMFILE );
-+      }
-+      return;
-+   }
-+
-    /* Otherwise handle normally */
-    *flags |= SfMayBlock;
- }
diff --git a/valgrind-3.16.1-ppc64-scv-hwcap.patch b/valgrind-3.16.1-ppc64-scv-hwcap.patch
deleted file mode 100644
index ef88bef..0000000
--- a/valgrind-3.16.1-ppc64-scv-hwcap.patch
+++ /dev/null
@@ -1,57 +0,0 @@
-From a88c168b4dd607bca47d3a1ec08573d3e5fa889b Mon Sep 17 00:00:00 2001
-From: Florian Weimer <fweimer@redhat.com>
-Date: Fri, 8 Jan 2021 15:08:50 +0100
-Subject: [PATCH] ppc64: Mask unrecognized AT_HWCAP2 values
-
-Also suppress printing a log message for scv instructions in the
-instruction stream.
-
-These changes are required for running glibc 2.33 on kernels with scv
-support under valgrind.
----
- VEX/priv/guest_ppc_toIR.c           | 5 +++--
- coregrind/m_initimg/initimg-linux.c | 6 ++++++
- 2 files changed, 9 insertions(+), 2 deletions(-)
-
-diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c
-index e7b576fa2..99e96a577 100644
---- a/VEX/priv/guest_ppc_toIR.c
-+++ b/VEX/priv/guest_ppc_toIR.c
-@@ -8739,8 +8739,9 @@
- {
-    IRType ty = mode64 ? Ity_I64 : Ity_I32;
- 
--   if (theInstr != 0x44000002) {
--      vex_printf("dis_syslink(ppc)(theInstr)\n");
-+   if (theInstr != 0x44000002) { // sc
-+      if (theInstr != 0x44000001) // scv
-+         vex_printf("dis_syslink(ppc)(theInstr)\n");
-       return False;
-    }
- 
-diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c
-index ba84fa6e9..fb68ae00b 100644
---- a/coregrind/m_initimg/initimg-linux.c
-+++ b/coregrind/m_initimg/initimg-linux.c
-@@ -750,6 +750,7 @@ Addr setup_client_stack( void*  init_sp,
-                 PPC_FEATURE2_HAS_ISEL         0x08000000
-                 PPC_FEATURE2_HAS_TAR          0x04000000
-                 PPC_FEATURE2_HAS_VCRYPTO      0x02000000
-+                PPC_FEATURE2_HAS_IEEE128      0x00400000
-             */
-             auxv_2_07 = (auxv->u.a_val & 0x80000000ULL) == 0x80000000ULL;
-             hw_caps_2_07 = (vex_archinfo->hwcaps & VEX_HWCAPS_PPC64_ISA2_07)
-@@ -757,6 +757,11 @@
- 	     * matches the setting in VEX HWCAPS.
- 	     */
-             vg_assert(auxv_2_07 == hw_caps_2_07);
-+
-+            /* Mask unrecognized HWCAP bits.  Only keep the bits that have
-+             * been mentioned above.
-+             */
-+            auxv->u.a_val &= 0xfec00000ULL;
-             }
- 
-             break;
---- valgrind-3.16.1/VEX/priv/guest_ppc_toIR.c	2021-01-08 16:43:45.947122866 +0100
-+++ guest_ppc_toIR.c.new	2021-01-08 16:43:40.238166866 +0100
diff --git a/valgrind-3.16.1-pthread-intercept.patch b/valgrind-3.16.1-pthread-intercept.patch
deleted file mode 100644
index 8234314..0000000
--- a/valgrind-3.16.1-pthread-intercept.patch
+++ /dev/null
@@ -1,222 +0,0 @@
-commit 15330adf7c2471fbaa6a0818db07078d81dbff97
-Author: Bart Van Assche <bvanassche@acm.org>
-Date:   Sat Sep 19 08:08:59 2020 -0700
-
-    drd: Port to Fedora 33
-    
-    Apparently on Fedora 33 the POSIX thread functions exist in both libc and
-    libpthread. Hence this patch that intercepts the pthread functions in
-    libc. See also https://bugs.kde.org/show_bug.cgi?id=426144 .
-
-diff --git a/drd/drd_pthread_intercepts.c b/drd/drd_pthread_intercepts.c
-index 58c45aaec..c2882e5ab 100644
---- a/drd/drd_pthread_intercepts.c
-+++ b/drd/drd_pthread_intercepts.c
-@@ -174,7 +174,16 @@ static int never_true;
-    ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBC_SONAME,zf) argl_decl            \
-    { return implf argl; }
- #else
-+/*
-+ * On Linux, intercept both the libc and the libpthread functions. At
-+ * least glibc 2.32.9000 (Fedora 34) has an implementation of all pthread
-+ * functions in both libc and libpthread. Older glibc versions only have an
-+ * implementation of the pthread functions in libpthread.
-+ */
- #define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl)                    \
-+   ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBC_SONAME,zf) argl_decl;           \
-+   ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBC_SONAME,zf) argl_decl            \
-+   { return implf argl; }                                               \
-    ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl;     \
-    ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl      \
-    { return implf argl; }
-
-commit 3073d03e4b6e76797828b3f466863dbdda76cc7a
-Author: Bart Van Assche <bvanassche@acm.org>
-Date:   Tue Oct 20 19:40:19 2020 -0700
-
-    drd: Unbreak the musl build
-    
-    See also https://bugs.kde.org/show_bug.cgi?id=428035.
-    
-    Reported-by: Stacy <stacy.gaikovaia@windriver.com>
-    Fixes: 15330adf7c24 ("drd: Port to Fedora 33")
-
-diff --git a/drd/drd_pthread_intercepts.c b/drd/drd_pthread_intercepts.c
-index 62c466f50..585aafe22 100644
---- a/drd/drd_pthread_intercepts.c
-+++ b/drd/drd_pthread_intercepts.c
-@@ -174,6 +174,13 @@ static int never_true;
-    ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBC_SONAME,zf) argl_decl            \
-    { return implf argl; }
- #else
-+#ifdef MUSL_LIBC
-+/* musl provides a single library that includes pthreads functions. */
-+#define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl)                    \
-+   ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl;     \
-+   ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl      \
-+   { return implf argl; }
-+#else
- /*
-  * On Linux, intercept both the libc and the libpthread functions. At
-  * least glibc 2.32.9000 (Fedora 34) has an implementation of all pthread
-@@ -188,6 +195,7 @@ static int never_true;
-    ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl      \
-    { return implf argl; }
- #endif
-+#endif
- 
- /**
-  * Macro for generating three Valgrind interception functions: one with the
-diff --git a/drd/drd_pthread_intercepts.c b/drd/drd_pthread_intercepts.c
-
-index 585aafe22..3d1f90d3b 100644
---- a/drd/drd_pthread_intercepts.c
-+++ b/drd/drd_pthread_intercepts.c
-@@ -151,7 +151,7 @@ static drd_rtld_guard_fn DRD_(rtld_bind_clear) = NULL;
-  * @param[in] arg_decl Argument declaration list enclosed in parentheses.
-  * @param[in] argl Argument list enclosed in parentheses.
-  */
--#ifdef VGO_darwin
-+#if defined(VGO_darwin)
- static int never_true;
- #define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl)                    \
-    ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl;     \
-@@ -164,29 +164,12 @@ static int never_true;
- 	 fflush(stdout);						\
-       return pth_func_result;						\
-    }
--#elif defined(VGO_solaris)
--/* On Solaris, libpthread is just a filter library on top of libc.
-- * Threading and synchronization functions in runtime linker are not
-- * intercepted.
-- */
-+#elif defined(VG_WRAP_THREAD_FUNCTION_LIBC_ONLY)
- #define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl)                    \
-    ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBC_SONAME,zf) argl_decl;           \
-    ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBC_SONAME,zf) argl_decl            \
-    { return implf argl; }
--#else
--#ifdef MUSL_LIBC
--/* musl provides a single library that includes pthreads functions. */
--#define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl)                    \
--   ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl;     \
--   ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl      \
--   { return implf argl; }
--#else
--/*
-- * On Linux, intercept both the libc and the libpthread functions. At
-- * least glibc 2.32.9000 (Fedora 34) has an implementation of all pthread
-- * functions in both libc and libpthread. Older glibc versions only have an
-- * implementation of the pthread functions in libpthread.
-- */
-+#elif defined(VG_WRAP_THREAD_FUNCTION_LIBC_AND_LIBPTHREAD)
- #define PTH_FUNC(ret_ty, zf, implf, argl_decl, argl)                    \
-    ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBC_SONAME,zf) argl_decl;           \
-    ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBC_SONAME,zf) argl_decl            \
-@@ -194,7 +177,8 @@ static int never_true;
-    ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl;     \
-    ret_ty VG_WRAP_FUNCTION_ZZ(VG_Z_LIBPTHREAD_SONAME,zf) argl_decl      \
-    { return implf argl; }
--#endif
-+#else
-+#  error "Unknown platform/thread wrapping"
- #endif
- 
- /**
-diff --git a/helgrind/hg_intercepts.c b/helgrind/hg_intercepts.c
-index a10c3a4a3..2bc89f8a0 100644
---- a/helgrind/hg_intercepts.c
-+++ b/helgrind/hg_intercepts.c
-@@ -78,26 +78,37 @@
- /*----------------------------------------------------------------*/
- 
- #if defined(VGO_solaris)
--/* On Solaris, libpthread is just a filter library on top of libc.
-- * Threading and synchronization functions in runtime linker are not
-- * intercepted.
-- */
--#define PTH_FUNC(ret_ty, f, args...) \
--   ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)(args); \
--   ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)(args)
--
- /* pthread_t is typedef'd to 'unsigned int' but in DO_CREQ_* macros
-    sizeof(Word) is expected. */
- #define CREQ_PTHREAD_T Word
- #define SEM_ERROR ret
- #else
--#define PTH_FUNC(ret_ty, f, args...) \
--   ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args); \
--   ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args)
- #define CREQ_PTHREAD_T pthread_t
- #define SEM_ERROR errno
- #endif /* VGO_solaris */
- 
-+#define HG_EXPAND(tok) #tok
-+#define HG_STR(tok) HG_EXPAND(tok)
-+#define HG_WEAK_ALIAS(name, aliasname) \
-+  extern __typeof (name) aliasname __attribute__ ((weak, alias(HG_STR(name))))
-+
-+#if defined(VG_WRAP_THREAD_FUNCTION_LIBPTHREAD_ONLY)
-+#define PTH_FUNC(ret_ty, f, args...) \
-+   ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args); \
-+   ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args)
-+#elif defined(VG_WRAP_THREAD_FUNCTION_LIBC_AND_LIBPTHREAD)
-+#define PTH_FUNC(ret_ty, f, args...) \
-+   ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args); \
-+   HG_WEAK_ALIAS(I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f), I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)); \
-+   ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBPTHREAD_SONAME,f)(args)
-+#elif defined(VG_WRAP_THREAD_FUNCTION_LIBC_ONLY)
-+#define PTH_FUNC(ret_ty, f, args...) \
-+   ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)(args); \
-+   ret_ty I_WRAP_SONAME_FNNAME_ZZ(VG_Z_LIBC_SONAME,f)(args)
-+#else
-+#  error "Unknown platform/thread wrapping"
-+#endif
-+
- // Do a client request.  These are macros rather than a functions so
- // as to avoid having an extra frame in stack traces.
- 
-diff --git a/include/pub_tool_redir.h b/include/pub_tool_redir.h
-index bd65a44b4..d665afd98 100644
---- a/include/pub_tool_redir.h
-+++ b/include/pub_tool_redir.h
-@@ -277,11 +277,7 @@
- /* --- Soname of the pthreads library. --- */
- 
- #if defined(VGO_linux)
--# if defined(MUSL_LIBC)
--#  define  VG_Z_LIBPTHREAD_SONAME  libcZdZa              // libc.*
--#else
- #  define  VG_Z_LIBPTHREAD_SONAME  libpthreadZdsoZd0     // libpthread.so.0
--#endif
- #elif defined(VGO_darwin)
- #  define  VG_Z_LIBPTHREAD_SONAME  libSystemZdZaZddylib  // libSystem.*.dylib
- #elif defined(VGO_solaris)
-@@ -364,6 +360,27 @@
- 
- Bool VG_(is_soname_ld_so) (const HChar *soname);
- 
-+// Some macros to help decide which libraries (libc or libpthread
-+// or some platform-specific variation of these) should be used
-+// for wrapping pthread/semaphore functions with DRD and Helgrind
-+// The possibilities are a) only in libpthread
-+// b) mabye in both libpthread and libc or c) only in libc
-+// Linux GNU libc is moving from a) to c) (starting with Fedora 33)
-+// Linux MUSL libc is c)
-+// Darwin is a)
-+// Solaris is c)
-+// FreeBSD is b)
-+
-+#if defined(VGO_darwin)
-+#define VG_WRAP_THREAD_FUNCTION_LIBPTHREAD_ONLY
-+#elif defined(VGO_solaris) || (defined(VGO_linux) && defined(MUSL_LIBC))
-+#define VG_WRAP_THREAD_FUNCTION_LIBC_ONLY
-+#elif defined(VGO_linux)
-+#define VG_WRAP_THREAD_FUNCTION_LIBC_AND_LIBPTHREAD
-+#else
-+#  error "Unknown platform"
-+#endif
-+
- #endif   // __PUB_TOOL_REDIR_H
- 
- /*--------------------------------------------------------------------*/
diff --git a/valgrind-3.16.1-readdwarf-line.patch b/valgrind-3.16.1-readdwarf-line.patch
deleted file mode 100644
index cfe34a8..0000000
--- a/valgrind-3.16.1-readdwarf-line.patch
+++ /dev/null
@@ -1,53 +0,0 @@
-commit 67363912e9cdba83869a72ff8c4084e7a7e4ab85
-Author: Mark Wielaard <mark@klomp.org>
-Date:   Sun Feb 21 22:45:51 2021 +0100
-
-    Fix typo in DWARF 5 line table readers
-    
-    This typo meant the directory entry was most often zero, which
-    happened to be sometimes correct anyway (since zero is the compdir).
-    So for simple testcases it looked correct. But it would be wrong for
-    compilation units not in the current compdir. Like files compiled with
-    a relative of absolute path.
-    
-    The same typo was in both readdwarf.c (read_dwarf2_lineblock) and
-    readdwarf3.c (read_filename_table). read_dwarf2_lineblock also had
-    an extra "dwarf" string in the debug-line output.
-    
-    https://bugzilla.redhat.com/show_bug.cgi?id=1927153
-
-diff --git a/coregrind/m_debuginfo/readdwarf.c b/coregrind/m_debuginfo/readdwarf.c
-index 88d5d99f1..3996623ed 100644
---- a/coregrind/m_debuginfo/readdwarf.c
-+++ b/coregrind/m_debuginfo/readdwarf.c
-@@ -683,7 +683,7 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
-       directories_count = step_leb128U(&data);
-       /* Read the contents of the Directory table.  */
-       if (di->ddump_line)
--         VG_(printf)(" dwarf The Directory Table%s\n",
-+         VG_(printf)(" The Directory Table%s\n",
-                      directories_count == 0 ? " is empty." : ":" );
- 
-       for (n = 0; n < directories_count; n++) {
-@@ -796,7 +796,7 @@ void read_dwarf2_lineblock ( struct _DebugInfo* di,
-             if (f == p_ndx)
-                name = get_line_str (di, ui, &data, form,
-                                     debugstr_img, debuglinestr_img);
--            else if (n == d_ndx)
-+            else if (f == d_ndx)
-                diridx = get_line_ndx (di, &data, form);
-             else
-                data = skip_line_form (di, ui, data, form);
-diff --git a/coregrind/m_debuginfo/readdwarf3.c b/coregrind/m_debuginfo/readdwarf3.c
-index 82bc8f241..60fc40244 100644
---- a/coregrind/m_debuginfo/readdwarf3.c
-+++ b/coregrind/m_debuginfo/readdwarf3.c
-@@ -2323,7 +2323,7 @@ void read_filename_table( /*MOD*/XArray* /* of UInt* */ fndn_ix_Table,
-             if (f == p_ndx)
-                str = get_line_str (cc->di, cc->is_dw64, &c, form,
-                                    debugstr_img, debuglinestr_img);
--            else if (n == d_ndx)
-+            else if (f == d_ndx)
-                dir_xa_ix = get_line_ndx (cc->di, &c, form);
-             else
-                skip_line_form (cc->di, cc->is_dw64, &c, form);
diff --git a/valgrind-3.16.1-s390_emit_load_mem.patch b/valgrind-3.16.1-s390_emit_load_mem.patch
deleted file mode 100644
index 95da59f..0000000
--- a/valgrind-3.16.1-s390_emit_load_mem.patch
+++ /dev/null
@@ -1,27 +0,0 @@
-commit ba73f8d2ebe4b5fe8163ee5ab806f0e50961ebdf
-Author: Andreas Arnez <arnez@linux.ibm.com>
-Date:   Tue Nov 3 18:17:30 2020 +0100
-
-    Bug 428648 - s390x: Force 12-bit amode for vector loads in isel
-    
-    Similar to Bug 417452, where the instruction selector sometimes attempted
-    to generate vector stores with a 20-bit displacement, the same problem has
-    now been reported with vector loads.
-    
-    The problem is caused in s390_isel_vec_expr_wrk(), where the addressing
-    mode is generated with s390_isel_amode() instead of
-    s390_isel_amode_short().  This is fixed.
-
-diff --git a/VEX/priv/host_s390_isel.c b/VEX/priv/host_s390_isel.c
-index 2f80dd850..134f3eb6f 100644
---- a/VEX/priv/host_s390_isel.c
-+++ b/VEX/priv/host_s390_isel.c
-@@ -3741,7 +3741,7 @@ s390_isel_vec_expr_wrk(ISelEnv *env, IRExpr *expr)
-    /* --------- LOAD --------- */
-    case Iex_Load: {
-       HReg        dst = newVRegV(env);
--      s390_amode *am  = s390_isel_amode(env, expr->Iex.Load.addr);
-+      s390_amode *am  = s390_isel_amode_short(env, expr->Iex.Load.addr);
- 
-       if (expr->Iex.Load.end != Iend_BE)
-          goto irreducible;
diff --git a/valgrind-3.16.1-s390x-z14-vector.patch b/valgrind-3.16.1-s390x-z14-vector.patch
deleted file mode 100644
index 747c8a8..0000000
--- a/valgrind-3.16.1-s390x-z14-vector.patch
+++ /dev/null
@@ -1,2977 +0,0 @@
-diff --git a/VEX/priv/guest_s390_defs.h b/VEX/priv/guest_s390_defs.h
-index 9f93cff19..905429015 100644
---- a/VEX/priv/guest_s390_defs.h
-+++ b/VEX/priv/guest_s390_defs.h
-@@ -8,7 +8,7 @@
-    This file is part of Valgrind, a dynamic binary instrumentation
-    framework.
- 
--   Copyright IBM Corp. 2010-2017
-+   Copyright IBM Corp. 2010-2020
- 
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-@@ -263,26 +263,27 @@ extern ULong last_execute_target;
-    before  S390_VEC_OP_LAST. */
- typedef enum {
-    S390_VEC_OP_INVALID = 0,
--   S390_VEC_OP_VPKS = 1,
--   S390_VEC_OP_VPKLS = 2,
--   S390_VEC_OP_VFAE = 3,
--   S390_VEC_OP_VFEE = 4,
--   S390_VEC_OP_VFENE = 5,
--   S390_VEC_OP_VISTR = 6,
--   S390_VEC_OP_VSTRC = 7,
--   S390_VEC_OP_VCEQ = 8,
--   S390_VEC_OP_VTM = 9,
--   S390_VEC_OP_VGFM = 10,
--   S390_VEC_OP_VGFMA = 11,
--   S390_VEC_OP_VMAH = 12,
--   S390_VEC_OP_VMALH = 13,
--   S390_VEC_OP_VCH = 14,
--   S390_VEC_OP_VCHL = 15,
--   S390_VEC_OP_VFCE = 16,
--   S390_VEC_OP_VFCH = 17,
--   S390_VEC_OP_VFCHE = 18,
--   S390_VEC_OP_VFTCI = 19,
--   S390_VEC_OP_LAST = 20 // supposed to be the last element in enum
-+   S390_VEC_OP_VPKS,
-+   S390_VEC_OP_VPKLS,
-+   S390_VEC_OP_VFAE,
-+   S390_VEC_OP_VFEE,
-+   S390_VEC_OP_VFENE,
-+   S390_VEC_OP_VISTR,
-+   S390_VEC_OP_VSTRC,
-+   S390_VEC_OP_VCEQ,
-+   S390_VEC_OP_VTM,
-+   S390_VEC_OP_VGFM,
-+   S390_VEC_OP_VGFMA,
-+   S390_VEC_OP_VMAH,
-+   S390_VEC_OP_VMALH,
-+   S390_VEC_OP_VCH,
-+   S390_VEC_OP_VCHL,
-+   S390_VEC_OP_VFTCI,
-+   S390_VEC_OP_VFMIN,
-+   S390_VEC_OP_VFMAX,
-+   S390_VEC_OP_VBPERM,
-+   S390_VEC_OP_VMSL,
-+   S390_VEC_OP_LAST             // supposed to be the last element in enum
- } s390x_vec_op_t;
- 
- /* Arguments of s390x_dirtyhelper_vec_op(...) which are packed into one
-diff --git a/VEX/priv/guest_s390_helpers.c b/VEX/priv/guest_s390_helpers.c
-index a470d9f8d..b71b621ae 100644
---- a/VEX/priv/guest_s390_helpers.c
-+++ b/VEX/priv/guest_s390_helpers.c
-@@ -8,7 +8,7 @@
-    This file is part of Valgrind, a dynamic binary instrumentation
-    framework.
- 
--   Copyright IBM Corp. 2010-2017
-+   Copyright IBM Corp. 2010-2020
- 
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-@@ -314,20 +314,11 @@ ULong s390x_dirtyhelper_STCKE(ULong *addr) {return 3;}
- /*--- Dirty helper for Store Facility instruction          ---*/
- /*------------------------------------------------------------*/
- #if defined(VGA_s390x)
--static void
--s390_set_facility_bit(ULong *addr, UInt bitno, UInt value)
--{
--   addr  += bitno / 64;
--   bitno  = bitno % 64;
--
--   ULong mask = 1;
--   mask <<= (63 - bitno);
- 
--   if (value == 1) {
--      *addr |= mask;   // set
--   } else {
--      *addr &= ~mask;  // clear
--   }
-+static ULong
-+s390_stfle_range(UInt lo, UInt hi)
-+{
-+   return ((1UL << (hi + 1 - lo)) - 1) << (63 - (hi % 64));
- }
- 
- ULong
-@@ -336,6 +327,77 @@ s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
-    ULong hoststfle[S390_NUM_FACILITY_DW], cc, num_dw, i;
-    register ULong reg0 asm("0") = guest_state->guest_r0 & 0xF;  /* r0[56:63] */
- 
-+   /* Restrict to facilities that we know about and that we assume to be
-+      compatible with Valgrind.  Of course, in this way we may reject features
-+      that Valgrind is not really involved in (and thus would be compatible
-+      with), but quering for such features doesn't seem like a typical use
-+      case. */
-+   ULong accepted_facility[S390_NUM_FACILITY_DW] = {
-+      /* ===  0 .. 63  === */
-+      (s390_stfle_range(0, 16)
-+       /* 17: message-security-assist, not supported */
-+       | s390_stfle_range(18, 19)
-+       /* 20: HFP-multiply-and-add/subtract, not supported */
-+       | s390_stfle_range(21, 22)
-+       /* 23: HFP-unnormalized-extension, not supported */
-+       | s390_stfle_range(24, 25)
-+       /* 26: parsing-enhancement, not supported */
-+       | s390_stfle_range(27, 28)
-+       /* 29: unassigned */
-+       | s390_stfle_range(30, 30)
-+       /* 31: extract-CPU-time, not supported */
-+       | s390_stfle_range(32, 41)
-+       /* 42-43: DFP, not fully supported */
-+       /* 44: PFPO, not fully supported */
-+       | s390_stfle_range(45, 47)
-+       /* 48: DFP zoned-conversion, not supported */
-+       /* 49: includes PPA, not supported */
-+       /* 50: constrained transactional-execution, not supported */
-+       | s390_stfle_range(51, 55)
-+       /* 56: unassigned */
-+       /* 57: MSA5, not supported */
-+       | s390_stfle_range(58, 60)
-+       /* 61: miscellaneous-instruction 3, not supported */
-+       | s390_stfle_range(62, 63)),
-+
-+      /* ===  64 .. 127  === */
-+      (s390_stfle_range(64, 72)
-+       /* 73: transactional-execution, not supported */
-+       | s390_stfle_range(74, 75)
-+       /* 76: MSA3, not supported */
-+       /* 77: MSA4, not supported */
-+       | s390_stfle_range(78, 78)
-+       /* 80: DFP packed-conversion, not supported */
-+       /* 81: PPA-in-order, not supported */
-+       | s390_stfle_range(82, 82)
-+       /* 83-127: unassigned */ ),
-+
-+      /* ===  128 .. 191  === */
-+      (s390_stfle_range(128, 131)
-+       /* 132: unassigned */
-+       /* 133: guarded-storage, not supported */
-+       /* 134: vector packed decimal, not supported */
-+       | s390_stfle_range(135, 135)
-+       /* 136: unassigned */
-+       /* 137: unassigned */
-+       | s390_stfle_range(138, 142)
-+       /* 143: unassigned */
-+       | s390_stfle_range(144, 145)
-+       /* 146: MSA8, not supported */
-+       | s390_stfle_range(147, 147)
-+       /* 148: vector-enhancements 2, not supported */
-+       | s390_stfle_range(149, 149)
-+       /* 150: unassigned */
-+       /* 151: DEFLATE-conversion, not supported */
-+       /* 153: unassigned */
-+       /* 154: unassigned */
-+       /* 155: MSA9, not supported */
-+       | s390_stfle_range(156, 156)
-+       /* 157-167: unassigned */
-+       | s390_stfle_range(168, 168)
-+       /* 168-191: unassigned */ ),
-+   };
-+
-    /* We cannot store more than S390_NUM_FACILITY_DW
-       (and it makes not much sense to do so anyhow) */
-    if (reg0 > S390_NUM_FACILITY_DW - 1)
-@@ -351,35 +413,9 @@ s390x_dirtyhelper_STFLE(VexGuestS390XState *guest_state, ULong *addr)
-    /* Update guest register 0  with what STFLE set r0 to */
-    guest_state->guest_r0 = reg0;
- 
--   /* Set default: VM facilities = host facilities */
-+   /* VM facilities = host facilities, filtered by acceptance */
-    for (i = 0; i < num_dw; ++i)
--      addr[i] = hoststfle[i];
--
--   /* Now adjust the VM facilities according to what the VM supports */
--   s390_set_facility_bit(addr, S390_FAC_LDISP,  1);
--   s390_set_facility_bit(addr, S390_FAC_EIMM,   1);
--   s390_set_facility_bit(addr, S390_FAC_ETF2,   1);
--   s390_set_facility_bit(addr, S390_FAC_ETF3,   1);
--   s390_set_facility_bit(addr, S390_FAC_GIE,    1);
--   s390_set_facility_bit(addr, S390_FAC_EXEXT,  1);
--   s390_set_facility_bit(addr, S390_FAC_HIGHW,  1);
--   s390_set_facility_bit(addr, S390_FAC_LSC2,   1);
--
--   s390_set_facility_bit(addr, S390_FAC_HFPMAS, 0);
--   s390_set_facility_bit(addr, S390_FAC_HFPUNX, 0);
--   s390_set_facility_bit(addr, S390_FAC_XCPUT,  0);
--   s390_set_facility_bit(addr, S390_FAC_MSA,    0);
--   s390_set_facility_bit(addr, S390_FAC_PENH,   0);
--   s390_set_facility_bit(addr, S390_FAC_DFP,    0);
--   s390_set_facility_bit(addr, S390_FAC_PFPO,   0);
--   s390_set_facility_bit(addr, S390_FAC_DFPZC,  0);
--   s390_set_facility_bit(addr, S390_FAC_MISC,   0);
--   s390_set_facility_bit(addr, S390_FAC_CTREXE, 0);
--   s390_set_facility_bit(addr, S390_FAC_TREXE,  0);
--   s390_set_facility_bit(addr, S390_FAC_MSA4,   0);
--   s390_set_facility_bit(addr, S390_FAC_VXE,    0);
--   s390_set_facility_bit(addr, S390_FAC_VXE2,   0);
--   s390_set_facility_bit(addr, S390_FAC_DFLT,   0);
-+      addr[i] = hoststfle[i] & accepted_facility[i];
- 
-    return cc;
- }
-@@ -2500,25 +2536,26 @@ s390x_dirtyhelper_vec_op(VexGuestS390XState *guest_state,
-    vassert(d->op > S390_VEC_OP_INVALID && d->op < S390_VEC_OP_LAST);
-    static const UChar opcodes[][2] = {
-       {0x00, 0x00}, /* invalid */
--      {0xe7, 0x97}, /* VPKS */
--      {0xe7, 0x95}, /* VPKLS */
--      {0xe7, 0x82}, /* VFAE */
--      {0xe7, 0x80}, /* VFEE */
--      {0xe7, 0x81}, /* VFENE */
--      {0xe7, 0x5c}, /* VISTR */
--      {0xe7, 0x8a}, /* VSTRC */
--      {0xe7, 0xf8}, /* VCEQ */
--      {0xe7, 0xd8}, /* VTM */
--      {0xe7, 0xb4}, /* VGFM */
--      {0xe7, 0xbc}, /* VGFMA */
--      {0xe7, 0xab}, /* VMAH */
--      {0xe7, 0xa9}, /* VMALH */
--      {0xe7, 0xfb}, /* VCH */
--      {0xe7, 0xf9}, /* VCHL */
--      {0xe7, 0xe8}, /* VFCE */
--      {0xe7, 0xeb}, /* VFCH */
--      {0xe7, 0xea}, /* VFCHE */
--      {0xe7, 0x4a}  /* VFTCI */
-+      [S390_VEC_OP_VPKS]  = {0xe7, 0x97},
-+      [S390_VEC_OP_VPKLS] = {0xe7, 0x95},
-+      [S390_VEC_OP_VFAE]  = {0xe7, 0x82},
-+      [S390_VEC_OP_VFEE]  = {0xe7, 0x80},
-+      [S390_VEC_OP_VFENE] = {0xe7, 0x81},
-+      [S390_VEC_OP_VISTR] = {0xe7, 0x5c},
-+      [S390_VEC_OP_VSTRC] = {0xe7, 0x8a},
-+      [S390_VEC_OP_VCEQ]  = {0xe7, 0xf8},
-+      [S390_VEC_OP_VTM]   = {0xe7, 0xd8},
-+      [S390_VEC_OP_VGFM]  = {0xe7, 0xb4},
-+      [S390_VEC_OP_VGFMA] = {0xe7, 0xbc},
-+      [S390_VEC_OP_VMAH]  = {0xe7, 0xab},
-+      [S390_VEC_OP_VMALH] = {0xe7, 0xa9},
-+      [S390_VEC_OP_VCH]   = {0xe7, 0xfb},
-+      [S390_VEC_OP_VCHL]  = {0xe7, 0xf9},
-+      [S390_VEC_OP_VFTCI] = {0xe7, 0x4a},
-+      [S390_VEC_OP_VFMIN] = {0xe7, 0xee},
-+      [S390_VEC_OP_VFMAX] = {0xe7, 0xef},
-+      [S390_VEC_OP_VBPERM]= {0xe7, 0x85},
-+      [S390_VEC_OP_VMSL]  = {0xe7, 0xb8},
-    };
- 
-    union {
-@@ -2612,6 +2649,7 @@ s390x_dirtyhelper_vec_op(VexGuestS390XState *guest_state,
-    case S390_VEC_OP_VGFMA:
-    case S390_VEC_OP_VMAH:
-    case S390_VEC_OP_VMALH:
-+   case S390_VEC_OP_VMSL:
-       the_insn.VRRd.v1 = 1;
-       the_insn.VRRd.v2 = 2;
-       the_insn.VRRd.v3 = 3;
-@@ -2621,9 +2659,9 @@ s390x_dirtyhelper_vec_op(VexGuestS390XState *guest_state,
-       the_insn.VRRd.m6 = d->m5;
-       break;
- 
--   case S390_VEC_OP_VFCE:
--   case S390_VEC_OP_VFCH:
--   case S390_VEC_OP_VFCHE:
-+   case S390_VEC_OP_VFMIN:
-+   case S390_VEC_OP_VFMAX:
-+   case S390_VEC_OP_VBPERM:
-       the_insn.VRRc.v1 = 1;
-       the_insn.VRRc.v2 = 2;
-       the_insn.VRRc.v3 = 3;
-diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c
-index c27a8d3fe..5f2c5ce98 100644
---- a/VEX/priv/guest_s390_toIR.c
-+++ b/VEX/priv/guest_s390_toIR.c
-@@ -8,7 +8,7 @@
-    This file is part of Valgrind, a dynamic binary instrumentation
-    framework.
- 
--   Copyright IBM Corp. 2010-2017
-+   Copyright IBM Corp. 2010-2020
- 
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-@@ -248,6 +248,13 @@ typedef enum {
- #define VRS_d2(insn) (((insn) >> 32) & 0xfff)
- #define VRS_m4(insn) (((insn) >> 28) & 0xf)
- #define VRS_rxb(insn) (((insn) >> 24) & 0xf)
-+#define VRSd_v1(insn) (((insn) >> 28) & 0xf)
-+#define VRSd_r3(insn) (((insn) >> 48) & 0xf)
-+#define VSI_i3(insn) (((insn) >> 48) & 0xff)
-+#define VSI_b2(insn) (((insn) >> 44) & 0xf)
-+#define VSI_d2(insn) (((insn) >> 32) & 0xfff)
-+#define VSI_v1(insn) (((insn) >> 28) & 0xf)
-+#define VSI_rxb(insn) (((insn) >> 24) & 0xf)
- 
- 
- /*------------------------------------------------------------*/
-@@ -1934,6 +1941,26 @@ s390_vr_get_type(const UChar m)
-    return results[m];
- }
- 
-+/* Determine IRType from instruction's floating-point format field */
-+static IRType
-+s390_vr_get_ftype(const UChar m)
-+{
-+   static const IRType results[] = {Ity_F32, Ity_F64, Ity_F128};
-+   if (m >= 2 && m <= 4)
-+      return results[m - 2];
-+   return Ity_INVALID;
-+}
-+
-+/* Determine number of elements from instruction's floating-point format
-+   field */
-+static UChar
-+s390_vr_get_n_elem(const UChar m)
-+{
-+   if (m >= 2 && m <= 4)
-+      return 1 << (4 - m);
-+   return 0;
-+}
-+
- /* Determine if Condition Code Set (CS) flag is set in m field */
- #define s390_vr_is_cs_set(m) (((m) & 0x1) != 0)
- 
-@@ -2188,12 +2215,15 @@ s390_vr_offset_by_index(UInt archreg,IRType type, UChar index)
-          goto invalidIndex;
-       }
-       return vr_offset(archreg) + sizeof(ULong) * index;
-+
-    case Ity_V128:
-+   case Ity_F128:
-       if(index == 0) {
-          return vr_qw_offset(archreg);
-       } else {
-          goto invalidIndex;
-       }
-+
-    default:
-       vpanic("s390_vr_offset_by_index: unknown type");
-    }
-@@ -2211,7 +2241,14 @@ put_vr(UInt archreg, IRType type, UChar index, IRExpr *expr)
-    UInt offset = s390_vr_offset_by_index(archreg, type, index);
-    vassert(typeOfIRExpr(irsb->tyenv, expr) == type);
- 
--   stmt(IRStmt_Put(offset, expr));
-+   if (type == Ity_F128) {
-+      IRTemp val = newTemp(Ity_F128);
-+      assign(val, expr);
-+      stmt(IRStmt_Put(offset, unop(Iop_F128HItoF64, mkexpr(val))));
-+      stmt(IRStmt_Put(offset + 8, unop(Iop_F128LOtoF64, mkexpr(val))));
-+   } else {
-+      stmt(IRStmt_Put(offset, expr));
-+   }
- }
- 
- /* Read type sized part specified by index of a vr register. */
-@@ -2219,6 +2256,11 @@ static IRExpr *
- get_vr(UInt archreg, IRType type, UChar index)
- {
-    UInt offset = s390_vr_offset_by_index(archreg, type, index);
-+   if (type == Ity_F128) {
-+      return binop(Iop_F64HLtoF128,
-+                   IRExpr_Get(offset, Ity_F64),
-+                   IRExpr_Get(offset + 8, Ity_F64));
-+   }
-    return IRExpr_Get(offset, type);
- }
- 
-@@ -2294,11 +2336,11 @@ s390_getCountToBlockBoundary(IRTemp op2addr, UChar m)
-    return mkexpr(output);
- }
- 
--/* Load bytes into v1.
--   maxIndex specifies max index to load and must be Ity_I32.
--   If maxIndex >= 15, all 16 bytes are loaded.
--   All bytes after maxIndex are zeroed. */
--static void s390_vr_loadWithLength(UChar v1, IRTemp addr, IRExpr *maxIndex)
-+/* Starting from addr, load at most maxIndex + 1 bytes into v1.  Fill the
-+   leftmost or rightmost bytes of v1, depending on whether `rightmost' is set.
-+   If maxIndex >= 15, load all 16 bytes; otherwise clear the remaining bytes. */
-+static void
-+s390_vr_loadWithLength(UChar v1, IRTemp addr, IRExpr *maxIndex, Bool rightmost)
- {
-    IRTemp maxIdx = newTemp(Ity_I32);
-    IRTemp cappedMax = newTemp(Ity_I64);
-@@ -2311,8 +2353,8 @@ static void s390_vr_loadWithLength(UChar v1, IRTemp addr, IRExpr *maxIndex)
-       crossed if and only if the real insn would have crossed it as well.
-       Thus, if the bytes to load are fully contained in an aligned 16-byte
-       chunk, load the whole 16-byte aligned chunk, and otherwise load 16 bytes
--      from the unaligned address.  Then shift the loaded data left-aligned
--      into the target vector register. */
-+      from the unaligned address.  Then shift the loaded data left- or
-+      right-aligned into the target vector register. */
- 
-    assign(maxIdx, maxIndex);
-    assign(cappedMax, mkite(binop(Iop_CmpLT32U, mkexpr(maxIdx), mkU32(15)),
-@@ -2325,20 +2367,60 @@ static void s390_vr_loadWithLength(UChar v1, IRTemp addr, IRExpr *maxIndex)
-    assign(back, mkite(binop(Iop_CmpLE64U, mkexpr(offset), mkexpr(zeroed)),
-                       mkexpr(offset), mkU64(0)));
- 
--   /* How much to shift the loaded 16-byte vector to the right, and then to
--      the left.  Since both 'zeroed' and 'back' range from 0 to 15, the shift
--      amounts range from 0 to 120. */
--   IRExpr *shrAmount = binop(Iop_Shl64,
--                             binop(Iop_Sub64, mkexpr(zeroed), mkexpr(back)),
--                             mkU8(3));
--   IRExpr *shlAmount = binop(Iop_Shl64, mkexpr(zeroed), mkU8(3));
-+   IRExpr* chunk = load(Ity_V128, binop(Iop_Sub64, mkexpr(addr), mkexpr(back)));
-+
-+   /* Shift the loaded 16-byte vector to the right, then to the left, or vice
-+      versa, where each shift amount ranges from 0 to 120. */
-+   IRExpr* shift1;
-+   IRExpr* shift2 = unop(Iop_64to8, binop(Iop_Shl64, mkexpr(zeroed), mkU8(3)));
-+
-+   if (rightmost) {
-+      shift1 = unop(Iop_64to8, binop(Iop_Shl64, mkexpr(back), mkU8(3)));
-+      put_vr_qw(v1, binop(Iop_ShrV128,
-+                          binop(Iop_ShlV128, chunk, shift1),
-+                          shift2));
-+   } else {
-+      shift1 = unop(Iop_64to8,
-+                    binop(Iop_Shl64,
-+                          binop(Iop_Sub64, mkexpr(zeroed), mkexpr(back)),
-+                          mkU8(3)));
-+      put_vr_qw(v1, binop(Iop_ShlV128,
-+                          binop(Iop_ShrV128, chunk, shift1),
-+                          shift2));
-+   }
-+}
-+
-+/* Store at most maxIndex + 1 bytes from v1 to addr.  Store the leftmost or
-+   rightmost bytes of v1, depending on whether `rightmost' is set.  If maxIndex
-+   >= 15, store all 16 bytes. */
-+static void
-+s390_vr_storeWithLength(UChar v1, IRTemp addr, IRExpr *maxIndex, Bool rightmost)
-+{
-+   IRTemp maxIdx = newTemp(Ity_I32);
-+   IRTemp cappedMax = newTemp(Ity_I64);
-+   IRTemp counter = newTemp(Ity_I64);
-+   IRExpr* offset;
-+
-+   assign(maxIdx, maxIndex);
-+   assign(cappedMax, mkite(binop(Iop_CmpLT32U, mkexpr(maxIdx), mkU32(15)),
-+                           unop(Iop_32Uto64, mkexpr(maxIdx)), mkU64(15)));
-+
-+   assign(counter, get_counter_dw0());
-+
-+   if (rightmost)
-+      offset = binop(Iop_Add64,
-+                     binop(Iop_Sub64, mkU64(15), mkexpr(cappedMax)),
-+                     mkexpr(counter));
-+   else
-+      offset = mkexpr(counter);
-+
-+   store(binop(Iop_Add64, mkexpr(addr), mkexpr(counter)),
-+         binop(Iop_GetElem8x16, get_vr_qw(v1), unop(Iop_64to8, offset)));
- 
--   put_vr_qw(v1, binop(Iop_ShlV128,
--                       binop(Iop_ShrV128,
--                             load(Ity_V128,
--                                  binop(Iop_Sub64, mkexpr(addr), mkexpr(back))),
--                             unop(Iop_64to8, shrAmount)),
--                       unop(Iop_64to8, shlAmount)));
-+   /* Check for end of field */
-+   put_counter_dw0(binop(Iop_Add64, mkexpr(counter), mkU64(1)));
-+   iterate_if(binop(Iop_CmpNE64, mkexpr(counter), mkexpr(cappedMax)));
-+   put_counter_dw0(mkU64(0));
- }
- 
- /* Bitwise vCond ? v1 : v2
-@@ -3749,6 +3831,28 @@ s390_format_VRS_RRDVM(const HChar *(*irgen)(UChar r1, IRTemp op2addr, UChar v3,
-       s390_disasm(ENC5(MNM, GPR, UDXB, VR, UINT), mnm, r1, d2, 0, b2, v3, m4);
- }
- 
-+static void
-+s390_format_VRS_RRDV(const HChar *(*irgen)(UChar v1, UChar r3, IRTemp op2addr),
-+                     UChar v1, UChar r3, UChar b2, UShort d2, UChar rxb)
-+{
-+   const HChar *mnm;
-+   IRTemp op2addr = newTemp(Ity_I64);
-+
-+   if (! s390_host_has_vx) {
-+      emulation_failure(EmFail_S390X_vx);
-+      return;
-+   }
-+
-+   assign(op2addr, binop(Iop_Add64, mkU64(d2), b2 != 0 ? get_gpr_dw0(b2) :
-+          mkU64(0)));
-+
-+   v1  = s390_vr_getVRindex(v1, 4, rxb);
-+   mnm = irgen(v1, r3, op2addr);
-+
-+   if (UNLIKELY(vex_traceflags & VEX_TRACE_FE))
-+      s390_disasm(ENC4(MNM, VR, GPR, UDXB), mnm, v1, r3, d2, 0, b2);
-+}
-+
- 
- static void
- s390_format_VRS_VRDVM(const HChar *(*irgen)(UChar v1, IRTemp op2addr, UChar v3,
-@@ -4081,6 +4185,29 @@ s390_format_VRRa_VVVMMM(const HChar *(*irgen)(UChar v1, UChar v2, UChar v3,
-                   mnm, v1, v2, v3, m4, m5, m6);
- }
- 
-+static void
-+s390_format_VSI_URDV(const HChar *(*irgen)(UChar v1, IRTemp op2addr, UChar i3),
-+                     UChar v1, UChar b2, UChar d2, UChar i3, UChar rxb)
-+{
-+   const HChar *mnm;
-+   IRTemp op2addr = newTemp(Ity_I64);
-+
-+   if (!s390_host_has_vx) {
-+      emulation_failure(EmFail_S390X_vx);
-+      return;
-+   }
-+
-+   v1 = s390_vr_getVRindex(v1, 4, rxb);
-+
-+   assign(op2addr, binop(Iop_Add64, mkU64(d2), b2 != 0 ? get_gpr_dw0(b2) :
-+          mkU64(0)));
-+
-+   mnm = irgen(v1, op2addr, i3);
-+
-+   if (vex_traceflags & VEX_TRACE_FE)
-+      s390_disasm(ENC4(MNM, VR, UDXB, UINT), mnm, v1, d2, 0, b2, i3);
-+}
-+
- /*------------------------------------------------------------*/
- /*--- Build IR for opcodes                                 ---*/
- /*------------------------------------------------------------*/
-@@ -16186,7 +16313,9 @@ s390_irgen_VGM(UChar v1, UShort i2, UChar m3)
- static const HChar *
- s390_irgen_VLLEZ(UChar v1, IRTemp op2addr, UChar m3)
- {
--   IRType type = s390_vr_get_type(m3);
-+   s390_insn_assert("vllez", m3 <= 3 || m3 == 6);
-+
-+   IRType type = s390_vr_get_type(m3 & 3);
-    IRExpr* op2 = load(type, mkexpr(op2addr));
-    IRExpr* op2as64bit;
-    switch (type) {
-@@ -16206,7 +16335,13 @@ s390_irgen_VLLEZ(UChar v1, IRTemp op2addr, UChar m3)
-       vpanic("s390_irgen_VLLEZ: unknown type");
-    }
- 
--   put_vr_dw0(v1, op2as64bit);
-+   if (m3 == 6) {
-+      /* left-aligned */
-+      put_vr_dw0(v1, binop(Iop_Shl64, op2as64bit, mkU8(32)));
-+   } else {
-+      /* right-aligned */
-+      put_vr_dw0(v1, op2as64bit);
-+   }
-    put_vr_dw1(v1, mkU64(0));
-    return "vllez";
- }
-@@ -16615,7 +16750,7 @@ s390_irgen_VLBB(UChar v1, IRTemp addr, UChar m3)
-                             s390_getCountToBlockBoundary(addr, m3),
-                             mkU32(1));
- 
--   s390_vr_loadWithLength(v1, addr, maxIndex);
-+   s390_vr_loadWithLength(v1, addr, maxIndex, False);
- 
-    return "vlbb";
- }
-@@ -16623,41 +16758,50 @@ s390_irgen_VLBB(UChar v1, IRTemp addr, UChar m3)
- static const HChar *
- s390_irgen_VLL(UChar v1, IRTemp addr, UChar r3)
- {
--   s390_vr_loadWithLength(v1, addr, get_gpr_w1(r3));
-+   s390_vr_loadWithLength(v1, addr, get_gpr_w1(r3), False);
- 
-    return "vll";
- }
- 
- static const HChar *
--s390_irgen_VSTL(UChar v1, IRTemp addr, UChar r3)
-+s390_irgen_VLRL(UChar v1, IRTemp addr, UChar i3)
- {
--   IRTemp counter = newTemp(Ity_I64);
--   IRTemp maxIndexToStore = newTemp(Ity_I64);
--   IRTemp gpr3 = newTemp(Ity_I64);
--
--   assign(gpr3, unop(Iop_32Uto64, get_gpr_w1(r3)));
--   assign(maxIndexToStore, mkite(binop(Iop_CmpLE64U,
--                                       mkexpr(gpr3),
--                                       mkU64(16)
--                                       ),
--                                 mkexpr(gpr3),
--                                 mkU64(16)
--                                 )
--         );
-+   s390_insn_assert("vlrl", (i3 & 0xf0) == 0);
-+   s390_vr_loadWithLength(v1, addr, mkU32((UInt) i3), True);
- 
--   assign(counter, get_counter_dw0());
-+   return "vlrl";
-+}
- 
--   store(binop(Iop_Add64, mkexpr(addr), mkexpr(counter)),
--         binop(Iop_GetElem8x16, get_vr_qw(v1), unop(Iop_64to8, mkexpr(counter))));
-+static const HChar *
-+s390_irgen_VLRLR(UChar v1, UChar r3, IRTemp addr)
-+{
-+   s390_vr_loadWithLength(v1, addr, get_gpr_w1(r3), True);
- 
--   /* Check for end of field */
--   put_counter_dw0(binop(Iop_Add64, mkexpr(counter), mkU64(1)));
--   iterate_if(binop(Iop_CmpNE64, mkexpr(counter), mkexpr(maxIndexToStore)));
--   put_counter_dw0(mkU64(0));
-+   return "vlrlr";
-+}
- 
-+static const HChar *
-+s390_irgen_VSTL(UChar v1, IRTemp addr, UChar r3)
-+{
-+   s390_vr_storeWithLength(v1, addr, get_gpr_w1(r3), False);
-    return "vstl";
- }
- 
-+static const HChar *
-+s390_irgen_VSTRL(UChar v1, IRTemp addr, UChar i3)
-+{
-+   s390_insn_assert("vstrl", (i3 & 0xf0) == 0);
-+   s390_vr_storeWithLength(v1, addr, mkU32((UInt) i3), True);
-+   return "vstrl";
-+}
-+
-+static const HChar *
-+s390_irgen_VSTRLR(UChar v1, UChar r3, IRTemp addr)
-+{
-+   s390_vr_storeWithLength(v1, addr, get_gpr_w1(r3), True);
-+   return "vstrlr";
-+}
-+
- static const HChar *
- s390_irgen_VX(UChar v1, UChar v2, UChar v3)
- {
-@@ -16682,6 +16826,24 @@ s390_irgen_VO(UChar v1, UChar v2, UChar v3)
-    return "vo";
- }
- 
-+static const HChar *
-+s390_irgen_VOC(UChar v1, UChar v2, UChar v3)
-+{
-+   put_vr_qw(v1, binop(Iop_OrV128, get_vr_qw(v2),
-+                       unop(Iop_NotV128, get_vr_qw(v3))));
-+
-+   return "voc";
-+}
-+
-+static const HChar *
-+s390_irgen_VNN(UChar v1, UChar v2, UChar v3)
-+{
-+   put_vr_qw(v1, unop(Iop_NotV128,
-+                      binop(Iop_AndV128, get_vr_qw(v2), get_vr_qw(v3))));
-+
-+   return "vnn";
-+}
-+
- static const HChar *
- s390_irgen_VNO(UChar v1, UChar v2, UChar v3)
- {
-@@ -16691,6 +16853,15 @@ s390_irgen_VNO(UChar v1, UChar v2, UChar v3)
-    return "vno";
- }
- 
-+static const HChar *
-+s390_irgen_VNX(UChar v1, UChar v2, UChar v3)
-+{
-+   put_vr_qw(v1, unop(Iop_NotV128,
-+                      binop(Iop_XorV128, get_vr_qw(v2), get_vr_qw(v3))));
-+
-+   return "vnx";
-+}
-+
- static const HChar *
- s390_irgen_LZRF(UChar r1, IRTemp op2addr)
- {
-@@ -17499,9 +17670,19 @@ s390_irgen_VCTZ(UChar v1, UChar v2, UChar m3)
- static const HChar *
- s390_irgen_VPOPCT(UChar v1, UChar v2, UChar m3)
- {
--   vassert(m3 == 0);
-+   s390_insn_assert("vpopct", m3 <= 3);
-+
-+   IRExpr* cnt = unop(Iop_Cnt8x16, get_vr_qw(v2));
- 
--   put_vr_qw(v1, unop(Iop_Cnt8x16, get_vr_qw(v2)));
-+   if (m3 >= 1) {
-+      cnt = unop(Iop_PwAddL8Ux16, cnt);
-+      if (m3 >= 2) {
-+         cnt = unop(Iop_PwAddL16Ux8, cnt);
-+         if (m3 == 3)
-+            cnt = unop(Iop_PwAddL32Ux4, cnt);
-+      }
-+   }
-+   put_vr_qw(v1, cnt);
- 
-    return "vpopct";
- }
-@@ -18335,12 +18516,53 @@ s390_irgen_VMALH(UChar v1, UChar v2, UChar v3, UChar v4, UChar m5)
-    return "vmalh";
- }
- 
-+static const HChar *
-+s390_irgen_VMSL(UChar v1, UChar v2, UChar v3, UChar v4, UChar m5, UChar m6)
-+{
-+   s390_insn_assert("vmsl", m5 == 3 && (m6 & 3) == 0);
-+
-+   IRDirty* d;
-+   IRTemp cc = newTemp(Ity_I64);
-+
-+   s390x_vec_op_details_t details = { .serialized = 0ULL };
-+   details.op = S390_VEC_OP_VMSL;
-+   details.v1 = v1;
-+   details.v2 = v2;
-+   details.v3 = v3;
-+   details.v4 = v4;
-+   details.m4 = m5;
-+   details.m5 = m6;
-+
-+   d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_vec_op",
-+                         &s390x_dirtyhelper_vec_op,
-+                         mkIRExprVec_2(IRExpr_GSPTR(),
-+                                       mkU64(details.serialized)));
-+
-+   d->nFxState = 4;
-+   vex_bzero(&d->fxState, sizeof(d->fxState));
-+   d->fxState[0].fx     = Ifx_Read;
-+   d->fxState[0].offset = S390X_GUEST_OFFSET(guest_v0) + v2 * sizeof(V128);
-+   d->fxState[0].size   = sizeof(V128);
-+   d->fxState[1].fx     = Ifx_Read;
-+   d->fxState[1].offset = S390X_GUEST_OFFSET(guest_v0) + v3 * sizeof(V128);
-+   d->fxState[1].size   = sizeof(V128);
-+   d->fxState[2].fx     = Ifx_Read;
-+   d->fxState[2].offset = S390X_GUEST_OFFSET(guest_v0) + v4 * sizeof(V128);
-+   d->fxState[2].size   = sizeof(V128);
-+   d->fxState[3].fx     = Ifx_Write;
-+   d->fxState[3].offset = S390X_GUEST_OFFSET(guest_v0) + v1 * sizeof(V128);
-+   d->fxState[3].size   = sizeof(V128);
-+
-+   stmt(IRStmt_Dirty(d));
-+
-+   return "vmsl";
-+}
-+
- static void
--s390_vector_fp_convert(IROp op, IRType fromType, IRType toType,
-+s390_vector_fp_convert(IROp op, IRType fromType, IRType toType, Bool rounding,
-                        UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
- {
-    Bool isSingleElementOp = s390_vr_is_single_element_control_set(m4);
--   UChar maxIndex = isSingleElementOp ? 0 : 1;
- 
-    /* For Iop_F32toF64 we do this:
-       f32[0] -> f64[0]
-@@ -18353,14 +18575,21 @@ s390_vector_fp_convert(IROp op, IRType fromType, IRType toType,
-       The magic below with scaling factors is used to achieve the logic
-       described above.
-    */
--   const UChar sourceIndexScaleFactor = (op == Iop_F32toF64) ? 2 : 1;
--   const UChar destinationIndexScaleFactor = (op == Iop_F64toF32) ? 2 : 1;
--
--   const Bool isUnary = (op == Iop_F32toF64);
--   for (UChar i = 0; i <= maxIndex; i++) {
-+   Int size_diff = sizeofIRType(toType) - sizeofIRType(fromType);
-+   const UChar sourceIndexScaleFactor = size_diff > 0 ? 2 : 1;
-+   const UChar destinationIndexScaleFactor = size_diff < 0 ? 2 : 1;
-+   UChar n_elem = (isSingleElementOp ? 1 :
-+                   16 / (size_diff > 0 ?
-+                         sizeofIRType(toType) : sizeofIRType(fromType)));
-+
-+   for (UChar i = 0; i < n_elem; i++) {
-       IRExpr* argument = get_vr(v2, fromType, i * sourceIndexScaleFactor);
-       IRExpr* result;
--      if (!isUnary) {
-+      if (rounding) {
-+         if (!s390_host_has_fpext && m5 != S390_BFP_ROUND_PER_FPC) {
-+            emulation_warning(EmWarn_S390X_fpext_rounding);
-+            m5 = S390_BFP_ROUND_PER_FPC;
-+         }
-          result = binop(op,
-                         mkexpr(encode_bfp_rounding_mode(m5)),
-                         argument);
-@@ -18369,10 +18598,6 @@ s390_vector_fp_convert(IROp op, IRType fromType, IRType toType,
-       }
-       put_vr(v1, toType, i * destinationIndexScaleFactor, result);
-    }
--
--   if (isSingleElementOp) {
--      put_vr_dw1(v1, mkU64(0));
--   }
- }
- 
- static const HChar *
-@@ -18380,12 +18605,8 @@ s390_irgen_VCDG(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
- {
-    s390_insn_assert("vcdg", m3 == 3);
- 
--   if (!s390_host_has_fpext && m5 != S390_BFP_ROUND_PER_FPC) {
--      emulation_warning(EmWarn_S390X_fpext_rounding);
--      m5 = S390_BFP_ROUND_PER_FPC;
--   }
--
--   s390_vector_fp_convert(Iop_I64StoF64, Ity_I64, Ity_F64, v1, v2, m3, m4, m5);
-+   s390_vector_fp_convert(Iop_I64StoF64, Ity_I64, Ity_F64, True,
-+                          v1, v2, m3, m4, m5);
- 
-    return "vcdg";
- }
-@@ -18395,12 +18616,8 @@ s390_irgen_VCDLG(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
- {
-    s390_insn_assert("vcdlg", m3 == 3);
- 
--   if (!s390_host_has_fpext && m5 != S390_BFP_ROUND_PER_FPC) {
--      emulation_warning(EmWarn_S390X_fpext_rounding);
--      m5 = S390_BFP_ROUND_PER_FPC;
--   }
--
--   s390_vector_fp_convert(Iop_I64UtoF64, Ity_I64, Ity_F64, v1, v2, m3, m4, m5);
-+   s390_vector_fp_convert(Iop_I64UtoF64, Ity_I64, Ity_F64, True,
-+                          v1, v2, m3, m4, m5);
- 
-    return "vcdlg";
- }
-@@ -18410,12 +18627,8 @@ s390_irgen_VCGD(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
- {
-    s390_insn_assert("vcgd", m3 == 3);
- 
--   if (!s390_host_has_fpext && m5 != S390_BFP_ROUND_PER_FPC) {
--      emulation_warning(EmWarn_S390X_fpext_rounding);
--      m5 = S390_BFP_ROUND_PER_FPC;
--   }
--
--   s390_vector_fp_convert(Iop_F64toI64S, Ity_F64, Ity_I64, v1, v2, m3, m4, m5);
-+   s390_vector_fp_convert(Iop_F64toI64S, Ity_F64, Ity_I64, True,
-+                          v1, v2, m3, m4, m5);
- 
-    return "vcgd";
- }
-@@ -18425,12 +18638,8 @@ s390_irgen_VCLGD(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
- {
-    s390_insn_assert("vclgd", m3 == 3);
- 
--   if (!s390_host_has_fpext && m5 != S390_BFP_ROUND_PER_FPC) {
--      emulation_warning(EmWarn_S390X_fpext_rounding);
--      m5 = S390_BFP_ROUND_PER_FPC;
--   }
--
--   s390_vector_fp_convert(Iop_F64toI64U, Ity_F64, Ity_I64, v1, v2, m3, m4, m5);
-+   s390_vector_fp_convert(Iop_F64toI64U, Ity_F64, Ity_I64, True,
-+                          v1, v2, m3, m4, m5);
- 
-    return "vclgd";
- }
-@@ -18438,246 +18647,262 @@ s390_irgen_VCLGD(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
- static const HChar *
- s390_irgen_VFI(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
- {
--   s390_insn_assert("vfi", m3 == 3);
-+   s390_insn_assert("vfi",
-+                    (m3 == 3 || (s390_host_has_vxe && m3 >= 2 && m3 <= 4)));
- 
--   if (!s390_host_has_fpext && m5 != S390_BFP_ROUND_PER_FPC) {
--      emulation_warning(EmWarn_S390X_fpext_rounding);
--      m5 = S390_BFP_ROUND_PER_FPC;
-+   switch (m3) {
-+   case 2: s390_vector_fp_convert(Iop_RoundF32toInt, Ity_F32, Ity_F32, True,
-+                                  v1, v2, m3, m4, m5); break;
-+   case 3: s390_vector_fp_convert(Iop_RoundF64toInt, Ity_F64, Ity_F64, True,
-+                                  v1, v2, m3, m4, m5); break;
-+   case 4: s390_vector_fp_convert(Iop_RoundF128toInt, Ity_F128, Ity_F128, True,
-+                                  v1, v2, m3, m4, m5); break;
-    }
- 
--   s390_vector_fp_convert(Iop_RoundF64toInt, Ity_F64, Ity_F64,
--                          v1, v2, m3, m4, m5);
--
--   return "vcgld";
-+   return "vfi";
- }
- 
- static const HChar *
--s390_irgen_VLDE(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
-+s390_irgen_VFLL(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
- {
--   s390_insn_assert("vlde", m3 == 2);
-+   s390_insn_assert("vfll", m3 == 2 || (s390_host_has_vxe && m3 == 3));
- 
--   s390_vector_fp_convert(Iop_F32toF64, Ity_F32, Ity_F64, v1, v2, m3, m4, m5);
-+   if (m3 == 2)
-+      s390_vector_fp_convert(Iop_F32toF64, Ity_F32, Ity_F64, False,
-+                             v1, v2, m3, m4, m5);
-+   else
-+      s390_vector_fp_convert(Iop_F64toF128, Ity_F64, Ity_F128, False,
-+                             v1, v2, m3, m4, m5);
- 
--   return "vlde";
-+   return "vfll";
- }
- 
- static const HChar *
--s390_irgen_VLED(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
-+s390_irgen_VFLR(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
- {
--   s390_insn_assert("vled", m3 == 3);
--
--   if (!s390_host_has_fpext && m5 != S390_BFP_ROUND_PER_FPC) {
--      m5 = S390_BFP_ROUND_PER_FPC;
--   }
-+   s390_insn_assert("vflr", m3 == 3 || (s390_host_has_vxe && m3 == 2));
- 
--   s390_vector_fp_convert(Iop_F64toF32, Ity_F64, Ity_F32, v1, v2, m3, m4, m5);
-+   if (m3 == 3)
-+      s390_vector_fp_convert(Iop_F64toF32, Ity_F64, Ity_F32, True,
-+                             v1, v2, m3, m4, m5);
-+   else
-+      s390_vector_fp_convert(Iop_F128toF64, Ity_F128, Ity_F64, True,
-+                             v1, v2, m3, m4, m5);
- 
--   return "vled";
-+   return "vflr";
- }
- 
- static const HChar *
- s390_irgen_VFPSO(UChar v1, UChar v2, UChar m3, UChar m4, UChar m5)
- {
--   s390_insn_assert("vfpso", m3 == 3);
--
--   IRExpr* result;
--   switch (m5) {
--   case 0: {
--      /* Invert sign */
--      if (!s390_vr_is_single_element_control_set(m4)) {
--         result = unop(Iop_Neg64Fx2, get_vr_qw(v2));
--      }
--      else {
--         result = binop(Iop_64HLtoV128,
--                        unop(Iop_ReinterpF64asI64,
--                             unop(Iop_NegF64, get_vr(v2, Ity_F64, 0))),
--                        mkU64(0));
--      }
--      break;
--   }
-+   s390_insn_assert("vfpso", m5 <= 2 &&
-+                    (m3 == 3 || (s390_host_has_vxe && m3 >= 2 && m3 <= 4)));
- 
--   case 1: {
--      /* Set sign to negative */
--      IRExpr* highHalf = mkU64(0x8000000000000000ULL);
--      if (!s390_vr_is_single_element_control_set(m4)) {
--         IRExpr* lowHalf = highHalf;
--         IRExpr* mask = binop(Iop_64HLtoV128, highHalf, lowHalf);
--         result = binop(Iop_OrV128, get_vr_qw(v2), mask);
--      }
--      else {
--         result = binop(Iop_64HLtoV128,
--                        binop(Iop_Or64, get_vr_dw0(v2), highHalf),
--                        mkU64(0ULL));
--      }
-+   Bool single = s390_vr_is_single_element_control_set(m4) || m3 == 4;
-+   IRType type = single ? s390_vr_get_ftype(m3) : Ity_V128;
-+   int idx = 2 * (m3 - 2) + (single ? 0 : 1);
- 
--      break;
--   }
--
--   case 2: {
--      /* Set sign to positive */
--      if (!s390_vr_is_single_element_control_set(m4)) {
--         result = unop(Iop_Abs64Fx2, get_vr_qw(v2));
--      }
--      else {
--         result = binop(Iop_64HLtoV128,
--                        unop(Iop_ReinterpF64asI64,
--                             unop(Iop_AbsF64, get_vr(v2, Ity_F64, 0))),
--                        mkU64(0));
--      }
--
--      break;
--   }
--
--   default:
--      vpanic("s390_irgen_VFPSO: Invalid m5 value");
--   }
-+   static const IROp negate_ops[] = {
-+      Iop_NegF32, Iop_Neg32Fx4,
-+      Iop_NegF64, Iop_Neg64Fx2,
-+      Iop_NegF128
-+   };
-+   static const IROp abs_ops[] = {
-+      Iop_AbsF32, Iop_Abs32Fx4,
-+      Iop_AbsF64, Iop_Abs64Fx2,
-+      Iop_AbsF128
-+   };
- 
--   put_vr_qw(v1, result);
--   if (s390_vr_is_single_element_control_set(m4)) {
--      put_vr_dw1(v1, mkU64(0ULL));
-+   if (m5 == 1) {
-+      /* Set sign to negative */
-+      put_vr(v1, type, 0,
-+             unop(negate_ops[idx],
-+                  unop(abs_ops[idx], get_vr(v2, type, 0))));
-+   } else {
-+      /* m5 == 0: invert sign; m5 == 2: set sign to positive */
-+      const IROp *ops = m5 == 2 ? abs_ops : negate_ops;
-+      put_vr(v1, type, 0, unop(ops[idx], get_vr(v2, type, 0)));
-    }
- 
-    return "vfpso";
- }
- 
--static void s390x_vec_fp_binary_op(IROp generalOp, IROp singleElementOp,
--                                   UChar v1, UChar v2, UChar v3, UChar m4,
--                                   UChar m5)
-+static const HChar *
-+s390x_vec_fp_binary_op(const HChar* mnm, const IROp ops[],
-+                       UChar v1, UChar v2, UChar v3,
-+                       UChar m4, UChar m5)
- {
--   IRExpr* result;
--   if (!s390_vr_is_single_element_control_set(m5)) {
--      result = triop(generalOp, get_bfp_rounding_mode_from_fpc(),
--                     get_vr_qw(v2), get_vr_qw(v3));
-+   s390_insn_assert(mnm, (m5 & 7) == 0 &&
-+                    (m4 == 3 || (s390_host_has_vxe && m4 >= 2 && m4 <= 4)));
-+
-+   int idx = 2 * (m4 - 2);
-+
-+   if (m4 == 4 || s390_vr_is_single_element_control_set(m5)) {
-+      IRType type = s390_vr_get_ftype(m4);
-+      put_vr(v1, type, 0,
-+             triop(ops[idx], get_bfp_rounding_mode_from_fpc(),
-+                   get_vr(v2, type, 0), get_vr(v3, type, 0)));
-    } else {
--      IRExpr* highHalf = triop(singleElementOp,
--                               get_bfp_rounding_mode_from_fpc(),
--                               get_vr(v2, Ity_F64, 0),
--                               get_vr(v3, Ity_F64, 0));
--      result = binop(Iop_64HLtoV128, unop(Iop_ReinterpF64asI64, highHalf),
--                     mkU64(0ULL));
-+      put_vr_qw(v1, triop(ops[idx + 1], get_bfp_rounding_mode_from_fpc(),
-+                          get_vr_qw(v2), get_vr_qw(v3)));
-    }
- 
--   put_vr_qw(v1, result);
-+   return mnm;
- }
- 
--static void s390x_vec_fp_unary_op(IROp generalOp, IROp singleElementOp,
--                                  UChar v1, UChar v2, UChar m3, UChar m4)
-+static const HChar *
-+s390x_vec_fp_unary_op(const HChar* mnm, const IROp ops[],
-+                      UChar v1, UChar v2, UChar m3, UChar m4)
- {
--   IRExpr* result;
--   if (!s390_vr_is_single_element_control_set(m4)) {
--      result = binop(generalOp, get_bfp_rounding_mode_from_fpc(),
--                     get_vr_qw(v2));
-+   s390_insn_assert(mnm, (m4 & 7) == 0 &&
-+                    (m3 == 3 || (s390_host_has_vxe && m3 >= 2 && m3 <= 4)));
-+
-+   int idx = 2 * (m3 - 2);
-+
-+   if (m3 == 4 || s390_vr_is_single_element_control_set(m4)) {
-+      IRType type = s390_vr_get_ftype(m3);
-+      put_vr(v1, type, 0,
-+             binop(ops[idx], get_bfp_rounding_mode_from_fpc(),
-+                   get_vr(v2, type, 0)));
-    }
-    else {
--      IRExpr* highHalf = binop(singleElementOp,
--                               get_bfp_rounding_mode_from_fpc(),
--                               get_vr(v2, Ity_F64, 0));
--      result = binop(Iop_64HLtoV128, unop(Iop_ReinterpF64asI64, highHalf),
--                     mkU64(0ULL));
-+      put_vr_qw(v1, binop(ops[idx + 1], get_bfp_rounding_mode_from_fpc(),
-+                          get_vr_qw(v2)));
-    }
- 
--   put_vr_qw(v1, result);
-+   return mnm;
- }
- 
- 
--static void
--s390_vector_fp_mulAddOrSub(IROp singleElementOp,
--                           UChar v1, UChar v2, UChar v3, UChar v4,
--                           UChar m5, UChar m6)
-+static const HChar *
-+s390_vector_fp_mulAddOrSub(UChar v1, UChar v2, UChar v3, UChar v4,
-+                           UChar m5, UChar m6,
-+                           const HChar* mnm, const IROp single_ops[],
-+                           Bool negate)
- {
--   Bool isSingleElementOp = s390_vr_is_single_element_control_set(m5);
-+   s390_insn_assert(mnm, m6 == 3 || (s390_host_has_vxe && m6 >= 2 && m6 <= 4));
-+
-+   static const IROp negate_ops[] = { Iop_NegF32, Iop_NegF64, Iop_NegF128 };
-+   IRType type = s390_vr_get_ftype(m6);
-+   Bool single = s390_vr_is_single_element_control_set(m5) || m6 == 4;
-+   UChar n_elem = single ? 1 : s390_vr_get_n_elem(m6);
-    IRTemp irrm_temp = newTemp(Ity_I32);
-    assign(irrm_temp, get_bfp_rounding_mode_from_fpc());
-    IRExpr* irrm = mkexpr(irrm_temp);
--   IRExpr* result;
--   IRExpr* highHalf = qop(singleElementOp,
--                          irrm,
--                          get_vr(v2, Ity_F64, 0),
--                          get_vr(v3, Ity_F64, 0),
--                          get_vr(v4, Ity_F64, 0));
--
--   if (isSingleElementOp) {
--      result = binop(Iop_64HLtoV128, unop(Iop_ReinterpF64asI64, highHalf),
--                     mkU64(0ULL));
--   } else {
--      IRExpr* lowHalf = qop(singleElementOp,
--                            irrm,
--                            get_vr(v2, Ity_F64, 1),
--                            get_vr(v3, Ity_F64, 1),
--                            get_vr(v4, Ity_F64, 1));
--      result = binop(Iop_64HLtoV128, unop(Iop_ReinterpF64asI64, highHalf),
--                     unop(Iop_ReinterpF64asI64, lowHalf));
--   }
- 
--   put_vr_qw(v1, result);
-+   for (UChar idx = 0; idx < n_elem; idx++) {
-+      IRExpr* result = qop(single_ops[m6 - 2],
-+                           irrm,
-+                           get_vr(v2, type, idx),
-+                           get_vr(v3, type, idx),
-+                           get_vr(v4, type, idx));
-+      put_vr(v1, type, idx, negate ? unop(negate_ops[m6 - 2], result) : result);
-+   }
-+   return mnm;
- }
- 
- static const HChar *
- s390_irgen_VFA(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
- {
--   s390_insn_assert("vfa", m4 == 3);
--   s390x_vec_fp_binary_op(Iop_Add64Fx2, Iop_AddF64, v1, v2, v3, m4, m5);
--   return "vfa";
-+   static const IROp vfa_ops[] = {
-+      Iop_AddF32, Iop_Add32Fx4,
-+      Iop_AddF64, Iop_Add64Fx2,
-+      Iop_AddF128,
-+   };
-+   return s390x_vec_fp_binary_op("vfa", vfa_ops, v1, v2, v3, m4, m5);
- }
- 
- static const HChar *
- s390_irgen_VFS(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
- {
--   s390_insn_assert("vfs", m4 == 3);
--   s390x_vec_fp_binary_op(Iop_Sub64Fx2, Iop_SubF64, v1, v2, v3, m4, m5);
--   return "vfs";
-+   static const IROp vfs_ops[] = {
-+      Iop_SubF32, Iop_Sub32Fx4,
-+      Iop_SubF64, Iop_Sub64Fx2,
-+      Iop_SubF128,
-+   };
-+   return s390x_vec_fp_binary_op("vfs", vfs_ops, v1, v2, v3, m4, m5);
- }
- 
- static const HChar *
- s390_irgen_VFM(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
- {
--   s390_insn_assert("vfm", m4 == 3);
--   s390x_vec_fp_binary_op(Iop_Mul64Fx2, Iop_MulF64, v1, v2, v3, m4, m5);
--   return "vfm";
-+   static const IROp vfm_ops[] = {
-+      Iop_MulF32, Iop_Mul32Fx4,
-+      Iop_MulF64, Iop_Mul64Fx2,
-+      Iop_MulF128,
-+   };
-+   return s390x_vec_fp_binary_op("vfm", vfm_ops, v1, v2, v3, m4, m5);
- }
- 
- static const HChar *
- s390_irgen_VFD(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5)
- {
--   s390_insn_assert("vfd", m4 == 3);
--   s390x_vec_fp_binary_op(Iop_Div64Fx2, Iop_DivF64, v1, v2, v3, m4, m5);
--   return "vfd";
-+   static const IROp vfd_ops[] = {
-+      Iop_DivF32, Iop_Div32Fx4,
-+      Iop_DivF64, Iop_Div64Fx2,
-+      Iop_DivF128,
-+   };
-+   return s390x_vec_fp_binary_op("vfd", vfd_ops, v1, v2, v3, m4, m5);
- }
- 
- static const HChar *
- s390_irgen_VFSQ(UChar v1, UChar v2, UChar m3, UChar m4)
- {
--   s390_insn_assert("vfsq", m3 == 3);
--   s390x_vec_fp_unary_op(Iop_Sqrt64Fx2, Iop_SqrtF64, v1, v2, m3, m4);
--
--   return "vfsq";
-+   static const IROp vfsq_ops[] = {
-+      Iop_SqrtF32, Iop_Sqrt32Fx4,
-+      Iop_SqrtF64, Iop_Sqrt64Fx2,
-+      Iop_SqrtF128
-+   };
-+   return s390x_vec_fp_unary_op("vfsq", vfsq_ops, v1, v2, m3, m4);
- }
- 
-+static const IROp FMA_single_ops[] = {
-+   Iop_MAddF32, Iop_MAddF64, Iop_MAddF128
-+};
-+
- static const HChar *
- s390_irgen_VFMA(UChar v1, UChar v2, UChar v3, UChar v4, UChar m5, UChar m6)
- {
--   s390_insn_assert("vfma", m6 == 3);
--   s390_vector_fp_mulAddOrSub(Iop_MAddF64, v1, v2, v3, v4, m5, m6);
--   return "vfma";
-+   return s390_vector_fp_mulAddOrSub(v1, v2, v3, v4, m5, m6,
-+                                     "vfma", FMA_single_ops, False);
- }
- 
-+static const HChar *
-+s390_irgen_VFNMA(UChar v1, UChar v2, UChar v3, UChar v4, UChar m5, UChar m6)
-+{
-+   return s390_vector_fp_mulAddOrSub(v1, v2, v3, v4, m5, m6,
-+                                     "vfnma", FMA_single_ops, True);
-+}
-+
-+static const IROp FMS_single_ops[] = {
-+   Iop_MSubF32, Iop_MSubF64, Iop_MSubF128
-+};
-+
- static const HChar *
- s390_irgen_VFMS(UChar v1, UChar v2, UChar v3, UChar v4, UChar m5, UChar m6)
- {
--   s390_insn_assert("vfms", m6 == 3);
--   s390_vector_fp_mulAddOrSub(Iop_MSubF64, v1, v2, v3, v4, m5, m6);
--   return "vfms";
-+   return s390_vector_fp_mulAddOrSub(v1, v2, v3, v4, m5, m6,
-+                                     "vfms", FMS_single_ops, False);
-+}
-+
-+static const HChar *
-+s390_irgen_VFNMS(UChar v1, UChar v2, UChar v3, UChar v4, UChar m5, UChar m6)
-+{
-+   return s390_vector_fp_mulAddOrSub(v1, v2, v3, v4, m5, m6,
-+                                     "vfnms", FMS_single_ops, True);
- }
- 
- static const HChar *
- s390_irgen_WFC(UChar v1, UChar v2, UChar m3, UChar m4)
- {
--   s390_insn_assert("wfc", m3 == 3);
--   s390_insn_assert("wfc", m4 == 0);
-+   s390_insn_assert("wfc", m4 == 0 &&
-+                    (m3 == 3 || (s390_host_has_vxe && m3 >= 2 && m3 <= 4)));
-+
-+   static const IROp ops[] = { Iop_CmpF32, Iop_CmpF64, Iop_CmpF128 };
-+   IRType type = s390_vr_get_ftype(m3);
- 
-    IRTemp cc_vex = newTemp(Ity_I32);
--   assign(cc_vex, binop(Iop_CmpF64,
--                        get_vr(v1, Ity_F64, 0), get_vr(v2, Ity_F64, 0)));
-+   assign(cc_vex, binop(ops[m3 - 2], get_vr(v1, type, 0), get_vr(v2, type, 0)));
- 
-    IRTemp cc_s390 = newTemp(Ity_I32);
-    assign(cc_s390, convert_vex_bfpcc_to_s390(cc_vex));
-@@ -18695,213 +18920,253 @@ s390_irgen_WFK(UChar v1, UChar v2, UChar m3, UChar m4)
- }
- 
- static const HChar *
--s390_irgen_VFCE(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5, UChar m6)
-+s390_irgen_VFCx(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5, UChar m6,
-+                const HChar *mnem, IRCmpFResult cmp, Bool equal_ok,
-+                IROp cmp32, IROp cmp64)
- {
--   s390_insn_assert("vfce", m4 == 3);
-+   s390_insn_assert(mnem, (m5 & 3) == 0 && (m6 & 14) == 0 &&
-+                    (m4 == 3 || (s390_host_has_vxe && m4 >= 2 && m4 <= 4)));
- 
--   Bool isSingleElementOp = s390_vr_is_single_element_control_set(m5);
--   if (!s390_vr_is_cs_set(m6)) {
--      if (!isSingleElementOp) {
--         put_vr_qw(v1, binop(Iop_CmpEQ64Fx2, get_vr_qw(v2), get_vr_qw(v3)));
-+   Bool single = s390_vr_is_single_element_control_set(m5) || m4 == 4;
-+
-+   if (single) {
-+      static const IROp ops[] = { Iop_CmpF32, Iop_CmpF64, Iop_CmpF128 };
-+      IRType type = s390_vr_get_ftype(m4);
-+      IRTemp result = newTemp(Ity_I32);
-+      IRTemp cond = newTemp(Ity_I1);
-+
-+      assign(result, binop(ops[m4 - 2],
-+                           get_vr(v2, type, 0), get_vr(v3, type, 0)));
-+      if (equal_ok) {
-+         assign(cond,
-+                binop(Iop_Or1,
-+                      binop(Iop_CmpEQ32, mkexpr(result), mkU32(cmp)),
-+                      binop(Iop_CmpEQ32, mkexpr(result), mkU32(Ircr_EQ))));
-       } else {
--         IRExpr* comparisonResult = binop(Iop_CmpF64, get_vr(v2, Ity_F64, 0),
--                                          get_vr(v3, Ity_F64, 0));
--         IRExpr* result = mkite(binop(Iop_CmpEQ32, comparisonResult,
--                                      mkU32(Ircr_EQ)),
--                                mkU64(0xffffffffffffffffULL),
--                                mkU64(0ULL));
--         put_vr_qw(v1, binop(Iop_64HLtoV128, result, mkU64(0ULL)));
-+         assign(cond, binop(Iop_CmpEQ32, mkexpr(result), mkU32(cmp)));
-+      }
-+      put_vr_qw(v1, mkite(mkexpr(cond),
-+                          IRExpr_Const(IRConst_V128(0xffff)),
-+                          IRExpr_Const(IRConst_V128(0))));
-+      if (s390_vr_is_cs_set(m6)) {
-+         IRTemp cc = newTemp(Ity_I64);
-+         assign(cc, mkite(mkexpr(cond), mkU64(0), mkU64(3)));
-+         s390_cc_set(cc);
-       }
-    } else {
--      IRDirty* d;
--      IRTemp cc = newTemp(Ity_I64);
--
--      s390x_vec_op_details_t details = { .serialized = 0ULL };
--      details.op = S390_VEC_OP_VFCE;
--      details.v1 = v1;
--      details.v2 = v2;
--      details.v3 = v3;
--      details.m4 = m4;
--      details.m5 = m5;
--      details.m6 = m6;
-+      IRTemp result = newTemp(Ity_V128);
-+
-+      assign(result, binop(m4 == 2 ? cmp32 : cmp64,
-+                           get_vr_qw(v2), get_vr_qw(v3)));
-+      put_vr_qw(v1, mkexpr(result));
-+      if (s390_vr_is_cs_set(m6)) {
-+         IRTemp cc = newTemp(Ity_I64);
-+         assign(cc,
-+                mkite(binop(Iop_CmpEQ64,
-+                            binop(Iop_And64,
-+                                  unop(Iop_V128to64, mkexpr(result)),
-+                                  unop(Iop_V128HIto64, mkexpr(result))),
-+                            mkU64(-1ULL)),
-+                      mkU64(0), /* all comparison results are true */
-+                      mkite(binop(Iop_CmpEQ64,
-+                                  binop(Iop_Or64,
-+                                        unop(Iop_V128to64, mkexpr(result)),
-+                                        unop(Iop_V128HIto64, mkexpr(result))),
-+                                  mkU64(0)),
-+                            mkU64(3), /* all false */
-+                            mkU64(1)))); /* mixed true/false */
-+         s390_cc_set(cc);
-+      }
-+   }
- 
--      d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_vec_op",
--                            &s390x_dirtyhelper_vec_op,
--                            mkIRExprVec_2(IRExpr_GSPTR(),
--                                          mkU64(details.serialized)));
-+   return mnem;
-+}
- 
--      const UChar elementSize = isSingleElementOp ? sizeof(ULong) : sizeof(V128);
--      d->nFxState = 3;
--      vex_bzero(&d->fxState, sizeof(d->fxState));
--      d->fxState[0].fx = Ifx_Read;
--      d->fxState[0].offset = S390X_GUEST_OFFSET(guest_v0) + v2 * sizeof(V128);
--      d->fxState[0].size = elementSize;
--      d->fxState[1].fx = Ifx_Read;
--      d->fxState[1].offset = S390X_GUEST_OFFSET(guest_v0) + v3 * sizeof(V128);
--      d->fxState[1].size = elementSize;
--      d->fxState[2].fx = Ifx_Write;
--      d->fxState[2].offset = S390X_GUEST_OFFSET(guest_v0) + v1 * sizeof(V128);
--      d->fxState[2].size = sizeof(V128);
-+static const HChar *
-+s390_irgen_VFCE(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5, UChar m6)
-+{
-+   return s390_irgen_VFCx(v1, v2, v3, m4, m5, m6, "vfce", Ircr_EQ,
-+                          False, Iop_CmpEQ32Fx4, Iop_CmpEQ64Fx2);
-+}
- 
--      stmt(IRStmt_Dirty(d));
--      s390_cc_set(cc);
--   }
-+static const HChar *
-+s390_irgen_VFCH(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5, UChar m6)
-+{
-+   /* Swap arguments and compare "low" instead. */
-+   return s390_irgen_VFCx(v1, v3, v2, m4, m5, m6, "vfch", Ircr_LT,
-+                          False, Iop_CmpLT32Fx4, Iop_CmpLT64Fx2);
-+}
- 
--   return "vfce";
-+static const HChar *
-+s390_irgen_VFCHE(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5, UChar m6)
-+{
-+   /* Swap arguments and compare "low or equal" instead. */
-+   return s390_irgen_VFCx(v1, v3, v2, m4, m5, m6, "vfche", Ircr_LT,
-+                          True, Iop_CmpLE32Fx4, Iop_CmpLE64Fx2);
- }
- 
- static const HChar *
--s390_irgen_VFCH(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5, UChar m6)
-+s390_irgen_VFTCI(UChar v1, UChar v2, UShort i3, UChar m4, UChar m5)
- {
--   vassert(m4 == 3);
-+   s390_insn_assert("vftci",
-+                    (m4 == 3 || (s390_host_has_vxe && m4 >= 2 && m4 <= 4)));
- 
-    Bool isSingleElementOp = s390_vr_is_single_element_control_set(m5);
--   if (!s390_vr_is_cs_set(m6)) {
--      if (!isSingleElementOp) {
--         put_vr_qw(v1, binop(Iop_CmpLE64Fx2, get_vr_qw(v3), get_vr_qw(v2)));
--      } else {
--         IRExpr* comparisonResult = binop(Iop_CmpF64, get_vr(v2, Ity_F64, 0),
--                                          get_vr(v3, Ity_F64, 0));
--         IRExpr* result = mkite(binop(Iop_CmpEQ32, comparisonResult,
--                                      mkU32(Ircr_GT)),
--                                mkU64(0xffffffffffffffffULL),
--                                mkU64(0ULL));
--         put_vr_qw(v1, binop(Iop_64HLtoV128, result, mkU64(0ULL)));
--      }
--   }
--   else {
--      IRDirty* d;
--      IRTemp cc = newTemp(Ity_I64);
- 
--      s390x_vec_op_details_t details = { .serialized = 0ULL };
--      details.op = S390_VEC_OP_VFCH;
--      details.v1 = v1;
--      details.v2 = v2;
--      details.v3 = v3;
--      details.m4 = m4;
--      details.m5 = m5;
--      details.m6 = m6;
-+   IRDirty* d;
-+   IRTemp cc = newTemp(Ity_I64);
- 
--      d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_vec_op",
--                            &s390x_dirtyhelper_vec_op,
--                            mkIRExprVec_2(IRExpr_GSPTR(),
--                                          mkU64(details.serialized)));
-+   s390x_vec_op_details_t details = { .serialized = 0ULL };
-+   details.op = S390_VEC_OP_VFTCI;
-+   details.v1 = v1;
-+   details.v2 = v2;
-+   details.i3 = i3;
-+   details.m4 = m4;
-+   details.m5 = m5;
- 
--      const UChar elementSize = isSingleElementOp ? sizeof(ULong) : sizeof(V128);
--      d->nFxState = 3;
--      vex_bzero(&d->fxState, sizeof(d->fxState));
--      d->fxState[0].fx = Ifx_Read;
--      d->fxState[0].offset = S390X_GUEST_OFFSET(guest_v0) + v2 * sizeof(V128);
--      d->fxState[0].size = elementSize;
--      d->fxState[1].fx = Ifx_Read;
--      d->fxState[1].offset = S390X_GUEST_OFFSET(guest_v0) + v3 * sizeof(V128);
--      d->fxState[1].size = elementSize;
--      d->fxState[2].fx = Ifx_Write;
--      d->fxState[2].offset = S390X_GUEST_OFFSET(guest_v0) + v1 * sizeof(V128);
--      d->fxState[2].size = sizeof(V128);
-+   d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_vec_op",
-+                         &s390x_dirtyhelper_vec_op,
-+                         mkIRExprVec_2(IRExpr_GSPTR(),
-+                                       mkU64(details.serialized)));
- 
--      stmt(IRStmt_Dirty(d));
--      s390_cc_set(cc);
--   }
-+   const UChar elementSize = isSingleElementOp ?
-+      sizeofIRType(s390_vr_get_ftype(m4)) : sizeof(V128);
-+   d->nFxState = 2;
-+   vex_bzero(&d->fxState, sizeof(d->fxState));
-+   d->fxState[0].fx = Ifx_Read;
-+   d->fxState[0].offset = S390X_GUEST_OFFSET(guest_v0) + v2 * sizeof(V128);
-+   d->fxState[0].size = elementSize;
-+   d->fxState[1].fx = Ifx_Write;
-+   d->fxState[1].offset = S390X_GUEST_OFFSET(guest_v0) + v1 * sizeof(V128);
-+   d->fxState[1].size = sizeof(V128);
-+
-+   stmt(IRStmt_Dirty(d));
-+   s390_cc_set(cc);
- 
--   return "vfch";
-+   return "vftci";
- }
- 
- static const HChar *
--s390_irgen_VFCHE(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5, UChar m6)
-+s390_irgen_VFMIN(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5, UChar m6)
- {
--   s390_insn_assert("vfche", m4 == 3);
-+   s390_insn_assert("vfmin",
-+                    (m4 == 3 || (s390_host_has_vxe && m4 >= 2 && m4 <= 4)));
- 
-    Bool isSingleElementOp = s390_vr_is_single_element_control_set(m5);
--   if (!s390_vr_is_cs_set(m6)) {
--      if (!isSingleElementOp) {
--         put_vr_qw(v1, binop(Iop_CmpLT64Fx2, get_vr_qw(v3), get_vr_qw(v2)));
--      }
--      else {
--         IRExpr* comparisonResult = binop(Iop_CmpF64, get_vr(v3, Ity_F64, 0),
--                                          get_vr(v2, Ity_F64, 0));
--         IRExpr* result = mkite(binop(Iop_CmpEQ32, comparisonResult,
--                                      mkU32(Ircr_LT)),
--                                mkU64(0xffffffffffffffffULL),
--                                mkU64(0ULL));
--         put_vr_qw(v1, binop(Iop_64HLtoV128, result, mkU64(0ULL)));
--      }
--   }
--   else {
--      IRDirty* d;
--      IRTemp cc = newTemp(Ity_I64);
--
--      s390x_vec_op_details_t details = { .serialized = 0ULL };
--      details.op = S390_VEC_OP_VFCHE;
--      details.v1 = v1;
--      details.v2 = v2;
--      details.v3 = v3;
--      details.m4 = m4;
--      details.m5 = m5;
--      details.m6 = m6;
-+   IRDirty* d;
-+   IRTemp cc = newTemp(Ity_I64);
- 
--      d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_vec_op",
--                            &s390x_dirtyhelper_vec_op,
--                            mkIRExprVec_2(IRExpr_GSPTR(),
--                                          mkU64(details.serialized)));
-+   s390x_vec_op_details_t details = { .serialized = 0ULL };
-+   details.op = S390_VEC_OP_VFMIN;
-+   details.v1 = v1;
-+   details.v2 = v2;
-+   details.v3 = v3;
-+   details.m4 = m4;
-+   details.m5 = m5;
-+   details.m6 = m6;
- 
--      const UChar elementSize = isSingleElementOp ? sizeof(ULong) : sizeof(V128);
--      d->nFxState = 3;
--      vex_bzero(&d->fxState, sizeof(d->fxState));
--      d->fxState[0].fx = Ifx_Read;
--      d->fxState[0].offset = S390X_GUEST_OFFSET(guest_v0) + v2 * sizeof(V128);
--      d->fxState[0].size = elementSize;
--      d->fxState[1].fx = Ifx_Read;
--      d->fxState[1].offset = S390X_GUEST_OFFSET(guest_v0) + v3 * sizeof(V128);
--      d->fxState[1].size = elementSize;
--      d->fxState[2].fx = Ifx_Write;
--      d->fxState[2].offset = S390X_GUEST_OFFSET(guest_v0) + v1 * sizeof(V128);
--      d->fxState[2].size = sizeof(V128);
-+   d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_vec_op",
-+                         &s390x_dirtyhelper_vec_op,
-+                         mkIRExprVec_2(IRExpr_GSPTR(),
-+                                       mkU64(details.serialized)));
- 
--      stmt(IRStmt_Dirty(d));
--      s390_cc_set(cc);
--   }
-+   const UChar elementSize = isSingleElementOp ?
-+      sizeofIRType(s390_vr_get_ftype(m4)) : sizeof(V128);
-+   d->nFxState = 3;
-+   vex_bzero(&d->fxState, sizeof(d->fxState));
-+   d->fxState[0].fx = Ifx_Read;
-+   d->fxState[0].offset = S390X_GUEST_OFFSET(guest_v0) + v2 * sizeof(V128);
-+   d->fxState[0].size = elementSize;
-+   d->fxState[1].fx = Ifx_Read;
-+   d->fxState[1].offset = S390X_GUEST_OFFSET(guest_v0) + v3 * sizeof(V128);
-+   d->fxState[1].size = elementSize;
-+   d->fxState[2].fx = Ifx_Write;
-+   d->fxState[2].offset = S390X_GUEST_OFFSET(guest_v0) + v1 * sizeof(V128);
-+   d->fxState[2].size = sizeof(V128);
- 
--   return "vfche";
-+   stmt(IRStmt_Dirty(d));
-+   s390_cc_set(cc);
-+   return "vfmin";
- }
- 
- static const HChar *
--s390_irgen_VFTCI(UChar v1, UChar v2, UShort i3, UChar m4, UChar m5)
-+s390_irgen_VFMAX(UChar v1, UChar v2, UChar v3, UChar m4, UChar m5, UChar m6)
- {
--   s390_insn_assert("vftci", m4 == 3);
-+   s390_insn_assert("vfmax",
-+                    (m4 == 3 || (s390_host_has_vxe && m4 >= 2 && m4 <= 4)));
- 
-    Bool isSingleElementOp = s390_vr_is_single_element_control_set(m5);
--
-    IRDirty* d;
-    IRTemp cc = newTemp(Ity_I64);
- 
-    s390x_vec_op_details_t details = { .serialized = 0ULL };
--   details.op = S390_VEC_OP_VFTCI;
-+   details.op = S390_VEC_OP_VFMAX;
-    details.v1 = v1;
-    details.v2 = v2;
--   details.i3 = i3;
-+   details.v3 = v3;
-    details.m4 = m4;
-    details.m5 = m5;
-+   details.m6 = m6;
- 
-    d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_vec_op",
-                          &s390x_dirtyhelper_vec_op,
-                          mkIRExprVec_2(IRExpr_GSPTR(),
-                                        mkU64(details.serialized)));
- 
--   const UChar elementSize = isSingleElementOp ? sizeof(ULong) : sizeof(V128);
--   d->nFxState = 2;
-+   const UChar elementSize = isSingleElementOp ?
-+      sizeofIRType(s390_vr_get_ftype(m4)) : sizeof(V128);
-+   d->nFxState = 3;
-    vex_bzero(&d->fxState, sizeof(d->fxState));
-    d->fxState[0].fx = Ifx_Read;
-    d->fxState[0].offset = S390X_GUEST_OFFSET(guest_v0) + v2 * sizeof(V128);
-    d->fxState[0].size = elementSize;
--   d->fxState[1].fx = Ifx_Write;
--   d->fxState[1].offset = S390X_GUEST_OFFSET(guest_v0) + v1 * sizeof(V128);
--   d->fxState[1].size = sizeof(V128);
-+   d->fxState[1].fx = Ifx_Read;
-+   d->fxState[1].offset = S390X_GUEST_OFFSET(guest_v0) + v3 * sizeof(V128);
-+   d->fxState[1].size = elementSize;
-+   d->fxState[2].fx = Ifx_Write;
-+   d->fxState[2].offset = S390X_GUEST_OFFSET(guest_v0) + v1 * sizeof(V128);
-+   d->fxState[2].size = sizeof(V128);
- 
-    stmt(IRStmt_Dirty(d));
-    s390_cc_set(cc);
-+   return "vfmax";
-+}
- 
--   return "vftci";
-+static const HChar *
-+s390_irgen_VBPERM(UChar v1, UChar v2, UChar v3)
-+{
-+   IRDirty* d;
-+   IRTemp cc = newTemp(Ity_I64);
-+
-+   s390x_vec_op_details_t details = { .serialized = 0ULL };
-+   details.op = S390_VEC_OP_VBPERM;
-+   details.v1 = v1;
-+   details.v2 = v2;
-+   details.v3 = v3;
-+   details.m4 = 0;
-+   details.m5 = 0;
-+   details.m6 = 0;
-+
-+   d = unsafeIRDirty_1_N(cc, 0, "s390x_dirtyhelper_vec_op",
-+                         &s390x_dirtyhelper_vec_op,
-+                         mkIRExprVec_2(IRExpr_GSPTR(),
-+                                       mkU64(details.serialized)));
-+
-+   d->nFxState = 3;
-+   vex_bzero(&d->fxState, sizeof(d->fxState));
-+   d->fxState[0].fx = Ifx_Read;
-+   d->fxState[0].offset = S390X_GUEST_OFFSET(guest_v0) + v2 * sizeof(V128);
-+   d->fxState[0].size = sizeof(V128);
-+   d->fxState[1].fx = Ifx_Read;
-+   d->fxState[1].offset = S390X_GUEST_OFFSET(guest_v0) + v3 * sizeof(V128);
-+   d->fxState[1].size = sizeof(V128);
-+   d->fxState[2].fx = Ifx_Write;
-+   d->fxState[2].offset = S390X_GUEST_OFFSET(guest_v0) + v1 * sizeof(V128);
-+   d->fxState[2].size = sizeof(V128);
-+
-+   stmt(IRStmt_Dirty(d));
-+   s390_cc_set(cc);
-+   return "vbperm";
- }
- 
- /* New insns are added here.
-@@ -20489,11 +20754,23 @@ s390_decode_6byte_and_irgen(const UChar *bytes)
-                                                 RXY_dl2(ovl),
-                                                 RXY_dh2(ovl));  goto ok;
-    case 0xe60000000034ULL: /* VPKZ */ goto unimplemented;
--   case 0xe60000000035ULL: /* VLRL */ goto unimplemented;
--   case 0xe60000000037ULL: /* VLRLR */ goto unimplemented;
-+   case 0xe60000000035ULL: s390_format_VSI_URDV(s390_irgen_VLRL, VSI_v1(ovl),
-+                                                VSI_b2(ovl), VSI_d2(ovl),
-+                                                VSI_i3(ovl),
-+                                                VSI_rxb(ovl)); goto ok;
-+   case 0xe60000000037ULL: s390_format_VRS_RRDV(s390_irgen_VLRLR, VRSd_v1(ovl),
-+                                                VRSd_r3(ovl), VRS_b2(ovl),
-+                                                VRS_d2(ovl),
-+                                                VRS_rxb(ovl));  goto ok;
-    case 0xe6000000003cULL: /* VUPKZ */ goto unimplemented;
--   case 0xe6000000003dULL: /* VSTRL */ goto unimplemented;
--   case 0xe6000000003fULL: /* VSTRLR */ goto unimplemented;
-+   case 0xe6000000003dULL:  s390_format_VSI_URDV(s390_irgen_VSTRL, VSI_v1(ovl),
-+                                                 VSI_b2(ovl), VSI_d2(ovl),
-+                                                 VSI_i3(ovl),
-+                                                 VSI_rxb(ovl)); goto ok;
-+   case 0xe6000000003fULL: s390_format_VRS_RRDV(s390_irgen_VSTRLR, VRSd_v1(ovl),
-+                                                VRSd_r3(ovl), VRS_b2(ovl),
-+                                                VRS_d2(ovl),
-+                                                VRS_rxb(ovl));  goto ok;
-    case 0xe60000000049ULL: /* VLIP */ goto unimplemented;
-    case 0xe60000000050ULL: /* VCVB */ goto unimplemented;
-    case 0xe60000000052ULL: /* VCVBG */ goto unimplemented;
-@@ -20691,12 +20968,18 @@ s390_decode_6byte_and_irgen(const UChar *bytes)
-    case 0xe7000000006bULL: s390_format_VRR_VVV(s390_irgen_VNO, VRR_v1(ovl),
-                                                VRR_v2(ovl), VRR_r3(ovl),
-                                                VRR_rxb(ovl));  goto ok;
--   case 0xe7000000006cULL: /* VNX */ goto unimplemented;
-+   case 0xe7000000006cULL: s390_format_VRR_VVV(s390_irgen_VNX, VRR_v1(ovl),
-+                                               VRR_v2(ovl), VRR_r3(ovl),
-+                                               VRR_rxb(ovl));  goto ok;
-    case 0xe7000000006dULL: s390_format_VRR_VVV(s390_irgen_VX, VRR_v1(ovl),
-                                                VRR_v2(ovl), VRR_r3(ovl),
-                                                VRR_rxb(ovl));  goto ok;
--   case 0xe7000000006eULL: /* VNN */ goto unimplemented;
--   case 0xe7000000006fULL: /* VOC */ goto unimplemented;
-+   case 0xe7000000006eULL: s390_format_VRR_VVV(s390_irgen_VNN, VRR_v1(ovl),
-+                                               VRR_v2(ovl), VRR_r3(ovl),
-+                                               VRR_rxb(ovl));  goto ok;
-+   case 0xe7000000006fULL: s390_format_VRR_VVV(s390_irgen_VOC, VRR_v1(ovl),
-+                                               VRR_v2(ovl), VRR_r3(ovl),
-+                                               VRR_rxb(ovl));  goto ok;
-    case 0xe70000000070ULL: s390_format_VRR_VVVM(s390_irgen_VESLV, VRR_v1(ovl),
-                                                 VRR_v2(ovl), VRR_r3(ovl),
-                                                 VRR_m4(ovl), VRR_rxb(ovl));  goto ok;
-@@ -20749,7 +21032,9 @@ s390_decode_6byte_and_irgen(const UChar *bytes)
-    case 0xe70000000084ULL: s390_format_VRR_VVVM(s390_irgen_VPDI, VRR_v1(ovl),
-                                                VRR_v2(ovl), VRR_r3(ovl),
-                                                VRR_m4(ovl), VRR_rxb(ovl));  goto ok;
--   case 0xe70000000085ULL: /* VBPERM */ goto unimplemented;
-+   case 0xe70000000085ULL: s390_format_VRR_VVV(s390_irgen_VBPERM, VRR_v1(ovl),
-+                                               VRR_v2(ovl), VRR_r3(ovl),
-+                                               VRR_rxb(ovl));  goto ok;
-    case 0xe7000000008aULL: s390_format_VRR_VVVVMM(s390_irgen_VSTRC, VRRd_v1(ovl),
-                                                   VRRd_v2(ovl), VRRd_v3(ovl),
-                                                   VRRd_v4(ovl), VRRd_m5(ovl),
-@@ -20780,8 +21065,16 @@ s390_decode_6byte_and_irgen(const UChar *bytes)
-    case 0xe70000000097ULL: s390_format_VRR_VVVMM(s390_irgen_VPKS, VRR_v1(ovl),
-                                                VRR_v2(ovl), VRR_r3(ovl),
-                                                VRR_m4(ovl), VRR_m5(ovl), VRR_rxb(ovl));  goto ok;
--   case 0xe7000000009eULL: /* VFNMS */ goto unimplemented;
--   case 0xe7000000009fULL: /* VFNMA */ goto unimplemented;
-+   case 0xe7000000009eULL: s390_format_VRR_VVVVMM(s390_irgen_VFNMS, VRRe_v1(ovl),
-+                                                  VRRe_v2(ovl), VRRe_v3(ovl),
-+                                                  VRRe_v4(ovl), VRRe_m5(ovl),
-+                                                  VRRe_m6(ovl),
-+                                                  VRRe_rxb(ovl));  goto ok;
-+   case 0xe7000000009fULL: s390_format_VRR_VVVVMM(s390_irgen_VFNMA, VRRe_v1(ovl),
-+                                                  VRRe_v2(ovl), VRRe_v3(ovl),
-+                                                  VRRe_v4(ovl), VRRe_m5(ovl),
-+                                                  VRRe_m6(ovl),
-+                                                  VRRe_rxb(ovl));  goto ok;
-    case 0xe700000000a1ULL: s390_format_VRR_VVVM(s390_irgen_VMLH, VRR_v1(ovl),
-                                                 VRR_v2(ovl), VRR_r3(ovl),
-                                                 VRR_m4(ovl), VRR_rxb(ovl));  goto ok;
-@@ -20834,7 +21127,11 @@ s390_decode_6byte_and_irgen(const UChar *bytes)
-    case 0xe700000000b4ULL: s390_format_VRR_VVVM(s390_irgen_VGFM, VRR_v1(ovl),
-                                                 VRR_v2(ovl), VRR_r3(ovl),
-                                                 VRR_m4(ovl), VRR_rxb(ovl));  goto ok;
--   case 0xe700000000b8ULL: /* VMSL */ goto unimplemented;
-+   case 0xe700000000b8ULL: s390_format_VRR_VVVVMM(s390_irgen_VMSL, VRRd_v1(ovl),
-+                                                  VRRd_v2(ovl), VRRd_v3(ovl),
-+                                                  VRRd_v4(ovl), VRRd_m5(ovl),
-+                                                  VRRd_m6(ovl),
-+                                                  VRRd_rxb(ovl));  goto ok;
-    case 0xe700000000b9ULL: s390_format_VRRd_VVVVM(s390_irgen_VACCC, VRRd_v1(ovl),
-                                                   VRRd_v2(ovl), VRRd_v3(ovl),
-                                                   VRRd_v4(ovl), VRRd_m5(ovl),
-@@ -20871,11 +21168,11 @@ s390_decode_6byte_and_irgen(const UChar *bytes)
-                                                   VRRa_v2(ovl), VRRa_m3(ovl),
-                                                   VRRa_m4(ovl), VRRa_m5(ovl),
-                                                   VRRa_rxb(ovl)); goto ok;
--   case 0xe700000000c4ULL: s390_format_VRRa_VVMMM(s390_irgen_VLDE, VRRa_v1(ovl),
-+   case 0xe700000000c4ULL: s390_format_VRRa_VVMMM(s390_irgen_VFLL, VRRa_v1(ovl),
-                                                   VRRa_v2(ovl), VRRa_m3(ovl),
-                                                   VRRa_m4(ovl), VRRa_m5(ovl),
-                                                   VRRa_rxb(ovl)); goto ok;
--   case 0xe700000000c5ULL: s390_format_VRRa_VVMMM(s390_irgen_VLED, VRRa_v1(ovl),
-+   case 0xe700000000c5ULL: s390_format_VRRa_VVMMM(s390_irgen_VFLR, VRRa_v1(ovl),
-                                                   VRRa_v2(ovl), VRRa_m3(ovl),
-                                                   VRRa_m4(ovl), VRRa_m5(ovl),
-                                                   VRRa_rxb(ovl)); goto ok;
-@@ -20956,8 +21253,16 @@ s390_decode_6byte_and_irgen(const UChar *bytes)
-                                                    VRRa_m3(ovl), VRRa_m4(ovl),
-                                                    VRRa_m5(ovl),
-                                                    VRRa_rxb(ovl)); goto ok;
--   case 0xe700000000eeULL: /* VFMIN */ goto unimplemented;
--   case 0xe700000000efULL: /* VFMAX */ goto unimplemented;
-+   case 0xe700000000eeULL: s390_format_VRRa_VVVMMM(s390_irgen_VFMIN, VRRa_v1(ovl),
-+                                                   VRRa_v2(ovl), VRRa_v3(ovl),
-+                                                   VRRa_m3(ovl), VRRa_m4(ovl),
-+                                                   VRRa_m5(ovl),
-+                                                   VRRa_rxb(ovl)); goto ok;
-+   case 0xe700000000efULL: s390_format_VRRa_VVVMMM(s390_irgen_VFMAX, VRRa_v1(ovl),
-+                                                   VRRa_v2(ovl), VRRa_v3(ovl),
-+                                                   VRRa_m3(ovl), VRRa_m4(ovl),
-+                                                   VRRa_m5(ovl),
-+                                                   VRRa_rxb(ovl)); goto ok;
-    case 0xe700000000f0ULL: s390_format_VRR_VVVM(s390_irgen_VAVGL, VRR_v1(ovl),
-                                                 VRR_v2(ovl), VRR_r3(ovl),
-                                                 VRR_m4(ovl), VRR_rxb(ovl));  goto ok;
-diff --git a/VEX/priv/host_s390_defs.c b/VEX/priv/host_s390_defs.c
-index 3b6121fec..8762975b2 100644
---- a/VEX/priv/host_s390_defs.c
-+++ b/VEX/priv/host_s390_defs.c
-@@ -8,7 +8,7 @@
-    This file is part of Valgrind, a dynamic binary instrumentation
-    framework.
- 
--   Copyright IBM Corp. 2010-2017
-+   Copyright IBM Corp. 2010-2020
-    Copyright (C) 2012-2017  Florian Krohm   (britzel@acm.org)
- 
-    This program is free software; you can redistribute it and/or
-@@ -684,6 +684,8 @@ s390_insn* genMove_S390(HReg from, HReg to, Bool mode64)
-    switch (hregClass(from)) {
-    case HRcInt64:
-       return s390_insn_move(sizeofIRType(Ity_I64), to, from);
-+   case HRcFlt64:
-+      return s390_insn_move(sizeofIRType(Ity_F64), to, from);
-    case HRcVec128:
-       return s390_insn_move(sizeofIRType(Ity_V128), to, from);
-    default:
-@@ -7870,6 +7872,10 @@ s390_insn_as_string(const s390_insn *insn)
-          op = "v-vfloatabs";
-          break;
- 
-+      case S390_VEC_FLOAT_NABS:
-+         op = "v-vfloatnabs";
-+         break;
-+
-       default:
-          goto fail;
-       }
-@@ -9439,21 +9445,28 @@ s390_insn_unop_emit(UChar *buf, const s390_insn *insn)
- 
-    case S390_VEC_FLOAT_NEG: {
-       vassert(insn->variant.unop.src.tag == S390_OPND_REG);
--      vassert(insn->size == 8);
-+      vassert(insn->size >= 4);
-       UChar v1 = hregNumber(insn->variant.unop.dst);
-       UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
-       return s390_emit_VFPSO(buf, v1, v2, s390_getM_from_size(insn->size), 0, 0);
-    }
-    case S390_VEC_FLOAT_ABS: {
-       vassert(insn->variant.unop.src.tag == S390_OPND_REG);
--      vassert(insn->size == 8);
-+      vassert(insn->size >= 4);
-       UChar v1 = hregNumber(insn->variant.unop.dst);
-       UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
-       return s390_emit_VFPSO(buf, v1, v2, s390_getM_from_size(insn->size), 0, 2);
-    }
-+   case S390_VEC_FLOAT_NABS: {
-+      vassert(insn->variant.unop.src.tag == S390_OPND_REG);
-+      vassert(insn->size >= 4);
-+      UChar v1 = hregNumber(insn->variant.unop.dst);
-+      UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
-+      return s390_emit_VFPSO(buf, v1, v2, s390_getM_from_size(insn->size), 0, 1);
-+   }
-    case S390_VEC_FLOAT_SQRT: {
-       vassert(insn->variant.unop.src.tag == S390_OPND_REG);
--      vassert(insn->size == 8);
-+      vassert(insn->size >= 4);
-       UChar v1 = hregNumber(insn->variant.unop.dst);
-       UChar v2 = hregNumber(insn->variant.unop.src.variant.reg);
-       return s390_emit_VFSQ(buf, v1, v2, s390_getM_from_size(insn->size), 0);
-diff --git a/VEX/priv/host_s390_defs.h b/VEX/priv/host_s390_defs.h
-index 3f6473e10..9b69f4d38 100644
---- a/VEX/priv/host_s390_defs.h
-+++ b/VEX/priv/host_s390_defs.h
-@@ -8,7 +8,7 @@
-    This file is part of Valgrind, a dynamic binary instrumentation
-    framework.
- 
--   Copyright IBM Corp. 2010-2017
-+   Copyright IBM Corp. 2010-2020
- 
-    This program is free software; you can redistribute it and/or
-    modify it under the terms of the GNU General Public License as
-@@ -205,6 +205,7 @@ typedef enum {
-    S390_VEC_COUNT_ONES,
-    S390_VEC_FLOAT_NEG,
-    S390_VEC_FLOAT_ABS,
-+   S390_VEC_FLOAT_NABS,
-    S390_VEC_FLOAT_SQRT,
-    S390_UNOP_T_INVALID
- } s390_unop_t;
-@@ -931,6 +932,8 @@ extern UInt s390_host_hwcaps;
-                       (s390_host_hwcaps & (VEX_HWCAPS_S390X_MSA5))
- #define s390_host_has_lsc2 \
-                       (s390_host_hwcaps & (VEX_HWCAPS_S390X_LSC2))
-+#define s390_host_has_vxe \
-+                      (s390_host_hwcaps & (VEX_HWCAPS_S390X_VXE))
- #endif /* ndef __VEX_HOST_S390_DEFS_H */
- 
- /*---------------------------------------------------------------*/
-diff --git a/VEX/priv/host_s390_isel.c b/VEX/priv/host_s390_isel.c
-index 134f3eb6f..2f9854038 100644
---- a/VEX/priv/host_s390_isel.c
-+++ b/VEX/priv/host_s390_isel.c
-@@ -8,7 +8,7 @@
-    This file is part of Valgrind, a dynamic binary instrumentation
-    framework.
- 
--   Copyright IBM Corp. 2010-2017
-+   Copyright IBM Corp. 2010-2020
-    Copyright (C) 2012-2017  Florian Krohm   (britzel@acm.org)
- 
-    This program is free software; you can redistribute it and/or
-@@ -2362,9 +2362,10 @@ s390_isel_float128_expr_wrk(HReg *dst_hi, HReg *dst_lo, ISelEnv *env,
-       case Iop_NegF128:
-          if (left->tag == Iex_Unop &&
-              (left->Iex.Unop.op == Iop_AbsF32 ||
--              left->Iex.Unop.op == Iop_AbsF64))
-+              left->Iex.Unop.op == Iop_AbsF64)) {
-             bfpop = S390_BFP_NABS;
--         else
-+            left = left->Iex.Unop.arg;
-+         } else
-             bfpop = S390_BFP_NEG;
-          goto float128_opnd;
-       case Iop_AbsF128:     bfpop = S390_BFP_ABS;         goto float128_opnd;
-@@ -2726,9 +2727,10 @@ s390_isel_float_expr_wrk(ISelEnv *env, IRExpr *expr)
-       case Iop_NegF64:
-          if (left->tag == Iex_Unop &&
-              (left->Iex.Unop.op == Iop_AbsF32 ||
--              left->Iex.Unop.op == Iop_AbsF64))
-+              left->Iex.Unop.op == Iop_AbsF64)) {
-             bfpop = S390_BFP_NABS;
--         else
-+            left = left->Iex.Unop.arg;
-+         } else
-             bfpop = S390_BFP_NEG;
-          break;
- 
-@@ -3944,11 +3946,27 @@ s390_isel_vec_expr_wrk(ISelEnv *env, IRExpr *expr)
-          vec_unop = S390_VEC_COUNT_ONES;
-          goto Iop_V_wrk;
- 
-+      case Iop_Neg32Fx4:
-+         size = 4;
-+         vec_unop = S390_VEC_FLOAT_NEG;
-+         if (arg->tag == Iex_Unop && arg->Iex.Unop.op == Iop_Abs32Fx4) {
-+            vec_unop = S390_VEC_FLOAT_NABS;
-+            arg = arg->Iex.Unop.arg;
-+         }
-+         goto Iop_V_wrk;
-       case Iop_Neg64Fx2:
-          size = 8;
-          vec_unop = S390_VEC_FLOAT_NEG;
-+         if (arg->tag == Iex_Unop && arg->Iex.Unop.op == Iop_Abs64Fx2) {
-+            vec_unop = S390_VEC_FLOAT_NABS;
-+            arg = arg->Iex.Unop.arg;
-+         }
-          goto Iop_V_wrk;
- 
-+      case Iop_Abs32Fx4:
-+         size = 4;
-+         vec_unop = S390_VEC_FLOAT_ABS;
-+         goto Iop_V_wrk;
-       case Iop_Abs64Fx2:
-          size = 8;
-          vec_unop = S390_VEC_FLOAT_ABS;
-@@ -4474,17 +4492,29 @@ s390_isel_vec_expr_wrk(ISelEnv *env, IRExpr *expr)
-          vec_binop = S390_VEC_ELEM_ROLL_V;
-          goto Iop_VV_wrk;
- 
-+      case Iop_CmpEQ32Fx4:
-+         size = 4;
-+         vec_binop = S390_VEC_FLOAT_COMPARE_EQUAL;
-+         goto Iop_VV_wrk;
-       case Iop_CmpEQ64Fx2:
-          size = 8;
-          vec_binop = S390_VEC_FLOAT_COMPARE_EQUAL;
-          goto Iop_VV_wrk;
- 
-+      case Iop_CmpLE32Fx4:
-+         size = 4;
-+         vec_binop = S390_VEC_FLOAT_COMPARE_LESS_OR_EQUAL;
-+         goto Iop_VV_wrk;
-       case Iop_CmpLE64Fx2: {
-          size = 8;
-          vec_binop = S390_VEC_FLOAT_COMPARE_LESS_OR_EQUAL;
-          goto Iop_VV_wrk;
-       }
- 
-+      case Iop_CmpLT32Fx4:
-+         size = 4;
-+         vec_binop = S390_VEC_FLOAT_COMPARE_LESS;
-+         goto Iop_VV_wrk;
-       case Iop_CmpLT64Fx2: {
-          size = 8;
-          vec_binop = S390_VEC_FLOAT_COMPARE_LESS;
-@@ -4671,20 +4701,41 @@ s390_isel_vec_expr_wrk(ISelEnv *env, IRExpr *expr)
-                                            dst, reg1, reg2, reg3));
-          return dst;
- 
-+      case Iop_Add32Fx4:
-+         size = 4;
-+         vec_binop = S390_VEC_FLOAT_ADD;
-+         goto Iop_irrm_VV_wrk;
-+
-       case Iop_Add64Fx2:
-          size = 8;
-          vec_binop = S390_VEC_FLOAT_ADD;
-          goto Iop_irrm_VV_wrk;
- 
-+      case Iop_Sub32Fx4:
-+         size = 4;
-+         vec_binop = S390_VEC_FLOAT_SUB;
-+         goto Iop_irrm_VV_wrk;
-+
-       case Iop_Sub64Fx2:
-          size = 8;
-          vec_binop = S390_VEC_FLOAT_SUB;
-          goto Iop_irrm_VV_wrk;
- 
-+      case Iop_Mul32Fx4:
-+         size = 4;
-+         vec_binop = S390_VEC_FLOAT_MUL;
-+         goto Iop_irrm_VV_wrk;
-+
-       case Iop_Mul64Fx2:
-          size = 8;
-          vec_binop = S390_VEC_FLOAT_MUL;
-          goto Iop_irrm_VV_wrk;
-+
-+      case Iop_Div32Fx4:
-+         size = 4;
-+         vec_binop = S390_VEC_FLOAT_DIV;
-+         goto Iop_irrm_VV_wrk;
-+
-       case Iop_Div64Fx2:
-          size = 8;
-          vec_binop = S390_VEC_FLOAT_DIV;
-diff --git a/VEX/priv/main_main.c b/VEX/priv/main_main.c
-index 72f419988..12f521d8c 100644
---- a/VEX/priv/main_main.c
-+++ b/VEX/priv/main_main.c
-@@ -1795,6 +1795,7 @@ static const HChar* show_hwcaps_s390x ( UInt hwcaps )
-       { VEX_HWCAPS_S390X_MSA5,  "msa5" },
-       { VEX_HWCAPS_S390X_MI2,   "mi2" },
-       { VEX_HWCAPS_S390X_LSC2,  "lsc2" },
-+      { VEX_HWCAPS_S390X_LSC2,  "vxe" },
-    };
-    /* Allocate a large enough buffer */
-    static HChar buf[sizeof prefix + 
-diff --git a/VEX/pub/libvex.h b/VEX/pub/libvex.h
-index 53e3705da..2ffed0ad0 100644
---- a/VEX/pub/libvex.h
-+++ b/VEX/pub/libvex.h
-@@ -171,7 +171,7 @@ typedef
- #define VEX_HWCAPS_S390X_MSA5  (1<<19)  /* message security assistance facility */
- #define VEX_HWCAPS_S390X_MI2   (1<<20)  /* miscellaneous-instruction-extensions facility 2 */
- #define VEX_HWCAPS_S390X_LSC2  (1<<21)  /* Conditional load/store facility2 */
--
-+#define VEX_HWCAPS_S390X_VXE   (1<<22)  /* Vector-enhancements facility */
- 
- /* Special value representing all available s390x hwcaps */
- #define VEX_HWCAPS_S390X_ALL   (VEX_HWCAPS_S390X_LDISP | \
-@@ -189,7 +189,8 @@ typedef
-                                 VEX_HWCAPS_S390X_VX    | \
-                                 VEX_HWCAPS_S390X_MSA5  | \
-                                 VEX_HWCAPS_S390X_MI2   | \
--                                VEX_HWCAPS_S390X_LSC2)
-+                                VEX_HWCAPS_S390X_LSC2  | \
-+                                VEX_HWCAPS_S390X_VXE)
- 
- #define VEX_HWCAPS_S390X(x)  ((x) & ~VEX_S390X_MODEL_MASK)
- #define VEX_S390X_MODEL(x)   ((x) &  VEX_S390X_MODEL_MASK)
-diff --git a/VEX/pub/libvex_emnote.h b/VEX/pub/libvex_emnote.h
-index be033b4da..77880a270 100644
---- a/VEX/pub/libvex_emnote.h
-+++ b/VEX/pub/libvex_emnote.h
-@@ -124,6 +124,10 @@ typedef
-       /* ppno insn is not supported on this host */
-       EmFail_S390X_ppno,
- 
-+      /* insn needs vector-enhancements facility which is not available on this
-+         host */
-+      EmFail_S390X_vxe,
-+
-       EmNote_NUMBER
-    }
-    VexEmNote;
-diff --git a/coregrind/m_initimg/initimg-linux.c b/coregrind/m_initimg/initimg-linux.c
-index 365942c4f..ba84fa6e9 100644
---- a/coregrind/m_initimg/initimg-linux.c
-+++ b/coregrind/m_initimg/initimg-linux.c
-@@ -697,9 +697,13 @@ Addr setup_client_stack( void*  init_sp,
-             }
- #           elif defined(VGP_s390x_linux)
-             {
--               /* Advertise hardware features "below" TE and VXRS.  TE itself
--                  and anything above VXRS is not supported by Valgrind. */
--               auxv->u.a_val &= (VKI_HWCAP_S390_TE - 1) | VKI_HWCAP_S390_VXRS;
-+               /* Out of the hardware features available on the platform,
-+                  advertise those "below" TE, as well as the ones explicitly
-+                  ORed in the expression below.  Anything else, such as TE
-+                  itself, is not supported by Valgrind. */
-+               auxv->u.a_val &= ((VKI_HWCAP_S390_TE - 1)
-+                                 | VKI_HWCAP_S390_VXRS
-+                                 | VKI_HWCAP_S390_VXRS_EXT);
-             }
- #           elif defined(VGP_arm64_linux)
-             {
-diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c
-index e7877e636..228ae2554 100644
---- a/coregrind/m_machine.c
-+++ b/coregrind/m_machine.c
-@@ -1555,6 +1555,7 @@ Bool VG_(machine_get_hwcaps)( void )
-         { False, S390_FAC_MSA5,  VEX_HWCAPS_S390X_MSA5,  "MSA5"  },
-         { False, S390_FAC_MI2,   VEX_HWCAPS_S390X_MI2,   "MI2"   },
-         { False, S390_FAC_LSC2,  VEX_HWCAPS_S390X_LSC2,  "LSC2"  },
-+        { False, S390_FAC_VXE,   VEX_HWCAPS_S390X_VXE,   "VXE"   },
-      };
- 
-      /* Set hwcaps according to the detected facilities */
-diff --git a/include/vki/vki-s390x-linux.h b/include/vki/vki-s390x-linux.h
-index 7b863a324..4ab2d3334 100644
---- a/include/vki/vki-s390x-linux.h
-+++ b/include/vki/vki-s390x-linux.h
-@@ -806,6 +806,7 @@ typedef vki_s390_regs vki_elf_gregset_t;
- 
- #define VKI_HWCAP_S390_TE           1024
- #define VKI_HWCAP_S390_VXRS         2048
-+#define VKI_HWCAP_S390_VXRS_EXT     8192
- 
- 
- //----------------------------------------------------------------------
-diff --git a/none/tests/s390x/vector.h b/none/tests/s390x/vector.h
-index de2391480..632c2cb9c 100644
---- a/none/tests/s390x/vector.h
-+++ b/none/tests/s390x/vector.h
-@@ -86,6 +86,13 @@ void print_hex(const V128 value) {
-    printf("%016lx | %016lx\n", value.u64[0], value.u64[1]);
- }
- 
-+void print_hex64(const V128 value, int zero_only) {
-+   if (zero_only)
-+      printf("%016lx | --\n", value.u64[0]);
-+   else
-+      printf("%016lx | %016lx\n", value.u64[0], value.u64[1]);
-+}
-+
- void print_f32(const V128 value, int even_only, int zero_only) {
-    if (zero_only)
-       printf("%a | -- | -- | --\n", value.f32[0]);
-@@ -222,8 +229,10 @@ static void test_##insn##_selective(const s390x_test_usageInfo info) \
-       {printf("  v_arg2   = "); print_hex(v_arg2);} \
-    if (info & V128_V_ARG3_AS_INT) \
-       {printf("  v_arg3   = "); print_hex(v_arg3);} \
--   if (info & V128_V_RES_AS_INT) \
--      {printf("  v_result = "); print_hex(v_result);} \
-+   if (info & V128_V_RES_AS_INT) { \
-+      printf("  v_result = "); \
-+      print_hex64(v_result, info & V128_V_RES_ZERO_ONLY); \
-+   } \
-    \
-    if (info & V128_V_ARG1_AS_FLOAT64) \
-       {printf("  v_arg1   = "); print_f64(v_arg1, 0);} \
-diff --git a/none/tests/s390x/vector_float.c b/none/tests/s390x/vector_float.c
-index 52f3a296f..20853f381 100644
---- a/none/tests/s390x/vector_float.c
-+++ b/none/tests/s390x/vector_float.c
-@@ -114,50 +114,59 @@ int main()
-    test_with_selective_printing(vldeb, (V128_V_RES_AS_FLOAT64 |
-                                         V128_V_ARG1_AS_FLOAT64));
-    test_with_selective_printing(wldeb, (V128_V_RES_AS_FLOAT64 |
--                                        V128_V_ARG1_AS_FLOAT64));
-+                                        V128_V_ARG1_AS_FLOAT64 |
-+                                        V128_V_RES_ZERO_ONLY));
- 
-    test_with_selective_printing(vflcdb, (V128_V_RES_AS_FLOAT64 |
-                                          V128_V_ARG1_AS_FLOAT64));
-    test_with_selective_printing(wflcdb, (V128_V_RES_AS_FLOAT64 |
--                                         V128_V_ARG1_AS_FLOAT64));
-+                                         V128_V_ARG1_AS_FLOAT64 |
-+                                        V128_V_RES_ZERO_ONLY));
-    test_with_selective_printing(vflndb, (V128_V_RES_AS_FLOAT64 |
-                                          V128_V_ARG1_AS_FLOAT64));
-    test_with_selective_printing(wflndb, (V128_V_RES_AS_FLOAT64 |
--                                         V128_V_ARG1_AS_FLOAT64));
-+                                         V128_V_ARG1_AS_FLOAT64 |
-+                                        V128_V_RES_ZERO_ONLY));
-    test_with_selective_printing(vflpdb, (V128_V_RES_AS_FLOAT64 |
-                                          V128_V_ARG1_AS_FLOAT64));
-    test_with_selective_printing(wflpdb, (V128_V_RES_AS_FLOAT64 |
--                                         V128_V_ARG1_AS_FLOAT64));
-+                                         V128_V_ARG1_AS_FLOAT64 |
-+                                        V128_V_RES_ZERO_ONLY));
- 
-    test_with_selective_printing(vfadb, (V128_V_RES_AS_FLOAT64 |
-                                         V128_V_ARG1_AS_FLOAT64 |
-                                         V128_V_ARG2_AS_FLOAT64));
-    test_with_selective_printing(wfadb, (V128_V_RES_AS_FLOAT64 |
-                                         V128_V_ARG1_AS_FLOAT64 |
--                                        V128_V_ARG2_AS_FLOAT64));
-+                                        V128_V_ARG2_AS_FLOAT64 |
-+                                        V128_V_RES_ZERO_ONLY));
-    test_with_selective_printing(vfsdb, (V128_V_RES_AS_FLOAT64 |
-                                         V128_V_ARG1_AS_FLOAT64 |
-                                         V128_V_ARG2_AS_FLOAT64));
-    test_with_selective_printing(wfsdb, (V128_V_RES_AS_FLOAT64 |
-                                         V128_V_ARG1_AS_FLOAT64 |
--                                        V128_V_ARG2_AS_FLOAT64));
-+                                        V128_V_ARG2_AS_FLOAT64 |
-+                                        V128_V_RES_ZERO_ONLY));
-    test_with_selective_printing(vfmdb, (V128_V_RES_AS_FLOAT64 |
-                                         V128_V_ARG1_AS_FLOAT64 |
-                                         V128_V_ARG2_AS_FLOAT64));
-    test_with_selective_printing(wfmdb, (V128_V_RES_AS_FLOAT64 |
-                                         V128_V_ARG1_AS_FLOAT64 |
--                                        V128_V_ARG2_AS_FLOAT64));
-+                                        V128_V_ARG2_AS_FLOAT64 |
-+                                        V128_V_RES_ZERO_ONLY));
-    test_with_selective_printing(vfddb, (V128_V_RES_AS_FLOAT64 |
-                                         V128_V_ARG1_AS_FLOAT64 |
-                                         V128_V_ARG2_AS_FLOAT64));
-    test_with_selective_printing(wfddb, (V128_V_RES_AS_FLOAT64 |
-                                         V128_V_ARG1_AS_FLOAT64 |
--                                        V128_V_ARG2_AS_FLOAT64));
-+                                        V128_V_ARG2_AS_FLOAT64 |
-+                                        V128_V_RES_ZERO_ONLY));
-  
-    test_with_selective_printing(vfsqdb, (V128_V_RES_AS_FLOAT64 |
-                                          V128_V_ARG1_AS_FLOAT64));
-    test_with_selective_printing(wfsqdb, (V128_V_RES_AS_FLOAT64 |
--                                         V128_V_ARG1_AS_FLOAT64));
-+                                         V128_V_ARG1_AS_FLOAT64 |
-+                                        V128_V_RES_ZERO_ONLY));
- 
-    test_with_selective_printing(vfmadb, (V128_V_RES_AS_FLOAT64 |
-                                          V128_V_ARG1_AS_FLOAT64 |
-@@ -166,7 +175,8 @@ int main()
-    test_with_selective_printing(wfmadb, (V128_V_RES_AS_FLOAT64 |
-                                          V128_V_ARG1_AS_FLOAT64 |
-                                          V128_V_ARG2_AS_FLOAT64 |
--                                         V128_V_ARG3_AS_FLOAT64));
-+                                         V128_V_ARG3_AS_FLOAT64 |
-+                                        V128_V_RES_ZERO_ONLY));
-    test_with_selective_printing(vfmsdb, (V128_V_RES_AS_FLOAT64 |
-                                          V128_V_ARG1_AS_FLOAT64 |
-                                          V128_V_ARG2_AS_FLOAT64 |
-@@ -174,21 +184,25 @@ int main()
-    test_with_selective_printing(wfmsdb, (V128_V_RES_AS_FLOAT64 |
-                                          V128_V_ARG1_AS_FLOAT64 |
-                                          V128_V_ARG2_AS_FLOAT64 |
--                                         V128_V_ARG3_AS_FLOAT64));
-+                                         V128_V_ARG3_AS_FLOAT64 |
-+                                        V128_V_RES_ZERO_ONLY));
- 
-    test_with_selective_printing(wfcdb, (V128_V_ARG1_AS_FLOAT64 |
-                                         V128_V_ARG2_AS_FLOAT64 |
--                                        V128_R_RES));
-+                                        V128_R_RES |
-+                                        V128_V_RES_ZERO_ONLY));
-    test_with_selective_printing(wfkdb, (V128_V_ARG1_AS_FLOAT64 |
-                                         V128_V_ARG2_AS_FLOAT64 |
--                                        V128_R_RES));
-+                                        V128_R_RES |
-+                                        V128_V_RES_ZERO_ONLY));
- 
-    test_with_selective_printing(vfcedb,  (V128_V_RES_AS_INT |
-                                           V128_V_ARG1_AS_FLOAT64 |
-                                           V128_V_ARG2_AS_FLOAT64));
-    test_with_selective_printing(wfcedb,  (V128_V_RES_AS_INT |
-                                           V128_V_ARG1_AS_FLOAT64 |
--                                          V128_V_ARG2_AS_FLOAT64));
-+                                          V128_V_ARG2_AS_FLOAT64 |
-+                                          V128_V_RES_ZERO_ONLY));
-    test_with_selective_printing(vfcedbs, (V128_V_RES_AS_INT |
-                                           V128_V_ARG1_AS_FLOAT64 |
-                                           V128_V_ARG2_AS_FLOAT64 |
-@@ -196,14 +210,16 @@ int main()
-    test_with_selective_printing(wfcedbs, (V128_V_RES_AS_INT |
-                                           V128_V_ARG1_AS_FLOAT64 |
-                                           V128_V_ARG2_AS_FLOAT64 |
--                                          V128_R_RES));
-+                                          V128_R_RES |
-+                                          V128_V_RES_ZERO_ONLY));
- 
-    test_with_selective_printing(vfchdb,  (V128_V_RES_AS_INT |
-                                           V128_V_ARG1_AS_FLOAT64 |
-                                           V128_V_ARG2_AS_FLOAT64));
-    test_with_selective_printing(wfchdb,  (V128_V_RES_AS_INT |
-                                           V128_V_ARG1_AS_FLOAT64 |
--                                          V128_V_ARG2_AS_FLOAT64));
-+                                          V128_V_ARG2_AS_FLOAT64 |
-+                                          V128_V_RES_ZERO_ONLY));
-    test_with_selective_printing(vfchdbs, (V128_V_RES_AS_INT |
-                                           V128_V_ARG1_AS_FLOAT64 |
-                                           V128_V_ARG2_AS_FLOAT64 |
-@@ -211,14 +227,16 @@ int main()
-    test_with_selective_printing(wfchdbs, (V128_V_RES_AS_INT |
-                                           V128_V_ARG1_AS_FLOAT64 |
-                                           V128_V_ARG2_AS_FLOAT64 |
--                                          V128_R_RES));
-+                                          V128_R_RES |
-+                                          V128_V_RES_ZERO_ONLY));
- 
-    test_with_selective_printing(vfchedb,  (V128_V_RES_AS_INT |
-                                            V128_V_ARG1_AS_FLOAT64 |
-                                            V128_V_ARG2_AS_FLOAT64));
-    test_with_selective_printing(wfchedb,  (V128_V_RES_AS_INT |
-                                            V128_V_ARG1_AS_FLOAT64 |
--                                           V128_V_ARG2_AS_FLOAT64));
-+                                           V128_V_ARG2_AS_FLOAT64 |
-+                                           V128_V_RES_ZERO_ONLY));
-    test_with_selective_printing(vfchedbs, (V128_V_RES_AS_INT |
-                                            V128_V_ARG1_AS_FLOAT64 |
-                                            V128_V_ARG2_AS_FLOAT64 |
-@@ -226,7 +244,8 @@ int main()
-    test_with_selective_printing(wfchedbs, (V128_V_RES_AS_INT |
-                                            V128_V_ARG1_AS_FLOAT64 |
-                                            V128_V_ARG2_AS_FLOAT64 |
--                                           V128_R_RES));
-+                                           V128_R_RES |
-+                                           V128_V_RES_ZERO_ONLY));
- 
-    test_with_selective_printing(vftcidb0,    (V128_V_RES_AS_INT |
-                                               V128_V_ARG1_AS_FLOAT64 |
-diff --git a/none/tests/s390x/vector_float.stdout.exp b/none/tests/s390x/vector_float.stdout.exp
-index eac525041..a330ac832 100644
---- a/none/tests/s390x/vector_float.stdout.exp
-+++ b/none/tests/s390x/vector_float.stdout.exp
-@@ -419,88 +419,88 @@ insn vcgdb07:
-   v_result = 7fffffffffffffff | 7fffffffffffffff
-   v_arg1   = 0x1.fed2f087c21p+341 | 0x1.180e4c1d87fc4p+682
- insn wcgdb00:
--  v_result = 7fffffffffffffff | 0000000000000000
-+  v_result = 7fffffffffffffff | --
-   v_arg1   = 0x1.d7fd9222e8b86p+670 | 0x1.c272612672a3p+798
- insn wcgdb00:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = 0x1.745cd360987e5p-496 | -0x1.f3b404919f358p-321
- insn wcgdb00:
--  v_result = 8000000000000000 | 0000000000000000
-+  v_result = 8000000000000000 | --
-   v_arg1   = -0x1.9523565cd92d5p+643 | 0x1.253677d6d3be2p-556
- insn wcgdb00:
--  v_result = 7fffffffffffffff | 0000000000000000
-+  v_result = 7fffffffffffffff | --
-   v_arg1   = 0x1.b6eb576ec3e6ap+845 | -0x1.c7e102c503d91p+266
- insn wcgdb01:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.3d4319841f4d6p-1011 | -0x1.2feabf7dfc506p-680
- insn wcgdb01:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.6fb8d1cd8b32cp-843 | -0x1.50f6a6922f97ep+33
- insn wcgdb01:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.64a673daccf1ap-566 | -0x1.69ef9b1d01499p+824
- insn wcgdb01:
--  v_result = 8000000000000000 | 0000000000000000
-+  v_result = 8000000000000000 | --
-   v_arg1   = -0x1.3e2ddd862b4adp+1005 | -0x1.312466410271p+184
- insn wcgdb03:
--  v_result = 0000000000000001 | 0000000000000000
-+  v_result = 0000000000000001 | --
-   v_arg1   = 0x1.d594c3412a11p-953 | -0x1.a07393d34d77cp-224
- insn wcgdb03:
--  v_result = 8000000000000000 | 0000000000000000
-+  v_result = 8000000000000000 | --
-   v_arg1   = -0x1.f7a0dbcfd6e4cp+104 | -0x1.40f7cde7f2214p-702
- insn wcgdb03:
--  v_result = 8000000000000000 | 0000000000000000
-+  v_result = 8000000000000000 | --
-   v_arg1   = -0x1.40739c1574808p+560 | -0x1.970328ddf1b6ep-374
- insn wcgdb03:
--  v_result = 0000000000000001 | 0000000000000000
-+  v_result = 0000000000000001 | --
-   v_arg1   = 0x1.477653afd7048p-38 | 0x1.1eac2f8b2a93cp-384
- insn wcgdb04:
--  v_result = ffffffffe9479a7d | 0000000000000000
-+  v_result = ffffffffe9479a7d | --
-   v_arg1   = -0x1.6b865833eff3p+28 | 0x1.06e8cf1834d0ep-722
- insn wcgdb04:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = 0x1.eef0b2294a5cp-544 | -0x1.8e8b133ccda15p+752
- insn wcgdb04:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.f34e77e6b6698p-894 | -0x1.9f7ce1cb53bddp-896
- insn wcgdb04:
--  v_result = 7fffffffffffffff | 0000000000000000
-+  v_result = 7fffffffffffffff | --
-   v_arg1   = 0x1.95707a6d75db5p+1018 | -0x1.3b0c072d23011p-224
- insn wcgdb05:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.a9fb71160793p-968 | 0x1.05f601fe8123ap-986
- insn wcgdb05:
--  v_result = 8000000000000000 | 0000000000000000
-+  v_result = 8000000000000000 | --
-   v_arg1   = -0x1.0864159b94305p+451 | -0x1.d4647f5a78b7ep-599
- insn wcgdb05:
--  v_result = 7fffffffffffffff | 0000000000000000
-+  v_result = 7fffffffffffffff | --
-   v_arg1   = 0x1.37eadff8397c8p+432 | -0x1.15d896b6f6063p+464
- insn wcgdb05:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = 0x1.eb0812b0d677p-781 | 0x1.3117c5e0e288cp-202
- insn wcgdb06:
--  v_result = 0000000000000001 | 0000000000000000
-+  v_result = 0000000000000001 | --
-   v_arg1   = 0x1.6b88069167c0fp-662 | -0x1.70571d27e1279p+254
- insn wcgdb06:
--  v_result = 7fffffffffffffff | 0000000000000000
-+  v_result = 7fffffffffffffff | --
-   v_arg1   = 0x1.f6a6d6e883596p+260 | 0x1.0d578afaaa34ap+604
- insn wcgdb06:
--  v_result = 0000000000000001 | 0000000000000000
-+  v_result = 0000000000000001 | --
-   v_arg1   = 0x1.d91c7d13c4694p-475 | -0x1.ecf1f8529767bp+830
- insn wcgdb06:
--  v_result = 0000000000000001 | 0000000000000000
-+  v_result = 0000000000000001 | --
-   v_arg1   = 0x1.fac8dd3bb7af6p-101 | 0x1.fb8324a00fba8p+959
- insn wcgdb07:
--  v_result = 7fffffffffffffff | 0000000000000000
-+  v_result = 7fffffffffffffff | --
-   v_arg1   = 0x1.4b0fa18fa73c7p+111 | -0x1.08e7b17633a49p+61
- insn wcgdb07:
--  v_result = e636b693e39a1100 | 0000000000000000
-+  v_result = e636b693e39a1100 | --
-   v_arg1   = -0x1.9c9496c1c65efp+60 | 0x1.c4182ee728d76p-572
- insn wcgdb07:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = -0x1.819718032dff7p-303 | 0x1.a784c77ff6aa2p-622
- insn wcgdb07:
--  v_result = 7fffffffffffffff | 0000000000000000
-+  v_result = 7fffffffffffffff | --
-   v_arg1   = 0x1.978e8abfd83c2p+152 | 0x1.2531ebf451762p+315
- insn vclgdb00:
-   v_result = 0000000000000000 | 0000000000000000
-@@ -587,88 +587,88 @@ insn vclgdb07:
-   v_result = 0000000000000000 | 0000000000000000
-   v_arg1   = -0x1.137bbb51f08bdp+306 | 0x1.18d2a1063356p-795
- insn wclgdb00:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.e66f55dcc2639p-1013 | -0x1.733ee56929f3bp-304
- insn wclgdb00:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = 0x1.8802fd9ab740cp-986 | -0x1.64d4d2c7c145fp-1015
- insn wclgdb00:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = 0x1.a67209b8c407bp-645 | -0x1.6410ff9b1c801p+487
- insn wclgdb00:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.cb2febaefeb2dp+49 | 0x1.dee368b2ec375p-502
- insn wclgdb01:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = 0x1.5703db3c1b0e2p-728 | 0x1.068c4d51ea4ebp+617
- insn wclgdb01:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.ae350291e5b3ep+291 | 0x1.1b87bb09b6032p+376
- insn wclgdb01:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.c4666a710127ep+424 | -0x1.19e969b6c0076p+491
- insn wclgdb01:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.c892c5a4d103fp+105 | -0x1.d4f937cc76704p+749
- insn wclgdb03:
--  v_result = 0000000000000001 | 0000000000000000
-+  v_result = 0000000000000001 | --
-   v_arg1   = 0x1.81090d8fc663dp-111 | 0x1.337ec5e0f0904p+1
- insn wclgdb03:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.e787adc70b91p-593 | 0x1.db8d83196b53cp-762
- insn wclgdb03:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.6529307e907efp+389 | -0x1.3ea0d8d5b4dd2p+589
- insn wclgdb03:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.be701a158637p-385 | 0x1.c5a7f70cb8a09p+107
- insn wclgdb04:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.2f328571ab445p+21 | -0x1.dcc21fc82ba01p-930
- insn wclgdb04:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.06b69fcbb7bffp-415 | 0x1.6f9a13a0a827ap+915
- insn wclgdb04:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.738e549b38bcdp+479 | 0x1.a522edb999c9p-45
- insn wclgdb04:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = 0x1.7f9399d2bcf3bp-215 | -0x1.7bc35f2d69a7fp+818
- insn wclgdb05:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.fc542bdb707f6p+880 | -0x1.8521ebc93a25fp-969
- insn wclgdb05:
--  v_result = 1ce8d9951b8c8600 | 0000000000000000
-+  v_result = 1ce8d9951b8c8600 | --
-   v_arg1   = 0x1.ce8d9951b8c86p+60 | 0x1.92712589230e7p+475
- insn wclgdb05:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.8a297f60a0811p-156 | 0x1.102b79043d82cp-204
- insn wclgdb05:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = 0x1.beb9057e1401dp-196 | -0x1.820f18f830262p+15
- insn wclgdb06:
--  v_result = 0000000000000001 | 0000000000000000
-+  v_result = 0000000000000001 | --
-   v_arg1   = 0x1.c321a966ecb4dp-430 | -0x1.2f6a1a95ead99p-943
- insn wclgdb06:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.f1a86b4aed821p-56 | -0x1.1ee6717cc2d7fp-899
- insn wclgdb06:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.73ce49d89ecb9p-302 | 0x1.52663b975ed23p-716
- insn wclgdb06:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.3e9c2de97a292p+879 | 0x1.d34eed36f2eafp+960
- insn wclgdb07:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.4e6ec6ddc6a45p-632 | -0x1.6e564d0fec72bp+369
- insn wclgdb07:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.42e2c658e4c4dp+459 | -0x1.9f9dc0252e44p+85
- insn wclgdb07:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.fb40ac8cda3c1p-762 | 0x1.0e9ed614bc8f1p-342
- insn wclgdb07:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.c1f8b3c68e214p+118 | -0x1.1a26a49368b61p+756
- insn vfidb00:
-   v_arg1   = -0x1.38df4cf9d52dbp-545 | -0x1.049253d90dd92p+94
-@@ -1020,16 +1020,16 @@ insn vldeb:
-   v_result = -0x1.6f5fb2p+70 | -0x1.0d2df6p-107
- insn wldeb:
-   v_arg1   = -0x1.d26169729db2ap-435 | 0x1.d6fd080793e8cp+767
--  v_result = -0x1.9a4c2cp-54 | 0x0p+0
-+  v_result = -0x1.9a4c2cp-54 | --
- insn wldeb:
-   v_arg1   = -0x1.f4b59107fce61p-930 | 0x1.cdf2816e253f4p-168
--  v_result = -0x1.be96b2p-116 | 0x0p+0
-+  v_result = -0x1.be96b2p-116 | --
- insn wldeb:
-   v_arg1   = -0x1.9603a2997928cp-441 | -0x1.aada85e355a11p-767
--  v_result = -0x1.d2c074p-55 | 0x0p+0
-+  v_result = -0x1.d2c074p-55 | --
- insn wldeb:
-   v_arg1   = 0x1.25ccf5bd0e83p+620 | 0x1.e1635864ebb17p-88
--  v_result = 0x1.64b99ep+78 | 0x0p+0
-+  v_result = 0x1.64b99ep+78 | --
- insn vflcdb:
-   v_arg1   = 0x1.0ae6d82f76afp-166 | -0x1.e8fb1e03a7415p-191
-   v_result = -0x1.0ae6d82f76afp-166 | 0x1.e8fb1e03a7415p-191
-@@ -1044,16 +1044,16 @@ insn vflcdb:
-   v_result = -0x1.19520153d35b4p-301 | -0x1.ac5325cd23253p+396
- insn wflcdb:
-   v_arg1   = 0x1.ffd3eecfd54d7p-831 | -0x1.97854fa523a77p+146
--  v_result = -0x1.ffd3eecfd54d7p-831 | 0x0p+0
-+  v_result = -0x1.ffd3eecfd54d7p-831 | --
- insn wflcdb:
-   v_arg1   = -0x1.508ea45606447p-442 | 0x1.ae7f0e6cf9d2bp+583
--  v_result = 0x1.508ea45606447p-442 | 0x0p+0
-+  v_result = 0x1.508ea45606447p-442 | --
- insn wflcdb:
-   v_arg1   = 0x1.da8ab2188c21ap+94 | 0x1.78a9c152aa074p-808
--  v_result = -0x1.da8ab2188c21ap+94 | 0x0p+0
-+  v_result = -0x1.da8ab2188c21ap+94 | --
- insn wflcdb:
-   v_arg1   = -0x1.086882645e0c5p-1001 | -0x1.54e2de5af5a74p-262
--  v_result = 0x1.086882645e0c5p-1001 | 0x0p+0
-+  v_result = 0x1.086882645e0c5p-1001 | --
- insn vflndb:
-   v_arg1   = -0x1.5bec561d407dcp+819 | -0x1.a5773dadb7a2dp+935
-   v_result = -0x1.5bec561d407dcp+819 | -0x1.a5773dadb7a2dp+935
-@@ -1068,16 +1068,16 @@ insn vflndb:
-   v_result = -0x1.c5bc39a06d4e2p-259 | -0x1.c5e61ad849e77p-833
- insn wflndb:
-   v_arg1   = -0x1.e9f3e6d1beffap-117 | -0x1.d58cc8bf123b3p-714
--  v_result = -0x1.e9f3e6d1beffap-117 | 0x0p+0
-+  v_result = -0x1.e9f3e6d1beffap-117 | --
- insn wflndb:
-   v_arg1   = -0x1.3fc4ef2e7485ep-691 | 0x1.eb328986081efp-775
--  v_result = -0x1.3fc4ef2e7485ep-691 | 0x0p+0
-+  v_result = -0x1.3fc4ef2e7485ep-691 | --
- insn wflndb:
-   v_arg1   = -0x1.7146c5afdec16p+23 | -0x1.597fcfa1fab2p-708
--  v_result = -0x1.7146c5afdec16p+23 | 0x0p+0
-+  v_result = -0x1.7146c5afdec16p+23 | --
- insn wflndb:
-   v_arg1   = 0x1.03f8d7e9afe84p-947 | 0x1.9a10c3feb6b57p-118
--  v_result = -0x1.03f8d7e9afe84p-947 | 0x0p+0
-+  v_result = -0x1.03f8d7e9afe84p-947 | --
- insn vflpdb:
-   v_arg1   = 0x1.64ae59b6c762ep-407 | -0x1.fa7191ab21e86p+533
-   v_result = 0x1.64ae59b6c762ep-407 | 0x1.fa7191ab21e86p+533
-@@ -1092,16 +1092,16 @@ insn vflpdb:
-   v_result = 0x1.85fa2de1d492ap+170 | 0x1.ac36828822c11p-968
- insn wflpdb:
-   v_arg1   = 0x1.a6cf677640a73p-871 | 0x1.b6f1792385922p-278
--  v_result = 0x1.a6cf677640a73p-871 | 0x0p+0
-+  v_result = 0x1.a6cf677640a73p-871 | --
- insn wflpdb:
-   v_arg1   = -0x1.b886774f6d888p-191 | -0x1.6a2b08d735d22p-643
--  v_result = 0x1.b886774f6d888p-191 | 0x0p+0
-+  v_result = 0x1.b886774f6d888p-191 | --
- insn wflpdb:
-   v_arg1   = 0x1.5045d37d46f5fp+943 | -0x1.333a86ef2dcf6p-1013
--  v_result = 0x1.5045d37d46f5fp+943 | 0x0p+0
-+  v_result = 0x1.5045d37d46f5fp+943 | --
- insn wflpdb:
-   v_arg1   = 0x1.1e7bec6ada14dp+252 | 0x1.a70b3f3e24dap-153
--  v_result = 0x1.1e7bec6ada14dp+252 | 0x0p+0
-+  v_result = 0x1.1e7bec6ada14dp+252 | --
- insn vfadb:
-   v_arg1   = 0x1.5b1ad8e9f17c6p-294 | -0x1.ddd8300a0bf02p+122
-   v_arg2   = -0x1.9b49c31ca8ac6p+926 | 0x1.fdbc992926268p+677
-@@ -1121,19 +1121,19 @@ insn vfadb:
- insn wfadb:
-   v_arg1   = 0x1.3c5466cb80722p+489 | -0x1.11e1770053ca2p+924
-   v_arg2   = 0x1.d876cd721a726p-946 | 0x1.5c04ceb79c9bcp+1001
--  v_result = 0x1.3c5466cb80722p+489 | 0x0p+0
-+  v_result = 0x1.3c5466cb80722p+489 | --
- insn wfadb:
-   v_arg1   = 0x1.b0b142d6b76a3p+577 | 0x1.3146824e993a2p+432
-   v_arg2   = -0x1.f7f3b7582925fp-684 | -0x1.9700143c2b935p-837
--  v_result = 0x1.b0b142d6b76a2p+577 | 0x0p+0
-+  v_result = 0x1.b0b142d6b76a2p+577 | --
- insn wfadb:
-   v_arg1   = -0x1.8d65e15edabd6p+244 | 0x1.3be7fd08492d6p-141
-   v_arg2   = -0x1.5eef86490fb0ap+481 | 0x1.7b26c897cb6dfp+810
--  v_result = -0x1.5eef86490fb0ap+481 | 0x0p+0
-+  v_result = -0x1.5eef86490fb0ap+481 | --
- insn wfadb:
-   v_arg1   = -0x1.2dffa5b5f29p+34 | 0x1.71a026274602fp-881
-   v_arg2   = 0x1.4dad707287289p+756 | -0x1.1500d55807247p-616
--  v_result = 0x1.4dad707287288p+756 | 0x0p+0
-+  v_result = 0x1.4dad707287288p+756 | --
- insn vfsdb:
-   v_arg1   = 0x1.054fd9c4d4883p+644 | 0x1.45c90ed85bd7fp-780
-   v_arg2   = 0x1.f3bc7a611dadap+494 | -0x1.7c9e1e858ba5bp-301
-@@ -1153,19 +1153,19 @@ insn vfsdb:
- insn wfsdb:
-   v_arg1   = 0x1.9090dabf846e7p-648 | 0x1.1c4ab843a2d15p+329
-   v_arg2   = -0x1.a7ceb293690dep+316 | 0x1.22245954a20cp+42
--  v_result = 0x1.a7ceb293690dep+316 | 0x0p+0
-+  v_result = 0x1.a7ceb293690dep+316 | --
- insn wfsdb:
-   v_arg1   = 0x1.4e5347c27819p-933 | -0x1.56a30bda28351p-64
-   v_arg2   = -0x1.dedb9f3935b56p-155 | 0x1.8c5b6ed76816cp-522
--  v_result = 0x1.dedb9f3935b56p-155 | 0x0p+0
-+  v_result = 0x1.dedb9f3935b56p-155 | --
- insn wfsdb:
-   v_arg1   = 0x1.0ec4e562a015bp-491 | 0x1.3996381b52d9fp-686
-   v_arg2   = 0x1.1dcce4e81819p+960 | -0x1.32fa425e8fc08p-263
--  v_result = -0x1.1dcce4e81818fp+960 | 0x0p+0
-+  v_result = -0x1.1dcce4e81818fp+960 | --
- insn wfsdb:
-   v_arg1   = -0x1.587229f90f77dp-19 | 0x1.100d8eb8105e4p-784
-   v_arg2   = -0x1.afb4cce4c43ddp+530 | -0x1.6da7f05e7f512p-869
--  v_result = 0x1.afb4cce4c43dcp+530 | 0x0p+0
-+  v_result = 0x1.afb4cce4c43dcp+530 | --
- insn vfmdb:
-   v_arg1   = 0x1.892b425556c47p-124 | 0x1.38222404079dfp-656
-   v_arg2   = 0x1.af612ed2c342dp-267 | -0x1.1f735fd6ce768p-877
-@@ -1185,19 +1185,19 @@ insn vfmdb:
- insn wfmdb:
-   v_arg1   = -0x1.b992d950126a1p-683 | -0x1.9c1b22eb58c59p-497
-   v_arg2   = 0x1.b557a7d8e32c3p-25 | -0x1.f746b2ddafccep+227
--  v_result = -0x1.792f6fb13894ap-707 | 0x0p+0
-+  v_result = -0x1.792f6fb13894ap-707 | --
- insn wfmdb:
-   v_arg1   = -0x1.677a8c20a5a2fp+876 | 0x1.c03e7b97e8c0dp-645
-   v_arg2   = 0x1.dab44be430937p-1011 | -0x1.3f51352c67be9p-916
--  v_result = -0x1.4d4b0a1827064p-134 | 0x0p+0
-+  v_result = -0x1.4d4b0a1827064p-134 | --
- insn wfmdb:
-   v_arg1   = -0x1.da60f596ad0cep+254 | 0x1.52332e0650e33p+966
-   v_arg2   = 0x1.a042c52ed993cp+215 | 0x1.8f380c84aa133p+204
--  v_result = -0x1.81aca4bbcbd24p+470 | 0x0p+0
-+  v_result = -0x1.81aca4bbcbd24p+470 | --
- insn wfmdb:
-   v_arg1   = -0x1.83d17f11f6aa3p-469 | -0x1.98117efe89b9ep-361
-   v_arg2   = 0x1.8c445fd46d214p-701 | -0x1.f98118821821cp+596
--  v_result = -0x0p+0 | 0x0p+0
-+  v_result = -0x0p+0 | --
- insn vfddb:
-   v_arg1   = -0x1.ecbb48899e0f1p+969 | 0x1.caf175ab352p-20
-   v_arg2   = -0x1.9455d67f9f79dp+208 | 0x1.bc4a431b04a6fp+482
-@@ -1217,19 +1217,19 @@ insn vfddb:
- insn wfddb:
-   v_arg1   = 0x1.bd48489b60731p-114 | 0x1.a760dcf57b74fp-51
-   v_arg2   = -0x1.171f83409eeb6p-402 | -0x1.e159d1409bdc6p-972
--  v_result = -0x1.9864f1511f8cp+288 | 0x0p+0
-+  v_result = -0x1.9864f1511f8cp+288 | --
- insn wfddb:
-   v_arg1   = -0x1.120505ef4606p-637 | -0x1.83f6f775c0eb7p+272
-   v_arg2   = -0x1.d18ba3872fde1p+298 | 0x1.c60f8d191068cp-454
--  v_result = 0x1.2d5cdb15a686cp-936 | 0x0p+0
-+  v_result = 0x1.2d5cdb15a686cp-936 | --
- insn wfddb:
-   v_arg1   = 0x1.f637f7f8c790fp-97 | -0x1.7bdce4d74947p+189
-   v_arg2   = -0x1.1c8f2d1b3a2edp-218 | -0x1.55fdfd1840241p-350
--  v_result = -0x1.c3d0799c1420fp+121 | 0x0p+0
-+  v_result = -0x1.c3d0799c1420fp+121 | --
- insn wfddb:
-   v_arg1   = -0x1.c63b7b2eee253p+250 | 0x1.dfd9dcd8b823fp-125
-   v_arg2   = 0x1.094a1f1f87e0cp+629 | 0x1.eeaa23c0d7843p-814
--  v_result = -0x1.b653a10ebdeccp-379 | 0x0p+0
-+  v_result = -0x1.b653a10ebdeccp-379 | --
- insn vfsqdb:
-   v_arg1   = 0x1.f60db25f7066p-703 | -0x1.d43509abca8c3p+631
-   v_result = 0x1.fb009ab25ec11p-352 | nan
-@@ -1244,16 +1244,16 @@ insn vfsqdb:
-   v_result = 0x1.833dba0954bccp+249 | nan
- insn wfsqdb:
-   v_arg1   = 0x1.71af4e7f64978p+481 | -0x1.3429dc60011d7p-879
--  v_result = 0x1.b30fc65551133p+240 | 0x0p+0
-+  v_result = 0x1.b30fc65551133p+240 | --
- insn wfsqdb:
-   v_arg1   = 0x1.5410db1c5f403p+173 | 0x1.97fa6581e692fp+108
--  v_result = 0x1.a144f43a592c1p+86 | 0x0p+0
-+  v_result = 0x1.a144f43a592c1p+86 | --
- insn wfsqdb:
-   v_arg1   = -0x1.5838027725afep+6 | 0x1.ac61529c11f38p+565
--  v_result = nan | 0x0p+0
-+  v_result = nan | --
- insn wfsqdb:
-   v_arg1   = -0x1.159e341dcc06ep-439 | 0x1.ed54ce5481ba5p-574
--  v_result = nan | 0x0p+0
-+  v_result = nan | --
- insn vfmadb:
-   v_arg1   = -0x1.eb00a5c503d75p+538 | 0x1.89fae603ddc07p+767
-   v_arg2   = -0x1.71c72712c3957p+715 | 0x1.1bd5773442feap+762
-@@ -1278,22 +1278,22 @@ insn wfmadb:
-   v_arg1   = 0x1.1cc5b10a14d54p+668 | -0x1.686407390f7d1p+616
-   v_arg2   = -0x1.bf34549e73246p+676 | -0x1.dc5a34cc470f3p+595
-   v_arg3   = -0x1.95e0fdcf13974p-811 | -0x1.79c7cc1a8ec83p-558
--  v_result = -0x1.fffffffffffffp+1023 | 0x0p+0
-+  v_result = -0x1.fffffffffffffp+1023 | --
- insn wfmadb:
-   v_arg1   = 0x1.138bc1a5d75f8p+713 | -0x1.e226ebba2fe54p+381
-   v_arg2   = -0x1.081ebb7cc3414p-772 | 0x1.369d99e174fc3p+922
-   v_arg3   = -0x1.0671c682a5d0cp-1016 | 0x1.03c9530dd0377p+378
--  v_result = -0x1.1c4933e117d95p-59 | 0x0p+0
-+  v_result = -0x1.1c4933e117d95p-59 | --
- insn wfmadb:
-   v_arg1   = -0x1.166f0b1fad67bp+64 | -0x1.e9ee8d32e1069p-452
-   v_arg2   = -0x1.4a235bdd109e2p-65 | 0x1.bacaa96fc7e81p-403
-   v_arg3   = -0x1.d2e19acf7c4bdp+99 | 0x1.f901130f685adp-963
--  v_result = -0x1.d2e19acf7c4bcp+99 | 0x0p+0
-+  v_result = -0x1.d2e19acf7c4bcp+99 | --
- insn wfmadb:
-   v_arg1   = -0x1.77d7bfec863d2p-988 | -0x1.b68029700c6b1p-206
-   v_arg2   = -0x1.aca05ad00aec1p+737 | 0x1.ac746bd7e216bp+51
-   v_arg3   = 0x1.17342292078b4p+188 | -0x1.49efaf9392301p+555
--  v_result = 0x1.17342292078b4p+188 | 0x0p+0
-+  v_result = 0x1.17342292078b4p+188 | --
- insn vfmsdb:
-   v_arg1   = -0x1.a1b218e84e61p+34 | 0x1.b220f0d144daep-111
-   v_arg2   = 0x1.564fcc2527961p-265 | 0x1.ea85a4154721ep+733
-@@ -1318,22 +1318,22 @@ insn wfmsdb:
-   v_arg1   = -0x1.7499a639673a6p-100 | -0x1.2a0d737e6cb1cp-207
-   v_arg2   = -0x1.01ad4670a7aa3p-911 | 0x1.f94385e1021e8p+317
-   v_arg3   = 0x1.aa42b2bb17af9p+982 | 0x1.c550e471711p+786
--  v_result = -0x1.aa42b2bb17af8p+982 | 0x0p+0
-+  v_result = -0x1.aa42b2bb17af8p+982 | --
- insn wfmsdb:
-   v_arg1   = 0x1.76840f99b431ep+500 | -0x1.989a500c92c08p+594
-   v_arg2   = 0x1.33c657cb8385cp-84 | -0x1.2c795ad92ce17p+807
-   v_arg3   = -0x1.ee58a39f02d54p-351 | -0x1.18695ed9a280ap+48
--  v_result = 0x1.c242894a0068p+416 | 0x0p+0
-+  v_result = 0x1.c242894a0068p+416 | --
- insn wfmsdb:
-   v_arg1   = -0x1.16db07e054a65p-469 | -0x1.3a627ab99c6e4p+689
-   v_arg2   = 0x1.17872eae826e5p-538 | 0x1.44ed513fb5873p-929
-   v_arg3   = 0x1.5ca912008e077p-217 | -0x1.982a6f7359876p-23
--  v_result = -0x1.5ca912008e077p-217 | 0x0p+0
-+  v_result = -0x1.5ca912008e077p-217 | --
- insn wfmsdb:
-   v_arg1   = -0x1.d315f4a932c6p+122 | 0x1.616a04493e143p+513
-   v_arg2   = -0x1.cf1cd3516f23fp+552 | 0x1.7121749c3932cp-750
-   v_arg3   = 0x1.dc26d92304d7fp-192 | -0x1.1fc3cca9ec20ep+371
--  v_result = 0x1.a67ca6ba395bcp+675 | 0x0p+0
-+  v_result = 0x1.a67ca6ba395bcp+675 | --
- insn wfcdb:
-   v_arg1   = 0x1.302001b736011p-633 | -0x1.72d5300225c97p-468
-   v_arg2   = -0x1.8c007c5aba108p-17 | -0x1.bb3f9ae136acdp+569
-@@ -1383,19 +1383,19 @@ insn vfcedb:
-   v_arg1   = 0x1.d8e5c9930c19dp+623 | -0x1.cf1facff4e194p-605
-   v_arg2   = -0x1.ed6ba02646d0dp+441 | -0x1.2d677e710620bp+810
- insn wfcedb:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.a252009e1a12cp-442 | 0x1.4dc608268bb29p-513
-   v_arg2   = -0x1.81020aa1a36e6p-687 | -0x1.300e64ce414f1p-899
- insn wfcedb:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = 0x1.cec439a8d4781p-175 | -0x1.d20e3b281d599p+893
-   v_arg2   = 0x1.ca17cf16cf0aap-879 | 0x1.61506f8596092p+545
- insn wfcedb:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = 0x1.0659f5f24a004p+877 | 0x1.fc46867ed0338p-680
-   v_arg2   = -0x1.1d6849587155ep-1010 | -0x1.f68171edc235fp+575
- insn wfcedb:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = 0x1.dc88a0d46ad79p-816 | 0x1.245140dcaed79p+851
-   v_arg2   = 0x1.b33e977c7b3ep-818 | -0x1.04319d7c69367p+787
- insn vfcedbs:
-@@ -1419,22 +1419,22 @@ insn vfcedbs:
-   v_arg2   = 0x1.ae2c06ea88ff4p+332 | -0x1.f668ce4f8ef9ap+821
-   r_result = 0000000000000003
- insn wfcedbs:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = 0x1.645261bf86b1fp-996 | 0x1.abd13c95397aap+992
-   v_arg2   = -0x1.ba09e8fc66a8cp+113 | 0x1.75dbfe92c16c4p-786
-   r_result = 0000000000000003
- insn wfcedbs:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.d02831d003e7dp+415 | -0x1.611a9dfd10f36p-80
-   v_arg2   = -0x1.10bda62f4647p+723 | 0x1.cc47af6653378p-614
-   r_result = 0000000000000003
- insn wfcedbs:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = 0x1.f168f32f84178p-321 | -0x1.79a2a0b9549d1p-136
-   v_arg2   = 0x1.41e19d1cfa692p+11 | -0x1.2a0ed6e7fd517p-453
-   r_result = 0000000000000003
- insn wfcedbs:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.76a9144ee26c5p+188 | -0x1.386aaea2d9cddp-542
-   v_arg2   = 0x1.810fcf222efc4p-999 | -0x1.ce90a9a43e2a1p+80
-   r_result = 0000000000000003
-@@ -1455,19 +1455,19 @@ insn vfchdb:
-   v_arg1   = 0x1.82be31fb88a2dp+946 | -0x1.7ca9e9ff31953p-931
-   v_arg2   = 0x1.fe75a1052beccp+490 | 0x1.179d18543d678p-255
- insn wfchdb:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.0af85d8d8d609p-464 | -0x1.9f639a686e0fep+203
-   v_arg2   = -0x1.3142b77b55761p-673 | 0x1.ca9c474339da1p+472
- insn wfchdb:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = -0x1.6cf16959a022bp+213 | 0x1.445606e4363e1p+942
-   v_arg2   = -0x1.8c343201bbd2p+939 | -0x1.e5095ad0c37a4p-434
- insn wfchdb:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.36b4fc9cf5bdap-52 | -0x1.f1fd95cbcd533p+540
-   v_arg2   = 0x1.5a2362891c9edp-175 | -0x1.e1f68c319e5d2p+58
- insn wfchdb:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.11c6489f544bbp+811 | 0x1.262a740ec3d47p+456
-   v_arg2   = -0x1.d9394d354e989p-154 | 0x1.cc21b3094391ap-972
- insn vfchdbs:
-@@ -1491,22 +1491,22 @@ insn vfchdbs:
-   v_arg2   = 0x1.e426748435a76p+370 | 0x1.8702527d17783p-871
-   r_result = 0000000000000003
- insn wfchdbs:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.6c51b9f6442c8p+639 | 0x1.1e6b37adff703p+702
-   v_arg2   = 0x1.0cba9c1c75e43p+520 | -0x1.145d44ed90967p+346
-   r_result = 0000000000000000
- insn wfchdbs:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.7b3dd643bf36bp+816 | -0x1.61ce7bfb9307ap-683
-   v_arg2   = -0x1.f2c998dc15c9ap-776 | 0x1.e16397f2dcdf5p+571
-   r_result = 0000000000000000
- insn wfchdbs:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.cc3be81884e0ap-865 | -0x1.8b353bd41064p+820
-   v_arg2   = -0x1.2c1bafaafdd4ep-34 | -0x1.24666808ab16ep-435
-   r_result = 0000000000000000
- insn wfchdbs:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.c3de33d3b673ap+554 | 0x1.d39ed71e53096p-798
-   v_arg2   = -0x1.c1e8f7b3c001p-828 | 0x1.22e2cf797fabp-787
-   r_result = 0000000000000000
-@@ -1527,19 +1527,19 @@ insn vfchedb:
-   v_arg1   = -0x1.6c5599e7ba923p+829 | -0x1.5d1a1191ed6eap-994
-   v_arg2   = -0x1.555c8775bc4d2p-478 | -0x1.4aa6a2c82319cp+493
- insn wfchedb:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.ae6cad07b0f3ep-232 | -0x1.2ed61a43f3b99p-74
-   v_arg2   = -0x1.226f7cddbde13p-902 | -0x1.790d1d6febbf8p+336
- insn wfchedb:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.20eb8eac3711dp-385 | 0x1.ef71d3312d7e1p+739
-   v_arg2   = 0x1.7a3ba08c5a0bdp-823 | -0x1.a7845ccaa544dp-129
- insn wfchedb:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.97ebdbc057be8p+824 | 0x1.2b7798b063cd6p+237
-   v_arg2   = 0x1.cdb87a6074294p-81 | -0x1.074c902b19bccp-416
- insn wfchedb:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.82deebf9ff023p+937 | 0x1.56c5adcf9d4abp-672
-   v_arg2   = -0x1.311ce49bc9439p+561 | 0x1.c8e1c512d8544p+103
- insn vfchedbs:
-@@ -1563,22 +1563,22 @@ insn vfchedbs:
-   v_arg2   = -0x1.47f5dfc7a5bcp-569 | 0x1.5877ef33664a3p-758
-   r_result = 0000000000000003
- insn wfchedbs:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.a7370ccfd9e49p+505 | 0x1.c6b2385850ca2p-591
-   v_arg2   = 0x1.984f4fcd338b1p+675 | -0x1.feb996c821232p-39
-   r_result = 0000000000000003
- insn wfchedbs:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.641878612dd2p+207 | 0x1.b35e3292db7f6p+567
-   v_arg2   = -0x1.18a87f209e96bp+299 | -0x1.3d598f3612d8ap+1016
-   r_result = 0000000000000000
- insn wfchedbs:
--  v_result = ffffffffffffffff | 0000000000000000
-+  v_result = ffffffffffffffff | --
-   v_arg1   = 0x1.cfc2cda244153p+404 | 0x1.d8b2b28e9d8d7p+276
-   v_arg2   = 0x1.3517b8c7a59a1p-828 | 0x1.6096fab7003ccp-415
-   r_result = 0000000000000000
- insn wfchedbs:
--  v_result = 0000000000000000 | 0000000000000000
-+  v_result = 0000000000000000 | --
-   v_arg1   = -0x1.54d656f033e56p-603 | -0x1.95ad0e2088967p+254
-   v_arg2   = 0x1.4cb319db206e4p-614 | 0x1.b41cd9e3739b6p-862
-   r_result = 0000000000000003
diff --git a/valgrind-3.16.1-sched_getsetattr.patch b/valgrind-3.16.1-sched_getsetattr.patch
deleted file mode 100644
index b95267d..0000000
--- a/valgrind-3.16.1-sched_getsetattr.patch
+++ /dev/null
@@ -1,201 +0,0 @@
-commit a53adb79711ccfc76a4ee32b20253045cdab55c7
-Author: Mark Wielaard <mark@klomp.org>
-Date:   Mon Jul 27 16:36:17 2020 +0200
-
-    Handle linux syscalls sched_getattr and sched_setattr
-    
-    The only "special" thing about these syscalls is that the given
-    struct sched_attr determines its own size for future expansion.
-    
-    Original fix by "ISHIKAWA,chiaki" <ishikawa@yk.rim.or.jp>
-    
-    https://bugs.kde.org/show_bug.cgi?id=369029
-
-diff --git a/coregrind/m_syswrap/priv_syswrap-linux.h b/coregrind/m_syswrap/priv_syswrap-linux.h
-index cdc73c1e6..eb0b320ca 100644
---- a/coregrind/m_syswrap/priv_syswrap-linux.h
-+++ b/coregrind/m_syswrap/priv_syswrap-linux.h
-@@ -227,6 +227,8 @@ DECL_TEMPLATE(linux, sys_fremovexattr);
- // syscalls.
- DECL_TEMPLATE(linux, sys_sched_setparam);
- DECL_TEMPLATE(linux, sys_sched_getparam);
-+DECL_TEMPLATE(linux, sys_sched_setattr);
-+DECL_TEMPLATE(linux, sys_sched_getattr);
- DECL_TEMPLATE(linux, sys_sched_setscheduler);
- DECL_TEMPLATE(linux, sys_sched_getscheduler);
- DECL_TEMPLATE(linux, sys_sched_yield);
-diff --git a/coregrind/m_syswrap/syswrap-amd64-linux.c b/coregrind/m_syswrap/syswrap-amd64-linux.c
-index 28d90135a..d6f3eb910 100644
---- a/coregrind/m_syswrap/syswrap-amd64-linux.c
-+++ b/coregrind/m_syswrap/syswrap-amd64-linux.c
-@@ -846,9 +846,8 @@ static SyscallTableEntry syscall_table[] = {
-    LINX_(__NR_process_vm_writev, sys_process_vm_writev),// 311
-    LINX_(__NR_kcmp,              sys_kcmp),             // 312
-    LINX_(__NR_finit_module,      sys_finit_module),     // 313
--//   LIN__(__NR_sched_setattr,     sys_ni_syscall),       // 314
--
--//   LIN__(__NR_sched_getattr,     sys_ni_syscall),       // 315
-+   LINX_(__NR_sched_setattr,     sys_sched_setattr),    // 314
-+   LINXY(__NR_sched_getattr,     sys_sched_getattr),    // 315
-    LINX_(__NR_renameat2,         sys_renameat2),        // 316
- //   LIN__(__NR_seccomp,           sys_ni_syscall),       // 317
-    LINXY(__NR_getrandom,         sys_getrandom),        // 318
-diff --git a/coregrind/m_syswrap/syswrap-arm-linux.c b/coregrind/m_syswrap/syswrap-arm-linux.c
-index 579542785..70700e53f 100644
---- a/coregrind/m_syswrap/syswrap-arm-linux.c
-+++ b/coregrind/m_syswrap/syswrap-arm-linux.c
-@@ -1009,6 +1009,8 @@ static SyscallTableEntry syscall_main_table[] = {
-    LINXY(__NR_process_vm_readv,  sys_process_vm_readv), // 376
-    LINX_(__NR_process_vm_writev, sys_process_vm_writev),// 377
- 
-+   LINX_(__NR_sched_setattr,     sys_sched_setattr),    // 380
-+   LINXY(__NR_sched_getattr,     sys_sched_getattr),    // 381
-    LINX_(__NR_renameat2,         sys_renameat2),        // 382
- 
-    LINXY(__NR_getrandom,         sys_getrandom),        // 384
-diff --git a/coregrind/m_syswrap/syswrap-arm64-linux.c b/coregrind/m_syswrap/syswrap-arm64-linux.c
-index 81e01456f..acca02442 100644
---- a/coregrind/m_syswrap/syswrap-arm64-linux.c
-+++ b/coregrind/m_syswrap/syswrap-arm64-linux.c
-@@ -806,8 +806,8 @@ static SyscallTableEntry syscall_main_table[] = {
-    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_ni_syscall),        // 274
--   //   (__NR_sched_getattr,     sys_ni_syscall),        // 275
-+   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_ni_syscall),        // 277
-    LINXY(__NR_getrandom,         sys_getrandom),         // 278
-diff --git a/coregrind/m_syswrap/syswrap-linux.c b/coregrind/m_syswrap/syswrap-linux.c
-index 5b5b7eee6..56be3032d 100644
---- a/coregrind/m_syswrap/syswrap-linux.c
-+++ b/coregrind/m_syswrap/syswrap-linux.c
-@@ -3677,6 +3677,41 @@ POST(sys_sched_getparam)
-    POST_MEM_WRITE( ARG2, sizeof(struct vki_sched_param) );
- }
- 
-+PRE(sys_sched_setattr)
-+{
-+   struct vki_sched_attr *attr;
-+   PRINT("sched_setattr ( %ld, %#" FMT_REGWORD "x, %#"
-+         FMT_REGWORD "x )", SARG1, ARG2, ARG3 );
-+   PRE_REG_READ3(long, "sched_setattr",
-+                 vki_pid_t, pid, struct sched_attr *, p, unsigned int, flags);
-+   /* We need to be able to read at least the size field.  */
-+   PRE_MEM_READ( "sched_setattr(attr->size)", ARG2, sizeof(vki_uint32_t) );
-+   attr = (struct vki_sched_attr *)(Addr)ARG2;
-+   if (ML_(safe_to_deref)(attr,sizeof(vki_uint32_t)))
-+      PRE_MEM_READ( "sched_setattr(attr)", (Addr)attr, attr->size);
-+}
-+
-+PRE(sys_sched_getattr)
-+{
-+   struct vki_sched_attr *attr;
-+   PRINT("sched_getattr ( %ld, %#" FMT_REGWORD "x, %ld, %#"
-+         FMT_REGWORD "x )", SARG1, ARG2, ARG3, ARG4 );
-+   PRE_REG_READ4(long, "sched_getattr",
-+                 vki_pid_t, pid, struct sched_attr *, p,
-+                 unsigned int, size, unsigned int, flags);
-+   /* We need to be able to read at least the size field.  */
-+   PRE_MEM_READ( "sched_setattr(attr->size)", ARG2, sizeof(vki_uint32_t) );
-+   /* And the kernel needs to be able to write to the whole struct size. */
-+   attr = (struct vki_sched_attr *)(Addr)ARG2;
-+   if (ML_(safe_to_deref)(attr,sizeof(vki_uint32_t)))
-+      PRE_MEM_WRITE( "sched_setattr(attr)", (Addr)attr, attr->size);
-+}
-+POST(sys_sched_getattr)
-+{
-+   struct vki_sched_attr *attr = (struct vki_sched_attr *)(Addr)ARG2;
-+   POST_MEM_WRITE( (Addr)attr, attr->size );
-+}
-+
- PRE(sys_sched_getscheduler)
- {
-    PRINT("sys_sched_getscheduler ( %ld )", SARG1);
-diff --git a/coregrind/m_syswrap/syswrap-ppc32-linux.c b/coregrind/m_syswrap/syswrap-ppc32-linux.c
-index eed12a1bc..c19cb9e0e 100644
---- a/coregrind/m_syswrap/syswrap-ppc32-linux.c
-+++ b/coregrind/m_syswrap/syswrap-ppc32-linux.c
-@@ -1016,6 +1016,9 @@ static SyscallTableEntry syscall_table[] = {
-    LINXY(__NR_process_vm_readv,  sys_process_vm_readv), // 351
-    LINX_(__NR_process_vm_writev, sys_process_vm_writev),// 352
- 
-+   LINX_(__NR_sched_setattr,     sys_sched_setattr),    // 355
-+   LINXY(__NR_sched_getattr,     sys_sched_getattr),    // 356
-+
-    LINXY(__NR_getrandom,         sys_getrandom),        // 359
-    LINXY(__NR_memfd_create,      sys_memfd_create),     // 360
- 
-diff --git a/coregrind/m_syswrap/syswrap-ppc64-linux.c b/coregrind/m_syswrap/syswrap-ppc64-linux.c
-index d58200b49..b6422a765 100644
---- a/coregrind/m_syswrap/syswrap-ppc64-linux.c
-+++ b/coregrind/m_syswrap/syswrap-ppc64-linux.c
-@@ -998,6 +998,8 @@ static SyscallTableEntry syscall_table[] = {
-    LINXY(__NR_process_vm_readv,  sys_process_vm_readv), // 351
-    LINX_(__NR_process_vm_writev, sys_process_vm_writev),// 352
- 
-+   LINX_(__NR_sched_setattr,     sys_sched_setattr),    // 355
-+   LINXY(__NR_sched_getattr,     sys_sched_getattr),    // 356
-    LINX_(__NR_renameat2,         sys_renameat2),        // 357
- 
-    LINXY(__NR_getrandom,         sys_getrandom),        // 359
-diff --git a/coregrind/m_syswrap/syswrap-s390x-linux.c b/coregrind/m_syswrap/syswrap-s390x-linux.c
-index a0a330aa2..3427fee16 100644
---- a/coregrind/m_syswrap/syswrap-s390x-linux.c
-+++ b/coregrind/m_syswrap/syswrap-s390x-linux.c
-@@ -825,8 +825,8 @@ static SyscallTableEntry syscall_table[] = {
-    LINX_(__NR_kcmp, sys_kcmp),                                        // 343
- // ?????(__NR_finit_module, ),                                        // 344
- 
--// ?????(__NR_sched_setattr, ),                                       // 345
--// ?????(__NR_sched_getattr, ),                                       // 346
-+   LINX_(__NR_sched_setattr, sys_sched_setattr),                      // 345
-+   LINXY(__NR_sched_getattr, sys_sched_getattr),                      // 346
-    LINX_(__NR_renameat2, sys_renameat2),                              // 347
- // ?????(__NR_seccomp, ),                                             // 348
-    LINXY(__NR_getrandom, sys_getrandom),                              // 349
-diff --git a/coregrind/m_syswrap/syswrap-x86-linux.c b/coregrind/m_syswrap/syswrap-x86-linux.c
-index 332ed0bf2..b59d96f37 100644
---- a/coregrind/m_syswrap/syswrap-x86-linux.c
-+++ b/coregrind/m_syswrap/syswrap-x86-linux.c
-@@ -1580,8 +1580,8 @@ static SyscallTableEntry syscall_table[] = {
-    LINX_(__NR_kcmp,              sys_kcmp),             // 349
- 
- //   LIN__(__NR_finit_module,      sys_ni_syscall),       // 350
--//   LIN__(__NR_sched_setattr,     sys_ni_syscall),       // 351
--//   LIN__(__NR_sched_getattr,     sys_ni_syscall),       // 352
-+   LINX_(__NR_sched_setattr,     sys_sched_setattr),    // 351
-+   LINXY(__NR_sched_getattr,     sys_sched_getattr),    // 352
-    LINX_(__NR_renameat2,         sys_renameat2),        // 353
- //   LIN__(__NR_seccomp,           sys_ni_syscall),       // 354
- 
-diff --git a/include/vki/vki-linux.h b/include/vki/vki-linux.h
-index 75b583165..ef93b9258 100644
---- a/include/vki/vki-linux.h
-+++ b/include/vki/vki-linux.h
-@@ -410,6 +410,23 @@ struct vki_sched_param {
- 	int sched_priority;
- };
- 
-+struct vki_sched_attr {
-+	vki_uint32_t size;
-+	vki_uint32_t sched_policy;
-+	vki_uint64_t sched_flags;
-+
-+	/* SCHED_NORMAL, SCHED_BATCH */
-+	vki_int32_t sched_nice;
-+
-+	/* SCHED_FIFO, SCHED_RR */
-+	vki_uint32_t sched_priority;
-+
-+	/* SCHED_DEADLINE */
-+	vki_uint64_t sched_runtime;
-+	vki_uint64_t sched_deadline;
-+	vki_uint64_t sched_period;
-+};
-+
- #define VKI_TASK_COMM_LEN 16
- 
- //----------------------------------------------------------------------
diff --git a/valgrind-3.16.1-stxsibx-stxsihx.patch b/valgrind-3.16.1-stxsibx-stxsihx.patch
deleted file mode 100644
index c94ad91..0000000
--- a/valgrind-3.16.1-stxsibx-stxsihx.patch
+++ /dev/null
@@ -1,63 +0,0 @@
-diff --git a/VEX/priv/guest_ppc_toIR.c b/VEX/priv/guest_ppc_toIR.c
-index c9c058a7a..d726d63de 100644
---- a/VEX/priv/guest_ppc_toIR.c
-+++ b/VEX/priv/guest_ppc_toIR.c
-@@ -25671,49 +25671,29 @@ dis_vx_store ( UInt prefix, UInt theInstr )
- 
-    case 0x38D: // stxsibx
-    {
--      IRExpr *stored_word;
--      IRTemp byte_to_store = newTemp( Ity_I64 );
-+      IRTemp byte_to_store = newTemp( Ity_I8 );
- 
-       DIP("stxsibx %u,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
- 
--      /* Can't store just a byte, need to fetch the word at EA merge data
--       * and store.
--       */
--      stored_word = load( Ity_I64, mkexpr( EA ) );
--      assign( byte_to_store, binop( Iop_And64,
-+      assign( byte_to_store, unop( Iop_64to8,
-                                     unop( Iop_V128HIto64,
--                                          mkexpr( vS ) ),
--                                    mkU64( 0xFF ) ) );
-+                                          mkexpr( vS ) ) ) );
- 
--      store( mkexpr( EA ), binop( Iop_Or64,
--                                  binop( Iop_And64,
--                                         stored_word,
--                                         mkU64( 0xFFFFFFFFFFFFFF00 ) ),
--                                  mkexpr( byte_to_store ) ) );
-+      store( mkexpr( EA ), mkexpr( byte_to_store ) );
-       break;
-    }
- 
-    case 0x3AD: // stxsihx
-    {
--      IRExpr *stored_word;
--      IRTemp byte_to_store = newTemp( Ity_I64 );
-+      IRTemp hword_to_store = newTemp( Ity_I16 );
- 
-       DIP("stxsihx %u,r%u,r%u\n", (UInt)XS, rA_addr, rB_addr);
- 
--      /* Can't store just a halfword, need to fetch the word at EA merge data
--       * and store.
--       */
--      stored_word = load( Ity_I64, mkexpr( EA ) );
--      assign( byte_to_store, binop( Iop_And64,
--                                    unop( Iop_V128HIto64,
--                                          mkexpr( vS ) ),
--                                    mkU64( 0xFFFF ) ) );
-+      assign( hword_to_store, unop( Iop_64to16,
-+                                    unop( Iop_V128HIto64,
-+                                          mkexpr( vS ) ) ) );
- 
--      store( mkexpr( EA ), binop( Iop_Or64,
--                                  binop( Iop_And64,
--                                         stored_word,
--                                         mkU64( 0xFFFFFFFFFFFF0000 ) ),
--                                  mkexpr( byte_to_store ) ) );
-+      store( mkexpr( EA ), mkexpr( hword_to_store ) );
-       break;
-    }
- 
diff --git a/valgrind.spec b/valgrind.spec
index b53b7ac..ae44977 100644
--- a/valgrind.spec
+++ b/valgrind.spec
@@ -2,8 +2,8 @@
 
 Summary: Tool for finding memory management bugs in programs
 Name: %{?scl_prefix}valgrind
-Version: 3.16.1
-Release: 20%{?dist}
+Version: 3.17.0
+Release: 0.1.RC1%{?dist}
 Epoch: 1
 License: GPLv2+
 URL: http://www.valgrind.org/
@@ -71,7 +71,7 @@ URL: http://www.valgrind.org/
 # So those will already have their full symbol table.
 %undefine _include_minidebuginfo
 
-Source0: ftp://sourceware.org/pub/valgrind/valgrind-%{version}.tar.bz2
+Source0: ftp://sourceware.org/pub/valgrind/valgrind-%{version}.RC1.tar.bz2
 
 # Needs investigation and pushing upstream
 Patch1: valgrind-3.9.0-cachegrind-improvements.patch
@@ -82,81 +82,11 @@ Patch2: valgrind-3.9.0-helgrind-race-supp.patch
 # Make ld.so supressions slightly less specific.
 Patch3: valgrind-3.9.0-ldso-supp.patch
 
-# We want all executables and libraries in libexec instead of lib
-# so they are only available for valgrind usage itself and so the
-# same directory is used independent of arch.
-Patch4: valgrind-3.16.0-pkglibexecdir.patch
-
 # Add some stack-protector
-Patch5: valgrind-3.16.0-some-stack-protector.patch
+Patch4: valgrind-3.16.0-some-stack-protector.patch
 
 # Add some -Wl,z,now.
-Patch6: valgrind-3.16.0-some-Wl-z-now.patch
-
-# KDE#422174  unhandled instruction bytes: 0x48 0xE9 (REX prefix JMP instr)
-Patch7: valgrind-3.16.1-REX-prefix-JMP.patch
-
-# KDE#422623  epoll_ctl warns for uninit padding on non-amd64 64bit arches
-Patch8: valgrind-3.16.1-epoll.patch
-
-# KDE#369029  handle linux syscalls sched_getattr and sched_setattr
-Patch9: valgrind-3.16.1-sched_getsetattr.patch
-
-# KDE#415293  Incorrect call-graph tracking due to new _dl_runtime_resolve*
-Patch10: valgrind-3.16.1-dl_runtime_resolve.patch
-
-# KDE#427787  Support new faccessat2 linux syscall (439)
-Patch11: valgrind-3.16.1-faccessat2.patch
-
-# KDE#427931 gdbserver_tests/nlcontrolc.vgtest hangs on fedora rawhide
-Patch12: valgrind-3.16.1-gdbserver_nlcontrolc.patch
-
-# KDE#427870 lmw, lswi and related PowerPC insns aren't allowed on ppc64le
-Patch13: valgrind-3.16.1-PPC64BE-lsw.patch
-
-# KDE#428909 helgrind: need to intercept duplicate libc definitions
-Patch14: valgrind-3.16.1-pthread-intercept.patch
-
-# KDE#428648 s390_emit_load_mem panics due to 20-bit offset for vector load
-Patch15: valgrind-3.16.1-s390_emit_load_mem.patch
-
-# KDE#133812 s390x: z14 vector instructions not implemented
-Patch16: valgrind-3.16.1-s390x-z14-vector.patch
-
-# KDE#430354 ppc stxsibx and stxsihx instructions write too much data
-Patch17: valgrind-3.16.1-stxsibx-stxsihx.patch
-
-# KDE#426014 arm64: implement fmadd and fmsub as Iop_MAdd/Sub
-# KDE#430485 expr_is_guardable doesn't handle Iex_Qop
-Patch18: valgrind-3.16.1-arm64-fma.patch
-
-# KDE#397605 Add support for Linux FICLONE ioctl
-Patch19: valgrind-3.16.1-ficlone.patch
-
-# rhbz#1909415 valgrind makes false complaint about strcmp() on aarch64
-# upstream git commit 359b98828
-Patch20: valgrind-3.16.1-arm64-expensive-cmp.patch
-
-# KDE#431157 PPC_FEATURE2_SCV needs to be masked in AT_HWCAP2
-Patch21: valgrind-3.16.1-ppc64-scv-hwcap.patch
-
-# KDE#432102 Support DWARF5
-Patch22: valgrind-3.16.1-dwarf5.patch
-
-# KDE#410743 shmat() calls for 32-bit programs fail when running in 64-bit
-# RHBZ#1909548 shmctl(IPC_STAT) doesn't set shm_nattch on aarch64
-Patch23: valgrind-3.16.0-shmctl.patch
-
-# KDE#140178 open("/proc/self/exe", ...); doesn't quite work
-# RHBZ#1925786 valgrind appears to only interject readlink on /proc/self/exe
-Patch24: valgrind-3.16.1-open-proc-self-exe.patch
-
-# RHBZ#1927153 -flto makes valgrind report non-existing paths to source files
-Patch25: valgrind-3.16.1-readdwarf-line.patch
-
-# RHBZ#433898 netresolve: FTBFS in Fedora rawhide/f34 because arm64 valgrind
-# KDE#433898 arm64: Handle sp, lr, fp as DwReg in CfiExpr
-Patch26: valgrind-3.16.1-arm64_sp_lr_fp_DwReg.patch
+Patch5: valgrind-3.16.0-some-Wl-z-now.patch
 
 BuildRequires: make
 BuildRequires: glibc-devel
@@ -191,6 +121,11 @@ BuildRequires: docbook-dtds
 # configure might use which
 BuildRequires: which
 
+# For testing the debuginfod
+%if 0%{?fedora} > 29 || 0%{?rhel} > 7
+BuildRequires: elfutils-debuginfod
+%endif
+
 %{?scl:Requires:%scl_runtime}
 
 # We need to fixup selinux file context when doing a scl build.
@@ -280,40 +215,18 @@ Valgrind User Manual for details.
 %endif
 
 %prep
-%setup -q -n %{?scl:%{pkg_name}}%{!?scl:%{name}}-%{version}
+%setup -q -n %{?scl:%{pkg_name}}%{!?scl:%{name}}-%{version}.RC1
 
 %patch1 -p1
 %patch2 -p1
 %patch3 -p1
-%patch4 -p1
 
 # Old rhel gcc doesn't have -fstack-protector-strong.
 %if 0%{?fedora} || 0%{?rhel} >= 7
+%patch4 -p1
 %patch5 -p1
-%patch6 -p1
 %endif
 
-%patch7 -p1
-%patch8 -p1
-%patch9 -p1
-%patch10 -p1
-%patch11 -p1
-%patch12 -p1
-%patch13 -p1
-%patch14 -p1
-%patch15 -p1
-%patch16 -p1
-%patch17 -p1
-%patch18 -p1
-%patch19 -p1
-%patch20 -p1
-%patch21 -p1
-%patch22 -p1
-%patch23 -p1
-%patch24 -p1
-%patch25 -p1
-%patch26 -p1
-
 %build
 # LTO triggers undefined symbols in valgrind.  Valgrind has a --enable-lto
 # configure time option, but that doesn't seem to help.
@@ -505,6 +418,7 @@ echo ===============END TESTING===============
 %{_includedir}/valgrind/drd.h
 %{_includedir}/valgrind/helgrind.h
 %{_includedir}/valgrind/memcheck.h
+%{_includedir}/valgrind/dhat.h
 %{_libdir}/pkgconfig/valgrind.pc
 
 %if %{build_tools_devel}
@@ -537,6 +451,10 @@ fi
 %endif
 
 %changelog
+* Mon Mar 15 2021 Mark Wielaard <mjw@fedoraproject.org> - 3.17.0-0.1.RC1
+- Update to upstream 3.17.0-RC1
+- Drop all upstreamed patches
+
 * Wed Mar  3 2021 Mark Wielaard <mjw@fedoraproject.org> - 3.16.1-20
 - Add valgrind-3.16.1-arm64_sp_lr_fp_DwReg.patch