1 /* 2 * Macros for swapping a value if the endianness is different 3 * between the target and the host. 4 * 5 * SPDX-License-Identifier: LGPL-2.1-or-later 6 */ 7 8 #ifndef TSWAP_H 9 #define TSWAP_H 10 11 #include "qemu/bswap.h" 12 #include "qemu/target-info.h" 13 14 /* 15 * If we're in target-specific code, we can hard-code the swapping 16 * condition, otherwise we have to do (slower) run-time checks. 17 */ 18 #ifdef COMPILING_PER_TARGET 19 #define target_needs_bswap() (HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN) 20 #else 21 #define target_needs_bswap() (HOST_BIG_ENDIAN != target_big_endian()) 22 #endif /* COMPILING_PER_TARGET */ 23 24 static inline uint16_t tswap16(uint16_t s) 25 { 26 if (target_needs_bswap()) { 27 return bswap16(s); 28 } else { 29 return s; 30 } 31 } 32 33 static inline uint32_t tswap32(uint32_t s) 34 { 35 if (target_needs_bswap()) { 36 return bswap32(s); 37 } else { 38 return s; 39 } 40 } 41 42 static inline uint64_t tswap64(uint64_t s) 43 { 44 if (target_needs_bswap()) { 45 return bswap64(s); 46 } else { 47 return s; 48 } 49 } 50 51 static inline void tswap16s(uint16_t *s) 52 { 53 if (target_needs_bswap()) { 54 *s = bswap16(*s); 55 } 56 } 57 58 static inline void tswap32s(uint32_t *s) 59 { 60 if (target_needs_bswap()) { 61 *s = bswap32(*s); 62 } 63 } 64 65 static inline void tswap64s(uint64_t *s) 66 { 67 if (target_needs_bswap()) { 68 *s = bswap64(*s); 69 } 70 } 71 72 /* Return ld{word}_{le,be}_p following target endianness. */ 73 #define LOAD_IMPL(word, args...) \ 74 do { \ 75 if (target_big_endian()) { \ 76 return glue(glue(ld, word), _be_p)(args); \ 77 } else { \ 78 return glue(glue(ld, word), _le_p)(args); \ 79 } \ 80 } while (0) 81 82 static inline int lduw_p(const void *ptr) 83 { 84 LOAD_IMPL(uw, ptr); 85 } 86 87 static inline int ldsw_p(const void *ptr) 88 { 89 LOAD_IMPL(sw, ptr); 90 } 91 92 static inline int ldl_p(const void *ptr) 93 { 94 LOAD_IMPL(l, ptr); 95 } 96 97 static inline uint64_t ldq_p(const void *ptr) 98 { 99 LOAD_IMPL(q, ptr); 100 } 101 102 static inline uint64_t ldn_p(const void *ptr, int sz) 103 { 104 LOAD_IMPL(n, ptr, sz); 105 } 106 107 #undef LOAD_IMPL 108 109 /* Call st{word}_{le,be}_p following target endianness. */ 110 #define STORE_IMPL(word, args...) \ 111 do { \ 112 if (target_big_endian()) { \ 113 glue(glue(st, word), _be_p)(args); \ 114 } else { \ 115 glue(glue(st, word), _le_p)(args); \ 116 } \ 117 } while (0) 118 119 120 static inline void stw_p(void *ptr, uint16_t v) 121 { 122 STORE_IMPL(w, ptr, v); 123 } 124 125 static inline void stl_p(void *ptr, uint32_t v) 126 { 127 STORE_IMPL(l, ptr, v); 128 } 129 130 static inline void stq_p(void *ptr, uint64_t v) 131 { 132 STORE_IMPL(q, ptr, v); 133 } 134 135 static inline void stn_p(void *ptr, int sz, uint64_t v) 136 { 137 STORE_IMPL(n, ptr, sz, v); 138 } 139 140 #undef STORE_IMPL 141 142 #endif /* TSWAP_H */ 143