From: Florian Krohm Date: Sun, 30 Mar 2025 20:51:33 +0000 (+0000) Subject: s390x: Fix disassembly for various DFP and BFP opcodes (BZ 495817) X-Git-Tag: VALGRIND_3_25_0~75 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=72de8eaf53d77b0aa51266864f5a339b787ca24c;p=thirdparty%2Fvalgrind.git s390x: Fix disassembly for various DFP and BFP opcodes (BZ 495817) Specifically: - DFP: add, subtract, divide, multiply - BFP: load FP integer, load rounded Change function names from e.g. s390_irgen/emit_LDXBR to s390_irgen/emit_LDXBRA because LDXBR does not have m3 and m4 operands. Adjust the returned mnemonic accordingly. New function s390_format_RRF_UUFF2 for FI[DEX]BRA. Add adtra_like_disasm to disassemble opcodes for DFP arithmetic. Part of fixing https://bugs.kde.org/show_bug.cgi?id=495817 --- diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index 7b029623d..b870b77fe 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -3094,7 +3094,18 @@ s390_format_RRF_UUFF(const HChar *(*irgen)(UChar m3, UChar m4, UChar r1, const HChar *mnm = irgen(m3, m4, r1, r2); if (UNLIKELY(vex_traceflags & VEX_TRACE_FE)) - S390_DISASM(MNM(mnm), FPR(r1), UINT(m3), FPR(r2), UINT(m4)); + S390_DISASM(XMNM(mnm, fp_convf_disasm), FPR(r1), MASK(m3), FPR(r2), MASK(m4)); +} + +static void +s390_format_RRF_UUFF2(const HChar *(*irgen)(UChar m3, UChar m4, UChar r1, + UChar r2), + UChar m3, UChar m4, UChar r1, UChar r2) +{ + const HChar *mnm = irgen(m3, m4, r1, r2); + + if (UNLIKELY(vex_traceflags & VEX_TRACE_FE)) + S390_DISASM(XMNM(mnm, fp_convt_disasm), FPR(r1), MASK(m3), FPR(r2), MASK(m4)); } static void @@ -3191,7 +3202,7 @@ s390_format_RRF_FUFF2(const HChar *(*irgen)(UChar, UChar, UChar, UChar), const HChar *mnm = irgen(r3, m4, r1, r2); if (UNLIKELY(vex_traceflags & VEX_TRACE_FE)) - S390_DISASM(MNM(mnm), FPR(r1), FPR(r2), FPR(r3), UINT(m4)); + S390_DISASM(XMNM(mnm, adtra_like_disasm), FPR(r1), FPR(r2), FPR(r3), MASK(m4)); } static void @@ -11807,8 +11818,8 @@ s390_irgen_LDEB(UChar r1, IRTemp op2addr) } static const HChar * -s390_irgen_LEDBR(UChar m3, UChar m4 __attribute__((unused)), - UChar r1, UChar r2) +s390_irgen_LEDBRA(UChar m3, UChar m4 __attribute__((unused)), + UChar r1, UChar r2) { if (! s390_host_has_fpext && m3 != S390_BFP_ROUND_PER_FPC) { emulation_warning(EmWarn_S390X_fpext_rounding); @@ -11820,7 +11831,7 @@ s390_irgen_LEDBR(UChar m3, UChar m4 __attribute__((unused)), put_fpr_w0(r1, binop(Iop_F64toF32, mkexpr(encode_bfp_rounding_mode(m3)), mkexpr(op))); - return "ledbr"; + return "ledbra"; } static const HChar * @@ -11988,7 +11999,7 @@ s390_irgen_ADTRA(UChar r3, UChar m4, UChar r1, UChar r2) s390_cc_thunk_putF(S390_CC_OP_DFP_RESULT_64, result); put_dpr_dw0(r1, mkexpr(result)); } - return (m4 == 0) ? "adtr" : "adtra"; + return "adtra"; } static const HChar * @@ -14970,8 +14981,8 @@ s390_irgen_LPXBR(UChar r1, UChar r2) } static const HChar * -s390_irgen_LDXBR(UChar m3, UChar m4 __attribute__((unused)), - UChar r1, UChar r2) +s390_irgen_LDXBRA(UChar m3, UChar m4 __attribute__((unused)), + UChar r1, UChar r2) { if (! s390_host_has_fpext && m3 != S390_BFP_ROUND_PER_FPC) { emulation_warning(EmWarn_S390X_fpext_rounding); @@ -14983,12 +14994,12 @@ s390_irgen_LDXBR(UChar m3, UChar m4 __attribute__((unused)), get_fpr_pair(r2))); put_fpr_dw0(r1, mkexpr(result)); - return "ldxbr"; + return "ldxbra"; } static const HChar * -s390_irgen_LEXBR(UChar m3, UChar m4 __attribute__((unused)), - UChar r1, UChar r2) +s390_irgen_LEXBRA(UChar m3, UChar m4 __attribute__((unused)), + UChar r1, UChar r2) { if (! s390_host_has_fpext && m3 != S390_BFP_ROUND_PER_FPC) { emulation_warning(EmWarn_S390X_fpext_rounding); @@ -15000,7 +15011,7 @@ s390_irgen_LEXBR(UChar m3, UChar m4 __attribute__((unused)), get_fpr_pair(r2))); put_fpr_w0(r1, mkexpr(result)); - return "lexbr"; + return "lexbra"; } static const HChar * @@ -20745,18 +20756,18 @@ s390_decode_4byte_and_irgen(const UChar *bytes) RRE_r2(ovl)); goto ok; case 0xb343: s390_format_RRE_FF(s390_irgen_LCXBR, RRE_r1(ovl), RRE_r2(ovl)); goto ok; - case 0xb344: s390_format_RRF_UUFF(s390_irgen_LEDBR, RRF2_m3(ovl), - RRF2_m4(ovl), RRF2_r1(ovl), - RRF2_r2(ovl)); goto ok; - case 0xb345: s390_format_RRF_UUFF(s390_irgen_LDXBR, RRF2_m3(ovl), + case 0xb344: s390_format_RRF_UUFF(s390_irgen_LEDBRA, RRF2_m3(ovl), RRF2_m4(ovl), RRF2_r1(ovl), RRF2_r2(ovl)); goto ok; - case 0xb346: s390_format_RRF_UUFF(s390_irgen_LEXBR, RRF2_m3(ovl), + case 0xb345: s390_format_RRF_UUFF(s390_irgen_LDXBRA, RRF2_m3(ovl), RRF2_m4(ovl), RRF2_r1(ovl), RRF2_r2(ovl)); goto ok; - case 0xb347: s390_format_RRF_UUFF(s390_irgen_FIXBRA, RRF2_m3(ovl), + case 0xb346: s390_format_RRF_UUFF(s390_irgen_LEXBRA, RRF2_m3(ovl), RRF2_m4(ovl), RRF2_r1(ovl), RRF2_r2(ovl)); goto ok; + case 0xb347: s390_format_RRF_UUFF2(s390_irgen_FIXBRA, RRF2_m3(ovl), + RRF2_m4(ovl), RRF2_r1(ovl), + RRF2_r2(ovl)); goto ok; case 0xb348: s390_format_RRE_FF(s390_irgen_KXBR, RRE_r1(ovl), RRE_r2(ovl)); goto ok; case 0xb349: s390_format_RRE_FF(s390_irgen_CXBR, RRE_r1(ovl), @@ -20772,15 +20783,15 @@ s390_decode_4byte_and_irgen(const UChar *bytes) case 0xb350: /* TBEDR */ goto unimplemented; case 0xb351: /* TBDR */ goto unimplemented; case 0xb353: /* DIEBR */ goto unimplemented; - case 0xb357: s390_format_RRF_UUFF(s390_irgen_FIEBRA, RRF2_m3(ovl), - RRF2_m4(ovl), RRF2_r1(ovl), - RRF2_r2(ovl)); goto ok; + case 0xb357: s390_format_RRF_UUFF2(s390_irgen_FIEBRA, RRF2_m3(ovl), + RRF2_m4(ovl), RRF2_r1(ovl), + RRF2_r2(ovl)); goto ok; case 0xb358: /* THDER */ goto unimplemented; case 0xb359: /* THDR */ goto unimplemented; case 0xb35b: /* DIDBR */ goto unimplemented; - case 0xb35f: s390_format_RRF_UUFF(s390_irgen_FIDBRA, RRF2_m3(ovl), - RRF2_m4(ovl), RRF2_r1(ovl), - RRF2_r2(ovl)); goto ok; + case 0xb35f: s390_format_RRF_UUFF2(s390_irgen_FIDBRA, RRF2_m3(ovl), + RRF2_m4(ovl), RRF2_r1(ovl), + RRF2_r2(ovl)); goto ok; case 0xb360: /* LPXR */ goto unimplemented; case 0xb361: /* LNXR */ goto unimplemented; case 0xb362: /* LTXR */ goto unimplemented; diff --git a/VEX/priv/host_s390_defs.c b/VEX/priv/host_s390_defs.c index 684d17358..c503d6dde 100644 --- a/VEX/priv/host_s390_defs.c +++ b/VEX/priv/host_s390_defs.c @@ -4383,12 +4383,8 @@ s390_emit_LEDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) vassert(m4 == 0); vassert(m3 == 0 || s390_host_has_fpext); - if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { - if (m3 == 0) - S390_DISASM(MNM("ledbr"), FPR(r1), FPR(r2)); - else - S390_DISASM(MNM("ledbra"), FPR(r1), UINT(m3), FPR(r2), UINT(m4)); - } + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + S390_DISASM(XMNM("ledbra", fp_convf_disasm), FPR(r1), MASK(m3), FPR(r2), MASK(m4)); return emit_RRF2(p, 0xb3440000, m3, m4, r1, r2); } @@ -4400,12 +4396,8 @@ s390_emit_LDXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) vassert(m4 == 0); vassert(m3 == 0 || s390_host_has_fpext); - if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { - if (m3 == 0) - S390_DISASM(MNM("ldxbr"), FPR(r1), FPR(r2)); - else - S390_DISASM(MNM("ldxbra"), FPR(r1), UINT(m3), FPR(r2), UINT(m4)); - } + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + S390_DISASM(XMNM("ldxbra", fp_convf_disasm), FPR(r1), MASK(m3), FPR(r2), MASK(m4)); return emit_RRF2(p, 0xb3450000, m3, m4, r1, r2); } @@ -4417,12 +4409,8 @@ s390_emit_LEXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) vassert(m4 == 0); vassert(m3 == 0 || s390_host_has_fpext); - if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { - if (m3 == 0) - S390_DISASM(MNM("lexbr"), FPR(r1), FPR(r2)); - else - S390_DISASM(MNM("lexbra"), FPR(r1), UINT(m3), FPR(r2), UINT(m4)); - } + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + S390_DISASM(XMNM("lexbra", fp_convf_disasm), FPR(r1), MASK(m3), FPR(r2), MASK(m4)); return emit_RRF2(p, 0xb3460000, m3, m4, r1, r2); } @@ -4433,12 +4421,8 @@ s390_emit_FIEBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) { vassert(m3 == 0 || s390_host_has_fpext); - if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { - if (m4 == 0) - S390_DISASM(MNM("fiebr"), FPR(r1), UINT(m3), FPR(r2)); - else - S390_DISASM(MNM("fiebra"), FPR(r1), UINT(m3), FPR(r2), UINT(m4)); - } + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + S390_DISASM(XMNM("fiebra", fp_convt_disasm), FPR(r1), MASK(m3), FPR(r2), MASK(m4)); return emit_RRF2(p, 0xb3570000, m3, m4, r1, r2); } @@ -4449,12 +4433,8 @@ s390_emit_FIDBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) { vassert(m3 == 0 || s390_host_has_fpext); - if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { - if (m4 == 0) - S390_DISASM(MNM("fidbr"), FPR(r1), UINT(m3), FPR(r2)); - else - S390_DISASM(MNM("fidbra"), FPR(r1), UINT(m3), FPR(r2), UINT(m4)); - } + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + S390_DISASM(XMNM("fidbra", fp_convt_disasm), FPR(r1), MASK(m3), FPR(r2), MASK(m4)); return emit_RRF2(p, 0xb35f0000, m3, m4, r1, r2); } @@ -4465,12 +4445,8 @@ s390_emit_FIXBRA(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) { vassert(m3 == 0 || s390_host_has_fpext); - if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { - if (m4 == 0) - S390_DISASM(MNM("fixbr"), FPR(r1), UINT(m3), FPR(r2)); - else - S390_DISASM(MNM("fixbra"), FPR(r1), UINT(m3), FPR(r2), UINT(m4)); - } + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + S390_DISASM(XMNM("fixbra", fp_convt_disasm), FPR(r1), MASK(m3), FPR(r2), MASK(m4)); return emit_RRF2(p, 0xb3470000, m3, m4, r1, r2); } @@ -4611,12 +4587,8 @@ s390_emit_ADTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) { vassert(s390_host_has_dfp); vassert(m4 == 0 || s390_host_has_fpext); - if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { - if (m4 == 0) - S390_DISASM(MNM("adtr"), FPR(r1), FPR(r2), FPR(r3)); - else - S390_DISASM(MNM("adtra"), FPR(r1), FPR(r2), FPR(r3), UINT(m4)); - } + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + S390_DISASM(XMNM("adtra", adtra_like_disasm), FPR(r1), FPR(r2), FPR(r3), MASK(m4)); return emit_RRF4(p, 0xb3d20000, r3, m4, r1, r2); } @@ -4627,12 +4599,8 @@ s390_emit_AXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) { vassert(s390_host_has_dfp); vassert(m4 == 0 || s390_host_has_fpext); - if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { - if (m4 == 0) - S390_DISASM(MNM("axtr"), FPR(r1), FPR(r2), FPR(r3)); - else - S390_DISASM(MNM("axtra"), FPR(r1), FPR(r2), FPR(r3), UINT(m4)); - } + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + S390_DISASM(XMNM("axtra", adtra_like_disasm), FPR(r1), FPR(r2), FPR(r3), MASK(m4)); return emit_RRF4(p, 0xb3da0000, r3, m4, r1, r2); } @@ -4911,12 +4879,8 @@ s390_emit_DDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) { vassert(s390_host_has_dfp); vassert(m4 == 0 || s390_host_has_fpext); - if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { - if (m4 == 0) - S390_DISASM(MNM("ddtr"), FPR(r1), FPR(r2), FPR(r3)); - else - S390_DISASM(MNM("ddtra"), FPR(r1), FPR(r2), FPR(r3), UINT(m4)); - } + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + S390_DISASM(XMNM("ddtra", adtra_like_disasm), FPR(r1), FPR(r2), FPR(r3), MASK(m4)); return emit_RRF4(p, 0xb3d10000, r3, m4, r1, r2); } @@ -4927,12 +4891,8 @@ s390_emit_DXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) { vassert(s390_host_has_dfp); vassert(m4 == 0 || s390_host_has_fpext); - if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { - if (m4 == 0) - S390_DISASM(MNM("dxtr"), FPR(r1), FPR(r2), FPR(r3)); - else - S390_DISASM(MNM("dxtra"), FPR(r1), FPR(r2), FPR(r3), UINT(m4)); - } + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + S390_DISASM(XMNM("dxtra", adtra_like_disasm), FPR(r1), FPR(r2), FPR(r3), MASK(m4)); return emit_RRF4(p, 0xb3d90000, r3, m4, r1, r2); } @@ -5028,7 +4988,7 @@ s390_emit_LEDTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) vassert(s390_host_has_fpext || m3 < 1 || m3 > 7); if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) - S390_DISASM(MNM("ledtr"), FPR(r1), UINT(m3), FPR(r2), UINT(m4)); + S390_DISASM(XMNM("ledtr", fp_convf_disasm), FPR(r1), MASK(m3), FPR(r2), MASK(m4)); return emit_RRF2(p, 0xb3d50000, m3, m4, r1, r2); } @@ -5042,7 +5002,7 @@ s390_emit_LDXTR(UChar *p, UChar m3, UChar m4, UChar r1, UChar r2) vassert(s390_host_has_fpext || m3 < 1 || m3 > 7); if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) - S390_DISASM(MNM("ldxtr"), FPR(r1), UINT(m3), FPR(r2), UINT(m4)); + S390_DISASM(XMNM("ldxtr", fp_convf_disasm), FPR(r1), MASK(m3), FPR(r2), MASK(m4)); return emit_RRF2(p, 0xb3dd0000, m3, m4, r1, r2); } @@ -5053,12 +5013,8 @@ s390_emit_MDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) { vassert(s390_host_has_dfp); vassert(m4 == 0 || s390_host_has_fpext); - if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { - if (m4 == 0) - S390_DISASM(MNM("mdtr"), FPR(r1), FPR(r2), FPR(r3)); - else - S390_DISASM(MNM("mdtra"), FPR(r1), FPR(r2), FPR(r3), UINT(m4)); - } + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + S390_DISASM(XMNM("mdtra", adtra_like_disasm), FPR(r1), FPR(r2), FPR(r3), MASK(m4)); return emit_RRF4(p, 0xb3d00000, r3, m4, r1, r2); } @@ -5069,12 +5025,8 @@ s390_emit_MXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) { vassert(s390_host_has_dfp); vassert(m4 == 0 || s390_host_has_fpext); - if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { - if (m4 == 0) - S390_DISASM(MNM("mxtr"), FPR(r1), FPR(r2), FPR(r3)); - else - S390_DISASM(MNM("mxtra"), FPR(r1), FPR(r2), FPR(r3), UINT(m4)); - } + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + S390_DISASM(XMNM("mxtra", adtra_like_disasm), FPR(r1), FPR(r2), FPR(r3), MASK(m4)); return emit_RRF4(p, 0xb3d80000, r3, m4, r1, r2); } @@ -5150,12 +5102,8 @@ s390_emit_SDTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) { vassert(s390_host_has_dfp); vassert(m4 == 0 || s390_host_has_fpext); - if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { - if (m4 == 0) - S390_DISASM(MNM("sdtr"), FPR(r1), FPR(r2), FPR(r3)); - else - S390_DISASM(MNM("sdtra"), FPR(r1), FPR(r2), FPR(r3), UINT(m4)); - } + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + S390_DISASM(XMNM("sdtra", adtra_like_disasm), FPR(r1), FPR(r2), FPR(r3), MASK(m4)); return emit_RRF4(p, 0xb3d30000, r3, m4, r1, r2); } @@ -5166,12 +5114,8 @@ s390_emit_SXTRA(UChar *p, UChar r3, UChar m4, UChar r1, UChar r2) { vassert(s390_host_has_dfp); vassert(m4 == 0 || s390_host_has_fpext); - if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) { - if (m4 == 0) - S390_DISASM(MNM("sxtr"), FPR(r1), FPR(r2), FPR(r3)); - else - S390_DISASM(MNM("sxtra"), FPR(r1), FPR(r2), FPR(r3), UINT(m4)); - } + if (UNLIKELY(vex_traceflags & VEX_TRACE_ASM)) + S390_DISASM(XMNM("sxtra", adtra_like_disasm), FPR(r1), FPR(r2), FPR(r3), MASK(m4)); return emit_RRF4(p, 0xb3db0000, r3, m4, r1, r2); } diff --git a/VEX/priv/s390_disasm.c b/VEX/priv/s390_disasm.c index 9649f9f0e..139e14199 100644 --- a/VEX/priv/s390_disasm.c +++ b/VEX/priv/s390_disasm.c @@ -1066,6 +1066,24 @@ fp_convt_disasm(const s390_opnd *opnds, HChar *p) } +HChar * +adtra_like_disasm(const s390_opnd *opnds, HChar *p) +{ + const HChar *base = opnds[0].xmnm.base; + UInt m4 = opnds[get_mask_index(opnds, 1)].mask; + UInt len = vex_strlen(base); + + HChar xmnm[len + 1]; + + vex_sprintf(xmnm, "%s", base); + + if (xmnm[len - 1] == 'a' && m4 == 0) { + xmnm[len - 1] = '\0'; + } + return s390_disasm_aux(opnds, xmnm, p, mask0_mh); +} + + /* Write out OPNDS. MH is a mask handler. It decides whether or not a MASK operand is written and if so, massages the mask value as needed. */ static HChar * diff --git a/VEX/priv/s390_disasm.h b/VEX/priv/s390_disasm.h index b28af8f65..f84f5061f 100644 --- a/VEX/priv/s390_disasm.h +++ b/VEX/priv/s390_disasm.h @@ -137,6 +137,7 @@ HChar *vfce_like_disasm(const s390_opnd *, HChar *); HChar *vfmix_like_disasm(const s390_opnd *, HChar *); HChar *fp_convf_disasm(const s390_opnd *, HChar *); HChar *fp_convt_disasm(const s390_opnd *, HChar *); +HChar *adtra_like_disasm(const s390_opnd *, HChar *); /*---------------------------------------------------------------*/ /*--- end s390_disasm.h ---*/