bytesex.h 8.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. /* ----------------------------------------------------------------------- *
  2. *
  3. * Copyright 1996-2017 The NASM Authors - All Rights Reserved
  4. * See the file AUTHORS included with the NASM distribution for
  5. * the specific copyright holders.
  6. *
  7. * Redistribution and use in source and binary forms, with or without
  8. * modification, are permitted provided that the following
  9. * conditions are met:
  10. *
  11. * * Redistributions of source code must retain the above copyright
  12. * notice, this list of conditions and the following disclaimer.
  13. * * Redistributions in binary form must reproduce the above
  14. * copyright notice, this list of conditions and the following
  15. * disclaimer in the documentation and/or other materials provided
  16. * with the distribution.
  17. *
  18. * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
  19. * CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
  20. * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
  21. * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
  22. * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
  23. * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  24. * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
  25. * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
  26. * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  27. * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
  28. * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
  29. * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
  30. * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  31. *
  32. * ----------------------------------------------------------------------- */
  33. /*
  34. * bytesex.h - byte order helper functions
  35. *
  36. * In this function, be careful about getting X86_MEMORY versus
  37. * LITTLE_ENDIAN correct: X86_MEMORY also means we are allowed to
  38. * do unaligned memory references, and is probabilistic.
  39. */
  40. #ifndef NASM_BYTEORD_H
  41. #define NASM_BYTEORD_H
  42. #include "compiler.h"
  43. /*
  44. * Some handy macros that will probably be of use in more than one
  45. * output format: convert integers into little-endian byte packed
  46. * format in memory.
  47. */
  48. #define WRITECHAR(p,v) \
  49. do { \
  50. uint8_t *_wc_p = (uint8_t *)(p); \
  51. *_wc_p++ = (v); \
  52. (p) = (void *)_wc_p; \
  53. } while (0)
  54. #if X86_MEMORY
  55. #define WRITESHORT(p,v) \
  56. do { \
  57. uint16_t *_ws_p = (uint16_t *)(p); \
  58. *_ws_p++ = (v); \
  59. (p) = (void *)_ws_p; \
  60. } while (0)
  61. #define WRITELONG(p,v) \
  62. do { \
  63. uint32_t *_wl_p = (uint32_t *)(p); \
  64. *_wl_p++ = (v); \
  65. (p) = (void *)_wl_p; \
  66. } while (0)
  67. #define WRITEDLONG(p,v) \
  68. do { \
  69. uint64_t *_wq_p = (uint64_t *)(p); \
  70. *_wq_p++ = (v); \
  71. (p) = (void *)_wq_p; \
  72. } while (0)
  73. #else /* !X86_MEMORY */
  74. #define WRITESHORT(p,v) \
  75. do { \
  76. uint8_t *_ws_p = (uint8_t *)(p); \
  77. const uint16_t _ws_v = (v); \
  78. WRITECHAR(_ws_p, _ws_v); \
  79. WRITECHAR(_ws_p, _ws_v >> 8); \
  80. (p) = (void *)_ws_p; \
  81. } while (0)
  82. #define WRITELONG(p,v) \
  83. do { \
  84. uint8_t *_wl_p = (uint8_t *)(p); \
  85. const uint32_t _wl_v = (v); \
  86. WRITESHORT(_wl_p, _wl_v); \
  87. WRITESHORT(_wl_p, _wl_v >> 16); \
  88. (p) = (void *)_wl_p; \
  89. } while (0)
  90. #define WRITEDLONG(p,v) \
  91. do { \
  92. uint8_t *_wq_p = (uint8_t *)(p); \
  93. const uint64_t _wq_v = (v); \
  94. WRITELONG(_wq_p, _wq_v); \
  95. WRITELONG(_wq_p, _wq_v >> 32); \
  96. (p) = (void *)_wq_p; \
  97. } while (0)
  98. #endif /* X86_MEMORY */
  99. /*
  100. * Endian control functions which work on a single integer
  101. */
  102. #ifdef WORDS_LITTLEENDIAN
  103. #ifndef HAVE_CPU_TO_LE16
  104. # define cpu_to_le16(v) ((uint16_t)(v))
  105. #endif
  106. #ifndef HAVE_CPU_TO_LE32
  107. # define cpu_to_le32(v) ((uint32_t)(v))
  108. #endif
  109. #ifndef HAVE_CPU_TO_LE64
  110. # define cpu_to_le64(v) ((uint64_t)(v))
  111. #endif
  112. #elif defined(WORDS_BIGENDIAN)
  113. #ifndef HAVE_CPU_TO_LE16
  114. static inline uint16_t cpu_to_le16(uint16_t v)
  115. {
  116. # ifdef HAVE___CPU_TO_LE16
  117. return __cpu_to_le16(v);
  118. # elif defined(HAVE_HTOLE16)
  119. return htole16(v);
  120. # elif defined(HAVE___BSWAP_16)
  121. return __bswap_16(v);
  122. # elif defined(HAVE___BUILTIN_BSWAP16)
  123. return __builtin_bswap16(v);
  124. # elif defined(HAVE__BYTESWAP_USHORT) && (USHRT_MAX == 0xffffU)
  125. return _byteswap_ushort(v);
  126. # else
  127. return (v << 8) | (v >> 8);
  128. # endif
  129. }
  130. #endif
  131. #ifndef HAVE_CPU_TO_LE32
  132. static inline uint32_t cpu_to_le32(uint32_t v)
  133. {
  134. # ifdef HAVE___CPU_TO_LE32
  135. return __cpu_to_le32(v);
  136. # elif defined(HAVE_HTOLE32)
  137. return htole32(v);
  138. # elif defined(HAVE___BSWAP_32)
  139. return __bswap_32(v);
  140. # elif defined(HAVE___BUILTIN_BSWAP32)
  141. return __builtin_bswap32(v);
  142. # elif defined(HAVE__BYTESWAP_ULONG) && (ULONG_MAX == 0xffffffffUL)
  143. return _byteswap_ulong(v);
  144. # else
  145. v = ((v << 8) & 0xff00ff00 ) |
  146. ((v >> 8) & 0x00ff00ff);
  147. return (v << 16) | (v >> 16);
  148. # endif
  149. }
  150. #endif
  151. #ifndef HAVE_CPU_TO_LE64
  152. static inline uint64_t cpu_to_le64(uint64_t v)
  153. {
  154. # ifdef HAVE___CPU_TO_LE64
  155. return __cpu_to_le64(v);
  156. # elif defined(HAVE_HTOLE64)
  157. return htole64(v);
  158. # elif defined(HAVE___BSWAP_64)
  159. return __bswap_64(v);
  160. # elif defined(HAVE___BUILTIN_BSWAP64)
  161. return __builtin_bswap64(v);
  162. # elif defined(HAVE__BYTESWAP_UINT64)
  163. return _byteswap_uint64(v);
  164. # else
  165. v = ((v << 8) & 0xff00ff00ff00ff00ull) |
  166. ((v >> 8) & 0x00ff00ff00ff00ffull);
  167. v = ((v << 16) & 0xffff0000ffff0000ull) |
  168. ((v >> 16) & 0x0000ffff0000ffffull);
  169. return (v << 32) | (v >> 32);
  170. # endif
  171. }
  172. #endif
  173. #else /* not WORDS_LITTLEENDIAN or WORDS_BIGENDIAN */
  174. static inline uint16_t cpu_to_le16(uint16_t v)
  175. {
  176. union u16 {
  177. uint16_t v;
  178. uint8_t c[2];
  179. } x;
  180. uint8_t *cp = &x.c;
  181. WRITESHORT(cp, v);
  182. return x.v;
  183. }
  184. static inline uint32_t cpu_to_le32(uint32_t v)
  185. {
  186. union u32 {
  187. uint32_t v;
  188. uint8_t c[4];
  189. } x;
  190. uint8_t *cp = &x.c;
  191. WRITELONG(cp, v);
  192. return x.v;
  193. }
  194. static inline uint64_t cpu_to_le64(uint64_t v)
  195. {
  196. union u64 {
  197. uint64_t v;
  198. uint8_t c[8];
  199. } x;
  200. uint8_t *cp = &x.c;
  201. WRITEDLONG(cp, v);
  202. return x.v;
  203. }
  204. #endif
  205. #define WRITEADDR(p,v,s) \
  206. do { \
  207. switch (is_constant(s) ? (s) : 0) { \
  208. case 1: \
  209. WRITECHAR(p,v); \
  210. break; \
  211. case 2: \
  212. WRITESHORT(p,v); \
  213. break; \
  214. case 4: \
  215. WRITELONG(p,v); \
  216. break; \
  217. case 8: \
  218. WRITEDLONG(p,v); \
  219. break; \
  220. default: \
  221. { \
  222. const uint64_t _wa_v = cpu_to_le64(v); \
  223. const size_t _wa_s = (s); \
  224. uint8_t * const _wa_p = (uint8_t *)(p); \
  225. memcpy(_wa_p, &_wa_v, _wa_s); \
  226. (p) = (void *)(_wa_p + _wa_s); \
  227. } \
  228. break; \
  229. } \
  230. } while (0)
  231. #endif /* NASM_BYTESEX_H */