Index: lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h =================================================================== --- lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h +++ lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.h @@ -32,6 +32,11 @@ class NativeProcessFreeBSD; +struct YMMSplitPtr { + void *xmm; + void *ymm_hi; +}; + class NativeRegisterContextFreeBSD_x86_64 : public NativeRegisterContextFreeBSD, public NativeRegisterContextWatchpoint_x86 { @@ -58,15 +63,13 @@ private: // Private member types. enum RegSetKind { + YMMRegSet, + MaxXSaveSet = YMMRegSet, + GPRegSet, FPRegSet, - XSaveRegSet, DBRegSet, }; - enum { - YMMXSaveSet, - MaxXSaveSet = YMMXSaveSet, - }; // Private member variables. std::array m_gpr; @@ -82,6 +85,7 @@ size_t GetFPROffset() const; size_t GetDBROffset() const; + llvm::Optional GetYMMSplitReg(uint32_t reg); }; } // namespace process_freebsd Index: lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp =================================================================== --- lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp +++ lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_x86_64.cpp @@ -275,31 +275,6 @@ } } -static constexpr int RegNumX86ToX86_64(int regnum) { - switch (regnum) { - case lldb_ymm0_i386: - case lldb_ymm1_i386: - case lldb_ymm2_i386: - case lldb_ymm3_i386: - case lldb_ymm4_i386: - case lldb_ymm5_i386: - case lldb_ymm6_i386: - case lldb_ymm7_i386: - return lldb_ymm0_x86_64 + regnum - lldb_ymm0_i386; - case lldb_bnd0_i386: - case lldb_bnd1_i386: - case lldb_bnd2_i386: - case lldb_bnd3_i386: - return lldb_bnd0_x86_64 + regnum - lldb_bnd0_i386; - case lldb_bndcfgu_i386: - return lldb_bndcfgu_x86_64; - case lldb_bndstatus_i386: - return lldb_bndstatus_x86_64; - default: - llvm_unreachable("Unhandled i386 register."); - } -} - llvm::Optional NativeRegisterContextFreeBSD_x86_64::GetSetForNativeRegNum(int reg_num) const { switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { @@ -309,7 +284,7 @@ if (reg_num >= k_first_fpr_i386 && reg_num <= k_last_fpr_i386) return FPRegSet; if (reg_num >= k_first_avx_i386 && reg_num <= k_last_avx_i386) - return XSaveRegSet; // AVX + return YMMRegSet; if (reg_num >= k_first_mpxr_i386 && reg_num <= k_last_mpxr_i386) return llvm::None; // MPXR if (reg_num >= k_first_mpxc_i386 && reg_num <= k_last_mpxc_i386) @@ -323,7 +298,7 @@ if (reg_num >= k_first_fpr_x86_64 && reg_num <= k_last_fpr_x86_64) return FPRegSet; if (reg_num >= k_first_avx_x86_64 && reg_num <= k_last_avx_x86_64) - return XSaveRegSet; // AVX + return YMMRegSet; if (reg_num >= k_first_mpxr_x86_64 && reg_num <= k_last_mpxr_x86_64) return llvm::None; // MPXR if (reg_num >= k_first_mpxc_x86_64 && reg_num <= k_last_mpxc_x86_64) @@ -354,7 +329,7 @@ case DBRegSet: return NativeProcessFreeBSD::PtraceWrapper(PT_GETDBREGS, m_thread.GetID(), m_dbr.data()); - case XSaveRegSet: { + case YMMRegSet: { struct ptrace_xstate_info info; Status ret = NativeProcessFreeBSD::PtraceWrapper( PT_GETXSTATE_INFO, GetProcessPid(), &info, sizeof(info)); @@ -364,10 +339,10 @@ assert(info.xsave_mask & XFEATURE_ENABLED_X87); assert(info.xsave_mask & XFEATURE_ENABLED_SSE); - m_xsave_offsets[YMMXSaveSet] = LLDB_INVALID_XSAVE_OFFSET; + m_xsave_offsets[YMMRegSet] = LLDB_INVALID_XSAVE_OFFSET; if (info.xsave_mask & XFEATURE_ENABLED_YMM_HI128) { uint32_t eax, ecx, edx; - __get_cpuid_count(0x0D, 2, &eax, &m_xsave_offsets[YMMXSaveSet], &ecx, + __get_cpuid_count(0x0D, 2, &eax, &m_xsave_offsets[YMMRegSet], &ecx, &edx); } @@ -395,7 +370,7 @@ case DBRegSet: return NativeProcessFreeBSD::PtraceWrapper(PT_SETDBREGS, m_thread.GetID(), m_dbr.data()); - case XSaveRegSet: + case YMMRegSet: // ReadRegisterSet() must always be called before WriteRegisterSet(). assert(m_xsave.size() > 0); return NativeProcessFreeBSD::PtraceWrapper(PT_SETXSTATE, GetProcessPid(), @@ -442,66 +417,27 @@ case GPRegSet: reg_value.SetBytes(m_gpr.data() + reg_info->byte_offset, reg_info->byte_size, endian::InlHostByteOrder()); - return error; + break; case FPRegSet: reg_value.SetBytes(m_fpr.data() + reg_info->byte_offset - GetFPROffset(), reg_info->byte_size, endian::InlHostByteOrder()); - return error; + break; case DBRegSet: reg_value.SetBytes(m_dbr.data() + reg_info->byte_offset - GetDBROffset(), reg_info->byte_size, endian::InlHostByteOrder()); - return error; - case XSaveRegSet: - // legacy logic break; - } - - switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { - case llvm::Triple::x86_64: - break; - case llvm::Triple::x86: - reg = RegNumX86ToX86_64(reg); - break; - default: - llvm_unreachable("Unhandled target architecture."); - } - - switch (reg) { - case lldb_ymm0_x86_64: - case lldb_ymm1_x86_64: - case lldb_ymm2_x86_64: - case lldb_ymm3_x86_64: - case lldb_ymm4_x86_64: - case lldb_ymm5_x86_64: - case lldb_ymm6_x86_64: - case lldb_ymm7_x86_64: - case lldb_ymm8_x86_64: - case lldb_ymm9_x86_64: - case lldb_ymm10_x86_64: - case lldb_ymm11_x86_64: - case lldb_ymm12_x86_64: - case lldb_ymm13_x86_64: - case lldb_ymm14_x86_64: - case lldb_ymm15_x86_64: { - uint32_t offset = m_xsave_offsets[YMMXSaveSet]; - if (offset == LLDB_INVALID_XSAVE_OFFSET) { + case YMMRegSet: { + llvm::Optional ymm_reg = GetYMMSplitReg(reg); + if (!ymm_reg) { error.SetErrorStringWithFormat( "register \"%s\" not supported by CPU/kernel", reg_info->name); } else { - uint32_t reg_index = reg - lldb_ymm0_x86_64; - auto *fpreg = reinterpret_cast(m_xsave.data()); - auto *ymmreg = reinterpret_cast(m_xsave.data() + offset); - - YMMReg ymm = - XStateToYMM(reinterpret_cast(&fpreg->sv_xmm[reg_index]), - reinterpret_cast(&ymmreg[reg_index])); + YMMReg ymm = XStateToYMM(ymm_reg->xmm, ymm_reg->ymm_hi); reg_value.SetBytes(ymm.bytes, reg_info->byte_size, endian::InlHostByteOrder()); } break; } - default: - llvm_unreachable("Reading unknown/unsupported register"); } return error; @@ -545,65 +481,27 @@ case GPRegSet: ::memcpy(m_gpr.data() + reg_info->byte_offset, reg_value.GetBytes(), reg_value.GetByteSize()); - return WriteRegisterSet(set); + break; case FPRegSet: ::memcpy(m_fpr.data() + reg_info->byte_offset - GetFPROffset(), reg_value.GetBytes(), reg_value.GetByteSize()); - return WriteRegisterSet(set); + break; case DBRegSet: ::memcpy(m_dbr.data() + reg_info->byte_offset - GetDBROffset(), reg_value.GetBytes(), reg_value.GetByteSize()); - return WriteRegisterSet(set); - case XSaveRegSet: - // legacy logic - break; - } - - switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { - case llvm::Triple::x86_64: break; - case llvm::Triple::x86: - reg = RegNumX86ToX86_64(reg); - break; - default: - llvm_unreachable("Unhandled target architecture."); - } - - switch (reg) { - case lldb_ymm0_x86_64: - case lldb_ymm1_x86_64: - case lldb_ymm2_x86_64: - case lldb_ymm3_x86_64: - case lldb_ymm4_x86_64: - case lldb_ymm5_x86_64: - case lldb_ymm6_x86_64: - case lldb_ymm7_x86_64: - case lldb_ymm8_x86_64: - case lldb_ymm9_x86_64: - case lldb_ymm10_x86_64: - case lldb_ymm11_x86_64: - case lldb_ymm12_x86_64: - case lldb_ymm13_x86_64: - case lldb_ymm14_x86_64: - case lldb_ymm15_x86_64: { - uint32_t offset = m_xsave_offsets[YMMXSaveSet]; - if (offset == LLDB_INVALID_XSAVE_OFFSET) { + case YMMRegSet: { + llvm::Optional ymm_reg = GetYMMSplitReg(reg); + if (!ymm_reg) { error.SetErrorStringWithFormat( "register \"%s\" not supported by CPU/kernel", reg_info->name); } else { - uint32_t reg_index = reg - lldb_ymm0_x86_64; - auto *fpreg = reinterpret_cast(m_xsave.data()); - auto *ymmreg = reinterpret_cast(m_xsave.data() + offset); - YMMReg ymm; ::memcpy(ymm.bytes, reg_value.GetBytes(), reg_value.GetByteSize()); - YMMToXState(ymm, reinterpret_cast(&fpreg->sv_xmm[reg_index]), - reinterpret_cast(&ymmreg[reg_index])); + YMMToXState(ymm, ymm_reg->xmm, ymm_reg->ymm_hi); } break; } - default: - llvm_unreachable("Reading unknown/unsupported register"); } return WriteRegisterSet(set); @@ -711,4 +609,28 @@ return GetRegisterInfoInterface().GetRegisterInfo()[regno].byte_offset; } +llvm::Optional +NativeRegisterContextFreeBSD_x86_64::GetYMMSplitReg(uint32_t reg) { + uint32_t offset = m_xsave_offsets[YMMRegSet]; + if (offset == LLDB_INVALID_XSAVE_OFFSET) + return llvm::None; + + uint32_t reg_index; + switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) { + case llvm::Triple::x86: + reg_index = reg - lldb_ymm0_i386; + break; + case llvm::Triple::x86_64: + reg_index = reg - lldb_ymm0_x86_64; + break; + default: + llvm_unreachable("Unhandled target architecture."); + } + + auto *fpreg = reinterpret_cast(m_xsave.data()); + auto *ymmreg = reinterpret_cast(m_xsave.data() + offset); + + return YMMSplitPtr{&fpreg->sv_xmm[reg_index], &ymmreg[reg_index]}; +} + #endif // defined(__x86_64__)