From 8cf62142b5c8eb5c94cb32e15842be048443f966 Mon Sep 17 00:00:00 2001 From: zilmar Date: Tue, 10 Jan 2017 18:25:18 +1100 Subject: [PATCH] [Android] Track push/pops --- .../N64System/Recompiler/Arm/ArmOps.cpp | 82 ++++++++++++++++--- .../N64System/Recompiler/Arm/ArmOps.h | 3 + .../Recompiler/Arm/ArmRecompilerOps.cpp | 5 ++ 3 files changed, 77 insertions(+), 13 deletions(-) diff --git a/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.cpp b/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.cpp index ac52fb300..0f2aa4721 100644 --- a/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.cpp @@ -23,6 +23,8 @@ int CArmOps::m_ItBlockInstruction = 0; CArmOps::ArmCompareType CArmOps::m_ItBlockCompareType; CArmOps::ArmItMask CArmOps::m_ItBlockMask; CArmOps::ArmReg CArmOps::m_LastStoreReg; +uint16_t CArmOps::m_PopRegisters = 0; +uint16_t CArmOps::m_PushRegisters = 0; /************************************************************************** * Logging Functions * @@ -836,6 +838,21 @@ void CArmOps::MulF32(ArmFpuSingle DestReg, ArmFpuSingle SourceReg1, ArmFpuSingle 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__); 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_PC) != 0) { g_Notify->BreakPoint(__FILE__,__LINE__); } + if ((Registers & ArmPushPop_LR) == 0) + { + m_PushRegisters = Registers; + } std::string pushed = PushPopRegisterList(Registers); if ((Registers & ArmPushPop_R8) != 0 || @@ -876,41 +897,67 @@ void CArmOps::PushArmReg(uint16_t Registers) void CArmOps::PopArmReg(uint16_t Registers) { PreOpCheck(false, __FILE__, __LINE__); - + if (Registers == 0) { 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_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); - if ((Registers & ArmPushPop_R8) != 0 || - (Registers & ArmPushPop_R9) != 0 || - (Registers & ArmPushPop_R10) != 0 || - (Registers & ArmPushPop_R11) != 0 || - (Registers & ArmPushPop_R12) != 0) + if ((m_PopRegisters & ArmPushPop_R8) != 0 || + (m_PopRegisters & ArmPushPop_R9) != 0 || + (m_PopRegisters & ArmPushPop_R10) != 0 || + (m_PopRegisters & ArmPushPop_R11) != 0 || + (m_PopRegisters & ArmPushPop_R12) != 0) { CPU_Message("%X pop\t{%s}", (int32_t)*g_RecompPos, pushed.c_str()); - Arm32Opcode op = {0}; - op.PushPop.register_list = Registers; + Arm32Opcode op = { 0 }; + op.PushPop.register_list = m_PopRegisters; op.PushPop.opcode = 0xE8BD; AddCode32(op.Hex); } else { CPU_Message(" pop\t%s", pushed.c_str()); - bool pc = (Registers & ArmPushPop_PC) != 0; - Registers &= Registers & ~ArmPushPop_PC; + bool pc = (m_PopRegisters & ArmPushPop_PC) != 0; + m_PopRegisters &= ~ArmPushPop_PC; - ArmThumbOpcode op = {0}; - op.Pop.register_list = (uint8_t)Registers; + ArmThumbOpcode op = { 0 }; + op.Pop.register_list = (uint8_t)m_PopRegisters; op.Pop.p = pc ? 1 : 0; op.Pop.opcode = ArmPOP; AddCode16(op.Hex); } + m_PopRegisters = 0; + m_PushRegisters = 0; } 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) { + if (m_PopRegisters != 0) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } if (Loc == NULL || JumpLoc == NULL) { 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) { + if (m_PopRegisters != 0) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } if (Loc == NULL || JumpLoc == NULL) { g_Notify->BreakPoint(__FILE__, __LINE__); @@ -1455,7 +1510,7 @@ void CArmOps::SetJump20(uint32_t * Loc, uint32_t * JumpLoc) else { 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.J2 = (immediate >> 18) & 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); } + FlushPopArmReg(); m_LastStoreReg = Arm_Unknown; } diff --git a/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.h b/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.h index 5f7be59b8..b79228345 100644 --- a/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.h +++ b/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.h @@ -212,6 +212,7 @@ protected: static void * GetAddressOf(int32_t value, ...); static void SetJump8(uint8_t * Loc, uint8_t * JumpLoc); static void SetJump20(uint32_t * Loc, uint32_t * JumpLoc); + static void FlushPopArmReg(void); static CArmRegInfo m_RegWorkingSet; @@ -245,6 +246,8 @@ private: static ArmCompareType m_ItBlockCompareType; static ArmItMask m_ItBlockMask; static ArmReg m_LastStoreReg; + static uint16_t m_PopRegisters; + static uint16_t m_PushRegisters; }; #define AddressOf(Addr) CArmOps::GetAddressOf(5,(Addr)) diff --git a/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.cpp index e5ced5499..f3785a25a 100644 --- a/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.cpp @@ -5949,6 +5949,7 @@ void CArmRecompilerOps::UpdateCounters(CRegInfo & RegSet, bool CheckTimer, bool MoveConstToArmReg(Arm_R0, (uint32_t)g_SystemTimer, "g_SystemTimer"); CallFunction(AddressOf(&CSystemTimer::TimerDone), "CSystemTimer::TimerDone"); RegSet.AfterCallDirect(); + FlushPopArmReg(); CPU_Message(""); CPU_Message(" $Continue_From_Timer_Test:"); @@ -6264,6 +6265,7 @@ void CArmRecompilerOps::SW_Const(uint32_t Value, uint32_t VAddr) StoreArmRegToArmRegPointer(TempValueReg, VariableReg, 0); CallFunction((void *)g_Plugins->Gfx()->ViStatusChanged, "ViStatusChanged"); m_RegWorkingSet.AfterCallDirect(); + FlushPopArmReg(); CPU_Message(""); CPU_Message(" Continue:"); SetJump8(Jump, *g_RecompPos); @@ -6286,6 +6288,7 @@ void CArmRecompilerOps::SW_Const(uint32_t Value, uint32_t VAddr) m_RegWorkingSet.BeforeCallDirect(); CallFunction((void *)g_Plugins->Gfx()->ViWidthChanged, "ViWidthChanged"); m_RegWorkingSet.AfterCallDirect(); + FlushPopArmReg(); CPU_Message(""); CPU_Message(" Continue:"); SetJump8(Jump, *g_RecompPos); @@ -6683,6 +6686,7 @@ void CArmRecompilerOps::SW_Register(ArmReg Reg, uint32_t VAddr) m_RegWorkingSet.BeforeCallDirect(); CallFunction((void *)g_Plugins->Gfx()->ViStatusChanged, "ViStatusChanged"); m_RegWorkingSet.AfterCallDirect(); + FlushPopArmReg(); CPU_Message(""); CPU_Message(" Continue:"); SetJump8(Jump, *g_RecompPos); @@ -6706,6 +6710,7 @@ void CArmRecompilerOps::SW_Register(ArmReg Reg, uint32_t VAddr) m_RegWorkingSet.BeforeCallDirect(); CallFunction((void *)g_Plugins->Gfx()->ViWidthChanged, "ViWidthChanged"); m_RegWorkingSet.AfterCallDirect(); + FlushPopArmReg(); CPU_Message(""); CPU_Message(" Continue:"); SetJump8(Jump, *g_RecompPos);