udivmoddi4.c 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200
  1. //===-- udivmoddi4.c - Implement __udivmoddi4 -----------------------------===//
  2. //
  3. // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
  4. // See https://llvm.org/LICENSE.txt for license information.
  5. // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
  6. //
  7. //===----------------------------------------------------------------------===//
  8. //
  9. // This file implements __udivmoddi4 for the compiler_rt library.
  10. //
  11. //===----------------------------------------------------------------------===//
  12. #include "int_lib.h"
  13. // Effects: if rem != 0, *rem = a % b
  14. // Returns: a / b
  15. // Translated from Figure 3-40 of The PowerPC Compiler Writer's Guide
  16. #if defined(_MSC_VER) && !defined(__clang__)
  17. // MSVC throws a warning about mod 0 here, disable it for builds that
  18. // warn-as-error
  19. #pragma warning(push)
  20. #pragma warning(disable : 4723 4724)
  21. #endif
  22. COMPILER_RT_ABI du_int __udivmoddi4(du_int a, du_int b, du_int *rem) {
  23. const unsigned n_uword_bits = sizeof(su_int) * CHAR_BIT;
  24. const unsigned n_udword_bits = sizeof(du_int) * CHAR_BIT;
  25. udwords n;
  26. n.all = a;
  27. udwords d;
  28. d.all = b;
  29. udwords q;
  30. udwords r;
  31. unsigned sr;
  32. // special cases, X is unknown, K != 0
  33. if (n.s.high == 0) {
  34. if (d.s.high == 0) {
  35. // 0 X
  36. // ---
  37. // 0 X
  38. if (rem)
  39. *rem = n.s.low % d.s.low;
  40. return n.s.low / d.s.low;
  41. }
  42. // 0 X
  43. // ---
  44. // K X
  45. if (rem)
  46. *rem = n.s.low;
  47. return 0;
  48. }
  49. // n.s.high != 0
  50. if (d.s.low == 0) {
  51. if (d.s.high == 0) {
  52. // K X
  53. // ---
  54. // 0 0
  55. if (rem)
  56. *rem = n.s.high % d.s.low;
  57. return n.s.high / d.s.low;
  58. }
  59. // d.s.high != 0
  60. if (n.s.low == 0) {
  61. // K 0
  62. // ---
  63. // K 0
  64. if (rem) {
  65. r.s.high = n.s.high % d.s.high;
  66. r.s.low = 0;
  67. *rem = r.all;
  68. }
  69. return n.s.high / d.s.high;
  70. }
  71. // K K
  72. // ---
  73. // K 0
  74. if ((d.s.high & (d.s.high - 1)) == 0) /* if d is a power of 2 */ {
  75. if (rem) {
  76. r.s.low = n.s.low;
  77. r.s.high = n.s.high & (d.s.high - 1);
  78. *rem = r.all;
  79. }
  80. return n.s.high >> ctzsi(d.s.high);
  81. }
  82. // K K
  83. // ---
  84. // K 0
  85. sr = clzsi(d.s.high) - clzsi(n.s.high);
  86. // 0 <= sr <= n_uword_bits - 2 or sr large
  87. if (sr > n_uword_bits - 2) {
  88. if (rem)
  89. *rem = n.all;
  90. return 0;
  91. }
  92. ++sr;
  93. // 1 <= sr <= n_uword_bits - 1
  94. // q.all = n.all << (n_udword_bits - sr);
  95. q.s.low = 0;
  96. q.s.high = n.s.low << (n_uword_bits - sr);
  97. // r.all = n.all >> sr;
  98. r.s.high = n.s.high >> sr;
  99. r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
  100. } else /* d.s.low != 0 */ {
  101. if (d.s.high == 0) {
  102. // K X
  103. // ---
  104. // 0 K
  105. if ((d.s.low & (d.s.low - 1)) == 0) /* if d is a power of 2 */ {
  106. if (rem)
  107. *rem = n.s.low & (d.s.low - 1);
  108. if (d.s.low == 1)
  109. return n.all;
  110. sr = ctzsi(d.s.low);
  111. q.s.high = n.s.high >> sr;
  112. q.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
  113. return q.all;
  114. }
  115. // K X
  116. // ---
  117. // 0 K
  118. sr = 1 + n_uword_bits + clzsi(d.s.low) - clzsi(n.s.high);
  119. // 2 <= sr <= n_udword_bits - 1
  120. // q.all = n.all << (n_udword_bits - sr);
  121. // r.all = n.all >> sr;
  122. if (sr == n_uword_bits) {
  123. q.s.low = 0;
  124. q.s.high = n.s.low;
  125. r.s.high = 0;
  126. r.s.low = n.s.high;
  127. } else if (sr < n_uword_bits) /* 2 <= sr <= n_uword_bits - 1 */ {
  128. q.s.low = 0;
  129. q.s.high = n.s.low << (n_uword_bits - sr);
  130. r.s.high = n.s.high >> sr;
  131. r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
  132. } else /* n_uword_bits + 1 <= sr <= n_udword_bits - 1 */ {
  133. q.s.low = n.s.low << (n_udword_bits - sr);
  134. q.s.high = (n.s.high << (n_udword_bits - sr)) |
  135. (n.s.low >> (sr - n_uword_bits));
  136. r.s.high = 0;
  137. r.s.low = n.s.high >> (sr - n_uword_bits);
  138. }
  139. } else {
  140. // K X
  141. // ---
  142. // K K
  143. sr = clzsi(d.s.high) - clzsi(n.s.high);
  144. // 0 <= sr <= n_uword_bits - 1 or sr large
  145. if (sr > n_uword_bits - 1) {
  146. if (rem)
  147. *rem = n.all;
  148. return 0;
  149. }
  150. ++sr;
  151. // 1 <= sr <= n_uword_bits
  152. // q.all = n.all << (n_udword_bits - sr);
  153. q.s.low = 0;
  154. if (sr == n_uword_bits) {
  155. q.s.high = n.s.low;
  156. r.s.high = 0;
  157. r.s.low = n.s.high;
  158. } else {
  159. q.s.high = n.s.low << (n_uword_bits - sr);
  160. r.s.high = n.s.high >> sr;
  161. r.s.low = (n.s.high << (n_uword_bits - sr)) | (n.s.low >> sr);
  162. }
  163. }
  164. }
  165. // Not a special case
  166. // q and r are initialized with:
  167. // q.all = n.all << (n_udword_bits - sr);
  168. // r.all = n.all >> sr;
  169. // 1 <= sr <= n_udword_bits - 1
  170. su_int carry = 0;
  171. for (; sr > 0; --sr) {
  172. // r:q = ((r:q) << 1) | carry
  173. r.s.high = (r.s.high << 1) | (r.s.low >> (n_uword_bits - 1));
  174. r.s.low = (r.s.low << 1) | (q.s.high >> (n_uword_bits - 1));
  175. q.s.high = (q.s.high << 1) | (q.s.low >> (n_uword_bits - 1));
  176. q.s.low = (q.s.low << 1) | carry;
  177. // carry = 0;
  178. // if (r.all >= d.all)
  179. // {
  180. // r.all -= d.all;
  181. // carry = 1;
  182. // }
  183. const di_int s = (di_int)(d.all - r.all - 1) >> (n_udword_bits - 1);
  184. carry = s & 1;
  185. r.all -= d.all & s;
  186. }
  187. q.all = (q.all << 1) | carry;
  188. if (rem)
  189. *rem = r.all;
  190. return q.all;
  191. }
  192. #if defined(_MSC_VER) && !defined(__clang__)
  193. #pragma warning(pop)
  194. #endif