aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJonathan Teh2022-02-22 23:57:22 +0000
committerJonathan Teh2022-02-22 23:57:22 +0000
commita8f26919a2ecb204d6d5f120709c52b6cd320835 (patch)
treeb845591a1ad324046de690e1fc54593eb564686d
parentf9698dddfebda59eff0331d9392f911de9ed7e4c (diff)
downloadsnes9x2005-a8f26919a2ecb204d6d5f120709c52b6cd320835.tar.gz
snes9x2005-a8f26919a2ecb204d6d5f120709c52b6cd320835.tar.bz2
snes9x2005-a8f26919a2ecb204d6d5f120709c52b6cd320835.zip
dsp1: Use clz CPU instruction when normalising fixed-point numbers
Use the gcc built-in function, making the operation constant-time and branch-free.
-rw-r--r--source/dsp1emu.c41
1 files changed, 39 insertions, 2 deletions
diff --git a/source/dsp1emu.c b/source/dsp1emu.c
index 76df362..d83e078 100644
--- a/source/dsp1emu.c
+++ b/source/dsp1emu.c
@@ -187,11 +187,19 @@ void DSP1_Inverse(int16_t Coefficient, int16_t Exponent, int16_t* 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)
@@ -336,9 +344,18 @@ int16_t DSP1_Cos(int16_t Angle)
void DSP1_Normalize(int16_t m, int16_t* Coefficient, int16_t* Exponent)
{
- int16_t i = 0x4000;
int16_t e = 0;
+#ifdef __GNUC__
+ int16_t n = m < 0 ? ~m : m;
+
+ if (n == 0)
+ e = 15;
+ else
+ e = __builtin_clz(n) - (8 * sizeof(int) - 15);
+#else
+ int16_t i = 0x4000;
+
if (m < 0)
{
while ((m & i) && i)
@@ -355,6 +372,7 @@ void DSP1_Normalize(int16_t m, int16_t* Coefficient, int16_t* Exponent)
e++;
}
}
+#endif
if (e > 0)
*Coefficient = m * DSP1ROM[0x21 + e] << 1;
@@ -368,9 +386,18 @@ void DSP1_NormalizeDouble(int32_t Product, int16_t* Coefficient, int16_t* Expone
{
int16_t n = Product & 0x7fff;
int16_t m = Product >> 15;
- int16_t i = 0x4000;
int16_t e = 0;
+#ifdef __GNUC__
+ int16_t t = m < 0 ? ~m : m;
+
+ if (t == 0)
+ e = 15;
+ else
+ e = __builtin_clz(t) - (8 * sizeof(int) - 15);
+#else
+ int16_t i = 0x4000;
+
if (m < 0)
{
while ((m & i) && i)
@@ -387,6 +414,7 @@ void DSP1_NormalizeDouble(int32_t Product, int16_t* Coefficient, int16_t* Expone
e++;
}
}
+#endif
if (e > 0)
{
@@ -396,6 +424,14 @@ void DSP1_NormalizeDouble(int32_t Product, int16_t* Coefficient, int16_t* Expone
*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)
@@ -414,6 +450,7 @@ void DSP1_NormalizeDouble(int32_t Product, int16_t* Coefficient, int16_t* Expone
e++;
}
}
+#endif
if (e > 15)
*Coefficient = n * DSP1ROM[0x0012 + e] << 1;