mirror of
https://github.com/holub/mame
synced 2025-04-25 01:40:16 +03:00
begin SH4 MMU improvements (with a view to seeing what mk6 needs)
This commit is contained in:
parent
9b2e44723c
commit
5a942ef207
@ -75,7 +75,11 @@ static ADDRESS_MAP_START( sh4_internal_map, AS_PROGRAM, 64, sh4_base_device )
|
||||
AM_RANGE(0x1C000000, 0x1C000FFF) AM_RAM AM_MIRROR(0x01FFF000)
|
||||
AM_RANGE(0x1E000000, 0x1E000FFF) AM_RAM AM_MIRROR(0x01FFF000)
|
||||
AM_RANGE(0xE0000000, 0xE000003F) AM_RAM AM_MIRROR(0x03FFFFC0) // todo: store queues should be write only on DC's SH4, executing PREFM shouldn't cause an actual memory read access!
|
||||
AM_RANGE(0xF6000000, 0xF7FFFFFF) AM_READWRITE(sh4_tlb_r,sh4_tlb_w)
|
||||
|
||||
AM_RANGE(0xF6000000, 0xF6FFFFFF) AM_READWRITE(sh4_utlb_address_array_r,sh4_utlb_address_array_w)
|
||||
AM_RANGE(0xF7000000, 0xF77FFFFF) AM_READWRITE(sh4_utlb_data_array1_r,sh4_utlb_data_array1_w)
|
||||
AM_RANGE(0xF7800000, 0xF7FFFFFF) AM_READWRITE(sh4_utlb_data_array2_r,sh4_utlb_data_array2_w)
|
||||
|
||||
AM_RANGE(0xFE000000, 0xFFFFFFFF) AM_READWRITE32(sh4_internal_r, sh4_internal_w, 0xffffffffffffffffU)
|
||||
ADDRESS_MAP_END
|
||||
|
||||
@ -180,6 +184,12 @@ void sh34_base_device::TODO(const uint16_t opcode)
|
||||
{
|
||||
}
|
||||
|
||||
void sh34_base_device::LDTLB(const uint16_t opcode)
|
||||
{
|
||||
logerror("unhandled LDTLB\n");
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
int sign_of(int n)
|
||||
{
|
||||
@ -3331,7 +3341,7 @@ inline void sh34_base_device::execute_one_0000(const uint16_t opcode)
|
||||
case 0x08: CLRT(opcode); break;
|
||||
case 0x18: SETT(opcode); break;
|
||||
case 0x28: CLRMAC(opcode); break;
|
||||
case 0x38: TODO(opcode); break;
|
||||
case 0x38: LDTLB(opcode); break;
|
||||
case 0x48: CLRS(opcode); break;
|
||||
case 0x58: SETS(opcode); break;
|
||||
case 0x68: NOP(opcode); break;
|
||||
@ -3339,7 +3349,7 @@ inline void sh34_base_device::execute_one_0000(const uint16_t opcode)
|
||||
case 0x88: CLRT(opcode); break;
|
||||
case 0x98: SETT(opcode); break;
|
||||
case 0xa8: CLRMAC(opcode); break;
|
||||
case 0xb8: TODO(opcode); break;
|
||||
case 0xb8: LDTLB(opcode); break;
|
||||
case 0xc8: CLRS(opcode); break;
|
||||
case 0xd8: SETS(opcode); break;
|
||||
case 0xe8: NOP(opcode); break;
|
||||
@ -4028,6 +4038,47 @@ void sh4be_device::execute_run()
|
||||
} while( m_sh4_icount > 0 );
|
||||
}
|
||||
|
||||
void sh4_base_device::device_start()
|
||||
{
|
||||
sh34_base_device::device_start();
|
||||
|
||||
int i;
|
||||
for (i=0;i<64;i++)
|
||||
{
|
||||
m_utlb[i].ASID = 0;
|
||||
m_utlb[i].VPN = 0;
|
||||
m_utlb[i].V = 0;
|
||||
m_utlb[i].PPN = 0;
|
||||
m_utlb[i].PSZ = 0;
|
||||
m_utlb[i].SH = 0;
|
||||
m_utlb[i].C = 0;
|
||||
m_utlb[i].PPR = 0;
|
||||
m_utlb[i].D = 0;
|
||||
m_utlb[i].WT = 0;
|
||||
m_utlb[i].SA = 0;
|
||||
m_utlb[i].TC = 0;
|
||||
}
|
||||
|
||||
for (i=0;i<64;i++)
|
||||
{
|
||||
save_item(NAME(m_utlb[i].ASID), i);
|
||||
save_item(NAME(m_utlb[i].VPN), i);
|
||||
save_item(NAME(m_utlb[i].V), i);
|
||||
save_item(NAME(m_utlb[i].PPN), i);
|
||||
save_item(NAME(m_utlb[i].PSZ), i);
|
||||
save_item(NAME(m_utlb[i].SH), i);
|
||||
save_item(NAME(m_utlb[i].C), i);
|
||||
save_item(NAME(m_utlb[i].PPR), i);
|
||||
save_item(NAME(m_utlb[i].D), i);
|
||||
save_item(NAME(m_utlb[i].WT), i);
|
||||
save_item(NAME(m_utlb[i].SA), i);
|
||||
save_item(NAME(m_utlb[i].TC), i);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
void sh34_base_device::device_start()
|
||||
{
|
||||
for (int i=0; i<3; i++)
|
||||
@ -4134,8 +4185,6 @@ void sh34_base_device::device_start()
|
||||
save_item(NAME( m_ioport16_direction));
|
||||
save_item(NAME(m_ioport4_pullup));
|
||||
save_item(NAME(m_ioport4_direction));
|
||||
save_item(NAME(m_sh4_tlb_address));
|
||||
save_item(NAME(m_sh4_tlb_data));
|
||||
save_item(NAME(m_sh4_mmu_enabled));
|
||||
save_item(NAME(m_sh3internal_upper));
|
||||
save_item(NAME(m_sh3internal_lower));
|
||||
|
@ -136,6 +136,26 @@ struct sh4_ddt_dma
|
||||
int mode;
|
||||
};
|
||||
|
||||
|
||||
// ASID [7:0] | VPN [31:10] | V | | PPN [28:10] | SZ[1:0] | SH | C | PR[1:0] | D | WT | SA[2:0] | TC
|
||||
|
||||
struct sh4_utlb
|
||||
{
|
||||
uint8_t ASID;
|
||||
uint32_t VPN;
|
||||
uint8_t V;
|
||||
uint32_t PPN;
|
||||
uint8_t PSZ;
|
||||
uint8_t SH;
|
||||
uint8_t C;
|
||||
uint8_t PPR;
|
||||
uint8_t D;
|
||||
uint8_t WT;
|
||||
uint8_t SA;
|
||||
uint8_t TC;
|
||||
};
|
||||
|
||||
|
||||
typedef void (*sh4_ftcsr_callback)(uint32_t);
|
||||
|
||||
|
||||
@ -358,8 +378,6 @@ protected:
|
||||
void (*m_ftcsr_read_callback)(uint32_t data);
|
||||
|
||||
/* This MMU simulation is good for the simple remap used on Naomi GD-ROM SQ access *ONLY* */
|
||||
uint32_t m_sh4_tlb_address[64];
|
||||
uint32_t m_sh4_tlb_data[64];
|
||||
uint8_t m_sh4_mmu_enabled;
|
||||
|
||||
int m_cpu_type;
|
||||
@ -451,6 +469,7 @@ protected:
|
||||
void LDSMMACH(const uint16_t opcode);
|
||||
void LDSMMACL(const uint16_t opcode);
|
||||
void LDSMPR(const uint16_t opcode);
|
||||
void LDTLB(const uint16_t opcode);
|
||||
void MAC_L(const uint16_t opcode);
|
||||
void MAC_W(const uint16_t opcode);
|
||||
void MOV(const uint16_t opcode);
|
||||
@ -627,7 +646,7 @@ protected:
|
||||
void increment_rtc_time(int mode);
|
||||
void sh4_dmac_nmi();
|
||||
void sh4_handler_ipra_w(uint32_t data, uint32_t mem_mask);
|
||||
uint32_t sh4_getsqremap(uint32_t address);
|
||||
virtual uint32_t sh4_getsqremap(uint32_t address);
|
||||
void sh4_parse_configuration();
|
||||
void sh4_timer_recompute(int which);
|
||||
uint32_t sh4_handle_tcnt0_addr_r(uint32_t mem_mask);
|
||||
@ -736,10 +755,18 @@ public:
|
||||
DECLARE_WRITE32_MEMBER( sh4_internal_w );
|
||||
DECLARE_READ32_MEMBER( sh4_internal_r );
|
||||
|
||||
DECLARE_READ64_MEMBER( sh4_tlb_r );
|
||||
DECLARE_WRITE64_MEMBER( sh4_tlb_w );
|
||||
DECLARE_READ64_MEMBER( sh4_utlb_address_array_r );
|
||||
DECLARE_WRITE64_MEMBER( sh4_utlb_address_array_w );
|
||||
DECLARE_READ64_MEMBER( sh4_utlb_data_array1_r );
|
||||
DECLARE_WRITE64_MEMBER( sh4_utlb_data_array1_w );
|
||||
DECLARE_READ64_MEMBER( sh4_utlb_data_array2_r );
|
||||
DECLARE_WRITE64_MEMBER( sh4_utlb_data_array2_w );
|
||||
|
||||
virtual uint32_t sh4_getsqremap(uint32_t address) override;
|
||||
sh4_utlb m_utlb[64];
|
||||
|
||||
protected:
|
||||
virtual void device_start() override;
|
||||
virtual void device_reset() override;
|
||||
};
|
||||
|
||||
|
@ -679,6 +679,8 @@ WRITE32_MEMBER( sh4_base_device::sh4_internal_w )
|
||||
switch( offset )
|
||||
{
|
||||
case MMUCR: // MMU Control
|
||||
logerror("MMUCR %08x\n", data);
|
||||
|
||||
if (data & MMUCR_AT)
|
||||
{
|
||||
printf("SH4 MMU Enabled\n");
|
||||
@ -686,16 +688,7 @@ WRITE32_MEMBER( sh4_base_device::sh4_internal_w )
|
||||
printf("The MMU emulation is a hack specific to that system\n");
|
||||
m_sh4_mmu_enabled = 1;
|
||||
|
||||
// should be a different bit!
|
||||
{
|
||||
int i;
|
||||
for (i=0;i<64;i++)
|
||||
{
|
||||
m_sh4_tlb_address[i] = 0;
|
||||
m_sh4_tlb_data[i] = 0;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1185,6 +1178,11 @@ void sh34_base_device::sh4_parse_configuration()
|
||||
}
|
||||
|
||||
uint32_t sh34_base_device::sh4_getsqremap(uint32_t address)
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
uint32_t sh4_base_device::sh4_getsqremap(uint32_t address)
|
||||
{
|
||||
if (!m_sh4_mmu_enabled)
|
||||
return address;
|
||||
@ -1195,9 +1193,9 @@ uint32_t sh34_base_device::sh4_getsqremap(uint32_t address)
|
||||
|
||||
for (i=0;i<64;i++)
|
||||
{
|
||||
uint32_t topcmp = m_sh4_tlb_address[i]&0xfff00000;
|
||||
uint32_t topcmp = (m_utlb[i].VPN<<10)&0xfff00000;
|
||||
if (topcmp==topaddr)
|
||||
return (address&0x000fffff) | ((m_sh4_tlb_data[i])&0xfff00000);
|
||||
return (address&0x000fffff) | ((m_utlb[i].PPN<<10)&0xfff00000);
|
||||
}
|
||||
|
||||
}
|
||||
@ -1205,34 +1203,147 @@ uint32_t sh34_base_device::sh4_getsqremap(uint32_t address)
|
||||
return address;
|
||||
}
|
||||
|
||||
READ64_MEMBER( sh4_base_device::sh4_tlb_r )
|
||||
{
|
||||
int offs = offset*8;
|
||||
|
||||
if (offs >= 0x01000000)
|
||||
WRITE64_MEMBER( sh4_base_device::sh4_utlb_address_array_w )
|
||||
{
|
||||
/* uses bits 13:8 of address to select which UTLB entry we're addressing
|
||||
bit 7 of the address enables 'associative' mode, causing a search
|
||||
operation rather than a direct write.
|
||||
|
||||
NNNN NNNN NNNN NNNN NNNN NNDV AAAA AAAA
|
||||
|
||||
N = VPM = Virtual Page Number
|
||||
D = Dirty Bit
|
||||
V = Validity Bit
|
||||
A = ASID = Address Space Identifier
|
||||
*/
|
||||
|
||||
logerror("sh4_utlb_address_array_w %08x %08x\n", offset, data);
|
||||
int offs = offset << 3;
|
||||
|
||||
uint8_t associative = (offs >> 7) & 1;
|
||||
|
||||
if (!associative)
|
||||
{
|
||||
uint8_t i = (offs>>8)&63;
|
||||
return m_sh4_tlb_data[i];
|
||||
// non-associative mode
|
||||
uint8_t i = (offs >> 8) & 63;
|
||||
|
||||
m_utlb[i].VPN = (data & 0xfffffc00) >> 10;
|
||||
m_utlb[i].D = (data & 0x00000200) >> 9;
|
||||
m_utlb[i].V = (data & 0x00000100) >> 8;
|
||||
m_utlb[i].ASID = (data & 0x000000ff) >> 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t i = (offs>>8)&63;
|
||||
return m_sh4_tlb_address[i];
|
||||
// associative mode
|
||||
fatalerror("SH4MMU: associative mode writes unsupported\n");
|
||||
}
|
||||
}
|
||||
|
||||
WRITE64_MEMBER( sh4_base_device::sh4_tlb_w )
|
||||
READ64_MEMBER( sh4_base_device::sh4_utlb_address_array_r )
|
||||
{
|
||||
// associative bit is ignored for reads
|
||||
int offs = offset*8;
|
||||
|
||||
if (offs >= 0x01000000)
|
||||
{
|
||||
uint8_t i = (offs>>8)&63;
|
||||
m_sh4_tlb_data[i] = data&0xffffffff;
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t i = (offs>>8)&63;
|
||||
m_sh4_tlb_address[i] = data&0xffffffff;
|
||||
}
|
||||
uint32_t ret = 0;
|
||||
|
||||
uint8_t i = (offs >> 8) & 63;
|
||||
|
||||
ret |= m_utlb[i].VPN << 10;
|
||||
ret |= m_utlb[i].D << 9;
|
||||
ret |= m_utlb[i].V << 8;
|
||||
ret |= m_utlb[i].ASID << 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
WRITE64_MEMBER( sh4_base_device::sh4_utlb_data_array1_w )
|
||||
{
|
||||
/* uses bits 13:8 of address to select which UTLB entry we're addressing
|
||||
|
||||
---P PPPP PPPP PPPP PPPP PP-V zRRz CDHW
|
||||
|
||||
P = PPN = Physical page number
|
||||
V = Validity bit
|
||||
z = SZ = Page Size (2 bits, split)
|
||||
D = Dirty Bit
|
||||
R = PR = Protection Key Data
|
||||
C = Cacheable bit
|
||||
H = Share status
|
||||
W = Write through
|
||||
- = unused (should be 0)
|
||||
*/
|
||||
logerror("sh4_utlb_data_array1_w %08x %08x\n", offset, data);
|
||||
int offs = offset*8;
|
||||
|
||||
uint8_t i = (offs>>8)&63;
|
||||
|
||||
m_utlb[i].PPN = (data & 0x1ffffc00) >> 10;
|
||||
m_utlb[i].V = (data & 0x00000100) >> 8;
|
||||
m_utlb[i].PSZ = (data & 0x00000080) >> 6;
|
||||
m_utlb[i].PSZ |=(data & 0x00000010) >> 4;
|
||||
m_utlb[i].PPR= (data & 0x00000060) >> 5;
|
||||
m_utlb[i].C = (data & 0x00000008) >> 3;
|
||||
m_utlb[i].D = (data & 0x00000004) >> 2;
|
||||
m_utlb[i].SH = (data & 0x00000002) >> 1;
|
||||
m_utlb[i].WT = (data & 0x00000001) >> 0;
|
||||
}
|
||||
|
||||
|
||||
READ64_MEMBER(sh4_base_device::sh4_utlb_data_array1_r)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
int offs = offset*8;
|
||||
|
||||
uint8_t i = (offs>>8)&63;
|
||||
|
||||
ret |= m_utlb[i].PPN << 10;
|
||||
ret |= m_utlb[i].V << 8;
|
||||
ret |= (m_utlb[i].PSZ & 2) << 6;
|
||||
ret |= (m_utlb[i].PSZ & 1) << 4;
|
||||
ret |= m_utlb[i].PPR << 5;
|
||||
ret |= m_utlb[i].C << 3;
|
||||
ret |= m_utlb[i].D << 2;
|
||||
ret |= m_utlb[i].SH << 1;
|
||||
ret |= m_utlb[i].WT << 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
WRITE64_MEMBER( sh4_base_device::sh4_utlb_data_array2_w )
|
||||
{
|
||||
/* uses bits 13:8 of address to select which UTLB entry we're addressing
|
||||
|
||||
---- ---- ---- ---- ---- ---- ---- TSSS
|
||||
|
||||
T = TC = Timing Control
|
||||
S = SA = Space attributes
|
||||
- = unused (should be 0)
|
||||
|
||||
*/
|
||||
|
||||
logerror("sh4_utlb_data_array2_w %08x %08x\n", offset, data);
|
||||
int offs = offset*8;
|
||||
|
||||
uint8_t i = (offs>>8)&63;
|
||||
|
||||
m_utlb[i].TC = (data & 0x00000008) >> 3;
|
||||
m_utlb[i].SA = (data & 0x00000007) >> 0;
|
||||
}
|
||||
|
||||
|
||||
READ64_MEMBER(sh4_base_device::sh4_utlb_data_array2_r)
|
||||
{
|
||||
uint32_t ret = 0;
|
||||
int offs = offset*8;
|
||||
|
||||
uint8_t i = (offs>>8)&63;
|
||||
|
||||
ret |= m_utlb[i].TC << 3;
|
||||
ret |= m_utlb[i].SA << 0;
|
||||
|
||||
return ret;
|
||||
}
|
Loading…
Reference in New Issue
Block a user