1326949Sdim//===-- RegisterContextPOSIXCore_ppc64le.cpp --------------------*- C++ -*-===//
2326949Sdim//
3353358Sdim// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4353358Sdim// See https://llvm.org/LICENSE.txt for license information.
5353358Sdim// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6326949Sdim//
7326949Sdim//===----------------------------------------------------------------------===//
8326949Sdim
9326949Sdim#include "RegisterContextPOSIXCore_ppc64le.h"
10326949Sdim
11326949Sdim#include "lldb/Target/Thread.h"
12326949Sdim#include "lldb/Utility/DataBufferHeap.h"
13344779Sdim#include "lldb/Utility/RegisterValue.h"
14326949Sdim
15326949Sdim#include "Plugins/Process/Utility/lldb-ppc64le-register-enums.h"
16326949Sdim#include "Plugins/Process/elf-core/RegisterUtilities.h"
17326949Sdim
18353358Sdim#include <memory>
19353358Sdim
20326949Sdimusing namespace lldb_private;
21326949Sdim
22326949SdimRegisterContextCorePOSIX_ppc64le::RegisterContextCorePOSIX_ppc64le(
23326949Sdim    Thread &thread, RegisterInfoInterface *register_info,
24326949Sdim    const DataExtractor &gpregset, llvm::ArrayRef<CoreNote> notes)
25326949Sdim    : RegisterContextPOSIX_ppc64le(thread, 0, register_info) {
26353358Sdim  m_gpr_buffer = std::make_shared<DataBufferHeap>(gpregset.GetDataStart(),
27353358Sdim                                                  gpregset.GetByteSize());
28326949Sdim  m_gpr.SetData(m_gpr_buffer);
29326949Sdim  m_gpr.SetByteOrder(gpregset.GetByteOrder());
30326949Sdim
31326949Sdim  ArchSpec arch = register_info->GetTargetArchitecture();
32326949Sdim  DataExtractor fpregset = getRegset(notes, arch.GetTriple(), FPR_Desc);
33353358Sdim  m_fpr_buffer = std::make_shared<DataBufferHeap>(fpregset.GetDataStart(),
34353358Sdim                                                  fpregset.GetByteSize());
35326949Sdim  m_fpr.SetData(m_fpr_buffer);
36326949Sdim  m_fpr.SetByteOrder(fpregset.GetByteOrder());
37326949Sdim
38326949Sdim  DataExtractor vmxregset = getRegset(notes, arch.GetTriple(), PPC_VMX_Desc);
39353358Sdim  m_vmx_buffer = std::make_shared<DataBufferHeap>(vmxregset.GetDataStart(),
40353358Sdim                                                  vmxregset.GetByteSize());
41326949Sdim  m_vmx.SetData(m_vmx_buffer);
42326949Sdim  m_vmx.SetByteOrder(vmxregset.GetByteOrder());
43326949Sdim
44326949Sdim  DataExtractor vsxregset = getRegset(notes, arch.GetTriple(), PPC_VSX_Desc);
45353358Sdim  m_vsx_buffer = std::make_shared<DataBufferHeap>(vsxregset.GetDataStart(),
46353358Sdim                                                  vsxregset.GetByteSize());
47326949Sdim  m_vsx.SetData(m_vsx_buffer);
48326949Sdim  m_vsx.SetByteOrder(vsxregset.GetByteOrder());
49326949Sdim}
50326949Sdim
51326949Sdimsize_t RegisterContextCorePOSIX_ppc64le::GetFPRSize() const {
52326949Sdim  return k_num_fpr_registers_ppc64le * sizeof(uint64_t);
53326949Sdim}
54326949Sdim
55326949Sdimsize_t RegisterContextCorePOSIX_ppc64le::GetVMXSize() const {
56326949Sdim  return (k_num_vmx_registers_ppc64le - 1) * sizeof(uint64_t) * 2 +
57326949Sdim         sizeof(uint32_t);
58326949Sdim}
59326949Sdim
60326949Sdimsize_t RegisterContextCorePOSIX_ppc64le::GetVSXSize() const {
61326949Sdim  return k_num_vsx_registers_ppc64le * sizeof(uint64_t) * 2;
62326949Sdim}
63326949Sdim
64326949Sdimbool RegisterContextCorePOSIX_ppc64le::ReadRegister(
65326949Sdim    const RegisterInfo *reg_info, RegisterValue &value) {
66326949Sdim  lldb::offset_t offset = reg_info->byte_offset;
67326949Sdim
68326949Sdim  if (IsFPR(reg_info->kinds[lldb::eRegisterKindLLDB])) {
69326949Sdim    uint64_t v;
70326949Sdim    offset -= GetGPRSize();
71326949Sdim    offset = m_fpr.CopyData(offset, reg_info->byte_size, &v);
72326949Sdim
73326949Sdim    if (offset == reg_info->byte_size) {
74326949Sdim      value.SetBytes(&v, reg_info->byte_size, m_fpr.GetByteOrder());
75326949Sdim      return true;
76326949Sdim    }
77326949Sdim  } else if (IsVMX(reg_info->kinds[lldb::eRegisterKindLLDB])) {
78326949Sdim    uint32_t v[4];
79326949Sdim    offset -= GetGPRSize() + GetFPRSize();
80326949Sdim    offset = m_vmx.CopyData(offset, reg_info->byte_size, &v);
81326949Sdim
82326949Sdim    if (offset == reg_info->byte_size) {
83326949Sdim      value.SetBytes(v, reg_info->byte_size, m_vmx.GetByteOrder());
84326949Sdim      return true;
85326949Sdim    }
86326949Sdim  } else if (IsVSX(reg_info->kinds[lldb::eRegisterKindLLDB])) {
87326949Sdim    uint32_t v[4];
88326949Sdim    lldb::offset_t tmp_offset;
89326949Sdim    offset -= GetGPRSize() + GetFPRSize() + GetVMXSize();
90326949Sdim
91326949Sdim    if (offset < GetVSXSize() / 2) {
92326949Sdim      tmp_offset = m_vsx.CopyData(offset / 2, reg_info->byte_size / 2, &v);
93326949Sdim
94326949Sdim      if (tmp_offset != reg_info->byte_size / 2) {
95326949Sdim        return false;
96326949Sdim      }
97326949Sdim
98326949Sdim      uint8_t *dst = (uint8_t *)&v + sizeof(uint64_t);
99326949Sdim      tmp_offset = m_fpr.CopyData(offset / 2, reg_info->byte_size / 2, dst);
100326949Sdim
101326949Sdim      if (tmp_offset != reg_info->byte_size / 2) {
102326949Sdim        return false;
103326949Sdim      }
104326949Sdim
105326949Sdim      value.SetBytes(&v, reg_info->byte_size, m_vsx.GetByteOrder());
106326949Sdim      return true;
107326949Sdim    } else {
108326949Sdim      offset =
109326949Sdim          m_vmx.CopyData(offset - GetVSXSize() / 2, reg_info->byte_size, &v);
110326949Sdim      if (offset == reg_info->byte_size) {
111326949Sdim        value.SetBytes(v, reg_info->byte_size, m_vmx.GetByteOrder());
112326949Sdim        return true;
113326949Sdim      }
114326949Sdim    }
115326949Sdim  } else {
116326949Sdim    uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size);
117326949Sdim
118326949Sdim    if (offset == reg_info->byte_offset + reg_info->byte_size) {
119326949Sdim      if (reg_info->byte_size < sizeof(v))
120326949Sdim        value = (uint32_t)v;
121326949Sdim      else
122326949Sdim        value = v;
123326949Sdim      return true;
124326949Sdim    }
125326949Sdim  }
126326949Sdim
127326949Sdim  return false;
128326949Sdim}
129326949Sdim
130326949Sdimbool RegisterContextCorePOSIX_ppc64le::WriteRegister(
131326949Sdim    const RegisterInfo *reg_info, const RegisterValue &value) {
132326949Sdim  return false;
133326949Sdim}
134