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/X64IRRegCache.h
Views: 1401
// Copyright (c) 2023- 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 "ppsspp_config.h"20#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)2122#include "Common/x64Emitter.h"23#include "Core/MIPS/MIPS.h"24#include "Core/MIPS/IR/IRJit.h"25#include "Core/MIPS/IR/IRRegCache.h"2627namespace X64IRJitConstants {2829#if PPSSPP_ARCH(AMD64)30const Gen::X64Reg MEMBASEREG = Gen::RBX;31const Gen::X64Reg CTXREG = Gen::R14;32// Note: this is actually offset from the base.33const Gen::X64Reg JITBASEREG = Gen::R15;34const Gen::X64Reg DOWNCOUNTREG = Gen::R15;35#else36const Gen::X64Reg CTXREG = Gen::EBP;37const Gen::X64Reg DOWNCOUNTREG = Gen::INVALID_REG;38#endif39const Gen::X64Reg SCRATCH1 = Gen::EAX;4041static constexpr auto downcountOffset = offsetof(MIPSState, downcount) - 128;42static constexpr auto tempOffset = offsetof(MIPSState, temp) - 128;43static constexpr auto fcr31Offset = offsetof(MIPSState, fcr31) - 128;44static constexpr auto pcOffset = offsetof(MIPSState, pc) - 128;45static constexpr auto mxcsrTempOffset = offsetof(MIPSState, mxcsrTemp) - 128;4647enum class X64Map : uint8_t {48NONE = 0,49// On 32-bit: EAX, EBX, ECX, EDX50LOW_SUBREG = 0x10,51// EDX/RDX for DIV/MUL/similar.52HIGH_DATA = 0x20,53// ECX/RCX only, for shifts.54SHIFT = 0x30,55// XMM0 for BLENDVPS, funcs.56XMM0 = 0x40,57MASK = 0xF0,58};59static inline MIPSMap operator |(const MIPSMap &lhs, const X64Map &rhs) {60return MIPSMap((uint8_t)lhs | (uint8_t)rhs);61}62static inline X64Map operator |(const X64Map &lhs, const X64Map &rhs) {63return X64Map((uint8_t)lhs | (uint8_t)rhs);64}65static inline X64Map operator &(const MIPSMap &lhs, const X64Map &rhs) {66return X64Map((uint8_t)lhs & (uint8_t)rhs);67}68static inline X64Map operator &(const X64Map &lhs, const X64Map &rhs) {69return X64Map((uint8_t)lhs & (uint8_t)rhs);70}7172} // namespace X64IRJitConstants7374class X64IRRegCache : public IRNativeRegCacheBase {75public:76X64IRRegCache(MIPSComp::JitOptions *jo);7778void Init(Gen::XEmitter *emitter);7980// May fail and return INVALID_REG if it needs flushing.81Gen::X64Reg TryMapTempImm(IRReg reg, X64IRJitConstants::X64Map flags = X64IRJitConstants::X64Map::NONE);8283// Returns an X64 register containing the requested MIPS register.84Gen::X64Reg MapGPR(IRReg reg, MIPSMap mapFlags = MIPSMap::INIT);85Gen::X64Reg MapGPR2(IRReg reg, MIPSMap mapFlags = MIPSMap::INIT);86Gen::X64Reg MapGPRAsPointer(IRReg reg);87Gen::X64Reg MapFPR(IRReg reg, MIPSMap mapFlags = MIPSMap::INIT);88Gen::X64Reg MapVec4(IRReg first, MIPSMap mapFlags = MIPSMap::INIT);8990Gen::X64Reg MapWithFPRTemp(const IRInst &inst);9192void MapWithFlags(IRInst inst, X64IRJitConstants::X64Map destFlags, X64IRJitConstants::X64Map src1Flags = X64IRJitConstants::X64Map::NONE, X64IRJitConstants::X64Map src2Flags = X64IRJitConstants::X64Map::NONE);9394// Note: may change the high lanes of single-register XMMs.95void FlushAll(bool gprs = true, bool fprs = true) override;96void FlushBeforeCall();9798Gen::X64Reg GetAndLockTempGPR();99Gen::X64Reg GetAndLockTempFPR();100void ReserveAndLockXGPR(Gen::X64Reg r);101102Gen::OpArg R(IRReg preg);103Gen::OpArg RPtr(IRReg preg);104Gen::OpArg F(IRReg preg);105Gen::X64Reg RX(IRReg preg); // Returns a cached register, while checking that it's NOT mapped as a pointer106Gen::X64Reg RXPtr(IRReg preg); // Returns a cached register, if it has been mapped as a pointer107Gen::X64Reg FX(IRReg preg);108109static bool HasLowSubregister(Gen::X64Reg reg);110111protected:112const int *GetAllocationOrder(MIPSLoc type, MIPSMap flags, int &count, int &base) const override;113void AdjustNativeRegAsPtr(IRNativeReg nreg, bool state) override;114115void LoadNativeReg(IRNativeReg nreg, IRReg first, int lanes) override;116void StoreNativeReg(IRNativeReg nreg, IRReg first, int lanes) override;117void SetNativeRegValue(IRNativeReg nreg, uint32_t imm) override;118void StoreRegValue(IRReg mreg, uint32_t imm) override;119bool TransferNativeReg(IRNativeReg nreg, IRNativeReg dest, MIPSLoc type, IRReg first, int lanes, MIPSMap flags) override;120121private:122bool TransferVecTo1(IRNativeReg nreg, IRNativeReg dest, IRReg first, int oldlanes);123bool Transfer1ToVec(IRNativeReg nreg, IRNativeReg dest, IRReg first, int lanes);124125IRNativeReg GPRToNativeReg(Gen::X64Reg r) {126return (IRNativeReg)r;127}128IRNativeReg XMMToNativeReg(Gen::X64Reg r) {129return (IRNativeReg)(r + NUM_X_REGS);130}131Gen::X64Reg FromNativeReg(IRNativeReg r) {132if (r >= NUM_X_REGS)133return (Gen::X64Reg)(Gen::XMM0 + (r - NUM_X_REGS));134return (Gen::X64Reg)(Gen::RAX + r);135}136137Gen::XEmitter *emit_ = nullptr;138139enum {140#if PPSSPP_ARCH(AMD64)141NUM_X_REGS = 16,142NUM_X_FREGS = 16,143#elif PPSSPP_ARCH(X86)144NUM_X_REGS = 8,145NUM_X_FREGS = 8,146#endif147};148};149150#endif151152153