Separate the IR frontend from the IR "Jit"

This commit is contained in:
Henrik Rydgard 2016-05-09 19:57:18 +02:00
parent 6e44e97ffa
commit e806c369b2
7 changed files with 165 additions and 182 deletions

View File

@ -45,7 +45,7 @@ using namespace MIPSAnalyst;
namespace MIPSComp {
void IRJit::Comp_IType(MIPSOpcode op) {
void IRFrontend::Comp_IType(MIPSOpcode op) {
CONDITIONAL_DISABLE;
s32 simm = (s32)(s16)(op & 0xFFFF); // sign extension
@ -87,7 +87,7 @@ void IRJit::Comp_IType(MIPSOpcode op) {
}
}
void IRJit::Comp_RType2(MIPSOpcode op) {
void IRFrontend::Comp_RType2(MIPSOpcode op) {
CONDITIONAL_DISABLE;
MIPSGPReg rs = _RS;
@ -110,7 +110,7 @@ void IRJit::Comp_RType2(MIPSOpcode op) {
}
}
void IRJit::Comp_RType3(MIPSOpcode op) {
void IRFrontend::Comp_RType3(MIPSOpcode op) {
CONDITIONAL_DISABLE;
MIPSGPReg rt = _RT;
@ -182,13 +182,13 @@ void IRJit::Comp_RType3(MIPSOpcode op) {
}
}
void IRJit::CompShiftImm(MIPSOpcode op, IROp shiftOpImm, int sa) {
void IRFrontend::CompShiftImm(MIPSOpcode op, IROp shiftOpImm, int sa) {
MIPSGPReg rd = _RD;
MIPSGPReg rt = _RT;
ir.Write(shiftOpImm, rd, rt, sa);
}
void IRJit::CompShiftVar(MIPSOpcode op, IROp shiftOp, IROp shiftOpImm) {
void IRFrontend::CompShiftVar(MIPSOpcode op, IROp shiftOp, IROp shiftOpImm) {
MIPSGPReg rd = _RD;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;
@ -196,7 +196,7 @@ void IRJit::CompShiftVar(MIPSOpcode op, IROp shiftOp, IROp shiftOpImm) {
ir.Write(shiftOp, rd, rt, IRTEMP_0);
}
void IRJit::Comp_ShiftType(MIPSOpcode op) {
void IRFrontend::Comp_ShiftType(MIPSOpcode op) {
CONDITIONAL_DISABLE;
MIPSGPReg rs = _RS;
MIPSGPReg rd = _RD;
@ -221,7 +221,7 @@ void IRJit::Comp_ShiftType(MIPSOpcode op) {
}
}
void IRJit::Comp_Special3(MIPSOpcode op) {
void IRFrontend::Comp_Special3(MIPSOpcode op) {
CONDITIONAL_DISABLE;
MIPSGPReg rs = _RS;
MIPSGPReg rt = _RT;
@ -260,7 +260,7 @@ void IRJit::Comp_Special3(MIPSOpcode op) {
}
void IRJit::Comp_Allegrex(MIPSOpcode op) {
void IRFrontend::Comp_Allegrex(MIPSOpcode op) {
CONDITIONAL_DISABLE;
MIPSGPReg rt = _RT;
MIPSGPReg rd = _RD;
@ -284,7 +284,7 @@ void IRJit::Comp_Allegrex(MIPSOpcode op) {
}
}
void IRJit::Comp_Allegrex2(MIPSOpcode op) {
void IRFrontend::Comp_Allegrex2(MIPSOpcode op) {
CONDITIONAL_DISABLE;
MIPSGPReg rt = _RT;
MIPSGPReg rd = _RD;
@ -305,7 +305,7 @@ void IRJit::Comp_Allegrex2(MIPSOpcode op) {
}
}
void IRJit::Comp_MulDivType(MIPSOpcode op) {
void IRFrontend::Comp_MulDivType(MIPSOpcode op) {
CONDITIONAL_DISABLE;
MIPSGPReg rt = _RT;
MIPSGPReg rs = _RS;

View File

@ -53,7 +53,7 @@ namespace MIPSComp
{
using namespace Arm64Gen;
void IRJit::BranchRSRTComp(MIPSOpcode op, IRComparison cc, bool likely) {
void IRFrontend::BranchRSRTComp(MIPSOpcode op, IRComparison cc, bool likely) {
if (js.inDelaySlot) {
ERROR_LOG_REPORT(JIT, "Branch in RSRTComp delay slot at %08x in block starting at %08x", GetCompilerPC(), js.blockStart);
return;
@ -98,7 +98,7 @@ void IRJit::BranchRSRTComp(MIPSOpcode op, IRComparison cc, bool likely) {
js.compiling = false;
}
void IRJit::BranchRSZeroComp(MIPSOpcode op, IRComparison cc, bool andLink, bool likely) {
void IRFrontend::BranchRSZeroComp(MIPSOpcode op, IRComparison cc, bool andLink, bool likely) {
if (js.inDelaySlot) {
ERROR_LOG_REPORT(JIT, "Branch in RSZeroComp delay slot at %08x in block starting at %08x", GetCompilerPC(), js.blockStart);
return;
@ -135,7 +135,7 @@ void IRJit::BranchRSZeroComp(MIPSOpcode op, IRComparison cc, bool andLink, bool
js.compiling = false;
}
void IRJit::Comp_RelBranch(MIPSOpcode op) {
void IRFrontend::Comp_RelBranch(MIPSOpcode op) {
// The CC flags here should be opposite of the actual branch becuase they skip the branching action.
switch (op >> 26) {
case 4: BranchRSRTComp(op, IRComparison::NotEqual, false); break;//beq
@ -156,7 +156,7 @@ void IRJit::Comp_RelBranch(MIPSOpcode op) {
}
}
void IRJit::Comp_RelBranchRI(MIPSOpcode op) {
void IRFrontend::Comp_RelBranchRI(MIPSOpcode op) {
switch ((op >> 16) & 0x1F) {
case 0: BranchRSZeroComp(op, IRComparison::GreaterEqual, false, false); break; //if ((s32)R(rs) < 0) DelayBranchTo(addr); else PC += 4; break;//bltz
case 1: BranchRSZeroComp(op, IRComparison::Less, false, false); break; //if ((s32)R(rs) >= 0) DelayBranchTo(addr); else PC += 4; break;//bgez
@ -173,7 +173,7 @@ void IRJit::Comp_RelBranchRI(MIPSOpcode op) {
}
// If likely is set, discard the branch slot if NOT taken.
void IRJit::BranchFPFlag(MIPSOpcode op, IRComparison cc, bool likely) {
void IRFrontend::BranchFPFlag(MIPSOpcode op, IRComparison cc, bool likely) {
if (js.inDelaySlot) {
ERROR_LOG_REPORT(JIT, "Branch in FPFlag delay slot at %08x in block starting at %08x", GetCompilerPC(), js.blockStart);
return;
@ -201,7 +201,7 @@ void IRJit::BranchFPFlag(MIPSOpcode op, IRComparison cc, bool likely) {
js.compiling = false;
}
void IRJit::Comp_FPUBranch(MIPSOpcode op) {
void IRFrontend::Comp_FPUBranch(MIPSOpcode op) {
switch((op >> 16) & 0x1f) {
case 0: BranchFPFlag(op, IRComparison::NotEqual, false); break; // bc1f
case 1: BranchFPFlag(op, IRComparison::Equal, false); break; // bc1t
@ -214,7 +214,7 @@ void IRJit::Comp_FPUBranch(MIPSOpcode op) {
}
// If likely is set, discard the branch slot if NOT taken.
void IRJit::BranchVFPUFlag(MIPSOpcode op, IRComparison cc, bool likely) {
void IRFrontend::BranchVFPUFlag(MIPSOpcode op, IRComparison cc, bool likely) {
if (js.inDelaySlot) {
ERROR_LOG_REPORT(JIT, "Branch in VFPU delay slot at %08x in block starting at %08x", GetCompilerPC(), js.blockStart);
return;
@ -223,7 +223,6 @@ void IRJit::BranchVFPUFlag(MIPSOpcode op, IRComparison cc, bool likely) {
u32 targetAddr = GetCompilerPC() + offset + 4;
MIPSOpcode delaySlotOp = GetOffsetInstruction(1);
logBlocks = 1;
ir.Write(IROp::VfpuCtrlToReg, IRTEMP_LHS, VFPU_CTRL_CC);
int dcAmount = js.downcountAmount;
@ -257,7 +256,7 @@ void IRJit::BranchVFPUFlag(MIPSOpcode op, IRComparison cc, bool likely) {
js.compiling = false;
}
void IRJit::Comp_VBranch(MIPSOpcode op) {
void IRFrontend::Comp_VBranch(MIPSOpcode op) {
switch ((op >> 16) & 3) {
case 0: BranchVFPUFlag(op, IRComparison::NotEqual, false); break; // bvf
case 1: BranchVFPUFlag(op, IRComparison::Equal, false); break; // bvt
@ -266,7 +265,7 @@ void IRJit::Comp_VBranch(MIPSOpcode op) {
}
}
void IRJit::Comp_Jump(MIPSOpcode op) {
void IRFrontend::Comp_Jump(MIPSOpcode op) {
if (js.inDelaySlot) {
ERROR_LOG_REPORT(JIT, "Branch in Jump delay slot at %08x in block starting at %08x", GetCompilerPC(), js.blockStart);
return;
@ -311,7 +310,7 @@ void IRJit::Comp_Jump(MIPSOpcode op) {
js.compiling = false;
}
void IRJit::Comp_JumpReg(MIPSOpcode op) {
void IRFrontend::Comp_JumpReg(MIPSOpcode op) {
if (js.inDelaySlot) {
ERROR_LOG_REPORT(JIT, "Branch in JumpReg delay slot at %08x in block starting at %08x", GetCompilerPC(), js.blockStart);
return;
@ -368,7 +367,7 @@ void IRJit::Comp_JumpReg(MIPSOpcode op) {
js.compiling = false;
}
void IRJit::Comp_Syscall(MIPSOpcode op) {
void IRFrontend::Comp_Syscall(MIPSOpcode op) {
RestoreRoundingMode();
// Note: If we're in a delay slot, this is off by one compared to the interpreter.
@ -385,7 +384,7 @@ void IRJit::Comp_Syscall(MIPSOpcode op) {
js.compiling = false;
}
void IRJit::Comp_Break(MIPSOpcode op) {
void IRFrontend::Comp_Break(MIPSOpcode op) {
ir.Write(IROp::Break);
js.compiling = false;
}

View File

@ -54,7 +54,7 @@
namespace MIPSComp {
void IRJit::Comp_FPU3op(MIPSOpcode op) {
void IRFrontend::Comp_FPU3op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
int ft = _FT;
@ -72,7 +72,7 @@ void IRJit::Comp_FPU3op(MIPSOpcode op) {
}
}
void IRJit::Comp_FPULS(MIPSOpcode op) {
void IRFrontend::Comp_FPULS(MIPSOpcode op) {
CONDITIONAL_DISABLE;
s32 offset = _IMM16;
int ft = _FT;
@ -93,7 +93,7 @@ void IRJit::Comp_FPULS(MIPSOpcode op) {
}
}
void IRJit::Comp_FPUComp(MIPSOpcode op) {
void IRFrontend::Comp_FPUComp(MIPSOpcode op) {
DISABLE; // IROps not yet implemented
int opc = op & 0xF;
@ -136,7 +136,7 @@ void IRJit::Comp_FPUComp(MIPSOpcode op) {
ir.Write(irOp, fs, ft);
}
void IRJit::Comp_FPU2op(MIPSOpcode op) {
void IRFrontend::Comp_FPU2op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
int fs = _FS;
@ -192,7 +192,7 @@ void IRJit::Comp_FPU2op(MIPSOpcode op) {
}
}
void IRJit::Comp_mxc1(MIPSOpcode op) {
void IRFrontend::Comp_mxc1(MIPSOpcode op) {
CONDITIONAL_DISABLE;
int fs = _FS;

View File

@ -65,11 +65,11 @@
#define DISABLE { Comp_Generic(op); return; }
namespace MIPSComp {
void IRJit::Comp_ITypeMemLR(MIPSOpcode op, bool load) {
void IRFrontend::Comp_ITypeMemLR(MIPSOpcode op, bool load) {
DISABLE;
}
void IRJit::Comp_ITypeMem(MIPSOpcode op) {
void IRFrontend::Comp_ITypeMem(MIPSOpcode op) {
CONDITIONAL_DISABLE;
int offset = (signed short)(op & 0xFFFF);
@ -124,7 +124,7 @@ namespace MIPSComp {
}
}
void IRJit::Comp_Cache(MIPSOpcode op) {
void IRFrontend::Comp_Cache(MIPSOpcode op) {
// int imm = (s16)(op & 0xFFFF);
// int rs = _RS;
// int addr = R(rs) + imm;

View File

@ -51,7 +51,7 @@
namespace MIPSComp {
void IRJit::Comp_VPFX(MIPSOpcode op) {
void IRFrontend::Comp_VPFX(MIPSOpcode op) {
CONDITIONAL_DISABLE;
int data = op & 0xFFFFF;
int regnum = (op >> 24) & 3;
@ -74,7 +74,7 @@ namespace MIPSComp {
}
}
void IRJit::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) {
void IRFrontend::ApplyPrefixST(u8 *vregs, u32 prefix, VectorSize sz) {
if (prefix == 0xE4)
return;
@ -128,7 +128,7 @@ namespace MIPSComp {
}
}
void IRJit::GetVectorRegsPrefixD(u8 *regs, VectorSize sz, int vectorReg) {
void IRFrontend::GetVectorRegsPrefixD(u8 *regs, VectorSize sz, int vectorReg) {
_assert_(js.prefixDFlag & JitState::PREFIX_KNOWN);
GetVectorRegs(regs, sz, vectorReg);
@ -143,7 +143,7 @@ namespace MIPSComp {
}
}
void IRJit::ApplyPrefixD(const u8 *vregs, VectorSize sz) {
void IRFrontend::ApplyPrefixD(const u8 *vregs, VectorSize sz) {
_assert_(js.prefixDFlag & JitState::PREFIX_KNOWN);
if (!js.prefixD)
return;
@ -176,11 +176,11 @@ namespace MIPSComp {
*/
}
void IRJit::Comp_SV(MIPSOpcode op) {
void IRFrontend::Comp_SV(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_SVQ(MIPSOpcode op) {
void IRFrontend::Comp_SVQ(MIPSOpcode op) {
int imm = (signed short)(op & 0xFFFC);
int vt = (((op >> 16) & 0x1f)) | ((op & 1) << 5);
MIPSGPReg rs = _RS;
@ -215,37 +215,37 @@ namespace MIPSComp {
}
}
void IRJit::Comp_VVectorInit(MIPSOpcode op) {
void IRFrontend::Comp_VVectorInit(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_VIdt(MIPSOpcode op) {
void IRFrontend::Comp_VIdt(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_VMatrixInit(MIPSOpcode op) {
void IRFrontend::Comp_VMatrixInit(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_VHdp(MIPSOpcode op) {
void IRFrontend::Comp_VHdp(MIPSOpcode op) {
DISABLE;
}
static const float MEMORY_ALIGNED16(vavg_table[4]) = { 1.0f, 1.0f / 2.0f, 1.0f / 3.0f, 1.0f / 4.0f };
void IRJit::Comp_Vhoriz(MIPSOpcode op) {
void IRFrontend::Comp_Vhoriz(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_VDot(MIPSOpcode op) {
void IRFrontend::Comp_VDot(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_VecDo3(MIPSOpcode op) {
void IRFrontend::Comp_VecDo3(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_VV2Op(MIPSOpcode op) {
void IRFrontend::Comp_VV2Op(MIPSOpcode op) {
CONDITIONAL_DISABLE;
// Pre-processing: Eliminate silly no-op VMOVs, common in Wipeout Pure
if (((op >> 16) & 0x1f) == 0 && _VS == _VD && js.HasNoPrefix()) {
@ -254,19 +254,19 @@ namespace MIPSComp {
DISABLE;
}
void IRJit::Comp_Vi2f(MIPSOpcode op) {
void IRFrontend::Comp_Vi2f(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vh2f(MIPSOpcode op) {
void IRFrontend::Comp_Vh2f(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vf2i(MIPSOpcode op) {
void IRFrontend::Comp_Vf2i(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Mftv(MIPSOpcode op) {
void IRFrontend::Comp_Mftv(MIPSOpcode op) {
int imm = op & 0xFF;
MIPSGPReg rt = _RT;
switch ((op >> 21) & 0x1f) {
@ -275,7 +275,6 @@ namespace MIPSComp {
if (rt != 0) {
if (imm < 128) { //R(rt) = VI(imm);
ir.Write(IROp::VMovToGPR, rt, imm);
logBlocks = 1;
} else {
DISABLE;
}
@ -285,7 +284,6 @@ namespace MIPSComp {
case 7: // mtv
if (imm < 128) {
ir.Write(IROp::VMovFromGPR, imm, rt);
logBlocks = 1;
} else {
DISABLE;
}
@ -296,93 +294,93 @@ namespace MIPSComp {
}
}
void IRJit::Comp_Vmfvc(MIPSOpcode op) {
void IRFrontend::Comp_Vmfvc(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vmtvc(MIPSOpcode op) {
void IRFrontend::Comp_Vmtvc(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vmmov(MIPSOpcode op) {
void IRFrontend::Comp_Vmmov(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_VScl(MIPSOpcode op) {
void IRFrontend::Comp_VScl(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vmmul(MIPSOpcode op) {
void IRFrontend::Comp_Vmmul(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vmscl(MIPSOpcode op) {
void IRFrontend::Comp_Vmscl(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vtfm(MIPSOpcode op) {
void IRFrontend::Comp_Vtfm(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_VCrs(MIPSOpcode op) {
void IRFrontend::Comp_VCrs(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_VDet(MIPSOpcode op) {
void IRFrontend::Comp_VDet(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vi2x(MIPSOpcode op) {
void IRFrontend::Comp_Vi2x(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vx2i(MIPSOpcode op) {
void IRFrontend::Comp_Vx2i(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_VCrossQuat(MIPSOpcode op) {
void IRFrontend::Comp_VCrossQuat(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vcmp(MIPSOpcode op) {
void IRFrontend::Comp_Vcmp(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vcmov(MIPSOpcode op) {
void IRFrontend::Comp_Vcmov(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Viim(MIPSOpcode op) {
void IRFrontend::Comp_Viim(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vfim(MIPSOpcode op) {
void IRFrontend::Comp_Vfim(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vcst(MIPSOpcode op) {
void IRFrontend::Comp_Vcst(MIPSOpcode op) {
DISABLE;
}
// Very heavily used by FF:CC. Should be replaced by a fast approximation instead of
// calling the math library.
void IRJit::Comp_VRot(MIPSOpcode op) {
void IRFrontend::Comp_VRot(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vsgn(MIPSOpcode op) {
void IRFrontend::Comp_Vsgn(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vocp(MIPSOpcode op) {
void IRFrontend::Comp_Vocp(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_ColorConv(MIPSOpcode op) {
void IRFrontend::Comp_ColorConv(MIPSOpcode op) {
DISABLE;
}
void IRJit::Comp_Vbfy(MIPSOpcode op) {
void IRFrontend::Comp_Vbfy(MIPSOpcode op) {
DISABLE;
}
}

View File

@ -42,11 +42,7 @@
namespace MIPSComp {
IRJit::IRJit(MIPSState *mips) : mips_(mips) {
logBlocks = 0;
dontLogBlocks = 0;
js.startDefaultPrefix = mips_->HasDefaultPrefix();
js.currentRoundingFunc = convertS0ToSCRATCH1[0];
IRJit::IRJit(MIPSState *mips) : mips_(mips), frontend_(mips->HasDefaultPrefix()) {
u32 size = 128 * 1024;
// blTrampolines_ = kernelMemory.Alloc(size, true, "trampoline");
InitIR();
@ -55,7 +51,14 @@ IRJit::IRJit(MIPSState *mips) : mips_(mips) {
IRJit::~IRJit() {
}
void IRJit::DoState(PointerWrap &p) {
IRFrontend::IRFrontend(bool startDefaultPrefix) {
logBlocks = 0;
dontLogBlocks = 0;
js.startDefaultPrefix = startDefaultPrefix;
// js.currentRoundingFunc = convertS0ToSCRATCH1[0];
}
void IRFrontend::DoState(PointerWrap &p) {
auto s = p.Section("Jit", 1, 2);
if (!s)
return;
@ -67,10 +70,10 @@ void IRJit::DoState(PointerWrap &p) {
} else {
js.hasSetRounding = 1;
}
}
if (p.GetMode() == PointerWrap::MODE_READ) {
js.currentRoundingFunc = convertS0ToSCRATCH1[(mips_->fcr31) & 3];
}
void IRJit::DoState(PointerWrap &p) {
frontend_.DoState(p);
}
// This is here so the savestate matches between jit and non-jit.
@ -87,11 +90,11 @@ void IRJit::DoDummyState(PointerWrap &p) {
}
}
void IRJit::FlushAll() {
void IRFrontend::FlushAll() {
FlushPrefixV();
}
void IRJit::FlushPrefixV() {
void IRFrontend::FlushPrefixV() {
if ((js.prefixSFlag & JitState::PREFIX_DIRTY) != 0) {
ir.Write(IROp::SetCtrlVFPU, VFPU_CTRL_SPREFIX, ir.AddConstant(js.prefixS));
js.prefixSFlag = (JitState::PrefixState) (js.prefixSFlag & ~JitState::PREFIX_DIRTY);
@ -121,7 +124,7 @@ void IRJit::InvalidateCacheAt(u32 em_address, int length) {
blocks_.InvalidateICache(em_address, length);
}
void IRJit::EatInstruction(MIPSOpcode op) {
void IRFrontend::EatInstruction(MIPSOpcode op) {
MIPSInfo info = MIPSGetInfo(op);
if (info & DELAYSLOT) {
ERROR_LOG_REPORT_ONCE(ateDelaySlot, JIT, "Ate a branch op.");
@ -135,23 +138,15 @@ void IRJit::EatInstruction(MIPSOpcode op) {
js.downcountAmount += MIPSGetInstructionCycleEstimate(op);
}
void IRJit::CompileDelaySlot() {
void IRFrontend::CompileDelaySlot() {
js.inDelaySlot = true;
MIPSOpcode op = GetOffsetInstruction(1);
MIPSCompileOp(op, this);
js.inDelaySlot = false;
}
void IRJit::Compile(u32 em_address) {
PROFILE_THIS_SCOPE("jitc");
int block_num = blocks_.AllocateBlock(em_address);
IRBlock *b = blocks_.GetBlock(block_num);
DoJit(em_address, b);
b->Finalize(block_num); // Overwrites the first instruction
bool IRFrontend::CheckRounding() {
bool cleanSlate = false;
if (js.hasSetRounding && !js.lastSetRounding) {
WARN_LOG(JIT, "Detected rounding mode usage, rebuilding jit with checks");
// Won't loop, since hasSetRounding is only ever set to 1.
@ -161,16 +156,27 @@ void IRJit::Compile(u32 em_address) {
// Drat. The VFPU hit an uneaten prefix at the end of a block.
if (js.startDefaultPrefix && js.MayHavePrefix()) {
WARN_LOG(JIT, "An uneaten prefix at end of block: %08x", GetCompilerPC() - 4);
WARN_LOG(JIT, "An uneaten prefix at end of block");
js.LogPrefix();
// Let's try that one more time. We won't get back here because we toggled the value.
js.startDefaultPrefix = false;
// TODO ARM64: This crashes.
//cleanSlate = true;
// TODO: Make sure this works.
// cleanSlate = true;
}
if (cleanSlate) {
return cleanSlate;
}
void IRJit::Compile(u32 em_address) {
PROFILE_THIS_SCOPE("jitc");
int block_num = blocks_.AllocateBlock(em_address);
IRBlock *b = blocks_.GetBlock(block_num);
frontend_.DoJit(em_address, b);
b->Finalize(block_num); // Overwrites the first instruction
if (frontend_.CheckRounding()) {
// Our assumptions are all wrong so it's clean-slate time.
ClearCache();
Compile(em_address);
@ -208,18 +214,18 @@ void IRJit::RunLoopUntil(u64 globalticks) {
// RestoreRoundingMode(true);
}
u32 IRJit::GetCompilerPC() {
u32 IRFrontend::GetCompilerPC() {
return js.compilerPC;
}
MIPSOpcode IRJit::GetOffsetInstruction(int offset) {
MIPSOpcode IRFrontend::GetOffsetInstruction(int offset) {
return Memory::Read_Instruction(GetCompilerPC() + 4 * offset);
}
void IRJit::DoJit(u32 em_address, IRBlock *b) {
void IRFrontend::DoJit(u32 em_address, IRBlock *b) {
js.cancel = false;
js.blockStart = mips_->pc;
js.compilerPC = mips_->pc;
js.blockStart = em_address;
js.compilerPC = em_address;
js.lastContinuedPC = 0;
js.initialBlockSize = 0;
js.nextExit = 0;
@ -262,7 +268,7 @@ void IRJit::DoJit(u32 em_address, IRBlock *b) {
if (logBlocks > 0 && dontLogBlocks == 0) {
char temp2[256];
ILOG("=============== mips %d %08x ===============", blocks_.GetNumBlocks(), em_address);
ILOG("=============== mips %08x ===============", em_address);
for (u32 cpc = em_address; cpc != GetCompilerPC() + 4; cpc += 4) {
temp2[0] = 0;
MIPSDisAsm(Memory::Read_Opcode_JIT(cpc), cpc, temp2, true);
@ -301,7 +307,7 @@ bool IRJit::DescribeCodePtr(const u8 *ptr, std::string &name) {
return false;
}
void IRJit::Comp_RunBlock(MIPSOpcode op) {
void IRFrontend::Comp_RunBlock(MIPSOpcode op) {
// This shouldn't be necessary, the dispatcher should catch us before we get here.
ERROR_LOG(JIT, "Comp_RunBlock should never be reached!");
}
@ -319,7 +325,7 @@ bool IRJit::ReplaceJalTo(u32 dest) {
return false;
}
void IRJit::Comp_ReplacementFunc(MIPSOpcode op) {
void IRFrontend::Comp_ReplacementFunc(MIPSOpcode op) {
int index = op.encoding & MIPS_EMUHACK_VALUE_MASK;
const ReplacementTableEntry *entry = GetReplacementFunc(index);
@ -351,7 +357,7 @@ void IRJit::Comp_ReplacementFunc(MIPSOpcode op) {
}
}
void IRJit::Comp_Generic(MIPSOpcode op) {
void IRFrontend::Comp_Generic(MIPSOpcode op) {
FlushAll();
ir.Write(IROp::Interpret, 0, ir.AddConstant(op.encoding));
const MIPSInfo info = MIPSGetInfo(op);
@ -363,7 +369,7 @@ void IRJit::Comp_Generic(MIPSOpcode op) {
}
// Destroys SCRATCH2
void IRJit::RestoreRoundingMode(bool force) {
void IRFrontend::RestoreRoundingMode(bool force) {
// If the game has never set an interesting rounding mode, we can safely skip this.
if (force || js.hasSetRounding) {
ir.Write(IROp::RestoreRoundingMode);
@ -371,7 +377,7 @@ void IRJit::RestoreRoundingMode(bool force) {
}
// Destroys SCRATCH1 and SCRATCH2
void IRJit::ApplyRoundingMode(bool force) {
void IRFrontend::ApplyRoundingMode(bool force) {
// If the game has never set an interesting rounding mode, we can safely skip this.
if (force || js.hasSetRounding) {
ir.Write(IROp::ApplyRoundingMode);
@ -379,14 +385,14 @@ void IRJit::ApplyRoundingMode(bool force) {
}
// Destroys SCRATCH1 and SCRATCH2
void IRJit::UpdateRoundingMode() {
void IRFrontend::UpdateRoundingMode() {
ir.Write(IROp::UpdateRoundingMode);
}
void IRJit::Comp_DoNothing(MIPSOpcode op) {
void IRFrontend::Comp_DoNothing(MIPSOpcode op) {
}
int IRJit::Replace_fabsf() {
int IRFrontend::Replace_fabsf() {
Crash();
return 0;
}

View File

@ -101,28 +101,11 @@ private:
std::vector<IRBlock> blocks_;
};
class IRJit : public JitInterface, public MIPSFrontendInterface{
class IRFrontend : public MIPSFrontendInterface {
public:
IRJit(MIPSState *mips);
virtual ~IRJit();
void DoState(PointerWrap &p) override;
void DoDummyState(PointerWrap &p) override;
const JitOptions &GetJitOptions() { return jo; }
// Compiled ops should ignore delay slots
// the compiler will take care of them by itself
// OR NOT
IRFrontend(bool startDefaultPrefix);
void Comp_Generic(MIPSOpcode op) override;
void RunLoopUntil(u64 globalticks) override;
void Compile(u32 em_address) override; // Compiles a block at current MIPS PC
void DoJit(u32 em_address, IRBlock *b);
bool DescribeCodePtr(const u8 *ptr, std::string &name) override;
void Comp_RunBlock(MIPSOpcode op) override;
void Comp_ReplacementFunc(MIPSOpcode op) override;
@ -195,25 +178,17 @@ public:
void Comp_Vbfy(MIPSOpcode op) override;
int Replace_fabsf();
void DoState(PointerWrap &p);
bool CheckRounding(); // returns true if we need a do-over
void DoJit(u32 em_address, IRBlock *b);
// Not using a regular block cache.
JitBlockCache *GetBlockCache() override { return nullptr; }
MIPSOpcode GetOriginalOp(MIPSOpcode op) override;
void ClearCache();
void InvalidateCache();
void InvalidateCacheAt(u32 em_address, int length = 4);
private:
void RestoreRoundingMode(bool force = false);
void ApplyRoundingMode(bool force = false);
void UpdateRoundingMode();
void EatPrefix() { js.EatPrefix(); }
const u8 *GetDispatcher() const override {
return dispatcher;
}
void LinkBlock(u8 *exitPoint, const u8 *checkedEntry) override;
void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override;
private:
void FlushAll();
void FlushPrefixV();
@ -222,12 +197,6 @@ private:
void EatInstruction(MIPSOpcode op);
MIPSOpcode GetOffsetInstruction(int offset);
void RestoreRoundingMode(bool force = false);
void ApplyRoundingMode(bool force = false);
void UpdateRoundingMode();
bool ReplaceJalTo(u32 dest);
// Utility compilation functions
void BranchFPFlag(MIPSOpcode op, IRComparison cc, bool likely);
void BranchVFPUFlag(MIPSOpcode op, IRComparison cc, bool likely);
@ -255,44 +224,55 @@ private:
// Utils
void Comp_ITypeMemLR(MIPSOpcode op, bool load);
JitOptions jo;
// State
JitState js;
IRWriter ir;
int dontLogBlocks;
int logBlocks;
};
class IRJit : public JitInterface {
public:
IRJit(MIPSState *mips);
virtual ~IRJit();
void DoState(PointerWrap &p) override;
void DoDummyState(PointerWrap &p) override;
const JitOptions &GetJitOptions() { return jo; }
void RunLoopUntil(u64 globalticks) override;
void Compile(u32 em_address) override; // Compiles a block at current MIPS PC
bool DescribeCodePtr(const u8 *ptr, std::string &name) override;
// Not using a regular block cache.
JitBlockCache *GetBlockCache() override { return nullptr; }
MIPSOpcode GetOriginalOp(MIPSOpcode op) override;
void ClearCache();
void InvalidateCache();
void InvalidateCacheAt(u32 em_address, int length = 4);
const u8 *GetDispatcher() const override { return nullptr; }
void LinkBlock(u8 *exitPoint, const u8 *checkedEntry) override;
void UnlinkBlock(u8 *checkedEntry, u32 originalAddress) override;
private:
bool ReplaceJalTo(u32 dest);
JitOptions jo;
IRFrontend frontend_;
IRBlockCache blocks_;
MIPSState *mips_;
int dontLogBlocks;
int logBlocks;
IRWriter ir;
// where to write branch-likely trampolines. not used atm
// u32 blTrampolines_;
// int blTrampolineCount_;
public:
// Code pointers
const u8 *enterDispatcher;
const u8 *outerLoop;
const u8 *outerLoopPCInSCRATCH1;
const u8 *dispatcherCheckCoreState;
const u8 *dispatcherPCInSCRATCH1;
const u8 *dispatcher;
const u8 *dispatcherNoCheck;
const u8 *breakpointBailout;
const u8 *saveStaticRegisters;
const u8 *loadStaticRegisters;
const u8 *restoreRoundingMode;
const u8 *applyRoundingMode;
const u8 *updateRoundingMode;
// Indexed by FPCR FZ:RN bits for convenience. Uses SCRATCH2.
const u8 *convertS0ToSCRATCH1[8];
};
} // namespace MIPSComp