Android project - Fixes related to microVU function

This commit is contained in:
k2154
2025-07-23 00:15:41 +09:00
parent ca2ac82c83
commit 7d169b8a6c
5 changed files with 70 additions and 165 deletions
+9 -3
View File
@@ -348,12 +348,18 @@ bool armIsCallerSaved(int id)
bool armIsCallerSavedXmm(int id)
{
#ifdef _WIN32
// XMM6 through XMM15 are saved. Upper 128 bits is always volatile.
return (id < 6);
#if defined(__ANDROID__)
// v9,v10,v11,v12,v13,v14,v15
return (id < 9);
// return true;
#else
#ifdef _WIN32
// XMM6 through XMM15 are saved. Upper 128 bits is always volatile.
return (id < 6);
#else
// All vector registers are volatile.
return true;
#endif
#endif
}
+1 -4
View File
@@ -666,12 +666,9 @@ void FPU_MUL(int regd, int regt, bool reverseOperands)
// xOR(edx, ecx);
armAsm->Orr(EDX, EDX, ECX);
// flag test
armAsm->Tst(EDX, EDX);
// u8* noHack = JNZ8(0);
a64::Label noHack;
armAsm->B(&noHack, a64::Condition::ne);
armAsm->Cbnz(EDX, &noHack);
// xMOVAPS(xRegisterSSE(regd), ptr128[result]);
armAsm->Ldr(regD.Q(), armMemOperandPtr(result));
// endMul = JMP8(0);
+1 -4
View File
@@ -560,12 +560,9 @@ void FPU_MUL(int info, int regd, int sreg, int treg, bool acc)
// xOR(edx, ecx);
armAsm->Orr(EDX, EDX, ECX);
// flag test
armAsm->Tst(EDX, EDX);
// u8* noHack = JNZ8(0);
a64::Label noHack;
armAsm->B(&noHack, a64::Condition::ne);
armAsm->Cbnz(EDX, &noHack);
// xMOVAPS(xRegisterSSE(regd), ptr128[result]);
armAsm->Ldr(regD.Q(), armMemOperandPtr(result));
// endMul = JMP32(0);
+46 -80
View File
@@ -195,50 +195,27 @@ static void mVUGenerateWaitMTVU(mV)
{
mVU.waitMTVU = armStartBlock();
int i, num_xmms = 0, num_gprs = 0;
for (i = 0; i < static_cast<int>(iREGCNT_GPR); ++i)
{
if (!armIsCallerSaved(i) || i == 4)
continue;
// T1 often contains the address we're loading when waiting for VU1.
// T2 isn't used until afterwards, so don't bother saving it.
if (i == gprT2.GetCode())
continue;
// xPUSH(xRegister64(i));
armAsm->Push(a64::xzr, a64::Register(i, a64::kXRegSize));
num_gprs++;
}
for (i = 0; i < static_cast<int>(iREGCNT_XMM); ++i)
{
if (!armIsCallerSavedXmm(i))
continue;
num_xmms++;
}
// We need 16 byte alignment on the stack.
// Since the stack is unaligned at entry to this function, we add 8 when it's even, not odd.
const int stack_size = (num_xmms * sizeof(u128)) + ((~num_gprs & 1) * sizeof(u128)) + SHADOW_STACK_SIZE;
int stack_offset = SHADOW_STACK_SIZE;
if (stack_size > 0)
{
// xSUB(rsp, stack_size);
armAsm->Sub(a64::sp, a64::sp, stack_size);
for (i = 0; i < static_cast<int>(iREGCNT_XMM); i++)
{
if (!armIsCallerSavedXmm(i))
continue;
// xMOVAPS(ptr128[rsp + stack_offset], xRegisterSSE(i));
armAsm->Str(a64::QRegister(i).Q(), a64::MemOperand(a64::sp, stack_offset));
stack_offset += sizeof(u128);
}
}
// int i;
// for (i = 0; i < static_cast<int>(iREGCNT_GPR); ++i)
// {
// if (!armIsCallerSaved(i) || i == 4)
// continue;
//
// // T1 often contains the address we're loading when waiting for VU1.
// // T2 isn't used until afterwards, so don't bother saving it.
// if (i == gprT2.GetCode())
// continue;
//
// armAsm->Push(a64::xzr, a64::XRegister(i));
// }
////
// for (i = 0; i < static_cast<int>(iREGCNT_XMM); ++i)
// {
// if (!armIsCallerSavedXmm(i))
// continue;
//
// armAsm->Push(a64::xzr, a64::DRegister(i));
// }
////
// xFastCall((void*)mVUwaitMTVU);
@@ -248,30 +225,24 @@ static void mVUGenerateWaitMTVU(mV)
armAsm->Pop(a64::lr, a64::xzr);
////
stack_offset = (num_xmms - 1) * sizeof(u128) + SHADOW_STACK_SIZE;
for (i = static_cast<int>(iREGCNT_XMM - 1); i >= 0; --i)
{
if (!armIsCallerSavedXmm(i))
continue;
// xMOVAPS(xRegisterSSE(i), ptr128[rsp + stack_offset]);
armAsm->Ldr(a64::QRegister(i).Q(), a64::MemOperand(a64::sp, stack_offset));
stack_offset -= sizeof(u128);
}
// xADD(rsp, stack_size);
armAsm->Add(a64::sp, a64::sp, stack_size);
for (i = static_cast<int>(iREGCNT_GPR - 1); i >= 0; --i)
{
if (!armIsCallerSaved(i) || i == 4)
continue;
if (i == gprT2.GetCode())
continue;
// xPOP(xRegister64(i));
armAsm->Pop(a64::Register(i, a64::kXRegSize), a64::xzr);
}
// for (i = static_cast<int>(iREGCNT_XMM - 1); i >= 0; --i)
// {
// if (!armIsCallerSavedXmm(i))
// continue;
//
// armAsm->Pop(a64::DRegister(i), a64::xzr);
// }
////
// for (i = static_cast<int>(iREGCNT_GPR - 1); i >= 0; --i)
// {
// if (!armIsCallerSaved(i) || i == 4)
// continue;
//
// if (i == gprT2.GetCode())
// continue;
//
// armAsm->Pop(a64::XRegister(i), a64::xzr);
// }
// xRET();
armAsm->Ret();
@@ -346,18 +317,13 @@ static void mVUGenerateCompareState(mV)
armAsm->And(xmm0.V16B(), xmm0.V16B(), xmm1.V16B());
// xMOVMSKPS(eax, xmm0);
armMOVMSKPS(EEX, xmm0);
armMOVMSKPS(EDX, xmm0);
// xXOR (eax, 0xf);
armAsm->Eor(EEX, EEX, 0xf);
// armAsm->Cmp(EEX, 0xf); // Eor or Cmp
// flag test
armAsm->Tst(EEX, EEX);
armAsm->Eor(EDX, EDX, 0xf);
// xForwardJNZ8 exitPoint;
a64::Label exitPoint;
armAsm->B(&exitPoint, a64::Condition::ne);
armAsm->Cbnz(EDX, &exitPoint);
// xMOVAPS (xmm0, ptr32[arg1reg + 0x20]);
armAsm->Ldr(xmm0, a64::MemOperand(RAX, 0x20));
@@ -384,15 +350,15 @@ static void mVUGenerateCompareState(mV)
armAsm->And(xmm0.V16B(), xmm0.V16B(), xmm1.V16B());
// xMOVMSKPS(eax, xmm0);
armMOVMSKPS(EEX, xmm0);
armMOVMSKPS(EDX, xmm0);
// xXOR(eax, 0xf);
armAsm->Eor(EEX, EEX, 0xf);
armAsm->Eor(EDX, EDX, 0xf);
// exitPoint.SetTarget();
armBind(&exitPoint);
// 결과값
armAsm->Mov(EAX, EEX);
// Result
armAsm->Mov(EAX, EDX);
}
// xRET();
+13 -74
View File
@@ -255,52 +255,26 @@ __fi void mVUbackupRegs(microVU& mVU, bool toMemory = false, bool onlyNeeded = f
{
if (toMemory)
{
int i, num_xmms = 0, num_gprs = 0;
int i;
for (i = 0; i < static_cast<int>(iREGCNT_GPR); ++i)
{
if (!armIsCallerSaved(i) || i == 4)
continue;
if (!onlyNeeded || mVU.regAlloc->checkCachedGPR(i))
{
num_gprs++;
// xPUSH(xRegister64(i));
armAsm->Push(a64::xzr, a64::Register(i, a64::kXRegSize));
if (!onlyNeeded || mVU.regAlloc->checkCachedGPR(i)) {
armAsm->Push(a64::xzr, a64::XRegister(i));
}
}
////
std::bitset<iREGCNT_XMM> save_xmms;
for (i = 0; i < static_cast<int>(iREGCNT_XMM); ++i)
{
if (!armIsCallerSavedXmm(i))
continue;
if (!onlyNeeded || mVU.regAlloc->checkCachedReg(i) || xmmPQ.GetCode() == i)
{
save_xmms[i] = true;
num_xmms++;
}
}
// we need 16 byte alignment on the stack
const int stack_size = (num_xmms * sizeof(u128)) + ((num_gprs & 1) * sizeof(u128)) + 32;
int stack_offset = 32;
if (stack_size > 0)
{
// xSUB(rsp, stack_size);
armAsm->Sub(a64::sp, a64::sp, stack_size);
for (i = 0; i < static_cast<int>(iREGCNT_XMM); ++i)
{
if (save_xmms[i])
{
// xMOVAPS(ptr128[rsp + stack_offset], xRegisterSSE(i));
armAsm->Str(a64::QRegister(i).Q(), a64::MemOperand(a64::sp, stack_offset));
stack_offset += sizeof(u128);
}
if (!onlyNeeded || mVU.regAlloc->checkCachedReg(i) || xmmPQ.GetCode() == i) {
armAsm->Push(a64::xzr, a64::DRegister(i));
}
}
}
@@ -318,59 +292,24 @@ __fi void mVUrestoreRegs(microVU& mVU, bool fromMemory = false, bool onlyNeeded
{
if (fromMemory)
{
int i, num_xmms = 0, num_gprs = 0;
std::bitset<iREGCNT_GPR> save_gprs;
for (i = 0; i < static_cast<int>(iREGCNT_GPR); ++i)
{
if (!armIsCallerSaved(i) || i == 4)
continue;
if (!onlyNeeded || mVU.regAlloc->checkCachedGPR(i))
{
save_gprs[i] = true;
num_gprs++;
}
}
std::bitset<iREGCNT_XMM> save_xmms;
int i;
for (i = 0; i < static_cast<int>(iREGCNT_XMM); ++i)
{
if (!armIsCallerSavedXmm(i))
continue;
if (!onlyNeeded || mVU.regAlloc->checkCachedReg(i) || xmmPQ.GetCode() == i)
{
save_xmms[i] = true;
num_xmms++;
if (!onlyNeeded || mVU.regAlloc->checkCachedReg(i) || xmmPQ.GetCode() == i) {
armAsm->Pop(a64::DRegister(i), a64::xzr);
}
}
const int stack_extra = 32;
const int stack_size = (num_xmms * sizeof(u128)) + ((num_gprs & 1) * sizeof(u128)) + stack_extra;
if (num_xmms > 0)
for (i = 0; i < static_cast<int>(iREGCNT_GPR); ++i)
{
int stack_offset = (num_xmms - 1) * sizeof(u128) + stack_extra;
for (i = static_cast<int>(iREGCNT_XMM - 1); i >= 0; --i)
{
if (!save_xmms[i])
continue;
if (!armIsCallerSaved(i) || i == 4)
continue;
// xMOVAPS(xRegisterSSE(i), ptr128[rsp + stack_offset]);
armAsm->Ldr(a64::QRegister(i).Q(), a64::MemOperand(a64::sp, stack_offset));
stack_offset -= sizeof(u128);
}
}
if (stack_size > 0) {
// xADD(rsp, stack_size);
armAsm->Add(a64::sp, a64::sp, stack_size);
}
for (i = static_cast<int>(iREGCNT_GPR - 1); i >= 0; --i)
{
if (save_gprs[i]) {
// xPOP(xRegister64(i));
armAsm->Pop(a64::Register(i, a64::kXRegSize), a64::xzr);
if (!onlyNeeded || mVU.regAlloc->checkCachedGPR(i)) {
armAsm->Pop(a64::XRegister(i), a64::xzr);
}
}
}