diff options
author | Andrew Waterman <andrew@sifive.com> | 2020-12-28 15:43:28 -0800 |
---|---|---|
committer | Andrew Waterman <andrew@sifive.com> | 2020-12-28 15:43:28 -0800 |
commit | 0f264a174ed6ec1cf18bf7d34aed79cdf2deb66d (patch) | |
tree | 77f76ef92ba195094ad372c5283ebaf5824cd86c /fesvr | |
parent | 032a68c3e94b0d315207a5a42251f836185b5d01 (diff) | |
download | riscv-isa-sim-0f264a174ed6ec1cf18bf7d34aed79cdf2deb66d.zip riscv-isa-sim-0f264a174ed6ec1cf18bf7d34aed79cdf2deb66d.tar.gz riscv-isa-sim-0f264a174ed6ec1cf18bf7d34aed79cdf2deb66d.tar.bz2 |
Install fesvr/byteorder.h to fix #622
Diffstat (limited to 'fesvr')
-rw-r--r-- | fesvr/byteorder.h | 94 | ||||
-rw-r--r-- | fesvr/fesvr.mk.in | 1 |
2 files changed, 95 insertions, 0 deletions
diff --git a/fesvr/byteorder.h b/fesvr/byteorder.h new file mode 100644 index 0000000..2b1dbf9 --- /dev/null +++ b/fesvr/byteorder.h @@ -0,0 +1,94 @@ +// See LICENSE for license details. + +#ifndef _RISCV_BYTEORDER_H +#define _RISCV_BYTEORDER_H + +#include "config.h" +#include <stdint.h> + +static inline uint8_t swap(uint8_t n) { return n; } +static inline uint16_t swap(uint16_t n) { return (n >> 8) | (n << 8); } +static inline uint32_t swap(uint32_t n) { return (swap(uint16_t(n)) << 16) | swap(uint16_t(n >> 16)); } +static inline uint64_t swap(uint64_t n) { return (uint64_t(swap(uint32_t(n))) << 32) | swap(uint32_t(n >> 32)); } +static inline int8_t swap(int8_t n) { return n; } +static inline int16_t swap(int16_t n) { return int16_t(swap(uint16_t(n))); } +static inline int32_t swap(int32_t n) { return int32_t(swap(uint32_t(n))); } +static inline int64_t swap(int64_t n) { return int64_t(swap(uint64_t(n))); } + +#ifdef WORDS_BIGENDIAN +template<typename T> static inline T from_be(T n) { return n; } +template<typename T> static inline T to_be(T n) { return n; } +template<typename T> static inline T from_le(T n) { return swap(n); } +template<typename T> static inline T to_le(T n) { return swap(n); } +#else +template<typename T> static inline T from_le(T n) { return n; } +template<typename T> static inline T to_le(T n) { return n; } +template<typename T> static inline T from_be(T n) { return swap(n); } +template<typename T> static inline T to_be(T n) { return swap(n); } +#endif + +// Wrapper to mark a value as target endian, to guide conversion code + +template<typename T> class base_endian { + + protected: + T value; + + base_endian(T n) : value(n) {} + + public: + // Setting to and testing against zero never needs swapping + base_endian() : value(0) {} + bool operator!() { return !value; } + + // Bitwise logic operations can be performed without swapping + base_endian& operator|=(const base_endian& rhs) { value |= rhs.value; return *this; } + base_endian& operator&=(const base_endian& rhs) { value &= rhs.value; return *this; } + base_endian& operator^=(const base_endian& rhs) { value ^= rhs.value; return *this; } + + inline T from_be() { return ::from_be(value); } + inline T from_le() { return ::from_le(value); } +}; + +template<typename T> class target_endian : public base_endian<T> { + protected: + target_endian(T n) : base_endian<T>(n) {} + + public: + target_endian() {} + + static inline target_endian to_be(T n) { return target_endian(::to_be(n)); } + static inline target_endian to_le(T n) { return target_endian(::to_le(n)); } + + // Useful values over which swapping is identity + static const target_endian zero; + static const target_endian all_ones; +}; + +template<typename T> const target_endian<T> target_endian<T>::zero = target_endian(T(0)); +template<typename T> const target_endian<T> target_endian<T>::all_ones = target_endian(~T(0)); + + +// Specializations with implicit conversions (no swap information needed) + +template<> class target_endian<uint8_t> : public base_endian<uint8_t> { + public: + target_endian() {} + target_endian(uint8_t n) : base_endian<uint8_t>(n) {} + operator uint8_t() { return value; } + + static inline target_endian to_be(uint8_t n) { return target_endian(n); } + static inline target_endian to_le(uint8_t n) { return target_endian(n); } +}; + +template<> class target_endian<int8_t> : public base_endian<int8_t> { + public: + target_endian() {} + target_endian(int8_t n) : base_endian<int8_t>(n) {} + operator int8_t() { return value; } + + static inline target_endian to_be(int8_t n) { return target_endian(n); } + static inline target_endian to_le(int8_t n) { return target_endian(n); } +}; + +#endif diff --git a/fesvr/fesvr.mk.in b/fesvr/fesvr.mk.in index 30c8bfe..48b3287 100644 --- a/fesvr/fesvr.mk.in +++ b/fesvr/fesvr.mk.in @@ -1,4 +1,5 @@ fesvr_hdrs = \ + byteorder.h \ elf.h \ elfloader.h \ htif.h \ |