Skip to main content

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}