124be3369SThomas Huth /* 224be3369SThomas Huth * Macros for swapping a value if the endianness is different 324be3369SThomas Huth * between the target and the host. 424be3369SThomas Huth * 524be3369SThomas Huth * SPDX-License-Identifier: LGPL-2.1-or-later 624be3369SThomas Huth */ 724be3369SThomas Huth 824be3369SThomas Huth #ifndef TSWAP_H 924be3369SThomas Huth #define TSWAP_H 1024be3369SThomas Huth 1124be3369SThomas Huth #include "qemu/bswap.h" 1224be3369SThomas Huth 1342508261SPhilippe Mathieu-Daudé /** 14*b939b8e4SPhilippe Mathieu-Daudé * target_big_endian: 1542508261SPhilippe Mathieu-Daudé * Returns true if the (default) endianness of the target is big endian, 16cfac5cdfSPierrick Bouvier * false otherwise. Common code should normally never need to know about the 17cfac5cdfSPierrick Bouvier * endianness of the target, so please do *not* use this function unless you 18cfac5cdfSPierrick Bouvier * know very well what you are doing! 1942508261SPhilippe Mathieu-Daudé */ 20*b939b8e4SPhilippe Mathieu-Daudé bool target_big_endian(void); 21cfac5cdfSPierrick Bouvier #ifdef COMPILING_PER_TARGET 22*b939b8e4SPhilippe Mathieu-Daudé #define target_big_endian() TARGET_BIG_ENDIAN 23cfac5cdfSPierrick Bouvier #endif 2442508261SPhilippe Mathieu-Daudé 2524be3369SThomas Huth /* 2624be3369SThomas Huth * If we're in target-specific code, we can hard-code the swapping 2724be3369SThomas Huth * condition, otherwise we have to do (slower) run-time checks. 2824be3369SThomas Huth */ 297d7a21baSPhilippe Mathieu-Daudé #ifdef COMPILING_PER_TARGET 3024be3369SThomas Huth #define target_needs_bswap() (HOST_BIG_ENDIAN != TARGET_BIG_ENDIAN) 3124be3369SThomas Huth #else 32*b939b8e4SPhilippe Mathieu-Daudé #define target_needs_bswap() (HOST_BIG_ENDIAN != target_big_endian()) 337d7a21baSPhilippe Mathieu-Daudé #endif /* COMPILING_PER_TARGET */ 3424be3369SThomas Huth 3524be3369SThomas Huth static inline uint16_t tswap16(uint16_t s) 3624be3369SThomas Huth { 3724be3369SThomas Huth if (target_needs_bswap()) { 3824be3369SThomas Huth return bswap16(s); 3924be3369SThomas Huth } else { 4024be3369SThomas Huth return s; 4124be3369SThomas Huth } 4224be3369SThomas Huth } 4324be3369SThomas Huth 4424be3369SThomas Huth static inline uint32_t tswap32(uint32_t s) 4524be3369SThomas Huth { 4624be3369SThomas Huth if (target_needs_bswap()) { 4724be3369SThomas Huth return bswap32(s); 4824be3369SThomas Huth } else { 4924be3369SThomas Huth return s; 5024be3369SThomas Huth } 5124be3369SThomas Huth } 5224be3369SThomas Huth 5324be3369SThomas Huth static inline uint64_t tswap64(uint64_t s) 5424be3369SThomas Huth { 5524be3369SThomas Huth if (target_needs_bswap()) { 5624be3369SThomas Huth return bswap64(s); 5724be3369SThomas Huth } else { 5824be3369SThomas Huth return s; 5924be3369SThomas Huth } 6024be3369SThomas Huth } 6124be3369SThomas Huth 6224be3369SThomas Huth static inline void tswap16s(uint16_t *s) 6324be3369SThomas Huth { 6424be3369SThomas Huth if (target_needs_bswap()) { 6524be3369SThomas Huth *s = bswap16(*s); 6624be3369SThomas Huth } 6724be3369SThomas Huth } 6824be3369SThomas Huth 6924be3369SThomas Huth static inline void tswap32s(uint32_t *s) 7024be3369SThomas Huth { 7124be3369SThomas Huth if (target_needs_bswap()) { 7224be3369SThomas Huth *s = bswap32(*s); 7324be3369SThomas Huth } 7424be3369SThomas Huth } 7524be3369SThomas Huth 7624be3369SThomas Huth static inline void tswap64s(uint64_t *s) 7724be3369SThomas Huth { 7824be3369SThomas Huth if (target_needs_bswap()) { 7924be3369SThomas Huth *s = bswap64(*s); 8024be3369SThomas Huth } 8124be3369SThomas Huth } 8224be3369SThomas Huth 83663310b0SPierrick Bouvier /* Return ld{word}_{le,be}_p following target endianness. */ 84663310b0SPierrick Bouvier #define LOAD_IMPL(word, args...) \ 85663310b0SPierrick Bouvier do { \ 86*b939b8e4SPhilippe Mathieu-Daudé if (target_big_endian()) { \ 87663310b0SPierrick Bouvier return glue(glue(ld, word), _be_p)(args); \ 88663310b0SPierrick Bouvier } else { \ 89663310b0SPierrick Bouvier return glue(glue(ld, word), _le_p)(args); \ 90663310b0SPierrick Bouvier } \ 91663310b0SPierrick Bouvier } while (0) 92663310b0SPierrick Bouvier 93663310b0SPierrick Bouvier static inline int lduw_p(const void *ptr) 94663310b0SPierrick Bouvier { 95663310b0SPierrick Bouvier LOAD_IMPL(uw, ptr); 96663310b0SPierrick Bouvier } 97663310b0SPierrick Bouvier 98663310b0SPierrick Bouvier static inline int ldsw_p(const void *ptr) 99663310b0SPierrick Bouvier { 100663310b0SPierrick Bouvier LOAD_IMPL(sw, ptr); 101663310b0SPierrick Bouvier } 102663310b0SPierrick Bouvier 103663310b0SPierrick Bouvier static inline int ldl_p(const void *ptr) 104663310b0SPierrick Bouvier { 105663310b0SPierrick Bouvier LOAD_IMPL(l, ptr); 106663310b0SPierrick Bouvier } 107663310b0SPierrick Bouvier 108663310b0SPierrick Bouvier static inline uint64_t ldq_p(const void *ptr) 109663310b0SPierrick Bouvier { 110663310b0SPierrick Bouvier LOAD_IMPL(q, ptr); 111663310b0SPierrick Bouvier } 112663310b0SPierrick Bouvier 113663310b0SPierrick Bouvier static inline uint64_t ldn_p(const void *ptr, int sz) 114663310b0SPierrick Bouvier { 115663310b0SPierrick Bouvier LOAD_IMPL(n, ptr, sz); 116663310b0SPierrick Bouvier } 117663310b0SPierrick Bouvier 118663310b0SPierrick Bouvier #undef LOAD_IMPL 119663310b0SPierrick Bouvier 120663310b0SPierrick Bouvier /* Call st{word}_{le,be}_p following target endianness. */ 121663310b0SPierrick Bouvier #define STORE_IMPL(word, args...) \ 122663310b0SPierrick Bouvier do { \ 123*b939b8e4SPhilippe Mathieu-Daudé if (target_big_endian()) { \ 124663310b0SPierrick Bouvier glue(glue(st, word), _be_p)(args); \ 125663310b0SPierrick Bouvier } else { \ 126663310b0SPierrick Bouvier glue(glue(st, word), _le_p)(args); \ 127663310b0SPierrick Bouvier } \ 128663310b0SPierrick Bouvier } while (0) 129663310b0SPierrick Bouvier 130663310b0SPierrick Bouvier 131663310b0SPierrick Bouvier static inline void stw_p(void *ptr, uint16_t v) 132663310b0SPierrick Bouvier { 133663310b0SPierrick Bouvier STORE_IMPL(w, ptr, v); 134663310b0SPierrick Bouvier } 135663310b0SPierrick Bouvier 136663310b0SPierrick Bouvier static inline void stl_p(void *ptr, uint32_t v) 137663310b0SPierrick Bouvier { 138663310b0SPierrick Bouvier STORE_IMPL(l, ptr, v); 139663310b0SPierrick Bouvier } 140663310b0SPierrick Bouvier 141663310b0SPierrick Bouvier static inline void stq_p(void *ptr, uint64_t v) 142663310b0SPierrick Bouvier { 143663310b0SPierrick Bouvier STORE_IMPL(q, ptr, v); 144663310b0SPierrick Bouvier } 145663310b0SPierrick Bouvier 146663310b0SPierrick Bouvier static inline void stn_p(void *ptr, int sz, uint64_t v) 147663310b0SPierrick Bouvier { 148663310b0SPierrick Bouvier STORE_IMPL(n, ptr, sz, v); 149663310b0SPierrick Bouvier } 150663310b0SPierrick Bouvier 151663310b0SPierrick Bouvier #undef STORE_IMPL 152663310b0SPierrick Bouvier 15324be3369SThomas Huth #endif /* TSWAP_H */ 154