2012-11-01 16:19:01 +01:00
|
|
|
// Copyright (c) 2012- PPSSPP Project.
|
|
|
|
|
|
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
|
// it under the terms of the GNU General Public License as published by
|
2012-11-04 23:01:49 +01:00
|
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
2012-11-01 16:19:01 +01:00
|
|
|
|
|
|
|
|
// This program is distributed in the hope that it will be useful,
|
|
|
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
|
// GNU General Public License 2.0 for more details.
|
|
|
|
|
|
|
|
|
|
// A copy of the GPL 2.0 should have been included with the program.
|
|
|
|
|
// If not, see http://www.gnu.org/licenses/
|
|
|
|
|
|
|
|
|
|
// Official git repository and contact information can be found at
|
|
|
|
|
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
|
|
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
2021-03-02 21:49:21 -08:00
|
|
|
#include "ppsspp_config.h"
|
2013-08-24 15:35:31 -07:00
|
|
|
#include "Common/x64Emitter.h"
|
2013-08-24 19:31:12 -07:00
|
|
|
#include "Core/MIPS/MIPS.h"
|
2013-01-25 22:11:51 +01:00
|
|
|
|
2014-12-13 21:11:36 +01:00
|
|
|
namespace X64JitConstants {
|
2021-03-02 21:49:21 -08:00
|
|
|
#if PPSSPP_ARCH(AMD64)
|
2014-12-17 01:11:33 -08:00
|
|
|
const Gen::X64Reg MEMBASEREG = Gen::RBX;
|
2014-12-13 21:11:36 +01:00
|
|
|
const Gen::X64Reg CTXREG = Gen::R14;
|
2014-12-17 01:11:33 -08:00
|
|
|
const Gen::X64Reg JITBASEREG = Gen::R15;
|
2014-10-12 14:09:35 +02:00
|
|
|
#else
|
2014-12-13 21:11:36 +01:00
|
|
|
const Gen::X64Reg CTXREG = Gen::EBP;
|
2014-10-12 14:09:35 +02:00
|
|
|
#endif
|
|
|
|
|
|
2014-12-13 21:11:36 +01:00
|
|
|
// This must be one of EAX, EBX, ECX, EDX as they have 8-bit subregisters.
|
|
|
|
|
const Gen::X64Reg TEMPREG = Gen::EAX;
|
|
|
|
|
const int NUM_MIPS_GPRS = 36;
|
|
|
|
|
|
2021-03-02 21:49:21 -08:00
|
|
|
#if PPSSPP_ARCH(AMD64)
|
2016-03-20 14:17:51 -07:00
|
|
|
const u32 NUM_X_REGS = 16;
|
2021-03-02 21:49:21 -08:00
|
|
|
#elif PPSSPP_ARCH(X86)
|
2016-03-20 14:17:51 -07:00
|
|
|
const u32 NUM_X_REGS = 8;
|
2014-12-13 21:11:36 +01:00
|
|
|
#endif
|
|
|
|
|
}
|
2014-11-16 17:38:26 +01:00
|
|
|
|
2022-10-27 23:26:44 -07:00
|
|
|
namespace MIPSAnalyst {
|
|
|
|
|
struct AnalysisResults;
|
|
|
|
|
};
|
|
|
|
|
|
2013-01-25 23:09:11 +01:00
|
|
|
struct MIPSCachedReg {
|
2014-12-07 14:44:15 +01:00
|
|
|
Gen::OpArg location;
|
2012-11-01 16:19:01 +01:00
|
|
|
bool away; // value not in source register
|
2013-01-25 22:11:51 +01:00
|
|
|
bool locked;
|
2012-11-01 16:19:01 +01:00
|
|
|
};
|
|
|
|
|
|
2013-01-25 23:09:11 +01:00
|
|
|
struct X64CachedReg {
|
2013-08-24 19:31:12 -07:00
|
|
|
MIPSGPReg mipsReg;
|
2012-11-01 16:19:01 +01:00
|
|
|
bool dirty;
|
|
|
|
|
bool free;
|
2013-01-25 22:11:51 +01:00
|
|
|
bool allocLocked;
|
2012-11-01 16:19:01 +01:00
|
|
|
};
|
|
|
|
|
|
2013-08-15 23:13:40 -07:00
|
|
|
struct GPRRegCacheState {
|
2014-12-13 21:11:36 +01:00
|
|
|
MIPSCachedReg regs[X64JitConstants::NUM_MIPS_GPRS];
|
|
|
|
|
X64CachedReg xregs[X64JitConstants::NUM_X_REGS];
|
2013-08-15 23:13:40 -07:00
|
|
|
};
|
2013-01-25 22:11:51 +01:00
|
|
|
|
2014-12-07 21:07:23 -08:00
|
|
|
namespace MIPSComp {
|
|
|
|
|
struct JitOptions;
|
|
|
|
|
struct JitState;
|
|
|
|
|
}
|
|
|
|
|
|
2013-01-25 22:11:51 +01:00
|
|
|
class GPRRegCache
|
2012-11-01 16:19:01 +01:00
|
|
|
{
|
|
|
|
|
public:
|
2013-01-25 22:11:51 +01:00
|
|
|
GPRRegCache();
|
|
|
|
|
~GPRRegCache() {}
|
2021-02-25 20:20:36 -08:00
|
|
|
void Start(MIPSState *mipsState, MIPSComp::JitState *js, MIPSComp::JitOptions *jo, MIPSAnalyst::AnalysisResults &stats);
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2013-08-24 19:31:12 -07:00
|
|
|
void DiscardRegContentsIfCached(MIPSGPReg preg);
|
2015-03-01 09:58:47 -08:00
|
|
|
void DiscardR(MIPSGPReg preg);
|
2014-12-07 14:44:15 +01:00
|
|
|
void SetEmitter(Gen::XEmitter *emitter) {emit = emitter;}
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2014-12-07 14:44:15 +01:00
|
|
|
void FlushR(Gen::X64Reg reg);
|
|
|
|
|
void FlushLockX(Gen::X64Reg reg) {
|
2012-11-01 16:19:01 +01:00
|
|
|
FlushR(reg);
|
|
|
|
|
LockX(reg);
|
|
|
|
|
}
|
2014-12-07 14:44:15 +01:00
|
|
|
void FlushLockX(Gen::X64Reg reg1, Gen::X64Reg reg2) {
|
2012-11-01 16:19:01 +01:00
|
|
|
FlushR(reg1); FlushR(reg2);
|
|
|
|
|
LockX(reg1); LockX(reg2);
|
|
|
|
|
}
|
2013-01-25 23:09:11 +01:00
|
|
|
void Flush();
|
2013-07-28 22:21:28 +02:00
|
|
|
void FlushBeforeCall();
|
2015-04-12 13:50:23 -07:00
|
|
|
|
|
|
|
|
// Flushes one register and reuses the register for another one. Dirtyness is implied.
|
|
|
|
|
void FlushRemap(MIPSGPReg oldreg, MIPSGPReg newreg);
|
|
|
|
|
|
2012-11-01 16:19:01 +01:00
|
|
|
int SanityCheck() const;
|
2013-08-24 19:31:12 -07:00
|
|
|
void KillImmediate(MIPSGPReg preg, bool doLoad, bool makeDirty);
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2013-11-09 15:23:31 +01:00
|
|
|
void MapReg(MIPSGPReg preg, bool doLoad = true, bool makeDirty = true);
|
2013-08-24 19:31:12 -07:00
|
|
|
void StoreFromRegister(MIPSGPReg preg);
|
2012-11-01 16:19:01 +01:00
|
|
|
|
2014-12-07 14:44:15 +01:00
|
|
|
const Gen::OpArg &R(MIPSGPReg preg) const {return regs[preg].location;}
|
|
|
|
|
Gen::X64Reg RX(MIPSGPReg preg) const
|
2012-11-01 16:19:01 +01:00
|
|
|
{
|
|
|
|
|
if (regs[preg].away && regs[preg].location.IsSimpleReg())
|
|
|
|
|
return regs[preg].location.GetSimpleReg();
|
2020-07-19 19:49:20 +02:00
|
|
|
_assert_msg_(false, "Not so simple - %d", preg);
|
2014-12-07 14:44:15 +01:00
|
|
|
return (Gen::X64Reg)-1;
|
2012-11-01 16:19:01 +01:00
|
|
|
}
|
2014-12-07 14:44:15 +01:00
|
|
|
Gen::OpArg GetDefaultLocation(MIPSGPReg reg) const;
|
2012-11-01 16:19:01 +01:00
|
|
|
|
|
|
|
|
// Register locking.
|
2013-08-24 19:31:12 -07:00
|
|
|
void Lock(MIPSGPReg p1, MIPSGPReg p2 = MIPS_REG_INVALID, MIPSGPReg p3 = MIPS_REG_INVALID, MIPSGPReg p4 = MIPS_REG_INVALID);
|
2012-11-01 16:19:01 +01:00
|
|
|
void LockX(int x1, int x2=0xff, int x3=0xff, int x4=0xff);
|
|
|
|
|
void UnlockAll();
|
|
|
|
|
void UnlockAllX();
|
|
|
|
|
|
2013-11-10 20:55:20 -08:00
|
|
|
void SetImm(MIPSGPReg preg, u32 immValue);
|
|
|
|
|
bool IsImm(MIPSGPReg preg) const;
|
|
|
|
|
u32 GetImm(MIPSGPReg preg) const;
|
2013-01-25 22:11:51 +01:00
|
|
|
|
2013-08-15 23:13:40 -07:00
|
|
|
void GetState(GPRRegCacheState &state) const;
|
2014-12-24 21:42:41 -05:00
|
|
|
void RestoreState(const GPRRegCacheState& state);
|
2013-08-15 23:13:40 -07:00
|
|
|
|
2021-02-25 20:20:36 -08:00
|
|
|
MIPSState *mips_ = nullptr;
|
2013-01-25 22:11:51 +01:00
|
|
|
|
|
|
|
|
private:
|
2014-12-07 14:44:15 +01:00
|
|
|
Gen::X64Reg GetFreeXReg();
|
2014-12-07 23:08:21 -08:00
|
|
|
Gen::X64Reg FindBestToSpill(bool unusedOnly, bool *clobbered);
|
2014-12-17 08:09:59 -08:00
|
|
|
const Gen::X64Reg *GetAllocationOrder(int &count);
|
2013-01-25 22:11:51 +01:00
|
|
|
|
2021-02-25 20:20:36 -08:00
|
|
|
MIPSCachedReg regs[X64JitConstants::NUM_MIPS_GPRS]{};
|
|
|
|
|
X64CachedReg xregs[X64JitConstants::NUM_X_REGS]{};
|
2013-01-25 22:11:51 +01:00
|
|
|
|
2021-02-25 20:20:36 -08:00
|
|
|
Gen::XEmitter *emit = nullptr;
|
2014-12-07 21:07:23 -08:00
|
|
|
MIPSComp::JitState *js_;
|
|
|
|
|
MIPSComp::JitOptions *jo_;
|
2012-11-01 16:19:01 +01:00
|
|
|
};
|