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