softjit: Add register cache for softjit.

This commit is contained in:
Unknown W. Brackets 2021-11-21 14:13:07 -08:00
parent 91787e63d9
commit 9fed7ea732
3 changed files with 168 additions and 0 deletions

View File

@ -479,6 +479,10 @@ SingleFunc GetSingleFunc(const PixelFuncID &id) {
return jitted;
}
return jitCache->GenericSingle(id);
}
SingleFunc PixelJitCache::GenericSingle(const PixelFuncID &id) {
if (id.clearMode) {
switch (id.fbFormat) {
case GE_FORMAT_565:
@ -568,4 +572,82 @@ SingleFunc PixelJitCache::GetSingle(const PixelFuncID &id) {
#endif
}
void PixelRegCache::Reset() {
regs.clear();
}
void PixelRegCache::Release(PixelRegCache::Reg r, PixelRegCache::Type t) {
for (auto &reg : regs) {
if (reg.reg == r && reg.type == t) {
reg.purpose = INVALID;
reg.locked = false;
return;
}
}
RegStatus newStatus;
newStatus.reg = r;
newStatus.purpose = INVALID;
newStatus.type = t;
regs.push_back(newStatus);
}
void PixelRegCache::Unlock(PixelRegCache::Reg r, PixelRegCache::Type t) {
for (auto &reg : regs) {
if (reg.reg == r && reg.type == t) {
reg.locked = false;
return;
}
}
_assert_msg_(false, "softjit Unlock() reg that isn't there");
}
bool PixelRegCache::Has(PixelRegCache::Purpose p, PixelRegCache::Type t) {
for (auto &reg : regs) {
if (reg.purpose == p && reg.type == t) {
return true;
}
}
return false;
}
PixelRegCache::Reg PixelRegCache::Find(PixelRegCache::Purpose p, PixelRegCache::Type t) {
for (auto &reg : regs) {
if (reg.purpose == p && reg.type == t) {
reg.locked = true;
return reg.reg;
}
}
_assert_msg_(false, "softjit Find() reg that isn't there (%d)", p);
return Reg(-1);
}
PixelRegCache::Reg PixelRegCache::Alloc(PixelRegCache::Purpose p, PixelRegCache::Type t) {
_assert_msg_(!Has(p, t), "softjit Alloc() reg duplicate");
RegStatus *best = nullptr;
for (auto &reg : regs) {
if (reg.locked || reg.type != t)
continue;
if (best == nullptr)
best = ®
// Prefer a free/purposeless reg.
if (reg.purpose == INVALID || reg.purpose >= TEMP0) {
best = ®
break;
}
}
if (best) {
best->locked = true;
best->purpose = p;
return best->reg;
}
_assert_msg_(false, "softjit Alloc() reg with none free (%d)", p);
return Reg();
}
};

View File

@ -20,6 +20,7 @@
#include "ppsspp_config.h"
#include <string>
#include <vector>
#include <unordered_map>
#if PPSSPP_ARCH(ARM)
#include "Common/ArmEmitter.h"
@ -59,6 +60,50 @@ void Shutdown();
bool DescribeCodePtr(const u8 *ptr, std::string &name);
struct PixelRegCache {
enum Purpose {
INVALID,
GSTATE,
CONST_BASE,
ALPHA,
// Above this can only be temps.
TEMP0,
TEMP1,
TEMP2,
TEMP3,
TEMP4,
TEMP5,
};
enum Type {
T_GEN,
T_VEC,
};
#if PPSSPP_ARCH(X86) || PPSSPP_ARCH(AMD64)
typedef Gen::X64Reg Reg;
#else
typedef int Reg;
#endif
struct RegStatus {
Reg reg;
Purpose purpose;
Type type;
bool locked = false;
};
void Reset();
void Release(Reg r, Type t);
void Unlock(Reg r, Type t);
bool Has(Purpose p, Type t);
Reg Find(Purpose p, Type t);
Reg Alloc(Purpose p, Type t);
private:
std::vector<RegStatus> regs;
};
#if PPSSPP_ARCH(ARM)
class PixelJitCache : public ArmGen::ARMXCodeBlock {
#elif PPSSPP_ARCH(ARM64)
@ -75,6 +120,7 @@ public:
// Returns a pointer to the code to run.
SingleFunc GetSingle(const PixelFuncID &id);
SingleFunc GenericSingle(const PixelFuncID &id);
void Clear();
std::string DescribeCodePtr(const u8 *ptr);
@ -86,8 +132,12 @@ private:
Arm64Gen::ARM64FloatEmitter fp;
#endif
PixelRegCache::Reg GetGState();
PixelRegCache::Reg GetConstBase();
std::unordered_map<PixelFuncID, SingleFunc> cache_;
std::unordered_map<PixelFuncID, const u8 *> addresses_;
PixelRegCache regCache_;
};
};

View File

@ -29,7 +29,43 @@ using namespace Gen;
namespace Rasterizer {
#if PPSSPP_PLATFORM(WINDOWS)
static const X64Reg argXReg = RCX;
static const X64Reg argYReg = RDX;
static const X64Reg argZReg = R8;
static const X64Reg argFogReg = R9;
static const X64Reg argColorReg = XMM4;
// Must save: RBX, RSP, RBP, RDI, RSI, R12-R15, XMM6-15
#else
static const X64Reg argXReg = RDI;
static const X64Reg argYReg = RSI;
static const X64Reg argZReg = RDX;
static const X64Reg argFogReg = RCX;
static const X64Reg argColorReg = XMM0;
// Must save: RBX, RSP, RBP, R12-R15
#endif
SingleFunc PixelJitCache::CompileSingle(const PixelFuncID &id) {
// Setup the reg cache.
regCache_.Reset();
regCache_.Release(RAX, PixelRegCache::T_GEN);
regCache_.Release(R10, PixelRegCache::T_GEN);
regCache_.Release(R11, PixelRegCache::T_GEN);
regCache_.Release(XMM1, PixelRegCache::T_VEC);
regCache_.Release(XMM2, PixelRegCache::T_VEC);
regCache_.Release(XMM3, PixelRegCache::T_VEC);
regCache_.Release(XMM5, PixelRegCache::T_VEC);
#if !PPSSPP_PLATFORM(WINDOWS)
regCache_.Release(R8, PixelRegCache::T_GEN);
regCache_.Release(R9, PixelRegCache::T_GEN);
regCache_.Release(XMM4, PixelRegCache::T_VEC);
#else
regCache_.Release(XMM0, PixelRegCache::T_VEC);
#endif
return nullptr;
}