Skip to content

Commit

Permalink
FEXCore: Support x64 -> arm64ec calls
Browse files Browse the repository at this point in the history
The frontend will provide the return logic via ExitFunctionEC, which
will be jumped to whenever there is an indirect branch/return to an addr
such that RtlIsEcCode(addr) returns true.
  • Loading branch information
bylaws committed Apr 6, 2024
1 parent e8127b9 commit 5c50268
Show file tree
Hide file tree
Showing 3 changed files with 33 additions and 8 deletions.
15 changes: 15 additions & 0 deletions FEXCore/Source/Interface/Core/Dispatcher/Dispatcher.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ void Dispatcher::EmitDispatcher() {

ARMEmitter::ForwardLabel l_CTX;
ARMEmitter::SingleUseForwardLabel l_Sleep;
#ifdef _M_ARM_64EC
ARMEmitter::SingleUseForwardLabel ExitEC;
#endif
ARMEmitter::SingleUseForwardLabel l_CompileBlock;

// Push all the register we need to save
Expand Down Expand Up @@ -134,6 +137,10 @@ void Dispatcher::EmitDispatcher() {

// If page pointer is zero then we have no block
cbz(ARMEmitter::Size::i64Bit, TMP1, &NoBlock);
#ifdef _M_ARM_64EC
// The LSB of an L2 page entry indicates if this page contains EC code
tbnz(TMP1, 0, &ExitEC);
#endif

// Steal the page offset
and_(ARMEmitter::Size::i64Bit, TMP2, TMP4, 0x0FFF);
Expand Down Expand Up @@ -167,6 +174,14 @@ void Dispatcher::EmitDispatcher() {
}
}

#ifdef _M_ARM_64EC
{
Bind(&ExitEC);
ldr(TMP2, STATE_PTR(CpuStateFrame, Pointers.Common.ExitFunctionEC));
br(TMP2);
}
#endif

{
ThreadStopHandlerAddressSpillSRA = GetCursorAddress<uint64_t>();
SpillStaticRegs(TMP1);
Expand Down
25 changes: 17 additions & 8 deletions FEXCore/Source/Interface/Core/JIT/Arm64/BranchOps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,23 @@ DEF_OP(ExitFunction) {
uint64_t NewRIP;

if (IsInlineConstant(Op->NewRIP, &NewRIP) || IsInlineEntrypointOffset(Op->NewRIP, &NewRIP)) {
ARMEmitter::SingleUseForwardLabel l_BranchHost;

ldr(TMP1, &l_BranchHost);
blr(TMP1);

Bind(&l_BranchHost);
dc64(ThreadState->CurrentFrame->Pointers.Common.ExitFunctionLinker);
dc64(NewRIP);
#ifdef _M_ARM_64EC
if (RtlIsEcCode(NewRIP)) {
LoadConstant(ARMEmitter::Size::i64Bit, TMP3, NewRIP);
ldr(TMP2, STATE_PTR(CpuStateFrame, Pointers.Common.ExitFunctionEC));
br(TMP2);
} else {
#endif
ARMEmitter::SingleUseForwardLabel l_BranchHost;
ldr(TMP1, &l_BranchHost);
blr(TMP1);

Bind(&l_BranchHost);
dc64(ThreadState->CurrentFrame->Pointers.Common.ExitFunctionLinker);
dc64(NewRIP);
#ifdef _M_ARM_64EC
}
#endif
} else {

ARMEmitter::SingleUseForwardLabel FullLookup;
Expand Down
1 change: 1 addition & 0 deletions FEXCore/include/FEXCore/Core/CoreState.h
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ namespace FEXCore::Core {
uint64_t SyscallHandlerObj{};
uint64_t SyscallHandlerFunc{};
uint64_t ExitFunctionLink{};
uint64_t ExitFunctionEC{};

uint64_t FallbackHandlerPointers[FallbackHandlerIndex::OPINDEX_MAX];
uint64_t NamedVectorConstantPointers[FEXCore::IR::NamedVectorConstant::NAMED_VECTOR_CONST_POOL_MAX];
Expand Down

0 comments on commit 5c50268

Please sign in to comment.