diff options
Diffstat (limited to 'target/arm/translate.c')
-rw-r--r-- | target/arm/translate.c | 26 |
1 files changed, 23 insertions, 3 deletions
diff --git a/target/arm/translate.c b/target/arm/translate.c index b859f10755..e32e38cadd 100644 --- a/target/arm/translate.c +++ b/target/arm/translate.c @@ -10377,6 +10377,9 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw goto illegal_op; if (insn & (1 << 26)) { + if (arm_dc_feature(s, ARM_FEATURE_M)) { + goto illegal_op; + } if (!(insn & (1 << 20))) { /* Hypervisor call (v7) */ int imm16 = extract32(insn, 16, 4) << 12 @@ -10400,7 +10403,8 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw case 0: /* msr cpsr. */ if (arm_dc_feature(s, ARM_FEATURE_M)) { tmp = load_reg(s, rn); - addr = tcg_const_i32(insn & 0xff); + /* the constant is the mask and SYSm fields */ + addr = tcg_const_i32(insn & 0xfff); gen_helper_v7m_msr(cpu_env, addr, tmp); tcg_temp_free_i32(addr); tcg_temp_free_i32(tmp); @@ -10497,7 +10501,8 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw gen_exception_return(s, tmp); break; case 6: /* MRS */ - if (extract32(insn, 5, 1)) { + if (extract32(insn, 5, 1) && + !arm_dc_feature(s, ARM_FEATURE_M)) { /* MRS (banked) */ int sysm = extract32(insn, 16, 4) | (extract32(insn, 4, 1) << 4); @@ -10506,6 +10511,14 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw break; } + if (extract32(insn, 16, 4) != 0xf) { + goto illegal_op; + } + if (!arm_dc_feature(s, ARM_FEATURE_M) && + extract32(insn, 0, 8) != 0) { + goto illegal_op; + } + /* mrs cpsr */ tmp = tcg_temp_new_i32(); if (arm_dc_feature(s, ARM_FEATURE_M)) { @@ -10518,7 +10531,8 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw store_reg(s, rd, tmp); break; case 7: /* MRS */ - if (extract32(insn, 5, 1)) { + if (extract32(insn, 5, 1) && + !arm_dc_feature(s, ARM_FEATURE_M)) { /* MRS (banked) */ int sysm = extract32(insn, 16, 4) | (extract32(insn, 4, 1) << 4); @@ -10532,6 +10546,12 @@ static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw if (IS_USER(s) || arm_dc_feature(s, ARM_FEATURE_M)) { goto illegal_op; } + + if (extract32(insn, 16, 4) != 0xf || + extract32(insn, 0, 8) != 0) { + goto illegal_op; + } + tmp = load_cpu_field(spsr); store_reg(s, rd, tmp); break; |