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