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