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}, 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_le32(_x) \ 134 ((((_x) & 0x000000ffU) << 24) | \ 135 (((_x) & 0x0000ff00U) << 8) | \ 136 (((_x) & 0x00ff0000U) >> 8) | \ 137 (((_x) & 0xff000000U) >> 24)) 138 # define const_le16(_x) \ 139 ((((_x) & 0x00ff) << 8) | \ 140 (((_x) & 0xff00) >> 8)) 141 #else 142 # define const_le32(_x) (_x) 143 # define const_le16(_x) (_x) 144 #endif 145 146 /* unaligned/endian-independent pointer access */ 147 148 /* 149 * the generic syntax is: 150 * 151 * load: ld{type}{sign}{size}_{endian}_p(ptr) 152 * 153 * store: st{type}{size}_{endian}_p(ptr, val) 154 * 155 * Note there are small differences with the softmmu access API! 156 * 157 * type is: 158 * (empty): integer access 159 * f : float access 160 * 161 * sign is: 162 * (empty): for 32 or 64 bit sizes (including floats and doubles) 163 * u : unsigned 164 * s : signed 165 * 166 * size is: 167 * b: 8 bits 168 * w: 16 bits 169 * l: 32 bits 170 * q: 64 bits 171 * 172 * endian is: 173 * he : host endian 174 * be : big endian 175 * le : little endian 176 * te : target endian 177 * (except for byte accesses, which have no endian infix). 178 * 179 * The target endian accessors are obviously only available to source 180 * files which are built per-target; they are defined in cpu-all.h. 181 * 182 * In all cases these functions take a host pointer. 183 * For accessors that take a guest address rather than a 184 * host address, see the cpu_{ld,st}_* accessors defined in 185 * cpu_ldst.h. 186 * 187 * For cases where the size to be used is not fixed at compile time, 188 * there are 189 * stn_{endian}_p(ptr, sz, val) 190 * which stores @val to @ptr as an @endian-order number @sz bytes in size 191 * and 192 * ldn_{endian}_p(ptr, sz) 193 * which loads @sz bytes from @ptr as an unsigned @endian-order number 194 * and returns it in a uint64_t. 195 */ 196 197 static inline int ldub_p(const void *ptr) 198 { 199 return *(uint8_t *)ptr; 200 } 201 202 static inline int ldsb_p(const void *ptr) 203 { 204 return *(int8_t *)ptr; 205 } 206 207 static inline void stb_p(void *ptr, uint8_t v) 208 { 209 *(uint8_t *)ptr = v; 210 } 211 212 /* 213 * Any compiler worth its salt will turn these memcpy into native unaligned 214 * operations. Thus we don't need to play games with packed attributes, or 215 * inline byte-by-byte stores. 216 * Some compilation environments (eg some fortify-source implementations) 217 * may intercept memcpy() in a way that defeats the compiler optimization, 218 * though, so we use __builtin_memcpy() to give ourselves the best chance 219 * of good performance. 220 */ 221 222 static inline int lduw_he_p(const void *ptr) 223 { 224 uint16_t r; 225 __builtin_memcpy(&r, ptr, sizeof(r)); 226 return r; 227 } 228 229 static inline int ldsw_he_p(const void *ptr) 230 { 231 int16_t r; 232 __builtin_memcpy(&r, ptr, sizeof(r)); 233 return r; 234 } 235 236 static inline void stw_he_p(void *ptr, uint16_t v) 237 { 238 __builtin_memcpy(ptr, &v, sizeof(v)); 239 } 240 241 static inline int ldl_he_p(const void *ptr) 242 { 243 int32_t r; 244 __builtin_memcpy(&r, ptr, sizeof(r)); 245 return r; 246 } 247 248 static inline void stl_he_p(void *ptr, uint32_t v) 249 { 250 __builtin_memcpy(ptr, &v, sizeof(v)); 251 } 252 253 static inline uint64_t ldq_he_p(const void *ptr) 254 { 255 uint64_t r; 256 __builtin_memcpy(&r, ptr, sizeof(r)); 257 return r; 258 } 259 260 static inline void stq_he_p(void *ptr, uint64_t v) 261 { 262 __builtin_memcpy(ptr, &v, sizeof(v)); 263 } 264 265 static inline int lduw_le_p(const void *ptr) 266 { 267 return (uint16_t)le_bswap(lduw_he_p(ptr), 16); 268 } 269 270 static inline int ldsw_le_p(const void *ptr) 271 { 272 return (int16_t)le_bswap(lduw_he_p(ptr), 16); 273 } 274 275 static inline int ldl_le_p(const void *ptr) 276 { 277 return le_bswap(ldl_he_p(ptr), 32); 278 } 279 280 static inline uint64_t ldq_le_p(const void *ptr) 281 { 282 return le_bswap(ldq_he_p(ptr), 64); 283 } 284 285 static inline void stw_le_p(void *ptr, uint16_t v) 286 { 287 stw_he_p(ptr, le_bswap(v, 16)); 288 } 289 290 static inline void stl_le_p(void *ptr, uint32_t v) 291 { 292 stl_he_p(ptr, le_bswap(v, 32)); 293 } 294 295 static inline void stq_le_p(void *ptr, uint64_t v) 296 { 297 stq_he_p(ptr, le_bswap(v, 64)); 298 } 299 300 static inline int lduw_be_p(const void *ptr) 301 { 302 return (uint16_t)be_bswap(lduw_he_p(ptr), 16); 303 } 304 305 static inline int ldsw_be_p(const void *ptr) 306 { 307 return (int16_t)be_bswap(lduw_he_p(ptr), 16); 308 } 309 310 static inline int ldl_be_p(const void *ptr) 311 { 312 return be_bswap(ldl_he_p(ptr), 32); 313 } 314 315 static inline uint64_t ldq_be_p(const void *ptr) 316 { 317 return be_bswap(ldq_he_p(ptr), 64); 318 } 319 320 static inline void stw_be_p(void *ptr, uint16_t v) 321 { 322 stw_he_p(ptr, be_bswap(v, 16)); 323 } 324 325 static inline void stl_be_p(void *ptr, uint32_t v) 326 { 327 stl_he_p(ptr, be_bswap(v, 32)); 328 } 329 330 static inline void stq_be_p(void *ptr, uint64_t v) 331 { 332 stq_he_p(ptr, be_bswap(v, 64)); 333 } 334 335 static inline unsigned long leul_to_cpu(unsigned long v) 336 { 337 #if HOST_LONG_BITS == 32 338 return le_bswap(v, 32); 339 #elif HOST_LONG_BITS == 64 340 return le_bswap(v, 64); 341 #else 342 # error Unknown sizeof long 343 #endif 344 } 345 346 /* Store v to p as a sz byte value in host order */ 347 #define DO_STN_LDN_P(END) \ 348 static inline void stn_## END ## _p(void *ptr, int sz, uint64_t v) \ 349 { \ 350 switch (sz) { \ 351 case 1: \ 352 stb_p(ptr, v); \ 353 break; \ 354 case 2: \ 355 stw_ ## END ## _p(ptr, v); \ 356 break; \ 357 case 4: \ 358 stl_ ## END ## _p(ptr, v); \ 359 break; \ 360 case 8: \ 361 stq_ ## END ## _p(ptr, v); \ 362 break; \ 363 default: \ 364 g_assert_not_reached(); \ 365 } \ 366 } \ 367 static inline uint64_t ldn_## END ## _p(const void *ptr, int sz) \ 368 { \ 369 switch (sz) { \ 370 case 1: \ 371 return ldub_p(ptr); \ 372 case 2: \ 373 return lduw_ ## END ## _p(ptr); \ 374 case 4: \ 375 return (uint32_t)ldl_ ## END ## _p(ptr); \ 376 case 8: \ 377 return ldq_ ## END ## _p(ptr); \ 378 default: \ 379 g_assert_not_reached(); \ 380 } \ 381 } 382 383 DO_STN_LDN_P(he) 384 DO_STN_LDN_P(le) 385 DO_STN_LDN_P(be) 386 387 #undef DO_STN_LDN_P 388 389 #undef le_bswap 390 #undef be_bswap 391 #undef le_bswaps 392 #undef be_bswaps 393 394 #endif /* BSWAP_H */ 395