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/ArmRegCache.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 "Core/MIPS/MIPS.h"20#include "ArmEmitter.h"2122namespace ArmJitConstants {2324const ArmGen::ARMReg JITBASEREG = ArmGen::R9;25const ArmGen::ARMReg CTXREG = ArmGen::R10;26const ArmGen::ARMReg MEMBASEREG = ArmGen::R11;27const ArmGen::ARMReg SCRATCHREG1 = ArmGen::R0;28const ArmGen::ARMReg SCRATCHREG2 = ArmGen::R14;29const ArmGen::ARMReg DOWNCOUNTREG = ArmGen::R7;3031enum {32TOTAL_MAPPABLE_MIPSREGS = 36,33};3435enum RegMIPSLoc {36ML_IMM,37ML_ARMREG,38// In an arm reg, but as a pre-adjusted pointer, not the actual reg.39ML_ARMREG_AS_PTR,40// In an arm reg, but also has a known immediate value.41ML_ARMREG_IMM,42ML_MEM,43};4445// Initing is the default so the flag is reversed.46enum {47MAP_DIRTY = 1,48MAP_NOINIT = 2 | MAP_DIRTY,49};5051}5253namespace MIPSAnalyst {54struct AnalysisResults;55};5657// R1 to R6: mapped MIPS regs58// R8 = flags (maybe we could do better here?)59// R9 = code pointers60// R10 = MIPS context61// R11 = base pointer62// R14 = scratch (actually LR)636465typedef int MIPSReg;6667struct RegARM {68MIPSGPReg mipsReg; // if -1, no mipsreg attached.69bool isDirty; // Should the register be written back?70};7172struct RegMIPS {73// Where is this MIPS register?74ArmJitConstants::RegMIPSLoc loc;75// Data (both or only one may be used, depending on loc.)76u32 imm;77ArmGen::ARMReg reg; // reg index78bool spillLock; // if true, this register cannot be spilled.79// If loc == ML_MEM, it's back in its location in the CPU context struct.80};8182namespace MIPSComp {83struct JitOptions;84struct JitState;85}8687class ArmRegCache {88public:89ArmRegCache(MIPSState *mipsState, MIPSComp::JitState *js, MIPSComp::JitOptions *jo);90~ArmRegCache() {}9192void Init(ArmGen::ARMXEmitter *emitter);93void Start(MIPSAnalyst::AnalysisResults &stats);9495// Protect the arm register containing a MIPS register from spilling, to ensure that96// it's being kept allocated.97void SpillLock(MIPSGPReg reg, MIPSGPReg reg2 = MIPS_REG_INVALID, MIPSGPReg reg3 = MIPS_REG_INVALID, MIPSGPReg reg4 = MIPS_REG_INVALID);98void ReleaseSpillLock(MIPSGPReg reg);99void ReleaseSpillLocks();100101void SetImm(MIPSGPReg reg, u32 immVal);102bool IsImm(MIPSGPReg reg) const;103u32 GetImm(MIPSGPReg reg) const;104// Optimally set a register to an imm value (possibly using another register.)105void SetRegImm(ArmGen::ARMReg reg, u32 imm);106107// Returns an ARM register containing the requested MIPS register.108ArmGen::ARMReg MapReg(MIPSGPReg reg, int mapFlags = 0);109ArmGen::ARMReg MapRegAsPointer(MIPSGPReg reg); // read-only, non-dirty.110111bool IsMapped(MIPSGPReg reg);112bool IsMappedAsPointer(MIPSGPReg reg);113114void MapInIn(MIPSGPReg rd, MIPSGPReg rs);115void MapDirtyIn(MIPSGPReg rd, MIPSGPReg rs, bool avoidLoad = true);116void MapDirtyInIn(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, bool avoidLoad = true);117void MapDirtyDirtyIn(MIPSGPReg rd1, MIPSGPReg rd2, MIPSGPReg rs, bool avoidLoad = true);118void MapDirtyDirtyInIn(MIPSGPReg rd1, MIPSGPReg rd2, MIPSGPReg rs, MIPSGPReg rt, bool avoidLoad = true);119void FlushArmReg(ArmGen::ARMReg r);120void FlushR(MIPSGPReg r);121void FlushBeforeCall();122void FlushAll();123void DiscardR(MIPSGPReg r);124125ArmGen::ARMReg R(MIPSGPReg preg); // Returns a cached register, while checking that it's NOT mapped as a pointer126ArmGen::ARMReg RPtr(MIPSGPReg preg); // Returns a cached register, while checking that it's mapped as a pointer127128void SetEmitter(ArmGen::ARMXEmitter *emitter) { emit_ = emitter; }129130// For better log output only.131void SetCompilerPC(u32 compilerPC) { compilerPC_ = compilerPC; }132133int GetMipsRegOffset(MIPSGPReg r);134135private:136const ArmGen::ARMReg *GetMIPSAllocationOrder(int &count);137void MapRegTo(ArmGen::ARMReg reg, MIPSGPReg mipsReg, int mapFlags);138int FlushGetSequential(MIPSGPReg startMipsReg, bool allowFlushImm);139ArmGen::ARMReg FindBestToSpill(bool unusedOnly, bool *clobbered);140141MIPSState *mips_;142ArmGen::ARMXEmitter *emit_;143MIPSComp::JitState *js_;144MIPSComp::JitOptions *jo_;145u32 compilerPC_;146147enum {148NUM_ARMREG = 16,149NUM_MIPSREG = ArmJitConstants::TOTAL_MAPPABLE_MIPSREGS,150};151152RegARM ar[NUM_ARMREG];153RegMIPS mr[NUM_MIPSREG];154};155156157