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/ARM64/Arm64RegCacheFPU.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 "Core/MIPS/ARM64/Arm64RegCache.h"21#include "Core/MIPS/MIPSVFPUUtils.h"22#include "Common/Arm64Emitter.h"2324namespace Arm64JitConstants {2526enum {27NUM_TEMPS = 16,28TEMP0 = 32 + 128,29TOTAL_MAPPABLE_MIPSFPUREGS = 32 + 128 + NUM_TEMPS,30};3132enum {33MAP_READ = 0,34MAP_MTX_TRANSPOSED = 16,35MAP_PREFER_LOW = 16,36MAP_PREFER_HIGH = 32,3738// Force is not yet correctly implemented, if the reg is already mapped it will not move39MAP_FORCE_LOW = 64, // Only map Q0-Q7 (and probably not Q0-Q3 as they are S registers so that leaves Q8-Q15)40MAP_FORCE_HIGH = 128, // Only map Q8-Q1541};4243}4445namespace MIPSAnalyst {46struct AnalysisResults;47};4849struct FPURegARM64 {50int mipsReg; // if -1, no mipsreg attached.51bool isDirty; // Should the register be written back?52};5354struct FPURegQuad64 {55int mipsVec;56VectorSize sz;57u8 vregs[4];58bool isDirty;59bool spillLock;60bool isTemp;61};6263struct FPURegMIPS {64// Where is this MIPS register?65Arm64JitConstants::RegMIPSLoc loc;66// Data (only one of these is used, depending on loc. Could make a union).67u32 reg;68int lane;6970bool spillLock; // if true, this register cannot be spilled.71bool tempLock;72// If loc == ML_MEM, it's back in its location in the CPU context struct.73};7475namespace MIPSComp {76struct JitOptions;77struct JitState;78}7980class Arm64RegCacheFPU {81public:82Arm64RegCacheFPU(MIPSState *mipsState, MIPSComp::JitState *js, MIPSComp::JitOptions *jo);83~Arm64RegCacheFPU() {}8485void Init(Arm64Gen::ARM64XEmitter *emitter, Arm64Gen::ARM64FloatEmitter *fp);8687void Start(MIPSAnalyst::AnalysisResults &stats);8889// Protect the arm register containing a MIPS register from spilling, to ensure that90// it's being kept allocated.91void SpillLock(MIPSReg reg, MIPSReg reg2 = -1, MIPSReg reg3 = -1, MIPSReg reg4 = -1);92void SpillLockV(MIPSReg r) { SpillLock(r + 32); }9394void ReleaseSpillLocksAndDiscardTemps();95void ReleaseSpillLock(int mipsreg) {96mr[mipsreg].spillLock = false;97}98void ReleaseSpillLockV(int mipsreg) {99ReleaseSpillLock(mipsreg + 32);100}101102void SetImm(MIPSReg reg, u32 immVal);103bool IsImm(MIPSReg reg) const;104u32 GetImm(MIPSReg reg) const;105106// Returns an ARM register containing the requested MIPS register.107Arm64Gen::ARM64Reg MapReg(MIPSReg reg, int mapFlags = 0);108void MapInIn(MIPSReg rd, MIPSReg rs);109void MapDirty(MIPSReg rd);110void MapDirtyIn(MIPSReg rd, MIPSReg rs, bool avoidLoad = true);111void MapDirtyInIn(MIPSReg rd, MIPSReg rs, MIPSReg rt, bool avoidLoad = true);112bool IsMapped(MIPSReg r);113bool IsMappedV(MIPSReg r) { return IsMapped((MIPSReg)(r + 32)); }114bool IsInRAM(MIPSReg r);115bool IsInRAMV(MIPSReg r) { return IsInRAM((MIPSReg)(r + 32)); }116void FlushArmReg(Arm64Gen::ARM64Reg r);117void FlushR(MIPSReg r);118void DiscardR(MIPSReg r);119Arm64Gen::ARM64Reg R(int preg); // Returns a cached register120121void MapRegV(int vreg, int flags = 0);122void LoadToRegV(Arm64Gen::ARM64Reg armReg, int vreg);123void MapInInV(int rt, int rs);124void MapDirtyInV(int rd, int rs, bool avoidLoad = true);125void MapDirtyInInV(int rd, int rs, int rt, bool avoidLoad = true);126127bool IsTempX(Arm64Gen::ARM64Reg r) const;128MIPSReg GetTempV() { return GetTempR() - 32; }129// VFPU registers as single VFP registers.130Arm64Gen::ARM64Reg V(int vreg) { return R(vreg + 32); }131132void FlushAll();133134// This one is allowed at any point.135void FlushV(MIPSReg r);136137// NOTE: These require you to release spill locks manually!138void MapRegsAndSpillLockV(int vec, VectorSize vsz, int flags);139void MapRegsAndSpillLockV(const u8 *v, VectorSize vsz, int flags);140141void SpillLockV(const u8 *v, VectorSize vsz);142void SpillLockV(int vec, VectorSize vsz);143144void SetEmitter(Arm64Gen::ARM64XEmitter *emitter, Arm64Gen::ARM64FloatEmitter *fp) { emit_ = emitter; fp_ = fp; }145146int GetMipsRegOffset(MIPSReg r);147int GetMipsRegOffsetV(MIPSReg r) {148return GetMipsRegOffset(r + 32);149}150151private:152Arm64Gen::ARM64Reg ARM64RegForFlush(int r);153MIPSReg GetTempR();154const Arm64Gen::ARM64Reg *GetMIPSAllocationOrder(int &count);155156void SetupInitialRegs();157158MIPSState *mips_;159Arm64Gen::ARM64XEmitter *emit_;160Arm64Gen::ARM64FloatEmitter *fp_;161MIPSComp::JitState *js_;162MIPSComp::JitOptions *jo_;163164int numARMFpuReg_;165166enum {167// On ARM64, each of the 32 registers are full 128-bit. No sharing of components!168MAX_ARMFPUREG = 32,169NUM_MIPSFPUREG = Arm64JitConstants::TOTAL_MAPPABLE_MIPSFPUREGS,170};171172FPURegARM64 ar[MAX_ARMFPUREG];173FPURegMIPS mr[NUM_MIPSFPUREG];174FPURegMIPS *vr;175176bool pendingFlush;177bool initialReady = false;178FPURegARM64 arInitial[MAX_ARMFPUREG];179FPURegMIPS mrInitial[NUM_MIPSFPUREG];180};181182183