array.asm 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397
  1. ; vim: ts=4:et:sw=4:
  2. ; Copyleft (K) by Jose M. Rodriguez de la Rosa
  3. ; (a.k.a. Boriel)
  4. ; http://www.boriel.com
  5. ; -------------------------------------------------------------------
  6. ; Simple array Index routine
  7. ; Number of total indexes dimensions - 1 at beginning of memory
  8. ; HL = Start of array memory (First two bytes contains N-1 dimensions)
  9. ; Dimension values on the stack, (top of the stack, highest dimension)
  10. ; E.g. A(2, 4) -> PUSH <4>; PUSH <2>
  11. ; For any array of N dimension A(aN-1, ..., a1, a0)
  12. ; and dimensions D[bN-1, ..., b1, b0], the offset is calculated as
  13. ; O = [a0 + b0 * (a1 + b1 * (a2 + ... bN-2(aN-1)))]
  14. ; What I will do here is to calculate the following sequence:
  15. ; ((aN-1 * bN-2) + aN-2) * bN-3 + ...
  16. ;
  17. #include once <mul16.asm>
  18. #ifdef __CHECK_ARRAY_BOUNDARY__
  19. #include once <error.asm>
  20. #endif
  21. ;
  22. __ARRAY:
  23. ;- PROC
  24. ;- LOCAL LOOP
  25. ;- LOCAL ARRAY_END
  26. ;- LOCAL RET_ADDRESS ; Stores return address
  27. tsx ;- ex (sp), hl ; Return address in HL, array address in the stack
  28. lda $0103,x
  29. ldy z80_h
  30. sta z80_h
  31. tya
  32. sta $0103,x
  33. lda $0104,x
  34. ldy z80_l
  35. sta z80_l
  36. tya
  37. sta $104,x
  38. ;- ld (RET_ADDRESS + 1), hl ; Stores it for later
  39. lda z80_c ;- exx
  40. ldx z80_cp
  41. stx z80_c
  42. sta z80_cp
  43. lda z80_b
  44. ldx z80_bp
  45. stx z80_b
  46. sta z80_bp
  47. lda z80_e
  48. ldx z80_ep
  49. stx z80_e
  50. sta z80_ep
  51. lda z80_d
  52. ldx z80_dp
  53. stx z80_d
  54. sta z80_dp
  55. lda z80_l
  56. ldx z80_lp
  57. stx z80_l
  58. sta z80_lp
  59. lda z80_h
  60. ldx z80_hp
  61. stx z80_h
  62. sta z80_hp
  63. pla ;- pop hl ; Will use H'L' as the pointer
  64. sta z80_h
  65. pla
  66. sta z80_l
  67. ldy #$00 ;- ld c,(hl) ; Loads Number of dimensions from (hl)
  68. lda (z80_hl),y
  69. sta z80_c
  70. inc z80_l ;- inc hl
  71. bne *+4
  72. inc z80_h
  73. ldy #$00 ;- ld b,(hl)
  74. lda (z80_hl),y
  75. sta z80_b
  76. inc z80_l ;- inc hl ; Ready
  77. bne *+4
  78. inc z80_h
  79. lda z80_c ;- exx
  80. ldx z80_cp
  81. stx z80_c
  82. sta z80_cp
  83. lda z80_b
  84. ldx z80_bp
  85. stx z80_b
  86. sta z80_bp
  87. lda z80_e
  88. ldx z80_ep
  89. stx z80_e
  90. sta z80_ep
  91. lda z80_d
  92. ldx z80_dp
  93. stx z80_d
  94. sta z80_dp
  95. lda z80_l
  96. ldx z80_lp
  97. stx z80_l
  98. sta z80_lp
  99. lda z80_h
  100. ldx z80_hp
  101. stx z80_h
  102. sta z80_hp
  103. lda #<0 ;- ld hl,0 ; BC = Offset "accumulator"
  104. sta z80_l
  105. lda #>0
  106. sta z80_h
  107. #ifdef __CHECK_ARRAY_BOUNDARY__
  108. pla ;- pop de
  109. sta z80_d
  110. pla
  111. sta z80_e
  112. #endif
  113. LOOP:
  114. pla ;- pop bc ; Get next index (Ai) from the stack
  115. sta z80_b
  116. pla
  117. sta z80_c
  118. #ifdef __CHECK_ARRAY_BOUNDARY__
  119. lda z80_e ;- ex de,hl
  120. ldx z80_l
  121. stx z80_e
  122. sta z80_l
  123. lda z80_d
  124. ldx z80_h
  125. stx z80_d
  126. sta z80_h
  127. ora z80_a ;- or a
  128. ;- sbc hl,bc
  129. ;- ld a,ERROR_SubscriptWrong
  130. jcc __ERROR ;- jp c,__ERROR
  131. lda z80_e ;- ex de,hl
  132. ldx z80_l
  133. stx z80_e
  134. sta z80_l
  135. lda z80_d
  136. ldx z80_h
  137. stx z80_d
  138. sta z80_h
  139. #endif
  140. lda z80_l ;- add hl,bc ; Adds current index
  141. clc
  142. adc z80_c
  143. sta z80_l
  144. lda z80_h
  145. adc z80_b
  146. sta z80_h
  147. lda z80_c ;- exx ; Checks if B'C' = 0
  148. ldx z80_cp
  149. stx z80_c
  150. sta z80_cp
  151. lda z80_b
  152. ldx z80_bp
  153. stx z80_b
  154. sta z80_bp
  155. lda z80_e
  156. ldx z80_ep
  157. stx z80_e
  158. sta z80_ep
  159. lda z80_d
  160. ldx z80_dp
  161. stx z80_d
  162. sta z80_dp
  163. lda z80_l
  164. ldx z80_lp
  165. stx z80_l
  166. sta z80_lp
  167. lda z80_h
  168. ldx z80_hp
  169. stx z80_h
  170. sta z80_hp
  171. lda z80_b ;- ld a,b ; Which means we must exit (last element is not multiplied by anything)
  172. sta z80_a
  173. ora z80_c ;- or c
  174. jeq ARRAY_END ;- jr z,ARRAY_END ; if B'Ci == 0 we are done
  175. ldy #$00 ;- ld e,(hl) ; Loads next dimension into D'E'
  176. lda (z80_hl),y
  177. sta z80_e
  178. inc z80_l ;- inc hl
  179. bne *+4
  180. inc z80_h
  181. ldy #$00 ;- ld d,(hl)
  182. lda (z80_hl),y
  183. sta z80_d
  184. inc z80_l ;- inc hl
  185. bne *+4
  186. inc z80_h
  187. lda z80_e ;- push de
  188. pha
  189. lda z80_d
  190. pha
  191. ;- dec bc ; Decrements loop counter
  192. lda z80_c ;- exx
  193. ldx z80_cp
  194. stx z80_c
  195. sta z80_cp
  196. lda z80_b
  197. ldx z80_bp
  198. stx z80_b
  199. sta z80_bp
  200. lda z80_e
  201. ldx z80_ep
  202. stx z80_e
  203. sta z80_ep
  204. lda z80_d
  205. ldx z80_dp
  206. stx z80_d
  207. sta z80_dp
  208. lda z80_l
  209. ldx z80_lp
  210. stx z80_l
  211. sta z80_lp
  212. lda z80_h
  213. ldx z80_hp
  214. stx z80_h
  215. sta z80_hp
  216. pla ;- pop de ; DE = Max bound Number (i-th dimension)
  217. sta z80_d
  218. pla
  219. sta z80_e
  220. #ifdef __CHECK_ARRAY_BOUNDARY__
  221. lda z80_e ;- push de
  222. pha
  223. lda z80_d
  224. pha
  225. #endif
  226. ;call __MUL16_FAST ; HL *= DE
  227. ;- call __FNMUL
  228. #ifdef __CHECK_ARRAY_BOUNDARY__
  229. pla ;- pop de
  230. sta z80_d
  231. pla
  232. sta z80_e
  233. ;- dec de
  234. #endif
  235. jmp LOOP ;- jp LOOP
  236. ARRAY_END:
  237. ldy #$00 ;- ld e,(hl)
  238. lda (z80_hl),y
  239. sta z80_e
  240. inc z80_l ;- inc hl
  241. bne *+4
  242. inc z80_h
  243. lda z80_c ;- ld d,c ; C = 0 => DE = E = Element size
  244. sta z80_d
  245. lda z80_l ;- push hl
  246. pha
  247. lda z80_h
  248. pha
  249. lda z80_e ;- push de
  250. pha
  251. lda z80_d
  252. pha
  253. lda z80_c ;- exx
  254. ldx z80_cp
  255. stx z80_c
  256. sta z80_cp
  257. lda z80_b
  258. ldx z80_bp
  259. stx z80_b
  260. sta z80_bp
  261. lda z80_e
  262. ldx z80_ep
  263. stx z80_e
  264. sta z80_ep
  265. lda z80_d
  266. ldx z80_dp
  267. stx z80_d
  268. sta z80_dp
  269. lda z80_l
  270. ldx z80_lp
  271. stx z80_l
  272. sta z80_lp
  273. lda z80_h
  274. ldx z80_hp
  275. stx z80_h
  276. sta z80_hp
  277. #ifdef __BIG_ARRAY__
  278. pla ;- pop de
  279. sta z80_d
  280. pla
  281. sta z80_e
  282. jsr __FNMUL ;- call __FNMUL
  283. #else
  284. ;- LOCAL ARRAY_SIZE_LOOP
  285. lda z80_e ;- ex de,hl
  286. ldx z80_l
  287. stx z80_e
  288. sta z80_l
  289. lda z80_d
  290. ldx z80_h
  291. stx z80_d
  292. sta z80_h
  293. lda #<0 ;- ld hl,0
  294. sta z80_l
  295. lda #>0
  296. sta z80_h
  297. pla ;- pop bc
  298. sta z80_b
  299. pla
  300. sta z80_c
  301. lda z80_c ;- ld b,c
  302. sta z80_b
  303. ARRAY_SIZE_LOOP:
  304. clc ;- add hl,de
  305. lda z80_l
  306. adc z80_e
  307. sta z80_l
  308. lda z80_h
  309. adc z80_d
  310. sta z80_h
  311. ;- djnz ARRAY_SIZE_LOOP
  312. ;; Even faster
  313. ;pop bc
  314. ;ld d, h
  315. ;ld e, l
  316. ;dec c
  317. ;jp z, __ARRAY_FIN
  318. ;add hl, hl
  319. ;dec c
  320. ;jp z, __ARRAY_FIN
  321. ;add hl, hl
  322. ;dec c
  323. ;dec c
  324. ;jp z, __ARRAY_FIN
  325. ;add hl, de
  326. ;__ARRAY_FIN:
  327. #endif
  328. pla ;- pop de
  329. sta z80_d
  330. pla
  331. sta z80_e
  332. clc ;- add hl,de ; Adds element start
  333. lda z80_l
  334. adc z80_e
  335. sta z80_l
  336. lda z80_h
  337. adc z80_d
  338. sta z80_h
  339. RET_ADDRESS:
  340. lda #<0 ;- ld de,0
  341. sta z80_e
  342. lda #>0
  343. sta z80_d
  344. lda z80_e ;- push de
  345. pha
  346. lda z80_d
  347. pha
  348. rts ;- ret ; HL = (Start of Elements + Offset)
  349. ;; Performs a faster multiply for little 16bit numbs
  350. ;- LOCAL __FNMUL, __FNMUL2
  351. __FNMUL:
  352. eor z80_a ;- xor a
  353. ora z80_d ;- or d
  354. jne __MUL16_FAST ;- jp nz, __MUL16_FAST
  355. ora z80_e ;- or e
  356. lda z80_e ;- ex de,hl
  357. ldx z80_l
  358. stx z80_e
  359. sta z80_l
  360. lda z80_d
  361. ldx z80_h
  362. stx z80_d
  363. sta z80_h
  364. bne *+3 ;- ret z
  365. rts
  366. cmp #33 ;- cp 33
  367. jcs __MUL16_FAST ;- jp nc, __MUL16_FAST
  368. lda z80_l ;- ld b,l
  369. sta z80_b
  370. lda z80_h ;- ld l,h ; HL = 0
  371. sta z80_l
  372. __FNMUL2:
  373. clc ;- add hl,de
  374. lda z80_l
  375. adc z80_e
  376. sta z80_l
  377. lda z80_h
  378. adc z80_d
  379. sta z80_h
  380. dec z80_b ;- djnz __FNMUL2
  381. jne __FNMUL2
  382. rts ;- ret
  383. ;- ENDP