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>