Statistics
| Branch: | Revision:

root / bswap.h @ c0424934

History | View | Annotate | Download (13.9 kB)

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 */