File Index
Files and directories
Sign in
FILE

string_32.c

File preview with syntax highlighting.

linux-6.19.14/arch/x86/lib/string_32.c C
  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#define __NO_FORTIFY
 15#include <linux/string.h>
 16#include <linux/export.h>
 17
 18#ifdef __HAVE_ARCH_STRCPY
 19char *strcpy(char *dest, const char *src)
 20{
 21	int d0, d1, d2;
 22	asm volatile("1:\tlodsb\n\t"
 23		"stosb\n\t"
 24		"testb %%al,%%al\n\t"
 25		"jne 1b"
 26		: "=&S" (d0), "=&D" (d1), "=&a" (d2)
 27		: "0" (src), "1" (dest) : "memory");
 28	return dest;
 29}
 30EXPORT_SYMBOL(strcpy);
 31#endif
 32
 33#ifdef __HAVE_ARCH_STRNCPY
 34char *strncpy(char *dest, const char *src, size_t count)
 35{
 36	int d0, d1, d2, d3;
 37	asm volatile("1:\tdecl %2\n\t"
 38		"js 2f\n\t"
 39		"lodsb\n\t"
 40		"stosb\n\t"
 41		"testb %%al,%%al\n\t"
 42		"jne 1b\n\t"
 43		"rep 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 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 scasb\n\t"
 74		"decl %1\n\t"
 75		"movl %8,%3\n"
 76		"1:\tdecl %3\n\t"
 77		"js 2f\n\t"
 78		"lodsb\n\t"
 79		"stosb\n\t"
 80		"testb %%al,%%al\n\t"
 81		"jne 1b\n"
 82		"2:\txorl %2,%2\n\t"
 83		"stosb"
 84		: "=&S" (d0), "=&D" (d1), "=&a" (d2), "=&c" (d3)
 85		: "0" (src), "1" (dest), "2" (0), "3" (0xffffffffu), "g" (count)
 86		: "memory");
 87	return dest;
 88}
 89EXPORT_SYMBOL(strncat);
 90#endif
 91
 92#ifdef __HAVE_ARCH_STRCMP
 93int strcmp(const char *cs, const char *ct)
 94{
 95	int d0, d1;
 96	int res;
 97	asm volatile("1:\tlodsb\n\t"
 98		"scasb\n\t"
 99		"jne 2f\n\t"
100		"testb %%al,%%al\n\t"
101		"jne 1b\n\t"
102		"xorl %%eax,%%eax\n\t"
103		"jmp 3f\n"
104		"2:\tsbbl %%eax,%%eax\n\t"
105		"orb $1,%%al\n"
106		"3:"
107		: "=a" (res), "=&S" (d0), "=&D" (d1)
108		: "1" (cs), "2" (ct)
109		: "memory");
110	return res;
111}
112EXPORT_SYMBOL(strcmp);
113#endif
114
115#ifdef __HAVE_ARCH_STRNCMP
116int strncmp(const char *cs, const char *ct, size_t count)
117{
118	int res;
119	int d0, d1, d2;
120	asm volatile("1:\tdecl %3\n\t"
121		"js 2f\n\t"
122		"lodsb\n\t"
123		"scasb\n\t"
124		"jne 3f\n\t"
125		"testb %%al,%%al\n\t"
126		"jne 1b\n"
127		"2:\txorl %%eax,%%eax\n\t"
128		"jmp 4f\n"
129		"3:\tsbbl %%eax,%%eax\n\t"
130		"orb $1,%%al\n"
131		"4:"
132		: "=a" (res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
133		: "1" (cs), "2" (ct), "3" (count)
134		: "memory");
135	return res;
136}
137EXPORT_SYMBOL(strncmp);
138#endif
139
140#ifdef __HAVE_ARCH_STRCHR
141char *strchr(const char *s, int c)
142{
143	int d0;
144	char *res;
145	asm volatile("movb %%al,%%ah\n"
146		"1:\tlodsb\n\t"
147		"cmpb %%ah,%%al\n\t"
148		"je 2f\n\t"
149		"testb %%al,%%al\n\t"
150		"jne 1b\n\t"
151		"movl $1,%1\n"
152		"2:\tmovl %1,%0\n\t"
153		"decl %0"
154		: "=a" (res), "=&S" (d0)
155		: "1" (s), "0" (c)
156		: "memory");
157	return res;
158}
159EXPORT_SYMBOL(strchr);
160#endif
161
162#ifdef __HAVE_ARCH_STRLEN
163size_t strlen(const char *s)
164{
165	int d0;
166	size_t res;
167	asm volatile("repne scasb"
168		: "=c" (res), "=&D" (d0)
169		: "1" (s), "a" (0), "0" (0xffffffffu)
170		: "memory");
171	return ~res - 1;
172}
173EXPORT_SYMBOL(strlen);
174#endif
175
176#ifdef __HAVE_ARCH_MEMCHR
177void *memchr(const void *cs, int c, size_t count)
178{
179	int d0;
180	void *res;
181	if (!count)
182		return NULL;
183	asm volatile("repne scasb\n\t"
184		"je 1f\n\t"
185		"movl $1,%0\n"
186		"1:\tdecl %0"
187		: "=D" (res), "=&c" (d0)
188		: "a" (c), "0" (cs), "1" (count)
189		: "memory");
190	return res;
191}
192EXPORT_SYMBOL(memchr);
193#endif
194
195#ifdef __HAVE_ARCH_MEMSCAN
196void *memscan(void *addr, int c, size_t size)
197{
198	if (!size)
199		return addr;
200	asm volatile("repnz scasb\n\t"
201	    "jnz 1f\n\t"
202	    "dec %%edi\n"
203	    "1:"
204	    : "=D" (addr), "=c" (size)
205	    : "0" (addr), "1" (size), "a" (c)
206	    : "memory");
207	return addr;
208}
209EXPORT_SYMBOL(memscan);
210#endif
211
212#ifdef __HAVE_ARCH_STRNLEN
213size_t strnlen(const char *s, size_t count)
214{
215	int d0;
216	int res;
217	asm volatile("movl %2,%0\n\t"
218		"jmp 2f\n"
219		"1:\tcmpb $0,(%0)\n\t"
220		"je 3f\n\t"
221		"incl %0\n"
222		"2:\tdecl %1\n\t"
223		"cmpl $-1,%1\n\t"
224		"jne 1b\n"
225		"3:\tsubl %2,%0"
226		: "=a" (res), "=&d" (d0)
227		: "c" (s), "1" (count)
228		: "memory");
229	return res;
230}
231EXPORT_SYMBOL(strnlen);
232#endif
~/ Read-only file preview.