1 /* HBYTESWP.H   (c) Copyright Jan Jaeger, 2001-2009                  */
2 /*              Hercules Little <> Big Endian conversion             */
3 
4 /* These definitions are only nessesary when running on older        */
5 /* versions of linux that do not have /usr/include/byteswap.h        */
6 /* compile option -DNO_ASM_BYTESWAP will expand 'C' code             */
7 /* otherwise Intel (486+) assember will be generated                 */
8 
9 #ifndef _BYTESWAP_H
10 #define _BYTESWAP_H
11 
12 #if !defined(NO_ASM_BYTESWAP)
13 
14   #include "htypes.h"       // (need Hercules fixed-size data types)
15 
16   #if defined( _MSVC_ )
17 
bswap_16(uint16_t x)18     static __inline  uint16_t  __fastcall  bswap_16 ( uint16_t  x )
19     {
20       return _byteswap_ushort((x));
21     }
22 
bswap_32(uint32_t x)23     static __inline  uint32_t  __fastcall  bswap_32 ( uint32_t  x )
24     {
25       return _byteswap_ulong((x));
26     }
27 
28   #else // !defined( _MSVC_ )
29 
30     static __inline__ uint16_t (ATTR_REGPARM(1) bswap_16)(uint16_t x)
31     {
32 #if defined(__x86_64__)
33       __asm__("xchgb %b0,%h0" : "=Q" (x) :  "0" (x));
34 #else
35       __asm__("xchgb %b0,%h0" : "=q" (x) :  "0" (x));
36 #endif
37       return x;
38     }
39 
40     static __inline__ uint32_t (ATTR_REGPARM(1) bswap_32)(uint32_t x)
41     {
42 #if defined(__x86_64__)
43       __asm__("bswapl %0" : "=r" (x) : "0" (x));
44 #else
45       __asm__("bswap %0" : "=r" (x) : "0" (x));
46 #endif
47       return x;
48     }
49 
50   #endif // defined( _MSVC_ )
51 
52 #else // defined(NO_ASM_BYTESWAP)
53 
54   #define bswap_16(_x) \
55           ( (((_x) & 0xFF00) >> 8) \
56           | (((_x) & 0x00FF) << 8) )
57 
58   #define bswap_32(_x) \
59           ( (((_x) & 0xFF000000) >> 24) \
60           | (((_x) & 0x00FF0000) >> 8)  \
61           | (((_x) & 0x0000FF00) << 8)  \
62           | (((_x) & 0x000000FF) << 24) )
63 
64 #endif // !defined(NO_ASM_BYTESWAP)
65 
66 #if defined( _MSVC_ )
67 
68   // Microsoft's Toolkit 2003 compiler (version 1300) has a known bug
69   // that causes the _byteswap_uint64 intrinsic to screw up if global
70   // otimizations are enabled. The new VStudio 8.0 compiler (version
71   // 14.00) doesn't have this problem that I am aware of. NOTE that
72   // the #pragma must be outside the function (at global scope) to
73   // prevent compiler error C2156 "pragma must be outside function".
74 
75   #if ( _MSC_VER < 1400 )
76     #pragma optimize("g",off)     // (disable global optimizations)
77   #endif
bswap_64(uint64_t x)78   static __inline  uint64_t  __fastcall  bswap_64(uint64_t x)
79   {
80       return _byteswap_uint64((x));
81   }
82   #if ( _MSC_VER < 1400 )
83     #pragma optimize ( "", on )
84   #endif
85 
86 #else // !defined( _MSVC_ )
87 
88   #if defined(NO_ASM_BYTESWAP)
89     #define bswap_64(_x) \
90           ( ((U64)((_x) & 0xFF00000000000000ULL) >> 56) \
91           | ((U64)((_x) & 0x00FF000000000000ULL) >> 40) \
92           | ((U64)((_x) & 0x0000FF0000000000ULL) >> 24) \
93           | ((U64)((_x) & 0x000000FF00000000ULL) >> 8)  \
94           | ((U64)((_x) & 0x00000000FF000000ULL) << 8)  \
95           | ((U64)((_x) & 0x0000000000FF0000ULL) << 24) \
96           | ((U64)((_x) & 0x000000000000FF00ULL) << 40) \
97           | ((U64)((_x) & 0x00000000000000FFULL) << 56) )
98   #else
99     static __inline__ uint64_t (ATTR_REGPARM(1) bswap_64)(uint64_t x)
100     {
101     #if defined(__x86_64__)
102       __asm__("bswapq %0" : "=r" (x) : "0" (x));
103       return x;
104     #else // swap the two words after byteswapping them
105       union
106       {
107         struct
108         {
109           uint32_t high,low;
110         } words;
111         uint64_t quad;
112       } value;
113 
114       value.quad=x;
115       __asm__("bswap %0" : "=r" (value.words.high) : "0" (value.words.high));
116       __asm__("bswap %0" : "=r" (value.words.low) : "0" (value.words.low));
117       __asm__("xchgl %0,%1" : "=r" (value.words.high), "=r" (value.words.low) :
118               "0" (value.words.high), "1" (value.words.low));
119       return value.quad;
120     #endif // defined(__x86_64__)
121     }
122   #endif // defined(NO_ASM_BYTESWAP)
123 
124 #endif // defined( _MSVC_ )
125 
126 #endif // _BYTESWAP_H
127