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:
Patrick Mackinlay 2020-12-09 14:03:06 +07:00
parent 09d755e44e
commit 9ee3522842
2 changed files with 278 additions and 124 deletions

View File

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

View File

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