mirror of
https://github.com/holub/mame
synced 2025-05-30 01:23:07 +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
|
||||
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
|
||||
|
@ -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)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user