Search code examples
assemblyfloating-pointarmcortex-a

arm; VFP; Floating-point Extension; Undefined Instructions;


I have a device on ARM cortex-a9 and trying to implement "lazy float switching" for OS for this device. "lazy switching" is when

  • VFP support is disabled,
  • thread tries to execute any VFP instruction and generates exception,
  • exception handler turn on VFP, manage thread context & return so the same instruction will be tried again,
  • scheduler turns off VFP before switching threads.

The problem is that almost all VFP instructions generate synchronous exception when VFP is enabled. Simply speaking

vadd.f32    s19, s19, s17

at first exception handler enables VFP and returns to retry vadd.f32 s19, s19, s17, the user-space code generates another exception

at second time generate synchronous exception.
Exception Register, FPEXC is FPEXC.EX == 0, FPEXC.EN == 1, FPEXC.DEX == 1

And I could not understand what is the reason for this synchronous exception. I checked that

  • Interrupts are disabled FPSCR[15, 12-8] == 0;
  • VFPv3 is presented and implements full hardware FPU instruction set;
  • MVFR0 & MVFR1 are also indicate that all features are implemented and software simulation is not required.

Any ideas what could be the reason of these extra exceptions?


PS:

apps are build w/ -mcpu=cortex-a9 -marm -mfpu=vfpv3-fp16 -mfloat-abi=hard -ffast-math;

vpush..., vldr... generate exception only when VFP is off (behave as expected)


Solution

  • According to the Cortex-A9 FPU docs, the only reason for FPEXC.DEX to be set is if the thing was incorrectly configured to attempt short vector operations. The "V" in VFP has been deprecated since NEON came about, and isn't supported at all on anything newer than Cortex-A8.

    You need to make sure that FPSCR.Len and FPSCR.Stride* are set to 0.

    * OK, so strictly the value of Stride shouldn't matter when Len == 0, but hey, there's no good reason not to...