diff options
author | Olivier Galibert <galibert@pobox.com> | 2020-02-12 06:48:31 +0100 |
---|---|---|
committer | Olivier Galibert <galibert@pobox.com> | 2020-02-12 06:48:46 +0100 |
commit | ad06ccc77c9094966dbbeba82e6267661c5f9115 (patch) | |
tree | 63302c33e64239570f36162b0a001ffbd3fd133e | |
parent | 6b3a689ce15e5536034a7b288dce31bc6b20073f (diff) |
xavix2: Add dma, completion issues (nw)
-rw-r--r-- | src/devices/cpu/xavix2/xavix2.cpp | 23 | ||||
-rw-r--r-- | src/devices/cpu/xavix2/xavix2.h | 35 | ||||
-rw-r--r-- | src/mame/drivers/xavix2.cpp | 135 |
3 files changed, 162 insertions, 31 deletions
diff --git a/src/devices/cpu/xavix2/xavix2.cpp b/src/devices/cpu/xavix2/xavix2.cpp index ac352aba46b..a96d1f09a0e 100644 --- a/src/devices/cpu/xavix2/xavix2.cpp +++ b/src/devices/cpu/xavix2/xavix2.cpp @@ -110,12 +110,15 @@ void xavix2_device::device_start() save_item(NAME(m_if1)); save_item(NAME(m_hr)); save_item(NAME(m_int_line)); + save_item(NAME(m_wait)); + save_item(NAME(m_ei_count)); set_icountptr(m_icount); m_pc = 0; m_f = 0; m_int_line = false; + m_wait = false; memset(m_r, 0, sizeof(m_r)); memset(m_hr, 0, sizeof(m_hr)); @@ -144,9 +147,11 @@ uint32_t xavix2_device::execute_input_lines() const noexcept u32 xavix2_device::check_interrupt(u32 cpc) { - if(m_int_line && !(m_f & F_I)) { + if(m_int_line && (!(m_f & F_I) || m_wait)) { standard_irq_callback(0); - m_ilr1 = cpc; + m_ilr1 = m_wait ? cpc + 1 : cpc; + m_wait = false; + m_ei_count = 0; m_if1 = m_f; m_f |= F_I; return 0x40000010; @@ -187,8 +192,14 @@ void xavix2_device::state_string_export(const device_state_entry &entry, std::st void xavix2_device::execute_run() { - m_pc = check_interrupt(m_pc); + if(!m_ei_count) + m_pc = check_interrupt(m_pc); while(m_icount > 0) { + if(m_ei_count) { + m_ei_count--; + if(!m_ei_count) + m_pc = check_interrupt(m_pc); + } if(machine().debug_flags & DEBUG_FLAG_ENABLED) debugger_instruction_hook(m_pc); @@ -373,10 +384,12 @@ void xavix2_device::execute_run() case 0xe3: /* rti2 */ break; // e4-fb case 0xf8: m_f |= F_I; break; - case 0xf9: m_f &= ~F_I; npc = check_interrupt(npc); break; + case 0xf9: m_f &= ~F_I; m_ei_count = 2; break; case 0xfc: break; - // fd-ff + // fd + case 0xfe: m_wait = true; npc = check_interrupt(npc-1); if(m_wait) m_icount = 0; break; + // ff } m_pc = npc; diff --git a/src/devices/cpu/xavix2/xavix2.h b/src/devices/cpu/xavix2/xavix2.h index c5d86074356..646ca7ebc69 100644 --- a/src/devices/cpu/xavix2/xavix2.h +++ b/src/devices/cpu/xavix2/xavix2.h @@ -21,6 +21,7 @@ protected: F_N = 2, F_C = 4, F_V = 8, + F_MASK = 15, F_I = 16 }; @@ -41,14 +42,14 @@ protected: address_space *m_program; memory_access_cache<2, 0, ENDIANNESS_LITTLE> *m_program_cache; - int m_icount; + int m_icount, m_ei_count; u32 m_pc; u32 m_r[8], m_hr[64]; u32 m_ilr1; u8 m_f; u8 m_if1; - bool m_int_line; + bool m_int_line, m_wait; static inline int r1(u32 opcode) { return (opcode >> 22) & 7; } static inline int r2(u32 opcode) { return (opcode >> 19) & 7; } @@ -81,7 +82,7 @@ protected: f |= F_C; if(((v1 ^ r) & (v2 ^ r)) & 0x80000000) f |= F_V; - m_f = f; + m_f = (m_f & ~F_MASK) | f; return r; } @@ -96,7 +97,7 @@ protected: f |= F_C; if(((v1 ^ v2) & (v2 ^ r)) & 0x80000000) f |= F_V; - m_f = f; + m_f = (m_f & ~F_MASK) | f; return r; } @@ -106,67 +107,67 @@ protected: f |= F_Z; if(r & 0x80000000) f |= F_N; - m_f = f; + m_f = (m_f & ~F_MASK) | f; return r; } inline u32 do_lsl(u32 v1, u32 shift) { if(!shift) { - m_f = v1 ? v1 & 0x80000000 ? F_N : 0 : F_Z; + m_f = (m_f & ~F_MASK) | (v1 ? v1 & 0x80000000 ? F_N : 0 : F_Z); return v1; } else if(shift < 32) { u32 r = v1 << shift; u32 f = v1 ? v1 & 0x80000000 ? F_N : 0 : F_Z; if(v1 & (1 << (32-shift))) f |= F_C; - m_f = f; + m_f = (m_f & ~F_MASK) | f; return r; } else if(shift == 32) { - m_f = v1 & 1 ? F_C|F_Z : F_Z; + m_f = (m_f & ~F_MASK) | (v1 & 1 ? F_C|F_Z : F_Z); return 0; } else { - m_f = F_Z; + m_f = (m_f & ~F_MASK) | F_Z; return 0; } } inline u32 do_lsr(u32 v1, u32 shift) { if(!shift) { - m_f = v1 ? v1 & 0x80000000 ? F_N : 0 : F_Z; + m_f = (m_f & ~F_MASK) | (v1 ? v1 & 0x80000000 ? F_N : 0 : F_Z); return v1; } else if(shift < 32) { u32 r = v1 >> shift; u32 f = v1 ? 0 : F_Z; if(v1 & (1 << (shift - 1))) f |= F_C; - m_f = f; + m_f = (m_f & ~F_MASK) | f; return r; } else if(shift == 32) { - m_f = v1 & 0x80000000 ? F_C|F_Z : F_Z; + m_f = (m_f & ~F_MASK) | (v1 & 0x80000000 ? F_C|F_Z : F_Z); return 0; } else { - m_f = F_Z; + m_f = (m_f & ~F_MASK) | F_Z; return 0; } } inline u32 do_asr(u32 v1, u32 shift) { if(!shift) { - m_f = v1 ? v1 & 0x80000000 ? F_N : 0 : F_Z; + m_f = (m_f & ~F_MASK) | (v1 ? v1 & 0x80000000 ? F_N : 0 : F_Z); return v1; } else if(shift < 32) { u32 r = static_cast<s32>(v1) >> shift; u32 f = v1 ? v1 & 0x80000000 ? F_N : 0 : F_Z; if(v1 & (1 << (shift - 1))) f |= F_C; - m_f = f; + m_f = (m_f & ~F_MASK) | f; return r; } else { if(v1 & 0x80000000) { - m_f = F_C; + m_f = (m_f & ~F_MASK) | F_C; return 0xffffffff; } else { - m_f = F_Z; + m_f = (m_f & ~F_MASK) | F_Z; return 0; } } diff --git a/src/mame/drivers/xavix2.cpp b/src/mame/drivers/xavix2.cpp index f165cd77688..452df360028 100644 --- a/src/mame/drivers/xavix2.cpp +++ b/src/mame/drivers/xavix2.cpp @@ -31,24 +31,139 @@ public: void xavix2(machine_config &config); private: - virtual void machine_start() override; - virtual void machine_reset() override; - - uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + enum { + IRQ_TIMER = 7, + IRQ_DMA = 12 + }; required_device<xavix2_device> m_maincpu; required_device<screen_device> m_screen; required_device<palette_device> m_palette; + u32 m_dma_src; + u16 m_dma_dst; + u16 m_dma_count; + emu_timer *m_dma_timer; + + u32 m_int_active; + + void irq_raise(u32 level); + void irq_clear(u32 level); + bool irq_state(u32 level) const; + u8 irq_level_r(); + + void dma_src_w(offs_t, u32 data, u32 mem_mask); + void dma_dst_w(offs_t, u16 data, u16 mem_mask); + void dma_count_w(offs_t, u16 data, u16 mem_mask); + void dma_control_w(u8 data); + void dma_status_w(u8 data); + u8 dma_status_r(); + + TIMER_CALLBACK_MEMBER(dma_end); + INTERRUPT_GEN_MEMBER(vblank_irq); + + virtual void machine_start() override; + virtual void machine_reset() override; + + uint32_t screen_update(screen_device &screen, bitmap_ind16 &bitmap, const rectangle &cliprect); + void mem(address_map &map); }; +void xavix2_state::irq_raise(u32 level) +{ + if(!m_int_active) + m_maincpu->set_input_line(0, ASSERT_LINE); + m_int_active |= 1 << level; +} + +void xavix2_state::irq_clear(u32 level) +{ + m_int_active &= ~(1 << level); + if(!m_int_active) + m_maincpu->set_input_line(0, CLEAR_LINE); +} + +u8 xavix2_state::irq_level_r() +{ + for(u32 i=31; i>=0; i--) + if(m_int_active & (1 << i)) + return i; + return 0xff; +} + +bool xavix2_state::irq_state(u32 level) const +{ + return m_int_active & (1 << level); +} + +void xavix2_state::dma_src_w(offs_t, u32 data, u32 mem_mask) +{ + COMBINE_DATA(&m_dma_src); +} + +void xavix2_state::dma_dst_w(offs_t, u16 data, u16 mem_mask) +{ + COMBINE_DATA(&m_dma_dst); +} + +void xavix2_state::dma_count_w(offs_t, u16 data, u16 mem_mask) +{ + COMBINE_DATA(&m_dma_count); +} + +void xavix2_state::dma_control_w(u8 data) +{ + if(data == 3 || data == 7) { + logerror("DMA %s:%08x -> %04x (%04x)\n", + data == 3 ? "ram" : "rom", + m_dma_src, m_dma_dst, m_dma_count); + u32 sadr = m_dma_src | (data == 3 ? 0xc0000000 : 0x40000000); + u32 dadr = m_dma_dst | 0xc0000000; + auto &prg = m_maincpu->space(AS_PROGRAM); + for(u32 i=0; i != m_dma_count; i++) + prg.write_byte(dadr + i, prg.read_byte(sadr + i)); + m_dma_timer->adjust(attotime::from_ticks(m_dma_count, m_maincpu->clock())); + } +} + +void xavix2_state::dma_status_w(u8 data) +{ + if(data == 2) + irq_clear(IRQ_DMA); +} + +u8 xavix2_state::dma_status_r() +{ + return irq_state(IRQ_DMA) ? 7 : 0; +} + +TIMER_CALLBACK_MEMBER(xavix2_state::dma_end) +{ + irq_raise(IRQ_DMA); +} + +INTERRUPT_GEN_MEMBER(xavix2_state::vblank_irq) +{ + irq_raise(IRQ_TIMER); +} + + + void xavix2_state::mem(address_map &map) { map(0x00000000, 0x00001fff).ram().share("part1"); + + map(0x00002000, 0x00002003).w(FUNC(xavix2_state::dma_src_w)); + map(0x00002004, 0x00002005).w(FUNC(xavix2_state::dma_dst_w)); + map(0x00002008, 0x00002009).w(FUNC(xavix2_state::dma_count_w)); + map(0x0000200c, 0x0000200c).w(FUNC(xavix2_state::dma_control_w)); + map(0x00002010, 0x00002010).rw(FUNC(xavix2_state::dma_status_r), FUNC(xavix2_state::dma_status_w)); + map(0x00002630, 0x00002631).lr16(NAME([]() { return 0x210; })); map(0x00002632, 0x00002633).lr16(NAME([]() { return 0x210; })); - map(0x00003c00, 0x00003c00).lr8(NAME([]() { return 7; })); // Current active interrupt number + map(0x00003c00, 0x00003c00).r(FUNC(xavix2_state::irq_level_r)); + map(0x00004000, 0x0000ffff).ram().share("part2"); map(0x00010000, 0x00ffffff).rom().region("maincpu", 0x010000); @@ -67,13 +182,15 @@ uint32_t xavix2_state::screen_update(screen_device &screen, bitmap_ind16 &bitmap void xavix2_state::machine_start() { + m_dma_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(xavix2_state::dma_end), this)); } void xavix2_state::machine_reset() { - auto &prg = m_maincpu->space(AS_PROGRAM); - for(u32 adr=0; adr != 0x2000; adr++) - prg.write_byte(adr, prg.read_byte(0x40000000 + adr)); + m_dma_src = 0; + m_dma_dst = 0; + m_dma_count = 0; + m_int_active = 0; } static INPUT_PORTS_START( xavix2 ) @@ -84,7 +201,7 @@ void xavix2_state::xavix2(machine_config &config) // unknown CPU 'SSD 2002-2004 NEC 800208-51' XAVIX2(config, m_maincpu, 98'000'000); m_maincpu->set_addrmap(AS_PROGRAM, &xavix2_state::mem); - m_maincpu->set_vblank_int("screen", FUNC(xavix2_state::irq0_line_hold)); + m_maincpu->set_vblank_int("screen", FUNC(xavix2_state::vblank_irq)); SCREEN(config, m_screen, SCREEN_TYPE_RASTER); m_screen->set_refresh_hz(60); |