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