aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCatalin Marinas <catalin.marinas@arm.com>2007-09-25 10:22:24 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2008-01-26 09:41:28 -0500
commit25ebee020bd34d1f4c5678538204f0b10bf9f6d5 (patch)
treeb9b04ddf0b9916922a3cba47a7f64f44cd0b28ff
parentc98929c07a01c9ec2e1e5253456acc7168da8b66 (diff)
[ARM] 4583/1: ARMv7: Add VFPv3 support
This patch adds the support for VFPv3 (the kernel currently supports VFPv2). The main difference is 32 double registers (compared to 16). Signed-off-by: Catalin Marinas <catalin.marinas@arm.com> Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
-rw-r--r--arch/arm/Kconfig7
-rw-r--r--arch/arm/vfp/vfp.h4
-rw-r--r--arch/arm/vfp/vfphw.S22
-rw-r--r--arch/arm/vfp/vfpinstr.h6
-rw-r--r--include/asm-arm/fpstate.h9
-rw-r--r--include/asm-arm/vfp.h6
-rw-r--r--include/asm-arm/vfpmacros.h18
7 files changed, 60 insertions, 12 deletions
diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig
index a04f507e7f2c..f4eeb03bc6a9 100644
--- a/arch/arm/Kconfig
+++ b/arch/arm/Kconfig
@@ -951,7 +951,7 @@ config FPE_FASTFPE
951 951
952config VFP 952config VFP
953 bool "VFP-format floating point maths" 953 bool "VFP-format floating point maths"
954 depends on CPU_V6 || CPU_ARM926T 954 depends on CPU_V6 || CPU_ARM926T || CPU_V7
955 help 955 help
956 Say Y to include VFP support code in the kernel. This is needed 956 Say Y to include VFP support code in the kernel. This is needed
957 if your hardware includes a VFP unit. 957 if your hardware includes a VFP unit.
@@ -961,6 +961,11 @@ config VFP
961 961
962 Say N if your target does not have VFP hardware. 962 Say N if your target does not have VFP hardware.
963 963
964config VFPv3
965 bool
966 depends on VFP
967 default y if CPU_V7
968
964endmenu 969endmenu
965 970
966menu "Userspace binary formats" 971menu "Userspace binary formats"
diff --git a/arch/arm/vfp/vfp.h b/arch/arm/vfp/vfp.h
index 791d0238c68f..c85860bad585 100644
--- a/arch/arm/vfp/vfp.h
+++ b/arch/arm/vfp/vfp.h
@@ -265,7 +265,11 @@ struct vfp_double {
265 * which returns (double)0.0. This is useful for the compare with 265 * which returns (double)0.0. This is useful for the compare with
266 * zero instructions. 266 * zero instructions.
267 */ 267 */
268#ifdef CONFIG_VFPv3
269#define VFP_REG_ZERO 32
270#else
268#define VFP_REG_ZERO 16 271#define VFP_REG_ZERO 16
272#endif
269extern u64 vfp_get_double(unsigned int reg); 273extern u64 vfp_get_double(unsigned int reg);
270extern void vfp_put_double(u64 val, unsigned int reg); 274extern void vfp_put_double(u64 val, unsigned int reg);
271 275
diff --git a/arch/arm/vfp/vfphw.S b/arch/arm/vfp/vfphw.S
index 53d9f8e8fac3..353f9e5c7919 100644
--- a/arch/arm/vfp/vfphw.S
+++ b/arch/arm/vfp/vfphw.S
@@ -99,12 +99,12 @@ vfp_support_entry:
99 DBGSTR1 "save old state %p", r4 99 DBGSTR1 "save old state %p", r4
100 cmp r4, #0 100 cmp r4, #0
101 beq no_old_VFP_process 101 beq no_old_VFP_process
102 VFPFSTMIA r4, r5 @ save the working registers
102 VFPFMRX r5, FPSCR @ current status 103 VFPFMRX r5, FPSCR @ current status
103 tst r1, #FPEXC_EX @ is there additional state to save? 104 tst r1, #FPEXC_EX @ is there additional state to save?
104 VFPFMRX r6, FPINST, NE @ FPINST (only if FPEXC.EX is set) 105 VFPFMRX r6, FPINST, NE @ FPINST (only if FPEXC.EX is set)
105 tstne r1, #FPEXC_FP2V @ is there an FPINST2 to read? 106 tstne r1, #FPEXC_FP2V @ is there an FPINST2 to read?
106 VFPFMRX r8, FPINST2, NE @ FPINST2 if needed (and present) 107 VFPFMRX r8, FPINST2, NE @ FPINST2 if needed (and present)
107 VFPFSTMIA r4 @ save the working registers
108 stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2 108 stmia r4, {r1, r5, r6, r8} @ save FPEXC, FPSCR, FPINST, FPINST2
109 @ and point r4 at the word at the 109 @ and point r4 at the word at the
110 @ start of the register dump 110 @ start of the register dump
@@ -114,7 +114,7 @@ no_old_VFP_process:
114 DBGSTR1 "load state %p", r10 114 DBGSTR1 "load state %p", r10
115 str r10, [r3, r11, lsl #2] @ update the last_VFP_context pointer 115 str r10, [r3, r11, lsl #2] @ update the last_VFP_context pointer
116 @ Load the saved state back into the VFP 116 @ Load the saved state back into the VFP
117 VFPFLDMIA r10 @ reload the working registers while 117 VFPFLDMIA r10, r5 @ reload the working registers while
118 @ FPEXC is in a safe state 118 @ FPEXC is in a safe state
119 ldmia r10, {r1, r5, r6, r8} @ load FPEXC, FPSCR, FPINST, FPINST2 119 ldmia r10, {r1, r5, r6, r8} @ load FPEXC, FPSCR, FPINST, FPINST2
120 tst r1, #FPEXC_EX @ is there additional state to restore? 120 tst r1, #FPEXC_EX @ is there additional state to restore?
@@ -174,12 +174,12 @@ vfp_save_state:
174 @ r0 - save location 174 @ r0 - save location
175 @ r1 - FPEXC 175 @ r1 - FPEXC
176 DBGSTR1 "save VFP state %p", r0 176 DBGSTR1 "save VFP state %p", r0
177 VFPFSTMIA r0, r2 @ save the working registers
177 VFPFMRX r2, FPSCR @ current status 178 VFPFMRX r2, FPSCR @ current status
178 tst r1, #FPEXC_EX @ is there additional state to save? 179 tst r1, #FPEXC_EX @ is there additional state to save?
179 VFPFMRX r3, FPINST, NE @ FPINST (only if FPEXC.EX is set) 180 VFPFMRX r3, FPINST, NE @ FPINST (only if FPEXC.EX is set)
180 tstne r1, #FPEXC_FP2V @ is there an FPINST2 to read? 181 tstne r1, #FPEXC_FP2V @ is there an FPINST2 to read?
181 VFPFMRX r12, FPINST2, NE @ FPINST2 if needed (and present) 182 VFPFMRX r12, FPINST2, NE @ FPINST2 if needed (and present)
182 VFPFSTMIA r0 @ save the working registers
183 stmia r0, {r1, r2, r3, r12} @ save FPEXC, FPSCR, FPINST, FPINST2 183 stmia r0, {r1, r2, r3, r12} @ save FPEXC, FPSCR, FPINST, FPINST2
184 mov pc, lr 184 mov pc, lr
185#endif 185#endif
@@ -217,8 +217,15 @@ vfp_get_double:
217 fmrrd r0, r1, d\dr 217 fmrrd r0, r1, d\dr
218 mov pc, lr 218 mov pc, lr
219 .endr 219 .endr
220#ifdef CONFIG_VFPv3
221 @ d16 - d31 registers
222 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
223 mrrc p11, 3, r0, r1, c\dr @ fmrrd r0, r1, d\dr
224 mov pc, lr
225 .endr
226#endif
220 227
221 @ virtual register 16 for compare with zero 228 @ virtual register 16 (or 32 if VFPv3) for compare with zero
222 mov r0, #0 229 mov r0, #0
223 mov r1, #0 230 mov r1, #0
224 mov pc, lr 231 mov pc, lr
@@ -231,3 +238,10 @@ vfp_put_double:
231 fmdrr d\dr, r0, r1 238 fmdrr d\dr, r0, r1
232 mov pc, lr 239 mov pc, lr
233 .endr 240 .endr
241#ifdef CONFIG_VFPv3
242 @ d16 - d31 registers
243 .irp dr,0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
244 mcrr p11, 3, r1, r2, c\dr @ fmdrr r1, r2, d\dr
245 mov pc, lr
246 .endr
247#endif
diff --git a/arch/arm/vfp/vfpinstr.h b/arch/arm/vfp/vfpinstr.h
index 7f343a4beca0..15b95b5ab97e 100644
--- a/arch/arm/vfp/vfpinstr.h
+++ b/arch/arm/vfp/vfpinstr.h
@@ -52,11 +52,11 @@
52#define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) 52#define FEXT_TO_IDX(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
53 53
54#define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22) 54#define vfp_get_sd(inst) ((inst & 0x0000f000) >> 11 | (inst & (1 << 22)) >> 22)
55#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12) 55#define vfp_get_dd(inst) ((inst & 0x0000f000) >> 12 | (inst & (1 << 22)) >> 18)
56#define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5) 56#define vfp_get_sm(inst) ((inst & 0x0000000f) << 1 | (inst & (1 << 5)) >> 5)
57#define vfp_get_dm(inst) ((inst & 0x0000000f)) 57#define vfp_get_dm(inst) ((inst & 0x0000000f) | (inst & (1 << 5)) >> 1)
58#define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7) 58#define vfp_get_sn(inst) ((inst & 0x000f0000) >> 15 | (inst & (1 << 7)) >> 7)
59#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16) 59#define vfp_get_dn(inst) ((inst & 0x000f0000) >> 16 | (inst & (1 << 7)) >> 3)
60 60
61#define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00) 61#define vfp_single(inst) (((inst) & 0x0000f00) == 0xa00)
62 62
diff --git a/include/asm-arm/fpstate.h b/include/asm-arm/fpstate.h
index f31cda5a55ee..392eb5332323 100644
--- a/include/asm-arm/fpstate.h
+++ b/include/asm-arm/fpstate.h
@@ -17,14 +17,18 @@
17/* 17/*
18 * VFP storage area has: 18 * VFP storage area has:
19 * - FPEXC, FPSCR, FPINST and FPINST2. 19 * - FPEXC, FPSCR, FPINST and FPINST2.
20 * - 16 double precision data registers 20 * - 16 or 32 double precision data registers
21 * - an implementation-dependant word of state for FLDMX/FSTMX 21 * - an implementation-dependant word of state for FLDMX/FSTMX (pre-ARMv6)
22 * 22 *
23 * FPEXC will always be non-zero once the VFP has been used in this process. 23 * FPEXC will always be non-zero once the VFP has been used in this process.
24 */ 24 */
25 25
26struct vfp_hard_struct { 26struct vfp_hard_struct {
27#ifdef CONFIG_VFPv3
28 __u64 fpregs[32];
29#else
27 __u64 fpregs[16]; 30 __u64 fpregs[16];
31#endif
28#if __LINUX_ARM_ARCH__ < 6 32#if __LINUX_ARM_ARCH__ < 6
29 __u32 fpmx_state; 33 __u32 fpmx_state;
30#endif 34#endif
@@ -35,6 +39,7 @@ struct vfp_hard_struct {
35 */ 39 */
36 __u32 fpinst; 40 __u32 fpinst;
37 __u32 fpinst2; 41 __u32 fpinst2;
42
38#ifdef CONFIG_SMP 43#ifdef CONFIG_SMP
39 __u32 cpu; 44 __u32 cpu;
40#endif 45#endif
diff --git a/include/asm-arm/vfp.h b/include/asm-arm/vfp.h
index 9d474d47b266..5f9a2cb3d452 100644
--- a/include/asm-arm/vfp.h
+++ b/include/asm-arm/vfp.h
@@ -7,6 +7,8 @@
7 7
8#define FPSID cr0 8#define FPSID cr0
9#define FPSCR cr1 9#define FPSCR cr1
10#define MVFR1 cr6
11#define MVFR0 cr7
10#define FPEXC cr8 12#define FPEXC cr8
11#define FPINST cr9 13#define FPINST cr9
12#define FPINST2 cr10 14#define FPINST2 cr10
@@ -70,6 +72,10 @@
70#define FPSCR_IXC (1<<4) 72#define FPSCR_IXC (1<<4)
71#define FPSCR_IDC (1<<7) 73#define FPSCR_IDC (1<<7)
72 74
75/* MVFR0 bits */
76#define MVFR0_A_SIMD_BIT (0)
77#define MVFR0_A_SIMD_MASK (0xf << MVFR0_A_SIMD_BIT)
78
73/* Bit patterns for decoding the packaged operation descriptors */ 79/* Bit patterns for decoding the packaged operation descriptors */
74#define VFPOPDESC_LENGTH_BIT (9) 80#define VFPOPDESC_LENGTH_BIT (9)
75#define VFPOPDESC_LENGTH_MASK (0x07 << VFPOPDESC_LENGTH_BIT) 81#define VFPOPDESC_LENGTH_MASK (0x07 << VFPOPDESC_LENGTH_BIT)
diff --git a/include/asm-arm/vfpmacros.h b/include/asm-arm/vfpmacros.h
index 27fe028b4e72..cccb3892e73c 100644
--- a/include/asm-arm/vfpmacros.h
+++ b/include/asm-arm/vfpmacros.h
@@ -15,19 +15,33 @@
15 .endm 15 .endm
16 16
17 @ read all the working registers back into the VFP 17 @ read all the working registers back into the VFP
18 .macro VFPFLDMIA, base 18 .macro VFPFLDMIA, base, tmp
19#if __LINUX_ARM_ARCH__ < 6 19#if __LINUX_ARM_ARCH__ < 6
20 LDC p11, cr0, [\base],#33*4 @ FLDMIAX \base!, {d0-d15} 20 LDC p11, cr0, [\base],#33*4 @ FLDMIAX \base!, {d0-d15}
21#else 21#else
22 LDC p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d0-d15} 22 LDC p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d0-d15}
23#endif 23#endif
24#ifdef CONFIG_VFPv3
25 VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0
26 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field
27 cmp \tmp, #2 @ 32 x 64bit registers?
28 ldceql p11, cr0, [\base],#32*4 @ FLDMIAD \base!, {d16-d31}
29 addne \base, \base, #32*4 @ step over unused register space
30#endif
24 .endm 31 .endm
25 32
26 @ write all the working registers out of the VFP 33 @ write all the working registers out of the VFP
27 .macro VFPFSTMIA, base 34 .macro VFPFSTMIA, base, tmp
28#if __LINUX_ARM_ARCH__ < 6 35#if __LINUX_ARM_ARCH__ < 6
29 STC p11, cr0, [\base],#33*4 @ FSTMIAX \base!, {d0-d15} 36 STC p11, cr0, [\base],#33*4 @ FSTMIAX \base!, {d0-d15}
30#else 37#else
31 STC p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d0-d15} 38 STC p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d0-d15}
32#endif 39#endif
40#ifdef CONFIG_VFPv3
41 VFPFMRX \tmp, MVFR0 @ Media and VFP Feature Register 0
42 and \tmp, \tmp, #MVFR0_A_SIMD_MASK @ A_SIMD field
43 cmp \tmp, #2 @ 32 x 64bit registers?
44 stceql p11, cr0, [\base],#32*4 @ FSTMIAD \base!, {d16-d31}
45 addne \base, \base, #32*4 @ step over unused register space
46#endif
33 .endm 47 .endm