Android project - Changed to microVU memory related registers

This commit is contained in:
k2154
2025-07-28 07:33:02 +09:00
parent 6988f54d71
commit 702315e715
19 changed files with 636 additions and 521 deletions
+22 -6
View File
@@ -526,8 +526,8 @@ u32 armEmitJmpPtr(void* code, const void* dst, bool flush_icache)
a64::Register armLoadPtr(const void* addr)
{
armAsm->Ldr(a64::w4, armMemOperandPtr(addr));
return a64::w4;
armAsm->Ldr(EEX, armMemOperandPtr(addr));
return EEX;
}
a64::Register armLoadPtr64(const void* addr)
@@ -538,14 +538,20 @@ a64::Register armLoadPtr64(const void* addr)
a64::Register armLdrh(const void* addr)
{
armAsm->Ldrh(a64::w4, armMemOperandPtr(addr));
return a64::w4;
armAsm->Ldrh(EEX, armMemOperandPtr(addr));
return EEX;
}
a64::Register armLdrsh(const void* addr)
{
armAsm->Ldrsh(a64::w4, armMemOperandPtr(addr));
return a64::w4;
armAsm->Ldrsh(EEX, armMemOperandPtr(addr));
return EEX;
}
a64::Register armLoadPtr(const a64::MemOperand offset)
{
armAsm->Ldr(EEX, offset);
return EEX;
}
void armLoadPtr(const a64::CPURegister& reg, const void* addr, int64_t offset)
@@ -612,6 +618,16 @@ void armStorePtr(uint64_t imm, const void* addr, const a64::Register& reg)
}
}
void armStorePtr(uint64_t imm, a64::MemOperand offset, const a64::Register& reg)
{
if(imm == 0) {
armAsm->Str(a64::xzr, offset);
} else {
armAsm->Mov(reg, imm);
armAsm->Str(reg, offset);
}
}
void armStorePtr(uint64_t imm, a64::Register regRs, int64_t offset, const a64::Register& regRt)
{
if(imm == 0) {
+14 -2
View File
@@ -54,16 +54,26 @@ namespace a64 = vixl::aarch64;
#define RSTATE_x22 a64::x22
#define RSTATE_x23 a64::x23
#define RSTATE_x24 a64::x24
#define RFASTMEMBASE a64::x25
#define RSTATE_x26 a64::x26
// microVU
#define RSTATE_MVU a64::x27
#define RSTATE_VU1 a64::x28
#define RSTATE_VUR a64::x26
#define PTR_MVU(field) a64::MemOperand(RSTATE_MVU, offsetof(microVU, field))
#define PTR_VU1(field) a64::MemOperand(RSTATE_VU1, offsetof(VURegs, field))
#define PTR_VUR(field) a64::MemOperand(RSTATE_VUR, offsetof(VURegs, field))
// CPU(iR5900), PSX(iR3000A), FPU(iFPU, iFPUd)
#define RSTATE_FPU a64::x27
#define RSTATE_PSX a64::x28
#define RSTATE_CPU a64::x29
#define PTR_FPU(field) a64::MemOperand(RSTATE_FPU, offsetof(fpuRegisters, field))
#define PTR_PSX(field) a64::MemOperand(RSTATE_PSX, offsetof(psxRegisters, field))
#define PTR_CPU(field) a64::MemOperand(RSTATE_CPU, offsetof(cpuRegisters, field))
static inline s64 GetPCDisplacement(const void* current, const void* target)
{
return static_cast<s64>((reinterpret_cast<ptrdiff_t>(target) - reinterpret_cast<ptrdiff_t>(current)) >> 2);
@@ -175,6 +185,7 @@ a64::Register armLoadPtr(const void* addr);
a64::Register armLoadPtr64(const void* addr);
a64::Register armLdrh(const void* addr);
a64::Register armLdrsh(const void* addr);
a64::Register armLoadPtr(const a64::MemOperand offset);
void armLoadPtr(const a64::CPURegister& reg, const void* addr, int64_t offset);
a64::Register armLoadPtr(a64::Register regRs, int64_t offset);
void armLoadPtr(const a64::CPURegister& regRt, a64::Register regRs, int64_t offset);
@@ -185,6 +196,7 @@ a64::VRegister armLoadPtrM(a64::Register regRs, int64_t offset=0);
void armStorePtr(const a64::CPURegister& reg, const void* addr, int64_t offset);
void armStorePtr(const a64::CPURegister& regRt, a64::Register regRs, int64_t offset);
void armStorePtr(uint64_t imm, const void* addr, const a64::Register& reg=EEX);
void armStorePtr(uint64_t imm, a64::MemOperand offset, const a64::Register& reg=EEX);
void armStorePtr(uint64_t imm, a64::Register regRs, int64_t offset, const a64::Register& regRt=EEX);
a64::MemOperand armMemOperandPtr(const void* addr);
+88 -81
View File
@@ -12,9 +12,6 @@
using namespace x86Emitter;
#endif
//thread_local u8* j8Ptr[32];
//thread_local u32* j32Ptr[32];
u16 g_x86AllocCounter = 0;
u16 g_xmmAllocCounter = 0;
@@ -50,10 +47,10 @@ bool _isAllocatableX86reg(int x86reg)
// if (!CHECK_FASTMEM && x86reg == R8X.GetCode())
// return false;
// rbp is used as the fastmem base
if (CHECK_FASTMEM && x86reg == 5)
// if (CHECK_FASTMEM && x86reg == 20)
return false;
// // rbp is used as the fastmem base
// if (CHECK_FASTMEM && x86reg == 5)
//// if (CHECK_FASTMEM && x86reg == 20)
// return false;
#ifdef ENABLE_VTUNE
// vtune needs ebp...
@@ -70,11 +67,11 @@ bool _isAllocatableX86reg(int x86reg)
bool _hasX86reg(int type, int reg, int required_mode /*= 0*/)
{
for (uint i = 0; i < iREGCNT_GPR; i++)
for (auto & x86reg : x86regs)
{
if (x86regs[i].inuse && x86regs[i].type == type && x86regs[i].reg == reg)
if (x86reg.inuse && x86reg.type == type && x86reg.reg == reg)
{
return ((x86regs[i].mode & required_mode) == required_mode);
return ((x86reg.mode & required_mode) == required_mode);
}
}
@@ -91,11 +88,11 @@ bool _hasX86reg(int type, int reg, int required_mode /*= 0*/)
// (i.e EEINST_USED is cleared)
int _getFreeXMMreg(u32 maxreg)
{
int i, tempi;
u32 bestcount = 0x10000;
int i, tempi;
u32 bestcount = 0x10000, e = maxreg;
// check for free registers
for (i = 0; (uint)i < maxreg; i++)
for (i = 0; i < e; ++i)
{
if (!xmmregs[i].inuse)
return i;
@@ -104,7 +101,7 @@ int _getFreeXMMreg(u32 maxreg)
// check for dead regs
tempi = -1;
bestcount = 0xffff;
for (i = 0; (uint)i < maxreg; i++)
for (i = 0; i < e; ++i)
{
pxAssert(xmmregs[i].inuse);
if (xmmregs[i].needed)
@@ -151,7 +148,7 @@ int _getFreeXMMreg(u32 maxreg)
// lastly, try without the used check
bestcount = 0xffff;
for (i = 0; (uint)i < maxreg; i++)
for (i = 0; i < e; ++i)
{
pxAssert(xmmregs[i].inuse);
if (xmmregs[i].needed)
@@ -194,7 +191,8 @@ int _allocTempXMMreg(XMMSSEType type)
// So basically it is mostly used to set the mode of the register, and load value if we need to read it
int _checkXMMreg(int type, int reg, int mode)
{
for (size_t i = 0; i < iREGCNT_XMM; i++)
u32 i;
for (i = 0; i < iREGCNT_XMM; ++i)
{
if (xmmregs[i].inuse && (xmmregs[i].type == (type & 0xff)) && (xmmregs[i].reg == reg))
{
@@ -222,11 +220,11 @@ int _checkXMMreg(int type, int reg, int mode)
bool _hasXMMreg(int type, int reg, int required_mode /*= 0*/)
{
for (uint i = 0; i < iREGCNT_XMM; i++)
for (auto & xmmreg : xmmregs)
{
if (xmmregs[i].inuse && xmmregs[i].type == type && xmmregs[i].reg == reg)
if (xmmreg.inuse && xmmreg.type == type && xmmreg.reg == reg)
{
return ((xmmregs[i].mode & required_mode) == required_mode);
return ((xmmreg.mode & required_mode) == required_mode);
}
}
@@ -242,7 +240,8 @@ bool _hasXMMreg(int type, int reg, int required_mode /*= 0*/)
// Note: FPU are always in XMM register
int _allocFPtoXMMreg(int fpreg, int mode)
{
for (size_t i = 0; i < iREGCNT_XMM; i++)
u32 i;
for (i = 0; i < iREGCNT_XMM; ++i)
{
if (xmmregs[i].inuse == 0)
continue;
@@ -290,7 +289,8 @@ int _allocGPRtoXMMreg(int gprreg, int mode)
// is this already in a gpr?
const int hostx86reg = _checkX86reg(X86TYPE_GPR, gprreg, MODE_READ);
for (u32 i = 0; i < iREGCNT_XMM; i++)
u32 i;
for (i = 0; i < iREGCNT_XMM; ++i)
{
if (!xmmregs[i].inuse || xmmregs[i].type != XMMTYPE_GPRREG || xmmregs[i].reg != gprreg)
continue;
@@ -413,7 +413,8 @@ int _allocGPRtoXMMreg(int gprreg, int mode)
// (seriously boy you could have factorized it)
int _allocFPACCtoXMMreg(int mode)
{
for (size_t i = 0; i < iREGCNT_XMM; i++)
u32 i;
for (i = 0; i < iREGCNT_XMM; ++i)
{
if (xmmregs[i].inuse == 0)
continue;
@@ -471,51 +472,51 @@ void _reallocateXMMreg(int xmmreg, int newtype, int newreg, int newmode, bool wr
// You must use _clearNeededXMMregs to clear the flag
void _addNeededGPRtoX86reg(int gprreg)
{
for (uint i = 0; i < iREGCNT_GPR; i++)
for (auto & x86reg : x86regs)
{
if (x86regs[i].inuse == 0)
if (x86reg.inuse == 0)
continue;
if (x86regs[i].type != X86TYPE_GPR)
if (x86reg.type != X86TYPE_GPR)
continue;
if (x86regs[i].reg != gprreg)
if (x86reg.reg != gprreg)
continue;
x86regs[i].counter = g_x86AllocCounter++; // update counter
x86regs[i].needed = 1;
x86reg.counter = g_x86AllocCounter++; // update counter
x86reg.needed = 1;
break;
}
}
void _addNeededPSXtoX86reg(int gprreg)
{
for (uint i = 0; i < iREGCNT_GPR; i++)
for (auto & x86reg : x86regs)
{
if (x86regs[i].inuse == 0)
if (x86reg.inuse == 0)
continue;
if (x86regs[i].type != X86TYPE_PSX)
if (x86reg.type != X86TYPE_PSX)
continue;
if (x86regs[i].reg != gprreg)
if (x86reg.reg != gprreg)
continue;
x86regs[i].counter = g_x86AllocCounter++; // update counter
x86regs[i].needed = 1;
x86reg.counter = g_x86AllocCounter++; // update counter
x86reg.needed = 1;
break;
}
}
void _addNeededGPRtoXMMreg(int gprreg)
{
for (uint i = 0; i < iREGCNT_XMM; i++)
for (auto & xmmreg : xmmregs)
{
if (xmmregs[i].inuse == 0)
if (xmmreg.inuse == 0)
continue;
if (xmmregs[i].type != XMMTYPE_GPRREG)
if (xmmreg.type != XMMTYPE_GPRREG)
continue;
if (xmmregs[i].reg != gprreg)
if (xmmreg.reg != gprreg)
continue;
xmmregs[i].counter = g_xmmAllocCounter++; // update counter
xmmregs[i].needed = 1;
xmmreg.counter = g_xmmAllocCounter++; // update counter
xmmreg.needed = 1;
break;
}
}
@@ -524,17 +525,17 @@ void _addNeededGPRtoXMMreg(int gprreg)
// You must use _clearNeededXMMregs to clear the flag
void _addNeededFPtoXMMreg(int fpreg)
{
for (uint i = 0; i < iREGCNT_XMM; i++)
for (auto & xmmreg : xmmregs)
{
if (xmmregs[i].inuse == 0)
if (xmmreg.inuse == 0)
continue;
if (xmmregs[i].type != XMMTYPE_FPREG)
if (xmmreg.type != XMMTYPE_FPREG)
continue;
if (xmmregs[i].reg != fpreg)
if (xmmreg.reg != fpreg)
continue;
xmmregs[i].counter = g_xmmAllocCounter++; // update counter
xmmregs[i].needed = 1;
xmmreg.counter = g_xmmAllocCounter++; // update counter
xmmreg.needed = 1;
break;
}
}
@@ -543,15 +544,15 @@ void _addNeededFPtoXMMreg(int fpreg)
// You must use _clearNeededXMMregs to clear the flag
void _addNeededFPACCtoXMMreg()
{
for (uint i = 0; i < iREGCNT_XMM; i++)
for (auto & xmmreg : xmmregs)
{
if (xmmregs[i].inuse == 0)
if (xmmreg.inuse == 0)
continue;
if (xmmregs[i].type != XMMTYPE_FPACC)
if (xmmreg.type != XMMTYPE_FPACC)
continue;
xmmregs[i].counter = g_xmmAllocCounter++; // update counter
xmmregs[i].needed = 1;
xmmreg.counter = g_xmmAllocCounter++; // update counter
xmmreg.needed = 1;
break;
}
}
@@ -560,19 +561,17 @@ void _addNeededFPACCtoXMMreg()
// Written register will set MODE_READ (aka data is valid, no need to load it)
void _clearNeededXMMregs()
{
for (uint i = 0; i < iREGCNT_XMM; i++)
for (auto & xmmreg : xmmregs)
{
if (xmmregs[i].needed)
if (xmmreg.needed)
{
// setup read to any just written regs
if (xmmregs[i].inuse && (xmmregs[i].mode & MODE_WRITE))
xmmregs[i].mode |= MODE_READ;
xmmregs[i].needed = 0;
if (xmmreg.inuse && (xmmreg.mode & MODE_WRITE))
xmmreg.mode |= MODE_READ;
xmmreg.needed = 0;
}
if (xmmregs[i].inuse)
if (xmmreg.inuse)
{
pxAssert(xmmregs[i].type != XMMTYPE_TEMP);
}
@@ -585,7 +584,8 @@ void _clearNeededXMMregs()
// Flush is 3: drop register content
void _deleteGPRtoX86reg(int reg, int flush)
{
for (uint i = 0; i < iREGCNT_XMM; i++)
u32 i;
for (i = 0; i < iREGCNT_XMM; ++i)
{
if (x86regs[i].inuse && x86regs[i].type == X86TYPE_GPR && x86regs[i].reg == reg)
{
@@ -623,11 +623,11 @@ void _deleteGPRtoX86reg(int reg, int flush)
void _deletePSXtoX86reg(int reg, int flush)
{
for (uint i = 0; i < iREGCNT_GPR; i++)
u32 i;
for (i = 0; i < iREGCNT_GPR; ++i)
{
if (x86regs[i].inuse && x86regs[i].type == X86TYPE_PSX && x86regs[i].reg == reg)
{
switch (flush)
{
case DELETE_REG_FREE:
@@ -664,12 +664,11 @@ void _deletePSXtoX86reg(int reg, int flush)
void _deleteGPRtoXMMreg(int reg, int flush)
{
for (uint i = 0; i < iREGCNT_XMM; i++)
u32 i;
for (i = 0; i < iREGCNT_XMM; ++i)
{
if (xmmregs[i].inuse && xmmregs[i].type == XMMTYPE_GPRREG && xmmregs[i].reg == reg)
{
switch (flush)
{
case DELETE_REG_FREE:
@@ -709,7 +708,8 @@ void _deleteGPRtoXMMreg(int reg, int flush)
// Flush is 2: drop register content
void _deleteFPtoXMMreg(int reg, int flush)
{
for (size_t i = 0; i < iREGCNT_XMM; i++)
u32 i;
for (i = 0; i < iREGCNT_XMM; ++i)
{
if (xmmregs[i].inuse && xmmregs[i].type == XMMTYPE_FPREG && xmmregs[i].reg == reg)
{
@@ -747,15 +747,15 @@ void _writebackXMMreg(int xmmreg)
{
if (xmmregs[xmmreg].reg == 33) {
// xMOVSS(ptr[&VU0.VI[REG_I].F], xRegisterSSE(xmmreg));
armAsm->Str(a64::QRegister(xmmreg).S(), armMemOperandPtr(&VU0.VI[REG_I].F));
armAsm->Str(a64::QRegister(xmmreg).S(), PTR_VUR(VI[REG_I].F));
}
else if (xmmregs[xmmreg].reg == 32) {
// xMOVAPS(ptr[VU0.ACC.F], xRegisterSSE(xmmreg));
armAsm->Str(a64::QRegister(xmmreg).Q(), armMemOperandPtr(VU0.ACC.F));
armAsm->Str(a64::QRegister(xmmreg).Q(), PTR_VUR(ACC.F));
}
else if (xmmregs[xmmreg].reg > 0) {
// xMOVAPS(ptr[VU0.VF[xmmregs[xmmreg].reg].F], xRegisterSSE(xmmreg));
armAsm->Str(a64::QRegister(xmmreg).Q(), armMemOperandPtr(VU0.VF[xmmregs[xmmreg].reg].F));
armAsm->Str(a64::QRegister(xmmreg).Q(), PTR_VUR(VF[xmmregs[xmmreg].reg].F));
}
}
break;
@@ -818,7 +818,8 @@ int _allocVFtoXMMreg(int vfreg, int mode)
// mode == 0 is called by the microvu side, and we don't want to clash with its temps...
if (mode != 0)
{
for (uint i = 0; i < iREGCNT_XMM; i++)
u32 i;
for (i = 0; i < iREGCNT_XMM; ++i)
{
if (xmmregs[i].inuse && xmmregs[i].type == XMMTYPE_VFREG && xmmregs[i].reg == vfreg)
{
@@ -843,15 +844,15 @@ int _allocVFtoXMMreg(int vfreg, int mode)
{
if (vfreg == 33) {
// xMOVSSZX(xRegisterSSE(xmmreg), ptr[&VU0.VI[REG_I].F]);
armAsm->Ldr(a64::QRegister(xmmreg).S(), armMemOperandPtr(&VU0.VI[REG_I].F));
armAsm->Ldr(a64::QRegister(xmmreg).S(), PTR_VUR(VI[REG_I].F));
}
else if (vfreg == 32) {
// xMOVAPS(xRegisterSSE(xmmreg), ptr[VU0.ACC.F]);
armAsm->Ldr(a64::QRegister(xmmreg).Q(), armMemOperandPtr(VU0.ACC.F));
armAsm->Ldr(a64::QRegister(xmmreg).Q(), PTR_VUR(ACC.F));
}
else {
// xMOVAPS(xRegisterSSE(xmmreg), ptr[VU0.VF[xmmregs[xmmreg].reg].F]);
armAsm->Ldr(a64::QRegister(xmmreg).Q(), armMemOperandPtr(VU0.VF[xmmregs[xmmreg].reg].F));
armAsm->Ldr(a64::QRegister(xmmreg).Q(), PTR_VUR(VF[xmmregs[xmmreg].reg].F));
}
}
@@ -860,7 +861,8 @@ int _allocVFtoXMMreg(int vfreg, int mode)
void _flushCOP2regs()
{
for (uint i = 0; i < iREGCNT_XMM; i++)
u32 i;
for (i = 0; i < iREGCNT_XMM; ++i)
{
if (xmmregs[i].inuse && xmmregs[i].type == XMMTYPE_VFREG)
{
@@ -883,8 +885,11 @@ void _flushXMMreg(int xmmreg)
// Flush in memory all inuse registers but registers are still valid
void _flushXMMregs()
{
for (u32 i = 0; i < iREGCNT_XMM; ++i)
_flushXMMreg(i);
u32 i;
for (i = 0; i < iREGCNT_XMM; ++i)
{
_flushXMMreg(i);
}
}
int _allocIfUsedGPRtoX86(int gprreg, int mode)
@@ -937,17 +942,17 @@ void _recClearInst(EEINST* pinst)
// returns nonzero value if reg has been written between [startpc, endpc-4]
u32 _recIsRegReadOrWritten(EEINST* pinst, int size, u8 xmmtype, u8 reg)
{
u32 inst = 1;
u32 i, inst = 1;
while (size-- > 0)
{
for (u32 i = 0; i < std::size(pinst->writeType); ++i)
for (i = 0; i < std::size(pinst->writeType); ++i)
{
if ((pinst->writeType[i] == xmmtype) && (pinst->writeReg[i] == reg))
return inst;
}
for (u32 i = 0; i < std::size(pinst->readType); ++i)
for (i = 0; i < std::size(pinst->readType); ++i)
{
if ((pinst->readType[i] == xmmtype) && (pinst->readReg[i] == reg))
return inst;
@@ -962,9 +967,11 @@ u32 _recIsRegReadOrWritten(EEINST* pinst, int size, u8 xmmtype, u8 reg)
void _recFillRegister(EEINST& pinst, int type, int reg, int write)
{
u32 i;
if (write)
{
for (size_t i = 0; i < std::size(pinst.writeType); ++i)
for (i = 0; i < std::size(pinst.writeType); ++i)
{
if (pinst.writeType[i] == XMMTYPE_TEMP)
{
@@ -977,7 +984,7 @@ void _recFillRegister(EEINST& pinst, int type, int reg, int write)
}
else
{
for (size_t i = 0; i < std::size(pinst.readType); ++i)
for (i = 0; i < std::size(pinst.readType); ++i)
{
if (pinst.readType[i] == XMMTYPE_TEMP)
{
+20 -14
View File
@@ -131,7 +131,8 @@ void _flushConstRegs(bool delete_const)
{
int zero_reg_count = 0;
int minusone_reg_count = 0;
for (u32 i = 0; i < 32; i++)
u32 i;
for (i = 0; i < 32; ++i)
{
if (!GPR_IS_CONST1(i) || g_cpuFlushedConstReg & (1u << i))
continue;
@@ -148,7 +149,7 @@ void _flushConstRegs(bool delete_const)
{
// xXOR(eax, eax);
armAsm->Eor(EAX, EAX, EAX);
for (u32 i = 0; i < 32; i++)
for (i = 0; i < 32; ++i)
{
if (!GPR_IS_CONST1(i) || g_cpuFlushedConstReg & (1u << i))
continue;
@@ -175,7 +176,7 @@ void _flushConstRegs(bool delete_const)
armAsm->Mvn(RAX, RAX);
}
for (u32 i = 0; i < 32; i++)
for (i = 0; i < 32; ++i)
{
if (!GPR_IS_CONST1(i) || g_cpuFlushedConstReg & (1u << i))
continue;
@@ -192,7 +193,7 @@ void _flushConstRegs(bool delete_const)
}
// and whatever's left over..
for (u32 i = 0; i < 32; i++)
for (i = 0; i < 32; ++i)
{
if (!GPR_IS_CONST1(i) || g_cpuFlushedConstReg & (1u << i))
continue;
@@ -257,7 +258,8 @@ int _allocX86reg(int type, int reg, int mode)
int hostXMMreg = (type == X86TYPE_GPR) ? _checkXMMreg(XMMTYPE_GPRREG, reg, 0) : -1;
if (type != X86TYPE_TEMP)
{
for (int i = 0; i < static_cast<int>(iREGCNT_GPR); i++)
int i, e = static_cast<int>(iREGCNT_GPR);
for (i = 0; i < e; ++i)
{
if (!x86regs[i].inuse || x86regs[i].type != type || x86regs[i].reg != reg)
continue;
@@ -417,7 +419,7 @@ int _allocX86reg(int type, int reg, int mode)
{
RALOG("Loading guest VI reg %d to GPR %d", reg, regnum);
// xMOVZX(xRegister32(regnum), ptr16[&VU0.VI[reg].US[0]]);
armAsm->Ldrh(a64::WRegister(regnum), armMemOperandPtr(&VU0.VI[reg].US[0]));
armAsm->Ldrh(a64::WRegister(regnum), PTR_VUR(VI[reg].US[0]));
}
break;
@@ -473,7 +475,7 @@ void _writebackX86Reg(int x86reg)
case X86TYPE_VIREG:
RALOG("Writing back VI reg %d for guest reg %d P2\n", x86reg, x86regs[x86reg].reg);
// xMOV(ptr16[&VU0.VI[x86regs[x86reg].reg].UL], xRegister16(x86reg));
armAsm->Strh(a64::WRegister(x86reg), armMemOperandPtr(&VU0.VI[x86regs[x86reg].reg].UL));
armAsm->Strh(a64::WRegister(x86reg), PTR_VUR(VI[x86regs[x86reg].reg].UL));
break;
case X86TYPE_PCWRITEBACK:
@@ -502,12 +504,11 @@ void _writebackX86Reg(int x86reg)
int _checkX86reg(int type, int reg, int mode)
{
for (uint i = 0; i < iREGCNT_GPR; i++)
u32 i;
for (i = 0; i < iREGCNT_GPR; ++i)
{
if (x86regs[i].inuse && x86regs[i].reg == reg && x86regs[i].type == type)
{
int n1 = GPR_IS_DIRTY_CONST(reg);
int n2 = PSX_IS_DIRTY_CONST(reg);
// shouldn't have dirty constants...
pxAssert((type != X86TYPE_GPR || !GPR_IS_DIRTY_CONST(reg)) &&
(type != X86TYPE_PSX || !PSX_IS_DIRTY_CONST(reg)));
@@ -542,7 +543,8 @@ int _checkX86reg(int type, int reg, int mode)
void _addNeededX86reg(int type, int reg)
{
for (uint i = 0; i < iREGCNT_GPR; i++)
u32 i;
for (i = 0; i < iREGCNT_GPR; ++i)
{
if (!x86regs[i].inuse || x86regs[i].reg != reg || x86regs[i].type != type)
continue;
@@ -554,7 +556,8 @@ void _addNeededX86reg(int type, int reg)
void _clearNeededX86regs()
{
for (uint i = 0; i < iREGCNT_GPR; i++)
u32 i;
for (i = 0; i < iREGCNT_GPR; ++i)
{
if (x86regs[i].needed)
{
@@ -606,14 +609,17 @@ void _freeX86regWithoutWriteback(int x86reg)
void _freeX86regs()
{
for (uint i = 0; i < iREGCNT_GPR; i++) {
u32 i;
for (i = 0; i < iREGCNT_GPR; ++i)
{
_freeX86reg(i);
}
}
void _flushX86regs()
{
for (u32 i = 0; i < iREGCNT_GPR; ++i)
u32 i;
for (i = 0; i < iREGCNT_GPR; ++i)
{
if (x86regs[i].inuse && x86regs[i].mode & MODE_WRITE)
{
@@ -499,9 +499,11 @@ static const void* _DynGen_EnterRecompiledCode()
// armAsm->Sub(a64::sp, a64::sp, stack_size);
#endif
// From memory to registry
armMoveAddressToReg(RSTATE_FPU, &fpuRegs);
armMoveAddressToReg(RSTATE_PSX, &psxRegs);
armMoveAddressToReg(RSTATE_CPU, &cpuRegs);
armMoveAddressToReg(RSTATE_VUR, &VU0);
if (CHECK_FASTMEM) {
// xMOV(RFASTMEMBASE, ptrNative[&vtlb_private::vtlbdata.fastmem_base]);
@@ -20,8 +20,8 @@ using namespace x86Emitter;
static u32 GetAllocatedGPRBitmask()
{
u32 mask = 0;
for (u32 i = 0; i < iREGCNT_GPR; i++)
u32 i, mask = 0;
for (i = 0; i < iREGCNT_GPR; ++i)
{
if (x86regs[i].inuse)
mask |= (1u << i);
@@ -31,8 +31,8 @@ static u32 GetAllocatedGPRBitmask()
static u32 GetAllocatedXMMBitmask()
{
u32 mask = 0;
for (u32 i = 0; i < iREGCNT_XMM; i++)
u32 i, mask = 0;
for (i = 0; i < iREGCNT_XMM; ++i)
{
if (xmmregs[i].inuse)
mask |= (1u << i);
@@ -405,11 +405,12 @@ void vtlb_DynGenDispatchers()
// clear the buffer to 0xcc (easier debugging).
std::memset(m_IndirectDispatchers, 0xcc, __pagesize);
for (int mode = 0; mode < 2; ++mode)
int mode, bits, sign;
for (mode = 0; mode < 2; ++mode)
{
for (int bits = 0; bits < 5; ++bits)
for (bits = 0; bits < 5; ++bits)
{
for (int sign = 0; sign < (!mode && bits < 3 ? 2 : 1); ++sign)
for (sign = 0; sign < (!mode && bits < 3 ? 2 : 1); ++sign)
{
armSetAsmPtr(GetIndirectDispatcherPtr(mode, bits, !!sign), INDIRECT_DISPATCHERS_SIZE, nullptr);
armStartBlock();
+35 -28
View File
@@ -67,21 +67,22 @@ void mVUreset(microVU& mVU, bool resetReserve)
armAlignAsmPtr();
mVU.prog.x86ptr = mVU.prog.x86start;
for (u32 i = 0; i < (mVU.progSize / 2); i++)
u32 i, e = (mVU.progSize >> 1); // mVU.progSize / 2
for ( i = 0; i < e; ++i)
{
if (!mVU.prog.prog[i])
{
mVU.prog.prog[i] = new std::deque<microProgram*>();
continue;
}
std::deque<microProgram*>::iterator it(mVU.prog.prog[i]->begin());
auto it(mVU.prog.prog[i]->begin());
for (; it != mVU.prog.prog[i]->end(); ++it)
{
mVUdeleteProg(mVU, it[0]);
}
mVU.prog.prog[i]->clear();
mVU.prog.quick[i].block = NULL;
mVU.prog.quick[i].prog = NULL;
mVU.prog.quick[i].block = NULL;
mVU.prog.quick[i].prog = NULL;
}
}
@@ -89,11 +90,12 @@ void mVUreset(microVU& mVU, bool resetReserve)
void mVUclose(microVU& mVU)
{
// Delete Programs and Block Managers
for (u32 i = 0; i < (mVU.progSize / 2); i++)
u32 i, e = (mVU.progSize >> 1); // mVU.progSize / 2
for (i = 0; i < e; ++i)
{
if (!mVU.prog.prog[i])
continue;
std::deque<microProgram*>::iterator it(mVU.prog.prog[i]->begin());
auto it(mVU.prog.prog[i]->begin());
for (; it != mVU.prog.prog[i]->end(); ++it)
{
mVUdeleteProg(mVU, it[0]);
@@ -105,16 +107,12 @@ void mVUclose(microVU& mVU)
// Clears Block Data in specified range
__fi void mVUclear(mV, u32 addr, u32 size)
{
if (!mVU.prog.cleared)
{
mVU.prog.cleared = 1; // Next execution searches/creates a new microprogram
std::memset(&mVU.prog.lpState, 0, sizeof(mVU.prog.lpState)); // Clear pipeline state
for (u32 i = 0; i < (mVU.progSize / 2); i++)
{
mVU.prog.quick[i].block = NULL; // Clear current quick-reference block
mVU.prog.quick[i].prog = NULL; // Clear current quick-reference prog
}
}
if (!mVU.prog.cleared)
{
mVU.prog.cleared = 1; // Next execution searches/creates a new microprogram
std::memset(&mVU.prog.lpState, 0, sizeof(mVU.prog.lpState)); // Clear pipeline state
std::memset(mVU.prog.quick, 0, (mVU.progSize >> 1) * sizeof(microProgramQuick)); // mVU.progSize / 2
}
}
//------------------------------------------------------------------
@@ -124,7 +122,8 @@ __fi void mVUclear(mV, u32 addr, u32 size)
// Deletes a program
__ri void mVUdeleteProg(microVU& mVU, microProgram*& prog)
{
for (u32 i = 0; i < (mVU.progSize / 2); i++)
u32 i, e = (mVU.progSize >> 1); // mVU.progSize / 2
for (i = 0; i < e; ++i)
{
safe_delete(prog->block[i]);
}
@@ -135,7 +134,7 @@ __ri void mVUdeleteProg(microVU& mVU, microProgram*& prog)
// Creates a new Micro Program
__ri microProgram* mVUcreateProg(microVU& mVU, int startPC)
{
microProgram* prog = (microProgram*)_aligned_malloc(sizeof(microProgram), 64);
auto* prog = (microProgram*)_aligned_malloc(sizeof(microProgram), 64);
memset(prog, 0, sizeof(microProgram));
prog->idx = mVU.prog.total++;
prog->ranges = new std::deque<microRange>();
@@ -179,13 +178,16 @@ u64 mVUrangesHash(microVU& mVU, microProgram& prog)
} hash = {0};
std::deque<microRange>::const_iterator it(prog.ranges->begin());
int i, s, e;
for (; it != prog.ranges->end(); ++it)
{
if ((it[0].start < 0) || (it[0].end < 0))
{
DevCon.Error("microVU%d: Negative Range![%d][%d]", mVU.index, it[0].start, it[0].end);
}
for (int i = it[0].start / 4; i < it[0].end / 4; i++)
s = it[0].start >> 2; // it[0].start / 4
e = it[0].end >> 2; // it[0].end / 4
for (i = s; i < e; ++i)
{
hash.v32[0] -= prog.data[i];
hash.v32[1] ^= prog.data[i];
@@ -198,12 +200,13 @@ u64 mVUrangesHash(microVU& mVU, microProgram& prog)
void mVUprintUniqueRatio(microVU& mVU)
{
std::vector<u64> v;
for (u32 pc = 0; pc < mProgSize / 2; pc++)
u32 pc, e = mProgSize >> 1; // mProgSize / 2
for (pc = 0; pc < e; ++pc)
{
microProgramList* list = mVU.prog.prog[pc];
if (!list)
continue;
std::deque<microProgram*>::iterator it(list->begin());
auto it(list->begin());
for (; it != list->end(); ++it)
{
v.push_back(mVUrangesHash(mVU, *it[0]));
@@ -249,19 +252,23 @@ __fi bool mVUcmpProg(microVU& mVU, microProgram& prog)
_mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState)
{
microVU& mVU = mVUx;
microProgramQuick& quick = mVU.prog.quick[mVU.regs().start_pc / 8];
microProgramList* list = mVU.prog.prog [mVU.regs().start_pc / 8];
u32 start_pc_8 = startPC >> 3; // startPC / 8
u32 regs_start_pc_8 = mVU.regs().start_pc >> 3; // mVU.regs().start_pc / 8
microProgramQuick& quick = mVU.prog.quick[regs_start_pc_8];
microProgramList* list = mVU.prog.prog [regs_start_pc_8];
if (!quick.prog) // If null, we need to search for new program
{
std::deque<microProgram*>::iterator it(list->begin());
auto it(list->begin());
for (; it != list->end(); ++it)
{
bool b = mVUcmpProg(mVU, *it[0]);
if (b)
{
quick.block = it[0]->block[startPC / 8];
quick.block = it[0]->block[start_pc_8];
quick.prog = it[0];
list->erase(it);
list->push_front(quick.prog);
@@ -279,9 +286,9 @@ _mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState)
// If cleared and program not found, make a new program instance
mVU.prog.cleared = 0;
mVU.prog.isSame = 1;
mVU.prog.cur = mVUcreateProg(mVU, mVU.regs().start_pc/8);
mVU.prog.cur = mVUcreateProg(mVU, regs_start_pc_8);
void* entryPoint = mVUblockFetch(mVU, startPC, pState);
quick.block = mVU.prog.cur->block[startPC/8];
quick.block = mVU.prog.cur->block[start_pc_8];
quick.prog = mVU.prog.cur;
list->push_front(mVU.prog.cur);
//mVUprintUniqueRatio(mVU);
@@ -293,7 +300,7 @@ _mVUt __fi void* mVUsearchProg(u32 startPC, uptr pState)
mVU.prog.cur = quick.prog;
// Because the VU's can now run in sections and not whole programs at once
// we need to set the current block so it gets the right program back
quick.block = mVU.prog.cur->block[startPC / 8];
quick.block = mVU.prog.cur->block[start_pc_8];
// Sanity check, in case for some reason the program compilation aborted half way through
if (quick.block == nullptr)
+9 -7
View File
@@ -42,11 +42,12 @@ struct microRange
s32 end; // End PC (The opcode the block ends with)
};
#define mProgSize (0x4000 / 4)
#define mProgSize (0x4000 >> 2) // (0x4000 / 4)
#define mProgSizeHalf (mProgSize >> 1) // mProgSize / 2
struct microProgram
{
u32 data [mProgSize]; // Holds a copy of the VU microProgram
microBlockManager* block[mProgSize / 2]; // Array of Block Managers
microBlockManager* block[mProgSizeHalf]; // Array of Block Managers
std::deque<microRange>* ranges; // The ranges of the microProgram that have already been recompiled
u32 startPC; // Start PC of this program
int idx; // Program index
@@ -63,8 +64,8 @@ struct microProgramQuick
struct microProgManager
{
microIR<mProgSize> IRinfo; // IR information
microProgramList* prog [mProgSize/2]; // List of microPrograms indexed by startPC values
microProgramQuick quick[mProgSize/2]; // Quick reference to valid microPrograms for current execution
microProgramList* prog [mProgSizeHalf]; // List of microPrograms indexed by startPC values
microProgramQuick quick[mProgSizeHalf]; // Quick reference to valid microPrograms for current execution
microProgram* cur; // Pointer to currently running MicroProgram
int total; // Total Number of valid MicroPrograms
int isSame; // Current cached microProgram is Exact Same program as mVU.regs().Micro (-1 = unknown, 0 = No, 1 = Yes)
@@ -185,9 +186,10 @@ public:
else
qListI++;
microBlockLink*& blockList = fullCmp ? fBlockList : qBlockList;
microBlockLink*& blockEnd = fullCmp ? fBlockEnd : qBlockEnd;
microBlockLink* newBlock = (microBlockLink*)_aligned_malloc(sizeof(microBlockLink), 32);
microBlockLink*& blockList = fullCmp ? fBlockList : qBlockList;
microBlockLink*& blockEnd = fullCmp ? fBlockEnd : qBlockEnd;
microBlockLink* newBlock = (microBlockLink*)_aligned_malloc(sizeof(microBlockLink), 32);
newBlock->block.jumpCache = nullptr;
newBlock->next = nullptr;
+8 -8
View File
@@ -106,7 +106,7 @@ __ri void mVUallocSFLAGd(u32* memAddr, const x32& reg = EAX, const x32& tmp1 = E
__fi void mVUallocMFLAGa(mV, const x32& reg, int fInstance)
{
// xMOVZX(reg, ptr16[&mVU.macFlag[fInstance]]);
armAsm->Ldrh(reg, armMemOperandPtr(&mVU.macFlag[fInstance]));
armAsm->Ldrh(reg, PTR_MVU(macFlag[fInstance]));
}
__fi void mVUallocMFLAGb(mV, const x32& reg, int fInstance)
@@ -114,11 +114,11 @@ __fi void mVUallocMFLAGb(mV, const x32& reg, int fInstance)
//xAND(reg, 0xffff);
if (fInstance < 4) {
// xMOV(ptr32[&mVU.macFlag[fInstance]], reg); // microVU
armAsm->Str(reg, armMemOperandPtr(&mVU.macFlag[fInstance]));
armAsm->Str(reg, PTR_MVU(macFlag[fInstance]));
}
else {
// xMOV(ptr32[&mVU.regs().VI[REG_MAC_FLAG].UL], reg); // macroVU
armAsm->Str(reg, armMemOperandPtr(&mVU.regs().VI[REG_MAC_FLAG].UL));
armAsm->Str(reg, PTR_VUR(VI[REG_MAC_FLAG].UL));
}
}
@@ -126,11 +126,11 @@ __fi void mVUallocCFLAGa(mV, const x32& reg, int fInstance)
{
if (fInstance < 4) {
// xMOV(reg, ptr32[&mVU.clipFlag[fInstance]]); // microVU
armAsm->Ldr(reg, armMemOperandPtr(&mVU.clipFlag[fInstance]));
armAsm->Ldr(reg, PTR_MVU(clipFlag[fInstance]));
}
else {
// xMOV(reg, ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL]); // macroVU
armAsm->Ldr(reg, armMemOperandPtr(&mVU.regs().VI[REG_CLIP_FLAG].UL));
armAsm->Ldr(reg, PTR_VUR(VI[REG_CLIP_FLAG].UL));
}
}
@@ -138,11 +138,11 @@ __fi void mVUallocCFLAGb(mV, const x32& reg, int fInstance)
{
if (fInstance < 4) {
// xMOV(ptr32[&mVU.clipFlag[fInstance]], reg); // microVU
armAsm->Str(reg, armMemOperandPtr(&mVU.clipFlag[fInstance]));
armAsm->Str(reg, PTR_MVU(clipFlag[fInstance]));
}
else {
// xMOV(ptr32[&mVU.regs().VI[REG_CLIP_FLAG].UL], reg); // macroVU
armAsm->Str(reg, armMemOperandPtr(&mVU.regs().VI[REG_CLIP_FLAG].UL));
armAsm->Str(reg, PTR_VUR(VI[REG_CLIP_FLAG].UL));
}
}
@@ -154,7 +154,7 @@ void microRegAlloc::writeVIBackup(const a64::Register& reg)
{
microVU& mVU = index ? microVU1 : microVU0;
// xMOV(ptr32[&mVU.VIbackup], xRegister32(reg));
armAsm->Str(a64::WRegister(reg), armMemOperandPtr(&mVU.VIbackup));
armAsm->Str(a64::WRegister(reg), PTR_MVU(VIbackup));
}
//------------------------------------------------------------------
@@ -371,7 +371,8 @@ __ri void flagSet(mV, bool setMacFlag)
//Check which ops need to do the flag settings, also check for runs of ops as they can do multiple calculations to get the sticky status flags (VP2)
//Make sure we get the last 4 calculations (Bloody Roar 3, possibly others)
for (int i = mVUcount, j = 0; i > 0; i--, j++)
int i, j;
for (i = mVUcount, j = 0; i > 0; --i, ++j)
{
j += mVUstall;
incPC(-2);
@@ -505,7 +506,7 @@ static void analyzeBranchVI(mV, int xReg, bool& infoVar)
int iEnd = 4;
int bPC = iPC;
incPC2(-2);
for (i = 0; i < iEnd && cyc < iEnd; i++)
for (i = 0; i < iEnd && cyc < iEnd; ++i)
{
if (i && mVUstall)
{
File diff suppressed because it is too large Load Diff
+50 -40
View File
@@ -139,7 +139,7 @@ void doIbit(mV)
// xMOV(gprT1, ptr32[&curI]);
armAsm->Ldr(gprT1, armMemOperandPtr(&curI));
// xMOV(ptr32[&mVU.getVI(REG_I)], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&mVU.getVI(REG_I)));
armAsm->Str(gprT1, PTR_VUR(VI[REG_I]));
}
else
{
@@ -153,7 +153,7 @@ void doIbit(mV)
tempI = curI;
// xMOV(ptr32[&mVU.getVI(REG_I)], tempI);
armStorePtr(tempI, &mVU.getVI(REG_I));
armStorePtr(tempI, PTR_VUR(VI[REG_I]));
}
incPC(1);
}
@@ -324,14 +324,15 @@ __fi void incQ(mV) { mVU.q ^= 1; }
// so essentially '1' will be the same as '0'...
void mVUoptimizePipeState(mV)
{
for (int i = 0; i < 32; i++)
int i;
for (i = 0; i < 32; ++i)
{
mVUregs.VF[i].x = optimizeReg(mVUregs.VF[i].x);
mVUregs.VF[i].y = optimizeReg(mVUregs.VF[i].y);
mVUregs.VF[i].z = optimizeReg(mVUregs.VF[i].z);
mVUregs.VF[i].w = optimizeReg(mVUregs.VF[i].w);
}
for (int i = 0; i < 16; i++)
for (i = 0; i < 16; ++i)
{
mVUregs.VI[i] = optimizeReg(mVUregs.VI[i]);
}
@@ -344,7 +345,9 @@ void mVUincCycles(mV, int x)
{
mVUcycles += x;
// VF[0] is a constant value (0.0 0.0 0.0 1.0)
for (int z = 31; z > 0; z--)
int z;
for (z = 31; z > 0; --z)
{
mVUregs.VF[z].x = calcCycles(mVUregs.VF[z].x, x);
mVUregs.VF[z].y = calcCycles(mVUregs.VF[z].y, x);
@@ -352,7 +355,7 @@ void mVUincCycles(mV, int x)
mVUregs.VF[z].w = calcCycles(mVUregs.VF[z].w, x);
}
// VI[0] is a constant value (0)
for (int z = 15; z > 0; z--)
for (z = 15; z > 0; --z)
{
mVUregs.VI[z] = calcCycles(mVUregs.VI[z], x);
}
@@ -497,7 +500,7 @@ void mVUtestCycles(microVU& mVU, microFlagCycles& mFC)
}
}
// xMOV(eax, ptr32[&mVU.cycles]);
armAsm->Ldrsw(EAX, armMemOperandPtr(&mVU.cycles));
armAsm->Ldrsw(EAX, PTR_MVU(cycles));
if (EmuConfig.Gamefixes.VUSyncHack) {
// xSUB(eax, mVUcycles); // Running behind, make sure we have time to run the block
armAsm->Subs(EAX, EAX, mVUcycles);
@@ -518,7 +521,7 @@ void mVUtestCycles(microVU& mVU, microFlagCycles& mFC)
if (EmuConfig.Gamefixes.VUSyncHack || EmuConfig.Gamefixes.FullVU0SyncHack) {
// xMOV(ptr32[&mVU.regs().nextBlockCycles], mVUcycles);
armStorePtr(mVUcycles, &mVU.regs().nextBlockCycles);
armStorePtr(mVUcycles, PTR_VUR(nextBlockCycles));
}
mVUendProgram(mVU, &mFC, 0);
@@ -526,7 +529,7 @@ void mVUtestCycles(microVU& mVU, microFlagCycles& mFC)
armBind(&skip);
// xSUB(ptr32[&mVU.cycles], mVUcycles);
armSub(&mVU.cycles, mVUcycles);
armSub(PTR_MVU(cycles), mVUcycles);
}
//------------------------------------------------------------------
@@ -549,7 +552,8 @@ __fi void startLoop(mV)
// Initialize VI Constants (vi15 propagates through blocks)
__fi void mVUinitConstValues(microVU& mVU)
{
for (int i = 0; i < 16; i++)
int i;
for (i = 0; i < 16; ++i)
{
mVUconstReg[i].isValid = 0;
mVUconstReg[i].regValue = 0;
@@ -576,7 +580,7 @@ __fi void mVUinitFirstPass(microVU& mVU, uptr pState, u8* thisPtr)
memcpy((u8*)&mVU.prog.lpState, (u8*)pState, sizeof(microRegInfo));
}
mVUblock.x86ptrStart = thisPtr;
mVUpBlock = mVUblocks[mVUstartPC / 2]->add(mVU, &mVUblock); // Add this block to block manager
mVUpBlock = mVUblocks[mVUstartPC >> 1]->add(mVU, &mVUblock); // Add this block to block manager (mVUstartPC / 2)
mVUregs.needExactMatch = (mVUpBlock->pState.blockType) ? 7 : 0; // ToDo: Fix 1-Op block flag linking (MGS2:Demo/Sly Cooper)
mVUregs.blockType = 0;
mVUregs.viBackUp = 0;
@@ -597,7 +601,7 @@ void mVUDoDBit(microVU& mVU, microFlagCycles* mFC)
}
else {
// xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x400 : 0x4));
armAsm->Tst(armLoadPtr(&VU0.VI[REG_FBRST].UL), (isVU1 ? 0x400 : 0x4));
armAsm->Tst(armLoadPtr(PTR_VUR(VI[REG_FBRST].UL)), (isVU1 ? 0x400 : 0x4));
}
// xForwardJump32 eJMP(Jcc_Zero);
a64::Label eJMP;
@@ -605,9 +609,9 @@ void mVUDoDBit(microVU& mVU, microFlagCycles* mFC)
if (!isVU1 || !THREAD_VU1)
{
// xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x200 : 0x2));
armOrr(&VU0.VI[REG_VPU_STAT].UL, (isVU1 ? 0x200 : 0x2));
armOrr(PTR_VUR(VI[REG_VPU_STAT].UL), (isVU1 ? 0x200 : 0x2));
// xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT);
armOrr(&mVU.regs().flags, VUFLAG_INTCINTERRUPT);
armOrr(PTR_VUR(flags), VUFLAG_INTCINTERRUPT);
}
incPC(1);
mVUDTendProgram(mVU, mFC, 1);
@@ -624,7 +628,7 @@ void mVUDoTBit(microVU& mVU, microFlagCycles* mFC)
}
else {
// xTEST(ptr32[&VU0.VI[REG_FBRST].UL], (isVU1 ? 0x800 : 0x8));
armAsm->Tst(armLoadPtr(&VU0.VI[REG_FBRST].UL), (isVU1 ? 0x800 : 0x8));
armAsm->Tst(armLoadPtr(PTR_VUR(VI[REG_FBRST].UL)), (isVU1 ? 0x800 : 0x8));
}
// xForwardJump32 eJMP(Jcc_Zero);
a64::Label eJMP;
@@ -632,9 +636,9 @@ void mVUDoTBit(microVU& mVU, microFlagCycles* mFC)
if (!isVU1 || !THREAD_VU1)
{
// xOR(ptr32[&VU0.VI[REG_VPU_STAT].UL], (isVU1 ? 0x400 : 0x4));
armOrr(&VU0.VI[REG_VPU_STAT].UL, (isVU1 ? 0x400 : 0x4));
armOrr(PTR_VUR(VI[REG_VPU_STAT].UL), (isVU1 ? 0x400 : 0x4));
// xOR(ptr32[&mVU.regs().flags], VUFLAG_INTCINTERRUPT);
armOrr(&mVU.regs().flags, VUFLAG_INTCINTERRUPT);
armOrr(PTR_VUR(flags), VUFLAG_INTCINTERRUPT);
}
incPC(1);
mVUDTendProgram(mVU, mFC, 1);
@@ -658,14 +662,15 @@ static void mvuPreloadRegisters(microVU& mVU, u32 endCount)
u32 vfs_loaded = 0;
u32 vis_loaded = 0;
for (int reg = 0; reg < mVU.regAlloc->getXmmCount(); reg++)
int reg;
for (reg = 0; reg < mVU.regAlloc->getXmmCount(); ++reg)
{
const int vf = mVU.regAlloc->getRegVF(reg);
if (vf >= 0)
vfs_loaded |= (1u << vf);
}
for (int reg = 0; reg < mVU.regAlloc->getGPRCount(); reg++)
for (reg = 0; reg < mVU.regAlloc->getGPRCount(); ++reg)
{
const int vi = mVU.regAlloc->getRegVI(reg);
if (vi >= 0)
@@ -701,7 +706,8 @@ static void mvuPreloadRegisters(microVU& mVU, u32 endCount)
return (free_regs >= REQUIRED_FREE_XMMS || free_gprs >= REQUIRED_FREE_GPRS);
};
for (u32 x = 0; x < endCount && canPreload(); x++)
u32 x, i;
for (x = 0; x < endCount && canPreload(); ++x)
{
incPC(1);
@@ -709,7 +715,7 @@ static void mvuPreloadRegisters(microVU& mVU, u32 endCount)
if (info->doXGKICK)
break;
for (u32 i = 0; i < 2; i++)
for (i = 0; i < 2; ++i)
{
preloadVF(info->uOp.VF_read[i].reg);
preloadVF(info->lOp.VF_read[i].reg);
@@ -741,17 +747,18 @@ static void mvuPreloadRegisters(microVU& mVU, u32 endCount)
void* mVUcompile(microVU& mVU, u32 startPC, uptr pState)
{
microFlagCycles mFC;
microFlagCycles mFC{};
u8* thisPtr = armGetCurrentCodePointer();
const u32 endCount = (((microRegInfo*)pState)->blockType) ? 1 : (mVU.microMemSize / 8);
const u32 endCount = (((microRegInfo*)pState)->blockType) ? 1 : (mVU.microMemSize >> 3); // mVU.microMemSize / 8
// First Pass
iPC = startPC / 4;
iPC = startPC >> 2; // startPC / 4
mVUsetupRange(mVU, startPC, 1); // Setup Program Bounds/Range
mVU.regAlloc->reset(false); // Reset regAlloc
mVUinitFirstPass(mVU, pState, thisPtr);
mVUbranch = 0;
for (int branch = 0; mVUcount < endCount;)
int branch;
for (branch = 0; mVUcount < endCount;)
{
incPC(1);
startLoop(mVU);
@@ -919,7 +926,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState)
mvuPreloadRegisters(mVU, endCount);
for (; x < endCount; x++)
for (; x < endCount; ++x)
{
#if 0
if (mVU.index == 1 && (x == 0 || true))
@@ -940,7 +947,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState)
if (mVUup.mBit)
{
// xOR(ptr32[&mVU.regs().flags], VUFLAG_MFLAGSET);
armOrr(&mVU.regs().flags, VUFLAG_MFLAGSET);
armOrr(PTR_VUR(flags), VUFLAG_MFLAGSET);
}
if (isVU1 && mVUlow.kickcycles && CHECK_XGKICKHACK)
@@ -968,7 +975,8 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState)
// Make sure we save the current state so it can come back to it
u32* cpS = (u32*)&mVUregs;
u32* lpS = (u32*)&mVU.prog.lpState;
for (size_t i = 0; i < (sizeof(microRegInfo) - 4) / 4; i++, lpS++, cpS++)
size_t i, e = (sizeof(microRegInfo) - 4) >> 2; // sizeof(microRegInfo) - 4
for (i = 0; i < e; ++i, ++lpS, ++cpS)
{
// xMOV(ptr32[lpS], cpS[0]);
armStorePtr(cpS[0], lpS);
@@ -977,7 +985,7 @@ void* mVUcompile(microVU& mVU, u32 startPC, uptr pState)
mVUsetupRange(mVU, xPC, false);
if (EmuConfig.Gamefixes.VUSyncHack || EmuConfig.Gamefixes.FullVU0SyncHack) {
// xMOV(ptr32[&mVU.regs().nextBlockCycles], 0);
armStorePtr(0, &mVU.regs().nextBlockCycles);
armStorePtr(0, PTR_VUR(nextBlockCycles));
}
mVUendProgram(mVU, &mFC, 0);
normBranchCompile(mVU, xPC);
@@ -1086,29 +1094,31 @@ __fi void* mVUentryGet(microVU& mVU, microBlockManager* block, u32 startPC, uptr
// Search for Existing Compiled Block (if found, return x86ptr; else, compile and return x86ptr)
__fi void* mVUblockFetch(microVU& mVU, u32 startPC, uptr pState)
{
pxAssert((startPC & 7) == 0);
pxAssert(startPC <= mVU.microMemSize - 8);
startPC &= mVU.microMemSize - 8;
blockCreate(startPC / 8);
return mVUentryGet(mVU, mVUblocks[startPC / 8], startPC, pState);
u32 startPC_8 = startPC >> 3; // startPC / 8
blockCreate(startPC_8);
return mVUentryGet(mVU, mVUblocks[startPC_8], startPC, pState);
}
// mVUcompileJIT() - Called By JR/JALR during execution
_mVUt void* mVUcompileJIT(u32 startPC, uptr ptr)
{
u32 startPC_8 = startPC >> 3; // startPC / 8
if (doJumpAsSameProgram) // Treat jump as part of same microProgram
{
if (doJumpCaching) // When doJumpCaching, ptr is a microBlock pointer
{
microVU& mVU = mVUx;
microBlock* pBlock = (microBlock*)ptr;
microJumpCache& jc = pBlock->jumpCache[startPC / 8];
if (jc.prog && jc.prog == mVU.prog.quick[startPC / 8].prog)
auto* pBlock = (microBlock*)ptr;
microJumpCache& jc = pBlock->jumpCache[startPC_8];
if (jc.prog && jc.prog == mVU.prog.quick[startPC_8].prog)
return jc.x86ptrStart;
void* v = mVUblockFetch(mVUx, startPC, (uptr)&pBlock->pStateEnd);
jc.prog = mVU.prog.quick[startPC / 8].prog;
jc.prog = mVU.prog.quick[startPC_8].prog;
jc.x86ptrStart = v;
return v;
}
@@ -1118,12 +1128,12 @@ _mVUt void* mVUcompileJIT(u32 startPC, uptr ptr)
if (doJumpCaching) // When doJumpCaching, ptr is a microBlock pointer
{
microVU& mVU = mVUx;
microBlock* pBlock = (microBlock*)ptr;
microJumpCache& jc = pBlock->jumpCache[startPC / 8];
if (jc.prog && jc.prog == mVU.prog.quick[startPC / 8].prog)
auto* pBlock = (microBlock*)ptr;
microJumpCache& jc = pBlock->jumpCache[startPC_8];
if (jc.prog && jc.prog == mVU.prog.quick[startPC_8].prog)
return jc.x86ptrStart;
void* v = mVUsearchProg<vuIndex>(startPC, (uptr)&pBlock->pStateEnd);
jc.prog = mVU.prog.quick[startPC / 8].prog;
jc.prog = mVU.prog.quick[startPC_8].prog;
jc.x86ptrStart = v;
return v;
}
+33 -27
View File
@@ -28,6 +28,11 @@ void mVUdispatcherAB(mV)
// xScopedStackFrame frame(false, true);
armBeginStackFrame();
// From memory to registry
armMoveAddressToReg(RSTATE_MVU, &mVU);
armMoveAddressToReg(RSTATE_VU1, &VU1);
armMoveAddressToReg(RSTATE_VUR, &mVU.regs());
// = The caller has already put the needed parameters in ecx/edx:
if (!isVU1) {
// xFastCall((void*)mVUexecuteVU0, arg1reg, arg2reg);
@@ -48,11 +53,11 @@ void mVUdispatcherAB(mV)
// Load Regs
// xMOVAPS (xmmT1, ptr128[&mVU.regs().VI[REG_P].UL]);
armAsm->Ldr(xmmT1, armMemOperandPtr(&mVU.regs().VI[REG_P].UL));
armAsm->Ldr(xmmT1, PTR_VUR(VI[REG_P].UL));
// xMOVAPS (xmmPQ, ptr128[&mVU.regs().VI[REG_Q].UL]);
armAsm->Ldr(xmmPQ, armMemOperandPtr(&mVU.regs().VI[REG_Q].UL));
armAsm->Ldr(xmmPQ, PTR_VUR(VI[REG_Q].UL));
// xMOVDZX (xmmT2, ptr32[&mVU.regs().pending_q]);
armAsm->Ldr(xmmT2, armMemOperandPtr(&mVU.regs().pending_q));
armAsm->Ldr(xmmT2, PTR_VUR(pending_q));
// xSHUF.PS(xmmPQ, xmmT1, 0); // wzyx = PPQQ
armSHUFPS(xmmPQ, xmmT1, 0);
//Load in other Q instance
@@ -67,7 +72,7 @@ void mVUdispatcherAB(mV)
{
//Load in other P instance
// xMOVDZX(xmmT2, ptr32[&mVU.regs().pending_p]);
armAsm->Ldr(xmmT2, armMemOperandPtr(&mVU.regs().pending_p));
armAsm->Ldr(xmmT2, PTR_VUR(pending_p));
// xPSHUF.D(xmmPQ, xmmPQ, 0x1B);
armPSHUFD(xmmPQ, xmmPQ, 0x1B);
// xMOVSS(xmmPQ, xmmT2);
@@ -77,23 +82,23 @@ void mVUdispatcherAB(mV)
}
// xMOVAPS(xmmT1, ptr128[&mVU.regs().micro_macflags]);
armAsm->Ldr(xmmT1.Q(), armMemOperandPtr(&mVU.regs().micro_macflags));
armAsm->Ldr(xmmT1.Q(), PTR_VUR(micro_macflags));
// xMOVAPS(ptr128[mVU.macFlag], xmmT1);
armAsm->Str(xmmT1.Q(), armMemOperandPtr(mVU.macFlag));
armAsm->Str(xmmT1.Q(), PTR_MVU(macFlag));
// xMOVAPS(xmmT1, ptr128[&mVU.regs().micro_clipflags]);
armAsm->Ldr(xmmT1.Q(), armMemOperandPtr(&mVU.regs().micro_clipflags));
armAsm->Ldr(xmmT1.Q(), PTR_VUR(micro_clipflags));
// xMOVAPS(ptr128[mVU.clipFlag], xmmT1);
armAsm->Str(xmmT1.Q(), armMemOperandPtr(mVU.clipFlag));
armAsm->Str(xmmT1.Q(), PTR_MVU(clipFlag));
// xMOV(gprF0, ptr32[&mVU.regs().micro_statusflags[0]]);
armAsm->Ldr(gprF0, armMemOperandPtr(&mVU.regs().micro_statusflags[0]));
armAsm->Ldr(gprF0, PTR_VUR(micro_statusflags[0]));
// xMOV(gprF1, ptr32[&mVU.regs().micro_statusflags[1]]);
armAsm->Ldr(gprF1, armMemOperandPtr(&mVU.regs().micro_statusflags[1]));
armAsm->Ldr(gprF1, PTR_VUR(micro_statusflags[1]));
// xMOV(gprF2, ptr32[&mVU.regs().micro_statusflags[2]]);
armAsm->Ldr(gprF2, armMemOperandPtr(&mVU.regs().micro_statusflags[2]));
armAsm->Ldr(gprF2, PTR_VUR(micro_statusflags[2]));
// xMOV(gprF3, ptr32[&mVU.regs().micro_statusflags[3]]);
armAsm->Ldr(gprF3, armMemOperandPtr(&mVU.regs().micro_statusflags[3]));
armAsm->Ldr(gprF3, PTR_VUR(micro_statusflags[3]));
// Jump to Recompiled Code Block
// xJMP(rax);
@@ -149,13 +154,13 @@ void mVUdispatcherCD(mV)
mVUrestoreRegs(mVU);
// xMOV(gprF0, ptr32[&mVU.regs().micro_statusflags[0]]);
armAsm->Ldr(gprF0, armMemOperandPtr(&mVU.regs().micro_statusflags[0]));
armAsm->Ldr(gprF0, PTR_VUR(micro_statusflags[0]));
// xMOV(gprF1, ptr32[&mVU.regs().micro_statusflags[1]]);
armAsm->Ldr(gprF1, armMemOperandPtr(&mVU.regs().micro_statusflags[1]));
armAsm->Ldr(gprF1, PTR_VUR(micro_statusflags[1]));
// xMOV(gprF2, ptr32[&mVU.regs().micro_statusflags[2]]);
armAsm->Ldr(gprF2, armMemOperandPtr(&mVU.regs().micro_statusflags[2]));
armAsm->Ldr(gprF2, PTR_VUR(micro_statusflags[2]));
// xMOV(gprF3, ptr32[&mVU.regs().micro_statusflags[3]]);
armAsm->Ldr(gprF3, armMemOperandPtr(&mVU.regs().micro_statusflags[3]));
armAsm->Ldr(gprF3, PTR_VUR(micro_statusflags[3]));
// Jump to Recompiled Code Block
// xJMP(ptrNative[&mVU.resumePtrXG]);
@@ -165,13 +170,13 @@ void mVUdispatcherCD(mV)
// Backup Status Flag (other regs were backed up on xgkick)
// xMOV(ptr32[&mVU.regs().micro_statusflags[0]], gprF0);
armAsm->Str(gprF0, armMemOperandPtr(&mVU.regs().micro_statusflags[0]));
armAsm->Str(gprF0, PTR_VUR(micro_statusflags[0]));
// xMOV(ptr32[&mVU.regs().micro_statusflags[1]], gprF1);
armAsm->Str(gprF1, armMemOperandPtr(&mVU.regs().micro_statusflags[1]));
armAsm->Str(gprF1, PTR_VUR(micro_statusflags[1]));
// xMOV(ptr32[&mVU.regs().micro_statusflags[2]], gprF2);
armAsm->Str(gprF2, armMemOperandPtr(&mVU.regs().micro_statusflags[2]));
armAsm->Str(gprF2, PTR_VUR(micro_statusflags[2]));
// xMOV(ptr32[&mVU.regs().micro_statusflags[3]], gprF3);
armAsm->Str(gprF3, armMemOperandPtr(&mVU.regs().micro_statusflags[3]));
armAsm->Str(gprF3, PTR_VUR(micro_statusflags[3]));
// Load EE's MXCSR state
if (mvuNeedsFPCRUpdate(mVU)) {
@@ -271,18 +276,20 @@ static void mVUGenerateCopyPipelineState(mV)
// xMOVAPS(xmm5, ptr[rax + 80u]);
armAsm->Ldr(xmm5, a64::MemOperand(RAX, 80u));
a64::MemOperand mop = PTR_MVU(prog.lpState);
// xMOVUPS(ptr[reinterpret_cast<u8*>(&mVU.prog.lpState)], xmm0);
armAsm->Str(xmm0, armMemOperandPtr(reinterpret_cast<u8*>(&mVU.prog.lpState)));
armAsm->Str(xmm0, mop);
// xMOVUPS(ptr[reinterpret_cast<u8*>(&mVU.prog.lpState) + 16u], xmm1);
armAsm->Str(xmm1, armMemOperandPtr(reinterpret_cast<u8*>(&mVU.prog.lpState) + 16u));
armAsm->Str(xmm1, armOffsetMemOperand(mop, 16u));
// xMOVUPS(ptr[reinterpret_cast<u8*>(&mVU.prog.lpState) + 32u], xmm2);
armAsm->Str(xmm2, armMemOperandPtr(reinterpret_cast<u8*>(&mVU.prog.lpState) + 32u));
armAsm->Str(xmm2, armOffsetMemOperand(mop, 32u));
// xMOVUPS(ptr[reinterpret_cast<u8*>(&mVU.prog.lpState) + 48u], xmm3);
armAsm->Str(xmm3, armMemOperandPtr(reinterpret_cast<u8*>(&mVU.prog.lpState) + 48u));
armAsm->Str(xmm3, armOffsetMemOperand(mop, 48u));
// xMOVUPS(ptr[reinterpret_cast<u8*>(&mVU.prog.lpState) + 64u], xmm4);
armAsm->Str(xmm4, armMemOperandPtr(reinterpret_cast<u8*>(&mVU.prog.lpState) + 64u));
armAsm->Str(xmm4, armOffsetMemOperand(mop, 64u));
// xMOVUPS(ptr[reinterpret_cast<u8*>(&mVU.prog.lpState) + 80u], xmm5);
armAsm->Str(xmm5, armMemOperandPtr(reinterpret_cast<u8*>(&mVU.prog.lpState) + 80u));
armAsm->Str(xmm5, armOffsetMemOperand(mop, 80u));
}
// xRET();
@@ -375,7 +382,6 @@ static void mVUGenerateCompareState(mV)
// Executes for number of cycles
_mVUt void* mVUexecute(u32 startPC, u32 cycles)
{
microVU& mVU = mVUx;
u32 vuLimit = vuIndex ? 0x3ff8 : 0xff8;
if (startPC > vuLimit + 7)
+25 -20
View File
@@ -16,7 +16,7 @@ __fi void mVUdivSet(mV)
// xAND(getFlagReg(sFLAG.write), 0xfff3ffff);
armAsm->And(reg32, reg32, 0xfff3ffff);
// xOR(getFlagReg(sFLAG.write), ptr32[&mVU.divFlag]);
armAsm->Orr(reg32, reg32, armLoadPtr(&mVU.divFlag));
armAsm->Orr(reg32, reg32, armLoadPtr(PTR_MVU(divFlag)));
}
}
@@ -34,7 +34,7 @@ __fi void mVUstatusFlagOp(mV)
}
else
{
for (; i > 0; i--)
for (; i > 0; --i)
{
incPC2(-2);
if (sFLAG.doNonSticky)
@@ -51,7 +51,7 @@ __fi void mVUstatusFlagOp(mV)
}
if (runLoop)
{
for (; i > 0; i--)
for (; i > 0; --i)
{
incPC2(-2);
@@ -67,8 +67,8 @@ __fi void mVUstatusFlagOp(mV)
int findFlagInst(int* fFlag, int cycles)
{
int j = 0, jValue = -1;
for (int i = 0; i < 4; i++)
int i, j = 0, jValue = -1;
for (i = 0; i < 4; ++i)
{
if ((fFlag[i] <= cycles) && (fFlag[i] > jValue))
{
@@ -83,8 +83,8 @@ int findFlagInst(int* fFlag, int cycles)
int sortFlag(int* fFlag, int* bFlag, int cycles)
{
int lFlag = -5;
int x = 0;
for (int i = 0; i < 4; i++)
int i, x = 0;
for (i = 0; i < 4; ++i)
{
bFlag[i] = findFlagInst(fFlag, cycles);
if (lFlag != bFlag[i])
@@ -98,9 +98,10 @@ int sortFlag(int* fFlag, int* bFlag, int cycles)
void sortFullFlag(int* fFlag, int* bFlag)
{
int m = std::max(std::max(fFlag[0], fFlag[1]), std::max(fFlag[2], fFlag[3]));
for (int i = 0; i < 4; i++)
int i, t;
for (i = 0; i < 4; ++i)
{
int t = 3 - (m - fFlag[i]);
t = 3 - (m - fFlag[i]);
bFlag[i] = (t < 0) ? 0 : t + 1;
}
}
@@ -116,7 +117,8 @@ __fi void mVUsetFlags(mV, microFlagCycles& mFC)
//bool writeProtect = false;
// Ensure last ~4+ instructions update mac/status flags (if next block's first 4 instructions will read them)
for (int i = mVUcount; i > 0; i--, aCount++)
int i;
for (i = mVUcount; i > 0; --i, ++aCount)
{
if (sFLAG.doFlag)
{
@@ -143,8 +145,9 @@ __fi void mVUsetFlags(mV, microFlagCycles& mFC)
// Status/Mac Flags Setup Code
int xS = 0, xM = 0, xC = 0;
int cyclesAddFour;
for (int i = 0; i < 4; i++)
for (i = 0; i < 4; ++i)
{
mFC.xStatus[i] = i;
mFC.xMac [i] = i;
@@ -182,7 +185,7 @@ __fi void mVUsetFlags(mV, microFlagCycles& mFC)
mFC.cycles = 0;
u32 xCount = mVUcount; // Backup count
iPC = mVUstartPC;
for (mVUcount = 0; mVUcount < xCount; mVUcount++)
for (mVUcount = 0; mVUcount < xCount; ++mVUcount)
{
if (mVUlow.isFSSET && !noFlagOpts)
{
@@ -222,21 +225,23 @@ __fi void mVUsetFlags(mV, microFlagCycles& mFC)
}
}
cyclesAddFour = mFC.cycles + 4;
if (sFlagCond)
{
mFC.xStatus[xS] = mFC.cycles + 4;
mFC.xStatus[xS] = cyclesAddFour;
xS = (xS + 1) & 3;
}
if (mFLAG.doFlag)
{
mFC.xMac[xM] = mFC.cycles + 4;
mFC.xMac[xM] = cyclesAddFour;
xM = (xM + 1) & 3;
}
if (cFLAG.doFlag)
{
mFC.xClip[xC] = mFC.cycles + 4;
mFC.xClip[xC] = cyclesAddFour;
xC = (xC + 1) & 3;
}
@@ -259,7 +264,6 @@ __fi void mVUsetFlags(mV, microFlagCycles& mFC)
// Recompiles Code for Proper Flags on Block Linkings
__fi void mVUsetupFlags(mV, microFlagCycles& mFC)
{
if (mVUregs.flagInfo & 1)
{
if (mVUregs.needExactMatch)
@@ -392,8 +396,8 @@ __fi void mVUsetupFlags(mV, microFlagCycles& mFC)
// Scan through instructions and check if flags are read (FSxxx, FMxxx, FCxxx opcodes)
void _mVUflagPass(mV, u32 startPC, u32 sCount, u32 found, std::vector<u32>& v)
{
for (u32 i = 0; i < v.size(); i++)
u32 i, e = v.size();
for (i = 0; i < e; ++i)
{
if (v[i] == startPC)
return; // Prevent infinite recursion
@@ -403,9 +407,10 @@ void _mVUflagPass(mV, u32 startPC, u32 sCount, u32 found, std::vector<u32>& v)
int oldPC = iPC;
int oldBranch = mVUbranch;
int aBranchAddr = 0;
iPC = startPC / 4;
iPC = startPC >> 2; // startPC / 4
mVUbranch = 0;
for (int branch = 0; sCount < 4; sCount += found)
int branch;
for (branch = 0; sCount < 4; sCount += found)
{
mVUregs.needExactMatch &= 7;
incPC(1);
+98 -71
View File
@@ -244,18 +244,19 @@ protected:
bool regAllocCOP2; // Local COP2 check
// Helper functions to get VU regs
VURegs& regs() const { return ::vuRegs[index]; }
__fi REG_VI& getVI(uint reg) const { return regs().VI[reg]; }
__fi VECTOR& getVF(uint reg) const { return regs().VF[reg]; }
// VURegs& regs() const { return ::vuRegs[index]; }
// __fi REG_VI& getVI(uint reg) const { return regs().VI[reg]; }
// __fi VECTOR& getVF(uint reg) const { return regs().VF[reg]; }
__ri void loadIreg(const xmm& reg, int xyzw)
{
for (int i = 0; i < gprTotal; i++)
int i;
for (i = 0; i < gprTotal; ++i)
{
if (gprMap[i].VIreg == REG_I)
{
// xMOVDZX(reg, xRegister32(i));
armAsm->Fmov(reg.S(), a64::Register(i, a64::kWRegSize));
armAsm->Fmov(reg.S(), armWRegister(i));
if (!_XYZWss(xyzw)) {
// xSHUF.PS(reg, reg, 0);
armSHUFPS(reg, reg, 0);
@@ -265,7 +266,7 @@ protected:
}
// xMOVSSZX(reg, ptr32[&getVI(REG_I)]);
armAsm->Ldr(reg.S(), armMemOperandPtr(&getVI(REG_I)));
armAsm->Ldr(reg.S(), PTR_VUR(VI[REG_I]));
if (!_XYZWss(xyzw)) {
// xSHUF.PS(reg, reg, 0);
armSHUFPS(reg, reg, 0);
@@ -274,7 +275,8 @@ protected:
int findFreeRegRec(int startIdx)
{
for (int i = startIdx; i < xmmTotal; i++)
int i;
for (i = startIdx; i < xmmTotal; ++i)
{
if (!xmmMap[i].isNeeded)
{
@@ -294,7 +296,8 @@ protected:
return _allocVFtoXMMreg(vfreg, 0);
}
for (int i = 0; i < xmmTotal; i++)
int i;
for (i = 0; i < xmmTotal; ++i)
{
if (!xmmMap[i].isNeeded && (xmmMap[i].VFreg < 0))
{
@@ -308,7 +311,8 @@ protected:
int findFreeGPRRec(int startIdx)
{
for (int i = startIdx; i < gprTotal; i++)
int i;
for (i = startIdx; i < gprTotal; ++i)
{
if (gprMap[i].usable && !gprMap[i].isNeeded)
{
@@ -326,7 +330,8 @@ protected:
if (regAllocCOP2)
return _allocX86reg(X86TYPE_VIREG, vireg, MODE_COP2);
for (int i = 0; i < gprTotal; i++)
int i;
for (i = 0; i < gprTotal; ++i)
{
if (gprMap[i].usable && !gprMap[i].isNeeded && (gprMap[i].VIreg < 0))
{
@@ -347,12 +352,13 @@ public:
// mark gpr registers as usable
gprMap.fill({0, 0, false, false, false, false});
for (uint i = 0; i < gprTotal; i++)
uint i, T1 = gprT1.GetCode(), T2 = gprT2.GetCode(), F0 = gprF0.GetCode(), F1 = gprF1.GetCode(), F2 = gprF2.GetCode(), F3 = gprF3.GetCode();
for (i = 0; i < gprTotal; ++i)
{
if (i == gprT1.GetCode() || i == gprT2.GetCode() ||
i == gprF0.GetCode() || i == gprF1.GetCode() || i == gprF2.GetCode() || i == gprF3.GetCode()
if (i == T1 || i == T2 || i == F0 || i == F1 || i == F2 || i == F3
|| i == 4 //i == rsp.GetId()
|| i == a64::x16.GetCode() || i == a64::x17.GetCode() || i == a64::x18.GetCode()
|| i == 16 || i == 17 || i == 18 //i == a64::x16.GetCode() || i == a64::x17.GetCode() || i == a64::x18.GetCode()
|| i >= iREGCNT_GPR
) {
continue;
@@ -372,9 +378,10 @@ public:
// we run this at the of cop2, so don't free fprs
regAllocCOP2 = false;
for (int i = 0; i < xmmTotal; i++)
int i;
for (i = 0; i < xmmTotal; ++i)
clearReg(i);
for (int i = 0; i < gprTotal; i++)
for (i = 0; i < gprTotal; ++i)
clearGPR(i);
counter = 0;
@@ -383,7 +390,7 @@ public:
if (cop2mode)
{
for (int i = 0; i < xmmTotal; i++)
for (i = 0; i < xmmTotal; ++i)
{
if (!pxmmregs[i].inuse || pxmmregs[i].type != XMMTYPE_VFREG)
continue;
@@ -402,7 +409,7 @@ public:
}
}
for (int i = 0; i < gprTotal; i++)
for (i = 0; i < gprTotal; ++i)
{
if (!x86regs[i].inuse || x86regs[i].type != X86TYPE_VIREG)
continue;
@@ -431,9 +438,9 @@ public:
int getFreeXmmCount()
{
int count = 0;
int i, count = 0;
for (int i = 0; i < xmmTotal; i++)
for (i = 0; i < xmmTotal; ++i)
{
if (!xmmMap[i].isNeeded && (xmmMap[i].VFreg < 0))
count++;
@@ -444,7 +451,8 @@ public:
bool hasRegVF(int vfreg)
{
for (int i = 0; i < xmmTotal; i++)
int i;
for (i = 0; i < xmmTotal; ++i)
{
if (xmmMap[i].VFreg == vfreg)
return true;
@@ -465,9 +473,9 @@ public:
int getFreeGPRCount()
{
int count = 0;
int i, count = 0;
for (int i = 0; i < gprTotal; i++)
for (i = 0; i < gprTotal; ++i)
{
if (!gprMap[i].usable && (gprMap[i].VIreg < 0))
count++;
@@ -478,7 +486,8 @@ public:
bool hasRegVI(int vireg)
{
for (int i = 0; i < gprTotal; i++)
int i;
for (i = 0; i < gprTotal; ++i)
{
if (gprMap[i].VIreg == vireg)
return true;
@@ -497,26 +506,29 @@ public:
// If clearState is 1, then it invalidates all cached reg data after write-back
void flushAll(bool clearState = true)
{
for (int i = 0; i < xmmTotal; i++)
int i;
for (i = 0; i < xmmTotal; ++i)
{
writeBackReg(xmm(i));
if (clearState)
clearReg(i);
}
for (int i = 0; i < gprTotal; i++)
for (i = 0; i < gprTotal; ++i)
{
writeBackReg(a64::WRegister(i), true);
if (clearState)
clearGPR(i);
}
usleep(1000);
// Wait flush
usleep(2000);
}
void flushCallerSavedRegisters(bool clearNeeded = false)
{
for (int i = 0; i < xmmTotal; i++)
int i;
for (i = 0; i < xmmTotal; ++i)
{
if (!armIsCallerSavedXmm(i))
continue;
@@ -526,7 +538,7 @@ public:
clearReg(i);
}
for (int i = 0; i < gprTotal; i++)
for (i = 0; i < gprTotal; ++i)
{
if (!armIsCallerSaved(i))
continue;
@@ -539,7 +551,8 @@ public:
void flushPartialForCOP2()
{
for (int i = 0; i < xmmTotal; i++)
int i;
for (i = 0; i < xmmTotal; ++i)
{
microMapXMM& clear = xmmMap[i];
@@ -562,7 +575,7 @@ public:
clear = {-1, 0, 0, false, false};
}
for (int i = 0; i < gprTotal; i++)
for (i = 0; i < gprTotal; ++i)
{
microMapGPR& clear = gprMap[i];
if (clear.VIreg < 0)
@@ -574,7 +587,8 @@ public:
{
// NOTE: We don't clear state here, this happens in an optional branch
for (int i = 0; i < xmmTotal; i++)
int i;
for (i = 0; i < xmmTotal; ++i)
{
microMapXMM& mapX = xmmMap[xmm(i).GetCode()];
@@ -582,20 +596,20 @@ public:
{
if (mapX.VFreg == 33) {
// xMOVSS(ptr32[&getVI(REG_I)], xmm(i));
armAsm->Str(xmm(i).S(), armMemOperandPtr(&getVI(REG_I)));
armAsm->Str(xmm(i).S(), PTR_VUR(VI[REG_I]));
}
else if (mapX.VFreg == 32) {
// mVUsaveReg(xmm(i), ptr[&regs().ACC], mapX.xyzw, 1);
mVUsaveReg(xmm(i), armMemOperandPtr(&regs().ACC), mapX.xyzw, 1);
mVUsaveReg(xmm(i), PTR_VUR(ACC), mapX.xyzw, 1);
}
else {
// mVUsaveReg(xmm(i), ptr[&getVF(mapX.VFreg)], mapX.xyzw, 1);
mVUsaveReg(xmm(i), armMemOperandPtr(&getVF(mapX.VFreg)), mapX.xyzw, 1);
mVUsaveReg(xmm(i), PTR_VUR(VF[mapX.VFreg]), mapX.xyzw, 1);
}
}
}
for (int i = 0; i < gprTotal; i++) {
for (i = 0; i < gprTotal; ++i) {
writeBackReg(a64::WRegister(i), false);
}
}
@@ -639,7 +653,8 @@ public:
void clearRegVF(int VFreg)
{
for (int i = 0; i < xmmTotal; i++)
int i;
for (i = 0; i < xmmTotal; ++i)
{
if (xmmMap[i].VFreg == VFreg)
clearReg(i);
@@ -669,30 +684,32 @@ public:
// If reg was not modified, then keeps the VF reg cached in the xmm register.
void writeBackReg(const xmm& reg, bool invalidateRegs = true)
{
microMapXMM& mapX = xmmMap[reg.GetCode()];
u32 reg_code = reg.GetCode();
microMapXMM& mapX = xmmMap[reg_code];
if ((mapX.VFreg > 0) && mapX.xyzw) // Reg was modified and not Temp or vf0
{
if (mapX.VFreg == 33) {
// xMOVSS(ptr32[&getVI(REG_I)], reg);
armAsm->Str(reg.S(), armMemOperandPtr(&getVI(REG_I)));
armAsm->Str(reg.S(), PTR_VUR(VI[REG_I]));
}
else if (mapX.VFreg == 32) {
// mVUsaveReg(reg, ptr[&regs().ACC], mapX.xyzw, true);
mVUsaveReg(reg, armMemOperandPtr(&regs().ACC), mapX.xyzw, true);
mVUsaveReg(reg, PTR_VUR(ACC), mapX.xyzw, true);
}
else {
// mVUsaveReg(reg, ptr[&getVF(mapX.VFreg)], mapX.xyzw, true);
mVUsaveReg(reg, armMemOperandPtr(&getVF(mapX.VFreg)), mapX.xyzw, true);
mVUsaveReg(reg, PTR_VUR(VF[mapX.VFreg]), mapX.xyzw, true);
}
if (invalidateRegs)
{
for (int i = 0; i < xmmTotal; i++)
u32 i;
for (i = 0; i < xmmTotal; ++i)
{
microMapXMM& mapI = xmmMap[i];
if ((i == reg.GetCode()) || mapI.isNeeded)
if ((i == reg_code) || mapI.isNeeded)
continue;
if (mapI.VFreg == mapX.VFreg)
@@ -708,7 +725,7 @@ public:
mapX.count = counter;
mapX.xyzw = 0;
mapX.isNeeded = false;
updateCOP2AllocState(reg.GetCode());
updateCOP2AllocState(reg_code);
return;
}
clearReg(reg);
@@ -726,11 +743,11 @@ public:
// writes into them.
void clearNeeded(const xmm& reg)
{
if ((reg.GetCode() < 0) || (reg.GetCode() >= xmmTotal)) // Sometimes xmmPQ hits this
u32 reg_code = reg.GetCode();
if ((reg_code < 0) || (reg_code >= xmmTotal)) // Sometimes xmmPQ hits this
return;
microMapXMM& clear = xmmMap[reg.GetCode()];
microMapXMM& clear = xmmMap[reg_code];
clear.isNeeded = false;
if (clear.xyzw) // Reg was modified
{
@@ -739,10 +756,13 @@ public:
int mergeRegs = 0;
if (clear.xyzw < 0xf) // Try to merge partial writes
mergeRegs = 1;
for (int i = 0; i < xmmTotal; i++) // Invalidate any other read-only regs of same vfReg
u32 i;
for (i = 0; i < xmmTotal; ++i) // Invalidate any other read-only regs of same vfReg
{
if (i == reg.GetCode())
if (i == reg_code)
continue;
microMapXMM& mapI = xmmMap[i];
if (mapI.VFreg == clear.VFreg)
{
@@ -773,8 +793,8 @@ public:
else if (regAllocCOP2 && clear.VFreg < 0)
{
// free on the EE side
pxAssert(pxmmregs[reg.GetCode()].type == XMMTYPE_VFREG);
pxmmregs[reg.GetCode()].inuse = false;
pxAssert(pxmmregs[reg_code].type == XMMTYPE_VFREG);
pxmmregs[reg_code].inuse = false;
}
}
@@ -792,7 +812,8 @@ public:
counter++;
if (vfLoadReg >= 0) // Search For Cached Regs
{
for (int i = 0; i < xmmTotal; i++)
int i;
for (i = 0; i < xmmTotal; ++i)
{
// const xmm& xmmI = xmm::GetInstance(i);
const xmm& xmmI = armQRegister(i);
@@ -861,6 +882,7 @@ public:
}
}
}
int x = findFreeReg((vfWriteReg >= 0) ? vfWriteReg : vfLoadReg);
// const xmm& xmmX = xmm::GetInstance(x);
const xmm& xmmX = armQRegister(x);
@@ -877,11 +899,11 @@ public:
}
else if (vfLoadReg == 32) {
// mVUloadReg(xmmX, ptr[&regs().ACC], xyzw);
mVUloadReg(xmmX, armMemOperandPtr(&regs().ACC), xyzw);
mVUloadReg(xmmX, PTR_VUR(ACC), xyzw);
}
else if (vfLoadReg >= 0) {
// mVUloadReg(xmmX, ptr[&getVF(vfLoadReg)], xyzw);
mVUloadReg(xmmX, armMemOperandPtr(&getVF(vfLoadReg)), xyzw);
mVUloadReg(xmmX, PTR_VUR(VF[vfLoadReg]), xyzw);
}
xmmMap[x].VFreg = vfWriteReg;
@@ -894,11 +916,11 @@ public:
}
else if (vfLoadReg == 32) {
// xMOVAPS(xmmX, ptr128[&regs().ACC]);
armAsm->Ldr(xmmX.Q(), armMemOperandPtr(&regs().ACC));
armAsm->Ldr(xmmX.Q(), PTR_VUR(ACC));
}
else if (vfLoadReg >= 0) {
// xMOVAPS(xmmX, ptr128[&getVF(vfLoadReg)]);
armAsm->Ldr(xmmX.Q(), armMemOperandPtr(&getVF(vfLoadReg)));
armAsm->Ldr(xmmX.Q(), PTR_VUR(VF[vfLoadReg]));
}
xmmMap[x].VFreg = vfLoadReg;
@@ -962,7 +984,7 @@ public:
pxAssert(mapX.VIreg > 0);
if (mapX.VIreg < 16) {
// xMOV(ptr16[&getVI(mapX.VIreg)], xRegister16(reg));
armAsm->Strh(reg, armMemOperandPtr(&getVI(mapX.VIreg)));
armAsm->Strh(reg, PTR_VUR(VI[mapX.VIreg]));
}
if (clearDirty)
{
@@ -974,16 +996,18 @@ public:
void clearNeeded(const a64::Register& reg)
{
pxAssert(reg.GetCode() < gprTotal);
microMapGPR& clear = gprMap[reg.GetCode()];
u32 reg_code = reg.GetCode();
pxAssert(reg_code < gprTotal);
microMapGPR& clear = gprMap[reg_code];
clear.isNeeded = false;
if (regAllocCOP2)
x86regs[reg.GetCode()].needed = false;
x86regs[reg_code].needed = false;
}
void unbindAnyVIAllocations(int reg, bool& backup)
{
for (int i = 0; i < gprTotal; i++)
int i, j;
for (i = 0; i < gprTotal; ++i)
{
microMapGPR& mapI = gprMap[i];
if (mapI.VIreg == reg)
@@ -1015,7 +1039,7 @@ public:
}
// shouldn't be any others...
for (int j = i + 1; j < gprTotal; j++)
for (j = i + 1; j < gprTotal; ++j)
{
pxAssert(gprMap[j].VIreg != reg);
}
@@ -1054,7 +1078,8 @@ public:
if (viLoadReg >= 0) // Search For Cached Regs
{
for (int i = 0; i < gprTotal; i++)
int i;
for (i = 0; i < gprTotal; ++i)
{
microMapGPR& mapI = gprMap[i];
if (mapI.VIreg == viLoadReg)
@@ -1080,7 +1105,7 @@ public:
if (backup && gprMap[x].VIreg != viWriteReg)
{
// xMOVZX(gprX, ptr16[&getVI(viWriteReg)]);
armAsm->Ldrh(gprX, armMemOperandPtr(&getVI(viWriteReg)));
armAsm->Ldrh(gprX, PTR_VUR(VI[viWriteReg]));
writeVIBackup(gprX);
backup = false;
}
@@ -1109,7 +1134,8 @@ public:
else if (zext_if_dirty && !gprMap[i].isZeroExtended)
{
// xMOVZX(xRegister32(i), xRegister16(i));
armAsm->Uxth(a64::WRegister(i), a64::WRegister(i));
auto reg32 = armWRegister(i);
armAsm->Uxth(reg32, reg32);
gprMap[i].isZeroExtended = true;
}
@@ -1146,14 +1172,14 @@ public:
if (backup && viLoadReg >= 0 && viWriteReg > 0 && viLoadReg != viWriteReg)
{
// xMOVZX(gprX, ptr16[&getVI(viWriteReg)]);
armAsm->Ldrh(gprX, armMemOperandPtr(&getVI(viWriteReg)));
armAsm->Ldrh(gprX, PTR_VUR(VI[viWriteReg]));
writeVIBackup(gprX);
backup = false;
}
if (viLoadReg > 0) {
// xMOVZX(gprX, ptr16[&getVI(viLoadReg)]);
armAsm->Ldrh(gprX, armMemOperandPtr(&getVI(viLoadReg)));
armAsm->Ldrh(gprX, PTR_VUR(VI[viLoadReg]));
}
else if (viLoadReg == 0) {
// xXOR(gprX, gprX);
@@ -1172,7 +1198,7 @@ public:
{
if (viLoadReg < 0 && viWriteReg > 0) {
// xMOVZX(gprX, ptr16[&getVI(viWriteReg)]);
armAsm->Ldrh(gprX, armMemOperandPtr(&getVI(viWriteReg)));
armAsm->Ldrh(gprX, PTR_VUR(VI[viWriteReg]));
}
writeVIBackup(gprX);
@@ -1195,11 +1221,12 @@ public:
void moveVIToGPR(const a64::Register& reg, int vi, bool signext = false)
{
const auto reg32 = a64::WRegister(reg);
pxAssert(vi >= 0);
if (vi == 0)
{
// xXOR(xRegister32(reg), xRegister32(reg));
auto reg32 = a64::WRegister(reg);
armAsm->Eor(reg32, reg32, reg32);
return;
}
@@ -1210,11 +1237,11 @@ public:
const a64::Register& srcreg = allocGPR(vi);
if (signext) {
// xMOVSX(xRegister32(reg), xRegister16(srcreg));
armAsm->Sxth(a64::WRegister(reg), srcreg);
armAsm->Sxth(reg32, srcreg);
}
else {
// xMOVZX(xRegister32(reg), xRegister16(srcreg));
armAsm->Uxth(a64::WRegister(reg), srcreg);
armAsm->Uxth(reg32, srcreg);
}
clearNeeded(srcreg);
}
+69 -69
View File
@@ -33,7 +33,7 @@ static __fi void testNeg(mV, const xmm& xmmReg, const x32& gprTemp)
a64::Label skip;
armAsm->B(&skip, a64::Condition::eq);
// xMOV(ptr32[&mVU.divFlag], divI);
armStorePtr(divI, &mVU.divFlag);
armStorePtr(divI, PTR_MVU(divFlag));
// xAND.PS(xmmReg, ptr128[mVUglob.absclip]);
armAsm->And(xmmReg.V16B(), xmmReg.V16B(), armLoadPtrV(mVUglob.absclip).V16B());
// skip.SetTarget();
@@ -61,14 +61,14 @@ mVUop(mVU_DIV)
a64::Label ajmp;
armAsm->B(&ajmp, a64::Condition::eq);
// xMOV(ptr32[&mVU.divFlag], divI); // Set invalid flag (0/0)
armStorePtr(divI, &mVU.divFlag);
armStorePtr(divI, PTR_MVU(divFlag));
// xForwardJump8 bjmp;
a64::Label bjmp;
armAsm->B(&bjmp);
// ajmp.SetTarget();
armBind(&ajmp);
// xMOV(ptr32[&mVU.divFlag], divD); // Zero divide (only when not 0/0)
armStorePtr(divD, &mVU.divFlag);
armStorePtr(divD, PTR_MVU(divFlag));
// bjmp.SetTarget();
armBind(&bjmp);
@@ -85,7 +85,7 @@ mVUop(mVU_DIV)
// cjmp.SetTarget();
armBind(&cjmp);
// xMOV(ptr32[&mVU.divFlag], 0); // Clear I/D flags
armStorePtr(0, &mVU.divFlag);
armStorePtr(0, PTR_MVU(divFlag));
SSE_DIVSS(mVU, Fs, Ft);
mVUclamp1(mVU, Fs, t1, 8, true);
// djmp.SetTarget();
@@ -98,7 +98,7 @@ mVUop(mVU_DIV)
// xAND(gprF0, ~0xc0000);
armAsm->And(gprF0, gprF0, ~0xc0000);
// xOR(gprF0, ptr32[&mVU.divFlag]);
armAsm->Orr(gprF0, gprF0, armLoadPtr(&mVU.divFlag));
armAsm->Orr(gprF0, gprF0, armLoadPtr(PTR_MVU(divFlag)));
}
mVU.regAlloc->clearNeeded(Fs);
@@ -117,7 +117,7 @@ mVUop(mVU_SQRT)
const xmm& Ft = mVU.regAlloc->allocReg(_Ft_, 0, (1 << (3 - _Ftf_)));
// xMOV(ptr32[&mVU.divFlag], 0); // Clear I/D flags
armStorePtr(0, &mVU.divFlag);
armStorePtr(0, PTR_MVU(divFlag));
testNeg(mVU, Ft, gprT1); // Check for negative sqrt
if (CHECK_VU_OVERFLOW(mVU.index)) { // Clamp infinities (only need to do positive clamp since xmmFt is positive)
@@ -133,7 +133,7 @@ mVUop(mVU_SQRT)
// xAND(gprF0, ~0xc0000);
armAsm->And(gprF0, gprF0, ~0xc0000);
// xOR(gprF0, ptr32[&mVU.divFlag]);
armAsm->Orr(gprF0, gprF0, armLoadPtr(&mVU.divFlag));
armAsm->Orr(gprF0, gprF0, armLoadPtr(PTR_MVU(divFlag)));
}
mVU.regAlloc->clearNeeded(Ft);
@@ -152,7 +152,7 @@ mVUop(mVU_RSQRT)
const xmm& t1 = mVU.regAlloc->allocReg();
// xMOV(ptr32[&mVU.divFlag], 0); // Clear I/D flags
armStorePtr(0, &mVU.divFlag);
armStorePtr(0, PTR_MVU(divFlag));
testNeg(mVU, Ft, gprT1); // Check for negative sqrt
// xSQRT.SS(Ft, Ft);
@@ -167,14 +167,14 @@ mVUop(mVU_RSQRT)
a64::Label bjmp;
armAsm->B(&bjmp, a64::Condition::eq);
// xMOV(ptr32[&mVU.divFlag], divI); // Set invalid flag (0/0)
armStorePtr(divI, &mVU.divFlag);
armStorePtr(divI, PTR_MVU(divFlag));
// xForwardJump8 cjmp;
a64::Label cjmp;
armAsm->B(&cjmp);
// bjmp.SetTarget();
armBind(&bjmp);
// xMOV(ptr32[&mVU.divFlag], divD); // Zero divide flag (only when not 0/0)
armStorePtr(divD, &mVU.divFlag);
armStorePtr(divD, PTR_MVU(divFlag));
// cjmp.SetTarget();
armBind(&cjmp);
@@ -200,7 +200,7 @@ mVUop(mVU_RSQRT)
// xAND(gprF0, ~0xc0000);
armAsm->And(gprF0, gprF0, ~0xc0000);
// xOR(gprF0, ptr32[&mVU.divFlag]);
armAsm->Orr(gprF0, gprF0, armLoadPtr(&mVU.divFlag));
armAsm->Orr(gprF0, gprF0, armLoadPtr(PTR_MVU(divFlag)));
}
mVU.regAlloc->clearNeeded(Fs);
@@ -1912,12 +1912,12 @@ mVUop(mVU_RINIT)
// xOR (gprT1, 0x3f800000);
armAsm->Orr(gprT1, gprT1, 0x3f800000);
// xMOV(ptr32[Rmem], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(Rmem));
armAsm->Str(gprT1, PTR_VUR(VI[REG_R].UL));
mVU.regAlloc->clearNeeded(Fs);
}
else {
// xMOV(ptr32[Rmem], 0x3f800000);
armStorePtr(0x3f800000, Rmem);
armStorePtr(0x3f800000, PTR_VUR(VI[REG_R].UL));
}
mVU.profiler.EmitOp(opRINIT);
}
@@ -1943,7 +1943,7 @@ mVUop(mVU_RGET)
pass2
{
// xMOV(gprT1, ptr32[Rmem]);
armAsm->Ldr(gprT1, armMemOperandPtr(Rmem));
armAsm->Ldr(gprT1, PTR_VUR(VI[REG_R].UL));
mVU_RGET_(mVU, gprT1);
mVU.profiler.EmitOp(opRGET);
}
@@ -1958,7 +1958,7 @@ mVUop(mVU_RNEXT)
// algorithm from www.project-fao.org
const a64::Register& temp3 = mVU.regAlloc->allocGPR();
// xMOV(temp3, ptr32[Rmem]);
armAsm->Ldr(temp3, armMemOperandPtr(Rmem));
armAsm->Ldr(temp3, PTR_VUR(VI[REG_R].UL));
// xMOV(gprT1, temp3);
armAsm->Mov(gprT1, temp3);
// xSHR(gprT1, 4);
@@ -1984,7 +1984,7 @@ mVUop(mVU_RNEXT)
// xOR (temp3, 0x3f800000);
armAsm->Orr(temp3, temp3, 0x3f800000);
// xMOV(ptr32[Rmem], temp3);
armAsm->Str(temp3, armMemOperandPtr(Rmem));
armAsm->Str(temp3, PTR_VUR(VI[REG_R].UL));
mVU_RGET_(mVU, temp3);
mVU.regAlloc->clearNeeded(temp3);
mVU.profiler.EmitOp(opRNEXT);
@@ -2005,7 +2005,7 @@ mVUop(mVU_RXOR)
// xAND(gprT1, 0x7fffff);
armAsm->And(gprT1, gprT1, 0x7fffff);
// xXOR(ptr32[Rmem], gprT1);
armEor(Rmem, gprT1);
armEor(PTR_VUR(VI[REG_R].UL), gprT1);
mVU.regAlloc->clearNeeded(Fs);
}
mVU.profiler.EmitOp(opRXOR);
@@ -2193,14 +2193,14 @@ static __fi void mVU_XGKICK_SYNC(mV, bool flush)
// on the second instruction after the kick and that needs to go through first
// but that's VERY close..
// xTEST(ptr32[&VU1.xgkickenable], 0x1);
armAsm->Tst(armLoadPtr(&VU1.xgkickenable), 0x1);
armAsm->Tst(armLoadPtr(PTR_VU1(xgkickenable)), 0x1);
// xForwardJZ32 skipxgkick;
a64::Label skipxgkick;
armAsm->B(&skipxgkick, a64::Condition::eq);
// xADD(ptr32[&VU1.xgkickcyclecount], mVUlow.kickcycles-1);
armAdd(&VU1.xgkickcyclecount, mVUlow.kickcycles-1);
armAdd(PTR_VU1(xgkickcyclecount), mVUlow.kickcycles-1);
// xCMP(ptr32[&VU1.xgkickcyclecount], 2);
armAsm->Cmp(armLoadPtr(&VU1.xgkickcyclecount), 2);
armAsm->Cmp(armLoadPtr(PTR_VU1(xgkickcyclecount)), 2);
// xForwardJL32 needcycles;
a64::Label needcycles;
armAsm->B(&needcycles, a64::Condition::lt);
@@ -2212,7 +2212,7 @@ static __fi void mVU_XGKICK_SYNC(mV, bool flush)
// needcycles.SetTarget();
armBind(&needcycles);
// xADD(ptr32[&VU1.xgkickcyclecount], 1);
armAdd(&VU1.xgkickcyclecount, 1);
armAdd(PTR_VU1(xgkickcyclecount), 1);
// skipxgkick.SetTarget();
armBind(&skipxgkick);
}
@@ -2228,7 +2228,7 @@ static __fi void mVU_XGKICK_DELAY(mV)
xJcc32(Jcc_NotZero, (uptr)mVU.exitFunctXG - ((uptr)xGetPtr()+6));
#endif
// xFastCall(mVU_XGKICK_, ptr32[&mVU.VIxgkick]);
armAsm->Ldr(EAX, armMemOperandPtr(&mVU.VIxgkick));
armAsm->Ldr(EAX, PTR_MVU(VIxgkick));
armEmitCall(reinterpret_cast<void*>(mVU_XGKICK_));
mVUrestoreRegs(mVU, true, true);
}
@@ -2262,26 +2262,26 @@ mVUop(mVU_XGKICK)
if (!CHECK_XGKICKHACK)
{
// xMOV(ptr32[&mVU.VIxgkick], regS);
armAsm->Str(regS, armMemOperandPtr(&mVU.VIxgkick));
armAsm->Str(regS, PTR_MVU(VIxgkick));
}
else
{
// xMOV(ptr32[&VU1.xgkickenable], 1);
armStorePtr(1, &VU1.xgkickenable);
armStorePtr(1, PTR_VU1(xgkickenable));
// xMOV(ptr32[&VU1.xgkickendpacket], 0);
armStorePtr(0, &VU1.xgkickendpacket);
armStorePtr(0, PTR_VU1(xgkickendpacket));
// xMOV(ptr32[&VU1.xgkicksizeremaining], 0);
armStorePtr(0, &VU1.xgkicksizeremaining);
armStorePtr(0, PTR_VU1(xgkicksizeremaining));
// xMOV(ptr32[&VU1.xgkickcyclecount], 0);
armStorePtr(0, &VU1.xgkickcyclecount);
armStorePtr(0, PTR_VU1(xgkickcyclecount));
// xMOV(gprT2, ptr32[&mVU.totalCycles]);
armAsm->Ldr(gprT2, armMemOperandPtr(&mVU.totalCycles));
armAsm->Ldr(gprT2, PTR_MVU(totalCycles));
// xSUB(gprT2, ptr32[&mVU.cycles]);
armAsm->Sub(gprT2, gprT2, armLoadPtr(&mVU.cycles));
armAsm->Sub(gprT2, gprT2, armLoadPtr(PTR_MVU(cycles)));
// xADD(gprT2, ptr32[&VU1.cycle]);
armAsm->Add(gprT2, gprT2, armLoadPtr(&VU1.cycle));
armAsm->Add(gprT2, gprT2, armLoadPtr(PTR_VU1(cycle)));
// xMOV(ptr32[&VU1.xgkicklastcycle], gprT2);
armAsm->Str(gprT2, armMemOperandPtr(&VU1.xgkicklastcycle));
armAsm->Str(gprT2, PTR_VU1(xgkicklastcycle));
// xMOV(gprT1, regS);
armAsm->Mov(gprT1, regS);
// xAND(gprT1, 0x3FF);
@@ -2289,7 +2289,7 @@ mVUop(mVU_XGKICK)
// xSHL(gprT1, 4);
armAsm->Lsl(gprT1, gprT1, 4);
// xMOV(ptr32[&VU1.xgkickaddr], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&VU1.xgkickaddr));
armAsm->Str(gprT1, PTR_VU1(xgkickaddr));
}
mVU.regAlloc->clearNeeded(regS);
mVU.profiler.EmitOp(opXGKICK);
@@ -2331,9 +2331,9 @@ void condEvilBranch(mV, a64::Condition JMPcc)
if (mVUlow.badBranch)
{
// xMOV(ptr32[&mVU.branch], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&mVU.branch));
armAsm->Str(gprT1, PTR_MVU(branch));
// xMOV(ptr32[&mVU.badBranch], branchAddr(mVU));
armStorePtr(branchAddr(mVU), &mVU.badBranch);
armStorePtr(branchAddr(mVU), PTR_MVU(badBranch));
// xCMP(gprT1b, 0);
armAsm->Cmp(gprT1b, 0);
@@ -2342,7 +2342,7 @@ void condEvilBranch(mV, a64::Condition JMPcc)
armAsm->B(&cJMP, JMPcc);
incPC(4); // Branch Not Taken Addr
// xMOV(ptr32[&mVU.badBranch], xPC);
armStorePtr(xPC, &mVU.badBranch);
armStorePtr(xPC, PTR_MVU(badBranch));
incPC(-4);
// cJMP.SetTarget();
armBind(&cJMP);
@@ -2351,36 +2351,36 @@ void condEvilBranch(mV, a64::Condition JMPcc)
if (isEvilBlock)
{
// xMOV(ptr32[&mVU.evilevilBranch], branchAddr(mVU));
armStorePtr(branchAddr(mVU), &mVU.evilevilBranch);
armStorePtr(branchAddr(mVU), PTR_MVU(evilevilBranch));
// xCMP(gprT1b, 0);
armAsm->Cmp(gprT1b, 0);
// xForwardJump8 cJMP((JccComparisonType)JMPcc);
a64::Label cJMP;
armAsm->B(&cJMP, JMPcc);
// xMOV(gprT1, ptr32[&mVU.evilBranch]); // Branch Not Taken
armAsm->Ldr(gprT1, armMemOperandPtr(&mVU.evilBranch));
armAsm->Ldr(gprT1, PTR_MVU(evilBranch));
// xADD(gprT1, 8); // We have already executed 1 instruction from the original branch
armAsm->Add(gprT1, gprT1, 8);
// xMOV(ptr32[&mVU.evilevilBranch], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&mVU.evilevilBranch));
armAsm->Str(gprT1, PTR_MVU(evilevilBranch));
// cJMP.SetTarget();
armBind(&cJMP);
}
else
{
// xMOV(ptr32[&mVU.evilBranch], branchAddr(mVU));
armStorePtr(branchAddr(mVU), &mVU.evilBranch);
armStorePtr(branchAddr(mVU), PTR_MVU(evilBranch));
// xCMP(gprT1b, 0);
armAsm->Cmp(gprT1b, 0);
// xForwardJump8 cJMP((JccComparisonType)JMPcc);
a64::Label cJMP;
armAsm->B(&cJMP, JMPcc);
// xMOV(gprT1, ptr32[&mVU.badBranch]); // Branch Not Taken
armAsm->Ldr(gprT1, armMemOperandPtr(&mVU.badBranch));
armAsm->Ldr(gprT1, PTR_MVU(badBranch));
// xADD(gprT1, 8); // We have already executed 1 instruction from the original branch
armAsm->Add(gprT1, gprT1, 8);
// xMOV(ptr32[&mVU.evilBranch], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&mVU.evilBranch));
armAsm->Str(gprT1, PTR_MVU(evilBranch));
// cJMP.SetTarget();
armBind(&cJMP);
incPC(-2);
@@ -2398,16 +2398,16 @@ mVUop(mVU_B)
{
if (mVUlow.badBranch) {
// xMOV(ptr32[&mVU.badBranch], branchAddr(mVU));
armStorePtr(branchAddr(mVU), &mVU.badBranch);
armStorePtr(branchAddr(mVU), PTR_MVU(badBranch));
}
if (mVUlow.evilBranch) {
if(isEvilBlock) {
// xMOV(ptr32[&mVU.evilevilBranch], branchAddr(mVU));
armStorePtr(branchAddr(mVU), &mVU.evilevilBranch);
armStorePtr(branchAddr(mVU), PTR_MVU(evilevilBranch));
}
else {
// xMOV(ptr32[&mVU.evilBranch], branchAddr(mVU));
armStorePtr(branchAddr(mVU), &mVU.evilBranch);
armStorePtr(branchAddr(mVU), PTR_MVU(evilBranch));
}
}
mVU.profiler.EmitOp(opB);
@@ -2437,11 +2437,11 @@ mVUop(mVU_BAL)
const a64::Register& regT = mVU.regAlloc->allocGPR(-1, _It_, mVUlow.backupVI);
if (isEvilBlock) {
// xMOV(regT, ptr32[&mVU.evilBranch]);
armAsm->Ldr(regT, armMemOperandPtr(&mVU.evilBranch));
armAsm->Ldr(regT, PTR_MVU(evilBranch));
}
else {
// xMOV(regT, ptr32[&mVU.badBranch]);
armAsm->Ldr(regT, armMemOperandPtr(&mVU.badBranch));
armAsm->Ldr(regT, PTR_MVU(badBranch));
}
// xADD(regT, 8);
@@ -2453,16 +2453,16 @@ mVUop(mVU_BAL)
if (mVUlow.badBranch) {
// xMOV(ptr32[&mVU.badBranch], branchAddr(mVU));
armStorePtr(branchAddr(mVU), &mVU.badBranch);
armStorePtr(branchAddr(mVU), PTR_MVU(badBranch));
}
if (mVUlow.evilBranch) {
if (isEvilBlock) {
// xMOV(ptr32[&mVU.evilevilBranch], branchAddr(mVU));
armStorePtr(branchAddr(mVU), &mVU.evilevilBranch);
armStorePtr(branchAddr(mVU), PTR_MVU(evilevilBranch));
}
else {
// xMOV(ptr32[&mVU.evilBranch], branchAddr(mVU));
armStorePtr(branchAddr(mVU), &mVU.evilBranch);
armStorePtr(branchAddr(mVU), PTR_MVU(evilBranch));
}
}
mVU.profiler.EmitOp(opBAL);
@@ -2478,7 +2478,7 @@ mVUop(mVU_IBEQ)
{
if (mVUlow.memReadIs) {
// xMOV(gprT1, ptr32[&mVU.VIbackup]);
armAsm->Ldr(gprT1, armMemOperandPtr(&mVU.VIbackup));
armAsm->Ldr(gprT1, PTR_MVU(VIbackup));
}
else {
mVU.regAlloc->moveVIToGPR(gprT1, _Is_);
@@ -2486,7 +2486,7 @@ mVUop(mVU_IBEQ)
if (mVUlow.memReadIt) {
// xXOR(gprT1, ptr32[&mVU.VIbackup]);
armAsm->Eor(gprT1, gprT1, armLoadPtr(&mVU.VIbackup));
armAsm->Eor(gprT1, gprT1, armLoadPtr(PTR_MVU(VIbackup)));
}
else
{
@@ -2498,7 +2498,7 @@ mVUop(mVU_IBEQ)
if (!(isBadOrEvil)) {
// xMOV(ptr32[&mVU.branch], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&mVU.branch));
armAsm->Str(gprT1, PTR_MVU(branch));
}
else {
// condEvilBranch(mVU, Jcc_Equal);
@@ -2517,14 +2517,14 @@ mVUop(mVU_IBGEZ)
{
if (mVUlow.memReadIs) {
// xMOV(gprT1, ptr32[&mVU.VIbackup]);
armAsm->Ldr(gprT1, armMemOperandPtr(&mVU.VIbackup));
armAsm->Ldr(gprT1, PTR_MVU(VIbackup));
}
else {
mVU.regAlloc->moveVIToGPR(gprT1, _Is_);
}
if (!(isBadOrEvil)) {
// xMOV(ptr32[&mVU.branch], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&mVU.branch));
armAsm->Str(gprT1, PTR_MVU(branch));
}
else {
// condEvilBranch(mVU, Jcc_GreaterOrEqual);
@@ -2543,14 +2543,14 @@ mVUop(mVU_IBGTZ)
{
if (mVUlow.memReadIs) {
// xMOV(gprT1, ptr32[&mVU.VIbackup]);
armAsm->Ldr(gprT1, armMemOperandPtr(&mVU.VIbackup));
armAsm->Ldr(gprT1, PTR_MVU(VIbackup));
}
else {
mVU.regAlloc->moveVIToGPR(gprT1, _Is_);
}
if (!(isBadOrEvil)) {
// xMOV(ptr32[&mVU.branch], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&mVU.branch));
armAsm->Str(gprT1, PTR_MVU(branch));
}
else {
// condEvilBranch(mVU, Jcc_Greater);
@@ -2569,14 +2569,14 @@ mVUop(mVU_IBLEZ)
{
if (mVUlow.memReadIs) {
// xMOV(gprT1, ptr32[&mVU.VIbackup]);
armAsm->Ldr(gprT1, armMemOperandPtr(&mVU.VIbackup));
armAsm->Ldr(gprT1, PTR_MVU(VIbackup));
}
else {
mVU.regAlloc->moveVIToGPR(gprT1, _Is_);
}
if (!(isBadOrEvil)) {
// xMOV(ptr32[&mVU.branch], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&mVU.branch));
armAsm->Str(gprT1, PTR_MVU(branch));
}
else {
// condEvilBranch(mVU, Jcc_LessOrEqual);
@@ -2595,14 +2595,14 @@ mVUop(mVU_IBLTZ)
{
if (mVUlow.memReadIs) {
// xMOV(gprT1, ptr32[&mVU.VIbackup]);
armAsm->Ldr(gprT1, armMemOperandPtr(&mVU.VIbackup));
armAsm->Ldr(gprT1, PTR_MVU(VIbackup));
}
else {
mVU.regAlloc->moveVIToGPR(gprT1, _Is_);
}
if (!(isBadOrEvil)) {
// xMOV(ptr32[&mVU.branch], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&mVU.branch));
armAsm->Str(gprT1, PTR_MVU(branch));
}
else {
// condEvilBranch(mVU, Jcc_Less);
@@ -2621,7 +2621,7 @@ mVUop(mVU_IBNE)
{
if (mVUlow.memReadIs) {
// xMOV(gprT1, ptr32[&mVU.VIbackup]);
armAsm->Ldr(gprT1, armMemOperandPtr(&mVU.VIbackup));
armAsm->Ldr(gprT1, PTR_MVU(VIbackup));
}
else {
mVU.regAlloc->moveVIToGPR(gprT1, _Is_);
@@ -2629,7 +2629,7 @@ mVUop(mVU_IBNE)
if (mVUlow.memReadIt) {
// xXOR(gprT1, ptr32[&mVU.VIbackup]);
armAsm->Eor(gprT1, gprT1, armLoadPtr(&mVU.VIbackup));
armAsm->Eor(gprT1, gprT1, armLoadPtr(PTR_MVU(VIbackup)));
}
else
{
@@ -2641,7 +2641,7 @@ mVUop(mVU_IBNE)
if (!(isBadOrEvil)) {
// xMOV(ptr32[&mVU.branch], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&mVU.branch));
armAsm->Str(gprT1, PTR_MVU(branch));
}
else {
// condEvilBranch(mVU, Jcc_NotEqual);
@@ -2665,24 +2665,24 @@ void normJumpPass2(mV)
if (!mVUlow.evilBranch)
{
// xMOV(ptr32[&mVU.branch], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&mVU.branch));
armAsm->Str(gprT1, PTR_MVU(branch));
}
else
{
if(isEvilBlock) {
// xMOV(ptr32[&mVU.evilevilBranch], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&mVU.evilevilBranch));
armAsm->Str(gprT1, PTR_MVU(evilevilBranch));
}
else {
// xMOV(ptr32[&mVU.evilBranch], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&mVU.evilBranch));
armAsm->Str(gprT1, PTR_MVU(evilBranch));
}
}
//If delay slot is conditional, it uses badBranch to go to its target
if (mVUlow.badBranch)
{
// xMOV(ptr32[&mVU.badBranch], gprT1);
armAsm->Str(gprT1, armMemOperandPtr(&mVU.badBranch));
armAsm->Str(gprT1, PTR_MVU(badBranch));
}
}
}
@@ -2719,7 +2719,7 @@ mVUop(mVU_JALR)
if (isEvilBlock)
{
// xMOV(regT, ptr32[&mVU.evilBranch]);
armAsm->Ldr(regT, armMemOperandPtr(&mVU.evilBranch));
armAsm->Ldr(regT, PTR_MVU(evilBranch));
// xADD(regT, 8);
armAsm->Add(regT, regT, 8);
// xSHR(regT, 3);
@@ -2732,7 +2732,7 @@ mVUop(mVU_JALR)
incPC(2);
// xMOV(regT, ptr32[&mVU.badBranch]);
armAsm->Ldr(regT, armMemOperandPtr(&mVU.badBranch));
armAsm->Ldr(regT, PTR_MVU(badBranch));
// xADD(regT, 8);
armAsm->Add(regT, regT, 8);
// xSHR(regT, 3);
+33 -31
View File
@@ -38,7 +38,7 @@ void setupMacroOp(int mode, const char* opName)
if (mode & 0x01) // Q-Reg will be Read
{
// xMOVSSZX(xmmPQ, ptr32[&vu0Regs.VI[REG_Q].UL]);
armAsm->Ldr(xmmPQ.S(), armMemOperandPtr(&vu0Regs.VI[REG_Q].UL));
armAsm->Ldr(xmmPQ.S(), PTR_VUR(VI[REG_Q].UL));
}
if (mode & 0x08 && (!CHECK_VU_FLAGHACK || g_pCurInstInfo->info & EEINST_COP2_CLIP_FLAG)) // Clip Instruction
{
@@ -71,7 +71,7 @@ void setupMacroOp(int mode, const char* opName)
// load denormalized status flag
// ideally we'd keep this in a register, but 32-bit...
// xMOV(gprF0, ptr32[&vuRegs->VI[REG_STATUS_FLAG].UL]);
armAsm->Ldr(gprF0, armMemOperandPtr(&vuRegs->VI[REG_STATUS_FLAG].UL));
armAsm->Ldr(gprF0, PTR_VUR(VI[REG_STATUS_FLAG].UL));
}
}
}
@@ -81,7 +81,7 @@ void endMacroOp(int mode)
if (mode & 0x02) // Q-Reg was Written To
{
// xMOVSS(ptr32[&vu0Regs.VI[REG_Q].UL], xmmPQ);
armAsm->Str(xmmPQ.S(), armMemOperandPtr(&vu0Regs.VI[REG_Q].UL));
armAsm->Str(xmmPQ.S(), PTR_VUR(VI[REG_Q].UL));
}
microVU0.regAlloc->flushPartialForCOP2();
@@ -93,14 +93,14 @@ void endMacroOp(int mode)
// Normalize
mVUallocSFLAGc(EAX, gprF0, 0);
// xMOV(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], eax);
armAsm->Str(EAX, armMemOperandPtr(&vu0Regs.VI[REG_STATUS_FLAG].UL));
armAsm->Str(EAX, PTR_VUR(VI[REG_STATUS_FLAG].UL));
}
else if (g_pCurInstInfo->info & (EEINST_COP2_STATUS_FLAG | EEINST_COP2_DENORMALIZE_STATUS_FLAG))
{
// backup denormalized flags for the next instruction
// this is fine, because we'll normalize them again before this reg is accessed
// xMOV(ptr32[&vuRegs->VI[REG_STATUS_FLAG].UL], gprF0);
armAsm->Str(gprF0, armMemOperandPtr(&vuRegs->VI[REG_STATUS_FLAG].UL));
armAsm->Str(gprF0, PTR_VUR(VI[REG_STATUS_FLAG].UL));
}
}
@@ -312,7 +312,7 @@ static void _setupBranchTest(a64::Condition p_cond, bool isLikely)
_eeFlushAllDirty();
//xTEST(ptr32[&vif1Regs.stat._u32], 0x4);
// xTEST(ptr32[&VU0.VI[REG_VPU_STAT].UL], 0x100);
armAsm->Tst(armLoadPtr(&VU0.VI[REG_VPU_STAT].UL), 0x100);
armAsm->Tst(armLoadPtr(PTR_VUR(VI[REG_VPU_STAT].UL)), 0x100);
// recDoBranchImm(branchTo, jmpType(0), isLikely, swap);
a64::Label jmpType;
@@ -363,21 +363,21 @@ static void COP2_Interlock(bool mBitSync)
armAdd(EAX, PTR_CPU(cycle), scaleblockcycles_clear());
// xTEST(ptr32[&VU0.VI[REG_VPU_STAT].UL], 0x1);
armAsm->Tst(armLoadPtr(&VU0.VI[REG_VPU_STAT].UL), 0x1);
armAsm->Tst(armLoadPtr(PTR_VUR(VI[REG_VPU_STAT].UL)), 0x1);
// xForwardJZ32 skipvuidle;
a64::Label skipvuidle;
armAsm->B(&skipvuidle, a64::Condition::eq);
if (mBitSync)
{
// xSUB(eax, ptr32[&VU0.cycle]);
armAsm->Sub(EAX, EAX, armLoadPtr(&VU0.cycle));
armAsm->Sub(EAX, EAX, armLoadPtr(PTR_VUR(cycle)));
// Why do we check this here? Ratchet games, maybe others end up with flickering polygons
// when we use lazy COP2 sync, otherwise. The micro resumption getting deferred an extra
// EE block is apparently enough to cause issues.
if (EmuConfig.Gamefixes.VUSyncHack || EmuConfig.Gamefixes.FullVU0SyncHack) {
// xSUB(eax, ptr32[&VU0.nextBlockCycles]);
armAsm->Sub(EAX, EAX, armLoadPtr(&VU0.nextBlockCycles));
armAsm->Sub(EAX, EAX, armLoadPtr(PTR_VUR(nextBlockCycles)));
}
// xCMP(eax, 4);
armAsm->Cmp(EAX, 4);
@@ -416,15 +416,15 @@ static void mVUSyncVU0()
armAdd(EAX, PTR_CPU(cycle), scaleblockcycles_clear());
// xTEST(ptr32[&VU0.VI[REG_VPU_STAT].UL], 0x1);
armAsm->Tst(armLoadPtr(&VU0.VI[REG_VPU_STAT].UL), 0x1);
armAsm->Tst(armLoadPtr(PTR_VUR(VI[REG_VPU_STAT].UL)), 0x1);
// xForwardJZ32 skipvuidle;
a64::Label skipvuidle;
armAsm->B(&skipvuidle, a64::Condition::eq);
// xSUB(eax, ptr32[&VU0.cycle]);
armAsm->Sub(EAX, EAX, armLoadPtr(&VU0.cycle));
armAsm->Sub(EAX, EAX, armLoadPtr(PTR_VUR(cycle)));
if (EmuConfig.Gamefixes.VUSyncHack || EmuConfig.Gamefixes.FullVU0SyncHack) {
// xSUB(eax, ptr32[&VU0.nextBlockCycles]);
armAsm->Sub(EAX, EAX, armLoadPtr(&VU0.nextBlockCycles));
armAsm->Sub(EAX, EAX, armLoadPtr(PTR_VUR(nextBlockCycles)));
}
// xCMP(eax, 4);
armAsm->Cmp(EAX, 4);
@@ -447,7 +447,7 @@ static void mVUFinishVU0()
{
iFlushCall(FLUSH_FOR_POSSIBLE_MICRO_EXEC);
// xTEST(ptr32[&VU0.VI[REG_VPU_STAT].UL], 0x1);
armAsm->Tst(armLoadPtr(&VU0.VI[REG_VPU_STAT].UL), 0x1);
armAsm->Tst(armLoadPtr(PTR_VUR(VI[REG_VPU_STAT].UL)), 0x1);
// xForwardJZ32 skipvuidle;
a64::Label skipvuidle;
armAsm->B(&skipvuidle, a64::Condition::eq);
@@ -509,20 +509,20 @@ static void recCFC2()
else
{
// xMOVSX(xRegister64(regt), ptr32[&vu0Regs.VI[_Rd_].UL]);
armAsm->Ldrsw(a64::XRegister(regt), armMemOperandPtr(&vu0Regs.VI[_Rd_].UL));
armAsm->Ldrsw(a64::XRegister(regt), PTR_VUR(VI[_Rd_].UL));
}
}
else if (_Rd_ == REG_R)
{
// xMOVSX(xRegister64(regt), ptr32[&vu0Regs.VI[REG_R].UL]);
armAsm->Ldrsw(a64::XRegister(regt), armMemOperandPtr(&vu0Regs.VI[REG_R].UL));
armAsm->Ldrsw(a64::XRegister(regt), PTR_VUR(VI[REG_R].UL));
// xAND(xRegister64(regt), 0x7FFFFF);
armAsm->And(a64::XRegister(regt), a64::XRegister(regt), 0x7FFFFF);
}
else if (_Rd_ >= REG_STATUS_FLAG) // FixMe: Should R-Reg have upper 9 bits 0?
{
// xMOVSX(xRegister64(regt), ptr32[&vu0Regs.VI[_Rd_].UL]);
armAsm->Ldrsw(a64::XRegister(regt), armMemOperandPtr(&vu0Regs.VI[_Rd_].UL));
armAsm->Ldrsw(a64::XRegister(regt), PTR_VUR(VI[_Rd_].UL));
}
else
{
@@ -533,7 +533,7 @@ static void recCFC2()
}
else {
// xMOVZX(xRegister32(regt), ptr16[&vu0Regs.VI[_Rd_].UL]);
armAsm->Ldrh(a64::WRegister(regt), armMemOperandPtr(&vu0Regs.VI[_Rd_].UL));
armAsm->Ldrh(a64::WRegister(regt), PTR_VUR(VI[_Rd_].UL));
}
}
}
@@ -568,7 +568,7 @@ static void recCTC2()
// xOR(eax, 0x3f800000);
armAsm->Orr(EAX, EAX, 0x3f800000);
// xMOV(ptr32[&vu0Regs.VI[REG_R].UL], eax);
armAsm->Str(EAX, armMemOperandPtr(&vu0Regs.VI[REG_R].UL));
armAsm->Str(EAX, PTR_VUR(VI[REG_R].UL));
break;
case REG_STATUS_FLAG:
{
@@ -578,13 +578,13 @@ static void recCTC2()
// xAND(eax, 0xFC0);
armAsm->And(EAX, EAX, 0xFC0);
// xAND(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], 0x3F);
armAnd(&vu0Regs.VI[REG_STATUS_FLAG].UL, 0x3F);
armAnd(PTR_VUR(VI[REG_STATUS_FLAG].UL), 0x3F);
// xOR(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], eax);
armOrr(&vu0Regs.VI[REG_STATUS_FLAG].UL, EAX);
armOrr(PTR_VUR(VI[REG_STATUS_FLAG].UL), EAX);
}
else {
// xAND(ptr32[&vu0Regs.VI[REG_STATUS_FLAG].UL], 0x3F);
armAnd(&vu0Regs.VI[REG_STATUS_FLAG].UL, 0x3F);
armAnd(PTR_VUR(VI[REG_STATUS_FLAG].UL), 0x3F);
}
const int xmmtemp = _allocTempXMMreg(XMMT_INT);
@@ -597,7 +597,7 @@ static void recCTC2()
armSHUFPS(a64::QRegister(xmmtemp), a64::QRegister(xmmtemp), 0);
// Make sure the values are everywhere the need to be
// xMOVAPS(ptr128[&vu0Regs.micro_statusflags], xRegisterSSE(xmmtemp));
armAsm->Str(a64::QRegister(xmmtemp).Q(), armMemOperandPtr(&vu0Regs.micro_statusflags));
armAsm->Str(a64::QRegister(xmmtemp).Q(), PTR_VUR(micro_statusflags));
_freeXMMreg(xmmtemp);
break;
}
@@ -617,7 +617,7 @@ static void recCTC2()
if (!_Rt_)
{
// xMOV(ptr32[&vu0Regs.VI[REG_FBRST].UL], 0);
armStorePtr(0, &vu0Regs.VI[REG_FBRST].UL);
armStorePtr(0, PTR_VUR(VI[REG_FBRST].UL));
return;
}
@@ -631,7 +631,7 @@ static void recCTC2()
// xAND(xRegister32(flagreg), 0x0C0C);
armAsm->And(a64::WRegister(flagreg), a64::WRegister(flagreg), 0x0C0C);
// xMOV(ptr32[&vu0Regs.VI[REG_FBRST].UL], xRegister32(flagreg));
armAsm->Str(a64::WRegister(flagreg), armMemOperandPtr(&vu0Regs.VI[REG_FBRST].UL));
armAsm->Str(a64::WRegister(flagreg), PTR_VUR(VI[REG_FBRST].UL));
_freeX86reg(flagreg);
}
break;
@@ -710,7 +710,7 @@ static void recCTC2()
// xMOV(ptr16[&vu0Regs.VI[_Rd_].US[0]], ax);
}
}
armAsm->Strh(EAX, armMemOperandPtr(&vu0Regs.VI[_Rd_].US[0]));
armAsm->Strh(EAX, PTR_VUR(VI[_Rd_].US[0]));
}
}
else
@@ -768,7 +768,7 @@ static void recQMFC2()
if (!_Rt_)
return;
if (!(cpuRegs.code & 1))
{
if (g_pCurInstInfo->info & EEINST_COP2_SYNC_VU0)
@@ -814,7 +814,7 @@ static void recQMTC2()
if (!_Rd_)
return;
if (!(cpuRegs.code & 1))
{
if (g_pCurInstInfo->info & EEINST_COP2_SYNC_VU0)
@@ -831,7 +831,7 @@ static void recQMTC2()
const int rtreg = (GPR_IS_DIRTY_CONST(_Rt_) || _hasX86reg(X86TYPE_GPR, _Rt_, MODE_WRITE)) ?
_allocGPRtoXMMreg(_Rt_, MODE_READ) :
_checkXMMreg(XMMTYPE_GPRREG, _Rt_, MODE_READ);
// NOTE: can't transfer xmm15 to VF, it's reserved for PQ.
int vfreg = _checkXMMreg(XMMTYPE_VFREG, _Rd_, MODE_WRITE);
if (can_rename && rtreg >= 0 && rtreg != xmmPQ.GetCode())
@@ -957,7 +957,8 @@ void recLQC2()
}
else
{
_eeMoveGPRtoR(arg1regd, _Rs_);
// _eeMoveGPRtoR(arg1regd, _Rs_);
_eeMoveGPRtoR(a64::WRegister(ECX), _Rs_);
if (_Imm_ != 0) {
// xADD(arg1regd, _Imm_);
armAsm->Add(ECX, ECX, _Imm_);
@@ -989,7 +990,7 @@ void recSQC2()
const int ftreg = _Rt_ ? _allocVFtoXMMreg(_Rt_, MODE_READ) : _allocTempXMMreg(XMMT_FPS);
if (!_Rt_) {
// xMOVAPS(xRegisterSSE(ftreg), ptr128[&vu0Regs.VF[0].F]);
armAsm->Ldr(a64::QRegister(ftreg).Q(), armMemOperandPtr(&vu0Regs.VF[0].F));
armAsm->Ldr(a64::QRegister(ftreg).Q(), PTR_VUR(VF[0].F));
}
if (GPR_IS_CONST1(_Rs_))
@@ -999,7 +1000,8 @@ void recSQC2()
}
else
{
_eeMoveGPRtoR(arg1regd, _Rs_);
// _eeMoveGPRtoR(arg1regd, _Rs_);
_eeMoveGPRtoR(a64::WRegister(ECX), _Rs_);
if (_Imm_ != 0) {
// xADD(arg1regd, _Imm_);
armAsm->Add(ECX, ECX, _Imm_);
+9 -6
View File
@@ -237,7 +237,8 @@ void mVUmergeRegs(const xmm& dest, const xmm& src, int xyzw, bool modXYZW)
}
// xyzw
for (u32 i = 0; i < 4; i++)
u32 i;
for (i = 0; i < 4; ++i)
{
if (xyzw & (1u << i))
armAsm->Mov(dest.V4S(), i, src.V4S(), i);
@@ -284,7 +285,7 @@ __fi void mVUbackupRegs(microVU& mVU, bool toMemory = false, bool onlyNeeded = f
// TODO(Stenzek): get rid of xmmbackup
mVU.regAlloc->flushAll(); // Flush Regalloc
// xMOVAPS(ptr128[&mVU.xmmBackup[xmmPQ.GetCode()][0]], xmmPQ);
armAsm->Str(xmmPQ.Q(), armMemOperandPtr(&mVU.xmmBackup[xmmPQ.GetCode()][0]));
armAsm->Str(xmmPQ.Q(), PTR_MVU(xmmBackup[xmmPQ.GetCode()][0]));
}
}
@@ -320,7 +321,7 @@ __fi void mVUrestoreRegs(microVU& mVU, bool fromMemory = false, bool onlyNeeded
else
{
// xMOVAPS(xmmPQ, ptr128[&mVU.xmmBackup[xmmPQ.GetCode()][0]]);
armAsm->Ldr(xmmPQ.Q(), armMemOperandPtr(&mVU.xmmBackup[xmmPQ.GetCode()][0]));
armAsm->Ldr(xmmPQ.Q(), PTR_MVU(xmmBackup[xmmPQ.GetCode()][0]));
}
}
@@ -347,7 +348,8 @@ static void mVUEBit()
static inline u32 branchAddr(const mV)
{
pxAssumeMsg(islowerOP, "MicroVU: Expected Lower OP code for valid branch addr.");
return ((((iPC + 2) + (_Imm11_ * 2)) & mVU.progMemMask) * 4);
// return ((((iPC + 2) + (_Imm11_ * 2)) & mVU.progMemMask) * 4)
return ((((iPC + 2) + (_Imm11_ << 1)) & mVU.progMemMask) << 2);
}
static void mVUwaitMTVU()
@@ -414,8 +416,9 @@ __fi std::optional<a64::MemOperand> mVUoptimizeConstantAddr(mV, u32 srcreg, s32
if (srcreg != 0)
return std::nullopt;
armMoveAddressToReg(REX, mVU.regs().Mem);
// armMoveAddressToReg(REX, mVU.regs().Mem);
armAsm->Ldr(REX, PTR_VUR(Mem));
const s32 addr = 0 + offset;
if (isVU1)
{
+3 -1
View File
@@ -23,13 +23,15 @@ alignas(16) const u32 sse4_compvals[2][4] = {
{0x7fffffff, 0x7fffffff, 0x7fffffff, 0x7fffffff}, //1111
};
const std::array<u16, 16> flipMask{0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15};
// Note: If modXYZW is true, then it adjusts XYZW for Single Scalar operations
static void mVUupdateFlags(mV, const xmm& reg, const xmm& regT1in = a64::NoVReg, const xmm& regT2in = a64::NoVReg, bool modXYZW = 1)
{
const x32& mReg = gprT1;
const x32& sReg = getFlagReg(sFLAG.write);
bool regT1b = regT1in.IsNone(), regT2b = false;
static const u16 flipMask[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15};
// static const u16 flipMask[16] = {0, 8, 4, 12, 2, 10, 6, 14, 1, 9, 5, 13, 3, 11, 7, 15};
//SysPrintf("Status = %d; Mac = %d\n", sFLAG.doFlag, mFLAG.doFlag);
if (!sFLAG.doFlag && !mFLAG.doFlag)