divU.S 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235
  1. /* 32 and 64-bit millicode, original author Hewlett-Packard
  2. adapted for gcc by Paul Bame <bame@debian.org>
  3. and Alan Modra <alan@linuxcare.com.au>.
  4. Copyright 2001, 2002, 2003 Free Software Foundation, Inc.
  5. This file is part of GCC and is released under the terms of
  6. of the GNU General Public License as published by the Free Software
  7. Foundation; either version 2, or (at your option) any later version.
  8. See the file COPYING in the top-level GCC source directory for a copy
  9. of the license. */
  10. #include "milli.h"
  11. #ifdef L_divU
  12. /* ROUTINE: $$divU
  13. .
  14. . Single precision divide for unsigned integers.
  15. .
  16. . Quotient is truncated towards zero.
  17. . Traps on divide by zero.
  18. INPUT REGISTERS:
  19. . arg0 == dividend
  20. . arg1 == divisor
  21. . mrp == return pc
  22. . sr0 == return space when called externally
  23. OUTPUT REGISTERS:
  24. . arg0 = undefined
  25. . arg1 = undefined
  26. . ret1 = quotient
  27. OTHER REGISTERS AFFECTED:
  28. . r1 = undefined
  29. SIDE EFFECTS:
  30. . Causes a trap under the following conditions:
  31. . divisor is zero
  32. . Changes memory at the following places:
  33. . NONE
  34. PERMISSIBLE CONTEXT:
  35. . Unwindable.
  36. . Does not create a stack frame.
  37. . Suitable for internal or external millicode.
  38. . Assumes the special millicode register conventions.
  39. DISCUSSION:
  40. . Branchs to other millicode routines using BE:
  41. . $$divU_# for 3,5,6,7,9,10,12,14,15
  42. .
  43. . For selected small divisors calls the special divide by constant
  44. . routines written by Karl Pettis. These are: 3,5,6,7,9,10,12,14,15. */
  45. RDEFINE(temp,r1)
  46. RDEFINE(retreg,ret1) /* r29 */
  47. RDEFINE(temp1,arg0)
  48. SUBSPA_MILLI_DIV
  49. ATTR_MILLI
  50. .export $$divU,millicode
  51. .import $$divU_3,millicode
  52. .import $$divU_5,millicode
  53. .import $$divU_6,millicode
  54. .import $$divU_7,millicode
  55. .import $$divU_9,millicode
  56. .import $$divU_10,millicode
  57. .import $$divU_12,millicode
  58. .import $$divU_14,millicode
  59. .import $$divU_15,millicode
  60. .proc
  61. .callinfo millicode
  62. .entry
  63. GSYM($$divU)
  64. /* The subtract is not nullified since it does no harm and can be used
  65. by the two cases that branch back to "normal". */
  66. ldo -1(arg1),temp /* is there at most one bit set ? */
  67. and,= arg1,temp,r0 /* if so, denominator is power of 2 */
  68. b LREF(regular_seq)
  69. addit,= 0,arg1,0 /* trap for zero dvr */
  70. copy arg0,retreg
  71. extru,= arg1,15,16,temp /* test denominator with 0xffff0000 */
  72. extru retreg,15,16,retreg /* retreg = retreg >> 16 */
  73. or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 16) */
  74. ldi 0xcc,temp1 /* setup 0xcc in temp1 */
  75. extru,= arg1,23,8,temp /* test denominator with 0xff00 */
  76. extru retreg,23,24,retreg /* retreg = retreg >> 8 */
  77. or arg1,temp,arg1 /* arg1 = arg1 | (arg1 >> 8) */
  78. ldi 0xaa,temp /* setup 0xaa in temp */
  79. extru,= arg1,27,4,r0 /* test denominator with 0xf0 */
  80. extru retreg,27,28,retreg /* retreg = retreg >> 4 */
  81. and,= arg1,temp1,r0 /* test denominator with 0xcc */
  82. extru retreg,29,30,retreg /* retreg = retreg >> 2 */
  83. and,= arg1,temp,r0 /* test denominator with 0xaa */
  84. extru retreg,30,31,retreg /* retreg = retreg >> 1 */
  85. MILLIRETN
  86. nop
  87. LSYM(regular_seq)
  88. comib,>= 15,arg1,LREF(special_divisor)
  89. subi 0,arg1,temp /* clear carry, negate the divisor */
  90. ds r0,temp,r0 /* set V-bit to 1 */
  91. LSYM(normal)
  92. add arg0,arg0,retreg /* shift msb bit into carry */
  93. ds r0,arg1,temp /* 1st divide step, if no carry */
  94. addc retreg,retreg,retreg /* shift retreg with/into carry */
  95. ds temp,arg1,temp /* 2nd divide step */
  96. addc retreg,retreg,retreg /* shift retreg with/into carry */
  97. ds temp,arg1,temp /* 3rd divide step */
  98. addc retreg,retreg,retreg /* shift retreg with/into carry */
  99. ds temp,arg1,temp /* 4th divide step */
  100. addc retreg,retreg,retreg /* shift retreg with/into carry */
  101. ds temp,arg1,temp /* 5th divide step */
  102. addc retreg,retreg,retreg /* shift retreg with/into carry */
  103. ds temp,arg1,temp /* 6th divide step */
  104. addc retreg,retreg,retreg /* shift retreg with/into carry */
  105. ds temp,arg1,temp /* 7th divide step */
  106. addc retreg,retreg,retreg /* shift retreg with/into carry */
  107. ds temp,arg1,temp /* 8th divide step */
  108. addc retreg,retreg,retreg /* shift retreg with/into carry */
  109. ds temp,arg1,temp /* 9th divide step */
  110. addc retreg,retreg,retreg /* shift retreg with/into carry */
  111. ds temp,arg1,temp /* 10th divide step */
  112. addc retreg,retreg,retreg /* shift retreg with/into carry */
  113. ds temp,arg1,temp /* 11th divide step */
  114. addc retreg,retreg,retreg /* shift retreg with/into carry */
  115. ds temp,arg1,temp /* 12th divide step */
  116. addc retreg,retreg,retreg /* shift retreg with/into carry */
  117. ds temp,arg1,temp /* 13th divide step */
  118. addc retreg,retreg,retreg /* shift retreg with/into carry */
  119. ds temp,arg1,temp /* 14th divide step */
  120. addc retreg,retreg,retreg /* shift retreg with/into carry */
  121. ds temp,arg1,temp /* 15th divide step */
  122. addc retreg,retreg,retreg /* shift retreg with/into carry */
  123. ds temp,arg1,temp /* 16th divide step */
  124. addc retreg,retreg,retreg /* shift retreg with/into carry */
  125. ds temp,arg1,temp /* 17th divide step */
  126. addc retreg,retreg,retreg /* shift retreg with/into carry */
  127. ds temp,arg1,temp /* 18th divide step */
  128. addc retreg,retreg,retreg /* shift retreg with/into carry */
  129. ds temp,arg1,temp /* 19th divide step */
  130. addc retreg,retreg,retreg /* shift retreg with/into carry */
  131. ds temp,arg1,temp /* 20th divide step */
  132. addc retreg,retreg,retreg /* shift retreg with/into carry */
  133. ds temp,arg1,temp /* 21st divide step */
  134. addc retreg,retreg,retreg /* shift retreg with/into carry */
  135. ds temp,arg1,temp /* 22nd divide step */
  136. addc retreg,retreg,retreg /* shift retreg with/into carry */
  137. ds temp,arg1,temp /* 23rd divide step */
  138. addc retreg,retreg,retreg /* shift retreg with/into carry */
  139. ds temp,arg1,temp /* 24th divide step */
  140. addc retreg,retreg,retreg /* shift retreg with/into carry */
  141. ds temp,arg1,temp /* 25th divide step */
  142. addc retreg,retreg,retreg /* shift retreg with/into carry */
  143. ds temp,arg1,temp /* 26th divide step */
  144. addc retreg,retreg,retreg /* shift retreg with/into carry */
  145. ds temp,arg1,temp /* 27th divide step */
  146. addc retreg,retreg,retreg /* shift retreg with/into carry */
  147. ds temp,arg1,temp /* 28th divide step */
  148. addc retreg,retreg,retreg /* shift retreg with/into carry */
  149. ds temp,arg1,temp /* 29th divide step */
  150. addc retreg,retreg,retreg /* shift retreg with/into carry */
  151. ds temp,arg1,temp /* 30th divide step */
  152. addc retreg,retreg,retreg /* shift retreg with/into carry */
  153. ds temp,arg1,temp /* 31st divide step */
  154. addc retreg,retreg,retreg /* shift retreg with/into carry */
  155. ds temp,arg1,temp /* 32nd divide step, */
  156. MILLIRET
  157. addc retreg,retreg,retreg /* shift last retreg bit into retreg */
  158. /* Handle the cases where divisor is a small constant or has high bit on. */
  159. LSYM(special_divisor)
  160. /* blr arg1,r0 */
  161. /* comib,>,n 0,arg1,LREF(big_divisor) ; nullify previous instruction */
  162. /* Pratap 8/13/90. The 815 Stirling chip set has a bug that prevents us from
  163. generating such a blr, comib sequence. A problem in nullification. So I
  164. rewrote this code. */
  165. #if defined(CONFIG_64BIT)
  166. /* Clear the upper 32 bits of the arg1 register. We are working with
  167. small divisors (and 32-bit unsigned integers) We must not be mislead
  168. by "1" bits left in the upper 32 bits. */
  169. depd %r0,31,32,%r25
  170. #endif
  171. comib,> 0,arg1,LREF(big_divisor)
  172. nop
  173. blr arg1,r0
  174. nop
  175. LSYM(zero_divisor) /* this label is here to provide external visibility */
  176. addit,= 0,arg1,0 /* trap for zero dvr */
  177. nop
  178. MILLIRET /* divisor == 1 */
  179. copy arg0,retreg
  180. MILLIRET /* divisor == 2 */
  181. extru arg0,30,31,retreg
  182. MILLI_BEN($$divU_3) /* divisor == 3 */
  183. nop
  184. MILLIRET /* divisor == 4 */
  185. extru arg0,29,30,retreg
  186. MILLI_BEN($$divU_5) /* divisor == 5 */
  187. nop
  188. MILLI_BEN($$divU_6) /* divisor == 6 */
  189. nop
  190. MILLI_BEN($$divU_7) /* divisor == 7 */
  191. nop
  192. MILLIRET /* divisor == 8 */
  193. extru arg0,28,29,retreg
  194. MILLI_BEN($$divU_9) /* divisor == 9 */
  195. nop
  196. MILLI_BEN($$divU_10) /* divisor == 10 */
  197. nop
  198. b LREF(normal) /* divisor == 11 */
  199. ds r0,temp,r0 /* set V-bit to 1 */
  200. MILLI_BEN($$divU_12) /* divisor == 12 */
  201. nop
  202. b LREF(normal) /* divisor == 13 */
  203. ds r0,temp,r0 /* set V-bit to 1 */
  204. MILLI_BEN($$divU_14) /* divisor == 14 */
  205. nop
  206. MILLI_BEN($$divU_15) /* divisor == 15 */
  207. nop
  208. /* Handle the case where the high bit is on in the divisor.
  209. Compute: if( dividend>=divisor) quotient=1; else quotient=0;
  210. Note: dividend>==divisor iff dividend-divisor does not borrow
  211. and not borrow iff carry. */
  212. LSYM(big_divisor)
  213. sub arg0,arg1,r0
  214. MILLIRET
  215. addc r0,r0,retreg
  216. .exit
  217. .procend
  218. .end
  219. #endif