byteswap.hh revision 3483
12330SN/A/*
22330SN/A * Copyright (c) 2004 The Regents of The University of Michigan
32330SN/A * All rights reserved.
42330SN/A *
52330SN/A * Redistribution and use in source and binary forms, with or without
62330SN/A * modification, are permitted provided that the following conditions are
72330SN/A * met: redistributions of source code must retain the above copyright
82330SN/A * notice, this list of conditions and the following disclaimer;
92330SN/A * redistributions in binary form must reproduce the above copyright
102330SN/A * notice, this list of conditions and the following disclaimer in the
112330SN/A * documentation and/or other materials provided with the distribution;
122330SN/A * neither the name of the copyright holders nor the names of its
132330SN/A * contributors may be used to endorse or promote products derived from
142330SN/A * this software without specific prior written permission.
152330SN/A *
162330SN/A * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
172330SN/A * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
182330SN/A * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
192330SN/A * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
202330SN/A * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
212330SN/A * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
222330SN/A * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
232330SN/A * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
242330SN/A * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
252330SN/A * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
262330SN/A * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
272689Sktlim@umich.edu *
282689Sktlim@umich.edu * Authors: Gabe Black
292330SN/A *          Ali Saidi
302292SN/A *          Nathan Binkert
312292SN/A */
322292SN/A
332292SN/A//The purpose of this file is to provide endainness conversion utility
342980Sgblack@eecs.umich.edu//functions. Depending on the endianness of the guest system, either
356658Snate@binkert.org//the LittleEndianGuest or BigEndianGuest namespace is used.
362362SN/A
372680Sktlim@umich.edu#ifndef __SIM_BYTE_SWAP_HH__
385712Shsul@eecs.umich.edu#define __SIM_BYTE_SWAP_HH__
392292SN/A
402678Sktlim@umich.edu#include "base/misc.hh"
412683Sktlim@umich.edu#include "sim/host.hh"
422683Sktlim@umich.edu
432678Sktlim@umich.edu// This lets us figure out what the byte order of the host system is
442678Sktlim@umich.edu#if defined(linux)
452292SN/A#include <endian.h>
462292SN/A// If this is a linux system, lets used the optimized definitions if they exist.
472292SN/A// If one doesn't exist, we pretty much get what is listed below, so it all
482292SN/A// works out
493548Sgblack@eecs.umich.edu#include <byteswap.h>
503548Sgblack@eecs.umich.edu#elif defined (__sun__)
513548Sgblack@eecs.umich.edu#include <sys/isa_defs.h>
523548Sgblack@eecs.umich.edu#else
532330SN/A#include <machine/endian.h>
542292SN/A#endif
552292SN/A
562862Sktlim@umich.edu#if defined(__APPLE__)
573486Sktlim@umich.edu#include <libkern/OSByteOrder.h>
583402Sktlim@umich.edu#endif
592862Sktlim@umich.edu
602330SN/A//These functions actually perform the swapping for parameters
612330SN/A//of various bit lengths
622330SN/Astatic inline uint64_t
632330SN/Aswap_byte64(uint64_t x)
642330SN/A{
652330SN/A#if defined(linux)
662292SN/A    return bswap_64(x);
672683Sktlim@umich.edu#elif defined(__APPLE__)
682683Sktlim@umich.edu    return OSSwapInt64(x);
692292SN/A#else
706221Snate@binkert.org    return  (uint64_t)((((uint64_t)(x) & 0xff) << 56) |
712292SN/A            ((uint64_t)(x) & 0xff00ULL) << 40 |
726331Sgblack@eecs.umich.edu            ((uint64_t)(x) & 0xff0000ULL) << 24 |
732292SN/A            ((uint64_t)(x) & 0xff000000ULL) << 8 |
742683Sktlim@umich.edu            ((uint64_t)(x) & 0xff00000000ULL) >> 8 |
753486Sktlim@umich.edu            ((uint64_t)(x) & 0xff0000000000ULL) >> 24 |
763486Sktlim@umich.edu            ((uint64_t)(x) & 0xff000000000000ULL) >> 40 |
772862Sktlim@umich.edu            ((uint64_t)(x) & 0xff00000000000000ULL) >> 56) ;
782862Sktlim@umich.edu#endif
792862Sktlim@umich.edu}
802862Sktlim@umich.edu
815712Shsul@eecs.umich.edustatic inline uint32_t
822683Sktlim@umich.eduswap_byte32(uint32_t x)
835714Shsul@eecs.umich.edu{
845714Shsul@eecs.umich.edu#if defined(linux)
855714Shsul@eecs.umich.edu    return bswap_32(x);
865714Shsul@eecs.umich.edu#elif defined(__APPLE__)
876221Snate@binkert.org    return OSSwapInt32(x);
882683Sktlim@umich.edu#else
896221Snate@binkert.org    return  (uint32_t)(((uint32_t)(x) & 0xff) << 24 |
902683Sktlim@umich.edu            ((uint32_t)(x) & 0xff00) << 8 | ((uint32_t)(x) & 0xff0000) >> 8 |
912683Sktlim@umich.edu            ((uint32_t)(x) & 0xff000000) >> 24);
922683Sktlim@umich.edu#endif
932683Sktlim@umich.edu}
942683Sktlim@umich.edu
952683Sktlim@umich.edustatic inline uint16_t
965497Ssaidi@eecs.umich.eduswap_byte16(uint16_t x)
973675Sktlim@umich.edu{
983686Sktlim@umich.edu#if defined(linux)
993675Sktlim@umich.edu    return bswap_16(x);
1005497Ssaidi@eecs.umich.edu#elif defined(__APPLE__)
1013675Sktlim@umich.edu    return OSSwapInt16(x);
1022683Sktlim@umich.edu#else
1032683Sktlim@umich.edu    return (uint16_t)(((uint16_t)(x) & 0xff) << 8 |
1042683Sktlim@umich.edu                      ((uint16_t)(x) & 0xff00) >> 8);
1052683Sktlim@umich.edu#endif
1062683Sktlim@umich.edu}
1072683Sktlim@umich.edu
1082683Sktlim@umich.edu// This function lets the compiler figure out how to call the
1092683Sktlim@umich.edu// swap_byte functions above for different data types.  Since the
1103548Sgblack@eecs.umich.edu// sizeof() values are known at compiel time, it should inline to a
1112683Sktlim@umich.edu// direct call to the right swap_byteNN() function.
1122690Sktlim@umich.edutemplate <typename T>
1132690Sktlim@umich.edustatic inline T swap_byte(T x) {
1142683Sktlim@umich.edu    if (sizeof(T) == 8)
1152683Sktlim@umich.edu        return swap_byte64((uint64_t)x);
1165499Ssaidi@eecs.umich.edu    else if (sizeof(T) == 4)
1172683Sktlim@umich.edu        return swap_byte32((uint32_t)x);
1182683Sktlim@umich.edu    else if (sizeof(T) == 2)
1192683Sktlim@umich.edu        return swap_byte16((uint16_t)x);
1203402Sktlim@umich.edu    else if (sizeof(T) == 1)
1212683Sktlim@umich.edu        return x;
1222683Sktlim@umich.edu    else
1232678Sktlim@umich.edu        panic("Can't byte-swap values larger than 64 bits");
1242292SN/A}
1252683Sktlim@umich.edu
1262683Sktlim@umich.edu//The conversion functions with fixed endianness on both ends don't need to
1272292SN/A//be in a namespace
1282683Sktlim@umich.edutemplate <typename T> static inline T betole(T value) {return swap_byte(value);}
1292683Sktlim@umich.edutemplate <typename T> static inline T letobe(T value) {return swap_byte(value);}
1302683Sktlim@umich.edu
1312683Sktlim@umich.edu//For conversions not involving the guest system, we can define the functions
1322683Sktlim@umich.edu//conditionally based on the BYTE_ORDER macro and outside of the namespaces
1332683Sktlim@umich.edu#if defined(_BIG_ENDIAN) || BYTE_ORDER == BIG_ENDIAN
1342683Sktlim@umich.edutemplate <typename T> static inline T htole(T value) {return swap_byte(value);}
1352683Sktlim@umich.edutemplate <typename T> static inline T letoh(T value) {return swap_byte(value);}
1362683Sktlim@umich.edutemplate <typename T> static inline T htobe(T value) {return value;}
1372683Sktlim@umich.edutemplate <typename T> static inline T betoh(T value) {return value;}
1382683Sktlim@umich.edu#elif defined(_LITTLE_ENDIAN) || BYTE_ORDER == LITTLE_ENDIAN
1392683Sktlim@umich.edutemplate <typename T> static inline T htole(T value) {return value;}
1402683Sktlim@umich.edutemplate <typename T> static inline T letoh(T value) {return value;}
1412683Sktlim@umich.edutemplate <typename T> static inline T htobe(T value) {return swap_byte(value);}
1422683Sktlim@umich.edutemplate <typename T> static inline T betoh(T value) {return swap_byte(value);}
1432683Sktlim@umich.edu#else
1442683Sktlim@umich.edu        #error Invalid Endianess
1452683Sktlim@umich.edu#endif
1462683Sktlim@umich.edu
1473673Srdreslin@umich.edunamespace BigEndianGuest
1483675Sktlim@umich.edu{
1493675Sktlim@umich.edu        template <typename T>
1503675Sktlim@umich.edu        static inline T gtole(T value) {return betole(value);}
1513486Sktlim@umich.edu        template <typename T>
1522683Sktlim@umich.edu        static inline T letog(T value) {return letobe(value);}
1532683Sktlim@umich.edu        template <typename T>
1542683Sktlim@umich.edu        static inline T gtobe(T value) {return value;}
1555999Snate@binkert.org        template <typename T>
1562683Sktlim@umich.edu        static inline T betog(T value) {return value;}
1575999Snate@binkert.org        template <typename T>
1582683Sktlim@umich.edu        static inline T htog(T value) {return htobe(value);}
1592683Sktlim@umich.edu        template <typename T>
1602683Sktlim@umich.edu        static inline T gtoh(T value) {return betoh(value);}
1612683Sktlim@umich.edu}
1622683Sktlim@umich.edu
1632683Sktlim@umich.edunamespace LittleEndianGuest
1642683Sktlim@umich.edu{
1652683Sktlim@umich.edu        template <typename T>
1662683Sktlim@umich.edu        static inline T gtole(T value) {return value;}
1672683Sktlim@umich.edu        template <typename T>
1682683Sktlim@umich.edu        static inline T letog(T value) {return value;}
1692683Sktlim@umich.edu        template <typename T>
1703402Sktlim@umich.edu        static inline T gtobe(T value) {return letobe(value);}
1713402Sktlim@umich.edu        template <typename T>
1723402Sktlim@umich.edu        static inline T betog(T value) {return betole(value);}
1735714Shsul@eecs.umich.edu        template <typename T>
1745714Shsul@eecs.umich.edu        static inline T htog(T value) {return htole(value);}
1755714Shsul@eecs.umich.edu        template <typename T>
1762292SN/A        static inline T gtoh(T value) {return letoh(value);}
1776221Snate@binkert.org}
1782292SN/A#endif // __SIM_BYTE_SWAP_HH__
1792690Sktlim@umich.edu