Merge pull request #1761 from mamehaze/mk6

begin SH4 MMU improvements (with a view to seeing what mk6 needs)
This commit is contained in:
MetalliC 2016-11-24 02:33:33 +02:00 committed by GitHub
commit 2a590ad3c9
6 changed files with 355 additions and 43 deletions

View File

@ -651,6 +651,19 @@ Published by Others (T-yyy*** serial codes, for yyy depending on the publisher)
</part>
</software>
<software name="cookpico">
<description>Cooking Pico (Jpn)</description>
<year>1999</year>
<publisher>Sega Toys</publisher>
<part name="cart" interface="pico_cart">
<feature name="pcb" value="171-7967" />
<feature name="ic1" value="9K0-0001A-RV" />
<dataarea name="rom" size="2097152">
<rom name="9k0-0001a-rv.ic1" size="2097152" crc="b94f7d54" sha1="dabeb440adbb7477cc880c51fb0cfc1e5f99d23b" offset="000000" loadflag="load16_word_swap" />
</dataarea>
</part>
</software>
<software name="crayola">
<description>Crayola - Create a World (USA)</description>
<year>19??</year>

View File

@ -17,6 +17,19 @@
</part>
</software>
<software name="doraedbl">
<description>Doraemon Nobita no Dou Butsu Land</description>
<year>1996</year>
<publisher>Sega</publisher>
<part name="cart" interface="sawatte_cart">
<feature name="pcb" value="171-7323A" />
<feature name="ic1" value="MPR-19040" />
<dataarea name="rom" size="524288">
<rom name="mpr-19040.ic1" size="524288" crc="0c9bae2f" sha1="bc5030fab99e8f4b1bcc8ed77c1cc07d8407df93" offset="0" />
</dataarea>
</part>
</software>
<software name="mickkuda">
<description>Mickey no Kudamonoya-san</description>
<year>1996</year>
@ -77,7 +90,20 @@
</part>
</software>
<software name="micknatk">
<software name="soreike">
<description>Soreike! Anpanman Onamae Na~ni</description>
<year>1996</year>
<publisher>Sega</publisher>
<part name="cart" interface="sawatte_cart">
<feature name="pcb" value="171-7323A" />
<feature name="ic1" value="MPR-19041" />
<dataarea name="rom" size="524288">
<rom name="mpr-19041.ic1" size="524288" crc="ec924165" sha1="b25a5637c8cc1f2f6224595853d540195be86ec9" offset="0" />
</dataarea>
</part>
</software>
<software name="micknatk">
<description>Tokyo Disneyland - Mickey no Nakayoshi Tankentai</description>
<year>1998</year>
<publisher>Sega?</publisher>
@ -122,4 +148,17 @@
</part>
</software>
<software name="uht">
<description>Ultra Hero Touch</description>
<year>1997</year>
<publisher>Bandai</publisher>
<part name="cart" interface="sawatte_cart">
<feature name="pcb" value="171-7323A" />
<feature name="ic1" value="MPR-19828-T" />
<dataarea name="rom" size="524288">
<rom name="mpr-19828-t.ic1" size="524288" crc="57988dc7" sha1="438a35b2a46ec82b5e31478d9e244928f98891ab" offset="0" />
</dataarea>
</part>
</software>
</softwarelist>

View File

@ -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,37 @@ void sh34_base_device::TODO(const uint16_t opcode)
{
}
void sh34_base_device::LDTLB(const uint16_t opcode)
{
logerror("unhandled LDTLB for this CPU type\n");
}
void sh4_base_device::LDTLB(const uint16_t opcode)
{
int replace = (m_m[MMUCR] & 0x0000fc00) >> 10;
logerror("using LDTLB to replace UTLB entry %02x\n", replace);
// these come from PTEH
m_utlb[replace].VPN = (m_m[PTEH] & 0xfffffc00) >> 10;
// m_utlb[replace].D = (m_m[PTEH] & 0x00000200) >> 9; // from PTEL
// m_utlb[replace].V = (m_m[PTEH] & 0x00000100) >> 8; // from PTEL
m_utlb[replace].ASID = (m_m[PTEH] & 0x000000ff) >> 0;
// these come from PTEL
m_utlb[replace].PPN = (m_m[PTEL] & 0x1ffffc00) >> 10;
m_utlb[replace].V = (m_m[PTEL] & 0x00000100) >> 8;
m_utlb[replace].PSZ = (m_m[PTEL] & 0x00000080) >> 6;
m_utlb[replace].PSZ |=(m_m[PTEL] & 0x00000010) >> 4;
m_utlb[replace].PPR= (m_m[PTEL] & 0x00000060) >> 5;
m_utlb[replace].C = (m_m[PTEL] & 0x00000008) >> 3;
m_utlb[replace].D = (m_m[PTEL] & 0x00000004) >> 2;
m_utlb[replace].SH = (m_m[PTEL] & 0x00000002) >> 1;
m_utlb[replace].WT = (m_m[PTEL] & 0x00000001) >> 0;
// these come from PTEA
m_utlb[replace].TC = (m_m[PTEA] & 0x00000008) >> 3;
m_utlb[replace].SA = (m_m[PTEA] & 0x00000007) >> 0;
}
#if 0
int sign_of(int n)
{
@ -3331,7 +3366,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 +3374,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 +4063,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 +4210,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));

View File

@ -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);
virtual 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,20 @@ 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 void LDTLB(const uint16_t opcode) override;
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;
};

View File

@ -676,9 +676,57 @@ WRITE32_MEMBER( sh4_base_device::sh4_internal_w )
// printf("sh4_internal_w: Write %08x (%x), %08x @ %08x\n", 0xfe000000+((offset & 0x3fc0) << 11)+((offset & 0x3f) << 2), offset, data, mem_mask);
switch( offset )
switch( offset )
{
case PTEH: // for use with LDTLB opcode
m_m[PTEH] &= 0xffffffff;
/*
NNNN NNNN NNNN NNNN NNNN NN-- AAAA AAAA
N = VPM = Virtual Page Number
A = ASID = Address Space Identifier
same as the address table part of the utlb but with 2 unused bits (these are sourced from PTEL instead when LDTLB is called)
*/
break;
case PTEL:
m_m[PTEL] &= 0xffffffff;
/*
---P PPPP PPPP PPPP PPPP PP-V zRRz CDHW
same format as data array 1 of the utlb
*/
break;
case PTEA:
m_m[PTEA] &= 0xffffffff;
/*
---- ---- ---- ---- ---- ---- ---- TSSS
same format as data array 2 of the utlb
*/
break;
case MMUCR: // MMU Control
logerror("MMUCR %08x\n", data);
m_m[MMUCR] &= 0xffffffff;
/*
LLLL LL-- BBBB BB-- CCCC CCQV ---- -T-A
L = LRUI = Least recently used ITLB
B = URB = UTLB replace boundary
C = URC = UTLB replace counter
Q = SQMD = Store Queue Mode Bit
V = SV = Single Virtual Mode Bit
T = TI = TLB invaldiate
A = AT = Address translation bit (enable)
*/
if (data & MMUCR_AT)
{
printf("SH4 MMU Enabled\n");
@ -686,16 +734,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 +1224,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 +1239,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 +1249,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;
}

View File

@ -5,7 +5,7 @@
a sound-only Pico type system (one of the boards even says S-PICO)
CPU is unknown (I can't see one?!) cartridge dumps should be good, but not confirmed, might be data only for an MCU?
CPU is unknown (I can't see one?! MCU with internal ROM?) cartridge dumps have been tested as working using a flash cart.
driver does nothing except allow the softlist to be connected to the -romident commands etc.