-ioc2: Fixed mappable interrupt checks. Fixes IRIX 6.5 installer hanging on keyboard input. [Ryan Holtz]

-r4000: Changed LL/SC behaviour to not use a write tap. Possibly incorrect behaviour, but IRIX 6.5 installer doesn't hang anymore on miniroot creation, nw
This commit is contained in:
mooglyguy 2019-05-12 10:31:37 +02:00 committed by MooglyGuy
parent 7388d5bd12
commit e9a84bc89e
5 changed files with 46 additions and 104 deletions

View File

@ -91,7 +91,7 @@ r4000_base_device::r4000_base_device(const machine_config &mconfig, device_type
: cpu_device(mconfig, type, tag, owner, clock)
, m_program_config_le("program", ENDIANNESS_LITTLE, 64, 32)
, m_program_config_be("program", ENDIANNESS_BIG, 64, 32)
, m_ll_watch(nullptr)
, m_ll_active(false)
, m_fcr0(0x00000500U)
{
m_cp0[CP0_PRId] = prid;
@ -200,11 +200,7 @@ void r4000_base_device::device_reset()
m_cp0_timer_zero = total_cycles();
if (m_ll_watch)
{
m_ll_watch->remove();
m_ll_watch = nullptr;
}
m_ll_active = false;
m_cp0[CP0_WatchLo] = 0;
m_cp0[CP0_WatchHi] = 0;
@ -1033,24 +1029,10 @@ void r4000_base_device::cpu_execute(u32 const op)
load_linked<s32>(ADDR(m_r[RSREG], s16(op)),
[this, op](u64 address, s32 data)
{
// remove existing tap
if (m_ll_watch)
m_ll_watch->remove();
m_r[RTREG] = data;
m_cp0[CP0_LLAddr] = u32(address >> 4);
// install write tap
// FIXME: physical address truncation
m_ll_watch = space(0).install_write_tap(offs_t(address & ~7), offs_t(address | 7), "ll",
[this, hi(bool(BIT(address, 2)))](offs_t offset, u64 &data, u64 mem_mask)
{
if (hi ? ACCESSING_BITS_32_63 : ACCESSING_BITS_0_31)
{
m_ll_watch->remove();
m_ll_watch = nullptr;
}
});
m_ll_active = true;
m_ll_addr = ADDR(m_r[RSREG], s16(op));
});
break;
@ -1066,20 +1048,10 @@ void r4000_base_device::cpu_execute(u32 const op)
[this, op](u64 address, u64 data)
{
// remove existing tap
if (m_ll_watch)
m_ll_watch->remove();
m_r[RTREG] = data;
m_cp0[CP0_LLAddr] = u32(address >> 4);
// install write tap
// FIXME: address truncation
m_ll_watch = space(0).install_write_tap(offs_t(address & ~7), offs_t(address | 7), "lld",
[this](offs_t offset, u64 &data, u64 mem_mask)
{
m_ll_watch->remove();
m_ll_watch = nullptr;
});
m_ll_active = true;
m_ll_addr = ADDR(m_r[RSREG], s16(op));
});
break;
@ -1097,10 +1069,9 @@ void r4000_base_device::cpu_execute(u32 const op)
});
break;
case 0x38: // SC
if (m_ll_watch && m_ll_addr == ADDR(m_r[RSREG], s16(op)))
if (m_ll_active && m_ll_addr == ADDR(m_r[RSREG], s16(op)))
{
m_ll_watch->remove();
m_ll_watch = nullptr;
m_ll_active = false;
store<u32>(ADDR(m_r[RSREG], s16(op)), u32(m_r[RTREG]));
m_r[RTREG] = 1;
@ -1116,11 +1087,8 @@ void r4000_base_device::cpu_execute(u32 const op)
break;
//case 0x3b: // *
case 0x3c: // SCD
if (m_ll_watch && m_ll_addr == ADDR(m_r[RSREG], s16(op)))
if (m_ll_active && m_ll_addr == ADDR(m_r[RSREG], s16(op)))
{
m_ll_watch->remove();
m_ll_watch = nullptr;
store<u64>(ADDR(m_r[RSREG], s16(op)), m_r[RTREG]);
m_r[RTREG] = 1;
}
@ -1358,11 +1326,7 @@ void r4000_base_device::cp0_execute(u32 const op)
SR &= ~SR_EXL;
}
if (m_ll_watch)
{
m_ll_watch->remove();
m_ll_watch = nullptr;
}
m_ll_active = false;
break;
default:

View File

@ -394,7 +394,7 @@ protected:
u64 m_cp0[32];
u64 m_cp0_timer_zero;
emu_timer *m_cp0_timer;
memory_passthrough_handler *m_ll_watch;
bool m_ll_active;
u64 m_ll_addr;
struct tlb_entry_t
{

View File

@ -414,11 +414,11 @@ READ32_MEMBER(hpc3_device::pbus4_r)
break;
case 0x0014/4:
ret = m_ioc2->get_map_int_mask(0);
LOGMASKED(LOG_PBUS4, "%s: HPC3 INT3 Mapped Interrupt 0 Read: %08x & %08x\n", machine().describe_context(), ret, mem_mask);
LOGMASKED(LOG_PBUS4, "%s: HPC3 INT3 Mapped Interrupt 0 Mask Read: %08x & %08x\n", machine().describe_context(), ret, mem_mask);
break;
case 0x0018/4:
ret = m_ioc2->get_map_int_mask(1);
LOGMASKED(LOG_PBUS4, "%s: HPC3 INT3 Mapped Interrupt 1 Read: %08x & %08x\n", machine().describe_context(), ret, mem_mask);
LOGMASKED(LOG_PBUS4, "%s: HPC3 INT3 Mapped Interrupt 1 Mask Read: %08x & %08x\n", machine().describe_context(), ret, mem_mask);
break;
case 0x0030/4:
ret = m_ioc2->get_pit_reg(0);
@ -457,11 +457,11 @@ WRITE32_MEMBER(hpc3_device::pbus4_w)
break;
case 0x0014/4:
m_ioc2->set_map_int_mask(0, data);
LOGMASKED(LOG_PBUS4, "%s: HPC3 INT3 Mapped Interrupt 0 Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
LOGMASKED(LOG_PBUS4, "%s: HPC3 INT3 Mapped Interrupt 0 Mask Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
break;
case 0x0018/4:
m_ioc2->set_map_int_mask(1, data);
LOGMASKED(LOG_PBUS4, "%s: HPC3 INT3 Mapped Interrupt 1 Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
LOGMASKED(LOG_PBUS4, "%s: HPC3 INT3 Mapped Interrupt 1 Mask Write: %08x & %08x\n", machine().describe_context(), data, mem_mask);
break;
case 0x0020/4:
m_ioc2->set_timer_int_clear(data);

View File

@ -23,7 +23,7 @@
#define LOG_PIT (1 << 10)
#define LOG_IRQS (1 << 11)
#define LOG_ALL (LOG_PI1 | LOG_SERIAL | LOG_MOUSEKBD | LOG_PANEL | LOG_SYSID | LOG_READ | LOG_DMA_SEL | LOG_RESET | LOG_WRITE | LOG_INT3 | LOG_PIT | LOG_IRQS)
#define LOG_DEFAULT (LOG_ALL & ~(LOG_SYSID | LOG_MOUSEKBD))
#define LOG_DEFAULT (LOG_ALL & ~(LOG_SYSID))
#define VERBOSE (0)
#include "logmacro.h"
@ -238,23 +238,31 @@ void ioc2_device::set_mappable_int(uint8_t mask, bool state)
const uint8_t new0 = m_int3_map_mask_reg[0] & m_int3_map_status_reg;
if (old0 ^ new0)
{
LOGMASKED(LOG_IRQS, "%sing Mappable interrupt mask %02x, interrupt status was %02x, now %02x, %sing mappable0\n", state ? "Rais" : "Lower", mask, old,
m_int3_map_status_reg, (m_int3_map_mask_reg[0] & m_int3_map_status_reg) ? "rais" : "lower");
if (m_int3_map_mask_reg[0] & m_int3_map_status_reg)
raise_local_irq(0, INT3_LOCAL0_MAPPABLE0);
else
lower_local_irq(0, INT3_LOCAL0_MAPPABLE0);
check_mappable_interrupt(0);
}
const uint8_t new1 = m_int3_map_mask_reg[1] & m_int3_map_status_reg;
if (old1 ^ new1)
{
LOGMASKED(LOG_IRQS, "%sing Mappable interrupt mask %02x, interrupt status was %02x, now %02x, %sing mappable1\n", state ? "Rais" : "Lower", mask, old,
m_int3_map_status_reg, (m_int3_map_mask_reg[0] & m_int3_map_status_reg) ? "rais" : "lower");
if (m_int3_map_mask_reg[1] & m_int3_map_status_reg)
raise_local_irq(1, INT3_LOCAL1_MAPPABLE1);
check_mappable_interrupt(1);
}
}
void ioc2_device::check_mappable_interrupt(int channel)
{
if (channel == 0)
{
if (m_int3_map_mask_reg[channel] & m_int3_map_status_reg)
raise_local_irq(channel, INT3_LOCAL0_MAPPABLE0);
else
lower_local_irq(1, INT3_LOCAL1_MAPPABLE1);
lower_local_irq(channel, INT3_LOCAL0_MAPPABLE0);
}
else
{
if (m_int3_map_mask_reg[channel] & m_int3_map_status_reg)
raise_local_irq(channel, INT3_LOCAL1_MAPPABLE1);
else
lower_local_irq(channel, INT3_LOCAL1_MAPPABLE1);
}
}
@ -330,13 +338,13 @@ READ32_MEMBER(ioc2_device::read)
case KBD_MOUSE_REGS1:
{
const uint8_t data = m_kbdc->data_r(space, (offset - KBD_MOUSE_REGS1) * 4);
const uint8_t data = m_kbdc->data_r(space, 0);
LOGMASKED(LOG_MOUSEKBD, "%s: Read Keyboard/Mouse Register 1: %02x\n", machine().describe_context(), data);
return data;
}
case KBD_MOUSE_REGS2:
{
const uint8_t data = m_kbdc->data_r(space, (offset - KBD_MOUSE_REGS1) * 4);
const uint8_t data = m_kbdc->data_r(space, 4);
LOGMASKED(LOG_MOUSEKBD, "%s: Read Keyboard/Mouse Register 2: %02x\n", machine().describe_context(), data);
return data;
}
@ -385,64 +393,44 @@ READ32_MEMBER(ioc2_device::read)
return m_write_reg;
case INT3_LOCAL0_STATUS_REG:
{
LOGMASKED(LOG_INT3, "%s: Read Interrupt Local0 Status Register: %02x\n", machine().describe_context(), m_int3_local_status_reg[0]);
return m_int3_local_status_reg[0];
}
case INT3_LOCAL0_MASK_REG:
{
LOGMASKED(LOG_INT3, "%s: Read Interrupt Local0 Mask Register: %02x\n", machine().describe_context(), m_int3_local_mask_reg[0]);
return m_int3_local_mask_reg[0];
}
case INT3_LOCAL1_STATUS_REG:
{
LOGMASKED(LOG_INT3, "%s: Read Interrupt Local1 Status Register: %02x\n", machine().describe_context(), m_int3_local_status_reg[1]);
return m_int3_local_status_reg[1];
}
case INT3_LOCAL1_MASK_REG:
{
LOGMASKED(LOG_INT3, "%s: Read Interrupt Local1 Mask Register: %02x\n", machine().describe_context(), m_int3_local_mask_reg[1]);
return m_int3_local_mask_reg[1];
}
case INT3_MAP_STATUS_REG:
{
LOGMASKED(LOG_INT3, "%s: Read Interrupt Map Status Register: %02x\n", machine().describe_context(), m_int3_map_status_reg);
return m_int3_map_status_reg;
}
case INT3_MAP_MASK0_REG:
{
LOGMASKED(LOG_INT3, "%s: Read Interrupt Map Mask0 Register: %02x\n", machine().describe_context(), m_int3_map_mask_reg[0]);
return m_int3_map_mask_reg[0];
}
case INT3_MAP_MASK1_REG:
{
LOGMASKED(LOG_INT3, "%s: Read Interrupt Map Mask1 Register: %02x\n", machine().describe_context(), m_int3_map_mask_reg[1]);
return m_int3_map_mask_reg[1];
}
case INT3_MAP_POLARITY_REG:
{
LOGMASKED(LOG_INT3, "%s: Read Interrupt Map Polarity Register: %02x\n", machine().describe_context(), m_int3_map_pol_reg);
return m_int3_map_pol_reg;
}
case INT3_TIMER_CLEAR_REG:
{
LOGMASKED(LOG_INT3, "%s: Read Interrupt Timer Clear (ignored)\n", machine().describe_context());
return 0;
}
case INT3_ERROR_STATUS_REG:
{
LOGMASKED(LOG_INT3, "%s: Read Interrupt Error Status Register: %02x\n", machine().describe_context(), m_int3_err_status_reg);
return m_int3_err_status_reg;
}
case TIMER_COUNT0_REG:
{
@ -514,28 +502,28 @@ WRITE32_MEMBER( ioc2_device::write )
case SERIAL1_CMD_REG:
LOGMASKED(LOG_SERIAL, "%s: Write Serial 1 Command Register: %02x\n", machine().describe_context(), (uint8_t)data);
m_scc->ba_cd_w(space, (offset - SERIAL1_CMD_REG) ^ 3, data & 0xff);
m_scc->ba_cd_w(space, 3, data & 0xff);
return;
case SERIAL1_DATA_REG:
LOGMASKED(LOG_SERIAL, "%s: Write Serial 1 Data Register: %02x\n", machine().describe_context(), (uint8_t)data);
m_scc->ba_cd_w(space, (offset - SERIAL1_CMD_REG) ^ 3, data & 0xff);
m_scc->ba_cd_w(space, 2, data & 0xff);
return;
case SERIAL2_CMD_REG:
LOGMASKED(LOG_SERIAL, "%s: Write Serial 2 Command Register: %02x\n", machine().describe_context(), (uint8_t)data);
m_scc->ba_cd_w(space, (offset - SERIAL1_CMD_REG) ^ 3, data & 0xff);
m_scc->ba_cd_w(space, 1, data & 0xff);
return;
case SERIAL2_DATA_REG:
LOGMASKED(LOG_SERIAL, "%s: Write Serial 2 Data Register: %02x\n", machine().describe_context(), (uint8_t)data);
m_scc->ba_cd_w(space, (offset - SERIAL1_CMD_REG) ^ 3, data & 0xff);
m_scc->ba_cd_w(space, 0, data & 0xff);
return;
case KBD_MOUSE_REGS1:
LOGMASKED(LOG_MOUSEKBD, "%s: Write Keyboard/Mouse Register 1: %02x\n", machine().describe_context(), (uint8_t)data);
m_kbdc->data_w(space, (offset - KBD_MOUSE_REGS1) * 4, data & 0xff);
m_kbdc->data_w(space, 0, data & 0xff);
return;
case KBD_MOUSE_REGS2:
LOGMASKED(LOG_MOUSEKBD, "%s: Write Keyboard/Mouse Register 2: %02x\n", machine().describe_context(), (uint8_t)data);
m_kbdc->data_w(space, (offset - KBD_MOUSE_REGS1) * 4, data & 0xff);
m_kbdc->data_w(space, 4, data & 0xff);
return;
case PANEL_REG:
@ -575,7 +563,7 @@ WRITE32_MEMBER( ioc2_device::write )
return;
case WRITE_REG:
LOGMASKED(LOG_RESET, "%s: Write Write Register: %02x\n", machine().describe_context(), (uint8_t)data);
LOGMASKED(LOG_WRITE, "%s: Write Write Register: %02x\n", machine().describe_context(), (uint8_t)data);
m_write_reg = data;
return;
@ -587,43 +575,31 @@ WRITE32_MEMBER( ioc2_device::write )
return;
case INT3_LOCAL0_MASK_REG:
{
LOGMASKED(LOG_INT3, "%s: Write Interrupt Local0 Mask Register: %02x\n", machine().describe_context(), (uint8_t)data);
set_local_int_mask(0, data);
return;
}
case INT3_LOCAL1_MASK_REG:
{
LOGMASKED(LOG_INT3, "%s: Write Interrupt Local1 Mask Register: %02x\n", machine().describe_context(), (uint8_t)data);
set_local_int_mask(1, data);
return;
}
case INT3_MAP_MASK0_REG:
// TODO: Implement mappable interrupts
LOGMASKED(LOG_INT3, "%s: Write Interrupt Map Mask0 Register: %02x\n", machine().describe_context(), (uint8_t)data);
set_map_int_mask(0, data);
return;
case INT3_MAP_MASK1_REG:
// TODO: Implement mappable interrupts
LOGMASKED(LOG_INT3, "%s: Write Interrupt Map Mask1 Register: %02x\n", machine().describe_context(), (uint8_t)data);
set_map_int_mask(1, data);
return;
case INT3_MAP_POLARITY_REG:
// TODO: Mappable interrupt polarity select
LOGMASKED(LOG_INT3, "%s: Write Interrupt Map Polarity Register: %02x\n", machine().describe_context(), (uint8_t)data);
m_int3_map_pol_reg = data;
return;
case INT3_TIMER_CLEAR_REG:
{
LOGMASKED(LOG_INT3, "%s: Write Interrupt Timer Clear Register: %02x\n", machine().describe_context(), (uint8_t)data);
set_timer_int_clear(data);
return;
}
case TIMER_COUNT0_REG:
LOGMASKED(LOG_PIT, "%s: Write Timer Count0 Register: %02x\n", machine().describe_context(), (uint8_t)data);
@ -660,6 +636,7 @@ void ioc2_device::set_local_int_mask(int channel, uint32_t mask)
void ioc2_device::set_map_int_mask(int channel, uint32_t mask)
{
m_int3_map_mask_reg[channel] = (uint8_t)mask;
check_mappable_interrupt(channel);
}
void ioc2_device::set_timer_int_clear(uint32_t data)

View File

@ -32,7 +32,7 @@ public:
void raise_local_irq(int channel, uint8_t mask);
void lower_local_irq(int channel, uint8_t mask);
enum
enum : uint8_t
{
INT3_LOCAL0_FIFO = 0x01,
INT3_LOCAL0_SCSI0 = 0x02,
@ -44,7 +44,7 @@ public:
INT3_LOCAL0_MAPPABLE0 = 0x80,
};
enum
enum : uint8_t
{
INT3_LOCAL1_GP0 = 0x01,
INT3_LOCAL1_PANEL = 0x02,
@ -83,6 +83,7 @@ protected:
DECLARE_WRITE_LINE_MEMBER(duart_int_w);
void set_mappable_int(uint8_t mask, bool state);
void check_mappable_interrupt(int channel);
enum
{