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