]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
s390x: Re-implement `vpdi' without intermediate updates
authorAndreas Arnez <arnez@linux.ibm.com>
Tue, 16 Apr 2024 15:24:47 +0000 (17:24 +0200)
committerAndreas Arnez <arnez@linux.ibm.com>
Wed, 17 Apr 2024 12:26:53 +0000 (14:26 +0200)
The vpdi instruction is implemented incorrectly for the case where the
result vector coincides with one of the input operands, because it
performs an intermediate update.  An example where this produces wrong
results is for

vpdi    %v3,%v3,%v3,4

where the instruction is used to swap the two halves of %v3.

Fix this by avoiding the intermediate update and using Iop_64HLtoV128
instead.

VEX/priv/guest_s390_toIR.c

index 1f105e951741a2f4ce2563949d1148a7316de243..d65ba998c2895a34ea7be1218a34f2074db0bcf5 100644 (file)
@@ -16588,20 +16588,11 @@ s390_irgen_VSCEG(UChar v1, IRTemp op2addr, UChar m3)
 static const HChar *
 s390_irgen_VPDI(UChar v1, UChar v2, UChar v3, UChar m4)
 {
-   /* Theese bits are reserved by specification */
-   vassert((m4 & 2) == 0);
-   vassert((m4 & 8) == 0);
-
-   if((m4 & 4) != 0)
-      put_vr_dw0(v1, get_vr_dw1(v2));
-   else
-      put_vr_dw0(v1, get_vr_dw0(v2));
-
-   if((m4 & 1) != 0)
-      put_vr_dw1(v1, get_vr_dw1(v3));
-   else
-      put_vr_dw1(v1, get_vr_dw0(v3));
+   /* These bits are reserved by specification */
+   s390_insn_assert("vpdi", (m4 & 2) == 0 && (m4 & 8) == 0);
 
+   put_vr_qw(v1, binop(Iop_64HLtoV128, m4 & 4 ? get_vr_dw1(v2) : get_vr_dw0(v2),
+                       m4 & 1 ? get_vr_dw1(v3) : get_vr_dw0(v3)));
    return "vpdi";
 }