diff --git a/target/s390x/translate.c b/target/s390x/translate.c index 3d5c0d6106..39e33eeb67 100644 --- a/target/s390x/translate.c +++ b/target/s390x/translate.c @@ -3815,22 +3815,23 @@ static DisasJumpType op_risbg(DisasContext *s, DisasOps *o) pmask = 0xffffffff00000000ull; break; case 0x51: /* risblg */ - i3 &= 31; - i4 &= 31; + i3 = (i3 & 31) + 32; + i4 = (i4 & 31) + 32; pmask = 0x00000000ffffffffull; break; default: g_assert_not_reached(); } - /* MASK is the set of bits to be inserted from R2. - Take care for I3/I4 wraparound. */ - mask = pmask >> i3; + /* MASK is the set of bits to be inserted from R2. */ if (i3 <= i4) { - mask ^= pmask >> i4 >> 1; + /* [0...i3---i4...63] */ + mask = (-1ull >> i3) & (-1ull << (63 - i4)); } else { - mask |= ~(pmask >> i4 >> 1); + /* [0---i4...i3---63] */ + mask = (-1ull >> i3) | (-1ull << (63 - i4)); } + /* For RISBLG/RISBHG, the wrapping is limited to the high/low doubleword. */ mask &= pmask; /* IMASK is the set of bits to be kept from R1. In the case of the high/low @@ -3843,9 +3844,6 @@ static DisasJumpType op_risbg(DisasContext *s, DisasOps *o) len = i4 - i3 + 1; pos = 63 - i4; rot = i5 & 63; - if (s->fields.op2 == 0x5d) { - pos += 32; - } /* In some cases we can implement this with extract. */ if (imask == 0 && pos == 0 && len > 0 && len <= rot) {