labtam: improved interrupt map logic

This commit is contained in:
Patrick Mackinlay 2022-06-16 15:01:49 +07:00
parent e7fe75fd5c
commit 184259c82d
2 changed files with 30 additions and 32 deletions

View File

@ -62,7 +62,8 @@ enum drvstatus_mask : u8
DRVSTATUS_G = 0x08, // FD3 is mini floppy DRVSTATUS_G = 0x08, // FD3 is mini floppy
DRVSTATUS_B = 0x10, // not used DRVSTATUS_B = 0x10, // not used
DRVSTATUS_D = 0x20, // not used DRVSTATUS_D = 0x20, // not used
DRVSTATUS_SS = 0x40, // 8" floppy is single-sided DRVSTATUS_F = 0x40, // ?
DRVSTATUS_DS = 0x80, // floppy is double-sided
}; };
DEFINE_DEVICE_TYPE(LABTAM_Z80SBC, labtam_z80sbc_device, "labtam_z80sbc", "Labtam Z80 SBC") DEFINE_DEVICE_TYPE(LABTAM_Z80SBC, labtam_z80sbc_device, "labtam_z80sbc", "Labtam Z80 SBC")
@ -240,6 +241,7 @@ void labtam_z80sbc_device::device_start()
save_item(NAME(m_map_mux)); save_item(NAME(m_map_mux));
save_item(NAME(m_map_num)); save_item(NAME(m_map_num));
save_item(NAME(m_map_cnt));
} }
void labtam_z80sbc_device::device_reset() void labtam_z80sbc_device::device_reset()
@ -264,6 +266,7 @@ void labtam_z80sbc_device::device_reset()
m_map_mux = 0; m_map_mux = 0;
m_map_num = 0; m_map_num = 0;
m_map_cnt = 0;
m_fdcstatus = 0x3c; m_fdcstatus = 0x3c;
m_dma[0]->iei_w(1); m_dma[0]->iei_w(1);
@ -283,7 +286,6 @@ void labtam_z80sbc_device::device_add_mconfig(machine_config &config)
{ {
Z80(config, m_cpu, 20_MHz_XTAL / 4); Z80(config, m_cpu, 20_MHz_XTAL / 4);
m_cpu->set_addrmap(AS_PROGRAM, &labtam_z80sbc_device::cpu_mem); m_cpu->set_addrmap(AS_PROGRAM, &labtam_z80sbc_device::cpu_mem);
m_cpu->set_addrmap(AS_OPCODES, &labtam_z80sbc_device::cpu_mem);
m_cpu->set_addrmap(AS_IO, &labtam_z80sbc_device::cpu_pio); m_cpu->set_addrmap(AS_IO, &labtam_z80sbc_device::cpu_pio);
m_cpu->irqack_cb().set([this](int state) { m_map_mux |= MM_PND; }); m_cpu->irqack_cb().set([this](int state) { m_map_mux |= MM_PND; });
m_cpu->set_daisy_config(daisy_chain); m_cpu->set_daisy_config(daisy_chain);
@ -389,13 +391,18 @@ void labtam_z80sbc_device::cpu_pio(address_map &map)
map(0x00e0, 0x00ff).mirror(0xff00).rw(m_rtc, FUNC(mm58167_device::read), FUNC(mm58167_device::write)); map(0x00e0, 0x00ff).mirror(0xff00).rw(m_rtc, FUNC(mm58167_device::read), FUNC(mm58167_device::write));
} }
u8 labtam_z80sbc_device::mem_r(address_space &space, offs_t offset) u8 labtam_z80sbc_device::mem_r(offs_t offset)
{ {
// check for and complete pending map number change // check for and complete pending map number change
if ((m_map_mux & MM_PND) && (space.spacenum() == AS_PROGRAM) && !machine().side_effects_disabled()) if ((m_map_mux & MM_PND) && !machine().side_effects_disabled())
{ {
m_map_mux &= ~MM_PND; if (m_map_cnt == 0)
m_map_mux ^= MM_INT; {
m_map_mux &= ~MM_PND;
m_map_mux ^= MM_INT;
}
else
m_map_cnt--;
} }
if (m_map_mux & MM_ENB) if (m_map_mux & MM_ENB)
@ -485,27 +492,17 @@ void labtam_z80sbc_device::map_w(unsigned map_num, offs_t offset, u8 data)
void labtam_z80sbc_device::intswt_w(u8 data) void labtam_z80sbc_device::intswt_w(u8 data)
{ {
/* /*
* Writing to this port toggles between interrupt (map number forced to 0) and * Writing to this port deactivates the interrupt map after the next three
* user (map number from mapnum latch) mode. The mapping mode can be applied * Z80 memory read cycles. This delay supports interrupt return, allowing
* immediately, or only upon the next non-instruction memory read. The delay * the standard epilogue of NOP, EI, and RET to be fetched and executed
* mechanism is used to support interrupts: * from map 0, before the return address is fetched from the non-interrupt
* * memory map.
* - When an interrupt is taken, the delayed map change allows the Z80 to
* store the return address on the currently mapped stack, before switching
* to map 0 to fetch the interrupt vector address.
*
* - When returning from an interrupt handler, the delayed map change allows
* further instructions (including RET) to be fetched from the interrupt
* service routine using map 0, while the return address will be fetched
* from the user mapped stack.
*/ */
LOG("intswt_w 0x%02x mapnum 0x%02x (%s)\n", data, m_map_num, machine().describe_context()); LOG("intswt map 0x%02x mux 0x%02x (%s)\n", m_map_num, m_map_mux, machine().describe_context());
if (BIT(data, 0)) m_map_mux |= MM_PND;
m_map_mux ^= MM_INT; m_map_cnt = 3;
else
m_map_mux |= MM_PND;
} }
void labtam_z80sbc_device::mapnum_w(u8 data) void labtam_z80sbc_device::mapnum_w(u8 data)
@ -515,7 +512,7 @@ void labtam_z80sbc_device::mapnum_w(u8 data)
m_map_mux |= MM_ENB; m_map_mux |= MM_ENB;
// TODO: what are bits 3, 4 and 5 used for? // TODO: what are bits 3, 4 and 5 used for?
m_map_num = data & 0x3f; m_map_num = data & 0x07;
} }
void labtam_z80sbc_device::fdcint_w(int state) void labtam_z80sbc_device::fdcint_w(int state)
@ -596,12 +593,12 @@ u8 labtam_z80sbc_device::drvstatus_r()
{ {
u8 data = m_e21->read(); u8 data = m_e21->read();
// TODO: read selected floppy twosid_r() if (m_drive)
#if 0 {
floppy_image_device *fid = m_fdd[*m_drive]->get_device(); floppy_image_device *fid = m_fdd[*m_drive]->get_device();
if (fid && !fid->twosid_r()) if (fid && !fid->twosid_r())
data |= DRVSTATUS_SS; data |= DRVSTATUS_DS;
#endif }
return data; return data;
} }

View File

@ -41,7 +41,7 @@ private:
void cpu_pio(address_map &map); void cpu_pio(address_map &map);
// cpu memory handlers // cpu memory handlers
u8 mem_r(address_space &space, offs_t offset); u8 mem_r(offs_t offset);
void mem_w(offs_t offset, u8 data); void mem_w(offs_t offset, u8 data);
// memory mapping handlers // memory mapping handlers
@ -85,6 +85,7 @@ private:
u8 m_map_mux; u8 m_map_mux;
u8 m_map_num; u8 m_map_num;
u8 m_map_cnt;
u8 m_fdcstatus; u8 m_fdcstatus;
std::optional<u8> m_drive; std::optional<u8> m_drive;