PowerPC Linux support from ericvh.
Mainly adding va_copy/va_end.
Also fix bug in sprint wrapping
around top of memory.
diff --git a/src/Makefile b/src/Makefile
index 7fe300b..9ced533 100644
--- a/src/Makefile
+++ b/src/Makefile
@@ -1,6 +1,6 @@
 ../bin/mk: mkmk.sh
 	SYSNAME=`uname` export SYSNAME; \
-	OBJTYPE=`uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'` export OBJTYPE; \
+	OBJTYPE=`uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g' | sed 's/ppc64/power/g' | sed 's/ppc/power/g'` export OBJTYPE; \
 	PATH=`pwd`/../bin:$$PATH export PATH; \
 	PLAN9=`pwd`/.. export PLAN9; \
 	sh -x mkmk.sh
diff --git a/src/lib9/fmt/fmtprint.c b/src/lib9/fmt/fmtprint.c
index fe2ad3c..c682f49 100644
--- a/src/lib9/fmt/fmtprint.c
+++ b/src/lib9/fmt/fmtprint.c
@@ -32,14 +32,15 @@
 	f->flags = 0;
 	f->width = 0;
 	f->prec = 0;
-	va = f->args;
+	va_copy(va, f->args);
 	va_start(f->args, fmt);
 	n = dofmt(f, fmt);
 	va_end(f->args);
 	f->flags = 0;
 	f->width = 0;
 	f->prec = 0;
-	f->args = va;
+	va_copy(f->args,va);
+	va_end(va);
 	if(n >= 0)
 		return 0;
 	return n;
diff --git a/src/lib9/fmt/fmtvprint.c b/src/lib9/fmt/fmtvprint.c
index 6aed013..60974a0 100644
--- a/src/lib9/fmt/fmtvprint.c
+++ b/src/lib9/fmt/fmtvprint.c
@@ -32,13 +32,15 @@
 	f->flags = 0;
 	f->width = 0;
 	f->prec = 0;
-	va = f->args;
-	f->args = args;
+	va_copy(va,f->args);
+	va_copy(f->args,args);
 	n = dofmt(f, fmt);
 	f->flags = 0;
 	f->width = 0;
 	f->prec = 0;
-	f->args = va;
+	va_end(f->args);
+	va_copy(f->args,va);
+	va_end(va);
 	if(n >= 0)
 		return 0;
 	return n;
diff --git a/src/lib9/fmt/nan64.c b/src/lib9/fmt/nan64.c
index a02a3ad..4df496c 100644
--- a/src/lib9/fmt/nan64.c
+++ b/src/lib9/fmt/nan64.c
@@ -7,7 +7,7 @@
 
 #include "nan.h"
 
-#ifdef __APPLE__
+#if defined (__APPLE__) || (__powerpc__)
 #define _NEEDLL
 #endif
 
diff --git a/src/lib9/fmt/runevseprint.c b/src/lib9/fmt/runevseprint.c
index e4cc1ea..a9ef99b 100644
--- a/src/lib9/fmt/runevseprint.c
+++ b/src/lib9/fmt/runevseprint.c
@@ -31,8 +31,9 @@
 	f.flush = nil;
 	f.farg = nil;
 	f.nfmt = 0;
-	f.args = args;
+	va_copy(f.args,args);
 	dofmt(&f, fmt);
+	va_end(f.args);
 	*(Rune*)f.to = '\0';
 	return (Rune*)f.to;
 }
diff --git a/src/lib9/fmt/runevsmprint.c b/src/lib9/fmt/runevsmprint.c
index 71c23d8..3326da8 100644
--- a/src/lib9/fmt/runevsmprint.c
+++ b/src/lib9/fmt/runevsmprint.c
@@ -28,8 +28,9 @@
 
 	if(runefmtstrinit(&f) < 0)
 		return nil;
-	f.args = args;
+	va_copy(f.args,args);
 	n = dofmt(&f, fmt);
+	va_end(f.args);
 	if(n < 0)
 		return nil;
 	*(Rune*)f.to = '\0';
diff --git a/src/lib9/fmt/runevsnprint.c b/src/lib9/fmt/runevsnprint.c
index 933a04c..71557e5 100644
--- a/src/lib9/fmt/runevsnprint.c
+++ b/src/lib9/fmt/runevsnprint.c
@@ -31,8 +31,9 @@
 	f.flush = nil;
 	f.farg = nil;
 	f.nfmt = 0;
-	f.args = args;
+	va_copy(f.args,args);
 	dofmt(&f, fmt);
+	va_end(f.args);
 	*(Rune*)f.to = '\0';
 	return (Rune*)f.to - buf;
 }
diff --git a/src/lib9/fmt/sprint.c b/src/lib9/fmt/sprint.c
index 57150c3..ac68851 100644
--- a/src/lib9/fmt/sprint.c
+++ b/src/lib9/fmt/sprint.c
@@ -18,10 +18,19 @@
 sprint(char *buf, char *fmt, ...)
 {
 	int n;
+	uint len;
 	va_list args;
 
+	len = 1<<30;  /* big number, but sprint is deprecated anyway */
+	/*
+	 * on PowerPC, the stack is near the top of memory, so
+	 * we must be sure not to overflow a 32-bit pointer.
+	 */
+	if(buf+len < buf)
+		len = -(uint)buf-1;
+
 	va_start(args, fmt);
-	n = vsnprint(buf, 65536, fmt, args);	/* big number, but sprint is deprecated anyway */
+	n = vsnprint(buf, len, fmt, args);
 	va_end(args);
 	return n;
 }
diff --git a/src/lib9/fmt/vfprint.c b/src/lib9/fmt/vfprint.c
index e4ab82a..711b658 100644
--- a/src/lib9/fmt/vfprint.c
+++ b/src/lib9/fmt/vfprint.c
@@ -23,8 +23,9 @@
 	int n;
 
 	fmtfdinit(&f, fd, buf, sizeof(buf));
-	f.args = args;
+	va_copy(f.args,args);
 	n = dofmt(&f, fmt);
+	va_end(f.args);
 	if(n > 0 && __fmtFdFlush(&f) == 0)
 		return -1;
 	return n;
diff --git a/src/lib9/fmt/vseprint.c b/src/lib9/fmt/vseprint.c
index 85ed810..a1be5e4 100644
--- a/src/lib9/fmt/vseprint.c
+++ b/src/lib9/fmt/vseprint.c
@@ -29,8 +29,9 @@
 	f.flush = 0;
 	f.farg = nil;
 	f.nfmt = 0;
-	f.args = args;
+	va_copy(f.args,args);
 	dofmt(&f, fmt);
+	va_end(f.args);
 	*(char*)f.to = '\0';
 	return (char*)f.to;
 }
diff --git a/src/lib9/fmt/vsmprint.c b/src/lib9/fmt/vsmprint.c
index 34a1b36..4f55c41 100644
--- a/src/lib9/fmt/vsmprint.c
+++ b/src/lib9/fmt/vsmprint.c
@@ -27,8 +27,9 @@
 
 	if(fmtstrinit(&f) < 0)
 		return nil;
-	f.args = args;
+	va_copy(f.args,args);
 	n = dofmt(&f, fmt);
+	va_end(f.args);
 	if(n < 0)
 		return nil;
 	return fmtstrflush(&f);
diff --git a/src/lib9/fmt/vsnprint.c b/src/lib9/fmt/vsnprint.c
index 21662e6..ad64203 100644
--- a/src/lib9/fmt/vsnprint.c
+++ b/src/lib9/fmt/vsnprint.c
@@ -20,6 +20,7 @@
 vsnprint(char *buf, int len, char *fmt, va_list args)
 {
 	Fmt f;
+	int x = 0;
 
 	if(len <= 0)
 		return -1;
@@ -30,8 +31,9 @@
 	f.flush = 0;
 	f.farg = nil;
 	f.nfmt = 0;
-	f.args = args;
+	va_copy(f.args,args);
 	dofmt(&f, fmt);
+	va_end(f.args);
 	*(char*)f.to = '\0';
 	return (char*)f.to - buf;
 }
diff --git a/src/libbio/bprint.c b/src/libbio/bprint.c
index 2b66605..f8a4d94 100644
--- a/src/libbio/bprint.c
+++ b/src/libbio/bprint.c
@@ -11,9 +11,10 @@
 	if(Bfmtinit(&f, bp) < 0)
 		return -1;
 	va_start(args, fmt);
-	f.args = args;
+	va_copy(f.args, args);
 	n = dofmt(&f, fmt);
 	va_end(args);
+	va_end(f.args);
 	if(n > 0 && Bfmtflush(&f) < 0)
 		return -1;
 	return n;
diff --git a/src/libthread/label.h b/src/libthread/label.h
index 5161e37..c3cef2d 100644
--- a/src/libthread/label.h
+++ b/src/libthread/label.h
@@ -40,6 +40,21 @@
 	ulong	sp;		/* %o6 */
 	ulong	link;		/* %o7 */
 };
+#elif defined(__powerpc__)
+struct Label
+{
+	ulong	pc;		/* lr */
+	ulong	cr;		/* mfcr */
+	ulong	ctr;		/* mfcr */
+	ulong	xer;		/* mfcr */
+	ulong	sp;		/* callee saved: r1 */
+	ulong	toc;		/* callee saved: r2 */
+	ulong	gpr[19];	/* callee saved: r13-r31 */
+// XXX: currently do not save vector registers or floating-point state
+//	ulong	pad;
+//	uvlong	fpr[18];	/* callee saved: f14-f31 */
+//	ulong	vr[4*12];	/* callee saved: v20-v31, 256-bits each */
+};
 #else
 #error "Unknown or unsupported architecture"
 #endif
diff --git a/src/libthread/mkfile b/src/libthread/mkfile
index f8ec8e8..221cb81 100644
--- a/src/libthread/mkfile
+++ b/src/libthread/mkfile
@@ -53,6 +53,7 @@
 
 CLEANFILES=$CLEANFILES tprimes texec
 
+asm-Linux-ppc.$O: asm-Linux-386.s
 asm-Linux-386.$O: asm-FreeBSD-386.s
 asm-NetBSD-386.$O: asm-FreeBSD-386.s
 asm-OpenBSD-386.$O: asm-FreeBSD-386.s
diff --git a/src/mkhdr b/src/mkhdr
index 1f80171..9229e92 100644
--- a/src/mkhdr
+++ b/src/mkhdr
@@ -1,5 +1,5 @@
 SYSNAME=`uname`
-OBJTYPE=`uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g'`
+OBJTYPE=`uname -m | sed 's;i.86;386;; s;/.*;;; s; ;;g' | sed 's/ppc64/power/g' | sed 's/ppc/power/g'`
 
 BIN=$PLAN9/bin
 LIBDIR=$PLAN9/lib