base: Add endianness conversion functions for std::array types.
[gem5.git] / src / sim / byteswap.hh
index f8e5215cf764b519930f9038be08e92d7887fdbd..02a05330810e29018d18252d6cc3f59b37cb26cd 100644 (file)
 #ifndef __SIM_BYTE_SWAP_HH__
 #define __SIM_BYTE_SWAP_HH__
 
-#include "base/misc.hh"
-#include "sim/host.hh"
+#include "base/bigint.hh"
+#include "base/types.hh"
 
 // This lets us figure out what the byte order of the host system is
-#if defined(linux)
+#if defined(__linux__)
 #include <endian.h>
 // If this is a linux system, lets used the optimized definitions if they exist.
 // If one doesn't exist, we pretty much get what is listed below, so it all
 
 //These functions actually perform the swapping for parameters
 //of various bit lengths
-static inline uint64_t
+inline uint64_t
 swap_byte64(uint64_t x)
 {
-#if defined(linux)
+#if defined(__linux__)
     return bswap_64(x);
 #elif defined(__APPLE__)
     return OSSwapInt64(x);
@@ -78,10 +78,10 @@ swap_byte64(uint64_t x)
 #endif
 }
 
-static inline uint32_t
+inline uint32_t
 swap_byte32(uint32_t x)
 {
-#if defined(linux)
+#if defined(__linux__)
     return bswap_32(x);
 #elif defined(__APPLE__)
     return OSSwapInt32(x);
@@ -92,10 +92,10 @@ swap_byte32(uint32_t x)
 #endif
 }
 
-static inline uint16_t
+inline uint16_t
 swap_byte16(uint16_t x)
 {
-#if defined(linux)
+#if defined(__linux__)
     return bswap_16(x);
 #elif defined(__APPLE__)
     return OSSwapInt16(x);
@@ -107,10 +107,10 @@ swap_byte16(uint16_t x)
 
 // This function lets the compiler figure out how to call the
 // swap_byte functions above for different data types.  Since the
-// sizeof() values are known at compiel time, it should inline to a
+// sizeof() values are known at compile time, it should inline to a
 // direct call to the right swap_byteNN() function.
 template <typename T>
-static inline T swap_byte(T x) {
+inline T swap_byte(T x) {
     if (sizeof(T) == 8)
         return swap_byte64((uint64_t)x);
     else if (sizeof(T) == 4)
@@ -123,56 +123,85 @@ static inline T swap_byte(T x) {
         panic("Can't byte-swap values larger than 64 bits");
 }
 
+template<>
+inline Twin64_t swap_byte<Twin64_t>(Twin64_t x)
+{
+    x.a = swap_byte(x.a);
+    x.b = swap_byte(x.b);
+    return x;
+}
+
+template<>
+inline Twin32_t swap_byte<Twin32_t>(Twin32_t x)
+{
+    x.a = swap_byte(x.a);
+    x.b = swap_byte(x.b);
+    return x;
+}
+
+template <typename T, size_t N>
+inline std::array<T, N>
+swap_byte(std::array<T, N> a)
+{
+    for (T &v: a)
+        v = swap_byte(v);
+    return a;
+}
+
 //The conversion functions with fixed endianness on both ends don't need to
 //be in a namespace
-template <typename T> static inline T betole(T value) {return swap_byte(value);}
-template <typename T> static inline T letobe(T value) {return swap_byte(value);}
+template <typename T> inline T betole(T value) {return swap_byte(value);}
+template <typename T> inline T letobe(T value) {return swap_byte(value);}
 
 //For conversions not involving the guest system, we can define the functions
 //conditionally based on the BYTE_ORDER macro and outside of the namespaces
-#if defined(_BIG_ENDIAN) || BYTE_ORDER == BIG_ENDIAN
-template <typename T> static inline T htole(T value) {return swap_byte(value);}
-template <typename T> static inline T letoh(T value) {return swap_byte(value);}
-template <typename T> static inline T htobe(T value) {return value;}
-template <typename T> static inline T betoh(T value) {return value;}
+#if (defined(_BIG_ENDIAN) || !defined(_LITTLE_ENDIAN)) && BYTE_ORDER == BIG_ENDIAN
+const ByteOrder HostByteOrder = BigEndianByteOrder;
+template <typename T> inline T htole(T value) {return swap_byte(value);}
+template <typename T> inline T letoh(T value) {return swap_byte(value);}
+template <typename T> inline T htobe(T value) {return value;}
+template <typename T> inline T betoh(T value) {return value;}
 #elif defined(_LITTLE_ENDIAN) || BYTE_ORDER == LITTLE_ENDIAN
-template <typename T> static inline T htole(T value) {return value;}
-template <typename T> static inline T letoh(T value) {return value;}
-template <typename T> static inline T htobe(T value) {return swap_byte(value);}
-template <typename T> static inline T betoh(T value) {return swap_byte(value);}
+const ByteOrder HostByteOrder = LittleEndianByteOrder;
+template <typename T> inline T htole(T value) {return value;}
+template <typename T> inline T letoh(T value) {return value;}
+template <typename T> inline T htobe(T value) {return swap_byte(value);}
+template <typename T> inline T betoh(T value) {return swap_byte(value);}
 #else
         #error Invalid Endianess
 #endif
 
 namespace BigEndianGuest
 {
-        template <typename T>
-        static inline T gtole(T value) {return betole(value);}
-        template <typename T>
-        static inline T letog(T value) {return letobe(value);}
-        template <typename T>
-        static inline T gtobe(T value) {return value;}
-        template <typename T>
-        static inline T betog(T value) {return value;}
-        template <typename T>
-        static inline T htog(T value) {return htobe(value);}
-        template <typename T>
-        static inline T gtoh(T value) {return betoh(value);}
+    const ByteOrder GuestByteOrder = BigEndianByteOrder;
+    template <typename T>
+    inline T gtole(T value) {return betole(value);}
+    template <typename T>
+    inline T letog(T value) {return letobe(value);}
+    template <typename T>
+    inline T gtobe(T value) {return value;}
+    template <typename T>
+    inline T betog(T value) {return value;}
+    template <typename T>
+    inline T htog(T value) {return htobe(value);}
+    template <typename T>
+    inline T gtoh(T value) {return betoh(value);}
 }
 
 namespace LittleEndianGuest
 {
-        template <typename T>
-        static inline T gtole(T value) {return value;}
-        template <typename T>
-        static inline T letog(T value) {return value;}
-        template <typename T>
-        static inline T gtobe(T value) {return letobe(value);}
-        template <typename T>
-        static inline T betog(T value) {return betole(value);}
-        template <typename T>
-        static inline T htog(T value) {return htole(value);}
-        template <typename T>
-        static inline T gtoh(T value) {return letoh(value);}
+    const ByteOrder GuestByteOrder = LittleEndianByteOrder;
+    template <typename T>
+    inline T gtole(T value) {return value;}
+    template <typename T>
+    inline T letog(T value) {return value;}
+    template <typename T>
+    inline T gtobe(T value) {return letobe(value);}
+    template <typename T>
+    inline T betog(T value) {return betole(value);}
+    template <typename T>
+    inline T htog(T value) {return htole(value);}
+    template <typename T>
+    inline T gtoh(T value) {return letoh(value);}
 }
 #endif // __SIM_BYTE_SWAP_HH__