xref: /openbmc/linux/arch/arm/vfp/vfphw.S (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1d2912cb1SThomas Gleixner/* SPDX-License-Identifier: GPL-2.0-only */
21da177e4SLinus Torvalds/*
31da177e4SLinus Torvalds *  linux/arch/arm/vfp/vfphw.S
41da177e4SLinus Torvalds *
51da177e4SLinus Torvalds *  Copyright (C) 2004 ARM Limited.
61da177e4SLinus Torvalds *  Written by Deep Blue Solutions Limited.
71da177e4SLinus Torvalds */
839ad04ccSCatalin Marinas#include <linux/init.h>
939ad04ccSCatalin Marinas#include <linux/linkage.h>
101da177e4SLinus Torvalds#include <asm/thread_info.h>
111da177e4SLinus Torvalds#include <asm/vfpmacros.h>
120cc41e4aSJoe Perches#include <linux/kern_levels.h>
1339ad04ccSCatalin Marinas#include <asm/assembler.h>
1439ad04ccSCatalin Marinas#include <asm/asm-offsets.h>
151da177e4SLinus Torvalds
161da177e4SLinus Torvalds	.macro  DBGSTR1, str, arg
171da177e4SLinus Torvalds#ifdef DEBUG
181da177e4SLinus Torvalds	stmfd	sp!, {r0-r3, ip, lr}
191da177e4SLinus Torvalds	mov	r1, \arg
20ded3ef0fSRussell King	ldr	r0, =1f
2133701557SChris Down	bl	_printk
22ded3ef0fSRussell King	ldmfd	sp!, {r0-r3, ip, lr}
23ded3ef0fSRussell King
24ded3ef0fSRussell King	.pushsection .rodata, "a"
25ded3ef0fSRussell King1:	.ascii	KERN_DEBUG "VFP: \str\n"
26ded3ef0fSRussell King	.byte	0
27ded3ef0fSRussell King	.previous
281da177e4SLinus Torvalds#endif
291da177e4SLinus Torvalds	.endm
301da177e4SLinus Torvalds
31*4708fb04SArd BiesheuvelENTRY(vfp_load_state)
32*4708fb04SArd Biesheuvel	@ Load the current VFP state
33*4708fb04SArd Biesheuvel	@ r0 - load location
34*4708fb04SArd Biesheuvel	@ returns FPEXC
35*4708fb04SArd Biesheuvel	DBGSTR1	"load VFP state %p", r0
361da177e4SLinus Torvalds					@ Load the saved state back into the VFP
37*4708fb04SArd Biesheuvel	VFPFLDMIA r0, r1		@ reload the working registers while
381da177e4SLinus Torvalds					@ FPEXC is in a safe state
39*4708fb04SArd Biesheuvel	ldmia	r0, {r0-r3}		@ load FPEXC, FPSCR, FPINST, FPINST2
40*4708fb04SArd Biesheuvel	tst	r0, #FPEXC_EX		@ is there additional state to restore?
4124b647a0SCatalin Marinas	beq	1f
42*4708fb04SArd Biesheuvel	VFPFMXR	FPINST, r2		@ restore FPINST (only if FPEXC.EX is set)
43*4708fb04SArd Biesheuvel	tst	r0, #FPEXC_FP2V		@ is there an FPINST2 to write?
4424b647a0SCatalin Marinas	beq	1f
45*4708fb04SArd Biesheuvel	VFPFMXR	FPINST2, r3		@ FPINST2 if needed (and present)
4624b647a0SCatalin Marinas1:
47*4708fb04SArd Biesheuvel	VFPFMXR	FPSCR, r1		@ restore status
48*4708fb04SArd Biesheuvel	ret	lr
49*4708fb04SArd BiesheuvelENDPROC(vfp_load_state)
501da177e4SLinus Torvalds
5193ed3970SCatalin MarinasENTRY(vfp_save_state)
52c6428464SCatalin Marinas	@ Save the current VFP state
53c6428464SCatalin Marinas	@ r0 - save location
54c6428464SCatalin Marinas	@ r1 - FPEXC
55c6428464SCatalin Marinas	DBGSTR1	"save VFP state %p", r0
5625ebee02SCatalin Marinas	VFPFSTMIA r0, r2		@ save the working registers
57c6428464SCatalin Marinas	VFPFMRX	r2, FPSCR		@ current status
58c98929c0SCatalin Marinas	tst	r1, #FPEXC_EX		@ is there additional state to save?
5924b647a0SCatalin Marinas	beq	1f
6024b647a0SCatalin Marinas	VFPFMRX	r3, FPINST		@ FPINST (only if FPEXC.EX is set)
6124b647a0SCatalin Marinas	tst	r1, #FPEXC_FP2V		@ is there an FPINST2 to read?
6224b647a0SCatalin Marinas	beq	1f
6324b647a0SCatalin Marinas	VFPFMRX	r12, FPINST2		@ FPINST2 if needed (and present)
6424b647a0SCatalin Marinas1:
65c6428464SCatalin Marinas	stmia	r0, {r1, r2, r3, r12}	@ save FPEXC, FPSCR, FPINST, FPINST2
666ebbf2ceSRussell King	ret	lr
6793ed3970SCatalin MarinasENDPROC(vfp_save_state)
68c6428464SCatalin Marinas
6907f33a03SCatalin Marinas	.macro	tbl_branch, base, tmp, shift
7007f33a03SCatalin Marinas#ifdef CONFIG_THUMB2_KERNEL
7107f33a03SCatalin Marinas	adr	\tmp, 1f
7207f33a03SCatalin Marinas	add	\tmp, \tmp, \base, lsl \shift
736ebbf2ceSRussell King	ret	\tmp
7407f33a03SCatalin Marinas#else
7507f33a03SCatalin Marinas	add	pc, pc, \base, lsl \shift
761da177e4SLinus Torvalds	mov	r0, r0
7707f33a03SCatalin Marinas#endif
7807f33a03SCatalin Marinas1:
7907f33a03SCatalin Marinas	.endm
8007f33a03SCatalin Marinas
8107f33a03SCatalin MarinasENTRY(vfp_get_float)
8207f33a03SCatalin Marinas	tbl_branch r0, r3, #3
83a6c30873SStefan Agner	.fpu	vfpv2
841da177e4SLinus Torvalds	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
85a6c30873SStefan Agner1:	vmov	r0, s\dr
866ebbf2ceSRussell King	ret	lr
8707f33a03SCatalin Marinas	.org	1b + 8
88a6c30873SStefan Agner	.endr
89a6c30873SStefan Agner	.irp	dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
90a6c30873SStefan Agner1:	vmov	r0, s\dr
916ebbf2ceSRussell King	ret	lr
9207f33a03SCatalin Marinas	.org	1b + 8
931da177e4SLinus Torvalds	.endr
9493ed3970SCatalin MarinasENDPROC(vfp_get_float)
951da177e4SLinus Torvalds
9693ed3970SCatalin MarinasENTRY(vfp_put_float)
9707f33a03SCatalin Marinas	tbl_branch r1, r3, #3
98a6c30873SStefan Agner	.fpu	vfpv2
991da177e4SLinus Torvalds	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
100a6c30873SStefan Agner1:	vmov	s\dr, r0
1016ebbf2ceSRussell King	ret	lr
10207f33a03SCatalin Marinas	.org	1b + 8
103a6c30873SStefan Agner	.endr
104a6c30873SStefan Agner	.irp	dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
105a6c30873SStefan Agner1:	vmov	s\dr, r0
1066ebbf2ceSRussell King	ret	lr
10707f33a03SCatalin Marinas	.org	1b + 8
1081da177e4SLinus Torvalds	.endr
10993ed3970SCatalin MarinasENDPROC(vfp_put_float)
1101da177e4SLinus Torvalds
11193ed3970SCatalin MarinasENTRY(vfp_get_double)
11207f33a03SCatalin Marinas	tbl_branch r0, r3, #3
113a6c30873SStefan Agner	.fpu	vfpv2
1141da177e4SLinus Torvalds	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
115a6c30873SStefan Agner1:	vmov	r0, r1, d\dr
1166ebbf2ceSRussell King	ret	lr
11707f33a03SCatalin Marinas	.org	1b + 8
1181da177e4SLinus Torvalds	.endr
11925ebee02SCatalin Marinas#ifdef CONFIG_VFPv3
12025ebee02SCatalin Marinas	@ d16 - d31 registers
121a6c30873SStefan Agner	.fpu	vfpv3
122a6c30873SStefan Agner	.irp	dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
123a6c30873SStefan Agner1:	vmov	r0, r1, d\dr
1246ebbf2ceSRussell King	ret	lr
12507f33a03SCatalin Marinas	.org	1b + 8
12625ebee02SCatalin Marinas	.endr
12725ebee02SCatalin Marinas#endif
1281da177e4SLinus Torvalds
12925ebee02SCatalin Marinas	@ virtual register 16 (or 32 if VFPv3) for compare with zero
1301da177e4SLinus Torvalds	mov	r0, #0
1311da177e4SLinus Torvalds	mov	r1, #0
1326ebbf2ceSRussell King	ret	lr
13393ed3970SCatalin MarinasENDPROC(vfp_get_double)
1341da177e4SLinus Torvalds
13593ed3970SCatalin MarinasENTRY(vfp_put_double)
13607f33a03SCatalin Marinas	tbl_branch r2, r3, #3
137a6c30873SStefan Agner	.fpu	vfpv2
1381da177e4SLinus Torvalds	.irp	dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
139a6c30873SStefan Agner1:	vmov	d\dr, r0, r1
1406ebbf2ceSRussell King	ret	lr
14107f33a03SCatalin Marinas	.org	1b + 8
1421da177e4SLinus Torvalds	.endr
14325ebee02SCatalin Marinas#ifdef CONFIG_VFPv3
144a6c30873SStefan Agner	.fpu	vfpv3
14525ebee02SCatalin Marinas	@ d16 - d31 registers
146a6c30873SStefan Agner	.irp	dr,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31
147a6c30873SStefan Agner1:	vmov	d\dr, r0, r1
1486ebbf2ceSRussell King	ret	lr
14907f33a03SCatalin Marinas	.org	1b + 8
15025ebee02SCatalin Marinas	.endr
15125ebee02SCatalin Marinas#endif
15293ed3970SCatalin MarinasENDPROC(vfp_put_double)
153