2 * Copyright (c) 2001 Daniel Eischen <deischen@freebsd.org>.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
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.
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
27 #include <machine/asm.h>
28 __FBSDID("$FreeBSD$");
31 * Where do we define these?
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 */
47 * int thr_setcontext(mcontext_t *mcp, intptr_t val, intptr_t *loc)
49 * Restores the context in mcp.
51 * Returns 0 if there are no errors; -1 otherwise
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 */
61 1: cmpl $MC_LEN, MC_LEN_OFFSET(%edx) /* is context valid? */
63 movl $-1, %eax /* bzzzt, invalid context */
65 2: /*movl 4(%edx), %gs*/ /* we don't touch %gs */
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 */
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
86 cmpl $MC_OWNEDFP_FPU, MC_OWNEDFP_OFFSET(%edx)
88 cmpl $MC_OWNEDFP_PCB, MC_OWNEDFP_OFFSET(%edx)
90 3: cmpl $MC_FPFMT_387, MC_FPFMT_OFFSET(%edx)
92 frstor MC_FPREGS_OFFSET(%edx) /* restore 387 FP regs */
94 4: cmpl $MC_FPFMT_XMM, MC_FPFMT_OFFSET(%edx)
96 fxrstor MC_FPREGS_OFFSET(%edx) /* restore XMM FP regs */
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 */
103 movl 12(%ecx), %eax /* get 3rd arg (loc) */
104 cmpl $0, %eax /* do nothing if loc == null */
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 */
114 * int thr_getcontext(mcontext_t *mcp);
116 * Returns -1 if there is an error, 0 no errors; 1 upon return
117 * from a setcontext().
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 */
126 popl %edx /* restore edx and stack */
129 1: /*movw %gs, 4(%edx)*/ /* we don't touch %gs */
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 */
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 */
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 */