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 LRF_FLAG = 0x10;
const u32 LOCK_FLAG = 0x8; 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 getFreeCache(u32 mem, int mode, int * way)
{ {
int number = 0; int number = 0;
const int i = (mem >> 6) & 0x3F; const int i = (mem >> 6) & 0x3F;
const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; const auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
s32 ppf = mem + vmv; uptr ppf = vmv.assumePtr(mem);
const u32 hand = (u8)vmv; const u32 paddr = vmv.assumeHandlerGetPAddr(mem);
const u32 paddr = ppf - hand + 0x80000000;
if((cpuRegs.CP0.n.Config & 0x10000) == 0) CACHE_LOG("Cache off!"); if((cpuRegs.CP0.n.Config & 0x10000) == 0) CACHE_LOG("Cache off!");
@ -112,9 +113,8 @@ void writeCache8(u32 mem, u8 value)
if (i == -1) if (i == -1)
{ {
const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
s32 ppf = mem + vmv; *reinterpret_cast<mem8_t*>(vmv.assumePtr(mem)) = value;
*reinterpret_cast<mem8_t*>(ppf) = value;
return; return;
} }
@ -130,9 +130,8 @@ void writeCache16(u32 mem, u16 value)
if (i == -1) if (i == -1)
{ {
const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
s32 ppf = mem + vmv; *reinterpret_cast<mem16_t*>(vmv.assumePtr(mem)) = value;
*reinterpret_cast<mem16_t*>(ppf) = value;
return; return;
} }
@ -148,9 +147,8 @@ void writeCache32(u32 mem, u32 value)
if (i == -1) if (i == -1)
{ {
const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
s32 ppf = mem + vmv; *reinterpret_cast<mem32_t*>(vmv.assumePtr(mem)) = value;
*reinterpret_cast<mem32_t*>(ppf) = value;
return; return;
} }
@ -166,9 +164,8 @@ void writeCache64(u32 mem, const u64 value)
if (i == -1) if (i == -1)
{ {
const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
s32 ppf = mem + vmv; *reinterpret_cast<mem64_t*>(vmv.assumePtr(mem)) = value;
*reinterpret_cast<mem64_t*>(ppf) = value;
return; return;
} }
@ -184,10 +181,10 @@ void writeCache128(u32 mem, const mem128_t* value)
if (i == -1) if (i == -1)
{ {
const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
s32 ppf = mem + vmv; auto ptr = reinterpret_cast<mem64_t*>(vmv.assumePtr(mem));
*reinterpret_cast<mem64_t*>(ppf) = value->lo; ptr[0] = value->lo;
*reinterpret_cast<mem64_t*>(ppf+8) = value->hi; ptr[1] = value->hi;
return; return;
} }
@ -204,9 +201,8 @@ u8 readCache8(u32 mem)
if (i == -1) if (i == -1)
{ {
const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
s32 ppf = mem + vmv; return *reinterpret_cast<u8*>(vmv.assumePtr(mem));
return *reinterpret_cast<u8*>(ppf);
} }
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)]); 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) if (i == -1)
{ {
const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
s32 ppf = mem + vmv; return *reinterpret_cast<u16*>(vmv.assumePtr(mem));
return *reinterpret_cast<u16*>(ppf);
} }
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]); 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) if (i == -1)
{ {
const u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
s32 ppf = mem + vmv; return *reinterpret_cast<u32*>(vmv.assumePtr(mem));
return *reinterpret_cast<u32*>(ppf);
} }
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]); 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) if (i == -1)
{ {
u32 vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[mem >> VTLB_PAGE_BITS];
s32 ppf=mem + vmv; return *reinterpret_cast<u64*>(vmv.assumePtr(mem));
return *reinterpret_cast<u64*>(ppf);
} }
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]); 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; const int index = (addr >> 6) & 0x3F;
int way = 0; int way = 0;
const u32 pfnaddr = addr; const u32 pfnaddr = addr;
const u32 vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; const auto vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS];
const s32 ppf = pfnaddr + vmv; const u32 paddr = vmv.assumeHandlerGetPAddr(pfnaddr);
const u32 hand = (u8)vmv;
const u32 paddr = ppf - hand + 0x80000000;
if ((paddr & ~0xFFF) == (pCache[index].tag[0] & ~0xfff) && (pCache[index].tag[0] & VALID_FLAG)) 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; const int index = (addr >> 6) & 0x3F;
int way = 0; int way = 0;
const u32 pfnaddr = addr; const u32 pfnaddr = addr;
const u32 vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; const auto vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS];
s32 ppf = (pfnaddr + vmv) & ~0x3F; uptr ppf = vmv.assumePtr(pfnaddr) & ~0x3F;
const u32 hand = (u8)vmv; const u32 paddr = vmv.assumeHandlerGetPAddr(pfnaddr) & ~0x3f;
const u32 paddr = ppf - hand + 0x80000000;
if ((pCache[index].tag[0] & ~0xFFF) == (paddr & ~0xFFF) && (pCache[index].tag[0] & VALID_FLAG)) 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; const int index = (addr >> 6) & 0x3F;
int way = 0; int way = 0;
const u32 pfnaddr = (pCache[index].tag[way] & ~0x80000fff) | (addr & 0xfc0); const u32 pfnaddr = (pCache[index].tag[way] & ~0x80000fff) | (addr & 0xfc0);
const u32 vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; const auto vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS];
s32 ppf = (pfnaddr + vmv) & ~0x3F; uptr ppf = vmv.assumePtr(pfnaddr);
const u32 hand = (u8)vmv; const u32 paddr = vmv.assumeHandlerGetPAddr(pfnaddr);
const u32 paddr = ppf - hand + 0x80000000;
CACHE_LOG("CACHE DHWOIN addr %x, index %d, way %d, Flags %x OP %x", addr, index, way, pCache[index].tag[way] & 0x78, cpuRegs.code); 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 //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. //For speed, we will do it here.
const u32 pfnaddr = (pCache[index].tag[way] & ~0x80000fff) | (addr & 0xfc0); const u32 pfnaddr = (pCache[index].tag[way] & ~0x80000fff) | (addr & 0xfc0);
const u32 vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; const auto vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS];
s32 ppf = (pfnaddr + vmv) & ~0x3F; s32 ppf = vmv.assumePtr(pfnaddr);
if ((pCache[index].tag[way] & (DIRTY_FLAG | VALID_FLAG)) == (DIRTY_FLAG | VALID_FLAG)) // Dirty 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 index = (addr >> 6) & 0x3F;
const int way = addr & 0x1; const int way = addr & 0x1;
const u32 pfnaddr = (pCache[index].tag[way] & ~0x80000fff) + (addr & 0xFC0); const u32 pfnaddr = (pCache[index].tag[way] & ~0x80000fff) + (addr & 0xFC0);
const u32 vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS]; const auto vmv = vtlbdata.vmap[pfnaddr >> VTLB_PAGE_BITS];
s32 ppf = pfnaddr + vmv; s32 ppf = vmv.assumePtr(pfnaddr);
const u32 hand = (u8)vmv; const u32 paddr = vmv.assumeHandlerGetPAddr(pfnaddr);
const u32 paddr = ppf - hand + 0x80000000;
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]); 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 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 UnmappedPhyHandler0;
static vtlbHandler UnmappedPhyHandler1; 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) __inline int CheckCache(u32 addr)
{ {
u32 mask; u32 mask;
@ -96,10 +116,9 @@ template< typename DataType >
DataType __fastcall vtlb_memRead(u32 addr) DataType __fastcall vtlb_memRead(u32 addr)
{ {
static const uint DataSize = sizeof(DataType) * 8; static const uint DataSize = sizeof(DataType) * 8;
uptr vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
sptr ppf=addr+vmv;
if (!(ppf<0)) if (!vmv.isHandler(addr))
{ {
if (!CHECK_EEREC) 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 //has to: translate, find function, call function
u32 hand=(u8)vmv; u32 paddr=vmv.assumeHandlerGetPAddr(addr);
u32 paddr=ppf-hand+0x80000000;
//Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr); //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); //return reinterpret_cast<TemplateHelper<DataSize,false>::HandlerType*>(vtlbdata.RWFT[TemplateHelper<DataSize,false>::sidx][0][hand])(paddr,data);
switch( DataSize ) switch( DataSize )
{ {
case 8: case 8:
return vmv.assumeHandler< 8, false>()(paddr);
return ((vtlbMemR8FP*)vtlbdata.RWFT[0][0][hand])(paddr); case 16:
case 16: return vmv.assumeHandler<16, false>()(paddr);
case 32:
return ((vtlbMemR16FP*)vtlbdata.RWFT[1][0][hand])(paddr); return vmv.assumeHandler<32, false>()(paddr);
case 32:
return ((vtlbMemR32FP*)vtlbdata.RWFT[2][0][hand])(paddr);
jNO_DEFAULT; jNO_DEFAULT;
} }
@ -151,10 +166,9 @@ DataType __fastcall vtlb_memRead(u32 addr)
void __fastcall vtlb_memRead64(u32 mem, mem64_t *out) void __fastcall vtlb_memRead64(u32 mem, mem64_t *out)
{ {
uptr vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[mem>>VTLB_PAGE_BITS];
sptr ppf=mem+vmv;
if (!(ppf<0)) if (!vmv.isHandler(mem))
{ {
if (!CHECK_EEREC) { if (!CHECK_EEREC) {
if(CHECK_CACHE && CheckCache(mem)) 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 else
{ {
//has to: translate, find function, call function //has to: translate, find function, call function
u32 hand=(u8)vmv; u32 paddr = vmv.assumeHandlerGetPAddr(mem);
u32 paddr=ppf-hand+0x80000000;
//Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr); //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr);
vmv.assumeHandler<64, false>()(paddr, out);
((vtlbMemR64FP*)vtlbdata.RWFT[3][0][hand])(paddr, out);
} }
} }
void __fastcall vtlb_memRead128(u32 mem, mem128_t *out) void __fastcall vtlb_memRead128(u32 mem, mem128_t *out)
{ {
uptr vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[mem>>VTLB_PAGE_BITS];
sptr ppf=mem+vmv;
if (!(ppf<0)) if (!vmv.isHandler(mem))
{ {
if (!CHECK_EEREC) 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 else
{ {
//has to: translate, find function, call function //has to: translate, find function, call function
u32 hand=(u8)vmv; u32 paddr = vmv.assumeHandlerGetPAddr(mem);
u32 paddr=ppf-hand+0x80000000;
//Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr); //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr);
vmv.assumeHandler<128, false>()(paddr, out);
((vtlbMemR128FP*)vtlbdata.RWFT[4][0][hand])(paddr, out);
} }
} }
@ -211,9 +220,9 @@ void __fastcall vtlb_memWrite(u32 addr, DataType data)
{ {
static const uint DataSize = sizeof(DataType) * 8; static const uint DataSize = sizeof(DataType) * 8;
uptr vmv=vtlbdata.vmap[addr>>VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[addr>>VTLB_PAGE_BITS];
sptr ppf=addr+vmv;
if (!(ppf<0)) if (!vmv.isHandler(addr))
{ {
if (!CHECK_EEREC) 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 else
{ {
//has to: translate, find function, call function //has to: translate, find function, call function
u32 hand=(u8)vmv; u32 paddr = vmv.assumeHandlerGetPAddr(addr);
u32 paddr=ppf-hand+0x80000000;
//Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr); //Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr);
return vmv.assumeHandler<sizeof(DataType)*8, true>()(paddr, data);
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;
}
} }
} }
void __fastcall vtlb_memWrite64(u32 mem, const mem64_t* value) void __fastcall vtlb_memWrite64(u32 mem, const mem64_t* value)
{ {
uptr vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[mem>>VTLB_PAGE_BITS];
sptr ppf=mem+vmv;
if (!(ppf<0)) if (!vmv.isHandler(mem))
{ {
if (!CHECK_EEREC) 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 else
{ {
//has to: translate, find function, call function //has to: translate, find function, call function
u32 hand=(u8)vmv; u32 paddr = vmv.assumeHandlerGetPAddr(mem);
u32 paddr=ppf-hand+0x80000000;
//Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr); //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) void __fastcall vtlb_memWrite128(u32 mem, const mem128_t *value)
{ {
uptr vmv=vtlbdata.vmap[mem>>VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[mem>>VTLB_PAGE_BITS];
sptr ppf=mem+vmv;
if (!(ppf<0)) if (!vmv.isHandler(mem))
{ {
if (!CHECK_EEREC) 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 else
{ {
//has to: translate, find function, call function //has to: translate, find function, call function
u32 hand=(u8)vmv; u32 paddr = vmv.assumeHandlerGetPAddr(mem);
u32 paddr=ppf-hand+0x80000000;
//Console.WriteLn("Translated 0x%08X to 0x%08X", addr,paddr); //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 vaddr = tlb[i].low_add;
u32 paddr = tlb[i].physical_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); 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( vaddr , paddr, size);
vtlb_VMap(0x20000000|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==(start&VTLB_PAGE_MASK));
verify(0==(size&VTLB_PAGE_MASK) && size>0); verify(0==(size&VTLB_PAGE_MASK) && size>0);
s32 value = handler | 0x80000000;
u32 end = start + (size - VTLB_PAGE_SIZE); u32 end = start + (size - VTLB_PAGE_SIZE);
pxAssume( (end>>VTLB_PAGE_BITS) < ArraySize(vtlbdata.pmap) ); pxAssume( (end>>VTLB_PAGE_BITS) < ArraySize(vtlbdata.pmap) );
while (start <= end) while (start <= end)
{ {
vtlbdata.pmap[start>>VTLB_PAGE_BITS] = value; vtlbdata.pmap[start>>VTLB_PAGE_BITS] = VTLBPhysical::fromHandler(handler);
start += VTLB_PAGE_SIZE; start += VTLB_PAGE_SIZE;
} }
} }
@ -619,7 +616,7 @@ void vtlb_MapBlock(void* base, u32 start, u32 size, u32 blocksize)
while (loopsz > 0) while (loopsz > 0)
{ {
vtlbdata.pmap[start>>VTLB_PAGE_BITS] = ptr; vtlbdata.pmap[start>>VTLB_PAGE_BITS] = VTLBPhysical::fromPointer(ptr);
start += VTLB_PAGE_SIZE; start += VTLB_PAGE_SIZE;
ptr += 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) __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; return NULL;
else 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) __fi u32 vtlb_V2P(u32 vaddr)
@ -671,23 +668,18 @@ void vtlb_VMap(u32 vaddr,u32 paddr,u32 size)
while (size > 0) while (size > 0)
{ {
sptr pme; VTLBVirtual vmv;
if (paddr >= VTLB_PMAP_SZ) if (paddr >= VTLB_PMAP_SZ) {
{ if ((s32)paddr >= 0) {
pme = UnmappedPhyHandler0; vmv = VTLBVirtual(VTLBPhysical::fromHandler(UnmappedPhyHandler0), paddr, vaddr);
if (paddr & POINTER_SIGN_BIT) } else {
pme = UnmappedPhyHandler1; vmv = VTLBVirtual(VTLBPhysical::fromHandler(UnmappedPhyHandler1), paddr & ~(1<<31), vaddr);
pme |= POINTER_SIGN_BIT; }
pme |= paddr;// top bit is set anyway ... } else {
} vmv = VTLBVirtual(vtlbdata.pmap[paddr>>VTLB_PAGE_BITS], paddr, vaddr);
else
{
pme = vtlbdata.pmap[paddr>>VTLB_PAGE_BITS];
if (pme<0)
pme |= paddr;// top bit is set anyway ...
} }
vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] = pme-vaddr; vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] = vmv;
if (vtlbdata.ppmap) if (vtlbdata.ppmap)
if (!(vaddr & 0x80000000)) // those address are already physical don't change them if (!(vaddr & 0x80000000)) // those address are already physical don't change them
vtlbdata.ppmap[vaddr>>VTLB_PAGE_BITS] = paddr & ~VTLB_PAGE_MASK; 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; uptr bu8 = (uptr)buffer;
while (size > 0) 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; vaddr += VTLB_PAGE_SIZE;
bu8 += VTLB_PAGE_SIZE; bu8 += VTLB_PAGE_SIZE;
size -= VTLB_PAGE_SIZE; size -= VTLB_PAGE_SIZE;
@ -720,16 +712,15 @@ void vtlb_VMapUnmap(u32 vaddr,u32 size)
while (size > 0) while (size > 0)
{ {
u32 handl = UnmappedVirtHandler0;
if (vaddr & 0x80000000) VTLBVirtual handl;
{ if ((s32)vaddr >= 0) {
handl = UnmappedVirtHandler1; handl = VTLBVirtual(VTLBPhysical::fromHandler(UnmappedVirtHandler0), vaddr, vaddr);
} else {
handl = VTLBVirtual(VTLBPhysical::fromHandler(UnmappedVirtHandler1), vaddr & ~(1<<31), vaddr);
} }
handl |= vaddr; // top bit is set anyway ... vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] = handl;
handl |= 0x80000000;
vtlbdata.vmap[vaddr>>VTLB_PAGE_BITS] = handl-vaddr;
vaddr += VTLB_PAGE_SIZE; vaddr += VTLB_PAGE_SIZE;
size -= 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() void vtlb_Core_Alloc()
{ {
// Can't return regions to the bump allocator // Can't return regions to the bump allocator
static sptr* vmap = nullptr; static VTLBVirtual* vmap = nullptr;
if (!vmap) if (!vmap)
vmap = (sptr*)GetVmMemory().BumpAllocator().Alloc(VMAP_SIZE); vmap = (VTLBVirtual*)GetVmMemory().BumpAllocator().Alloc(VMAP_SIZE);
if (!vtlbdata.vmap) if (!vtlbdata.vmap)
{ {
bool okay = HostSys::MmapCommitPtr(vmap, VMAP_SIZE, PageProtectionMode().Read().Write()); 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 vtlbMemW64FP(u32 addr,const mem64_t* data);
typedef void __fastcall vtlbMemW128FP(u32 addr,const mem128_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; typedef u32 vtlbHandler;
extern void vtlb_Core_Alloc(); extern void vtlb_Core_Alloc();
@ -173,6 +186,59 @@ namespace vtlb_private
static const uptr POINTER_SIGN_BIT = 1ULL << (sizeof(uptr) * 8 - 1); 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 struct MapData
{ {
// first indexer -- 8/16/32/64/128 bit tables [values 0-4] // first indexer -- 8/16/32/64/128 bit tables [values 0-4]
@ -180,9 +246,9 @@ namespace vtlb_private
// third indexer -- 128 possible handlers! // third indexer -- 128 possible handlers!
void* RWFT[5][2][VTLB_HANDLER_ITEMS]; 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 u32* ppmap; //4MB (allocated by vtlb_init) // PS2 virtual to PS2 physical
@ -194,6 +260,18 @@ namespace vtlb_private
}; };
extern __aligned(64) MapData vtlbdata; 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); EE::Profiler.EmitConstMem(addr_const);
u32 vmv_ptr = vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS];
s32 ppf = addr_const + vmv_ptr; if( !vmv.isHandler(addr_const) )
if( ppf >= 0 )
{ {
auto ppf = vmv.assumeHandlerGetPAddr(addr_const);
switch( bits ) switch( bits )
{ {
case 64: case 64:
@ -395,8 +395,7 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const )
else else
{ {
// has to: translate, find function, call function // has to: translate, find function, call function
u32 handler = (u8)vmv_ptr; u32 paddr = vmv.assumeHandlerGetPAddr(addr_const);
u32 paddr = ppf - handler + 0x80000000;
int szidx = 0; int szidx = 0;
switch( bits ) switch( bits )
@ -406,7 +405,7 @@ void vtlb_DynGenRead64_Const( u32 bits, u32 addr_const )
} }
iFlushCall(FLUSH_FULLVTLB); 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); EE::Profiler.EmitConstMem(addr_const);
u32 vmv_ptr = vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS];
s32 ppf = addr_const + vmv_ptr; if( !vmv.isHandler(addr_const) )
if( ppf >= 0 )
{ {
auto ppf = vmv.assumePtr(addr_const);
switch( bits ) switch( bits )
{ {
case 8: case 8:
@ -450,8 +449,7 @@ void vtlb_DynGenRead32_Const( u32 bits, bool sign, u32 addr_const )
else else
{ {
// has to: translate, find function, call function // has to: translate, find function, call function
u32 handler = (u8)vmv_ptr; u32 paddr = vmv.assumeHandlerGetPAddr(addr_const);
u32 paddr = ppf - handler + 0x80000000;
int szidx = 0; int szidx = 0;
switch( bits ) switch( bits )
@ -469,7 +467,7 @@ void vtlb_DynGenRead32_Const( u32 bits, bool sign, u32 addr_const )
else else
{ {
iFlushCall(FLUSH_FULLVTLB); iFlushCall(FLUSH_FULLVTLB);
xFastCall( vtlbdata.RWFT[szidx][0][handler], paddr ); xFastCall( vmv.assumeHandlerGetRaw(szidx, false), paddr );
// perform sign extension on the result: // perform sign extension on the result:
@ -513,10 +511,10 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const )
{ {
EE::Profiler.EmitConstMem(addr_const); EE::Profiler.EmitConstMem(addr_const);
u32 vmv_ptr = vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS]; auto vmv = vtlbdata.vmap[addr_const>>VTLB_PAGE_BITS];
s32 ppf = addr_const + vmv_ptr; if( !vmv.isHandler(addr_const) )
if( ppf >= 0 )
{ {
auto ppf = vmv.assumePtr(addr_const);
switch(bits) switch(bits)
{ {
//8 , 16, 32 : data on EDX //8 , 16, 32 : data on EDX
@ -545,8 +543,7 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const )
else else
{ {
// has to: translate, find function, call function // has to: translate, find function, call function
u32 handler = (u8)vmv_ptr; u32 paddr = vmv.assumeHandlerGetPAddr(addr_const);
u32 paddr = ppf - handler + 0x80000000;
int szidx = 0; int szidx = 0;
switch( bits ) switch( bits )
@ -559,7 +556,7 @@ void vtlb_DynGenWrite_Const( u32 bits, u32 addr_const )
} }
iFlushCall(FLUSH_FULLVTLB); iFlushCall(FLUSH_FULLVTLB);
xFastCall( vtlbdata.RWFT[szidx][1][handler], paddr, edx ); xFastCall( vmv.assumeHandlerGetRaw(szidx, true), paddr, edx );
} }
} }