_modsi3.S 2.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #include <linux/linkage.h>
  2. .macro ARM_MOD_BODY dividend, divisor, order, spare
  3. #if __LINUX_ARM_ARCH__ >= 5
  4. clz \order, \divisor
  5. clz \spare, \dividend
  6. sub \order, \order, \spare
  7. mov \divisor, \divisor, lsl \order
  8. #else
  9. mov \order, #0
  10. @ Unless the divisor is very big, shift it up in multiples of
  11. @ four bits, since this is the amount of unwinding in the main
  12. @ division loop. Continue shifting until the divisor is
  13. @ larger than the dividend.
  14. 1: cmp \divisor, #0x10000000
  15. cmplo \divisor, \dividend
  16. movlo \divisor, \divisor, lsl #4
  17. addlo \order, \order, #4
  18. blo 1b
  19. @ For very big divisors, we must shift it a bit at a time, or
  20. @ we will be in danger of overflowing.
  21. 1: cmp \divisor, #0x80000000
  22. cmplo \divisor, \dividend
  23. movlo \divisor, \divisor, lsl #1
  24. addlo \order, \order, #1
  25. blo 1b
  26. #endif
  27. @ Perform all needed substractions to keep only the reminder.
  28. @ Do comparisons in batch of 4 first.
  29. subs \order, \order, #3 @ yes, 3 is intended here
  30. blt 2f
  31. 1: cmp \dividend, \divisor
  32. subhs \dividend, \dividend, \divisor
  33. cmp \dividend, \divisor, lsr #1
  34. subhs \dividend, \dividend, \divisor, lsr #1
  35. cmp \dividend, \divisor, lsr #2
  36. subhs \dividend, \dividend, \divisor, lsr #2
  37. cmp \dividend, \divisor, lsr #3
  38. subhs \dividend, \dividend, \divisor, lsr #3
  39. cmp \dividend, #1
  40. mov \divisor, \divisor, lsr #4
  41. subges \order, \order, #4
  42. bge 1b
  43. tst \order, #3
  44. teqne \dividend, #0
  45. beq 5f
  46. @ Either 1, 2 or 3 comparison/substractions are left.
  47. 2: cmn \order, #2
  48. blt 4f
  49. beq 3f
  50. cmp \dividend, \divisor
  51. subhs \dividend, \dividend, \divisor
  52. mov \divisor, \divisor, lsr #1
  53. 3: cmp \dividend, \divisor
  54. subhs \dividend, \dividend, \divisor
  55. mov \divisor, \divisor, lsr #1
  56. 4: cmp \dividend, \divisor
  57. subhs \dividend, \dividend, \divisor
  58. 5:
  59. .endm
  60. .align 5
  61. ENTRY(__modsi3)
  62. cmp r1, #0
  63. beq Ldiv0
  64. rsbmi r1, r1, #0 @ loops below use unsigned.
  65. movs ip, r0 @ preserve sign of dividend
  66. rsbmi r0, r0, #0 @ if negative make positive
  67. subs r2, r1, #1 @ compare divisor with 1
  68. cmpne r0, r1 @ compare dividend with divisor
  69. moveq r0, #0
  70. tsthi r1, r2 @ see if divisor is power of 2
  71. andeq r0, r0, r2
  72. bls 10f
  73. ARM_MOD_BODY r0, r1, r2, r3
  74. 10: cmp ip, #0
  75. rsbmi r0, r0, #0
  76. mov pc, lr
  77. ENDPROC(__modsi3)
  78. Ldiv0:
  79. str lr, [sp, #-4]!
  80. bl __div0
  81. mov r0, #0 @ About as wrong as it could be.
  82. ldr pc, [sp], #4