mirror of https://github.com/snes9xgit/snes9x.git
dsp1: Use clz CPU instruction when normalising fixed-point numbers
Use the gcc built-in GCC function, making the operation constant-time and branch-free. Verified on x86 and ARM.
This commit is contained in:
parent
423361e4d1
commit
104769cec0
39
dsp1.cpp
39
dsp1.cpp
|
@ -316,11 +316,17 @@ static void DSP1_Inverse (int16 Coefficient, int16 Exponent, int16 *iCoefficient
|
|||
}
|
||||
|
||||
// Step Three: Normalize
|
||||
#ifdef __GNUC__
|
||||
const int shift = __builtin_clz(Coefficient) - (8 * sizeof(int) - 15);
|
||||
Coefficient <<= shift;
|
||||
Exponent -= shift;
|
||||
#else
|
||||
while (Coefficient < 0x4000)
|
||||
{
|
||||
Coefficient <<= 1;
|
||||
Exponent--;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Step Four: Special Case
|
||||
if (Coefficient == 0x4000)
|
||||
|
@ -398,9 +404,18 @@ static int16 DSP1_Cos (int16 Angle)
|
|||
|
||||
static void DSP1_Normalize (int16 m, int16 *Coefficient, int16 *Exponent)
|
||||
{
|
||||
int16 i = 0x4000;
|
||||
int16 e = 0;
|
||||
|
||||
#ifdef __GNUC__
|
||||
int16 n = m < 0 ? ~m : m;
|
||||
|
||||
if (n == 0)
|
||||
e = 15;
|
||||
else
|
||||
e = __builtin_clz(n) - (8 * sizeof(int) - 15);
|
||||
#else
|
||||
int16 i = 0x4000;
|
||||
|
||||
if (m < 0)
|
||||
{
|
||||
while ((m & i) && i)
|
||||
|
@ -417,6 +432,7 @@ static void DSP1_Normalize (int16 m, int16 *Coefficient, int16 *Exponent)
|
|||
e++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (e > 0)
|
||||
*Coefficient = m * DSP1ROM[0x21 + e] << 1;
|
||||
|
@ -430,9 +446,18 @@ static void DSP1_NormalizeDouble (int32 Product, int16 *Coefficient, int16 *Expo
|
|||
{
|
||||
int16 n = Product & 0x7fff;
|
||||
int16 m = Product >> 15;
|
||||
int16 i = 0x4000;
|
||||
int16 e = 0;
|
||||
|
||||
#ifdef __GNUC__
|
||||
int16 t = m < 0 ? ~m : m;
|
||||
|
||||
if (t == 0)
|
||||
e = 15;
|
||||
else
|
||||
e = __builtin_clz(t) - (8 * sizeof(int) - 15);
|
||||
#else
|
||||
int16 i = 0x4000;
|
||||
|
||||
if (m < 0)
|
||||
{
|
||||
while ((m & i) && i)
|
||||
|
@ -449,6 +474,7 @@ static void DSP1_NormalizeDouble (int32 Product, int16 *Coefficient, int16 *Expo
|
|||
e++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (e > 0)
|
||||
{
|
||||
|
@ -458,6 +484,14 @@ static void DSP1_NormalizeDouble (int32 Product, int16 *Coefficient, int16 *Expo
|
|||
*Coefficient += n * DSP1ROM[0x0040 - e] >> 15;
|
||||
else
|
||||
{
|
||||
#ifdef __GNUC__
|
||||
t = m < 0 ? ~(n | 0x8000) : n;
|
||||
|
||||
if (t == 0)
|
||||
e += 15;
|
||||
else
|
||||
e += __builtin_clz(t) - (8 * sizeof(int) - 15);
|
||||
#else
|
||||
i = 0x4000;
|
||||
|
||||
if (m < 0)
|
||||
|
@ -476,6 +510,7 @@ static void DSP1_NormalizeDouble (int32 Product, int16 *Coefficient, int16 *Expo
|
|||
e++;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
if (e > 15)
|
||||
*Coefficient = n * DSP1ROM[0x0012 + e] << 1;
|
||||
|
|
Loading…
Reference in New Issue