DNBArchImplX86_64.cpp revision c71899ef308e6134d1b0ca5f30cbc64414855e1a
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
23uint64_t
24DNBArchImplX86_64::GetPC(uint64_t failValue)
25{
26    // Get program counter
27    if (GetGPRState(false) == KERN_SUCCESS)
28        return m_state.context.gpr.__rip;
29    return failValue;
30}
31
32kern_return_t
33DNBArchImplX86_64::SetPC(uint64_t value)
34{
35    // Get program counter
36    kern_return_t err = GetGPRState(false);
37    if (err == KERN_SUCCESS)
38    {
39        m_state.context.gpr.__rip = value;
40        err = SetGPRState();
41    }
42    return err == KERN_SUCCESS;
43}
44
45uint64_t
46DNBArchImplX86_64::GetSP(uint64_t failValue)
47{
48    // Get stack pointer
49    if (GetGPRState(false) == KERN_SUCCESS)
50        return m_state.context.gpr.__rsp;
51    return failValue;
52}
53
54// Uncomment the value below to verify the values in the debugger.
55//#define DEBUG_GPR_VALUES 1    // DO NOT CHECK IN WITH THIS DEFINE ENABLED
56
57kern_return_t
58DNBArchImplX86_64::GetGPRState(bool force)
59{
60    if (force || m_state.GetError(e_regSetGPR, Read))
61    {
62#if DEBUG_GPR_VALUES
63        m_state.context.gpr.__rax = ('a' << 8) + 'x';
64        m_state.context.gpr.__rbx = ('b' << 8) + 'x';
65        m_state.context.gpr.__rcx = ('c' << 8) + 'x';
66        m_state.context.gpr.__rdx = ('d' << 8) + 'x';
67        m_state.context.gpr.__rdi = ('d' << 8) + 'i';
68        m_state.context.gpr.__rsi = ('s' << 8) + 'i';
69        m_state.context.gpr.__rbp = ('b' << 8) + 'p';
70        m_state.context.gpr.__rsp = ('s' << 8) + 'p';
71        m_state.context.gpr.__r8  = ('r' << 8) + '8';
72        m_state.context.gpr.__r9  = ('r' << 8) + '9';
73        m_state.context.gpr.__r10 = ('r' << 8) + 'a';
74        m_state.context.gpr.__r11 = ('r' << 8) + 'b';
75        m_state.context.gpr.__r12 = ('r' << 8) + 'c';
76        m_state.context.gpr.__r13 = ('r' << 8) + 'd';
77        m_state.context.gpr.__r14 = ('r' << 8) + 'e';
78        m_state.context.gpr.__r15 = ('r' << 8) + 'f';
79        m_state.context.gpr.__rip = ('i' << 8) + 'p';
80        m_state.context.gpr.__rflags = ('f' << 8) + 'l';
81        m_state.context.gpr.__cs = ('c' << 8) + 's';
82        m_state.context.gpr.__fs = ('f' << 8) + 's';
83        m_state.context.gpr.__gs = ('g' << 8) + 's';
84        m_state.SetError(e_regSetGPR, Read, 0);
85#else
86        mach_msg_type_number_t count = x86_THREAD_STATE64_COUNT;
87        m_state.SetError(e_regSetGPR, Read, ::thread_get_state(m_thread->ThreadID(), x86_THREAD_STATE64, (thread_state_t)&m_state.context.gpr, &count));
88        DNBLogThreadedIf (LOG_THREAD, "::thread_get_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x"
89                          "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx"
90                          "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx"
91                          "\n\t r8 = %16.16llx  r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx"
92                          "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx"
93                          "\n\trip = %16.16llx"
94                          "\n\tflg = %16.16llx  cs = %16.16llx  fs = %16.16llx  gs = %16.16llx",
95                          m_thread->ThreadID(), x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT,
96                          m_state.GetError(e_regSetGPR, Read),
97                          m_state.context.gpr.__rax,m_state.context.gpr.__rbx,m_state.context.gpr.__rcx,
98                          m_state.context.gpr.__rdx,m_state.context.gpr.__rdi,m_state.context.gpr.__rsi,
99                          m_state.context.gpr.__rbp,m_state.context.gpr.__rsp,m_state.context.gpr.__r8,
100                          m_state.context.gpr.__r9, m_state.context.gpr.__r10,m_state.context.gpr.__r11,
101                          m_state.context.gpr.__r12,m_state.context.gpr.__r13,m_state.context.gpr.__r14,
102                          m_state.context.gpr.__r15,m_state.context.gpr.__rip,m_state.context.gpr.__rflags,
103                          m_state.context.gpr.__cs,m_state.context.gpr.__fs, m_state.context.gpr.__gs);
104
105        //      DNBLogThreadedIf (LOG_THREAD, "thread_get_state(0x%4.4x, %u, &gpr, %u) => 0x%8.8x"
106        //                        "\n\trax = %16.16llx"
107        //                        "\n\trbx = %16.16llx"
108        //                        "\n\trcx = %16.16llx"
109        //                        "\n\trdx = %16.16llx"
110        //                        "\n\trdi = %16.16llx"
111        //                        "\n\trsi = %16.16llx"
112        //                        "\n\trbp = %16.16llx"
113        //                        "\n\trsp = %16.16llx"
114        //                        "\n\t r8 = %16.16llx"
115        //                        "\n\t r9 = %16.16llx"
116        //                        "\n\tr10 = %16.16llx"
117        //                        "\n\tr11 = %16.16llx"
118        //                        "\n\tr12 = %16.16llx"
119        //                        "\n\tr13 = %16.16llx"
120        //                        "\n\tr14 = %16.16llx"
121        //                        "\n\tr15 = %16.16llx"
122        //                        "\n\trip = %16.16llx"
123        //                        "\n\tflg = %16.16llx"
124        //                        "\n\t cs = %16.16llx"
125        //                        "\n\t fs = %16.16llx"
126        //                        "\n\t gs = %16.16llx",
127        //                        m_thread->ThreadID(),
128        //                        x86_THREAD_STATE64,
129        //                        x86_THREAD_STATE64_COUNT,
130        //                        m_state.GetError(e_regSetGPR, Read),
131        //                        m_state.context.gpr.__rax,
132        //                        m_state.context.gpr.__rbx,
133        //                        m_state.context.gpr.__rcx,
134        //                        m_state.context.gpr.__rdx,
135        //                        m_state.context.gpr.__rdi,
136        //                        m_state.context.gpr.__rsi,
137        //                        m_state.context.gpr.__rbp,
138        //                        m_state.context.gpr.__rsp,
139        //                        m_state.context.gpr.__r8,
140        //                        m_state.context.gpr.__r9,
141        //                        m_state.context.gpr.__r10,
142        //                        m_state.context.gpr.__r11,
143        //                        m_state.context.gpr.__r12,
144        //                        m_state.context.gpr.__r13,
145        //                        m_state.context.gpr.__r14,
146        //                        m_state.context.gpr.__r15,
147        //                        m_state.context.gpr.__rip,
148        //                        m_state.context.gpr.__rflags,
149        //                        m_state.context.gpr.__cs,
150        //                        m_state.context.gpr.__fs,
151        //                        m_state.context.gpr.__gs);
152#endif
153    }
154    return m_state.GetError(e_regSetGPR, Read);
155}
156
157// Uncomment the value below to verify the values in the debugger.
158//#define DEBUG_FPU_VALUES 1    // DO NOT CHECK IN WITH THIS DEFINE ENABLED
159
160kern_return_t
161DNBArchImplX86_64::GetFPUState(bool force)
162{
163    if (force || m_state.GetError(e_regSetFPU, Read))
164    {
165#if DEBUG_FPU_VALUES
166        m_state.context.fpu.__fpu_reserved[0] = -1;
167        m_state.context.fpu.__fpu_reserved[1] = -1;
168        *(uint16_t *)&(m_state.context.fpu.__fpu_fcw) = 0x1234;
169        *(uint16_t *)&(m_state.context.fpu.__fpu_fsw) = 0x5678;
170        m_state.context.fpu.__fpu_ftw = 1;
171        m_state.context.fpu.__fpu_rsrv1 = UINT8_MAX;
172        m_state.context.fpu.__fpu_fop = 2;
173        m_state.context.fpu.__fpu_ip = 3;
174        m_state.context.fpu.__fpu_cs = 4;
175        m_state.context.fpu.__fpu_rsrv2 = 5;
176        m_state.context.fpu.__fpu_dp = 6;
177        m_state.context.fpu.__fpu_ds = 7;
178        m_state.context.fpu.__fpu_rsrv3 = UINT16_MAX;
179        m_state.context.fpu.__fpu_mxcsr = 8;
180        m_state.context.fpu.__fpu_mxcsrmask = 9;
181        int i;
182        for (i=0; i<16; ++i)
183        {
184            if (i<10)
185            {
186                m_state.context.fpu.__fpu_stmm0.__mmst_reg[i] = 'a';
187                m_state.context.fpu.__fpu_stmm1.__mmst_reg[i] = 'b';
188                m_state.context.fpu.__fpu_stmm2.__mmst_reg[i] = 'c';
189                m_state.context.fpu.__fpu_stmm3.__mmst_reg[i] = 'd';
190                m_state.context.fpu.__fpu_stmm4.__mmst_reg[i] = 'e';
191                m_state.context.fpu.__fpu_stmm5.__mmst_reg[i] = 'f';
192                m_state.context.fpu.__fpu_stmm6.__mmst_reg[i] = 'g';
193                m_state.context.fpu.__fpu_stmm7.__mmst_reg[i] = 'h';
194            }
195            else
196            {
197                m_state.context.fpu.__fpu_stmm0.__mmst_reg[i] = INT8_MIN;
198                m_state.context.fpu.__fpu_stmm1.__mmst_reg[i] = INT8_MIN;
199                m_state.context.fpu.__fpu_stmm2.__mmst_reg[i] = INT8_MIN;
200                m_state.context.fpu.__fpu_stmm3.__mmst_reg[i] = INT8_MIN;
201                m_state.context.fpu.__fpu_stmm4.__mmst_reg[i] = INT8_MIN;
202                m_state.context.fpu.__fpu_stmm5.__mmst_reg[i] = INT8_MIN;
203                m_state.context.fpu.__fpu_stmm6.__mmst_reg[i] = INT8_MIN;
204                m_state.context.fpu.__fpu_stmm7.__mmst_reg[i] = INT8_MIN;
205            }
206
207            m_state.context.fpu.__fpu_xmm0.__xmm_reg[i] = '0';
208            m_state.context.fpu.__fpu_xmm1.__xmm_reg[i] = '1';
209            m_state.context.fpu.__fpu_xmm2.__xmm_reg[i] = '2';
210            m_state.context.fpu.__fpu_xmm3.__xmm_reg[i] = '3';
211            m_state.context.fpu.__fpu_xmm4.__xmm_reg[i] = '4';
212            m_state.context.fpu.__fpu_xmm5.__xmm_reg[i] = '5';
213            m_state.context.fpu.__fpu_xmm6.__xmm_reg[i] = '6';
214            m_state.context.fpu.__fpu_xmm7.__xmm_reg[i] = '7';
215            m_state.context.fpu.__fpu_xmm8.__xmm_reg[i] = '8';
216            m_state.context.fpu.__fpu_xmm9.__xmm_reg[i] = '9';
217            m_state.context.fpu.__fpu_xmm10.__xmm_reg[i] = 'A';
218            m_state.context.fpu.__fpu_xmm11.__xmm_reg[i] = 'B';
219            m_state.context.fpu.__fpu_xmm12.__xmm_reg[i] = 'C';
220            m_state.context.fpu.__fpu_xmm13.__xmm_reg[i] = 'D';
221            m_state.context.fpu.__fpu_xmm14.__xmm_reg[i] = 'E';
222            m_state.context.fpu.__fpu_xmm15.__xmm_reg[i] = 'F';
223        }
224        for (i=0; i<sizeof(m_state.context.fpu.__fpu_rsrv4); ++i)
225            m_state.context.fpu.__fpu_rsrv4[i] = INT8_MIN;
226        m_state.context.fpu.__fpu_reserved1 = -1;
227        m_state.SetError(e_regSetFPU, Read, 0);
228#else
229        mach_msg_type_number_t count = x86_FLOAT_STATE64_COUNT;
230        m_state.SetError(e_regSetFPU, Read, ::thread_get_state(m_thread->ThreadID(), x86_FLOAT_STATE64, (thread_state_t)&m_state.context.fpu, &count));
231#endif
232    }
233    return m_state.GetError(e_regSetFPU, Read);
234}
235
236kern_return_t
237DNBArchImplX86_64::GetEXCState(bool force)
238{
239    if (force || m_state.GetError(e_regSetEXC, Read))
240    {
241        mach_msg_type_number_t count = X86_EXCEPTION_STATE64_COUNT;
242        m_state.SetError(e_regSetEXC, Read, ::thread_get_state(m_thread->ThreadID(), x86_EXCEPTION_STATE64, (thread_state_t)&m_state.context.exc, &count));
243    }
244    return m_state.GetError(e_regSetEXC, Read);
245}
246
247kern_return_t
248DNBArchImplX86_64::SetGPRState()
249{
250    m_state.SetError(e_regSetGPR, Write, ::thread_set_state(m_thread->ThreadID(), x86_THREAD_STATE64, (thread_state_t)&m_state.context.gpr, x86_THREAD_STATE64_COUNT));
251    DNBLogThreadedIf (LOG_THREAD, "::thread_set_state (0x%4.4x, %u, &gpr, %u) => 0x%8.8x"
252                      "\n\trax = %16.16llx rbx = %16.16llx rcx = %16.16llx rdx = %16.16llx"
253                      "\n\trdi = %16.16llx rsi = %16.16llx rbp = %16.16llx rsp = %16.16llx"
254                      "\n\t r8 = %16.16llx  r9 = %16.16llx r10 = %16.16llx r11 = %16.16llx"
255                      "\n\tr12 = %16.16llx r13 = %16.16llx r14 = %16.16llx r15 = %16.16llx"
256                      "\n\trip = %16.16llx"
257                      "\n\tflg = %16.16llx  cs = %16.16llx  fs = %16.16llx  gs = %16.16llx",
258                      m_thread->ThreadID(), x86_THREAD_STATE64, x86_THREAD_STATE64_COUNT,
259                      m_state.GetError(e_regSetGPR, Write),
260                      m_state.context.gpr.__rax,m_state.context.gpr.__rbx,m_state.context.gpr.__rcx,
261                      m_state.context.gpr.__rdx,m_state.context.gpr.__rdi,m_state.context.gpr.__rsi,
262                      m_state.context.gpr.__rbp,m_state.context.gpr.__rsp,m_state.context.gpr.__r8,
263                      m_state.context.gpr.__r9, m_state.context.gpr.__r10,m_state.context.gpr.__r11,
264                      m_state.context.gpr.__r12,m_state.context.gpr.__r13,m_state.context.gpr.__r14,
265                      m_state.context.gpr.__r15,m_state.context.gpr.__rip,m_state.context.gpr.__rflags,
266                      m_state.context.gpr.__cs, m_state.context.gpr.__fs, m_state.context.gpr.__gs);
267    return m_state.GetError(e_regSetGPR, Write);
268}
269
270kern_return_t
271DNBArchImplX86_64::SetFPUState()
272{
273    m_state.SetError(e_regSetFPU, Write, ::thread_set_state(m_thread->ThreadID(), x86_FLOAT_STATE64, (thread_state_t)&m_state.context.fpu, x86_FLOAT_STATE64_COUNT));
274    return m_state.GetError(e_regSetFPU, Write);
275}
276
277kern_return_t
278DNBArchImplX86_64::SetEXCState()
279{
280    m_state.SetError(e_regSetEXC, Write, ::thread_set_state(m_thread->ThreadID(), x86_EXCEPTION_STATE64, (thread_state_t)&m_state.context.exc, X86_EXCEPTION_STATE64_COUNT));
281    return m_state.GetError(e_regSetEXC, Write);
282}
283
284void
285DNBArchImplX86_64::ThreadWillResume()
286{
287    // Do we need to step this thread? If so, let the mach thread tell us so.
288    if (m_thread->IsStepping())
289    {
290        // This is the primary thread, let the arch do anything it needs
291        EnableHardwareSingleStep(true) == KERN_SUCCESS;
292    }
293}
294
295bool
296DNBArchImplX86_64::ThreadDidStop()
297{
298    bool success = true;
299
300    m_state.InvalidateAllRegisterStates();
301
302    // Are we stepping a single instruction?
303    if (GetGPRState(true) == KERN_SUCCESS)
304    {
305        // We are single stepping, was this the primary thread?
306        if (m_thread->IsStepping())
307        {
308            // This was the primary thread, we need to clear the trace
309            // bit if so.
310            success = EnableHardwareSingleStep(false) == KERN_SUCCESS;
311        }
312        else
313        {
314            // The MachThread will automatically restore the suspend count
315            // in ThreadDidStop(), so we don't need to do anything here if
316            // we weren't the primary thread the last time
317        }
318    }
319    return success;
320}
321
322bool
323DNBArchImplX86_64::NotifyException(MachException::Data& exc)
324{
325    switch (exc.exc_type)
326    {
327        case EXC_BAD_ACCESS:
328            break;
329        case EXC_BAD_INSTRUCTION:
330            break;
331        case EXC_ARITHMETIC:
332            break;
333        case EXC_EMULATION:
334            break;
335        case EXC_SOFTWARE:
336            break;
337        case EXC_BREAKPOINT:
338            if (exc.exc_data.size() >= 2 && exc.exc_data[0] == 2)
339            {
340                nub_addr_t pc = GetPC(INVALID_NUB_ADDRESS);
341                if (pc != INVALID_NUB_ADDRESS && pc > 0)
342                {
343                    pc -= 1;
344                    // Check for a breakpoint at one byte prior to the current PC value
345                    // since the PC will be just past the trap.
346
347                    nub_break_t breakID = m_thread->Process()->Breakpoints().FindIDByAddress(pc);
348                    if (NUB_BREAK_ID_IS_VALID(breakID))
349                    {
350                        // Backup the PC for i386 since the trap was taken and the PC
351                        // is at the address following the single byte trap instruction.
352                        if (m_state.context.gpr.__rip > 0)
353                        {
354                            m_state.context.gpr.__rip = pc;
355                            // Write the new PC back out
356                            SetGPRState ();
357                        }
358                    }
359                    return true;
360                }
361            }
362            break;
363        case EXC_SYSCALL:
364            break;
365        case EXC_MACH_SYSCALL:
366            break;
367        case EXC_RPC_ALERT:
368            break;
369    }
370    return false;
371}
372
373
374// Set the single step bit in the processor status register.
375kern_return_t
376DNBArchImplX86_64::EnableHardwareSingleStep (bool enable)
377{
378    if (GetGPRState(false) == KERN_SUCCESS)
379    {
380        const uint32_t trace_bit = 0x100u;
381        if (enable)
382            m_state.context.gpr.__rflags |= trace_bit;
383        else
384            m_state.context.gpr.__rflags &= ~trace_bit;
385        return SetGPRState();
386    }
387    return m_state.GetError(e_regSetGPR, Read);
388}
389
390
391//----------------------------------------------------------------------
392// Register information defintions
393//----------------------------------------------------------------------
394
395enum
396{
397    gpr_rax = 0,
398    gpr_rbx,
399    gpr_rcx,
400    gpr_rdx,
401    gpr_rdi,
402    gpr_rsi,
403    gpr_rbp,
404    gpr_rsp,
405    gpr_r8,
406    gpr_r9,
407    gpr_r10,
408    gpr_r11,
409    gpr_r12,
410    gpr_r13,
411    gpr_r14,
412    gpr_r15,
413    gpr_rip,
414    gpr_rflags,
415    gpr_cs,
416    gpr_fs,
417    gpr_gs,
418    k_num_gpr_regs
419};
420
421enum {
422    fpu_fcw,
423    fpu_fsw,
424    fpu_ftw,
425    fpu_fop,
426    fpu_ip,
427    fpu_cs,
428    fpu_dp,
429    fpu_ds,
430    fpu_mxcsr,
431    fpu_mxcsrmask,
432    fpu_stmm0,
433    fpu_stmm1,
434    fpu_stmm2,
435    fpu_stmm3,
436    fpu_stmm4,
437    fpu_stmm5,
438    fpu_stmm6,
439    fpu_stmm7,
440    fpu_xmm0,
441    fpu_xmm1,
442    fpu_xmm2,
443    fpu_xmm3,
444    fpu_xmm4,
445    fpu_xmm5,
446    fpu_xmm6,
447    fpu_xmm7,
448    fpu_xmm8,
449    fpu_xmm9,
450    fpu_xmm10,
451    fpu_xmm11,
452    fpu_xmm12,
453    fpu_xmm13,
454    fpu_xmm14,
455    fpu_xmm15,
456    k_num_fpu_regs,
457
458    // Aliases
459    fpu_fctrl = fpu_fcw,
460    fpu_fstat = fpu_fsw,
461    fpu_ftag  = fpu_ftw,
462    fpu_fiseg = fpu_cs,
463    fpu_fioff = fpu_ip,
464    fpu_foseg = fpu_ds,
465    fpu_fooff = fpu_dp
466};
467
468enum {
469    exc_trapno,
470    exc_err,
471    exc_faultvaddr,
472    k_num_exc_regs,
473};
474
475
476enum gcc_dwarf_regnums
477{
478    gcc_dwarf_rax = 0,
479    gcc_dwarf_rdx,
480    gcc_dwarf_rcx,
481    gcc_dwarf_rbx,
482    gcc_dwarf_rsi,
483    gcc_dwarf_rdi,
484    gcc_dwarf_rbp,
485    gcc_dwarf_rsp,
486    gcc_dwarf_r8,
487    gcc_dwarf_r9,
488    gcc_dwarf_r10,
489    gcc_dwarf_r11,
490    gcc_dwarf_r12,
491    gcc_dwarf_r13,
492    gcc_dwarf_r14,
493    gcc_dwarf_r15,
494    gcc_dwarf_rip,
495    gcc_dwarf_xmm0,
496    gcc_dwarf_xmm1,
497    gcc_dwarf_xmm2,
498    gcc_dwarf_xmm3,
499    gcc_dwarf_xmm4,
500    gcc_dwarf_xmm5,
501    gcc_dwarf_xmm6,
502    gcc_dwarf_xmm7,
503    gcc_dwarf_xmm8,
504    gcc_dwarf_xmm9,
505    gcc_dwarf_xmm10,
506    gcc_dwarf_xmm11,
507    gcc_dwarf_xmm12,
508    gcc_dwarf_xmm13,
509    gcc_dwarf_xmm14,
510    gcc_dwarf_xmm15,
511    gcc_dwarf_stmm0,
512    gcc_dwarf_stmm1,
513    gcc_dwarf_stmm2,
514    gcc_dwarf_stmm3,
515    gcc_dwarf_stmm4,
516    gcc_dwarf_stmm5,
517    gcc_dwarf_stmm6,
518    gcc_dwarf_stmm7,
519
520};
521
522enum gdb_regnums
523{
524    gdb_rax     =   0,
525    gdb_rbx     =   1,
526    gdb_rcx     =   2,
527    gdb_rdx     =   3,
528    gdb_rsi     =   4,
529    gdb_rdi     =   5,
530    gdb_rbp     =   6,
531    gdb_rsp     =   7,
532    gdb_r8      =   8,
533    gdb_r9      =   9,
534    gdb_r10     =  10,
535    gdb_r11     =  11,
536    gdb_r12     =  12,
537    gdb_r13     =  13,
538    gdb_r14     =  14,
539    gdb_r15     =  15,
540    gdb_rip     =  16,
541    gdb_rflags  =  17,
542    gdb_cs      =  18,
543    gdb_ss      =  19,
544    gdb_ds      =  20,
545    gdb_es      =  21,
546    gdb_fs      =  22,
547    gdb_gs      =  23,
548    gdb_stmm0   =  24,
549    gdb_stmm1   =  25,
550    gdb_stmm2   =  26,
551    gdb_stmm3   =  27,
552    gdb_stmm4   =  28,
553    gdb_stmm5   =  29,
554    gdb_stmm6   =  30,
555    gdb_stmm7   =  31,
556    gdb_fctrl   =  32,  gdb_fcw = gdb_fctrl,
557    gdb_fstat   =  33,  gdb_fsw = gdb_fstat,
558    gdb_ftag    =  34,  gdb_ftw = gdb_ftag,
559    gdb_fiseg   =  35,  gdb_fpu_cs  = gdb_fiseg,
560    gdb_fioff   =  36,  gdb_ip  = gdb_fioff,
561    gdb_foseg   =  37,  gdb_fpu_ds  = gdb_foseg,
562    gdb_fooff   =  38,  gdb_dp  = gdb_fooff,
563    gdb_fop     =  39,
564    gdb_xmm0    =  40,
565    gdb_xmm1    =  41,
566    gdb_xmm2    =  42,
567    gdb_xmm3    =  43,
568    gdb_xmm4    =  44,
569    gdb_xmm5    =  45,
570    gdb_xmm6    =  46,
571    gdb_xmm7    =  47,
572    gdb_xmm8    =  48,
573    gdb_xmm9    =  49,
574    gdb_xmm10   =  50,
575    gdb_xmm11   =  51,
576    gdb_xmm12   =  52,
577    gdb_xmm13   =  53,
578    gdb_xmm14   =  54,
579    gdb_xmm15   =  55,
580    gdb_mxcsr   =  56,
581};
582
583#define GPR_OFFSET(reg) (offsetof (DNBArchImplX86_64::GPR, __##reg))
584#define FPU_OFFSET(reg) (offsetof (DNBArchImplX86_64::FPU, __fpu_##reg) + offsetof (DNBArchImplX86_64::Context, fpu))
585#define EXC_OFFSET(reg) (offsetof (DNBArchImplX86_64::EXC, __##reg)     + offsetof (DNBArchImplX86_64::Context, exc))
586
587#define GPR_SIZE(reg)       (sizeof(((DNBArchImplX86_64::GPR *)NULL)->__##reg))
588#define FPU_SIZE_UINT(reg)  (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg))
589#define FPU_SIZE_MMST(reg)  (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__mmst_reg))
590#define FPU_SIZE_XMM(reg)   (sizeof(((DNBArchImplX86_64::FPU *)NULL)->__fpu_##reg.__xmm_reg))
591#define EXC_SIZE(reg)       (sizeof(((DNBArchImplX86_64::EXC *)NULL)->__##reg))
592
593// These macros will auto define the register name, alt name, register size,
594// register offset, encoding, format and native register. This ensures that
595// the register state structures are defined correctly and have the correct
596// sizes and offsets.
597#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 }
598#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 }
599#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 }
600
601// General purpose registers for 64 bit
602const DNBRegisterInfo
603DNBArchImplX86_64::g_gpr_registers[] =
604{
605    DEFINE_GPR      (rax),
606    DEFINE_GPR      (rbx),
607    DEFINE_GPR      (rcx),
608    DEFINE_GPR      (rdx),
609    DEFINE_GPR      (rdi),
610    DEFINE_GPR      (rsi),
611    DEFINE_GPR_ALT  (rbp, "fp", GENERIC_REGNUM_FP),
612    DEFINE_GPR_ALT  (rsp, "sp", GENERIC_REGNUM_SP),
613    DEFINE_GPR      (r8),
614    DEFINE_GPR      (r9),
615    DEFINE_GPR      (r10),
616    DEFINE_GPR      (r11),
617    DEFINE_GPR      (r12),
618    DEFINE_GPR      (r13),
619    DEFINE_GPR      (r14),
620    DEFINE_GPR      (r15),
621    DEFINE_GPR_ALT  (rip, "pc", GENERIC_REGNUM_PC),
622    DEFINE_GPR_ALT2 (rflags, "flags"),
623    DEFINE_GPR_ALT2 (cs,        NULL),
624    DEFINE_GPR_ALT2 (fs,        NULL),
625    DEFINE_GPR_ALT2 (gs,        NULL),
626};
627
628// Floating point registers 64 bit
629const DNBRegisterInfo
630DNBArchImplX86_64::g_fpu_registers[] =
631{
632    { e_regSetFPU, fpu_fcw      , "fctrl"       , NULL, Uint, Hex, FPU_SIZE_UINT(fcw)       , FPU_OFFSET(fcw)       , -1, -1, -1, -1 },
633    { e_regSetFPU, fpu_fsw      , "fstat"       , NULL, Uint, Hex, FPU_SIZE_UINT(fsw)       , FPU_OFFSET(fsw)       , -1, -1, -1, -1 },
634    { e_regSetFPU, fpu_ftw      , "ftag"        , NULL, Uint, Hex, FPU_SIZE_UINT(ftw)       , FPU_OFFSET(ftw)       , -1, -1, -1, -1 },
635    { e_regSetFPU, fpu_fop      , "fop"         , NULL, Uint, Hex, FPU_SIZE_UINT(fop)       , FPU_OFFSET(fop)       , -1, -1, -1, -1 },
636    { e_regSetFPU, fpu_ip       , "fioff"       , NULL, Uint, Hex, FPU_SIZE_UINT(ip)        , FPU_OFFSET(ip)        , -1, -1, -1, -1 },
637    { e_regSetFPU, fpu_cs       , "fiseg"       , NULL, Uint, Hex, FPU_SIZE_UINT(cs)        , FPU_OFFSET(cs)        , -1, -1, -1, -1 },
638    { e_regSetFPU, fpu_dp       , "fooff"       , NULL, Uint, Hex, FPU_SIZE_UINT(dp)        , FPU_OFFSET(dp)        , -1, -1, -1, -1 },
639    { e_regSetFPU, fpu_ds       , "foseg"       , NULL, Uint, Hex, FPU_SIZE_UINT(ds)        , FPU_OFFSET(ds)        , -1, -1, -1, -1 },
640    { e_regSetFPU, fpu_mxcsr    , "mxcsr"       , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsr)     , FPU_OFFSET(mxcsr)     , -1, -1, -1, -1 },
641    { e_regSetFPU, fpu_mxcsrmask, "mxcsrmask"   , NULL, Uint, Hex, FPU_SIZE_UINT(mxcsrmask) , FPU_OFFSET(mxcsrmask) , -1, -1, -1, -1 },
642
643    { e_regSetFPU, fpu_stmm0, "stmm0", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm0), FPU_OFFSET(stmm0), gcc_dwarf_stmm0, gcc_dwarf_stmm0, -1, gdb_stmm0 },
644    { e_regSetFPU, fpu_stmm1, "stmm1", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm1), FPU_OFFSET(stmm1), gcc_dwarf_stmm1, gcc_dwarf_stmm1, -1, gdb_stmm1 },
645    { e_regSetFPU, fpu_stmm2, "stmm2", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm2), FPU_OFFSET(stmm2), gcc_dwarf_stmm2, gcc_dwarf_stmm2, -1, gdb_stmm2 },
646    { e_regSetFPU, fpu_stmm3, "stmm3", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm3), FPU_OFFSET(stmm3), gcc_dwarf_stmm3, gcc_dwarf_stmm3, -1, gdb_stmm3 },
647    { e_regSetFPU, fpu_stmm4, "stmm4", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm4), FPU_OFFSET(stmm4), gcc_dwarf_stmm4, gcc_dwarf_stmm4, -1, gdb_stmm4 },
648    { e_regSetFPU, fpu_stmm5, "stmm5", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm5), FPU_OFFSET(stmm5), gcc_dwarf_stmm5, gcc_dwarf_stmm5, -1, gdb_stmm5 },
649    { e_regSetFPU, fpu_stmm6, "stmm6", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm6), FPU_OFFSET(stmm6), gcc_dwarf_stmm6, gcc_dwarf_stmm6, -1, gdb_stmm6 },
650    { e_regSetFPU, fpu_stmm7, "stmm7", NULL, Vector, VectorOfUInt8, FPU_SIZE_MMST(stmm7), FPU_OFFSET(stmm7), gcc_dwarf_stmm7, gcc_dwarf_stmm7, -1, gdb_stmm7 },
651
652    { e_regSetFPU, fpu_xmm0 , "xmm0"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm0)   , FPU_OFFSET(xmm0) , gcc_dwarf_xmm0 , gcc_dwarf_xmm0 , -1, gdb_xmm0 },
653    { e_regSetFPU, fpu_xmm1 , "xmm1"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm1)   , FPU_OFFSET(xmm1) , gcc_dwarf_xmm1 , gcc_dwarf_xmm1 , -1, gdb_xmm1 },
654    { e_regSetFPU, fpu_xmm2 , "xmm2"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm2)   , FPU_OFFSET(xmm2) , gcc_dwarf_xmm2 , gcc_dwarf_xmm2 , -1, gdb_xmm2 },
655    { e_regSetFPU, fpu_xmm3 , "xmm3"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm3)   , FPU_OFFSET(xmm3) , gcc_dwarf_xmm3 , gcc_dwarf_xmm3 , -1, gdb_xmm3 },
656    { e_regSetFPU, fpu_xmm4 , "xmm4"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm4)   , FPU_OFFSET(xmm4) , gcc_dwarf_xmm4 , gcc_dwarf_xmm4 , -1, gdb_xmm4 },
657    { e_regSetFPU, fpu_xmm5 , "xmm5"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm5)   , FPU_OFFSET(xmm5) , gcc_dwarf_xmm5 , gcc_dwarf_xmm5 , -1, gdb_xmm5 },
658    { e_regSetFPU, fpu_xmm6 , "xmm6"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm6)   , FPU_OFFSET(xmm6) , gcc_dwarf_xmm6 , gcc_dwarf_xmm6 , -1, gdb_xmm6 },
659    { e_regSetFPU, fpu_xmm7 , "xmm7"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm7)   , FPU_OFFSET(xmm7) , gcc_dwarf_xmm7 , gcc_dwarf_xmm7 , -1, gdb_xmm7 },
660    { e_regSetFPU, fpu_xmm8 , "xmm8"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm8)   , FPU_OFFSET(xmm8) , gcc_dwarf_xmm8 , gcc_dwarf_xmm8 , -1, gdb_xmm8  },
661    { e_regSetFPU, fpu_xmm9 , "xmm9"    , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm9)   , FPU_OFFSET(xmm9) , gcc_dwarf_xmm9 , gcc_dwarf_xmm9 , -1, gdb_xmm9  },
662    { e_regSetFPU, fpu_xmm10, "xmm10"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm10)  , FPU_OFFSET(xmm10), gcc_dwarf_xmm10, gcc_dwarf_xmm10, -1, gdb_xmm10 },
663    { e_regSetFPU, fpu_xmm11, "xmm11"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm11)  , FPU_OFFSET(xmm11), gcc_dwarf_xmm11, gcc_dwarf_xmm11, -1, gdb_xmm11 },
664    { e_regSetFPU, fpu_xmm12, "xmm12"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm12)  , FPU_OFFSET(xmm12), gcc_dwarf_xmm12, gcc_dwarf_xmm12, -1, gdb_xmm12 },
665    { e_regSetFPU, fpu_xmm13, "xmm13"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm13)  , FPU_OFFSET(xmm13), gcc_dwarf_xmm13, gcc_dwarf_xmm13, -1, gdb_xmm13 },
666    { e_regSetFPU, fpu_xmm14, "xmm14"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm14)  , FPU_OFFSET(xmm14), gcc_dwarf_xmm14, gcc_dwarf_xmm14, -1, gdb_xmm14 },
667    { e_regSetFPU, fpu_xmm15, "xmm15"   , NULL, Vector, VectorOfUInt8, FPU_SIZE_XMM(xmm15)  , FPU_OFFSET(xmm15), gcc_dwarf_xmm15, gcc_dwarf_xmm15, -1, gdb_xmm15 },
668};
669
670// Exception registers
671
672const DNBRegisterInfo
673DNBArchImplX86_64::g_exc_registers[] =
674{
675    { e_regSetEXC, exc_trapno,      "trapno"    , NULL, Uint, Hex, EXC_SIZE (trapno)    , EXC_OFFSET (trapno)       , -1, -1, -1, -1 },
676    { e_regSetEXC, exc_err,         "err"       , NULL, Uint, Hex, EXC_SIZE (err)       , EXC_OFFSET (err)          , -1, -1, -1, -1 },
677    { e_regSetEXC, exc_faultvaddr,  "faultvaddr", NULL, Uint, Hex, EXC_SIZE (faultvaddr), EXC_OFFSET (faultvaddr)   , -1, -1, -1, -1 }
678};
679
680// Number of registers in each register set
681const size_t DNBArchImplX86_64::k_num_gpr_registers = sizeof(g_gpr_registers)/sizeof(DNBRegisterInfo);
682const size_t DNBArchImplX86_64::k_num_fpu_registers = sizeof(g_fpu_registers)/sizeof(DNBRegisterInfo);
683const size_t DNBArchImplX86_64::k_num_exc_registers = sizeof(g_exc_registers)/sizeof(DNBRegisterInfo);
684const size_t DNBArchImplX86_64::k_num_all_registers = k_num_gpr_registers + k_num_fpu_registers + k_num_exc_registers;
685
686//----------------------------------------------------------------------
687// Register set definitions. The first definitions at register set index
688// of zero is for all registers, followed by other registers sets. The
689// register information for the all register set need not be filled in.
690//----------------------------------------------------------------------
691const DNBRegisterSetInfo
692DNBArchImplX86_64::g_reg_sets[] =
693{
694    { "x86_64 Registers",           NULL,               k_num_all_registers },
695    { "General Purpose Registers",  g_gpr_registers,    k_num_gpr_registers },
696    { "Floating Point Registers",   g_fpu_registers,    k_num_fpu_registers },
697    { "Exception State Registers",  g_exc_registers,    k_num_exc_registers }
698};
699// Total number of register sets for this architecture
700const size_t DNBArchImplX86_64::k_num_register_sets = sizeof(g_reg_sets)/sizeof(DNBRegisterSetInfo);
701
702
703DNBArchProtocol *
704DNBArchImplX86_64::Create (MachThread *thread)
705{
706    return new DNBArchImplX86_64 (thread);
707}
708
709const uint8_t * const
710DNBArchImplX86_64::SoftwareBreakpointOpcode (nub_size_t byte_size)
711{
712    static const uint8_t g_breakpoint_opcode[] = { 0xCC };
713    if (byte_size == 1)
714        return g_breakpoint_opcode;
715    return NULL;
716}
717
718const DNBRegisterSetInfo *
719DNBArchImplX86_64::GetRegisterSetInfo(nub_size_t *num_reg_sets)
720{
721    *num_reg_sets = k_num_register_sets;
722    return g_reg_sets;
723}
724
725void
726DNBArchImplX86_64::Initialize()
727{
728    DNBArchPluginInfo arch_plugin_info =
729    {
730        CPU_TYPE_X86_64,
731        DNBArchImplX86_64::Create,
732        DNBArchImplX86_64::GetRegisterSetInfo,
733        DNBArchImplX86_64::SoftwareBreakpointOpcode
734    };
735
736    // Register this arch plug-in with the main protocol class
737    DNBArchProtocol::RegisterArchPlugin (arch_plugin_info);
738}
739
740bool
741DNBArchImplX86_64::GetRegisterValue(int set, int reg, DNBRegisterValue *value)
742{
743    if (set == REGISTER_SET_GENERIC)
744    {
745        switch (reg)
746        {
747            case GENERIC_REGNUM_PC:     // Program Counter
748                set = e_regSetGPR;
749                reg = gpr_rip;
750                break;
751
752            case GENERIC_REGNUM_SP:     // Stack Pointer
753                set = e_regSetGPR;
754                reg = gpr_rsp;
755                break;
756
757            case GENERIC_REGNUM_FP:     // Frame Pointer
758                set = e_regSetGPR;
759                reg = gpr_rbp;
760                break;
761
762            case GENERIC_REGNUM_FLAGS:  // Processor flags register
763                set = e_regSetGPR;
764                reg = gpr_rflags;
765                break;
766
767            case GENERIC_REGNUM_RA:     // Return Address
768            default:
769                return false;
770        }
771    }
772
773    if (GetRegisterState(set, false) != KERN_SUCCESS)
774        return false;
775
776    const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
777    if (regInfo)
778    {
779        value->info = *regInfo;
780        switch (set)
781        {
782            case e_regSetGPR:
783                if (reg < k_num_gpr_registers)
784                {
785                    value->value.uint64 = ((uint64_t*)(&m_state.context.gpr))[reg];
786                    return true;
787                }
788                break;
789
790            case e_regSetFPU:
791                switch (reg)
792            {
793                case fpu_fcw:       value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.__fpu_fcw));    return true;
794                case fpu_fsw:       value->value.uint16 = *((uint16_t *)(&m_state.context.fpu.__fpu_fsw));    return true;
795                case fpu_ftw:       value->value.uint8  = m_state.context.fpu.__fpu_ftw;                      return true;
796                case fpu_fop:       value->value.uint16 = m_state.context.fpu.__fpu_fop;                      return true;
797                case fpu_ip:        value->value.uint32 = m_state.context.fpu.__fpu_ip;                       return true;
798                case fpu_cs:        value->value.uint16 = m_state.context.fpu.__fpu_cs;                       return true;
799                case fpu_dp:        value->value.uint32 = m_state.context.fpu.__fpu_dp;                       return true;
800                case fpu_ds:        value->value.uint16 = m_state.context.fpu.__fpu_ds;                       return true;
801                case fpu_mxcsr:     value->value.uint32 = m_state.context.fpu.__fpu_mxcsr;                    return true;
802                case fpu_mxcsrmask: value->value.uint32 = m_state.context.fpu.__fpu_mxcsrmask;                return true;
803
804                case fpu_stmm0:
805                case fpu_stmm1:
806                case fpu_stmm2:
807                case fpu_stmm3:
808                case fpu_stmm4:
809                case fpu_stmm5:
810                case fpu_stmm6:
811                case fpu_stmm7:
812                    memcpy(&value->value.uint8, &m_state.context.fpu.__fpu_stmm0 + (reg - fpu_stmm0), 10);
813                    return true;
814
815                case fpu_xmm0:
816                case fpu_xmm1:
817                case fpu_xmm2:
818                case fpu_xmm3:
819                case fpu_xmm4:
820                case fpu_xmm5:
821                case fpu_xmm6:
822                case fpu_xmm7:
823                case fpu_xmm8:
824                case fpu_xmm9:
825                case fpu_xmm10:
826                case fpu_xmm11:
827                case fpu_xmm12:
828                case fpu_xmm13:
829                case fpu_xmm14:
830                case fpu_xmm15:
831                    memcpy(&value->value.uint8, &m_state.context.fpu.__fpu_xmm0 + (reg - fpu_xmm0), 16);
832                    return true;
833            }
834                break;
835
836            case e_regSetEXC:
837                switch (reg)
838            {
839                case exc_trapno:    value->value.uint32 = m_state.context.exc.__trapno; return true;
840                case exc_err:       value->value.uint32 = m_state.context.exc.__err; return true;
841                case exc_faultvaddr:value->value.uint64 = m_state.context.exc.__faultvaddr; return true;
842            }
843                break;
844        }
845    }
846    return false;
847}
848
849
850bool
851DNBArchImplX86_64::SetRegisterValue(int set, int reg, const DNBRegisterValue *value)
852{
853    if (set == REGISTER_SET_GENERIC)
854    {
855        switch (reg)
856        {
857            case GENERIC_REGNUM_PC:     // Program Counter
858                set = e_regSetGPR;
859                reg = gpr_rip;
860                break;
861
862            case GENERIC_REGNUM_SP:     // Stack Pointer
863                set = e_regSetGPR;
864                reg = gpr_rsp;
865                break;
866
867            case GENERIC_REGNUM_FP:     // Frame Pointer
868                set = e_regSetGPR;
869                reg = gpr_rbp;
870                break;
871
872            case GENERIC_REGNUM_FLAGS:  // Processor flags register
873                set = e_regSetGPR;
874                reg = gpr_rflags;
875                break;
876
877            case GENERIC_REGNUM_RA:     // Return Address
878            default:
879                return false;
880        }
881    }
882
883    if (GetRegisterState(set, false) != KERN_SUCCESS)
884        return false;
885
886    bool success = false;
887    const DNBRegisterInfo *regInfo = m_thread->GetRegisterInfo(set, reg);
888    if (regInfo)
889    {
890        switch (set)
891        {
892            case e_regSetGPR:
893                if (reg < k_num_gpr_registers)
894                {
895                    ((uint64_t*)(&m_state.context.gpr))[reg] = value->value.uint64;
896                    success = true;
897                }
898                break;
899
900            case e_regSetFPU:
901                switch (reg)
902            {
903                case fpu_fcw:       *((uint16_t *)(&m_state.context.fpu.__fpu_fcw)) = value->value.uint16;    success = true; break;
904                case fpu_fsw:       *((uint16_t *)(&m_state.context.fpu.__fpu_fsw)) = value->value.uint16;    success = true; break;
905                case fpu_ftw:       m_state.context.fpu.__fpu_ftw = value->value.uint8;                       success = true; break;
906                case fpu_fop:       m_state.context.fpu.__fpu_fop = value->value.uint16;                      success = true; break;
907                case fpu_ip:        m_state.context.fpu.__fpu_ip = value->value.uint32;                       success = true; break;
908                case fpu_cs:        m_state.context.fpu.__fpu_cs = value->value.uint16;                       success = true; break;
909                case fpu_dp:        m_state.context.fpu.__fpu_dp = value->value.uint32;                       success = true; break;
910                case fpu_ds:        m_state.context.fpu.__fpu_ds = value->value.uint16;                       success = true; break;
911                case fpu_mxcsr:     m_state.context.fpu.__fpu_mxcsr = value->value.uint32;                    success = true; break;
912                case fpu_mxcsrmask: m_state.context.fpu.__fpu_mxcsrmask = value->value.uint32;                success = true; break;
913
914                case fpu_stmm0:
915                case fpu_stmm1:
916                case fpu_stmm2:
917                case fpu_stmm3:
918                case fpu_stmm4:
919                case fpu_stmm5:
920                case fpu_stmm6:
921                case fpu_stmm7:
922                    memcpy (&m_state.context.fpu.__fpu_stmm0 + (reg - fpu_stmm0), &value->value.uint8, 10);
923                    success = true;
924                    break;
925
926                case fpu_xmm0:
927                case fpu_xmm1:
928                case fpu_xmm2:
929                case fpu_xmm3:
930                case fpu_xmm4:
931                case fpu_xmm5:
932                case fpu_xmm6:
933                case fpu_xmm7:
934                case fpu_xmm8:
935                case fpu_xmm9:
936                case fpu_xmm10:
937                case fpu_xmm11:
938                case fpu_xmm12:
939                case fpu_xmm13:
940                case fpu_xmm14:
941                case fpu_xmm15:
942                    memcpy (&m_state.context.fpu.__fpu_xmm0 + (reg - fpu_xmm0), &value->value.uint8, 16);
943                    success = true;
944                    break;
945            }
946                break;
947
948            case e_regSetEXC:
949                switch (reg)
950            {
951                case exc_trapno:    m_state.context.exc.__trapno = value->value.uint32;     success = true; break;
952                case exc_err:       m_state.context.exc.__err = value->value.uint32;        success = true; break;
953                case exc_faultvaddr:m_state.context.exc.__faultvaddr = value->value.uint64; success = true; break;
954            }
955                break;
956        }
957    }
958
959    if (success)
960        return SetRegisterState(set) == KERN_SUCCESS;
961    return false;
962}
963
964
965nub_size_t
966DNBArchImplX86_64::GetRegisterContext (void *buf, nub_size_t buf_len)
967{
968    nub_size_t size = sizeof (m_state.context);
969
970    if (buf && buf_len)
971    {
972        if (size > buf_len)
973            size = buf_len;
974
975        bool force = false;
976        if (GetGPRState(force) | GetFPUState(force) | GetEXCState(force))
977            return 0;
978        ::memcpy (buf, &m_state.context, size);
979    }
980    DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::GetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size);
981    // Return the size of the register context even if NULL was passed in
982    return size;
983}
984
985nub_size_t
986DNBArchImplX86_64::SetRegisterContext (const void *buf, nub_size_t buf_len)
987{
988    nub_size_t size = sizeof (m_state.context);
989    if (buf == NULL || buf_len == 0)
990        size = 0;
991
992    if (size)
993    {
994        if (size > buf_len)
995            size = buf_len;
996
997        ::memcpy (&m_state.context, buf, size);
998        SetGPRState();
999        SetFPUState();
1000        SetEXCState();
1001    }
1002    DNBLogThreadedIf (LOG_THREAD, "DNBArchImplX86_64::SetRegisterContext (buf = %p, len = %zu) => %zu", buf, buf_len, size);
1003    return size;
1004}
1005
1006
1007kern_return_t
1008DNBArchImplX86_64::GetRegisterState(int set, bool force)
1009{
1010    switch (set)
1011    {
1012        case e_regSetALL:    return GetGPRState(force) | GetFPUState(force) | GetEXCState(force);
1013        case e_regSetGPR:    return GetGPRState(force);
1014        case e_regSetFPU:    return GetFPUState(force);
1015        case e_regSetEXC:    return GetEXCState(force);
1016        default: break;
1017    }
1018    return KERN_INVALID_ARGUMENT;
1019}
1020
1021kern_return_t
1022DNBArchImplX86_64::SetRegisterState(int set)
1023{
1024    // Make sure we have a valid context to set.
1025    if (RegisterSetStateIsValid(set))
1026    {
1027        switch (set)
1028        {
1029            case e_regSetALL:    return SetGPRState() | SetFPUState() | SetEXCState();
1030            case e_regSetGPR:    return SetGPRState();
1031            case e_regSetFPU:    return SetFPUState();
1032            case e_regSetEXC:    return SetEXCState();
1033            default: break;
1034        }
1035    }
1036    return KERN_INVALID_ARGUMENT;
1037}
1038
1039bool
1040DNBArchImplX86_64::RegisterSetStateIsValid (int set) const
1041{
1042    return m_state.RegsAreValid(set);
1043}
1044
1045
1046
1047#endif    // #if defined (__i386__) || defined (__x86_64__)
1048