]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - lib/libkse/arch/i386/i386/thr_getcontext.S
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / lib / libkse / arch / i386 / i386 / thr_getcontext.S
1 /*-
2  * Copyright (c) 2001 Daniel Eischen <deischen@freebsd.org>.
3  * All rights reserved.
4  *
5  * Redistribution and use in source and binary forms, with or without
6  * modification, are permitted provided that the following conditions
7  * are met:
8  * 1. Redistributions of source code must retain the above copyright
9  *    notice, this list of conditions and the following disclaimer.
10  * 2. Neither the name of the author nor the names of its contributors
11  *    may be used to endorse or promote products derived from this software
12  *    without specific prior written permission.
13  *
14  * THIS SOFTWARE IS PROVIDED BY DANIEL EISCHEN AND CONTRIBUTORS ``AS IS'' AND
15  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24  * SUCH DAMAGE.
25  */
26
27 #include <machine/asm.h>
28 __FBSDID("$FreeBSD$");
29
30 /*
31  * Where do we define these?
32  */
33 #define MC_LEN_OFFSET           80      /* offset to mc_len from mcontext */
34 #define MC_LEN                  640     /* mc_len <machine/ucontext.h> */
35 #define MC_FPFMT_OFFSET         84
36 #define MC_FPFMT_NODEV          0x10000
37 #define MC_FPFMT_387            0x10001
38 #define MC_FPFMT_XMM            0x10002
39 #define MC_OWNEDFP_OFFSET       88
40 #define MC_OWNEDFP_NONE         0x20000
41 #define MC_OWNEDFP_FPU          0x20001
42 #define MC_OWNEDFP_PCB          0x20002
43 #define MC_FPREGS_OFFSET        96      /* offset to FP regs from mcontext */
44 #define MC_FP_CW_OFFSET         96      /* offset to FP control word */
45
46 /*
47  * int thr_setcontext(mcontext_t *mcp, intptr_t val, intptr_t *loc)
48  *
49  * Restores the context in mcp.
50  *
51  * Returns 0 if there are no errors; -1 otherwise
52  */
53         .weak CNAME(_thr_setcontext)
54         .set CNAME(_thr_setcontext),CNAME(__thr_setcontext)
55 ENTRY(__thr_setcontext)
56         movl    4(%esp), %edx           /* get address of mcontext */
57         cmpl    $0, %edx                /* check for null pointer */
58         jne     1f
59         movl    $-1, %eax
60         jmp     8f
61 1:      cmpl    $MC_LEN, MC_LEN_OFFSET(%edx)    /* is context valid? */
62         je      2f
63         movl    $-1, %eax               /* bzzzt, invalid context */
64         jmp     8f
65 2:      /*movl  4(%edx), %gs*/          /* we don't touch %gs */
66         movw    8(%edx), %fs
67         movw    12(%edx), %es
68         movw    16(%edx), %ds
69         movw    76(%edx), %ss
70         movl    20(%edx), %edi
71         movl    24(%edx), %esi
72         movl    28(%edx), %ebp
73         movl    %esp, %ecx              /* save current stack in ecx */
74         movl    72(%edx), %esp          /* switch to context defined stack */
75         pushl   60(%edx)                /* push return address on stack */
76         pushl   44(%edx)                /* push ecx on stack */
77         pushl   48(%edx)                /* push eax on stack */
78         /*
79          * if (mc_fpowned == MC_OWNEDFP_FPU || mc_fpowned == MC_OWNEDFP_PCB) {
80          *    if (mc_fpformat == MC_FPFMT_387)
81          *        restore 387 FP register format
82          *    else if (mc_fpformat == MC_FPFMT_XMM)
83          *        restore XMM/SSE FP register format
84          * }
85          */
86         cmpl    $MC_OWNEDFP_FPU, MC_OWNEDFP_OFFSET(%edx)
87         je      3f
88         cmpl    $MC_OWNEDFP_PCB, MC_OWNEDFP_OFFSET(%edx)
89         jne     5f
90 3:      cmpl    $MC_FPFMT_387, MC_FPFMT_OFFSET(%edx)
91         jne     4f
92         frstor  MC_FPREGS_OFFSET(%edx)  /* restore 387 FP regs */
93         jmp     6f
94 4:      cmpl    $MC_FPFMT_XMM, MC_FPFMT_OFFSET(%edx)
95         jne     5f
96         fxrstor MC_FPREGS_OFFSET(%edx)  /* restore XMM FP regs */
97         jmp     6f
98 5:      fninit
99         fldcw   MC_FP_CW_OFFSET(%edx)
100 6:      pushl   68(%edx)                /* push flags register on stack*/
101         movl    36(%edx), %ebx          /* restore ebx and edx */
102         movl    40(%edx), %edx
103         movl    12(%ecx), %eax          /* get 3rd arg (loc) */
104         cmpl    $0, %eax                /* do nothing if loc == null */
105         je      7f
106         movl    8(%ecx), %ecx           /* get 2nd arg (val) */
107         movl    %ecx, (%eax)            /* set loc = val */
108 7:      popfl                           /* restore flags after test */
109         popl    %eax                    /* restore eax and ecx last */
110         popl    %ecx
111 8:      ret
112
113 /*
114  * int thr_getcontext(mcontext_t *mcp);
115  *
116  * Returns -1 if there is an error, 0 no errors; 1 upon return
117  * from a setcontext().
118  */
119         .weak CNAME(_thr_getcontext)
120         .set CNAME(_thr_getcontext),CNAME(__thr_getcontext)
121 ENTRY(__thr_getcontext)
122         pushl   %edx                    /* save edx */
123         movl    8(%esp), %edx           /* get address of mcontext */
124         cmpl    $0, %edx                /* check for null pointer */
125         jne     1f
126         popl    %edx                    /* restore edx and stack */
127         movl    $-1, %eax
128         jmp     2f
129 1:      /*movw  %gs, 4(%edx)*/          /* we don't touch %gs */
130         movw    %fs, 8(%edx)
131         movw    %es, 12(%edx)
132         movw    %ds, 16(%edx)
133         movw    %ss, 76(%edx)
134         movl    %edi, 20(%edx)
135         movl    %esi, 24(%edx)
136         movl    %ebp, 28(%edx)
137         movl    %ebx, 36(%edx)
138         movl    $1, 48(%edx)            /* store successful return in eax */
139         popl    %eax                    /* get saved value of edx */
140         movl    %eax, 40(%edx)          /* save edx */
141         movl    %ecx, 44(%edx)
142         movl    (%esp), %eax            /* get return address */
143         movl    %eax, 60(%edx)          /* save return address */
144         fnstcw  MC_FP_CW_OFFSET(%edx)
145         movl    $MC_LEN, MC_LEN_OFFSET(%edx)
146         movl    $MC_FPFMT_NODEV, MC_FPFMT_OFFSET(%edx)  /* no FP */
147         movl    $MC_OWNEDFP_NONE, MC_OWNEDFP_OFFSET(%edx) /* no FP */
148         pushfl
149         popl    %eax                    /* get eflags */
150         movl    %eax, 68(%edx)          /* store eflags */
151         movl    %esp, %eax              /* setcontext pushes the return  */
152         addl    $4, %eax                /*   address onto the top of the */
153         movl    %eax, 72(%edx)          /*   stack; account for this     */
154         movl    40(%edx), %edx          /* restore edx -- is this needed? */
155         xorl    %eax, %eax              /* return 0 */
156 2:      ret