[Lldb-commits] [lldb] bd03f6d - [lldb] [Process/FreeBSDRemote] Introduce powerpc support

Michał Górny via lldb-commits lldb-commits at lists.llvm.org
Tue Feb 9 12:29:19 PST 2021


Author: Michał Górny
Date: 2021-02-09T21:10:45+01:00
New Revision: bd03f6df51d161551a0439d8f51e2640a218048f

URL: https://github.com/llvm/llvm-project/commit/bd03f6df51d161551a0439d8f51e2640a218048f
DIFF: https://github.com/llvm/llvm-project/commit/bd03f6df51d161551a0439d8f51e2640a218048f.diff

LOG: [lldb] [Process/FreeBSDRemote] Introduce powerpc support

Introduce a minimal support for the 32-bit powerpc platform.  This
includes support for GPR and FPR registers.  I also needed to add
software breakpoint opcode for PPC32/PPC64 (big endian), and to fix
offsets in RegisterInfos_powerpc.h (used only by FreeBSD register
context to be globally unique rather than relative to each struct).

Differential Revision: https://reviews.llvm.org/D95947

Added: 
    lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_powerpc.cpp
    lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_powerpc.h

Modified: 
    lldb/source/Host/common/NativeProcessProtocol.cpp
    lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
    lldb/source/Plugins/Process/FreeBSDRemote/CMakeLists.txt
    lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
    lldb/unittests/Process/Utility/RegisterContextFreeBSDTest.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/source/Host/common/NativeProcessProtocol.cpp b/lldb/source/Host/common/NativeProcessProtocol.cpp
index 493e14cb904b..070fda664678 100644
--- a/lldb/source/Host/common/NativeProcessProtocol.cpp
+++ b/lldb/source/Host/common/NativeProcessProtocol.cpp
@@ -522,7 +522,8 @@ NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
   static const uint8_t g_mips64_opcode[] = {0x00, 0x00, 0x00, 0x0d};
   static const uint8_t g_mips64el_opcode[] = {0x0d, 0x00, 0x00, 0x00};
   static const uint8_t g_s390x_opcode[] = {0x00, 0x01};
-  static const uint8_t g_ppc64le_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap
+  static const uint8_t g_ppc_opcode[] = {0x7f, 0xe0, 0x00, 0x08}; // trap
+  static const uint8_t g_ppcle_opcode[] = {0x08, 0x00, 0xe0, 0x7f}; // trap
 
   switch (GetArchitecture().GetMachine()) {
   case llvm::Triple::aarch64:
@@ -544,8 +545,12 @@ NativeProcessProtocol::GetSoftwareBreakpointTrapOpcode(size_t size_hint) {
   case llvm::Triple::systemz:
     return llvm::makeArrayRef(g_s390x_opcode);
 
+  case llvm::Triple::ppc:
+  case llvm::Triple::ppc64:
+    return llvm::makeArrayRef(g_ppc_opcode);
+
   case llvm::Triple::ppc64le:
-    return llvm::makeArrayRef(g_ppc64le_opcode);
+    return llvm::makeArrayRef(g_ppcle_opcode);
 
   default:
     return llvm::createStringError(llvm::inconvertibleErrorCode(),
@@ -568,6 +573,8 @@ size_t NativeProcessProtocol::GetSoftwareBreakpointPCOffset() {
   case llvm::Triple::mips64el:
   case llvm::Triple::mips:
   case llvm::Triple::mipsel:
+  case llvm::Triple::ppc:
+  case llvm::Triple::ppc64:
   case llvm::Triple::ppc64le:
     // On these architectures the PC doesn't get updated for breakpoint hits.
     return 0;

diff  --git a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
index 7994e602703a..e16c573b93f9 100644
--- a/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
+++ b/lldb/source/Plugins/Platform/FreeBSD/PlatformFreeBSD.cpp
@@ -256,6 +256,7 @@ bool PlatformFreeBSD::CanDebugProcess() {
       case llvm::Triple::aarch64:
       case llvm::Triple::arm:
       case llvm::Triple::mips64:
+      case llvm::Triple::ppc:
       case llvm::Triple::x86:
       case llvm::Triple::x86_64:
         use_legacy_plugin = !!getenv("FREEBSD_LEGACY_PLUGIN");

diff  --git a/lldb/source/Plugins/Process/FreeBSDRemote/CMakeLists.txt b/lldb/source/Plugins/Process/FreeBSDRemote/CMakeLists.txt
index 826d7162967a..7480154d9998 100644
--- a/lldb/source/Plugins/Process/FreeBSDRemote/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/FreeBSDRemote/CMakeLists.txt
@@ -4,6 +4,7 @@ add_lldb_library(lldbPluginProcessFreeBSDRemote
   NativeRegisterContextFreeBSD_arm.cpp
   NativeRegisterContextFreeBSD_arm64.cpp
   NativeRegisterContextFreeBSD_mips64.cpp
+  NativeRegisterContextFreeBSD_powerpc.cpp
   NativeRegisterContextFreeBSD_x86_64.cpp
   NativeThreadFreeBSD.cpp
 

diff  --git a/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_powerpc.cpp b/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_powerpc.cpp
new file mode 100644
index 000000000000..f923507b595d
--- /dev/null
+++ b/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_powerpc.cpp
@@ -0,0 +1,289 @@
+//===-- NativeRegisterContextFreeBSD_powerpc.cpp --------------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__powerpc__)
+
+#include "NativeRegisterContextFreeBSD_powerpc.h"
+
+#include "lldb/Host/HostInfo.h"
+#include "lldb/Utility/DataBufferHeap.h"
+#include "lldb/Utility/RegisterValue.h"
+#include "lldb/Utility/Status.h"
+
+#include "Plugins/Process/FreeBSDRemote/NativeProcessFreeBSD.h"
+// for register enum definitions
+#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
+
+// clang-format off
+#include <sys/param.h>
+#include <sys/ptrace.h>
+#include <sys/types.h>
+// clang-format on
+
+using namespace lldb;
+using namespace lldb_private;
+using namespace lldb_private::process_freebsd;
+
+static const uint32_t g_gpr_regnums[] = {
+    gpr_r0_powerpc,  gpr_r1_powerpc,  gpr_r2_powerpc,  gpr_r3_powerpc,
+    gpr_r4_powerpc,  gpr_r5_powerpc,  gpr_r6_powerpc,  gpr_r7_powerpc,
+    gpr_r8_powerpc,  gpr_r9_powerpc,  gpr_r10_powerpc, gpr_r11_powerpc,
+    gpr_r12_powerpc, gpr_r13_powerpc, gpr_r14_powerpc, gpr_r15_powerpc,
+    gpr_r16_powerpc, gpr_r17_powerpc, gpr_r18_powerpc, gpr_r19_powerpc,
+    gpr_r20_powerpc, gpr_r21_powerpc, gpr_r22_powerpc, gpr_r23_powerpc,
+    gpr_r24_powerpc, gpr_r25_powerpc, gpr_r26_powerpc, gpr_r27_powerpc,
+    gpr_r28_powerpc, gpr_r29_powerpc, gpr_r30_powerpc, gpr_r31_powerpc,
+    gpr_lr_powerpc,  gpr_cr_powerpc,  gpr_xer_powerpc, gpr_ctr_powerpc,
+    gpr_pc_powerpc,
+};
+
+static const uint32_t g_fpr_regnums[] = {
+    fpr_f0_powerpc,    fpr_f1_powerpc,  fpr_f2_powerpc,  fpr_f3_powerpc,
+    fpr_f4_powerpc,    fpr_f5_powerpc,  fpr_f6_powerpc,  fpr_f7_powerpc,
+    fpr_f8_powerpc,    fpr_f9_powerpc,  fpr_f10_powerpc, fpr_f11_powerpc,
+    fpr_f12_powerpc,   fpr_f13_powerpc, fpr_f14_powerpc, fpr_f15_powerpc,
+    fpr_f16_powerpc,   fpr_f17_powerpc, fpr_f18_powerpc, fpr_f19_powerpc,
+    fpr_f20_powerpc,   fpr_f21_powerpc, fpr_f22_powerpc, fpr_f23_powerpc,
+    fpr_f24_powerpc,   fpr_f25_powerpc, fpr_f26_powerpc, fpr_f27_powerpc,
+    fpr_f28_powerpc,   fpr_f29_powerpc, fpr_f30_powerpc, fpr_f31_powerpc,
+    fpr_fpscr_powerpc,
+};
+
+// Number of register sets provided by this context.
+enum { k_num_register_sets = 2 };
+
+static const RegisterSet g_reg_sets_powerpc[k_num_register_sets] = {
+    {"General Purpose Registers", "gpr", k_num_gpr_registers_powerpc,
+     g_gpr_regnums},
+    {"Floating Point Registers", "fpr", k_num_fpr_registers_powerpc,
+     g_fpr_regnums},
+};
+
+NativeRegisterContextFreeBSD *
+NativeRegisterContextFreeBSD::CreateHostNativeRegisterContextFreeBSD(
+    const ArchSpec &target_arch, NativeThreadProtocol &native_thread) {
+  return new NativeRegisterContextFreeBSD_powerpc(target_arch, native_thread);
+}
+
+static RegisterInfoInterface *
+CreateRegisterInfoInterface(const ArchSpec &target_arch) {
+  if (HostInfo::GetArchitecture().GetAddressByteSize() == 4) {
+    return new RegisterContextFreeBSD_powerpc32(target_arch);
+  } else {
+    assert((HostInfo::GetArchitecture().GetAddressByteSize() == 8) &&
+           "Register setting path assumes this is a 64-bit host");
+    return new RegisterContextFreeBSD_powerpc64(target_arch);
+  }
+}
+
+NativeRegisterContextFreeBSD_powerpc::NativeRegisterContextFreeBSD_powerpc(
+    const ArchSpec &target_arch, NativeThreadProtocol &native_thread)
+    : NativeRegisterContextRegisterInfo(
+          native_thread, CreateRegisterInfoInterface(target_arch)) {}
+
+RegisterContextFreeBSD_powerpc &
+NativeRegisterContextFreeBSD_powerpc::GetRegisterInfo() const {
+  return static_cast<RegisterContextFreeBSD_powerpc &>(*m_register_info_interface_up);
+}
+
+uint32_t NativeRegisterContextFreeBSD_powerpc::GetRegisterSetCount() const {
+  return k_num_register_sets;
+}
+
+const RegisterSet *
+NativeRegisterContextFreeBSD_powerpc::GetRegisterSet(uint32_t set_index) const {
+  switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
+  case llvm::Triple::ppc:
+    return &g_reg_sets_powerpc[set_index];
+  default:
+    llvm_unreachable("Unhandled target architecture.");
+  }
+}
+
+llvm::Optional<NativeRegisterContextFreeBSD_powerpc::RegSetKind>
+NativeRegisterContextFreeBSD_powerpc::GetSetForNativeRegNum(
+    uint32_t reg_num) const {
+  switch (GetRegisterInfoInterface().GetTargetArchitecture().GetMachine()) {
+  case llvm::Triple::ppc:
+    if (reg_num >= k_first_gpr_powerpc && reg_num <= k_last_gpr_powerpc)
+      return GPRegSet;
+    if (reg_num >= k_first_fpr && reg_num <= k_last_fpr)
+      return FPRegSet;
+    break;
+  default:
+    llvm_unreachable("Unhandled target architecture.");
+  }
+
+  llvm_unreachable("Register does not belong to any register set");
+}
+
+
+uint32_t NativeRegisterContextFreeBSD_powerpc::GetUserRegisterCount() const {
+  uint32_t count = 0;
+  for (uint32_t set_index = 0; set_index < GetRegisterSetCount(); ++set_index)
+    count += GetRegisterSet(set_index)->num_registers;
+  return count;
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet(RegSetKind set) {
+  switch (set) {
+  case GPRegSet:
+    return NativeProcessFreeBSD::PtraceWrapper(PT_GETREGS, m_thread.GetID(),
+                                               m_reg_data.data());
+  case FPRegSet:
+    return NativeProcessFreeBSD::PtraceWrapper(
+        PT_GETFPREGS, m_thread.GetID(), m_reg_data.data() + sizeof(reg));
+  }
+  llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::ReadRegisterSet");
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet(RegSetKind set) {
+  switch (set) {
+  case GPRegSet:
+    return NativeProcessFreeBSD::PtraceWrapper(PT_SETREGS, m_thread.GetID(),
+                                               m_reg_data.data());
+  case FPRegSet:
+    return NativeProcessFreeBSD::PtraceWrapper(
+        PT_SETFPREGS, m_thread.GetID(), m_reg_data.data() + sizeof(reg));
+  }
+  llvm_unreachable("NativeRegisterContextFreeBSD_powerpc::WriteRegisterSet");
+}
+
+Status
+NativeRegisterContextFreeBSD_powerpc::ReadRegister(const RegisterInfo *reg_info,
+                                               RegisterValue &reg_value) {
+  Status error;
+
+  if (!reg_info) {
+    error.SetErrorString("reg_info NULL");
+    return error;
+  }
+
+  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+  if (reg == LLDB_INVALID_REGNUM)
+    return Status("no lldb regnum for %s", reg_info && reg_info->name
+                                               ? reg_info->name
+                                               : "<unknown register>");
+
+  llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
+  if (!opt_set) {
+    // This is likely an internal register for lldb use only and should not be
+    // directly queried.
+    error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
+                                   reg_info->name);
+    return error;
+  }
+
+  RegSetKind set = opt_set.getValue();
+  error = ReadRegisterSet(set);
+  if (error.Fail())
+    return error;
+
+  assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+  reg_value.SetBytes(m_reg_data.data() + reg_info->byte_offset,
+                     reg_info->byte_size, endian::InlHostByteOrder());
+  return error;
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::WriteRegister(
+    const RegisterInfo *reg_info, const RegisterValue &reg_value) {
+  Status error;
+
+  if (!reg_info)
+    return Status("reg_info NULL");
+
+  const uint32_t reg = reg_info->kinds[lldb::eRegisterKindLLDB];
+
+  if (reg == LLDB_INVALID_REGNUM)
+    return Status("no lldb regnum for %s", reg_info && reg_info->name
+                                               ? reg_info->name
+                                               : "<unknown register>");
+
+  llvm::Optional<RegSetKind> opt_set = GetSetForNativeRegNum(reg);
+  if (!opt_set) {
+    // This is likely an internal register for lldb use only and should not be
+    // directly queried.
+    error.SetErrorStringWithFormat("register \"%s\" is in unrecognized set",
+                                   reg_info->name);
+    return error;
+  }
+
+  RegSetKind set = opt_set.getValue();
+  error = ReadRegisterSet(set);
+  if (error.Fail())
+    return error;
+
+  assert(reg_info->byte_offset + reg_info->byte_size <= m_reg_data.size());
+  ::memcpy(m_reg_data.data() + reg_info->byte_offset, reg_value.GetBytes(),
+           reg_info->byte_size);
+
+  return WriteRegisterSet(set);
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::ReadAllRegisterValues(
+    lldb::DataBufferSP &data_sp) {
+  Status error;
+
+  error = ReadRegisterSet(GPRegSet);
+  if (error.Fail())
+    return error;
+
+  error = ReadRegisterSet(FPRegSet);
+  if (error.Fail())
+    return error;
+
+  data_sp.reset(new DataBufferHeap(m_reg_data.size(), 0));
+  uint8_t *dst = data_sp->GetBytes();
+  ::memcpy(dst, m_reg_data.data(), m_reg_data.size());
+
+  return error;
+}
+
+Status NativeRegisterContextFreeBSD_powerpc::WriteAllRegisterValues(
+    const lldb::DataBufferSP &data_sp) {
+  Status error;
+
+  if (!data_sp) {
+    error.SetErrorStringWithFormat(
+        "NativeRegisterContextFreeBSD_powerpc::%s invalid data_sp provided",
+        __FUNCTION__);
+    return error;
+  }
+
+  if (data_sp->GetByteSize() != m_reg_data.size()) {
+    error.SetErrorStringWithFormat(
+        "NativeRegisterContextFreeBSD_powerpc::%s data_sp contained mismatched "
+        "data size, expected %zu, actual %" PRIu64,
+        __FUNCTION__, m_reg_data.size(), data_sp->GetByteSize());
+    return error;
+  }
+
+  uint8_t *src = data_sp->GetBytes();
+  if (src == nullptr) {
+    error.SetErrorStringWithFormat("NativeRegisterContextFreeBSD_powerpc::%s "
+                                   "DataBuffer::GetBytes() returned a null "
+                                   "pointer",
+                                   __FUNCTION__);
+    return error;
+  }
+  ::memcpy(m_reg_data.data(), src, m_reg_data.size());
+
+  error = WriteRegisterSet(GPRegSet);
+  if (error.Fail())
+    return error;
+
+  return WriteRegisterSet(FPRegSet);
+}
+
+llvm::Error NativeRegisterContextFreeBSD_powerpc::CopyHardwareWatchpointsFrom(
+    NativeRegisterContextFreeBSD &source) {
+  return llvm::Error::success();
+}
+
+#endif // defined (__powerpc__)

diff  --git a/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_powerpc.h b/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_powerpc.h
new file mode 100644
index 000000000000..d76fdae1d2e0
--- /dev/null
+++ b/lldb/source/Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD_powerpc.h
@@ -0,0 +1,73 @@
+//===-- NativeRegisterContextFreeBSD_powerpc.h ------------------*- C++ -*-===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#if defined(__powerpc__)
+
+#ifndef lldb_NativeRegisterContextFreeBSD_powerpc_h
+#define lldb_NativeRegisterContextFreeBSD_powerpc_h
+
+// clang-format off
+#include <sys/types.h>
+#include <machine/reg.h>
+// clang-format on
+
+#include "Plugins/Process/FreeBSDRemote/NativeRegisterContextFreeBSD.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
+
+#include <array>
+
+namespace lldb_private {
+namespace process_freebsd {
+
+class NativeProcessFreeBSD;
+
+class NativeRegisterContextFreeBSD_powerpc : public NativeRegisterContextFreeBSD {
+public:
+  NativeRegisterContextFreeBSD_powerpc(const ArchSpec &target_arch,
+                                   NativeThreadProtocol &native_thread);
+
+  uint32_t GetRegisterSetCount() const override;
+
+  uint32_t GetUserRegisterCount() const override;
+
+  const RegisterSet *GetRegisterSet(uint32_t set_index) const override;
+
+  Status ReadRegister(const RegisterInfo *reg_info,
+                      RegisterValue &reg_value) override;
+
+  Status WriteRegister(const RegisterInfo *reg_info,
+                       const RegisterValue &reg_value) override;
+
+  Status ReadAllRegisterValues(lldb::DataBufferSP &data_sp) override;
+
+  Status WriteAllRegisterValues(const lldb::DataBufferSP &data_sp) override;
+
+  llvm::Error
+  CopyHardwareWatchpointsFrom(NativeRegisterContextFreeBSD &source) override;
+
+private:
+  enum RegSetKind {
+    GPRegSet,
+    FPRegSet,
+  };
+  std::array<uint8_t, sizeof(reg) + sizeof(fpreg)> m_reg_data;
+
+  llvm::Optional<RegSetKind> GetSetForNativeRegNum(uint32_t reg_num) const;
+
+  Status ReadRegisterSet(RegSetKind set);
+  Status WriteRegisterSet(RegSetKind set);
+
+  RegisterContextFreeBSD_powerpc &GetRegisterInfo() const;
+};
+
+} // namespace process_freebsd
+} // namespace lldb_private
+
+#endif // #ifndef lldb_NativeRegisterContextFreeBSD_powerpc_h
+
+#endif // defined (__powerpc__)

diff  --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
index 51be31f8e028..90863dfdb090 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
@@ -10,8 +10,8 @@
 
 // Computes the offset of the given GPR in the user data area.
 #define GPR_OFFSET(regname) (offsetof(GPR, regname))
-#define FPR_OFFSET(regname) (offsetof(FPR, regname))
-#define VMX_OFFSET(regname) (offsetof(VMX, regname))
+#define FPR_OFFSET(regname) (sizeof(GPR) + offsetof(FPR, regname))
+#define VMX_OFFSET(regname) (sizeof(GPR) + sizeof(FPR) + offsetof(VMX, regname))
 #define GPR_SIZE(regname) (sizeof(((GPR *)NULL)->regname))
 
 #ifdef DECLARE_REGISTER_INFOS_POWERPC_STRUCT

diff  --git a/lldb/unittests/Process/Utility/RegisterContextFreeBSDTest.cpp b/lldb/unittests/Process/Utility/RegisterContextFreeBSDTest.cpp
index ed0b2275c4ba..548830d19a52 100644
--- a/lldb/unittests/Process/Utility/RegisterContextFreeBSDTest.cpp
+++ b/lldb/unittests/Process/Utility/RegisterContextFreeBSDTest.cpp
@@ -19,7 +19,9 @@
 
 #include "Plugins/Process/Utility/RegisterContextFreeBSD_i386.h"
 #include "Plugins/Process/Utility/RegisterContextFreeBSD_mips64.h"
+#include "Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h"
 #include "Plugins/Process/Utility/RegisterContextFreeBSD_x86_64.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm.h"
 #include "Plugins/Process/Utility/RegisterInfoPOSIX_arm64.h"
 #include "Plugins/Process/Utility/lldb-arm-register-enums.h"
@@ -458,3 +460,95 @@ TEST(RegisterContextFreeBSDTest, mips64) {
 }
 
 #endif // defined(__mips64__)
+
+#if defined(__powerpc__)
+
+#define EXPECT_GPR_PPC(lldb_reg, fbsd_reg)                                \
+  EXPECT_THAT(GetRegParams(reg_ctx, gpr_##lldb_reg##_powerpc),                  \
+              ::testing::Pair(offsetof(reg, fbsd_reg),               \
+                              sizeof(reg::fbsd_reg)))
+#define EXPECT_FPU_PPC(lldb_reg, fbsd_reg)                                   \
+  EXPECT_THAT(GetRegParams(reg_ctx, fpr_##lldb_reg##_powerpc),                   \
+              ::testing::Pair(offsetof(fpreg, fbsd_reg) + base_offset,         \
+                              sizeof(fpreg::fbsd_reg)))
+
+TEST(RegisterContextFreeBSDTest, powerpc32) {
+  ArchSpec arch{"powerpc-unknown-freebsd"};
+  RegisterContextFreeBSD_powerpc32 reg_ctx{arch};
+
+  EXPECT_GPR_PPC(r0, fixreg[0]);
+  EXPECT_GPR_PPC(r1, fixreg[1]);
+  EXPECT_GPR_PPC(r2, fixreg[2]);
+  EXPECT_GPR_PPC(r3, fixreg[3]);
+  EXPECT_GPR_PPC(r4, fixreg[4]);
+  EXPECT_GPR_PPC(r5, fixreg[5]);
+  EXPECT_GPR_PPC(r6, fixreg[6]);
+  EXPECT_GPR_PPC(r7, fixreg[7]);
+  EXPECT_GPR_PPC(r8, fixreg[8]);
+  EXPECT_GPR_PPC(r9, fixreg[9]);
+  EXPECT_GPR_PPC(r10, fixreg[10]);
+  EXPECT_GPR_PPC(r11, fixreg[11]);
+  EXPECT_GPR_PPC(r12, fixreg[12]);
+  EXPECT_GPR_PPC(r13, fixreg[13]);
+  EXPECT_GPR_PPC(r14, fixreg[14]);
+  EXPECT_GPR_PPC(r15, fixreg[15]);
+  EXPECT_GPR_PPC(r16, fixreg[16]);
+  EXPECT_GPR_PPC(r17, fixreg[17]);
+  EXPECT_GPR_PPC(r18, fixreg[18]);
+  EXPECT_GPR_PPC(r19, fixreg[19]);
+  EXPECT_GPR_PPC(r20, fixreg[20]);
+  EXPECT_GPR_PPC(r21, fixreg[21]);
+  EXPECT_GPR_PPC(r22, fixreg[22]);
+  EXPECT_GPR_PPC(r23, fixreg[23]);
+  EXPECT_GPR_PPC(r24, fixreg[24]);
+  EXPECT_GPR_PPC(r25, fixreg[25]);
+  EXPECT_GPR_PPC(r26, fixreg[26]);
+  EXPECT_GPR_PPC(r27, fixreg[27]);
+  EXPECT_GPR_PPC(r28, fixreg[28]);
+  EXPECT_GPR_PPC(r29, fixreg[29]);
+  EXPECT_GPR_PPC(r30, fixreg[30]);
+  EXPECT_GPR_PPC(r31, fixreg[31]);
+  EXPECT_GPR_PPC(lr, lr);
+  EXPECT_GPR_PPC(cr, cr);
+  EXPECT_GPR_PPC(xer, xer);
+  EXPECT_GPR_PPC(ctr, ctr);
+  EXPECT_GPR_PPC(pc, pc);
+
+  size_t base_offset = reg_ctx.GetRegisterInfo()[fpr_f0_powerpc].byte_offset;
+
+  EXPECT_FPU_PPC(f0, fpreg[0]);
+  EXPECT_FPU_PPC(f1, fpreg[1]);
+  EXPECT_FPU_PPC(f2, fpreg[2]);
+  EXPECT_FPU_PPC(f3, fpreg[3]);
+  EXPECT_FPU_PPC(f4, fpreg[4]);
+  EXPECT_FPU_PPC(f5, fpreg[5]);
+  EXPECT_FPU_PPC(f6, fpreg[6]);
+  EXPECT_FPU_PPC(f7, fpreg[7]);
+  EXPECT_FPU_PPC(f8, fpreg[8]);
+  EXPECT_FPU_PPC(f9, fpreg[9]);
+  EXPECT_FPU_PPC(f10, fpreg[10]);
+  EXPECT_FPU_PPC(f11, fpreg[11]);
+  EXPECT_FPU_PPC(f12, fpreg[12]);
+  EXPECT_FPU_PPC(f13, fpreg[13]);
+  EXPECT_FPU_PPC(f14, fpreg[14]);
+  EXPECT_FPU_PPC(f15, fpreg[15]);
+  EXPECT_FPU_PPC(f16, fpreg[16]);
+  EXPECT_FPU_PPC(f17, fpreg[17]);
+  EXPECT_FPU_PPC(f18, fpreg[18]);
+  EXPECT_FPU_PPC(f19, fpreg[19]);
+  EXPECT_FPU_PPC(f20, fpreg[20]);
+  EXPECT_FPU_PPC(f21, fpreg[21]);
+  EXPECT_FPU_PPC(f22, fpreg[22]);
+  EXPECT_FPU_PPC(f23, fpreg[23]);
+  EXPECT_FPU_PPC(f24, fpreg[24]);
+  EXPECT_FPU_PPC(f25, fpreg[25]);
+  EXPECT_FPU_PPC(f26, fpreg[26]);
+  EXPECT_FPU_PPC(f27, fpreg[27]);
+  EXPECT_FPU_PPC(f28, fpreg[28]);
+  EXPECT_FPU_PPC(f29, fpreg[29]);
+  EXPECT_FPU_PPC(f30, fpreg[30]);
+  EXPECT_FPU_PPC(f31, fpreg[31]);
+  EXPECT_FPU_PPC(fpscr, fpscr);
+}
+
+#endif // defined(__powerpc__)


        


More information about the lldb-commits mailing list