revmc_context/arch/x86_64.rs
1use super::{EXIT_RESULT_OFFSET, EXIT_SP_OFFSET};
2use crate::{EvmContext, EvmStack, RawEvmCompilerFn};
3use core::ptr::NonNull;
4use revm_interpreter::InstructionResult;
5
6/// Entry trampoline: saves callee-saved registers, stores RSP into
7/// `ecx.exit_sp`, and calls the JIT function.
8///
9/// On normal return the JIT function's `InstructionResult` is forwarded.
10/// On abnormal exit (builtin error), [`revmc_exit`] restores RSP and
11/// returns the `exit_result` stored in `EvmContext`.
12#[unsafe(naked)]
13pub(crate) unsafe extern "C" fn revmc_entry(
14 ecx: NonNull<EvmContext<'_>>,
15 stack: NonNull<EvmStack>,
16 stack_len: NonNull<usize>,
17 f: RawEvmCompilerFn,
18) -> InstructionResult {
19 // System V AMD64: rdi=ecx, rsi=stack, rdx=stack_len, rcx=f
20 // The JIT function takes (ecx, stack, stack_len) — already in rdi, rsi, rdx.
21 core::arch::naked_asm!(
22 // Save callee-saved registers.
23 "push rbp",
24 "push rbx",
25 "push r12",
26 "push r13",
27 "push r14",
28 "push r15",
29 // Save RSP into ecx->exit_sp (after pushes, before alignment).
30 "mov [rdi + {exit_sp}], rsp",
31 // Align stack to 16 bytes for the call.
32 "sub rsp, 8",
33 "call rcx",
34 // Normal return — eax = InstructionResult.
35 "add rsp, 8",
36 "pop r15",
37 "pop r14",
38 "pop r13",
39 "pop r12",
40 "pop rbx",
41 "pop rbp",
42 "ret",
43 exit_sp = const EXIT_SP_OFFSET,
44 )
45}
46
47/// Exit trampoline: loads `ecx.exit_result`, restores the saved RSP,
48/// pops callee-saved registers and returns to the caller of `revmc_entry`.
49///
50/// # Safety
51///
52/// Must only be called from a builtin that was invoked through `revmc_entry`.
53#[unsafe(naked)]
54pub unsafe extern "C" fn revmc_exit(ecx: *const EvmContext<'_>) -> ! {
55 core::arch::naked_asm!(
56 // Load exit_result into the return register.
57 "movzx eax, byte ptr [rdi + {exit_result}]",
58 // Restore the saved RSP (points at the callee-saved saves).
59 "mov rsp, [rdi + {exit_sp}]",
60 "pop r15",
61 "pop r14",
62 "pop r13",
63 "pop r12",
64 "pop rbx",
65 "pop rbp",
66 "ret",
67 exit_result = const EXIT_RESULT_OFFSET,
68 exit_sp = const EXIT_SP_OFFSET,
69 )
70}