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;