]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - tools/debugserver/source/MacOSX/i386/DNBArchImplI386.cpp
Vendor import of lldb trunk r256945:
[FreeBSD/FreeBSD.git] / tools / debugserver / source / MacOSX / i386 / DNBArchImplI386.cpp
1 //===-- DNBArchImplI386.cpp -------------------------------------*- C++ -*-===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9 //
10 //  Created by Greg Clayton on 6/25/07.
11 //
12 //===----------------------------------------------------------------------===//
13
14 #if defined (__i386__) || defined (__x86_64__)
15
16 #include <sys/cdefs.h>
17
18 #include "MacOSX/i386/DNBArchImplI386.h"
19 #include "DNBLog.h"
20 #include "MachThread.h"
21 #include "MachProcess.h"
22
23 extern "C" bool CPUHasAVX(); // Defined over in DNBArchImplX86_64.cpp
24
25 #if defined (LLDB_DEBUGSERVER_RELEASE) || defined (LLDB_DEBUGSERVER_DEBUG)
26 enum debugState {
27     debugStateUnknown,
28     debugStateOff,
29     debugStateOn
30 };
31
32 static debugState sFPUDebugState = debugStateUnknown;
33 static debugState sAVXForceState = debugStateUnknown;
34
35 static bool DebugFPURegs ()
36 {
37     if (sFPUDebugState == debugStateUnknown)
38     {
39         if (getenv("DNB_DEBUG_FPU_REGS"))
40             sFPUDebugState = debugStateOn;
41         else
42             sFPUDebugState = debugStateOff;
43     }
44     
45     return (sFPUDebugState == debugStateOn);
46 }
47
48 static bool ForceAVXRegs ()
49 {
50     if (sFPUDebugState == debugStateUnknown)
51     {
52         if (getenv("DNB_DEBUG_X86_FORCE_AVX_REGS"))
53             sAVXForceState = debugStateOn;
54         else
55             sAVXForceState = debugStateOff;
56     }
57     
58     return (sAVXForceState == debugStateOn);
59 }
60
61 #define DEBUG_FPU_REGS (DebugFPURegs())
62 #define FORCE_AVX_REGS (ForceAVXRegs())
63 #else
64 #define DEBUG_FPU_REGS (0)
65 #define FORCE_AVX_REGS (0)
66 #endif
67
68 enum
69 {
70     gpr_eax         = 0,
71     gpr_ebx         = 1,
72     gpr_ecx         = 2,
73     gpr_edx         = 3,
74     gpr_edi         = 4,
75     gpr_esi         = 5,
76     gpr_ebp         = 6,
77     gpr_esp         = 7,
78     gpr_ss          = 8,
79     gpr_eflags      = 9,
80     gpr_eip         = 10,
81     gpr_cs          = 11,
82     gpr_ds          = 12,
83     gpr_es          = 13,
84     gpr_fs          = 14,
85     gpr_gs          = 15,
86     gpr_ax ,
87     gpr_bx ,
88     gpr_cx ,
89     gpr_dx ,
90     gpr_di ,
91     gpr_si ,
92     gpr_bp ,
93     gpr_sp ,
94     gpr_ah ,
95     gpr_bh ,
96     gpr_ch ,
97     gpr_dh ,
98     gpr_al ,
99     gpr_bl ,
100     gpr_cl ,
101     gpr_dl ,
102     gpr_dil,
103     gpr_sil,
104     gpr_bpl,
105     gpr_spl,
106     k_num_gpr_regs
107 };
108
109 enum {
110     fpu_fcw,
111     fpu_fsw,
112     fpu_ftw,
113     fpu_fop,
114     fpu_ip,
115     fpu_cs,
116     fpu_dp,
117     fpu_ds,
118     fpu_mxcsr,
119     fpu_mxcsrmask,
120     fpu_stmm0,
121     fpu_stmm1,
122     fpu_stmm2,
123     fpu_stmm3,
124     fpu_stmm4,
125     fpu_stmm5,
126     fpu_stmm6,
127     fpu_stmm7,
128     fpu_xmm0,
129     fpu_xmm1,
130     fpu_xmm2,
131     fpu_xmm3,
132     fpu_xmm4,
133     fpu_xmm5,
134     fpu_xmm6,
135     fpu_xmm7,
136     fpu_ymm0,
137     fpu_ymm1,
138     fpu_ymm2,
139     fpu_ymm3,
140     fpu_ymm4,
141     fpu_ymm5,
142     fpu_ymm6,
143     fpu_ymm7,
144     k_num_fpu_regs,
145
146     // Aliases
147     fpu_fctrl = fpu_fcw,
148     fpu_fstat = fpu_fsw,
149     fpu_ftag  = fpu_ftw,
150     fpu_fiseg = fpu_cs,
151     fpu_fioff = fpu_ip,
152     fpu_foseg = fpu_ds,
153     fpu_fooff = fpu_dp
154 };
155
156 enum {
157     exc_trapno,
158     exc_err,
159     exc_faultvaddr,
160     k_num_exc_regs,
161 };
162
163
164 enum
165 {
166     ehframe_eax = 0,
167     ehframe_ecx,
168     ehframe_edx,
169     ehframe_ebx,
170
171     // On i386 Darwin the eh_frame register numbers for ebp and esp are reversed from DWARF.
172     // It's due to an ancient compiler bug in the output of the eh_frame.
173     // Specifically, on i386 darwin eh_frame, 4 is ebp, 5 is esp.
174     // On i386 darwin debug_frame (and debug_info), 4 is esp, 5 is ebp.
175     ehframe_ebp,   
176     ehframe_esp,
177     ehframe_esi,
178     ehframe_edi,
179     ehframe_eip,
180     ehframe_eflags
181 };
182
183 enum
184 {
185     dwarf_eax = 0,
186     dwarf_ecx,
187     dwarf_edx,
188     dwarf_ebx,
189     dwarf_esp,
190     dwarf_ebp,
191     dwarf_esi,
192     dwarf_edi,
193     dwarf_eip,
194     dwarf_eflags,
195     dwarf_stmm0 = 11,
196     dwarf_stmm1,
197     dwarf_stmm2,
198     dwarf_stmm3,
199     dwarf_stmm4,
200     dwarf_stmm5,
201     dwarf_stmm6,
202     dwarf_stmm7,
203     dwarf_xmm0 = 21,
204     dwarf_xmm1,
205     dwarf_xmm2,
206     dwarf_xmm3,
207     dwarf_xmm4,
208     dwarf_xmm5,
209     dwarf_xmm6,
210     dwarf_xmm7,
211     dwarf_ymm0 = dwarf_xmm0,
212     dwarf_ymm1 = dwarf_xmm1,
213     dwarf_ymm2 = dwarf_xmm2,
214     dwarf_ymm3 = dwarf_xmm3,
215     dwarf_ymm4 = dwarf_xmm4,
216     dwarf_ymm5 = dwarf_xmm5,
217     dwarf_ymm6 = dwarf_xmm6,
218     dwarf_ymm7 = dwarf_xmm7,
219 };
220
221 enum
222 {
223     debugserver_eax        =  0,
224     debugserver_ecx        =  1,
225     debugserver_edx        =  2,
226     debugserver_ebx        =  3,
227     debugserver_esp        =  4,
228     debugserver_ebp        =  5,
229     debugserver_esi        =  6,
230     debugserver_edi        =  7,
231     debugserver_eip        =  8,
232     debugserver_eflags     =  9,
233     debugserver_cs         = 10,
234     debugserver_ss         = 11,
235     debugserver_ds         = 12,
236     debugserver_es         = 13,
237     debugserver_fs         = 14,
238     debugserver_gs         = 15,
239     debugserver_stmm0      = 16,
240     debugserver_stmm1      = 17,
241     debugserver_stmm2      = 18,
242     debugserver_stmm3      = 19,
243     debugserver_stmm4      = 20,
244     debugserver_stmm5      = 21,
245     debugserver_stmm6      = 22,
246     debugserver_stmm7      = 23,
247     debugserver_fctrl      = 24,    debugserver_fcw     = debugserver_fctrl,
248     debugserver_fstat      = 25,    debugserver_fsw     = debugserver_fstat,
249     debugserver_ftag       = 26,    debugserver_ftw     = debugserver_ftag,
250     debugserver_fiseg      = 27,    debugserver_fpu_cs  = debugserver_fiseg,
251     debugserver_fioff      = 28,    debugserver_ip      = debugserver_fioff,
252     debugserver_foseg      = 29,    debugserver_fpu_ds  = debugserver_foseg,
253     debugserver_fooff      = 30,    debugserver_dp      = debugserver_fooff,
254     debugserver_fop        = 31,
255     debugserver_xmm0       = 32,
256     debugserver_xmm1       = 33,
257     debugserver_xmm2       = 34,
258     debugserver_xmm3       = 35,
259     debugserver_xmm4       = 36,
260     debugserver_xmm5       = 37,
261     debugserver_xmm6       = 38,
262     debugserver_xmm7       = 39,
263     debugserver_mxcsr      = 40,
264     debugserver_mm0        = 41,
265     debugserver_mm1        = 42,
266     debugserver_mm2        = 43,
267     debugserver_mm3        = 44,
268     debugserver_mm4        = 45,
269     debugserver_mm5        = 46,
270     debugserver_mm6        = 47,
271     debugserver_mm7        = 48,
272     debugserver_ymm0       = debugserver_xmm0,
273     debugserver_ymm1       = debugserver_xmm1,
274     debugserver_ymm2       = debugserver_xmm2,
275     debugserver_ymm3       = debugserver_xmm3,
276     debugserver_ymm4       = debugserver_xmm4,
277     debugserver_ymm5       = debugserver_xmm5,
278     debugserver_ymm6       = debugserver_xmm6,
279     debugserver_ymm7       = debugserver_xmm7
280 };
281
282 uint64_t
283 DNBArchImplI386::GetPC(uint64_t failValue)
284 {
285     // Get program counter
286     if (GetGPRState(false) == KERN_SUCCESS)
287         return m_state.context.gpr.__eip;
288     return failValue;
289 }
290
291 kern_return_t
292 DNBArchImplI386::SetPC(uint64_t value)
293 {
294     // Get program counter
295     kern_return_t err = GetGPRState(false);
296     if (err == KERN_SUCCESS)
297     {
298         m_state.context.gpr.__eip = static_cast<uint32_t>(value);
299         err = SetGPRState();
300     }
301     return err == KERN_SUCCESS;
302 }
303
304 uint64_t
305 DNBArchImplI386::GetSP(uint64_t failValue)
306 {
307     // Get stack pointer
308     if (GetGPRState(false) == KERN_SUCCESS)
309         return m_state.context.gpr.__esp;
310     return failValue;
311 }
312
313 // Uncomment the value below to verify the values in the debugger.
314 //#define DEBUG_GPR_VALUES 1    // DO NOT CHECK IN WITH THIS DEFINE ENABLED
315 //#define SET_GPR(reg) m_state.context.gpr.__##reg = gpr_##reg
316
317 kern_return_t
318 DNBArchImplI386::GetGPRState(bool force)
319 {
320     if (force || m_state.GetError(e_regSetGPR, Read))
321     {
322 #if DEBUG_GPR_VALUES
323         SET_GPR(eax);
324         SET_GPR(ebx);
325         SET_GPR(ecx);
326         SET_GPR(edx);
327         SET_GPR(edi);
328         SET_GPR(esi);
329         SET_GPR(ebp);
330         SET_GPR(esp);
331         SET_GPR(ss);
332         SET_GPR(eflags);
333         SET_GPR(eip);
334         SET_GPR(cs);
335         SET_GPR(ds);
336         SET_GPR(es);
337         SET_GPR(fs);
338         SET_GPR(gs);
339         m_state.SetError(e_regSetGPR, Read, 0);
340 #else
341         mach_msg_type_number_t count = e_regSetWordSizeGPR;
342         m_state.SetError(e_regSetGPR, Read, ::thread_get_state(m_thread->MachPortNumber(), __i386_THREAD_STATE, (thread_state_t)&m_state.context.gpr, &count));
343 #endif
344     }
345     return m_state.GetError(e_regSetGPR, Read);
346 }
347
348 // Uncomment the value below to verify the values in the debugger.
349 //#define DEBUG_FPU_VALUES 1    // DO NOT CHECK IN WITH THIS DEFINE ENABLED
350
351 kern_return_t
352 DNBArchImplI386::GetFPUState(bool force)
353 {
354     if (force || m_state.GetError(e_regSetFPU, Read))
355     {
356         if (DEBUG_FPU_REGS)
357         {
358             if (CPUHasAVX() || FORCE_AVX_REGS)
359             {
360                 m_state.context.fpu.avx.__fpu_reserved[0] = -1;
361                 m_state.context.fpu.avx.__fpu_reserved[1] = -1;
362                 *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fcw) = 0x1234;
363                 *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fsw) = 0x5678;
364                 m_state.context.fpu.avx.__fpu_ftw = 1;
365                 m_state.context.fpu.avx.__fpu_rsrv1 = UINT8_MAX;
366                 m_state.context.fpu.avx.__fpu_fop = 2;
367                 m_state.context.fpu.avx.__fpu_ip = 3;
368                 m_state.context.fpu.avx.__fpu_cs = 4;
369                 m_state.context.fpu.avx.__fpu_rsrv2 = 5;
370                 m_state.context.fpu.avx.__fpu_dp = 6;
371                 m_state.context.fpu.avx.__fpu_ds = 7;
372                 m_state.context.fpu.avx.__fpu_rsrv3 = UINT16_MAX;
373                 m_state.context.fpu.avx.__fpu_mxcsr = 8;
374                 m_state.context.fpu.avx.__fpu_mxcsrmask = 9;
375                 int i;
376                 for (i=0; i<16; ++i)
377                 {
378                     if (i<10)
379                     {
380                         m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = 'a';
381                         m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = 'b';
382                         m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = 'c';
383                         m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = 'd';
384                         m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = 'e';
385                         m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = 'f';
386                         m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = 'g';
387                         m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = 'h';
388                     }
389                     else
390                     {
391                         m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN;
392                         m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN;
393                         m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN;
394                         m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN;
395                         m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN;
396                         m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN;
397                         m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN;
398                         m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN;
399                     }
400                     
401                     m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg[i] = '0';
402                     m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg[i] = '1';
403                     m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg[i] = '2';
404                     m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg[i] = '3';
405                     m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg[i] = '4';
406                     m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg[i] = '5';
407                     m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg[i] = '6';
408                     m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg[i] = '7';
409                 }
410                 for (i=0; i<sizeof(m_state.context.fpu.avx.__fpu_rsrv4); ++i)
411                     m_state.context.fpu.avx.__fpu_rsrv4[i] = INT8_MIN;
412                 m_state.context.fpu.avx.__fpu_reserved1 = -1;
413                 for (i=0; i<sizeof(m_state.context.fpu.avx.__avx_reserved1); ++i)
414                     m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN;
415                 
416                 for (i = 0; i < 16; ++i)
417                 {
418                     m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0';
419                     m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1';
420                     m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2';
421                     m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3';
422                     m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4';
423                     m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5';
424                     m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6';
425                     m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7';
426                 }
427             }
428             else
429             {
430                 m_state.context.fpu.no_avx.__fpu_reserved[0] = -1;
431                 m_state.context.fpu.no_avx.__fpu_reserved[1] = -1;
432                 *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fcw) = 0x1234;
433                 *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fsw) = 0x5678;
434                 m_state.context.fpu.no_avx.__fpu_ftw = 1;
435                 m_state.context.fpu.no_avx.__fpu_rsrv1 = UINT8_MAX;
436                 m_state.context.fpu.no_avx.__fpu_fop = 2;
437                 m_state.context.fpu.no_avx.__fpu_ip = 3;
438                 m_state.context.fpu.no_avx.__fpu_cs = 4;
439                 m_state.context.fpu.no_avx.__fpu_rsrv2 = 5;
440                 m_state.context.fpu.no_avx.__fpu_dp = 6;
441                 m_state.context.fpu.no_avx.__fpu_ds = 7;
442                 m_state.context.fpu.no_avx.__fpu_rsrv3 = UINT16_MAX;
443                 m_state.context.fpu.no_avx.__fpu_mxcsr = 8;
444                 m_state.context.fpu.no_avx.__fpu_mxcsrmask = 9;
445                 int i;
446                 for (i=0; i<16; ++i)
447                 {
448                     if (i<10)
449                     {
450                         m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = 'a';
451                         m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = 'b';
452                         m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = 'c';
453                         m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = 'd';
454                         m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = 'e';
455                         m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = 'f';
456                         m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = 'g';
457                         m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = 'h';
458                     }
459                     else
460                     {
461                         m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN;
462                         m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN;
463                         m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN;
464                         m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN;
465                         m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN;
466                         m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN;
467                         m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN;
468                         m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN;
469                     }
470
471                     m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg[i] = '0';
472                     m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg[i] = '1';
473                     m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg[i] = '2';
474                     m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg[i] = '3';
475                     m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg[i] = '4';
476                     m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg[i] = '5';
477                     m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg[i] = '6';
478                     m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg[i] = '7';
479                 }
480                 for (i=0; i<sizeof(m_state.context.fpu.avx.__fpu_rsrv4); ++i)
481                     m_state.context.fpu.no_avx.__fpu_rsrv4[i] = INT8_MIN;
482                 m_state.context.fpu.no_avx.__fpu_reserved1 = -1;
483             }
484             m_state.SetError(e_regSetFPU, Read, 0);
485         }
486         else
487         {
488             if (CPUHasAVX() || FORCE_AVX_REGS)
489             {
490                 mach_msg_type_number_t count = e_regSetWordSizeAVX;
491                 m_state.SetError (e_regSetFPU, Read, ::thread_get_state(m_thread->MachPortNumber(), __i386_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, &count));
492                 DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &avx, %u (%u passed in)) => 0x%8.8x",
493                                   m_thread->MachPortNumber(), __i386_AVX_STATE, count, e_regSetWordSizeAVX,
494                                   m_state.GetError(e_regSetFPU, Read));
495             }
496             else
497             {    
498                 mach_msg_type_number_t count = e_regSetWordSizeFPU;
499                 m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->MachPortNumber(), __i386_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, &count));
500                 DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &fpu, %u (%u passed in) => 0x%8.8x",
501                                   m_thread->MachPortNumber(), __i386_FLOAT_STATE, count, e_regSetWordSizeFPU,
502                                   m_state.GetError(e_regSetFPU, Read));
503             }
504         }
505     }
506     return m_state.GetError(e_regSetFPU, Read);
507 }
508
509 kern_return_t
510 DNBArchImplI386::GetEXCState(bool force)
511 {
512     if (force || m_state.GetError(e_regSetEXC, Read))
513     {
514         mach_msg_type_number_t count = e_regSetWordSizeEXC;
515         m_state.SetError(e_regSetEXC, Read, ::thread_get_state(m_thread->MachPortNumber(), __i386_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, &count));
516     }
517     return m_state.GetError(e_regSetEXC, Read);
518 }
519
520 kern_return_t
521 DNBArchImplI386::SetGPRState()
522 {
523     kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber());
524     DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount());
525     
526
527     m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->MachPortNumber(), __i386_THREAD_STATE, (thread_state_t)&m_state.context.gpr, e_regSetWordSizeGPR));
528     return m_state.GetError(e_regSetGPR, Write);
529 }
530
531 kern_return_t
532 DNBArchImplI386::SetFPUState()
533 {
534     if (DEBUG_FPU_REGS)
535     {
536         m_state.SetError(e_regSetFPU, Write, 0);
537         return m_state.GetError(e_regSetFPU, Write);   
538     }
539     else
540     {
541         if (CPUHasAVX() || FORCE_AVX_REGS)
542             m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->MachPortNumber(), __i386_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, e_regSetWordSizeAVX));
543         else
544             m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->MachPortNumber(), __i386_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, e_regSetWordSizeFPU));
545         return m_state.GetError(e_regSetFPU, Write);
546     }
547 }
548
549 kern_return_t
550 DNBArchImplI386::SetEXCState()
551 {
552     m_state.SetError(e_regSetEXC, Write, ::thread_set_state(m_thread->MachPortNumber(), __i386_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, e_regSetWordSizeEXC));
553     return m_state.GetError(e_regSetEXC, Write);
554 }
555
556 kern_return_t
557 DNBArchImplI386::GetDBGState(bool force)
558 {
559     if (force || m_state.GetError(e_regSetDBG, Read))
560     {
561         mach_msg_type_number_t count = e_regSetWordSizeDBG;
562         m_state.SetError(e_regSetDBG, Read, ::thread_get_state(m_thread->MachPortNumber(), __i386_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, &count));
563     }
564     return m_state.GetError(e_regSetDBG, Read);
565 }
566
567 kern_return_t
568 DNBArchImplI386::SetDBGState(bool also_set_on_task)
569 {
570     m_state.SetError(e_regSetDBG, Write, ::thread_set_state(m_thread->MachPortNumber(), __i386_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG));
571     if (also_set_on_task)
572     {
573         kern_return_t kret = ::task_set_state(m_thread->Process()->Task().TaskPort(), __i386_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG);
574         if (kret != KERN_SUCCESS)
575             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::SetDBGState failed to set debug control register state: 0x%8.8x.", kret);
576
577     }
578     return m_state.GetError(e_regSetDBG, Write);
579 }
580
581 void
582 DNBArchImplI386::ThreadWillResume()
583 {
584     // Do we need to step this thread? If so, let the mach thread tell us so.
585     if (m_thread->IsStepping())
586     {
587         // This is the primary thread, let the arch do anything it needs
588         EnableHardwareSingleStep(true);
589     }
590
591     // Reset the debug status register, if necessary, before we resume.
592     kern_return_t kret = GetDBGState(false);
593     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::ThreadWillResume() GetDBGState() => 0x%8.8x.", kret);
594     if (kret != KERN_SUCCESS)
595         return;
596
597     DBG &debug_state = m_state.context.dbg;
598     bool need_reset = false;
599     uint32_t i, num = NumSupportedHardwareWatchpoints();
600     for (i = 0; i < num; ++i)
601         if (IsWatchpointHit(debug_state, i))
602             need_reset = true;
603
604     if (need_reset)
605     {
606         ClearWatchpointHits(debug_state);
607         kret = SetDBGState(false);
608         DNBLogThreadedIf(LOG_WATCHPOINTS,"DNBArchImplI386::ThreadWillResume() SetDBGState() => 0x%8.8x.", kret);
609     }
610 }
611
612 bool
613 DNBArchImplI386::ThreadDidStop()
614 {
615     bool success = true;
616
617     m_state.InvalidateAllRegisterStates();
618
619     // Are we stepping a single instruction?
620     if (GetGPRState(true) == KERN_SUCCESS)
621     {
622         // We are single stepping, was this the primary thread?
623         if (m_thread->IsStepping())
624         {
625             // This was the primary thread, we need to clear the trace
626             // bit if so.
627             success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
628         }
629         else
630         {
631             // The MachThread will automatically restore the suspend count
632             // in ThreadDidStop(), so we don't need to do anything here if
633             // we weren't the primary thread the last time
634         }
635     }
636     return success;
637 }
638
639 bool
640 DNBArchImplI386::NotifyException(MachException::Data& exc)
641 {
642     switch (exc.exc_type)
643     {
644     case EXC_BAD_ACCESS:
645         break;
646     case EXC_BAD_INSTRUCTION:
647         break;
648     case EXC_ARITHMETIC:
649         break;
650     case EXC_EMULATION:
651         break;
652     case EXC_SOFTWARE:
653         break;
654     case EXC_BREAKPOINT:
655         if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2)
656         {
657             // exc_code = EXC_I386_BPT
658             //
659             nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS);
660             if (pc != INVALID_NUB_ADDRESS && pc > 0)
661             {
662                 pc -= 1;
663                 // Check for a breakpoint at one byte prior to the current PC value
664                 // since the PC will be just past the trap.
665
666                 DNBBreakpoint *bp = m_thread->Process()->Breakpoints().FindByAddress(pc);
667                 if (bp)
668                 {
669                     // Backup the PC for i386 since the trap was taken and the PC
670                     // is at the address following the single byte trap instruction.
671                     if (m_state.context.gpr.__eip > 0)
672                     {
673                         m_state.context.gpr.__eip = static_cast<uint32_t>(pc);
674                         // Write the new PC back out
675                         SetGPRState ();
676                     }
677                 }
678                 return true;
679             }
680         }
681         else if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 1)
682         {
683             // exc_code = EXC_I386_SGL
684             //
685             // Check whether this corresponds to a watchpoint hit event.
686             // If yes, set the exc_sub_code to the data break address.
687             nub_addr_t addr = 0;
688             uint32_t hw_index = GetHardwareWatchpointHit(addr);
689             if (hw_index != INVALID_NUB_HW_INDEX)
690             {
691                 exc.exc_data[1] = addr;
692                 // Piggyback the hw_index in the exc.data.
693                 exc.exc_data.push_back(hw_index);
694             }
695
696             return true;
697         }
698         break;
699     case EXC_SYSCALL:
700         break;
701     case EXC_MACH_SYSCALL:
702         break;
703     case EXC_RPC_ALERT:
704         break;
705     }
706     return false;
707 }
708
709 uint32_t
710 DNBArchImplI386::NumSupportedHardwareWatchpoints()
711 {
712     // Available debug address registers: dr0, dr1, dr2, dr3.
713     return 4;
714 }
715
716 static uint32_t
717 size_and_rw_bits(nub_size_t size, bool read, bool write)
718 {
719     uint32_t rw;
720     if (read) {
721         rw = 0x3; // READ or READ/WRITE
722     } else if (write) {
723         rw = 0x1; // WRITE
724     } else {
725         assert(0 && "read and write cannot both be false");
726     }
727
728     switch (size) {
729     case 1:
730         return rw;
731     case 2:
732         return (0x1 << 2) | rw;
733     case 4:
734         return (0x3 << 2) | rw;
735     case 8:
736         return (0x2 << 2) | rw;
737     }    
738     assert(0 && "invalid size, must be one of 1, 2, 4, or 8");
739     return 0;
740 }
741
742 void
743 DNBArchImplI386::SetWatchpoint(DBG &debug_state, uint32_t hw_index, nub_addr_t addr, nub_size_t size, bool read, bool write)
744 {
745     // Set both dr7 (debug control register) and dri (debug address register).
746     
747     // dr7{7-0} encodes the local/gloabl enable bits:
748     //  global enable --. .-- local enable
749     //                  | |
750     //                  v v
751     //      dr0 -> bits{1-0}
752     //      dr1 -> bits{3-2}
753     //      dr2 -> bits{5-4}
754     //      dr3 -> bits{7-6}
755     //
756     // dr7{31-16} encodes the rw/len bits:
757     //  b_x+3, b_x+2, b_x+1, b_x
758     //      where bits{x+1, x} => rw
759     //            0b00: execute, 0b01: write, 0b11: read-or-write, 0b10: io read-or-write (unused)
760     //      and bits{x+3, x+2} => len
761     //            0b00: 1-byte, 0b01: 2-byte, 0b11: 4-byte, 0b10: 8-byte
762     //
763     //      dr0 -> bits{19-16}
764     //      dr1 -> bits{23-20}
765     //      dr2 -> bits{27-24}
766     //      dr3 -> bits{31-28}
767     debug_state.__dr7 |= (1 << (2*hw_index) |
768                           size_and_rw_bits(size, read, write) << (16+4*hw_index));
769     uint32_t addr_32 = addr & 0xffffffff;
770     switch (hw_index) {
771     case 0:
772         debug_state.__dr0 = addr_32; break;
773     case 1:
774         debug_state.__dr1 = addr_32; break;
775     case 2:
776         debug_state.__dr2 = addr_32; break;
777     case 3:
778         debug_state.__dr3 = addr_32; break;
779     default:
780         assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3");
781     }
782     return;
783 }
784
785 void
786 DNBArchImplI386::ClearWatchpoint(DBG &debug_state, uint32_t hw_index)
787 {
788     debug_state.__dr7 &= ~(3 << (2*hw_index));
789     switch (hw_index) {
790     case 0:
791         debug_state.__dr0 = 0; break;
792     case 1:
793         debug_state.__dr1 = 0; break;
794     case 2:
795         debug_state.__dr2 = 0; break;
796     case 3:
797         debug_state.__dr3 = 0; break;
798     default:
799         assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3");
800     }
801     return;
802 }
803
804 bool
805 DNBArchImplI386::IsWatchpointVacant(const DBG &debug_state, uint32_t hw_index)
806 {
807     // Check dr7 (debug control register) for local/global enable bits:
808     //  global enable --. .-- local enable
809     //                  | |
810     //                  v v
811     //      dr0 -> bits{1-0}
812     //      dr1 -> bits{3-2}
813     //      dr2 -> bits{5-4}
814     //      dr3 -> bits{7-6}
815     return (debug_state.__dr7 & (3 << (2*hw_index))) == 0;
816 }
817
818 // Resets local copy of debug status register to wait for the next debug exception.
819 void
820 DNBArchImplI386::ClearWatchpointHits(DBG &debug_state)
821 {
822     // See also IsWatchpointHit().
823     debug_state.__dr6 = 0;
824     return;
825 }
826
827 bool
828 DNBArchImplI386::IsWatchpointHit(const DBG &debug_state, uint32_t hw_index)
829 {
830     // Check dr6 (debug status register) whether a watchpoint hits:
831     //          is watchpoint hit?
832     //                  |
833     //                  v
834     //      dr0 -> bits{0}
835     //      dr1 -> bits{1}
836     //      dr2 -> bits{2}
837     //      dr3 -> bits{3}
838     return (debug_state.__dr6 & (1 << hw_index));
839 }
840
841 nub_addr_t
842 DNBArchImplI386::GetWatchAddress(const DBG &debug_state, uint32_t hw_index)
843 {
844     switch (hw_index) {
845     case 0:
846         return debug_state.__dr0;
847     case 1:
848         return debug_state.__dr1;
849     case 2:
850         return debug_state.__dr2;
851     case 3:
852         return debug_state.__dr3;
853     }
854     assert(0 && "invalid hardware register index, must be one of 0, 1, 2, or 3");
855     return 0;
856 }
857
858 bool
859 DNBArchImplI386::StartTransForHWP()
860 {
861     if (m_2pc_trans_state != Trans_Done && m_2pc_trans_state != Trans_Rolled_Back)
862         DNBLogError ("%s inconsistent state detected, expected %d or %d, got: %d", __FUNCTION__, Trans_Done, Trans_Rolled_Back, m_2pc_trans_state);
863     m_2pc_dbg_checkpoint = m_state.context.dbg;
864     m_2pc_trans_state = Trans_Pending;
865     return true;
866 }
867 bool
868 DNBArchImplI386::RollbackTransForHWP()
869 {
870     m_state.context.dbg = m_2pc_dbg_checkpoint;
871     if (m_2pc_trans_state != Trans_Pending)
872         DNBLogError ("%s inconsistent state detected, expected %d, got: %d", __FUNCTION__, Trans_Pending, m_2pc_trans_state);
873     m_2pc_trans_state = Trans_Rolled_Back;
874     kern_return_t kret = SetDBGState(false);
875     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::RollbackTransForHWP() SetDBGState() => 0x%8.8x.", kret);
876
877     if (kret == KERN_SUCCESS)
878         return true;
879     else
880         return false;
881 }
882 bool
883 DNBArchImplI386::FinishTransForHWP()
884 {
885     m_2pc_trans_state = Trans_Done;
886     return true;
887 }
888 DNBArchImplI386::DBG
889 DNBArchImplI386::GetDBGCheckpoint()
890 {
891     return m_2pc_dbg_checkpoint;
892 }
893
894 uint32_t
895 DNBArchImplI386::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write, bool also_set_on_task)
896 {
897     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::EnableHardwareWatchpoint(addr = 0x%llx, size = %llu, read = %u, write = %u)", (uint64_t)addr, (uint64_t)size, read, write);
898
899     const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
900
901     // Can only watch 1, 2, 4, or 8 bytes.
902     if (!(size == 1 || size == 2 || size == 4 || size == 8))
903         return INVALID_NUB_HW_INDEX;
904
905     // We must watch for either read or write
906     if (read == false && write == false)
907         return INVALID_NUB_HW_INDEX;
908
909     // Read the debug state
910     kern_return_t kret = GetDBGState(false);
911
912     if (kret == KERN_SUCCESS)
913     {
914         // Check to make sure we have the needed hardware support
915         uint32_t i = 0;
916
917         DBG &debug_state = m_state.context.dbg;
918         for (i = 0; i < num_hw_watchpoints; ++i)
919         {
920             if (IsWatchpointVacant(debug_state, i))
921                 break;
922         }
923
924         // See if we found an available hw breakpoint slot above
925         if (i < num_hw_watchpoints)
926         {
927             StartTransForHWP();
928
929             // Modify our local copy of the debug state, first.
930             SetWatchpoint(debug_state, i, addr, size, read, write);
931             // Now set the watch point in the inferior.
932             kret = SetDBGState(also_set_on_task);
933             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret);
934
935             if (kret == KERN_SUCCESS)
936                 return i;
937             else // Revert to the previous debug state voluntarily.  The transaction coordinator knows that we have failed.
938                 m_state.context.dbg = GetDBGCheckpoint();
939         }
940         else
941         {
942             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
943         }
944     }
945     return INVALID_NUB_HW_INDEX;
946 }
947
948 bool
949 DNBArchImplI386::DisableHardwareWatchpoint (uint32_t hw_index, bool also_set_on_task)
950 {
951     kern_return_t kret = GetDBGState(false);
952
953     const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
954     if (kret == KERN_SUCCESS)
955     {
956         DBG &debug_state = m_state.context.dbg;
957         if (hw_index < num_hw_points && !IsWatchpointVacant(debug_state, hw_index))
958         {
959             StartTransForHWP();
960
961             // Modify our local copy of the debug state, first.
962             ClearWatchpoint(debug_state, hw_index);
963             // Now disable the watch point in the inferior.
964             kret = SetDBGState(also_set_on_task);
965             DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::DisableHardwareWatchpoint( %u )",
966                              hw_index);
967
968             if (kret == KERN_SUCCESS)
969                 return true;
970             else // Revert to the previous debug state voluntarily.  The transaction coordinator knows that we have failed.
971                 m_state.context.dbg = GetDBGCheckpoint();
972         }
973     }
974     return false;
975 }
976
977 // Iterate through the debug status register; return the index of the first hit.
978 uint32_t
979 DNBArchImplI386::GetHardwareWatchpointHit(nub_addr_t &addr)
980 {
981     // Read the debug state
982     kern_return_t kret = GetDBGState(true);
983     DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplI386::GetHardwareWatchpointHit() GetDBGState() => 0x%8.8x.", kret);
984     if (kret == KERN_SUCCESS)
985     {
986         DBG &debug_state = m_state.context.dbg;
987         uint32_t i, num = NumSupportedHardwareWatchpoints();
988         for (i = 0; i < num; ++i)
989         {
990             if (IsWatchpointHit(debug_state, i))
991             {
992                 addr = GetWatchAddress(debug_state, i);
993                 DNBLogThreadedIf(LOG_WATCHPOINTS,
994                                  "DNBArchImplI386::GetHardwareWatchpointHit() found => %u (addr = 0x%llx).",
995                                  i, (uint64_t)addr);
996                 return i;
997             }
998         }
999     }
1000     return INVALID_NUB_HW_INDEX;
1001 }
1002
1003 // Set the single step bit in the processor status register.
1004 kern_return_t
1005 DNBArchImplI386::EnableHardwareSingleStep (bool enable)
1006 {
1007     if (GetGPRState(false) == KERN_SUCCESS)
1008     {
1009         const uint32_t trace_bit = 0x100u;
1010         if (enable)
1011             m_state.context.gpr.__eflags |= trace_bit;
1012         else
1013             m_state.context.gpr.__eflags &= ~trace_bit;
1014         return SetGPRState();
1015     }
1016     return m_state.GetError(e_regSetGPR, Read);
1017 }
1018
1019
1020 //----------------------------------------------------------------------
1021 // Register information definitions
1022 //----------------------------------------------------------------------
1023
1024 #define DEFINE_GPR_PSEUDO_16(reg16,reg32) { e_regSetGPR, gpr_##reg16, #reg16, NULL, Uint, Hex, 2, 0,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg32, g_invalidate_##reg32 }
1025 #define DEFINE_GPR_PSEUDO_8H(reg8,reg32)  { e_regSetGPR, gpr_##reg8 , #reg8 , NULL, Uint, Hex, 1, 1,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg32, g_invalidate_##reg32 }
1026 #define DEFINE_GPR_PSEUDO_8L(reg8,reg32)  { e_regSetGPR, gpr_##reg8 , #reg8 , NULL, Uint, Hex, 1, 0,INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, g_contained_##reg32, g_invalidate_##reg32 }
1027
1028
1029 #define GPR_OFFSET(reg) (offsetof (DNBArchImplI386::GPR, __##reg))
1030 #define FPU_OFFSET(reg) (offsetof (DNBArchImplI386::FPU, __fpu_##reg) + offsetof (DNBArchImplI386::Context, fpu.no_avx))
1031 #define AVX_OFFSET(reg) (offsetof (DNBArchImplI386::AVX, __fpu_##reg) + offsetof (DNBArchImplI386::Context, fpu.avx))
1032 #define EXC_OFFSET(reg) (offsetof (DNBArchImplI386::EXC, __##reg)     + offsetof (DNBArchImplI386::Context, exc))
1033
1034 #define GPR_SIZE(reg)       (sizeof(((DNBArchImplI386::GPR *)NULL)->__##reg))
1035 #define FPU_SIZE_UINT(reg)  (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg))
1036 #define FPU_SIZE_MMST(reg)  (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__mmst_reg))
1037 #define FPU_SIZE_XMM(reg)   (sizeof(((DNBArchImplI386::FPU *)NULL)->__fpu_##reg.__xmm_reg))
1038 #define FPU_SIZE_YMM(reg)   (32)
1039 #define EXC_SIZE(reg)       (sizeof(((DNBArchImplI386::EXC *)NULL)->__##reg))
1040
1041 // This does not accurately identify the location of ymm0...7 in 
1042 // Context.fpu.avx.  That is because there is a bunch of padding
1043 // in Context.fpu.avx that we don't need.  Offset macros lay out
1044 // the register state that Debugserver transmits to the debugger
1045 // -- not to interpret the thread_get_state info.
1046 #define AVX_OFFSET_YMM(n)   (AVX_OFFSET(xmm7) + FPU_SIZE_XMM(xmm7) + (32 * n))
1047
1048 // These macros will auto define the register name, alt name, register size,
1049 // register offset, encoding, format and native register. This ensures that
1050 // the register state structures are defined correctly and have the correct
1051 // sizes and offsets.
1052
1053 const char * g_contained_eax[] = { "eax", NULL };
1054 const char * g_contained_ebx[] = { "ebx", NULL };
1055 const char * g_contained_ecx[] = { "ecx", NULL };
1056 const char * g_contained_edx[] = { "edx", NULL };
1057 const char * g_contained_edi[] = { "edi", NULL };
1058 const char * g_contained_esi[] = { "esi", NULL };
1059 const char * g_contained_ebp[] = { "ebp", NULL };
1060 const char * g_contained_esp[] = { "esp", NULL };
1061
1062 const char * g_invalidate_eax[] = { "eax", "ax", "ah", "al", NULL };
1063 const char * g_invalidate_ebx[] = { "ebx", "bx", "bh", "bl", NULL };
1064 const char * g_invalidate_ecx[] = { "ecx", "cx", "ch", "cl", NULL };
1065 const char * g_invalidate_edx[] = { "edx", "dx", "dh", "dl", NULL };
1066 const char * g_invalidate_edi[] = { "edi", "di", "dil", NULL };
1067 const char * g_invalidate_esi[] = { "esi", "si", "sil", NULL };
1068 const char * g_invalidate_ebp[] = { "ebp", "bp", "bpl", NULL };
1069 const char * g_invalidate_esp[] = { "esp", "sp", "spl", NULL };
1070
1071 // General purpose registers for 64 bit
1072 const DNBRegisterInfo
1073 DNBArchImplI386::g_gpr_registers[] =
1074 {
1075 { e_regSetGPR, gpr_eax,     "eax"   , NULL      , Uint, Hex, GPR_SIZE(eax),     GPR_OFFSET(eax)     , ehframe_eax           , dwarf_eax         , INVALID_NUB_REGNUM    , debugserver_eax   , NULL, g_invalidate_eax },
1076 { e_regSetGPR, gpr_ebx,     "ebx"   , NULL      , Uint, Hex, GPR_SIZE(ebx),     GPR_OFFSET(ebx)     , ehframe_ebx           , dwarf_ebx         , INVALID_NUB_REGNUM    , debugserver_ebx   , NULL, g_invalidate_ebx },
1077 { e_regSetGPR, gpr_ecx,     "ecx"   , NULL      , Uint, Hex, GPR_SIZE(ecx),     GPR_OFFSET(ecx)     , ehframe_ecx           , dwarf_ecx         , INVALID_NUB_REGNUM    , debugserver_ecx   , NULL, g_invalidate_ecx },
1078 { e_regSetGPR, gpr_edx,     "edx"   , NULL      , Uint, Hex, GPR_SIZE(edx),     GPR_OFFSET(edx)     , ehframe_edx           , dwarf_edx         , INVALID_NUB_REGNUM    , debugserver_edx   , NULL, g_invalidate_edx },
1079 { e_regSetGPR, gpr_edi,     "edi"   , NULL      , Uint, Hex, GPR_SIZE(edi),     GPR_OFFSET(edi)     , ehframe_edi           , dwarf_edi         , INVALID_NUB_REGNUM    , debugserver_edi   , NULL, g_invalidate_edi },
1080 { e_regSetGPR, gpr_esi,     "esi"   , NULL      , Uint, Hex, GPR_SIZE(esi),     GPR_OFFSET(esi)     , ehframe_esi           , dwarf_esi         , INVALID_NUB_REGNUM    , debugserver_esi   , NULL, g_invalidate_esi },
1081 { e_regSetGPR, gpr_ebp,     "ebp"   , "fp"      , Uint, Hex, GPR_SIZE(ebp),     GPR_OFFSET(ebp)     , ehframe_ebp           , dwarf_ebp         , GENERIC_REGNUM_FP     , debugserver_ebp   , NULL, g_invalidate_ebp },
1082 { e_regSetGPR, gpr_esp,     "esp"   , "sp"      , Uint, Hex, GPR_SIZE(esp),     GPR_OFFSET(esp)     , ehframe_esp           , dwarf_esp         , GENERIC_REGNUM_SP     , debugserver_esp   , NULL, g_invalidate_esp },
1083 { e_regSetGPR, gpr_ss,      "ss"    , NULL      , Uint, Hex, GPR_SIZE(ss),      GPR_OFFSET(ss)      , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM    , debugserver_ss    , NULL, NULL},
1084 { e_regSetGPR, gpr_eflags,  "eflags", "flags"   , Uint, Hex, GPR_SIZE(eflags),  GPR_OFFSET(eflags)  , ehframe_eflags        , dwarf_eflags      , GENERIC_REGNUM_FLAGS  , debugserver_eflags, NULL, NULL},
1085 { e_regSetGPR, gpr_eip,     "eip"   , "pc"      , Uint, Hex, GPR_SIZE(eip),     GPR_OFFSET(eip)     , ehframe_eip           , dwarf_eip         , GENERIC_REGNUM_PC     , debugserver_eip   , NULL, NULL},
1086 { e_regSetGPR, gpr_cs,      "cs"    , NULL      , Uint, Hex, GPR_SIZE(cs),      GPR_OFFSET(cs)      , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM    , debugserver_cs    , NULL, NULL},
1087 { e_regSetGPR, gpr_ds,      "ds"    , NULL      , Uint, Hex, GPR_SIZE(ds),      GPR_OFFSET(ds)      , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM    , debugserver_ds    , NULL, NULL},
1088 { e_regSetGPR, gpr_es,      "es"    , NULL      , Uint, Hex, GPR_SIZE(es),      GPR_OFFSET(es)      , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM    , debugserver_es    , NULL, NULL},
1089 { e_regSetGPR, gpr_fs,      "fs"    , NULL      , Uint, Hex, GPR_SIZE(fs),      GPR_OFFSET(fs)      , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM    , debugserver_fs    , NULL, NULL},
1090 { e_regSetGPR, gpr_gs,      "gs"    , NULL      , Uint, Hex, GPR_SIZE(gs),      GPR_OFFSET(gs)      , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM    , debugserver_gs    , NULL, NULL},
1091 DEFINE_GPR_PSEUDO_16 (ax , eax),
1092 DEFINE_GPR_PSEUDO_16 (bx , ebx),
1093 DEFINE_GPR_PSEUDO_16 (cx , ecx),
1094 DEFINE_GPR_PSEUDO_16 (dx , edx),
1095 DEFINE_GPR_PSEUDO_16 (di , edi),
1096 DEFINE_GPR_PSEUDO_16 (si , esi),
1097 DEFINE_GPR_PSEUDO_16 (bp , ebp),
1098 DEFINE_GPR_PSEUDO_16 (sp , esp),
1099 DEFINE_GPR_PSEUDO_8H (ah , eax),
1100 DEFINE_GPR_PSEUDO_8H (bh , ebx),
1101 DEFINE_GPR_PSEUDO_8H (ch , ecx),
1102 DEFINE_GPR_PSEUDO_8H (dh , edx),
1103 DEFINE_GPR_PSEUDO_8L (al , eax),
1104 DEFINE_GPR_PSEUDO_8L (bl , ebx),
1105 DEFINE_GPR_PSEUDO_8L (cl , ecx),
1106 DEFINE_GPR_PSEUDO_8L (dl , edx),
1107 DEFINE_GPR_PSEUDO_8L (dil, edi),
1108 DEFINE_GPR_PSEUDO_8L (sil, esi),
1109 DEFINE_GPR_PSEUDO_8L (bpl, ebp),
1110 DEFINE_GPR_PSEUDO_8L (spl, esp)
1111 };
1112
1113
1114 const DNBRegisterInfo
1115 DNBArchImplI386::g_fpu_registers_no_avx[] =
1116 {
1117 { e_regSetFPU, fpu_fcw      , "fctrl"       , NULL, Uint, Hex, FPU_SIZE_UINT(fcw)       , FPU_OFFSET(fcw)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1118 { e_regSetFPU, fpu_fsw      , "fstat"       , NULL, Uint, Hex, FPU_SIZE_UINT(fsw)       , FPU_OFFSET(fsw)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1119 { e_regSetFPU, fpu_ftw      , "ftag"        , NULL, Uint, Hex, FPU_SIZE_UINT(ftw)       , FPU_OFFSET(ftw)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1120 { e_regSetFPU, fpu_fop      , "fop"         , NULL, Uint, Hex, FPU_SIZE_UINT(fop)       , FPU_OFFSET(fop)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1121 { e_regSetFPU, fpu_ip       , "fioff"       , NULL, Uint, Hex, FPU_SIZE_UINT(ip)        , FPU_OFFSET(ip)        , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1122 { e_regSetFPU, fpu_cs       , "fiseg"       , NULL, Uint, Hex, FPU_SIZE_UINT(cs)        , FPU_OFFSET(cs)        , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1123 { e_regSetFPU, fpu_dp       , "fooff"       , NULL, Uint, Hex, FPU_SIZE_UINT(dp)        , FPU_OFFSET(dp)        , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1124 { e_regSetFPU, fpu_ds       , "foseg"       , NULL, Uint, Hex, FPU_SIZE_UINT(ds)        , FPU_OFFSET(ds)        , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1125 { e_regSetFPU, fpu_mxcsr    , "mxcsr"       , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr)     , FPU_OFFSET(mxcsr)     , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1126 { e_regSetFPU, fpu_mxcsrmask, "mxcsrmask"   , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , FPU_OFFSET(mxcsrmask) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1127
1128 { e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0, INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL },
1129 { e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1, INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL },
1130 { e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2, INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL },
1131 { e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3, INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL },
1132 { e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4, INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL },
1133 { e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5, INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL },
1134 { e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6, INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL },
1135 { e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7, INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL },
1136
1137 { e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0), FPU_OFFSET(xmm0), INVALID_NUB_REGNUM, dwarf_xmm0, INVALID_NUB_REGNUM, debugserver_xmm0, NULL, NULL },
1138 { e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1), FPU_OFFSET(xmm1), INVALID_NUB_REGNUM, dwarf_xmm1, INVALID_NUB_REGNUM, debugserver_xmm1, NULL, NULL },
1139 { e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2), FPU_OFFSET(xmm2), INVALID_NUB_REGNUM, dwarf_xmm2, INVALID_NUB_REGNUM, debugserver_xmm2, NULL, NULL },
1140 { e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3), FPU_OFFSET(xmm3), INVALID_NUB_REGNUM, dwarf_xmm3, INVALID_NUB_REGNUM, debugserver_xmm3, NULL, NULL },
1141 { e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4), FPU_OFFSET(xmm4), INVALID_NUB_REGNUM, dwarf_xmm4, INVALID_NUB_REGNUM, debugserver_xmm4, NULL, NULL },
1142 { e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5), FPU_OFFSET(xmm5), INVALID_NUB_REGNUM, dwarf_xmm5, INVALID_NUB_REGNUM, debugserver_xmm5, NULL, NULL },
1143 { e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6), FPU_OFFSET(xmm6), INVALID_NUB_REGNUM, dwarf_xmm6, INVALID_NUB_REGNUM, debugserver_xmm6, NULL, NULL },
1144 { e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7), FPU_OFFSET(xmm7), INVALID_NUB_REGNUM, dwarf_xmm7, INVALID_NUB_REGNUM, debugserver_xmm7, NULL, NULL }
1145 };
1146
1147
1148 static const char *g_contained_ymm0 [] = { "ymm0", NULL };
1149 static const char *g_contained_ymm1 [] = { "ymm1", NULL };
1150 static const char *g_contained_ymm2 [] = { "ymm2", NULL };
1151 static const char *g_contained_ymm3 [] = { "ymm3", NULL };
1152 static const char *g_contained_ymm4 [] = { "ymm4", NULL };
1153 static const char *g_contained_ymm5 [] = { "ymm5", NULL };
1154 static const char *g_contained_ymm6 [] = { "ymm6", NULL };
1155 static const char *g_contained_ymm7 [] = { "ymm7", NULL };
1156
1157
1158 const DNBRegisterInfo
1159 DNBArchImplI386::g_fpu_registers_avx[] =
1160 {
1161 { e_regSetFPU, fpu_fcw      , "fctrl"       , NULL, Uint, Hex, FPU_SIZE_UINT(fcw)       , AVX_OFFSET(fcw)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1162 { e_regSetFPU, fpu_fsw      , "fstat"       , NULL, Uint, Hex, FPU_SIZE_UINT(fsw)       , AVX_OFFSET(fsw)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1163 { e_regSetFPU, fpu_ftw      , "ftag"        , NULL, Uint, Hex, FPU_SIZE_UINT(ftw)       , AVX_OFFSET(ftw)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1164 { e_regSetFPU, fpu_fop      , "fop"         , NULL, Uint, Hex, FPU_SIZE_UINT(fop)       , AVX_OFFSET(fop)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1165 { e_regSetFPU, fpu_ip       , "fioff"       , NULL, Uint, Hex, FPU_SIZE_UINT(ip)        , AVX_OFFSET(ip)        , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1166 { e_regSetFPU, fpu_cs       , "fiseg"       , NULL, Uint, Hex, FPU_SIZE_UINT(cs)        , AVX_OFFSET(cs)        , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1167 { e_regSetFPU, fpu_dp       , "fooff"       , NULL, Uint, Hex, FPU_SIZE_UINT(dp)        , AVX_OFFSET(dp)        , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1168 { e_regSetFPU, fpu_ds       , "foseg"       , NULL, Uint, Hex, FPU_SIZE_UINT(ds)        , AVX_OFFSET(ds)        , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1169 { e_regSetFPU, fpu_mxcsr    , "mxcsr"       , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr)     , AVX_OFFSET(mxcsr)     , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1170 { e_regSetFPU, fpu_mxcsrmask, "mxcsrmask"   , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , AVX_OFFSET(mxcsrmask) , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1171
1172 { e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), INVALID_NUB_REGNUM, dwarf_stmm0, INVALID_NUB_REGNUM, debugserver_stmm0, NULL, NULL },
1173 { e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), INVALID_NUB_REGNUM, dwarf_stmm1, INVALID_NUB_REGNUM, debugserver_stmm1, NULL, NULL },
1174 { e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), INVALID_NUB_REGNUM, dwarf_stmm2, INVALID_NUB_REGNUM, debugserver_stmm2, NULL, NULL },
1175 { e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), INVALID_NUB_REGNUM, dwarf_stmm3, INVALID_NUB_REGNUM, debugserver_stmm3, NULL, NULL },
1176 { e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), INVALID_NUB_REGNUM, dwarf_stmm4, INVALID_NUB_REGNUM, debugserver_stmm4, NULL, NULL },
1177 { e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), INVALID_NUB_REGNUM, dwarf_stmm5, INVALID_NUB_REGNUM, debugserver_stmm5, NULL, NULL },
1178 { e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), INVALID_NUB_REGNUM, dwarf_stmm6, INVALID_NUB_REGNUM, debugserver_stmm6, NULL, NULL },
1179 { e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), INVALID_NUB_REGNUM, dwarf_stmm7, INVALID_NUB_REGNUM, debugserver_stmm7, NULL, NULL },
1180
1181 { e_regSetFPU, fpu_ymm0, "ymm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm0), AVX_OFFSET_YMM(0), INVALID_NUB_REGNUM, dwarf_ymm0, INVALID_NUB_REGNUM, debugserver_ymm0, NULL, NULL },
1182 { e_regSetFPU, fpu_ymm1, "ymm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm1), AVX_OFFSET_YMM(1), INVALID_NUB_REGNUM, dwarf_ymm1, INVALID_NUB_REGNUM, debugserver_ymm1, NULL, NULL },
1183 { e_regSetFPU, fpu_ymm2, "ymm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm2), AVX_OFFSET_YMM(2), INVALID_NUB_REGNUM, dwarf_ymm2, INVALID_NUB_REGNUM, debugserver_ymm2, NULL, NULL },
1184 { e_regSetFPU, fpu_ymm3, "ymm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm3), AVX_OFFSET_YMM(3), INVALID_NUB_REGNUM, dwarf_ymm3, INVALID_NUB_REGNUM, debugserver_ymm3, NULL, NULL },
1185 { e_regSetFPU, fpu_ymm4, "ymm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm4), AVX_OFFSET_YMM(4), INVALID_NUB_REGNUM, dwarf_ymm4, INVALID_NUB_REGNUM, debugserver_ymm4, NULL, NULL },
1186 { e_regSetFPU, fpu_ymm5, "ymm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm5), AVX_OFFSET_YMM(5), INVALID_NUB_REGNUM, dwarf_ymm5, INVALID_NUB_REGNUM, debugserver_ymm5, NULL, NULL },
1187 { e_regSetFPU, fpu_ymm6, "ymm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm6), AVX_OFFSET_YMM(6), INVALID_NUB_REGNUM, dwarf_ymm6, INVALID_NUB_REGNUM, debugserver_ymm6, NULL, NULL },
1188 { e_regSetFPU, fpu_ymm7, "ymm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm7), AVX_OFFSET_YMM(7), INVALID_NUB_REGNUM, dwarf_ymm7, INVALID_NUB_REGNUM, debugserver_ymm7, NULL, NULL },
1189
1190 { e_regSetFPU, fpu_xmm0, "xmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0), 0, INVALID_NUB_REGNUM, dwarf_xmm0, INVALID_NUB_REGNUM, debugserver_xmm0, g_contained_ymm0, NULL },
1191 { e_regSetFPU, fpu_xmm1, "xmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1), 0, INVALID_NUB_REGNUM, dwarf_xmm1, INVALID_NUB_REGNUM, debugserver_xmm1, g_contained_ymm1, NULL },
1192 { e_regSetFPU, fpu_xmm2, "xmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2), 0, INVALID_NUB_REGNUM, dwarf_xmm2, INVALID_NUB_REGNUM, debugserver_xmm2, g_contained_ymm2, NULL },
1193 { e_regSetFPU, fpu_xmm3, "xmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3), 0, INVALID_NUB_REGNUM, dwarf_xmm3, INVALID_NUB_REGNUM, debugserver_xmm3, g_contained_ymm3, NULL },
1194 { e_regSetFPU, fpu_xmm4, "xmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4), 0, INVALID_NUB_REGNUM, dwarf_xmm4, INVALID_NUB_REGNUM, debugserver_xmm4, g_contained_ymm4, NULL },
1195 { e_regSetFPU, fpu_xmm5, "xmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5), 0, INVALID_NUB_REGNUM, dwarf_xmm5, INVALID_NUB_REGNUM, debugserver_xmm5, g_contained_ymm5, NULL },
1196 { e_regSetFPU, fpu_xmm6, "xmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6), 0, INVALID_NUB_REGNUM, dwarf_xmm6, INVALID_NUB_REGNUM, debugserver_xmm6, g_contained_ymm6, NULL },
1197 { e_regSetFPU, fpu_xmm7, "xmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7), 0, INVALID_NUB_REGNUM, dwarf_xmm7, INVALID_NUB_REGNUM, debugserver_xmm7, g_contained_ymm7, NULL },
1198
1199 };
1200
1201 const DNBRegisterInfo
1202 DNBArchImplI386::g_exc_registers[] =
1203 {
1204 { e_regSetEXC, exc_trapno,      "trapno"    , NULL, Uint, Hex, EXC_SIZE (trapno)    , EXC_OFFSET (trapno)       , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1205 { e_regSetEXC, exc_err,         "err"       , NULL, Uint, Hex, EXC_SIZE (err)       , EXC_OFFSET (err)          , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL },
1206 { e_regSetEXC, exc_faultvaddr,  "faultvaddr", NULL, Uint, Hex, EXC_SIZE (faultvaddr), EXC_OFFSET (faultvaddr)   , INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, NULL, NULL }
1207 };
1208
1209 // Number of registers in each register set
1210 const size_t DNBArchImplI386::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo);
1211 const size_t DNBArchImplI386::k_num_fpu_registers_no_avx = sizeof(g_fpu_registers_no_avx)/sizeof(DNBRegisterInfo);
1212 const size_t DNBArchImplI386::k_num_fpu_registers_avx = sizeof(g_fpu_registers_avx)/sizeof(DNBRegisterInfo);
1213 const size_t DNBArchImplI386::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo);
1214 const size_t DNBArchImplI386::k_num_all_registers_no_avx = k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers;
1215 const size_t DNBArchImplI386::k_num_all_registers_avx = k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers;
1216
1217 //----------------------------------------------------------------------
1218 // Register set definitions. The first definitions at register set index
1219 // of zero is for all registers, followed by other registers sets. The
1220 // register information for the all register set need not be filled in.
1221 //----------------------------------------------------------------------
1222 const DNBRegisterSetInfo
1223 DNBArchImplI386::g_reg_sets_no_avx[] =
1224 {
1225     { "i386 Registers",             NULL,                   k_num_all_registers_no_avx },
1226     { "General Purpose Registers",  g_gpr_registers,        k_num_gpr_registers        },
1227     { "Floating Point Registers",   g_fpu_registers_no_avx, k_num_fpu_registers_no_avx },
1228     { "Exception State Registers",  g_exc_registers,        k_num_exc_registers        }
1229 };
1230
1231 const DNBRegisterSetInfo
1232 DNBArchImplI386::g_reg_sets_avx[] =
1233 {
1234     { "i386 Registers",             NULL,                   k_num_all_registers_avx },
1235     { "General Purpose Registers",  g_gpr_registers,        k_num_gpr_registers     },
1236     { "Floating Point Registers",   g_fpu_registers_avx,    k_num_fpu_registers_avx },
1237     { "Exception State Registers",  g_exc_registers,        k_num_exc_registers     }
1238 };
1239
1240 // Total number of register sets for this architecture
1241 const size_t DNBArchImplI386::k_num_register_sets = sizeof(g_reg_sets_no_avx)/sizeof(DNBRegisterSetInfo);
1242
1243 DNBArchProtocol *
1244 DNBArchImplI386::Create (MachThread *thread)
1245 {
1246     DNBArchImplI386 *obj = new DNBArchImplI386 (thread);
1247     return obj;
1248 }
1249
1250 const uint8_t *
1251 DNBArchImplI386::SoftwareBreakpointOpcode (nub_size_t byte_size)
1252 {
1253     static const uint8_t g_breakpoint_opcode[] = { 0xCC };
1254     if (byte_size == 1)
1255         return g_breakpoint_opcode;
1256     return NULL;
1257 }
1258
1259 const DNBRegisterSetInfo *
1260 DNBArchImplI386::GetRegisterSetInfo(nub_size_t *num_reg_sets)
1261 {
1262     *num_reg_sets = k_num_register_sets;
1263     if (CPUHasAVX() || FORCE_AVX_REGS)
1264         return g_reg_sets_avx;
1265     else
1266         return g_reg_sets_no_avx;
1267 }
1268
1269
1270 void
1271 DNBArchImplI386::Initialize()
1272 {
1273     DNBArchPluginInfo arch_plugin_info = 
1274     {
1275         CPU_TYPE_I386, 
1276         DNBArchImplI386::Create, 
1277         DNBArchImplI386::GetRegisterSetInfo,
1278         DNBArchImplI386::SoftwareBreakpointOpcode
1279     };
1280     
1281     // Register this arch plug-in with the main protocol class
1282     DNBArchProtocol::RegisterArchPlugin (arch_plugin_info);
1283 }
1284
1285 bool
1286 DNBArchImplI386::GetRegisterValue(uint32_t set, uint32_t reg, DNBRegisterValue *value)
1287 {
1288     if (set == REGISTER_SET_GENERIC)
1289     {
1290         switch (reg)
1291         {
1292         case GENERIC_REGNUM_PC:     // Program Counter
1293             set = e_regSetGPR;
1294             reg = gpr_eip;
1295             break;
1296
1297         case GENERIC_REGNUM_SP:     // Stack Pointer
1298             set = e_regSetGPR;
1299             reg = gpr_esp;
1300             break;
1301
1302         case GENERIC_REGNUM_FP:     // Frame Pointer
1303             set = e_regSetGPR;
1304             reg = gpr_ebp;
1305             break;
1306
1307         case GENERIC_REGNUM_FLAGS:  // Processor flags register
1308             set = e_regSetGPR;
1309             reg = gpr_eflags;
1310             break;
1311
1312         case GENERIC_REGNUM_RA:     // Return Address
1313         default:
1314             return false;
1315         }
1316     }
1317
1318     if (GetRegisterState(set, false) != KERN_SUCCESS)
1319         return false;
1320
1321     const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
1322     if (regInfo)
1323     {
1324         value->info = *regInfo;
1325         switch (set)
1326         {
1327         case e_regSetGPR:
1328             if (reg < k_num_gpr_registers)
1329             {
1330                 value->value.uint32 = ((uint32_t*)(&m_state.context.gpr))[reg];
1331                 return true;
1332             }
1333             break;
1334
1335         case e_regSetFPU:
1336             if (CPUHasAVX() || FORCE_AVX_REGS)
1337             {
1338                 switch (reg)
1339                 {
1340                 case fpu_fcw:       value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw));    return true;
1341                 case fpu_fsw:       value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw));    return true;
1342                 case fpu_ftw:       value->value.uint8  = m_state.context.fpu.avx.__fpu_ftw;                      return true;
1343                 case fpu_fop:       value->value.uint16 = m_state.context.fpu.avx.__fpu_fop;                      return true;
1344                 case fpu_ip:        value->value.uint32 = m_state.context.fpu.avx.__fpu_ip;                       return true;
1345                 case fpu_cs:        value->value.uint16 = m_state.context.fpu.avx.__fpu_cs;                       return true;
1346                 case fpu_dp:        value->value.uint32 = m_state.context.fpu.avx.__fpu_dp;                       return true;
1347                 case fpu_ds:        value->value.uint16 = m_state.context.fpu.avx.__fpu_ds;                       return true;
1348                 case fpu_mxcsr:     value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsr;                    return true;
1349                 case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsrmask;                return true;
1350                     
1351                 case fpu_stmm0:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg, 10);    return true;
1352                 case fpu_stmm1:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg, 10);    return true;
1353                 case fpu_stmm2:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg, 10);    return true;
1354                 case fpu_stmm3:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg, 10);    return true;
1355                 case fpu_stmm4:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg, 10);    return true;
1356                 case fpu_stmm5:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg, 10);    return true;
1357                 case fpu_stmm6:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg, 10);    return true;
1358                 case fpu_stmm7:     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg, 10);    return true;
1359                     
1360                 case fpu_xmm0:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg, 16);    return true;
1361                 case fpu_xmm1:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg, 16);    return true;
1362                 case fpu_xmm2:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg, 16);    return true;
1363                 case fpu_xmm3:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg, 16);    return true;
1364                 case fpu_xmm4:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg, 16);    return true;
1365                 case fpu_xmm5:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg, 16);    return true;
1366                 case fpu_xmm6:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg, 16);    return true;
1367                 case fpu_xmm7:      memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg, 16);    return true;
1368                 
1369 #define MEMCPY_YMM(n)                                                                           \
1370     memcpy(&value->value.uint8, m_state.context.fpu.avx.__fpu_xmm##n.__xmm_reg, 16);            \
1371     memcpy((&value->value.uint8) + 16, m_state.context.fpu.avx.__fpu_ymmh##n.__xmm_reg, 16);
1372                 case fpu_ymm0:      MEMCPY_YMM(0);  return true;
1373                 case fpu_ymm1:      MEMCPY_YMM(1);  return true;
1374                 case fpu_ymm2:      MEMCPY_YMM(2);  return true;
1375                 case fpu_ymm3:      MEMCPY_YMM(3);  return true;
1376                 case fpu_ymm4:      MEMCPY_YMM(4);  return true;
1377                 case fpu_ymm5:      MEMCPY_YMM(5);  return true;
1378                 case fpu_ymm6:      MEMCPY_YMM(6);  return true;
1379                 case fpu_ymm7:      MEMCPY_YMM(7);  return true;
1380 #undef MEMCPY_YMM
1381                 }
1382             }
1383             else
1384             {
1385                 switch (reg)
1386                 {
1387                 case fpu_fcw:       value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw));    return true;
1388                 case fpu_fsw:       value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw));    return true;
1389                 case fpu_ftw:       value->value.uint8  = m_state.context.fpu.no_avx.__fpu_ftw;                      return true;
1390                 case fpu_fop:       value->value.uint16 = m_state.context.fpu.no_avx.__fpu_fop;                      return true;
1391                 case fpu_ip:        value->value.uint32 = m_state.context.fpu.no_avx.__fpu_ip;                       return true;
1392                 case fpu_cs:        value->value.uint16 = m_state.context.fpu.no_avx.__fpu_cs;                       return true;
1393                 case fpu_dp:        value->value.uint32 = m_state.context.fpu.no_avx.__fpu_dp;                       return true;
1394                 case fpu_ds:        value->value.uint16 = m_state.context.fpu.no_avx.__fpu_ds;                       return true;
1395                 case fpu_mxcsr:     value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsr;                    return true;
1396                 case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsrmask;                return true;
1397
1398                 case fpu_stmm0:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg, 10);    return true;
1399                 case fpu_stmm1:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg, 10);    return true;
1400                 case fpu_stmm2:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg, 10);    return true;
1401                 case fpu_stmm3:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg, 10);    return true;
1402                 case fpu_stmm4:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg, 10);    return true;
1403                 case fpu_stmm5:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg, 10);    return true;
1404                 case fpu_stmm6:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg, 10);    return true;
1405                 case fpu_stmm7:     memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg, 10);    return true;
1406
1407                 case fpu_xmm0:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg, 16);    return true;
1408                 case fpu_xmm1:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg, 16);    return true;
1409                 case fpu_xmm2:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg, 16);    return true;
1410                 case fpu_xmm3:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg, 16);    return true;
1411                 case fpu_xmm4:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg, 16);    return true;
1412                 case fpu_xmm5:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg, 16);    return true;
1413                 case fpu_xmm6:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg, 16);    return true;
1414                 case fpu_xmm7:      memcpy(&value->value.uint8, m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg, 16);    return true;
1415                 }
1416             }
1417             break;
1418
1419         case e_regSetEXC:
1420             if (reg < k_num_exc_registers)
1421             {
1422                 value->value.uint32 = (&m_state.context.exc.__trapno)[reg];
1423                 return true;
1424             }
1425             break;
1426         }
1427     }
1428     return false;
1429 }
1430
1431
1432 bool
1433 DNBArchImplI386::SetRegisterValue(uint32_t set, uint32_t reg, const DNBRegisterValue *value)
1434 {
1435     if (set == REGISTER_SET_GENERIC)
1436     {
1437         switch (reg)
1438         {
1439         case GENERIC_REGNUM_PC:     // Program Counter
1440             set = e_regSetGPR;
1441             reg = gpr_eip;
1442             break;
1443
1444         case GENERIC_REGNUM_SP:     // Stack Pointer
1445             set = e_regSetGPR;
1446             reg = gpr_esp;
1447             break;
1448
1449         case GENERIC_REGNUM_FP:     // Frame Pointer
1450             set = e_regSetGPR;
1451             reg = gpr_ebp;
1452             break;
1453
1454         case GENERIC_REGNUM_FLAGS:  // Processor flags register
1455             set = e_regSetGPR;
1456             reg = gpr_eflags;
1457             break;
1458
1459         case GENERIC_REGNUM_RA:     // Return Address
1460         default:
1461             return false;
1462         }
1463     }
1464
1465     if (GetRegisterState(set, false) != KERN_SUCCESS)
1466         return false;
1467
1468     bool success = false;
1469     const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
1470     if (regInfo)
1471     {
1472         switch (set)
1473         {
1474         case e_regSetGPR:
1475             if (reg < k_num_gpr_registers)
1476             {
1477                 ((uint32_t*)(&m_state.context.gpr))[reg] = value->value.uint32;
1478                 success = true;
1479             }
1480             break;
1481
1482         case e_regSetFPU:
1483             if (CPUHasAVX() || FORCE_AVX_REGS)
1484             {
1485                 switch (reg)
1486                 {
1487                 case fpu_fcw:       *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)) = value->value.uint16;    success = true; break;
1488                 case fpu_fsw:       *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)) = value->value.uint16;    success = true; break;
1489                 case fpu_ftw:       m_state.context.fpu.avx.__fpu_ftw = value->value.uint8;                       success = true; break;
1490                 case fpu_fop:       m_state.context.fpu.avx.__fpu_fop = value->value.uint16;                      success = true; break;
1491                 case fpu_ip:        m_state.context.fpu.avx.__fpu_ip = value->value.uint32;                       success = true; break;
1492                 case fpu_cs:        m_state.context.fpu.avx.__fpu_cs = value->value.uint16;                       success = true; break;
1493                 case fpu_dp:        m_state.context.fpu.avx.__fpu_dp = value->value.uint32;                       success = true; break;
1494                 case fpu_ds:        m_state.context.fpu.avx.__fpu_ds = value->value.uint16;                       success = true; break;
1495                 case fpu_mxcsr:     m_state.context.fpu.avx.__fpu_mxcsr = value->value.uint32;                    success = true; break;
1496                 case fpu_mxcsrmask: m_state.context.fpu.avx.__fpu_mxcsrmask = value->value.uint32;                success = true; break;
1497                     
1498                 case fpu_stmm0:     memcpy (m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1499                 case fpu_stmm1:     memcpy (m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1500                 case fpu_stmm2:     memcpy (m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1501                 case fpu_stmm3:     memcpy (m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1502                 case fpu_stmm4:     memcpy (m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1503                 case fpu_stmm5:     memcpy (m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1504                 case fpu_stmm6:     memcpy (m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1505                 case fpu_stmm7:     memcpy (m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1506                     
1507                 case fpu_xmm0:      memcpy(m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1508                 case fpu_xmm1:      memcpy(m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1509                 case fpu_xmm2:      memcpy(m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1510                 case fpu_xmm3:      memcpy(m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1511                 case fpu_xmm4:      memcpy(m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1512                 case fpu_xmm5:      memcpy(m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1513                 case fpu_xmm6:      memcpy(m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1514                 case fpu_xmm7:      memcpy(m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1515                         
1516 #define MEMCPY_YMM(n)                                                                           \
1517     memcpy(m_state.context.fpu.avx.__fpu_xmm##n.__xmm_reg, &value->value.uint8, 16);            \
1518     memcpy(m_state.context.fpu.avx.__fpu_ymmh##n.__xmm_reg, (&value->value.uint8) + 16, 16);
1519                 case fpu_ymm0:      MEMCPY_YMM(0);  return true;
1520                 case fpu_ymm1:      MEMCPY_YMM(1);  return true;
1521                 case fpu_ymm2:      MEMCPY_YMM(2);  return true;
1522                 case fpu_ymm3:      MEMCPY_YMM(3);  return true;
1523                 case fpu_ymm4:      MEMCPY_YMM(4);  return true;
1524                 case fpu_ymm5:      MEMCPY_YMM(5);  return true;
1525                 case fpu_ymm6:      MEMCPY_YMM(6);  return true;
1526                 case fpu_ymm7:      MEMCPY_YMM(7);  return true;
1527 #undef MEMCPY_YMM
1528                 }
1529             }
1530             else
1531             {
1532                 switch (reg)
1533                 {
1534                 case fpu_fcw:       *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)) = value->value.uint16;    success = true; break;
1535                 case fpu_fsw:       *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)) = value->value.uint16;    success = true; break;
1536                 case fpu_ftw:       m_state.context.fpu.no_avx.__fpu_ftw = value->value.uint8;                       success = true; break;
1537                 case fpu_fop:       m_state.context.fpu.no_avx.__fpu_fop = value->value.uint16;                      success = true; break;
1538                 case fpu_ip:        m_state.context.fpu.no_avx.__fpu_ip = value->value.uint32;                       success = true; break;
1539                 case fpu_cs:        m_state.context.fpu.no_avx.__fpu_cs = value->value.uint16;                       success = true; break;
1540                 case fpu_dp:        m_state.context.fpu.no_avx.__fpu_dp = value->value.uint32;                       success = true; break;
1541                 case fpu_ds:        m_state.context.fpu.no_avx.__fpu_ds = value->value.uint16;                       success = true; break;
1542                 case fpu_mxcsr:     m_state.context.fpu.no_avx.__fpu_mxcsr = value->value.uint32;                    success = true; break;
1543                 case fpu_mxcsrmask: m_state.context.fpu.no_avx.__fpu_mxcsrmask = value->value.uint32;                success = true; break;
1544
1545                 case fpu_stmm0:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1546                 case fpu_stmm1:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1547                 case fpu_stmm2:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1548                 case fpu_stmm3:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1549                 case fpu_stmm4:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1550                 case fpu_stmm5:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1551                 case fpu_stmm6:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1552                 case fpu_stmm7:     memcpy (m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg, &value->value.uint8, 10);    success = true; break;
1553
1554                 case fpu_xmm0:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1555                 case fpu_xmm1:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1556                 case fpu_xmm2:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1557                 case fpu_xmm3:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1558                 case fpu_xmm4:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1559                 case fpu_xmm5:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1560                 case fpu_xmm6:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1561                 case fpu_xmm7:      memcpy(m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg, &value->value.uint8, 16);    success = true; break;
1562                 }
1563             }
1564             break;
1565
1566         case e_regSetEXC:
1567             if (reg < k_num_exc_registers)
1568             {
1569                 (&m_state.context.exc.__trapno)[reg] = value->value.uint32;
1570                 success = true;
1571             }
1572             break;
1573         }
1574     }
1575
1576     if (success)
1577         return SetRegisterState(set) == KERN_SUCCESS;
1578     return false;
1579 }
1580
1581
1582 uint32_t
1583 DNBArchImplI386::GetRegisterContextSize()
1584 {
1585     static uint32_t g_cached_size = 0;
1586     if (g_cached_size == 0)
1587     {
1588         if (CPUHasAVX() || FORCE_AVX_REGS)
1589         {
1590             for (size_t i=0; i<k_num_fpu_registers_avx; ++i)
1591             {
1592                 if (g_fpu_registers_avx[i].value_regs == NULL)
1593                     g_cached_size += g_fpu_registers_avx[i].size;
1594             }
1595         }
1596         else
1597         {
1598             for (size_t i=0; i<k_num_fpu_registers_no_avx; ++i)
1599             {
1600                 if (g_fpu_registers_no_avx[i].value_regs == NULL)
1601                     g_cached_size += g_fpu_registers_no_avx[i].size;
1602             }
1603         }
1604         DNBLogThreaded ("DNBArchImplX86_64::GetRegisterContextSize() - GPR = %zu, FPU = %u, EXC = %zu", sizeof(GPR), g_cached_size, sizeof(EXC));
1605         g_cached_size += sizeof(GPR);
1606         g_cached_size += sizeof(EXC);
1607         DNBLogThreaded ("DNBArchImplX86_64::GetRegisterContextSize() - GPR + FPU + EXC = %u", g_cached_size);
1608     }
1609     return g_cached_size;
1610 }
1611
1612
1613 nub_size_t
1614 DNBArchImplI386::GetRegisterContext (void *buf, nub_size_t buf_len)
1615 {
1616     uint32_t size = GetRegisterContextSize();
1617     
1618     if (buf && buf_len)
1619     {
1620         if (size > buf_len)
1621             size = static_cast<uint32_t>(buf_len);
1622
1623         bool force = false;
1624         kern_return_t kret;
1625         if ((kret = GetGPRState(force)) != KERN_SUCCESS)
1626         {
1627             DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = %llu) error: GPR regs failed to read: %u ", buf, (uint64_t)buf_len, kret);
1628             size = 0;
1629         }
1630         else if ((kret = GetFPUState(force)) != KERN_SUCCESS)
1631         {
1632             DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = %llu) error: %s regs failed to read: %u", buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret);
1633             size = 0;
1634         }
1635         else if ((kret = GetEXCState(force)) != KERN_SUCCESS)
1636         {
1637             DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = %llu) error: EXC regs failed to read: %u", buf, (uint64_t)buf_len, kret);
1638             size = 0;
1639         }
1640         else
1641         {
1642             uint8_t *p = (uint8_t *)buf;
1643             // Copy the GPR registers
1644             memcpy(p, &m_state.context.gpr, sizeof(GPR));
1645             p += sizeof(GPR);
1646             
1647             if (CPUHasAVX() || FORCE_AVX_REGS)
1648             {
1649                 // Walk around the gaps in the FPU regs
1650                 memcpy(p, &m_state.context.fpu.avx.__fpu_fcw, 5);
1651                 p += 5;
1652                 memcpy(p, &m_state.context.fpu.avx.__fpu_fop, 8);
1653                 p += 8;
1654                 memcpy(p, &m_state.context.fpu.avx.__fpu_dp, 6);
1655                 p += 6;
1656                 memcpy(p, &m_state.context.fpu.avx.__fpu_mxcsr, 8);
1657                 p += 8;
1658                 
1659                 // Work around the padding between the stmm registers as they are 16
1660                 // byte structs with 10 bytes of the value in each
1661                 for (size_t i=0; i<8; ++i)
1662                 {
1663                     memcpy(p, &m_state.context.fpu.avx.__fpu_stmm0 + i, 10);
1664                     p += 10;
1665                 }
1666                 
1667                 // Interleave the XMM and YMMH registers to make the YMM registers
1668                 for (size_t i=0; i<8; ++i)
1669                 {
1670                     memcpy(p, &m_state.context.fpu.avx.__fpu_xmm0 + i, 16);
1671                     p += 16;
1672                     memcpy(p, &m_state.context.fpu.avx.__fpu_ymmh0 + i, 16);
1673                     p += 16;
1674                 }
1675             }
1676             else
1677             {
1678                 // Walk around the gaps in the FPU regs
1679                 memcpy(p, &m_state.context.fpu.no_avx.__fpu_fcw, 5);
1680                 p += 5;
1681                 memcpy(p, &m_state.context.fpu.no_avx.__fpu_fop, 8);
1682                 p += 8;
1683                 memcpy(p, &m_state.context.fpu.no_avx.__fpu_dp, 6);
1684                 p += 6;
1685                 memcpy(p, &m_state.context.fpu.no_avx.__fpu_mxcsr, 8);
1686                 p += 8;
1687                 
1688                 // Work around the padding between the stmm registers as they are 16
1689                 // byte structs with 10 bytes of the value in each
1690                 for (size_t i=0; i<8; ++i)
1691                 {
1692                     memcpy(p, &m_state.context.fpu.no_avx.__fpu_stmm0 + i, 10);
1693                     p += 10;
1694                 }
1695                 
1696                 // Copy the XMM registers in a single block
1697                 memcpy(p, &m_state.context.fpu.no_avx.__fpu_xmm0, 8 * 16);
1698                 p += 8 * 16;
1699             }
1700             
1701             // Copy the exception registers
1702             memcpy(p, &m_state.context.exc, sizeof(EXC));
1703             p += sizeof(EXC);
1704             
1705             // make sure we end up with exactly what we think we should have
1706             size_t bytes_written = p - (uint8_t *)buf;
1707             UNUSED_IF_ASSERT_DISABLED(bytes_written);
1708             assert (bytes_written == size);
1709         }
1710     }
1711     DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::GetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size);
1712     // Return the size of the register context even if NULL was passed in
1713     return size;
1714 }
1715
1716 nub_size_t
1717 DNBArchImplI386::SetRegisterContext (const void *buf, nub_size_t buf_len)
1718 {
1719     nub_size_t size = sizeof (m_state.context);
1720     if (buf == NULL || buf_len == 0)
1721         size = 0;
1722     
1723     if (size)
1724     {
1725         if (size > buf_len)
1726             size = buf_len;
1727
1728         uint8_t *p = (uint8_t *)buf;
1729         // Copy the GPR registers
1730         memcpy(&m_state.context.gpr, p, sizeof(GPR));
1731         p += sizeof(GPR);
1732         
1733         if (CPUHasAVX() || FORCE_AVX_REGS)
1734         {
1735             // Walk around the gaps in the FPU regs
1736             memcpy(&m_state.context.fpu.avx.__fpu_fcw, p, 5);
1737             p += 5;
1738             memcpy(&m_state.context.fpu.avx.__fpu_fop, p, 8);
1739             p += 8;
1740             memcpy(&m_state.context.fpu.avx.__fpu_dp, p, 6);
1741             p += 6;
1742             memcpy(&m_state.context.fpu.avx.__fpu_mxcsr, p, 8);
1743             p += 8;
1744             
1745             // Work around the padding between the stmm registers as they are 16
1746             // byte structs with 10 bytes of the value in each
1747             for (size_t i=0; i<8; ++i)
1748             {
1749                 memcpy(&m_state.context.fpu.avx.__fpu_stmm0 + i, p, 10);
1750                 p += 10;
1751             }
1752             
1753             // Interleave the XMM and YMMH registers to make the YMM registers
1754             for (size_t i=0; i<8; ++i)
1755             {
1756                 memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + i, p, 16);
1757                 p += 16;
1758                 memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + i, p, 16);
1759                 p += 16;
1760             }
1761         }
1762         else
1763         {
1764             // Copy fcw through mxcsrmask as there is no padding
1765             memcpy(&m_state.context.fpu.no_avx.__fpu_fcw, p, 5);
1766             p += 5;
1767             memcpy(&m_state.context.fpu.no_avx.__fpu_fop, p, 8);
1768             p += 8;
1769             memcpy(&m_state.context.fpu.no_avx.__fpu_dp, p, 6);
1770             p += 6;
1771             memcpy(&m_state.context.fpu.no_avx.__fpu_mxcsr, p, 8);
1772             p += 8;
1773             
1774             // Work around the padding between the stmm registers as they are 16
1775             // byte structs with 10 bytes of the value in each
1776             for (size_t i=0; i<8; ++i)
1777             {
1778                 memcpy(&m_state.context.fpu.no_avx.__fpu_stmm0 + i, p, 10);
1779                 p += 10;
1780             }
1781             
1782             // Copy the XMM registers in a single block
1783             memcpy(&m_state.context.fpu.no_avx.__fpu_xmm0, p, 8 * 16);
1784             p += 8 * 16;
1785         }
1786         
1787         // Copy the exception registers
1788         memcpy(&m_state.context.exc, p, sizeof(EXC));
1789         p += sizeof(EXC);
1790         
1791         // make sure we end up with exactly what we think we should have
1792         size_t bytes_written = p - (uint8_t *)buf;
1793         UNUSED_IF_ASSERT_DISABLED(bytes_written);
1794         assert (bytes_written == size);
1795         kern_return_t kret;
1796         if ((kret = SetGPRState()) != KERN_SUCCESS)
1797             DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = %llu) error: GPR regs failed to write: %u", buf, (uint64_t)buf_len, kret);
1798         if ((kret = SetFPUState()) != KERN_SUCCESS)
1799             DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = %llu) error: %s regs failed to write: %u", buf, (uint64_t)buf_len, CPUHasAVX() ? "AVX" : "FPU", kret);
1800         if ((kret = SetEXCState()) != KERN_SUCCESS)
1801             DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = %llu) error: EXP regs failed to write: %u", buf, (uint64_t)buf_len, kret);
1802     }
1803     DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SetRegisterContext (buf = %p, len = %llu) => %llu", buf, (uint64_t)buf_len, (uint64_t)size);
1804     return size;
1805 }
1806
1807
1808 uint32_t
1809 DNBArchImplI386::SaveRegisterState ()
1810 {
1811     kern_return_t kret = ::thread_abort_safely(m_thread->MachPortNumber());
1812     DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->MachPortNumber(), kret, m_thread->Process()->StopCount());
1813
1814     bool force = true;
1815     
1816     if ((kret = GetGPRState(force)) != KERN_SUCCESS)
1817     {
1818         DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SaveRegisterState () error: GPR regs failed to read: %u ", kret);
1819     }
1820     else if ((kret = GetFPUState(force)) != KERN_SUCCESS)
1821     {
1822         DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::SaveRegisterState () error: %s regs failed to read: %u", CPUHasAVX() ? "AVX" : "FPU", kret);
1823     }
1824     else
1825     {
1826         const uint32_t save_id = GetNextRegisterStateSaveID ();
1827         m_saved_register_states[save_id] = m_state.context;
1828         return save_id;
1829     }
1830     return 0;
1831 }
1832 bool
1833 DNBArchImplI386::RestoreRegisterState (uint32_t save_id)
1834 {
1835     SaveRegisterStates::iterator pos = m_saved_register_states.find(save_id);
1836     if (pos != m_saved_register_states.end())
1837     {
1838         m_state.context.gpr = pos->second.gpr;
1839         m_state.context.fpu = pos->second.fpu;
1840         m_state.context.exc = pos->second.exc;
1841         m_state.SetError(e_regSetGPR, Read, 0);
1842         m_state.SetError(e_regSetFPU, Read, 0);
1843         m_state.SetError(e_regSetEXC, Read, 0);
1844         kern_return_t kret;
1845         bool success = true;
1846         if ((kret = SetGPRState()) != KERN_SUCCESS)
1847         {
1848             DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::RestoreRegisterState (save_id = %u) error: GPR regs failed to write: %u", save_id, kret);
1849             success = false;
1850         }
1851         else if ((kret = SetFPUState()) != KERN_SUCCESS)
1852         {
1853             DNBLogThreadedIf (LOG_THREAD, "DNBArchImplI386::RestoreRegisterState (save_id = %u) error: %s regs failed to write: %u", save_id, CPUHasAVX() ? "AVX" : "FPU", kret);
1854             success = false;
1855         }
1856         m_saved_register_states.erase(pos);
1857         return success;
1858     }
1859     return false;
1860 }
1861
1862
1863 kern_return_t
1864 DNBArchImplI386::GetRegisterState(int set, bool force)
1865 {
1866     switch (set)
1867     {
1868     case e_regSetALL:    return GetGPRState(force) | GetFPUState(force) | GetEXCState(force);
1869     case e_regSetGPR:    return GetGPRState(force);
1870     case e_regSetFPU:    return GetFPUState(force);
1871     case e_regSetEXC:    return GetEXCState(force);
1872     default: break;
1873     }
1874     return KERN_INVALID_ARGUMENT;
1875 }
1876
1877 kern_return_t
1878 DNBArchImplI386::SetRegisterState(int set)
1879 {
1880     // Make sure we have a valid context to set.
1881     if (RegisterSetStateIsValid(set))
1882     {
1883         switch (set)
1884         {
1885         case e_regSetALL:    return SetGPRState() | SetFPUState() | SetEXCState();
1886         case e_regSetGPR:    return SetGPRState();
1887         case e_regSetFPU:    return SetFPUState();
1888         case e_regSetEXC:    return SetEXCState();
1889         default: break;
1890         }
1891     }
1892     return KERN_INVALID_ARGUMENT;
1893 }
1894
1895 bool
1896 DNBArchImplI386::RegisterSetStateIsValid (int set) const
1897 {
1898     return m_state.RegsAreValid(set);
1899 }
1900
1901 #endif    // #if defined (__i386__)