upstream: https://github.com/mirage/mirage-crypto
1/*
2 * Copyright (C) 2006-2009 Vincent Hanquez <vincent@snarc.org>
3 *
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions
6 * are met:
7 * 1. Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * 2. Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
14 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
15 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
16 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
17 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
18 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
19 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
20 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
22 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23 */
24
25#ifndef BITFN_H
26#define BITFN_H
27#include <stdint.h>
28
29# if (defined(__i386__))
30# define ARCH_HAS_SWAP32
31static inline uint32_t bitfn_swap32(uint32_t a)
32{
33 __asm__ ("bswap %0" : "=r" (a) : "0" (a));
34 return a;
35}
36/**********************************************************/
37# elif (defined(__arm__))
38# define ARCH_HAS_SWAP32
39static inline uint32_t bitfn_swap32(uint32_t a)
40{
41 uint32_t tmp = a;
42 __asm__ volatile ("eor %1, %0, %0, ror #16\n"
43 "bic %1, %1, #0xff0000\n"
44 "mov %0, %0, ror #8\n"
45 "eor %0, %0, %1, lsr #8\n"
46 : "=r" (a), "=r" (tmp) : "0" (a), "1" (tmp));
47 return a;
48}
49/**********************************************************/
50# elif defined(__x86_64__)
51# define ARCH_HAS_SWAP32
52# define ARCH_HAS_SWAP64
53static inline uint32_t bitfn_swap32(uint32_t a)
54{
55 __asm__ ("bswap %0" : "=r" (a) : "0" (a));
56 return a;
57}
58
59static inline uint64_t bitfn_swap64(uint64_t a)
60{
61 __asm__ ("bswap %0" : "=r" (a) : "0" (a));
62 return a;
63}
64
65# endif
66
67#ifndef ARCH_HAS_SWAP32
68static inline uint32_t bitfn_swap32(uint32_t a)
69{
70 return (a << 24) | ((a & 0xff00) << 8) | ((a >> 8) & 0xff00) | (a >> 24);
71}
72#endif
73
74#ifndef ARCH_HAS_SWAP64
75static inline uint64_t bitfn_swap64(uint64_t a)
76{
77 return ((uint64_t) bitfn_swap32((uint32_t) (a >> 32))) |
78 (((uint64_t) bitfn_swap32((uint32_t) a)) << 32);
79}
80#endif
81
82static inline uint32_t rol32(uint32_t word, uint32_t shift)
83{
84 return (word << shift) | (word >> (32 - shift));
85}
86
87static inline uint32_t ror32(uint32_t word, uint32_t shift)
88{
89 return (word >> shift) | (word << (32 - shift));
90}
91
92static inline uint64_t rol64(uint64_t word, uint32_t shift)
93{
94 return (word << shift) | (word >> (64 - shift));
95}
96
97static inline uint64_t ror64(uint64_t word, uint32_t shift)
98{
99 return (word >> shift) | (word << (64 - shift));
100}
101
102static inline void array_swap32(uint32_t *d, const uint32_t *s, uint32_t nb)
103{
104 while (nb--)
105 *d++ = bitfn_swap32(*s++);
106}
107
108static inline void array_swap64(uint64_t *d, const uint64_t *s, uint32_t nb)
109{
110 while (nb--)
111 *d++ = bitfn_swap64(*s++);
112}
113
114static inline void array_copy32(uint32_t *d, const uint32_t *s, uint32_t nb)
115{
116 while (nb--) *d++ = *s++;
117}
118
119static inline void array_copy64(uint64_t *d, const uint64_t *s, uint32_t nb)
120{
121 while (nb--) *d++ = *s++;
122}
123
124#if defined(_MSC_VER) || defined(__BYTE_ORDER__)
125#if defined(_MSC_VER) || (__ORDER_LITTLE_ENDIAN__ == __BYTE_ORDER__)
126
127# define be32_to_cpu(a) bitfn_swap32(a)
128# define cpu_to_be32(a) bitfn_swap32(a)
129# define le32_to_cpu(a) (a)
130# define cpu_to_le32(a) (a)
131# define be64_to_cpu(a) bitfn_swap64(a)
132# define cpu_to_be64(a) bitfn_swap64(a)
133# define le64_to_cpu(a) (a)
134# define cpu_to_le64(a) (a)
135
136# define cpu_to_le32_array(d, s, l) array_copy32(d, s, l)
137# define le32_to_cpu_array(d, s, l) array_copy32(d, s, l)
138# define cpu_to_be32_array(d, s, l) array_swap32(d, s, l)
139# define be32_to_cpu_array(d, s, l) array_swap32(d, s, l)
140
141# define cpu_to_le64_array(d, s, l) array_copy64(d, s, l)
142# define le64_to_cpu_array(d, s, l) array_copy64(d, s, l)
143# define cpu_to_be64_array(d, s, l) array_swap64(d, s, l)
144# define be64_to_cpu_array(d, s, l) array_swap64(d, s, l)
145
146# define ARCH_IS_LITTLE_ENDIAN
147
148#elif __ORDER_BIG_ENDIAN__ == __BYTE_ORDER__
149
150# define be32_to_cpu(a) (a)
151# define cpu_to_be32(a) (a)
152# define le32_to_cpu(a) bitfn_swap32(a)
153# define cpu_to_le32(a) bitfn_swap32(a)
154# define be64_to_cpu(a) (a)
155# define cpu_to_be64(a) (a)
156# define le64_to_cpu(a) bitfn_swap64(a)
157# define cpu_to_le64(a) bitfn_swap64(a)
158
159# define cpu_to_le32_array(d, s, l) array_swap32(d, s, l)
160# define le32_to_cpu_array(d, s, l) array_swap32(d, s, l)
161# define cpu_to_be32_array(d, s, l) array_copy32(d, s, l)
162# define be32_to_cpu_array(d, s, l) array_copy32(d, s, l)
163
164# define cpu_to_le64_array(d, s, l) array_swap64(d, s, l)
165# define le64_to_cpu_array(d, s, l) array_swap64(d, s, l)
166# define cpu_to_be64_array(d, s, l) array_copy64(d, s, l)
167# define be64_to_cpu_array(d, s, l) array_copy64(d, s, l)
168
169# define ARCH_IS_BIG_ENDIAN
170
171#else
172# error "endian is neither big nor little endian"
173#endif
174
175#else
176# error "__BYTE_ORDER__ is not defined"
177#endif
178
179#endif /* !BITFN_H */