diff --git a/src/arch/x86/mod.rs b/src/arch/x86/mod.rs index 40aedaf..7789839 100644 --- a/src/arch/x86/mod.rs +++ b/src/arch/x86/mod.rs @@ -32,10 +32,13 @@ impl Registers { } #[inline(always)] - pub unsafe fn swap(&mut self) { + pub unsafe fn swap2(out_regs: *mut Registers, in_regs: *const Registers) { + let out_espp = &mut (*out_regs).esp; + let in_espp = &(*in_regs).esp; asm!(include_str!("swap.s") : - : "{eax}" (&mut self.esp) + : "{eax}" (out_espp), + "{ebx}" (in_espp) : "eax", "ebx", "ecx", "edx", "esi", "edi", //"ebp", "esp", "mmx0", "mmx1", "mmx2", "mmx3", "mmx4", "mmx5", "mmx6", "mmx7", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", diff --git a/src/arch/x86/swap.s b/src/arch/x86/swap.s index baca48a..d3310e5 100644 --- a/src/arch/x86/swap.s +++ b/src/arch/x86/swap.s @@ -4,7 +4,8 @@ //! switch to a new context //! arguments: -//! * eax: stack pointer pointer +//! * eax: stack pointer out pointer +//! * ebx: stack pointer in pointer // save the frame pointer pushl %ebp @@ -21,11 +22,11 @@ jmp 2f 1: // retrieve the new stack pointer - movl (%eax), %ebx + movl (%eax), %edx // save the old stack pointer - movl %esp, (%eax) + movl %esp, (%ebx) // switch to the new stack pointer - movl %ebx, %esp + movl %edx, %esp // jump into the new context (return to the call point) // doing this instead of a straight `ret` is 8ns slower, diff --git a/src/arch/x86_64/mod.rs b/src/arch/x86_64/mod.rs index 66d1a2e..824b2b7 100644 --- a/src/arch/x86_64/mod.rs +++ b/src/arch/x86_64/mod.rs @@ -31,10 +31,13 @@ impl Registers { } #[inline(always)] - pub unsafe fn swap(&mut self) { + pub unsafe fn swap2(out_regs: *mut Registers, in_regs: *const Registers) { + let out_rspp = &mut (*out_regs).rsp; + let in_rspp = &(*in_regs).rsp; asm!(include_str!("swap.s") : - : "{rdi}" (&mut self.rsp) + : "{rdi}" (out_rspp), + "{rdi}" (in_rspp) : "rax", "rbx", "rcx", "rdx", "rsi", "rdi", //"rbp", "rsp", "r8", "r9", "r10", "r11", "r12", "r13", "r14", "r15", "xmm0", "xmm1", "xmm2", "xmm3", "xmm4", "xmm5", "xmm6", "xmm7", diff --git a/src/arch/x86_64/swap.s b/src/arch/x86_64/swap.s index a4270a9..270fdc1 100644 --- a/src/arch/x86_64/swap.s +++ b/src/arch/x86_64/swap.s @@ -4,7 +4,8 @@ //! switch to a new context //! arguments: -//! * rdi: stack pointer pointer +//! * rdi: stack pointer out pointer +//! * rsi: stack pointer in pointer // make sure we leave the red zone alone sub $$128, %rsp @@ -27,7 +28,7 @@ jmp 2f 1: // retrieve the new stack pointer - movq (%rdi), %rax + movq (%rsi), %rax // save the old stack pointer movq %rsp, (%rdi) // switch to the new stack pointer diff --git a/src/context.rs b/src/context.rs index ab65add..b647bba 100644 --- a/src/context.rs +++ b/src/context.rs @@ -46,7 +46,13 @@ impl<'a, Stack> Context<'a, Stack> where Stack: stack::Stack { /// Switch to the context, saving the current thread of execution there. #[inline(always)] pub unsafe fn swap(&mut self) { - self.regs.swap() + Context::swap2(self, self) + } + + /// Switch to in_ctx, saving the current thread of execution to out_ctx. + #[inline(always)] + pub unsafe fn swap2(out_ctx: *mut Context<'a, Stack>, in_ctx: *const Context<'a, Stack>) { + Registers::swap2(&mut (*out_ctx).regs, &(*in_ctx).regs) } /// Unwrap the context, returning the stack it contained.