[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

vfp exception issues with freepascal



I am involved in a project called raspbian to produce a hard-float derivative of debian for the raspberry pi. Within this port we had problems with floating point exceptions while running the compiler. These problems were tracked down by masta (a freepascal upstream developer) to reversed logic in a routine for controlling floating point exception settings (attempting to disable an exception enabled it and vice-versa)

Howevr this then left the question of "why didn't I see this problem when preparing the freepascal packages for debian armhf?". The conclusion i've come to is that on the armv7 systems i've tested (a beagleboard XM running 2.6.39.2-x2 and an IMX53 quickstart board running ) the method freepascal uses for enabling vfp exceptions simply doesn't work.

I've written a small test program in C and inline assembler to demonstrate this. It tries to enable a number of floating point exceptions using a price of inline assembly I copied from the freepascal run time library and then does a division of the command line arguments. When I test this on a Pi running raspbian I get a floating point exception as expected.

root@raspbian:~# ./a.out 1 0
Floating point exception
root@raspbian:~#

but when I try it on my beagleboard XM or IMX53 board I don't get any exception.

root@plugwash:/home/plugwash# ./a.out 1 0
inf
root@plugwash:/home/plugwash#

Any vfp experts able to help get to the bottom of what is going on here?
#include <stdio.h>

int main(int argc, char *argv[]) {
__asm__(
    "fmrx r0,fpscr\n\t"
    // set "round to nearest" mode
    "and  r0,r0,#0xff3fffff\n\t"
    // mask "exception happened" and overflow flags
    "and  r0,r0,#0xffffff20\n\t"
    // mask exception flags
    "and  r0,r0,#0xffff40ff\n\t"
    // disable flush-to-zero mode (IEEE math compliant)
    "and  r0,r0,#0xfeffffff\n\t"
    // enable invalid operation, div-by-zero and overflow exceptions
    "orr  r0,r0,#0x00000700\n\t"

    "fmxr fpscr,r0"
    : //no output registers
    : //no input registers
    : "r0"
    );
    double a = atoi(argv[1]);
    double b = atoi(argv[2]);
    double c = a / b;
    printf("%f\n",c);
}

Reply to: