byteswap.hh revision 4176:2d52a9751dfc
15390SN/A/* 25390SN/A * Copyright (c) 2004 The Regents of The University of Michigan 35390SN/A * All rights reserved. 45390SN/A * 55390SN/A * Redistribution and use in source and binary forms, with or without 65390SN/A * modification, are permitted provided that the following conditions are 75390SN/A * met: redistributions of source code must retain the above copyright 85390SN/A * notice, this list of conditions and the following disclaimer; 95390SN/A * redistributions in binary form must reproduce the above copyright 105390SN/A * notice, this list of conditions and the following disclaimer in the 115390SN/A * documentation and/or other materials provided with the distribution; 125390SN/A * neither the name of the copyright holders nor the names of its 135390SN/A * contributors may be used to endorse or promote products derived from 145390SN/A * this software without specific prior written permission. 155390SN/A * 165390SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 175390SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 185390SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 195390SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 205390SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 215390SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 225390SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 235390SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 245390SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 255390SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 265390SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 275390SN/A * 285390SN/A * Authors: Gabe Black 295390SN/A * Ali Saidi 305390SN/A * Nathan Binkert 318232Snate@binkert.org */ 325629Sgblack@eecs.umich.edu 335634Sgblack@eecs.umich.edu//The purpose of this file is to provide endainness conversion utility 345390SN/A//functions. Depending on the endianness of the guest system, either 355390SN/A//the LittleEndianGuest or BigEndianGuest namespace is used. 365632Sgblack@eecs.umich.edu 375632Sgblack@eecs.umich.edu#ifndef __SIM_BYTE_SWAP_HH__ 385632Sgblack@eecs.umich.edu#define __SIM_BYTE_SWAP_HH__ 395634Sgblack@eecs.umich.edu 405827Sgblack@eecs.umich.edu#include "base/bigint.hh" 415827Sgblack@eecs.umich.edu#include "base/misc.hh" 425827Sgblack@eecs.umich.edu#include "sim/host.hh" 435632Sgblack@eecs.umich.edu 445632Sgblack@eecs.umich.edu// This lets us figure out what the byte order of the host system is 455390SN/A#if defined(linux) 465390SN/A#include <endian.h> 475390SN/A// If this is a linux system, lets used the optimized definitions if they exist. 485390SN/A// If one doesn't exist, we pretty much get what is listed below, so it all 495629Sgblack@eecs.umich.edu// works out 505390SN/A#include <byteswap.h> 515390SN/A#elif defined (__sun) 525390SN/A#include <sys/isa_defs.h> 535390SN/A#else 545390SN/A#include <machine/endian.h> 555390SN/A#endif 565390SN/A 575390SN/A#if defined(__APPLE__) 585390SN/A#include <libkern/OSByteOrder.h> 595390SN/A#endif 605898Sgblack@eecs.umich.edu 615390SN/Aenum ByteOrder {BigEndianByteOrder, LittleEndianByteOrder}; 625390SN/A 635390SN/A//These functions actually perform the swapping for parameters 645390SN/A//of various bit lengths 655390SN/Astatic inline uint64_t 665390SN/Aswap_byte64(uint64_t x) 675390SN/A{ 685629Sgblack@eecs.umich.edu#if defined(linux) 695390SN/A return bswap_64(x); 705390SN/A#elif defined(__APPLE__) 715390SN/A return OSSwapInt64(x); 725390SN/A#else 735390SN/A return (uint64_t)((((uint64_t)(x) & 0xff) << 56) | 745390SN/A ((uint64_t)(x) & 0xff00ULL) << 40 | 755390SN/A ((uint64_t)(x) & 0xff0000ULL) << 24 | 765390SN/A ((uint64_t)(x) & 0xff000000ULL) << 8 | 775390SN/A ((uint64_t)(x) & 0xff00000000ULL) >> 8 | 785390SN/A ((uint64_t)(x) & 0xff0000000000ULL) >> 24 | 795898Sgblack@eecs.umich.edu ((uint64_t)(x) & 0xff000000000000ULL) >> 40 | 805390SN/A ((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ; 815390SN/A#endif 825390SN/A} 835390SN/A 845390SN/Astatic inline uint32_t 855390SN/Aswap_byte32(uint32_t x) 865390SN/A{ 875629Sgblack@eecs.umich.edu#if defined(linux) 885393SN/A return bswap_32(x); 895629Sgblack@eecs.umich.edu#elif defined(__APPLE__) 905629Sgblack@eecs.umich.edu return OSSwapInt32(x); 917799Sgblack@eecs.umich.edu#else 925393SN/A return (uint32_t)(((uint32_t)(x) & 0xff) << 24 | 935629Sgblack@eecs.umich.edu ((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 | 945629Sgblack@eecs.umich.edu ((uint32_t)(x) & 0xff000000) >> 24); 957799Sgblack@eecs.umich.edu#endif 965390SN/A} 975629Sgblack@eecs.umich.edu 985390SN/Astatic inline uint16_t 995390SN/Aswap_byte16(uint16_t x) 1005390SN/A{ 1015390SN/A#if defined(linux) 1025390SN/A return bswap_16(x); 1035390SN/A#elif defined(__APPLE__) 1045393SN/A return OSSwapInt16(x); 1055629Sgblack@eecs.umich.edu#else 1067799Sgblack@eecs.umich.edu return (uint16_t)(((uint16_t)(x) & 0xff) << 8 | 1075393SN/A ((uint16_t)(x) & 0xff00) >> 8); 1085393SN/A#endif 1095629Sgblack@eecs.umich.edu} 1107799Sgblack@eecs.umich.edu 1115629Sgblack@eecs.umich.edu// This function lets the compiler figure out how to call the 1125390SN/A// swap_byte functions above for different data types. Since the 1135390SN/A// sizeof() values are known at compile time, it should inline to a 1145629Sgblack@eecs.umich.edu// direct call to the right swap_byteNN() function. 1157903Shestness@cs.utexas.edutemplate <typename T> 11610631Scdirik@micron.comstatic inline T swap_byte(T x) { 11710631Scdirik@micron.com if (sizeof(T) == 8) 11810631Scdirik@micron.com return swap_byte64((uint64_t)x); 11910631Scdirik@micron.com else if (sizeof(T) == 4) 12010631Scdirik@micron.com return swap_byte32((uint32_t)x); 12110631Scdirik@micron.com else if (sizeof(T) == 2) 1227903Shestness@cs.utexas.edu return swap_byte16((uint16_t)x); 1237903Shestness@cs.utexas.edu else if (sizeof(T) == 1) 1247903Shestness@cs.utexas.edu return x; 1257903Shestness@cs.utexas.edu else 1267903Shestness@cs.utexas.edu panic("Can't byte-swap values larger than 64 bits"); 1277903Shestness@cs.utexas.edu} 1287903Shestness@cs.utexas.edu 1297903Shestness@cs.utexas.edutemplate<> 1307903Shestness@cs.utexas.edustatic inline Twin64_t swap_byte<Twin64_t>(Twin64_t x) 1317903Shestness@cs.utexas.edu{ 1327903Shestness@cs.utexas.edu x.a = swap_byte(x.a); 1337903Shestness@cs.utexas.edu x.b = swap_byte(x.b); 1347903Shestness@cs.utexas.edu return x; 1357903Shestness@cs.utexas.edu} 1367903Shestness@cs.utexas.edu 1377903Shestness@cs.utexas.edutemplate<> 1387903Shestness@cs.utexas.edustatic inline Twin32_t swap_byte<Twin32_t>(Twin32_t x) 1397903Shestness@cs.utexas.edu{ 1407903Shestness@cs.utexas.edu x.a = swap_byte(x.a); 1415629Sgblack@eecs.umich.edu x.b = swap_byte(x.b); 1425629Sgblack@eecs.umich.edu return x; 1435629Sgblack@eecs.umich.edu} 1445629Sgblack@eecs.umich.edu 1455629Sgblack@eecs.umich.edu//The conversion functions with fixed endianness on both ends don't need to 146//be in a namespace 147template <typename T> static inline T betole(T value) {return swap_byte(value);} 148template <typename T> static inline T letobe(T value) {return swap_byte(value);} 149 150//For conversions not involving the guest system, we can define the functions 151//conditionally based on the BYTE_ORDER macro and outside of the namespaces 152#if defined(_BIG_ENDIAN) || !defined(_LITTLE_ENDIAN) && BYTE_ORDER == BIG_ENDIAN 153const ByteOrder HostByteOrder = BigEndianByteOrder; 154template <typename T> static inline T htole(T value) {return swap_byte(value);} 155template <typename T> static inline T letoh(T value) {return swap_byte(value);} 156template <typename T> static inline T htobe(T value) {return value;} 157template <typename T> static inline T betoh(T value) {return value;} 158#elif defined(_LITTLE_ENDIAN) || BYTE_ORDER == LITTLE_ENDIAN 159const ByteOrder HostByteOrder = LittleEndianByteOrder; 160template <typename T> static inline T htole(T value) {return value;} 161template <typename T> static inline T letoh(T value) {return value;} 162template <typename T> static inline T htobe(T value) {return swap_byte(value);} 163template <typename T> static inline T betoh(T value) {return swap_byte(value);} 164#else 165 #error Invalid Endianess 166#endif 167 168namespace BigEndianGuest 169{ 170 const bool ByteOrderDiffers = (HostByteOrder != BigEndianByteOrder); 171 template <typename T> 172 static inline T gtole(T value) {return betole(value);} 173 template <typename T> 174 static inline T letog(T value) {return letobe(value);} 175 template <typename T> 176 static inline T gtobe(T value) {return value;} 177 template <typename T> 178 static inline T betog(T value) {return value;} 179 template <typename T> 180 static inline T htog(T value) {return htobe(value);} 181 template <typename T> 182 static inline T gtoh(T value) {return betoh(value);} 183} 184 185namespace LittleEndianGuest 186{ 187 const bool ByteOrderDiffers = (HostByteOrder != LittleEndianByteOrder); 188 template <typename T> 189 static inline T gtole(T value) {return value;} 190 template <typename T> 191 static inline T letog(T value) {return value;} 192 template <typename T> 193 static inline T gtobe(T value) {return letobe(value);} 194 template <typename T> 195 static inline T betog(T value) {return betole(value);} 196 template <typename T> 197 static inline T htog(T value) {return htole(value);} 198 template <typename T> 199 static inline T gtoh(T value) {return letoh(value);} 200} 201#endif // __SIM_BYTE_SWAP_HH__ 202