summaryrefslogtreecommitdiff
path: root/target/arm/translate.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/arm/translate.c')
-rw-r--r--target/arm/translate.c29
1 files changed, 28 insertions, 1 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 50339e7bdd..e15192d5d6 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -9810,7 +9810,7 @@ static int disas_thumb2_insn(DisasContext *s, uint32_t insn)
if (insn & (1 << 22)) {
/* 0b1110_100x_x1xx_xxxx_xxxx_xxxx_xxxx_xxxx
* - load/store doubleword, load/store exclusive, ldacq/strel,
- * table branch.
+ * table branch, TT.
*/
if (insn == 0xe97fe97f && arm_dc_feature(s, ARM_FEATURE_M) &&
arm_dc_feature(s, ARM_FEATURE_V8)) {
@@ -9887,8 +9887,35 @@ static int disas_thumb2_insn(DisasContext *s, uint32_t insn)
} else if ((insn & (1 << 23)) == 0) {
/* 0b1110_1000_010x_xxxx_xxxx_xxxx_xxxx_xxxx
* - load/store exclusive word
+ * - TT (v8M only)
*/
if (rs == 15) {
+ if (!(insn & (1 << 20)) &&
+ arm_dc_feature(s, ARM_FEATURE_M) &&
+ arm_dc_feature(s, ARM_FEATURE_V8)) {
+ /* 0b1110_1000_0100_xxxx_1111_xxxx_xxxx_xxxx
+ * - TT (v8M only)
+ */
+ bool alt = insn & (1 << 7);
+ TCGv_i32 addr, op, ttresp;
+
+ if ((insn & 0x3f) || rd == 13 || rd == 15 || rn == 15) {
+ /* we UNDEF for these UNPREDICTABLE cases */
+ goto illegal_op;
+ }
+
+ if (alt && !s->v8m_secure) {
+ goto illegal_op;
+ }
+
+ addr = load_reg(s, rn);
+ op = tcg_const_i32(extract32(insn, 6, 2));
+ ttresp = tcg_temp_new_i32();
+ gen_helper_v7m_tt(ttresp, cpu_env, addr, op);
+ tcg_temp_free_i32(addr);
+ tcg_temp_free_i32(op);
+ store_reg(s, rd, ttresp);
+ }
goto illegal_op;
}
addr = tcg_temp_local_new_i32();