From ce7e1002888a03fde0eea631748489b12ff56490 Mon Sep 17 00:00:00 2001
From: Piotr Kubaj <pkubaj@FreeBSD.org>
Date: Sat, 12 Mar 2022 14:37:42 +0100
Subject: [PATCH] Add support for FreeBSD/PPC32

While here, mention that FreeBSD/PPC64 is also supported.
---
 README                         |   2 +
 src/ppc32/Ginit.c              |  12 ++
 src/ppc32/ucontext_i.h         | 198 ++++++++++++++++++++-------------
 src/ptrace/_UPT_access_fpreg.c |   7 +-
 src/ptrace/_UPT_reg_offset.c   |   4 +-
 5 files changed, 142 insertions(+), 81 deletions(-)

diff --git a/README b/README
index 10734ef49..b355c89f0 100644
--- a/README
+++ b/README
@@ -23,6 +23,8 @@ This library supports several architecture/operating-system combinations:
 | FreeBSD | x86-64       | ✓      |
 | FreeBSD | x86          | ✓      |
 | FreeBSD | AArch64      | ✓      |
+| FreeBSD | PPC32        | ✓      |
+| FreeBSD | PPC64        | ✓      |
 | Solaris | x86-64       | ✓      |
 
 ## Libc Requirements
diff --git a/src/ppc32/Ginit.c b/src/ppc32/Ginit.c
index 7b4545580..d978a7752 100644
--- a/src/ppc32/Ginit.c
+++ b/src/ppc32/Ginit.c
@@ -48,12 +48,20 @@ uc_addr (ucontext_t *uc, int reg)
   void *addr;
 
   if ((unsigned) (reg - UNW_PPC32_R0) < 32)
+#if defined(__linux__)
     addr = &uc->uc_mcontext.uc_regs->gregs[reg - UNW_PPC32_R0];
+#elif defined(__FreeBSD__)
+    addr = &uc->uc_mcontext.mc_gpr[reg - UNW_PPC32_R0];
+#endif
 
   else
   if ( ((unsigned) (reg - UNW_PPC32_F0) < 32) &&
        ((unsigned) (reg - UNW_PPC32_F0) >= 0) )
+#if defined(__linux__)
     addr = &uc->uc_mcontext.uc_regs->fpregs.fpregs[reg - UNW_PPC32_F0];
+ #elif defined(__FreeBSD__)
+    addr = &uc->uc_mcontext.mc_fpreg[reg - UNW_PPC32_F0];
+#endif
 
   else
     {
@@ -76,7 +84,11 @@ uc_addr (ucontext_t *uc, int reg)
         default:
           return NULL;
         }
+#if defined(__linux__)
       addr = &uc->uc_mcontext.uc_regs->gregs[gregs_idx];
+#elif defined(__FreeBSD__)
+      addr = &uc->uc_mcontext.mc_gpr[gregs_idx];
+#endif
     }
   return addr;
 }
diff --git a/src/ppc32/ucontext_i.h b/src/ppc32/ucontext_i.h
index c6ba806a0..64f8ed878 100644
--- a/src/ppc32/ucontext_i.h
+++ b/src/ppc32/ucontext_i.h
@@ -29,6 +29,8 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #include "compiler.h"
 #include <ucontext.h>
 
+#if defined(__linux__)
+
 /* These values were derived by reading
    /usr/src/linux-2.6.18-1.8/arch/um/include/sysdep-ppc/ptrace.h and
    /usr/src/linux-2.6.18-1.8/arch/powerpc/kernel/ppc32.h
@@ -42,87 +44,127 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 //#define MQ_IDX                36
 #define LINK_IDX        36
 
+#define _UC_MCONTEXT_GPR(x) ( (void *)&dmy_ctxt.uc_mcontext.gregs[x] - (void *)&dmy_ctxt) )
+#define _UC_MCONTEXT_FPR(x) ( ((void *)&dmy_ctxt.uc_mcontext.fpregs[x] - (void *)&dmy_ctxt) )
+
 /* These are dummy structures used only for obtaining the offsets of the
    various structure members. */
 static ucontext_t dmy_ctxt UNUSED;
 
-#define UC_MCONTEXT_GREGS_R0 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[0] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R1 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[1] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R2 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[2] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R3 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[3] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R4 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[4] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R5 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[5] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R6 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[6] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R7 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[7] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R8 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[8] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R9 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[9] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R10 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[10] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R11 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[11] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R12 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[12] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R13 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[13] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R14 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[14] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R15 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[15] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R16 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[16] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R17 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[17] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R18 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[18] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R19 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[19] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R20 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[20] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R21 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[21] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R22 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[22] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R23 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[23] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R24 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[24] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R25 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[25] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R26 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[26] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R27 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[27] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R28 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[28] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R29 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[29] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R30 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[30] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_R31 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[31] - (void *)&dmy_ctxt)
-
-#define UC_MCONTEXT_GREGS_MSR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[MSR_IDX] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_ORIG_GPR3 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[ORIG_GPR3_IDX] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_CTR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[CTR_IDX] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_LINK ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[LINK_IDX] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_XER ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[XER_IDX] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_CCR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[CCR_IDX] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_SOFTE ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[SOFTE_IDX] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_TRAP ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[TRAP_IDX] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_DAR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[DAR_IDX] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_DSISR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[DSISR_IDX] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_GREGS_RESULT ((void *)&dmy_ctxt.uc_mcontext.uc_regs->gregs[RESULT_IDX] - (void *)&dmy_ctxt)
-
-#define UC_MCONTEXT_FREGS_R0 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[0] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R1 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[1] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R2 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[2] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R3 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[3] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R4 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[4] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R5 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[5] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R6 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[6] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R7 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[7] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R8 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[8] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R9 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[9] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R10 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[10] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R11 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[11] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R12 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[12] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R13 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[13] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R14 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[14] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R15 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[15] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R16 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[16] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R17 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[17] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R18 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[18] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R19 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[19] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R20 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[20] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R21 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[21] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R22 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[22] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R23 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[23] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R24 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[24] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R25 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[25] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R26 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[26] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R27 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[27] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R28 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[28] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R29 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[29] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R30 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[30] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_R31 ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[31] - (void *)&dmy_ctxt)
-#define UC_MCONTEXT_FREGS_FPSCR ((void *)&dmy_ctxt.uc_mcontext.uc_regs->fpregs.fpregs[32] - (void *)&dmy_ctxt)
+#elif defined(__FreeBSD__)
+ /* See /usr/src/sys/powerpc/include/ucontext.h.
+   FreeBSD uses a different structure than Linux.
+*/
+
+#define NIP_IDX         36
+#define MSR_IDX         37
+//#define ORIG_GPR3_IDX
+#define CTR_IDX         35
+#define LINK_IDX        32
+#define XER_IDX         34
+#define CCR_IDX         33
+//#define SOFTE_IDX
+//#define TRAP_IDX
+#define DAR_IDX         39
+#define DSISR_IDX       40
+//#define RESULT_IDX
+
+#define _UC_MCONTEXT_GPR(_x) ( ((void *)&dmy_ctxt.mc_gpr[_x] - (void *)&dmy_ctxt) )
+#define _UC_MCONTEXT_FPR(_x) ( ((void *)&dmy_ctxt.mc_fpreg[_x] - (void *)&dmy_ctxt) )
+
+/* These are dummy structures used only for obtaining the offsets of the
+   various structure members. */
+static struct __mcontext dmy_ctxt;
+
+#else
+#error "Not implemented!"
+#endif
+
+#define UC_MCONTEXT_GREGS_R0 _UC_MCONTEXT_GPR(0)
+#define UC_MCONTEXT_GREGS_R1 _UC_MCONTEXT_GPR(1)
+#define UC_MCONTEXT_GREGS_R2 _UC_MCONTEXT_GPR(2)
+#define UC_MCONTEXT_GREGS_R3 _UC_MCONTEXT_GPR(3)
+#define UC_MCONTEXT_GREGS_R4 _UC_MCONTEXT_GPR(4)
+#define UC_MCONTEXT_GREGS_R5 _UC_MCONTEXT_GPR(5)
+#define UC_MCONTEXT_GREGS_R6 _UC_MCONTEXT_GPR(6)
+#define UC_MCONTEXT_GREGS_R7 _UC_MCONTEXT_GPR(7)
+#define UC_MCONTEXT_GREGS_R8 _UC_MCONTEXT_GPR(8)
+#define UC_MCONTEXT_GREGS_R9 _UC_MCONTEXT_GPR(9)
+#define UC_MCONTEXT_GREGS_R10 _UC_MCONTEXT_GPR(10)
+#define UC_MCONTEXT_GREGS_R11 _UC_MCONTEXT_GPR(11)
+#define UC_MCONTEXT_GREGS_R12 _UC_MCONTEXT_GPR(12)
+#define UC_MCONTEXT_GREGS_R13 _UC_MCONTEXT_GPR(13)
+#define UC_MCONTEXT_GREGS_R14 _UC_MCONTEXT_GPR(14)
+#define UC_MCONTEXT_GREGS_R15 _UC_MCONTEXT_GPR(15)
+#define UC_MCONTEXT_GREGS_R16 _UC_MCONTEXT_GPR(16)
+#define UC_MCONTEXT_GREGS_R17 _UC_MCONTEXT_GPR(17)
+#define UC_MCONTEXT_GREGS_R18 _UC_MCONTEXT_GPR(18)
+#define UC_MCONTEXT_GREGS_R19 _UC_MCONTEXT_GPR(19)
+#define UC_MCONTEXT_GREGS_R20 _UC_MCONTEXT_GPR(20)
+#define UC_MCONTEXT_GREGS_R21 _UC_MCONTEXT_GPR(21)
+#define UC_MCONTEXT_GREGS_R22 _UC_MCONTEXT_GPR(22)
+#define UC_MCONTEXT_GREGS_R23 _UC_MCONTEXT_GPR(23)
+#define UC_MCONTEXT_GREGS_R24 _UC_MCONTEXT_GPR(24)
+#define UC_MCONTEXT_GREGS_R25 _UC_MCONTEXT_GPR(25)
+#define UC_MCONTEXT_GREGS_R26 _UC_MCONTEXT_GPR(26)
+#define UC_MCONTEXT_GREGS_R27 _UC_MCONTEXT_GPR(27)
+#define UC_MCONTEXT_GREGS_R28 _UC_MCONTEXT_GPR(28)
+#define UC_MCONTEXT_GREGS_R29 _UC_MCONTEXT_GPR(29)
+#define UC_MCONTEXT_GREGS_R30 _UC_MCONTEXT_GPR(30)
+#define UC_MCONTEXT_GREGS_R31 _UC_MCONTEXT_GPR(31)
+#define UC_MCONTEXT_GREGS_NIP _UC_MCONTEXT_GPR(NIP_IDX)
+#define UC_MCONTEXT_GREGS_MSR _UC_MCONTEXT_GPR(MSR_IDX)
+#ifdef ORIG_GPR3_IDX
+#define UC_MCONTEXT_GREGS_ORIG_GPR3 _UC_MCONTEXT_GPR(ORIG_GPR3_IDX)
+#endif
+#define UC_MCONTEXT_GREGS_CTR _UC_MCONTEXT_GPR(CTR_IDX)
+#define UC_MCONTEXT_GREGS_LINK _UC_MCONTEXT_GPR(LINK_IDX)
+#define UC_MCONTEXT_GREGS_XER _UC_MCONTEXT_GPR(XER_IDX)
+#define UC_MCONTEXT_GREGS_CCR _UC_MCONTEXT_GPR(CCR_IDX)
+#ifdef SOFTE_IDX
+#define UC_MCONTEXT_GREGS_SOFTE _UC_MCONTEXT_GPR(SOFTE_IDX)
+#endif
+#ifdef TRAP_IDX
+#define UC_MCONTEXT_GREGS_TRAP _UC_MCONTEXT_GPR(TRAP_IDX)
+#endif
+#define UC_MCONTEXT_GREGS_DAR _UC_MCONTEXT_GPR(DAR_IDX)
+#define UC_MCONTEXT_GREGS_DSISR _UC_MCONTEXT_GPR(DSISR_IDX)
+#ifdef RESULT_IDX
+#define UC_MCONTEXT_GREGS_RESULT _UC_MCONTEXT_GPR(RESULT_IDX)
+#endif
+
+#define UC_MCONTEXT_FREGS_R0 _UC_MCONTEXT_FPR(0)
+#define UC_MCONTEXT_FREGS_R1 _UC_MCONTEXT_FPR(1)
+#define UC_MCONTEXT_FREGS_R2 _UC_MCONTEXT_FPR(2)
+#define UC_MCONTEXT_FREGS_R3 _UC_MCONTEXT_FPR(3)
+#define UC_MCONTEXT_FREGS_R4 _UC_MCONTEXT_FPR(4)
+#define UC_MCONTEXT_FREGS_R5 _UC_MCONTEXT_FPR(5)
+#define UC_MCONTEXT_FREGS_R6 _UC_MCONTEXT_FPR(6)
+#define UC_MCONTEXT_FREGS_R7 _UC_MCONTEXT_FPR(7)
+#define UC_MCONTEXT_FREGS_R8 _UC_MCONTEXT_FPR(8)
+#define UC_MCONTEXT_FREGS_R9 _UC_MCONTEXT_FPR(9)
+#define UC_MCONTEXT_FREGS_R10 _UC_MCONTEXT_FPR(10)
+#define UC_MCONTEXT_FREGS_R11 _UC_MCONTEXT_FPR(11)
+#define UC_MCONTEXT_FREGS_R12 _UC_MCONTEXT_FPR(12)
+#define UC_MCONTEXT_FREGS_R13 _UC_MCONTEXT_FPR(13)
+#define UC_MCONTEXT_FREGS_R14 _UC_MCONTEXT_FPR(14)
+#define UC_MCONTEXT_FREGS_R15 _UC_MCONTEXT_FPR(15)
+#define UC_MCONTEXT_FREGS_R16 _UC_MCONTEXT_FPR(16)
+#define UC_MCONTEXT_FREGS_R17 _UC_MCONTEXT_FPR(17)
+#define UC_MCONTEXT_FREGS_R18 _UC_MCONTEXT_FPR(18)
+#define UC_MCONTEXT_FREGS_R19 _UC_MCONTEXT_FPR(19)
+#define UC_MCONTEXT_FREGS_R20 _UC_MCONTEXT_FPR(20)
+#define UC_MCONTEXT_FREGS_R21 _UC_MCONTEXT_FPR(21)
+#define UC_MCONTEXT_FREGS_R22 _UC_MCONTEXT_FPR(22)
+#define UC_MCONTEXT_FREGS_R23 _UC_MCONTEXT_FPR(23)
+#define UC_MCONTEXT_FREGS_R24 _UC_MCONTEXT_FPR(24)
+#define UC_MCONTEXT_FREGS_R25 _UC_MCONTEXT_FPR(25)
+#define UC_MCONTEXT_FREGS_R26 _UC_MCONTEXT_FPR(26)
+#define UC_MCONTEXT_FREGS_R27 _UC_MCONTEXT_FPR(27)
+#define UC_MCONTEXT_FREGS_R28 _UC_MCONTEXT_FPR(28)
+#define UC_MCONTEXT_FREGS_R29 _UC_MCONTEXT_FPR(29)
+#define UC_MCONTEXT_FREGS_R30 _UC_MCONTEXT_FPR(30)
+#define UC_MCONTEXT_FREGS_R31 _UC_MCONTEXT_FPR(31)
+#define UC_MCONTEXT_FREGS_FPSCR _UC_MCONTEXT_FPR(32)
 
 #endif
diff --git a/src/ptrace/_UPT_access_fpreg.c b/src/ptrace/_UPT_access_fpreg.c
index bae343833..a14fced45 100644
--- a/src/ptrace/_UPT_access_fpreg.c
+++ b/src/ptrace/_UPT_access_fpreg.c
@@ -90,6 +90,9 @@ _UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
 #elif defined(__powerpc64__)
   if ((unsigned) reg < UNW_PPC64_F0 || (unsigned) reg > UNW_PPC64_F31)
     return -UNW_EBADREG;
+#elif defined(__powerpc__)
+  if ((unsigned) reg < UNW_PPC32_F0 || (unsigned) reg > UNW_PPC32_F31)
+    return -UNW_EBADREG;
 #else
 #error Fix me
 #endif
@@ -107,7 +110,7 @@ _UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
           memcpy(&fpreg.fpr[reg], val, sizeof(unw_fpreg_t));
 #elif defined(__aarch64__)
           memcpy(&fpreg.fp_q[reg], val, sizeof(unw_fpreg_t));
-#elif defined(__powerpc64__)
+#elif defined(__powerpc__)
           memcpy(&fpreg.fpreg[reg], val, sizeof(unw_fpreg_t));
 #else
 #error Fix me
@@ -123,7 +126,7 @@ _UPT_access_fpreg (unw_addr_space_t as, unw_regnum_t reg, unw_fpreg_t *val,
           memcpy(val, &fpreg.fpr[reg], sizeof(unw_fpreg_t));
 #elif defined(__aarch64__)
           memcpy(val, &fpreg.fp_q[reg], sizeof(unw_fpreg_t));
-#elif defined(__powerpc64__)
+#elif defined(__powerpc__)
           memcpy(val, &fpreg.fpreg[reg], sizeof(unw_fpreg_t));
 #else
 #error Fix me
diff --git a/src/ptrace/_UPT_reg_offset.c b/src/ptrace/_UPT_reg_offset.c
index 57e9c4aa1..382904417 100644
--- a/src/ptrace/_UPT_reg_offset.c
+++ b/src/ptrace/_UPT_reg_offset.c
@@ -36,7 +36,7 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 # include <asm/ptrace_offsets.h>
 #endif
 
-#if defined(__powerpc64__) && defined(__FreeBSD__)
+#if defined(__powerpc__) && defined(__FreeBSD__)
 #define PT_R0   0
 #define PT_R1   1
 #define PT_R2   2
@@ -70,10 +70,12 @@ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.  */
 #define PT_R30  30
 #define PT_R31  31
 #define PT_NIP  32
+#define PT_CCR  33
 #define PT_CTR  35
 #define PT_LNK  36
 #define PT_XER  37
 #define PT_FPR0  48
+#define PT_FPSCR (PT_FPR0 + 2*32 + 1)
 #define PT_VR0  82
 #define PT_VSCR (PT_VR0 + 32*2 + 1)
 #define PT_VRSAVE (PT_VR0 + 33*2)
