From 22b86e64f5583dcfb59270bc2bee45354ded88f2 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 21 Dec 2013 19:10:04 -0600 Subject: [PATCH 1/5] redo 'jit: change our linking module to be able to handle arbitrary exit addresses' --- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 35 ++++++++++--------- Source/Core/Core/PowerPC/Jit64/Jit.h | 2 +- Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp | 10 +++--- .../Core/Core/PowerPC/Jit64/Jit_Integer.cpp | 10 +++--- .../Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp | 2 +- .../PowerPC/Jit64/Jit_SystemRegisters.cpp | 2 +- Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp | 13 +++---- Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp | 19 ++++++---- Source/Core/Core/PowerPC/Jit64IL/JitIL.h | 4 +-- Source/Core/Core/PowerPC/JitArm32/Jit.cpp | 13 ++++--- Source/Core/Core/PowerPC/JitArm32/Jit.h | 2 +- .../Core/PowerPC/JitArm32/JitArm_Branch.cpp | 10 +++--- .../PowerPC/JitArm32/JitArm_LoadStore.cpp | 2 +- .../JitArm32/JitArm_SystemRegisters.cpp | 2 +- Source/Core/Core/PowerPC/JitArmIL/IR_Arm.cpp | 11 +++--- Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp | 15 ++++---- Source/Core/Core/PowerPC/JitArmIL/JitIL.h | 4 +-- .../Core/Core/PowerPC/JitCommon/JitCache.cpp | 29 ++++++--------- Source/Core/Core/PowerPC/JitCommon/JitCache.h | 11 +++--- 19 files changed, 103 insertions(+), 93 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 394c7bc86a..0e66510264 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -276,7 +276,7 @@ void Jit64::Cleanup() ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst); } -void Jit64::WriteExit(u32 destination, int exit_num) +void Jit64::WriteExit(u32 destination) { Cleanup(); @@ -284,23 +284,26 @@ void Jit64::WriteExit(u32 destination, int exit_num) //If nobody has taken care of this yet (this can be removed when all branches are done) JitBlock *b = js.curBlock; - b->exitAddress[exit_num] = destination; - b->exitPtrs[exit_num] = GetWritableCodePtr(); + JitBlock::LinkData linkData; + linkData.exitAddress = destination; + linkData.exitPtrs = GetWritableCodePtr(); + linkData.linkStatus = false; // Link opportunity! - if (jo.enableBlocklink) + int block = blocks.GetBlockNumberFromStartAddress(destination); + if (block >= 0 && jo.enableBlocklink) { - int block = blocks.GetBlockNumberFromStartAddress(destination); - if (block >= 0) - { - // It exists! Joy of joy! - JMP(blocks.GetBlock(block)->checkedEntry, true); - b->linkStatus[exit_num] = true; - return; - } + // It exists! Joy of joy! + JMP(blocks.GetBlock(block)->checkedEntry, true); + linkData.linkStatus = true; } - MOV(32, M(&PC), Imm32(destination)); - JMP(asm_routines.dispatcher, true); + else + { + MOV(32, M(&PC), Imm32(destination)); + JMP(asm_routines.dispatcher, true); + } + + b->linkData.push_back(linkData); } void Jit64::WriteExitDestInEAX() @@ -625,7 +628,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF)); FixupBranch noBreakpoint = J_CC(CC_Z); - WriteExit(ops[i].address, 0); + WriteExit(ops[i].address); SetJumpTarget(noBreakpoint); } @@ -707,7 +710,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc { gpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL); - WriteExit(nextPC, 0); + WriteExit(nextPC); } b->flags = js.block_flags; diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.h b/Source/Core/Core/PowerPC/Jit64/Jit.h index dbec3e0174..4f00aac342 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/PowerPC/Jit64/Jit.h @@ -88,7 +88,7 @@ public: // Utilities for use by opcodes - void WriteExit(u32 destination, int exit_num); + void WriteExit(u32 destination); void WriteExitDestInEAX(); void WriteExceptionExit(); void WriteExternalExceptionExit(); diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp index b0f3f1cd18..a1e28ac6ea 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Branch.cpp @@ -91,7 +91,7 @@ void Jit64::bx(UGeckoInstruction inst) // make idle loops go faster js.downcountAmount += 8; } - WriteExit(destination, 0); + WriteExit(destination); } // TODO - optimize to hell and beyond @@ -136,13 +136,13 @@ void Jit64::bcx(UGeckoInstruction inst) destination = SignExt16(inst.BD << 2); else destination = js.compilerPC + SignExt16(inst.BD << 2); - WriteExit(destination, 0); + WriteExit(destination); if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) SetJumpTarget( pConditionDontBranch ); if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) SetJumpTarget( pCTRDontBranch ); - WriteExit(js.compilerPC + 4, 1); + WriteExit(js.compilerPC + 4); } void Jit64::bcctrx(UGeckoInstruction inst) @@ -190,7 +190,7 @@ void Jit64::bcctrx(UGeckoInstruction inst) WriteExitDestInEAX(); // Would really like to continue the block here, but it ends. TODO. SetJumpTarget(b); - WriteExit(js.compilerPC + 4, 1); + WriteExit(js.compilerPC + 4); } } @@ -245,5 +245,5 @@ void Jit64::bclrx(UGeckoInstruction inst) SetJumpTarget( pConditionDontBranch ); if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) SetJumpTarget( pCTRDontBranch ); - WriteExit(js.compilerPC + 4, 1); + WriteExit(js.compilerPC + 4); } diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp index 696bf398f1..60fcc796d3 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_Integer.cpp @@ -400,7 +400,7 @@ void Jit64::cmpXX(UGeckoInstruction inst) destination = SignExt16(js.next_inst.BD << 2); else destination = js.next_compilerPC + SignExt16(js.next_inst.BD << 2); - WriteExit(destination, 0); + WriteExit(destination); } else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528)) // bcctrx { @@ -424,7 +424,7 @@ void Jit64::cmpXX(UGeckoInstruction inst) } else { - WriteExit(js.next_compilerPC + 4, 0); + WriteExit(js.next_compilerPC + 4); } js.cancel = true; @@ -507,7 +507,7 @@ void Jit64::cmpXX(UGeckoInstruction inst) destination = SignExt16(js.next_inst.BD << 2); else destination = js.next_compilerPC + SignExt16(js.next_inst.BD << 2); - WriteExit(destination, 0); + WriteExit(destination); } else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528)) // bcctrx { @@ -534,7 +534,7 @@ void Jit64::cmpXX(UGeckoInstruction inst) if (!!(4 & test_bit) == condition) SetJumpTarget(continue2); if (!!(2 & test_bit) == condition) SetJumpTarget(continue1); - WriteExit(js.next_compilerPC + 4, 1); + WriteExit(js.next_compilerPC + 4); js.cancel = true; } @@ -2221,5 +2221,5 @@ void Jit64::twx(UGeckoInstruction inst) SetJumpTarget(exit3); SetJumpTarget(exit4); SetJumpTarget(exit5); - WriteExit(js.compilerPC + 4, 1); + WriteExit(js.compilerPC + 4); } diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp index a1c3bd971c..1b41c2f1e9 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_LoadStore.cpp @@ -480,5 +480,5 @@ void Jit64::stmw(UGeckoInstruction inst) void Jit64::icbi(UGeckoInstruction inst) { Default(inst); - WriteExit(js.compilerPC + 4, 0); + WriteExit(js.compilerPC + 4); } diff --git a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp index f2e6d70b90..e5aa46e749 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit_SystemRegisters.cpp @@ -125,7 +125,7 @@ void Jit64::mtmsr(UGeckoInstruction inst) SetJumpTarget(noExceptionsPending); SetJumpTarget(eeDisabled); - WriteExit(js.compilerPC + 4, 0); + WriteExit(js.compilerPC + 4); js.firstFPInstructionFound = false; } diff --git a/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp index 5c9d2075a8..6d1723b0fe 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp +++ b/Source/Core/Core/PowerPC/Jit64IL/IR_X86.cpp @@ -554,7 +554,8 @@ static void regEmitICmpInst(RegInfo& RI, InstLoc I, CCFlags flag) { static void regWriteExit(RegInfo& RI, InstLoc dest) { if (isImm(*dest)) { - RI.Jit->WriteExit(RI.Build->GetImmValue(dest), RI.exitNumber++); + RI.exitNumber++; + RI.Jit->WriteExit(RI.Build->GetImmValue(dest)); } else { RI.Jit->WriteExitDestInOpArg(regLocForInst(RI, dest)); } @@ -566,7 +567,7 @@ static bool checkIsSNAN() { return MathUtil::IsSNAN(isSNANTemp[0][0]) || MathUtil::IsSNAN(isSNANTemp[1][0]); } -static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit) { +static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) { //printf("Writing block: %x\n", js.blockStart); RegInfo RI(Jit, ibuild->getFirstInst(), ibuild->getNumInsts()); RI.Build = ibuild; @@ -1793,7 +1794,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit) { Jit->ABI_CallFunction(reinterpret_cast(&PowerPC::CheckBreakPoints)); Jit->TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF)); FixupBranch noBreakpoint = Jit->J_CC(CC_Z); - Jit->WriteExit(InstLoc, 0); + Jit->WriteExit(InstLoc); Jit->SetJumpTarget(noBreakpoint); break; } @@ -1821,10 +1822,10 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit) { } } - Jit->WriteExit(jit->js.curBlock->exitAddress[0], 0); + Jit->WriteExit(exitAddress); Jit->UD2(); } -void JitIL::WriteCode() { - DoWriteCode(&ibuild, this); +void JitIL::WriteCode(u32 exitAddress) { + DoWriteCode(&ibuild, this, exitAddress); } diff --git a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp index b15ffbacca..36ac5a3789 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp @@ -381,7 +381,7 @@ void JitIL::Cleanup() ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst); } -void JitIL::WriteExit(u32 destination, int exit_num) +void JitIL::WriteExit(u32 destination) { Cleanup(); if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) { @@ -391,8 +391,10 @@ void JitIL::WriteExit(u32 destination, int exit_num) //If nobody has taken care of this yet (this can be removed when all branches are done) JitBlock *b = js.curBlock; - b->exitAddress[exit_num] = destination; - b->exitPtrs[exit_num] = GetWritableCodePtr(); + JitBlock::LinkData linkData; + linkData.exitAddress = destination; + linkData.exitPtrs = GetWritableCodePtr(); + linkData.linkStatus = false; // Link opportunity! int block = blocks.GetBlockNumberFromStartAddress(destination); @@ -400,13 +402,14 @@ void JitIL::WriteExit(u32 destination, int exit_num) { // It exists! Joy of joy! JMP(blocks.GetBlock(block)->checkedEntry, true); - b->linkStatus[exit_num] = true; + linkData.linkStatus = true; } else { MOV(32, M(&PC), Imm32(destination)); JMP(asm_routines.dispatcher, true); } + b->linkData.push_back(linkData); } void JitIL::WriteExitDestInOpArg(const Gen::OpArg& arg) @@ -541,14 +544,16 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc // Analyze the block, collect all instructions it is made of (including inlining, // if that is enabled), reorder instructions for optimal performance, and join joinable instructions. - b->exitAddress[0] = em_address; + u32 exitAddress = em_address; + u32 merged_addresses[32]; const int capacity_of_merged_addresses = sizeof(merged_addresses) / sizeof(merged_addresses[0]); int size_of_merged_addresses = 0; if (!memory_exception) { // If there is a memory exception inside a block (broken_block==true), compile up to that instruction. - b->exitAddress[0] = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, broken_block, code_buf, blockSize, merged_addresses, capacity_of_merged_addresses, size_of_merged_addresses); + // TODO + exitAddress = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, broken_block, code_buf, blockSize, merged_addresses, capacity_of_merged_addresses, size_of_merged_addresses); } PPCAnalyst::CodeOp *ops = code_buf->codebuffer; @@ -707,7 +712,7 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc } // Perform actual code generation - WriteCode(); + WriteCode(exitAddress); b->codeSize = (u32)(GetCodePtr() - normalEntry); b->originalSize = size; diff --git a/Source/Core/Core/PowerPC/Jit64IL/JitIL.h b/Source/Core/Core/PowerPC/Jit64IL/JitIL.h index 2e5e382e5d..fab95f4687 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/JitIL.h +++ b/Source/Core/Core/PowerPC/Jit64IL/JitIL.h @@ -95,7 +95,7 @@ public: // Utilities for use by opcodes - void WriteExit(u32 destination, int exit_num); + void WriteExit(u32 destination); void WriteExitDestInOpArg(const Gen::OpArg& arg); void WriteExceptionExit(); void WriteRfiExitDestInOpArg(const Gen::OpArg& arg); @@ -111,7 +111,7 @@ public: void regimmop(int d, int a, bool binary, u32 value, Operation doop, void (Gen::XEmitter::*op)(int, const Gen::OpArg&, const Gen::OpArg&), bool Rc = false, bool carry = false); void fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (Gen::XEmitter::*op)(Gen::X64Reg, Gen::OpArg)); - void WriteCode(); + void WriteCode(u32 exitAddress); // OPCODES void unknown_instruction(UGeckoInstruction _inst) override; diff --git a/Source/Core/Core/PowerPC/JitArm32/Jit.cpp b/Source/Core/Core/PowerPC/JitArm32/Jit.cpp index 4083a383e9..eab7f3711a 100644 --- a/Source/Core/Core/PowerPC/JitArm32/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm32/Jit.cpp @@ -186,15 +186,16 @@ void JitArm::WriteExceptionExit() MOVI2R(A, (u32)asm_routines.testExceptions); B(A); } -void JitArm::WriteExit(u32 destination, int exit_num) +void JitArm::WriteExit(u32 destination) { Cleanup(); DoDownCount(); //If nobody has taken care of this yet (this can be removed when all branches are done) JitBlock *b = js.curBlock; - b->exitAddress[exit_num] = destination; - b->exitPtrs[exit_num] = GetWritableCodePtr(); + JitBlock::LinkData linkData; + linkData.exitAddress = destination; + linkData.exitPtrs = GetWritableCodePtr(); // Link opportunity! int block = blocks.GetBlockNumberFromStartAddress(destination); @@ -202,7 +203,7 @@ void JitArm::WriteExit(u32 destination, int exit_num) { // It exists! Joy of joy! B(blocks.GetBlock(block)->checkedEntry); - b->linkStatus[exit_num] = true; + linkData.linkStatus = true; } else { @@ -212,6 +213,8 @@ void JitArm::WriteExit(u32 destination, int exit_num) MOVI2R(A, (u32)asm_routines.dispatcher); B(A); } + + b->linkData.push_back(linkData); } void STACKALIGN JitArm::Run() @@ -496,7 +499,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo if (broken_block) { printf("Broken Block going to 0x%08x\n", nextPC); - WriteExit(nextPC, 0); + WriteExit(nextPC); } b->flags = js.block_flags; diff --git a/Source/Core/Core/PowerPC/JitArm32/Jit.h b/Source/Core/Core/PowerPC/JitArm32/Jit.h index 7e29964645..0e9e8fe3b2 100644 --- a/Source/Core/Core/PowerPC/JitArm32/Jit.h +++ b/Source/Core/Core/PowerPC/JitArm32/Jit.h @@ -101,7 +101,7 @@ public: // Utilities for use by opcodes - void WriteExit(u32 destination, int exit_num); + void WriteExit(u32 destination); void WriteExitDestInR(ARMReg Reg); void WriteRfiExitDestInR(ARMReg Reg); void WriteExceptionExit(); diff --git a/Source/Core/Core/PowerPC/JitArm32/JitArm_Branch.cpp b/Source/Core/Core/PowerPC/JitArm32/JitArm_Branch.cpp index 4e9101f7b2..eac488a5b0 100644 --- a/Source/Core/Core/PowerPC/JitArm32/JitArm_Branch.cpp +++ b/Source/Core/Core/PowerPC/JitArm32/JitArm_Branch.cpp @@ -154,7 +154,7 @@ void JitArm::bx(UGeckoInstruction inst) MOVI2R(R14, (u32)asm_routines.testExceptions); B(R14); } - WriteExit(destination, 0); + WriteExit(destination); } void JitArm::bcx(UGeckoInstruction inst) @@ -209,14 +209,14 @@ void JitArm::bcx(UGeckoInstruction inst) destination = SignExt16(inst.BD << 2); else destination = js.compilerPC + SignExt16(inst.BD << 2); - WriteExit(destination, 0); + WriteExit(destination); if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) SetJumpTarget( pConditionDontBranch ); if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) SetJumpTarget( pCTRDontBranch ); - WriteExit(js.compilerPC + 4, 1); + WriteExit(js.compilerPC + 4); } void JitArm::bcctrx(UGeckoInstruction inst) { @@ -278,7 +278,7 @@ void JitArm::bcctrx(UGeckoInstruction inst) WriteExitDestInR(rA); SetJumpTarget(b); - WriteExit(js.compilerPC + 4, 1); + WriteExit(js.compilerPC + 4); } } void JitArm::bclrx(UGeckoInstruction inst) @@ -355,5 +355,5 @@ void JitArm::bclrx(UGeckoInstruction inst) SetJumpTarget( pConditionDontBranch ); if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) SetJumpTarget( pCTRDontBranch ); - WriteExit(js.compilerPC + 4, 1); + WriteExit(js.compilerPC + 4); } diff --git a/Source/Core/Core/PowerPC/JitArm32/JitArm_LoadStore.cpp b/Source/Core/Core/PowerPC/JitArm32/JitArm_LoadStore.cpp index f04c88d6c3..3983772aa6 100644 --- a/Source/Core/Core/PowerPC/JitArm32/JitArm_LoadStore.cpp +++ b/Source/Core/Core/PowerPC/JitArm32/JitArm_LoadStore.cpp @@ -531,6 +531,6 @@ void JitArm::dcbst(UGeckoInstruction inst) void JitArm::icbi(UGeckoInstruction inst) { Default(inst); - WriteExit(js.compilerPC + 4, 0); + WriteExit(js.compilerPC + 4); } diff --git a/Source/Core/Core/PowerPC/JitArm32/JitArm_SystemRegisters.cpp b/Source/Core/Core/PowerPC/JitArm32/JitArm_SystemRegisters.cpp index e4ab630fce..62b15e1d5e 100644 --- a/Source/Core/Core/PowerPC/JitArm32/JitArm_SystemRegisters.cpp +++ b/Source/Core/Core/PowerPC/JitArm32/JitArm_SystemRegisters.cpp @@ -205,7 +205,7 @@ void JitArm::mtmsr(UGeckoInstruction inst) gpr.Flush(); fpr.Flush(); - WriteExit(js.compilerPC + 4, 0); + WriteExit(js.compilerPC + 4); } void JitArm::mfmsr(UGeckoInstruction inst) diff --git a/Source/Core/Core/PowerPC/JitArmIL/IR_Arm.cpp b/Source/Core/Core/PowerPC/JitArmIL/IR_Arm.cpp index 10620d9183..c1bee507fc 100644 --- a/Source/Core/Core/PowerPC/JitArmIL/IR_Arm.cpp +++ b/Source/Core/Core/PowerPC/JitArmIL/IR_Arm.cpp @@ -156,7 +156,8 @@ static ARMReg regEnsureInReg(RegInfo& RI, InstLoc I) { static void regWriteExit(RegInfo& RI, InstLoc dest) { if (isImm(*dest)) { - RI.Jit->WriteExit(RI.Build->GetImmValue(dest), RI.exitNumber++); + RI.exitNumber++; + RI.Jit->WriteExit(RI.Build->GetImmValue(dest)); } else { RI.Jit->WriteExitDestInReg(regLocForInst(RI, dest)); } @@ -281,7 +282,7 @@ static void regEmitCmp(RegInfo& RI, InstLoc I) { } } -static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit) { +static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit, u32 exitAddress) { RegInfo RI(Jit, ibuild->getFirstInst(), ibuild->getNumInsts()); RI.Build = ibuild; @@ -733,10 +734,10 @@ static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit) { } } - Jit->WriteExit(jit->js.curBlock->exitAddress[0], 0); + Jit->WriteExit(exitAddress); Jit->BKPT(0x111); } -void JitArmIL::WriteCode() { - DoWriteCode(&ibuild, this); +void JitArmIL::WriteCode(u32 exitAddress) { + DoWriteCode(&ibuild, this, exitAddress); } diff --git a/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp b/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp index 0aac4d6722..44ebc8b6eb 100644 --- a/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp +++ b/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp @@ -117,13 +117,14 @@ void JitArmIL::WriteExceptionExit() MOVI2R(R14, (u32)asm_routines.testExceptions); B(R14); } -void JitArmIL::WriteExit(u32 destination, int exit_num) +void JitArmIL::WriteExit(u32 destination) { DoDownCount(); //If nobody has taken care of this yet (this can be removed when all branches are done) JitBlock *b = js.curBlock; - b->exitAddress[exit_num] = destination; - b->exitPtrs[exit_num] = GetWritableCodePtr(); + JitBlock::LinkData linkData; + linkData.exitAddress = destination; + linkData.exitPtrs = GetWritableCodePtr(); // Link opportunity! int block = blocks.GetBlockNumberFromStartAddress(destination); @@ -131,7 +132,7 @@ void JitArmIL::WriteExit(u32 destination, int exit_num) { // It exists! Joy of joy! B(blocks.GetBlock(block)->checkedEntry); - b->linkStatus[exit_num] = true; + linkData.linkStatus = true; } else { @@ -140,6 +141,8 @@ void JitArmIL::WriteExit(u32 destination, int exit_num) MOVI2R(R14, (u32)asm_routines.dispatcher); B(R14); } + + b->linkData.push_back(linkData); } void JitArmIL::PrintDebug(UGeckoInstruction inst, u32 level) { @@ -347,12 +350,12 @@ const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB if (broken_block) { printf("Broken Block going to 0x%08x\n", nextPC); - WriteExit(nextPC, 0); + WriteExit(nextPC); } // Perform actual code generation - WriteCode(); + WriteCode(nextPC); b->flags = js.block_flags; b->codeSize = (u32)(GetCodePtr() - normalEntry); b->originalSize = size; diff --git a/Source/Core/Core/PowerPC/JitArmIL/JitIL.h b/Source/Core/Core/PowerPC/JitArmIL/JitIL.h index 595e1dc526..416dfaf3ac 100644 --- a/Source/Core/Core/PowerPC/JitArmIL/JitIL.h +++ b/Source/Core/Core/PowerPC/JitArmIL/JitIL.h @@ -58,8 +58,8 @@ public: void Run(); void SingleStep(); // - void WriteCode(); - void WriteExit(u32 destination, int exit_num); + void WriteCode(u32 exitAddress); + void WriteExit(u32 destination); void WriteExitDestInReg(ARMReg Reg); void WriteRfiExitDestInR(ARMReg Reg); void WriteExceptionExit(); diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp index a7efa3d1c4..0dd0c63d8b 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp @@ -35,8 +35,6 @@ op_agent_t agent; using namespace Gen; -#define INVALID_EXIT 0xFFFFFFFF - bool JitBaseBlockCache::IsFull() const { return GetNumBlocks() >= MAX_NUM_BLOCKS - 1; @@ -167,12 +165,6 @@ using namespace Gen; JitBlock &b = blocks[num_blocks]; b.invalid = false; b.originalAddress = em_address; - b.exitAddress[0] = INVALID_EXIT; - b.exitAddress[1] = INVALID_EXIT; - b.exitPtrs[0] = 0; - b.exitPtrs[1] = 0; - b.linkStatus[0] = false; - b.linkStatus[1] = false; num_blocks++; //commit the current block return num_blocks - 1; } @@ -193,10 +185,9 @@ using namespace Gen; block_map[std::make_pair(pAddr + 4 * b.originalSize - 1, pAddr)] = block_num; if (block_link) { - for (int i = 0; i < 2; i++) + for (const auto& e : b.linkData) { - if (b.exitAddress[i] != INVALID_EXIT) - links_to.insert(std::pair(b.exitAddress[i], block_num)); + links_to.insert(std::pair(e.exitAddress, block_num)); } LinkBlock(block_num); @@ -275,15 +266,15 @@ using namespace Gen; // This block is dead. Don't relink it. return; } - for (int e = 0; e < 2; e++) + for (auto& e : b.linkData) { - if (b.exitAddress[e] != INVALID_EXIT && !b.linkStatus[e]) + if (!e.linkStatus) { - int destinationBlock = GetBlockNumberFromStartAddress(b.exitAddress[e]); + int destinationBlock = GetBlockNumberFromStartAddress(e.exitAddress); if (destinationBlock != -1) { - WriteLinkBlock(b.exitPtrs[e], blocks[destinationBlock].checkedEntry); - b.linkStatus[e] = true; + WriteLinkBlock(e.exitPtrs, blocks[destinationBlock].checkedEntry); + e.linkStatus = true; } } } @@ -316,10 +307,10 @@ using namespace Gen; return; for (multimap::iterator iter = ppp.first; iter != ppp.second; ++iter) { JitBlock &sourceBlock = blocks[iter->second]; - for (int e = 0; e < 2; e++) + for (auto& e : sourceBlock.linkData) { - if (sourceBlock.exitAddress[e] == b.originalAddress) - sourceBlock.linkStatus[e] = false; + if (e.exitAddress == b.originalAddress) + e.linkStatus = false; } } } diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.h b/Source/Core/Core/PowerPC/JitCommon/JitCache.h index f795a020a7..b1d7d9b6d7 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.h +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.h @@ -34,9 +34,6 @@ struct JitBlock const u8 *checkedEntry; const u8 *normalEntry; - u8 *exitPtrs[2]; // to be able to rewrite the exit jum - u32 exitAddress[2]; // 0xFFFFFFFF == unknown - u32 originalAddress; u32 codeSize; u32 originalSize; @@ -44,7 +41,13 @@ struct JitBlock int flags; bool invalid; - bool linkStatus[2]; + + struct LinkData { + u8 *exitPtrs; // to be able to rewrite the exit jum + u32 exitAddress; + bool linkStatus; // is it already linked? + }; + std::vector linkData; #ifdef _WIN32 // we don't really need to save start and stop From c5b8c65ddcbffe1832248a8027ec9f84f5f71d9a Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 21 Dec 2013 19:15:02 -0600 Subject: [PATCH 2/5] Initialize linkStatus to false in the ARM JIT cores as well. --- Source/Core/Core/PowerPC/JitArm32/Jit.cpp | 1 + Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp | 1 + 2 files changed, 2 insertions(+) diff --git a/Source/Core/Core/PowerPC/JitArm32/Jit.cpp b/Source/Core/Core/PowerPC/JitArm32/Jit.cpp index eab7f3711a..8d0590d871 100644 --- a/Source/Core/Core/PowerPC/JitArm32/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm32/Jit.cpp @@ -196,6 +196,7 @@ void JitArm::WriteExit(u32 destination) JitBlock::LinkData linkData; linkData.exitAddress = destination; linkData.exitPtrs = GetWritableCodePtr(); + linkData.linkStatus = false; // Link opportunity! int block = blocks.GetBlockNumberFromStartAddress(destination); diff --git a/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp b/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp index 44ebc8b6eb..66fa3f009b 100644 --- a/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp +++ b/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp @@ -125,6 +125,7 @@ void JitArmIL::WriteExit(u32 destination) JitBlock::LinkData linkData; linkData.exitAddress = destination; linkData.exitPtrs = GetWritableCodePtr(); + linkData.linkStatus = false; // Link opportunity! int block = blocks.GetBlockNumberFromStartAddress(destination); From d2a90e6eabb8213cf7ecc502895952f59cdba861 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 21 Dec 2013 19:24:25 -0600 Subject: [PATCH 3/5] If block linking isn't enabled then make sure there isn't a performance hit from getting a block number. --- Source/Core/Core/PowerPC/Jit64/Jit.cpp | 4 ++-- Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp | 4 ++-- Source/Core/Core/PowerPC/JitArm32/Jit.cpp | 4 ++-- Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Source/Core/Core/PowerPC/Jit64/Jit.cpp b/Source/Core/Core/PowerPC/Jit64/Jit.cpp index 0e66510264..2186bf8784 100644 --- a/Source/Core/Core/PowerPC/Jit64/Jit.cpp +++ b/Source/Core/Core/PowerPC/Jit64/Jit.cpp @@ -290,8 +290,8 @@ void Jit64::WriteExit(u32 destination) linkData.linkStatus = false; // Link opportunity! - int block = blocks.GetBlockNumberFromStartAddress(destination); - if (block >= 0 && jo.enableBlocklink) + int block; + if (jo.enableBlocklink && (block = blocks.GetBlockNumberFromStartAddress(destination)) >= 0) { // It exists! Joy of joy! JMP(blocks.GetBlock(block)->checkedEntry, true); diff --git a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp index 36ac5a3789..9d17b58f92 100644 --- a/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/PowerPC/Jit64IL/JitIL.cpp @@ -397,8 +397,8 @@ void JitIL::WriteExit(u32 destination) linkData.linkStatus = false; // Link opportunity! - int block = blocks.GetBlockNumberFromStartAddress(destination); - if (block >= 0 && jo.enableBlocklink) + int block; + if (jo.enableBlocklink && (block = blocks.GetBlockNumberFromStartAddress(destination)) >= 0) { // It exists! Joy of joy! JMP(blocks.GetBlock(block)->checkedEntry, true); diff --git a/Source/Core/Core/PowerPC/JitArm32/Jit.cpp b/Source/Core/Core/PowerPC/JitArm32/Jit.cpp index 8d0590d871..e84c8d9f36 100644 --- a/Source/Core/Core/PowerPC/JitArm32/Jit.cpp +++ b/Source/Core/Core/PowerPC/JitArm32/Jit.cpp @@ -199,8 +199,8 @@ void JitArm::WriteExit(u32 destination) linkData.linkStatus = false; // Link opportunity! - int block = blocks.GetBlockNumberFromStartAddress(destination); - if (block >= 0 && jo.enableBlocklink) + int block; + if (jo.enableBlocklink && (block = blocks.GetBlockNumberFromStartAddress(destination)) >= 0) { // It exists! Joy of joy! B(blocks.GetBlock(block)->checkedEntry); diff --git a/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp b/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp index 66fa3f009b..0802266bf4 100644 --- a/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp +++ b/Source/Core/Core/PowerPC/JitArmIL/JitIL.cpp @@ -128,8 +128,8 @@ void JitArmIL::WriteExit(u32 destination) linkData.linkStatus = false; // Link opportunity! - int block = blocks.GetBlockNumberFromStartAddress(destination); - if (block >= 0 && jo.enableBlocklink) + int block; + if (jo.enableBlocklink && (block = blocks.GetBlockNumberFromStartAddress(destination)) >= 0) { // It exists! Joy of joy! B(blocks.GetBlock(block)->checkedEntry); From 0a9fd93eda4bba67866cd2292af229ffaa44ad21 Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Wed, 25 Dec 2013 18:26:29 -0600 Subject: [PATCH 4/5] On block unlinking, wipe the address from the valid links. --- Source/Core/Core/PowerPC/JitCommon/JitCache.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp index 0dd0c63d8b..f9171d927e 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp @@ -313,6 +313,7 @@ using namespace Gen; e.linkStatus = false; } } + links_to.erase(b.originalAddress); } void JitBaseBlockCache::DestroyBlock(int block_num, bool invalidate) From 77851edc1b1ae96c30d42791ca296febe5fa2d2b Mon Sep 17 00:00:00 2001 From: Ryan Houdek Date: Sat, 15 Feb 2014 20:41:42 -0600 Subject: [PATCH 5/5] Fix the arbitrary exits. We have to make sure that the block links are cleared entirely. --- Source/Core/Core/PowerPC/JitCommon/JitCache.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp index f9171d927e..8fb7bd471b 100644 --- a/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp +++ b/Source/Core/Core/PowerPC/JitCommon/JitCache.cpp @@ -165,6 +165,7 @@ using namespace Gen; JitBlock &b = blocks[num_blocks]; b.invalid = false; b.originalAddress = em_address; + b.linkData.clear(); num_blocks++; //commit the current block return num_blocks - 1; }