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));
|
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());
|
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);
|
code->J_CC(CC_G, next_bb->code_ptr, true);
|
||||||
} else {
|
} else {
|
||||||
code->NOP(6); // Leave enough space for a jg instruction.
|
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) {
|
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) {
|
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);
|
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()]) {
|
for (CodePtr location : patch_unique_hash_locations[desc.UniqueHash()]) {
|
||||||
code->SetCodePtr(const_cast<u8*>(location));
|
code->SetCodePtr(const_cast<u8*>(location));
|
||||||
code->MOV(64, R(RCX), Imm64(u64(bb)));
|
code->MOV(64, R(RCX), Imm64(u64(bb)));
|
||||||
|
@ -1777,6 +1803,7 @@ void EmitX64::Patch(Arm::LocationDescriptor desc, CodePtr bb) {
|
||||||
void EmitX64::ClearCache() {
|
void EmitX64::ClearCache() {
|
||||||
basic_blocks.clear();
|
basic_blocks.clear();
|
||||||
patch_jg_locations.clear();
|
patch_jg_locations.clear();
|
||||||
|
patch_jmp_locations.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace BackendX64
|
} // namespace BackendX64
|
||||||
|
|
|
@ -78,6 +78,7 @@ private:
|
||||||
std::unordered_map<u64, std::vector<CodePtr>> patch_unique_hash_locations;
|
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, 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_jg_locations;
|
||||||
|
std::unordered_map<Arm::LocationDescriptor, std::vector<CodePtr>, Arm::LocationDescriptorHash> patch_jmp_locations;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace BackendX64
|
} // namespace BackendX64
|
||||||
|
|
|
@ -41,7 +41,7 @@ IR::Block TranslateArm(LocationDescriptor descriptor, MemoryRead32FuncType memor
|
||||||
|
|
||||||
if (visitor.cond_state == ConditionalState::Translating) {
|
if (visitor.cond_state == ConditionalState::Translating) {
|
||||||
if (should_continue) {
|
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 };
|
visitor.ir.block.cond_failed = { visitor.ir.current_location };
|
||||||
}
|
}
|
||||||
|
@ -73,7 +73,7 @@ bool ArmTranslatorVisitor::ConditionPassed(Cond cond) {
|
||||||
if (!ir.block.instructions.IsEmpty()) {
|
if (!ir.block.instructions.IsEmpty()) {
|
||||||
// We've already emitted instructions. Quit for now, we'll make a new block here later.
|
// We've already emitted instructions. Quit for now, we'll make a new block here later.
|
||||||
cond_state = ConditionalState::Break;
|
cond_state = ConditionalState::Break;
|
||||||
ir.SetTerm(IR::Term::LinkBlock{ir.current_location});
|
ir.SetTerm(IR::Term::LinkBlockFast{ir.current_location});
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue