arm7: Flesh out ARM946ES, add movable DTCM and ITCM support. [R. Belmont]

This commit is contained in:
arbee 2017-11-19 17:39:24 -05:00
parent 86366508b4
commit c4b79a2a08
2 changed files with 323 additions and 8 deletions

View File

@ -149,12 +149,23 @@ arm920t_cpu_device::arm920t_cpu_device(const machine_config &mconfig, const char
arm946es_cpu_device::arm946es_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
: arm9_cpu_device(mconfig, ARM946ES, tag, owner, clock, 5, ARCHFLAG_T | ARCHFLAG_E, ENDIANNESS_LITTLE)
: arm9_cpu_device(mconfig, ARM946ES, tag, owner, clock, 5, ARCHFLAG_T | ARCHFLAG_E, ENDIANNESS_LITTLE),
cp15_control(0x78)
{
m_copro_id = ARM9_COPRO_ID_MFR_ARM
| ARM9_COPRO_ID_ARCH_V5TE
| ARM9_COPRO_ID_PART_ARM946
| ARM9_COPRO_ID_STEP_ARM946_A0;
memset(ITCM, 0, 0x8000);
memset(DTCM, 0, 0x4000);
cp15_itcm_base = 0xffffffff;
cp15_itcm_size = 0;
cp15_itcm_end = 0;
cp15_dtcm_base = 0xffffffff;
cp15_dtcm_size = 0;
cp15_dtcm_end = 0;
}
pxa255_cpu_device::pxa255_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock)
@ -1231,6 +1242,291 @@ WRITE32_MEMBER( arm7_cpu_device::arm7_rt_w_callback )
}
}
READ32_MEMBER( arm946es_cpu_device::arm7_rt_r_callback )
{
uint32_t opcode = offset;
uint8_t cReg = ( opcode & INSN_COPRO_CREG ) >> INSN_COPRO_CREG_SHIFT;
uint8_t op2 = ( opcode & INSN_COPRO_OP2 ) >> INSN_COPRO_OP2_SHIFT;
uint8_t op3 = opcode & INSN_COPRO_OP3;
uint8_t cpnum = (opcode & INSN_COPRO_CPNUM) >> INSN_COPRO_CPNUM_SHIFT;
uint32_t data = 0;
//printf("arm7946: read cpnum %d cReg %d op2 %d op3 %d (%x)\n", cpnum, cReg, op2, op3, opcode);
if (cpnum == 15)
{
switch( cReg )
{
case 0:
switch (op2)
{
case 0: // chip ID
data = 0x41059461;
break;
case 1: // cache ID
data = 0x0f0d2112;
break;
case 2: // TCM size
data = (6 << 6) || (5 << 18);
break;
}
break;
case 1:
return cp15_control;
break;
case 9:
if (op3 == 1)
{
if (op2 == 0)
{
return cp15_dtcm_reg;
}
else
{
return cp15_itcm_reg;
}
}
break;
}
}
return data;
}
WRITE32_MEMBER( arm946es_cpu_device::arm7_rt_w_callback )
{
uint32_t opcode = offset;
uint8_t cReg = ( opcode & INSN_COPRO_CREG ) >> INSN_COPRO_CREG_SHIFT;
uint8_t op2 = ( opcode & INSN_COPRO_OP2 ) >> INSN_COPRO_OP2_SHIFT;
uint8_t op3 = opcode & INSN_COPRO_OP3;
uint8_t cpnum = (opcode & INSN_COPRO_CPNUM) >> INSN_COPRO_CPNUM_SHIFT;
// printf("arm7946: copro %d write %x to cReg %d op2 %d op3 %d (mask %08x)\n", cpnum, data, cReg, op2, op3, mem_mask);
if (cpnum == 15)
{
switch (cReg)
{
case 1: // control
cp15_control = data;
RefreshDTCM();
RefreshITCM();
break;
case 2: // Protection Unit cacheability bits
break;
case 3: // write bufferability bits for PU
break;
case 5: // protection unit region controls
break;
case 6: // protection unit region controls 2
break;
case 7: // cache commands
break;
case 9: // cache lockdown & TCM controls
if (op3 == 1)
{
if (op2 == 0)
{
cp15_dtcm_reg = data;
RefreshDTCM();
}
else if (op2 == 1)
{
cp15_itcm_reg = data;
RefreshITCM();
}
}
break;
}
}
}
void arm946es_cpu_device::RefreshDTCM()
{
if (cp15_control & (1<<16))
{
cp15_dtcm_base = (cp15_dtcm_reg & ~0xfff);
cp15_dtcm_size = 512 << ((cp15_dtcm_reg & 0x3f) >> 1);
cp15_dtcm_end = cp15_dtcm_base + cp15_dtcm_size;
//printf("DTCM enabled: base %08x size %x\n", cp15_dtcm_base, cp15_dtcm_size);
}
else
{
cp15_dtcm_base = 0xffffffff;
cp15_dtcm_size = cp15_dtcm_end = 0;
}
}
void arm946es_cpu_device::RefreshITCM()
{
if (cp15_control & (1<<18))
{
cp15_itcm_base = 0; //(cp15_itcm_reg & ~0xfff);
cp15_itcm_size = 512 << ((cp15_itcm_reg & 0x3f) >> 1);
cp15_itcm_end = cp15_itcm_base + cp15_itcm_size;
//printf("ITCM enabled: base %08x size %x\n", cp15_dtcm_base, cp15_dtcm_size);
}
else
{
cp15_itcm_base = 0xffffffff;
cp15_itcm_size = cp15_itcm_end = 0;
}
}
void arm946es_cpu_device::arm7_cpu_write32(uint32_t addr, uint32_t data)
{
addr &= ~3;
if ((addr >= cp15_itcm_base) && (addr <= cp15_itcm_end))
{
uint32_t *wp = (uint32_t *)&ITCM[addr&0x7fff];
*wp = data;
return;
}
else if ((addr >= cp15_dtcm_base) && (addr <= cp15_dtcm_end))
{
uint32_t *wp = (uint32_t *)&DTCM[addr&0x3fff];
*wp = data;
return;
}
m_program->write_dword(addr, data);
}
void arm946es_cpu_device::arm7_cpu_write16(uint32_t addr, uint16_t data)
{
addr &= ~1;
if ((addr >= cp15_itcm_base) && (addr <= cp15_itcm_end))
{
uint16_t *wp = (uint16_t *)&ITCM[addr&0x7fff];
*wp = data;
return;
}
else if ((addr >= cp15_dtcm_base) && (addr <= cp15_dtcm_end))
{
uint16_t *wp = (uint16_t *)&DTCM[addr&0x3fff];
*wp = data;
return;
}
m_program->write_word(addr, data);
}
void arm946es_cpu_device::arm7_cpu_write8(uint32_t addr, uint8_t data)
{
if ((addr >= cp15_itcm_base) && (addr <= cp15_itcm_end))
{
ITCM[addr&0x7fff] = data;
return;
}
else if ((addr >= cp15_dtcm_base) && (addr <= cp15_dtcm_end))
{
DTCM[addr&0x3fff] = data;
return;
}
m_program->write_byte(addr, data);
}
uint32_t arm946es_cpu_device::arm7_cpu_read32(uint32_t addr)
{
uint32_t result;
if ((addr >= cp15_itcm_base) && (addr <= cp15_itcm_end))
{
if (addr & 3)
{
uint32_t *wp = (uint32_t *)&ITCM[(addr & ~3)&0x7fff];
result = *wp;
result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3))));
}
else
{
uint32_t *wp = (uint32_t *)&ITCM[addr&0x7fff];
result = *wp;
}
}
else if ((addr >= cp15_dtcm_base) && (addr <= cp15_dtcm_end))
{
if (addr & 3)
{
uint32_t *wp = (uint32_t *)&DTCM[(addr & ~3)&0x3fff];
result = *wp;
result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3))));
}
else
{
uint32_t *wp = (uint32_t *)&DTCM[addr&0x3fff];
result = *wp;
}
}
else
{
if (addr & 3)
{
result = m_program->read_dword(addr & ~3);
result = (result >> (8 * (addr & 3))) | (result << (32 - (8 * (addr & 3))));
}
else
{
result = m_program->read_dword(addr);
}
}
return result;
}
uint16_t arm946es_cpu_device::arm7_cpu_read16(uint32_t addr)
{
uint16_t result;
if ((addr >= cp15_itcm_base) && (addr <= cp15_itcm_end))
{
uint16_t *wp = (uint16_t *)&ITCM[(addr & ~1)&0x7fff];
result = *wp;
}
else if ((addr >= cp15_dtcm_base) && (addr <= cp15_dtcm_end))
{
uint16_t *wp = (uint16_t *)&DTCM[(addr & ~1)&0x3fff];
result = *wp;
}
else
{
result = m_program->read_word(addr & ~1);
}
if (addr & 1)
{
result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
}
return result;
}
uint8_t arm946es_cpu_device::arm7_cpu_read8(uint32_t addr)
{
if ((addr >= cp15_itcm_base) && (addr <= cp15_itcm_end))
{
return ITCM[addr & 0x7fff];
}
else if ((addr >= cp15_dtcm_base) && (addr <= cp15_dtcm_end))
{
return DTCM[addr & 0x3fff];
}
// Handle through normal 8 bit handler (for 32 bit cpu)
return m_program->read_byte(addr);
}
WRITE32_MEMBER(igs036_cpu_device::arm7_rt_w_callback)
{
arm7_cpu_device::arm7_rt_w_callback(space, offset, data, mem_mask);

View File

@ -231,16 +231,16 @@ protected:
int detect_fault(int desc_lvl1, int ap, int flags);
void arm7_check_irq_state();
void update_irq_state();
void arm7_cpu_write32(uint32_t addr, uint32_t data);
void arm7_cpu_write16(uint32_t addr, uint16_t data);
void arm7_cpu_write8(uint32_t addr, uint8_t data);
uint32_t arm7_cpu_read32(uint32_t addr);
uint16_t arm7_cpu_read16(uint32_t addr);
uint8_t arm7_cpu_read8(uint32_t addr);
virtual void arm7_cpu_write32(uint32_t addr, uint32_t data);
virtual void arm7_cpu_write16(uint32_t addr, uint16_t data);
virtual void arm7_cpu_write8(uint32_t addr, uint8_t data);
virtual uint32_t arm7_cpu_read32(uint32_t addr);
virtual uint16_t arm7_cpu_read16(uint32_t addr);
virtual uint8_t arm7_cpu_read8(uint32_t addr);
// Coprocessor support
DECLARE_WRITE32_MEMBER( arm7_do_callback );
DECLARE_READ32_MEMBER( arm7_rt_r_callback );
virtual DECLARE_READ32_MEMBER( arm7_rt_r_callback );
virtual DECLARE_WRITE32_MEMBER( arm7_rt_w_callback );
void arm7_dt_r_callback(uint32_t insn, uint32_t *prn);
void arm7_dt_w_callback(uint32_t insn, uint32_t *prn);
@ -613,6 +613,25 @@ class arm946es_cpu_device : public arm9_cpu_device
public:
// construction/destruction
arm946es_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock);
// 946E-S has Protection Unit instead of ARM MMU so CP15 is quite different
virtual DECLARE_READ32_MEMBER( arm7_rt_r_callback ) override;
virtual DECLARE_WRITE32_MEMBER( arm7_rt_w_callback ) override;
virtual void arm7_cpu_write32(uint32_t addr, uint32_t data) override;
virtual void arm7_cpu_write16(uint32_t addr, uint16_t data) override;
virtual void arm7_cpu_write8(uint32_t addr, uint8_t data) override;
virtual uint32_t arm7_cpu_read32(uint32_t addr) override;
virtual uint16_t arm7_cpu_read16(uint32_t addr) override;
virtual uint8_t arm7_cpu_read8(uint32_t addr) override;
private:
uint32_t cp15_control, cp15_itcm_base, cp15_dtcm_base, cp15_itcm_size, cp15_dtcm_size;
uint32_t cp15_itcm_end, cp15_dtcm_end, cp15_itcm_reg, cp15_dtcm_reg;
uint8_t ITCM[0x8000], DTCM[0x4000];
void RefreshITCM();
void RefreshDTCM();
};