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

112 lines
No EOL
2.7 KiB
C++

#include "platform_macro.h"
#if defined(TARGET_ARCH_IA32)
#include "dobby_internal.h"
#include "core/modules/assembler/assembler-ia32.h"
#include "TrampolineBridge/ClosureTrampolineBridge/common-bridge-handler.h"
using namespace zz;
using namespace zz::x86;
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;
#else
// otherwise, use the Assembler build the closure_bridge
#define _ turbo_assembler_.
#define __ turbo_assembler_.GetCodeBuffer()->
char *pushfd = (char *)"\x9c";
char *popfd = (char *)"\x9d";
TurboAssembler turbo_assembler_(0);
// general register
_ sub(esp, Immediate(8 * 4, 32));
_ mov(Address(esp, 4 * 0), eax);
_ mov(Address(esp, 4 * 1), ebx);
_ mov(Address(esp, 4 * 2), ecx);
_ mov(Address(esp, 4 * 3), edx);
_ mov(Address(esp, 4 * 4), ebp);
_ mov(Address(esp, 4 * 5), esp);
_ mov(Address(esp, 4 * 6), edi);
_ mov(Address(esp, 4 * 7), esi);
// save flags register
__ EmitBuffer(pushfd, 1);
_ pop(eax);
{ // save to stack
_ sub(esp, Immediate(2 * 4, 32));
_ mov(Address(esp, 4), eax);
}
// save origin sp
_ mov(eax, esp);
_ add(eax, Immediate(8 * 4 + 2 * 4 + 4, 32));
{ // save to stack
_ sub(esp, Immediate(2 * 4, 32));
_ mov(Address(esp, 4), eax);
}
// ======= Jump to UnifiedInterface Bridge Handle =======
// prepare args
_ sub(esp, Immediate(2 * 4, 32));
_ mov(eax, Address(esp, 8 * 4 + 2 * 4 + 2 * 4 + 2 * 4));
_ mov(Address(esp, 4), eax);
_ mov(eax, esp);
_ add(eax, Immediate(2 * 4, 32));
_ mov(Address(esp, 0), eax);
// LABEL: call_bridge
_ CallFunction(ExternalReference((void *)intercept_routing_common_bridge_handler));
// ======= RegisterContext Restore =======
// restore argument reserved stack
_ add(esp, Immediate(2 * 4, 32));
// restore sp placeholder stack
_ add(esp, Immediate(2 * 4, 32));
_ add(esp, Immediate(4, 32));
// restore flags register
__ EmitBuffer(popfd, 1);
// general register
_ pop(eax);
_ pop(ebx);
_ pop(ecx);
_ pop(edx);
_ pop(ebp);
_ add(esp, Immediate(4, 32)); // => pop rsp
_ pop(edi);
_ pop(esi);
// trick: use the 'carry_data' stack(remain at closure trampoline) placeholder, as the return address
_ ret();
_ RelocBind();
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