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 # args are always 4 bytes in stack, caller restores sp
10 .macro ldargw arg, stacksz, reg
11     move.w (4 + \arg * 4 + 2 + \stacksz)(%sp), \reg
12 .endm
13
14 .global burn10 /* u16 val */
15 burn10:
16     ldargw      0, 0, d0
17     subq.l      #1, d0
18 0:
19     dbra        d0, 0b      /* 10|14 */
20     rts                     /* 16 */
21
22 .global write16_x16 /* u32 a, u16 count, u16 d */
23 write16_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
31 0:
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
45 #  destroys d1
46 .global get_input
47 get_input:
48 .global get_input_s
49 get_input_s:
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
72 .global get_input_end
73 get_input_end:
74
75 .global get_line
76 get_line:
77     movea.l     #0xc00008, a0
78     moveq.l     #0, d0
79 0:
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
85 .global write_and_read1 /* u32 a, u16 d, void *dst */
86 write_and_read1:
87     ldarg       0, 0, a0
88     ldargw      1, 0, d0
89 #ifndef PICO
90     move.w      d0, (a0)
91 #else
92     /* different timing due to extra fetch of offset, */
93     /* less troulesome to emulate */
94     movea.l     a0, a1
95     subq.l      #1, a1
96     move.w      d0, 1(a1)
97 #endif
98     move.l      (a0), d0
99     move.l      (a0), d1
100
101     ldarg       2, 0, a1
102     move.l      d0, (a1)+
103     move.l      d1, (a1)+
104     rts
105
106 .global move_sr /* u16 sr */
107 move_sr:
108     ldargw      0, 0, d0
109     move.w      d0, sr
110     rts
111
112 .global move_sr_and_read /* u16 sr, u32 a */
113 move_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
120 .global read_sr
121 read_sr:
122     move.w      sr, d0
123     rts
124
125 .global memcpy_ /* void *dst, const void *src, u16 size */
126 memcpy_:
127     ldarg       0, 0, a0
128     ldarg       1, 0, a1
129     ldargw      2, 0, d0
130     subq.w      #1, d0
131 0:
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 */
137 memset_:
138     ldarg       0, 0, a0
139     ldargw      1, 0, d1
140     ldargw      2, 0, d0
141     subq.w      #1, d0
142 0:
143     move.b      d1, (a0)+         /* not in a hurry */
144     dbra        d0, 0b
145     rts
146
147 # tests
148
149 .global test_vcnt_vb
150 test_vcnt_vb:
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 */
159 0:
160     btst        #3, (a0)
161     beq         0b          /* not blanking */
162 0:
163     btst        #3, (a0)
164     bne         0b          /* blanking */
165
166     addq.l      #1, a0
167 0:
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 ###
175 0:
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
184 1:
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
196 2: /* 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
203 3: /* 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
212     rts
213
214 .global test_vcnt_loops
215 test_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 */
222 0:
223     btst        #3, (a0)
224     beq         0b          /* not blanking */
225 0:
226     btst        #3, (a0)
227     bne         0b          /* blanking */
228
229     addq.w      #1, a0
230 0:
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
244 .global test_hint
245 test_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 */
252 0:
253     move.w      d0, (0xf004).w    /* 12 */
254     move.w      (sp)+, d0         /*  8 */
255     rte                           /* 20 114+44 */
256 .global test_hint_end
257 test_hint_end:
258
259 .global test_vint
260 test_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 */
267 0:
268     move.w      d0, (0xf00c).w    /* 12 */
269     move.w      (sp)+, d0         /*  8 */
270     rte                           /* 20 114 */
271 .global test_vint_end
272 test_vint_end:
273
274 .global x32x_enable
275 x32x_enable:
276     movea.l     #0xa15100, a0
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
283 0:
284     dbra        d0, 0b
285     move.w      #3, (a0)          /* ADEN, nRES */
286 0:
287     move.w      #0xffff, d0       /* waste some cycles */
288     tst.w       (a1)
289     beq         0b                /* master BIOS busy */
290
291 0:                                /* 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
295     or.w        #1, 6(a0)         /* RV */
296     rts
297 .global x32x_enable_end
298 x32x_enable_end:
299
300 .global x32x_disable
301 x32x_disable:
302     movea.l     #0xa15100, a0
303     move.w      #1, (a0)          /* ADEN (reset sh2) */
304     move.w      #0, (a0)          /* adapter disable, reset sh2 */
305     move.w      #1, d0
306 0:
307     dbra        d0, 0b
308     move.w      #2, (a0)          /* nRES - sh2s should see no ADEN and sleep */
309     rts
310 .global x32x_disable_end
311 x32x_disable_end:
312
313 .global test_32x_b_c0
314 test_32x_b_c0:
315     ldarg       0, 0, a1
316     ldargw      1, 0, d0
317     jsr         (0xc0).l          /* move.b d0, (a1); RV=0 */
318     bset        #0, (0xa15107).l  /* RV=1 */
319     rts
320 .global test_32x_b_c0_end
321 test_32x_b_c0_end:
322
323 # some nastyness from Fatal Rewind
324 .global test_h_v_2
325 test_h_v_2:
326     move.w      #0x2000, sr
327     move.w      #0x8014, (0xFFC00004).l
328     move.w      #0x8164, (0xFFC00004).l
329     move.w      #1, d0
330 0:
331     dbra        d0, 0b
332     move.w      #0x2700, sr
333     rts
334
335 .global test_v_h_2
336 test_v_h_2:
337     move.w      #0x2000, sr
338     movea.l     #0xc00004, a0
339     move.w      #0x8164, (a0)
340     move.w      #0x8144, (a0)
341     move.w      #480/2/10-1, d0
342 0:
343     dbra        d0, 0b
344     move.w      #0x8164, (0xFFC00004).l
345     move.w      #0x8014, (0xFFC00004).l
346     move.w      #0x2700, sr
347     rts
348
349 .global test_f_vint
350 test_f_vint:
351     move.w      (a1), d0
352     rte
353 .global test_f_vint_end
354 test_f_vint_end:
355
356 .global test_f
357 test_f:
358     movea.l     #0xc00005, a0
359     movea.l     #0xc00004, a1
360     move.w      #0x2000, sr
361 0:
362     btst        #3, (a0)
363     bne         0b
364 0:
365     btst        #3, (a0)
366     beq         0b
367     movem.l     d2-d7/a2, -(sp)
368     move.l      (a1), d1
369     move.l      (a1), d2
370     move.l      (a1), d3
371     move.l      (a1), d4
372     move.l      (a1), d5
373     move.l      (a1), d6
374     move.w      #0x2700, sr
375     movea.l     #0xff0000, a0
376     move.b      d0, (a0)+
377     move.b      #0, (a0)+
378 .macro test_lb_s sr, dr
379     swap        \sr
380     move.b      \sr, (\dr)+
381     swap        \sr
382     move.b      \sr, (\dr)+
383 .endm
384     test_lb_s   d1, a0
385     test_lb_s   d2, a0
386     test_lb_s   d3, a0
387     test_lb_s   d4, a0
388     test_lb_s   d5, a0
389     movem.l     (sp)+, d2-d7/a2
390     rts
391
392 .global test_hb
393 test_hb:
394     movem.l     d2-d7, -(sp)
395     movea.l     #0xc00004, a0
396     movea.l     #0xc00008, a1
397     moveq.l     #1, d0
398 0:
399     cmp.b       (a1), d0
400     beq         0b
401 0:
402     cmp.b       (a1), d0
403     bne         0b
404     move.l      (a0), d0
405     move.l      (a0), d1
406     move.l      (a0), d2
407     movea.l     #0xff0000, a1
408     movea.l     #0xff0000, a1
409     nop
410     nop
411     move.l      (a0), d3
412     move.l      (a0), d4
413     move.l      (a0), d5
414     move.l      (a0), d6
415     move.l      (a0), d7
416     test_lb_s   d0, a1
417     test_lb_s   d1, a1
418     test_lb_s   d2, a1
419     test_lb_s   d3, a1
420     test_lb_s   d4, a1
421     test_lb_s   d5, a1
422     test_lb_s   d6, a1
423     test_lb_s   d7, a1
424     movem.l     (sp)+, d2-d7
425     rts
426
427 .macro ymwrite  areg, dreg addr dat
428     move.b      \addr, (\areg) /* 12 addr */
429     nbcd        d0             /*  6 delay to reach 17 ym cycles (M/7) */
430     move.b      \dat, (\dreg)  /* 12 data */
431 .endm
432
433 .global test_ym_stopped_tick
434 test_ym_stopped_tick:
435     movem.l     a2-a3, -(sp)
436     movea.l     #0xa04000, a0
437     movea.l     #0xa04001, a1
438     movea.l     #0xc00007, a2
439     movea.l     #0xfff000, a3
440
441     ymwrite     a0, a1, #0x27, #0x30  /* 30 disable, clear */
442     ymwrite     a0, a1, #0x26, #0xff  /* 30 timer b shortest interval */
443     move.b      #0x27, (a0)           /* 12 addr prep */
444 0:
445     btst        #3, (a2)
446     beq         0b                    /* not blanking */
447 0:
448     btst        #3, (a2)
449     bne         0b                    /* blanking */
450
451     addq.l      #1, a2
452 0:
453     tst.b       (a2)
454     bne         0b                    /* not line 0 - waiting for sequential vcnt */
455
456     move.b      #0x0a, (a1)           /* 12 start timer b  */
457     moveq.l     #0, d0
458     moveq.l     #2, d1
459 0:
460     move.b      (a0), d0
461     and.b       d1, d0
462     beq         0b
463 0:
464 #    move.w      (a2), (a3)+           /* 12 save hvcnt */
465     move.b      (a2), d0
466     cmp.b       (a2), d0
467     bne         0b
468     move.w      d0, (a3)+
469     move.b      #0x30, (a1)           /* 12 stop b, clear  */
470
471     move.w      #(1900/10-1), d0      /* waste cycles */
472 0:
473     dbra        d0, 0b
474     moveq.l     #0, d0
475
476     move.w      (a0), (a3)+           /* 12 save status */
477     move.b      #0x0a, (a1)           /* 12 start b  */
478 0:
479     move.b      (a0), d0
480     and.b       d1, d0
481     beq         0b
482
483 0:
484 #    move.w      (a2), (a3)+           /* 12 save hvcnt */
485     move.b      (a2), d1
486     cmp.b       (a2), d1
487     bne         0b
488     move.w      d1, (a3)+
489     move.w      d0, (a3)+             /* 12 save status */
490
491     movem.l     (sp)+, a2-a3
492     rts
493
494 .global test_ym_ab_sync
495 test_ym_ab_sync:
496     movea.l     #0xa04000, a0
497     movea.l     #0xa04001, a1
498
499     ymwrite     a0, a1, #0x27, #0x30  /* 30 disable, clear */
500     ymwrite     a0, a1, #0x24, #0xfc  /* 30 timer a */
501     ymwrite     a0, a1, #0x25, #0x01  /* 30  =15 */
502     ymwrite     a0, a1, #0x26, #0xff  /* 30 timer b shortest interval */
503     move.b      #0x27, (a0)           /* 12 addr prep */
504     nop
505     nop
506
507     move.b      #0x0a, (a1)           /* 12 start timer b  */
508     moveq.l     #0, d0
509     moveq.l     #2, d1
510 0:
511     move.b      (a0), d0              /*  8 */
512     and.b       d1, d0                /*  4 */
513     beq         0b                    /* 10|8 */
514
515     move.b      #0x3f, (a1)           /* 12 start a, clear  */
516
517     move.w      #(488/10), d0         /* waste cycles */
518 0:  dbra        d0, 0b
519
520     ymwrite     a0, a1, #0x24, #0xf0  /* 30 show that rewriting count */
521     ymwrite     a0, a1, #0x25, #0x00  /* 30 does nothing until timer expires */
522
523     move.w      #(488*2/10), d0       /* waste cycles */
524 0:  dbra        d0, 0b
525
526     ymwrite     a0, a1, #0x26, #0xfc  /* 30 same for timer b */
527     ymwrite     a0, a1, #0x27, #0x0f  /* 30 setting already set bits too  */
528     moveq.l     #0, d0
529     moveq.l     #3, d1
530 0:
531     move.b      (a0), d0
532     and.b       d1, d0
533     beq         0b
534     move.b      (a0), d0              /* re-read, else very occasionally get 1 */
535     rts
536
537 .global test_ym_ab_sync2
538 test_ym_ab_sync2:
539     movea.l     #0xa04000, a0
540     movea.l     #0xa04001, a1
541
542     move.b      #0x0f, (a1)           /* 12 enable  */
543     moveq.l     #0, d0
544     moveq.l     #3, d1
545     nop                               /*  4 need ~12c to clear */
546 0:
547     move.b      (a0), d0              /*  8 */
548     and.b       d1, d0                /*  4 */
549     beq         0b                    /* 10|8 */
550     move.b      (a0), d0              /* re-read */
551     move.b      #0x3c, (a1)           /* 12 clear, disable  */
552     rts
553
554 .global x32x_switch_rv
555 x32x_switch_rv:
556     ldargw      0, 0, d0
557     move.l      (sp)+, d1
558     movea.l     #0xa15106, a0
559     btst        #0, d0
560     bne         0f
561     move.w      #0, (a0)
562     or.l        #0x880000, d1
563     bra         1f
564 0:
565     move.w      #1, (a0)
566     and.l       #0x07ffff, d1
567 1:
568     movea.l     d1, a1
569     jmp         (a1)
570 .global x32x_switch_rv_end
571 x32x_switch_rv_end:
572
573 # vim:filetype=asmM68k:ts=4:sw=4:expandtab