xref: /reactos/sdk/lib/rtl/amd64/except_asm.S (revision 9393fc32)
1/*
2 * COPYRIGHT:       See COPYING in the top level directory
3 * PROJECT:         ReactOS Runtime Library (RTL)
4 * FILE:            lib/rtl/amd64/except_asm.S
5 * PURPOSE:         Exception support for AMD64
6 * PROGRAMMERS:     Timo Kreuzer (timo.kreuzer@reactos.org)
7 */
8
9/* INCLUDES ******************************************************************/
10
11#include <asm.inc>
12#include <ksamd64.inc>
13
14/* FUNCTIONS *****************************************************************/
15
16.code64
17
18/*
19 * VOID
20 * RtlCaptureContext(
21 *     _Out_ PCONTEXT ContextRecord@<rcx>);
22 */
23PUBLIC RtlCaptureContext
24.PROC RtlCaptureContext
25
26    /* Push rflags */
27    pushfq
28    .ALLOCSTACK 8
29    .ENDPROLOG
30
31    /* Save rax first, we use it later to copy some data */
32    mov [rcx + CxRax], rax
33
34    /* Set ContextFlags */
35    mov dword ptr [rcx + CxContextFlags], (CONTEXT_FULL or CONTEXT_SEGMENTS)
36
37    /* Store the basic register context */
38    mov [rcx + CxRcx], rcx
39    mov [rcx + CxRdx], rdx
40    mov [rcx + CxRbx], rbx
41    mov [rcx + CxRsi], rsi
42
43    /* Load return address in rax */
44    mov rax, [rsp + 8]
45
46    mov [rcx + CxRdi], rdi
47    mov [rcx + CxRbp], rbp
48    mov [rcx + CxR8], r8
49    mov [rcx + CxR9], r9
50    mov [rcx + CxR10], r10
51
52    /* Store the return address */
53    mov [rcx + CxRip], rax
54
55    mov [rcx + CxR11], r11
56    mov [rcx + CxR12], r12
57    mov [rcx + CxR13], r13
58    mov [rcx + CxR14], r14
59    mov [rcx + CxR15], r15
60
61    /* Load former stack pointer in rax */
62    lea rax, [rsp + 16]
63
64    /* Store segment selectors */
65    mov [rcx + CxSegCs], cs
66    mov [rcx + CxSegDs], ds
67    mov [rcx + CxSegEs], es
68    mov [rcx + CxSegFs], fs
69    mov [rcx + CxSegGs], gs
70    mov [rcx + CxSegSs], ss
71
72    /* Store stack pointer */
73    mov [rcx + CxRsp], rax
74
75    /* Store xmm registers */
76    movaps [rcx + CxXmm0], xmm0
77    movaps [rcx + CxXmm1], xmm1
78    movaps [rcx + CxXmm2], xmm2
79    movaps [rcx + CxXmm3], xmm3
80    movaps [rcx + CxXmm4], xmm4
81    movaps [rcx + CxXmm5], xmm5
82    movaps [rcx + CxXmm6], xmm6
83    movaps [rcx + CxXmm7], xmm7
84
85    /* Load rflags into eax */
86    mov eax, [rsp]
87
88    movaps [rcx + CxXmm8], xmm8
89    movaps [rcx + CxXmm9], xmm9
90    movaps [rcx + CxXmm10], xmm10
91    movaps [rcx + CxXmm11], xmm11
92    movaps [rcx + CxXmm12], xmm12
93    movaps [rcx + CxXmm13], xmm13
94    movaps [rcx + CxXmm14], xmm14
95    movaps [rcx + CxXmm15], xmm15
96
97    /* Store legacy floating point registers */
98    fxsave [rcx + CxFltSave]
99    stmxcsr [rcx + CxMxCsr]
100
101    /* Store rflags */
102    mov [rcx + CxEFlags], eax
103
104    /* Cleanup stack and return */
105    add rsp, 8
106    ret
107.ENDP
108
109/*
110 * VOID NTAPI
111 * RtlRestoreContext(
112 *     _In_ PCONTEXT ContextRecord@<rcx>,
113 *     PEXCEPTION_RECORD *ExceptionRecord@<rdx>);
114 */
115PUBLIC RtlRestoreContext
116.PROC RtlRestoreContext
117
118    /* Allocate space */
119    sub rsp, HEX(8)
120    .ALLOCSTACK 8
121    .ENDPROLOG
122
123    // TODO: Handle ExceptionRecord
124
125    /* Restore legacy floating point registers (It's slow, so do it first) */
126    ldmxcsr [rcx + CxMxCsr]
127    fxrstor [rcx + CxFltSave]
128
129    /* Load the target stack pointer into rdx */
130    mov rdx, [rcx + CxRsp]
131
132    /* Load EFlags into rax (zero extended) */
133    mov eax, [rcx + CxEFlags]
134
135    /* Load the return address into r8 */
136    mov r8, [rcx + CxRip]
137
138    /* Load rdx restore value into r9 */
139    mov r9, [rcx + CxRdx]
140
141    /* Restore xmm registers */
142    movaps xmm0, [rcx + CxXmm0]
143    movaps xmm1, [rcx + CxXmm1]
144    movaps xmm2, [rcx + CxXmm2]
145    movaps xmm3, [rcx + CxXmm3]
146    movaps xmm4, [rcx + CxXmm4]
147    movaps xmm5, [rcx + CxXmm5]
148    movaps xmm6, [rcx + CxXmm6]
149    movaps xmm7, [rcx + CxXmm7]
150    movaps xmm8, [rcx + CxXmm8]
151    movaps xmm9, [rcx + CxXmm9]
152    movaps xmm10, [rcx + CxXmm10]
153    movaps xmm11, [rcx + CxXmm11]
154    movaps xmm12, [rcx + CxXmm12]
155    movaps xmm13, [rcx + CxXmm13]
156    movaps xmm14, [rcx + CxXmm14]
157    movaps xmm15, [rcx + CxXmm15]
158
159    /* Copy Return address (now in r8) to the target stack */
160    mov [rdx - 2 * 8], r8
161
162    /* Copy Eflags (now in rax) to the target stack */
163    mov [rdx - 3 * 8], rax
164
165    /* Copy the value for rdx (now in r9) to the target stack */
166    mov [rdx - 4 * 8], r9
167
168    /* Restore the integer registers */
169    mov rbx, [rcx + CxRbx]
170    mov rsi, [rcx + CxRsi]
171    mov rdi, [rcx + CxRdi]
172    mov rbp, [rcx + CxRbp]
173    mov r10, [rcx + CxR10]
174    mov r11, [rcx + CxR11]
175    mov r12, [rcx + CxR12]
176    mov r13, [rcx + CxR13]
177    mov r14, [rcx + CxR14]
178    mov r15, [rcx + CxR15]
179
180    /* Restore segment selectors */
181    mov ds, [rcx + CxSegDs] // FIXME: WOW64 context?
182    mov es, [rcx + CxSegEs]
183    mov fs, [rcx + CxSegFs]
184    //mov gs, [rcx + CxSegGs]
185    //mov ss, [rcx + CxSegSs]
186
187    /* Restore the registers we used */
188    mov r8,  [rcx + CxR8]
189    mov r9,  [rcx + CxR9]
190
191    /* Check if we go to a different cs */
192    mov ax, cs
193    cmp [rcx + CxSegCs], ax
194    jne ReturnFar
195
196    /* Restore rax and rcx */
197    mov rax, [rcx + CxRax]
198    mov rcx, [rcx + CxRcx]
199
200    /* Switch to the target stack */
201    lea rsp, [rdx - 4 * 8]
202
203    /* Pop rdx from the stack */
204    pop rdx
205
206    /* Pop Eflags from the stack */
207    popfq
208
209    /* Return and fix up the stack */
210    ret 8
211
212ReturnFar:
213
214    /* Put cs on the stack for the far return */
215    mov ax, [rcx + CxSegCs]
216    mov [rdx - 1 * 8], ax
217
218    /* Load ss */
219    mov ss, [rcx + CxSegSs]
220
221    /* Restore rax and rcx */
222    mov rax, [rcx + CxRax]
223    mov rcx, [rcx + CxRcx]
224
225    /* Switch to the target stack */
226    lea rsp, [rdx - 4 * 8]
227
228    /* Pop rdx from the stack */
229    pop rdx
230
231    /* Pop Eflags from the stack */
232    popfq
233
234    /* Return far */
235    retf
236
237.ENDP
238
239END
240
241
242