180814287SRaphael Isemann //===-- NativeRegisterContextNetBSD_x86_64.cpp ----------------------------===//
2f07a9995SKamil Rytarowski //
32946cd70SChandler Carruth // Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
42946cd70SChandler Carruth // See https://llvm.org/LICENSE.txt for license information.
52946cd70SChandler Carruth // SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6f07a9995SKamil Rytarowski //
7f07a9995SKamil Rytarowski //===----------------------------------------------------------------------===//
8f07a9995SKamil Rytarowski 
95cc817beSMichał Górny #if defined(__i386__) || defined(__x86_64__)
10f07a9995SKamil Rytarowski 
11f07a9995SKamil Rytarowski #include "NativeRegisterContextNetBSD_x86_64.h"
12f07a9995SKamil Rytarowski 
13f07a9995SKamil Rytarowski #include "lldb/Host/HostInfo.h"
14f07a9995SKamil Rytarowski #include "lldb/Utility/DataBufferHeap.h"
15f07a9995SKamil Rytarowski #include "lldb/Utility/Log.h"
16d821c997SPavel Labath #include "lldb/Utility/RegisterValue.h"
1797206d57SZachary Turner #include "lldb/Utility/Status.h"
18f07a9995SKamil Rytarowski 
195cc817beSMichał Górny #include "Plugins/Process/Utility/RegisterContextNetBSD_i386.h"
20f07a9995SKamil Rytarowski #include "Plugins/Process/Utility/RegisterContextNetBSD_x86_64.h"
21f07a9995SKamil Rytarowski 
2236e23ecaSKamil Rytarowski // clang-format off
2336e23ecaSKamil Rytarowski #include <sys/types.h>
24d687fa7dSMichal Gorny #include <sys/ptrace.h>
2536e23ecaSKamil Rytarowski #include <sys/sysctl.h>
262b2ad934SMichal Gorny #include <sys/uio.h>
2736e23ecaSKamil Rytarowski #include <x86/cpu.h>
282b2ad934SMichal Gorny #include <x86/cpu_extended_state.h>
292b2ad934SMichal Gorny #include <x86/specialreg.h>
30f07a9995SKamil Rytarowski #include <elf.h>
3136e23ecaSKamil Rytarowski #include <err.h>
3276e47d48SRaphael Isemann #include <cstdint>
3376e47d48SRaphael Isemann #include <cstdlib>
3436e23ecaSKamil Rytarowski // clang-format on
35f07a9995SKamil Rytarowski 
36f07a9995SKamil Rytarowski using namespace lldb_private;
37f07a9995SKamil Rytarowski using namespace lldb_private::process_netbsd;
38f07a9995SKamil Rytarowski 
39d5317b41SMichał Górny // x86 64-bit general purpose registers.
40f07a9995SKamil Rytarowski static const uint32_t g_gpr_regnums_x86_64[] = {
41f07a9995SKamil Rytarowski     lldb_rax_x86_64,    lldb_rbx_x86_64,    lldb_rcx_x86_64, lldb_rdx_x86_64,
42f07a9995SKamil Rytarowski     lldb_rdi_x86_64,    lldb_rsi_x86_64,    lldb_rbp_x86_64, lldb_rsp_x86_64,
43f07a9995SKamil Rytarowski     lldb_r8_x86_64,     lldb_r9_x86_64,     lldb_r10_x86_64, lldb_r11_x86_64,
44f07a9995SKamil Rytarowski     lldb_r12_x86_64,    lldb_r13_x86_64,    lldb_r14_x86_64, lldb_r15_x86_64,
45f07a9995SKamil Rytarowski     lldb_rip_x86_64,    lldb_rflags_x86_64, lldb_cs_x86_64,  lldb_fs_x86_64,
46f07a9995SKamil Rytarowski     lldb_gs_x86_64,     lldb_ss_x86_64,     lldb_ds_x86_64,  lldb_es_x86_64,
47f07a9995SKamil Rytarowski     lldb_eax_x86_64,    lldb_ebx_x86_64,    lldb_ecx_x86_64, lldb_edx_x86_64,
48f07a9995SKamil Rytarowski     lldb_edi_x86_64,    lldb_esi_x86_64,    lldb_ebp_x86_64, lldb_esp_x86_64,
49f07a9995SKamil Rytarowski     lldb_r8d_x86_64,  // Low 32 bits or r8
50f07a9995SKamil Rytarowski     lldb_r9d_x86_64,  // Low 32 bits or r9
51f07a9995SKamil Rytarowski     lldb_r10d_x86_64, // Low 32 bits or r10
52f07a9995SKamil Rytarowski     lldb_r11d_x86_64, // Low 32 bits or r11
53f07a9995SKamil Rytarowski     lldb_r12d_x86_64, // Low 32 bits or r12
54f07a9995SKamil Rytarowski     lldb_r13d_x86_64, // Low 32 bits or r13
55f07a9995SKamil Rytarowski     lldb_r14d_x86_64, // Low 32 bits or r14
56f07a9995SKamil Rytarowski     lldb_r15d_x86_64, // Low 32 bits or r15
57f07a9995SKamil Rytarowski     lldb_ax_x86_64,     lldb_bx_x86_64,     lldb_cx_x86_64,  lldb_dx_x86_64,
58f07a9995SKamil Rytarowski     lldb_di_x86_64,     lldb_si_x86_64,     lldb_bp_x86_64,  lldb_sp_x86_64,
59f07a9995SKamil Rytarowski     lldb_r8w_x86_64,  // Low 16 bits or r8
60f07a9995SKamil Rytarowski     lldb_r9w_x86_64,  // Low 16 bits or r9
61f07a9995SKamil Rytarowski     lldb_r10w_x86_64, // Low 16 bits or r10
62f07a9995SKamil Rytarowski     lldb_r11w_x86_64, // Low 16 bits or r11
63f07a9995SKamil Rytarowski     lldb_r12w_x86_64, // Low 16 bits or r12
64f07a9995SKamil Rytarowski     lldb_r13w_x86_64, // Low 16 bits or r13
65f07a9995SKamil Rytarowski     lldb_r14w_x86_64, // Low 16 bits or r14
66f07a9995SKamil Rytarowski     lldb_r15w_x86_64, // Low 16 bits or r15
67f07a9995SKamil Rytarowski     lldb_ah_x86_64,     lldb_bh_x86_64,     lldb_ch_x86_64,  lldb_dh_x86_64,
68f07a9995SKamil Rytarowski     lldb_al_x86_64,     lldb_bl_x86_64,     lldb_cl_x86_64,  lldb_dl_x86_64,
69f07a9995SKamil Rytarowski     lldb_dil_x86_64,    lldb_sil_x86_64,    lldb_bpl_x86_64, lldb_spl_x86_64,
70f07a9995SKamil Rytarowski     lldb_r8l_x86_64,    // Low 8 bits or r8
71f07a9995SKamil Rytarowski     lldb_r9l_x86_64,    // Low 8 bits or r9
72f07a9995SKamil Rytarowski     lldb_r10l_x86_64,   // Low 8 bits or r10
73f07a9995SKamil Rytarowski     lldb_r11l_x86_64,   // Low 8 bits or r11
74f07a9995SKamil Rytarowski     lldb_r12l_x86_64,   // Low 8 bits or r12
75f07a9995SKamil Rytarowski     lldb_r13l_x86_64,   // Low 8 bits or r13
76f07a9995SKamil Rytarowski     lldb_r14l_x86_64,   // Low 8 bits or r14
77f07a9995SKamil Rytarowski     lldb_r15l_x86_64,   // Low 8 bits or r15
78f07a9995SKamil Rytarowski     LLDB_INVALID_REGNUM // register sets need to end with this flag
79f07a9995SKamil Rytarowski };
80f07a9995SKamil Rytarowski static_assert((sizeof(g_gpr_regnums_x86_64) / sizeof(g_gpr_regnums_x86_64[0])) -
81f07a9995SKamil Rytarowski                       1 ==
82f07a9995SKamil Rytarowski                   k_num_gpr_registers_x86_64,
83f07a9995SKamil Rytarowski               "g_gpr_regnums_x86_64 has wrong number of register infos");
84f07a9995SKamil Rytarowski 
85d5317b41SMichał Górny // x86 64-bit floating point registers.
86d5317b41SMichał Górny static const uint32_t g_fpu_regnums_x86_64[] = {
87d5317b41SMichał Górny     lldb_fctrl_x86_64,  lldb_fstat_x86_64, lldb_ftag_x86_64,
88d5317b41SMichał Górny     lldb_fop_x86_64,    lldb_fiseg_x86_64, lldb_fioff_x86_64,
89d5317b41SMichał Górny     lldb_fip_x86_64,    lldb_foseg_x86_64, lldb_fooff_x86_64,
90d5317b41SMichał Górny     lldb_fdp_x86_64,    lldb_mxcsr_x86_64, lldb_mxcsrmask_x86_64,
91d5317b41SMichał Górny     lldb_st0_x86_64,    lldb_st1_x86_64,   lldb_st2_x86_64,
92d5317b41SMichał Górny     lldb_st3_x86_64,    lldb_st4_x86_64,   lldb_st5_x86_64,
93d5317b41SMichał Górny     lldb_st6_x86_64,    lldb_st7_x86_64,   lldb_mm0_x86_64,
94d5317b41SMichał Górny     lldb_mm1_x86_64,    lldb_mm2_x86_64,   lldb_mm3_x86_64,
95d5317b41SMichał Górny     lldb_mm4_x86_64,    lldb_mm5_x86_64,   lldb_mm6_x86_64,
96d5317b41SMichał Górny     lldb_mm7_x86_64,    lldb_xmm0_x86_64,  lldb_xmm1_x86_64,
97d5317b41SMichał Górny     lldb_xmm2_x86_64,   lldb_xmm3_x86_64,  lldb_xmm4_x86_64,
98d5317b41SMichał Górny     lldb_xmm5_x86_64,   lldb_xmm6_x86_64,  lldb_xmm7_x86_64,
99d5317b41SMichał Górny     lldb_xmm8_x86_64,   lldb_xmm9_x86_64,  lldb_xmm10_x86_64,
100d5317b41SMichał Górny     lldb_xmm11_x86_64,  lldb_xmm12_x86_64, lldb_xmm13_x86_64,
101d5317b41SMichał Górny     lldb_xmm14_x86_64,  lldb_xmm15_x86_64,
1026eca4f46SMichał Górny     LLDB_INVALID_REGNUM // register sets need to end with this flag
1036eca4f46SMichał Górny };
104d5317b41SMichał Górny static_assert((sizeof(g_fpu_regnums_x86_64) / sizeof(g_fpu_regnums_x86_64[0])) -
1056eca4f46SMichał Górny                       1 ==
106d5317b41SMichał Górny                   k_num_fpr_registers_x86_64,
107d5317b41SMichał Górny               "g_fpu_regnums_x86_64 has wrong number of register infos");
108d5317b41SMichał Górny 
109d5317b41SMichał Górny static const uint32_t g_avx_regnums_x86_64[] = {
110d5317b41SMichał Górny     lldb_ymm0_x86_64,   lldb_ymm1_x86_64,  lldb_ymm2_x86_64,  lldb_ymm3_x86_64,
111d5317b41SMichał Górny     lldb_ymm4_x86_64,   lldb_ymm5_x86_64,  lldb_ymm6_x86_64,  lldb_ymm7_x86_64,
112d5317b41SMichał Górny     lldb_ymm8_x86_64,   lldb_ymm9_x86_64,  lldb_ymm10_x86_64, lldb_ymm11_x86_64,
113d5317b41SMichał Górny     lldb_ymm12_x86_64,  lldb_ymm13_x86_64, lldb_ymm14_x86_64, lldb_ymm15_x86_64,
114d5317b41SMichał Górny     LLDB_INVALID_REGNUM // register sets need to end with this flag
115d5317b41SMichał Górny };
116d5317b41SMichał Górny static_assert((sizeof(g_avx_regnums_x86_64) / sizeof(g_avx_regnums_x86_64[0])) -
117d5317b41SMichał Górny                       1 ==
118d5317b41SMichał Górny                   k_num_avx_registers_x86_64,
119d5317b41SMichał Górny               "g_avx_regnums_x86_64 has wrong number of register infos");
120d5317b41SMichał Górny 
121d5317b41SMichał Górny static const uint32_t g_mpx_regnums_x86_64[] = {
122d5317b41SMichał Górny     // Note: we currently do not provide them but this is needed to avoid
123d5317b41SMichał Górny     // unnamed groups in SBFrame::GetRegisterContext().
124d5317b41SMichał Górny     lldb_bnd0_x86_64,   lldb_bnd1_x86_64,    lldb_bnd2_x86_64,
125d5317b41SMichał Górny     lldb_bnd3_x86_64,   lldb_bndcfgu_x86_64, lldb_bndstatus_x86_64,
126d5317b41SMichał Górny     LLDB_INVALID_REGNUM // register sets need to end with this flag
127d5317b41SMichał Górny };
128d5317b41SMichał Górny static_assert((sizeof(g_mpx_regnums_x86_64) / sizeof(g_mpx_regnums_x86_64[0])) -
129d5317b41SMichał Górny                       1 ==
130d96cb528SMichał Górny                   k_num_mpx_registers_x86_64,
131d5317b41SMichał Górny               "g_mpx_regnums_x86_64 has wrong number of register infos");
1326eca4f46SMichał Górny 
1336eca4f46SMichał Górny // x86 debug registers.
1346eca4f46SMichał Górny static const uint32_t g_dbr_regnums_x86_64[] = {
1356eca4f46SMichał Górny     lldb_dr0_x86_64,    lldb_dr1_x86_64, lldb_dr2_x86_64, lldb_dr3_x86_64,
1366eca4f46SMichał Górny     lldb_dr4_x86_64,    lldb_dr5_x86_64, lldb_dr6_x86_64, lldb_dr7_x86_64,
1376eca4f46SMichał Górny     LLDB_INVALID_REGNUM // register sets need to end with this flag
1386eca4f46SMichał Górny };
1396eca4f46SMichał Górny static_assert((sizeof(g_dbr_regnums_x86_64) / sizeof(g_dbr_regnums_x86_64[0])) -
1406eca4f46SMichał Górny                       1 ==
1416eca4f46SMichał Górny                   k_num_dbr_registers_x86_64,
1426eca4f46SMichał Górny               "g_dbr_regnums_x86_64 has wrong number of register infos");
1436eca4f46SMichał Górny 
1445cc817beSMichał Górny // x86 32-bit general purpose registers.
145d96cb528SMichał Górny static const uint32_t g_gpr_regnums_i386[] = {
1465cc817beSMichał Górny     lldb_eax_i386,      lldb_ebx_i386,    lldb_ecx_i386, lldb_edx_i386,
1475cc817beSMichał Górny     lldb_edi_i386,      lldb_esi_i386,    lldb_ebp_i386, lldb_esp_i386,
1485cc817beSMichał Górny     lldb_eip_i386,      lldb_eflags_i386, lldb_cs_i386,  lldb_fs_i386,
1495cc817beSMichał Górny     lldb_gs_i386,       lldb_ss_i386,     lldb_ds_i386,  lldb_es_i386,
1505cc817beSMichał Górny     lldb_ax_i386,       lldb_bx_i386,     lldb_cx_i386,  lldb_dx_i386,
1515cc817beSMichał Górny     lldb_di_i386,       lldb_si_i386,     lldb_bp_i386,  lldb_sp_i386,
1525cc817beSMichał Górny     lldb_ah_i386,       lldb_bh_i386,     lldb_ch_i386,  lldb_dh_i386,
1535cc817beSMichał Górny     lldb_al_i386,       lldb_bl_i386,     lldb_cl_i386,  lldb_dl_i386,
1545cc817beSMichał Górny     LLDB_INVALID_REGNUM // register sets need to end with this flag
1555cc817beSMichał Górny };
1565cc817beSMichał Górny static_assert((sizeof(g_gpr_regnums_i386) / sizeof(g_gpr_regnums_i386[0])) -
1575cc817beSMichał Górny                       1 ==
1585cc817beSMichał Górny                   k_num_gpr_registers_i386,
1595cc817beSMichał Górny               "g_gpr_regnums_i386 has wrong number of register infos");
1605cc817beSMichał Górny 
161d5317b41SMichał Górny // x86 32-bit floating point registers.
162d5317b41SMichał Górny static const uint32_t g_fpu_regnums_i386[] = {
1635cc817beSMichał Górny     lldb_fctrl_i386,    lldb_fstat_i386,     lldb_ftag_i386,  lldb_fop_i386,
1645cc817beSMichał Górny     lldb_fiseg_i386,    lldb_fioff_i386,     lldb_foseg_i386, lldb_fooff_i386,
1655cc817beSMichał Górny     lldb_mxcsr_i386,    lldb_mxcsrmask_i386, lldb_st0_i386,   lldb_st1_i386,
1665cc817beSMichał Górny     lldb_st2_i386,      lldb_st3_i386,       lldb_st4_i386,   lldb_st5_i386,
1675cc817beSMichał Górny     lldb_st6_i386,      lldb_st7_i386,       lldb_mm0_i386,   lldb_mm1_i386,
1685cc817beSMichał Górny     lldb_mm2_i386,      lldb_mm3_i386,       lldb_mm4_i386,   lldb_mm5_i386,
1695cc817beSMichał Górny     lldb_mm6_i386,      lldb_mm7_i386,       lldb_xmm0_i386,  lldb_xmm1_i386,
1705cc817beSMichał Górny     lldb_xmm2_i386,     lldb_xmm3_i386,      lldb_xmm4_i386,  lldb_xmm5_i386,
1715cc817beSMichał Górny     lldb_xmm6_i386,     lldb_xmm7_i386,
172d5317b41SMichał Górny     LLDB_INVALID_REGNUM // register sets need to end with this flag
173d5317b41SMichał Górny };
174d5317b41SMichał Górny static_assert((sizeof(g_fpu_regnums_i386) / sizeof(g_fpu_regnums_i386[0])) -
175d5317b41SMichał Górny                       1 ==
176d5317b41SMichał Górny                   k_num_fpr_registers_i386,
177d5317b41SMichał Górny               "g_fpu_regnums_i386 has wrong number of register infos");
178d5317b41SMichał Górny 
179d5317b41SMichał Górny static const uint32_t g_avx_regnums_i386[] = {
1805cc817beSMichał Górny     lldb_ymm0_i386,     lldb_ymm1_i386, lldb_ymm2_i386, lldb_ymm3_i386,
1815cc817beSMichał Górny     lldb_ymm4_i386,     lldb_ymm5_i386, lldb_ymm6_i386, lldb_ymm7_i386,
182d5317b41SMichał Górny     LLDB_INVALID_REGNUM // register sets need to end with this flag
183d5317b41SMichał Górny };
184d5317b41SMichał Górny static_assert((sizeof(g_avx_regnums_i386) / sizeof(g_avx_regnums_i386[0])) -
185d5317b41SMichał Górny                       1 ==
186d5317b41SMichał Górny                   k_num_avx_registers_i386,
187d5317b41SMichał Górny               "g_avx_regnums_i386 has wrong number of register infos");
188d5317b41SMichał Górny 
189d5317b41SMichał Górny static const uint32_t g_mpx_regnums_i386[] = {
1905cc817beSMichał Górny     // Note: we currently do not provide them but this is needed to avoid
1915cc817beSMichał Górny     // unnamed groups in SBFrame::GetRegisterContext().
1925cc817beSMichał Górny     lldb_bnd0_i386,     lldb_bnd1_i386,    lldb_bnd2_i386,
1935cc817beSMichał Górny     lldb_bnd3_i386,     lldb_bndcfgu_i386, lldb_bndstatus_i386,
1945cc817beSMichał Górny     LLDB_INVALID_REGNUM // register sets need to end with this flag
1955cc817beSMichał Górny };
196d5317b41SMichał Górny static_assert((sizeof(g_mpx_regnums_i386) / sizeof(g_mpx_regnums_i386[0])) -
1975cc817beSMichał Górny                       1 ==
198d5317b41SMichał Górny                   k_num_mpx_registers_i386,
199d5317b41SMichał Górny               "g_mpx_regnums_i386 has wrong number of register infos");
2005cc817beSMichał Górny 
2015cc817beSMichał Górny // x86 debug registers.
2025cc817beSMichał Górny static const uint32_t g_dbr_regnums_i386[] = {
2035cc817beSMichał Górny     lldb_dr0_i386,      lldb_dr1_i386, lldb_dr2_i386, lldb_dr3_i386,
2045cc817beSMichał Górny     lldb_dr4_i386,      lldb_dr5_i386, lldb_dr6_i386, lldb_dr7_i386,
2055cc817beSMichał Górny     LLDB_INVALID_REGNUM // register sets need to end with this flag
2065cc817beSMichał Górny };
2075cc817beSMichał Górny static_assert((sizeof(g_dbr_regnums_i386) / sizeof(g_dbr_regnums_i386[0])) -
2085cc817beSMichał Górny                       1 ==
2095cc817beSMichał Górny                   k_num_dbr_registers_i386,
2105cc817beSMichał Górny               "g_dbr_regnums_i386 has wrong number of register infos");
2115cc817beSMichał Górny 
212f07a9995SKamil Rytarowski // Number of register sets provided by this context.
213d5317b41SMichał Górny enum { k_num_register_sets = 5 };
214f07a9995SKamil Rytarowski 
2155cc817beSMichał Górny // Register sets for x86 32-bit.
2165cc817beSMichał Górny static const RegisterSet g_reg_sets_i386[k_num_register_sets] = {
2175cc817beSMichał Górny     {"General Purpose Registers", "gpr", k_num_gpr_registers_i386,
2185cc817beSMichał Górny      g_gpr_regnums_i386},
219d5317b41SMichał Górny     {"Floating Point Registers", "fpu", k_num_fpr_registers_i386,
220d5317b41SMichał Górny      g_fpu_regnums_i386},
221d5317b41SMichał Górny     {"Debug Registers", "dbr", k_num_dbr_registers_i386, g_dbr_regnums_i386},
222d5317b41SMichał Górny     {"Advanced Vector Extensions", "avx", k_num_avx_registers_i386,
223d5317b41SMichał Górny      g_avx_regnums_i386},
224d5317b41SMichał Górny     {"Memory Protection Extensions", "mpx", k_num_mpx_registers_i386,
225d5317b41SMichał Górny      g_mpx_regnums_i386},
2265cc817beSMichał Górny };
2275cc817beSMichał Górny 
228f07a9995SKamil Rytarowski // Register sets for x86 64-bit.
229f07a9995SKamil Rytarowski static const RegisterSet g_reg_sets_x86_64[k_num_register_sets] = {
230f07a9995SKamil Rytarowski     {"General Purpose Registers", "gpr", k_num_gpr_registers_x86_64,
231f07a9995SKamil Rytarowski      g_gpr_regnums_x86_64},
232d5317b41SMichał Górny     {"Floating Point Registers", "fpu", k_num_fpr_registers_x86_64,
233d5317b41SMichał Górny      g_fpu_regnums_x86_64},
2346eca4f46SMichał Górny     {"Debug Registers", "dbr", k_num_dbr_registers_x86_64,
2356eca4f46SMichał Górny      g_dbr_regnums_x86_64},
236d5317b41SMichał Górny     {"Advanced Vector Extensions", "avx", k_num_avx_registers_x86_64,
237d5317b41SMichał Górny      g_avx_regnums_x86_64},
238d5317b41SMichał Górny     {"Memory Protection Extensions", "mpx", k_num_mpx_registers_x86_64,
239d5317b41SMichał Górny      g_mpx_regnums_x86_64},
240f07a9995SKamil Rytarowski };
241f07a9995SKamil Rytarowski 
242f07a9995SKamil Rytarowski #define REG_CONTEXT_SIZE (GetRegisterInfoInterface().GetGPRSize())
243f07a9995SKamil Rytarowski 
244f07a9995SKamil Rytarowski NativeRegisterContextNetBSD *
CreateHostNativeRegisterContextNetBSD(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)245f07a9995SKamil Rytarowski NativeRegisterContextNetBSD::CreateHostNativeRegisterContextNetBSD(
246d37349f3SPavel Labath     const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
247d37349f3SPavel Labath   return new NativeRegisterContextNetBSD_x86_64(target_arch, native_thread);
248f07a9995SKamil Rytarowski }
249f07a9995SKamil Rytarowski 
250f07a9995SKamil Rytarowski // NativeRegisterContextNetBSD_x86_64 members.
251f07a9995SKamil Rytarowski 
252f07a9995SKamil Rytarowski static RegisterInfoInterface *
CreateRegisterInfoInterface(const ArchSpec & target_arch)253f07a9995SKamil Rytarowski CreateRegisterInfoInterface(const ArchSpec &target_arch) {
2545cc817beSMichał Górny   if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
2555cc817beSMichał Górny     // 32-bit hosts run with a RegisterContextNetBSD_i386 context.
2565cc817beSMichał Górny     return new RegisterContextNetBSD_i386(target_arch);
2575cc817beSMichał Górny   } else {
258f07a9995SKamil Rytarowski     assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
259f07a9995SKamil Rytarowski            "Register setting path assumes this is a 64-bit host");
260d5317b41SMichał Górny     // X86_64 hosts know how to work with 64-bit and 32-bit EXEs using the
261d5317b41SMichał Górny     // x86_64 register context.
262f07a9995SKamil Rytarowski     return new RegisterContextNetBSD_x86_64(target_arch);
263f07a9995SKamil Rytarowski   }
2645cc817beSMichał Górny }
265f07a9995SKamil Rytarowski 
NativeRegisterContextNetBSD_x86_64(const ArchSpec & target_arch,NativeThreadProtocol & native_thread)266f07a9995SKamil Rytarowski NativeRegisterContextNetBSD_x86_64::NativeRegisterContextNetBSD_x86_64(
267d37349f3SPavel Labath     const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
268dae7b100SMichał Górny     : NativeRegisterContextRegisterInfo(
269dae7b100SMichał Górny           native_thread, CreateRegisterInfoInterface(target_arch)),
270e1d4fb1eSPavel Labath       NativeRegisterContextDBReg_x86(native_thread), m_regset_offsets({0}) {
271d5317b41SMichał Górny   assert(m_gpr.size() == GetRegisterInfoInterface().GetGPRSize());
272d5317b41SMichał Górny   std::array<uint32_t, MaxRegularRegSet + 1> first_regnos;
273f07a9995SKamil Rytarowski 
274d5317b41SMichał Górny   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
275d5317b41SMichał Górny   case llvm::Triple::x86:
276d5317b41SMichał Górny     first_regnos[FPRegSet] = lldb_fctrl_i386;
277d5317b41SMichał Górny     first_regnos[DBRegSet] = lldb_dr0_i386;
278d5317b41SMichał Górny     break;
279d5317b41SMichał Górny   case llvm::Triple::x86_64:
280d5317b41SMichał Górny     first_regnos[FPRegSet] = lldb_fctrl_x86_64;
281d5317b41SMichał Górny     first_regnos[DBRegSet] = lldb_dr0_x86_64;
282d5317b41SMichał Górny     break;
283d5317b41SMichał Górny   default:
284d5317b41SMichał Górny     llvm_unreachable("Unhandled target architecture.");
285f07a9995SKamil Rytarowski   }
286f07a9995SKamil Rytarowski 
287d5317b41SMichał Górny   for (int i : {FPRegSet, DBRegSet})
288d5317b41SMichał Górny     m_regset_offsets[i] = GetRegisterInfoInterface()
289d5317b41SMichał Górny                               .GetRegisterInfo()[first_regnos[i]]
290d5317b41SMichał Górny                               .byte_offset;
291d5317b41SMichał Górny }
292d5317b41SMichał Górny 
GetRegisterSetCount() const293d5317b41SMichał Górny uint32_t NativeRegisterContextNetBSD_x86_64::GetRegisterSetCount() const {
294d5317b41SMichał Górny   return k_num_register_sets;
295f07a9995SKamil Rytarowski }
296f07a9995SKamil Rytarowski 
297f07a9995SKamil Rytarowski const RegisterSet *
GetRegisterSet(uint32_t set_index) const298f07a9995SKamil Rytarowski NativeRegisterContextNetBSD_x86_64::GetRegisterSet(uint32_t set_index) const {
299f07a9995SKamil Rytarowski   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
3005cc817beSMichał Górny   case llvm::Triple::x86:
3015cc817beSMichał Górny     return &g_reg_sets_i386[set_index];
302f07a9995SKamil Rytarowski   case llvm::Triple::x86_64:
303f07a9995SKamil Rytarowski     return &g_reg_sets_x86_64[set_index];
304f07a9995SKamil Rytarowski   default:
30598216320SMichał Górny     llvm_unreachable("Unhandled target architecture.");
306f07a9995SKamil Rytarowski   }
307f07a9995SKamil Rytarowski }
308f07a9995SKamil Rytarowski 
309d5317b41SMichał Górny llvm::Optional<NativeRegisterContextNetBSD_x86_64::RegSetKind>
GetSetForNativeRegNum(uint32_t reg_num) const310d5317b41SMichał Górny NativeRegisterContextNetBSD_x86_64::GetSetForNativeRegNum(
311d5317b41SMichał Górny     uint32_t reg_num) const {
3125cc817beSMichał Górny   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
3135cc817beSMichał Górny   case llvm::Triple::x86:
31498216320SMichał Górny     if (reg_num >= k_first_gpr_i386 && reg_num <= k_last_gpr_i386)
3155cc817beSMichał Górny       return GPRegSet;
31698216320SMichał Górny     if (reg_num >= k_first_fpr_i386 && reg_num <= k_last_fpr_i386)
317d5317b41SMichał Górny       return FPRegSet;
31898216320SMichał Górny     if (reg_num >= k_first_avx_i386 && reg_num <= k_last_avx_i386)
319d5317b41SMichał Górny       return YMMRegSet;
32098216320SMichał Górny     if (reg_num >= k_first_mpxr_i386 && reg_num <= k_last_mpxr_i386)
321d5317b41SMichał Górny       return llvm::None; // MPXR
32298216320SMichał Górny     if (reg_num >= k_first_mpxc_i386 && reg_num <= k_last_mpxc_i386)
323d5317b41SMichał Górny       return llvm::None; // MPXC
32498216320SMichał Górny     if (reg_num >= k_first_dbr_i386 && reg_num <= k_last_dbr_i386)
32536e23ecaSKamil Rytarowski       return DBRegSet; // DBR
32698216320SMichał Górny     break;
32798216320SMichał Górny   case llvm::Triple::x86_64:
32898216320SMichał Górny     if (reg_num >= k_first_gpr_x86_64 && reg_num <= k_last_gpr_x86_64)
32998216320SMichał Górny       return GPRegSet;
33098216320SMichał Górny     if (reg_num >= k_first_fpr_x86_64 && reg_num <= k_last_fpr_x86_64)
331d5317b41SMichał Górny       return FPRegSet;
33298216320SMichał Górny     if (reg_num >= k_first_avx_x86_64 && reg_num <= k_last_avx_x86_64)
333d5317b41SMichał Górny       return YMMRegSet;
33498216320SMichał Górny     if (reg_num >= k_first_mpxr_x86_64 && reg_num <= k_last_mpxr_x86_64)
335d5317b41SMichał Górny       return llvm::None; // MPXR
33698216320SMichał Górny     if (reg_num >= k_first_mpxc_x86_64 && reg_num <= k_last_mpxc_x86_64)
337d5317b41SMichał Górny       return llvm::None; // MPXC
33898216320SMichał Górny     if (reg_num >= k_first_dbr_x86_64 && reg_num <= k_last_dbr_x86_64)
33998216320SMichał Górny       return DBRegSet; // DBR
34098216320SMichał Górny     break;
3415cc817beSMichał Górny   default:
34298216320SMichał Górny     llvm_unreachable("Unhandled target architecture.");
3435cc817beSMichał Górny   }
34498216320SMichał Górny 
34598216320SMichał Górny   llvm_unreachable("Register does not belong to any register set");
346f07a9995SKamil Rytarowski }
347f07a9995SKamil Rytarowski 
ReadRegisterSet(RegSetKind set)348d5317b41SMichał Górny Status NativeRegisterContextNetBSD_x86_64::ReadRegisterSet(RegSetKind set) {
349f07a9995SKamil Rytarowski   switch (set) {
350f07a9995SKamil Rytarowski   case GPRegSet:
351d5317b41SMichał Górny     return DoRegisterSet(PT_GETREGS, m_gpr.data());
35236e23ecaSKamil Rytarowski   case DBRegSet:
353d5317b41SMichał Górny     return DoRegisterSet(PT_GETDBREGS, m_dbr.data());
354d5317b41SMichał Górny   case FPRegSet:
355d5317b41SMichał Górny   case YMMRegSet:
356d5317b41SMichał Górny   case MPXRegSet: {
357d5317b41SMichał Górny     struct iovec iov = {m_xstate.data(), m_xstate.size()};
358d5317b41SMichał Górny     Status ret = DoRegisterSet(PT_GETXSTATE, &iov);
359d5317b41SMichał Górny     assert(reinterpret_cast<xstate *>(m_xstate.data())->xs_rfbm & XCR0_X87);
360d5317b41SMichał Górny     return ret;
3612b2ad934SMichal Gorny   }
362f07a9995SKamil Rytarowski   }
363a984404fSMichal Gorny   llvm_unreachable("NativeRegisterContextNetBSD_x86_64::ReadRegisterSet");
364f07a9995SKamil Rytarowski }
365a984404fSMichal Gorny 
WriteRegisterSet(RegSetKind set)366d5317b41SMichał Górny Status NativeRegisterContextNetBSD_x86_64::WriteRegisterSet(RegSetKind set) {
367f07a9995SKamil Rytarowski   switch (set) {
368f07a9995SKamil Rytarowski   case GPRegSet:
369d5317b41SMichał Górny     return DoRegisterSet(PT_SETREGS, m_gpr.data());
37036e23ecaSKamil Rytarowski   case DBRegSet:
371d5317b41SMichał Górny     return DoRegisterSet(PT_SETDBREGS, m_dbr.data());
372d5317b41SMichał Górny   case FPRegSet:
373d5317b41SMichał Górny   case YMMRegSet:
374d5317b41SMichał Górny   case MPXRegSet: {
3755cc817beSMichał Górny     struct iovec iov = {&m_xstate, sizeof(m_xstate)};
3762b2ad934SMichal Gorny     return DoRegisterSet(PT_SETXSTATE, &iov);
3772b2ad934SMichal Gorny   }
378f07a9995SKamil Rytarowski   }
379a984404fSMichal Gorny   llvm_unreachable("NativeRegisterContextNetBSD_x86_64::WriteRegisterSet");
380f07a9995SKamil Rytarowski }
381f07a9995SKamil Rytarowski 
38297206d57SZachary Turner Status
ReadRegister(const RegisterInfo * reg_info,RegisterValue & reg_value)38397206d57SZachary Turner NativeRegisterContextNetBSD_x86_64::ReadRegister(const RegisterInfo *reg_info,
38497206d57SZachary Turner                                                  RegisterValue &reg_value) {
38597206d57SZachary Turner   Status error;
386f07a9995SKamil Rytarowski 
387f07a9995SKamil Rytarowski   if (!reg_info) {
388f07a9995SKamil Rytarowski     error.SetErrorString("reg_info NULL");
389f07a9995SKamil Rytarowski     return error;
390f07a9995SKamil Rytarowski   }
391f07a9995SKamil Rytarowski 
3925cc817beSMichał Górny   uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
393f07a9995SKamil Rytarowski   if (reg == LLDB_INVALID_REGNUM) {
394f07a9995SKamil Rytarowski     // This is likely an internal register for lldb use only and should not be
395f07a9995SKamil Rytarowski     // directly queried.
396f07a9995SKamil Rytarowski     error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
397f07a9995SKamil Rytarowski                                    "register, cannot read directly",
398f07a9995SKamil Rytarowski                                    reg_info->name);
399f07a9995SKamil Rytarowski     return error;
400f07a9995SKamil Rytarowski   }
401f07a9995SKamil Rytarowski 
402d5317b41SMichał Górny   llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
403d5317b41SMichał Górny   if (!opt_set) {
404f07a9995SKamil Rytarowski     // This is likely an internal register for lldb use only and should not be
405f07a9995SKamil Rytarowski     // directly queried.
406f07a9995SKamil Rytarowski     error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
407f07a9995SKamil Rytarowski                                    reg_info->name);
408f07a9995SKamil Rytarowski     return error;
409f07a9995SKamil Rytarowski   }
410f07a9995SKamil Rytarowski 
411d5317b41SMichał Górny   RegSetKind set = opt_set.getValue();
412a984404fSMichal Gorny   error = ReadRegisterSet(set);
413a984404fSMichal Gorny   if (error.Fail())
414f07a9995SKamil Rytarowski     return error;
415f07a9995SKamil Rytarowski 
416d5317b41SMichał Górny   switch (set) {
417d5317b41SMichał Górny   case GPRegSet:
418d5317b41SMichał Górny   case FPRegSet:
419d5317b41SMichał Górny   case DBRegSet: {
420d5317b41SMichał Górny     void *data = GetOffsetRegSetData(set, reg_info->byte_offset);
421d5317b41SMichał Górny     FXSAVE *fpr = reinterpret_cast<FXSAVE *>(m_xstate.data() +
422d5317b41SMichał Górny                                              offsetof(xstate, xs_fxsave));
423d5317b41SMichał Górny     if (data == &fpr->ftag) // ftag
424d5317b41SMichał Górny       reg_value.SetUInt16(
425d5317b41SMichał Górny           AbridgedToFullTagWord(fpr->ftag, fpr->fstat, fpr->stmm));
426d5317b41SMichał Górny     else
427d5317b41SMichał Górny       reg_value.SetBytes(data, reg_info->byte_size, endian::InlHostByteOrder());
42836e23ecaSKamil Rytarowski     break;
4298aea95f3SMichał Górny   }
430d5317b41SMichał Górny   case YMMRegSet: {
431d5317b41SMichał Górny     llvm::Optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg);
432d5317b41SMichał Górny     if (!ymm_reg) {
433d96cb528SMichał Górny       error.SetErrorStringWithFormat(
434d96cb528SMichał Górny           "register \"%s\" not supported by CPU/kernel", reg_info->name);
435d96cb528SMichał Górny     } else {
436d5317b41SMichał Górny       YMMReg ymm = XStateToYMM(ymm_reg->xmm, ymm_reg->ymm_hi);
4372b2ad934SMichal Gorny       reg_value.SetBytes(ymm.bytes, reg_info->byte_size,
4382b2ad934SMichal Gorny                          endian::InlHostByteOrder());
4392b2ad934SMichal Gorny     }
4402b2ad934SMichal Gorny     break;
441d5317b41SMichał Górny   }
442d5317b41SMichał Górny   case MPXRegSet:
443d5317b41SMichał Górny     llvm_unreachable("MPX regset should have returned error");
444f07a9995SKamil Rytarowski   }
445f07a9995SKamil Rytarowski 
446f07a9995SKamil Rytarowski   return error;
447f07a9995SKamil Rytarowski }
448f07a9995SKamil Rytarowski 
WriteRegister(const RegisterInfo * reg_info,const RegisterValue & reg_value)44997206d57SZachary Turner Status NativeRegisterContextNetBSD_x86_64::WriteRegister(
450f07a9995SKamil Rytarowski     const RegisterInfo *reg_info, const RegisterValue &reg_value) {
451f07a9995SKamil Rytarowski 
45297206d57SZachary Turner   Status error;
453f07a9995SKamil Rytarowski 
454f07a9995SKamil Rytarowski   if (!reg_info) {
455f07a9995SKamil Rytarowski     error.SetErrorString("reg_info NULL");
456f07a9995SKamil Rytarowski     return error;
457f07a9995SKamil Rytarowski   }
458f07a9995SKamil Rytarowski 
4595cc817beSMichał Górny   uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
460f07a9995SKamil Rytarowski   if (reg == LLDB_INVALID_REGNUM) {
461f07a9995SKamil Rytarowski     // This is likely an internal register for lldb use only and should not be
462f07a9995SKamil Rytarowski     // directly queried.
463f07a9995SKamil Rytarowski     error.SetErrorStringWithFormat("register \"%s\" is an internal-only lldb "
464f07a9995SKamil Rytarowski                                    "register, cannot read directly",
465f07a9995SKamil Rytarowski                                    reg_info->name);
466f07a9995SKamil Rytarowski     return error;
467f07a9995SKamil Rytarowski   }
468f07a9995SKamil Rytarowski 
469d5317b41SMichał Górny   llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
470d5317b41SMichał Górny   if (!opt_set) {
471f07a9995SKamil Rytarowski     // This is likely an internal register for lldb use only and should not be
472f07a9995SKamil Rytarowski     // directly queried.
473f07a9995SKamil Rytarowski     error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
474f07a9995SKamil Rytarowski                                    reg_info->name);
475f07a9995SKamil Rytarowski     return error;
476f07a9995SKamil Rytarowski   }
477f07a9995SKamil Rytarowski 
478d5317b41SMichał Górny   RegSetKind set = opt_set.getValue();
479d5317b41SMichał Górny   uint64_t new_xstate_bv = 0;
4805cc817beSMichał Górny 
481a984404fSMichal Gorny   error = ReadRegisterSet(set);
482a984404fSMichal Gorny   if (error.Fail())
483f07a9995SKamil Rytarowski     return error;
484f07a9995SKamil Rytarowski 
485d5317b41SMichał Górny   switch (set) {
486d5317b41SMichał Górny   case GPRegSet:
487d5317b41SMichał Górny   case DBRegSet:
488d5317b41SMichał Górny     ::memcpy(GetOffsetRegSetData(set, reg_info->byte_offset),
48936e23ecaSKamil Rytarowski              reg_value.GetBytes(), reg_value.GetByteSize());
49036e23ecaSKamil Rytarowski     break;
491d5317b41SMichał Górny   case FPRegSet: {
492d5317b41SMichał Górny     void *data = GetOffsetRegSetData(set, reg_info->byte_offset);
493d5317b41SMichał Górny     FXSAVE *fpr = reinterpret_cast<FXSAVE *>(m_xstate.data() +
494d5317b41SMichał Górny                                              offsetof(xstate, xs_fxsave));
495d5317b41SMichał Górny     if (data == &fpr->ftag) // ftag
496d5317b41SMichał Górny       fpr->ftag = FullToAbridgedTagWord(reg_value.GetAsUInt16());
497d5317b41SMichał Górny     else
498d5317b41SMichał Górny       ::memcpy(data, reg_value.GetBytes(), reg_value.GetByteSize());
499d5317b41SMichał Górny     if (data >= &fpr->xmm)
500d5317b41SMichał Górny       new_xstate_bv |= XCR0_SSE;
501d5317b41SMichał Górny     else if (data >= &fpr->mxcsr && data < &fpr->stmm)
502d5317b41SMichał Górny       new_xstate_bv |= XCR0_SSE;
503d5317b41SMichał Górny     else
504d5317b41SMichał Górny       new_xstate_bv |= XCR0_X87;
50536e23ecaSKamil Rytarowski     break;
506d96cb528SMichał Górny   }
507d5317b41SMichał Górny   case YMMRegSet: {
508d5317b41SMichał Górny     llvm::Optional<YMMSplitPtr> ymm_reg = GetYMMSplitReg(reg);
509d5317b41SMichał Górny     if (!ymm_reg) {
510d96cb528SMichał Górny       error.SetErrorStringWithFormat(
511d96cb528SMichał Górny           "register \"%s\" not supported by CPU/kernel", reg_info->name);
5122b2ad934SMichal Gorny     } else {
5132b2ad934SMichal Gorny       YMMReg ymm;
5142b2ad934SMichal Gorny       ::memcpy(ymm.bytes, reg_value.GetBytes(), reg_value.GetByteSize());
515d5317b41SMichał Górny       YMMToXState(ymm, ymm_reg->xmm, ymm_reg->ymm_hi);
516d5317b41SMichał Górny       new_xstate_bv |= XCR0_SSE | XCR0_YMM_Hi128;
5172b2ad934SMichal Gorny     }
5182b2ad934SMichal Gorny     break;
519d5317b41SMichał Górny   }
520d5317b41SMichał Górny   case MPXRegSet:
521d5317b41SMichał Górny     llvm_unreachable("MPX regset should have returned error");
522f07a9995SKamil Rytarowski   }
523f07a9995SKamil Rytarowski 
524d5317b41SMichał Górny   if (new_xstate_bv != 0)
525d5317b41SMichał Górny     reinterpret_cast<xstate *>(m_xstate.data())->xs_xstate_bv |= new_xstate_bv;
526a984404fSMichal Gorny   return WriteRegisterSet(set);
527f07a9995SKamil Rytarowski }
528f07a9995SKamil Rytarowski 
ReadAllRegisterValues(lldb::WritableDataBufferSP & data_sp)52997206d57SZachary Turner Status NativeRegisterContextNetBSD_x86_64::ReadAllRegisterValues(
530c2f64601SJonas Devlieghere     lldb::WritableDataBufferSP &data_sp) {
53197206d57SZachary Turner   Status error;
532f07a9995SKamil Rytarowski 
533f07a9995SKamil Rytarowski   data_sp.reset(new DataBufferHeap(REG_CONTEXT_SIZE, 0));
534d687fa7dSMichal Gorny   error = ReadRegisterSet(GPRegSet);
535f07a9995SKamil Rytarowski   if (error.Fail())
536f07a9995SKamil Rytarowski     return error;
537f07a9995SKamil Rytarowski 
538f07a9995SKamil Rytarowski   uint8_t *dst = data_sp->GetBytes();
539d5317b41SMichał Górny   ::memcpy(dst, m_gpr.data(), GetRegisterInfoInterface().GetGPRSize());
540f07a9995SKamil Rytarowski   dst += GetRegisterInfoInterface().GetGPRSize();
541f07a9995SKamil Rytarowski 
542f07a9995SKamil Rytarowski   return error;
543f07a9995SKamil Rytarowski }
544f07a9995SKamil Rytarowski 
WriteAllRegisterValues(const lldb::DataBufferSP & data_sp)54597206d57SZachary Turner Status NativeRegisterContextNetBSD_x86_64::WriteAllRegisterValues(
546f07a9995SKamil Rytarowski     const lldb::DataBufferSP &data_sp) {
54797206d57SZachary Turner   Status error;
548f07a9995SKamil Rytarowski 
549f07a9995SKamil Rytarowski   if (!data_sp) {
550f07a9995SKamil Rytarowski     error.SetErrorStringWithFormat(
551f07a9995SKamil Rytarowski         "NativeRegisterContextNetBSD_x86_64::%s invalid data_sp provided",
552f07a9995SKamil Rytarowski         __FUNCTION__);
553f07a9995SKamil Rytarowski     return error;
554f07a9995SKamil Rytarowski   }
555f07a9995SKamil Rytarowski 
556f07a9995SKamil Rytarowski   if (data_sp->GetByteSize() != REG_CONTEXT_SIZE) {
557f07a9995SKamil Rytarowski     error.SetErrorStringWithFormat(
558f07a9995SKamil Rytarowski         "NativeRegisterContextNetBSD_x86_64::%s data_sp contained mismatched "
5595cc817beSMichał Górny         "data size, expected %zu, actual %" PRIu64,
560f07a9995SKamil Rytarowski         __FUNCTION__, REG_CONTEXT_SIZE, data_sp->GetByteSize());
561f07a9995SKamil Rytarowski     return error;
562f07a9995SKamil Rytarowski   }
563f07a9995SKamil Rytarowski 
564*470eb5c2SJonas Devlieghere   const uint8_t *src = data_sp->GetBytes();
565f07a9995SKamil Rytarowski   if (src == nullptr) {
566f07a9995SKamil Rytarowski     error.SetErrorStringWithFormat("NativeRegisterContextNetBSD_x86_64::%s "
567f07a9995SKamil Rytarowski                                    "DataBuffer::GetBytes() returned a null "
568f07a9995SKamil Rytarowski                                    "pointer",
569f07a9995SKamil Rytarowski                                    __FUNCTION__);
570f07a9995SKamil Rytarowski     return error;
571f07a9995SKamil Rytarowski   }
572d5317b41SMichał Górny   ::memcpy(m_gpr.data(), src, GetRegisterInfoInterface().GetGPRSize());
573f07a9995SKamil Rytarowski 
574d687fa7dSMichal Gorny   error = WriteRegisterSet(GPRegSet);
575f07a9995SKamil Rytarowski   if (error.Fail())
576f07a9995SKamil Rytarowski     return error;
577f07a9995SKamil Rytarowski   src += GetRegisterInfoInterface().GetGPRSize();
578f07a9995SKamil Rytarowski 
579f07a9995SKamil Rytarowski   return error;
580f07a9995SKamil Rytarowski }
581f07a9995SKamil Rytarowski 
CopyHardwareWatchpointsFrom(NativeRegisterContextNetBSD & source)582f21e704dSMichał Górny llvm::Error NativeRegisterContextNetBSD_x86_64::CopyHardwareWatchpointsFrom(
583d970d4d4SMichał Górny     NativeRegisterContextNetBSD &source) {
584d970d4d4SMichał Górny   auto &r_source = static_cast<NativeRegisterContextNetBSD_x86_64 &>(source);
585d5317b41SMichał Górny   // NB: This implicitly reads the whole dbreg set.
586d5317b41SMichał Górny   RegisterValue dr7;
587d5317b41SMichał Górny   Status res = r_source.ReadRegister(GetDR(7), dr7);
588d970d4d4SMichał Górny   if (!res.Fail()) {
589d970d4d4SMichał Górny     // copy dbregs only if any watchpoints were set
590d5317b41SMichał Górny     if ((dr7.GetAsUInt64() & 0xFF) == 0)
591f21e704dSMichał Górny       return llvm::Error::success();
592d970d4d4SMichał Górny 
5935cc817beSMichał Górny     m_dbr = r_source.m_dbr;
594d970d4d4SMichał Górny     res = WriteRegisterSet(DBRegSet);
595d970d4d4SMichał Górny   }
596f21e704dSMichał Górny   return res.ToError();
597d970d4d4SMichał Górny }
598d970d4d4SMichał Górny 
599d5317b41SMichał Górny uint8_t *
GetOffsetRegSetData(RegSetKind set,size_t reg_offset)600d5317b41SMichał Górny NativeRegisterContextNetBSD_x86_64::GetOffsetRegSetData(RegSetKind set,
601d5317b41SMichał Górny                                                         size_t reg_offset) {
602d5317b41SMichał Górny   uint8_t *base;
603d5317b41SMichał Górny   switch (set) {
604d5317b41SMichał Górny   case GPRegSet:
605d5317b41SMichał Górny     base = m_gpr.data();
606d5317b41SMichał Górny     break;
607d5317b41SMichał Górny   case FPRegSet:
608d5317b41SMichał Górny     base = m_xstate.data() + offsetof(xstate, xs_fxsave);
609d5317b41SMichał Górny     break;
610d5317b41SMichał Górny   case DBRegSet:
611d5317b41SMichał Górny     base = m_dbr.data();
612d5317b41SMichał Górny     break;
613d5317b41SMichał Górny   case YMMRegSet:
614d5317b41SMichał Górny     llvm_unreachable("GetRegSetData() is unsuitable for this regset.");
615d5317b41SMichał Górny   case MPXRegSet:
616d5317b41SMichał Górny     llvm_unreachable("MPX regset should have returned error");
617d5317b41SMichał Górny   }
618d5317b41SMichał Górny   assert(reg_offset >= m_regset_offsets[set]);
619d5317b41SMichał Górny   return base + (reg_offset - m_regset_offsets[set]);
620d5317b41SMichał Górny }
621d5317b41SMichał Górny 
622d5317b41SMichał Górny llvm::Optional<NativeRegisterContextNetBSD_x86_64::YMMSplitPtr>
GetYMMSplitReg(uint32_t reg)623d5317b41SMichał Górny NativeRegisterContextNetBSD_x86_64::GetYMMSplitReg(uint32_t reg) {
624d5317b41SMichał Górny   auto xst = reinterpret_cast<xstate *>(m_xstate.data());
625d5317b41SMichał Górny   if (!(xst->xs_rfbm & XCR0_SSE) || !(xst->xs_rfbm & XCR0_YMM_Hi128))
626d5317b41SMichał Górny     return llvm::None;
627d5317b41SMichał Górny 
628d5317b41SMichał Górny   uint32_t reg_index;
629d5317b41SMichał Górny   switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
630d5317b41SMichał Górny   case llvm::Triple::x86:
631d5317b41SMichał Górny     reg_index = reg - lldb_ymm0_i386;
632d5317b41SMichał Górny     break;
633d5317b41SMichał Górny   case llvm::Triple::x86_64:
634d5317b41SMichał Górny     reg_index = reg - lldb_ymm0_x86_64;
635d5317b41SMichał Górny     break;
636d5317b41SMichał Górny   default:
637d5317b41SMichał Górny     llvm_unreachable("Unhandled target architecture.");
638d5317b41SMichał Górny   }
639d5317b41SMichał Górny 
640d5317b41SMichał Górny   return YMMSplitPtr{&xst->xs_fxsave.fx_xmm[reg_index],
641d5317b41SMichał Górny                      &xst->xs_ymm_hi128.xs_ymm[reg_index]};
642d5317b41SMichał Górny }
643d5317b41SMichał Górny 
644f07a9995SKamil Rytarowski #endif // defined(__x86_64__)
645