xref: /dragonfly/lib/libc/x86_64/gen/qcontext.S (revision 335b9e93)
1/*
2 * Copyright (c) 2007 Matthew Dillon <dillon@backplane.com>
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 THE AUTHOR 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 * swapcontext_quick() and setcontext_quick().  There is *NO*
28 * getcontext_quick() routine on purpose.
29 *
30 * Quick routines are not required to save or resetore scratch registers,
31 * FP regs (which are scratch), or flags.
32 */
33#include <machine/asm.h>
34#include <cpu/specialreg.h>
35#include <asmcontext.h>
36
37	/*
38	 * void setcontext_quick(ucontext_t *ucp)
39	 *
40	 * Load the register context, effectively switching to the
41	 * new context.
42	 */
43        .weak   setcontext_quick
44        .set    setcontext_quick,_setcontext_quick
45ENTRY(_setcontext_quick)
46	addq	$UC_MCONTEXT,%rdi
47
48	/*	MC_ONSTACK(%rdi)	*/
49	/*	MC_RDI(%rdi)	- see below */
50	movq	MC_RSI(%rdi),%rsi
51	movq	MC_RDX(%rdi),%rdx
52	movq	MC_R8(%rdi),%r8
53	movq	MC_R9(%rdi),%r9
54	/*	MC_RAX(%rdi)	- see below */
55	movq	MC_RBX(%rdi),%rbx
56	movq	MC_RCX(%rdi),%rcx
57	movq	MC_RBP(%rdi),%rbp
58	movq	MC_R10(%rdi),%r10
59	movq	MC_R11(%rdi),%r11
60	movq	MC_R12(%rdi),%r12
61	movq	MC_R13(%rdi),%r13
62	movq	MC_R14(%rdi),%r14
63	movq	MC_R15(%rdi),%r15
64	/*	MC_TRAPNO(%rdi)	*/
65	/*	MC_ADDR(%rdi)	*/
66	/*	MC_FLAGS(%rdi)  */
67	/*	MC_ERR(%rdi)	*/
68	/*	MC_RIP(%rdi)	- see below */
69	/*	MC_CS(%rdi)	*/
70	/*	MC_RFLAGS(%rdi)	*/
71	/*	MC_RSP(%rdi)	- see below */
72	/*	MC_SS(%rdi)	*/
73
74	/*
75	 * Load the new stack pointer
76	 */
77	movq	MC_RSP(%rdi),%rsp
78
79	/*
80	 * Use %rax to hold the return pc.  function returns void.  Do
81	 * not mess with the target stack (particularly not the red-zone!).
82	 */
83	movq	MC_RIP(%rdi),%rax
84
85	/*
86	 * Finally rdi
87	 */
88	movq	MC_RDI(%rdi),%rdi
89	jmp	*%rax
90END(_setcontext_quick)
91
92
93	/*
94	 * void swapcontext_quick(ucontex_t *oucp, ucontext_t *nucp)
95	 *
96	 * Save the current state in oucp and switch to nucp.
97	 */
98        .weak   swapcontext_quick
99        .set    swapcontext_quick,_swapcontext_quick
100ENTRY(_swapcontext_quick)
101	/*
102	 * Save
103	 */
104	addq	$UC_MCONTEXT,%rdi
105	popq	%rax			/* return pc */
106
107	movq	%rsi,MC_RSI(%rdi)
108	movq	%rbx,MC_RBX(%rdi)
109	movq	%rdx,MC_RDX(%rdi)
110	movq	%rbp,MC_RBP(%rdi)
111	movq	%r10,MC_R10(%rdi)
112	movq	%r11,MC_R11(%rdi)
113	movq	%r12,MC_R12(%rdi)
114	movq	%r13,MC_R13(%rdi)
115	movq	%r14,MC_R14(%rdi)
116	movq	%r15,MC_R15(%rdi)
117	movq	%rsp,MC_RSP(%rdi)
118	movq	%rax,MC_RIP(%rdi)
119
120	/*
121	 * Restore (copy of setcontext above)
122	 */
123	movq	%rsi,%rdi
124	addq	$UC_MCONTEXT,%rdi
125
126	/*	MC_ONSTACK(%rdi)	*/
127	/*	MC_RDI(%rdi)	- see below */
128	movq	MC_RSI(%rdi),%rsi
129	movq	MC_RDX(%rdi),%rdx
130	/*	MC_RAX(%rdi)	- see below */
131	movq	MC_RBX(%rdi),%rbx
132	movq	MC_RCX(%rdi),%rcx
133	movq	MC_RBP(%rdi),%rbp
134	movq	MC_R10(%rdi),%r10
135	movq	MC_R11(%rdi),%r11
136	movq	MC_R12(%rdi),%r12
137	movq	MC_R13(%rdi),%r13
138	movq	MC_R14(%rdi),%r14
139	movq	MC_R15(%rdi),%r15
140	/*	MC_TRAPNO(%rdi)	*/
141	/*	MC_ADDR(%rdi)	*/
142	/*	MC_FLAGS(%rdi)  */
143	/*	MC_ERR(%rdi)	*/
144	/*	MC_RIP(%rdi)	- see below */
145	/*	MC_CS(%rdi)	*/
146	/*	MC_RFLAGS(%rdi)	*/
147	/*	MC_RSP(%rdi)	- see below */
148	/*	MC_SS(%rdi)	*/
149
150	/*
151	 * Load the new stack pointer
152	 */
153	movq	MC_RSP(%rdi),%rsp
154
155	/*
156	 * Use %rax to hold the return pc.  function returns void.  Do
157	 * not mess with the target stack (particularly not the red-zone!).
158	 */
159	movq	MC_RIP(%rdi),%rax
160
161	/*
162	 * Finally rdi
163	 */
164	movq	MC_RDI(%rdi),%rdi
165	jmp	*%rax
166
167END(_swapcontext_quick)
168
169	.section .note.GNU-stack,"",%progbits
170