4507b4
commit b77dbefe72e4a5c7bcf1576a02c909010bd56991
4507b4
Author: Andreas Arnez <arnez@linux.ibm.com>
4507b4
Date:   Fri Oct 22 19:55:12 2021 +0200
4507b4
4507b4
    Bug 444242 - s390x: Sign-extend "relative long" offset in EXRL
4507b4
    
4507b4
    In s390_irgen_EXRL, the offset is zero-extended instead of sign-extended,
4507b4
    typically causing Valgrind to crash when a negative offset occurs.
4507b4
    
4507b4
    Fix this with a new helper function that calculates a "relative long"
4507b4
    address from a 32-bit offset.  Replace other calculations of "relative
4507b4
    long" addresses by invocations of this function as well.  And for
4507b4
    consistency, do the same with "relative" (short) addresses.
4507b4
4507b4
diff --git a/VEX/priv/guest_s390_toIR.c b/VEX/priv/guest_s390_toIR.c
4507b4
index 72222ab04..fffc563d4 100644
4507b4
--- a/VEX/priv/guest_s390_toIR.c
4507b4
+++ b/VEX/priv/guest_s390_toIR.c
4507b4
@@ -399,6 +399,22 @@ mkF64i(ULong value)
4507b4
    return IRExpr_Const(IRConst_F64i(value));
4507b4
 }
4507b4
 
4507b4
+/* Return the 64-bit address with the given 32-bit "relative long" offset from
4507b4
+   the current guest instruction being translated. */
4507b4
+static __inline__ Addr64
4507b4
+addr_rel_long(UInt offset)
4507b4
+{
4507b4
+   return guest_IA_curr_instr + ((Addr64)(Long)(Int)offset << 1);
4507b4
+}
4507b4
+
4507b4
+/* Return the 64-bit address with the given 16-bit "relative" offset from the
4507b4
+   current guest instruction being translated. */
4507b4
+static __inline__ Addr64
4507b4
+addr_relative(UShort offset)
4507b4
+{
4507b4
+   return guest_IA_curr_instr + ((Addr64)(Long)(Short)offset << 1);
4507b4
+}
4507b4
+
4507b4
 /* Little helper function for my sanity. ITE = if-then-else */
4507b4
 static IRExpr *
4507b4
 mkite(IRExpr *condition, IRExpr *iftrue, IRExpr *iffalse)
4507b4
@@ -5516,7 +5532,7 @@ static const HChar *
4507b4
 s390_irgen_BRAS(UChar r1, UShort i2)
4507b4
 {
4507b4
    put_gpr_dw0(r1, mkU64(guest_IA_curr_instr + 4ULL));
4507b4
-   call_function_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Short)i2 << 1));
4507b4
+   call_function_and_chase(addr_relative(i2));
4507b4
 
4507b4
    return "bras";
4507b4
 }
4507b4
@@ -5525,7 +5541,7 @@ static const HChar *
4507b4
 s390_irgen_BRASL(UChar r1, UInt i2)
4507b4
 {
4507b4
    put_gpr_dw0(r1, mkU64(guest_IA_curr_instr + 6ULL));
4507b4
-   call_function_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Int)i2 << 1));
4507b4
+   call_function_and_chase(addr_rel_long(i2));
4507b4
 
4507b4
    return "brasl";
4507b4
 }
4507b4
@@ -5538,12 +5554,11 @@ s390_irgen_BRC(UChar r1, UShort i2)
4507b4
    if (r1 == 0) {
4507b4
    } else {
4507b4
       if (r1 == 15) {
4507b4
-         always_goto_and_chase(
4507b4
-               guest_IA_curr_instr + ((ULong)(Long)(Short)i2 << 1));
4507b4
+         always_goto_and_chase(addr_relative(i2));
4507b4
       } else {
4507b4
          assign(cond, s390_call_calculate_cond(r1));
4507b4
          if_condition_goto(binop(Iop_CmpNE32, mkexpr(cond), mkU32(0)),
4507b4
-                           guest_IA_curr_instr + ((ULong)(Long)(Short)i2 << 1));
4507b4
+                           addr_relative(i2));
4507b4
 
4507b4
       }
4507b4
    }
4507b4
@@ -5561,11 +5576,11 @@ s390_irgen_BRCL(UChar r1, UInt i2)
4507b4
    if (r1 == 0) {
4507b4
    } else {
4507b4
       if (r1 == 15) {
4507b4
-         always_goto_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Int)i2 << 1));
4507b4
+         always_goto_and_chase(addr_rel_long(i2));
4507b4
       } else {
4507b4
          assign(cond, s390_call_calculate_cond(r1));
4507b4
          if_condition_goto(binop(Iop_CmpNE32, mkexpr(cond), mkU32(0)),
4507b4
-                           guest_IA_curr_instr + ((ULong)(Long)(Int)i2 << 1));
4507b4
+                           addr_rel_long(i2));
4507b4
       }
4507b4
    }
4507b4
    if (UNLIKELY(vex_traceflags & VEX_TRACE_FE))
4507b4
@@ -5579,7 +5594,7 @@ s390_irgen_BRCT(UChar r1, UShort i2)
4507b4
 {
4507b4
    put_gpr_w1(r1, binop(Iop_Sub32, get_gpr_w1(r1), mkU32(1)));
4507b4
    if_condition_goto(binop(Iop_CmpNE32, get_gpr_w1(r1), mkU32(0)),
4507b4
-                     guest_IA_curr_instr + ((ULong)(Long)(Short)i2 << 1));
4507b4
+                     addr_relative(i2));
4507b4
 
4507b4
    return "brct";
4507b4
 }
4507b4
@@ -5589,7 +5604,7 @@ s390_irgen_BRCTH(UChar r1, UInt i2)
4507b4
 {
4507b4
    put_gpr_w0(r1, binop(Iop_Sub32, get_gpr_w0(r1), mkU32(1)));
4507b4
    if_condition_goto(binop(Iop_CmpNE32, get_gpr_w0(r1), mkU32(0)),
4507b4
-                     guest_IA_curr_instr + ((ULong)(Long)(Short)i2 << 1));
4507b4
+                     addr_relative(i2));
4507b4
 
4507b4
    return "brcth";
4507b4
 }
4507b4
@@ -5599,7 +5614,7 @@ s390_irgen_BRCTG(UChar r1, UShort i2)
4507b4
 {
4507b4
    put_gpr_dw0(r1, binop(Iop_Sub64, get_gpr_dw0(r1), mkU64(1)));
4507b4
    if_condition_goto(binop(Iop_CmpNE64, get_gpr_dw0(r1), mkU64(0)),
4507b4
-                     guest_IA_curr_instr + ((ULong)(Long)(Short)i2 << 1));
4507b4
+                     addr_relative(i2));
4507b4
 
4507b4
    return "brctg";
4507b4
 }
4507b4
@@ -5612,7 +5627,7 @@ s390_irgen_BRXH(UChar r1, UChar r3, UShort i2)
4507b4
    assign(value, get_gpr_w1(r3 | 1));
4507b4
    put_gpr_w1(r1, binop(Iop_Add32, get_gpr_w1(r1), get_gpr_w1(r3)));
4507b4
    if_condition_goto(binop(Iop_CmpLT32S, mkexpr(value), get_gpr_w1(r1)),
4507b4
-                     guest_IA_curr_instr + ((ULong)(Long)(Short)i2 << 1));
4507b4
+                     addr_relative(i2));
4507b4
 
4507b4
    return "brxh";
4507b4
 }
4507b4
@@ -5625,7 +5640,7 @@ s390_irgen_BRXHG(UChar r1, UChar r3, UShort i2)
4507b4
    assign(value, get_gpr_dw0(r3 | 1));
4507b4
    put_gpr_dw0(r1, binop(Iop_Add64, get_gpr_dw0(r1), get_gpr_dw0(r3)));
4507b4
    if_condition_goto(binop(Iop_CmpLT64S, mkexpr(value), get_gpr_dw0(r1)),
4507b4
-                     guest_IA_curr_instr + ((ULong)(Long)(Short)i2 << 1));
4507b4
+                     addr_relative(i2));
4507b4
 
4507b4
    return "brxhg";
4507b4
 }
4507b4
@@ -5638,7 +5653,7 @@ s390_irgen_BRXLE(UChar r1, UChar r3, UShort i2)
4507b4
    assign(value, get_gpr_w1(r3 | 1));
4507b4
    put_gpr_w1(r1, binop(Iop_Add32, get_gpr_w1(r1), get_gpr_w1(r3)));
4507b4
    if_condition_goto(binop(Iop_CmpLE32S, get_gpr_w1(r1), mkexpr(value)),
4507b4
-                     guest_IA_curr_instr + ((ULong)(Long)(Short)i2 << 1));
4507b4
+                     addr_relative(i2));
4507b4
 
4507b4
    return "brxle";
4507b4
 }
4507b4
@@ -5651,7 +5666,7 @@ s390_irgen_BRXLG(UChar r1, UChar r3, UShort i2)
4507b4
    assign(value, get_gpr_dw0(r3 | 1));
4507b4
    put_gpr_dw0(r1, binop(Iop_Add64, get_gpr_dw0(r1), get_gpr_dw0(r3)));
4507b4
    if_condition_goto(binop(Iop_CmpLE64S, get_gpr_dw0(r1), mkexpr(value)),
4507b4
-                     guest_IA_curr_instr + ((ULong)(Long)(Short)i2 << 1));
4507b4
+                     addr_relative(i2));
4507b4
 
4507b4
    return "brxlg";
4507b4
 }
4507b4
@@ -5782,8 +5797,7 @@ s390_irgen_CRL(UChar r1, UInt i2)
4507b4
    IRTemp op2 = newTemp(Ity_I32);
4507b4
 
4507b4
    assign(op1, get_gpr_w1(r1));
4507b4
-   assign(op2, load(Ity_I32, mkU64(guest_IA_curr_instr + ((ULong)(Long)(Int)
4507b4
-          i2 << 1))));
4507b4
+   assign(op2, load(Ity_I32, mkU64(addr_rel_long(i2))));
4507b4
    s390_cc_thunk_putSS(S390_CC_OP_SIGNED_COMPARE, op1, op2);
4507b4
 
4507b4
    return "crl";
4507b4
@@ -5796,8 +5810,7 @@ s390_irgen_CGRL(UChar r1, UInt i2)
4507b4
    IRTemp op2 = newTemp(Ity_I64);
4507b4
 
4507b4
    assign(op1, get_gpr_dw0(r1));
4507b4
-   assign(op2, load(Ity_I64, mkU64(guest_IA_curr_instr + ((ULong)(Long)(Int)
4507b4
-          i2 << 1))));
4507b4
+   assign(op2, load(Ity_I64, mkU64(addr_rel_long(i2))));
4507b4
    s390_cc_thunk_putSS(S390_CC_OP_SIGNED_COMPARE, op1, op2);
4507b4
 
4507b4
    return "cgrl";
4507b4
@@ -5810,8 +5823,7 @@ s390_irgen_CGFRL(UChar r1, UInt i2)
4507b4
    IRTemp op2 = newTemp(Ity_I64);
4507b4
 
4507b4
    assign(op1, get_gpr_dw0(r1));
4507b4
-   assign(op2, unop(Iop_32Sto64, load(Ity_I32, mkU64(guest_IA_curr_instr +
4507b4
-          ((ULong)(Long)(Int)i2 << 1)))));
4507b4
+   assign(op2, unop(Iop_32Sto64, load(Ity_I32, mkU64(addr_rel_long(i2)))));
4507b4
    s390_cc_thunk_putSS(S390_CC_OP_SIGNED_COMPARE, op1, op2);
4507b4
 
4507b4
    return "cgfrl";
4507b4
@@ -5875,15 +5887,14 @@ s390_irgen_CRJ(UChar r1, UChar r2, UShort i4, UChar m3)
4507b4
    if (m3 == 0) {
4507b4
    } else {
4507b4
       if (m3 == 14) {
4507b4
-         always_goto_and_chase(
4507b4
-                guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+         always_goto_and_chase(addr_relative(i4));
4507b4
       } else {
4507b4
          assign(op1, get_gpr_w1(r1));
4507b4
          assign(op2, get_gpr_w1(r2));
4507b4
          assign(cond, s390_call_calculate_icc(m3, S390_CC_OP_SIGNED_COMPARE,
4507b4
                                               op1, op2));
4507b4
          if_condition_goto(binop(Iop_CmpNE32, mkexpr(cond), mkU32(0)),
4507b4
-                           guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+                           addr_relative(i4));
4507b4
 
4507b4
       }
4507b4
    }
4507b4
@@ -5901,15 +5912,14 @@ s390_irgen_CGRJ(UChar r1, UChar r2, UShort i4, UChar m3)
4507b4
    if (m3 == 0) {
4507b4
    } else {
4507b4
       if (m3 == 14) {
4507b4
-         always_goto_and_chase(
4507b4
-                guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+         always_goto_and_chase(addr_relative(i4));
4507b4
       } else {
4507b4
          assign(op1, get_gpr_dw0(r1));
4507b4
          assign(op2, get_gpr_dw0(r2));
4507b4
          assign(cond, s390_call_calculate_icc(m3, S390_CC_OP_SIGNED_COMPARE,
4507b4
                                               op1, op2));
4507b4
          if_condition_goto(binop(Iop_CmpNE32, mkexpr(cond), mkU32(0)),
4507b4
-                           guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+                           addr_relative(i4));
4507b4
 
4507b4
       }
4507b4
    }
4507b4
@@ -5975,14 +5985,14 @@ s390_irgen_CIJ(UChar r1, UChar m3, UShort i4, UChar i2)
4507b4
    if (m3 == 0) {
4507b4
    } else {
4507b4
       if (m3 == 14) {
4507b4
-         always_goto_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+         always_goto_and_chase(addr_relative(i4));
4507b4
       } else {
4507b4
          assign(op1, get_gpr_w1(r1));
4507b4
          op2 = (Int)(Char)i2;
4507b4
          assign(cond, s390_call_calculate_icc(m3, S390_CC_OP_SIGNED_COMPARE, op1,
4507b4
                                               mktemp(Ity_I32, mkU32((UInt)op2))));
4507b4
          if_condition_goto(binop(Iop_CmpNE32, mkexpr(cond), mkU32(0)),
4507b4
-                           guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+                           addr_relative(i4));
4507b4
 
4507b4
       }
4507b4
    }
4507b4
@@ -6000,14 +6010,14 @@ s390_irgen_CGIJ(UChar r1, UChar m3, UShort i4, UChar i2)
4507b4
    if (m3 == 0) {
4507b4
    } else {
4507b4
       if (m3 == 14) {
4507b4
-         always_goto_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+         always_goto_and_chase(addr_relative(i4));
4507b4
       } else {
4507b4
          assign(op1, get_gpr_dw0(r1));
4507b4
          op2 = (Long)(Char)i2;
4507b4
          assign(cond, s390_call_calculate_icc(m3, S390_CC_OP_SIGNED_COMPARE, op1,
4507b4
                                               mktemp(Ity_I64, mkU64((ULong)op2))));
4507b4
          if_condition_goto(binop(Iop_CmpNE32, mkexpr(cond), mkU32(0)),
4507b4
-                           guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+                           addr_relative(i4));
4507b4
 
4507b4
       }
4507b4
    }
4507b4
@@ -6131,8 +6141,7 @@ s390_irgen_CHRL(UChar r1, UInt i2)
4507b4
    IRTemp op2 = newTemp(Ity_I32);
4507b4
 
4507b4
    assign(op1, get_gpr_w1(r1));
4507b4
-   assign(op2, unop(Iop_16Sto32, load(Ity_I16, mkU64(guest_IA_curr_instr +
4507b4
-          ((ULong)(Long)(Int)i2 << 1)))));
4507b4
+   assign(op2, unop(Iop_16Sto32, load(Ity_I16, mkU64(addr_rel_long(i2)))));
4507b4
    s390_cc_thunk_putSS(S390_CC_OP_SIGNED_COMPARE, op1, op2);
4507b4
 
4507b4
    return "chrl";
4507b4
@@ -6145,8 +6154,7 @@ s390_irgen_CGHRL(UChar r1, UInt i2)
4507b4
    IRTemp op2 = newTemp(Ity_I64);
4507b4
 
4507b4
    assign(op1, get_gpr_dw0(r1));
4507b4
-   assign(op2, unop(Iop_16Sto64, load(Ity_I16, mkU64(guest_IA_curr_instr +
4507b4
-          ((ULong)(Long)(Int)i2 << 1)))));
4507b4
+   assign(op2, unop(Iop_16Sto64, load(Ity_I16, mkU64(addr_rel_long(i2)))));
4507b4
    s390_cc_thunk_putSS(S390_CC_OP_SIGNED_COMPARE, op1, op2);
4507b4
 
4507b4
    return "cghrl";
4507b4
@@ -6401,8 +6409,7 @@ s390_irgen_CLRL(UChar r1, UInt i2)
4507b4
    IRTemp op2 = newTemp(Ity_I32);
4507b4
 
4507b4
    assign(op1, get_gpr_w1(r1));
4507b4
-   assign(op2, load(Ity_I32, mkU64(guest_IA_curr_instr + ((ULong)(Long)(Int)
4507b4
-          i2 << 1))));
4507b4
+   assign(op2, load(Ity_I32, mkU64(addr_rel_long(i2))));
4507b4
    s390_cc_thunk_putZZ(S390_CC_OP_UNSIGNED_COMPARE, op1, op2);
4507b4
 
4507b4
    return "clrl";
4507b4
@@ -6415,8 +6422,7 @@ s390_irgen_CLGRL(UChar r1, UInt i2)
4507b4
    IRTemp op2 = newTemp(Ity_I64);
4507b4
 
4507b4
    assign(op1, get_gpr_dw0(r1));
4507b4
-   assign(op2, load(Ity_I64, mkU64(guest_IA_curr_instr + ((ULong)(Long)(Int)
4507b4
-          i2 << 1))));
4507b4
+   assign(op2, load(Ity_I64, mkU64(addr_rel_long(i2))));
4507b4
    s390_cc_thunk_putZZ(S390_CC_OP_UNSIGNED_COMPARE, op1, op2);
4507b4
 
4507b4
    return "clgrl";
4507b4
@@ -6429,8 +6435,7 @@ s390_irgen_CLGFRL(UChar r1, UInt i2)
4507b4
    IRTemp op2 = newTemp(Ity_I64);
4507b4
 
4507b4
    assign(op1, get_gpr_dw0(r1));
4507b4
-   assign(op2, unop(Iop_32Uto64, load(Ity_I32, mkU64(guest_IA_curr_instr +
4507b4
-          ((ULong)(Long)(Int)i2 << 1)))));
4507b4
+   assign(op2, unop(Iop_32Uto64, load(Ity_I32, mkU64(addr_rel_long(i2)))));
4507b4
    s390_cc_thunk_putZZ(S390_CC_OP_UNSIGNED_COMPARE, op1, op2);
4507b4
 
4507b4
    return "clgfrl";
4507b4
@@ -6443,8 +6448,7 @@ s390_irgen_CLHRL(UChar r1, UInt i2)
4507b4
    IRTemp op2 = newTemp(Ity_I32);
4507b4
 
4507b4
    assign(op1, get_gpr_w1(r1));
4507b4
-   assign(op2, unop(Iop_16Uto32, load(Ity_I16, mkU64(guest_IA_curr_instr +
4507b4
-          ((ULong)(Long)(Int)i2 << 1)))));
4507b4
+   assign(op2, unop(Iop_16Uto32, load(Ity_I16, mkU64(addr_rel_long(i2)))));
4507b4
    s390_cc_thunk_putZZ(S390_CC_OP_UNSIGNED_COMPARE, op1, op2);
4507b4
 
4507b4
    return "clhrl";
4507b4
@@ -6457,8 +6461,7 @@ s390_irgen_CLGHRL(UChar r1, UInt i2)
4507b4
    IRTemp op2 = newTemp(Ity_I64);
4507b4
 
4507b4
    assign(op1, get_gpr_dw0(r1));
4507b4
-   assign(op2, unop(Iop_16Uto64, load(Ity_I16, mkU64(guest_IA_curr_instr +
4507b4
-          ((ULong)(Long)(Int)i2 << 1)))));
4507b4
+   assign(op2, unop(Iop_16Uto64, load(Ity_I16, mkU64(addr_rel_long(i2)))));
4507b4
    s390_cc_thunk_putZZ(S390_CC_OP_UNSIGNED_COMPARE, op1, op2);
4507b4
 
4507b4
    return "clghrl";
4507b4
@@ -6730,14 +6733,14 @@ s390_irgen_CLRJ(UChar r1, UChar r2, UShort i4, UChar m3)
4507b4
    if (m3 == 0) {
4507b4
    } else {
4507b4
       if (m3 == 14) {
4507b4
-         always_goto_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+         always_goto_and_chase(addr_relative(i4));
4507b4
       } else {
4507b4
          assign(op1, get_gpr_w1(r1));
4507b4
          assign(op2, get_gpr_w1(r2));
4507b4
          assign(cond, s390_call_calculate_icc(m3, S390_CC_OP_UNSIGNED_COMPARE,
4507b4
                                               op1, op2));
4507b4
          if_condition_goto(binop(Iop_CmpNE32, mkexpr(cond), mkU32(0)),
4507b4
-                           guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+                           addr_relative(i4));
4507b4
 
4507b4
       }
4507b4
    }
4507b4
@@ -6755,14 +6758,14 @@ s390_irgen_CLGRJ(UChar r1, UChar r2, UShort i4, UChar m3)
4507b4
    if (m3 == 0) {
4507b4
    } else {
4507b4
       if (m3 == 14) {
4507b4
-         always_goto_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+         always_goto_and_chase(addr_relative(i4));
4507b4
       } else {
4507b4
          assign(op1, get_gpr_dw0(r1));
4507b4
          assign(op2, get_gpr_dw0(r2));
4507b4
          assign(cond, s390_call_calculate_icc(m3, S390_CC_OP_UNSIGNED_COMPARE,
4507b4
                                               op1, op2));
4507b4
          if_condition_goto(binop(Iop_CmpNE32, mkexpr(cond), mkU32(0)),
4507b4
-                           guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+                           addr_relative(i4));
4507b4
 
4507b4
       }
4507b4
    }
4507b4
@@ -6828,14 +6831,14 @@ s390_irgen_CLIJ(UChar r1, UChar m3, UShort i4, UChar i2)
4507b4
    if (m3 == 0) {
4507b4
    } else {
4507b4
       if (m3 == 14) {
4507b4
-         always_goto_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+         always_goto_and_chase(addr_relative(i4));
4507b4
       } else {
4507b4
          assign(op1, get_gpr_w1(r1));
4507b4
          op2 = (UInt)i2;
4507b4
          assign(cond, s390_call_calculate_icc(m3, S390_CC_OP_UNSIGNED_COMPARE, op1,
4507b4
                                               mktemp(Ity_I32, mkU32(op2))));
4507b4
          if_condition_goto(binop(Iop_CmpNE32, mkexpr(cond), mkU32(0)),
4507b4
-                           guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+                           addr_relative(i4));
4507b4
 
4507b4
       }
4507b4
    }
4507b4
@@ -6853,14 +6856,14 @@ s390_irgen_CLGIJ(UChar r1, UChar m3, UShort i4, UChar i2)
4507b4
    if (m3 == 0) {
4507b4
    } else {
4507b4
       if (m3 == 14) {
4507b4
-         always_goto_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+         always_goto_and_chase(addr_relative(i4));
4507b4
       } else {
4507b4
          assign(op1, get_gpr_dw0(r1));
4507b4
          op2 = (ULong)i2;
4507b4
          assign(cond, s390_call_calculate_icc(m3, S390_CC_OP_UNSIGNED_COMPARE, op1,
4507b4
                                               mktemp(Ity_I64, mkU64(op2))));
4507b4
          if_condition_goto(binop(Iop_CmpNE32, mkexpr(cond), mkU32(0)),
4507b4
-                           guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
4507b4
+                           addr_relative(i4));
4507b4
 
4507b4
       }
4507b4
    }
4507b4
@@ -7539,8 +7542,7 @@ s390_irgen_LGFI(UChar r1, UInt i2)
4507b4
 static const HChar *
4507b4
 s390_irgen_LRL(UChar r1, UInt i2)
4507b4
 {
4507b4
-   put_gpr_w1(r1, load(Ity_I32, mkU64(guest_IA_curr_instr + ((ULong)(Long)(Int)
4507b4
-              i2 << 1))));
4507b4
+   put_gpr_w1(r1, load(Ity_I32, mkU64(addr_rel_long(i2))));
4507b4
 
4507b4
    return "lrl";
4507b4
 }
4507b4
@@ -7548,8 +7550,7 @@ s390_irgen_LRL(UChar r1, UInt i2)
4507b4
 static const HChar *
4507b4
 s390_irgen_LGRL(UChar r1, UInt i2)
4507b4
 {
4507b4
-   put_gpr_dw0(r1, load(Ity_I64, mkU64(guest_IA_curr_instr + ((ULong)(Long)(Int)
4507b4
-               i2 << 1))));
4507b4
+   put_gpr_dw0(r1, load(Ity_I64, mkU64(addr_rel_long(i2))));
4507b4
 
4507b4
    return "lgrl";
4507b4
 }
4507b4
@@ -7557,8 +7558,7 @@ s390_irgen_LGRL(UChar r1, UInt i2)
4507b4
 static const HChar *
4507b4
 s390_irgen_LGFRL(UChar r1, UInt i2)
4507b4
 {
4507b4
-   put_gpr_dw0(r1, unop(Iop_32Sto64, load(Ity_I32, mkU64(guest_IA_curr_instr +
4507b4
-               ((ULong)(Long)(Int)i2 << 1)))));
4507b4
+   put_gpr_dw0(r1, unop(Iop_32Sto64, load(Ity_I32, mkU64(addr_rel_long(i2)))));
4507b4
 
4507b4
    return "lgfrl";
4507b4
 }
4507b4
@@ -7598,7 +7598,7 @@ s390_irgen_LAEY(UChar r1, IRTemp op2addr)
4507b4
 static const HChar *
4507b4
 s390_irgen_LARL(UChar r1, UInt i2)
4507b4
 {
4507b4
-   put_gpr_dw0(r1, mkU64(guest_IA_curr_instr + ((ULong)(Long)(Int)i2 << 1)));
4507b4
+   put_gpr_dw0(r1, mkU64(addr_rel_long(i2)));
4507b4
 
4507b4
    return "larl";
4507b4
 }
4507b4
@@ -8038,8 +8038,7 @@ s390_irgen_LGHI(UChar r1, UShort i2)
4507b4
 static const HChar *
4507b4
 s390_irgen_LHRL(UChar r1, UInt i2)
4507b4
 {
4507b4
-   put_gpr_w1(r1, unop(Iop_16Sto32, load(Ity_I16, mkU64(guest_IA_curr_instr +
4507b4
-              ((ULong)(Long)(Int)i2 << 1)))));
4507b4
+   put_gpr_w1(r1, unop(Iop_16Sto32, load(Ity_I16, mkU64(addr_rel_long(i2)))));
4507b4
 
4507b4
    return "lhrl";
4507b4
 }
4507b4
@@ -8047,8 +8046,7 @@ s390_irgen_LHRL(UChar r1, UInt i2)
4507b4
 static const HChar *
4507b4
 s390_irgen_LGHRL(UChar r1, UInt i2)
4507b4
 {
4507b4
-   put_gpr_dw0(r1, unop(Iop_16Sto64, load(Ity_I16, mkU64(guest_IA_curr_instr +
4507b4
-               ((ULong)(Long)(Int)i2 << 1)))));
4507b4
+   put_gpr_dw0(r1, unop(Iop_16Sto64, load(Ity_I16, mkU64(addr_rel_long(i2)))));
4507b4
 
4507b4
    return "lghrl";
4507b4
 }
4507b4
@@ -8088,8 +8086,7 @@ s390_irgen_LLGF(UChar r1, IRTemp op2addr)
4507b4
 static const HChar *
4507b4
 s390_irgen_LLGFRL(UChar r1, UInt i2)
4507b4
 {
4507b4
-   put_gpr_dw0(r1, unop(Iop_32Uto64, load(Ity_I32, mkU64(guest_IA_curr_instr +
4507b4
-               ((ULong)(Long)(Int)i2 << 1)))));
4507b4
+   put_gpr_dw0(r1, unop(Iop_32Uto64, load(Ity_I32, mkU64(addr_rel_long(i2)))));
4507b4
 
4507b4
    return "llgfrl";
4507b4
 }
4507b4
@@ -8169,8 +8166,7 @@ s390_irgen_LLGH(UChar r1, IRTemp op2addr)
4507b4
 static const HChar *
4507b4
 s390_irgen_LLHRL(UChar r1, UInt i2)
4507b4
 {
4507b4
-   put_gpr_w1(r1, unop(Iop_16Uto32, load(Ity_I16, mkU64(guest_IA_curr_instr +
4507b4
-              ((ULong)(Long)(Int)i2 << 1)))));
4507b4
+   put_gpr_w1(r1, unop(Iop_16Uto32, load(Ity_I16, mkU64(addr_rel_long(i2)))));
4507b4
 
4507b4
    return "llhrl";
4507b4
 }
4507b4
@@ -8178,8 +8174,7 @@ s390_irgen_LLHRL(UChar r1, UInt i2)
4507b4
 static const HChar *
4507b4
 s390_irgen_LLGHRL(UChar r1, UInt i2)
4507b4
 {
4507b4
-   put_gpr_dw0(r1, unop(Iop_16Uto64, load(Ity_I16, mkU64(guest_IA_curr_instr +
4507b4
-               ((ULong)(Long)(Int)i2 << 1)))));
4507b4
+   put_gpr_dw0(r1, unop(Iop_16Uto64, load(Ity_I16, mkU64(addr_rel_long(i2)))));
4507b4
 
4507b4
    return "llghrl";
4507b4
 }
4507b4
@@ -10064,8 +10059,7 @@ s390_irgen_STG(UChar r1, IRTemp op2addr)
4507b4
 static const HChar *
4507b4
 s390_irgen_STRL(UChar r1, UInt i2)
4507b4
 {
4507b4
-   store(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Int)i2 << 1)),
4507b4
-         get_gpr_w1(r1));
4507b4
+   store(mkU64(addr_rel_long(i2)), get_gpr_w1(r1));
4507b4
 
4507b4
    return "strl";
4507b4
 }
4507b4
@@ -10073,8 +10067,7 @@ s390_irgen_STRL(UChar r1, UInt i2)
4507b4
 static const HChar *
4507b4
 s390_irgen_STGRL(UChar r1, UInt i2)
4507b4
 {
4507b4
-   store(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Int)i2 << 1)),
4507b4
-         get_gpr_dw0(r1));
4507b4
+   store(mkU64(addr_rel_long(i2)), get_gpr_dw0(r1));
4507b4
 
4507b4
    return "stgrl";
4507b4
 }
4507b4
@@ -10203,8 +10196,7 @@ s390_irgen_STHY(UChar r1, IRTemp op2addr)
4507b4
 static const HChar *
4507b4
 s390_irgen_STHRL(UChar r1, UInt i2)
4507b4
 {
4507b4
-   store(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Int)i2 << 1)),
4507b4
-         get_gpr_hw3(r1));
4507b4
+   store(mkU64(addr_rel_long(i2)), get_gpr_hw3(r1));
4507b4
 
4507b4
    return "sthrl";
4507b4
 }
4507b4
@@ -13282,7 +13274,7 @@ static const HChar *
4507b4
 s390_irgen_EXRL(UChar r1, UInt offset)
4507b4
 {
4507b4
    IRTemp addr = newTemp(Ity_I64);
4507b4
-   Addr64 bytes_addr = guest_IA_curr_instr + offset * 2UL;
4507b4
+   Addr64 bytes_addr = addr_rel_long(offset);
4507b4
    UChar *bytes = (UChar *)(HWord)bytes_addr;
4507b4
    /* we might save one round trip because we know the target */
4507b4
    if (!last_execute_target)
4507b4
diff --git a/none/tests/s390x/exrl.c b/none/tests/s390x/exrl.c
4507b4
index 2c99602d8..e669e484f 100644
4507b4
--- a/none/tests/s390x/exrl.c
4507b4
+++ b/none/tests/s390x/exrl.c
4507b4
@@ -54,6 +54,17 @@ int main(void)
4507b4
    printf("|\n");
4507b4
    printf("\n");
4507b4
 
4507b4
+   printf("------- EXRL with negative offset\n");
4507b4
+   asm volatile( "j    2f\n\t"
4507b4
+                 "1:\n\t"
4507b4
+                 "mvc  2(1,%0),0(%0)\n\t"
4507b4
+                 "2:\n\t"
4507b4
+                 "lghi 1,8\n\t"
4507b4
+                 ".insn ril,0xc60000000000,1,1b\n\t" // exrl 1, 1b
4507b4
+                 : : "a" (target)
4507b4
+                 : "1", "2", "3", "4");
4507b4
+   printf("        target = |%s|\n", target);
4507b4
+
4507b4
    return 0;
4507b4
 }
4507b4
 
4507b4
diff --git a/none/tests/s390x/exrl.stdout.exp b/none/tests/s390x/exrl.stdout.exp
4507b4
index 520919e92..30dcde829 100644
4507b4
--- a/none/tests/s390x/exrl.stdout.exp
4507b4
+++ b/none/tests/s390x/exrl.stdout.exp
4507b4
@@ -11,3 +11,5 @@ after:  target = |0123456789aXXXXX|
4507b4
 ------- EXRL to OR in the syscall number (writes out target)
4507b4
         target = |0123456789aXXXXX|
4507b4
 
4507b4
+------- EXRL with negative offset
4507b4
+        target = |01010101010XXXXX|