host-utils.h 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. /*
  2. * Utility compute operations used by translated code.
  3. *
  4. * Copyright (c) 2007 Thiemo Seufer
  5. * Copyright (c) 2007 Jocelyn Mayer
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  20. * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. #include "osdep.h"
  26. #if defined(__x86_64__)
  27. #define __HAVE_FAST_MULU64__
  28. static inline void mulu64(uint64_t *plow, uint64_t *phigh,
  29. uint64_t a, uint64_t b)
  30. {
  31. __asm__ ("mul %0\n\t"
  32. : "=d" (*phigh), "=a" (*plow)
  33. : "a" (a), "0" (b));
  34. }
  35. #define __HAVE_FAST_MULS64__
  36. static inline void muls64(uint64_t *plow, uint64_t *phigh,
  37. int64_t a, int64_t b)
  38. {
  39. __asm__ ("imul %0\n\t"
  40. : "=d" (*phigh), "=a" (*plow)
  41. : "a" (a), "0" (b));
  42. }
  43. #else
  44. void muls64(uint64_t *phigh, uint64_t *plow, int64_t a, int64_t b);
  45. void mulu64(uint64_t *phigh, uint64_t *plow, uint64_t a, uint64_t b);
  46. #endif
  47. /* Binary search for leading zeros. */
  48. static inline int clz32(uint32_t val)
  49. {
  50. #if QEMU_GNUC_PREREQ(3, 4)
  51. if (val)
  52. return __builtin_clz(val);
  53. else
  54. return 32;
  55. #else
  56. int cnt = 0;
  57. if (!(val & 0xFFFF0000U)) {
  58. cnt += 16;
  59. val <<= 16;
  60. }
  61. if (!(val & 0xFF000000U)) {
  62. cnt += 8;
  63. val <<= 8;
  64. }
  65. if (!(val & 0xF0000000U)) {
  66. cnt += 4;
  67. val <<= 4;
  68. }
  69. if (!(val & 0xC0000000U)) {
  70. cnt += 2;
  71. val <<= 2;
  72. }
  73. if (!(val & 0x80000000U)) {
  74. cnt++;
  75. val <<= 1;
  76. }
  77. if (!(val & 0x80000000U)) {
  78. cnt++;
  79. }
  80. return cnt;
  81. #endif
  82. }
  83. static inline int clo32(uint32_t val)
  84. {
  85. return clz32(~val);
  86. }
  87. static inline int clz64(uint64_t val)
  88. {
  89. #if QEMU_GNUC_PREREQ(3, 4)
  90. if (val)
  91. return __builtin_clzll(val);
  92. else
  93. return 64;
  94. #else
  95. int cnt = 0;
  96. if (!(val >> 32)) {
  97. cnt += 32;
  98. } else {
  99. val >>= 32;
  100. }
  101. return cnt + clz32(val);
  102. #endif
  103. }
  104. static inline int clo64(uint64_t val)
  105. {
  106. return clz64(~val);
  107. }
  108. static inline int ctz32(uint32_t val)
  109. {
  110. #if QEMU_GNUC_PREREQ(3, 4)
  111. if (val)
  112. return __builtin_ctz(val);
  113. else
  114. return 32;
  115. #else
  116. int cnt;
  117. cnt = 0;
  118. if (!(val & 0x0000FFFFUL)) {
  119. cnt += 16;
  120. val >>= 16;
  121. }
  122. if (!(val & 0x000000FFUL)) {
  123. cnt += 8;
  124. val >>= 8;
  125. }
  126. if (!(val & 0x0000000FUL)) {
  127. cnt += 4;
  128. val >>= 4;
  129. }
  130. if (!(val & 0x00000003UL)) {
  131. cnt += 2;
  132. val >>= 2;
  133. }
  134. if (!(val & 0x00000001UL)) {
  135. cnt++;
  136. val >>= 1;
  137. }
  138. if (!(val & 0x00000001UL)) {
  139. cnt++;
  140. }
  141. return cnt;
  142. #endif
  143. }
  144. static inline int cto32(uint32_t val)
  145. {
  146. return ctz32(~val);
  147. }
  148. static inline int ctz64(uint64_t val)
  149. {
  150. #if QEMU_GNUC_PREREQ(3, 4)
  151. if (val)
  152. return __builtin_ctzll(val);
  153. else
  154. return 64;
  155. #else
  156. int cnt;
  157. cnt = 0;
  158. if (!((uint32_t)val)) {
  159. cnt += 32;
  160. val >>= 32;
  161. }
  162. return cnt + ctz32(val);
  163. #endif
  164. }
  165. static inline int cto64(uint64_t val)
  166. {
  167. return ctz64(~val);
  168. }
  169. static inline int ctpop8(uint8_t val)
  170. {
  171. val = (val & 0x55) + ((val >> 1) & 0x55);
  172. val = (val & 0x33) + ((val >> 2) & 0x33);
  173. val = (val & 0x0f) + ((val >> 4) & 0x0f);
  174. return val;
  175. }
  176. static inline int ctpop16(uint16_t val)
  177. {
  178. val = (val & 0x5555) + ((val >> 1) & 0x5555);
  179. val = (val & 0x3333) + ((val >> 2) & 0x3333);
  180. val = (val & 0x0f0f) + ((val >> 4) & 0x0f0f);
  181. val = (val & 0x00ff) + ((val >> 8) & 0x00ff);
  182. return val;
  183. }
  184. static inline int ctpop32(uint32_t val)
  185. {
  186. #if QEMU_GNUC_PREREQ(3, 4)
  187. return __builtin_popcount(val);
  188. #else
  189. val = (val & 0x55555555) + ((val >> 1) & 0x55555555);
  190. val = (val & 0x33333333) + ((val >> 2) & 0x33333333);
  191. val = (val & 0x0f0f0f0f) + ((val >> 4) & 0x0f0f0f0f);
  192. val = (val & 0x00ff00ff) + ((val >> 8) & 0x00ff00ff);
  193. val = (val & 0x0000ffff) + ((val >> 16) & 0x0000ffff);
  194. return val;
  195. #endif
  196. }
  197. static inline int ctpop64(uint64_t val)
  198. {
  199. #if QEMU_GNUC_PREREQ(3, 4)
  200. return __builtin_popcountll(val);
  201. #else
  202. val = (val & 0x5555555555555555ULL) + ((val >> 1) & 0x5555555555555555ULL);
  203. val = (val & 0x3333333333333333ULL) + ((val >> 2) & 0x3333333333333333ULL);
  204. val = (val & 0x0f0f0f0f0f0f0f0fULL) + ((val >> 4) & 0x0f0f0f0f0f0f0f0fULL);
  205. val = (val & 0x00ff00ff00ff00ffULL) + ((val >> 8) & 0x00ff00ff00ff00ffULL);
  206. val = (val & 0x0000ffff0000ffffULL) + ((val >> 16) & 0x0000ffff0000ffffULL);
  207. val = (val & 0x00000000ffffffffULL) + ((val >> 32) & 0x00000000ffffffffULL);
  208. return val;
  209. #endif
  210. }