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/ARM/ArmJit.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/.1617#pragma once1819#include "Common/CPUDetect.h"20#include "Common/ArmCommon.h"21#include "Common/ArmEmitter.h"22#include "Core/MIPS/JitCommon/JitState.h"23#include "Core/MIPS/JitCommon/JitBlockCache.h"24#include "Core/MIPS/JitCommon/JitCommon.h"25#include "Core/MIPS/ARM/ArmRegCache.h"26#include "Core/MIPS/ARM/ArmRegCacheFPU.h"27#include "Core/MIPS/MIPSVFPUUtils.h"2829#ifndef offsetof30#include "stddef.h"31#endif3233namespace MIPSComp {3435class ArmJit : public ArmGen::ARMXCodeBlock, public JitInterface, public MIPSFrontendInterface {36public:37ArmJit(MIPSState *mipsState);38virtual ~ArmJit();3940void DoState(PointerWrap &p) override;4142const JitOptions &GetJitOptions() { return jo; }4344// Compiled ops should ignore delay slots45// the compiler will take care of them by itself46// OR NOT47void Comp_Generic(MIPSOpcode op) override;4849void RunLoopUntil(u64 globalticks) override;5051void Compile(u32 em_address) override; // Compiles a block at current MIPS PC5253const u8 *GetCrashHandler() const override { return crashHandler; }54bool CodeInRange(const u8 *ptr) const override { return IsInSpace(ptr); }55bool DescribeCodePtr(const u8 *ptr, std::string &name) override;56MIPSOpcode GetOriginalOp(MIPSOpcode op) override;5758void Comp_RunBlock(MIPSOpcode op) override;59void Comp_ReplacementFunc(MIPSOpcode op) override;6061// Ops62void Comp_ITypeMem(MIPSOpcode op) override;63void Comp_StoreSync(MIPSOpcode op) override;64void Comp_Cache(MIPSOpcode op) override;6566void Comp_RelBranch(MIPSOpcode op) override;67void Comp_RelBranchRI(MIPSOpcode op) override;68void Comp_FPUBranch(MIPSOpcode op) override;69void Comp_FPULS(MIPSOpcode op) override;70void Comp_FPUComp(MIPSOpcode op) override;71void Comp_Jump(MIPSOpcode op) override;72void Comp_JumpReg(MIPSOpcode op) override;73void Comp_Syscall(MIPSOpcode op) override;74void Comp_Break(MIPSOpcode op) override;7576void Comp_IType(MIPSOpcode op) override;77void Comp_RType2(MIPSOpcode op) override;78void Comp_RType3(MIPSOpcode op) override;79void Comp_ShiftType(MIPSOpcode op) override;80void Comp_Allegrex(MIPSOpcode op) override;81void Comp_Allegrex2(MIPSOpcode op) override;82void Comp_VBranch(MIPSOpcode op) override;83void Comp_MulDivType(MIPSOpcode op) override;84void Comp_Special3(MIPSOpcode op) override;8586void Comp_FPU3op(MIPSOpcode op) override;87void Comp_FPU2op(MIPSOpcode op) override;88void Comp_mxc1(MIPSOpcode op) override;8990void Comp_DoNothing(MIPSOpcode op) override;9192void Comp_SV(MIPSOpcode op) override;93void Comp_SVQ(MIPSOpcode op) override;94void Comp_VPFX(MIPSOpcode op) override;95void Comp_VVectorInit(MIPSOpcode op) override;96void Comp_VMatrixInit(MIPSOpcode op) override;97void Comp_VDot(MIPSOpcode op) override;98void Comp_VecDo3(MIPSOpcode op) override;99void Comp_VV2Op(MIPSOpcode op) override;100void Comp_Mftv(MIPSOpcode op) override;101void Comp_Vmfvc(MIPSOpcode op) override;102void Comp_Vmtvc(MIPSOpcode op) override;103void Comp_Vmmov(MIPSOpcode op) override;104void Comp_VScl(MIPSOpcode op) override;105void Comp_Vmmul(MIPSOpcode op) override;106void Comp_Vmscl(MIPSOpcode op) override;107void Comp_Vtfm(MIPSOpcode op) override;108void Comp_VHdp(MIPSOpcode op) override;109void Comp_VCrs(MIPSOpcode op) override;110void Comp_VDet(MIPSOpcode op) override;111void Comp_Vi2x(MIPSOpcode op) override;112void Comp_Vx2i(MIPSOpcode op) override;113void Comp_Vf2i(MIPSOpcode op) override;114void Comp_Vi2f(MIPSOpcode op) override;115void Comp_Vh2f(MIPSOpcode op) override;116void Comp_Vcst(MIPSOpcode op) override;117void Comp_Vhoriz(MIPSOpcode op) override;118void Comp_VRot(MIPSOpcode op) override;119void Comp_VIdt(MIPSOpcode op) override;120void Comp_Vcmp(MIPSOpcode op) override;121void Comp_Vcmov(MIPSOpcode op) override;122void Comp_Viim(MIPSOpcode op) override;123void Comp_Vfim(MIPSOpcode op) override;124void Comp_VCrossQuat(MIPSOpcode op) override;125void Comp_Vsgn(MIPSOpcode op) override;126void Comp_Vocp(MIPSOpcode op) override;127void Comp_ColorConv(MIPSOpcode op) override;128void Comp_Vbfy(MIPSOpcode op) override;129130// Non-NEON: VPFX131132// NEON implementations of the VFPU ops.133void CompNEON_SV(MIPSOpcode op);134void CompNEON_SVQ(MIPSOpcode op);135void CompNEON_VVectorInit(MIPSOpcode op);136void CompNEON_VMatrixInit(MIPSOpcode op);137void CompNEON_VDot(MIPSOpcode op);138void CompNEON_VecDo3(MIPSOpcode op);139void CompNEON_VV2Op(MIPSOpcode op);140void CompNEON_Mftv(MIPSOpcode op);141void CompNEON_Vmfvc(MIPSOpcode op);142void CompNEON_Vmtvc(MIPSOpcode op);143void CompNEON_Vmmov(MIPSOpcode op);144void CompNEON_VScl(MIPSOpcode op);145void CompNEON_Vmmul(MIPSOpcode op);146void CompNEON_Vmscl(MIPSOpcode op);147void CompNEON_Vtfm(MIPSOpcode op);148void CompNEON_VHdp(MIPSOpcode op);149void CompNEON_VCrs(MIPSOpcode op);150void CompNEON_VDet(MIPSOpcode op);151void CompNEON_Vi2x(MIPSOpcode op);152void CompNEON_Vx2i(MIPSOpcode op);153void CompNEON_Vf2i(MIPSOpcode op);154void CompNEON_Vi2f(MIPSOpcode op);155void CompNEON_Vh2f(MIPSOpcode op);156void CompNEON_Vcst(MIPSOpcode op);157void CompNEON_Vhoriz(MIPSOpcode op);158void CompNEON_VRot(MIPSOpcode op);159void CompNEON_VIdt(MIPSOpcode op);160void CompNEON_Vcmp(MIPSOpcode op);161void CompNEON_Vcmov(MIPSOpcode op);162void CompNEON_Viim(MIPSOpcode op);163void CompNEON_Vfim(MIPSOpcode op);164void CompNEON_VCrossQuat(MIPSOpcode op);165void CompNEON_Vsgn(MIPSOpcode op);166void CompNEON_Vocp(MIPSOpcode op);167void CompNEON_ColorConv(MIPSOpcode op);168void CompNEON_Vbfy(MIPSOpcode op);169170int Replace_fabsf() override;171172JitBlockCache *GetBlockCache() override { return &blocks; }173JitBlockCacheDebugInterface *GetBlockCacheDebugInterface() override { return &blocks; }174175std::vector<u32> SaveAndClearEmuHackOps() override { return blocks.SaveAndClearEmuHackOps(); }176void RestoreSavedEmuHackOps(std::vector<u32> saved) override { blocks.RestoreSavedEmuHackOps(saved); }177178void ClearCache() override;179void InvalidateCacheAt(u32 em_address, int length = 4) override;180void UpdateFCR31() override;181182void EatPrefix() override { js.EatPrefix(); }183184const u8 *GetDispatcher() const override {185return dispatcher;186}187bool IsAtDispatchFetch(const u8 *ptr) const override {188return ptr == dispatcherFetch;189}190191void LinkBlock(u8 *exitPoint, const u8 *checkedEntry) override;192void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override;193194private:195const u8 *DoJit(u32 em_address, JitBlock *b);196197void GenerateFixedCode();198void FlushAll();199void FlushPrefixV();200201u32 GetCompilerPC();202void CompileDelaySlot(int flags);203void EatInstruction(MIPSOpcode op);204void AddContinuedBlock(u32 dest);205MIPSOpcode GetOffsetInstruction(int offset);206207void WriteDownCount(int offset = 0);208void WriteDownCountR(ArmGen::ARMReg reg);209void RestoreRoundingMode(bool force = false);210void ApplyRoundingMode(bool force = false);211void UpdateRoundingMode(u32 fcr31 = -1);212void MovFromPC(ArmGen::ARMReg r);213void MovToPC(ArmGen::ARMReg r);214215bool ReplaceJalTo(u32 dest);216217void SaveDowncount();218void RestoreDowncount();219220void WriteExit(u32 destination, int exit_num);221void WriteExitDestInR(ArmGen::ARMReg Reg);222void WriteSyscallExit();223bool CheckJitBreakpoint(u32 addr, int downcountOffset);224bool CheckMemoryBreakpoint(int instructionOffset = 0);225226// Utility compilation functions227void BranchFPFlag(MIPSOpcode op, CCFlags cc, bool likely);228void BranchVFPUFlag(MIPSOpcode op, CCFlags cc, bool likely);229void BranchRSZeroComp(MIPSOpcode op, CCFlags cc, bool andLink, bool likely);230void BranchRSRTComp(MIPSOpcode op, CCFlags cc, bool likely);231232// Utilities to reduce duplicated code233void CompImmLogic(MIPSGPReg rs, MIPSGPReg rt, u32 uimm, void (ARMXEmitter::*arith)(ArmGen::ARMReg dst, ArmGen::ARMReg src, ArmGen::Operand2 op2), bool (ARMXEmitter::*tryArithI2R)(ArmGen::ARMReg dst, ArmGen::ARMReg src, u32 val), u32 (*eval)(u32 a, u32 b));234void CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, void (ARMXEmitter::*arithOp2)(ArmGen::ARMReg dst, ArmGen::ARMReg rm, ArmGen::Operand2 rn), bool (ARMXEmitter::*tryArithI2R)(ArmGen::ARMReg dst, ArmGen::ARMReg rm, u32 val), u32 (*eval)(u32 a, u32 b), bool symmetric = false);235236void CompShiftImm(MIPSOpcode op, ArmGen::ShiftType shiftType, int sa);237void CompShiftVar(MIPSOpcode op, ArmGen::ShiftType shiftType);238void CompVrotShuffle(u8 *dregs, int imm, VectorSize sz, bool negSin);239240void ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz);241void ApplyPrefixD(const u8 *vregs, VectorSize sz);242void GetVectorRegsPrefixS(u8 *regs, VectorSize sz, int vectorReg) {243_assert_(js.prefixSFlag & JitState::PREFIX_KNOWN);244GetVectorRegs(regs, sz, vectorReg);245ApplyPrefixST(regs, js.prefixS, sz);246}247void GetVectorRegsPrefixT(u8 *regs, VectorSize sz, int vectorReg) {248_assert_(js.prefixTFlag & JitState::PREFIX_KNOWN);249GetVectorRegs(regs, sz, vectorReg);250ApplyPrefixST(regs, js.prefixT, sz);251}252void GetVectorRegsPrefixD(u8 *regs, VectorSize sz, int vectorReg);253254255// For NEON mappings, it will be easier to deal directly in ARM registers.256257ArmGen::ARMReg NEONMapPrefixST(int vfpuReg, VectorSize sz, u32 prefix, int mapFlags);258ArmGen::ARMReg NEONMapPrefixS(int vfpuReg, VectorSize sz, int mapFlags) {259return NEONMapPrefixST(vfpuReg, sz, js.prefixS, mapFlags);260}261ArmGen::ARMReg NEONMapPrefixT(int vfpuReg, VectorSize sz, int mapFlags) {262return NEONMapPrefixST(vfpuReg, sz, js.prefixT, mapFlags);263}264265struct DestARMReg {266ArmGen::ARMReg rd;267ArmGen::ARMReg backingRd;268VectorSize sz;269270operator ArmGen::ARMReg() const { return rd; }271};272273struct MappedRegs {274ArmGen::ARMReg vs;275ArmGen::ARMReg vt;276DestARMReg vd;277bool overlap;278};279280MappedRegs NEONMapDirtyInIn(MIPSOpcode op, VectorSize dsize, VectorSize ssize, VectorSize tsize, bool applyPrefixes = true);281MappedRegs NEONMapInIn(MIPSOpcode op, VectorSize ssize, VectorSize tsize, bool applyPrefixes = true);282MappedRegs NEONMapDirtyIn(MIPSOpcode op, VectorSize dsize, VectorSize ssize, bool applyPrefixes = true);283284DestARMReg NEONMapPrefixD(int vfpuReg, VectorSize sz, int mapFlags);285void NEONApplyPrefixD(DestARMReg dest);286287// NEON utils288void NEONMaskToSize(ArmGen::ARMReg vs, VectorSize sz);289void NEONTranspose4x4(ArmGen::ARMReg cols[4]);290291// Utils292void SetR0ToEffectiveAddress(MIPSGPReg rs, s16 offset);293void SetCCAndR0ForSafeAddress(MIPSGPReg rs, s16 offset, ArmGen::ARMReg tempReg, bool reverse = false);294void Comp_ITypeMemLR(MIPSOpcode op, bool load);295296JitBlockCache blocks;297JitOptions jo;298JitState js;299300ArmRegCache gpr;301ArmRegCacheFPU fpr;302303MIPSState *mips_;304305int dontLogBlocks;306int logBlocks;307308public:309// Code pointers310const u8 *enterDispatcher;311312const u8 *outerLoop;313const u8 *outerLoopPCInR0;314const u8 *dispatcherCheckCoreState;315const u8 *dispatcherPCInR0;316const u8 *dispatcher;317const u8 *dispatcherFetch;318const u8 *dispatcherNoCheck;319320const u8 *restoreRoundingMode;321const u8 *applyRoundingMode;322323const u8 *crashHandler;324};325326} // namespace MIPSComp327328329330