mirror of
https://github.com/torvalds/linux.git
synced 2024-12-29 14:21:47 +00:00
ARM: 8991/1: use VFP assembler mnemonics if available
The integrated assembler of Clang 10 and earlier do not allow to access the VFP registers through the coprocessor load/store instructions: arch/arm/vfp/vfpmodule.c:342:2: error: invalid operand for instruction fmxr(FPEXC, fpexc & ~(FPEXC_EX|FPEXC_DEX|FPEXC_FP2V|FPEXC_VV|FPEXC_TRAP_MASK)); ^ arch/arm/vfp/vfpinstr.h:79:6: note: expanded from macro 'fmxr' asm("mcr p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmxr " #_vfp_ ", %0" ^ <inline asm>:1:6: note: instantiated into assembly here mcr p10, 7, r0, cr8, cr0, 0 @ fmxr FPEXC, r0 ^ This has been addressed with Clang 11 [0]. However, to support earlier versions of Clang and for better readability use of VFP assembler mnemonics still is preferred. Ideally we would replace this code with the unified assembler language mnemonics vmrs/vmsr on call sites along with .fpu assembler directives. The GNU assembler supports the .fpu directive at least since 2.17 (when documentation has been added). Since Linux requires binutils 2.21 it is safe to use .fpu directive. However, binutils does not allow to use FPINST or FPINST2 as an argument to vmrs/vmsr instructions up to binutils 2.24 (see binutils commit 16d02dc907c5): arch/arm/vfp/vfphw.S: Assembler messages: arch/arm/vfp/vfphw.S:162: Error: operand 0 must be FPSID or FPSCR pr FPEXC -- `vmsr FPINST,r6' arch/arm/vfp/vfphw.S:165: Error: operand 0 must be FPSID or FPSCR pr FPEXC -- `vmsr FPINST2,r8' arch/arm/vfp/vfphw.S:235: Error: operand 1 must be a VFP extension System Register -- `vmrs r3,FPINST' arch/arm/vfp/vfphw.S:238: Error: operand 1 must be a VFP extension System Register -- `vmrs r12,FPINST2' Use as-instr in Kconfig to check if FPINST/FPINST2 can be used. If they can be used make use of .fpu directives and UAL VFP mnemonics for register access. This allows to build vfpmodule.c with Clang and its integrated assembler. [0] https://reviews.llvm.org/D59733 Link: https://github.com/ClangBuiltLinux/linux/issues/905 Signed-off-by: Stefan Agner <stefan@agner.ch> Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk>
This commit is contained in:
parent
ee440336e5
commit
2cbd1cc3dc
@ -2097,3 +2097,5 @@ source "drivers/firmware/Kconfig"
|
|||||||
if CRYPTO
|
if CRYPTO
|
||||||
source "arch/arm/crypto/Kconfig"
|
source "arch/arm/crypto/Kconfig"
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
source "arch/arm/Kconfig.assembler"
|
||||||
|
6
arch/arm/Kconfig.assembler
Normal file
6
arch/arm/Kconfig.assembler
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
# SPDX-License-Identifier: GPL-2.0
|
||||||
|
|
||||||
|
config AS_VFP_VMRS_FPINST
|
||||||
|
def_bool $(as-instr,.fpu vfpv2\nvmrs r0$(comma)FPINST)
|
||||||
|
help
|
||||||
|
Supported by binutils >= 2.24 and LLVM integrated assembler.
|
@ -9,6 +9,7 @@
|
|||||||
#ifndef __ASM_VFP_H
|
#ifndef __ASM_VFP_H
|
||||||
#define __ASM_VFP_H
|
#define __ASM_VFP_H
|
||||||
|
|
||||||
|
#ifndef CONFIG_AS_VFP_VMRS_FPINST
|
||||||
#define FPSID cr0
|
#define FPSID cr0
|
||||||
#define FPSCR cr1
|
#define FPSCR cr1
|
||||||
#define MVFR1 cr6
|
#define MVFR1 cr6
|
||||||
@ -16,6 +17,7 @@
|
|||||||
#define FPEXC cr8
|
#define FPEXC cr8
|
||||||
#define FPINST cr9
|
#define FPINST cr9
|
||||||
#define FPINST2 cr10
|
#define FPINST2 cr10
|
||||||
|
#endif
|
||||||
|
|
||||||
/* FPSID bits */
|
/* FPSID bits */
|
||||||
#define FPSID_IMPLEMENTER_BIT (24)
|
#define FPSID_IMPLEMENTER_BIT (24)
|
||||||
|
@ -8,7 +8,16 @@
|
|||||||
|
|
||||||
#include <asm/vfp.h>
|
#include <asm/vfp.h>
|
||||||
|
|
||||||
@ Macros to allow building with old toolkits (with no VFP support)
|
#ifdef CONFIG_AS_VFP_VMRS_FPINST
|
||||||
|
.macro VFPFMRX, rd, sysreg, cond
|
||||||
|
vmrs\cond \rd, \sysreg
|
||||||
|
.endm
|
||||||
|
|
||||||
|
.macro VFPFMXR, sysreg, rd, cond
|
||||||
|
vmsr\cond \sysreg, \rd
|
||||||
|
.endm
|
||||||
|
#else
|
||||||
|
@ Macros to allow building with old toolkits (with no VFP support)
|
||||||
.macro VFPFMRX, rd, sysreg, cond
|
.macro VFPFMRX, rd, sysreg, cond
|
||||||
MRC\cond p10, 7, \rd, \sysreg, cr0, 0 @ FMRX \rd, \sysreg
|
MRC\cond p10, 7, \rd, \sysreg, cr0, 0 @ FMRX \rd, \sysreg
|
||||||
.endm
|
.endm
|
||||||
@ -16,6 +25,7 @@
|
|||||||
.macro VFPFMXR, sysreg, rd, cond
|
.macro VFPFMXR, sysreg, rd, cond
|
||||||
MCR\cond p10, 7, \rd, \sysreg, cr0, 0 @ FMXR \sysreg, \rd
|
MCR\cond p10, 7, \rd, \sysreg, cr0, 0 @ FMXR \sysreg, \rd
|
||||||
.endm
|
.endm
|
||||||
|
#endif
|
||||||
|
|
||||||
@ read all the working registers back into the VFP
|
@ read all the working registers back into the VFP
|
||||||
.macro VFPFLDMIA, base, tmp
|
.macro VFPFLDMIA, base, tmp
|
||||||
|
@ -78,6 +78,7 @@
|
|||||||
ENTRY(vfp_support_entry)
|
ENTRY(vfp_support_entry)
|
||||||
DBGSTR3 "instr %08x pc %08x state %p", r0, r2, r10
|
DBGSTR3 "instr %08x pc %08x state %p", r0, r2, r10
|
||||||
|
|
||||||
|
.fpu vfpv2
|
||||||
ldr r3, [sp, #S_PSR] @ Neither lazy restore nor FP exceptions
|
ldr r3, [sp, #S_PSR] @ Neither lazy restore nor FP exceptions
|
||||||
and r3, r3, #MODE_MASK @ are supported in kernel mode
|
and r3, r3, #MODE_MASK @ are supported in kernel mode
|
||||||
teq r3, #USR_MODE
|
teq r3, #USR_MODE
|
||||||
|
@ -62,10 +62,23 @@
|
|||||||
#define FPSCR_C (1 << 29)
|
#define FPSCR_C (1 << 29)
|
||||||
#define FPSCR_V (1 << 28)
|
#define FPSCR_V (1 << 28)
|
||||||
|
|
||||||
/*
|
#ifdef CONFIG_AS_VFP_VMRS_FPINST
|
||||||
* Since we aren't building with -mfpu=vfp, we need to code
|
|
||||||
* these instructions using their MRC/MCR equivalents.
|
#define fmrx(_vfp_) ({ \
|
||||||
*/
|
u32 __v; \
|
||||||
|
asm(".fpu vfpv2\n" \
|
||||||
|
"vmrs %0, " #_vfp_ \
|
||||||
|
: "=r" (__v) : : "cc"); \
|
||||||
|
__v; \
|
||||||
|
})
|
||||||
|
|
||||||
|
#define fmxr(_vfp_,_var_) \
|
||||||
|
asm(".fpu vfpv2\n" \
|
||||||
|
"vmsr " #_vfp_ ", %0" \
|
||||||
|
: : "r" (_var_) : "cc")
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
#define vfpreg(_vfp_) #_vfp_
|
#define vfpreg(_vfp_) #_vfp_
|
||||||
|
|
||||||
#define fmrx(_vfp_) ({ \
|
#define fmrx(_vfp_) ({ \
|
||||||
@ -79,6 +92,8 @@
|
|||||||
asm("mcr p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmxr " #_vfp_ ", %0" \
|
asm("mcr p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmxr " #_vfp_ ", %0" \
|
||||||
: : "r" (_var_) : "cc")
|
: : "r" (_var_) : "cc")
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
u32 vfp_single_cpdo(u32 inst, u32 fpscr);
|
u32 vfp_single_cpdo(u32 inst, u32 fpscr);
|
||||||
u32 vfp_single_cprt(u32 inst, u32 fpscr, struct pt_regs *regs);
|
u32 vfp_single_cprt(u32 inst, u32 fpscr, struct pt_regs *regs);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user