CPACR register allows to control access rights to coprocessor 0-13 interfaces. Bits corresponding to unimplemented coprocessors should be RAZ/WI. QEMU implement only VFP coprocessor on ARMv6+ targets. So only cp10 & cp11 bits is writable.
Signed-off-by: Sergey Fedorov <s.fedo...@samsung.com> --- target-arm/helper.c | 6 ++++++ target-arm/translate.c | 36 +++++++++++++++++++++++++----------- 2 files changed, 31 insertions(+), 11 deletions(-) diff --git a/target-arm/helper.c b/target-arm/helper.c index 3bd0a64..19f5830 100644 --- a/target-arm/helper.c +++ b/target-arm/helper.c @@ -418,6 +418,12 @@ static const ARMCPRegInfo not_v7_cp_reginfo[] = { static int cpacr_write(CPUARMState *env, const ARMCPRegInfo *ri, uint64_t value) { + uint32_t mask = 0; + + if (arm_feature(env, ARM_FEATURE_VFP)) { + mask |= 0x00f00000; /* VFP coprocessor: cp10 & cp11 */ + } + value &= mask; if (env->cp15.c1_coproc != value) { env->cp15.c1_coproc = value; /* ??? Is this safe when called from within a TB? */ diff --git a/target-arm/translate.c b/target-arm/translate.c index a47fcdb..78612c8 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -6284,20 +6284,34 @@ static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn) ARMCPU *cpu = arm_env_get_cpu(env); cpnum = (insn >> 8) & 0xf; - if (arm_feature(env, ARM_FEATURE_XSCALE) - && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum))) - return 1; + if (cpnum < 14) { + if (arm_feature(env, ARM_FEATURE_XSCALE)) { + if (~env->cp15.c15_cpar & (1 << cpnum)) { + return 1; + } + } else { + switch ((env->cp15.c1_coproc >> (cpnum * 2)) & 3) { + case 0: + case 2: + return 1; + case 1: + if (IS_USER(s)) { + return 1; + } + } + } + } /* First check for coprocessor space used for actual instructions */ switch (cpnum) { - case 0: - case 1: - if (arm_feature(env, ARM_FEATURE_IWMMXT)) { - return disas_iwmmxt_insn(env, s, insn); - } else if (arm_feature(env, ARM_FEATURE_XSCALE)) { - return disas_dsp_insn(env, s, insn); - } - return 1; + case 0: + case 1: + if (arm_feature(env, ARM_FEATURE_IWMMXT)) { + return disas_iwmmxt_insn(env, s, insn); + } else if (arm_feature(env, ARM_FEATURE_XSCALE)) { + return disas_dsp_insn(env, s, insn); + } + return 1; case 10: case 11: return disas_vfp_insn (env, s, insn); -- 1.7.9.5