diff --git a/pcsx2/Cache.cpp b/pcsx2/Cache.cpp index 280a0b0742..e205255ab6 100644 --- a/pcsx2/Cache.cpp +++ b/pcsx2/Cache.cpp @@ -40,14 +40,15 @@ const u32 VALID_FLAG = 0x20; const u32 LRF_FLAG = 0x10; const u32 LOCK_FLAG = 0x8; +// TODO: You can't assume the vtlb entry is in both states at once! + int getFreeCache(u32 mem, int mode, int * way) { int number = 0; const int i = (mem >> 6) & 0x3F; - const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; - s32 ppf = mem + vmv; - const u32 hand = (u8)vmv; - const u32 paddr = ppf - hand + 0x80000000; + const auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; + uptr ppf = vmv.assumePtr(mem); + const u32 paddr = vmv.assumeHandlerGetPAddr(mem); if((cpuRegs.CP0.n.Config & 0x10000) == 0) CACHE_LOG("Cache off!"); @@ -112,9 +113,8 @@ void writeCache8(u32 mem, u8 value) if (i == -1) { - const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; - s32 ppf = mem + vmv; - *reinterpret_cast(ppf) = value; + auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; + *reinterpret_cast(vmv.assumePtr(mem)) = value; return; } @@ -130,9 +130,8 @@ void writeCache16(u32 mem, u16 value) if (i == -1) { - const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; - s32 ppf = mem + vmv; - *reinterpret_cast(ppf) = value; + auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; + *reinterpret_cast(vmv.assumePtr(mem)) = value; return; } @@ -148,9 +147,8 @@ void writeCache32(u32 mem, u32 value) if (i == -1) { - const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; - s32 ppf = mem + vmv; - *reinterpret_cast(ppf) = value; + auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; + *reinterpret_cast(vmv.assumePtr(mem)) = value; return; } @@ -166,9 +164,8 @@ void writeCache64(u32 mem, const u64 value) if (i == -1) { - const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; - s32 ppf = mem + vmv; - *reinterpret_cast(ppf) = value; + auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; + *reinterpret_cast(vmv.assumePtr(mem)) = value; return; } @@ -184,10 +181,10 @@ void writeCache128(u32 mem, const mem128_t* value) if (i == -1) { - const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; - s32 ppf = mem + vmv; - *reinterpret_cast(ppf) = value->lo; - *reinterpret_cast(ppf+8) = value->hi; + auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; + auto ptr = reinterpret_cast(vmv.assumePtr(mem)); + ptr[0] = value->lo; + ptr[1] = value->hi; return; } @@ -204,9 +201,8 @@ u8 readCache8(u32 mem) if (i == -1) { - const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; - s32 ppf = mem + vmv; - return *reinterpret_cast(ppf); + auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; + return *reinterpret_cast(vmv.assumePtr(mem)); } CACHE_LOG("readCache %8.8x from %d, way %d QW %x u8 part %x Really Reading %x", mem, i, number, (mem >> 4) & 0x3, (mem & 0xf) >> 2, (u32)pCache[i].data[number][(mem >> 4) & 0x3].b8._u8[(mem & 0xf)]); @@ -220,9 +216,8 @@ u16 readCache16(u32 mem) if (i == -1) { - const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; - s32 ppf = mem + vmv; - return *reinterpret_cast(ppf); + auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; + return *reinterpret_cast(vmv.assumePtr(mem)); } CACHE_LOG("readCache %8.8x from %d, way %d QW %x u16 part %x Really Reading %x", mem, i, number, (mem >> 4) & 0x3, (mem & 0xf) >> 2, (u32)pCache[i].data[number][(mem >> 4) & 0x3].b8._u16[(mem & 0xf) >> 1]); @@ -236,9 +231,8 @@ u32 readCache32(u32 mem) if (i == -1) { - const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; - s32 ppf = mem + vmv; - return *reinterpret_cast(ppf); + auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; + return *reinterpret_cast(vmv.assumePtr(mem)); } CACHE_LOG("readCache %8.8x from %d, way %d QW %x u32 part %x Really Reading %x", mem, i, number, (mem >> 4) & 0x3, (mem & 0xf) >> 2, (u32)pCache[i].data[number][(mem >> 4) & 0x3].b8._u32[(mem & 0xf) >> 2]); @@ -252,9 +246,8 @@ u64 readCache64(u32 mem) if (i == -1) { - u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; - s32 ppf=mem + vmv; - return *reinterpret_cast(ppf); + auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; + return *reinterpret_cast(vmv.assumePtr(mem)); } CACHE_LOG("readCache %8.8x from %d, way %d QW %x u64 part %x Really Reading %x_%x", mem, i, number, (mem >> 4) & 0x3, (mem & 0xf) >> 2, pCache[i].data[number][(mem >> 4) & 0x3].b8._u64[(mem & 0xf) >> 3]); @@ -297,10 +290,8 @@ void CACHE() const int index = (addr >> 6) & 0x3F; int way = 0; const u32 pfnaddr = addr; - const u32 vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; - const s32 ppf = pfnaddr + vmv; - const u32 hand = (u8)vmv; - const u32 paddr = ppf - hand + 0x80000000; + const auto vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; + const u32 paddr = vmv.assumeHandlerGetPAddr(pfnaddr); if ((paddr & ~0xFFF) == (pCache[index].tag[0] & ~0xfff) && (pCache[index].tag[0] & VALID_FLAG)) { @@ -327,10 +318,9 @@ void CACHE() const int index = (addr >> 6) & 0x3F; int way = 0; const u32 pfnaddr = addr; - const u32 vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; - s32 ppf = (pfnaddr + vmv) & ~0x3F; - const u32 hand = (u8)vmv; - const u32 paddr = ppf - hand + 0x80000000; + const auto vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; + uptr ppf = vmv.assumePtr(pfnaddr) & ~0x3F; + const u32 paddr = vmv.assumeHandlerGetPAddr(pfnaddr) & ~0x3f; if ((pCache[index].tag[0] & ~0xFFF) == (paddr & ~0xFFF) && (pCache[index].tag[0] & VALID_FLAG)) { @@ -371,10 +361,9 @@ void CACHE() const int index = (addr >> 6) & 0x3F; int way = 0; const u32 pfnaddr = (pCache[index].tag[way] & ~0x80000fff) | (addr & 0xfc0); - const u32 vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; - s32 ppf = (pfnaddr + vmv) & ~0x3F; - const u32 hand = (u8)vmv; - const u32 paddr = ppf - hand + 0x80000000; + const auto vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; + uptr ppf = vmv.assumePtr(pfnaddr); + const u32 paddr = vmv.assumeHandlerGetPAddr(pfnaddr); CACHE_LOG("CACHE DHWOIN addr %x, index %d, way %d, Flags %x OP %x", addr, index, way, pCache[index].tag[way] & 0x78, cpuRegs.code); @@ -439,8 +428,8 @@ void CACHE() //DXLTG demands that SYNC.L is called before this command, which forces the cache to write back, so presumably games are checking the cache has updated the memory //For speed, we will do it here. const u32 pfnaddr = (pCache[index].tag[way] & ~0x80000fff) | (addr & 0xfc0); - const u32 vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; - s32 ppf = (pfnaddr + vmv) & ~0x3F; + const auto vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; + s32 ppf = vmv.assumePtr(pfnaddr); if ((pCache[index].tag[way] & (DIRTY_FLAG | VALID_FLAG)) == (DIRTY_FLAG | VALID_FLAG)) // Dirty { @@ -489,10 +478,9 @@ void CACHE() const int index = (addr >> 6) & 0x3F; const int way = addr & 0x1; const u32 pfnaddr = (pCache[index].tag[way] & ~0x80000fff) + (addr & 0xFC0); - const u32 vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; - s32 ppf = pfnaddr + vmv; - const u32 hand = (u8)vmv; - const u32 paddr = ppf - hand + 0x80000000; + const auto vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; + s32 ppf = vmv.assumePtr(pfnaddr); + const u32 paddr = vmv.assumeHandlerGetPAddr(pfnaddr); CACHE_LOG("CACHE DXWBIN addr %x, index %d, way %d, Flags %x Paddr %x tag %x", addr, index, way, pCache[index].tag[way] & 0x78, paddr, pCache[index].tag[way]); if ((pCache[index].tag[way] & (DIRTY_FLAG|VALID_FLAG)) == (DIRTY_FLAG|VALID_FLAG)) // Dirty diff --git a/pcsx2/vtlb.cpp b/pcsx2/vtlb.cpp index 2bcdb0024e..3d3b9c57fe 100644 --- a/pcsx2/vtlb.cpp +++ b/pcsx2/vtlb.cpp @@ -56,6 +56,26 @@ static vtlbHandler UnmappedVirtHandler1; static vtlbHandler UnmappedPhyHandler0; static vtlbHandler UnmappedPhyHandler1; +vtlb_private::VTLBPhysical vtlb_private::VTLBPhysical::fromPointer(sptr ptr) { + pxAssertMsg(ptr >= 0, "Address too high"); + return VTLBPhysical(ptr); +} + +vtlb_private::VTLBPhysical vtlb_private::VTLBPhysical::fromHandler(vtlbHandler handler) { + return VTLBPhysical(handler | POINTER_SIGN_BIT); +} + +vtlb_private::VTLBVirtual::VTLBVirtual(VTLBPhysical phys, u32 paddr, u32 vaddr) { + pxAssertMsg(0 == (paddr & VTLB_PAGE_MASK), "Should be page aligned"); + pxAssertMsg(0 == (vaddr & VTLB_PAGE_MASK), "Should be page aligned"); + pxAssertMsg((uptr)paddr < POINTER_SIGN_BIT, "Address too high"); + if (phys.isHandler()) { + value = phys.raw() + paddr - vaddr; + } else { + value = phys.raw() - vaddr; + } +} + __inline int CheckCache(u32 addr) { u32 mask; @@ -96,10 +116,9 @@ template< typename DataType > DataType __fastcall vtlb_memRead(u32 addr) { static const uint DataSize = sizeof(DataType) * 8; - uptr vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS]; - sptr ppf=addr+vmv; + auto vmv = vtlbdata.vmap[addr>>VTLB_PAGE_BITS]; - if (!(ppf<0)) + if (!vmv.isHandler(addr)) { if (!CHECK_EEREC) { @@ -122,26 +141,22 @@ DataType __fastcall vtlb_memRead(u32 addr) } } - return *reinterpret_cast(ppf); + return *reinterpret_cast(vmv.assumePtr(addr)); } //has to: translate, find function, call function - u32 hand=(u8)vmv; - u32 paddr=ppf-hand+0x80000000; + u32 paddr=vmv.assumeHandlerGetPAddr(addr); //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr); //return reinterpret_cast::HandlerType*>(vtlbdata.RWFT[TemplateHelper::sidx][0][hand])(paddr,data); switch( DataSize ) { - case 8: - - return ((vtlbMemR8FP*)vtlbdata.RWFT[0][0][hand])(paddr); - case 16: - - return ((vtlbMemR16FP*)vtlbdata.RWFT[1][0][hand])(paddr); - case 32: - - return ((vtlbMemR32FP*)vtlbdata.RWFT[2][0][hand])(paddr); + case 8: + return vmv.assumeHandler< 8, false>()(paddr); + case 16: + return vmv.assumeHandler<16, false>()(paddr); + case 32: + return vmv.assumeHandler<32, false>()(paddr); jNO_DEFAULT; } @@ -151,10 +166,9 @@ DataType __fastcall vtlb_memRead(u32 addr) void __fastcall vtlb_memRead64(u32 mem, mem64_t *out) { - uptr vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS]; - sptr ppf=mem+vmv; + auto vmv = vtlbdata.vmap[mem>>VTLB_PAGE_BITS]; - if (!(ppf<0)) + if (!vmv.isHandler(mem)) { if (!CHECK_EEREC) { if(CHECK_CACHE && CheckCache(mem)) @@ -164,24 +178,21 @@ void __fastcall vtlb_memRead64(u32 mem, mem64_t *out) } } - *out = *(mem64_t*)ppf; + *out = *(mem64_t*)vmv.assumePtr(mem); } else { //has to: translate, find function, call function - u32 hand=(u8)vmv; - u32 paddr=ppf-hand+0x80000000; + u32 paddr = vmv.assumeHandlerGetPAddr(mem); //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr); - - ((vtlbMemR64FP*)vtlbdata.RWFT[3][0][hand])(paddr, out); + vmv.assumeHandler<64, false>()(paddr, out); } } void __fastcall vtlb_memRead128(u32 mem, mem128_t *out) { - uptr vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS]; - sptr ppf=mem+vmv; + auto vmv = vtlbdata.vmap[mem>>VTLB_PAGE_BITS]; - if (!(ppf<0)) + if (!vmv.isHandler(mem)) { if (!CHECK_EEREC) { @@ -193,16 +204,14 @@ void __fastcall vtlb_memRead128(u32 mem, mem128_t *out) } } - CopyQWC(out,(void*)ppf); + CopyQWC(out,(void*)vmv.assumePtr(mem)); } else { //has to: translate, find function, call function - u32 hand=(u8)vmv; - u32 paddr=ppf-hand+0x80000000; + u32 paddr = vmv.assumeHandlerGetPAddr(mem); //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr); - - ((vtlbMemR128FP*)vtlbdata.RWFT[4][0][hand])(paddr, out); + vmv.assumeHandler<128, false>()(paddr, out); } } @@ -211,9 +220,9 @@ void __fastcall vtlb_memWrite(u32 addr, DataType data) { static const uint DataSize = sizeof(DataType) * 8; - uptr vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS]; - sptr ppf=addr+vmv; - if (!(ppf<0)) + auto vmv = vtlbdata.vmap[addr>>VTLB_PAGE_BITS]; + + if (!vmv.isHandler(addr)) { if (!CHECK_EEREC) { @@ -234,34 +243,22 @@ void __fastcall vtlb_memWrite(u32 addr, DataType data) } } - *reinterpret_cast(ppf)=data; + *reinterpret_cast(vmv.assumePtr(addr))=data; } else { //has to: translate, find function, call function - u32 hand=(u8)vmv; - u32 paddr=ppf-hand+0x80000000; + u32 paddr = vmv.assumeHandlerGetPAddr(addr); //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr); - - switch( DataSize ) - { - case 8: - return ((vtlbMemW8FP*)vtlbdata.RWFT[0][1][hand])(paddr, (u8)data); - case 16: - return ((vtlbMemW16FP*)vtlbdata.RWFT[1][1][hand])(paddr, (u16)data); - case 32: - return ((vtlbMemW32FP*)vtlbdata.RWFT[2][1][hand])(paddr, (u32)data); - - jNO_DEFAULT; - } + return vmv.assumeHandler()(paddr, data); } } void __fastcall vtlb_memWrite64(u32 mem, const mem64_t* value) { - uptr vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS]; - sptr ppf=mem+vmv; - if (!(ppf<0)) + auto vmv = vtlbdata.vmap[mem>>VTLB_PAGE_BITS]; + + if (!vmv.isHandler(mem)) { if (!CHECK_EEREC) { @@ -272,24 +269,23 @@ void __fastcall vtlb_memWrite64(u32 mem, const mem64_t* value) } } - *(mem64_t*)ppf = *value; + *(mem64_t*)vmv.assumePtr(mem) = *value; } else { //has to: translate, find function, call function - u32 hand=(u8)vmv; - u32 paddr=ppf-hand+0x80000000; + u32 paddr = vmv.assumeHandlerGetPAddr(mem); //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr); - ((vtlbMemW64FP*)vtlbdata.RWFT[3][1][hand])(paddr, value); + vmv.assumeHandler<64, true>()(paddr, value); } } void __fastcall vtlb_memWrite128(u32 mem, const mem128_t *value) { - uptr vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS]; - sptr ppf=mem+vmv; - if (!(ppf<0)) + auto vmv = vtlbdata.vmap[mem>>VTLB_PAGE_BITS]; + + if (!vmv.isHandler(mem)) { if (!CHECK_EEREC) { @@ -300,16 +296,15 @@ void __fastcall vtlb_memWrite128(u32 mem, const mem128_t *value) } } - CopyQWC((void*)ppf, value); + CopyQWC((void*)vmv.assumePtr(mem), value); } else { //has to: translate, find function, call function - u32 hand=(u8)vmv; - u32 paddr=ppf-hand+0x80000000; + u32 paddr = vmv.assumeHandlerGetPAddr(mem); //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr); - ((vtlbMemW128FP*)vtlbdata.RWFT[4][1][hand])(paddr, value); + vmv.assumeHandler<128, true>()(paddr, value); } } @@ -357,7 +352,10 @@ void __fastcall GoemonPreloadTlb() u32 vaddr = tlb[i].low_add; u32 paddr = tlb[i].physical_add; - if ((uptr)vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] == POINTER_SIGN_BIT) { + // TODO: The old code (commented below) seems to check specifically for handler 0. Is this really correct? + //if ((uptr)vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] == POINTER_SIGN_BIT) { + auto vmv = vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS]; + if (vmv.isHandler(vaddr) && vmv.assumeHandlerGetID() == 0) { DevCon.WriteLn("GoemonPreloadTlb: Entry %d. Key %x. From V:0x%8.8x to P:0x%8.8x (%d pages)", i, tlb[i].key, vaddr, paddr, size >> VTLB_PAGE_BITS); vtlb_VMap( vaddr , paddr, size); vtlb_VMap(0x20000000|vaddr , paddr, size); @@ -588,13 +586,12 @@ void vtlb_MapHandler(vtlbHandler handler, u32 start, u32 size) verify(0==(start&VTLB_PAGE_MASK)); verify(0==(size&VTLB_PAGE_MASK) && size>0); - s32 value = handler | 0x80000000; u32 end = start + (size - VTLB_PAGE_SIZE); pxAssume( (end>>VTLB_PAGE_BITS) < ArraySize(vtlbdata.pmap) ); while (start <= end) { - vtlbdata.pmap[start>>VTLB_PAGE_BITS] = value; + vtlbdata.pmap[start>>VTLB_PAGE_BITS] = VTLBPhysical::fromHandler(handler); start += VTLB_PAGE_SIZE; } } @@ -619,7 +616,7 @@ void vtlb_MapBlock(void* base, u32 start, u32 size, u32 blocksize) while (loopsz > 0) { - vtlbdata.pmap[start>>VTLB_PAGE_BITS] = ptr; + vtlbdata.pmap[start>>VTLB_PAGE_BITS] = VTLBPhysical::fromPointer(ptr); start += VTLB_PAGE_SIZE; ptr += VTLB_PAGE_SIZE; @@ -648,10 +645,10 @@ void vtlb_Mirror(u32 new_region,u32 start,u32 size) __fi void* vtlb_GetPhyPtr(u32 paddr) { - if (paddr>=VTLB_PMAP_SZ || vtlbdata.pmap[paddr>>VTLB_PAGE_BITS]<0) + if (paddr>=VTLB_PMAP_SZ || vtlbdata.pmap[paddr>>VTLB_PAGE_BITS].isHandler()) return NULL; else - return reinterpret_cast(vtlbdata.pmap[paddr>>VTLB_PAGE_BITS]+(paddr&VTLB_PAGE_MASK)); + return reinterpret_cast(vtlbdata.pmap[paddr>>VTLB_PAGE_BITS].assumePtr()+(paddr&VTLB_PAGE_MASK)); } __fi u32 vtlb_V2P(u32 vaddr) @@ -671,23 +668,18 @@ void vtlb_VMap(u32 vaddr,u32 paddr,u32 size) while (size > 0) { - sptr pme; - if (paddr >= VTLB_PMAP_SZ) - { - pme = UnmappedPhyHandler0; - if (paddr & POINTER_SIGN_BIT) - pme = UnmappedPhyHandler1; - pme |= POINTER_SIGN_BIT; - pme |= paddr;// top bit is set anyway ... - } - else - { - pme = vtlbdata.pmap[paddr>>VTLB_PAGE_BITS]; - if (pme<0) - pme |= paddr;// top bit is set anyway ... + VTLBVirtual vmv; + if (paddr >= VTLB_PMAP_SZ) { + if ((s32)paddr >= 0) { + vmv = VTLBVirtual(VTLBPhysical::fromHandler(UnmappedPhyHandler0), paddr, vaddr); + } else { + vmv = VTLBVirtual(VTLBPhysical::fromHandler(UnmappedPhyHandler1), paddr & ~(1<<31), vaddr); + } + } else { + vmv = VTLBVirtual(vtlbdata.pmap[paddr>>VTLB_PAGE_BITS], paddr, vaddr); } - vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] = pme-vaddr; + vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] = vmv; if (vtlbdata.ppmap) if (!(vaddr & 0x80000000)) // those address are already physical don't change them vtlbdata.ppmap[vaddr>>VTLB_PAGE_BITS] = paddr & ~VTLB_PAGE_MASK; @@ -706,7 +698,7 @@ void vtlb_VMapBuffer(u32 vaddr,void* buffer,u32 size) uptr bu8 = (uptr)buffer; while (size > 0) { - vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] = bu8-vaddr; + vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] = VTLBVirtual::fromPointer(bu8, vaddr); vaddr += VTLB_PAGE_SIZE; bu8 += VTLB_PAGE_SIZE; size -= VTLB_PAGE_SIZE; @@ -720,16 +712,15 @@ void vtlb_VMapUnmap(u32 vaddr,u32 size) while (size > 0) { - u32 handl = UnmappedVirtHandler0; - if (vaddr & 0x80000000) - { - handl = UnmappedVirtHandler1; + + VTLBVirtual handl; + if ((s32)vaddr >= 0) { + handl = VTLBVirtual(VTLBPhysical::fromHandler(UnmappedVirtHandler0), vaddr, vaddr); + } else { + handl = VTLBVirtual(VTLBPhysical::fromHandler(UnmappedVirtHandler1), vaddr & ~(1<<31), vaddr); } - handl |= vaddr; // top bit is set anyway ... - handl |= 0x80000000; - - vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] = handl-vaddr; + vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] = handl; vaddr += VTLB_PAGE_SIZE; size -= VTLB_PAGE_SIZE; } @@ -800,9 +791,9 @@ constexpr size_t VMAP_SIZE = sizeof(sptr) * VTLB_VMAP_ITEMS; void vtlb_Core_Alloc() { // Can't return regions to the bump allocator - static sptr* vmap = nullptr; + static VTLBVirtual* vmap = nullptr; if (!vmap) - vmap = (sptr*)GetVmMemory().BumpAllocator().Alloc(VMAP_SIZE); + vmap = (VTLBVirtual*)GetVmMemory().BumpAllocator().Alloc(VMAP_SIZE); if (!vtlbdata.vmap) { bool okay = HostSys::MmapCommitPtr(vmap, VMAP_SIZE, PageProtectionMode().Read().Write()); diff --git a/pcsx2/vtlb.h b/pcsx2/vtlb.h index d917614767..7ea7bcecc5 100644 --- a/pcsx2/vtlb.h +++ b/pcsx2/vtlb.h @@ -35,6 +35,19 @@ typedef void __fastcall vtlbMemW32FP(u32 addr,mem32_t data); typedef void __fastcall vtlbMemW64FP(u32 addr,const mem64_t* data); typedef void __fastcall vtlbMemW128FP(u32 addr,const mem128_t* data); +template struct vtlbMemFP; + +template<> struct vtlbMemFP< 8, false> { typedef vtlbMemR8FP fn; static const uptr Index = 0; }; +template<> struct vtlbMemFP< 16, false> { typedef vtlbMemR16FP fn; static const uptr Index = 1; }; +template<> struct vtlbMemFP< 32, false> { typedef vtlbMemR32FP fn; static const uptr Index = 2; }; +template<> struct vtlbMemFP< 64, false> { typedef vtlbMemR64FP fn; static const uptr Index = 3; }; +template<> struct vtlbMemFP<128, false> { typedef vtlbMemR128FP fn; static const uptr Index = 4; }; +template<> struct vtlbMemFP< 8, true> { typedef vtlbMemW8FP fn; static const uptr Index = 0; }; +template<> struct vtlbMemFP< 16, true> { typedef vtlbMemW16FP fn; static const uptr Index = 1; }; +template<> struct vtlbMemFP< 32, true> { typedef vtlbMemW32FP fn; static const uptr Index = 2; }; +template<> struct vtlbMemFP< 64, true> { typedef vtlbMemW64FP fn; static const uptr Index = 3; }; +template<> struct vtlbMemFP<128, true> { typedef vtlbMemW128FP fn; static const uptr Index = 4; }; + typedef u32 vtlbHandler; extern void vtlb_Core_Alloc(); @@ -173,6 +186,59 @@ namespace vtlb_private static const uptr POINTER_SIGN_BIT = 1ULL << (sizeof(uptr) * 8 - 1); + struct VTLBPhysical + { + private: + sptr value; + explicit VTLBPhysical(sptr value): value(value) { } + public: + VTLBPhysical(): value(0) {} + /// Create from a pointer to raw memory + static VTLBPhysical fromPointer(void *ptr) { return fromPointer((sptr)ptr); } + /// Create from an integer representing a pointer to raw memory + static VTLBPhysical fromPointer(sptr ptr); + /// Create from a handler and address + static VTLBPhysical fromHandler(vtlbHandler handler); + + /// Get the raw value held by the entry + uptr raw() const { return value; } + /// Returns whether or not this entry is a handler + bool isHandler() const { return value < 0; } + /// Assumes the entry is a pointer, giving back its value + uptr assumePtr() const { return value; } + /// Assumes the entry is a handler, and gets the raw handler ID + u8 assumeHandler() const { return value; } + }; + + struct VTLBVirtual + { + private: + uptr value; + explicit VTLBVirtual(uptr value): value(value) { } + public: + VTLBVirtual(): value(0) {} + VTLBVirtual(VTLBPhysical phys, u32 paddr, u32 vaddr); + static VTLBVirtual fromPointer(uptr ptr, u32 vaddr) { + return VTLBVirtual(VTLBPhysical::fromPointer(ptr), 0, vaddr); + } + + /// Get the raw value held by the entry + uptr raw() const { return value; } + /// Returns whether or not this entry is a handler + bool isHandler(u32 vaddr) const { return (sptr)(value + vaddr) < 0; } + /// Assumes the entry is a pointer, giving back its value + uptr assumePtr(u32 vaddr) const { return value + vaddr; } + /// Assumes the entry is a handler, and gets the raw handler ID + u8 assumeHandlerGetID() const { return value; } + /// Assumes the entry is a handler, and gets the physical address + u32 assumeHandlerGetPAddr(u32 vaddr) const { return (value + vaddr - assumeHandlerGetID()) & ~POINTER_SIGN_BIT; } + /// Assumes the entry is a handler, returning it as a void* + void *assumeHandlerGetRaw(int index, bool write) const; + /// Assumes the entry is a handler, returning it + template + typename vtlbMemFP::fn *assumeHandler() const; + }; + struct MapData { // first indexer -- 8/16/32/64/128 bit tables [values 0-4] @@ -180,9 +246,9 @@ namespace vtlb_private // third indexer -- 128 possible handlers! void* RWFT[5][2][VTLB_HANDLER_ITEMS]; - sptr pmap[VTLB_PMAP_ITEMS]; //512KB // PS2 physical to x86 physical + VTLBPhysical pmap[VTLB_PMAP_ITEMS]; //512KB // PS2 physical to x86 physical - sptr* vmap; //4MB (allocated by vtlb_init) // PS2 virtual to x86 physical + VTLBVirtual* vmap; //4MB (allocated by vtlb_init) // PS2 virtual to x86 physical u32* ppmap; //4MB (allocated by vtlb_init) // PS2 virtual to PS2 physical @@ -194,6 +260,18 @@ namespace vtlb_private }; extern __aligned(64) MapData vtlbdata; + + inline void *VTLBVirtual::assumeHandlerGetRaw(int index, bool write) const + { + return vtlbdata.RWFT[index][write][assumeHandlerGetID()]; + } + + template + typename vtlbMemFP::fn *VTLBVirtual::assumeHandler() const + { + using FP = vtlbMemFP; + return (typename FP::fn *)assumeHandlerGetRaw(FP::Index, Write); + } } // -------------------------------------------------------------------------------------- diff --git a/pcsx2/x86/ix86-32/recVTLB.cpp b/pcsx2/x86/ix86-32/recVTLB.cpp index f69a8a6002..6895858204 100644 --- a/pcsx2/x86/ix86-32/recVTLB.cpp +++ b/pcsx2/x86/ix86-32/recVTLB.cpp @@ -375,10 +375,10 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const ) { EE::Profiler.EmitConstMem(addr_const); - u32 vmv_ptr = vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS]; - s32 ppf = addr_const + vmv_ptr; - if( ppf >= 0 ) + auto vmv = vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS]; + if( !vmv.isHandler(addr_const) ) { + auto ppf = vmv.assumeHandlerGetPAddr(addr_const); switch( bits ) { case 64: @@ -395,8 +395,7 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const ) else { // has to: translate, find function, call function - u32 handler = (u8)vmv_ptr; - u32 paddr = ppf - handler + 0x80000000; + u32 paddr = vmv.assumeHandlerGetPAddr(addr_const); int szidx = 0; switch( bits ) @@ -406,7 +405,7 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const ) } iFlushCall(FLUSH_FULLVTLB); - xFastCall( vtlbdata.RWFT[szidx][0][handler], paddr ); + xFastCall( vmv.assumeHandlerGetRaw(szidx, 0), paddr ); } } @@ -422,10 +421,10 @@ void vtlb_DynGenRead32_Const( u32 bits, bool sign, u32 addr_const ) { EE::Profiler.EmitConstMem(addr_const); - u32 vmv_ptr = vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS]; - s32 ppf = addr_const + vmv_ptr; - if( ppf >= 0 ) + auto vmv = vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS]; + if( !vmv.isHandler(addr_const) ) { + auto ppf = vmv.assumePtr(addr_const); switch( bits ) { case 8: @@ -450,8 +449,7 @@ void vtlb_DynGenRead32_Const( u32 bits, bool sign, u32 addr_const ) else { // has to: translate, find function, call function - u32 handler = (u8)vmv_ptr; - u32 paddr = ppf - handler + 0x80000000; + u32 paddr = vmv.assumeHandlerGetPAddr(addr_const); int szidx = 0; switch( bits ) @@ -469,7 +467,7 @@ void vtlb_DynGenRead32_Const( u32 bits, bool sign, u32 addr_const ) else { iFlushCall(FLUSH_FULLVTLB); - xFastCall( vtlbdata.RWFT[szidx][0][handler], paddr ); + xFastCall( vmv.assumeHandlerGetRaw(szidx, false), paddr ); // perform sign extension on the result: @@ -513,10 +511,10 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const ) { EE::Profiler.EmitConstMem(addr_const); - u32 vmv_ptr = vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS]; - s32 ppf = addr_const + vmv_ptr; - if( ppf >= 0 ) + auto vmv = vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS]; + if( !vmv.isHandler(addr_const) ) { + auto ppf = vmv.assumePtr(addr_const); switch(bits) { //8 , 16, 32 : data on EDX @@ -545,8 +543,7 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const ) else { // has to: translate, find function, call function - u32 handler = (u8)vmv_ptr; - u32 paddr = ppf - handler + 0x80000000; + u32 paddr = vmv.assumeHandlerGetPAddr(addr_const); int szidx = 0; switch( bits ) @@ -559,7 +556,7 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const ) } iFlushCall(FLUSH_FULLVTLB); - xFastCall( vtlbdata.RWFT[szidx][1][handler], paddr, edx ); + xFastCall( vmv.assumeHandlerGetRaw(szidx, true), paddr, edx ); } }