[Android] Track push/pops

This commit is contained in:
zilmar 2017-01-10 18:25:18 +11:00
parent 20fe044b7d
commit 8cf62142b5
3 changed files with 77 additions and 13 deletions

View File

@ -23,6 +23,8 @@ int CArmOps::m_ItBlockInstruction = 0;
CArmOps::ArmCompareType CArmOps::m_ItBlockCompareType; CArmOps::ArmCompareType CArmOps::m_ItBlockCompareType;
CArmOps::ArmItMask CArmOps::m_ItBlockMask; CArmOps::ArmItMask CArmOps::m_ItBlockMask;
CArmOps::ArmReg CArmOps::m_LastStoreReg; CArmOps::ArmReg CArmOps::m_LastStoreReg;
uint16_t CArmOps::m_PopRegisters = 0;
uint16_t CArmOps::m_PushRegisters = 0;
/************************************************************************** /**************************************************************************
* Logging Functions * * Logging Functions *
@ -836,6 +838,21 @@ void CArmOps::MulF32(ArmFpuSingle DestReg, ArmFpuSingle SourceReg1, ArmFpuSingle
void CArmOps::PushArmReg(uint16_t Registers) void CArmOps::PushArmReg(uint16_t Registers)
{ {
if (m_PopRegisters != 0)
{
if (Registers == m_PopRegisters)
{
CPU_Message("%s: Ignoring Push/Pop", __FUNCTION__);
m_PopRegisters = 0;
PreOpCheck(false, __FILE__, __LINE__);
return;
}
ArmNop();
}
if (m_PushRegisters != 0)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
PreOpCheck(false,__FILE__,__LINE__); PreOpCheck(false,__FILE__,__LINE__);
if (Registers == 0) if (Registers == 0)
@ -844,6 +861,10 @@ void CArmOps::PushArmReg(uint16_t Registers)
} }
if ((Registers & ArmPushPop_SP) != 0) { g_Notify->BreakPoint(__FILE__,__LINE__); } if ((Registers & ArmPushPop_SP) != 0) { g_Notify->BreakPoint(__FILE__,__LINE__); }
if ((Registers & ArmPushPop_PC) != 0) { g_Notify->BreakPoint(__FILE__,__LINE__); } if ((Registers & ArmPushPop_PC) != 0) { g_Notify->BreakPoint(__FILE__,__LINE__); }
if ((Registers & ArmPushPop_LR) == 0)
{
m_PushRegisters = Registers;
}
std::string pushed = PushPopRegisterList(Registers); std::string pushed = PushPopRegisterList(Registers);
if ((Registers & ArmPushPop_R8) != 0 || if ((Registers & ArmPushPop_R8) != 0 ||
@ -876,41 +897,67 @@ void CArmOps::PushArmReg(uint16_t Registers)
void CArmOps::PopArmReg(uint16_t Registers) void CArmOps::PopArmReg(uint16_t Registers)
{ {
PreOpCheck(false, __FILE__, __LINE__); PreOpCheck(false, __FILE__, __LINE__);
if (Registers == 0) if (Registers == 0)
{ {
return; return;
} }
if (m_PopRegisters != 0)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (m_PushRegisters == 0 && (Registers & ArmPushPop_PC) == 0)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (m_PushRegisters != Registers && (Registers & ArmPushPop_PC) == 0)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if ((Registers & ArmPushPop_SP) != 0) { g_Notify->BreakPoint(__FILE__,__LINE__); } if ((Registers & ArmPushPop_SP) != 0) { g_Notify->BreakPoint(__FILE__,__LINE__); }
if ((Registers & ArmPushPop_LR) != 0) { g_Notify->BreakPoint(__FILE__,__LINE__); } if ((Registers & ArmPushPop_LR) != 0) { g_Notify->BreakPoint(__FILE__,__LINE__); }
m_PopRegisters = Registers;
if ((m_PopRegisters & ArmPushPop_PC) != 0)
{
FlushPopArmReg();
}
}
void CArmOps::FlushPopArmReg(void)
{
if (m_PopRegisters == 0)
{
return;
}
std::string pushed = PushPopRegisterList(m_PopRegisters); std::string pushed = PushPopRegisterList(m_PopRegisters);
if ((Registers & ArmPushPop_R8) != 0 || if ((m_PopRegisters & ArmPushPop_R8) != 0 ||
(Registers & ArmPushPop_R9) != 0 || (m_PopRegisters & ArmPushPop_R9) != 0 ||
(Registers & ArmPushPop_R10) != 0 || (m_PopRegisters & ArmPushPop_R10) != 0 ||
(Registers & ArmPushPop_R11) != 0 || (m_PopRegisters & ArmPushPop_R11) != 0 ||
(Registers & ArmPushPop_R12) != 0) (m_PopRegisters & ArmPushPop_R12) != 0)
{ {
CPU_Message("%X pop\t{%s}", (int32_t)*g_RecompPos, pushed.c_str()); CPU_Message("%X pop\t{%s}", (int32_t)*g_RecompPos, pushed.c_str());
Arm32Opcode op = {0}; Arm32Opcode op = { 0 };
op.PushPop.register_list = Registers; op.PushPop.register_list = m_PopRegisters;
op.PushPop.opcode = 0xE8BD; op.PushPop.opcode = 0xE8BD;
AddCode32(op.Hex); AddCode32(op.Hex);
} }
else else
{ {
CPU_Message(" pop\t%s", pushed.c_str()); CPU_Message(" pop\t%s", pushed.c_str());
bool pc = (Registers & ArmPushPop_PC) != 0; bool pc = (m_PopRegisters & ArmPushPop_PC) != 0;
Registers &= Registers & ~ArmPushPop_PC; m_PopRegisters &= ~ArmPushPop_PC;
ArmThumbOpcode op = {0}; ArmThumbOpcode op = { 0 };
op.Pop.register_list = (uint8_t)Registers; op.Pop.register_list = (uint8_t)m_PopRegisters;
op.Pop.p = pc ? 1 : 0; op.Pop.p = pc ? 1 : 0;
op.Pop.opcode = ArmPOP; op.Pop.opcode = ArmPOP;
AddCode16(op.Hex); AddCode16(op.Hex);
} }
m_PopRegisters = 0;
m_PushRegisters = 0;
} }
std::string CArmOps::PushPopRegisterList(uint16_t Registers) std::string CArmOps::PushPopRegisterList(uint16_t Registers)
@ -1396,6 +1443,10 @@ uint16_t CArmOps::ThumbCompressConst (uint32_t value)
void CArmOps::SetJump8(uint8_t * Loc, uint8_t * JumpLoc) void CArmOps::SetJump8(uint8_t * Loc, uint8_t * JumpLoc)
{ {
if (m_PopRegisters != 0)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (Loc == NULL || JumpLoc == NULL) if (Loc == NULL || JumpLoc == NULL)
{ {
g_Notify->BreakPoint(__FILE__, __LINE__); g_Notify->BreakPoint(__FILE__, __LINE__);
@ -1430,6 +1481,10 @@ void CArmOps::SetJump8(uint8_t * Loc, uint8_t * JumpLoc)
void CArmOps::SetJump20(uint32_t * Loc, uint32_t * JumpLoc) void CArmOps::SetJump20(uint32_t * Loc, uint32_t * JumpLoc)
{ {
if (m_PopRegisters != 0)
{
g_Notify->BreakPoint(__FILE__, __LINE__);
}
if (Loc == NULL || JumpLoc == NULL) if (Loc == NULL || JumpLoc == NULL)
{ {
g_Notify->BreakPoint(__FILE__, __LINE__); g_Notify->BreakPoint(__FILE__, __LINE__);
@ -1455,7 +1510,7 @@ void CArmOps::SetJump20(uint32_t * Loc, uint32_t * JumpLoc)
else else
{ {
op.Branch20.imm11 = (immediate & 0x7FF); op.Branch20.imm11 = (immediate & 0x7FF);
op.Branch20.imm6 = (immediate >> 11) & 0x37; op.Branch20.imm6 = (immediate >> 11) & 0x3F;
op.Branch20.J1 = (immediate >> 17) & 0x1; op.Branch20.J1 = (immediate >> 17) & 0x1;
op.Branch20.J2 = (immediate >> 18) & 0x1; op.Branch20.J2 = (immediate >> 18) & 0x1;
op.Branch20.S = (immediate >> 19) & 0x1; op.Branch20.S = (immediate >> 19) & 0x1;
@ -1494,6 +1549,7 @@ void CArmOps::PreOpCheck(bool AllowedInItBlock, const char * FileName, uint32_t
{ {
g_Notify->BreakPoint(FileName, LineNumber); g_Notify->BreakPoint(FileName, LineNumber);
} }
FlushPopArmReg();
m_LastStoreReg = Arm_Unknown; m_LastStoreReg = Arm_Unknown;
} }

View File

@ -212,6 +212,7 @@ protected:
static void * GetAddressOf(int32_t value, ...); static void * GetAddressOf(int32_t value, ...);
static void SetJump8(uint8_t * Loc, uint8_t * JumpLoc); static void SetJump8(uint8_t * Loc, uint8_t * JumpLoc);
static void SetJump20(uint32_t * Loc, uint32_t * JumpLoc); static void SetJump20(uint32_t * Loc, uint32_t * JumpLoc);
static void FlushPopArmReg(void);
static CArmRegInfo m_RegWorkingSet; static CArmRegInfo m_RegWorkingSet;
@ -245,6 +246,8 @@ private:
static ArmCompareType m_ItBlockCompareType; static ArmCompareType m_ItBlockCompareType;
static ArmItMask m_ItBlockMask; static ArmItMask m_ItBlockMask;
static ArmReg m_LastStoreReg; static ArmReg m_LastStoreReg;
static uint16_t m_PopRegisters;
static uint16_t m_PushRegisters;
}; };
#define AddressOf(Addr) CArmOps::GetAddressOf(5,(Addr)) #define AddressOf(Addr) CArmOps::GetAddressOf(5,(Addr))

View File

@ -5949,6 +5949,7 @@ void CArmRecompilerOps::UpdateCounters(CRegInfo & RegSet, bool CheckTimer, bool
MoveConstToArmReg(Arm_R0, (uint32_t)g_SystemTimer, "g_SystemTimer"); MoveConstToArmReg(Arm_R0, (uint32_t)g_SystemTimer, "g_SystemTimer");
CallFunction(AddressOf(&CSystemTimer::TimerDone), "CSystemTimer::TimerDone"); CallFunction(AddressOf(&CSystemTimer::TimerDone), "CSystemTimer::TimerDone");
RegSet.AfterCallDirect(); RegSet.AfterCallDirect();
FlushPopArmReg();
CPU_Message(""); CPU_Message("");
CPU_Message(" $Continue_From_Timer_Test:"); CPU_Message(" $Continue_From_Timer_Test:");
@ -6264,6 +6265,7 @@ void CArmRecompilerOps::SW_Const(uint32_t Value, uint32_t VAddr)
StoreArmRegToArmRegPointer(TempValueReg, VariableReg, 0); StoreArmRegToArmRegPointer(TempValueReg, VariableReg, 0);
CallFunction((void *)g_Plugins->Gfx()->ViStatusChanged, "ViStatusChanged"); CallFunction((void *)g_Plugins->Gfx()->ViStatusChanged, "ViStatusChanged");
m_RegWorkingSet.AfterCallDirect(); m_RegWorkingSet.AfterCallDirect();
FlushPopArmReg();
CPU_Message(""); CPU_Message("");
CPU_Message(" Continue:"); CPU_Message(" Continue:");
SetJump8(Jump, *g_RecompPos); SetJump8(Jump, *g_RecompPos);
@ -6286,6 +6288,7 @@ void CArmRecompilerOps::SW_Const(uint32_t Value, uint32_t VAddr)
m_RegWorkingSet.BeforeCallDirect(); m_RegWorkingSet.BeforeCallDirect();
CallFunction((void *)g_Plugins->Gfx()->ViWidthChanged, "ViWidthChanged"); CallFunction((void *)g_Plugins->Gfx()->ViWidthChanged, "ViWidthChanged");
m_RegWorkingSet.AfterCallDirect(); m_RegWorkingSet.AfterCallDirect();
FlushPopArmReg();
CPU_Message(""); CPU_Message("");
CPU_Message(" Continue:"); CPU_Message(" Continue:");
SetJump8(Jump, *g_RecompPos); SetJump8(Jump, *g_RecompPos);
@ -6683,6 +6686,7 @@ void CArmRecompilerOps::SW_Register(ArmReg Reg, uint32_t VAddr)
m_RegWorkingSet.BeforeCallDirect(); m_RegWorkingSet.BeforeCallDirect();
CallFunction((void *)g_Plugins->Gfx()->ViStatusChanged, "ViStatusChanged"); CallFunction((void *)g_Plugins->Gfx()->ViStatusChanged, "ViStatusChanged");
m_RegWorkingSet.AfterCallDirect(); m_RegWorkingSet.AfterCallDirect();
FlushPopArmReg();
CPU_Message(""); CPU_Message("");
CPU_Message(" Continue:"); CPU_Message(" Continue:");
SetJump8(Jump, *g_RecompPos); SetJump8(Jump, *g_RecompPos);
@ -6706,6 +6710,7 @@ void CArmRecompilerOps::SW_Register(ArmReg Reg, uint32_t VAddr)
m_RegWorkingSet.BeforeCallDirect(); m_RegWorkingSet.BeforeCallDirect();
CallFunction((void *)g_Plugins->Gfx()->ViWidthChanged, "ViWidthChanged"); CallFunction((void *)g_Plugins->Gfx()->ViWidthChanged, "ViWidthChanged");
m_RegWorkingSet.AfterCallDirect(); m_RegWorkingSet.AfterCallDirect();
FlushPopArmReg();
CPU_Message(""); CPU_Message("");
CPU_Message(" Continue:"); CPU_Message(" Continue:");
SetJump8(Jump, *g_RecompPos); SetJump8(Jump, *g_RecompPos);