Implement getcontext(), setcontext(), makecontext(), and swapcontext().
[dragonfly.git] / lib / libc / i386 / gen / mcontext.S
1 /*
2  * Copyright (c) 2007 Matthew T. Emmerton <matt@gsicomp.on.ca>
3  * All rights reserved.
4  * Copyright (c) 2007 Matthew Dillon <dillon@backplane.com>
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted provided that the following conditions
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Neither the name of the author nor the names of its contributors
13  *    may be used to endorse or promote products derived from this software
14  *    without specific prior written permission.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  *
28  * $DragonFly: src/lib/libc/i386/gen/mcontext.S,v 1.1 2007/01/16 07:16:23 dillon Exp $
29  */
30
31 #include <machine/asm.h>
32 #include <asmcontext.h>
33
34         /*
35          * int get_mcontext(mcontext_t *mcp)
36          *
37          * Copy the caller's context into the mcontext, %eax excepted.
38          */
39         .weak   get_mcontext
40         .set    get_mcontext,_get_mcontext
41 ENTRY(_get_mcontext)
42         movl    4(%esp),%eax
43         /*      mc_onstack,0*4(%eax)    */
44         movl    %gs,1*4(%eax)
45         movl    %fs,2*4(%eax)
46         movl    %es,3*4(%eax)
47         /*      %ds,4*4(%eax)   */
48         movl    %edi,5*4(%eax)
49         movl    %esi,6*4(%eax)
50         movl    %ebp,7*4(%eax)
51         /*      %isp,8*4(%eax)  */
52         movl    %ebx,9*4(%eax)
53         movl    %edx,10*4(%eax)
54         movl    %ecx,11*4(%eax)
55         /*      mc_eax:         12*4(%eax)      */
56         /*      mc_xflags:      13*4(%eax)      */
57         /*      mc_trapno:      14*4(%eax)      */
58         /*      mc_err:         15*4(%eax)      */
59         /*      mc_eip:         16*4(%eax)      */
60         /*      mc_cs:          17*4(%eax)      */
61         /*      mc_eflags:      18*4(%eax)      */
62         /*      mc_esp:         19*4(%eax)      */
63
64         /*
65          * Saved stack pointer as if we had returned from this
66          * procedure.
67          */
68         movl    %esp,19*4(%eax)
69         addl    $4,19*4(%eax)
70
71         /*
72          * Save eflags
73          */
74         pushfl
75         popl    18*4(%eax)
76
77         /*
78          * Saved instruction pointer as if we had returned from
79          * this procedure.
80          */
81         movl    (%esp),%edx
82         movl    %edx,16*4(%eax)
83
84         /*
85          * On restore as if procedure returned the value 1
86          */
87         movl    $1,12*4(%eax)   
88
89         /*
90          * Set MC_LEN
91          */
92         movl    $SIZEOF_MCONTEXT_T,MC_LEN(%eax)
93
94         /*
95          * Return 0
96          */
97         xorl    %eax,%eax
98         ret
99
100
101         /*
102          * int set_mcontext(mcontext_t *mcp)
103          *
104          * Load the register context, effectively switching to the
105          * new context.
106          */
107         .weak   set_mcontext
108         .set    set_mcontext,_set_mcontext
109 ENTRY(_set_mcontext)
110         movl    4(%esp),%eax
111         /*      0*4(%eax),mc_onstack    */
112         movl    1*4(%eax),%gs
113         movl    2*4(%eax),%fs
114         movl    3*4(%eax),%es
115         /*      4*4(%eax),%ds   */
116         movl    5*4(%eax),%edi
117         movl    6*4(%eax),%esi
118         movl    7*4(%eax),%ebp
119         /*      8*4(%eax),%isp  */
120         movl    9*4(%eax),%ebx
121         movl    10*4(%eax),%edx
122         movl    11*4(%eax),%ecx
123         /*      mc_eax:         12*4(%eax)      */
124         /*      mc_xflags:      13*4(%eax)      */
125         /*      mc_trapno:      14*4(%eax)      */
126         /*      mc_err:         15*4(%eax)      */
127         /*      mc_eip:         16*4(%eax)      */
128         /*      mc_cs:          17*4(%eax)      */
129         /*      mc_eflags:      18*4(%eax)      */
130         /*      mc_esp:         19*4(%eax)      */
131
132         /*
133          * Load the new stack pointer
134          */
135         movl    19*4(%eax),%esp
136
137         /*
138          * Restore the flags
139          */
140         pushl   18*4(%eax)
141         popfl
142
143         /*
144          * Push the return pc so we can 'ret' to it.
145          */
146         pushl   16*4(%eax)
147
148         /*
149          * Load %eax last, and return.
150          */
151         movl    12*4(%eax),%eax
152         ret