emit_arm64: Add BlockRelocationType::MoveToScratch0
This commit is contained in:
parent
a179e2f2bb
commit
15e889fbe3
5 changed files with 45 additions and 15 deletions
|
@ -124,13 +124,27 @@ static void LinkBlockLinks(const CodePtr entry_point, const CodePtr target_ptr,
|
||||||
using namespace oaknut;
|
using namespace oaknut;
|
||||||
using namespace oaknut::util;
|
using namespace oaknut::util;
|
||||||
|
|
||||||
for (auto [ptr_offset] : block_relocations_list) {
|
for (auto [ptr_offset, type] : block_relocations_list) {
|
||||||
CodeGenerator c{reinterpret_cast<u32*>(entry_point + ptr_offset)};
|
CodeGenerator c{reinterpret_cast<u32*>(entry_point + ptr_offset)};
|
||||||
|
|
||||||
if (target_ptr) {
|
switch (type) {
|
||||||
c.B((void*)target_ptr);
|
case BlockRelocationType::Branch:
|
||||||
} else {
|
if (target_ptr) {
|
||||||
c.NOP();
|
c.B((void*)target_ptr);
|
||||||
|
} else {
|
||||||
|
c.NOP();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case BlockRelocationType::MoveToScratch0:
|
||||||
|
if (target_ptr) {
|
||||||
|
c.ADRL(Xscratch0, (void*)target_ptr);
|
||||||
|
} else {
|
||||||
|
c.NOP();
|
||||||
|
c.NOP();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
ASSERT_FALSE("Invalid BlockRelocationType");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -256,9 +256,19 @@ void EmitRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, LinkTarget li
|
||||||
code.NOP();
|
code.NOP();
|
||||||
}
|
}
|
||||||
|
|
||||||
void EmitBlockLinkRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, const IR::LocationDescriptor& descriptor) {
|
void EmitBlockLinkRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, const IR::LocationDescriptor& descriptor, BlockRelocationType type) {
|
||||||
ctx.ebi.block_relocations[descriptor].emplace_back(BlockRelocation{code.ptr<CodePtr>() - ctx.ebi.entry_point});
|
ctx.ebi.block_relocations[descriptor].emplace_back(BlockRelocation{code.ptr<CodePtr>() - ctx.ebi.entry_point, type});
|
||||||
code.NOP();
|
switch (type) {
|
||||||
|
case BlockRelocationType::Branch:
|
||||||
|
code.NOP();
|
||||||
|
break;
|
||||||
|
case BlockRelocationType::MoveToScratch0:
|
||||||
|
code.NOP();
|
||||||
|
code.NOP();
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
UNREACHABLE();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Dynarmic::Backend::Arm64
|
} // namespace Dynarmic::Backend::Arm64
|
||||||
|
|
|
@ -91,8 +91,14 @@ struct Relocation {
|
||||||
LinkTarget target;
|
LinkTarget target;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class BlockRelocationType {
|
||||||
|
Branch,
|
||||||
|
MoveToScratch0,
|
||||||
|
};
|
||||||
|
|
||||||
struct BlockRelocation {
|
struct BlockRelocation {
|
||||||
std::ptrdiff_t code_offset;
|
std::ptrdiff_t code_offset;
|
||||||
|
BlockRelocationType type;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct EmittedBlockInfo {
|
struct EmittedBlockInfo {
|
||||||
|
@ -165,7 +171,7 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E
|
||||||
template<IR::Opcode op>
|
template<IR::Opcode op>
|
||||||
void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst);
|
void EmitIR(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Inst* inst);
|
||||||
void EmitRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, LinkTarget link_target);
|
void EmitRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, LinkTarget link_target);
|
||||||
void EmitBlockLinkRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, const IR::LocationDescriptor& descriptor);
|
void EmitBlockLinkRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, const IR::LocationDescriptor& descriptor, BlockRelocationType type);
|
||||||
oaknut::Label EmitA32Cond(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Cond cond);
|
oaknut::Label EmitA32Cond(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Cond cond);
|
||||||
oaknut::Label EmitA64Cond(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Cond cond);
|
oaknut::Label EmitA64Cond(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Cond cond);
|
||||||
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx);
|
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx);
|
||||||
|
|
|
@ -67,11 +67,11 @@ void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Li
|
||||||
if (ctx.conf.enable_cycle_counting) {
|
if (ctx.conf.enable_cycle_counting) {
|
||||||
code.CMP(Xticks, 0);
|
code.CMP(Xticks, 0);
|
||||||
code.B(LE, fail);
|
code.B(LE, fail);
|
||||||
EmitBlockLinkRelocation(code, ctx, terminal.next);
|
EmitBlockLinkRelocation(code, ctx, terminal.next, BlockRelocationType::Branch);
|
||||||
} else {
|
} else {
|
||||||
code.LDAR(Wscratch0, Xhalt);
|
code.LDAR(Wscratch0, Xhalt);
|
||||||
code.CBNZ(Wscratch0, fail);
|
code.CBNZ(Wscratch0, fail);
|
||||||
EmitBlockLinkRelocation(code, ctx, terminal.next);
|
EmitBlockLinkRelocation(code, ctx, terminal.next, BlockRelocationType::Branch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -85,7 +85,7 @@ void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Li
|
||||||
EmitSetUpperLocationDescriptor(code, ctx, terminal.next, initial_location);
|
EmitSetUpperLocationDescriptor(code, ctx, terminal.next, initial_location);
|
||||||
|
|
||||||
if (ctx.conf.HasOptimization(OptimizationFlag::BlockLinking) && !is_single_step) {
|
if (ctx.conf.HasOptimization(OptimizationFlag::BlockLinking) && !is_single_step) {
|
||||||
EmitBlockLinkRelocation(code, ctx, terminal.next);
|
EmitBlockLinkRelocation(code, ctx, terminal.next, BlockRelocationType::Branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
code.MOV(Wscratch0, A32::LocationDescriptor{terminal.next}.PC());
|
code.MOV(Wscratch0, A32::LocationDescriptor{terminal.next}.PC());
|
||||||
|
|
|
@ -46,11 +46,11 @@ void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Li
|
||||||
if (ctx.conf.enable_cycle_counting) {
|
if (ctx.conf.enable_cycle_counting) {
|
||||||
code.CMP(Xticks, 0);
|
code.CMP(Xticks, 0);
|
||||||
code.B(LE, fail);
|
code.B(LE, fail);
|
||||||
EmitBlockLinkRelocation(code, ctx, terminal.next);
|
EmitBlockLinkRelocation(code, ctx, terminal.next, BlockRelocationType::Branch);
|
||||||
} else {
|
} else {
|
||||||
code.LDAR(Wscratch0, Xhalt);
|
code.LDAR(Wscratch0, Xhalt);
|
||||||
code.CBNZ(Wscratch0, fail);
|
code.CBNZ(Wscratch0, fail);
|
||||||
EmitBlockLinkRelocation(code, ctx, terminal.next);
|
EmitBlockLinkRelocation(code, ctx, terminal.next, BlockRelocationType::Branch);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,7 +62,7 @@ void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Li
|
||||||
|
|
||||||
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor, bool is_single_step) {
|
void EmitA64Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::LinkBlockFast terminal, IR::LocationDescriptor, bool is_single_step) {
|
||||||
if (ctx.conf.HasOptimization(OptimizationFlag::BlockLinking) && !is_single_step) {
|
if (ctx.conf.HasOptimization(OptimizationFlag::BlockLinking) && !is_single_step) {
|
||||||
EmitBlockLinkRelocation(code, ctx, terminal.next);
|
EmitBlockLinkRelocation(code, ctx, terminal.next, BlockRelocationType::Branch);
|
||||||
}
|
}
|
||||||
|
|
||||||
code.MOV(Xscratch0, A64::LocationDescriptor{terminal.next}.PC());
|
code.MOV(Xscratch0, A64::LocationDescriptor{terminal.next}.PC());
|
||||||
|
|
Loading…
Reference in a new issue