Implement intrinsics CountTrailingZeroes and test it.

This commit is contained in:
Fernando Sahmkow 2019-03-15 23:18:11 -04:00 committed by FernandoS27
parent 522957f9f3
commit 3bc815a5dc
3 changed files with 76 additions and 12 deletions

View file

@ -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; unsigned long trailing_zero = 0;
while (((value >> count) & 0xf) == 0 && count < 32)
count += 4; if (_BitScanForward(&trailing_zero, value) != 0) {
while (((value >> count) & 1) == 0 && count < 32) return trailing_zero;
count++; }
return count;
return 32;
} }
inline u64 CountTrailingZeroes64(u64 value) { inline u64 CountTrailingZeroes64(u64 value) {
u64 count = 0; unsigned long trailing_zero = 0;
while (((value >> count) & 0xf) == 0 && count < 64)
count += 4; if (_BitScanForward64(&trailing_zero, value) != 0) {
while (((value >> count) & 1) == 0 && count < 64) return trailing_zero;
count++;
return count;
} }
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

View file

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

View file

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