vif: reorganize dVifUnpack

Inline the execution part
Add a num parameter to dVifsetVUptr
Use a local variable for the nVifBlock instead of a global struct state

The goal is to ease future update of the nVifBlock struct
This commit is contained in:
Gregory Hainaut 2016-12-14 19:12:31 +01:00
parent 10b3d429fe
commit 555c96a941
2 changed files with 26 additions and 35 deletions

View File

@ -56,9 +56,6 @@ _vifT extern void dVifUnpack (const u8* data, bool isFill);
#define xmmTemp xmm7 #define xmmTemp xmm7
struct nVifStruct { struct nVifStruct {
__aligned16 nVifBlock block;
// Buffer for partial transfers (should always be first to ensure alignment) // Buffer for partial transfers (should always be first to ensure alignment)
// Maximum buffer size is 256 (vifRegs.Num max range) * 16 (quadword) // Maximum buffer size is 256 (vifRegs.Num max range) * 16 (quadword)
__aligned16 u8 buffer[256*16]; __aligned16 u8 buffer[256*16];

View File

@ -258,21 +258,20 @@ void VifUnpackSSE_Dynarec::CompileRoutine() {
xRET(); xRET();
} }
_vifT static __fi u8* dVifsetVUptr(uint cl, uint wl, bool isFill) { _vifT static __fi u8* dVifsetVUptr(uint cl, uint wl, u8 num, bool isFill) {
nVifStruct& v = nVif[idx];
vifStruct& vif = MTVU_VifX; vifStruct& vif = MTVU_VifX;
const VURegs& VU = vuRegs[idx]; const VURegs& VU = vuRegs[idx];
const uint vuMemLimit = idx ? 0x4000 : 0x1000; const uint vuMemLimit = idx ? 0x4000 : 0x1000;
u8* startmem = VU.Mem + (vif.tag.addr & (vuMemLimit-0x10)); u8* startmem = VU.Mem + (vif.tag.addr & (vuMemLimit-0x10));
u8* endmem = VU.Mem + vuMemLimit; u8* endmem = VU.Mem + vuMemLimit;
uint length = (v.block.num > 0) ? (v.block.num * 16) : 4096; // 0 = 256 uint length = (num > 0) ? (num * 16) : 4096; // 0 = 256
//wl = wl ? wl : 256; //0 is taken as 256 (KH2) //wl = wl ? wl : 256; //0 is taken as 256 (KH2)
//if (wl == 256) isFill = true; //if (wl == 256) isFill = true;
if (!isFill) { if (!isFill) {
uint skipSize = (cl - wl) * 16; uint skipSize = (cl - wl) * 16;
uint blocks = (v.block.num + (wl-1)) / wl; //Need to round up num's to calculate skip size correctly. uint blocks = (num + (wl-1)) / wl; //Need to round up num's to calculate skip size correctly.
length += (blocks-1) * skipSize; length += (blocks-1) * skipSize;
} }
@ -283,19 +282,6 @@ _vifT static __fi u8* dVifsetVUptr(uint cl, uint wl, bool isFill) {
return NULL; // Fall Back to Interpreters which have wrap-around logic return NULL; // Fall Back to Interpreters which have wrap-around logic
} }
_vifT static __ri void dVifExecuteUnpack(const u8* data, uptr x86, bool isFill)
{
VIFregisters& vifRegs = MTVU_VifXRegs;
if (u8* dest = dVifsetVUptr<idx>(vifRegs.cycle.cl, vifRegs.cycle.wl, isFill)) {
//DevCon.WriteLn("Running Recompiled Block!");
((nVifrecCall)x86)((uptr)dest, (uptr)data);
} else {
VIF_LOG("Running Interpreter Block");
_nVifUnpack(idx, data, vifRegs.mode, isFill);
}
}
_vifT __fi uptr dVifCompile(nVifBlock& key) { _vifT __fi uptr dVifCompile(nVifBlock& key) {
nVifStruct& v = nVif[idx]; nVifStruct& v = nVif[idx];
nVifBlock* block = v.vifBlocks.find(&key); nVifBlock* block = v.vifBlocks.find(&key);
@ -320,7 +306,7 @@ _vifT __fi uptr dVifCompile(nVifBlock& key) {
VifUnpackSSE_Dynarec(v, key).CompileRoutine(); VifUnpackSSE_Dynarec(v, key).CompileRoutine();
Perf::vif.map((uptr)v.recWritePtr, xGetPtr() - v.recWritePtr, v.block.upkType /* FIXME ideally a key*/); Perf::vif.map((uptr)v.recWritePtr, xGetPtr() - v.recWritePtr, key.upkType /* FIXME ideally a key*/);
v.recWritePtr = xGetPtr(); v.recWritePtr = xGetPtr();
return key.startPtr; return key.startPtr;
@ -335,31 +321,39 @@ _vifT __fi void dVifUnpack(const u8* data, bool isFill) {
const u8 upkType = (vif.cmd & 0x1f) | (vif.usn << 5); const u8 upkType = (vif.cmd & 0x1f) | (vif.usn << 5);
const int doMask = isFill? 1 : (vif.cmd & 0x10); const int doMask = isFill? 1 : (vif.cmd & 0x10);
v.block.upkType = upkType; __aligned16 nVifBlock block;
v.block.num = (u8&)vifRegs.num; block.upkType = upkType;
v.block.mode = (u8&)vifRegs.mode; block.num = (u8&)vifRegs.num;
v.block.cl = vifRegs.cycle.cl; block.mode = (u8&)vifRegs.mode;
v.block.wl = vifRegs.cycle.wl ? vifRegs.cycle.wl : 256; block.cl = vifRegs.cycle.cl;
v.block.aligned = vif.start_aligned; //MTVU doesn't have a packet size! block.wl = vifRegs.cycle.wl ? vifRegs.cycle.wl : 256;
v.block.startPtr = 0; // Ease the detection of the end of the hash bucket block.aligned = vif.start_aligned; //MTVU doesn't have a packet size!
block.startPtr = 0; // Ease the detection of the end of the hash bucket
if ((upkType & 0xf) != 9) if ((upkType & 0xf) != 9)
v.block.aligned &= 0x1; block.aligned &= 0x1;
//DevCon.Warning("Alignment %d", v.block.aligned); //DevCon.Warning("Alignment %d", block.aligned);
// Zero out the mask parameter if it's unused -- games leave random junk // Zero out the mask parameter if it's unused -- games leave random junk
// values here which cause false recblock cache misses. // values here which cause false recblock cache misses.
v.block.mask = doMask ? vifRegs.mask : 0; block.mask = doMask ? vifRegs.mask : 0;
//DevCon.WriteLn("nVif%d: Recompiled Block!", idx); //DevCon.WriteLn("nVif%d: Recompiled Block!", idx);
//DevCon.WriteLn(L"[num=% 3d][upkType=0x%02x][scl=%d][cl=%d][wl=%d][mode=%d][m=%d][mask=%s]", //DevCon.WriteLn(L"[num=% 3d][upkType=0x%02x][scl=%d][cl=%d][wl=%d][mode=%d][m=%d][mask=%s]",
// v.Block.num, v.Block.upkType, v.Block.scl, v.Block.cl, v.Block.wl, v.Block.mode, // block.num, block.upkType, block.scl, block.cl, block.wl, block.mode,
// doMask >> 4, doMask ? wxsFormat( L"0x%08x", v.Block.mask ).c_str() : L"ignored" // doMask >> 4, doMask ? wxsFormat( L"0x%08x", block.mask ).c_str() : L"ignored"
//); //);
uptr x86 = dVifCompile<idx>(v.block); uptr x86 = dVifCompile<idx>(block);
dVifExecuteUnpack<idx>(data, x86, isFill); // Run either the dynarec or the interpreter (if complex wrapping)
if (u8* dest = dVifsetVUptr<idx>(vifRegs.cycle.cl, vifRegs.cycle.wl, vifRegs.num, isFill)) {
//DevCon.WriteLn("Running Recompiled Block!");
((nVifrecCall)x86)((uptr)dest, (uptr)data);
} else {
VIF_LOG("Running Interpreter Block");
_nVifUnpack(idx, data, vifRegs.mode, isFill);
}
} }
template void dVifUnpack<0>(const u8* data, bool isFill); template void dVifUnpack<0>(const u8* data, bool isFill);