lib1funcs.S 7.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337
  1. /*
  2. * linux/arch/arm/lib/lib1funcs.S: Optimized ARM division routines
  3. *
  4. * Author: Nicolas Pitre <nico@cam.org>
  5. * - contributed to gcc-3.4 on Sep 30, 2003
  6. * - adapted for the Linux kernel on Oct 2, 2003
  7. */
  8. /* Copyright 1995, 1996, 1998, 1999, 2000, 2003 Free Software Foundation, Inc.
  9. This file is free software; you can redistribute it and/or modify it
  10. under the terms of the GNU General Public License as published by the
  11. Free Software Foundation; either version 2, or (at your option) any
  12. later version.
  13. In addition to the permissions in the GNU General Public License, the
  14. Free Software Foundation gives you unlimited permission to link the
  15. compiled version of this file into combinations with other programs,
  16. and to distribute those combinations without any restriction coming
  17. from the use of this file. (The General Public License restrictions
  18. do apply in other respects; for example, they cover modification of
  19. the file, and distribution when not linked into a combine
  20. executable.)
  21. This file is distributed in the hope that it will be useful, but
  22. WITHOUT ANY WARRANTY; without even the implied warranty of
  23. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  24. General Public License for more details.
  25. You should have received a copy of the GNU General Public License
  26. along with this program; see the file COPYING. If not, write to
  27. the Free Software Foundation, 59 Temple Place - Suite 330,
  28. Boston, MA 02111-1307, USA. */
  29. #include <linux/linkage.h>
  30. #include <asm/assembler.h>
  31. .macro ARM_DIV_BODY dividend, divisor, result, curbit
  32. #if __LINUX_ARM_ARCH__ >= 5
  33. clz \curbit, \divisor
  34. clz \result, \dividend
  35. sub \result, \curbit, \result
  36. mov \curbit, #1
  37. mov \divisor, \divisor, lsl \result
  38. mov \curbit, \curbit, lsl \result
  39. mov \result, #0
  40. #else
  41. @ Initially shift the divisor left 3 bits if possible,
  42. @ set curbit accordingly. This allows for curbit to be located
  43. @ at the left end of each 4 bit nibbles in the division loop
  44. @ to save one loop in most cases.
  45. tst \divisor, #0xe0000000
  46. moveq \divisor, \divisor, lsl #3
  47. moveq \curbit, #8
  48. movne \curbit, #1
  49. @ Unless the divisor is very big, shift it up in multiples of
  50. @ four bits, since this is the amount of unwinding in the main
  51. @ division loop. Continue shifting until the divisor is
  52. @ larger than the dividend.
  53. 1: cmp \divisor, #0x10000000
  54. cmplo \divisor, \dividend
  55. movlo \divisor, \divisor, lsl #4
  56. movlo \curbit, \curbit, lsl #4
  57. blo 1b
  58. @ For very big divisors, we must shift it a bit at a time, or
  59. @ we will be in danger of overflowing.
  60. 1: cmp \divisor, #0x80000000
  61. cmplo \divisor, \dividend
  62. movlo \divisor, \divisor, lsl #1
  63. movlo \curbit, \curbit, lsl #1
  64. blo 1b
  65. mov \result, #0
  66. #endif
  67. @ Division loop
  68. 1: cmp \dividend, \divisor
  69. subhs \dividend, \dividend, \divisor
  70. orrhs \result, \result, \curbit
  71. cmp \dividend, \divisor, lsr #1
  72. subhs \dividend, \dividend, \divisor, lsr #1
  73. orrhs \result, \result, \curbit, lsr #1
  74. cmp \dividend, \divisor, lsr #2
  75. subhs \dividend, \dividend, \divisor, lsr #2
  76. orrhs \result, \result, \curbit, lsr #2
  77. cmp \dividend, \divisor, lsr #3
  78. subhs \dividend, \dividend, \divisor, lsr #3
  79. orrhs \result, \result, \curbit, lsr #3
  80. cmp \dividend, #0 @ Early termination?
  81. movnes \curbit, \curbit, lsr #4 @ No, any more bits to do?
  82. movne \divisor, \divisor, lsr #4
  83. bne 1b
  84. .endm
  85. .macro ARM_DIV2_ORDER divisor, order
  86. #if __LINUX_ARM_ARCH__ >= 5
  87. clz \order, \divisor
  88. rsb \order, \order, #31
  89. #else
  90. cmp \divisor, #(1 << 16)
  91. movhs \divisor, \divisor, lsr #16
  92. movhs \order, #16
  93. movlo \order, #0
  94. cmp \divisor, #(1 << 8)
  95. movhs \divisor, \divisor, lsr #8
  96. addhs \order, \order, #8
  97. cmp \divisor, #(1 << 4)
  98. movhs \divisor, \divisor, lsr #4
  99. addhs \order, \order, #4
  100. cmp \divisor, #(1 << 2)
  101. addhi \order, \order, #3
  102. addls \order, \order, \divisor, lsr #1
  103. #endif
  104. .endm
  105. .macro ARM_MOD_BODY dividend, divisor, order, spare
  106. #if __LINUX_ARM_ARCH__ >= 5
  107. clz \order, \divisor
  108. clz \spare, \dividend
  109. sub \order, \order, \spare
  110. mov \divisor, \divisor, lsl \order
  111. #else
  112. mov \order, #0
  113. @ Unless the divisor is very big, shift it up in multiples of
  114. @ four bits, since this is the amount of unwinding in the main
  115. @ division loop. Continue shifting until the divisor is
  116. @ larger than the dividend.
  117. 1: cmp \divisor, #0x10000000
  118. cmplo \divisor, \dividend
  119. movlo \divisor, \divisor, lsl #4
  120. addlo \order, \order, #4
  121. blo 1b
  122. @ For very big divisors, we must shift it a bit at a time, or
  123. @ we will be in danger of overflowing.
  124. 1: cmp \divisor, #0x80000000
  125. cmplo \divisor, \dividend
  126. movlo \divisor, \divisor, lsl #1
  127. addlo \order, \order, #1
  128. blo 1b
  129. #endif
  130. @ Perform all needed substractions to keep only the reminder.
  131. @ Do comparisons in batch of 4 first.
  132. subs \order, \order, #3 @ yes, 3 is intended here
  133. blt 2f
  134. 1: cmp \dividend, \divisor
  135. subhs \dividend, \dividend, \divisor
  136. cmp \dividend, \divisor, lsr #1
  137. subhs \dividend, \dividend, \divisor, lsr #1
  138. cmp \dividend, \divisor, lsr #2
  139. subhs \dividend, \dividend, \divisor, lsr #2
  140. cmp \dividend, \divisor, lsr #3
  141. subhs \dividend, \dividend, \divisor, lsr #3
  142. cmp \dividend, #1
  143. mov \divisor, \divisor, lsr #4
  144. subges \order, \order, #4
  145. bge 1b
  146. tst \order, #3
  147. teqne \dividend, #0
  148. beq 5f
  149. @ Either 1, 2 or 3 comparison/substractions are left.
  150. 2: cmn \order, #2
  151. blt 4f
  152. beq 3f
  153. cmp \dividend, \divisor
  154. subhs \dividend, \dividend, \divisor
  155. mov \divisor, \divisor, lsr #1
  156. 3: cmp \dividend, \divisor
  157. subhs \dividend, \dividend, \divisor
  158. mov \divisor, \divisor, lsr #1
  159. 4: cmp \dividend, \divisor
  160. subhs \dividend, \dividend, \divisor
  161. 5:
  162. .endm
  163. ENTRY(__udivsi3)
  164. ENTRY(__aeabi_uidiv)
  165. subs r2, r1, #1
  166. moveq pc, lr
  167. bcc Ldiv0
  168. cmp r0, r1
  169. bls 11f
  170. tst r1, r2
  171. beq 12f
  172. ARM_DIV_BODY r0, r1, r2, r3
  173. mov r0, r2
  174. mov pc, lr
  175. 11: moveq r0, #1
  176. movne r0, #0
  177. mov pc, lr
  178. 12: ARM_DIV2_ORDER r1, r2
  179. mov r0, r0, lsr r2
  180. mov pc, lr
  181. ENTRY(__umodsi3)
  182. subs r2, r1, #1 @ compare divisor with 1
  183. bcc Ldiv0
  184. cmpne r0, r1 @ compare dividend with divisor
  185. moveq r0, #0
  186. tsthi r1, r2 @ see if divisor is power of 2
  187. andeq r0, r0, r2
  188. movls pc, lr
  189. ARM_MOD_BODY r0, r1, r2, r3
  190. mov pc, lr
  191. ENTRY(__divsi3)
  192. ENTRY(__aeabi_idiv)
  193. cmp r1, #0
  194. eor ip, r0, r1 @ save the sign of the result.
  195. beq Ldiv0
  196. rsbmi r1, r1, #0 @ loops below use unsigned.
  197. subs r2, r1, #1 @ division by 1 or -1 ?
  198. beq 10f
  199. movs r3, r0
  200. rsbmi r3, r0, #0 @ positive dividend value
  201. cmp r3, r1
  202. bls 11f
  203. tst r1, r2 @ divisor is power of 2 ?
  204. beq 12f
  205. ARM_DIV_BODY r3, r1, r0, r2
  206. cmp ip, #0
  207. rsbmi r0, r0, #0
  208. mov pc, lr
  209. 10: teq ip, r0 @ same sign ?
  210. rsbmi r0, r0, #0
  211. mov pc, lr
  212. 11: movlo r0, #0
  213. moveq r0, ip, asr #31
  214. orreq r0, r0, #1
  215. mov pc, lr
  216. 12: ARM_DIV2_ORDER r1, r2
  217. cmp ip, #0
  218. mov r0, r3, lsr r2
  219. rsbmi r0, r0, #0
  220. mov pc, lr
  221. ENTRY(__modsi3)
  222. cmp r1, #0
  223. beq Ldiv0
  224. rsbmi r1, r1, #0 @ loops below use unsigned.
  225. movs ip, r0 @ preserve sign of dividend
  226. rsbmi r0, r0, #0 @ if negative make positive
  227. subs r2, r1, #1 @ compare divisor with 1
  228. cmpne r0, r1 @ compare dividend with divisor
  229. moveq r0, #0
  230. tsthi r1, r2 @ see if divisor is power of 2
  231. andeq r0, r0, r2
  232. bls 10f
  233. ARM_MOD_BODY r0, r1, r2, r3
  234. 10: cmp ip, #0
  235. rsbmi r0, r0, #0
  236. mov pc, lr
  237. #ifdef CONFIG_AEABI
  238. ENTRY(__aeabi_uidivmod)
  239. stmfd sp!, {r0, r1, ip, lr}
  240. bl __aeabi_uidiv
  241. ldmfd sp!, {r1, r2, ip, lr}
  242. mul r3, r0, r2
  243. sub r1, r1, r3
  244. mov pc, lr
  245. ENTRY(__aeabi_idivmod)
  246. stmfd sp!, {r0, r1, ip, lr}
  247. bl __aeabi_idiv
  248. ldmfd sp!, {r1, r2, ip, lr}
  249. mul r3, r0, r2
  250. sub r1, r1, r3
  251. mov pc, lr
  252. #endif
  253. Ldiv0:
  254. str lr, [sp, #-8]!
  255. bl __div0
  256. mov r0, #0 @ About as wrong as it could be.
  257. ldr pc, [sp], #8