Initial Contribution
diff --git a/libc/arch-x86/string/bcmp.S b/libc/arch-x86/string/bcmp.S
new file mode 100644
index 0000000..a5b46ae
--- /dev/null
+++ b/libc/arch-x86/string/bcmp.S
@@ -0,0 +1,32 @@
+/*	$OpenBSD: bcmp.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+ENTRY(bcmp)
+	pushl	%edi
+	pushl	%esi
+	movl	12(%esp),%edi
+	movl	16(%esp),%esi
+	xorl	%eax,%eax		/* clear return value */
+	cld				/* set compare direction forward */
+
+	movl	20(%esp),%ecx		/* compare by words */
+	shrl	$2,%ecx
+	repe
+	cmpsl
+	jne	L1
+
+	movl	20(%esp),%ecx		/* compare remainder by bytes */
+	andl	$3,%ecx
+	repe
+	cmpsb
+	je	L2
+
+L1:	incl	%eax
+L2:	popl	%esi
+	popl	%edi
+	ret
diff --git a/libc/arch-x86/string/bcopy.S b/libc/arch-x86/string/bcopy.S
new file mode 100644
index 0000000..dde5ae1
--- /dev/null
+++ b/libc/arch-x86/string/bcopy.S
@@ -0,0 +1,93 @@
+/*	$OpenBSD: bcopy.S,v 1.5 2005/08/07 11:30:38 espie Exp $	*/
+
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from locore.s.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <machine/asm.h>
+
+	/*
+	 * (ov)bcopy (src,dst,cnt)
+	 *  ws@tools.de     (Wolfgang Solfrank, TooLs GmbH) +49-228-985800
+	 */
+
+#ifdef MEMCOPY
+ENTRY(memcpy)
+#else
+#ifdef MEMMOVE
+ENTRY(memmove)
+#else
+ENTRY(bcopy)
+#endif
+#endif
+	pushl	%esi
+	pushl	%edi
+#if defined(MEMCOPY) || defined(MEMMOVE)
+	movl	12(%esp),%edi
+	movl	16(%esp),%esi
+	movl	%edi, %eax
+#else
+	movl	12(%esp),%esi
+	movl	16(%esp),%edi
+#endif
+	movl	20(%esp),%ecx
+	movl	%ecx,%edx
+	cmpl	%esi,%edi	/* potentially overlapping? */
+	jnb	1f
+	cld			/* nope, copy forwards. */
+	shrl	$2,%ecx		/* copy by words */
+	rep
+	movsl
+	movl	%edx,%ecx
+	andl	$3,%ecx		/* any bytes left? */
+	rep
+	movsb
+	popl	%edi
+	popl	%esi
+	ret
+1:
+	addl	%ecx,%edi	/* copy backwards. */
+	addl	%ecx,%esi
+	std
+	andl	$3,%ecx		/* any fractional bytes? */
+	decl	%edi
+	decl	%esi
+	rep
+	movsb
+	movl	%edx,%ecx
+	shrl	$2,%ecx
+	subl	$3,%esi
+	subl	$3,%edi
+	rep
+	movsl
+	popl	%edi
+	popl	%esi
+	cld
+	ret
diff --git a/libc/arch-x86/string/bzero.S b/libc/arch-x86/string/bzero.S
new file mode 100644
index 0000000..2ec9c7d
--- /dev/null
+++ b/libc/arch-x86/string/bzero.S
@@ -0,0 +1,43 @@
+/*	$OpenBSD: bzero.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+ENTRY(bzero)
+	pushl	%edi
+	movl	8(%esp),%edi
+	movl	12(%esp),%edx
+
+	cld				/* set fill direction forward */
+	xorl	%eax,%eax		/* set fill data to 0 */
+
+	/*
+	 * if the string is too short, it's really not worth the overhead
+	 * of aligning to word boundries, etc.  So we jump to a plain
+	 * unaligned set.
+	 */
+	cmpl	$16,%edx
+	jb	L1
+
+	movl	%edi,%ecx		/* compute misalignment */
+	negl	%ecx
+	andl	$3,%ecx
+	subl	%ecx,%edx
+	rep				/* zero until word aligned */
+	stosb
+
+	movl	%edx,%ecx		/* zero by words */
+	shrl	$2,%ecx
+	andl	$3,%edx
+	rep
+	stosl
+
+L1:	movl	%edx,%ecx		/* zero remainder by bytes */
+	rep
+	stosb
+
+	popl	%edi
+	ret
diff --git a/libc/arch-x86/string/fss.S b/libc/arch-x86/string/fss.S
new file mode 100644
index 0000000..96affab
--- /dev/null
+++ b/libc/arch-x86/string/fss.S
@@ -0,0 +1,17 @@
+/*	$OpenBSD: ffs.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+ENTRY(ffs)
+	bsfl	4(%esp),%eax
+	jz	L1	 		/* ZF is set if all bits are 0 */
+	incl	%eax			/* bits numbered from 1, not 0 */
+	ret
+
+	.align 2
+L1:	xorl	%eax,%eax		/* clear result */
+	ret
diff --git a/libc/arch-x86/string/index.S b/libc/arch-x86/string/index.S
new file mode 100644
index 0000000..7f83ef5
--- /dev/null
+++ b/libc/arch-x86/string/index.S
@@ -0,0 +1,26 @@
+/*	$OpenBSD: index.S,v 1.4 2005/08/07 11:30:38 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+#ifdef STRCHR
+ENTRY(strchr)
+#else
+ENTRY(index)
+#endif
+	movl	4(%esp),%eax
+	movb	8(%esp),%cl
+	.align 2,0x90
+L1:
+	movb	(%eax),%dl
+	cmpb	%dl,%cl			/* found char??? */
+	je 	L2
+	incl	%eax
+	testb	%dl,%dl			/* null terminator??? */
+	jnz	L1
+	xorl	%eax,%eax
+L2:
+	ret
diff --git a/libc/arch-x86/string/memchr.S b/libc/arch-x86/string/memchr.S
new file mode 100644
index 0000000..d6bcbe6
--- /dev/null
+++ b/libc/arch-x86/string/memchr.S
@@ -0,0 +1,26 @@
+/*	$OpenBSD: memchr.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+ENTRY(memchr)
+	pushl	%edi
+	movl	8(%esp),%edi		/* string address */
+	movl	12(%esp),%eax		/* set character to search for */
+	movl	16(%esp),%ecx		/* set length of search */
+	testl	%ecx,%ecx		/* test for len == 0 */
+	jz	L1
+	cld				/* set search forward */
+	repne				/* search! */
+	scasb
+	jne	L1			/* scan failed, return null */
+	leal	-1(%edi),%eax		/* adjust result of scan */
+	popl	%edi
+	ret
+	.align 2,0x90
+L1:	xorl	%eax,%eax
+	popl	%edi
+	ret
diff --git a/libc/arch-x86/string/memcmp.S b/libc/arch-x86/string/memcmp.S
new file mode 100644
index 0000000..1be189a
--- /dev/null
+++ b/libc/arch-x86/string/memcmp.S
@@ -0,0 +1,43 @@
+/*	$OpenBSD: memcmp.S,v 1.4 2005/08/07 11:30:38 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+ENTRY(memcmp)
+	pushl	%edi
+	pushl	%esi
+	movl	12(%esp),%edi
+	movl	16(%esp),%esi
+	cld				/* set compare direction forward */
+
+	movl	20(%esp),%ecx		/* compare by words */
+	shrl	$2,%ecx
+	repe
+	cmpsl
+	jne	L5			/* do we match so far? */
+
+	movl	20(%esp),%ecx		/* compare remainder by bytes */
+	andl	$3,%ecx
+	repe
+	cmpsb
+	jne	L6			/* do we match? */
+
+	xorl	%eax,%eax		/* we match, return zero	*/
+	popl	%esi
+	popl	%edi
+	ret
+
+L5:	movl	$4,%ecx			/* We know that one of the next	*/
+	subl	%ecx,%edi		/* four pairs of bytes do not	*/
+	subl	%ecx,%esi		/* match.			*/
+	repe
+	cmpsb
+L6:	movzbl  -1(%edi),%eax		/* Perform unsigned comparison	*/
+	movzbl	-1(%esi),%edx
+	subl	%edx,%eax
+	popl	%esi
+	popl	%edi
+	ret
diff --git a/libc/arch-x86/string/memcpy.S b/libc/arch-x86/string/memcpy.S
new file mode 100644
index 0000000..95c8a83
--- /dev/null
+++ b/libc/arch-x86/string/memcpy.S
@@ -0,0 +1,3 @@
+/*	$OpenBSD: memcpy.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
+#define MEMCOPY
+#include "bcopy.S"
diff --git a/libc/arch-x86/string/memmove.S b/libc/arch-x86/string/memmove.S
new file mode 100644
index 0000000..c5bfd19
--- /dev/null
+++ b/libc/arch-x86/string/memmove.S
@@ -0,0 +1,3 @@
+/*	$OpenBSD: memmove.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
+#define MEMMOVE
+#include "bcopy.S"
diff --git a/libc/arch-x86/string/memset.S b/libc/arch-x86/string/memset.S
new file mode 100644
index 0000000..1059ccc
--- /dev/null
+++ b/libc/arch-x86/string/memset.S
@@ -0,0 +1,55 @@
+/*	$OpenBSD: memset.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+ENTRY(memset)
+	pushl	%edi
+	pushl	%ebx
+	movl	12(%esp),%edi
+	movzbl	16(%esp),%eax		/* unsigned char, zero extend */
+	movl	20(%esp),%ecx
+	pushl	%edi			/* push address of buffer */
+
+	cld				/* set fill direction forward */
+
+	/*
+	 * if the string is too short, it's really not worth the overhead
+	 * of aligning to word boundries, etc.  So we jump to a plain
+	 * unaligned set.
+	 */
+	cmpl	$0x0f,%ecx
+	jle	L1
+
+	movb	%al,%ah			/* copy char to all bytes in word */
+	movl	%eax,%edx
+	sall	$16,%eax
+	orl	%edx,%eax
+
+	movl	%edi,%edx		/* compute misalignment */
+	negl	%edx
+	andl	$3,%edx
+	movl	%ecx,%ebx
+	subl	%edx,%ebx
+
+	movl	%edx,%ecx		/* set until word aligned */
+	rep
+	stosb
+
+	movl	%ebx,%ecx
+	shrl	$2,%ecx			/* set by words */
+	rep
+	stosl
+
+	movl	%ebx,%ecx		/* set remainder by bytes */
+	andl	$3,%ecx
+L1:	rep
+	stosb
+
+	popl	%eax			/* pop address of buffer */
+	popl	%ebx
+	popl	%edi
+	ret
diff --git a/libc/arch-x86/string/rindex.S b/libc/arch-x86/string/rindex.S
new file mode 100644
index 0000000..0260d38
--- /dev/null
+++ b/libc/arch-x86/string/rindex.S
@@ -0,0 +1,29 @@
+/*	$OpenBSD: rindex.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+#ifdef STRRCHR
+ENTRY(strrchr)
+#else
+ENTRY(rindex)
+#endif
+	pushl	%ebx
+	movl	8(%esp),%edx
+	movb	12(%esp),%cl
+	xorl	%eax,%eax		/* init pointer to null */
+	.align 2,0x90
+L1:
+	movb	(%edx),%bl
+	cmpb	%bl,%cl
+	jne	L2
+	movl	%edx,%eax
+L2:
+	incl	%edx
+	testb	%bl,%bl			/* null terminator??? */
+	jnz	L1
+	popl	%ebx
+	ret
diff --git a/libc/arch-x86/string/strcat.S b/libc/arch-x86/string/strcat.S
new file mode 100644
index 0000000..60fdd55
--- /dev/null
+++ b/libc/arch-x86/string/strcat.S
@@ -0,0 +1,73 @@
+/*	$OpenBSD: strcat.S,v 1.8 2005/08/07 11:30:38 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+#if defined(APIWARN)
+#APP
+	.section .gnu.warning.strcat
+	.ascii "warning: strcat() is almost always misused, please use strlcat()"
+#NO_APP
+#endif
+
+/*
+ * NOTE: I've unrolled the loop eight times: large enough to make a
+ * significant difference, and small enough not to totally trash the
+ * cache.
+ */
+
+ENTRY(strcat)
+	pushl	%edi			/* save edi */
+	movl	8(%esp),%edi		/* dst address */
+	movl	12(%esp),%edx		/* src address */
+	pushl	%edi			/* push destination address */
+
+	cld				/* set search forward */
+	xorl	%eax,%eax		/* set search for null terminator */
+	movl	$-1,%ecx		/* set search for lots of characters */
+	repne				/* search! */
+	scasb
+
+	leal	-1(%edi),%ecx		/* correct dst address */
+
+	.align 2,0x90
+L1:	movb	(%edx),%al		/* unroll loop, but not too much */
+	movb	%al,(%ecx)
+	testb	%al,%al
+	jz	L2
+	movb	1(%edx),%al
+	movb	%al,1(%ecx)
+	testb	%al,%al
+	jz	L2
+	movb	2(%edx),%al
+	movb	%al,2(%ecx)
+	testb	%al,%al
+	jz	L2
+	movb	3(%edx),%al
+	movb	%al,3(%ecx)
+	testb	%al,%al
+	jz	L2
+	movb	4(%edx),%al
+	movb	%al,4(%ecx)
+	testb	%al,%al
+	jz	L2
+	movb	5(%edx),%al
+	movb	%al,5(%ecx)
+	testb	%al,%al
+	jz	L2
+	movb	6(%edx),%al
+	movb	%al,6(%ecx)
+	testb	%al,%al
+	jz	L2
+	movb	7(%edx),%al
+	movb	%al,7(%ecx)
+	addl	$8,%edx
+	addl	$8,%ecx
+	testb	%al,%al
+	jnz	L1
+L2:	popl	%eax			/* pop destination address */
+	popl	%edi			/* restore edi */
+	ret
diff --git a/libc/arch-x86/string/strchr.S b/libc/arch-x86/string/strchr.S
new file mode 100644
index 0000000..f76e593
--- /dev/null
+++ b/libc/arch-x86/string/strchr.S
@@ -0,0 +1,3 @@
+/*	$OpenBSD: strchr.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
+#define STRCHR
+#include "index.S"
diff --git a/libc/arch-x86/string/strcmp.S b/libc/arch-x86/string/strcmp.S
new file mode 100644
index 0000000..22ba546
--- /dev/null
+++ b/libc/arch-x86/string/strcmp.S
@@ -0,0 +1,81 @@
+/*	$OpenBSD: strcmp.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+/*
+ * NOTE: I've unrolled the loop eight times: large enough to make a
+ * significant difference, and small enough not to totally trash the
+ * cache.
+ */
+
+ENTRY(strcmp)
+	movl	0x04(%esp),%eax
+	movl	0x08(%esp),%edx
+	jmp	L2			/* Jump into the loop! */
+
+	.align	2,0x90
+L1:	incl	%eax
+	incl	%edx
+L2:	movb	(%eax),%cl
+	testb	%cl,%cl			/* null terminator??? */
+	jz	L3
+	cmpb	%cl,(%edx)		/* chars match??? */
+	jne	L3
+	incl	%eax
+	incl	%edx
+	movb	(%eax),%cl
+	testb	%cl,%cl
+	jz	L3
+	cmpb	%cl,(%edx)
+	jne	L3
+	incl	%eax
+	incl	%edx
+	movb	(%eax),%cl
+	testb	%cl,%cl
+	jz	L3
+	cmpb	%cl,(%edx)
+	jne	L3
+	incl	%eax
+	incl	%edx
+	movb	(%eax),%cl
+	testb	%cl,%cl
+	jz	L3
+	cmpb	%cl,(%edx)
+	jne	L3
+	incl	%eax
+	incl	%edx
+	movb	(%eax),%cl
+	testb	%cl,%cl
+	jz	L3
+	cmpb	%cl,(%edx)
+	jne	L3
+	incl	%eax
+	incl	%edx
+	movb	(%eax),%cl
+	testb	%cl,%cl
+	jz	L3
+	cmpb	%cl,(%edx)
+	jne	L3
+	incl	%eax
+	incl	%edx
+	movb	(%eax),%cl
+	testb	%cl,%cl
+	jz	L3
+	cmpb	%cl,(%edx)
+	jne	L3
+	incl	%eax
+	incl	%edx
+	movb	(%eax),%cl
+	testb	%cl,%cl
+	jz	L3
+	cmpb	%cl,(%edx)
+	je	L1
+	.align 2, 0x90
+L3:	movzbl	(%eax),%eax		/* unsigned comparison */
+	movzbl	(%edx),%edx
+	subl	%edx,%eax
+	ret
diff --git a/libc/arch-x86/string/strcpy.S b/libc/arch-x86/string/strcpy.S
new file mode 100644
index 0000000..341eb6c
--- /dev/null
+++ b/libc/arch-x86/string/strcpy.S
@@ -0,0 +1,63 @@
+/*	$OpenBSD: strcpy.S,v 1.8 2005/08/07 11:30:38 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+#if defined(APIWARN)
+#APP
+	.section .gnu.warning.strcpy
+	.ascii "warning: strcpy() is almost always misused, please use strlcpy()"
+#NO_APP
+#endif
+
+/*
+ * NOTE: I've unrolled the loop eight times: large enough to make a
+ * significant difference, and small enough not to totally trash the
+ * cache.
+ */
+
+ENTRY(strcpy)
+	movl	4(%esp),%ecx		/* dst address */
+	movl	8(%esp),%edx		/* src address */
+	pushl	%ecx			/* push dst address */
+
+	.align 2,0x90
+L1:	movb	(%edx),%al		/* unroll loop, but not too much */
+	movb	%al,(%ecx)
+	testb	%al,%al
+	jz	L2
+	movb	1(%edx),%al
+	movb	%al,1(%ecx)
+	testb	%al,%al
+	jz	L2
+	movb	2(%edx),%al
+	movb	%al,2(%ecx)
+	testb	%al,%al
+	jz	L2
+	movb	3(%edx),%al
+	movb	%al,3(%ecx)
+	testb	%al,%al
+	jz	L2
+	movb	4(%edx),%al
+	movb	%al,4(%ecx)
+	testb	%al,%al
+	jz	L2
+	movb	5(%edx),%al
+	movb	%al,5(%ecx)
+	testb	%al,%al
+	jz	L2
+	movb	6(%edx),%al
+	movb	%al,6(%ecx)
+	testb	%al,%al
+	jz	L2
+	movb	7(%edx),%al
+	movb	%al,7(%ecx)
+	addl	$8,%edx
+	addl	$8,%ecx
+	testb	%al,%al
+	jnz	L1
+L2:	popl	%eax			/* pop dst address */
+	ret
diff --git a/libc/arch-x86/string/strlen.S b/libc/arch-x86/string/strlen.S
new file mode 100644
index 0000000..4f04ffc
--- /dev/null
+++ b/libc/arch-x86/string/strlen.S
@@ -0,0 +1,20 @@
+/*	$OpenBSD: strlen.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+ENTRY(strlen)
+	pushl	%edi
+	movl	8(%esp),%edi		/* string address */
+	cld				/* set search forward */
+	xorl	%eax,%eax		/* set search for null terminator */
+	movl	$-1,%ecx		/* set search for lots of characters */
+	repne				/* search! */
+	scasb
+	notl	%ecx			/* get length by taking	complement */
+	leal	-1(%ecx),%eax		/* and subtracting one */
+	popl	%edi
+	ret
diff --git a/libc/arch-x86/string/strncmp.S b/libc/arch-x86/string/strncmp.S
new file mode 100644
index 0000000..5aa88d7
--- /dev/null
+++ b/libc/arch-x86/string/strncmp.S
@@ -0,0 +1,113 @@
+/*	$OpenBSD: strncmp.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+/*
+ * NOTE: I've unrolled the loop eight times: large enough to make a
+ * significant difference, and small enough not to totally trash the
+ * cache.
+ */
+
+ENTRY(strncmp)
+	pushl	%ebx
+	movl	8(%esp),%eax
+	movl	12(%esp),%ecx
+	movl	16(%esp),%edx
+	testl	%edx,%edx
+	jmp	L2			/* Jump into the loop! */
+
+	.align 2,0x90
+L1:	incl	%eax
+	incl	%ecx
+	decl	%edx
+L2:	jz	L4			/* strings are equal */
+	movb	(%eax),%bl
+	testb	%bl,%bl
+	jz	L3
+	cmpb	%bl,(%ecx)
+	jne	L3
+
+	incl	%eax
+	incl	%ecx
+	decl	%edx
+	jz	L4
+	movb	(%eax),%bl
+	testb	%bl,%bl
+	jz	L3
+	cmpb	%bl,(%ecx)
+	jne	L3
+
+	incl	%eax
+	incl	%ecx
+	decl	%edx
+	jz	L4
+	movb	(%eax),%bl
+	testb	%bl,%bl
+	jz	L3
+	cmpb	%bl,(%ecx)
+	jne	L3
+
+	incl	%eax
+	incl	%ecx
+	decl	%edx
+	jz	L4
+	movb	(%eax),%bl
+	testb	%bl,%bl
+	jz	L3
+	cmpb	%bl,(%ecx)
+	jne	L3
+
+	incl	%eax
+	incl	%ecx
+	decl	%edx
+	jz	L4
+	movb	(%eax),%bl
+	testb	%bl,%bl
+	jz	L3
+	cmpb	%bl,(%ecx)
+	jne	L3
+
+	incl	%eax
+	incl	%ecx
+	decl	%edx
+	jz	L4
+	movb	(%eax),%bl
+	testb	%bl,%bl
+	jz	L3
+	cmpb	%bl,(%ecx)
+	jne	L3
+
+	incl	%eax
+	incl	%ecx
+	decl	%edx
+	jz	L4
+	movb	(%eax),%bl
+	testb	%bl,%bl
+	jz	L3
+	cmpb	%bl,(%ecx)
+	jne	L3
+
+	incl	%eax
+	incl	%ecx
+	decl	%edx
+	jz	L4
+	movb	(%eax),%bl
+	testb	%bl,%bl
+	jz	L3
+	cmpb	%bl,(%ecx)
+	je	L1
+
+	.align 2,0x90
+L3:	movzbl	(%eax),%eax		/* unsigned comparision */
+	movzbl	(%ecx),%ecx
+	subl	%ecx,%eax
+	popl	%ebx
+	ret
+	.align 2,0x90
+L4:	xorl	%eax,%eax
+	popl	%ebx
+	ret
diff --git a/libc/arch-x86/string/strrchr.S b/libc/arch-x86/string/strrchr.S
new file mode 100644
index 0000000..4ee153f
--- /dev/null
+++ b/libc/arch-x86/string/strrchr.S
@@ -0,0 +1,3 @@
+/*	$OpenBSD: strrchr.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
+#define STRRCHR
+#include "rindex.S"
diff --git a/libc/arch-x86/string/swab.S b/libc/arch-x86/string/swab.S
new file mode 100644
index 0000000..3055860
--- /dev/null
+++ b/libc/arch-x86/string/swab.S
@@ -0,0 +1,67 @@
+/*	$OpenBSD: swab.S,v 1.3 2005/08/07 11:30:38 espie Exp $ */
+/*
+ * Written by J.T. Conklin <jtc@netbsd.org>.
+ * Public domain.
+ */
+
+#include <machine/asm.h>
+
+/*
+ * On the i486, this code is negligibly faster than the code generated
+ * by gcc at about half the size.  If my i386 databook is correct, it
+ * should be considerably faster than the gcc code on a i386.
+ */
+
+ENTRY(swab)
+	pushl	%esi
+	pushl	%edi
+	movl	12(%esp),%esi
+	movl	16(%esp),%edi
+	movl	20(%esp),%ecx
+
+	cld				# set direction forward
+
+	shrl	$1,%ecx
+	testl	$7,%ecx			# copy first group of 1 to 7 words
+	jz	L2			# while swaping alternate bytes.
+	.align	2,0x90
+L1:	lodsw
+	rorw	$8,%ax
+	stosw
+	decl	%ecx
+	testl	$7,%ecx
+	jnz	L1
+
+L2:	shrl	$3,%ecx			# copy remainder 8 words at a time
+	jz	L4			# while swapping alternate bytes.
+	.align	2,0x90
+L3:	lodsw
+	rorw	$8,%ax
+	stosw
+	lodsw
+	rorw	$8,%ax
+	stosw
+	lodsw
+	rorw	$8,%ax
+	stosw
+	lodsw
+	rorw	$8,%ax
+	stosw
+	lodsw
+	rorw	$8,%ax
+	stosw
+	lodsw
+	rorw	$8,%ax
+	stosw
+	lodsw
+	rorw	$8,%ax
+	stosw
+	lodsw
+	rorw	$8,%ax
+	stosw
+	decl	%ecx
+	jnz	L3
+
+L4:	popl	%edi
+	popl	%esi
+	ret