qemu/target/arm/tcg/m-nocp.decode

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

73 lines
3.2 KiB
Plaintext
Raw Normal View History

# M-profile UserFault.NOCP exception handling
#
# Copyright (c) 2020 Linaro, Ltd
#
# This library is free software; you can redistribute it and/or
# modify it under the terms of the GNU Lesser General Public
# License as published by the Free Software Foundation; either
# version 2.1 of the License, or (at your option) any later version.
#
# This library is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
# Lesser General Public License for more details.
#
# You should have received a copy of the GNU Lesser General Public
# License along with this library; if not, see <http://www.gnu.org/licenses/>.
#
# This file is processed by scripts/decodetree.py
#
# For M-profile, the architecture specifies that NOCP UsageFaults
# should take precedence over UNDEF faults over the whole wide
# range of coprocessor-space encodings, with the exception of
# VLLDM and VLSTM. (Compare v8.1M IsCPInstruction() pseudocode and
# v8M Arm ARM rule R_QLGM.) This isn't mandatory for v8.0M but we choose
# to behave the same as v8.1M.
# This decode is handled before any others (and in particular before
# decoding FP instructions which are in the coprocessor space).
# If the coprocessor is not present or disabled then we will generate
# the NOCP exception; otherwise we let the insn through to the main decode.
%vd_dp 22:1 12:4
%vd_sp 12:4 22:1
&nocp cp
target/arm: Don't NOCP fault for FPCXT_NS accesses The M-profile architecture requires that accesses to FPCXT_NS when there is no active FP state must not take a NOCP fault even if the FPU is disabled. We were not implementing this correctly, because in our decode we catch the NOCP faults early in m-nocp.decode. Fix this bug by moving all the handling of M-profile FP system register accesses from vfp.decode into m-nocp.decode and putting it above the NOCP blocks. This provides the correct behaviour: * for accesses other than FPCXT_NS the trans functions call vfp_access_check(), which will check for FPU disabled and raise a NOCP exception if necessary * for FPCXT_NS we have the special case code that doesn't call vfp_access_check() * when these trans functions want to raise an UNDEF they return false, so the decoder will fall through into the NOCP blocks. This means that NOCP correctly takes precedence over UNDEF for these insns. (This is a difference from the other insns handled by m-nocp.decode, where UNDEF takes precedence and which we implement by having those trans functions call unallocated_encoding() in the appropriate places.) [Note for backport to stable: this commit has a semantic dependency on commit 9a486856e9173af, which was not marked as cc-stable because we didn't know we'd need it for a for-stable bugfix.] Cc: qemu-stable@nongnu.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210618141019.10671-4-peter.maydell@linaro.org
2021-06-18 17:10:15 +03:00
# M-profile VLDR/VSTR to sysreg
%vldr_sysreg 22:1 13:3
%imm7_0x4 0:7 !function=times_4
&vldr_sysreg rn reg imm a w p
@vldr_sysreg .... ... . a:1 . . . rn:4 ... . ... .. ....... \
reg=%vldr_sysreg imm=%imm7_0x4 &vldr_sysreg
{
# Special cases which do not take an early NOCP: VLLDM and VLSTM
VLLDM_VLSTM 1110 1100 001 l:1 rn:4 0000 1010 op:1 000 0000
# VSCCLRM (new in v8.1M) is similar:
VSCCLRM 1110 1100 1.01 1111 .... 1011 imm:7 0 vd=%vd_dp size=3
VSCCLRM 1110 1100 1.01 1111 .... 1010 imm:8 vd=%vd_sp size=2
target/arm: Don't NOCP fault for FPCXT_NS accesses The M-profile architecture requires that accesses to FPCXT_NS when there is no active FP state must not take a NOCP fault even if the FPU is disabled. We were not implementing this correctly, because in our decode we catch the NOCP faults early in m-nocp.decode. Fix this bug by moving all the handling of M-profile FP system register accesses from vfp.decode into m-nocp.decode and putting it above the NOCP blocks. This provides the correct behaviour: * for accesses other than FPCXT_NS the trans functions call vfp_access_check(), which will check for FPU disabled and raise a NOCP exception if necessary * for FPCXT_NS we have the special case code that doesn't call vfp_access_check() * when these trans functions want to raise an UNDEF they return false, so the decoder will fall through into the NOCP blocks. This means that NOCP correctly takes precedence over UNDEF for these insns. (This is a difference from the other insns handled by m-nocp.decode, where UNDEF takes precedence and which we implement by having those trans functions call unallocated_encoding() in the appropriate places.) [Note for backport to stable: this commit has a semantic dependency on commit 9a486856e9173af, which was not marked as cc-stable because we didn't know we'd need it for a for-stable bugfix.] Cc: qemu-stable@nongnu.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20210618141019.10671-4-peter.maydell@linaro.org
2021-06-18 17:10:15 +03:00
# FP system register accesses: these are a special case because accesses
# to FPCXT_NS succeed even if the FPU is disabled. We therefore need
# to handle them before the big NOCP blocks. Note that within these
# insns NOCP still has higher priority than UNDEFs; this is implemented
# by their returning 'false' for UNDEF so as to fall through into the
# NOCP check (in contrast to VLLDM etc, which call unallocated_encoding()
# for the UNDEFs there that must take precedence over NOCP.)
VMSR_VMRS ---- 1110 111 l:1 reg:4 rt:4 1010 0001 0000
# P=0 W=0 is SEE "Related encodings", so split into two patterns
VLDR_sysreg ---- 110 1 . . w:1 1 .... ... 0 111 11 ....... @vldr_sysreg p=1
VLDR_sysreg ---- 110 0 . . 1 1 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
VSTR_sysreg ---- 110 1 . . w:1 0 .... ... 0 111 11 ....... @vldr_sysreg p=1
VSTR_sysreg ---- 110 0 . . 1 0 .... ... 0 111 11 ....... @vldr_sysreg p=0 w=1
NOCP 111- 1110 ---- ---- ---- cp:4 ---- ---- &nocp
NOCP 111- 110- ---- ---- ---- cp:4 ---- ---- &nocp
# From v8.1M onwards this range will also NOCP:
NOCP_8_1 111- 1111 ---- ---- ---- ---- ---- ---- &nocp cp=10
}