qemu-tech.texi: update implemented xtensa features list
[qemu/agraf.git] / bswap.h
blobcc7f84d30f91a45964a13eb2fe4d3fa6db77a590
1 #ifndef BSWAP_H
2 #define BSWAP_H
4 #include "config-host.h"
6 #include <inttypes.h>
7 #include "softfloat.h"
9 #ifdef CONFIG_MACHINE_BSWAP_H
10 #include <sys/endian.h>
11 #include <sys/types.h>
12 #include <machine/bswap.h>
13 #else
15 #ifdef CONFIG_BYTESWAP_H
16 #include <byteswap.h>
17 #else
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) )); \
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) )); \
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) )); \
51 #endif /* !CONFIG_BYTESWAP_H */
53 static inline uint16_t bswap16(uint16_t x)
55 return bswap_16(x);
58 static inline uint32_t bswap32(uint32_t x)
60 return bswap_32(x);
63 static inline uint64_t bswap64(uint64_t x)
65 return bswap_64(x);
68 #endif /* ! CONFIG_MACHINE_BSWAP_H */
70 static inline void bswap16s(uint16_t *s)
72 *s = bswap16(*s);
75 static inline void bswap32s(uint32_t *s)
77 *s = bswap32(*s);
80 static inline void bswap64s(uint64_t *s)
82 *s = bswap64(*s);
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
97 #define CPU_CONVERT(endian, size, type)\
98 static inline type endian ## size ## _to_cpu(type v)\
100 return endian ## _bswap(v, size);\
103 static inline type cpu_to_ ## endian ## size(type v)\
105 return endian ## _bswap(v, size);\
108 static inline void endian ## size ## _to_cpus(type *p)\
110 endian ## _bswaps(p, size)\
113 static inline void cpu_to_ ## endian ## size ## s(type *p)\
115 endian ## _bswaps(p, size)\
118 static inline type endian ## size ## _to_cpup(const type *p)\
120 return endian ## size ## _to_cpu(*p);\
123 static inline void cpu_to_ ## endian ## size ## w(type *p, type v)\
125 *p = cpu_to_ ## endian ## size(v);\
128 CPU_CONVERT(be, 16, uint16_t)
129 CPU_CONVERT(be, 32, uint32_t)
130 CPU_CONVERT(be, 64, uint64_t)
132 CPU_CONVERT(le, 16, uint16_t)
133 CPU_CONVERT(le, 32, uint32_t)
134 CPU_CONVERT(le, 64, uint64_t)
136 /* unaligned versions (optimized for frequent unaligned accesses)*/
138 #if defined(__i386__) || defined(_ARCH_PPC)
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)
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)
150 #else
152 static inline void cpu_to_le16wu(uint16_t *p, uint16_t v)
154 uint8_t *p1 = (uint8_t *)p;
156 p1[0] = v & 0xff;
157 p1[1] = v >> 8;
160 static inline void cpu_to_le32wu(uint32_t *p, uint32_t v)
162 uint8_t *p1 = (uint8_t *)p;
164 p1[0] = v & 0xff;
165 p1[1] = v >> 8;
166 p1[2] = v >> 16;
167 p1[3] = v >> 24;
170 static inline uint16_t le16_to_cpupu(const uint16_t *p)
172 const uint8_t *p1 = (const uint8_t *)p;
173 return p1[0] | (p1[1] << 8);
176 static inline uint32_t le32_to_cpupu(const uint32_t *p)
178 const uint8_t *p1 = (const uint8_t *)p;
179 return p1[0] | (p1[1] << 8) | (p1[2] << 16) | (p1[3] << 24);
182 static inline uint32_t be32_to_cpupu(const uint32_t *p)
184 const uint8_t *p1 = (const uint8_t *)p;
185 return p1[3] | (p1[2] << 8) | (p1[1] << 16) | (p1[0] << 24);
188 static inline void cpu_to_be16wu(uint16_t *p, uint16_t v)
190 uint8_t *p1 = (uint8_t *)p;
192 p1[0] = v >> 8;
193 p1[1] = v & 0xff;
196 static inline void cpu_to_be32wu(uint32_t *p, uint32_t v)
198 uint8_t *p1 = (uint8_t *)p;
200 p1[0] = v >> 24;
201 p1[1] = v >> 16;
202 p1[2] = v >> 8;
203 p1[3] = v & 0xff;
206 static inline void cpu_to_be64wu(uint64_t *p, uint64_t v)
208 uint8_t *p1 = (uint8_t *)p;
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;
220 #endif
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
230 #undef le_bswap
231 #undef be_bswap
232 #undef le_bswaps
233 #undef be_bswaps
235 /* len must be one of 1, 2, 4 */
236 static inline uint32_t qemu_bswap_len(uint32_t value, int len)
238 return bswap32(value) >> (32 - 8 * len);
241 typedef union {
242 float32 f;
243 uint32_t l;
244 } CPU_FloatU;
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;
262 typedef union {
263 floatx80 d;
264 struct {
265 uint64_t lower;
266 uint16_t upper;
267 } l;
268 } CPU_LDoubleU;
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;
297 /* unaligned/endian-independent pointer access */
300 * the generic syntax is:
302 * load: ld{type}{sign}{size}{endian}_p(ptr)
304 * store: st{type}{size}{endian}_p(ptr, val)
306 * Note there are small differences with the softmmu access API!
308 * type is:
309 * (empty): integer access
310 * f : float access
312 * sign is:
313 * (empty): for floats or 32 bit size
314 * u : unsigned
315 * s : signed
317 * size is:
318 * b: 8 bits
319 * w: 16 bits
320 * l: 32 bits
321 * q: 64 bits
323 * endian is:
324 * (empty): 8 bit access
325 * be : big endian
326 * le : little endian
328 static inline int ldub_p(const void *ptr)
330 return *(uint8_t *)ptr;
333 static inline int ldsb_p(const void *ptr)
335 return *(int8_t *)ptr;
338 static inline void stb_p(void *ptr, int v)
340 *(uint8_t *)ptr = v;
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)
348 /* conservative code for little endian unaligned accesses */
349 static inline int lduw_le_p(const void *ptr)
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
361 static inline int ldsw_le_p(const void *ptr)
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
373 static inline int ldl_le_p(const void *ptr)
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
385 static inline uint64_t ldq_le_p(const void *ptr)
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);
394 static inline void stw_le_p(void *ptr, int v)
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
405 static inline void stl_le_p(void *ptr, int v)
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
418 static inline void stq_le_p(void *ptr, uint64_t v)
420 uint8_t *p = ptr;
421 stl_le_p(p, (uint32_t)v);
422 stl_le_p(p + 4, v >> 32);
425 /* float access */
427 static inline float32 ldfl_le_p(const void *ptr)
429 union {
430 float32 f;
431 uint32_t i;
432 } u;
433 u.i = ldl_le_p(ptr);
434 return u.f;
437 static inline void stfl_le_p(void *ptr, float32 v)
439 union {
440 float32 f;
441 uint32_t i;
442 } u;
443 u.f = v;
444 stl_le_p(ptr, u.i);
447 static inline float64 ldfq_le_p(const void *ptr)
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;
455 static inline void stfq_le_p(void *ptr, float64 v)
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);
463 #else
465 static inline int lduw_le_p(const void *ptr)
467 return *(uint16_t *)ptr;
470 static inline int ldsw_le_p(const void *ptr)
472 return *(int16_t *)ptr;
475 static inline int ldl_le_p(const void *ptr)
477 return *(uint32_t *)ptr;
480 static inline uint64_t ldq_le_p(const void *ptr)
482 return *(uint64_t *)ptr;
485 static inline void stw_le_p(void *ptr, int v)
487 *(uint16_t *)ptr = v;
490 static inline void stl_le_p(void *ptr, int v)
492 *(uint32_t *)ptr = v;
495 static inline void stq_le_p(void *ptr, uint64_t v)
497 *(uint64_t *)ptr = v;
500 /* float access */
502 static inline float32 ldfl_le_p(const void *ptr)
504 return *(float32 *)ptr;
507 static inline float64 ldfq_le_p(const void *ptr)
509 return *(float64 *)ptr;
512 static inline void stfl_le_p(void *ptr, float32 v)
514 *(float32 *)ptr = v;
517 static inline void stfq_le_p(void *ptr, float64 v)
519 *(float64 *)ptr = v;
521 #endif
523 #if !defined(HOST_WORDS_BIGENDIAN) || defined(WORDS_ALIGNED)
525 static inline int lduw_be_p(const void *ptr)
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
540 static inline int ldsw_be_p(const void *ptr)
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
555 static inline int ldl_be_p(const void *ptr)
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
570 static inline uint64_t ldq_be_p(const void *ptr)
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);
578 static inline void stw_be_p(void *ptr, int v)
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
592 static inline void stl_be_p(void *ptr, int v)
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
608 static inline void stq_be_p(void *ptr, uint64_t v)
610 stl_be_p(ptr, v >> 32);
611 stl_be_p((uint8_t *)ptr + 4, v);
614 /* float access */
616 static inline float32 ldfl_be_p(const void *ptr)
618 union {
619 float32 f;
620 uint32_t i;
621 } u;
622 u.i = ldl_be_p(ptr);
623 return u.f;
626 static inline void stfl_be_p(void *ptr, float32 v)
628 union {
629 float32 f;
630 uint32_t i;
631 } u;
632 u.f = v;
633 stl_be_p(ptr, u.i);
636 static inline float64 ldfq_be_p(const void *ptr)
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;
644 static inline void stfq_be_p(void *ptr, float64 v)
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);
652 #else
654 static inline int lduw_be_p(const void *ptr)
656 return *(uint16_t *)ptr;
659 static inline int ldsw_be_p(const void *ptr)
661 return *(int16_t *)ptr;
664 static inline int ldl_be_p(const void *ptr)
666 return *(uint32_t *)ptr;
669 static inline uint64_t ldq_be_p(const void *ptr)
671 return *(uint64_t *)ptr;
674 static inline void stw_be_p(void *ptr, int v)
676 *(uint16_t *)ptr = v;
679 static inline void stl_be_p(void *ptr, int v)
681 *(uint32_t *)ptr = v;
684 static inline void stq_be_p(void *ptr, uint64_t v)
686 *(uint64_t *)ptr = v;
689 /* float access */
691 static inline float32 ldfl_be_p(const void *ptr)
693 return *(float32 *)ptr;
696 static inline float64 ldfq_be_p(const void *ptr)
698 return *(float64 *)ptr;
701 static inline void stfl_be_p(void *ptr, float32 v)
703 *(float32 *)ptr = v;
706 static inline void stfq_be_p(void *ptr, float64 v)
708 *(float64 *)ptr = v;
711 #endif
713 #endif /* BSWAP_H */