dvu4.s 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142
  1. .define .dvu4
  2. .sect .text
  3. .sect .rom
  4. .sect .data
  5. .sect .bss
  6. .sect .text
  7. ! 4-byte divide routine for z80
  8. ! parameters:
  9. ! stack: divisor
  10. ! dividend
  11. ! stack: quotient (out)
  12. ! bc de: remainder (out) (high part in bc)
  13. ! a n-byte divide may be implemented
  14. ! using 2 (virtual) registers:
  15. ! - a n-byte register containing
  16. ! the divisor
  17. ! - a 2n-byte shiftregister (VSR)
  18. !
  19. ! Initially, the VSR contains the dividend
  20. ! in its low (right) n bytes and zeroes in its
  21. ! high n bytes. The dividend is shifted
  22. ! left into a "window" bit by bit. After
  23. ! each shift, the contents of the window
  24. ! is compared with the divisor. If it is
  25. ! higher or equal, the divisor is subtracted from
  26. ! it and a "1" bit is inserted in the
  27. ! VSR from the right side! else a "0" bit
  28. ! is inserted. These bits are shifted left
  29. ! too during subsequent iterations.
  30. ! At the end, the rightmost part of VSR
  31. ! contains the quotient.
  32. ! For n=4, we need 2*4+4 = 12 bytes of
  33. ! registers. Unfortunately we only have
  34. ! 5 2-byte registers on the z80
  35. ! (bc,de,hl,ix and iy). Therefore we use
  36. ! an overlay technique for the rightmost
  37. ! 4 bytes of the VSR. The 32 iterations
  38. ! are split up into two groups: during
  39. ! the first 16 iterations we use the high
  40. ! order 16 bits of the dividend! during
  41. ! the last 16 iterations we use the
  42. ! low order 16 bits.
  43. ! register allocation:
  44. ! VSR iy hl ix
  45. ! divisor -de bc
  46. .dvu4:
  47. ! initialization
  48. pop hl ! save return address
  49. ld (.retaddr),hl
  50. pop bc ! low part (2 bytes)
  51. ! of divisor in bc
  52. xor a ! clear carry, a := 0
  53. ld h,a ! hl := 0
  54. ld l,a
  55. ld (.flag),a ! first pass main loop
  56. pop de ! high part divisor
  57. sbc hl,de ! inverse of high part
  58. ex de,hl ! of divisor in de
  59. pop hl ! save low part of
  60. ! dividend in memory
  61. ld (.low),hl ! used during second
  62. ! iteration over main loop
  63. pop ix ! high part of dividend
  64. push iy ! save LB
  65. ld h,a ! hl := 0
  66. ld l,a
  67. ld iy,0 ! now the VSR is initialized
  68. ! main loop, done twice
  69. 1:
  70. ld a,16
  71. ! sub-loop, done 16 times
  72. 2:
  73. add iy,iy ! shift VSR left
  74. add ix,ix
  75. adc hl,hl
  76. jp nc,3f
  77. inc iy
  78. 3:
  79. or a ! subtract divisor from
  80. ! window (iy hl)
  81. ld (.iysave),iy
  82. sbc hl,bc
  83. jr nc,4f ! decrement iy if there
  84. ! was no borrow
  85. dec iy
  86. 4:
  87. add iy,de ! there is no "sbc iy,ss"
  88. ! on the z80, so de was
  89. ! inverted during init.
  90. inc ix
  91. ! see if the result is non-negative,
  92. ! otherwise undo the subtract.
  93. ! note that this uncooperating machine
  94. ! does not set its S -or Z flag after
  95. ! a 16-bit add.
  96. ex (sp),iy ! does anyone see a better
  97. ex (sp),hl ! solution ???
  98. bit 7,h
  99. ex (sp),hl
  100. ex (sp),iy
  101. jp z,5f
  102. ! undo the subtract
  103. add hl,bc
  104. ld iy,(.iysave)
  105. dec ix
  106. 5:
  107. dec a
  108. jr nz,2b
  109. ld a,(.flag) ! see if this was first or
  110. ! second iteration of main loop
  111. or a ! 0=first, 1=second
  112. jr nz,6f
  113. inc a ! a := 1
  114. ld (.flag),a ! flag := 1
  115. ld (.result),ix ! save high part of result
  116. ld ix,(.low) ! initialize second
  117. ! iteration, ix := low
  118. ! part of dividend
  119. jr 1b
  120. 6:
  121. ! clean up
  122. push iy ! transfer remainder
  123. pop bc ! from iy-hl to bc-de
  124. ex de,hl
  125. pop iy ! restore LB
  126. ld hl,(.result) ! high part of result
  127. push hl
  128. push ix ! low part of result
  129. ld hl,(.retaddr)
  130. jp (hl) ! return
  131. .sect .data
  132. .flag: .data1 0
  133. .low: .data2 0
  134. .iysave: .data2 0
  135. .retaddr: .data2 0
  136. .result: .data2 0