From: Florian Krohm Date: Sun, 28 Jun 2026 13:51:52 +0000 (+0000) Subject: Tweak s390_insn_cas_emit and s390_insn_cdas_emit X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=aa7619dacd357e554aeb6016e4e2ce0c09c235c4;p=thirdparty%2Fvalgrind.git Tweak s390_insn_cas_emit and s390_insn_cdas_emit These functions required an amode without an index register to be passed in. This patch removes that restriction and also allows S390_AMODE_BX12 and S390_AMODE_BX12. The trick goes like this: if an index register is present - add its contents to the base register - emit the compare and swap insn - subtract the contents of the index register from the base register leaving it unmodified. If the incoming amode has R0 as the base register we simply use the index register as the base register. The function s390_isel_amode_b12_b20 is now obsolete. But it is not removed in this patch. Instead it is modified to create BX12 and BX20 amodes in order to enable testing of above tweak. Regtested. --- diff --git a/VEX/priv/host_s390_defs.c b/VEX/priv/host_s390_defs.c index db5345632..54a91a53c 100644 --- a/VEX/priv/host_s390_defs.c +++ b/VEX/priv/host_s390_defs.c @@ -5051,8 +5051,6 @@ s390_insn_cas(UChar size, HReg op1, s390_amode *op2, HReg op3, HReg old_mem) s390_insn *insn = LibVEX_Alloc_inline(sizeof(s390_insn)); vassert(size == 4 || size == 8); - vassert(hregNumber(op2->x) == 0); - vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20); insn->tag = S390_INSN_CAS; insn->size = size; @@ -5074,9 +5072,7 @@ s390_insn_cdas(UChar size, HReg op1_high, HReg op1_low, s390_amode *op2, s390_cdas *cdas = LibVEX_Alloc_inline(sizeof(s390_cdas)); vassert(size == 4 || size == 8); - vassert(hregNumber(op2->x) == 0); vassert(hregNumber(scratch) == 1); /* r0,r1 used as scratch reg pair */ - vassert(op2->tag == S390_AMODE_B12 || op2->tag == S390_AMODE_B20); insn->tag = S390_INSN_CDAS; insn->size = size; @@ -8287,7 +8283,7 @@ s390_insn_cc2bool_emit(UChar *buf, const s390_insn *insn) static UChar * s390_insn_cas_emit(UChar *buf, const s390_insn *insn) { - UChar r1, r3, b, old; + UChar r1, r3, b, x, old; Int d; s390_amode *am; @@ -8296,32 +8292,50 @@ s390_insn_cas_emit(UChar *buf, const s390_insn *insn) old= hregNumber(insn->variant.cas.old_mem); am = insn->variant.cas.op2; b = hregNumber(am->b); + x = hregNumber(am->x); d = am->d; - vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20); + int b_was_zero = b == 0; + if (x != 0) { + if (b != 0) + buf = s390_emit_AGR(buf, b, x); // b = b + x + else + b = x; + } switch (insn->size) { case 4: /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */ buf = s390_emit_LR(buf, R0, r1); - if (am->tag == S390_AMODE_B12) + if (am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_BX12) buf = s390_emit_CS(buf, R0, r3, b, d); else buf = s390_emit_CSY(buf, R0, r3, b, DISP20(d)); /* Now copy R0 which has the old memory value to OLD */ - return s390_emit_LR(buf, old, R0); + buf = s390_emit_LR(buf, old, R0); + break; case 8: /* r1 must not be overwritten. So copy it to R0 and let CS clobber it */ buf = s390_emit_LGR(buf, R0, r1); buf = s390_emit_CSG(buf, R0, r3, b, DISP20(d)); /* Now copy R0 which has the old memory value to OLD */ - return s390_emit_LGR(buf, old, R0); + buf = s390_emit_LGR(buf, old, R0); + break; default: goto fail; } + if (x != 0) { + if (! b_was_zero) { + buf = s390_emit_SGR(buf, b, x); + } else { + /* Nothing to do because b was 0 and that is a scratch reg. */ + } + } + return buf; + fail: vpanic("s390_insn_cas_emit"); } @@ -8331,7 +8345,7 @@ s390_insn_cas_emit(UChar *buf, const s390_insn *insn) static UChar * s390_insn_cdas_emit(UChar *buf, const s390_insn *insn) { - UChar r1, r1p1, r3, /*r3p1,*/ b, old_high, old_low, scratch; + UChar r1, r1p1, r3, /*r3p1,*/ b, x, old_high, old_low, scratch; Int d; s390_amode *am; s390_cdas *cdas = insn->variant.cdas.details; @@ -8345,10 +8359,17 @@ s390_insn_cdas_emit(UChar *buf, const s390_insn *insn) scratch = hregNumber(cdas->scratch); am = cdas->op2; b = hregNumber(am->b); + x = hregNumber(am->x); d = am->d; + int b_was_zero = b == 0; + if (x != 0) { + if (b != 0) + buf = s390_emit_AGR(buf, b, x); // b = b + x + else + b = x; + } vassert(scratch == 1); - vassert(am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20); switch (insn->size) { case 4: @@ -8357,7 +8378,7 @@ s390_insn_cdas_emit(UChar *buf, const s390_insn *insn) buf = s390_emit_LR(buf, R0, r1); buf = s390_emit_LR(buf, scratch, r1p1); - if (am->tag == S390_AMODE_B12) + if (am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_BX12) buf = s390_emit_CDS(buf, R0, r3, b, d); else buf = s390_emit_CDSY(buf, R0, r3, b, DISP20(d)); @@ -8365,7 +8386,7 @@ s390_insn_cdas_emit(UChar *buf, const s390_insn *insn) /* Now copy R0,scratch which has the old memory value to OLD */ buf = s390_emit_LR(buf, old_high, R0); buf = s390_emit_LR(buf, old_low, scratch); - return buf; + break; case 8: /* r1, r1+1 must not be overwritten. So copy them to R0,scratch @@ -8378,12 +8399,21 @@ s390_insn_cdas_emit(UChar *buf, const s390_insn *insn) /* Now copy R0,scratch which has the old memory value to OLD */ buf = s390_emit_LGR(buf, old_high, R0); buf = s390_emit_LGR(buf, old_low, scratch); - return buf; + break; default: goto fail; } + if (x != 0) { + if (! b_was_zero) { + buf = s390_emit_SGR(buf, b, x); + } else { + /* Nothing to do because b was 0 and that is a scratch reg. */ + } + } + return buf; + fail: vpanic("s390_insn_cdas_emit"); } diff --git a/VEX/priv/host_s390_isel.c b/VEX/priv/host_s390_isel.c index 18bb95af9..d00e991b0 100644 --- a/VEX/priv/host_s390_isel.c +++ b/VEX/priv/host_s390_isel.c @@ -427,11 +427,45 @@ s390_isel_amode_b12_b20(ISelEnv *env, IRExpr *expr) am = s390_isel_amode_wrk(env, expr, True, False); - /* Check post-condition */ - vassert(s390_amode_is_sane(am) && - (am->tag == S390_AMODE_B12 || am->tag == S390_AMODE_B20)); + HReg x = newVRegI(env); + ULong d = (Long)am->d; + + static UInt count = 0; + + ++count; + if ((count % 2) == 0) { + /* Scenario #1: Move d to the index register and construct + an amode with d == 0 */ + if (d != 0) { +// vex_printf("!!! CASE 1\n"); + addInstr(env, s390_insn_load_immediate(8, x, d)); + + if (am->tag == S390_AMODE_B12) + return s390_amode_bx12(0, am->b, x); + if (am->tag == S390_AMODE_B20) + return s390_amode_bx20(0, am->b, x); + vpanic("WHOOPSIE"); + } else { +// vex_printf("!!! CASE 2\n"); + d = -11; + addInstr(env, s390_insn_load_immediate(8, x, d)); - return am; + if (am->tag == S390_AMODE_B12) + return s390_amode_bx12(-d, am->b, x); + if (am->tag == S390_AMODE_B20) + return s390_amode_bx20(-d, am->b, x); + vpanic("WHOOPSIE"); + } + } else { + /* Scenario #2: Use b as an index register and construct an + amode with b == R0. */ +// vex_printf("!!! CASE 3\n"); + if (am->tag == S390_AMODE_B12) + return s390_amode_bx12(d, s390_hreg_gpr(0), am->b); + if (am->tag == S390_AMODE_B20) + return s390_amode_bx20(d, s390_hreg_gpr(0), am->b); + vpanic("WHOOPSIE"); + } }