root/arch/x86/lib/string_32.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. strcpy
  2. strncpy
  3. strcat
  4. strncat
  5. strcmp
  6. strncmp
  7. strchr
  8. strlen
  9. memchr
  10. memscan
  11. strnlen

   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
  18 char *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 }
  29 EXPORT_SYMBOL(strcpy);
  30 #endif
  31 
  32 #ifdef __HAVE_ARCH_STRNCPY
  33 char *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 }
  49 EXPORT_SYMBOL(strncpy);
  50 #endif
  51 
  52 #ifdef __HAVE_ARCH_STRCAT
  53 char *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 }
  67 EXPORT_SYMBOL(strcat);
  68 #endif
  69 
  70 #ifdef __HAVE_ARCH_STRNCAT
  71 char *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 }
  91 EXPORT_SYMBOL(strncat);
  92 #endif
  93 
  94 #ifdef __HAVE_ARCH_STRCMP
  95 int 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 }
 114 EXPORT_SYMBOL(strcmp);
 115 #endif
 116 
 117 #ifdef __HAVE_ARCH_STRNCMP
 118 int 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 }
 139 EXPORT_SYMBOL(strncmp);
 140 #endif
 141 
 142 #ifdef __HAVE_ARCH_STRCHR
 143 char *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 }
 161 EXPORT_SYMBOL(strchr);
 162 #endif
 163 
 164 #ifdef __HAVE_ARCH_STRLEN
 165 size_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 }
 176 EXPORT_SYMBOL(strlen);
 177 #endif
 178 
 179 #ifdef __HAVE_ARCH_MEMCHR
 180 void *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 }
 196 EXPORT_SYMBOL(memchr);
 197 #endif
 198 
 199 #ifdef __HAVE_ARCH_MEMSCAN
 200 void *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 }
 213 EXPORT_SYMBOL(memscan);
 214 #endif
 215 
 216 #ifdef __HAVE_ARCH_STRNLEN
 217 size_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 }
 235 EXPORT_SYMBOL(strnlen);
 236 #endif

/* [<][>][^][v][top][bottom][index][help] */