1 | // Licensed to the .NET Foundation under one or more agreements. |
2 | // The .NET Foundation licenses this file to you under the MIT license. |
3 | // See the LICENSE file in the project root for more information. |
4 | // |
5 | // crosscomp.h - cross-compilation enablement structures. |
6 | // |
7 | |
8 | |
9 | #pragma once |
10 | |
11 | #if (!defined(_WIN64) && defined(_TARGET_64BIT_)) || (defined(_WIN64) && !defined(_TARGET_64BIT_)) |
12 | #define CROSSBITNESS_COMPILE |
13 | #endif |
14 | |
15 | #if !defined(_ARM_) && defined(_TARGET_ARM_) // Non-ARM Host managing ARM related code |
16 | |
17 | #ifndef CROSS_COMPILE |
18 | #define CROSS_COMPILE |
19 | #endif |
20 | |
21 | #define ARM_MAX_BREAKPOINTS 8 |
22 | #define ARM_MAX_WATCHPOINTS 1 |
23 | |
24 | #define CONTEXT_UNWOUND_TO_CALL 0x20000000 |
25 | |
26 | typedef struct _NEON128 { |
27 | ULONGLONG Low; |
28 | LONGLONG High; |
29 | } NEON128, *PNEON128; |
30 | |
31 | typedef struct DECLSPEC_ALIGN(8) _T_CONTEXT { |
32 | // |
33 | // Control flags. |
34 | // |
35 | |
36 | DWORD ContextFlags; |
37 | |
38 | // |
39 | // Integer registers |
40 | // |
41 | |
42 | DWORD R0; |
43 | DWORD R1; |
44 | DWORD R2; |
45 | DWORD R3; |
46 | DWORD R4; |
47 | DWORD R5; |
48 | DWORD R6; |
49 | DWORD R7; |
50 | DWORD R8; |
51 | DWORD R9; |
52 | DWORD R10; |
53 | DWORD R11; |
54 | DWORD R12; |
55 | |
56 | // |
57 | // Control Registers |
58 | // |
59 | |
60 | DWORD Sp; |
61 | DWORD Lr; |
62 | DWORD Pc; |
63 | DWORD Cpsr; |
64 | |
65 | // |
66 | // Floating Point/NEON Registers |
67 | // |
68 | |
69 | DWORD Fpscr; |
70 | DWORD Padding; |
71 | union { |
72 | NEON128 Q[16]; |
73 | ULONGLONG D[32]; |
74 | DWORD S[32]; |
75 | }; |
76 | |
77 | // |
78 | // Debug registers |
79 | // |
80 | |
81 | DWORD Bvr[ARM_MAX_BREAKPOINTS]; |
82 | DWORD Bcr[ARM_MAX_BREAKPOINTS]; |
83 | DWORD Wvr[ARM_MAX_WATCHPOINTS]; |
84 | DWORD Wcr[ARM_MAX_WATCHPOINTS]; |
85 | |
86 | DWORD Padding2[2]; |
87 | |
88 | } T_CONTEXT, *PT_CONTEXT; |
89 | |
90 | // |
91 | // Define function table entry - a function table entry is generated for |
92 | // each frame function. |
93 | // |
94 | |
95 | #ifndef FEATURE_PAL |
96 | #ifdef _X86_ |
97 | typedef struct _RUNTIME_FUNCTION { |
98 | DWORD BeginAddress; |
99 | DWORD UnwindData; |
100 | } RUNTIME_FUNCTION, *PRUNTIME_FUNCTION; |
101 | |
102 | // |
103 | // Define unwind history table structure. |
104 | // |
105 | |
106 | #define UNWIND_HISTORY_TABLE_SIZE 12 |
107 | |
108 | typedef struct _UNWIND_HISTORY_TABLE_ENTRY { |
109 | DWORD ImageBase; |
110 | PRUNTIME_FUNCTION FunctionEntry; |
111 | } UNWIND_HISTORY_TABLE_ENTRY, *PUNWIND_HISTORY_TABLE_ENTRY; |
112 | |
113 | typedef struct _UNWIND_HISTORY_TABLE { |
114 | DWORD Count; |
115 | BYTE LocalHint; |
116 | BYTE GlobalHint; |
117 | BYTE Search; |
118 | BYTE Once; |
119 | DWORD LowAddress; |
120 | DWORD HighAddress; |
121 | UNWIND_HISTORY_TABLE_ENTRY Entry[UNWIND_HISTORY_TABLE_SIZE]; |
122 | } UNWIND_HISTORY_TABLE, *PUNWIND_HISTORY_TABLE; |
123 | #endif // _X86_ |
124 | #endif // !FEATURE_PAL |
125 | |
126 | |
127 | // |
128 | // Nonvolatile context pointer record. |
129 | // |
130 | |
131 | typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS { |
132 | |
133 | PDWORD R4; |
134 | PDWORD R5; |
135 | PDWORD R6; |
136 | PDWORD R7; |
137 | PDWORD R8; |
138 | PDWORD R9; |
139 | PDWORD R10; |
140 | PDWORD R11; |
141 | PDWORD Lr; |
142 | |
143 | PULONGLONG D8; |
144 | PULONGLONG D9; |
145 | PULONGLONG D10; |
146 | PULONGLONG D11; |
147 | PULONGLONG D12; |
148 | PULONGLONG D13; |
149 | PULONGLONG D14; |
150 | PULONGLONG D15; |
151 | |
152 | } T_KNONVOLATILE_CONTEXT_POINTERS, *PT_KNONVOLATILE_CONTEXT_POINTERS; |
153 | |
154 | // |
155 | // Define dynamic function table entry. |
156 | // |
157 | |
158 | typedef |
159 | PRUNTIME_FUNCTION |
160 | (*PGET_RUNTIME_FUNCTION_CALLBACK) ( |
161 | IN DWORD64 ControlPc, |
162 | IN PVOID Context |
163 | ); |
164 | |
165 | typedef struct _T_DISPATCHER_CONTEXT { |
166 | ULONG ControlPc; |
167 | ULONG ImageBase; |
168 | PRUNTIME_FUNCTION FunctionEntry; |
169 | ULONG EstablisherFrame; |
170 | ULONG TargetPc; |
171 | PT_CONTEXT ContextRecord; |
172 | PEXCEPTION_ROUTINE LanguageHandler; |
173 | PVOID HandlerData; |
174 | PUNWIND_HISTORY_TABLE HistoryTable; |
175 | ULONG ScopeIndex; |
176 | BOOLEAN ControlPcIsUnwound; |
177 | PUCHAR NonVolatileRegisters; |
178 | } T_DISPATCHER_CONTEXT, *PT_DISPATCHER_CONTEXT; |
179 | |
180 | #if defined(FEATURE_PAL) || defined(_X86_) |
181 | #define T_RUNTIME_FUNCTION RUNTIME_FUNCTION |
182 | #define PT_RUNTIME_FUNCTION PRUNTIME_FUNCTION |
183 | #else |
184 | typedef struct _T_RUNTIME_FUNCTION { |
185 | DWORD BeginAddress; |
186 | DWORD UnwindData; |
187 | } T_RUNTIME_FUNCTION, *PT_RUNTIME_FUNCTION; |
188 | #endif |
189 | |
190 | #elif defined(_AMD64_) && defined(_TARGET_ARM64_) // Host amd64 managing ARM64 related code |
191 | |
192 | #ifndef CROSS_COMPILE |
193 | #define CROSS_COMPILE |
194 | #endif |
195 | |
196 | // |
197 | // Specify the number of breakpoints and watchpoints that the OS |
198 | // will track. Architecturally, ARM64 supports up to 16. In practice, |
199 | // however, almost no one implements more than 4 of each. |
200 | // |
201 | |
202 | #define ARM64_MAX_BREAKPOINTS 8 |
203 | #define ARM64_MAX_WATCHPOINTS 2 |
204 | |
205 | #define CONTEXT_UNWOUND_TO_CALL 0x20000000 |
206 | |
207 | typedef union _NEON128 { |
208 | struct { |
209 | ULONGLONG Low; |
210 | LONGLONG High; |
211 | }; |
212 | double D[2]; |
213 | float S[4]; |
214 | WORD H[8]; |
215 | BYTE B[16]; |
216 | } NEON128, *PNEON128; |
217 | |
218 | typedef struct DECLSPEC_ALIGN(16) _T_CONTEXT { |
219 | |
220 | // |
221 | // Control flags. |
222 | // |
223 | |
224 | /* +0x000 */ DWORD ContextFlags; |
225 | |
226 | // |
227 | // Integer registers |
228 | // |
229 | |
230 | /* +0x004 */ DWORD Cpsr; // NZVF + DAIF + CurrentEL + SPSel |
231 | /* +0x008 */ union { |
232 | struct { |
233 | DWORD64 X0; |
234 | DWORD64 X1; |
235 | DWORD64 X2; |
236 | DWORD64 X3; |
237 | DWORD64 X4; |
238 | DWORD64 X5; |
239 | DWORD64 X6; |
240 | DWORD64 X7; |
241 | DWORD64 X8; |
242 | DWORD64 X9; |
243 | DWORD64 X10; |
244 | DWORD64 X11; |
245 | DWORD64 X12; |
246 | DWORD64 X13; |
247 | DWORD64 X14; |
248 | DWORD64 X15; |
249 | DWORD64 X16; |
250 | DWORD64 X17; |
251 | DWORD64 X18; |
252 | DWORD64 X19; |
253 | DWORD64 X20; |
254 | DWORD64 X21; |
255 | DWORD64 X22; |
256 | DWORD64 X23; |
257 | DWORD64 X24; |
258 | DWORD64 X25; |
259 | DWORD64 X26; |
260 | DWORD64 X27; |
261 | DWORD64 X28; |
262 | }; |
263 | DWORD64 X[29]; |
264 | }; |
265 | /* +0x0f0 */ DWORD64 Fp; |
266 | /* +0x0f8 */ DWORD64 Lr; |
267 | /* +0x100 */ DWORD64 Sp; |
268 | /* +0x108 */ DWORD64 Pc; |
269 | |
270 | // |
271 | // Floating Point/NEON Registers |
272 | // |
273 | |
274 | /* +0x110 */ NEON128 V[32]; |
275 | /* +0x310 */ DWORD Fpcr; |
276 | /* +0x314 */ DWORD Fpsr; |
277 | |
278 | // |
279 | // Debug registers |
280 | // |
281 | |
282 | /* +0x318 */ DWORD Bcr[ARM64_MAX_BREAKPOINTS]; |
283 | /* +0x338 */ DWORD64 Bvr[ARM64_MAX_BREAKPOINTS]; |
284 | /* +0x378 */ DWORD Wcr[ARM64_MAX_WATCHPOINTS]; |
285 | /* +0x380 */ DWORD64 Wvr[ARM64_MAX_WATCHPOINTS]; |
286 | /* +0x390 */ |
287 | |
288 | } T_CONTEXT, *PT_CONTEXT; |
289 | |
290 | // _IMAGE_ARM64_RUNTIME_FUNCTION_ENTRY (see ExternalAPIs\Win9CoreSystem\inc\winnt.h) |
291 | typedef struct _T_RUNTIME_FUNCTION { |
292 | DWORD BeginAddress; |
293 | union { |
294 | DWORD UnwindData; |
295 | struct { |
296 | DWORD Flag : 2; |
297 | DWORD FunctionLength : 11; |
298 | DWORD RegF : 3; |
299 | DWORD RegI : 4; |
300 | DWORD H : 1; |
301 | DWORD CR : 2; |
302 | DWORD FrameSize : 9; |
303 | } PackedUnwindData; |
304 | }; |
305 | } T_RUNTIME_FUNCTION, *PT_RUNTIME_FUNCTION; |
306 | |
307 | |
308 | // |
309 | // Define exception dispatch context structure. |
310 | // |
311 | |
312 | typedef struct _T_DISPATCHER_CONTEXT { |
313 | DWORD64 ControlPc; |
314 | DWORD64 ImageBase; |
315 | PT_RUNTIME_FUNCTION FunctionEntry; |
316 | DWORD64 EstablisherFrame; |
317 | DWORD64 TargetPc; |
318 | PCONTEXT ContextRecord; |
319 | PEXCEPTION_ROUTINE LanguageHandler; |
320 | PVOID HandlerData; |
321 | PUNWIND_HISTORY_TABLE HistoryTable; |
322 | DWORD ScopeIndex; |
323 | BOOLEAN ControlPcIsUnwound; |
324 | PBYTE NonVolatileRegisters; |
325 | } T_DISPATCHER_CONTEXT, *PT_DISPATCHER_CONTEXT; |
326 | |
327 | |
328 | |
329 | // |
330 | // Nonvolatile context pointer record. |
331 | // |
332 | |
333 | typedef struct _T_KNONVOLATILE_CONTEXT_POINTERS { |
334 | |
335 | PDWORD64 X19; |
336 | PDWORD64 X20; |
337 | PDWORD64 X21; |
338 | PDWORD64 X22; |
339 | PDWORD64 X23; |
340 | PDWORD64 X24; |
341 | PDWORD64 X25; |
342 | PDWORD64 X26; |
343 | PDWORD64 X27; |
344 | PDWORD64 X28; |
345 | PDWORD64 Fp; |
346 | PDWORD64 Lr; |
347 | |
348 | PDWORD64 D8; |
349 | PDWORD64 D9; |
350 | PDWORD64 D10; |
351 | PDWORD64 D11; |
352 | PDWORD64 D12; |
353 | PDWORD64 D13; |
354 | PDWORD64 D14; |
355 | PDWORD64 D15; |
356 | |
357 | } T_KNONVOLATILE_CONTEXT_POINTERS, *PT_KNONVOLATILE_CONTEXT_POINTERS; |
358 | |
359 | #else |
360 | |
361 | #define T_CONTEXT CONTEXT |
362 | #define PT_CONTEXT PCONTEXT |
363 | |
364 | #define T_DISPATCHER_CONTEXT DISPATCHER_CONTEXT |
365 | #define PT_DISPATCHER_CONTEXT PDISPATCHER_CONTEXT |
366 | |
367 | #define T_KNONVOLATILE_CONTEXT_POINTERS KNONVOLATILE_CONTEXT_POINTERS |
368 | #define PT_KNONVOLATILE_CONTEXT_POINTERS PKNONVOLATILE_CONTEXT_POINTERS |
369 | |
370 | #define T_RUNTIME_FUNCTION RUNTIME_FUNCTION |
371 | #define PT_RUNTIME_FUNCTION PRUNTIME_FUNCTION |
372 | |
373 | #endif |
374 | |
375 | |
376 | #ifdef CROSSGEN_COMPILE |
377 | void CrossGenNotSupported(const char * message); |
378 | #endif |
379 | |