target/arm: Execute Thumb instructions when their condbits are 0xf
Thumb instructions in an IT block are set up to be conditionally executed depending on a set of condition bits encoded into the IT bits of the CPSR/XPSR. The architecture specifies that if the condition bits are 0b1111 this means "always execute" (like 0b1110), not "never execute"; we were treating it as "never execute". (See the ConditionHolds() pseudocode in both the A-profile and M-profile Arm ARM.) This is a bit of an obscure corner case, because the only legal way to get to an 0b1111 set of condbits is to do an exception return which sets the XPSR/CPSR up that way. An IT instruction which encodes a condition sequence that would include an 0b1111 is UNPREDICTABLE, and for v8A the CONSTRAINED UNPREDICTABLE choices for such an IT insn are to NOP, UNDEF, or treat 0b1111 like 0b1110. Add a comment noting that we take the latter option. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20190617175317.27557-7-peter.maydell@linaro.org
This commit is contained in:
parent
9bed521ec8
commit
5529de1e55
@ -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);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user