diff options
Diffstat (limited to 'target-arm/translate.c')
-rw-r--r-- | target-arm/translate.c | 31 |
1 files changed, 31 insertions, 0 deletions
diff --git a/target-arm/translate.c b/target-arm/translate.c index 84700ca7fd..03e2c00e94 100644 --- a/target-arm/translate.c +++ b/target-arm/translate.c @@ -2952,6 +2952,16 @@ static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn) if (!arm_feature(env, ARM_FEATURE_VFP)) return 1; + /* FIXME: this access check should not take precedence over UNDEF + * for invalid encodings; we will generate incorrect syndrome information + * for attempts to execute invalid vfp/neon encodings with FP disabled. + */ + if (!s->cpacr_fpen) { + gen_exception_insn(s, 4, EXCP_UDEF, + syn_fp_access_trap(1, 0xe, s->thumb)); + return 0; + } + if (!s->vfp_enabled) { /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */ if ((insn & 0x0fe00fff) != 0x0ee00a10) @@ -4232,6 +4242,16 @@ static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn) TCGv_i32 tmp2; TCGv_i64 tmp64; + /* FIXME: this access check should not take precedence over UNDEF + * for invalid encodings; we will generate incorrect syndrome information + * for attempts to execute invalid vfp/neon encodings with FP disabled. + */ + if (!s->cpacr_fpen) { + gen_exception_insn(s, 4, EXCP_UDEF, + syn_fp_access_trap(1, 0xe, s->thumb)); + return 0; + } + if (!s->vfp_enabled) return 1; VFP_DREG_D(rd, insn); @@ -4954,6 +4974,16 @@ static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t ins TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5; TCGv_i64 tmp64; + /* FIXME: this access check should not take precedence over UNDEF + * for invalid encodings; we will generate incorrect syndrome information + * for attempts to execute invalid vfp/neon encodings with FP disabled. + */ + if (!s->cpacr_fpen) { + gen_exception_insn(s, 4, EXCP_UDEF, + syn_fp_access_trap(1, 0xe, s->thumb)); + return 0; + } + if (!s->vfp_enabled) return 1; q = (insn & (1 << 6)) != 0; @@ -10736,6 +10766,7 @@ static inline void gen_intermediate_code_internal(ARMCPU *cpu, #if !defined(CONFIG_USER_ONLY) dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0); #endif + dc->cpacr_fpen = ARM_TBFLAG_CPACR_FPEN(tb->flags); dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags); dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags); dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags); |