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