power: Fix regStats for PowerModel and PowerModelState
[gem5.git] / src / sim / byteswap.hh
index a8c5da9d7661f679a8a7a2455abb82a138d636a1..06205cd6e6040d8ff294b82d27f97a6138d41894 100644 (file)
 #ifndef __SIM_BYTE_SWAP_HH__
 #define __SIM_BYTE_SWAP_HH__
 
-#include "sim/host.hh"
+#include "base/logging.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
 // works out
 #include <byteswap.h>
+#elif defined (__sun)
+#include <sys/isa_defs.h>
 #else
 #include <machine/endian.h>
 #endif
 
+#if defined(__APPLE__)
+#include <libkern/OSByteOrder.h>
+#endif
+
 //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);
 #else
     return  (uint64_t)((((uint64_t)(x) & 0xff) << 56) |
             ((uint64_t)(x) & 0xff00ULL) << 40 |
@@ -65,11 +74,13 @@ 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);
 #else
     return  (uint32_t)(((uint32_t)(x) & 0xff) << 24 |
             ((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 |
@@ -77,87 +88,81 @@ 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);
 #else
     return (uint16_t)(((uint16_t)(x) & 0xff) << 8 |
                       ((uint16_t)(x) & 0xff00) >> 8);
 #endif
 }
 
-//This lets the compiler figure out how to call the swap_byte functions above
-//for different data types.
-static inline uint64_t swap_byte(uint64_t x) {return swap_byte64(x);}
-static inline int64_t swap_byte(int64_t x) {return swap_byte64((uint64_t)x);}
-static inline uint32_t swap_byte(uint32_t x) {return swap_byte32(x);}
-static inline int32_t swap_byte(int32_t x) {return swap_byte32((uint32_t)x);}
-//This is to prevent the following two functions from compiling on
-//64bit machines. It won't detect everything, so it should be changed.
-#ifndef __x86_64__
-static inline long swap_byte(long x) {return swap_byte32((long)x);}
-static inline unsigned long swap_byte(unsigned long x)
-                                { return swap_byte32((unsigned long)x);}
-#endif
-static inline uint16_t swap_byte(uint16_t x) {return swap_byte32(x);}
-static inline int16_t swap_byte(int16_t x) {return swap_byte16((uint16_t)x);}
-static inline uint8_t swap_byte(uint8_t x) {return x;}
-static inline int8_t swap_byte(int8_t x) {return x;}
-static inline double swap_byte(double x) {return swap_byte64((uint64_t)x);}
-static inline float swap_byte(float x) {return swap_byte32((uint32_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 compile time, it should inline to a
+// direct call to the right swap_byteNN() function.
+template <typename T>
+inline T swap_byte(T x) {
+    if (sizeof(T) == 8)
+        return swap_byte64((uint64_t)x);
+    else if (sizeof(T) == 4)
+        return swap_byte32((uint32_t)x);
+    else if (sizeof(T) == 2)
+        return swap_byte16((uint16_t)x);
+    else if (sizeof(T) == 1)
+        return x;
+    else
+        panic("Can't byte-swap values larger than 64 bits");
+}
+
+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 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;}
-#elif 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);}
+#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
+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>
+inline T htog(T value, ByteOrder guest_byte_order)
 {
-        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);}
+    return guest_byte_order == BigEndianByteOrder ?
+        htobe(value) : htole(value);
 }
 
-namespace LittleEndianGuest
+template <typename T>
+inline T gtoh(T value, ByteOrder guest_byte_order)
 {
-        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);}
+    return guest_byte_order == BigEndianByteOrder ?
+        betoh(value) : letoh(value);
 }
+
 #endif // __SIM_BYTE_SWAP_HH__