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