emit_arm64: Fix 1MB block link limit
This commit is contained in:
parent
424fdb5c50
commit
9d6758b4ae
4 changed files with 16 additions and 38 deletions
|
@ -329,33 +329,13 @@ static void LinkBlockLinks(const CodePtr entry_point, const CodePtr target_ptr,
|
|||
using namespace oaknut;
|
||||
using namespace oaknut::util;
|
||||
|
||||
for (auto [ptr_offset, type] : block_relocations_list) {
|
||||
for (auto [ptr_offset] : block_relocations_list) {
|
||||
CodeGenerator c{reinterpret_cast<u32*>(entry_point + ptr_offset)};
|
||||
|
||||
switch (type) {
|
||||
case BlockLinkType::LinkBlockUnconditionally:
|
||||
if (target_ptr) {
|
||||
c.B((void*)target_ptr);
|
||||
} else {
|
||||
c.NOP();
|
||||
}
|
||||
break;
|
||||
case BlockLinkType::LinkBlockIfGreater:
|
||||
if (target_ptr) {
|
||||
c.B(GE, (void*)target_ptr);
|
||||
} else {
|
||||
c.NOP();
|
||||
}
|
||||
break;
|
||||
case BlockLinkType::LinkBlockIfWscratch0IsZero:
|
||||
if (target_ptr) {
|
||||
c.CBZ(Wscratch0, (void*)target_ptr);
|
||||
} else {
|
||||
c.NOP();
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ASSERT_FALSE("Invalid block relocation type");
|
||||
if (target_ptr) {
|
||||
c.B((void*)target_ptr);
|
||||
} else {
|
||||
c.NOP();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -216,8 +216,8 @@ void EmitRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, LinkTarget li
|
|||
code.NOP();
|
||||
}
|
||||
|
||||
void EmitRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, BlockLinkType link_type, const IR::LocationDescriptor& descriptor) {
|
||||
ctx.ebi.block_relocations[descriptor].emplace_back(BlockRelocation{code.ptr<CodePtr>() - ctx.ebi.entry_point, link_type});
|
||||
void EmitBlockLinkRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, const IR::LocationDescriptor& descriptor) {
|
||||
ctx.ebi.block_relocations[descriptor].emplace_back(BlockRelocation{code.ptr<CodePtr>() - ctx.ebi.entry_point});
|
||||
code.NOP();
|
||||
}
|
||||
|
||||
|
|
|
@ -66,12 +66,6 @@ enum class LinkTarget {
|
|||
GetTicksRemaining,
|
||||
};
|
||||
|
||||
enum class BlockLinkType {
|
||||
LinkBlockUnconditionally,
|
||||
LinkBlockIfGreater,
|
||||
LinkBlockIfWscratch0IsZero,
|
||||
};
|
||||
|
||||
struct Relocation {
|
||||
std::ptrdiff_t code_offset;
|
||||
LinkTarget target;
|
||||
|
@ -79,7 +73,6 @@ struct Relocation {
|
|||
|
||||
struct BlockRelocation {
|
||||
std::ptrdiff_t code_offset;
|
||||
BlockLinkType type;
|
||||
};
|
||||
|
||||
struct EmittedBlockInfo {
|
||||
|
@ -113,7 +106,7 @@ EmittedBlockInfo EmitArm64(oaknut::CodeGenerator& code, IR::Block block, const E
|
|||
template<IR::Opcode op>
|
||||
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, BlockLinkType type, const IR::LocationDescriptor& descriptor);
|
||||
void EmitBlockLinkRelocation(oaknut::CodeGenerator& code, EmitContext& ctx, const IR::LocationDescriptor& descriptor);
|
||||
oaknut::Label EmitA32Cond(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Cond cond);
|
||||
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx);
|
||||
void EmitA32ConditionFailedTerminal(oaknut::CodeGenerator& code, EmitContext& ctx);
|
||||
|
|
|
@ -61,16 +61,21 @@ void EmitSetUpperLocationDescriptor(oaknut::CodeGenerator& code, EmitContext& ct
|
|||
void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::LinkBlock terminal, IR::LocationDescriptor initial_location, bool is_single_step) {
|
||||
EmitSetUpperLocationDescriptor(code, ctx, terminal.next, initial_location);
|
||||
|
||||
oaknut::Label fail;
|
||||
|
||||
if (ctx.conf.HasOptimization(OptimizationFlag::BlockLinking) && !is_single_step) {
|
||||
if (ctx.conf.enable_cycle_counting) {
|
||||
code.CMP(Xticks, 0);
|
||||
EmitRelocation(code, ctx, BlockLinkType::LinkBlockIfGreater, terminal.next);
|
||||
code.B(LE, fail);
|
||||
EmitBlockLinkRelocation(code, ctx, terminal.next);
|
||||
} else {
|
||||
code.LDAR(Wscratch0, Xhalt);
|
||||
EmitRelocation(code, ctx, BlockLinkType::LinkBlockIfWscratch0IsZero, terminal.next);
|
||||
code.CBNZ(Wscratch0, fail);
|
||||
EmitBlockLinkRelocation(code, ctx, terminal.next);
|
||||
}
|
||||
}
|
||||
|
||||
code.l(fail);
|
||||
code.MOV(Wscratch0, A32::LocationDescriptor{terminal.next}.PC());
|
||||
code.STR(Wscratch0, Xstate, offsetof(A32JitState, regs) + sizeof(u32) * 15);
|
||||
EmitRelocation(code, ctx, LinkTarget::ReturnToDispatcher);
|
||||
|
@ -80,7 +85,7 @@ void EmitA32Terminal(oaknut::CodeGenerator& code, EmitContext& ctx, IR::Term::Li
|
|||
EmitSetUpperLocationDescriptor(code, ctx, terminal.next, initial_location);
|
||||
|
||||
if (ctx.conf.HasOptimization(OptimizationFlag::BlockLinking) && !is_single_step) {
|
||||
EmitRelocation(code, ctx, BlockLinkType::LinkBlockUnconditionally, terminal.next);
|
||||
EmitBlockLinkRelocation(code, ctx, terminal.next);
|
||||
}
|
||||
|
||||
code.MOV(Wscratch0, A32::LocationDescriptor{terminal.next}.PC());
|
||||
|
|
Loading…
Reference in a new issue