udivsi3.S 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. ###################################-
  2. #
  3. # Copyright (C) 2009-2022 Free Software Foundation, Inc.
  4. #
  5. # Contributed by Michael Eager <eager@eagercon.com>.
  6. #
  7. # This file is free software; you can redistribute it and/or modify it
  8. # under the terms of the GNU General Public License as published by the
  9. # Free Software Foundation; either version 3, or (at your option) any
  10. # later version.
  11. #
  12. # GCC is distributed in the hope that it will be useful, but WITHOUT
  13. # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  14. # or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  15. # License for more details.
  16. #
  17. # Under Section 7 of GPL version 3, you are granted additional
  18. # permissions described in the GCC Runtime Library Exception, version
  19. # 3.1, as published by the Free Software Foundation.
  20. #
  21. # You should have received a copy of the GNU General Public License and
  22. # a copy of the GCC Runtime Library Exception along with this program;
  23. # see the files COPYING3 and COPYING.RUNTIME respectively. If not, see
  24. # <http://www.gnu.org/licenses/>.
  25. #
  26. # udivsi3.S
  27. #
  28. # Unsigned divide operation.
  29. # Input : Divisor in Reg r5
  30. # Dividend in Reg r6
  31. # Output: Result in Reg r3
  32. #
  33. #######################################
  34. /* An executable stack is *not* required for these functions. */
  35. #ifdef __linux__
  36. .section .note.GNU-stack,"",%progbits
  37. .previous
  38. #endif
  39. .globl __udivsi3
  40. .ent __udivsi3
  41. .type __udivsi3,@function
  42. __udivsi3:
  43. .frame r1,0,r15
  44. ADDIK r1,r1,-12
  45. SWI r29,r1,0
  46. SWI r30,r1,4
  47. SWI r31,r1,8
  48. BEQI r6,$LaDiv_By_Zero # Div_by_Zero # Division Error
  49. BEQID r5,$LaResult_Is_Zero # Result is Zero
  50. ADDIK r30,r0,0 # Clear mod
  51. ADDIK r29,r0,32 # Initialize the loop count
  52. # Check if r6 and r5 are equal # if yes, return 1
  53. RSUB r18,r5,r6
  54. BEQID r18,$LaRETURN_HERE
  55. ADDIK r3,r0,1
  56. # Check if (uns)r6 is greater than (uns)r5. In that case, just return 0
  57. XOR r18,r5,r6
  58. BGEID r18,16
  59. ADD r3,r0,r0 # We would anyways clear r3
  60. BLTI r6,$LaRETURN_HERE # r6[bit 31 = 1] hence is greater
  61. BRI $LCheckr6
  62. RSUB r18,r6,r5 # MICROBLAZEcmp
  63. BLTI r18,$LaRETURN_HERE
  64. # If r6 [bit 31] is set, then return result as 1
  65. $LCheckr6:
  66. BGTI r6,$LaDIV0
  67. BRID $LaRETURN_HERE
  68. ADDIK r3,r0,1
  69. # First part try to find the first '1' in the r5
  70. $LaDIV0:
  71. BLTI r5,$LaDIV2
  72. $LaDIV1:
  73. ADD r5,r5,r5 # left shift logical r5
  74. BGTID r5,$LaDIV1
  75. ADDIK r29,r29,-1
  76. $LaDIV2:
  77. ADD r5,r5,r5 # left shift logical r5 get the '1' into the Carry
  78. ADDC r30,r30,r30 # Move that bit into the Mod register
  79. RSUB r31,r6,r30 # Try to subtract (r30 a r6)
  80. BLTI r31,$LaMOD_TOO_SMALL
  81. OR r30,r0,r31 # Move the r31 to mod since the result was positive
  82. ADDIK r3,r3,1
  83. $LaMOD_TOO_SMALL:
  84. ADDIK r29,r29,-1
  85. BEQi r29,$LaLOOP_END
  86. ADD r3,r3,r3 # Shift in the '1' into div
  87. BRI $LaDIV2 # Div2
  88. $LaLOOP_END:
  89. BRI $LaRETURN_HERE
  90. $LaDiv_By_Zero:
  91. $LaResult_Is_Zero:
  92. OR r3,r0,r0 # set result to 0
  93. $LaRETURN_HERE:
  94. # Restore values of CSRs and that of r3 and the divisor and the dividend
  95. LWI r29,r1,0
  96. LWI r30,r1,4
  97. LWI r31,r1,8
  98. RTSD r15,8
  99. ADDIK r1,r1,12
  100. .end __udivsi3
  101. .size __udivsi3, . - __udivsi3