div.c 3.7 KB

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