draw_arm.S 13 KB

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