geode/loader/dobby/source/TrampolineBridge/ClosureTrampolineBridge/arm64/closure-bridge-arm64.cc
2022-07-30 19:24:03 +03:00

159 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