mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-24 08:39:51 +00:00
Separate the IR frontend from the IR "Jit"
This commit is contained in:
parent
6e44e97ffa
commit
e806c369b2
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user