xavix2: Add dma, completion issues (nw)

This commit is contained in:
Olivier Galibert 2020-02-12 06:48:31 +01:00
parent 6b3a689ce1
commit ad06ccc77c
3 changed files with 162 additions and 31 deletions

View File

@ -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;

View File

@ -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;
}
}

View File

@ -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);