linux/arch/x86/lib/string_32.c
<<
>>
Prefs
   1/*
   2 * Most of the string-functions are rather heavily hand-optimized,
   3 * see especially strsep,strstr,str[c]spn. They should work, but are not
   4 * very easy to understand. Everything is done entirely within the register
   5 * set, making the functions fast and clean. String instructions have been
   6 * used through-out, making for "slightly" unclear code :-)
   7 *
   8 * AK: On P4 and K7 using non string instruction implementations might be faster
   9 * for large memory blocks. But most of them are unlikely to be used on large
  10 * strings.
  11 */
  12
  13#include <linux/string.h>
  14#include <linux/module.h>
  15
  16#ifdef __HAVE_ARCH_STRCPY
  17char *strcpy(char *dest, const char *src)
  18{
  19        int d0, d1, d2;
  20        asm volatile("1:\tlodsb\n\t"
  21                "stosb\n\t"
  22                "testb %%al,%%al\n\t"
  23                "jne 1b"
  24                : "=&S" (d0), "=&D" (d1), "=&a" (d2)
  25                : "0" (src), "1" (dest) : "memory");
  26        return dest;
  27}
  28EXPORT_SYMBOL(strcpy);
  29#endif
  30
  31#ifdef __HAVE_ARCH_STRNCPY
  32char *strncpy(char *dest, const char *src, size_t count)
  33{
  34        int d0, d1, d2, d3;
  35        asm volatile("1:\tdecl %2\n\t"
  36                "js 2f\n\t"
  37                "lodsb\n\t"
  38                "stosb\n\t"
  39                "testb %%al,%%al\n\t"
  40                "jne 1b\n\t"
  41                "rep\n\t"
  42                "stosb\n"
  43                "2:"
  44                : "=&S" (d0), "=&D" (d1), "=&c" (d2), "=&a" (d3)
  45                : "0" (src), "1" (dest), "2" (count) : "memory");
  46        return dest;
  47}
  48EXPORT_SYMBOL(strncpy);
  49#endif
  50
  51#ifdef __HAVE_ARCH_STRCAT
  52char *strcat(char *dest, const char *src)
  53{
  54        int d0, d1, d2, d3;
  55        asm volatile("repne\n\t"
  56                "scasb\n\t"
  57                "decl %1\n"
  58                "1:\tlodsb\n\t"
  59                "stosb\n\t"
  60                "testb %%al,%%al\n\t"
  61                "jne 1b"
  62                : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
  63                : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu) : "memory");
  64        return dest;
  65}
  66EXPORT_SYMBOL(strcat);
  67#endif
  68
  69#ifdef __HAVE_ARCH_STRNCAT
  70char *strncat(char *dest, const char *src, size_t count)
  71{
  72        int d0, d1, d2, d3;
  73        asm volatile("repne\n\t"
  74                "scasb\n\t"
  75                "decl %1\n\t"
  76                "movl %8,%3\n"
  77                "1:\tdecl %3\n\t"
  78                "js 2f\n\t"
  79                "lodsb\n\t"
  80                "stosb\n\t"
  81                "testb %%al,%%al\n\t"
  82                "jne 1b\n"
  83                "2:\txorl %2,%2\n\t"
  84                "stosb"
  85                : "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
  86                : "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu), "g" (count)
  87                : "memory");
  88        return dest;
  89}
  90EXPORT_SYMBOL(strncat);
  91#endif
  92
  93#ifdef __HAVE_ARCH_STRCMP
  94int strcmp(const char *cs, const char *ct)
  95{
  96        int d0, d1;
  97        int res;
  98        asm volatile("1:\tlodsb\n\t"
  99                "scasb\n\t"
 100                "jne 2f\n\t"
 101                "testb %%al,%%al\n\t"
 102                "jne 1b\n\t"
 103                "xorl %%eax,%%eax\n\t"
 104                "jmp 3f\n"
 105                "2:\tsbbl %%eax,%%eax\n\t"
 106                "orb $1,%%al\n"
 107                "3:"
 108                : "=a" (res), "=&S" (d0), "=&D" (d1)
 109                : "1" (cs), "2" (ct)
 110                : "memory");
 111        return res;
 112}
 113EXPORT_SYMBOL(strcmp);
 114#endif
 115
 116#ifdef __HAVE_ARCH_STRNCMP
 117int strncmp(const char *cs, const char *ct, size_t count)
 118{
 119        int res;
 120        int d0, d1, d2;
 121        asm volatile("1:\tdecl %3\n\t"
 122                "js 2f\n\t"
 123                "lodsb\n\t"
 124                "scasb\n\t"
 125                "jne 3f\n\t"
 126                "testb %%al,%%al\n\t"
 127                "jne 1b\n"
 128                "2:\txorl %%eax,%%eax\n\t"
 129                "jmp 4f\n"
 130                "3:\tsbbl %%eax,%%eax\n\t"
 131                "orb $1,%%al\n"
 132                "4:"
 133                : "=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
 134                : "1" (cs), "2" (ct), "3" (count)
 135                : "memory");
 136        return res;
 137}
 138EXPORT_SYMBOL(strncmp);
 139#endif
 140
 141#ifdef __HAVE_ARCH_STRCHR
 142char *strchr(const char *s, int c)
 143{
 144        int d0;
 145        char *res;
 146        asm volatile("movb %%al,%%ah\n"
 147                "1:\tlodsb\n\t"
 148                "cmpb %%ah,%%al\n\t"
 149                "je 2f\n\t"
 150                "testb %%al,%%al\n\t"
 151                "jne 1b\n\t"
 152                "movl $1,%1\n"
 153                "2:\tmovl %1,%0\n\t"
 154                "decl %0"
 155                : "=a" (res), "=&S" (d0)
 156                : "1" (s), "0" (c)
 157                : "memory");
 158        return res;
 159}
 160EXPORT_SYMBOL(strchr);
 161#endif
 162
 163#ifdef __HAVE_ARCH_STRLEN
 164size_t strlen(const char *s)
 165{
 166        int d0;
 167        int res;
 168        asm volatile("repne\n\t"
 169                "scasb\n\t"
 170                "notl %0\n\t"
 171                "decl %0"
 172                : "=c" (res), "=&D" (d0)
 173                : "1" (s), "a" (0), "0" (0xffffffffu)
 174                : "memory");
 175        return res;
 176}
 177EXPORT_SYMBOL(strlen);
 178#endif
 179
 180#ifdef __HAVE_ARCH_MEMCHR
 181void *memchr(const void *cs, int c, size_t count)
 182{
 183        int d0;
 184        void *res;
 185        if (!count)
 186                return NULL;
 187        asm volatile("repne\n\t"
 188                "scasb\n\t"
 189                "je 1f\n\t"
 190                "movl $1,%0\n"
 191                "1:\tdecl %0"
 192                : "=D" (res), "=&c" (d0)
 193                : "a" (c), "0" (cs), "1" (count)
 194                : "memory");
 195        return res;
 196}
 197EXPORT_SYMBOL(memchr);
 198#endif
 199
 200#ifdef __HAVE_ARCH_MEMSCAN
 201void *memscan(void *addr, int c, size_t size)
 202{
 203        if (!size)
 204                return addr;
 205        asm volatile("repnz; scasb\n\t"
 206            "jnz 1f\n\t"
 207            "dec %%edi\n"
 208            "1:"
 209            : "=D" (addr), "=c" (size)
 210            : "0" (addr), "1" (size), "a" (c)
 211            : "memory");
 212        return addr;
 213}
 214EXPORT_SYMBOL(memscan);
 215#endif
 216
 217#ifdef __HAVE_ARCH_STRNLEN
 218size_t strnlen(const char *s, size_t count)
 219{
 220        int d0;
 221        int res;
 222        asm volatile("movl %2,%0\n\t"
 223                "jmp 2f\n"
 224                "1:\tcmpb $0,(%0)\n\t"
 225                "je 3f\n\t"
 226                "incl %0\n"
 227                "2:\tdecl %1\n\t"
 228                "cmpl $-1,%1\n\t"
 229                "jne 1b\n"
 230                "3:\tsubl %2,%0"
 231                : "=a" (res), "=&d" (d0)
 232                : "c" (s), "1" (count)
 233                : "memory");
 234        return res;
 235}
 236EXPORT_SYMBOL(strnlen);
 237#endif
 238