divsi3.S 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. ! Copyright (C) 2001, 2002, 2003, 2004, 2005, 2006, 2007
  2. ! Imagination Technologies Ltd
  3. !
  4. ! Integer divide routines.
  5. !
  6. .text
  7. .global ___udivsi3
  8. .type ___udivsi3,function
  9. .align 2
  10. ___udivsi3:
  11. !!
  12. !! Since core is signed divide case, just set control variable
  13. !!
  14. MOV D1Re0,D0Ar2 ! Au already in A1Ar1, Bu -> D1Re0
  15. MOV D0Re0,#0 ! Result is 0
  16. MOV D0Ar4,#0 ! Return positive result
  17. B $LIDMCUStart
  18. .size ___udivsi3,.-___udivsi3
  19. !!
  20. !! 32-bit division signed i/p - passed signed 32-bit numbers
  21. !!
  22. .global ___divsi3
  23. .type ___divsi3,function
  24. .align 2
  25. ___divsi3:
  26. !!
  27. !! A already in D1Ar1, B already in D0Ar2 -> make B abs(B)
  28. !!
  29. MOV D1Re0,D0Ar2 ! A already in A1Ar1, B -> D1Re0
  30. MOV D0Re0,#0 ! Result is 0
  31. XOR D0Ar4,D1Ar1,D1Re0 ! D0Ar4 -ive if result is -ive
  32. ABS D1Ar1,D1Ar1 ! abs(A) -> Au
  33. ABS D1Re0,D1Re0 ! abs(B) -> Bu
  34. $LIDMCUStart:
  35. CMP D1Ar1,D1Re0 ! Is ( Au > Bu )?
  36. LSR D1Ar3,D1Ar1,#2 ! Calculate (Au & (~3)) >> 2
  37. CMPHI D1Re0,D1Ar3 ! OR ( (Au & (~3)) <= (Bu << 2) )?
  38. LSLSHI D1Ar3,D1Re0,#1 ! Buq = Bu << 1
  39. BLS $LIDMCUSetup ! Yes: Do normal divide
  40. !!
  41. !! Quick divide setup can assume that CurBit only needs to start at 2
  42. !!
  43. $LIDMCQuick:
  44. CMP D1Ar1,D1Ar3 ! ( A >= Buq )?
  45. ADDCC D0Re0,D0Re0,#2 ! If yes result += 2
  46. SUBCC D1Ar1,D1Ar1,D1Ar3 ! and A -= Buq
  47. CMP D1Ar1,D1Re0 ! ( A >= Bu )?
  48. ADDCC D0Re0,D0Re0,#1 ! If yes result += 1
  49. SUBCC D1Ar1,D1Ar1,D1Re0 ! and A -= Bu
  50. ORS D0Ar4,D0Ar4,D0Ar4 ! Return neg result?
  51. NEG D0Ar2,D0Re0 ! Calculate neg result
  52. MOVMI D0Re0,D0Ar2 ! Yes: Take neg result
  53. $LIDMCRet:
  54. MOV PC,D1RtP
  55. !!
  56. !! Setup for general unsigned divide code
  57. !!
  58. !! D0Re0 is used to form the result, already set to Zero
  59. !! D1Re0 is the input Bu value, this gets trashed
  60. !! D0Ar6 is curbit which is set to 1 at the start and shifted up
  61. !! D0Ar4 is negative if we should return a negative result
  62. !! D1Ar1 is the input Au value, eventually this holds the remainder
  63. !!
  64. $LIDMCUSetup:
  65. CMP D1Ar1,D1Re0 ! Is ( Au < Bu )?
  66. MOV D0Ar6,#1 ! Set curbit to 1
  67. BCS $LIDMCRet ! Yes: Return 0 remainder Au
  68. !!
  69. !! Calculate alignment using FFB instruction
  70. !!
  71. FFB D1Ar5,D1Ar1 ! Find first bit of Au
  72. ANDN D1Ar5,D1Ar5,#31 ! Handle exceptional case.
  73. ORN D1Ar5,D1Ar5,#31 ! if N bit set, set to 31
  74. FFB D1Ar3,D1Re0 ! Find first bit of Bu
  75. ANDN D1Ar3,D1Ar3,#31 ! Handle exceptional case.
  76. ORN D1Ar3,D1Ar3,#31 ! if N bit set, set to 31
  77. SUBS D1Ar3,D1Ar5,D1Ar3 ! calculate diff, ffbA - ffbB
  78. MOV D0Ar2,D1Ar3 ! copy into bank 0
  79. LSLGT D1Re0,D1Re0,D1Ar3 ! ( > 0) ? left shift B
  80. LSLGT D0Ar6,D0Ar6,D0Ar2 ! ( > 0) ? left shift curbit
  81. !!
  82. !! Now we start the divide proper, logic is
  83. !!
  84. !! if ( A >= B ) add curbit to result and subtract B from A
  85. !! shift curbit and B down by 1 in either case
  86. !!
  87. $LIDMCLoop:
  88. CMP D1Ar1, D1Re0 ! ( A >= B )?
  89. ADDCC D0Re0, D0Re0, D0Ar6 ! If yes result += curbit
  90. SUBCC D1Ar1, D1Ar1, D1Re0 ! and A -= B
  91. LSRS D0Ar6, D0Ar6, #1 ! Shift down curbit, is it zero?
  92. LSR D1Re0, D1Re0, #1 ! Shift down B
  93. BNZ $LIDMCLoop ! Was single bit in curbit lost?
  94. ORS D0Ar4,D0Ar4,D0Ar4 ! Return neg result?
  95. NEG D0Ar2,D0Re0 ! Calculate neg result
  96. MOVMI D0Re0,D0Ar2 ! Yes: Take neg result
  97. MOV PC,D1RtP
  98. .size ___divsi3,.-___divsi3