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        size_t res;
 168        asm volatile("repne\n\t"
 169                "scasb"
 170                : "=c" (res), "=&D" (d0)
 171                : "1" (s), "a" (0), "0" (0xffffffffu)
 172                : "memory");
 173        return ~res - 1;
 174}
 175EXPORT_SYMBOL(strlen);
 176#endif
 177
 178#ifdef __HAVE_ARCH_MEMCHR
 179void *memchr(const void *cs, int c, size_t count)
 180{
 181        int d0;
 182        void *res;
 183        if (!count)
 184                return NULL;
 185        asm volatile("repne\n\t"
 186                "scasb\n\t"
 187                "je 1f\n\t"
 188                "movl $1,%0\n"
 189                "1:\tdecl %0"
 190                : "=D" (res), "=&c" (d0)
 191                : "a" (c), "0" (cs), "1" (count)
 192                : "memory");
 193        return res;
 194}
 195EXPORT_SYMBOL(memchr);
 196#endif
 197
 198#ifdef __HAVE_ARCH_MEMSCAN
 199void *memscan(void *addr, int c, size_t size)
 200{
 201        if (!size)
 202                return addr;
 203        asm volatile("repnz; scasb\n\t"
 204            "jnz 1f\n\t"
 205            "dec %%edi\n"
 206            "1:"
 207            : "=D" (addr), "=c" (size)
 208            : "0" (addr), "1" (size), "a" (c)
 209            : "memory");
 210        return addr;
 211}
 212EXPORT_SYMBOL(memscan);
 213#endif
 214
 215#ifdef __HAVE_ARCH_STRNLEN
 216size_t strnlen(const char *s, size_t count)
 217{
 218        int d0;
 219        int res;
 220        asm volatile("movl %2,%0\n\t"
 221                "jmp 2f\n"
 222                "1:\tcmpb $0,(%0)\n\t"
 223                "je 3f\n\t"
 224                "incl %0\n"
 225                "2:\tdecl %1\n\t"
 226                "cmpl $-1,%1\n\t"
 227                "jne 1b\n"
 228                "3:\tsubl %2,%0"
 229                : "=a" (res), "=&d" (d0)
 230                : "c" (s), "1" (count)
 231                : "memory");
 232        return res;
 233}
 234EXPORT_SYMBOL(strnlen);
 235#endif
 236