divide.inc 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Based on restoring division algorithm
  2. // Algorithm source document: Lecture notes by S. Galal and D. Pham, Division algorithms and hardware implementations.
  3. // Link to documentation http://www.seas.ucla.edu/~ingrid/ee213a/lectures/division_presentV2.pdf
  4. // Also refer to description on Wikipedia: https://en.wikipedia.org/wiki/Division_algorithm#Restoring_division
  5. // Note that the algorithm automatically yields the following results for special cases:
  6. // z div 0 = MAX(type)
  7. // 0 div 0 = MAX(type)
  8. // 0 div n = 0
  9. // Checks for z = 0; n = [0,1]; n = z and n > z could shortcut the algorithm for speed-ups
  10. // but would add extra code
  11. // Perhaps add the checks depending on optimization settings?
  12. // z in Ra, n in Rb, 0 in Rp
  13. function fpc_divmod_byte(n, z: byte): byte; assembler; nostackframe;
  14. label
  15. div1, div2, div3, finish;
  16. asm
  17. // Symbol Name Register(s)
  18. // z (A) dividend R22
  19. // n (B) divisor R24
  20. // p (P) remainder R20
  21. // i counter R18
  22. clr R20 // clear remainder
  23. ldi R18, 8 // iterate over 8 bits
  24. div1:
  25. lsl R22 // shift left A
  26. rol R20 // shift left P with carry from A shift
  27. sub R20, R24 // Subtract B from P, P <= P - B
  28. brlo div2
  29. ori R22, 1 // Set A[0] = 1
  30. rjmp div3
  31. div2: // negative branch, A[0] = 0 (default after shift), restore P
  32. add R20, R24 // restore old value of P
  33. div3:
  34. dec R18
  35. brne div1
  36. finish:
  37. mov R24, R22 // Move result from R22 to R24
  38. end;
  39. // z in Ra, n in Rb, 0 in Rp
  40. function fpc_divmod_word(n, z: word): word; assembler; nostackframe;
  41. label
  42. div1, div2, div3, finish;
  43. asm
  44. // Symbol Name Register(s)
  45. // z (A) dividend R23, R22
  46. // n (B) divisor R25, R24
  47. // p (P) remainder R21, R20
  48. // i counter R18
  49. clr R20 // clear remainder low
  50. clr R21 // clear remainder hi
  51. ldi R18, 16 // iterate over 16 bits
  52. div1:
  53. lsl R22 // shift left A_L
  54. rol R23
  55. rol R20 // shift left P with carry from A shift
  56. rol R21
  57. sub R20, R24 // Subtract B from P, P <= P - B
  58. sbc R21, R25
  59. brlo div2
  60. ori R22, 1 // Set A[0] = 1
  61. rjmp div3
  62. div2: // negative branch, A[0] = 0 (default after shift), restore P
  63. add R20, R24 // restore old value of P
  64. adc R21, R25
  65. div3:
  66. dec R18
  67. brne div1
  68. finish:
  69. movw R24, R22 // Move result from R22:R23 to R24:R25
  70. end;
  71. // z in Ra, n in Rb, 0 in Rp
  72. function fpc_divmod_dword(n, z: dword): dword; assembler; nostackframe;
  73. label
  74. div1, div2, div3, finish;
  75. asm
  76. // Symbol Name Register(s)
  77. // z (A) dividend R21, R20, R19, R18
  78. // n (B) divisor R25, R24, R23, R22
  79. // p (P) remainder R17, R16, R15, R14 -> Returned in R25, R24, R23, R22
  80. // i counter R26
  81. push R17
  82. push R16
  83. push R15
  84. push R14
  85. clr R14 // clear remainder
  86. clr R15 // clear remainder
  87. clr R16
  88. clr R17
  89. ldi R26, 32 // iterate over 32 bits
  90. div1:
  91. lsl R18 // shift left A_L
  92. rol R19
  93. rol R20
  94. rol R21
  95. rol R14 // shift left P with carry from A shift
  96. rol R15
  97. rol R16
  98. rol R17
  99. sub R14, R22 // Subtract B from P, P <= P - B
  100. sbc R15, R23
  101. sbc R16, R24
  102. sbc R17, R25
  103. brlo div2
  104. ori R18, 1 // Set A[0] = 1
  105. rjmp div3
  106. div2: // negative branch, A[0] = 0 (default after shift), restore P
  107. add R14, R22 // restore old value of P
  108. adc R15, R23
  109. adc R16, R24
  110. adc R17, R25
  111. div3:
  112. dec R26
  113. brne div1
  114. finish:
  115. movw R22, R14 // Move remainder into reg that is not volatile
  116. movw R24, R16
  117. pop R14
  118. pop R15
  119. pop R16
  120. pop R17
  121. end;