From a90e4a7172e940887e0c64cb4229ed17d24b3954 Mon Sep 17 00:00:00 2001 From: Andreas Arnez Date: Tue, 16 Apr 2024 17:24:47 +0200 Subject: [PATCH] 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. --- VEX/priv/guest_s390_toIR.c | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) 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"; } -- 2.47.2