summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bits.h24
-rw-r--r--src/wasm-interpreter.h27
2 files changed, 30 insertions, 21 deletions
diff --git a/src/bits.h b/src/bits.h
index 98bb96a4f..98ae5c4b7 100644
--- a/src/bits.h
+++ b/src/bits.h
@@ -17,6 +17,8 @@
#ifndef wasm_bits_h
#define wasm_bits_h
+#include <type_traits>
+
/*
* Portable bit functions.
*
@@ -37,6 +39,18 @@ template<typename T> inline T BitReverse(T /* v */);
template<typename T> inline int CountTrailingZeroes(T /* v */);
template<typename T> inline int CountLeadingZeroes(T /* v */);
+// Convenience signed -> unsigned. It usually doesn't make much sense to use bit
+// functions on signed types.
+template <typename T> inline int PopCount(T v) {
+ return PopCount(typename std::make_unsigned<T>::type(v));
+}
+template <typename T> inline int CountTrailingZeroes(T v) {
+ return CountTrailingZeroes(typename std::make_unsigned<T>::type(v));
+}
+template <typename T> inline int CountLeadingZeroes(T v) {
+ return CountLeadingZeroes(typename std::make_unsigned<T>::type(v));
+}
+
// Implementations for the above templates.
template<> inline int PopCount<uint8_t>(uint8_t v) {
@@ -84,6 +98,11 @@ template<> inline int CountTrailingZeroes<uint32_t>(uint32_t v) {
32;
}
+template<> inline int CountTrailingZeroes<uint64_t>(uint64_t v) {
+ return (uint32_t)v ? CountTrailingZeroes<uint32_t>(v)
+ : 32 + CountTrailingZeroes<uint32_t>(v >> 32);
+}
+
template<> inline int CountLeadingZeroes<uint32_t>(uint32_t v) {
// See Stanford bithacks, find the log base 2 of an N-bit integer in
// O(lg(N)) operations with multiply and lookup:
@@ -102,6 +121,11 @@ template<> inline int CountLeadingZeroes<uint32_t>(uint32_t v) {
32;
}
+template<> inline int CountLeadingZeroes<uint64_t>(uint64_t v) {
+ return v >> 32 ? CountLeadingZeroes<uint32_t>(v >> 32)
+ : 32 + CountLeadingZeroes<uint32_t>(v);
+}
+
} // namespace wasm
#endif // wasm_bits_h
diff --git a/src/wasm-interpreter.h b/src/wasm-interpreter.h
index 012c1c347..d231aee42 100644
--- a/src/wasm-interpreter.h
+++ b/src/wasm-interpreter.h
@@ -360,15 +360,9 @@ private:
if (value.type == i32) {
int32_t v = value.geti32();
switch (curr->op) {
- case Clz: {
- if (v == 0) return Literal(32);
- return Literal(CountLeadingZeroes((uint32_t)v));
- }
- case Ctz: {
- if (v == 0) return Literal(32);
- return Literal(CountTrailingZeroes((uint32_t)v));
- }
- case Popcnt: return Literal((int32_t)PopCount((uint32_t)v));
+ case Clz: return Literal((int32_t)CountLeadingZeroes(v));
+ case Ctz: return Literal((int32_t)CountTrailingZeroes(v));
+ case Popcnt: return Literal((int32_t)PopCount(v));
case ReinterpretInt: {
float v = value.reinterpretf32();
if (isnan(v)) {
@@ -385,19 +379,10 @@ private:
}
if (value.type == i64) {
int64_t v = value.geti64();
- int32_t high = v >> 32, low = v;
switch (curr->op) {
- case Clz: {
- if (v == 0) return Literal((int64_t)64);
- if (high == 0) return Literal(32+(int64_t)CountLeadingZeroes((uint32_t)low));
- return Literal((int64_t)CountLeadingZeroes((uint32_t)high));
- }
- case Ctz: {
- if (v == 0) return Literal((int64_t)64);
- if (low == 0) return Literal(32+(int64_t)CountTrailingZeroes((uint32_t)high));
- return Literal((int64_t)CountTrailingZeroes((uint32_t)low));
- }
- case Popcnt: return Literal((int64_t)PopCount((uint64_t)v));
+ case Clz: return Literal((int64_t)CountLeadingZeroes(v));
+ case Ctz: return Literal((int64_t)CountTrailingZeroes(v));
+ case Popcnt: return Literal((int64_t)PopCount(v));
case WrapInt64: return Literal(int32_t(value.geti64()));
case ReinterpretInt: {
return Literal(value.reinterpretf64());