From 12edfcea5aad7ff0509229154a2bfcb1d080ea5f Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Sat, 7 May 2016 21:00:30 +0200 Subject: [PATCH] Enough to run cpu_alu.prx. --- Core/MIPS/IR/IRCompALU.cpp | 56 +++++++++++++++++++++++++++++-- Core/MIPS/IR/IRCompBranch.cpp | 22 +++++++----- Core/MIPS/IR/IRInst.cpp | 19 +++++++++-- Core/MIPS/IR/IRJit.cpp | 26 ++++++++++---- Core/MIPS/IR/IRJit.h | 7 +++- Core/MIPS/JitCommon/JitCommon.cpp | 26 +++++++------- Core/MIPS/MIPSTables.cpp | 14 ++++++++ Core/MIPS/x86/Asm.cpp | 2 +- Core/MIPS/x86/Jit.cpp | 3 +- 9 files changed, 137 insertions(+), 38 deletions(-) diff --git a/Core/MIPS/IR/IRCompALU.cpp b/Core/MIPS/IR/IRCompALU.cpp index 69cf25de56..7c360082c9 100644 --- a/Core/MIPS/IR/IRCompALU.cpp +++ b/Core/MIPS/IR/IRCompALU.cpp @@ -153,7 +153,7 @@ void IRJit::CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, IROp op, IROp co } return; } - + /* if (gpr.IsImm(rt) || (gpr.IsImm(rs) && symmetric)) { MIPSGPReg lhs = gpr.IsImm(rs) ? rt : rs; MIPSGPReg rhs = gpr.IsImm(rs) ? rs : rt; @@ -167,7 +167,7 @@ void IRJit::CompType3(MIPSGPReg rd, MIPSGPReg rs, MIPSGPReg rt, IROp op, IROp co gpr.SetImm(rhs, rhsImm); } return; - } + }*/ // Can't do the RSB optimization on ARM64 - no RSB! @@ -343,7 +343,57 @@ void IRJit::Comp_ShiftType(MIPSOpcode op) { } void IRJit::Comp_Special3(MIPSOpcode op) { - DISABLE; + CONDITIONAL_DISABLE; + + MIPSGPReg rs = _RS; + MIPSGPReg rt = _RT; + + int pos = _POS; + int size = _SIZE + 1; + u32 mask = 0xFFFFFFFFUL >> (32 - size); + + // Don't change $zr. + if (rt == 0) + return; + + switch (op & 0x3f) { + case 0x0: //ext + if (gpr.IsImm(rs)) { + gpr.SetImm(rt, (gpr.GetImm(rs) >> pos) & mask); + return; + } + + gpr.MapDirtyIn(rt, rs); + ir.Write(IROp::Shl, rt, rs); + ir.Write(IROp::AndConst, rt, rt, ir.AddConstant(mask)); + break; + + case 0x4: //ins + { + u32 sourcemask = mask >> pos; + u32 destmask = ~(sourcemask << pos); + if (gpr.IsImm(rs)) { + u32 inserted = (gpr.GetImm(rs) & sourcemask) << pos; + if (gpr.IsImm(rt)) { + gpr.SetImm(rt, (gpr.GetImm(rt) & destmask) | inserted); + return; + } + + gpr.MapDirty(rt); + ir.Write(IROp::AndConst, rt, rt, ir.AddConstant(destmask)); + if (inserted != 0) { + ir.Write(IROp::OrConst, rt, rt, inserted); + } + } else { + gpr.MapDirtyIn(rt, rs); + ir.Write(IROp::AndConst, IRTEMP_0, rs, ir.AddConstant(sourcemask)); + ir.Write(IROp::AndConst, rt, rt, ir.AddConstant(destmask)); + ir.Write(IROp::ShlImm, IRTEMP_0, IRTEMP_0, pos); + ir.Write(IROp::Or, rt, rt, IRTEMP_0); + } + } + break; + } } void IRJit::Comp_Allegrex(MIPSOpcode op) { diff --git a/Core/MIPS/IR/IRCompBranch.cpp b/Core/MIPS/IR/IRCompBranch.cpp index 7d01d0b685..27fb5ae52d 100644 --- a/Core/MIPS/IR/IRCompBranch.cpp +++ b/Core/MIPS/IR/IRCompBranch.cpp @@ -72,12 +72,14 @@ void IRJit::BranchRSRTComp(MIPSOpcode op, IRComparison cc, bool likely) MIPSGPReg lhs = rs; MIPSGPReg rhs = rt; - if (!delaySlotIsNice && !likely) { // if likely, we don't need this + if (!delaySlotIsNice) { // if likely, we don't need this if (rs != 0) { + gpr.MapIn(rs); ir.Write(IROp::Mov, IRTEMP_0, rs); lhs = (MIPSGPReg)IRTEMP_0; } if (rt != 0) { + gpr.MapIn(rt); ir.Write(IROp::Mov, IRTEMP_1, rt); rhs = (MIPSGPReg)IRTEMP_1; } @@ -113,21 +115,22 @@ void IRJit::BranchRSZeroComp(MIPSOpcode op, IRComparison cc, bool andLink, bool ir.Write(IROp::Downcount, 0, js.downcountAmount & 0xFF, js.downcountAmount >> 8); - if (!likely && delaySlotIsNice) - CompileDelaySlot(); - int lhs = rs; - gpr.MapIn(rs); - if (!delaySlotIsNice && !likely) { // if likely, we don't need this + MIPSGPReg lhs = rs; + if (!delaySlotIsNice) { // if likely, we don't need this ir.Write(IROp::Mov, IRTEMP_0, rs); - lhs = IRTEMP_0; + lhs = (MIPSGPReg)IRTEMP_0; } if (andLink) gpr.SetImm(MIPS_REG_RA, GetCompilerPC() + 8); + + if (!likely) + CompileDelaySlot(); + + gpr.MapIn(lhs); FlushAll(); ir.Write(ComparisonToExit(cc), ir.AddConstant(GetCompilerPC() + 8), lhs); - if (likely) { + if (likely) CompileDelaySlot(); - } // Taken FlushAll(); ir.Write(IROp::ExitToConst, ir.AddConstant(targetAddr)); @@ -327,6 +330,7 @@ void IRJit::Comp_JumpReg(MIPSOpcode op) { if (andLink) gpr.SetImm(rd, GetCompilerPC() + 8); CompileDelaySlot(); + // Syscall (the delay slot) does FlushAll. return; // Syscall (delay slot) wrote exit code. } else if (delaySlotIsNice) { if (andLink) diff --git a/Core/MIPS/IR/IRInst.cpp b/Core/MIPS/IR/IRInst.cpp index 1e0cdabf0b..fc4a07a2ec 100644 --- a/Core/MIPS/IR/IRInst.cpp +++ b/Core/MIPS/IR/IRInst.cpp @@ -170,13 +170,13 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, const u32 *constPool, int c break; case IROp::ShlImm: - mips->r[inst->dest] = mips->r[inst->src1] << inst->src2; + mips->r[inst->dest] = mips->r[inst->src1] << (int)inst->src2; break; case IROp::ShrImm: - mips->r[inst->dest] = mips->r[inst->src1] >> inst->src2; + mips->r[inst->dest] = mips->r[inst->src1] >> (int)inst->src2; break; case IROp::SarImm: - mips->r[inst->dest] = (s32)mips->r[inst->src1] >> inst->src2; + mips->r[inst->dest] = (s32)mips->r[inst->src1] >> (int)inst->src2; break; case IROp::RorImm: { @@ -203,6 +203,19 @@ u32 IRInterpret(MIPSState *mips, const IRInst *inst, const u32 *constPool, int c } break; + case IROp::Clz: + { + int x = 31; + int count = 0; + int value = mips->r[inst->src1]; + while (x >= 0 && !(value & (1 << x))) { + count++; + x--; + } + mips->r[inst->dest] = count; + break; + } + case IROp::Slt: mips->r[inst->dest] = (s32)mips->r[inst->src1] < (s32)mips->r[inst->src2]; break; diff --git a/Core/MIPS/IR/IRJit.cpp b/Core/MIPS/IR/IRJit.cpp index 7fae3255c3..d99cebfc3e 100644 --- a/Core/MIPS/IR/IRJit.cpp +++ b/Core/MIPS/IR/IRJit.cpp @@ -48,7 +48,7 @@ IRJit::IRJit(MIPSState *mips) : gpr(), mips_(mips) { js.currentRoundingFunc = convertS0ToSCRATCH1[0]; u32 size = 128 * 1024; blTrampolines_ = kernelMemory.Alloc(size, true, "trampoline"); - logBlocks = 100; + logBlocks = 0; InitIR(); } @@ -184,6 +184,12 @@ void IRJit::RunLoopUntil(u64 globalticks) { // ApplyRoundingMode(true); // IR Dispatcher + FILE *f; + int numBlocks = 0; + if (numBlocks) { + f = fopen("E:\\blockir.txt", "w"); + } + while (true) { // RestoreRoundingMode(true); CoreTiming::Advance(); @@ -197,11 +203,18 @@ void IRJit::RunLoopUntil(u64 globalticks) { u32 data = inst & 0xFFFFFF; if (opcode == (MIPS_EMUHACK_OPCODE >> 24)) { IRBlock *block = blocks_.GetBlock(data); - ILOG("Run block at %08x : v1=%08x a0=%08x", mips_->pc, mips_->r[MIPS_REG_V1], mips_->r[MIPS_REG_A0]); + if (numBlocks > 0) { + // ILOG("Run block at %08x : v1=%08x a0=%08x", mips_->pc, mips_->r[MIPS_REG_V1], mips_->r[MIPS_REG_A0]); + fprintf(f, "BLOCK : %08x v0: %08x v1: %08x a0: %08x s0: %08x s4: %08x\n", mips_->pc, mips_->r[MIPS_REG_V0], mips_->r[MIPS_REG_V1], mips_->r[MIPS_REG_A0], mips_->r[MIPS_REG_S0], mips_->r[MIPS_REG_S4]); + fflush(f); + numBlocks--; + } mips_->pc = IRInterpret(mips_, block->GetInstructions(), block->GetConstants(), block->GetNumInstructions()); } else { + if (mips_->pc == 0x0880de94) + logBlocks = 10; // RestoreRoundingMode(true); - ILOG("Compile block at %08x : v1=%08x a0=%08x", mips_->pc, mips_->r[MIPS_REG_V1], mips_->r[MIPS_REG_A0]); + // ILOG("Compile block at %08x : v1=%08x a0=%08x", mips_->pc, mips_->r[MIPS_REG_V1], mips_->r[MIPS_REG_A0]); Compile(mips_->pc); // ApplyRoundingMode(true); } @@ -252,7 +265,7 @@ void IRJit::DoJit(u32 em_address, IRBlock *b) { if (logBlocks > 0 && dontLogBlocks == 0) { char temp2[256]; - ILOG("=============== mips %d ===============", blocks_.GetNumBlocks()); + ILOG("=============== mips %d %08x ===============", blocks_.GetNumBlocks(), em_address); for (u32 cpc = em_address; cpc != GetCompilerPC() + 4; cpc += 4) { temp2[0] = 0; MIPSDisAsm(Memory::Read_Opcode_JIT(cpc), cpc, temp2, true); @@ -304,7 +317,8 @@ void IRJit::Comp_ReplacementFunc(MIPSOpcode op) { } void IRJit::Comp_Generic(MIPSOpcode op) { - ir.Write(IROp::Interpret, ir.AddConstant(op.encoding)); + FlushAll(); + ir.Write(IROp::Interpret, 0, ir.AddConstant(op.encoding)); const MIPSInfo info = MIPSGetInfo(op); if ((info & IS_VFPU) != 0 && (info & VFPU_NO_PREFIX) == 0) { // If it does eat them, it'll happen in MIPSCompileOp(). @@ -351,7 +365,7 @@ void IRBlockCache::InvalidateICache(u32 addess, u32 length) { } void IRBlock::Finalize(int number) { - origFirstOpcode_= Memory::Read_Opcode_JIT(origAddr_); + origFirstOpcode_ = Memory::Read_Opcode_JIT(origAddr_); MIPSOpcode opcode = MIPSOpcode(MIPS_EMUHACK_OPCODE | number); Memory::Write_Opcode_JIT(origAddr_, opcode); } diff --git a/Core/MIPS/IR/IRJit.h b/Core/MIPS/IR/IRJit.h index 440e96d282..63badb5ce2 100644 --- a/Core/MIPS/IR/IRJit.h +++ b/Core/MIPS/IR/IRJit.h @@ -42,6 +42,7 @@ public: numInstructions_ = b.numInstructions_; numConstants_ = b.numConstants_; origAddr_ = b.origAddr_; + origFirstOpcode_ = b.origFirstOpcode_; b.instr_ = nullptr; b.const_ = nullptr; } @@ -86,7 +87,11 @@ public: return (int)blocks_.size() - 1; } IRBlock *GetBlock(int i) { - return &blocks_[i]; + if (i >= 0 && i < blocks_.size()) { + return &blocks_[i]; + } else { + return nullptr; + } } private: std::vector blocks_; diff --git a/Core/MIPS/JitCommon/JitCommon.cpp b/Core/MIPS/JitCommon/JitCommon.cpp index 0b7fc19322..630494f973 100644 --- a/Core/MIPS/JitCommon/JitCommon.cpp +++ b/Core/MIPS/JitCommon/JitCommon.cpp @@ -47,21 +47,21 @@ namespace MIPSComp { } JitInterface *CreateNativeJit(MIPSState *mips) { - if (false && g_Config.iCpuCore == (int)CPUCore::CPU_JIT) { -#if defined(ARM) - return new MIPSComp::ArmJit(mips); -#elif defined(ARM64) - return new MIPSComp::IRJit(mips); -#elif defined(_M_IX86) || defined(_M_X64) - return new MIPSComp::Jit(mips); -#elif defined(MIPS) - return new MIPSComp::MipsJit(mips); +#if 1 + return new MIPSComp::IRJit(mips); #else - return new MIPSComp::FakeJit(mips); +#if defined(ARM) + return new MIPSComp::ArmJit(mips); +#elif defined(ARM64) + return new MIPSComp::IRJit(mips); +#elif defined(_M_IX86) || defined(_M_X64) + return new MIPSComp::Jit(mips); +#elif defined(MIPS) + return new MIPSComp::MipsJit(mips); +#else + return new MIPSComp::FakeJit(mips); +#endif #endif - } else if (true || g_Config.iCpuCore == (int)CPUCore::CPU_IRJIT) { - return new MIPSComp::IRJit(mips); - } } } diff --git a/Core/MIPS/MIPSTables.cpp b/Core/MIPS/MIPSTables.cpp index 39038df6ae..c5ef44bc0d 100644 --- a/Core/MIPS/MIPSTables.cpp +++ b/Core/MIPS/MIPSTables.cpp @@ -28,6 +28,7 @@ #include "Core/CoreTiming.h" #include "Core/Reporting.h" #include "Core/Debugger/Breakpoints.h" +#include "base/logging.h" #include "JitCommon/JitCommon.h" @@ -973,10 +974,13 @@ void MIPSInterpret(MIPSOpcode op) { int MIPSInterpret_RunUntil(u64 globalTicks) { + int blockCount = 150000; + FILE *f = fopen("E:\\blockjit.txt", "w"); MIPSState *curMips = currentMIPS; while (coreState == CORE_RUNNING) { CoreTiming::Advance(); + u32 lastPC = 0; // NEVER stop in a delay slot! while (curMips->downcount >= 0 && coreState == CORE_RUNNING) @@ -1015,6 +1019,16 @@ int MIPSInterpret_RunUntil(u64 globalTicks) bool wasInDelaySlot = curMips->inDelaySlot; + if (curMips->pc != lastPC + 4) { + if (blockCount > 0) { + MIPSState *mips_ = curMips; + fprintf(f, "BLOCK : %08x v0: %08x v1: %08x a0: %08x s0: %08x s4: %08x\n", mips_->pc, mips_->r[MIPS_REG_V0], mips_->r[MIPS_REG_V1], mips_->r[MIPS_REG_A0], mips_->r[MIPS_REG_S0], mips_->r[MIPS_REG_S4]); + fflush(f); + blockCount--; + } + } + lastPC = curMips->pc; + MIPSInterpret(op); if (curMips->inDelaySlot) diff --git a/Core/MIPS/x86/Asm.cpp b/Core/MIPS/x86/Asm.cpp index 6d03ba5f6f..86dfc1d7fb 100644 --- a/Core/MIPS/x86/Asm.cpp +++ b/Core/MIPS/x86/Asm.cpp @@ -40,7 +40,7 @@ namespace MIPSComp //TODO - make an option //#if _DEBUG -static bool enableDebug = false; + static bool enableDebug = true; //#else // bool enableDebug = false; diff --git a/Core/MIPS/x86/Jit.cpp b/Core/MIPS/x86/Jit.cpp index c2c01a56f4..4bfce6814e 100644 --- a/Core/MIPS/x86/Jit.cpp +++ b/Core/MIPS/x86/Jit.cpp @@ -81,8 +81,7 @@ u32 JitBreakpoint() host->SetDebugMode(true); // There's probably a better place for this. - if (USE_JIT_MISSMAP) - { + if (USE_JIT_MISSMAP) { std::map notJitSorted; std::transform(notJitOps.begin(), notJitOps.end(), std::inserter(notJitSorted, notJitSorted.begin()), flip_pair);