18c2ecf20Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * arch/arm/include/asm/vfpmacros.h
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci * Assembler-only file containing VFP macros and register definitions.
68c2ecf20Sopenharmony_ci */
78c2ecf20Sopenharmony_ci#include <asm/hwcap.h>
88c2ecf20Sopenharmony_ci
98c2ecf20Sopenharmony_ci#include <asm/vfp.h>
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#ifdef CONFIG_AS_VFP_VMRS_FPINST
128c2ecf20Sopenharmony_ci	.macro	VFPFMRX, rd, sysreg, cond
138c2ecf20Sopenharmony_ci	vmrs\cond	\rd, \sysreg
148c2ecf20Sopenharmony_ci	.endm
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_ci	.macro	VFPFMXR, sysreg, rd, cond
178c2ecf20Sopenharmony_ci	vmsr\cond	\sysreg, \rd
188c2ecf20Sopenharmony_ci	.endm
198c2ecf20Sopenharmony_ci#else
208c2ecf20Sopenharmony_ci	@ Macros to allow building with old toolkits (with no VFP support)
218c2ecf20Sopenharmony_ci	.macro	VFPFMRX, rd, sysreg, cond
228c2ecf20Sopenharmony_ci	MRC\cond	p10, 7, \rd, \sysreg, cr0, 0	@ FMRX	\rd, \sysreg
238c2ecf20Sopenharmony_ci	.endm
248c2ecf20Sopenharmony_ci
258c2ecf20Sopenharmony_ci	.macro	VFPFMXR, sysreg, rd, cond
268c2ecf20Sopenharmony_ci	MCR\cond	p10, 7, \rd, \sysreg, cr0, 0	@ FMXR	\sysreg, \rd
278c2ecf20Sopenharmony_ci	.endm
288c2ecf20Sopenharmony_ci#endif
298c2ecf20Sopenharmony_ci
308c2ecf20Sopenharmony_ci	@ read all the working registers back into the VFP
318c2ecf20Sopenharmony_ci	.macro	VFPFLDMIA, base, tmp
328c2ecf20Sopenharmony_ci	.fpu	vfpv2
338c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ < 6
348c2ecf20Sopenharmony_ci	fldmiax	\base!, {d0-d15}
358c2ecf20Sopenharmony_ci#else
368c2ecf20Sopenharmony_ci	vldmia	\base!, {d0-d15}
378c2ecf20Sopenharmony_ci#endif
388c2ecf20Sopenharmony_ci#ifdef CONFIG_VFPv3
398c2ecf20Sopenharmony_ci	.fpu	vfpv3
408c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ <= 6
418c2ecf20Sopenharmony_ci	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs
428c2ecf20Sopenharmony_ci	ldr	\tmp, [\tmp, #0]
438c2ecf20Sopenharmony_ci	tst	\tmp, #HWCAP_VFPD32
448c2ecf20Sopenharmony_ci	vldmiane \base!, {d16-d31}
458c2ecf20Sopenharmony_ci	addeq	\base, \base, #32*4		    @ step over unused register space
468c2ecf20Sopenharmony_ci#else
478c2ecf20Sopenharmony_ci	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0
488c2ecf20Sopenharmony_ci	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field
498c2ecf20Sopenharmony_ci	cmp	\tmp, #2			    @ 32 x 64bit registers?
508c2ecf20Sopenharmony_ci	vldmiaeq \base!, {d16-d31}
518c2ecf20Sopenharmony_ci	addne	\base, \base, #32*4		    @ step over unused register space
528c2ecf20Sopenharmony_ci#endif
538c2ecf20Sopenharmony_ci#endif
548c2ecf20Sopenharmony_ci	.endm
558c2ecf20Sopenharmony_ci
568c2ecf20Sopenharmony_ci	@ write all the working registers out of the VFP
578c2ecf20Sopenharmony_ci	.macro	VFPFSTMIA, base, tmp
588c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ < 6
598c2ecf20Sopenharmony_ci	fstmiax	\base!, {d0-d15}
608c2ecf20Sopenharmony_ci#else
618c2ecf20Sopenharmony_ci	vstmia	\base!, {d0-d15}
628c2ecf20Sopenharmony_ci#endif
638c2ecf20Sopenharmony_ci#ifdef CONFIG_VFPv3
648c2ecf20Sopenharmony_ci	.fpu	vfpv3
658c2ecf20Sopenharmony_ci#if __LINUX_ARM_ARCH__ <= 6
668c2ecf20Sopenharmony_ci	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs
678c2ecf20Sopenharmony_ci	ldr	\tmp, [\tmp, #0]
688c2ecf20Sopenharmony_ci	tst	\tmp, #HWCAP_VFPD32
698c2ecf20Sopenharmony_ci	vstmiane \base!, {d16-d31}
708c2ecf20Sopenharmony_ci	addeq	\base, \base, #32*4		    @ step over unused register space
718c2ecf20Sopenharmony_ci#else
728c2ecf20Sopenharmony_ci	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0
738c2ecf20Sopenharmony_ci	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field
748c2ecf20Sopenharmony_ci	cmp	\tmp, #2			    @ 32 x 64bit registers?
758c2ecf20Sopenharmony_ci	vstmiaeq \base!, {d16-d31}
768c2ecf20Sopenharmony_ci	addne	\base, \base, #32*4		    @ step over unused register space
778c2ecf20Sopenharmony_ci#endif
788c2ecf20Sopenharmony_ci#endif
798c2ecf20Sopenharmony_ci	.endm
80