This page is indeed to show how the floating-point exceptions can be checked in both Zynq-7000 and ZynqMPSoC architectures. Floating-point exception trapping is completely dependent to the implementation of the FPU and in both cases those exceptions are not trapped by the processor, so the only way to get them is accessing to the status registers by software after each FP operation.

Although the C code standard defines floating point exception access routines in fenv.h, the newlib C library used in both Linaro and Xilinx GCC compiler does not provide it. These feature should be available for ARM Keil compiler as described in Keil user guide.

Zynq-7000 (Cortex-A9)

The Floating-Point Status and Control Register (FPSCR) can be accessed from the processor unit in order to check FP exceptions after each FP operation as described in the following example code.

#include <stdio.h>
#include "xil_printf.h"

#include "xpseudo_asm.h"

int main()
{
  float a = 0.0;
  float b = 0.0;
  float c = 0.0;
  u32 fpscr_reg;

  print("Floating Point exception test\r\n");
  print("Invalid Operation \t");
  a = 0.0;
  b = 0.0;
  c = a / b;

  asm("VMRS r0, FPSCR");
  asm("MOV %0, r0" : "=r"(fpscr_reg));
  printf("FPSCR: 0x%08lX, %s\r\n", fpscr_reg, (fpscr_reg == 0x01) ? "SUCCESS" : "FAIL");
  asm("MOV r0, $0");
  asm("VMSR FPSCR, r0");

  print("Division by zero \t");
  a = 1.0;
  b = 0.0;
  c = a / b;

  asm("VMRS r0, FPSCR");
  asm("MOV %0, r0" : "=r"(fpscr_reg));
  printf("FPSCR: 0x%08lX, %s\r\n", fpscr_reg, (fpscr_reg == 0x02) ? "SUCCESS" : "FAIL");
  asm("MOV r0, $0");
  asm("VMSR FPSCR, r0");

  print("Inexact cumulative\t");
  a = 1.0;
  b = 10;
  c = a / b;

  asm("VMRS r0, FPSCR");
  asm("MOV %0, r0" : "=r"(fpscr_reg));
  printf("FPSCR: 0x%08lX, %s\r\n", fpscr_reg, (fpscr_reg == 0x10) ? "SUCCESS" : "FAIL");

  return 0;
}

Zynq-MPSoC (Cortex-A53)

The Floating-Point Status Register (FPSR) can be accessed from the processor unit in order to check FP exceptions after each FP operation as described in the following example code.

#include <stdio.h>
#include "xil_printf.h"

#include "xpseudo_asm.h"

int main()
{
  double a = 0.0;
  double b = 0.0;
  double c = 0.0;
  u32 fpscr_reg;

  print("Floating Point exception test\r\n");
  print("Invalid Operation \t");
  a = 0.0;
  b = 0.0;
  c = a / b;

  asm("MRS x0, FPSR");
  asm("MOV %0, x0" : "=r"(fpscr_reg));
  printf("FPSCR: 0x%08lX, %s\r\n", fpscr_reg, (fpscr_reg == 0x01) ? "SUCCESS" : "FAIL");
  asm("MOV x0, #0");
  asm("MSR FPSR, x0");

  print("Division by zero \t");
  a = 1.0;
  b = 0.0;
  c = a / b;

  asm("MRS x0, FPSR");
  asm("MOV %0, x0" : "=r"(fpscr_reg));
  printf("FPSCR: 0x%08lX, %s\r\n", fpscr_reg, (fpscr_reg == 0x02) ? "SUCCESS" : "FAIL");
  asm("MOV x0, #0");
  asm("MSR FPSR, x0");

  print("Inexact cumulative\t");
  a = 1.0;
  b = 10;
  c = a / b;

  asm("MRS x0, FPSR");
  asm("MOV %0, x0" : "=r"(fpscr_reg));
  printf("FPSCR: 0x%08lX, %s\r\n", fpscr_reg, (fpscr_reg == 0x10) ? "SUCCESS" : "FAIL");
  asm("MOV x0, #0");
  asm("MSR FPSR, x0");

  return 0;
}

Related Links

  • Cortex A9 - FPU TRM
  • Cortex A53 - FPU TRM