mirror of
https://github.com/holub/mame
synced 2025-04-22 16:31:49 +03:00
romp: various improvements and fixes
* handle mmu exceptions in load/store instructions * implement wait instruction * fix "and link register" instructions when target == link * fix illegal branch subject instruction exception address * fix i/o instruction exception type * fix lps address space selection * don't use irb for hardware interrupts
This commit is contained in:
parent
09d755e44e
commit
9ee3522842
@ -8,8 +8,9 @@
|
||||
* - http://bitsavers.org/pdf/ibm/pc/rt/6489893_RT_PC_Technical_Reference_Volume_1_Nov85.pdf
|
||||
*
|
||||
* TODO:
|
||||
* - mmu/iocc exceptions
|
||||
* - unimplemented instructions (wait)
|
||||
* - instruction fetch and rmw cycles
|
||||
* - multiple exceptions
|
||||
* - check stop mask
|
||||
*/
|
||||
|
||||
#include "emu.h"
|
||||
@ -36,6 +37,7 @@ romp_device::romp_device(machine_config const &mconfig, char const *tag, device_
|
||||
, m_mem_config("memory", ENDIANNESS_BIG, 32, 32)
|
||||
, m_io_config("io", ENDIANNESS_BIG, 32, 24, -2)
|
||||
, m_icount(0)
|
||||
, m_reqi(0)
|
||||
{
|
||||
}
|
||||
|
||||
@ -65,7 +67,13 @@ void romp_device::device_start()
|
||||
// register state for saving
|
||||
save_item(NAME(m_scr));
|
||||
save_item(NAME(m_gpr));
|
||||
|
||||
save_item(NAME(m_reqi));
|
||||
save_item(NAME(m_trap));
|
||||
save_item(NAME(m_error));
|
||||
|
||||
save_item(NAME(m_branch_state));
|
||||
save_item(NAME(m_branch_source));
|
||||
save_item(NAME(m_branch_target));
|
||||
}
|
||||
|
||||
@ -87,8 +95,6 @@ void romp_device::state_string_export(device_state_entry const &entry, std::stri
|
||||
|
||||
void romp_device::device_reset()
|
||||
{
|
||||
space(0).cache(m_mem);
|
||||
|
||||
// TODO: assumed
|
||||
for (u32 &scr : m_scr)
|
||||
scr = 0;
|
||||
@ -98,9 +104,14 @@ void romp_device::device_reset()
|
||||
gpr = 0;
|
||||
|
||||
// initialize the state
|
||||
m_scr[IAR] = m_mem.read_dword(0);
|
||||
m_branch_state = DEFAULT;
|
||||
set_space(m_scr[ICS]);
|
||||
|
||||
m_trap = false;
|
||||
m_error = false;
|
||||
m_branch_state = DEFAULT;
|
||||
|
||||
// fetch initial iar
|
||||
m_scr[IAR] = m_mem.read_dword(0);
|
||||
}
|
||||
|
||||
void romp_device::execute_run()
|
||||
@ -108,63 +119,104 @@ void romp_device::execute_run()
|
||||
// core execution loop
|
||||
while (m_icount-- > 0)
|
||||
{
|
||||
// debugging
|
||||
debugger_instruction_hook(m_scr[IAR]);
|
||||
m_error = false;
|
||||
|
||||
if (m_branch_state == DEFAULT)
|
||||
if (m_branch_state != BRANCH)
|
||||
interrupt_check();
|
||||
|
||||
if (m_branch_state == WAIT)
|
||||
{
|
||||
m_icount = 0;
|
||||
return;
|
||||
}
|
||||
else
|
||||
debugger_instruction_hook(m_scr[IAR]);
|
||||
|
||||
// fetch instruction
|
||||
u16 const op = m_mem.read_word(m_scr[IAR]);
|
||||
u32 updated_iar = m_scr[IAR] + 2;
|
||||
if (m_error)
|
||||
program_check(PCS_PCK | PCS_IAE);
|
||||
|
||||
switch (op >> 12)
|
||||
{
|
||||
case 0x0: // jb/jnb: jump on [not] condition bit
|
||||
if (m_branch_state == BRANCH)
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
else if (BIT(m_scr[CS], ((op >> 8) & 7) ^ 7) == BIT(op, 11))
|
||||
if (m_branch_state != BRANCH)
|
||||
{
|
||||
m_branch_target = m_scr[IAR] + ji(op);
|
||||
m_branch_state = BRANCH;
|
||||
m_icount -= 4;
|
||||
if (BIT(m_scr[CS], ((op >> 8) & 7) ^ 7) == BIT(op, 11))
|
||||
{
|
||||
m_branch_target = m_scr[IAR] + ji(op);
|
||||
m_branch_state = BRANCH;
|
||||
m_icount -= 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC, m_branch_source);
|
||||
break;
|
||||
case 0x1: // stcs: store character short
|
||||
m_mem.write_byte(r3_0(R3) + ((op >> 8) & 15), m_gpr[R2]);
|
||||
if (m_error)
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= 4;
|
||||
break;
|
||||
case 0x2: // sths: store half short
|
||||
m_mem.write_word(r3_0(R3) + ((op >> 7) & 30), m_gpr[R2]);
|
||||
if (m_error)
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= 4;
|
||||
break;
|
||||
case 0x3: // sts: store short
|
||||
m_mem.write_dword(r3_0(R3) + ((op >> 6) & 60), m_gpr[R2]);
|
||||
if (m_error)
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= 4;
|
||||
break;
|
||||
case 0x4: // lcs: load character short
|
||||
m_gpr[R2] = m_mem.read_byte(r3_0(R3) + ((op >> 8) & 15));
|
||||
m_icount -= 4;
|
||||
{
|
||||
u8 const data = m_mem.read_byte(r3_0(R3) + ((op >> 8) & 15));
|
||||
if (!m_error)
|
||||
m_gpr[R2] = data;
|
||||
else
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= 4;
|
||||
}
|
||||
break;
|
||||
case 0x5: // lhas: load half algebraic short
|
||||
m_gpr[R2] = s32(s16(m_mem.read_word(r3_0(R3) + ((op >> 7) & 30))));
|
||||
m_icount -= 4;
|
||||
{
|
||||
s32 const data = s32(s16(m_mem.read_word(r3_0(R3) + ((op >> 7) & 30))));
|
||||
if (!m_error)
|
||||
m_gpr[R2] = data;
|
||||
else
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= 4;
|
||||
}
|
||||
break;
|
||||
case 0x6: // cas: compute address short
|
||||
m_gpr[(op >> 8) & 15] = m_gpr[R2] + r3_0(R3);
|
||||
break;
|
||||
case 0x7: // ls: load short
|
||||
m_gpr[R2] = m_mem.read_dword(r3_0(R3) + ((op >> 6) & 60));
|
||||
m_icount -= 4;
|
||||
{
|
||||
u32 const data = m_mem.read_dword(r3_0(R3) + ((op >> 6) & 60));
|
||||
if (!m_error)
|
||||
m_gpr[R2] = data;
|
||||
else
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= 4;
|
||||
}
|
||||
break;
|
||||
case 0x8: // BI, BA format
|
||||
{
|
||||
u16 const b = m_mem.read_word(updated_iar);
|
||||
updated_iar += 2;
|
||||
if (m_error)
|
||||
{
|
||||
program_check(PCS_PCK | PCS_IAE);
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_branch_state == BRANCH)
|
||||
{
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
program_check(PCS_PCK | PCS_IOC, m_branch_source);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -181,6 +233,7 @@ void romp_device::execute_run()
|
||||
case 0x89: // bnbx: branch on not condition bit immediate with execute
|
||||
if (!BIT(m_scr[CS], R2 ^ 15))
|
||||
{
|
||||
m_branch_source = m_scr[IAR];
|
||||
m_branch_target = m_scr[IAR] + bi(op, b);
|
||||
m_branch_state = DELAY;
|
||||
m_icount -= 4;
|
||||
@ -194,6 +247,7 @@ void romp_device::execute_run()
|
||||
break;
|
||||
case 0x8b: // balax: branch and link absolute with execute
|
||||
m_gpr[15] = updated_iar + 4;
|
||||
m_branch_source = m_scr[IAR];
|
||||
m_branch_target = ba(op, b);
|
||||
m_branch_state = DELAY;
|
||||
m_icount -= 4;
|
||||
@ -206,6 +260,7 @@ void romp_device::execute_run()
|
||||
break;
|
||||
case 0x8d: // balix: branch and link immediate with execute
|
||||
m_gpr[R2] = updated_iar + 4;
|
||||
m_branch_source = m_scr[IAR];
|
||||
m_branch_target = m_scr[IAR] + bi(op, b);
|
||||
m_branch_state = DELAY;
|
||||
m_icount -= 4;
|
||||
@ -221,6 +276,7 @@ void romp_device::execute_run()
|
||||
case 0x8f: // bbx: branch on condition bit immediate with execute
|
||||
if (BIT(m_scr[CS], R2 ^ 15))
|
||||
{
|
||||
m_branch_source = m_scr[IAR];
|
||||
m_branch_target = m_scr[IAR] + bi(op, b);
|
||||
m_branch_state = DELAY;
|
||||
m_icount -= 4;
|
||||
@ -239,6 +295,11 @@ void romp_device::execute_run()
|
||||
{
|
||||
u16 const i = m_mem.read_word(updated_iar);
|
||||
updated_iar += 2;
|
||||
if (m_error)
|
||||
{
|
||||
program_check(PCS_PCK | PCS_IAE);
|
||||
break;
|
||||
}
|
||||
|
||||
u32 const r3 = R3 ? m_gpr[R3] : 0;
|
||||
|
||||
@ -253,7 +314,7 @@ void romp_device::execute_run()
|
||||
m_icount -= 15;
|
||||
}
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
program_check(PCS_PCK | PCS_IOC, m_branch_source);
|
||||
break;
|
||||
case 0xc1: // ai: add immediate
|
||||
flags_add(m_gpr[R3], s32(s16(i)));
|
||||
@ -288,41 +349,77 @@ void romp_device::execute_run()
|
||||
case 0xc9: // lm: load multiple
|
||||
for (unsigned reg = R2, offset = r3 + s16(i); reg < 16; reg++, offset += 4)
|
||||
{
|
||||
m_gpr[reg] = m_mem.read_dword(offset);
|
||||
u32 const data = m_mem.read_dword(offset);
|
||||
if (!m_error)
|
||||
m_gpr[reg] = data;
|
||||
m_icount -= 2;
|
||||
}
|
||||
if (m_error)
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= (m_scr[ICS] & ICS_TM) ? 3 : 1;
|
||||
break;
|
||||
case 0xca: // lha: load half algebraic
|
||||
m_gpr[R2] = s32(s16(m_mem.read_word(r3 + s16(i))));
|
||||
m_icount -= 4;
|
||||
{
|
||||
s32 const data = s32(s16(m_mem.read_word(r3 + s16(i))));
|
||||
if (!m_error)
|
||||
m_gpr[R2] = data;
|
||||
else
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= 4;
|
||||
}
|
||||
break;
|
||||
case 0xcb: // ior: input/output read
|
||||
if (r3 + i < 0x0100'0000U)
|
||||
if (!((r3 + i) & 0xff00'0000U))
|
||||
m_gpr[R2] = space(AS_IO).read_dword(r3 + i);
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
break;
|
||||
case 0xcc: // ti: trap on condition immediate
|
||||
if (m_branch_state == BRANCH)
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
else if ((BIT(op, 6) && (m_gpr[R3] < u32(s32(s16(i)))))
|
||||
|| (BIT(op, 5) && (m_gpr[R3] == u32(s32(s16(i)))))
|
||||
|| (BIT(op, 4) && (m_gpr[R3] > u32(s32(s16(i))))))
|
||||
program_check(PCS_PCK | PCS_PT);
|
||||
if (m_branch_state != BRANCH)
|
||||
{
|
||||
if ((BIT(op, 6) && (m_gpr[R3] < u32(s32(s16(i)))))
|
||||
|| (BIT(op, 5) && (m_gpr[R3] == u32(s32(s16(i)))))
|
||||
|| (BIT(op, 4) && (m_gpr[R3] > u32(s32(s16(i))))))
|
||||
program_check(PCS_PCK | PCS_PT);
|
||||
}
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC, m_branch_source);
|
||||
break;
|
||||
case 0xcd: // l: load
|
||||
m_gpr[R2] = m_mem.read_dword(r3 + s16(i));
|
||||
m_icount -= 4;
|
||||
{
|
||||
u32 const data = m_mem.read_dword(r3 + s16(i));
|
||||
if (!m_error)
|
||||
m_gpr[R2] = data;
|
||||
else
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= 4;
|
||||
}
|
||||
break;
|
||||
case 0xce: // lc: load character
|
||||
m_gpr[R2] = m_mem.read_byte(r3 + s16(i));
|
||||
m_icount -= 4;
|
||||
{
|
||||
u8 const data = m_mem.read_byte(r3 + s16(i));
|
||||
if (!m_error)
|
||||
m_gpr[R2] = data;
|
||||
else
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= 4;
|
||||
}
|
||||
break;
|
||||
case 0xcf: // tsh: test and set half
|
||||
m_gpr[R2] = m_mem.read_word(r3 + s16(i));
|
||||
m_mem.write_byte(r3 + s16(i), 0xff);
|
||||
m_icount -= 4;
|
||||
{
|
||||
u16 const data = m_mem.read_word(r3 + s16(i));
|
||||
if (!m_error)
|
||||
{
|
||||
m_gpr[R2] = data;
|
||||
m_mem.write_word(r3 + s16(i), 0xff00, 0xff00);
|
||||
if (m_error)
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
}
|
||||
else
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
|
||||
m_icount -= 4;
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xd0: // lps: load program status
|
||||
@ -340,10 +437,12 @@ void romp_device::execute_run()
|
||||
m_scr[MPCS] &= ~PCS_ALL;
|
||||
// TODO: defer interrupt enable
|
||||
|
||||
set_space(m_scr[ICS]);
|
||||
|
||||
m_icount -= 15;
|
||||
}
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
program_check(PCS_PCK | PCS_IOC, m_branch_source);
|
||||
}
|
||||
else
|
||||
program_check(PCS_PCK | PCS_PIE);
|
||||
@ -395,29 +494,43 @@ void romp_device::execute_run()
|
||||
m_mem.write_dword(offset, m_gpr[reg]);
|
||||
m_icount -= (m_scr[ICS] & ICS_TM) ? 3 : 2;
|
||||
}
|
||||
if (m_error)
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= (m_scr[ICS] & ICS_TM) ? 3 : 2;
|
||||
break;
|
||||
case 0xda: // lh: load half
|
||||
m_gpr[R2] = m_mem.read_word(r3 + s16(i));
|
||||
m_icount -= 4;
|
||||
{
|
||||
u16 const data = m_mem.read_word(r3 + s16(i));
|
||||
if (!m_error)
|
||||
m_gpr[R2] = data;
|
||||
else
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= 4;
|
||||
}
|
||||
break;
|
||||
case 0xdb: // iow: input/output write
|
||||
if (r3 + i < 0x0100'0000U)
|
||||
if (!((r3 + i) & 0xff00'0000U))
|
||||
space(AS_IO).write_dword(r3 + i, m_gpr[R2]);
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount--;
|
||||
break;
|
||||
case 0xdc: // sth: store half
|
||||
m_mem.write_word(r3 + s16(i), m_gpr[R2]);
|
||||
if (m_error)
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= 4;
|
||||
break;
|
||||
case 0xdd: // st: store
|
||||
m_mem.write_dword(r3 + s16(i), m_gpr[R2]);
|
||||
if (m_error)
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= 4;
|
||||
break;
|
||||
case 0xde: // stc: store character
|
||||
m_mem.write_byte(r3 + s16(i), m_gpr[R2]);
|
||||
if (m_error)
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= 4;
|
||||
break;
|
||||
|
||||
@ -648,24 +761,32 @@ void romp_device::execute_run()
|
||||
m_gpr[R2] &= ~(0x8000'0000U >> (m_gpr[R3] & 31));
|
||||
break;
|
||||
case 0xbd: // tgte: trap if register greater than or equal
|
||||
if (m_branch_state == BRANCH)
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
else if (m_gpr[R2] >= m_gpr[R3])
|
||||
if (m_branch_state != BRANCH)
|
||||
{
|
||||
program_check(PCS_PCK | PCS_PT);
|
||||
m_icount -= 14;
|
||||
if (m_gpr[R2] >= m_gpr[R3])
|
||||
{
|
||||
program_check(PCS_PCK | PCS_PT);
|
||||
m_icount -= 14;
|
||||
}
|
||||
|
||||
m_icount--;
|
||||
}
|
||||
m_icount--;
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC, m_branch_source);
|
||||
break;
|
||||
case 0xbe: // tlt: trap if register less than
|
||||
if (m_branch_state == BRANCH)
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
else if (m_gpr[R2] < m_gpr[R3])
|
||||
if (m_branch_state != BRANCH)
|
||||
{
|
||||
program_check(PCS_PCK | PCS_PT);
|
||||
m_icount -= 14;
|
||||
if (m_gpr[R2] < m_gpr[R3])
|
||||
{
|
||||
program_check(PCS_PCK | PCS_PT);
|
||||
m_icount -= 14;
|
||||
}
|
||||
|
||||
m_icount--;
|
||||
}
|
||||
m_icount--;
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC, m_branch_source);
|
||||
break;
|
||||
case 0xbf: // mttb: move to test bit
|
||||
if (m_gpr[R2] & (0x8000'0000U >> (m_gpr[R3] & 31)))
|
||||
@ -744,78 +865,99 @@ void romp_device::execute_run()
|
||||
flags_log(m_gpr[R2]);
|
||||
break;
|
||||
case 0xe8: // bnbr: branch on not condition bit
|
||||
if (m_branch_state == BRANCH)
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
else if (!BIT(m_scr[CS], R2 ^ 15))
|
||||
if (m_branch_state != BRANCH)
|
||||
{
|
||||
m_branch_target = m_gpr[R3] & ~1;
|
||||
m_branch_state = BRANCH;
|
||||
if (!BIT(m_scr[CS], R2 ^ 15))
|
||||
{
|
||||
m_branch_target = m_gpr[R3] & ~1;
|
||||
m_branch_state = BRANCH;
|
||||
}
|
||||
}
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC, m_branch_source);
|
||||
break;
|
||||
case 0xe9: // bnbrx: branch on not condition bit with execute
|
||||
if (m_branch_state == BRANCH)
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
else if (!BIT(m_scr[CS], R2 ^ 15))
|
||||
if (m_branch_state != BRANCH)
|
||||
{
|
||||
m_branch_target = m_gpr[R3] & ~1;
|
||||
m_branch_state = DELAY;
|
||||
if (!BIT(m_scr[CS], R2 ^ 15))
|
||||
{
|
||||
m_branch_source = m_scr[IAR];
|
||||
m_branch_target = m_gpr[R3] & ~1;
|
||||
m_branch_state = DELAY;
|
||||
}
|
||||
}
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC, m_branch_source);
|
||||
break;
|
||||
|
||||
case 0xeb: // lhs: load half short
|
||||
m_gpr[R2] = m_mem.read_word(m_gpr[R3]);
|
||||
m_icount -= 4;
|
||||
{
|
||||
u16 const data = m_mem.read_word(m_gpr[R3]);
|
||||
if (!m_error)
|
||||
m_gpr[R2] = data;
|
||||
else
|
||||
program_check(PCS_PCK | PCS_DAE);
|
||||
m_icount -= 4;
|
||||
}
|
||||
break;
|
||||
case 0xec: // balr: branch and link
|
||||
if (m_branch_state != BRANCH)
|
||||
{
|
||||
m_gpr[R2] = updated_iar;
|
||||
m_branch_target = m_gpr[R3] & ~1;
|
||||
m_branch_state = BRANCH;
|
||||
m_gpr[R2] = updated_iar;
|
||||
m_icount -= 4;
|
||||
}
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
program_check(PCS_PCK | PCS_IOC, m_branch_source);
|
||||
break;
|
||||
case 0xed: // balrx: branch and link with execute
|
||||
if (m_branch_state != BRANCH)
|
||||
{
|
||||
m_gpr[R2] = updated_iar + 4;
|
||||
m_branch_source = m_scr[IAR];
|
||||
m_branch_target = m_gpr[R3] & ~1;
|
||||
m_branch_state = DELAY;
|
||||
m_gpr[R2] = updated_iar + 4;
|
||||
m_icount -= 4;
|
||||
}
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
program_check(PCS_PCK | PCS_IOC, m_branch_source);
|
||||
break;
|
||||
case 0xee: // bbr: branch on condition bit
|
||||
if (m_branch_state == BRANCH)
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
else if (BIT(m_scr[CS], R2 ^ 15))
|
||||
if (m_branch_state != BRANCH)
|
||||
{
|
||||
m_branch_target = m_gpr[R3] & ~1;
|
||||
m_branch_state = BRANCH;
|
||||
m_icount -= 4;
|
||||
if (BIT(m_scr[CS], R2 ^ 15))
|
||||
{
|
||||
m_branch_target = m_gpr[R3] & ~1;
|
||||
m_branch_state = BRANCH;
|
||||
m_icount -= 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC, m_branch_source);
|
||||
break;
|
||||
case 0xef: // bbrx: branch on condition bit with execute
|
||||
if (m_branch_state == BRANCH)
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
else if (BIT(m_scr[CS], R2 ^ 15))
|
||||
if (m_branch_state != BRANCH)
|
||||
{
|
||||
m_branch_target = m_gpr[R3] & ~1;
|
||||
m_branch_state = DELAY;
|
||||
m_icount -= 4;
|
||||
if (BIT(m_scr[CS], R2 ^ 15))
|
||||
{
|
||||
m_branch_source = m_scr[IAR];
|
||||
m_branch_target = m_gpr[R3] & ~1;
|
||||
m_branch_state = DELAY;
|
||||
m_icount -= 4;
|
||||
}
|
||||
}
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC, m_branch_source);
|
||||
break;
|
||||
|
||||
case 0xf0: // wait: wait
|
||||
if (!(m_scr[ICS] & ICS_US))
|
||||
{
|
||||
if (m_branch_state != BRANCH)
|
||||
fatalerror("wait (%s)\n", machine().describe_context());
|
||||
m_branch_state = WAIT;
|
||||
else
|
||||
program_check(PCS_PCK | PCS_IOC);
|
||||
program_check(PCS_PCK | PCS_IOC, m_branch_source);
|
||||
}
|
||||
else
|
||||
program_check(PCS_PCK | PCS_PIE);
|
||||
@ -888,6 +1030,12 @@ void romp_device::execute_run()
|
||||
case EXCEPTION:
|
||||
m_branch_state = DEFAULT;
|
||||
break;
|
||||
|
||||
case WAIT:
|
||||
// TODO: assume iar is updated
|
||||
m_scr[IAR] = updated_iar;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -907,10 +1055,7 @@ void romp_device::set_scr(unsigned scr, u32 data)
|
||||
switch (scr)
|
||||
{
|
||||
case ICS:
|
||||
space(bool(data & ICS_TM)).cache(m_mem);
|
||||
break;
|
||||
|
||||
default:
|
||||
set_space(data);
|
||||
break;
|
||||
}
|
||||
|
||||
@ -930,25 +1075,28 @@ void romp_device::execute_set_input(int irqline, int state)
|
||||
break;
|
||||
|
||||
default:
|
||||
// interrupt lines are active low
|
||||
if (!state)
|
||||
{
|
||||
m_scr[IRB] |= (IRB_L0 >> irqline);
|
||||
// interrupt lines are active low
|
||||
if (!state)
|
||||
{
|
||||
m_reqi |= 1U << irqline;
|
||||
|
||||
// enable debugger interrupt breakpoints
|
||||
standard_irq_callback(irqline);
|
||||
}
|
||||
else
|
||||
m_scr[IRB] &= ~(IRB_L0 >> irqline);
|
||||
// enable debugger interrupt breakpoints
|
||||
standard_irq_callback(irqline);
|
||||
}
|
||||
else
|
||||
m_reqi &= ~(1U << irqline);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
device_memory_interface::space_config_vector romp_device::memory_space_config() const
|
||||
{
|
||||
return space_config_vector {
|
||||
std::make_pair(0, &m_mem_config), // untranslated
|
||||
std::make_pair(1, &m_mem_config), // translated
|
||||
std::make_pair(AS_IO, &m_io_config)
|
||||
std::make_pair(0, &m_mem_config), // privileged, untranslated
|
||||
std::make_pair(1, &m_mem_config), // privileged, translated
|
||||
std::make_pair(2, &m_io_config),
|
||||
std::make_pair(4, &m_mem_config), // unprivileged, untranslated
|
||||
std::make_pair(5, &m_mem_config), // unprivileged, translated
|
||||
};
|
||||
}
|
||||
|
||||
@ -1028,22 +1176,19 @@ void romp_device::interrupt_check()
|
||||
if (m_trap)
|
||||
{
|
||||
// TODO: traps with check-stop mask 0
|
||||
program_check(PCS_PCK);
|
||||
machine_check(MCS_IOT);
|
||||
m_trap = false;
|
||||
|
||||
m_branch_state = DEFAULT;
|
||||
return;
|
||||
}
|
||||
|
||||
// interrupts masked or no interrupts
|
||||
if ((m_scr[ICS] & ICS_IM) || !(m_scr[IRB] & IRB_ALL))
|
||||
if ((m_scr[ICS] & ICS_IM) || !(m_reqi || (m_scr[IRB] & IRB_ALL)))
|
||||
return;
|
||||
|
||||
unsigned const priority = m_scr[ICS] & ICS_PP;
|
||||
for (unsigned irl = 0; irl < priority; irl++)
|
||||
{
|
||||
if (BIT(m_scr[IRB], 15 - irl))
|
||||
if (BIT(m_reqi, irl) || BIT(m_scr[IRB], 15 - irl))
|
||||
{
|
||||
LOGMASKED(LOG_INTERRUPT, "interrupt_check taking interrupt request level %d\n", irl);
|
||||
interrupt_enter(irl, m_scr[IAR]);
|
||||
@ -1063,11 +1208,9 @@ void romp_device::machine_check(u32 mcs)
|
||||
m_scr[MPCS] |= (mcs & MCS_ALL);
|
||||
|
||||
interrupt_enter(7, m_scr[IAR]);
|
||||
|
||||
m_branch_state = EXCEPTION;
|
||||
}
|
||||
|
||||
void romp_device::program_check(u32 pcs)
|
||||
void romp_device::program_check(u32 pcs, u32 iar)
|
||||
{
|
||||
debugger_exception_hook(8);
|
||||
|
||||
@ -1076,7 +1219,7 @@ void romp_device::program_check(u32 pcs)
|
||||
m_scr[MPCS] &= ~PCS_ALL;
|
||||
m_scr[MPCS] |= (pcs & PCS_ALL);
|
||||
|
||||
interrupt_enter(8, m_scr[IAR]);
|
||||
interrupt_enter(8, iar);
|
||||
|
||||
m_branch_state = EXCEPTION;
|
||||
}
|
||||
@ -1099,7 +1242,9 @@ void romp_device::interrupt_enter(unsigned vector, u32 iar, u16 svc)
|
||||
if (vector < 7)
|
||||
m_scr[CS] = space(0).read_word(address + 14);
|
||||
|
||||
space(bool(m_scr[ICS] & ICS_TM)).cache(m_mem);
|
||||
set_space(m_scr[ICS]);
|
||||
|
||||
m_branch_state = DEFAULT;
|
||||
}
|
||||
|
||||
void romp_device::clk_w(int state)
|
||||
@ -1125,7 +1270,7 @@ void romp_device::clk_w(int state)
|
||||
|
||||
// raise interrupt
|
||||
if ((m_scr[TS] & TS_P) < 7)
|
||||
m_scr[IRB] |= 0x8000U >> (m_scr[TS] & TS_P);
|
||||
m_scr[IRB] |= IRB_L0 >> (m_scr[TS] & TS_P);
|
||||
}
|
||||
|
||||
// reload counter
|
||||
|
@ -11,6 +11,7 @@ class romp_device : public cpu_device
|
||||
public:
|
||||
romp_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock);
|
||||
|
||||
void err_w(int state) { m_error = state; }
|
||||
void clk_w(int state);
|
||||
|
||||
protected:
|
||||
@ -23,14 +24,14 @@ protected:
|
||||
enum scr : unsigned
|
||||
{
|
||||
COUS = 6, // counter source
|
||||
COU = 7, // counter
|
||||
TS = 8, // timer status
|
||||
MQ = 10, // multiplier quotient
|
||||
COU = 7, // counter
|
||||
TS = 8, // timer status
|
||||
MQ = 10, // multiplier quotient
|
||||
MPCS = 11, // machine/program check status
|
||||
IRB = 12, // interrupt request buffer
|
||||
IAR = 13, // instruction address register
|
||||
ICS = 14, // interrupt control status
|
||||
CS = 15, // condition status
|
||||
IRB = 12, // interrupt request buffer
|
||||
IAR = 13, // instruction address register
|
||||
ICS = 14, // interrupt control status
|
||||
CS = 15, // condition status
|
||||
};
|
||||
|
||||
enum ts_mask : u32
|
||||
@ -131,11 +132,13 @@ private:
|
||||
void flags_add(u32 const op1, u32 const op2);
|
||||
void flags_sub(u32 const op1, u32 const op2);
|
||||
|
||||
void set_space(u32 const ics) { space(((ics & ICS_US) ? 4 : 0) + ((ics & ICS_TM) ? 1 : 0)).cache(m_mem); }
|
||||
void set_scr(unsigned scr, u32 data);
|
||||
|
||||
void interrupt_check();
|
||||
void machine_check(u32 mcs);
|
||||
void program_check(u32 pcs);
|
||||
void program_check(u32 pcs, u32 iar);
|
||||
void program_check(u32 pcs) { program_check(pcs, m_scr[IAR]); }
|
||||
void interrupt_enter(unsigned vector, u32 iar, u16 svc = 0);
|
||||
|
||||
// address spaces
|
||||
@ -151,6 +154,11 @@ private:
|
||||
u32 m_scr[16];
|
||||
u32 m_gpr[16];
|
||||
|
||||
// input line state
|
||||
u8 m_reqi;
|
||||
bool m_trap;
|
||||
bool m_error;
|
||||
|
||||
// internal state
|
||||
enum branch_state : unsigned
|
||||
{
|
||||
@ -158,10 +166,11 @@ private:
|
||||
BRANCH = 1, // branch subject instruction active
|
||||
DELAY = 2, // delayed branch instruction active
|
||||
EXCEPTION = 3,
|
||||
WAIT = 4,
|
||||
}
|
||||
m_branch_state;
|
||||
u32 m_branch_source;
|
||||
u32 m_branch_target;
|
||||
bool m_trap;
|
||||
};
|
||||
|
||||
DECLARE_DEVICE_TYPE(ROMP, romp_device)
|
||||
|
Loading…
Reference in New Issue
Block a user