Permalink
Browse files

refactor so clean up the ifdef'ery and restore armhf

  • Loading branch information...
1 parent f554393 commit 2559ef40410a4abf695e9930536752f2da16eb19 @davilla davilla committed May 17, 2012
Showing with 98 additions and 71 deletions.
  1. +98 −71 xbmc/utils/MathUtils.h
View
@@ -29,6 +29,22 @@
#include <emmintrin.h>
#endif
+// use real compiler defines in here as we want to
+// avoid including system.h or other magic includes.
+// use 'gcc -dM -E - < /dev/null' or similar to find them.
+
+#if defined(__ppc__) || \
+ defined(__powerpc__) || \
+ (defined(__APPLE__) && defined(__arm__) && defined(__llvm__))
+ #define DISABLE_MATHUTILS_ASM_ROUND_INT
+#endif
+
+#if defined(__ppc__) || \
+ defined(__powerpc__) || \
+ (defined(__APPLE__) && defined(__llvm__))
+ #define DISABLE_MATHUTILS_ASM_TRUNCATE_INT
+#endif
+
/*! \brief Math utility class.
Note that the test() routine should return true for all implementations
@@ -49,31 +65,19 @@ namespace MathUtils
Make sure MathUtils::test() returns true for each implementation.
\sa truncate_int, test
- */
- inline int round_int (double x)
+ */
+ inline int round_int(double x)
{
assert(x > static_cast<double>(INT_MIN / 2) - 1.0);
- assert(x < static_cast <double>(INT_MAX / 2) + 1.0);
+ assert(x < static_cast<double>(INT_MAX / 2) + 1.0);
const float round_to_nearest = 0.5f;
int i;
-#if defined(__SSE2__)
- const float round_dn_to_nearest = 0.4999999f;
- i = (x > 0) ? _mm_cvttsd_si32(_mm_set_sd(x + round_to_nearest)) : _mm_cvttsd_si32(_mm_set_sd(x - round_dn_to_nearest));
-#elif !defined(_LINUX)
- __asm
- {
- fld x
- fadd st, st (0)
- fadd round_to_nearest
- fistp i
- sar i, 1
- }
-#else
-#if defined(__powerpc__) || defined(__ppc__) || defined(__ARM_PCS_VFP) || defined(TARGET_DARWIN)
+#if defined(DISABLE_MATHUTILS_ASM_ROUND_INT)
i = floor(x + round_to_nearest);
+
#elif defined(__arm__)
- // From 'ARM®v7-M Architecture Reference Manual' page A7-569:
+ // From 'ARM-v7-M Architecture Reference Manual' page A7-569:
// "The floating-point to integer operation (vcvt) [normally] uses the Round towards Zero rounding mode"
// Because of this...we must use some less-than-straightforward logic to perform this operation without
// changing the rounding mode flags
@@ -88,39 +92,63 @@ namespace MathUtils
if (err == 0.5f)
int_val++;
return int_val;
- */
+ */
__asm__ __volatile__ (
- "vmov.F64 d1,%[rnd_val] \n\t" // Copy round_to_nearest into a working register (d1 = 0.5)
- "fcmpezd %P[value] \n\t" // Check value against zero (value == 0?)
- "fmstat \n\t" // Copy the floating-point status flags into the general-purpose status flags
- "it mi \n\t"
- "vnegmi.F64 d1, d1 \n\t" // if N-flag is set, negate round_to_nearest (if (value < 0) d1 = -1 * d1)
- "vadd.F64 d1,%P[value],d1 \n\t" // Add round_to_nearest to value, store result in working register (d1 += value)
- "vcvt.S32.F64 s3,d1 \n\t" // Truncate(round towards zero) (s3 = (int)d1)
- "vmov %[result],s3 \n\t" // Store the integer result in a general-purpose register (result = s3)
- "vcvt.F64.S32 d1,s3 \n\t" // Convert back to floating-point (d1 = (double)s3)
- "vsub.F64 d1,%P[value],d1 \n\t" // Calculate the error (d1 = value - d1)
- "vmov.F64 d2,%[rnd_val] \n\t" // d2 = 0.5;
- "fcmped d1, d2 \n\t" // (d1 == 0.5?)
- "fmstat \n\t" // Copy the floating-point status flags into the general-purpose status flags
- "it eq \n\t"
- "addeq %[result],#1 \n\t" // (if (d1 == d2) result++;)
- : [result] "=r"(i) // Outputs
- : [rnd_val] "Dv" (round_to_nearest), [value] "w"(x) // Inputs
- : "d1", "d2", "s3" // Clobbers
- );
+#if defined(__ARM_PCS_VFP)
+ "fconstd d1,#%G[rnd_val] \n\t" // Copy round_to_nearest into a working register (d1 = 0.5)
#else
- __asm__ __volatile__ (
- "fadd %%st\n\t"
- "fadd %%st(1)\n\t"
- "fistpl %0\n\t"
- "sarl $1, %0\n"
- : "=m"(i) : "u"(round_to_nearest), "t"(x) : "st"
- );
+ "vmov.F64 d1,%[rnd_val] \n\t"
#endif
+ "fcmpezd %P[value] \n\t" // Check value against zero (value == 0?)
+ "fmstat \n\t" // Copy the floating-point status flags into the general-purpose status flags
+ "it mi \n\t"
+ "vnegmi.F64 d1, d1 \n\t" // if N-flag is set, negate round_to_nearest (if (value < 0) d1 = -1 * d1)
+ "vadd.F64 d1,%P[value],d1 \n\t" // Add round_to_nearest to value, store result in working register (d1 += value)
+ "vcvt.S32.F64 s3,d1 \n\t" // Truncate(round towards zero) (s3 = (int)d1)
+ "vmov %[result],s3 \n\t" // Store the integer result in a general-purpose register (result = s3)
+ "vcvt.F64.S32 d1,s3 \n\t" // Convert back to floating-point (d1 = (double)s3)
+ "vsub.F64 d1,%P[value],d1 \n\t" // Calculate the error (d1 = value - d1)
+#if defined(__ARM_PCS_VFP)
+ "fconstd d2,#%G[rnd_val] \n\t" // d2 = 0.5;
+#else
+ "vmov.F64 d2,%[rnd_val] \n\t"
#endif
- return (i);
+ "fcmped d1, d2 \n\t" // (d1 == 0.5?)
+ "fmstat \n\t" // Copy the floating-point status flags into the general-purpose status flags
+ "it eq \n\t"
+ "addeq %[result],#1 \n\t" // (if (d1 == d2) result++;)
+ : [result] "=r"(i) // Outputs
+ : [rnd_val] "Dv" (round_to_nearest), [value] "w"(x) // Inputs
+ : "d1", "d2", "s3" // Clobbers
+ );
+
+#elif defined(__SSE2__)
+ const float round_dn_to_nearest = 0.4999999f;
+ i = (x > 0) ? _mm_cvttsd_si32(_mm_set_sd(x + round_to_nearest)) : _mm_cvttsd_si32(_mm_set_sd(x - round_dn_to_nearest));
+
+#elif defined(_WIN32)
+ __asm
+ {
+ fld x
+ fadd st, st (0)
+ fadd round_to_nearest
+ fistp i
+ sar i, 1
+ }
+
+#else
+ __asm__ __volatile__ (
+ "fadd %%st\n\t"
+ "fadd %%st(1)\n\t"
+ "fistpl %0\n\t"
+ "sarl $1, %0\n"
+ : "=m"(i) : "u"(round_to_nearest), "t"(x) : "st"
+ );
+
+#endif
+
+ return i;
}
/*! \brief Truncate to nearest integer.
@@ -129,18 +157,26 @@ namespace MathUtils
Make sure MathUtils::test() returns true for each implementation.
\sa round_int, test
- */
+ */
inline int truncate_int(double x)
{
assert(x > static_cast<double>(INT_MIN / 2) - 1.0);
- assert(x < static_cast <double>(INT_MAX / 2) + 1.0);
-
-#if !defined(__powerpc__) && !defined(__ppc__) && !defined(__arm__) && !defined(TARGET_DARWIN)
- const float round_towards_m_i = -0.5f;
-#endif
+ assert(x < static_cast<double>(INT_MAX / 2) + 1.0);
int i;
-#ifndef _LINUX
+#if defined(DISABLE_MATHUTILS_ASM_TRUNCATE_INT)
+ return i = (int)x;
+
+#elif defined(__arm__)
+ __asm__ __volatile__ (
+ "vcvt.S32.F64 %[result],%P[value] \n\t" // Truncate(round towards zero) and store the result
+ : [result] "=w"(i) // Outputs
+ : [value] "w"(x) // Inputs
+ );
+ return i;
+
+#elif defined(_WIN32)
+ const float round_towards_m_i = -0.5f;
__asm
{
fld x
@@ -150,26 +186,17 @@ namespace MathUtils
fistp i
sar i, 1
}
+
#else
-#if defined(__powerpc__) || defined(__ppc__) || defined(TARGET_DARWIN)
- return (int)x;
-#elif defined(__arm__)
- __asm__ __volatile__ (
- "vcvt.S32.F64 %[result],%P[value] \n\t" // Truncate(round towards zero) and store the result
- : [result] "=w"(i) // Outputs
- : [value] "w"(x) // Inputs
- );
- return i;
-#else
+ const float round_towards_m_i = -0.5f;
__asm__ __volatile__ (
- "fadd %%st\n\t"
- "fabs\n\t"
- "fadd %%st(1)\n\t"
- "fistpl %0\n\t"
- "sarl $1, %0\n"
- : "=m"(i) : "u"(round_towards_m_i), "t"(x) : "st"
- );
-#endif
+ "fadd %%st\n\t"
+ "fabs\n\t"
+ "fadd %%st(1)\n\t"
+ "fistpl %0\n\t"
+ "sarl $1, %0\n"
+ : "=m"(i) : "u"(round_towards_m_i), "t"(x) : "st"
+ );
#endif
if (x < 0)
i = -i;

0 comments on commit 2559ef4

Please sign in to comment.