divrem_1.asm
上传用户:qaz666999
上传日期:2022-08-06
资源大小:2570k
文件大小:4k
源码类别:

数学计算

开发平台:

Unix_Linux

  1. dnl  AMD K6 mpn_divrem_1 -- mpn by limb division.
  2. dnl  Copyright 1999, 2000, 2001, 2002, 2003, 2007 Free Software Foundation,
  3. dnl  Inc.
  4. dnl
  5. dnl  This file is part of the GNU MP Library.
  6. dnl
  7. dnl  The GNU MP Library is free software; you can redistribute it and/or
  8. dnl  modify it under the terms of the GNU Lesser General Public License as
  9. dnl  published by the Free Software Foundation; either version 3 of the
  10. dnl  License, or (at your option) any later version.
  11. dnl
  12. dnl  The GNU MP Library is distributed in the hope that it will be useful,
  13. dnl  but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. dnl  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15. dnl  Lesser General Public License for more details.
  16. dnl
  17. dnl  You should have received a copy of the GNU Lesser General Public License
  18. dnl  along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.
  19. include(`../config.m4')
  20. C K6: 20 cycles/limb
  21. C mp_limb_t mpn_divrem_1 (mp_ptr dst, mp_size_t xsize,
  22. C                         mp_srcptr src, mp_size_t size, mp_limb_t divisor);
  23. C mp_limb_t mpn_divrem_1c (mp_ptr dst, mp_size_t xsize,
  24. C                          mp_srcptr src, mp_size_t size, mp_limb_t divisor,
  25. C                          mp_limb_t carry);
  26. C
  27. C The code here is basically the same as mpn/x86/divrem_1.asm, but uses loop
  28. C instead of decl+jnz, since it comes out 2 cycles/limb faster.
  29. C
  30. C A test is done to see if the high limb is less than the divisor, and if so
  31. C one less div is done.  A div is 20 cycles, so assuming high<divisor about
  32. C half the time, then this test saves half that amount.  The branch
  33. C misprediction penalty is less than that.
  34. C
  35. C Back-to-back div instructions run at 20 cycles, the same as the loop here,
  36. C so it seems there's nothing to gain by rearranging the loop.  Pairing the
  37. C mov and loop instructions was found to gain nothing.
  38. C
  39. C Enhancements:
  40. C
  41. C The low-latency K6 multiply might be thought to suit a mul-by-inverse, but
  42. C that algorithm has been found to suffer from the relatively poor carry
  43. C handling on K6 and too many auxiliary instructions.  The fractional part
  44. C however could be done at about 13 c/l, if it mattered enough.
  45. defframe(PARAM_CARRY,  24)
  46. defframe(PARAM_DIVISOR,20)
  47. defframe(PARAM_SIZE,   16)
  48. defframe(PARAM_SRC,    12)
  49. defframe(PARAM_XSIZE,  8)
  50. defframe(PARAM_DST,    4)
  51. TEXT
  52. ALIGN(32)
  53. PROLOGUE(mpn_divrem_1c)
  54. deflit(`FRAME',0)
  55. movl PARAM_SIZE, %ecx
  56. pushl %edi FRAME_pushl()
  57. movl PARAM_SRC, %edi
  58. pushl %esi FRAME_pushl()
  59. movl PARAM_DIVISOR, %esi
  60. pushl %ebx FRAME_pushl()
  61. movl PARAM_DST, %ebx
  62. pushl %ebp FRAME_pushl()
  63. movl PARAM_XSIZE, %ebp
  64. orl %ecx, %ecx C size
  65. movl PARAM_CARRY, %edx
  66. jz L(fraction) C if size==0
  67. leal -4(%ebx,%ebp,4), %ebx C dst one limb below integer part
  68. jmp L(integer_top)
  69. EPILOGUE()
  70. ALIGN(16)
  71. PROLOGUE(mpn_divrem_1)
  72. deflit(`FRAME',0)
  73. movl PARAM_SIZE, %ecx
  74. pushl %edi FRAME_pushl()
  75. movl PARAM_SRC, %edi
  76. pushl %esi FRAME_pushl()
  77. movl PARAM_DIVISOR, %esi
  78. orl %ecx,%ecx C size
  79. jz L(size_zero)
  80. pushl %ebx FRAME_pushl()
  81. movl -4(%edi,%ecx,4), %eax C src high limb
  82. xorl %edx, %edx
  83. movl PARAM_DST, %ebx
  84. pushl %ebp FRAME_pushl()
  85. movl PARAM_XSIZE, %ebp
  86. cmpl %esi, %eax
  87. leal -4(%ebx,%ebp,4), %ebx C dst one limb below integer part
  88. jae L(integer_entry)
  89. C high<divisor, so high of dst is zero, and avoid one div
  90. movl %edx, (%ebx,%ecx,4)
  91. decl %ecx
  92. movl %eax, %edx
  93. jz L(fraction)
  94. L(integer_top):
  95. C eax scratch (quotient)
  96. C ebx dst+4*xsize-4
  97. C ecx counter
  98. C edx scratch (remainder)
  99. C esi divisor
  100. C edi src
  101. C ebp xsize
  102. movl -4(%edi,%ecx,4), %eax
  103. L(integer_entry):
  104. divl %esi
  105. movl %eax, (%ebx,%ecx,4)
  106. loop L(integer_top)
  107. L(fraction):
  108. orl %ebp, %ecx
  109. jz L(done)
  110. movl PARAM_DST, %ebx
  111. L(fraction_top):
  112. C eax scratch (quotient)
  113. C ebx dst
  114. C ecx counter
  115. C edx scratch (remainder)
  116. C esi divisor
  117. C edi
  118. C ebp
  119. xorl %eax, %eax
  120. divl %esi
  121. movl %eax, -4(%ebx,%ecx,4)
  122. loop L(fraction_top)
  123. L(done):
  124. popl %ebp
  125. movl %edx, %eax
  126. popl %ebx
  127. popl %esi
  128. popl %edi
  129. ret
  130. L(size_zero):
  131. deflit(`FRAME',8)
  132. movl PARAM_XSIZE, %ecx
  133. xorl %eax, %eax
  134. movl PARAM_DST, %edi
  135. cld C better safe than sorry, see mpn/x86/README
  136. rep
  137. stosl
  138. popl %esi
  139. popl %edi
  140. ret
  141. EPILOGUE()