From: Florian Krohm Date: Wed, 4 Dec 2024 15:53:17 +0000 (+0100) Subject: Bug 495817 - s390x: Fix disassembly for compare-and-branch/trap insns X-Git-Tag: VALGRIND_3_25_0~208 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c251bf089f4e4502affa0db9972a78991bbfb1a9;p=thirdparty%2Fvalgrind.git Bug 495817 - s390x: Fix disassembly for compare-and-branch/trap insns The insns C[L][G]R[BJ], C[L][G]I[BJ], CL[G]T, and CL[FG]IT are disassembled incorrectly. Fix this. Replace s390_format_RIEv1 with s390_format_R0UU and s390_format_R0IU. Handling both a signed and unsigned immediate constant field with the same s390_format_... function does not work. Add function s390_format_RSY_R0RD for CLT and CLGT. Those opcodes have extended mnemonics. So adjusting the formerly used s390_format_RSY_RURD wasn't an option as that function is also used for CLM[HY], STCM[HY], and ICM[HY] which don't have extended mnemonics. --- diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c index 7f077efd2..1d889ac32 100644 --- a/VEX/priv/guest_s390_toIR.c +++ b/VEX/priv/guest_s390_toIR.c @@ -141,9 +141,9 @@ typedef enum { #define RIE_RRUUU_i3(insn) (((insn) >> 40) & 0xff) #define RIE_RRUUU_i4(insn) (((insn) >> 32) & 0xff) #define RIE_RRUUU_i5(insn) (((insn) >> 24) & 0xff) -#define RIEv1_r1(insn) (((insn) >> 52) & 0xf) -#define RIEv1_i2(insn) (((insn) >> 32) & 0xffff) -#define RIEv1_m3(insn) (((insn) >> 28) & 0xf) +#define RIE_R0xU_r1(insn) (((insn) >> 52) & 0xf) +#define RIE_R0xU_i2(insn) (((insn) >> 32) & 0xffff) +#define RIE_R0xU_m3(insn) (((insn) >> 28) & 0xf) #define RIE_RRPU_r1(insn) (((insn) >> 52) & 0xf) #define RIE_RRPU_r2(insn) (((insn) >> 48) & 0xf) #define RIE_RRPU_i4(insn) (((insn) >> 32) & 0xffff) @@ -2796,13 +2796,25 @@ s390_format_RIE_RRUUU(const HChar *(*irgen)(UChar r1, UChar r2, UChar i3, } static void -s390_format_RIEv1(const HChar *(*irgen)(UChar r1, UShort i2, UChar m3), - UChar r1, UShort i2, UChar m3) +s390_format_R0UU(const HChar *(*irgen)(UChar r1, UShort i2, UChar m3), + UChar r1, UShort i2, UChar m3) { const HChar *mnm = irgen(r1, i2, m3); if (UNLIKELY(vex_traceflags & VEX_TRACE_FE)) - s390_disasm(ENC4(MNM, GPR, UINT, UINT), mnm, r1, i2, m3); + s390_disasm(ENC4(XMNM, GPR, INT, CABM), S390_XMNM_CAB, mnm, m3, r1, + i2, m3); +} + +static void +s390_format_R0IU(const HChar *(*irgen)(UChar r1, UShort i2, UChar m3), + UChar r1, UShort i2, UChar m3) +{ + const HChar *mnm = irgen(r1, i2, m3); + + if (UNLIKELY(vex_traceflags & VEX_TRACE_FE)) + s390_disasm(ENC4(XMNM, GPR, INT, CABM), S390_XMNM_CAB, mnm, m3, r1, + (Int)(Short)i2, m3); } static void @@ -3333,6 +3345,25 @@ s390_format_RSY_RURD(const HChar *(*irgen)(UChar r1, UChar r3, IRTemp op2addr), s390_disasm(ENC4(MNM, GPR, UINT, SDXB), mnm, r1, r3, dh2, dl2, 0, b2); } +static void +s390_format_RSY_R0RD(const HChar *(*irgen)(UChar r1, UChar m3, IRTemp op2addr), + UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2) +{ + const HChar *mnm; + IRTemp op2addr = newTemp(Ity_I64); + IRTemp d2 = newTemp(Ity_I64); + + assign(d2, mkU64(((ULong)(Long)(Char)dh2 << 12) | ((ULong)dl2))); + assign(op2addr, binop(Iop_Add64, mkexpr(d2), b2 != 0 ? get_gpr_dw0(b2) : + mkU64(0))); + + mnm = irgen(r1, m3, op2addr); + + if (UNLIKELY(vex_traceflags & VEX_TRACE_FE)) + s390_disasm(ENC4(XMNM, GPR, CABM, SDXB), S390_XMNM_CAB, mnm, m3, r1, m3, + dh2, dl2, 0, b2); +} + static void s390_format_RSY_RDRM(const HChar *(*irgen)(UChar r1, IRTemp op2addr), UChar r1, UChar m3, UChar b2, UShort dl2, UChar dh2) @@ -22121,7 +22152,7 @@ s390_decode_6byte_and_irgen(const UChar *bytes) RSY_r3(ovl), RSY_b2(ovl), RSY_dl2(ovl), RSY_dh2(ovl)); goto ok; - case 0xeb0000000023ULL: s390_format_RSY_RURD(s390_irgen_CLT, RSY_r1(ovl), + case 0xeb0000000023ULL: s390_format_RSY_R0RD(s390_irgen_CLT, RSY_r1(ovl), RSY_r3(ovl), RSY_b2(ovl), RSY_dl2(ovl), RSY_dh2(ovl)); goto ok; @@ -22134,7 +22165,7 @@ s390_decode_6byte_and_irgen(const UChar *bytes) RSY_r3(ovl), RSY_b2(ovl), RSY_dl2(ovl), RSY_dh2(ovl)); goto ok; - case 0xeb000000002bULL: s390_format_RSY_RURD(s390_irgen_CLGT, RSY_r1(ovl), + case 0xeb000000002bULL: s390_format_RSY_R0RD(s390_irgen_CLGT, RSY_r1(ovl), RSY_r3(ovl), RSY_b2(ovl), RSY_dl2(ovl), RSY_dh2(ovl)); goto ok; @@ -22390,22 +22421,22 @@ s390_decode_6byte_and_irgen(const UChar *bytes) RIE_RRPU_r2(ovl), RIE_RRPU_i4(ovl), RIE_RRPU_m3(ovl)); goto ok; - case 0xec0000000070ULL: s390_format_RIEv1(s390_irgen_CGIT, - RIEv1_r1(ovl), - RIEv1_i2(ovl), - RIEv1_m3(ovl)); goto ok; - case 0xec0000000071ULL: s390_format_RIEv1(s390_irgen_CLGIT, - RIEv1_r1(ovl), - RIEv1_i2(ovl), - RIEv1_m3(ovl)); goto ok; - case 0xec0000000072ULL: s390_format_RIEv1(s390_irgen_CIT, - RIEv1_r1(ovl), - RIEv1_i2(ovl), - RIEv1_m3(ovl)); goto ok; - case 0xec0000000073ULL: s390_format_RIEv1(s390_irgen_CLFIT, - RIEv1_r1(ovl), - RIEv1_i2(ovl), - RIEv1_m3(ovl)); goto ok; + case 0xec0000000070ULL: s390_format_R0IU(s390_irgen_CGIT, + RIE_R0xU_r1(ovl), + RIE_R0xU_i2(ovl), + RIE_R0xU_m3(ovl)); goto ok; + case 0xec0000000071ULL: s390_format_R0UU(s390_irgen_CLGIT, + RIE_R0xU_r1(ovl), + RIE_R0xU_i2(ovl), + RIE_R0xU_m3(ovl)); goto ok; + case 0xec0000000072ULL: s390_format_R0IU(s390_irgen_CIT, + RIE_R0xU_r1(ovl), + RIE_R0xU_i2(ovl), + RIE_R0xU_m3(ovl)); goto ok; + case 0xec0000000073ULL: s390_format_R0UU(s390_irgen_CLFIT, + RIE_R0xU_r1(ovl), + RIE_R0xU_i2(ovl), + RIE_R0xU_m3(ovl)); goto ok; case 0xec0000000076ULL: s390_format_RIE_RRPU(s390_irgen_CRJ, RIE_RRPU_r1(ovl), RIE_RRPU_r2(ovl), diff --git a/VEX/priv/s390_disasm.c b/VEX/priv/s390_disasm.c index 77f7bd7e8..b4ff13c23 100644 --- a/VEX/priv/s390_disasm.c +++ b/VEX/priv/s390_disasm.c @@ -124,8 +124,10 @@ cab_operand(const HChar *base, UInt mask) *to = *from; } /* strcat(buf, suffix); */ - for (from = suffix[mask >> 1]; *from; ++from, ++to) { - *to = *from; + if (! (mask & 0x1)) { + for (from = suffix[mask >> 1]; *from; ++from, ++to) { + *to = *from; + } } *to = '\0'; @@ -424,7 +426,7 @@ s390_disasm(UInt command, ...) break; case S390_ARG_INT: - p += vex_sprintf(p, "%d", (Int)(va_arg(args, UInt))); + p += vex_sprintf(p, "%d", va_arg(args, Int)); break; case S390_ARG_PCREL: { @@ -478,8 +480,8 @@ s390_disasm(UInt command, ...) case S390_ARG_CABM: { UInt mask; - mask = va_arg(args, UInt) & 0xE; - if (mask == 0 || mask == 14) { + mask = va_arg(args, UInt); + if (mask == 0 || mask == 14 || (mask & 0x1)) { p += vex_sprintf(p, ",%u", mask); } break;