59cbcdb5d8
This is almost a copy/paste of the existing version, with a couple of subtle differences: - Only write to FPEXC once on the save path - Add an isb when enabling VFP access The patch also defines a few sysreg accessors and a __vfp_enabled predicate that test the VFP trapping state. Reviewed-by: Christoffer Dall <christoffer.dall@linaro.org> Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
69 lines
1.9 KiB
ArmAsm
69 lines
1.9 KiB
ArmAsm
/*
|
|
* Copyright (C) 2012 - Virtual Open Systems and Columbia University
|
|
* Author: Christoffer Dall <c.dall@virtualopensystems.com>
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License version 2 as
|
|
* published by the Free Software Foundation.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
*/
|
|
|
|
#include <linux/linkage.h>
|
|
#include <asm/vfpmacros.h>
|
|
|
|
.text
|
|
.pushsection .hyp.text, "ax"
|
|
|
|
/* void __vfp_save_state(struct vfp_hard_struct *vfp); */
|
|
ENTRY(__vfp_save_state)
|
|
push {r4, r5}
|
|
VFPFMRX r1, FPEXC
|
|
|
|
@ Make sure *really* VFP is enabled so we can touch the registers.
|
|
orr r5, r1, #FPEXC_EN
|
|
tst r5, #FPEXC_EX @ Check for VFP Subarchitecture
|
|
bic r5, r5, #FPEXC_EX @ FPEXC_EX disable
|
|
VFPFMXR FPEXC, r5
|
|
isb
|
|
|
|
VFPFMRX r2, FPSCR
|
|
beq 1f
|
|
|
|
@ If FPEXC_EX is 0, then FPINST/FPINST2 reads are upredictable, so
|
|
@ we only need to save them if FPEXC_EX is set.
|
|
VFPFMRX r3, FPINST
|
|
tst r5, #FPEXC_FP2V
|
|
VFPFMRX r4, FPINST2, ne @ vmrsne
|
|
1:
|
|
VFPFSTMIA r0, r5 @ Save VFP registers
|
|
stm r0, {r1-r4} @ Save FPEXC, FPSCR, FPINST, FPINST2
|
|
pop {r4, r5}
|
|
bx lr
|
|
ENDPROC(__vfp_save_state)
|
|
|
|
/* void __vfp_restore_state(struct vfp_hard_struct *vfp);
|
|
* Assume FPEXC_EN is on and FPEXC_EX is off */
|
|
ENTRY(__vfp_restore_state)
|
|
VFPFLDMIA r0, r1 @ Load VFP registers
|
|
ldm r0, {r0-r3} @ Load FPEXC, FPSCR, FPINST, FPINST2
|
|
|
|
VFPFMXR FPSCR, r1
|
|
tst r0, #FPEXC_EX @ Check for VFP Subarchitecture
|
|
beq 1f
|
|
VFPFMXR FPINST, r2
|
|
tst r0, #FPEXC_FP2V
|
|
VFPFMXR FPINST2, r3, ne
|
|
1:
|
|
VFPFMXR FPEXC, r0 @ FPEXC (last, in case !EN)
|
|
bx lr
|
|
ENDPROC(__vfp_restore_state)
|
|
|
|
.popsection
|