Move VTLB manipulation to class (#3524)

Another small piece of #3451

Moves all VTLB pointer manipulation into dedicated classes for the purpose, which should allow the algorithm to be changed much more easily in the future (only have to change the class and recVTLB.cpp assembly since it obviously can't use the class)

Also some of the functions that manipulated the VTLB previously used POINTER_SIGN_BIT (which 1 << 63 on 64-bit) while others used a sign-extended 0x80000000. Now they all use the same one (POINTER_SIGN_BIT)

Note: recVTLB.cpp was updated to keep it compiling but the rest of the x86-64 compatibility changes were left out

Also, Cache.cpp seems to assume VTLB entries are both sides of the union at the same time, which is impossible. Does anyone know how this actually worked (and if this patch breaks it) or if it never worked properly in the first place?
This commit is contained in:
tellowkrinkle 2020-08-19 03:37:23 -05:00 committed by GitHub
parent 75aac90452
commit 850efdc690
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 219 additions and 165 deletions

View File

@ -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<mem8_t*>(ppf) = value;
auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
*reinterpret_cast<mem8_t*>(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<mem16_t*>(ppf) = value;
auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
*reinterpret_cast<mem16_t*>(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<mem32_t*>(ppf) = value;
auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
*reinterpret_cast<mem32_t*>(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<mem64_t*>(ppf) = value;
auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
*reinterpret_cast<mem64_t*>(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<mem64_t*>(ppf) = value->lo;
*reinterpret_cast<mem64_t*>(ppf+8) = value->hi;
auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
auto ptr = reinterpret_cast<mem64_t*>(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<u8*>(ppf);
auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
return *reinterpret_cast<u8*>(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<u16*>(ppf);
auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
return *reinterpret_cast<u16*>(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<u32*>(ppf);
auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
return *reinterpret_cast<u32*>(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<u64*>(ppf);
auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
return *reinterpret_cast<u64*>(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

View File

@ -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<DataType*>(ppf);
return *reinterpret_cast<DataType*>(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<TemplateHelper<DataSize,false>::HandlerType*>(vtlbdata.RWFT[TemplateHelper<DataSize,false>::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<DataType*>(ppf)=data;
*reinterpret_cast<DataType*>(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<sizeof(DataType)*8, true>()(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<void*>(vtlbdata.pmap[paddr>>VTLB_PAGE_BITS]+(paddr&VTLB_PAGE_MASK));
return reinterpret_cast<void*>(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());

View File

@ -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 <size_t Width, bool Write> 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 <size_t Width, bool Write>
typename vtlbMemFP<Width, Write>::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 <size_t Width, bool Write>
typename vtlbMemFP<Width, Write>::fn *VTLBVirtual::assumeHandler() const
{
using FP = vtlbMemFP<Width, Write>;
return (typename FP::fn *)assumeHandlerGetRaw(FP::Index, Write);
}
}
// --------------------------------------------------------------------------------------

View File

@ -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 );
}
}