Optimization: Implement terminal LinkBlockFast
This commit is contained in:
parent
624e84fa09
commit
6c45619aa1
3 changed files with 33 additions and 5 deletions
|
@ -1714,9 +1714,8 @@ void EmitX64::EmitTerminalLinkBlock(IR::Term::LinkBlock terminal, Arm::LocationD
|
|||
|
||||
code->CMP(64, MDisp(R15, offsetof(JitState, cycles_remaining)), Imm32(0));
|
||||
|
||||
auto next_bb = GetBasicBlock(terminal.next);
|
||||
patch_jg_locations[terminal.next].emplace_back(code->GetWritableCodePtr());
|
||||
if (next_bb) {
|
||||
if (auto next_bb = GetBasicBlock(terminal.next)) {
|
||||
code->J_CC(CC_G, next_bb->code_ptr, true);
|
||||
} else {
|
||||
code->NOP(6); // Leave enough space for a jg instruction.
|
||||
|
@ -1726,7 +1725,28 @@ void EmitX64::EmitTerminalLinkBlock(IR::Term::LinkBlock terminal, Arm::LocationD
|
|||
}
|
||||
|
||||
void EmitX64::EmitTerminalLinkBlockFast(IR::Term::LinkBlockFast terminal, Arm::LocationDescriptor initial_location) {
|
||||
EmitTerminalLinkBlock(IR::Term::LinkBlock{terminal.next}, initial_location); // TODO: Implement
|
||||
if (terminal.next.TFlag() != initial_location.TFlag()) {
|
||||
if (terminal.next.TFlag()) {
|
||||
code->OR(32, MJitStateCpsr(), Imm32(1 << 5));
|
||||
} else {
|
||||
code->AND(32, MJitStateCpsr(), Imm32(~(1 << 5)));
|
||||
}
|
||||
}
|
||||
if (terminal.next.EFlag() != initial_location.EFlag()) {
|
||||
if (terminal.next.EFlag()) {
|
||||
code->OR(32, MJitStateCpsr(), Imm32(1 << 9));
|
||||
} else {
|
||||
code->AND(32, MJitStateCpsr(), Imm32(~(1 << 9)));
|
||||
}
|
||||
}
|
||||
|
||||
patch_jmp_locations[terminal.next].emplace_back(code->GetWritableCodePtr());
|
||||
if (auto next_bb = GetBasicBlock(terminal.next)) {
|
||||
code->JMP(next_bb->code_ptr, true);
|
||||
} else {
|
||||
code->MOV(32, MJitStateReg(Arm::Reg::PC), Imm32(terminal.next.PC()));
|
||||
code->JMP(code->GetReturnFromRunCodeAddress(), true);
|
||||
}
|
||||
}
|
||||
|
||||
void EmitX64::EmitTerminalPopRSBHint(IR::Term::PopRSBHint, Arm::LocationDescriptor initial_location) {
|
||||
|
@ -1765,6 +1785,12 @@ void EmitX64::Patch(Arm::LocationDescriptor desc, CodePtr bb) {
|
|||
ASSERT(code->GetCodePtr() - location == 6);
|
||||
}
|
||||
|
||||
for (CodePtr location : patch_jmp_locations[desc]) {
|
||||
code->SetCodePtr(const_cast<u8*>(location));
|
||||
code->JMP(bb, true);
|
||||
ASSERT(code->GetCodePtr() - location == 5);
|
||||
}
|
||||
|
||||
for (CodePtr location : patch_unique_hash_locations[desc.UniqueHash()]) {
|
||||
code->SetCodePtr(const_cast<u8*>(location));
|
||||
code->MOV(64, R(RCX), Imm64(u64(bb)));
|
||||
|
@ -1777,6 +1803,7 @@ void EmitX64::Patch(Arm::LocationDescriptor desc, CodePtr bb) {
|
|||
void EmitX64::ClearCache() {
|
||||
basic_blocks.clear();
|
||||
patch_jg_locations.clear();
|
||||
patch_jmp_locations.clear();
|
||||
}
|
||||
|
||||
} // namespace BackendX64
|
||||
|
|
|
@ -78,6 +78,7 @@ private:
|
|||
std::unordered_map<u64, std::vector<CodePtr>> patch_unique_hash_locations;
|
||||
std::unordered_map<Arm::LocationDescriptor, BlockDescriptor, Arm::LocationDescriptorHash> basic_blocks;
|
||||
std::unordered_map<Arm::LocationDescriptor, std::vector<CodePtr>, Arm::LocationDescriptorHash> patch_jg_locations;
|
||||
std::unordered_map<Arm::LocationDescriptor, std::vector<CodePtr>, Arm::LocationDescriptorHash> patch_jmp_locations;
|
||||
};
|
||||
|
||||
} // namespace BackendX64
|
||||
|
|
|
@ -41,7 +41,7 @@ IR::Block TranslateArm(LocationDescriptor descriptor, MemoryRead32FuncType memor
|
|||
|
||||
if (visitor.cond_state == ConditionalState::Translating) {
|
||||
if (should_continue) {
|
||||
visitor.ir.SetTerm(IR::Term::LinkBlock{visitor.ir.current_location});
|
||||
visitor.ir.SetTerm(IR::Term::LinkBlockFast{visitor.ir.current_location});
|
||||
}
|
||||
visitor.ir.block.cond_failed = { visitor.ir.current_location };
|
||||
}
|
||||
|
@ -73,7 +73,7 @@ bool ArmTranslatorVisitor::ConditionPassed(Cond cond) {
|
|||
if (!ir.block.instructions.IsEmpty()) {
|
||||
// We've already emitted instructions. Quit for now, we'll make a new block here later.
|
||||
cond_state = ConditionalState::Break;
|
||||
ir.SetTerm(IR::Term::LinkBlock{ir.current_location});
|
||||
ir.SetTerm(IR::Term::LinkBlockFast{ir.current_location});
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue