divsi3.S 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216
  1. /*
  2. * File: arch/blackfin/lib/divsi3.S
  3. * Based on:
  4. * Author:
  5. *
  6. * Created:
  7. * Description: 16 / 32 bit signed division.
  8. * Special cases :
  9. * 1) If(numerator == 0)
  10. * return 0
  11. * 2) If(denominator ==0)
  12. * return positive max = 0x7fffffff
  13. * 3) If(numerator == denominator)
  14. * return 1
  15. * 4) If(denominator ==1)
  16. * return numerator
  17. * 5) If(denominator == -1)
  18. * return -numerator
  19. *
  20. * Operand : R0 - Numerator (i)
  21. * R1 - Denominator (i)
  22. * R0 - Quotient (o)
  23. * Registers Used : R2-R7,P0-P2
  24. *
  25. * Modified:
  26. * Copyright 2004-2006 Analog Devices Inc.
  27. *
  28. * Bugs: Enter bugs at http://blackfin.uclinux.org/
  29. *
  30. * This program is free software; you can redistribute it and/or modify
  31. * it under the terms of the GNU General Public License as published by
  32. * the Free Software Foundation; either version 2 of the License, or
  33. * (at your option) any later version.
  34. *
  35. * This program is distributed in the hope that it will be useful,
  36. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  37. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  38. * GNU General Public License for more details.
  39. *
  40. * You should have received a copy of the GNU General Public License
  41. * along with this program; if not, see the file COPYING, or write
  42. * to the Free Software Foundation, Inc.,
  43. * 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
  44. */
  45. .global ___divsi3;
  46. #ifdef CONFIG_ARITHMETIC_OPS_L1
  47. .section .l1.text
  48. #else
  49. .text
  50. #endif
  51. .align 2;
  52. ___divsi3 :
  53. R3 = R0 ^ R1;
  54. R0 = ABS R0;
  55. CC = V;
  56. r3 = rot r3 by -1;
  57. r1 = abs r1; /* now both positive, r3.30 means "negate result",
  58. ** r3.31 means overflow, add one to result
  59. */
  60. cc = r0 < r1;
  61. if cc jump .Lret_zero;
  62. r2 = r1 >> 15;
  63. cc = r2;
  64. if cc jump .Lidents;
  65. r2 = r1 << 16;
  66. cc = r2 <= r0;
  67. if cc jump .Lidents;
  68. DIVS(R0, R1);
  69. DIVQ(R0, R1);
  70. DIVQ(R0, R1);
  71. DIVQ(R0, R1);
  72. DIVQ(R0, R1);
  73. DIVQ(R0, R1);
  74. DIVQ(R0, R1);
  75. DIVQ(R0, R1);
  76. DIVQ(R0, R1);
  77. DIVQ(R0, R1);
  78. DIVQ(R0, R1);
  79. DIVQ(R0, R1);
  80. DIVQ(R0, R1);
  81. DIVQ(R0, R1);
  82. DIVQ(R0, R1);
  83. DIVQ(R0, R1);
  84. DIVQ(R0, R1);
  85. R0 = R0.L (Z);
  86. r1 = r3 >> 31; /* add overflow issue back in */
  87. r0 = r0 + r1;
  88. r1 = -r0;
  89. cc = bittst(r3, 30);
  90. if cc r0 = r1;
  91. RTS;
  92. /* Can't use the primitives. Test common identities.
  93. ** If the identity is true, return the value in R2.
  94. */
  95. .Lidents:
  96. CC = R1 == 0; /* check for divide by zero */
  97. IF CC JUMP .Lident_return;
  98. CC = R0 == 0; /* check for division of zero */
  99. IF CC JUMP .Lzero_return;
  100. CC = R0 == R1; /* check for identical operands */
  101. IF CC JUMP .Lident_return;
  102. CC = R1 == 1; /* check for divide by 1 */
  103. IF CC JUMP .Lident_return;
  104. R2.L = ONES R1;
  105. R2 = R2.L (Z);
  106. CC = R2 == 1;
  107. IF CC JUMP .Lpower_of_two;
  108. /* Identities haven't helped either.
  109. ** Perform the full division process.
  110. */
  111. P1 = 31; /* Set loop counter */
  112. [--SP] = (R7:5); /* Push registers R5-R7 */
  113. R2 = -R1;
  114. [--SP] = R2;
  115. R2 = R0 << 1; /* R2 lsw of dividend */
  116. R6 = R0 ^ R1; /* Get sign */
  117. R5 = R6 >> 31; /* Shift sign to LSB */
  118. R0 = 0 ; /* Clear msw partial remainder */
  119. R2 = R2 | R5; /* Shift quotient bit */
  120. R6 = R0 ^ R1; /* Get new quotient bit */
  121. LSETUP(.Llst,.Llend) LC0 = P1; /* Setup loop */
  122. .Llst: R7 = R2 >> 31; /* record copy of carry from R2 */
  123. R2 = R2 << 1; /* Shift 64 bit dividend up by 1 bit */
  124. R0 = R0 << 1 || R5 = [SP];
  125. R0 = R0 | R7; /* and add carry */
  126. CC = R6 < 0; /* Check quotient(AQ) */
  127. /* we might be subtracting divisor (AQ==0) */
  128. IF CC R5 = R1; /* or we might be adding divisor (AQ==1)*/
  129. R0 = R0 + R5; /* do add or subtract, as indicated by AQ */
  130. R6 = R0 ^ R1; /* Generate next quotient bit */
  131. R5 = R6 >> 31;
  132. /* Assume AQ==1, shift in zero */
  133. BITTGL(R5,0); /* tweak AQ to be what we want to shift in */
  134. .Llend: R2 = R2 + R5; /* and then set shifted-in value to
  135. ** tweaked AQ.
  136. */
  137. r1 = r3 >> 31;
  138. r2 = r2 + r1;
  139. cc = bittst(r3,30);
  140. r0 = -r2;
  141. if !cc r0 = r2;
  142. SP += 4;
  143. (R7:5)= [SP++]; /* Pop registers R6-R7 */
  144. RTS;
  145. .Lident_return:
  146. CC = R1 == 0; /* check for divide by zero => 0x7fffffff */
  147. R2 = -1 (X);
  148. R2 >>= 1;
  149. IF CC JUMP .Ltrue_ident_return;
  150. CC = R0 == R1; /* check for identical operands => 1 */
  151. R2 = 1 (Z);
  152. IF CC JUMP .Ltrue_ident_return;
  153. R2 = R0; /* assume divide by 1 => numerator */
  154. /*FALLTHRU*/
  155. .Ltrue_ident_return:
  156. R0 = R2; /* Return an identity value */
  157. R2 = -R2;
  158. CC = bittst(R3,30);
  159. IF CC R0 = R2;
  160. .Lzero_return:
  161. RTS; /* ...including zero */
  162. .Lpower_of_two:
  163. /* Y has a single bit set, which means it's a power of two.
  164. ** That means we can perform the division just by shifting
  165. ** X to the right the appropriate number of bits
  166. */
  167. /* signbits returns the number of sign bits, minus one.
  168. ** 1=>30, 2=>29, ..., 0x40000000=>0. Which means we need
  169. ** to shift right n-signbits spaces. It also means 0x80000000
  170. ** is a special case, because that *also* gives a signbits of 0
  171. */
  172. R2 = R0 >> 31;
  173. CC = R1 < 0;
  174. IF CC JUMP .Ltrue_ident_return;
  175. R1.l = SIGNBITS R1;
  176. R1 = R1.L (Z);
  177. R1 += -30;
  178. R0 = LSHIFT R0 by R1.L;
  179. r1 = r3 >> 31;
  180. r0 = r0 + r1;
  181. R2 = -R0; // negate result if necessary
  182. CC = bittst(R3,30);
  183. IF CC R0 = R2;
  184. RTS;
  185. .Lret_zero:
  186. R0 = 0;
  187. RTS;