summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/tms9900/tms9900.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/tms9900/tms9900.cpp')
-rw-r--r--src/devices/cpu/tms9900/tms9900.cpp71
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);