1 | //===-- RegisterContext_x86.h -----------------------------------*- C++ -*-===// |
2 | // |
3 | // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. |
4 | // See https://llvm.org/LICENSE.txt for license information. |
5 | // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception |
6 | // |
7 | //===----------------------------------------------------------------------===// |
8 | |
9 | #ifndef LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXT_X86_H |
10 | #define LLDB_SOURCE_PLUGINS_PROCESS_UTILITY_REGISTERCONTEXT_X86_H |
11 | |
12 | #include <cstddef> |
13 | #include <cstdint> |
14 | |
15 | #include "llvm/ADT/ArrayRef.h" |
16 | #include "llvm/ADT/BitmaskEnum.h" |
17 | #include "llvm/Support/Compiler.h" |
18 | |
19 | namespace lldb_private { |
20 | // i386 ehframe, dwarf regnums |
21 | |
22 | // Register numbers seen in eh_frame (eRegisterKindEHFrame) on i386 systems |
23 | // (non-Darwin) |
24 | // |
25 | enum { |
26 | ehframe_eax_i386 = 0, |
27 | ehframe_ecx_i386, |
28 | ehframe_edx_i386, |
29 | ehframe_ebx_i386, |
30 | |
31 | // on Darwin esp & ebp are reversed in the eh_frame section for i386 (versus |
32 | // dwarf's reg numbering). |
33 | // To be specific: |
34 | // i386+darwin eh_frame: 4 is ebp, 5 is esp |
35 | // i386+everyone else eh_frame: 4 is esp, 5 is ebp |
36 | // i386 dwarf: 4 is esp, 5 is ebp |
37 | // lldb will get the darwin-specific eh_frame reg numberings from debugserver, |
38 | // or the ABI, so we |
39 | // only encode the generally correct 4 == esp, 5 == ebp numbers in this |
40 | // generic header. |
41 | |
42 | ehframe_esp_i386, |
43 | ehframe_ebp_i386, |
44 | ehframe_esi_i386, |
45 | ehframe_edi_i386, |
46 | ehframe_eip_i386, |
47 | ehframe_eflags_i386, |
48 | ehframe_st0_i386 = 12, |
49 | ehframe_st1_i386, |
50 | ehframe_st2_i386, |
51 | ehframe_st3_i386, |
52 | ehframe_st4_i386, |
53 | ehframe_st5_i386, |
54 | ehframe_st6_i386, |
55 | ehframe_st7_i386, |
56 | ehframe_xmm0_i386 = 21, |
57 | ehframe_xmm1_i386, |
58 | ehframe_xmm2_i386, |
59 | ehframe_xmm3_i386, |
60 | ehframe_xmm4_i386, |
61 | ehframe_xmm5_i386, |
62 | ehframe_xmm6_i386, |
63 | ehframe_xmm7_i386, |
64 | ehframe_mm0_i386 = 29, |
65 | ehframe_mm1_i386, |
66 | ehframe_mm2_i386, |
67 | ehframe_mm3_i386, |
68 | ehframe_mm4_i386, |
69 | ehframe_mm5_i386, |
70 | ehframe_mm6_i386, |
71 | ehframe_mm7_i386, |
72 | }; |
73 | |
74 | // DWARF register numbers (eRegisterKindDWARF) |
75 | // Intel's x86 or IA-32 |
76 | enum { |
77 | // General Purpose Registers. |
78 | dwarf_eax_i386 = 0, |
79 | dwarf_ecx_i386, |
80 | dwarf_edx_i386, |
81 | dwarf_ebx_i386, |
82 | dwarf_esp_i386, |
83 | dwarf_ebp_i386, |
84 | dwarf_esi_i386, |
85 | dwarf_edi_i386, |
86 | dwarf_eip_i386, |
87 | dwarf_eflags_i386, |
88 | // Floating Point Registers |
89 | dwarf_st0_i386 = 11, |
90 | dwarf_st1_i386, |
91 | dwarf_st2_i386, |
92 | dwarf_st3_i386, |
93 | dwarf_st4_i386, |
94 | dwarf_st5_i386, |
95 | dwarf_st6_i386, |
96 | dwarf_st7_i386, |
97 | // SSE Registers |
98 | dwarf_xmm0_i386 = 21, |
99 | dwarf_xmm1_i386, |
100 | dwarf_xmm2_i386, |
101 | dwarf_xmm3_i386, |
102 | dwarf_xmm4_i386, |
103 | dwarf_xmm5_i386, |
104 | dwarf_xmm6_i386, |
105 | dwarf_xmm7_i386, |
106 | // MMX Registers |
107 | dwarf_mm0_i386 = 29, |
108 | dwarf_mm1_i386, |
109 | dwarf_mm2_i386, |
110 | dwarf_mm3_i386, |
111 | dwarf_mm4_i386, |
112 | dwarf_mm5_i386, |
113 | dwarf_mm6_i386, |
114 | dwarf_mm7_i386, |
115 | dwarf_fctrl_i386 = 37, // x87 control word |
116 | dwarf_fstat_i386 = 38, // x87 status word |
117 | dwarf_mxcsr_i386 = 39, |
118 | dwarf_es_i386 = 40, |
119 | dwarf_cs_i386 = 41, |
120 | dwarf_ss_i386 = 42, |
121 | dwarf_ds_i386 = 43, |
122 | dwarf_fs_i386 = 44, |
123 | dwarf_gs_i386 = 45, |
124 | |
125 | // I believe the ymm registers use the dwarf_xmm%_i386 register numbers and |
126 | // then differentiate based on size of the register. |
127 | dwarf_bnd0_i386 = 101, |
128 | dwarf_bnd1_i386, |
129 | dwarf_bnd2_i386, |
130 | dwarf_bnd3_i386, |
131 | }; |
132 | |
133 | // AMD x86_64, AMD64, Intel EM64T, or Intel 64 ehframe, dwarf regnums |
134 | |
135 | // EHFrame and DWARF Register numbers (eRegisterKindEHFrame & |
136 | // eRegisterKindDWARF) |
137 | // This is the spec I used (as opposed to x86-64-abi-0.99.pdf): |
138 | // http://software.intel.com/sites/default/files/article/402129/mpx-linux64-abi.pdf |
139 | enum { |
140 | // GP Registers |
141 | dwarf_rax_x86_64 = 0, |
142 | dwarf_rdx_x86_64, |
143 | dwarf_rcx_x86_64, |
144 | dwarf_rbx_x86_64, |
145 | dwarf_rsi_x86_64, |
146 | dwarf_rdi_x86_64, |
147 | dwarf_rbp_x86_64, |
148 | dwarf_rsp_x86_64, |
149 | // Extended GP Registers |
150 | dwarf_r8_x86_64 = 8, |
151 | dwarf_r9_x86_64, |
152 | dwarf_r10_x86_64, |
153 | dwarf_r11_x86_64, |
154 | dwarf_r12_x86_64, |
155 | dwarf_r13_x86_64, |
156 | dwarf_r14_x86_64, |
157 | dwarf_r15_x86_64, |
158 | // Return Address (RA) mapped to RIP |
159 | dwarf_rip_x86_64 = 16, |
160 | // SSE Vector Registers |
161 | dwarf_xmm0_x86_64 = 17, |
162 | dwarf_xmm1_x86_64, |
163 | dwarf_xmm2_x86_64, |
164 | dwarf_xmm3_x86_64, |
165 | dwarf_xmm4_x86_64, |
166 | dwarf_xmm5_x86_64, |
167 | dwarf_xmm6_x86_64, |
168 | dwarf_xmm7_x86_64, |
169 | dwarf_xmm8_x86_64, |
170 | dwarf_xmm9_x86_64, |
171 | dwarf_xmm10_x86_64, |
172 | dwarf_xmm11_x86_64, |
173 | dwarf_xmm12_x86_64, |
174 | dwarf_xmm13_x86_64, |
175 | dwarf_xmm14_x86_64, |
176 | dwarf_xmm15_x86_64, |
177 | // Floating Point Registers |
178 | dwarf_st0_x86_64 = 33, |
179 | dwarf_st1_x86_64, |
180 | dwarf_st2_x86_64, |
181 | dwarf_st3_x86_64, |
182 | dwarf_st4_x86_64, |
183 | dwarf_st5_x86_64, |
184 | dwarf_st6_x86_64, |
185 | dwarf_st7_x86_64, |
186 | // MMX Registers |
187 | dwarf_mm0_x86_64 = 41, |
188 | dwarf_mm1_x86_64, |
189 | dwarf_mm2_x86_64, |
190 | dwarf_mm3_x86_64, |
191 | dwarf_mm4_x86_64, |
192 | dwarf_mm5_x86_64, |
193 | dwarf_mm6_x86_64, |
194 | dwarf_mm7_x86_64, |
195 | // Control and Status Flags Register |
196 | dwarf_rflags_x86_64 = 49, |
197 | // selector registers |
198 | dwarf_es_x86_64 = 50, |
199 | dwarf_cs_x86_64, |
200 | dwarf_ss_x86_64, |
201 | dwarf_ds_x86_64, |
202 | dwarf_fs_x86_64, |
203 | dwarf_gs_x86_64, |
204 | // Base registers |
205 | dwarf_fs_base_x86_64 = 58, |
206 | dwarf_gs_base_x86_64 = 59, |
207 | // Floating point control registers |
208 | dwarf_mxcsr_x86_64 = 64, // Media Control and Status |
209 | dwarf_fctrl_x86_64, // x87 control word |
210 | dwarf_fstat_x86_64, // x87 status word |
211 | // Upper Vector Registers |
212 | dwarf_ymm0h_x86_64 = 67, |
213 | dwarf_ymm1h_x86_64, |
214 | dwarf_ymm2h_x86_64, |
215 | dwarf_ymm3h_x86_64, |
216 | dwarf_ymm4h_x86_64, |
217 | dwarf_ymm5h_x86_64, |
218 | dwarf_ymm6h_x86_64, |
219 | dwarf_ymm7h_x86_64, |
220 | dwarf_ymm8h_x86_64, |
221 | dwarf_ymm9h_x86_64, |
222 | dwarf_ymm10h_x86_64, |
223 | dwarf_ymm11h_x86_64, |
224 | dwarf_ymm12h_x86_64, |
225 | dwarf_ymm13h_x86_64, |
226 | dwarf_ymm14h_x86_64, |
227 | dwarf_ymm15h_x86_64, |
228 | // MPX registers |
229 | dwarf_bnd0_x86_64 = 126, |
230 | dwarf_bnd1_x86_64, |
231 | dwarf_bnd2_x86_64, |
232 | dwarf_bnd3_x86_64, |
233 | // AVX2 Vector Mask Registers |
234 | // dwarf_k0_x86_64 = 118, |
235 | // dwarf_k1_x86_64, |
236 | // dwarf_k2_x86_64, |
237 | // dwarf_k3_x86_64, |
238 | // dwarf_k4_x86_64, |
239 | // dwarf_k5_x86_64, |
240 | // dwarf_k6_x86_64, |
241 | // dwarf_k7_x86_64, |
242 | }; |
243 | |
244 | // Generic floating-point registers |
245 | |
246 | LLVM_PACKED_START |
247 | struct MMSRegComp { |
248 | uint64_t mantissa; |
249 | uint16_t sign_exp; |
250 | }; |
251 | |
252 | struct MMSReg { |
253 | union { |
254 | uint8_t bytes[10]; |
255 | MMSRegComp comp; |
256 | }; |
257 | uint8_t pad[6]; |
258 | }; |
259 | LLVM_PACKED_END |
260 | |
261 | static_assert(sizeof(MMSRegComp) == 10, "MMSRegComp is not 10 bytes of size" ); |
262 | static_assert(sizeof(MMSReg) == 16, "MMSReg is not 16 bytes of size" ); |
263 | |
264 | struct XMMReg { |
265 | uint8_t bytes[16]; // 128-bits for each XMM register |
266 | }; |
267 | |
268 | // i387_fxsave_struct |
269 | struct FXSAVE { |
270 | uint16_t fctrl; // FPU Control Word (fcw) |
271 | uint16_t fstat; // FPU Status Word (fsw) |
272 | uint16_t ftag; // FPU Tag Word (ftw) |
273 | uint16_t fop; // Last Instruction Opcode (fop) |
274 | union { |
275 | struct { |
276 | uint64_t fip; // Instruction Pointer |
277 | uint64_t fdp; // Data Pointer |
278 | } x86_64; |
279 | struct { |
280 | uint32_t fioff; // FPU IP Offset (fip) |
281 | uint32_t fiseg; // FPU IP Selector (fcs) |
282 | uint32_t fooff; // FPU Operand Pointer Offset (foo) |
283 | uint32_t foseg; // FPU Operand Pointer Selector (fos) |
284 | } i386_; // Added _ in the end to avoid error with gcc defining i386 in some |
285 | // cases |
286 | } ptr; |
287 | uint32_t mxcsr; // MXCSR Register State |
288 | uint32_t mxcsrmask; // MXCSR Mask |
289 | MMSReg stmm[8]; // 8*16 bytes for each FP-reg = 128 bytes |
290 | XMMReg xmm[16]; // 16*16 bytes for each XMM-reg = 256 bytes |
291 | uint8_t padding1[48]; |
292 | uint64_t xcr0; |
293 | uint8_t padding2[40]; |
294 | }; |
295 | |
296 | // Extended floating-point registers |
297 | |
298 | struct YMMHReg { |
299 | uint8_t bytes[16]; // 16 * 8 bits for the high bytes of each YMM register |
300 | }; |
301 | |
302 | struct YMMReg { |
303 | uint8_t bytes[32]; // 16 * 16 bits for each YMM register |
304 | }; |
305 | |
306 | struct YMM { |
307 | YMMReg ymm[16]; // assembled from ymmh and xmm registers |
308 | }; |
309 | |
310 | struct MPXReg { |
311 | uint8_t bytes[16]; // MPX 128 bit bound registers |
312 | }; |
313 | |
314 | struct MPXCsr { |
315 | uint8_t bytes[8]; // MPX 64 bit bndcfgu and bndstatus registers (collectively |
316 | // BNDCSR state) |
317 | }; |
318 | |
319 | struct MPX { |
320 | MPXReg mpxr[4]; |
321 | MPXCsr mpxc[2]; |
322 | }; |
323 | |
324 | LLVM_PACKED_START |
325 | struct XSAVE_HDR { |
326 | enum class XFeature : uint64_t { |
327 | FP = 1, |
328 | SSE = FP << 1, |
329 | YMM = SSE << 1, |
330 | BNDREGS = YMM << 1, |
331 | BNDCSR = BNDREGS << 1, |
332 | OPMASK = BNDCSR << 1, |
333 | ZMM_Hi256 = OPMASK << 1, |
334 | Hi16_ZMM = ZMM_Hi256 << 1, |
335 | PT = Hi16_ZMM << 1, |
336 | PKRU = PT << 1, |
337 | LLVM_MARK_AS_BITMASK_ENUM(/*LargestValue*/ PKRU) |
338 | }; |
339 | |
340 | XFeature xstate_bv; // OS enabled xstate mask to determine the extended states |
341 | // supported by the processor |
342 | XFeature xcomp_bv; // Mask to indicate the format of the XSAVE area and of |
343 | // the XRSTOR instruction |
344 | uint64_t reserved1[1]; |
345 | uint64_t reserved2[5]; |
346 | }; |
347 | static_assert(sizeof(XSAVE_HDR) == 64, "XSAVE_HDR layout incorrect" ); |
348 | LLVM_PACKED_END |
349 | |
350 | // x86 extensions to FXSAVE (i.e. for AVX and MPX processors) |
351 | LLVM_PACKED_START |
352 | struct XSAVE { |
353 | FXSAVE i387; // floating point registers typical in i387_fxsave_struct |
354 | XSAVE_HDR ; // The xsave_hdr_struct can be used to determine if the |
355 | // following extensions are usable |
356 | YMMHReg ymmh[16]; // High 16 bytes of each of 16 YMM registers (the low bytes |
357 | // are in FXSAVE.xmm for compatibility with SSE) |
358 | uint64_t reserved3[16]; |
359 | MPXReg mpxr[4]; // MPX BNDREG state, containing 128-bit bound registers |
360 | MPXCsr mpxc[2]; // MPX BNDCSR state, containing 64-bit BNDCFGU and |
361 | // BNDSTATUS registers |
362 | }; |
363 | LLVM_PACKED_END |
364 | |
365 | // Floating-point registers |
366 | union FPR { |
367 | FXSAVE fxsave; // Generic floating-point registers. |
368 | XSAVE xsave; // x86 extended processor state. |
369 | }; |
370 | |
371 | LLVM_ENABLE_BITMASK_ENUMS_IN_NAMESPACE(); |
372 | |
373 | // Convenience function to combine YMM register data from XSAVE-style input. |
374 | inline YMMReg XStateToYMM(const void* xmm_bytes, const void* ymmh_bytes) { |
375 | YMMReg ret; |
376 | |
377 | ::memcpy(dest: ret.bytes, src: xmm_bytes, n: sizeof(XMMReg)); |
378 | ::memcpy(dest: ret.bytes + sizeof(XMMReg), src: ymmh_bytes, n: sizeof(YMMHReg)); |
379 | |
380 | return ret; |
381 | } |
382 | |
383 | // Convenience function to copy YMM register data into XSAVE-style output. |
384 | inline void YMMToXState(const YMMReg& input, void* xmm_bytes, void* ymmh_bytes) { |
385 | ::memcpy(dest: xmm_bytes, src: input.bytes, n: sizeof(XMMReg)); |
386 | ::memcpy(dest: ymmh_bytes, src: input.bytes + sizeof(XMMReg), n: sizeof(YMMHReg)); |
387 | } |
388 | |
389 | uint16_t AbridgedToFullTagWord(uint8_t abridged_tw, uint16_t sw, |
390 | llvm::ArrayRef<MMSReg> st_regs); |
391 | uint8_t FullToAbridgedTagWord(uint16_t tw); |
392 | |
393 | } // namespace lldb_private |
394 | |
395 | #endif |
396 | |