home *** CD-ROM | disk | FTP | other *** search
- #pragma once
-
- #include "common.h"
-
- inline uint32_t hi32(const uint64_t x)
- {
- return (x >> 32);
- }
-
- inline uint32_t lo32(const uint64_t x)
- {
- return (x & 0xFFFFFFFFu);
- }
-
- union uint128_t
- {
- inline uint128_t()
- : hi(0)
- , lo(0)
- {
- }
-
- inline uint128_t(uint64_t x)
- : hi(0)
- , lo(x)
- {
- }
-
- struct
- {
- uint64_t hi;
- uint64_t lo;
- };
- };
-
- uint128_t mul64(const uint64_t a, const uint64_t b);
-
- inline uint32_t float_as_uint(const float x)
- {
- union { float f; uint32_t u; } f2u;
- f2u.f = x;
- return f2u.u;
- }
-
- inline float uint_as_float(const uint32_t x)
- {
- union { uint32_t u; float f; } u2f;
- u2f.u = x;
- return u2f.f;
- }
-
- inline uint64_t double_as_uint(const double x)
- {
- union { double f; uint64_t u; } f2u;
- f2u.f = x;
- return f2u.u;
- }
-
- inline double uint_as_double(const uint64_t x)
- {
- union { uint64_t u; double f; } u2f;
- u2f.u = x;
- return u2f.f;
- }
-
- template<typename T>
- inline typename std::enable_if<std::is_arithmetic<T>::value && std::is_signed<T>::value, T>::type isign(T x)
- {
- return (x >> (sizeof(x) * CHAR_BIT - 1));
- }
-
- uint32_t bitmask32(const int begin, const int end);
-
- uint32_t rotl(const uint32_t x, int n);
- uint32_t rotr(const uint32_t x, int n);
-
- uint32_t rlwinm(const uint32_t rs, const uint32_t sh, const int mb, const int me);
- uint32_t rlwimi(const uint32_t ra, const uint32_t rs, const uint32_t sh, const int mb, const int me);
- uint32_t clrlslwi(const uint32_t rs, const int b, const int n);
- uint32_t slw(const uint32_t ra, const uint32_t rs, const int rb);
- int32_t srawi(const int32_t rs, const int b);
-
- template<typename T>
- inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type align_up(T address, size_t alignment)
- {
- return (address + (alignment - 1)) & ~(T(alignment) - 1);
- }
-
- template<typename T>
- inline typename std::enable_if<std::is_arithmetic<T>::value, T>::type align_down(T address, size_t alignment)
- {
- return address & ~(T(alignment) - 1);
- }
-
- inline const void* advance_pointer(const void* ptr, intptr_t offset)
- {
- return static_cast<const char*>(ptr) + offset;
- }
-
- template<typename T> inline typename std::enable_if<std::is_enum<T>::value, T>::type operator ~(T x) { return static_cast<T>(~static_cast<typename std::underlying_type<T>::type>(x)); }
- template<typename T> inline typename std::enable_if<std::is_enum<T>::value, T>::type operator &(T x, T y) { return static_cast<T>(static_cast<typename std::underlying_type<T>::type>(x) & static_cast<typename std::underlying_type<T>::type>(y)); }
- template<typename T> inline typename std::enable_if<std::is_enum<T>::value, T>::type operator |(T x, T y) { return static_cast<T>(static_cast<typename std::underlying_type<T>::type>(x) | static_cast<typename std::underlying_type<T>::type>(y)); }
- template<typename T> inline typename std::enable_if<std::is_enum<T>::value, T>::type operator ^(T x, T y) { return static_cast<T>(static_cast<typename std::underlying_type<T>::type>(x) ^ static_cast<typename std::underlying_type<T>::type>(y)); }
-
- namespace detail
- {
- template<typename T, size_t Size>
- struct swap_bytes
- {
- inline T operator()(const T x)
- {
- throw std::out_of_range("Unsupported type size");
- }
- };
-
- template<typename T>
- struct swap_bytes<T, 1>
- {
- inline T operator()(const T x)
- {
- return x;
- }
- };
-
- template<typename T>
- struct swap_bytes<T, 2>
- {
- inline T operator()(const T x)
- {
- return ((x >> 8) & 0xFF) | ((x & 0xFF) << 8);
- }
- };
-
- template<typename T>
- struct swap_bytes<T, 4>
- {
- inline T operator()(const T x)
- {
- return ((x & 0xFF000000u) >> 24) | ((x & 0x00FF0000u) >> 8) | ((x & 0x0000FF00u) << 8) | ((x & 0x000000FFu) << 24);
- }
- };
-
- template<>
- struct swap_bytes<float, 4>
- {
- inline float operator()(const float x)
- {
- return uint_as_float(swap_bytes<uint32_t, sizeof(uint32_t)>()(float_as_uint(x)));
- }
- };
-
- template<typename T>
- struct swap_bytes<T, 8>
- {
- inline T operator()(const T x)
- {
- return ((x & 0xFF00000000000000ull) >> 56) | ((x & 0x00FF000000000000ull) >> 40) | ((x & 0x0000FF0000000000ull) >> 24) | ((x & 0x000000FF00000000ull) >> 8) | ((x & 0x00000000FF000000ull) << 8) | ((x & 0x0000000000FF0000ull) << 24) | ((x & 0x000000000000FF00ull) << 40) | ((x & 0x00000000000000FFull) << 56);
- }
- };
-
- template<>
- struct swap_bytes<double, 8>
- {
- inline double operator()(const double x)
- {
- return uint_as_double(swap_bytes<uint64_t, sizeof(uint64_t)>()(double_as_uint(x)));
- }
- };
-
- template<Endianness from, Endianness to, typename T>
- struct do_byte_swap
- {
- inline T operator()(const T x)
- {
- return swap_bytes<T, sizeof(T)>()(x);
- }
- };
-
- template<typename T> struct do_byte_swap<Endianness::kLITTLE, Endianness::kLITTLE, T>
- {
- inline T operator()(const T x)
- {
- return x;
- }
- };
-
- template<typename T> struct do_byte_swap<Endianness::kBIG, Endianness::kBIG, T>
- {
- inline T operator()(const T x)
- {
- return x;
- }
- };
- }
-
- template<typename T>
- inline T swap_bytes(const T x)
- {
- static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Unsupported type size");
- static_assert(std::is_arithmetic<T>::value, "Non arithmetic type");
- return detail::swap_bytes<T, sizeof(T)>()(x);
- }
-
- template<Endianness from, Endianness to, typename T>
- inline T byte_swap(const T x)
- {
- static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8, "Unsupported type size");
- static_assert(std::is_arithmetic<T>::value, "Non arithmetic type");
- return detail::do_byte_swap<from, to, T>()(x);
- }
-
- template<typename T>
- inline T little_to_host(const T x)
- {
- return byte_swap<Endianness::kLITTLE, Endianness::kHOST>(x);
- }
-
- template<typename T> inline T big_to_host(const T x)
- {
- return byte_swap<Endianness::kBIG, Endianness::kHOST>(x);
- }
-
- template<typename T> inline T host_to_little(const T x)
- {
- return byte_swap<Endianness::kHOST, Endianness::kLITTLE>(x);
- }
-
- template<typename T> inline T host_to_big(const T x)
- {
- return byte_swap<Endianness::kHOST, Endianness::kBIG>(x);
- }
-