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

数学计算

开发平台:

Unix_Linux

  1. dnl  ARM mpn_udiv_qrnnd -- divide a two limb dividend and a one limb divisor.
  2. dnl  Return quotient and store remainder through a supplied pointer.
  3. dnl  Copyright 2001 Free Software Foundation, Inc.
  4. dnl  This file is part of the GNU MP Library.
  5. dnl  The GNU MP Library is free software; you can redistribute it and/or modify
  6. dnl  it under the terms of the GNU Lesser General Public License as published
  7. dnl  by the Free Software Foundation; either version 3 of the License, or (at
  8. dnl  your option) any later version.
  9. dnl  The GNU MP Library is distributed in the hope that it will be useful, but
  10. dnl  WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  11. dnl  or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
  12. dnl  License for more details.
  13. dnl  You should have received a copy of the GNU Lesser General Public License
  14. dnl  along with the GNU MP Library.  If not, see http://www.gnu.org/licenses/.
  15. include(`../config.m4')
  16. C INPUT PARAMETERS
  17. define(`rem_ptr',`r0')
  18. define(`n1',`r1')
  19. define(`n0',`r2')
  20. define(`d',`r3')
  21. C divstep -- develop one quotient bit.  Dividend in $1$2, divisor in $3.
  22. C Quotient bit is shifted into $2.
  23. define(`divstep',
  24.        `adcs $2, $2, $2
  25. adc $1, $1, $1
  26. cmp $1, $3
  27. subcs $1, $1, $3')
  28. ASM_START()
  29. PROLOGUE(mpn_udiv_qrnnd)
  30. mov r12, #8 C loop counter for both loops below
  31. cmp d, #0x80000000 C check divisor msb and clear carry
  32. bcs L(_large_divisor)
  33. L(oop): divstep(n1,n0,d)
  34. divstep(n1,n0,d)
  35. divstep(n1,n0,d)
  36. divstep(n1,n0,d)
  37. sub r12, r12, #1
  38. teq r12, #0
  39. bne L(oop)
  40. str n1, [ rem_ptr ] C store remainder
  41. adc r0, n0, n0 C quotient: add last carry from divstep
  42. mov pc, lr
  43. L(_large_divisor):
  44. stmfd sp!, { r8, lr }
  45. and r8, n0, #1 C save lsb of dividend
  46. mov lr, n1, lsl #31
  47. orrs n0, lr, n0, lsr #1 C n0 = lo(n1n0 >> 1)
  48. mov n1, n1, lsr #1 C n1 = hi(n1n0 >> 1)
  49. and lr, d, #1 C save lsb of divisor
  50. movs d, d, lsr #1 C d = floor(orig_d / 2)
  51. adc d, d, #0 C d = ceil(orig_d / 2)
  52. L(oop2):
  53. divstep(n1,n0,d)
  54. divstep(n1,n0,d)
  55. divstep(n1,n0,d)
  56. divstep(n1,n0,d)
  57. sub r12, r12, #1
  58. teq r12, #0
  59. bne L(oop2)
  60. adc n0, n0, n0 C shift and add last carry from divstep
  61. add n1, r8, n1, lsl #1 C shift in omitted dividend lsb
  62. tst lr, lr C test saved divisor lsb
  63. beq L(_even_divisor)
  64. rsb d, lr, d, lsl #1 C restore orig d value
  65. adds n1, n1, n0 C fix remainder for omitted divisor lsb
  66. addcs n0, n0, #1 C adjust quotient if rem. fix carried
  67. subcs n1, n1, d C adjust remainder accordingly
  68. cmp n1, d C remainder >= divisor?
  69. subcs n1, n1, d C adjust remainder
  70. addcs n0, n0, #1 C adjust quotient
  71. L(_even_divisor):
  72. str n1, [ rem_ptr ] C store remainder
  73. mov r0, n0 C quotient
  74. ldmfd sp!, { r8, pc }
  75. EPILOGUE(mpn_udiv_qrnnd)