1 /*
2  * Copyright (C) 2016 Andes Technology, Inc.
3  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
4  */
5 
6 /* Macros to swap the order of bytes in integer values.
7    Copyright (C) 1997, 1998, 2000, 2002, 2003, 2006, 2007
8    Free Software Foundation, Inc.
9 
10    The GNU C Library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2.1 of the License, or (at your option) any later version.
14 
15    The GNU C Library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19 
20    You should have received a copy of the GNU Lesser General Public
21    License along with the GNU C Library; if not, write to the Free
22    Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
23    02111-1307 USA.  */
24 
25 #if !defined _BYTESWAP_H && !defined _NETINET_IN_H
26 # error "Never use <bits/byteswap.h> directly; include <byteswap.h> instead."
27 #endif
28 
29 #ifndef _BITS_BYTESWAP_H
30 #define _BITS_BYTESWAP_H 1
31 
32 /* Swap bytes in 16 bit value.  */
33 #define __bswap_constant_16(x) \
34      ((((x) >> 8) & 0xff) | (((x) & 0xff) << 8))
35 
36 #ifdef __GNUC__
37 # if __GNUC__ >= 2
38 #  define __bswap_16(x) \
39      (__extension__							      \
40       ({ register unsigned short int __v, __x = (x);			      \
41 	 if (__builtin_constant_p (__x))				      \
42 	   __v = __bswap_constant_16 (__x);				      \
43 	 else								      \
44 	   __asm__ ("wsbh	%0, %0\n\t"				  \
45 		    : "=r" (__v)					      \
46  		    : "0" (__x));						  \
47 	 __v; }))
48 # else
49 /* This is better than nothing.  */
50 #  define __bswap_16(x) \
51      (__extension__							      \
52       ({ register unsigned short int __x = (x); __bswap_constant_16 (__x); }))
53 # endif
54 #else
55 static __inline unsigned short int
__bswap_16(unsigned short int __bsx)56 __bswap_16 (unsigned short int __bsx)
57 {
58   return __bswap_constant_16 (__bsx);
59 }
60 #endif
61 
62 /* Swap bytes in 32 bit value.  */
63 #define __bswap_constant_32(x) \
64      ((((x) & 0xff000000) >> 24) | (((x) & 0x00ff0000) >>  8) |		      \
65       (((x) & 0x0000ff00) <<  8) | (((x) & 0x000000ff) << 24))
66 
67 #ifdef __GNUC__
68 # if __GNUC__ >= 2
69 #   define __bswap_32(x) \
70      (__extension__							      \
71       ({ register unsigned int __v, __x = (x);				      \
72 	 if (__builtin_constant_p (__x))				      \
73 	   __v = __bswap_constant_32 (__x);				      \
74 	 else								      \
75 	   __asm__ ("wsbh	%0, %0\n\t"		\
76 			"rotri	%0, %0, #16\n\t"	\
77 			: "=r" (__v)				\
78 			: "0" (__x));				\
79 	 __v; }))
80 # else
81 #  define __bswap_32(x) \
82      (__extension__							      \
83       ({ register unsigned int __x = (x); __bswap_constant_32 (__x); }))
84 # endif
85 #else
86 static __inline unsigned int
__bswap_32(unsigned int __bsx)87 __bswap_32 (unsigned int __bsx)
88 {
89   return __bswap_constant_32 (__bsx);
90 }
91 #endif
92 
93 
94 #if defined __GNUC__ && __GNUC__ >= 2
95 /* Swap bytes in 64 bit value.  */
96 #define __bswap_constant_64(x) \
97      ((((x) & 0xff00000000000000ull) >> 56)				      \
98       | (((x) & 0x00ff000000000000ull) >> 40)				      \
99       | (((x) & 0x0000ff0000000000ull) >> 24)				      \
100       | (((x) & 0x000000ff00000000ull) >> 8)				      \
101       | (((x) & 0x00000000ff000000ull) << 8)				      \
102       | (((x) & 0x0000000000ff0000ull) << 24)				      \
103       | (((x) & 0x000000000000ff00ull) << 40)				      \
104       | (((x) & 0x00000000000000ffull) << 56))
105 
106 # define __bswap_64(x) \
107      (__extension__							      \
108       ({ union { __extension__ unsigned long long int __ll;		      \
109 		 unsigned long int __l[2]; } __w, __r;			      \
110          if (__builtin_constant_p (x))					      \
111 	   __r.__ll = __bswap_constant_64 (x);				      \
112 	 else								      \
113 	   {								      \
114 	     __w.__ll = (x);						      \
115 	     __r.__l[0] = __bswap_32 (__w.__l[1]);			      \
116 	     __r.__l[1] = __bswap_32 (__w.__l[0]);			      \
117 	   }								      \
118 	 __r.__ll; }))
119 #endif
120 
121 #endif /* _BITS_BYTESWAP_H */
122