libutil: add O_NOCTTY back to old pty open code
[minix.git] / lib / libc / arch / i386 / sys-minix / ucontext.S
blob3c73c0970b91b66f046eddd9534203abf27d18f0
1 #include <machine/asm.h>
2 #include <ucontextoffsets.h>
4 #ifdef __ACK__
5 .text
6 begtext:
7 #ifdef __ACK__
8 .rom
9 #else
10 .data
11 #endif
12 begrom:
13 .data
14 begdata:
15 .bss
16 begbss:
17 #endif
20 IMPORT(getuctx)
21 IMPORT(setuctx)
22 IMPORT(resumecontext)
25 /* MCF_MAGIC value from <mcontext.h> */
26 #define MCF_MAGIC       0xc0ffee
28 /* Values from <sys/ucontext.h> */
29 #define UCF_IGNFPU      0x002
30 #define UCF_IGNSIGM     0x004
33 /* EINVAL from errno.h */
34 #define EFAULT          14
35 #define EINVAL          22
38 /* int getcontext(ucontext_t *ucp) 
39  *      Initialise the structure pointed to by ucp to the current user context
40  *      of the calling thread. */
41 ENTRY(getcontext)
42         /* In case a process does not use the FPU and is neither interested in
43          * saving its signal mask, then we can skip the context switch to
44          * PM and kernel altogether and only save general-purpose registers. */
46         mov (%esp), %ecx        /* Save return address:
47                                  * When setcontext or swapcontext is called,
48                                  * we jump to this address and continue
49                                  * running. */
51         mov 4(%esp), %edx               /* edx = ucp */
52         /* Check null pointer */
53         cmp $0, %edx                    /* edx == NULL? */
54         jne 3f                          /* Not null, continue */
55         movl $EFAULT, (_C_LABEL(errno))
56         xor %eax, %eax
57         dec %eax                        /* return -1 */
58         ret
59         
60 3:      /* Check flags */
61         push %ecx                       /* save ecx */
62         push %ebx                       /* save ebx */
63         lea UC_FLAGS(%edx), %ebx        /* ebx = &(ucp->uc_flags) */
64         mov (%ebx), %ecx                /* ecx = ucp->uc_flags */
65         mov $UCF_IGNFPU, %eax
66         or $UCF_IGNSIGM, %eax
67         cmp %eax, %ecx                  /* is UCF_IGNFPU or UCF_IGNSIGM set? */
68         pop %ebx                        /* restore ebx */
69         pop %ecx                        /* restore ecx */
70         jz 1f                           /* Both are set, skip getuctx */
73         push %ecx                       /* Save ecx */
74         push %edx                
75         call _C_LABEL(getuctx)          /* getuctx(ucp) */
76         pop %edx                        /* clean up stack and restore edx */
77         pop %ecx                        /* Restore ecx */
79 1: 
80         /* Save the context */
81         mov 4(%esp), %edx               /* edx = ucp */
82         pop %eax                        /* retaddr */
83         mov %eax, PC(%edx)              /* Save real RTA in mcp struct */
84         mov %esp, SP(%edx)      /* Save stack pointer (now pointing to ucp) */
85         /* Save GP registers */
86         mov %ebp, BP(%edx)              /* Save EBP */
87         mov %esi, SI(%edx)              /* Save ESI */
88         mov %edi, DI(%edx)              /* Save EDI */
89         mov %ebx, BX(%edx)              /* Save EBX */
90         mov %ecx, CX(%edx)              /* Save ECX */
91         movl $MCF_MAGIC, MAGIC(%edx)    /* Set magic value */
92         push %eax                       /* Restore retaddr */
94         xor %eax, %eax                  /* Return 0 */
96 2:      
97         add $4, %esp                    /* Remove stale (setcontext) RTA */
98         jmp *%ecx                       /* Restore return address */
99         
101 /* int setcontext(const ucontext_t *ucp)
102  *      Restore the user context pointed to by ucp. A successful call to
103  *      setcontext does not return; program execution resumes at the point
104  *      specified by the ucp argument. If ucp was created with getcontext(), 
105  *      program execution continues as if the corresponding call of getcontext()
106  *      had just returned. If ucp was created with makecontext(), program
107  *      execution continues with the function passed to makecontext(). */
108 ENTRY(setcontext)
109         /* In case a process does not use the FPU and is neither interested in
110          * restoring its signal mask, then we can skip the context switch to
111          * PM and kernel altogether and restore state here. */
113         mov 4(%esp), %edx               /* edx = ucp */
115         /* Check null pointer */
116         cmp $0, %edx                    /* edx == NULL? */
117         jnz 3f                          /* Not null, continue */
118         movl $EFAULT, (_C_LABEL(errno))
119         xor %eax, %eax
120         dec %eax                        /* return -1 */
121         ret
122         
123 3:      /* Check flags */
124         push %ebx                       /* save ebx */
125         lea MAGIC(%edx), %ebx           /* ebx = &(ucp->mc_context.mc_magic) */
126         mov (%ebx), %ecx                /* ecx = ucp->mc_context.mc_magic */
127         pop %ebx                        /* restore ebx */
128         cmp $MCF_MAGIC, %ecx    /* is the magic value set (is context valid)?*/
129         jz 4f                           /* is set, proceed */
130         movl $EINVAL, (_C_LABEL(errno)) /* not set, return error code */
131         xor %eax, %eax
132         dec %eax                        /* return -1 */
133         ret     
136 4:      push %ebx                       /* save ebx */
137         lea UC_FLAGS(%edx), %ebx        /* ebx = &(ucp->uc_flags) */
138         mov (%ebx), %ecx                /* ecx = ucp->uc_flags */
139         pop %ebx                        /* restore ebx */
140         mov $UCF_IGNFPU, %eax
141         or $UCF_IGNSIGM, %eax
142         cmp %eax, %ecx          /* Are UCF_IGNFPU and UCF_IGNSIGM flags set? */
143         jz 1f                   /* Both are set, so don't bother restoring FPU
144                                  * state and signal mask */
146 0:      push %ecx                       /* Save ecx */
147         push %edx                
148         call _C_LABEL(setuctx)          /* setuctx(ucp) */
149         pop %edx                        /* Clean up stack and restore edx */
150         pop %ecx                        /* Restore ecx */
152 1:      /* Restore the registers */
153         mov 4(%esp), %edx               /* edx = ucp */
154         mov CX(%edx), %ecx              /* Restore ECX */
155         mov BX(%edx), %ebx              /* Restore EBX */
156         mov DI(%edx), %edi              /* Restore EDI */
157         mov SI(%edx), %esi              /* Restore ESI */
158         mov BP(%edx), %ebp              /* Restore EBP */
159         mov SP(%edx), %esp              /* Restore stack pointer */
162         jmp *PC(%edx)   /* Push RTA onto stack so we can return to it */
165 /* void ctx_start((void *func)(int arg1, ..., argn), arg1, ..., argn,
166  *                ucontext_t *ucp)
167  *      A wrapper to start function `func'. ESI register will contain a pointer
168  *      to ucp on the stack. By setting ESP to ESI, we effectively 'remove' all
169  *      arguments to `func' from the stack. Finally, a call to resumecontext
170  *      will start the next context in the linked list (or exit the program if
171  *      there is no context). */
172 ENTRY(ctx_start)
173         /* 0(esp) -> func
174          * 4(esp) -> arg1
175          * ...
176          * 4*n(esp) -> argn
177          * 4*(n+1)(esp) -> ucp */
179         pop %eax                        /* eax = func */
180         call *%eax                      /* func(arg1, ..., argn) */
181         mov %esi, %esp                  /* Clean up stack */
182         /* ucp is now at the top of the stack again */
183         call _C_LABEL(resumecontext)    /* resumecontext(ucp) */
184         ret                     /* never reached */