1 /*
2  * Copyright (C) 2004 Joakim Tjernlund
3  * Copyright (C) 2000-2005 Erik Andersen <andersen@uclibc.org>
4  *
5  * Licensed under the LGPL v2.1, see the file COPYING.LIB in this tarball.
6  */
7 
8 /* These are carefully optimized mem*() functions for PPC written in C.
9  * Don't muck around with these function without checking the generated
10  * assembler code.
11  * It is possible to optimize these significantly more by using specific
12  * data cache instructions(mainly dcbz). However that requires knownledge
13  * about the CPU's cache line size.
14  *
15  * BUG ALERT!
16  * The cache instructions on MPC8xx CPU's are buggy(they don't update
17  * the DAR register when causing a DTLB Miss/Error) and cannot be
18  * used on 8xx CPU's without a kernel patch to work around this
19  * problem.
20  */
21 
22 #include <string.h>
23 
24 
expand_byte_word(int c)25 static __inline__ int expand_byte_word(int c){
26 	/* this does:
27 	   c = c << 8 | c;
28 	   c = c << 16 | c ;
29 	*/
30 	__asm__("rlwimi	%0,%0,8,16,23\n"
31 	    "\trlwimi	%0,%0,16,0,15\n"
32 	    : "=r" (c) : "0" (c));
33 	return c;
34 }
35 
memset(void * to,int c,size_t n)36 void *memset(void *to, int c, size_t n)
37 {
38 	unsigned long rem, chunks;
39 	unsigned char *tmp_to;
40 
41 	chunks = n / 8;
42 	tmp_to = to - 4;
43 	c = expand_byte_word(c);
44 	if (!chunks)
45 		goto lessthan8;
46 	rem = (unsigned long )tmp_to % 4;
47 	if (rem)
48 		goto align;
49  copy_chunks:
50 	do {
51 		*(unsigned long *)(tmp_to+4) = c;
52 		tmp_to += 4;
53 		*(unsigned long *)(tmp_to+4) = c;
54 		tmp_to += 4;
55 	} while (--chunks);
56  lessthan8:
57 	n = n % 8;
58 	if (n >= 4) {
59 		*(unsigned long *)(tmp_to+4) = c;
60 		tmp_to += 4;
61 		n = n-4;
62 	}
63 	if (!n ) return to;
64 	tmp_to += 3;
65 	do {
66 		*++tmp_to = c;
67 	} while (--n);
68 
69 	return to;
70  align:
71 	rem = 4 - rem;
72 	n = n-rem;
73 	do {
74 		*(tmp_to+4) = c;
75 		++tmp_to;
76 	} while (--rem);
77 	chunks = n / 8;
78 	if (chunks)
79 		goto copy_chunks;
80 	goto lessthan8;
81 }
82 libc_hidden_def(memset)
83