Skip to content

Commit bcafedd

Browse files
agnersnathanchance
authored andcommitted
ARM: use VFP assembler mnemonics if available
Clang's integrated assembler does not allow to to use the mcr instruction to access floating point co-processor registers: 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 ^ 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). Use as-instr 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. Signed-off-by: Stefan Agner <[email protected]> Link: ClangBuiltLinux/linux#905 Link: https://lore.kernel.org/lkml/3c8127839ced991fadb08c0a5a7beebb3ff489af.1583360296.git.stefan@agner.ch/ Signed-off-by: Nathan Chancellor <[email protected]>
1 parent e079e31 commit bcafedd

File tree

5 files changed

+38
-5
lines changed

5 files changed

+38
-5
lines changed

arch/arm/include/asm/vfp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,13 +9,15 @@
99
#ifndef __ASM_VFP_H
1010
#define __ASM_VFP_H
1111

12+
#ifndef HAVE_VMRS_FPINST
1213
#define FPSID cr0
1314
#define FPSCR cr1
1415
#define MVFR1 cr6
1516
#define MVFR0 cr7
1617
#define FPEXC cr8
1718
#define FPINST cr9
1819
#define FPINST2 cr10
20+
#endif
1921

2022
/* FPSID bits */
2123
#define FPSID_IMPLEMENTER_BIT (24)

arch/arm/include/asm/vfpmacros.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,14 +8,24 @@
88

99
#include <asm/vfp.h>
1010

11-
@ Macros to allow building with old toolkits (with no VFP support)
11+
#ifdef HAVE_VMRS_FPINST
12+
.macro VFPFMRX, rd, sysreg, cond
13+
vmrs\cond \rd, \sysreg
14+
.endm
15+
16+
.macro VFPFMXR, sysreg, rd, cond
17+
vmsr\cond \sysreg, \rd
18+
.endm
19+
#else
20+
@ Macros to allow building with old toolkits (with no VFP support)
1221
.macro VFPFMRX, rd, sysreg, cond
1322
MRC\cond p10, 7, \rd, \sysreg, cr0, 0 @ FMRX \rd, \sysreg
1423
.endm
1524

1625
.macro VFPFMXR, sysreg, rd, cond
1726
MCR\cond p10, 7, \rd, \sysreg, cr0, 0 @ FMXR \sysreg, \rd
1827
.endm
28+
#endif
1929

2030
@ read all the working registers back into the VFP
2131
.macro VFPFLDMIA, base, tmp

arch/arm/vfp/Makefile

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,4 +7,9 @@
77
# ccflags-y := -DDEBUG
88
# asflags-y := -DDEBUG
99

10+
vmrs_fpinst := $(call as-instr,.fpu vfpv2\nvmrs r0$(comma)FPINST,-DHAVE_VMRS_FPINST=1)
11+
12+
KBUILD_CFLAGS += $(vmrs_fpinst)
13+
KBUILD_AFLAGS += $(vmrs_fpinst)
14+
1015
obj-y += vfpmodule.o entry.o vfphw.o vfpsingle.o vfpdouble.o

arch/arm/vfp/vfphw.S

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,6 +81,7 @@
8181
ENTRY(vfp_support_entry)
8282
DBGSTR3 "instr %08x pc %08x state %p", r0, r2, r10
8383

84+
.fpu vfpv2
8485
ldr r3, [sp, #S_PSR] @ Neither lazy restore nor FP exceptions
8586
and r3, r3, #MODE_MASK @ are supported in kernel mode
8687
teq r3, #USR_MODE

arch/arm/vfp/vfpinstr.h

Lines changed: 19 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -65,10 +65,23 @@
6565
#define FPSCR_C (1 << 29)
6666
#define FPSCR_V (1 << 28)
6767

68-
/*
69-
* Since we aren't building with -mfpu=vfp, we need to code
70-
* these instructions using their MRC/MCR equivalents.
71-
*/
68+
#ifdef HAVE_VMRS_FPINST
69+
70+
#define fmrx(_vfp_) ({ \
71+
u32 __v; \
72+
asm(".fpu vfpv2\n" \
73+
"vmrs %0, " #_vfp_ \
74+
: "=r" (__v) : : "cc"); \
75+
__v; \
76+
})
77+
78+
#define fmxr(_vfp_,_var_) \
79+
asm(".fpu vfpv2\n" \
80+
"vmsr " #_vfp_ ", %0" \
81+
: : "r" (_var_) : "cc")
82+
83+
#else
84+
7285
#define vfpreg(_vfp_) #_vfp_
7386

7487
#define fmrx(_vfp_) ({ \
@@ -82,6 +95,8 @@
8295
asm("mcr p10, 7, %0, " vfpreg(_vfp_) ", cr0, 0 @ fmxr " #_vfp_ ", %0" \
8396
: : "r" (_var_) : "cc")
8497

98+
#endif
99+
85100
u32 vfp_single_cpdo(u32 inst, u32 fpscr);
86101
u32 vfp_single_cprt(u32 inst, u32 fpscr, struct pt_regs *regs);
87102

0 commit comments

Comments
 (0)