First cut of PowerPC(64) support in LLDB.

Summary:
This adds preliminary support for PowerPC/PowerPC64, for FreeBSD.  There are
some issues still:

 * Breakpoints don't work well on powerpc64.
 * Shared libraries don't yet get loaded for a 32-bit process on powerpc64 host.
 * Backtraces don't work.  This is due to PowerPC ABI using a backchain pointer
   in memory, instead of a dedicated frame pointer register for the backchain.
 * Breakpoints on functions without debug info may not work correctly for 32-bit
   powerpc.

Reviewers: emaste, tfiala, jingham, clayborg

Reviewed By: clayborg

Subscribers: emaste, lldb-commits

Differential Revision: http://reviews.llvm.org/D5988

llvm-svn: 220944
diff --git a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp b/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
index cb30a15..bd96b6b 100644
--- a/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
+++ b/lldb/source/Plugins/Process/FreeBSD/ProcessMonitor.cpp
@@ -113,6 +113,7 @@
             log->Printf("PT_GETREGS: ax=0x%lx", r->r_rax);
         }
 #endif
+#ifndef __powerpc__
         if (req == PT_GETDBREGS || req == PT_SETDBREGS) {
             struct dbreg *r = (struct dbreg *) addr;
             char setget = (req == PT_GETDBREGS) ? 'G' : 'S';
@@ -120,6 +121,7 @@
             for (int i = 0; i <= 7; i++)
                 log->Printf("PT_%cETDBREGS: dr[%d]=0x%lx", setget, i, r->dr[i]);
         }
+#endif
     }
      
     return result;
diff --git a/lldb/source/Plugins/Process/POSIX/CMakeLists.txt b/lldb/source/Plugins/Process/POSIX/CMakeLists.txt
index ad12952..8fd7bd1 100644
--- a/lldb/source/Plugins/Process/POSIX/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/POSIX/CMakeLists.txt
@@ -12,5 +12,6 @@
   ProcessPOSIXLog.cpp
   RegisterContextPOSIXProcessMonitor_arm64.cpp
   RegisterContextPOSIXProcessMonitor_mips64.cpp
+  RegisterContextPOSIXProcessMonitor_powerpc.cpp
   RegisterContextPOSIXProcessMonitor_x86.cpp
   )
diff --git a/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp b/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp
index 64c9de9..1057585 100644
--- a/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp
+++ b/lldb/source/Plugins/Process/POSIX/POSIXThread.cpp
@@ -34,12 +34,14 @@
 #include "Plugins/Process/Linux/ProcessMonitor.h"
 #include "RegisterContextPOSIXProcessMonitor_arm64.h"
 #include "RegisterContextPOSIXProcessMonitor_mips64.h"
+#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
 #include "RegisterContextPOSIXProcessMonitor_x86.h"
 #include "Plugins/Process/Utility/RegisterContextLinux_arm64.h"
 #include "Plugins/Process/Utility/RegisterContextLinux_i386.h"
 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
 #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/UnwindLLDB.h"
 
@@ -167,6 +169,14 @@
             case llvm::Triple::FreeBSD:
                 switch (target_arch.GetMachine())
                 {
+                    case llvm::Triple::ppc:
+#ifndef __powerpc64__
+                        reg_interface = new RegisterContextFreeBSD_powerpc32(target_arch);
+                        break;
+#endif
+                    case llvm::Triple::ppc64:
+                        reg_interface = new RegisterContextFreeBSD_powerpc64(target_arch);
+                        break;
                     case llvm::Triple::mips64:
                         reg_interface = new RegisterContextFreeBSD_mips64(target_arch);
                         break;
@@ -229,6 +239,14 @@
                     m_reg_context_sp.reset(reg_ctx);
                     break;
                 }
+            case llvm::Triple::ppc:
+            case llvm::Triple::ppc64:
+                {
+                    RegisterContextPOSIXProcessMonitor_powerpc *reg_ctx = new RegisterContextPOSIXProcessMonitor_powerpc(*this, 0, reg_interface);
+                    m_posix_thread = reg_ctx;
+                    m_reg_context_sp.reset(reg_ctx);
+                    break;
+                }
             case llvm::Triple::x86:
             case llvm::Triple::x86_64:
                 {
@@ -624,6 +642,8 @@
 
     case llvm::Triple::aarch64:
     case llvm::Triple::mips64:
+    case llvm::Triple::ppc:
+    case llvm::Triple::ppc64:
     case llvm::Triple::x86:
     case llvm::Triple::x86_64:
         {
@@ -655,6 +675,8 @@
 
     case llvm::Triple::aarch64:
     case llvm::Triple::mips64:
+    case llvm::Triple::ppc:
+    case llvm::Triple::ppc64:
     case llvm::Triple::x86:
     case llvm::Triple::x86_64:
         name = GetRegisterContext()->GetRegisterName(reg);
diff --git a/lldb/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp b/lldb/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp
new file mode 100644
index 0000000..0dfb91d
--- /dev/null
+++ b/lldb/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.cpp
@@ -0,0 +1,316 @@
+//===-- RegisterContextPOSIXProcessMonitor_powerpc.h ------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include "lldb/Target/Thread.h"
+#include "lldb/Core/RegisterValue.h"
+
+#include "RegisterContextPOSIX_powerpc.h"
+#include "ProcessPOSIX.h"
+#include "RegisterContextPOSIXProcessMonitor_powerpc.h"
+#include "ProcessMonitor.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+#define REG_CONTEXT_SIZE (GetGPRSize())
+
+RegisterContextPOSIXProcessMonitor_powerpc::RegisterContextPOSIXProcessMonitor_powerpc(Thread &thread,
+                                                                                     uint32_t concrete_frame_idx,
+                                                                                     lldb_private::RegisterInfoInterface *register_info)
+    : RegisterContextPOSIX_powerpc(thread, concrete_frame_idx, register_info)
+{
+}
+
+ProcessMonitor &
+RegisterContextPOSIXProcessMonitor_powerpc::GetMonitor()
+{
+    ProcessSP base = CalculateProcess();
+    ProcessPOSIX *process = static_cast<ProcessPOSIX*>(base.get());
+    return process->GetMonitor();
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::ReadGPR()
+{
+     ProcessMonitor &monitor = GetMonitor();
+     return monitor.ReadGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::ReadFPR()
+{
+    // XXX not yet implemented
+    return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::WriteGPR()
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.WriteGPR(m_thread.GetID(), &m_gpr_powerpc, GetGPRSize());
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::WriteFPR()
+{
+    // XXX not yet implemented
+    return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(const unsigned reg,
+                                                        RegisterValue &value)
+{
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.ReadRegisterValue(m_thread.GetID(),
+                                     GetRegisterOffset(reg),
+                                     GetRegisterName(reg),
+                                     GetRegisterSize(reg),
+                                     value);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(const unsigned reg,
+                                                         const RegisterValue &value)
+{
+    unsigned reg_to_write = reg;
+    RegisterValue value_to_write = value;
+
+    // Check if this is a subregister of a full register.
+    const RegisterInfo *reg_info = GetRegisterInfoAtIndex(reg);
+    if (reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM))
+    {
+        RegisterValue full_value;
+        uint32_t full_reg = reg_info->invalidate_regs[0];
+        const RegisterInfo *full_reg_info = GetRegisterInfoAtIndex(full_reg);
+
+        // Read the full register.
+        if (ReadRegister(full_reg_info, full_value))
+        {
+            Error error;
+            ByteOrder byte_order = GetByteOrder();
+            uint8_t dst[RegisterValue::kMaxRegisterByteSize];
+
+            // Get the bytes for the full register.
+            const uint32_t dest_size = full_value.GetAsMemoryData (full_reg_info,
+                                                                   dst,
+                                                                   sizeof(dst),
+                                                                   byte_order,
+                                                                   error);
+            if (error.Success() && dest_size)
+            {
+                uint8_t src[RegisterValue::kMaxRegisterByteSize];
+
+                // Get the bytes for the source data.
+                const uint32_t src_size = value.GetAsMemoryData (reg_info, src, sizeof(src), byte_order, error);
+                if (error.Success() && src_size && (src_size < dest_size))
+                {
+                    // Copy the src bytes to the destination.
+                    memcpy (dst + (reg_info->byte_offset & 0x1), src, src_size);
+                    // Set this full register as the value to write.
+                    value_to_write.SetBytes(dst, full_value.GetByteSize(), byte_order);
+                    value_to_write.SetType(full_reg_info);
+                    reg_to_write = full_reg;
+                }
+            }
+        }
+    }
+
+    ProcessMonitor &monitor = GetMonitor();
+    return monitor.WriteRegisterValue(m_thread.GetID(),
+                                      GetRegisterOffset(reg_to_write),
+                                      GetRegisterName(reg_to_write),
+                                      value_to_write);
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
+{
+    if (!reg_info)
+        return false;
+
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+    if (IsFPR(reg))
+    {
+        if (!ReadFPR())
+            return false;
+    }
+    else
+    {
+        uint32_t full_reg = reg;
+        bool is_subreg = reg_info->invalidate_regs && (reg_info->invalidate_regs[0] != LLDB_INVALID_REGNUM);
+
+        if (is_subreg)
+        {
+            // Read the full aligned 64-bit register.
+            full_reg = reg_info->invalidate_regs[0];
+        }
+
+        bool success = ReadRegister(full_reg, value);
+
+        if (success)
+        {
+            // If our read was not aligned (for ah,bh,ch,dh), shift our returned value one byte to the right.
+            if (is_subreg && (reg_info->byte_offset & 0x1))
+                value.SetUInt64(value.GetAsUInt64() >> 8);
+
+            // If our return byte size was greater than the return value reg size, then
+            // use the type specified by reg_info rather than the uint64_t default
+            if (value.GetByteSize() > reg_info->byte_size)
+                value.SetType(reg_info);
+        }
+        return success;
+    }
+
+    return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
+{
+    const uint32_t reg = reg_info->kinds[eRegisterKindLLDB];
+
+    if (IsGPR(reg))
+        return WriteRegister(reg, value);
+
+    return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::ReadAllRegisterValues(DataBufferSP &data_sp)
+{
+    bool success = false;
+    data_sp.reset (new DataBufferHeap (REG_CONTEXT_SIZE, 0));
+    if (data_sp && ReadGPR () && ReadFPR ())
+    {
+        uint8_t *dst = data_sp->GetBytes();
+        success = dst != 0;
+
+        if (success)
+        {
+            ::memcpy (dst, &m_gpr_powerpc, GetGPRSize());
+            dst += GetGPRSize();
+        }
+    }
+    return success;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::WriteAllRegisterValues(const DataBufferSP &data_sp)
+{
+    bool success = false;
+    if (data_sp && data_sp->GetByteSize() == REG_CONTEXT_SIZE)
+    {
+        uint8_t *src = data_sp->GetBytes();
+        if (src)
+        {
+            ::memcpy (&m_gpr_powerpc, src, GetGPRSize());
+
+            if (WriteGPR())
+            {
+                src += GetGPRSize();
+            }
+        }
+    }
+    return success;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpoint(addr_t addr, size_t size,
+                                              bool read, bool write)
+{
+    const uint32_t num_hw_watchpoints = NumSupportedHardwareWatchpoints();
+    uint32_t hw_index;
+
+    for (hw_index = 0; hw_index < num_hw_watchpoints; ++hw_index)
+    {
+        if (IsWatchpointVacant(hw_index))
+            return SetHardwareWatchpointWithIndex(addr, size,
+                                                  read, write,
+                                                  hw_index);
+    }
+
+    return LLDB_INVALID_INDEX32;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::ClearHardwareWatchpoint(uint32_t hw_index)
+{
+    return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::HardwareSingleStep(bool enable)
+{
+    return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::UpdateAfterBreakpoint()
+{
+    lldb::addr_t pc;
+
+    if ((pc = GetPC()) == LLDB_INVALID_ADDRESS)
+        return false;
+
+    return true;
+}
+
+unsigned
+RegisterContextPOSIXProcessMonitor_powerpc::GetRegisterIndexFromOffset(unsigned offset)
+{
+    unsigned reg;
+    for (reg = 0; reg < k_num_registers_powerpc; reg++)
+    {
+        if (GetRegisterInfo()[reg].byte_offset == offset)
+            break;
+    }
+    assert(reg < k_num_registers_powerpc && "Invalid register offset.");
+    return reg;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointHit(uint32_t hw_index)
+{
+    return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::ClearWatchpointHits()
+{
+    return false;
+}
+
+addr_t
+RegisterContextPOSIXProcessMonitor_powerpc::GetWatchpointAddress(uint32_t hw_index)
+{
+    return LLDB_INVALID_ADDRESS;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::IsWatchpointVacant(uint32_t hw_index)
+{
+    return false;
+}
+
+bool
+RegisterContextPOSIXProcessMonitor_powerpc::SetHardwareWatchpointWithIndex(addr_t addr, size_t size,
+                                                       bool read, bool write,
+                                                       uint32_t hw_index)
+{
+    return false;
+}
+
+uint32_t
+RegisterContextPOSIXProcessMonitor_powerpc::NumSupportedHardwareWatchpoints()
+{
+    return 0;
+}
+
diff --git a/lldb/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h b/lldb/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h
new file mode 100644
index 0000000..92a3312
--- /dev/null
+++ b/lldb/source/Plugins/Process/POSIX/RegisterContextPOSIXProcessMonitor_powerpc.h
@@ -0,0 +1,95 @@
+//===-- RegisterContextPOSIXProcessMonitor_powerpc.h -------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_
+#define liblldb_RegisterContextPOSIXProcessMonitor_powerpc_H_
+
+#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
+
+class RegisterContextPOSIXProcessMonitor_powerpc:
+    public RegisterContextPOSIX_powerpc,
+    public POSIXBreakpointProtocol
+{
+public:
+    RegisterContextPOSIXProcessMonitor_powerpc(lldb_private::Thread &thread,
+                                              uint32_t concrete_frame_idx,
+                                              lldb_private::RegisterInfoInterface *register_info);
+
+protected:
+    bool
+    ReadGPR();
+
+    bool
+    ReadFPR();
+
+    bool
+    WriteGPR();
+
+    bool
+    WriteFPR();
+
+    // lldb_private::RegisterContext
+    bool
+    ReadRegister(const unsigned reg, lldb_private::RegisterValue &value);
+
+    bool
+    WriteRegister(const unsigned reg, const lldb_private::RegisterValue &value);
+
+    bool
+    ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+    bool
+    WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+
+    bool
+    ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+    bool
+    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+    uint32_t
+    SetHardwareWatchpoint(lldb::addr_t addr, size_t size, bool read, bool write);
+
+    bool
+    ClearHardwareWatchpoint(uint32_t hw_index);
+
+    bool
+    HardwareSingleStep(bool enable);
+
+    // POSIXBreakpointProtocol
+    bool
+    UpdateAfterBreakpoint();
+
+    unsigned
+    GetRegisterIndexFromOffset(unsigned offset);
+
+    bool
+    IsWatchpointHit(uint32_t hw_index);
+
+    bool
+    ClearWatchpointHits();
+
+    lldb::addr_t
+    GetWatchpointAddress(uint32_t hw_index);
+
+    bool
+    IsWatchpointVacant(uint32_t hw_index);
+
+    bool
+    SetHardwareWatchpointWithIndex(lldb::addr_t addr, size_t size, bool read, bool write, uint32_t hw_index);
+
+    uint32_t
+    NumSupportedHardwareWatchpoints();
+
+private:
+    ProcessMonitor &
+    GetMonitor();
+};
+
+#endif
diff --git a/lldb/source/Plugins/Process/Utility/CMakeLists.txt b/lldb/source/Plugins/Process/Utility/CMakeLists.txt
index b9f6c7e..addfa41 100644
--- a/lldb/source/Plugins/Process/Utility/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/Utility/CMakeLists.txt
@@ -16,6 +16,7 @@
   RegisterContextDummy.cpp
   RegisterContextFreeBSD_i386.cpp
   RegisterContextFreeBSD_mips64.cpp
+  RegisterContextFreeBSD_powerpc.cpp
   RegisterContextFreeBSD_x86_64.cpp
   RegisterContextHistory.cpp
   RegisterContextLinux_arm64.cpp
@@ -29,6 +30,7 @@
   RegisterContextMemory.cpp
   RegisterContextPOSIX_arm64.cpp
   RegisterContextPOSIX_mips64.cpp
+  RegisterContextPOSIX_powerpc.cpp
   RegisterContextPOSIX_x86.cpp
   RegisterContextThreadMemory.cpp
   StopInfoMachException.cpp
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
new file mode 100644
index 0000000..375f9b8
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.cpp
@@ -0,0 +1,227 @@
+//===-- RegisterContextFreeBSD_powerpc.cpp ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include <vector>
+#include "RegisterContextPOSIX_powerpc.h"
+#include "RegisterContextFreeBSD_powerpc.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+// http://svnweb.freebsd.org/base/head/sys/powerpc/include/reg.h
+typedef struct _GPR64
+{
+    uint64_t r0;
+    uint64_t r1;
+    uint64_t r2;
+    uint64_t r3;
+    uint64_t r4;
+    uint64_t r5;
+    uint64_t r6;
+    uint64_t r7;
+    uint64_t r8;
+    uint64_t r9;
+    uint64_t r10;
+    uint64_t r11;
+    uint64_t r12;
+    uint64_t r13;
+    uint64_t r14;
+    uint64_t r15;
+    uint64_t r16;
+    uint64_t r17;
+    uint64_t r18;
+    uint64_t r19;
+    uint64_t r20;
+    uint64_t r21;
+    uint64_t r22;
+    uint64_t r23;
+    uint64_t r24;
+    uint64_t r25;
+    uint64_t r26;
+    uint64_t r27;
+    uint64_t r28;
+    uint64_t r29;
+    uint64_t r30;
+    uint64_t r31;
+    uint64_t lr;
+    uint64_t cr;
+    uint64_t xer;
+    uint64_t ctr;
+    uint64_t pc;
+} GPR64;
+
+typedef struct _GPR32
+{
+    uint32_t r0;
+    uint32_t r1;
+    uint32_t r2;
+    uint32_t r3;
+    uint32_t r4;
+    uint32_t r5;
+    uint32_t r6;
+    uint32_t r7;
+    uint32_t r8;
+    uint32_t r9;
+    uint32_t r10;
+    uint32_t r11;
+    uint32_t r12;
+    uint32_t r13;
+    uint32_t r14;
+    uint32_t r15;
+    uint32_t r16;
+    uint32_t r17;
+    uint32_t r18;
+    uint32_t r19;
+    uint32_t r20;
+    uint32_t r21;
+    uint32_t r22;
+    uint32_t r23;
+    uint32_t r24;
+    uint32_t r25;
+    uint32_t r26;
+    uint32_t r27;
+    uint32_t r28;
+    uint32_t r29;
+    uint32_t r30;
+    uint32_t r31;
+    uint32_t lr;
+    uint32_t cr;
+    uint32_t xer;
+    uint32_t ctr;
+    uint32_t pc;
+} GPR32;
+
+typedef struct _FPR
+{
+    uint64_t f0;
+    uint64_t f1;
+    uint64_t f2;
+    uint64_t f3;
+    uint64_t f4;
+    uint64_t f5;
+    uint64_t f6;
+    uint64_t f7;
+    uint64_t f8;
+    uint64_t f9;
+    uint64_t f10;
+    uint64_t f11;
+    uint64_t f12;
+    uint64_t f13;
+    uint64_t f14;
+    uint64_t f15;
+    uint64_t f16;
+    uint64_t f17;
+    uint64_t f18;
+    uint64_t f19;
+    uint64_t f20;
+    uint64_t f21;
+    uint64_t f22;
+    uint64_t f23;
+    uint64_t f24;
+    uint64_t f25;
+    uint64_t f26;
+    uint64_t f27;
+    uint64_t f28;
+    uint64_t f29;
+    uint64_t f30;
+    uint64_t f31;
+    uint64_t fpscr;
+} FPR;
+
+//---------------------------------------------------------------------------
+// Include RegisterInfos_powerpc to declare our g_register_infos_powerpc structure.
+//---------------------------------------------------------------------------
+#define DECLARE_REGISTER_INFOS_POWERPC_STRUCT
+#include "RegisterInfos_powerpc.h"
+#undef DECLARE_REGISTER_INFOS_POWERPC_STRUCT
+
+RegisterContextFreeBSD_powerpc::RegisterContextFreeBSD_powerpc(const ArchSpec &target_arch) :
+    RegisterInfoInterface(target_arch)
+{
+}
+
+RegisterContextFreeBSD_powerpc::~RegisterContextFreeBSD_powerpc()
+{
+}
+
+size_t
+RegisterContextFreeBSD_powerpc::GetGPRSize() const
+{
+    return sizeof(GPR64);
+}
+
+const RegisterInfo *
+RegisterContextFreeBSD_powerpc::GetRegisterInfo() const
+{
+    //assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc);
+    llvm_unreachable("Abstract class!");
+    return NULL;
+}
+
+uint32_t
+RegisterContextFreeBSD_powerpc::GetRegisterCount () const
+{
+    return 0;
+}
+
+RegisterContextFreeBSD_powerpc32::RegisterContextFreeBSD_powerpc32(const ArchSpec &target_arch) :
+    RegisterContextFreeBSD_powerpc(target_arch)
+{
+}
+
+RegisterContextFreeBSD_powerpc32::~RegisterContextFreeBSD_powerpc32()
+{
+}
+
+size_t
+RegisterContextFreeBSD_powerpc32::GetGPRSize() const
+{
+    return sizeof(GPR32);
+}
+
+const RegisterInfo *
+RegisterContextFreeBSD_powerpc32::GetRegisterInfo() const
+{
+    //assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc);
+    return g_register_infos_powerpc32;
+}
+
+uint32_t
+RegisterContextFreeBSD_powerpc32::GetRegisterCount () const
+{
+    return static_cast<uint32_t> (sizeof (g_register_infos_powerpc32) / sizeof (g_register_infos_powerpc32 [0]));
+}
+
+RegisterContextFreeBSD_powerpc64::RegisterContextFreeBSD_powerpc64(const ArchSpec &target_arch) :
+    RegisterContextFreeBSD_powerpc(target_arch)
+{
+}
+
+RegisterContextFreeBSD_powerpc64::~RegisterContextFreeBSD_powerpc64()
+{
+}
+
+size_t
+RegisterContextFreeBSD_powerpc64::GetGPRSize() const
+{
+    return sizeof(GPR64);
+}
+
+const RegisterInfo *
+RegisterContextFreeBSD_powerpc64::GetRegisterInfo() const
+{
+    //assert (m_target_arch.GetCore() == ArchSpec::eCore_powerpc);
+    return g_register_infos_powerpc64;
+}
+
+uint32_t
+RegisterContextFreeBSD_powerpc64::GetRegisterCount () const
+{
+    return static_cast<uint32_t> (sizeof (g_register_infos_powerpc64) / sizeof (g_register_infos_powerpc64 [0]));
+}
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
new file mode 100644
index 0000000..b907fe9
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextFreeBSD_powerpc.h
@@ -0,0 +1,66 @@
+//===-- RegisterContextFreeBSD_powerpc.h -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextFreeBSD_powerpc_H_
+#define liblldb_RegisterContextFreeBSD_powerpc_H_
+
+#include "RegisterContextPOSIX.h"
+
+class RegisterContextFreeBSD_powerpc:
+    public lldb_private::RegisterInfoInterface
+{
+public:
+    RegisterContextFreeBSD_powerpc(const lldb_private::ArchSpec &target_arch);
+    virtual ~RegisterContextFreeBSD_powerpc();
+
+    size_t
+    GetGPRSize() const override;
+
+    const lldb_private::RegisterInfo *
+    GetRegisterInfo() const override;
+
+    uint32_t
+    GetRegisterCount() const override;
+};
+
+class RegisterContextFreeBSD_powerpc32:
+    public RegisterContextFreeBSD_powerpc
+{
+public:
+    RegisterContextFreeBSD_powerpc32(const lldb_private::ArchSpec &target_arch);
+    virtual ~RegisterContextFreeBSD_powerpc32();
+
+    size_t
+    GetGPRSize() const override;
+
+    const lldb_private::RegisterInfo *
+    GetRegisterInfo() const override;
+
+    uint32_t
+    GetRegisterCount() const override;
+};
+
+class RegisterContextFreeBSD_powerpc64:
+    public RegisterContextFreeBSD_powerpc
+{
+public:
+    RegisterContextFreeBSD_powerpc64(const lldb_private::ArchSpec &target_arch);
+    virtual ~RegisterContextFreeBSD_powerpc64();
+
+    size_t
+    GetGPRSize() const override;
+
+    const lldb_private::RegisterInfo *
+    GetRegisterInfo() const override;
+
+    uint32_t
+    GetRegisterCount() const override;
+};
+
+#endif
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
index e246e71..5579b0b 100644
--- a/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextMacOSXFrameBackchain.cpp
@@ -149,7 +149,8 @@
 
             // TOOD: need a better way to detect when "long double" types are
             // the same bytes size as "double"
-#if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) && !defined(_MSC_VER) && !defined(__mips__)
+#if !defined(__arm__) && !defined(__arm64__) && !defined(__aarch64__) && !defined(_MSC_VER) && \
+    !defined(__mips__) && !defined(__powerpc__)
         case sizeof (long double):
             if (sizeof (long double) == sizeof(uint32_t))
             {
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
new file mode 100644
index 0000000..a9477d5
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.cpp
@@ -0,0 +1,273 @@
+//===-- RegisterContextPOSIX_powerpc.cpp -------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include <cstring>
+#include <errno.h>
+#include <stdint.h>
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Core/Scalar.h"
+#include "lldb/Target/Target.h"
+#include "lldb/Target/Thread.h"
+#include "lldb/Host/Endian.h"
+#include "llvm/Support/Compiler.h"
+
+#include "RegisterContextPOSIX_powerpc.h"
+#include "Plugins/Process/elf-core/ProcessElfCore.h"
+
+using namespace lldb_private;
+using namespace lldb;
+
+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 },
+};
+
+bool RegisterContextPOSIX_powerpc::IsGPR(unsigned reg)
+{
+    return reg <= k_num_gpr_registers_powerpc;   // GPR's come first.
+}
+
+bool
+RegisterContextPOSIX_powerpc::IsFPR(unsigned reg)
+{
+    // XXX
+    return (reg >= k_first_fpr) && (reg <= k_last_fpr);
+}
+
+RegisterContextPOSIX_powerpc::RegisterContextPOSIX_powerpc(Thread &thread,
+                                               uint32_t concrete_frame_idx,
+                                               RegisterInfoInterface *register_info)
+    : RegisterContext(thread, concrete_frame_idx)
+{
+    m_register_info_ap.reset(register_info);
+
+    // elf-core yet to support ReadFPR()
+    ProcessSP base = CalculateProcess();
+    if (base.get()->GetPluginName() ==  ProcessElfCore::GetPluginNameStatic())
+        return;
+}
+
+RegisterContextPOSIX_powerpc::~RegisterContextPOSIX_powerpc()
+{
+}
+
+void
+RegisterContextPOSIX_powerpc::Invalidate()
+{
+}
+
+void
+RegisterContextPOSIX_powerpc::InvalidateAllRegisters()
+{
+}
+
+unsigned
+RegisterContextPOSIX_powerpc::GetRegisterOffset(unsigned reg)
+{
+    assert(reg < k_num_registers_powerpc && "Invalid register number.");
+    return GetRegisterInfo()[reg].byte_offset;
+}
+
+unsigned
+RegisterContextPOSIX_powerpc::GetRegisterSize(unsigned reg)
+{
+    assert(reg < k_num_registers_powerpc && "Invalid register number.");
+    return GetRegisterInfo()[reg].byte_size;
+}
+
+size_t
+RegisterContextPOSIX_powerpc::GetRegisterCount()
+{
+    size_t num_registers = k_num_registers_powerpc;
+    return num_registers;
+}
+
+size_t
+RegisterContextPOSIX_powerpc::GetGPRSize()
+{
+    return m_register_info_ap->GetGPRSize();
+}
+
+const RegisterInfo *
+RegisterContextPOSIX_powerpc::GetRegisterInfo()
+{
+    // Commonly, this method is overridden and g_register_infos is copied and specialized.
+    // So, use GetRegisterInfo() rather than g_register_infos in this scope.
+    return m_register_info_ap->GetRegisterInfo ();
+}
+
+const RegisterInfo *
+RegisterContextPOSIX_powerpc::GetRegisterInfoAtIndex(size_t reg)
+{
+    if (reg < k_num_registers_powerpc)
+        return &GetRegisterInfo()[reg];
+    else
+        return NULL;
+}
+
+size_t
+RegisterContextPOSIX_powerpc::GetRegisterSetCount()
+{
+    size_t sets = 0;
+    for (size_t set = 0; set < k_num_register_sets; ++set)
+    {
+        if (IsRegisterSetAvailable(set))
+            ++sets;
+    }
+
+    return sets;
+}
+
+const RegisterSet *
+RegisterContextPOSIX_powerpc::GetRegisterSet(size_t set)
+{
+    if (IsRegisterSetAvailable(set))
+        return &g_reg_sets_powerpc[set];
+    else
+        return NULL;
+}
+
+const char *
+RegisterContextPOSIX_powerpc::GetRegisterName(unsigned reg)
+{
+    assert(reg < k_num_registers_powerpc && "Invalid register offset.");
+    return GetRegisterInfo()[reg].name;
+}
+
+lldb::ByteOrder
+RegisterContextPOSIX_powerpc::GetByteOrder()
+{
+    // Get the target process whose privileged thread was used for the register read.
+    lldb::ByteOrder byte_order = eByteOrderInvalid;
+    Process *process = CalculateProcess().get();
+
+    if (process)
+        byte_order = process->GetByteOrder();
+    return byte_order;
+}
+
+bool
+RegisterContextPOSIX_powerpc::IsRegisterSetAvailable(size_t set_index)
+{
+    size_t num_sets = k_num_register_sets;
+
+    return (set_index < num_sets);
+}
+
+// Used when parsing DWARF and EH frame information and any other
+// object file sections that contain register numbers in them.
+uint32_t
+RegisterContextPOSIX_powerpc::ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind,
+                                                                 uint32_t num)
+{
+    const uint32_t num_regs = GetRegisterCount();
+
+    assert (kind < kNumRegisterKinds);
+    for (uint32_t reg_idx = 0; reg_idx < num_regs; ++reg_idx)
+    {
+        const RegisterInfo *reg_info = GetRegisterInfoAtIndex (reg_idx);
+
+        if (reg_info->kinds[kind] == num)
+            return reg_idx;
+    }
+
+    return LLDB_INVALID_REGNUM;
+}
+
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
new file mode 100644
index 0000000..3194c39
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h
@@ -0,0 +1,173 @@
+//===-- RegisterContextPOSIX_powerpc.h ---------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextPOSIX_powerpc_H_
+#define liblldb_RegisterContextPOSIX_powerpc_H_
+
+#include "lldb/Core/Log.h"
+#include "RegisterContextPOSIX.h"
+#include "RegisterContext_powerpc.h"
+
+class ProcessMonitor;
+
+// ---------------------------------------------------------------------------
+// Internal codes for all powerpc registers.
+// ---------------------------------------------------------------------------
+enum
+{
+    k_first_gpr_powerpc,
+    gpr_r0_powerpc = k_first_gpr_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,
+    k_last_gpr_powerpc = gpr_pc_powerpc,
+
+    k_first_fpr,
+    fpr_f0_powerpc = k_first_fpr,
+    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,
+    k_last_fpr = fpr_fpscr_powerpc,
+
+    k_num_registers_powerpc,
+    k_num_gpr_registers_powerpc = k_last_gpr_powerpc - k_first_gpr_powerpc + 1,
+    k_num_fpr_registers_powerpc = k_last_fpr - k_first_fpr + 1,
+};
+
+class RegisterContextPOSIX_powerpc
+  : public lldb_private::RegisterContext
+{
+public:
+    RegisterContextPOSIX_powerpc (lldb_private::Thread &thread,
+                            uint32_t concrete_frame_idx,
+                            lldb_private::RegisterInfoInterface *register_info);
+
+    ~RegisterContextPOSIX_powerpc();
+
+    void
+    Invalidate();
+
+    void
+    InvalidateAllRegisters();
+
+    size_t
+    GetRegisterCount();
+
+    virtual size_t
+    GetGPRSize();
+
+    virtual unsigned
+    GetRegisterSize(unsigned reg);
+
+    virtual unsigned
+    GetRegisterOffset(unsigned reg);
+
+    const lldb_private::RegisterInfo *
+    GetRegisterInfoAtIndex(size_t reg);
+
+    size_t
+    GetRegisterSetCount();
+
+    const lldb_private::RegisterSet *
+    GetRegisterSet(size_t set);
+
+    const char *
+    GetRegisterName(unsigned reg);
+
+    uint32_t
+    ConvertRegisterKindToRegisterNumber(lldb::RegisterKind kind, uint32_t num);
+
+protected:
+    uint64_t m_gpr_powerpc[k_num_gpr_registers_powerpc];         // general purpose registers.
+    std::unique_ptr<lldb_private::RegisterInfoInterface> m_register_info_ap; // Register Info Interface (FreeBSD or Linux)
+
+    // Determines if an extended register set is supported on the processor running the inferior process.
+    virtual bool
+    IsRegisterSetAvailable(size_t set_index);
+
+    virtual const lldb_private::RegisterInfo *
+    GetRegisterInfo();
+
+    bool
+    IsGPR(unsigned reg);
+
+    bool
+    IsFPR(unsigned reg);
+
+    lldb::ByteOrder GetByteOrder();
+
+    virtual bool ReadGPR() = 0;
+    virtual bool ReadFPR() = 0;
+    virtual bool WriteGPR() = 0;
+    virtual bool WriteFPR() = 0;
+};
+
+#endif // #ifndef liblldb_RegisterContextPOSIX_powerpc_H_
diff --git a/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h b/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h
new file mode 100644
index 0000000..cf54cc0
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/RegisterContext_powerpc.h
@@ -0,0 +1,163 @@
+//===-- RegisterContext_powerpc.h --------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContext_powerpc_H_
+#define liblldb_RegisterContext_powerpc_H_
+
+// GCC and DWARF Register numbers (eRegisterKindGCC & eRegisterKindDWARF)
+enum
+{
+    gcc_dwarf_r0_powerpc = 0,
+    gcc_dwarf_r1_powerpc,
+    gcc_dwarf_r2_powerpc,
+    gcc_dwarf_r3_powerpc,
+    gcc_dwarf_r4_powerpc,
+    gcc_dwarf_r5_powerpc,
+    gcc_dwarf_r6_powerpc,
+    gcc_dwarf_r7_powerpc,
+    gcc_dwarf_r8_powerpc,
+    gcc_dwarf_r9_powerpc,
+    gcc_dwarf_r10_powerpc,
+    gcc_dwarf_r11_powerpc,
+    gcc_dwarf_r12_powerpc,
+    gcc_dwarf_r13_powerpc,
+    gcc_dwarf_r14_powerpc,
+    gcc_dwarf_r15_powerpc,
+    gcc_dwarf_r16_powerpc,
+    gcc_dwarf_r17_powerpc,
+    gcc_dwarf_r18_powerpc,
+    gcc_dwarf_r19_powerpc,
+    gcc_dwarf_r20_powerpc,
+    gcc_dwarf_r21_powerpc,
+    gcc_dwarf_r22_powerpc,
+    gcc_dwarf_r23_powerpc,
+    gcc_dwarf_r24_powerpc,
+    gcc_dwarf_r25_powerpc,
+    gcc_dwarf_r26_powerpc,
+    gcc_dwarf_r27_powerpc,
+    gcc_dwarf_r28_powerpc,
+    gcc_dwarf_r29_powerpc,
+    gcc_dwarf_r30_powerpc,
+    gcc_dwarf_r31_powerpc,
+    gcc_dwarf_f0_powerpc,
+    gcc_dwarf_f1_powerpc,
+    gcc_dwarf_f2_powerpc,
+    gcc_dwarf_f3_powerpc,
+    gcc_dwarf_f4_powerpc,
+    gcc_dwarf_f5_powerpc,
+    gcc_dwarf_f6_powerpc,
+    gcc_dwarf_f7_powerpc,
+    gcc_dwarf_f8_powerpc,
+    gcc_dwarf_f9_powerpc,
+    gcc_dwarf_f10_powerpc,
+    gcc_dwarf_f11_powerpc,
+    gcc_dwarf_f12_powerpc,
+    gcc_dwarf_f13_powerpc,
+    gcc_dwarf_f14_powerpc,
+    gcc_dwarf_f15_powerpc,
+    gcc_dwarf_f16_powerpc,
+    gcc_dwarf_f17_powerpc,
+    gcc_dwarf_f18_powerpc,
+    gcc_dwarf_f19_powerpc,
+    gcc_dwarf_f20_powerpc,
+    gcc_dwarf_f21_powerpc,
+    gcc_dwarf_f22_powerpc,
+    gcc_dwarf_f23_powerpc,
+    gcc_dwarf_f24_powerpc,
+    gcc_dwarf_f25_powerpc,
+    gcc_dwarf_f26_powerpc,
+    gcc_dwarf_f27_powerpc,
+    gcc_dwarf_f28_powerpc,
+    gcc_dwarf_f29_powerpc,
+    gcc_dwarf_f30_powerpc,
+    gcc_dwarf_f31_powerpc,
+    gcc_dwarf_cr_powerpc,
+    gcc_dwarf_fpscr_powerpc,
+    gcc_dwarf_xer_powerpc = 101,
+    gcc_dwarf_lr_powerpc = 108,
+    gcc_dwarf_ctr_powerpc,
+    gcc_dwarf_pc_powerpc,
+};
+
+// GDB Register numbers (eRegisterKindGDB)
+enum
+{
+    gdb_r0_powerpc = 0,
+    gdb_r1_powerpc,
+    gdb_r2_powerpc,
+    gdb_r3_powerpc,
+    gdb_r4_powerpc,
+    gdb_r5_powerpc,
+    gdb_r6_powerpc,
+    gdb_r7_powerpc,
+    gdb_r8_powerpc,
+    gdb_r9_powerpc,
+    gdb_r10_powerpc,
+    gdb_r11_powerpc,
+    gdb_r12_powerpc,
+    gdb_r13_powerpc,
+    gdb_r14_powerpc,
+    gdb_r15_powerpc,
+    gdb_r16_powerpc,
+    gdb_r17_powerpc,
+    gdb_r18_powerpc,
+    gdb_r19_powerpc,
+    gdb_r20_powerpc,
+    gdb_r21_powerpc,
+    gdb_r22_powerpc,
+    gdb_r23_powerpc,
+    gdb_r24_powerpc,
+    gdb_r25_powerpc,
+    gdb_r26_powerpc,
+    gdb_r27_powerpc,
+    gdb_r28_powerpc,
+    gdb_r29_powerpc,
+    gdb_r30_powerpc,
+    gdb_r31_powerpc,
+    gdb_f0_powerpc,
+    gdb_f1_powerpc,
+    gdb_f2_powerpc,
+    gdb_f3_powerpc,
+    gdb_f4_powerpc,
+    gdb_f5_powerpc,
+    gdb_f6_powerpc,
+    gdb_f7_powerpc,
+    gdb_f8_powerpc,
+    gdb_f9_powerpc,
+    gdb_f10_powerpc,
+    gdb_f11_powerpc,
+    gdb_f12_powerpc,
+    gdb_f13_powerpc,
+    gdb_f14_powerpc,
+    gdb_f15_powerpc,
+    gdb_f16_powerpc,
+    gdb_f17_powerpc,
+    gdb_f18_powerpc,
+    gdb_f19_powerpc,
+    gdb_f20_powerpc,
+    gdb_f21_powerpc,
+    gdb_f22_powerpc,
+    gdb_f23_powerpc,
+    gdb_f24_powerpc,
+    gdb_f25_powerpc,
+    gdb_f26_powerpc,
+    gdb_f27_powerpc,
+    gdb_f28_powerpc,
+    gdb_f29_powerpc,
+    gdb_f30_powerpc,
+    gdb_f31_powerpc,
+    gdb_cr_powerpc,
+    gdb_fpscr_powerpc,
+    gdb_xer_powerpc = 101,
+    gdb_lr_powerpc = 108,
+    gdb_ctr_powerpc,
+    gdb_pc_powerpc,
+};
+
+#endif // liblldb_RegisterContext_powerpc_H_
diff --git a/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h b/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
new file mode 100644
index 0000000..67dd487
--- /dev/null
+++ b/lldb/source/Plugins/Process/Utility/RegisterInfos_powerpc.h
@@ -0,0 +1,127 @@
+//===-- RegisterInfos_powerpc.h ---------------------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#include <stddef.h>
+
+// 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))
+
+#ifdef DECLARE_REGISTER_INFOS_POWERPC_STRUCT
+
+// Note that the size and offset will be updated by platform-specific classes.
+#define DEFINE_GPR(reg, alt, lldb_kind)           \
+    { #reg, alt, sizeof(((GPR*)NULL)->reg), GPR_OFFSET(reg), eEncodingUint, \
+      eFormatHex, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, gpr_##reg##_powerpc }, NULL, NULL }
+#define DEFINE_FPR(reg, lldb_kind)           \
+    { #reg, NULL, 8, FPR_OFFSET(reg), eEncodingIEEE754, \
+      eFormatFloat, { gcc_dwarf_##reg##_powerpc, gcc_dwarf_##reg##_powerpc, lldb_kind, gdb_##reg##_powerpc, fpr_##reg##_powerpc }, NULL, NULL }
+
+    // General purpose registers.                 GCC,                  DWARF,              Generic,                GDB
+#define POWERPC_REGS \
+    DEFINE_GPR(r0,       NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r1,       "sp",  LLDB_REGNUM_GENERIC_SP), \
+    DEFINE_GPR(r2,       NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r3,       "arg1",LLDB_REGNUM_GENERIC_ARG1), \
+    DEFINE_GPR(r4,       "arg2",LLDB_REGNUM_GENERIC_ARG2), \
+    DEFINE_GPR(r5,       "arg3",LLDB_REGNUM_GENERIC_ARG3), \
+    DEFINE_GPR(r6,       "arg4",LLDB_REGNUM_GENERIC_ARG4), \
+    DEFINE_GPR(r7,       "arg5",LLDB_REGNUM_GENERIC_ARG5), \
+    DEFINE_GPR(r8,       "arg6",LLDB_REGNUM_GENERIC_ARG6), \
+    DEFINE_GPR(r9,       "arg7",LLDB_REGNUM_GENERIC_ARG7), \
+    DEFINE_GPR(r10,      "arg8",LLDB_REGNUM_GENERIC_ARG8), \
+    DEFINE_GPR(r11,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r12,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r13,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r14,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r15,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r16,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r17,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r18,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r19,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r20,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r21,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r22,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r23,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r24,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r25,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r26,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r27,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r28,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r29,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r30,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(r31,      NULL,  LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(lr,       "lr",  LLDB_REGNUM_GENERIC_RA), \
+    DEFINE_GPR(cr,       "cr",  LLDB_REGNUM_GENERIC_FLAGS), \
+    DEFINE_GPR(xer,      "xer", LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(ctr,      "ctr", LLDB_INVALID_REGNUM), \
+    DEFINE_GPR(pc,       "pc",  LLDB_REGNUM_GENERIC_PC), \
+    DEFINE_FPR(f0,       LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f1,       LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f2,       LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f3,       LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f4,       LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f5,       LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f6,       LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f7,       LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f8,       LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f9,       LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f10,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f11,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f12,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f13,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f14,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f15,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f16,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f17,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f18,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f19,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f20,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f21,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f22,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f23,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f24,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f25,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f26,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f27,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f28,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f29,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f30,      LLDB_INVALID_REGNUM), \
+    DEFINE_FPR(f31,      LLDB_INVALID_REGNUM), \
+    { "fpscr", NULL, 8, FPR_OFFSET(fpscr), eEncodingUint, eFormatHex, { gcc_dwarf_fpscr_powerpc, gcc_dwarf_fpscr_powerpc, LLDB_INVALID_REGNUM, gdb_fpscr_powerpc, fpr_fpscr_powerpc }, NULL, NULL },
+    //{ NULL, NULL, sizeof(((GPR*)NULL)->r0), 0, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, LLDB_INVALID_REGNUM, gpr_cfa_powerpc}, NULL, NULL}
+static RegisterInfo
+g_register_infos_powerpc64[] =
+{
+#define GPR GPR64
+    POWERPC_REGS
+#undef GPR
+};
+
+static RegisterInfo
+g_register_infos_powerpc32[] =
+{
+#define GPR GPR32
+    POWERPC_REGS
+#undef GPR
+};
+static_assert((sizeof(g_register_infos_powerpc32) / sizeof(g_register_infos_powerpc32[0])) == k_num_registers_powerpc,
+    "g_register_infos_powerpc32 has wrong number of register infos");
+static_assert((sizeof(g_register_infos_powerpc64) / sizeof(g_register_infos_powerpc64[0])) == k_num_registers_powerpc,
+    "g_register_infos_powerpc64 has wrong number of register infos");
+
+#undef DEFINE_FPR
+#undef DEFINE_GPR
+
+#endif // DECLARE_REGISTER_INFOS_POWERPC_STRUCT
+
+#undef GPR_OFFSET
+
diff --git a/lldb/source/Plugins/Process/elf-core/CMakeLists.txt b/lldb/source/Plugins/Process/elf-core/CMakeLists.txt
index 29c3018..2f5de56 100644
--- a/lldb/source/Plugins/Process/elf-core/CMakeLists.txt
+++ b/lldb/source/Plugins/Process/elf-core/CMakeLists.txt
@@ -6,5 +6,6 @@
   ProcessElfCore.cpp
   ThreadElfCore.cpp
   RegisterContextPOSIXCore_mips64.cpp
+  RegisterContextPOSIXCore_powerpc.cpp
   RegisterContextPOSIXCore_x86_64.cpp
   )
diff --git a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
index 5668167..38e092f 100644
--- a/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ProcessElfCore.cpp
@@ -420,6 +420,7 @@
 {
     lldb::offset_t offset = 0;
     bool lp64 = (arch.GetMachine() == llvm::Triple::mips64 ||
+                 arch.GetMachine() == llvm::Triple::ppc64 ||
                  arch.GetMachine() == llvm::Triple::x86_64);
     int pr_version = data.GetU32(&offset);
 
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
new file mode 100644
index 0000000..15b1b44
--- /dev/null
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.cpp
@@ -0,0 +1,109 @@
+//===-- RegisterContextCorePOSIX_powerpc.cpp ---------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===----------------------------------------------------------------------===//
+
+#include "lldb/Core/DataExtractor.h"
+#include "lldb/Core/RegisterValue.h"
+#include "lldb/Target/Thread.h"
+#include "RegisterContextPOSIX.h"
+#include "RegisterContextPOSIXCore_powerpc.h"
+
+using namespace lldb_private;
+
+RegisterContextCorePOSIX_powerpc::RegisterContextCorePOSIX_powerpc(Thread &thread,
+                                                                 RegisterInfoInterface *register_info,
+                                                                 const DataExtractor &gpregset,
+                                                                 const DataExtractor &fpregset)
+    : RegisterContextPOSIX_powerpc(thread, 0, register_info)
+{
+    m_gpr_buffer.reset(new DataBufferHeap(gpregset.GetDataStart(), gpregset.GetByteSize()));
+    m_gpr.SetData(m_gpr_buffer);
+    m_gpr.SetByteOrder(gpregset.GetByteOrder());
+    m_fpr_buffer.reset(new DataBufferHeap(fpregset.GetDataStart(), fpregset.GetByteSize()));
+    m_fpr.SetData(m_fpr_buffer);
+    m_fpr.SetByteOrder(fpregset.GetByteOrder());
+}
+
+RegisterContextCorePOSIX_powerpc::~RegisterContextCorePOSIX_powerpc()
+{
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::ReadGPR()
+{
+    return true;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::ReadFPR()
+{
+    return true;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::WriteGPR()
+{
+    assert(0);
+    return false;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::WriteFPR()
+{
+    assert(0);
+    return false;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::ReadRegister(const RegisterInfo *reg_info, RegisterValue &value)
+{
+    lldb::offset_t offset = reg_info->byte_offset;
+    if (reg_info->name[0] == 'f') {
+        uint64_t v = m_fpr.GetMaxU64(&offset, reg_info->byte_size);
+        if (offset == reg_info->byte_offset + reg_info->byte_size)
+        {
+            value = v;
+            return true;
+        }
+    } else {
+        uint64_t v = m_gpr.GetMaxU64(&offset, reg_info->byte_size);
+        if (offset == reg_info->byte_offset + reg_info->byte_size)
+        {
+            if (reg_info->byte_size < sizeof(v))
+                value = (uint32_t)v;
+            else
+                value = v;
+            return true;
+        }
+    }
+    return false;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::ReadAllRegisterValues(lldb::DataBufferSP &data_sp)
+{
+    return false;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::WriteRegister(const RegisterInfo *reg_info, const RegisterValue &value)
+{
+    return false;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::WriteAllRegisterValues(const lldb::DataBufferSP &data_sp)
+{
+    return false;
+}
+
+bool
+RegisterContextCorePOSIX_powerpc::HardwareSingleStep(bool enable)
+{
+    return false;
+}
diff --git a/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
new file mode 100644
index 0000000..e657558
--- /dev/null
+++ b/lldb/source/Plugins/Process/elf-core/RegisterContextPOSIXCore_powerpc.h
@@ -0,0 +1,62 @@
+//===-- RegisterContextCorePOSIX_powerpc.h ----------------------*- C++ -*-===//
+//
+//                     The LLVM Compiler Infrastructure
+//
+// This file is distributed under the University of Illinois Open Source
+// License. See LICENSE.TXT for details.
+//
+//===---------------------------------------------------------------------===//
+
+#ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_
+#define liblldb_RegisterContextCorePOSIX_powerpc_H_
+
+#include "lldb/Core/DataBufferHeap.h"
+#include "Plugins/Process/Utility/RegisterContextPOSIX_powerpc.h"
+
+class RegisterContextCorePOSIX_powerpc :
+    public RegisterContextPOSIX_powerpc
+{
+public:
+    RegisterContextCorePOSIX_powerpc (lldb_private::Thread &thread,
+                                     lldb_private::RegisterInfoInterface *register_info,
+                                     const lldb_private::DataExtractor &gpregset,
+                                     const lldb_private::DataExtractor &fpregset);
+
+    ~RegisterContextCorePOSIX_powerpc();
+
+    virtual bool
+    ReadRegister(const lldb_private::RegisterInfo *reg_info, lldb_private::RegisterValue &value);
+
+    virtual bool
+    WriteRegister(const lldb_private::RegisterInfo *reg_info, const lldb_private::RegisterValue &value);
+
+    bool
+    ReadAllRegisterValues(lldb::DataBufferSP &data_sp);
+
+    bool
+    WriteAllRegisterValues(const lldb::DataBufferSP &data_sp);
+
+    bool
+    HardwareSingleStep(bool enable);
+
+protected:
+    bool
+    ReadGPR();
+
+    bool
+    ReadFPR();
+
+    bool
+    WriteGPR();
+
+    bool
+    WriteFPR();
+
+private:
+    lldb::DataBufferSP m_gpr_buffer;
+    lldb::DataBufferSP m_fpr_buffer;
+    lldb_private::DataExtractor m_gpr;
+    lldb_private::DataExtractor m_fpr;
+};
+
+#endif // #ifndef liblldb_RegisterContextCorePOSIX_powerpc_H_
diff --git a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
index 4b611bf..d62bcfc 100644
--- a/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
+++ b/lldb/source/Plugins/Process/elf-core/ThreadElfCore.cpp
@@ -19,8 +19,10 @@
 #include "Plugins/Process/Utility/RegisterContextLinux_x86_64.h"
 #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 "RegisterContextPOSIXCore_mips64.h"
+#include "RegisterContextPOSIXCore_powerpc.h"
 #include "RegisterContextPOSIXCore_x86_64.h"
 
 using namespace lldb;
@@ -94,6 +96,12 @@
             {
                 switch (arch.GetMachine())
                 {
+                    case llvm::Triple::ppc:
+                        reg_interface = new RegisterContextFreeBSD_powerpc32(arch);
+                        break;
+                    case llvm::Triple::ppc64:
+                        reg_interface = new RegisterContextFreeBSD_powerpc64(arch);
+                        break;
                     case llvm::Triple::mips64:
                         reg_interface = new RegisterContextFreeBSD_mips64(arch);
                         break;
@@ -138,6 +146,10 @@
             case llvm::Triple::mips64:
                 m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_mips64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));
                 break;
+            case llvm::Triple::ppc:
+            case llvm::Triple::ppc64:
+                m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_powerpc (*this, reg_interface, m_gpregset_data, m_fpregset_data));
+                break;
             case llvm::Triple::x86:
             case llvm::Triple::x86_64:
                 m_thread_reg_ctx_sp.reset(new RegisterContextCorePOSIX_x86_64 (*this, reg_interface, m_gpregset_data, m_fpregset_data));