linux/include/asm-x86/string_32.h
<<
>>
Prefs
   1#ifndef _I386_STRING_H_
   2#define _I386_STRING_H_
   3
   4#ifdef __KERNEL__
   5
   6/* Let gcc decide wether to inline or use the out of line functions */
   7
   8#define __HAVE_ARCH_STRCPY
   9extern char *strcpy(char *dest, const char *src);
  10
  11#define __HAVE_ARCH_STRNCPY
  12extern char *strncpy(char *dest, const char *src, size_t count);
  13
  14#define __HAVE_ARCH_STRCAT
  15extern char *strcat(char *dest, const char *src);
  16
  17#define __HAVE_ARCH_STRNCAT
  18extern char *strncat(char *dest, const char *src, size_t count);
  19
  20#define __HAVE_ARCH_STRCMP
  21extern int strcmp(const char *cs, const char *ct);
  22
  23#define __HAVE_ARCH_STRNCMP
  24extern int strncmp(const char *cs, const char *ct, size_t count);
  25
  26#define __HAVE_ARCH_STRCHR
  27extern char *strchr(const char *s, int c);
  28
  29#define __HAVE_ARCH_STRLEN
  30extern size_t strlen(const char *s);
  31
  32static __always_inline void * __memcpy(void * to, const void * from, size_t n)
  33{
  34int d0, d1, d2;
  35__asm__ __volatile__(
  36        "rep ; movsl\n\t"
  37        "movl %4,%%ecx\n\t"
  38        "andl $3,%%ecx\n\t"
  39        "jz 1f\n\t"
  40        "rep ; movsb\n\t"
  41        "1:"
  42        : "=&c" (d0), "=&D" (d1), "=&S" (d2)
  43        : "0" (n/4), "g" (n), "1" ((long) to), "2" ((long) from)
  44        : "memory");
  45return (to);
  46}
  47
  48/*
  49 * This looks ugly, but the compiler can optimize it totally,
  50 * as the count is constant.
  51 */
  52static __always_inline void * __constant_memcpy(void * to, const void * from, size_t n)
  53{
  54        long esi, edi;
  55        if (!n) return to;
  56#if 1   /* want to do small copies with non-string ops? */
  57        switch (n) {
  58                case 1: *(char*)to = *(char*)from; return to;
  59                case 2: *(short*)to = *(short*)from; return to;
  60                case 4: *(int*)to = *(int*)from; return to;
  61#if 1   /* including those doable with two moves? */
  62                case 3: *(short*)to = *(short*)from;
  63                        *((char*)to+2) = *((char*)from+2); return to;
  64                case 5: *(int*)to = *(int*)from;
  65                        *((char*)to+4) = *((char*)from+4); return to;
  66                case 6: *(int*)to = *(int*)from;
  67                        *((short*)to+2) = *((short*)from+2); return to;
  68                case 8: *(int*)to = *(int*)from;
  69                        *((int*)to+1) = *((int*)from+1); return to;
  70#endif
  71        }
  72#endif
  73        esi = (long) from;
  74        edi = (long) to;
  75        if (n >= 5*4) {
  76                /* large block: use rep prefix */
  77                int ecx;
  78                __asm__ __volatile__(
  79                        "rep ; movsl"
  80                        : "=&c" (ecx), "=&D" (edi), "=&S" (esi)
  81                        : "0" (n/4), "1" (edi),"2" (esi)
  82                        : "memory"
  83                );
  84        } else {
  85                /* small block: don't clobber ecx + smaller code */
  86                if (n >= 4*4) __asm__ __volatile__("movsl"
  87                        :"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory");
  88                if (n >= 3*4) __asm__ __volatile__("movsl"
  89                        :"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory");
  90                if (n >= 2*4) __asm__ __volatile__("movsl"
  91                        :"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory");
  92                if (n >= 1*4) __asm__ __volatile__("movsl"
  93                        :"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory");
  94        }
  95        switch (n % 4) {
  96                /* tail */
  97                case 0: return to;
  98                case 1: __asm__ __volatile__("movsb"
  99                        :"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory");
 100                        return to;
 101                case 2: __asm__ __volatile__("movsw"
 102                        :"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory");
 103                        return to;
 104                default: __asm__ __volatile__("movsw\n\tmovsb"
 105                        :"=&D"(edi),"=&S"(esi):"0"(edi),"1"(esi):"memory");
 106                        return to;
 107        }
 108}
 109
 110#define __HAVE_ARCH_MEMCPY
 111
 112#ifdef CONFIG_X86_USE_3DNOW
 113
 114#include <asm/mmx.h>
 115
 116/*
 117 *      This CPU favours 3DNow strongly (eg AMD Athlon)
 118 */
 119
 120static inline void * __constant_memcpy3d(void * to, const void * from, size_t len)
 121{
 122        if (len < 512)
 123                return __constant_memcpy(to, from, len);
 124        return _mmx_memcpy(to, from, len);
 125}
 126
 127static __inline__ void *__memcpy3d(void *to, const void *from, size_t len)
 128{
 129        if (len < 512)
 130                return __memcpy(to, from, len);
 131        return _mmx_memcpy(to, from, len);
 132}
 133
 134#define memcpy(t, f, n) \
 135(__builtin_constant_p(n) ? \
 136 __constant_memcpy3d((t),(f),(n)) : \
 137 __memcpy3d((t),(f),(n)))
 138
 139#else
 140
 141/*
 142 *      No 3D Now!
 143 */
 144 
 145#define memcpy(t, f, n) \
 146(__builtin_constant_p(n) ? \
 147 __constant_memcpy((t),(f),(n)) : \
 148 __memcpy((t),(f),(n)))
 149
 150#endif
 151
 152#define __HAVE_ARCH_MEMMOVE
 153void *memmove(void * dest,const void * src, size_t n);
 154
 155#define memcmp __builtin_memcmp
 156
 157#define __HAVE_ARCH_MEMCHR
 158extern void *memchr(const void * cs,int c,size_t count);
 159
 160static inline void * __memset_generic(void * s, char c,size_t count)
 161{
 162int d0, d1;
 163__asm__ __volatile__(
 164        "rep\n\t"
 165        "stosb"
 166        : "=&c" (d0), "=&D" (d1)
 167        :"a" (c),"1" (s),"0" (count)
 168        :"memory");
 169return s;
 170}
 171
 172/* we might want to write optimized versions of these later */
 173#define __constant_count_memset(s,c,count) __memset_generic((s),(c),(count))
 174
 175/*
 176 * memset(x,0,y) is a reasonably common thing to do, so we want to fill
 177 * things 32 bits at a time even when we don't know the size of the
 178 * area at compile-time..
 179 */
 180static __always_inline void * __constant_c_memset(void * s, unsigned long c, size_t count)
 181{
 182int d0, d1;
 183__asm__ __volatile__(
 184        "rep ; stosl\n\t"
 185        "testb $2,%b3\n\t"
 186        "je 1f\n\t"
 187        "stosw\n"
 188        "1:\ttestb $1,%b3\n\t"
 189        "je 2f\n\t"
 190        "stosb\n"
 191        "2:"
 192        :"=&c" (d0), "=&D" (d1)
 193        :"a" (c), "q" (count), "0" (count/4), "1" ((long) s)
 194        :"memory");
 195return (s);     
 196}
 197
 198/* Added by Gertjan van Wingerde to make minix and sysv module work */
 199#define __HAVE_ARCH_STRNLEN
 200extern size_t strnlen(const char * s, size_t count);
 201/* end of additional stuff */
 202
 203#define __HAVE_ARCH_STRSTR
 204extern char *strstr(const char *cs, const char *ct);
 205
 206/*
 207 * This looks horribly ugly, but the compiler can optimize it totally,
 208 * as we by now know that both pattern and count is constant..
 209 */
 210static __always_inline void * __constant_c_and_count_memset(void * s, unsigned long pattern, size_t count)
 211{
 212        switch (count) {
 213                case 0:
 214                        return s;
 215                case 1:
 216                        *(unsigned char *)s = pattern & 0xff;
 217                        return s;
 218                case 2:
 219                        *(unsigned short *)s = pattern & 0xffff;
 220                        return s;
 221                case 3:
 222                        *(unsigned short *)s = pattern & 0xffff;
 223                        *(2+(unsigned char *)s) = pattern & 0xff;
 224                        return s;
 225                case 4:
 226                        *(unsigned long *)s = pattern;
 227                        return s;
 228        }
 229#define COMMON(x) \
 230__asm__  __volatile__( \
 231        "rep ; stosl" \
 232        x \
 233        : "=&c" (d0), "=&D" (d1) \
 234        : "a" (pattern),"0" (count/4),"1" ((long) s) \
 235        : "memory")
 236{
 237        int d0, d1;
 238        switch (count % 4) {
 239                case 0: COMMON(""); return s;
 240                case 1: COMMON("\n\tstosb"); return s;
 241                case 2: COMMON("\n\tstosw"); return s;
 242                default: COMMON("\n\tstosw\n\tstosb"); return s;
 243        }
 244}
 245  
 246#undef COMMON
 247}
 248
 249#define __constant_c_x_memset(s, c, count) \
 250(__builtin_constant_p(count) ? \
 251 __constant_c_and_count_memset((s),(c),(count)) : \
 252 __constant_c_memset((s),(c),(count)))
 253
 254#define __memset(s, c, count) \
 255(__builtin_constant_p(count) ? \
 256 __constant_count_memset((s),(c),(count)) : \
 257 __memset_generic((s),(c),(count)))
 258
 259#define __HAVE_ARCH_MEMSET
 260#define memset(s, c, count) \
 261(__builtin_constant_p(c) ? \
 262 __constant_c_x_memset((s),(0x01010101UL*(unsigned char)(c)),(count)) : \
 263 __memset((s),(c),(count)))
 264
 265/*
 266 * find the first occurrence of byte 'c', or 1 past the area if none
 267 */
 268#define __HAVE_ARCH_MEMSCAN
 269extern void *memscan(void * addr, int c, size_t size);
 270
 271#endif /* __KERNEL__ */
 272
 273#endif
 274
lxr.linux.no kindly hosted by Redpill Linpro AS, provider of Linux consulting and operations services since 1995.