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.cpp87
1 files changed, 47 insertions, 40 deletions
diff --git a/src/devices/cpu/tms9900/tms9900.cpp b/src/devices/cpu/tms9900/tms9900.cpp
index 8f092a3159d..840fd5d631a 100644
--- a/src/devices/cpu/tms9900/tms9900.cpp
+++ b/src/devices/cpu/tms9900/tms9900.cpp
@@ -182,11 +182,11 @@ tms99xx_device::tms99xx_device(const machine_config &mconfig, device_type type,
: cpu_device(mconfig, type, tag, owner, clock),
m_program_config("program", ENDIANNESS_BIG, data_width, prg_addr_bits),
m_setoffset_config("setoffset", ENDIANNESS_BIG, data_width, prg_addr_bits),
- m_io_config("cru", ENDIANNESS_BIG, 8, cru_addr_bits),
+ 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((1<<cru_addr_bits)-1),
+ m_cruaddr_mask((2<<cru_addr_bits)-2),
m_clock_out_line(*this),
m_wait_line(*this),
m_holda_line(*this),
@@ -1625,67 +1625,70 @@ void tms99xx_device::register_write()
idempotent (i.e. they must not change the state of the queried device).
Read returns the number of consecutive CRU bits, with increasing CRU address
- from the least significant to the most significant bit; right-aligned
+ from the least significant to the most significant bit; right-aligned (in
+ other words, little-endian as opposed to the big-endian order of memory words).
There seems to be no handling of wait states during CRU operations on the
TMS9900. The TMS9995, in contrast, respects wait states during the transmission
of each single bit.
+ The current emulation of the CRU space involves a 1-bit address shift,
+ reflecting the one-to-one correspondence between CRU bits and words (not
+ bytes) in the lower part of the memory space. (On the TMS9980A and TMS9995,
+ CRUOUT is multiplexed with the least significant address line.) Thus, what
+ TI's documentation calls the software address (the R12 base value plus the
+ bit offset multiplied by 2) is used in address maps and CPU-side operations.
+ MAME's memory architecture automatically translates these to right-justified
+ hardware addresses in the process of decoding offsets for read/write handlers,
+ which is more typical of what peripheral devices expect. (Note also that
+ address spaces do not support data widths narrower than 8 bits, so these
+ handlers must specify 8-bit types despite only one bit being useful.)
+
Usage of this method:
CRU write: First bit is at rightmost position of m_value.
*/
void tms99xx_device::cru_input_operation()
{
- int value, value1;
- int offset, location;
-
- location = (m_cru_address >> 4) & (m_cruaddr_mask>>3);
- offset = (m_cru_address>>1) & 0x07;
+ offs_t cruaddr = m_cru_address & m_cruaddr_mask;
+ uint16_t value = 0;
- // Read 8 bits (containing the desired bits)
- value = m_cru->read_byte(location);
-
- if ((offset + m_count) > 8) // spans two 8 bit cluster
+ for (int i = 0; i < m_count; i++)
{
- // Read next 8 bits
- location = (location + 1) & (m_cruaddr_mask>>3);
- value1 = m_cru->read_byte(location);
- value |= (value1 << 8);
+ // Poll one bit at a time
+ bool cruin = BIT(m_cru->read_byte(cruaddr), 0);
+ if (cruin)
+ value |= 1 << i;
- if ((offset + m_count) > 16) // spans three 8 bit cluster
- {
- // Read next 8 bits
- location = (location + 1) & (m_cruaddr_mask>>3);
- value1 = m_cru->read_byte(location);
- value |= (value1 << 16);
- }
- }
+ if (TRACE_CRU) logerror("CRU input operation, address %04x, value %d\n", cruaddr, cruin ? 1 : 0);
- // On each machine cycle (2 clocks) only one CRU bit is transmitted
- pulse_clock(m_count<<1);
+ // Increment the CRU address
+ cruaddr = (cruaddr + 2) & m_cruaddr_mask;
- // Shift back the bits so that the first bit is at the rightmost place
- m_value = (value >> offset);
+ // On each machine cycle (2 clocks) only one CRU bit is transmitted
+ pulse_clock(2);
+ }
- // Mask out what we want
- m_value &= (0x0000ffff >> (16-m_count));
+ m_value = value;
}
void tms99xx_device::cru_output_operation()
{
- int value;
- int location;
- location = (m_cru_address >> 1) & m_cruaddr_mask;
- value = m_value;
+ offs_t cruaddr = m_cru_address & m_cruaddr_mask;
+ uint16_t value = m_value;
// Write m_count bits from cru_address
- for (int i=0; i < m_count; i++)
+ for (int i = 0; i < m_count; i++)
{
- if (TRACE_CRU) logerror("CRU output operation, address %04x, value %d\n", location<<1, value & 0x01);
- m_cru->write_byte(location, (value & 0x01));
+ if (TRACE_CRU) logerror("CRU output operation, address %04x, value %d\n", cruaddr, BIT(value, 0));
+
+ // Write one bit at a time
+ m_cru->write_byte(cruaddr, BIT(value, 0));
value >>= 1;
- location = (location + 1) & m_cruaddr_mask;
+
+ // Increment the CRU address
+ cruaddr = (cruaddr + 2) & m_cruaddr_mask;
+
pulse_clock(2);
}
}
@@ -2164,6 +2167,7 @@ void tms99xx_device::alu_clr_swpb()
bool setstatus = true;
bool check_ov = true;
+ bool check_c = true;
switch (m_command)
{
@@ -2181,6 +2185,7 @@ void tms99xx_device::alu_clr_swpb()
// LAE
dest_new = ~src_val & 0xffff;
check_ov = false;
+ check_c = false;
break;
case NEG:
// LAECO
@@ -2223,7 +2228,7 @@ void tms99xx_device::alu_clr_swpb()
if (setstatus)
{
if (check_ov) set_status_bit(ST_OV, ((src_val & 0x8000)==sign) && ((dest_new & 0x8000)!=sign));
- set_status_bit(ST_C, (dest_new & 0x10000) != 0);
+ if (check_c) set_status_bit(ST_C, (dest_new & 0x10000) != 0);
m_current_value = dest_new & 0xffff;
compare_and_set_lae(m_current_value, 0);
}
@@ -2515,6 +2520,7 @@ void tms99xx_device::alu_shift()
uint16_t sign = 0;
uint32_t value;
int count;
+ bool check_ov = false;
switch (m_state)
{
@@ -2572,6 +2578,7 @@ void tms99xx_device::alu_shift()
case SLA:
carry = ((value & 0x8000)!=0);
value <<= 1;
+ check_ov = true;
if (carry != ((value&0x8000)!=0)) overflow = true;
break;
case SRC:
@@ -2584,7 +2591,7 @@ void tms99xx_device::alu_shift()
m_current_value = value & 0xffff;
set_status_bit(ST_C, carry);
- set_status_bit(ST_OV, overflow);
+ if (check_ov) set_status_bit(ST_OV, overflow); // only SLA
compare_and_set_lae(m_current_value, 0);
m_address = m_address_saved; // Register address
if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value);