162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * arch/arm/include/asm/vfpmacros.h
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Assembler-only file containing VFP macros and register definitions.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci#include <asm/hwcap.h>
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <asm/vfp.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#ifdef CONFIG_AS_VFP_VMRS_FPINST
1262306a36Sopenharmony_ci	.macro	VFPFMRX, rd, sysreg, cond
1362306a36Sopenharmony_ci	vmrs\cond	\rd, \sysreg
1462306a36Sopenharmony_ci	.endm
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_ci	.macro	VFPFMXR, sysreg, rd, cond
1762306a36Sopenharmony_ci	vmsr\cond	\sysreg, \rd
1862306a36Sopenharmony_ci	.endm
1962306a36Sopenharmony_ci#else
2062306a36Sopenharmony_ci	@ Macros to allow building with old toolkits (with no VFP support)
2162306a36Sopenharmony_ci	.macro	VFPFMRX, rd, sysreg, cond
2262306a36Sopenharmony_ci	MRC\cond	p10, 7, \rd, \sysreg, cr0, 0	@ FMRX	\rd, \sysreg
2362306a36Sopenharmony_ci	.endm
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci	.macro	VFPFMXR, sysreg, rd, cond
2662306a36Sopenharmony_ci	MCR\cond	p10, 7, \rd, \sysreg, cr0, 0	@ FMXR	\sysreg, \rd
2762306a36Sopenharmony_ci	.endm
2862306a36Sopenharmony_ci#endif
2962306a36Sopenharmony_ci
3062306a36Sopenharmony_ci	@ read all the working registers back into the VFP
3162306a36Sopenharmony_ci	.macro	VFPFLDMIA, base, tmp
3262306a36Sopenharmony_ci	.fpu	vfpv2
3362306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ < 6
3462306a36Sopenharmony_ci	fldmiax	\base!, {d0-d15}
3562306a36Sopenharmony_ci#else
3662306a36Sopenharmony_ci	vldmia	\base!, {d0-d15}
3762306a36Sopenharmony_ci#endif
3862306a36Sopenharmony_ci#ifdef CONFIG_VFPv3
3962306a36Sopenharmony_ci	.fpu	vfpv3
4062306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ <= 6
4162306a36Sopenharmony_ci	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs
4262306a36Sopenharmony_ci	ldr	\tmp, [\tmp, #0]
4362306a36Sopenharmony_ci	tst	\tmp, #HWCAP_VFPD32
4462306a36Sopenharmony_ci	vldmiane \base!, {d16-d31}
4562306a36Sopenharmony_ci	addeq	\base, \base, #32*4		    @ step over unused register space
4662306a36Sopenharmony_ci#else
4762306a36Sopenharmony_ci	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0
4862306a36Sopenharmony_ci	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field
4962306a36Sopenharmony_ci	cmp	\tmp, #2			    @ 32 x 64bit registers?
5062306a36Sopenharmony_ci	vldmiaeq \base!, {d16-d31}
5162306a36Sopenharmony_ci	addne	\base, \base, #32*4		    @ step over unused register space
5262306a36Sopenharmony_ci#endif
5362306a36Sopenharmony_ci#endif
5462306a36Sopenharmony_ci	.endm
5562306a36Sopenharmony_ci
5662306a36Sopenharmony_ci	@ write all the working registers out of the VFP
5762306a36Sopenharmony_ci	.macro	VFPFSTMIA, base, tmp
5862306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ < 6
5962306a36Sopenharmony_ci	fstmiax	\base!, {d0-d15}
6062306a36Sopenharmony_ci#else
6162306a36Sopenharmony_ci	vstmia	\base!, {d0-d15}
6262306a36Sopenharmony_ci#endif
6362306a36Sopenharmony_ci#ifdef CONFIG_VFPv3
6462306a36Sopenharmony_ci	.fpu	vfpv3
6562306a36Sopenharmony_ci#if __LINUX_ARM_ARCH__ <= 6
6662306a36Sopenharmony_ci	ldr	\tmp, =elf_hwcap		    @ may not have MVFR regs
6762306a36Sopenharmony_ci	ldr	\tmp, [\tmp, #0]
6862306a36Sopenharmony_ci	tst	\tmp, #HWCAP_VFPD32
6962306a36Sopenharmony_ci	vstmiane \base!, {d16-d31}
7062306a36Sopenharmony_ci	addeq	\base, \base, #32*4		    @ step over unused register space
7162306a36Sopenharmony_ci#else
7262306a36Sopenharmony_ci	VFPFMRX	\tmp, MVFR0			    @ Media and VFP Feature Register 0
7362306a36Sopenharmony_ci	and	\tmp, \tmp, #MVFR0_A_SIMD_MASK	    @ A_SIMD field
7462306a36Sopenharmony_ci	cmp	\tmp, #2			    @ 32 x 64bit registers?
7562306a36Sopenharmony_ci	vstmiaeq \base!, {d16-d31}
7662306a36Sopenharmony_ci	addne	\base, \base, #32*4		    @ step over unused register space
7762306a36Sopenharmony_ci#endif
7862306a36Sopenharmony_ci#endif
7962306a36Sopenharmony_ci	.endm
80