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

数学计算

开发平台:

Unix_Linux

  1. dnl  Intel Pentium-4 mpn_submul_1 -- Multiply a limb vector with a limb and
  2. dnl  subtract the result from a second limb vector.
  3. dnl  Copyright 2001, 2002 Free Software Foundation, 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 P4: 7 cycles/limb, unstable timing, at least on early Pentium4 silicon
  21. C     (stepping 10).
  22. C mp_limb_t mpn_submul_1 (mp_ptr dst, mp_srcptr src, mp_size_t size,
  23. C                         mp_limb_t mult);
  24. C mp_limb_t mpn_submul_1c (mp_ptr dst, mp_srcptr src, mp_size_t size,
  25. C                          mp_limb_t mult, mp_limb_t carry);
  26. C
  27. C This code is not particularly good at 7 c/l.  The dependent chain is only
  28. C 4 c/l and there's only 4 MMX unit instructions, so it's not clear why that
  29. C speed isn't achieved.
  30. C
  31. C The arrangements made here to get a two instruction dependent chain are
  32. C slightly subtle.  In the loop the carry (or borrow rather) is a negative
  33. C so that a paddq can be used to give a low limb ready to store, and a high
  34. C limb ready to become the new carry after a psrlq.
  35. C
  36. C If the carry was a simple twos complement negative then the psrlq shift
  37. C would need to bring in 0 bits or 1 bits according to whether the high was
  38. C zero or non-zero, since a non-zero value would represent a negative
  39. C needing sign extension.  That wouldn't be particularly easy to arrange and
  40. C certainly would add an instruction to the dependent chain, so instead an
  41. C offset is applied so that the high limb will be 0xFFFFFFFF+c.  With c in
  42. C the range -0xFFFFFFFF to 0, the value 0xFFFFFFFF+c is in the range 0 to
  43. C 0xFFFFFFFF and is therefore always positive and can always have 0 bits
  44. C shifted in, which is what psrlq does.
  45. C
  46. C The extra 0xFFFFFFFF must be subtracted before c is used, but that can be
  47. C done off the dependent chain.  The total adjustment then is to add
  48. C 0xFFFFFFFF00000000 to offset the new carry, and subtract
  49. C 0x00000000FFFFFFFF to remove the offset from the current carry, for a net
  50. C add of 0xFFFFFFFE00000001.  In the code this is applied to the destination
  51. C limb when fetched.
  52. C
  53. C It's also possible to view the 0xFFFFFFFF adjustment as a ones-complement
  54. C negative, which is how it's undone for the return value, but that doesn't
  55. C seem as clear.
  56. defframe(PARAM_CARRY,     20)
  57. defframe(PARAM_MULTIPLIER,16)
  58. defframe(PARAM_SIZE,      12)
  59. defframe(PARAM_SRC,       8)
  60. defframe(PARAM_DST,       4)
  61. TEXT
  62. ALIGN(16)
  63. PROLOGUE(mpn_submul_1c)
  64. deflit(`FRAME',0)
  65. movd PARAM_CARRY, %mm1
  66. jmp L(start_1c)
  67. EPILOGUE()
  68. PROLOGUE(mpn_submul_1)
  69. deflit(`FRAME',0)
  70. pxor %mm1, %mm1 C initial borrow
  71. L(start_1c):
  72. movl PARAM_SRC, %eax
  73. pcmpeqd %mm0, %mm0
  74. movd PARAM_MULTIPLIER, %mm7
  75. pcmpeqd %mm6, %mm6
  76. movl PARAM_DST, %edx
  77. psrlq $32, %mm0 C 0x00000000FFFFFFFF
  78. movl PARAM_SIZE, %ecx
  79. psllq $32, %mm6 C 0xFFFFFFFF00000000
  80. psubq %mm0, %mm6 C 0xFFFFFFFE00000001
  81. psubq %mm1, %mm0 C 0xFFFFFFFF - borrow
  82. C eax src, incrementing
  83. C ebx
  84. C ecx loop counter, decrementing
  85. C edx dst, incrementing
  86. C
  87. C mm0 0xFFFFFFFF - borrow
  88. C mm6 0xFFFFFFFE00000001
  89. C mm7 multiplier
  90. L(loop):
  91. movd (%eax), %mm1 C src
  92. leal 4(%eax), %eax
  93. movd (%edx), %mm2 C dst
  94. paddq %mm6, %mm2 C add 0xFFFFFFFE00000001
  95. pmuludq %mm7, %mm1
  96. psubq %mm1, %mm2 C prod
  97. paddq %mm2, %mm0 C borrow
  98. subl $1, %ecx
  99. movd %mm0, (%edx) C result
  100. psrlq $32, %mm0
  101. leal 4(%edx), %edx
  102. jnz L(loop)
  103. movd %mm0, %eax
  104. notl %eax
  105. emms
  106. ret
  107. EPILOGUE()