testpico: show that vres clear is separate
[megadrive.git] / testpico / asmtools.S
CommitLineData
ffd4b35c 1# Assemble with gas
2# --register-prefix-optional --bitwise-or
e71680d5 3# reminder: d2-d7/a2-a6 are callee-save
ffd4b35c 4
5.macro ldarg arg, stacksz, reg
6 move.l (4 + \arg * 4 + \stacksz)(%sp), \reg
7.endm
8
5073ab5a 9# args are always 4 bytes in stack, caller restores sp
6c839579 10.macro ldargw arg, stacksz, reg
11 move.w (4 + \arg * 4 + 2 + \stacksz)(%sp), \reg
12.endm
13
ffd4b35c 14.global burn10 /* u16 val */
15burn10:
635f2450 16 ldargw 0, 0, d0
ffd4b35c 17 subq.l #1, d0
180:
635f2450 19 dbra d0, 0b /* 10|14 */
20 rts /* 16 */
ffd4b35c 21
a385208c 22.global write16_x16 /* u32 a, u16 count, u16 d */
23write16_x16:
24 ldarg 0, 0, a0
25 ldarg 2, 0, d0
26 move.w d0, d1
27 swap d0
28 move.w d1, d0
29 ldarg 1, 0, d1
30 subq.l #1, d1
310:
32 move.l d0, (a0)
33 move.l d0, (a0)
34 move.l d0, (a0)
35 move.l d0, (a0)
36 move.l d0, (a0)
37 move.l d0, (a0)
38 move.l d0, (a0)
39 move.l d0, (a0)
40 dbra d1, 0b
41 rts
42
43# read single phase from controller
44# d0 - result
e71680d5 45# destroys d1
a385208c 46.global get_input
47get_input:
5073ab5a 48.global get_input_s
49get_input_s:
a385208c 50 move.b #0x40,(0xa10003)
51 moveq.l #0,d0
52 nop
53 nop
54 move.b (0xa10003),d1
55 move.b #0x00,(0xa10003)
56 andi.w #0x3f,d1 /* 00CB RLDU */
57 nop
58 move.b (0xa10003),d0
59 lsl.b #2,d0
60 andi.w #0xc0,d0 /* SA00 0000 */
61 or.b d1,d0
62 eor.b #0xff,d0
63.if 0
64 swap d7
65 move.w d7,d1
66 eor.w d0,d1 /* changed btns */
67 move.w d0,d7 /* old val */
68 swap d7
69 and.w d0,d1 /* what changed now */
70.endif
71 rts
5073ab5a 72.global get_input_end
73get_input_end:
a385208c 74
635f2450 75.global get_line
76get_line:
77 movea.l #0xc00008, a0
78 moveq.l #0, d0
790:
80 move.b (a0), d0 /* 8 d2 = vcnt */
81 cmp.b (a0), d0 /* 8 reread for super-rare corruption (torn read) */
82 bne 0b
83 rts
84
6c839579 85.global write_and_read1 /* u32 a, u16 d, void *dst */
86write_and_read1:
87 ldarg 0, 0, a0
88 ldargw 1, 0, d0
cc7e5122 89#ifndef PICO
6c839579 90 move.w d0, (a0)
cc7e5122 91#else
234c4556 92 /* different timing due to extra fetch of offset, */
93 /* less troulesome to emulate */
cc7e5122 94 movea.l a0, a1
95 subq.l #1, a1
96 move.w d0, 1(a1)
97#endif
6c839579 98 move.l (a0), d0
99 move.l (a0), d1
cc7e5122 100
101 ldarg 2, 0, a1
6c839579 102 move.l d0, (a1)+
103 move.l d1, (a1)+
104 rts
105
106.global move_sr /* u16 sr */
107move_sr:
108 ldargw 0, 0, d0
109 move.w d0, sr
110 rts
111
112.global move_sr_and_read /* u16 sr, u32 a */
113move_sr_and_read:
114 ldargw 0, 0, d0
115 ldarg 1, 0, a0
116 move.w d0, sr
117 move.w (a0), d0
118 rts
119
8517a6df 120.global read_sr
121read_sr:
122 move.w sr, d0
123 rts
124
6c839579 125.global memcpy_ /* void *dst, const void *src, u16 size */
126memcpy_:
127 ldarg 0, 0, a0
128 ldarg 1, 0, a1
129 ldargw 2, 0, d0
130 subq.w #1, d0
1310:
132 move.b (a1)+, (a0)+ /* not in a hurry */
133 dbra d0, 0b
134 rts
135
136.global memset_ /* void *dst, int d, u16 size */
137memset_:
138 ldarg 0, 0, a0
139 ldargw 1, 0, d1
140 ldargw 2, 0, d0
141 subq.w #1, d0
1420:
143 move.b d1, (a0)+ /* not in a hurry */
144 dbra d0, 0b
145 rts
146
147# tests
148
cc7e5122 149.global test_vcnt_vb
150test_vcnt_vb:
a385208c 151 movem.l d2-d7/a2, -(sp)
152 movea.l #0xc00007, a0
153 movea.l #0xc00008, a1
154 movea.l #0xff0000, a2
155 moveq.l #0, d4 /* d4 = count */
156 moveq.l #0, d5 /* d5 = vcnt_expect */
157 /* d6 = old */
158 move.l #1<<(3+16), d7 /* d7 = SR_VB */
1590:
160 btst #3, (a0)
161 beq 0b /* not blanking */
1620:
163 btst #3, (a0)
164 bne 0b /* blanking */
165
166 addq.l #1, a0
1670:
168 tst.b (a0)
169 bne 0b /* not line 0 */
170
171 subq.l #2, a0
172 move.l (a0), d6
173 move.l d6, (a2)+ /* d0 = old */
174###
1750:
176 move.b (a1), d2 /* 8 d2 = vcnt */
177 cmp.b (a1), d2 /* 8 reread for corruption */
178 bne 0b /* 10 on changing vcounter? */
179 cmp.b d2, d5 /* 4 vcnt == vcnt_expect? */
180 beq 0b /* 10 */
181 move.l (a0), d0 /* 12 */
182 tst.b d2 /* 4 */
183 beq 3f
1841:
185 addq.l #1, d4 /* count++ */
186 addq.l #1, d5
187 cmp.b d2, d5
188 bne 2f /* vcnt == vcnt_expect + 1 */
189 move.l d0, d1
190 eor.l d6, d1
191 and.l d7, d1 /* (old ^ val) & vb */
192 bne 2f
193 move.l d0, d6 /* old = val */
194 bra 0b
195
1962: /* vcnt jump or vb change */
197 move.l d6, (a2)+ /* *ram++ = old */
198 move.l d0, (a2)+ /* *ram++ = val */
199 move.b d2, d5 /* vcnt_expect = vcnt */
200 move.l d0, d6 /* old = val */
201 bra 0b
202
2033: /* vcnt == 0 */
204 move.l d0, d1
205 and.l d7, d1
206 bne 1b /* still in VB */
207
208 move.l d0, (a2)+ /* *ram++ = val */
209 move.l d4, (a2)+ /* *ram++ = count */
210
211 movem.l (sp)+, d2-d7/a2
9d39a80e 212 rts
a385208c 213
e71680d5 214.global test_vcnt_loops
215test_vcnt_loops:
216 movem.l d2, -(sp)
217 movea.l #0xc00007, a0
218 movea.l #0xfff000, a1
219 move.b #0xff, d0 /* d0 = current_vcnt */
220 moveq.l #0, d1 /* d1 = loop counter */
221 move.w #315-1, d2 /* d2 = line limit */
2220:
223 btst #3, (a0)
224 beq 0b /* not blanking */
2250:
226 btst #3, (a0)
227 bne 0b /* blanking */
228
229 addq.w #1, a0
2300:
231 addq.w #1, d1 /* 4 */
232 cmp.b (a0), d0 /* 8 vcnt changed? */
233 beq 0b /* 10 */
234
235 move.w d0, (a1)+ /* 8 save */
236 move.w d1, (a1)+
237 move.b (a0), d0 /* 8 new vcnt */
238 moveq.l #0, d1
239 dbra d2, 0b
240
241 movem.l (sp)+, d2
242 rts
243
6c839579 244.global test_hint
245test_hint:
246 move.w d0, -(sp) /* 8 */
247 move.w (0xc00008).l, d0 /* 16 */
248 addq.w #1, (0xf000).w /* 16 */
249 tst.w (0xf002).w /* 12 */
250 bne 0f /* 10 */
251 move.w d0, (0xf002).w /* 12 */
2520:
253 move.w d0, (0xf004).w /* 12 */
254 move.w (sp)+, d0 /* 8 */
8517a6df 255 rte /* 20 114+44 */
6c839579 256.global test_hint_end
257test_hint_end:
258
259.global test_vint
260test_vint:
261 move.w d0, -(sp) /* 8 */
262 move.w (0xc00008).l, d0 /* 16 */
263 addq.w #1, (0xf008).w /* 16 */
264 tst.w (0xf00a).w /* 12 */
265 bne 0f /* 10 */
266 move.w d0, (0xf00a).w /* 12 */
2670:
268 move.w d0, (0xf00c).w /* 12 */
269 move.w (sp)+, d0 /* 8 */
270 rte /* 20 114 */
271.global test_vint_end
272test_vint_end:
273
9d39a80e 274.global x32x_enable
275x32x_enable:
276 movea.l #0xa15100, a0
71b41fdd 277 movea.l #0xa15122, a1
278 move.w #1, (a0) /* ADEN */
279# wait for min(20_sh2_cycles, pll_setup_time)
280# pll time is unclear, icd_mars.prg mentions 10ms which sounds
281# way too much. Hope 40 68k cycles is enough
282 move.w #40/10, d0
2830:
284 dbra d0, 0b
9d39a80e 285 move.w #3, (a0) /* ADEN, nRES */
2860:
71b41fdd 287 move.w #0xffff, d0 /* waste some cycles */
9d39a80e 288 tst.w (a1)
71b41fdd 289 beq 0b /* master BIOS busy */
290
2910: /* for slave, use a limit, as it */
292 tst.w 4(a1) /* won't respond on master error. */
293 dbne d0, 0b /* slave BIOS busy */
294
9d39a80e 295 or.w #1, 6(a0) /* RV */
296 rts
297.global x32x_enable_end
298x32x_enable_end:
299
234c4556 300.global x32x_disable
301x32x_disable:
302 movea.l #0xa15100, a0
c8abdf56 303 move.w #0, 6(a0) /* RV=0 */
234c4556 304 move.w #1, (a0) /* ADEN (reset sh2) */
305 move.w #0, (a0) /* adapter disable, reset sh2 */
306 move.w #1, d0
3070:
308 dbra d0, 0b
309 move.w #2, (a0) /* nRES - sh2s should see no ADEN and sleep */
310 rts
311.global x32x_disable_end
312x32x_disable_end:
313
06d7984c 314.global test_32x_b_c0
315test_32x_b_c0:
316 ldarg 0, 0, a1
317 ldargw 1, 0, d0
318 jsr (0xc0).l /* move.b d0, (a1); RV=0 */
234c4556 319 bset #0, (0xa15107).l /* RV=1 */
06d7984c 320 rts
321.global test_32x_b_c0_end
322test_32x_b_c0_end:
323
cc7e5122 324# some nastyness from Fatal Rewind
325.global test_h_v_2
326test_h_v_2:
327 move.w #0x2000, sr
328 move.w #0x8014, (0xFFC00004).l
329 move.w #0x8164, (0xFFC00004).l
330 move.w #1, d0
3310:
332 dbra d0, 0b
333 move.w #0x2700, sr
334 rts
335
336.global test_v_h_2
337test_v_h_2:
338 move.w #0x2000, sr
339 movea.l #0xc00004, a0
340 move.w #0x8164, (a0)
341 move.w #0x8144, (a0)
342 move.w #480/2/10-1, d0
3430:
344 dbra d0, 0b
345 move.w #0x8164, (0xFFC00004).l
346 move.w #0x8014, (0xFFC00004).l
347 move.w #0x2700, sr
348 rts
349
350.global test_f_vint
351test_f_vint:
352 move.w (a1), d0
353 rte
354.global test_f_vint_end
355test_f_vint_end:
356
357.global test_f
358test_f:
359 movea.l #0xc00005, a0
360 movea.l #0xc00004, a1
361 move.w #0x2000, sr
3620:
363 btst #3, (a0)
364 bne 0b
3650:
366 btst #3, (a0)
367 beq 0b
368 movem.l d2-d7/a2, -(sp)
369 move.l (a1), d1
370 move.l (a1), d2
371 move.l (a1), d3
372 move.l (a1), d4
373 move.l (a1), d5
374 move.l (a1), d6
375 move.w #0x2700, sr
376 movea.l #0xff0000, a0
377 move.b d0, (a0)+
378 move.b #0, (a0)+
379.macro test_lb_s sr, dr
380 swap \sr
381 move.b \sr, (\dr)+
382 swap \sr
383 move.b \sr, (\dr)+
384.endm
385 test_lb_s d1, a0
386 test_lb_s d2, a0
387 test_lb_s d3, a0
388 test_lb_s d4, a0
389 test_lb_s d5, a0
390 movem.l (sp)+, d2-d7/a2
9d39a80e 391 rts
cc7e5122 392
393.global test_hb
394test_hb:
395 movem.l d2-d7, -(sp)
396 movea.l #0xc00004, a0
397 movea.l #0xc00008, a1
398 moveq.l #1, d0
3990:
400 cmp.b (a1), d0
401 beq 0b
4020:
403 cmp.b (a1), d0
404 bne 0b
405 move.l (a0), d0
406 move.l (a0), d1
407 move.l (a0), d2
408 movea.l #0xff0000, a1
409 movea.l #0xff0000, a1
410 nop
411 nop
412 move.l (a0), d3
413 move.l (a0), d4
414 move.l (a0), d5
415 move.l (a0), d6
416 move.l (a0), d7
417 test_lb_s d0, a1
418 test_lb_s d1, a1
419 test_lb_s d2, a1
420 test_lb_s d3, a1
421 test_lb_s d4, a1
422 test_lb_s d5, a1
423 test_lb_s d6, a1
424 test_lb_s d7, a1
425 movem.l (sp)+, d2-d7
9d39a80e 426 rts
6c839579 427
e71680d5 428.macro ymwrite areg, dreg addr dat
429 move.b \addr, (\areg) /* 12 addr */
430 nbcd d0 /* 6 delay to reach 17 ym cycles (M/7) */
431 move.b \dat, (\dreg) /* 12 data */
432.endm
433
434.global test_ym_stopped_tick
435test_ym_stopped_tick:
436 movem.l a2-a3, -(sp)
437 movea.l #0xa04000, a0
438 movea.l #0xa04001, a1
439 movea.l #0xc00007, a2
440 movea.l #0xfff000, a3
441
442 ymwrite a0, a1, #0x27, #0x30 /* 30 disable, clear */
443 ymwrite a0, a1, #0x26, #0xff /* 30 timer b shortest interval */
444 move.b #0x27, (a0) /* 12 addr prep */
4450:
446 btst #3, (a2)
447 beq 0b /* not blanking */
4480:
449 btst #3, (a2)
450 bne 0b /* blanking */
451
452 addq.l #1, a2
4530:
454 tst.b (a2)
455 bne 0b /* not line 0 - waiting for sequential vcnt */
456
457 move.b #0x0a, (a1) /* 12 start timer b */
458 moveq.l #0, d0
459 moveq.l #2, d1
4600:
461 move.b (a0), d0
462 and.b d1, d0
463 beq 0b
4640:
465# move.w (a2), (a3)+ /* 12 save hvcnt */
466 move.b (a2), d0
467 cmp.b (a2), d0
468 bne 0b
469 move.w d0, (a3)+
470 move.b #0x30, (a1) /* 12 stop b, clear */
471
472 move.w #(1900/10-1), d0 /* waste cycles */
4730:
474 dbra d0, 0b
475 moveq.l #0, d0
476
477 move.w (a0), (a3)+ /* 12 save status */
478 move.b #0x0a, (a1) /* 12 start b */
4790:
480 move.b (a0), d0
481 and.b d1, d0
482 beq 0b
483
4840:
485# move.w (a2), (a3)+ /* 12 save hvcnt */
486 move.b (a2), d1
487 cmp.b (a2), d1
488 bne 0b
489 move.w d1, (a3)+
490 move.w d0, (a3)+ /* 12 save status */
491
492 movem.l (sp)+, a2-a3
493 rts
494
495.global test_ym_ab_sync
496test_ym_ab_sync:
497 movea.l #0xa04000, a0
498 movea.l #0xa04001, a1
499
500 ymwrite a0, a1, #0x27, #0x30 /* 30 disable, clear */
501 ymwrite a0, a1, #0x24, #0xfc /* 30 timer a */
635f2450 502 ymwrite a0, a1, #0x25, #0x01 /* 30 =15 */
e71680d5 503 ymwrite a0, a1, #0x26, #0xff /* 30 timer b shortest interval */
504 move.b #0x27, (a0) /* 12 addr prep */
505 nop
506 nop
507
508 move.b #0x0a, (a1) /* 12 start timer b */
509 moveq.l #0, d0
510 moveq.l #2, d1
5110:
512 move.b (a0), d0 /* 8 */
513 and.b d1, d0 /* 4 */
514 beq 0b /* 10|8 */
635f2450 515
e71680d5 516 move.b #0x3f, (a1) /* 12 start a, clear */
438648dc 517
635f2450 518 move.w #(488/10), d0 /* waste cycles */
5190: dbra d0, 0b
520
521 ymwrite a0, a1, #0x24, #0xf0 /* 30 show that rewriting count */
522 ymwrite a0, a1, #0x25, #0x00 /* 30 does nothing until timer expires */
523
524 move.w #(488*2/10), d0 /* waste cycles */
5250: dbra d0, 0b
526
527 ymwrite a0, a1, #0x26, #0xfc /* 30 same for timer b */
438648dc 528 ymwrite a0, a1, #0x27, #0x0f /* 30 setting already set bits too */
529 moveq.l #0, d0
530 moveq.l #3, d1
e71680d5 5310:
532 move.b (a0), d0
533 and.b d1, d0
534 beq 0b
535 move.b (a0), d0 /* re-read, else very occasionally get 1 */
536 rts
537
635f2450 538.global test_ym_ab_sync2
539test_ym_ab_sync2:
540 movea.l #0xa04000, a0
541 movea.l #0xa04001, a1
542
3d80f940 543 move.b #0x0f, (a1) /* 12 enable */
635f2450 544 moveq.l #0, d0
545 moveq.l #3, d1
546 nop /* 4 need ~12c to clear */
5470:
548 move.b (a0), d0 /* 8 */
549 and.b d1, d0 /* 4 */
550 beq 0b /* 10|8 */
551 move.b (a0), d0 /* re-read */
3d80f940 552 move.b #0x3c, (a1) /* 12 clear, disable */
635f2450 553 rts
554
5073ab5a 555.global x32x_switch_rv
556x32x_switch_rv:
557 ldargw 0, 0, d0
558 move.l (sp)+, d1
559 movea.l #0xa15106, a0
560 btst #0, d0
561 bne 0f
562 move.w #0, (a0)
563 or.l #0x880000, d1
564 bra 1f
5650:
566 move.w #1, (a0)
567 and.l #0x07ffff, d1
5681:
569 movea.l d1, a1
570 jmp (a1)
571.global x32x_switch_rv_end
572x32x_switch_rv_end:
573
ffd4b35c 574# vim:filetype=asmM68k:ts=4:sw=4:expandtab