[linux-audio-dev] Denormal numbers

Simon Jenkins sjenkins at blueyonder.co.uk
Mon Aug 4 18:01:59 UTC 2003


Jussi Laako wrote:

>On Sun, 2003-08-03 at 21:42, Steve Harris wrote:
>
>
>>I should play with it somemore, its possibel that you can tell the 387 to
>>ignore the exceptions.
>>
>
>See /usr/include/fpu_control.h
>
The trouble with turning off the exceptions is, erm, that they are already
turned off.

(Following discussion is intel 32-bit and equivalent specific:)

There are two exceptions relevant to denormals:

- A denormal operand exception occurs when an operand is denormal.

- An underflow exception occurs when the result of an operation is denormal,

You can either enable these exceptions and deal with them in software, or
you can mask them and let the FPU deal with them. If you let the FPU
deal with them (which is the default) then it proceeds with calculations
that have denormal operands, and it produces denormal results when
calculations underflow. There is no hardware option to flush either denormal
operands or denormal results to zero. (I think that there is such an option
on Itanium processors though, and on some other processor families).

The slow-down that happens with denormal calculations isn't the result
of exception handling, its the result of the FPU hardware itself taking
a lot longer to perform the calculations.

So, at least until the next hardware upgrade, we're stuck with detecting
and dealing with denormals ourselves.

Here are some possibly useful macros:

typedef unsigned int fpu_status_t __attribute__ ((__mode__ (__HI__)));
#define GET_FPU_STATUS_WORD(x) __asm__ ("fnstsw %0" : "=m" (*&x))
#define CLEAR_FPU_STATUS_BITS __asm__ ("fnclex")
#define FPU_SW_DENORMAL_EXCEPTION_MASK (0x0002)
#define FPU_SW_UNDERFLOW_EXCEPTION_MASK (0x0010)

The exception bits are "sticky" so we can do things like...

    fpu_status_t FPUStatus;

    /*..*/

    CLEAR_FPU_STATUS_BITS;

    /*..*/
    /* do a chunk of FP math here */
    /*..*/

    GET_FPU_STATUS_WORD(FPUStatus);
    if( FPUStatus
        & (   FPU_SW_DENORMAL_EXCEPTION_MASK
            | FPU_SW_UNDERFLOW_EXCEPTION_MASK ) != 0 ) {
        /* either we were passed a denormal or we generated one ourselves */

        /*..*/
        /* flush results to zero or - depending what the math was - take
        some other appropriate action */
        /*..*/
    }      

Simon Jenkins
(Bristol, UK)





More information about the Linux-audio-dev mailing list