testpico: show that vres clear is separate
[megadrive.git] / testpico / main.c
index bd99ac3..43da6e6 100644 (file)
@@ -346,10 +346,11 @@ void exception(const struct exc_frame *f)
         printf("  PC: %08x SR: %04x            \n", f->g.pc, f->g.sr);
         sp_add = 6;
     }
-    for (i = 0; i < 8; i++)
+    sp = (u32 *)(f->ar[7] + sp_add);
+    for (i = 0; i < 7; i++)
         printf("  D%d: %08x A%d: %08x    \n", i, f->dr[i], i, f->ar[i]);
+    printf("  D%d: %08x SP: %08x    \n", i, f->dr[i], (u32)sp);
     printf("                               \n");
-    sp = (u32 *)(f->ar[7] + sp_add);
     printf(" %08x %08x %08x %08x\n", sp[0], sp[1], sp[2], sp[3]);
     printf(" %08x %08x %08x %08x\n", sp[4], sp[5], sp[6], sp[7]);
 }
@@ -404,6 +405,14 @@ static void vdp_wait_for_line_0(void)
         ;
 }
 
+static void wait_next_vsync(void)
+{
+    while (read16(VDP_CTRL_PORT) & SR_VB)
+        /* blanking */;
+    while (!(read16(VDP_CTRL_PORT) & SR_VB))
+        /* not blanking */;
+}
+
 static void t_dma_zero_wrap_early(void)
 {
     const u32 *src = (const u32 *)0x3c0000;
@@ -1759,9 +1768,11 @@ static int t_irq_f_flag_h32(void)
 
 #define IRQ_CNT_FB_BASE 0x1ff00
 
+// see do_cmd()
 static void x32_cmd(enum x32x_cmd cmd, u32 a0, u32 a1, u16 is_slave)
 {
     u16 v, *r = (u16 *)0xa15120;
+    u8 *r8 = (u8 *)r;
     u16 cmd_s = cmd | (is_slave << 15);
     int i;
 
@@ -1775,7 +1786,7 @@ static void x32_cmd(enum x32x_cmd cmd, u32 a0, u32 a1, u16 is_slave)
     if (v != 0) {
         printf("cmd clr: %x\n", v);
         mem_barrier();
-        printf("c, e: %02x %02x\n", r[0x0c/2],  r[0x0e/2]);
+        printf("exc m s: %02x %02x\n", r8[0x0e], r8[0x0f]);
         write16(r, 0);
     }
     v = read16(&r[1]);
@@ -1817,16 +1828,19 @@ static int t_32x_reset_btn(void)
     expect(ok, r32[0x20/4], 0x00005a20);
     expect(ok, r32[0x24/4], 0x5a5a5a24);
     expect(ok, r32[0x28/4], 0x5a5a5a28);
-    expect(ok, r32[0x2c/4], 0x5a5a5a2c);
+    expect(ok, r32[0x2c/4], 0x075a5a2c); // 7 - last_irq_vec
     if (!(r16[0x00/2] & 0x8000)) {
-        expect(ok, r8 [0x81], 0);
-        expect(ok, r16[0x82/2], 0);
-        expect(ok, r16[0x84/2], 0);
-        expect(ok, r16[0x86/2], 0);
-        //expect(ok, r16[0x88/2], 0); // triggers fill?
+        expect(ok, r8 [0x81], 1);
+        expect(ok, r16[0x82/2], 1);
+        expect(ok, r16[0x84/2], 0xff);
+        expect(ok, r16[0x86/2], 0xffff);
+        expect(ok, r16[0x88/2], 0);
         expect(ok, r8 [0x8b] & ~2, 0); // FEN toggles periodically?
         expect(ok, r16[0x8c/2], 0);
         expect(ok, r16[0x8e/2], 0);
+        // setup vdp for t_32x_init
+        r8 [0x81] = 0;
+        r16[0x82/2] = r16[0x84/2] = r16[0x86/2] = 0;
     }
     r32[0x20/4] = r32[0x24/4] = r32[0x28/4] = r32[0x2c/4] = 0;
     for (s = 0; s < 2; s++)
@@ -1844,7 +1858,18 @@ static int t_32x_reset_btn(void)
         expect(ok, s_icnt[i], 0x100);
     }
     expect(ok, m_icnt[7], 0x101); // VRES happened
+    expect(ok, s_icnt[7], 0x100); // masked on slave
+
+    x32_cmd(CMD_GETSR, 0, 0, 1);
+    expect_sh2(ok, 1, r32[0x24/4] & ~1, 0xf0); // still masked
+    x32_cmd(CMD_SETSR, 0x10, 0, 1);
+    expect(ok, r16[0x00/2], 0x8083);
+    write8(r8, 0x00); // FM=0
+    mem_barrier();
+    expect(ok, m_icnt[7], 0x101);
     expect(ok, s_icnt[7], 0x101);
+    expect(ok, r32[0x2c/4], 0x00070000); // 7 - last_irq_vec
+    r32[0x2c/4] = 0;
 
     memcpy_(do_32x_disable, x32x_disable,
             x32x_disable_end - x32x_disable);
@@ -1853,7 +1878,7 @@ static int t_32x_reset_btn(void)
     expect(ok, r16[0x00/2], 0x82);
     expect(ok, r16[0x02/2], 0);
     expect(ok, r16[0x04/2], 3);
-    expect(ok, r16[0x06/2], 1); // RV
+    expect(ok, r16[0x06/2], 0); // RV cleared by x32x_disable
     expect(ok, r32[0x08/4], 0x5a5a08);
     expect(ok, r32[0x0c/4], 0x5a5a0c);
     expect(ok, r16[0x10/2], 0x5a10);
@@ -1861,7 +1886,6 @@ static int t_32x_reset_btn(void)
 
     // setup for t_32x_init, t_32x_sh_defaults
     r16[0x04/2] = 0;
-    r16[0x06/2] = 0;      // can just set without ADEN
     r16[0x10/2] = 0x1234; // warm reset indicator
     mem_barrier();
     expect(ok, r16[0x06/2], 0); // RV
@@ -1905,9 +1929,40 @@ static int t_32x_init(void)
     r32[0x28/4] = 0;
     r32[0x2c/4] = 0;
 
-    // these have garbage or old values (survive MD's power cycle)
+    // check writable bits without ADEN
+    // 08,0c have garbage or old values (survive MD's power cycle)
+    write16(&r16[0x00/2], 0);
+    mem_barrier();
+    expect(ok, r16[0x00/2], 0x80);
+    write16(&r16[0x00/2], 0xfffe);
+    mem_barrier();
+    expect(ok, r16[0x00/2], 0x8082);
+    r16[0x00/2] = 0x82;
+    r16[0x02/2] = 0xffff;
+    r32[0x04/4] = 0xffffffff;
+    r32[0x08/4] = 0xffffffff;
+    r32[0x0c/4] = 0xffffffff;
+    r16[0x10/2] = 0xffff;
+    r32[0x14/4] = 0xffffffff;
+    r32[0x18/4] = 0xffffffff;
+    r32[0x1c/4] = 0xffffffff;
+    mem_barrier();
+    expect(ok, r16[0x00/2], 0x82);
+    expect(ok, r16[0x02/2], 0x03);
+    expect(ok, r16[0x04/2], 0x03);
+    expect(ok, r16[0x06/2], 0x07);
+    expect(ok, r32[0x08/4], 0x00fffffe);
+    expect(ok, r32[0x0c/4], 0x00ffffff);
+    expect(ok, r16[0x10/2], 0xfffc);
+    expect(ok, r32[0x14/4], 0);
+    expect(ok, r16[0x18/2], 0);
+    expect(ok, r16[0x1a/2], 0x0101);
+    expect(ok, r32[0x1c/4], 0);
+    r16[0x02/2] = 0;
+    r32[0x04/4] = 0;
     r32[0x08/4] = 0;
     r32[0x0c/4] = 0;
+    r16[0x1a/2] = 0;
 
     // could just set RV, but BIOS reads ROM, so can't
     memcpy_(do_32x_enable, x32x_enable,
@@ -1941,13 +1996,16 @@ static int t_32x_init(void)
 
 static int t_32x_echo(void)
 {
-    u16 *r = (u16 *)0xa15120;
+    u16 *r16 = (u16 *)0xa15100;
     int ok = 1;
 
+    r16[0x2c/2] = r16[0x2e/2] = 0;
     x32_cmd(CMD_ECHO, 0x12340000, 0, 0);
-    expect_sh2(ok, 0, r[0x06/2], 0x1234);
+    expect_sh2(ok, 0, r16[0x26/2], 0x1234);
     x32_cmd(CMD_ECHO, 0x23450000, 0, 1);
-    expect_sh2(ok, 1, r[0x06/2], 0xa345);
+    expect_sh2(ok, 1, r16[0x26/2], 0xa345);
+    expect(ok, r16[0x2c/2], 0); // no last_irq_vec
+    expect(ok, r16[0x2e/2], 0); // no exception_index
     return ok;
 }
 
@@ -2069,9 +2127,11 @@ static int t_32x_irq(void)
     u16 *s_icnt = m_icnt + 8;
     u32 *r = (u32 *)0xa15100;
     u16 *r16 = (u16 *)r;
+    u8 *r8 = (u8 *)r;
     int ok = 1, i;
 
     write8(r, 0x00); // FM=0
+    r[0x2c/4] = 0;
     mem_barrier();
     for (i = 0; i < 8; i++)
         write32(&fbl_icnt[i], 0);
@@ -2085,6 +2145,9 @@ static int t_32x_irq(void)
     write8(r, 0x00); // FM=0 (hangs without)
     mem_barrier();
     expect(ok, r16[0x02/2], 0);
+    expect(ok, r8 [0x2c], 4);
+    expect(ok, r8 [0x2d], 0);
+    expect(ok, r16[0x2e/2], 0); // no exception_index
     expect(ok, m_icnt[4], 1);
     expect(ok, s_icnt[4], 0);
     write16(&r16[0x02/2], 0xaaaa); // INTS+unused_bits
@@ -2093,6 +2156,9 @@ static int t_32x_irq(void)
     burn10(10);
     mem_barrier();
     expect(ok, r16[0x02/2], 0);
+    expect(ok, r8 [0x2c], 4);
+    expect(ok, r8 [0x2d], 4);
+    expect(ok, r16[0x2e/2], 0); // no exception_index
     write8(r, 0x00); // FM=0
     mem_barrier();
     expect(ok, m_icnt[4], 1);
@@ -2131,7 +2197,8 @@ static int t_32x_reg_w(void)
 // prepare for reset btn press tests
 static int t_32x_reset_prep(void)
 {
-    u32 *fbl_icnt = (u32 *)(0x840000 + IRQ_CNT_FB_BASE);
+    u32 *fbl = (u32 *)0x840000;
+    u32 *fbl_icnt = fbl + IRQ_CNT_FB_BASE / 4;
     u32 *r32 = (u32 *)0xa15100;
     u16 *r16 = (u16 *)r32;
     u8 *r8 = (u8 *)r32;
@@ -2139,14 +2206,17 @@ static int t_32x_reset_prep(void)
 
     expect(ok, r16[0x00/2], 0x83);
     write8(r8, 0x00); // FM=0
+    r32[0x2c/4] = 0;
     mem_barrier();
     expect(ok, r8[0x8b] & ~2, 0);
     for (i = 0; i < 8; i++)
         write32(&fbl_icnt[i], 0x01000100);
     x32_cmd(CMD_WRITE8, 0x20004001, 0x02, 0); // unmask cmd
     x32_cmd(CMD_WRITE8, 0x20004001, 0x02, 1); // unmask slave
+    x32_cmd(CMD_SETSR, 0xf0, 0, 1);           // mask slave irqs (on the cpu)
     burn10(10);
     write8(r8, 0x00); // FM=0
+    expect(ok, r32[0x2c/4], 0);
     mem_barrier();
     for (i = 0; i < 8; i++)
         expect(ok, fbl_icnt[i], 0x01000100);
@@ -2159,6 +2229,21 @@ static int t_32x_reset_prep(void)
     r32[0x24/4] = 0x5a5a5a24;
     r32[0x28/4] = 0x5a5a5a28;
     r32[0x2c/4] = 0x5a5a5a2c;
+    if (!(r16[0x00/2] & 0x8000)) {
+        wait_next_vsync();
+        r16[0x8a/2] = 0x0001;
+        mem_barrier();
+        for (i = 0; i < 220/2; i++)
+            fbl[i] = 0;
+        r8 [0x81] = 1;
+        r16[0x82/2] = 0xffff;
+        r16[0x84/2] = 0xffff;
+        r16[0x86/2] = 0xffff;
+        r16[0x8a/2] = 0x0000;
+        r16[0x8c/2] = 0xffff;
+        r16[0x8e/2] = 0xffff;
+        r16[0x100/2] = 0;
+    }
     return ok;
 }
 
@@ -2269,14 +2354,6 @@ static void setup_z80(void)
         ;
 }
 
-static void wait_next_vsync(void)
-{
-    while (read16(VDP_CTRL_PORT) & SR_VB)
-        /* blanking */;
-    while (!(read16(VDP_CTRL_PORT) & SR_VB))
-        /* not blanking */;
-}
-
 static unused int hexinc(char *c)
 {
     (*c)++;
@@ -2370,6 +2447,12 @@ int main()
         (v8 & 0x40) ? "pal" : "ntsc",
         have_32x ? "32X" : "",
         en_32x ? "+" : "");
+    printf("reset hvc %04x->%04x\n", read16(-4), read16(-2));
+
+    // sanity check
+    extern u32 sh2_test[];
+    if (sh2_test[0] != read32(0x3e0) || sh2_test[0x200/4] != read32(0x3e4))
+        printf("bad 0x3c0 tab\n");
 
     for (i = 0; i < ARRAY_SIZE(g_tests); i++) {
         // print test number if we haven't scrolled away
@@ -2405,7 +2488,7 @@ int main()
     printf_ypos = 0;
     printf("     ");
 
-    if (have_32x) {
+    if (have_32x && (read16(0xa15100) & 1)) {
         u8 *p = (u8 *)0xff0040;
         u32 len = x32x_switch_rv_end - x32x_switch_rv;
         px32x_switch_rv = (void *)p; p += len;
@@ -2419,14 +2502,18 @@ int main()
         // todo: broken printf
         px32x_switch_rv(0);
     }
-    for (i = 0; i < 60*60 && !(pget_input() & BTNM_A); i++)
-        wait_next_vsync();
+    for (i = 0; i < 60*60 && !(pget_input() & BTNM_A); i++) {
+        while (read16(VDP_CTRL_PORT) & SR_VB)
+            write16(-4, read16(VDP_HV_COUNTER)); /* blanking */
+        while (!(read16(VDP_CTRL_PORT) & SR_VB))
+            write16(-4, read16(VDP_HV_COUNTER)); /* not blanking */;
+    }
 #ifndef PICO
     // blank due to my lame tv being burn-in prone
     VDP_setReg(VDP_MODE2, VDP_MODE2_MD);
 #endif
     while (!(pget_input() & BTNM_A))
-        burn10(488*100/10);
+        write16(-4, read16(VDP_HV_COUNTER));
     VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP);