diff options
author | 2019-03-25 23:13:40 +0100 | |
---|---|---|
committer | 2019-03-25 23:13:40 +0100 | |
commit | b380514764cf857469bae61c11143a19f79a74c5 (patch) | |
tree | 63c8012e262618f08a332da31dd714281aa2c5ed /src/devices/cpu/tms9900 | |
parent | c24473ddff715ecec2e258a6eb38960cf8c8e98e (diff) |
Revert "conflict resolution (nw)"
This reverts commit c24473ddff715ecec2e258a6eb38960cf8c8e98e, reversing
changes made to 009cba4fb8102102168ef32870892438327f3705.
Diffstat (limited to 'src/devices/cpu/tms9900')
-rw-r--r-- | src/devices/cpu/tms9900/tms9900.cpp | 87 | ||||
-rw-r--r-- | src/devices/cpu/tms9900/tms9995.cpp | 108 | ||||
-rw-r--r-- | src/devices/cpu/tms9900/tms9995.h | 2 |
3 files changed, 107 insertions, 90 deletions
diff --git a/src/devices/cpu/tms9900/tms9900.cpp b/src/devices/cpu/tms9900/tms9900.cpp index 840fd5d631a..8f092a3159d 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_LITTLE, 8, cru_addr_bits + 1, 1), + m_io_config("cru", ENDIANNESS_BIG, 8, cru_addr_bits), m_prgspace(nullptr), m_cru(nullptr), m_prgaddr_mask((1<<prg_addr_bits)-1), - m_cruaddr_mask((2<<cru_addr_bits)-2), + m_cruaddr_mask((1<<cru_addr_bits)-1), m_clock_out_line(*this), m_wait_line(*this), m_holda_line(*this), @@ -1625,70 +1625,67 @@ 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 (in - other words, little-endian as opposed to the big-endian order of memory words). + from the least significant to the most significant bit; right-aligned 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() { - offs_t cruaddr = m_cru_address & m_cruaddr_mask; - uint16_t value = 0; + int value, value1; + int offset, location; - for (int i = 0; i < m_count; i++) - { - // Poll one bit at a time - bool cruin = BIT(m_cru->read_byte(cruaddr), 0); - if (cruin) - value |= 1 << i; + location = (m_cru_address >> 4) & (m_cruaddr_mask>>3); + offset = (m_cru_address>>1) & 0x07; - if (TRACE_CRU) logerror("CRU input operation, address %04x, value %d\n", cruaddr, cruin ? 1 : 0); + // Read 8 bits (containing the desired bits) + value = m_cru->read_byte(location); - // Increment the CRU address - cruaddr = (cruaddr + 2) & m_cruaddr_mask; + if ((offset + m_count) > 8) // spans two 8 bit cluster + { + // Read next 8 bits + location = (location + 1) & (m_cruaddr_mask>>3); + value1 = m_cru->read_byte(location); + value |= (value1 << 8); - // On each machine cycle (2 clocks) only one CRU bit is transmitted - pulse_clock(2); + 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); + } } - m_value = value; + // On each machine cycle (2 clocks) only one CRU bit is transmitted + pulse_clock(m_count<<1); + + // Shift back the bits so that the first bit is at the rightmost place + m_value = (value >> offset); + + // Mask out what we want + m_value &= (0x0000ffff >> (16-m_count)); } void tms99xx_device::cru_output_operation() { - offs_t cruaddr = m_cru_address & m_cruaddr_mask; - uint16_t value = m_value; + int value; + int location; + location = (m_cru_address >> 1) & m_cruaddr_mask; + 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", cruaddr, BIT(value, 0)); - - // Write one bit at a time - m_cru->write_byte(cruaddr, BIT(value, 0)); + if (TRACE_CRU) logerror("CRU output operation, address %04x, value %d\n", location<<1, value & 0x01); + m_cru->write_byte(location, (value & 0x01)); value >>= 1; - - // Increment the CRU address - cruaddr = (cruaddr + 2) & m_cruaddr_mask; - + location = (location + 1) & m_cruaddr_mask; pulse_clock(2); } } @@ -2167,7 +2164,6 @@ void tms99xx_device::alu_clr_swpb() bool setstatus = true; bool check_ov = true; - bool check_c = true; switch (m_command) { @@ -2185,7 +2181,6 @@ void tms99xx_device::alu_clr_swpb() // LAE dest_new = ~src_val & 0xffff; check_ov = false; - check_c = false; break; case NEG: // LAECO @@ -2228,7 +2223,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)); - 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); } @@ -2520,7 +2515,6 @@ void tms99xx_device::alu_shift() uint16_t sign = 0; uint32_t value; int count; - bool check_ov = false; switch (m_state) { @@ -2578,7 +2572,6 @@ 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: @@ -2591,7 +2584,7 @@ void tms99xx_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 if (TRACE_STATUS) logerror("ST = %04x (val=%04x)\n", ST, m_current_value); 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); diff --git a/src/devices/cpu/tms9900/tms9995.h b/src/devices/cpu/tms9900/tms9995.h index 531e5208a41..72dfc2960a1 100644 --- a/src/devices/cpu/tms9900/tms9995.h +++ b/src/devices/cpu/tms9900/tms9995.h @@ -245,6 +245,8 @@ private: uint16_t m_cru_address; uint16_t m_cru_value; bool m_cru_first_read; + int m_cru_bits_left; + uint32_t m_cru_read; // CPU-internal CRU flags bool m_flag[16]; |