How are traps generated for floating point exceptions?

2k views Asked by At

I want to know which code and files in the glibc library are responsible for generating traps for floating point exceptions when traps are enabled.

Currently, GCC for RISC-V does not trap floating point exceptions. I am interested in adding this feature. So, I was looking at how this functionality is implemented in GCC for x86.

I am aware that we can trap signals as described in this [question] (Trapping floating-point overflow in C) but I want to know more details about how it works.

I went through files in glibc/math which according to me are in some form responsible for generating traps like

fenv.h
feenablxcpt.c
fegetexpect.c
feupdateenv.c

and many other files starting with fe.

All these files are also present in glibc for RISC-V. I am not able to figure out how glibc for x86 is able to generate traps.

2

There are 2 answers

12
Basile Starynkevitch On BEST ANSWER

These traps are usually generated by the hardware itself, at the instruction set architecture (ISA) level. In particular on x86-64.

I want to know which code and files in the glibc library are responsible for generating traps for floating point exceptions when traps are enabled.

So there are no such file. However, the operating system kernel (notably with signal(7)-s on Linux...) is translating traps to something else.

Please read Operating Systems: Three Easy Pieces for more. And study the x86-64 instruction set in details.

A more familiar example is the integer division by zero. On most hardware, that produces a machine trap (or machine exception), handled by the kernel. On some hardware (IIRC, PowerPC), its gives -1 as a result and sets some bit in a status register. Further machine code could test that bit. I believe that the GCC compiler would, in some cases and with some optimizations disabled, generate such a test after every division. But it is not required to do that.

The C language (read n1570, which practically is the C11 standard) has defined the notion of undefined behavior to handle such situations the most quickly and simply possible. Read Lattner's What every C programmer should know about undefined behavior blog.

Since you mention RISC-V, read about the RISC philosophy of the previous century, and be aware that designing out-of-order and super-scalar processors requires a lot of engineering efforts. My guess is that if you invest as much R&D (that means tens of billions of US$ or €) as Intel -or, to a lesser extent, AMD- did on x86-64 into a RISC-V chip, you could get comparable performance to current x86-64 processors. Notice that SPARC or PowerPC (or perhaps ARM) chips are RISC-like, and their best processors are nearly comparable in performance to Intel chips but got probably ten times less R&D investment than what Intel put in its microprocessors.

0
Bruno Haible On

The RISC-V floating-point control and status register (fcsr) contains, as explained in the RISC-V instruction set manual, section 8.2, exception flags, but no exception trap mask/bits. This means that invoking an OS trap and thus a signal handler is not done by the hardware.

In order to implement it in GCC, you would have to add, after each floating-point operation, a test whether an exception flag in the fcsr is set and, if so, whether an exception trap bit is set (in thread-local local storage) for that exception.