div.c 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206
  1. #include "gc.h"
  2. /*
  3. * Based on: Granlund, T.; Montgomery, P.L.
  4. * "Division by Invariant Integers using Multiplication".
  5. * SIGPLAN Notices, Vol. 29, June 1994, page 61.
  6. */
  7. #define TN(n) (1ULL << (n))
  8. #define T31 TN(31)
  9. #define T32 TN(32)
  10. int
  11. multiplier(ulong d, int p, uvlong *mp)
  12. {
  13. int l;
  14. uvlong mlo, mhi, tlo, thi;
  15. l = topbit(d - 1) + 1;
  16. mlo = (((TN(l) - d) << 32) / d) + T32;
  17. if(l + p == 64)
  18. mhi = (((TN(l) + 1 - d) << 32) / d) + T32;
  19. else
  20. mhi = (TN(32 + l) + TN(32 + l - p)) / d;
  21. assert(mlo < mhi);
  22. while(l > 0) {
  23. tlo = mlo >> 1;
  24. thi = mhi >> 1;
  25. if(tlo == thi)
  26. break;
  27. mlo = tlo;
  28. mhi = thi;
  29. l--;
  30. }
  31. *mp = mhi;
  32. return l;
  33. }
  34. int
  35. sdiv(ulong d, ulong *mp, int *sp)
  36. {
  37. int s;
  38. uvlong m;
  39. s = multiplier(d, 32 - 1, &m);
  40. *mp = m;
  41. *sp = s;
  42. if(m >= T31)
  43. return 1;
  44. else
  45. return 0;
  46. }
  47. int
  48. udiv(ulong d, ulong *mp, int *sp, int *pp)
  49. {
  50. int p, s;
  51. uvlong m;
  52. s = multiplier(d, 32, &m);
  53. p = 0;
  54. if(m >= T32) {
  55. while((d & 1) == 0) {
  56. d >>= 1;
  57. p++;
  58. }
  59. s = multiplier(d, 32 - p, &m);
  60. }
  61. *mp = m;
  62. *pp = p;
  63. if(m >= T32) {
  64. assert(p == 0);
  65. *sp = s - 1;
  66. return 1;
  67. }
  68. else {
  69. *sp = s;
  70. return 0;
  71. }
  72. }
  73. void
  74. sdivgen(Node *l, Node *r, Node *ax, Node *dx)
  75. {
  76. int a, s;
  77. ulong m;
  78. vlong c;
  79. c = r->vconst;
  80. if(c < 0)
  81. c = -c;
  82. a = sdiv(c, &m, &s);
  83. //print("a=%d i=%ld s=%d m=%lux\n", a, (long)r->vconst, s, m);
  84. gins(AMOVL, nodconst(m), ax);
  85. gins(AIMULL, l, Z);
  86. gins(AMOVL, l, ax);
  87. if(a)
  88. gins(AADDL, ax, dx);
  89. gins(ASHRL, nodconst(31), ax);
  90. gins(ASARL, nodconst(s), dx);
  91. gins(AADDL, ax, dx);
  92. if(r->vconst < 0)
  93. gins(ANEGL, Z, dx);
  94. }
  95. void
  96. udivgen(Node *l, Node *r, Node *ax, Node *dx)
  97. {
  98. int a, s, t;
  99. ulong m;
  100. Node nod;
  101. a = udiv(r->vconst, &m, &s, &t);
  102. //print("a=%ud i=%ld p=%d s=%d m=%lux\n", a, (long)r->vconst, t, s, m);
  103. if(t != 0) {
  104. gins(AMOVL, l, ax);
  105. gins(ASHRL, nodconst(t), ax);
  106. gins(AMOVL, nodconst(m), dx);
  107. gins(AMULL, dx, Z);
  108. }
  109. else if(a) {
  110. if(l->op != OREGISTER) {
  111. regalloc(&nod, l, Z);
  112. gins(AMOVL, l, &nod);
  113. l = &nod;
  114. }
  115. gins(AMOVL, nodconst(m), ax);
  116. gins(AMULL, l, Z);
  117. gins(AADDL, l, dx);
  118. gins(ARCRL, nodconst(1), dx);
  119. if(l == &nod)
  120. regfree(l);
  121. }
  122. else {
  123. gins(AMOVL, nodconst(m), ax);
  124. gins(AMULL, l, Z);
  125. }
  126. if(s != 0)
  127. gins(ASHRL, nodconst(s), dx);
  128. }
  129. void
  130. sext(Node *d, Node *s, Node *l)
  131. {
  132. if(s->reg == D_AX && !nodreg(d, Z, D_DX)) {
  133. reg[D_DX]++;
  134. gins(ACDQ, Z, Z);
  135. }
  136. else {
  137. regalloc(d, l, Z);
  138. gins(AMOVL, s, d);
  139. gins(ASARL, nodconst(31), d);
  140. }
  141. }
  142. void
  143. sdiv2(long c, int v, Node *l, Node *n)
  144. {
  145. Node nod;
  146. if(v > 0) {
  147. if(v > 1) {
  148. sext(&nod, n, l);
  149. gins(AANDL, nodconst((1 << v) - 1), &nod);
  150. gins(AADDL, &nod, n);
  151. regfree(&nod);
  152. }
  153. else {
  154. gins(ACMPL, n, nodconst(0x80000000));
  155. gins(ASBBL, nodconst(-1), n);
  156. }
  157. gins(ASARL, nodconst(v), n);
  158. }
  159. if(c < 0)
  160. gins(ANEGL, Z, n);
  161. }
  162. void
  163. smod2(long c, int v, Node *l, Node *n)
  164. {
  165. Node nod;
  166. if(c == 1) {
  167. zeroregm(n);
  168. return;
  169. }
  170. sext(&nod, n, l);
  171. if(v == 0) {
  172. zeroregm(n);
  173. gins(AXORL, &nod, n);
  174. gins(ASUBL, &nod, n);
  175. }
  176. else if(v > 1) {
  177. gins(AANDL, nodconst((1 << v) - 1), &nod);
  178. gins(AADDL, &nod, n);
  179. gins(AANDL, nodconst((1 << v) - 1), n);
  180. gins(ASUBL, &nod, n);
  181. }
  182. else {
  183. gins(AANDL, nodconst(1), n);
  184. gins(AXORL, &nod, n);
  185. gins(ASUBL, &nod, n);
  186. }
  187. regfree(&nod);
  188. }