From c2462427b564430ddabe20e000d2a9e04ffda288 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Wed, 9 May 2018 11:08:00 +0700 Subject: [PATCH 1/3] tms32031: add tms320c30 and basic hold/holda support For some reason there was no TMS320C30 device, so it's been added. Stubbed in basic HOLD/HOLDA line/callback support which is used to suspend DSP external bus access, and used by the InterPro EDGE graphics boards under development. This change doesn't actually change the 'C30 behaviour yet, but allows the external device to get an acknowledgement and proceed. --- src/devices/cpu/tms32031/tms32031.cpp | 98 +++++++++++++++++++++++++-- src/devices/cpu/tms32031/tms32031.h | 39 +++++++++++ 2 files changed, 130 insertions(+), 7 deletions(-) diff --git a/src/devices/cpu/tms32031/tms32031.cpp b/src/devices/cpu/tms32031/tms32031.cpp index 3ccfff7ec69..e44b0d7b881 100644 --- a/src/devices/cpu/tms32031/tms32031.cpp +++ b/src/devices/cpu/tms32031/tms32031.cpp @@ -88,24 +88,47 @@ const int GIEFLAG = 0x2000; //************************************************************************** // device type definition +DEFINE_DEVICE_TYPE(TMS32030, tms32030_device, "tms32030", "Texas Instruments TMS32030") DEFINE_DEVICE_TYPE(TMS32031, tms32031_device, "tms32031", "Texas Instruments TMS32031") DEFINE_DEVICE_TYPE(TMS32032, tms32032_device, "tms32032", "Texas Instruments TMS32032") +// memory map common to all 'C30 devices +// TODO: expand to cover all the standard internal peripherals +void tms3203x_device::common_3203x(address_map &map) +{ + map(0x808064, 0x808064).rw(this, FUNC(tms3203x_device::primary_bus_control_r), FUNC(tms3203x_device::primary_bus_control_w)); +} // internal memory maps +void tms32030_device::internal_32030(address_map &map) +{ + common_3203x(map); + + map(0x809800, 0x809fff).ram(); +} + void tms32031_device::internal_32031(address_map &map) { + common_3203x(map); + map(0x809800, 0x809fff).ram(); } void tms32032_device::internal_32032(address_map &map) { + common_3203x(map); + map(0x87fe00, 0x87ffff).ram(); } // ROM definitions for the internal boot loader programs // (Using assembled versions until the code ROMs are extracted from both DSPs) +ROM_START( tms32030 ) + ROM_REGION(0x4000, "tms32030", 0) + ROM_LOAD( "c30boot.bin", 0x0000, 0x4000, BAD_DUMP CRC(bddc2763) SHA1(96b2170ecee5bec5abaa1741bb2d3b6096ecc262)) +ROM_END + ROM_START( tms32031 ) ROM_REGION(0x4000, "tms32031", 0) ROM_LOAD( "c31boot.bin", 0x0000, 0x4000, BAD_DUMP CRC(bddc2763) SHA1(96b2170ecee5bec5abaa1741bb2d3b6096ecc262) ) // Assembled from c31boot.asm (02-07-92) @@ -260,6 +283,7 @@ tms3203x_device::tms3203x_device(const machine_config &mconfig, device_type type m_chip_type(chiptype), m_pc(0), m_bkmask(0), + m_primary_bus_control(0), m_irq_state(0), m_delayed(false), m_irq_pending(false), @@ -270,7 +294,8 @@ tms3203x_device::tms3203x_device(const machine_config &mconfig, device_type type m_mcbl_mode(false), m_xf0_cb(*this), m_xf1_cb(*this), - m_iack_cb(*this) + m_iack_cb(*this), + m_holda_cb(*this) { // initialize remaining state memset(&m_r, 0, sizeof(m_r)); @@ -283,6 +308,11 @@ tms3203x_device::tms3203x_device(const machine_config &mconfig, device_type type #endif } +tms32030_device::tms32030_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) + : tms3203x_device(mconfig, TMS32030, tag, owner, clock, CHIP_TYPE_TMS32030, address_map_constructor(FUNC(tms32030_device::internal_32030), this)) +{ +} + tms32031_device::tms32031_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : tms3203x_device(mconfig, TMS32031, tag, owner, clock, CHIP_TYPE_TMS32031, address_map_constructor(FUNC(tms32031_device::internal_32031), this)) { @@ -317,6 +347,7 @@ const tiny_rom_entry *tms3203x_device::device_rom_region() const switch (m_chip_type) { default: + case CHIP_TYPE_TMS32030: return ROM_NAME( tms32030 ); case CHIP_TYPE_TMS32031: return ROM_NAME( tms32031 ); case CHIP_TYPE_TMS32032: return ROM_NAME( tms32032 ); } @@ -372,6 +403,7 @@ void tms3203x_device::device_start() m_xf0_cb.resolve_safe(); m_xf1_cb.resolve_safe(); m_iack_cb.resolve_safe(); + m_holda_cb.resolve_safe(); // set up the internal boot loader ROM m_bootrom = reinterpret_cast(memregion(shortname())->base()); @@ -381,11 +413,13 @@ void tms3203x_device::device_start() for (int regnum = 0; regnum < 36; regnum++) save_item(NAME(m_r[regnum].i32), regnum); save_item(NAME(m_bkmask)); + save_item(NAME(m_primary_bus_control)); save_item(NAME(m_irq_state)); save_item(NAME(m_delayed)); save_item(NAME(m_irq_pending)); save_item(NAME(m_is_idling)); save_item(NAME(m_mcbl_mode)); + save_item(NAME(m_hold_state)); // register our state for the debugger state_add(TMS3203X_PC, "PC", m_pc); @@ -448,6 +482,9 @@ void tms3203x_device::device_reset() // update IF with the external interrupt state (required for boot loader operation) IREG(TMR_IF) |= m_irq_state & 0x0f; + // reset peripheral registers + m_primary_bus_control = 0x000010f8; + // reset internal stuff m_delayed = m_irq_pending = m_is_idling = false; } @@ -694,7 +731,7 @@ uint32_t tms3203x_device::execute_max_cycles() const uint32_t tms3203x_device::execute_input_lines() const { - return (m_chip_type == CHIP_TYPE_TMS32032) ? 13 : 12; + return 14; } @@ -704,10 +741,6 @@ uint32_t tms3203x_device::execute_input_lines() const void tms3203x_device::execute_set_input(int inputnum, int state) { - // ignore anything out of range - if (inputnum >= 13) - return; - if (inputnum == TMS3203X_MCBL) { // switch between microcomputer/boot loader and microprocessor modes @@ -716,6 +749,33 @@ void tms3203x_device::execute_set_input(int inputnum, int state) return; } + if (inputnum == TMS3203X_HOLD) + { + m_hold_state = (state == ASSERT_LINE); + + // FIXME: "there is a minimum of one cycle delay from the time when + // the processor recognises /HOLD = 0 until /HOLDA = 0" + if (m_hold_state) + { + // assert hold acknowledge if external hold enabled + if (!(m_primary_bus_control & NOHOLD)) + { + m_primary_bus_control |= HOLDST; + m_holda_cb(ASSERT_LINE); + } + } + else + { + // clear hold acknowledge if port is held externally + if ((m_primary_bus_control & HOLDST) && !(m_primary_bus_control & HIZ)) + { + m_primary_bus_control &= ~HOLDST; + m_holda_cb(CLEAR_LINE); + } + } + return; + } + // update the external state uint16_t intmask = 1 << inputnum; if (state == ASSERT_LINE) @@ -729,7 +789,7 @@ void tms3203x_device::execute_set_input(int inputnum, int state) // external interrupts are level-sensitive on the '31 and can be // configured as such on the '32; in that case, if the external // signal is high, we need to update the value in IF accordingly - if (m_chip_type == CHIP_TYPE_TMS32031 || (IREG(TMR_ST) & 0x4000) == 0) + if (m_chip_type != CHIP_TYPE_TMS32032 || (IREG(TMR_ST) & 0x4000) == 0) IREG(TMR_IF) |= m_irq_state & 0x0f; } @@ -813,6 +873,30 @@ void tms3203x_device::execute_run() } } +// internal peripherals +WRITE32_MEMBER(tms3203x_device::primary_bus_control_w) +{ + // change in internal hold state + if ((m_primary_bus_control ^ data) & HIZ) + { + if (m_primary_bus_control & HOLDST) + m_primary_bus_control &= ~HOLDST; + else + m_primary_bus_control |= HOLDST; + m_holda_cb(data & HIZ ? ASSERT_LINE : CLEAR_LINE); + } + + // enable of external hold with hold pending + if (m_primary_bus_control & NOHOLD && !(data & NOHOLD) && m_hold_state) + { + m_primary_bus_control |= HOLDST; + m_holda_cb(ASSERT_LINE); + } + + // update register + m_primary_bus_control = (m_primary_bus_control & ~(mem_mask | WMASK)) | (data & mem_mask & WMASK); +} + //************************************************************************** // CORE OPCODES diff --git a/src/devices/cpu/tms32031/tms32031.h b/src/devices/cpu/tms32031/tms32031.h index 25046630461..9efca2eda67 100644 --- a/src/devices/cpu/tms32031/tms32031.h +++ b/src/devices/cpu/tms32031/tms32031.h @@ -41,6 +41,7 @@ const int TMS3203X_DINT = 10; // DMA interrupt const int TMS3203X_DINT0 = 10; // DMA 0 interrupt (32032 only) const int TMS3203X_DINT1 = 11; // DMA 1 interrupt (32032 only) const int TMS3203X_MCBL = 12; // Microcomputer/boot loader mode +const int TMS3203X_HOLD = 13; // Primary bus interface hold signal // register enumeration enum @@ -102,6 +103,8 @@ enum #define MCFG_TMS3203X_IACK_CB(_devcb) \ devcb = &downcast(*device).set_iack_callback(DEVCB_##_devcb); +#define MCFG_TMS3203X_HOLDA_CB(_devcb) \ + devcb = &downcast(*device).set_holda_callback(DEVCB_##_devcb); //************************************************************************** // TYPE DEFINITIONS @@ -143,6 +146,7 @@ public: template devcb_base &set_xf0_callback(Object &&cb) { return m_xf0_cb.set_callback(std::forward(cb)); } template devcb_base &set_xf1_callback(Object &&cb) { return m_xf1_cb.set_callback(std::forward(cb)); } template devcb_base &set_iack_callback(Object &&cb) { return m_iack_cb.set_callback(std::forward(cb)); } + template devcb_base &set_holda_callback(Object &&cb) { return m_holda_cb.set_callback(std::forward(cb)); } // public interfaces static float fp_to_float(uint32_t floatdata); @@ -153,12 +157,14 @@ public: protected: enum { + CHIP_TYPE_TMS32030, CHIP_TYPE_TMS32031, CHIP_TYPE_TMS32032 }; // construction/destruction tms3203x_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock, uint32_t chiptype, address_map_constructor internal_map); + void common_3203x(address_map &map); // device-level overrides virtual void device_start() override; @@ -184,6 +190,10 @@ protected: // device_disasm_interface overrides virtual std::unique_ptr create_disassembler() override; + // internal peripheral device handlers + DECLARE_READ32_MEMBER(primary_bus_control_r) { return m_primary_bus_control; } + DECLARE_WRITE32_MEMBER(primary_bus_control_w); + // memory helpers uint32_t ROPCODE(offs_t pc); uint32_t RMEM(offs_t addr); @@ -755,6 +765,20 @@ protected: tmsreg m_r[36]; uint32_t m_bkmask; + // internal peripheral registers + enum primary_bus_control_mask : u32 + { + HOLDST = 0x00000001, // hold status + NOHOLD = 0x00000002, // external hold disable + HIZ = 0x00000004, // internal hold + SWW = 0x00000018, // software wait mode + WTCNT = 0x000000e0, // software wait count + BNKCMP = 0x00001f00, // bank compare + + WMASK = 0x00001ffe + }; + u32 m_primary_bus_control; + // internal stuff uint16_t m_irq_state; bool m_delayed; @@ -768,9 +792,12 @@ protected: uint32_t * m_bootrom; bool m_mcbl_mode; + bool m_hold_state; + devcb_write8 m_xf0_cb; devcb_write8 m_xf1_cb; devcb_write8 m_iack_cb; + devcb_write_line m_holda_cb; // tables static void (tms3203x_device::*const s_tms32031ops[])(uint32_t op); @@ -784,6 +811,17 @@ protected: }; +// ======================> tms32030_device + +class tms32030_device : public tms3203x_device +{ +public: + // construction/destruction + tms32030_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock); + void internal_32030(address_map &map); +}; + + // ======================> tms32031_device class tms32031_device : public tms3203x_device @@ -807,6 +845,7 @@ public: // device type definition +DECLARE_DEVICE_TYPE(TMS32030, tms32030_device) DECLARE_DEVICE_TYPE(TMS32031, tms32031_device) DECLARE_DEVICE_TYPE(TMS32032, tms32032_device) From d09d1800447474c0d01a65b5b5c9575a98946e04 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Wed, 9 May 2018 11:14:06 +0700 Subject: [PATCH 2/3] formatting (nw) --- src/devices/cpu/tms32031/tms32031.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/devices/cpu/tms32031/tms32031.h b/src/devices/cpu/tms32031/tms32031.h index 9efca2eda67..3d919bb2c78 100644 --- a/src/devices/cpu/tms32031/tms32031.h +++ b/src/devices/cpu/tms32031/tms32031.h @@ -766,7 +766,7 @@ protected: uint32_t m_bkmask; // internal peripheral registers - enum primary_bus_control_mask : u32 + enum primary_bus_control_mask : uint32_t { HOLDST = 0x00000001, // hold status NOHOLD = 0x00000002, // external hold disable @@ -777,7 +777,7 @@ protected: WMASK = 0x00001ffe }; - u32 m_primary_bus_control; + uint32_t m_primary_bus_control; // internal stuff uint16_t m_irq_state; @@ -792,7 +792,7 @@ protected: uint32_t * m_bootrom; bool m_mcbl_mode; - bool m_hold_state; + bool m_hold_state; devcb_write8 m_xf0_cb; devcb_write8 m_xf1_cb; From c5013e17346e4dade324c6aed3218dc9c780f014 Mon Sep 17 00:00:00 2001 From: Patrick Mackinlay Date: Wed, 9 May 2018 11:18:33 +0700 Subject: [PATCH 3/3] parens (nw) --- src/devices/cpu/tms32031/tms32031.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/devices/cpu/tms32031/tms32031.cpp b/src/devices/cpu/tms32031/tms32031.cpp index e44b0d7b881..83677827bc7 100644 --- a/src/devices/cpu/tms32031/tms32031.cpp +++ b/src/devices/cpu/tms32031/tms32031.cpp @@ -887,7 +887,7 @@ WRITE32_MEMBER(tms3203x_device::primary_bus_control_w) } // enable of external hold with hold pending - if (m_primary_bus_control & NOHOLD && !(data & NOHOLD) && m_hold_state) + if ((m_primary_bus_control & NOHOLD) && !(data & NOHOLD) && m_hold_state) { m_primary_bus_control |= HOLDST; m_holda_cb(ASSERT_LINE);