From patchwork Sat Feb 15 16:07:21 2014 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Maydell X-Patchwork-Id: 24695 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-oa0-f69.google.com (mail-oa0-f69.google.com [209.85.219.69]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 11781203BE for ; Sat, 15 Feb 2014 16:08:04 +0000 (UTC) Received: by mail-oa0-f69.google.com with SMTP id h16sf55691625oag.8 for ; Sat, 15 Feb 2014 08:08:04 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:x-original-sender :x-original-authentication-results:precedence:mailing-list:list-id :list-post:list-help:list-archive:list-unsubscribe; bh=JfLtE/9yYr63RdhThUWjX7bxhE1mC3BgJYqXoug6PqI=; b=Xokny04HHfZSwg67rTprNm9ZV+eHkFyA6Kn9lzlJpoxL69qUK5bW+k4L0oZNPqdJq+ kr3Wcxqb7zqQsyEEjqhnVmuSORo9zOlSIUl9yJx8AAlj7DiWwbrRDNRlorXW/62LyhtS OTiLFkCPyFRkg/bWKkp3HsCUeZNM6g0nfSwtwyFEFBjVQzLm7CXbbzakNHJP/EC1WCFg XQDWPhFcJ6dum/SuOYrs0LECGUd/I1ElBPhvQQ/PqADbJRBuF+gvntjDU4JzPrdlKAgR fEChhOKVM+O5AzHqiKI4bDiZn8+yBKOrygzw46FYXsTUk8VQlYxXABX3XWl6ZCO+PQ73 tmwg== X-Gm-Message-State: ALoCoQld+4FqhlWSxP90qa+pkkE77skLnP4xgLUBbZrBYkNH6Ow9MLbZHu09axt0v4ElxC5QAJQr X-Received: by 10.182.11.70 with SMTP id o6mr6166316obb.19.1392480484188; Sat, 15 Feb 2014 08:08:04 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.140.36.200 with SMTP id p66ls395230qgp.74.gmail; Sat, 15 Feb 2014 08:08:04 -0800 (PST) X-Received: by 10.221.27.133 with SMTP id rq5mr2913839vcb.9.1392480484018; Sat, 15 Feb 2014 08:08:04 -0800 (PST) Received: from mail-ve0-f174.google.com (mail-ve0-f174.google.com [209.85.128.174]) by mx.google.com with ESMTPS id xn9si3011006vcb.41.2014.02.15.08.08.04 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sat, 15 Feb 2014 08:08:04 -0800 (PST) Received-SPF: neutral (google.com: 209.85.128.174 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.128.174; Received: by mail-ve0-f174.google.com with SMTP id pa12so10751707veb.33 for ; Sat, 15 Feb 2014 08:08:03 -0800 (PST) X-Received: by 10.52.227.193 with SMTP id sc1mr8168666vdc.1.1392480483927; Sat, 15 Feb 2014 08:08:03 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp25588vcz; Sat, 15 Feb 2014 08:08:02 -0800 (PST) X-Received: by 10.152.203.193 with SMTP id ks1mr10275454lac.0.1392480466404; Sat, 15 Feb 2014 08:07:46 -0800 (PST) Received: from mnementh.archaic.org.uk (mnementh.archaic.org.uk. [2001:8b0:1d0::1]) by mx.google.com with ESMTPS id uf1si14719369lbb.79.2014.02.15.08.07.43 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sat, 15 Feb 2014 08:07:46 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of pm215@archaic.org.uk designates 2001:8b0:1d0::1 as permitted sender) client-ip=2001:8b0:1d0::1; Received: from pm215 by mnementh.archaic.org.uk with local (Exim 4.80) (envelope-from ) id 1WEhm2-0006gc-55; Sat, 15 Feb 2014 16:07:26 +0000 From: Peter Maydell To: qemu-devel@nongnu.org Cc: patches@linaro.org, Alexander Graf , Michael Matz , Claudio Fontana , Dirk Mueller , Laurent Desnogues , kvmarm@lists.cs.columbia.edu, Richard Henderson , =?UTF-8?q?Alex=20Benn=C3=A9e?= , Christoffer Dall , Will Newton , Peter Crosthwaite , Rob Herring Subject: [PATCH v3 28/31] target-arm: A64: Correctly fault FP/Neon if CPACR.FPEN set Date: Sat, 15 Feb 2014 16:07:21 +0000 Message-Id: <1392480444-25565-29-git-send-email-peter.maydell@linaro.org> X-Mailer: git-send-email 1.7.10.4 In-Reply-To: <1392480444-25565-1-git-send-email-peter.maydell@linaro.org> References: <1392480444-25565-1-git-send-email-peter.maydell@linaro.org> X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: peter.maydell@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.128.174 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , For the A64 instruction set, the only FP/Neon disable trap is the CPACR FPEN bits, which may indicate "enabled", "disabled" or "disabled for EL0". Add a bit to the AArch64 tb flags indicating whether FP/Neon access is currently enabled and make the decoder emit code to raise exceptions on use of FP/Neon insns if it is not. We use a new flag in DisasContext rather than borrowing the existing vfp_enabled flag because the A32/T32 decoder is going to need both. Signed-off-by: Peter Maydell --- I'm aware this is a rather hard to review patch; sorry. I have done an exhaustive check that we have fp access checks in all code paths with the aid of the assertions added in the next patch plus the code-coverage hack patch I posted to the list earlier. For the record, this patch is correct for all commits up to: target-arm: A64: Implement remaining 3-same instructions If we add further SIMD instructions before this patch hits master, it will need additional fp access check hunks... --- target-arm/cpu.c | 7 ++ target-arm/cpu.h | 16 ++++ target-arm/translate-a64.c | 234 ++++++++++++++++++++++++++++++++++++++++++++- target-arm/translate.h | 3 +- 4 files changed, 254 insertions(+), 6 deletions(-) diff --git a/target-arm/cpu.c b/target-arm/cpu.c index 7384e17..fbb5755 100644 --- a/target-arm/cpu.c +++ b/target-arm/cpu.c @@ -93,9 +93,16 @@ static void arm_cpu_reset(CPUState *s) env->pstate = PSTATE_MODE_EL0t; /* Userspace expects access to CTL_EL0 and the cache ops */ env->cp15.c1_sys |= SCTLR_UCT | SCTLR_UCI; + /* and to the FP/Neon instructions */ + env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 2, 3); #else env->pstate = PSTATE_MODE_EL1h; #endif + } else { +#if defined(CONFIG_USER_ONLY) + /* Userspace expects access to cp10 and cp11 for FP/Neon */ + env->cp15.c1_coproc = deposit64(env->cp15.c1_coproc, 20, 4, 0xf); +#endif } #if defined(CONFIG_USER_ONLY) diff --git a/target-arm/cpu.h b/target-arm/cpu.h index bf8b7d5..6b7b1d0 100644 --- a/target-arm/cpu.h +++ b/target-arm/cpu.h @@ -713,6 +713,13 @@ static inline uint32_t syn_cp15_rrt_trap(int cv, int cond, int opc1, int crm, | (rt2 << 10) | (rt << 5) | (crm << 1) | isread; } +static inline uint32_t syn_fp_access_trap(int cv, int cond, bool is_thumb) +{ + return (EC_ADVSIMDFPACCESSTRAP << ARM_EL_EC_SHIFT) + | (is_thumb ? 0 : ARM_EL_IL) + | (cv << 24) | (cond << 20); +} + enum arm_cpu_mode { ARM_CPU_MODE_USR = 0x10, ARM_CPU_MODE_FIQ = 0x11, @@ -1266,6 +1273,8 @@ static inline int cpu_mmu_index (CPUARMState *env) /* Bit usage when in AArch64 state */ #define ARM_TBFLAG_AA64_EL_SHIFT 0 #define ARM_TBFLAG_AA64_EL_MASK (0x3 << ARM_TBFLAG_AA64_EL_SHIFT) +#define ARM_TBFLAG_AA64_FPEN_SHIFT 2 +#define ARM_TBFLAG_AA64_FPEN_MASK (1 << ARM_TBFLAG_AA64_FPEN_SHIFT) /* some convenience accessor macros */ #define ARM_TBFLAG_AARCH64_STATE(F) \ @@ -1286,14 +1295,21 @@ static inline int cpu_mmu_index (CPUARMState *env) (((F) & ARM_TBFLAG_BSWAP_CODE_MASK) >> ARM_TBFLAG_BSWAP_CODE_SHIFT) #define ARM_TBFLAG_AA64_EL(F) \ (((F) & ARM_TBFLAG_AA64_EL_MASK) >> ARM_TBFLAG_AA64_EL_SHIFT) +#define ARM_TBFLAG_AA64_FPEN(F) \ + (((F) & ARM_TBFLAG_AA64_FPEN_MASK) >> ARM_TBFLAG_AA64_FPEN_SHIFT) static inline void cpu_get_tb_cpu_state(CPUARMState *env, target_ulong *pc, target_ulong *cs_base, int *flags) { + int fpen = extract32(env->cp15.c1_coproc, 20, 2); + if (is_a64(env)) { *pc = env->pc; *flags = ARM_TBFLAG_AARCH64_STATE_MASK | (arm_current_pl(env) << ARM_TBFLAG_AA64_EL_SHIFT); + if (fpen == 3 || (fpen == 1 && arm_current_pl(env) != 0)) { + *flags |= ARM_TBFLAG_AA64_FPEN_MASK; + } } else { int privmode; *pc = env->regs[15]; diff --git a/target-arm/translate-a64.c b/target-arm/translate-a64.c index af43aab..987b0b4 100644 --- a/target-arm/translate-a64.c +++ b/target-arm/translate-a64.c @@ -871,6 +871,23 @@ static void do_vec_ld(DisasContext *s, int destidx, int element, tcg_temp_free_i64(tcg_tmp); } +/* Check that FP/Neon access is enabled. If it is, return + * true. If not, emit code to generate an appropriate exception, + * and return false; the caller should not emit any code for + * the instruction. Note that this check must happen after all + * unallocated-encoding checks (otherwise the syndrome information + * for the resulting exception will be incorrect). + */ +static inline bool fp_access_check(DisasContext *s) +{ + if (s->cpacr_fpen) { + return true; + } + + gen_exception_insn(s, 4, EXCP_UDEF, syn_fp_access_trap(1, 0xe, false)); + return false; +} + /* * This utility function is for doing register extension with an * optional shift. You will likely want to pass a temporary for the @@ -1709,6 +1726,9 @@ static void disas_ld_lit(DisasContext *s, uint32_t insn) return; } size = 2 + opc; + if (!fp_access_check(s)) { + return; + } } else { if (opc == 3) { /* PRFM (literal) : prefetch */ @@ -1818,6 +1838,10 @@ static void disas_ldst_pair(DisasContext *s, uint32_t insn) break; } + if (is_vector && !fp_access_check(s)) { + return; + } + offset <<= size; if (rn == 31) { @@ -1909,6 +1933,9 @@ static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn) return; } is_store = ((opc & 1) == 0); + if (!fp_access_check(s)) { + return; + } } else { if (size == 3 && opc == 2) { /* PRFM - prefetch */ @@ -2024,6 +2051,9 @@ static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn) return; } is_store = !extract32(opc, 0, 1); + if (!fp_access_check(s)) { + return; + } } else { if (size == 3 && opc == 2) { /* PRFM - prefetch */ @@ -2104,6 +2134,9 @@ static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn) return; } is_store = !extract32(opc, 0, 1); + if (!fp_access_check(s)) { + return; + } } else { if (size == 3 && opc == 2) { /* PRFM - prefetch */ @@ -2261,6 +2294,10 @@ static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + if (rn == 31) { gen_check_sp_alignment(s); } @@ -2387,6 +2424,10 @@ static void disas_ldst_single_struct(DisasContext *s, uint32_t insn) g_assert_not_reached(); } + if (!fp_access_check(s)) { + return; + } + ebytes = 1 << scale; if (rn == 31) { @@ -3864,6 +3905,10 @@ static void disas_fp_compare(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + handle_fp_compare(s, type, rn, rm, opc & 1, opc & 2); } @@ -3892,6 +3937,10 @@ static void disas_fp_ccomp(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + if (cond < 0x0e) { /* not always */ int label_match = gen_new_label(); label_continue = gen_new_label(); @@ -3948,6 +3997,10 @@ static void disas_fp_csel(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + if (cond < 0x0e) { /* not always */ int label_match = gen_new_label(); label_continue = gen_new_label(); @@ -4165,6 +4218,10 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn) unallocated_encoding(s); return; } + if (!fp_access_check(s)) { + return; + } + handle_fp_fcvt(s, opcode, rd, rn, dtype, type); break; } @@ -4174,9 +4231,17 @@ static void disas_fp_1src(DisasContext *s, uint32_t insn) /* 32-to-32 and 64-to-64 ops */ switch (type) { case 0: + if (!fp_access_check(s)) { + return; + } + handle_fp_1src_single(s, opcode, rd, rn); break; case 1: + if (!fp_access_check(s)) { + return; + } + handle_fp_1src_double(s, opcode, rd, rn); break; default: @@ -4316,9 +4381,15 @@ static void disas_fp_2src(DisasContext *s, uint32_t insn) switch (type) { case 0: + if (!fp_access_check(s)) { + return; + } handle_fp_2src_single(s, opcode, rd, rn, rm); break; case 1: + if (!fp_access_check(s)) { + return; + } handle_fp_2src_double(s, opcode, rd, rn, rm); break; default: @@ -4420,9 +4491,15 @@ static void disas_fp_3src(DisasContext *s, uint32_t insn) switch (type) { case 0: + if (!fp_access_check(s)) { + return; + } handle_fp_3src_single(s, o0, o1, rd, rn, rm, ra); break; case 1: + if (!fp_access_check(s)) { + return; + } handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra); break; default: @@ -4449,6 +4526,10 @@ static void disas_fp_imm(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + /* The imm8 encodes the sign bit, enough bits to represent * an exponent in the range 01....1xx to 10....0xx, * and the most significant 4 bits of the mantissa; see @@ -4635,6 +4716,10 @@ static void disas_fp_fixed_conv(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + handle_fpfpcvt(s, rd, rn, opcode, itof, FPROUNDING_ZERO, scale, sf, type); } @@ -4734,6 +4819,9 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn) break; } + if (!fp_access_check(s)) { + return; + } handle_fmov(s, rd, rn, type, itof); } else { /* actual FP conversions */ @@ -4744,6 +4832,9 @@ static void disas_fp_int_conv(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type); } } @@ -4844,6 +4935,10 @@ static void disas_simd_ext(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + tcg_resh = tcg_temp_new_i64(); tcg_resl = tcg_temp_new_i64(); @@ -4914,6 +5009,10 @@ static void disas_simd_tb(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + /* This does a table lookup: for every byte element in the input * we index into a table formed from up to four vector registers, * and then the output is the result of the lookups. Our helper @@ -4984,6 +5083,10 @@ static void disas_simd_zip_trn(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + tcg_resl = tcg_const_i64(0); tcg_resh = tcg_const_i64(0); tcg_res = tcg_temp_new_i64(); @@ -5117,6 +5220,10 @@ static void disas_simd_across_lanes(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + esize = 8 << size; elements = (is_q ? 128 : 64) / esize; @@ -5249,6 +5356,10 @@ static void handle_simd_dupe(DisasContext *s, int is_q, int rd, int rn, return; } + if (!fp_access_check(s)) { + return; + } + index = imm5 >> (size + 1); tmp = tcg_temp_new_i64(); @@ -5283,6 +5394,10 @@ static void handle_simd_dupes(DisasContext *s, int rd, int rn, return; } + if (!fp_access_check(s)) { + return; + } + index = imm5 >> (size + 1); /* This instruction just extracts the specified element and @@ -5315,6 +5430,11 @@ static void handle_simd_dupg(DisasContext *s, int is_q, int rd, int rn, unallocated_encoding(s); return; } + + if (!fp_access_check(s)) { + return; + } + for (i = 0; i < elements; i++) { write_vec_element(s, cpu_reg(s, rn), rd, i, size); } @@ -5344,6 +5464,11 @@ static void handle_simd_inse(DisasContext *s, int rd, int rn, unallocated_encoding(s); return; } + + if (!fp_access_check(s)) { + return; + } + dst_index = extract32(imm5, 1+size, 5); src_index = extract32(imm4, size, 4); @@ -5376,6 +5501,10 @@ static void handle_simd_insg(DisasContext *s, int rd, int rn, int imm5) return; } + if (!fp_access_check(s)) { + return; + } + idx = extract32(imm5, 1 + size, 4 - size); write_vec_element(s, cpu_reg(s, rn), rd, idx, size); } @@ -5413,6 +5542,11 @@ static void handle_simd_umov_smov(DisasContext *s, int is_q, int is_signed, return; } } + + if (!fp_access_check(s)) { + return; + } + element = extract32(imm5, 1+size, 4); tcg_rd = cpu_reg(s, rd); @@ -5505,6 +5639,10 @@ static void disas_simd_mod_imm(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + /* See AdvSIMDExpandImm() in ARM ARM */ switch (cmode_3_1) { case 0: /* Replicate(Zeros(24):imm8, 2) */ @@ -5653,6 +5791,10 @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn) unallocated_encoding(s); return; } + if (!fp_access_check(s)) { + return; + } + TCGV_UNUSED_PTR(fpst); break; case 0xc: /* FMAXNMP */ @@ -5665,6 +5807,10 @@ static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn) unallocated_encoding(s); return; } + if (!fp_access_check(s)) { + return; + } + size = extract32(size, 0, 1) ? 3 : 2; fpst = get_fpstatus_ptr(); break; @@ -5867,6 +6013,10 @@ static void handle_scalar_simd_shri(DisasContext *s, return; } + if (!fp_access_check(s)) { + return; + } + switch (opcode) { case 0x02: /* SSRA / USRA (accumulate) */ accumulate = true; @@ -5917,6 +6067,10 @@ static void handle_scalar_simd_shli(DisasContext *s, bool insert, return; } + if (!fp_access_check(s)) { + return; + } + tcg_rn = read_fp_dreg(s, rn); tcg_rd = insert ? read_fp_dreg(s, rd) : tcg_temp_new_i64(); @@ -5995,6 +6149,10 @@ static void disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + if (size == 2) { TCGv_i64 tcg_op1 = tcg_temp_new_i64(); TCGv_i64 tcg_op2 = tcg_temp_new_i64(); @@ -6379,6 +6537,10 @@ static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + handle_3same_float(s, extract32(size, 0, 1), 1, fpopcode, rd, rn, rm); return; } @@ -6411,6 +6573,10 @@ static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + tcg_rd = tcg_temp_new_i64(); if (size == 3) { @@ -6561,7 +6727,13 @@ static void handle_2misc_fcmp_zero(DisasContext *s, int opcode, int size, int rn, int rd) { bool is_double = (size == 3); - TCGv_ptr fpst = get_fpstatus_ptr(); + TCGv_ptr fpst; + + if (!fp_access_check(s)) { + return; + } + + fpst = get_fpstatus_ptr(); if (is_double) { TCGv_i64 tcg_op = tcg_temp_new_i64(); @@ -6743,6 +6915,10 @@ static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + if (size == 3) { TCGv_i64 tcg_rn = read_fp_dreg(s, rn); TCGv_i64 tcg_rd = tcg_temp_new_i64(); @@ -6785,6 +6961,10 @@ static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u, return; } + if (!fp_access_check(s)) { + return; + } + switch (opcode) { case 0x02: /* SSRA / USRA (accumulate) */ accumulate = true; @@ -6849,6 +7029,10 @@ static void handle_vec_simd_shli(DisasContext *s, bool is_q, bool insert, return; } + if (!fp_access_check(s)) { + return; + } + for (i = 0; i < elements; i++) { read_vec_element(s, tcg_rn, rn, i, size); if (insert) { @@ -6884,6 +7068,10 @@ static void handle_vec_simd_wshli(DisasContext *s, bool is_q, bool is_u, return; } + if (!fp_access_check(s)) { + return; + } + /* For the LL variants the store is larger than the load, * so if rd == rn we would overwrite parts of our input. * So load everything right now and use shifts in the main loop. @@ -7173,6 +7361,10 @@ static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn) unallocated_encoding(s); return; } + if (!fp_access_check(s)) { + return; + } + handle_3rd_widening(s, is_q, is_u, size, opcode, rd, rn, rm); break; default: @@ -7191,11 +7383,15 @@ static void disas_simd_3same_logic(DisasContext *s, uint32_t insn) int size = extract32(insn, 22, 2); bool is_u = extract32(insn, 29, 1); bool is_q = extract32(insn, 30, 1); - TCGv_i64 tcg_op1 = tcg_temp_new_i64(); - TCGv_i64 tcg_op2 = tcg_temp_new_i64(); - TCGv_i64 tcg_res[2]; + TCGv_i64 tcg_op1, tcg_op2, tcg_res[2]; int pass; + if (!fp_access_check(s)) { + return; + } + + tcg_op1 = tcg_temp_new_i64(); + tcg_op2 = tcg_temp_new_i64(); tcg_res[0] = tcg_temp_new_i64(); tcg_res[1] = tcg_temp_new_i64(); @@ -7298,6 +7494,10 @@ static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode, TCGV_UNUSED_PTR(fpst); } + if (!fp_access_check(s)) { + return; + } + /* These operations work on the concatenated rm:rn, with each pair of * adjacent elements being operated on to produce an element in the result. */ @@ -7490,6 +7690,10 @@ static void disas_simd_3same_float(DisasContext *s, uint32_t insn) case 0x5f: /* FDIV */ case 0x7a: /* FABD */ case 0x7c: /* FCMGT */ + if (!fp_access_check(s)) { + return; + } + handle_3same_float(s, size, elements, fpopcode, rd, rn, rm); return; default: @@ -7544,6 +7748,10 @@ static void disas_simd_3same_int(DisasContext *s, uint32_t insn) break; } + if (!fp_access_check(s)) { + return; + } + if (size == 3) { for (pass = 0; pass < (is_q ? 2 : 1); pass++) { TCGv_i64 tcg_op1 = tcg_temp_new_i64(); @@ -7936,6 +8144,10 @@ static void handle_rev(DisasContext *s, int opcode, bool u, return; } + if (!fp_access_check(s)) { + return; + } + if (size == 0) { /* Special case bytes, use bswap op on each group of elements */ int groups = dsize / (8 << grp_size); @@ -8031,6 +8243,10 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) unallocated_encoding(s); return; } + if (!fp_access_check(s)) { + return; + } + handle_2misc_narrow(s, opcode, u, is_q, size, rn, rd); return; case 0x2: /* SADDLP, UADDLP */ @@ -8139,6 +8355,10 @@ static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn) return; } + if (!fp_access_check(s)) { + return; + } + if (size == 3) { /* All 64-bit element operations can be shared with scalar 2misc */ int pass; @@ -8400,6 +8620,10 @@ static void disas_simd_indexed(DisasContext *s, uint32_t insn) } } + if (!fp_access_check(s)) { + return; + } + if (is_fp) { fpst = get_fpstatus_ptr(); } else { @@ -8898,7 +9122,7 @@ void gen_intermediate_code_internal_a64(ARMCPU *cpu, #if !defined(CONFIG_USER_ONLY) dc->user = (ARM_TBFLAG_AA64_EL(tb->flags) == 0); #endif - dc->vfp_enabled = 0; + dc->cpacr_fpen = ARM_TBFLAG_AA64_FPEN(tb->flags); dc->vec_len = 0; dc->vec_stride = 0; dc->cp_regs = cpu->cp_regs; diff --git a/target-arm/translate.h b/target-arm/translate.h index fa029a0..2adf0bc 100644 --- a/target-arm/translate.h +++ b/target-arm/translate.h @@ -20,7 +20,8 @@ typedef struct DisasContext { #if !defined(CONFIG_USER_ONLY) int user; #endif - int vfp_enabled; + bool cpacr_fpen; /* FP enabled via CPACR.FPEN */ + bool vfp_enabled; /* FP enabled via FPSCR.EN */ int vec_len; int vec_stride; /* Immediate value in AArch32 SVC insn; must be set if is_jmp == DISAS_SWI