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