diff options
Diffstat (limited to 'src/devices/cpu/nec/v25.cpp')
-rw-r--r-- | src/devices/cpu/nec/v25.cpp | 362 |
1 files changed, 206 insertions, 156 deletions
diff --git a/src/devices/cpu/nec/v25.cpp b/src/devices/cpu/nec/v25.cpp index 952cff5bd0c..ee4f1886170 100644 --- a/src/devices/cpu/nec/v25.cpp +++ b/src/devices/cpu/nec/v25.cpp @@ -35,16 +35,21 @@ ****************************************************************************/ #include "emu.h" -#include "debugger.h" +#include "v25.h" +#include "necdasm.h" + +#define LOG_BUSLOCK (1 << 1) +//#define VERBOSE (...) + +#include "logmacro.h" typedef uint8_t BOOLEAN; typedef uint8_t BYTE; typedef uint16_t WORD; typedef uint32_t DWORD; -#include "v25.h" -#include "v25priv.h" -#include "necdasm.h" +#include "v25priv.ipp" + DEFINE_DEVICE_TYPE(V25, v25_device, "v25", "NEC V25") DEFINE_DEVICE_TYPE(V35, v35_device, "v35", "NEC V35") @@ -57,13 +62,15 @@ v25_common_device::v25_common_device(const machine_config &mconfig, device_type , m_io_config("io", ENDIANNESS_LITTLE, is_16bit ? 16 : 8, 16, 0) , m_internal_ram(*this, "internal_ram") , m_PCK(8) - , m_pt_in(*this) - , m_p0_in(*this) - , m_p1_in(*this) - , m_p2_in(*this) + , m_pt_in(*this, 0xff) + , m_p0_in(*this, 0xff) + , m_p1_in(*this, 0xff) + , m_p2_in(*this, 0xff) , m_p0_out(*this) , m_p1_out(*this) , m_p2_out(*this) + , m_dma_read(*this, 0xffff) + , m_dma_write(*this) , m_prefetch_size(prefetch_size) , m_prefetch_cycles(prefetch_cycles) , m_chip_type(chip_type) @@ -180,6 +187,7 @@ uint8_t v25_common_device::fetchop() void v25_common_device::device_reset() { m_ip = 0; + m_prev_ip = 0; m_IBRK = 1; m_F0 = 0; m_F1 = 0; @@ -209,9 +217,20 @@ void v25_common_device::device_reset() m_intm = 0; m_halted = 0; - m_TM0 = m_MD0 = m_TM1 = m_MD1 = 0; m_TMC0 = m_TMC1 = 0; + for (int i = 0; i < 2; i++) + { + m_scm[i] = 0; + m_scc[i] = 0; + m_brg[i] = 0; + m_sce[i] = 0; + } + + m_dmam[0] = m_dmam[1] = 0; + m_dma_channel = -1; + m_last_dma_channel = 0; + m_RAMEN = 1; m_TB = 20; m_PCK = 8; @@ -257,18 +276,20 @@ void v25_common_device::nec_interrupt(unsigned int_num, int /*INTSOURCES*/ sourc logerror("%06x: BRKS executed with no decryption table\n",PC()); break; case INT_IRQ: /* get vector */ - int_num = standard_irq_callback(0); + int_num = standard_irq_callback(0, PC()); break; default: break; } + debugger_exception_hook(int_num); + dest_off = read_mem_word(int_num*4); dest_seg = read_mem_word(int_num*4+2); PUSH(Sreg(PS)); PUSH(m_ip); - m_ip = (WORD)dest_off; + m_prev_ip = m_ip = (WORD)dest_off; Sreg(PS) = (WORD)dest_seg; CHANGE_PC; } @@ -284,7 +305,7 @@ void v25_common_device::nec_bankswitch(unsigned bank_num) Wreg(PSW_SAVE) = tmp; Wreg(PC_SAVE) = m_ip; - m_ip = Wreg(VECTOR_PC); + m_prev_ip = m_ip = Wreg(VECTOR_PC); CHANGE_PC; } @@ -448,7 +469,10 @@ void v25_common_device::external_int() m_IRQS = vector; m_ISPR |= (1 << i); if (m_bankswitch_irq & source) + { + debugger_exception_hook(vector); nec_bankswitch(i); + } else nec_interrupt(vector, source); } @@ -464,6 +488,111 @@ void v25_common_device::external_int() } } +void v25_common_device::dma_process() +{ + uint16_t sar = m_internal_ram[m_dma_channel * 4]; + uint16_t dar = m_internal_ram[m_dma_channel * 4 + 1]; + uint16_t sarh_darh = m_internal_ram[m_dma_channel * 4 + 2]; + uint8_t dmamode = BIT(m_dmam[m_dma_channel], 5, 3); + bool w = BIT(m_dmam[m_dma_channel], 4); + + uint32_t saddr = ((uint32_t(sarh_darh) & 0xff00) << 4) + sar; + uint32_t daddr = ((uint32_t(sarh_darh) & 0x00ff) << 12) + dar; + + switch (dmamode & 3) + { + case 0: + // Memory to memory transfer + if (w) + { + uint16_t data = v25_read_word(saddr); + v25_write_word(daddr, data); + } + else + { + uint8_t data = v25_read_byte(saddr); + v25_write_byte(daddr, data); + } + m_icount -= (w && m_program->addr_width() == 8) ? 8 : 4; + break; + + case 1: + // I/O to memory transfer + if (w && m_program->addr_width() == 16) + { + uint16_t data = m_dma_read[m_dma_channel](daddr); + v25_write_word(daddr, data); + } + else + { + uint8_t data = m_dma_read[m_dma_channel](daddr); + v25_write_byte(daddr, data); + if (w) + { + logerror("Warning: V25 16-bit I/O to memory transfer\n"); + data = m_dma_read[m_dma_channel](daddr + 1); + v25_write_byte(daddr + 1, data); + m_icount -= 2; + } + } + m_icount -= 2; + break; + + case 2: + // Memory to I/O transfer + if (w && m_program->addr_width() == 16) + { + uint16_t data = v25_read_word(saddr); + m_dma_write[m_dma_channel](saddr, data); + } + else + { + uint8_t data = v25_read_byte(saddr); + m_dma_write[m_dma_channel](saddr, data); + if (w) + { + logerror("Warning: V25 16-bit memory to I/O transfer\n"); + data = v25_read_byte(saddr + 1); + m_dma_write[m_dma_channel](saddr + 1, data); + m_icount -= 2; + } + } + m_icount -= 2; + break; + + default: + logerror("Reserved DMA transfer mode\n"); + m_icount--; + break; + } + + // Update source and destination based on address control + uint8_t dmac = m_dmac[m_dma_channel]; + if (BIT(dmac, 0, 2) == 1) + m_internal_ram[m_dma_channel * 4] = sar + (w ? 2 : 1); + else if (BIT(dmac, 0, 2) == 2) + m_internal_ram[m_dma_channel * 4] = sar - (w ? 2 : 1); + if (BIT(dmac, 4, 2) == 1) + m_internal_ram[m_dma_channel * 4 + 1] = dar + (w ? 2 : 1); + else if (BIT(dmac, 4, 2) == 2) + m_internal_ram[m_dma_channel * 4 + 1] = dar - (w ? 2 : 1); + + // Update TC + uint16_t tc = --m_internal_ram[m_dma_channel * 4 + 3]; + if (tc == 0) + { + m_dmam[m_dma_channel] &= 0xf0; // disable channel + m_pending_irq |= m_dma_channel ? INTD1 : INTD0; // request interrupt + } + + if (dmamode == 0 || dmamode > 4 || tc == 0) + { + // Single step/single transfer modes (or end of burst) + m_last_dma_channel = m_dma_channel; + m_dma_channel = -1; + } +} + /****************************************************************************/ /* OPCODES */ /****************************************************************************/ @@ -513,7 +642,7 @@ void v25_common_device::execute_set_input(int irqline, int state) std::unique_ptr<util::disasm_interface> v25_common_device::create_disassembler() { - return std::make_unique<nec_disassembler>(m_v25v35_decryptiontable); + return std::make_unique<nec_disassembler>(this, m_v25v35_decryptiontable); } void v25_common_device::device_start() @@ -551,8 +680,11 @@ void v25_common_device::device_start() m_EO = 0; m_E16 = 0; + m_TM0 = m_MD0 = m_TM1 = m_MD1 = 0; + m_dmac[0] = m_dmac[1] = 0; + for (i = 0; i < 4; i++) - m_timers[i] = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(v25_common_device::v25_timer_callback),this)); + m_timers[i] = timer_alloc(FUNC(v25_common_device::v25_timer_callback), this); std::fill_n(&m_intp_state[0], 3, 0); std::fill_n(&m_ems[0], 3, 0); @@ -563,6 +695,7 @@ void v25_common_device::device_start() save_item(NAME(m_intp_state)); save_item(NAME(m_ip)); + save_item(NAME(m_prev_ip)); save_item(NAME(m_IBRK)); save_item(NAME(m_F0)); save_item(NAME(m_F1)); @@ -606,6 +739,14 @@ void v25_common_device::device_start() save_item(NAME(m_MD1)); save_item(NAME(m_TMC0)); save_item(NAME(m_TMC1)); + save_item(NAME(m_scm)); + save_item(NAME(m_scc)); + save_item(NAME(m_brg)); + save_item(NAME(m_sce)); + save_item(NAME(m_dmac)); + save_item(NAME(m_dmam)); + save_item(NAME(m_dma_channel)); + save_item(NAME(m_last_dma_channel)); save_item(NAME(m_RAMEN)); save_item(NAME(m_TB)); save_item(NAME(m_PCK)); @@ -617,45 +758,44 @@ void v25_common_device::device_start() m_program = &space(AS_PROGRAM); if(m_program->data_width() == 8) { - auto cache = m_program->cache<0, 0, ENDIANNESS_LITTLE>(); - m_dr8 = [cache](offs_t address) -> u8 { return cache->read_byte(address); }; + m_program->cache(m_cache8); + m_dr8 = [this](offs_t address) -> u8 { return m_cache8.read_byte(address); }; } else { - auto cache = m_program->cache<1, 0, ENDIANNESS_LITTLE>(); - m_dr8 = [cache](offs_t address) -> u8 { return cache->read_byte(address); }; + m_program->cache(m_cache16); + m_dr8 = [this](offs_t address) -> u8 { return m_cache16.read_byte(address); }; } - m_data = &space(AS_DATA); + space(AS_DATA).specific(m_data); m_io = &space(AS_IO); - m_pt_in.resolve_safe(0xff); - m_p0_in.resolve_safe(0xff); - m_p1_in.resolve_safe(0xff); - m_p2_in.resolve_safe(0xff); - - m_p0_out.resolve_safe(); - m_p1_out.resolve_safe(); - m_p2_out.resolve_safe(); - - state_add( V25_PC, "PC", m_debugger_temp).callimport().callexport().formatstr("%05X"); - state_add( V25_IP, "IP", m_ip).formatstr("%04X"); - state_add( V25_SP, "SP", m_debugger_temp).callimport().callexport().formatstr("%04X"); - state_add( V25_FLAGS, "F", m_debugger_temp).callimport().callexport().formatstr("%04X"); - state_add( V25_AW, "AW", m_debugger_temp).callimport().callexport().formatstr("%04X"); - state_add( V25_CW, "CW", m_debugger_temp).callimport().callexport().formatstr("%04X"); - state_add( V25_DW, "DW", m_debugger_temp).callimport().callexport().formatstr("%04X"); - state_add( V25_BW, "BW", m_debugger_temp).callimport().callexport().formatstr("%04X"); - state_add( V25_BP, "BP", m_debugger_temp).callimport().callexport().formatstr("%04X"); - state_add( V25_IX, "IX", m_debugger_temp).callimport().callexport().formatstr("%04X"); - state_add( V25_IY, "IY", m_debugger_temp).callimport().callexport().formatstr("%04X"); - state_add( V25_ES, "DS1", m_debugger_temp).callimport().callexport().formatstr("%04X"); - state_add( V25_CS, "PS", m_debugger_temp).callimport().callexport().formatstr("%04X"); - state_add( V25_SS, "SS", m_debugger_temp).callimport().callexport().formatstr("%04X"); - state_add( V25_DS, "DS0", m_debugger_temp).callimport().callexport().formatstr("%04X"); - - state_add( V25_IDB, "IDB", m_IDB).mask(0xffe00).callimport(); + state_add( V25_PC, "PC", m_ip).formatstr("%04X"); + state_add<uint16_t>( V25_PSW, "PSW", [this]() { return CompressFlags(); }, [this](uint16_t data) { ExpandFlags(data); }); + + state_add<uint16_t>( V25_AW, "AW", [this]() { return Wreg(AW); }, [this](uint16_t data) { Wreg(AW) = data; }); + state_add<uint16_t>( V25_CW, "CW", [this]() { return Wreg(CW); }, [this](uint16_t data) { Wreg(CW) = data; }); + state_add<uint16_t>( V25_DW, "DW", [this]() { return Wreg(DW); }, [this](uint16_t data) { Wreg(DW) = data; }); + state_add<uint16_t>( V25_BW, "BW", [this]() { return Wreg(BW); }, [this](uint16_t data) { Wreg(BW) = data; }); + state_add<uint16_t>( V25_SP, "SP", [this]() { return Wreg(SP); }, [this](uint16_t data) { Wreg(SP) = data; }); + state_add<uint16_t>( V25_BP, "BP", [this]() { return Wreg(BP); }, [this](uint16_t data) { Wreg(BP) = data; }); + state_add<uint16_t>( V25_IX, "IX", [this]() { return Wreg(IX); }, [this](uint16_t data) { Wreg(IX) = data; }); + state_add<uint16_t>( V25_IY, "IY", [this]() { return Wreg(IY); }, [this](uint16_t data) { Wreg(IY) = data; }); + state_add<uint16_t>( V25_DS1, "DS1", [this]() { return Sreg(DS1); }, [this](uint16_t data) { Sreg(DS1) = data; }); + state_add<uint16_t>( V25_PS, "PS", [this]() { return Sreg(PS); }, [this](uint16_t data) { Sreg(PS) = data; }); + state_add<uint16_t>( V25_SS, "SS", [this]() { return Sreg(SS); }, [this](uint16_t data) { Sreg(SS) = data; }); + state_add<uint16_t>( V25_DS0, "DS0", [this]() { return Sreg(DS0); }, [this](uint16_t data) { Sreg(DS0) = data; }); + + state_add<uint8_t>( V25_AL, "AL", [this]() { return Breg(AL); }, [this](uint8_t data) { Breg(AL) = data; }).noshow(); + state_add<uint8_t>( V25_AH, "AH", [this]() { return Breg(AH); }, [this](uint8_t data) { Breg(AH) = data; }).noshow(); + state_add<uint8_t>( V25_CL, "CL", [this]() { return Breg(CL); }, [this](uint8_t data) { Breg(CL) = data; }).noshow(); + state_add<uint8_t>( V25_CH, "CH", [this]() { return Breg(CH); }, [this](uint8_t data) { Breg(CH) = data; }).noshow(); + state_add<uint8_t>( V25_DL, "DL", [this]() { return Breg(DL); }, [this](uint8_t data) { Breg(DL) = data; }).noshow(); + state_add<uint8_t>( V25_DH, "DH", [this]() { return Breg(DH); }, [this](uint8_t data) { Breg(DH) = data; }).noshow(); + state_add<uint8_t>( V25_BL, "BL", [this]() { return Breg(BL); }, [this](uint8_t data) { Breg(BL) = data; }).noshow(); + state_add<uint8_t>( V25_BH, "BH", [this]() { return Breg(BH); }, [this](uint8_t data) { Breg(BH) = data; }).noshow(); + + state_add( V25_IDB, "IDB", m_IDB).mask(0xffe00).callimport(); state_add( STATE_GENPC, "GENPC", m_debugger_temp).callexport().noshow(); state_add( STATE_GENPCBASE, "CURPC", m_debugger_temp).callexport().noshow(); - state_add( STATE_GENSP, "GENSP", m_debugger_temp).callimport().callexport().noshow(); state_add( STATE_GENFLAGS, "GENFLAGS", m_debugger_temp).formatstr("%16s").noshow(); set_icountptr(m_icount); @@ -692,7 +832,7 @@ void v25_common_device::state_import(const device_state_entry &entry) { switch (entry.index()) { - case V25_PC: + case STATE_GENPC: if( m_debugger_temp - (Sreg(PS)<<4) < 0x10000 ) { m_ip = m_debugger_temp - (Sreg(PS)<<4); @@ -702,58 +842,7 @@ void v25_common_device::state_import(const device_state_entry &entry) Sreg(PS) = m_debugger_temp >> 4; m_ip = m_debugger_temp & 0x0000f; } - break; - - case V25_SP: - Wreg(SP) = m_debugger_temp; - break; - - case V25_FLAGS: - ExpandFlags(m_debugger_temp); - break; - - case V25_AW: - Wreg(AW) = m_debugger_temp; - break; - - case V25_CW: - Wreg(CW) = m_debugger_temp; - break; - - case V25_DW: - Wreg(DW) = m_debugger_temp; - break; - - case V25_BW: - Wreg(BW) = m_debugger_temp; - break; - - case V25_BP: - Wreg(BP) = m_debugger_temp; - break; - - case V25_IX: - Wreg(IX) = m_debugger_temp; - break; - - case V25_IY: - Wreg(IY) = m_debugger_temp; - break; - - case V25_ES: - Sreg(DS1) = m_debugger_temp; - break; - - case V25_CS: - Sreg(PS) = m_debugger_temp; - break; - - case V25_SS: - Sreg(SS) = m_debugger_temp; - break; - - case V25_DS: - Sreg(DS0) = m_debugger_temp; + m_prev_ip = m_ip; break; case V25_IDB: @@ -768,65 +857,11 @@ void v25_common_device::state_export(const device_state_entry &entry) switch (entry.index()) { case STATE_GENPC: - case STATE_GENPCBASE: - case V25_PC: m_debugger_temp = (Sreg(PS)<<4) + m_ip; break; - case STATE_GENSP: - m_debugger_temp = (Sreg(SS)<<4) + Wreg(SP); - break; - - case V25_SP: - m_debugger_temp = Wreg(SP); - break; - - case V25_FLAGS: - m_debugger_temp = CompressFlags(); - break; - - case V25_AW: - m_debugger_temp = Wreg(AW); - break; - - case V25_CW: - m_debugger_temp = Wreg(CW); - break; - - case V25_DW: - m_debugger_temp = Wreg(DW); - break; - - case V25_BW: - m_debugger_temp = Wreg(BW); - break; - - case V25_BP: - m_debugger_temp = Wreg(BP); - break; - - case V25_IX: - m_debugger_temp = Wreg(IX); - break; - - case V25_IY: - m_debugger_temp = Wreg(IY); - break; - - case V25_ES: - m_debugger_temp = Sreg(DS1); - break; - - case V25_CS: - m_debugger_temp = Sreg(PS); - break; - - case V25_SS: - m_debugger_temp = Sreg(SS); - break; - - case V25_DS: - m_debugger_temp = Sreg(DS0); + case STATE_GENPCBASE: + m_debugger_temp = (Sreg(PS)<<4) + m_prev_ip; break; } } @@ -866,13 +901,20 @@ void v25_common_device::execute_run() if (m_halted) { + debugger_wait_hook(); m_icount = 0; - debugger_instruction_hook((Sreg(PS)<<4) + m_ip); return; } while(m_icount>0) { + if (m_dma_channel != -1) + { + dma_process(); + continue; + } + /* Dispatch IRQ */ + m_prev_ip = m_ip; if (m_no_interrupt==0 && (m_pending_irq & m_unmasked_irq)) { if (m_pending_irq & NMI_IRQ) @@ -889,5 +931,13 @@ void v25_common_device::execute_run() prev_ICount = m_icount; (this->*s_nec_instruction[fetchop()])(); do_prefetch(prev_ICount); + + if ((m_dmam[0] & 0x0c) == 0x0c || (m_dmam[1] & 0x0c) == 0x0c) + { + if ((m_dmam[1 - m_last_dma_channel] & 0x0c) == 0x0c) + m_dma_channel = 1 - m_last_dma_channel; + else + m_dma_channel = m_last_dma_channel; + } } } |