From: Andreas Arnez Date: Tue, 16 Apr 2024 15:24:47 +0000 (+0200) Subject: s390x: Re-implement `vpdi' without intermediate updates X-Git-Tag: VALGRIND_3_23_0~34 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a90e4a7172e940887e0c64cb4229ed17d24b3954;p=thirdparty%2Fvalgrind.git s390x: Re-implement `vpdi' without intermediate updates 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. --- diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index 1f105e951..d65ba998c 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -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"; }