diff options
Diffstat (limited to 'src/ARMJIT_x64/ARMJIT_Compiler.h')
-rw-r--r-- | src/ARMJIT_x64/ARMJIT_Compiler.h | 255 |
1 files changed, 255 insertions, 0 deletions
diff --git a/src/ARMJIT_x64/ARMJIT_Compiler.h b/src/ARMJIT_x64/ARMJIT_Compiler.h new file mode 100644 index 0000000..9a64d09 --- /dev/null +++ b/src/ARMJIT_x64/ARMJIT_Compiler.h @@ -0,0 +1,255 @@ +#ifndef ARMJIT_COMPILER_H +#define ARMJIT_COMPILER_H + +#include "../dolphin/x64Emitter.h" + +#include "../ARMJIT.h" +#include "../ARMJIT_Internal.h" +#include "../ARMJIT_RegisterCache.h" + +#include <unordered_map> + +namespace ARMJIT +{ + +const Gen::X64Reg RCPU = Gen::RBP; +const Gen::X64Reg RCPSR = Gen::R15; + +const Gen::X64Reg RSCRATCH = Gen::EAX; +const Gen::X64Reg RSCRATCH2 = Gen::EDX; +const Gen::X64Reg RSCRATCH3 = Gen::ECX; +const Gen::X64Reg RSCRATCH4 = Gen::R8; + +struct LoadStorePatch +{ + void* PatchFunc; + s16 Offset; + u16 Size; +}; + +struct Op2 +{ + Op2() + {} + + Op2(u32 imm) + : IsImm(true), Imm(imm) + {} + Op2(int reg, int op, int amount) + : IsImm(false) + { + Reg.Reg = reg; + Reg.Op = op; + Reg.Amount = amount; + } + + bool IsImm; + union + { + struct + { + int Reg, Op, Amount; + } Reg; + u32 Imm; + }; +}; + +class Compiler : public Gen::XEmitter +{ +public: + Compiler(); + + void Reset(); + + JitBlockEntry CompileBlock(ARM* cpu, bool thumb, FetchedInstr instrs[], int instrsCount); + + void LoadReg(int reg, Gen::X64Reg nativeReg); + void SaveReg(int reg, Gen::X64Reg nativeReg); + + bool CanCompile(bool thumb, u16 kind); + + typedef void (Compiler::*CompileFunc)(); + + void Comp_JumpTo(Gen::X64Reg addr, bool restoreCPSR = false); + void Comp_JumpTo(u32 addr, bool forceNonConstantCycles = false); + + void Comp_AddCycles_C(bool forceNonConstant = false); + void Comp_AddCycles_CI(u32 i); + void Comp_AddCycles_CI(Gen::X64Reg i, int add); + void Comp_AddCycles_CDI(); + void Comp_AddCycles_CD(); + + enum + { + opSetsFlags = 1 << 0, + opSymmetric = 1 << 1, + opRetriveCV = 1 << 2, + opInvertCarry = 1 << 3, + opSyncCarry = 1 << 4, + opInvertOp2 = 1 << 5, + }; + + void Nop() {} + + void A_Comp_Arith(); + void A_Comp_MovOp(); + void A_Comp_CmpOp(); + + void A_Comp_MUL_MLA(); + void A_Comp_Mul_Long(); + + void A_Comp_CLZ(); + + void A_Comp_MemWB(); + void A_Comp_MemHalf(); + void A_Comp_LDM_STM(); + + void A_Comp_BranchImm(); + void A_Comp_BranchXchangeReg(); + + void A_Comp_MRS(); + void A_Comp_MSR(); + + void T_Comp_ShiftImm(); + void T_Comp_AddSub_(); + void T_Comp_ALU_Imm8(); + void T_Comp_ALU(); + void T_Comp_ALU_HiReg(); + void T_Comp_MUL(); + + void T_Comp_RelAddr(); + void T_Comp_AddSP(); + + void T_Comp_MemReg(); + void T_Comp_MemImm(); + void T_Comp_MemRegHalf(); + void T_Comp_MemImmHalf(); + void T_Comp_LoadPCRel(); + void T_Comp_MemSPRel(); + void T_Comp_PUSH_POP(); + void T_Comp_LDMIA_STMIA(); + + void T_Comp_BCOND(); + void T_Comp_B(); + void T_Comp_BranchXchangeReg(); + void T_Comp_BL_LONG_1(); + void T_Comp_BL_LONG_2(); + void T_Comp_BL_Merged(); + + enum + { + memop_Writeback = 1 << 0, + memop_Post = 1 << 1, + memop_SignExtend = 1 << 2, + memop_Store = 1 << 3, + memop_SubtractOffset = 1 << 4 + }; + void Comp_MemAccess(int rd, int rn, const Op2& op2, int size, int flags); + s32 Comp_MemAccessBlock(int rn, BitSet16 regs, bool store, bool preinc, bool decrement, bool usermode); + bool Comp_MemLoadLiteral(int size, bool signExtend, int rd, u32 addr); + + void Comp_ArithTriOp(void (Compiler::*op)(int, const Gen::OpArg&, const Gen::OpArg&), + Gen::OpArg rd, Gen::OpArg rn, Gen::OpArg op2, bool carryUsed, int opFlags); + void Comp_ArithTriOpReverse(void (Compiler::*op)(int, const Gen::OpArg&, const Gen::OpArg&), + Gen::OpArg rd, Gen::OpArg rn, Gen::OpArg op2, bool carryUsed, int opFlags); + void Comp_CmpOp(int op, Gen::OpArg rn, Gen::OpArg op2, bool carryUsed); + + void Comp_MulOp(bool S, bool add, Gen::OpArg rd, Gen::OpArg rm, Gen::OpArg rs, Gen::OpArg rn); + + void Comp_RetriveFlags(bool sign, bool retriveCV, bool carryUsed); + + void Comp_SpecialBranchBehaviour(bool taken); + + + Gen::OpArg Comp_RegShiftImm(int op, int amount, Gen::OpArg rm, bool S, bool& carryUsed); + Gen::OpArg Comp_RegShiftReg(int op, Gen::OpArg rs, Gen::OpArg rm, bool S, bool& carryUsed); + + Gen::OpArg A_Comp_GetALUOp2(bool S, bool& carryUsed); + + void LoadCPSR(); + void SaveCPSR(bool flagClean = true); + + bool FlagsNZRequired() + { return CurInstr.SetFlags & 0xC; } + + Gen::FixupBranch CheckCondition(u32 cond); + + void PushRegs(bool saveHiRegs); + void PopRegs(bool saveHiRegs); + + Gen::OpArg MapReg(int reg) + { + if (reg == 15 && !(RegCache.LoadedRegs & (1 << 15))) + return Gen::Imm32(R15); + + assert(RegCache.Mapping[reg] != Gen::INVALID_REG); + return Gen::R(RegCache.Mapping[reg]); + } + + JitBlockEntry AddEntryOffset(u32 offset) + { + return (JitBlockEntry)(ResetStart + offset); + } + + u32 SubEntryOffset(JitBlockEntry entry) + { + return (u8*)entry - ResetStart; + } + + void SwitchToNearCode() + { + FarCode = GetWritableCodePtr(); + SetCodePtr(NearCode); + } + + void SwitchToFarCode() + { + NearCode = GetWritableCodePtr(); + SetCodePtr(FarCode); + } + + bool IsJITFault(u64 addr); + + s32 RewriteMemAccess(u64 pc); + + u8* FarCode; + u8* NearCode; + u32 FarSize; + u32 NearSize; + + u8* NearStart; + u8* FarStart; + + void* PatchedStoreFuncs[2][2][3][16]; + void* PatchedLoadFuncs[2][2][3][2][16]; + + std::unordered_map<u8*, LoadStorePatch> LoadStorePatches; + + u8* ResetStart; + u32 CodeMemSize; + + bool Exit; + bool IrregularCycles; + + void* ReadBanked; + void* WriteBanked; + + bool CPSRDirty = false; + + FetchedInstr CurInstr; + + RegisterCache<Compiler, Gen::X64Reg> RegCache; + + bool Thumb; + u32 Num; + u32 R15; + u32 CodeRegion; + + u32 ConstantCycles; + + ARM* CurCPU; +}; + +} + +#endif
\ No newline at end of file |