Source: upstream
--- common/system/libcontext.cpp
+++ common/system/libcontext.cpp
@@ -710,3 +710,445 @@ __asm (
 );
 
 #endif
+
+#if defined(LIBCONTEXT_PLATFORM_linux_ppc32) && defined(LIBCONTEXT_COMPILER_gcc)
+__asm (
+".text\n"
+".globl jump_fcontext\n"
+".align 2\n"
+".type jump_fcontext,@function\n"
+"jump_fcontext:\n"
+"    # reserve space on stack\n"
+"    subi  %r1, %r1, 240\n"
+"    stw  %r13, 152(%r1)  # save R13\n"
+"    stw  %r14, 156(%r1)  # save R14\n"
+"    stw  %r15, 160(%r1)  # save R15\n"
+"    stw  %r16, 164(%r1)  # save R16\n"
+"    stw  %r17, 168(%r1)  # save R17\n"
+"    stw  %r18, 172(%r1)  # save R18\n"
+"    stw  %r19, 176(%r1)  # save R19\n"
+"    stw  %r20, 180(%r1)  # save R20\n"
+"    stw  %r21, 184(%r1)  # save R21\n"
+"    stw  %r22, 188(%r1)  # save R22\n"
+"    stw  %r23, 192(%r1)  # save R23\n"
+"    stw  %r24, 196(%r1)  # save R24\n"
+"    stw  %r25, 200(%r1)  # save R25\n"
+"    stw  %r26, 204(%r1)  # save R26\n"
+"    stw  %r27, 208(%r1)  # save R27\n"
+"    stw  %r28, 212(%r1)  # save R28\n"
+"    stw  %r29, 216(%r1)  # save R29\n"
+"    stw  %r30, 220(%r1)  # save R30\n"
+"    stw  %r31, 224(%r1)  # save R31\n"
+"    # save CR\n"
+"    mfcr  %r0\n"
+"    stw  %r0, 228(%r1)\n"
+"    # save LR\n"
+"    mflr  %r0\n"
+"    stw  %r0, 232(%r1)\n"
+"    # save LR as PC\n"
+"    stw  %r0, 236(%r1)\n"
+"    # test if fpu env should be preserved\n"
+"    cmpwi  cr7, %r6, 0\n"
+"    beq  cr7, 1f\n"
+"    stfd  %f14, 0(%r1)  # save F14\n"
+"    stfd  %f15, 8(%r1)  # save F15\n"
+"    stfd  %f16, 16(%r1)  # save F16\n"
+"    stfd  %f17, 24(%r1)  # save F17\n"
+"    stfd  %f18, 32(%r1)  # save F18\n"
+"    stfd  %f19, 40(%r1)  # save F19\n"
+"    stfd  %f20, 48(%r1)  # save F20\n"
+"    stfd  %f21, 56(%r1)  # save F21\n"
+"    stfd  %f22, 64(%r1)  # save F22\n"
+"    stfd  %f23, 72(%r1)  # save F23\n"
+"    stfd  %f24, 80(%r1)  # save F24\n"
+"    stfd  %f25, 88(%r1)  # save F25\n"
+"    stfd  %f26, 96(%r1)  # save F26\n"
+"    stfd  %f27, 104(%r1)  # save F27\n"
+"    stfd  %f28, 112(%r1)  # save F28\n"
+"    stfd  %f29, 120(%r1)  # save F29\n"
+"    stfd  %f30, 128(%r1)  # save F30\n"
+"    stfd  %f31, 136(%r1)  # save F31\n"
+"    mffs  %f0  # load FPSCR\n"
+"    stfd  %f0, 144(%r1)  # save FPSCR\n"
+"1:\n"
+"    # store RSP (pointing to context-data) in R3\n"
+"    stw  %r1, 0(%r3)\n"
+"    # restore RSP (pointing to context-data) from R4\n"
+"    mr  %r1, %r4\n"
+"    # test if fpu env should be preserved\n"
+"    cmpwi  cr7, %r6, 0\n"
+"    beq  cr7, 2f\n"
+"    lfd  %f14, 0(%r1)  # restore F14\n"
+"    lfd  %f15, 8(%r1)  # restore F15\n"
+"    lfd  %f16, 16(%r1)  # restore F16\n"
+"    lfd  %f17, 24(%r1)  # restore F17\n"
+"    lfd  %f18, 32(%r1)  # restore F18\n"
+"    lfd  %f19, 40(%r1)  # restore F19\n"
+"    lfd  %f20, 48(%r1)  # restore F20\n"
+"    lfd  %f21, 56(%r1)  # restore F21\n"
+"    lfd  %f22, 64(%r1)  # restore F22\n"
+"    lfd  %f23, 72(%r1)  # restore F23\n"
+"    lfd  %f24, 80(%r1)  # restore F24\n"
+"    lfd  %f25, 88(%r1)  # restore F25\n"
+"    lfd  %f26, 96(%r1)  # restore F26\n"
+"    lfd  %f27, 104(%r1)  # restore F27\n"
+"    lfd  %f28, 112(%r1)  # restore F28\n"
+"    lfd  %f29, 120(%r1)  # restore F29\n"
+"    lfd  %f30, 128(%r1)  # restore F30\n"
+"    lfd  %f31, 136(%r1)  # restore F31\n"
+"    lfd  %f0,  144(%r1)  # load FPSCR\n"
+"    mtfsf  0xff, %f0  # restore FPSCR\n"
+"2:\n"
+"    lwz  %r13, 152(%r1)  # restore R13\n"
+"    lwz  %r14, 156(%r1)  # restore R14\n"
+"    lwz  %r15, 160(%r1)  # restore R15\n"
+"    lwz  %r16, 164(%r1)  # restore R16\n"
+"    lwz  %r17, 168(%r1)  # restore R17\n"
+"    lwz  %r18, 172(%r1)  # restore R18\n"
+"    lwz  %r19, 176(%r1)  # restore R19\n"
+"    lwz  %r20, 180(%r1)  # restore R20\n"
+"    lwz  %r21, 184(%r1)  # restore R21\n"
+"    lwz  %r22, 188(%r1)  # restore R22\n"
+"    lwz  %r23, 192(%r1)  # restore R23\n"
+"    lwz  %r24, 196(%r1)  # restore R24\n"
+"    lwz  %r25, 200(%r1)  # restore R25\n"
+"    lwz  %r26, 204(%r1)  # restore R26\n"
+"    lwz  %r27, 208(%r1)  # restore R27\n"
+"    lwz  %r28, 212(%r1)  # restore R28\n"
+"    lwz  %r29, 216(%r1)  # restore R29\n"
+"    lwz  %r30, 220(%r1)  # restore R30\n"
+"    lwz  %r31, 224(%r1)  # restore R31\n"
+"    # restore CR\n"
+"    lwz  %r0, 228(%r1)\n"
+"    mtcr  %r0\n"
+"    # restore LR\n"
+"    lwz  %r0, 232(%r1)\n"
+"    mtlr  %r0\n"
+"    # load PC\n"
+"    lwz  %r0, 236(%r1)\n"
+"    # restore CTR\n"
+"    mtctr  %r0\n"
+"    # adjust stack\n"
+"    addi  %r1, %r1, 240\n"
+"    # use third arg as return value after jump\n"
+"    # use third arg as first arg in context function\n"
+"    mr  %r3, %r5\n"
+"    # jump to context\n"
+"    bctr\n"
+".size jump_fcontext, .-jump_fcontext\n"
+".section .note.GNU-stack,\"\",%progbits\n"
+);
+
+#endif
+
+#if defined(LIBCONTEXT_PLATFORM_linux_ppc32) && defined(LIBCONTEXT_COMPILER_gcc)
+__asm (
+".text\n"
+".globl make_fcontext\n"
+".align 2\n"
+".type make_fcontext,@function\n"
+"make_fcontext:\n"
+"    # save return address into R6\n"
+"    mflr  %r6\n"
+"    # first arg of make_fcontext() == top address of context-function\n"
+"    # shift address in R3 to lower 16 byte boundary\n"
+"    clrrwi  %r3, %r3, 4\n"
+"    # reserve space for context-data on context-stack\n"
+"    # including 64 byte of linkage + parameter area (R1 % 16 == 0)\n"
+"    subi  %r3, %r3, 304\n"
+"    # third arg of make_fcontext() == address of context-function\n"
+"    stw  %r5, 236(%r3)\n"
+"    # load LR\n"
+"    mflr  %r0\n"
+"    # jump to label 1\n"
+"    bl  1f\n"
+"1:\n"
+"    # load LR into R4\n"
+"    mflr  %r4\n"
+"    # compute abs address of label finish\n"
+"    addi  %r4, %r4, finish - 1b\n"
+"    # restore LR\n"
+"    mtlr  %r0\n"
+"    # save address of finish as return-address for context-function\n"
+"    # will be entered after context-function returns\n"
+"    stw  %r4, 232(%r3)\n"
+"    # restore return address from R6\n"
+"    mtlr  %r6\n"
+"    blr  # return pointer to context-data\n"
+"finish:\n"
+"    # save return address into R0\n"
+"    mflr  %r0\n"
+"    # save return address on stack, set up stack frame\n"
+"    stw  %r0, 4(%r1)\n"
+"    # allocate stack space, R1 % 16 == 0\n"
+"    stwu  %r1, -16(%r1)\n"
+"    # exit code is zero\n"
+"    li  %r3, 0\n"
+"    # exit application\n"
+"    bl  _exit@plt\n"
+".size make_fcontext, .-make_fcontext\n"
+".section .note.GNU-stack,\"\",%progbits\n"
+);
+
+#endif
+
+#if defined(LIBCONTEXT_PLATFORM_linux_ppc64) && defined(LIBCONTEXT_COMPILER_gcc)
+__asm (
+".globl jump_fcontext\n"
+#if _CALL_ELF == 2
+"  .text\n"
+"  .align 2\n"
+"jump_fcontext:\n"
+"        addis   %r2, %r12, .TOC.-jump_fcontext@ha\n"
+"        addi    %r2, %r2, .TOC.-jump_fcontext@l\n"
+"        .localentry jump_fcontext, . - jump_fcontext\n"
+#else
+"  .section \".opd\",\"aw\"\n"
+"  .align 3\n"
+"jump_fcontext:\n"
+# ifdef _CALL_LINUX
+"        .quad   .L.jump_fcontext,.TOC.@tocbase,0\n"
+"        .type   jump_fcontext,@function\n"
+"        .text\n"
+"        .align 2\n"
+".L.jump_fcontext:\n"
+# else
+"        .hidden .jump_fcontext\n"
+"        .globl  .jump_fcontext\n"
+"        .quad   .jump_fcontext,.TOC.@tocbase,0\n"
+"        .size   jump_fcontext,24\n"
+"        .type   .jump_fcontext,@function\n"
+"        .text\n"
+"        .align 2\n"
+".jump_fcontext:\n"
+# endif
+#endif
+"    # reserve space on stack\n"
+"    subi  %r1, %r1, 328\n"
+#if _CALL_ELF != 2
+"    std  %r2,  152(%r1)  # save TOC\n"
+#endif
+"    std  %r14, 160(%r1)  # save R14\n"
+"    std  %r15, 168(%r1)  # save R15\n"
+"    std  %r16, 176(%r1)  # save R16\n"
+"    std  %r17, 184(%r1)  # save R17\n"
+"    std  %r18, 192(%r1)  # save R18\n"
+"    std  %r19, 200(%r1)  # save R19\n"
+"    std  %r20, 208(%r1)  # save R20\n"
+"    std  %r21, 216(%r1)  # save R21\n"
+"    std  %r22, 224(%r1)  # save R22\n"
+"    std  %r23, 232(%r1)  # save R23\n"
+"    std  %r24, 240(%r1)  # save R24\n"
+"    std  %r25, 248(%r1)  # save R25\n"
+"    std  %r26, 256(%r1)  # save R26\n"
+"    std  %r27, 264(%r1)  # save R27\n"
+"    std  %r28, 272(%r1)  # save R28\n"
+"    std  %r29, 280(%r1)  # save R29\n"
+"    std  %r30, 288(%r1)  # save R30\n"
+"    std  %r31, 296(%r1)  # save R31\n"
+"    # save CR\n"
+"    mfcr  %r0\n"
+"    std  %r0, 304(%r1)\n"
+"    # save LR\n"
+"    mflr  %r0\n"
+"    std  %r0, 312(%r1)\n"
+"    # save LR as PC\n"
+"    std  %r0, 320(%r1)\n"
+"    # test if fpu env should be preserved\n"
+"    cmpwi  cr7, %r6, 0\n"
+"    beq  cr7, 1f\n"
+"    stfd  %f14, 0(%r1)  # save F14\n"
+"    stfd  %f15, 8(%r1)  # save F15\n"
+"    stfd  %f16, 16(%r1)  # save F16\n"
+"    stfd  %f17, 24(%r1)  # save F17\n"
+"    stfd  %f18, 32(%r1)  # save F18\n"
+"    stfd  %f19, 40(%r1)  # save F19\n"
+"    stfd  %f20, 48(%r1)  # save F20\n"
+"    stfd  %f21, 56(%r1)  # save F21\n"
+"    stfd  %f22, 64(%r1)  # save F22\n"
+"    stfd  %f23, 72(%r1)  # save F23\n"
+"    stfd  %f24, 80(%r1)  # save F24\n"
+"    stfd  %f25, 88(%r1)  # save F25\n"
+"    stfd  %f26, 96(%r1)  # save F26\n"
+"    stfd  %f27, 104(%r1)  # save F27\n"
+"    stfd  %f28, 112(%r1)  # save F28\n"
+"    stfd  %f29, 120(%r1)  # save F29\n"
+"    stfd  %f30, 128(%r1)  # save F30\n"
+"    stfd  %f31, 136(%r1)  # save F31\n"
+"    mffs  %f0  # load FPSCR\n"
+"    stfd  %f0, 144(%r1)  # save FPSCR\n"
+"1:\n"
+"    # store RSP (pointing to context-data) in R3\n"
+"    std  %r1, 0(%r3)\n"
+"    # restore RSP (pointing to context-data) from R4\n"
+"    mr  %r1, %r4\n"
+"    # test if fpu env should be preserved\n"
+"    cmpwi  cr7, %r6, 0\n"
+"    beq  cr7, 2f\n"
+"    lfd  %f14, 0(%r1)  # restore F14\n"
+"    lfd  %f15, 8(%r1)  # restore F15\n"
+"    lfd  %f16, 16(%r1)  # restore F16\n"
+"    lfd  %f17, 24(%r1)  # restore F17\n"
+"    lfd  %f18, 32(%r1)  # restore F18\n"
+"    lfd  %f19, 40(%r1)  # restore F19\n"
+"    lfd  %f20, 48(%r1)  # restore F20\n"
+"    lfd  %f21, 56(%r1)  # restore F21\n"
+"    lfd  %f22, 64(%r1)  # restore F22\n"
+"    lfd  %f23, 72(%r1)  # restore F23\n"
+"    lfd  %f24, 80(%r1)  # restore F24\n"
+"    lfd  %f25, 88(%r1)  # restore F25\n"
+"    lfd  %f26, 96(%r1)  # restore F26\n"
+"    lfd  %f27, 104(%r1)  # restore F27\n"
+"    lfd  %f28, 112(%r1)  # restore F28\n"
+"    lfd  %f29, 120(%r1)  # restore F29\n"
+"    lfd  %f30, 128(%r1)  # restore F30\n"
+"    lfd  %f31, 136(%r1)  # restore F31\n"
+"    lfd  %f0,  144(%r1)  # load FPSCR\n"
+"    mtfsf  0xff, %f0  # restore FPSCR\n"
+"2:\n"
+#if _CALL_ELF != 2
+"    ld  %r2,  152(%r1)  # restore TOC\n"
+#endif
+"    ld  %r14, 160(%r1)  # restore R14\n"
+"    ld  %r15, 168(%r1)  # restore R15\n"
+"    ld  %r16, 176(%r1)  # restore R16\n"
+"    ld  %r17, 184(%r1)  # restore R17\n"
+"    ld  %r18, 192(%r1)  # restore R18\n"
+"    ld  %r19, 200(%r1)  # restore R19\n"
+"    ld  %r20, 208(%r1)  # restore R20\n"
+"    ld  %r21, 216(%r1)  # restore R21\n"
+"    ld  %r22, 224(%r1)  # restore R22\n"
+"    ld  %r23, 232(%r1)  # restore R23\n"
+"    ld  %r24, 240(%r1)  # restore R24\n"
+"    ld  %r25, 248(%r1)  # restore R25\n"
+"    ld  %r26, 256(%r1)  # restore R26\n"
+"    ld  %r27, 264(%r1)  # restore R27\n"
+"    ld  %r28, 272(%r1)  # restore R28\n"
+"    ld  %r29, 280(%r1)  # restore R29\n"
+"    ld  %r30, 288(%r1)  # restore R30\n"
+"    ld  %r31, 296(%r1)  # restore R31\n"
+"    # restore CR\n"
+"    ld  %r0, 304(%r1)\n"
+"    mtcr  %r0\n"
+"    # restore LR\n"
+"    ld  %r0, 312(%r1)\n"
+"    mtlr  %r0\n"
+"    # load PC\n"
+"    ld  %r12, 320(%r1)\n"
+"    # restore CTR\n"
+"    mtctr  %r12\n"
+"    # adjust stack\n"
+"    addi  %r1, %r1, 328\n"
+"    # use third arg as return value after jump\n"
+"    # use third arg as first arg in context function\n"
+"    mr  %r3, %r5\n"
+"    # jump to context\n"
+"    bctr\n"
+#if _CALL_ELF == 2
+"  .size jump_fcontext, .-jump_fcontext\n"
+#else
+# ifdef _CALL_LINUX
+"  .size .jump_fcontext, .-.L.jump_fcontext\n"
+# else
+"  .size .jump_fcontext, .-.jump_fcontext\n"
+# endif
+#endif
+".section .note.GNU-stack,\"\",%progbits\n"
+);
+
+#endif
+
+#if defined(LIBCONTEXT_PLATFORM_linux_ppc64) && defined(LIBCONTEXT_COMPILER_gcc)
+__asm (
+".globl make_fcontext\n"
+#if _CALL_ELF == 2
+"  .text\n"
+"  .align 2\n"
+"make_fcontext:\n"
+"  addis   %r2, %r12, .TOC.-make_fcontext@ha\n"
+"  addi    %r2, %r2, .TOC.-make_fcontext@l\n"
+"  .localentry make_fcontext, . - make_fcontext\n"
+#else
+"  .section \".opd\",\"aw\"\n"
+"  .align 3\n"
+"make_fcontext:\n"
+# ifdef _CALL_LINUX
+"  .quad   .L.make_fcontext,.TOC.@tocbase,0\n"
+"  .type   make_fcontext,@function\n"
+"  .text\n"
+"  .align 2\n"
+".L.make_fcontext:\n"
+# else
+"  .hidden .make_fcontext\n"
+"  .globl  .make_fcontext\n"
+"  .quad   .make_fcontext,.TOC.@tocbase,0\n"
+"  .size   make_fcontext,24\n"
+"  .type   .make_fcontext,@function\n"
+"  .text\n"
+"  .align 2\n"
+".make_fcontext:\n"
+# endif
+#endif
+"    # save return address into R6\n"
+"    mflr  %r6\n"
+"    # first arg of make_fcontext() == top address of context-stack\n"
+"    # shift address in R3 to lower 16 byte boundary\n"
+"    clrrdi  %r3, %r3, 4\n"
+"    # reserve space for context-data on context-stack\n"
+"    # including 64 byte of linkage + parameter area (R1 % 16 == 0)\n"
+"    subi  %r3, %r3, 392\n"
+"    # third arg of make_fcontext() == address of context-function\n"
+"    # entry point (ELFv2) or descriptor (ELFv1)\n"
+#if _CALL_ELF == 2
+"    # save address of context-function entry point\n"
+"    std  %r5, 320(%r3)\n"
+#else
+"    # save address of context-function entry point\n"
+"    ld   %r4, 0(%r5)\n"
+"    std  %r4, 320(%r3)\n"
+"    # save TOC of context-function\n"
+"    ld   %r4, 8(%r5)\n"
+"    std  %r4, 152(%r3)\n"
+#endif
+"    # load LR\n"
+"    mflr  %r0\n"
+"    # jump to label 1\n"
+"    bl  1f\n"
+"1:\n"
+"    # load LR into R4\n"
+"    mflr  %r4\n"
+"    # compute abs address of label finish\n"
+"    addi  %r4, %r4, finish - 1b\n"
+"    # restore LR\n"
+"    mtlr  %r0\n"
+"    # save address of finish as return-address for context-function\n"
+"    # will be entered after context-function returns\n"
+"    std  %r4, 312(%r3)\n"
+"    # restore return address from R6\n"
+"    mtlr  %r6\n"
+"    blr  # return pointer to context-data\n"
+"finish:\n"
+"    # save return address into R0\n"
+"    mflr  %r0\n"
+"    # save return address on stack, set up stack frame\n"
+"    std  %r0, 8(%r1)\n"
+"    # allocate stack space, R1 % 16 == 0\n"
+"    stdu  %r1, -32(%r1)\n"
+"    # exit code is zero\n"
+"    li  %r3, 0\n"
+"    # exit application\n"
+"    bl  _exit\n"
+"    nop\n"
+#if _CALL_ELF == 2
+"  .size make_fcontext, .-make_fcontext\n"
+#else
+# ifdef _CALL_LINUX
+"  .size .make_fcontext, .-.L.make_fcontext\n"
+# else
+"  .size .make_fcontext, .-.make_fcontext\n"
+# endif
+#endif
+".section .note.GNU-stack,\"\",%progbits\n"
+);
+
+#endif
--- include/system/libcontext.h
+++ include/system/libcontext.h
@@ -39,6 +39,12 @@
     #elif __aarch64__
         #define LIBCONTEXT_PLATFORM_linux_arm64
         #define LIBCONTEXT_CALL_CONVENTION
+    #elif __powerpc64__
+        #define LIBCONTEXT_PLATFORM_linux_ppc64
+        #define LIBCONTEXT_CALL_CONVENTION
+    #elif __powerpc__
+        #define LIBCONTEXT_PLATFORM_linux_ppc32
+        #define LIBCONTEXT_CALL_CONVENTION
     #endif
 
     #elif defined(__MINGW32__) || defined(__MINGW64__)