testpico: check more settable bits
[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      #0, 6(a0)         /* RV=0 */
304     move.w      #1, (a0)          /* ADEN (reset sh2) */
305     move.w      #0, (a0)          /* adapter disable, reset sh2 */
306     move.w      #1, d0
307 0:
308     dbra        d0, 0b
309     move.w      #2, (a0)          /* nRES - sh2s should see no ADEN and sleep */
310     rts
311 .global x32x_disable_end
312 x32x_disable_end:
313
314 .global test_32x_b_c0
315 test_32x_b_c0:
316     ldarg       0, 0, a1
317     ldargw      1, 0, d0
318     jsr         (0xc0).l          /* move.b d0, (a1); RV=0 */
319     bset        #0, (0xa15107).l  /* RV=1 */
320     rts
321 .global test_32x_b_c0_end
322 test_32x_b_c0_end:
323
324 # some nastyness from Fatal Rewind
325 .global test_h_v_2
326 test_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
331 0:
332     dbra        d0, 0b
333     move.w      #0x2700, sr
334     rts
335
336 .global test_v_h_2
337 test_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
343 0:
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
351 test_f_vint:
352     move.w      (a1), d0
353     rte
354 .global test_f_vint_end
355 test_f_vint_end:
356
357 .global test_f
358 test_f:
359     movea.l     #0xc00005, a0
360     movea.l     #0xc00004, a1
361     move.w      #0x2000, sr
362 0:
363     btst        #3, (a0)
364     bne         0b
365 0:
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
391     rts
392
393 .global test_hb
394 test_hb:
395     movem.l     d2-d7, -(sp)
396     movea.l     #0xc00004, a0
397     movea.l     #0xc00008, a1
398     moveq.l     #1, d0
399 0:
400     cmp.b       (a1), d0
401     beq         0b
402 0:
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
426     rts
427
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
435 test_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 */
445 0:
446     btst        #3, (a2)
447     beq         0b                    /* not blanking */
448 0:
449     btst        #3, (a2)
450     bne         0b                    /* blanking */
451
452     addq.l      #1, a2
453 0:
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
460 0:
461     move.b      (a0), d0
462     and.b       d1, d0
463     beq         0b
464 0:
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 */
473 0:
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  */
479 0:
480     move.b      (a0), d0
481     and.b       d1, d0
482     beq         0b
483
484 0:
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
496 test_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 */
502     ymwrite     a0, a1, #0x25, #0x01  /* 30  =15 */
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
511 0:
512     move.b      (a0), d0              /*  8 */
513     and.b       d1, d0                /*  4 */
514     beq         0b                    /* 10|8 */
515
516     move.b      #0x3f, (a1)           /* 12 start a, clear  */
517
518     move.w      #(488/10), d0         /* waste cycles */
519 0:  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 */
525 0:  dbra        d0, 0b
526
527     ymwrite     a0, a1, #0x26, #0xfc  /* 30 same for timer b */
528     ymwrite     a0, a1, #0x27, #0x0f  /* 30 setting already set bits too  */
529     moveq.l     #0, d0
530     moveq.l     #3, d1
531 0:
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
538 .global test_ym_ab_sync2
539 test_ym_ab_sync2:
540     movea.l     #0xa04000, a0
541     movea.l     #0xa04001, a1
542
543     move.b      #0x0f, (a1)           /* 12 enable  */
544     moveq.l     #0, d0
545     moveq.l     #3, d1
546     nop                               /*  4 need ~12c to clear */
547 0:
548     move.b      (a0), d0              /*  8 */
549     and.b       d1, d0                /*  4 */
550     beq         0b                    /* 10|8 */
551     move.b      (a0), d0              /* re-read */
552     move.b      #0x3c, (a1)           /* 12 clear, disable  */
553     rts
554
555 .global x32x_switch_rv
556 x32x_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
565 0:
566     move.w      #1, (a0)
567     and.l       #0x07ffff, d1
568 1:
569     movea.l     d1, a1
570     jmp         (a1)
571 .global x32x_switch_rv_end
572 x32x_switch_rv_end:
573
574 # vim:filetype=asmM68k:ts=4:sw=4:expandtab