From 864820d8ade26280adbdb01da26fbdca2b677f99 Mon Sep 17 00:00:00 2001 From: "R. Belmont" Date: Sun, 12 Oct 2008 00:05:13 +0000 Subject: [PATCH] Fix Mantis #02211 PsikyoSH: hook up VBL IRQ ack SH2: fix DRC's handling of internally generated IRQs SH2: fix compiling in interpreter mode --- src/emu/cpu/sh2/sh2.c | 24 ++++++++++++++++++++++++ src/emu/cpu/sh2/sh2comn.c | 2 +- src/emu/cpu/sh2/sh2drc.c | 22 ++++++++++++++-------- src/mame/drivers/psikyosh.c | 17 +++++++++++++---- 4 files changed, 52 insertions(+), 13 deletions(-) diff --git a/src/emu/cpu/sh2/sh2.c b/src/emu/cpu/sh2/sh2.c index ba5e285225e..99d20fdbe44 100644 --- a/src/emu/cpu/sh2/sh2.c +++ b/src/emu/cpu/sh2/sh2.c @@ -2176,6 +2176,16 @@ static void sh2_reset(void) sh2->internal_irq_level = -1; } +/*------------------------------------------------- + sh1_reset - reset the processor +-------------------------------------------------*/ + +static void sh1_reset(void) +{ + sh2_reset(); + sh2->cpu_type = CPU_TYPE_SH1; +} + /* Execute cycles - returns number of cycles actually run */ static int sh2_execute(int cycles) { @@ -2462,4 +2472,18 @@ void sh2_get_info(UINT32 state, cpuinfo *info) } } +void sh1_get_info(UINT32 state, cpuinfo *info) +{ + switch (state) + { + /* --- the following bits of info are returned as pointers to data or functions --- */ + case CPUINFO_PTR_RESET: info->reset = sh1_reset; break; + + /* --- the following bits of info are returned as NULL-terminated strings --- */ + case CPUINFO_STR_NAME: strcpy(info->s, "SH-1"); break; + + default: sh2_get_info(state, info); break; + } +} + #endif diff --git a/src/emu/cpu/sh2/sh2comn.c b/src/emu/cpu/sh2/sh2comn.c index 917cd876090..7998f4ad3b8 100644 --- a/src/emu/cpu/sh2/sh2comn.c +++ b/src/emu/cpu/sh2/sh2comn.c @@ -651,7 +651,7 @@ void sh2_exception(const char *message, int irqline) else sh2->sr = (sh2->sr & ~I) | (irqline << 4); -// printf("sh2_exception [%s] irqline %x evec %x save SR %x new SR %x\n", message, irqline, sh2->evec, sh2->irqsr, sh2->sr); +// printf("sh2_exception [%s] irqline %x evec %x save SR %x new SR %x\n", message, irqline, sh2->evec, sh2->irqsr, sh2->sr); #else sh2->r[15] -= 4; WL( sh2->r[15], sh2->sr ); /* push SR onto stack */ diff --git a/src/emu/cpu/sh2/sh2drc.c b/src/emu/cpu/sh2/sh2drc.c index ece49719d3c..1f30af17435 100644 --- a/src/emu/cpu/sh2/sh2drc.c +++ b/src/emu/cpu/sh2/sh2drc.c @@ -1034,6 +1034,7 @@ static void static_generate_entry_point(drcuml_state *drcuml) load_fast_iregs(block); /* check for interrupts */ + UML_MOV(block, MEM(&sh2->irqline), IMM(0xffffffff)); // mov irqline, #-1 UML_CMP(block, MEM(&sh2->pending_nmi), IMM(0)); // cmp pending_nmi, #0 UML_JMPc(block, IF_Z, skip+2); // jz skip+2 @@ -1044,16 +1045,18 @@ static void static_generate_entry_point(drcuml_state *drcuml) UML_MOV(block, MEM(&sh2->evec), IMM(0xffffffff)); // mov evec, -1 UML_MOV(block, IREG(0), IMM(0xffffffff)); // mov r0, -1 (r0 = irq) UML_AND(block, IREG(1), IREG(0), IMM(0xffff)); // and r1, 0xffff + UML_LZCNT(block, IREG(1), MEM(&sh2->pending_irq)); // lzcnt r1, r1 UML_CMP(block, IREG(1), IMM(32)); // cmp r1, #32 - UML_JMPc(block, IF_Z, skip+1); // jz skip+1 + UML_JMPc(block, IF_Z, skip+4); // jz skip+4 UML_SUB(block, MEM(&sh2->irqline), IMM(31), IREG(1)); // sub irqline, #31, r1 + UML_LABEL(block, skip+4); // skip+4: UML_CMP(block, MEM(&sh2->internal_irq_level), IMM(0xffffffff)); // cmp internal_irq_level, #-1 UML_JMPc(block, IF_Z, skip+3); // jz skip+3 UML_CMP(block, MEM(&sh2->internal_irq_level), MEM(&sh2->irqline)); // cmp internal_irq_level, irqline - UML_JMPc(block, IF_BE, skip+3); // ja skip+3 + UML_JMPc(block, IF_LE, skip+3); // jle skip+3 UML_MOV(block, MEM(&sh2->irqline), MEM(&sh2->internal_irq_level)); // mov r0, internal_irq_level @@ -1409,14 +1412,15 @@ static void log_add_disasm_comment(drcuml_block *block, UINT32 pc, UINT32 op) static void generate_update_cycles(drcuml_block *block, compiler_state *compiler, drcuml_ptype ptype, UINT64 pvalue, int allow_exception) { /* check full interrupts if pending */ - if (compiler->checkints) + if (compiler->checkints) { drcuml_codelabel skip = compiler->labelnum++; compiler->checkints = FALSE; - compiler->labelnum += 3; + compiler->labelnum += 4; /* check for interrupts */ + UML_MOV(block, MEM(&sh2->irqline), IMM(0xffffffff)); // mov irqline, #-1 UML_CMP(block, MEM(&sh2->pending_nmi), IMM(0)); // cmp pending_nmi, #0 UML_JMPc(block, IF_Z, skip+2); // jz skip+2 @@ -1426,17 +1430,19 @@ static void generate_update_cycles(drcuml_block *block, compiler_state *compiler UML_LABEL(block, skip+2); // skip+2: UML_MOV(block, MEM(&sh2->evec), IMM(0xffffffff)); // mov evec, -1 UML_MOV(block, IREG(0), IMM(0xffffffff)); // mov r0, -1 (r0 = irq) - UML_AND(block, IREG(1), IREG(0), IMM(0xffff)); // and r1, 0xffff - UML_LZCNT(block, IREG(1), MEM(&sh2->pending_irq)); // lzcnt r1, r1 + UML_AND(block, IREG(1), IREG(0), IMM(0xffff)); // and r1, r0, 0xffff + + UML_LZCNT(block, IREG(1), MEM(&sh2->pending_irq)); // lzcnt r1, pending_irq UML_CMP(block, IREG(1), IMM(32)); // cmp r1, #32 - UML_JMPc(block, IF_Z, skip+1); // jz skip+1 + UML_JMPc(block, IF_Z, skip+4); // jz skip+4 UML_SUB(block, MEM(&sh2->irqline), IMM(31), IREG(1)); // sub irqline, #31, r1 + UML_LABEL(block, skip+4); // skip+4: UML_CMP(block, MEM(&sh2->internal_irq_level), IMM(0xffffffff)); // cmp internal_irq_level, #-1 UML_JMPc(block, IF_Z, skip+3); // jz skip+3 UML_CMP(block, MEM(&sh2->internal_irq_level), MEM(&sh2->irqline)); // cmp internal_irq_level, irqline - UML_JMPc(block, IF_BE, skip+3); // ja skip+3 + UML_JMPc(block, IF_LE, skip+3); // jle skip+3 UML_MOV(block, MEM(&sh2->irqline), MEM(&sh2->internal_irq_level)); // mov r0, internal_irq_level diff --git a/src/mame/drivers/psikyosh.c b/src/mame/drivers/psikyosh.c index 7b8a6852b87..8e3cc3de4aa 100644 --- a/src/mame/drivers/psikyosh.c +++ b/src/mame/drivers/psikyosh.c @@ -48,7 +48,6 @@ To Do: - see notes in video file - - Sol Divide's music is completely broken since the SH2 DRC Daraku is missing some screen blend effects @@ -414,7 +413,17 @@ static READ32_HANDLER( psh_eeprom_r ) static INTERRUPT_GEN(psikyosh_interrupt) { - cpunum_set_input_line(machine, 0, 4, HOLD_LINE); + cpunum_set_input_line(machine, 0, 4, ASSERT_LINE); +} + +// VBL handler writes 0x00 on entry, 0xc0 on exit +// bit 0 controls game speed on readback, mechanism is a little weird +static WRITE32_HANDLER( psikyosh_irqctrl_w ) +{ + if (!(data & 0x00c00000)) + { + cpunum_set_input_line(machine, 0, 4, CLEAR_LINE); + } } static WRITE32_HANDLER( paletteram32_RRRRRRRRGGGGGGGGBBBBBBBBxxxxxxxx_dword_w ) @@ -532,7 +541,7 @@ static ADDRESS_MAP_START( ps3v1_writemem, ADDRESS_SPACE_PROGRAM, 32 ) AM_RANGE(0x03004000, 0x0300ffff) AM_WRITE(SMH_RAM) AM_BASE(&psikyosh_bgram) // backgrounds AM_RANGE(0x03040000, 0x03044fff) AM_WRITE(paletteram32_RRRRRRRRGGGGGGGGBBBBBBBBxxxxxxxx_dword_w) AM_BASE(&paletteram32) // palette.. AM_RANGE(0x03050000, 0x030501ff) AM_WRITE(SMH_RAM) AM_BASE(&psikyosh_zoomram) // a gradient sometimes ... - AM_RANGE(0x0305ffdc, 0x0305ffdf) AM_WRITE(SMH_RAM) // also reads from this address + AM_RANGE(0x0305ffdc, 0x0305ffdf) AM_WRITE(psikyosh_irqctrl_w) AM_RANGE(0x0305ffe0, 0x0305ffff) AM_WRITE(psikyosh_vidregs_w) AM_BASE(&psikyosh_vidregs) // video registers AM_RANGE(0x05000000, 0x05000003) AM_WRITE(psh_ymf_fm_w) // first 2 OPL4 register banks AM_RANGE(0x05000004, 0x05000007) AM_WRITE(psh_ymf_pcm_w) // third OPL4 register bank @@ -569,7 +578,7 @@ static ADDRESS_MAP_START( ps5_writemem, ADDRESS_SPACE_PROGRAM, 32 ) AM_RANGE(0x04004000, 0x0400ffff) AM_WRITE(SMH_RAM) AM_BASE(&psikyosh_bgram) // backgrounds AM_RANGE(0x04040000, 0x04044fff) AM_WRITE(paletteram32_RRRRRRRRGGGGGGGGBBBBBBBBxxxxxxxx_dword_w) AM_BASE(&paletteram32) AM_RANGE(0x04050000, 0x040501ff) AM_WRITE(SMH_RAM) AM_BASE(&psikyosh_zoomram) - AM_RANGE(0x0405ffdc, 0x0405ffdf) AM_WRITE(SMH_RAM) // also reads from this address + AM_RANGE(0x0405ffdc, 0x0405ffdf) AM_WRITE(psikyosh_irqctrl_w) AM_RANGE(0x0405ffe0, 0x0405ffff) AM_WRITE(psikyosh_vidregs_w) AM_BASE(&psikyosh_vidregs) // video registers AM_RANGE(0x05000000, 0x0507ffff) AM_WRITE(SMH_ROM) // data ROM AM_RANGE(0x06000000, 0x060fffff) AM_WRITE(SMH_RAM) AM_BASE(&psh_ram)