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