View of xos/usr/lib/libc/string.c


XOS | Parent Directory | View | Download

/* Copyright (C) 2008  Emmanuel Varoquaux
 
   This file is part of XOS.
 
   This program is free software: you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation, either version 3 of the License, or
   (at your option) any later version.
 
   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.
 
   You should have received a copy of the GNU General Public License
   along with this program.  If not, see <http://www.gnu.org/licenses/>. */
 
#include <string.h>
 
#include <stdlib.h> /* malloc() */
#include <stdio.h> /* sprintf() */
#include <signal.h>
#include <errno.h>
 
char __attribute__ ((weak, visibility ("default"))) *strcat(char *dest, const char *src)
{
  int d0, d1, d2, d3;
 
  asm volatile ("cld\n\t"
                "repne\n\t"
                "scasb\n\t"
                "decl %1\n"
                "1:\tlodsb\n\t"
                "stosb\n\t"
                "testb %%al, %%al\n\t"
                "jne 1b"
                : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
                : "0" (src), "1" (dest), "2" (0), "3" (0xffffffff)
                : "cc", "memory");
  return dest;
}
 
char __attribute__ ((weak, visibility ("default"))) *strchr(const char *s, int c)
{
  int d0;
  register char *res;
 
  asm ("cld\n\t"
       "movb %%al, %%ah\n"
       "1:\tlodsb\n\t"
       "cmpb %%ah, %%al\n\t"
       "je 2f\n\t"
       "testb %%al, %%al\n\t"
       "jne 1b\n\t"
       "movl $1, %1\n"
       "2:\tmovl %1, %0\n\t"
       "decl %0"
       : "=a" (res), "=&S" (d0)
       : "1" (s), "0" (c)
       : "cc");
  return res;
}
 
int __attribute__ ((weak, visibility ("default"))) strcmp(const char *s1, const char *s2)
{
  int d0, d1;
  register int res;
 
  asm ("cld\n"
       "1:\tlodsb\n\t"
       "scasb\n\t"
       "jne 2f\n\t"
       "testb %%al, %%al\n\t"
       "jne 1b\n\t"
       "xorl %%eax, %%eax\n\t"
       "jmp 3f\n"
       "2:\tsbbl %%eax, %%eax\n\t"
       "orb $1, %%al\n"
       "3:"
       : "=a" (res), "=&S" (d0), "=&D" (d1)
       : "1" (s1), "2" (s2)
       : "cc");
  return res;
}
 
char __attribute__ ((weak, visibility ("default"))) *strcpy(char *dest, const char *src)
{
  int d0, d1, d2;
 
  asm volatile ("cld\n"
                "1:\tlodsb\n\t"
                "stosb\n\t"
                "testb %%al, %%al\n\t"
                "jne 1b"
                : "=&S" (d0), "=&D" (d1), "=&a" (d2)
                : "0" (src), "1" (dest)
                : "cc", "memory");
  return dest;
}
 
size_t __attribute__ ((weak, visibility ("default"))) strlen(const char *s)
{
  int d0;
  register int res;
 
  asm ("cld\n\t"
       "repne\n\t"
       "scasb\n\t"
       "notl %0\n\t"
       "decl %0"
       : "=c" (res), "=&D" (d0)
       : "1" (s), "a" (0), "0" (0xffffffff)
       : "cc");
  return res;
}
 
size_t __attribute__ ((weak, visibility ("default"))) strnlen(const char *s, size_t n)
{
  int d0, d1, d2;
  register unsigned int res;
 
  asm ("cld\n"
       "1:\tdecl %5\n\t"
       "js 2f\n\t"
       "scasb\n\t"
       "je 2f\n\t"
       "incl %6\n\t"
       "jmp 1b\n\t"
       "2:"
       : "=q" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
       : "2" (s), "1" (n), "0" (0), "3" (0)
       : "cc");
  return res;
}
 
char __attribute__ ((weak, visibility ("default"))) *strncat(char *dest, const char *src, size_t n)
{
  int d0, d1, d2, d3;
 
  asm volatile ("cld\n\t"
                "repne\n\t"
                "scasb\n\t"
                "decl %1\n\t"
                "movl %8, %3\n"
                "1:\tdecl %3\n\t"
                "js 2f\n\t"
                "lodsb\n\t"
                "stosb\n\t"
                "testb %%al, %%al\n\t"
                "jne 1b\n"
                "2:\txorl %2, %2\n\t"
                "stosb"
                : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
                : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu), "g" (n)
                : "cc", "memory");
  return dest;
}
 
int __attribute__ ((weak, visibility ("default"))) strncmp(const char *s1, const char *s2, size_t n)
{
  int d0, d1, d2;
  register int res;
 
  asm ("cld\n"
       "1:\tdecl %3\n\t"
       "js 2f\n\t"
       "lodsb\n\t"
       "scasb\n\t"
       "jne 3f\n\t"
       "testb %%al, %%al\n\t"
       "jne 1b\n"
       "2:\txorl %%eax, %%eax\n\t"
       "jmp 4f\n"
       "3:\tsbbl %%eax, %%eax\n\t"
       "orb $1, %%al\n"
       "4:"
       : "=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
       : "1" (s2), "2" (s1), "3" (n)
       : "cc");
  return res;
}
 
char __attribute__ ((weak, visibility ("default"))) *strncpy(char *dest, const char *src, size_t n)
{
  int d0, d1, d2, d3;
 
  asm volatile ("cld\n"
                "1:\tdecl %2\n\t"
                "js 2f\n\t"
                "lodsb\n\t"
                "stosb\n\t"
                "testb %%al, %%al\n\t"
                "jne 1b\n\t"
                "rep\n\t"
                "stosb\n"
                "2:"
                : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
                : "0" (src), "1" (dest), "2" (n)
                : "cc", "memory");
  return dest;
}
 
char __attribute__ ((weak, visibility ("default"))) *strrchr(const char *s, int c)
{
  int d0, d1;
  register char *res;
 
  asm ("cld\n\t"
       "movb %%al, %%ah\n"
       "1:\tlodsb\n\t"
       "cmpb %%ah, %%al\n\t"
       "jne 2f\n\t"
       "leal -1(%%esi), %0\n"
       "2:\ttestb %%al, %%al\n\t"
       "jne 1b"
       : "=g" (res), "=&S" (d0), "=&a" (d1)
       : "0" (0), "1" (s), "2" (c)
       : "cc");
  return res;
}
 
void __attribute__ ((weak, visibility ("default"))) *memcpy(void *dest, const void *src, size_t n)
{
  int d0, d1, d2;
 
  asm volatile ("cld\n\t"
                "rep\n\t"
                "movsl\n\t"
                "testb $2, %b4\n\t"
                "je 1f\n\t"
                "movsw\n"
                "1:\ttestb $1, %b4\n\t"
                "je 2f\n\t"
                "movsb\n"
                "2:"
                : "=&c" (d0), "=&D" (d1), "=&S" (d2)
                : "0" (n / 4), "q" (n), "1" (dest), "2" (src)
                : "cc", "memory");
  return dest;
}
 
void __attribute__ ((weak, visibility ("default"))) *memmove(void *dest, const void *src, size_t n)
{
  int d0, d1, d2;
 
  if (dest < src)
    asm volatile ("cld\n\t"
                  "rep\n\t"
                  "movsb\n\t"
                  : "=&c" (d0), "=&D" (d1), "=&S" (d2)
                  : "0" (n), "1" (dest), "2" (src)
                  : "cc", "memory");
  else
    asm volatile ("std\n\t"
                  "rep\n\t"
                  "movsb\n\t"
                  : "=&c" (d0), "=&D" (d1), "=&S" (d2)
                  : "0" (n), "1" (dest + n - 1), "2" (src + n - 1)
                  : "cc", "memory");
  return dest;
}
 
int __attribute__ ((weak, visibility ("default"))) memcmp(const void *s1, const void *s2, size_t n)
{
  int d0, d1, d2;
  register int res;
 
  asm ("cld\n\t"
       "repe\n\t"
       "cmpsb\n\t"
       "je 1f\n\t"
       "movl $1, %%eax\n\t"
       "jl 1f\n\t"
       "negl %%eax\n"
       "1:"
       : "=a" (res), "=&c" (d0), "=&D" (d1), "=&S" (d2)
       : "0" (0), "1" (n), "2" (s1), "3" (s2)
       : "cc");
  return res;
}
 
void __attribute__ ((weak, visibility ("default"))) *memchr(const void *s, int c, size_t n)
{
  int d0;
  register void *res;
 
  asm ("cld\n\t"
       "repne\n\t"
       "scasb\n\t"
       "je 1f\n\t"
       "movl $1, %0\n"
       "1:\tdecl %0"
       : "=D" (res), "=&c" (d0)
       : "a" (c), "1" (n), "0" (s)
       : "cc");
  return res;
}
 
void __attribute__ ((weak, visibility ("default"))) *memset(void *s, int c, size_t n)
{
  int d0, d1;
 
  asm volatile ("cld\n\t"
                "rep\n\t"
                "stosb"
                : "=&c" (d0), "=&D" (d1)
                : "a" (c), "1" (s), "0" (n)
                : "cc", "memory");
  return s;
}
 
char __attribute__ ((weak, visibility ("default"))) *strerror(int errnum)
{
  static char str[64];
 
  if (errnum < 0 || errnum >= sys_nerr || !sys_errlist[errnum])
    sprintf(str, "Unknown error %d", errnum);
  else
    strcpy(str, sys_errlist[errnum]);
  return str;
}
 
char __attribute__ ((weak, visibility ("default"))) *strdup(const char *s)
{
  char *d;
 
  if (!(d = malloc(strlen(s) + 1)))
    return NULL;
  strcpy(d, s);
  return d;
}
 
char __attribute__ ((weak, visibility ("default"))) *strsignal(int sig)
{
  static char str[64];
 
  if (sig < 0 || sig >= sys_nsig || !sys_siglist[sig])
    sprintf(str, "Unknown signal %d", sig);
  else
    strcpy(str, sys_siglist[sig]);
  return str;
}