1 /* 2 * string.h: External definitions for optimized assembly string 3 * routines for the Linux Kernel. 4 * 5 * Copyright (C) 1995,1996 David S. Miller (davem@caip.rutgers.edu) 6 * Copyright (C) 1996,1997 Jakub Jelinek (jj@sunsite.mff.cuni.cz) 7 */ 8 9 #ifndef __SPARC_STRING_H__ 10 #define __SPARC_STRING_H__ 11 12 #include <asm/page.h> 13 14 /* Really, userland/ksyms should not see any of this stuff. */ 15 16 #ifdef __KERNEL__ 17 18 extern void __memmove(void *,const void *,__kernel_size_t); 19 extern __kernel_size_t __memcpy(void *,const void *,__kernel_size_t); 20 extern __kernel_size_t __memset(void *,int,__kernel_size_t); 21 22 #ifndef EXPORT_SYMTAB_STROPS 23 24 /* First the mem*() things. */ 25 #define __HAVE_ARCH_MEMMOVE 26 #undef memmove 27 #define memmove(_to, _from, _n) \ 28 ({ \ 29 void *_t = (_to); \ 30 __memmove(_t, (_from), (_n)); \ 31 _t; \ 32 }) 33 34 #define __HAVE_ARCH_MEMCPY 35 36 static inline void *__constant_memcpy(void *to, const void *from, __kernel_size_t n) 37 { 38 extern void __copy_1page(void *, const void *); 39 40 if(n <= 32) { 41 __builtin_memcpy(to, from, n); 42 } else if (((unsigned int) to & 7) != 0) { 43 /* Destination is not aligned on the double-word boundary */ 44 __memcpy(to, from, n); 45 } else { 46 switch(n) { 47 case PAGE_SIZE: 48 __copy_1page(to, from); 49 break; 50 default: 51 __memcpy(to, from, n); 52 break; 53 } 54 } 55 return to; 56 } 57 58 static inline void *__nonconstant_memcpy(void *to, const void *from, __kernel_size_t n) 59 { 60 __memcpy(to, from, n); 61 return to; 62 } 63 64 #undef memcpy 65 #define memcpy(t, f, n) \ 66 (__builtin_constant_p(n) ? \ 67 __constant_memcpy((t),(f),(n)) : \ 68 __nonconstant_memcpy((t),(f),(n))) 69 70 #define __HAVE_ARCH_MEMSET 71 72 static inline void *__constant_c_and_count_memset(void *s, char c, __kernel_size_t count) 73 { 74 extern void bzero_1page(void *); 75 extern __kernel_size_t __bzero(void *, __kernel_size_t); 76 77 if(!c) { 78 if(count == PAGE_SIZE) 79 bzero_1page(s); 80 else 81 __bzero(s, count); 82 } else { 83 __memset(s, c, count); 84 } 85 return s; 86 } 87 88 static inline void *__constant_c_memset(void *s, char c, __kernel_size_t count) 89 { 90 extern __kernel_size_t __bzero(void *, __kernel_size_t); 91 92 if(!c) 93 __bzero(s, count); 94 else 95 __memset(s, c, count); 96 return s; 97 } 98 99 static inline void *__nonconstant_memset(void *s, char c, __kernel_size_t count) 100 { 101 __memset(s, c, count); 102 return s; 103 } 104 105 #undef memset 106 #define memset(s, c, count) \ 107 (__builtin_constant_p(c) ? (__builtin_constant_p(count) ? \ 108 __constant_c_and_count_memset((s), (c), (count)) : \ 109 __constant_c_memset((s), (c), (count))) \ 110 : __nonconstant_memset((s), (c), (count))) 111 112 #define __HAVE_ARCH_MEMSCAN 113 114 #undef memscan 115 #define memscan(__arg0, __char, __arg2) \ 116 ({ \ 117 extern void *__memscan_zero(void *, size_t); \ 118 extern void *__memscan_generic(void *, int, size_t); \ 119 void *__retval, *__addr = (__arg0); \ 120 size_t __size = (__arg2); \ 121 \ 122 if(__builtin_constant_p(__char) && !(__char)) \ 123 __retval = __memscan_zero(__addr, __size); \ 124 else \ 125 __retval = __memscan_generic(__addr, (__char), __size); \ 126 \ 127 __retval; \ 128 }) 129 130 #define __HAVE_ARCH_MEMCMP 131 extern int memcmp(const void *,const void *,__kernel_size_t); 132 133 /* Now the str*() stuff... */ 134 #define __HAVE_ARCH_STRLEN 135 extern __kernel_size_t strlen(const char *); 136 137 #define __HAVE_ARCH_STRNCMP 138 139 extern int __strncmp(const char *, const char *, __kernel_size_t); 140 141 static inline int __constant_strncmp(const char *src, const char *dest, __kernel_size_t count) 142 { 143 register int retval; 144 switch(count) { 145 case 0: return 0; 146 case 1: return (src[0] - dest[0]); 147 case 2: retval = (src[0] - dest[0]); 148 if(!retval && src[0]) 149 retval = (src[1] - dest[1]); 150 return retval; 151 case 3: retval = (src[0] - dest[0]); 152 if(!retval && src[0]) { 153 retval = (src[1] - dest[1]); 154 if(!retval && src[1]) 155 retval = (src[2] - dest[2]); 156 } 157 return retval; 158 case 4: retval = (src[0] - dest[0]); 159 if(!retval && src[0]) { 160 retval = (src[1] - dest[1]); 161 if(!retval && src[1]) { 162 retval = (src[2] - dest[2]); 163 if (!retval && src[2]) 164 retval = (src[3] - dest[3]); 165 } 166 } 167 return retval; 168 case 5: retval = (src[0] - dest[0]); 169 if(!retval && src[0]) { 170 retval = (src[1] - dest[1]); 171 if(!retval && src[1]) { 172 retval = (src[2] - dest[2]); 173 if (!retval && src[2]) { 174 retval = (src[3] - dest[3]); 175 if (!retval && src[3]) 176 retval = (src[4] - dest[4]); 177 } 178 } 179 } 180 return retval; 181 default: 182 retval = (src[0] - dest[0]); 183 if(!retval && src[0]) { 184 retval = (src[1] - dest[1]); 185 if(!retval && src[1]) { 186 retval = (src[2] - dest[2]); 187 if(!retval && src[2]) 188 retval = __strncmp(src+3,dest+3,count-3); 189 } 190 } 191 return retval; 192 } 193 } 194 195 #undef strncmp 196 #define strncmp(__arg0, __arg1, __arg2) \ 197 (__builtin_constant_p(__arg2) ? \ 198 __constant_strncmp(__arg0, __arg1, __arg2) : \ 199 __strncmp(__arg0, __arg1, __arg2)) 200 201 #endif /* !EXPORT_SYMTAB_STROPS */ 202 203 #endif /* __KERNEL__ */ 204 205 #endif /* !(__SPARC_STRING_H__) */ 206