summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
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
commitad06ccc77c9094966dbbeba82e6267661c5f9115 (patch)
tree63302c33e64239570f36162b0a001ffbd3fd133e
parent6b3a689ce15e5536034a7b288dce31bc6b20073f (diff)
xavix2: Add dma, completion issues (nw)
-rw-r--r--src/devices/cpu/xavix2/xavix2.cpp23
-rw-r--r--src/devices/cpu/xavix2/xavix2.h35
-rw-r--r--src/mame/drivers/xavix2.cpp135
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);