Linux Audio

Check our new training course

Loading...
  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