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