msvc.mak: (hopefully) make external dependencies work with NMAKE
[nasm.git] / include / bytesex.h
blobee20adff484007feedc502daea8826fd8c5e8842
1 /* ----------------------------------------------------------------------- *
3 * Copyright 1996-2017 The NASM Authors - All Rights Reserved
4 * See the file AUTHORS included with the NASM distribution for
5 * the specific copyright holders.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following
9 * conditions are met:
11 * * Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * * Redistributions in binary form must reproduce the above
14 * copyright notice, this list of conditions and the following
15 * disclaimer in the documentation and/or other materials provided
16 * with the distribution.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
19 * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
20 * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
21 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
22 * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
23 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
24 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
26 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
29 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
30 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * ----------------------------------------------------------------------- */
35 * bytesex.h - byte order helper functions
37 * In this function, be careful about getting X86_MEMORY versus
38 * LITTLE_ENDIAN correct: X86_MEMORY also means we are allowed to
39 * do unaligned memory references, and is probabilistic.
42 #ifndef NASM_BYTEORD_H
43 #define NASM_BYTEORD_H
45 #include "compiler.h"
48 * Some handy macros that will probably be of use in more than one
49 * output format: convert integers into little-endian byte packed
50 * format in memory.
53 #if X86_MEMORY
55 #define WRITECHAR(p,v) \
56 do { \
57 *(uint8_t *)(p) = (v); \
58 (p) += 1; \
59 } while (0)
61 #define WRITESHORT(p,v) \
62 do { \
63 *(uint16_t *)(p) = (v); \
64 (p) += 2; \
65 } while (0)
67 #define WRITELONG(p,v) \
68 do { \
69 *(uint32_t *)(p) = (v); \
70 (p) += 4; \
71 } while (0)
73 #define WRITEDLONG(p,v) \
74 do { \
75 *(uint64_t *)(p) = (v); \
76 (p) += 8; \
77 } while (0)
79 #define WRITEADDR(p,v,s) \
80 do { \
81 uint64_t _wa_v = (v); \
82 memcpy((p), &_wa_v, (s)); \
83 (p) += (s); \
84 } while (0)
86 #else /* !X86_MEMORY */
88 #define WRITECHAR(p,v) \
89 do { \
90 uint8_t *_wc_p = (uint8_t *)(p); \
91 uint8_t _wc_v = (v); \
92 _wc_p[0] = _wc_v; \
93 (p) = (void *)(_wc_p + 1); \
94 } while (0)
96 #define WRITESHORT(p,v) \
97 do { \
98 uint8_t *_ws_p = (uint8_t *)(p); \
99 uint16_t _ws_v = (v); \
100 _ws_p[0] = _ws_v; \
101 _ws_p[1] = _ws_v >> 8; \
102 (p) = (void *)(_ws_p + 2); \
103 } while (0)
105 #define WRITELONG(p,v) \
106 do { \
107 uint8_t *_wl_p = (uint8_t *)(p); \
108 uint32_t _wl_v = (v); \
109 _wl_p[0] = _wl_v; \
110 _wl_p[1] = _wl_v >> 8; \
111 _wl_p[2] = _wl_v >> 16; \
112 _wl_p[3] = _wl_v >> 24; \
113 (p) = (void *)(_wl_p + 4); \
114 } while (0)
116 #define WRITEDLONG(p,v) \
117 do { \
118 uint8_t *_wq_p = (uint8_t *)(p); \
119 uint64_t _wq_v = (v); \
120 _wq_p[0] = _wq_v; \
121 _wq_p[1] = _wq_v >> 8; \
122 _wq_p[2] = _wq_v >> 16; \
123 _wq_p[3] = _wq_v >> 24; \
124 _wq_p[4] = _wq_v >> 32; \
125 _wq_p[5] = _wq_v >> 40; \
126 _wq_p[6] = _wq_v >> 48; \
127 _wq_p[7] = _wq_v >> 56; \
128 (p) = (void *)(_wq_p + 8); \
129 } while (0)
131 #define WRITEADDR(p,v,s) \
132 do { \
133 int _wa_s = (s); \
134 uint64_t _wa_v = (v); \
135 while (_wa_s--) { \
136 WRITECHAR(p,_wa_v); \
137 _wa_v >>= 8; \
139 } while(0)
141 #endif
145 * Endian control functions which work on a single integer
147 #ifdef WORDS_LITTLEENDIAN
149 #ifndef HAVE_CPU_TO_LE16
150 static inline uint16_t cpu_to_le16(uint16_t v) { return v; }
151 #endif
152 #ifndef HAVE_CPU_TO_LE32
153 static inline uint32_t cpu_to_le32(uint32_t v) { return v; }
154 #endif
155 #ifndef HAVE_CPU_TO_LE64
156 static inline uint64_t cpu_to_le64(uint64_t v) { return v; }
157 #endif
159 #elif defined(WORDS_BIGENDIAN)
161 #ifndef HAVE_CPU_TO_LE16
162 static inline uint16_t cpu_to_le16(uint16_t v)
164 # ifdef HAVE___CPU_TO_LE16
165 return __cpu_to_le16(v);
166 # elif defined(HAVE_HTOLE16)
167 return htole16(v);
168 # elif defined(HAVE___BSWAP_16)
169 return __bswap_16(v);
170 # elif defined(HAVE___BUILTIN_BSWAP16)
171 return __builtin_bswap16(v);
172 # elif defined(HAVE__BYTESWAP_USHORT) && (USHRT_MAX == 0xffffU)
173 return _byteswap_ushort(v);
174 # else
175 return (v << 8) | (v >> 8);
176 # endif
178 #endif
180 #ifndef HAVE_CPU_TO_LE32
181 static inline uint32_t cpu_to_le32(uint32_t v)
183 # ifdef HAVE___CPU_TO_LE32
184 return __cpu_to_le32(v);
185 # elif defined(HAVE_HTOLE32)
186 return htole32(v);
187 # elif defined(HAVE___BSWAP_32)
188 return __bswap_32(v);
189 # elif defined(HAVE___BUILTIN_BSWAP32)
190 return __builtin_bswap32(v);
191 # elif defined(HAVE__BYTESWAP_ULONG) && (ULONG_MAX == 0xffffffffUL)
192 return _byteswap_ulong(v);
193 # else
194 v = ((v << 8) & 0xff00ff00 ) |
195 ((v >> 8) & 0x00ff00ff);
196 return (v << 16) | (v >> 16);
197 # endif
199 #endif
201 #ifndef HAVE_CPU_TO_LE64
202 static inline uint64_t cpu_to_le64(uint64_t v)
204 # ifdef HAVE___CPU_TO_LE64
205 return __cpu_to_le64(v);
206 # elif defined(HAVE_HTOLE64)
207 return htole64(v);
208 # elif defined(HAVE___BSWAP_64)
209 return __bswap_64(v);
210 # elif defined(HAVE___BUILTIN_BSWAP64)
211 return __builtin_bswap64(v);
212 # elif defined(HAVE__BYTESWAP_UINT64)
213 return _byteswap_uint64(v);
214 # else
215 v = ((v << 8) & 0xff00ff00ff00ff00ull) |
216 ((v >> 8) & 0x00ff00ff00ff00ffull);
217 v = ((v << 16) & 0xffff0000ffff0000ull) |
218 ((v >> 16) & 0x0000ffff0000ffffull);
219 return (v << 32) | (v >> 32);
220 # endif
222 #endif
224 #else /* not WORDS_LITTLEENDIAN or WORDS_BIGENDIAN */
226 static inline uint16_t cpu_to_le16(uint16_t v)
228 union u16 {
229 uint16_t v;
230 uint8_t c[2];
231 } x;
232 uint8_t *cp = &x.c;
234 WRITESHORT(cp, v);
235 return x.v;
238 static inline uint32_t cpu_to_le32(uint32_t v)
240 union u32 {
241 uint32_t v;
242 uint8_t c[4];
243 } x;
244 uint8_t *cp = &x.c;
246 WRITELONG(cp, v);
247 return x.v;
250 static inline uint64_t cpu_to_le64(uint64_t v)
252 union u64 {
253 uint64_t v;
254 uint8_t c[8];
255 } x;
256 uint8_t *cp = &x.c;
258 WRITEDLONG(cp, v);
259 return x.v;
262 #endif
264 #endif /* NASM_BYTESEX_H */