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 1aa06b8fa4105d22cac0dd847230215099bbeb78.
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);
}
void Jit64::WriteExit(u32 destination)
void Jit64::WriteExit(u32 destination, int exit_num)
{
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)
JitBlock *b = js.curBlock;
JitBlock::LinkData linkData;
linkData.exitAddress = destination;
linkData.exitPtrs = GetWritableCodePtr();
b->exitAddress[exit_num] = destination;
b->exitPtrs[exit_num] = GetWritableCodePtr();
// Link opportunity!
if (jo.enableBlocklink)
@ -296,14 +295,12 @@ void Jit64::WriteExit(u32 destination)
{
// It exists! Joy of joy!
JMP(blocks.GetBlock(block)->checkedEntry, true);
linkData.linkStatus = true;
b->linkStatus[exit_num] = true;
return;
}
}
MOV(32, M(&PC), Imm32(destination));
JMP(asm_routines.dispatcher, true);
b->linkData.push_back(linkData);
}
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));
FixupBranch noBreakpoint = J_CC(CC_Z);
WriteExit(ops[i].address);
WriteExit(ops[i].address, 0);
SetJumpTarget(noBreakpoint);
}
@ -710,7 +707,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
{
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
WriteExit(nextPC);
WriteExit(nextPC, 0);
}
b->flags = js.block_flags;

View File

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

View File

@ -91,7 +91,7 @@ void Jit64::bx(UGeckoInstruction inst)
// make idle loops go faster
js.downcountAmount += 8;
}
WriteExit(destination);
WriteExit(destination, 0);
}
// 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);
WriteExit(destination, 0);
if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0)
SetJumpTarget( pConditionDontBranch );
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
SetJumpTarget( pCTRDontBranch );
WriteExit(js.compilerPC + 4);
WriteExit(js.compilerPC + 4, 1);
}
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);
WriteExit(js.compilerPC + 4, 1);
}
}
@ -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);
WriteExit(js.compilerPC + 4, 1);
}

View File

@ -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);
WriteExit(destination, 0);
}
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);
WriteExit(js.next_compilerPC + 4, 0);
}
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);
WriteExit(destination, 0);
}
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);
WriteExit(js.next_compilerPC + 4, 1);
js.cancel = true;
}
@ -2221,5 +2221,5 @@ void Jit64::twx(UGeckoInstruction inst)
SetJumpTarget(exit3);
SetJumpTarget(exit4);
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)
{
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(eeDisabled);
WriteExit(js.compilerPC + 4);
WriteExit(js.compilerPC + 4, 0);
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) {
if (isImm(*dest)) {
RI.exitNumber++;
RI.Jit->WriteExit(RI.Build->GetImmValue(dest));
RI.Jit->WriteExit(RI.Build->GetImmValue(dest), RI.exitNumber++);
} else {
RI.Jit->WriteExitDestInOpArg(regLocForInst(RI, dest));
}
@ -565,7 +564,7 @@ static bool checkIsSNAN() {
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);
RegInfo RI(Jit, ibuild->getFirstInst(), ibuild->getNumInsts());
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->TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = Jit->J_CC(CC_Z);
Jit->WriteExit(InstLoc);
Jit->WriteExit(InstLoc, 0);
Jit->SetJumpTarget(noBreakpoint);
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();
}
void JitIL::WriteCode(u32 exitAddress) {
DoWriteCode(&ibuild, this, exitAddress);
void JitIL::WriteCode() {
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);
}
void JitIL::WriteExit(u32 destination)
void JitIL::WriteExit(u32 destination, int exit_num)
{
Cleanup();
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)
JitBlock *b = js.curBlock;
JitBlock::LinkData linkData;
linkData.exitAddress = destination;
linkData.exitPtrs = GetWritableCodePtr();
b->exitAddress[exit_num] = destination;
b->exitPtrs[exit_num] = GetWritableCodePtr();
// Link opportunity!
int block = blocks.GetBlockNumberFromStartAddress(destination);
@ -401,14 +400,13 @@ void JitIL::WriteExit(u32 destination)
{
// It exists! Joy of joy!
JMP(blocks.GetBlock(block)->checkedEntry, true);
linkData.linkStatus = true;
b->linkStatus[exit_num] = 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)
@ -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,
// 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];
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.
// 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);
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);
}
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
WriteCode(exitAddress);
WriteCode();
b->codeSize = (u32)(GetCodePtr() - normalEntry);
b->originalSize = size;

View File

@ -105,7 +105,7 @@ public:
// Utilities for use by opcodes
void WriteExit(u32 destination);
void WriteExit(u32 destination, int exit_num);
void WriteExitDestInOpArg(const Gen::OpArg& arg);
void WriteExceptionExit();
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 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
void unknown_instruction(UGeckoInstruction _inst) override;

View File

@ -186,16 +186,15 @@ void JitArm::WriteExceptionExit()
MOVI2R(A, (u32)asm_routines.testExceptions);
B(A);
}
void JitArm::WriteExit(u32 destination)
void JitArm::WriteExit(u32 destination, int exit_num)
{
Cleanup();
DoDownCount();
//If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock;
JitBlock::LinkData linkData;
linkData.exitAddress = destination;
linkData.exitPtrs = GetWritableCodePtr();
b->exitAddress[exit_num] = destination;
b->exitPtrs[exit_num] = GetWritableCodePtr();
// Link opportunity!
int block = blocks.GetBlockNumberFromStartAddress(destination);
@ -203,7 +202,7 @@ void JitArm::WriteExit(u32 destination)
{
// It exists! Joy of joy!
B(blocks.GetBlock(block)->checkedEntry);
linkData.linkStatus = true;
b->linkStatus[exit_num] = true;
}
else
{
@ -213,8 +212,6 @@ void JitArm::WriteExit(u32 destination)
MOVI2R(A, (u32)asm_routines.dispatcher);
B(A);
}
b->linkData.push_back(linkData);
}
void STACKALIGN JitArm::Run()
@ -499,7 +496,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);
WriteExit(nextPC, 0);
}
b->flags = js.block_flags;

View File

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

View File

@ -154,7 +154,7 @@ void JitArm::bx(UGeckoInstruction inst)
MOVI2R(R14, (u32)asm_routines.testExceptions);
B(R14);
}
WriteExit(destination);
WriteExit(destination, 0);
}
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);
WriteExit(destination, 0);
if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0)
SetJumpTarget( pConditionDontBranch );
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
SetJumpTarget( pCTRDontBranch );
WriteExit(js.compilerPC + 4);
WriteExit(js.compilerPC + 4, 1);
}
void JitArm::bcctrx(UGeckoInstruction inst)
{
@ -278,7 +278,7 @@ void JitArm::bcctrx(UGeckoInstruction inst)
WriteExitDestInR(rA);
SetJumpTarget(b);
WriteExit(js.compilerPC + 4);
WriteExit(js.compilerPC + 4, 1);
}
}
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);
WriteExit(js.compilerPC + 4, 1);
}

View File

@ -531,6 +531,6 @@ void JitArm::dcbst(UGeckoInstruction inst)
void JitArm::icbi(UGeckoInstruction 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();
fpr.Flush();
WriteExit(js.compilerPC + 4);
WriteExit(js.compilerPC + 4, 0);
}
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) {
if (isImm(*dest)) {
RI.exitNumber++;
RI.Jit->WriteExit(RI.Build->GetImmValue(dest));
RI.Jit->WriteExit(RI.Build->GetImmValue(dest), RI.exitNumber++);
} else {
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());
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);
}
void JitArmIL::WriteCode(u32 exitAddress) {
DoWriteCode(&ibuild, this, exitAddress);
void JitArmIL::WriteCode() {
DoWriteCode(&ibuild, this);
}

View File

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

View File

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

View File

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

View File

@ -35,6 +35,9 @@ 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;
@ -42,13 +45,7 @@ struct JitBlock
int flags;
bool invalid;
struct LinkData {
u8 *exitPtrs; // to be able to rewrite the exit jum
u32 exitAddress;
bool linkStatus; // is it already linked?
};
std::vector<LinkData> linkData;
bool linkStatus[2];
#ifdef _WIN32
// we don't really need to save start and stop