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/IR/IRJit.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 <cstring>20#include <unordered_map>2122#include "Common/CommonTypes.h"23#include "Common/CPUDetect.h"24#include "Core/MIPS/JitCommon/JitBlockCache.h"25#include "Core/MIPS/JitCommon/JitCommon.h"26#include "Core/MIPS/IR/IRRegCache.h"27#include "Core/MIPS/IR/IRInst.h"28#include "Core/MIPS/IR/IRFrontend.h"29#include "Core/MIPS/MIPSVFPUUtils.h"3031#ifndef offsetof32#include "stddef.h"33#endif3435// Very expensive, time-profiles every block.36// Not to be released with this enabled.37//38// #define IR_PROFILING3940// Try to catch obvious misses of be above rule.41#if defined(IR_PROFILING) && defined(GOLD)42#error43#endif4445namespace MIPSComp {4647// TODO : Use arena allocators. For now let's just malloc.48class IRBlock {49public:50IRBlock() {}51IRBlock(u32 emAddr, u32 origSize, int instOffset, u32 numInstructions)52: origAddr_(emAddr), origSize_(origSize), arenaOffset_(instOffset), numIRInstructions_(numInstructions) {}53IRBlock(IRBlock &&b) {54arenaOffset_ = b.arenaOffset_;55hash_ = b.hash_;56origAddr_ = b.origAddr_;57origSize_ = b.origSize_;58origFirstOpcode_ = b.origFirstOpcode_;59nativeOffset_ = b.nativeOffset_;60numIRInstructions_ = b.numIRInstructions_;61b.arenaOffset_ = 0xFFFFFFFF;62}6364~IRBlock() {}6566u32 GetIRArenaOffset() const { return arenaOffset_; }67int GetNumIRInstructions() const { return numIRInstructions_; }68MIPSOpcode GetOriginalFirstOp() const { return origFirstOpcode_; }69bool HasOriginalFirstOp() const;70bool RestoreOriginalFirstOp(int number);71bool IsValid() const { return origAddr_ != 0 && origFirstOpcode_.encoding != 0x68FFFFFF; }72void SetNativeOffset(int offset) {73nativeOffset_ = offset;74}75int GetNativeOffset() const {76return nativeOffset_;77}78void UpdateHash() {79hash_ = CalculateHash();80}81bool HashMatches() const {82return origAddr_ && hash_ == CalculateHash();83}84bool OverlapsRange(u32 addr, u32 size) const;8586void GetRange(u32 *start, u32 *size) const {87*start = origAddr_;88*size = origSize_;89}90u32 GetOriginalStart() const {91return origAddr_;92}93u64 GetHash() const {94return hash_;95}9697void Finalize(int number);98void Destroy(int number);99100#ifdef IR_PROFILING101JitBlockProfileStats profileStats_{};102#endif103104private:105u64 CalculateHash() const;106107// Offset into the block cache's Arena108u32 arenaOffset_ = 0;109// Offset into the native code buffer.110int nativeOffset_ = -1;111u64 hash_ = 0;112u32 origAddr_ = 0;113u32 origSize_ = 0;114MIPSOpcode origFirstOpcode_ = MIPSOpcode(0x68FFFFFF);115u32 numIRInstructions_ = 0;116};117118class IRBlockCache : public JitBlockCacheDebugInterface {119public:120IRBlockCache(bool compileToNative);121122void Clear();123std::vector<int> FindInvalidatedBlockNumbers(u32 address, u32 length);124void FinalizeBlock(int blockNum, bool preload = false);125int GetNumBlocks() const override { return (int)blocks_.size(); }126int AllocateBlock(int emAddr, u32 origSize, const std::vector<IRInst> &inst);127IRBlock *GetBlock(int blockNum) {128if (blockNum >= 0 && blockNum < (int)blocks_.size()) {129return &blocks_[blockNum];130} else {131return nullptr;132}133}134void RemoveBlockFromPageLookup(int blockNum);135int GetBlockNumFromIRArenaOffset(int offset) const;136const IRInst *GetBlockInstructionPtr(const IRBlock &block) const {137return arena_.data() + block.GetIRArenaOffset();138}139const IRInst *GetBlockInstructionPtr(int blockNum) const {140return arena_.data() + blocks_[blockNum].GetIRArenaOffset();141}142const IRInst *GetArenaPtr() const {143return arena_.data();144}145bool IsValidBlock(int blockNum) const override {146return blockNum >= 0 && blockNum < (int)blocks_.size() && blocks_[blockNum].IsValid();147}148IRBlock *GetBlockUnchecked(int blockNum) {149return &blocks_[blockNum];150}151const IRBlock *GetBlock(int blockNum) const {152if (blockNum >= 0 && blockNum < (int)blocks_.size()) {153return &blocks_[blockNum];154} else {155return nullptr;156}157}158159int FindPreloadBlock(u32 em_address);160161// "Cookie" means the 24 bits we inject into the first instruction of each block.162int FindByCookie(int cookie);163164std::vector<u32> SaveAndClearEmuHackOps();165void RestoreSavedEmuHackOps(const std::vector<u32> &saved);166167JitBlockDebugInfo GetBlockDebugInfo(int blockNum) const override;168JitBlockMeta GetBlockMeta(int blockNum) const override {169JitBlockMeta meta{};170if (IsValidBlock(blockNum)) {171meta.valid = true;172blocks_[blockNum].GetRange(&meta.addr, &meta.sizeInBytes);173}174return meta;175}176JitBlockProfileStats GetBlockProfileStats(int blockNum) const override {177#ifdef IR_PROFILING178return blocks_[blockNum].profileStats_;179#else180return JitBlockProfileStats{};181#endif182}183void ComputeStats(BlockCacheStats &bcStats) const override;184int GetBlockNumberFromStartAddress(u32 em_address, bool realBlocksOnly = true) const override;185186bool SupportsProfiling() const override {187#ifdef IR_PROFILING188return true;189#else190return false;191#endif192}193194private:195u32 AddressToPage(u32 addr) const;196bool compileToNative_;197std::vector<IRBlock> blocks_;198std::vector<IRInst> arena_;199std::unordered_map<u32, std::vector<int>> byPage_;200};201202class IRJit : public JitInterface {203public:204IRJit(MIPSState *mipsState, bool actualJit);205~IRJit();206207void DoState(PointerWrap &p) override;208209const JitOptions &GetJitOptions() { return jo; }210211void RunLoopUntil(u64 globalticks) override;212213void Compile(u32 em_address) override; // Compiles a block at current MIPS PC214void CompileFunction(u32 start_address, u32 length) override;215216bool DescribeCodePtr(const u8 *ptr, std::string &name) override;217// Not using a regular block cache.218JitBlockCache *GetBlockCache() override { return nullptr; }219JitBlockCacheDebugInterface *GetBlockCacheDebugInterface() override { return &blocks_; }220MIPSOpcode GetOriginalOp(MIPSOpcode op) override;221222std::vector<u32> SaveAndClearEmuHackOps() override { return blocks_.SaveAndClearEmuHackOps(); }223void RestoreSavedEmuHackOps(std::vector<u32> saved) override { blocks_.RestoreSavedEmuHackOps(saved); }224225void ClearCache() override;226void InvalidateCacheAt(u32 em_address, int length = 4) override;227void UpdateFCR31() override;228229bool CodeInRange(const u8 *ptr) const override {230return false;231}232233const u8 *GetDispatcher() const override { return nullptr; }234const u8 *GetCrashHandler() const override { return nullptr; }235236void LinkBlock(u8 *exitPoint, const u8 *checkedEntry) override;237void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override;238239protected:240bool CompileBlock(u32 em_address, std::vector<IRInst> &instructions, u32 &mipsBytes, bool preload);241virtual bool CompileNativeBlock(IRBlockCache *irBlockCache, int block_num, bool preload) { return true; }242virtual void FinalizeNativeBlock(IRBlockCache *irBlockCache, int block_num) {}243244bool compileToNative_;245246JitOptions jo;247248IRFrontend frontend_;249IRBlockCache blocks_;250251MIPSState *mips_;252253bool compilerEnabled_ = true;254255// where to write branch-likely trampolines. not used atm256// u32 blTrampolines_;257// int blTrampolineCount_;258};259260} // namespace MIPSComp261262263