diff options
Diffstat (limited to 'src/devices/cpu/tms9900/tms9900.cpp')
-rw-r--r-- | src/devices/cpu/tms9900/tms9900.cpp | 101 |
1 files changed, 42 insertions, 59 deletions
diff --git a/src/devices/cpu/tms9900/tms9900.cpp b/src/devices/cpu/tms9900/tms9900.cpp index c2ef748a925..5ae5cb54f6b 100644 --- a/src/devices/cpu/tms9900/tms9900.cpp +++ b/src/devices/cpu/tms9900/tms9900.cpp @@ -124,29 +124,29 @@ enum The following defines can be set to 0 or 1 to disable or enable certain output in the log. */ -#define LOG_OP (1U<<1) // Current instruction -#define LOG_EXEC (1U<<2) // Address of current instruction -#define LOG_CYCLES (1U<<4) // Cycles -#define LOG_WARN (1U<<5) // Illegal operation or other condition -#define LOG_MEM (1U<<6) // Memory access -#define LOG_CONTEXT (1U<<7) // Context switch -#define LOG_INT (1U<<8) // Interrupts -#define LOG_READY (1U<<9) // READY line input -#define LOG_CLOCK (1U<<10) // Clock pulses -#define LOG_ADDRESSBUS (1U<<11) // Address bus operation -#define LOG_STATUS (1U<<12) // Status register -#define LOG_CRU (1U<<13) // CRU operations -#define LOG_WAIT (1U<<15) // Wait states -#define LOG_HOLD (1U<<16) // Hold states -#define LOG_IDLE (1U<<17) // Idle states -#define LOG_EMU (1U<<18) // Emulation details -#define LOG_MICRO (1U<<19) // Microinstruction processing -#define LOG_INTD (1U<<20) // Interrupts (detailed phases) -#define LOG_LOAD (1U<<21) // LOAD interrupt -#define LOG_DETAIL (1U<<31) // Increased detail +#define LOG_OP (1U << 1) // Current instruction +#define LOG_EXEC (1U << 2) // Address of current instruction +#define LOG_CYCLES (1U << 4) // Cycles +#define LOG_WARN (1U << 5) // Illegal operation or other condition +#define LOG_MEM (1U << 6) // Memory access +#define LOG_CONTEXT (1U << 7) // Context switch +#define LOG_INT (1U << 8) // Interrupts +#define LOG_READY (1U << 9) // READY line input +#define LOG_CLOCK (1U << 10) // Clock pulses +#define LOG_ADDRESSBUS (1U << 11) // Address bus operation +#define LOG_STATUS (1U << 12) // Status register +#define LOG_CRU (1U << 13) // CRU operations +#define LOG_WAIT (1U << 15) // Wait states +#define LOG_HOLD (1U << 16) // Hold states +#define LOG_IDLE (1U << 17) // Idle states +#define LOG_EMU (1U << 18) // Emulation details +#define LOG_MICRO (1U << 19) // Microinstruction processing +#define LOG_INTD (1U << 20) // Interrupts (detailed phases) +#define LOG_LOAD (1U << 21) // LOAD interrupt +#define LOG_DETAIL (1U << 31) // Increased detail // Minimum log should be warnings -#define VERBOSE ( LOG_GENERAL | LOG_WARN ) +#define VERBOSE (LOG_GENERAL | LOG_WARN) #include "logmacro.h" @@ -169,7 +169,7 @@ tms99xx_device::tms99xx_device(const machine_config &mconfig, device_type type, m_clock_out_line(*this), m_wait_line(*this), m_holda_line(*this), - m_get_intlevel(*this), + m_get_intlevel(*this, 0), m_external_operation(*this), m_ready_bufd(true), m_program_index(NOPRG), @@ -202,7 +202,6 @@ enum void tms99xx_device::device_start() { // TODO: Restore state save feature - resolve_lines(); m_prgspace = &space(AS_PROGRAM); m_setaddr = has_space(AS_SETADDRESS) ? &space(AS_SETADDRESS) : nullptr; m_cru = &space(AS_IO); @@ -221,8 +220,8 @@ void tms99xx_device::device_start() // callexport = need to use the state_export method to read the state variable state_add(i, s_statename[i], m_state_any).callimport().callexport().formatstr("%04X"); } - state_add(STATE_GENPC, "GENPC", PC).formatstr("%4s").noshow(); - state_add(STATE_GENPCBASE, "CURPC", PC).formatstr("%4s").noshow(); + state_add(STATE_GENPC, "GENPC", PC).noshow(); + state_add(STATE_GENPCBASE, "CURPC", PC).noshow(); state_add(STATE_GENFLAGS, "status", m_state_any).callimport().callexport().formatstr("%16s").noshow(); build_command_lookup_table(); @@ -278,19 +277,6 @@ void tms99xx_device::device_stop() } /* - External connections -*/ -void tms99xx_device::resolve_lines() -{ - // Resolve our external connections - m_external_operation.resolve(); - m_get_intlevel.resolve(); - m_clock_out_line.resolve(); - m_wait_line.resolve(); - m_holda_line.resolve(); -} - -/* TMS9900 hard reset The device reset is just the emulator's trigger for the reset procedure which is invoked via the main loop. @@ -1218,7 +1204,7 @@ void tms99xx_device::execute_run() { LOGMASKED(LOG_IDLE, "IDLE state\n"); pulse_clock(1); - if (!m_external_operation.isnull()) + if (!m_external_operation.isunset()) { m_external_operation(IDLE_OP, 0, 0xff); m_external_operation(IDLE_OP, 1, 0xff); @@ -1322,7 +1308,7 @@ void tms99xx_device::execute_set_input(int irqline, int state) */ int tms99xx_device::get_intlevel(int state) { - if (!m_get_intlevel.isnull()) return m_get_intlevel(0); + if (!m_get_intlevel.isunset()) return m_get_intlevel(0); return 0; } @@ -1332,7 +1318,7 @@ void tms99xx_device::service_interrupt() m_command = INTR; m_idle_state = false; - if (!m_external_operation.isnull()) m_external_operation(IDLE_OP, 0, 0xff); + if (!m_external_operation.isunset()) m_external_operation(IDLE_OP, 0, 0xff); m_state = 0; @@ -1360,6 +1346,12 @@ void tms99xx_device::service_interrupt() m_reset = false; LOG("** RESET triggered\n"); + + // RESET could occur during a data derivation sequence, so we have to + // prevent the execution loop to return into that sequence by + // clearing the return index. This fixes a bug that leads to undefined + // behaviour in that situation. + m_caller_index = NOPRG; } else { @@ -1380,9 +1372,9 @@ void tms99xx_device::pulse_clock(int count) { for (int i=0; i < count; i++) { - if (!m_clock_out_line.isnull()) m_clock_out_line(ASSERT_LINE); + if (!m_clock_out_line.isunset()) m_clock_out_line(ASSERT_LINE); m_ready = m_ready_bufd; // get the latched READY state - if (!m_clock_out_line.isnull()) m_clock_out_line(CLEAR_LINE); + if (!m_clock_out_line.isunset()) m_clock_out_line(CLEAR_LINE); m_icount--; // This is the only location where we count down the cycles. if (m_check_ready) LOGMASKED(LOG_CLOCK, "pulse_clock, READY=%d\n", m_ready? 1:0); else LOGMASKED(LOG_CLOCK, "pulse_clock\n"); @@ -1398,7 +1390,7 @@ void tms99xx_device::set_hold(int state) if (!m_hold_state) { m_hold_acknowledged = false; - if (!m_holda_line.isnull()) m_holda_line(CLEAR_LINE); + if (!m_holda_line.isunset()) m_holda_line(CLEAR_LINE); } } @@ -1408,7 +1400,7 @@ void tms99xx_device::set_hold(int state) inline void tms99xx_device::acknowledge_hold() { m_hold_acknowledged = true; - if (!m_holda_line.isnull()) m_holda_line(ASSERT_LINE); + if (!m_holda_line.isunset()) m_holda_line(ASSERT_LINE); } /* @@ -1444,7 +1436,7 @@ void tms99xx_device::abort_operation() inline void tms99xx_device::set_wait_state(bool state) { if (m_wait_state != state) - if (!m_wait_line.isnull()) m_wait_line(state? ASSERT_LINE : CLEAR_LINE); + if (!m_wait_line.isunset()) m_wait_line(state? ASSERT_LINE : CLEAR_LINE); m_wait_state = state; } @@ -2222,7 +2214,7 @@ void tms99xx_device::alu_clr_swpb() sign = 0x8000; break; case SWPB: - m_current_value = ((m_current_value << 8) | (m_current_value >> 8)) & 0xffff; + m_current_value = swapendian_int16(m_current_value); setstatus = false; break; } @@ -2670,7 +2662,7 @@ void tms99xx_device::alu_external() if (m_command == IDLE) m_idle_state = true; - if (!m_external_operation.isnull()) m_external_operation((IR >> 5) & 0x07, 1, 0xff); + if (!m_external_operation.isunset()) m_external_operation((IR >> 5) & 0x07, 1, 0xff); pulse_clock(2); } @@ -2765,7 +2757,7 @@ void tms99xx_device::alu_int() /* The minimum number of cycles applies to a command like STWP R0. */ -uint32_t tms99xx_device::execute_min_cycles() const +uint32_t tms99xx_device::execute_min_cycles() const noexcept { return 8; } @@ -2774,20 +2766,11 @@ uint32_t tms99xx_device::execute_min_cycles() const The maximum number of cycles applies to a DIV command, depending on the data to be divided, and the mode of adressing. */ -uint32_t tms99xx_device::execute_max_cycles() const +uint32_t tms99xx_device::execute_max_cycles() const noexcept { return 124; } -uint32_t tms99xx_device::execute_input_lines() const -{ - return 2; -} - -// clocks to cycles, cycles to clocks = id -// execute_default_irq_vector = 0 -// execute_burn = nop - // device_disasm_interface overrides std::unique_ptr<util::disasm_interface> tms99xx_device::create_disassembler() |