1 /* Copyright 2007-2012 Fredrik Wikstrom. All rights reserved.
3 ** Redistribution and use in source and binary forms, with or without
4 ** modification, are permitted provided that the following conditions
7 ** 1. Redistributions of source code must retain the above copyright
8 ** notice, this list of conditions and the following disclaimer.
10 ** 2. Redistributions in binary form must reproduce the above copyright
11 ** notice, this list of conditions and the following disclaimer in the
12 ** documentation and/or other materials provided with the distribution.
14 ** THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS `AS IS'
15 ** AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 ** IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 ** ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
18 ** LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
19 ** CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
20 ** SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
21 ** INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
22 ** CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
23 ** ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24 ** POSSIBILITY OF SUCH DAMAGE.
32 #ifndef WORDS_BIGENDIAN
34 #include_next <endian.h>
35 #if _BYTE_ORDER == _BIG_ENDIAN
36 #define WORDS_BIGENDIAN 1
37 #elif _BYTE_ORDER == _LITTLE_ENDIAN
38 #define WORDS_BIGENDIAN 0
40 #error "Unsupported endian format."
43 #define WORDS_BIGENDIAN 1
47 #define swap16(x) ((((uint16_t)(x) & 0x00ff)<<8)| \
48 (((uint16_t)(x) & 0xff00)>>8))
49 #define swap32(x) ((((uint32_t)(x) & 0x000000ff)<<24)| \
50 (((uint32_t)(x) & 0x0000ff00)<<8)| \
51 (((uint32_t)(x) & 0x00ff0000)>>8)| \
52 (((uint32_t)(x) & 0xff000000)>>24))
53 #define swap64(x) ((uint64_t)swap32((uint64_t)(x) >> 32)|((uint64_t)swap32(x) << 32))
54 #define rswap16(p) swap16(*(uint16_t *)(p))
55 #define rswap32(p) swap32(*(uint32_t *)(p))
56 #define rswap64(p) swap64(*(uint64_t *)(p))
57 #define wswap16(p,x) (*(uint16_t *)(p) = swap16(x))
58 #define wswap32(p,x) (*(uint32_t *)(p) = swap32(x))
59 #define wswap64(p,x) (*(uint64_t *)(p) = swap64(x))
65 #define h2le16(x) swap16(x)
66 #define h2le32(x) swap32(x)
67 #define h2le64(x) swap64(x)
68 #define rbe16(p) (*(uint16_t *)(p))
69 #define rbe32(p) (*(uint32_t *)(p))
70 #define rbe64(p) (*(uint64_t *)(p))
71 #define rle16(p) rswap16(p)
72 #define rle32(p) rswap32(p)
73 #define rle64(p) rswap64(p)
74 #define wbe16(p,x) (*(uint16_t *)(p) = (x))
75 #define wbe32(p,x) (*(uint32_t *)(p) = (x))
76 #define wbe64(p,x) (*(uint64_t *)(p) = (x))
77 #define wle16(p,x) wswap16(p,x)
78 #define wle32(p,x) wswap32(p,x)
79 #define wle64(p,x) wswap64(p,x)
84 #define h2be16(x) swap16(x)
85 #define h2be32(x) swap32(x)
86 #define h2be64(x) swap64(x)
87 #define rle16(p) (*(uint16_t *)(p))
88 #define rle32(p) (*(uint32_t *)(p))
89 #define rle64(p) (*(uint64_t *)(p))
90 #define rbe16(p) rswap16(p)
91 #define rbe32(p) rswap32(p)
92 #define rbe64(p) rswap64(p)
93 #define wle16(p,x) (*(uint16_t *)(p) = (x))
94 #define wle32(p,x) (*(uint32_t *)(p) = (x))
95 #define wle64(p,x) (*(uint64_t *)(p) = (x))
96 #define wbe16(p,x) wswap16(p,x)
97 #define wbe32(p,x) wswap32(p,x)
98 #define wbe64(p,x) wswap64(p,x)
101 #if defined(__VBCC__) && defined(__PPC__)
107 uint16_t swap16(__reg("r4") uint16_t) =
108 "\trlwinm\t3,4,8,16,24\n"
109 "\trlwimi\t3,4,24,24,31";
111 uint32_t swap32(__reg("r4") uint32_t) =
112 "\trlwinm\t3,4,24,0,31\n"
113 "\trlwimi\t3,4,8,8,15\n"
114 "\trlwimi\t3,4,8,24,31";
116 uint64_t swap64(__reg("r5/r6") uint64_t) =
117 "\trlwinm\t4,5,24,0,31\n"
118 "\trlwinm\t3,6,24,0,31\n"
119 "\trlwimi\t4,5,8,8,15\n"
120 "\trlwimi\t3,6,8,8,15\n"
121 "\trlwimi\t4,5,8,24,31\n"
122 "\trlwimi\t3,6,8,24,31";
128 uint16_t rswap16(__reg("r3") void *) =
131 uint32_t rswap32(__reg("r3") void *) =
134 uint64_t rswap64(__reg("r3") void *) =
135 "\taddi\t5,3,4\n" // r5 = r3 + 4
143 void wswap16(__reg("r3") void *, __reg("r4") uint16_t) =
146 void wswap32(__reg("r3") void *, __reg("r4") uint32_t) =
149 void wswap64(__reg("r3") void *, __reg("r5/r6") uint64_t) =
150 "\taddi\t4,3,4\n" // r4 = r3 + 4
154 #endif /* defined(__VBCC__) && defined(__PPC__) */
156 #if defined(__GNUC__) && defined(__PPC__)
162 static inline uint32_t swap16(uint16_t x
) {
164 asm("rlwinm %0,%1,8,16,23\n"
165 "\trlwimi %0,%1,24,24,31"
171 static inline uint32_t swap32(uint32_t x
) {
173 asm("rlwinm %0,%1,24,0,31\n"
174 "\trlwimi %0,%1,8,8,15\n"
175 "\trlwimi %0,%1,8,24,31"
181 static inline uint64_t swap64(uint64_t x
) {
183 asm("rlwinm %L0,%H1,24,0,31\n"
184 "\trlwinm %H0,%L1,24,0,31\n"
185 "\trlwimi %L0,%H1,8,8,15\n"
186 "\trlwimi %H0,%L1,8,8,15\n"
187 "\trlwimi %L0,%H1,8,24,31\n"
188 "\trlwimi %H0,%L1,8,24,31"
198 static inline uint32_t rswap16(const void *p
) {
200 const uint16_t *p0
= p
;
207 static inline uint32_t rswap32(const void *p
) {
209 const uint32_t *p0
= p
;
216 static inline uint64_t rswap64(const void *p
) {
218 const uint32_t *p0
= p
;
219 const uint32_t *p1
= p0
+1;
220 asm("lwbrx %L0,%y1\n"
223 : "Z" (*p0
), "Z" (*p1
));
231 static inline void wswap16(void *p
, uint16_t x
) {
235 : "Z" (*p0
), "r" (x
));
238 static inline void wswap32(void *p
, uint32_t x
) {
242 : "Z" (*p0
), "r" (x
));
245 static inline void wswap64(void *p
, uint64_t x
) {
248 asm("stwbrx %L2,%y0\n"
251 : "Z" (*p0
), "Z" (*p1
), "r" (x
));
253 #endif /* defined(__GNUC__) && defined(__PPC__) */
255 #if defined(__GNUC__) && (defined(__i386__) || defined(__i486__))
264 static inline uint16_t swap16(uint16_t x
) {
273 static inline uint32_t swap32(uint32_t x
) {
292 #if defined(__VBCC__) && defined(__M68K__)
298 static inline uint16_t swap16(__reg("d0") uint16_t) =
301 static inline uint32_t swap32(__reg("d0") uint32_t) =
306 static inline uint64_t swap64(__reg("d0/d1") uint64_t) =
319 static inline uint64_t rswap64(__reg("a0") void *) =
320 "\tmove.l\t4(a0),d0\n"
321 "\tmove.l\t(a0),d1\n"
331 static inline uint64_t wswap64(__reg("a0") void *, __reg("d0/d1") uint64_t) =
338 "\tmove.l\td0,4(a0)\n"
341 #endif /* defined(__VBCC__) && defined(__M68K__) */
343 #endif /* ENDIAN_H */