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