summaryrefslogtreecommitdiffstats
path: root/libc/arch-x86/string
diff options
context:
space:
mode:
Diffstat (limited to 'libc/arch-x86/string')
-rw-r--r--libc/arch-x86/string/bcmp.S32
-rw-r--r--libc/arch-x86/string/bcopy.S93
-rw-r--r--libc/arch-x86/string/bzero.S43
-rw-r--r--libc/arch-x86/string/fss.S17
-rw-r--r--libc/arch-x86/string/index.S26
-rw-r--r--libc/arch-x86/string/memchr.S26
-rw-r--r--libc/arch-x86/string/memcmp.S43
-rw-r--r--libc/arch-x86/string/memcpy.S3
-rw-r--r--libc/arch-x86/string/memmove.S3
-rw-r--r--libc/arch-x86/string/memset.S55
-rw-r--r--libc/arch-x86/string/rindex.S29
-rw-r--r--libc/arch-x86/string/strcat.S73
-rw-r--r--libc/arch-x86/string/strchr.S3
-rw-r--r--libc/arch-x86/string/strcmp.S81
-rw-r--r--libc/arch-x86/string/strcpy.S63
-rw-r--r--libc/arch-x86/string/strlen.S20
-rw-r--r--libc/arch-x86/string/strncmp.S113
-rw-r--r--libc/arch-x86/string/strrchr.S3
-rw-r--r--libc/arch-x86/string/swab.S67
19 files changed, 793 insertions, 0 deletions
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