123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310 |
- #ifndef CRCUTIL_UINT128_SSE2_H_
- #define CRCUTIL_UINT128_SSE2_H_
- #include "base_types.h"
- #include "crc_casts.h"
- #include "platform.h"
- #if HAVE_SSE2
- namespace crcutil {
- template<> __forceinline uint64 Downcast(const __m128i &value) {
- #if HAVE_AMD64 && defined(__GNUC__)
-
-
-
-
- uint64 temp;
- asm(SSE2_MOVQ " %[i128], %[u64]\n" : [u64] "=r" (temp) : [i128] "x" (value));
- return temp;
- #elif HAVE_AMD64 && (!defined(_MSC_FULL_VER) || _MSC_FULL_VER > 150030729)
- return static_cast<uint64>(_mm_cvtsi128_si64(value));
- #else
-
-
- uint64 temp;
- _mm_storel_epi64(reinterpret_cast<__m128i *>(&temp), value);
- return temp;
- #endif
- }
- class uint128_sse2 {
- public:
- uint128_sse2() {}
- ~uint128_sse2() {}
-
- __forceinline void operator =(uint64 value) {
- #if HAVE_AMD64 && defined(__GNUC__) && !GCC_VERSION_AVAILABLE(4, 5)
-
-
- asm(SSE2_MOVQ " %[u64], %[i128]\n" : [i128] "=x" (x_) : [u64] "r" (value));
- #elif HAVE_AMD64
- x_ = _mm_cvtsi64_si128(static_cast<int64>(value));
- #else
- x_ = _mm_loadl_epi64(reinterpret_cast<const __m128i *>(&value));
- #endif
- }
- __forceinline uint128_sse2(uint64 x) {
- *this = x;
- }
- __forceinline uint128_sse2(const __m128i x) : x_(x) {
- }
- __forceinline operator __m128i() const {
- return x_;
- }
- __forceinline void operator =(const uint128_sse2 &x) {
- x_ = x.x_;
- }
-
- __forceinline uint64 to_uint64() const {
- return Downcast<__m128i, uint64>(x_);
- }
-
- __forceinline bool operator ==(const uint128_sse2 &y) const {
- union {
- __m128i i128;
- uint64 u64[2];
- } t;
- t.i128 = _mm_xor_si128(x_, y.x_);
- return (t.u64[0] | t.u64[1]) == 0;
- }
- __forceinline bool operator ==(uint64 value) const {
- union {
- __m128i i128;
- uint64 u64[2];
- } t;
- t.i128 = x_;
- return (t.u64[0] == value && t.u64[1] == 0);
- }
- __forceinline bool operator !=(const uint128_sse2 &y) const {
- union {
- __m128i i128;
- uint64 u64[2];
- } t;
- t.i128 = _mm_xor_si128(x_, y.x_);
- return (t.u64[0] | t.u64[1]) != 0;
- }
- __forceinline bool operator !=(uint64 value) const {
- union {
- __m128i i128;
- uint64 u64[2];
- } t;
- t.i128 = x_;
- return (t.u64[0] != value || t.u64[1] != 0);
- }
- __forceinline bool operator <(const uint128_sse2 &y) const {
- union {
- __m128i i128;
- uint64 u64[2];
- } xx, yy;
- xx.i128 = x_;
- yy.i128 = y.x_;
- return (xx.u64[0] < yy.u64[0] ||
- (xx.u64[0] == yy.u64[0] && xx.u64[1] < yy.u64[1]));
- }
-
- __forceinline uint128_sse2 operator ^(const uint128_sse2 &y) const {
- return _mm_xor_si128(x_, y.x_);
- }
- __forceinline uint128_sse2 operator &(const uint128_sse2 &y) const {
- return _mm_and_si128(x_, y.x_);
- }
- __forceinline uint128_sse2 operator |(const uint128_sse2 &y) const {
- return _mm_or_si128(x_, y.x_);
- }
- __forceinline void operator ^=(const uint128_sse2 &y) {
- *this = *this ^ y.x_;
- }
- __forceinline void operator &=(const uint128_sse2 &y) {
- *this = *this & y.x_;
- }
- __forceinline void operator |=(const uint128_sse2 &y) {
- *this = *this | y.x_;
- }
-
- __forceinline uint128_sse2 operator +(uint64 y) const {
- union {
- __m128i i128;
- uint64 u64[2];
- } temp;
- temp.i128 = x_;
-
-
-
-
- if (temp.u64[0] > ~y) {
- temp.u64[1] += 1;
- }
- temp.u64[0] += y;
- return temp.i128;
- }
- __forceinline void operator +=(uint64 x) {
- *this = *this + x;
- }
- __forceinline uint128_sse2 operator -(uint64 y) const {
- union {
- __m128i i128;
- uint64 u64[2];
- } temp;
- temp.i128 = x_;
- if (temp.u64[0] < y) {
- temp.u64[1] -= 1;
- }
- temp.u64[0] -= y;
- return temp.i128;
- }
- __forceinline void operator -=(uint64 x) {
- *this = *this - x;
- }
-
- __forceinline uint128_sse2 operator >>(const int bits) const {
- if (bits == 8) {
- return _mm_srli_si128(x_, 1);
- } else if (bits == 16) {
- return _mm_srli_si128(x_, 2);
- } else if (bits == 32) {
- return _mm_srli_si128(x_, 4);
- } else if (bits == 64) {
- return _mm_srli_si128(x_, 8);
- } else {
- return long_shift_right(bits);
- }
- }
- __forceinline uint128_sse2 operator >>(const size_t bits) const {
- return *this >> static_cast<int>(bits);
- }
- __forceinline void operator >>=(const int bits) {
- *this = *this >> bits;
- }
- __forceinline void operator >>=(const size_t bits) {
- *this = *this >> static_cast<int>(bits);
- }
- __forceinline uint128_sse2 operator <<(int bits) const {
- if (bits == 8) {
- return _mm_slli_si128(x_, 1);
- } else if (bits == 16) {
- return _mm_slli_si128(x_, 2);
- } else if (bits == 32) {
- return _mm_slli_si128(x_, 4);
- } else if (bits == 64) {
- return _mm_slli_si128(x_, 8);
- } else {
- return long_shift_left(bits);
- }
- }
- __forceinline uint128_sse2 operator <<(size_t bits) const {
- return *this << static_cast<int>(bits);
- }
- __forceinline void operator <<=(int bits) {
- *this = *this << bits;
- }
- __forceinline void operator <<=(size_t bits) {
- *this = *this << static_cast<int>(bits);
- }
- protected:
- __forceinline uint128_sse2 long_shift_right(int bits) const {
- union {
- __m128i i128;
- uint64 u64[2];
- } x;
- x.i128 = x_;
- for (; bits > 0; --bits) {
- x.u64[0] >>= 1;
- if (x.u64[1] & 1) {
- x.u64[0] |= static_cast<uint64>(1) << 63;
- }
- x.u64[1] >>= 1;
- }
- return x.i128;
- }
- __forceinline uint128_sse2 long_shift_left(int bits) const {
- union {
- __m128i i128;
- int64 i64[2];
- } x;
- x.i128 = x_;
- for (; bits > 0; --bits) {
- x.i64[1] <<= 1;
- if (x.i64[0] < 0) {
- x.i64[1] |= 1;
- }
- x.i64[0] <<= 1;
- }
- return x.i128;
- }
- __m128i x_;
- } GCC_ALIGN_ATTRIBUTE(16);
- template<> __forceinline uint64 Downcast(const uint128_sse2 &x) {
- return x.to_uint64();
- }
- template<> __forceinline uint32 Downcast(const uint128_sse2 &x) {
- return static_cast<uint32>(x.to_uint64());
- }
- template<> __forceinline uint16 Downcast(const uint128_sse2 &x) {
- return static_cast<uint16>(x.to_uint64());
- }
- template<> __forceinline uint8 Downcast(const uint128_sse2 &x) {
- return static_cast<uint8>(x.to_uint64());
- }
- template<> __forceinline uint128_sse2 CrcFromUint64(uint64 lo, uint64 hi) {
- union {
- __m128i i128;
- uint64 u64[2];
- } temp;
- temp.u64[0] = lo;
- temp.u64[1] = hi;
- return temp.i128;
- }
- template<> __forceinline void Uint64FromCrc(const uint128_sse2 &crc,
- uint64 *lo, uint64 *hi) {
- union {
- __m128i i128;
- uint64 u64[2];
- } temp;
- temp.i128 = crc;
- *lo = temp.u64[0];
- *hi = temp.u64[1];
- }
- }
- #endif
- #endif
|