summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/tms9900/tms9995.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/devices/cpu/tms9900/tms9995.cpp')
-rw-r--r--src/devices/cpu/tms9900/tms9995.cpp108
1 files changed, 65 insertions, 43 deletions
diff --git a/src/devices/cpu/tms9900/tms9995.cpp b/src/devices/cpu/tms9900/tms9995.cpp
index 09509f4623e..c83f74ac073 100644
--- a/src/devices/cpu/tms9900/tms9995.cpp
+++ b/src/devices/cpu/tms9900/tms9995.cpp
@@ -170,7 +170,7 @@ tms9995_device::tms9995_device(const machine_config &mconfig, device_type type,
PC_debug(0),
m_program_config("program", ENDIANNESS_BIG, 8, 16),
m_setoffset_config("setoffset", ENDIANNESS_BIG, 8, 16),
- m_io_config("cru", ENDIANNESS_LITTLE, 8, 16, 1),
+ m_io_config("cru", ENDIANNESS_BIG, 8, 16),
m_prgspace(nullptr),
m_sospace(nullptr),
m_cru(nullptr),
@@ -288,6 +288,8 @@ void tms9995_device::device_start()
save_item(NAME(m_cru_address));
save_item(NAME(m_cru_value));
save_item(NAME(m_cru_first_read));
+ save_item(NAME(m_cru_bits_left));
+ save_item(NAME(m_cru_read));
save_pointer(NAME(m_flag),16);
save_item(NAME(IR));
save_item(NAME(m_pre_IR));
@@ -1508,13 +1510,10 @@ void tms9995_device::int_prefetch_and_decode()
// If the current command is XOP or BLWP, ignore the interrupt
if (m_command != XOP && m_command != BLWP)
{
- // The actual interrupt trigger is an OR of the latch and of
- // the interrupt line (for INT1 and INT4); see [1],
- // section 2.3.2.1.3
- if ((m_int1_active || m_flag[2]) && intmask >= 1) m_int_pending |= PENDING_LEVEL1;
+ if (m_flag[2] && intmask >= 1) m_int_pending |= PENDING_LEVEL1;
if (m_int_overflow && intmask >= 2) m_int_pending |= PENDING_OVERFLOW;
if (m_flag[3] && intmask >= 3) m_int_pending |= PENDING_DECR;
- if ((m_int4_active || m_flag[4]) && intmask >= 4) m_int_pending |= PENDING_LEVEL4;
+ if (m_flag[4] && intmask >= 4) m_int_pending |= PENDING_LEVEL4;
}
if (m_int_pending!=0)
@@ -1563,7 +1562,7 @@ void tms9995_device::prefetch_and_decode()
m_value_copy = m_current_value;
if (!m_iaq_line.isnull()) m_iaq_line(ASSERT_LINE);
m_address = PC;
- LOGMASKED(LOG_DETAIL, "** Prefetching new instruction at %04x **\n", PC);
+ LOGMASKED(LOG_DETAIL, "**** Prefetching new instruction at %04x ****\n", PC);
}
word_read(); // changes m_mem_phase
@@ -1576,7 +1575,7 @@ void tms9995_device::prefetch_and_decode()
m_current_value = m_value_copy; // restore m_current_value
PC = (PC + 2) & 0xfffe; // advance PC
if (!m_iaq_line.isnull()) m_iaq_line(CLEAR_LINE);
- LOGMASKED(LOG_DETAIL, "++ Prefetch done ++\n");
+ LOGMASKED(LOG_DETAIL, "++++ Prefetch done ++++\n");
}
}
@@ -1689,7 +1688,7 @@ void tms9995_device::service_interrupt()
vectorpos = 0x0008;
m_intmask = 0x0001;
PC = (PC + 2) & 0xfffe;
- LOGMASKED(LOG_INT, "** MID pending\n");
+ LOGMASKED(LOG_INT, "***** MID pending\n");
m_mid_active = false;
}
else
@@ -1699,7 +1698,7 @@ void tms9995_device::service_interrupt()
vectorpos = 0xfffc;
m_int_pending &= ~PENDING_NMI;
m_intmask = 0;
- LOGMASKED(LOG_INT, "** NMI pending\n");
+ LOGMASKED(LOG_INT, "***** NMI pending\n");
}
else
{
@@ -1707,12 +1706,9 @@ void tms9995_device::service_interrupt()
{
vectorpos = 0x0004;
m_int_pending &= ~PENDING_LEVEL1;
- // Latches must be reset when the interrupt is serviced
- // Since the latch is edge-triggered, we should be allowed
- // to clear it right here, without considering the line state
- m_flag[2] = false;
+ if (!m_int1_active) m_flag[2] = false;
m_intmask = 0;
- LOGMASKED(LOG_INT, "** INT1 pending\n");
+ LOGMASKED(LOG_INT, "***** INT1 pending\n");
}
else
{
@@ -1721,7 +1717,7 @@ void tms9995_device::service_interrupt()
vectorpos = 0x0008;
m_int_pending &= ~PENDING_OVERFLOW;
m_intmask = 0x0001;
- LOGMASKED(LOG_INT, "** OVERFL pending\n");
+ LOGMASKED(LOG_INT, "***** OVERFL pending\n");
}
else
{
@@ -1731,16 +1727,15 @@ void tms9995_device::service_interrupt()
m_intmask = 0x0002;
m_int_pending &= ~PENDING_DECR;
m_flag[3] = false;
- LOGMASKED(LOG_DEC, "** DECR pending\n");
+ LOGMASKED(LOG_DEC, "***** DECR pending\n");
}
else
{
vectorpos = 0x0010;
m_intmask = 0x0003;
m_int_pending &= ~PENDING_LEVEL4;
- // See above for clearing the latch
- m_flag[4] = false;
- LOGMASKED(LOG_INT, "** INT4 pending\n");
+ if (!m_int4_active) m_flag[4] = false;
+ LOGMASKED(LOG_INT, "***** INT4 pending\n");
}
}
}
@@ -1748,7 +1743,7 @@ void tms9995_device::service_interrupt()
}
}
- LOGMASKED(LOG_INTD, "*** triggered an interrupt with vector %04x/%04x\n", vectorpos, vectorpos+2);
+ LOGMASKED(LOG_INT, "********* triggered an interrupt with vector %04x/%04x\n", vectorpos, vectorpos+2);
// just for debugging purposes
if (!m_reset) m_log_interrupt = true;
@@ -2085,7 +2080,8 @@ void tms9995_device::return_with_address_copy()
1FDA MID flag (only indication, does not trigger when set)
The TMS9995 allows for wait states during external CRU access. Therefore
- we do iterations for each bit, checking every time for the READY line
+ we read one block of 8 bits in one go (as given by the MESS architecture)
+ but we do iterations for each bit, checking every time for the READY line
in the main loop.
(write)
@@ -2096,8 +2092,8 @@ void tms9995_device::return_with_address_copy()
*/
-#define CRUREADMASK 0xfffe
-#define CRUWRITEMASK 0xfffe
+#define CRUREADMASK 0x0fff
+#define CRUWRITEMASK 0x7fff
void tms9995_device::cru_output_operation()
{
@@ -2133,7 +2129,7 @@ void tms9995_device::cru_output_operation()
// of the CPU. However, no wait states are generated for internal
// accesses. ([1], section 2.3.3.2)
- m_cru->write_byte(m_cru_address & CRUWRITEMASK, (m_cru_value & 0x01));
+ m_cru->write_byte((m_cru_address >> 1)& CRUWRITEMASK, (m_cru_value & 0x01));
m_cru_value >>= 1;
m_cru_address = (m_cru_address + 2) & 0xfffe;
m_count--;
@@ -2154,29 +2150,55 @@ void tms9995_device::cru_output_operation()
void tms9995_device::cru_input_operation()
{
- if (m_cru_first_read)
+ uint16_t crubit;
+ uint8_t crubyte;
+
+ // Reading is different, since MESS uses 8 bit transfers
+ // We read 8 bits in one go, then iterate another min(n-1,7) times to allow
+ // for wait states.
+
+ // read_byte for CRU delivers the first bit on the rightmost position
+
+ int offset = (m_cru_address>>1) & 0x07;
+
+ if (m_cru_first_read || m_cru_bits_left == 0)
{
- m_cru_value = 0;
- m_cru_first_read = false;
- m_pass = m_count;
+ // Read next 8 bits
+ // 00000000 0rrrrrrr r
+ // v
+ // ........ ........ X....... ........
+ //
+ crubyte = m_cru->read_byte((m_cru_address >> 4)& CRUREADMASK);
+ LOGMASKED(LOG_DETAIL, "Need to get next 8 bits (addresses %04x-%04x): %02x\n", (m_cru_address&0xfff0)+14, m_cru_address&0xfff0, crubyte);
+ m_cru_read = crubyte << 15;
+ m_cru_bits_left = 8;
+
+ if (m_cru_first_read)
+ {
+ m_cru_read >>= offset;
+ m_cru_bits_left -= offset;
+ m_cru_value = 0;
+ m_cru_first_read = false;
+ m_pass = m_count;
+ }
+ LOGMASKED(LOG_DETAIL, "adjusted value for shift: %06x\n", m_cru_read);
}
- // Read a single CRU bit
- bool crubit = BIT(m_cru->read_byte(m_cru_address & CRUREADMASK), 0);
+ crubit = (m_cru_read & 0x8000);
m_cru_value = (m_cru_value >> 1) & 0x7fff;
// During internal reading, the CRUIN line will be ignored. We emulate this
// by overwriting the bit which we got from outside. Also, READY is ignored.
if (m_cru_address == 0x1fda)
{
- crubit = m_mid_flag;
+ crubit = m_mid_flag? 0x8000 : 0x0000;
m_check_ready = false;
}
else
{
if ((m_cru_address & 0xffe0)==0x1ee0)
{
- crubit = m_flag[(m_cru_address>>1)&0x000f];
+ crubit = (m_flag[(m_cru_address>>1)&0x000f]==true)? 0x8000 : 0x0000;
m_check_ready = false;
}
else
@@ -2185,14 +2207,18 @@ void tms9995_device::cru_input_operation()
}
}
- LOGMASKED(LOG_CRU, "CRU input operation, address %04x, value %d\n", m_cru_address, crubit ? 1 : 0);
+ LOGMASKED(LOG_CRU, "CRU input operation, address %04x, value %d\n", m_cru_address, (crubit & 0x8000)>>15);
- if (crubit)
- m_cru_value |= 0x8000;
+ m_cru_value |= crubit;
m_cru_address = (m_cru_address + 2) & 0xfffe;
+ m_cru_bits_left--;
- if (m_pass == 1)
+ if (m_pass > 1)
+ {
+ m_cru_read >>= 1;
+ }
+ else
{
// This is the final shift. For both byte and word length transfers,
// the first bit is always m_cru_value & 0x0001.
@@ -3090,7 +3116,6 @@ void tms9995_device::alu_shift()
uint16_t sign = 0;
uint32_t value;
int count;
- bool check_ov = false;
switch (m_inst_state)
{
@@ -3139,7 +3164,6 @@ void tms9995_device::alu_shift()
case SLA:
carry = ((value & 0x8000)!=0);
value <<= 1;
- check_ov = true;
if (carry != ((value&0x8000)!=0)) overflow = true;
break;
case SRC:
@@ -3152,7 +3176,7 @@ void tms9995_device::alu_shift()
m_current_value = value & 0xffff;
set_status_bit(ST_C, carry);
- if (check_ov) set_status_bit(ST_OV, overflow); // only SLA
+ set_status_bit(ST_OV, overflow);
compare_and_set_lae(m_current_value, 0);
m_address = m_address_saved; // Register address
LOGMASKED(LOG_STATUS, "ST = %04x (val=%04x)\n", ST, m_current_value);
@@ -3170,7 +3194,6 @@ void tms9995_device::alu_single_arithm()
uint32_t src_val = m_current_value & 0x0000ffff;
uint16_t sign = 0;
bool check_ov = true;
- bool check_c = true;
switch (m_command)
{
@@ -3221,7 +3244,6 @@ void tms9995_device::alu_single_arithm()
// LAE
dest_new = ~src_val & 0xffff;
check_ov = false;
- check_c = false;
break;
case NEG:
// LAECO
@@ -3249,7 +3271,7 @@ void tms9995_device::alu_single_arithm()
}
if (check_ov) set_status_bit(ST_OV, ((src_val & 0x8000)==sign) && ((dest_new & 0x8000)!=sign));
- if (check_c) set_status_bit(ST_C, (dest_new & 0x10000) != 0);
+ set_status_bit(ST_C, (dest_new & 0x10000) != 0);
m_current_value = dest_new & 0xffff;
compare_and_set_lae(m_current_value, 0);