Revert "jit: change our linking module to be able to handle arbitrary exit addresses"

This shouldn't cause issues, but does in Windows. Revert for now.
This reverts commit 1aa06b8fa4.
This commit is contained in:
Ryan Houdek
2013-11-25 16:56:04 -06:00
parent 230e12ae8c
commit db9c586356
19 changed files with 83 additions and 92 deletions

View File

@ -276,7 +276,7 @@ void Jit64::Cleanup()
ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst); ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst);
} }
void Jit64::WriteExit(u32 destination) void Jit64::WriteExit(u32 destination, int exit_num)
{ {
Cleanup(); Cleanup();
@ -284,9 +284,8 @@ void Jit64::WriteExit(u32 destination)
//If nobody has taken care of this yet (this can be removed when all branches are done) //If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock; JitBlock *b = js.curBlock;
JitBlock::LinkData linkData; b->exitAddress[exit_num] = destination;
linkData.exitAddress = destination; b->exitPtrs[exit_num] = GetWritableCodePtr();
linkData.exitPtrs = GetWritableCodePtr();
// Link opportunity! // Link opportunity!
if (jo.enableBlocklink) if (jo.enableBlocklink)
@ -296,14 +295,12 @@ void Jit64::WriteExit(u32 destination)
{ {
// It exists! Joy of joy! // It exists! Joy of joy!
JMP(blocks.GetBlock(block)->checkedEntry, true); JMP(blocks.GetBlock(block)->checkedEntry, true);
linkData.linkStatus = true; b->linkStatus[exit_num] = true;
return; return;
} }
} }
MOV(32, M(&PC), Imm32(destination)); MOV(32, M(&PC), Imm32(destination));
JMP(asm_routines.dispatcher, true); JMP(asm_routines.dispatcher, true);
b->linkData.push_back(linkData);
} }
void Jit64::WriteExitDestInEAX() void Jit64::WriteExitDestInEAX()
@ -628,7 +625,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF)); TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = J_CC(CC_Z); FixupBranch noBreakpoint = J_CC(CC_Z);
WriteExit(ops[i].address); WriteExit(ops[i].address, 0);
SetJumpTarget(noBreakpoint); SetJumpTarget(noBreakpoint);
} }
@ -710,7 +707,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
{ {
gpr.Flush(FLUSH_ALL); gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL); fpr.Flush(FLUSH_ALL);
WriteExit(nextPC); WriteExit(nextPC, 0);
} }
b->flags = js.block_flags; b->flags = js.block_flags;

View File

@ -99,7 +99,7 @@ public:
// Utilities for use by opcodes // Utilities for use by opcodes
void WriteExit(u32 destination); void WriteExit(u32 destination, int exit_num);
void WriteExitDestInEAX(); void WriteExitDestInEAX();
void WriteExceptionExit(); void WriteExceptionExit();
void WriteExternalExceptionExit(); void WriteExternalExceptionExit();

View File

@ -91,7 +91,7 @@ void Jit64::bx(UGeckoInstruction inst)
// make idle loops go faster // make idle loops go faster
js.downcountAmount += 8; js.downcountAmount += 8;
} }
WriteExit(destination); WriteExit(destination, 0);
} }
// TODO - optimize to hell and beyond // TODO - optimize to hell and beyond
@ -136,13 +136,13 @@ void Jit64::bcx(UGeckoInstruction inst)
destination = SignExt16(inst.BD << 2); destination = SignExt16(inst.BD << 2);
else else
destination = js.compilerPC + SignExt16(inst.BD << 2); destination = js.compilerPC + SignExt16(inst.BD << 2);
WriteExit(destination); WriteExit(destination, 0);
if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0)
SetJumpTarget( pConditionDontBranch ); SetJumpTarget( pConditionDontBranch );
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
SetJumpTarget( pCTRDontBranch ); SetJumpTarget( pCTRDontBranch );
WriteExit(js.compilerPC + 4); WriteExit(js.compilerPC + 4, 1);
} }
void Jit64::bcctrx(UGeckoInstruction inst) void Jit64::bcctrx(UGeckoInstruction inst)
@ -190,7 +190,7 @@ void Jit64::bcctrx(UGeckoInstruction inst)
WriteExitDestInEAX(); WriteExitDestInEAX();
// Would really like to continue the block here, but it ends. TODO. // Would really like to continue the block here, but it ends. TODO.
SetJumpTarget(b); SetJumpTarget(b);
WriteExit(js.compilerPC + 4); WriteExit(js.compilerPC + 4, 1);
} }
} }
@ -245,5 +245,5 @@ void Jit64::bclrx(UGeckoInstruction inst)
SetJumpTarget( pConditionDontBranch ); SetJumpTarget( pConditionDontBranch );
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
SetJumpTarget( pCTRDontBranch ); SetJumpTarget( pCTRDontBranch );
WriteExit(js.compilerPC + 4); WriteExit(js.compilerPC + 4, 1);
} }

View File

@ -400,7 +400,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
destination = SignExt16(js.next_inst.BD << 2); destination = SignExt16(js.next_inst.BD << 2);
else else
destination = js.next_compilerPC + SignExt16(js.next_inst.BD << 2); destination = js.next_compilerPC + SignExt16(js.next_inst.BD << 2);
WriteExit(destination); WriteExit(destination, 0);
} }
else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528)) // bcctrx else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528)) // bcctrx
{ {
@ -424,7 +424,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
} }
else else
{ {
WriteExit(js.next_compilerPC + 4); WriteExit(js.next_compilerPC + 4, 0);
} }
js.cancel = true; js.cancel = true;
@ -507,7 +507,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
destination = SignExt16(js.next_inst.BD << 2); destination = SignExt16(js.next_inst.BD << 2);
else else
destination = js.next_compilerPC + SignExt16(js.next_inst.BD << 2); destination = js.next_compilerPC + SignExt16(js.next_inst.BD << 2);
WriteExit(destination); WriteExit(destination, 0);
} }
else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528)) // bcctrx 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 (!!(4 & test_bit) == condition) SetJumpTarget(continue2);
if (!!(2 & test_bit) == condition) SetJumpTarget(continue1); if (!!(2 & test_bit) == condition) SetJumpTarget(continue1);
WriteExit(js.next_compilerPC + 4); WriteExit(js.next_compilerPC + 4, 1);
js.cancel = true; js.cancel = true;
} }
@ -2221,5 +2221,5 @@ void Jit64::twx(UGeckoInstruction inst)
SetJumpTarget(exit3); SetJumpTarget(exit3);
SetJumpTarget(exit4); SetJumpTarget(exit4);
SetJumpTarget(exit5); SetJumpTarget(exit5);
WriteExit(js.compilerPC + 4); WriteExit(js.compilerPC + 4, 1);
} }

View File

@ -480,5 +480,5 @@ void Jit64::stmw(UGeckoInstruction inst)
void Jit64::icbi(UGeckoInstruction inst) void Jit64::icbi(UGeckoInstruction inst)
{ {
Default(inst); Default(inst);
WriteExit(js.compilerPC + 4); WriteExit(js.compilerPC + 4, 0);
} }

View File

@ -137,7 +137,7 @@ void Jit64::mtmsr(UGeckoInstruction inst)
SetJumpTarget(noExceptionsPending); SetJumpTarget(noExceptionsPending);
SetJumpTarget(eeDisabled); SetJumpTarget(eeDisabled);
WriteExit(js.compilerPC + 4); WriteExit(js.compilerPC + 4, 0);
js.firstFPInstructionFound = false; js.firstFPInstructionFound = false;
} }

View File

@ -552,8 +552,7 @@ static void regEmitICmpInst(RegInfo& RI, InstLoc I, CCFlags flag) {
static void regWriteExit(RegInfo& RI, InstLoc dest) { static void regWriteExit(RegInfo& RI, InstLoc dest) {
if (isImm(*dest)) { if (isImm(*dest)) {
RI.exitNumber++; RI.Jit->WriteExit(RI.Build->GetImmValue(dest), RI.exitNumber++);
RI.Jit->WriteExit(RI.Build->GetImmValue(dest));
} else { } else {
RI.Jit->WriteExitDestInOpArg(regLocForInst(RI, dest)); RI.Jit->WriteExitDestInOpArg(regLocForInst(RI, dest));
} }
@ -565,7 +564,7 @@ static bool checkIsSNAN() {
return MathUtil::IsSNAN(isSNANTemp[0][0]) || MathUtil::IsSNAN(isSNANTemp[1][0]); return MathUtil::IsSNAN(isSNANTemp[0][0]) || MathUtil::IsSNAN(isSNANTemp[1][0]);
} }
static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) { static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit) {
//printf("Writing block: %x\n", js.blockStart); //printf("Writing block: %x\n", js.blockStart);
RegInfo RI(Jit, ibuild->getFirstInst(), ibuild->getNumInsts()); RegInfo RI(Jit, ibuild->getFirstInst(), ibuild->getNumInsts());
RI.Build = ibuild; RI.Build = ibuild;
@ -1792,7 +1791,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) {
Jit->ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints)); Jit->ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints));
Jit->TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF)); Jit->TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = Jit->J_CC(CC_Z); FixupBranch noBreakpoint = Jit->J_CC(CC_Z);
Jit->WriteExit(InstLoc); Jit->WriteExit(InstLoc, 0);
Jit->SetJumpTarget(noBreakpoint); Jit->SetJumpTarget(noBreakpoint);
break; break;
} }
@ -1820,10 +1819,10 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) {
} }
} }
Jit->WriteExit(exitAddress); Jit->WriteExit(jit->js.curBlock->exitAddress[0], 0);
Jit->UD2(); Jit->UD2();
} }
void JitIL::WriteCode(u32 exitAddress) { void JitIL::WriteCode() {
DoWriteCode(&ibuild, this, exitAddress); DoWriteCode(&ibuild, this);
} }

View File

@ -381,7 +381,7 @@ void JitIL::Cleanup()
ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst); ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst);
} }
void JitIL::WriteExit(u32 destination) void JitIL::WriteExit(u32 destination, int exit_num)
{ {
Cleanup(); Cleanup();
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) { if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) {
@ -391,9 +391,8 @@ void JitIL::WriteExit(u32 destination)
//If nobody has taken care of this yet (this can be removed when all branches are done) //If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock; JitBlock *b = js.curBlock;
JitBlock::LinkData linkData; b->exitAddress[exit_num] = destination;
linkData.exitAddress = destination; b->exitPtrs[exit_num] = GetWritableCodePtr();
linkData.exitPtrs = GetWritableCodePtr();
// Link opportunity! // Link opportunity!
int block = blocks.GetBlockNumberFromStartAddress(destination); int block = blocks.GetBlockNumberFromStartAddress(destination);
@ -401,14 +400,13 @@ void JitIL::WriteExit(u32 destination)
{ {
// It exists! Joy of joy! // It exists! Joy of joy!
JMP(blocks.GetBlock(block)->checkedEntry, true); JMP(blocks.GetBlock(block)->checkedEntry, true);
linkData.linkStatus = true; b->linkStatus[exit_num] = true;
} }
else else
{ {
MOV(32, M(&PC), Imm32(destination)); MOV(32, M(&PC), Imm32(destination));
JMP(asm_routines.dispatcher, true); JMP(asm_routines.dispatcher, true);
} }
b->linkData.push_back(linkData);
} }
void JitIL::WriteExitDestInOpArg(const Gen::OpArg& arg) void JitIL::WriteExitDestInOpArg(const Gen::OpArg& arg)
@ -543,16 +541,14 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
// Analyze the block, collect all instructions it is made of (including inlining, // 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. // if that is enabled), reorder instructions for optimal performance, and join joinable instructions.
u32 exitAddress = em_address; b->exitAddress[0] = em_address;
u32 merged_addresses[32]; u32 merged_addresses[32];
const int capacity_of_merged_addresses = sizeof(merged_addresses) / sizeof(merged_addresses[0]); const int capacity_of_merged_addresses = sizeof(merged_addresses) / sizeof(merged_addresses[0]);
int size_of_merged_addresses = 0; int size_of_merged_addresses = 0;
if (!memory_exception) if (!memory_exception)
{ {
// If there is a memory exception inside a block (broken_block==true), compile up to that instruction. // If there is a memory exception inside a block (broken_block==true), compile up to that instruction.
// TODO 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);
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; PPCAnalyst::CodeOp *ops = code_buf->codebuffer;
@ -711,7 +707,7 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
} }
// Perform actual code generation // Perform actual code generation
WriteCode(exitAddress); WriteCode();
b->codeSize = (u32)(GetCodePtr() - normalEntry); b->codeSize = (u32)(GetCodePtr() - normalEntry);
b->originalSize = size; b->originalSize = size;

View File

@ -105,7 +105,7 @@ public:
// Utilities for use by opcodes // Utilities for use by opcodes
void WriteExit(u32 destination); void WriteExit(u32 destination, int exit_num);
void WriteExitDestInOpArg(const Gen::OpArg& arg); void WriteExitDestInOpArg(const Gen::OpArg& arg);
void WriteExceptionExit(); void WriteExceptionExit();
void WriteRfiExitDestInOpArg(const Gen::OpArg& arg); void WriteRfiExitDestInOpArg(const Gen::OpArg& arg);
@ -121,7 +121,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 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 fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (Gen::XEmitter::*op)(Gen::X64Reg, Gen::OpArg));
void WriteCode(u32 exitAddress); void WriteCode();
// OPCODES // OPCODES
void unknown_instruction(UGeckoInstruction _inst) override; void unknown_instruction(UGeckoInstruction _inst) override;

View File

@ -186,16 +186,15 @@ void JitArm::WriteExceptionExit()
MOVI2R(A, (u32)asm_routines.testExceptions); MOVI2R(A, (u32)asm_routines.testExceptions);
B(A); B(A);
} }
void JitArm::WriteExit(u32 destination) void JitArm::WriteExit(u32 destination, int exit_num)
{ {
Cleanup(); Cleanup();
DoDownCount(); DoDownCount();
//If nobody has taken care of this yet (this can be removed when all branches are done) //If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock; JitBlock *b = js.curBlock;
JitBlock::LinkData linkData; b->exitAddress[exit_num] = destination;
linkData.exitAddress = destination; b->exitPtrs[exit_num] = GetWritableCodePtr();
linkData.exitPtrs = GetWritableCodePtr();
// Link opportunity! // Link opportunity!
int block = blocks.GetBlockNumberFromStartAddress(destination); int block = blocks.GetBlockNumberFromStartAddress(destination);
@ -203,7 +202,7 @@ void JitArm::WriteExit(u32 destination)
{ {
// It exists! Joy of joy! // It exists! Joy of joy!
B(blocks.GetBlock(block)->checkedEntry); B(blocks.GetBlock(block)->checkedEntry);
linkData.linkStatus = true; b->linkStatus[exit_num] = true;
} }
else else
{ {
@ -213,8 +212,6 @@ void JitArm::WriteExit(u32 destination)
MOVI2R(A, (u32)asm_routines.dispatcher); MOVI2R(A, (u32)asm_routines.dispatcher);
B(A); B(A);
} }
b->linkData.push_back(linkData);
} }
void STACKALIGN JitArm::Run() void STACKALIGN JitArm::Run()
@ -499,7 +496,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
if (broken_block) if (broken_block)
{ {
printf("Broken Block going to 0x%08x\n", nextPC); printf("Broken Block going to 0x%08x\n", nextPC);
WriteExit(nextPC); WriteExit(nextPC, 0);
} }
b->flags = js.block_flags; b->flags = js.block_flags;

View File

@ -109,7 +109,7 @@ public:
// Utilities for use by opcodes // Utilities for use by opcodes
void WriteExit(u32 destination); void WriteExit(u32 destination, int exit_num);
void WriteExitDestInR(ARMReg Reg); void WriteExitDestInR(ARMReg Reg);
void WriteRfiExitDestInR(ARMReg Reg); void WriteRfiExitDestInR(ARMReg Reg);
void WriteExceptionExit(); void WriteExceptionExit();

View File

@ -154,7 +154,7 @@ void JitArm::bx(UGeckoInstruction inst)
MOVI2R(R14, (u32)asm_routines.testExceptions); MOVI2R(R14, (u32)asm_routines.testExceptions);
B(R14); B(R14);
} }
WriteExit(destination); WriteExit(destination, 0);
} }
void JitArm::bcx(UGeckoInstruction inst) void JitArm::bcx(UGeckoInstruction inst)
@ -209,14 +209,14 @@ void JitArm::bcx(UGeckoInstruction inst)
destination = SignExt16(inst.BD << 2); destination = SignExt16(inst.BD << 2);
else else
destination = js.compilerPC + SignExt16(inst.BD << 2); destination = js.compilerPC + SignExt16(inst.BD << 2);
WriteExit(destination); WriteExit(destination, 0);
if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0) if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0)
SetJumpTarget( pConditionDontBranch ); SetJumpTarget( pConditionDontBranch );
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
SetJumpTarget( pCTRDontBranch ); SetJumpTarget( pCTRDontBranch );
WriteExit(js.compilerPC + 4); WriteExit(js.compilerPC + 4, 1);
} }
void JitArm::bcctrx(UGeckoInstruction inst) void JitArm::bcctrx(UGeckoInstruction inst)
{ {
@ -278,7 +278,7 @@ void JitArm::bcctrx(UGeckoInstruction inst)
WriteExitDestInR(rA); WriteExitDestInR(rA);
SetJumpTarget(b); SetJumpTarget(b);
WriteExit(js.compilerPC + 4); WriteExit(js.compilerPC + 4, 1);
} }
} }
void JitArm::bclrx(UGeckoInstruction inst) void JitArm::bclrx(UGeckoInstruction inst)
@ -355,5 +355,5 @@ void JitArm::bclrx(UGeckoInstruction inst)
SetJumpTarget( pConditionDontBranch ); SetJumpTarget( pConditionDontBranch );
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0) if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
SetJumpTarget( pCTRDontBranch ); SetJumpTarget( pCTRDontBranch );
WriteExit(js.compilerPC + 4); WriteExit(js.compilerPC + 4, 1);
} }

View File

@ -531,6 +531,6 @@ void JitArm::dcbst(UGeckoInstruction inst)
void JitArm::icbi(UGeckoInstruction inst) void JitArm::icbi(UGeckoInstruction inst)
{ {
Default(inst); Default(inst);
WriteExit(js.compilerPC + 4); WriteExit(js.compilerPC + 4, 0);
} }

View File

@ -205,7 +205,7 @@ void JitArm::mtmsr(UGeckoInstruction inst)
gpr.Flush(); gpr.Flush();
fpr.Flush(); fpr.Flush();
WriteExit(js.compilerPC + 4); WriteExit(js.compilerPC + 4, 0);
} }
void JitArm::mfmsr(UGeckoInstruction inst) void JitArm::mfmsr(UGeckoInstruction inst)

View File

@ -156,8 +156,7 @@ static ARMReg regEnsureInReg(RegInfo& RI, InstLoc I) {
static void regWriteExit(RegInfo& RI, InstLoc dest) { static void regWriteExit(RegInfo& RI, InstLoc dest) {
if (isImm(*dest)) { if (isImm(*dest)) {
RI.exitNumber++; RI.Jit->WriteExit(RI.Build->GetImmValue(dest), RI.exitNumber++);
RI.Jit->WriteExit(RI.Build->GetImmValue(dest));
} else { } else {
RI.Jit->WriteExitDestInReg(regLocForInst(RI, dest)); RI.Jit->WriteExitDestInReg(regLocForInst(RI, dest));
} }
@ -282,7 +281,7 @@ static void regEmitCmp(RegInfo& RI, InstLoc I) {
} }
} }
static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit, u32 exitAddress) { static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit) {
RegInfo RI(Jit, ibuild->getFirstInst(), ibuild->getNumInsts()); RegInfo RI(Jit, ibuild->getFirstInst(), ibuild->getNumInsts());
RI.Build = ibuild; RI.Build = ibuild;
@ -734,10 +733,10 @@ static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit, u32 exitAddress) {
} }
} }
Jit->WriteExit(exitAddress); Jit->WriteExit(jit->js.curBlock->exitAddress[0], 0);
Jit->BKPT(0x111); Jit->BKPT(0x111);
} }
void JitArmIL::WriteCode(u32 exitAddress) { void JitArmIL::WriteCode() {
DoWriteCode(&ibuild, this, exitAddress); DoWriteCode(&ibuild, this);
} }

View File

@ -117,14 +117,13 @@ void JitArmIL::WriteExceptionExit()
MOVI2R(R14, (u32)asm_routines.testExceptions); MOVI2R(R14, (u32)asm_routines.testExceptions);
B(R14); B(R14);
} }
void JitArmIL::WriteExit(u32 destination) void JitArmIL::WriteExit(u32 destination, int exit_num)
{ {
DoDownCount(); DoDownCount();
//If nobody has taken care of this yet (this can be removed when all branches are done) //If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock; JitBlock *b = js.curBlock;
JitBlock::LinkData linkData; b->exitAddress[exit_num] = destination;
linkData.exitAddress = destination; b->exitPtrs[exit_num] = GetWritableCodePtr();
linkData.exitPtrs = GetWritableCodePtr();
// Link opportunity! // Link opportunity!
int block = blocks.GetBlockNumberFromStartAddress(destination); int block = blocks.GetBlockNumberFromStartAddress(destination);
@ -132,7 +131,7 @@ void JitArmIL::WriteExit(u32 destination)
{ {
// It exists! Joy of joy! // It exists! Joy of joy!
B(blocks.GetBlock(block)->checkedEntry); B(blocks.GetBlock(block)->checkedEntry);
linkData.linkStatus = true; b->linkStatus[exit_num] = true;
} }
else else
{ {
@ -141,8 +140,6 @@ void JitArmIL::WriteExit(u32 destination)
MOVI2R(R14, (u32)asm_routines.dispatcher); MOVI2R(R14, (u32)asm_routines.dispatcher);
B(R14); B(R14);
} }
b->linkData.push_back(linkData);
} }
void JitArmIL::PrintDebug(UGeckoInstruction inst, u32 level) void JitArmIL::PrintDebug(UGeckoInstruction inst, u32 level)
{ {
@ -350,12 +347,12 @@ const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
if (broken_block) if (broken_block)
{ {
printf("Broken Block going to 0x%08x\n", nextPC); printf("Broken Block going to 0x%08x\n", nextPC);
WriteExit(nextPC); WriteExit(nextPC, 0);
} }
// Perform actual code generation // Perform actual code generation
WriteCode(nextPC); WriteCode();
b->flags = js.block_flags; b->flags = js.block_flags;
b->codeSize = (u32)(GetCodePtr() - normalEntry); b->codeSize = (u32)(GetCodePtr() - normalEntry);
b->originalSize = size; b->originalSize = size;

View File

@ -64,8 +64,8 @@ public:
void Run(); void Run();
void SingleStep(); void SingleStep();
// //
void WriteCode(u32 exitAddress); void WriteCode();
void WriteExit(u32 destination); void WriteExit(u32 destination, int exit_num);
void WriteExitDestInReg(ARMReg Reg); void WriteExitDestInReg(ARMReg Reg);
void WriteRfiExitDestInR(ARMReg Reg); void WriteRfiExitDestInR(ARMReg Reg);
void WriteExceptionExit(); void WriteExceptionExit();

View File

@ -35,6 +35,8 @@ op_agent_t agent;
using namespace Gen; using namespace Gen;
#define INVALID_EXIT 0xFFFFFFFF
bool JitBaseBlockCache::IsFull() const bool JitBaseBlockCache::IsFull() const
{ {
return GetNumBlocks() >= MAX_NUM_BLOCKS - 1; return GetNumBlocks() >= MAX_NUM_BLOCKS - 1;
@ -165,6 +167,12 @@ using namespace Gen;
JitBlock &b = blocks[num_blocks]; JitBlock &b = blocks[num_blocks];
b.invalid = false; b.invalid = false;
b.originalAddress = em_address; 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 num_blocks++; //commit the current block
return num_blocks - 1; return num_blocks - 1;
} }
@ -185,9 +193,10 @@ using namespace Gen;
block_map[std::make_pair(pAddr + 4 * b.originalSize - 1, pAddr)] = block_num; block_map[std::make_pair(pAddr + 4 * b.originalSize - 1, pAddr)] = block_num;
if (block_link) if (block_link)
{ {
for (const auto& e : b.linkData) for (int i = 0; i < 2; i++)
{ {
links_to.insert(std::pair<u32, int>(e.exitAddress, block_num)); if (b.exitAddress[i] != INVALID_EXIT)
links_to.insert(std::pair<u32, int>(b.exitAddress[i], block_num));
} }
LinkBlock(block_num); LinkBlock(block_num);
@ -266,15 +275,15 @@ using namespace Gen;
// This block is dead. Don't relink it. // This block is dead. Don't relink it.
return; return;
} }
for (auto& e : b.linkData) for (int e = 0; e < 2; e++)
{ {
if (!e.linkStatus) if (b.exitAddress[e] != INVALID_EXIT && !b.linkStatus[e])
{ {
int destinationBlock = GetBlockNumberFromStartAddress(e.exitAddress); int destinationBlock = GetBlockNumberFromStartAddress(b.exitAddress[e]);
if (destinationBlock != -1) if (destinationBlock != -1)
{ {
WriteLinkBlock(e.exitPtrs, blocks[destinationBlock].checkedEntry); WriteLinkBlock(b.exitPtrs[e], blocks[destinationBlock].checkedEntry);
e.linkStatus = true; b.linkStatus[e] = true;
} }
} }
} }
@ -307,10 +316,10 @@ using namespace Gen;
return; return;
for (multimap<u32, int>::iterator iter = ppp.first; iter != ppp.second; ++iter) { for (multimap<u32, int>::iterator iter = ppp.first; iter != ppp.second; ++iter) {
JitBlock &sourceBlock = blocks[iter->second]; JitBlock &sourceBlock = blocks[iter->second];
for (auto& e : sourceBlock.linkData) for (int e = 0; e < 2; e++)
{ {
if (e.exitAddress == b.originalAddress) if (sourceBlock.exitAddress[e] == b.originalAddress)
e.linkStatus = false; sourceBlock.linkStatus[e] = false;
} }
} }
} }

View File

@ -35,6 +35,9 @@ struct JitBlock
const u8 *checkedEntry; const u8 *checkedEntry;
const u8 *normalEntry; const u8 *normalEntry;
u8 *exitPtrs[2]; // to be able to rewrite the exit jum
u32 exitAddress[2]; // 0xFFFFFFFF == unknown
u32 originalAddress; u32 originalAddress;
u32 codeSize; u32 codeSize;
u32 originalSize; u32 originalSize;
@ -42,13 +45,7 @@ struct JitBlock
int flags; int flags;
bool invalid; 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> linkData;
#ifdef _WIN32 #ifdef _WIN32
// we don't really need to save start and stop // we don't really need to save start and stop