1 | #ifndef BSWAP_H |
2 | #define BSWAP_H |
3 | |
4 | #include "fpu/softfloat-types.h" |
5 | |
6 | #ifdef CONFIG_MACHINE_BSWAP_H |
7 | # include <sys/endian.h> |
8 | # include <machine/bswap.h> |
9 | #elif defined(__FreeBSD__) |
10 | # include <sys/endian.h> |
11 | #elif defined(CONFIG_BYTESWAP_H) |
12 | # include <byteswap.h> |
13 | |
14 | static inline uint16_t bswap16(uint16_t x) |
15 | { |
16 | return bswap_16(x); |
17 | } |
18 | |
19 | static inline uint32_t bswap32(uint32_t x) |
20 | { |
21 | return bswap_32(x); |
22 | } |
23 | |
24 | static inline uint64_t bswap64(uint64_t x) |
25 | { |
26 | return bswap_64(x); |
27 | } |
28 | # else |
29 | static inline uint16_t bswap16(uint16_t x) |
30 | { |
31 | return (((x & 0x00ff) << 8) | |
32 | ((x & 0xff00) >> 8)); |
33 | } |
34 | |
35 | static inline uint32_t bswap32(uint32_t x) |
36 | { |
37 | return (((x & 0x000000ffU) << 24) | |
38 | ((x & 0x0000ff00U) << 8) | |
39 | ((x & 0x00ff0000U) >> 8) | |
40 | ((x & 0xff000000U) >> 24)); |
41 | } |
42 | |
43 | static inline uint64_t bswap64(uint64_t x) |
44 | { |
45 | return (((x & 0x00000000000000ffULL) << 56) | |
46 | ((x & 0x000000000000ff00ULL) << 40) | |
47 | ((x & 0x0000000000ff0000ULL) << 24) | |
48 | ((x & 0x00000000ff000000ULL) << 8) | |
49 | ((x & 0x000000ff00000000ULL) >> 8) | |
50 | ((x & 0x0000ff0000000000ULL) >> 24) | |
51 | ((x & 0x00ff000000000000ULL) >> 40) | |
52 | ((x & 0xff00000000000000ULL) >> 56)); |
53 | } |
54 | #endif /* ! CONFIG_MACHINE_BSWAP_H */ |
55 | |
56 | static inline void bswap16s(uint16_t *s) |
57 | { |
58 | *s = bswap16(*s); |
59 | } |
60 | |
61 | static inline void bswap32s(uint32_t *s) |
62 | { |
63 | *s = bswap32(*s); |
64 | } |
65 | |
66 | static inline void bswap64s(uint64_t *s) |
67 | { |
68 | *s = bswap64(*s); |
69 | } |
70 | |
71 | #if defined(HOST_WORDS_BIGENDIAN) |
72 | #define be_bswap(v, size) (v) |
73 | #define le_bswap(v, size) glue(bswap, size)(v) |
74 | #define be_bswaps(v, size) |
75 | #define le_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0) |
76 | #else |
77 | #define le_bswap(v, size) (v) |
78 | #define be_bswap(v, size) glue(bswap, size)(v) |
79 | #define le_bswaps(v, size) |
80 | #define be_bswaps(p, size) do { *p = glue(bswap, size)(*p); } while(0) |
81 | #endif |
82 | |
83 | /** |
84 | * Endianness conversion functions between host cpu and specified endianness. |
85 | * (We list the complete set of prototypes produced by the macros below |
86 | * to assist people who search the headers to find their definitions.) |
87 | * |
88 | * uint16_t le16_to_cpu(uint16_t v); |
89 | * uint32_t le32_to_cpu(uint32_t v); |
90 | * uint64_t le64_to_cpu(uint64_t v); |
91 | * uint16_t be16_to_cpu(uint16_t v); |
92 | * uint32_t be32_to_cpu(uint32_t v); |
93 | * uint64_t be64_to_cpu(uint64_t v); |
94 | * |
95 | * Convert the value @v from the specified format to the native |
96 | * endianness of the host CPU by byteswapping if necessary, and |
97 | * return the converted value. |
98 | * |
99 | * uint16_t cpu_to_le16(uint16_t v); |
100 | * uint32_t cpu_to_le32(uint32_t v); |
101 | * uint64_t cpu_to_le64(uint64_t v); |
102 | * uint16_t cpu_to_be16(uint16_t v); |
103 | * uint32_t cpu_to_be32(uint32_t v); |
104 | * uint64_t cpu_to_be64(uint64_t v); |
105 | * |
106 | * Convert the value @v from the native endianness of the host CPU to |
107 | * the specified format by byteswapping if necessary, and return |
108 | * the converted value. |
109 | * |
110 | * void le16_to_cpus(uint16_t *v); |
111 | * void le32_to_cpus(uint32_t *v); |
112 | * void le64_to_cpus(uint64_t *v); |
113 | * void be16_to_cpus(uint16_t *v); |
114 | * void be32_to_cpus(uint32_t *v); |
115 | * void be64_to_cpus(uint64_t *v); |
116 | * |
117 | * Do an in-place conversion of the value pointed to by @v from the |
118 | * specified format to the native endianness of the host CPU. |
119 | * |
120 | * void cpu_to_le16s(uint16_t *v); |
121 | * void cpu_to_le32s(uint32_t *v); |
122 | * void cpu_to_le64s(uint64_t *v); |
123 | * void cpu_to_be16s(uint16_t *v); |
124 | * void cpu_to_be32s(uint32_t *v); |
125 | * void cpu_to_be64s(uint64_t *v); |
126 | * |
127 | * Do an in-place conversion of the value pointed to by @v from the |
128 | * native endianness of the host CPU to the specified format. |
129 | * |
130 | * Both X_to_cpu() and cpu_to_X() perform the same operation; you |
131 | * should use whichever one is better documenting of the function your |
132 | * code is performing. |
133 | * |
134 | * Do not use these functions for conversion of values which are in guest |
135 | * memory, since the data may not be sufficiently aligned for the host CPU's |
136 | * load and store instructions. Instead you should use the ld*_p() and |
137 | * st*_p() functions, which perform loads and stores of data of any |
138 | * required size and endianness and handle possible misalignment. |
139 | */ |
140 | |
141 | #define CPU_CONVERT(endian, size, type)\ |
142 | static inline type endian ## size ## _to_cpu(type v)\ |
143 | {\ |
144 | return glue(endian, _bswap)(v, size);\ |
145 | }\ |
146 | \ |
147 | static inline type cpu_to_ ## endian ## size(type v)\ |
148 | {\ |
149 | return glue(endian, _bswap)(v, size);\ |
150 | }\ |
151 | \ |
152 | static inline void endian ## size ## _to_cpus(type *p)\ |
153 | {\ |
154 | glue(endian, _bswaps)(p, size);\ |
155 | }\ |
156 | \ |
157 | static inline void cpu_to_ ## endian ## size ## s(type *p)\ |
158 | {\ |
159 | glue(endian, _bswaps)(p, size);\ |
160 | } |
161 | |
162 | CPU_CONVERT(be, 16, uint16_t) |
163 | CPU_CONVERT(be, 32, uint32_t) |
164 | CPU_CONVERT(be, 64, uint64_t) |
165 | |
166 | CPU_CONVERT(le, 16, uint16_t) |
167 | CPU_CONVERT(le, 32, uint32_t) |
168 | CPU_CONVERT(le, 64, uint64_t) |
169 | |
170 | /* len must be one of 1, 2, 4 */ |
171 | static inline uint32_t qemu_bswap_len(uint32_t value, int len) |
172 | { |
173 | return bswap32(value) >> (32 - 8 * len); |
174 | } |
175 | |
176 | /* |
177 | * Same as cpu_to_le{16,32}, except that gcc will figure the result is |
178 | * a compile-time constant if you pass in a constant. So this can be |
179 | * used to initialize static variables. |
180 | */ |
181 | #if defined(HOST_WORDS_BIGENDIAN) |
182 | # define const_le32(_x) \ |
183 | ((((_x) & 0x000000ffU) << 24) | \ |
184 | (((_x) & 0x0000ff00U) << 8) | \ |
185 | (((_x) & 0x00ff0000U) >> 8) | \ |
186 | (((_x) & 0xff000000U) >> 24)) |
187 | # define const_le16(_x) \ |
188 | ((((_x) & 0x00ff) << 8) | \ |
189 | (((_x) & 0xff00) >> 8)) |
190 | #else |
191 | # define const_le32(_x) (_x) |
192 | # define const_le16(_x) (_x) |
193 | #endif |
194 | |
195 | /* Unions for reinterpreting between floats and integers. */ |
196 | |
197 | typedef union { |
198 | float32 f; |
199 | uint32_t l; |
200 | } CPU_FloatU; |
201 | |
202 | typedef union { |
203 | float64 d; |
204 | #if defined(HOST_WORDS_BIGENDIAN) |
205 | struct { |
206 | uint32_t upper; |
207 | uint32_t lower; |
208 | } l; |
209 | #else |
210 | struct { |
211 | uint32_t lower; |
212 | uint32_t upper; |
213 | } l; |
214 | #endif |
215 | uint64_t ll; |
216 | } CPU_DoubleU; |
217 | |
218 | typedef union { |
219 | floatx80 d; |
220 | struct { |
221 | uint64_t lower; |
222 | uint16_t upper; |
223 | } l; |
224 | } CPU_LDoubleU; |
225 | |
226 | typedef union { |
227 | float128 q; |
228 | #if defined(HOST_WORDS_BIGENDIAN) |
229 | struct { |
230 | uint32_t upmost; |
231 | uint32_t upper; |
232 | uint32_t lower; |
233 | uint32_t lowest; |
234 | } l; |
235 | struct { |
236 | uint64_t upper; |
237 | uint64_t lower; |
238 | } ll; |
239 | #else |
240 | struct { |
241 | uint32_t lowest; |
242 | uint32_t lower; |
243 | uint32_t upper; |
244 | uint32_t upmost; |
245 | } l; |
246 | struct { |
247 | uint64_t lower; |
248 | uint64_t upper; |
249 | } ll; |
250 | #endif |
251 | } CPU_QuadU; |
252 | |
253 | /* unaligned/endian-independent pointer access */ |
254 | |
255 | /* |
256 | * the generic syntax is: |
257 | * |
258 | * load: ld{type}{sign}{size}_{endian}_p(ptr) |
259 | * |
260 | * store: st{type}{size}_{endian}_p(ptr, val) |
261 | * |
262 | * Note there are small differences with the softmmu access API! |
263 | * |
264 | * type is: |
265 | * (empty): integer access |
266 | * f : float access |
267 | * |
268 | * sign is: |
269 | * (empty): for 32 or 64 bit sizes (including floats and doubles) |
270 | * u : unsigned |
271 | * s : signed |
272 | * |
273 | * size is: |
274 | * b: 8 bits |
275 | * w: 16 bits |
276 | * l: 32 bits |
277 | * q: 64 bits |
278 | * |
279 | * endian is: |
280 | * he : host endian |
281 | * be : big endian |
282 | * le : little endian |
283 | * te : target endian |
284 | * (except for byte accesses, which have no endian infix). |
285 | * |
286 | * The target endian accessors are obviously only available to source |
287 | * files which are built per-target; they are defined in cpu-all.h. |
288 | * |
289 | * In all cases these functions take a host pointer. |
290 | * For accessors that take a guest address rather than a |
291 | * host address, see the cpu_{ld,st}_* accessors defined in |
292 | * cpu_ldst.h. |
293 | * |
294 | * For cases where the size to be used is not fixed at compile time, |
295 | * there are |
296 | * stn_{endian}_p(ptr, sz, val) |
297 | * which stores @val to @ptr as an @endian-order number @sz bytes in size |
298 | * and |
299 | * ldn_{endian}_p(ptr, sz) |
300 | * which loads @sz bytes from @ptr as an unsigned @endian-order number |
301 | * and returns it in a uint64_t. |
302 | */ |
303 | |
304 | static inline int ldub_p(const void *ptr) |
305 | { |
306 | return *(uint8_t *)ptr; |
307 | } |
308 | |
309 | static inline int ldsb_p(const void *ptr) |
310 | { |
311 | return *(int8_t *)ptr; |
312 | } |
313 | |
314 | static inline void stb_p(void *ptr, uint8_t v) |
315 | { |
316 | *(uint8_t *)ptr = v; |
317 | } |
318 | |
319 | /* |
320 | * Any compiler worth its salt will turn these memcpy into native unaligned |
321 | * operations. Thus we don't need to play games with packed attributes, or |
322 | * inline byte-by-byte stores. |
323 | * Some compilation environments (eg some fortify-source implementations) |
324 | * may intercept memcpy() in a way that defeats the compiler optimization, |
325 | * though, so we use __builtin_memcpy() to give ourselves the best chance |
326 | * of good performance. |
327 | */ |
328 | |
329 | static inline int lduw_he_p(const void *ptr) |
330 | { |
331 | uint16_t r; |
332 | __builtin_memcpy(&r, ptr, sizeof(r)); |
333 | return r; |
334 | } |
335 | |
336 | static inline int ldsw_he_p(const void *ptr) |
337 | { |
338 | int16_t r; |
339 | __builtin_memcpy(&r, ptr, sizeof(r)); |
340 | return r; |
341 | } |
342 | |
343 | static inline void stw_he_p(void *ptr, uint16_t v) |
344 | { |
345 | __builtin_memcpy(ptr, &v, sizeof(v)); |
346 | } |
347 | |
348 | static inline int ldl_he_p(const void *ptr) |
349 | { |
350 | int32_t r; |
351 | __builtin_memcpy(&r, ptr, sizeof(r)); |
352 | return r; |
353 | } |
354 | |
355 | static inline void stl_he_p(void *ptr, uint32_t v) |
356 | { |
357 | __builtin_memcpy(ptr, &v, sizeof(v)); |
358 | } |
359 | |
360 | static inline uint64_t ldq_he_p(const void *ptr) |
361 | { |
362 | uint64_t r; |
363 | __builtin_memcpy(&r, ptr, sizeof(r)); |
364 | return r; |
365 | } |
366 | |
367 | static inline void stq_he_p(void *ptr, uint64_t v) |
368 | { |
369 | __builtin_memcpy(ptr, &v, sizeof(v)); |
370 | } |
371 | |
372 | static inline int lduw_le_p(const void *ptr) |
373 | { |
374 | return (uint16_t)le_bswap(lduw_he_p(ptr), 16); |
375 | } |
376 | |
377 | static inline int ldsw_le_p(const void *ptr) |
378 | { |
379 | return (int16_t)le_bswap(lduw_he_p(ptr), 16); |
380 | } |
381 | |
382 | static inline int ldl_le_p(const void *ptr) |
383 | { |
384 | return le_bswap(ldl_he_p(ptr), 32); |
385 | } |
386 | |
387 | static inline uint64_t ldq_le_p(const void *ptr) |
388 | { |
389 | return le_bswap(ldq_he_p(ptr), 64); |
390 | } |
391 | |
392 | static inline void stw_le_p(void *ptr, uint16_t v) |
393 | { |
394 | stw_he_p(ptr, le_bswap(v, 16)); |
395 | } |
396 | |
397 | static inline void stl_le_p(void *ptr, uint32_t v) |
398 | { |
399 | stl_he_p(ptr, le_bswap(v, 32)); |
400 | } |
401 | |
402 | static inline void stq_le_p(void *ptr, uint64_t v) |
403 | { |
404 | stq_he_p(ptr, le_bswap(v, 64)); |
405 | } |
406 | |
407 | /* float access */ |
408 | |
409 | static inline float32 ldfl_le_p(const void *ptr) |
410 | { |
411 | CPU_FloatU u; |
412 | u.l = ldl_le_p(ptr); |
413 | return u.f; |
414 | } |
415 | |
416 | static inline void stfl_le_p(void *ptr, float32 v) |
417 | { |
418 | CPU_FloatU u; |
419 | u.f = v; |
420 | stl_le_p(ptr, u.l); |
421 | } |
422 | |
423 | static inline float64 ldfq_le_p(const void *ptr) |
424 | { |
425 | CPU_DoubleU u; |
426 | u.ll = ldq_le_p(ptr); |
427 | return u.d; |
428 | } |
429 | |
430 | static inline void stfq_le_p(void *ptr, float64 v) |
431 | { |
432 | CPU_DoubleU u; |
433 | u.d = v; |
434 | stq_le_p(ptr, u.ll); |
435 | } |
436 | |
437 | static inline int lduw_be_p(const void *ptr) |
438 | { |
439 | return (uint16_t)be_bswap(lduw_he_p(ptr), 16); |
440 | } |
441 | |
442 | static inline int ldsw_be_p(const void *ptr) |
443 | { |
444 | return (int16_t)be_bswap(lduw_he_p(ptr), 16); |
445 | } |
446 | |
447 | static inline int ldl_be_p(const void *ptr) |
448 | { |
449 | return be_bswap(ldl_he_p(ptr), 32); |
450 | } |
451 | |
452 | static inline uint64_t ldq_be_p(const void *ptr) |
453 | { |
454 | return be_bswap(ldq_he_p(ptr), 64); |
455 | } |
456 | |
457 | static inline void stw_be_p(void *ptr, uint16_t v) |
458 | { |
459 | stw_he_p(ptr, be_bswap(v, 16)); |
460 | } |
461 | |
462 | static inline void stl_be_p(void *ptr, uint32_t v) |
463 | { |
464 | stl_he_p(ptr, be_bswap(v, 32)); |
465 | } |
466 | |
467 | static inline void stq_be_p(void *ptr, uint64_t v) |
468 | { |
469 | stq_he_p(ptr, be_bswap(v, 64)); |
470 | } |
471 | |
472 | /* float access */ |
473 | |
474 | static inline float32 ldfl_be_p(const void *ptr) |
475 | { |
476 | CPU_FloatU u; |
477 | u.l = ldl_be_p(ptr); |
478 | return u.f; |
479 | } |
480 | |
481 | static inline void stfl_be_p(void *ptr, float32 v) |
482 | { |
483 | CPU_FloatU u; |
484 | u.f = v; |
485 | stl_be_p(ptr, u.l); |
486 | } |
487 | |
488 | static inline float64 ldfq_be_p(const void *ptr) |
489 | { |
490 | CPU_DoubleU u; |
491 | u.ll = ldq_be_p(ptr); |
492 | return u.d; |
493 | } |
494 | |
495 | static inline void stfq_be_p(void *ptr, float64 v) |
496 | { |
497 | CPU_DoubleU u; |
498 | u.d = v; |
499 | stq_be_p(ptr, u.ll); |
500 | } |
501 | |
502 | static inline unsigned long leul_to_cpu(unsigned long v) |
503 | { |
504 | #if HOST_LONG_BITS == 32 |
505 | return le_bswap(v, 32); |
506 | #elif HOST_LONG_BITS == 64 |
507 | return le_bswap(v, 64); |
508 | #else |
509 | # error Unknown sizeof long |
510 | #endif |
511 | } |
512 | |
513 | /* Store v to p as a sz byte value in host order */ |
514 | #define DO_STN_LDN_P(END) \ |
515 | static inline void stn_## END ## _p(void *ptr, int sz, uint64_t v) \ |
516 | { \ |
517 | switch (sz) { \ |
518 | case 1: \ |
519 | stb_p(ptr, v); \ |
520 | break; \ |
521 | case 2: \ |
522 | stw_ ## END ## _p(ptr, v); \ |
523 | break; \ |
524 | case 4: \ |
525 | stl_ ## END ## _p(ptr, v); \ |
526 | break; \ |
527 | case 8: \ |
528 | stq_ ## END ## _p(ptr, v); \ |
529 | break; \ |
530 | default: \ |
531 | g_assert_not_reached(); \ |
532 | } \ |
533 | } \ |
534 | static inline uint64_t ldn_## END ## _p(const void *ptr, int sz) \ |
535 | { \ |
536 | switch (sz) { \ |
537 | case 1: \ |
538 | return ldub_p(ptr); \ |
539 | case 2: \ |
540 | return lduw_ ## END ## _p(ptr); \ |
541 | case 4: \ |
542 | return (uint32_t)ldl_ ## END ## _p(ptr); \ |
543 | case 8: \ |
544 | return ldq_ ## END ## _p(ptr); \ |
545 | default: \ |
546 | g_assert_not_reached(); \ |
547 | } \ |
548 | } |
549 | |
550 | DO_STN_LDN_P(he) |
551 | DO_STN_LDN_P(le) |
552 | DO_STN_LDN_P(be) |
553 | |
554 | #undef DO_STN_LDN_P |
555 | |
556 | #undef le_bswap |
557 | #undef be_bswap |
558 | #undef le_bswaps |
559 | #undef be_bswaps |
560 | |
561 | #endif /* BSWAP_H */ |
562 | |