mirror of
https://github.com/geode-sdk/geode.git
synced 2024-12-11 16:41:12 -05:00
160 lines
5.4 KiB
C++
160 lines
5.4 KiB
C++
|
#include "platform_macro.h"
|
||
|
#if defined(TARGET_ARCH_ARM64)
|
||
|
|
||
|
#include "dobby_internal.h"
|
||
|
|
||
|
#include "core/modules/assembler/assembler.h"
|
||
|
#include "core/modules/assembler/assembler-arm64.h"
|
||
|
|
||
|
#include "TrampolineBridge/ClosureTrampolineBridge/common-bridge-handler.h"
|
||
|
|
||
|
using namespace zz;
|
||
|
using namespace zz::arm64;
|
||
|
|
||
|
static void *closure_bridge = NULL;
|
||
|
|
||
|
void *get_closure_bridge() {
|
||
|
// if already initialized, just return.
|
||
|
if (closure_bridge)
|
||
|
return closure_bridge;
|
||
|
|
||
|
// check if enable the inline-assembly closure_bridge_template
|
||
|
#if ENABLE_CLOSURE_BRIDGE_TEMPLATE
|
||
|
extern void closure_bridge_tempate();
|
||
|
closure_bridge = closure_bridge_template;
|
||
|
// otherwise, use the Assembler build the closure_bridge
|
||
|
#else
|
||
|
#define _ turbo_assembler_.
|
||
|
#define MEM(reg, offset) MemOperand(reg, offset)
|
||
|
#define MEM_EXT(reg, offset, addrmode) MemOperand(reg, offset, addrmode)
|
||
|
TurboAssembler turbo_assembler_(0);
|
||
|
|
||
|
#if defined(FULL_FLOATING_POINT_REGISTER_PACK)
|
||
|
|
||
|
_ sub(SP, SP, 24 * 16);
|
||
|
_ stp(Q(30), Q(31), MEM(SP, 22 * 16));
|
||
|
_ stp(Q(28), Q(29), MEM(SP, 20 * 16));
|
||
|
_ stp(Q(26), Q(27), MEM(SP, 18 * 16));
|
||
|
_ stp(Q(24), Q(25), MEM(SP, 16 * 16));
|
||
|
_ stp(Q(22), Q(23), MEM(SP, 14 * 16));
|
||
|
_ stp(Q(20), Q(21), MEM(SP, 12 * 16));
|
||
|
_ stp(Q(18), Q(19), MEM(SP, 10 * 16));
|
||
|
_ stp(Q(16), Q(17), MEM(SP, 8 * 16));
|
||
|
_ stp(Q(14), Q(15), MEM(SP, 6 * 16));
|
||
|
_ stp(Q(12), Q(13), MEM(SP, 4 * 16));
|
||
|
_ stp(Q(10), Q(11), MEM(SP, 2 * 16));
|
||
|
_ stp(Q(8), Q(9), MEM(SP, 0 * 16));
|
||
|
|
||
|
#endif
|
||
|
|
||
|
// save {q0-q7}
|
||
|
_ sub(SP, SP, 8 * 16);
|
||
|
_ stp(Q(6), Q(7), MEM(SP, 6 * 16));
|
||
|
_ stp(Q(4), Q(5), MEM(SP, 4 * 16));
|
||
|
_ stp(Q(2), Q(3), MEM(SP, 2 * 16));
|
||
|
_ stp(Q(0), Q(1), MEM(SP, 0 * 16));
|
||
|
|
||
|
// save {x1-x30}
|
||
|
_ sub(SP, SP, 30 * 8);
|
||
|
_ stp(X(29), X(30), MEM(SP, 28 * 8));
|
||
|
_ stp(X(27), X(28), MEM(SP, 26 * 8));
|
||
|
_ stp(X(25), X(26), MEM(SP, 24 * 8));
|
||
|
_ stp(X(23), X(24), MEM(SP, 22 * 8));
|
||
|
_ stp(X(21), X(22), MEM(SP, 20 * 8));
|
||
|
_ stp(X(19), X(20), MEM(SP, 18 * 8));
|
||
|
_ stp(X(17), X(18), MEM(SP, 16 * 8));
|
||
|
_ stp(X(15), X(16), MEM(SP, 14 * 8));
|
||
|
_ stp(X(13), X(14), MEM(SP, 12 * 8));
|
||
|
_ stp(X(11), X(12), MEM(SP, 10 * 8));
|
||
|
_ stp(X(9), X(10), MEM(SP, 8 * 8));
|
||
|
_ stp(X(7), X(8), MEM(SP, 6 * 8));
|
||
|
_ stp(X(5), X(6), MEM(SP, 4 * 8));
|
||
|
_ stp(X(3), X(4), MEM(SP, 2 * 8));
|
||
|
_ stp(X(1), X(2), MEM(SP, 0 * 8));
|
||
|
|
||
|
// save {x0}
|
||
|
_ sub(SP, SP, 2 * 8);
|
||
|
_ str(x0, MEM(SP, 8));
|
||
|
|
||
|
// calculate original sp
|
||
|
_ add(TMP_REG_0, SP, 2 * 8); // closure trampoline reserved
|
||
|
_ add(TMP_REG_0, TMP_REG_0, 2 * 8 + 30 * 8 + 8 * 16); // x0, x1-x30, q0-q7 reserved
|
||
|
#if defined(FULL_FLOATING_POINT_REGISTER_PACK)
|
||
|
_ add(TMP_REG_0, TMP_REG_0, 24 * 16); // q8-q31 reserved
|
||
|
#endif
|
||
|
|
||
|
// alloc stack, store original sp
|
||
|
_ sub(SP, SP, 2 * 8);
|
||
|
_ str(TMP_REG_0, MEM(SP, 8));
|
||
|
|
||
|
#if defined(FULL_FLOATING_POINT_REGISTER_PACK)
|
||
|
#define REGISTER_CONTEXT_SIZE (sizeof(RegisterContext))
|
||
|
#else
|
||
|
#define REGISTER_CONTEXT_SIZE (sizeof(RegisterContext) - 24 * 16)
|
||
|
#endif
|
||
|
// create function arm64 call convention
|
||
|
_ mov(x0, SP); // arg1: register context
|
||
|
// load package(closure trampoline reserved)
|
||
|
_ ldr(x1, MEM(SP, REGISTER_CONTEXT_SIZE + 0)); // arg2: closure trampoline package
|
||
|
_ CallFunction(ExternalReference((void *)intercept_routing_common_bridge_handler));
|
||
|
|
||
|
// restore sp placeholder stack
|
||
|
_ add(SP, SP, 2 * 8);
|
||
|
|
||
|
// restore x0
|
||
|
_ ldr(X(0), MEM(SP, 8));
|
||
|
_ add(SP, SP, 2 * 8);
|
||
|
|
||
|
// restore {x1-x30}
|
||
|
_ ldp(X(1), X(2), MEM_EXT(SP, 16, PostIndex));
|
||
|
_ ldp(X(3), X(4), MEM_EXT(SP, 16, PostIndex));
|
||
|
_ ldp(X(5), X(6), MEM_EXT(SP, 16, PostIndex));
|
||
|
_ ldp(X(7), X(8), MEM_EXT(SP, 16, PostIndex));
|
||
|
_ ldp(X(9), X(10), MEM_EXT(SP, 16, PostIndex));
|
||
|
_ ldp(X(11), X(12), MEM_EXT(SP, 16, PostIndex));
|
||
|
_ ldp(X(13), X(14), MEM_EXT(SP, 16, PostIndex));
|
||
|
_ ldp(X(15), X(16), MEM_EXT(SP, 16, PostIndex));
|
||
|
_ ldp(X(17), X(18), MEM_EXT(SP, 16, PostIndex));
|
||
|
_ ldp(X(19), X(20), MEM_EXT(SP, 16, PostIndex));
|
||
|
_ ldp(X(21), X(22), MEM_EXT(SP, 16, PostIndex));
|
||
|
_ ldp(X(23), X(24), MEM_EXT(SP, 16, PostIndex));
|
||
|
_ ldp(X(25), X(26), MEM_EXT(SP, 16, PostIndex));
|
||
|
_ ldp(X(27), X(28), MEM_EXT(SP, 16, PostIndex));
|
||
|
_ ldp(X(29), X(30), MEM_EXT(SP, 16, PostIndex));
|
||
|
|
||
|
// restore {q0-q7}
|
||
|
_ ldp(Q(0), Q(1), MEM_EXT(SP, 32, PostIndex));
|
||
|
_ ldp(Q(2), Q(3), MEM_EXT(SP, 32, PostIndex));
|
||
|
_ ldp(Q(4), Q(5), MEM_EXT(SP, 32, PostIndex));
|
||
|
_ ldp(Q(6), Q(7), MEM_EXT(SP, 32, PostIndex));
|
||
|
|
||
|
#if defined(FULL_FLOATING_POINT_REGISTER_PACK)
|
||
|
_ ldp(Q(8), Q(9), MEM_EXT(SP, 32, PostIndex));
|
||
|
_ ldp(Q(10), Q(11), MEM_EXT(SP, 32, PostIndex));
|
||
|
_ ldp(Q(12), Q(13), MEM_EXT(SP, 32, PostIndex));
|
||
|
_ ldp(Q(14), Q(15), MEM_EXT(SP, 32, PostIndex));
|
||
|
_ ldp(Q(16), Q(17), MEM_EXT(SP, 32, PostIndex));
|
||
|
_ ldp(Q(18), Q(19), MEM_EXT(SP, 32, PostIndex));
|
||
|
_ ldp(Q(20), Q(21), MEM_EXT(SP, 32, PostIndex));
|
||
|
_ ldp(Q(22), Q(23), MEM_EXT(SP, 32, PostIndex));
|
||
|
_ ldp(Q(24), Q(25), MEM_EXT(SP, 32, PostIndex));
|
||
|
_ ldp(Q(26), Q(27), MEM_EXT(SP, 32, PostIndex));
|
||
|
_ ldp(Q(28), Q(29), MEM_EXT(SP, 32, PostIndex));
|
||
|
_ ldp(Q(30), Q(31), MEM_EXT(SP, 32, PostIndex));
|
||
|
#endif
|
||
|
|
||
|
// _ brk(0); // for debug
|
||
|
|
||
|
// return to closure trampoline, but TMP_REG_0, had been modified with next hop address
|
||
|
_ ret(); // AKA br x30
|
||
|
|
||
|
AssemblyCodeChunk *code = AssemblyCodeBuilder::FinalizeFromTurboAssembler(&turbo_assembler_);
|
||
|
closure_bridge = (void *)code->raw_instruction_start();
|
||
|
|
||
|
DLOG(0, "[closure bridge] Build the closure bridge at %p", closure_bridge);
|
||
|
#endif
|
||
|
return (void *)closure_bridge;
|
||
|
}
|
||
|
|
||
|
#endif
|