diff options
author | 2013-11-01 17:06:32 +0000 | |
---|---|---|
committer | 2013-11-01 17:06:32 +0000 | |
commit | f4ff52905ae2e4e875a79e937d872c5e05b23772 (patch) | |
tree | eb50411f2cdc3c76242f58772cef6ad822c6e3d9 /src/emu | |
parent | 4d6f21861bb5c09bc356211ba66671d55ec771ff (diff) |
tms9995: Cycles fine-tuned, almost complete. (nw)
Diffstat (limited to 'src/emu')
-rw-r--r-- | src/emu/cpu/tms9900/tms9995.c | 366 | ||||
-rw-r--r-- | src/emu/cpu/tms9900/tms9995.h | 1 |
2 files changed, 196 insertions, 171 deletions
diff --git a/src/emu/cpu/tms9900/tms9995.c b/src/emu/cpu/tms9900/tms9995.c index c2606121f7a..97291c3a29b 100644 --- a/src/emu/cpu/tms9900/tms9995.c +++ b/src/emu/cpu/tms9900/tms9995.c @@ -84,7 +84,6 @@ [1] Texas Instruments 9900 Microprocessor series: TMS9995 16-bit Microcomputer TODO: - - Fine-tune cycles - State save - Test HOLD @@ -117,7 +116,18 @@ enum PENDING_LEVEL4 = 32 }; +/***************************************************************** + Debugging + Set to 0 (disable) or 1 (enable) +******************************************************************/ + #define LOG logerror + +// Log addresses of executed opcodes +#define TRACE_EXEC 0 + +// old debugging approach; going to be replaced +// VERBOSE = 0 ... 9 #define VERBOSE 1 /**************************************************************************** @@ -214,6 +224,7 @@ void tms9995_device::device_stop() void tms9995_device::device_reset() { m_reset = true; // for the main loop + m_servicing_interrupt = false; // only for debugging } const char* tms9995_device::s_statename[20] = @@ -471,7 +482,7 @@ MICROPROGRAM(add_s_sxc_mp) MEMORY_READ, // 1 (1) ALU_ADD_S_SXC, // 0 (see above, occurs in parallel with PREFETCH) PREFETCH, // 1 (1) - MEMORY_WRITE, // 1 (1) + DECODE=0 + MEMORY_WRITE, // 1 (1) + decode in parallel (0) END }; @@ -530,7 +541,7 @@ MICROPROGRAM(c_mp) MICROPROGRAM(ci_mp) { MEMORY_READ, // 1 (1) (reg) - SET_IMM, // 0 + SET_IMM, // 0 belongs to next cycle MEMORY_READ, // 1 (1) (imm) ALU_CI, // 0 set status PREFETCH, // 1 (1) @@ -540,105 +551,106 @@ MICROPROGRAM(ci_mp) MICROPROGRAM(coc_czc_mp) { - OPERAND_ADDR, - MEMORY_READ, - ALU_F3, - MEMORY_READ, - ALU_F3, - PREFETCH, - ALU_NOP, + OPERAND_ADDR, // x + MEMORY_READ, // 1 (1) + ALU_F3, // 0 + MEMORY_READ, // 1 (1) + ALU_F3, // 0 + PREFETCH, // 1 (1) + ALU_NOP, // 1 decode END }; MICROPROGRAM(clr_seto_mp) { - OPERAND_ADDR, - ALU_NOP, - ALU_CLR_SETO, // (1) - PREFETCH, // 1 - MEMORY_WRITE, // 1 + OPERAND_ADDR, // x + ALU_NOP, // 1 + ALU_CLR_SETO, // 0 + PREFETCH, // 1 (1) + MEMORY_WRITE, // 1 (1) END }; -MICROPROGRAM(divide_mp) -{ - OPERAND_ADDR, // Address of divisor S in Q=W1W2/S - MEMORY_READ, // Get S - ALU_DIV, - MEMORY_READ, // Get W1 - ALU_DIV, // Check for overflow; skip next instruction if not - ABORT, - MEMORY_READ, // Get W2 - ALU_DIV, // Calculate quotient - MEMORY_WRITE, // Write quotient to &W1 - ALU_DIV, - PREFETCH, - MEMORY_WRITE, // Write remainder to &W2 +MICROPROGRAM(divide_mp) // TODO: Verify cycles on the real machine +{ + OPERAND_ADDR, // x Address of divisor S in Q=W1W2/S + MEMORY_READ, // 1 (1) Get S + ALU_DIV, // 1 + MEMORY_READ, // 1 (1) Get W1 + ALU_DIV, // 1 Check for overflow; skip next instruction if not + ABORT, // 1 + MEMORY_READ, // 1 (1) Get W2 + ALU_DIV, // d Calculate quotient + MEMORY_WRITE, // 1 (1) Write quotient to &W1 + ALU_DIV, // 0 + PREFETCH, // 1 (1) + MEMORY_WRITE, // 1 (1) Write remainder to &W2 END }; -MICROPROGRAM(divide_signed_mp) -{ - OPERAND_ADDR, // Address of divisor S in Q=W1W2/S - MEMORY_READ, // Get S - ALU_DIVS, - MEMORY_READ, // Get W1 - ALU_DIVS, // - MEMORY_READ, // Get W2 - ALU_DIVS, // Check for overflow, skip next instruction if not - ABORT, - ALU_DIVS, // Calculate quotient - MEMORY_WRITE, // Write quotient to &W1 - ALU_DIVS, - PREFETCH, - MEMORY_WRITE, // Write remainder to &W2 +MICROPROGRAM(divide_signed_mp) // TODO: Verify cycles on the real machine +{ + OPERAND_ADDR, // x Address of divisor S in Q=W1W2/S + MEMORY_READ, // 1 (1) Get S + ALU_DIVS, // 1 + MEMORY_READ, // 1 (1) Get W1 + ALU_DIVS, // 1 + MEMORY_READ, // 1 (1) Get W2 + ALU_DIVS, // 1 Check for overflow, skip next instruction if not + ABORT, // 1 + ALU_DIVS, // d Calculate quotient + MEMORY_WRITE, // 1 (1) Write quotient to &W1 + ALU_DIVS, // 0 + PREFETCH, // 1 + MEMORY_WRITE, // 1 (1) Write remainder to &W2 END }; MICROPROGRAM(external_mp) { - ALU_NOP, - ALU_NOP, - ALU_NOP, - ALU_NOP, - ALU_NOP, - ALU_EXTERNAL, - PREFETCH, - ALU_NOP, + ALU_NOP, // 1 + ALU_NOP, // 1 + ALU_NOP, // 1 + ALU_NOP, // 1 + ALU_NOP, // 1 + ALU_EXTERNAL, // 0 + PREFETCH, // 1 (1) + ALU_NOP, // 1 END }; MICROPROGRAM(imm_arithm_mp) { - MEMORY_READ, + MEMORY_READ, // 1 (1) SET_IMM, // 0 MEMORY_READ, // 1 (1) ALU_IMM_ARITHM, // 0 PREFETCH, // 1 (1) - MEMORY_WRITE, + MEMORY_WRITE, // 1 (1) END }; MICROPROGRAM(jump_mp) { - ALU_JUMP, - PREFETCH, - ALU_NOP, + ALU_NOP, // 1 + ALU_JUMP, // 0 + PREFETCH, // 1 (1) + ALU_NOP, // 1 END }; -MICROPROGRAM(ldcr_mp) +MICROPROGRAM(ldcr_mp) // TODO: Verify cycles { - ALU_LDCR, - OPERAND_ADDR, - MEMORY_READ, // Get source data - ALU_LDCR, // Save it, point to R12 - WORD_READ, // Get R12 - ALU_LDCR, // Prepare CRU operation - CRU_OUTPUT, - ALU_NOP, - PREFETCH, - ALU_NOP, + ALU_LDCR, // 1 + OPERAND_ADDR, // x + MEMORY_READ, // 1 (1) Get source data + ALU_LDCR, // 1 Save it, point to R12 + WORD_READ, // 1 (1) Get R12 + ALU_LDCR, // 1 Prepare CRU operation + CRU_OUTPUT, // c + ALU_NOP, // 0 + PREFETCH, // 1 (1) + ALU_NOP, // 1 END }; @@ -657,19 +669,19 @@ MICROPROGRAM(limi_lwpi_mp) SET_IMM, // 0 MEMORY_READ, // 1 (1) ALU_NOP, // 1 - ALU_LIMIWP, // (1) - PREFETCH, // 1 + ALU_LIMIWP, // 0 lwpi, 1 limi + PREFETCH, // 1 (1) ALU_NOP, // 1 END }; MICROPROGRAM(lst_lwp_mp) { - MEMORY_READ, - ALU_NOP, - ALU_LSTWP, - PREFETCH, - ALU_NOP, + MEMORY_READ, // 1 (1) + ALU_NOP, // 1 + ALU_LSTWP, // 0 lwp, 1 lst + PREFETCH, // 1 (1) + ALU_NOP, // 1 END }; @@ -678,146 +690,148 @@ MICROPROGRAM(mov_mp) OPERAND_ADDR, // 0 MEMORY_READ, // 1 (1) OPERAND_ADDR, // 0 - ALU_MOV, // 1 - PREFETCH, + ALU_MOV, // 0 + PREFETCH, // 1 (1) MEMORY_WRITE, // 1 (1) END }; MICROPROGRAM(multiply_mp) { - OPERAND_ADDR, - MEMORY_READ, - ALU_MPY, - MEMORY_READ, - ALU_MPY, - MEMORY_WRITE, - ALU_MPY, - PREFETCH, - MEMORY_WRITE, + OPERAND_ADDR, // x + MEMORY_READ, // 1 (1) + ALU_MPY, // 1 + MEMORY_READ, // 1 (1) + ALU_MPY, // 17 + MEMORY_WRITE, // 1 (1) + ALU_MPY, // 0 + PREFETCH, // 1 (1) + MEMORY_WRITE, // 1 (1) END }; MICROPROGRAM(rtwp_mp) { - ALU_RTWP, - MEMORY_READ, - ALU_RTWP, - MEMORY_READ, - ALU_RTWP, - MEMORY_READ, - ALU_RTWP, - PREFETCH, - ALU_NOP, + ALU_RTWP, // 1 + MEMORY_READ, // 1 (1) + ALU_RTWP, // 0 + MEMORY_READ, // 1 (1) + ALU_RTWP, // 0 + MEMORY_READ, // 1 (1) + ALU_RTWP, // 0 + PREFETCH, // 1 (1) + ALU_NOP, // 1 END }; MICROPROGRAM(sbo_sbz_mp) { - ALU_SBO_SBZ, // Set address = &R12 - WORD_READ, // Read R12 - ALU_SBO_SBZ, // Add offset - CRU_OUTPUT, // output via CRU - ALU_NOP, - PREFETCH, - ALU_NOP, + ALU_SBO_SBZ, // 1 Set address = &R12 + WORD_READ, // 1 (1) Read R12 + ALU_SBO_SBZ, // 1 Add offset + CRU_OUTPUT, // 1 output via CRU + PREFETCH, // 1 (1) + ALU_NOP, // 1 + ALU_NOP, // 1 END }; MICROPROGRAM(shift_mp) { - MEMORY_READ, - ALU_SHIFT, // skip next operation if count != 0 - MEMORY_READ, // if count=0 we must read R0 - ALU_SHIFT, // do the shift - PREFETCH, - MEMORY_WRITE, + MEMORY_READ, // 1 (1) + ALU_SHIFT, // 2 skip next operation if count != 0 + MEMORY_READ, // 1 (1) if count=0 we must read R0 + ALU_SHIFT, // c do the shift + PREFETCH, // 1 (1) + MEMORY_WRITE, // 1 (1) END }; MICROPROGRAM(single_arithm_mp) { - OPERAND_ADDR, - MEMORY_READ, // This one is not done for CLR/SETO - ALU_SINGLE_ARITHM, - PREFETCH, - MEMORY_WRITE, + OPERAND_ADDR, // x + MEMORY_READ, // 1 (1) + ALU_SINGLE_ARITHM, // 0 + PREFETCH, // 1 (1) + MEMORY_WRITE, // 1 (1) END }; -MICROPROGRAM(stcr_mp) +MICROPROGRAM(stcr_mp) // TODO: Verify on real machine { - ALU_STCR, // Check for byte operation - OPERAND_ADDR, // Source operand - ALU_STCR, // Save, set R12 - WORD_READ, // Read R12 - ALU_STCR, - CRU_INPUT, - ALU_STCR, - PREFETCH, - MEMORY_WRITE, + ALU_STCR, // 1 Check for byte operation + OPERAND_ADDR, // x Source operand + ALU_STCR, // 1 Save, set R12 + WORD_READ, // 1 (1) Read R12 + ALU_STCR, // 1 + CRU_INPUT, // c + ALU_STCR, // 13 + PREFETCH, // 1 (1) + MEMORY_WRITE, // 1 (1) END }; MICROPROGRAM(stst_stwp_mp) { - ALU_STSTWP, - ALU_NOP, - PREFETCH, - MEMORY_WRITE, + ALU_STSTWP, // 0 + ALU_NOP, // 1 + PREFETCH, // 1 (1) + MEMORY_WRITE, // 1 (1) END }; MICROPROGRAM(tb_mp) { - ALU_TB, - WORD_READ, - ALU_TB, - CRU_INPUT, - ALU_TB, - PREFETCH, - ALU_NOP, + ALU_TB, // 1 + WORD_READ, // 1 (1) + ALU_TB, // 1 + CRU_INPUT, // 2 + ALU_TB, // 0 + PREFETCH, // 1 (1) + ALU_NOP, // 1 + ALU_NOP, // 1 END }; MICROPROGRAM(x_mp) { - OPERAND_ADDR, - MEMORY_READ, - ALU_X, + OPERAND_ADDR, // x + MEMORY_READ, // 1 (1) + ALU_X, // 1 END // should not be reached }; MICROPROGRAM(xop_mp) { - OPERAND_ADDR, // Determine source address - ALU_XOP, // Save it; determine XOP number - MEMORY_READ, // Read new WP - ALU_XOP, // - MEMORY_WRITE, // save source address to new R11 - ALU_XOP, - MEMORY_WRITE, // save old ST to new R15 - ALU_XOP, - MEMORY_WRITE, // save old PC to new R14 - ALU_XOP, - MEMORY_WRITE, // save old WP to new R13 - ALU_XOP, - MEMORY_READ, // Read new PC - ALU_XOP, // set new PC, set X flag - PREFETCH, - ALU_NOP, + OPERAND_ADDR, // x Determine source address + ALU_XOP, // 1 Save it; determine XOP number + MEMORY_READ, // 1 (1) Read new WP + ALU_XOP, // 1 + MEMORY_WRITE, // 1 (1) save source address to new R11 + ALU_XOP, // 1 + MEMORY_WRITE, // 1 (1) save old ST to new R15 + ALU_XOP, // 1 + MEMORY_WRITE, // 1 (1) save old PC to new R14 + ALU_XOP, // 1 + MEMORY_WRITE, // 1 (1) save old WP to new R13 + ALU_XOP, // 1 + MEMORY_READ, // 1 (1) Read new PC + ALU_XOP, // 0 set new PC, set X flag + PREFETCH, // 1 (1) + ALU_NOP, // 1 + ALU_NOP, // 1 END }; MICROPROGRAM(xor_mp) { - OPERAND_ADDR, - MEMORY_READ, - ALU_F3, - MEMORY_READ, - ALU_F3, - PREFETCH, - MEMORY_WRITE, + OPERAND_ADDR, // x + MEMORY_READ, // 1 (1) + ALU_F3, // 0 + MEMORY_READ, // 1 (1) + ALU_F3, // 0 + PREFETCH, // 1 (1) + MEMORY_WRITE, // 1 (1) END }; @@ -1470,6 +1484,10 @@ void tms9995_device::next_command() m_address = WP + ((m_instruction->IR & 0x000f)<<1); MPC = -1; if (VERBOSE>3) LOG("tms9995: ===== Next operation %04x (%s) at %04x =====\n", m_instruction->IR, opname[m_instruction->command], PC-2); +#if TRACE_EXEC + if (m_servicing_interrupt) LOG("i%04x\n", PC-2); + else LOG("%04x\n", PC-2); +#endif PC_debug = PC - 2; debugger_instruction_hook(this, PC_debug); m_first_cycle = m_icount; @@ -1609,6 +1627,9 @@ void tms9995_device::service_interrupt() if (VERBOSE>6) LOG("tms9995: ********* triggered an interrupt with vector %04x/%04x\n", vectorpos, vectorpos+2); + // just for debugging purposes + m_servicing_interrupt = true; + // The microinstructions will do the context switch m_address = vectorpos; m_instruction->program = int_mp; @@ -2632,7 +2653,6 @@ void tms9995_device::alu_f3() if (VERBOSE>7) LOG("tms9995: ST = %04x\n", ST); break; } - pulse_clock(1); m_instruction->state++; } @@ -2729,7 +2749,6 @@ void tms9995_device::alu_jump() if (VERBOSE>7) LOG("tms9995: Jump condition true\n"); PC = (PC + (displacement<<1)) & 0xfffe; } - pulse_clock(1); } /* @@ -2858,7 +2877,7 @@ void tms9995_device::alu_multiply() m_current_value = (result >> 16) & 0xffff; m_value_copy = result & 0xffff; // m_address is still the register - n = 16; + n = 17; break; case 2: m_address += 2; @@ -2901,11 +2920,11 @@ void tms9995_device::alu_multiply() void tms9995_device::alu_rtwp() { - int n = 0; switch (m_instruction->state) { case 0: m_address = WP + 30; // R15 + pulse_clock(1); break; case 1: ST = m_current_value; @@ -2917,12 +2936,14 @@ void tms9995_device::alu_rtwp() break; case 3: WP = m_current_value & 0xfffe; - n = 1; + + // Just for debugging purposes + m_servicing_interrupt = false; + if (VERBOSE>4) LOG("tms9995: RTWP restored old context (WP=%04x, PC=%04x, ST=%04x)\n", WP, PC, ST); break; } m_instruction->state++; - pulse_clock(n); } void tms9995_device::alu_sbo_sbz() @@ -2969,12 +2990,13 @@ void tms9995_device::alu_shift() { // skip the next read operation MPC++; - pulse_clock(1); } else { if (VERBOSE>8) LOG("tms9995: Shift operation gets count from R0\n"); } + pulse_clock(1); + pulse_clock(1); break; case 1: @@ -3020,7 +3042,6 @@ void tms9995_device::alu_shift() break; } m_instruction->state++; - pulse_clock(1); } /* @@ -3217,7 +3238,6 @@ void tms9995_device::alu_x() */ void tms9995_device::alu_xop() { - int n = 1; switch (m_instruction->state) { case 0: @@ -3225,6 +3245,7 @@ void tms9995_device::alu_xop() m_address_saved = m_address; // Format is xxxx xxnn nnxx xxxx m_address = 0x0040 + ((m_instruction->IR & 0x03c0)>>4); + pulse_clock(1); break; case 1: // m_current_value is new WP @@ -3232,30 +3253,33 @@ void tms9995_device::alu_xop() WP = m_current_value & 0xfffe; m_address = WP + 0x0016; // Address of new R11 m_current_value = m_address_saved; + pulse_clock(1); break; case 2: m_address = WP + 0x001e; m_current_value = ST; + pulse_clock(1); break; case 3: m_address = WP + 0x001c; m_current_value = PC; + pulse_clock(1); break; case 4: m_address = WP + 0x001a; m_current_value = m_value_copy; + pulse_clock(1); break; case 5: m_address = 0x0042 + ((m_instruction->IR & 0x03c0)>>4); + pulse_clock(1); break; case 6: PC = m_current_value & 0xfffe; set_status_bit(ST_X, true); - n = 0; break; } m_instruction->state++; - pulse_clock(n); } /* diff --git a/src/emu/cpu/tms9900/tms9995.h b/src/emu/cpu/tms9900/tms9995.h index f18b81ccf3d..5b2abedb2ea 100644 --- a/src/emu/cpu/tms9900/tms9995.h +++ b/src/emu/cpu/tms9900/tms9995.h @@ -174,6 +174,7 @@ private: bool m_mid_active; int m_decrementer_clkdiv; + bool m_servicing_interrupt; // Flag field int m_int_pending; |