aboutsummaryrefslogtreecommitdiff
path: root/target/s390x/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/s390x/translate.c')
-rw-r--r--target/s390x/translate.c15
1 files changed, 15 insertions, 0 deletions
diff --git a/target/s390x/translate.c b/target/s390x/translate.c
index ac10f42..be32938 100644
--- a/target/s390x/translate.c
+++ b/target/s390x/translate.c
@@ -1214,6 +1214,7 @@ typedef struct {
#define IF_DFP 0x0010 /* decimal floating point instruction */
#define IF_PRIV 0x0020 /* privileged instruction */
#define IF_VEC 0x0040 /* vector instruction */
+#define IF_IO 0x0080 /* input/output instruction */
struct DisasInsn {
unsigned opc:16;
@@ -6369,6 +6370,7 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
const DisasInsn *insn;
DisasJumpType ret = DISAS_NEXT;
DisasOps o = {};
+ bool icount = false;
/* Search for the insn in the table. */
insn = extract_insn(env, s);
@@ -6435,6 +6437,14 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
return DISAS_NORETURN;
}
}
+
+ /* input/output is the special case for icount mode */
+ if (unlikely(insn->flags & IF_IO)) {
+ icount = tb_cflags(s->base.tb) & CF_USE_ICOUNT;
+ if (icount) {
+ gen_io_start();
+ }
+ }
}
/* Check for insn specification exceptions. */
@@ -6488,6 +6498,11 @@ static DisasJumpType translate_one(CPUS390XState *env, DisasContext *s)
tcg_temp_free_i64(o.addr1);
}
+ /* io should be the last instruction in tb when icount is enabled */
+ if (unlikely(icount && ret == DISAS_NEXT)) {
+ ret = DISAS_PC_STALE;
+ }
+
#ifndef CONFIG_USER_ONLY
if (s->base.tb->flags & FLAG_MASK_PER) {
/* An exception might be triggered, save PSW if not already done. */