From 93475500e285057a73dfe73efb868dd22931f5a8 Mon Sep 17 00:00:00 2001 From: zilmar Date: Sat, 1 Oct 2016 05:58:04 +1000 Subject: [PATCH] [Android] Add mapping temp register --- .../N64System/Recompiler/Arm/ArmOps.cpp | 35 +++++ .../N64System/Recompiler/Arm/ArmOps.h | 1 + .../N64System/Recompiler/Arm/ArmRegInfo.cpp | 121 ++++++++++++++++++ .../N64System/Recompiler/Arm/ArmRegInfo.h | 6 +- 4 files changed, 162 insertions(+), 1 deletion(-) diff --git a/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.cpp b/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.cpp index b1d982863..ef8a6e370 100644 --- a/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.cpp +++ b/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.cpp @@ -386,6 +386,41 @@ void CArmOps::PopArmReg(uint16_t Registers) AddCode16(op.Hex); } +void CArmOps::ShiftRightSignImmed(ArmReg DestReg, ArmReg SourceReg, uint32_t shift) +{ + if ((shift & (~0x1F)) != 0) + { + g_Notify->BreakPoint(__FILE__,__LINE__); + } + else if (DestReg > 0x7 || SourceReg > 0x7) + { + CPU_Message(" asrs.w\t%s, %s, #%d", ArmRegName(DestReg), ArmRegName(SourceReg), (uint32_t)shift); + Arm32Opcode op = {0}; + op.imm5.rn = 0xF; + op.imm5.s = 0; + op.imm5.opcode = 0x752; + + op.imm5.rm = SourceReg; + op.imm5.type = 2; + op.imm5.imm2 = shift & 3; + op.imm5.rd = DestReg; + op.imm5.imm3 = (shift >> 2) & 7; + op.imm5.opcode2 = 0; + AddCode32(op.Hex); + } + else + { + CPU_Message(" asrs\t%s, %s, #%d", ArmRegName(DestReg), ArmRegName(SourceReg), (uint32_t)shift); + + ArmThumbOpcode op = {0}; + op.Imm5.rt = DestReg; + op.Imm5.rn = SourceReg; + op.Imm5.imm5 = shift; + op.Imm5.opcode = 0x2; + AddCode16(op.Hex); + } +} + void CArmOps::StoreArmRegToArmRegPointer(ArmReg Reg, ArmReg RegPointer, uint8_t offset) { if (Reg > 0x7 || RegPointer > 0x7) diff --git a/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.h b/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.h index c54b63b9f..3a5c6c023 100644 --- a/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.h +++ b/Source/Project64-core/N64System/Recompiler/Arm/ArmOps.h @@ -153,6 +153,7 @@ protected: static void MoveVariableToArmReg(void * Variable, const char * VariableName, ArmReg reg); static void PushArmReg(uint16_t Registers); static void PopArmReg(uint16_t Registers); + static void ShiftRightSignImmed(ArmReg DestReg, ArmReg SourceReg, uint32_t shift); static void StoreArmRegToArmRegPointer(ArmReg Reg, ArmReg RegPointer, uint8_t offset); static void SubConstFromArmReg(ArmReg Reg, uint32_t Const); static void SubConstFromVariable(uint32_t Const, void * Variable, const char * VariableName); diff --git a/Source/Project64-core/N64System/Recompiler/Arm/ArmRegInfo.cpp b/Source/Project64-core/N64System/Recompiler/Arm/ArmRegInfo.cpp index 564a622ce..e5fd89a03 100644 --- a/Source/Project64-core/N64System/Recompiler/Arm/ArmRegInfo.cpp +++ b/Source/Project64-core/N64System/Recompiler/Arm/ArmRegInfo.cpp @@ -21,6 +21,7 @@ m_InCallDirect(false) { for (int32_t i = 0, n = sizeof(m_ArmReg_MappedTo) / sizeof(m_ArmReg_MappedTo[0]); i < n; i++) { + m_ArmReg_MapOrder[i] = 0; m_ArmReg_Protected[i] = false; m_ArmReg_MappedTo[i] = NotMapped; m_Variable_MappedTo[i] = VARIABLE_UNKNOWN; @@ -41,6 +42,7 @@ CArmRegInfo& CArmRegInfo::operator=(const CArmRegInfo& right) CRegBase::operator=(right); m_InCallDirect = right.m_InCallDirect; + memcpy(&m_ArmReg_MapOrder, &right.m_ArmReg_MapOrder, sizeof(m_ArmReg_MapOrder)); memcpy(&m_ArmReg_Protected, &right.m_ArmReg_Protected, sizeof(m_ArmReg_Protected)); memcpy(&m_ArmReg_MappedTo, &right.m_ArmReg_MappedTo, sizeof(m_ArmReg_MappedTo)); memcpy(&m_Variable_MappedTo, &right.m_Variable_MappedTo, sizeof(m_Variable_MappedTo)); @@ -105,6 +107,125 @@ void CArmRegInfo::WriteBackRegisters() { } +CArmOps::ArmReg CArmRegInfo::Map_TempReg(ArmReg Reg, int32_t MipsReg, bool LoadHiWord) +{ + if (m_InCallDirect) + { + CPU_Message("%s: in CallDirect",__FUNCTION__); + g_Notify->BreakPoint(__FILE__, __LINE__); + return Arm_Unknown; + } + ArmReg GprReg = MipsReg >= 0 ? Map_Variable(VARIABLE_GPR) : Arm_Unknown; + + if (Reg == CArmOps::Arm_Any) + { + if (GetArmRegMapped(Arm_R7) == Temp_Mapped && !GetArmRegProtected(Arm_R7)) { Reg = Arm_R7; } + else if (GetArmRegMapped(Arm_R6) == Temp_Mapped && !GetArmRegProtected(Arm_R6)) { Reg = Arm_R6; } + else if (GetArmRegMapped(Arm_R5) == Temp_Mapped && !GetArmRegProtected(Arm_R5)) { Reg = Arm_R5; } + else if (GetArmRegMapped(Arm_R4) == Temp_Mapped && !GetArmRegProtected(Arm_R4)) { Reg = Arm_R4; } + else if (GetArmRegMapped(Arm_R3) == Temp_Mapped && !GetArmRegProtected(Arm_R3)) { Reg = Arm_R3; } + else if (GetArmRegMapped(Arm_R2) == Temp_Mapped && !GetArmRegProtected(Arm_R2)) { Reg = Arm_R2; } + else if (GetArmRegMapped(Arm_R1) == Temp_Mapped && !GetArmRegProtected(Arm_R1)) { Reg = Arm_R1; } + else if (GetArmRegMapped(Arm_R0) == Temp_Mapped && !GetArmRegProtected(Arm_R0)) { Reg = Arm_R0; } + else if (GetArmRegMapped(Arm_R12) == Temp_Mapped && !GetArmRegProtected(Arm_R12)) { Reg = Arm_R12; } + else if (GetArmRegMapped(Arm_R11) == Temp_Mapped && !GetArmRegProtected(Arm_R11)) { Reg = Arm_R11; } + else if (GetArmRegMapped(Arm_R10) == Temp_Mapped && !GetArmRegProtected(Arm_R10)) { Reg = Arm_R10; } + else if (GetArmRegMapped(Arm_R9) == Temp_Mapped && !GetArmRegProtected(Arm_R9)) { Reg = Arm_R9; } + else if (GetArmRegMapped(Arm_R8) == Temp_Mapped && !GetArmRegProtected(Arm_R8)) { Reg = Arm_R8; } + + if (Reg == Arm_Any) + { + Reg = FreeArmReg(); + if (Reg == Arm_Unknown) + { + WriteTrace(TraceRegisterCache, TraceError, "Failed to find a free register"); + g_Notify->BreakPoint(__FILE__, __LINE__); + return Arm_Unknown; + } + } + } + else if (GetArmRegMapped(Reg) == NotMapped || GetArmRegMapped(Reg) == Temp_Mapped) + { + if (GetArmRegProtected(Reg)) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + } + else if (GetArmRegMapped(Reg) == GPR_Mapped) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + else + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + if (MipsReg < 0) + { + CPU_Message(" regcache: allocate %s as temp storage", ArmRegName(Reg)); + } + else + { + CPU_Message(" regcache: allocate %s as temp storage (%s)", ArmRegName(Reg), LoadHiWord ? CRegName::GPR_Hi[MipsReg] : CRegName::GPR_Lo[MipsReg]); + if (GprReg == Arm_Unknown) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + if (LoadHiWord) + { + if (IsUnknown(MipsReg)) + { + LoadArmRegPointerToArmReg(Reg, GprReg, (uint8_t)(MipsReg << 3) + 4); + } + else if (IsMapped(MipsReg)) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + } + else + { + if (Is64Bit(MipsReg)) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + //MoveConstToArmReg(Reg, GetMipsRegHi(MipsReg)); + } + else + { + g_Notify->BreakPoint(__FILE__, __LINE__); + //MoveConstToArmReg(Reg, GetMipsRegLo_S(MipsReg) >> 31); + } + } + } + else + { + if (IsUnknown(MipsReg)) + { + LoadArmRegPointerToArmReg(Reg, GprReg, (uint8_t)(MipsReg << 3)); + } + else if (IsMapped(MipsReg)) + { + g_Notify->BreakPoint(__FILE__, __LINE__); + //MoveArmRegToArmReg(GetMipsRegMapLo(MipsReg), Reg); + } + else + { + MoveConstToArmReg(GetMipsRegLo(MipsReg), Reg ); + } + } + } + SetArmRegMapped(Reg, Temp_Mapped); + SetArmRegProtected(Reg, true); + for (int32_t i = 0, n = sizeof(m_ArmReg_MappedTo) / sizeof(m_ArmReg_MappedTo[0]); i < n; i++) + { + int32_t MapOrder = GetArmRegMapOrder((ArmReg)i); + if (MapOrder > 0) + { + SetArmRegMapOrder((ArmReg)i, MapOrder + 1); + } + } + SetArmRegMapOrder(Reg, 1); + SetArmRegProtected(GprReg, false); + return Reg; +} + CArmOps::ArmReg CArmRegInfo::Map_Variable(VARIABLE_MAPPED variable) { if (m_InCallDirect) diff --git a/Source/Project64-core/N64System/Recompiler/Arm/ArmRegInfo.h b/Source/Project64-core/N64System/Recompiler/Arm/ArmRegInfo.h index 8f20d7c1c..c5afad7a3 100644 --- a/Source/Project64-core/N64System/Recompiler/Arm/ArmRegInfo.h +++ b/Source/Project64-core/N64System/Recompiler/Arm/ArmRegInfo.h @@ -46,19 +46,23 @@ public: bool operator==(const CArmRegInfo& right) const; bool operator!=(const CArmRegInfo& right) const; - + void BeforeCallDirect(void); void AfterCallDirect(void); ArmReg FreeArmReg(); void WriteBackRegisters(); + ArmReg Map_TempReg(ArmReg Reg, int32_t MipsReg, bool LoadHiWord); ArmReg Map_Variable(VARIABLE_MAPPED variable); + inline uint32_t GetArmRegMapOrder(ArmReg Reg) const { return m_ArmReg_MapOrder[Reg]; } inline bool GetArmRegProtected(ArmReg Reg) const { return m_ArmReg_Protected[Reg]; } inline REG_MAPPED GetArmRegMapped(ArmReg Reg) const { return m_ArmReg_MappedTo[Reg]; } + inline void SetArmRegMapOrder(ArmReg Reg, uint32_t Order) { m_ArmReg_MapOrder[Reg] = Order; } inline void SetArmRegProtected(ArmReg Reg, bool Protected) { m_ArmReg_Protected[Reg] = Protected; } inline void SetArmRegMapped(ArmReg Reg, REG_MAPPED Mapping) { m_ArmReg_MappedTo[Reg] = Mapping; } private: + uint32_t m_ArmReg_MapOrder[16]; bool m_ArmReg_Protected[16]; REG_MAPPED m_ArmReg_MappedTo[16]; VARIABLE_MAPPED m_Variable_MappedTo[16];