Android project - Change calleesaved x86(rbp,rbx,r12,r13,r14,r15) => arm64(19,20,21,22,23,24)

This commit is contained in:
k2154
2025-07-18 22:17:04 +09:00
parent 5a7729ea33
commit e5ce561449
9 changed files with 92 additions and 117 deletions
+9 -27
View File
@@ -170,21 +170,8 @@ void armEmitJmp(const void* ptr, bool force_inline)
}
}
//a64::RegList g_cpuList(a64::x3.GetBit() | a64::x5.GetBit() | a64::x12.GetBit() | a64::x13.GetBit() | a64::x14.GetBit() | a64::x15.GetBit());
//a64::CPURegList g_caller_regs = a64::CPURegList(a64::CPURegister::kRegister, a64::kXRegSize, g_cpuList);
void armEmitCall(const void* ptr, bool force_inline, bool reg_move)
void armEmitCall(const void* ptr, bool force_inline)
{
if(reg_move) {
// armAsm->PushCPURegList(g_caller_regs);
armAsm->Mov(RSTATE_x19, a64::x3);
armAsm->Mov(RSTATE_x20, a64::x5);
armAsm->Mov(RSTATE_x21, a64::x12);
armAsm->Mov(RSTATE_x22, a64::x13);
armAsm->Mov(RSTATE_x23, a64::x14);
armAsm->Mov(RSTATE_x24, a64::x15);
}
s64 displacement = GetPCDisplacement(armGetCurrentCodePointer(), ptr);
bool use_blr = !vixl::IsInt26(displacement);
if (use_blr && armConstantPool && !force_inline)
@@ -206,16 +193,6 @@ void armEmitCall(const void* ptr, bool force_inline, bool reg_move)
a64::SingleEmissionCheckScope guard(armAsm);
armAsm->bl(displacement);
}
if(reg_move) {
// armAsm->PopCPURegList(g_caller_regs);
armAsm->Mov(a64::x3, RSTATE_x19);
armAsm->Mov(a64::x5, RSTATE_x20);
armAsm->Mov(a64::x12, RSTATE_x21);
armAsm->Mov(a64::x13, RSTATE_x22);
armAsm->Mov(a64::x14, RSTATE_x23);
armAsm->Mov(a64::x15, RSTATE_x24);
}
}
void armEmitCbnz(const a64::Register& reg, const void* ptr)
@@ -355,12 +332,17 @@ bool armIsCalleeSavedRegister(int reg)
bool armIsCallerSaved(int id)
{
#ifdef _WIN32
// The x64 ABI considers the registers RAX, RCX, RDX, R8, R9, R10, R11, and XMM0-XMM5 volatile.
return (id <= 2 || (id >= 8 && id <= 11));
#if defined(__ANDROID__)
// 0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15
return (id <= 15);
#else
#ifdef _WIN32
// The x64 ABI considers the registers RAX, RCX, RDX, R8, R9, R10, R11, and XMM0-XMM5 volatile.
return (id <= 2 || (id >= 8 && id <= 11));
#else
// rax, rdi, rsi, rdx, rcx, r8, r9, r10, r11 are scratch registers.
return (id <= 2 || id == 6 || id == 7 || (id >= 8 && id <= 11));
#endif
#endif
}
+4 -4
View File
@@ -71,9 +71,9 @@ namespace a64 = vixl::aarch64;
#define RSTATE_x23 a64::x23
#define RSTATE_x24 a64::x24
#define RFASTMEMBASE a64::x25
#define RSTATE_FPU a64::x26
#define RSTATE_PSX a64::x27
#define RSTATE_CPU a64::x28
#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))
@@ -121,7 +121,7 @@ u8* armEndBlock();
void armDisassembleAndDumpCode(const void* ptr, size_t size);
void armEmitJmp(const void* ptr, bool force_inline = false);
void armEmitCall(const void* ptr, bool force_inline = false, bool reg_move = true);
void armEmitCall(const void* ptr, bool force_inline = false);
void armEmitCbnz(const a64::Register& reg, const void* ptr);
void armEmitCondBranch(a64::Condition cond, const void* ptr);
void armMoveAddressToReg(const a64::Register& reg, const void* addr);
@@ -9,7 +9,11 @@
#include "common/arm64/AsmHelpers.h"
static const uint iREGCNT_XMM = 16;
#if defined(__ANDROID__)
static const uint iREGCNT_GPR = 25;
#else
static const uint iREGCNT_GPR = 16;
#endif
enum XMMSSEType
{
+3 -3
View File
@@ -46,9 +46,9 @@ bool _isAllocatableX86reg(int x86reg)
// if (x86reg == arg1reg.GetId() || x86reg == arg2reg.GetId())
// return false;
// arg3reg is also used for dispatching without fastmem
if (!CHECK_FASTMEM && x86reg == R8X.GetCode())
return false;
// // arg3reg is also used for dispatching without fastmem
// if (!CHECK_FASTMEM && x86reg == R8X.GetCode())
// return false;
// rbp is used as the fastmem base
if (CHECK_FASTMEM && x86reg == 5)
-14
View File
@@ -37,13 +37,6 @@
#define EEREC_HI (((info) >> 24) & 0xf)
#define EEREC_ACC (((info) >> 20) & 0xf)
//#define EEREC_S (((info) >> 8) & 0x1f)
//#define EEREC_T (((info) >> 13) & 0x1f)
//#define EEREC_D (((info) >> 18) & 0x1f)
//#define EEREC_LO (((info) >> 20) & 0x1f)
//#define EEREC_HI (((info) >> 24) & 0x1f)
//#define EEREC_ACC (((info) >> 20) & 0x1f)
#define PROCESS_EE_SET_S(reg) (((reg) << 8) | PROCESS_EE_S)
#define PROCESS_EE_SET_T(reg) (((reg) << 12) | PROCESS_EE_T)
#define PROCESS_EE_SET_D(reg) (((reg) << 16) | PROCESS_EE_D)
@@ -51,13 +44,6 @@
#define PROCESS_EE_SET_HI(reg) (((reg) << 24) | PROCESS_EE_HI)
#define PROCESS_EE_SET_ACC(reg) (((reg) << 20) | PROCESS_EE_ACC)
//#define PROCESS_EE_SET_S(reg) (((reg) << 8) | PROCESS_EE_S)
//#define PROCESS_EE_SET_T(reg) (((reg) << 13) | PROCESS_EE_T)
//#define PROCESS_EE_SET_D(reg) (((reg) << 18) | PROCESS_EE_D)
//#define PROCESS_EE_SET_LO(reg) (((reg) << 20) | PROCESS_EE_LO)
//#define PROCESS_EE_SET_HI(reg) (((reg) << 24) | PROCESS_EE_HI)
//#define PROCESS_EE_SET_ACC(reg) (((reg) << 20) | PROCESS_EE_ACC)
// special info not related to above flags
#define PROCESS_CONSTS 1
#define PROCESS_CONSTT 2
+64 -60
View File
@@ -30,82 +30,86 @@ void _initX86regs()
g_x86checknext = 0;
}
std::array<int, 16> callee_saved_order{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
//std::array<int, 16> callee_saved_order{0, 1, 2, 19, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15};
//std::array<int, 16> callee_saved_order{0, 1, 2, 19, 4, 20, 6, 7, 8, 9, 10, 11, 21, 22, 23, 24};
int _getFreeX86reg(int mode)
{
int tempi = -1;
u32 bestcount = 0x10000;
int i, tempi = -1;
u32 bestcount = 0x10000;
for (uint i = 0; i < iREGCNT_GPR; i++)
// for (uint i = 0; i < 16; i++)
{
const int reg = (g_x86checknext + i) % iREGCNT_GPR;
// const int ii = (g_x86checknext + i) % 16;
// int reg = callee_saved_order[ii];
for (i = 0; i < iREGCNT_GPR; ++i)
{
const int reg = (g_x86checknext + i) % iREGCNT_GPR;
if (x86regs[reg].inuse || !_isAllocatableX86reg(reg))
continue;
if (x86regs[reg].inuse || !_isAllocatableX86reg(reg))
continue;
// if ((mode & MODE_CALLEESAVED) && xRegister32::IsCallerSaved(reg))
// continue;
if ((mode & MODE_CALLEESAVED) && armIsCallerSaved(reg))
continue;
if (mode & MODE_CALLEESAVED) {
if(!armIsCalleeSavedRegister(reg)) {
continue;
}
} else {
if(!armIsCallerSaved(reg)) {
continue;
}
}
if ((mode & MODE_COP2) && mVUIsReservedCOP2(reg))
continue;
if ((mode & MODE_COP2) && mVUIsReservedCOP2(reg))
continue;
if (x86regs[reg].inuse == 0)
{
g_x86checknext = (reg + 1) % iREGCNT_GPR;
// g_x86checknext = (ii + 1) % 16;
// if(reg == 23) {
// reg = reg;
// }
return reg;
}
}
if (x86regs[reg].inuse == 0)
{
g_x86checknext = (reg + 1) % iREGCNT_GPR;
return reg;
}
}
for (uint i = 0; i < iREGCNT_GPR; i++)
// for (uint i2 = 0; i2 < 16; i2++)
{
// int i = callee_saved_order[i2];
for (i = 0; i < iREGCNT_GPR; ++i)
{
if (!_isAllocatableX86reg(i))
continue;
if (!_isAllocatableX86reg(i))
continue;
// if ((mode & MODE_CALLEESAVED) && xRegister32::IsCallerSaved(i))
// continue;
if ((mode & MODE_CALLEESAVED) && armIsCallerSaved(i))
continue;
if (mode & MODE_CALLEESAVED) {
if(!armIsCalleeSavedRegister(i)) {
continue;
}
} else {
if(!armIsCallerSaved(i)) {
continue;
}
}
if ((mode & MODE_COP2) && mVUIsReservedCOP2(i))
continue;
if ((mode & MODE_COP2) && mVUIsReservedCOP2(i))
continue;
// should have checked inuse in the previous loop.
pxAssert(x86regs[i].inuse);
// should have checked inuse in the previous loop.
pxAssert(x86regs[i].inuse);
if (x86regs[i].needed)
continue;
if (x86regs[i].needed)
continue;
if (x86regs[i].type != X86TYPE_TEMP)
{
if (x86regs[i].type != X86TYPE_TEMP)
{
if (x86regs[i].counter < bestcount)
{
tempi = static_cast<int>(i);
bestcount = x86regs[i].counter;
}
continue;
}
if (x86regs[i].counter < bestcount)
{
tempi = static_cast<int>(i);
bestcount = x86regs[i].counter;
}
continue;
}
_freeX86reg(i);
return i;
}
_freeX86reg(i);
return i;
}
if (tempi != -1)
{
_freeX86reg(tempi);
return tempi;
}
if (tempi != -1)
{
_freeX86reg(tempi);
return tempi;
}
pxFailRel("x86 register allocation error");
return -1;
@@ -370,7 +370,7 @@ void recCall(void (*func)())
{
iFlushCall(FLUSH_INTERPRETER);
// xFastCall((void*)func);
armEmitCall(reinterpret_cast<void*>(func), false);
armEmitCall(reinterpret_cast<void*>(func));
}
// =====================================================================================================
+7 -3
View File
@@ -347,15 +347,19 @@ public:
// mark gpr registers as usable
gprMap.fill({0, 0, false, false, false, false});
for (int i = 0; i < gprTotal; i++)
for (uint i = 0; i < gprTotal; i++)
{
if (i == gprT1.GetCode() || i == gprT2.GetCode() ||
i == gprF0.GetCode() || i == gprF1.GetCode() || i == gprF2.GetCode() || i == gprF3.GetCode() ||
i == 4 //i == rsp.GetId()
i == gprF0.GetCode() || i == gprF1.GetCode() || i == gprF2.GetCode() || i == gprF3.GetCode()
|| i == 4 //i == rsp.GetId()
|| i == a64::x16.GetCode() || i == a64::x17.GetCode() || i == a64::x18.GetCode()
|| i >= iREGCNT_GPR
) {
continue;
}
// 19,20,21,22,23,24 <= callee
gprMap[i].usable = true;
}
@@ -148,11 +148,6 @@ static const char branchSTR[16][8] = {
#define gprF2 a64::w13 // Status Flag 2
#define gprF3 a64::w14 // Status Flag 3
//#define gprF0 a64::w19 // Status Flag 0
//#define gprF1 a64::w21 // Status Flag 1
//#define gprF2 a64::w22 // Status Flag 2
//#define gprF3 a64::w23 // Status Flag 3
// Function Params
#define mP microVU& mVU, int recPass
#define mV microVU& mVU