blob: 675a52348d8dc11d7a5e724aca7441af1fef8282 [file] [log] [blame]
David Brazdil0f672f62019-12-10 10:32:29 +00001/* SPDX-License-Identifier: GPL-2.0-only */
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00002/*
3 * Copyright (C) 2012 - Virtual Open Systems and Columbia University
4 * Author: Christoffer Dall <c.dall@virtualopensystems.com>
Andrew Scullb4b6d4a2019-01-02 15:54:55 +00005 */
6
7#include <linux/linkage.h>
8#include <asm/vfpmacros.h>
9
10 .text
11 .pushsection .hyp.text, "ax"
12
13/* void __vfp_save_state(struct vfp_hard_struct *vfp); */
14ENTRY(__vfp_save_state)
15 push {r4, r5}
16 VFPFMRX r1, FPEXC
17
18 @ Make sure *really* VFP is enabled so we can touch the registers.
19 orr r5, r1, #FPEXC_EN
20 tst r5, #FPEXC_EX @ Check for VFP Subarchitecture
21 bic r5, r5, #FPEXC_EX @ FPEXC_EX disable
22 VFPFMXR FPEXC, r5
23 isb
24
25 VFPFMRX r2, FPSCR
26 beq 1f
27
28 @ If FPEXC_EX is 0, then FPINST/FPINST2 reads are upredictable, so
29 @ we only need to save them if FPEXC_EX is set.
30 VFPFMRX r3, FPINST
31 tst r5, #FPEXC_FP2V
32 VFPFMRX r4, FPINST2, ne @ vmrsne
331:
34 VFPFSTMIA r0, r5 @ Save VFP registers
35 stm r0, {r1-r4} @ Save FPEXC, FPSCR, FPINST, FPINST2
36 pop {r4, r5}
37 bx lr
38ENDPROC(__vfp_save_state)
39
40/* void __vfp_restore_state(struct vfp_hard_struct *vfp);
41 * Assume FPEXC_EN is on and FPEXC_EX is off */
42ENTRY(__vfp_restore_state)
43 VFPFLDMIA r0, r1 @ Load VFP registers
44 ldm r0, {r0-r3} @ Load FPEXC, FPSCR, FPINST, FPINST2
45
46 VFPFMXR FPSCR, r1
47 tst r0, #FPEXC_EX @ Check for VFP Subarchitecture
48 beq 1f
49 VFPFMXR FPINST, r2
50 tst r0, #FPEXC_FP2V
51 VFPFMXR FPINST2, r3, ne
521:
53 VFPFMXR FPEXC, r0 @ FPEXC (last, in case !EN)
54 bx lr
55ENDPROC(__vfp_restore_state)
56
57 .popsection