~ubuntu-branches/ubuntu/utopic/grub/utopic

« back to all changes in this revision

Viewing changes to netboot/linux-asm-string.h

  • Committer: Bazaar Package Importer
  • Author(s): Jason Thomas
  • Date: 2002-02-04 15:35:01 UTC
  • Revision ID: james.westby@ubuntu.com-20020204153501-neulkag77r3a2m0v
Tags: upstream-0.91
ImportĀ upstreamĀ versionĀ 0.91

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
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
 */
 
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
 
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
 
 
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
 */
 
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
 */
 
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
 
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
 
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