draw_arm.S 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444
  1. @*
  2. @* PicoDrive
  3. @* (C) notaz, 2010
  4. @* (C) kub, 2019
  5. @*
  6. @* This work is licensed under the terms of MAME license.
  7. @* See COPYING file in the top-level directory.
  8. @*
  9. #include <pico/arm_features.h>
  10. #include <pico/pico_int_offs.h>
  11. .extern Pico32x
  12. .extern Pico
  13. .equiv P32XV_PRI, (1<< 7)
  14. .text
  15. .align 2
  16. PIC_LDR_INIT()
  17. .macro call_scan_prep cond est @ &Pico.est
  18. .if \cond
  19. PIC_LDR(r4, r6, PicoScan32xBegin)
  20. PIC_LDR(r5, r6, PicoScan32xEnd)
  21. ldr r6, [\est, #OFS_EST_DrawLineDest]
  22. ldr r4, [r4]
  23. ldr r5, [r5]
  24. stmfd sp!, {r4,r5,r6}
  25. .endif
  26. .endm
  27. .macro call_scan_fin_ge cond
  28. .if \cond
  29. addge sp, sp, #4*3
  30. .endif
  31. .endm
  32. .macro call_scan_begin cond
  33. .if \cond
  34. stmfd sp!, {r1-r3}
  35. and r0, r2, #0xff
  36. add r0, r0, r4
  37. mov lr, pc
  38. ldr pc, [sp, #(3+0)*4]
  39. ldr r0, [sp, #(3+2)*4] @ &DrawLineDest
  40. ldmfd sp!, {r1-r3}
  41. ldr r0, [r0]
  42. .endif
  43. .endm
  44. .macro call_scan_end cond
  45. .if \cond
  46. stmfd sp!, {r0-r3}
  47. and r0, r2, #0xff
  48. add r0, r0, r4
  49. mov lr, pc
  50. ldr pc, [sp, #(4+1)*4]
  51. ldmfd sp!, {r0-r3}
  52. .endif
  53. .endm
  54. @ direct color
  55. @ unsigned short *dst, unsigned short *dram, int lines_sft_offs, int mdbg
  56. .macro make_do_loop_dc name call_scan do_md
  57. .global \name
  58. \name:
  59. stmfd sp!, {r4-r11,lr}
  60. PIC_LDR(lr, r9, Pico)
  61. PIC_LDR(r10,r9, Pico32x)
  62. ldr r11, [lr, #OFS_Pico_est+OFS_EST_Draw2FB]
  63. ldrh r10,[r10, #0x40] @ Pico32x.vdp_regs[0]
  64. add r9, lr, #OFS_Pico_est+OFS_EST_HighPal @ palmd
  65. and r4, r2, #0xff
  66. mov r5, #328
  67. mov r3, r3, lsl #26 @ mdbg << 26
  68. mla r11,r4,r5,r11 @ r11 = pmd = PicoDraw2FB + offs*328: md data
  69. tst r10,#P32XV_PRI
  70. movne r10,#0
  71. moveq r10,#0x8000 @ r10 = inv_bit
  72. call_scan_prep \call_scan lr
  73. mov r4, #0 @ line
  74. b 1f @ loop_outer_entry
  75. 0: @ loop_outer:
  76. call_scan_end \call_scan
  77. add r4, r4, #1
  78. cmp r4, r2, lsr #16
  79. call_scan_fin_ge \call_scan
  80. ldmgefd sp!, {r4-r11,pc}
  81. 1: @ loop_outer_entry:
  82. call_scan_begin \call_scan
  83. mov r12,r4, lsl #1
  84. ldrh r12,[r1, r12]
  85. add r11,r11,#8
  86. mov r6, #320
  87. add r5, r1, r12, lsl #1 @ p32x = dram + dram[l]
  88. 2: @ loop_inner:
  89. ldrh r8, [r5], #2
  90. subs lr, r6, #1
  91. blt 0b @ loop_outer
  92. 3: @ loop_innermost:
  93. ldrh r7, [r5], #2 @ 32x pixel
  94. subs lr, lr, #1
  95. cmpge r7, r8
  96. beq 3b @ loop_innermost
  97. sub r5, r5, #2
  98. add lr, lr, #1
  99. sub lr, r6, lr
  100. sub r6, r6, lr
  101. eor r12,r8, r10
  102. tst r12, #0x8000 @ !((t ^ inv) & 0x8000)
  103. bne 5f @ draw_md
  104. and r7 ,r8, #0x03e0
  105. mov r8, r8, lsl #11
  106. orr r8, r8, r8, lsr #(10+11)
  107. orr r8, r8, r7 ,lsl #1
  108. bic r8, r8, #0x0020 @ kill prio bit
  109. add r11,r11,lr
  110. tst r0, #2 @ dst unaligned?
  111. strneh r8, [r0], #2
  112. subne lr, lr, #1
  113. cmp lr, #0
  114. beq 2b @ loop_inner
  115. mov r8, r8, lsl #16
  116. orr r12,r8, r8, lsr #16
  117. mov r8 ,r12
  118. 4: @ draw_32x:
  119. subs lr, lr, #4 @ store 4 pixels
  120. stmgeia r0!, {r8, r12}
  121. bgt 4b @ draw_32x
  122. beq 2b @ loop_inner
  123. adds lr, lr, #2 @ store 1-3 leftover pixels
  124. strge r8, [r0], #4
  125. strneh r8, [r0], #2
  126. b 2b @ loop_inner
  127. 5: @ draw_md:
  128. subs lr, lr, #1
  129. ldrgeb r7, [r11], #1 @ MD pixel
  130. blt 2b @ loop_inner
  131. cmp r3, r7, lsl #26 @ MD has bg pixel?
  132. .if \do_md
  133. mov r7, r7, lsl #1
  134. ldrneh r7 ,[r9, r7]
  135. strneh r7 ,[r0], #2 @ *dst++ = palmd[*pmd]
  136. .else
  137. addne r0, r0, #2
  138. .endif
  139. bne 5b @ draw_md
  140. and r7 ,r8, #0x03e0
  141. mov r8, r8, lsl #11
  142. orr r8, r8, r8, lsr #(10+11)
  143. orr r8, r8, r7 ,lsl #1
  144. bic r8, r8, #0x0020 @ kill prio bit
  145. strh r8, [r0], #2 @ *dst++ = bgr2rgb(*p32x++)
  146. 6: @ draw_md_32x:
  147. subs lr, lr, #1
  148. ldrgeb r7, [r11], #1 @ MD pixel
  149. blt 2b @ loop_inner
  150. cmp r3, r7, lsl #26 @ MD has bg pixel?
  151. .if \do_md
  152. mov r7, r7, lsl #1
  153. ldrneh r7 ,[r9, r7] @ *dst++ = palmd[*pmd]
  154. moveq r7 ,r8 @ *dst++ = bgr2rgb(*p32x++)
  155. strh r7 ,[r0], #2
  156. .else
  157. streqh r8, [r0] @ *dst++ = bgr2rgb(*p32x++)
  158. add r0, r0, #2
  159. .endif
  160. b 6b @ draw_md_32x
  161. .endm
  162. @ packed pixel
  163. @ note: this may read a few bytes over the end of PicoDraw2FB and dram,
  164. @ so those should have a bit more alloc'ed than really needed.
  165. @ unsigned short *dst, unsigned short *dram, int lines_sft_offs, int mdbg
  166. .macro make_do_loop_pp name call_scan do_md
  167. .global \name
  168. \name:
  169. stmfd sp!, {r4-r11,lr}
  170. PIC_LDR(lr, r9, Pico)
  171. PIC_LDR(r10,r9, Pico32xMem)
  172. ldr r9,=OFS_PMEM32x_pal_native
  173. ldr r10, [r10]
  174. ldr r11, [lr, #OFS_Pico_est+OFS_EST_Draw2FB]
  175. add r10,r10,r9
  176. add r9, lr, #OFS_Pico_est+OFS_EST_HighPal @ palmd
  177. and r4, r2, #0xff
  178. mov r5, #328
  179. mov r3, r3, lsl #26 @ mdbg << 26
  180. mla r11,r4,r5,r11 @ r11 = pmd = PicoDraw2FB + offs*328: md data
  181. call_scan_prep \call_scan lr
  182. mov r4, #0 @ line
  183. b 1f @ loop_outer_entry
  184. 0: @ loop_outer:
  185. call_scan_end \call_scan
  186. add r4, r4, #1
  187. cmp r4, r2, lsr #16
  188. call_scan_fin_ge \call_scan
  189. ldmgefd sp!, {r4-r11,pc}
  190. 1: @ loop_outer_entry:
  191. call_scan_begin \call_scan
  192. mov r12,r4, lsl #1
  193. ldrh r12,[r1, r12]
  194. add r11,r11,#8
  195. mov r6, #320/2
  196. add r5, r1, r12, lsl #1 @ p32x = dram + dram[l]
  197. and r12,r2, #0x100 @ shift
  198. add r5, r5, r12,lsr #8
  199. 2: @ loop_inner:
  200. @ r4,r6 - counters; r5 - 32x data; r9,r10 - md,32x pal; r11 - md data
  201. @ r7,r8,r12,lr - temp
  202. tst r5, #1
  203. ldreqb r8, [r5], #2
  204. ldrb r7, [r5, #-1]
  205. ldrneb r8, [r5, #2]! @ r7,r8 - pixel 0,1 index
  206. subs r6, r6, #1
  207. blt 0b @ loop_outer
  208. cmp r7, r8
  209. beq 5f @ check_fill @ +8
  210. 3: @ no_fill:
  211. mov r12,r7, lsl #1
  212. mov lr, r8, lsl #1
  213. ldrh r7, [r10,r12]
  214. ldrh r8, [r10,lr]
  215. add r11,r11,#2
  216. eor r12,r7, #0x20
  217. tst r12,#0x20
  218. ldrneb r12,[r11,#-2] @ MD pixel 0
  219. eor lr, r8, #0x20
  220. cmpne r3, r12, lsl #26 @ MD has bg pixel?
  221. .if \do_md
  222. mov r12,r12,lsl #1
  223. ldrneh r7, [r9, r12] @ t = palmd[pmd[0]]
  224. tst lr, #0x20
  225. ldrneb lr, [r11,#-1] @ MD pixel 1
  226. cmpne r3, lr, lsl #26 @ MD has bg pixel?
  227. mov lr, lr, lsl #1
  228. ldrneh r8, [r9, lr] @ t = palmd[pmd[1]]
  229. orr r7, r7, r8, lsl #16 @ combine 2 pixels to optimize memory bandwidth
  230. str r7, [r0], #4 @ (no write combining on ARM9)
  231. .else
  232. streqh r7, [r0]
  233. tst lr, #0x20
  234. ldrneb lr, [r11,#-1] @ MD pixel 1
  235. add r0, r0, #4
  236. cmpne r3, lr, lsl #26 @ MD has bg pixel?
  237. streqh r8, [r0, #-2]
  238. .endif
  239. b 2b @ loop_inner
  240. 5: @ check_fill:
  241. @ count pixels, align if needed
  242. bic r12,r5, #1
  243. ldrh lr ,[r12, #2] @ only do this for at least 4 pixels
  244. ldrh r12,[r12]
  245. orr r12,lr,r12, lsl #16
  246. orr lr, r7, r7, lsl #8
  247. orr lr, lr, lr, lsl #16
  248. cmp r12,lr
  249. bne 3b @ no_fill
  250. tst r5, #1
  251. sub lr, r5, #2 @ starting r5 (32x render data start)
  252. addeq r5, r5, #4
  253. addne r5, r5, #3 @ add for the check above
  254. add r6, r6, #1 @ restore from dec
  255. orr r7, r7, r7, lsl #8
  256. 6:
  257. sub r12,r5, lr
  258. ldrh r8, [r5], #2
  259. cmp r12,r6, lsl #1
  260. ldrh r12,[r5], #2
  261. bge 7f @ count_done
  262. cmp r8, r7
  263. subne r5, r5, #2 @ undo readahead
  264. cmpeq r12,r7
  265. beq 6b
  266. 7: @ count_done:
  267. sub r5, r5, #2 @ undo readahead
  268. @ fix alignment and check type
  269. sub r8, r5, lr
  270. tst r8, #1
  271. subne r5, r5, #1
  272. subne r8, r8, #1
  273. and r7, r7, #0xff
  274. cmp r8, r6, lsl #1
  275. mov r7, r7, lsl #1
  276. movgt r8, r6, lsl #1 @ r8=count
  277. ldrh r7, [r10,r7]
  278. sub r6, r6, r8, lsr #1 @ adjust counter
  279. tst r7, #0x20
  280. beq 9f @ bg_mode
  281. add r11,r11,r8
  282. orr r12,r7, r7, lsl #16
  283. mov r7 ,r12
  284. 8: @ 32x_loop:
  285. subs r8, r8, #4 @ store 4 pixels
  286. stmgeia r0!, {r7, r12}
  287. bgt 8b @ 32x_loop
  288. beq 2b @ loop_inner
  289. adds r8, r8, #2
  290. strge r7, [r0], #4 @ store 2 leftover pixels
  291. b 2b @ loop_inner
  292. 9: @ bg_mode:
  293. ldrb r12,[r11],#1 @ MD pixel 0,1
  294. ldrb lr, [r11],#1
  295. cmp r3, r12,lsl #26 @ MD pixel 0 has bg?
  296. .if \do_md
  297. mov r12,r12,lsl #1
  298. ldrneh r12,[r9, r12] @ t = palmd[*pmd]
  299. moveq r12,r7
  300. cmp r3, lr, lsl #26 @ MD pixel 1 has bg?
  301. mov lr, lr, lsl #1
  302. ldrneh lr, [r9, lr]
  303. moveq lr, r7
  304. orr r12,r12,lr, lsl #16 @ combine 2 pixels to optimize memory bandwidth
  305. str r12,[r0], #4 @ (no write combining on ARM9)
  306. .else
  307. streqh r7, [r0]
  308. cmp r3, lr, lsl #26 @ MD pixel 1 has bg?
  309. streqh r7, [r0, #2]
  310. add r0, r0, #4
  311. .endif
  312. subs r8, r8, #2
  313. bgt 9b @ bg_mode
  314. b 2b @ loop_inner
  315. .endm
  316. @ run length
  317. @ unsigned short *dst, unsigned short *dram, int lines_sft_offs, int mdbg
  318. .macro make_do_loop_rl name call_scan do_md
  319. .global \name
  320. \name:
  321. stmfd sp!, {r4-r11,lr}
  322. PIC_LDR(lr, r9, Pico)
  323. PIC_LDR(r10,r9, Pico32xMem)
  324. ldr r9,=OFS_PMEM32x_pal_native
  325. ldr r10, [r10]
  326. ldr r11, [lr, #OFS_Pico_est+OFS_EST_Draw2FB]
  327. add r10,r10,r9
  328. add r9, lr, #OFS_Pico_est+OFS_EST_HighPal @ palmd
  329. and r4, r2, #0xff
  330. mov r5, #328
  331. mov r3, r3, lsl #26 @ mdbg << 26
  332. mla r11,r4,r5,r11 @ r11 = pmd = PicoDraw2FB + offs*328: md data
  333. call_scan_prep \call_scan lr
  334. mov r4, #0 @ line
  335. b 1f @ loop_outer_entry
  336. 0: @ loop_outer:
  337. call_scan_end \call_scan
  338. add r4, r4, #1
  339. cmp r4, r2, lsr #16
  340. call_scan_fin_ge \call_scan
  341. ldmgefd sp!, {r4-r11,pc}
  342. 1: @ loop_outer_entry:
  343. call_scan_begin \call_scan
  344. mov r12,r4, lsl #1
  345. ldrh r12,[r1, r12]
  346. add r11,r11,#8
  347. mov r6, #320
  348. add r5, r1, r12, lsl #1 @ p32x = dram + dram[l]
  349. 2: @ loop_inner:
  350. ldrh r8, [r5], #2 @ control word
  351. and r12,r8, #0xff
  352. mov r12,r12,lsl #1
  353. ldrh lr, [r10,r12] @ t = 32x pixel
  354. eor lr, lr, #0x20
  355. 3: @ loop_innermost:
  356. subs r6, r6, #1
  357. ldrgeb r7, [r11], #1 @ MD pixel
  358. blt 0b @ loop_outer
  359. tst lr, #0x20
  360. cmpne r3, r7, lsl #26 @ MD has bg pixel?
  361. .if \do_md
  362. mov r7, r7, lsl #1
  363. ldrneh r12,[r9, r7] @ t = palmd[*pmd]
  364. streqh lr, [r0], #2
  365. strneh r12,[r0], #2 @ *dst++ = t
  366. .else
  367. streqh lr, [r0]
  368. add r0, r0, #2
  369. .endif
  370. subs r8, r8, #0x100
  371. bge 3b @ loop_innermost
  372. b 2b @ loop_inner
  373. .endm
  374. make_do_loop_dc do_loop_dc, 0, 0
  375. make_do_loop_dc do_loop_dc_md, 0, 1
  376. make_do_loop_dc do_loop_dc_scan, 1, 0
  377. make_do_loop_dc do_loop_dc_scan_md, 1, 1
  378. .pool
  379. make_do_loop_pp do_loop_pp, 0, 0
  380. make_do_loop_pp do_loop_pp_md, 0, 1
  381. make_do_loop_pp do_loop_pp_scan, 1, 0
  382. make_do_loop_pp do_loop_pp_scan_md, 1, 1
  383. .pool
  384. make_do_loop_rl do_loop_rl, 0, 0
  385. make_do_loop_rl do_loop_rl_md, 0, 1
  386. make_do_loop_rl do_loop_rl_scan, 1, 0
  387. make_do_loop_rl do_loop_rl_scan_md, 1, 1
  388. .pool
  389. @ vim:filetype=armasm