807ac9a99ed0b01584450590f047bdcd4c7c1636
[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     ldarg       0, 0, d0
16     subq.l      #1, d0
17 0:
18     dbra        d0, 0b
19     rts
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 write_and_read1 /* u32 a, u16 d, void *dst */
71 write_and_read1:
72     ldarg       0, 0, a0
73     ldargw      1, 0, d0
74 #ifndef PICO
75     move.w      d0, (a0)
76 #else
77     /* different timing due to extra fetch of offset, */
78     /* less troulesome to emulate */
79     movea.l     a0, a1
80     subq.l      #1, a1
81     move.w      d0, 1(a1)
82 #endif
83     move.l      (a0), d0
84     move.l      (a0), d1
85
86     ldarg       2, 0, a1
87     move.l      d0, (a1)+
88     move.l      d1, (a1)+
89     rts
90
91 .global move_sr /* u16 sr */
92 move_sr:
93     ldargw      0, 0, d0
94     move.w      d0, sr
95     rts
96
97 .global move_sr_and_read /* u16 sr, u32 a */
98 move_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
105 .global read_sr
106 read_sr:
107     move.w      sr, d0
108     rts
109
110 .global memcpy_ /* void *dst, const void *src, u16 size */
111 memcpy_:
112     ldarg       0, 0, a0
113     ldarg       1, 0, a1
114     ldargw      2, 0, d0
115     subq.w      #1, d0
116 0:
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 */
122 memset_:
123     ldarg       0, 0, a0
124     ldargw      1, 0, d1
125     ldargw      2, 0, d0
126     subq.w      #1, d0
127 0:
128     move.b      d1, (a0)+         /* not in a hurry */
129     dbra        d0, 0b
130     rts
131
132 # tests
133
134 .global test_vcnt_vb
135 test_vcnt_vb:
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 */
144 0:
145     btst        #3, (a0)
146     beq         0b          /* not blanking */
147 0:
148     btst        #3, (a0)
149     bne         0b          /* blanking */
150
151     addq.l      #1, a0
152 0:
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 ###
160 0:
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
169 1:
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
181 2: /* 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
188 3: /* 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
197     rts
198
199 .global test_vcnt_loops
200 test_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 */
207 0:
208     btst        #3, (a0)
209     beq         0b          /* not blanking */
210 0:
211     btst        #3, (a0)
212     bne         0b          /* blanking */
213
214     addq.w      #1, a0
215 0:
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
229 .global test_hint
230 test_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 */
237 0:
238     move.w      d0, (0xf004).w    /* 12 */
239     move.w      (sp)+, d0         /*  8 */
240     rte                           /* 20 114+44 */
241 .global test_hint_end
242 test_hint_end:
243
244 .global test_vint
245 test_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 */
252 0:
253     move.w      d0, (0xf00c).w    /* 12 */
254     move.w      (sp)+, d0         /*  8 */
255     rte                           /* 20 114 */
256 .global test_vint_end
257 test_vint_end:
258
259 .global x32x_enable
260 x32x_enable:
261     movea.l     #0xa15100, a0
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
268 0:
269     dbra        d0, 0b
270     move.w      #3, (a0)          /* ADEN, nRES */
271 0:
272     move.w      #0xffff, d0       /* waste some cycles */
273     tst.w       (a1)
274     beq         0b                /* master BIOS busy */
275
276 0:                                /* 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
280     or.w        #1, 6(a0)         /* RV */
281     rts
282 .global x32x_enable_end
283 x32x_enable_end:
284
285 .global x32x_disable
286 x32x_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
291 0:
292     dbra        d0, 0b
293     move.w      #2, (a0)          /* nRES - sh2s should see no ADEN and sleep */
294     rts
295 .global x32x_disable_end
296 x32x_disable_end:
297
298 .global test_32x_b_c0
299 test_32x_b_c0:
300     ldarg       0, 0, a1
301     ldargw      1, 0, d0
302     jsr         (0xc0).l          /* move.b d0, (a1); RV=0 */
303     bset        #0, (0xa15107).l  /* RV=1 */
304     rts
305 .global test_32x_b_c0_end
306 test_32x_b_c0_end:
307
308 # some nastyness from Fatal Rewind
309 .global test_h_v_2
310 test_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
315 0:
316     dbra        d0, 0b
317     move.w      #0x2700, sr
318     rts
319
320 .global test_v_h_2
321 test_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
327 0:
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
335 test_f_vint:
336     move.w      (a1), d0
337     rte
338 .global test_f_vint_end
339 test_f_vint_end:
340
341 .global test_f
342 test_f:
343     movea.l     #0xc00005, a0
344     movea.l     #0xc00004, a1
345     move.w      #0x2000, sr
346 0:
347     btst        #3, (a0)
348     bne         0b
349 0:
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
375     rts
376
377 .global test_hb
378 test_hb:
379     movem.l     d2-d7, -(sp)
380     movea.l     #0xc00004, a0
381     movea.l     #0xc00008, a1
382     moveq.l     #1, d0
383 0:
384     cmp.b       (a1), d0
385     beq         0b
386 0:
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
410     rts
411
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
419 test_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 */
429 0:
430     btst        #3, (a2)
431     beq         0b                    /* not blanking */
432 0:
433     btst        #3, (a2)
434     bne         0b                    /* blanking */
435
436     addq.l      #1, a2
437 0:
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
444 0:
445     move.b      (a0), d0
446     and.b       d1, d0
447     beq         0b
448 0:
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 */
457 0:
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  */
463 0:
464     move.b      (a0), d0
465     and.b       d1, d0
466     beq         0b
467
468 0:
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
480 test_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
495 0:
496     move.b      (a0), d0              /*  8 */
497     and.b       d1, d0                /*  4 */
498     beq         0b                    /* 10|8 */
499 0:
500     move.b      #0x3f, (a1)           /* 12 start a, clear  */
501     moveq.l     #3, d1                /* 12 cycles for old flag to clear itself */
502     nop
503     nop
504 0:
505     move.b      (a0), d0
506     and.b       d1, d0
507     beq         0b
508     move.b      (a0), d0              /* re-read, else very occasionally get 1 */
509     rts
510
511 # vim:filetype=asmM68k:ts=4:sw=4:expandtab