VEX-side changes to enable chasing of unconditional jumps/calls
for s390x. See also valgrind r11899.
git-svn-id: svn://svn.valgrind.org/vex/trunk@2174 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest_s390_toIR.c b/priv/guest_s390_toIR.c
index 2849665..98ecaa3 100644
--- a/priv/guest_s390_toIR.c
+++ b/priv/guest_s390_toIR.c
@@ -69,6 +69,10 @@
/* Result of disassembly step. */
static DisResult *dis_res;
+/* Resteer function and callback data */
+static Bool (*resteer_fn)(void *, Addr64);
+static void *resteer_data;
+
/* The last seen execute target instruction */
ULong last_execute_target;
@@ -245,6 +249,20 @@
dis_res->whatNext = Dis_StopHere;
}
+/* Function call with known target. */
+static void
+call_function_and_chase(Addr64 callee_address)
+{
+ if (resteer_fn(resteer_data, callee_address)) {
+ dis_res->whatNext = Dis_ResteerU;
+ dis_res->continueAt = callee_address;
+ } else {
+ irsb->next = mkU64(callee_address);
+ irsb->jumpkind = Ijk_Call;
+ dis_res->whatNext = Dis_StopHere;
+ }
+}
+
/* Function return sequence */
static void
return_from_function(IRExpr *return_address)
@@ -301,6 +319,20 @@
dis_res->whatNext = Dis_StopHere;
}
+/* An unconditional branch to a known target. */
+static void
+always_goto_and_chase(Addr64 target)
+{
+ if (resteer_fn(resteer_data, target)) {
+ dis_res->whatNext = Dis_ResteerU;
+ dis_res->continueAt = target;
+ } else {
+ irsb->next = mkU64(target);
+ irsb->jumpkind = Ijk_Boring;
+ dis_res->whatNext = Dis_StopHere;
+ }
+}
+
/* A system call */
static void
system_call(IRExpr *sysno)
@@ -3199,7 +3231,7 @@
s390_irgen_BRAS(UChar r1, UShort i2)
{
put_gpr_dw0(r1, mkU64(guest_IA_curr_instr + 4ULL));
- call_function(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Short)i2 << 1)));
+ call_function_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Short)i2 << 1));
return "bras";
}
@@ -3208,7 +3240,7 @@
s390_irgen_BRASL(UChar r1, UInt i2)
{
put_gpr_dw0(r1, mkU64(guest_IA_curr_instr + 6ULL));
- call_function(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Int)i2 << 1)));
+ call_function_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Int)i2 << 1));
return "brasl";
}
@@ -3221,8 +3253,8 @@
if (r1 == 0) {
} else {
if (r1 == 15) {
- always_goto(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Short)i2 << 1))
- );
+ always_goto_and_chase(
+ guest_IA_curr_instr + ((ULong)(Long)(Short)i2 << 1));
} else {
assign(cond, s390_call_calculate_cond(r1));
if_condition_goto(binop(Iop_CmpNE32, mkexpr(cond), mkU32(0)),
@@ -3244,7 +3276,7 @@
if (r1 == 0) {
} else {
if (r1 == 15) {
- always_goto(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Int)i2 << 1)));
+ always_goto_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Int)i2 << 1));
} else {
assign(cond, s390_call_calculate_cond(r1));
if_condition_goto(binop(Iop_CmpNE32, mkexpr(cond), mkU32(0)),
@@ -3555,8 +3587,8 @@
if (m3 == 0) {
} else {
if (m3 == 14) {
- always_goto(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1))
- );
+ always_goto_and_chase(
+ guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
} else {
assign(op1, get_gpr_w1(r1));
assign(op2, get_gpr_w1(r2));
@@ -3584,8 +3616,8 @@
if (m3 == 0) {
} else {
if (m3 == 14) {
- always_goto(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1))
- );
+ always_goto_and_chase(
+ guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
} else {
assign(op1, get_gpr_dw0(r1));
assign(op2, get_gpr_dw0(r2));
@@ -3667,8 +3699,7 @@
if (m3 == 0) {
} else {
if (m3 == 14) {
- always_goto(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1))
- );
+ always_goto_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
} else {
assign(op1, get_gpr_w1(r1));
op2 = (Int)(Char)i2;
@@ -3696,8 +3727,7 @@
if (m3 == 0) {
} else {
if (m3 == 14) {
- always_goto(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1))
- );
+ always_goto_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
} else {
assign(op1, get_gpr_dw0(r1));
op2 = (Long)(Char)i2;
@@ -4228,8 +4258,7 @@
if (m3 == 0) {
} else {
if (m3 == 14) {
- always_goto(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1))
- );
+ always_goto_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
} else {
assign(op1, get_gpr_w1(r1));
assign(op2, get_gpr_w1(r2));
@@ -4257,8 +4286,7 @@
if (m3 == 0) {
} else {
if (m3 == 14) {
- always_goto(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1))
- );
+ always_goto_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
} else {
assign(op1, get_gpr_dw0(r1));
assign(op2, get_gpr_dw0(r2));
@@ -4340,8 +4368,7 @@
if (m3 == 0) {
} else {
if (m3 == 14) {
- always_goto(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1))
- );
+ always_goto_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
} else {
assign(op1, get_gpr_w1(r1));
op2 = (UInt)i2;
@@ -4369,8 +4396,7 @@
if (m3 == 0) {
} else {
if (m3 == 14) {
- always_goto(mkU64(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1))
- );
+ always_goto_and_chase(guest_IA_curr_instr + ((ULong)(Long)(Short)i4 << 1));
} else {
assign(op1, get_gpr_dw0(r1));
op2 = (ULong)i2;
@@ -8637,10 +8663,11 @@
mkU64(0)),
guest_IA_next_instr);
- always_goto(mkU64(guest_IA_curr_instr));
+ always_goto_and_chase(guest_IA_curr_instr);
return "clcle";
}
+
static void
s390_irgen_XC_EX(IRTemp length, IRTemp start1, IRTemp start2)
{
@@ -13020,6 +13047,8 @@
/* fixs390: we should probably pass the resteer-function and the callback
data. It's not needed for correctness but improves performance. */
+ resteer_fn = resteerOkFn;
+ resteer_data = callback_data;
/* Normal and special instruction handling starts here. */
if (s390_decode_and_irgen(insn, insn_length, &dres) == 0) {