1 /*
2 * Taken from Linux /usr/include/asm/string.h
3 * All except memcpy, memmove, memset and memcmp removed.
4 */
5
6 #ifndef _I386_STRING_H_
7 #define _I386_STRING_H_
8
9 /*
10 * This string-include defines all string functions as inline
11 * functions. Use gcc. It also assumes ds=es=data space, this should be
12 * normal. Most of the string-functions are rather heavily hand-optimized,
13 * see especially strtok,strstr,str[c]spn. They should work, but are not
14 * very easy to understand. Everything is done entirely within the register
15 * set, making the functions fast and clean. String instructions have been
16 * used through-out, making for "slightly" unclear code :-)
17 *
18 * NO Copyright (C) 1991, 1992 Linus Torvalds,
19 * consider these trivial functions to be PD.
20 */
21
22 typedef int size_t;
23
24 extern void *__memcpy(void * to, const void * from, size_t n);
25 extern void *__constant_memcpy(void * to, const void * from, size_t n);
26 extern void *memmove(void * dest,const void * src, size_t n);
27 extern void *__memset_generic(void * s, char c,size_t count);
28 extern void *__constant_c_memset(void * s, unsigned long c, size_t count);
29 extern void *__constant_c_and_count_memset(void * s, unsigned long pattern, size_t count);
30
31
__memcpy(void * to,const void * from,size_t n)32 extern inline void * __memcpy(void * to, const void * from, size_t n)
33 {
34 int d0, d1, d2;
35 __asm__ __volatile__(
36 "cld\n\t"
37 "rep ; movsl\n\t"
38 "testb $2,%b4\n\t"
39 "je 1f\n\t"
40 "movsw\n"
41 "1:\ttestb $1,%b4\n\t"
42 "je 2f\n\t"
43 "movsb\n"
44 "2:"
45 : "=&c" (d0), "=&D" (d1), "=&S" (d2)
46 :"0" (n/4), "q" (n),"1" ((long) to),"2" ((long) from)
47 : "memory");
48 return (to);
49 }
50
51 /*
52 * This looks horribly ugly, but the compiler can optimize it totally,
53 * as the count is constant.
54 */
__constant_memcpy(void * to,const void * from,size_t n)55 extern inline void * __constant_memcpy(void * to, const void * from, size_t n)
56 {
57 switch (n) {
58 case 0:
59 return to;
60 case 1:
61 *(unsigned char *)to = *(const unsigned char *)from;
62 return to;
63 case 2:
64 *(unsigned short *)to = *(const unsigned short *)from;
65 return to;
66 case 3:
67 *(unsigned short *)to = *(const unsigned short *)from;
68 *(2+(unsigned char *)to) = *(2+(const unsigned char *)from);
69 return to;
70 case 4:
71 *(unsigned long *)to = *(const unsigned long *)from;
72 return to;
73 case 6: /* for Ethernet addresses */
74 *(unsigned long *)to = *(const unsigned long *)from;
75 *(2+(unsigned short *)to) = *(2+(const unsigned short *)from);
76 return to;
77 case 8:
78 *(unsigned long *)to = *(const unsigned long *)from;
79 *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
80 return to;
81 case 12:
82 *(unsigned long *)to = *(const unsigned long *)from;
83 *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
84 *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
85 return to;
86 case 16:
87 *(unsigned long *)to = *(const unsigned long *)from;
88 *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
89 *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
90 *(3+(unsigned long *)to) = *(3+(const unsigned long *)from);
91 return to;
92 case 20:
93 *(unsigned long *)to = *(const unsigned long *)from;
94 *(1+(unsigned long *)to) = *(1+(const unsigned long *)from);
95 *(2+(unsigned long *)to) = *(2+(const unsigned long *)from);
96 *(3+(unsigned long *)to) = *(3+(const unsigned long *)from);
97 *(4+(unsigned long *)to) = *(4+(const unsigned long *)from);
98 return to;
99 }
100 #define COMMON(x) \
101 __asm__ __volatile__( \
102 "cld\n\t" \
103 "rep ; movsl" \
104 x \
105 : "=&c" (d0), "=&D" (d1), "=&S" (d2) \
106 : "0" (n/4),"1" ((long) to),"2" ((long) from) \
107 : "memory");
108 {
109 int d0, d1, d2;
110 switch (n % 4) {
111 case 0: COMMON(""); return to;
112 case 1: COMMON("\n\tmovsb"); return to;
113 case 2: COMMON("\n\tmovsw"); return to;
114 default: COMMON("\n\tmovsw\n\tmovsb"); return to;
115 }
116 }
117
118 #undef COMMON
119 }
120
121 #define __HAVE_ARCH_MEMCPY
122 #define memcpy(t, f, n) \
123 (__builtin_constant_p(n) ? \
124 __constant_memcpy((t),(f),(n)) : \
125 __memcpy((t),(f),(n)))
126
127 #define __HAVE_ARCH_MEMMOVE
memmove(void * dest,const void * src,size_t n)128 extern inline void * memmove(void * dest,const void * src, size_t n)
129 {
130 int d0, d1, d2;
131 if (dest<src)
132 __asm__ __volatile__(
133 "cld\n\t"
134 "rep\n\t"
135 "movsb"
136 : "=&c" (d0), "=&S" (d1), "=&D" (d2)
137 :"0" (n),"1" (src),"2" (dest)
138 : "memory");
139 else
140 __asm__ __volatile__(
141 "std\n\t"
142 "rep\n\t"
143 "movsb\n\t"
144 "cld"
145 : "=&c" (d0), "=&S" (d1), "=&D" (d2)
146 :"0" (n),
147 "1" (n-1+(const char *)src),
148 "2" (n-1+(char *)dest)
149 :"memory");
150 return dest;
151 }
152
153 #define memcmp __builtin_memcmp
154
__memset_generic(void * s,char c,size_t count)155 extern inline void * __memset_generic(void * s, char c,size_t count)
156 {
157 int d0, d1;
158 __asm__ __volatile__(
159 "cld\n\t"
160 "rep\n\t"
161 "stosb"
162 : "=&c" (d0), "=&D" (d1)
163 :"a" (c),"1" (s),"0" (count)
164 :"memory");
165 return s;
166 }
167
168 /* we might want to write optimized versions of these later */
169 #define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
170
171 /*
172 * memset(x,0,y) is a reasonably common thing to do, so we want to fill
173 * things 32 bits at a time even when we don't know the size of the
174 * area at compile-time..
175 */
__constant_c_memset(void * s,unsigned long c,size_t count)176 extern inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
177 {
178 int d0, d1;
179 __asm__ __volatile__(
180 "cld\n\t"
181 "rep ; stosl\n\t"
182 "testb $2,%b3\n\t"
183 "je 1f\n\t"
184 "stosw\n"
185 "1:\ttestb $1,%b3\n\t"
186 "je 2f\n\t"
187 "stosb\n"
188 "2:"
189 : "=&c" (d0), "=&D" (d1)
190 :"a" (c), "q" (count), "0" (count/4), "1" ((long) s)
191 :"memory");
192 return (s);
193 }
194
195 /*
196 * This looks horribly ugly, but the compiler can optimize it totally,
197 * as we by now know that both pattern and count is constant..
198 */
__constant_c_and_count_memset(void * s,unsigned long pattern,size_t count)199 extern inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
200 {
201 switch (count) {
202 case 0:
203 return s;
204 case 1:
205 *(unsigned char *)s = pattern;
206 return s;
207 case 2:
208 *(unsigned short *)s = pattern;
209 return s;
210 case 3:
211 *(unsigned short *)s = pattern;
212 *(2+(unsigned char *)s) = pattern;
213 return s;
214 case 4:
215 *(unsigned long *)s = pattern;
216 return s;
217 }
218 #define COMMON(x) \
219 __asm__ __volatile__("cld\n\t" \
220 "rep ; stosl" \
221 x \
222 : "=&c" (d0), "=&D" (d1) \
223 : "a" (pattern),"0" (count/4),"1" ((long) s) \
224 : "memory")
225 {
226 int d0, d1;
227 switch (count % 4) {
228 case 0: COMMON(""); return s;
229 case 1: COMMON("\n\tstosb"); return s;
230 case 2: COMMON("\n\tstosw"); return s;
231 default: COMMON("\n\tstosw\n\tstosb"); return s;
232 }
233 }
234
235 #undef COMMON
236 }
237
238 #define __constant_c_x_memset(s, c, count) \
239 (__builtin_constant_p(count) ? \
240 __constant_c_and_count_memset((s),(c),(count)) : \
241 __constant_c_memset((s),(c),(count)))
242
243 #define __memset(s, c, count) \
244 (__builtin_constant_p(count) ? \
245 __constant_count_memset((s),(c),(count)) : \
246 __memset_generic((s),(c),(count)))
247
248 #define __HAVE_ARCH_MEMSET
249 #define memset(s, c, count) \
250 (__builtin_constant_p(c) ? \
251 __constant_c_x_memset((s),(c),(count)) : \
252 __memset((s),(c),(count)))
253
254 #define __HAVE_ARCH_STRNCMP
strncmp(const char * cs,const char * ct,size_t count)255 static inline int strncmp(const char * cs,const char * ct,size_t count)
256 {
257 register int __res;
258 int d0, d1, d2;
259 __asm__ __volatile__(
260 "1:\tdecl %3\n\t"
261 "js 2f\n\t"
262 "lodsb\n\t"
263 "scasb\n\t"
264 "jne 3f\n\t"
265 "testb %%al,%%al\n\t"
266 "jne 1b\n"
267 "2:\txorl %%eax,%%eax\n\t"
268 "jmp 4f\n"
269 "3:\tsbbl %%eax,%%eax\n\t"
270 "orb $1,%%al\n"
271 "4:"
272 :"=a" (__res), "=&S" (d0), "=&D" (d1), "=&c" (d2)
273 :"1" (cs),"2" (ct),"3" (count));
274 return __res;
275 }
276
277 #define __HAVE_ARCH_STRLEN
strlen(const char * s)278 static inline size_t strlen(const char * s)
279 {
280 int d0;
281 register int __res;
282 __asm__ __volatile__(
283 "repne\n\t"
284 "scasb\n\t"
285 "notl %0\n\t"
286 "decl %0"
287 :"=c" (__res), "=&D" (d0) :"1" (s),"a" (0), "0" (0xffffffff));
288 return __res;
289 }
290
291 #endif
292