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