Home | History | Annotate | Download | only in include
      1 #ifndef _BYTESWAP_H
      2 #define _BYTESWAP_H
      3 
      4 #include <stdint.h>
      5 #include <klibc/endian.h>
      6 #include <klibc/compiler.h>
      7 
      8 /* This assumes an i386 platform */
      9 
     10 #define __bswap_16_macro(v) ((uint16_t)		  			\
     11 			     (((uint16_t)(v) << 8) | 			\
     12 			      ((uint16_t)(v) >> 8)))
     13 
     14 static inline __constfunc uint16_t __bswap_16(uint16_t v)
     15 {
     16     return __bswap_16_macro(v);
     17 }
     18 
     19 #define bswap_16(x) (__builtin_constant_p(x) ?				\
     20 			__bswap_16_macro(x) : __bswap_16(x))
     21 
     22 #define __bswap_32_macro(v) ((uint32_t)					\
     23 			     ((((uint32_t)(v) & 0x000000ff) << 24) |	\
     24 			      (((uint32_t)(v) & 0x0000ff00) << 8)  |	\
     25 			     (((uint32_t)(v) & 0x00ff0000) >> 8)  |	\
     26 			      (((uint32_t)(v) & 0xff000000) >> 24)))
     27 
     28 static inline __constfunc uint32_t __bswap_32(uint32_t v)
     29 {
     30 #if defined(__x86_64__)
     31     asm("bswap %0" : "+r" (v));
     32 #elif defined(__i386__)
     33     asm("xchgb %h0,%b0 ; roll $16,%0 ; xchgb %h0,%b0"
     34 	: "+q" (v));
     35 #else
     36     v = __bswap_32_macro(v);
     37 #endif
     38     return v;
     39 }
     40 
     41 #define bswap_32(x) (__builtin_constant_p(x) ?				\
     42 			 __bswap_32_macro(x) : __bswap_32(x))
     43 
     44 
     45 #define __bswap_64_macro(v) ((uint64_t)					\
     46     (((uint64_t)__bswap_32_macro((uint32_t)(v)) << 32) |		\
     47      (__bswap_32_macro((uint32_t)((uint64_t)(v) >> 32)))))
     48 
     49 static inline __constfunc uint64_t __bswap_64(uint64_t v)
     50 {
     51 #if defined(__x86_64__)
     52     asm("bswap %0" : "+r" (v));
     53 #else
     54     v = ((uint64_t)__bswap_32(v) << 32) | __bswap_32(v >> 32);
     55 #endif
     56     return v;
     57 }
     58 
     59 #define bswap_64(x) (__builtin_constant_p(x) ? 				\
     60 			__bswap_64_macro(x) :  __bswap_64(x))
     61 
     62 /* This is generic */
     63 
     64 #if __BYTE_ORDER == __LITTLE_ENDIAN
     65 
     66 #define be16_to_cpu(x) bswap_16(x)
     67 #define cpu_to_be16(x) bswap_16(x)
     68 #define be32_to_cpu(x) bswap_32(x)
     69 #define cpu_to_be32(x) bswap_32(x)
     70 #define be64_to_cpu(x) bswap_64(x)
     71 #define cpu_to_be64(x) bswap_64(x)
     72 
     73 #define le16_to_cpu(x) (x)
     74 #define cpu_to_le16(x) (x)
     75 #define le32_to_cpu(x) (x)
     76 #define cpu_to_le32(x) (x)
     77 #define le64_to_cpu(x) (x)
     78 #define cpu_to_le64(x) (x)
     79 
     80 #elif __BYTE_ORDER == __BIG_ENDIAN
     81 
     82 #define le16_to_cpu(x) bswap_16(x)
     83 #define cpu_to_le16(x) bswap_16(x)
     84 #define le32_to_cpu(x) bswap_32(x)
     85 #define cpu_to_le32(x) bswap_32(x)
     86 #define le64_to_cpu(x) bswap_64(x)
     87 #define cpu_to_le64(x) bswap_64(x)
     88 
     89 #define be16_to_cpu(x) (x)
     90 #define cpu_to_be16(x) (x)
     91 #define be32_to_cpu(x) (x)
     92 #define cpu_to_be32(x) (x)
     93 #define be64_to_cpu(x) (x)
     94 #define cpu_to_be64(x) (x)
     95 
     96 #else
     97 
     98 #error "Unknown byte order!"
     99 
    100 #endif
    101 
    102 typedef struct { uint16_t x; } __attribute__((packed)) __ua_uint16_t;
    103 typedef struct { uint32_t x; } __attribute__((packed)) __ua_uint32_t;
    104 typedef struct { uint64_t x; } __attribute__((packed)) __ua_uint64_t;
    105 
    106 /* These are guaranteed to support unaligned accesses */
    107 static inline uint16_t get_le16(const uint16_t *p)
    108 {
    109     const __ua_uint16_t *up = (const __ua_uint16_t *)p;
    110     return le16_to_cpu(up->x);
    111 }
    112 
    113 static inline uint32_t get_le32(const uint32_t *p)
    114 {
    115     const __ua_uint32_t *up = (const __ua_uint32_t *)p;
    116     return le32_to_cpu(up->x);
    117 }
    118 
    119 static inline uint64_t get_le64(const uint64_t *p)
    120 {
    121     const __ua_uint64_t *up = (const __ua_uint64_t *)p;
    122     return le64_to_cpu(up->x);
    123 }
    124 
    125 static inline uint16_t get_be16(const uint16_t *p)
    126 {
    127     const __ua_uint16_t *up = (const __ua_uint16_t *)p;
    128     return be16_to_cpu(up->x);
    129 }
    130 
    131 static inline uint32_t get_be32(const uint32_t *p)
    132 {
    133     const __ua_uint32_t *up = (const __ua_uint32_t *)p;
    134     return be32_to_cpu(up->x);
    135 }
    136 
    137 static inline uint64_t get_be64(const uint64_t *p)
    138 {
    139     const __ua_uint64_t *up = (const __ua_uint64_t *)p;
    140     return be64_to_cpu(up->x);
    141 }
    142 
    143 static inline void put_le16(uint16_t v, uint16_t *p)
    144 {
    145     __ua_uint16_t *up = (__ua_uint16_t *)p;
    146     up->x = cpu_to_le16(v);
    147 }
    148 
    149 static inline void put_le32(uint32_t v, uint32_t *p)
    150 {
    151     __ua_uint32_t *up = (__ua_uint32_t *)p;
    152     up->x = cpu_to_le32(v);
    153 }
    154 
    155 static inline void put_le64(uint64_t v, uint64_t *p)
    156 {
    157     __ua_uint64_t *up = (__ua_uint64_t *)p;
    158     up->x = cpu_to_le64(v);
    159 }
    160 
    161 static inline void put_be16(uint16_t v, uint16_t *p)
    162 {
    163     __ua_uint16_t *up = (__ua_uint16_t *)p;
    164     up->x = cpu_to_be16(v);
    165 }
    166 
    167 static inline void put_be32(uint32_t v, uint32_t *p)
    168 {
    169     __ua_uint32_t *up = (__ua_uint32_t *)p;
    170     up->x = cpu_to_be32(v);
    171 }
    172 
    173 static inline void put_be64(uint64_t v, uint64_t *p)
    174 {
    175     __ua_uint64_t *up = (__ua_uint64_t *)p;
    176     up->x = cpu_to_be64(v);
    177 }
    178 
    179 #endif /* _BYTESWAP_H */
    180 
    181