diff options
Diffstat (limited to 'src/devices/cpu/tms34010/tms34010.cpp')
-rw-r--r-- | src/devices/cpu/tms34010/tms34010.cpp | 255 |
1 files changed, 177 insertions, 78 deletions
diff --git a/src/devices/cpu/tms34010/tms34010.cpp b/src/devices/cpu/tms34010/tms34010.cpp index 79e9cf42fb6..cc2d2481a0c 100644 --- a/src/devices/cpu/tms34010/tms34010.cpp +++ b/src/devices/cpu/tms34010/tms34010.cpp @@ -16,10 +16,8 @@ #include "tms34010.h" #include "34010dsm.h" -#include "debugger.h" #include "screen.h" -#define LOG_GENERAL (1U << 0) #define LOG_CONTROL_REGS (1U << 1) #define LOG_GRAPHICS_OPS (1U << 2) @@ -59,10 +57,10 @@ DEFINE_DEVICE_TYPE(TMS34020, tms34020_device, "tms34020", "Texas Instruments TMS GLOBAL VARIABLES ***************************************************************************/ -tms340x0_device::tms340x0_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_regs_map) +tms340x0_device::tms340x0_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, address_map_constructor internal_regs_map, bool is_34020) : cpu_device(mconfig, type, tag, owner, clock) , device_video_interface(mconfig, *this) - , m_program_config("program", ENDIANNESS_LITTLE, 16, 32, 3, internal_regs_map) + , m_program_config("program", ENDIANNESS_LITTLE, is_34020 ? 32 : 16, 32, 3, internal_regs_map) , m_pc(0) , m_ppc(0) , m_st(0) @@ -76,35 +74,35 @@ tms340x0_device::tms340x0_device(const machine_config &mconfig, device_type type , m_convmp(0) , m_gfxcycles(0) , m_pixelshift(0) - , m_is_34020(0) + , m_is_34020(is_34020) , m_reset_deferred(false) , m_halt_on_reset(false) , m_hblank_stable(0) , m_external_host_access(0) , m_executing(0) - , m_program(nullptr) - , m_cache(nullptr) , m_pixclock(0) , m_pixperclock(0) , m_scantimer(nullptr) , m_icount(0) + , m_scanline_ind16_cb(*this) + , m_scanline_rgb32_cb(*this) , m_output_int_cb(*this) , m_ioreg_pre_write_cb(*this) + , m_to_shiftreg_cb(*this) + , m_from_shiftreg_cb(*this) { } tms34010_device::tms34010_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : tms340x0_device(mconfig, TMS34010, tag, owner, clock, address_map_constructor(FUNC(tms34010_device::internal_regs_map), this)) + : tms340x0_device(mconfig, TMS34010, tag, owner, clock, address_map_constructor(FUNC(tms34010_device::internal_regs_map), this), false) { - m_is_34020 = 0; } tms34020_device::tms34020_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) - : tms340x0_device(mconfig, TMS34020, tag, owner, clock, address_map_constructor(FUNC(tms34020_device::internal_regs_map), this)) + : tms340x0_device(mconfig, TMS34020, tag, owner, clock, address_map_constructor(FUNC(tms34020_device::internal_regs_map), this), true) { - m_is_34020 = 1; } device_memory_interface::space_config_vector tms340x0_device::memory_space_config() const @@ -187,10 +185,13 @@ device_memory_interface::space_config_vector tms340x0_device::memory_space_confi #define OFFSET() BREG(4) #define WSTART_X() BREG_X(5) #define WSTART_Y() BREG_Y(5) +#define WSTART_XY() BREG_XY(5) #define WEND_X() BREG_X(6) #define WEND_Y() BREG_Y(6) +#define WEND_XY() BREG_XY(6) #define DYDX_X() BREG_X(7) #define DYDX_Y() BREG_Y(7) +#define DYDX_XY() BREG_XY(7) #define COLOR0() BREG(8) #define COLOR1() BREG(9) #define COUNT() BREG(10) @@ -225,38 +226,121 @@ inline void tms340x0_device::RESET_ST() } /* shortcuts for reading opcodes */ -inline uint32_t tms340x0_device::ROPCODE() +uint16_t tms34010_device::ROPCODE() { uint32_t pc = m_pc; m_pc += 2 << 3; - return m_cache->read_word(pc); + return m_cache.read_word(pc); } -inline int16_t tms340x0_device::PARAM_WORD() +uint16_t tms34020_device::ROPCODE() { uint32_t pc = m_pc; m_pc += 2 << 3; - return m_cache->read_word(pc); + return m_cache.read_word(pc); } -inline int32_t tms340x0_device::PARAM_LONG() +int16_t tms34010_device::PARAM_WORD() +{ + uint32_t pc = m_pc; + m_pc += 2 << 3; + return m_cache.read_word(pc); +} + +int16_t tms34020_device::PARAM_WORD() +{ + uint32_t pc = m_pc; + m_pc += 2 << 3; + return m_cache.read_word(pc); +} + +int32_t tms34010_device::PARAM_LONG() +{ + uint32_t pc = m_pc; + m_pc += 4 << 3; + return (uint16_t)m_cache.read_word(pc) | (m_cache.read_word(pc + 16) << 16); +} + +int32_t tms34020_device::PARAM_LONG() { uint32_t pc = m_pc; m_pc += 4 << 3; - return (uint16_t)m_cache->read_word(pc) | (m_cache->read_word(pc + 16) << 16); + return m_cache.read_dword_unaligned(pc); } -inline int16_t tms340x0_device::PARAM_WORD_NO_INC() +int16_t tms34010_device::PARAM_WORD_NO_INC() { - return m_cache->read_word(m_pc); + return m_cache.read_word(m_pc); } -inline int32_t tms340x0_device::PARAM_LONG_NO_INC() +int16_t tms34020_device::PARAM_WORD_NO_INC() +{ + return m_cache.read_word(m_pc); +} + +int32_t tms34010_device::PARAM_LONG_NO_INC() { uint32_t pc = m_pc; - return (uint16_t)m_cache->read_word(pc) | (m_cache->read_word(pc + 16) << 16); + return (uint16_t)m_cache.read_word(pc) | (m_cache.read_word(pc + 16) << 16); +} + +int32_t tms34020_device::PARAM_LONG_NO_INC() +{ + return m_cache.read_dword_unaligned(m_pc); +} + +uint32_t tms34010_device::TMS34010_RDMEM_WORD(offs_t A) +{ + return m_program.read_word(A); +} + +uint32_t tms34020_device::TMS34010_RDMEM_WORD(offs_t A) +{ + return m_program.read_word(A); +} + +uint32_t tms34010_device::TMS34010_RDMEM_DWORD(offs_t A) +{ + uint32_t result = m_program.read_word(A); + return result | (m_program.read_word(A+16)<<16); +} + +uint32_t tms34020_device::TMS34010_RDMEM_DWORD(offs_t A) +{ + return m_program.read_dword_unaligned(A); +} + +void tms34010_device::TMS34010_WRMEM_WORD(offs_t A, uint32_t V) +{ + m_program.write_word(A,V); +} + +void tms34020_device::TMS34010_WRMEM_WORD(offs_t A, uint32_t V) +{ + if (BIT(A, 4)) + m_program.write_dword(A-16,(V<<16)|(V>>16),0xffff0000); + else + m_program.write_dword(A,V,0x0000ffff); +} + +void tms34010_device::TMS34010_WRMEM_DWORD(offs_t A, uint32_t V) +{ + m_program.write_word(A,V); + m_program.write_word(A+16,V>>16); +} + +void tms34020_device::TMS34010_WRMEM_DWORD(offs_t A, uint32_t V) +{ + if (BIT(A, 4)) + { + m_program.write_dword(A-16,(V<<16)|(V>>16),0xffff0000); + m_program.write_dword(A+16,(V<<16)|(V>>16),0x0000ffff); + } + else + m_program.write_dword(A,V); } + /* read memory byte */ inline uint32_t tms340x0_device::RBYTE(offs_t offset) { @@ -326,7 +410,7 @@ uint32_t tms340x0_device::read_pixel_32(offs_t offset) uint32_t tms340x0_device::read_pixel_shiftreg(offs_t offset) { if (!m_to_shiftreg_cb.isnull()) - m_to_shiftreg_cb(*m_program, offset, &m_shiftreg[0]); + m_to_shiftreg_cb(offset, &m_shiftreg[0]); else fatalerror("To ShiftReg function not set. PC = %08X\n", m_pc); return m_shiftreg[0]; @@ -468,7 +552,7 @@ void tms340x0_device::write_pixel_r_t_32(offs_t offset, uint32_t data) void tms340x0_device::write_pixel_shiftreg(offs_t offset, uint32_t data) { if (!m_from_shiftreg_cb.isnull()) - m_from_shiftreg_cb(*m_program, offset, &m_shiftreg[0]); + m_from_shiftreg_cb(offset, &m_shiftreg[0]); else fatalerror("From ShiftReg function not set. PC = %08X\n", m_pc); } @@ -606,15 +690,15 @@ void tms340x0_device::check_interrupt() /* if we took something, generate it */ if (vector) { + /* call the callback for externals */ + if (irqline >= 0) + standard_irq_callback(irqline, m_pc); + PUSH(m_pc); PUSH(m_st); RESET_ST(); m_pc = RLONG(vector); COUNT_CYCLES(16); - - /* call the callback for externals */ - if (irqline >= 0) - standard_irq_callback(irqline); } } @@ -626,25 +710,19 @@ void tms340x0_device::check_interrupt() void tms340x0_device::device_start() { - m_scanline_ind16_cb.bind_relative_to(*owner()); - m_scanline_rgb32_cb.bind_relative_to(*owner()); - m_output_int_cb.resolve(); - m_ioreg_pre_write_cb.resolve(); - m_to_shiftreg_cb.bind_relative_to(*owner()); - m_from_shiftreg_cb.bind_relative_to(*owner()); + m_scanline_ind16_cb.resolve(); + m_scanline_rgb32_cb.resolve(); + m_to_shiftreg_cb.resolve(); + m_from_shiftreg_cb.resolve(); m_external_host_access = false; - m_program = &space(AS_PROGRAM); - m_cache = m_program->cache<1, 3, ENDIANNESS_LITTLE>(); - /* set up the state table */ { state_add(TMS34010_PC, "PC", m_pc); state_add(STATE_GENPC, "GENPC", m_pc).noshow(); state_add(STATE_GENPCBASE, "CURPC", m_ppc).noshow(); state_add(TMS34010_SP, "SP", m_regs[15].reg); - state_add(STATE_GENSP, "GENSP", m_regs[15].reg).noshow(); state_add(TMS34010_ST, "ST", m_st); state_add(STATE_GENFLAGS, "GENFLAGS", m_st).noshow().formatstr("%18s"); @@ -659,7 +737,7 @@ void tms340x0_device::device_start() } /* allocate a scanline timer and set it to go off at the start */ - m_scantimer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(tms340x0_device::scanline_callback), this)); + m_scantimer = timer_alloc(FUNC(tms340x0_device::scanline_callback), this); m_scantimer->adjust(attotime::zero); save_item(NAME(m_pc)); @@ -672,11 +750,27 @@ void tms340x0_device::device_start() save_item(NAME(m_convmp)); save_item(NAME(m_pixelshift)); save_item(NAME(m_gfxcycles)); - save_pointer(NAME(&m_regs[0].reg), ARRAY_LENGTH(m_regs)); + save_pointer(NAME(&m_regs[0].reg), std::size(m_regs)); set_icountptr(m_icount); } +void tms34010_device::device_start() +{ + tms340x0_device::device_start(); + + space(AS_PROGRAM).cache(m_cache); + space(AS_PROGRAM).specific(m_program); +} + +void tms34020_device::device_start() +{ + tms340x0_device::device_start(); + + space(AS_PROGRAM).cache(m_cache); + space(AS_PROGRAM).specific(m_program); +} + void tms340x0_device::device_reset() { m_ppc = 0; @@ -769,6 +863,7 @@ void tms340x0_device::execute_run() /* Get out if CPU is halted. Absolutely no interrupts must be taken!!! */ if (IOREG(REG_HSTCTLH) & 0x8000) { + debugger_wait_hook(); m_icount = 0; return; } @@ -782,14 +877,14 @@ void tms340x0_device::execute_run() /* check interrupts first */ m_executing = true; check_interrupt(); - if ((machine().debug_flags & DEBUG_FLAG_ENABLED) == 0) + if (!debugger_enabled()) { do { uint16_t op; m_ppc = m_pc; op = ROPCODE(); - (this->*s_opcode_table[op >> 4])(op); + execute_op(op); } while (m_icount > 0); } else @@ -800,12 +895,22 @@ void tms340x0_device::execute_run() m_ppc = m_pc; debugger_instruction_hook(m_pc); op = ROPCODE(); - (this->*s_opcode_table[op >> 4])(op); + execute_op(op); } while (m_icount > 0); } m_executing = false; } +void tms34010_device::execute_op(uint16_t op) +{ + (this->*s_opcode_table[op >> 4])(op); +} + +void tms34020_device::execute_op(uint16_t op) +{ + (this->*s_opcode_table[op >> 4])(op); +} + /*************************************************************************** @@ -866,14 +971,14 @@ void tms340x0_device::set_pixel_function() const tms340x0_device::raster_op_func tms340x0_device::s_raster_ops[32] = { - nullptr, &tms340x0_device::raster_op_1 , &tms340x0_device::raster_op_2 , &tms340x0_device::raster_op_3, - &tms340x0_device::raster_op_4 , &tms340x0_device::raster_op_5 , &tms340x0_device::raster_op_6 , &tms340x0_device::raster_op_7, - &tms340x0_device::raster_op_8 , &tms340x0_device::raster_op_9 , &tms340x0_device::raster_op_10, &tms340x0_device::raster_op_11, + nullptr, &tms340x0_device::raster_op_1, &tms340x0_device::raster_op_2, &tms340x0_device::raster_op_3, + &tms340x0_device::raster_op_4, &tms340x0_device::raster_op_5, &tms340x0_device::raster_op_6, &tms340x0_device::raster_op_7, + &tms340x0_device::raster_op_8, &tms340x0_device::raster_op_9, &tms340x0_device::raster_op_10, &tms340x0_device::raster_op_11, &tms340x0_device::raster_op_12, &tms340x0_device::raster_op_13, &tms340x0_device::raster_op_14, &tms340x0_device::raster_op_15, &tms340x0_device::raster_op_16, &tms340x0_device::raster_op_17, &tms340x0_device::raster_op_18, &tms340x0_device::raster_op_19, - &tms340x0_device::raster_op_20, &tms340x0_device::raster_op_21, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, - nullptr, nullptr, nullptr, nullptr, + &tms340x0_device::raster_op_20, &tms340x0_device::raster_op_21, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, + nullptr, nullptr, nullptr, nullptr, }; @@ -915,7 +1020,7 @@ TIMER_CALLBACK_MEMBER( tms340x0_device::scanline_callback ) if (enabled && vcount == SMART_IOREG(DPYINT)) { /* generate the display interrupt signal */ - internal_interrupt_callback(nullptr, TMS34010_DI); + internal_interrupt_callback(TMS34010_DI); } /* at the start of VBLANK, load the starting display address */ @@ -1079,7 +1184,7 @@ uint32_t tms340x0_device::tms340x0_ind16(screen_device &screen, bitmap_ind16 &bi params.heblnk = params.hsblnk = cliprect.max_x + 1; /* blank out the blank regions */ - uint16_t *dest = &bitmap.pix16(cliprect.min_y); + uint16_t *dest = &bitmap.pix(cliprect.min_y); for (x = cliprect.min_x; x < params.heblnk; x++) dest[x] = blackpen; for (x = params.hsblnk; x <= cliprect.max_x; x++) @@ -1110,7 +1215,7 @@ uint32_t tms340x0_device::tms340x0_rgb32(screen_device &screen, bitmap_rgb32 &bi params.heblnk = params.hsblnk = cliprect.max_x + 1; /* blank out the blank regions */ - uint32_t *dest = &bitmap.pix32(cliprect.min_y); + uint32_t *dest = &bitmap.pix(cliprect.min_y); for (x = cliprect.min_x; x < params.heblnk; x++) dest[x] = blackpen; for (x = params.hsblnk; x <= cliprect.max_x; x++) @@ -1138,7 +1243,7 @@ static const char *const ioreg_name[] = void tms34010_device::io_register_w(offs_t offset, u16 data, u16 mem_mask) { - if (!m_ioreg_pre_write_cb.isnull()) + if (!m_ioreg_pre_write_cb.isunset()) m_ioreg_pre_write_cb(offset, data, mem_mask); int oldreg, newreg; @@ -1213,15 +1318,9 @@ void tms34010_device::io_register_w(offs_t offset, u16 data, u16 mem_mask) /* the TMS34010 can set output interrupt? */ if (!(oldreg & 0x0080) && (newreg & 0x0080)) - { - if (!m_output_int_cb.isnull()) - m_output_int_cb(1); - } + m_output_int_cb(1); else if ((oldreg & 0x0080) && !(newreg & 0x0080)) - { - if (!m_output_int_cb.isnull()) - m_output_int_cb(0); - } + m_output_int_cb(0); /* input interrupt? (should really be state-based, but the functions don't exist!) */ if (!(oldreg & 0x0008) && (newreg & 0x0008)) @@ -1289,7 +1388,7 @@ static const char *const ioreg020_name[] = void tms34020_device::io_register_w(offs_t offset, u16 data, u16 mem_mask) { - if (!m_ioreg_pre_write_cb.isnull()) + if (!m_ioreg_pre_write_cb.isunset()) m_ioreg_pre_write_cb(offset, data, mem_mask); int oldreg, newreg; @@ -1365,15 +1464,9 @@ void tms34020_device::io_register_w(offs_t offset, u16 data, u16 mem_mask) /* the TMS34010 can set output interrupt? */ if (!(oldreg & 0x0080) && (newreg & 0x0080)) - { - if (!m_output_int_cb.isnull()) - m_output_int_cb(1); - } + m_output_int_cb(1); else if ((oldreg & 0x0080) && !(newreg & 0x0080)) - { - if (!m_output_int_cb.isnull()) - m_output_int_cb(0); - } + m_output_int_cb(0); /* input interrupt? (should really be state-based, but the functions don't exist!) */ if (!(oldreg & 0x0008) && (newreg & 0x0008)) @@ -1455,7 +1548,8 @@ u16 tms34010_device::io_register_r(offs_t offset) { int result, total; - LOGCONTROLREGS("%s: read %s\n", machine().describe_context(), ioreg_name[offset]); + if (!machine().side_effects_disabled()) + LOGCONTROLREGS("%s: read %s\n", machine().describe_context(), ioreg_name[offset]); switch (offset) { @@ -1496,7 +1590,8 @@ u16 tms34020_device::io_register_r(offs_t offset) { int result, total; - LOGCONTROLREGS("%s: read %s\n", machine().describe_context(), ioreg_name[offset]); + if (!machine().side_effects_disabled()) + LOGCONTROLREGS("%s: read %s\n", machine().describe_context(), ioreg020_name[offset]); switch (offset) { @@ -1626,13 +1721,16 @@ u16 tms340x0_device::host_r(offs_t offset) addr = (IOREG(REG_HSTADRH) << 16) | IOREG(REG_HSTADRL); result = TMS34010_RDMEM_WORD(addr & 0xfffffff0); - /* optional postincrement (it says preincrement, but data is preloaded, so it - is effectively a postincrement */ - if (IOREG(REG_HSTCTLH) & 0x1000) + if (!machine().side_effects_disabled()) { - addr += 0x10; - IOREG(REG_HSTADRH) = addr >> 16; - IOREG(REG_HSTADRL) = (uint16_t)addr; + /* optional postincrement (it says preincrement, but data is preloaded, so it + is effectively a postincrement */ + if (IOREG(REG_HSTCTLH) & 0x1000) + { + addr += 0x10; + IOREG(REG_HSTADRH) = addr >> 16; + IOREG(REG_HSTADRL) = (uint16_t)addr; + } } break; @@ -1643,7 +1741,8 @@ u16 tms340x0_device::host_r(offs_t offset) /* error case */ default: - logerror("tms34010_host_control_r called on invalid register %d\n", reg); + if (!machine().side_effects_disabled()) + logerror("tms34010_host_control_r called on invalid register %d\n", reg); break; } |