Clang Project

include/x86_64-linux-gnu/bits/byteswap.h
1/* Macros to swap the order of bytes in integer values.
2   Copyright (C) 1997-2016 Free Software Foundation, Inc.
3   This file is part of the GNU C Library.
4
5   The GNU C Library is free software; you can redistribute it and/or
6   modify it under the terms of the GNU Lesser General Public
7   License as published by the Free Software Foundation; either
8   version 2.1 of the License, or (at your option) any later version.
9
10   The GNU C Library is distributed in the hope that it will be useful,
11   but WITHOUT ANY WARRANTY; without even the implied warranty of
12   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13   Lesser General Public License for more details.
14
15   You should have received a copy of the GNU Lesser General Public
16   License along with the GNU C Library; if not, see
17   <http://www.gnu.org/licenses/>.  */
18
19#if !defined _BYTESWAP_H && !defined _NETINET_IN_H && !defined _ENDIAN_H
20# error "Never use <bits/byteswap.h> directly; include <byteswap.h> instead."
21#endif
22
23#ifndef _BITS_BYTESWAP_H
24#define _BITS_BYTESWAP_H 1
25
26#include <features.h>
27#include <bits/types.h>
28#include <bits/wordsize.h>
29
30/* Swap bytes in 16 bit value.  */
31#define __bswap_constant_16(x) \
32     ((unsigned short int) ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8)))
33
34/* Get __bswap_16.  */
35#include <bits/byteswap-16.h>
36
37/* Swap bytes in 32 bit value.  */
38#define __bswap_constant_32(x) \
39     ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) |       \
40      (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))
41
42#ifdef __GNUC__
43if __GNUC_PREREQ (4, 3)
44static __inline unsigned int
45__bswap_32 (unsigned int __bsx)
46{
47  return __builtin_bswap32 (__bsx);
48}
49elif __GNUC__ >= 2
50#  if __WORDSIZE == 64 || (defined __i486__ || defined __pentium__       \
51    || defined __pentiumpro__ || defined __pentium4__  \
52    || defined __k8__ || defined __athlon__       \
53    || defined __k6__ || defined __nocona__       \
54    || defined __core2__ || defined __geode__       \
55    || defined __amdfam10__)
56/* To swap the bytes in a word the i486 processors and up provide the
57   `bswap' opcode.  On i386 we have to use three instructions.  */
58#   define __bswap_32(x) \
59      (__extension__       \
60       ({ unsigned int __v, __x = (x);       \
61   if (__builtin_constant_p (__x))       \
62     __v = __bswap_constant_32 (__x);       \
63   else       \
64     __asm__ ("bswap %0" : "=r" (__v) : "0" (__x));       \
65   __v; }))
66#  else
67#   define __bswap_32(x)       \
68      (__extension__       \
69       ({ unsigned int __v, __x = (x);       \
70   if (__builtin_constant_p (__x))       \
71     __v = __bswap_constant_32 (__x);       \
72   else       \
73     __asm__ ("rorw $8, %w0;"       \
74      "rorl $16, %0;"       \
75      "rorw $8, %w0"       \
76      : "=r" (__v)       \
77      : "0" (__x)       \
78      : "cc");       \
79   __v; }))
80#  endif
81else
82#  define __bswap_32(x) \
83     (__extension__       \
84      ({ unsigned int __x = (x); __bswap_constant_32 (__x); }))
85endif
86#else
87static __inline unsigned int
88__bswap_32 (unsigned int __bsx)
89{
90  return __bswap_constant_32 (__bsx);
91}
92#endif
93
94
95#if __GNUC_PREREQ (2, 0)
96/* Swap bytes in 64 bit value.  */
97# define __bswap_constant_64(x) \
98     (__extension__ ((((x) & 0xff00000000000000ull) >> 56)       \
99      | (((x) & 0x00ff000000000000ull) >> 40)       \
100      | (((x) & 0x0000ff0000000000ull) >> 24)       \
101      | (((x) & 0x000000ff00000000ull) >> 8)       \
102      | (((x) & 0x00000000ff000000ull) << 8)       \
103      | (((x) & 0x0000000000ff0000ull) << 24)       \
104      | (((x) & 0x000000000000ff00ull) << 40)       \
105      | (((x) & 0x00000000000000ffull) << 56)))
106
107if __GNUC_PREREQ (4, 3)
108static __inline __uint64_t
109__bswap_64 (__uint64_t __bsx)
110{
111  return __builtin_bswap64 (__bsx);
112}
113elif __WORDSIZE == 64
114#  define __bswap_64(x) \
115     (__extension__       \
116      ({ __uint64_t __v, __x = (x);       \
117  if (__builtin_constant_p (__x))       \
118    __v = __bswap_constant_64 (__x);       \
119  else       \
120    __asm__ ("bswap %q0" : "=r" (__v) : "0" (__x));       \
121  __v; }))
122else
123#  define __bswap_64(x) \
124     (__extension__                                                           \
125      ({ union { __extension__ __uint64_t __ll;                       \
126  unsigned int __l[2]; } __w, __r;                             \
127  if (__builtin_constant_p (x))                                        \
128    __r.__ll = __bswap_constant_64 (x);                                \
129  else                                                                 \
130    {                                                                  \
131      __w.__ll = (x);                                                  \
132      __r.__l[0] = __bswap_32 (__w.__l[1]);                            \
133      __r.__l[1] = __bswap_32 (__w.__l[0]);                            \
134    }                                                                  \
135  __r.__ll; }))
136endif
137#else
138# define __bswap_constant_64(x) \
139     ((((x) & 0xff00000000000000ull) >> 56)       \
140      | (((x) & 0x00ff000000000000ull) >> 40)       \
141      | (((x) & 0x0000ff0000000000ull) >> 24)       \
142      | (((x) & 0x000000ff00000000ull) >> 8)       \
143      | (((x) & 0x00000000ff000000ull) << 8)       \
144      | (((x) & 0x0000000000ff0000ull) << 24)       \
145      | (((x) & 0x000000000000ff00ull) << 40)       \
146      | (((x) & 0x00000000000000ffull) << 56))
147
148static __inline __uint64_t
149__bswap_64 (__uint64_t __bsx)
150{
151  return __bswap_constant_64 (__bsx);
152}
153#endif
154
155#endif /* _BITS_BYTESWAP_H */
156