isort.z80 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237
  1. ;uses 19 bytes of RAM, 4 bytes of stack space
  2. ;#define speed
  3. #define tmp OP1+14
  4. #define head tmp+1
  5. #define head_lag tmp+3
  6. #macro advanceVAT()
  7. #ifdef speed
  8. ;17cc saved per iteration
  9. ;8 bytes vs a 3 byte call (but no 8-byte subroutine)
  10. ld bc,-6
  11. add hl,bc
  12. sbc a,a ;HL<=FE66, so carry flag is set
  13. sub (hl)
  14. ld c,a
  15. add hl,bc
  16. #else
  17. call advance_VAT ;preserves DE
  18. #endif
  19. #endmacro
  20. sortVAT:
  21. #ifdef nointerrupt
  22. di
  23. #endif
  24. ld hl,(progPtr)
  25. isort_main:
  26. _:
  27. ld (head_lag),hl
  28. ld d,h
  29. ld e,l
  30. advanceVAT()
  31. ld (head),hl
  32. #ifdef speed
  33. ;11 bytes, 29cc or 46cc. avg=29.06640625cc
  34. ld a,(pTemp)
  35. cp l
  36. jr nz,$+7
  37. ld a,(pTemp+1)
  38. cp h
  39. ret z
  40. #else
  41. ;adds 8 bytes, 55cc
  42. ld bc,(pTemp) ;Need to verify that we haven't reached the end of the progVAT
  43. or a ;
  44. sbc hl,bc ;
  45. ret z ;
  46. add hl,bc ;
  47. #endif
  48. call cmpVAT
  49. ld hl,(head)
  50. jr nc,-_
  51. ;if it makes it here, then (head) needs to be inserted into the previous part of the VAT
  52. ;We might be able to speed it up a little more if I also grab the next element
  53. ; If (head_advance) is bigger than (head), then no need to start the search from the beginning
  54. ld de,tmp
  55. #ifdef speed
  56. ldd
  57. ldd
  58. ldd
  59. ldd
  60. ldd
  61. ldd
  62. ld b,0
  63. ld c,(hl)
  64. lddr
  65. ldd
  66. #else
  67. ld bc,6
  68. lddr
  69. ld c,(hl)
  70. inc c
  71. lddr
  72. #endif
  73. ld hl,(progPtr)
  74. _:
  75. push hl
  76. #ifdef speed
  77. ;+5 bytes, -11cc
  78. ld bc,-6
  79. add hl,bc
  80. ld de,tmp-6
  81. call cmpVAT_stepin
  82. #else
  83. ex de,hl
  84. ld hl,tmp
  85. call cmpVAT
  86. #endif
  87. pop hl
  88. jr c,+_
  89. advanceVAT()
  90. jp -_
  91. _:
  92. ;HL is where to insert
  93. ld de,(head)
  94. or a
  95. sbc hl,de
  96. ld b,h
  97. ld c,l
  98. ld hl,-6
  99. add hl,de
  100. ld a,l
  101. sub a,(hl)
  102. ld l,a
  103. jr nc,$+4
  104. dec h
  105. or a
  106. inc de
  107. ex de,hl
  108. #ifdef speed
  109. call fastldir
  110. #else
  111. ldir
  112. #endif
  113. ;begin at DE, copy tmp. First need size of tmp
  114. ld hl,tmp-6
  115. ld c,(hl)
  116. sbc hl,bc
  117. ld a,c
  118. ldir
  119. #ifdef speed
  120. ldi
  121. ldi
  122. ldi
  123. ldi
  124. ldi
  125. ldi
  126. ldi
  127. add a,7
  128. #else
  129. ld c,7
  130. add a,c
  131. ldir
  132. #endif
  133. ld hl,(head_lag)
  134. ld c,a
  135. ld a,l
  136. sub c
  137. ld l,a
  138. jp nc,isort_main
  139. dec h
  140. jp isort_main
  141. #ifndef speed
  142. advance_VAT:
  143. ld bc,-6
  144. add hl,bc
  145. sbc a,a ;HL<=FE66, so carry flag is set
  146. sub (hl)
  147. ld c,a
  148. add hl,bc
  149. ret
  150. #endif
  151. cmpVAT:
  152. ;if @HL>=@DE, return nc
  153. ld bc,-6
  154. add hl,bc
  155. ex de,hl
  156. add hl,bc
  157. cmpVAT_stepin:
  158. ld a,(de)
  159. cp (hl)
  160. jr nc,first_longer
  161. ;the second name is longer.
  162. ld c,a
  163. _:
  164. dec hl
  165. dec de
  166. ld a,(de)
  167. cp (hl)
  168. ret nz
  169. dec c
  170. jr nz,-_
  171. scf
  172. ret
  173. first_longer:
  174. ;the first name is longer, so load c with the size of the second name
  175. ld c,(hl)
  176. _:
  177. dec hl
  178. dec de
  179. ld a,(de)
  180. cp (hl)
  181. ret nz
  182. dec c
  183. jr nz,-_
  184. ret
  185. #ifdef speed
  186. fastldir:
  187. ;copy BC bytes from HL to DE
  188. ;breaks even at 26 bytes
  189. ; 5% faster than LDIR with 35 bytes
  190. ;10% faster than LDIR with 48 bytes
  191. ;15% faster than LDIR with 91 bytes
  192. ;20% faster than LDIR with 635 bytes
  193. ;max is ~ 20.8% faster than LDIR
  194. ;Cost: 104+16N+10ceiling(N/16)
  195. push hl
  196. ; push af
  197. xor a
  198. sub c
  199. and 15 ;change to n-1
  200. add a,a
  201. ld hl,ldirloop
  202. add a,l
  203. ld l,a
  204. #if (ldirloop>>8)!=(_ldirloop_end>>8)
  205. jr nc,$+3 ;these aren't needed if the ldirloop doesn't cross a 256 byte boundary. Can save 12cc on the above timings and 3 bytes.
  206. inc h ;
  207. #endif
  208. ; pop af
  209. ex (sp),hl
  210. ret
  211. ldirloop:
  212. ;n=16, (number of LDI instructions, use qty of 4,8,16,32,64)
  213. ldi
  214. ldi
  215. ldi
  216. ldi
  217. ldi
  218. ldi
  219. ldi
  220. ldi
  221. ldi
  222. ldi
  223. ldi
  224. ldi
  225. ldi
  226. ldi
  227. ldi
  228. _ldirloop_end:
  229. ldi
  230. jp pe,ldirloop
  231. ret
  232. #endif
  233. #undefine tmp
  234. #undefine head
  235. #undefine head_lag1