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 13 /** 14 * target_big_endian: 15 * Returns true if the (default) endianness of the target is big endian, 16 * false otherwise. Common code should normally never need to know about the 17 * endianness of the target, so please do *not* use this function unless you 18 * know very well what you are doing! 19 */ 20 bool target_big_endian(void); 21 #ifdef COMPILING_PER_TARGET 22 #define target_big_endian() TARGET_BIG_ENDIAN 23 #endif 24 25 /* 26 * If we're in target-specific code, we can hard-code the swapping 27 * condition, otherwise we have to do (slower) run-time checks. 28 */ 29 #ifdef COMPILING_PER_TARGET 30 #define target_needs_bswap() (HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN) 31 #else 32 #define target_needs_bswap() (HOST_BIG_ENDIAN != target_big_endian()) 33 #endif /* COMPILING_PER_TARGET */ 34 35 static inline uint16_t tswap16(uint16_t s) 36 { 37 if (target_needs_bswap()) { 38 return bswap16(s); 39 } else { 40 return s; 41 } 42 } 43 44 static inline uint32_t tswap32(uint32_t s) 45 { 46 if (target_needs_bswap()) { 47 return bswap32(s); 48 } else { 49 return s; 50 } 51 } 52 53 static inline uint64_t tswap64(uint64_t s) 54 { 55 if (target_needs_bswap()) { 56 return bswap64(s); 57 } else { 58 return s; 59 } 60 } 61 62 static inline void tswap16s(uint16_t *s) 63 { 64 if (target_needs_bswap()) { 65 *s = bswap16(*s); 66 } 67 } 68 69 static inline void tswap32s(uint32_t *s) 70 { 71 if (target_needs_bswap()) { 72 *s = bswap32(*s); 73 } 74 } 75 76 static inline void tswap64s(uint64_t *s) 77 { 78 if (target_needs_bswap()) { 79 *s = bswap64(*s); 80 } 81 } 82 83 /* Return ld{word}_{le,be}_p following target endianness. */ 84 #define LOAD_IMPL(word, args...) \ 85 do { \ 86 if (target_big_endian()) { \ 87 return glue(glue(ld, word), _be_p)(args); \ 88 } else { \ 89 return glue(glue(ld, word), _le_p)(args); \ 90 } \ 91 } while (0) 92 93 static inline int lduw_p(const void *ptr) 94 { 95 LOAD_IMPL(uw, ptr); 96 } 97 98 static inline int ldsw_p(const void *ptr) 99 { 100 LOAD_IMPL(sw, ptr); 101 } 102 103 static inline int ldl_p(const void *ptr) 104 { 105 LOAD_IMPL(l, ptr); 106 } 107 108 static inline uint64_t ldq_p(const void *ptr) 109 { 110 LOAD_IMPL(q, ptr); 111 } 112 113 static inline uint64_t ldn_p(const void *ptr, int sz) 114 { 115 LOAD_IMPL(n, ptr, sz); 116 } 117 118 #undef LOAD_IMPL 119 120 /* Call st{word}_{le,be}_p following target endianness. */ 121 #define STORE_IMPL(word, args...) \ 122 do { \ 123 if (target_big_endian()) { \ 124 glue(glue(st, word), _be_p)(args); \ 125 } else { \ 126 glue(glue(st, word), _le_p)(args); \ 127 } \ 128 } while (0) 129 130 131 static inline void stw_p(void *ptr, uint16_t v) 132 { 133 STORE_IMPL(w, ptr, v); 134 } 135 136 static inline void stl_p(void *ptr, uint32_t v) 137 { 138 STORE_IMPL(l, ptr, v); 139 } 140 141 static inline void stq_p(void *ptr, uint64_t v) 142 { 143 STORE_IMPL(q, ptr, v); 144 } 145 146 static inline void stn_p(void *ptr, int sz, uint64_t v) 147 { 148 STORE_IMPL(n, ptr, sz, v); 149 } 150 151 #undef STORE_IMPL 152 153 #endif /* TSWAP_H */ 154