+static int t_32x_irq_vint(void)
+{
+ u32 *fbl_icnt = (u32 *)(0x840000 + IRQ_CNT_FB_BASE);
+ u16 *m_icnt = (u16 *)fbl_icnt;
+ u16 *s_icnt = m_icnt + 8;
+ u32 *r = (u32 *)0xa15100;
+ u16 *r16 = (u16 *)r;
+ u8 *r8 = (u8 *)r;
+ int ok = 1, i;
+
+ vdp_wait_for_line_0();
+ write8(r, 0x00); // FM=0
+ r[0x2c/4] = 0;
+ mem_barrier();
+ for (i = 0; i < 8; i++)
+ write32(&fbl_icnt[i], 0);
+ mem_barrier();
+ x32_cmd(CMD_SETSR, 0xf0, 0, 0); // master mask at sr
+ x32_cmd(CMD_WRITE8, 0x20004001, 8, 0); // unmask both 32x vint
+ x32_cmd(CMD_WRITE8, 0x20004001, 8, 1);
+ burn10(10);
+ mem_barrier();
+ expect(ok, r16[0x2c/2], 0); // no pending vints
+ expect(ok, r16[0x2e/2], 0); // no exception_index
+
+ write8(&r8[0x23], 0x5a); // no-32x-source-autoclear flag
+ wait_next_vsync();
+ burn10(10);
+ expect(ok, r8 [0x2c], 0);
+ expect(ok, r8 [0x2d], 12/2);
+ write8(&r8[0x2d], 0);
+ burn10(10);
+ expect(ok, r8 [0x2c], 0);
+ expect(ok, r8 [0x2d], 12/2);
+
+ x32_cmd(CMD_WRITE16, 0x20004016, 0, 0); // clear on 32x (from master)
+ burn10(10);
+ write16(&r[0x2c/4], 0);
+ burn10(10);
+ expect(ok, r8 [0x2c], 0);
+ expect(ok, r8 [0x2d], 12/2);
+ // (here the slave can't accept commands as it keeps retaking the irq)
+ write8(&r8[0x23], 0); // handler 32x clear on
+ burn10(10);
+ write16(&r[0x2c/4], 0);
+ burn10(10);
+ expect(ok, r16[0x2c/2], 0); // no pending vints
+ expect(ok, r16[0x2e/2], 0); // no exception_index
+ write8(r, 0x00); // FM=0
+ mem_barrier();
+ expect(ok, m_icnt[12/2], 0);
+ expect_range(ok, s_icnt[12/2], 0x10, 0x1000);
+
+ x32_cmd(CMD_SETSR, 0x10, 0, 0); // master unmask at sr
+ wait_next_vsync();
+ burn10(10);
+ expect(ok, r8 [0x2c], 12/2);
+ expect(ok, r8 [0x2d], 12/2);
+
+ x32_cmd(CMD_WRITE8, 0x20004001, 0, 0); // mask
+ x32_cmd(CMD_WRITE8, 0x20004001, 0, 1);
+ write16(&r[0x2c/4], 0);
+ wait_next_vsync();
+ burn10(10);
+ expect(ok, r16[0x2c/2], 0); // no pending vints
+ expect(ok, r16[0x2e/2], 0); // no exception_index
+
+ x32_cmd(CMD_WRITE8, 0x20004001, 8, 1); // slave unmask
+ burn10(10);
+ x32_cmd(CMD_WRITE8, 0x20004001, 0, 1); // mask
+ burn10(10);
+ expect(ok, r8 [0x2c], 0);
+ expect(ok, r8 [0x2d], 12/2);
+ write16(&r[0x2c/4], 0);
+
+ vdp_wait_for_line_0();
+ x32_cmd(CMD_WRITE8, 0x20004001, 8, 0); // master unmask
+ burn10(10);
+ x32_cmd(CMD_WRITE8, 0x20004001, 0, 0); // mask
+ burn10(10);
+ expect(ok, r8 [0x2c], 0);
+ expect(ok, r8 [0x2d], 0);
+
+ write8(&r8[0x23], 0); // handler 32x clear on
+ write8(r, 0x00); // FM=0
+ mem_barrier();
+ expect(ok, m_icnt[12/2], 1);
+ for (i = 0; i < 8; i++) {
+ if (i == 12/2)
+ continue;
+ expect(ok, m_icnt[i], 0);
+ expect(ok, s_icnt[i], 0);
+ }
+ return ok;
+}
+