#pragma once #if defined(__arm__) || defined(_M_ARM) #if !defined(_MSC_VER) && !defined(_Printf_format_string_) #define _Printf_format_string_ #endif #include class CCodeBlock; class CArmRegInfo; class CArmOps : protected CDebugSettings { public: enum ArmReg { Arm_R0 = 0, Arm_R1 = 1, Arm_R2 = 2, Arm_R3 = 3, Arm_R4 = 4, Arm_R5 = 5, Arm_R6 = 6, Arm_R7 = 7, Arm_R8 = 8, Arm_R9 = 9, Arm_R10 = 10, Arm_R11 = 11, Arm_R12 = 12, Arm_R13 = 13, ArmRegSP = 13, Arm_R14 = 14, ArmRegLR = 14, Arm_R15 = 15, ArmRegPC = 15, Arm_Unknown = -1, Arm_Any = -2, }; enum ArmFpuSingle { Arm_S0 = 0, Arm_S1 = 1, Arm_S2 = 2, Arm_S3 = 3, Arm_S4 = 4, Arm_S5 = 5, Arm_S6 = 6, Arm_S7 = 7, Arm_S8 = 8, Arm_S9 = 9, Arm_S10 = 10, Arm_S11 = 11, Arm_S12 = 12, Arm_S13 = 13, Arm_S14 = 14, Arm_S15 = 15, Arm_S16 = 16, Arm_S17 = 17, Arm_S18 = 18, Arm_S19 = 19, Arm_S20 = 20, Arm_S21 = 21, Arm_S22 = 22, Arm_S23 = 23, Arm_S24 = 24, Arm_S25 = 25, Arm_S26 = 26, Arm_S27 = 27, Arm_S28 = 28, Arm_S29 = 29, Arm_S30 = 30, Arm_S31 = 31, }; enum ArmFpuDouble { Arm_D0 = 0, Arm_D1 = 1, Arm_D2 = 2, Arm_D3 = 3, Arm_D4 = 4, Arm_D5 = 5, Arm_D6 = 6, Arm_D7 = 7, Arm_D8 = 8, Arm_D9 = 9, Arm_D10 = 10, Arm_D11 = 11, Arm_D12 = 12, Arm_D13 = 13, Arm_D14 = 14, Arm_D15 = 15, }; enum ArmRegPushPop { ArmPushPop_R0 = 0x0001, ArmPushPop_R1 = 0x0002, ArmPushPop_R2 = 0x0004, ArmPushPop_R3 = 0x0008, ArmPushPop_R4 = 0x0010, ArmPushPop_R5 = 0x0020, ArmPushPop_R6 = 0x0040, ArmPushPop_R7 = 0x0080, ArmPushPop_R8 = 0x0100, ArmPushPop_R9 = 0x0200, ArmPushPop_R10 = 0x0400, ArmPushPop_R11 = 0x0800, ArmPushPop_R12 = 0x1000, ArmPushPop_R13 = 0x2000, ArmPushPop_SP = 0x2000, ArmPushPop_R14 = 0x4000, ArmPushPop_LR = 0x4000, ArmPushPop_R15 = 0x8000, ArmPushPop_PC = 0x8000, }; enum ArmCompareType { ArmBranch_Equal = 0, // Code = 0000 ArmBranch_Notequal = 1, // Code = 0001 ArmBranch_GreaterThanOrEqual = 10, // Code = 1010 ArmBranch_LessThan = 11, // Code = 1011 ArmBranch_GreaterThan = 12, // Code = 1100 ArmBranch_LessThanOrEqual = 13, // Code = 1101 ArmBranch_Always = 14, // Code = 1110 }; enum ArmItMask { ItMask_None, ItMask_T, ItMask_E, ItMask_TT, ItMask_ET, ItMask_TE, ItMask_EE, ItMask_TTT, ItMask_ETT, ItMask_TET, ItMask_EET, ItMask_TTE, ItMask_ETE, ItMask_TEE, ItMask_EEE, }; CArmOps(CCodeBlock & CodeBlock, CArmRegInfo & RegWorkingSet); // Logging functions void WriteArmComment(const char * Comment); void WriteArmLabel(const char * Label); void AddArmRegToArmReg(ArmReg DestReg, ArmReg SourceReg1, ArmReg SourceReg2); void AddConstToArmReg(ArmReg DestReg, uint32_t Const); void AddConstToArmReg(ArmReg DestReg, ArmReg SourceReg, uint32_t Const); void AndConstToVariable(void * Variable, const char * VariableName, uint32_t Const); void AndConstToArmReg(ArmReg DestReg, ArmReg SourceReg, uint32_t Const); void AndArmRegToArmReg(ArmReg DestReg, ArmReg SourceReg1, ArmReg SourceReg2); void ArmBreakPoint(const char * FileName, uint32_t LineNumber); void ArmNop(void); void BranchLabel8(ArmCompareType CompareType, const char * Label); void BranchLabel20(ArmCompareType CompareType, const char * Label); void CallFunction(void * Function, const char * FunctionName); void CompareArmRegToConst(ArmReg Reg, uint32_t value); void CompareArmRegToArmReg(ArmReg Reg1, ArmReg Reg2); void IfBlock(ArmItMask mask, ArmCompareType CompareType); void LoadArmRegPointerByteToArmReg(ArmReg DestReg, ArmReg RegPointer, uint16_t offset); void LoadArmRegPointerByteToArmReg(ArmReg DestReg, ArmReg RegPointer, ArmReg RegPointer2, uint8_t shift); void LoadArmRegPointerToArmReg(ArmReg DestReg, ArmReg RegPointer, uint8_t Offset, const char * comment = nullptr); void LoadArmRegPointerToArmReg(ArmReg DestReg, ArmReg RegPointer, ArmReg RegPointer2, uint8_t shift); void LoadArmRegPointerToFloatReg(ArmReg RegPointer, ArmFpuSingle Reg, uint8_t Offset); void LoadFloatingPointControlReg(ArmReg DestReg); void MoveArmRegArmReg(ArmReg DestReg, ArmReg SourceReg); void MoveArmRegToVariable(ArmReg Reg, void * Variable, const char * VariableName); void MoveConstToArmReg(ArmReg DestReg, uint16_t Const, const char * comment = nullptr); void MoveConstToArmRegTop(ArmReg DestReg, uint16_t Const, const char * comment = nullptr); void MoveConstToArmReg(ArmReg DestReg, uint32_t Const, const char * comment = nullptr); void MoveConstToVariable(uint32_t Const, void * Variable, const char * VariableName); void MoveFloatRegToVariable(ArmFpuSingle reg, void * Variable, const char * VariableName); void MoveVariableToArmReg(void * Variable, const char * VariableName, ArmReg reg); void MoveVariableToFloatReg(void * Variable, const char * VariableName, ArmFpuSingle reg); void OrArmRegToArmReg(ArmReg DestReg, ArmReg SourceReg1, ArmReg SourceReg2, uint32_t shift); void OrConstToArmReg(ArmReg DestReg, ArmReg SourceReg, uint32_t value); void OrConstToVariable(void * Variable, const char * VariableName, uint32_t value); void MulF32(ArmFpuSingle DestReg, ArmFpuSingle SourceReg1, ArmFpuSingle SourceReg2); void PushArmReg(uint16_t Registers); void PopArmReg(uint16_t Registers); void ShiftRightSignImmed(ArmReg DestReg, ArmReg SourceReg, uint32_t shift); void ShiftRightUnsignImmed(ArmReg DestReg, ArmReg SourceReg, uint32_t shift); void ShiftLeftImmed(ArmReg DestReg, ArmReg SourceReg, uint32_t shift); void SignExtendByte(ArmReg Reg); void StoreArmRegToArmRegPointer(ArmReg DestReg, ArmReg RegPointer, uint8_t Offset, const char * comment = nullptr); void StoreArmRegToArmRegPointer(ArmReg DestReg, ArmReg RegPointer, ArmReg RegPointer2, uint8_t shift); void StoreFloatingPointControlReg(ArmReg SourceReg); void StoreFloatRegToArmRegPointer(ArmFpuSingle Reg, ArmReg RegPointer, uint8_t Offset); void SubArmRegFromArmReg(ArmReg DestReg, ArmReg SourceReg1, ArmReg SourceReg2); void SubConstFromArmReg(ArmReg Reg, ArmReg SourceReg, uint32_t Const); void SubConstFromVariable(uint32_t Const, void * Variable, const char * VariableName); void TestVariable(uint32_t Const, void * Variable, const char * VariableName); void XorConstToArmReg(ArmReg DestReg, uint32_t value); void XorArmRegToArmReg(ArmReg DestReg, ArmReg SourceReg); void XorArmRegToArmReg(ArmReg DestReg, ArmReg SourceReg1, ArmReg SourceReg2); void SetJump8(uint8_t * Loc, uint8_t * JumpLoc); void SetJump20(uint32_t * Loc, uint32_t * JumpLoc); void FlushPopArmReg(void); const char * ArmRegName(ArmReg Reg); uint32_t PushPopRegisterSize(uint16_t Registers); std::string PushPopRegisterList(uint16_t Registers); static void * GetAddressOf(int32_t value, ...); private: CArmOps(void); CArmOps(const CArmOps &); CArmOps & operator=(const CArmOps &); void CodeLog(_Printf_format_string_ const char * Text, ...); void PreOpCheck(ArmReg DestReg, bool AllowedInItBlock, const char * FileName, uint32_t LineNumber); void BreakPointNotification(const char * FileName, uint32_t LineNumber); bool ArmCompareInverse(ArmCompareType CompareType); ArmCompareType ArmCompareInverseType(ArmCompareType CompareType); const char * ArmCompareSuffix(ArmCompareType CompareType); const char * ArmFpuSingleName(ArmFpuSingle Reg); const char * ArmItMaskName(ArmItMask mask); const char * ArmCurrentItCondition(); void ProgressItBlock(void); bool CanThumbCompressConst(uint32_t value); uint16_t ThumbCompressConst(uint32_t value); void AddCode8(uint8_t value); void AddCode16(uint16_t value); void AddCode32(uint32_t value); CCodeBlock & m_CodeBlock; CArmRegInfo & m_RegWorkingSet; bool m_InItBlock; int m_ItBlockInstruction; ArmCompareType m_ItBlockCompareType; ArmItMask m_ItBlockMask; ArmReg m_LastStoreReg; uint16_t m_PopRegisters; uint16_t m_PushRegisters; }; #define AddressOf(Addr) CArmOps::GetAddressOf(5, (Addr)) #endif