Merge pull request #74 from Sonicadvance1/arbitrary-exit

Arbitrary exits but actually fixed
This commit is contained in:
Matthew Parlane 2014-02-16 16:51:26 +13:00
commit 96272c89bc
19 changed files with 113 additions and 99 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, int exit_num) void Jit64::WriteExit(u32 destination)
{ {
Cleanup(); 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) //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;
b->exitAddress[exit_num] = destination; JitBlock::LinkData linkData;
b->exitPtrs[exit_num] = GetWritableCodePtr(); linkData.exitAddress = destination;
linkData.exitPtrs = GetWritableCodePtr();
linkData.linkStatus = false;
// Link opportunity! // Link opportunity!
if (jo.enableBlocklink) int block;
if (jo.enableBlocklink && (block = blocks.GetBlockNumberFromStartAddress(destination)) >= 0)
{ {
int block = blocks.GetBlockNumberFromStartAddress(destination); // It exists! Joy of joy!
if (block >= 0) JMP(blocks.GetBlock(block)->checkedEntry, true);
{ linkData.linkStatus = true;
// It exists! Joy of joy!
JMP(blocks.GetBlock(block)->checkedEntry, true);
b->linkStatus[exit_num] = true;
return;
}
} }
MOV(32, M(&PC), Imm32(destination)); else
JMP(asm_routines.dispatcher, true); {
MOV(32, M(&PC), Imm32(destination));
JMP(asm_routines.dispatcher, true);
}
b->linkData.push_back(linkData);
} }
void Jit64::WriteExitDestInEAX() 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)); TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = J_CC(CC_Z); FixupBranch noBreakpoint = J_CC(CC_Z);
WriteExit(ops[i].address, 0); WriteExit(ops[i].address);
SetJumpTarget(noBreakpoint); SetJumpTarget(noBreakpoint);
} }
@ -707,7 +710,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, 0); WriteExit(nextPC);
} }
b->flags = js.block_flags; b->flags = js.block_flags;

View File

@ -88,7 +88,7 @@ public:
// Utilities for use by opcodes // Utilities for use by opcodes
void WriteExit(u32 destination, int exit_num); void WriteExit(u32 destination);
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, 0); WriteExit(destination);
} }
// 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, 0); WriteExit(destination);
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, 1); WriteExit(js.compilerPC + 4);
} }
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, 1); WriteExit(js.compilerPC + 4);
} }
} }
@ -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, 1); WriteExit(js.compilerPC + 4);
} }

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, 0); WriteExit(destination);
} }
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, 0); WriteExit(js.next_compilerPC + 4);
} }
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, 0); WriteExit(destination);
} }
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, 1); WriteExit(js.next_compilerPC + 4);
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, 1); WriteExit(js.compilerPC + 4);
} }

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, 0); WriteExit(js.compilerPC + 4);
} }

View File

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

View File

@ -554,7 +554,8 @@ 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.Jit->WriteExit(RI.Build->GetImmValue(dest), RI.exitNumber++); RI.exitNumber++;
RI.Jit->WriteExit(RI.Build->GetImmValue(dest));
} else { } else {
RI.Jit->WriteExitDestInOpArg(regLocForInst(RI, dest)); RI.Jit->WriteExitDestInOpArg(regLocForInst(RI, dest));
} }
@ -566,7 +567,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) { static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) {
//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;
@ -1793,7 +1794,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit) {
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, 0); Jit->WriteExit(InstLoc);
Jit->SetJumpTarget(noBreakpoint); Jit->SetJumpTarget(noBreakpoint);
break; 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(); Jit->UD2();
} }
void JitIL::WriteCode() { void JitIL::WriteCode(u32 exitAddress) {
DoWriteCode(&ibuild, this); DoWriteCode(&ibuild, this, exitAddress);
} }

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, int exit_num) void JitIL::WriteExit(u32 destination)
{ {
Cleanup(); Cleanup();
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) { if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) {
@ -391,22 +391,25 @@ 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) //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;
b->exitAddress[exit_num] = destination; JitBlock::LinkData linkData;
b->exitPtrs[exit_num] = GetWritableCodePtr(); linkData.exitAddress = destination;
linkData.exitPtrs = GetWritableCodePtr();
linkData.linkStatus = false;
// Link opportunity! // Link opportunity!
int block = blocks.GetBlockNumberFromStartAddress(destination); int block;
if (block >= 0 && jo.enableBlocklink) if (jo.enableBlocklink && (block = blocks.GetBlockNumberFromStartAddress(destination)) >= 0)
{ {
// It exists! Joy of joy! // It exists! Joy of joy!
JMP(blocks.GetBlock(block)->checkedEntry, true); JMP(blocks.GetBlock(block)->checkedEntry, true);
b->linkStatus[exit_num] = true; linkData.linkStatus = 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)
@ -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, // 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.
b->exitAddress[0] = em_address; u32 exitAddress = 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.
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; 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 // Perform actual code generation
WriteCode(); WriteCode(exitAddress);
b->codeSize = (u32)(GetCodePtr() - normalEntry); b->codeSize = (u32)(GetCodePtr() - normalEntry);
b->originalSize = size; b->originalSize = size;

View File

@ -95,7 +95,7 @@ public:
// Utilities for use by opcodes // Utilities for use by opcodes
void WriteExit(u32 destination, int exit_num); void WriteExit(u32 destination);
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);
@ -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 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(); void WriteCode(u32 exitAddress);
// OPCODES // OPCODES
void unknown_instruction(UGeckoInstruction _inst) override; void unknown_instruction(UGeckoInstruction _inst) override;

View File

@ -186,23 +186,25 @@ void JitArm::WriteExceptionExit()
MOVI2R(A, (u32)asm_routines.testExceptions); MOVI2R(A, (u32)asm_routines.testExceptions);
B(A); B(A);
} }
void JitArm::WriteExit(u32 destination, int exit_num) void JitArm::WriteExit(u32 destination)
{ {
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;
b->exitAddress[exit_num] = destination; JitBlock::LinkData linkData;
b->exitPtrs[exit_num] = GetWritableCodePtr(); linkData.exitAddress = destination;
linkData.exitPtrs = GetWritableCodePtr();
linkData.linkStatus = false;
// Link opportunity! // Link opportunity!
int block = blocks.GetBlockNumberFromStartAddress(destination); int block;
if (block >= 0 && jo.enableBlocklink) if (jo.enableBlocklink && (block = blocks.GetBlockNumberFromStartAddress(destination)) >= 0)
{ {
// It exists! Joy of joy! // It exists! Joy of joy!
B(blocks.GetBlock(block)->checkedEntry); B(blocks.GetBlock(block)->checkedEntry);
b->linkStatus[exit_num] = true; linkData.linkStatus = true;
} }
else else
{ {
@ -212,6 +214,8 @@ void JitArm::WriteExit(u32 destination, int exit_num)
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()
@ -496,7 +500,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, 0); WriteExit(nextPC);
} }
b->flags = js.block_flags; b->flags = js.block_flags;

View File

@ -101,7 +101,7 @@ public:
// Utilities for use by opcodes // Utilities for use by opcodes
void WriteExit(u32 destination, int exit_num); void WriteExit(u32 destination);
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, 0); WriteExit(destination);
} }
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, 0); WriteExit(destination);
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, 1); WriteExit(js.compilerPC + 4);
} }
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, 1); WriteExit(js.compilerPC + 4);
} }
} }
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, 1); WriteExit(js.compilerPC + 4);
} }

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, 0); WriteExit(js.compilerPC + 4);
} }

View File

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

View File

@ -156,7 +156,8 @@ 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.Jit->WriteExit(RI.Build->GetImmValue(dest), RI.exitNumber++); RI.exitNumber++;
RI.Jit->WriteExit(RI.Build->GetImmValue(dest));
} else { } else {
RI.Jit->WriteExitDestInReg(regLocForInst(RI, dest)); 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()); RegInfo RI(Jit, ibuild->getFirstInst(), ibuild->getNumInsts());
RI.Build = ibuild; 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); Jit->BKPT(0x111);
} }
void JitArmIL::WriteCode() { void JitArmIL::WriteCode(u32 exitAddress) {
DoWriteCode(&ibuild, this); DoWriteCode(&ibuild, this, exitAddress);
} }

View File

@ -117,21 +117,23 @@ void JitArmIL::WriteExceptionExit()
MOVI2R(R14, (u32)asm_routines.testExceptions); MOVI2R(R14, (u32)asm_routines.testExceptions);
B(R14); B(R14);
} }
void JitArmIL::WriteExit(u32 destination, int exit_num) void JitArmIL::WriteExit(u32 destination)
{ {
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;
b->exitAddress[exit_num] = destination; JitBlock::LinkData linkData;
b->exitPtrs[exit_num] = GetWritableCodePtr(); linkData.exitAddress = destination;
linkData.exitPtrs = GetWritableCodePtr();
linkData.linkStatus = false;
// Link opportunity! // Link opportunity!
int block = blocks.GetBlockNumberFromStartAddress(destination); int block;
if (block >= 0 && jo.enableBlocklink) if (jo.enableBlocklink && (block = blocks.GetBlockNumberFromStartAddress(destination)) >= 0)
{ {
// It exists! Joy of joy! // It exists! Joy of joy!
B(blocks.GetBlock(block)->checkedEntry); B(blocks.GetBlock(block)->checkedEntry);
b->linkStatus[exit_num] = true; linkData.linkStatus = true;
} }
else else
{ {
@ -140,6 +142,8 @@ void JitArmIL::WriteExit(u32 destination, int exit_num)
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)
{ {
@ -347,12 +351,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, 0); WriteExit(nextPC);
} }
// Perform actual code generation // Perform actual code generation
WriteCode(); WriteCode(nextPC);
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

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

View File

@ -35,8 +35,6 @@ 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;
@ -167,12 +165,7 @@ 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.linkData.clear();
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;
} }
@ -193,10 +186,9 @@ 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 (int i = 0; i < 2; i++) for (const auto& e : b.linkData)
{ {
if (b.exitAddress[i] != INVALID_EXIT) links_to.insert(std::pair<u32, int>(e.exitAddress, block_num));
links_to.insert(std::pair<u32, int>(b.exitAddress[i], block_num));
} }
LinkBlock(block_num); LinkBlock(block_num);
@ -275,15 +267,15 @@ using namespace Gen;
// This block is dead. Don't relink it. // This block is dead. Don't relink it.
return; 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) if (destinationBlock != -1)
{ {
WriteLinkBlock(b.exitPtrs[e], blocks[destinationBlock].checkedEntry); WriteLinkBlock(e.exitPtrs, blocks[destinationBlock].checkedEntry);
b.linkStatus[e] = true; e.linkStatus = true;
} }
} }
} }
@ -316,12 +308,13 @@ 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 (int e = 0; e < 2; e++) for (auto& e : sourceBlock.linkData)
{ {
if (sourceBlock.exitAddress[e] == b.originalAddress) if (e.exitAddress == b.originalAddress)
sourceBlock.linkStatus[e] = false; e.linkStatus = false;
} }
} }
links_to.erase(b.originalAddress);
} }
void JitBaseBlockCache::DestroyBlock(int block_num, bool invalidate) void JitBaseBlockCache::DestroyBlock(int block_num, bool invalidate)

View File

@ -34,9 +34,6 @@ 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;
@ -44,7 +41,13 @@ 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