ARM: Make VMSR, RFE PC/LR etc non speculative, and serializing
[gem5.git] / src / sim / byteswap.hh
index a3138a25e98df1d494b190291160926e53a6977e..fc36bdf3324c352808c1ff181aec705c32e89944 100644 (file)
@@ -26,6 +26,8 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  *
  * Authors: Gabe Black
+ *          Ali Saidi
+ *          Nathan Binkert
  */
 
 //The purpose of this file is to provide endainness conversion utility
@@ -35,7 +37,9 @@
 #ifndef __SIM_BYTE_SWAP_HH__
 #define __SIM_BYTE_SWAP_HH__
 
-#include "sim/host.hh"
+#include "base/bigint.hh"
+#include "base/misc.hh"
+#include "base/types.hh"
 
 // This lets us figure out what the byte order of the host system is
 #if defined(linux)
 // 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
+
+enum ByteOrder {BigEndianByteOrder, LittleEndianByteOrder};
+
 //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)
     return bswap_64(x);
+#elif defined(__APPLE__)
+    return OSSwapInt64(x);
 #else
     return  (uint64_t)((((uint64_t)(x) & 0xff) << 56) |
             ((uint64_t)(x) & 0xff00ULL) << 40 |
@@ -67,11 +81,13 @@ swap_byte64(uint64_t x)
 #endif
 }
 
-static inline uint32_t
+inline uint32_t
 swap_byte32(uint32_t x)
 {
 #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 |
@@ -79,87 +95,107 @@ swap_byte32(uint32_t x)
 #endif
 }
 
-static inline uint16_t
+inline uint16_t
 swap_byte16(uint16_t x)
 {
 #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<>
+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;
+}
 
 //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>
-        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 bool ByteOrderDiffers = (HostByteOrder != 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 bool ByteOrderDiffers = (HostByteOrder != 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__