2 * This program is free software; you can redistribute it and/or modify it under
3 * the terms of the GNU Library General Public License as published by the Free
4 * Software Foundation; either version 2 of the License, or (at your option) any
7 * This program is distributed in the hope that it will be useful, but WITHOUT
8 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
9 * FOR A PARTICULAR PURPOSE. See the GNU Library General Public License for more
13 /* These are carefully optimized mem*() functions for PPC written in C.
14 * Don't muck around with these function without checking the generated
16 * It is possible to optimize these significantly more by using specific
17 * data cache instructions(mainly dcbz). However that requires knownledge
18 * about the CPU's cache line size.
21 * The cache instructions on MPC8xx CPU's are buggy(they don't update
22 * the DAR register when causing a DTLB Miss/Error) and cannot be
23 * used on 8xx CPU's without a kernel patch to work around this
26 * Copyright (C) 2004 Joakim Tjernlund
29 #define _STDIO_UTILITY
32 #include <locale.h> /* for __LOCALE_C_ONLY */
35 void *memcpy(void *to, const void *from, size_t n)
36 /* PPC can do pre increment and load/store, but not post increment and load/store.
37 Therefore use *++ptr instead of *ptr++. */
39 unsigned long rem, chunks, tmp1, tmp2;
47 rem = (unsigned long )tmp_to % 4;
52 /* make gcc to load all data, then store it */
53 tmp1 = *(unsigned long *)(from+4);
55 tmp2 = *(unsigned long *)from;
56 *(unsigned long *)(tmp_to+4) = tmp1;
58 *(unsigned long *)tmp_to = tmp2;
63 *++(unsigned long *)tmp_to = *++(unsigned long *)from;
70 *++(unsigned char *)tmp_to = *++(unsigned char *)from;
78 *(unsigned char *)(tmp_to+4) = *(unsigned char *)(from+4);
90 void *memmove(void *to, const void *from, size_t n)
92 unsigned long rem, chunks, tmp1, tmp2;
96 return memcpy(to, from, n);
102 rem = (unsigned long )tmp_to % 4;
107 /* make gcc to load all data, then store it */
108 tmp1 = *(unsigned long *)(from-4);
110 tmp2 = *(unsigned long *)from;
111 *(unsigned long *)(tmp_to-4) = tmp1;
113 *(unsigned long *)tmp_to = tmp2;
118 *--(unsigned long *)tmp_to = *--(unsigned long *)from;
123 *--(unsigned char *)tmp_to = *--(unsigned char *)from;
131 *--(unsigned char *)tmp_to = *--(unsigned char *)from;
141 static inline int expand_byte_word(int c){
146 asm("rlwimi %0,%0,8,16,23\n"
147 "\trlwimi %0,%0,16,0,15\n"
148 : "=r" (c) : "0" (c));
151 void *memset(void *to, int c, size_t n)
153 unsigned long rem, chunks;
158 c = expand_byte_word(c);
161 rem = (unsigned long )tmp_to % 4;
166 *++(unsigned long *)tmp_to = c;
167 *++(unsigned long *)tmp_to = c;
172 *++(unsigned long *)tmp_to = c;
178 *++(unsigned char *)tmp_to = c;
186 *(unsigned char *)(tmp_to+4) = c;
197 weak_alias(__bzero,bzero);
198 void __bzero(void *s, size_t n)
200 (void)memset(s, 0, n);