Re: Denormalization
Re: Denormalization
- Subject: Re: Denormalization
- From: Ian Ollmann <email@hidden>
- Date: Wed, 11 Dec 2002 14:54:28 -0800
>
Has anybody got some asm-code at hand to appropriately save-set-restore
>
the FP control register? (By this, small numbers will result in zero
>
instead of a denormal, which is also called non-IEEE mode)
FPU
---
If you are using ProjectBuilder/gcc, you will find a file called
/usr/include/gcc/darwin/3.1/ppc_intrinsics.h. It includes a lot of built
in functionality comparable to MWCW's __asm()'s, including some for
massaging the FPSCR.
From these, it is fairly easy to construct what you need:
#include <ppc_intrinsics.h>
//Turns off denormals and returns the old FPSCR value
double DisableDenormals( void )
{
union
{
double d;
int i[2];
}newValue;
double oldFPSCR = __mffs();
const int nonIEEEMask = 0x00000004;
//Copy the old FPSCR to the newValue union
newValue.d = oldFPSCR;
//Turn on the non-IEEE (NI) bit
newValue.i[1] |= nonIEEEMask;
//move the new FPSCR setting
__mtfsf(0xFF, newValue.d);
return oldFPSCR;
}
double EnableDenormals( void )
{
union
{
double d;
int i[2];
}newValue;
double oldFPSCR = __mffs();
const int nonIEEEMask = 0x00000004;
//Copy the old FPSCR to the newValue union
newValue.d = oldFPSCR;
//Turn on the non-IEEE (NI) bit
newValue.i[1] &= ~nonIEEEMask;
//move the new FPSCR setting
__mtfsf(0xFF, newValue.d);
return oldFPSCR;
}
//Sets the FPSCR to the new value
void SetFPSCR( double newValue )
{
__mtfsf( 0xFF, newValue );
}
Now, here imagine you see a big bright red warning light, because what
exactly happens when you turn on the Non-IEEE754 bit is IMPLEMENTATION
DEFINED. In other words, you have potentially a lot of testing to do every
time a new processor comes out.
AltiVec
-------
AltiVec is a bit simpler because we don't need asms. Otherwise its roughly
the same idea. You can use vec_mfscr() to read the VSCR. You can use
vec_mtvscr() to write to it.
vector unsigned short DisableVectorDenormals( void )
{
vector unsigned short njMask, oldVSCR, newVSCR;
//Generate the non-Java bit mask
njMask = vec_sub( vec_splat_u16(1),
(vector unsigned short) vec_splat_u32(1) );
oldVSCR = vec_mfvscr();
newVSCR = vec_or( oldVSCR, njMask );
vec_mtvscr( newVSCR );
return oldVSCR;
}
vector unsigned short EnableVectorDenormals( void )
{
vector unsigned short njMask, oldVSCR, newVSCR;
//Generate the non-Java bit mask
njMask = vec_sub( vec_splat_u16(1),
(vector unsigned short) vec_splat_u32(1) );
oldVSCR = vec_mfvscr();
newVSCR = vec_andc( oldVSCR, njMask );
vec_mtvscr( newVSCR );
return oldVSCR;
}
and to set the vscr to a new value, just use
vec_mtvscr( newValue );
>
I 'seen a function that does it for the AltiVec (setting it to
>
non-JAVA-mode or so). - Wouldn't it be nice to have such useful
>
low-level functions in CoreAudio?
It might be handy as a convenience method, but you should not need such a
function to get CoreAudio to start disregarding denormals. Simply setting
the FPSCR or VSCR to turn off IEEE/Java mode will in most cases cause the
CoreAudio code to start ignoring the denormals too. The bit is carried
forth into whatever functions you call and may impact calculations going
on there.
IEEE-754 / Java mode may be required for correct operation of certain
functions. Disable at your own risk.
Ian
_______________________________________________
coreaudio-api mailing list | email@hidden
Help/Unsubscribe/Archives:
http://www.lists.apple.com/mailman/listinfo/coreaudio-api
Do not post admin requests to the list. They will be ignored.