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
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<uint32_t*>(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

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_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<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
@ -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_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_holda_callback(Object &&cb) { return m_holda_cb.set_callback(std::forward<Object>(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<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
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 : 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
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)