Special handling of pipe() on alpha

diff --git a/SYSCALLS b/SYSCALLS
index 7815050..62a3471 100644
--- a/SYSCALLS
+++ b/SYSCALLS
@@ -74,7 +74,7 @@
 <!alpha> int utime(const char *, struct utimbuf *)
 int mkdir(const char *, mode_t)
 int rmdir(const char *)
-<!mips,mips64> int pipe(int *)
+<!alpha,mips,mips64> int pipe(int *)
 mode_t umask(mode_t)
 int chroot(const char *)
 int symlink(const char *, const char *)
diff --git a/arch/alpha/Makefile.inc b/arch/alpha/Makefile.inc
index b8ab8b1..a29c48c 100644
--- a/arch/alpha/Makefile.inc
+++ b/arch/alpha/Makefile.inc
@@ -24,7 +24,8 @@
 	arch/$(ARCH)/__divlu.o \
 	arch/$(ARCH)/__remlu.o \
 	arch/$(ARCH)/__divl.o \
-	arch/$(ARCH)/__reml.o
+	arch/$(ARCH)/__reml.o \
+	arch/$(ARCH)/pipe.o
 
 ARCHSOOBJS = $(patsubst %.o,%.lo,$(ARCHOBJS))
 
diff --git a/arch/alpha/pipe.c b/arch/alpha/pipe.c
new file mode 100644
index 0000000..8c587a9
--- /dev/null
+++ b/arch/alpha/pipe.c
@@ -0,0 +1,29 @@
+#include <unistd.h>
+#include <sys/syscall.h>
+
+/* pipe() on alpha returns both file descriptors in registers --
+   $0 and $20 respectively.  This is unlike any other system call,
+   as far as I can tell. */
+
+int pipe(int *fds)
+{
+  long sc_err;
+  register long sc_0 __asm__("$0");
+  register long sc_19 __asm__("$19");
+  register long sc_20 __asm__("$20");
+
+  sc_0 = __NR_pipe;
+  asm volatile("callsys" : "=r" (sc_0), "=r" (sc_19), "=r" (sc_20)
+	       : "0" (sc_0)
+	       : _syscall_clobbers);
+  
+  if ( sc_19 ) {
+    errno = sc_19;
+    return -1;
+  }
+
+  fds[0] = sc_0;
+  fds[1] = sc_20;
+
+  return 0;
+}
diff --git a/klibc/SYSCALLS b/klibc/SYSCALLS
index 7815050..62a3471 100644
--- a/klibc/SYSCALLS
+++ b/klibc/SYSCALLS
@@ -74,7 +74,7 @@
 <!alpha> int utime(const char *, struct utimbuf *)
 int mkdir(const char *, mode_t)
 int rmdir(const char *)
-<!mips,mips64> int pipe(int *)
+<!alpha,mips,mips64> int pipe(int *)
 mode_t umask(mode_t)
 int chroot(const char *)
 int symlink(const char *, const char *)
diff --git a/klibc/arch/alpha/Makefile.inc b/klibc/arch/alpha/Makefile.inc
index b8ab8b1..a29c48c 100644
--- a/klibc/arch/alpha/Makefile.inc
+++ b/klibc/arch/alpha/Makefile.inc
@@ -24,7 +24,8 @@
 	arch/$(ARCH)/__divlu.o \
 	arch/$(ARCH)/__remlu.o \
 	arch/$(ARCH)/__divl.o \
-	arch/$(ARCH)/__reml.o
+	arch/$(ARCH)/__reml.o \
+	arch/$(ARCH)/pipe.o
 
 ARCHSOOBJS = $(patsubst %.o,%.lo,$(ARCHOBJS))
 
diff --git a/klibc/arch/alpha/pipe.c b/klibc/arch/alpha/pipe.c
new file mode 100644
index 0000000..8c587a9
--- /dev/null
+++ b/klibc/arch/alpha/pipe.c
@@ -0,0 +1,29 @@
+#include <unistd.h>
+#include <sys/syscall.h>
+
+/* pipe() on alpha returns both file descriptors in registers --
+   $0 and $20 respectively.  This is unlike any other system call,
+   as far as I can tell. */
+
+int pipe(int *fds)
+{
+  long sc_err;
+  register long sc_0 __asm__("$0");
+  register long sc_19 __asm__("$19");
+  register long sc_20 __asm__("$20");
+
+  sc_0 = __NR_pipe;
+  asm volatile("callsys" : "=r" (sc_0), "=r" (sc_19), "=r" (sc_20)
+	       : "0" (sc_0)
+	       : _syscall_clobbers);
+  
+  if ( sc_19 ) {
+    errno = sc_19;
+    return -1;
+  }
+
+  fds[0] = sc_0;
+  fds[1] = sc_20;
+
+  return 0;
+}