enum { Invalid_execute_target = 1 };
ULong last_execute_target = Invalid_execute_target;
+/* The guest address to be used as the base for relative addresses. */
+Addr64 guest_IA_rel_base;
+
/* The possible outcomes of a decoding operation */
typedef enum {
S390_DECODE_OK,
static __inline__ Addr64
addr_rel_long(UInt offset)
{
- return guest_IA_curr_instr + ((Addr64)(Long)(Int)offset << 1);
+ return guest_IA_rel_base + ((Addr64)(Long)(Int)offset << 1);
}
/* Return the 64-bit address with the given 16-bit "relative" offset from the
static __inline__ Addr64
addr_relative(UShort offset)
{
- return guest_IA_curr_instr + ((Addr64)(Long)(Short)offset << 1);
+ return guest_IA_rel_base + ((Addr64)(Long)(Short)offset << 1);
}
/* Little helper function for my sanity. ITE = if-then-else */
IRTemp target = newTemp(Ity_I64);
if (r2 == 0) {
- put_gpr_dw0(r1, mkU64(guest_IA_curr_instr + 2ULL));
+ put_gpr_dw0(r1, mkU64(guest_IA_next_instr));
} else {
if (r1 != r2) {
- put_gpr_dw0(r1, mkU64(guest_IA_curr_instr + 2ULL));
+ put_gpr_dw0(r1, mkU64(guest_IA_next_instr));
call_function(get_gpr_dw0(r2));
} else {
assign(target, get_gpr_dw0(r2));
- put_gpr_dw0(r1, mkU64(guest_IA_curr_instr + 2ULL));
+ put_gpr_dw0(r1, mkU64(guest_IA_next_instr));
call_function(mkexpr(target));
}
}
{
IRTemp target = newTemp(Ity_I64);
- put_gpr_dw0(r1, mkU64(guest_IA_curr_instr + 4ULL));
+ put_gpr_dw0(r1, mkU64(guest_IA_next_instr));
assign(target, mkexpr(op2addr));
call_function(mkexpr(target));
static const HChar *
s390_irgen_BRAS(UChar r1, UShort i2)
{
- put_gpr_dw0(r1, mkU64(guest_IA_curr_instr + 4ULL));
+ put_gpr_dw0(r1, mkU64(guest_IA_next_instr));
call_function_and_chase(addr_relative(i2));
return "bras";
static const HChar *
s390_irgen_BRASL(UChar r1, UInt i2)
{
- put_gpr_dw0(r1, mkU64(guest_IA_curr_instr + 6ULL));
+ put_gpr_dw0(r1, mkU64(guest_IA_next_instr));
call_function_and_chase(addr_rel_long(i2));
return "brasl";
assign(cond, binop(Iop_CmpNE64, mkexpr(torun), mkU64(last_execute_target)));
/* If not, save the new value */
d = unsafeIRDirty_0_N (0, "s390x_dirtyhelper_EX", &s390x_dirtyhelper_EX,
- mkIRExprVec_1(mkexpr(torun)));
+ mkIRExprVec_2(mkexpr(torun), mkexpr(addr2)));
d->guard = mkexpr(cond);
stmt(IRStmt_Dirty(d));
/* so safe the code... */
d = unsafeIRDirty_0_N (0, "s390x_dirtyhelper_EX", &s390x_dirtyhelper_EX,
- mkIRExprVec_1(mkexpr(unmodified_insn)));
+ mkIRExprVec_2(mkexpr(unmodified_insn), mkexpr(addr2)));
stmt(IRStmt_Dirty(d));
/* and restart */
stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_CMSTART),
assign(torun, binop(Iop_Or64, mkexpr(unmodified_insn),
binop(Iop_Shl64, mkexpr(orperand), mkU8(48))));
- /* Start with a check that saved code is still correct */
- assign(cond, binop(Iop_CmpNE64, mkexpr(torun),
- mkU64(last_execute_target)));
- /* If not, save the new value */
+ /* Start with a check that saved code is still correct. Compare the target
+ * address as well, since it may be relevant to relative addressing. */
+ assign(
+ cond,
+ binop(Iop_Or1,
+ binop(Iop_CmpNE64, mkexpr(torun), mkU64(last_execute_target)),
+ binop(Iop_CmpNE64, mkexpr(addr2), mkU64(guest_IA_rel_base))));
+ /* If not, save the new values */
d = unsafeIRDirty_0_N (0, "s390x_dirtyhelper_EX", &s390x_dirtyhelper_EX,
- mkIRExprVec_1(mkexpr(torun)));
+ mkIRExprVec_2(mkexpr(torun), mkexpr(addr2)));
d->guard = mkexpr(cond);
stmt(IRStmt_Dirty(d));
s390_irgen_EXRL(UChar r1, UInt offset)
{
IRTemp addr = newTemp(Ity_I64);
- Addr64 bytes_addr = addr_rel_long(offset);
- UChar *bytes = (UChar *)(HWord)bytes_addr;
+ Addr64 bytes_addr;
+ UChar *bytes;
/* we might save one round trip because we know the target */
if (last_execute_target == Invalid_execute_target) {
+ bytes_addr = addr_rel_long(offset);
+ bytes = (UChar *)(HWord)bytes_addr;
last_execute_target = ((ULong)bytes[0] << 56) | ((ULong)bytes[1] << 48);
if (bytes[0] >= 0x40)
last_execute_target |= ((ULong)bytes[2] << 40) | ((ULong)bytes[3] << 32);
if (bytes[0] >= 0xc0)
last_execute_target |= ((ULong)bytes[4] << 24) | ((ULong)bytes[5] << 16);
- }
+ guest_IA_rel_base = bytes_addr;
+ } else
+ bytes_addr = guest_IA_rel_base;
assign(addr, mkU64(bytes_addr));
s390_irgen_EX(r1, addr);
return "exrl";
/* Set globals (see top of this file) */
guest_IA_curr_instr = guest_IP;
+ if (last_execute_target == Invalid_execute_target)
+ guest_IA_rel_base = guest_IA_curr_instr;
irsb = irsb_IN;
sigill_diag = sigill_diag_IN;