• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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