_umodsi3.S 2.7 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. /* # 1 "libgcc1.S" */
  2. @ libgcc1 routines for ARM cpu.
  3. @ Division routines, written by Richard Earnshaw, (rearnsha@armltd.co.uk)
  4. /* # 145 "libgcc1.S" */
  5. dividend .req r0
  6. divisor .req r1
  7. overdone .req r2
  8. curbit .req r3
  9. /* ip .req r12 */
  10. /* sp .req r13 */
  11. /* lr .req r14 */
  12. /* pc .req r15 */
  13. .text
  14. .globl __umodsi3
  15. .type __umodsi3 ,function
  16. .align 0
  17. __umodsi3 :
  18. cmp divisor, #0
  19. beq Ldiv0
  20. mov curbit, #1
  21. cmp dividend, divisor
  22. movcc pc, lr
  23. Loop1:
  24. @ Unless the divisor is very big, shift it up in multiples of
  25. @ four bits, since this is the amount of unwinding in the main
  26. @ division loop. Continue shifting until the divisor is
  27. @ larger than the dividend.
  28. cmp divisor, #0x10000000
  29. cmpcc divisor, dividend
  30. movcc divisor, divisor, lsl #4
  31. movcc curbit, curbit, lsl #4
  32. bcc Loop1
  33. Lbignum:
  34. @ For very big divisors, we must shift it a bit at a time, or
  35. @ we will be in danger of overflowing.
  36. cmp divisor, #0x80000000
  37. cmpcc divisor, dividend
  38. movcc divisor, divisor, lsl #1
  39. movcc curbit, curbit, lsl #1
  40. bcc Lbignum
  41. Loop3:
  42. @ Test for possible subtractions. On the final pass, this may
  43. @ subtract too much from the dividend, so keep track of which
  44. @ subtractions are done, we can fix them up afterwards...
  45. mov overdone, #0
  46. cmp dividend, divisor
  47. subcs dividend, dividend, divisor
  48. cmp dividend, divisor, lsr #1
  49. subcs dividend, dividend, divisor, lsr #1
  50. orrcs overdone, overdone, curbit, ror #1
  51. cmp dividend, divisor, lsr #2
  52. subcs dividend, dividend, divisor, lsr #2
  53. orrcs overdone, overdone, curbit, ror #2
  54. cmp dividend, divisor, lsr #3
  55. subcs dividend, dividend, divisor, lsr #3
  56. orrcs overdone, overdone, curbit, ror #3
  57. mov ip, curbit
  58. cmp dividend, #0 @ Early termination?
  59. movnes curbit, curbit, lsr #4 @ No, any more bits to do?
  60. movne divisor, divisor, lsr #4
  61. bne Loop3
  62. @ Any subtractions that we should not have done will be recorded in
  63. @ the top three bits of "overdone". Exactly which were not needed
  64. @ are governed by the position of the bit, stored in ip.
  65. @ If we terminated early, because dividend became zero,
  66. @ then none of the below will match, since the bit in ip will not be
  67. @ in the bottom nibble.
  68. ands overdone, overdone, #0xe0000000
  69. moveq pc, lr @ No fixups needed
  70. tst overdone, ip, ror #3
  71. addne dividend, dividend, divisor, lsr #3
  72. tst overdone, ip, ror #2
  73. addne dividend, dividend, divisor, lsr #2
  74. tst overdone, ip, ror #1
  75. addne dividend, dividend, divisor, lsr #1
  76. mov pc, lr
  77. Ldiv0:
  78. str lr, [sp, #-4]!
  79. bl __div0 (PLT)
  80. mov r0, #0 @ about as wrong as it could be
  81. ldmia sp!, {pc}
  82. .size __umodsi3 , . - __umodsi3
  83. /* # 320 "libgcc1.S" */
  84. /* # 421 "libgcc1.S" */
  85. /* # 433 "libgcc1.S" */
  86. /* # 456 "libgcc1.S" */
  87. /* # 500 "libgcc1.S" */
  88. /* # 580 "libgcc1.S" */