--- mono/utils/Makefile.in	2011-04-18 20:15:51.000000000 +0800
+++ mono/utils/Makefile.in	2026-01-23 15:09:36.000000000 +0800
@@ -37,6 +37,7 @@
 @X86_TRUE@am__append_1 = mach-support-x86.c
 @AMD64_TRUE@am__append_2 = mach-support-amd64.c
 @ARM_TRUE@am__append_3 = mach-support-arm.c
+@POWERPC_TRUE@am__append_4 = mach-support-ppc.c
 subdir = mono/utils
 DIST_COMMON = $(libmonoutilsinclude_HEADERS) $(srcdir)/Makefile.am \
 	$(srcdir)/Makefile.in ChangeLog
@@ -86,8 +87,9 @@
 @X86_TRUE@am__objects_2 = mach-support-x86.lo
 @AMD64_TRUE@am__objects_3 = mach-support-amd64.lo
 @ARM_TRUE@am__objects_4 = mach-support-arm.lo
-am__objects_5 = $(am__objects_2) $(am__objects_3) $(am__objects_4)
-am_libmonoutils_la_OBJECTS = $(am__objects_1) $(am__objects_5)
+@POWERPC_TRUE@am__objects_5 = mach-support-ppc.lo
+am__objects_6 = $(am__objects_2) $(am__objects_3) $(am__objects_4) $(am__objects_5)
+am_libmonoutils_la_OBJECTS = $(am__objects_1) $(am__objects_6)
 libmonoutils_la_OBJECTS = $(am_libmonoutils_la_OBJECTS)
 DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
 depcomp = $(SHELL) $(top_srcdir)/depcomp
@@ -376,7 +378,7 @@
 	mach-support.h  \
 	memcheck.h
 
-arch_sources = $(am__append_1) $(am__append_2) $(am__append_3)
+arch_sources = $(am__append_1) $(am__append_2) $(am__append_3) $(am__append_4)
 libmonoutils_la_SOURCES = $(monoutils_sources) $(arch_sources)
 libmonoutilsincludedir = $(includedir)/mono-$(API_VER)/mono/utils
 libmonoutilsinclude_HEADERS = \


--- /dev/null	2026-01-23 14:48:46.000000000 +0800
+++ mono/utils/mach-support-ppc.c	2026-01-23 15:40:08.000000000 +0800
@@ -0,0 +1,104 @@
+/*
+ * mach-support-ppc.c: mach support for ppc
+ *
+ * Authors:
+ *   Geoff Norton (gnorton@novell.com)
+ *   Sergey Fedorov (barracuda@macos-powerpc.org)
+ *
+ * (C) 2026 Novell, Inc.
+ */
+
+#include <config.h>
+
+#if defined(__MACH__)
+#include <stdint.h>
+#include <glib.h>
+#include <pthread.h>
+#include "utils/mono-sigcontext.h"
+#include "mach-support.h"
+
+void *
+mono_mach_arch_get_ip (thread_state_t state)
+{
+	ppc_thread_state_t *arch_state = (ppc_thread_state_t *) state;
+
+	return (void *) arch_state->__srr0;
+}
+
+void *
+mono_mach_arch_get_sp (thread_state_t state)
+{
+	ppc_thread_state_t *arch_state = (ppc_thread_state_t *) state;
+
+	return (void *) arch_state->__r1;
+}
+
+int
+mono_mach_arch_get_mcontext_size ()
+{
+	return sizeof (struct __darwin_mcontext);
+}
+
+void
+mono_mach_arch_thread_state_to_mcontext (thread_state_t state, mcontext_t context)
+{
+	ppc_thread_state_t *arch_state = (ppc_thread_state_t *) state;
+	struct __darwin_mcontext *ctx = (struct __darwin_mcontext *) context;
+
+	ctx->__ss = *arch_state;
+}
+
+void
+mono_mach_arch_mcontext_to_thread_state (mcontext_t context, thread_state_t state)
+{
+	ppc_thread_state_t *arch_state = (ppc_thread_state_t *) state;
+	struct __darwin_mcontext *ctx = (struct __darwin_mcontext *) context;
+
+	*arch_state = ctx->__ss;
+}
+
+int
+mono_mach_arch_get_thread_state_size ()
+{
+	return sizeof (ppc_thread_state_t);
+}
+
+kern_return_t
+mono_mach_arch_get_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t *count)
+{
+	ppc_thread_state_t *arch_state = (ppc_thread_state_t *) state;
+	kern_return_t ret;
+
+	*count = PPC_THREAD_STATE_COUNT;
+
+	ret = thread_get_state (thread, PPC_THREAD_STATE, (thread_state_t) arch_state, count);
+
+	return ret;
+}
+
+kern_return_t
+mono_mach_arch_set_thread_state (thread_port_t thread, thread_state_t state, mach_msg_type_number_t count)
+{
+	return thread_set_state (thread, PPC_THREAD_STATE, state, count);
+}
+
+void *
+mono_mach_get_tls_address_from_thread (pthread_t thread, pthread_key_t key)
+{
+	/* OSX stores TLS values in a hidden array inside the pthread_t structure
+	 * They are keyed off a giant array offset 0x48 into the pointer. This value
+	 * is baked into their pthread_getspecific implementation
+	 */
+	intptr_t *p = (intptr_t *) thread;
+	intptr_t **tsd = (intptr_t **) ((char*)p + 0x48);
+
+	return (void *) &tsd [key];	
+}
+
+void *
+mono_mach_arch_get_tls_value_from_thread (pthread_t thread, guint32 key)
+{
+	return *(void**)mono_mach_get_tls_address_from_thread (thread, key);
+}
+
+#endif

--- mono/metadata/sgen-archdep.h	2012-09-07 03:09:49.000000000 +0800
+++ mono/metadata/sgen-archdep.h	2026-01-23 18:18:24.000000000 +0800
@@ -73,31 +73,15 @@
 
 #elif defined(__ppc__) || defined(__powerpc__) || defined(__powerpc64__)
 
+#include <mono/utils/mono-context.h>
+
 #define REDZONE_SIZE	224
 
 #define ARCH_NUM_REGS 32
-#ifdef __APPLE__
-#define ARCH_STORE_REGS(ptr)	\
-	__asm__ __volatile__(	\
-		"stmw r0, 0(%0)\n"	\
-		:			\
-		: "b" (ptr)		\
-	)
-#else
-#define ARCH_STORE_REGS(ptr)	\
-	__asm__ __volatile__(	\
-		"stmw 0, 0(%0)\n"	\
-		:			\
-		: "b" (ptr)		\
-	)
-#endif
+#define USE_MONO_CTX
+
 #define ARCH_SIGCTX_SP(ctx)	(UCONTEXT_REG_Rn((ctx), 1))
 #define ARCH_SIGCTX_IP(ctx)	(UCONTEXT_REG_NIP((ctx)))
-#define ARCH_COPY_SIGCTX_REGS(a,ctx) do {	\
-	int __i;	\
-	for (__i = 0; __i < 32; ++__i)	\
-		((a)[__i]) = UCONTEXT_REG_Rn((ctx), __i);	\
-	} while (0)
 
 #elif defined(__arm__)
 

--- mono/utils/mono-context.h	2012-09-07 03:09:51.000000000 +0800
+++ mono/utils/mono-context.h	2026-01-23 18:17:29.000000000 +0800
@@ -250,8 +250,8 @@
 typedef struct {
 	gulong sc_ir;          // pc 
 	gulong sc_sp;          // r1
-	mgreg_t regs [19]; /*FIXME, this must be changed to 32 for sgen*/
-	double fregs [18];
+	mgreg_t regs [32];     /* Changed from 19 to 32 for sgen */
+	double fregs [32];
 } MonoContext;
 
 /* we have the stack pointer, not the base pointer in sigcontext */
@@ -264,6 +264,14 @@
 #define MONO_CONTEXT_GET_BP(ctx) ((gpointer)((ctx)->regs [ppc_r31-13]))
 #define MONO_CONTEXT_GET_SP(ctx) ((gpointer)((ctx)->sc_sp))
 
+#define MONO_CONTEXT_GET_CURRENT(ctx)    \
+    __asm__ __volatile__(    \
+        "stmw r0, %0\n"    \
+        : "=r" ((ctx).regs[0])    \
+        :    \
+        : "memory"    \
+    )
+
 #elif defined(__sparc__) || defined(sparc) /* defined(__mono_ppc__) */
 
 typedef struct MonoContext {

--- mono/utils/mono-context.c	2012-09-07 03:09:51.000000000 +0800
+++ mono/utils/mono-context.c	2026-01-23 18:14:46.000000000 +0800
@@ -204,6 +204,58 @@
 #endif
 }
 
+#elif defined(__POWERPC__) || defined(__powerpc__)
+
+#include <mono/utils/mono-context.h>
+
+void
+mono_sigctx_to_monoctx (void *sigctx, MonoContext *mctx)
+{
+#ifdef MONO_SIGNAL_USE_SIGACTION
+    ucontext_t *ctx = (ucontext_t*)sigctx;
+    int i;
+
+    mctx->sc_ir = UCONTEXT_REG_NIP (ctx);
+    mctx->sc_sp = UCONTEXT_REG_Rn (ctx, 1);
+
+    for (i = 0; i < 32; ++i) {
+        mctx->regs = UCONTEXT_REG_Rn (ctx, i);
+    }
+
+    /* Copy FP registers if needed */
+    for (i = 0; i < 32; ++i) {
+        mctx->fregs = UCONTEXT_REG_FPRn (ctx, i);
+    }
+#else
+    /* Fallback for non-sigaction platforms */
+    g_assert_not_reached ();
+#endif
+}
+
+void
+mono_monoctx_to_sigctx (MonoContext *mctx, void *sigctx)
+{
+#ifdef MONO_SIGNAL_USE_SIGACTION
+    ucontext_t *ctx = (ucontext_t*)sigctx;
+    int i;
+
+    UCONTEXT_REG_NIP (ctx) = mctx->sc_ir;
+    UCONTEXT_REG_Rn (ctx, 1) = mctx->sc_sp;
+
+    for (i = 0; i < 32; ++i) {
+        UCONTEXT_REG_Rn (ctx, i) = mctx->regs;
+    }
+
+    /* Copy FP registers if needed */
+    for (i = 0; i < 32; ++i) {
+        UCONTEXT_REG_FPRn (ctx, i) = mctx->fregs;
+    }
+#else
+    /* Fallback for non-sigaction platforms */
+    g_assert_not_reached ();
+#endif
+}
+
 #elif defined(__s390x__)
 
 #include <mono/utils/mono-context.h>
