divremu.S 2.6 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. ;; Copyright 2011 Free Software Foundation, Inc.
  2. ;; Contributed by Bernd Schmidt <bernds@codesourcery.com>.
  3. ;;
  4. ;; This program is free software; you can redistribute it and/or modify
  5. ;; it under the terms of the GNU General Public License as published by
  6. ;; the Free Software Foundation; either version 2 of the License, or
  7. ;; (at your option) any later version.
  8. ;;
  9. ;; This program is distributed in the hope that it will be useful,
  10. ;; but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. ;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. ;; GNU General Public License for more details.
  13. ;;
  14. ;; You should have received a copy of the GNU General Public License
  15. ;; along with this program; if not, write to the Free Software
  16. ;; Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
  17. #include <linux/linkage.h>
  18. .text
  19. ENTRY(__c6xabi_divremu)
  20. ;; We use a series of up to 31 subc instructions. First, we find
  21. ;; out how many leading zero bits there are in the divisor. This
  22. ;; gives us both a shift count for aligning (shifting) the divisor
  23. ;; to the, and the number of times we have to execute subc.
  24. ;; At the end, we have both the remainder and most of the quotient
  25. ;; in A4. The top bit of the quotient is computed first and is
  26. ;; placed in A2.
  27. ;; Return immediately if the dividend is zero. Setting B4 to 1
  28. ;; is a trick to allow us to leave the following insns in the jump
  29. ;; delay slot without affecting the result.
  30. mv .s2x A4, B1
  31. [b1] lmbd .l2 1, B4, B1
  32. ||[!b1] b .s2 B3 ; RETURN A
  33. ||[!b1] mvk .d2 1, B4
  34. ||[!b1] zero .s1 A5
  35. mv .l1x B1, A6
  36. || shl .s2 B4, B1, B4
  37. ;; The loop performs a maximum of 28 steps, so we do the
  38. ;; first 3 here.
  39. cmpltu .l1x A4, B4, A2
  40. [!A2] sub .l1x A4, B4, A4
  41. || shru .s2 B4, 1, B4
  42. || xor .s1 1, A2, A2
  43. shl .s1 A2, 31, A2
  44. || [b1] subc .l1x A4,B4,A4
  45. || [b1] add .s2 -1, B1, B1
  46. [b1] subc .l1x A4,B4,A4
  47. || [b1] add .s2 -1, B1, B1
  48. ;; RETURN A may happen here (note: must happen before the next branch)
  49. __divremu0:
  50. cmpgt .l2 B1, 7, B0
  51. || [b1] subc .l1x A4,B4,A4
  52. || [b1] add .s2 -1, B1, B1
  53. [b1] subc .l1x A4,B4,A4
  54. || [b1] add .s2 -1, B1, B1
  55. || [b0] b .s1 __divremu0
  56. [b1] subc .l1x A4,B4,A4
  57. || [b1] add .s2 -1, B1, B1
  58. [b1] subc .l1x A4,B4,A4
  59. || [b1] add .s2 -1, B1, B1
  60. [b1] subc .l1x A4,B4,A4
  61. || [b1] add .s2 -1, B1, B1
  62. [b1] subc .l1x A4,B4,A4
  63. || [b1] add .s2 -1, B1, B1
  64. [b1] subc .l1x A4,B4,A4
  65. || [b1] add .s2 -1, B1, B1
  66. ;; loop backwards branch happens here
  67. ret .s2 B3
  68. || mvk .s1 32, A1
  69. sub .l1 A1, A6, A6
  70. || extu .s1 A4, A6, A5
  71. shl .s1 A4, A6, A4
  72. shru .s1 A4, 1, A4
  73. || sub .l1 A6, 1, A6
  74. or .l1 A2, A4, A4
  75. shru .s1 A4, A6, A4
  76. nop
  77. ENDPROC(__c6xabi_divremu)