175fd0b74Schristos // elfcpp_swap.h -- Handle swapping for elfcpp -*- C++ -*-
275fd0b74Schristos
3*e992f068Schristos // Copyright (C) 2006-2022 Free Software Foundation, Inc.
475fd0b74Schristos // Written by Ian Lance Taylor <iant@google.com>.
575fd0b74Schristos
675fd0b74Schristos // This file is part of elfcpp.
775fd0b74Schristos
875fd0b74Schristos // This program is free software; you can redistribute it and/or
975fd0b74Schristos // modify it under the terms of the GNU Library General Public License
1075fd0b74Schristos // as published by the Free Software Foundation; either version 2, or
1175fd0b74Schristos // (at your option) any later version.
1275fd0b74Schristos
1375fd0b74Schristos // In addition to the permissions in the GNU Library General Public
1475fd0b74Schristos // License, the Free Software Foundation gives you unlimited
1575fd0b74Schristos // permission to link the compiled version of this file into
1675fd0b74Schristos // combinations with other programs, and to distribute those
1775fd0b74Schristos // combinations without any restriction coming from the use of this
1875fd0b74Schristos // file. (The Library Public License restrictions do apply in other
1975fd0b74Schristos // respects; for example, they cover modification of the file, and
2075fd0b74Schristos /// distribution when not linked into a combined executable.)
2175fd0b74Schristos
2275fd0b74Schristos // This program is distributed in the hope that it will be useful, but
2375fd0b74Schristos // WITHOUT ANY WARRANTY; without even the implied warranty of
2475fd0b74Schristos // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
2575fd0b74Schristos // Library General Public License for more details.
2675fd0b74Schristos
2775fd0b74Schristos // You should have received a copy of the GNU Library General Public
2875fd0b74Schristos // License along with this program; if not, write to the Free Software
2975fd0b74Schristos // Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston, MA
3075fd0b74Schristos // 02110-1301, USA.
3175fd0b74Schristos
3275fd0b74Schristos // This header file defines basic template classes to efficiently swap
3375fd0b74Schristos // numbers between host form and target form. When the host and
3475fd0b74Schristos // target have the same endianness, these turn into no-ops.
3575fd0b74Schristos
3675fd0b74Schristos #ifndef ELFCPP_SWAP_H
3775fd0b74Schristos #define ELFCPP_SWAP_H
3875fd0b74Schristos
3975fd0b74Schristos #include <stdint.h>
4075fd0b74Schristos
4175fd0b74Schristos // We need an autoconf-generated config.h file for endianness and
4275fd0b74Schristos // swapping. We check two macros: WORDS_BIGENDIAN and
4375fd0b74Schristos // HAVE_BYTESWAP_H.
4475fd0b74Schristos
4575fd0b74Schristos #include "config.h"
4675fd0b74Schristos
4775fd0b74Schristos #ifdef HAVE_BYTESWAP_H
4875fd0b74Schristos #include <byteswap.h>
49*e992f068Schristos #endif // defined(HAVE_BYTESWAP_H)
50*e992f068Schristos
5175fd0b74Schristos // Provide our own versions of the byteswap functions.
52*e992f068Schristos #if !HAVE_DECL_BSWAP_16
53*e992f068Schristos static inline uint16_t
bswap_16(uint16_t v)5475fd0b74Schristos bswap_16(uint16_t v)
5575fd0b74Schristos {
5675fd0b74Schristos return ((v >> 8) & 0xff) | ((v & 0xff) << 8);
5775fd0b74Schristos }
58*e992f068Schristos #endif // !HAVE_DECL_BSWAP16
5975fd0b74Schristos
60*e992f068Schristos #if !HAVE_DECL_BSWAP_32
61*e992f068Schristos static inline uint32_t
bswap_32(uint32_t v)6275fd0b74Schristos bswap_32(uint32_t v)
6375fd0b74Schristos {
6475fd0b74Schristos return ( ((v & 0xff000000) >> 24)
6575fd0b74Schristos | ((v & 0x00ff0000) >> 8)
6675fd0b74Schristos | ((v & 0x0000ff00) << 8)
6775fd0b74Schristos | ((v & 0x000000ff) << 24));
6875fd0b74Schristos }
69*e992f068Schristos #endif // !HAVE_DECL_BSWAP32
7075fd0b74Schristos
71*e992f068Schristos #if !HAVE_DECL_BSWAP_64
72*e992f068Schristos static inline uint64_t
bswap_64(uint64_t v)7375fd0b74Schristos bswap_64(uint64_t v)
7475fd0b74Schristos {
7575fd0b74Schristos return ( ((v & 0xff00000000000000ULL) >> 56)
7675fd0b74Schristos | ((v & 0x00ff000000000000ULL) >> 40)
7775fd0b74Schristos | ((v & 0x0000ff0000000000ULL) >> 24)
7875fd0b74Schristos | ((v & 0x000000ff00000000ULL) >> 8)
7975fd0b74Schristos | ((v & 0x00000000ff000000ULL) << 8)
8075fd0b74Schristos | ((v & 0x0000000000ff0000ULL) << 24)
8175fd0b74Schristos | ((v & 0x000000000000ff00ULL) << 40)
8275fd0b74Schristos | ((v & 0x00000000000000ffULL) << 56));
8375fd0b74Schristos }
84*e992f068Schristos #endif // !HAVE_DECL_BSWAP64
8575fd0b74Schristos
8675fd0b74Schristos // gcc 4.3 and later provides __builtin_bswap32 and __builtin_bswap64.
8775fd0b74Schristos
8875fd0b74Schristos #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 3))
8975fd0b74Schristos #undef bswap_32
9075fd0b74Schristos #define bswap_32 __builtin_bswap32
9175fd0b74Schristos #undef bswap_64
9275fd0b74Schristos #define bswap_64 __builtin_bswap64
9375fd0b74Schristos #endif
9475fd0b74Schristos
9575fd0b74Schristos namespace elfcpp
9675fd0b74Schristos {
9775fd0b74Schristos
9875fd0b74Schristos // Endian simply indicates whether the host is big endian or not.
9975fd0b74Schristos
10075fd0b74Schristos struct Endian
10175fd0b74Schristos {
10275fd0b74Schristos public:
10375fd0b74Schristos // Used for template specializations.
10475fd0b74Schristos static const bool host_big_endian =
10575fd0b74Schristos #ifdef WORDS_BIGENDIAN
10675fd0b74Schristos true
10775fd0b74Schristos #else
10875fd0b74Schristos false
10975fd0b74Schristos #endif
11075fd0b74Schristos ;
11175fd0b74Schristos };
11275fd0b74Schristos
11375fd0b74Schristos // Valtype_base is a template based on size (8, 16, 32, 64) which
11475fd0b74Schristos // defines the type Valtype as the unsigned integer, and
11575fd0b74Schristos // Signed_valtype as the signed integer, of the specified size.
11675fd0b74Schristos
11775fd0b74Schristos template<int size>
11875fd0b74Schristos struct Valtype_base;
11975fd0b74Schristos
12075fd0b74Schristos template<>
12175fd0b74Schristos struct Valtype_base<8>
12275fd0b74Schristos {
12375fd0b74Schristos typedef uint8_t Valtype;
12475fd0b74Schristos typedef int8_t Signed_valtype;
12575fd0b74Schristos };
12675fd0b74Schristos
12775fd0b74Schristos template<>
12875fd0b74Schristos struct Valtype_base<16>
12975fd0b74Schristos {
13075fd0b74Schristos typedef uint16_t Valtype;
13175fd0b74Schristos typedef int16_t Signed_valtype;
13275fd0b74Schristos };
13375fd0b74Schristos
13475fd0b74Schristos template<>
13575fd0b74Schristos struct Valtype_base<32>
13675fd0b74Schristos {
13775fd0b74Schristos typedef uint32_t Valtype;
13875fd0b74Schristos typedef int32_t Signed_valtype;
13975fd0b74Schristos };
14075fd0b74Schristos
14175fd0b74Schristos template<>
14275fd0b74Schristos struct Valtype_base<64>
14375fd0b74Schristos {
14475fd0b74Schristos typedef uint64_t Valtype;
14575fd0b74Schristos typedef int64_t Signed_valtype;
14675fd0b74Schristos };
14775fd0b74Schristos
14875fd0b74Schristos // Convert_endian is a template based on size and on whether the host
14975fd0b74Schristos // and target have the same endianness. It defines the type Valtype
15075fd0b74Schristos // as Valtype_base does, and also defines a function convert_host
15175fd0b74Schristos // which takes an argument of type Valtype and returns the same value,
15275fd0b74Schristos // but swapped if the host and target have different endianness.
15375fd0b74Schristos
15475fd0b74Schristos template<int size, bool same_endian>
15575fd0b74Schristos struct Convert_endian;
15675fd0b74Schristos
15775fd0b74Schristos template<int size>
15875fd0b74Schristos struct Convert_endian<size, true>
15975fd0b74Schristos {
16075fd0b74Schristos typedef typename Valtype_base<size>::Valtype Valtype;
16175fd0b74Schristos
16275fd0b74Schristos static inline Valtype
16375fd0b74Schristos convert_host(Valtype v)
16475fd0b74Schristos { return v; }
16575fd0b74Schristos };
16675fd0b74Schristos
16775fd0b74Schristos template<>
16875fd0b74Schristos struct Convert_endian<8, false>
16975fd0b74Schristos {
17075fd0b74Schristos typedef Valtype_base<8>::Valtype Valtype;
17175fd0b74Schristos
17275fd0b74Schristos static inline Valtype
17375fd0b74Schristos convert_host(Valtype v)
17475fd0b74Schristos { return v; }
17575fd0b74Schristos };
17675fd0b74Schristos
17775fd0b74Schristos template<>
17875fd0b74Schristos struct Convert_endian<16, false>
17975fd0b74Schristos {
18075fd0b74Schristos typedef Valtype_base<16>::Valtype Valtype;
18175fd0b74Schristos
18275fd0b74Schristos static inline Valtype
18375fd0b74Schristos convert_host(Valtype v)
18475fd0b74Schristos { return bswap_16(v); }
18575fd0b74Schristos };
18675fd0b74Schristos
18775fd0b74Schristos template<>
18875fd0b74Schristos struct Convert_endian<32, false>
18975fd0b74Schristos {
19075fd0b74Schristos typedef Valtype_base<32>::Valtype Valtype;
19175fd0b74Schristos
19275fd0b74Schristos static inline Valtype
19375fd0b74Schristos convert_host(Valtype v)
19475fd0b74Schristos { return bswap_32(v); }
19575fd0b74Schristos };
19675fd0b74Schristos
19775fd0b74Schristos template<>
19875fd0b74Schristos struct Convert_endian<64, false>
19975fd0b74Schristos {
20075fd0b74Schristos typedef Valtype_base<64>::Valtype Valtype;
20175fd0b74Schristos
20275fd0b74Schristos static inline Valtype
20375fd0b74Schristos convert_host(Valtype v)
20475fd0b74Schristos { return bswap_64(v); }
20575fd0b74Schristos };
20675fd0b74Schristos
20775fd0b74Schristos // Convert is a template based on size and on whether the target is
20875fd0b74Schristos // big endian. It defines Valtype and convert_host like
20975fd0b74Schristos // Convert_endian. That is, it is just like Convert_endian except in
21075fd0b74Schristos // the meaning of the second template parameter.
21175fd0b74Schristos
21275fd0b74Schristos template<int size, bool big_endian>
21375fd0b74Schristos struct Convert
21475fd0b74Schristos {
21575fd0b74Schristos typedef typename Valtype_base<size>::Valtype Valtype;
21675fd0b74Schristos
21775fd0b74Schristos static inline Valtype
21875fd0b74Schristos convert_host(Valtype v)
21975fd0b74Schristos {
22075fd0b74Schristos return Convert_endian<size, big_endian == Endian::host_big_endian>
22175fd0b74Schristos ::convert_host(v);
22275fd0b74Schristos }
22375fd0b74Schristos };
22475fd0b74Schristos
22575fd0b74Schristos // Swap is a template based on size and on whether the target is big
22675fd0b74Schristos // endian. It defines the type Valtype and the functions readval and
22775fd0b74Schristos // writeval. The functions read and write values of the appropriate
22875fd0b74Schristos // size out of buffers, swapping them if necessary. readval and
22975fd0b74Schristos // writeval are overloaded to take pointers to the appropriate type or
23075fd0b74Schristos // pointers to unsigned char.
23175fd0b74Schristos
23275fd0b74Schristos template<int size, bool big_endian>
23375fd0b74Schristos struct Swap
23475fd0b74Schristos {
23575fd0b74Schristos typedef typename Valtype_base<size>::Valtype Valtype;
23675fd0b74Schristos
23775fd0b74Schristos static inline Valtype
23875fd0b74Schristos readval(const Valtype* wv)
23975fd0b74Schristos { return Convert<size, big_endian>::convert_host(*wv); }
24075fd0b74Schristos
24175fd0b74Schristos static inline void
24275fd0b74Schristos writeval(Valtype* wv, Valtype v)
24375fd0b74Schristos { *wv = Convert<size, big_endian>::convert_host(v); }
24475fd0b74Schristos
24575fd0b74Schristos static inline Valtype
24675fd0b74Schristos readval(const unsigned char* wv)
24775fd0b74Schristos { return readval(reinterpret_cast<const Valtype*>(wv)); }
24875fd0b74Schristos
24975fd0b74Schristos static inline void
25075fd0b74Schristos writeval(unsigned char* wv, Valtype v)
25175fd0b74Schristos { writeval(reinterpret_cast<Valtype*>(wv), v); }
25275fd0b74Schristos };
25375fd0b74Schristos
25475fd0b74Schristos // We need to specialize the 8-bit version of Swap to avoid
25575fd0b74Schristos // conflicting overloads, since both versions of readval and writeval
25675fd0b74Schristos // will have the same type parameters.
25775fd0b74Schristos
25875fd0b74Schristos template<bool big_endian>
25975fd0b74Schristos struct Swap<8, big_endian>
26075fd0b74Schristos {
26175fd0b74Schristos typedef typename Valtype_base<8>::Valtype Valtype;
26275fd0b74Schristos
26375fd0b74Schristos static inline Valtype
26475fd0b74Schristos readval(const Valtype* wv)
26575fd0b74Schristos { return *wv; }
26675fd0b74Schristos
26775fd0b74Schristos static inline void
26875fd0b74Schristos writeval(Valtype* wv, Valtype v)
26975fd0b74Schristos { *wv = v; }
27075fd0b74Schristos };
27175fd0b74Schristos
27275fd0b74Schristos // Swap_unaligned is a template based on size and on whether the
27375fd0b74Schristos // target is big endian. It defines the type Valtype and the
27475fd0b74Schristos // functions readval and writeval. The functions read and write
27575fd0b74Schristos // values of the appropriate size out of buffers which may be
27675fd0b74Schristos // misaligned.
27775fd0b74Schristos
27875fd0b74Schristos template<int size, bool big_endian>
27975fd0b74Schristos struct Swap_unaligned;
28075fd0b74Schristos
28175fd0b74Schristos template<bool big_endian>
28275fd0b74Schristos struct Swap_unaligned<8, big_endian>
28375fd0b74Schristos {
28475fd0b74Schristos typedef typename Valtype_base<8>::Valtype Valtype;
28575fd0b74Schristos
28675fd0b74Schristos static inline Valtype
28775fd0b74Schristos readval(const unsigned char* wv)
28875fd0b74Schristos { return *wv; }
28975fd0b74Schristos
29075fd0b74Schristos static inline void
29175fd0b74Schristos writeval(unsigned char* wv, Valtype v)
29275fd0b74Schristos { *wv = v; }
29375fd0b74Schristos };
29475fd0b74Schristos
29575fd0b74Schristos template<>
29675fd0b74Schristos struct Swap_unaligned<16, false>
29775fd0b74Schristos {
29875fd0b74Schristos typedef Valtype_base<16>::Valtype Valtype;
29975fd0b74Schristos
30075fd0b74Schristos static inline Valtype
30175fd0b74Schristos readval(const unsigned char* wv)
30275fd0b74Schristos {
30375fd0b74Schristos return (wv[1] << 8) | wv[0];
30475fd0b74Schristos }
30575fd0b74Schristos
30675fd0b74Schristos static inline void
30775fd0b74Schristos writeval(unsigned char* wv, Valtype v)
30875fd0b74Schristos {
30975fd0b74Schristos wv[1] = v >> 8;
31075fd0b74Schristos wv[0] = v;
31175fd0b74Schristos }
31275fd0b74Schristos };
31375fd0b74Schristos
31475fd0b74Schristos template<>
31575fd0b74Schristos struct Swap_unaligned<16, true>
31675fd0b74Schristos {
31775fd0b74Schristos typedef Valtype_base<16>::Valtype Valtype;
31875fd0b74Schristos
31975fd0b74Schristos static inline Valtype
32075fd0b74Schristos readval(const unsigned char* wv)
32175fd0b74Schristos {
32275fd0b74Schristos return (wv[0] << 8) | wv[1];
32375fd0b74Schristos }
32475fd0b74Schristos
32575fd0b74Schristos static inline void
32675fd0b74Schristos writeval(unsigned char* wv, Valtype v)
32775fd0b74Schristos {
32875fd0b74Schristos wv[0] = v >> 8;
32975fd0b74Schristos wv[1] = v;
33075fd0b74Schristos }
33175fd0b74Schristos };
33275fd0b74Schristos
33375fd0b74Schristos template<>
33475fd0b74Schristos struct Swap_unaligned<32, false>
33575fd0b74Schristos {
33675fd0b74Schristos typedef Valtype_base<32>::Valtype Valtype;
33775fd0b74Schristos
33875fd0b74Schristos static inline Valtype
33975fd0b74Schristos readval(const unsigned char* wv)
34075fd0b74Schristos {
34175fd0b74Schristos return (wv[3] << 24) | (wv[2] << 16) | (wv[1] << 8) | wv[0];
34275fd0b74Schristos }
34375fd0b74Schristos
34475fd0b74Schristos static inline void
34575fd0b74Schristos writeval(unsigned char* wv, Valtype v)
34675fd0b74Schristos {
34775fd0b74Schristos wv[3] = v >> 24;
34875fd0b74Schristos wv[2] = v >> 16;
34975fd0b74Schristos wv[1] = v >> 8;
35075fd0b74Schristos wv[0] = v;
35175fd0b74Schristos }
35275fd0b74Schristos };
35375fd0b74Schristos
35475fd0b74Schristos template<>
35575fd0b74Schristos struct Swap_unaligned<32, true>
35675fd0b74Schristos {
35775fd0b74Schristos typedef Valtype_base<32>::Valtype Valtype;
35875fd0b74Schristos
35975fd0b74Schristos static inline Valtype
36075fd0b74Schristos readval(const unsigned char* wv)
36175fd0b74Schristos {
36275fd0b74Schristos return (wv[0] << 24) | (wv[1] << 16) | (wv[2] << 8) | wv[3];
36375fd0b74Schristos }
36475fd0b74Schristos
36575fd0b74Schristos static inline void
36675fd0b74Schristos writeval(unsigned char* wv, Valtype v)
36775fd0b74Schristos {
36875fd0b74Schristos wv[0] = v >> 24;
36975fd0b74Schristos wv[1] = v >> 16;
37075fd0b74Schristos wv[2] = v >> 8;
37175fd0b74Schristos wv[3] = v;
37275fd0b74Schristos }
37375fd0b74Schristos };
37475fd0b74Schristos
37575fd0b74Schristos template<>
37675fd0b74Schristos struct Swap_unaligned<64, false>
37775fd0b74Schristos {
37875fd0b74Schristos typedef Valtype_base<64>::Valtype Valtype;
37975fd0b74Schristos
38075fd0b74Schristos static inline Valtype
38175fd0b74Schristos readval(const unsigned char* wv)
38275fd0b74Schristos {
38375fd0b74Schristos return ((static_cast<Valtype>(wv[7]) << 56)
38475fd0b74Schristos | (static_cast<Valtype>(wv[6]) << 48)
38575fd0b74Schristos | (static_cast<Valtype>(wv[5]) << 40)
38675fd0b74Schristos | (static_cast<Valtype>(wv[4]) << 32)
38775fd0b74Schristos | (static_cast<Valtype>(wv[3]) << 24)
38875fd0b74Schristos | (static_cast<Valtype>(wv[2]) << 16)
38975fd0b74Schristos | (static_cast<Valtype>(wv[1]) << 8)
39075fd0b74Schristos | static_cast<Valtype>(wv[0]));
39175fd0b74Schristos }
39275fd0b74Schristos
39375fd0b74Schristos static inline void
39475fd0b74Schristos writeval(unsigned char* wv, Valtype v)
39575fd0b74Schristos {
39675fd0b74Schristos wv[7] = v >> 56;
39775fd0b74Schristos wv[6] = v >> 48;
39875fd0b74Schristos wv[5] = v >> 40;
39975fd0b74Schristos wv[4] = v >> 32;
40075fd0b74Schristos wv[3] = v >> 24;
40175fd0b74Schristos wv[2] = v >> 16;
40275fd0b74Schristos wv[1] = v >> 8;
40375fd0b74Schristos wv[0] = v;
40475fd0b74Schristos }
40575fd0b74Schristos };
40675fd0b74Schristos
40775fd0b74Schristos template<>
40875fd0b74Schristos struct Swap_unaligned<64, true>
40975fd0b74Schristos {
41075fd0b74Schristos typedef Valtype_base<64>::Valtype Valtype;
41175fd0b74Schristos
41275fd0b74Schristos static inline Valtype
41375fd0b74Schristos readval(const unsigned char* wv)
41475fd0b74Schristos {
41575fd0b74Schristos return ((static_cast<Valtype>(wv[0]) << 56)
41675fd0b74Schristos | (static_cast<Valtype>(wv[1]) << 48)
41775fd0b74Schristos | (static_cast<Valtype>(wv[2]) << 40)
41875fd0b74Schristos | (static_cast<Valtype>(wv[3]) << 32)
41975fd0b74Schristos | (static_cast<Valtype>(wv[4]) << 24)
42075fd0b74Schristos | (static_cast<Valtype>(wv[5]) << 16)
42175fd0b74Schristos | (static_cast<Valtype>(wv[6]) << 8)
42275fd0b74Schristos | static_cast<Valtype>(wv[7]));
42375fd0b74Schristos }
42475fd0b74Schristos
42575fd0b74Schristos static inline void
42675fd0b74Schristos writeval(unsigned char* wv, Valtype v)
42775fd0b74Schristos {
42875fd0b74Schristos wv[0] = v >> 56;
42975fd0b74Schristos wv[1] = v >> 48;
43075fd0b74Schristos wv[2] = v >> 40;
43175fd0b74Schristos wv[3] = v >> 32;
43275fd0b74Schristos wv[4] = v >> 24;
43375fd0b74Schristos wv[5] = v >> 16;
43475fd0b74Schristos wv[6] = v >> 8;
43575fd0b74Schristos wv[7] = v;
43675fd0b74Schristos }
43775fd0b74Schristos };
43875fd0b74Schristos
43975fd0b74Schristos // Swap_aligned32 is a template based on size and on whether the
44075fd0b74Schristos // target is big endian. It defines the type Valtype and the
44175fd0b74Schristos // functions readval and writeval. The functions read and write
44275fd0b74Schristos // values of the appropriate size out of buffers which may not be
44375fd0b74Schristos // 64-bit aligned, but are 32-bit aligned.
44475fd0b74Schristos
44575fd0b74Schristos template<int size, bool big_endian>
44675fd0b74Schristos struct Swap_aligned32
44775fd0b74Schristos {
44875fd0b74Schristos typedef typename Valtype_base<size>::Valtype Valtype;
44975fd0b74Schristos
45075fd0b74Schristos static inline Valtype
45175fd0b74Schristos readval(const unsigned char* wv)
45275fd0b74Schristos { return Swap<size, big_endian>::readval(
45375fd0b74Schristos reinterpret_cast<const Valtype*>(wv)); }
45475fd0b74Schristos
45575fd0b74Schristos static inline void
45675fd0b74Schristos writeval(unsigned char* wv, Valtype v)
45775fd0b74Schristos { Swap<size, big_endian>::writeval(reinterpret_cast<Valtype*>(wv), v); }
45875fd0b74Schristos };
45975fd0b74Schristos
46075fd0b74Schristos template<>
46175fd0b74Schristos struct Swap_aligned32<64, true>
46275fd0b74Schristos {
46375fd0b74Schristos typedef Valtype_base<64>::Valtype Valtype;
46475fd0b74Schristos
46575fd0b74Schristos static inline Valtype
46675fd0b74Schristos readval(const unsigned char* wv)
46775fd0b74Schristos {
46875fd0b74Schristos return ((static_cast<Valtype>(Swap<32, true>::readval(wv)) << 32)
46975fd0b74Schristos | static_cast<Valtype>(Swap<32, true>::readval(wv + 4)));
47075fd0b74Schristos }
47175fd0b74Schristos
47275fd0b74Schristos static inline void
47375fd0b74Schristos writeval(unsigned char* wv, Valtype v)
47475fd0b74Schristos {
47575fd0b74Schristos typedef Valtype_base<32>::Valtype Valtype32;
47675fd0b74Schristos
47775fd0b74Schristos Swap<32, true>::writeval(wv, static_cast<Valtype32>(v >> 32));
47875fd0b74Schristos Swap<32, true>::writeval(wv + 4, static_cast<Valtype32>(v));
47975fd0b74Schristos }
48075fd0b74Schristos };
48175fd0b74Schristos
48275fd0b74Schristos template<>
48375fd0b74Schristos struct Swap_aligned32<64, false>
48475fd0b74Schristos {
48575fd0b74Schristos typedef Valtype_base<64>::Valtype Valtype;
48675fd0b74Schristos
48775fd0b74Schristos static inline Valtype
48875fd0b74Schristos readval(const unsigned char* wv)
48975fd0b74Schristos {
49075fd0b74Schristos return ((static_cast<Valtype>(Swap<32, false>::readval(wv + 4)) << 32)
49175fd0b74Schristos | static_cast<Valtype>(Swap<32, false>::readval(wv)));
49275fd0b74Schristos }
49375fd0b74Schristos
49475fd0b74Schristos static inline void
49575fd0b74Schristos writeval(unsigned char* wv, Valtype v)
49675fd0b74Schristos {
49775fd0b74Schristos typedef Valtype_base<32>::Valtype Valtype32;
49875fd0b74Schristos
49975fd0b74Schristos Swap<32, false>::writeval(wv + 4, static_cast<Valtype32>(v >> 32));
50075fd0b74Schristos Swap<32, false>::writeval(wv, static_cast<Valtype32>(v));
50175fd0b74Schristos }
50275fd0b74Schristos };
50375fd0b74Schristos
50475fd0b74Schristos } // End namespace elfcpp.
50575fd0b74Schristos
50675fd0b74Schristos #endif // !defined(ELFCPP_SWAP_H)
507