// Copyright (c) 2012- PPSSPP Project. // This program is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, version 2.0 or later versions. // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License 2.0 for more details. // A copy of the GPL 2.0 should have been included with the program. // If not, see http://www.gnu.org/licenses/ // Official git repository and contact information can be found at // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #pragma once #include #include #include "Common/CommonTypes.h" #include "Core/MemMap.h" #include "Core/MIPS/MIPS.h" // TODO: Find a better place for these. std::vector DisassembleArm2(const u8 *data, int size); std::vector DisassembleArm64(const u8 *data, int size); // offsets, if given, receives each line's offset from data. std::vector DisassembleX86(const u8 *data, int size, std::vector *offsets = nullptr); std::vector DisassembleRV64(const u8 *data, int size); std::vector DisassembleLA64(const u8 *data, int size); class JitBlockCacheDebugInterface; class PointerWrap; class MIPSState; namespace MIPSComp { void JitAt(MIPSState *mips); class MIPSFrontendInterface { public: virtual ~MIPSFrontendInterface() {} virtual void EatPrefix() = 0; virtual void Comp_Generic(MIPSOpcode op) = 0; virtual void Comp_ReplacementFunc(MIPSOpcode op) = 0; virtual void Comp_ITypeMem(MIPSOpcode op) = 0; virtual void Comp_StoreSync(MIPSOpcode op) = 0; virtual void Comp_Cache(MIPSOpcode op) = 0; virtual void Comp_RelBranch(MIPSOpcode op) = 0; virtual void Comp_RelBranchRI(MIPSOpcode op) = 0; virtual void Comp_FPUBranch(MIPSOpcode op) = 0; virtual void Comp_FPULS(MIPSOpcode op) = 0; virtual void Comp_FPUComp(MIPSOpcode op) = 0; virtual void Comp_Jump(MIPSOpcode op) = 0; virtual void Comp_JumpReg(MIPSOpcode op) = 0; virtual void Comp_Syscall(MIPSOpcode op) = 0; virtual void Comp_Break(MIPSOpcode op) = 0; virtual void Comp_IType(MIPSOpcode op) = 0; virtual void Comp_RType2(MIPSOpcode op) = 0; virtual void Comp_RType3(MIPSOpcode op) = 0; virtual void Comp_ShiftType(MIPSOpcode op) = 0; virtual void Comp_Allegrex(MIPSOpcode op) = 0; virtual void Comp_Allegrex2(MIPSOpcode op) = 0; virtual void Comp_VBranch(MIPSOpcode op) = 0; virtual void Comp_MulDivType(MIPSOpcode op) = 0; virtual void Comp_Special3(MIPSOpcode op) = 0; virtual void Comp_FPU3op(MIPSOpcode op) = 0; virtual void Comp_FPU2op(MIPSOpcode op) = 0; virtual void Comp_mxc1(MIPSOpcode op) = 0; virtual void Comp_SV(MIPSOpcode op) = 0; virtual void Comp_SVQ(MIPSOpcode op) = 0; virtual void Comp_VPFX(MIPSOpcode op) = 0; virtual void Comp_VVectorInit(MIPSOpcode op) = 0; virtual void Comp_VMatrixInit(MIPSOpcode op) = 0; virtual void Comp_VDot(MIPSOpcode op) = 0; virtual void Comp_VecDo3(MIPSOpcode op) = 0; virtual void Comp_VV2Op(MIPSOpcode op) = 0; virtual void Comp_Mftv(MIPSOpcode op) = 0; virtual void Comp_Vmfvc(MIPSOpcode op) = 0; virtual void Comp_Vmtvc(MIPSOpcode op) = 0; virtual void Comp_Vmmov(MIPSOpcode op) = 0; virtual void Comp_VScl(MIPSOpcode op) = 0; virtual void Comp_Vmmul(MIPSOpcode op) = 0; virtual void Comp_Vmscl(MIPSOpcode op) = 0; virtual void Comp_Vtfm(MIPSOpcode op) = 0; virtual void Comp_VHdp(MIPSOpcode op) = 0; virtual void Comp_VCrs(MIPSOpcode op) = 0; virtual void Comp_VDet(MIPSOpcode op) = 0; virtual void Comp_Vi2x(MIPSOpcode op) = 0; virtual void Comp_Vx2i(MIPSOpcode op) = 0; virtual void Comp_Vf2i(MIPSOpcode op) = 0; virtual void Comp_Vi2f(MIPSOpcode op) = 0; virtual void Comp_Vh2f(MIPSOpcode op) = 0; virtual void Comp_Vcst(MIPSOpcode op) = 0; virtual void Comp_Vhoriz(MIPSOpcode op) = 0; virtual void Comp_VRot(MIPSOpcode op) = 0; virtual void Comp_VIdt(MIPSOpcode op) = 0; virtual void Comp_Vcmp(MIPSOpcode op) = 0; virtual void Comp_Vcmov(MIPSOpcode op) = 0; virtual void Comp_Viim(MIPSOpcode op) = 0; virtual void Comp_Vfim(MIPSOpcode op) = 0; virtual void Comp_VCrossQuat(MIPSOpcode op) = 0; virtual void Comp_Vsgn(MIPSOpcode op) = 0; virtual void Comp_Vocp(MIPSOpcode op) = 0; virtual void Comp_ColorConv(MIPSOpcode op) = 0; virtual void Comp_Vbfy(MIPSOpcode op) = 0; virtual void Comp_DoNothing(MIPSOpcode op) = 0; virtual int Replace_fabsf() = 0; }; // For the JIT stats debug overlay. struct JitStats { int numBlocks = 0; int numValidBlocks = 0; // In IR instructions. Invalidated blocks keep their space until the cache is cleared. size_t irArenaUsed = 0; size_t irArenaSize = 0; // In bytes. Zero when not compiling to native code. size_t codeUsed = 0; size_t codeSize = 0; // How many times the cache was cleared because one of them filled up. int irArenaFullClears = 0; int codeFullClears = 0; // Calls to InvalidateCacheAt that hit at least one block, and the blocks they hit. int invalidations = 0; int invalidatedBlocks = 0; }; class JitInterface { public: virtual ~JitInterface() {} virtual void GetStats(JitStats *stats) const {} virtual const u8 *GetCodeBase() const = 0; // Just for displaying in the debugger. virtual bool CodeInRange(const u8 *ptr) const = 0; virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) = 0; virtual bool IsAtDispatchFetch(const u8 *ptr) const { return false; } virtual const u8 *GetDispatcher() const = 0; virtual const u8 *GetCrashHandler() const = 0; virtual JitBlockCacheDebugInterface *GetBlockCacheDebugInterface() = 0; virtual void InvalidateCacheAt(u32 em_address, int length = 4) = 0; // Invalidates every block not entirely inside one of the (address, size) ranges. virtual void InvalidateCacheExcept(const std::vector> &keep) = 0; virtual void DoState(PointerWrap &p) = 0; virtual void RunLoopUntil(u64 globalticks) = 0; // Runs until the downcount runs out, without CoreTiming. For the Media Engine, which the IR // interpreter runs, and the native JITs that NativeJitRunsMediaEngine(). virtual void RunDowncount() {} virtual void Compile(u32 em_address) = 0; virtual void ClearCache() = 0; virtual void UpdateFCR31() = 0; // Writes out what --jit-profile collected, before the JIT goes away. virtual void FlushProfile() {} // What the block shadow holds for a replacement hook without a compiled block. The // dispatcher has to send this to the compiler. virtual u32 GetBlockShadowHookValue() const { return Memory::BLOCK_SHADOW_HOOK_NO_JIT; } }; typedef void (MIPSFrontendInterface::*MIPSCompileFunc)(MIPSOpcode opcode); typedef int (MIPSFrontendInterface::*MIPSReplaceFunc)(); struct BranchInfo { BranchInfo(u32 pc, MIPSOpcode op, MIPSOpcode delaySlotOp, bool andLink, bool likely); u32 compilerPC; MIPSOpcode op; MIPSOpcode delaySlotOp; u64 delaySlotInfo; bool likely; bool andLink; // Update manually if it's not always nice (rs/rt, rs/zero, etc.) bool delaySlotIsNice = true; bool delaySlotIsBranch; }; // This seems to be the same for all branch types. u32 ResolveNotTakenTarget(const BranchInfo &branchInfo); void DoDummyJitState(PointerWrap &p, const MIPSState *mips); JitInterface *CreateNativeJit(MIPSState *mipsState); // Whether the native JIT's dispatcher can run the Media Engine. bool NativeJitRunsMediaEngine(); }