1/*
2 * Copyright (c) 1999-2007 Apple Inc. All rights reserved.
3 */
4
5#ifndef _OS_OSBYTEORDERARM_H
6#define _OS_OSBYTEORDERARM_H
7
8#include <stdint.h>
9#include <arm/arch.h> /* for _ARM_ARCH_6 */
10
11/* Generic byte swapping functions. */
12
13__DARWIN_OS_INLINE
14uint16_t
15_OSSwapInt16(
16 uint16_t _data
17 )
18{
19 /* Reduces to 'rev16' with clang */
20 return (uint16_t)(_data << 8 | _data >> 8);
21}
22
23__DARWIN_OS_INLINE
24uint32_t
25_OSSwapInt32(
26 uint32_t _data
27 )
28{
29#if defined(__llvm__)
30 _data = __builtin_bswap32(_data);
31#else
32 /* This actually generates the best code */
33 _data = (((_data ^ (_data >> 16 | (_data << 16))) & 0xFF00FFFF) >> 8) ^ (_data >> 8 | _data << 24);
34#endif
35
36 return _data;
37}
38
39__DARWIN_OS_INLINE
40uint64_t
41_OSSwapInt64(
42 uint64_t _data
43 )
44{
45#if defined(__llvm__)
46 return __builtin_bswap64(_data);
47#else
48 union {
49 uint64_t _ull;
50 uint32_t _ul[2];
51 } _u;
52
53 /* This actually generates the best code */
54 _u._ul[0] = (uint32_t)(_data >> 32);
55 _u._ul[1] = (uint32_t)(_data & 0xffffffff);
56 _u._ul[0] = _OSSwapInt32(_u._ul[0]);
57 _u._ul[1] = _OSSwapInt32(_u._ul[1]);
58 return _u._ull;
59#endif
60}
61
62/* Functions for byte reversed loads. */
63
64struct _OSUnalignedU16 {
65 volatile uint16_t __val;
66} __attribute__((__packed__));
67
68struct _OSUnalignedU32 {
69 volatile uint32_t __val;
70} __attribute__((__packed__));
71
72struct _OSUnalignedU64 {
73 volatile uint64_t __val;
74} __attribute__((__packed__));
75
76#if defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE)
77__DARWIN_OS_INLINE
78uint16_t
79_OSReadSwapInt16(
80 const volatile void * _base,
81 uintptr_t _offset
82 )
83{
84 return _OSSwapInt16(((struct _OSUnalignedU16 *)((uintptr_t)_base + _offset))->__val);
85}
86#else
87__DARWIN_OS_INLINE
88uint16_t
89OSReadSwapInt16(
90 const volatile void * _base,
91 uintptr_t _offset
92 )
93{
94 return _OSSwapInt16(data: ((struct _OSUnalignedU16 *)((uintptr_t)_base + _offset))->__val);
95}
96#endif
97
98#if defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE)
99__DARWIN_OS_INLINE
100uint32_t
101_OSReadSwapInt32(
102 const volatile void * _base,
103 uintptr_t _offset
104 )
105{
106 return _OSSwapInt32(((struct _OSUnalignedU32 *)((uintptr_t)_base + _offset))->__val);
107}
108#else
109__DARWIN_OS_INLINE
110uint32_t
111OSReadSwapInt32(
112 const volatile void * _base,
113 uintptr_t _offset
114 )
115{
116 return _OSSwapInt32(data: ((struct _OSUnalignedU32 *)((uintptr_t)_base + _offset))->__val);
117}
118#endif
119
120#if defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE)
121__DARWIN_OS_INLINE
122uint64_t
123_OSReadSwapInt64(
124 const volatile void * _base,
125 uintptr_t _offset
126 )
127{
128 return _OSSwapInt64(((struct _OSUnalignedU64 *)((uintptr_t)_base + _offset))->__val);
129}
130#else
131__DARWIN_OS_INLINE
132uint64_t
133OSReadSwapInt64(
134 const volatile void * _base,
135 uintptr_t _offset
136 )
137{
138 return _OSSwapInt64(data: ((struct _OSUnalignedU64 *)((uintptr_t)_base + _offset))->__val);
139}
140#endif
141
142/* Functions for byte reversed stores. */
143
144#if defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE)
145__DARWIN_OS_INLINE
146void
147_OSWriteSwapInt16(
148 volatile void * _base,
149 uintptr_t _offset,
150 uint16_t _data
151 )
152{
153 ((struct _OSUnalignedU16 *)((uintptr_t)_base + _offset))->__val = _OSSwapInt16(_data);
154}
155#else
156__DARWIN_OS_INLINE
157void
158OSWriteSwapInt16(
159 volatile void * _base,
160 uintptr_t _offset,
161 uint16_t _data
162 )
163{
164 ((struct _OSUnalignedU16 *)((uintptr_t)_base + _offset))->__val = _OSSwapInt16(_data);
165}
166#endif
167
168#if defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE)
169__DARWIN_OS_INLINE
170void
171_OSWriteSwapInt32(
172 volatile void * _base,
173 uintptr_t _offset,
174 uint32_t _data
175 )
176{
177 ((struct _OSUnalignedU32 *)((uintptr_t)_base + _offset))->__val = _OSSwapInt32(_data);
178}
179#else
180__DARWIN_OS_INLINE
181void
182OSWriteSwapInt32(
183 volatile void * _base,
184 uintptr_t _offset,
185 uint32_t _data
186 )
187{
188 ((struct _OSUnalignedU32 *)((uintptr_t)_base + _offset))->__val = _OSSwapInt32(_data);
189}
190#endif
191
192#if defined(_POSIX_C_SOURCE) || defined(_XOPEN_SOURCE)
193__DARWIN_OS_INLINE
194void
195_OSWriteSwapInt64(
196 volatile void * _base,
197 uintptr_t _offset,
198 uint64_t _data
199 )
200{
201 ((struct _OSUnalignedU64 *)((uintptr_t)_base + _offset))->__val = _OSSwapInt64(_data);
202}
203#else
204__DARWIN_OS_INLINE
205void
206OSWriteSwapInt64(
207 volatile void * _base,
208 uintptr_t _offset,
209 uint64_t _data
210 )
211{
212 ((struct _OSUnalignedU64 *)((uintptr_t)_base + _offset))->__val = _OSSwapInt64(_data);
213}
214#endif
215
216#endif /* ! _OS_OSBYTEORDERARM_H */
217