diff --git a/hash/pico.xml b/hash/pico.xml
index 77e1808613f..00922ecae17 100644
--- a/hash/pico.xml
+++ b/hash/pico.xml
@@ -651,6 +651,19 @@ Published by Others (T-yyy*** serial codes, for yyy depending on the publisher)
+
+ Cooking Pico (Jpn)
+ 1999
+ Sega Toys
+
+
+
+
+
+
+
+
+
Crayola - Create a World (USA)
19??
diff --git a/hash/sawatte.xml b/hash/sawatte.xml
index c72719da411..2d6478edba7 100644
--- a/hash/sawatte.xml
+++ b/hash/sawatte.xml
@@ -17,6 +17,19 @@
+
+ Doraemon Nobita no Dou Butsu Land
+ 1996
+ Sega
+
+
+
+
+
+
+
+
+
Mickey no Kudamonoya-san
1996
@@ -77,7 +90,20 @@
-
+
+ Soreike! Anpanman Onamae Na~ni
+ 1996
+ Sega
+
+
+
+
+
+
+
+
+
+
Tokyo Disneyland - Mickey no Nakayoshi Tankentai
1998
Sega?
@@ -122,4 +148,17 @@
+
+ Ultra Hero Touch
+ 1997
+ Bandai
+
+
+
+
+
+
+
+
+
diff --git a/src/devices/cpu/sh4/sh4.cpp b/src/devices/cpu/sh4/sh4.cpp
index 1d5c69ad483..637929121ec 100644
--- a/src/devices/cpu/sh4/sh4.cpp
+++ b/src/devices/cpu/sh4/sh4.cpp
@@ -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));
diff --git a/src/devices/cpu/sh4/sh4.h b/src/devices/cpu/sh4/sh4.h
index 7531363c2da..2b9d10bfed4 100644
--- a/src/devices/cpu/sh4/sh4.h
+++ b/src/devices/cpu/sh4/sh4.h
@@ -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;
};
diff --git a/src/devices/cpu/sh4/sh4comn.cpp b/src/devices/cpu/sh4/sh4comn.cpp
index 985413e4a73..f02c9f50242 100644
--- a/src/devices/cpu/sh4/sh4comn.cpp
+++ b/src/devices/cpu/sh4/sh4comn.cpp
@@ -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;
+}
\ No newline at end of file
diff --git a/src/mame/drivers/sega_sawatte.cpp b/src/mame/drivers/sega_sawatte.cpp
index 04dd9fa432e..1caec4a2748 100644
--- a/src/mame/drivers/sega_sawatte.cpp
+++ b/src/mame/drivers/sega_sawatte.cpp
@@ -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.