muldivrt.s 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310
  1. /*
  2. * ulong
  3. * _udiv(ulong num, ulong den)
  4. * {
  5. * int i;
  6. * ulong quo;
  7. *
  8. * if(den == 0)
  9. * *(ulong*)-1 = 0;
  10. * quo = num;
  11. * if(quo > 1<<(32-1))
  12. * quo = 1<<(32-1);
  13. * for(i=0; den<quo; i++)
  14. * den <<= 1;
  15. * quo = 0;
  16. * for(; i>=0; i--) {
  17. * quo <<= 1;
  18. * if(num >= den) {
  19. * num -= den;
  20. * quo |= 1;
  21. * }
  22. * den >>= 1;
  23. * }
  24. * return quo::num;
  25. * }
  26. */
  27. #define NOPROF 1
  28. /*
  29. * calling sequence:
  30. * num: 4(R1)
  31. * den: 8(R1)
  32. * returns
  33. * quo: 4(R1)
  34. * rem: 8(R1)
  35. */
  36. TEXT _udivmod(SB), NOPROF, $-4
  37. MOVW $(1<<31), R11
  38. MOVW 4(R1), R13 /* numerator */
  39. MOVW 8(R1), R10 /* denominator */
  40. CMP R10, R0
  41. BNE udm20
  42. MOVW R0, -1(R0) /* fault -- divide by zero */
  43. udm20:
  44. MOVW R13, R12
  45. CMP R13, R11
  46. BLEU udm34
  47. MOVW R11, R12
  48. udm34:
  49. MOVW R0, R11
  50. udm38:
  51. CMP R10, R12
  52. BCC udm54
  53. SLL $1, R10
  54. ADD $1, R11
  55. BA udm38
  56. udm54:
  57. MOVW R0, R12
  58. udm58:
  59. CMP R11, R0
  60. BL udm8c
  61. SLL $1, R12
  62. CMP R13, R10
  63. BCS udm7c
  64. SUB R10, R13
  65. OR $1, R12
  66. udm7c:
  67. SRL $1, R10
  68. SUB $1, R11
  69. BA udm58
  70. udm8c:
  71. MOVW R12, 4(R1) /* quotent */
  72. MOVW R13, 8(R1) /* remainder */
  73. JMPL 8(R15)
  74. /*
  75. * save working registers
  76. * and bring in num/den parameters
  77. */
  78. TEXT _unsarg(SB), NOPROF, $-4
  79. MOVW R10, 12(R1)
  80. MOVW R11, 16(R1)
  81. MOVW R12, 20(R1)
  82. MOVW R13, 24(R1)
  83. MOVW R14, 4(R1)
  84. MOVW 32(R1), R14
  85. MOVW R14, 8(R1)
  86. JMPL 8(R15)
  87. /*
  88. * save working registers
  89. * and bring in absolute value
  90. * of num/den parameters
  91. */
  92. TEXT _absarg(SB), NOPROF, $-4
  93. MOVW R10, 12(R1)
  94. MOVW R11, 16(R1)
  95. MOVW R12, 20(R1)
  96. MOVW R13, 24(R1)
  97. MOVW R14, 28(R1)
  98. CMP R14, R0
  99. BGE ab1
  100. SUB R14, R0, R14
  101. ab1:
  102. MOVW R14, 4(R1) /* numerator */
  103. MOVW 32(R1), R14
  104. CMP R14, R0
  105. BGE ab2
  106. SUB R14, R0, R14
  107. ab2:
  108. MOVW R14, 8(R1) /* denominator */
  109. JMPL 8(R15)
  110. /*
  111. * restore registers and
  112. * return to original caller
  113. * answer is in R14
  114. */
  115. TEXT _retarg(SB), NOPROF, $-4
  116. MOVW 12(R1), R10
  117. MOVW 16(R1), R11
  118. MOVW 20(R1), R12
  119. MOVW 24(R1), R13
  120. MOVW 0(R1), R15
  121. ADD $28, R1
  122. JMP 8(R15) /* back to main sequence */
  123. /*
  124. * calling sequence
  125. * num: R14
  126. * den: 8(R1)
  127. * returns
  128. * quo: R14
  129. */
  130. TEXT _div(SB), NOPROF, $-4
  131. SUB $28, R1 /* 4 reg save, 2 parameters, link */
  132. MOVW R15, 0(R1)
  133. JMPL _absarg(SB)
  134. JMPL _udivmod(SB)
  135. MOVW 4(R1), R14
  136. MOVW 28(R1), R10 /* clean up the sign */
  137. MOVW 32(R1), R11
  138. XORCC R11, R10, R0
  139. BGE div1
  140. SUB R14, R0, R14
  141. div1:
  142. JMPL _retarg(SB)
  143. JMP 8(R15) /* not executed */
  144. /*
  145. * calling sequence
  146. * num: R14
  147. * den: 8(R1)
  148. * returns
  149. * quo: R14
  150. */
  151. TEXT _divl(SB), NOPROF, $-4
  152. SUB $((4+2+1)*4), R1 /* 4 reg save, 2 parameters, link */
  153. MOVW R15, 0(R1)
  154. JMPL _unsarg(SB)
  155. JMPL _udivmod(SB)
  156. MOVW 4(R1), R14
  157. JMPL _retarg(SB)
  158. JMP 8(R15) /* not executed */
  159. /*
  160. * calling sequence
  161. * num: R14
  162. * den: 8(R1)
  163. * returns
  164. * rem: R14
  165. */
  166. TEXT _mod(SB), NOPROF, $-4
  167. SUB $28, R1 /* 4 reg save, 2 parameters, link */
  168. MOVW R15, 0(R1)
  169. JMPL _absarg(SB)
  170. JMPL _udivmod(SB)
  171. MOVW 8(R1), R14
  172. MOVW 28(R1), R10 /* clean up the sign */
  173. CMP R10, R0
  174. BGE mod1
  175. SUB R14, R0, R14
  176. mod1:
  177. JMPL _retarg(SB)
  178. JMP 8(R15) /* not executed */
  179. /*
  180. * calling sequence
  181. * num: R14
  182. * den: 8(R1)
  183. * returns
  184. * rem: R14
  185. */
  186. TEXT _modl(SB), NOPROF, $-4
  187. SUB $28, R1 /* 4 reg save, 2 parameters, link */
  188. MOVW R15, 0(R1)
  189. JMPL _unsarg(SB)
  190. JMPL _udivmod(SB)
  191. MOVW 8(R1), R14
  192. JMPL _retarg(SB)
  193. JMP 8(R15) /* not executed */
  194. /*
  195. * special calling sequence:
  196. * arg1 in R14
  197. * arg2 in 4(R1), will save R9
  198. * nothing in 0(R1), will save R8
  199. * result in R14
  200. */
  201. TEXT _mul+0(SB), NOPROF, $-4
  202. /*
  203. * exchange stack and registers
  204. */
  205. MOVW R8, 0(R1)
  206. MOVW 4(R1), R8
  207. MOVW R9, 4(R1)
  208. CMP R14, R8
  209. BLE mul1
  210. MOVW R14, R9
  211. MOVW R8, R14
  212. MOVW R9, R8
  213. mul1:
  214. MOVW R14, Y
  215. ANDNCC $0xFFF, R14, R0
  216. BE mul_shortway
  217. ANDCC R0, R0, R9 /* zero partial product and clear N and V cond's */
  218. /* long multiply */
  219. MULSCC R8, R9, R9 /* 0 */
  220. MULSCC R8, R9, R9 /* 1 */
  221. MULSCC R8, R9, R9 /* 2 */
  222. MULSCC R8, R9, R9 /* 3 */
  223. MULSCC R8, R9, R9 /* 4 */
  224. MULSCC R8, R9, R9 /* 5 */
  225. MULSCC R8, R9, R9 /* 6 */
  226. MULSCC R8, R9, R9 /* 7 */
  227. MULSCC R8, R9, R9 /* 8 */
  228. MULSCC R8, R9, R9 /* 9 */
  229. MULSCC R8, R9, R9 /* 10 */
  230. MULSCC R8, R9, R9 /* 11 */
  231. MULSCC R8, R9, R9 /* 12 */
  232. MULSCC R8, R9, R9 /* 13 */
  233. MULSCC R8, R9, R9 /* 14 */
  234. MULSCC R8, R9, R9 /* 15 */
  235. MULSCC R8, R9, R9 /* 16 */
  236. MULSCC R8, R9, R9 /* 17 */
  237. MULSCC R8, R9, R9 /* 18 */
  238. MULSCC R8, R9, R9 /* 19 */
  239. MULSCC R8, R9, R9 /* 20 */
  240. MULSCC R8, R9, R9 /* 21 */
  241. MULSCC R8, R9, R9 /* 22 */
  242. MULSCC R8, R9, R9 /* 23 */
  243. MULSCC R8, R9, R9 /* 24 */
  244. MULSCC R8, R9, R9 /* 25 */
  245. MULSCC R8, R9, R9 /* 26 */
  246. MULSCC R8, R9, R9 /* 27 */
  247. MULSCC R8, R9, R9 /* 28 */
  248. MULSCC R8, R9, R9 /* 29 */
  249. MULSCC R8, R9, R9 /* 30 */
  250. MULSCC R8, R9, R9 /* 31 */
  251. MULSCC R0, R9, R9 /* 32; shift only */
  252. MOVW Y, R14 /* get low part */
  253. BA mul_return
  254. mul_shortway:
  255. ANDCC R0, R0, R9 /* zero partial product and clear N and V cond's */
  256. MULSCC R8, R9, R9 /* 0 */
  257. MULSCC R8, R9, R9 /* 1 */
  258. MULSCC R8, R9, R9 /* 2 */
  259. MULSCC R8, R9, R9 /* 3 */
  260. MULSCC R8, R9, R9 /* 4 */
  261. MULSCC R8, R9, R9 /* 5 */
  262. MULSCC R8, R9, R9 /* 6 */
  263. MULSCC R8, R9, R9 /* 7 */
  264. MULSCC R8, R9, R9 /* 8 */
  265. MULSCC R8, R9, R9 /* 9 */
  266. MULSCC R8, R9, R9 /* 10 */
  267. MULSCC R8, R9, R9 /* 11 */
  268. MULSCC R0, R9, R9 /* 12; shift only */
  269. MOVW Y, R8
  270. SLL $12, R9
  271. SRL $20, R8
  272. OR R8, R9, R14
  273. mul_return:
  274. MOVW 0(R1), R8
  275. MOVW 4(R1), R9
  276. JMP 8(R15)