Home | History | Annotate | Download | only in netboot
      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
    292