remI.S 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185
  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_remI
  12. /* ROUTINE: $$remI
  13. DESCRIPTION:
  14. . $$remI returns the remainder of the division of two signed 32-bit
  15. . integers. The sign of the remainder is the same as the sign of
  16. . the dividend.
  17. INPUT REGISTERS:
  18. . arg0 == dividend
  19. . arg1 == divisor
  20. . mrp == return pc
  21. . sr0 == return space when called externally
  22. OUTPUT REGISTERS:
  23. . arg0 = destroyed
  24. . arg1 = destroyed
  25. . ret1 = remainder
  26. OTHER REGISTERS AFFECTED:
  27. . r1 = undefined
  28. SIDE EFFECTS:
  29. . Causes a trap under the following conditions: DIVIDE BY ZERO
  30. . Changes memory at the following places: NONE
  31. PERMISSIBLE CONTEXT:
  32. . Unwindable
  33. . Does not create a stack frame
  34. . Is usable for internal or external microcode
  35. DISCUSSION:
  36. . Calls other millicode routines via mrp: NONE
  37. . Calls other millicode routines: NONE */
  38. RDEFINE(tmp,r1)
  39. RDEFINE(retreg,ret1)
  40. SUBSPA_MILLI
  41. ATTR_MILLI
  42. .proc
  43. .callinfo millicode
  44. .entry
  45. GSYM($$remI)
  46. GSYM($$remoI)
  47. .export $$remI,MILLICODE
  48. .export $$remoI,MILLICODE
  49. ldo -1(arg1),tmp /* is there at most one bit set ? */
  50. and,<> arg1,tmp,r0 /* if not, don't use power of 2 */
  51. addi,> 0,arg1,r0 /* if denominator > 0, use power */
  52. /* of 2 */
  53. b,n LREF(neg_denom)
  54. LSYM(pow2)
  55. comb,>,n 0,arg0,LREF(neg_num) /* is numerator < 0 ? */
  56. and arg0,tmp,retreg /* get the result */
  57. MILLIRETN
  58. LSYM(neg_num)
  59. subi 0,arg0,arg0 /* negate numerator */
  60. and arg0,tmp,retreg /* get the result */
  61. subi 0,retreg,retreg /* negate result */
  62. MILLIRETN
  63. LSYM(neg_denom)
  64. addi,< 0,arg1,r0 /* if arg1 >= 0, it's not power */
  65. /* of 2 */
  66. b,n LREF(regular_seq)
  67. sub r0,arg1,tmp /* make denominator positive */
  68. comb,=,n arg1,tmp,LREF(regular_seq) /* test against 0x80000000 and 0 */
  69. ldo -1(tmp),retreg /* is there at most one bit set ? */
  70. and,= tmp,retreg,r0 /* if not, go to regular_seq */
  71. b,n LREF(regular_seq)
  72. comb,>,n 0,arg0,LREF(neg_num_2) /* if arg0 < 0, negate it */
  73. and arg0,retreg,retreg
  74. MILLIRETN
  75. LSYM(neg_num_2)
  76. subi 0,arg0,tmp /* test against 0x80000000 */
  77. and tmp,retreg,retreg
  78. subi 0,retreg,retreg
  79. MILLIRETN
  80. LSYM(regular_seq)
  81. addit,= 0,arg1,0 /* trap if div by zero */
  82. add,>= 0,arg0,retreg /* move dividend, if retreg < 0, */
  83. sub 0,retreg,retreg /* make it positive */
  84. sub 0,arg1, tmp /* clear carry, */
  85. /* negate the divisor */
  86. ds 0, tmp,0 /* set V-bit to the comple- */
  87. /* ment of the divisor sign */
  88. or 0,0, tmp /* clear tmp */
  89. add retreg,retreg,retreg /* shift msb bit into carry */
  90. ds tmp,arg1, tmp /* 1st divide step, if no carry */
  91. /* out, msb of quotient = 0 */
  92. addc retreg,retreg,retreg /* shift retreg with/into carry */
  93. LSYM(t1)
  94. ds tmp,arg1, tmp /* 2nd divide step */
  95. addc retreg,retreg,retreg /* shift retreg with/into carry */
  96. ds tmp,arg1, tmp /* 3rd divide step */
  97. addc retreg,retreg,retreg /* shift retreg with/into carry */
  98. ds tmp,arg1, tmp /* 4th divide step */
  99. addc retreg,retreg,retreg /* shift retreg with/into carry */
  100. ds tmp,arg1, tmp /* 5th divide step */
  101. addc retreg,retreg,retreg /* shift retreg with/into carry */
  102. ds tmp,arg1, tmp /* 6th divide step */
  103. addc retreg,retreg,retreg /* shift retreg with/into carry */
  104. ds tmp,arg1, tmp /* 7th divide step */
  105. addc retreg,retreg,retreg /* shift retreg with/into carry */
  106. ds tmp,arg1, tmp /* 8th divide step */
  107. addc retreg,retreg,retreg /* shift retreg with/into carry */
  108. ds tmp,arg1, tmp /* 9th divide step */
  109. addc retreg,retreg,retreg /* shift retreg with/into carry */
  110. ds tmp,arg1, tmp /* 10th divide step */
  111. addc retreg,retreg,retreg /* shift retreg with/into carry */
  112. ds tmp,arg1, tmp /* 11th divide step */
  113. addc retreg,retreg,retreg /* shift retreg with/into carry */
  114. ds tmp,arg1, tmp /* 12th divide step */
  115. addc retreg,retreg,retreg /* shift retreg with/into carry */
  116. ds tmp,arg1, tmp /* 13th divide step */
  117. addc retreg,retreg,retreg /* shift retreg with/into carry */
  118. ds tmp,arg1, tmp /* 14th divide step */
  119. addc retreg,retreg,retreg /* shift retreg with/into carry */
  120. ds tmp,arg1, tmp /* 15th divide step */
  121. addc retreg,retreg,retreg /* shift retreg with/into carry */
  122. ds tmp,arg1, tmp /* 16th divide step */
  123. addc retreg,retreg,retreg /* shift retreg with/into carry */
  124. ds tmp,arg1, tmp /* 17th divide step */
  125. addc retreg,retreg,retreg /* shift retreg with/into carry */
  126. ds tmp,arg1, tmp /* 18th divide step */
  127. addc retreg,retreg,retreg /* shift retreg with/into carry */
  128. ds tmp,arg1, tmp /* 19th divide step */
  129. addc retreg,retreg,retreg /* shift retreg with/into carry */
  130. ds tmp,arg1, tmp /* 20th divide step */
  131. addc retreg,retreg,retreg /* shift retreg with/into carry */
  132. ds tmp,arg1, tmp /* 21st divide step */
  133. addc retreg,retreg,retreg /* shift retreg with/into carry */
  134. ds tmp,arg1, tmp /* 22nd divide step */
  135. addc retreg,retreg,retreg /* shift retreg with/into carry */
  136. ds tmp,arg1, tmp /* 23rd divide step */
  137. addc retreg,retreg,retreg /* shift retreg with/into carry */
  138. ds tmp,arg1, tmp /* 24th divide step */
  139. addc retreg,retreg,retreg /* shift retreg with/into carry */
  140. ds tmp,arg1, tmp /* 25th divide step */
  141. addc retreg,retreg,retreg /* shift retreg with/into carry */
  142. ds tmp,arg1, tmp /* 26th divide step */
  143. addc retreg,retreg,retreg /* shift retreg with/into carry */
  144. ds tmp,arg1, tmp /* 27th divide step */
  145. addc retreg,retreg,retreg /* shift retreg with/into carry */
  146. ds tmp,arg1, tmp /* 28th divide step */
  147. addc retreg,retreg,retreg /* shift retreg with/into carry */
  148. ds tmp,arg1, tmp /* 29th divide step */
  149. addc retreg,retreg,retreg /* shift retreg with/into carry */
  150. ds tmp,arg1, tmp /* 30th divide step */
  151. addc retreg,retreg,retreg /* shift retreg with/into carry */
  152. ds tmp,arg1, tmp /* 31st divide step */
  153. addc retreg,retreg,retreg /* shift retreg with/into carry */
  154. ds tmp,arg1, tmp /* 32nd divide step, */
  155. addc retreg,retreg,retreg /* shift last bit into retreg */
  156. movb,>=,n tmp,retreg,LREF(finish) /* branch if pos. tmp */
  157. add,< arg1,0,0 /* if arg1 > 0, add arg1 */
  158. add,tr tmp,arg1,retreg /* for correcting remainder tmp */
  159. sub tmp,arg1,retreg /* else add absolute value arg1 */
  160. LSYM(finish)
  161. add,>= arg0,0,0 /* set sign of remainder */
  162. sub 0,retreg,retreg /* to sign of dividend */
  163. MILLIRET
  164. nop
  165. .exit
  166. .procend
  167. #ifdef milliext
  168. .origin 0x00000200
  169. #endif
  170. .end
  171. #endif