1/* Save current context and install the given one. 2 Copyright (C) 2001-2022 Free Software Foundation, Inc. 3 This file is part of the GNU C Library. 4 5 The GNU C Library is free software; you can redistribute it and/or 6 modify it under the terms of the GNU Lesser General Public 7 License as published by the Free Software Foundation; either 8 version 2.1 of the License, or (at your option) any later version. 9 10 The GNU C Library is distributed in the hope that it will be useful, 11 but WITHOUT ANY WARRANTY; without even the implied warranty of 12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 Lesser General Public License for more details. 14 15 You should have received a copy of the GNU Lesser General Public 16 License along with the GNU C Library; if not, see 17 <https://www.gnu.org/licenses/>. */ 18 19#include <sysdep.h> 20 21#include "ucontext_i.h" 22 23 24ENTRY(__swapcontext) 25 /* Load address of the context data structure we save in. */ 26 movl 4(%esp), %eax 27 28 /* Return value of swapcontext. EAX is the only register whose 29 value is not preserved. */ 30 movl $0, oEAX(%eax) 31 32 /* Save the 32-bit register values and the return address. */ 33 movl %ecx, oECX(%eax) 34 movl %edx, oEDX(%eax) 35 movl %edi, oEDI(%eax) 36 movl %esi, oESI(%eax) 37 movl %ebp, oEBP(%eax) 38 movl (%esp), %ecx 39 movl %ecx, oEIP(%eax) 40 leal 4(%esp), %ecx 41 movl %ecx, oESP(%eax) 42 movl %ebx, oEBX(%eax) 43 44 /* Save the FS segment register. */ 45 xorl %edx, %edx 46 movw %fs, %dx 47 movl %edx, oFS(%eax) 48 49 leal oFPREGS(%eax), %ecx 50 /* Save the floating-point context. */ 51 fnstenv (%ecx) 52 53 /* Load address of the context data structure we have to load. */ 54 movl 8(%esp), %ecx 55 56 /* Save the current signal mask and install the new one. */ 57 subl $12, %esp 58 cfi_adjust_cfa_offset (12) 59 leal oSIGMASK(%eax), %eax 60 movl %eax, 8(%esp) 61 leal oSIGMASK(%ecx), %eax 62 movl %eax, 4(%esp) 63 movl $SIG_SETMASK, (%esp) 64 call HIDDEN_JUMPTARGET (__sigprocmask) 65 addl $12, %esp 66 cfi_adjust_cfa_offset (-12) 67 testl %eax, %eax 68 jne L(pseudo_end) 69 70 /* EAX was modified, reload it. */ 71 movl 8(%esp), %eax 72 73 /* Restore the floating-point context. Not the registers, only the 74 rest. */ 75 leal oFPREGS(%eax), %ecx 76 fldenv (%ecx) 77 78 /* Restore the FS segment register. We don't touch the GS register 79 since it is used for threads. */ 80 movl oFS(%eax), %edx 81 movw %dx, %fs 82 83 /* Fetch the address to return to. */ 84 movl oEIP(%eax), %ecx 85 86 /* Load the new stack pointer. */ 87 movl oESP(%eax), %esp 88 89 /* Push the return address on the new stack so we can return there. */ 90 pushl %ecx 91 92 /* Load the values of all the 32-bit registers (except ESP). 93 Since we are loading from EAX, it must be last. */ 94 movl oEDI(%eax), %edi 95 movl oESI(%eax), %esi 96 movl oEBP(%eax), %ebp 97 movl oEBX(%eax), %ebx 98 movl oEDX(%eax), %edx 99 movl oECX(%eax), %ecx 100 movl oEAX(%eax), %eax 101 102 /* The following 'ret' will pop the address of the code and jump 103 to it. */ 104 105L(pseudo_end): 106 ret 107PSEUDO_END(__swapcontext) 108 109weak_alias (__swapcontext, swapcontext) 110