[BACK]Return to elfcpp_swap.h CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / external / gpl3 / binutils.old / dist / elfcpp

Annotation of src/external/gpl3/binutils.old/dist/elfcpp/elfcpp_swap.h, Revision 1.3

1.1       christos    1: // elfcpp_swap.h -- Handle swapping for elfcpp   -*- C++ -*-
                      2:
1.3     ! christos    3: // Copyright (C) 2006-2015 Free Software Foundation, Inc.
1.1       christos    4: // Written by Ian Lance Taylor <iant@google.com>.
                      5:
                      6: // This file is part of elfcpp.
                      7:
                      8: // This program is free software; you can redistribute it and/or
                      9: // modify it under the terms of the GNU Library General Public License
                     10: // as published by the Free Software Foundation; either version 2, or
                     11: // (at your option) any later version.
                     12:
                     13: // In addition to the permissions in the GNU Library General Public
                     14: // License, the Free Software Foundation gives you unlimited
                     15: // permission to link the compiled version of this file into
                     16: // combinations with other programs, and to distribute those
                     17: // combinations without any restriction coming from the use of this
                     18: // file.  (The Library Public License restrictions do apply in other
                     19: // respects; for example, they cover modification of the file, and
                     20: /// distribution when not linked into a combined executable.)
                     21:
                     22: // This program is distributed in the hope that it will be useful, but
                     23: // WITHOUT ANY WARRANTY; without even the implied warranty of
                     24: // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
                     25: // Library General Public License for more details.
                     26:
                     27: // You should have received a copy of the GNU Library General Public
                     28: // License along with this program; if not, write to the Free Software
                     29: // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
                     30: // 02110-1301, USA.
                     31:
                     32: // This header file defines basic template classes to efficiently swap
                     33: // numbers between host form and target form.  When the host and
                     34: // target have the same endianness, these turn into no-ops.
                     35:
                     36: #ifndef ELFCPP_SWAP_H
                     37: #define ELFCPP_SWAP_H
                     38:
                     39: #include <stdint.h>
                     40:
                     41: // We need an autoconf-generated config.h file for endianness and
                     42: // swapping.  We check two macros: WORDS_BIGENDIAN and
                     43: // HAVE_BYTESWAP_H.
                     44:
                     45: #include "config.h"
                     46:
                     47: #ifdef HAVE_BYTESWAP_H
                     48: #include <byteswap.h>
                     49: #else
                     50: // Provide our own versions of the byteswap functions.
                     51: inline uint16_t
                     52: bswap_16(uint16_t v)
                     53: {
                     54:   return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
                     55: }
                     56:
                     57: inline uint32_t
                     58: bswap_32(uint32_t v)
                     59: {
                     60:   return (  ((v & 0xff000000) >> 24)
                     61:          | ((v & 0x00ff0000) >>  8)
                     62:          | ((v & 0x0000ff00) <<  8)
                     63:          | ((v & 0x000000ff) << 24));
                     64: }
                     65:
                     66: inline uint64_t
                     67: bswap_64(uint64_t v)
                     68: {
                     69:   return (  ((v & 0xff00000000000000ULL) >> 56)
                     70:          | ((v & 0x00ff000000000000ULL) >> 40)
                     71:          | ((v & 0x0000ff0000000000ULL) >> 24)
                     72:          | ((v & 0x000000ff00000000ULL) >>  8)
                     73:          | ((v & 0x00000000ff000000ULL) <<  8)
                     74:          | ((v & 0x0000000000ff0000ULL) << 24)
                     75:          | ((v & 0x000000000000ff00ULL) << 40)
                     76:          | ((v & 0x00000000000000ffULL) << 56));
                     77: }
                     78: #endif // !defined(HAVE_BYTESWAP_H)
                     79:
                     80: // gcc 4.3 and later provides __builtin_bswap32 and __builtin_bswap64.
                     81:
                     82: #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
                     83: #undef bswap_32
                     84: #define bswap_32 __builtin_bswap32
                     85: #undef bswap_64
                     86: #define bswap_64 __builtin_bswap64
                     87: #endif
                     88:
                     89: namespace elfcpp
                     90: {
                     91:
                     92: // Endian simply indicates whether the host is big endian or not.
                     93:
                     94: struct Endian
                     95: {
                     96:  public:
                     97:   // Used for template specializations.
                     98:   static const bool host_big_endian =
                     99: #ifdef WORDS_BIGENDIAN
                    100:     true
                    101: #else
                    102:     false
                    103: #endif
                    104:     ;
                    105: };
                    106:
                    107: // Valtype_base is a template based on size (8, 16, 32, 64) which
                    108: // defines the type Valtype as the unsigned integer, and
                    109: // Signed_valtype as the signed integer, of the specified size.
                    110:
                    111: template<int size>
                    112: struct Valtype_base;
                    113:
                    114: template<>
                    115: struct Valtype_base<8>
                    116: {
                    117:   typedef uint8_t Valtype;
                    118:   typedef int8_t Signed_valtype;
                    119: };
                    120:
                    121: template<>
                    122: struct Valtype_base<16>
                    123: {
                    124:   typedef uint16_t Valtype;
                    125:   typedef int16_t Signed_valtype;
                    126: };
                    127:
                    128: template<>
                    129: struct Valtype_base<32>
                    130: {
                    131:   typedef uint32_t Valtype;
                    132:   typedef int32_t Signed_valtype;
                    133: };
                    134:
                    135: template<>
                    136: struct Valtype_base<64>
                    137: {
                    138:   typedef uint64_t Valtype;
                    139:   typedef int64_t Signed_valtype;
                    140: };
                    141:
                    142: // Convert_endian is a template based on size and on whether the host
                    143: // and target have the same endianness.  It defines the type Valtype
                    144: // as Valtype_base does, and also defines a function convert_host
                    145: // which takes an argument of type Valtype and returns the same value,
                    146: // but swapped if the host and target have different endianness.
                    147:
                    148: template<int size, bool same_endian>
                    149: struct Convert_endian;
                    150:
                    151: template<int size>
                    152: struct Convert_endian<size, true>
                    153: {
                    154:   typedef typename Valtype_base<size>::Valtype Valtype;
                    155:
                    156:   static inline Valtype
                    157:   convert_host(Valtype v)
                    158:   { return v; }
                    159: };
                    160:
                    161: template<>
                    162: struct Convert_endian<8, false>
                    163: {
                    164:   typedef Valtype_base<8>::Valtype Valtype;
                    165:
                    166:   static inline Valtype
                    167:   convert_host(Valtype v)
                    168:   { return v; }
                    169: };
                    170:
                    171: template<>
                    172: struct Convert_endian<16, false>
                    173: {
                    174:   typedef Valtype_base<16>::Valtype Valtype;
                    175:
                    176:   static inline Valtype
                    177:   convert_host(Valtype v)
                    178:   { return bswap_16(v); }
                    179: };
                    180:
                    181: template<>
                    182: struct Convert_endian<32, false>
                    183: {
                    184:   typedef Valtype_base<32>::Valtype Valtype;
                    185:
                    186:   static inline Valtype
                    187:   convert_host(Valtype v)
                    188:   { return bswap_32(v); }
                    189: };
                    190:
                    191: template<>
                    192: struct Convert_endian<64, false>
                    193: {
                    194:   typedef Valtype_base<64>::Valtype Valtype;
                    195:
                    196:   static inline Valtype
                    197:   convert_host(Valtype v)
                    198:   { return bswap_64(v); }
                    199: };
                    200:
                    201: // Convert is a template based on size and on whether the target is
                    202: // big endian.  It defines Valtype and convert_host like
                    203: // Convert_endian.  That is, it is just like Convert_endian except in
                    204: // the meaning of the second template parameter.
                    205:
                    206: template<int size, bool big_endian>
                    207: struct Convert
                    208: {
                    209:   typedef typename Valtype_base<size>::Valtype Valtype;
                    210:
                    211:   static inline Valtype
                    212:   convert_host(Valtype v)
                    213:   {
                    214:     return Convert_endian<size, big_endian == Endian::host_big_endian>
                    215:       ::convert_host(v);
                    216:   }
                    217: };
                    218:
                    219: // Swap is a template based on size and on whether the target is big
                    220: // endian.  It defines the type Valtype and the functions readval and
                    221: // writeval.  The functions read and write values of the appropriate
                    222: // size out of buffers, swapping them if necessary.  readval and
                    223: // writeval are overloaded to take pointers to the appropriate type or
                    224: // pointers to unsigned char.
                    225:
                    226: template<int size, bool big_endian>
                    227: struct Swap
                    228: {
                    229:   typedef typename Valtype_base<size>::Valtype Valtype;
                    230:
                    231:   static inline Valtype
                    232:   readval(const Valtype* wv)
                    233:   { return Convert<size, big_endian>::convert_host(*wv); }
                    234:
                    235:   static inline void
                    236:   writeval(Valtype* wv, Valtype v)
                    237:   { *wv = Convert<size, big_endian>::convert_host(v); }
                    238:
                    239:   static inline Valtype
                    240:   readval(const unsigned char* wv)
                    241:   { return readval(reinterpret_cast<const Valtype*>(wv)); }
                    242:
                    243:   static inline void
                    244:   writeval(unsigned char* wv, Valtype v)
                    245:   { writeval(reinterpret_cast<Valtype*>(wv), v); }
                    246: };
                    247:
                    248: // We need to specialize the 8-bit version of Swap to avoid
                    249: // conflicting overloads, since both versions of readval and writeval
                    250: // will have the same type parameters.
                    251:
                    252: template<bool big_endian>
                    253: struct Swap<8, big_endian>
                    254: {
                    255:   typedef typename Valtype_base<8>::Valtype Valtype;
                    256:
                    257:   static inline Valtype
                    258:   readval(const Valtype* wv)
                    259:   { return *wv; }
                    260:
                    261:   static inline void
                    262:   writeval(Valtype* wv, Valtype v)
                    263:   { *wv = v; }
                    264: };
                    265:
                    266: // Swap_unaligned is a template based on size and on whether the
                    267: // target is big endian.  It defines the type Valtype and the
                    268: // functions readval and writeval.  The functions read and write
                    269: // values of the appropriate size out of buffers which may be
                    270: // misaligned.
                    271:
                    272: template<int size, bool big_endian>
                    273: struct Swap_unaligned;
                    274:
                    275: template<bool big_endian>
                    276: struct Swap_unaligned<8, big_endian>
                    277: {
                    278:   typedef typename Valtype_base<8>::Valtype Valtype;
                    279:
                    280:   static inline Valtype
                    281:   readval(const unsigned char* wv)
                    282:   { return *wv; }
                    283:
                    284:   static inline void
                    285:   writeval(unsigned char* wv, Valtype v)
                    286:   { *wv = v; }
                    287: };
                    288:
                    289: template<>
                    290: struct Swap_unaligned<16, false>
                    291: {
                    292:   typedef Valtype_base<16>::Valtype Valtype;
                    293:
                    294:   static inline Valtype
                    295:   readval(const unsigned char* wv)
                    296:   {
                    297:     return (wv[1] << 8) | wv[0];
                    298:   }
                    299:
                    300:   static inline void
                    301:   writeval(unsigned char* wv, Valtype v)
                    302:   {
                    303:     wv[1] = v >> 8;
                    304:     wv[0] = v;
                    305:   }
                    306: };
                    307:
                    308: template<>
                    309: struct Swap_unaligned<16, true>
                    310: {
                    311:   typedef Valtype_base<16>::Valtype Valtype;
                    312:
                    313:   static inline Valtype
                    314:   readval(const unsigned char* wv)
                    315:   {
                    316:     return (wv[0] << 8) | wv[1];
                    317:   }
                    318:
                    319:   static inline void
                    320:   writeval(unsigned char* wv, Valtype v)
                    321:   {
                    322:     wv[0] = v >> 8;
                    323:     wv[1] = v;
                    324:   }
                    325: };
                    326:
                    327: template<>
                    328: struct Swap_unaligned<32, false>
                    329: {
                    330:   typedef Valtype_base<32>::Valtype Valtype;
                    331:
                    332:   static inline Valtype
                    333:   readval(const unsigned char* wv)
                    334:   {
                    335:     return (wv[3] << 24) | (wv[2] << 16) | (wv[1] << 8) | wv[0];
                    336:   }
                    337:
                    338:   static inline void
                    339:   writeval(unsigned char* wv, Valtype v)
                    340:   {
                    341:     wv[3] = v >> 24;
                    342:     wv[2] = v >> 16;
                    343:     wv[1] = v >> 8;
                    344:     wv[0] = v;
                    345:   }
                    346: };
                    347:
                    348: template<>
                    349: struct Swap_unaligned<32, true>
                    350: {
                    351:   typedef Valtype_base<32>::Valtype Valtype;
                    352:
                    353:   static inline Valtype
                    354:   readval(const unsigned char* wv)
                    355:   {
                    356:     return (wv[0] << 24) | (wv[1] << 16) | (wv[2] << 8) | wv[3];
                    357:   }
                    358:
                    359:   static inline void
                    360:   writeval(unsigned char* wv, Valtype v)
                    361:   {
                    362:     wv[0] = v >> 24;
                    363:     wv[1] = v >> 16;
                    364:     wv[2] = v >> 8;
                    365:     wv[3] = v;
                    366:   }
                    367: };
                    368:
                    369: template<>
                    370: struct Swap_unaligned<64, false>
                    371: {
                    372:   typedef Valtype_base<64>::Valtype Valtype;
                    373:
                    374:   static inline Valtype
                    375:   readval(const unsigned char* wv)
                    376:   {
                    377:     return ((static_cast<Valtype>(wv[7]) << 56)
                    378:            | (static_cast<Valtype>(wv[6]) << 48)
                    379:            | (static_cast<Valtype>(wv[5]) << 40)
                    380:            | (static_cast<Valtype>(wv[4]) << 32)
                    381:            | (static_cast<Valtype>(wv[3]) << 24)
                    382:            | (static_cast<Valtype>(wv[2]) << 16)
                    383:            | (static_cast<Valtype>(wv[1]) << 8)
                    384:            | static_cast<Valtype>(wv[0]));
                    385:   }
                    386:
                    387:   static inline void
                    388:   writeval(unsigned char* wv, Valtype v)
                    389:   {
                    390:     wv[7] = v >> 56;
                    391:     wv[6] = v >> 48;
                    392:     wv[5] = v >> 40;
                    393:     wv[4] = v >> 32;
                    394:     wv[3] = v >> 24;
                    395:     wv[2] = v >> 16;
                    396:     wv[1] = v >> 8;
                    397:     wv[0] = v;
                    398:   }
                    399: };
                    400:
                    401: template<>
                    402: struct Swap_unaligned<64, true>
                    403: {
                    404:   typedef Valtype_base<64>::Valtype Valtype;
                    405:
                    406:   static inline Valtype
                    407:   readval(const unsigned char* wv)
                    408:   {
                    409:     return ((static_cast<Valtype>(wv[0]) << 56)
                    410:            | (static_cast<Valtype>(wv[1]) << 48)
                    411:            | (static_cast<Valtype>(wv[2]) << 40)
                    412:            | (static_cast<Valtype>(wv[3]) << 32)
                    413:            | (static_cast<Valtype>(wv[4]) << 24)
                    414:            | (static_cast<Valtype>(wv[5]) << 16)
                    415:            | (static_cast<Valtype>(wv[6]) << 8)
                    416:            | static_cast<Valtype>(wv[7]));
                    417:   }
                    418:
                    419:   static inline void
                    420:   writeval(unsigned char* wv, Valtype v)
                    421:   {
                    422:     wv[0] = v >> 56;
                    423:     wv[1] = v >> 48;
                    424:     wv[2] = v >> 40;
                    425:     wv[3] = v >> 32;
                    426:     wv[4] = v >> 24;
                    427:     wv[5] = v >> 16;
                    428:     wv[6] = v >> 8;
                    429:     wv[7] = v;
                    430:   }
                    431: };
                    432:
                    433: // Swap_aligned32 is a template based on size and on whether the
                    434: // target is big endian.  It defines the type Valtype and the
                    435: // functions readval and writeval.  The functions read and write
                    436: // values of the appropriate size out of buffers which may not be
                    437: // 64-bit aligned, but are 32-bit aligned.
                    438:
                    439: template<int size, bool big_endian>
                    440: struct Swap_aligned32
                    441: {
                    442:   typedef typename Valtype_base<size>::Valtype Valtype;
                    443:
                    444:   static inline Valtype
                    445:   readval(const unsigned char* wv)
                    446:   { return Swap<size, big_endian>::readval(
                    447:        reinterpret_cast<const Valtype*>(wv)); }
                    448:
                    449:   static inline void
                    450:   writeval(unsigned char* wv, Valtype v)
                    451:   { Swap<size, big_endian>::writeval(reinterpret_cast<Valtype*>(wv), v); }
                    452: };
                    453:
                    454: template<>
                    455: struct Swap_aligned32<64, true>
                    456: {
                    457:   typedef Valtype_base<64>::Valtype Valtype;
                    458:
                    459:   static inline Valtype
                    460:   readval(const unsigned char* wv)
                    461:   {
                    462:     return ((static_cast<Valtype>(Swap<32, true>::readval(wv)) << 32)
                    463:            | static_cast<Valtype>(Swap<32, true>::readval(wv + 4)));
                    464:   }
                    465:
                    466:   static inline void
                    467:   writeval(unsigned char* wv, Valtype v)
                    468:   {
                    469:     typedef Valtype_base<32>::Valtype Valtype32;
                    470:
                    471:     Swap<32, true>::writeval(wv, static_cast<Valtype32>(v >> 32));
                    472:     Swap<32, true>::writeval(wv + 4, static_cast<Valtype32>(v));
                    473:   }
                    474: };
                    475:
                    476: template<>
                    477: struct Swap_aligned32<64, false>
                    478: {
                    479:   typedef Valtype_base<64>::Valtype Valtype;
                    480:
                    481:   static inline Valtype
                    482:   readval(const unsigned char* wv)
                    483:   {
                    484:     return ((static_cast<Valtype>(Swap<32, false>::readval(wv + 4)) << 32)
                    485:            | static_cast<Valtype>(Swap<32, false>::readval(wv)));
                    486:   }
                    487:
                    488:   static inline void
                    489:   writeval(unsigned char* wv, Valtype v)
                    490:   {
                    491:     typedef Valtype_base<32>::Valtype Valtype32;
                    492:
                    493:     Swap<32, false>::writeval(wv + 4, static_cast<Valtype32>(v >> 32));
                    494:     Swap<32, false>::writeval(wv, static_cast<Valtype32>(v));
                    495:   }
                    496: };
                    497:
                    498: } // End namespace elfcpp.
                    499:
                    500: #endif // !defined(ELFCPP_SWAP_H)

CVSweb <webmaster@jp.NetBSD.org>