diff options
author | 2018-10-21 21:11:09 +0200 | |
---|---|---|
committer | 2018-10-21 21:29:13 +0200 | |
commit | af515310d71f7f8529c3d52c1380e732d27492ca (patch) | |
tree | a067064c2a3867c05289e520f7804f204fa286a4 /src | |
parent | 5e85036f34456506b03b98d5cdbf5afcb6a14302 (diff) |
vsmile: Fixed erroneous cartridge ROM mirroring. Gets V.Smile games to boot. Needs cleanup. [Ryan Holtz]
Diffstat (limited to 'src')
-rw-r--r-- | src/devices/cpu/unsp/unsp.cpp | 1311 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unsp.h | 34 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unspdasm.cpp | 550 | ||||
-rw-r--r-- | src/devices/cpu/unsp/unspdasm.h | 18 | ||||
-rw-r--r-- | src/devices/machine/spg2xx.cpp | 107 | ||||
-rw-r--r-- | src/devices/machine/spg2xx.h | 13 | ||||
-rw-r--r-- | src/mame/drivers/vii.cpp | 80 |
7 files changed, 1287 insertions, 826 deletions
diff --git a/src/devices/cpu/unsp/unsp.cpp b/src/devices/cpu/unsp/unsp.cpp index ca8b149fe5d..48e48ae16b0 100644 --- a/src/devices/cpu/unsp/unsp.cpp +++ b/src/devices/cpu/unsp/unsp.cpp @@ -1,10 +1,14 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz +// license:GPL-2.0+ +// copyright-holders:Segher Boessenkool,Ryan Holtz /***************************************************************************** - SunPlus micro'nSP core + SunPlus micro'nSP emulator - based primarily on Unununium, by segher + Copyright 2008-2017 Segher Boessenkool <segher@kernel.crashing.org> + Licensed under the terms of the GNU GPL, version 2 + http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt + + Ported to MAME framework by Ryan Holtz *****************************************************************************/ @@ -173,6 +177,20 @@ void unsp_device::state_import(const device_state_entry &entry) } } +static struct unsp_timer timer_tmb1 = { + .time = 0, + .interval = 27000000/8, + .index = 0, + .next = nullptr +}; + +static struct unsp_timer timer_tmb2 = { + .time = 0, + .interval = 27000000/128, + .index = 1, + .next = nullptr +}; + void unsp_device::device_reset() { memset(m_r, 0, sizeof(uint16_t) * 16); @@ -182,6 +200,10 @@ void unsp_device::device_reset() m_enable_fiq = false; m_irq = false; m_fiq = false; + + timers = nullptr; + timer_add(&timer_tmb1); + timer_add(&timer_tmb2); } /*****************************************************************************/ @@ -260,20 +282,60 @@ void unsp_device::trigger_irq(int line) UNSP_REG(SR) = 0; } +int unsp_device::get_irq() +{ + if (!m_enable_irq || m_irq) + return -1; + + // video + if (read16(0x2862) & read16(0x2863)) + return UNSP_IRQ0_LINE; + + const uint16_t enable = read16(0x3d21); + const uint16_t status = read16(0x3d22); + + // timerA, timerB + if (enable & status & 0x0c00) + return UNSP_IRQ2_LINE; + + // UART, ADC XXX: also SPI + if (enable & status & 0x2100) + return UNSP_IRQ3_LINE; + + // XXX audio, IRQ4 + + // extint1, extint2 + if (enable & status & 0x1200) + return UNSP_IRQ5_LINE; + + // 1024Hz, 2048HZ, 4096HZ + if (enable & status & 0x0070) + return UNSP_IRQ6_LINE; + + // TMB1, TMB2, 4Hz, key change + if (enable & status & 0x008b) + return UNSP_IRQ7_LINE; + + return -1; +} + void unsp_device::check_irqs() { - if (!m_sirq) - return; + //if (!m_sirq) + //return; - int highest_irq = -1; - for (int i = 0; i <= 8; i++) + int highest_irq = get_irq(); + /*if (highest_irq == -1) { - if (BIT(m_sirq, i)) + for (int i = 0; i <= 8; i++) { - highest_irq = i; - break; + if (BIT(m_sirq, i)) + { + highest_irq = i; + break; + } } - } + }*/ if (highest_irq < 0) return; @@ -285,606 +347,761 @@ void unsp_device::check_irqs() } else { - //logerror("Trying to trigger IRQ\n"); + //printf("Trying to trigger IRQ%d\n", highest_irq - 1); trigger_irq(highest_irq - 1); } } -void unsp_device::execute_run() +void unsp_device::add_lpc(const int32_t offset) { -#if UNSP_LOG_OPCODES - unsp_disassembler dasm; -#endif + const uint32_t new_lpc = UNSP_LPC + offset; + UNSP_REG(PC) = (uint16_t)new_lpc; + UNSP_REG(SR) &= 0xffc0; + UNSP_REG(SR) |= (new_lpc >> 16) & 0x3f; +} +static const int32_t cycles_per_line = 1728; +static uint32_t cycle_count = 0; +static int32_t lines_per_frame = 312; +static int32_t line_count = 0; + +inline void unsp_device::execute_one(const uint16_t op) +{ uint32_t lres = 0; uint16_t r0 = 0; uint16_t r1 = 0; uint32_t r2 = 0; - while (m_icount > 0) - { - check_irqs(); - - debugger_instruction_hook(UNSP_LPC); - const uint32_t op = read16(UNSP_LPC); + const uint8_t lower_op = (OP1 << 4) | OP0; -#if UNSP_LOG_OPCODES - if (m_log_ops) + if(OP0 < 0xf && OPA == 0x7 && OP1 < 2) + { + switch(OP0) { - std::stringstream strbuffer; - dasm.disassemble(strbuffer, UNSP_LPC, op, read16(UNSP_LPC+1)); - logerror("%06x: %s\n", UNSP_LPC, strbuffer.str().c_str()); + case 0: // JB + if(!(UNSP_REG(SR) & UNSP_C)) + { + m_icount -= 4; + cycle_count += 4; + add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM)); + } + else + { + m_icount -= 2; + cycle_count += 2; + } + return; + case 1: // JAE + if(UNSP_REG(SR) & UNSP_C) + { + m_icount -= 4; + cycle_count += 4; + add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM)); + } + else + { + m_icount -= 2; + cycle_count += 2; + } + return; + case 2: // JGE + if(!(UNSP_REG(SR) & UNSP_S)) + { + m_icount -= 4; + cycle_count += 4; + add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM)); + } + else + { + m_icount -= 2; + cycle_count += 2; + } + return; + case 3: // JL + if(UNSP_REG(SR) & UNSP_S) + { + m_icount -= 4; + cycle_count += 4; + add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM)); + } + else + { + m_icount -= 2; + cycle_count += 2; + } + return; + case 4: // JNE + if(!(UNSP_REG(SR) & UNSP_Z)) + { + m_icount -= 4; + cycle_count += 4; + add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM)); + } + else + { + m_icount -= 2; + cycle_count += 2; + } + return; + case 5: // JE + if(UNSP_REG(SR) & UNSP_Z) + { + m_icount -= 4; + cycle_count += 4; + add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM)); + } + else + { + m_icount -= 2; + cycle_count += 2; + } + return; + case 6: // JPL + if(!(UNSP_REG(SR) & UNSP_N)) + { + m_icount -= 4; + cycle_count += 4; + add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM)); + } + else + { + m_icount -= 2; + cycle_count += 2; + } + return; + case 7: // JMI + if(UNSP_REG(SR) & UNSP_N) + { + m_icount -= 4; + cycle_count += 4; + add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM)); + } + else + { + m_icount -= 2; + cycle_count += 2; + } + return; + case 8: // JBE + if((UNSP_REG(SR) & (UNSP_Z | UNSP_C)) != UNSP_C) + { + m_icount -= 4; + cycle_count += 4; + add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM)); + } + else + { + m_icount -= 2; + cycle_count += 2; + } + return; + case 9: // JA + if((UNSP_REG(SR) & (UNSP_Z | UNSP_C)) == UNSP_C) + { + m_icount -= 4; + cycle_count += 4; + add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM)); + } + else + { + m_icount -= 2; + cycle_count += 2; + } + return; + case 10: // JLE + if(UNSP_REG(SR) & (UNSP_Z | UNSP_S)) + { + m_icount -= 4; + cycle_count += 4; + add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM)); + } + else + { + m_icount -= 2; + cycle_count += 2; + } + return; + case 11: // JG + if(!(UNSP_REG(SR) & (UNSP_Z | UNSP_S))) + { + m_icount -= 4; + cycle_count += 4; + add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM)); + } + else + { + m_icount -= 2; + cycle_count += 2; + } + return; + case 14: // JMP + add_lpc((OP1 == 0) ? OPIMM : (0 - OPIMM)); + m_icount -= 4; + cycle_count += 4; + return; + default: + unimplemented_opcode(op); + return; } -#endif - - UNSP_REG(PC)++; - - const uint8_t lower_op = (OP1 << 4) | OP0; + } + else if (lower_op == 0x2d) // Push + { + r0 = OPN; + r1 = OPA; + m_icount -= 4 + 2 * r0; + cycle_count += 4 + 2 * r0; - if(OP0 < 0xf && OPA == 0x7 && OP1 < 2) + while (r0--) { - switch(OP0) + push(UNSP_REG_I(r1--), &UNSP_REG_I(OPB)); + } + return; + } + else if (lower_op == 0x29) // Pop + { + if (op == 0x9a98) // reti + { + m_icount -= 8; + cycle_count += 8; + UNSP_REG(SR) = pop(&UNSP_REG(SP)); + UNSP_REG(PC) = pop(&UNSP_REG(SP)); + + if(m_fiq) { - case 0: // JB - if(!(UNSP_REG(SR) & UNSP_C)) - { - m_icount -= 4; - UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM); - } - else - m_icount -= 2; - continue; - case 1: // JAE - if(UNSP_REG(SR) & UNSP_C) - { - m_icount -= 4; - UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM); - } - else - m_icount -= 2; - continue; - case 2: // JGE - if(!(UNSP_REG(SR) & UNSP_S)) - { - m_icount -= 4; - UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM); - } - else - m_icount -= 2; - continue; - case 3: // JL - if(UNSP_REG(SR) & UNSP_S) - { - m_icount -= 4; - UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM); - } - else - m_icount -= 2; - continue; - case 4: // JNE - if(!(UNSP_REG(SR) & UNSP_Z)) - { - m_icount -= 4; - UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM); - } - else - m_icount -= 2; - continue; - case 5: // JE - if(UNSP_REG(SR) & UNSP_Z) - { - m_icount -= 4; - UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM); - } - else - m_icount -= 2; - continue; - case 6: // JPL - if(!(UNSP_REG(SR) & UNSP_N)) - { - m_icount -= 4; - UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM); - } - else - m_icount -= 2; - continue; - case 7: // JMI - if(UNSP_REG(SR) & UNSP_N) - { - m_icount -= 4; - UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM); - } - else - m_icount -= 2; - continue; - case 8: // JBE - if((UNSP_REG(SR) & (UNSP_Z | UNSP_C)) != UNSP_C) - { - m_icount -= 4; - UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM); - } - else - m_icount -= 2; - continue; - case 9: // JA - if((UNSP_REG(SR) & (UNSP_Z | UNSP_C)) == UNSP_C) - { - m_icount -= 4; - UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM); - } - else - m_icount -= 2; - continue; - case 10: // JLE - if(UNSP_REG(SR) & (UNSP_Z | UNSP_S)) - { - m_icount -= 4; - UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM); - } - else - m_icount -= 2; - continue; - case 11: // JG - if(!(UNSP_REG(SR) & (UNSP_Z | UNSP_S))) - { - m_icount -= 4; - UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM); - } - else - m_icount -= 2; - continue; - case 14: // JMP - UNSP_REG(PC) += (OP1 == 0) ? OPIMM : (0 - OPIMM); - m_icount -= 4; - continue; - default: - unimplemented_opcode(op); - continue; + m_fiq = false; + m_saved_sb[2] = m_sb; + m_sb = m_saved_sb[m_irq ? 1 : 0]; } + else if(m_irq) + { + m_irq = false; + m_saved_sb[1] = m_sb; + m_sb = m_saved_sb[0]; + } + m_curirq = 0; + + check_irqs(); + return; } - else if (lower_op == 0x2d) // Push + else { r0 = OPN; r1 = OPA; m_icount -= 4 + 2 * r0; + cycle_count += 4 + 2 * r0; while (r0--) { - push(UNSP_REG_I(r1--), &UNSP_REG_I(OPB)); + UNSP_REG_I(++r1) = pop(&UNSP_REG_I(OPB)); } - continue; + return; } - else if (lower_op == 0x29) // Pop + } + else if (OP0 == 0xf) + { + switch (OP1) { - if (op == 0x9a98) // reti - { - m_icount -= 8; - UNSP_REG(SR) = pop(&UNSP_REG(SP)); - UNSP_REG(PC) = pop(&UNSP_REG(SP)); - - if(m_fiq) + case 0x00: // Multiply, Unsigned * Signed + if(OPN == 1 && OPA != 7) { - m_fiq = false; - m_saved_sb[2] = m_sb; - m_sb = m_saved_sb[m_irq ? 1 : 0]; + m_icount -= 12; + cycle_count += 12; + lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB); + if(UNSP_REG_I(OPB) & 0x8000) + { + lres -= UNSP_REG_I(OPA) << 16; + } + UNSP_REG(R4) = lres >> 16; + UNSP_REG(R3) = (uint16_t)lres; } - else if(m_irq) + else { - m_irq = false; - m_saved_sb[1] = m_sb; - m_sb = m_saved_sb[0]; + unimplemented_opcode(op); } - m_curirq = 0; + return; - check_irqs(); - continue; - } - else - { - r0 = OPN; - r1 = OPA; - m_icount -= 4 + 2 * r0; - - while (r0--) + case 0x01: // Call + if(!(OPA & 1)) { - UNSP_REG_I(++r1) = pop(&UNSP_REG_I(OPB)); + m_icount -= 9; + cycle_count += 9; + r1 = read16(UNSP_LPC); + add_lpc(1); + push(UNSP_REG(PC), &UNSP_REG(SP)); + push(UNSP_REG(SR), &UNSP_REG(SP)); + UNSP_REG(PC) = r1; + UNSP_REG(SR) &= 0xffc0; + UNSP_REG(SR) |= OPIMM; } - continue; - } - } - else if (OP0 == 0xf) - { - switch (OP1) - { - case 0x00: // Multiply, Unsigned * Signed - if(OPN == 1 && OPA != 7) - { - m_icount -= 12; - lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB); - if(UNSP_REG_I(OPB) & 0x8000) - { - lres -= UNSP_REG_I(OPA) << 16; - } - UNSP_REG(R4) = lres >> 16; - UNSP_REG(R3) = (uint16_t)lres; - } - else - { - unimplemented_opcode(op); - } - continue; + else + { + unimplemented_opcode(op); + } + return; - case 0x01: // Call - if(!(OPA & 1)) - { - m_icount -= 9; - r1 = read16(UNSP_LPC); - UNSP_REG(PC)++; - push(UNSP_REG(PC), &UNSP_REG(SP)); - push(UNSP_REG(SR), &UNSP_REG(SP)); - UNSP_REG(PC) = r1; - UNSP_REG(SR) &= 0xffc0; - UNSP_REG(SR) |= OPIMM; - } - else - { - unimplemented_opcode(op); - } - continue; + case 0x02: // Far Jump + if (OPA == 7) + { + m_icount -= 5; + cycle_count += 5; + UNSP_REG(PC) = read16(UNSP_LPC); + UNSP_REG(SR) &= 0xffc0; + UNSP_REG(SR) |= OPIMM; + } + else + { + unimplemented_opcode(op); + } + return; - case 0x02: // Far Jump - if (OPA == 7) + case 0x04: // Multiply, Signed * Signed + if(OPN == 1 && OPA != 7) + { + m_icount -= 12; + cycle_count += 12; + lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB); + if(UNSP_REG_I(OPB) & 0x8000) { - m_icount -= 5; - UNSP_REG(PC) = read16(UNSP_LPC); - UNSP_REG(SR) &= 0xffc0; - UNSP_REG(SR) |= OPIMM; + lres -= UNSP_REG_I(OPA) << 16; } - else + if(UNSP_REG_I(OPA) & 0x8000) { - unimplemented_opcode(op); + lres -= UNSP_REG_I(OPB) << 16; } - continue; + UNSP_REG(R4) = lres >> 16; + UNSP_REG(R3) = (uint16_t)lres; + } + else + { + unimplemented_opcode(op); + } + return; - case 0x04: // Multiply, Signed * Signed - if(OPN == 1 && OPA != 7) - { - m_icount -= 12; - lres = UNSP_REG_I(OPA) * UNSP_REG_I(OPB); - if(UNSP_REG_I(OPB) & 0x8000) - { - lres -= UNSP_REG_I(OPA) << 16; - } - if(UNSP_REG_I(OPA) & 0x8000) - { - lres -= UNSP_REG_I(OPB) << 16; - } - UNSP_REG(R4) = lres >> 16; - UNSP_REG(R3) = (uint16_t)lres; - } - else - { + case 0x05: // Interrupt flags + m_icount -= 2; + cycle_count += 2; + switch(OPIMM) + { + case 0: + m_enable_irq = false; + m_enable_fiq = false; + break; + case 1: + m_enable_irq = true; + m_enable_fiq = false; + break; + case 2: + m_enable_irq = false; + m_enable_fiq = true; + break; + case 3: + m_enable_irq = true; + m_enable_fiq = true; + break; + case 8: // irq off + m_enable_irq = false; + break; + case 9: // irq on + m_enable_irq = true; + break; + case 12: // fiq off + m_enable_fiq = false; + break; + case 14: // fiq on + m_enable_fiq = true; + break; + case 37: // nop + break; + default: unimplemented_opcode(op); - } - continue; - - case 0x05: // Interrupt flags - m_icount -= 2; - switch(OPIMM) - { - case 0: - m_enable_irq = false; - m_enable_fiq = false; - break; - case 1: - m_enable_irq = true; - m_enable_fiq = false; - break; - case 2: - m_enable_irq = false; - m_enable_fiq = true; - break; - case 3: - m_enable_irq = true; - m_enable_fiq = true; - break; - case 8: // irq off - m_enable_irq = false; - break; - case 9: // irq on - m_enable_irq = true; - break; - case 12: // fiq off - m_enable_fiq = false; - break; - case 14: // fiq on - m_enable_fiq = true; - break; - case 37: // nop - break; - default: - unimplemented_opcode(op); - break; - } - continue; + break; + } + return; - default: - unimplemented_opcode(op); - continue; - } + default: + unimplemented_opcode(op); + return; } + } - // At this point, we should be dealing solely with ALU ops. + // At this point, we should be dealing solely with ALU ops. - r0 = UNSP_REG_I(OPA); + r0 = UNSP_REG_I(OPA); - switch (OP1) - { - case 0x00: // r, [bp+imm6] - m_icount -= 6; + switch (OP1) + { + case 0x00: // r, [bp+imm6] + m_icount -= 6; + cycle_count += 6; - r2 = (uint16_t)(UNSP_REG(BP) + OPIMM); - if (OP0 != 0x0d) - r1 = read16(r2); - break; + r2 = (uint16_t)(UNSP_REG(BP) + OPIMM); + if (OP0 != 0x0d) + r1 = read16(r2); + break; - case 0x01: // r, imm6 - m_icount -= 2; + case 0x01: // r, imm6 + m_icount -= 2; + cycle_count += 2; - r1 = OPIMM; - break; + r1 = OPIMM; + break; - case 0x03: // Indirect + case 0x03: // Indirect + { + m_icount -= 6; + cycle_count += 6; + if (OPA == 7) { - m_icount -= 6; - if (OPA == 7) - m_icount -= 1; + m_icount -= 1; + cycle_count += 1; + } - const uint8_t lsbits = OPN & 3; - const uint8_t opb = OPB; - if (OPN & 4) - { - switch (lsbits) - { - case 0: // r, [r] - r2 = UNSP_LREG_I(opb); - if (OP0 != 0x0d) - r1 = read16(r2); - break; - case 1: // r, [<ds:>r--] - r2 = UNSP_LREG_I(opb); - if (OP0 != 0x0d) - r1 = read16(r2); - UNSP_REG_I(opb)--; - if (UNSP_REG_I(opb) == 0xffff) - UNSP_REG(SR) -= 0x0400; - break; - case 2: // r, [<ds:>r++] - r2 = UNSP_LREG_I(opb); - if (OP0 != 0x0d) - r1 = read16(r2); - UNSP_REG_I(opb)++; - if (UNSP_REG_I(opb) == 0x0000) - UNSP_REG(SR) += 0x0400; - break; - case 3: // r, [<ds:>++r] - UNSP_REG_I(opb)++; - if (UNSP_REG_I(opb) == 0x0000) - UNSP_REG(SR) += 0x0400; - r2 = UNSP_LREG_I(opb); - if (OP0 != 0x0d) - r1 = read16(r2); - break; - default: - break; - } - } - else + const uint8_t lsbits = OPN & 3; + const uint8_t opb = OPB; + if (OPN & 4) + { + switch (lsbits) { - switch (lsbits) - { - case 0: // r, [r] - r2 = UNSP_REG_I(opb); - if (OP0 != 0x0d) - r1 = read16(r2); - break; - case 1: // r, [r--] - r2 = UNSP_REG_I(opb); - if (OP0 != 0x0d) - r1 = read16(r2); - UNSP_REG_I(opb)--; - break; - case 2: // r, [r++] - r2 = UNSP_REG_I(opb); - if (OP0 != 0x0d) - r1 = read16(r2); - UNSP_REG_I(opb)++; - break; - case 3: // r, [++r] - UNSP_REG_I(opb)++; - r2 = UNSP_REG_I(opb); - if (OP0 != 0x0d) - r1 = read16(r2); - break; - default: - break; - } + case 0: // r, [r] + r2 = UNSP_LREG_I(opb); + if (OP0 != 0x0d) + r1 = read16(r2); + break; + case 1: // r, [<ds:>r--] + r2 = UNSP_LREG_I(opb); + if (OP0 != 0x0d) + r1 = read16(r2); + UNSP_REG_I(opb)--; + if (UNSP_REG_I(opb) == 0xffff) + UNSP_REG(SR) -= 0x0400; + break; + case 2: // r, [<ds:>r++] + r2 = UNSP_LREG_I(opb); + if (OP0 != 0x0d) + r1 = read16(r2); + UNSP_REG_I(opb)++; + if (UNSP_REG_I(opb) == 0x0000) + UNSP_REG(SR) += 0x0400; + break; + case 3: // r, [<ds:>++r] + UNSP_REG_I(opb)++; + if (UNSP_REG_I(opb) == 0x0000) + UNSP_REG(SR) += 0x0400; + r2 = UNSP_LREG_I(opb); + if (OP0 != 0x0d) + r1 = read16(r2); + break; + default: + break; } - break; } - - case 0x04: // 16-bit ops - switch (OPN) + else + { + switch (lsbits) { - case 0x00: // r - m_icount -= 3; - if (OPA == 7) - m_icount -= 2; - - r1 = UNSP_REG_I(OPB); + case 0: // r, [r] + r2 = UNSP_REG_I(opb); + if (OP0 != 0x0d) + r1 = read16(r2); + break; + case 1: // r, [r--] + r2 = UNSP_REG_I(opb); + if (OP0 != 0x0d) + r1 = read16(r2); + UNSP_REG_I(opb)--; + break; + case 2: // r, [r++] + r2 = UNSP_REG_I(opb); + if (OP0 != 0x0d) + r1 = read16(r2); + UNSP_REG_I(opb)++; + break; + case 3: // r, [++r] + UNSP_REG_I(opb)++; + r2 = UNSP_REG_I(opb); + if (OP0 != 0x0d) + r1 = read16(r2); break; + default: + break; + } + } + break; + } - case 0x01: // imm16 - m_icount -= 4; - if (OPA == 7) - m_icount -= 1; + case 0x04: // 16-bit ops + switch (OPN) + { + case 0x00: // r + m_icount -= 3; + cycle_count += 3; + if (OPA == 7) + { + m_icount -= 2; + cycle_count += 2; + } - r0 = UNSP_REG_I(OPB); - r1 = read16(UNSP_LPC); - UNSP_REG(PC)++; - break; + r1 = UNSP_REG_I(OPB); + break; - case 0x02: // [imm16] - m_icount -= 7; - if (OPA == 7) - m_icount -= 1; + case 0x01: // imm16 + m_icount -= 4; + cycle_count += 4; + if (OPA == 7) + { + m_icount -= 1; + cycle_count += 1; + } - r0 = UNSP_REG_I(OPB); - r2 = read16(UNSP_LPC); - UNSP_REG(PC)++; + r0 = UNSP_REG_I(OPB); + r1 = read16(UNSP_LPC); + add_lpc(1); + break; - if (OP0 != 0x0d) - { - r1 = read16(r2); - } - break; + case 0x02: // [imm16] + m_icount -= 7; + cycle_count += 7; + if (OPA == 7) + { + m_icount -= 1; + cycle_count += 1; + } - case 0x03: // store [imm16], r - m_icount -= 7; - if (OPA == 7) - m_icount -= 1; + r0 = UNSP_REG_I(OPB); + r2 = read16(UNSP_LPC); + add_lpc(1); - r1 = r0; - r0 = UNSP_REG_I(OPB); - r2 = read16(UNSP_LPC); - UNSP_REG(PC)++; - break; + if (OP0 != 0x0d) + { + r1 = read16(r2); + } + break; - default: // Shifted ops + case 0x03: // store [imm16], r + m_icount -= 7; + cycle_count += 7; + if (OPA == 7) { - m_icount -= 3; - if (OPA == 7) - m_icount -= 2; - - uint32_t shift = (UNSP_REG_I(OPB) << 4) | m_sb; - if (shift & 0x80000) - shift |= 0xf00000; - shift >>= (OPN - 3); - m_sb = shift & 0x0f; - r1 = (uint16_t)(shift >> 4); - break; + m_icount -= 1; + cycle_count += 1; } - } - break; - case 0x05: // More shifted ops - m_icount -= 3; - if (OPA == 7) - m_icount -= 2; + r1 = r0; + r0 = UNSP_REG_I(OPB); + r2 = read16(UNSP_LPC); + add_lpc(1); + break; - if (OPN & 4) // Shift right + default: // Shifted ops { - const uint32_t shift = ((UNSP_REG_I(OPB) << 4) | m_sb) >> (OPN - 3); + m_icount -= 3; + cycle_count += 3; + if (OPA == 7) + { + m_icount -= 2; + cycle_count += 2; + } + + uint32_t shift = (UNSP_REG_I(OPB) << 4) | m_sb; + if (shift & 0x80000) + shift |= 0xf00000; + shift >>= (OPN - 3); m_sb = shift & 0x0f; r1 = (uint16_t)(shift >> 4); + break; } - else // Shift left - { - const uint32_t shift = ((m_sb << 16) | UNSP_REG_I(OPB)) << (OPN + 1); - m_sb = (shift >> 16) & 0x0f; - r1 = (uint16_t)shift; - } - break; + } + break; - case 0x06: // Rotated ops + case 0x05: // More shifted ops + m_icount -= 3; + cycle_count += 3; + if (OPA == 7) { - m_icount -= 3; - if (OPA == 7) - m_icount -= 2; + m_icount -= 2; + cycle_count += 2; + } - uint32_t shift = (((m_sb << 16) | UNSP_REG_I(OPB)) << 4) | m_sb; - if (OPN & 4) // Rotate right - { - shift >>= (OPN - 3); - m_sb = shift & 0x0f; - } - else - { - shift <<= (OPN + 1); - m_sb = (shift >> 20) & 0x0f; - } + if (OPN & 4) // Shift right + { + const uint32_t shift = ((UNSP_REG_I(OPB) << 4) | m_sb) >> (OPN - 3); + m_sb = shift & 0x0f; r1 = (uint16_t)(shift >> 4); - break; } + else // Shift left + { + const uint32_t shift = ((m_sb << 16) | UNSP_REG_I(OPB)) << (OPN + 1); + m_sb = (shift >> 16) & 0x0f; + r1 = (uint16_t)shift; + } + break; - case 0x07: // Direct 8 - m_icount -= 5; - if (OPA == 7) - m_icount -= 1; - - r1 = read16(OPIMM); - break; + case 0x06: // Rotated ops + { + m_icount -= 3; + cycle_count += 3; + if (OPA == 7) + { + m_icount -= 2; + cycle_count += 2; + } - default: - break; + uint32_t shift = (((m_sb << 16) | UNSP_REG_I(OPB)) << 4) | m_sb; + if (OPN & 4) // Rotate right + { + shift >>= (OPN - 3); + m_sb = shift & 0x0f; + } + else + { + shift <<= (OPN + 1); + m_sb = (shift >> 20) & 0x0f; + } + r1 = (uint16_t)(shift >> 4); + break; } - switch (OP0) + case 0x07: // Direct 8 + m_icount -= 5; + cycle_count += 5; + if (OPA == 7) + { + m_icount -= 1; + cycle_count += 1; + } + + r2 = OPIMM; + r1 = read16(OPIMM); + break; + + default: + break; + } + + switch (OP0) + { + case 0x00: // Add + lres = r0 + r1; + break; + case 0x01: // Add w/ carry + lres = r0 + r1; + if(UNSP_REG(SR) & UNSP_C) + lres++; + break; + case 0x02: // Subtract + case 0x04: // Compare + lres = r0 + (uint16_t)(~r1) + 1; + break; + case 0x03: // Subtract w/ carry + lres = r0 + (uint16_t)(~r1); + if(UNSP_REG(SR) & UNSP_C) + lres++; + break; + case 0x06: // Negate + lres = -r1; + break; + case 0x08: // XOR + lres = r0 ^ r1; + break; + case 0x09: // Load + lres = r1; + break; + case 0x0a: // OR + lres = r0 | r1; + break; + case 0x0b: // AND + case 0x0c: // Test + lres = r0 & r1; + break; + case 0x0d: // Store + write16(r2, r0); + return; + default: + unimplemented_opcode(op); + return; + } + + if (OP0 != 0x0d && OPA != 7) // If not a store opcode and not updating the PC, update negative/zero flags. + { + update_nz(lres); + } + + if (OP0 < 0x05 && OPA != 7) // If Add, Add w/ Carry, Subtract, Subtract w/ Carry, Compare, and not updating the PC, update sign/carry flags. + update_sc(lres, r0, r1); + + if (OP0 == 0x04 || OP0 == 0x0c) // Compare and Test don't write back results. + return; + + if (OP1 == 0x04 && OPN == 0x03) // store [imm16], r + write16(r2, lres); + else + UNSP_REG_I(OPA) = lres; +} + +void unsp_device::execute_run() +{ +#if UNSP_LOG_OPCODES + unsp_disassembler dasm; +#endif + + while (m_icount > 0) + { + debugger_instruction_hook(UNSP_LPC); + const uint32_t op = read16(UNSP_LPC); + +#if UNSP_LOG_OPCODES + if (m_log_ops) { - case 0x00: // Add - lres = r0 + r1; - break; - case 0x01: // Add w/ carry - lres = r0 + r1; - if(UNSP_REG(SR) & UNSP_C) - lres++; - break; - case 0x02: // Subtract - case 0x04: // Compare - lres = r0 + (uint16_t)(~r1) + 1; - break; - case 0x03: // Subtract w/ carry - lres = r0 + (uint16_t)(~r1); - if(UNSP_REG(SR) & UNSP_C) - lres++; - break; - case 0x06: // Negate - lres = -r1; - break; - case 0x08: // XOR - lres = r0 ^ r1; - break; - case 0x09: // Load - lres = r1; - break; - case 0x0a: // OR - lres = r0 | r1; - break; - case 0x0b: // AND - case 0x0c: // Test - lres = r0 & r1; - break; - case 0x0d: // Store - write16(r2, r0); - continue; - default: - unimplemented_opcode(op); - continue; + std::stringstream strbuffer; + dasm.disassemble(strbuffer, UNSP_LPC, op, read16(UNSP_LPC+1)); + uint32_t len = 1; + if ((OP0 < 14 && OP1 == 4 && (OPN == 1 || OPN == 2 || OPN == 3)) || (OP0 == 15 && (OP1 == 1 || OP1 == 2))) + { + len = 2; + } + if (len == 1) + { + logerror("%04x %04x %04x %04x %04x %04x %04x %04x %02x %x%x%x%x %02x %x %x %d %x: %04x %x %x %x %x %x %s\n", + m_r[0], m_r[1], m_r[2], m_r[3], m_r[4], m_r[5], m_r[6], m_r[7], + m_r[6] & 0x3f, BIT(m_r[6], 9), BIT(m_r[6], 8), BIT(m_r[6], 7), BIT(m_r[6], 6), (m_r[6] >> 10) & 0x3f, + m_sb, m_enable_irq ? 1 : 0, cycle_count, UNSP_LPC, op, OP0, OPA, OP1, OPN, OPB, strbuffer.str().c_str()); + } + else + { + logerror("%04x %04x %04x %04x %04x %04x %04x %04x %02x %x%x%x%x %02x %x %x %d %x: %04x %04x %x %x %x %x %x %s\n", + m_r[0], m_r[1], m_r[2], m_r[3], m_r[4], m_r[5], m_r[6], m_r[7], + m_r[6] & 0x3f, BIT(m_r[6], 9), BIT(m_r[6], 8), BIT(m_r[6], 7), BIT(m_r[6], 6), (m_r[6] >> 10) & 0x3f, + m_sb, m_enable_irq ? 1 : 0, cycle_count, UNSP_LPC, op, read16(UNSP_LPC+1), OP0, OPA, OP1, OPN, OPB, strbuffer.str().c_str()); + } + //logerror("%x: %s\n", UNSP_LPC, strbuffer.str().c_str()); + //logerror("%x%04x: %d\n", UNSP_REG(SR) & 0x3f, UNSP_REG(PC), cycle_count); } +#endif - if (OP0 != 0x0d && OPA != 7) // If not a store opcode and not updating the PC, update negative/zero flags. - update_nz(lres); + add_lpc(1); - if (OP0 < 0x05 && OPA != 7) // If Add, Add w/ Carry, Subtract, Subtract w/ Carry, Compare, and not updating the PC, update sign/carry flags. - update_sc(lres, r0, r1); + execute_one(op); - if (OP0 == 0x04 || OP0 == 0x0c) // Compare and Test don't write back results. - continue; + if (cycle_count >= cycles_per_line) + { + cycle_count -= cycles_per_line; - if (OP1 == 0x04 && OPN == 0x03) // store [imm16], r - write16(r2, lres); - else - UNSP_REG_I(OPA) = lres; + timer_run(cycles_per_line); + + if (line_count == 240) + write16(0x3d61, 1); // trigger vblank IRQ + if (line_count == read16(0x2836)) + write16(0x3d61, 2); // trigger vpos IRQ + + check_irqs(); + + line_count++; + if (line_count == lines_per_frame) + { + line_count = 0; + write16(0x3d60, 0x0100); + } + } } } @@ -917,3 +1134,55 @@ void unsp_device::execute_set_input(int irqline, int state) break; } } + +void unsp_device::set_timer_interval(int timer, uint32_t interval) +{ + if (timer == 0) + timer_tmb1.interval = interval; + else if (timer == 1) + timer_tmb2.interval = interval; +} + +void unsp_device::timer_add(struct unsp_timer *timer) +{ + if (timer->time == 0) + timer->time = timer->interval; + + uint32_t time = timer->time; + struct unsp_timer **p = &timers; + + while (*p && (*p)->time <= time) { + time -= (*p)->time; + p = &(*p)->next; + } + + timer->next = *p; + *p = timer; + timer->time = time; + if (timer->next) + timer->next->time -= time; +} + +void unsp_device::timer_run(uint32_t ticks) +{ + struct unsp_timer *timer; + while ((timer = timers) && timer->time <= ticks) { + timers = timer->next; + ticks -= timer->time; + + write16(0x3d62, 1 << timer->index); + + if (timer->interval) { + timer->time = timer->interval; + timer_add(timer); + } + } + + if (timer) + timer->time -= ticks; +} + +uint16_t unsp_device::get_video_line() +{ + return line_count; +} diff --git a/src/devices/cpu/unsp/unsp.h b/src/devices/cpu/unsp/unsp.h index cd939aeb25e..2ff18871a8f 100644 --- a/src/devices/cpu/unsp/unsp.h +++ b/src/devices/cpu/unsp/unsp.h @@ -1,10 +1,14 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz +// license:GPL-2.0+ +// copyright-holders:Segher Boessenkool,Ryan Holtz /***************************************************************************** - SunPlus micro'nSP core + SunPlus micro'nSP emulator - based primarily on Unununium, by segher + Copyright 2008-2017 Segher Boessenkool <segher@kernel.crashing.org> + Licensed under the terms of the GNU GPL, version 2 + http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt + + Ported to MAME framework by Ryan Holtz *****************************************************************************/ @@ -13,7 +17,7 @@ #pragma once -#define UNSP_LOG_OPCODES (0) +#define UNSP_LOG_OPCODES (1) enum { @@ -56,6 +60,13 @@ enum UNSP_NUM_LINES }; +struct unsp_timer +{ + uint32_t time; + uint32_t interval; + int index; + struct unsp_timer *next; +}; class unsp_device : public cpu_device { @@ -63,6 +74,10 @@ public: // construction/destruction unsp_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + void set_timer_interval(int timer, uint32_t interval); + + uint16_t get_video_line(); + protected: // device-level overrides virtual void device_start() override; @@ -87,8 +102,15 @@ protected: virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; private: + void add_lpc(const int32_t offset); + + inline void execute_one(const uint16_t op); + address_space_config m_program_config; + void timer_add(struct unsp_timer *timer); + void timer_run(uint32_t ticks); + uint16_t m_r[16]; bool m_enable_irq; bool m_enable_fiq; @@ -98,6 +120,7 @@ private: uint16_t m_sirq; uint8_t m_sb; uint8_t m_saved_sb[3]; + struct unsp_timer *timers; address_space *m_program; int m_icount; @@ -117,6 +140,7 @@ private: inline void trigger_fiq(); inline void trigger_irq(int line); inline void check_irqs(); + inline int get_irq(); }; diff --git a/src/devices/cpu/unsp/unspdasm.cpp b/src/devices/cpu/unsp/unspdasm.cpp index 14996cbbf2a..ad67ce9d17e 100644 --- a/src/devices/cpu/unsp/unspdasm.cpp +++ b/src/devices/cpu/unsp/unspdasm.cpp @@ -1,257 +1,435 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz +// license:GPL-2.0+ +// copyright-holders:Segher Boessenkool /***************************************************************************** SunPlus micro'nSP disassembler + Copyright 2008-2017 Segher Boessenkool <segher@kernel.crashing.org> + Licensed under the terms of the GNU GPL, version 2 + http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt + *****************************************************************************/ #include "emu.h" #include "unspdasm.h" -char const *const unsp_disassembler::reg[] = +char const *const unsp_disassembler::regs[] = { "sp", "r1", "r2", "r3", "r4", "bp", "sr", "pc" }; -char const *const unsp_disassembler::jmp[] = +char const *const unsp_disassembler::jumps[] = { "jb", "jae", "jge", "jl", "jne", "je", "jpl", "jmi", "jbe", "ja", "jle", "jg", "jvc", "jvs", "jmp", "<inv>" }; -char const *const unsp_disassembler::alu[] = +#define UNSP_DASM_OK (len | SUPPORTED) + +u32 unsp_disassembler::opcode_alignment() const { - "add", "adc", "sub", "sbc", - "cmp", "<inv>", "neg", "<inv>", - "xor", "load", "or", "and", - "test", "store", "<inv>", "<inv>" -}; + return 1; +} -/*****************************************************************************/ +void unsp_disassembler::print_alu_op_start(std::ostream &stream, uint8_t op0, uint8_t opA) +{ + static const char* const alu_op_start[] = + { + "%s += ", "%s += ", "%s -= ", "%s -= ", + "cmp %s, ", "<BAD>", "%s =- ", "<BAD>", + "%s ^= ", "%s = ", "%s |= ", "%s &= ", + "test %s, " + }; -#define OP0 (op >> 12) -#define OPA ((op >> 9) & 7) -#define OP1 ((op >> 6) & 7) -#define OPN ((op >> 3) & 7) -#define OPB (op & 7) -#define OPIMM (op & 0x3f) -#define OP2X ((OP0 < 14 && OP1 == 4 && (OPN >= 1 && OPN <= 3)) || (OP0 == 15 && (OP1 == 1 || OP1 == 2))) + util::stream_format(stream, alu_op_start[op0], regs[opA]); +} -/*****************************************************************************/ +void unsp_disassembler::print_alu_op3(std::ostream &stream, uint8_t op0, uint8_t opB) +{ + static const char* const alu_op3[] = + { + "%s + ", "%s + ", "%s - ", "%s - ", + "cmp %s, ", "<BAD>", "-", "<BAD>", + "%s ^ ", "", "%s | ", "%s & ", + "test %s, " + }; -#define UNSP_DASM_OK ((OP2X ? 2 : 1) | SUPPORTED) + util::stream_format(stream, alu_op3[op0], regs[opB]); +} -u32 unsp_disassembler::opcode_alignment() const +void unsp_disassembler::print_alu_op_end(std::ostream &stream, uint8_t op0) { - return 1; + if (op0 == 1 || op0 == 3) + util::stream_format(stream, ", carry"); } -offs_t unsp_disassembler::disassemble(std::ostream &stream, offs_t pc, uint16_t op, uint16_t imm16) +void unsp_disassembler::print_indirect_op(std::ostream &stream, uint8_t opN, uint8_t opB) { - if(OP0 < 0xf && OPA == 0x7 && OP1 < 2) + static const char* const forms[] = { "[%s]", "[%s--]", "[%s++]", "[++%s]" }; + + if (opN & 4) + util::stream_format(stream, "ds:"); + util::stream_format(stream, forms[opN & 3], regs[opB]); +} + +offs_t unsp_disassembler::disassemble(std::ostream &stream, offs_t pc, uint16_t op, uint16_t ximm) +{ + // the top four bits are the alu op or the branch condition, or E or F + uint8_t op0 = (op >> 12); + + // the next three are usually the destination register + uint8_t opA = (op >> 9) & 7; + + // and the next three the addressing mode + uint8_t op1 = (op >> 6) & 7; + + // the next three can be anything + uint8_t opN = (op >> 3) & 7; + + // and the last three usually the second register (source register) + uint8_t opB = op & 7; + + // the last six sometimes are a single immediate number + uint8_t opimm = op & 63; + + uint32_t len = 1; + if ((op0 < 14 && op1 == 4 && (opN == 1 || opN == 2 || opN == 3)) || (op0 == 15 && (op1 == 1 || op1 == 2))) { - util::stream_format(stream, "%s %04x", jmp[OP0], OP1 ? (pc - OPIMM + 1) : (pc + OPIMM + 1)); + len = 2; + } + + // all-zero and all-one are invalid insns: + if (op == 0 || op == 0xffff) + { + util::stream_format(stream, "--"); return UNSP_DASM_OK; } - switch((OP1 << 4) | OP0) + // first, check for the conditional branch insns + if (op0 < 15 && opA == 7 && op1 == 0) { - // ALU, Indexed - case 0x00: case 0x01: case 0x02: case 0x03: case 0x04: case 0x06: case 0x08: case 0x09: case 0x0a: case 0x0b: case 0x0c: case 0x0d: - util::stream_format(stream, "%s %s, [bp+%02x]", alu[OP0], reg[OPA], OPIMM); - return UNSP_DASM_OK; + util::stream_format(stream, "%s %04x", jumps[op0], pc+1+opimm); + return UNSP_DASM_OK; + } + if (op0 < 15 && opA == 7 && op1 == 1) + { + util::stream_format(stream, "%s %04x", jumps[op0], pc+1-opimm); + return UNSP_DASM_OK; + } + + switch ((op1 << 4) | op0) + { + case 0x05: case 0x15: case 0x25: case 0x35: + case 0x45: case 0x55: case 0x65: case 0x75: + case 0x85: case 0x95: case 0xa5: case 0xb5: + case 0xc5: case 0xd5: + case 0x07: case 0x17: case 0x27: case 0x37: + case 0x47: case 0x57: case 0x67: case 0x77: + case 0x87: case 0x97: case 0xa7: case 0xb7: + case 0xc7: case 0xd7: + case 0x1d: case 0x5d: case 0x6d: + case 0x20: case 0x21: case 0x22: case 0x23: + case 0x24: case 0x26: case 0x28: case 0x2a: + case 0x2b: case 0x2c: + util::stream_format(stream, "<BAD>"); + return UNSP_DASM_OK; + + + // alu, base+displacement + case 0x00: case 0x01: case 0x02: case 0x03: + case 0x04: case 0x06: case 0x08: case 0x09: + case 0x0a: case 0x0b: case 0x0c: + print_alu_op_start(stream, op0, opA); + util::stream_format(stream, "[bp+%02x]", opimm); + print_alu_op_end(stream, op0); + return UNSP_DASM_OK; + case 0x0d: + util::stream_format(stream, "[bp+%02x] = %s", opimm, regs[opA]); + return UNSP_DASM_OK; + + + // alu, 6-bit immediate + case 0x10: case 0x11: case 0x12: case 0x13: + case 0x14: case 0x16: case 0x18: case 0x19: + case 0x1a: case 0x1b: case 0x1c: + print_alu_op_start(stream, op0, opA); + util::stream_format(stream, "%02x", opimm); + print_alu_op_end(stream, op0); + return UNSP_DASM_OK; + + + // pop insns + case 0x29: + if (op == 0x9a90) + util::stream_format(stream, "retf"); + else if (op == 0x9a98) + util::stream_format(stream, "reti"); + else if (opA+1 < 8 && opA+opN < 8) + util::stream_format(stream, "pop %s, %s from [%s]", + regs[opA+1], regs[opA+opN], regs[opB]); + else + util::stream_format(stream, "<BAD>"); + return UNSP_DASM_OK; + + + // push insns + case 0x2d: + if (opA+1 >= opN && opA < opN+7) + util::stream_format(stream, "push %s, %s to [%s]", + regs[opA+1-opN], regs[opA], regs[opB]); + else + util::stream_format(stream, "<BAD>"); + return UNSP_DASM_OK; + + + // alu, indirect memory + case 0x30: case 0x31: case 0x32: case 0x33: + case 0x34: case 0x36: case 0x38: case 0x39: + case 0x3a: case 0x3b: case 0x3c: + print_alu_op_start(stream, op0, opA); + print_indirect_op(stream, opN, opB); + print_alu_op_end(stream, op0); + return UNSP_DASM_OK; + case 0x3d: + print_indirect_op(stream, opN, opB); + util::stream_format(stream, " = %s", regs[opA]); + return UNSP_DASM_OK; - // ALU, Immediate - case 0x10: case 0x11: case 0x12: case 0x13: case 0x14: case 0x16: case 0x18: case 0x19: case 0x1a: case 0x1b: case 0x1c: - util::stream_format(stream, "%s %s, %02x", alu[OP0], reg[OPA], OPIMM); + + case 0x40: case 0x41: case 0x42: case 0x43: + case 0x44: case 0x46: case 0x48: case 0x49: + case 0x4a: case 0x4b: case 0x4c: + switch (opN) + { + // alu, register + case 0: + print_alu_op_start(stream, op0, opA); + util::stream_format(stream, "%s", regs[opB]); + print_alu_op_end(stream, op0); return UNSP_DASM_OK; - // Pop / Interrupt return - case 0x29: - if(op == 0x9a90) + // alu, 16-bit immediate + case 1: + if ((op0 == 4 || op0 == 12 || op0 == 6 || op0 == 9) && opA != opB) { - util::stream_format(stream, "retf"); + util::stream_format(stream, "<BAD>"); return UNSP_DASM_OK; } - else if(op == 0x9a98) - { - util::stream_format(stream, "reti"); - return UNSP_DASM_OK; - } - else if((OPA + 1) < 8 && ((OPA + OPN) < 8)) + if (op0 != 4 && op0 != 12) + util::stream_format(stream, "%s = ", regs[opA]); + print_alu_op3(stream, op0, opB); + util::stream_format(stream, "%04x", ximm); + print_alu_op_end(stream, op0); + return UNSP_DASM_OK; + + // alu, direct memory + case 2: + if ((op0 == 4 || op0 == 12 || op0 == 6 || op0 == 9) && opA != opB) { - util::stream_format(stream, "pop %s, %s [%s]", reg[OPA+1], reg[OPA+OPN], reg[OPB]); + util::stream_format(stream, "<BAD>"); return UNSP_DASM_OK; } - break; + if (op0 != 4 && op0 != 12) + util::stream_format(stream, "%s = ", regs[opA]); + print_alu_op3(stream, op0, opB); + util::stream_format(stream, "[%04x]", ximm); + print_alu_op_end(stream, op0); + return UNSP_DASM_OK; - // Push - case 0x2d: - if((OPA + 1) >= OPN && OPA < (OPN + 7)) + // alu, direct memory + case 3: + if (op0 == 4 || op0 == 12) { - util::stream_format(stream, "push %s, %s [%s]", reg[(OPA+1)-OPN], reg[OPA], reg[OPB]); + util::stream_format(stream, "<BAD>"); return UNSP_DASM_OK; } - break; - - // ALU, Indirect - case 0x30: case 0x31: case 0x32: case 0x33: case 0x34: case 0x36: case 0x38: case 0x39: case 0x3a: case 0x3b: case 0x3c: case 0x3d: - switch(OPN & 3) + if ((op0 == 6 || op0 == 9) && opA != opB) { - case 0: - util::stream_format(stream, "%s %s, [%s%s]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]); - return UNSP_DASM_OK; - case 1: - util::stream_format(stream, "%s %s, [%s%s--]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]); - return UNSP_DASM_OK; - case 2: - util::stream_format(stream, "%s %s, [%s%s++]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]); - return UNSP_DASM_OK; - case 3: - util::stream_format(stream, "%s %s, [%s++%s]", alu[OP0], reg[OPA], (OPN & 4) ? "ds:" : "", reg[OPB]); - return UNSP_DASM_OK; + util::stream_format(stream, "<BAD>"); + return UNSP_DASM_OK; } + util::stream_format(stream, "[%04x] = ", ximm); + print_alu_op3(stream, op0, opB); + util::stream_format(stream, "%s", regs[opA]); + print_alu_op_end(stream, op0); return UNSP_DASM_OK; - // ALU, 16-bit ops - case 0x40: case 0x41: case 0x42: case 0x43: case 0x44: case 0x46: case 0x48: case 0x49: case 0x4a: case 0x4b: case 0x4c: - switch(OPN) + // alu, with shift + default: + print_alu_op_start(stream, op0, opA); + util::stream_format(stream, "%s asr %x", regs[opB], (opN & 3) + 1); + print_alu_op_end(stream, op0); + return UNSP_DASM_OK; + } + + case 0x4d: + switch (opN) + { + // alu, direct memory + case 3: + if (opA != opB) { - // ALU, Register - case 0: - util::stream_format(stream, "%s %s, %s", alu[OP0], reg[OPA], reg[OPB]); - return UNSP_DASM_OK; - - // ALU, 16-bit Immediate - case 1: - if(!((OP0 == 4 || OP0 == 6 || OP0 == 9 || OP0 == 12) && OPA != OPB)) - { - if(OP0 != 4 && OP0 != 12) - { - util::stream_format(stream, "%s %s, %s, %04x", alu[OP0], reg[OPA], reg[OPB], imm16); - return UNSP_DASM_OK; - } - else - { - util::stream_format(stream, "%s %s, %04x", alu[OP0], reg[OPB], imm16); - return UNSP_DASM_OK; - } - } - break; - - // ALU, Direct 16 - case 2: - util::stream_format(stream, "%s %s, [%04x]", alu[OP0], reg[OPA], imm16); - return UNSP_DASM_OK; - - // ALU, Direct 16 - case 3: - util::stream_format(stream, "%s [%04x], %s, %s", alu[OP0], imm16, reg[OPA], reg[OPB]); - return UNSP_DASM_OK; - - // ALU, Shifted - default: - util::stream_format(stream, "%s %s, %s asr %d", alu[OP0], reg[OPA], reg[OPB], (OPN & 3) + 1); - return UNSP_DASM_OK; + util::stream_format(stream, "<BAD>"); + return UNSP_DASM_OK; } - case 0x4d: - if((OPN == 3) && (OPA == OPB)) - util::stream_format(stream, "store [%04x], %s", imm16, reg[OPB]); - else - util::stream_format(stream, "<inv>"); + util::stream_format(stream, "[%04x] = %s", ximm, regs[opB]); return UNSP_DASM_OK; - - // ALU, Shifted - case 0x50: case 0x51: case 0x52: case 0x53: case 0x54: case 0x56: case 0x58: case 0x59: case 0x5a: case 0x5b: case 0x5c: - util::stream_format(stream, "%s %s, %s %s %d", alu[OP0], reg[OPA], reg[OPB], (OPN & 4) ? ">>" : "<<", (OPN & 3) + 1); + default: + util::stream_format(stream, "<BAD>"); return UNSP_DASM_OK; + } + + + // alu, with shift + case 0x50: case 0x51: case 0x52: case 0x53: + case 0x54: case 0x56: case 0x58: case 0x59: + case 0x5a: case 0x5b: case 0x5c: + print_alu_op_start(stream, op0, opA); + if ((opN & 4) == 0) + util::stream_format(stream, "%s lsl %x", regs[opB], (opN & 3) + 1); + else + util::stream_format(stream, "%s lsr %x", regs[opB], (opN & 3) + 1); + print_alu_op_end(stream, op0); + return UNSP_DASM_OK; - // ALU, Rotated - case 0x60: case 0x61: case 0x62: case 0x63: case 0x64: case 0x66: case 0x68: case 0x69: case 0x6a: case 0x6b: case 0x6c: - util::stream_format(stream, "%s %s, %s %s %d", alu[OP0], reg[OPA], reg[OPB], (OPN & 4) ? "ror" : "rol", (OPN & 3) + 1); - return UNSP_DASM_OK; - // ALU, Direct 8 - case 0x70: case 0x71: case 0x72: case 0x73: case 0x74: case 0x76: case 0x78: case 0x79: case 0x7a: case 0x7b: case 0x7c: - util::stream_format(stream, "%s %s, [%02x]", alu[OP0], reg[OPA], OPIMM); - return UNSP_DASM_OK; + // alu, with shift + case 0x60: case 0x61: case 0x62: case 0x63: + case 0x64: case 0x66: case 0x68: case 0x69: + case 0x6a: case 0x6b: case 0x6c: + print_alu_op_start(stream, op0, opA); + if ((opN & 4) == 0) + util::stream_format(stream, "%s rol %x", regs[opB], (opN & 3) + 1); + else + util::stream_format(stream, "%s ror %x", regs[opB], (opN & 3) + 1); + print_alu_op_end(stream, op0); + return UNSP_DASM_OK; - // Call - case 0x1f: - if(OPA == 0) - util::stream_format(stream, "call %06x", (OPIMM << 16) | imm16); - else - util::stream_format(stream, "<inv>"); - return UNSP_DASM_OK; - // Far Jump - case 0x2f: case 0x3f: case 0x6f: case 0x7f: - if (OPA == 7 && OP1 == 2) - util::stream_format(stream, "goto %06x", (OPIMM << 16) | imm16); - else - util::stream_format(stream, "<inv>"); + // alu, direct memory + case 0x70: case 0x71: case 0x72: case 0x73: + case 0x74: case 0x76: case 0x78: case 0x79: + case 0x7a: case 0x7b: case 0x7c: + print_alu_op_start(stream, op0, opA); + util::stream_format(stream, "[%02x]", opimm); + print_alu_op_end(stream, op0); + return UNSP_DASM_OK; + case 0x7d: + util::stream_format(stream, "[%02x] = %s", opimm, regs[opA]); + return UNSP_DASM_OK; + + + case 0x1f: + if (opA == 0) + { + util::stream_format(stream, "call %04x", (opimm << 16) | ximm); return UNSP_DASM_OK; + } + util::stream_format(stream, "<DUNNO>"); + return UNSP_DASM_OK; - // Multiply, Unsigned * Signed - case 0x0f: - if(OPN == 1 && OPA != 7) - util::stream_format(stream, "mulus %s, %s", reg[OPA], reg[OPB]); - else - util::stream_format(stream, "<inv>"); + case 0x2f: case 0x3f: case 0x6f: case 0x7f: + if (opA == 7 && op1 == 2) + { + util::stream_format(stream, "goto %04x", (opimm << 16) | ximm); + return UNSP_DASM_OK; + } + if (opA == 7 && op1 == 3) + { + util::stream_format(stream, "<DUNNO>"); return UNSP_DASM_OK; + } + util::stream_format(stream, "<DUNNO>"); + return UNSP_DASM_OK; - // Multiply, Signed * Signed - case 0x4f: - if(OPN == 1 && OPA != 7) - util::stream_format(stream, "mulss %s, %s", reg[OPA], reg[OPB]); - else - util::stream_format(stream, "<inv>"); + + case 0x0f: + switch (opN) + { + case 1: + if (opA == 7) + { + util::stream_format(stream, "<DUNNO>"); + return UNSP_DASM_OK; + } + util::stream_format(stream, "mr = %s*%s, us", regs[opA], regs[opB]); return UNSP_DASM_OK; + default: + util::stream_format(stream, "<DUNNO>"); + return UNSP_DASM_OK; + } - // Interrupt flags - case 0x5f: - if(OPA == 0) + case 0x4f: + switch (opN) + { + case 1: + if (opA == 7) { - switch(OPIMM) - { - case 0: - util::stream_format(stream, "int off"); - break; - case 1: - util::stream_format(stream, "int irq"); - break; - case 2: - util::stream_format(stream, "int fiq"); - break; - case 3: - util::stream_format(stream, "int irq,fiq"); - break; - case 8: - util::stream_format(stream, "irq off"); - break; - case 9: - util::stream_format(stream, "irq on"); - break; - case 12: - util::stream_format(stream, "fiq off"); - break; - case 14: - util::stream_format(stream, "fiq on"); - break; - case 37: - util::stream_format(stream, "nop"); - break; - default: - util::stream_format(stream, "<inv>"); - break; - } + util::stream_format(stream, "<DUNNO>"); + return UNSP_DASM_OK; } - else - util::stream_format(stream, "<inv>"); + util::stream_format(stream, "mr = %s*%s", regs[opA], regs[opB]); + return UNSP_DASM_OK; + default: + util::stream_format(stream, "<DUNNO>"); + return UNSP_DASM_OK; + } + + case 0x5f: + if (opA != 0) + { + util::stream_format(stream, "<DUNNO>"); + return UNSP_DASM_OK; + } + switch (opimm) + { + case 0x00: + util::stream_format(stream, "int off"); + return UNSP_DASM_OK; + case 0x01: + util::stream_format(stream, "int irq"); + return UNSP_DASM_OK; + case 0x02: + util::stream_format(stream, "int fiq"); + return UNSP_DASM_OK; + case 0x03: + util::stream_format(stream, "int fiq,irq"); return UNSP_DASM_OK; + case 0x04: + util::stream_format(stream, "fir_mov on"); + return UNSP_DASM_OK; + case 0x05: + util::stream_format(stream, "fir_mov off"); + return UNSP_DASM_OK; + case 0x08: + util::stream_format(stream, "irq off"); + return UNSP_DASM_OK; + case 0x09: + util::stream_format(stream, "irq on"); + return UNSP_DASM_OK; + case 0x0c: + util::stream_format(stream, "fiq off"); + return UNSP_DASM_OK; + case 0x0e: + util::stream_format(stream, "fiq on"); + return UNSP_DASM_OK; + case 0x25: + util::stream_format(stream, "nop"); + return UNSP_DASM_OK; + default: + util::stream_format(stream, "<DUNNO>"); + return UNSP_DASM_OK; + } + + case 0x0e: case 0x1e: case 0x2e: case 0x3e: + case 0x4e: case 0x5e: case 0x6e: case 0x7e: + util::stream_format(stream, "<DUNNO>"); + return UNSP_DASM_OK; + + default: + util::stream_format(stream, "<UNHANDLED>"); + return UNSP_DASM_OK; } - util::stream_format(stream, "<inv>"); return UNSP_DASM_OK; } diff --git a/src/devices/cpu/unsp/unspdasm.h b/src/devices/cpu/unsp/unspdasm.h index 94bfdeece7c..eb921b22346 100644 --- a/src/devices/cpu/unsp/unspdasm.h +++ b/src/devices/cpu/unsp/unspdasm.h @@ -1,9 +1,13 @@ -// license:BSD-3-Clause -// copyright-holders:Ryan Holtz +// license:GPL-2.0 +// copyright-holders:Segher Boessenkool /***************************************************************************** SunPlus micro'nSP disassembler + Copyright 2008-2017 Segher Boessenkool <segher@kernel.crashing.org> + Licensed under the terms of the GNU GPL, version 2 + http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt + *****************************************************************************/ #ifndef MAME_CPU_UNSP_UNSPDASM_H @@ -22,9 +26,13 @@ public: offs_t disassemble(std::ostream &stream, offs_t pc, uint16_t op, uint16_t imm16); private: - static char const *const reg[]; - static char const *const jmp[]; - static char const *const alu[]; + void print_alu_op_start(std::ostream &stream, uint8_t op0, uint8_t opA); + void print_alu_op3(std::ostream &stream, uint8_t op0, uint8_t opB); + void print_alu_op_end(std::ostream &stream, uint8_t op0); + void print_indirect_op(std::ostream &stream, uint8_t opN, uint8_t opB); + + static char const *const regs[]; + static char const *const jumps[]; }; #endif diff --git a/src/devices/machine/spg2xx.cpp b/src/devices/machine/spg2xx.cpp index 7be6477f5f9..2da5385b0c3 100644 --- a/src/devices/machine/spg2xx.cpp +++ b/src/devices/machine/spg2xx.cpp @@ -167,7 +167,8 @@ void spg2xx_device::device_reset() memset(m_video_regs, 0, 0x100 * sizeof(uint16_t)); memset(m_io_regs, 0, 0x200 * sizeof(uint16_t)); - m_io_regs[0x23] = 0x0028; + //m_io_regs[0x23] = 0x0028; + m_uart_rx_available = false; m_video_regs[0x36] = 0xffff; m_video_regs[0x37] = 0xffff; @@ -830,7 +831,7 @@ WRITE_LINE_MEMBER(spg2xx_device::vblank) #endif const uint16_t old = VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS; - VIDEO_IRQ_STATUS |= 1; + //VIDEO_IRQ_STATUS |= 1; LOGMASKED(LOG_IRQS, "Setting video IRQ status to %04x\n", VIDEO_IRQ_STATUS); const uint16_t changed = old ^ (VIDEO_IRQ_ENABLE & VIDEO_IRQ_STATUS); if (changed) @@ -849,18 +850,16 @@ void spg2xx_device::check_video_irq() void spg2xx_device::uart_rx(uint8_t data) { - if (m_uart_rx_index < 8) + if (!m_uart_rx_available) { - m_uart_rx_fifo[m_uart_rx_index] = data; - m_uart_rx_index++; - m_io_regs[0x31] |= 1; - if (m_uart_rx_index > (m_io_regs[0x37] & 7)) + if (BIT(m_io_regs[0x30], 6)) { - const uint16_t old = IO_IRQ_STATUS; - IO_IRQ_STATUS |= 0x0100; - const uint16_t changed = old ^ IO_IRQ_STATUS; - if (changed & IO_IRQ_ENABLE) + m_io_regs[0x36] = data; + if (BIT(m_io_regs[0x30], 0)) + { + IO_IRQ_STATUS |= 0x0100; check_irqs(0x0100); + } } } else @@ -947,32 +946,26 @@ READ16_MEMBER(spg2xx_device::io_r) break; case 0x31: // UART Status - val = 0x0002 | (m_uart_rx_index ? 1 : 0) | (m_uart_rx_index == 8 ? 0x80 : 0); + val |= 0x81;//(m_uart_rx_available ? 0x81 : 0); LOGMASKED(LOG_UART, "io_r: UART Status = %04x\n", val); break; case 0x36: // UART RX Data - if (m_uart_rx_index) + if (m_uart_rx_available) { - val = m_uart_rx_fifo[0]; - m_uart_rx_fifo[0] = 0; - m_uart_rx_index--; - for (uint8_t i = 0; i < m_uart_rx_index; i++) - { - m_uart_rx_fifo[i] = m_uart_rx_fifo[i + 1]; - } + m_uart_rx_available = false; + m_io_regs[0x36] = 0; } else { m_io_regs[0x37] |= 0x2000; - val = 0; } LOGMASKED(LOG_UART, "io_r: UART Rx Data = %04x\n", val); break; case 0x37: // UART Rx FIFO Control val &= ~0x0070; - val |= (m_uart_rx_index > 7 ? 7 : m_uart_rx_index) << 4; + val |= (m_uart_rx_available ? 7 : 0) << 4; LOGMASKED(LOG_UART, "io_r: UART Rx FIFO Control = %04x\n", val); break; @@ -1147,12 +1140,14 @@ WRITE16_MEMBER(spg2xx_device::io_w) if (changed & 0x0013) { const uint32_t freq = s_tmb1_freq[hifreq][data & 3]; - m_tmb1->adjust(attotime::from_hz(freq), 0, attotime::from_hz(freq)); + m_cpu->set_timer_interval(0, 27000000 / freq); + //m_tmb1->adjust(attotime::from_hz(freq), 0, attotime::from_hz(freq)); } if (changed & 0x001c) { const uint32_t freq = s_tmb2_freq[hifreq][(data >> 2) & 3]; - m_tmb2->adjust(attotime::from_hz(freq), 0, attotime::from_hz(freq)); + m_cpu->set_timer_interval(1, 27000000 / freq); + //m_tmb2->adjust(attotime::from_hz(freq), 0, attotime::from_hz(freq)); } } break; @@ -1238,16 +1233,16 @@ WRITE16_MEMBER(spg2xx_device::io_w) case 0x25: // ADC Control { LOGMASKED(LOG_IO_WRITES, "io_w: ADC Control = %04x\n", data); - const uint16_t changed = m_io_regs[offset] ^ data; + //const uint16_t changed = m_io_regs[offset] ^ data; m_io_regs[offset] = data; - if (BIT(changed, 12) && BIT(data, 12) && !BIT(m_io_regs[offset], 1)) + //if (BIT(changed, 12) && BIT(data, 12) && !BIT(m_io_regs[offset], 1)) { - m_io_regs[0x27] = 0x80ff; - const uint16_t old = IO_IRQ_STATUS; - IO_IRQ_STATUS |= 0x2000; - const uint16_t changed = IO_IRQ_STATUS ^ old; - if (changed) - check_irqs(changed); + //m_io_regs[0x27] = 0x80ff; + //const uint16_t old = IO_IRQ_STATUS; + //IO_IRQ_STATUS |= 0x2000; + //const uint16_t changed = IO_IRQ_STATUS ^ old; + //if (changed) + //check_irqs(changed); } break; } @@ -1306,23 +1301,23 @@ WRITE16_MEMBER(spg2xx_device::io_w) static const char* const s_9th_bit[4] = { "0", "1", "Odd", "Even" }; LOGMASKED(LOG_UART, "io_w: UART Control = %04x (TxEn:%d, RxEn:%d, Bits:%d, MultiProc:%d, 9thBit:%s, TxIntEn:%d, RxIntEn:%d\n", data , BIT(data, 7), BIT(data, 6), BIT(data, 5) ? 9 : 8, BIT(data, 4), s_9th_bit[(data >> 2) & 3], BIT(data, 1), BIT(data, 0)); - const uint16_t changed = m_io_regs[offset] ^ data; + //const uint16_t changed = m_io_regs[offset] ^ data; m_io_regs[offset] = data; if (!BIT(data, 6)) { - m_uart_rx_index = 0; - memset(m_uart_rx_fifo, 0, 8); - } - if (BIT(changed, 7) && BIT(data, 7)) - { - m_io_regs[0x31] |= 0x0002; + m_uart_rx_available = false; + m_io_regs[0x36] = 0; } + //if (BIT(changed, 7) && BIT(data, 7)) + //{ + // m_io_regs[0x31] |= 0x0002; + //} break; } case 0x31: // UART Status LOGMASKED(LOG_UART, "io_w: UART Status = %04x\n", data); - //m_io_regs[offset] &= ~data; + m_io_regs[offset] &= ~data; break; case 0x33: // UART Baud Rate @@ -1333,6 +1328,7 @@ WRITE16_MEMBER(spg2xx_device::io_w) case 0x35: // UART TX Data LOGMASKED(LOG_UART, "io_w: UART Tx Data = %02x\n", data & 0x00ff); m_io_regs[offset] = data; + m_io_regs[0x31] |= 2; m_uart_tx((uint8_t)data); break; @@ -1345,8 +1341,8 @@ WRITE16_MEMBER(spg2xx_device::io_w) , BIT(data, 15), BIT(data, 14), BIT(data, 13), (data >> 4) & 7, data & 7); if (data & 0x8000) { - m_uart_rx_index = 0; - memset(m_uart_rx_fifo, 0, 8); + m_uart_rx_available = false; + m_io_regs[0x36] = 0; } m_io_regs[offset] &= ~data & 0x6000; m_io_regs[offset] &= ~0x0007; @@ -1394,6 +1390,18 @@ WRITE16_MEMBER(spg2xx_device::io_w) m_io_regs[offset] = data; break; + case 0x60: // SPECIAL INTERRUPT HAX - REMOVE BEFORE CHECKIN + m_io_regs[0x22] |= data; + break; + + case 0x61: // SPECIAL INTERRUPT HAX - REMOVE BEFORE CHECKIN + m_video_regs[0x63] |= data; + break; + + case 0x62: // SPECIAL INTERRUPT HAX - REMOVE BEFORE CHECKIN + m_io_regs[0x22] |= data; + break; + case 0x100: // DMA Source (lo) LOGMASKED(LOG_DMA, "io_w: DMA Source (lo) = %04x\n", data); m_io_regs[offset] = data; @@ -1427,17 +1435,17 @@ void spg2xx_device::device_timer(emu_timer &timer, device_timer_id id, int param { case TIMER_TMB1: { - LOGMASKED(LOG_TIMERS, "TMB1 elapsed, setting IRQ Status bit 0 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 1, IO_IRQ_ENABLE); - IO_IRQ_STATUS |= 1; - check_irqs(0x0001); + //LOGMASKED(LOG_TIMERS, "TMB1 elapsed, setting IRQ Status bit 0 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 1, IO_IRQ_ENABLE); + //IO_IRQ_STATUS |= 1; + //check_irqs(0x0001); break; } case TIMER_TMB2: { - LOGMASKED(LOG_TIMERS, "TMB2 elapsed, setting IRQ Status bit 1 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 2, IO_IRQ_ENABLE); - IO_IRQ_STATUS |= 2; - check_irqs(0x0002); + //LOGMASKED(LOG_TIMERS, "TMB2 elapsed, setting IRQ Status bit 1 (old:%04x, new:%04x, enable:%04x)\n", IO_IRQ_STATUS, IO_IRQ_STATUS | 2, IO_IRQ_ENABLE); + //IO_IRQ_STATUS |= 2; + //check_irqs(0x0002); break; } @@ -1468,6 +1476,9 @@ void spg2xx_device::check_irqs(const uint16_t changed) // m_cpu->set_input_line(UNSP_IRQ1_LINE, ASSERT_LINE); // } + if (true) + return; + if (changed & 0x0c00) // Timer A, Timer B IRQ { m_cpu->set_input_line(UNSP_IRQ2_LINE, (IO_IRQ_ENABLE & IO_IRQ_STATUS & 0x0c00) ? ASSERT_LINE : CLEAR_LINE); diff --git a/src/devices/machine/spg2xx.h b/src/devices/machine/spg2xx.h index 7a993251ece..b6ea28025ae 100644 --- a/src/devices/machine/spg2xx.h +++ b/src/devices/machine/spg2xx.h @@ -225,16 +225,16 @@ protected: AUDIO_ADPCM36_MASK = 0x8000, AUDIO_PHASE_HIGH = 0x200, - AUDIO_PHASE_HIGH_MASK = 0x0007, + AUDIO_PHASE_HIGH_MASK = 0xffff, AUDIO_PHASE_ACCUM_HIGH = 0x201, - AUDIO_PHASE_ACCUM_HIGH_MASK = 0x0007, + AUDIO_PHASE_ACCUM_HIGH_MASK = 0xffff, AUDIO_TARGET_PHASE_HIGH = 0x202, - AUDIO_TARGET_PHASE_HIGH_MASK= 0x0007, + AUDIO_TARGET_PHASE_HIGH_MASK= 0xffff, AUDIO_RAMP_DOWN_CLOCK = 0x203, - AUDIO_RAMP_DOWN_CLOCK_MASK = 0x0007, + AUDIO_RAMP_DOWN_CLOCK_MASK = 0xffff, AUDIO_PHASE = 0x204, AUDIO_PHASE_ACCUM = 0x205, @@ -439,8 +439,7 @@ protected: uint16_t m_audio_curr_beat_base_count; uint16_t m_io_regs[0x200]; - uint8_t m_uart_rx_fifo[8]; - uint8_t m_uart_rx_index; + bool m_uart_rx_available; uint16_t m_video_regs[0x100]; size_t m_sprite_limit; @@ -468,7 +467,7 @@ protected: sound_stream *m_stream; oki_adpcm_state m_adpcm[16]; - required_device<cpu_device> m_cpu; + required_device<unsp_device> m_cpu; required_device<screen_device> m_screen; required_shared_ptr<uint16_t> m_scrollram; required_shared_ptr<uint16_t> m_paletteram; diff --git a/src/mame/drivers/vii.cpp b/src/mame/drivers/vii.cpp index dcd25d3466f..a7ffd7d4ef5 100644 --- a/src/mame/drivers/vii.cpp +++ b/src/mame/drivers/vii.cpp @@ -186,7 +186,7 @@ public: : spg2xx_game_state(mconfig, type, tag) , m_cart(*this, "cartslot") , m_bankdev(*this, "bank") - , m_cart_banks(*this, "cartbank%u", 0U) + , m_system_region(*this, "maincpu") { } void vsmile(machine_config &config); @@ -218,9 +218,9 @@ private: DECLARE_READ16_MEMBER(bank2_r); DECLARE_READ16_MEMBER(bank3_r); optional_device<generic_slot_device> m_cart; - memory_region *m_cart_rom; required_device<address_map_bank_device> m_bankdev; - optional_memory_bank_array<4> m_cart_banks; + memory_region *m_cart_region; + required_memory_region m_system_region; emu_timer *m_pad_timer; uint8_t m_pad_counter; @@ -248,7 +248,7 @@ private: virtual void machine_reset() override; optional_device<generic_slot_device> m_cart; - memory_region *m_cart_rom; + memory_region *m_cart_region; }; #define VERBOSE_LEVEL (4) @@ -340,7 +340,7 @@ void vsmile_state::device_timer(emu_timer &timer, device_timer_id id, int param, if (m_pad_counter >= 100) { m_pad_counter = 0; - m_spg->uart_rx(0x55); + //m_spg->uart_rx(0x55); } } } @@ -362,59 +362,55 @@ void vsmile_state::device_timer(emu_timer &timer, device_timer_id id, int param, READ16_MEMBER(vsmile_state::bank0_r) { - const uint16_t data = ((uint16_t*)m_cart_rom->base())[offset]; - //printf("bank0_r: %06x: %04x\n", offset, data); - return data; + return ((uint16_t*)m_cart_region->base())[offset]; } READ16_MEMBER(vsmile_state::bank1_r) { - const uint16_t data = ((uint16_t*)m_cart_rom->base())[offset + 0x100000]; - //printf("bank1_r: %06x: %04x\n", offset + 0x100000, data); - return data; + return ((uint16_t*)m_cart_region->base())[offset + 0x100000]; } READ16_MEMBER(vsmile_state::bank2_r) { - const uint16_t data = ((uint16_t*)m_cart_rom->base())[offset + 0x200000]; - //printf("bank2_r: %06x: %04x\n", offset + 0x200000, data); - return data; + return ((uint16_t*)m_cart_region->base())[offset + 0x200000]; } READ16_MEMBER(vsmile_state::bank3_r) { - const uint16_t data = ((uint16_t*)memregion("maincpu")->base())[offset]; - //printf("bank3_r: %06x: %04x\n", offset + 0x300000, data); - return data; + return ((uint16_t*)m_system_region->base())[offset]; } READ16_MEMBER(vsmile_state::portb_r) { //const uint8_t inputs = m_io_p2->read(); //const uint16_t input_bits = BIT(inputs, 0) ? VSMILE_PORTB_ON_SW : 0; - const uint16_t data = VSMILE_PORTB_ON_SW | (m_cart && m_cart->exists() ? VSMILE_PORTB_CART : 0); + //const uint16_t data = VSMILE_PORTB_ON_SW | VSMILE_PORTB_OFF_SW | (m_cart && m_cart->exists() ? VSMILE_PORTB_CART : 0); //logerror("V.Smile Port B read %04x, mask %04x\n", data, mem_mask); //printf("V.Smile Port B read %04x, mask %04x\n", data, mem_mask); - return data; + return m_portb_data;// | data; } READ16_MEMBER(vsmile_state::portc_r) { - const uint16_t data = VSMILE_PORTC_LOGO | 0x0004; + uint16_t data = 0x0004; + if (m_portc_data & 0x0100) + data |= 0x0400; + if (m_portc_data & 0x0200) + data |= 0x1000; //logerror("V.Smile Port C read %04x, mask %04x\n", data, mem_mask); - return data; + return (m_portc_data & ~0x000f) | data; } WRITE16_MEMBER(vsmile_state::portb_w) { - m_portb_data = data & mem_mask; + m_portb_data = data;//(m_portb_data &~ mem_mask) | (data & mem_mask); //logerror("V.Smile Port B write %04x, mask %04x\n", m_portb_data, mem_mask); //printf("V.Smile Port B write %04x, mask %04x\n", m_portb_data, mem_mask); } WRITE16_MEMBER(vsmile_state::portc_w) { - m_portc_data = data & mem_mask; + m_portc_data = data;//(m_portc_data &~ mem_mask) | (data & mem_mask); //logerror("V.Smile Port C write %04x, mask %04x\n", m_portc_data, mem_mask); //printf("V.Smile Port C write %04x, mask %04x\n", m_portc_data, mem_mask); //printf("%02x ", data >> 8); @@ -422,26 +418,22 @@ WRITE16_MEMBER(vsmile_state::portc_w) WRITE8_MEMBER(vsmile_state::uart_tx) { - //logerror("UART Tx: %02x\n", data); + logerror("UART Tx: %02x\n", data); } WRITE8_MEMBER(vsmile_state::chip_sel_w) { - //logerror("Chip select mode: %d\n", data); const uint16_t cart_offset = m_cart && m_cart->exists() ? 4 : 0; switch (data) { case 0: - //logerror("Setting bank %d\n", cart_offset); m_bankdev->set_bank(cart_offset); break; case 1: - //logerror("Setting bank %d\n", 1 + cart_offset); m_bankdev->set_bank(1 + cart_offset); break; case 2: case 3: - //logerror("Setting bank %d\n", 2 + cart_offset); m_bankdev->set_bank(2 + cart_offset); break; } @@ -499,15 +491,10 @@ void vsmile_state::banked_map(address_map &map) map(0x0a00000, 0x0afffff).rom().region("maincpu", 0); map(0x0b00000, 0x0bfffff).rom().region("maincpu", 0); - map(0x1000000, 0x10fffff).bankr("cartbank0"); - map(0x1100000, 0x11fffff).bankr("cartbank0"); - map(0x1200000, 0x12fffff).bankr("cartbank0"); - map(0x1300000, 0x13fffff).bankr("cartbank0"); + map(0x1000000, 0x13fffff).r(FUNC(vsmile_state::bank0_r)); - map(0x1400000, 0x14fffff).bankr("cartbank0"); - map(0x1500000, 0x15fffff).bankr("cartbank0"); - map(0x1600000, 0x16fffff).bankr("cartbank1"); - map(0x1700000, 0x17fffff).bankr("cartbank1"); + map(0x1400000, 0x15fffff).r(FUNC(vsmile_state::bank0_r)); + map(0x1600000, 0x17fffff).r(FUNC(vsmile_state::bank1_r)); map(0x1800000, 0x18fffff).r(FUNC(vsmile_state::bank0_r)); map(0x1900000, 0x19fffff).r(FUNC(vsmile_state::bank1_r)); @@ -759,8 +746,8 @@ void spg2xx_cart_state::machine_start() if (m_cart && m_cart->exists()) { std::string region_tag; - m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str()); - m_bank->configure_entries(0, ceilf((float)m_cart_rom->bytes() / 0x800000), m_cart_rom->base(), 0x800000); + m_cart_region = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str()); + m_bank->configure_entries(0, ceilf((float)m_cart_region->bytes() / 0x800000), m_cart_region->base(), 0x800000); m_bank->set_entry(0); } } @@ -771,22 +758,7 @@ void vsmile_state::machine_start() if (m_cart && m_cart->exists()) { std::string region_tag; - m_cart_rom = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str()); - const uint32_t banks = (m_cart_rom->bytes() + 0x1fffff) / 0x200000; - for (uint32_t i = 0; i < 2; i++) - { - m_cart_banks[i]->configure_entries(0, banks, m_cart_rom->base(), 0x200000); - m_cart_banks[i]->set_entry(i % banks); - } - } - else - { - for (uint32_t i = 0; i < 2; i++) - { - m_cart_rom = memregion("maincpu"); - m_cart_banks[i]->configure_entries(0, (m_cart_rom->bytes() + 0x1fffff) / 0x200000, m_cart_rom->base(), 0x200000); - m_cart_banks[i]->set_entry(0); - } + m_cart_region = memregion(region_tag.assign(m_cart->tag()).append(GENERIC_ROM_REGION_TAG).c_str()); } m_bankdev->set_bank(m_cart && m_cart->exists() ? 4 : 0); |