linux-asm-string.h revision 1650e5296608be8925d9831310c9ad3595fd6869
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 22typedef int size_t; 23 24extern void *__memcpy(void * to, const void * from, size_t n); 25extern void *__constant_memcpy(void * to, const void * from, size_t n); 26extern void *memmove(void * dest,const void * src, size_t n); 27extern void *__memset_generic(void * s, char c,size_t count); 28extern void *__constant_c_memset(void * s, unsigned long c, size_t count); 29extern void *__constant_c_and_count_memset(void * s, unsigned long pattern, size_t count); 30 31 32extern inline void * __memcpy(void * to, const void * from, size_t n) 33{ 34int 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"); 48return (to); 49} 50 51/* 52 * This looks horribly ugly, but the compiler can optimize it totally, 53 * as the count is constant. 54 */ 55extern 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 128extern inline void * memmove(void * dest,const void * src, size_t n) 129{ 130int d0, d1, d2; 131if (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"); 139else 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"); 150return dest; 151} 152 153#define memcmp __builtin_memcmp 154 155extern inline void * __memset_generic(void * s, char c,size_t count) 156{ 157int 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"); 165return 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 */ 176extern inline void * __constant_c_memset(void * s, unsigned long c, size_t count) 177{ 178int 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"); 192return (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 */ 199extern 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 255static inline int strncmp(const char * cs,const char * ct,size_t count) 256{ 257register int __res; 258int 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)); 274return __res; 275} 276 277#define __HAVE_ARCH_STRLEN 278static inline size_t strlen(const char * s) 279{ 280int d0; 281register 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)); 288return __res; 289} 290 291#endif 292