summaryrefslogtreecommitdiffstatshomepage
path: root/src/devices/cpu/tms9900/tms9995.cpp
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2019-03-26 11:13:37 +1100
committer Vas Crabb <vas@vastheman.com>2019-03-26 11:13:37 +1100
commit97b67170277437131adf6ed4d60139c172529e4f (patch)
tree7a5cbf608f191075f1612b1af15832c206a3fe2d /src/devices/cpu/tms9900/tms9995.cpp
parentb380514764cf857469bae61c11143a19f79a74c5 (diff)
(nw) Clean up the mess on master
This effectively reverts b380514764cf857469bae61c11143a19f79a74c5 and c24473ddff715ecec2e258a6eb38960cf8c8e98e, restoring the state at 598cd5227223c3b04ca31f0dbc1981256d9ea3ff. Before pushing, please check that what you're about to push is sane. Check your local commit log and ensure there isn't anything out-of-place before pushing to mainline. When things like this happen, it wastes everyone's time. I really don't need this in a week when real work™ is busting my balls and I'm behind where I want to be with preparing for MAME release.
Diffstat (limited to 'src/devices/cpu/tms9900/tms9995.cpp')
-rw-r--r--src/devices/cpu/tms9900/tms9995.cpp108
1 files changed, 43 insertions, 65 deletions
diff --git a/src/devices/cpu/tms9900/tms9995.cpp b/src/devices/cpu/tms9900/tms9995.cpp
index c83f74ac073..09509f4623e 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_BIG, 8, 16),
+ m_io_config("cru", ENDIANNESS_LITTLE, 8, 16, 1),
m_prgspace(nullptr),
m_sospace(nullptr),
m_cru(nullptr),
@@ -288,8 +288,6 @@ 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));
@@ -1510,10 +1508,13 @@ 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)
{
- if (m_flag[2] && intmask >= 1) m_int_pending |= PENDING_LEVEL1;
+ // 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_int_overflow && intmask >= 2) m_int_pending |= PENDING_OVERFLOW;
if (m_flag[3] && intmask >= 3) m_int_pending |= PENDING_DECR;
- if (m_flag[4] && intmask >= 4) m_int_pending |= PENDING_LEVEL4;
+ if ((m_int4_active || m_flag[4]) && intmask >= 4) m_int_pending |= PENDING_LEVEL4;
}
if (m_int_pending!=0)
@@ -1562,7 +1563,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
@@ -1575,7 +1576,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");
}
}
@@ -1688,7 +1689,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
@@ -1698,7 +1699,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
{
@@ -1706,9 +1707,12 @@ void tms9995_device::service_interrupt()
{
vectorpos = 0x0004;
m_int_pending &= ~PENDING_LEVEL1;
- if (!m_int1_active) m_flag[2] = false;
+ // 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;
m_intmask = 0;
- LOGMASKED(LOG_INT, "***** INT1 pending\n");
+ LOGMASKED(LOG_INT, "** INT1 pending\n");
}
else
{
@@ -1717,7 +1721,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
{
@@ -1727,15 +1731,16 @@ 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;
- if (!m_int4_active) m_flag[4] = false;
- LOGMASKED(LOG_INT, "***** INT4 pending\n");
+ // See above for clearing the latch
+ m_flag[4] = false;
+ LOGMASKED(LOG_INT, "** INT4 pending\n");
}
}
}
@@ -1743,7 +1748,7 @@ void tms9995_device::service_interrupt()
}
}
- LOGMASKED(LOG_INT, "********* triggered an interrupt with vector %04x/%04x\n", vectorpos, vectorpos+2);
+ LOGMASKED(LOG_INTD, "*** triggered an interrupt with vector %04x/%04x\n", vectorpos, vectorpos+2);
// just for debugging purposes
if (!m_reset) m_log_interrupt = true;
@@ -2080,8 +2085,7 @@ 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 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
+ we do iterations for each bit, checking every time for the READY line
in the main loop.
(write)
@@ -2092,8 +2096,8 @@ void tms9995_device::return_with_address_copy()
*/
-#define CRUREADMASK 0x0fff
-#define CRUWRITEMASK 0x7fff
+#define CRUREADMASK 0xfffe
+#define CRUWRITEMASK 0xfffe
void tms9995_device::cru_output_operation()
{
@@ -2129,7 +2133,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 >> 1)& CRUWRITEMASK, (m_cru_value & 0x01));
+ m_cru->write_byte(m_cru_address & CRUWRITEMASK, (m_cru_value & 0x01));
m_cru_value >>= 1;
m_cru_address = (m_cru_address + 2) & 0xfffe;
m_count--;
@@ -2150,55 +2154,29 @@ void tms9995_device::cru_output_operation()
void tms9995_device::cru_input_operation()
{
- 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)
+ if (m_cru_first_read)
{
- // 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);
+ m_cru_value = 0;
+ m_cru_first_read = false;
+ m_pass = m_count;
}
- crubit = (m_cru_read & 0x8000);
+ // Read a single CRU bit
+ bool crubit = BIT(m_cru->read_byte(m_cru_address & CRUREADMASK), 0);
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? 0x8000 : 0x0000;
+ crubit = m_mid_flag;
m_check_ready = false;
}
else
{
if ((m_cru_address & 0xffe0)==0x1ee0)
{
- crubit = (m_flag[(m_cru_address>>1)&0x000f]==true)? 0x8000 : 0x0000;
+ crubit = m_flag[(m_cru_address>>1)&0x000f];
m_check_ready = false;
}
else
@@ -2207,18 +2185,14 @@ void tms9995_device::cru_input_operation()
}
}
- LOGMASKED(LOG_CRU, "CRU input operation, address %04x, value %d\n", m_cru_address, (crubit & 0x8000)>>15);
+ LOGMASKED(LOG_CRU, "CRU input operation, address %04x, value %d\n", m_cru_address, crubit ? 1 : 0);
- m_cru_value |= crubit;
+ if (crubit)
+ m_cru_value |= 0x8000;
m_cru_address = (m_cru_address + 2) & 0xfffe;
- m_cru_bits_left--;
- if (m_pass > 1)
- {
- m_cru_read >>= 1;
- }
- else
+ if (m_pass == 1)
{
// This is the final shift. For both byte and word length transfers,
// the first bit is always m_cru_value & 0x0001.
@@ -3116,6 +3090,7 @@ void tms9995_device::alu_shift()
uint16_t sign = 0;
uint32_t value;
int count;
+ bool check_ov = false;
switch (m_inst_state)
{
@@ -3164,6 +3139,7 @@ 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:
@@ -3176,7 +3152,7 @@ void tms9995_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
LOGMASKED(LOG_STATUS, "ST = %04x (val=%04x)\n", ST, m_current_value);
@@ -3194,6 +3170,7 @@ 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)
{
@@ -3244,6 +3221,7 @@ void tms9995_device::alu_single_arithm()
// LAE
dest_new = ~src_val & 0xffff;
check_ov = false;
+ check_c = false;
break;
case NEG:
// LAECO
@@ -3271,7 +3249,7 @@ void tms9995_device::alu_single_arithm()
}
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);