Special-case socketcalls on i386, esp. since i386 is possibly the only
architecture still using socketcalls.  It also lends itself to a particular
optimization.

diff --git a/include/sys/socketcalls.h b/include/sys/socketcalls.h
new file mode 100644
index 0000000..dac9f9a
--- /dev/null
+++ b/include/sys/socketcalls.h
@@ -0,0 +1,28 @@
+/*
+ * sys/socketcalls.h
+ */
+
+#ifndef _SYS_SOCKETCALLS_H
+#define _SYS_SOCKETCALLS_H
+
+/* socketcalls by number, since <linux/net.h> isn't usable for assembly */
+
+#define SYS_SOCKET      1               /* sys_socket(2)                */
+#define SYS_BIND        2               /* sys_bind(2)                  */
+#define SYS_CONNECT     3               /* sys_connect(2)               */
+#define SYS_LISTEN      4               /* sys_listen(2)                */
+#define SYS_ACCEPT      5               /* sys_accept(2)                */
+#define SYS_GETSOCKNAME 6               /* sys_getsockname(2)           */
+#define SYS_GETPEERNAME 7               /* sys_getpeername(2)           */
+#define SYS_SOCKETPAIR  8               /* sys_socketpair(2)            */
+#define SYS_SEND        9               /* sys_send(2)                  */
+#define SYS_RECV        10              /* sys_recv(2)                  */
+#define SYS_SENDTO      11              /* sys_sendto(2)                */
+#define SYS_RECVFROM    12              /* sys_recvfrom(2)              */
+#define SYS_SHUTDOWN    13              /* sys_shutdown(2)              */
+#define SYS_SETSOCKOPT  14              /* sys_setsockopt(2)            */
+#define SYS_GETSOCKOPT  15              /* sys_getsockopt(2)            */
+#define SYS_SENDMSG     16              /* sys_sendmsg(2)               */
+#define SYS_RECVMSG     17              /* sys_recvmsg(2)               */
+
+#endif /* _SYS_SOCKETCALLS_H */
diff --git a/klibc/MCONFIG b/klibc/MCONFIG
index 781e547..34d21f1 100644
--- a/klibc/MCONFIG
+++ b/klibc/MCONFIG
@@ -44,9 +44,15 @@
 .S.o:
 	$(CC) $(CFLAGS) -D__ASSEMBLY__ -c -o $@ $<
 
+.S.s:
+	$(CC) $(CFLAGS) -D__ASSEMBLY__ -E -o $@ $<
+
 .S.lo:
 	$(CC) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -c -o $@ $<
 
+.S.ls:
+	$(CC) $(CFLAGS) $(SOFLAGS) -D__ASSEMBLY__ -E -o $@ $<
+
 .s.o:
 	$(CC) $(CFLAGS) -x assembler -c -o $@ $<
 
diff --git a/klibc/Makefile b/klibc/Makefile
index 7579f58..9af3deb 100644
--- a/klibc/Makefile
+++ b/klibc/Makefile
@@ -29,6 +29,7 @@
 	  getenv.o setenv.o unsetenv.o getopt.o readdir.o \
 	  time.o fdatasync.o llseek.o select.o nice.o getpriority.o \
 	  qsort.o lrand48.o srand48.o seed48.o \
+	  socketcall.o \
 	  inet/inet_ntoa.o inet/inet_aton.o inet/inet_addr.o \
 	  inet/inet_ntop.o inet/inet_pton.o
 LIB     = libc.a
diff --git a/klibc/include/sys/socketcalls.h b/klibc/include/sys/socketcalls.h
new file mode 100644
index 0000000..dac9f9a
--- /dev/null
+++ b/klibc/include/sys/socketcalls.h
@@ -0,0 +1,28 @@
+/*
+ * sys/socketcalls.h
+ */
+
+#ifndef _SYS_SOCKETCALLS_H
+#define _SYS_SOCKETCALLS_H
+
+/* socketcalls by number, since <linux/net.h> isn't usable for assembly */
+
+#define SYS_SOCKET      1               /* sys_socket(2)                */
+#define SYS_BIND        2               /* sys_bind(2)                  */
+#define SYS_CONNECT     3               /* sys_connect(2)               */
+#define SYS_LISTEN      4               /* sys_listen(2)                */
+#define SYS_ACCEPT      5               /* sys_accept(2)                */
+#define SYS_GETSOCKNAME 6               /* sys_getsockname(2)           */
+#define SYS_GETPEERNAME 7               /* sys_getpeername(2)           */
+#define SYS_SOCKETPAIR  8               /* sys_socketpair(2)            */
+#define SYS_SEND        9               /* sys_send(2)                  */
+#define SYS_RECV        10              /* sys_recv(2)                  */
+#define SYS_SENDTO      11              /* sys_sendto(2)                */
+#define SYS_RECVFROM    12              /* sys_recvfrom(2)              */
+#define SYS_SHUTDOWN    13              /* sys_shutdown(2)              */
+#define SYS_SETSOCKOPT  14              /* sys_setsockopt(2)            */
+#define SYS_GETSOCKOPT  15              /* sys_getsockopt(2)            */
+#define SYS_SENDMSG     16              /* sys_sendmsg(2)               */
+#define SYS_RECVMSG     17              /* sys_recvmsg(2)               */
+
+#endif /* _SYS_SOCKETCALLS_H */
diff --git a/klibc/socketcall.S b/klibc/socketcall.S
new file mode 100644
index 0000000..6bac1e6
--- /dev/null
+++ b/klibc/socketcall.S
@@ -0,0 +1,38 @@
+#
+# socketcall.S
+#
+# On i386, the main (only?) user of socketcall(2), the memory array
+# socketcall(2) needs is conveniently already assembled for us on
+# the stack.  Capitalize on that to make a common socketcall stub.
+#
+
+#include <asm/unistd.h>
+
+#ifdef __i386__
+
+	.text
+	.align 4
+	.globl __socketcall_common
+	.type __socketcall_common, @function
+
+__socketcall_common:
+	pushl %ebx
+	movzbl %al,%ebx		# The socketcall number is passed in in %al
+	leal 8(%esp),%ecx	# Argument pointer
+	movl $__NR_socketcall, %eax
+	int $0x80
+	cmpl $-125,%eax		# Error return?
+	popl %ebx
+	jb 1f
+	neg %eax
+	movl %eax,errno
+	xorl %eax,%eax
+	decl %eax		# Return = -1
+1:
+	ret
+
+	.size __socketcall_common,.-__socketcall_common
+	
+#endif
+
+	
diff --git a/klibc/socketcalls.pl b/klibc/socketcalls.pl
index 34d1839..0820b98 100644
--- a/klibc/socketcalls.pl
+++ b/klibc/socketcalls.pl
@@ -1,4 +1,6 @@
 #!/usr/bin/perl
+($arch) = @ARGV;
+
 while ( defined($line = <STDIN>) ) {
     chomp $line;
     $line =~ s/\s*\#.*$//;	# Strip comments and trailing blanks
@@ -17,28 +19,44 @@
 	}
 	$nargs = $i;
 
-	open(OUT, "> socketcalls/${name}.c")
-	    or die "$0: Cannot open socketcalls/${name}.c\n";
-	print OUT "#include \"socketcommon.h\"\n\n";
+	if ( $arch eq 'i386' ) {
+	    open(OUT, "> socketcalls/${name}.S")
+		or die "$0: Cannot open socketcalls/${name}.S\n";
 
-	print OUT "#ifdef __NR_$name\n\n";
-	print OUT "_syscall", scalar(@args), "(", $type, ',', $name;
-	$i = 0;
-	foreach $arg ( @args ) {
-	    print OUT ",", $arg, ",a",$i++;
+	    print OUT "#include <sys/socketcalls.h>\n";
+	    print OUT "\n";
+	    print OUT "\t.text\n";
+	    print OUT "\t.align 4\n";
+	    print OUT "\t.globl ${name}\n";
+	    print OUT "\t.type ${name},\@function\n";
+	    print OUT "${name}:\n";
+	    print OUT "\tmovb \$SYS_\U${name}\E,%al\n";
+	    print OUT "\tjmp __socketcall_common\n";
+	    print OUT "\t.size ${name},.-${name}\n";
+	} else {
+	    open(OUT, "> socketcalls/${name}.c")
+		or die "$0: Cannot open socketcalls/${name}.c\n";
+	    print OUT "#include \"socketcommon.h\"\n\n";
+	    
+	    print OUT "#ifdef __NR_$name\n\n";
+	    print OUT "_syscall", scalar(@args), "(", $type, ',', $name;
+	    $i = 0;
+	    foreach $arg ( @args ) {
+		print OUT ",", $arg, ",a",$i++;
+	    }
+	    print OUT ");\n";
+	    print OUT "\n#else\n\n";
+	    
+	    print OUT "$type $name (", join(', ', @cargs), ")\n";
+	    print OUT "{\n";
+	    print OUT "    unsigned long args[$nargs];\n";
+	    for ( $i = 0 ; $i < $nargs ; $i++ ) {
+		print OUT "    args[$i] = (unsigned long)a$i;\n";
+	    }
+	    print OUT "    return ($type) socketcall(SYS_\U${name}\E, args);\n";
+	    print OUT "}\n";
+	    print OUT "\n#endif\n";
 	}
-	print OUT ");\n";
-	print OUT "\n#else\n\n";
-
-	print OUT "$type $name (", join(', ', @cargs), ")\n";
-	print OUT "{\n";
-	print OUT "    unsigned long args[$nargs];\n";
-	for ( $i = 0 ; $i < $nargs ; $i++ ) {
-	    print OUT "    args[$i] = (unsigned long)a$i;\n";
-	}
-	print OUT "    return ($type) socketcall(SYS_\U${name}\E, args);\n";
-	print OUT "}\n";
-	print OUT "\n#endif\n";
 	close(OUT);
     }
 }
diff --git a/socketcall.S b/socketcall.S
new file mode 100644
index 0000000..6bac1e6
--- /dev/null
+++ b/socketcall.S
@@ -0,0 +1,38 @@
+#
+# socketcall.S
+#
+# On i386, the main (only?) user of socketcall(2), the memory array
+# socketcall(2) needs is conveniently already assembled for us on
+# the stack.  Capitalize on that to make a common socketcall stub.
+#
+
+#include <asm/unistd.h>
+
+#ifdef __i386__
+
+	.text
+	.align 4
+	.globl __socketcall_common
+	.type __socketcall_common, @function
+
+__socketcall_common:
+	pushl %ebx
+	movzbl %al,%ebx		# The socketcall number is passed in in %al
+	leal 8(%esp),%ecx	# Argument pointer
+	movl $__NR_socketcall, %eax
+	int $0x80
+	cmpl $-125,%eax		# Error return?
+	popl %ebx
+	jb 1f
+	neg %eax
+	movl %eax,errno
+	xorl %eax,%eax
+	decl %eax		# Return = -1
+1:
+	ret
+
+	.size __socketcall_common,.-__socketcall_common
+	
+#endif
+
+	
diff --git a/socketcalls.pl b/socketcalls.pl
index 34d1839..0820b98 100644
--- a/socketcalls.pl
+++ b/socketcalls.pl
@@ -1,4 +1,6 @@
 #!/usr/bin/perl
+($arch) = @ARGV;
+
 while ( defined($line = <STDIN>) ) {
     chomp $line;
     $line =~ s/\s*\#.*$//;	# Strip comments and trailing blanks
@@ -17,28 +19,44 @@
 	}
 	$nargs = $i;
 
-	open(OUT, "> socketcalls/${name}.c")
-	    or die "$0: Cannot open socketcalls/${name}.c\n";
-	print OUT "#include \"socketcommon.h\"\n\n";
+	if ( $arch eq 'i386' ) {
+	    open(OUT, "> socketcalls/${name}.S")
+		or die "$0: Cannot open socketcalls/${name}.S\n";
 
-	print OUT "#ifdef __NR_$name\n\n";
-	print OUT "_syscall", scalar(@args), "(", $type, ',', $name;
-	$i = 0;
-	foreach $arg ( @args ) {
-	    print OUT ",", $arg, ",a",$i++;
+	    print OUT "#include <sys/socketcalls.h>\n";
+	    print OUT "\n";
+	    print OUT "\t.text\n";
+	    print OUT "\t.align 4\n";
+	    print OUT "\t.globl ${name}\n";
+	    print OUT "\t.type ${name},\@function\n";
+	    print OUT "${name}:\n";
+	    print OUT "\tmovb \$SYS_\U${name}\E,%al\n";
+	    print OUT "\tjmp __socketcall_common\n";
+	    print OUT "\t.size ${name},.-${name}\n";
+	} else {
+	    open(OUT, "> socketcalls/${name}.c")
+		or die "$0: Cannot open socketcalls/${name}.c\n";
+	    print OUT "#include \"socketcommon.h\"\n\n";
+	    
+	    print OUT "#ifdef __NR_$name\n\n";
+	    print OUT "_syscall", scalar(@args), "(", $type, ',', $name;
+	    $i = 0;
+	    foreach $arg ( @args ) {
+		print OUT ",", $arg, ",a",$i++;
+	    }
+	    print OUT ");\n";
+	    print OUT "\n#else\n\n";
+	    
+	    print OUT "$type $name (", join(', ', @cargs), ")\n";
+	    print OUT "{\n";
+	    print OUT "    unsigned long args[$nargs];\n";
+	    for ( $i = 0 ; $i < $nargs ; $i++ ) {
+		print OUT "    args[$i] = (unsigned long)a$i;\n";
+	    }
+	    print OUT "    return ($type) socketcall(SYS_\U${name}\E, args);\n";
+	    print OUT "}\n";
+	    print OUT "\n#endif\n";
 	}
-	print OUT ");\n";
-	print OUT "\n#else\n\n";
-
-	print OUT "$type $name (", join(', ', @cargs), ")\n";
-	print OUT "{\n";
-	print OUT "    unsigned long args[$nargs];\n";
-	for ( $i = 0 ; $i < $nargs ; $i++ ) {
-	    print OUT "    args[$i] = (unsigned long)a$i;\n";
-	}
-	print OUT "    return ($type) socketcall(SYS_\U${name}\E, args);\n";
-	print OUT "}\n";
-	print OUT "\n#endif\n";
 	close(OUT);
     }
 }