mirror of
https://github.com/holub/mame
synced 2025-04-25 09:50:04 +03:00
Logging changed; fixed HOLD handling; added synchronous RESET
This commit is contained in:
parent
2a71be55e9
commit
a444e30e28
@ -85,7 +85,6 @@
|
||||
|
||||
TODO:
|
||||
- State save
|
||||
- Test HOLD
|
||||
|
||||
Michael Zapf, June 2012
|
||||
*/
|
||||
@ -275,7 +274,7 @@ void tms9995_device::device_start()
|
||||
void tms9995_device::device_stop()
|
||||
{
|
||||
int k = 0;
|
||||
if (TRACE_CONFIG) logerror("%s: Deleting lookup tables\n", tag());
|
||||
if (TRACE_EMU) logerror("%s: Deleting lookup tables\n", tag());
|
||||
while (m_lotables[k]!=nullptr) delete[] m_lotables[k++];
|
||||
}
|
||||
|
||||
@ -292,6 +291,7 @@ void tms9995_device::device_reset()
|
||||
m_reset = true; // for the main loop
|
||||
m_servicing_interrupt = false; // only for debugging
|
||||
m_request_auto_wait_state = false;
|
||||
m_hold_requested = false;
|
||||
memset(m_flag, 0, sizeof(m_flag));
|
||||
}
|
||||
|
||||
@ -1150,7 +1150,7 @@ void tms9995_device::build_command_lookup_table()
|
||||
{
|
||||
inst = &s_command[i];
|
||||
table = m_command_lookup_table;
|
||||
if (TRACE_EMU) logerror("tms9995: === opcode=%04x, len=%d\n", inst->opcode, format_mask_len[inst->format]);
|
||||
if (TRACE_EMU) logerror("=== opcode=%04x, len=%d\n", inst->opcode, format_mask_len[inst->format]);
|
||||
bitcount = 4;
|
||||
opcode = inst->opcode;
|
||||
cmdindex = (opcode>>12) & 0x000f;
|
||||
@ -1160,7 +1160,7 @@ void tms9995_device::build_command_lookup_table()
|
||||
// Descend
|
||||
if (table[cmdindex].next_digit == nullptr)
|
||||
{
|
||||
if (TRACE_EMU) logerror("tms9995: create new table at bitcount=%d for index=%d\n", bitcount, cmdindex);
|
||||
if (TRACE_EMU) logerror("create new table at bitcount=%d for index=%d\n", bitcount, cmdindex);
|
||||
table[cmdindex].next_digit = new lookup_entry[16];
|
||||
m_lotables[k++] = table[cmdindex].next_digit;
|
||||
for (int j=0; j < 16; j++)
|
||||
@ -1171,7 +1171,7 @@ void tms9995_device::build_command_lookup_table()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TRACE_EMU) logerror("tms9995: found a table at bitcount=%d\n", bitcount);
|
||||
if (TRACE_EMU) logerror("found a table at bitcount=%d\n", bitcount);
|
||||
}
|
||||
|
||||
table = table[cmdindex].next_digit;
|
||||
@ -1179,17 +1179,17 @@ void tms9995_device::build_command_lookup_table()
|
||||
bitcount = bitcount+4;
|
||||
opcode <<= 4;
|
||||
cmdindex = (opcode>>12) & 0x000f;
|
||||
if (TRACE_EMU) logerror("tms9995: next index=%x\n", cmdindex);
|
||||
if (TRACE_EMU) logerror("next index=%x\n", cmdindex);
|
||||
}
|
||||
|
||||
if (TRACE_EMU) logerror("tms9995: bitcount=%d\n", bitcount);
|
||||
if (TRACE_EMU) logerror("bitcount=%d\n", bitcount);
|
||||
// We are at the target level
|
||||
// Need to fill in the same entry for all values in the bitcount
|
||||
// (if a command needs 10 bits we have to copy it four
|
||||
// times for all combinations with 12 bits)
|
||||
for (int j=0; j < (1<<(bitcount-format_mask_len[inst->format])); j++)
|
||||
{
|
||||
if (TRACE_EMU) logerror("tms9995: opcode=%04x at position %d\n", inst->opcode, cmdindex+j);
|
||||
if (TRACE_EMU) logerror("opcode=%04x at position %d\n", inst->opcode, cmdindex+j);
|
||||
table[cmdindex+j].entry = inst;
|
||||
}
|
||||
|
||||
@ -1197,7 +1197,7 @@ void tms9995_device::build_command_lookup_table()
|
||||
} while (inst->opcode != 0xf000);
|
||||
|
||||
m_lotables[k++] = nullptr;
|
||||
if (TRACE_EMU) logerror("tms9995: Allocated %d tables\n", k);
|
||||
if (TRACE_EMU) logerror("Allocated %d tables\n", k);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1212,24 +1212,24 @@ void tms9995_device::execute_run()
|
||||
{
|
||||
if (m_reset) service_interrupt();
|
||||
|
||||
if (TRACE_EMU) logerror("tms9995: calling execute_run for %d cycles\n", m_icount);
|
||||
if (TRACE_EMU) logerror("calling execute_run for %d cycles\n", m_icount);
|
||||
do
|
||||
{
|
||||
// Normal operation
|
||||
if (m_check_ready && m_ready == false)
|
||||
{
|
||||
// We are in a wait state
|
||||
if (TRACE_WAITHOLD) logerror("tms9995: wait state\n");
|
||||
if (TRACE_WAITHOLD) logerror("wait state\n");
|
||||
// The clock output should be used to change the state of an outer
|
||||
// device which operates the READY line
|
||||
pulse_clock(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (m_check_hold && m_hold_state)
|
||||
if (m_check_hold && m_hold_requested)
|
||||
{
|
||||
set_hold_state(true);
|
||||
if (TRACE_WAITHOLD) logerror("tms9995: hold state\n");
|
||||
if (TRACE_WAITHOLD) logerror("HOLD state\n");
|
||||
pulse_clock(1);
|
||||
}
|
||||
else
|
||||
@ -1238,7 +1238,7 @@ void tms9995_device::execute_run()
|
||||
|
||||
m_check_ready = false;
|
||||
|
||||
if (TRACE_MICRO) logerror("tms9995: main loop, operation %s, MPC = %d\n", opname[m_instruction->command], MPC);
|
||||
if (TRACE_MICRO) logerror("main loop, operation %s, MPC = %d\n", opname[m_instruction->command], MPC);
|
||||
(this->*s_microoperation[m_instruction->program[MPC]])();
|
||||
|
||||
// For multi-pass operations where the MPC should not advance
|
||||
@ -1252,7 +1252,8 @@ void tms9995_device::execute_run()
|
||||
}
|
||||
}
|
||||
} while (m_icount>0 && !m_reset);
|
||||
if (TRACE_EMU) logerror("tms9995: cycles expired; will return soon.\n");
|
||||
|
||||
if (TRACE_EMU) logerror("cycles expired; will return soon.\n");
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
@ -1266,49 +1267,61 @@ void tms9995_device::execute_run()
|
||||
*/
|
||||
void tms9995_device::execute_set_input(int irqline, int state)
|
||||
{
|
||||
if (irqline==INT_9995_RESET && state==ASSERT_LINE)
|
||||
if (irqline == INT_9995_RESET)
|
||||
{
|
||||
m_reset = true;
|
||||
if (state == ASSERT_LINE)
|
||||
{
|
||||
logerror("RESET interrupt line; READY=%d\n", m_ready_bufd);
|
||||
m_reset = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (irqline == INPUT_LINE_NMI)
|
||||
{
|
||||
m_nmi_active = (state==ASSERT_LINE);
|
||||
if (TRACE_INT) logerror("tms9995: NMI interrupt line state=%d\n", state);
|
||||
if (TRACE_INT) logerror("NMI interrupt line state=%d\n", state);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (irqline == INT_9995_INT1)
|
||||
{
|
||||
m_int1_active = m_flag[2] = (state==ASSERT_LINE);
|
||||
if (TRACE_INT) logerror("tms9995: Line INT1 state=%d\n", state);
|
||||
if (TRACE_INT) logerror("Line INT1 state=%d\n", state);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (irqline == INT_9995_INT4)
|
||||
{
|
||||
if (TRACE_INT) logerror("tms9995: Line INT4/EC state=%d\n", state);
|
||||
if (TRACE_INT) logerror("Line INT4/EC state=%d\n", state);
|
||||
if (m_flag[0]==false)
|
||||
{
|
||||
if (TRACE_INT) logerror("tms9995: set as interrupt\n");
|
||||
if (TRACE_INT) logerror("set as interrupt\n");
|
||||
m_int4_active = m_flag[4] = (state==ASSERT_LINE);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TRACE_INT) logerror("tms9995: set as event count\n");
|
||||
if (TRACE_INT) logerror("set as event count\n");
|
||||
trigger_decrementer();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
logerror("tms9995: Accessed invalid interrupt line %d\n", irqline);
|
||||
logerror("Accessed invalid interrupt line %d\n", irqline);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
Triggers a RESET.
|
||||
*/
|
||||
WRITE_LINE_MEMBER( tms9995_device::reset_line )
|
||||
{
|
||||
if (state==ASSERT_LINE) m_reset = true;
|
||||
}
|
||||
|
||||
/*
|
||||
Issue a pulse on the clock line.
|
||||
*/
|
||||
@ -1322,8 +1335,8 @@ void tms9995_device::pulse_clock(int count)
|
||||
m_icount--; // This is the only location where we count down the cycles.
|
||||
if (TRACE_CLOCK)
|
||||
{
|
||||
if (m_check_ready) logerror("tms9995: pulse_clock, READY=%d, auto_wait=%d\n", m_ready_bufd? 1:0, m_auto_wait? 1:0);
|
||||
else logerror("tms9995: pulse_clock\n");
|
||||
if (m_check_ready) logerror("pulse_clock, READY=%d, auto_wait=%d\n", m_ready_bufd? 1:0, m_auto_wait? 1:0);
|
||||
else logerror("pulse_clock\n");
|
||||
}
|
||||
m_request_auto_wait_state = false;
|
||||
if (m_flag[0] == false && m_flag[1] == true)
|
||||
@ -1339,11 +1352,11 @@ void tms9995_device::pulse_clock(int count)
|
||||
/*
|
||||
Enter the hold state.
|
||||
*/
|
||||
void tms9995_device::set_hold(int state)
|
||||
WRITE_LINE_MEMBER( tms9995_device::set_hold )
|
||||
{
|
||||
m_hold_state = (state==ASSERT_LINE);
|
||||
if (TRACE_WAITHOLD) logerror("tms9995: set HOLD = %d\n", state);
|
||||
if (!m_hold_state)
|
||||
m_hold_requested = (state==ASSERT_LINE);
|
||||
if (TRACE_WAITHOLD) logerror("set HOLD = %d\n", state);
|
||||
if (!m_hold_requested)
|
||||
{
|
||||
if (!m_holda_line.isnull()) m_holda_line(CLEAR_LINE);
|
||||
}
|
||||
@ -1353,10 +1366,14 @@ void tms9995_device::set_hold(int state)
|
||||
Signal READY to the CPU. When cleared, the CPU enters wait states. This
|
||||
becomes effective on a clock pulse.
|
||||
*/
|
||||
void tms9995_device::set_ready(int state)
|
||||
WRITE_LINE_MEMBER( tms9995_device::set_ready )
|
||||
{
|
||||
m_ready_bufd = (state==ASSERT_LINE);
|
||||
if (TRACE_READY) logerror("tms9995: set READY = %d\n", m_ready_bufd? 1 : 0);
|
||||
if (m_reset && (m_ready_bufd != state)) logerror("Ignoring READY=%d change due to pending RESET\n", state);
|
||||
else
|
||||
{
|
||||
m_ready_bufd = (state==ASSERT_LINE);
|
||||
if (TRACE_READY) logerror("set READY = %d\n", m_ready_bufd? 1 : 0);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -1374,7 +1391,7 @@ void tms9995_device::abort_operation()
|
||||
/*
|
||||
Enter or leave the hold state. We only operate the HOLDA line when there is a change.
|
||||
*/
|
||||
inline void tms9995_device::set_hold_state(bool state)
|
||||
void tms9995_device::set_hold_state(bool state)
|
||||
{
|
||||
if (m_hold_state != state)
|
||||
if (!m_holda_line.isnull()) m_holda_line(state? ASSERT_LINE : CLEAR_LINE);
|
||||
@ -1400,7 +1417,7 @@ void tms9995_device::decode(UINT16 inst)
|
||||
while (!complete)
|
||||
{
|
||||
index = (opcode >> 12) & 0x000f;
|
||||
if (TRACE_EMU) logerror("tms9995: Check next hex digit of instruction %x\n", index);
|
||||
if (TRACE_EMU) logerror("Check next hex digit of instruction %x\n", index);
|
||||
if (table[index].next_digit != nullptr)
|
||||
{
|
||||
table = table[index].next_digit;
|
||||
@ -1412,7 +1429,7 @@ void tms9995_device::decode(UINT16 inst)
|
||||
if (decoded == nullptr)
|
||||
{
|
||||
// not found
|
||||
logerror("tms9995: Undefined opcode %04x at logical address %04x, will trigger MID\n", inst, PC);
|
||||
logerror("Undefined opcode %04x at logical address %04x, will trigger MID\n", inst, PC);
|
||||
m_decoded[dindex].IR = 0;
|
||||
m_decoded[dindex].command = MID;
|
||||
}
|
||||
@ -1423,7 +1440,7 @@ void tms9995_device::decode(UINT16 inst)
|
||||
m_decoded[dindex].program = decoded->prog;
|
||||
m_decoded[dindex].byteop = ((decoded->format == 1) && ((inst & 0x1000)!=0));
|
||||
m_decoded[dindex].state = 0;
|
||||
if (TRACE_EMU) logerror("tms9995: Command decoded as id %d, %s, base opcode %04x\n", decoded->id, opname[decoded->id], decoded->opcode);
|
||||
if (TRACE_EMU) logerror("Command decoded as id %d, %s, base opcode %04x\n", decoded->id, opname[decoded->id], decoded->opcode);
|
||||
m_pass = 1;
|
||||
}
|
||||
}
|
||||
@ -1444,7 +1461,7 @@ void tms9995_device::int_prefetch_and_decode()
|
||||
// Check interrupt lines
|
||||
if (m_nmi_active)
|
||||
{
|
||||
if (TRACE_INT) logerror("tms9995: Checking interrupts ... NMI active\n");
|
||||
if (TRACE_INT) logerror("Checking interrupts ... NMI active\n");
|
||||
m_int_pending |= PENDING_NMI;
|
||||
m_idle_state = false;
|
||||
PC = (PC + 2) & 0xfffe; // we have not prefetched the next instruction
|
||||
@ -1467,19 +1484,19 @@ void tms9995_device::int_prefetch_and_decode()
|
||||
if (m_idle_state)
|
||||
{
|
||||
m_idle_state = false;
|
||||
if (TRACE_INT) logerror("tms9995: Interrupt occurred, terminate IDLE state\n");
|
||||
if (TRACE_INT) logerror("Interrupt occurred, terminate IDLE state\n");
|
||||
}
|
||||
PC = PC + 2; // PC must be advanced (see flow chart), but no prefetch
|
||||
if (TRACE_INT) logerror("tms9995: Interrupts pending; no prefetch; advance PC to %04x\n", PC);
|
||||
if (TRACE_INT) logerror("Interrupts pending; no prefetch; advance PC to %04x\n", PC);
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TRACE_INT) logerror("tms9995: Checking interrupts ... none pending\n");
|
||||
if (TRACE_INT) logerror("Checking interrupts ... none pending\n");
|
||||
// No pending interrupts
|
||||
if (m_idle_state)
|
||||
{
|
||||
if (TRACE_WAITHOLD) logerror("tms9995: IDLE state\n");
|
||||
if (TRACE_WAITHOLD) logerror("IDLE state\n");
|
||||
// We are IDLE, stay in the loop and do not advance the PC
|
||||
m_pass = 2;
|
||||
pulse_clock(1);
|
||||
@ -1509,7 +1526,7 @@ void tms9995_device::prefetch_and_decode()
|
||||
m_value_copy = m_current_value;
|
||||
if (!m_iaq_line.isnull()) m_iaq_line(ASSERT_LINE);
|
||||
m_address = PC;
|
||||
if (TRACE_OP) logerror("tms9995: **** Prefetching new instruction at %04x ****\n", PC);
|
||||
if (TRACE_OP) logerror("**** Prefetching new instruction at %04x ****\n", PC);
|
||||
}
|
||||
|
||||
word_read(); // changes m_mem_phase
|
||||
@ -1522,7 +1539,7 @@ void tms9995_device::prefetch_and_decode()
|
||||
m_current_value = m_value_copy; // restore m_current_value
|
||||
PC = (PC + 2) & 0xfffe; // advance PC
|
||||
if (!m_iaq_line.isnull()) m_iaq_line(CLEAR_LINE);
|
||||
if (TRACE_OP) logerror("tms9995: ++++ Prefetch done ++++\n");
|
||||
if (TRACE_OP) logerror("++++ Prefetch done ++++\n");
|
||||
}
|
||||
}
|
||||
|
||||
@ -1549,7 +1566,7 @@ void tms9995_device::next_command()
|
||||
// This is a preset for opcodes which do not need an opcode address derivation
|
||||
m_address = WP + ((m_instruction->IR & 0x000f)<<1);
|
||||
MPC = -1;
|
||||
if (TRACE_OP) logerror("tms9995: ===== Next operation %04x (%s) at %04x =====\n", m_instruction->IR, opname[m_instruction->command], PC-2);
|
||||
if (TRACE_OP) logerror("===== Next operation %04x (%s) at %04x =====\n", m_instruction->IR, opname[m_instruction->command], PC-2);
|
||||
|
||||
if (TRACE_EXEC)
|
||||
{
|
||||
@ -1570,7 +1587,7 @@ void tms9995_device::command_completed()
|
||||
// Pseudo state at the end of the current instruction cycle sequence
|
||||
if (TRACE_CYCLES)
|
||||
{
|
||||
logerror("tms9995: +++++ Instruction %04x (%s) completed", m_instruction->IR, opname[m_instruction->command]);
|
||||
logerror("+++++ Instruction %04x (%s) completed", m_instruction->IR, opname[m_instruction->command]);
|
||||
int cycles = m_first_cycle - m_icount;
|
||||
// Avoid nonsense values due to expired and resumed main loop
|
||||
if (cycles > 0 && cycles < 10000) logerror(", consumed %d cycles", cycles);
|
||||
@ -1607,9 +1624,10 @@ void tms9995_device::service_interrupt()
|
||||
m_intmask = 0; // clear interrupt mask
|
||||
|
||||
m_nmi_state = false;
|
||||
m_hold_requested = false;
|
||||
m_hold_state = false;
|
||||
m_mem_phase = 1;
|
||||
m_check_hold = false;
|
||||
m_check_hold = true;
|
||||
m_word_access = false;
|
||||
m_int1_active = false;
|
||||
m_int4_active = false;
|
||||
@ -1626,7 +1644,7 @@ void tms9995_device::service_interrupt()
|
||||
// The auto-wait state generation is turned on when the READY line is cleared
|
||||
// on RESET.
|
||||
m_auto_wait = !m_ready_bufd;
|
||||
if (TRACE_CONFIG) logerror("tms9995: RESET; automatic wait state creation is %s\n", m_auto_wait? "enabled":"disabled");
|
||||
logerror("RESET; automatic wait state creation is %s\n", m_auto_wait? "enabled":"disabled");
|
||||
// We reset the READY flag, or the CPU will not start
|
||||
m_ready_bufd = true;
|
||||
}
|
||||
@ -1637,7 +1655,7 @@ void tms9995_device::service_interrupt()
|
||||
vectorpos = 0x0008;
|
||||
m_intmask = 0x0001;
|
||||
PC = (PC + 2) & 0xfffe;
|
||||
if (TRACE_INT) logerror("tms9995: ***** MID pending\n");
|
||||
if (TRACE_INT) logerror("***** MID pending\n");
|
||||
m_mid_active = false;
|
||||
}
|
||||
else
|
||||
@ -1647,7 +1665,7 @@ void tms9995_device::service_interrupt()
|
||||
vectorpos = 0xfffc;
|
||||
m_int_pending &= ~PENDING_NMI;
|
||||
m_intmask = 0;
|
||||
if (TRACE_INT) logerror("tms9995: ***** NMI pending\n");
|
||||
if (TRACE_INT) logerror("***** NMI pending\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1657,7 +1675,7 @@ void tms9995_device::service_interrupt()
|
||||
m_int_pending &= ~PENDING_LEVEL1;
|
||||
m_flag[2] = false;
|
||||
m_intmask = 0;
|
||||
if (TRACE_INT) logerror("tms9995: ***** INT1 pending\n");
|
||||
if (TRACE_INT) logerror("***** INT1 pending\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1666,7 +1684,7 @@ void tms9995_device::service_interrupt()
|
||||
vectorpos = 0x0008;
|
||||
m_int_pending &= ~PENDING_OVERFLOW;
|
||||
m_intmask = 0x0001;
|
||||
if (TRACE_INT) logerror("tms9995: ***** OVERFL pending\n");
|
||||
if (TRACE_INT) logerror("***** OVERFL pending\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1677,7 +1695,7 @@ void tms9995_device::service_interrupt()
|
||||
m_int_pending &= ~PENDING_DECR;
|
||||
m_flag[3] = false;
|
||||
m_int_decrementer = false;
|
||||
if (TRACE_DEC) logerror("tms9995: ***** DECR pending\n");
|
||||
if (TRACE_DEC) logerror("***** DECR pending\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1685,7 +1703,7 @@ void tms9995_device::service_interrupt()
|
||||
m_intmask = 0x0003;
|
||||
m_int_pending &= ~PENDING_LEVEL4;
|
||||
m_flag[4] = false;
|
||||
if (TRACE_INT) logerror("tms9995: ***** INT4 pending\n");
|
||||
if (TRACE_INT) logerror("***** INT4 pending\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -1693,10 +1711,10 @@ void tms9995_device::service_interrupt()
|
||||
}
|
||||
}
|
||||
|
||||
if (TRACE_INT) logerror("tms9995: ********* triggered an interrupt with vector %04x/%04x\n", vectorpos, vectorpos+2);
|
||||
if (TRACE_INT) logerror("********* triggered an interrupt with vector %04x/%04x\n", vectorpos, vectorpos+2);
|
||||
|
||||
// just for debugging purposes
|
||||
m_servicing_interrupt = true;
|
||||
if (!m_reset) m_servicing_interrupt = true;
|
||||
|
||||
// The microinstructions will do the context switch
|
||||
m_address = vectorpos;
|
||||
@ -1743,7 +1761,7 @@ void tms9995_device::mem_read()
|
||||
|
||||
if ((m_address & 0xfffe)==0xfffa && !m_mp9537)
|
||||
{
|
||||
if (TRACE_DEC) logerror("tms9995: read decrementer\n");
|
||||
if (TRACE_DEC) logerror("read decrementer\n");
|
||||
// Decrementer mapped into the address space
|
||||
m_current_value = m_decrementer_value;
|
||||
if (m_instruction->byteop)
|
||||
@ -1762,7 +1780,7 @@ void tms9995_device::mem_read()
|
||||
// byte operations (e.g. when retrieving the index register)
|
||||
if (m_word_access || !m_instruction->byteop) m_address &= 0xfffe;
|
||||
|
||||
if (TRACE_MEM) logerror("tms9995: read onchip memory (single pass, address %04x)\n", m_address);
|
||||
if (TRACE_MEM) logerror("read onchip memory (single pass, address %04x)\n", m_address);
|
||||
|
||||
// Ignore the READY state
|
||||
m_check_ready = false;
|
||||
@ -1797,7 +1815,7 @@ void tms9995_device::mem_read()
|
||||
else m_pass = 2;
|
||||
|
||||
m_check_hold = false;
|
||||
if (TRACE_ADDRESSBUS) logerror("tms9995: set address bus %04x\n", m_address & ~1);
|
||||
if (TRACE_ADDRESSBUS) logerror("set address bus %04x\n", m_address & ~1);
|
||||
m_prgspace->set_address(address);
|
||||
m_request_auto_wait_state = m_auto_wait;
|
||||
pulse_clock(1);
|
||||
@ -1806,20 +1824,21 @@ void tms9995_device::mem_read()
|
||||
// Sample the value on the data bus (high byte)
|
||||
if (m_word_access || !m_instruction->byteop) address &= 0xfffe;
|
||||
value = m_prgspace->read_byte(address);
|
||||
if (TRACE_MEM) logerror("tms9995: memory read byte %04x -> %02x\n", m_address & ~1, value);
|
||||
if (TRACE_MEM) logerror("memory read byte %04x -> %02x\n", m_address & ~1, value);
|
||||
m_current_value = (value << 8) & 0xff00;
|
||||
break;
|
||||
case 3:
|
||||
// Set address + 1 (unless byte command)
|
||||
if (TRACE_ADDRESSBUS) logerror("tms9995: set address bus %04x\n", m_address | 1);
|
||||
if (TRACE_ADDRESSBUS) logerror("set address bus %04x\n", m_address | 1);
|
||||
m_prgspace->set_address(m_address | 1);
|
||||
m_request_auto_wait_state = m_auto_wait;
|
||||
pulse_clock(1);
|
||||
break;
|
||||
case 4:
|
||||
// Read low byte
|
||||
value = m_prgspace->read_byte(m_address | 1);
|
||||
m_current_value |= value;
|
||||
if (TRACE_MEM) logerror("tms9995: memory read byte %04x -> %02x, complete word = %04x\n", m_address | 1, value, m_current_value);
|
||||
if (TRACE_MEM) logerror("memory read byte %04x -> %02x, complete word = %04x\n", m_address | 1, value, m_current_value);
|
||||
m_check_hold = true;
|
||||
break;
|
||||
}
|
||||
@ -1827,7 +1846,11 @@ void tms9995_device::mem_read()
|
||||
m_mem_phase = (m_mem_phase % 4) +1;
|
||||
|
||||
// Reset to 1 when we are done
|
||||
if (m_pass==1) m_mem_phase = 1;
|
||||
if (m_pass==1)
|
||||
{
|
||||
m_mem_phase = 1;
|
||||
m_check_hold = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1883,7 +1906,7 @@ void tms9995_device::mem_write()
|
||||
{
|
||||
m_starting_count_storage_register = m_decrementer_value = m_current_value;
|
||||
}
|
||||
if (TRACE_DEC) logerror("tms9995: Setting decrementer to %04x, PC=%04x\n", m_current_value, PC);
|
||||
if (TRACE_DEC) logerror("Setting decrementer to %04x, PC=%04x\n", m_current_value, PC);
|
||||
pulse_clock(1);
|
||||
return;
|
||||
}
|
||||
@ -1895,7 +1918,7 @@ void tms9995_device::mem_write()
|
||||
// byte operations (e.g. when retrieving the index register)
|
||||
if (m_word_access || !m_instruction->byteop) m_address &= 0xfffe;
|
||||
|
||||
if (TRACE_MEM) logerror("tms9995: write to onchip memory (single pass, address %04x, value=%04x)\n", m_address, m_current_value);
|
||||
if (TRACE_MEM) logerror("write to onchip memory (single pass, address %04x, value=%04x)\n", m_address, m_current_value);
|
||||
m_check_ready = false;
|
||||
m_onchip_memory[m_address & 0x00ff] = (m_current_value >> 8) & 0xff;
|
||||
if (m_word_access || !m_instruction->byteop)
|
||||
@ -1924,10 +1947,11 @@ void tms9995_device::mem_write()
|
||||
else m_pass = 2;
|
||||
|
||||
m_check_hold = false;
|
||||
if (TRACE_ADDRESSBUS) logerror("tms9995: set address bus %04x\n", address);
|
||||
if (TRACE_ADDRESSBUS) logerror("set address bus %04x\n", address);
|
||||
m_prgspace->set_address(address);
|
||||
if (TRACE_MEM) logerror("tms9995: memory write byte %04x <- %02x\n", address, (m_current_value >> 8)&0xff);
|
||||
if (TRACE_MEM) logerror("memory write byte %04x <- %02x\n", address, (m_current_value >> 8)&0xff);
|
||||
m_prgspace->write_byte(address, (m_current_value >> 8)&0xff);
|
||||
m_request_auto_wait_state = m_auto_wait;
|
||||
pulse_clock(1);
|
||||
break;
|
||||
|
||||
@ -1936,22 +1960,26 @@ void tms9995_device::mem_write()
|
||||
break;
|
||||
case 3:
|
||||
// Set address + 1 (unless byte command)
|
||||
if (TRACE_ADDRESSBUS) logerror("tms9995: set address bus %04x\n", m_address | 1);
|
||||
if (TRACE_ADDRESSBUS) logerror("set address bus %04x\n", m_address | 1);
|
||||
m_prgspace->set_address(m_address | 1);
|
||||
if (TRACE_MEM) logerror("tms9995: memory write byte %04x <- %02x\n", m_address | 1, m_current_value & 0xff);
|
||||
if (TRACE_MEM) logerror("memory write byte %04x <- %02x\n", m_address | 1, m_current_value & 0xff);
|
||||
m_prgspace->write_byte(m_address | 1, m_current_value & 0xff);
|
||||
m_request_auto_wait_state = m_auto_wait;
|
||||
pulse_clock(1);
|
||||
break;
|
||||
case 4:
|
||||
// no action here, just wait for READY
|
||||
m_check_hold = true;
|
||||
break;
|
||||
}
|
||||
|
||||
m_mem_phase = (m_mem_phase % 4) +1;
|
||||
|
||||
// Reset to 1 when we are done
|
||||
if (m_pass==1) m_mem_phase = 1;
|
||||
if (m_pass==1)
|
||||
{
|
||||
m_mem_phase = 1;
|
||||
m_check_hold = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1975,7 +2003,7 @@ void tms9995_device::return_with_address()
|
||||
m_instruction->program = m_caller;
|
||||
MPC = m_caller_MPC; // will be increased on return
|
||||
m_address = m_current_value + m_address_add;
|
||||
if (TRACE_DETAIL) logerror("tms9995: +++ return from operand address derivation +++\n");
|
||||
if (TRACE_DETAIL) logerror("+++ return from operand address derivation +++\n");
|
||||
// no clock pulse
|
||||
}
|
||||
|
||||
@ -1989,7 +2017,7 @@ void tms9995_device::return_with_address_copy()
|
||||
m_instruction->program = m_caller;
|
||||
MPC = m_caller_MPC; // will be increased on return
|
||||
m_address = m_address_saved;
|
||||
if (TRACE_DETAIL) logerror("tms9995: +++ return from operand address derivation (auto inc) +++\n");
|
||||
if (TRACE_DETAIL) logerror("+++ return from operand address derivation (auto inc) +++\n");
|
||||
// no clock pulse
|
||||
}
|
||||
|
||||
@ -2030,7 +2058,7 @@ void tms9995_device::return_with_address_copy()
|
||||
|
||||
void tms9995_device::cru_output_operation()
|
||||
{
|
||||
if (TRACE_CRU) logerror("tms9995: CRU output operation, address %04x, value %d\n", m_cru_address, m_cru_value & 0x01);
|
||||
if (TRACE_CRU) logerror("CRU output operation, address %04x, value %d\n", m_cru_address, m_cru_value & 0x01);
|
||||
|
||||
if (m_cru_address == 0x1fda)
|
||||
{
|
||||
@ -2045,7 +2073,7 @@ void tms9995_device::cru_output_operation()
|
||||
{
|
||||
m_check_ready = false;
|
||||
// FLAG2, FLAG3, and FLAG4 are read-only
|
||||
if (TRACE_CRU) logerror("tms9995: set CRU address %04x to %d\n", m_cru_address, m_cru_value&1);
|
||||
if (TRACE_CRU) logerror("set CRU address %04x to %d\n", m_cru_address, m_cru_value&1);
|
||||
if ((m_cru_address != 0x1ee4) && (m_cru_address != 0x1ee6) && (m_cru_address != 0x1ee8))
|
||||
m_flag[(m_cru_address>>1)&0x000f] = (m_cru_value & 0x01);
|
||||
}
|
||||
@ -2102,7 +2130,7 @@ void tms9995_device::cru_input_operation()
|
||||
// ........ ........ X....... ........
|
||||
//
|
||||
crubyte = m_cru->read_byte((m_cru_address >> 4)& CRUREADMASK);
|
||||
if (TRACE_DETAIL) logerror("tms9995: Need to get next 8 bits (addresses %04x-%04x): %02x\n", (m_cru_address&0xfff0)+14, m_cru_address&0xfff0, crubyte);
|
||||
if (TRACE_DETAIL) logerror("Need to get next 8 bits (addresses %04x-%04x): %02x\n", (m_cru_address&0xfff0)+14, m_cru_address&0xfff0, crubyte);
|
||||
m_cru_read = crubyte << 15;
|
||||
m_cru_bits_left = 8;
|
||||
|
||||
@ -2115,7 +2143,7 @@ void tms9995_device::cru_input_operation()
|
||||
m_cru_first_read = false;
|
||||
m_pass = m_count;
|
||||
}
|
||||
if (TRACE_DETAIL) logerror("tms9995: adjusted value for shift: %06x\n", m_cru_read);
|
||||
if (TRACE_DETAIL) logerror("adjusted value for shift: %06x\n", m_cru_read);
|
||||
}
|
||||
|
||||
crubit = (m_cru_read & 0x8000);
|
||||
@ -2141,7 +2169,7 @@ void tms9995_device::cru_input_operation()
|
||||
}
|
||||
}
|
||||
|
||||
if (TRACE_CRU) logerror("tms9995: CRU input operation, address %04x, value %d\n", m_cru_address, (crubit & 0x8000)>>15);
|
||||
if (TRACE_CRU) logerror("CRU input operation, address %04x, value %d\n", m_cru_address, (crubit & 0x8000)>>15);
|
||||
|
||||
m_cru_value |= crubit;
|
||||
if (crubit!=0) m_parity++;
|
||||
@ -2172,11 +2200,11 @@ void tms9995_device::trigger_decrementer()
|
||||
m_decrementer_value--;
|
||||
if (m_decrementer_value==0)
|
||||
{
|
||||
if (TRACE_DEC) logerror("tms9995: decrementer reached 0\n");
|
||||
if (TRACE_DEC) logerror("decrementer reached 0\n");
|
||||
m_decrementer_value = m_starting_count_storage_register;
|
||||
if (m_flag[1]==true)
|
||||
{
|
||||
if (TRACE_DEC) logerror("tms9995: decrementer flags interrupt\n");
|
||||
if (TRACE_DEC) logerror("decrementer flags interrupt\n");
|
||||
m_flag[3] = true;
|
||||
m_int_decrementer = true;
|
||||
}
|
||||
@ -2225,12 +2253,12 @@ void tms9995_device::operand_address_subprogram()
|
||||
{
|
||||
if (m_regnumber != 0)
|
||||
{
|
||||
if (TRACE_DETAIL) logerror("tms9995: indexed addressing\n");
|
||||
if (TRACE_DETAIL) logerror("indexed addressing\n");
|
||||
MPC = 16; // indexed
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TRACE_DETAIL) logerror("tms9995: symbolic addressing\n");
|
||||
if (TRACE_DETAIL) logerror("symbolic addressing\n");
|
||||
m_address = PC;
|
||||
PC = (PC + 2) & 0xfffe;
|
||||
}
|
||||
@ -2240,7 +2268,7 @@ void tms9995_device::operand_address_subprogram()
|
||||
m_mem_phase = 1;
|
||||
m_address_add = 0;
|
||||
MPC--; // will be increased in the mail loop
|
||||
if (TRACE_DETAIL) logerror("tms9995: *** Operand address derivation; address=%04x; index=%d\n", m_address, MPC+1);
|
||||
if (TRACE_DETAIL) logerror("*** Operand address derivation; address=%04x; index=%d\n", m_address, MPC+1);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2382,7 +2410,7 @@ void tms9995_device::alu_add_s_sxc()
|
||||
{
|
||||
set_status_parity((UINT8)(dest_new>>8));
|
||||
}
|
||||
if (TRACE_STATUS) logerror("tms9995: ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
// No clock pulse (will be done by prefetch)
|
||||
}
|
||||
|
||||
@ -2429,7 +2457,7 @@ void tms9995_device::alu_blwp()
|
||||
case 4:
|
||||
PC = m_current_value & 0xfffe;
|
||||
n = 0;
|
||||
if (TRACE_OP) logerror("tms9995: Context switch complete; WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
|
||||
if (TRACE_OP) logerror("Context switch complete; WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
|
||||
break;
|
||||
}
|
||||
m_instruction->state++;
|
||||
@ -2450,7 +2478,7 @@ void tms9995_device::alu_c()
|
||||
set_status_parity((UINT8)(m_source_value>>8));
|
||||
}
|
||||
compare_and_set_lae(m_source_value, m_current_value);
|
||||
if (TRACE_STATUS) logerror("tms9995: ST = %04x (val1=%04x, val2=%04x)\n", ST, m_source_value, m_current_value);
|
||||
if (TRACE_STATUS) logerror("ST = %04x (val1=%04x, val2=%04x)\n", ST, m_source_value, m_current_value);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2461,12 +2489,12 @@ void tms9995_device::alu_ci()
|
||||
// We have the register value in m_source_value, the register address in m_address_saved
|
||||
// and the immediate value in m_current_value
|
||||
compare_and_set_lae(m_source_value, m_current_value);
|
||||
if (TRACE_STATUS) logerror("tms9995: ST = %04x (val1=%04x, val2=%04x)\n", ST, m_source_value, m_current_value);
|
||||
if (TRACE_STATUS) logerror("ST = %04x (val1=%04x, val2=%04x)\n", ST, m_source_value, m_current_value);
|
||||
}
|
||||
|
||||
void tms9995_device::alu_clr_seto()
|
||||
{
|
||||
if (TRACE_OP) logerror("tms9995: clr/seto: Setting values for address %04x\n", m_address);
|
||||
if (TRACE_OP) logerror("clr/seto: Setting values for address %04x\n", m_address);
|
||||
switch (m_instruction->command)
|
||||
{
|
||||
case CLR:
|
||||
@ -2675,14 +2703,14 @@ void tms9995_device::alu_external()
|
||||
|
||||
if (m_instruction->command == IDLE)
|
||||
{
|
||||
if (TRACE_OP) logerror("tms9995: Entering IDLE state\n");
|
||||
if (TRACE_OP) logerror("Entering IDLE state\n");
|
||||
m_idle_state = true;
|
||||
}
|
||||
|
||||
if (m_instruction->command == RSET)
|
||||
{
|
||||
ST &= 0xfff0;
|
||||
if (TRACE_OP) logerror("tms9995: RSET, new ST = %04x\n", ST);
|
||||
if (TRACE_OP) logerror("RSET, new ST = %04x\n", ST);
|
||||
}
|
||||
|
||||
if (!m_external_operation.isnull()) m_external_operation((m_instruction->IR >> 5) & 0x07, 1, 0xff);
|
||||
@ -2723,7 +2751,7 @@ void tms9995_device::alu_f3()
|
||||
compare_and_set_lae(m_current_value, 0);
|
||||
}
|
||||
}
|
||||
if (TRACE_STATUS) logerror("tms9995: ST = %04x\n", ST);
|
||||
if (TRACE_STATUS) logerror("ST = %04x\n", ST);
|
||||
break;
|
||||
}
|
||||
m_instruction->state++;
|
||||
@ -2759,7 +2787,7 @@ void tms9995_device::alu_imm_arithm()
|
||||
m_current_value = (UINT16)(dest_new & 0xffff);
|
||||
compare_and_set_lae(m_current_value, 0);
|
||||
m_address = m_address_saved;
|
||||
if (TRACE_STATUS) logerror("tms9995: ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -2815,11 +2843,11 @@ void tms9995_device::alu_jump()
|
||||
|
||||
if (!cond)
|
||||
{
|
||||
if (TRACE_OP) logerror("tms9995: Jump condition false\n");
|
||||
if (TRACE_OP) logerror("Jump condition false\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TRACE_OP) logerror("tms9995: Jump condition true\n");
|
||||
if (TRACE_OP) logerror("Jump condition true\n");
|
||||
PC = (PC + (displacement<<1)) & 0xfffe;
|
||||
}
|
||||
}
|
||||
@ -2839,7 +2867,7 @@ void tms9995_device::alu_ldcr()
|
||||
case 1:
|
||||
// We have read the byte or word into m_current_value.
|
||||
compare_and_set_lae(m_current_value, 0);
|
||||
if (TRACE_STATUS) logerror("tms9995: ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
if (m_instruction->byteop)
|
||||
{
|
||||
m_current_value = (m_current_value>>8) & 0xff;
|
||||
@ -2868,7 +2896,7 @@ void tms9995_device::alu_li()
|
||||
// The immediate value is still in m_current_value
|
||||
m_address = m_address_saved;
|
||||
compare_and_set_lae(m_current_value, 0);
|
||||
if (TRACE_STATUS) logerror("tms9995: ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
}
|
||||
|
||||
void tms9995_device::alu_limi_lwpi()
|
||||
@ -2877,13 +2905,13 @@ void tms9995_device::alu_limi_lwpi()
|
||||
if (m_instruction->command == LIMI)
|
||||
{
|
||||
ST = (ST & 0xfff0) | (m_current_value & 0x000f);
|
||||
if (TRACE_OP) logerror("tms9995: LIMI sets ST = %04x\n", ST);
|
||||
if (TRACE_OP) logerror("LIMI sets ST = %04x\n", ST);
|
||||
pulse_clock(1); // needs one more than LWPI
|
||||
}
|
||||
else
|
||||
{
|
||||
WP = m_current_value & 0xfffe;
|
||||
if (TRACE_OP) logerror("tms9995: LWPI sets new WP = %04x\n", WP);
|
||||
if (TRACE_OP) logerror("LWPI sets new WP = %04x\n", WP);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2896,13 +2924,13 @@ void tms9995_device::alu_lst_lwp()
|
||||
if (m_instruction->command==LST)
|
||||
{
|
||||
ST = m_current_value;
|
||||
if (TRACE_OP) logerror("tms9995: new ST = %04x\n", ST);
|
||||
if (TRACE_OP) logerror("new ST = %04x\n", ST);
|
||||
pulse_clock(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
WP = m_current_value & 0xfffe;
|
||||
if (TRACE_OP) logerror("tms9995: new WP = %04x\n", WP);
|
||||
if (TRACE_OP) logerror("new WP = %04x\n", WP);
|
||||
}
|
||||
}
|
||||
|
||||
@ -2920,7 +2948,7 @@ void tms9995_device::alu_mov()
|
||||
set_status_parity((UINT8)(m_current_value>>8));
|
||||
}
|
||||
compare_and_set_lae(m_current_value, 0);
|
||||
if (TRACE_STATUS) logerror("tms9995: ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
// No clock pulse, as next instruction is prefetch
|
||||
}
|
||||
|
||||
@ -3013,7 +3041,7 @@ void tms9995_device::alu_rtwp()
|
||||
// Just for debugging purposes
|
||||
m_servicing_interrupt = false;
|
||||
|
||||
if (TRACE_OP) logerror("tms9995: RTWP restored old context (WP=%04x, PC=%04x, ST=%04x)\n", WP, PC, ST);
|
||||
if (TRACE_OP) logerror("RTWP restored old context (WP=%04x, PC=%04x, ST=%04x)\n", WP, PC, ST);
|
||||
break;
|
||||
}
|
||||
m_instruction->state++;
|
||||
@ -3066,7 +3094,7 @@ void tms9995_device::alu_shift()
|
||||
}
|
||||
else
|
||||
{
|
||||
if (TRACE_DETAIL) logerror("tms9995: Shift operation gets count from R0\n");
|
||||
if (TRACE_DETAIL) logerror("Shift operation gets count from R0\n");
|
||||
}
|
||||
pulse_clock(1);
|
||||
pulse_clock(1);
|
||||
@ -3111,7 +3139,7 @@ void tms9995_device::alu_shift()
|
||||
set_status_bit(ST_OV, overflow);
|
||||
compare_and_set_lae(m_current_value, 0);
|
||||
m_address = m_address_saved; // Register address
|
||||
if (TRACE_STATUS) logerror("tms9995: ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
break;
|
||||
}
|
||||
m_instruction->state++;
|
||||
@ -3207,7 +3235,7 @@ void tms9995_device::alu_single_arithm()
|
||||
m_current_value = dest_new & 0xffff;
|
||||
compare_and_set_lae(m_current_value, 0);
|
||||
|
||||
if (TRACE_STATUS) logerror("tms9995: ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
// No clock pulse, as next instruction is prefetch
|
||||
}
|
||||
|
||||
@ -3245,7 +3273,7 @@ void tms9995_device::alu_stcr()
|
||||
m_current_value <<= 8;
|
||||
}
|
||||
else n += 8;
|
||||
if (TRACE_STATUS) logerror("tms9995: ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);
|
||||
break;
|
||||
}
|
||||
m_instruction->state++;
|
||||
@ -3285,7 +3313,7 @@ void tms9995_device::alu_tb()
|
||||
break;
|
||||
case 2:
|
||||
set_status_bit(ST_EQ, m_cru_value!=0);
|
||||
if (TRACE_STATUS) logerror("tms9995: ST = %04x\n", ST);
|
||||
if (TRACE_STATUS) logerror("ST = %04x\n", ST);
|
||||
break;
|
||||
}
|
||||
m_instruction->state++;
|
||||
@ -3368,7 +3396,7 @@ void tms9995_device::alu_int()
|
||||
case 0:
|
||||
PC = (PC - 2) & 0xfffe;
|
||||
m_address_saved = m_address;
|
||||
if (TRACE_INTD) logerror("tms9995: interrupt service (0): Prepare to read vector\n");
|
||||
if (TRACE_INTD) logerror("interrupt service (0): Prepare to read vector\n");
|
||||
break;
|
||||
case 1:
|
||||
pulse = 2; // two cycles (with the one at the end)
|
||||
@ -3376,30 +3404,30 @@ void tms9995_device::alu_int()
|
||||
WP = m_current_value & 0xfffe; // new WP
|
||||
m_current_value = ST;
|
||||
m_address = (WP + 30)&0xfffe;
|
||||
if (TRACE_INTD) logerror("tms9995: interrupt service (1): Read new WP = %04x, save ST to %04x\n", WP, m_address);
|
||||
if (TRACE_INTD) logerror("interrupt service (1): Read new WP = %04x, save ST to %04x\n", WP, m_address);
|
||||
break;
|
||||
case 2:
|
||||
m_address = (WP + 28)&0xfffe;
|
||||
m_current_value = PC;
|
||||
if (TRACE_INTD) logerror("tms9995: interrupt service (2): Save PC to %04x\n", m_address);
|
||||
if (TRACE_INTD) logerror("interrupt service (2): Save PC to %04x\n", m_address);
|
||||
break;
|
||||
case 3:
|
||||
m_address = (WP + 26)&0xfffe;
|
||||
m_current_value = m_source_value; // old WP
|
||||
if (TRACE_INTD) logerror("tms9995: interrupt service (3): Save WP to %04x\n", m_address);
|
||||
if (TRACE_INTD) logerror("interrupt service (3): Save WP to %04x\n", m_address);
|
||||
break;
|
||||
case 4:
|
||||
m_address = (m_address_saved + 2) & 0xfffe;
|
||||
if (TRACE_INTD) logerror("tms9995: interrupt service (4): Read PC from %04x\n", m_address);
|
||||
if (TRACE_INTD) logerror("interrupt service (4): Read PC from %04x\n", m_address);
|
||||
break;
|
||||
case 5:
|
||||
PC = m_current_value & 0xfffe;
|
||||
ST = (ST & 0xfe00) | m_intmask;
|
||||
if (TRACE_INTD) logerror("tms9995: interrupt service (5): Context switch complete; WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
|
||||
if (TRACE_INTD) logerror("interrupt service (5): Context switch complete; WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST);
|
||||
|
||||
if (((m_int_pending & PENDING_MID)!=0) && m_nmi_active)
|
||||
{
|
||||
if (TRACE_INTD) logerror("tms9995: interrupt service (6): NMI active after context switch\n");
|
||||
if (TRACE_INTD) logerror("interrupt service (6): NMI active after context switch\n");
|
||||
m_int_pending &= ~PENDING_MID;
|
||||
m_address = 0xfffc;
|
||||
m_intmask = 0;
|
||||
@ -3409,7 +3437,7 @@ void tms9995_device::alu_int()
|
||||
{
|
||||
if (m_from_reset)
|
||||
{
|
||||
if (TRACE_INTD) logerror("tms9995: interrupt service (6): RESET completed\n");
|
||||
if (TRACE_INTD) logerror("interrupt service (6): RESET completed\n");
|
||||
// We came from the RESET interrupt
|
||||
m_from_reset = false;
|
||||
ST &= 0x01ff;
|
||||
|
@ -54,12 +54,16 @@ public:
|
||||
// READY input line. When asserted (high), the memory is ready for data exchange.
|
||||
// We chose to use a direct method instead of a delegate to keep performance
|
||||
// footprint low; this method may be called very frequently.
|
||||
void set_ready(int state);
|
||||
DECLARE_WRITE_LINE_MEMBER( set_ready );
|
||||
|
||||
// HOLD input line. When asserted (low), the CPU is requested to release the
|
||||
// data and address bus and enter the HOLD state. The entrance of this state
|
||||
// is acknowledged by the HOLDA output line.
|
||||
void set_hold(int state);
|
||||
DECLARE_WRITE_LINE_MEMBER( set_hold );
|
||||
|
||||
// RESET input line. Unlike the standard set_input_line, this input method
|
||||
// is synchronous and will immediately lead to a reset of the CPU.
|
||||
DECLARE_WRITE_LINE_MEMBER( reset_line );
|
||||
|
||||
// Callbacks
|
||||
template<class _Object> static devcb_base &static_set_extop_callback(device_t &device, _Object object) { return downcast<tms9995_device &>(device).m_external_operation.set_callback(object); }
|
||||
@ -133,6 +137,7 @@ private:
|
||||
bool m_nmi_state;
|
||||
// bool m_irq_state;
|
||||
bool m_hold_state;
|
||||
bool m_hold_requested;
|
||||
|
||||
// READY handling. The READY line is operated before the clock
|
||||
// pulse falls. As the ready line is only set once in this emulation we
|
||||
@ -205,7 +210,7 @@ private:
|
||||
inline void pulse_clock(int count);
|
||||
|
||||
// Signal the hold state via the external line
|
||||
inline void set_hold_state(bool state);
|
||||
void set_hold_state(bool state);
|
||||
|
||||
// Only used for the DIV(S) operations. It seems sufficient to let the
|
||||
// command terminate at this point, so this method just calls command_terminated.
|
||||
|
Loading…
Reference in New Issue
Block a user