mirror of
https://github.com/holub/mame
synced 2025-06-02 19:06:43 +03:00
Merge pull request #3542 from pmackinlay/tms320c30
tms32031: add tms320c30 and basic hold/holda support
This commit is contained in:
commit
e30a760f1c
@ -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
|
||||||
|
@ -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)
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user