testpico: show that vres clear is separate
[megadrive.git] / testpico / asmtools.S
index d216a83..83f03db 100644 (file)
@@ -1,21 +1,23 @@
 # Assemble with gas
 #   --register-prefix-optional --bitwise-or
+# reminder: d2-d7/a2-a6 are callee-save
 
 .macro ldarg  arg, stacksz, reg
     move.l (4 + \arg * 4 + \stacksz)(%sp), \reg
 .endm
 
+# args are always 4 bytes in stack, caller restores sp
 .macro ldargw arg, stacksz, reg
     move.w (4 + \arg * 4 + 2 + \stacksz)(%sp), \reg
 .endm
 
 .global burn10 /* u16 val */
 burn10:
-    ldarg       0, 0, d0
+    ldargw      0, 0, d0
     subq.l      #1, d0
 0:
-    dbra        d0, 0b
-    rts
+    dbra        d0, 0b      /* 10|14 */
+    rts                     /* 16 */
 
 .global write16_x16 /* u32 a, u16 count, u16 d */
 write16_x16:
@@ -40,9 +42,11 @@ write16_x16:
 
 # read single phase from controller
 #  d0 - result
-#  destroys d1,d2
+#  destroys d1
 .global get_input
 get_input:
+.global get_input_s
+get_input_s:
        move.b          #0x40,(0xa10003)
        moveq.l         #0,d0
        nop
@@ -65,6 +69,18 @@ get_input:
        and.w           d0,d1           /* what changed now */
 .endif
        rts
+.global get_input_end
+get_input_end:
+
+.global get_line
+get_line:
+    movea.l     #0xc00008, a0
+    moveq.l     #0, d0
+0:
+    move.b      (a0), d0    /*  8 d2 = vcnt */
+    cmp.b       (a0), d0    /*  8 reread for super-rare corruption (torn read) */
+    bne         0b
+    rts
 
 .global write_and_read1 /* u32 a, u16 d, void *dst */
 write_and_read1:
@@ -73,6 +89,8 @@ write_and_read1:
 #ifndef PICO
     move.w      d0, (a0)
 #else
+    /* different timing due to extra fetch of offset, */
+    /* less troulesome to emulate */
     movea.l     a0, a1
     subq.l      #1, a1
     move.w      d0, 1(a1)
@@ -193,6 +211,36 @@ test_vcnt_vb:
     movem.l     (sp)+, d2-d7/a2
     rts
 
+.global test_vcnt_loops
+test_vcnt_loops:
+    movem.l     d2, -(sp)
+    movea.l     #0xc00007, a0
+    movea.l     #0xfff000, a1
+    move.b      #0xff, d0       /* d0 = current_vcnt */
+    moveq.l     #0, d1          /* d1 = loop counter */
+    move.w      #315-1, d2      /* d2 = line limit */
+0:
+    btst        #3, (a0)
+    beq         0b          /* not blanking */
+0:
+    btst        #3, (a0)
+    bne         0b          /* blanking */
+
+    addq.w      #1, a0
+0:
+    addq.w      #1, d1      /*  4 */
+    cmp.b       (a0), d0    /*  8 vcnt changed? */
+    beq         0b          /* 10 */
+
+    move.w      d0, (a1)+   /*  8 save */
+    move.w      d1, (a1)+
+    move.b      (a0), d0    /*  8 new vcnt */
+    moveq.l     #0, d1
+    dbra        d2, 0b
+
+    movem.l     (sp)+, d2
+    rts
+
 .global test_hint
 test_hint:
     move.w      d0, -(sp)         /*  8 */
@@ -249,12 +297,26 @@ x32x_enable:
 .global x32x_enable_end
 x32x_enable_end:
 
+.global x32x_disable
+x32x_disable:
+    movea.l     #0xa15100, a0
+    move.w      #0, 6(a0)         /* RV=0 */
+    move.w      #1, (a0)          /* ADEN (reset sh2) */
+    move.w      #0, (a0)          /* adapter disable, reset sh2 */
+    move.w      #1, d0
+0:
+    dbra        d0, 0b
+    move.w      #2, (a0)          /* nRES - sh2s should see no ADEN and sleep */
+    rts
+.global x32x_disable_end
+x32x_disable_end:
+
 .global test_32x_b_c0
 test_32x_b_c0:
     ldarg       0, 0, a1
     ldargw      1, 0, d0
     jsr         (0xc0).l          /* move.b d0, (a1); RV=0 */
-    bset        #0, (0xa15107).l
+    bset        #0, (0xa15107).l  /* RV=1 */
     rts
 .global test_32x_b_c0_end
 test_32x_b_c0_end:
@@ -363,4 +425,150 @@ test_hb:
     movem.l     (sp)+, d2-d7
     rts
 
+.macro ymwrite  areg, dreg addr dat
+    move.b      \addr, (\areg) /* 12 addr */
+    nbcd        d0             /*  6 delay to reach 17 ym cycles (M/7) */
+    move.b      \dat, (\dreg)  /* 12 data */
+.endm
+
+.global test_ym_stopped_tick
+test_ym_stopped_tick:
+    movem.l     a2-a3, -(sp)
+    movea.l     #0xa04000, a0
+    movea.l     #0xa04001, a1
+    movea.l     #0xc00007, a2
+    movea.l     #0xfff000, a3
+
+    ymwrite     a0, a1, #0x27, #0x30  /* 30 disable, clear */
+    ymwrite     a0, a1, #0x26, #0xff  /* 30 timer b shortest interval */
+    move.b      #0x27, (a0)           /* 12 addr prep */
+0:
+    btst        #3, (a2)
+    beq         0b                    /* not blanking */
+0:
+    btst        #3, (a2)
+    bne         0b                    /* blanking */
+
+    addq.l      #1, a2
+0:
+    tst.b       (a2)
+    bne         0b                    /* not line 0 - waiting for sequential vcnt */
+
+    move.b      #0x0a, (a1)           /* 12 start timer b  */
+    moveq.l     #0, d0
+    moveq.l     #2, d1
+0:
+    move.b      (a0), d0
+    and.b       d1, d0
+    beq         0b
+0:
+#    move.w      (a2), (a3)+           /* 12 save hvcnt */
+    move.b      (a2), d0
+    cmp.b       (a2), d0
+    bne         0b
+    move.w      d0, (a3)+
+    move.b      #0x30, (a1)           /* 12 stop b, clear  */
+
+    move.w      #(1900/10-1), d0      /* waste cycles */
+0:
+    dbra        d0, 0b
+    moveq.l     #0, d0
+
+    move.w      (a0), (a3)+           /* 12 save status */
+    move.b      #0x0a, (a1)           /* 12 start b  */
+0:
+    move.b      (a0), d0
+    and.b       d1, d0
+    beq         0b
+
+0:
+#    move.w      (a2), (a3)+           /* 12 save hvcnt */
+    move.b      (a2), d1
+    cmp.b       (a2), d1
+    bne         0b
+    move.w      d1, (a3)+
+    move.w      d0, (a3)+             /* 12 save status */
+
+    movem.l     (sp)+, a2-a3
+    rts
+
+.global test_ym_ab_sync
+test_ym_ab_sync:
+    movea.l     #0xa04000, a0
+    movea.l     #0xa04001, a1
+
+    ymwrite     a0, a1, #0x27, #0x30  /* 30 disable, clear */
+    ymwrite     a0, a1, #0x24, #0xfc  /* 30 timer a */
+    ymwrite     a0, a1, #0x25, #0x01  /* 30  =15 */
+    ymwrite     a0, a1, #0x26, #0xff  /* 30 timer b shortest interval */
+    move.b      #0x27, (a0)           /* 12 addr prep */
+    nop
+    nop
+
+    move.b      #0x0a, (a1)           /* 12 start timer b  */
+    moveq.l     #0, d0
+    moveq.l     #2, d1
+0:
+    move.b      (a0), d0              /*  8 */
+    and.b       d1, d0                /*  4 */
+    beq         0b                    /* 10|8 */
+
+    move.b      #0x3f, (a1)           /* 12 start a, clear  */
+
+    move.w      #(488/10), d0         /* waste cycles */
+0:  dbra        d0, 0b
+
+    ymwrite     a0, a1, #0x24, #0xf0  /* 30 show that rewriting count */
+    ymwrite     a0, a1, #0x25, #0x00  /* 30 does nothing until timer expires */
+
+    move.w      #(488*2/10), d0       /* waste cycles */
+0:  dbra        d0, 0b
+
+    ymwrite     a0, a1, #0x26, #0xfc  /* 30 same for timer b */
+    ymwrite     a0, a1, #0x27, #0x0f  /* 30 setting already set bits too  */
+    moveq.l     #0, d0
+    moveq.l     #3, d1
+0:
+    move.b      (a0), d0
+    and.b       d1, d0
+    beq         0b
+    move.b      (a0), d0              /* re-read, else very occasionally get 1 */
+    rts
+
+.global test_ym_ab_sync2
+test_ym_ab_sync2:
+    movea.l     #0xa04000, a0
+    movea.l     #0xa04001, a1
+
+    move.b      #0x0f, (a1)           /* 12 enable  */
+    moveq.l     #0, d0
+    moveq.l     #3, d1
+    nop                               /*  4 need ~12c to clear */
+0:
+    move.b      (a0), d0              /*  8 */
+    and.b       d1, d0                /*  4 */
+    beq         0b                    /* 10|8 */
+    move.b      (a0), d0              /* re-read */
+    move.b      #0x3c, (a1)           /* 12 clear, disable  */
+    rts
+
+.global x32x_switch_rv
+x32x_switch_rv:
+    ldargw      0, 0, d0
+    move.l      (sp)+, d1
+    movea.l     #0xa15106, a0
+    btst        #0, d0
+    bne         0f
+    move.w      #0, (a0)
+    or.l        #0x880000, d1
+    bra         1f
+0:
+    move.w      #1, (a0)
+    and.l       #0x07ffff, d1
+1:
+    movea.l     d1, a1
+    jmp         (a1)
+.global x32x_switch_rv_end
+x32x_switch_rv_end:
+
 # vim:filetype=asmM68k:ts=4:sw=4:expandtab