linux-user: save auxv length
[qemu.git] / bswap.h
1 #ifndef BSWAP_H
2 #define BSWAP_H
3
4 #include "config-host.h"
5
6 #include <inttypes.h>
7 #include "softfloat.h"
8
9 #ifdef CONFIG_MACHINE_BSWAP_H
10 #include <sys/endian.h>
11 #include <sys/types.h>
12 #include <machine/bswap.h>
13 #else
14
15 #ifdef CONFIG_BYTESWAP_H
16 #include <byteswap.h>
17 #else
18
19 #define bswap_16(x) \
20 ({ \
21 uint16_t __x = (x); \
22 ((uint16_t)( \
23 (((uint16_t)(__x) & (uint16_t)0x00ffU) << 8) | \
24 (((uint16_t)(__x) & (uint16_t)0xff00U) >> 8) )); \
25 })
26
27 #define bswap_32(x) \
28 ({ \
29 uint32_t __x = (x); \
30 ((uint32_t)( \
31 (((uint32_t)(__x) & (uint32_t)0x000000ffUL) << 24) | \
32 (((uint32_t)(__x) & (uint32_t)0x0000ff00UL) << 8) | \
33 (((uint32_t)(__x) & (uint32_t)0x00ff0000UL) >> 8) | \
34 (((uint32_t)(__x) & (uint32_t)0xff000000UL) >> 24) )); \
35 })
36
37 #define bswap_64(x) \
38 ({ \
39 uint64_t __x = (x); \
40 ((uint64_t)( \
41 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000000000ffULL) << 56) | \
42 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000000000ff00ULL) << 40) | \
43 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000000000ff0000ULL) << 24) | \
44 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00000000ff000000ULL) << 8) | \
45 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x000000ff00000000ULL) >> 8) | \
46 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x0000ff0000000000ULL) >> 24) | \
47 (uint64_t)(((uint64_t)(__x) & (uint64_t)0x00ff000000000000ULL) >> 40) | \
48 (uint64_t)(((uint64_t)(__x) & (uint64_t)0xff00000000000000ULL) >> 56) )); \
49 })
50
51 #endif /* !CONFIG_BYTESWAP_H */
52
53 static inline uint16_t bswap16(uint16_t x)
54 {
55 return bswap_16(x);
56 }
57
58 static inline uint32_t bswap32(uint32_t x)
59 {
60 return bswap_32(x);
61 }
62
63 static inline uint64_t bswap64(uint64_t x)
64 {
65 return bswap_64(x);
66 }
67
68 #endif /* ! CONFIG_MACHINE_BSWAP_H */
69
70 static inline void bswap16s(uint16_t *s)
71 {
72 *s = bswap16(*s);
73 }
74
75 static inline void bswap32s(uint32_t *s)
76 {
77 *s = bswap32(*s);
78 }
79
80 static inline void bswap64s(uint64_t *s)
81 {
82 *s = bswap64(*s);
83 }
84
85 #if defined(HOST_WORDS_BIGENDIAN)
86 #define be_bswap(v, size) (v)
87 #define le_bswap(v, size) bswap ## size(v)
88 #define be_bswaps(v, size)
89 #define le_bswaps(p, size) *p = bswap ## size(*p);
90 #else
91 #define le_bswap(v, size) (v)
92 #define be_bswap(v, size) bswap ## size(v)
93 #define le_bswaps(v, size)
94 #define be_bswaps(p, size) *p = bswap ## size(*p);
95 #endif
96
97 #define CPU_CONVERT(endian, size, type)\
98 static inline type endian ## size ## _to_cpu(type v)\
99 {\
100 return endian ## _bswap(v, size);\
101 }\
102 \
103 static inline type cpu_to_ ## endian ## size(type v)\
104 {\
105 return endian ## _bswap(v, size);\
106 }\
107 \
108 static inline void endian ## size ## _to_cpus(type *p)\
109 {\
110 endian ## _bswaps(p, size)\
111 }\
112 \
113 static inline void cpu_to_ ## endian ## size ## s(type *p)\
114 {\
115 endian ## _bswaps(p, size)\
116 }\
117 \
118 static inline type endian ## size ## _to_cpup(const type *p)\
119 {\
120 return endian ## size ## _to_cpu(*p);\
121 }\
122 \
123 static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\
124 {\
125 *p = cpu_to_ ## endian ## size(v);\
126 }
127
128 CPU_CONVERT(be, 16, uint16_t)
129 CPU_CONVERT(be, 32, uint32_t)
130 CPU_CONVERT(be, 64, uint64_t)
131
132 CPU_CONVERT(le, 16, uint16_t)
133 CPU_CONVERT(le, 32, uint32_t)
134 CPU_CONVERT(le, 64, uint64_t)
135
136 /* unaligned versions (optimized for frequent unaligned accesses)*/
137
138 #if defined(__i386__) || defined(_ARCH_PPC)
139
140 #define cpu_to_le16wu(p, v) cpu_to_le16w(p, v)
141 #define cpu_to_le32wu(p, v) cpu_to_le32w(p, v)
142 #define le16_to_cpupu(p) le16_to_cpup(p)
143 #define le32_to_cpupu(p) le32_to_cpup(p)
144 #define be32_to_cpupu(p) be32_to_cpup(p)
145
146 #define cpu_to_be16wu(p, v) cpu_to_be16w(p, v)
147 #define cpu_to_be32wu(p, v) cpu_to_be32w(p, v)
148 #define cpu_to_be64wu(p, v) cpu_to_be64w(p, v)
149
150 #else
151
152 static inline void cpu_to_le16wu(uint16_t *p, uint16_t v)
153 {
154 uint8_t *p1 = (uint8_t *)p;
155
156 p1[0] = v & 0xff;
157 p1[1] = v >> 8;
158 }
159
160 static inline void cpu_to_le32wu(uint32_t *p, uint32_t v)
161 {
162 uint8_t *p1 = (uint8_t *)p;
163
164 p1[0] = v & 0xff;
165 p1[1] = v >> 8;
166 p1[2] = v >> 16;
167 p1[3] = v >> 24;
168 }
169
170 static inline uint16_t le16_to_cpupu(const uint16_t *p)
171 {
172 const uint8_t *p1 = (const uint8_t *)p;
173 return p1[0] | (p1[1] << 8);
174 }
175
176 static inline uint32_t le32_to_cpupu(const uint32_t *p)
177 {
178 const uint8_t *p1 = (const uint8_t *)p;
179 return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24);
180 }
181
182 static inline uint32_t be32_to_cpupu(const uint32_t *p)
183 {
184 const uint8_t *p1 = (const uint8_t *)p;
185 return p1[3] | (p1[2] << 8) | (p1[1] << 16) | (p1[0] << 24);
186 }
187
188 static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
189 {
190 uint8_t *p1 = (uint8_t *)p;
191
192 p1[0] = v >> 8;
193 p1[1] = v & 0xff;
194 }
195
196 static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
197 {
198 uint8_t *p1 = (uint8_t *)p;
199
200 p1[0] = v >> 24;
201 p1[1] = v >> 16;
202 p1[2] = v >> 8;
203 p1[3] = v & 0xff;
204 }
205
206 static inline void cpu_to_be64wu(uint64_t *p, uint64_t v)
207 {
208 uint8_t *p1 = (uint8_t *)p;
209
210 p1[0] = v >> 56;
211 p1[1] = v >> 48;
212 p1[2] = v >> 40;
213 p1[3] = v >> 32;
214 p1[4] = v >> 24;
215 p1[5] = v >> 16;
216 p1[6] = v >> 8;
217 p1[7] = v & 0xff;
218 }
219
220 #endif
221
222 #ifdef HOST_WORDS_BIGENDIAN
223 #define cpu_to_32wu cpu_to_be32wu
224 #define leul_to_cpu(v) glue(glue(le,HOST_LONG_BITS),_to_cpu)(v)
225 #else
226 #define cpu_to_32wu cpu_to_le32wu
227 #define leul_to_cpu(v) (v)
228 #endif
229
230 #undef le_bswap
231 #undef be_bswap
232 #undef le_bswaps
233 #undef be_bswaps
234
235 /* len must be one of 1, 2, 4 */
236 static inline uint32_t qemu_bswap_len(uint32_t value, int len)
237 {
238 return bswap32(value) >> (32 - 8 * len);
239 }
240
241 typedef union {
242 float32 f;
243 uint32_t l;
244 } CPU_FloatU;
245
246 typedef union {
247 float64 d;
248 #if defined(HOST_WORDS_BIGENDIAN)
249 struct {
250 uint32_t upper;
251 uint32_t lower;
252 } l;
253 #else
254 struct {
255 uint32_t lower;
256 uint32_t upper;
257 } l;
258 #endif
259 uint64_t ll;
260 } CPU_DoubleU;
261
262 typedef union {
263 floatx80 d;
264 struct {
265 uint64_t lower;
266 uint16_t upper;
267 } l;
268 } CPU_LDoubleU;
269
270 typedef union {
271 float128 q;
272 #if defined(HOST_WORDS_BIGENDIAN)
273 struct {
274 uint32_t upmost;
275 uint32_t upper;
276 uint32_t lower;
277 uint32_t lowest;
278 } l;
279 struct {
280 uint64_t upper;
281 uint64_t lower;
282 } ll;
283 #else
284 struct {
285 uint32_t lowest;
286 uint32_t lower;
287 uint32_t upper;
288 uint32_t upmost;
289 } l;
290 struct {
291 uint64_t lower;
292 uint64_t upper;
293 } ll;
294 #endif
295 } CPU_QuadU;
296
297 /* unaligned/endian-independent pointer access */
298
299 /*
300 * the generic syntax is:
301 *
302 * load: ld{type}{sign}{size}{endian}_p(ptr)
303 *
304 * store: st{type}{size}{endian}_p(ptr, val)
305 *
306 * Note there are small differences with the softmmu access API!
307 *
308 * type is:
309 * (empty): integer access
310 * f : float access
311 *
312 * sign is:
313 * (empty): for floats or 32 bit size
314 * u : unsigned
315 * s : signed
316 *
317 * size is:
318 * b: 8 bits
319 * w: 16 bits
320 * l: 32 bits
321 * q: 64 bits
322 *
323 * endian is:
324 * (empty): 8 bit access
325 * be : big endian
326 * le : little endian
327 */
328 static inline int ldub_p(const void *ptr)
329 {
330 return *(uint8_t *)ptr;
331 }
332
333 static inline int ldsb_p(const void *ptr)
334 {
335 return *(int8_t *)ptr;
336 }
337
338 static inline void stb_p(void *ptr, int v)
339 {
340 *(uint8_t *)ptr = v;
341 }
342
343 /* NOTE: on arm, putting 2 in /proc/sys/debug/alignment so that the
344 kernel handles unaligned load/stores may give better results, but
345 it is a system wide setting : bad */
346 #if defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
347
348 /* conservative code for little endian unaligned accesses */
349 static inline int lduw_le_p(const void *ptr)
350 {
351 #ifdef _ARCH_PPC
352 int val;
353 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
354 return val;
355 #else
356 const uint8_t *p = ptr;
357 return p[0] | (p[1] << 8);
358 #endif
359 }
360
361 static inline int ldsw_le_p(const void *ptr)
362 {
363 #ifdef _ARCH_PPC
364 int val;
365 __asm__ __volatile__ ("lhbrx %0,0,%1" : "=r" (val) : "r" (ptr));
366 return (int16_t)val;
367 #else
368 const uint8_t *p = ptr;
369 return (int16_t)(p[0] | (p[1] << 8));
370 #endif
371 }
372
373 static inline int ldl_le_p(const void *ptr)
374 {
375 #ifdef _ARCH_PPC
376 int val;
377 __asm__ __volatile__ ("lwbrx %0,0,%1" : "=r" (val) : "r" (ptr));
378 return val;
379 #else
380 const uint8_t *p = ptr;
381 return p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
382 #endif
383 }
384
385 static inline uint64_t ldq_le_p(const void *ptr)
386 {
387 const uint8_t *p = ptr;
388 uint32_t v1, v2;
389 v1 = ldl_le_p(p);
390 v2 = ldl_le_p(p + 4);
391 return v1 | ((uint64_t)v2 << 32);
392 }
393
394 static inline void stw_le_p(void *ptr, int v)
395 {
396 #ifdef _ARCH_PPC
397 __asm__ __volatile__ ("sthbrx %1,0,%2" : "=m" (*(uint16_t *)ptr) : "r" (v), "r" (ptr));
398 #else
399 uint8_t *p = ptr;
400 p[0] = v;
401 p[1] = v >> 8;
402 #endif
403 }
404
405 static inline void stl_le_p(void *ptr, int v)
406 {
407 #ifdef _ARCH_PPC
408 __asm__ __volatile__ ("stwbrx %1,0,%2" : "=m" (*(uint32_t *)ptr) : "r" (v), "r" (ptr));
409 #else
410 uint8_t *p = ptr;
411 p[0] = v;
412 p[1] = v >> 8;
413 p[2] = v >> 16;
414 p[3] = v >> 24;
415 #endif
416 }
417
418 static inline void stq_le_p(void *ptr, uint64_t v)
419 {
420 uint8_t *p = ptr;
421 stl_le_p(p, (uint32_t)v);
422 stl_le_p(p + 4, v >> 32);
423 }
424
425 /* float access */
426
427 static inline float32 ldfl_le_p(const void *ptr)
428 {
429 union {
430 float32 f;
431 uint32_t i;
432 } u;
433 u.i = ldl_le_p(ptr);
434 return u.f;
435 }
436
437 static inline void stfl_le_p(void *ptr, float32 v)
438 {
439 union {
440 float32 f;
441 uint32_t i;
442 } u;
443 u.f = v;
444 stl_le_p(ptr, u.i);
445 }
446
447 static inline float64 ldfq_le_p(const void *ptr)
448 {
449 CPU_DoubleU u;
450 u.l.lower = ldl_le_p(ptr);
451 u.l.upper = ldl_le_p(ptr + 4);
452 return u.d;
453 }
454
455 static inline void stfq_le_p(void *ptr, float64 v)
456 {
457 CPU_DoubleU u;
458 u.d = v;
459 stl_le_p(ptr, u.l.lower);
460 stl_le_p(ptr + 4, u.l.upper);
461 }
462
463 #else
464
465 static inline int lduw_le_p(const void *ptr)
466 {
467 return *(uint16_t *)ptr;
468 }
469
470 static inline int ldsw_le_p(const void *ptr)
471 {
472 return *(int16_t *)ptr;
473 }
474
475 static inline int ldl_le_p(const void *ptr)
476 {
477 return *(uint32_t *)ptr;
478 }
479
480 static inline uint64_t ldq_le_p(const void *ptr)
481 {
482 return *(uint64_t *)ptr;
483 }
484
485 static inline void stw_le_p(void *ptr, int v)
486 {
487 *(uint16_t *)ptr = v;
488 }
489
490 static inline void stl_le_p(void *ptr, int v)
491 {
492 *(uint32_t *)ptr = v;
493 }
494
495 static inline void stq_le_p(void *ptr, uint64_t v)
496 {
497 *(uint64_t *)ptr = v;
498 }
499
500 /* float access */
501
502 static inline float32 ldfl_le_p(const void *ptr)
503 {
504 return *(float32 *)ptr;
505 }
506
507 static inline float64 ldfq_le_p(const void *ptr)
508 {
509 return *(float64 *)ptr;
510 }
511
512 static inline void stfl_le_p(void *ptr, float32 v)
513 {
514 *(float32 *)ptr = v;
515 }
516
517 static inline void stfq_le_p(void *ptr, float64 v)
518 {
519 *(float64 *)ptr = v;
520 }
521 #endif
522
523 #if !defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
524
525 static inline int lduw_be_p(const void *ptr)
526 {
527 #if defined(__i386__)
528 int val;
529 asm volatile ("movzwl %1, %0\n"
530 "xchgb %b0, %h0\n"
531 : "=q" (val)
532 : "m" (*(uint16_t *)ptr));
533 return val;
534 #else
535 const uint8_t *b = ptr;
536 return ((b[0] << 8) | b[1]);
537 #endif
538 }
539
540 static inline int ldsw_be_p(const void *ptr)
541 {
542 #if defined(__i386__)
543 int val;
544 asm volatile ("movzwl %1, %0\n"
545 "xchgb %b0, %h0\n"
546 : "=q" (val)
547 : "m" (*(uint16_t *)ptr));
548 return (int16_t)val;
549 #else
550 const uint8_t *b = ptr;
551 return (int16_t)((b[0] << 8) | b[1]);
552 #endif
553 }
554
555 static inline int ldl_be_p(const void *ptr)
556 {
557 #if defined(__i386__) || defined(__x86_64__)
558 int val;
559 asm volatile ("movl %1, %0\n"
560 "bswap %0\n"
561 : "=r" (val)
562 : "m" (*(uint32_t *)ptr));
563 return val;
564 #else
565 const uint8_t *b = ptr;
566 return (b[0] << 24) | (b[1] << 16) | (b[2] << 8) | b[3];
567 #endif
568 }
569
570 static inline uint64_t ldq_be_p(const void *ptr)
571 {
572 uint32_t a,b;
573 a = ldl_be_p(ptr);
574 b = ldl_be_p((uint8_t *)ptr + 4);
575 return (((uint64_t)a<<32)|b);
576 }
577
578 static inline void stw_be_p(void *ptr, int v)
579 {
580 #if defined(__i386__)
581 asm volatile ("xchgb %b0, %h0\n"
582 "movw %w0, %1\n"
583 : "=q" (v)
584 : "m" (*(uint16_t *)ptr), "0" (v));
585 #else
586 uint8_t *d = (uint8_t *) ptr;
587 d[0] = v >> 8;
588 d[1] = v;
589 #endif
590 }
591
592 static inline void stl_be_p(void *ptr, int v)
593 {
594 #if defined(__i386__) || defined(__x86_64__)
595 asm volatile ("bswap %0\n"
596 "movl %0, %1\n"
597 : "=r" (v)
598 : "m" (*(uint32_t *)ptr), "0" (v));
599 #else
600 uint8_t *d = (uint8_t *) ptr;
601 d[0] = v >> 24;
602 d[1] = v >> 16;
603 d[2] = v >> 8;
604 d[3] = v;
605 #endif
606 }
607
608 static inline void stq_be_p(void *ptr, uint64_t v)
609 {
610 stl_be_p(ptr, v >> 32);
611 stl_be_p((uint8_t *)ptr + 4, v);
612 }
613
614 /* float access */
615
616 static inline float32 ldfl_be_p(const void *ptr)
617 {
618 union {
619 float32 f;
620 uint32_t i;
621 } u;
622 u.i = ldl_be_p(ptr);
623 return u.f;
624 }
625
626 static inline void stfl_be_p(void *ptr, float32 v)
627 {
628 union {
629 float32 f;
630 uint32_t i;
631 } u;
632 u.f = v;
633 stl_be_p(ptr, u.i);
634 }
635
636 static inline float64 ldfq_be_p(const void *ptr)
637 {
638 CPU_DoubleU u;
639 u.l.upper = ldl_be_p(ptr);
640 u.l.lower = ldl_be_p((uint8_t *)ptr + 4);
641 return u.d;
642 }
643
644 static inline void stfq_be_p(void *ptr, float64 v)
645 {
646 CPU_DoubleU u;
647 u.d = v;
648 stl_be_p(ptr, u.l.upper);
649 stl_be_p((uint8_t *)ptr + 4, u.l.lower);
650 }
651
652 #else
653
654 static inline int lduw_be_p(const void *ptr)
655 {
656 return *(uint16_t *)ptr;
657 }
658
659 static inline int ldsw_be_p(const void *ptr)
660 {
661 return *(int16_t *)ptr;
662 }
663
664 static inline int ldl_be_p(const void *ptr)
665 {
666 return *(uint32_t *)ptr;
667 }
668
669 static inline uint64_t ldq_be_p(const void *ptr)
670 {
671 return *(uint64_t *)ptr;
672 }
673
674 static inline void stw_be_p(void *ptr, int v)
675 {
676 *(uint16_t *)ptr = v;
677 }
678
679 static inline void stl_be_p(void *ptr, int v)
680 {
681 *(uint32_t *)ptr = v;
682 }
683
684 static inline void stq_be_p(void *ptr, uint64_t v)
685 {
686 *(uint64_t *)ptr = v;
687 }
688
689 /* float access */
690
691 static inline float32 ldfl_be_p(const void *ptr)
692 {
693 return *(float32 *)ptr;
694 }
695
696 static inline float64 ldfq_be_p(const void *ptr)
697 {
698 return *(float64 *)ptr;
699 }
700
701 static inline void stfl_be_p(void *ptr, float32 v)
702 {
703 *(float32 *)ptr = v;
704 }
705
706 static inline void stfq_be_p(void *ptr, float64 v)
707 {
708 *(float64 *)ptr = v;
709 }
710
711 #endif
712
713 #endif /* BSWAP_H */