Merge pull request #3542 from pmackinlay/tms320c30

tms32031: add tms320c30 and basic hold/holda support
This commit is contained in:
ajrhacker 2018-05-09 01:06:49 -04:00 committed by GitHub
commit e30a760f1c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 130 additions and 7 deletions

View File

@ -88,24 +88,47 @@ const int GIEFLAG = 0x2000;
//************************************************************************** //**************************************************************************
// device type definition // 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(TMS32031, tms32031_device, "tms32031", "Texas Instruments TMS32031")
DEFINE_DEVICE_TYPE(TMS32032, tms32032_device, "tms32032", "Texas Instruments TMS32032") 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 // 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) void tms32031_device::internal_32031(address_map &map)
{ {
common_3203x(map);
map(0x809800, 0x809fff).ram(); map(0x809800, 0x809fff).ram();
} }
void tms32032_device::internal_32032(address_map &map) void tms32032_device::internal_32032(address_map &map)
{ {
common_3203x(map);
map(0x87fe00, 0x87ffff).ram(); map(0x87fe00, 0x87ffff).ram();
} }
// ROM definitions for the internal boot loader programs // ROM definitions for the internal boot loader programs
// (Using assembled versions until the code ROMs are extracted from both DSPs) // (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_START( tms32031 )
ROM_REGION(0x4000, "tms32031", 0) ROM_REGION(0x4000, "tms32031", 0)
ROM_LOAD( "c31boot.bin", 0x0000, 0x4000, BAD_DUMP CRC(bddc2763) SHA1(96b2170ecee5bec5abaa1741bb2d3b6096ecc262) ) // Assembled from c31boot.asm (02-07-92) 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_chip_type(chiptype),
m_pc(0), m_pc(0),
m_bkmask(0), m_bkmask(0),
m_primary_bus_control(0),
m_irq_state(0), m_irq_state(0),
m_delayed(false), m_delayed(false),
m_irq_pending(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_mcbl_mode(false),
m_xf0_cb(*this), m_xf0_cb(*this),
m_xf1_cb(*this), m_xf1_cb(*this),
m_iack_cb(*this) m_iack_cb(*this),
m_holda_cb(*this)
{ {
// initialize remaining state // initialize remaining state
memset(&m_r, 0, sizeof(m_r)); memset(&m_r, 0, sizeof(m_r));
@ -283,6 +308,11 @@ tms3203x_device::tms3203x_device(const machine_config &mconfig, device_type type
#endif #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) 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)) : 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) switch (m_chip_type)
{ {
default: default:
case CHIP_TYPE_TMS32030: return ROM_NAME( tms32030 );
case CHIP_TYPE_TMS32031: return ROM_NAME( tms32031 ); case CHIP_TYPE_TMS32031: return ROM_NAME( tms32031 );
case CHIP_TYPE_TMS32032: return ROM_NAME( tms32032 ); case CHIP_TYPE_TMS32032: return ROM_NAME( tms32032 );
} }
@ -372,6 +403,7 @@ void tms3203x_device::device_start()
m_xf0_cb.resolve_safe(); m_xf0_cb.resolve_safe();
m_xf1_cb.resolve_safe(); m_xf1_cb.resolve_safe();
m_iack_cb.resolve_safe(); m_iack_cb.resolve_safe();
m_holda_cb.resolve_safe();
// set up the internal boot loader ROM // set up the internal boot loader ROM
m_bootrom = reinterpret_cast<uint32_t*>(memregion(shortname())->base()); m_bootrom = reinterpret_cast<uint32_t*>(memregion(shortname())->base());
@ -381,11 +413,13 @@ void tms3203x_device::device_start()
for (int regnum = 0; regnum < 36; regnum++) for (int regnum = 0; regnum < 36; regnum++)
save_item(NAME(m_r[regnum].i32), regnum); save_item(NAME(m_r[regnum].i32), regnum);
save_item(NAME(m_bkmask)); save_item(NAME(m_bkmask));
save_item(NAME(m_primary_bus_control));
save_item(NAME(m_irq_state)); save_item(NAME(m_irq_state));
save_item(NAME(m_delayed)); save_item(NAME(m_delayed));
save_item(NAME(m_irq_pending)); save_item(NAME(m_irq_pending));
save_item(NAME(m_is_idling)); save_item(NAME(m_is_idling));
save_item(NAME(m_mcbl_mode)); save_item(NAME(m_mcbl_mode));
save_item(NAME(m_hold_state));
// register our state for the debugger // register our state for the debugger
state_add(TMS3203X_PC, "PC", m_pc); 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) // update IF with the external interrupt state (required for boot loader operation)
IREG(TMR_IF) |= m_irq_state & 0x0f; IREG(TMR_IF) |= m_irq_state & 0x0f;
// reset peripheral registers
m_primary_bus_control = 0x000010f8;
// reset internal stuff // reset internal stuff
m_delayed = m_irq_pending = m_is_idling = false; 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 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) void tms3203x_device::execute_set_input(int inputnum, int state)
{ {
// ignore anything out of range
if (inputnum >= 13)
return;
if (inputnum == TMS3203X_MCBL) if (inputnum == TMS3203X_MCBL)
{ {
// switch between microcomputer/boot loader and microprocessor modes // switch between microcomputer/boot loader and microprocessor modes
@ -716,6 +749,33 @@ void tms3203x_device::execute_set_input(int inputnum, int state)
return; 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 // update the external state
uint16_t intmask = 1 << inputnum; uint16_t intmask = 1 << inputnum;
if (state == ASSERT_LINE) 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 // external interrupts are level-sensitive on the '31 and can be
// configured as such on the '32; in that case, if the external // configured as such on the '32; in that case, if the external
// signal is high, we need to update the value in IF accordingly // 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; 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 // CORE OPCODES

View File

@ -41,6 +41,7 @@ const int TMS3203X_DINT = 10; // DMA interrupt
const int TMS3203X_DINT0 = 10; // DMA 0 interrupt (32032 only) const int TMS3203X_DINT0 = 10; // DMA 0 interrupt (32032 only)
const int TMS3203X_DINT1 = 11; // DMA 1 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_MCBL = 12; // Microcomputer/boot loader mode
const int TMS3203X_HOLD = 13; // Primary bus interface hold signal
// register enumeration // register enumeration
enum enum
@ -102,6 +103,8 @@ enum
#define MCFG_TMS3203X_IACK_CB(_devcb) \ #define MCFG_TMS3203X_IACK_CB(_devcb) \
devcb = &downcast<tms3203x_device &>(*device).set_iack_callback(DEVCB_##_devcb); devcb = &downcast<tms3203x_device &>(*device).set_iack_callback(DEVCB_##_devcb);
#define MCFG_TMS3203X_HOLDA_CB(_devcb) \
devcb = &downcast<tms3203x_device &>(*device).set_holda_callback(DEVCB_##_devcb);
//************************************************************************** //**************************************************************************
// TYPE DEFINITIONS // TYPE DEFINITIONS
@ -143,6 +146,7 @@ public:
template <class Object> devcb_base &set_xf0_callback(Object &&cb) { return m_xf0_cb.set_callback(std::forward<Object>(cb)); } template <class Object> devcb_base &set_xf0_callback(Object &&cb) { return m_xf0_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_xf1_callback(Object &&cb) { return m_xf1_cb.set_callback(std::forward<Object>(cb)); } template <class Object> devcb_base &set_xf1_callback(Object &&cb) { return m_xf1_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_iack_callback(Object &&cb) { return m_iack_cb.set_callback(std::forward<Object>(cb)); } template <class Object> devcb_base &set_iack_callback(Object &&cb) { return m_iack_cb.set_callback(std::forward<Object>(cb)); }
template <class Object> devcb_base &set_holda_callback(Object &&cb) { return m_holda_cb.set_callback(std::forward<Object>(cb)); }
// public interfaces // public interfaces
static float fp_to_float(uint32_t floatdata); static float fp_to_float(uint32_t floatdata);
@ -153,12 +157,14 @@ public:
protected: protected:
enum enum
{ {
CHIP_TYPE_TMS32030,
CHIP_TYPE_TMS32031, CHIP_TYPE_TMS32031,
CHIP_TYPE_TMS32032 CHIP_TYPE_TMS32032
}; };
// construction/destruction // 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); 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 // device-level overrides
virtual void device_start() override; virtual void device_start() override;
@ -184,6 +190,10 @@ protected:
// device_disasm_interface overrides // device_disasm_interface overrides
virtual std::unique_ptr<util::disasm_interface> create_disassembler() override; virtual std::unique_ptr<util::disasm_interface> 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 // memory helpers
uint32_t ROPCODE(offs_t pc); uint32_t ROPCODE(offs_t pc);
uint32_t RMEM(offs_t addr); uint32_t RMEM(offs_t addr);
@ -755,6 +765,20 @@ protected:
tmsreg m_r[36]; tmsreg m_r[36];
uint32_t m_bkmask; uint32_t m_bkmask;
// internal peripheral registers
enum primary_bus_control_mask : uint32_t
{
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
};
uint32_t m_primary_bus_control;
// internal stuff // internal stuff
uint16_t m_irq_state; uint16_t m_irq_state;
bool m_delayed; bool m_delayed;
@ -768,9 +792,12 @@ protected:
uint32_t * m_bootrom; uint32_t * m_bootrom;
bool m_mcbl_mode; bool m_mcbl_mode;
bool m_hold_state;
devcb_write8 m_xf0_cb; devcb_write8 m_xf0_cb;
devcb_write8 m_xf1_cb; devcb_write8 m_xf1_cb;
devcb_write8 m_iack_cb; devcb_write8 m_iack_cb;
devcb_write_line m_holda_cb;
// tables // tables
static void (tms3203x_device::*const s_tms32031ops[])(uint32_t op); 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 // ======================> tms32031_device
class tms32031_device : public tms3203x_device class tms32031_device : public tms3203x_device
@ -807,6 +845,7 @@ public:
// device type definition // device type definition
DECLARE_DEVICE_TYPE(TMS32030, tms32030_device)
DECLARE_DEVICE_TYPE(TMS32031, tms32031_device) DECLARE_DEVICE_TYPE(TMS32031, tms32031_device)
DECLARE_DEVICE_TYPE(TMS32032, tms32032_device) DECLARE_DEVICE_TYPE(TMS32032, tms32032_device)