ARM application development SDK for MNT ZZ9000 graphics and coprocessor card for classic Amiga computers.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

idivmod.S 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. /* Runtime ABI for the ARM Cortex-M0
  2. * idivmod.S: signed 32 bit division (quotient and remainder)
  3. *
  4. * Copyright (c) 2012 Jörg Mische <bobbl@gmx.de>
  5. *
  6. * Permission to use, copy, modify, and/or distribute this software for any
  7. * purpose with or without fee is hereby granted, provided that the above
  8. * copyright notice and this permission notice appear in all copies.
  9. *
  10. * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
  11. * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
  12. * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
  13. * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
  14. * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
  15. * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
  16. * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
  17. */
  18. .syntax unified
  19. .text
  20. .thumb
  21. .cpu cortex-a9
  22. @ {int quotient:r0, int remainder:r1}
  23. @ __aeabi_idivmod(int numerator:r0, int denominator:r1)
  24. @
  25. @ Divide r0 by r1 and return the quotient in r0 and the remainder in r1
  26. @
  27. .thumb_func
  28. .global __aeabi_idivmod
  29. __aeabi_idivmod:
  30. cmp r0, #0
  31. bge .Lnumerator_pos
  32. rsbs r0, r0, #0 @ num = -num
  33. cmp r1, #0
  34. bge .Lboth_neg
  35. rsbs r1, r1, #0 @ den = -den
  36. push {lr}
  37. bl __aeabi_uidivmod
  38. rsbs r1, r1, #0 @ rem = -rem
  39. pop {pc}
  40. .Lboth_neg:
  41. push {lr}
  42. bl __aeabi_uidivmod
  43. rsbs r0, r0, #0 @ quot = -quot
  44. rsbs r1, r1, #0 @ rem = -rem
  45. pop {pc}
  46. .Lnumerator_pos:
  47. cmp r1, #0
  48. bge .Luidivmod
  49. rsbs r1, r1, #0 @ den = -den
  50. push {lr}
  51. bl __aeabi_uidivmod
  52. rsbs r0, r0, #0 @ quot = -quot
  53. pop {pc}
  54. @ unsigned __udivsi3(unsigned num, unsigned denom)
  55. @
  56. @ libgcc wrapper: just an alias for __aeabi_uidivmod(), the remainder is ignored
  57. @
  58. .thumb_func
  59. .global __udivsi3
  60. __udivsi3:
  61. @ unsigned __aeabi_uidiv(unsigned num, unsigned denom)
  62. @
  63. @ Just an alias for __aeabi_uidivmod(), the remainder is ignored
  64. @
  65. .thumb_func
  66. .global __aeabi_uidiv
  67. __aeabi_uidiv:
  68. @ {unsigned quotient:r0, unsigned remainder:r1}
  69. @ __aeabi_uidivmod(unsigned numerator:r0, unsigned denominator:r1)
  70. @
  71. @ Divide r0 by r1 and return the quotient in r0 and the remainder in r1
  72. @
  73. .thumb_func
  74. .global __aeabi_uidivmod
  75. __aeabi_uidivmod:
  76. .Luidivmod:
  77. cmp r1, #0
  78. bne 1f
  79. b __aeabi_idiv0
  80. 1:
  81. @ Shift left the denominator until it is greater than the numerator
  82. movs r2, #1 @ counter
  83. movs r3, #0 @ result
  84. cmp r0, r1
  85. bls .Lsub_loop
  86. adds r1, #0 @ dont shift if denominator would overflow
  87. bmi .Lsub_loop
  88. .Ldenom_shift_loop:
  89. lsls r2, #1
  90. lsls r1, #1
  91. bmi .Lsub_loop
  92. cmp r0, r1
  93. bhi .Ldenom_shift_loop
  94. .Lsub_loop:
  95. cmp r0, r1
  96. bcc .Ldont_sub @ if (num>denom)
  97. subs r0, r1 @ numerator -= denom
  98. orrs r3, r2 @ result(r3) |= bitmask(r2)
  99. .Ldont_sub:
  100. lsrs r1, #1 @ denom(r1) >>= 1
  101. lsrs r2, #1 @ bitmask(r2) >>= 1
  102. bne .Lsub_loop
  103. mov r1, r0 @ remainder(r1) = numerator(r0)
  104. mov r0, r3 @ quotient(r0) = result(r3)
  105. bx lr