Quellcode durchsuchen

Implement intrinsics CountTrailingZeroes and test it.

Fernando Sahmkow vor 7 Jahren
Ursprung
Commit
3bc815a5dc
3 geänderte Dateien mit 76 neuen und 12 gelöschten Zeilen
  1. 33 12
      src/common/bit_util.h
  2. 1 0
      src/tests/CMakeLists.txt
  3. 42 0
      src/tests/common/bit_utils.cpp

+ 33 - 12
src/common/bit_util.h

@@ -59,22 +59,43 @@ inline u64 CountLeadingZeroes64(u64 value) {
 }
 }
 #endif
 #endif
 
 
+
+#ifdef _MSC_VER
 inline u32 CountTrailingZeroes32(u32 value) {
 inline u32 CountTrailingZeroes32(u32 value) {
-  u32 count = 0;
-  while (((value >> count) & 0xf) == 0 && count < 32)
-    count += 4;
-  while (((value >> count) & 1) == 0 && count < 32)
-    count++;
-  return count;
+    unsigned long trailing_zero = 0;
+
+    if (_BitScanForward(&trailing_zero, value) != 0) {
+        return trailing_zero;
+    }
+
+    return 32;
 }
 }
 
 
 inline u64 CountTrailingZeroes64(u64 value) {
 inline u64 CountTrailingZeroes64(u64 value) {
-  u64 count = 0;
-  while (((value >> count) & 0xf) == 0 && count < 64)
-    count += 4;
-  while (((value >> count) & 1) == 0 && count < 64)
-    count++;
-  return count;
+    unsigned long trailing_zero = 0;
+
+    if (_BitScanForward64(&trailing_zero, value) != 0) {
+        return trailing_zero;
+    }
+
+    return 64;
 }
 }
+#else
+inline u32 CountTrailingZeroes32(u32 value) {
+    if (value == 0) {
+        return 32;
+    }
+
+    return __builtin_ctz(value);
+}
+
+inline u64 CountTrailingZeroes64(u64 value) {
+    if (value == 0) {
+        return 64;
+    }
+
+    return __builtin_ctzll(value);
+}
+#endif
 
 
 } // namespace Common
 } // namespace Common

+ 1 - 0
src/tests/CMakeLists.txt

@@ -1,5 +1,6 @@
 add_executable(tests
 add_executable(tests
     common/bit_field.cpp
     common/bit_field.cpp
+    common/bit_utils.cpp
     common/param_package.cpp
     common/param_package.cpp
     common/ring_buffer.cpp
     common/ring_buffer.cpp
     core/arm/arm_test_common.cpp
     core/arm/arm_test_common.cpp

+ 42 - 0
src/tests/common/bit_utils.cpp

@@ -0,0 +1,42 @@
+// Copyright 2017 Citra Emulator Project
+// Licensed under GPLv2 or any later version
+// Refer to the license.txt file included.
+
+#include <catch2/catch.hpp>
+#include <math.h>
+#include "common/bit_util.h"
+
+namespace Common {
+
+inline u32 CTZ32(u32 value) {
+  u32 count = 0;
+  while (((value >> count) & 0xf) == 0 && count < 32)
+    count += 4;
+  while (((value >> count) & 1) == 0 && count < 32)
+    count++;
+  return count;
+}
+
+inline u64 CTZ64(u64 value) {
+  u64 count = 0;
+  while (((value >> count) & 0xf) == 0 && count < 64)
+    count += 4;
+  while (((value >> count) & 1) == 0 && count < 64)
+    count++;
+  return count;
+}
+
+
+TEST_CASE("BitUtils", "[common]") {
+    REQUIRE(Common::CountTrailingZeroes32(0) == CTZ32(0));
+    REQUIRE(Common::CountTrailingZeroes64(0) == CTZ64(0));
+    REQUIRE(Common::CountTrailingZeroes32(9) == CTZ32(9));
+    REQUIRE(Common::CountTrailingZeroes32(8) == CTZ32(8));
+    REQUIRE(Common::CountTrailingZeroes32(0x801000) == CTZ32(0x801000));
+    REQUIRE(Common::CountTrailingZeroes64(9) == CTZ64(9));
+    REQUIRE(Common::CountTrailingZeroes64(8) == CTZ64(8));
+    REQUIRE(Common::CountTrailingZeroes64(0x801000) == CTZ64(0x801000));
+    REQUIRE(Common::CountTrailingZeroes64(0x801000000000UL) == CTZ64(0x801000000000UL));
+}
+
+} // namespace Common