1 // See LICENSE for license details. 2 3 #ifndef _RISCV_BYTEORDER_H 4 #define _RISCV_BYTEORDER_H 5 6 #include "config.h" 7 #include <stdint.h> 8 swap(uint8_t n)9static inline uint8_t swap(uint8_t n) { return n; } swap(uint16_t n)10static inline uint16_t swap(uint16_t n) { return (n >> 8) | (n << 8); } swap(uint32_t n)11static inline uint32_t swap(uint32_t n) { return (swap(uint16_t(n)) << 16) | swap(uint16_t(n >> 16)); } swap(uint64_t n)12static inline uint64_t swap(uint64_t n) { return (uint64_t(swap(uint32_t(n))) << 32) | swap(uint32_t(n >> 32)); } swap(int8_t n)13static inline int8_t swap(int8_t n) { return n; } swap(int16_t n)14static inline int16_t swap(int16_t n) { return int16_t(swap(uint16_t(n))); } swap(int32_t n)15static inline int32_t swap(int32_t n) { return int32_t(swap(uint32_t(n))); } swap(int64_t n)16static inline int64_t swap(int64_t n) { return int64_t(swap(uint64_t(n))); } 17 18 #ifdef WORDS_BIGENDIAN from_be(T n)19template<typename T> static inline T from_be(T n) { return n; } to_be(T n)20template<typename T> static inline T to_be(T n) { return n; } from_le(T n)21template<typename T> static inline T from_le(T n) { return swap(n); } to_le(T n)22template<typename T> static inline T to_le(T n) { return swap(n); } 23 #else from_le(T n)24template<typename T> static inline T from_le(T n) { return n; } to_le(T n)25template<typename T> static inline T to_le(T n) { return n; } from_be(T n)26template<typename T> static inline T from_be(T n) { return swap(n); } to_be(T n)27template<typename T> static inline T to_be(T n) { return swap(n); } 28 #endif 29 30 // Wrapper to mark a value as target endian, to guide conversion code 31 32 template<typename T> class base_endian { 33 34 protected: 35 T value; 36 base_endian(T n)37 base_endian(T n) : value(n) {} 38 39 public: 40 // Setting to and testing against zero never needs swapping base_endian()41 base_endian() : value(0) {} 42 bool operator!() { return !value; } 43 44 // Bitwise logic operations can be performed without swapping 45 base_endian& operator|=(const base_endian& rhs) { value |= rhs.value; return *this; } 46 base_endian& operator&=(const base_endian& rhs) { value &= rhs.value; return *this; } 47 base_endian& operator^=(const base_endian& rhs) { value ^= rhs.value; return *this; } 48 from_be()49 inline T from_be() { return ::from_be(value); } from_le()50 inline T from_le() { return ::from_le(value); } 51 }; 52 53 template<typename T> class target_endian : public base_endian<T> { 54 protected: target_endian(T n)55 target_endian(T n) : base_endian<T>(n) {} 56 57 public: target_endian()58 target_endian() {} 59 to_be(T n)60 static inline target_endian to_be(T n) { return target_endian(::to_be(n)); } to_le(T n)61 static inline target_endian to_le(T n) { return target_endian(::to_le(n)); } 62 63 // Useful values over which swapping is identity 64 static const target_endian zero; 65 static const target_endian all_ones; 66 }; 67 68 template<typename T> const target_endian<T> target_endian<T>::zero = target_endian(T(0)); 69 template<typename T> const target_endian<T> target_endian<T>::all_ones = target_endian(~T(0)); 70 71 72 // Specializations with implicit conversions (no swap information needed) 73 74 template<> class target_endian<uint8_t> : public base_endian<uint8_t> { 75 public: target_endian()76 target_endian() {} target_endian(uint8_t n)77 target_endian(uint8_t n) : base_endian<uint8_t>(n) {} uint8_t()78 operator uint8_t() { return value; } 79 to_be(uint8_t n)80 static inline target_endian to_be(uint8_t n) { return target_endian(n); } to_le(uint8_t n)81 static inline target_endian to_le(uint8_t n) { return target_endian(n); } 82 }; 83 84 template<> class target_endian<int8_t> : public base_endian<int8_t> { 85 public: target_endian()86 target_endian() {} target_endian(int8_t n)87 target_endian(int8_t n) : base_endian<int8_t>(n) {} int8_t()88 operator int8_t() { return value; } 89 to_be(int8_t n)90 static inline target_endian to_be(int8_t n) { return target_endian(n); } to_le(int8_t n)91 static inline target_endian to_le(int8_t n) { return target_endian(n); } 92 }; 93 94 #endif 95