aboutsummaryrefslogtreecommitdiff
path: root/fesvr
diff options
context:
space:
mode:
authorAndrew Waterman <andrew@sifive.com>2020-12-28 15:43:28 -0800
committerAndrew Waterman <andrew@sifive.com>2020-12-28 15:43:28 -0800
commit0f264a174ed6ec1cf18bf7d34aed79cdf2deb66d (patch)
tree77f76ef92ba195094ad372c5283ebaf5824cd86c /fesvr
parent032a68c3e94b0d315207a5a42251f836185b5d01 (diff)
downloadspike-0f264a174ed6ec1cf18bf7d34aed79cdf2deb66d.zip
spike-0f264a174ed6ec1cf18bf7d34aed79cdf2deb66d.tar.gz
spike-0f264a174ed6ec1cf18bf7d34aed79cdf2deb66d.tar.bz2
Install fesvr/byteorder.h to fix #622
Diffstat (limited to 'fesvr')
-rw-r--r--fesvr/byteorder.h94
-rw-r--r--fesvr/fesvr.mk.in1
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 \