aboutsummaryrefslogtreecommitdiff
path: root/sysdeps/mach/hurd/x86_64/setcontext.S
diff options
context:
space:
mode:
Diffstat (limited to 'sysdeps/mach/hurd/x86_64/setcontext.S')
-rw-r--r--sysdeps/mach/hurd/x86_64/setcontext.S96
1 files changed, 96 insertions, 0 deletions
diff --git a/sysdeps/mach/hurd/x86_64/setcontext.S b/sysdeps/mach/hurd/x86_64/setcontext.S
new file mode 100644
index 0000000000..99919ee2a8
--- /dev/null
+++ b/sysdeps/mach/hurd/x86_64/setcontext.S
@@ -0,0 +1,96 @@
+/* Install given context.
+ Copyright (C) 2024 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+
+ The GNU C Library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ The GNU C Library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with the GNU C Library; if not, see
+ <https://www.gnu.org/licenses/>. */
+
+#include <sysdep.h>
+
+#include "ucontext_i.h"
+
+
+ENTRY(__setcontext)
+ /* Save argument since call will destroy it. */
+ pushq %rdi
+ cfi_adjust_cfa_offset(8)
+
+ /* Set the signal mask with
+ __sigprocmask (SIG_SETMASK, mask, NULL). */
+ xorl %edx, %edx
+ leaq oSIGMASK(%rdi), %rsi
+ movl $SIG_SETMASK, %edi
+ call HIDDEN_JUMPTARGET (__sigprocmask)
+ /* Pop the pointer into RDX. The choice is arbitrary, but
+ leaving RDI and RSI available for use later can avoid
+ shuffling values. */
+ popq %rdx
+
+ test %rax, %rax
+ jne L(pseudo_end)
+
+ /* Restore the floating-point context. Not the registers, only the
+ rest. */
+ movq oFPREGS(%rdx), %rcx
+ fldenv (%rcx)
+ ldmxcsr oMXCSR(%rdx)
+
+ /* Load the new stack pointer, the preserved registers and
+ registers used for passing args. */
+ cfi_def_cfa(%rdx, 0)
+ cfi_offset(%rbx,oRBX)
+ cfi_offset(%rbp,oRBP)
+ cfi_offset(%r12,oR12)
+ cfi_offset(%r13,oR13)
+ cfi_offset(%r14,oR14)
+ cfi_offset(%r15,oR15)
+ cfi_offset(%rsp,oRSP)
+ cfi_offset(%rip,oRIP)
+
+ movq oRSP(%rdx), %rsp
+ movq oRBX(%rdx), %rbx
+ movq oRBP(%rdx), %rbp
+ movq oR12(%rdx), %r12
+ movq oR13(%rdx), %r13
+ movq oR14(%rdx), %r14
+ movq oR15(%rdx), %r15
+
+ /* The following ret should return to the address set with
+ getcontext. Therefore push the address on the stack. */
+ movq oRIP(%rdx), %rcx
+ pushq %rcx
+
+ movq oRSI(%rdx), %rsi
+ movq oRDI(%rdx), %rdi
+ movq oRCX(%rdx), %rcx
+ movq oR8(%rdx), %r8
+ movq oR9(%rdx), %r9
+
+ /* Setup finally %rdx. */
+ movq oRDX(%rdx), %rdx
+
+ /* End FDE here, we fall into another context. */
+ cfi_endproc
+ cfi_startproc
+
+ /* Clear rax to indicate success. */
+ xorl %eax, %eax
+L(pseudo_end):
+ /* The following 'ret' will pop the address of the code and jump
+ to it. */
+ ret
+PSEUDO_END(__setcontext)
+libc_hidden_def (__setcontext)
+
+weak_alias (__setcontext, setcontext)