Permalink
Browse files

Merge pull request #10503 from unknownbrackets/irjit

irjit: Embed constant inside IRInst (now 64-bit)
  • Loading branch information...
hrydgard committed Jan 4, 2018
2 parents 5c50c00 + bc541bd commit c3f271c715dbc3f3c550b80226abf46e58f7aabd
@@ -92,7 +92,7 @@ void IRFrontend::BranchRSRTComp(MIPSOpcode op, IRComparison cc, bool likely) {
CompileDelaySlot();
int dcAmount = js.downcountAmount;
ir.Write(IROp::Downcount, 0, dcAmount & 0xFF, dcAmount >> 8);
ir.Write(IROp::Downcount, 0, ir.AddConstant(dcAmount));
js.downcountAmount = 0;
FlushAll();
@@ -133,7 +133,7 @@ void IRFrontend::BranchRSZeroComp(MIPSOpcode op, IRComparison cc, bool andLink,
CompileDelaySlot();
int dcAmount = js.downcountAmount;
ir.Write(IROp::Downcount, 0, dcAmount & 0xFF, dcAmount >> 8);
ir.Write(IROp::Downcount, 0, ir.AddConstant(dcAmount));
js.downcountAmount = 0;
FlushAll();
@@ -200,7 +200,7 @@ void IRFrontend::BranchFPFlag(MIPSOpcode op, IRComparison cc, bool likely) {
CompileDelaySlot();
int dcAmount = js.downcountAmount;
ir.Write(IROp::Downcount, 0, dcAmount & 0xFF, dcAmount >> 8);
ir.Write(IROp::Downcount, 0, ir.AddConstant(dcAmount));
js.downcountAmount = 0;
FlushAll();
@@ -249,7 +249,7 @@ void IRFrontend::BranchVFPUFlag(MIPSOpcode op, IRComparison cc, bool likely) {
CompileDelaySlot();
int dcAmount = js.downcountAmount;
ir.Write(IROp::Downcount, 0, dcAmount & 0xFF, dcAmount >> 8);
ir.Write(IROp::Downcount, 0, ir.AddConstant(dcAmount));
js.downcountAmount = 0;
if (delaySlotIsBranch && (signed short)(delaySlotOp & 0xFFFF) != (signed short)(op & 0xFFFF) - 1)
@@ -320,7 +320,7 @@ void IRFrontend::Comp_Jump(MIPSOpcode op) {
}
int dcAmount = js.downcountAmount;
ir.Write(IROp::Downcount, 0, dcAmount & 0xFF, dcAmount >> 8);
ir.Write(IROp::Downcount, 0, ir.AddConstant(dcAmount));
js.downcountAmount = 0;
FlushAll();
@@ -384,7 +384,7 @@ void IRFrontend::Comp_JumpReg(MIPSOpcode op) {
}
int dcAmount = js.downcountAmount;
ir.Write(IROp::Downcount, 0, dcAmount & 0xFF, dcAmount >> 8);
ir.Write(IROp::Downcount, 0, ir.AddConstant(dcAmount));
js.downcountAmount = 0;
ir.Write(IROp::ExitToReg, 0, destReg, 0);
@@ -397,7 +397,7 @@ void IRFrontend::Comp_JumpReg(MIPSOpcode op) {
void IRFrontend::Comp_Syscall(MIPSOpcode op) {
// Note: If we're in a delay slot, this is off by one compared to the interpreter.
int dcAmount = js.downcountAmount + (js.inDelaySlot ? -1 : 0);
ir.Write(IROp::Downcount, 0, dcAmount & 0xFF, dcAmount >> 8);
ir.Write(IROp::Downcount, 0, ir.AddConstant(dcAmount));
js.downcountAmount = 0;
// If not in a delay slot, we need to update PC.
@@ -162,7 +162,7 @@ void IRFrontend::Comp_ReplacementFunc(MIPSOpcode op) {
MIPSCompileOp(Memory::Read_Instruction(GetCompilerPC(), true), this);
} else {
ApplyRoundingMode();
ir.Write(IROp::Downcount, 0, js.downcountAmount & 0xFF, js.downcountAmount >> 8);
ir.Write(IROp::Downcount, 0, ir.AddConstant(js.downcountAmount));
ir.Write(IROp::ExitToReg, 0, MIPS_REG_RA, 0);
js.compiling = false;
}
@@ -219,7 +219,7 @@ MIPSOpcode IRFrontend::GetOffsetInstruction(int offset) {
return Memory::Read_Instruction(GetCompilerPC() + 4 * offset);
}
void IRFrontend::DoJit(u32 em_address, std::vector<IRInst> &instructions, std::vector<u32> &constants, u32 &mipsBytes) {
void IRFrontend::DoJit(u32 em_address, std::vector<IRInst> &instructions, u32 &mipsBytes) {
js.cancel = false;
js.blockStart = em_address;
js.compilerPC = em_address;
@@ -244,12 +244,6 @@ void IRFrontend::DoJit(u32 em_address, std::vector<IRInst> &instructions, std::v
MIPSCompileOp(inst, this);
js.compilerPC += 4;
js.numInstructions++;
if (ir.GetConstants().size() > 64) {
// Need to break the block
ir.Write(IROp::ExitToConst, ir.AddConstant(js.compilerPC));
js.compiling = false;
}
}
mipsBytes = js.compilerPC - em_address;
@@ -273,7 +267,6 @@ void IRFrontend::DoJit(u32 em_address, std::vector<IRInst> &instructions, std::v
}
instructions = code->GetInstructions();
constants = code->GetConstants();
if (logBlocks > 0 && dontLogBlocks == 0) {
char temp2[256];
@@ -286,20 +279,20 @@ void IRFrontend::DoJit(u32 em_address, std::vector<IRInst> &instructions, std::v
}
if (logBlocks > 0 && dontLogBlocks == 0) {
NOTICE_LOG(JIT, "=============== Original IR (%d instructions, %d const) ===============", (int)ir.GetInstructions().size(), (int)ir.GetConstants().size());
NOTICE_LOG(JIT, "=============== Original IR (%d instructions) ===============", (int)ir.GetInstructions().size());
for (size_t i = 0; i < ir.GetInstructions().size(); i++) {
char buf[256];
DisassembleIR(buf, sizeof(buf), ir.GetInstructions()[i], &ir.GetConstants()[0]);
DisassembleIR(buf, sizeof(buf), ir.GetInstructions()[i]);
NOTICE_LOG(JIT, "%s", buf);
}
NOTICE_LOG(JIT, "=============== end =================");
}
if (logBlocks > 0 && dontLogBlocks == 0) {
NOTICE_LOG(JIT, "=============== IR (%d instructions, %d const) ===============", (int)code->GetInstructions().size(), (int)code->GetConstants().size());
NOTICE_LOG(JIT, "=============== IR (%d instructions) ===============", (int)code->GetInstructions().size());
for (size_t i = 0; i < code->GetInstructions().size(); i++) {
char buf[256];
DisassembleIR(buf, sizeof(buf), code->GetInstructions()[i], &code->GetConstants()[0]);
DisassembleIR(buf, sizeof(buf), code->GetInstructions()[i]);
NOTICE_LOG(JIT, "%s", buf);
}
NOTICE_LOG(JIT, "=============== end =================");
@@ -326,7 +319,7 @@ void IRFrontend::CheckBreakpoint(u32 addr) {
// TODO: In likely branches, downcount will be incorrect.
int downcountOffset = js.inDelaySlot && js.downcountAmount >= 2 ? -2 : 0;
int downcountAmount = js.downcountAmount + downcountOffset;
ir.Write(IROp::Downcount, 0, downcountAmount & 0xFF, downcountAmount >> 8);
ir.Write(IROp::Downcount, 0, ir.AddConstant(downcountAmount));
// Note that this means downcount can't be metadata on the block.
js.downcountAmount = -downcountOffset;
ir.Write(IROp::Breakpoint);
@@ -349,7 +342,7 @@ void IRFrontend::CheckMemoryBreakpoint(int rs, int offset) {
downcountOffset = 0;
}
int downcountAmount = js.downcountAmount + downcountOffset;
ir.Write(IROp::Downcount, 0, downcountAmount & 0xFF, downcountAmount >> 8);
ir.Write(IROp::Downcount, 0, ir.AddConstant(downcountAmount));
// Note that this means downcount can't be metadata on the block.
js.downcountAmount = -downcountOffset;
ir.Write(IROp::MemoryCheck, 0, rs, ir.AddConstant(offset));
@@ -88,7 +88,7 @@ class IRFrontend : public MIPSFrontendInterface {
void DoState(PointerWrap &p);
bool CheckRounding(u32 blockAddress); // returns true if we need a do-over
void DoJit(u32 em_address, std::vector<IRInst> &instructions, std::vector<u32> &constants, u32 &mipsBytes);
void DoJit(u32 em_address, std::vector<IRInst> &instructions, u32 &mipsBytes);
void EatPrefix() override {
js.EatPrefix();
View
@@ -141,7 +141,7 @@ static const IRMeta irMeta[] = {
{ IROp::Vec2Pack31To16, "Vec2Pack31To16", "2V" },
{ IROp::Interpret, "Interpret", "_C" },
{ IROp::Downcount, "Downcount", "_II" },
{ IROp::Downcount, "Downcount", "_C" },
{ IROp::ExitToPC, "ExitToPC", "", IRFLAG_EXIT },
{ IROp::ExitToConst, "Exit", "C", IRFLAG_EXIT },
{ IROp::ExitToConstIfEq, "ExitIfEq", "CGG", IRFLAG_EXIT },
@@ -174,24 +174,19 @@ void IRWriter::Write(IROp op, u8 dst, u8 src1, u8 src2) {
inst.dest = dst;
inst.src1 = src1;
inst.src2 = src2;
inst.constant = nextConst_;
insts_.push_back(inst);
nextConst_ = 0;
}
void IRWriter::WriteSetConstant(u8 dst, u32 value) {
Write(IROp::SetConst, dst, AddConstant(value));
}
int IRWriter::AddConstant(u32 value) {
for (size_t i = 0; i < constPool_.size(); i++) {
if (constPool_[i] == value)
return (int)i;
}
constPool_.push_back(value);
if (constPool_.size() > 255) {
// Cannot have more than 256 constants in a block!
Crash();
}
return (int)constPool_.size() - 1;
nextConst_ = value;
return 255;
}
int IRWriter::AddConstantFloat(float value) {
@@ -215,7 +210,7 @@ const char *GetGPRName(int r) {
}
}
void DisassembleParam(char *buf, int bufSize, u8 param, char type, const u32 *constPool) {
void DisassembleParam(char *buf, int bufSize, u8 param, char type, u32 constant) {
static const char *vfpuCtrlNames[VFPU_CTRL_MAX] = {
"SPFX",
"TPFX",
@@ -271,7 +266,7 @@ void DisassembleParam(char *buf, int bufSize, u8 param, char type, const u32 *co
}
break;
case 'C':
snprintf(buf, bufSize, "%08x", constPool[param]);
snprintf(buf, bufSize, "%08x", constant);
break;
case 'I':
snprintf(buf, bufSize, "%02x", param);
@@ -302,7 +297,7 @@ 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 IRMeta *meta = GetIRMeta(inst.op);
if (!meta) {
snprintf(buf, bufsize, "Unknown %d", (int)inst.op);
@@ -311,9 +306,9 @@ void DisassembleIR(char *buf, size_t bufsize, IRInst inst, const u32 *constPool)
char bufDst[16];
char bufSrc1[16];
char bufSrc2[16];
DisassembleParam(bufDst, sizeof(bufDst) - 2, inst.dest, meta->types[0], constPool);
DisassembleParam(bufSrc1, sizeof(bufSrc1) - 2, inst.src1, meta->types[1], constPool);
DisassembleParam(bufSrc2, sizeof(bufSrc2), inst.src2, meta->types[2], constPool);
DisassembleParam(bufDst, sizeof(bufDst) - 2, inst.dest, meta->types[0], inst.constant);
DisassembleParam(bufSrc1, sizeof(bufSrc1) - 2, inst.src1, meta->types[1], inst.constant);
DisassembleParam(bufSrc2, sizeof(bufSrc2), inst.src2, meta->types[2], inst.constant);
if (meta->types[1] && meta->types[0] != '_') {
strcat(bufDst, ", ");
}
View
@@ -313,10 +313,7 @@ struct IRMeta {
u32 flags;
};
// 32 bits.
// TODO: Evaluate whether it would make sense to switch to 64-bit ops with immediates
// included instead of storing immediates separately. Would simplify things at some memory
// storage and bandwidth cost.
// 64 bits.
struct IRInst {
IROp op;
union {
@@ -325,22 +322,21 @@ struct IRInst {
};
u8 src1;
u8 src2;
u32 constant;
};
// Returns the new PC.
u32 IRInterpret(MIPSState *mips, const IRInst *inst, const u32 *constPool, int count);
u32 IRInterpret(MIPSState *mips, const IRInst *inst, int count);
// Each IR block gets a constant pool.
class IRWriter {
public:
IRWriter &operator =(const IRWriter &w) {
insts_ = w.insts_;
constPool_ = w.constPool_;
return *this;
}
IRWriter &operator =(IRWriter &&w) {
insts_ = std::move(w.insts_);
constPool_ = std::move(w.constPool_);
return *this;
}
@@ -355,21 +351,19 @@ class IRWriter {
void Clear() {
insts_.clear();
constPool_.clear();
}
const std::vector<IRInst> &GetInstructions() const { return insts_; }
const std::vector<u32> &GetConstants() const { return constPool_; }
private:
std::vector<IRInst> insts_;
std::vector<u32> constPool_;
u32 nextConst_ = 0;
};
struct IROptions {
bool unalignedLoadStore;
};
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);
void InitIR();
Oops, something went wrong.

0 comments on commit c3f271c

Please sign in to comment.