DNBArchImplX86_64.cpp revision eb0eae254e4e2d737b9c137296197a70a1ba7f68
1//===-- DNBArchImplX86_64.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/x86_64/DNBArchImplX86_64.h"
19#include "DNBLog.h"
20#include "MachThread.h"
21#include "MachProcess.h"
22#include <mach/mach.h>
23#include <stdlib.h>
24
25#if defined (LLDB_DEBUGSERVER_RELEASE) || defined (LLDB_DEBUGSERVER_DEBUG)
26enum debugState {
27    debugStateUnknown,
28    debugStateOff,
29    debugStateOn
30};
31
32static debugState sFPUDebugState = debugStateUnknown;
33static debugState sAVXForceState = debugStateUnknown;
34
35static 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
48static 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
68enum DNBArchImplX86_64::AVXPresence DNBArchImplX86_64::s_has_avx = DNBArchImplX86_64::kAVXUnknown;
69
70uint64_t
71DNBArchImplX86_64::GetPC(uint64_t failValue)
72{
73    // Get program counter
74    if (GetGPRState(false) == KERN_SUCCESS)
75        return m_state.context.gpr.__rip;
76    return failValue;
77}
78
79kern_return_t
80DNBArchImplX86_64::SetPC(uint64_t value)
81{
82    // Get program counter
83    kern_return_t err = GetGPRState(false);
84    if (err == KERN_SUCCESS)
85    {
86        m_state.context.gpr.__rip = value;
87        err = SetGPRState();
88    }
89    return err == KERN_SUCCESS;
90}
91
92uint64_t
93DNBArchImplX86_64::GetSP(uint64_t failValue)
94{
95    // Get stack pointer
96    if (GetGPRState(false) == KERN_SUCCESS)
97        return m_state.context.gpr.__rsp;
98    return failValue;
99}
100
101// Uncomment the value below to verify the values in the debugger.
102//#define DEBUG_GPR_VALUES 1    // DO NOT CHECK IN WITH THIS DEFINE ENABLED
103
104kern_return_t
105DNBArchImplX86_64::GetGPRState(bool force)
106{
107    if (force || m_state.GetError(e_regSetGPR, Read))
108    {
109        kern_return_t kret = ::thread_abort_safely(m_thread->ThreadID());
110        DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (GetGPRState() for stop_count = %u)", m_thread->ThreadID(), kret, m_thread->Process()->StopCount());
111
112#if DEBUG_GPR_VALUES
113        m_state.context.gpr.__rax = ('a' << 8) + 'x';
114        m_state.context.gpr.__rbx = ('b' << 8) + 'x';
115        m_state.context.gpr.__rcx = ('c' << 8) + 'x';
116        m_state.context.gpr.__rdx = ('d' << 8) + 'x';
117        m_state.context.gpr.__rdi = ('d' << 8) + 'i';
118        m_state.context.gpr.__rsi = ('s' << 8) + 'i';
119        m_state.context.gpr.__rbp = ('b' << 8) + 'p';
120        m_state.context.gpr.__rsp = ('s' << 8) + 'p';
121        m_state.context.gpr.__r8  = ('r' << 8) + '8';
122        m_state.context.gpr.__r9  = ('r' << 8) + '9';
123        m_state.context.gpr.__r10 = ('r' << 8) + 'a';
124        m_state.context.gpr.__r11 = ('r' << 8) + 'b';
125        m_state.context.gpr.__r12 = ('r' << 8) + 'c';
126        m_state.context.gpr.__r13 = ('r' << 8) + 'd';
127        m_state.context.gpr.__r14 = ('r' << 8) + 'e';
128        m_state.context.gpr.__r15 = ('r' << 8) + 'f';
129        m_state.context.gpr.__rip = ('i' << 8) + 'p';
130        m_state.context.gpr.__rflags = ('f' << 8) + 'l';
131        m_state.context.gpr.__cs = ('c' << 8) + 's';
132        m_state.context.gpr.__fs = ('f' << 8) + 's';
133        m_state.context.gpr.__gs = ('g' << 8) + 's';
134        m_state.SetError(e_regSetGPR, Read, 0);
135#else
136        mach_msg_type_number_t count = e_regSetWordSizeGPR;
137        m_state.SetError(e_regSetGPR, Read, ::thread_get_state(m_thread->ThreadID(), __x86_64_THREAD_STATE, (thread_state_t)&m_state.context.gpr, &count));
138        DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x"
139                          "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx"
140                          "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx"
141                          "\n\t r8 = %16.16llx  r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx"
142                          "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx"
143                          "\n\trip = %16.16llx"
144                          "\n\tflg = %16.16llx  cs = %16.16llx  fs = %16.16llx  gs = %16.16llx",
145                          m_thread->ThreadID(), x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT,
146                          m_state.GetError(e_regSetGPR, Read),
147                          m_state.context.gpr.__rax,m_state.context.gpr.__rbx,m_state.context.gpr.__rcx,
148                          m_state.context.gpr.__rdx,m_state.context.gpr.__rdi,m_state.context.gpr.__rsi,
149                          m_state.context.gpr.__rbp,m_state.context.gpr.__rsp,m_state.context.gpr.__r8,
150                          m_state.context.gpr.__r9, m_state.context.gpr.__r10,m_state.context.gpr.__r11,
151                          m_state.context.gpr.__r12,m_state.context.gpr.__r13,m_state.context.gpr.__r14,
152                          m_state.context.gpr.__r15,m_state.context.gpr.__rip,m_state.context.gpr.__rflags,
153                          m_state.context.gpr.__cs,m_state.context.gpr.__fs, m_state.context.gpr.__gs);
154
155        //      DNBLogThreadedIf (LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x"
156        //                        "\n\trax = %16.16llx"
157        //                        "\n\trbx = %16.16llx"
158        //                        "\n\trcx = %16.16llx"
159        //                        "\n\trdx = %16.16llx"
160        //                        "\n\trdi = %16.16llx"
161        //                        "\n\trsi = %16.16llx"
162        //                        "\n\trbp = %16.16llx"
163        //                        "\n\trsp = %16.16llx"
164        //                        "\n\t r8 = %16.16llx"
165        //                        "\n\t r9 = %16.16llx"
166        //                        "\n\tr10 = %16.16llx"
167        //                        "\n\tr11 = %16.16llx"
168        //                        "\n\tr12 = %16.16llx"
169        //                        "\n\tr13 = %16.16llx"
170        //                        "\n\tr14 = %16.16llx"
171        //                        "\n\tr15 = %16.16llx"
172        //                        "\n\trip = %16.16llx"
173        //                        "\n\tflg = %16.16llx"
174        //                        "\n\t cs = %16.16llx"
175        //                        "\n\t fs = %16.16llx"
176        //                        "\n\t gs = %16.16llx",
177        //                        m_thread->ThreadID(),
178        //                        x86_THREAD_STATE64,
179        //                        x86_THREAD_STATE64_COUNT,
180        //                        m_state.GetError(e_regSetGPR, Read),
181        //                        m_state.context.gpr.__rax,
182        //                        m_state.context.gpr.__rbx,
183        //                        m_state.context.gpr.__rcx,
184        //                        m_state.context.gpr.__rdx,
185        //                        m_state.context.gpr.__rdi,
186        //                        m_state.context.gpr.__rsi,
187        //                        m_state.context.gpr.__rbp,
188        //                        m_state.context.gpr.__rsp,
189        //                        m_state.context.gpr.__r8,
190        //                        m_state.context.gpr.__r9,
191        //                        m_state.context.gpr.__r10,
192        //                        m_state.context.gpr.__r11,
193        //                        m_state.context.gpr.__r12,
194        //                        m_state.context.gpr.__r13,
195        //                        m_state.context.gpr.__r14,
196        //                        m_state.context.gpr.__r15,
197        //                        m_state.context.gpr.__rip,
198        //                        m_state.context.gpr.__rflags,
199        //                        m_state.context.gpr.__cs,
200        //                        m_state.context.gpr.__fs,
201        //                        m_state.context.gpr.__gs);
202#endif
203    }
204    return m_state.GetError(e_regSetGPR, Read);
205}
206
207// Uncomment the value below to verify the values in the debugger.
208//#define DEBUG_FPU_REGS 1    // DO NOT CHECK IN WITH THIS DEFINE ENABLED
209
210kern_return_t
211DNBArchImplX86_64::GetFPUState(bool force)
212{
213    if (force || m_state.GetError(e_regSetFPU, Read))
214    {
215        if (DEBUG_FPU_REGS) {
216            if (CPUHasAVX() || FORCE_AVX_REGS)
217            {
218                m_state.context.fpu.avx.__fpu_reserved[0] = -1;
219                m_state.context.fpu.avx.__fpu_reserved[1] = -1;
220                *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fcw) = 0x1234;
221                *(uint16_t *)&(m_state.context.fpu.avx.__fpu_fsw) = 0x5678;
222                m_state.context.fpu.avx.__fpu_ftw = 1;
223                m_state.context.fpu.avx.__fpu_rsrv1 = UINT8_MAX;
224                m_state.context.fpu.avx.__fpu_fop = 2;
225                m_state.context.fpu.avx.__fpu_ip = 3;
226                m_state.context.fpu.avx.__fpu_cs = 4;
227                m_state.context.fpu.avx.__fpu_rsrv2 = 5;
228                m_state.context.fpu.avx.__fpu_dp = 6;
229                m_state.context.fpu.avx.__fpu_ds = 7;
230                m_state.context.fpu.avx.__fpu_rsrv3 = UINT16_MAX;
231                m_state.context.fpu.avx.__fpu_mxcsr = 8;
232                m_state.context.fpu.avx.__fpu_mxcsrmask = 9;
233                int i;
234                for (i=0; i<16; ++i)
235                {
236                    if (i<10)
237                    {
238                        m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = 'a';
239                        m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = 'b';
240                        m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = 'c';
241                        m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = 'd';
242                        m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = 'e';
243                        m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = 'f';
244                        m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = 'g';
245                        m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = 'h';
246                    }
247                    else
248                    {
249                        m_state.context.fpu.avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN;
250                        m_state.context.fpu.avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN;
251                        m_state.context.fpu.avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN;
252                        m_state.context.fpu.avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN;
253                        m_state.context.fpu.avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN;
254                        m_state.context.fpu.avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN;
255                        m_state.context.fpu.avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN;
256                        m_state.context.fpu.avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN;
257                    }
258
259                    m_state.context.fpu.avx.__fpu_xmm0.__xmm_reg[i] = '0';
260                    m_state.context.fpu.avx.__fpu_xmm1.__xmm_reg[i] = '1';
261                    m_state.context.fpu.avx.__fpu_xmm2.__xmm_reg[i] = '2';
262                    m_state.context.fpu.avx.__fpu_xmm3.__xmm_reg[i] = '3';
263                    m_state.context.fpu.avx.__fpu_xmm4.__xmm_reg[i] = '4';
264                    m_state.context.fpu.avx.__fpu_xmm5.__xmm_reg[i] = '5';
265                    m_state.context.fpu.avx.__fpu_xmm6.__xmm_reg[i] = '6';
266                    m_state.context.fpu.avx.__fpu_xmm7.__xmm_reg[i] = '7';
267                    m_state.context.fpu.avx.__fpu_xmm8.__xmm_reg[i] = '8';
268                    m_state.context.fpu.avx.__fpu_xmm9.__xmm_reg[i] = '9';
269                    m_state.context.fpu.avx.__fpu_xmm10.__xmm_reg[i] = 'A';
270                    m_state.context.fpu.avx.__fpu_xmm11.__xmm_reg[i] = 'B';
271                    m_state.context.fpu.avx.__fpu_xmm12.__xmm_reg[i] = 'C';
272                    m_state.context.fpu.avx.__fpu_xmm13.__xmm_reg[i] = 'D';
273                    m_state.context.fpu.avx.__fpu_xmm14.__xmm_reg[i] = 'E';
274                    m_state.context.fpu.avx.__fpu_xmm15.__xmm_reg[i] = 'F';
275
276                    m_state.context.fpu.avx.__fpu_ymmh0.__xmm_reg[i] = '0';
277                    m_state.context.fpu.avx.__fpu_ymmh1.__xmm_reg[i] = '1';
278                    m_state.context.fpu.avx.__fpu_ymmh2.__xmm_reg[i] = '2';
279                    m_state.context.fpu.avx.__fpu_ymmh3.__xmm_reg[i] = '3';
280                    m_state.context.fpu.avx.__fpu_ymmh4.__xmm_reg[i] = '4';
281                    m_state.context.fpu.avx.__fpu_ymmh5.__xmm_reg[i] = '5';
282                    m_state.context.fpu.avx.__fpu_ymmh6.__xmm_reg[i] = '6';
283                    m_state.context.fpu.avx.__fpu_ymmh7.__xmm_reg[i] = '7';
284                    m_state.context.fpu.avx.__fpu_ymmh8.__xmm_reg[i] = '8';
285                    m_state.context.fpu.avx.__fpu_ymmh9.__xmm_reg[i] = '9';
286                    m_state.context.fpu.avx.__fpu_ymmh10.__xmm_reg[i] = 'A';
287                    m_state.context.fpu.avx.__fpu_ymmh11.__xmm_reg[i] = 'B';
288                    m_state.context.fpu.avx.__fpu_ymmh12.__xmm_reg[i] = 'C';
289                    m_state.context.fpu.avx.__fpu_ymmh13.__xmm_reg[i] = 'D';
290                    m_state.context.fpu.avx.__fpu_ymmh14.__xmm_reg[i] = 'E';
291                    m_state.context.fpu.avx.__fpu_ymmh15.__xmm_reg[i] = 'F';
292                }
293                for (i=0; i<sizeof(m_state.context.fpu.avx.__fpu_rsrv4); ++i)
294                    m_state.context.fpu.avx.__fpu_rsrv4[i] = INT8_MIN;
295                m_state.context.fpu.avx.__fpu_reserved1 = -1;
296                for (i=0; i<sizeof(m_state.context.fpu.avx.__avx_reserved1); ++i)
297                    m_state.context.fpu.avx.__avx_reserved1[i] = INT8_MIN;
298                m_state.SetError(e_regSetFPU, Read, 0);
299            }
300            else
301            {
302                m_state.context.fpu.no_avx.__fpu_reserved[0] = -1;
303                m_state.context.fpu.no_avx.__fpu_reserved[1] = -1;
304                *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fcw) = 0x1234;
305                *(uint16_t *)&(m_state.context.fpu.no_avx.__fpu_fsw) = 0x5678;
306                m_state.context.fpu.no_avx.__fpu_ftw = 1;
307                m_state.context.fpu.no_avx.__fpu_rsrv1 = UINT8_MAX;
308                m_state.context.fpu.no_avx.__fpu_fop = 2;
309                m_state.context.fpu.no_avx.__fpu_ip = 3;
310                m_state.context.fpu.no_avx.__fpu_cs = 4;
311                m_state.context.fpu.no_avx.__fpu_rsrv2 = 5;
312                m_state.context.fpu.no_avx.__fpu_dp = 6;
313                m_state.context.fpu.no_avx.__fpu_ds = 7;
314                m_state.context.fpu.no_avx.__fpu_rsrv3 = UINT16_MAX;
315                m_state.context.fpu.no_avx.__fpu_mxcsr = 8;
316                m_state.context.fpu.no_avx.__fpu_mxcsrmask = 9;
317                int i;
318                for (i=0; i<16; ++i)
319                {
320                    if (i<10)
321                    {
322                        m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = 'a';
323                        m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = 'b';
324                        m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = 'c';
325                        m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = 'd';
326                        m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = 'e';
327                        m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = 'f';
328                        m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = 'g';
329                        m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = 'h';
330                    }
331                    else
332                    {
333                        m_state.context.fpu.no_avx.__fpu_stmm0.__mmst_reg[i] = INT8_MIN;
334                        m_state.context.fpu.no_avx.__fpu_stmm1.__mmst_reg[i] = INT8_MIN;
335                        m_state.context.fpu.no_avx.__fpu_stmm2.__mmst_reg[i] = INT8_MIN;
336                        m_state.context.fpu.no_avx.__fpu_stmm3.__mmst_reg[i] = INT8_MIN;
337                        m_state.context.fpu.no_avx.__fpu_stmm4.__mmst_reg[i] = INT8_MIN;
338                        m_state.context.fpu.no_avx.__fpu_stmm5.__mmst_reg[i] = INT8_MIN;
339                        m_state.context.fpu.no_avx.__fpu_stmm6.__mmst_reg[i] = INT8_MIN;
340                        m_state.context.fpu.no_avx.__fpu_stmm7.__mmst_reg[i] = INT8_MIN;
341                    }
342
343                    m_state.context.fpu.no_avx.__fpu_xmm0.__xmm_reg[i] = '0';
344                    m_state.context.fpu.no_avx.__fpu_xmm1.__xmm_reg[i] = '1';
345                    m_state.context.fpu.no_avx.__fpu_xmm2.__xmm_reg[i] = '2';
346                    m_state.context.fpu.no_avx.__fpu_xmm3.__xmm_reg[i] = '3';
347                    m_state.context.fpu.no_avx.__fpu_xmm4.__xmm_reg[i] = '4';
348                    m_state.context.fpu.no_avx.__fpu_xmm5.__xmm_reg[i] = '5';
349                    m_state.context.fpu.no_avx.__fpu_xmm6.__xmm_reg[i] = '6';
350                    m_state.context.fpu.no_avx.__fpu_xmm7.__xmm_reg[i] = '7';
351                    m_state.context.fpu.no_avx.__fpu_xmm8.__xmm_reg[i] = '8';
352                    m_state.context.fpu.no_avx.__fpu_xmm9.__xmm_reg[i] = '9';
353                    m_state.context.fpu.no_avx.__fpu_xmm10.__xmm_reg[i] = 'A';
354                    m_state.context.fpu.no_avx.__fpu_xmm11.__xmm_reg[i] = 'B';
355                    m_state.context.fpu.no_avx.__fpu_xmm12.__xmm_reg[i] = 'C';
356                    m_state.context.fpu.no_avx.__fpu_xmm13.__xmm_reg[i] = 'D';
357                    m_state.context.fpu.no_avx.__fpu_xmm14.__xmm_reg[i] = 'E';
358                    m_state.context.fpu.no_avx.__fpu_xmm15.__xmm_reg[i] = 'F';
359                }
360                for (i=0; i<sizeof(m_state.context.fpu.no_avx.__fpu_rsrv4); ++i)
361                    m_state.context.fpu.no_avx.__fpu_rsrv4[i] = INT8_MIN;
362                m_state.context.fpu.no_avx.__fpu_reserved1 = -1;
363                m_state.SetError(e_regSetFPU, Read, 0);
364            }
365        }
366        else
367        {
368            if (CPUHasAVX() || FORCE_AVX_REGS)
369            {
370                mach_msg_type_number_t count = e_regSetWordSizeAVX;
371                m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->ThreadID(), __x86_64_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, &count));
372            }
373            else
374            {
375                mach_msg_type_number_t count = e_regSetWordSizeFPR;
376                m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->ThreadID(), __x86_64_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, &count));
377            }
378        }
379    }
380    return m_state.GetError(e_regSetFPU, Read);
381}
382
383kern_return_t
384DNBArchImplX86_64::GetEXCState(bool force)
385{
386    if (force || m_state.GetError(e_regSetEXC, Read))
387    {
388        mach_msg_type_number_t count = e_regSetWordSizeEXC;
389        m_state.SetError(e_regSetEXC, Read, ::thread_get_state(m_thread->ThreadID(), __x86_64_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, &count));
390    }
391    return m_state.GetError(e_regSetEXC, Read);
392}
393
394kern_return_t
395DNBArchImplX86_64::SetGPRState()
396{
397    kern_return_t kret = ::thread_abort_safely(m_thread->ThreadID());
398    DNBLogThreadedIf (LOG_THREAD, "thread = 0x%4.4x calling thread_abort_safely (tid) => %u (SetGPRState() for stop_count = %u)", m_thread->ThreadID(), kret, m_thread->Process()->StopCount());
399
400    m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->ThreadID(), __x86_64_THREAD_STATE, (thread_state_t)&m_state.context.gpr, e_regSetWordSizeGPR));
401    DNBLogThreadedIf (LOG_THREAD, "::thread_set_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x"
402                      "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx"
403                      "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx"
404                      "\n\t r8 = %16.16llx  r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx"
405                      "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx"
406                      "\n\trip = %16.16llx"
407                      "\n\tflg = %16.16llx  cs = %16.16llx  fs = %16.16llx  gs = %16.16llx",
408                      m_thread->ThreadID(), __x86_64_THREAD_STATE, e_regSetWordSizeGPR,
409                      m_state.GetError(e_regSetGPR, Write),
410                      m_state.context.gpr.__rax,m_state.context.gpr.__rbx,m_state.context.gpr.__rcx,
411                      m_state.context.gpr.__rdx,m_state.context.gpr.__rdi,m_state.context.gpr.__rsi,
412                      m_state.context.gpr.__rbp,m_state.context.gpr.__rsp,m_state.context.gpr.__r8,
413                      m_state.context.gpr.__r9, m_state.context.gpr.__r10,m_state.context.gpr.__r11,
414                      m_state.context.gpr.__r12,m_state.context.gpr.__r13,m_state.context.gpr.__r14,
415                      m_state.context.gpr.__r15,m_state.context.gpr.__rip,m_state.context.gpr.__rflags,
416                      m_state.context.gpr.__cs, m_state.context.gpr.__fs, m_state.context.gpr.__gs);
417    return m_state.GetError(e_regSetGPR, Write);
418}
419
420kern_return_t
421DNBArchImplX86_64::SetFPUState()
422{
423    if (DEBUG_FPU_REGS)
424    {
425        m_state.SetError(e_regSetFPU, Write, 0);
426        return m_state.GetError(e_regSetFPU, Write);
427    }
428    else
429    {
430        if (CPUHasAVX() || FORCE_AVX_REGS)
431        {
432            m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->ThreadID(), __x86_64_AVX_STATE, (thread_state_t)&m_state.context.fpu.avx, e_regSetWordSizeAVX));
433            return m_state.GetError(e_regSetFPU, Write);
434        }
435        else
436        {
437            m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->ThreadID(), __x86_64_FLOAT_STATE, (thread_state_t)&m_state.context.fpu.no_avx, e_regSetWordSizeFPR));
438            return m_state.GetError(e_regSetFPU, Write);
439        }
440    }
441}
442
443kern_return_t
444DNBArchImplX86_64::SetEXCState()
445{
446    m_state.SetError(e_regSetEXC, Write, ::thread_set_state(m_thread->ThreadID(), __x86_64_EXCEPTION_STATE, (thread_state_t)&m_state.context.exc, e_regSetWordSizeEXC));
447    return m_state.GetError(e_regSetEXC, Write);
448}
449
450kern_return_t
451DNBArchImplX86_64::GetDBGState(bool force)
452{
453    if (force || m_state.GetError(e_regSetDBG, Read))
454    {
455        mach_msg_type_number_t count = e_regSetWordSizeDBG;
456        m_state.SetError(e_regSetDBG, Read, ::thread_get_state(m_thread->ThreadID(), __x86_64_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, &count));
457    }
458    return m_state.GetError(e_regSetDBG, Read);
459}
460
461kern_return_t
462DNBArchImplX86_64::SetDBGState()
463{
464    m_state.SetError(e_regSetDBG, Write, ::thread_set_state(m_thread->ThreadID(), __x86_64_DEBUG_STATE, (thread_state_t)&m_state.context.dbg, e_regSetWordSizeDBG));
465    return m_state.GetError(e_regSetDBG, Write);
466}
467
468void
469DNBArchImplX86_64::ThreadWillResume()
470{
471    // Do we need to step this thread? If so, let the mach thread tell us so.
472    if (m_thread->IsStepping())
473    {
474        // This is the primary thread, let the arch do anything it needs
475        EnableHardwareSingleStep(true);
476    }
477}
478
479bool
480DNBArchImplX86_64::ThreadDidStop()
481{
482    bool success = true;
483
484    m_state.InvalidateAllRegisterStates();
485
486    // Are we stepping a single instruction?
487    if (GetGPRState(true) == KERN_SUCCESS)
488    {
489        // We are single stepping, was this the primary thread?
490        if (m_thread->IsStepping())
491        {
492            // This was the primary thread, we need to clear the trace
493            // bit if so.
494            success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
495        }
496        else
497        {
498            // The MachThread will automatically restore the suspend count
499            // in ThreadDidStop(), so we don't need to do anything here if
500            // we weren't the primary thread the last time
501        }
502    }
503    return success;
504}
505
506bool
507DNBArchImplX86_64::NotifyException(MachException::Data& exc)
508{
509    switch (exc.exc_type)
510    {
511        case EXC_BAD_ACCESS:
512            break;
513        case EXC_BAD_INSTRUCTION:
514            break;
515        case EXC_ARITHMETIC:
516            break;
517        case EXC_EMULATION:
518            break;
519        case EXC_SOFTWARE:
520            break;
521        case EXC_BREAKPOINT:
522            if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2)
523            {
524                nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS);
525                if (pc != INVALID_NUB_ADDRESS && pc > 0)
526                {
527                    pc -= 1;
528                    // Check for a breakpoint at one byte prior to the current PC value
529                    // since the PC will be just past the trap.
530
531                    nub_break_t breakID = m_thread->Process()->Breakpoints().FindIDByAddress(pc);
532                    if (NUB_BREAK_ID_IS_VALID(breakID))
533                    {
534                        // Backup the PC for i386 since the trap was taken and the PC
535                        // is at the address following the single byte trap instruction.
536                        if (m_state.context.gpr.__rip > 0)
537                        {
538                            m_state.context.gpr.__rip = pc;
539                            // Write the new PC back out
540                            SetGPRState ();
541                        }
542                    }
543                    return true;
544                }
545            }
546            break;
547        case EXC_SYSCALL:
548            break;
549        case EXC_MACH_SYSCALL:
550            break;
551        case EXC_RPC_ALERT:
552            break;
553    }
554    return false;
555}
556
557#ifndef DR_FIRSTADDR
558#define DR_FIRSTADDR 0
559#endif
560
561#ifndef DR_LASTADDR
562#define DR_LASTADDR 3
563#endif
564
565#ifndef DR_STATUS
566#define DR_STATUS 6
567#endif
568
569#ifndef DR_CONTROL
570#define DR_CONTROL 7
571#endif
572
573uint32_t
574DNBArchImplX86_64::NumSupportedHardwareWatchpoints()
575{
576    return DR_LASTADDR - DR_FIRSTADDR + 1;
577}
578
579uint32_t
580DNBArchImplX86_64::EnableHardwareWatchpoint (nub_addr_t addr, nub_size_t size, bool read, bool write)
581{
582    DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::EnableHardwareWatchpoint(addr = %8.8p, size = %u, read = %u, write = %u)", addr, size, read, write);
583
584    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
585
586    // Can't watch zero bytes
587    if (size == 0)
588        return INVALID_NUB_HW_INDEX;
589
590    // We must watch for either read or write
591    if (read == false && write == false)
592        return INVALID_NUB_HW_INDEX;
593
594    //
595    // FIXME: Add implmentation.
596    //
597
598    // Read the debug state
599    kern_return_t kret = GetDBGState(false);
600
601    if (kret == KERN_SUCCESS)
602    {
603        // Check to make sure we have the needed hardware support
604        uint32_t i = 0;
605
606        DBG debug_state = m_state.context.dbg;
607        for (i=0; i<num_hw_watchpoints; ++i)
608        {
609            uint64_t dr_val = 0;
610            switch (i) {
611            case 0:
612                dr_val = debug_state.__dr0; break;
613            case 1:
614                dr_val = debug_state.__dr1; break;
615            case 2:
616                dr_val = debug_state.__dr2; break;
617            case 3:
618                dr_val = debug_state.__dr3; break;
619            default:
620                break;
621            }
622            if (dr_val != 0)
623                break; // We found an available hw breakpoint slot (in i)
624        }
625
626        // See if we found an available hw breakpoint slot above
627        if (i < num_hw_watchpoints)
628        {
629            kret = SetDBGState();
630            DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::EnableHardwareWatchpoint() SetDBGState() => 0x%8.8x.", kret);
631
632            if (kret == KERN_SUCCESS)
633                return i;
634        }
635        else
636        {
637            DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::EnableHardwareWatchpoint(): All hardware resources (%u) are in use.", num_hw_watchpoints);
638        }
639    }
640    return INVALID_NUB_HW_INDEX;
641}
642
643bool
644DNBArchImplX86_64::DisableHardwareWatchpoint (uint32_t hw_index)
645{
646    kern_return_t kret = GetDBGState(false);
647
648    const uint32_t num_hw_points = NumSupportedHardwareWatchpoints();
649    if (kret == KERN_SUCCESS)
650    {
651        if (hw_index < num_hw_points)
652        {
653            //
654            // FIXEME: Add implementation.
655            //
656
657            DNBLogThreadedIf(LOG_WATCHPOINTS, "DNBArchImplX86_64::DisableHardwareWatchpoint( %u )",
658                             hw_index);
659
660            kret = SetDBGState();
661
662            if (kret == KERN_SUCCESS)
663                return true;
664        }
665    }
666    return false;
667}
668
669// Set the single step bit in the processor status register.
670kern_return_t
671DNBArchImplX86_64::EnableHardwareSingleStep (bool enable)
672{
673    if (GetGPRState(false) == KERN_SUCCESS)
674    {
675        const uint32_t trace_bit = 0x100u;
676        if (enable)
677            m_state.context.gpr.__rflags |= trace_bit;
678        else
679            m_state.context.gpr.__rflags &= ~trace_bit;
680        return SetGPRState();
681    }
682    return m_state.GetError(e_regSetGPR, Read);
683}
684
685
686//----------------------------------------------------------------------
687// Register information defintions
688//----------------------------------------------------------------------
689
690enum
691{
692    gpr_rax = 0,
693    gpr_rbx,
694    gpr_rcx,
695    gpr_rdx,
696    gpr_rdi,
697    gpr_rsi,
698    gpr_rbp,
699    gpr_rsp,
700    gpr_r8,
701    gpr_r9,
702    gpr_r10,
703    gpr_r11,
704    gpr_r12,
705    gpr_r13,
706    gpr_r14,
707    gpr_r15,
708    gpr_rip,
709    gpr_rflags,
710    gpr_cs,
711    gpr_fs,
712    gpr_gs,
713    k_num_gpr_regs
714};
715
716enum {
717    fpu_fcw,
718    fpu_fsw,
719    fpu_ftw,
720    fpu_fop,
721    fpu_ip,
722    fpu_cs,
723    fpu_dp,
724    fpu_ds,
725    fpu_mxcsr,
726    fpu_mxcsrmask,
727    fpu_stmm0,
728    fpu_stmm1,
729    fpu_stmm2,
730    fpu_stmm3,
731    fpu_stmm4,
732    fpu_stmm5,
733    fpu_stmm6,
734    fpu_stmm7,
735    fpu_xmm0,
736    fpu_xmm1,
737    fpu_xmm2,
738    fpu_xmm3,
739    fpu_xmm4,
740    fpu_xmm5,
741    fpu_xmm6,
742    fpu_xmm7,
743    fpu_xmm8,
744    fpu_xmm9,
745    fpu_xmm10,
746    fpu_xmm11,
747    fpu_xmm12,
748    fpu_xmm13,
749    fpu_xmm14,
750    fpu_xmm15,
751    fpu_ymm0,
752    fpu_ymm1,
753    fpu_ymm2,
754    fpu_ymm3,
755    fpu_ymm4,
756    fpu_ymm5,
757    fpu_ymm6,
758    fpu_ymm7,
759    fpu_ymm8,
760    fpu_ymm9,
761    fpu_ymm10,
762    fpu_ymm11,
763    fpu_ymm12,
764    fpu_ymm13,
765    fpu_ymm14,
766    fpu_ymm15,
767    k_num_fpu_regs,
768
769    // Aliases
770    fpu_fctrl = fpu_fcw,
771    fpu_fstat = fpu_fsw,
772    fpu_ftag  = fpu_ftw,
773    fpu_fiseg = fpu_cs,
774    fpu_fioff = fpu_ip,
775    fpu_foseg = fpu_ds,
776    fpu_fooff = fpu_dp
777};
778
779enum {
780    exc_trapno,
781    exc_err,
782    exc_faultvaddr,
783    k_num_exc_regs,
784};
785
786
787enum gcc_dwarf_regnums
788{
789    gcc_dwarf_rax = 0,
790    gcc_dwarf_rdx = 1,
791    gcc_dwarf_rcx = 2,
792    gcc_dwarf_rbx = 3,
793    gcc_dwarf_rsi = 4,
794    gcc_dwarf_rdi = 5,
795    gcc_dwarf_rbp = 6,
796    gcc_dwarf_rsp = 7,
797    gcc_dwarf_r8,
798    gcc_dwarf_r9,
799    gcc_dwarf_r10,
800    gcc_dwarf_r11,
801    gcc_dwarf_r12,
802    gcc_dwarf_r13,
803    gcc_dwarf_r14,
804    gcc_dwarf_r15,
805    gcc_dwarf_rip,
806    gcc_dwarf_xmm0,
807    gcc_dwarf_xmm1,
808    gcc_dwarf_xmm2,
809    gcc_dwarf_xmm3,
810    gcc_dwarf_xmm4,
811    gcc_dwarf_xmm5,
812    gcc_dwarf_xmm6,
813    gcc_dwarf_xmm7,
814    gcc_dwarf_xmm8,
815    gcc_dwarf_xmm9,
816    gcc_dwarf_xmm10,
817    gcc_dwarf_xmm11,
818    gcc_dwarf_xmm12,
819    gcc_dwarf_xmm13,
820    gcc_dwarf_xmm14,
821    gcc_dwarf_xmm15,
822    gcc_dwarf_stmm0,
823    gcc_dwarf_stmm1,
824    gcc_dwarf_stmm2,
825    gcc_dwarf_stmm3,
826    gcc_dwarf_stmm4,
827    gcc_dwarf_stmm5,
828    gcc_dwarf_stmm6,
829    gcc_dwarf_stmm7,
830    gcc_dwarf_ymm0 = gcc_dwarf_xmm0,
831    gcc_dwarf_ymm1 = gcc_dwarf_xmm1,
832    gcc_dwarf_ymm2 = gcc_dwarf_xmm2,
833    gcc_dwarf_ymm3 = gcc_dwarf_xmm3,
834    gcc_dwarf_ymm4 = gcc_dwarf_xmm4,
835    gcc_dwarf_ymm5 = gcc_dwarf_xmm5,
836    gcc_dwarf_ymm6 = gcc_dwarf_xmm6,
837    gcc_dwarf_ymm7 = gcc_dwarf_xmm7,
838    gcc_dwarf_ymm8 = gcc_dwarf_xmm8,
839    gcc_dwarf_ymm9 = gcc_dwarf_xmm9,
840    gcc_dwarf_ymm10 = gcc_dwarf_xmm10,
841    gcc_dwarf_ymm11 = gcc_dwarf_xmm11,
842    gcc_dwarf_ymm12 = gcc_dwarf_xmm12,
843    gcc_dwarf_ymm13 = gcc_dwarf_xmm13,
844    gcc_dwarf_ymm14 = gcc_dwarf_xmm14,
845    gcc_dwarf_ymm15 = gcc_dwarf_xmm15
846};
847
848enum gdb_regnums
849{
850    gdb_rax     =   0,
851    gdb_rbx     =   1,
852    gdb_rcx     =   2,
853    gdb_rdx     =   3,
854    gdb_rsi     =   4,
855    gdb_rdi     =   5,
856    gdb_rbp     =   6,
857    gdb_rsp     =   7,
858    gdb_r8      =   8,
859    gdb_r9      =   9,
860    gdb_r10     =  10,
861    gdb_r11     =  11,
862    gdb_r12     =  12,
863    gdb_r13     =  13,
864    gdb_r14     =  14,
865    gdb_r15     =  15,
866    gdb_rip     =  16,
867    gdb_rflags  =  17,
868    gdb_cs      =  18,
869    gdb_ss      =  19,
870    gdb_ds      =  20,
871    gdb_es      =  21,
872    gdb_fs      =  22,
873    gdb_gs      =  23,
874    gdb_stmm0   =  24,
875    gdb_stmm1   =  25,
876    gdb_stmm2   =  26,
877    gdb_stmm3   =  27,
878    gdb_stmm4   =  28,
879    gdb_stmm5   =  29,
880    gdb_stmm6   =  30,
881    gdb_stmm7   =  31,
882    gdb_fctrl   =  32,  gdb_fcw = gdb_fctrl,
883    gdb_fstat   =  33,  gdb_fsw = gdb_fstat,
884    gdb_ftag    =  34,  gdb_ftw = gdb_ftag,
885    gdb_fiseg   =  35,  gdb_fpu_cs  = gdb_fiseg,
886    gdb_fioff   =  36,  gdb_ip  = gdb_fioff,
887    gdb_foseg   =  37,  gdb_fpu_ds  = gdb_foseg,
888    gdb_fooff   =  38,  gdb_dp  = gdb_fooff,
889    gdb_fop     =  39,
890    gdb_xmm0    =  40,
891    gdb_xmm1    =  41,
892    gdb_xmm2    =  42,
893    gdb_xmm3    =  43,
894    gdb_xmm4    =  44,
895    gdb_xmm5    =  45,
896    gdb_xmm6    =  46,
897    gdb_xmm7    =  47,
898    gdb_xmm8    =  48,
899    gdb_xmm9    =  49,
900    gdb_xmm10   =  50,
901    gdb_xmm11   =  51,
902    gdb_xmm12   =  52,
903    gdb_xmm13   =  53,
904    gdb_xmm14   =  54,
905    gdb_xmm15   =  55,
906    gdb_mxcsr   =  56,
907    gdb_ymm0    =  gdb_xmm0,
908    gdb_ymm1    =  gdb_xmm1,
909    gdb_ymm2    =  gdb_xmm2,
910    gdb_ymm3    =  gdb_xmm3,
911    gdb_ymm4    =  gdb_xmm4,
912    gdb_ymm5    =  gdb_xmm5,
913    gdb_ymm6    =  gdb_xmm6,
914    gdb_ymm7    =  gdb_xmm7,
915    gdb_ymm8    =  gdb_xmm8,
916    gdb_ymm9    =  gdb_xmm9,
917    gdb_ymm10   =  gdb_xmm10,
918    gdb_ymm11   =  gdb_xmm11,
919    gdb_ymm12   =  gdb_xmm12,
920    gdb_ymm13   =  gdb_xmm13,
921    gdb_ymm14   =  gdb_xmm14,
922    gdb_ymm15   =  gdb_xmm15
923};
924
925#define GPR_OFFSET(reg) (offsetof (DNBArchImplX86_64::GPR, __##reg))
926#define FPU_OFFSET(reg) (offsetof (DNBArchImplX86_64::FPU, __fpu_##reg) + offsetof (DNBArchImplX86_64::Context, fpu.no_avx))
927#define AVX_OFFSET(reg) (offsetof (DNBArchImplX86_64::AVX, __fpu_##reg) + offsetof (DNBArchImplX86_64::Context, fpu.avx))
928#define EXC_OFFSET(reg) (offsetof (DNBArchImplX86_64::EXC, __##reg)     + offsetof (DNBArchImplX86_64::Context, exc))
929
930// This does not accurately identify the location of ymm0...7 in
931// Context.fpu.avx.  That is because there is a bunch of padding
932// in Context.fpu.avx that we don't need.  Offset macros lay out
933// the register state that Debugserver transmits to the debugger
934// -- not to interpret the thread_get_state info.
935#define AVX_OFFSET_YMM(n)   (AVX_OFFSET(xmm7) + FPU_SIZE_XMM(xmm7) + (32 * n))
936
937#define GPR_SIZE(reg)       (sizeof(((DNBArchImplX86_64::GPR *)NULL)->__##reg))
938#define FPU_SIZE_UINT(reg)  (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg))
939#define FPU_SIZE_MMST(reg)  (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__mmst_reg))
940#define FPU_SIZE_XMM(reg)   (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__xmm_reg))
941#define FPU_SIZE_YMM(reg)   (32)
942#define EXC_SIZE(reg)       (sizeof(((DNBArchImplX86_64::EXC *)NULL)->__##reg))
943
944// These macros will auto define the register name, alt name, register size,
945// register offset, encoding, format and native register. This ensures that
946// the register state structures are defined correctly and have the correct
947// sizes and offsets.
948#define DEFINE_GPR(reg) { e_regSetGPR, gpr_##reg, #reg, NULL, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), gcc_dwarf_##reg, gcc_dwarf_##reg, INVALID_NUB_REGNUM, gdb_##reg }
949#define DEFINE_GPR_ALT(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), gcc_dwarf_##reg, gcc_dwarf_##reg, gen, gdb_##reg }
950#define DEFINE_GPR_ALT2(reg, alt) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gdb_##reg }
951#define DEFINE_GPR_ALT3(reg, alt, gen) { e_regSetGPR, gpr_##reg, #reg, alt, Uint, Hex, GPR_SIZE(reg), GPR_OFFSET(reg), INVALID_NUB_REGNUM, INVALID_NUB_REGNUM, gen, gdb_##reg }
952
953// General purpose registers for 64 bit
954const DNBRegisterInfo
955DNBArchImplX86_64::g_gpr_registers[] =
956{
957    DEFINE_GPR      (rax),
958    DEFINE_GPR      (rbx),
959    DEFINE_GPR_ALT  (rcx , "arg4", GENERIC_REGNUM_ARG4),
960    DEFINE_GPR_ALT  (rdx , "arg3", GENERIC_REGNUM_ARG3),
961    DEFINE_GPR_ALT  (rdi , "arg1", GENERIC_REGNUM_ARG1),
962    DEFINE_GPR_ALT  (rsi , "arg2", GENERIC_REGNUM_ARG2),
963    DEFINE_GPR_ALT  (rbp , "fp"  , GENERIC_REGNUM_FP),
964    DEFINE_GPR_ALT  (rsp , "sp"  , GENERIC_REGNUM_SP),
965    DEFINE_GPR_ALT  (r8  , "arg5", GENERIC_REGNUM_ARG5),
966    DEFINE_GPR_ALT  (r9  , "arg6", GENERIC_REGNUM_ARG6),
967    DEFINE_GPR      (r10),
968    DEFINE_GPR      (r11),
969    DEFINE_GPR      (r12),
970    DEFINE_GPR      (r13),
971    DEFINE_GPR      (r14),
972    DEFINE_GPR      (r15),
973    DEFINE_GPR_ALT  (rip , "pc", GENERIC_REGNUM_PC),
974    DEFINE_GPR_ALT3 (rflags, "flags", GENERIC_REGNUM_FLAGS),
975    DEFINE_GPR_ALT2 (cs,        NULL),
976    DEFINE_GPR_ALT2 (fs,        NULL),
977    DEFINE_GPR_ALT2 (gs,        NULL),
978};
979
980// Floating point registers 64 bit
981const DNBRegisterInfo
982DNBArchImplX86_64::g_fpu_registers_no_avx[] =
983{
984    { e_regSetFPU, fpu_fcw      , "fctrl"       , NULL, Uint, Hex, FPU_SIZE_UINT(fcw)       , FPU_OFFSET(fcw)       , -1, -1, -1, -1 },
985    { e_regSetFPU, fpu_fsw      , "fstat"       , NULL, Uint, Hex, FPU_SIZE_UINT(fsw)       , FPU_OFFSET(fsw)       , -1, -1, -1, -1 },
986    { e_regSetFPU, fpu_ftw      , "ftag"        , NULL, Uint, Hex, FPU_SIZE_UINT(ftw)       , FPU_OFFSET(ftw)       , -1, -1, -1, -1 },
987    { e_regSetFPU, fpu_fop      , "fop"         , NULL, Uint, Hex, FPU_SIZE_UINT(fop)       , FPU_OFFSET(fop)       , -1, -1, -1, -1 },
988    { e_regSetFPU, fpu_ip       , "fioff"       , NULL, Uint, Hex, FPU_SIZE_UINT(ip)        , FPU_OFFSET(ip)        , -1, -1, -1, -1 },
989    { e_regSetFPU, fpu_cs       , "fiseg"       , NULL, Uint, Hex, FPU_SIZE_UINT(cs)        , FPU_OFFSET(cs)        , -1, -1, -1, -1 },
990    { e_regSetFPU, fpu_dp       , "fooff"       , NULL, Uint, Hex, FPU_SIZE_UINT(dp)        , FPU_OFFSET(dp)        , -1, -1, -1, -1 },
991    { e_regSetFPU, fpu_ds       , "foseg"       , NULL, Uint, Hex, FPU_SIZE_UINT(ds)        , FPU_OFFSET(ds)        , -1, -1, -1, -1 },
992    { e_regSetFPU, fpu_mxcsr    , "mxcsr"       , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr)     , FPU_OFFSET(mxcsr)     , -1, -1, -1, -1 },
993    { e_regSetFPU, fpu_mxcsrmask, "mxcsrmask"   , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , FPU_OFFSET(mxcsrmask) , -1, -1, -1, -1 },
994
995    { e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), gcc_dwarf_stmm0, gcc_dwarf_stmm0, -1, gdb_stmm0 },
996    { e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), gcc_dwarf_stmm1, gcc_dwarf_stmm1, -1, gdb_stmm1 },
997    { e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), gcc_dwarf_stmm2, gcc_dwarf_stmm2, -1, gdb_stmm2 },
998    { e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), gcc_dwarf_stmm3, gcc_dwarf_stmm3, -1, gdb_stmm3 },
999    { e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), gcc_dwarf_stmm4, gcc_dwarf_stmm4, -1, gdb_stmm4 },
1000    { e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), gcc_dwarf_stmm5, gcc_dwarf_stmm5, -1, gdb_stmm5 },
1001    { e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), gcc_dwarf_stmm6, gcc_dwarf_stmm6, -1, gdb_stmm6 },
1002    { e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), gcc_dwarf_stmm7, gcc_dwarf_stmm7, -1, gdb_stmm7 },
1003
1004    { e_regSetFPU, fpu_xmm0 , "xmm0"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0)   , FPU_OFFSET(xmm0) , gcc_dwarf_xmm0 , gcc_dwarf_xmm0 , -1, gdb_xmm0 },
1005    { e_regSetFPU, fpu_xmm1 , "xmm1"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1)   , FPU_OFFSET(xmm1) , gcc_dwarf_xmm1 , gcc_dwarf_xmm1 , -1, gdb_xmm1 },
1006    { e_regSetFPU, fpu_xmm2 , "xmm2"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2)   , FPU_OFFSET(xmm2) , gcc_dwarf_xmm2 , gcc_dwarf_xmm2 , -1, gdb_xmm2 },
1007    { e_regSetFPU, fpu_xmm3 , "xmm3"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3)   , FPU_OFFSET(xmm3) , gcc_dwarf_xmm3 , gcc_dwarf_xmm3 , -1, gdb_xmm3 },
1008    { e_regSetFPU, fpu_xmm4 , "xmm4"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4)   , FPU_OFFSET(xmm4) , gcc_dwarf_xmm4 , gcc_dwarf_xmm4 , -1, gdb_xmm4 },
1009    { e_regSetFPU, fpu_xmm5 , "xmm5"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5)   , FPU_OFFSET(xmm5) , gcc_dwarf_xmm5 , gcc_dwarf_xmm5 , -1, gdb_xmm5 },
1010    { e_regSetFPU, fpu_xmm6 , "xmm6"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6)   , FPU_OFFSET(xmm6) , gcc_dwarf_xmm6 , gcc_dwarf_xmm6 , -1, gdb_xmm6 },
1011    { e_regSetFPU, fpu_xmm7 , "xmm7"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7)   , FPU_OFFSET(xmm7) , gcc_dwarf_xmm7 , gcc_dwarf_xmm7 , -1, gdb_xmm7 },
1012    { e_regSetFPU, fpu_xmm8 , "xmm8"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm8)   , FPU_OFFSET(xmm8) , gcc_dwarf_xmm8 , gcc_dwarf_xmm8 , -1, gdb_xmm8  },
1013    { e_regSetFPU, fpu_xmm9 , "xmm9"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm9)   , FPU_OFFSET(xmm9) , gcc_dwarf_xmm9 , gcc_dwarf_xmm9 , -1, gdb_xmm9  },
1014    { e_regSetFPU, fpu_xmm10, "xmm10"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm10)  , FPU_OFFSET(xmm10), gcc_dwarf_xmm10, gcc_dwarf_xmm10, -1, gdb_xmm10 },
1015    { e_regSetFPU, fpu_xmm11, "xmm11"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm11)  , FPU_OFFSET(xmm11), gcc_dwarf_xmm11, gcc_dwarf_xmm11, -1, gdb_xmm11 },
1016    { e_regSetFPU, fpu_xmm12, "xmm12"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm12)  , FPU_OFFSET(xmm12), gcc_dwarf_xmm12, gcc_dwarf_xmm12, -1, gdb_xmm12 },
1017    { e_regSetFPU, fpu_xmm13, "xmm13"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm13)  , FPU_OFFSET(xmm13), gcc_dwarf_xmm13, gcc_dwarf_xmm13, -1, gdb_xmm13 },
1018    { e_regSetFPU, fpu_xmm14, "xmm14"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm14)  , FPU_OFFSET(xmm14), gcc_dwarf_xmm14, gcc_dwarf_xmm14, -1, gdb_xmm14 },
1019    { e_regSetFPU, fpu_xmm15, "xmm15"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm15)  , FPU_OFFSET(xmm15), gcc_dwarf_xmm15, gcc_dwarf_xmm15, -1, gdb_xmm15 },
1020};
1021
1022const DNBRegisterInfo
1023DNBArchImplX86_64::g_fpu_registers_avx[] =
1024{
1025    { e_regSetFPU, fpu_fcw      , "fctrl"       , NULL, Uint, Hex, FPU_SIZE_UINT(fcw)       , AVX_OFFSET(fcw)       , -1, -1, -1, -1 },
1026    { e_regSetFPU, fpu_fsw      , "fstat"       , NULL, Uint, Hex, FPU_SIZE_UINT(fsw)       , AVX_OFFSET(fsw)       , -1, -1, -1, -1 },
1027    { e_regSetFPU, fpu_ftw      , "ftag"        , NULL, Uint, Hex, FPU_SIZE_UINT(ftw)       , AVX_OFFSET(ftw)       , -1, -1, -1, -1 },
1028    { e_regSetFPU, fpu_fop      , "fop"         , NULL, Uint, Hex, FPU_SIZE_UINT(fop)       , AVX_OFFSET(fop)       , -1, -1, -1, -1 },
1029    { e_regSetFPU, fpu_ip       , "fioff"       , NULL, Uint, Hex, FPU_SIZE_UINT(ip)        , AVX_OFFSET(ip)        , -1, -1, -1, -1 },
1030    { e_regSetFPU, fpu_cs       , "fiseg"       , NULL, Uint, Hex, FPU_SIZE_UINT(cs)        , AVX_OFFSET(cs)        , -1, -1, -1, -1 },
1031    { e_regSetFPU, fpu_dp       , "fooff"       , NULL, Uint, Hex, FPU_SIZE_UINT(dp)        , AVX_OFFSET(dp)        , -1, -1, -1, -1 },
1032    { e_regSetFPU, fpu_ds       , "foseg"       , NULL, Uint, Hex, FPU_SIZE_UINT(ds)        , AVX_OFFSET(ds)        , -1, -1, -1, -1 },
1033    { e_regSetFPU, fpu_mxcsr    , "mxcsr"       , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr)     , AVX_OFFSET(mxcsr)     , -1, -1, -1, -1 },
1034    { e_regSetFPU, fpu_mxcsrmask, "mxcsrmask"   , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , AVX_OFFSET(mxcsrmask) , -1, -1, -1, -1 },
1035
1036    { e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), AVX_OFFSET(stmm0), gcc_dwarf_stmm0, gcc_dwarf_stmm0, -1, gdb_stmm0 },
1037    { e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), AVX_OFFSET(stmm1), gcc_dwarf_stmm1, gcc_dwarf_stmm1, -1, gdb_stmm1 },
1038    { e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), AVX_OFFSET(stmm2), gcc_dwarf_stmm2, gcc_dwarf_stmm2, -1, gdb_stmm2 },
1039    { e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), AVX_OFFSET(stmm3), gcc_dwarf_stmm3, gcc_dwarf_stmm3, -1, gdb_stmm3 },
1040    { e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), AVX_OFFSET(stmm4), gcc_dwarf_stmm4, gcc_dwarf_stmm4, -1, gdb_stmm4 },
1041    { e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), AVX_OFFSET(stmm5), gcc_dwarf_stmm5, gcc_dwarf_stmm5, -1, gdb_stmm5 },
1042    { e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), AVX_OFFSET(stmm6), gcc_dwarf_stmm6, gcc_dwarf_stmm6, -1, gdb_stmm6 },
1043    { e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), AVX_OFFSET(stmm7), gcc_dwarf_stmm7, gcc_dwarf_stmm7, -1, gdb_stmm7 },
1044
1045    { e_regSetFPU, fpu_xmm0 , "xmm0"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0)   , AVX_OFFSET(xmm0) , gcc_dwarf_xmm0 , gcc_dwarf_xmm0 , -1, gdb_xmm0 },
1046    { e_regSetFPU, fpu_xmm1 , "xmm1"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1)   , AVX_OFFSET(xmm1) , gcc_dwarf_xmm1 , gcc_dwarf_xmm1 , -1, gdb_xmm1 },
1047    { e_regSetFPU, fpu_xmm2 , "xmm2"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2)   , AVX_OFFSET(xmm2) , gcc_dwarf_xmm2 , gcc_dwarf_xmm2 , -1, gdb_xmm2 },
1048    { e_regSetFPU, fpu_xmm3 , "xmm3"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3)   , AVX_OFFSET(xmm3) , gcc_dwarf_xmm3 , gcc_dwarf_xmm3 , -1, gdb_xmm3 },
1049    { e_regSetFPU, fpu_xmm4 , "xmm4"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4)   , AVX_OFFSET(xmm4) , gcc_dwarf_xmm4 , gcc_dwarf_xmm4 , -1, gdb_xmm4 },
1050    { e_regSetFPU, fpu_xmm5 , "xmm5"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5)   , AVX_OFFSET(xmm5) , gcc_dwarf_xmm5 , gcc_dwarf_xmm5 , -1, gdb_xmm5 },
1051    { e_regSetFPU, fpu_xmm6 , "xmm6"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6)   , AVX_OFFSET(xmm6) , gcc_dwarf_xmm6 , gcc_dwarf_xmm6 , -1, gdb_xmm6 },
1052    { e_regSetFPU, fpu_xmm7 , "xmm7"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7)   , AVX_OFFSET(xmm7) , gcc_dwarf_xmm7 , gcc_dwarf_xmm7 , -1, gdb_xmm7 },
1053    { e_regSetFPU, fpu_xmm8 , "xmm8"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm8)   , AVX_OFFSET(xmm8) , gcc_dwarf_xmm8 , gcc_dwarf_xmm8 , -1, gdb_xmm8  },
1054    { e_regSetFPU, fpu_xmm9 , "xmm9"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm9)   , AVX_OFFSET(xmm9) , gcc_dwarf_xmm9 , gcc_dwarf_xmm9 , -1, gdb_xmm9  },
1055    { e_regSetFPU, fpu_xmm10, "xmm10"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm10)  , AVX_OFFSET(xmm10), gcc_dwarf_xmm10, gcc_dwarf_xmm10, -1, gdb_xmm10 },
1056    { e_regSetFPU, fpu_xmm11, "xmm11"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm11)  , AVX_OFFSET(xmm11), gcc_dwarf_xmm11, gcc_dwarf_xmm11, -1, gdb_xmm11 },
1057    { e_regSetFPU, fpu_xmm12, "xmm12"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm12)  , AVX_OFFSET(xmm12), gcc_dwarf_xmm12, gcc_dwarf_xmm12, -1, gdb_xmm12 },
1058    { e_regSetFPU, fpu_xmm13, "xmm13"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm13)  , AVX_OFFSET(xmm13), gcc_dwarf_xmm13, gcc_dwarf_xmm13, -1, gdb_xmm13 },
1059    { e_regSetFPU, fpu_xmm14, "xmm14"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm14)  , AVX_OFFSET(xmm14), gcc_dwarf_xmm14, gcc_dwarf_xmm14, -1, gdb_xmm14 },
1060    { e_regSetFPU, fpu_xmm15, "xmm15"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm15)  , AVX_OFFSET(xmm15), gcc_dwarf_xmm15, gcc_dwarf_xmm15, -1, gdb_xmm15 },
1061
1062    { e_regSetFPU, fpu_ymm0 , "ymm0"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm0)   , AVX_OFFSET_YMM(0) , gcc_dwarf_ymm0 , gcc_dwarf_ymm0 , -1, gdb_ymm0 },
1063    { e_regSetFPU, fpu_ymm1 , "ymm1"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm1)   , AVX_OFFSET_YMM(1) , gcc_dwarf_ymm1 , gcc_dwarf_ymm1 , -1, gdb_ymm1 },
1064    { e_regSetFPU, fpu_ymm2 , "ymm2"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm2)   , AVX_OFFSET_YMM(2) , gcc_dwarf_ymm2 , gcc_dwarf_ymm2 , -1, gdb_ymm2 },
1065    { e_regSetFPU, fpu_ymm3 , "ymm3"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm3)   , AVX_OFFSET_YMM(3) , gcc_dwarf_ymm3 , gcc_dwarf_ymm3 , -1, gdb_ymm3 },
1066    { e_regSetFPU, fpu_ymm4 , "ymm4"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm4)   , AVX_OFFSET_YMM(4) , gcc_dwarf_ymm4 , gcc_dwarf_ymm4 , -1, gdb_ymm4 },
1067    { e_regSetFPU, fpu_ymm5 , "ymm5"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm5)   , AVX_OFFSET_YMM(5) , gcc_dwarf_ymm5 , gcc_dwarf_ymm5 , -1, gdb_ymm5 },
1068    { e_regSetFPU, fpu_ymm6 , "ymm6"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm6)   , AVX_OFFSET_YMM(6) , gcc_dwarf_ymm6 , gcc_dwarf_ymm6 , -1, gdb_ymm6 },
1069    { e_regSetFPU, fpu_ymm7 , "ymm7"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm7)   , AVX_OFFSET_YMM(7) , gcc_dwarf_ymm7 , gcc_dwarf_ymm7 , -1, gdb_ymm7 },
1070    { e_regSetFPU, fpu_ymm8 , "ymm8"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm8)   , AVX_OFFSET_YMM(8) , gcc_dwarf_ymm8 , gcc_dwarf_ymm8 , -1, gdb_ymm8  },
1071    { e_regSetFPU, fpu_ymm9 , "ymm9"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm9)   , AVX_OFFSET_YMM(9) , gcc_dwarf_ymm9 , gcc_dwarf_ymm9 , -1, gdb_ymm9  },
1072    { e_regSetFPU, fpu_ymm10, "ymm10"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm10)  , AVX_OFFSET_YMM(10), gcc_dwarf_ymm10, gcc_dwarf_ymm10, -1, gdb_ymm10 },
1073    { e_regSetFPU, fpu_ymm11, "ymm11"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm11)  , AVX_OFFSET_YMM(11), gcc_dwarf_ymm11, gcc_dwarf_ymm11, -1, gdb_ymm11 },
1074    { e_regSetFPU, fpu_ymm12, "ymm12"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm12)  , AVX_OFFSET_YMM(12), gcc_dwarf_ymm12, gcc_dwarf_ymm12, -1, gdb_ymm12 },
1075    { e_regSetFPU, fpu_ymm13, "ymm13"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm13)  , AVX_OFFSET_YMM(13), gcc_dwarf_ymm13, gcc_dwarf_ymm13, -1, gdb_ymm13 },
1076    { e_regSetFPU, fpu_ymm14, "ymm14"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm14)  , AVX_OFFSET_YMM(14), gcc_dwarf_ymm14, gcc_dwarf_ymm14, -1, gdb_ymm14 },
1077    { e_regSetFPU, fpu_ymm15, "ymm15"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_YMM(ymm15)  , AVX_OFFSET_YMM(15), gcc_dwarf_ymm15, gcc_dwarf_ymm15, -1, gdb_ymm15 }
1078};
1079
1080// Exception registers
1081
1082const DNBRegisterInfo
1083DNBArchImplX86_64::g_exc_registers[] =
1084{
1085    { e_regSetEXC, exc_trapno,      "trapno"    , NULL, Uint, Hex, EXC_SIZE (trapno)    , EXC_OFFSET (trapno)       , -1, -1, -1, -1 },
1086    { e_regSetEXC, exc_err,         "err"       , NULL, Uint, Hex, EXC_SIZE (err)       , EXC_OFFSET (err)          , -1, -1, -1, -1 },
1087    { e_regSetEXC, exc_faultvaddr,  "faultvaddr", NULL, Uint, Hex, EXC_SIZE (faultvaddr), EXC_OFFSET (faultvaddr)   , -1, -1, -1, -1 }
1088};
1089
1090// Number of registers in each register set
1091const size_t DNBArchImplX86_64::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo);
1092const size_t DNBArchImplX86_64::k_num_fpu_registers_no_avx = sizeof(g_fpu_registers_no_avx)/sizeof(DNBRegisterInfo);
1093const size_t DNBArchImplX86_64::k_num_fpu_registers_avx = sizeof(g_fpu_registers_avx)/sizeof(DNBRegisterInfo);
1094const size_t DNBArchImplX86_64::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo);
1095const size_t DNBArchImplX86_64::k_num_all_registers_no_avx = k_num_gpr_registers + k_num_fpu_registers_no_avx + k_num_exc_registers;
1096const size_t DNBArchImplX86_64::k_num_all_registers_avx = k_num_gpr_registers + k_num_fpu_registers_avx + k_num_exc_registers;
1097
1098//----------------------------------------------------------------------
1099// Register set definitions. The first definitions at register set index
1100// of zero is for all registers, followed by other registers sets. The
1101// register information for the all register set need not be filled in.
1102//----------------------------------------------------------------------
1103const DNBRegisterSetInfo
1104DNBArchImplX86_64::g_reg_sets_no_avx[] =
1105{
1106    { "x86_64 Registers",           NULL,               k_num_all_registers_no_avx },
1107    { "General Purpose Registers",  g_gpr_registers,    k_num_gpr_registers },
1108    { "Floating Point Registers",   g_fpu_registers_no_avx, k_num_fpu_registers_no_avx },
1109    { "Exception State Registers",  g_exc_registers,    k_num_exc_registers }
1110};
1111
1112const DNBRegisterSetInfo
1113DNBArchImplX86_64::g_reg_sets_avx[] =
1114{
1115    { "x86_64 Registers",           NULL,               k_num_all_registers_avx },
1116    { "General Purpose Registers",  g_gpr_registers,    k_num_gpr_registers },
1117    { "Floating Point Registers",   g_fpu_registers_avx, k_num_fpu_registers_avx },
1118    { "Exception State Registers",  g_exc_registers,    k_num_exc_registers }
1119};
1120
1121// Total number of register sets for this architecture
1122const size_t DNBArchImplX86_64::k_num_register_sets = sizeof(g_reg_sets_avx)/sizeof(DNBRegisterSetInfo);
1123
1124
1125DNBArchProtocol *
1126DNBArchImplX86_64::Create (MachThread *thread)
1127{
1128    return new DNBArchImplX86_64 (thread);
1129}
1130
1131const uint8_t * const
1132DNBArchImplX86_64::SoftwareBreakpointOpcode (nub_size_t byte_size)
1133{
1134    static const uint8_t g_breakpoint_opcode[] = { 0xCC };
1135    if (byte_size == 1)
1136        return g_breakpoint_opcode;
1137    return NULL;
1138}
1139
1140const DNBRegisterSetInfo *
1141DNBArchImplX86_64::GetRegisterSetInfo(nub_size_t *num_reg_sets)
1142{
1143    *num_reg_sets = k_num_register_sets;
1144
1145    if (CPUHasAVX() || FORCE_AVX_REGS)
1146        return g_reg_sets_avx;
1147    else
1148        return g_reg_sets_no_avx;
1149}
1150
1151void
1152DNBArchImplX86_64::Initialize()
1153{
1154    DNBArchPluginInfo arch_plugin_info =
1155    {
1156        CPU_TYPE_X86_64,
1157        DNBArchImplX86_64::Create,
1158        DNBArchImplX86_64::GetRegisterSetInfo,
1159        DNBArchImplX86_64::SoftwareBreakpointOpcode
1160    };
1161
1162    // Register this arch plug-in with the main protocol class
1163    DNBArchProtocol::RegisterArchPlugin (arch_plugin_info);
1164}
1165
1166bool
1167DNBArchImplX86_64::GetRegisterValue(int set, int reg, DNBRegisterValue *value)
1168{
1169    if (set == REGISTER_SET_GENERIC)
1170    {
1171        switch (reg)
1172        {
1173            case GENERIC_REGNUM_PC:     // Program Counter
1174                set = e_regSetGPR;
1175                reg = gpr_rip;
1176                break;
1177
1178            case GENERIC_REGNUM_SP:     // Stack Pointer
1179                set = e_regSetGPR;
1180                reg = gpr_rsp;
1181                break;
1182
1183            case GENERIC_REGNUM_FP:     // Frame Pointer
1184                set = e_regSetGPR;
1185                reg = gpr_rbp;
1186                break;
1187
1188            case GENERIC_REGNUM_FLAGS:  // Processor flags register
1189                set = e_regSetGPR;
1190                reg = gpr_rflags;
1191                break;
1192
1193            case GENERIC_REGNUM_RA:     // Return Address
1194            default:
1195                return false;
1196        }
1197    }
1198
1199    if (GetRegisterState(set, false) != KERN_SUCCESS)
1200        return false;
1201
1202    const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
1203    if (regInfo)
1204    {
1205        value->info = *regInfo;
1206        switch (set)
1207        {
1208            case e_regSetGPR:
1209                if (reg < k_num_gpr_registers)
1210                {
1211                    value->value.uint64 = ((uint64_t*)(&m_state.context.gpr))[reg];
1212                    return true;
1213                }
1214                break;
1215
1216            case e_regSetFPU:
1217                if (CPUHasAVX() || FORCE_AVX_REGS)
1218                {
1219                    switch (reg)
1220                    {
1221                    case fpu_fcw:       value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw));    return true;
1222                    case fpu_fsw:       value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw));    return true;
1223                    case fpu_ftw:       value->value.uint8  = m_state.context.fpu.avx.__fpu_ftw;                      return true;
1224                    case fpu_fop:       value->value.uint16 = m_state.context.fpu.avx.__fpu_fop;                      return true;
1225                    case fpu_ip:        value->value.uint32 = m_state.context.fpu.avx.__fpu_ip;                       return true;
1226                    case fpu_cs:        value->value.uint16 = m_state.context.fpu.avx.__fpu_cs;                       return true;
1227                    case fpu_dp:        value->value.uint32 = m_state.context.fpu.avx.__fpu_dp;                       return true;
1228                    case fpu_ds:        value->value.uint16 = m_state.context.fpu.avx.__fpu_ds;                       return true;
1229                    case fpu_mxcsr:     value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsr;                    return true;
1230                    case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.avx.__fpu_mxcsrmask;                return true;
1231
1232                    case fpu_stmm0:
1233                    case fpu_stmm1:
1234                    case fpu_stmm2:
1235                    case fpu_stmm3:
1236                    case fpu_stmm4:
1237                    case fpu_stmm5:
1238                    case fpu_stmm6:
1239                    case fpu_stmm7:
1240                        memcpy(&value->value.uint8, &m_state.context.fpu.avx.__fpu_stmm0 + (reg - fpu_stmm0), 10);
1241                        return true;
1242
1243                    case fpu_xmm0:
1244                    case fpu_xmm1:
1245                    case fpu_xmm2:
1246                    case fpu_xmm3:
1247                    case fpu_xmm4:
1248                    case fpu_xmm5:
1249                    case fpu_xmm6:
1250                    case fpu_xmm7:
1251                    case fpu_xmm8:
1252                    case fpu_xmm9:
1253                    case fpu_xmm10:
1254                    case fpu_xmm11:
1255                    case fpu_xmm12:
1256                    case fpu_xmm13:
1257                    case fpu_xmm14:
1258                    case fpu_xmm15:
1259                        memcpy(&value->value.uint8, &m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_xmm0), 16);
1260                        return true;
1261
1262                    case fpu_ymm0:
1263                    case fpu_ymm1:
1264                    case fpu_ymm2:
1265                    case fpu_ymm3:
1266                    case fpu_ymm4:
1267                    case fpu_ymm5:
1268                    case fpu_ymm6:
1269                    case fpu_ymm7:
1270                    case fpu_ymm8:
1271                    case fpu_ymm9:
1272                    case fpu_ymm10:
1273                    case fpu_ymm11:
1274                    case fpu_ymm12:
1275                    case fpu_ymm13:
1276                    case fpu_ymm14:
1277                    case fpu_ymm15:
1278                        memcpy(&value->value.uint8, &m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), 16);
1279                        memcpy((&value->value.uint8) + 16, &m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), 16);
1280                        return true;
1281                    }
1282                }
1283                else
1284                {
1285                    switch (reg)
1286                    {
1287                        case fpu_fcw:       value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw));    return true;
1288                        case fpu_fsw:       value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw));    return true;
1289                        case fpu_ftw:       value->value.uint8  = m_state.context.fpu.no_avx.__fpu_ftw;                      return true;
1290                        case fpu_fop:       value->value.uint16 = m_state.context.fpu.no_avx.__fpu_fop;                      return true;
1291                        case fpu_ip:        value->value.uint32 = m_state.context.fpu.no_avx.__fpu_ip;                       return true;
1292                        case fpu_cs:        value->value.uint16 = m_state.context.fpu.no_avx.__fpu_cs;                       return true;
1293                        case fpu_dp:        value->value.uint32 = m_state.context.fpu.no_avx.__fpu_dp;                       return true;
1294                        case fpu_ds:        value->value.uint16 = m_state.context.fpu.no_avx.__fpu_ds;                       return true;
1295                        case fpu_mxcsr:     value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsr;                    return true;
1296                        case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.no_avx.__fpu_mxcsrmask;                return true;
1297
1298                        case fpu_stmm0:
1299                        case fpu_stmm1:
1300                        case fpu_stmm2:
1301                        case fpu_stmm3:
1302                        case fpu_stmm4:
1303                        case fpu_stmm5:
1304                        case fpu_stmm6:
1305                        case fpu_stmm7:
1306                            memcpy(&value->value.uint8, &m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0), 10);
1307                            return true;
1308
1309                        case fpu_xmm0:
1310                        case fpu_xmm1:
1311                        case fpu_xmm2:
1312                        case fpu_xmm3:
1313                        case fpu_xmm4:
1314                        case fpu_xmm5:
1315                        case fpu_xmm6:
1316                        case fpu_xmm7:
1317                        case fpu_xmm8:
1318                        case fpu_xmm9:
1319                        case fpu_xmm10:
1320                        case fpu_xmm11:
1321                        case fpu_xmm12:
1322                        case fpu_xmm13:
1323                        case fpu_xmm14:
1324                        case fpu_xmm15:
1325                            memcpy(&value->value.uint8, &m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), 16);
1326                            return true;
1327                    }
1328                }
1329                break;
1330
1331            case e_regSetEXC:
1332                switch (reg)
1333                {
1334                case exc_trapno:    value->value.uint32 = m_state.context.exc.__trapno; return true;
1335                case exc_err:       value->value.uint32 = m_state.context.exc.__err; return true;
1336                case exc_faultvaddr:value->value.uint64 = m_state.context.exc.__faultvaddr; return true;
1337                }
1338                break;
1339        }
1340    }
1341    return false;
1342}
1343
1344
1345bool
1346DNBArchImplX86_64::SetRegisterValue(int set, int reg, const DNBRegisterValue *value)
1347{
1348    if (set == REGISTER_SET_GENERIC)
1349    {
1350        switch (reg)
1351        {
1352            case GENERIC_REGNUM_PC:     // Program Counter
1353                set = e_regSetGPR;
1354                reg = gpr_rip;
1355                break;
1356
1357            case GENERIC_REGNUM_SP:     // Stack Pointer
1358                set = e_regSetGPR;
1359                reg = gpr_rsp;
1360                break;
1361
1362            case GENERIC_REGNUM_FP:     // Frame Pointer
1363                set = e_regSetGPR;
1364                reg = gpr_rbp;
1365                break;
1366
1367            case GENERIC_REGNUM_FLAGS:  // Processor flags register
1368                set = e_regSetGPR;
1369                reg = gpr_rflags;
1370                break;
1371
1372            case GENERIC_REGNUM_RA:     // Return Address
1373            default:
1374                return false;
1375        }
1376    }
1377
1378    if (GetRegisterState(set, false) != KERN_SUCCESS)
1379        return false;
1380
1381    bool success = false;
1382    const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
1383    if (regInfo)
1384    {
1385        switch (set)
1386        {
1387            case e_regSetGPR:
1388                if (reg < k_num_gpr_registers)
1389                {
1390                    ((uint64_t*)(&m_state.context.gpr))[reg] = value->value.uint64;
1391                    success = true;
1392                }
1393                break;
1394
1395            case e_regSetFPU:
1396                if (CPUHasAVX() || FORCE_AVX_REGS)
1397                {
1398                    switch (reg)
1399                    {
1400                    case fpu_fcw:       *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fcw)) = value->value.uint16;    success = true; break;
1401                    case fpu_fsw:       *((uint16_t *)(&m_state.context.fpu.avx.__fpu_fsw)) = value->value.uint16;    success = true; break;
1402                    case fpu_ftw:       m_state.context.fpu.avx.__fpu_ftw = value->value.uint8;                       success = true; break;
1403                    case fpu_fop:       m_state.context.fpu.avx.__fpu_fop = value->value.uint16;                      success = true; break;
1404                    case fpu_ip:        m_state.context.fpu.avx.__fpu_ip = value->value.uint32;                       success = true; break;
1405                    case fpu_cs:        m_state.context.fpu.avx.__fpu_cs = value->value.uint16;                       success = true; break;
1406                    case fpu_dp:        m_state.context.fpu.avx.__fpu_dp = value->value.uint32;                       success = true; break;
1407                    case fpu_ds:        m_state.context.fpu.avx.__fpu_ds = value->value.uint16;                       success = true; break;
1408                    case fpu_mxcsr:     m_state.context.fpu.avx.__fpu_mxcsr = value->value.uint32;                    success = true; break;
1409                    case fpu_mxcsrmask: m_state.context.fpu.avx.__fpu_mxcsrmask = value->value.uint32;                success = true; break;
1410
1411                    case fpu_stmm0:
1412                    case fpu_stmm1:
1413                    case fpu_stmm2:
1414                    case fpu_stmm3:
1415                    case fpu_stmm4:
1416                    case fpu_stmm5:
1417                    case fpu_stmm6:
1418                    case fpu_stmm7:
1419                        memcpy (&m_state.context.fpu.avx.__fpu_stmm0 + (reg - fpu_stmm0), &value->value.uint8, 10);
1420                        success = true;
1421                        break;
1422
1423                    case fpu_xmm0:
1424                    case fpu_xmm1:
1425                    case fpu_xmm2:
1426                    case fpu_xmm3:
1427                    case fpu_xmm4:
1428                    case fpu_xmm5:
1429                    case fpu_xmm6:
1430                    case fpu_xmm7:
1431                    case fpu_xmm8:
1432                    case fpu_xmm9:
1433                    case fpu_xmm10:
1434                    case fpu_xmm11:
1435                    case fpu_xmm12:
1436                    case fpu_xmm13:
1437                    case fpu_xmm14:
1438                    case fpu_xmm15:
1439                        memcpy (&m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_xmm0), &value->value.uint8, 16);
1440                        success = true;
1441                        break;
1442
1443                    case fpu_ymm0:
1444                    case fpu_ymm1:
1445                    case fpu_ymm2:
1446                    case fpu_ymm3:
1447                    case fpu_ymm4:
1448                    case fpu_ymm5:
1449                    case fpu_ymm6:
1450                    case fpu_ymm7:
1451                    case fpu_ymm8:
1452                    case fpu_ymm9:
1453                    case fpu_ymm10:
1454                    case fpu_ymm11:
1455                    case fpu_ymm12:
1456                    case fpu_ymm13:
1457                    case fpu_ymm14:
1458                    case fpu_ymm15:
1459                        memcpy(&m_state.context.fpu.avx.__fpu_xmm0 + (reg - fpu_ymm0), &value->value.uint8, 16);
1460                        memcpy(&m_state.context.fpu.avx.__fpu_ymmh0 + (reg - fpu_ymm0), (&value->value.uint8) + 16, 16);
1461                        return true;
1462                    }
1463                }
1464                else
1465                {
1466                    switch (reg)
1467                    {
1468                    case fpu_fcw:       *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fcw)) = value->value.uint16;    success = true; break;
1469                    case fpu_fsw:       *((uint16_t *)(&m_state.context.fpu.no_avx.__fpu_fsw)) = value->value.uint16;    success = true; break;
1470                    case fpu_ftw:       m_state.context.fpu.no_avx.__fpu_ftw = value->value.uint8;                       success = true; break;
1471                    case fpu_fop:       m_state.context.fpu.no_avx.__fpu_fop = value->value.uint16;                      success = true; break;
1472                    case fpu_ip:        m_state.context.fpu.no_avx.__fpu_ip = value->value.uint32;                       success = true; break;
1473                    case fpu_cs:        m_state.context.fpu.no_avx.__fpu_cs = value->value.uint16;                       success = true; break;
1474                    case fpu_dp:        m_state.context.fpu.no_avx.__fpu_dp = value->value.uint32;                       success = true; break;
1475                    case fpu_ds:        m_state.context.fpu.no_avx.__fpu_ds = value->value.uint16;                       success = true; break;
1476                    case fpu_mxcsr:     m_state.context.fpu.no_avx.__fpu_mxcsr = value->value.uint32;                    success = true; break;
1477                    case fpu_mxcsrmask: m_state.context.fpu.no_avx.__fpu_mxcsrmask = value->value.uint32;                success = true; break;
1478
1479                    case fpu_stmm0:
1480                    case fpu_stmm1:
1481                    case fpu_stmm2:
1482                    case fpu_stmm3:
1483                    case fpu_stmm4:
1484                    case fpu_stmm5:
1485                    case fpu_stmm6:
1486                    case fpu_stmm7:
1487                        memcpy (&m_state.context.fpu.no_avx.__fpu_stmm0 + (reg - fpu_stmm0), &value->value.uint8, 10);
1488                        success = true;
1489                        break;
1490
1491                    case fpu_xmm0:
1492                    case fpu_xmm1:
1493                    case fpu_xmm2:
1494                    case fpu_xmm3:
1495                    case fpu_xmm4:
1496                    case fpu_xmm5:
1497                    case fpu_xmm6:
1498                    case fpu_xmm7:
1499                    case fpu_xmm8:
1500                    case fpu_xmm9:
1501                    case fpu_xmm10:
1502                    case fpu_xmm11:
1503                    case fpu_xmm12:
1504                    case fpu_xmm13:
1505                    case fpu_xmm14:
1506                    case fpu_xmm15:
1507                        memcpy (&m_state.context.fpu.no_avx.__fpu_xmm0 + (reg - fpu_xmm0), &value->value.uint8, 16);
1508                        success = true;
1509                        break;
1510                    }
1511                }
1512                break;
1513
1514            case e_regSetEXC:
1515                switch (reg)
1516            {
1517                case exc_trapno:    m_state.context.exc.__trapno = value->value.uint32;     success = true; break;
1518                case exc_err:       m_state.context.exc.__err = value->value.uint32;        success = true; break;
1519                case exc_faultvaddr:m_state.context.exc.__faultvaddr = value->value.uint64; success = true; break;
1520            }
1521                break;
1522        }
1523    }
1524
1525    if (success)
1526        return SetRegisterState(set) == KERN_SUCCESS;
1527    return false;
1528}
1529
1530
1531nub_size_t
1532DNBArchImplX86_64::GetRegisterContext (void *buf, nub_size_t buf_len)
1533{
1534    nub_size_t size = sizeof (m_state.context);
1535
1536    if (buf && buf_len)
1537    {
1538        if (size > buf_len)
1539            size = buf_len;
1540
1541        bool force = false;
1542        if (GetGPRState(force) | GetFPUState(force) | GetEXCState(force))
1543            return 0;
1544        ::memcpy (buf, &m_state.context, size);
1545    }
1546    DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size);
1547    // Return the size of the register context even if NULL was passed in
1548    return size;
1549}
1550
1551nub_size_t
1552DNBArchImplX86_64::SetRegisterContext (const void *buf, nub_size_t buf_len)
1553{
1554    nub_size_t size = sizeof (m_state.context);
1555    if (buf == NULL || buf_len == 0)
1556        size = 0;
1557
1558    if (size)
1559    {
1560        if (size > buf_len)
1561            size = buf_len;
1562
1563        ::memcpy (&m_state.context, buf, size);
1564        SetGPRState();
1565        SetFPUState();
1566        SetEXCState();
1567    }
1568    DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size);
1569    return size;
1570}
1571
1572
1573kern_return_t
1574DNBArchImplX86_64::GetRegisterState(int set, bool force)
1575{
1576    switch (set)
1577    {
1578        case e_regSetALL:    return GetGPRState(force) | GetFPUState(force) | GetEXCState(force);
1579        case e_regSetGPR:    return GetGPRState(force);
1580        case e_regSetFPU:    return GetFPUState(force);
1581        case e_regSetEXC:    return GetEXCState(force);
1582        default: break;
1583    }
1584    return KERN_INVALID_ARGUMENT;
1585}
1586
1587kern_return_t
1588DNBArchImplX86_64::SetRegisterState(int set)
1589{
1590    // Make sure we have a valid context to set.
1591    if (RegisterSetStateIsValid(set))
1592    {
1593        switch (set)
1594        {
1595            case e_regSetALL:    return SetGPRState() | SetFPUState() | SetEXCState();
1596            case e_regSetGPR:    return SetGPRState();
1597            case e_regSetFPU:    return SetFPUState();
1598            case e_regSetEXC:    return SetEXCState();
1599            default: break;
1600        }
1601    }
1602    return KERN_INVALID_ARGUMENT;
1603}
1604
1605bool
1606DNBArchImplX86_64::RegisterSetStateIsValid (int set) const
1607{
1608    return m_state.RegsAreValid(set);
1609}
1610
1611
1612
1613#endif    // #if defined (__i386__) || defined (__x86_64__)
1614