testpico: 32x reset + other tests
[megadrive.git] / testpico / asmtools.S
1 # Assemble with gas
2 #   --register-prefix-optional --bitwise-or
3 # reminder: d2-d7/a2-a6 are callee-save
4
5 .macro ldarg  arg, stacksz, reg
6     move.l (4 + \arg * 4 + \stacksz)(%sp), \reg
7 .endm
8
9 .macro ldargw arg, stacksz, reg
10     move.w (4 + \arg * 4 + 2 + \stacksz)(%sp), \reg
11 .endm
12
13 .global burn10 /* u16 val */
14 burn10:
15     ldargw      0, 0, d0
16     subq.l      #1, d0
17 0:
18     dbra        d0, 0b      /* 10|14 */
19     rts                     /* 16 */
20
21 .global write16_x16 /* u32 a, u16 count, u16 d */
22 write16_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
30 0:
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
44 #  destroys d1
45 .global get_input
46 get_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
70 .global get_line
71 get_line:
72     movea.l     #0xc00008, a0
73     moveq.l     #0, d0
74 0:
75     move.b      (a0), d0    /*  8 d2 = vcnt */
76     cmp.b       (a0), d0    /*  8 reread for super-rare corruption (torn read) */
77     bne         0b
78     rts
79
80 .global write_and_read1 /* u32 a, u16 d, void *dst */
81 write_and_read1:
82     ldarg       0, 0, a0
83     ldargw      1, 0, d0
84 #ifndef PICO
85     move.w      d0, (a0)
86 #else
87     /* different timing due to extra fetch of offset, */
88     /* less troulesome to emulate */
89     movea.l     a0, a1
90     subq.l      #1, a1
91     move.w      d0, 1(a1)
92 #endif
93     move.l      (a0), d0
94     move.l      (a0), d1
95
96     ldarg       2, 0, a1
97     move.l      d0, (a1)+
98     move.l      d1, (a1)+
99     rts
100
101 .global move_sr /* u16 sr */
102 move_sr:
103     ldargw      0, 0, d0
104     move.w      d0, sr
105     rts
106
107 .global move_sr_and_read /* u16 sr, u32 a */
108 move_sr_and_read:
109     ldargw      0, 0, d0
110     ldarg       1, 0, a0
111     move.w      d0, sr
112     move.w      (a0), d0
113     rts
114
115 .global read_sr
116 read_sr:
117     move.w      sr, d0
118     rts
119
120 .global memcpy_ /* void *dst, const void *src, u16 size */
121 memcpy_:
122     ldarg       0, 0, a0
123     ldarg       1, 0, a1
124     ldargw      2, 0, d0
125     subq.w      #1, d0
126 0:
127     move.b      (a1)+, (a0)+      /* not in a hurry */
128     dbra        d0, 0b
129     rts
130
131 .global memset_ /* void *dst, int d, u16 size */
132 memset_:
133     ldarg       0, 0, a0
134     ldargw      1, 0, d1
135     ldargw      2, 0, d0
136     subq.w      #1, d0
137 0:
138     move.b      d1, (a0)+         /* not in a hurry */
139     dbra        d0, 0b
140     rts
141
142 # tests
143
144 .global test_vcnt_vb
145 test_vcnt_vb:
146     movem.l     d2-d7/a2, -(sp)
147     movea.l     #0xc00007, a0
148     movea.l     #0xc00008, a1
149     movea.l     #0xff0000, a2
150     moveq.l     #0, d4          /* d4 = count */
151     moveq.l     #0, d5          /* d5 = vcnt_expect */
152                                 /* d6 = old */
153     move.l      #1<<(3+16), d7  /* d7 = SR_VB */
154 0:
155     btst        #3, (a0)
156     beq         0b          /* not blanking */
157 0:
158     btst        #3, (a0)
159     bne         0b          /* blanking */
160
161     addq.l      #1, a0
162 0:
163     tst.b       (a0)
164     bne         0b          /* not line 0 */
165
166     subq.l      #2, a0
167     move.l      (a0), d6
168     move.l      d6, (a2)+   /* d0 = old */
169 ###
170 0:
171     move.b      (a1), d2    /*  8 d2 = vcnt */
172     cmp.b       (a1), d2    /*  8 reread for corruption */
173     bne 0b                  /* 10 on changing vcounter? */
174     cmp.b       d2, d5      /*  4 vcnt == vcnt_expect? */
175     beq         0b          /* 10 */
176     move.l      (a0), d0    /* 12 */
177     tst.b       d2          /*  4 */
178     beq         3f
179 1:
180     addq.l      #1, d4      /* count++ */
181     addq.l      #1, d5
182     cmp.b       d2, d5
183     bne         2f          /* vcnt == vcnt_expect + 1 */
184     move.l      d0, d1
185     eor.l       d6, d1
186     and.l       d7, d1      /* (old ^ val) & vb */
187     bne         2f
188     move.l      d0, d6      /* old = val */
189     bra         0b
190
191 2: /* vcnt jump or vb change */
192     move.l      d6, (a2)+   /* *ram++ = old */
193     move.l      d0, (a2)+   /* *ram++ = val */
194     move.b      d2, d5      /* vcnt_expect = vcnt */
195     move.l      d0, d6      /* old = val */
196     bra         0b
197
198 3: /* vcnt == 0 */
199     move.l      d0, d1
200     and.l       d7, d1
201     bne         1b          /* still in VB */
202
203     move.l      d0, (a2)+   /* *ram++ = val */
204     move.l      d4, (a2)+   /* *ram++ = count */
205
206     movem.l     (sp)+, d2-d7/a2
207     rts
208
209 .global test_vcnt_loops
210 test_vcnt_loops:
211     movem.l     d2, -(sp)
212     movea.l     #0xc00007, a0
213     movea.l     #0xfff000, a1
214     move.b      #0xff, d0       /* d0 = current_vcnt */
215     moveq.l     #0, d1          /* d1 = loop counter */
216     move.w      #315-1, d2      /* d2 = line limit */
217 0:
218     btst        #3, (a0)
219     beq         0b          /* not blanking */
220 0:
221     btst        #3, (a0)
222     bne         0b          /* blanking */
223
224     addq.w      #1, a0
225 0:
226     addq.w      #1, d1      /*  4 */
227     cmp.b       (a0), d0    /*  8 vcnt changed? */
228     beq         0b          /* 10 */
229
230     move.w      d0, (a1)+   /*  8 save */
231     move.w      d1, (a1)+
232     move.b      (a0), d0    /*  8 new vcnt */
233     moveq.l     #0, d1
234     dbra        d2, 0b
235
236     movem.l     (sp)+, d2
237     rts
238
239 .global test_hint
240 test_hint:
241     move.w      d0, -(sp)         /*  8 */
242     move.w      (0xc00008).l, d0  /* 16 */
243     addq.w      #1, (0xf000).w    /* 16 */
244     tst.w       (0xf002).w        /* 12 */
245     bne         0f                /* 10 */
246     move.w      d0, (0xf002).w    /* 12 */
247 0:
248     move.w      d0, (0xf004).w    /* 12 */
249     move.w      (sp)+, d0         /*  8 */
250     rte                           /* 20 114+44 */
251 .global test_hint_end
252 test_hint_end:
253
254 .global test_vint
255 test_vint:
256     move.w      d0, -(sp)         /*  8 */
257     move.w      (0xc00008).l, d0  /* 16 */
258     addq.w      #1, (0xf008).w    /* 16 */
259     tst.w       (0xf00a).w        /* 12 */
260     bne         0f                /* 10 */
261     move.w      d0, (0xf00a).w    /* 12 */
262 0:
263     move.w      d0, (0xf00c).w    /* 12 */
264     move.w      (sp)+, d0         /*  8 */
265     rte                           /* 20 114 */
266 .global test_vint_end
267 test_vint_end:
268
269 .global x32x_enable
270 x32x_enable:
271     movea.l     #0xa15100, a0
272     movea.l     #0xa15122, a1
273     move.w      #1, (a0)          /* ADEN */
274 # wait for min(20_sh2_cycles, pll_setup_time)
275 # pll time is unclear, icd_mars.prg mentions 10ms which sounds
276 # way too much. Hope 40 68k cycles is enough
277     move.w      #40/10, d0
278 0:
279     dbra        d0, 0b
280     move.w      #3, (a0)          /* ADEN, nRES */
281 0:
282     move.w      #0xffff, d0       /* waste some cycles */
283     tst.w       (a1)
284     beq         0b                /* master BIOS busy */
285
286 0:                                /* for slave, use a limit, as it */
287     tst.w       4(a1)             /* won't respond on master error. */
288     dbne        d0, 0b            /* slave BIOS busy */
289
290     or.w        #1, 6(a0)         /* RV */
291     rts
292 .global x32x_enable_end
293 x32x_enable_end:
294
295 .global x32x_disable
296 x32x_disable:
297     movea.l     #0xa15100, a0
298     move.w      #1, (a0)          /* ADEN (reset sh2) */
299     move.w      #0, (a0)          /* adapter disable, reset sh2 */
300     move.w      #1, d0
301 0:
302     dbra        d0, 0b
303     move.w      #2, (a0)          /* nRES - sh2s should see no ADEN and sleep */
304     rts
305 .global x32x_disable_end
306 x32x_disable_end:
307
308 .global test_32x_b_c0
309 test_32x_b_c0:
310     ldarg       0, 0, a1
311     ldargw      1, 0, d0
312     jsr         (0xc0).l          /* move.b d0, (a1); RV=0 */
313     bset        #0, (0xa15107).l  /* RV=1 */
314     rts
315 .global test_32x_b_c0_end
316 test_32x_b_c0_end:
317
318 # some nastyness from Fatal Rewind
319 .global test_h_v_2
320 test_h_v_2:
321     move.w      #0x2000, sr
322     move.w      #0x8014, (0xFFC00004).l
323     move.w      #0x8164, (0xFFC00004).l
324     move.w      #1, d0
325 0:
326     dbra        d0, 0b
327     move.w      #0x2700, sr
328     rts
329
330 .global test_v_h_2
331 test_v_h_2:
332     move.w      #0x2000, sr
333     movea.l     #0xc00004, a0
334     move.w      #0x8164, (a0)
335     move.w      #0x8144, (a0)
336     move.w      #480/2/10-1, d0
337 0:
338     dbra        d0, 0b
339     move.w      #0x8164, (0xFFC00004).l
340     move.w      #0x8014, (0xFFC00004).l
341     move.w      #0x2700, sr
342     rts
343
344 .global test_f_vint
345 test_f_vint:
346     move.w      (a1), d0
347     rte
348 .global test_f_vint_end
349 test_f_vint_end:
350
351 .global test_f
352 test_f:
353     movea.l     #0xc00005, a0
354     movea.l     #0xc00004, a1
355     move.w      #0x2000, sr
356 0:
357     btst        #3, (a0)
358     bne         0b
359 0:
360     btst        #3, (a0)
361     beq         0b
362     movem.l     d2-d7/a2, -(sp)
363     move.l      (a1), d1
364     move.l      (a1), d2
365     move.l      (a1), d3
366     move.l      (a1), d4
367     move.l      (a1), d5
368     move.l      (a1), d6
369     move.w      #0x2700, sr
370     movea.l     #0xff0000, a0
371     move.b      d0, (a0)+
372     move.b      #0, (a0)+
373 .macro test_lb_s sr, dr
374     swap        \sr
375     move.b      \sr, (\dr)+
376     swap        \sr
377     move.b      \sr, (\dr)+
378 .endm
379     test_lb_s   d1, a0
380     test_lb_s   d2, a0
381     test_lb_s   d3, a0
382     test_lb_s   d4, a0
383     test_lb_s   d5, a0
384     movem.l     (sp)+, d2-d7/a2
385     rts
386
387 .global test_hb
388 test_hb:
389     movem.l     d2-d7, -(sp)
390     movea.l     #0xc00004, a0
391     movea.l     #0xc00008, a1
392     moveq.l     #1, d0
393 0:
394     cmp.b       (a1), d0
395     beq         0b
396 0:
397     cmp.b       (a1), d0
398     bne         0b
399     move.l      (a0), d0
400     move.l      (a0), d1
401     move.l      (a0), d2
402     movea.l     #0xff0000, a1
403     movea.l     #0xff0000, a1
404     nop
405     nop
406     move.l      (a0), d3
407     move.l      (a0), d4
408     move.l      (a0), d5
409     move.l      (a0), d6
410     move.l      (a0), d7
411     test_lb_s   d0, a1
412     test_lb_s   d1, a1
413     test_lb_s   d2, a1
414     test_lb_s   d3, a1
415     test_lb_s   d4, a1
416     test_lb_s   d5, a1
417     test_lb_s   d6, a1
418     test_lb_s   d7, a1
419     movem.l     (sp)+, d2-d7
420     rts
421
422 .macro ymwrite  areg, dreg addr dat
423     move.b      \addr, (\areg) /* 12 addr */
424     nbcd        d0             /*  6 delay to reach 17 ym cycles (M/7) */
425     move.b      \dat, (\dreg)  /* 12 data */
426 .endm
427
428 .global test_ym_stopped_tick
429 test_ym_stopped_tick:
430     movem.l     a2-a3, -(sp)
431     movea.l     #0xa04000, a0
432     movea.l     #0xa04001, a1
433     movea.l     #0xc00007, a2
434     movea.l     #0xfff000, a3
435
436     ymwrite     a0, a1, #0x27, #0x30  /* 30 disable, clear */
437     ymwrite     a0, a1, #0x26, #0xff  /* 30 timer b shortest interval */
438     move.b      #0x27, (a0)           /* 12 addr prep */
439 0:
440     btst        #3, (a2)
441     beq         0b                    /* not blanking */
442 0:
443     btst        #3, (a2)
444     bne         0b                    /* blanking */
445
446     addq.l      #1, a2
447 0:
448     tst.b       (a2)
449     bne         0b                    /* not line 0 - waiting for sequential vcnt */
450
451     move.b      #0x0a, (a1)           /* 12 start timer b  */
452     moveq.l     #0, d0
453     moveq.l     #2, d1
454 0:
455     move.b      (a0), d0
456     and.b       d1, d0
457     beq         0b
458 0:
459 #    move.w      (a2), (a3)+           /* 12 save hvcnt */
460     move.b      (a2), d0
461     cmp.b       (a2), d0
462     bne         0b
463     move.w      d0, (a3)+
464     move.b      #0x30, (a1)           /* 12 stop b, clear  */
465
466     move.w      #(1900/10-1), d0      /* waste cycles */
467 0:
468     dbra        d0, 0b
469     moveq.l     #0, d0
470
471     move.w      (a0), (a3)+           /* 12 save status */
472     move.b      #0x0a, (a1)           /* 12 start b  */
473 0:
474     move.b      (a0), d0
475     and.b       d1, d0
476     beq         0b
477
478 0:
479 #    move.w      (a2), (a3)+           /* 12 save hvcnt */
480     move.b      (a2), d1
481     cmp.b       (a2), d1
482     bne         0b
483     move.w      d1, (a3)+
484     move.w      d0, (a3)+             /* 12 save status */
485
486     movem.l     (sp)+, a2-a3
487     rts
488
489 .global test_ym_ab_sync
490 test_ym_ab_sync:
491     movea.l     #0xa04000, a0
492     movea.l     #0xa04001, a1
493
494     ymwrite     a0, a1, #0x27, #0x30  /* 30 disable, clear */
495     ymwrite     a0, a1, #0x24, #0xfc  /* 30 timer a */
496     ymwrite     a0, a1, #0x25, #0x01  /* 30  =15 */
497     ymwrite     a0, a1, #0x26, #0xff  /* 30 timer b shortest interval */
498     move.b      #0x27, (a0)           /* 12 addr prep */
499     nop
500     nop
501
502     move.b      #0x0a, (a1)           /* 12 start timer b  */
503     moveq.l     #0, d0
504     moveq.l     #2, d1
505 0:
506     move.b      (a0), d0              /*  8 */
507     and.b       d1, d0                /*  4 */
508     beq         0b                    /* 10|8 */
509
510     move.b      #0x3f, (a1)           /* 12 start a, clear  */
511
512     move.w      #(488/10), d0         /* waste cycles */
513 0:  dbra        d0, 0b
514
515     ymwrite     a0, a1, #0x24, #0xf0  /* 30 show that rewriting count */
516     ymwrite     a0, a1, #0x25, #0x00  /* 30 does nothing until timer expires */
517
518     move.w      #(488*2/10), d0       /* waste cycles */
519 0:  dbra        d0, 0b
520
521     ymwrite     a0, a1, #0x26, #0xfc  /* 30 same for timer b */
522     ymwrite     a0, a1, #0x27, #0x0f  /* 30 setting already set bits too  */
523     moveq.l     #0, d0
524     moveq.l     #3, d1
525 0:
526     move.b      (a0), d0
527     and.b       d1, d0
528     beq         0b
529     move.b      (a0), d0              /* re-read, else very occasionally get 1 */
530     rts
531
532 .global test_ym_ab_sync2
533 test_ym_ab_sync2:
534     movea.l     #0xa04000, a0
535     movea.l     #0xa04001, a1
536
537     move.b      #0x0f, (a1)           /* 12 enable  */
538     moveq.l     #0, d0
539     moveq.l     #3, d1
540     nop                               /*  4 need ~12c to clear */
541 0:
542     move.b      (a0), d0              /*  8 */
543     and.b       d1, d0                /*  4 */
544     beq         0b                    /* 10|8 */
545     move.b      (a0), d0              /* re-read */
546     move.b      #0x3c, (a1)           /* 12 clear, disable  */
547     rts
548
549 # vim:filetype=asmM68k:ts=4:sw=4:expandtab