divsi3.S 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199
  1. /*
  2. * Copyright 2004-2009 Analog Devices Inc.
  3. *
  4. * Licensed under the Clear BSD license or the GPL-2 (or later)
  5. *
  6. * 16 / 32 bit signed division.
  7. * Special cases :
  8. * 1) If(numerator == 0)
  9. * return 0
  10. * 2) If(denominator ==0)
  11. * return positive max = 0x7fffffff
  12. * 3) If(numerator == denominator)
  13. * return 1
  14. * 4) If(denominator ==1)
  15. * return numerator
  16. * 5) If(denominator == -1)
  17. * return -numerator
  18. *
  19. * Operand : R0 - Numerator (i)
  20. * R1 - Denominator (i)
  21. * R0 - Quotient (o)
  22. * Registers Used : R2-R7,P0-P2
  23. *
  24. */
  25. .global ___divsi3;
  26. .type ___divsi3, STT_FUNC;
  27. #ifdef CONFIG_ARITHMETIC_OPS_L1
  28. .section .l1.text
  29. #else
  30. .text
  31. #endif
  32. .align 2;
  33. ___divsi3 :
  34. R3 = R0 ^ R1;
  35. R0 = ABS R0;
  36. CC = V;
  37. r3 = rot r3 by -1;
  38. r1 = abs r1; /* now both positive, r3.30 means "negate result",
  39. ** r3.31 means overflow, add one to result
  40. */
  41. cc = r0 < r1;
  42. if cc jump .Lret_zero;
  43. r2 = r1 >> 15;
  44. cc = r2;
  45. if cc jump .Lidents;
  46. r2 = r1 << 16;
  47. cc = r2 <= r0;
  48. if cc jump .Lidents;
  49. DIVS(R0, R1);
  50. DIVQ(R0, R1);
  51. DIVQ(R0, R1);
  52. DIVQ(R0, R1);
  53. DIVQ(R0, R1);
  54. DIVQ(R0, R1);
  55. DIVQ(R0, R1);
  56. DIVQ(R0, R1);
  57. DIVQ(R0, R1);
  58. DIVQ(R0, R1);
  59. DIVQ(R0, R1);
  60. DIVQ(R0, R1);
  61. DIVQ(R0, R1);
  62. DIVQ(R0, R1);
  63. DIVQ(R0, R1);
  64. DIVQ(R0, R1);
  65. DIVQ(R0, R1);
  66. R0 = R0.L (Z);
  67. r1 = r3 >> 31; /* add overflow issue back in */
  68. r0 = r0 + r1;
  69. r1 = -r0;
  70. cc = bittst(r3, 30);
  71. if cc r0 = r1;
  72. RTS;
  73. /* Can't use the primitives. Test common identities.
  74. ** If the identity is true, return the value in R2.
  75. */
  76. .Lidents:
  77. CC = R1 == 0; /* check for divide by zero */
  78. IF CC JUMP .Lident_return;
  79. CC = R0 == 0; /* check for division of zero */
  80. IF CC JUMP .Lzero_return;
  81. CC = R0 == R1; /* check for identical operands */
  82. IF CC JUMP .Lident_return;
  83. CC = R1 == 1; /* check for divide by 1 */
  84. IF CC JUMP .Lident_return;
  85. R2.L = ONES R1;
  86. R2 = R2.L (Z);
  87. CC = R2 == 1;
  88. IF CC JUMP .Lpower_of_two;
  89. /* Identities haven't helped either.
  90. ** Perform the full division process.
  91. */
  92. P1 = 31; /* Set loop counter */
  93. [--SP] = (R7:5); /* Push registers R5-R7 */
  94. R2 = -R1;
  95. [--SP] = R2;
  96. R2 = R0 << 1; /* R2 lsw of dividend */
  97. R6 = R0 ^ R1; /* Get sign */
  98. R5 = R6 >> 31; /* Shift sign to LSB */
  99. R0 = 0 ; /* Clear msw partial remainder */
  100. R2 = R2 | R5; /* Shift quotient bit */
  101. R6 = R0 ^ R1; /* Get new quotient bit */
  102. LSETUP(.Llst,.Llend) LC0 = P1; /* Setup loop */
  103. .Llst: R7 = R2 >> 31; /* record copy of carry from R2 */
  104. R2 = R2 << 1; /* Shift 64 bit dividend up by 1 bit */
  105. R0 = R0 << 1 || R5 = [SP];
  106. R0 = R0 | R7; /* and add carry */
  107. CC = R6 < 0; /* Check quotient(AQ) */
  108. /* we might be subtracting divisor (AQ==0) */
  109. IF CC R5 = R1; /* or we might be adding divisor (AQ==1)*/
  110. R0 = R0 + R5; /* do add or subtract, as indicated by AQ */
  111. R6 = R0 ^ R1; /* Generate next quotient bit */
  112. R5 = R6 >> 31;
  113. /* Assume AQ==1, shift in zero */
  114. BITTGL(R5,0); /* tweak AQ to be what we want to shift in */
  115. .Llend: R2 = R2 + R5; /* and then set shifted-in value to
  116. ** tweaked AQ.
  117. */
  118. r1 = r3 >> 31;
  119. r2 = r2 + r1;
  120. cc = bittst(r3,30);
  121. r0 = -r2;
  122. if !cc r0 = r2;
  123. SP += 4;
  124. (R7:5)= [SP++]; /* Pop registers R6-R7 */
  125. RTS;
  126. .Lident_return:
  127. CC = R1 == 0; /* check for divide by zero => 0x7fffffff */
  128. R2 = -1 (X);
  129. R2 >>= 1;
  130. IF CC JUMP .Ltrue_ident_return;
  131. CC = R0 == R1; /* check for identical operands => 1 */
  132. R2 = 1 (Z);
  133. IF CC JUMP .Ltrue_ident_return;
  134. R2 = R0; /* assume divide by 1 => numerator */
  135. /*FALLTHRU*/
  136. .Ltrue_ident_return:
  137. R0 = R2; /* Return an identity value */
  138. R2 = -R2;
  139. CC = bittst(R3,30);
  140. IF CC R0 = R2;
  141. .Lzero_return:
  142. RTS; /* ...including zero */
  143. .Lpower_of_two:
  144. /* Y has a single bit set, which means it's a power of two.
  145. ** That means we can perform the division just by shifting
  146. ** X to the right the appropriate number of bits
  147. */
  148. /* signbits returns the number of sign bits, minus one.
  149. ** 1=>30, 2=>29, ..., 0x40000000=>0. Which means we need
  150. ** to shift right n-signbits spaces. It also means 0x80000000
  151. ** is a special case, because that *also* gives a signbits of 0
  152. */
  153. R2 = R0 >> 31;
  154. CC = R1 < 0;
  155. IF CC JUMP .Ltrue_ident_return;
  156. R1.l = SIGNBITS R1;
  157. R1 = R1.L (Z);
  158. R1 += -30;
  159. R0 = LSHIFT R0 by R1.L;
  160. r1 = r3 >> 31;
  161. r0 = r0 + r1;
  162. R2 = -R0; // negate result if necessary
  163. CC = bittst(R3,30);
  164. IF CC R0 = R2;
  165. RTS;
  166. .Lret_zero:
  167. R0 = 0;
  168. RTS;
  169. .size ___divsi3, .-___divsi3