1 #ifndef BSWAP_H 2 #define BSWAP_H 3 4 #ifdef __cplusplus 5 extern "C" { 6 #endif 7 8 #undef bswap16 9 #define bswap16(_x) __builtin_bswap16(_x) 10 #undef bswap32 11 #define bswap32(_x) __builtin_bswap32(_x) 12 #undef bswap64 13 #define bswap64(_x) __builtin_bswap64(_x) 14 15 static inline void bswap16s(uint16_t *s) 16 { 17 *s = __builtin_bswap16(*s); 18 } 19 20 static inline void bswap32s(uint32_t *s) 21 { 22 *s = __builtin_bswap32(*s); 23 } 24 25 static inline void bswap64s(uint64_t *s) 26 { 27 *s = __builtin_bswap64(*s); 28 } 29 30 #if HOST_BIG_ENDIAN 31 #define be_bswap(v, size) (v) 32 #define le_bswap(v, size) glue(__builtin_bswap, size)(v) 33 #define be_bswaps(v, size) 34 #define le_bswaps(p, size) \ 35 do { *p = glue(__builtin_bswap, size)(*p); } while (0) 36 #else 37 #define le_bswap(v, size) (v) 38 #define be_bswap(v, size) glue(__builtin_bswap, size)(v) 39 #define le_bswaps(v, size) 40 #define be_bswaps(p, size) \ 41 do { *p = glue(__builtin_bswap, size)(*p); } while (0) 42 #endif 43 44 /** 45 * Endianness conversion functions between host cpu and specified endianness. 46 * (We list the complete set of prototypes produced by the macros below 47 * to assist people who search the headers to find their definitions.) 48 * 49 * uint16_t le16_to_cpu(uint16_t v); 50 * uint32_t le32_to_cpu(uint32_t v); 51 * uint64_t le64_to_cpu(uint64_t v); 52 * uint16_t be16_to_cpu(uint16_t v); 53 * uint32_t be32_to_cpu(uint32_t v); 54 * uint64_t be64_to_cpu(uint64_t v); 55 * 56 * Convert the value @v from the specified format to the native 57 * endianness of the host CPU by byteswapping if necessary, and 58 * return the converted value. 59 * 60 * uint16_t cpu_to_le16(uint16_t v); 61 * uint32_t cpu_to_le32(uint32_t v); 62 * uint64_t cpu_to_le64(uint64_t v); 63 * uint16_t cpu_to_be16(uint16_t v); 64 * uint32_t cpu_to_be32(uint32_t v); 65 * uint64_t cpu_to_be64(uint64_t v); 66 * 67 * Convert the value @v from the native endianness of the host CPU to 68 * the specified format by byteswapping if necessary, and return 69 * the converted value. 70 * 71 * void le16_to_cpus(uint16_t *v); 72 * void le32_to_cpus(uint32_t *v); 73 * void le64_to_cpus(uint64_t *v); 74 * void be16_to_cpus(uint16_t *v); 75 * void be32_to_cpus(uint32_t *v); 76 * void be64_to_cpus(uint64_t *v); 77 * 78 * Do an in-place conversion of the value pointed to by @v from the 79 * specified format to the native endianness of the host CPU. 80 * 81 * void cpu_to_le16s(uint16_t *v); 82 * void cpu_to_le32s(uint32_t *v); 83 * void cpu_to_le64s(uint64_t *v); 84 * void cpu_to_be16s(uint16_t *v); 85 * void cpu_to_be32s(uint32_t *v); 86 * void cpu_to_be64s(uint64_t *v); 87 * 88 * Do an in-place conversion of the value pointed to by @v from the 89 * native endianness of the host CPU to the specified format. 90 * 91 * Both X_to_cpu() and cpu_to_X() perform the same operation; you 92 * should use whichever one is better documenting of the function your 93 * code is performing. 94 * 95 * Do not use these functions for conversion of values which are in guest 96 * memory, since the data may not be sufficiently aligned for the host CPU's 97 * load and store instructions. Instead you should use the ld*_p() and 98 * st*_p() functions, which perform loads and stores of data of any 99 * required size and endianness and handle possible misalignment. 100 */ 101 102 #define CPU_CONVERT(endian, size, type)\ 103 static inline type endian ## size ## _to_cpu(type v)\ 104 {\ 105 return glue(endian, _bswap)(v, size);\ 106 }\ 107 \ 108 static inline type cpu_to_ ## endian ## size(type v)\ 109 {\ 110 return glue(endian, _bswap)(v, size);\ 111 }\ 112 \ 113 static inline void endian ## size ## _to_cpus(type *p)\ 114 {\ 115 glue(endian, _bswaps)(p, size);\ 116 }\ 117 \ 118 static inline void cpu_to_ ## endian ## size ## s(type *p)\ 119 {\ 120 glue(endian, _bswaps)(p, size);\ 121 } 122 123 CPU_CONVERT(be, 16, uint16_t) 124 CPU_CONVERT(be, 32, uint32_t) 125 CPU_CONVERT(be, 64, uint64_t) 126 127 CPU_CONVERT(le, 16, uint16_t) 128 CPU_CONVERT(le, 32, uint32_t) 129 CPU_CONVERT(le, 64, uint64_t) 130 131 /* 132 * Same as cpu_to_le{16,32}, except that gcc will figure the result is 133 * a compile-time constant if you pass in a constant. So this can be 134 * used to initialize static variables. 135 */ 136 #if HOST_BIG_ENDIAN 137 # define const_le32(_x) \ 138 ((((_x) & 0x000000ffU) << 24) | \ 139 (((_x) & 0x0000ff00U) << 8) | \ 140 (((_x) & 0x00ff0000U) >> 8) | \ 141 (((_x) & 0xff000000U) >> 24)) 142 # define const_le16(_x) \ 143 ((((_x) & 0x00ff) << 8) | \ 144 (((_x) & 0xff00) >> 8)) 145 #else 146 # define const_le32(_x) (_x) 147 # define const_le16(_x) (_x) 148 #endif 149 150 /* unaligned/endian-independent pointer access */ 151 152 /* 153 * the generic syntax is: 154 * 155 * load: ld{type}{sign}{size}_{endian}_p(ptr) 156 * 157 * store: st{type}{size}_{endian}_p(ptr, val) 158 * 159 * Note there are small differences with the softmmu access API! 160 * 161 * type is: 162 * (empty): integer access 163 * f : float access 164 * 165 * sign is: 166 * (empty): for 32 or 64 bit sizes (including floats and doubles) 167 * u : unsigned 168 * s : signed 169 * 170 * size is: 171 * b: 8 bits 172 * w: 16 bits 173 * l: 32 bits 174 * q: 64 bits 175 * 176 * endian is: 177 * he : host endian 178 * be : big endian 179 * le : little endian 180 * te : target endian 181 * (except for byte accesses, which have no endian infix). 182 * 183 * The target endian accessors are obviously only available to source 184 * files which are built per-target; they are defined in cpu-all.h. 185 * 186 * In all cases these functions take a host pointer. 187 * For accessors that take a guest address rather than a 188 * host address, see the cpu_{ld,st}_* accessors defined in 189 * cpu_ldst.h. 190 * 191 * For cases where the size to be used is not fixed at compile time, 192 * there are 193 * stn_{endian}_p(ptr, sz, val) 194 * which stores @val to @ptr as an @endian-order number @sz bytes in size 195 * and 196 * ldn_{endian}_p(ptr, sz) 197 * which loads @sz bytes from @ptr as an unsigned @endian-order number 198 * and returns it in a uint64_t. 199 */ 200 201 static inline int ldub_p(const void *ptr) 202 { 203 return *(uint8_t *)ptr; 204 } 205 206 static inline int ldsb_p(const void *ptr) 207 { 208 return *(int8_t *)ptr; 209 } 210 211 static inline void stb_p(void *ptr, uint8_t v) 212 { 213 *(uint8_t *)ptr = v; 214 } 215 216 /* 217 * Any compiler worth its salt will turn these memcpy into native unaligned 218 * operations. Thus we don't need to play games with packed attributes, or 219 * inline byte-by-byte stores. 220 * Some compilation environments (eg some fortify-source implementations) 221 * may intercept memcpy() in a way that defeats the compiler optimization, 222 * though, so we use __builtin_memcpy() to give ourselves the best chance 223 * of good performance. 224 */ 225 226 static inline int lduw_he_p(const void *ptr) 227 { 228 uint16_t r; 229 __builtin_memcpy(&r, ptr, sizeof(r)); 230 return r; 231 } 232 233 static inline int ldsw_he_p(const void *ptr) 234 { 235 int16_t r; 236 __builtin_memcpy(&r, ptr, sizeof(r)); 237 return r; 238 } 239 240 static inline void stw_he_p(void *ptr, uint16_t v) 241 { 242 __builtin_memcpy(ptr, &v, sizeof(v)); 243 } 244 245 static inline int ldl_he_p(const void *ptr) 246 { 247 int32_t r; 248 __builtin_memcpy(&r, ptr, sizeof(r)); 249 return r; 250 } 251 252 static inline void stl_he_p(void *ptr, uint32_t v) 253 { 254 __builtin_memcpy(ptr, &v, sizeof(v)); 255 } 256 257 static inline uint64_t ldq_he_p(const void *ptr) 258 { 259 uint64_t r; 260 __builtin_memcpy(&r, ptr, sizeof(r)); 261 return r; 262 } 263 264 static inline void stq_he_p(void *ptr, uint64_t v) 265 { 266 __builtin_memcpy(ptr, &v, sizeof(v)); 267 } 268 269 static inline int lduw_le_p(const void *ptr) 270 { 271 return (uint16_t)le_bswap(lduw_he_p(ptr), 16); 272 } 273 274 static inline int ldsw_le_p(const void *ptr) 275 { 276 return (int16_t)le_bswap(lduw_he_p(ptr), 16); 277 } 278 279 static inline int ldl_le_p(const void *ptr) 280 { 281 return le_bswap(ldl_he_p(ptr), 32); 282 } 283 284 static inline uint64_t ldq_le_p(const void *ptr) 285 { 286 return le_bswap(ldq_he_p(ptr), 64); 287 } 288 289 static inline void stw_le_p(void *ptr, uint16_t v) 290 { 291 stw_he_p(ptr, le_bswap(v, 16)); 292 } 293 294 static inline void stl_le_p(void *ptr, uint32_t v) 295 { 296 stl_he_p(ptr, le_bswap(v, 32)); 297 } 298 299 static inline void stq_le_p(void *ptr, uint64_t v) 300 { 301 stq_he_p(ptr, le_bswap(v, 64)); 302 } 303 304 static inline int lduw_be_p(const void *ptr) 305 { 306 return (uint16_t)be_bswap(lduw_he_p(ptr), 16); 307 } 308 309 static inline int ldsw_be_p(const void *ptr) 310 { 311 return (int16_t)be_bswap(lduw_he_p(ptr), 16); 312 } 313 314 static inline int ldl_be_p(const void *ptr) 315 { 316 return be_bswap(ldl_he_p(ptr), 32); 317 } 318 319 static inline uint64_t ldq_be_p(const void *ptr) 320 { 321 return be_bswap(ldq_he_p(ptr), 64); 322 } 323 324 static inline void stw_be_p(void *ptr, uint16_t v) 325 { 326 stw_he_p(ptr, be_bswap(v, 16)); 327 } 328 329 static inline void stl_be_p(void *ptr, uint32_t v) 330 { 331 stl_he_p(ptr, be_bswap(v, 32)); 332 } 333 334 static inline void stq_be_p(void *ptr, uint64_t v) 335 { 336 stq_he_p(ptr, be_bswap(v, 64)); 337 } 338 339 static inline unsigned long leul_to_cpu(unsigned long v) 340 { 341 #if HOST_LONG_BITS == 32 342 return le_bswap(v, 32); 343 #elif HOST_LONG_BITS == 64 344 return le_bswap(v, 64); 345 #else 346 # error Unknown sizeof long 347 #endif 348 } 349 350 /* Store v to p as a sz byte value in host order */ 351 #define DO_STN_LDN_P(END) \ 352 static inline void stn_## END ## _p(void *ptr, int sz, uint64_t v) \ 353 { \ 354 switch (sz) { \ 355 case 1: \ 356 stb_p(ptr, v); \ 357 break; \ 358 case 2: \ 359 stw_ ## END ## _p(ptr, v); \ 360 break; \ 361 case 4: \ 362 stl_ ## END ## _p(ptr, v); \ 363 break; \ 364 case 8: \ 365 stq_ ## END ## _p(ptr, v); \ 366 break; \ 367 default: \ 368 g_assert_not_reached(); \ 369 } \ 370 } \ 371 static inline uint64_t ldn_## END ## _p(const void *ptr, int sz) \ 372 { \ 373 switch (sz) { \ 374 case 1: \ 375 return ldub_p(ptr); \ 376 case 2: \ 377 return lduw_ ## END ## _p(ptr); \ 378 case 4: \ 379 return (uint32_t)ldl_ ## END ## _p(ptr); \ 380 case 8: \ 381 return ldq_ ## END ## _p(ptr); \ 382 default: \ 383 g_assert_not_reached(); \ 384 } \ 385 } 386 387 DO_STN_LDN_P(he) 388 DO_STN_LDN_P(le) 389 DO_STN_LDN_P(be) 390 391 #undef DO_STN_LDN_P 392 393 #undef le_bswap 394 #undef be_bswap 395 #undef le_bswaps 396 #undef be_bswaps 397 398 #ifdef __cplusplus 399 } 400 #endif 401 402 #endif /* BSWAP_H */ 403