use crate::Control;
use core::arch::asm;
use core::mem::offset_of;
use core::ptr::{Alignment, NonNull};
#[naked]
pub extern "system" fn stack_ptr() -> NonNull<u8> {
unsafe { asm!("mov rax, rsp", "ret", options(noreturn)) }
}
pub unsafe extern "system" fn transfer_control(record: &mut Control) {
asm!(
"push rbx",
"push rbp",
"mov rax, rsp",
"mov rsp, [rdi + {stack_ptr_offset}]",
"mov [rdi + {stack_ptr_offset}], rax",
"mov rax, [rdi + {instr_ptr_offset}]",
"lea rdx, [rip + 2f]",
"mov [rdi + {instr_ptr_offset}], rdx",
"jmp rax",
"2:",
"pop rbp",
"pop rbx",
in("rdi") record,
stack_ptr_offset = const offset_of!(Control, stack_ptr),
instr_ptr_offset = const offset_of!(Control, instr_ptr),
clobber_abi("system"), lateout("r12") _, lateout("r13") _, lateout("r14") _, lateout("r15") _,
);
}
pub unsafe extern "system" fn return_control<R>(
record: &mut Control,
ret_val_addr: NonNull<R>,
) -> ! {
asm!(
"mov rsp, [rdi + {stack_ptr_offset}]",
"mov [rdi + {stack_ptr_offset}], rdx",
"mov rax, [rdi + {instr_ptr_offset}]",
"mov qword ptr [rdi + {instr_ptr_offset}], 0",
"jmp rax",
in("rdi") record,
in("rdx") ret_val_addr.as_ptr(),
stack_ptr_offset = const offset_of!(Control, stack_ptr),
instr_ptr_offset = const offset_of!(Control, instr_ptr),
options(noreturn)
)
}
pub const STACK_FRAME_ALIGN: Alignment = unsafe { Alignment::new_unchecked(16) };