1/* $Id: string.h,v 1.1.1.1 2008/10/15 03:29:17 james26_jang Exp $
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
18extern void __memmove(void *,const void *,__kernel_size_t);
19extern __kernel_size_t __memcpy(void *,const void *,__kernel_size_t);
20extern __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_BCOPY
26#define __HAVE_ARCH_MEMMOVE
27#undef memmove
28#define memmove(_to, _from, _n) \
29({ \
30	void *_t = (_to); \
31	__memmove(_t, (_from), (_n)); \
32	_t; \
33})
34
35#define __HAVE_ARCH_MEMCPY
36
37static inline void *__constant_memcpy(void *to, const void *from, __kernel_size_t n)
38{
39	extern void __copy_1page(void *, const void *);
40
41	if(n <= 32) {
42		__builtin_memcpy(to, from, n);
43	} else {
44		switch(n) {
45		case PAGE_SIZE:
46			__copy_1page(to, from);
47			break;
48		default:
49			__memcpy(to, from, n);
50			break;
51		}
52	}
53	return to;
54}
55
56static inline void *__nonconstant_memcpy(void *to, const void *from, __kernel_size_t n)
57{
58	__memcpy(to, from, n);
59	return to;
60}
61
62#undef memcpy
63#define memcpy(t, f, n) \
64(__builtin_constant_p(n) ? \
65 __constant_memcpy((t),(f),(n)) : \
66 __nonconstant_memcpy((t),(f),(n)))
67
68#define __HAVE_ARCH_MEMSET
69
70static inline void *__constant_c_and_count_memset(void *s, char c, __kernel_size_t count)
71{
72	extern void bzero_1page(void *);
73	extern __kernel_size_t __bzero(void *, __kernel_size_t);
74
75	if(!c) {
76		if(count == PAGE_SIZE)
77			bzero_1page(s);
78		else
79			__bzero(s, count);
80	} else {
81		__memset(s, c, count);
82	}
83	return s;
84}
85
86static inline void *__constant_c_memset(void *s, char c, __kernel_size_t count)
87{
88	extern __kernel_size_t __bzero(void *, __kernel_size_t);
89
90	if(!c)
91		__bzero(s, count);
92	else
93		__memset(s, c, count);
94	return s;
95}
96
97static inline void *__nonconstant_memset(void *s, char c, __kernel_size_t count)
98{
99	__memset(s, c, count);
100	return s;
101}
102
103#undef memset
104#define memset(s, c, count) \
105(__builtin_constant_p(c) ? (__builtin_constant_p(count) ? \
106                            __constant_c_and_count_memset((s), (c), (count)) : \
107                            __constant_c_memset((s), (c), (count))) \
108                          : __nonconstant_memset((s), (c), (count)))
109
110#define __HAVE_ARCH_MEMSCAN
111
112#undef memscan
113#define memscan(__arg0, __char, __arg2)						\
114({										\
115	extern void *__memscan_zero(void *, size_t);				\
116	extern void *__memscan_generic(void *, int, size_t);			\
117	void *__retval, *__addr = (__arg0);					\
118	size_t __size = (__arg2);						\
119										\
120	if(__builtin_constant_p(__char) && !(__char))				\
121		__retval = __memscan_zero(__addr, __size);			\
122	else									\
123		__retval = __memscan_generic(__addr, (__char), __size);		\
124										\
125	__retval;								\
126})
127
128#define __HAVE_ARCH_MEMCMP
129extern int memcmp(const void *,const void *,__kernel_size_t);
130
131/* Now the str*() stuff... */
132#define __HAVE_ARCH_STRLEN
133extern __kernel_size_t strlen(const char *);
134
135#define __HAVE_ARCH_STRNCMP
136
137extern int __strncmp(const char *, const char *, __kernel_size_t);
138
139static inline int __constant_strncmp(const char *src, const char *dest, __kernel_size_t count)
140{
141	register int retval;
142	switch(count) {
143	case 0: return 0;
144	case 1: return (src[0] - dest[0]);
145	case 2: retval = (src[0] - dest[0]);
146		if(!retval && src[0])
147		  retval = (src[1] - dest[1]);
148		return retval;
149	case 3: retval = (src[0] - dest[0]);
150		if(!retval && src[0]) {
151		  retval = (src[1] - dest[1]);
152		  if(!retval && src[1])
153		    retval = (src[2] - dest[2]);
154		}
155		return retval;
156	case 4: retval = (src[0] - dest[0]);
157		if(!retval && src[0]) {
158		  retval = (src[1] - dest[1]);
159		  if(!retval && src[1]) {
160		    retval = (src[2] - dest[2]);
161		    if (!retval && src[2])
162		      retval = (src[3] - dest[3]);
163		  }
164		}
165		return retval;
166	case 5: retval = (src[0] - dest[0]);
167		if(!retval && src[0]) {
168		  retval = (src[1] - dest[1]);
169		  if(!retval && src[1]) {
170		    retval = (src[2] - dest[2]);
171		    if (!retval && src[2]) {
172		      retval = (src[3] - dest[3]);
173		      if (!retval && src[3])
174		        retval = (src[4] - dest[4]);
175		    }
176		  }
177		}
178		return retval;
179	default:
180		retval = (src[0] - dest[0]);
181		if(!retval && src[0]) {
182		  retval = (src[1] - dest[1]);
183		  if(!retval && src[1]) {
184		    retval = (src[2] - dest[2]);
185		    if(!retval && src[2])
186		      retval = __strncmp(src+3,dest+3,count-3);
187		  }
188		}
189		return retval;
190	}
191}
192
193#undef strncmp
194#define strncmp(__arg0, __arg1, __arg2)	\
195(__builtin_constant_p(__arg2) ?	\
196 __constant_strncmp(__arg0, __arg1, __arg2) : \
197 __strncmp(__arg0, __arg1, __arg2))
198
199#endif /* !EXPORT_SYMTAB_STROPS */
200
201#endif /* __KERNEL__ */
202
203#endif /* !(__SPARC_STRING_H__) */
204