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
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
|
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//
//
// Implementation of _CONTEXT_CaptureContext for the ARM platform.
// This function is processor dependent. It is used by exception handling,
// and is always apply to the current thread.
//
#include "unixasmmacros.inc"
.syntax unified
.thumb
#define CONTEXT_ARM 0x00200000
#define CONTEXT_CONTROL 1 // Sp, Lr, Pc, Cpsr
#define CONTEXT_INTEGER 2 // R0-R12
#define CONTEXT_SEGMENTS 4 //
#define CONTEXT_FLOATING_POINT 8
#define CONTEXT_DEBUG_REGISTERS 16 //
#define CONTEXT_FULL (CONTEXT_CONTROL | CONTEXT_INTEGER | CONTEXT_FLOATING_POINT)
#define CONTEXT_ContextFlags 0
#define CONTEXT_R0 CONTEXT_ContextFlags+4
#define CONTEXT_R1 CONTEXT_R0+4
#define CONTEXT_R2 CONTEXT_R1+4
#define CONTEXT_R3 CONTEXT_R2+4
#define CONTEXT_R4 CONTEXT_R3+4
#define CONTEXT_R5 CONTEXT_R4+4
#define CONTEXT_R6 CONTEXT_R5+4
#define CONTEXT_R7 CONTEXT_R6+4
#define CONTEXT_R8 CONTEXT_R7+4
#define CONTEXT_R9 CONTEXT_R8+4
#define CONTEXT_R10 CONTEXT_R9+4
#define CONTEXT_R11 CONTEXT_R10+4
#define CONTEXT_R12 CONTEXT_R11+4
#define CONTEXT_Sp CONTEXT_R12+4
#define CONTEXT_Lr CONTEXT_Sp+4
#define CONTEXT_Pc CONTEXT_Lr+4
#define CONTEXT_Cpsr CONTEXT_Pc+4
#define CONTEXT_Fpscr CONTEXT_Cpsr+4
#define CONTEXT_Padding CONTEXT_Fpscr+4
#define CONTEXT_D0 CONTEXT_Padding+4
#define CONTEXT_D1 CONTEXT_D0+8
#define CONTEXT_D2 CONTEXT_D1+8
#define CONTEXT_D3 CONTEXT_D2+8
#define CONTEXT_D4 CONTEXT_D3+8
#define CONTEXT_D5 CONTEXT_D4+8
#define CONTEXT_D6 CONTEXT_D5+8
#define CONTEXT_D7 CONTEXT_D6+8
#define CONTEXT_D8 CONTEXT_D7+8
#define CONTEXT_D9 CONTEXT_D8+8
#define CONTEXT_D10 CONTEXT_D9+8
#define CONTEXT_D11 CONTEXT_D10+8
#define CONTEXT_D12 CONTEXT_D11+8
#define CONTEXT_D13 CONTEXT_D12+8
#define CONTEXT_D14 CONTEXT_D13+8
#define CONTEXT_D15 CONTEXT_D14+8
#define CONTEXT_D16 CONTEXT_D15+8
#define CONTEXT_D17 CONTEXT_D16+8
#define CONTEXT_D18 CONTEXT_D17+8
#define CONTEXT_D19 CONTEXT_D18+8
#define CONTEXT_D20 CONTEXT_D19+8
#define CONTEXT_D21 CONTEXT_D20+8
#define CONTEXT_D22 CONTEXT_D21+8
#define CONTEXT_D23 CONTEXT_D22+8
#define CONTEXT_D24 CONTEXT_D23+8
#define CONTEXT_D25 CONTEXT_D24+8
#define CONTEXT_D26 CONTEXT_D25+8
#define CONTEXT_D27 CONTEXT_D26+8
#define CONTEXT_D28 CONTEXT_D27+8
#define CONTEXT_D29 CONTEXT_D28+8
#define CONTEXT_D30 CONTEXT_D29+8
#define CONTEXT_D31 CONTEXT_D30+8
// Incoming:
// r0: Context*
//
LEAF_ENTRY CONTEXT_CaptureContext, _TEXT
// Ensure we save these registers
push {r4-r11}
// Save processor flags before calling any of the following 'test' instructions
// because they will modify state of some flags
push {r1}
mrs r1, apsr // Get APSR - equivalent to eflags
push {r1} // Save APSR
END_PROLOGUE
push {r2}
ldr r2, [r0, #(CONTEXT_ContextFlags)]
tst r2, #(CONTEXT_INTEGER)
pop {r2}
// Add 4 to stack so we point at R1, pop, then sub 8 to point at APSR
add sp, sp, #4
pop {r1}
sub sp, sp, #8
itttt ne
strne r0, [r0, #(CONTEXT_R0)]
addne r0, CONTEXT_R1
stmiane r0, {r1-r12}
subne r0, CONTEXT_R1
ldr r2, [r0, #(CONTEXT_ContextFlags)]
tst r2, #(CONTEXT_CONTROL)
ittt ne
addne sp, sp, #(10*4) // This needs to put the stack in the same state as it started
strne sp, [r0, #(CONTEXT_Sp)]
subne sp, sp, #(10*4)
itt ne
strne lr, [r0, #(CONTEXT_Lr)]
strne lr, [r0, #(CONTEXT_Pc)]
// Get the APSR pushed onto the stack at the start
pop {r1}
it ne
strne r1, [r0, #(CONTEXT_Cpsr)]
ldr r2, [r0, #(CONTEXT_ContextFlags)]
tst r2, #(CONTEXT_FLOATING_POINT)
itt ne
vmrsne r3, fpscr
strne r3, [r0, #(CONTEXT_Fpscr)]
itttt ne
addne r0, CONTEXT_D0
vstmiane r0!, {d0-d15}
vstmiane r0!, {d16-d31}
subne r0, CONTEXT_D31
// Make sure sp is restored
add sp, sp, #4
// Restore callee saved registers
pop {r4-r11}
bx lr
LEAF_END CONTEXT_CaptureContext, _TEXT
// Incoming:
// R0: Context*
//
LEAF_ENTRY RtlCaptureContext, _TEXT
push {r1}
mov r1, #0
orr r1, r1, #CONTEXT_ARM
orr r1, r1, #CONTEXT_INTEGER
orr r1, r1, #CONTEXT_CONTROL
orr r1, r1, #CONTEXT_FLOATING_POINT
str r1, [r0, #(CONTEXT_ContextFlags)]
pop {r1}
b C_FUNC(CONTEXT_CaptureContext)
LEAF_END RtlCaptureContext, _TEXT
// Incoming:
// r0: Context*
// r1: Exception*
//
LEAF_ENTRY RtlRestoreContext, _TEXT
END_PROLOGUE
ldr r2, [r0, #(CONTEXT_ContextFlags)]
tst r2, #(CONTEXT_FLOATING_POINT)
itttt ne
addne r0, CONTEXT_D0
vldmiane r0!, {d0-d15}
vldmiane r0, {d16-d31}
subne r0, CONTEXT_D16
itt ne
ldrne r3, [r0, #(CONTEXT_Fpscr)]
vmrsne r3, FPSCR
ldr r2, [r0, #(CONTEXT_ContextFlags)]
tst r2, #(CONTEXT_CONTROL)
it eq
beq LOCAL_LABEL(No_Restore_CONTEXT_CONTROL)
ldr r2, [r0, #(CONTEXT_ContextFlags)]
tst r2, #(CONTEXT_INTEGER)
it eq
beq LOCAL_LABEL(No_Restore_CONTEXT_INTEGER)
ldr R2, [r0, #(CONTEXT_Cpsr)]
msr APSR, r2
add r0, CONTEXT_R0
ldmia r0, {r0-r12, sp, lr, pc}
LOCAL_LABEL(No_Restore_CONTEXT_INTEGER):
ldr r2, [r0, #(CONTEXT_Cpsr)]
msr APSR, r2
add r0, CONTEXT_Sp
ldmia r0, {sp, lr, pc}
LOCAL_LABEL(No_Restore_CONTEXT_CONTROL):
ldr r2, [r0, #(CONTEXT_ContextFlags)]
tst r2, #(CONTEXT_INTEGER)
itt ne
addne r0, CONTEXT_R0
ldmiane r0, {r0-r12}
sub sp, sp, #4
bx lr
LEAF_END RtlRestoreContext, _TEXT
|