CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Core/MIPS/x86/Jit.h
Views: 1401
// Copyright (c) 2012- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.161718// TODO: Implement https://github.com/dolphin-emu/dolphin/pull/1025/commits/b597ec3e081a289d9ac782586617a876535183d6 .1920#pragma once2122#include "Common/CommonTypes.h"23#include "Common/Thunk.h"24#include "Common/x64Emitter.h"2526#include "Common/x64Emitter.h"27#include "Core/MIPS/JitCommon/JitBlockCache.h"28#include "Core/MIPS/JitCommon/JitState.h"29#include "Core/MIPS/JitCommon/JitCommon.h"30#include "Core/MIPS/x86/JitSafeMem.h"31#include "Core/MIPS/x86/RegCache.h"32#include "Core/MIPS/x86/RegCacheFPU.h"3334class PointerWrap;3536namespace MIPSComp {3738struct RegCacheState {39GPRRegCacheState gpr;40FPURegCacheState fpr;41};4243class Jit : public Gen::XCodeBlock, public JitInterface, public MIPSFrontendInterface {44public:45Jit(MIPSState *mipsState);46~Jit();4748const JitOptions &GetJitOptions() { return jo; }4950void DoState(PointerWrap &p) override;5152// Compiled ops should ignore delay slots53// the compiler will take care of them by itself54// OR NOT55void Comp_Generic(MIPSOpcode op) override;5657void RunLoopUntil(u64 globalticks) override;5859void Compile(u32 em_address) override; // Compiles a block at current MIPS PC60const u8 *DoJit(u32 em_address, JitBlock *b);6162const u8 *GetCrashHandler() const override { return crashHandler; }63bool CodeInRange(const u8 *ptr) const override { return IsInSpace(ptr); }64bool DescribeCodePtr(const u8 *ptr, std::string &name) override;6566void Comp_RunBlock(MIPSOpcode op) override;67void Comp_ReplacementFunc(MIPSOpcode op) override;6869// Ops70void Comp_ITypeMem(MIPSOpcode op) override;71void Comp_StoreSync(MIPSOpcode op) override;72void Comp_Cache(MIPSOpcode op) override;7374void Comp_RelBranch(MIPSOpcode op) override;75void Comp_RelBranchRI(MIPSOpcode op) override;76void Comp_FPUBranch(MIPSOpcode op) override;77void Comp_FPULS(MIPSOpcode op) override;78void Comp_FPUComp(MIPSOpcode op) override;79void Comp_Jump(MIPSOpcode op) override;80void Comp_JumpReg(MIPSOpcode op) override;81void Comp_Syscall(MIPSOpcode op) override;82void Comp_Break(MIPSOpcode op) override;8384void Comp_IType(MIPSOpcode op) override;85void Comp_RType2(MIPSOpcode op) override;86void Comp_RType3(MIPSOpcode op) override;87void Comp_ShiftType(MIPSOpcode op) override;88void Comp_Allegrex(MIPSOpcode op) override;89void Comp_Allegrex2(MIPSOpcode op) override;90void Comp_VBranch(MIPSOpcode op) override;91void Comp_MulDivType(MIPSOpcode op) override;92void Comp_Special3(MIPSOpcode op) override;9394void Comp_FPU3op(MIPSOpcode op) override;95void Comp_FPU2op(MIPSOpcode op) override;96void Comp_mxc1(MIPSOpcode op) override;9798void Comp_SV(MIPSOpcode op) override;99void Comp_SVQ(MIPSOpcode op) override;100void Comp_VPFX(MIPSOpcode op) override;101void Comp_VVectorInit(MIPSOpcode op) override;102void Comp_VMatrixInit(MIPSOpcode op) override;103void Comp_VDot(MIPSOpcode op) override;104void Comp_VecDo3(MIPSOpcode op) override;105void Comp_VV2Op(MIPSOpcode op) override;106void Comp_Mftv(MIPSOpcode op) override;107void Comp_Vmfvc(MIPSOpcode op) override;108void Comp_Vmtvc(MIPSOpcode op) override;109void Comp_Vmmov(MIPSOpcode op) override;110void Comp_VScl(MIPSOpcode op) override;111void Comp_Vmmul(MIPSOpcode op) override;112void Comp_Vmscl(MIPSOpcode op) override;113void Comp_Vtfm(MIPSOpcode op) override;114void Comp_VHdp(MIPSOpcode op) override;115void Comp_VCrs(MIPSOpcode op) override;116void Comp_VDet(MIPSOpcode op) override;117void Comp_Vi2x(MIPSOpcode op) override;118void Comp_Vx2i(MIPSOpcode op) override;119void Comp_Vf2i(MIPSOpcode op) override;120void Comp_Vi2f(MIPSOpcode op) override;121void Comp_Vh2f(MIPSOpcode op) override;122void Comp_Vcst(MIPSOpcode op) override;123void Comp_Vhoriz(MIPSOpcode op) override;124void Comp_VRot(MIPSOpcode op) override;125void Comp_VIdt(MIPSOpcode op) override;126void Comp_Vcmp(MIPSOpcode op) override;127void Comp_Vcmov(MIPSOpcode op) override;128void Comp_Viim(MIPSOpcode op) override;129void Comp_Vfim(MIPSOpcode op) override;130void Comp_VCrossQuat(MIPSOpcode op) override;131void Comp_Vsgn(MIPSOpcode op) override;132void Comp_Vocp(MIPSOpcode op) override;133void Comp_ColorConv(MIPSOpcode op) override;134void Comp_Vbfy(MIPSOpcode op) override;135136void Comp_DoNothing(MIPSOpcode op) override;137138int Replace_fabsf() override;139140void ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz);141void ApplyPrefixD(const u8 *vregs, VectorSize sz);142void GetVectorRegsPrefixS(u8 *regs, VectorSize sz, int vectorReg) {143_assert_(js.prefixSFlag & JitState::PREFIX_KNOWN);144GetVectorRegs(regs, sz, vectorReg);145ApplyPrefixST(regs, js.prefixS, sz);146}147void GetVectorRegsPrefixT(u8 *regs, VectorSize sz, int vectorReg) {148_assert_(js.prefixTFlag & JitState::PREFIX_KNOWN);149GetVectorRegs(regs, sz, vectorReg);150ApplyPrefixST(regs, js.prefixT, sz);151}152void GetVectorRegsPrefixD(u8 *regs, VectorSize sz, int vectorReg);153void EatPrefix() override { js.EatPrefix(); }154155void RestoreRoundingMode(bool force = false);156void ApplyRoundingMode(bool force = false);157void UpdateRoundingMode(u32 fcr31 = -1);158159JitBlockCache *GetBlockCache() override { return &blocks; }160JitBlockCacheDebugInterface *GetBlockCacheDebugInterface() override { return &blocks; }161162MIPSOpcode GetOriginalOp(MIPSOpcode op) override;163164std::vector<u32> SaveAndClearEmuHackOps() override { return blocks.SaveAndClearEmuHackOps(); }165void RestoreSavedEmuHackOps(std::vector<u32> saved) override { blocks.RestoreSavedEmuHackOps(saved); }166167void ClearCache() override;168void InvalidateCacheAt(u32 em_address, int length = 4) override {169if (blocks.RangeMayHaveEmuHacks(em_address, em_address + length)) {170blocks.InvalidateICache(em_address, length);171}172}173void UpdateFCR31() override;174175const u8 *GetDispatcher() const override {176return dispatcher;177}178179void LinkBlock(u8 *exitPoint, const u8 *checkedEntry) override;180void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override;181182private:183void GenerateFixedCode(JitOptions &jo);184void GetStateAndFlushAll(RegCacheState &state);185void RestoreState(const RegCacheState& state);186void FlushAll();187void FlushPrefixV();188void WriteDowncount(int offset = 0);189bool ReplaceJalTo(u32 dest);190191u32 GetCompilerPC();192// See CompileDelaySlotFlags for flags.193void CompileDelaySlot(int flags, RegCacheState *state = NULL);194void CompileDelaySlot(int flags, RegCacheState &state) {195CompileDelaySlot(flags, &state);196}197void EatInstruction(MIPSOpcode op);198void AddContinuedBlock(u32 dest);199MIPSOpcode GetOffsetInstruction(int offset);200201void WriteExit(u32 destination, int exit_num);202void WriteExitDestInReg(Gen::X64Reg reg);203204// void WriteRfiExitDestInEAX();205void WriteSyscallExit();206bool CheckJitBreakpoint(u32 addr, int downcountOffset);207void CheckMemoryBreakpoint(int instructionOffset, MIPSGPReg rs, int offset);208209// Utility compilation functions210void BranchFPFlag(MIPSOpcode op, Gen::CCFlags cc, bool likely);211void BranchVFPUFlag(MIPSOpcode op, Gen::CCFlags cc, bool likely);212void BranchRSZeroComp(MIPSOpcode op, Gen::CCFlags cc, bool andLink, bool likely);213void BranchRSRTComp(MIPSOpcode op, Gen::CCFlags cc, bool likely);214void BranchLog(MIPSOpcode op);215void BranchLogExit(MIPSOpcode op, u32 dest, bool useEAX);216217// Utilities to reduce duplicated code218void CompImmLogic(MIPSOpcode op, void (XEmitter::*arith)(int, const Gen::OpArg &, const Gen::OpArg &));219void CompTriArith(MIPSOpcode op, void (XEmitter::*arith)(int, const Gen::OpArg &, const Gen::OpArg &), u32 (*doImm)(const u32, const u32), bool invertResult = false);220void CompShiftImm(MIPSOpcode op, void (XEmitter::*shift)(int, Gen::OpArg, Gen::OpArg), u32 (*doImm)(const u32, const u32));221void CompShiftVar(MIPSOpcode op, void (XEmitter::*shift)(int, Gen::OpArg, Gen::OpArg), u32 (*doImm)(const u32, const u32));222void CompITypeMemRead(MIPSOpcode op, u32 bits, void (XEmitter::*mov)(int, int, Gen::X64Reg, Gen::OpArg), const void *safeFunc);223template <typename T>224void CompITypeMemRead(MIPSOpcode op, u32 bits, void (XEmitter::*mov)(int, int, Gen::X64Reg, Gen::OpArg), T (*safeFunc)(u32 addr)) {225CompITypeMemRead(op, bits, mov, (const void *)safeFunc);226}227void CompITypeMemWrite(MIPSOpcode op, u32 bits, const void *safeFunc, bool makeRTWritable = false);228template <typename T>229void CompITypeMemWrite(MIPSOpcode op, u32 bits, void (*safeFunc)(T val, u32 addr)) {230CompITypeMemWrite(op, bits, (const void *)safeFunc);231}232void CompITypeMemUnpairedLR(MIPSOpcode op, bool isStore);233void CompITypeMemUnpairedLRInner(MIPSOpcode op, Gen::X64Reg shiftReg);234void CompBranchExits(Gen::CCFlags cc, u32 targetAddr, u32 notTakenAddr, const BranchInfo &branchInfo);235void CompBranchExit(bool taken, u32 targetAddr, u32 notTakenAddr, const BranchInfo &branchInfo);236static Gen::CCFlags FlipCCFlag(Gen::CCFlags flag);237static Gen::CCFlags SwapCCFlag(Gen::CCFlags flag);238239void CopyFPReg(Gen::X64Reg dst, Gen::OpArg src);240void CompFPTriArith(MIPSOpcode op, void (XEmitter::*arith)(Gen::X64Reg reg, Gen::OpArg), bool orderMatters);241void CompFPComp(int lhs, int rhs, u8 compare, bool allowNaN = false);242void CompVrotShuffle(u8 *dregs, int imm, int n, bool negSin);243244void CallProtectedFunction(const void *func, const Gen::OpArg &arg1);245void CallProtectedFunction(const void *func, const Gen::OpArg &arg1, const Gen::OpArg &arg2);246void CallProtectedFunction(const void *func, const Gen::OpArg &arg1, const u32 arg2);247void CallProtectedFunction(const void *func, const u32 arg1, const u32 arg2);248249template <typename Tr, typename T1>250void CallProtectedFunction(Tr (*func)(T1), const Gen::OpArg &arg1) {251CallProtectedFunction((const void *)func, arg1);252}253254template <typename Tr, typename T1, typename T2>255void CallProtectedFunction(Tr (*func)(T1, T2), const Gen::OpArg &arg1, const Gen::OpArg &arg2) {256CallProtectedFunction((const void *)func, arg1, arg2);257}258259template <typename Tr, typename T1, typename T2>260void CallProtectedFunction(Tr(*func)(T1, T2), const Gen::OpArg &arg1, const u32 arg2) {261CallProtectedFunction((const void *)func, arg1, arg2);262}263264template <typename Tr, typename T1, typename T2>265void CallProtectedFunction(Tr(*func)(T1, T2), const u32 arg1, const u32 arg2) {266CallProtectedFunction((const void *)func, arg1, arg2);267}268269bool PredictTakeBranch(u32 targetAddr, bool likely);270bool CanContinueBranch(u32 targetAddr) {271if (!jo.continueBranches || js.numInstructions >= jo.continueMaxInstructions) {272return false;273}274// Need at least 2 exits left over.275if (js.nextExit >= MAX_JIT_BLOCK_EXITS - 2) {276return false;277}278// Sometimes we predict wrong and get into impossible conditions where games have jumps to 0.279if (!targetAddr) {280return false;281}282return true;283}284bool CanContinueJump(u32 targetAddr) {285if (!jo.continueJumps || js.numInstructions >= jo.continueMaxInstructions) {286return false;287}288if (!targetAddr) {289return false;290}291return true;292}293bool CanContinueImmBranch(u32 targetAddr) {294if (!jo.immBranches || js.numInstructions >= jo.continueMaxInstructions) {295return false;296}297return true;298}299300bool IsAtDispatchFetch(const u8 *codePtr) const override {301return codePtr == dispatcherFetch;302}303304void SaveFlags();305void LoadFlags();306307JitBlockCache blocks;308JitOptions jo;309JitState js;310311GPRRegCache gpr;312FPURegCache fpr;313314ThunkManager thunks;315JitSafeMemFuncs safeMemFuncs;316317MIPSState *mips_;318319320const u8 *enterDispatcher;321322const u8 *outerLoop;323const u8 *dispatcher;324const u8 *dispatcherCheckCoreState;325const u8 *dispatcherNoCheck;326const u8 *dispatcherInEAXNoCheck;327const u8 *dispatcherFetch;328329const u8 *restoreRoundingMode;330const u8 *applyRoundingMode;331332const u8 *endOfPregeneratedCode;333334const u8 *crashHandler;335336friend class JitSafeMem;337friend class JitSafeMemFuncs;338};339340} // namespace MIPSComp341342343344