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:
jSTE0 2022-02-04 22:55:06 +00:00
parent 423361e4d1
commit 104769cec0
1 changed files with 37 additions and 2 deletions

View File

@ -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;