2023-08-15 21:51:38 -07:00
|
|
|
// Copyright (c) 2023- 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
|
|
|
|
// the Free Software Foundation, version 2.0 or later versions.
|
|
|
|
|
|
|
|
// 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/.
|
|
|
|
|
|
|
|
#ifndef offsetof
|
|
|
|
#include <cstddef>
|
|
|
|
#endif
|
|
|
|
|
2016-05-08 14:06:42 -07:00
|
|
|
#include <cstring>
|
2023-08-06 08:36:19 -07:00
|
|
|
#include "Common/Log.h"
|
2016-05-06 23:45:37 +02:00
|
|
|
#include "Core/MIPS/IR/IRRegCache.h"
|
|
|
|
#include "Core/MIPS/IR/IRInst.h"
|
2023-08-15 21:51:38 -07:00
|
|
|
#include "Core/MIPS/IR/IRJit.h"
|
|
|
|
#include "Core/MIPS/JitCommon/JitState.h"
|
2016-05-06 23:45:37 +02:00
|
|
|
|
2023-08-06 18:33:34 -07:00
|
|
|
void IRImmRegCache::Flush(IRReg rd) {
|
2016-05-06 23:45:37 +02:00
|
|
|
if (rd == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (reg_[rd].isImm) {
|
2023-08-06 08:36:19 -07:00
|
|
|
_assert_((rd > 0 && rd < 32) || (rd >= IRTEMP_0 && rd < IRREG_VFPU_CTRL_BASE));
|
2016-05-06 23:45:37 +02:00
|
|
|
ir_->WriteSetConstant(rd, reg_[rd].immVal);
|
|
|
|
reg_[rd].isImm = false;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-08-06 18:33:34 -07:00
|
|
|
void IRImmRegCache::Discard(IRReg rd) {
|
2016-05-08 01:06:07 +02:00
|
|
|
if (rd == 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
reg_[rd].isImm = false;
|
2016-05-06 23:45:37 +02:00
|
|
|
}
|
|
|
|
|
2023-08-06 18:33:34 -07:00
|
|
|
IRImmRegCache::IRImmRegCache(IRWriter *ir) : ir_(ir) {
|
2016-05-08 01:06:07 +02:00
|
|
|
memset(®_, 0, sizeof(reg_));
|
|
|
|
reg_[0].isImm = true;
|
|
|
|
ir_ = ir;
|
2016-05-06 23:45:37 +02:00
|
|
|
}
|
|
|
|
|
2023-08-06 18:33:34 -07:00
|
|
|
void IRImmRegCache::FlushAll() {
|
2023-08-15 21:51:38 -07:00
|
|
|
for (int i = 0; i < TOTAL_MAPPABLE_IRREGS; i++) {
|
2022-07-24 10:37:54 -07:00
|
|
|
Flush(i);
|
2016-05-08 01:06:07 +02:00
|
|
|
}
|
2016-05-06 23:45:37 +02:00
|
|
|
}
|
|
|
|
|
2023-08-06 18:33:34 -07:00
|
|
|
void IRImmRegCache::MapIn(IRReg rd) {
|
2016-05-08 10:36:37 +02:00
|
|
|
Flush(rd);
|
|
|
|
}
|
|
|
|
|
2023-08-06 18:33:34 -07:00
|
|
|
void IRImmRegCache::MapDirty(IRReg rd) {
|
2016-05-08 10:36:37 +02:00
|
|
|
Discard(rd);
|
|
|
|
}
|
|
|
|
|
2023-08-06 18:33:34 -07:00
|
|
|
void IRImmRegCache::MapInIn(IRReg rs, IRReg rt) {
|
2016-05-08 01:06:07 +02:00
|
|
|
Flush(rs);
|
|
|
|
Flush(rt);
|
2016-05-06 23:45:37 +02:00
|
|
|
}
|
|
|
|
|
2023-08-06 18:33:34 -07:00
|
|
|
void IRImmRegCache::MapInInIn(IRReg rd, IRReg rs, IRReg rt) {
|
2016-05-08 22:54:07 +02:00
|
|
|
Flush(rd);
|
|
|
|
Flush(rs);
|
|
|
|
Flush(rt);
|
|
|
|
}
|
|
|
|
|
2023-08-06 18:33:34 -07:00
|
|
|
void IRImmRegCache::MapDirtyIn(IRReg rd, IRReg rs) {
|
2016-05-08 01:06:07 +02:00
|
|
|
if (rs != rd) {
|
|
|
|
Discard(rd);
|
|
|
|
}
|
|
|
|
Flush(rs);
|
2016-05-06 23:45:37 +02:00
|
|
|
}
|
|
|
|
|
2023-08-06 18:33:34 -07:00
|
|
|
void IRImmRegCache::MapDirtyInIn(IRReg rd, IRReg rs, IRReg rt) {
|
2016-05-08 01:06:07 +02:00
|
|
|
if (rs != rd && rt != rd) {
|
|
|
|
Discard(rd);
|
2016-05-07 17:37:19 +02:00
|
|
|
}
|
2016-05-08 01:06:07 +02:00
|
|
|
Flush(rs);
|
|
|
|
Flush(rt);
|
2016-05-06 23:45:37 +02:00
|
|
|
}
|
2016-05-08 01:06:07 +02:00
|
|
|
|
2023-08-15 21:51:38 -07:00
|
|
|
IRNativeRegCache::IRNativeRegCache(MIPSComp::JitOptions *jo)
|
|
|
|
: jo_(jo) {}
|
|
|
|
|
|
|
|
void IRNativeRegCache::Start(MIPSComp::IRBlock *irBlock) {
|
|
|
|
if (!initialReady_) {
|
|
|
|
SetupInitialRegs();
|
|
|
|
initialReady_ = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
memcpy(nr, nrInitial_, sizeof(nr[0]) * totalNativeRegs_);
|
|
|
|
memcpy(mr, mrInitial_, sizeof(mr));
|
|
|
|
pendingFlush_ = false;
|
|
|
|
|
|
|
|
int numStatics;
|
|
|
|
const StaticAllocation *statics = GetStaticAllocations(numStatics);
|
|
|
|
for (int i = 0; i < numStatics; i++) {
|
|
|
|
nr[statics[i].nr].mipsReg = statics[i].mr;
|
|
|
|
nr[statics[i].nr].pointerified = statics[i].pointerified && jo_->enablePointerify;
|
|
|
|
nr[statics[i].nr].normalized32 = statics[i].normalized32;
|
|
|
|
mr[statics[i].mr].loc = MIPSLoc::REG;
|
|
|
|
mr[statics[i].mr].nReg = statics[i].nr;
|
|
|
|
mr[statics[i].mr].isStatic = true;
|
|
|
|
// Lock it until the very end.
|
|
|
|
mr[statics[i].mr].spillLockIRIndex = irBlock->GetNumInstructions();
|
|
|
|
}
|
|
|
|
|
|
|
|
irBlock_ = irBlock;
|
|
|
|
irIndex_ = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void IRNativeRegCache::SetupInitialRegs() {
|
|
|
|
_assert_msg_(totalNativeRegs_ > 0, "totalNativeRegs_ was never set by backend");
|
|
|
|
|
|
|
|
// Everything else is initialized in the struct.
|
|
|
|
mrInitial_[MIPS_REG_ZERO].loc = MIPSLoc::IMM;
|
|
|
|
mrInitial_[MIPS_REG_ZERO].imm = 0;
|
|
|
|
}
|