EmitX64: Implement block linking

This commit is contained in:
MerryMage 2016-08-07 22:11:39 +01:00
parent b3bb1d5048
commit a32063fa60
2 changed files with 25 additions and 1 deletions

View file

@ -65,7 +65,7 @@ EmitX64::BlockDescriptor* EmitX64::Emit(const Arm::LocationDescriptor descriptor
reg_alloc.Reset();
code->INT3();
CodePtr code_ptr = code->GetCodePtr();
const CodePtr code_ptr = code->GetCodePtr();
basic_blocks[descriptor].code_ptr = code_ptr;
EmitCondPrelude(block.cond, block.cond_failed, block.location);
@ -96,6 +96,7 @@ EmitX64::BlockDescriptor* EmitX64::Emit(const Arm::LocationDescriptor descriptor
reg_alloc.AssertNoMoreUses();
Patch(descriptor, code_ptr);
basic_blocks[descriptor].size = code->GetCodePtr() - code_ptr;
return &basic_blocks[descriptor];
}
@ -1522,6 +1523,14 @@ void EmitX64::EmitTerminalReturnToDispatch(IR::Term::ReturnToDispatch, Arm::Loca
}
void EmitX64::EmitTerminalLinkBlock(IR::Term::LinkBlock terminal, Arm::LocationDescriptor initial_location) {
BlockDescriptor* next_bb = GetBasicBlock(terminal.next);
patch_jmp_locations[terminal.next].emplace_back(code->GetWritableCodePtr());
if (next_bb) {
code->J_CC(CC_G, next_bb->code_ptr, true);
} else {
code->NOP(6); // Leave enough space for a jg instruction.
}
code->MOV(32, MJitStateReg(Arm::Reg::PC), Imm32(terminal.next.PC()));
if (terminal.next.TFlag() != initial_location.TFlag()) {
if (terminal.next.TFlag()) {
@ -1556,8 +1565,21 @@ void EmitX64::EmitTerminalIf(IR::Term::If terminal, Arm::LocationDescriptor init
EmitTerminal(terminal.then_, initial_location);
}
void EmitX64::Patch(Arm::LocationDescriptor desc, CodePtr bb) {
u8* const save_code_ptr = code->GetWritableCodePtr();
for (CodePtr location : patch_jmp_locations[desc]) {
code->SetCodePtr(const_cast<u8*>(location));
code->J_CC(CC_G, bb, true);
ASSERT(code->GetCodePtr() - location == 6);
}
code->SetCodePtr(save_code_ptr);
}
void EmitX64::ClearCache() {
basic_blocks.clear();
patch_jmp_locations.clear();
}
} // namespace BackendX64

View file

@ -56,6 +56,7 @@ private:
void EmitTerminalLinkBlockFast(IR::Term::LinkBlockFast terminal, Arm::LocationDescriptor initial_location);
void EmitTerminalPopRSBHint(IR::Term::PopRSBHint terminal, Arm::LocationDescriptor initial_location);
void EmitTerminalIf(IR::Term::If terminal, Arm::LocationDescriptor initial_location);
void Patch(Arm::LocationDescriptor desc, CodePtr bb);
// Per-block state
std::set<IR::Value*> inhibit_emission;
@ -66,6 +67,7 @@ private:
UserCallbacks cb;
Jit* jit_interface;
std::unordered_map<Arm::LocationDescriptor, BlockDescriptor, Arm::LocationDescriptorHash> basic_blocks;
std::unordered_map<Arm::LocationDescriptor, std::vector<CodePtr>, Arm::LocationDescriptorHash> patch_jmp_locations;
};
} // namespace BackendX64