mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-24 16:49:50 +00:00
Use the regcache in a new (incomplete) pass, PropagateConstants.
This commit is contained in:
parent
a33f8b68c6
commit
09969c0156
@ -61,12 +61,7 @@ void IRJit::Comp_IType(MIPSOpcode op) {
|
|||||||
switch (op >> 26) {
|
switch (op >> 26) {
|
||||||
case 8: // same as addiu?
|
case 8: // same as addiu?
|
||||||
case 9: // R(rt) = R(rs) + simm; break; //addiu
|
case 9: // R(rt) = R(rs) + simm; break; //addiu
|
||||||
// Special-case for small adjustments of pointerified registers. Commonly for SP but happens for others.
|
ir.Write(IROp::AddConst, rt, rs, ir.AddConstant(simm));
|
||||||
if (simm >= 0) {
|
|
||||||
ir.Write(IROp::AddConst, rt, rs, ir.AddConstant(simm));
|
|
||||||
} else if (simm < 0) {
|
|
||||||
ir.Write(IROp::SubConst, rt, rs, ir.AddConstant(-simm));
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 12: ir.Write(IROp::AndConst, rt, rs, ir.AddConstant(uimm)); break;
|
case 12: ir.Write(IROp::AndConst, rt, rs, ir.AddConstant(uimm)); break;
|
||||||
|
@ -121,6 +121,7 @@ void IRJit::Comp_FPUComp(MIPSOpcode op) {
|
|||||||
|
|
||||||
void IRJit::Comp_FPU2op(MIPSOpcode op) {
|
void IRJit::Comp_FPU2op(MIPSOpcode op) {
|
||||||
CONDITIONAL_DISABLE;
|
CONDITIONAL_DISABLE;
|
||||||
|
|
||||||
int fs = _FS;
|
int fs = _FS;
|
||||||
int fd = _FD;
|
int fd = _FD;
|
||||||
|
|
||||||
|
@ -9,7 +9,7 @@
|
|||||||
#include "math/math_util.h"
|
#include "math/math_util.h"
|
||||||
|
|
||||||
static const IRMeta irMeta[] = {
|
static const IRMeta irMeta[] = {
|
||||||
{ IROp::SetConst, "SetConst", "GC_" },
|
{ IROp::SetConst, "SetConst", "GC" },
|
||||||
{ IROp::Mov, "Mov", "GG" },
|
{ IROp::Mov, "Mov", "GG" },
|
||||||
{ IROp::Add, "Add", "GGG" },
|
{ IROp::Add, "Add", "GGG" },
|
||||||
{ IROp::Sub, "Sub", "GGG" },
|
{ IROp::Sub, "Sub", "GGG" },
|
||||||
@ -81,7 +81,7 @@ static const IRMeta irMeta[] = {
|
|||||||
{ IROp::FMovFromGPR, "FMovFromGPR", "FG" },
|
{ IROp::FMovFromGPR, "FMovFromGPR", "FG" },
|
||||||
{ IROp::FMovToGPR, "FMovToGPR", "GF" },
|
{ IROp::FMovToGPR, "FMovToGPR", "GF" },
|
||||||
{ IROp::FpCondToReg, "FpCondToReg", "G" },
|
{ IROp::FpCondToReg, "FpCondToReg", "G" },
|
||||||
{ IROp::SetCtrlVFPU, "SetCtrlVFPU", "T" },
|
{ IROp::SetCtrlVFPU, "SetCtrlVFPU", "TC" },
|
||||||
{ IROp::Interpret, "Interpret", "_C" },
|
{ IROp::Interpret, "Interpret", "_C" },
|
||||||
{ IROp::Downcount, "Downcount", "_II" },
|
{ IROp::Downcount, "Downcount", "_II" },
|
||||||
{ IROp::ExitToConst, "Exit", "C" },
|
{ IROp::ExitToConst, "Exit", "C" },
|
||||||
@ -94,7 +94,9 @@ static const IRMeta irMeta[] = {
|
|||||||
{ IROp::ExitToReg, "ExitToReg", "G" },
|
{ IROp::ExitToReg, "ExitToReg", "G" },
|
||||||
{ IROp::Syscall, "Syscall", "_C" },
|
{ IROp::Syscall, "Syscall", "_C" },
|
||||||
{ IROp::Break, "Break", ""},
|
{ IROp::Break, "Break", ""},
|
||||||
{ IROp::SetPC, "SetPC", "_G"},
|
{ IROp::SetPC, "SetPC", "_G" },
|
||||||
|
{ IROp::SetPCConst, "SetPC", "_C" },
|
||||||
|
{ IROp::CallReplacement, "CallRepl", "_C"},
|
||||||
};
|
};
|
||||||
|
|
||||||
const IRMeta *metaIndex[256];
|
const IRMeta *metaIndex[256];
|
||||||
@ -454,6 +456,10 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, const u32 *constPool, int c
|
|||||||
Crash();
|
Crash();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case IROp::SetCtrlVFPU:
|
||||||
|
mips->vfpuCtrl[inst->dest] = constPool[inst->src1];
|
||||||
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
Crash();
|
Crash();
|
||||||
}
|
}
|
||||||
@ -498,7 +504,7 @@ int IRWriter::AddConstantFloat(float value) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IRWriter::Simplify() {
|
void IRWriter::Simplify() {
|
||||||
SimplifyInPlace(&insts_[0], insts_.size(), constPool_.data());
|
SimplifyInPlace(&insts_[0], (int)insts_.size(), constPool_.data());
|
||||||
}
|
}
|
||||||
|
|
||||||
const char *GetGPRName(int r) {
|
const char *GetGPRName(int r) {
|
||||||
@ -536,8 +542,12 @@ void DisassembleParam(char *buf, int bufSize, u8 param, char type, const u32 *co
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const IRMeta *GetIRMeta(IROp op) {
|
||||||
|
return metaIndex[(int)op];
|
||||||
|
}
|
||||||
|
|
||||||
void DisassembleIR(char *buf, size_t bufsize, IRInst inst, const u32 *constPool) {
|
void DisassembleIR(char *buf, size_t bufsize, IRInst inst, const u32 *constPool) {
|
||||||
const IRMeta *meta = metaIndex[(int)inst.op];
|
const IRMeta *meta = GetIRMeta(inst.op);
|
||||||
if (!meta) {
|
if (!meta) {
|
||||||
snprintf(buf, bufsize, "Unknown %d", (int)inst.op);
|
snprintf(buf, bufsize, "Unknown %d", (int)inst.op);
|
||||||
return;
|
return;
|
||||||
|
@ -249,6 +249,9 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, const u32 *constPool, int c
|
|||||||
class IRWriter {
|
class IRWriter {
|
||||||
public:
|
public:
|
||||||
void Write(IROp op, u8 dst = 0, u8 src1 = 0, u8 src2 = 0);
|
void Write(IROp op, u8 dst = 0, u8 src1 = 0, u8 src2 = 0);
|
||||||
|
void Write(IRInst inst) {
|
||||||
|
insts_.push_back(inst);
|
||||||
|
}
|
||||||
void WriteSetConstant(u8 dst, u32 value);
|
void WriteSetConstant(u8 dst, u32 value);
|
||||||
|
|
||||||
int AddConstant(u32 value);
|
int AddConstant(u32 value);
|
||||||
@ -261,13 +264,14 @@ public:
|
|||||||
|
|
||||||
void Simplify();
|
void Simplify();
|
||||||
|
|
||||||
const std::vector<IRInst> &GetInstructions() { return insts_; }
|
const std::vector<IRInst> &GetInstructions() const { return insts_; }
|
||||||
const std::vector<u32> &GetConstants() { return constPool_; }
|
const std::vector<u32> &GetConstants() const { return constPool_; }
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::vector<IRInst> insts_;
|
std::vector<IRInst> insts_;
|
||||||
std::vector<u32> constPool_;
|
std::vector<u32> constPool_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const IRMeta *GetIRMeta(IROp op);
|
||||||
void DisassembleIR(char *buf, size_t bufsize, IRInst inst, const u32 *constPool);
|
void DisassembleIR(char *buf, size_t bufsize, IRInst inst, const u32 *constPool);
|
||||||
void InitIR();
|
void InitIR();
|
||||||
|
@ -36,6 +36,7 @@
|
|||||||
#include "Core/HLE/sceKernelMemory.h"
|
#include "Core/HLE/sceKernelMemory.h"
|
||||||
#include "Core/MIPS/IR/IRRegCache.h"
|
#include "Core/MIPS/IR/IRRegCache.h"
|
||||||
#include "Core/MIPS/IR/IRJit.h"
|
#include "Core/MIPS/IR/IRJit.h"
|
||||||
|
#include "Core/MIPS/IR/IRPassSimplify.h"
|
||||||
#include "Core/MIPS/JitCommon/JitCommon.h"
|
#include "Core/MIPS/JitCommon/JitCommon.h"
|
||||||
|
|
||||||
namespace MIPSComp
|
namespace MIPSComp
|
||||||
@ -44,11 +45,11 @@ namespace MIPSComp
|
|||||||
IRJit::IRJit(MIPSState *mips) : mips_(mips) {
|
IRJit::IRJit(MIPSState *mips) : mips_(mips) {
|
||||||
logBlocks = 0;
|
logBlocks = 0;
|
||||||
dontLogBlocks = 0;
|
dontLogBlocks = 0;
|
||||||
js.startDefaultPrefix = true;
|
js.startDefaultPrefix = mips_->HasDefaultPrefix();
|
||||||
js.currentRoundingFunc = convertS0ToSCRATCH1[0];
|
js.currentRoundingFunc = convertS0ToSCRATCH1[0];
|
||||||
u32 size = 128 * 1024;
|
u32 size = 128 * 1024;
|
||||||
blTrampolines_ = kernelMemory.Alloc(size, true, "trampoline");
|
blTrampolines_ = kernelMemory.Alloc(size, true, "trampoline");
|
||||||
logBlocks = 100;
|
logBlocks = 12;
|
||||||
InitIR();
|
InitIR();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -88,8 +89,7 @@ void IRJit::DoDummyState(PointerWrap &p) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void IRJit::FlushAll() {
|
void IRJit::FlushAll() {
|
||||||
// gpr.FlushAll();
|
FlushPrefixV();
|
||||||
// FlushPrefixV();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRJit::FlushPrefixV() {
|
void IRJit::FlushPrefixV() {
|
||||||
@ -259,7 +259,15 @@ void IRJit::DoJit(u32 em_address, IRBlock *b) {
|
|||||||
|
|
||||||
ir.Simplify();
|
ir.Simplify();
|
||||||
|
|
||||||
b->SetInstructions(ir.GetInstructions(), ir.GetConstants());
|
IRWriter simplified;
|
||||||
|
|
||||||
|
IRWriter *code = &ir;
|
||||||
|
if (true) {
|
||||||
|
PropagateConstants(ir, simplified);
|
||||||
|
code = &simplified;
|
||||||
|
}
|
||||||
|
|
||||||
|
b->SetInstructions(code->GetInstructions(), code->GetConstants());
|
||||||
|
|
||||||
if (logBlocks > 0 && dontLogBlocks == 0) {
|
if (logBlocks > 0 && dontLogBlocks == 0) {
|
||||||
char temp2[256];
|
char temp2[256];
|
||||||
@ -272,7 +280,7 @@ void IRJit::DoJit(u32 em_address, IRBlock *b) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (logBlocks > 0 && dontLogBlocks == 0) {
|
if (logBlocks > 0 && dontLogBlocks == 0) {
|
||||||
ILOG("=============== IR (%d instructions) ===============", js.numInstructions);
|
ILOG("=============== Original IR (%d instructions) ===============", (int)ir.GetInstructions().size());
|
||||||
for (int i = 0; i < ir.GetInstructions().size(); i++) {
|
for (int i = 0; i < ir.GetInstructions().size(); i++) {
|
||||||
char buf[256];
|
char buf[256];
|
||||||
DisassembleIR(buf, sizeof(buf), ir.GetInstructions()[i], ir.GetConstants().data());
|
DisassembleIR(buf, sizeof(buf), ir.GetInstructions()[i], ir.GetConstants().data());
|
||||||
@ -281,6 +289,16 @@ void IRJit::DoJit(u32 em_address, IRBlock *b) {
|
|||||||
ILOG("=============== end =================");
|
ILOG("=============== end =================");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (logBlocks > 0 && dontLogBlocks == 0) {
|
||||||
|
ILOG("=============== IR (%d instructions) ===============", (int)code->GetInstructions().size());
|
||||||
|
for (int i = 0; i < code->GetInstructions().size(); i++) {
|
||||||
|
char buf[256];
|
||||||
|
DisassembleIR(buf, sizeof(buf), code->GetInstructions()[i], code->GetConstants().data());
|
||||||
|
ILOG("%s", buf);
|
||||||
|
}
|
||||||
|
ILOG("=============== end =================");
|
||||||
|
}
|
||||||
|
|
||||||
if (logBlocks > 0)
|
if (logBlocks > 0)
|
||||||
logBlocks--;
|
logBlocks--;
|
||||||
if (dontLogBlocks > 0)
|
if (dontLogBlocks > 0)
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
#include "Core/MIPS/IR/IRPassSimplify.h"
|
#include "Core/MIPS/IR/IRPassSimplify.h"
|
||||||
|
#include "Core/MIPS/IR/IRRegCache.h"
|
||||||
|
|
||||||
void SimplifyInPlace(IRInst *inst, int count, const u32 *constPool) {
|
void SimplifyInPlace(IRInst *inst, int count, const u32 *constPool) {
|
||||||
for (int i = 0; i < count; i++) {
|
for (int i = 0; i < count; i++) {
|
||||||
@ -15,4 +16,143 @@ void SimplifyInPlace(IRInst *inst, int count, const u32 *constPool) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
u32 Evaluate(u32 a, u32 b, IROp op) {
|
||||||
|
switch (op) {
|
||||||
|
case IROp::Add: case IROp::AddConst: return a + b;
|
||||||
|
case IROp::Sub: case IROp::SubConst: return a - b;
|
||||||
|
case IROp::And: case IROp::AndConst: return a & b;
|
||||||
|
case IROp::Or: case IROp::OrConst: return a | b;
|
||||||
|
case IROp::Xor: case IROp::XorConst: return a ^ b;
|
||||||
|
default:
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IROp ArithToArithConst(IROp op) {
|
||||||
|
switch (op) {
|
||||||
|
case IROp::Add: return IROp::AddConst;
|
||||||
|
case IROp::Sub: return IROp::SubConst;
|
||||||
|
case IROp::And: return IROp::AndConst;
|
||||||
|
case IROp::Or: return IROp::OrConst;
|
||||||
|
case IROp::Xor: return IROp::XorConst;
|
||||||
|
default:
|
||||||
|
return (IROp)-1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void PropagateConstants(const IRWriter &in, IRWriter &out) {
|
||||||
|
IRRegCache gpr(&out);
|
||||||
|
|
||||||
|
const u32 *constants = in.GetConstants().data();
|
||||||
|
for (int i = 0; i < (int)in.GetInstructions().size(); i++) {
|
||||||
|
IRInst inst = in.GetInstructions()[i];
|
||||||
|
bool symmetric = true;
|
||||||
|
switch (inst.op) {
|
||||||
|
case IROp::SetConst:
|
||||||
|
gpr.SetImm((MIPSGPReg)inst.dest, constants[inst.src1]);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IROp::Sub:
|
||||||
|
symmetric = false; // fallthrough
|
||||||
|
case IROp::Add:
|
||||||
|
case IROp::And:
|
||||||
|
case IROp::Or:
|
||||||
|
case IROp::Xor:
|
||||||
|
if (gpr.IsImm(inst.src1) && gpr.IsImm(inst.src2)) {
|
||||||
|
gpr.SetImm(inst.dest, Evaluate(gpr.GetImm(inst.src1), gpr.GetImm(inst.src2), inst.op));
|
||||||
|
} else if (gpr.IsImm(inst.src2) && inst.src1 != inst.src2 && inst.dest != inst.src2) {
|
||||||
|
gpr.MapDirtyIn(inst.dest, inst.src1);
|
||||||
|
if (gpr.GetImm(inst.src2) == 0 && (inst.op == IROp::Add || inst.op == IROp::Or)) {
|
||||||
|
out.Write(IROp::Mov, inst.dest, inst.src1);
|
||||||
|
} else {
|
||||||
|
out.Write(ArithToArithConst(inst.op), inst.dest, inst.src1, out.AddConstant(gpr.GetImm(inst.src2)));
|
||||||
|
}
|
||||||
|
} else if (gpr.IsImm(inst.src1) && inst.src1 != inst.src2 && inst.dest != inst.src2 && symmetric) {
|
||||||
|
gpr.MapDirtyIn(inst.dest, inst.src2);
|
||||||
|
out.Write(ArithToArithConst(inst.op), inst.dest, inst.src2, out.AddConstant(gpr.GetImm(inst.src1)));
|
||||||
|
} else {
|
||||||
|
gpr.MapDirtyInIn(inst.dest, inst.src1, inst.src2);
|
||||||
|
goto doDefault;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IROp::AddConst:
|
||||||
|
case IROp::SubConst:
|
||||||
|
case IROp::AndConst:
|
||||||
|
case IROp::OrConst:
|
||||||
|
case IROp::XorConst:
|
||||||
|
if (gpr.IsImm(inst.src1)) {
|
||||||
|
gpr.SetImm(inst.dest, Evaluate(gpr.GetImm(inst.src1), constants[inst.src2], inst.op));
|
||||||
|
} else {
|
||||||
|
gpr.MapDirtyIn(inst.dest, inst.src1);
|
||||||
|
goto doDefault;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IROp::Mov:
|
||||||
|
if (inst.src1 == inst.src2) {
|
||||||
|
// Nop
|
||||||
|
} else if (gpr.IsImm(inst.src1)) {
|
||||||
|
gpr.SetImm(inst.dest, gpr.GetImm(inst.src1));
|
||||||
|
} else {
|
||||||
|
gpr.MapDirtyIn(inst.dest, inst.src1);
|
||||||
|
goto doDefault;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case IROp::Store8:
|
||||||
|
case IROp::Store16:
|
||||||
|
case IROp::Store32:
|
||||||
|
// Just pass through, no excessive flushing
|
||||||
|
gpr.MapInIn(inst.dest, inst.src1);
|
||||||
|
goto doDefault;
|
||||||
|
|
||||||
|
case IROp::Load8:
|
||||||
|
case IROp::Load8Ext:
|
||||||
|
case IROp::Load16:
|
||||||
|
case IROp::Load16Ext:
|
||||||
|
case IROp::Load32:
|
||||||
|
gpr.MapDirtyIn(inst.dest, inst.src1);
|
||||||
|
goto doDefault;
|
||||||
|
|
||||||
|
case IROp::ExitToConst:
|
||||||
|
case IROp::ExitToReg:
|
||||||
|
case IROp::ExitToConstIfEq:
|
||||||
|
case IROp::ExitToConstIfNeq:
|
||||||
|
case IROp::ExitToConstIfFpFalse:
|
||||||
|
case IROp::ExitToConstIfFpTrue:
|
||||||
|
case IROp::ExitToConstIfGeZ:
|
||||||
|
case IROp::ExitToConstIfGtZ:
|
||||||
|
case IROp::ExitToConstIfLeZ:
|
||||||
|
case IROp::ExitToConstIfLtZ:
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
gpr.FlushAll();
|
||||||
|
doDefault:
|
||||||
|
// Remap constants to the new reality
|
||||||
|
const IRMeta *m = GetIRMeta(inst.op);
|
||||||
|
switch (m->types[0]) {
|
||||||
|
case 'C':
|
||||||
|
inst.dest = out.AddConstant(constants[inst.dest]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (m->types[1]) {
|
||||||
|
case 'C':
|
||||||
|
inst.src1 = out.AddConstant(constants[inst.src1]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
switch (m->types[2]) {
|
||||||
|
case 'C':
|
||||||
|
inst.src2 = out.AddConstant(constants[inst.src2]);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
out.Write(inst);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -4,3 +4,6 @@
|
|||||||
|
|
||||||
// Dumb example of a simplification pass that can't add or remove instructions.
|
// Dumb example of a simplification pass that can't add or remove instructions.
|
||||||
void SimplifyInPlace(IRInst *inst, int count, const u32 *constPool);
|
void SimplifyInPlace(IRInst *inst, int count, const u32 *constPool);
|
||||||
|
|
||||||
|
|
||||||
|
void PropagateConstants(const IRWriter &in, IRWriter &out);
|
@ -1,7 +1,7 @@
|
|||||||
#include "Core/MIPS/IR/IRRegCache.h"
|
#include "Core/MIPS/IR/IRRegCache.h"
|
||||||
#include "Core/MIPS/IR/IRInst.h"
|
#include "Core/MIPS/IR/IRInst.h"
|
||||||
|
|
||||||
void IRRegCache::Dirty(MIPSGPReg rd) {
|
void IRRegCache::Flush(int rd) {
|
||||||
if (rd == 0) {
|
if (rd == 0) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -11,31 +11,14 @@ void IRRegCache::Dirty(MIPSGPReg rd) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRRegCache::MapIn(MIPSGPReg rd) {
|
void IRRegCache::Discard(int rd) {
|
||||||
Dirty(rd);
|
if (rd == 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
reg_[rd].isImm = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void IRRegCache::MapInIn(MIPSGPReg rs, MIPSGPReg rt) {
|
IRRegCache::IRRegCache(IRWriter *ir) : ir_(ir) {
|
||||||
Dirty(rs);
|
|
||||||
Dirty(rt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRRegCache::MapDirty(MIPSGPReg rd) {
|
|
||||||
Dirty(rd);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRRegCache::MapDirtyIn(MIPSGPReg rd, MIPSGPReg rs) {
|
|
||||||
Dirty(rd);
|
|
||||||
Dirty(rs);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRRegCache::MapDirtyInIn(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt) {
|
|
||||||
Dirty(rd);
|
|
||||||
Dirty(rs);
|
|
||||||
Dirty(rt);
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRRegCache::Start(IRWriter *ir) {
|
|
||||||
memset(®_, 0, sizeof(reg_));
|
memset(®_, 0, sizeof(reg_));
|
||||||
reg_[0].isImm = true;
|
reg_[0].isImm = true;
|
||||||
ir_ = ir;
|
ir_ = ir;
|
||||||
@ -43,6 +26,27 @@ void IRRegCache::Start(IRWriter *ir) {
|
|||||||
|
|
||||||
void IRRegCache::FlushAll() {
|
void IRRegCache::FlushAll() {
|
||||||
for (int i = 0; i < TOTAL_MAPPABLE_MIPSREGS; i++) {
|
for (int i = 0; i < TOTAL_MAPPABLE_MIPSREGS; i++) {
|
||||||
Dirty((MIPSGPReg)i);
|
Flush(i);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void IRRegCache::MapInIn(int rs, int rt) {
|
||||||
|
Flush(rs);
|
||||||
|
Flush(rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRRegCache::MapDirtyIn(int rd, int rs) {
|
||||||
|
if (rs != rd) {
|
||||||
|
Discard(rd);
|
||||||
|
}
|
||||||
|
Flush(rs);
|
||||||
|
}
|
||||||
|
|
||||||
|
void IRRegCache::MapDirtyInIn(int rd, int rs, int rt) {
|
||||||
|
if (rs != rd && rt != rd) {
|
||||||
|
Discard(rd);
|
||||||
|
}
|
||||||
|
Flush(rs);
|
||||||
|
Flush(rt);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ -17,27 +17,28 @@ struct RegIR {
|
|||||||
|
|
||||||
class IRWriter;
|
class IRWriter;
|
||||||
|
|
||||||
|
// Transient
|
||||||
class IRRegCache {
|
class IRRegCache {
|
||||||
public:
|
public:
|
||||||
void SetImm(MIPSGPReg r, u32 immVal) {
|
IRRegCache(IRWriter *ir);
|
||||||
|
|
||||||
|
void SetImm(int r, u32 immVal) {
|
||||||
reg_[r].isImm = true;
|
reg_[r].isImm = true;
|
||||||
reg_[r].immVal = immVal;
|
reg_[r].immVal = immVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsImm(MIPSGPReg r) const { return reg_[r].isImm; }
|
bool IsImm(int r) const { return reg_[r].isImm; }
|
||||||
u32 GetImm(MIPSGPReg r) const { return reg_[r].immVal; }
|
u32 GetImm(int r) const { return reg_[r].immVal; }
|
||||||
|
|
||||||
void MapIn(MIPSGPReg rd);
|
|
||||||
void MapInIn(MIPSGPReg rs, MIPSGPReg rt);
|
|
||||||
void MapDirty(MIPSGPReg rd);
|
|
||||||
void MapDirtyIn(MIPSGPReg rd, MIPSGPReg rs);
|
|
||||||
void MapDirtyInIn(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt);
|
|
||||||
|
|
||||||
void Start(IRWriter *ir);
|
|
||||||
void FlushAll();
|
void FlushAll();
|
||||||
|
|
||||||
|
void MapInIn(int rs, int rt);
|
||||||
|
void MapDirtyIn(int rd, int rs);
|
||||||
|
void MapDirtyInIn(int rd, int rs, int rt);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void Dirty(MIPSGPReg rd);
|
void Flush(int rd);
|
||||||
|
void Discard(int rd);
|
||||||
RegIR reg_[TOTAL_MAPPABLE_MIPSREGS];
|
RegIR reg_[TOTAL_MAPPABLE_MIPSREGS];
|
||||||
IRWriter *ir_;
|
IRWriter *ir_;
|
||||||
};
|
};
|
||||||
|
Loading…
Reference in New Issue
Block a user