aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--target/arm/translate.c15
1 files changed, 13 insertions, 2 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c
index a5d7723423..7853462b21 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -11594,7 +11594,14 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
gen_nop_hint(s, (insn >> 4) & 0xf);
break;
}
- /* If Then. */
+ /*
+ * IT (If-Then)
+ *
+ * Combinations of firstcond and mask which set up an 0b1111
+ * condition are UNPREDICTABLE; we take the CONSTRAINED
+ * UNPREDICTABLE choice to treat 0b1111 the same as 0b1110,
+ * i.e. both meaning "execute always".
+ */
s->condexec_cond = (insn >> 4) & 0xe;
s->condexec_mask = insn & 0x1f;
/* No actual code generated for this insn, just setup state. */
@@ -12128,7 +12135,11 @@ static void thumb_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
if (dc->condexec_mask && !thumb_insn_is_unconditional(dc, insn)) {
uint32_t cond = dc->condexec_cond;
- if (cond != 0x0e) { /* Skip conditional when condition is AL. */
+ /*
+ * Conditionally skip the insn. Note that both 0xe and 0xf mean
+ * "always"; 0xf is not "never".
+ */
+ if (cond < 0x0e) {
arm_skip_unless(dc, cond);
}
}