Skip to content

Commit 1412010

Browse files
jusualpm215
authored andcommitted
target/arm: Allow ARMv6-M Thumb2 instructions
ARMv6-M supports 6 Thumb2 instructions. This patch checks for these instructions and allows their execution. Like Thumb2 cores, ARMv6-M always interprets BL instruction as 32-bit. This patch is required for future Cortex-M0 support. Signed-off-by: Julia Suvorova <jusual@mail.ru> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Message-id: 20180612204632.28780-1-jusual@mail.ru [PMM: move armv6m_insn[] and armv6m_mask[] closer to point of use, and mark 'const'. Check for M-and-not-v7 rather than M-and-6.] Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
1 parent 1f871c5 commit 1412010

File tree

1 file changed

+38
-5
lines changed

1 file changed

+38
-5
lines changed

target/arm/translate.c

Lines changed: 38 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9965,7 +9965,8 @@ static bool thumb_insn_is_16bit(DisasContext *s, uint32_t insn)
99659965
* end up actually treating this as two 16-bit insns, though,
99669966
* if it's half of a bl/blx pair that might span a page boundary.
99679967
*/
9968-
if (arm_dc_feature(s, ARM_FEATURE_THUMB2)) {
9968+
if (arm_dc_feature(s, ARM_FEATURE_THUMB2) ||
9969+
arm_dc_feature(s, ARM_FEATURE_M)) {
99699970
/* Thumb2 cores (including all M profile ones) always treat
99709971
* 32-bit insns as 32-bit.
99719972
*/
@@ -10085,10 +10086,38 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
1008510086
int conds;
1008610087
int logic_cc;
1008710088

10088-
/* The only 32 bit insn that's allowed for Thumb1 is the combined
10089-
* BL/BLX prefix and suffix.
10089+
/*
10090+
* ARMv6-M supports a limited subset of Thumb2 instructions.
10091+
* Other Thumb1 architectures allow only 32-bit
10092+
* combined BL/BLX prefix and suffix.
1009010093
*/
10091-
if ((insn & 0xf800e800) != 0xf000e800) {
10094+
if (arm_dc_feature(s, ARM_FEATURE_M) &&
10095+
!arm_dc_feature(s, ARM_FEATURE_V7)) {
10096+
int i;
10097+
bool found = false;
10098+
const uint32_t armv6m_insn[] = {0xf3808000 /* msr */,
10099+
0xf3b08040 /* dsb */,
10100+
0xf3b08050 /* dmb */,
10101+
0xf3b08060 /* isb */,
10102+
0xf3e08000 /* mrs */,
10103+
0xf000d000 /* bl */};
10104+
const uint32_t armv6m_mask[] = {0xffe0d000,
10105+
0xfff0d0f0,
10106+
0xfff0d0f0,
10107+
0xfff0d0f0,
10108+
0xffe0d000,
10109+
0xf800d000};
10110+
10111+
for (i = 0; i < ARRAY_SIZE(armv6m_insn); i++) {
10112+
if ((insn & armv6m_mask[i]) == armv6m_insn[i]) {
10113+
found = true;
10114+
break;
10115+
}
10116+
}
10117+
if (!found) {
10118+
goto illegal_op;
10119+
}
10120+
} else if ((insn & 0xf800e800) != 0xf000e800) {
1009210121
ARCH(6T2);
1009310122
}
1009410123

@@ -11009,7 +11038,11 @@ static void disas_thumb2_insn(DisasContext *s, uint32_t insn)
1100911038
}
1101011039
break;
1101111040
case 3: /* Special control operations. */
11012-
ARCH(7);
11041+
if (!arm_dc_feature(s, ARM_FEATURE_V7) &&
11042+
!(arm_dc_feature(s, ARM_FEATURE_V6) &&
11043+
arm_dc_feature(s, ARM_FEATURE_M))) {
11044+
goto illegal_op;
11045+
}
1101311046
op = (insn >> 4) & 0xf;
1101411047
switch (op) {
1101511048
case 2: /* clrex */

0 commit comments

Comments
 (0)