xref: /openbsd-src/gnu/llvm/lldb/tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp (revision be691f3bb6417f04a68938fadbcaee2d5795e764)
1061da546Spatrick //===-- DNBArchImplI386.cpp -------------------------------------*- C++ -*-===//
2061da546Spatrick //
3061da546Spatrick // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4061da546Spatrick // See https://llvm.org/LICENSE.txt for license information.
5061da546Spatrick // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6061da546Spatrick //
7061da546Spatrick //===----------------------------------------------------------------------===//
8061da546Spatrick //
9061da546Spatrick //  Created by Greg Clayton on 6/25/07.
10061da546Spatrick //
11061da546Spatrick //===----------------------------------------------------------------------===//
12061da546Spatrick 
13061da546Spatrick #if defined(__i386__) || defined(__x86_64__)
14061da546Spatrick 
15061da546Spatrick #include <sys/cdefs.h>
16061da546Spatrick 
17061da546Spatrick #include "DNBLog.h"
18061da546Spatrick #include "MacOSX/i386/DNBArchImplI386.h"
19061da546Spatrick #include "MachProcess.h"
20061da546Spatrick #include "MachThread.h"
21061da546Spatrick 
22061da546Spatrick extern "C" bool CPUHasAVX(); // Defined over in DNBArchImplX86_64.cpp
23061da546Spatrick extern "C" bool CPUHasAVX512f(); // Defined over in DNBArchImplX86_64.cpp
24061da546Spatrick #if defined(LLDB_DEBUGSERVER_RELEASE) || defined(LLDB_DEBUGSERVER_DEBUG)
25061da546Spatrick enum debugState { debugStateUnknown, debugStateOff, debugStateOn };
26061da546Spatrick 
27061da546Spatrick static debugState sFPUDebugState = debugStateUnknown;
28061da546Spatrick static debugState sAVXForceState = debugStateUnknown;
29061da546Spatrick 
DebugFPURegs()30061da546Spatrick static bool DebugFPURegs() {
31061da546Spatrick   if (sFPUDebugState == debugStateUnknown) {
32061da546Spatrick     if (getenv("DNB_DEBUG_FPU_REGS"))
33061da546Spatrick       sFPUDebugState = debugStateOn;
34061da546Spatrick     else
35061da546Spatrick       sFPUDebugState = debugStateOff;
36061da546Spatrick   }
37061da546Spatrick 
38061da546Spatrick   return (sFPUDebugState == debugStateOn);
39061da546Spatrick }
40061da546Spatrick 
ForceAVXRegs()41061da546Spatrick static bool ForceAVXRegs() {
42061da546Spatrick   if (sFPUDebugState == debugStateUnknown) {
43061da546Spatrick     if (getenv("DNB_DEBUG_X86_FORCE_AVX_REGS"))
44061da546Spatrick       sAVXForceState = debugStateOn;
45061da546Spatrick     else
46061da546Spatrick       sAVXForceState = debugStateOff;
47061da546Spatrick   }
48061da546Spatrick 
49061da546Spatrick   return (sAVXForceState == debugStateOn);
50061da546Spatrick }
51061da546Spatrick 
52061da546Spatrick #define DEBUG_FPU_REGS (DebugFPURegs())
53061da546Spatrick #define FORCE_AVX_REGS (ForceAVXRegs())
54061da546Spatrick #else
55061da546Spatrick #define DEBUG_FPU_REGS (0)
56061da546Spatrick #define FORCE_AVX_REGS (0)
57061da546Spatrick #endif
58061da546Spatrick 
59061da546Spatrick enum {
60061da546Spatrick   gpr_eax = 0,
61061da546Spatrick   gpr_ebx = 1,
62061da546Spatrick   gpr_ecx = 2,
63061da546Spatrick   gpr_edx = 3,
64061da546Spatrick   gpr_edi = 4,
65061da546Spatrick   gpr_esi = 5,
66061da546Spatrick   gpr_ebp = 6,
67061da546Spatrick   gpr_esp = 7,
68061da546Spatrick   gpr_ss = 8,
69061da546Spatrick   gpr_eflags = 9,
70061da546Spatrick   gpr_eip = 10,
71061da546Spatrick   gpr_cs = 11,
72061da546Spatrick   gpr_ds = 12,
73061da546Spatrick   gpr_es = 13,
74061da546Spatrick   gpr_fs = 14,
75061da546Spatrick   gpr_gs = 15,
76061da546Spatrick   gpr_ax,
77061da546Spatrick   gpr_bx,
78061da546Spatrick   gpr_cx,
79061da546Spatrick   gpr_dx,
80061da546Spatrick   gpr_di,
81061da546Spatrick   gpr_si,
82061da546Spatrick   gpr_bp,
83061da546Spatrick   gpr_sp,
84061da546Spatrick   gpr_ah,
85061da546Spatrick   gpr_bh,
86061da546Spatrick   gpr_ch,
87061da546Spatrick   gpr_dh,
88061da546Spatrick   gpr_al,
89061da546Spatrick   gpr_bl,
90061da546Spatrick   gpr_cl,
91061da546Spatrick   gpr_dl,
92061da546Spatrick   gpr_dil,
93061da546Spatrick   gpr_sil,
94061da546Spatrick   gpr_bpl,
95061da546Spatrick   gpr_spl,
96061da546Spatrick   k_num_gpr_regs
97061da546Spatrick };
98061da546Spatrick 
99061da546Spatrick enum {
100061da546Spatrick   fpu_fcw,
101061da546Spatrick   fpu_fsw,
102061da546Spatrick   fpu_ftw,
103061da546Spatrick   fpu_fop,
104061da546Spatrick   fpu_ip,
105061da546Spatrick   fpu_cs,
106061da546Spatrick   fpu_dp,
107061da546Spatrick   fpu_ds,
108061da546Spatrick   fpu_mxcsr,
109061da546Spatrick   fpu_mxcsrmask,
110061da546Spatrick   fpu_stmm0,
111061da546Spatrick   fpu_stmm1,
112061da546Spatrick   fpu_stmm2,
113061da546Spatrick   fpu_stmm3,
114061da546Spatrick   fpu_stmm4,
115061da546Spatrick   fpu_stmm5,
116061da546Spatrick   fpu_stmm6,
117061da546Spatrick   fpu_stmm7,
118061da546Spatrick   fpu_xmm0,
119061da546Spatrick   fpu_xmm1,
120061da546Spatrick   fpu_xmm2,
121061da546Spatrick   fpu_xmm3,
122061da546Spatrick   fpu_xmm4,
123061da546Spatrick   fpu_xmm5,
124061da546Spatrick   fpu_xmm6,
125061da546Spatrick   fpu_xmm7,
126061da546Spatrick   fpu_ymm0,
127061da546Spatrick   fpu_ymm1,
128061da546Spatrick   fpu_ymm2,
129061da546Spatrick   fpu_ymm3,
130061da546Spatrick   fpu_ymm4,
131061da546Spatrick   fpu_ymm5,
132061da546Spatrick   fpu_ymm6,
133061da546Spatrick   fpu_ymm7,
134061da546Spatrick   fpu_k0,
135061da546Spatrick   fpu_k1,
136061da546Spatrick   fpu_k2,
137061da546Spatrick   fpu_k3,
138061da546Spatrick   fpu_k4,
139061da546Spatrick   fpu_k5,
140061da546Spatrick   fpu_k6,
141061da546Spatrick   fpu_k7,
142061da546Spatrick   fpu_zmm0,
143061da546Spatrick   fpu_zmm1,
144061da546Spatrick   fpu_zmm2,
145061da546Spatrick   fpu_zmm3,
146061da546Spatrick   fpu_zmm4,
147061da546Spatrick   fpu_zmm5,
148061da546Spatrick   fpu_zmm6,
149061da546Spatrick   fpu_zmm7,
150061da546Spatrick   k_num_fpu_regs,
151061da546Spatrick 
152061da546Spatrick   // Aliases
153061da546Spatrick   fpu_fctrl = fpu_fcw,
154061da546Spatrick   fpu_fstat = fpu_fsw,
155061da546Spatrick   fpu_ftag = fpu_ftw,
156061da546Spatrick   fpu_fiseg = fpu_cs,
157061da546Spatrick   fpu_fioff = fpu_ip,
158061da546Spatrick   fpu_foseg = fpu_ds,
159061da546Spatrick   fpu_fooff = fpu_dp
160061da546Spatrick };
161061da546Spatrick 
162061da546Spatrick enum {
163061da546Spatrick   exc_trapno,
164061da546Spatrick   exc_err,
165061da546Spatrick   exc_faultvaddr,
166061da546Spatrick   k_num_exc_regs,
167061da546Spatrick };
168061da546Spatrick 
169061da546Spatrick enum {
170061da546Spatrick   ehframe_eax = 0,
171061da546Spatrick   ehframe_ecx,
172061da546Spatrick   ehframe_edx,
173061da546Spatrick   ehframe_ebx,
174061da546Spatrick 
175061da546Spatrick   // On i386 Darwin the eh_frame register numbers for ebp and esp are reversed
176061da546Spatrick   // from DWARF.
177061da546Spatrick   // It's due to an ancient compiler bug in the output of the eh_frame.
178061da546Spatrick   // Specifically, on i386 darwin eh_frame, 4 is ebp, 5 is esp.
179061da546Spatrick   // On i386 darwin debug_frame (and debug_info), 4 is esp, 5 is ebp.
180061da546Spatrick   ehframe_ebp,
181061da546Spatrick   ehframe_esp,
182061da546Spatrick   ehframe_esi,
183061da546Spatrick   ehframe_edi,
184061da546Spatrick   ehframe_eip,
185061da546Spatrick   ehframe_eflags
186061da546Spatrick };
187061da546Spatrick 
188061da546Spatrick enum {
189061da546Spatrick   dwarf_eax = 0,
190061da546Spatrick   dwarf_ecx,
191061da546Spatrick   dwarf_edx,
192061da546Spatrick   dwarf_ebx,
193061da546Spatrick   dwarf_esp,
194061da546Spatrick   dwarf_ebp,
195061da546Spatrick   dwarf_esi,
196061da546Spatrick   dwarf_edi,
197061da546Spatrick   dwarf_eip,
198061da546Spatrick   dwarf_eflags,
199061da546Spatrick   dwarf_stmm0 = 11,
200061da546Spatrick   dwarf_stmm1,
201061da546Spatrick   dwarf_stmm2,
202061da546Spatrick   dwarf_stmm3,
203061da546Spatrick   dwarf_stmm4,
204061da546Spatrick   dwarf_stmm5,
205061da546Spatrick   dwarf_stmm6,
206061da546Spatrick   dwarf_stmm7,
207061da546Spatrick   dwarf_xmm0 = 21,
208061da546Spatrick   dwarf_xmm1,
209061da546Spatrick   dwarf_xmm2,
210061da546Spatrick   dwarf_xmm3,
211061da546Spatrick   dwarf_xmm4,
212061da546Spatrick   dwarf_xmm5,
213061da546Spatrick   dwarf_xmm6,
214061da546Spatrick   dwarf_xmm7,
215061da546Spatrick   dwarf_ymm0 = dwarf_xmm0,
216061da546Spatrick   dwarf_ymm1 = dwarf_xmm1,
217061da546Spatrick   dwarf_ymm2 = dwarf_xmm2,
218061da546Spatrick   dwarf_ymm3 = dwarf_xmm3,
219061da546Spatrick   dwarf_ymm4 = dwarf_xmm4,
220061da546Spatrick   dwarf_ymm5 = dwarf_xmm5,
221061da546Spatrick   dwarf_ymm6 = dwarf_xmm6,
222061da546Spatrick   dwarf_ymm7 = dwarf_xmm7,
223061da546Spatrick   dwarf_zmm0 = dwarf_xmm0,
224061da546Spatrick   dwarf_zmm1 = dwarf_xmm1,
225061da546Spatrick   dwarf_zmm2 = dwarf_xmm2,
226061da546Spatrick   dwarf_zmm3 = dwarf_xmm3,
227061da546Spatrick   dwarf_zmm4 = dwarf_xmm4,
228061da546Spatrick   dwarf_zmm5 = dwarf_xmm5,
229061da546Spatrick   dwarf_zmm6 = dwarf_xmm6,
230061da546Spatrick   dwarf_zmm7 = dwarf_xmm7,
231061da546Spatrick   dwarf_k0 = 118,
232061da546Spatrick   dwarf_k1,
233061da546Spatrick   dwarf_k2,
234061da546Spatrick   dwarf_k3,
235061da546Spatrick   dwarf_k4,
236061da546Spatrick   dwarf_k5,
237061da546Spatrick   dwarf_k6,
238061da546Spatrick   dwarf_k7,
239061da546Spatrick };
240061da546Spatrick 
241061da546Spatrick enum {
242061da546Spatrick   debugserver_eax = 0,
243061da546Spatrick   debugserver_ecx = 1,
244061da546Spatrick   debugserver_edx = 2,
245061da546Spatrick   debugserver_ebx = 3,
246061da546Spatrick   debugserver_esp = 4,
247061da546Spatrick   debugserver_ebp = 5,
248061da546Spatrick   debugserver_esi = 6,
249061da546Spatrick   debugserver_edi = 7,
250061da546Spatrick   debugserver_eip = 8,
251061da546Spatrick   debugserver_eflags = 9,
252061da546Spatrick   debugserver_cs = 10,
253061da546Spatrick   debugserver_ss = 11,
254061da546Spatrick   debugserver_ds = 12,
255061da546Spatrick   debugserver_es = 13,
256061da546Spatrick   debugserver_fs = 14,
257061da546Spatrick   debugserver_gs = 15,
258061da546Spatrick   debugserver_stmm0 = 16,
259061da546Spatrick   debugserver_stmm1 = 17,
260061da546Spatrick   debugserver_stmm2 = 18,
261061da546Spatrick   debugserver_stmm3 = 19,
262061da546Spatrick   debugserver_stmm4 = 20,
263061da546Spatrick   debugserver_stmm5 = 21,
264061da546Spatrick   debugserver_stmm6 = 22,
265061da546Spatrick   debugserver_stmm7 = 23,
266061da546Spatrick   debugserver_fctrl = 24,
267061da546Spatrick   debugserver_fcw = debugserver_fctrl,
268061da546Spatrick   debugserver_fstat = 25,
269061da546Spatrick   debugserver_fsw = debugserver_fstat,
270061da546Spatrick   debugserver_ftag = 26,
271061da546Spatrick   debugserver_ftw = debugserver_ftag,
272061da546Spatrick   debugserver_fiseg = 27,
273061da546Spatrick   debugserver_fpu_cs = debugserver_fiseg,
274061da546Spatrick   debugserver_fioff = 28,
275061da546Spatrick   debugserver_ip = debugserver_fioff,
276061da546Spatrick   debugserver_foseg = 29,
277061da546Spatrick   debugserver_fpu_ds = debugserver_foseg,
278061da546Spatrick   debugserver_fooff = 30,
279061da546Spatrick   debugserver_dp = debugserver_fooff,
280061da546Spatrick   debugserver_fop = 31,
281061da546Spatrick   debugserver_xmm0 = 32,
282061da546Spatrick   debugserver_xmm1 = 33,
283061da546Spatrick   debugserver_xmm2 = 34,
284061da546Spatrick   debugserver_xmm3 = 35,
285061da546Spatrick   debugserver_xmm4 = 36,
286061da546Spatrick   debugserver_xmm5 = 37,
287061da546Spatrick   debugserver_xmm6 = 38,
288061da546Spatrick   debugserver_xmm7 = 39,
289061da546Spatrick   debugserver_mxcsr = 40,
290061da546Spatrick   debugserver_mm0 = 41,
291061da546Spatrick   debugserver_mm1 = 42,
292061da546Spatrick   debugserver_mm2 = 43,
293061da546Spatrick   debugserver_mm3 = 44,
294061da546Spatrick   debugserver_mm4 = 45,
295061da546Spatrick   debugserver_mm5 = 46,
296061da546Spatrick   debugserver_mm6 = 47,
297061da546Spatrick   debugserver_mm7 = 48,
298061da546Spatrick   debugserver_ymm0 = debugserver_xmm0,
299061da546Spatrick   debugserver_ymm1 = debugserver_xmm1,
300061da546Spatrick   debugserver_ymm2 = debugserver_xmm2,
301061da546Spatrick   debugserver_ymm3 = debugserver_xmm3,
302061da546Spatrick   debugserver_ymm4 = debugserver_xmm4,
303061da546Spatrick   debugserver_ymm5 = debugserver_xmm5,
304061da546Spatrick   debugserver_ymm6 = debugserver_xmm6,
305061da546Spatrick   debugserver_ymm7 = debugserver_xmm7,
306061da546Spatrick   debugserver_zmm0 = debugserver_xmm0,
307061da546Spatrick   debugserver_zmm1 = debugserver_xmm1,
308061da546Spatrick   debugserver_zmm2 = debugserver_xmm2,
309061da546Spatrick   debugserver_zmm3 = debugserver_xmm3,
310061da546Spatrick   debugserver_zmm4 = debugserver_xmm4,
311061da546Spatrick   debugserver_zmm5 = debugserver_xmm5,
312061da546Spatrick   debugserver_zmm6 = debugserver_xmm6,
313061da546Spatrick   debugserver_zmm7 = debugserver_xmm7,
314061da546Spatrick   debugserver_k0 = 118,
315061da546Spatrick   debugserver_k1 = 119,
316061da546Spatrick   debugserver_k2 = 120,
317061da546Spatrick   debugserver_k3 = 121,
318061da546Spatrick   debugserver_k4 = 122,
319061da546Spatrick   debugserver_k5 = 123,
320061da546Spatrick   debugserver_k6 = 124,
321061da546Spatrick   debugserver_k7 = 125,
322061da546Spatrick };
323061da546Spatrick 
GetPC(uint64_t failValue)324061da546Spatrick uint64_t DNBArchImplI386::GetPC(uint64_t failValue) {
325061da546Spatrick   // Get program counter
326061da546Spatrick   if (GetGPRState(false) == KERN_SUCCESS)
327061da546Spatrick     return m_state.context.gpr.__eip;
328061da546Spatrick   return failValue;
329061da546Spatrick }
330061da546Spatrick 
SetPC(uint64_t value)331061da546Spatrick kern_return_t DNBArchImplI386::SetPC(uint64_t value) {
332061da546Spatrick   // Get program counter
333061da546Spatrick   kern_return_t err = GetGPRState(false);
334061da546Spatrick   if (err == KERN_SUCCESS) {
335061da546Spatrick     m_state.context.gpr.__eip = static_cast<uint32_t>(value);
336061da546Spatrick     err = SetGPRState();
337061da546Spatrick   }
338061da546Spatrick   return err == KERN_SUCCESS;
339061da546Spatrick }
340061da546Spatrick 
GetSP(uint64_t failValue)341061da546Spatrick uint64_t DNBArchImplI386::GetSP(uint64_t failValue) {
342061da546Spatrick   // Get stack pointer
343061da546Spatrick   if (GetGPRState(false) == KERN_SUCCESS)
344061da546Spatrick     return m_state.context.gpr.__esp;
345061da546Spatrick   return failValue;
346061da546Spatrick }
347061da546Spatrick 
348061da546Spatrick // Uncomment the value below to verify the values in the debugger.
349061da546Spatrick //#define DEBUG_GPR_VALUES 1    // DO NOT CHECK IN WITH THIS DEFINE ENABLED
350061da546Spatrick //#define SET_GPR(reg) m_state.context.gpr.__##reg = gpr_##reg
351061da546Spatrick 
GetGPRState(bool force)352061da546Spatrick kern_return_t DNBArchImplI386::GetGPRState(bool force) {
353061da546Spatrick   if (force || m_state.GetError(e_regSetGPR, Read)) {
354061da546Spatrick #if DEBUG_GPR_VALUES
355061da546Spatrick     SET_GPR(eax);
356061da546Spatrick     SET_GPR(ebx);
357061da546Spatrick     SET_GPR(ecx);
358061da546Spatrick     SET_GPR(edx);
359061da546Spatrick     SET_GPR(edi);
360061da546Spatrick     SET_GPR(esi);
361061da546Spatrick     SET_GPR(ebp);
362061da546Spatrick     SET_GPR(esp);
363061da546Spatrick     SET_GPR(ss);
364061da546Spatrick     SET_GPR(eflags);
365061da546Spatrick     SET_GPR(eip);
366061da546Spatrick     SET_GPR(cs);
367061da546Spatrick     SET_GPR(ds);
368061da546Spatrick     SET_GPR(es);
369061da546Spatrick     SET_GPR(fs);
370061da546Spatrick     SET_GPR(gs);
371061da546Spatrick     m_state.SetError(e_regSetGPR, Read, 0);
372061da546Spatrick #else
373061da546Spatrick     mach_msg_type_number_t count = e_regSetWordSizeGPR;
374061da546Spatrick     m_state.SetError(
375061da546Spatrick         e_regSetGPR, Read,
376061da546Spatrick         ::thread_get_state(m_thread->MachPortNumber(), __i386_THREAD_STATE,
377061da546Spatrick                            (thread_state_t)&m_state.context.gpr, &count));
378061da546Spatrick #endif
379061da546Spatrick   }
380061da546Spatrick   return m_state.GetError(e_regSetGPR, Read);
381061da546Spatrick }
382061da546Spatrick 
383061da546Spatrick // Uncomment the value below to verify the values in the debugger.
384061da546Spatrick //#define DEBUG_FPU_VALUES 1    // DO NOT CHECK IN WITH THIS DEFINE ENABLED
385061da546Spatrick 
GetFPUState(bool force)386061da546Spatrick kern_return_t DNBArchImplI386::GetFPUState(bool force) {
387061da546Spatrick   if (force || m_state.GetError(e_regSetFPU, Read)) {
388061da546Spatrick     if (DEBUG_FPU_REGS) {
389061da546Spatrick 
390061da546Spatrick       m_state.context.fpu.no_avx.__fpu_reserved[0] = -1;
391061da546Spatrick       m_state.context.fpu.no_avx.__fpu_reserved[1] = -1;
392061da546Spatrick       *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fcw) = 0x1234;
393061da546Spatrick       *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fsw) = 0x5678;
394061da546Spatrick       m_state.context.fpu.no_avx.__fpu_ftw = 1;
395061da546Spatrick       m_state.context.fpu.no_avx.__fpu_rsrv1 = UINT8_MAX;
396061da546Spatrick       m_state.context.fpu.no_avx.__fpu_fop = 2;
397061da546Spatrick       m_state.context.fpu.no_avx.__fpu_ip = 3;
398061da546Spatrick       m_state.context.fpu.no_avx.__fpu_cs = 4;
399061da546Spatrick       m_state.context.fpu.no_avx.__fpu_rsrv2 = 5;
400061da546Spatrick       m_state.context.fpu.no_avx.__fpu_dp = 6;
401061da546Spatrick       m_state.context.fpu.no_avx.__fpu_ds = 7;
402061da546Spatrick       m_state.context.fpu.no_avx.__fpu_rsrv3 = UINT16_MAX;
403061da546Spatrick       m_state.context.fpu.no_avx.__fpu_mxcsr = 8;
404061da546Spatrick       m_state.context.fpu.no_avx.__fpu_mxcsrmask = 9;
405061da546Spatrick       for (int i = 0; i < 16; ++i) {
406061da546Spatrick         if (i < 10) {
407061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = 'a';
408061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = 'b';
409061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = 'c';
410061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = 'd';
411061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = 'e';
412061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = 'f';
413061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = 'g';
414061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = 'h';
415061da546Spatrick         } else {
416061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN;
417061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN;
418061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN;
419061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN;
420061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN;
421061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN;
422061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN;
423061da546Spatrick           m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN;
424061da546Spatrick         }
425061da546Spatrick 
426061da546Spatrick         m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg[i] = '0';
427061da546Spatrick         m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg[i] = '1';
428061da546Spatrick         m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg[i] = '2';
429061da546Spatrick         m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg[i] = '3';
430061da546Spatrick         m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg[i] = '4';
431061da546Spatrick         m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg[i] = '5';
432061da546Spatrick         m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg[i] = '6';
433061da546Spatrick         m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg[i] = '7';
434061da546Spatrick       }
435061da546Spatrick       for (int i = 0; i < sizeof(m_state.context.fpu.no_avx.__fpu_rsrv4); ++i)
436061da546Spatrick         m_state.context.fpu.no_avx.__fpu_rsrv4[i] = INT8_MIN;
437061da546Spatrick       m_state.context.fpu.no_avx.__fpu_reserved1 = -1;
438061da546Spatrick 
439061da546Spatrick       if (CPUHasAVX() || FORCE_AVX_REGS) {
440061da546Spatrick         for (int i = 0; i < sizeof(m_state.context.fpu.avx.__avx_reserved1);
441061da546Spatrick              ++i)
442061da546Spatrick           m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN;
443061da546Spatrick 
444061da546Spatrick         for (int i = 0; i < 16; ++i) {
445061da546Spatrick           m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0';
446061da546Spatrick           m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1';
447061da546Spatrick           m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2';
448061da546Spatrick           m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3';
449061da546Spatrick           m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4';
450061da546Spatrick           m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5';
451061da546Spatrick           m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6';
452061da546Spatrick           m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7';
453061da546Spatrick         }
454061da546Spatrick       }
455061da546Spatrick       if (CPUHasAVX512f() || FORCE_AVX_REGS) {
456061da546Spatrick         for (int i = 0; i < 8; ++i) {
457061da546Spatrick           m_state.context.fpu.avx512f.__fpu_k0.__opmask_reg[i] = '0';
458061da546Spatrick           m_state.context.fpu.avx512f.__fpu_k1.__opmask_reg[i] = '1';
459061da546Spatrick           m_state.context.fpu.avx512f.__fpu_k2.__opmask_reg[i] = '2';
460061da546Spatrick           m_state.context.fpu.avx512f.__fpu_k3.__opmask_reg[i] = '3';
461061da546Spatrick           m_state.context.fpu.avx512f.__fpu_k4.__opmask_reg[i] = '4';
462061da546Spatrick           m_state.context.fpu.avx512f.__fpu_k5.__opmask_reg[i] = '5';
463061da546Spatrick           m_state.context.fpu.avx512f.__fpu_k6.__opmask_reg[i] = '6';
464061da546Spatrick           m_state.context.fpu.avx512f.__fpu_k7.__opmask_reg[i] = '7';
465061da546Spatrick         }
466061da546Spatrick 
467061da546Spatrick         for (int i = 0; i < 32; ++i) {
468061da546Spatrick           m_state.context.fpu.avx512f.__fpu_zmmh0.__ymm_reg[i] = '0';
469061da546Spatrick           m_state.context.fpu.avx512f.__fpu_zmmh1.__ymm_reg[i] = '1';
470061da546Spatrick           m_state.context.fpu.avx512f.__fpu_zmmh2.__ymm_reg[i] = '2';
471061da546Spatrick           m_state.context.fpu.avx512f.__fpu_zmmh3.__ymm_reg[i] = '3';
472061da546Spatrick           m_state.context.fpu.avx512f.__fpu_zmmh4.__ymm_reg[i] = '4';
473061da546Spatrick           m_state.context.fpu.avx512f.__fpu_zmmh5.__ymm_reg[i] = '5';
474061da546Spatrick           m_state.context.fpu.avx512f.__fpu_zmmh6.__ymm_reg[i] = '6';
475061da546Spatrick           m_state.context.fpu.avx512f.__fpu_zmmh7.__ymm_reg[i] = '7';
476061da546Spatrick         }
477061da546Spatrick       }
478061da546Spatrick       m_state.SetError(e_regSetFPU, Read, 0);
479061da546Spatrick     } else {
480061da546Spatrick       mach_msg_type_number_t count = e_regSetWordSizeFPU;
481061da546Spatrick       int flavor = __i386_FLOAT_STATE;
482061da546Spatrick 
483061da546Spatrick       // On a machine with the AVX512 register set, a process only gets a
484061da546Spatrick       // full AVX512 register context after it uses the AVX512 registers;
485061da546Spatrick       // if the process has not yet triggered this change, trying to fetch
486061da546Spatrick       // the AVX512 registers will fail.  Fall through to fetching the AVX
487061da546Spatrick       // registers.
488061da546Spatrick       if (CPUHasAVX512f() || FORCE_AVX_REGS) {
489061da546Spatrick         count = e_regSetWordSizeAVX512f;
490061da546Spatrick         flavor = __i386_AVX512F_STATE;
491061da546Spatrick         m_state.SetError(e_regSetFPU, Read,
492061da546Spatrick                          ::thread_get_state(m_thread->MachPortNumber(), flavor,
493061da546Spatrick                                             (thread_state_t)&m_state.context.fpu,
494061da546Spatrick                                             &count));
495061da546Spatrick         DNBLogThreadedIf(LOG_THREAD,
496061da546Spatrick                          "::thread_get_state (0x%4.4x, %u, &fpu, %u => 0x%8.8x",
497061da546Spatrick                          m_thread->MachPortNumber(), flavor, (uint32_t)count,
498061da546Spatrick                          m_state.GetError(e_regSetFPU, Read));
499061da546Spatrick         if (m_state.GetError(e_regSetFPU, Read) == KERN_SUCCESS)
500061da546Spatrick           return m_state.GetError(e_regSetFPU, Read);
501061da546Spatrick       }
502061da546Spatrick       if (CPUHasAVX()) {
503061da546Spatrick         count = e_regSetWordSizeAVX;
504061da546Spatrick         flavor = __i386_AVX_STATE;
505061da546Spatrick       }
506061da546Spatrick       m_state.SetError(e_regSetFPU, Read,
507061da546Spatrick                        ::thread_get_state(m_thread->MachPortNumber(), flavor,
508061da546Spatrick                                           (thread_state_t)&m_state.context.fpu,
509061da546Spatrick                                           &count));
510061da546Spatrick       DNBLogThreadedIf(LOG_THREAD,
511061da546Spatrick                        "::thread_get_state (0x%4.4x, %u, &fpu, %u => 0x%8.8x",
512061da546Spatrick                        m_thread->MachPortNumber(), flavor, (uint32_t)count,
513061da546Spatrick                        m_state.GetError(e_regSetFPU, Read));
514061da546Spatrick     }
515061da546Spatrick   }
516061da546Spatrick   return m_state.GetError(e_regSetFPU, Read);
517061da546Spatrick }
518061da546Spatrick 
GetEXCState(bool force)519061da546Spatrick kern_return_t DNBArchImplI386::GetEXCState(bool force) {
520061da546Spatrick   if (force || m_state.GetError(e_regSetEXC, Read)) {
521061da546Spatrick     mach_msg_type_number_t count = e_regSetWordSizeEXC;
522061da546Spatrick     m_state.SetError(
523061da546Spatrick         e_regSetEXC, Read,
524061da546Spatrick         ::thread_get_state(m_thread->MachPortNumber(), __i386_EXCEPTION_STATE,
525061da546Spatrick                            (thread_state_t)&m_state.context.exc, &count));
526061da546Spatrick   }
527061da546Spatrick   return m_state.GetError(e_regSetEXC, Read);
528061da546Spatrick }
529061da546Spatrick 
SetGPRState()530061da546Spatrick kern_return_t DNBArchImplI386::SetGPRState() {
531061da546Spatrick   kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber());
532061da546Spatrick   DNBLogThreadedIf(
533061da546Spatrick       LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u "
534061da546Spatrick                   "(SetGPRState() for stop_count = %u)",
535061da546Spatrick       m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount());
536061da546Spatrick 
537061da546Spatrick   m_state.SetError(e_regSetGPR, Write,
538061da546Spatrick                    ::thread_set_state(m_thread->MachPortNumber(),
539061da546Spatrick                                       __i386_THREAD_STATE,
540061da546Spatrick                                       (thread_state_t)&m_state.context.gpr,
541061da546Spatrick                                       e_regSetWordSizeGPR));
542061da546Spatrick   return m_state.GetError(e_regSetGPR, Write);
543061da546Spatrick }
544061da546Spatrick 
SetFPUState()545061da546Spatrick kern_return_t DNBArchImplI386::SetFPUState() {
546061da546Spatrick   if (DEBUG_FPU_REGS) {
547061da546Spatrick     m_state.SetError(e_regSetFPU, Write, 0);
548061da546Spatrick     return m_state.GetError(e_regSetFPU, Write);
549061da546Spatrick   } else {
550061da546Spatrick     int flavor = __i386_FLOAT_STATE;
551061da546Spatrick     mach_msg_type_number_t count = e_regSetWordSizeFPU;
552061da546Spatrick     if (CPUHasAVX512f() || FORCE_AVX_REGS) {
553061da546Spatrick       flavor = __i386_AVX512F_STATE;
554061da546Spatrick       count = e_regSetWordSizeAVX512f;
555061da546Spatrick     } else
556061da546Spatrick     if (CPUHasAVX()) {
557061da546Spatrick       flavor = __i386_AVX_STATE;
558061da546Spatrick       count = e_regSetWordSizeAVX;
559061da546Spatrick     }
560061da546Spatrick 
561061da546Spatrick     m_state.SetError(e_regSetFPU, Write,
562061da546Spatrick                      ::thread_set_state(m_thread->MachPortNumber(), flavor,
563061da546Spatrick                                         (thread_state_t)&m_state.context.fpu,
564061da546Spatrick                                         count));
565061da546Spatrick     return m_state.GetError(e_regSetFPU, Write);
566061da546Spatrick   }
567061da546Spatrick }
568061da546Spatrick 
SetEXCState()569061da546Spatrick kern_return_t DNBArchImplI386::SetEXCState() {
570061da546Spatrick   m_state.SetError(e_regSetEXC, Write,
571061da546Spatrick                    ::thread_set_state(m_thread->MachPortNumber(),
572061da546Spatrick                                       __i386_EXCEPTION_STATE,
573061da546Spatrick                                       (thread_state_t)&m_state.context.exc,
574061da546Spatrick                                       e_regSetWordSizeEXC));
575061da546Spatrick   return m_state.GetError(e_regSetEXC, Write);
576061da546Spatrick }
577061da546Spatrick 
GetDBGState(bool force)578061da546Spatrick kern_return_t DNBArchImplI386::GetDBGState(bool force) {
579061da546Spatrick   if (force || m_state.GetError(e_regSetDBG, Read)) {
580061da546Spatrick     mach_msg_type_number_t count = e_regSetWordSizeDBG;
581061da546Spatrick     m_state.SetError(
582061da546Spatrick         e_regSetDBG, Read,
583061da546Spatrick         ::thread_get_state(m_thread->MachPortNumber(), __i386_DEBUG_STATE,
584061da546Spatrick                            (thread_state_t)&m_state.context.dbg, &count));
585061da546Spatrick   }
586061da546Spatrick   return m_state.GetError(e_regSetDBG, Read);
587061da546Spatrick }
588061da546Spatrick 
SetDBGState(bool also_set_on_task)589061da546Spatrick kern_return_t DNBArchImplI386::SetDBGState(bool also_set_on_task) {
590061da546Spatrick   m_state.SetError(e_regSetDBG, Write,
591061da546Spatrick                    ::thread_set_state(m_thread->MachPortNumber(),
592061da546Spatrick                                       __i386_DEBUG_STATE,
593061da546Spatrick                                       (thread_state_t)&m_state.context.dbg,
594061da546Spatrick                                       e_regSetWordSizeDBG));
595061da546Spatrick   if (also_set_on_task) {
596061da546Spatrick     kern_return_t kret = ::task_set_state(
597061da546Spatrick         m_thread->Process()->Task().TaskPort(), __i386_DEBUG_STATE,
598061da546Spatrick         (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG);
599061da546Spatrick     if (kret != KERN_SUCCESS)
600061da546Spatrick       DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::SetDBGState failed "
601061da546Spatrick                                         "to set debug control register state: "
602061da546Spatrick                                         "0x%8.8x.",
603061da546Spatrick                        kret);
604061da546Spatrick   }
605061da546Spatrick   return m_state.GetError(e_regSetDBG, Write);
606061da546Spatrick }
607061da546Spatrick 
ThreadWillResume()608061da546Spatrick void DNBArchImplI386::ThreadWillResume() {
609061da546Spatrick   // Do we need to step this thread? If so, let the mach thread tell us so.
610061da546Spatrick   if (m_thread->IsStepping()) {
611061da546Spatrick     // This is the primary thread, let the arch do anything it needs
612061da546Spatrick     EnableHardwareSingleStep(true);
613061da546Spatrick   }
614061da546Spatrick 
615061da546Spatrick   // Reset the debug status register, if necessary, before we resume.
616061da546Spatrick   kern_return_t kret = GetDBGState(false);
617061da546Spatrick   DNBLogThreadedIf(
618061da546Spatrick       LOG_WATCHPOINTS,
619061da546Spatrick       "DNBArchImplI386::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret);
620061da546Spatrick   if (kret != KERN_SUCCESS)
621061da546Spatrick     return;
622061da546Spatrick 
623061da546Spatrick   DBG &debug_state = m_state.context.dbg;
624061da546Spatrick   bool need_reset = false;
625061da546Spatrick   uint32_t i, num = NumSupportedHardwareWatchpoints();
626061da546Spatrick   for (i = 0; i < num; ++i)
627061da546Spatrick     if (IsWatchpointHit(debug_state, i))
628061da546Spatrick       need_reset = true;
629061da546Spatrick 
630061da546Spatrick   if (need_reset) {
631061da546Spatrick     ClearWatchpointHits(debug_state);
632061da546Spatrick     kret = SetDBGState(false);
633061da546Spatrick     DNBLogThreadedIf(
634061da546Spatrick         LOG_WATCHPOINTS,
635061da546Spatrick         "DNBArchImplI386::ThreadWillResume() SetDBGState() => 0x%8.8x.", kret);
636061da546Spatrick   }
637061da546Spatrick }
638061da546Spatrick 
ThreadDidStop()639061da546Spatrick bool DNBArchImplI386::ThreadDidStop() {
640061da546Spatrick   bool success = true;
641061da546Spatrick 
642061da546Spatrick   m_state.InvalidateAllRegisterStates();
643061da546Spatrick 
644061da546Spatrick   // Are we stepping a single instruction?
645061da546Spatrick   if (GetGPRState(true) == KERN_SUCCESS) {
646061da546Spatrick     // We are single stepping, was this the primary thread?
647061da546Spatrick     if (m_thread->IsStepping()) {
648061da546Spatrick       // This was the primary thread, we need to clear the trace
649061da546Spatrick       // bit if so.
650061da546Spatrick       success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
651061da546Spatrick     } else {
652061da546Spatrick       // The MachThread will automatically restore the suspend count
653061da546Spatrick       // in ThreadDidStop(), so we don't need to do anything here if
654061da546Spatrick       // we weren't the primary thread the last time
655061da546Spatrick     }
656061da546Spatrick   }
657061da546Spatrick   return success;
658061da546Spatrick }
659061da546Spatrick 
NotifyException(MachException::Data & exc)660061da546Spatrick bool DNBArchImplI386::NotifyException(MachException::Data &exc) {
661061da546Spatrick   switch (exc.exc_type) {
662061da546Spatrick   case EXC_BAD_ACCESS:
663061da546Spatrick     break;
664061da546Spatrick   case EXC_BAD_INSTRUCTION:
665061da546Spatrick     break;
666061da546Spatrick   case EXC_ARITHMETIC:
667061da546Spatrick     break;
668061da546Spatrick   case EXC_EMULATION:
669061da546Spatrick     break;
670061da546Spatrick   case EXC_SOFTWARE:
671061da546Spatrick     break;
672061da546Spatrick   case EXC_BREAKPOINT:
673061da546Spatrick     if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2) {
674061da546Spatrick       // exc_code = EXC_I386_BPT
675061da546Spatrick       //
676061da546Spatrick       nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS);
677061da546Spatrick       if (pc != INVALID_NUB_ADDRESS && pc > 0) {
678061da546Spatrick         pc -= 1;
679061da546Spatrick         // Check for a breakpoint at one byte prior to the current PC value
680061da546Spatrick         // since the PC will be just past the trap.
681061da546Spatrick 
682061da546Spatrick         DNBBreakpoint *bp =
683061da546Spatrick             m_thread->Process()->Breakpoints().FindByAddress(pc);
684061da546Spatrick         if (bp) {
685061da546Spatrick           // Backup the PC for i386 since the trap was taken and the PC
686061da546Spatrick           // is at the address following the single byte trap instruction.
687061da546Spatrick           if (m_state.context.gpr.__eip > 0) {
688061da546Spatrick             m_state.context.gpr.__eip = static_cast<uint32_t>(pc);
689061da546Spatrick             // Write the new PC back out
690061da546Spatrick             SetGPRState();
691061da546Spatrick           }
692061da546Spatrick         }
693061da546Spatrick         return true;
694061da546Spatrick       }
695061da546Spatrick     } else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1) {
696061da546Spatrick       // exc_code = EXC_I386_SGL
697061da546Spatrick       //
698061da546Spatrick       // Check whether this corresponds to a watchpoint hit event.
699061da546Spatrick       // If yes, set the exc_sub_code to the data break address.
700061da546Spatrick       nub_addr_t addr = 0;
701061da546Spatrick       uint32_t hw_index = GetHardwareWatchpointHit(addr);
702061da546Spatrick       if (hw_index != INVALID_NUB_HW_INDEX) {
703061da546Spatrick         exc.exc_data[1] = addr;
704061da546Spatrick         // Piggyback the hw_index in the exc.data.
705061da546Spatrick         exc.exc_data.push_back(hw_index);
706061da546Spatrick       }
707061da546Spatrick 
708061da546Spatrick       return true;
709061da546Spatrick     }
710061da546Spatrick     break;
711061da546Spatrick   case EXC_SYSCALL:
712061da546Spatrick     break;
713061da546Spatrick   case EXC_MACH_SYSCALL:
714061da546Spatrick     break;
715061da546Spatrick   case EXC_RPC_ALERT:
716061da546Spatrick     break;
717061da546Spatrick   }
718061da546Spatrick   return false;
719061da546Spatrick }
720061da546Spatrick 
NumSupportedHardwareBreakpoints()721dda28197Spatrick uint32_t DNBArchImplI386::NumSupportedHardwareBreakpoints() {
722dda28197Spatrick   // Available debug address registers: dr0, dr1, dr2, dr3.
723dda28197Spatrick   return 4;
724dda28197Spatrick }
725dda28197Spatrick 
NumSupportedHardwareWatchpoints()726061da546Spatrick uint32_t DNBArchImplI386::NumSupportedHardwareWatchpoints() {
727061da546Spatrick   // Available debug address registers: dr0, dr1, dr2, dr3.
728061da546Spatrick   return 4;
729061da546Spatrick }
730061da546Spatrick 
size_and_rw_bits(nub_size_t size,bool read,bool write)731061da546Spatrick static uint32_t size_and_rw_bits(nub_size_t size, bool read, bool write) {
732061da546Spatrick   uint32_t rw;
733061da546Spatrick   if (read) {
734061da546Spatrick     rw = 0x3; // READ or READ/WRITE
735061da546Spatrick   } else if (write) {
736061da546Spatrick     rw = 0x1; // WRITE
737061da546Spatrick   } else {
738061da546Spatrick     assert(0 && "read and write cannot both be false");
739061da546Spatrick   }
740061da546Spatrick 
741061da546Spatrick   switch (size) {
742061da546Spatrick   case 1:
743061da546Spatrick     return rw;
744061da546Spatrick   case 2:
745061da546Spatrick     return (0x1 << 2) | rw;
746061da546Spatrick   case 4:
747061da546Spatrick     return (0x3 << 2) | rw;
748061da546Spatrick   case 8:
749061da546Spatrick     return (0x2 << 2) | rw;
750061da546Spatrick   }
751061da546Spatrick   assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
752061da546Spatrick   return 0;
753061da546Spatrick }
754061da546Spatrick 
SetWatchpoint(DBG & debug_state,uint32_t hw_index,nub_addr_t addr,nub_size_t size,bool read,bool write)755061da546Spatrick void DNBArchImplI386::SetWatchpoint(DBG &debug_state, uint32_t hw_index,
756061da546Spatrick                                     nub_addr_t addr, nub_size_t size, bool read,
757061da546Spatrick                                     bool write) {
758061da546Spatrick   // Set both dr7 (debug control register) and dri (debug address register).
759061da546Spatrick 
760061da546Spatrick   // dr7{7-0} encodes the local/gloabl enable bits:
761061da546Spatrick   //  global enable --. .-- local enable
762061da546Spatrick   //                  | |
763061da546Spatrick   //                  v v
764061da546Spatrick   //      dr0 -> bits{1-0}
765061da546Spatrick   //      dr1 -> bits{3-2}
766061da546Spatrick   //      dr2 -> bits{5-4}
767061da546Spatrick   //      dr3 -> bits{7-6}
768061da546Spatrick   //
769061da546Spatrick   // dr7{31-16} encodes the rw/len bits:
770061da546Spatrick   //  b_x+3, b_x+2, b_x+1, b_x
771061da546Spatrick   //      where bits{x+1, x} => rw
772061da546Spatrick   //            0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io
773061da546Spatrick   //            read-or-write (unused)
774061da546Spatrick   //      and bits{x+3, x+2} => len
775061da546Spatrick   //            0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
776061da546Spatrick   //
777061da546Spatrick   //      dr0 -> bits{19-16}
778061da546Spatrick   //      dr1 -> bits{23-20}
779061da546Spatrick   //      dr2 -> bits{27-24}
780061da546Spatrick   //      dr3 -> bits{31-28}
781061da546Spatrick   debug_state.__dr7 |=
782061da546Spatrick       (1 << (2 * hw_index) |
783061da546Spatrick        size_and_rw_bits(size, read, write) << (16 + 4 * hw_index));
784061da546Spatrick   uint32_t addr_32 = addr & 0xffffffff;
785061da546Spatrick   switch (hw_index) {
786061da546Spatrick   case 0:
787061da546Spatrick     debug_state.__dr0 = addr_32;
788061da546Spatrick     break;
789061da546Spatrick   case 1:
790061da546Spatrick     debug_state.__dr1 = addr_32;
791061da546Spatrick     break;
792061da546Spatrick   case 2:
793061da546Spatrick     debug_state.__dr2 = addr_32;
794061da546Spatrick     break;
795061da546Spatrick   case 3:
796061da546Spatrick     debug_state.__dr3 = addr_32;
797061da546Spatrick     break;
798061da546Spatrick   default:
799061da546Spatrick     assert(0 &&
800061da546Spatrick            "invalid hardware register index, must be one of 0, 1, 2, or 3");
801061da546Spatrick   }
802061da546Spatrick   return;
803061da546Spatrick }
804061da546Spatrick 
SetHardwareBreakpoint(DBG & debug_state,uint32_t hw_index,nub_addr_t addr,nub_size_t size)805dda28197Spatrick void DNBArchImplI386::SetHardwareBreakpoint(DBG &debug_state, uint32_t hw_index,
806dda28197Spatrick                                             nub_addr_t addr, nub_size_t size) {
807dda28197Spatrick   // Set both dr7 (debug control register) and dri (debug address register).
808dda28197Spatrick 
809dda28197Spatrick   // dr7{7-0} encodes the local/gloabl enable bits:
810dda28197Spatrick   //  global enable --. .-- local enable
811dda28197Spatrick   //                  | |
812dda28197Spatrick   //                  v v
813dda28197Spatrick   //      dr0 -> bits{1-0}
814dda28197Spatrick   //      dr1 -> bits{3-2}
815dda28197Spatrick   //      dr2 -> bits{5-4}
816dda28197Spatrick   //      dr3 -> bits{7-6}
817dda28197Spatrick   //
818dda28197Spatrick   // dr7{31-16} encodes the rw/len bits:
819dda28197Spatrick   //  b_x+3, b_x+2, b_x+1, b_x
820dda28197Spatrick   //      where bits{x+1, x} => rw
821dda28197Spatrick   //            0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io
822dda28197Spatrick   //            read-or-write (unused)
823dda28197Spatrick   //      and bits{x+3, x+2} => len
824dda28197Spatrick   //            0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
825dda28197Spatrick   //
826dda28197Spatrick   //      dr0 -> bits{19-16}
827dda28197Spatrick   //      dr1 -> bits{23-20}
828dda28197Spatrick   //      dr2 -> bits{27-24}
829dda28197Spatrick   //      dr3 -> bits{31-28}
830dda28197Spatrick   debug_state.__dr7 |= (1 << (2 * hw_index) | 0 << (16 + 4 * hw_index));
831dda28197Spatrick   uint32_t addr_32 = addr & 0xffffffff;
832dda28197Spatrick   switch (hw_index) {
833dda28197Spatrick   case 0:
834dda28197Spatrick     debug_state.__dr0 = addr_32;
835dda28197Spatrick     break;
836dda28197Spatrick   case 1:
837dda28197Spatrick     debug_state.__dr1 = addr_32;
838dda28197Spatrick     break;
839dda28197Spatrick   case 2:
840dda28197Spatrick     debug_state.__dr2 = addr_32;
841dda28197Spatrick     break;
842dda28197Spatrick   case 3:
843dda28197Spatrick     debug_state.__dr3 = addr_32;
844dda28197Spatrick     break;
845dda28197Spatrick   default:
846dda28197Spatrick     assert(0 &&
847dda28197Spatrick            "invalid hardware register index, must be one of 0, 1, 2, or 3");
848dda28197Spatrick   }
849dda28197Spatrick   return;
850dda28197Spatrick }
851dda28197Spatrick 
EnableHardwareBreakpoint(nub_addr_t addr,nub_size_t size,bool also_set_on_task)852dda28197Spatrick uint32_t DNBArchImplI386::EnableHardwareBreakpoint(nub_addr_t addr,
853dda28197Spatrick                                                    nub_size_t size,
854dda28197Spatrick                                                    bool also_set_on_task) {
855dda28197Spatrick   DNBLogThreadedIf(LOG_BREAKPOINTS,
856dda28197Spatrick                    "DNBArchImplI386::EnableHardwareBreakpoint( addr = "
857dda28197Spatrick                    "0x%8.8llx, size = %llu )",
858dda28197Spatrick                    (uint64_t)addr, (uint64_t)size);
859dda28197Spatrick 
860dda28197Spatrick   const uint32_t num_hw_breakpoints = NumSupportedHardwareBreakpoints();
861dda28197Spatrick   // Read the debug state
862dda28197Spatrick   kern_return_t kret = GetDBGState(false);
863dda28197Spatrick 
864dda28197Spatrick   if (kret != KERN_SUCCESS) {
865dda28197Spatrick     return INVALID_NUB_HW_INDEX;
866dda28197Spatrick   }
867dda28197Spatrick 
868dda28197Spatrick   // Check to make sure we have the needed hardware support
869dda28197Spatrick   uint32_t i = 0;
870dda28197Spatrick 
871dda28197Spatrick   DBG &debug_state = m_state.context.dbg;
872dda28197Spatrick   for (i = 0; i < num_hw_breakpoints; ++i) {
873dda28197Spatrick     if (IsWatchpointVacant(debug_state, i)) {
874dda28197Spatrick       break;
875dda28197Spatrick     }
876dda28197Spatrick   }
877dda28197Spatrick 
878dda28197Spatrick   // See if we found an available hw breakpoint slot above
879dda28197Spatrick   if (i < num_hw_breakpoints) {
880dda28197Spatrick     DNBLogThreadedIf(
881dda28197Spatrick         LOG_BREAKPOINTS,
882dda28197Spatrick         "DNBArchImplI386::EnableHardwareBreakpoint( free slot = %u )", i);
883dda28197Spatrick 
884dda28197Spatrick     StartTransForHWP();
885dda28197Spatrick 
886dda28197Spatrick     // Modify our local copy of the debug state, first.
887dda28197Spatrick     SetHardwareBreakpoint(debug_state, i, addr, size);
888dda28197Spatrick     // Now set the watch point in the inferior.
889dda28197Spatrick     kret = SetDBGState(also_set_on_task);
890dda28197Spatrick 
891dda28197Spatrick     DNBLogThreadedIf(LOG_BREAKPOINTS,
892dda28197Spatrick                      "DNBArchImplI386::"
893dda28197Spatrick                      "EnableHardwareBreakpoint() "
894dda28197Spatrick                      "SetDBGState() => 0x%8.8x.",
895dda28197Spatrick                      kret);
896dda28197Spatrick 
897dda28197Spatrick     if (kret == KERN_SUCCESS) {
898dda28197Spatrick       DNBLogThreadedIf(
899dda28197Spatrick           LOG_BREAKPOINTS,
900dda28197Spatrick           "DNBArchImplI386::EnableHardwareBreakpoint( enabled at slot = %u)",
901dda28197Spatrick           i);
902dda28197Spatrick       return i;
903dda28197Spatrick     }
904dda28197Spatrick     // Revert to the previous debug state voluntarily.  The transaction
905dda28197Spatrick     // coordinator knows that we have failed.
906dda28197Spatrick     else {
907dda28197Spatrick       m_state.context.dbg = GetDBGCheckpoint();
908dda28197Spatrick     }
909dda28197Spatrick   } else {
910dda28197Spatrick     DNBLogThreadedIf(LOG_BREAKPOINTS,
911dda28197Spatrick                      "DNBArchImplI386::EnableHardwareBreakpoint(addr = "
912dda28197Spatrick                      "0x%8.8llx, size = %llu) => all hardware breakpoint "
913dda28197Spatrick                      "resources are being used.",
914dda28197Spatrick                      (uint64_t)addr, (uint64_t)size);
915dda28197Spatrick   }
916dda28197Spatrick 
917dda28197Spatrick   return INVALID_NUB_HW_INDEX;
918dda28197Spatrick }
919dda28197Spatrick 
DisableHardwareBreakpoint(uint32_t hw_index,bool also_set_on_task)920dda28197Spatrick bool DNBArchImplI386::DisableHardwareBreakpoint(uint32_t hw_index,
921dda28197Spatrick                                                 bool also_set_on_task) {
922dda28197Spatrick   kern_return_t kret = GetDBGState(false);
923dda28197Spatrick 
924dda28197Spatrick   const uint32_t num_hw_points = NumSupportedHardwareBreakpoints();
925dda28197Spatrick   if (kret == KERN_SUCCESS) {
926dda28197Spatrick     DBG &debug_state = m_state.context.dbg;
927dda28197Spatrick     if (hw_index < num_hw_points &&
928dda28197Spatrick         !IsWatchpointVacant(debug_state, hw_index)) {
929dda28197Spatrick 
930dda28197Spatrick       StartTransForHWP();
931dda28197Spatrick 
932dda28197Spatrick       // Modify our local copy of the debug state, first.
933dda28197Spatrick       ClearWatchpoint(debug_state, hw_index);
934dda28197Spatrick       // Now disable the watch point in the inferior.
935dda28197Spatrick       kret = SetDBGState(true);
936dda28197Spatrick       DNBLogThreadedIf(LOG_WATCHPOINTS,
937dda28197Spatrick                        "DNBArchImplI386::DisableHardwareBreakpoint( %u )",
938dda28197Spatrick                        hw_index);
939dda28197Spatrick 
940dda28197Spatrick       if (kret == KERN_SUCCESS)
941dda28197Spatrick         return true;
942dda28197Spatrick       else // Revert to the previous debug state voluntarily.  The transaction
943dda28197Spatrick            // coordinator knows that we have failed.
944dda28197Spatrick         m_state.context.dbg = GetDBGCheckpoint();
945dda28197Spatrick     }
946dda28197Spatrick   }
947dda28197Spatrick   return false;
948dda28197Spatrick }
949dda28197Spatrick 
ClearWatchpoint(DBG & debug_state,uint32_t hw_index)950061da546Spatrick void DNBArchImplI386::ClearWatchpoint(DBG &debug_state, uint32_t hw_index) {
951061da546Spatrick   debug_state.__dr7 &= ~(3 << (2 * hw_index));
952061da546Spatrick   switch (hw_index) {
953061da546Spatrick   case 0:
954061da546Spatrick     debug_state.__dr0 = 0;
955061da546Spatrick     break;
956061da546Spatrick   case 1:
957061da546Spatrick     debug_state.__dr1 = 0;
958061da546Spatrick     break;
959061da546Spatrick   case 2:
960061da546Spatrick     debug_state.__dr2 = 0;
961061da546Spatrick     break;
962061da546Spatrick   case 3:
963061da546Spatrick     debug_state.__dr3 = 0;
964061da546Spatrick     break;
965061da546Spatrick   default:
966061da546Spatrick     assert(0 &&
967061da546Spatrick            "invalid hardware register index, must be one of 0, 1, 2, or 3");
968061da546Spatrick   }
969061da546Spatrick   return;
970061da546Spatrick }
971061da546Spatrick 
IsWatchpointVacant(const DBG & debug_state,uint32_t hw_index)972061da546Spatrick bool DNBArchImplI386::IsWatchpointVacant(const DBG &debug_state,
973061da546Spatrick                                          uint32_t hw_index) {
974061da546Spatrick   // Check dr7 (debug control register) for local/global enable bits:
975061da546Spatrick   //  global enable --. .-- local enable
976061da546Spatrick   //                  | |
977061da546Spatrick   //                  v v
978061da546Spatrick   //      dr0 -> bits{1-0}
979061da546Spatrick   //      dr1 -> bits{3-2}
980061da546Spatrick   //      dr2 -> bits{5-4}
981061da546Spatrick   //      dr3 -> bits{7-6}
982061da546Spatrick   return (debug_state.__dr7 & (3 << (2 * hw_index))) == 0;
983061da546Spatrick }
984061da546Spatrick 
985061da546Spatrick // Resets local copy of debug status register to wait for the next debug
986061da546Spatrick // exception.
ClearWatchpointHits(DBG & debug_state)987061da546Spatrick void DNBArchImplI386::ClearWatchpointHits(DBG &debug_state) {
988061da546Spatrick   // See also IsWatchpointHit().
989061da546Spatrick   debug_state.__dr6 = 0;
990061da546Spatrick   return;
991061da546Spatrick }
992061da546Spatrick 
IsWatchpointHit(const DBG & debug_state,uint32_t hw_index)993061da546Spatrick bool DNBArchImplI386::IsWatchpointHit(const DBG &debug_state,
994061da546Spatrick                                       uint32_t hw_index) {
995061da546Spatrick   // Check dr6 (debug status register) whether a watchpoint hits:
996061da546Spatrick   //          is watchpoint hit?
997061da546Spatrick   //                  |
998061da546Spatrick   //                  v
999061da546Spatrick   //      dr0 -> bits{0}
1000061da546Spatrick   //      dr1 -> bits{1}
1001061da546Spatrick   //      dr2 -> bits{2}
1002061da546Spatrick   //      dr3 -> bits{3}
1003061da546Spatrick   return (debug_state.__dr6 & (1 << hw_index));
1004061da546Spatrick }
1005061da546Spatrick 
GetWatchAddress(const DBG & debug_state,uint32_t hw_index)1006061da546Spatrick nub_addr_t DNBArchImplI386::GetWatchAddress(const DBG &debug_state,
1007061da546Spatrick                                             uint32_t hw_index) {
1008061da546Spatrick   switch (hw_index) {
1009061da546Spatrick   case 0:
1010061da546Spatrick     return debug_state.__dr0;
1011061da546Spatrick   case 1:
1012061da546Spatrick     return debug_state.__dr1;
1013061da546Spatrick   case 2:
1014061da546Spatrick     return debug_state.__dr2;
1015061da546Spatrick   case 3:
1016061da546Spatrick     return debug_state.__dr3;
1017061da546Spatrick   }
1018061da546Spatrick   assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3");
1019061da546Spatrick   return 0;
1020061da546Spatrick }
1021061da546Spatrick 
StartTransForHWP()1022061da546Spatrick bool DNBArchImplI386::StartTransForHWP() {
1023061da546Spatrick   if (m_2pc_trans_state != Trans_Done && m_2pc_trans_state != Trans_Rolled_Back)
1024061da546Spatrick     DNBLogError("%s inconsistent state detected, expected %d or %d, got: %d",
1025061da546Spatrick                 __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state);
1026061da546Spatrick   m_2pc_dbg_checkpoint = m_state.context.dbg;
1027061da546Spatrick   m_2pc_trans_state = Trans_Pending;
1028061da546Spatrick   return true;
1029061da546Spatrick }
RollbackTransForHWP()1030061da546Spatrick bool DNBArchImplI386::RollbackTransForHWP() {
1031061da546Spatrick   m_state.context.dbg = m_2pc_dbg_checkpoint;
1032061da546Spatrick   if (m_2pc_trans_state != Trans_Pending)
1033061da546Spatrick     DNBLogError("%s inconsistent state detected, expected %d, got: %d",
1034061da546Spatrick                 __FUNCTION__, Trans_Pending, m_2pc_trans_state);
1035061da546Spatrick   m_2pc_trans_state = Trans_Rolled_Back;
1036061da546Spatrick   kern_return_t kret = SetDBGState(false);
1037061da546Spatrick   DNBLogThreadedIf(
1038061da546Spatrick       LOG_WATCHPOINTS,
1039061da546Spatrick       "DNBArchImplI386::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", kret);
1040061da546Spatrick 
1041061da546Spatrick   return kret == KERN_SUCCESS;
1042061da546Spatrick }
FinishTransForHWP()1043061da546Spatrick bool DNBArchImplI386::FinishTransForHWP() {
1044061da546Spatrick   m_2pc_trans_state = Trans_Done;
1045061da546Spatrick   return true;
1046061da546Spatrick }
GetDBGCheckpoint()1047061da546Spatrick DNBArchImplI386::DBG DNBArchImplI386::GetDBGCheckpoint() {
1048061da546Spatrick   return m_2pc_dbg_checkpoint;
1049061da546Spatrick }
1050061da546Spatrick 
EnableHardwareWatchpoint(nub_addr_t addr,nub_size_t size,bool read,bool write,bool also_set_on_task)1051061da546Spatrick uint32_t DNBArchImplI386::EnableHardwareWatchpoint(nub_addr_t addr,
1052061da546Spatrick                                                    nub_size_t size, bool read,
1053061da546Spatrick                                                    bool write,
1054061da546Spatrick                                                    bool also_set_on_task) {
1055061da546Spatrick   DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::EnableHardwareWatchpoint("
1056061da546Spatrick                                     "addr = 0x%llx, size = %llu, read = %u, "
1057061da546Spatrick                                     "write = %u)",
1058061da546Spatrick                    (uint64_t)addr, (uint64_t)size, read, write);
1059061da546Spatrick 
1060061da546Spatrick   const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
1061061da546Spatrick 
1062061da546Spatrick   // Can only watch 1, 2, 4, or 8 bytes.
1063061da546Spatrick   if (!(size == 1 || size == 2 || size == 4 || size == 8))
1064061da546Spatrick     return INVALID_NUB_HW_INDEX;
1065061da546Spatrick 
1066061da546Spatrick   // We must watch for either read or write
1067061da546Spatrick   if (!read && !write)
1068061da546Spatrick     return INVALID_NUB_HW_INDEX;
1069061da546Spatrick 
1070061da546Spatrick   // Read the debug state
1071061da546Spatrick   kern_return_t kret = GetDBGState(false);
1072061da546Spatrick 
1073061da546Spatrick   if (kret == KERN_SUCCESS) {
1074061da546Spatrick     // Check to make sure we have the needed hardware support
1075061da546Spatrick     uint32_t i = 0;
1076061da546Spatrick 
1077061da546Spatrick     DBG &debug_state = m_state.context.dbg;
1078061da546Spatrick     for (i = 0; i < num_hw_watchpoints; ++i) {
1079061da546Spatrick       if (IsWatchpointVacant(debug_state, i))
1080061da546Spatrick         break;
1081061da546Spatrick     }
1082061da546Spatrick 
1083061da546Spatrick     // See if we found an available hw breakpoint slot above
1084061da546Spatrick     if (i < num_hw_watchpoints) {
1085061da546Spatrick       StartTransForHWP();
1086061da546Spatrick 
1087061da546Spatrick       // Modify our local copy of the debug state, first.
1088061da546Spatrick       SetWatchpoint(debug_state, i, addr, size, read, write);
1089061da546Spatrick       // Now set the watch point in the inferior.
1090061da546Spatrick       kret = SetDBGState(also_set_on_task);
1091061da546Spatrick       DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::"
1092061da546Spatrick                                         "EnableHardwareWatchpoint() "
1093061da546Spatrick                                         "SetDBGState() => 0x%8.8x.",
1094061da546Spatrick                        kret);
1095061da546Spatrick 
1096061da546Spatrick       if (kret == KERN_SUCCESS)
1097061da546Spatrick         return i;
1098061da546Spatrick       else // Revert to the previous debug state voluntarily.  The transaction
1099061da546Spatrick            // coordinator knows that we have failed.
1100061da546Spatrick         m_state.context.dbg = GetDBGCheckpoint();
1101061da546Spatrick     } else {
1102061da546Spatrick       DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::"
1103061da546Spatrick                                         "EnableHardwareWatchpoint(): All "
1104061da546Spatrick                                         "hardware resources (%u) are in use.",
1105061da546Spatrick                        num_hw_watchpoints);
1106061da546Spatrick     }
1107061da546Spatrick   }
1108061da546Spatrick   return INVALID_NUB_HW_INDEX;
1109061da546Spatrick }
1110061da546Spatrick 
DisableHardwareWatchpoint(uint32_t hw_index,bool also_set_on_task)1111061da546Spatrick bool DNBArchImplI386::DisableHardwareWatchpoint(uint32_t hw_index,
1112061da546Spatrick                                                 bool also_set_on_task) {
1113061da546Spatrick   kern_return_t kret = GetDBGState(false);
1114061da546Spatrick 
1115061da546Spatrick   const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
1116061da546Spatrick   if (kret == KERN_SUCCESS) {
1117061da546Spatrick     DBG &debug_state = m_state.context.dbg;
1118061da546Spatrick     if (hw_index < num_hw_points &&
1119061da546Spatrick         !IsWatchpointVacant(debug_state, hw_index)) {
1120061da546Spatrick       StartTransForHWP();
1121061da546Spatrick 
1122061da546Spatrick       // Modify our local copy of the debug state, first.
1123061da546Spatrick       ClearWatchpoint(debug_state, hw_index);
1124061da546Spatrick       // Now disable the watch point in the inferior.
1125061da546Spatrick       kret = SetDBGState(also_set_on_task);
1126061da546Spatrick       DNBLogThreadedIf(LOG_WATCHPOINTS,
1127061da546Spatrick                        "DNBArchImplI386::DisableHardwareWatchpoint( %u )",
1128061da546Spatrick                        hw_index);
1129061da546Spatrick 
1130061da546Spatrick       if (kret == KERN_SUCCESS)
1131061da546Spatrick         return true;
1132061da546Spatrick       else // Revert to the previous debug state voluntarily.  The transaction
1133061da546Spatrick            // coordinator knows that we have failed.
1134061da546Spatrick         m_state.context.dbg = GetDBGCheckpoint();
1135061da546Spatrick     }
1136061da546Spatrick   }
1137061da546Spatrick   return false;
1138061da546Spatrick }
1139061da546Spatrick 
1140061da546Spatrick // Iterate through the debug status register; return the index of the first hit.
GetHardwareWatchpointHit(nub_addr_t & addr)1141061da546Spatrick uint32_t DNBArchImplI386::GetHardwareWatchpointHit(nub_addr_t &addr) {
1142061da546Spatrick   // Read the debug state
1143061da546Spatrick   kern_return_t kret = GetDBGState(true);
1144061da546Spatrick   DNBLogThreadedIf(
1145061da546Spatrick       LOG_WATCHPOINTS,
1146061da546Spatrick       "DNBArchImplI386::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.",
1147061da546Spatrick       kret);
1148061da546Spatrick   if (kret == KERN_SUCCESS) {
1149061da546Spatrick     DBG &debug_state = m_state.context.dbg;
1150061da546Spatrick     uint32_t i, num = NumSupportedHardwareWatchpoints();
1151061da546Spatrick     for (i = 0; i < num; ++i) {
1152061da546Spatrick       if (IsWatchpointHit(debug_state, i)) {
1153061da546Spatrick         addr = GetWatchAddress(debug_state, i);
1154061da546Spatrick         DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::"
1155061da546Spatrick                                           "GetHardwareWatchpointHit() found => "
1156061da546Spatrick                                           "%u (addr = 0x%llx).",
1157061da546Spatrick                          i, (uint64_t)addr);
1158061da546Spatrick         return i;
1159061da546Spatrick       }
1160061da546Spatrick     }
1161061da546Spatrick   }
1162061da546Spatrick   return INVALID_NUB_HW_INDEX;
1163061da546Spatrick }
1164061da546Spatrick 
1165061da546Spatrick // Set the single step bit in the processor status register.
EnableHardwareSingleStep(bool enable)1166061da546Spatrick kern_return_t DNBArchImplI386::EnableHardwareSingleStep(bool enable) {
1167061da546Spatrick   if (GetGPRState(false) == KERN_SUCCESS) {
1168061da546Spatrick     const uint32_t trace_bit = 0x100u;
1169061da546Spatrick     if (enable)
1170061da546Spatrick       m_state.context.gpr.__eflags |= trace_bit;
1171061da546Spatrick     else
1172061da546Spatrick       m_state.context.gpr.__eflags &= ~trace_bit;
1173061da546Spatrick     return SetGPRState();
1174061da546Spatrick   }
1175061da546Spatrick   return m_state.GetError(e_regSetGPR, Read);
1176061da546Spatrick }
1177061da546Spatrick 
1178061da546Spatrick // Register information definitions
1179061da546Spatrick 
1180061da546Spatrick #define DEFINE_GPR_PSEUDO_16(reg16, reg32)                                     \
1181061da546Spatrick   {                                                                            \
1182061da546Spatrick     e_regSetGPR, gpr_##reg16, #reg16, NULL, Uint, Hex, 2, 0,                   \
1183061da546Spatrick         INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,            \
1184061da546Spatrick         INVALID_NUB_REGNUM, g_contained_##reg32, g_invalidate_##reg32          \
1185061da546Spatrick   }
1186061da546Spatrick #define DEFINE_GPR_PSEUDO_8H(reg8, reg32)                                      \
1187061da546Spatrick   {                                                                            \
1188061da546Spatrick     e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 1, INVALID_NUB_REGNUM, \
1189061da546Spatrick         INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,            \
1190061da546Spatrick         g_contained_##reg32, g_invalidate_##reg32                              \
1191061da546Spatrick   }
1192061da546Spatrick #define DEFINE_GPR_PSEUDO_8L(reg8, reg32)                                      \
1193061da546Spatrick   {                                                                            \
1194061da546Spatrick     e_regSetGPR, gpr_##reg8, #reg8, NULL, Uint, Hex, 1, 0, INVALID_NUB_REGNUM, \
1195061da546Spatrick         INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,            \
1196061da546Spatrick         g_contained_##reg32, g_invalidate_##reg32                              \
1197061da546Spatrick   }
1198061da546Spatrick 
1199061da546Spatrick #define GPR_OFFSET(reg) (offsetof(DNBArchImplI386::GPR, __##reg))
1200061da546Spatrick #define FPU_OFFSET(reg)                                                        \
1201061da546Spatrick   (offsetof(DNBArchImplI386::FPU, __fpu_##reg) +                               \
1202061da546Spatrick    offsetof(DNBArchImplI386::Context, fpu.no_avx))
1203061da546Spatrick #define AVX_OFFSET(reg)                                                        \
1204061da546Spatrick   (offsetof(DNBArchImplI386::AVX, __fpu_##reg) +                               \
1205061da546Spatrick    offsetof(DNBArchImplI386::Context, fpu.avx))
1206061da546Spatrick #define AVX512F_OFFSET(reg)                                                    \
1207061da546Spatrick   (offsetof(DNBArchImplI386::AVX512F, __fpu_##reg) +                           \
1208061da546Spatrick    offsetof(DNBArchImplI386::Context, fpu.avx512f))
1209061da546Spatrick #define EXC_OFFSET(reg)                                                        \
1210061da546Spatrick   (offsetof(DNBArchImplI386::EXC, __##reg) +                                   \
1211061da546Spatrick    offsetof(DNBArchImplI386::Context, exc))
1212061da546Spatrick 
1213061da546Spatrick #define GPR_SIZE(reg) (sizeof(((DNBArchImplI386::GPR *)NULL)->__##reg))
1214061da546Spatrick #define FPU_SIZE_UINT(reg) (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg))
1215061da546Spatrick #define FPU_SIZE_MMST(reg)                                                     \
1216061da546Spatrick   (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__mmst_reg))
1217061da546Spatrick #define FPU_SIZE_XMM(reg)                                                      \
1218061da546Spatrick   (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__xmm_reg))
1219061da546Spatrick #define FPU_SIZE_YMM(reg) (32)
1220061da546Spatrick #define FPU_SIZE_ZMM(reg) (64)
1221061da546Spatrick #define EXC_SIZE(reg) (sizeof(((DNBArchImplI386::EXC *)NULL)->__##reg))
1222061da546Spatrick 
1223061da546Spatrick // This does not accurately identify the location of ymm0...7 in
1224061da546Spatrick // Context.fpu.avx.  That is because there is a bunch of padding
1225061da546Spatrick // in Context.fpu.avx that we don't need.  Offset macros lay out
1226061da546Spatrick // the register state that Debugserver transmits to the debugger
1227061da546Spatrick // -- not to interpret the thread_get_state info.
1228061da546Spatrick #define AVX_OFFSET_YMM(n) (AVX_OFFSET(xmm7) + FPU_SIZE_XMM(xmm7) + (32 * n))
1229061da546Spatrick 
1230061da546Spatrick // TODO: Test this and come back.
1231061da546Spatrick #define AVX512F_OFFSET_ZMM(n) (AVX_OFFSET_YMM(7) + FPU_SIZE_XMM(xmm7) + (64 * n))
1232061da546Spatrick 
1233061da546Spatrick // These macros will auto define the register name, alt name, register size,
1234061da546Spatrick // register offset, encoding, format and native register. This ensures that
1235061da546Spatrick // the register state structures are defined correctly and have the correct
1236061da546Spatrick // sizes and offsets.
1237061da546Spatrick 
1238061da546Spatrick const char *g_contained_eax[] = {"eax", NULL};
1239061da546Spatrick const char *g_contained_ebx[] = {"ebx", NULL};
1240061da546Spatrick const char *g_contained_ecx[] = {"ecx", NULL};
1241061da546Spatrick const char *g_contained_edx[] = {"edx", NULL};
1242061da546Spatrick const char *g_contained_edi[] = {"edi", NULL};
1243061da546Spatrick const char *g_contained_esi[] = {"esi", NULL};
1244061da546Spatrick const char *g_contained_ebp[] = {"ebp", NULL};
1245061da546Spatrick const char *g_contained_esp[] = {"esp", NULL};
1246061da546Spatrick 
1247061da546Spatrick const char *g_invalidate_eax[] = {"eax", "ax", "ah", "al", NULL};
1248061da546Spatrick const char *g_invalidate_ebx[] = {"ebx", "bx", "bh", "bl", NULL};
1249061da546Spatrick const char *g_invalidate_ecx[] = {"ecx", "cx", "ch", "cl", NULL};
1250061da546Spatrick const char *g_invalidate_edx[] = {"edx", "dx", "dh", "dl", NULL};
1251061da546Spatrick const char *g_invalidate_edi[] = {"edi", "di", "dil", NULL};
1252061da546Spatrick const char *g_invalidate_esi[] = {"esi", "si", "sil", NULL};
1253061da546Spatrick const char *g_invalidate_ebp[] = {"ebp", "bp", "bpl", NULL};
1254061da546Spatrick const char *g_invalidate_esp[] = {"esp", "sp", "spl", NULL};
1255061da546Spatrick 
1256061da546Spatrick // General purpose registers for 64 bit
1257061da546Spatrick const DNBRegisterInfo DNBArchImplI386::g_gpr_registers[] = {
1258061da546Spatrick     {e_regSetGPR, gpr_eax, "eax", NULL, Uint, Hex, GPR_SIZE(eax),
1259061da546Spatrick      GPR_OFFSET(eax), ehframe_eax, dwarf_eax, INVALID_NUB_REGNUM,
1260061da546Spatrick      debugserver_eax, NULL, g_invalidate_eax},
1261061da546Spatrick     {e_regSetGPR, gpr_ebx, "ebx", NULL, Uint, Hex, GPR_SIZE(ebx),
1262061da546Spatrick      GPR_OFFSET(ebx), ehframe_ebx, dwarf_ebx, INVALID_NUB_REGNUM,
1263061da546Spatrick      debugserver_ebx, NULL, g_invalidate_ebx},
1264061da546Spatrick     {e_regSetGPR, gpr_ecx, "ecx", NULL, Uint, Hex, GPR_SIZE(ecx),
1265061da546Spatrick      GPR_OFFSET(ecx), ehframe_ecx, dwarf_ecx, INVALID_NUB_REGNUM,
1266061da546Spatrick      debugserver_ecx, NULL, g_invalidate_ecx},
1267061da546Spatrick     {e_regSetGPR, gpr_edx, "edx", NULL, Uint, Hex, GPR_SIZE(edx),
1268061da546Spatrick      GPR_OFFSET(edx), ehframe_edx, dwarf_edx, INVALID_NUB_REGNUM,
1269061da546Spatrick      debugserver_edx, NULL, g_invalidate_edx},
1270061da546Spatrick     {e_regSetGPR, gpr_edi, "edi", NULL, Uint, Hex, GPR_SIZE(edi),
1271061da546Spatrick      GPR_OFFSET(edi), ehframe_edi, dwarf_edi, INVALID_NUB_REGNUM,
1272061da546Spatrick      debugserver_edi, NULL, g_invalidate_edi},
1273061da546Spatrick     {e_regSetGPR, gpr_esi, "esi", NULL, Uint, Hex, GPR_SIZE(esi),
1274061da546Spatrick      GPR_OFFSET(esi), ehframe_esi, dwarf_esi, INVALID_NUB_REGNUM,
1275061da546Spatrick      debugserver_esi, NULL, g_invalidate_esi},
1276061da546Spatrick     {e_regSetGPR, gpr_ebp, "ebp", "fp", Uint, Hex, GPR_SIZE(ebp),
1277061da546Spatrick      GPR_OFFSET(ebp), ehframe_ebp, dwarf_ebp, GENERIC_REGNUM_FP,
1278061da546Spatrick      debugserver_ebp, NULL, g_invalidate_ebp},
1279061da546Spatrick     {e_regSetGPR, gpr_esp, "esp", "sp", Uint, Hex, GPR_SIZE(esp),
1280061da546Spatrick      GPR_OFFSET(esp), ehframe_esp, dwarf_esp, GENERIC_REGNUM_SP,
1281061da546Spatrick      debugserver_esp, NULL, g_invalidate_esp},
1282061da546Spatrick     {e_regSetGPR, gpr_ss, "ss", NULL, Uint, Hex, GPR_SIZE(ss), GPR_OFFSET(ss),
1283061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_ss,
1284061da546Spatrick      NULL, NULL},
1285061da546Spatrick     {e_regSetGPR, gpr_eflags, "eflags", "flags", Uint, Hex, GPR_SIZE(eflags),
1286061da546Spatrick      GPR_OFFSET(eflags), ehframe_eflags, dwarf_eflags, GENERIC_REGNUM_FLAGS,
1287061da546Spatrick      debugserver_eflags, NULL, NULL},
1288061da546Spatrick     {e_regSetGPR, gpr_eip, "eip", "pc", Uint, Hex, GPR_SIZE(eip),
1289061da546Spatrick      GPR_OFFSET(eip), ehframe_eip, dwarf_eip, GENERIC_REGNUM_PC,
1290061da546Spatrick      debugserver_eip, NULL, NULL},
1291061da546Spatrick     {e_regSetGPR, gpr_cs, "cs", NULL, Uint, Hex, GPR_SIZE(cs), GPR_OFFSET(cs),
1292061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_cs,
1293061da546Spatrick      NULL, NULL},
1294061da546Spatrick     {e_regSetGPR, gpr_ds, "ds", NULL, Uint, Hex, GPR_SIZE(ds), GPR_OFFSET(ds),
1295061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_ds,
1296061da546Spatrick      NULL, NULL},
1297061da546Spatrick     {e_regSetGPR, gpr_es, "es", NULL, Uint, Hex, GPR_SIZE(es), GPR_OFFSET(es),
1298061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_es,
1299061da546Spatrick      NULL, NULL},
1300061da546Spatrick     {e_regSetGPR, gpr_fs, "fs", NULL, Uint, Hex, GPR_SIZE(fs), GPR_OFFSET(fs),
1301061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_fs,
1302061da546Spatrick      NULL, NULL},
1303061da546Spatrick     {e_regSetGPR, gpr_gs, "gs", NULL, Uint, Hex, GPR_SIZE(gs), GPR_OFFSET(gs),
1304061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, debugserver_gs,
1305061da546Spatrick      NULL, NULL},
1306061da546Spatrick     DEFINE_GPR_PSEUDO_16(ax, eax),
1307061da546Spatrick     DEFINE_GPR_PSEUDO_16(bx, ebx),
1308061da546Spatrick     DEFINE_GPR_PSEUDO_16(cx, ecx),
1309061da546Spatrick     DEFINE_GPR_PSEUDO_16(dx, edx),
1310061da546Spatrick     DEFINE_GPR_PSEUDO_16(di, edi),
1311061da546Spatrick     DEFINE_GPR_PSEUDO_16(si, esi),
1312061da546Spatrick     DEFINE_GPR_PSEUDO_16(bp, ebp),
1313061da546Spatrick     DEFINE_GPR_PSEUDO_16(sp, esp),
1314061da546Spatrick     DEFINE_GPR_PSEUDO_8H(ah, eax),
1315061da546Spatrick     DEFINE_GPR_PSEUDO_8H(bh, ebx),
1316061da546Spatrick     DEFINE_GPR_PSEUDO_8H(ch, ecx),
1317061da546Spatrick     DEFINE_GPR_PSEUDO_8H(dh, edx),
1318061da546Spatrick     DEFINE_GPR_PSEUDO_8L(al, eax),
1319061da546Spatrick     DEFINE_GPR_PSEUDO_8L(bl, ebx),
1320061da546Spatrick     DEFINE_GPR_PSEUDO_8L(cl, ecx),
1321061da546Spatrick     DEFINE_GPR_PSEUDO_8L(dl, edx),
1322061da546Spatrick     DEFINE_GPR_PSEUDO_8L(dil, edi),
1323061da546Spatrick     DEFINE_GPR_PSEUDO_8L(sil, esi),
1324061da546Spatrick     DEFINE_GPR_PSEUDO_8L(bpl, ebp),
1325061da546Spatrick     DEFINE_GPR_PSEUDO_8L(spl, esp)};
1326061da546Spatrick 
1327061da546Spatrick const DNBRegisterInfo DNBArchImplI386::g_fpu_registers_no_avx[] = {
1328061da546Spatrick     {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw),
1329061da546Spatrick      FPU_OFFSET(fcw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1330061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1331061da546Spatrick     {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw),
1332061da546Spatrick      FPU_OFFSET(fsw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1333061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1334061da546Spatrick     {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, 2 /* sizeof __fpu_ftw + sizeof __fpu_rsrv1 */,
1335061da546Spatrick      FPU_OFFSET(ftw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1336061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1337061da546Spatrick     {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop),
1338061da546Spatrick      FPU_OFFSET(fop), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1339061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1340061da546Spatrick     {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip),
1341061da546Spatrick      FPU_OFFSET(ip), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1342061da546Spatrick      INVALID_NUB_REGNUM, NULL, NULL},
1343061da546Spatrick     {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs),
1344061da546Spatrick      FPU_OFFSET(cs), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1345061da546Spatrick      INVALID_NUB_REGNUM, NULL, NULL},
1346061da546Spatrick     {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp),
1347061da546Spatrick      FPU_OFFSET(dp), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1348061da546Spatrick      INVALID_NUB_REGNUM, NULL, NULL},
1349061da546Spatrick     {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds),
1350061da546Spatrick      FPU_OFFSET(ds), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1351061da546Spatrick      INVALID_NUB_REGNUM, NULL, NULL},
1352061da546Spatrick     {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr),
1353061da546Spatrick      FPU_OFFSET(mxcsr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1354061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1355061da546Spatrick     {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex,
1356061da546Spatrick      FPU_SIZE_UINT(mxcsrmask), FPU_OFFSET(mxcsrmask), INVALID_NUB_REGNUM,
1357061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1358061da546Spatrick 
1359*be691f3bSpatrick     {e_regSetFPU, fpu_stmm0, "stmm0", "st0", Vector, VectorOfUInt8,
1360061da546Spatrick      FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0,
1361061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL},
1362*be691f3bSpatrick     {e_regSetFPU, fpu_stmm1, "stmm1", "st1", Vector, VectorOfUInt8,
1363061da546Spatrick      FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1,
1364061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL},
1365*be691f3bSpatrick     {e_regSetFPU, fpu_stmm2, "stmm2", "st2", Vector, VectorOfUInt8,
1366061da546Spatrick      FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2,
1367061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL},
1368*be691f3bSpatrick     {e_regSetFPU, fpu_stmm3, "stmm3", "st3", Vector, VectorOfUInt8,
1369061da546Spatrick      FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3,
1370061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL},
1371*be691f3bSpatrick     {e_regSetFPU, fpu_stmm4, "stmm4", "st4", Vector, VectorOfUInt8,
1372061da546Spatrick      FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4,
1373061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL},
1374*be691f3bSpatrick     {e_regSetFPU, fpu_stmm5, "stmm5", "st5", Vector, VectorOfUInt8,
1375061da546Spatrick      FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5,
1376061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL},
1377*be691f3bSpatrick     {e_regSetFPU, fpu_stmm6, "stmm6", "st6", Vector, VectorOfUInt8,
1378061da546Spatrick      FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6,
1379061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL},
1380*be691f3bSpatrick     {e_regSetFPU, fpu_stmm7, "stmm7", "st7", Vector, VectorOfUInt8,
1381061da546Spatrick      FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7,
1382061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL},
1383061da546Spatrick 
1384061da546Spatrick     {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8,
1385061da546Spatrick      FPU_SIZE_XMM(xmm0), FPU_OFFSET(xmm0), INVALID_NUB_REGNUM, dwarf_xmm0,
1386061da546Spatrick      INVALID_NUB_REGNUM, debugserver_xmm0, NULL, NULL},
1387061da546Spatrick     {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8,
1388061da546Spatrick      FPU_SIZE_XMM(xmm1), FPU_OFFSET(xmm1), INVALID_NUB_REGNUM, dwarf_xmm1,
1389061da546Spatrick      INVALID_NUB_REGNUM, debugserver_xmm1, NULL, NULL},
1390061da546Spatrick     {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8,
1391061da546Spatrick      FPU_SIZE_XMM(xmm2), FPU_OFFSET(xmm2), INVALID_NUB_REGNUM, dwarf_xmm2,
1392061da546Spatrick      INVALID_NUB_REGNUM, debugserver_xmm2, NULL, NULL},
1393061da546Spatrick     {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8,
1394061da546Spatrick      FPU_SIZE_XMM(xmm3), FPU_OFFSET(xmm3), INVALID_NUB_REGNUM, dwarf_xmm3,
1395061da546Spatrick      INVALID_NUB_REGNUM, debugserver_xmm3, NULL, NULL},
1396061da546Spatrick     {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8,
1397061da546Spatrick      FPU_SIZE_XMM(xmm4), FPU_OFFSET(xmm4), INVALID_NUB_REGNUM, dwarf_xmm4,
1398061da546Spatrick      INVALID_NUB_REGNUM, debugserver_xmm4, NULL, NULL},
1399061da546Spatrick     {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8,
1400061da546Spatrick      FPU_SIZE_XMM(xmm5), FPU_OFFSET(xmm5), INVALID_NUB_REGNUM, dwarf_xmm5,
1401061da546Spatrick      INVALID_NUB_REGNUM, debugserver_xmm5, NULL, NULL},
1402061da546Spatrick     {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8,
1403061da546Spatrick      FPU_SIZE_XMM(xmm6), FPU_OFFSET(xmm6), INVALID_NUB_REGNUM, dwarf_xmm6,
1404061da546Spatrick      INVALID_NUB_REGNUM, debugserver_xmm6, NULL, NULL},
1405061da546Spatrick     {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8,
1406061da546Spatrick      FPU_SIZE_XMM(xmm7), FPU_OFFSET(xmm7), INVALID_NUB_REGNUM, dwarf_xmm7,
1407061da546Spatrick      INVALID_NUB_REGNUM, debugserver_xmm7, NULL, NULL}};
1408061da546Spatrick 
1409061da546Spatrick static const char *g_contained_ymm0[] = {"ymm0", NULL};
1410061da546Spatrick static const char *g_contained_ymm1[] = {"ymm1", NULL};
1411061da546Spatrick static const char *g_contained_ymm2[] = {"ymm2", NULL};
1412061da546Spatrick static const char *g_contained_ymm3[] = {"ymm3", NULL};
1413061da546Spatrick static const char *g_contained_ymm4[] = {"ymm4", NULL};
1414061da546Spatrick static const char *g_contained_ymm5[] = {"ymm5", NULL};
1415061da546Spatrick static const char *g_contained_ymm6[] = {"ymm6", NULL};
1416061da546Spatrick static const char *g_contained_ymm7[] = {"ymm7", NULL};
1417061da546Spatrick 
1418061da546Spatrick const DNBRegisterInfo DNBArchImplI386::g_fpu_registers_avx[] = {
1419061da546Spatrick     {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw),
1420061da546Spatrick      AVX_OFFSET(fcw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1421061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1422061da546Spatrick     {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw),
1423061da546Spatrick      AVX_OFFSET(fsw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1424061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1425061da546Spatrick     {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, 2 /* sizeof __fpu_ftw + sizeof __fpu_rsrv1 */,
1426061da546Spatrick      AVX_OFFSET(ftw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1427061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1428061da546Spatrick     {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop),
1429061da546Spatrick      AVX_OFFSET(fop), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1430061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1431061da546Spatrick     {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip),
1432061da546Spatrick      AVX_OFFSET(ip), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1433061da546Spatrick      INVALID_NUB_REGNUM, NULL, NULL},
1434061da546Spatrick     {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs),
1435061da546Spatrick      AVX_OFFSET(cs), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1436061da546Spatrick      INVALID_NUB_REGNUM, NULL, NULL},
1437061da546Spatrick     {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp),
1438061da546Spatrick      AVX_OFFSET(dp), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1439061da546Spatrick      INVALID_NUB_REGNUM, NULL, NULL},
1440061da546Spatrick     {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds),
1441061da546Spatrick      AVX_OFFSET(ds), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1442061da546Spatrick      INVALID_NUB_REGNUM, NULL, NULL},
1443061da546Spatrick     {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr),
1444061da546Spatrick      AVX_OFFSET(mxcsr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1445061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1446061da546Spatrick     {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex,
1447061da546Spatrick      FPU_SIZE_UINT(mxcsrmask), AVX_OFFSET(mxcsrmask), INVALID_NUB_REGNUM,
1448061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1449061da546Spatrick 
1450*be691f3bSpatrick     {e_regSetFPU, fpu_stmm0, "stmm0", "st0", Vector, VectorOfUInt8,
1451061da546Spatrick      FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0,
1452061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL},
1453*be691f3bSpatrick     {e_regSetFPU, fpu_stmm1, "stmm1", "st1", Vector, VectorOfUInt8,
1454061da546Spatrick      FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1,
1455061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL},
1456*be691f3bSpatrick     {e_regSetFPU, fpu_stmm2, "stmm2", "st2", Vector, VectorOfUInt8,
1457061da546Spatrick      FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2,
1458061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL},
1459*be691f3bSpatrick     {e_regSetFPU, fpu_stmm3, "stmm3", "st3", Vector, VectorOfUInt8,
1460061da546Spatrick      FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3,
1461061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL},
1462*be691f3bSpatrick     {e_regSetFPU, fpu_stmm4, "stmm4", "st4", Vector, VectorOfUInt8,
1463061da546Spatrick      FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4,
1464061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL},
1465*be691f3bSpatrick     {e_regSetFPU, fpu_stmm5, "stmm5", "st5", Vector, VectorOfUInt8,
1466061da546Spatrick      FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5,
1467061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL},
1468*be691f3bSpatrick     {e_regSetFPU, fpu_stmm6, "stmm6", "st6", Vector, VectorOfUInt8,
1469061da546Spatrick      FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6,
1470061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL},
1471*be691f3bSpatrick     {e_regSetFPU, fpu_stmm7, "stmm7", "st7", Vector, VectorOfUInt8,
1472061da546Spatrick      FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7,
1473061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL},
1474061da546Spatrick 
1475061da546Spatrick     {e_regSetFPU, fpu_ymm0, "ymm0", NULL, Vector, VectorOfUInt8,
1476061da546Spatrick      FPU_SIZE_YMM(ymm0), AVX_OFFSET_YMM(0), INVALID_NUB_REGNUM, dwarf_ymm0,
1477061da546Spatrick      INVALID_NUB_REGNUM, debugserver_ymm0, NULL, NULL},
1478061da546Spatrick     {e_regSetFPU, fpu_ymm1, "ymm1", NULL, Vector, VectorOfUInt8,
1479061da546Spatrick      FPU_SIZE_YMM(ymm1), AVX_OFFSET_YMM(1), INVALID_NUB_REGNUM, dwarf_ymm1,
1480061da546Spatrick      INVALID_NUB_REGNUM, debugserver_ymm1, NULL, NULL},
1481061da546Spatrick     {e_regSetFPU, fpu_ymm2, "ymm2", NULL, Vector, VectorOfUInt8,
1482061da546Spatrick      FPU_SIZE_YMM(ymm2), AVX_OFFSET_YMM(2), INVALID_NUB_REGNUM, dwarf_ymm2,
1483061da546Spatrick      INVALID_NUB_REGNUM, debugserver_ymm2, NULL, NULL},
1484061da546Spatrick     {e_regSetFPU, fpu_ymm3, "ymm3", NULL, Vector, VectorOfUInt8,
1485061da546Spatrick      FPU_SIZE_YMM(ymm3), AVX_OFFSET_YMM(3), INVALID_NUB_REGNUM, dwarf_ymm3,
1486061da546Spatrick      INVALID_NUB_REGNUM, debugserver_ymm3, NULL, NULL},
1487061da546Spatrick     {e_regSetFPU, fpu_ymm4, "ymm4", NULL, Vector, VectorOfUInt8,
1488061da546Spatrick      FPU_SIZE_YMM(ymm4), AVX_OFFSET_YMM(4), INVALID_NUB_REGNUM, dwarf_ymm4,
1489061da546Spatrick      INVALID_NUB_REGNUM, debugserver_ymm4, NULL, NULL},
1490061da546Spatrick     {e_regSetFPU, fpu_ymm5, "ymm5", NULL, Vector, VectorOfUInt8,
1491061da546Spatrick      FPU_SIZE_YMM(ymm5), AVX_OFFSET_YMM(5), INVALID_NUB_REGNUM, dwarf_ymm5,
1492061da546Spatrick      INVALID_NUB_REGNUM, debugserver_ymm5, NULL, NULL},
1493061da546Spatrick     {e_regSetFPU, fpu_ymm6, "ymm6", NULL, Vector, VectorOfUInt8,
1494061da546Spatrick      FPU_SIZE_YMM(ymm6), AVX_OFFSET_YMM(6), INVALID_NUB_REGNUM, dwarf_ymm6,
1495061da546Spatrick      INVALID_NUB_REGNUM, debugserver_ymm6, NULL, NULL},
1496061da546Spatrick     {e_regSetFPU, fpu_ymm7, "ymm7", NULL, Vector, VectorOfUInt8,
1497061da546Spatrick      FPU_SIZE_YMM(ymm7), AVX_OFFSET_YMM(7), INVALID_NUB_REGNUM, dwarf_ymm7,
1498061da546Spatrick      INVALID_NUB_REGNUM, debugserver_ymm7, NULL, NULL},
1499061da546Spatrick 
1500061da546Spatrick     {e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8,
1501061da546Spatrick      FPU_SIZE_XMM(xmm0), 0, INVALID_NUB_REGNUM, dwarf_xmm0, INVALID_NUB_REGNUM,
1502061da546Spatrick      debugserver_xmm0, g_contained_ymm0, NULL},
1503061da546Spatrick     {e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8,
1504061da546Spatrick      FPU_SIZE_XMM(xmm1), 0, INVALID_NUB_REGNUM, dwarf_xmm1, INVALID_NUB_REGNUM,
1505061da546Spatrick      debugserver_xmm1, g_contained_ymm1, NULL},
1506061da546Spatrick     {e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8,
1507061da546Spatrick      FPU_SIZE_XMM(xmm2), 0, INVALID_NUB_REGNUM, dwarf_xmm2, INVALID_NUB_REGNUM,
1508061da546Spatrick      debugserver_xmm2, g_contained_ymm2, NULL},
1509061da546Spatrick     {e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8,
1510061da546Spatrick      FPU_SIZE_XMM(xmm3), 0, INVALID_NUB_REGNUM, dwarf_xmm3, INVALID_NUB_REGNUM,
1511061da546Spatrick      debugserver_xmm3, g_contained_ymm3, NULL},
1512061da546Spatrick     {e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8,
1513061da546Spatrick      FPU_SIZE_XMM(xmm4), 0, INVALID_NUB_REGNUM, dwarf_xmm4, INVALID_NUB_REGNUM,
1514061da546Spatrick      debugserver_xmm4, g_contained_ymm4, NULL},
1515061da546Spatrick     {e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8,
1516061da546Spatrick      FPU_SIZE_XMM(xmm5), 0, INVALID_NUB_REGNUM, dwarf_xmm5, INVALID_NUB_REGNUM,
1517061da546Spatrick      debugserver_xmm5, g_contained_ymm5, NULL},
1518061da546Spatrick     {e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8,
1519061da546Spatrick      FPU_SIZE_XMM(xmm6), 0, INVALID_NUB_REGNUM, dwarf_xmm6, INVALID_NUB_REGNUM,
1520061da546Spatrick      debugserver_xmm6, g_contained_ymm6, NULL},
1521061da546Spatrick     {e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8,
1522061da546Spatrick      FPU_SIZE_XMM(xmm7), 0, INVALID_NUB_REGNUM, dwarf_xmm7, INVALID_NUB_REGNUM,
1523061da546Spatrick      debugserver_xmm7, g_contained_ymm7, NULL},
1524061da546Spatrick 
1525061da546Spatrick };
1526061da546Spatrick 
1527061da546Spatrick 
1528061da546Spatrick #define STR(s) #s
1529061da546Spatrick 
1530061da546Spatrick #define ZMM_REG_DEF(reg)                                                       \
1531061da546Spatrick   {                                                                            \
1532061da546Spatrick     e_regSetFPU, fpu_zmm##reg, STR(zmm##reg), NULL, Vector, VectorOfUInt8,        \
1533061da546Spatrick         FPU_SIZE_ZMM(zmm##reg), AVX512F_OFFSET_ZMM(reg), INVALID_NUB_REGNUM,   \
1534061da546Spatrick         dwarf_zmm##reg, INVALID_NUB_REGNUM, debugserver_zmm##reg, NULL, NULL   \
1535061da546Spatrick   }
1536061da546Spatrick 
1537061da546Spatrick #define YMM_REG_ALIAS(reg)                                                     \
1538061da546Spatrick   {                                                                            \
1539061da546Spatrick     e_regSetFPU, fpu_ymm##reg, STR(ymm##reg), NULL, Vector, VectorOfUInt8,        \
1540061da546Spatrick         FPU_SIZE_YMM(ymm##reg), 0, INVALID_NUB_REGNUM, dwarf_ymm##reg,         \
1541061da546Spatrick         INVALID_NUB_REGNUM, debugserver_ymm##reg, g_contained_zmm##reg, NULL   \
1542061da546Spatrick   }
1543061da546Spatrick 
1544061da546Spatrick #define XMM_REG_ALIAS(reg)                                                     \
1545061da546Spatrick   {                                                                            \
1546061da546Spatrick     e_regSetFPU, fpu_xmm##reg, STR(xmm##reg), NULL, Vector, VectorOfUInt8,        \
1547061da546Spatrick         FPU_SIZE_XMM(xmm##reg), 0, INVALID_NUB_REGNUM, dwarf_xmm##reg,         \
1548061da546Spatrick         INVALID_NUB_REGNUM, debugserver_xmm##reg, g_contained_zmm##reg, NULL   \
1549061da546Spatrick   }
1550061da546Spatrick 
1551061da546Spatrick #define AVX512_K_REG_DEF(reg)                                                  \
1552061da546Spatrick   {                                                                            \
1553061da546Spatrick     e_regSetFPU, fpu_k##reg, STR(k##reg), NULL, Vector, VectorOfUInt8, 8,      \
1554061da546Spatrick         AVX512F_OFFSET(k##reg), dwarf_k##reg, dwarf_k##reg, -1U,               \
1555061da546Spatrick         debugserver_k##reg, NULL, NULL                                         \
1556061da546Spatrick   }
1557061da546Spatrick 
1558061da546Spatrick static const char *g_contained_zmm0[] = {"zmm0", NULL};
1559061da546Spatrick static const char *g_contained_zmm1[] = {"zmm1", NULL};
1560061da546Spatrick static const char *g_contained_zmm2[] = {"zmm2", NULL};
1561061da546Spatrick static const char *g_contained_zmm3[] = {"zmm3", NULL};
1562061da546Spatrick static const char *g_contained_zmm4[] = {"zmm4", NULL};
1563061da546Spatrick static const char *g_contained_zmm5[] = {"zmm5", NULL};
1564061da546Spatrick static const char *g_contained_zmm6[] = {"zmm6", NULL};
1565061da546Spatrick static const char *g_contained_zmm7[] = {"zmm7", NULL};
1566061da546Spatrick 
1567061da546Spatrick const DNBRegisterInfo DNBArchImplI386::g_fpu_registers_avx512f[] = {
1568061da546Spatrick     {e_regSetFPU, fpu_fcw, "fctrl", NULL, Uint, Hex, FPU_SIZE_UINT(fcw),
1569061da546Spatrick      AVX_OFFSET(fcw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1570061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1571061da546Spatrick     {e_regSetFPU, fpu_fsw, "fstat", NULL, Uint, Hex, FPU_SIZE_UINT(fsw),
1572061da546Spatrick      AVX_OFFSET(fsw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1573061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1574061da546Spatrick     {e_regSetFPU, fpu_ftw, "ftag", NULL, Uint, Hex, 2 /* sizeof __fpu_ftw + sizeof __fpu_rsrv1 */,
1575061da546Spatrick      FPU_OFFSET(ftw), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1576061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1577061da546Spatrick     {e_regSetFPU, fpu_fop, "fop", NULL, Uint, Hex, FPU_SIZE_UINT(fop),
1578061da546Spatrick      AVX_OFFSET(fop), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1579061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1580061da546Spatrick     {e_regSetFPU, fpu_ip, "fioff", NULL, Uint, Hex, FPU_SIZE_UINT(ip),
1581061da546Spatrick      AVX_OFFSET(ip), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1582061da546Spatrick      INVALID_NUB_REGNUM, NULL, NULL},
1583061da546Spatrick     {e_regSetFPU, fpu_cs, "fiseg", NULL, Uint, Hex, FPU_SIZE_UINT(cs),
1584061da546Spatrick      AVX_OFFSET(cs), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1585061da546Spatrick      INVALID_NUB_REGNUM, NULL, NULL},
1586061da546Spatrick     {e_regSetFPU, fpu_dp, "fooff", NULL, Uint, Hex, FPU_SIZE_UINT(dp),
1587061da546Spatrick      AVX_OFFSET(dp), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1588061da546Spatrick      INVALID_NUB_REGNUM, NULL, NULL},
1589061da546Spatrick     {e_regSetFPU, fpu_ds, "foseg", NULL, Uint, Hex, FPU_SIZE_UINT(ds),
1590061da546Spatrick      AVX_OFFSET(ds), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1591061da546Spatrick      INVALID_NUB_REGNUM, NULL, NULL},
1592061da546Spatrick     {e_regSetFPU, fpu_mxcsr, "mxcsr", NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr),
1593061da546Spatrick      AVX_OFFSET(mxcsr), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1594061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1595061da546Spatrick     {e_regSetFPU, fpu_mxcsrmask, "mxcsrmask", NULL, Uint, Hex,
1596061da546Spatrick      FPU_SIZE_UINT(mxcsrmask), AVX_OFFSET(mxcsrmask), INVALID_NUB_REGNUM,
1597061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1598061da546Spatrick 
1599*be691f3bSpatrick     {e_regSetFPU, fpu_stmm0, "stmm0", "st0", Vector, VectorOfUInt8,
1600061da546Spatrick      FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0,
1601061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL},
1602*be691f3bSpatrick     {e_regSetFPU, fpu_stmm1, "stmm1", "st1", Vector, VectorOfUInt8,
1603061da546Spatrick      FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1,
1604061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL},
1605*be691f3bSpatrick     {e_regSetFPU, fpu_stmm2, "stmm2", "st2", Vector, VectorOfUInt8,
1606061da546Spatrick      FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2,
1607061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL},
1608*be691f3bSpatrick     {e_regSetFPU, fpu_stmm3, "stmm3", "st3", Vector, VectorOfUInt8,
1609061da546Spatrick      FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3,
1610061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL},
1611*be691f3bSpatrick     {e_regSetFPU, fpu_stmm4, "stmm4", "st4", Vector, VectorOfUInt8,
1612061da546Spatrick      FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4,
1613061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL},
1614*be691f3bSpatrick     {e_regSetFPU, fpu_stmm5, "stmm5", "st5", Vector, VectorOfUInt8,
1615061da546Spatrick      FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5,
1616061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL},
1617*be691f3bSpatrick     {e_regSetFPU, fpu_stmm6, "stmm6", "st6", Vector, VectorOfUInt8,
1618061da546Spatrick      FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6,
1619061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL},
1620*be691f3bSpatrick     {e_regSetFPU, fpu_stmm7, "stmm7", "st7", Vector, VectorOfUInt8,
1621061da546Spatrick      FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7,
1622061da546Spatrick      INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL},
1623061da546Spatrick 
1624061da546Spatrick     AVX512_K_REG_DEF(0),
1625061da546Spatrick     AVX512_K_REG_DEF(1),
1626061da546Spatrick     AVX512_K_REG_DEF(2),
1627061da546Spatrick     AVX512_K_REG_DEF(3),
1628061da546Spatrick     AVX512_K_REG_DEF(4),
1629061da546Spatrick     AVX512_K_REG_DEF(5),
1630061da546Spatrick     AVX512_K_REG_DEF(6),
1631061da546Spatrick     AVX512_K_REG_DEF(7),
1632061da546Spatrick 
1633061da546Spatrick     ZMM_REG_DEF(0),
1634061da546Spatrick     ZMM_REG_DEF(1),
1635061da546Spatrick     ZMM_REG_DEF(2),
1636061da546Spatrick     ZMM_REG_DEF(3),
1637061da546Spatrick     ZMM_REG_DEF(4),
1638061da546Spatrick     ZMM_REG_DEF(5),
1639061da546Spatrick     ZMM_REG_DEF(6),
1640061da546Spatrick     ZMM_REG_DEF(7),
1641061da546Spatrick 
1642061da546Spatrick     YMM_REG_ALIAS(0),
1643061da546Spatrick     YMM_REG_ALIAS(1),
1644061da546Spatrick     YMM_REG_ALIAS(2),
1645061da546Spatrick     YMM_REG_ALIAS(3),
1646061da546Spatrick     YMM_REG_ALIAS(4),
1647061da546Spatrick     YMM_REG_ALIAS(5),
1648061da546Spatrick     YMM_REG_ALIAS(6),
1649061da546Spatrick     YMM_REG_ALIAS(7),
1650061da546Spatrick 
1651061da546Spatrick     XMM_REG_ALIAS(0),
1652061da546Spatrick     XMM_REG_ALIAS(1),
1653061da546Spatrick     XMM_REG_ALIAS(2),
1654061da546Spatrick     XMM_REG_ALIAS(3),
1655061da546Spatrick     XMM_REG_ALIAS(4),
1656061da546Spatrick     XMM_REG_ALIAS(5),
1657061da546Spatrick     XMM_REG_ALIAS(6),
1658061da546Spatrick     XMM_REG_ALIAS(7)
1659061da546Spatrick 
1660061da546Spatrick };
1661061da546Spatrick 
1662061da546Spatrick const DNBRegisterInfo DNBArchImplI386::g_exc_registers[] = {
1663061da546Spatrick     {e_regSetEXC, exc_trapno, "trapno", NULL, Uint, Hex, EXC_SIZE(trapno),
1664061da546Spatrick      EXC_OFFSET(trapno), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1665061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1666061da546Spatrick     {e_regSetEXC, exc_err, "err", NULL, Uint, Hex, EXC_SIZE(err),
1667061da546Spatrick      EXC_OFFSET(err), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM,
1668061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL},
1669061da546Spatrick     {e_regSetEXC, exc_faultvaddr, "faultvaddr", NULL, Uint, Hex,
1670061da546Spatrick      EXC_SIZE(faultvaddr), EXC_OFFSET(faultvaddr), INVALID_NUB_REGNUM,
1671061da546Spatrick      INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL}};
1672061da546Spatrick 
1673061da546Spatrick // Number of registers in each register set
1674061da546Spatrick const size_t DNBArchImplI386::k_num_gpr_registers =
1675061da546Spatrick     sizeof(g_gpr_registers) / sizeof(DNBRegisterInfo);
1676061da546Spatrick const size_t DNBArchImplI386::k_num_fpu_registers_no_avx =
1677061da546Spatrick     sizeof(g_fpu_registers_no_avx) / sizeof(DNBRegisterInfo);
1678061da546Spatrick const size_t DNBArchImplI386::k_num_fpu_registers_avx =
1679061da546Spatrick     sizeof(g_fpu_registers_avx) / sizeof(DNBRegisterInfo);
1680061da546Spatrick const size_t DNBArchImplI386::k_num_fpu_registers_avx512f =
1681061da546Spatrick     sizeof(g_fpu_registers_avx512f) / sizeof(DNBRegisterInfo);
1682061da546Spatrick const size_t DNBArchImplI386::k_num_exc_registers =
1683061da546Spatrick     sizeof(g_exc_registers) / sizeof(DNBRegisterInfo);
1684061da546Spatrick const size_t DNBArchImplI386::k_num_all_registers_no_avx =
1685061da546Spatrick     k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers;
1686061da546Spatrick const size_t DNBArchImplI386::k_num_all_registers_avx =
1687061da546Spatrick     k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers;
1688061da546Spatrick const size_t DNBArchImplI386::k_num_all_registers_avx512f =
1689061da546Spatrick     k_num_gpr_registers + k_num_fpu_registers_avx512f + k_num_exc_registers;
1690061da546Spatrick 
1691061da546Spatrick // Register set definitions. The first definitions at register set index
1692061da546Spatrick // of zero is for all registers, followed by other registers sets. The
1693061da546Spatrick // register information for the all register set need not be filled in.
1694061da546Spatrick const DNBRegisterSetInfo DNBArchImplI386::g_reg_sets_no_avx[] = {
1695061da546Spatrick     {"i386 Registers", NULL, k_num_all_registers_no_avx},
1696061da546Spatrick     {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers},
1697061da546Spatrick     {"Floating Point Registers", g_fpu_registers_no_avx,
1698061da546Spatrick      k_num_fpu_registers_no_avx},
1699061da546Spatrick     {"Exception State Registers", g_exc_registers, k_num_exc_registers}};
1700061da546Spatrick 
1701061da546Spatrick const DNBRegisterSetInfo DNBArchImplI386::g_reg_sets_avx[] = {
1702061da546Spatrick     {"i386 Registers", NULL, k_num_all_registers_avx},
1703061da546Spatrick     {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers},
1704061da546Spatrick     {"Floating Point Registers", g_fpu_registers_avx, k_num_fpu_registers_avx},
1705061da546Spatrick     {"Exception State Registers", g_exc_registers, k_num_exc_registers}};
1706061da546Spatrick 
1707061da546Spatrick const DNBRegisterSetInfo DNBArchImplI386::g_reg_sets_avx512f[] = {
1708061da546Spatrick     {"i386 Registers", NULL, k_num_all_registers_avx512f},
1709061da546Spatrick     {"General Purpose Registers", g_gpr_registers, k_num_gpr_registers},
1710061da546Spatrick     {"Floating Point Registers", g_fpu_registers_avx512f,
1711061da546Spatrick     k_num_fpu_registers_avx512f},
1712061da546Spatrick     {"Exception State Registers", g_exc_registers, k_num_exc_registers}};
1713061da546Spatrick 
1714061da546Spatrick // Total number of register sets for this architecture
1715061da546Spatrick const size_t DNBArchImplI386::k_num_register_sets =
1716061da546Spatrick     sizeof(g_reg_sets_avx) / sizeof(DNBRegisterSetInfo);
1717061da546Spatrick 
Create(MachThread * thread)1718061da546Spatrick DNBArchProtocol *DNBArchImplI386::Create(MachThread *thread) {
1719061da546Spatrick   DNBArchImplI386 *obj = new DNBArchImplI386(thread);
1720061da546Spatrick   return obj;
1721061da546Spatrick }
1722061da546Spatrick 
SoftwareBreakpointOpcode(nub_size_t byte_size)1723061da546Spatrick const uint8_t *DNBArchImplI386::SoftwareBreakpointOpcode(nub_size_t byte_size) {
1724061da546Spatrick   static const uint8_t g_breakpoint_opcode[] = {0xCC};
1725061da546Spatrick   if (byte_size == 1)
1726061da546Spatrick     return g_breakpoint_opcode;
1727061da546Spatrick   return NULL;
1728061da546Spatrick }
1729061da546Spatrick 
1730061da546Spatrick const DNBRegisterSetInfo *
GetRegisterSetInfo(nub_size_t * num_reg_sets)1731061da546Spatrick DNBArchImplI386::GetRegisterSetInfo(nub_size_t *num_reg_sets) {
1732061da546Spatrick   *num_reg_sets = k_num_register_sets;
1733061da546Spatrick   if (CPUHasAVX512f() || FORCE_AVX_REGS)
1734061da546Spatrick     return g_reg_sets_avx512f;
1735061da546Spatrick   if (CPUHasAVX())
1736061da546Spatrick     return g_reg_sets_avx;
1737061da546Spatrick   else
1738061da546Spatrick     return g_reg_sets_no_avx;
1739061da546Spatrick }
1740061da546Spatrick 
Initialize()1741061da546Spatrick void DNBArchImplI386::Initialize() {
1742061da546Spatrick   DNBArchPluginInfo arch_plugin_info = {
1743061da546Spatrick       CPU_TYPE_I386, DNBArchImplI386::Create,
1744061da546Spatrick       DNBArchImplI386::GetRegisterSetInfo,
1745061da546Spatrick       DNBArchImplI386::SoftwareBreakpointOpcode};
1746061da546Spatrick 
1747061da546Spatrick   // Register this arch plug-in with the main protocol class
1748061da546Spatrick   DNBArchProtocol::RegisterArchPlugin(arch_plugin_info);
1749061da546Spatrick }
1750061da546Spatrick 
GetRegisterValue(uint32_t set,uint32_t reg,DNBRegisterValue * value)1751061da546Spatrick bool DNBArchImplI386::GetRegisterValue(uint32_t set, uint32_t reg,
1752061da546Spatrick                                        DNBRegisterValue *value) {
1753061da546Spatrick   if (set == REGISTER_SET_GENERIC) {
1754061da546Spatrick     switch (reg) {
1755061da546Spatrick     case GENERIC_REGNUM_PC: // Program Counter
1756061da546Spatrick       set = e_regSetGPR;
1757061da546Spatrick       reg = gpr_eip;
1758061da546Spatrick       break;
1759061da546Spatrick 
1760061da546Spatrick     case GENERIC_REGNUM_SP: // Stack Pointer
1761061da546Spatrick       set = e_regSetGPR;
1762061da546Spatrick       reg = gpr_esp;
1763061da546Spatrick       break;
1764061da546Spatrick 
1765061da546Spatrick     case GENERIC_REGNUM_FP: // Frame Pointer
1766061da546Spatrick       set = e_regSetGPR;
1767061da546Spatrick       reg = gpr_ebp;
1768061da546Spatrick       break;
1769061da546Spatrick 
1770061da546Spatrick     case GENERIC_REGNUM_FLAGS: // Processor flags register
1771061da546Spatrick       set = e_regSetGPR;
1772061da546Spatrick       reg = gpr_eflags;
1773061da546Spatrick       break;
1774061da546Spatrick 
1775061da546Spatrick     case GENERIC_REGNUM_RA: // Return Address
1776061da546Spatrick     default:
1777061da546Spatrick       return false;
1778061da546Spatrick     }
1779061da546Spatrick   }
1780061da546Spatrick 
1781061da546Spatrick   if (GetRegisterState(set, false) != KERN_SUCCESS)
1782061da546Spatrick     return false;
1783061da546Spatrick 
1784061da546Spatrick   const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
1785061da546Spatrick   if (regInfo) {
1786061da546Spatrick     value->info = *regInfo;
1787061da546Spatrick     switch (set) {
1788061da546Spatrick     case e_regSetGPR:
1789061da546Spatrick       if (reg < k_num_gpr_registers) {
1790061da546Spatrick         value->value.uint32 = ((uint32_t *)(&m_state.context.gpr))[reg];
1791061da546Spatrick         return true;
1792061da546Spatrick       }
1793061da546Spatrick       break;
1794061da546Spatrick 
1795061da546Spatrick     case e_regSetFPU:
1796061da546Spatrick       if (reg > fpu_xmm7 && !(CPUHasAVX() || FORCE_AVX_REGS))
1797061da546Spatrick         return false;
1798061da546Spatrick       if (reg > fpu_ymm7 && !(CPUHasAVX512f() || FORCE_AVX_REGS))
1799061da546Spatrick         return false;
1800061da546Spatrick       switch (reg) {
1801061da546Spatrick       case fpu_fcw:
1802061da546Spatrick         value->value.uint16 =
1803061da546Spatrick             *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw));
1804061da546Spatrick         return true;
1805061da546Spatrick       case fpu_fsw:
1806061da546Spatrick         value->value.uint16 =
1807061da546Spatrick             *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw));
1808061da546Spatrick         return true;
1809061da546Spatrick       case fpu_ftw:
1810061da546Spatrick         memcpy (&value->value.uint16, &m_state.context.fpu.no_avx.__fpu_ftw, 2);
1811061da546Spatrick         return true;
1812061da546Spatrick       case fpu_fop:
1813061da546Spatrick         value->value.uint16 = m_state.context.fpu.no_avx.__fpu_fop;
1814061da546Spatrick         return true;
1815061da546Spatrick       case fpu_ip:
1816061da546Spatrick         value->value.uint32 = m_state.context.fpu.no_avx.__fpu_ip;
1817061da546Spatrick         return true;
1818061da546Spatrick       case fpu_cs:
1819061da546Spatrick         value->value.uint16 = m_state.context.fpu.no_avx.__fpu_cs;
1820061da546Spatrick         return true;
1821061da546Spatrick       case fpu_dp:
1822061da546Spatrick         value->value.uint32 = m_state.context.fpu.no_avx.__fpu_dp;
1823061da546Spatrick         return true;
1824061da546Spatrick       case fpu_ds:
1825061da546Spatrick         value->value.uint16 = m_state.context.fpu.no_avx.__fpu_ds;
1826061da546Spatrick         return true;
1827061da546Spatrick       case fpu_mxcsr:
1828061da546Spatrick         value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsr;
1829061da546Spatrick         return true;
1830061da546Spatrick       case fpu_mxcsrmask:
1831061da546Spatrick         value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsrmask;
1832061da546Spatrick         return true;
1833061da546Spatrick 
1834061da546Spatrick       case fpu_stmm0:
1835061da546Spatrick         memcpy(&value->value.uint8,
1836061da546Spatrick                m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg, 10);
1837061da546Spatrick         return true;
1838061da546Spatrick       case fpu_stmm1:
1839061da546Spatrick         memcpy(&value->value.uint8,
1840061da546Spatrick                m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg, 10);
1841061da546Spatrick         return true;
1842061da546Spatrick       case fpu_stmm2:
1843061da546Spatrick         memcpy(&value->value.uint8,
1844061da546Spatrick                m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg, 10);
1845061da546Spatrick         return true;
1846061da546Spatrick       case fpu_stmm3:
1847061da546Spatrick         memcpy(&value->value.uint8,
1848061da546Spatrick                m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg, 10);
1849061da546Spatrick         return true;
1850061da546Spatrick       case fpu_stmm4:
1851061da546Spatrick         memcpy(&value->value.uint8,
1852061da546Spatrick                m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg, 10);
1853061da546Spatrick         return true;
1854061da546Spatrick       case fpu_stmm5:
1855061da546Spatrick         memcpy(&value->value.uint8,
1856061da546Spatrick                m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg, 10);
1857061da546Spatrick         return true;
1858061da546Spatrick       case fpu_stmm6:
1859061da546Spatrick         memcpy(&value->value.uint8,
1860061da546Spatrick                m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg, 10);
1861061da546Spatrick         return true;
1862061da546Spatrick       case fpu_stmm7:
1863061da546Spatrick         memcpy(&value->value.uint8,
1864061da546Spatrick                m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg, 10);
1865061da546Spatrick         return true;
1866061da546Spatrick 
1867061da546Spatrick       case fpu_xmm0:
1868061da546Spatrick         memcpy(&value->value.uint8,
1869061da546Spatrick                m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg, 16);
1870061da546Spatrick         return true;
1871061da546Spatrick       case fpu_xmm1:
1872061da546Spatrick         memcpy(&value->value.uint8,
1873061da546Spatrick                m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg, 16);
1874061da546Spatrick         return true;
1875061da546Spatrick       case fpu_xmm2:
1876061da546Spatrick         memcpy(&value->value.uint8,
1877061da546Spatrick                m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg, 16);
1878061da546Spatrick         return true;
1879061da546Spatrick       case fpu_xmm3:
1880061da546Spatrick         memcpy(&value->value.uint8,
1881061da546Spatrick                m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg, 16);
1882061da546Spatrick         return true;
1883061da546Spatrick       case fpu_xmm4:
1884061da546Spatrick         memcpy(&value->value.uint8,
1885061da546Spatrick                m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg, 16);
1886061da546Spatrick         return true;
1887061da546Spatrick       case fpu_xmm5:
1888061da546Spatrick         memcpy(&value->value.uint8,
1889061da546Spatrick                m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg, 16);
1890061da546Spatrick         return true;
1891061da546Spatrick       case fpu_xmm6:
1892061da546Spatrick         memcpy(&value->value.uint8,
1893061da546Spatrick                m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg, 16);
1894061da546Spatrick         return true;
1895061da546Spatrick       case fpu_xmm7:
1896061da546Spatrick         memcpy(&value->value.uint8,
1897061da546Spatrick                m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg, 16);
1898061da546Spatrick         return true;
1899061da546Spatrick 
1900061da546Spatrick #define MEMCPY_YMM(n)                                                          \
1901061da546Spatrick   memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm##n.__xmm_reg,  \
1902061da546Spatrick          16);                                                                  \
1903061da546Spatrick   memcpy((&value->value.uint8) + 16,                                           \
1904061da546Spatrick          m_state.context.fpu.avx.__fpu_ymmh##n.__xmm_reg, 16);
1905061da546Spatrick       case fpu_ymm0:
1906061da546Spatrick         MEMCPY_YMM(0);
1907061da546Spatrick         return true;
1908061da546Spatrick       case fpu_ymm1:
1909061da546Spatrick         MEMCPY_YMM(1);
1910061da546Spatrick         return true;
1911061da546Spatrick       case fpu_ymm2:
1912061da546Spatrick         MEMCPY_YMM(2);
1913061da546Spatrick         return true;
1914061da546Spatrick       case fpu_ymm3:
1915061da546Spatrick         MEMCPY_YMM(3);
1916061da546Spatrick         return true;
1917061da546Spatrick       case fpu_ymm4:
1918061da546Spatrick         MEMCPY_YMM(4);
1919061da546Spatrick         return true;
1920061da546Spatrick       case fpu_ymm5:
1921061da546Spatrick         MEMCPY_YMM(5);
1922061da546Spatrick         return true;
1923061da546Spatrick       case fpu_ymm6:
1924061da546Spatrick         MEMCPY_YMM(6);
1925061da546Spatrick         return true;
1926061da546Spatrick       case fpu_ymm7:
1927061da546Spatrick         MEMCPY_YMM(7);
1928061da546Spatrick         return true;
1929061da546Spatrick #undef MEMCPY_YMM
1930061da546Spatrick 
1931061da546Spatrick       case fpu_k0:
1932061da546Spatrick       case fpu_k1:
1933061da546Spatrick       case fpu_k2:
1934061da546Spatrick       case fpu_k3:
1935061da546Spatrick       case fpu_k4:
1936061da546Spatrick       case fpu_k5:
1937061da546Spatrick       case fpu_k6:
1938061da546Spatrick       case fpu_k7:
1939061da546Spatrick         memcpy((&value->value.uint8),
1940061da546Spatrick                &m_state.context.fpu.avx512f.__fpu_k0 + (reg - fpu_k0), 8);
1941061da546Spatrick         return true;
1942061da546Spatrick       case fpu_zmm0:
1943061da546Spatrick       case fpu_zmm1:
1944061da546Spatrick       case fpu_zmm2:
1945061da546Spatrick       case fpu_zmm3:
1946061da546Spatrick       case fpu_zmm4:
1947061da546Spatrick       case fpu_zmm5:
1948061da546Spatrick       case fpu_zmm6:
1949061da546Spatrick       case fpu_zmm7:
1950061da546Spatrick         memcpy(&value->value.uint8,
1951061da546Spatrick                &m_state.context.fpu.avx512f.__fpu_xmm0 + (reg - fpu_zmm0), 16);
1952061da546Spatrick         memcpy(&value->value.uint8 + 16,
1953061da546Spatrick                &m_state.context.fpu.avx512f.__fpu_ymmh0 + (reg - fpu_zmm0), 16);
1954061da546Spatrick         memcpy(&value->value.uint8 + 32,
1955061da546Spatrick                &m_state.context.fpu.avx512f.__fpu_zmmh0 + (reg - fpu_zmm0), 32);
1956061da546Spatrick         return true;
1957061da546Spatrick       }
1958061da546Spatrick       break;
1959061da546Spatrick 
1960061da546Spatrick     case e_regSetEXC:
1961061da546Spatrick       if (reg < k_num_exc_registers) {
1962061da546Spatrick         value->value.uint32 = (&m_state.context.exc.__trapno)[reg];
1963061da546Spatrick         return true;
1964061da546Spatrick       }
1965061da546Spatrick       break;
1966061da546Spatrick     }
1967061da546Spatrick   }
1968061da546Spatrick   return false;
1969061da546Spatrick }
1970061da546Spatrick 
SetRegisterValue(uint32_t set,uint32_t reg,const DNBRegisterValue * value)1971061da546Spatrick bool DNBArchImplI386::SetRegisterValue(uint32_t set, uint32_t reg,
1972061da546Spatrick                                        const DNBRegisterValue *value) {
1973061da546Spatrick   if (set == REGISTER_SET_GENERIC) {
1974061da546Spatrick     switch (reg) {
1975061da546Spatrick     case GENERIC_REGNUM_PC: // Program Counter
1976061da546Spatrick       set = e_regSetGPR;
1977061da546Spatrick       reg = gpr_eip;
1978061da546Spatrick       break;
1979061da546Spatrick 
1980061da546Spatrick     case GENERIC_REGNUM_SP: // Stack Pointer
1981061da546Spatrick       set = e_regSetGPR;
1982061da546Spatrick       reg = gpr_esp;
1983061da546Spatrick       break;
1984061da546Spatrick 
1985061da546Spatrick     case GENERIC_REGNUM_FP: // Frame Pointer
1986061da546Spatrick       set = e_regSetGPR;
1987061da546Spatrick       reg = gpr_ebp;
1988061da546Spatrick       break;
1989061da546Spatrick 
1990061da546Spatrick     case GENERIC_REGNUM_FLAGS: // Processor flags register
1991061da546Spatrick       set = e_regSetGPR;
1992061da546Spatrick       reg = gpr_eflags;
1993061da546Spatrick       break;
1994061da546Spatrick 
1995061da546Spatrick     case GENERIC_REGNUM_RA: // Return Address
1996061da546Spatrick     default:
1997061da546Spatrick       return false;
1998061da546Spatrick     }
1999061da546Spatrick   }
2000061da546Spatrick 
2001061da546Spatrick   if (GetRegisterState(set, false) != KERN_SUCCESS)
2002061da546Spatrick     return false;
2003061da546Spatrick 
2004061da546Spatrick   bool success = false;
2005061da546Spatrick   const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
2006061da546Spatrick   if (regInfo) {
2007061da546Spatrick     switch (set) {
2008061da546Spatrick     case e_regSetGPR:
2009061da546Spatrick       if (reg < k_num_gpr_registers) {
2010061da546Spatrick         ((uint32_t *)(&m_state.context.gpr))[reg] = value->value.uint32;
2011061da546Spatrick         success = true;
2012061da546Spatrick       }
2013061da546Spatrick       break;
2014061da546Spatrick 
2015061da546Spatrick     case e_regSetFPU:
2016061da546Spatrick       if (reg > fpu_xmm7 && !(CPUHasAVX() || FORCE_AVX_REGS))
2017061da546Spatrick         return false;
2018061da546Spatrick       if (reg > fpu_ymm7 && !(CPUHasAVX512f() || FORCE_AVX_REGS))
2019061da546Spatrick         return false;
2020061da546Spatrick       switch (reg) {
2021061da546Spatrick       case fpu_fcw:
2022061da546Spatrick         *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)) =
2023061da546Spatrick             value->value.uint16;
2024061da546Spatrick         success = true;
2025061da546Spatrick         break;
2026061da546Spatrick       case fpu_fsw:
2027061da546Spatrick         *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)) =
2028061da546Spatrick             value->value.uint16;
2029061da546Spatrick         success = true;
2030061da546Spatrick         break;
2031061da546Spatrick       case fpu_ftw:
2032061da546Spatrick         memcpy (&m_state.context.fpu.no_avx.__fpu_ftw, &value->value.uint16, 2);
2033061da546Spatrick         success = true;
2034061da546Spatrick         break;
2035061da546Spatrick       case fpu_fop:
2036061da546Spatrick         m_state.context.fpu.no_avx.__fpu_fop = value->value.uint16;
2037061da546Spatrick         success = true;
2038061da546Spatrick         break;
2039061da546Spatrick       case fpu_ip:
2040061da546Spatrick         m_state.context.fpu.no_avx.__fpu_ip = value->value.uint32;
2041061da546Spatrick         success = true;
2042061da546Spatrick         break;
2043061da546Spatrick       case fpu_cs:
2044061da546Spatrick         m_state.context.fpu.no_avx.__fpu_cs = value->value.uint16;
2045061da546Spatrick         success = true;
2046061da546Spatrick         break;
2047061da546Spatrick       case fpu_dp:
2048061da546Spatrick         m_state.context.fpu.no_avx.__fpu_dp = value->value.uint32;
2049061da546Spatrick         success = true;
2050061da546Spatrick         break;
2051061da546Spatrick       case fpu_ds:
2052061da546Spatrick         m_state.context.fpu.no_avx.__fpu_ds = value->value.uint16;
2053061da546Spatrick         success = true;
2054061da546Spatrick         break;
2055061da546Spatrick       case fpu_mxcsr:
2056061da546Spatrick         m_state.context.fpu.no_avx.__fpu_mxcsr = value->value.uint32;
2057061da546Spatrick         success = true;
2058061da546Spatrick         break;
2059061da546Spatrick       case fpu_mxcsrmask:
2060061da546Spatrick         m_state.context.fpu.no_avx.__fpu_mxcsrmask = value->value.uint32;
2061061da546Spatrick         success = true;
2062061da546Spatrick         break;
2063061da546Spatrick 
2064061da546Spatrick       case fpu_stmm0:
2065061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg,
2066061da546Spatrick                &value->value.uint8, 10);
2067061da546Spatrick         success = true;
2068061da546Spatrick         break;
2069061da546Spatrick       case fpu_stmm1:
2070061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg,
2071061da546Spatrick                &value->value.uint8, 10);
2072061da546Spatrick         success = true;
2073061da546Spatrick         break;
2074061da546Spatrick       case fpu_stmm2:
2075061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg,
2076061da546Spatrick                &value->value.uint8, 10);
2077061da546Spatrick         success = true;
2078061da546Spatrick         break;
2079061da546Spatrick       case fpu_stmm3:
2080061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg,
2081061da546Spatrick                &value->value.uint8, 10);
2082061da546Spatrick         success = true;
2083061da546Spatrick         break;
2084061da546Spatrick       case fpu_stmm4:
2085061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg,
2086061da546Spatrick                &value->value.uint8, 10);
2087061da546Spatrick         success = true;
2088061da546Spatrick         break;
2089061da546Spatrick       case fpu_stmm5:
2090061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg,
2091061da546Spatrick                &value->value.uint8, 10);
2092061da546Spatrick         success = true;
2093061da546Spatrick         break;
2094061da546Spatrick       case fpu_stmm6:
2095061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg,
2096061da546Spatrick                &value->value.uint8, 10);
2097061da546Spatrick         success = true;
2098061da546Spatrick         break;
2099061da546Spatrick       case fpu_stmm7:
2100061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg,
2101061da546Spatrick                &value->value.uint8, 10);
2102061da546Spatrick         success = true;
2103061da546Spatrick         break;
2104061da546Spatrick 
2105061da546Spatrick       case fpu_xmm0:
2106061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg,
2107061da546Spatrick                &value->value.uint8, 16);
2108061da546Spatrick         success = true;
2109061da546Spatrick         break;
2110061da546Spatrick       case fpu_xmm1:
2111061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg,
2112061da546Spatrick                &value->value.uint8, 16);
2113061da546Spatrick         success = true;
2114061da546Spatrick         break;
2115061da546Spatrick       case fpu_xmm2:
2116061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg,
2117061da546Spatrick                &value->value.uint8, 16);
2118061da546Spatrick         success = true;
2119061da546Spatrick         break;
2120061da546Spatrick       case fpu_xmm3:
2121061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg,
2122061da546Spatrick                &value->value.uint8, 16);
2123061da546Spatrick         success = true;
2124061da546Spatrick         break;
2125061da546Spatrick       case fpu_xmm4:
2126061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg,
2127061da546Spatrick                &value->value.uint8, 16);
2128061da546Spatrick         success = true;
2129061da546Spatrick         break;
2130061da546Spatrick       case fpu_xmm5:
2131061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg,
2132061da546Spatrick                &value->value.uint8, 16);
2133061da546Spatrick         success = true;
2134061da546Spatrick         break;
2135061da546Spatrick       case fpu_xmm6:
2136061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg,
2137061da546Spatrick                &value->value.uint8, 16);
2138061da546Spatrick         success = true;
2139061da546Spatrick         break;
2140061da546Spatrick       case fpu_xmm7:
2141061da546Spatrick         memcpy(m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg,
2142061da546Spatrick                &value->value.uint8, 16);
2143061da546Spatrick         success = true;
2144061da546Spatrick         break;
2145061da546Spatrick 
2146061da546Spatrick #define MEMCPY_YMM(n)                                                          \
2147061da546Spatrick   memcpy(m_state.context.fpu.avx.__fpu_xmm##n.__xmm_reg, &value->value.uint8,  \
2148061da546Spatrick          16);                                                                  \
2149061da546Spatrick   memcpy(m_state.context.fpu.avx.__fpu_ymmh##n.__xmm_reg,                      \
2150061da546Spatrick          (&value->value.uint8) + 16, 16);
2151061da546Spatrick       case fpu_ymm0:
2152061da546Spatrick         MEMCPY_YMM(0);
2153061da546Spatrick         return true;
2154061da546Spatrick       case fpu_ymm1:
2155061da546Spatrick         MEMCPY_YMM(1);
2156061da546Spatrick         return true;
2157061da546Spatrick       case fpu_ymm2:
2158061da546Spatrick         MEMCPY_YMM(2);
2159061da546Spatrick         return true;
2160061da546Spatrick       case fpu_ymm3:
2161061da546Spatrick         MEMCPY_YMM(3);
2162061da546Spatrick         return true;
2163061da546Spatrick       case fpu_ymm4:
2164061da546Spatrick         MEMCPY_YMM(4);
2165061da546Spatrick         return true;
2166061da546Spatrick       case fpu_ymm5:
2167061da546Spatrick         MEMCPY_YMM(5);
2168061da546Spatrick         return true;
2169061da546Spatrick       case fpu_ymm6:
2170061da546Spatrick         MEMCPY_YMM(6);
2171061da546Spatrick         return true;
2172061da546Spatrick       case fpu_ymm7:
2173061da546Spatrick         MEMCPY_YMM(7);
2174061da546Spatrick         return true;
2175061da546Spatrick #undef MEMCPY_YMM
2176061da546Spatrick 
2177061da546Spatrick       case fpu_k0:
2178061da546Spatrick       case fpu_k1:
2179061da546Spatrick       case fpu_k2:
2180061da546Spatrick       case fpu_k3:
2181061da546Spatrick       case fpu_k4:
2182061da546Spatrick       case fpu_k5:
2183061da546Spatrick       case fpu_k6:
2184061da546Spatrick       case fpu_k7:
2185061da546Spatrick         memcpy(&m_state.context.fpu.avx512f.__fpu_k0 + (reg - fpu_k0),
2186061da546Spatrick                &value->value.uint8, 8);
2187061da546Spatrick         return true;
2188061da546Spatrick       case fpu_zmm0:
2189061da546Spatrick       case fpu_zmm1:
2190061da546Spatrick       case fpu_zmm2:
2191061da546Spatrick       case fpu_zmm3:
2192061da546Spatrick       case fpu_zmm4:
2193061da546Spatrick       case fpu_zmm5:
2194061da546Spatrick       case fpu_zmm6:
2195061da546Spatrick       case fpu_zmm7:
2196061da546Spatrick         memcpy(&m_state.context.fpu.avx512f.__fpu_xmm0 + (reg - fpu_zmm0),
2197061da546Spatrick                &value->value.uint8, 16);
2198061da546Spatrick         memcpy(&m_state.context.fpu.avx512f.__fpu_ymmh0 + (reg - fpu_zmm0),
2199061da546Spatrick                &value->value.uint8 + 16, 16);
2200061da546Spatrick         memcpy(&m_state.context.fpu.avx512f.__fpu_zmmh0 + (reg - fpu_zmm0),
2201061da546Spatrick                &value->value.uint8 + 32, 32);
2202061da546Spatrick         return true;
2203061da546Spatrick       }
2204061da546Spatrick       break;
2205061da546Spatrick 
2206061da546Spatrick     case e_regSetEXC:
2207061da546Spatrick       if (reg < k_num_exc_registers) {
2208061da546Spatrick         (&m_state.context.exc.__trapno)[reg] = value->value.uint32;
2209061da546Spatrick         success = true;
2210061da546Spatrick       }
2211061da546Spatrick       break;
2212061da546Spatrick     }
2213061da546Spatrick   }
2214061da546Spatrick 
2215061da546Spatrick   if (success)
2216061da546Spatrick     return SetRegisterState(set) == KERN_SUCCESS;
2217061da546Spatrick   return false;
2218061da546Spatrick }
2219061da546Spatrick 
GetRegisterContextSize()2220061da546Spatrick uint32_t DNBArchImplI386::GetRegisterContextSize() {
2221061da546Spatrick   static uint32_t g_cached_size = 0;
2222061da546Spatrick   if (g_cached_size == 0) {
2223061da546Spatrick     if(CPUHasAVX512f() || FORCE_AVX_REGS) {
2224061da546Spatrick       for (size_t i = 0; i < k_num_fpu_registers_avx512f; ++i) {
2225061da546Spatrick         if (g_fpu_registers_avx512f[i].value_regs == NULL)
2226061da546Spatrick           g_cached_size += g_fpu_registers_avx512f[i].size;
2227061da546Spatrick       }
2228061da546Spatrick     } else
2229061da546Spatrick     if (CPUHasAVX()) {
2230061da546Spatrick       for (size_t i = 0; i < k_num_fpu_registers_avx; ++i) {
2231061da546Spatrick         if (g_fpu_registers_avx[i].value_regs == NULL)
2232061da546Spatrick           g_cached_size += g_fpu_registers_avx[i].size;
2233061da546Spatrick       }
2234061da546Spatrick     } else {
2235061da546Spatrick       for (size_t i = 0; i < k_num_fpu_registers_no_avx; ++i) {
2236061da546Spatrick         if (g_fpu_registers_no_avx[i].value_regs == NULL)
2237061da546Spatrick           g_cached_size += g_fpu_registers_no_avx[i].size;
2238061da546Spatrick       }
2239061da546Spatrick     }
2240061da546Spatrick     DNBLogThreaded("DNBArchImplX86_64::GetRegisterContextSize() - GPR = %zu, "
2241061da546Spatrick                    "FPU = %u, EXC = %zu",
2242061da546Spatrick                    sizeof(GPR), g_cached_size, sizeof(EXC));
2243061da546Spatrick     g_cached_size += sizeof(GPR);
2244061da546Spatrick     g_cached_size += sizeof(EXC);
2245061da546Spatrick     DNBLogThreaded(
2246061da546Spatrick         "DNBArchImplX86_64::GetRegisterContextSize() - GPR + FPU + EXC = %u",
2247061da546Spatrick         g_cached_size);
2248061da546Spatrick   }
2249061da546Spatrick   return g_cached_size;
2250061da546Spatrick }
2251061da546Spatrick 
GetRegisterContext(void * buf,nub_size_t buf_len)2252061da546Spatrick nub_size_t DNBArchImplI386::GetRegisterContext(void *buf, nub_size_t buf_len) {
2253061da546Spatrick   uint32_t size = GetRegisterContextSize();
2254061da546Spatrick 
2255061da546Spatrick   if (buf && buf_len) {
2256061da546Spatrick     if (size > buf_len)
2257061da546Spatrick       size = static_cast<uint32_t>(buf_len);
2258061da546Spatrick 
2259061da546Spatrick     bool force = false;
2260061da546Spatrick     kern_return_t kret;
2261061da546Spatrick     if ((kret = GetGPRState(force)) != KERN_SUCCESS) {
2262061da546Spatrick       DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = "
2263061da546Spatrick                                    "%p, len = %llu) error: GPR regs failed to "
2264061da546Spatrick                                    "read: %u ",
2265061da546Spatrick                        buf, (uint64_t)buf_len, kret);
2266061da546Spatrick       size = 0;
2267061da546Spatrick     } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) {
2268061da546Spatrick       DNBLogThreadedIf(
2269061da546Spatrick           LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = "
2270061da546Spatrick                       "%llu) error: %s regs failed to read: %u",
2271061da546Spatrick           buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret);
2272061da546Spatrick       size = 0;
2273061da546Spatrick     } else if ((kret = GetEXCState(force)) != KERN_SUCCESS) {
2274061da546Spatrick       DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = "
2275061da546Spatrick                                    "%p, len = %llu) error: EXC regs failed to "
2276061da546Spatrick                                    "read: %u",
2277061da546Spatrick                        buf, (uint64_t)buf_len, kret);
2278061da546Spatrick       size = 0;
2279061da546Spatrick     } else {
2280061da546Spatrick       uint8_t *p = (uint8_t *)buf;
2281061da546Spatrick       // Copy the GPR registers
2282061da546Spatrick       memcpy(p, &m_state.context.gpr, sizeof(GPR));
2283061da546Spatrick       p += sizeof(GPR);
2284061da546Spatrick 
2285061da546Spatrick       // Walk around the gaps in the FPU regs
2286061da546Spatrick       memcpy(p, &m_state.context.fpu.no_avx.__fpu_fcw, 5);
2287061da546Spatrick       p += 5;
2288061da546Spatrick       memcpy(p, &m_state.context.fpu.no_avx.__fpu_fop, 8);
2289061da546Spatrick       p += 8;
2290061da546Spatrick       memcpy(p, &m_state.context.fpu.no_avx.__fpu_dp, 6);
2291061da546Spatrick       p += 6;
2292061da546Spatrick       memcpy(p, &m_state.context.fpu.no_avx.__fpu_mxcsr, 8);
2293061da546Spatrick       p += 8;
2294061da546Spatrick 
2295061da546Spatrick       // Work around the padding between the stmm registers as they are 16
2296061da546Spatrick       // byte structs with 10 bytes of the value in each
2297061da546Spatrick       for (size_t i = 0; i < 8; ++i) {
2298061da546Spatrick         memcpy(p, &m_state.context.fpu.no_avx.__fpu_stmm0 + i, 10);
2299061da546Spatrick         p += 10;
2300061da546Spatrick       }
2301061da546Spatrick 
2302061da546Spatrick       if (CPUHasAVX512f() || FORCE_AVX_REGS) {
2303061da546Spatrick         for (size_t i = 0; i < 8; ++i) {
2304061da546Spatrick           memcpy(p, &m_state.context.fpu.avx512f.__fpu_k0 + i, 8);
2305061da546Spatrick           p += 8;
2306061da546Spatrick         }
2307061da546Spatrick       }
2308061da546Spatrick 
2309061da546Spatrick       if (CPUHasAVX() || FORCE_AVX_REGS) {
2310061da546Spatrick         // Interleave the XMM and YMMH registers to make the YMM registers
2311061da546Spatrick         for (size_t i = 0; i < 8; ++i) {
2312061da546Spatrick           memcpy(p, &m_state.context.fpu.avx.__fpu_xmm0 + i, 16);
2313061da546Spatrick           p += 16;
2314061da546Spatrick           memcpy(p, &m_state.context.fpu.avx.__fpu_ymmh0 + i, 16);
2315061da546Spatrick           p += 16;
2316061da546Spatrick         }
2317061da546Spatrick         if(CPUHasAVX512f() || FORCE_AVX_REGS) {
2318061da546Spatrick           for (size_t i = 0; i < 8; ++i) {
2319061da546Spatrick             memcpy(p, &m_state.context.fpu.avx512f.__fpu_zmmh0 + i, 32);
2320061da546Spatrick             p += 32;
2321061da546Spatrick           }
2322061da546Spatrick         }
2323061da546Spatrick       } else {
2324061da546Spatrick         // Copy the XMM registers in a single block
2325061da546Spatrick         memcpy(p, &m_state.context.fpu.no_avx.__fpu_xmm0, 8 * 16);
2326061da546Spatrick         p += 8 * 16;
2327061da546Spatrick       }
2328061da546Spatrick 
2329061da546Spatrick       // Copy the exception registers
2330061da546Spatrick       memcpy(p, &m_state.context.exc, sizeof(EXC));
2331061da546Spatrick       p += sizeof(EXC);
2332061da546Spatrick 
2333061da546Spatrick       // make sure we end up with exactly what we think we should have
2334061da546Spatrick       size_t bytes_written = p - (uint8_t *)buf;
2335061da546Spatrick       UNUSED_IF_ASSERT_DISABLED(bytes_written);
2336061da546Spatrick       assert(bytes_written == size);
2337061da546Spatrick     }
2338061da546Spatrick   }
2339061da546Spatrick   DNBLogThreadedIf(
2340061da546Spatrick       LOG_THREAD,
2341061da546Spatrick       "DNBArchImplI386::GetRegisterContext (buf = %p, len = %llu) => %llu", buf,
2342061da546Spatrick       (uint64_t)buf_len, (uint64_t)size);
2343061da546Spatrick   // Return the size of the register context even if NULL was passed in
2344061da546Spatrick   return size;
2345061da546Spatrick }
2346061da546Spatrick 
SetRegisterContext(const void * buf,nub_size_t buf_len)2347061da546Spatrick nub_size_t DNBArchImplI386::SetRegisterContext(const void *buf,
2348061da546Spatrick                                                nub_size_t buf_len) {
2349061da546Spatrick   nub_size_t size = sizeof(m_state.context);
2350061da546Spatrick   if (buf == NULL || buf_len == 0)
2351061da546Spatrick     size = 0;
2352061da546Spatrick 
2353061da546Spatrick   if (size) {
2354061da546Spatrick     if (size > buf_len)
2355061da546Spatrick       size = buf_len;
2356061da546Spatrick 
2357061da546Spatrick     const uint8_t *p = (const uint8_t *)buf;
2358061da546Spatrick     // Copy the GPR registers
2359061da546Spatrick     memcpy(&m_state.context.gpr, p, sizeof(GPR));
2360061da546Spatrick     p += sizeof(GPR);
2361061da546Spatrick 
2362061da546Spatrick     // Copy fcw through mxcsrmask as there is no padding
2363061da546Spatrick     memcpy(&m_state.context.fpu.no_avx.__fpu_fcw, p, 5);
2364061da546Spatrick     p += 5;
2365061da546Spatrick     memcpy(&m_state.context.fpu.no_avx.__fpu_fop, p, 8);
2366061da546Spatrick     p += 8;
2367061da546Spatrick     memcpy(&m_state.context.fpu.no_avx.__fpu_dp, p, 6);
2368061da546Spatrick     p += 6;
2369061da546Spatrick     memcpy(&m_state.context.fpu.no_avx.__fpu_mxcsr, p, 8);
2370061da546Spatrick     p += 8;
2371061da546Spatrick 
2372061da546Spatrick     // Work around the padding between the stmm registers as they are 16
2373061da546Spatrick     // byte structs with 10 bytes of the value in each
2374061da546Spatrick     for (size_t i = 0; i < 8; ++i) {
2375061da546Spatrick       memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + i, p, 10);
2376061da546Spatrick       p += 10;
2377061da546Spatrick     }
2378061da546Spatrick 
2379061da546Spatrick     if(CPUHasAVX512f() || FORCE_AVX_REGS) {
2380061da546Spatrick       for (size_t i = 0; i < 8; ++i) {
2381061da546Spatrick         memcpy(&m_state.context.fpu.avx512f.__fpu_k0 + i, p, 8);
2382061da546Spatrick         p += 8;
2383061da546Spatrick       }
2384061da546Spatrick     }
2385061da546Spatrick 
2386061da546Spatrick     if (CPUHasAVX() || FORCE_AVX_REGS) {
2387061da546Spatrick       // Interleave the XMM and YMMH registers to make the YMM registers
2388061da546Spatrick       for (size_t i = 0; i < 8; ++i) {
2389061da546Spatrick         memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + i, p, 16);
2390061da546Spatrick         p += 16;
2391061da546Spatrick         memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + i, p, 16);
2392061da546Spatrick         p += 16;
2393061da546Spatrick       }
2394061da546Spatrick 
2395061da546Spatrick       if(CPUHasAVX512f() || FORCE_AVX_REGS) {
2396061da546Spatrick         for (size_t i = 0; i < 8; ++i) {
2397061da546Spatrick           memcpy(&m_state.context.fpu.avx512f.__fpu_zmmh0 + i, p, 32);
2398061da546Spatrick           p += 32;
2399061da546Spatrick         }
2400061da546Spatrick       }
2401061da546Spatrick     } else {
2402061da546Spatrick       // Copy the XMM registers in a single block
2403061da546Spatrick       memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0, p, 8 * 16);
2404061da546Spatrick       p += 8 * 16;
2405061da546Spatrick     }
2406061da546Spatrick 
2407061da546Spatrick     // Copy the exception registers
2408061da546Spatrick     memcpy(&m_state.context.exc, p, sizeof(EXC));
2409061da546Spatrick     p += sizeof(EXC);
2410061da546Spatrick 
2411061da546Spatrick     // make sure we end up with exactly what we think we should have
2412061da546Spatrick     size_t bytes_written = p - (const uint8_t *)buf;
2413061da546Spatrick     UNUSED_IF_ASSERT_DISABLED(bytes_written);
2414061da546Spatrick     assert(bytes_written == size);
2415061da546Spatrick     kern_return_t kret;
2416061da546Spatrick     if ((kret = SetGPRState()) != KERN_SUCCESS)
2417061da546Spatrick       DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = "
2418061da546Spatrick                                    "%p, len = %llu) error: GPR regs failed to "
2419061da546Spatrick                                    "write: %u",
2420061da546Spatrick                        buf, (uint64_t)buf_len, kret);
2421061da546Spatrick     if ((kret = SetFPUState()) != KERN_SUCCESS)
2422061da546Spatrick       DNBLogThreadedIf(
2423061da546Spatrick           LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = "
2424061da546Spatrick                       "%llu) error: %s regs failed to write: %u",
2425061da546Spatrick           buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret);
2426061da546Spatrick     if ((kret = SetEXCState()) != KERN_SUCCESS)
2427061da546Spatrick       DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = "
2428061da546Spatrick                                    "%p, len = %llu) error: EXP regs failed to "
2429061da546Spatrick                                    "write: %u",
2430061da546Spatrick                        buf, (uint64_t)buf_len, kret);
2431061da546Spatrick   }
2432061da546Spatrick   DNBLogThreadedIf(
2433061da546Spatrick       LOG_THREAD,
2434061da546Spatrick       "DNBArchImplI386::SetRegisterContext (buf = %p, len = %llu) => %llu", buf,
2435061da546Spatrick       (uint64_t)buf_len, (uint64_t)size);
2436061da546Spatrick   return size;
2437061da546Spatrick }
2438061da546Spatrick 
SaveRegisterState()2439061da546Spatrick uint32_t DNBArchImplI386::SaveRegisterState() {
2440061da546Spatrick   kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber());
2441061da546Spatrick   DNBLogThreadedIf(
2442061da546Spatrick       LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u "
2443061da546Spatrick                   "(SetGPRState() for stop_count = %u)",
2444061da546Spatrick       m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount());
2445061da546Spatrick 
2446061da546Spatrick   bool force = true;
2447061da546Spatrick 
2448061da546Spatrick   if ((kret = GetGPRState(force)) != KERN_SUCCESS) {
2449061da546Spatrick     DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SaveRegisterState () error: "
2450061da546Spatrick                                  "GPR regs failed to read: %u ",
2451061da546Spatrick                      kret);
2452061da546Spatrick   } else if ((kret = GetFPUState(force)) != KERN_SUCCESS) {
2453061da546Spatrick     DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::SaveRegisterState () error: "
2454061da546Spatrick                                  "%s regs failed to read: %u",
2455061da546Spatrick                      CPUHasAVX() ? "AVX" : "FPU", kret);
2456061da546Spatrick   } else {
2457061da546Spatrick     const uint32_t save_id = GetNextRegisterStateSaveID();
2458061da546Spatrick     m_saved_register_states[save_id] = m_state.context;
2459061da546Spatrick     return save_id;
2460061da546Spatrick   }
2461061da546Spatrick   return 0;
2462061da546Spatrick }
RestoreRegisterState(uint32_t save_id)2463061da546Spatrick bool DNBArchImplI386::RestoreRegisterState(uint32_t save_id) {
2464061da546Spatrick   SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id);
2465061da546Spatrick   if (pos != m_saved_register_states.end()) {
2466061da546Spatrick     m_state.context.gpr = pos->second.gpr;
2467061da546Spatrick     m_state.context.fpu = pos->second.fpu;
2468061da546Spatrick     m_state.context.exc = pos->second.exc;
2469061da546Spatrick     m_state.SetError(e_regSetGPR, Read, 0);
2470061da546Spatrick     m_state.SetError(e_regSetFPU, Read, 0);
2471061da546Spatrick     m_state.SetError(e_regSetEXC, Read, 0);
2472061da546Spatrick     kern_return_t kret;
2473061da546Spatrick     bool success = true;
2474061da546Spatrick     if ((kret = SetGPRState()) != KERN_SUCCESS) {
2475061da546Spatrick       DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::RestoreRegisterState "
2476061da546Spatrick                                    "(save_id = %u) error: GPR regs failed to "
2477061da546Spatrick                                    "write: %u",
2478061da546Spatrick                        save_id, kret);
2479061da546Spatrick       success = false;
2480061da546Spatrick     } else if ((kret = SetFPUState()) != KERN_SUCCESS) {
2481061da546Spatrick       DNBLogThreadedIf(LOG_THREAD, "DNBArchImplI386::RestoreRegisterState "
2482061da546Spatrick                                    "(save_id = %u) error: %s regs failed to "
2483061da546Spatrick                                    "write: %u",
2484061da546Spatrick                        save_id, CPUHasAVX() ? "AVX" : "FPU", kret);
2485061da546Spatrick       success = false;
2486061da546Spatrick     }
2487061da546Spatrick     m_saved_register_states.erase(pos);
2488061da546Spatrick     return success;
2489061da546Spatrick   }
2490061da546Spatrick   return false;
2491061da546Spatrick }
2492061da546Spatrick 
GetRegisterState(int set,bool force)2493061da546Spatrick kern_return_t DNBArchImplI386::GetRegisterState(int set, bool force) {
2494061da546Spatrick   switch (set) {
2495061da546Spatrick   case e_regSetALL:
2496061da546Spatrick     return GetGPRState(force) | GetFPUState(force) | GetEXCState(force);
2497061da546Spatrick   case e_regSetGPR:
2498061da546Spatrick     return GetGPRState(force);
2499061da546Spatrick   case e_regSetFPU:
2500061da546Spatrick     return GetFPUState(force);
2501061da546Spatrick   case e_regSetEXC:
2502061da546Spatrick     return GetEXCState(force);
2503061da546Spatrick   default:
2504061da546Spatrick     break;
2505061da546Spatrick   }
2506061da546Spatrick   return KERN_INVALID_ARGUMENT;
2507061da546Spatrick }
2508061da546Spatrick 
SetRegisterState(int set)2509061da546Spatrick kern_return_t DNBArchImplI386::SetRegisterState(int set) {
2510061da546Spatrick   // Make sure we have a valid context to set.
2511061da546Spatrick   if (RegisterSetStateIsValid(set)) {
2512061da546Spatrick     switch (set) {
2513061da546Spatrick     case e_regSetALL:
2514061da546Spatrick       return SetGPRState() | SetFPUState() | SetEXCState();
2515061da546Spatrick     case e_regSetGPR:
2516061da546Spatrick       return SetGPRState();
2517061da546Spatrick     case e_regSetFPU:
2518061da546Spatrick       return SetFPUState();
2519061da546Spatrick     case e_regSetEXC:
2520061da546Spatrick       return SetEXCState();
2521061da546Spatrick     default:
2522061da546Spatrick       break;
2523061da546Spatrick     }
2524061da546Spatrick   }
2525061da546Spatrick   return KERN_INVALID_ARGUMENT;
2526061da546Spatrick }
2527061da546Spatrick 
RegisterSetStateIsValid(int set) const2528061da546Spatrick bool DNBArchImplI386::RegisterSetStateIsValid(int set) const {
2529061da546Spatrick   return m_state.RegsAreValid(set);
2530061da546Spatrick }
2531061da546Spatrick 
2532061da546Spatrick #endif // #if defined (__i386__)
2533