summaryrefslogtreecommitdiff
path: root/src/pal/src/arch/i386/context2.S
blob: 6c31b074cc18ba9ea98f7d0ac7baac4399ae9f51 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

.intel_syntax noprefix
#include "unixasmmacros.inc"
#include "asmconstants.h"

//
// Implementation of CONTEXT_CaptureContext for the Intel x86 platform.
//
//  extern void CONTEXT_CaptureContext(LPCONTEXT lpContext);
//
// This function is processor-dependent. It is used by exception handling,
// and is always apply to the current thread.
//
LEAF_ENTRY CONTEXT_CaptureContext, _TEXT
    // Store
    push  eax
    push  ebx

    // The stack will contain the following elements on the top of
    // the caller's stack
    //  [ebx]             / esp + 00
    //  [eax]             / esp + 04
    //  [ret]             / esp + 08
    //  [arg0: lpContext] / esp + 12

    mov   eax, [esp + 12] // eax will point to lpContext

    // Capture INTEGER registers
    mov   ebx, [esp + 4]
    mov   [eax + CONTEXT_Eax], ebx
    mov   ebx, [esp]
    mov   [eax + CONTEXT_Ebx], ebx
    mov   [eax + CONTEXT_Ecx], ecx
    mov   [eax + CONTEXT_Edx], edx
    mov   [eax + CONTEXT_Esi], esi
    mov   [eax + CONTEXT_Edi], edi

    // Capture CONTROL registers
    mov   [eax + CONTEXT_Ebp], ebp
    lea   ebx, [esp + 12]
    mov   [eax + CONTEXT_Esp], ebx
    mov   [eax + CONTEXT_ResumeEsp], ebx
    mov   ebx, [esp + 8]
    mov   [eax + CONTEXT_Eip], ebx

    push  cs
    xor   ebx, ebx
    pop   bx
    mov   [eax + CONTEXT_SegCs], ebx

    push  ss
    xor   ebx, ebx
    pop   bx
    mov   [eax + CONTEXT_SegSs], ebx

    pushf
    xor   ebx, ebx
    pop   bx
    mov   [eax + CONTEXT_EFlags], ebx

    test   BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT
    je      LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT)
    // Capture FPU status
    fnsave [eax + CONTEXT_FloatSave]
    frstor [eax + CONTEXT_FloatSave]
LOCAL_LABEL(Done_CONTEXT_FLOATING_POINT):

    test   BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_EXTENDED_REGISTERS
    je     LOCAL_LABEL(Done_CONTEXT_EXTENDED_REGISTERS)
    movdqu [eax + CONTEXT_Xmm0], xmm0
    movdqu [eax + CONTEXT_Xmm1], xmm1
    movdqu [eax + CONTEXT_Xmm2], xmm2
    movdqu [eax + CONTEXT_Xmm3], xmm3
    movdqu [eax + CONTEXT_Xmm4], xmm4
    movdqu [eax + CONTEXT_Xmm5], xmm5
    movdqu [eax + CONTEXT_Xmm6], xmm6
    movdqu [eax + CONTEXT_Xmm7], xmm7
LOCAL_LABEL(Done_CONTEXT_EXTENDED_REGISTERS):

    // Restore
    pop   ebx
    pop   eax
    ret
LEAF_END CONTEXT_CaptureContext, _TEXT

LEAF_ENTRY RtlCaptureContext, _TEXT
    push    eax
    mov     eax, [esp + 8]
    mov     DWORD PTR [eax + CONTEXT_ContextFlags], (CONTEXT_FLOATING_POINT)
    pop     eax
    jmp     C_FUNC(CONTEXT_CaptureContext)
LEAF_END RtlCaptureContext, _TEXT

LEAF_ENTRY RtlRestoreContext, _TEXT
    mov   eax, [esp + 4]

    test    BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_FLOATING_POINT
    je      LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT)
    frstor  [eax + CONTEXT_FloatSave]
LOCAL_LABEL(Done_Restore_CONTEXT_FLOATING_POINT):

    test   BYTE PTR [eax + CONTEXT_ContextFlags], CONTEXT_EXTENDED_REGISTERS
    je     LOCAL_LABEL(Done_Restore_CONTEXT_EXTENDED_REGISTERS)
    movdqu xmm0, [eax + CONTEXT_Xmm0]
    movdqu xmm1, [eax + CONTEXT_Xmm1]
    movdqu xmm2, [eax + CONTEXT_Xmm2]
    movdqu xmm3, [eax + CONTEXT_Xmm3]
    movdqu xmm4, [eax + CONTEXT_Xmm4]
    movdqu xmm5, [eax + CONTEXT_Xmm5]
    movdqu xmm6, [eax + CONTEXT_Xmm6]
    movdqu xmm7, [eax + CONTEXT_Xmm7]
LOCAL_LABEL(Done_Restore_CONTEXT_EXTENDED_REGISTERS):

    // Restore Stack
    mov   esp, [eax + CONTEXT_ResumeEsp]

    // Create a minimal frame
    push  DWORD PTR [eax + CONTEXT_Eip]

    // Restore register(s)
    mov   ebp, [eax + CONTEXT_Ebp]
    mov   edi, [eax + CONTEXT_Edi]
    mov   esi, [eax + CONTEXT_Esi]
    mov   edx, [eax + CONTEXT_Edx]
    mov   ecx, [eax + CONTEXT_Ecx]
    mov   ebx, [eax + CONTEXT_Ebx]
    mov   eax, [eax + CONTEXT_Eax]

    // Resume
    ret
LEAF_END RtlRestoreContext, _TEXT