asm.hpp: constexpr refactoring

Removed asm (what an irony), made many functions constexpr.
Removed some unused function, readding them should be trivial.
This commit is contained in:
Nekotekina 2020-11-24 12:30:03 +03:00
parent ab248e170c
commit d8e9382573

View File

@ -111,259 +111,177 @@ namespace utils
return _m_prefetchw(ptr);
}
#if defined(__GNUG__)
inline u8 rol8(u8 x, u8 n)
constexpr u8 rol8(u8 x, u8 n)
{
#if __has_builtin(__builtin_rotateleft8)
return __builtin_rotateleft8(x, n);
#else
u8 result = x;
__asm__("rolb %[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
inline u8 ror8(u8 x, u8 n)
{
#if __has_builtin(__builtin_rotateright8)
return __builtin_rotateright8(x, n);
#else
u8 result = x;
__asm__("rorb %[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
inline u16 rol16(u16 x, u16 n)
{
#if __has_builtin(__builtin_rotateleft16)
return __builtin_rotateleft16(x, n);
#else
u16 result = x;
__asm__("rolw %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
inline u16 ror16(u16 x, u16 n)
{
#if __has_builtin(__builtin_rotateright16)
return __builtin_rotateright16(x, n);
#else
u16 result = x;
__asm__("rorw %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
inline u32 rol32(u32 x, u32 n)
{
#if __has_builtin(__builtin_rotateleft32)
return __builtin_rotateleft32(x, n);
#else
u32 result = x;
__asm__("roll %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
inline u32 ror32(u32 x, u32 n)
{
#if __has_builtin(__builtin_rotateright32)
return __builtin_rotateright32(x, n);
#else
u32 result = x;
__asm__("rorl %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
inline u64 rol64(u64 x, u64 n)
{
#if __has_builtin(__builtin_rotateleft64)
return __builtin_rotateleft64(x, n);
#else
u64 result = x;
__asm__("rolq %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
inline u64 ror64(u64 x, u64 n)
{
#if __has_builtin(__builtin_rotateright64)
return __builtin_rotateright64(x, n);
#else
u64 result = x;
__asm__("rorq %b[n], %[result]" : [result] "+g"(result) : [n] "c"(n));
return result;
#endif
}
constexpr u64 umulh64(u64 a, u64 b)
{
const __uint128_t x = a;
const __uint128_t y = b;
return (x * y) >> 64;
}
constexpr s64 mulh64(s64 a, s64 b)
{
const __int128_t x = a;
const __int128_t y = b;
return (x * y) >> 64;
}
constexpr s64 div128(s64 high, s64 low, s64 divisor, s64* remainder = nullptr)
{
const __int128_t x = (__uint128_t{u64(high)} << 64) | u64(low);
const __int128_t r = x / divisor;
if (remainder)
if (std::is_constant_evaluated())
{
*remainder = x % divisor;
return (x << (n & 7)) | (x >> ((-n & 7)));
}
return r;
}
constexpr u64 udiv128(u64 high, u64 low, u64 divisor, u64* remainder = nullptr)
{
const __uint128_t x = (__uint128_t{high} << 64) | low;
const __uint128_t r = x / divisor;
if (remainder)
{
*remainder = x % divisor;
}
return r;
}
inline u32 ctz128(u128 arg)
{
if (u64 lo = static_cast<u64>(arg))
{
return std::countr_zero<u64>(lo);
}
else
{
return std::countr_zero<u64>(arg >> 64) + 64;
}
}
inline u32 clz128(u128 arg)
{
if (u64 hi = static_cast<u64>(arg >> 64))
{
return std::countl_zero<u64>(hi);
}
else
{
return std::countl_zero<u64>(arg) + 64;
}
}
#elif defined(_MSC_VER)
inline u8 rol8(u8 x, u8 n)
{
#ifdef _MSC_VER
return _rotl8(x, n);
#else
return __rolb(x, n);
#endif
}
inline u8 ror8(u8 x, u8 n)
constexpr u16 rol16(u16 x, u16 n)
{
return _rotr8(x, n);
if (std::is_constant_evaluated())
{
return (x << (n & 15)) | (x >> ((-n & 15)));
}
#ifdef _MSC_VER
return _rotl16(x, n);
#else
return __rolw(x, n);
#endif
}
inline u16 rol16(u16 x, u16 n)
constexpr u32 rol32(u32 x, u32 n)
{
return _rotl16(x, (u8)n);
if (std::is_constant_evaluated())
{
return (x << (n & 31)) | (x >> (((0 - n) & 31)));
}
#ifdef _MSC_VER
return _rotl(x, n);
#else
return __rold(x, n);
#endif
}
inline u16 ror16(u16 x, u16 n)
constexpr u32 ror32(u32 x, u32 n)
{
return _rotr16(x, (u8)n);
if (std::is_constant_evaluated())
{
return (x >> (n & 31)) | (x << (((0 - n) & 31)));
}
#ifdef _MSC_VER
return _rotr(x, n);
#else
return __rord(x, n);
#endif
}
inline u32 rol32(u32 x, u32 n)
constexpr u64 rol64(u64 x, u64 n)
{
return _rotl(x, (int)n);
if (std::is_constant_evaluated())
{
return (x << (n & 63)) | (x >> (((0 - n) & 63)));
}
#ifdef _MSC_VER
return _rotl64(x, static_cast<int>(n));
#else
return __rolq(x, static_cast<int>(n));
#endif
}
inline u32 ror32(u32 x, u32 n)
constexpr u64 umulh64(u64 x, u64 y)
{
return _rotr(x, (int)n);
}
#ifdef _MSC_VER
if (std::is_constant_evaluated())
{
u128 a = (u32)x * (u64)(u32)y;
u128 b = (x >> 32) * (u32)y;
u128 c = (u32)x * (y >> 32);
u128 d = (x >> 32) * (y >> 32);
a += (b << 32);
a += (c << 32);
a.hi += d.lo;
return a.hi;
}
inline u64 rol64(u64 x, u64 n)
{
return _rotl64(x, (int)n);
}
inline u64 ror64(u64 x, u64 n)
{
return _rotr64(x, (int)n);
}
inline u64 umulh64(u64 x, u64 y)
{
return __umulh(x, y);
#else
return (u128{x} * u128{y}) >> 64;
#endif
}
inline s64 mulh64(s64 x, s64 y)
{
#ifdef _MSC_VER
return __mulh(x, y);
#else
return (s128{x} * s128{y}) >> 64;
#endif
}
inline s64 div128(s64 high, s64 low, s64 divisor, s64* remainder = nullptr)
{
s64 rem;
#ifdef _MSC_VER
s64 rem = 0;
s64 r = _div128(high, low, divisor, &rem);
if (remainder)
{
*remainder = rem;
}
#else
const s128 x = (u128{static_cast<u64>(high)} << 64) | u64(low);
const s128 r = x / divisor;
if (remainder)
{
*remainder = x % divisor;
}
#endif
return r;
}
inline u64 udiv128(u64 high, u64 low, u64 divisor, u64* remainder = nullptr)
{
u64 rem;
#ifdef _MSC_VER
u64 rem = 0;
u64 r = _udiv128(high, low, divisor, &rem);
if (remainder)
{
*remainder = rem;
}
#else
const u128 x = (u128{high} << 64) | low;
const u128 r = x / divisor;
if (remainder)
{
*remainder = x % divisor;
}
#endif
return r;
}
inline u32 ctz128(u128 arg)
constexpr u32 ctz128(u128 arg)
{
#ifdef _MSC_VER
if (!arg.lo)
{
return std::countr_zero(arg.hi) + 64u;
}
else
{
return std::countr_zero(arg.lo);
}
#else
if (u64 lo = static_cast<u64>(arg))
return std::countr_zero<u64>(lo);
else
return std::countr_zero<u64>(arg >> 64) + 64;
#endif
}
inline u32 clz128(u128 arg)
constexpr u32 clz128(u128 arg)
{
#ifdef _MSC_VER
if (arg.hi)
{
return std::countl_zero(arg.hi);
}
else
{
return std::countl_zero(arg.lo) + 64;
}
}
#else
if (u64 hi = static_cast<u64>(arg >> 64))
return std::countl_zero<u64>(hi);
else
return std::countl_zero<u64>(arg) + 64;
#endif
}
} // namespace utils