1 /*---------------------------------------------------------------------------*
2 Project: TwlSDK - MI - include
3 File: endian.h
4
5 Copyright 2006-2008 Nintendo. All rights reserved.
6
7 These coded instructions, statements, and computer programs contain
8 proprietary information of Nintendo of America Inc. and/or Nintendo
9 Company Ltd., and are protected by Federal copyright law. They may
10 not be disclosed to third parties or copied or duplicated in any form,
11 in whole or in part, without the prior written consent of Nintendo.
12
13 $Date:: 2008-09-18#$
14 $Rev: 8573 $
15 $Author: okubata_ryoma $
16 *---------------------------------------------------------------------------*/
17
18 #ifndef NITRO_MI_ENDIAN_H_
19 #define NITRO_MI_ENDIAN_H_
20
21 #ifdef __cplusplus
22 extern "C" {
23 #endif
24
25 #include <nitro/misc.h>
26 #include <nitro/types.h>
27 #include <nitro/platform.h>
28
29
30 /*****************************************************************************/
31 /* Functions */
32
33 /*---------------------------------------------------------------------------*
34 Name: MI_SwapEndian8
35
36 Description: A macro to convert a 8-bit value's endian type.
37 This will actually never perform any conversions.
38
39 Arguments: val the value for which to convert the endian type
40
41 Returns: The value for which the endian type has been converted
42 *---------------------------------------------------------------------------*/
43 #define MI_SwapEndian8(val) (u8)(val)
44
45 /*---------------------------------------------------------------------------*
46 Name: MI_SwapEndian16
47
48 Description: A macro to convert a 16-bit value's endian type.
49 Although this can be used for constants, be aware that the arguments will be evaluated multiple times.
50
51 Arguments: val the value for which to convert the endian type
52
53 Returns: The value for which the endian type has been converted
54 *---------------------------------------------------------------------------*/
55 #define MI_SwapEndian16(val) (u16)( \
56 (((val) & 0xFF00UL) >> 8UL) | \
57 (((val) & 0x00FFUL) << 8UL))
58
59 /*---------------------------------------------------------------------------*
60 Name: MI_SwapEndian32
61
62 Description: A macro to convert a 32-bit value's endian type.
63 Although this can be used for constants, be aware that the arguments will be evaluated multiple times.
64
65 Arguments: val the value for which to convert the endian type
66
67 Returns: The value for which the endian type has been converted
68 *---------------------------------------------------------------------------*/
69 #define MI_SwapEndian32(val) (u32)( \
70 (((val) & 0xFF000000UL) >> 24UL) | \
71 (((val) & 0x00FF0000UL) >> 8UL) | \
72 (((val) & 0x0000FF00UL) << 8UL) | \
73 (((val) & 0x000000FFUL) << 24UL))
74
75 /*---------------------------------------------------------------------------*
76 Name: MI_SwapEndian64
77
78 Description: A macro to convert a 64-bit value's endian type.
79 Although this can be used for constants, be aware that the arguments will be evaluated multiple times.
80
81 Arguments: val the value for which to convert the endian type
82
83 Returns: The value for which the endian type has been converted
84 *---------------------------------------------------------------------------*/
85 #define MI_SwapEndian64(val) (u64)( \
86 (((val) & 0xFF00000000000000ULL) >> 56ULL) \
87 | (((val) & 0x00FF000000000000ULL) >> 40ULL) \
88 | (((val) & 0x0000FF0000000000ULL) >> 24ULL) \
89 | (((val) & 0x000000FF00000000ULL) >> 8ULL) \
90 | (((val) & 0x00000000FF000000ULL) << 8ULL) \
91 | (((val) & 0x0000000000FF0000ULL) << 24ULL) \
92 | (((val) & 0x000000000000FF00ULL) << 40ULL) \
93 | (((val) & 0x00000000000000FFULL) << 56ULL) )
94
95 #if (PLATFORM_BYTES_ENDIAN == PLATFORM_ENDIAN_LITTLE)
96 #define MIi_SwapEndian8IfLE(val) MI_SwapEndian8(val)
97 #define MIi_SwapEndian16IfLE(val) MI_SwapEndian16(val)
98 #define MIi_SwapEndian32IfLE(val) MI_SwapEndian32(val)
99 #define MIi_SwapEndian64IfLE(val) MI_SwapEndian64(val)
100 #define MIi_SwapEndian8IfBE(val) (val)
101 #define MIi_SwapEndian16IfBE(val) (val)
102 #define MIi_SwapEndian32IfBE(val) (val)
103 #define MIi_SwapEndian64IfBE(val) (val)
104 #else
105 #define MIi_SwapEndian8IfLE(val) (val)
106 #define MIi_SwapEndian16IfLE(val) (val)
107 #define MIi_SwapEndian32IfLE(val) (val)
108 #define MIi_SwapEndian64IfLE(val) (val)
109 #define MIi_SwapEndian8IfBE(val) MI_SwapEndian8(val)
110 #define MIi_SwapEndian16IfBE(val) MI_SwapEndian16(val)
111 #define MIi_SwapEndian32IfBE(val) MI_SwapEndian32(val)
112 #define MIi_SwapEndian64IfBE(val) MI_SwapEndian64(val)
113 #endif
114
115 /*---------------------------------------------------------------------------*
116 Name: MI_HTo*
117
118 Description: Value conversion from current environment to specified endian type.
119 As the Nintendo DS uses a little-endian environment, conversion takes place with a do-nothing macro for *HToLe*.
120
121 Although this can be used for constants, be aware that the arguments will be evaluated multiple times.
122
123 Arguments: val the value for which to convert the endian type
124
125 Returns: The value converted to the specified endian type.
126 *---------------------------------------------------------------------------*/
127 #define MI_HToLE8(val) MIi_SwapEndian8IfBE(val)
128 #define MI_HToBE8(val) MIi_SwapEndian8IfLE(val)
129 #define MI_HToLE16(val) MIi_SwapEndian16IfBE(val)
130 #define MI_HToBE16(val) MIi_SwapEndian16IfLE(val)
131 #define MI_HToLE32(val) MIi_SwapEndian32IfBE(val)
132 #define MI_HToBE32(val) MIi_SwapEndian32IfLE(val)
133 #define MI_HToBE64(val) MIi_SwapEndian64IfLE(val)
134
135 /*---------------------------------------------------------------------------*
136 Name: MI_*ToH*
137
138 Description: Value conversion from the specified endian type to the current environment.
139 As the Nintendo DS uses a little-endian environment, conversion takes place with a do-nothing macro for *LeToH*.
140
141 Although this can be used for constants, be aware that the arguments will be evaluated multiple times.
142
143 Arguments: val the value for which to convert the endian type
144
145 Returns: The value converted from the specified endian type.
146 *---------------------------------------------------------------------------*/
147 #define MI_LEToH8(val) MIi_SwapEndian8IfBE(val)
148 #define MI_BEToH8(val) MIi_SwapEndian8IfLE(val)
149 #define MI_LEToH16(val) MIi_SwapEndian16IfBE(val)
150 #define MI_BEToH16(val) MIi_SwapEndian16IfLE(val)
151 #define MI_LEToH32(val) MIi_SwapEndian32IfBE(val)
152 #define MI_BEToH32(val) MIi_SwapEndian32IfLE(val)
153 #define MI_BEToH64(val) MIi_SwapEndian64IfLE(val)
154
155 /*---------------------------------------------------------------------------*
156 Name: MI_LoadLE*
157
158 Description: Gets the little-endian value from the specified address.
159 The content of this function is not dependent on the current environment's endian type.
160
161 Arguments: ptr The data address read in as little-endian.
162 You don't need to worry about alignment.
163
164 Returns: The value of the specified bit width gotten in little-endian.
165 *---------------------------------------------------------------------------*/
MI_LoadLE8(const void * ptr)166 SDK_INLINE u8 MI_LoadLE8(const void *ptr)
167 {
168 const u8 *src = (const u8 *)ptr;
169 return (u8)((src[0] << 0UL));
170 }
MI_LoadLE16(const void * ptr)171 SDK_INLINE u16 MI_LoadLE16(const void *ptr)
172 {
173 const u8 *src = (const u8 *)ptr;
174 return (u16)((src[0] << 0UL) | (src[1] << 8UL));
175 }
MI_LoadLE32(const void * ptr)176 SDK_INLINE u32 MI_LoadLE32(const void *ptr)
177 {
178 const u8 *src = (const u8 *)ptr;
179 return (u32)((src[0] << 0UL) | (src[1] << 8UL) | (src[2] << 16UL) | (src[3] << 24UL));
180 }
MI_LoadLE64(const void * ptr)181 SDK_INLINE u64 MI_LoadLE64(const void *ptr)
182 {
183 const u8 *src = (const u8 *)ptr;
184 return ((u64)MI_LoadLE32(src + 4) << 32) | (u64)MI_LoadLE32(src);
185 }
186
187 /*---------------------------------------------------------------------------*
188 Name: MI_LoadBE*
189
190 Description: Gets the big-endian value from the specified address.
191 The content of this function is not dependent on the current environment's endian type.
192
193 Arguments: ptr The data address read in as big-endian.
194 You don't need to worry about alignment.
195
196 Returns: The value of the specified bit width gotten in big-endian.
197 *---------------------------------------------------------------------------*/
MI_LoadBE8(const void * ptr)198 SDK_INLINE u8 MI_LoadBE8(const void *ptr)
199 {
200 const u8 *src = (const u8 *)ptr;
201 return (u8)((src[0] << 0UL));
202 }
MI_LoadBE16(const void * ptr)203 SDK_INLINE u16 MI_LoadBE16(const void *ptr)
204 {
205 const u8 *src = (const u8 *)ptr;
206 return (u16)((src[0] << 8UL) | (src[1] << 0UL));
207 }
MI_LoadBE32(const void * ptr)208 SDK_INLINE u32 MI_LoadBE32(const void *ptr)
209 {
210 const u8 *src = (const u8 *)ptr;
211 return (u32)((src[0] << 24UL) | (src[1] << 16UL) | (src[2] << 8UL) | (src[3] << 0UL));
212 }
MI_LoadBE64(const void * ptr)213 SDK_INLINE u64 MI_LoadBE64(const void *ptr)
214 {
215 const u8 *src = (const u8 *)ptr;
216 return ((u64)MI_LoadLE32(src) << 32) | (u64)MI_LoadLE32(src + 4);
217 }
218
219 /*---------------------------------------------------------------------------*
220 Name: MI_StoreLE*
221
222 Description: Stores the little-endian value at the specified address.
223 The content of this function is not dependent on the current environment's endian type.
224
225 Arguments: ptr The data address written as little-endian.
226 You don't need to worry about alignment.
227 val The value to be written
228
229 Returns: None.
230 *---------------------------------------------------------------------------*/
MI_StoreLE8(void * ptr,u8 val)231 SDK_INLINE void MI_StoreLE8(void *ptr, u8 val)
232 {
233 u8 *src = (u8 *)ptr;
234 src[0] = (u8)(val >> 0UL);
235 }
MI_StoreLE16(void * ptr,u16 val)236 SDK_INLINE void MI_StoreLE16(void *ptr, u16 val)
237 {
238 u8 *src = (u8 *)ptr;
239 src[0] = (u8)(val >> 0UL);
240 src[1] = (u8)(val >> 8UL);
241 }
MI_StoreLE32(void * ptr,u32 val)242 SDK_INLINE void MI_StoreLE32(void *ptr, u32 val)
243 {
244 u8 *src = (u8 *)ptr;
245 src[0] = (u8)(val >> 0UL);
246 src[1] = (u8)(val >> 8UL);
247 src[2] = (u8)(val >> 16UL);
248 src[3] = (u8)(val >> 24UL);
249 }
MI_StoreLE64(void * ptr,u64 val)250 SDK_INLINE void MI_StoreLE64(void *ptr, u64 val)
251 {
252 u8 *src = (u8 *)ptr;
253 MI_StoreLE32(src, (u32)(val >> 0));
254 MI_StoreLE32(src + 4, (u32)(val >> 32));
255 }
256
257 /*---------------------------------------------------------------------------*
258 Name: MI_StoreBE*
259
260 Description: Stores the big-endian value at the specified address.
261 The content of this function is not dependent on the current environment's endian type.
262
263 Arguments: ptr The data address written as big-endian.
264 You don't need to worry about alignment.
265 val The value to be written
266
267 Returns: None.
268 *---------------------------------------------------------------------------*/
MI_StoreBE8(void * ptr,u8 val)269 SDK_INLINE void MI_StoreBE8(void *ptr, u8 val)
270 {
271 u8 *src = (u8 *)ptr;
272 src[0] = (u8)(val >> 0UL);
273 }
MI_StoreBE16(void * ptr,u16 val)274 SDK_INLINE void MI_StoreBE16(void *ptr, u16 val)
275 {
276 u8 *src = (u8 *)ptr;
277 src[0] = (u8)(val >> 8UL);
278 src[1] = (u8)(val >> 0UL);
279 }
MI_StoreBE32(void * ptr,u32 val)280 SDK_INLINE void MI_StoreBE32(void *ptr, u32 val)
281 {
282 u8 *src = (u8 *)ptr;
283 src[0] = (u8)(val >> 24UL);
284 src[1] = (u8)(val >> 16UL);
285 src[2] = (u8)(val >> 8UL);
286 src[3] = (u8)(val >> 0UL);
287 }
MI_StoreBE64(void * ptr,u64 val)288 SDK_INLINE void MI_StoreBE64(void *ptr, u64 val)
289 {
290 u8 *src = (u8 *)ptr;
291 MI_StoreLE32(src, (u32)(val >> 32));
292 MI_StoreLE32(src + 4, (u32)(val >> 0));
293 }
294
295
296 #ifdef __cplusplus
297 } /* extern "C" */
298 #endif
299
300 /* NITRO_MI_ENDIAN_H_ */
301 #endif
302