2017-10-16 17:50:09 +02:00
|
|
|
#pragma once
|
|
|
|
|
2018-05-19 08:26:25 +01:00
|
|
|
#ifndef _MSC_VER
|
2018-05-09 20:37:49 +02:00
|
|
|
#include <x86intrin.h>
|
2018-05-19 08:26:25 +01:00
|
|
|
#else
|
|
|
|
#include <intrin.h>
|
|
|
|
#endif
|
2018-05-09 20:37:49 +02:00
|
|
|
|
2017-10-16 17:50:09 +02:00
|
|
|
namespace dxvk::bit {
|
|
|
|
|
2017-10-21 17:58:58 +02:00
|
|
|
template<typename T>
|
2017-11-07 15:10:38 +01:00
|
|
|
T extract(T value, uint32_t fst, uint32_t lst) {
|
2017-10-21 17:58:58 +02:00
|
|
|
return (value >> fst) & ~(~T(0) << (lst - fst + 1));
|
2017-10-16 17:50:09 +02:00
|
|
|
}
|
|
|
|
|
2017-11-07 15:10:38 +01:00
|
|
|
template<typename T>
|
|
|
|
T popcnt(T value) {
|
|
|
|
return value != 0
|
|
|
|
? (value & 1) + popcnt(value >> 1)
|
|
|
|
: 0;
|
|
|
|
}
|
|
|
|
|
2018-05-09 20:09:09 +02:00
|
|
|
inline uint32_t tzcnt(uint32_t n) {
|
2018-05-19 08:26:25 +01:00
|
|
|
#if defined(_MSC_VER)
|
|
|
|
return _tzcnt_u32(n);
|
|
|
|
#elif defined(__BMI__)
|
2018-05-09 20:09:09 +02:00
|
|
|
return __tzcnt_u32(n);
|
|
|
|
#elif defined(__GNUC__)
|
|
|
|
uint32_t res;
|
|
|
|
uint32_t tmp;
|
|
|
|
asm (
|
2018-07-09 13:31:34 +02:00
|
|
|
"mov $32, %1;"
|
|
|
|
"bsf %2, %0;"
|
2018-05-09 20:09:09 +02:00
|
|
|
"cmovz %1, %0;"
|
|
|
|
: "=&r" (res), "=&r" (tmp)
|
|
|
|
: "r" (n));
|
|
|
|
return res;
|
|
|
|
#else
|
|
|
|
uint32_t r = 31;
|
|
|
|
n &= -n;
|
|
|
|
r -= (n & 0x0000FFFF) ? 16 : 0;
|
|
|
|
r -= (n & 0x00FF00FF) ? 8 : 0;
|
|
|
|
r -= (n & 0x0F0F0F0F) ? 4 : 0;
|
|
|
|
r -= (n & 0x33333333) ? 2 : 0;
|
|
|
|
r -= (n & 0x55555555) ? 1 : 0;
|
|
|
|
return n != 0 ? r : 32;
|
|
|
|
#endif
|
2017-11-07 15:10:38 +01:00
|
|
|
}
|
|
|
|
|
2017-10-16 17:50:09 +02:00
|
|
|
}
|