This patch adds support for floating point operations on the ARM
Cortex-A5.  The Cortex-A5 uses VFPv4, which differs from the (mostly)
standard VFPv3 in that VFPv4 has 16 FPU registers instead of 32 on
VFPv3.

I've tested this on a BeagleBone Black (uses VFPv3) and the Atmel
SAMA5D3 Xplained (uses VFPv4 on Cortex-A5), which I'm currently
porting to OpenBSD.


Index: sys/arch/arm/arm/vfp.c
===================================================================
RCS file: /cvs/src/sys/arch/arm/arm/vfp.c,v
retrieving revision 1.3
diff -u -p -r1.3 vfp.c
--- sys/arch/arm/arm/vfp.c      24 Jan 2019 13:19:19 -0000      1.3
+++ sys/arch/arm/arm/vfp.c      9 Mar 2019 03:39:13 -0000
@@ -64,16 +64,27 @@ vfp_init(void)
 void
 vfp_store(struct fpreg *vfpsave)
 {
+       struct cpu_info *ci = curcpu();
        uint32_t scratch;
+       u_int cpuid = ci->ci_arm_cpuid;
 
        if (get_vfp_fpexc() & VFPEXC_EN) {
-               __asm __volatile(
-                   ".fpu vfpv3\n"
-                   "vstmia     %1!, {d0-d15}\n"        /* d0-d15 */
-                   "vstmia     %1!, {d16-d31}\n"       /* d16-d31 */
-                   "vmrs       %0, fpscr\n"
-                   "str        %0, [%1]\n"             /* save vfpscr */
-               : "=&r" (scratch) : "r" (vfpsave));
+               if ((cpuid & CPU_ID_CORTEX_MASK) == CPU_ID_CORTEX_A5) {
+                       __asm __volatile(
+                           ".fpu vfpv3\n"
+                           "vstmia     %1!, {d0-d15}\n"        /* d0-d15 */
+                           "vmrs       %0, fpscr\n"
+                           "str        %0, [%1]\n"     /* save vfpscr */
+                       : "=&r" (scratch) : "r" (vfpsave));
+               } else {
+                       __asm __volatile(
+                           ".fpu vfpv3\n"
+                           "vstmia     %1!, {d0-d15}\n"        /* d0-d15 */
+                           "vstmia     %1!, {d16-d31}\n"       /* d16-d31 */
+                           "vmrs       %0, fpscr\n"
+                           "str        %0, [%1]\n"     /* save vfpscr */
+                       : "=&r" (scratch) : "r" (vfpsave));
+               }
        }
 
        /* disable FPU */
@@ -137,6 +148,7 @@ vfp_load(struct proc *p)
        struct pcb *pcb = &p->p_addr->u_pcb;
        uint32_t scratch = 0;
        int psw;
+       u_int cpuid = ci->ci_arm_cpuid;
 
        /* do not allow a partially synced state here */
        psw = disable_interrupts(PSR_I|PSR_F);
@@ -150,13 +162,22 @@ vfp_load(struct proc *p)
        /* enable to be able to load ctx */
        set_vfp_fpexc(VFPEXC_EN);
 
-       __asm __volatile(
-           ".fpu vfpv3\n"
-           "vldmia     %1!, {d0-d15}\n"                /* d0-d15 */
-           "vldmia     %1!, {d16-d31}\n"               /* d16-d31 */
-           "ldr        %0, [%1]\n"                     /* set old vfpscr */
-           "vmsr       fpscr, %0\n"
-           : "=&r" (scratch) : "r" (&pcb->pcb_fpstate));
+       if ((cpuid & CPU_ID_CORTEX_MASK) == CPU_ID_CORTEX_A5) {
+               __asm __volatile(
+                   ".fpu vfpv3\n"
+                   "vldmia     %1!, {d0-d15}\n"        /* d0-d15 */
+                   "ldr        %0, [%1]\n"             /* set old vfpscr */
+                   "vmsr       fpscr, %0\n"
+                   : "=&r" (scratch) : "r" (&pcb->pcb_fpstate));
+       } else {
+               __asm __volatile(
+                   ".fpu vfpv3\n"
+                   "vldmia     %1!, {d0-d15}\n"        /* d0-d15 */
+                   "vldmia     %1!, {d16-d31}\n"       /* d16-d31 */
+                   "ldr        %0, [%1]\n"             /* set old vfpscr */
+                   "vmsr       fpscr, %0\n"
+                   : "=&r" (scratch) : "r" (&pcb->pcb_fpstate));
+       }
 
        ci->ci_fpuproc = p;
        pcb->pcb_fpcpu = ci;

Reply via email to