diff options
Diffstat (limited to 'src/devices/cpu/tms9900/tms9900.cpp')
-rw-r--r-- | src/devices/cpu/tms9900/tms9900.cpp | 71 |
1 files changed, 43 insertions, 28 deletions
diff --git a/src/devices/cpu/tms9900/tms9900.cpp b/src/devices/cpu/tms9900/tms9900.cpp index de0621bb6bd..c2ef748a925 100644 --- a/src/devices/cpu/tms9900/tms9900.cpp +++ b/src/devices/cpu/tms9900/tms9900.cpp @@ -159,12 +159,12 @@ enum tms99xx_device::tms99xx_device(const machine_config &mconfig, device_type type, const char *tag, int data_width, int prg_addr_bits, int cru_addr_bits, device_t *owner, uint32_t clock) : cpu_device(mconfig, type, tag, owner, clock), m_program_config("program", ENDIANNESS_BIG, data_width, prg_addr_bits), - m_setaddress_config("setaddress", ENDIANNESS_BIG, prg_addr_bits, prg_addr_bits), // data = address + m_setaddress_config("setaddress", ENDIANNESS_BIG, data_width, prg_addr_bits), // choose the same width as the program space m_io_config("cru", ENDIANNESS_LITTLE, 8, cru_addr_bits + 1, 1), m_prgspace(nullptr), m_cru(nullptr), - m_prgaddr_mask((1<<prg_addr_bits)-1), - m_cruaddr_mask((2<<cru_addr_bits)-2), + m_prgaddr_mask((1<<prg_addr_bits)-2), // fffe for 16 bits, 3ffe for 14 bits (only even addresses) + m_cruaddr_mask((2<<cru_addr_bits)-2), // Address is shifted left by one m_iaq(false), m_clock_out_line(*this), m_wait_line(*this), @@ -328,10 +328,10 @@ void tms99xx_device::state_import(const device_state_entry &entry) // bits of the STATUS register break; case TMS9900_PC: - PC = (uint16_t)(m_state_any & m_prgaddr_mask & 0xfffe); + PC = (uint16_t)(m_state_any & m_prgaddr_mask); break; case TMS9900_WP: - WP = (uint16_t)(m_state_any & m_prgaddr_mask & 0xfffe); + WP = (uint16_t)(m_state_any & m_prgaddr_mask); break; case TMS9900_STATUS: ST = (uint16_t)m_state_any; @@ -404,7 +404,7 @@ uint16_t tms99xx_device::read_workspace_register_debug(int reg) { int temp = m_icount; auto dis = machine().disable_side_effects(); - uint16_t value = m_prgspace->read_word((WP+(reg<<1)) & m_prgaddr_mask & 0xfffe); + uint16_t value = m_prgspace->read_word((WP+(reg<<1)) & m_prgaddr_mask); m_icount = temp; return value; } @@ -413,10 +413,26 @@ void tms99xx_device::write_workspace_register_debug(int reg, uint16_t data) { int temp = m_icount; auto dis = machine().disable_side_effects(); - m_prgspace->write_word((WP+(reg<<1)) & m_prgaddr_mask & 0xfffe, data); + m_prgspace->write_word((WP+(reg<<1)) & m_prgaddr_mask, data); m_icount = temp; } +/* + The setaddress space is used to implement a split-phase memory access + where the address bus is first set, then the CPU samples the READY line, + (when low, enters wait states,) then the CPU reads the address bus. For + writing, setting the address and setting the data bus is done in direct + succession. + + It is an optional feature, where drivers may connect to this space to + make use of it, or to completely ignore it when there is no need for + waitstate control. + + In order to allow for using address maps, the setaddress space shows the + same widths as the normal program space. Its values are the levels of + certains lines that are set or reset during the memory access, in + particular DBIN and IAQ. +*/ device_memory_interface::space_config_vector tms99xx_device::memory_space_config() const { if (has_configured_map(AS_SETADDRESS)) @@ -1511,7 +1527,7 @@ void tms99xx_device::acquire_instruction() LOGMASKED(LOG_EXEC, "%04x\n", PC); debugger_instruction_hook(PC); - PC = (PC + 2) & 0xfffe & m_prgaddr_mask; + PC = (PC + 2) & m_prgaddr_mask; // IAQ will be cleared in the main loop } } @@ -1530,8 +1546,7 @@ void tms99xx_device::mem_read() { LOGMASKED(LOG_ADDRESSBUS, "set address (r) %04x\n", m_address); if (m_setaddr) - // Note that the bus lines form a pseudo address that is shifted right by one in the handler - m_setaddr->write_word((TMS99xx_BUS_DBIN | (m_iaq? TMS99xx_BUS_IAQ : 0))<<1, m_address & m_prgaddr_mask & 0xfffe); + m_setaddr->write_word(m_address & m_prgaddr_mask, (TMS99xx_BUS_DBIN | (m_iaq? TMS99xx_BUS_IAQ : 0))); m_check_ready = true; m_mem_phase = 2; m_pass = 2; @@ -1541,7 +1556,7 @@ void tms99xx_device::mem_read() else { // Second phase (after READY was raised again) - m_current_value = m_prgspace->read_word(m_address & m_prgaddr_mask & 0xfffe); + m_current_value = m_prgspace->read_word(m_address & m_prgaddr_mask); pulse_clock(1); m_mem_phase = 1; // reset to phase 1 LOGMASKED(LOG_MEM, "mem r %04x -> %04x\n", m_address, m_current_value); @@ -1555,9 +1570,9 @@ void tms99xx_device::mem_write() LOGMASKED(LOG_ADDRESSBUS, "set address (w) %04x\n", m_address); // When writing, the data bus is asserted immediately after the address bus if (m_setaddr) - m_setaddr->write_word(TMS99xx_BUS_WRITE, m_address & m_prgaddr_mask & 0xfffe); + m_setaddr->write_word(m_address & m_prgaddr_mask, TMS99xx_BUS_WRITE); LOGMASKED(LOG_MEM, "mem w %04x <- %04x\n", m_address, m_current_value); - m_prgspace->write_word(m_address & m_prgaddr_mask & 0xfffe, m_current_value); + m_prgspace->write_word(m_address & m_prgaddr_mask, m_current_value); m_check_ready = true; m_mem_phase = 2; m_pass = 2; @@ -1595,7 +1610,7 @@ void tms99xx_device::register_write() { // This will be called twice; m_pass is set by the embedded mem_write uint16_t addr_save = m_address; - m_address = (WP + (m_regnumber<<1)) & m_prgaddr_mask & 0xfffe; + m_address = (WP + (m_regnumber<<1)) & m_prgaddr_mask; mem_write(); m_address = addr_save; } @@ -1820,7 +1835,7 @@ void tms99xx_device::alu_pcaddr_advance() { // Set PC as new read address, increase by 2 m_address = PC; - PC = (PC + 2) & 0xfffe & m_prgaddr_mask; + PC = (PC + 2) & m_prgaddr_mask; pulse_clock(2); } @@ -1836,7 +1851,7 @@ void tms99xx_device::alu_imm() m_value_copy = m_current_value; m_address_copy = m_address; m_address = PC; - PC = (PC + 2) & 0xfffe & m_prgaddr_mask; + PC = (PC + 2) & m_prgaddr_mask; pulse_clock(2); } @@ -2118,7 +2133,7 @@ void tms99xx_device::alu_xop() break; case 1: m_value_copy = WP; // save the old WP - WP = m_current_value & m_prgaddr_mask & 0xfffe; // the new WP has been read in the previous microoperation + WP = m_current_value & m_prgaddr_mask; // the new WP has been read in the previous microoperation m_current_value = m_address_saved; // we saved the address of the source operand; retrieve it m_address = WP + 0x0016; // Next register is R11 break; @@ -2139,7 +2154,7 @@ void tms99xx_device::alu_xop() set_status_bit(ST_X, true); break; case 6: - PC = m_current_value & m_prgaddr_mask & 0xfffe; + PC = m_current_value & m_prgaddr_mask; break; } pulse_clock(2); @@ -2264,7 +2279,7 @@ void tms99xx_device::alu_b() // retrieves the value at 0xa000, but in fact it will load the PC // with the address 0xa000 m_current_value = PC; - PC = m_address & m_prgaddr_mask & 0xfffe; + PC = m_address & m_prgaddr_mask; m_address = WP + 22; pulse_clock(2); } @@ -2275,7 +2290,7 @@ void tms99xx_device::alu_blwp() { case 0: m_value_copy = WP; - WP = m_current_value & m_prgaddr_mask & 0xfffe; // set new WP (*m_destination) + WP = m_current_value & m_prgaddr_mask; // set new WP (*m_destination) m_address_saved = (m_address + 2) & m_prgaddr_mask; // Save the location of the WP m_address = WP + 30; m_current_value = ST; // get status register @@ -2292,7 +2307,7 @@ void tms99xx_device::alu_blwp() m_address = m_address_saved; // point to PC component of branch vector break; case 4: - PC = m_current_value & m_prgaddr_mask & 0xfffe; + PC = m_current_value & m_prgaddr_mask; LOGMASKED(LOG_CONTEXT, "Context switch (blwp): WP=%04x, PC=%04x, ST=%04x\n", WP, PC, ST); break; } @@ -2492,7 +2507,7 @@ void tms99xx_device::alu_jmp() else { displacement = (IR & 0xff); - PC = (PC + (displacement<<1)) & m_prgaddr_mask & 0xfffe; + PC = (PC + (displacement<<1)) & m_prgaddr_mask; } m_state++; pulse_clock(2); @@ -2623,7 +2638,7 @@ void tms99xx_device::alu_li() void tms99xx_device::alu_lwpi() { - WP = m_current_value & m_prgaddr_mask & 0xfffe; + WP = m_current_value & m_prgaddr_mask; pulse_clock(2); } @@ -2672,11 +2687,11 @@ void tms99xx_device::alu_rtwp() m_address -= 2; // R14 break; case 2: - PC = m_current_value & m_prgaddr_mask & 0xfffe; + PC = m_current_value & m_prgaddr_mask; m_address -= 2; // R13 break; case 3: - WP = m_current_value & m_prgaddr_mask & 0xfffe; + WP = m_current_value & m_prgaddr_mask; pulse_clock(2); // Just for debugging purposes m_log_interrupt = false; @@ -2710,7 +2725,7 @@ void tms99xx_device::alu_int() case 1: m_address_copy = m_address; m_value_copy = WP; // old WP - WP = m_current_value & m_prgaddr_mask & 0xfffe; // new WP + WP = m_current_value & m_prgaddr_mask; // new WP m_current_value = ST; m_address = (WP + 30) & m_prgaddr_mask; LOGMASKED(LOG_INTD, "interrupt service (1): Read new WP = %04x, save ST to %04x\n", WP, m_address); @@ -2726,11 +2741,11 @@ void tms99xx_device::alu_int() LOGMASKED(LOG_INTD, "interrupt service (3): Save WP to %04x\n", m_address); break; case 4: - m_address = (m_address_copy + 2) & 0xfffe & m_prgaddr_mask; + m_address = (m_address_copy + 2) & m_prgaddr_mask; LOGMASKED(LOG_INTD, "interrupt service (4): Read PC from %04x\n", m_address); break; case 5: - PC = m_current_value & m_prgaddr_mask & 0xfffe; + PC = m_current_value & m_prgaddr_mask; if (m_irq_level > 0 ) { ST = (ST & 0xfff0) | (m_irq_level - 1); |