aboutsummaryrefslogtreecommitdiff
path: root/target
diff options
context:
space:
mode:
authorRichard Henderson <richard.henderson@linaro.org>2019-09-04 12:30:53 -0700
committerPeter Maydell <peter.maydell@linaro.org>2019-09-05 13:23:04 +0100
commit43f7e42c7d515f41ff243034f51b28267ae69938 (patch)
treedd4266f08458d504fea3630b864f2dabcf448430 /target
parent629fcaa71ca9a5d6695d1664257b6a5327f38bd6 (diff)
target/arm: Convert T16, Miscellaneous 16-bit instructions
Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20190904193059.26202-64-richard.henderson@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'target')
-rw-r--r--target/arm/t16.decode31
-rw-r--r--target/arm/translate.c111
2 files changed, 55 insertions, 87 deletions
diff --git a/target/arm/t16.decode b/target/arm/t16.decode
index cbc64f4e48..f128110dee 100644
--- a/target/arm/t16.decode
+++ b/target/arm/t16.decode
@@ -211,18 +211,29 @@ REVSH 1011 1010 11 ... ... @rdm
# Hints
{
- YIELD 1011 1111 0001 0000
- WFE 1011 1111 0010 0000
- WFI 1011 1111 0011 0000
+ {
+ YIELD 1011 1111 0001 0000
+ WFE 1011 1111 0010 0000
+ WFI 1011 1111 0011 0000
+
+ # TODO: Implement SEV, SEVL; may help SMP performance.
+ # SEV 1011 1111 0100 0000
+ # SEVL 1011 1111 0101 0000
+
+ # The canonical nop has the second nibble as 0000, but the whole of the
+ # rest of the space is a reserved hint, behaves as nop.
+ NOP 1011 1111 ---- 0000
+ }
+ IT 1011 1111 cond_mask:8
+}
- # TODO: Implement SEV, SEVL; may help SMP performance.
- # SEV 1011 1111 0100 0000
- # SEVL 1011 1111 0101 0000
+# Miscellaneous 16-bit instructions
- # The canonical nop has the second nibble as 0000, but the whole of the
- # rest of the space is a reserved hint, behaves as nop.
- NOP 1011 1111 ---- 0000
-}
+%imm6_9_3 9:1 3:5 !function=times_2
+
+HLT 1011 1010 10 imm:6 &i
+BKPT 1011 1110 imm:8 &i
+CBZ 1011 nz:1 0.1 ..... rn:3 imm=%imm6_9_3
# Push and Pop
diff --git a/target/arm/translate.c b/target/arm/translate.c
index a4844992d5..48ed6f6b5d 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -10196,6 +10196,18 @@ static bool trans_TBH(DisasContext *s, arg_tbranch *a)
return op_tbranch(s, a, true);
}
+static bool trans_CBZ(DisasContext *s, arg_CBZ *a)
+{
+ TCGv_i32 tmp = load_reg(s, a->rn);
+
+ arm_gen_condlabel(s);
+ tcg_gen_brcondi_i32(a->nz ? TCG_COND_EQ : TCG_COND_NE,
+ tmp, 0, s->condlabel);
+ tcg_temp_free_i32(tmp);
+ gen_jmp(s, read_pc(s) + a->imm);
+ return true;
+}
+
/*
* Supervisor call
*/
@@ -10418,6 +10430,27 @@ static bool trans_PLI(DisasContext *s, arg_PLD *a)
}
/*
+ * If-then
+ */
+
+static bool trans_IT(DisasContext *s, arg_IT *a)
+{
+ int cond_mask = a->cond_mask;
+
+ /*
+ * No actual code generated for this insn, just setup state.
+ *
+ * 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 = (cond_mask >> 4) & 0xe;
+ s->condexec_mask = cond_mask & 0x1f;
+ return true;
+}
+
+/*
* Legacy decoder.
*/
@@ -10783,83 +10816,8 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
case 8: /* load/store halfword immediate offset, in decodetree */
case 9: /* load/store from stack, in decodetree */
case 10: /* add PC/SP (immediate), in decodetree */
+ case 11: /* misc, in decodetree */
case 12: /* load/store multiple, in decodetree */
- goto illegal_op;
-
- case 11:
- /* misc */
- op = (insn >> 8) & 0xf;
- switch (op) {
- case 0: /* add/sub (sp, immediate), in decodetree */
- case 2: /* sign/zero extend, in decodetree */
- goto illegal_op;
-
- case 4: case 5: case 0xc: case 0xd:
- /* push/pop, in decodetree */
- goto illegal_op;
-
- case 1: case 3: case 9: case 11: /* czb */
- rm = insn & 7;
- tmp = load_reg(s, rm);
- arm_gen_condlabel(s);
- if (insn & (1 << 11))
- tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
- else
- tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
- tcg_temp_free_i32(tmp);
- offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
- gen_jmp(s, read_pc(s) + offset);
- break;
-
- case 15: /* IT, nop-hint. */
- if ((insn & 0xf) == 0) {
- goto illegal_op; /* nop hint, in decodetree */
- }
- /*
- * 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. */
- break;
-
- case 0xe: /* bkpt */
- {
- int imm8 = extract32(insn, 0, 8);
- ARCH(5);
- gen_exception_bkpt_insn(s, syn_aa32_bkpt(imm8, true));
- break;
- }
-
- case 0xa: /* rev, and hlt */
- {
- int op1 = extract32(insn, 6, 2);
-
- if (op1 == 2) {
- /* HLT */
- int imm6 = extract32(insn, 0, 6);
-
- gen_hlt(s, imm6);
- break;
- }
-
- /* Otherwise this is rev, in decodetree */
- goto illegal_op;
- }
-
- case 6: /* setend, cps; in decodetree */
- goto illegal_op;
-
- default:
- goto undef;
- }
- break;
-
case 13: /* conditional branch or swi, in decodetree */
goto illegal_op;
@@ -10915,7 +10873,6 @@ static void disas_thumb_insn(DisasContext *s, uint32_t insn)
}
return;
illegal_op:
-undef:
unallocated_encoding(s);
}