From 3d80f9400569f545d9e651a68aa0382f7ca6db40 Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 30 Jun 2023 21:05:42 +0300 Subject: [PATCH 1/7] testpico: more on timer reload --- testpico/asmtools.S | 3 ++- testpico/main.c | 27 +++++++++++++++++++++------ 2 files changed, 23 insertions(+), 7 deletions(-) diff --git a/testpico/asmtools.S b/testpico/asmtools.S index 24b6458..dd22368 100644 --- a/testpico/asmtools.S +++ b/testpico/asmtools.S @@ -534,7 +534,7 @@ test_ym_ab_sync2: movea.l #0xa04000, a0 movea.l #0xa04001, a1 -# move.b #0x3f, (a1) /* 12 clear */ + move.b #0x0f, (a1) /* 12 enable */ moveq.l #0, d0 moveq.l #3, d1 nop /* 4 need ~12c to clear */ @@ -543,6 +543,7 @@ test_ym_ab_sync2: and.b d1, d0 /* 4 */ beq 0b /* 10|8 */ move.b (a0), d0 /* re-read */ + move.b #0x3c, (a1) /* 12 clear, disable */ rts # vim:filetype=asmM68k:ts=4:sw=4:expandtab diff --git a/testpico/main.c b/testpico/main.c index 9c07110..1d27128 100644 --- a/testpico/main.c +++ b/testpico/main.c @@ -1409,19 +1409,34 @@ static int t_tim_ym_timerb_stop(void) static int t_tim_ym_timer_ab_sync(void) { - u16 v1, v2, v3, start, line_diff; + u16 v1, v2, v3, v4, v5, ln0, ln1, ln2; int ok = 1; + + vdp_wait_for_line_0(); v1 = test_ym_ab_sync(); - start = get_line(); - write8(0xa04001, 0x3f); // clear - burn10(3420*11/7/10); // ~11 scanlines + + ln0 = get_line(); + burn10(3420*15/7/10); // ~15 scanlines + write8(0xa04001, 0x3f); // clear, no reload + burn10(12); // wait for busy to clear v2 = read8(0xa04000); v3 = test_ym_ab_sync2(); - line_diff = get_line() - start; + + ln1 = get_line(); + burn10(3420*15/7/10); // ~15 scanlines + v4 = test_ym_ab_sync2(); + + ln2 = get_line(); + burn10(3420*30/7/10); // ~35 scanlines + v5 = read8(0xa04000); + expect(ok, v1, 3); expect(ok, v2, 0); expect(ok, v3, 3); - expect_range(ok, line_diff, 18, 19); + expect(ok, v4, 2); + expect(ok, v5, 0); + expect_range(ok, ln1-ln0, 18, 19); + expect_range(ok, ln2-ln1, 32, 34); // almost always 33 return ok; } -- 2.39.2 From be6b619d40e776f814ea8fd8b25c5a178ee5d7fc Mon Sep 17 00:00:00 2001 From: notaz Date: Wed, 1 May 2024 23:44:07 +0300 Subject: [PATCH 2/7] testpico: z80 timing correction from 2013 --- testpico/z80_test.s80 | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/testpico/z80_test.s80 b/testpico/z80_test.s80 index 5fbada1..ca6704d 100644 --- a/testpico/z80_test.s80 +++ b/testpico/z80_test.s80 @@ -21,9 +21,9 @@ loop ld e, a ; 4 ld a, (de) ; 7 inc e ; 4 - ld ixl, a ; 9 + ld ixl, a ; 8 ld a, (de) ; 7 - ld ixh, a ; 9 + ld ixh, a ; 8 pop hl ; src 10 ld hl, ($1002) pop de ; dst 10 ld de, ($1004) @@ -149,7 +149,7 @@ t_timer_a ld (hl), $25 ; 10 ld (bc), a ; 7 ld (hl), $27 ; 10 - ld_a (bc), $35 ; 14 enable timer+flag,clear ( max 67 + ld_a (bc), $35 ; 14 enable timer+flag,clear nop ; 4 flag clear delay tim_a_loop ld a, (hl) ; 7 -- 2.39.2 From 5073ab5adb8157c35014505385575473284788df Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 5 May 2024 01:49:33 +0300 Subject: [PATCH 3/7] testpico: 32x reset + other tests --- testpico/asmtools.S | 24 +++ testpico/asmtools.h | 4 + testpico/common.h | 2 + testpico/main.c | 393 ++++++++++++++++++++++++++++++++++-------- testpico/sega_gcc.s | 24 ++- testpico/sh2_main.c | 8 + testpico/sh2_test.sh2 | 71 ++++++-- 7 files changed, 429 insertions(+), 97 deletions(-) diff --git a/testpico/asmtools.S b/testpico/asmtools.S index dd22368..c240b6a 100644 --- a/testpico/asmtools.S +++ b/testpico/asmtools.S @@ -6,6 +6,7 @@ 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 @@ -44,6 +45,8 @@ write16_x16: # destroys d1 .global get_input get_input: +.global get_input_s +get_input_s: move.b #0x40,(0xa10003) moveq.l #0,d0 nop @@ -66,6 +69,8 @@ get_input: and.w d0,d1 /* what changed now */ .endif rts +.global get_input_end +get_input_end: .global get_line get_line: @@ -546,4 +551,23 @@ test_ym_ab_sync2: 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 diff --git a/testpico/asmtools.h b/testpico/asmtools.h index 0b34a1a..94bcfea 100644 --- a/testpico/asmtools.h +++ b/testpico/asmtools.h @@ -30,6 +30,8 @@ void test_ym_stopped_tick(void); short test_ym_ab_sync(void); short test_ym_ab_sync2(void); +extern const char get_input_s[]; +extern const char get_input_end[]; extern const char test_hint[]; extern const char test_hint_end[]; extern const char test_vint[]; @@ -40,5 +42,7 @@ extern const char x32x_enable[]; extern const char x32x_enable_end[]; extern const char x32x_disable[]; extern const char x32x_disable_end[]; +extern const char x32x_switch_rv[]; +extern const char x32x_switch_rv_end[]; extern const char test_32x_b_c0[]; extern const char test_32x_b_c0_end[]; diff --git a/testpico/common.h b/testpico/common.h index e65c6d0..ce02a51 100644 --- a/testpico/common.h +++ b/testpico/common.h @@ -35,6 +35,8 @@ enum x32x_cmd { CMD_WRITE8 = 6, CMD_WRITE16 = 7, CMD_WRITE32 = 8, + CMD_GETGBR = 9, + CMD_GETVBR = 10, }; // vim:ts=4:sw=4:expandtab diff --git a/testpico/main.c b/testpico/main.c index 1d27128..bd99ac3 100644 --- a/testpico/main.c +++ b/testpico/main.c @@ -6,6 +6,7 @@ #include #include "common.h" #include "asmtools.h" +//#pragma GCC diagnostic ignored "-Wunused-function" #define VDP_DATA_PORT 0xC00000 #define VDP_CTRL_PORT 0xC00004 @@ -231,6 +232,9 @@ static noinline int printf(const char *fmt, ...) for (j--; j >= 0; j--) buf[d++] = hexchars[(uval >> j * 4) & 0x0f]; break; + case 'c': + buf[d++] = va_arg(ap, int); + break; case 's': s = va_arg(ap, char *); while (*s && d < PRINTF_LEN) @@ -437,12 +441,20 @@ static void t_dma_zero_fill_early(void) ram[3] = read32(VDP_DATA_PORT); } +#define R_SKIP 0x5a5a + #define expect(ok_, v0_, v1_) \ do { if ((v0_) != (v1_)) { \ printf("%s: %08x %08x\n", #v0_, v0_, v1_); \ ok_ = 0; \ }} while (0) +#define expect_sh2(ok_, sh2_, v0_, v1_) \ +do { if ((v0_) != (v1_)) { \ + printf("%csh2: %08x %08x\n", sh2_ ? 's' : 'm', v0_, v1_); \ + ok_ = 0; \ +}} while (0) + #define expect_range(ok_, v0_, vmin_, vmax_) \ do { if ((v0_) < (vmin_) || (v0_) > (vmax_)) { \ printf("%s: %02x /%02x-%02x\n", #v0_, v0_, vmin_, vmax_); \ @@ -1745,13 +1757,125 @@ static int t_irq_f_flag_h32(void) // 32X +#define IRQ_CNT_FB_BASE 0x1ff00 + +static void x32_cmd(enum x32x_cmd cmd, u32 a0, u32 a1, u16 is_slave) +{ + u16 v, *r = (u16 *)0xa15120; + u16 cmd_s = cmd | (is_slave << 15); + int i; + + write32(&r[4/2], a0); + write32(&r[8/2], a1); + mem_barrier(); + write16(r, cmd_s); + mem_barrier(); + for (i = 0; i < 10000 && (v = read16(r)) == cmd_s; i++) + burn10(1); + if (v != 0) { + printf("cmd clr: %x\n", v); + mem_barrier(); + printf("c, e: %02x %02x\n", r[0x0c/2], r[0x0e/2]); + write16(r, 0); + } + v = read16(&r[1]); + if (v != 0) { + printf("cmd err: %x\n", v); + write16(&r[1], 0); + } +} + +static int t_32x_reset_btn(void) +{ + void (*do_32x_disable)(void) = (void *)0xff0040; + u32 *fbl_icnt = (u32 *)(0x840000 + IRQ_CNT_FB_BASE); + u16 *m_icnt = (u16 *)fbl_icnt; + u16 *s_icnt = m_icnt + 8; + u32 *r32 = (u32 *)0xa15100; + u16 *r16 = (u16 *)r32, i, s; + u8 *r8 = (u8 *)r32; + u32 *rl = (u32 *)0; + int ok = 1; + + if (!(read16(r16) & 1)) + return R_SKIP; + + expect(ok, r16[0x00/2], 0x8083); + + write8(r8, 0x00); // FM=0 + mem_barrier(); + expect(ok, r16[0x00/2], 0x83); + expect(ok, r16[0x02/2], 0); + expect(ok, r16[0x04/2], 3); + expect(ok, r16[0x06/2], 1); // RV (set in sega_gcc.s reset handler) + expect(ok, r32[0x08/4], 0x5a5a08); + expect(ok, r32[0x0c/4], 0x5a5a0c); + expect(ok, r16[0x10/2], 0x5a10); + expect(ok, r32[0x14/4], 0); + expect(ok, r32[0x18/4], 0); + expect(ok, r32[0x1c/4], 0); + expect(ok, r32[0x20/4], 0x00005a20); + expect(ok, r32[0x24/4], 0x5a5a5a24); + expect(ok, r32[0x28/4], 0x5a5a5a28); + expect(ok, r32[0x2c/4], 0x5a5a5a2c); + 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 [0x8b] & ~2, 0); // FEN toggles periodically? + expect(ok, r16[0x8c/2], 0); + expect(ok, r16[0x8e/2], 0); + } + r32[0x20/4] = r32[0x24/4] = r32[0x28/4] = r32[0x2c/4] = 0; + for (s = 0; s < 2; s++) + { + x32_cmd(CMD_READ32, 0x20004000, 0, s); // not cleared by hw + expect_sh2(ok, s, r32[0x24/4], 0x02020000); // ADEN | cmd + // t_32x_sh_defaults will test the other bits + } + // setup for t_32x_sh_defaults + x32_cmd(CMD_WRITE8, 0x20004001, 0, 0); + x32_cmd(CMD_WRITE8, 0x20004001, 0, 1); + + for (i = 0; i < 7; i++) { + expect(ok, m_icnt[i], 0x100); + expect(ok, s_icnt[i], 0x100); + } + expect(ok, m_icnt[7], 0x101); // VRES happened + expect(ok, s_icnt[7], 0x101); + + memcpy_(do_32x_disable, x32x_disable, + x32x_disable_end - x32x_disable); + do_32x_disable(); + + 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, r32[0x08/4], 0x5a5a08); + expect(ok, r32[0x0c/4], 0x5a5a0c); + expect(ok, r16[0x10/2], 0x5a10); + expect(ok, rl[0x04/4], 0x000800); + + // 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 + return ok; +} + static int t_32x_init(void) { void (*do_32x_enable)(void) = (void *)0xff0040; u32 M_OK = MKLONG('M','_','O','K'); u32 S_OK = MKLONG('S','_','O','K'); - u32 *r = (u32 *)0xa15100; - u16 *r16 = (u16 *)r; + u32 *r32 = (u32 *)0xa15100; + u16 *r16 = (u16 *)r32; + u8 *r8 = (u8 *)r32; int i, ok = 1; //v1070 = read32(0x1070); @@ -1765,13 +1889,25 @@ static int t_32x_init(void) expect(ok, r16[0x02/2], 0); expect(ok, r16[0x04/2], 0); expect(ok, r16[0x06/2], 0); - expect(ok, r[0x14/4], 0); - expect(ok, r[0x18/4], 0); - expect(ok, r[0x1c/4], 0); - write32(&r[0x20/4], 0); // master resp - write32(&r[0x24/4], 0); // slave resp - write32(&r[0x28/4], 0); - write32(&r[0x2c/4], 0); + expect(ok, r8 [0x08], 0); + //expect(ok, r32[0x08/4], 0); // garbage 24bit + expect(ok, r8 [0x0c], 0); + //expect(ok, r32[0x0c/4], 0); // garbage 24bit + if (r16[0x10/2] != 0x1234) // warm reset + expect(ok, r16[0x10/2], 0xffff); + expect(ok, r16[0x12/2], 0); + expect(ok, r32[0x14/4], 0); + expect(ok, r32[0x18/4], 0); + expect(ok, r32[0x1c/4], 0); + //expect(ok, r8 [0x81], 0); // VDP; hangs without ADEN + r32[0x20/4] = 0; // master resp + r32[0x24/4] = 0; // slave resp + r32[0x28/4] = 0; + r32[0x2c/4] = 0; + + // these have garbage or old values (survive MD's power cycle) + r32[0x08/4] = 0; + r32[0x0c/4] = 0; // could just set RV, but BIOS reads ROM, so can't memcpy_(do_32x_enable, x32x_enable, @@ -1782,41 +1918,25 @@ static int t_32x_init(void) expect(ok, r16[0x02/2], 0); expect(ok, r16[0x04/2], 0); expect(ok, r16[0x06/2], 1); // RV - expect(ok, r[0x14/4], 0); - expect(ok, r[0x18/4], 0); - expect(ok, r[0x1c/4], 0); - expect(ok, r[0x20/4], M_OK); + expect(ok, r32[0x14/4], 0); + expect(ok, r32[0x18/4], 0); + expect(ok, r32[0x1c/4], 0); + expect(ok, r32[0x20/4], M_OK); while (!read16(&r16[0x24/2])) ; - expect(ok, r[0x24/4], S_OK); - write32(&r[0x20/4], 0); - return ok; -} - -static void x32_cmd(enum x32x_cmd cmd, u32 a0, u32 a1, u16 is_slave) -{ - u16 v, *r = (u16 *)0xa15120; - u16 cmd_s = cmd | (is_slave << 15); - int i; - - write32(&r[4/2], a0); - write32(&r[8/2], a1); - mem_barrier(); - write16(r, cmd_s); - mem_barrier(); - for (i = 0; i < 10000 && (v = read16(r)) == cmd_s; i++) - burn10(1); - if (v != 0) { - printf("cmd clr: %x\n", v); - mem_barrier(); - printf("c, e: %02x %02x\n", r[0x0c/2], r[0x0e/2]); - write16(r, 0); - } - v = read16(&r[1]); - if (v != 0) { - printf("cmd err: %x\n", v); - write16(&r[1], 0); + expect(ok, r32[0x24/4], S_OK); + write32(&r32[0x20/4], 0); + 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 [0x8b] & ~2, 0); + expect(ok, r16[0x8c/2], 0); + expect(ok, r16[0x8e/2], 0); } + return ok; } static int t_32x_echo(void) @@ -1825,9 +1945,30 @@ static int t_32x_echo(void) int ok = 1; x32_cmd(CMD_ECHO, 0x12340000, 0, 0); - expect(ok, r[0x06/2], 0x1234); + expect_sh2(ok, 0, r[0x06/2], 0x1234); x32_cmd(CMD_ECHO, 0x23450000, 0, 1); - expect(ok, r[0x06/2], 0xa345); + expect_sh2(ok, 1, r[0x06/2], 0xa345); + return ok; +} + +static int t_32x_sh_defaults(void) +{ + u32 *r32 = (u32 *)0xa15120; + int ok = 1, s; + + for (s = 0; s < 2; s++) + { + x32_cmd(CMD_READ32, 0x20004000, 0, s); + expect_sh2(ok, s, r32[0x04/4], 0x02000000); // ADEN + x32_cmd(CMD_READ32, 0x20004004, 0, s); + expect_sh2(ok, s, r32[0x04/4], 0x00004001); // Empty Rv + x32_cmd(CMD_READ32, 0x20004008, 0, s); + expect_sh2(ok, s, r32[0x04/4], 0); + x32_cmd(CMD_READ32, 0x2000400c, 0, s); + expect_sh2(ok, s, r32[0x04/4], 0); + x32_cmd(CMD_GETGBR, 0, 0, s); + expect_sh2(ok, s, r32[0x04/4], 0x20004000); + } return ok; } @@ -1900,50 +2041,124 @@ static int t_32x_md_fb(void) static int t_32x_sh_fb(void) { u32 *fbl = (u32 *)0x840000; + u8 *r8 = (u8 *)0xa15100; int ok = 1; + if (read8(r8) & 0x80) + write8(r8, 0x00); // FM=0 fbl[0] = 0x12345678; fbl[1] = 0x89abcdef; mem_barrier(); - write8(0xa15100, 0x80); // FM=1 - x32_cmd(CMD_WRITE8, 0x24000000, 0, 0); - x32_cmd(CMD_WRITE8, 0x24020001, 0, 0); - x32_cmd(CMD_WRITE16, 0x24000002, 0, 0); - x32_cmd(CMD_WRITE16, 0x24020000, 0, 0); + write8(r8, 0x80); // FM=1 + x32_cmd(CMD_WRITE8, 0x24000000, 0, 0); // should ignore + x32_cmd(CMD_WRITE8, 0x24020001, 0, 0); // ignore + x32_cmd(CMD_WRITE16, 0x24000002, 0, 0); // ok + x32_cmd(CMD_WRITE16, 0x24020000, 0, 0); // ignore x32_cmd(CMD_WRITE32, 0x24020004, 0x5a0000a5, 1); - write8(0xa15100, 0x00); // FM=0 + write8(r8, 0x00); // FM=0 mem_barrier(); expect(ok, fbl[0], 0x12340000); expect(ok, fbl[1], 0x5aabcda5); return ok; } -static int t_32x_disable(void) +static int t_32x_irq(void) { - void (*do_32x_disable)(void) = (void *)0xff0040; + 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; - u32 *rl = (u32 *)0; - int ok = 1; + int ok = 1, i; - expect(ok, r16[0x00/2], 0x83); + write8(r, 0x00); // FM=0 + mem_barrier(); + for (i = 0; i < 8; i++) + write32(&fbl_icnt[i], 0); + mem_barrier(); + write16(&r16[0x02/2], 0xfffd); // INTM+unused_bits + mem_barrier(); + expect(ok, r16[0x02/2], 1); + x32_cmd(CMD_WRITE8, 0x20004001, 2, 0); // unmask cmd + x32_cmd(CMD_WRITE8, 0x20004001, 2, 1); // unmask cmd slave + burn10(10); + write8(r, 0x00); // FM=0 (hangs without) + mem_barrier(); + expect(ok, r16[0x02/2], 0); + expect(ok, m_icnt[4], 1); + expect(ok, s_icnt[4], 0); + write16(&r16[0x02/2], 0xaaaa); // INTS+unused_bits + mem_barrier(); + expect(ok, r16[0x02/2], 2); + burn10(10); + mem_barrier(); + expect(ok, r16[0x02/2], 0); + write8(r, 0x00); // FM=0 + mem_barrier(); + expect(ok, m_icnt[4], 1); + expect(ok, s_icnt[4], 1); + for (i = 0; i < 8; i++) { + if (i == 4) + continue; + expect(ok, m_icnt[i], 0); + expect(ok, s_icnt[i], 0); + } + return ok; +} - memcpy_(do_32x_disable, x32x_disable, - x32x_disable_end - x32x_disable); - do_32x_disable(); +static int t_32x_reg_w(void) +{ + u32 *r32 = (u32 *)0xa15100; + u16 *r16 = (u16 *)r32, old; + int ok = 1; - expect(ok, r16[0x00/2], 0x82); - expect(ok, r16[0x02/2], 0); - expect(ok, r16[0x04/2], 0); - expect(ok, r16[0x06/2], 1); // RV - expect(ok, r[0x14/4], 0); - expect(ok, r[0x18/4], 0); - expect(ok, r[0x1c/4], 0); - expect(ok, rl[0x04/4], 0x000800); + r32[0x08/4] = ~0; + r32[0x0c/4] = ~0; + r16[0x10/2] = ~0; + mem_barrier(); + expect(ok, r32[0x08/4], 0xfffffe); + expect(ok, r32[0x0c/4], 0xffffff); + expect(ok, r16[0x10/2], 0xfffc); + mem_barrier(); + r32[0x08/4] = r32[0x0c/4] = 0; + r16[0x10/2] = 0; + old = r16[0x06/2]; + x32_cmd(CMD_WRITE16, 0x20004006, ~old, 0); + expect(ok, r16[0x06/2], old); + return ok; +} - write16(&r16[0x06/2], 0); // can just set without ADEN +// prepare for reset btn press tests +static int t_32x_reset_prep(void) +{ + u32 *fbl_icnt = (u32 *)(0x840000 + IRQ_CNT_FB_BASE); + u32 *r32 = (u32 *)0xa15100; + u16 *r16 = (u16 *)r32; + u8 *r8 = (u8 *)r32; + int ok = 1, i; + + expect(ok, r16[0x00/2], 0x83); + write8(r8, 0x00); // FM=0 mem_barrier(); - expect(ok, r16[0x06/2], 0); // RV + 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 + burn10(10); + write8(r8, 0x00); // FM=0 + mem_barrier(); + for (i = 0; i < 8; i++) + expect(ok, fbl_icnt[i], 0x01000100); + + r16[0x04/2] = 0xffff; + r32[0x08/4] = 0x5a5a5a08; + r32[0x0c/4] = 0x5a5a5a0c; + r16[0x10/2] = 0x5a10; + r32[0x20/4] = 0x00005a20; // no x32_cmd + r32[0x24/4] = 0x5a5a5a24; + r32[0x28/4] = 0x5a5a5a28; + r32[0x2c/4] = 0x5a5a5a2c; return ok; } @@ -1957,6 +2172,9 @@ static const struct { int (*test)(void); const char *name; } g_tests[] = { + // this must be first to disable the 32x and restore the 68k vector table + { T_32, t_32x_reset_btn, "32x resetbtn" }, + { T_MD, t_dma_zero_wrap, "dma zero len + wrap" }, { T_MD, t_dma_zero_fill, "dma zero len + fill" }, { T_MD, t_dma_ram_wrap, "dma ram wrap" }, @@ -2008,11 +2226,14 @@ static const struct { // all tests assume RV=1 FM=0 { T_32, t_32x_init, "32x init" }, { T_32, t_32x_echo, "32x echo" }, + { T_32, t_32x_sh_defaults, "32x sh def" }, { T_32, t_32x_md_bios, "32x md bios" }, { T_32, t_32x_md_rom, "32x md rom" }, { T_32, t_32x_md_fb, "32x md fb" }, { T_32, t_32x_sh_fb, "32x sh fb" }, - { T_32, t_32x_disable, "32x disable" }, // must be last 32x + { T_32, t_32x_irq, "32x irq" }, + { T_32, t_32x_reg_w, "32x reg w" }, + { T_32, t_32x_reset_prep, "32x rstprep" }, // must be last 32x }; static void setup_z80(void) @@ -2070,6 +2291,8 @@ static unused int hexinc(char *c) int main() { + void (*px32x_switch_rv)(short rv); + short (*pget_input)(void) = get_input; int passed = 0; int skipped = 0; int have_32x; @@ -2140,7 +2363,7 @@ int main() VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP); have_32x = read32(0xa130ec) == MKLONG('M','A','R','S'); - en_32x = have_32x && (read32(0xa15100) & 1); + en_32x = have_32x && (read16(0xa15100) & 1); v8 = read8(0xa10001); printf("MD version: %02x %s %s %s%s\n", v8, (v8 & 0x80) ? "world" : "jap", @@ -2162,6 +2385,10 @@ int main() continue; } ret = g_tests[i].test(); + if (ret == R_SKIP) { + skipped++; + continue; + } if (ret != 1) { text_pal = 2; printf("failed %d: %s\n", i, g_tests[i].name); @@ -2178,13 +2405,27 @@ int main() printf_ypos = 0; printf(" "); - for (i = 0; i < 60*60 && !(get_input() & BTNM_A); i++) + if (have_32x) { + u8 *p = (u8 *)0xff0040; + u32 len = x32x_switch_rv_end - x32x_switch_rv; + px32x_switch_rv = (void *)p; p += len; + memcpy_(px32x_switch_rv, x32x_switch_rv, len); + + len = get_input_end - get_input_s; + pget_input = (void *)p; p += len; + memcpy_(pget_input, get_input_s, len); + + // prepare for reset - run from 880xxx as the reset vector points there + // todo: broken printf + px32x_switch_rv(0); + } + for (i = 0; i < 60*60 && !(pget_input() & BTNM_A); i++) wait_next_vsync(); #ifndef PICO // blank due to my lame tv being burn-in prone VDP_setReg(VDP_MODE2, VDP_MODE2_MD); #endif - while (!(get_input() & BTNM_A)) + while (!(pget_input() & BTNM_A)) burn10(488*100/10); VDP_setReg(VDP_MODE2, VDP_MODE2_MD | VDP_MODE2_DMA | VDP_MODE2_DISP); @@ -2215,18 +2456,18 @@ int main() hexinc(&c[2]); } #endif - while (get_input() & BTNM_A) + while (pget_input() & BTNM_A) wait_next_vsync(); wait_next_vsync(); for (;;) { - int b = get_input(); + int b = pget_input(); if (b & BTNM_C) { hscroll = 1, vscroll = -1; do { wait_next_vsync(); - } while (get_input() & BTNM_C); + } while (pget_input() & BTNM_C); cellmode ^= 1; } if (b & (BTNM_L | BTNM_R | BTNM_C)) { @@ -2252,13 +2493,13 @@ int main() hsz = (hsz + 1) & 3; do { wait_next_vsync(); - } while (get_input() & BTNM_A); + } while (pget_input() & BTNM_A); } if (b & BTNM_B) { vsz = (vsz + 1) & 3; do { wait_next_vsync(); - } while (get_input() & BTNM_B); + } while (pget_input() & BTNM_B); } VDP_setReg(VDP_SCROLLSZ, (vsz << 4) | hsz); diff --git a/testpico/sega_gcc.s b/testpico/sega_gcc.s index 1e0116a..52c9f8a 100644 --- a/testpico/sega_gcc.s +++ b/testpico/sega_gcc.s @@ -23,9 +23,12 @@ exc_tab: .ascii "src: https://github.com/notaz/megadrive/" /* 1c8 */ .ascii "JUE " /* 1f0 */ +# 32X reset vector (880200) + bra RST32X + # mystery landing area for reset with 32X on and RV=1 # 2c8 - 304 in multiples of 4 -.rept 0x1c0/2 +.rept 0x1bc/2 illegal .endr @@ -139,6 +142,23 @@ RST: #VBL: # rte +RST32X: + lea ram_rv_switch, %a0 + movea.l #0xff0100, %a1 + lea ram_rv_switch_end, %a2 +0: + move.l (%a0)+, (%a1)+ + cmp.l %a2, %a0 + blt.s 0b + jmp (0xff0100).l + +ram_rv_switch: + move.l (0x880004).l, %a0 + bset #0, (0xa15107).l /* RV=1 */ + nop /* just in case */ + jmp (%a0) +ram_rv_switch_end: + pre_exception: move.w #0x2700, %sr movem.l %d0-%d7/%a0-%a7,-(%sp) @@ -152,7 +172,7 @@ pre_exception: .macro exc_stub num exc\num: move.w #0x\num, -(%sp) - jmp pre_exception + bra pre_exception .endm exc_stub 02 diff --git a/testpico/sh2_main.c b/testpico/sh2_main.c index 97ecd3a..6fe8ad7 100644 --- a/testpico/sh2_main.c +++ b/testpico/sh2_main.c @@ -49,6 +49,14 @@ static void do_cmd(u16 cmd, u16 r[6], u32 is_slave) d = read32(&rl[8/4]); write32(a, d); break; + case CMD_GETGBR: + asm("stc gbr, %0" : "=r"(d)); + write32(&rl[4/4], d); + break; + case CMD_GETVBR: + asm("stc vbr, %0" : "=r"(d)); + write32(&rl[4/4], d); + break; default: r[2/2]++; // error mem_barrier(); diff --git a/testpico/sh2_test.sh2 b/testpico/sh2_test.sh2 index 1f3d61a..692fd92 100644 --- a/testpico/sh2_test.sh2 +++ b/testpico/sh2_test.sh2 @@ -100,7 +100,7 @@ xstart: mov.b @r1, r0 mov_bc 0x01, 0, r1 /* enable */ .endif - mov #0xd0, r0 /* enable irqs */ + mov #0x10, r0 /* enable irqs, 0 causes endless irq */ ldc r0, sr mov.l l_main_c, r0 jmp @r0 @@ -108,18 +108,38 @@ xstart: main_irq: mov.l r0, @-r15 + mov.l r1, @-r15 + mov.l l_irq_cnt, r1 /* counters in fb (0x2401ff00) */ - stc sr, r0 /* SR holds IRQ level in I3-I0 */ +do_irq_cmn: + mov.l r2, @-r15 + mov #0x80, r0 + mov.b r0, @(0, gbr) /* FM=1 */ + mov.b r0, @(0, gbr) /* flush write buf */ + stc sr, r0 /* SR holds IRQ level in I3-I0 */ shlr2 r0 - and #0x38,r0 - cmp/eq #0x38,r0 - bt main_irq_vres -! todo -0: - bra 0b + shlr2 r0 + and #0x0e, r0 + mov r0, r2 + add r1, r0 + mov.w @r0, r1 + add #1, r1 + mov.w r1, @r0 + mova l_irq_ao, r0 + mov.w @(r0, r2), r0 + stc gbr, r1 + mov.w r0, @(r0, r1) /* ack */ + mov #0x80, r0 + mov.b r0, @(0, gbr) /* FM=1 and flush writebuf (alt: ~20 nops) */ + mov.l @r15+, r2 + mov.l @r15+, r1 + mov.l @r15+, r0 + rte nop -main_irq_vres: +! not used +.if 0 +main_irq_vres_: mov.w r0, @(0x14, gbr) /* ack */ mov.b @(7, gbr), r0 /* RV */ tst #1, r0 @@ -146,8 +166,10 @@ main_irq_vres: nop main_irq_ret: - rte mov.l @r15+, r0 + rte + nop +.endif .global _read_frt _read_frt: @@ -160,14 +182,6 @@ _read_frt: rts or r1, r0 -.align 2 -l_cctl: - .long 0xFFFFFE92 -l_frt: - .long 0xFFFFFE10 -l_main_c: - .long _main_c - ! dummy .global _start _start: @@ -176,10 +190,29 @@ main_err: bra do_exc_master mov #0xff, r0 slave_err: -slave_irq: bra do_exc_slave mov #0xff, r0 +slave_irq: + mov.l r0, @-r15 + mov.l r1, @-r15 + mov.l l_irq_cnt, r1 /* counters in fb (0x2401ff00) */ + bra do_irq_cmn + add #0x10, r1 + +.align 2 +l_cctl: + .long 0xFFFFFE92 +l_frt: + .long 0xFFFFFE10 +l_main_c: + .long _main_c +l_irq_cnt: + .long 0x2401ff00 +l_irq_ao: + /* ?, ?, ?, pwm, cmd, h, v, rst */ + .word 0x0e, 0x0e, 0x0e, 0x1c, 0x1a, 0x18, 0x16, 0x14 + .macro exc_master num master_e\num: bra do_exc_master -- 2.39.2 From 6474d733133dc605ee02e4e2e02f025c41d202df Mon Sep 17 00:00:00 2001 From: notaz Date: Sun, 5 May 2024 17:45:23 +0300 Subject: [PATCH 4/7] testpico: check irq vector also --- testpico/main.c | 25 ++++++++++--- testpico/sh2_main.c | 9 +++++ testpico/sh2_test.sh2 | 84 +++++++++++++++++++++++++++++-------------- 3 files changed, 87 insertions(+), 31 deletions(-) diff --git a/testpico/main.c b/testpico/main.c index bd99ac3..d02a468 100644 --- a/testpico/main.c +++ b/testpico/main.c @@ -1759,9 +1759,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 +1777,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,7 +1819,7 @@ 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], 0x07075a2c); // 7 - last_irq_vec if (!(r16[0x00/2] & 0x8000)) { expect(ok, r8 [0x81], 0); expect(ok, r16[0x82/2], 0); @@ -1941,13 +1943,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 +2074,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 +2092,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 +2103,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); @@ -2139,6 +2152,7 @@ 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++) @@ -2147,6 +2161,7 @@ static int t_32x_reset_prep(void) x32_cmd(CMD_WRITE8, 0x20004001, 0x02, 1); // unmask slave 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); diff --git a/testpico/sh2_main.c b/testpico/sh2_main.c index 6fe8ad7..1bd9b90 100644 --- a/testpico/sh2_main.c +++ b/testpico/sh2_main.c @@ -3,6 +3,15 @@ void spin(int loops); u16 read_frt(void); +// comm area map: +// 00-01: cmd +// 02-03: error +// 04-07: arg0/response +// 08-0b: arg1 +// 0c: last_irq_vec_master +// 0d: last_irq_vec_slave +// 0e: exception_index_master +// 0f: exception_index_slave static void do_cmd(u16 cmd, u16 r[6], u32 is_slave) { u32 *rl = (u32 *)r; diff --git a/testpico/sh2_test.sh2 b/testpico/sh2_test.sh2 index 692fd92..0201827 100644 --- a/testpico/sh2_test.sh2 +++ b/testpico/sh2_test.sh2 @@ -17,21 +17,21 @@ .long master_e11 /* NMI vector */ .long master_e12 /* User break vector */ .rept 19 - .long main_err /* reserved */ + .long master_err /* reserved */ .endr .rept 32 - .long main_err /* TRAPA #32-63 */ + .long master_err /* TRAPA #32-63 */ .endr - .long main_irq /* Level 1 IRQ */ - .long main_irq /* Level 2 & 3 IRQ's */ - .long main_irq /* Level 4 & 5 IRQ's */ - .long main_irq /* PWM interupt */ - .long main_irq /* Command interupt */ - .long main_irq /* H Blank interupt */ - .long main_irq /* V Blank interupt */ - .long main_irq /* Reset Button */ + .long master_irq0 /* Level 1 IRQ */ + .long master_irq1 /* Level 2 & 3 IRQ's */ + .long master_irq2 /* Level 4 & 5 IRQ's */ + .long master_irq3 /* PWM interupt */ + .long master_irq4 /* Command interupt */ + .long master_irq5 /* H Blank interupt */ + .long master_irq6 /* V Blank interupt */ + .long master_irq7 /* Reset Button */ .rept 56 - .long main_err /* peripherals */ + .long master_err /* peripherals */ .endr ! Slave Vector Base Table at 0x06000200 @@ -55,14 +55,14 @@ .rept 32 .long slave_err /* TRAPA #32-63 */ .endr - .long slave_irq /* Level 1 IRQ */ - .long slave_irq /* Level 2 & 3 IRQ's */ - .long slave_irq /* Level 4 & 5 IRQ's */ - .long slave_irq /* PWM interupt */ - .long slave_irq /* Command interupt */ - .long slave_irq /* H Blank interupt */ - .long slave_irq /* V Blank interupt */ - .long slave_irq /* Reset Button */ + .long slave_irq0 /* Level 1 IRQ */ + .long slave_irq1 /* Level 2 & 3 IRQ's */ + .long slave_irq2 /* Level 4 & 5 IRQ's */ + .long slave_irq3 /* PWM interupt */ + .long slave_irq4 /* Command interupt */ + .long slave_irq5 /* H Blank interupt */ + .long slave_irq6 /* V Blank interupt */ + .long slave_irq7 /* Reset Button */ .rept 56 .long slave_err /* peripherals */ .endr @@ -106,8 +106,9 @@ xstart: jmp @r0 nop -main_irq: - mov.l r0, @-r15 +! r0=vector_number +do_irq_master: + mov.b r0, @(0x2c, gbr) mov.l r1, @-r15 mov.l l_irq_cnt, r1 /* counters in fb (0x2401ff00) */ @@ -186,15 +187,16 @@ _read_frt: .global _start _start: -main_err: +master_err: bra do_exc_master mov #0xff, r0 slave_err: bra do_exc_slave mov #0xff, r0 -slave_irq: - mov.l r0, @-r15 +! r0=vector_number +do_irq_slave: + mov.b r0, @(0x2d, gbr) mov.l r1, @-r15 mov.l l_irq_cnt, r1 /* counters in fb (0x2401ff00) */ bra do_irq_cmn @@ -225,6 +227,20 @@ slave_e\num: mov #\num, r0 .endm +.macro irq_master num +master_irq\num: + mov.l r0, @-r15 + bra do_irq_master + mov #\num, r0 +.endm + +.macro irq_slave num +slave_irq\num: + mov.l r0, @-r15 + bra do_irq_slave + mov #\num, r0 +.endm + exc_master 4 exc_master 5 exc_master 6 @@ -234,6 +250,14 @@ exc_master 9 exc_master 10 exc_master 11 exc_master 12 +irq_master 0 +irq_master 1 +irq_master 2 +irq_master 3 +irq_master 4 +irq_master 5 +irq_master 6 +irq_master 7 exc_slave 4 exc_slave 5 @@ -244,15 +268,23 @@ exc_slave 9 exc_slave 10 exc_slave 11 exc_slave 12 +irq_slave 0 +irq_slave 1 +irq_slave 2 +irq_slave 3 +irq_slave 4 +irq_slave 5 +irq_slave 6 +irq_slave 7 do_exc_master: - mov.w r0, @(0x2c, gbr) + mov.b r0, @(0x2e, gbr) 0: bra 0b nop do_exc_slave: - mov.w r0, @(0x2e, gbr) + mov.b r0, @(0x2f, gbr) 0: bra 0b nop -- 2.39.2 From c8abdf56595daf17437b16453526336f170046be Mon Sep 17 00:00:00 2001 From: notaz Date: Mon, 6 May 2024 23:53:04 +0300 Subject: [PATCH 5/7] testpico: check more settable bits with no ADEN --- testpico/asmtools.S | 1 + testpico/main.c | 36 +++++++++++++++++++++++++++++++++--- 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/testpico/asmtools.S b/testpico/asmtools.S index c240b6a..83f03db 100644 --- a/testpico/asmtools.S +++ b/testpico/asmtools.S @@ -300,6 +300,7 @@ 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 diff --git a/testpico/main.c b/testpico/main.c index d02a468..80d1660 100644 --- a/testpico/main.c +++ b/testpico/main.c @@ -1855,7 +1855,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); @@ -1863,7 +1863,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 @@ -1907,9 +1906,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, -- 2.39.2 From 7449b889b89e674e2b2b2ea3e2eea7c4aa57ff72 Mon Sep 17 00:00:00 2001 From: notaz Date: Fri, 10 May 2024 01:34:09 +0300 Subject: [PATCH 6/7] testpico: print hv counter, some tweaks --- testpico/main.c | 70 ++++++++++++++++++++++++++++++------------- testpico/sega_gcc.s | 26 ++++++++-------- testpico/sh2_test.sh2 | 8 +++-- 3 files changed, 70 insertions(+), 34 deletions(-) diff --git a/testpico/main.c b/testpico/main.c index 80d1660..b4a65c8 100644 --- a/testpico/main.c +++ b/testpico/main.c @@ -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; @@ -1821,14 +1830,17 @@ static int t_32x_reset_btn(void) expect(ok, r32[0x28/4], 0x5a5a5a28); expect(ok, r32[0x2c/4], 0x07075a2c); // 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++) @@ -2174,7 +2186,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; @@ -2204,6 +2217,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; } @@ -2314,14 +2342,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)++; @@ -2415,6 +2435,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 @@ -2450,7 +2476,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; @@ -2464,14 +2490,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); diff --git a/testpico/sega_gcc.s b/testpico/sega_gcc.s index 52c9f8a..4abb418 100644 --- a/testpico/sega_gcc.s +++ b/testpico/sega_gcc.s @@ -112,20 +112,22 @@ exc_tab: .word 0x5100,0x3340,0x0006,0x303C,0x8000,0x6004,0x44FC,0x0001 RST: - move.w #0x2600, %sr - - move.b (0xA10001), %d0 - andi.b #0x0F, %d0 - beq.s 0f - move.l #0x53454741, (0xA14000) /* 'SEGA' */ + andi.b #0x0F, (0xA10001) /* 24 */ + bne.s 0f /* 10 */ + move.w #0x8104, (0xc00004) + bra 1f 0: - tst.w (0xc00004).l + move.l #0x53454741, (0xA14000) /* 28 'SEGA' */ +1: + move.w (0xc00008), %d0 /* 16 */ + move.w %d0, -(%sp) + subq.l #2, %sp + move %sp, %usp - moveq #0, %d0 - movea.l %d0, %a7 - move %a7, %usp + move.w #0x2600, %sr /* clear .bss */ + moveq.l #0, %d0 lea __bss_start, %a0 lea __end, %a1 0: @@ -162,9 +164,9 @@ ram_rv_switch_end: pre_exception: move.w #0x2700, %sr movem.l %d0-%d7/%a0-%a7,-(%sp) - add.w #2, 0x3e(%sp) + add.w #2, 0x3e(%sp) /* ecxnum */ move.l %sp, %d0 - move.l %d0,-(%sp) /* arg0 */ + move.l %d0,-(%sp) /* arg0 */ jsr exception 0: bra 0b diff --git a/testpico/sh2_test.sh2 b/testpico/sh2_test.sh2 index 0201827..d72f083 100644 --- a/testpico/sh2_test.sh2 +++ b/testpico/sh2_test.sh2 @@ -29,6 +29,7 @@ .long master_irq4 /* Command interupt */ .long master_irq5 /* H Blank interupt */ .long master_irq6 /* V Blank interupt */ +! .long main_irq_vres .long master_irq7 /* Reset Button */ .rept 56 .long master_err /* peripherals */ @@ -112,6 +113,9 @@ do_irq_master: mov.l r1, @-r15 mov.l l_irq_cnt, r1 /* counters in fb (0x2401ff00) */ +! According to "32X Technical Information Attachment 1" FTOA pin must be toggled +! or interrupts may be missed when multiple irqs trigger. We skip that here since +! we test only 1 irq at a time. do_irq_cmn: mov.l r2, @-r15 mov #0x80, r0 @@ -140,7 +144,7 @@ do_irq_cmn: ! not used .if 0 -main_irq_vres_: +main_irq_vres: mov.w r0, @(0x14, gbr) /* ack */ mov.b @(7, gbr), r0 /* RV */ tst #1, r0 @@ -159,7 +163,7 @@ main_irq_vres_: mov.b r0, @(5, r1) /* OCRB L */ mov.b r0, @(2, r1) /* FRC H */ mov.b r0, @(3, r1) /* FRC L */ - mov.b @(7, r1), r0 + mov.b @(3, r1), r0 ! sleep - docs say not to use ! sleep 0: -- 2.39.2 From ec8170d94019bbfcdd7f53b31f0d27951162c23b Mon Sep 17 00:00:00 2001 From: notaz Date: Sat, 11 May 2024 01:31:00 +0300 Subject: [PATCH 7/7] testpico: show that vres clear is separate --- testpico/common.h | 2 ++ testpico/main.c | 14 +++++++++++++- testpico/sh2_main.c | 12 ++++++++++-- 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/testpico/common.h b/testpico/common.h index ce02a51..665b295 100644 --- a/testpico/common.h +++ b/testpico/common.h @@ -37,6 +37,8 @@ enum x32x_cmd { CMD_WRITE32 = 8, CMD_GETGBR = 9, CMD_GETVBR = 10, + CMD_GETSR = 11, + CMD_SETSR = 12, }; // vim:ts=4:sw=4:expandtab diff --git a/testpico/main.c b/testpico/main.c index b4a65c8..43da6e6 100644 --- a/testpico/main.c +++ b/testpico/main.c @@ -1828,7 +1828,7 @@ 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], 0x07075a2c); // 7 - last_irq_vec + expect(ok, r32[0x2c/4], 0x075a5a2c); // 7 - last_irq_vec if (!(r16[0x00/2] & 0x8000)) { expect(ok, r8 [0x81], 1); expect(ok, r16[0x82/2], 1); @@ -1858,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); @@ -2202,6 +2213,7 @@ static int t_32x_reset_prep(void) 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); diff --git a/testpico/sh2_main.c b/testpico/sh2_main.c index 1bd9b90..303fe3f 100644 --- a/testpico/sh2_main.c +++ b/testpico/sh2_main.c @@ -59,13 +59,21 @@ static void do_cmd(u16 cmd, u16 r[6], u32 is_slave) write32(a, d); break; case CMD_GETGBR: - asm("stc gbr, %0" : "=r"(d)); + asm volatile("stc gbr, %0" : "=r"(d)); write32(&rl[4/4], d); break; case CMD_GETVBR: - asm("stc vbr, %0" : "=r"(d)); + asm volatile("stc vbr, %0" : "=r"(d)); write32(&rl[4/4], d); break; + case CMD_GETSR: + asm volatile("stc sr, %0" : "=r"(d)); + write32(&rl[4/4], d); + break; + case CMD_SETSR: + d = read32(&rl[4/4]); + asm volatile("ldc %0, sr" :: "r"(d)); + break; default: r[2/2]++; // error mem_barrier(); -- 2.39.2