Translation chaining for s390. To be debugged.
git-svn-id: svn://svn.valgrind.org/vex/branches/TCHAIN@2279 8f6e269a-dfd6-0310-a8e1-e2731360e62c
diff --git a/priv/guest_s390_toIR.c b/priv/guest_s390_toIR.c
index ca23acb..5befc74 100644
--- a/priv/guest_s390_toIR.c
+++ b/priv/guest_s390_toIR.c
@@ -120,6 +120,13 @@
return IRExpr_RdTmp(tmp);
}
+/* Generate an expression node for an address. */
+static __inline__ IRExpr *
+mkaddr_expr(Addr64 addr)
+{
+ return IRExpr_Const(IRConst_U64(addr));
+}
+
/* Add a statement that assigns to a temporary */
static __inline__ void
assign(IRTemp dst, IRExpr *expr)
@@ -127,6 +134,22 @@
stmt(IRStmt_WrTmp(dst, expr));
}
+/* Write an address into the guest_IA */
+static __inline__ void
+put_IA(IRExpr *address)
+{
+ stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_IA), address));
+}
+
+/* Add a dummy put to the guest_IA to satisfy an assert in bb_to_IR
+ that wants the last statement in an IRSB to be a put to the guest_IA.
+ Mostly used for insns that use the "counter" pseudo guest reg. */
+static __inline__ void
+dummy_put_IA(void)
+{
+ put_IA(IRExpr_Get(S390X_GUEST_OFFSET(guest_IA), Ity_I64));
+}
+
/* Create a temporary of the given type and assign the expression to it */
static __inline__ IRTemp
mktemp(IRType type, IRExpr *expr)
@@ -242,10 +265,10 @@
static void
call_function(IRExpr *callee_address)
{
- irsb->next = callee_address;
- irsb->jumpkind = Ijk_Call;
+ put_IA(callee_address);
- dis_res->whatNext = Dis_StopHere;
+ dis_res->whatNext = Dis_StopHere;
+ dis_res->jk_StopHere = Ijk_Call;
}
/* Function call with known target. */
@@ -256,9 +279,10 @@
dis_res->whatNext = Dis_ResteerU;
dis_res->continueAt = callee_address;
} else {
- irsb->next = mkU64(callee_address);
- irsb->jumpkind = Ijk_Call;
+ put_IA(mkaddr_expr(callee_address));
+
dis_res->whatNext = Dis_StopHere;
+ dis_res->jk_StopHere = Ijk_Call;
}
}
@@ -266,10 +290,10 @@
static void
return_from_function(IRExpr *return_address)
{
- irsb->next = return_address;
- irsb->jumpkind = Ijk_Ret;
+ put_IA(return_address);
- dis_res->whatNext = Dis_StopHere;
+ dis_res->whatNext = Dis_StopHere;
+ dis_res->jk_StopHere = Ijk_Ret;
}
/* A conditional branch whose target is not known at instrumentation time.
@@ -289,12 +313,13 @@
{
vassert(typeOfIRExpr(irsb->tyenv, condition) == Ity_I1);
- stmt(IRStmt_Exit3(condition, Ijk_Boring, IRConst_U64(guest_IA_next_instr)));
+ stmt(IRStmt_Exit(condition, Ijk_Boring, IRConst_U64(guest_IA_next_instr),
+ S390X_GUEST_OFFSET(guest_IA)));
- irsb->next = target;
- irsb->jumpkind = Ijk_Boring;
+ put_IA(target);
- dis_res->whatNext = Dis_StopHere;
+ dis_res->whatNext = Dis_StopHere;
+ dis_res->jk_StopHere = Ijk_Boring;
}
/* A conditional branch whose target is known at instrumentation time. */
@@ -303,8 +328,13 @@
{
vassert(typeOfIRExpr(irsb->tyenv, condition) == Ity_I1);
- stmt(IRStmt_Exit3(condition, Ijk_Boring, IRConst_U64(target)));
- dis_res->whatNext = Dis_Continue;
+ stmt(IRStmt_Exit(condition, Ijk_Boring, IRConst_U64(target),
+ S390X_GUEST_OFFSET(guest_IA)));
+
+ put_IA(mkaddr_expr(target));
+
+ dis_res->whatNext = Dis_StopHere;
+ dis_res->jk_StopHere = Ijk_Boring;
}
/* An unconditional branch. Target may or may not be known at instrumentation
@@ -312,23 +342,26 @@
static void
always_goto(IRExpr *target)
{
- irsb->next = target;
- irsb->jumpkind = Ijk_Boring;
+ put_IA(target);
- dis_res->whatNext = Dis_StopHere;
+ dis_res->whatNext = Dis_StopHere;
+ dis_res->jk_StopHere = Ijk_Boring;
}
+
/* An unconditional branch to a known target. */
static void
always_goto_and_chase(Addr64 target)
{
if (resteer_fn(resteer_data, target)) {
+ /* Follow into the target */
dis_res->whatNext = Dis_ResteerU;
dis_res->continueAt = target;
} else {
- irsb->next = mkU64(target);
- irsb->jumpkind = Ijk_Boring;
- dis_res->whatNext = Dis_StopHere;
+ put_IA(mkaddr_expr(target));
+
+ dis_res->whatNext = Dis_StopHere;
+ dis_res->jk_StopHere = Ijk_Boring;
}
}
@@ -343,14 +376,13 @@
stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_IP_AT_SYSCALL),
mkU64(guest_IA_curr_instr)));
+ put_IA(mkaddr_expr(guest_IA_next_instr));
+
/* It's important that all ArchRegs carry their up-to-date value
at this point. So we declare an end-of-block here, which
forces any TempRegs caching ArchRegs to be flushed. */
- irsb->next = mkU64(guest_IA_next_instr);
-
- irsb->jumpkind = Ijk_Sys_syscall;
-
- dis_res->whatNext = Dis_StopHere;
+ dis_res->whatNext = Dis_StopHere;
+ dis_res->jk_StopHere = Ijk_Sys_syscall;
}
/* Encode the s390 rounding mode as it appears in the m3/m4 fields of certain
@@ -8576,6 +8608,7 @@
if_condition_goto(binop(Iop_CmpNE64, mkexpr(counter), mkU64(length)),
guest_IA_curr_instr);
put_counter_dw0(mkU64(0));
+ dummy_put_IA();
return "clc";
}
@@ -8869,8 +8902,8 @@
stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_TISTART),
mkU64(guest_IA_curr_instr)));
stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_TILEN), mkU64(4)));
- stmt(IRStmt_Exit3(mkexpr(cond), Ijk_TInval,
- IRConst_U64(guest_IA_curr_instr)));
+ stmt(IRStmt_Exit(mkexpr(cond), Ijk_TInval, IRConst_U64(guest_IA_curr_instr),
+ S390X_GUEST_OFFSET(guest_IA)));
ss.bytes = last_execute_target;
assign(start1, binop(Iop_Add64, mkU64(ss.dec.d1),
@@ -8880,6 +8913,8 @@
assign(len, unop(lensize == 64 ? Iop_8Uto64 : Iop_8Uto32, binop(Iop_Or8,
r != 0 ? get_gpr_b7(r): mkU8(0), mkU8(ss.dec.l))));
irgen(len, start1, start2);
+ dummy_put_IA();
+
last_execute_target = 0;
}
@@ -8900,8 +8935,9 @@
stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_TISTART),
mkU64(guest_IA_curr_instr)));
stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_TILEN), mkU64(4)));
- stmt(IRStmt_Exit3(IRExpr_Const(IRConst_U1(True)), Ijk_TInval,
- IRConst_U64(guest_IA_curr_instr)));
+ stmt(IRStmt_Exit(IRExpr_Const(IRConst_U1(True)), Ijk_TInval,
+ IRConst_U64(guest_IA_curr_instr),
+ S390X_GUEST_OFFSET(guest_IA)));
/* we know that this will be invalidated */
irsb->next = mkU64(guest_IA_next_instr);
dis_res->whatNext = Dis_StopHere;
@@ -8958,8 +8994,9 @@
/* and restart */
stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_TISTART), mkU64(guest_IA_curr_instr)));
stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_TILEN), mkU64(4)));
- stmt(IRStmt_Exit3(mkexpr(cond), Ijk_TInval,
- IRConst_U64(guest_IA_curr_instr)));
+ stmt(IRStmt_Exit(mkexpr(cond), Ijk_TInval,
+ IRConst_U64(guest_IA_curr_instr),
+ S390X_GUEST_OFFSET(guest_IA)));
/* Now comes the actual translation */
bytes = (UChar *) &last_execute_target;
@@ -9032,11 +9069,13 @@
put_counter_dw0(binop(Iop_Add64, mkexpr(counter), mkU64(1)));
put_gpr_dw0(r1, mkexpr(next));
put_gpr_dw0(r2, binop(Iop_Add64, mkexpr(address), mkU64(1)));
- stmt(IRStmt_Exit3(binop(Iop_CmpNE64, mkexpr(counter), mkU64(255)),
- Ijk_Boring, IRConst_U64(guest_IA_curr_instr)));
+ stmt(IRStmt_Exit(binop(Iop_CmpNE64, mkexpr(counter), mkU64(255)),
+ Ijk_Boring, IRConst_U64(guest_IA_curr_instr),
+ S390X_GUEST_OFFSET(guest_IA)));
// >= 256 bytes done CC=3
s390_cc_set(3);
put_counter_dw0(mkU64(0));
+ dummy_put_IA();
return "srst";
}
@@ -9098,11 +9137,13 @@
put_counter_dw0(binop(Iop_Add64, mkexpr(counter), mkU64(1)));
put_gpr_dw0(r1, binop(Iop_Add64, get_gpr_dw0(r1), mkU64(1)));
put_gpr_dw0(r2, binop(Iop_Add64, get_gpr_dw0(r2), mkU64(1)));
- stmt(IRStmt_Exit3(binop(Iop_CmpNE64, mkexpr(counter), mkU64(255)),
- Ijk_Boring, IRConst_U64(guest_IA_curr_instr)));
+ stmt(IRStmt_Exit(binop(Iop_CmpNE64, mkexpr(counter), mkU64(255)),
+ Ijk_Boring, IRConst_U64(guest_IA_curr_instr),
+ S390X_GUEST_OFFSET(guest_IA)));
// >= 256 bytes done CC=3
s390_cc_set(3);
put_counter_dw0(mkU64(0));
+ dummy_put_IA();
return "clst";
}
@@ -9297,6 +9338,7 @@
s390_cc_thunk_put1(S390_CC_OP_BITWISE, mktemp(Ity_I32, get_counter_w1()),
False);
put_counter_dw0(mkU64(0));
+ dummy_put_IA();
}
static HChar *
@@ -9338,6 +9380,7 @@
/* Reset counter */
put_counter_dw0(mkU64(0));
+ dummy_put_IA();
}
s390_cc_thunk_put1(S390_CC_OP_BITWISE, mktemp(Ity_I32, mkU32(0)), False);
@@ -9378,6 +9421,7 @@
if_condition_goto(binop(Iop_CmpNE64, mkexpr(counter), mkU64(length)),
guest_IA_curr_instr);
put_counter_dw0(mkU64(0));
+ dummy_put_IA();
return "mvc";
}
@@ -9558,6 +9602,7 @@
s390_cc_set(1);
put_gpr_dw0(r1, binop(Iop_Add64, mkexpr(addr1), mkexpr(counter)));
put_counter_dw0(mkU64(0));
+ dummy_put_IA();
return "mvst";
}
@@ -9823,8 +9868,9 @@
Otherwise, store the old_value from memory in r1 and yield. */
assign(nequal, binop(Iop_CmpNE32, s390_call_calculate_cc(), mkU32(0)));
put_gpr_w1(r1, mkite(mkexpr(nequal), mkexpr(old_mem), mkexpr(op1)));
- stmt(IRStmt_Exit3(mkexpr(nequal), Ijk_Yield,
- IRConst_U64(guest_IA_next_instr)));
+ stmt(IRStmt_Exit(mkexpr(nequal), Ijk_Yield,
+ IRConst_U64(guest_IA_next_instr),
+ S390X_GUEST_OFFSET(guest_IA)));
}
static HChar *
@@ -9872,8 +9918,9 @@
Otherwise, store the old_value from memory in r1 and yield. */
assign(nequal, binop(Iop_CmpNE32, s390_call_calculate_cc(), mkU32(0)));
put_gpr_dw0(r1, mkite(mkexpr(nequal), mkexpr(old_mem), mkexpr(op1)));
- stmt(IRStmt_Exit3(mkexpr(nequal), Ijk_Yield,
- IRConst_U64(guest_IA_next_instr)));
+ stmt(IRStmt_Exit(mkexpr(nequal), Ijk_Yield,
+ IRConst_U64(guest_IA_next_instr),
+ S390X_GUEST_OFFSET(guest_IA)));
return "csg";
}
@@ -11059,6 +11106,7 @@
guest_IA_curr_instr);
put_counter_dw0(mkU64(0));
+ dummy_put_IA();
return "tr";
}
@@ -13518,14 +13566,6 @@
}
-/* Generate an IRExpr for an address. */
-static __inline__ IRExpr *
-mkaddr_expr(Addr64 addr)
-{
- return IRExpr_Const(IRConst_U64(addr));
-}
-
-
/* Disassemble a single instruction INSN into IR. */
static DisResult
disInstr_S390_WRK(UChar *insn)
@@ -13553,6 +13593,7 @@
dres.whatNext = Dis_Continue;
dres.len = insn_length;
dres.continueAt = 0;
+ dres.jk_StopHere = Ijk_INVALID;
/* fixs390: consider chasing of conditional jumps */
@@ -13561,17 +13602,28 @@
/* All decode failures end up here. The decoder has already issued an
error message.
Tell the dispatcher that this insn cannot be decoded, and so has
- not been executed, and (is currently) the next to be executed.
- IA should be up-to-date since it made so at the start of each
- insn, but nevertheless be paranoid and update it again right
- now. */
- stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_IA),
- mkaddr_expr(guest_IA_curr_instr)));
+ not been executed, and (is currently) the next to be executed. */
+ put_IA(mkaddr_expr(guest_IA_curr_instr));
- irsb->next = mkaddr_expr(guest_IA_next_instr);
- irsb->jumpkind = Ijk_NoDecode;
- dres.whatNext = Dis_StopHere;
- dres.len = 0;
+ dres.whatNext = Dis_StopHere;
+ dres.jk_StopHere = Ijk_NoDecode;
+ dres.continueAt = 0;
+ dres.len = 0;
+ } else {
+ /* Decode success */
+ switch (dres.whatNext) {
+ case Dis_Continue:
+ put_IA(mkaddr_expr(guest_IA_curr_instr));
+ break;
+ case Dis_ResteerU:
+ case Dis_ResteerC:
+ put_IA(mkaddr_expr(dres.continueAt));
+ break;
+ case Dis_StopHere:
+ break;
+ default:
+ vassert(0);
+ }
}
return dres;
@@ -13587,7 +13639,6 @@
DisResult
disInstr_S390(IRSB *irsb_IN,
- Bool put_IP __attribute__((unused)),
Bool (*resteerOkFn)(void *, Addr64),
Bool resteerCisOk,
void *callback_opaque,
@@ -13610,10 +13661,6 @@
resteer_fn = resteerOkFn;
resteer_data = callback_opaque;
- /* Always update the guest IA. See comment in s390_isel_stmt for Ist_Put. */
- stmt(IRStmt_Put(S390X_GUEST_OFFSET(guest_IA),
- mkaddr_expr(guest_IA_curr_instr)));
-
return disInstr_S390_WRK(guest_code + delta);
}