From 0f264a174ed6ec1cf18bf7d34aed79cdf2deb66d Mon Sep 17 00:00:00 2001 From: Andrew Waterman Date: Mon, 28 Dec 2020 15:43:28 -0800 Subject: Install fesvr/byteorder.h to fix #622 --- fesvr/byteorder.h | 94 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ fesvr/fesvr.mk.in | 1 + 2 files changed, 95 insertions(+) create mode 100644 fesvr/byteorder.h (limited to 'fesvr') 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 + +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 static inline T from_be(T n) { return n; } +template static inline T to_be(T n) { return n; } +template static inline T from_le(T n) { return swap(n); } +template static inline T to_le(T n) { return swap(n); } +#else +template static inline T from_le(T n) { return n; } +template static inline T to_le(T n) { return n; } +template static inline T from_be(T n) { return swap(n); } +template static inline T to_be(T n) { return swap(n); } +#endif + +// Wrapper to mark a value as target endian, to guide conversion code + +template 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 class target_endian : public base_endian { + protected: + target_endian(T n) : base_endian(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 const target_endian target_endian::zero = target_endian(T(0)); +template const target_endian target_endian::all_ones = target_endian(~T(0)); + + +// Specializations with implicit conversions (no swap information needed) + +template<> class target_endian : public base_endian { + public: + target_endian() {} + target_endian(uint8_t n) : base_endian(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 : public base_endian { + public: + target_endian() {} + target_endian(int8_t n) : base_endian(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 \ -- cgit v1.1