diff --git a/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.cpp b/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.cpp index 2ce7075a6..9b815344d 100644 --- a/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.cpp @@ -40,6 +40,7 @@ void CArmRecompilerOps::PreCompileOpcode(void) } }*/ m_RegWorkingSet.SetBlockCycleCount(m_RegWorkingSet.GetBlockCycleCount() + g_System->CountPerOp()); + m_RegWorkingSet.ResetRegProtection(); } void CArmRecompilerOps::PostCompileOpcode ( void ) @@ -48,6 +49,7 @@ void CArmRecompilerOps::PostCompileOpcode ( void ) { g_Notify->BreakPoint(__FILE__, __LINE__); } + m_RegWorkingSet.ResetRegProtection(); } CArmRecompilerOps::CArmRecompilerOps() : @@ -251,6 +253,7 @@ void CArmRecompilerOps::Compile_Branch(BRANCH_COMPARE CompareType, BRANCH_TYPE B CPU_Message(" DoDelaySlot:"); SetJump8(DelayLinkLocation, *g_RecompPos); } + ResetRegProtection(); OverflowDelaySlot(false); return; } @@ -498,22 +501,244 @@ void CArmRecompilerOps::Compile_BranchLikely(BRANCH_COMPARE CompareType, bool Li void CArmRecompilerOps::BNE_Compare() { - if (IsKnown(m_Opcode.rs) || IsKnown(m_Opcode.rt)) + uint8_t * Jump = NULL; + + if (IsKnown(m_Opcode.rs) && IsKnown(m_Opcode.rt)) { - g_Notify->BreakPoint(__FILE__, __LINE__); - CArmRecompilerOps::UnknownOpcode(); + if (IsConst(m_Opcode.rs) && IsConst(m_Opcode.rt)) + { + if (Is64Bit(m_Opcode.rs) || Is64Bit(m_Opcode.rt)) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + CArmRecompilerOps::UnknownOpcode(); + } + else if (GetMipsRegLo(m_Opcode.rs) != GetMipsRegLo(m_Opcode.rt)) + { + m_Section->m_Jump.FallThrough = true; + m_Section->m_Cont.FallThrough = false; + } + else + { + m_Section->m_Jump.FallThrough = false; + m_Section->m_Cont.FallThrough = true; + } + } + else if (IsMapped(m_Opcode.rs) && IsMapped(m_Opcode.rt)) + { + ProtectGPR(m_Opcode.rs); + ProtectGPR(m_Opcode.rt); + if (Is64Bit(m_Opcode.rs) || Is64Bit(m_Opcode.rt)) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + CArmRecompilerOps::UnknownOpcode(); + } + else + { + CompareArmRegToArmReg(GetMipsRegMapLo(m_Opcode.rs), GetMipsRegMapLo(m_Opcode.rt)); + if (m_Section->m_Cont.FallThrough) + { + BranchLabel20(ArmBranch_Notequal, m_Section->m_Jump.BranchLabel.c_str()); + m_Section->m_Jump.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + } + else if (m_Section->m_Jump.FallThrough) + { + BranchLabel20(ArmBranch_Equal, m_Section->m_Cont.BranchLabel.c_str()); + m_Section->m_Cont.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + } + else + { + BranchLabel20(ArmBranch_Equal, m_Section->m_Cont.BranchLabel.c_str()); + m_Section->m_Cont.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + BranchLabel20(ArmBranch_Always, m_Section->m_Jump.BranchLabel.c_str()); + m_Section->m_Jump.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + } + } + } + else + { + uint32_t ConstReg = IsConst(m_Opcode.rt) ? m_Opcode.rt : m_Opcode.rs; + uint32_t MappedReg = IsConst(m_Opcode.rt) ? m_Opcode.rs : m_Opcode.rt; + + if (Is64Bit(ConstReg) || Is64Bit(MappedReg)) + { + if (Is32Bit(ConstReg) || Is32Bit(MappedReg)) + { + ProtectGPR(MappedReg); + if (Is32Bit(MappedReg)) + { + CompareArmRegToConst(Map_TempReg(Arm_Any, MappedReg, true), GetMipsRegHi(ConstReg)); + } + else + { + CompareArmRegToConst(GetMipsRegMapHi(MappedReg), GetMipsRegLo_S(ConstReg) >> 31); + } + } + else + { + g_Notify->BreakPoint(__FILE__, __LINE__); + //CompareArmRegToConst(GetMipsRegMapHi(MappedReg), GetMipsRegHi(ConstReg)); + } + if (m_Section->m_Jump.FallThrough) + { + Jump = *g_RecompPos; + BranchLabel8(ArmBranch_Notequal, "continue"); + } + else + { + BranchLabel20(ArmBranch_Notequal, m_Section->m_Jump.BranchLabel.c_str()); + m_Section->m_Jump.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + } + CompareArmRegToConst(GetMipsRegMapLo(MappedReg), GetMipsRegLo(ConstReg)); + if (m_Section->m_Cont.FallThrough) + { + BranchLabel20(ArmBranch_Notequal, m_Section->m_Jump.BranchLabel.c_str()); + m_Section->m_Jump.LinkLocation2 = (uint32_t *)(*g_RecompPos - 4); + } + else if (m_Section->m_Jump.FallThrough) + { + BranchLabel20(ArmBranch_Equal, m_Section->m_Cont.BranchLabel.c_str()); + m_Section->m_Cont.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + CPU_Message(" "); + CPU_Message(" continue:"); + SetJump8(Jump, *g_RecompPos); + } + else + { + BranchLabel20(ArmBranch_Equal, m_Section->m_Cont.BranchLabel.c_str()); + m_Section->m_Cont.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + BranchLabel20(ArmBranch_Always, m_Section->m_Jump.BranchLabel.c_str()); + m_Section->m_Jump.LinkLocation2 = (uint32_t *)(*g_RecompPos - 4); + } + } + else + { + CompareArmRegToConst(GetMipsRegMapLo(MappedReg), GetMipsRegLo(ConstReg)); + if (m_Section->m_Cont.FallThrough) + { + BranchLabel20(ArmBranch_Notequal, m_Section->m_Jump.BranchLabel.c_str()); + m_Section->m_Jump.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + } + else if (m_Section->m_Jump.FallThrough) + { + BranchLabel20(ArmBranch_Equal, m_Section->m_Cont.BranchLabel.c_str()); + m_Section->m_Cont.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + } + else + { + BranchLabel20(ArmBranch_Equal, m_Section->m_Cont.BranchLabel.c_str()); + m_Section->m_Cont.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + BranchLabel20(ArmBranch_Always, m_Section->m_Jump.BranchLabel.c_str()); + m_Section->m_Jump.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + } + } + } + } + else if (IsKnown(m_Opcode.rs) || IsKnown(m_Opcode.rt)) + { + uint32_t KnownReg = IsKnown(m_Opcode.rt) ? m_Opcode.rt : m_Opcode.rs; + uint32_t UnknownReg = IsKnown(m_Opcode.rt) ? m_Opcode.rs : m_Opcode.rt; + + if (IsMapped(KnownReg)) + { + ProtectGPR(KnownReg); + } + + if (!g_System->b32BitCore()) + { + ArmReg TempReg = Map_TempReg(Arm_Any, UnknownReg, true); + if (IsConst(KnownReg)) + { + if (Is32Bit(KnownReg) && IsSigned(KnownReg)) + { + CompareArmRegToConst(TempReg, (GetMipsRegLo_S(KnownReg) >> 31)); + } + else if (Is32Bit(KnownReg)) + { + CompareArmRegToConst(TempReg, 0); + } + else + { + CompareArmRegToConst(TempReg, GetMipsRegHi(KnownReg)); + } + } + else + { + ProtectGPR(KnownReg); + CompareArmRegToArmReg(TempReg, Is32Bit(KnownReg) ? Map_TempReg(Arm_Any, KnownReg, true) : GetMipsRegMapHi(KnownReg)); + } + if (m_Section->m_Jump.FallThrough) + { + Jump = *g_RecompPos; + BranchLabel8(ArmBranch_Notequal, "continue"); + } + else + { + BranchLabel20(ArmBranch_Notequal, m_Section->m_Jump.BranchLabel.c_str()); + m_Section->m_Jump.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + } + } + ArmReg TempReg = Map_TempReg(Arm_Any, UnknownReg, false); + if (IsConst(KnownReg)) + { + CompareArmRegToConst(TempReg, GetMipsRegLo(KnownReg)); + } + else + { + CompareArmRegToArmReg(TempReg, GetMipsRegMapLo(KnownReg)); + } + m_RegWorkingSet.SetArmRegProtected(TempReg, false); + + if (m_Section->m_Cont.FallThrough) + { + BranchLabel20(ArmBranch_Notequal, m_Section->m_Jump.BranchLabel.c_str()); + if (g_System->b32BitCore()) + { + m_Section->m_Jump.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + } + else + { + m_Section->m_Jump.LinkLocation2 = (uint32_t *)(*g_RecompPos - 4); + } + } + else if (m_Section->m_Jump.FallThrough) + { + BranchLabel20(ArmBranch_Equal, m_Section->m_Cont.BranchLabel.c_str()); + m_Section->m_Cont.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + + if (Jump) + { + CPU_Message(" "); + CPU_Message(" continue:"); + + SetJump8(Jump, *g_RecompPos); + } + } + else + { + g_Notify->BreakPoint(__FILE__, __LINE__); + CArmRecompilerOps::UnknownOpcode(); + /*JeLabel32(m_Section->m_Cont.BranchLabel.c_str(), 0); + m_Section->m_Cont.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + BranchLabel20(ArmBranch_Always, m_Section->m_Jump.BranchLabel.c_str()); + if (g_System->b32BitCore()) + { + m_Section->m_Jump.LinkLocation = (uint32_t *)(*g_RecompPos - 4); + } + else + { + m_Section->m_Jump.LinkLocation2 = (uint32_t *)(*g_RecompPos - 4); + }*/ + } } else { - uint8_t * Jump = NULL; - - //r0 = low, r1 = high - //r2 = low, r3 = high if (!g_System->b32BitCore()) { - MoveVariableToArmReg(&_GPR[m_Opcode.rs].UW[1],CRegName::GPR_Hi[m_Opcode.rs], Arm_R1); - MoveVariableToArmReg(&_GPR[m_Opcode.rt].UW[1],CRegName::GPR_Hi[m_Opcode.rt], Arm_R3); - CompareArmRegToArmReg(Arm_R1,Arm_R3); + ArmReg TempRegRs = Map_TempReg(Arm_Any, m_Opcode.rs, true); + ArmReg TempRegRt = Map_TempReg(Arm_Any, m_Opcode.rt, true); + CompareArmRegToArmReg(TempRegRs,TempRegRt); + m_RegWorkingSet.SetArmRegProtected(TempRegRs, false); + m_RegWorkingSet.SetArmRegProtected(TempRegRt, false); if (m_Section->m_Jump.FallThrough) { @@ -527,9 +752,12 @@ void CArmRecompilerOps::BNE_Compare() } } - MoveVariableToArmReg(&_GPR[m_Opcode.rs].UW[0],CRegName::GPR_Lo[m_Opcode.rs], Arm_R0); - MoveVariableToArmReg(&_GPR[m_Opcode.rt].UW[0],CRegName::GPR_Lo[m_Opcode.rt], Arm_R2); - CompareArmRegToArmReg(Arm_R0,Arm_R2); + ArmReg TempRegRs = Map_TempReg(Arm_Any, m_Opcode.rs, false); + ArmReg TempRegRt = Map_TempReg(Arm_Any, m_Opcode.rt, false); + CompareArmRegToArmReg(TempRegRs,TempRegRt); + m_RegWorkingSet.SetArmRegProtected(TempRegRs, false); + m_RegWorkingSet.SetArmRegProtected(TempRegRt, false); + if (m_Section->m_Cont.FallThrough) { BranchLabel20(ArmBranch_Notequal, m_Section->m_Jump.BranchLabel.c_str()); @@ -559,7 +787,7 @@ void CArmRecompilerOps::BNE_Compare() #ifdef tofix JeLabel32(m_Section->m_Cont.BranchLabel.c_str(), 0); m_Section->m_Cont.LinkLocation = (uint32_t *)(*g_RecompPos - 4); - JmpLabel32(m_Section->m_Jump.BranchLabel.c_str(), 0); + BranchLabel20(ArmBranch_Always, m_Section->m_Jump.BranchLabel.c_str()); if (g_System->b32BitCore()) { m_Section->m_Jump.LinkLocation = (uint32_t *)(*g_RecompPos - 4); diff --git a/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.h b/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.h index 71170967c..89d6462e8 100644 --- a/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.h +++ b/Source/Project64-core/N64System/Recompiler/Arm/ArmRecompilerOps.h @@ -222,15 +222,24 @@ public: void UpdateCounters(CRegInfo & RegSet, bool CheckTimer, bool ClearValues = false); void CompileSystemCheck(uint32_t TargetPC, const CRegInfo & RegSet); - static bool IsKnown(int32_t Reg) { return false; } - static void ResetRegProtection() - { - //m_RegWorkingSet.ResetRegProtection(); - } - inline void UnMap_GPR ( uint32_t Reg, bool WriteBackValue ) - { - //m_RegWorkingSet.UnMap_GPR(Reg,WriteBackValue); - } + static inline uint32_t GetMipsRegLo(int32_t Reg) { return m_RegWorkingSet.GetMipsRegLo(Reg); } + static inline int32_t GetMipsRegLo_S(int32_t Reg) { return m_RegWorkingSet.GetMipsRegLo_S(Reg); } + static inline uint32_t GetMipsRegHi(int32_t Reg) { return m_RegWorkingSet.GetMipsRegHi(Reg); } + static inline ArmReg GetMipsRegMapLo(int32_t Reg) { return m_RegWorkingSet.GetMipsRegMapLo(Reg); } + static inline ArmReg GetMipsRegMapHi(int32_t Reg) { return m_RegWorkingSet.GetMipsRegMapHi(Reg); } + + static inline bool IsKnown(int32_t Reg) { return m_RegWorkingSet.IsKnown(Reg); } + static inline bool IsMapped(int32_t Reg) { return m_RegWorkingSet.IsMapped(Reg); } + static inline bool IsConst(int32_t Reg) { return m_RegWorkingSet.IsConst(Reg); } + static inline bool IsSigned(int32_t Reg) { return m_RegWorkingSet.IsSigned(Reg); } + static inline bool Is32Bit(int32_t Reg) { return m_RegWorkingSet.Is32Bit(Reg); } + static inline bool Is64Bit(int32_t Reg) { return m_RegWorkingSet.Is64Bit(Reg); } + static inline void UnMap_GPR(uint32_t Reg, bool WriteBackValue){ m_RegWorkingSet.UnMap_GPR(Reg, WriteBackValue); } + static inline ArmReg Map_TempReg(ArmReg Reg, int32_t MipsReg, bool LoadHiWord) { return m_RegWorkingSet.Map_TempReg(Reg, MipsReg, LoadHiWord); } + + static inline void ResetRegProtection() { m_RegWorkingSet.ResetRegProtection(); } + static inline void ProtectGPR(uint32_t Reg) { m_RegWorkingSet.ProtectGPR(Reg); } + private: void CompileInterpterCall (void * Function, const char * FunctionName); void OverflowDelaySlot(bool TestTimer); @@ -239,7 +248,6 @@ private: STEP_TYPE m_NextInstruction; uint32_t m_CompilePC; OPCODE m_Opcode; - CArmRegInfo m_RegWorkingSet; CCodeSection * m_Section; };