testpico: more messing to better understand timers
[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
6c839579 9.macro ldargw arg, stacksz, reg
10 move.w (4 + \arg * 4 + 2 + \stacksz)(%sp), \reg
11.endm
12
ffd4b35c 13.global burn10 /* u16 val */
14burn10:
15 ldarg 0, 0, d0
16 subq.l #1, d0
170:
18 dbra d0, 0b
19 rts
20
a385208c 21.global write16_x16 /* u32 a, u16 count, u16 d */
22write16_x16:
23 ldarg 0, 0, a0
24 ldarg 2, 0, d0
25 move.w d0, d1
26 swap d0
27 move.w d1, d0
28 ldarg 1, 0, d1
29 subq.l #1, d1
300:
31 move.l d0, (a0)
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 dbra d1, 0b
40 rts
41
42# read single phase from controller
43# d0 - result
e71680d5 44# destroys d1
a385208c 45.global get_input
46get_input:
47 move.b #0x40,(0xa10003)
48 moveq.l #0,d0
49 nop
50 nop
51 move.b (0xa10003),d1
52 move.b #0x00,(0xa10003)
53 andi.w #0x3f,d1 /* 00CB RLDU */
54 nop
55 move.b (0xa10003),d0
56 lsl.b #2,d0
57 andi.w #0xc0,d0 /* SA00 0000 */
58 or.b d1,d0
59 eor.b #0xff,d0
60.if 0
61 swap d7
62 move.w d7,d1
63 eor.w d0,d1 /* changed btns */
64 move.w d0,d7 /* old val */
65 swap d7
66 and.w d0,d1 /* what changed now */
67.endif
68 rts
69
6c839579 70.global write_and_read1 /* u32 a, u16 d, void *dst */
71write_and_read1:
72 ldarg 0, 0, a0
73 ldargw 1, 0, d0
cc7e5122 74#ifndef PICO
6c839579 75 move.w d0, (a0)
cc7e5122 76#else
234c4556 77 /* different timing due to extra fetch of offset, */
78 /* less troulesome to emulate */
cc7e5122 79 movea.l a0, a1
80 subq.l #1, a1
81 move.w d0, 1(a1)
82#endif
6c839579 83 move.l (a0), d0
84 move.l (a0), d1
cc7e5122 85
86 ldarg 2, 0, a1
6c839579 87 move.l d0, (a1)+
88 move.l d1, (a1)+
89 rts
90
91.global move_sr /* u16 sr */
92move_sr:
93 ldargw 0, 0, d0
94 move.w d0, sr
95 rts
96
97.global move_sr_and_read /* u16 sr, u32 a */
98move_sr_and_read:
99 ldargw 0, 0, d0
100 ldarg 1, 0, a0
101 move.w d0, sr
102 move.w (a0), d0
103 rts
104
8517a6df 105.global read_sr
106read_sr:
107 move.w sr, d0
108 rts
109
6c839579 110.global memcpy_ /* void *dst, const void *src, u16 size */
111memcpy_:
112 ldarg 0, 0, a0
113 ldarg 1, 0, a1
114 ldargw 2, 0, d0
115 subq.w #1, d0
1160:
117 move.b (a1)+, (a0)+ /* not in a hurry */
118 dbra d0, 0b
119 rts
120
121.global memset_ /* void *dst, int d, u16 size */
122memset_:
123 ldarg 0, 0, a0
124 ldargw 1, 0, d1
125 ldargw 2, 0, d0
126 subq.w #1, d0
1270:
128 move.b d1, (a0)+ /* not in a hurry */
129 dbra d0, 0b
130 rts
131
132# tests
133
cc7e5122 134.global test_vcnt_vb
135test_vcnt_vb:
a385208c 136 movem.l d2-d7/a2, -(sp)
137 movea.l #0xc00007, a0
138 movea.l #0xc00008, a1
139 movea.l #0xff0000, a2
140 moveq.l #0, d4 /* d4 = count */
141 moveq.l #0, d5 /* d5 = vcnt_expect */
142 /* d6 = old */
143 move.l #1<<(3+16), d7 /* d7 = SR_VB */
1440:
145 btst #3, (a0)
146 beq 0b /* not blanking */
1470:
148 btst #3, (a0)
149 bne 0b /* blanking */
150
151 addq.l #1, a0
1520:
153 tst.b (a0)
154 bne 0b /* not line 0 */
155
156 subq.l #2, a0
157 move.l (a0), d6
158 move.l d6, (a2)+ /* d0 = old */
159###
1600:
161 move.b (a1), d2 /* 8 d2 = vcnt */
162 cmp.b (a1), d2 /* 8 reread for corruption */
163 bne 0b /* 10 on changing vcounter? */
164 cmp.b d2, d5 /* 4 vcnt == vcnt_expect? */
165 beq 0b /* 10 */
166 move.l (a0), d0 /* 12 */
167 tst.b d2 /* 4 */
168 beq 3f
1691:
170 addq.l #1, d4 /* count++ */
171 addq.l #1, d5
172 cmp.b d2, d5
173 bne 2f /* vcnt == vcnt_expect + 1 */
174 move.l d0, d1
175 eor.l d6, d1
176 and.l d7, d1 /* (old ^ val) & vb */
177 bne 2f
178 move.l d0, d6 /* old = val */
179 bra 0b
180
1812: /* vcnt jump or vb change */
182 move.l d6, (a2)+ /* *ram++ = old */
183 move.l d0, (a2)+ /* *ram++ = val */
184 move.b d2, d5 /* vcnt_expect = vcnt */
185 move.l d0, d6 /* old = val */
186 bra 0b
187
1883: /* vcnt == 0 */
189 move.l d0, d1
190 and.l d7, d1
191 bne 1b /* still in VB */
192
193 move.l d0, (a2)+ /* *ram++ = val */
194 move.l d4, (a2)+ /* *ram++ = count */
195
196 movem.l (sp)+, d2-d7/a2
9d39a80e 197 rts
a385208c 198
e71680d5 199.global test_vcnt_loops
200test_vcnt_loops:
201 movem.l d2, -(sp)
202 movea.l #0xc00007, a0
203 movea.l #0xfff000, a1
204 move.b #0xff, d0 /* d0 = current_vcnt */
205 moveq.l #0, d1 /* d1 = loop counter */
206 move.w #315-1, d2 /* d2 = line limit */
2070:
208 btst #3, (a0)
209 beq 0b /* not blanking */
2100:
211 btst #3, (a0)
212 bne 0b /* blanking */
213
214 addq.w #1, a0
2150:
216 addq.w #1, d1 /* 4 */
217 cmp.b (a0), d0 /* 8 vcnt changed? */
218 beq 0b /* 10 */
219
220 move.w d0, (a1)+ /* 8 save */
221 move.w d1, (a1)+
222 move.b (a0), d0 /* 8 new vcnt */
223 moveq.l #0, d1
224 dbra d2, 0b
225
226 movem.l (sp)+, d2
227 rts
228
6c839579 229.global test_hint
230test_hint:
231 move.w d0, -(sp) /* 8 */
232 move.w (0xc00008).l, d0 /* 16 */
233 addq.w #1, (0xf000).w /* 16 */
234 tst.w (0xf002).w /* 12 */
235 bne 0f /* 10 */
236 move.w d0, (0xf002).w /* 12 */
2370:
238 move.w d0, (0xf004).w /* 12 */
239 move.w (sp)+, d0 /* 8 */
8517a6df 240 rte /* 20 114+44 */
6c839579 241.global test_hint_end
242test_hint_end:
243
244.global test_vint
245test_vint:
246 move.w d0, -(sp) /* 8 */
247 move.w (0xc00008).l, d0 /* 16 */
248 addq.w #1, (0xf008).w /* 16 */
249 tst.w (0xf00a).w /* 12 */
250 bne 0f /* 10 */
251 move.w d0, (0xf00a).w /* 12 */
2520:
253 move.w d0, (0xf00c).w /* 12 */
254 move.w (sp)+, d0 /* 8 */
255 rte /* 20 114 */
256.global test_vint_end
257test_vint_end:
258
9d39a80e 259.global x32x_enable
260x32x_enable:
261 movea.l #0xa15100, a0
71b41fdd 262 movea.l #0xa15122, a1
263 move.w #1, (a0) /* ADEN */
264# wait for min(20_sh2_cycles, pll_setup_time)
265# pll time is unclear, icd_mars.prg mentions 10ms which sounds
266# way too much. Hope 40 68k cycles is enough
267 move.w #40/10, d0
2680:
269 dbra d0, 0b
9d39a80e 270 move.w #3, (a0) /* ADEN, nRES */
2710:
71b41fdd 272 move.w #0xffff, d0 /* waste some cycles */
9d39a80e 273 tst.w (a1)
71b41fdd 274 beq 0b /* master BIOS busy */
275
2760: /* for slave, use a limit, as it */
277 tst.w 4(a1) /* won't respond on master error. */
278 dbne d0, 0b /* slave BIOS busy */
279
9d39a80e 280 or.w #1, 6(a0) /* RV */
281 rts
282.global x32x_enable_end
283x32x_enable_end:
284
234c4556 285.global x32x_disable
286x32x_disable:
287 movea.l #0xa15100, a0
288 move.w #1, (a0) /* ADEN (reset sh2) */
289 move.w #0, (a0) /* adapter disable, reset sh2 */
290 move.w #1, d0
2910:
292 dbra d0, 0b
293 move.w #2, (a0) /* nRES - sh2s should see no ADEN and sleep */
294 rts
295.global x32x_disable_end
296x32x_disable_end:
297
06d7984c 298.global test_32x_b_c0
299test_32x_b_c0:
300 ldarg 0, 0, a1
301 ldargw 1, 0, d0
302 jsr (0xc0).l /* move.b d0, (a1); RV=0 */
234c4556 303 bset #0, (0xa15107).l /* RV=1 */
06d7984c 304 rts
305.global test_32x_b_c0_end
306test_32x_b_c0_end:
307
cc7e5122 308# some nastyness from Fatal Rewind
309.global test_h_v_2
310test_h_v_2:
311 move.w #0x2000, sr
312 move.w #0x8014, (0xFFC00004).l
313 move.w #0x8164, (0xFFC00004).l
314 move.w #1, d0
3150:
316 dbra d0, 0b
317 move.w #0x2700, sr
318 rts
319
320.global test_v_h_2
321test_v_h_2:
322 move.w #0x2000, sr
323 movea.l #0xc00004, a0
324 move.w #0x8164, (a0)
325 move.w #0x8144, (a0)
326 move.w #480/2/10-1, d0
3270:
328 dbra d0, 0b
329 move.w #0x8164, (0xFFC00004).l
330 move.w #0x8014, (0xFFC00004).l
331 move.w #0x2700, sr
332 rts
333
334.global test_f_vint
335test_f_vint:
336 move.w (a1), d0
337 rte
338.global test_f_vint_end
339test_f_vint_end:
340
341.global test_f
342test_f:
343 movea.l #0xc00005, a0
344 movea.l #0xc00004, a1
345 move.w #0x2000, sr
3460:
347 btst #3, (a0)
348 bne 0b
3490:
350 btst #3, (a0)
351 beq 0b
352 movem.l d2-d7/a2, -(sp)
353 move.l (a1), d1
354 move.l (a1), d2
355 move.l (a1), d3
356 move.l (a1), d4
357 move.l (a1), d5
358 move.l (a1), d6
359 move.w #0x2700, sr
360 movea.l #0xff0000, a0
361 move.b d0, (a0)+
362 move.b #0, (a0)+
363.macro test_lb_s sr, dr
364 swap \sr
365 move.b \sr, (\dr)+
366 swap \sr
367 move.b \sr, (\dr)+
368.endm
369 test_lb_s d1, a0
370 test_lb_s d2, a0
371 test_lb_s d3, a0
372 test_lb_s d4, a0
373 test_lb_s d5, a0
374 movem.l (sp)+, d2-d7/a2
9d39a80e 375 rts
cc7e5122 376
377.global test_hb
378test_hb:
379 movem.l d2-d7, -(sp)
380 movea.l #0xc00004, a0
381 movea.l #0xc00008, a1
382 moveq.l #1, d0
3830:
384 cmp.b (a1), d0
385 beq 0b
3860:
387 cmp.b (a1), d0
388 bne 0b
389 move.l (a0), d0
390 move.l (a0), d1
391 move.l (a0), d2
392 movea.l #0xff0000, a1
393 movea.l #0xff0000, a1
394 nop
395 nop
396 move.l (a0), d3
397 move.l (a0), d4
398 move.l (a0), d5
399 move.l (a0), d6
400 move.l (a0), d7
401 test_lb_s d0, a1
402 test_lb_s d1, a1
403 test_lb_s d2, a1
404 test_lb_s d3, a1
405 test_lb_s d4, a1
406 test_lb_s d5, a1
407 test_lb_s d6, a1
408 test_lb_s d7, a1
409 movem.l (sp)+, d2-d7
9d39a80e 410 rts
6c839579 411
e71680d5 412.macro ymwrite areg, dreg addr dat
413 move.b \addr, (\areg) /* 12 addr */
414 nbcd d0 /* 6 delay to reach 17 ym cycles (M/7) */
415 move.b \dat, (\dreg) /* 12 data */
416.endm
417
418.global test_ym_stopped_tick
419test_ym_stopped_tick:
420 movem.l a2-a3, -(sp)
421 movea.l #0xa04000, a0
422 movea.l #0xa04001, a1
423 movea.l #0xc00007, a2
424 movea.l #0xfff000, a3
425
426 ymwrite a0, a1, #0x27, #0x30 /* 30 disable, clear */
427 ymwrite a0, a1, #0x26, #0xff /* 30 timer b shortest interval */
428 move.b #0x27, (a0) /* 12 addr prep */
4290:
430 btst #3, (a2)
431 beq 0b /* not blanking */
4320:
433 btst #3, (a2)
434 bne 0b /* blanking */
435
436 addq.l #1, a2
4370:
438 tst.b (a2)
439 bne 0b /* not line 0 - waiting for sequential vcnt */
440
441 move.b #0x0a, (a1) /* 12 start timer b */
442 moveq.l #0, d0
443 moveq.l #2, d1
4440:
445 move.b (a0), d0
446 and.b d1, d0
447 beq 0b
4480:
449# move.w (a2), (a3)+ /* 12 save hvcnt */
450 move.b (a2), d0
451 cmp.b (a2), d0
452 bne 0b
453 move.w d0, (a3)+
454 move.b #0x30, (a1) /* 12 stop b, clear */
455
456 move.w #(1900/10-1), d0 /* waste cycles */
4570:
458 dbra d0, 0b
459 moveq.l #0, d0
460
461 move.w (a0), (a3)+ /* 12 save status */
462 move.b #0x0a, (a1) /* 12 start b */
4630:
464 move.b (a0), d0
465 and.b d1, d0
466 beq 0b
467
4680:
469# move.w (a2), (a3)+ /* 12 save hvcnt */
470 move.b (a2), d1
471 cmp.b (a2), d1
472 bne 0b
473 move.w d1, (a3)+
474 move.w d0, (a3)+ /* 12 save status */
475
476 movem.l (sp)+, a2-a3
477 rts
478
479.global test_ym_ab_sync
480test_ym_ab_sync:
481 movea.l #0xa04000, a0
482 movea.l #0xa04001, a1
483
484 ymwrite a0, a1, #0x27, #0x30 /* 30 disable, clear */
485 ymwrite a0, a1, #0x24, #0xfc /* 30 timer a */
486 ymwrite a0, a1, #0x25, #0x01 /* 30 =15 - why 15? expected 16 */
487 ymwrite a0, a1, #0x26, #0xff /* 30 timer b shortest interval */
488 move.b #0x27, (a0) /* 12 addr prep */
489 nop
490 nop
491
492 move.b #0x0a, (a1) /* 12 start timer b */
493 moveq.l #0, d0
494 moveq.l #2, d1
4950:
496 move.b (a0), d0 /* 8 */
497 and.b d1, d0 /* 4 */
498 beq 0b /* 10|8 */
4990:
500 move.b #0x3f, (a1) /* 12 start a, clear */
438648dc 501 move.w #(1800/10-1), d0 /* waste cycles */
5020:
503 dbra d0, 0b
504
505 ymwrite a0, a1, #0x24, #0x00 /* 30 show that rewriting count */
506 ymwrite a0, a1, #0x25, #0x00 /* 30 does nothing */
507 ymwrite a0, a1, #0x26, #0x00 /* 30 */
508 ymwrite a0, a1, #0x27, #0x0f /* 30 setting already set bits too */
509 moveq.l #0, d0
510 moveq.l #3, d1
e71680d5 5110:
512 move.b (a0), d0
513 and.b d1, d0
514 beq 0b
515 move.b (a0), d0 /* re-read, else very occasionally get 1 */
516 rts
517
ffd4b35c 518# vim:filetype=asmM68k:ts=4:sw=4:expandtab