mirror of
https://github.com/holub/mame
synced 2025-05-28 08:33:05 +03:00
Added internal boot loader programs to the TMS3203x core and support a switch between microcomputer (bootloader) and microprocessor modes via the TMS3203X_MCBL input [Phil Bennett]
*** This is required for Rise of the Robots, whose boot code jumps into the middle of the bootloader ROM. Changes tested with primrage, sfrush and speedup.
This commit is contained in:
parent
3ea4845b77
commit
a93919643d
@ -5693,8 +5693,6 @@ void tms3203x_device::trap(int trapnum)
|
||||
IREG(TMR_ST) &= ~GIEFLAG;
|
||||
if (m_chip_type == CHIP_TYPE_TMS32032)
|
||||
m_pc = RMEM(((IREG(TMR_IF) >> 16) << 8) + trapnum);
|
||||
else if (m_mcu_mode)
|
||||
m_pc = 0x809fc0 + trapnum;
|
||||
else
|
||||
m_pc = RMEM(trapnum);
|
||||
m_icount -= 4*2;
|
||||
|
@ -119,16 +119,30 @@ const int GIEFLAG = 0x2000;
|
||||
const device_type TMS32031 = &device_creator<tms32031_device>;
|
||||
const device_type TMS32032 = &device_creator<tms32032_device>;
|
||||
|
||||
|
||||
// internal memory maps
|
||||
static ADDRESS_MAP_START( internal_32031, AS_PROGRAM, 32, legacy_cpu_device )
|
||||
static ADDRESS_MAP_START( internal_32031, AS_PROGRAM, 32, tms32031_device )
|
||||
AM_RANGE(0x809800, 0x809fff) AM_RAM
|
||||
ADDRESS_MAP_END
|
||||
|
||||
static ADDRESS_MAP_START( internal_32032, AS_PROGRAM, 32, legacy_cpu_device )
|
||||
static ADDRESS_MAP_START( internal_32032, AS_PROGRAM, 32, tms32032_device )
|
||||
AM_RANGE(0x87fe00, 0x87ffff) AM_RAM
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
// ROM definitions for the internal boot loader programs
|
||||
// (Using assembled versions until the code ROMs are extracted from both DSPs)
|
||||
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)
|
||||
ROM_END
|
||||
|
||||
ROM_START( tms32032 )
|
||||
ROM_REGION(0x4000, "tms32032", 0)
|
||||
ROM_LOAD( "c32boot.bin", 0x0000, 0x4000, BAD_DUMP CRC(ecf84729) SHA1(4d32ead450f921f563514b061ea561a222283616) ) // Assembled from c32boot.asm (03-04-96)
|
||||
ROM_END
|
||||
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// TMSREG REGISTER
|
||||
@ -275,14 +289,13 @@ tms3203x_device::tms3203x_device(const machine_config &mconfig, device_type type
|
||||
m_irq_state(0),
|
||||
m_delayed(false),
|
||||
m_irq_pending(false),
|
||||
m_mcu_mode(false),
|
||||
m_is_idling(false),
|
||||
m_icount(0),
|
||||
m_irq_callback(0),
|
||||
m_program(0),
|
||||
m_direct(0)
|
||||
{
|
||||
m_bootoffset = 0;
|
||||
m_mcbl_mode = false;
|
||||
m_xf0_w = NULL;
|
||||
m_xf1_w = NULL;
|
||||
m_iack_w = NULL;
|
||||
@ -299,10 +312,29 @@ tms3203x_device::tms3203x_device(const machine_config &mconfig, device_type type
|
||||
}
|
||||
|
||||
tms32031_device::tms32031_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: tms3203x_device(mconfig, TMS32031, "TMS32031", tag, owner, clock, CHIP_TYPE_TMS32031, ADDRESS_MAP_NAME(internal_32031)) { }
|
||||
: tms3203x_device(mconfig, TMS32031, "TMS32031", tag, owner, clock, CHIP_TYPE_TMS32031, ADDRESS_MAP_NAME(internal_32031))
|
||||
{
|
||||
m_shortname = "tms32031";
|
||||
}
|
||||
|
||||
tms32032_device::tms32032_device(const machine_config &mconfig, const char *tag, device_t *owner, UINT32 clock)
|
||||
: tms3203x_device(mconfig, TMS32032, "TMS32032", tag, owner, clock, CHIP_TYPE_TMS32032, ADDRESS_MAP_NAME(internal_32032)) { }
|
||||
: tms3203x_device(mconfig, TMS32032, "TMS32032", tag, owner, clock, CHIP_TYPE_TMS32032, ADDRESS_MAP_NAME(internal_32032))
|
||||
{
|
||||
m_shortname = "tms32032";
|
||||
}
|
||||
|
||||
|
||||
DIRECT_UPDATE_MEMBER( tms3203x_device::direct_handler )
|
||||
{
|
||||
// internal boot loader ROM
|
||||
if (m_mcbl_mode && address < (0x1000 << 2))
|
||||
{
|
||||
direct.explicit_configure(0x000000, 0x003fff, 0x003fff, m_bootrom);
|
||||
return (offs_t)-1;
|
||||
}
|
||||
|
||||
return address;
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
@ -331,6 +363,21 @@ void tms3203x_device::static_set_config(device_t &device, const tms3203x_config
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// rom_region - return a pointer to the device's
|
||||
// internal ROM region
|
||||
//-------------------------------------------------
|
||||
|
||||
const rom_entry *tms3203x_device::device_rom_region() const
|
||||
{
|
||||
switch (m_chip_type)
|
||||
{
|
||||
default:
|
||||
case CHIP_TYPE_TMS32031: return ROM_NAME( tms32031 );
|
||||
case CHIP_TYPE_TMS32032: return ROM_NAME( tms32032 );
|
||||
}
|
||||
}
|
||||
|
||||
//-------------------------------------------------
|
||||
// ROPCODE - fetch an opcode
|
||||
//-------------------------------------------------
|
||||
@ -347,6 +394,9 @@ inline UINT32 tms3203x_device::ROPCODE(offs_t pc)
|
||||
|
||||
inline UINT32 tms3203x_device::RMEM(offs_t addr)
|
||||
{
|
||||
if (m_mcbl_mode && addr < 0x1000)
|
||||
return m_bootrom[addr];
|
||||
|
||||
return m_program->read_dword(addr << 2);
|
||||
}
|
||||
|
||||
@ -371,6 +421,10 @@ void tms3203x_device::device_start()
|
||||
m_program = &space(AS_PROGRAM);
|
||||
m_direct = &m_program->direct();
|
||||
|
||||
// set up the internal boot loader ROM
|
||||
m_bootrom = reinterpret_cast<UINT32*>(memregion(m_shortname)->base());
|
||||
m_direct->set_direct_update(direct_update_delegate(FUNC(tms3203x_device::direct_handler), this));
|
||||
|
||||
// save state
|
||||
save_item(NAME(m_pc));
|
||||
for (int regnum = 0; regnum < 36; regnum++)
|
||||
@ -379,7 +433,6 @@ void tms3203x_device::device_start()
|
||||
save_item(NAME(m_irq_state));
|
||||
save_item(NAME(m_delayed));
|
||||
save_item(NAME(m_irq_pending));
|
||||
save_item(NAME(m_mcu_mode));
|
||||
save_item(NAME(m_is_idling));
|
||||
|
||||
// register our state for the debugger
|
||||
@ -431,17 +484,7 @@ void tms3203x_device::device_start()
|
||||
|
||||
void tms3203x_device::device_reset()
|
||||
{
|
||||
// if we have a config struct, get the boot ROM address
|
||||
if (m_bootoffset != 0)
|
||||
{
|
||||
m_mcu_mode = true;
|
||||
m_pc = boot_loader(m_bootoffset);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_mcu_mode = false;
|
||||
m_pc = RMEM(0);
|
||||
}
|
||||
m_pc = RMEM(0);
|
||||
|
||||
// reset some registers
|
||||
IREG(TMR_IE) = 0;
|
||||
@ -449,6 +492,9 @@ void tms3203x_device::device_reset()
|
||||
IREG(TMR_ST) = 0;
|
||||
IREG(TMR_IOF) = 0;
|
||||
|
||||
// update IF with the external interrupt state (required for boot loader operation)
|
||||
IREG(TMR_IF) |= m_irq_state & 0x0f;
|
||||
|
||||
// reset internal stuff
|
||||
m_delayed = m_irq_pending = m_is_idling = false;
|
||||
}
|
||||
@ -718,7 +764,7 @@ UINT32 tms3203x_device::execute_max_cycles() const
|
||||
|
||||
UINT32 tms3203x_device::execute_input_lines() const
|
||||
{
|
||||
return 11;
|
||||
return (m_chip_type == CHIP_TYPE_TMS32032) ? 13 : 12;
|
||||
}
|
||||
|
||||
|
||||
@ -729,9 +775,17 @@ UINT32 tms3203x_device::execute_input_lines() const
|
||||
void tms3203x_device::execute_set_input(int inputnum, int state)
|
||||
{
|
||||
// ignore anything out of range
|
||||
if (inputnum >= 12)
|
||||
if (inputnum >= 13)
|
||||
return;
|
||||
|
||||
if (inputnum == TMS3203X_MCBL)
|
||||
{
|
||||
// switch between microcomputer/boot loader and microprocessor modes
|
||||
m_mcbl_mode = (state == ASSERT_LINE);
|
||||
m_direct->force_update();
|
||||
return;
|
||||
}
|
||||
|
||||
// update the external state
|
||||
UINT16 intmask = 1 << inputnum;
|
||||
if (state == ASSERT_LINE)
|
||||
@ -830,67 +884,6 @@ void tms3203x_device::execute_run()
|
||||
}
|
||||
|
||||
|
||||
//-------------------------------------------------
|
||||
// boot_loader - reset the state of the system
|
||||
// by simulating the internal boot loader
|
||||
//-------------------------------------------------
|
||||
|
||||
UINT32 tms3203x_device::boot_loader(UINT32 boot_rom_addr)
|
||||
{
|
||||
// read the size of the data
|
||||
UINT32 bits = RMEM(boot_rom_addr);
|
||||
if (bits != 8 && bits != 16 && bits != 32)
|
||||
return 0;
|
||||
UINT32 datamask = 0xffffffffUL >> (32 - bits);
|
||||
UINT32 advance = 32 / bits;
|
||||
boot_rom_addr += advance;
|
||||
|
||||
// read the control register
|
||||
UINT32 control = RMEM(boot_rom_addr++) & datamask;
|
||||
for (int i = 1; i < advance; i++)
|
||||
control |= (RMEM(boot_rom_addr++) & datamask) << (bits * i);
|
||||
|
||||
// now parse the data
|
||||
UINT32 start_offset = 0;
|
||||
bool first = true;
|
||||
while (1)
|
||||
{
|
||||
// read the length of this section
|
||||
UINT32 len = RMEM(boot_rom_addr++) & datamask;
|
||||
for (int i = 1; i < advance; i++)
|
||||
len |= (RMEM(boot_rom_addr++) & datamask) << (bits * i);
|
||||
|
||||
// stop at 0
|
||||
if (len == 0)
|
||||
return start_offset;
|
||||
|
||||
// read the destination offset of this section
|
||||
UINT32 offs = RMEM(boot_rom_addr++) & datamask;
|
||||
for (int i = 1; i < advance; i++)
|
||||
offs |= (RMEM(boot_rom_addr++) & datamask) << (bits * i);
|
||||
|
||||
// if this is the first block, that's where we boot to
|
||||
if (first)
|
||||
{
|
||||
start_offset = offs;
|
||||
first = false;
|
||||
}
|
||||
|
||||
// now copy the data
|
||||
while (len--)
|
||||
{
|
||||
// extract the 32-bit word
|
||||
UINT32 data = RMEM(boot_rom_addr++) & datamask;
|
||||
for (int i = 1; i < advance; i++)
|
||||
data |= (RMEM(boot_rom_addr++) & datamask) << (bits * i);
|
||||
|
||||
// write it out
|
||||
WMEM(offs++, data);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//**************************************************************************
|
||||
// CORE OPCODES
|
||||
//**************************************************************************
|
||||
|
@ -69,6 +69,7 @@ const int TMS3203X_TINT1 = 9; // timer 1 interrupt
|
||||
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
|
||||
|
||||
// register enumeration
|
||||
enum
|
||||
@ -138,7 +139,7 @@ typedef void (*tms3203x_iack_func)(tms3203x_device &device, UINT8 val, offs_t ad
|
||||
|
||||
struct tms3203x_config
|
||||
{
|
||||
UINT32 m_bootoffset;
|
||||
bool m_mcbl_mode;
|
||||
tms3203x_xf_func m_xf0_w;
|
||||
tms3203x_xf_func m_xf1_w;
|
||||
tms3203x_iack_func m_iack_w;
|
||||
@ -201,6 +202,8 @@ protected:
|
||||
virtual void device_start();
|
||||
virtual void device_reset();
|
||||
|
||||
virtual const rom_entry *device_rom_region() const;
|
||||
|
||||
// device_execute_interface overrides
|
||||
virtual UINT32 execute_min_cycles() const;
|
||||
virtual UINT32 execute_max_cycles() const;
|
||||
@ -222,13 +225,13 @@ protected:
|
||||
virtual offs_t disasm_disassemble(char *buffer, offs_t pc, const UINT8 *oprom, const UINT8 *opram, UINT32 options);
|
||||
|
||||
// memory helpers
|
||||
DECLARE_DIRECT_UPDATE_MEMBER(direct_handler);
|
||||
UINT32 ROPCODE(offs_t pc);
|
||||
UINT32 RMEM(offs_t addr);
|
||||
void WMEM(offs_t addr, UINT32 data);
|
||||
|
||||
// misc helpers
|
||||
void check_irqs();
|
||||
UINT32 boot_loader(UINT32 boot_rom_addr);
|
||||
void execute_one();
|
||||
void update_special(int dreg);
|
||||
bool condition(int which);
|
||||
@ -798,7 +801,6 @@ protected:
|
||||
UINT16 m_irq_state;
|
||||
bool m_delayed;
|
||||
bool m_irq_pending;
|
||||
bool m_mcu_mode;
|
||||
bool m_is_idling;
|
||||
int m_icount;
|
||||
|
||||
@ -806,6 +808,7 @@ protected:
|
||||
device_irq_acknowledge_callback m_irq_callback;
|
||||
address_space * m_program;
|
||||
direct_read_data * m_direct;
|
||||
UINT32 * m_bootrom;
|
||||
|
||||
// tables
|
||||
static void (tms3203x_device::*const s_tms32031ops[])(UINT32 op);
|
||||
|
@ -603,6 +603,7 @@ void cage_control_w(running_machine &machine, UINT16 data)
|
||||
if (!(state->control & 3))
|
||||
{
|
||||
state->cpu->set_input_line(INPUT_LINE_RESET, ASSERT_LINE);
|
||||
state->cpu->set_input_line(TMS3203X_IRQ1, ASSERT_LINE);
|
||||
|
||||
state->dma_enabled = 0;
|
||||
state->dma_timer_enabled = 0;
|
||||
@ -619,7 +620,10 @@ void cage_control_w(running_machine &machine, UINT16 data)
|
||||
state->cage_to_cpu_ready = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
state->cpu->set_input_line(INPUT_LINE_RESET, CLEAR_LINE);
|
||||
state->cpu->set_input_line(TMS3203X_IRQ1, CLEAR_LINE);
|
||||
}
|
||||
|
||||
/* update the control state */
|
||||
update_control_lines(machine);
|
||||
@ -651,7 +655,7 @@ static WRITE32_HANDLER( speedup_w )
|
||||
|
||||
static const tms3203x_config cage_config =
|
||||
{
|
||||
0x400000
|
||||
true
|
||||
};
|
||||
|
||||
|
||||
|
@ -980,7 +980,7 @@ static const adsp21xx_config adsp_config =
|
||||
|
||||
static const tms3203x_config tms_config =
|
||||
{
|
||||
0x1000,
|
||||
true,
|
||||
0,
|
||||
0,
|
||||
iack_w
|
||||
|
@ -496,7 +496,7 @@ static ADDRESS_MAP_START( midvunit_map, AS_PROGRAM, 32, midvunit_state )
|
||||
ADDRESS_MAP_END
|
||||
|
||||
|
||||
static const tms3203x_config midvplus_config = { 0, NULL, midvplus_xf1_w };
|
||||
static const tms3203x_config midvplus_config = { false, NULL, midvplus_xf1_w };
|
||||
|
||||
static ADDRESS_MAP_START( midvplus_map, AS_PROGRAM, 32, midvunit_state )
|
||||
AM_RANGE(0x000000, 0x01ffff) AM_RAM AM_SHARE("ram_base")
|
||||
|
Loading…
Reference in New Issue
Block a user