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