summaryrefslogtreecommitdiff
path: root/src/sim/byteswap.hh
diff options
context:
space:
mode:
Diffstat (limited to 'src/sim/byteswap.hh')
-rw-r--r--src/sim/byteswap.hh176
1 files changed, 176 insertions, 0 deletions
diff --git a/src/sim/byteswap.hh b/src/sim/byteswap.hh
new file mode 100644
index 000000000..7648b8fcd
--- /dev/null
+++ b/src/sim/byteswap.hh
@@ -0,0 +1,176 @@
+/*
+ * Copyright (c) 2004 The Regents of The University of Michigan
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met: redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer;
+ * redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution;
+ * neither the name of the copyright holders nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * 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
+//functions. Depending on the endianness of the guest system, either
+//the LittleEndianGuest or BigEndianGuest namespace is used.
+
+#ifndef __SIM_BYTE_SWAP_HH__
+#define __SIM_BYTE_SWAP_HH__
+
+#include "base/misc.hh"
+#include "sim/host.hh"
+
+// This lets us figure out what the byte order of the host system is
+#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>
+#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
+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 |
+ ((uint64_t)(x) & 0xff0000ULL) << 24 |
+ ((uint64_t)(x) & 0xff000000ULL) << 8 |
+ ((uint64_t)(x) & 0xff00000000ULL) >> 8 |
+ ((uint64_t)(x) & 0xff0000000000ULL) >> 24 |
+ ((uint64_t)(x) & 0xff000000000000ULL) >> 40 |
+ ((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ;
+#endif
+}
+
+static 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 |
+ ((uint32_t)(x) & 0xff000000) >> 24);
+#endif
+}
+
+static 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 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
+// direct call to the right swap_byteNN() function.
+template <typename T>
+static 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");
+}
+
+//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);}
+
+//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);}
+#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);}
+}
+
+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);}
+}
+#endif // __SIM_BYTE_SWAP_HH__