aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc/lib
diff options
context:
space:
mode:
Diffstat (limited to 'arch/ppc/lib')
-rw-r--r--arch/ppc/lib/Makefile5
-rw-r--r--arch/ppc/lib/checksum.S225
-rw-r--r--arch/ppc/lib/div64.S58
-rw-r--r--arch/ppc/lib/locks.c189
-rw-r--r--arch/ppc/lib/string.S732
5 files changed, 0 insertions, 1209 deletions
diff --git a/arch/ppc/lib/Makefile b/arch/ppc/lib/Makefile
deleted file mode 100644
index 095e661e79dd..000000000000
--- a/arch/ppc/lib/Makefile
+++ /dev/null
@@ -1,5 +0,0 @@
1#
2# Makefile for ppc-specific library files..
3#
4
5obj-y := checksum.o string.o div64.o
diff --git a/arch/ppc/lib/checksum.S b/arch/ppc/lib/checksum.S
deleted file mode 100644
index 7874e8a80455..000000000000
--- a/arch/ppc/lib/checksum.S
+++ /dev/null
@@ -1,225 +0,0 @@
1/*
2 * This file contains assembly-language implementations
3 * of IP-style 1's complement checksum routines.
4 *
5 * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org)
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License
9 * as published by the Free Software Foundation; either version
10 * 2 of the License, or (at your option) any later version.
11 *
12 * Severely hacked about by Paul Mackerras (paulus@cs.anu.edu.au).
13 */
14
15#include <linux/sys.h>
16#include <asm/processor.h>
17#include <asm/errno.h>
18#include <asm/ppc_asm.h>
19
20 .text
21
22/*
23 * ip_fast_csum(buf, len) -- Optimized for IP header
24 * len is in words and is always >= 5.
25 */
26_GLOBAL(ip_fast_csum)
27 lwz r0,0(r3)
28 lwzu r5,4(r3)
29 addic. r4,r4,-2
30 addc r0,r0,r5
31 mtctr r4
32 blelr-
331: lwzu r4,4(r3)
34 adde r0,r0,r4
35 bdnz 1b
36 addze r0,r0 /* add in final carry */
37 rlwinm r3,r0,16,0,31 /* fold two halves together */
38 add r3,r0,r3
39 not r3,r3
40 srwi r3,r3,16
41 blr
42
43/*
44 * Compute checksum of TCP or UDP pseudo-header:
45 * csum_tcpudp_magic(saddr, daddr, len, proto, sum)
46 */
47_GLOBAL(csum_tcpudp_magic)
48 rlwimi r5,r6,16,0,15 /* put proto in upper half of len */
49 addc r0,r3,r4 /* add 4 32-bit words together */
50 adde r0,r0,r5
51 adde r0,r0,r7
52 addze r0,r0 /* add in final carry */
53 rlwinm r3,r0,16,0,31 /* fold two halves together */
54 add r3,r0,r3
55 not r3,r3
56 srwi r3,r3,16
57 blr
58
59/*
60 * computes the checksum of a memory block at buff, length len,
61 * and adds in "sum" (32-bit)
62 *
63 * csum_partial(buff, len, sum)
64 */
65_GLOBAL(csum_partial)
66 addic r0,r5,0
67 subi r3,r3,4
68 srwi. r6,r4,2
69 beq 3f /* if we're doing < 4 bytes */
70 andi. r5,r3,2 /* Align buffer to longword boundary */
71 beq+ 1f
72 lhz r5,4(r3) /* do 2 bytes to get aligned */
73 addi r3,r3,2
74 subi r4,r4,2
75 addc r0,r0,r5
76 srwi. r6,r4,2 /* # words to do */
77 beq 3f
781: mtctr r6
792: lwzu r5,4(r3) /* the bdnz has zero overhead, so it should */
80 adde r0,r0,r5 /* be unnecessary to unroll this loop */
81 bdnz 2b
82 andi. r4,r4,3
833: cmpwi 0,r4,2
84 blt+ 4f
85 lhz r5,4(r3)
86 addi r3,r3,2
87 subi r4,r4,2
88 adde r0,r0,r5
894: cmpwi 0,r4,1
90 bne+ 5f
91 lbz r5,4(r3)
92 slwi r5,r5,8 /* Upper byte of word */
93 adde r0,r0,r5
945: addze r3,r0 /* add in final carry */
95 blr
96
97/*
98 * Computes the checksum of a memory block at src, length len,
99 * and adds in "sum" (32-bit), while copying the block to dst.
100 * If an access exception occurs on src or dst, it stores -EFAULT
101 * to *src_err or *dst_err respectively, and (for an error on
102 * src) zeroes the rest of dst.
103 *
104 * csum_partial_copy_generic(src, dst, len, sum, src_err, dst_err)
105 */
106_GLOBAL(csum_partial_copy_generic)
107 addic r0,r6,0
108 subi r3,r3,4
109 subi r4,r4,4
110 srwi. r6,r5,2
111 beq 3f /* if we're doing < 4 bytes */
112 andi. r9,r4,2 /* Align dst to longword boundary */
113 beq+ 1f
11481: lhz r6,4(r3) /* do 2 bytes to get aligned */
115 addi r3,r3,2
116 subi r5,r5,2
11791: sth r6,4(r4)
118 addi r4,r4,2
119 addc r0,r0,r6
120 srwi. r6,r5,2 /* # words to do */
121 beq 3f
1221: srwi. r6,r5,4 /* # groups of 4 words to do */
123 beq 10f
124 mtctr r6
12571: lwz r6,4(r3)
12672: lwz r9,8(r3)
12773: lwz r10,12(r3)
12874: lwzu r11,16(r3)
129 adde r0,r0,r6
13075: stw r6,4(r4)
131 adde r0,r0,r9
13276: stw r9,8(r4)
133 adde r0,r0,r10
13477: stw r10,12(r4)
135 adde r0,r0,r11
13678: stwu r11,16(r4)
137 bdnz 71b
13810: rlwinm. r6,r5,30,30,31 /* # words left to do */
139 beq 13f
140 mtctr r6
14182: lwzu r9,4(r3)
14292: stwu r9,4(r4)
143 adde r0,r0,r9
144 bdnz 82b
14513: andi. r5,r5,3
1463: cmpwi 0,r5,2
147 blt+ 4f
14883: lhz r6,4(r3)
149 addi r3,r3,2
150 subi r5,r5,2
15193: sth r6,4(r4)
152 addi r4,r4,2
153 adde r0,r0,r6
1544: cmpwi 0,r5,1
155 bne+ 5f
15684: lbz r6,4(r3)
15794: stb r6,4(r4)
158 slwi r6,r6,8 /* Upper byte of word */
159 adde r0,r0,r6
1605: addze r3,r0 /* add in final carry */
161 blr
162
163/* These shouldn't go in the fixup section, since that would
164 cause the ex_table addresses to get out of order. */
165
166src_error_4:
167 mfctr r6 /* update # bytes remaining from ctr */
168 rlwimi r5,r6,4,0,27
169 b 79f
170src_error_1:
171 li r6,0
172 subi r5,r5,2
17395: sth r6,4(r4)
174 addi r4,r4,2
17579: srwi. r6,r5,2
176 beq 3f
177 mtctr r6
178src_error_2:
179 li r6,0
18096: stwu r6,4(r4)
181 bdnz 96b
1823: andi. r5,r5,3
183 beq src_error
184src_error_3:
185 li r6,0
186 mtctr r5
187 addi r4,r4,3
18897: stbu r6,1(r4)
189 bdnz 97b
190src_error:
191 cmpwi 0,r7,0
192 beq 1f
193 li r6,-EFAULT
194 stw r6,0(r7)
1951: addze r3,r0
196 blr
197
198dst_error:
199 cmpwi 0,r8,0
200 beq 1f
201 li r6,-EFAULT
202 stw r6,0(r8)
2031: addze r3,r0
204 blr
205
206.section __ex_table,"a"
207 .long 81b,src_error_1
208 .long 91b,dst_error
209 .long 71b,src_error_4
210 .long 72b,src_error_4
211 .long 73b,src_error_4
212 .long 74b,src_error_4
213 .long 75b,dst_error
214 .long 76b,dst_error
215 .long 77b,dst_error
216 .long 78b,dst_error
217 .long 82b,src_error_2
218 .long 92b,dst_error
219 .long 83b,src_error_3
220 .long 93b,dst_error
221 .long 84b,src_error_3
222 .long 94b,dst_error
223 .long 95b,dst_error
224 .long 96b,dst_error
225 .long 97b,dst_error
diff --git a/arch/ppc/lib/div64.S b/arch/ppc/lib/div64.S
deleted file mode 100644
index 3527569e9926..000000000000
--- a/arch/ppc/lib/div64.S
+++ /dev/null
@@ -1,58 +0,0 @@
1/*
2 * Divide a 64-bit unsigned number by a 32-bit unsigned number.
3 * This routine assumes that the top 32 bits of the dividend are
4 * non-zero to start with.
5 * On entry, r3 points to the dividend, which get overwritten with
6 * the 64-bit quotient, and r4 contains the divisor.
7 * On exit, r3 contains the remainder.
8 *
9 * Copyright (C) 2002 Paul Mackerras, IBM Corp.
10 *
11 * This program is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU General Public License
13 * as published by the Free Software Foundation; either version
14 * 2 of the License, or (at your option) any later version.
15 */
16#include <asm/ppc_asm.h>
17#include <asm/processor.h>
18
19_GLOBAL(__div64_32)
20 lwz r5,0(r3) # get the dividend into r5/r6
21 lwz r6,4(r3)
22 cmplw r5,r4
23 li r7,0
24 li r8,0
25 blt 1f
26 divwu r7,r5,r4 # if dividend.hi >= divisor,
27 mullw r0,r7,r4 # quotient.hi = dividend.hi / divisor
28 subf. r5,r0,r5 # dividend.hi %= divisor
29 beq 3f
301: mr r11,r5 # here dividend.hi != 0
31 andis. r0,r5,0xc000
32 bne 2f
33 cntlzw r0,r5 # we are shifting the dividend right
34 li r10,-1 # to make it < 2^32, and shifting
35 srw r10,r10,r0 # the divisor right the same amount,
36 add r9,r4,r10 # rounding up (so the estimate cannot
37 andc r11,r6,r10 # ever be too large, only too small)
38 andc r9,r9,r10
39 or r11,r5,r11
40 rotlw r9,r9,r0
41 rotlw r11,r11,r0
42 divwu r11,r11,r9 # then we divide the shifted quantities
432: mullw r10,r11,r4 # to get an estimate of the quotient,
44 mulhwu r9,r11,r4 # multiply the estimate by the divisor,
45 subfc r6,r10,r6 # take the product from the divisor,
46 add r8,r8,r11 # and add the estimate to the accumulated
47 subfe. r5,r9,r5 # quotient
48 bne 1b
493: cmplw r6,r4
50 blt 4f
51 divwu r0,r6,r4 # perform the remaining 32-bit division
52 mullw r10,r0,r4 # and get the remainder
53 add r8,r8,r0
54 subf r6,r10,r6
554: stw r7,0(r3) # return the quotient in *r3
56 stw r8,4(r3)
57 mr r3,r6 # return the remainder in r3
58 blr
diff --git a/arch/ppc/lib/locks.c b/arch/ppc/lib/locks.c
deleted file mode 100644
index ea4aee6b20e6..000000000000
--- a/arch/ppc/lib/locks.c
+++ /dev/null
@@ -1,189 +0,0 @@
1/*
2 * Locks for smp ppc
3 *
4 * Written by Cort Dougan (cort@cs.nmt.edu)
5 */
6
7#include <linux/sched.h>
8#include <linux/spinlock.h>
9#include <linux/module.h>
10#include <asm/ppc_asm.h>
11#include <asm/smp.h>
12
13#ifdef CONFIG_DEBUG_SPINLOCK
14
15#undef INIT_STUCK
16#define INIT_STUCK 200000000 /*0xffffffff*/
17
18/*
19 * Try to acquire a spinlock.
20 * Only does the stwcx. if the load returned 0 - the Programming
21 * Environments Manual suggests not doing unnecessary stcwx.'s
22 * since they may inhibit forward progress by other CPUs in getting
23 * a lock.
24 */
25static inline unsigned long __spin_trylock(volatile unsigned long *lock)
26{
27 unsigned long ret;
28
29 __asm__ __volatile__ ("\n\
301: lwarx %0,0,%1\n\
31 cmpwi 0,%0,0\n\
32 bne 2f\n"
33 PPC405_ERR77(0,%1)
34" stwcx. %2,0,%1\n\
35 bne- 1b\n\
36 isync\n\
372:"
38 : "=&r"(ret)
39 : "r"(lock), "r"(1)
40 : "cr0", "memory");
41
42 return ret;
43}
44
45void _raw_spin_lock(spinlock_t *lock)
46{
47 int cpu = smp_processor_id();
48 unsigned int stuck = INIT_STUCK;
49 while (__spin_trylock(&lock->lock)) {
50 while ((unsigned volatile long)lock->lock != 0) {
51 if (!--stuck) {
52 printk("_spin_lock(%p) CPU#%d NIP %p"
53 " holder: cpu %ld pc %08lX\n",
54 lock, cpu, __builtin_return_address(0),
55 lock->owner_cpu,lock->owner_pc);
56 stuck = INIT_STUCK;
57 /* steal the lock */
58 /*xchg_u32((void *)&lock->lock,0);*/
59 }
60 }
61 }
62 lock->owner_pc = (unsigned long)__builtin_return_address(0);
63 lock->owner_cpu = cpu;
64}
65EXPORT_SYMBOL(_raw_spin_lock);
66
67int _raw_spin_trylock(spinlock_t *lock)
68{
69 if (__spin_trylock(&lock->lock))
70 return 0;
71 lock->owner_cpu = smp_processor_id();
72 lock->owner_pc = (unsigned long)__builtin_return_address(0);
73 return 1;
74}
75EXPORT_SYMBOL(_raw_spin_trylock);
76
77void _raw_spin_unlock(spinlock_t *lp)
78{
79 if ( !lp->lock )
80 printk("_spin_unlock(%p): no lock cpu %d curr PC %p %s/%d\n",
81 lp, smp_processor_id(), __builtin_return_address(0),
82 current->comm, current->pid);
83 if ( lp->owner_cpu != smp_processor_id() )
84 printk("_spin_unlock(%p): cpu %d trying clear of cpu %d pc %lx val %lx\n",
85 lp, smp_processor_id(), (int)lp->owner_cpu,
86 lp->owner_pc,lp->lock);
87 lp->owner_pc = lp->owner_cpu = 0;
88 wmb();
89 lp->lock = 0;
90}
91EXPORT_SYMBOL(_raw_spin_unlock);
92
93/*
94 * For rwlocks, zero is unlocked, -1 is write-locked,
95 * positive is read-locked.
96 */
97static __inline__ int __read_trylock(rwlock_t *rw)
98{
99 signed int tmp;
100
101 __asm__ __volatile__(
102"2: lwarx %0,0,%1 # __read_trylock\n\
103 addic. %0,%0,1\n\
104 ble- 1f\n"
105 PPC405_ERR77(0,%1)
106" stwcx. %0,0,%1\n\
107 bne- 2b\n\
108 isync\n\
1091:"
110 : "=&r"(tmp)
111 : "r"(&rw->lock)
112 : "cr0", "memory");
113
114 return tmp;
115}
116
117int _raw_read_trylock(rwlock_t *rw)
118{
119 return __read_trylock(rw) > 0;
120}
121EXPORT_SYMBOL(_raw_read_trylock);
122
123void _raw_read_lock(rwlock_t *rw)
124{
125 unsigned int stuck;
126
127 while (__read_trylock(rw) <= 0) {
128 stuck = INIT_STUCK;
129 while (!read_can_lock(rw)) {
130 if (--stuck == 0) {
131 printk("_read_lock(%p) CPU#%d lock %d\n",
132 rw, raw_smp_processor_id(), rw->lock);
133 stuck = INIT_STUCK;
134 }
135 }
136 }
137}
138EXPORT_SYMBOL(_raw_read_lock);
139
140void _raw_read_unlock(rwlock_t *rw)
141{
142 if ( rw->lock == 0 )
143 printk("_read_unlock(): %s/%d (nip %08lX) lock %d\n",
144 current->comm,current->pid,current->thread.regs->nip,
145 rw->lock);
146 wmb();
147 atomic_dec((atomic_t *) &(rw)->lock);
148}
149EXPORT_SYMBOL(_raw_read_unlock);
150
151void _raw_write_lock(rwlock_t *rw)
152{
153 unsigned int stuck;
154
155 while (cmpxchg(&rw->lock, 0, -1) != 0) {
156 stuck = INIT_STUCK;
157 while (!write_can_lock(rw)) {
158 if (--stuck == 0) {
159 printk("write_lock(%p) CPU#%d lock %d)\n",
160 rw, raw_smp_processor_id(), rw->lock);
161 stuck = INIT_STUCK;
162 }
163 }
164 }
165 wmb();
166}
167EXPORT_SYMBOL(_raw_write_lock);
168
169int _raw_write_trylock(rwlock_t *rw)
170{
171 if (cmpxchg(&rw->lock, 0, -1) != 0)
172 return 0;
173 wmb();
174 return 1;
175}
176EXPORT_SYMBOL(_raw_write_trylock);
177
178void _raw_write_unlock(rwlock_t *rw)
179{
180 if (rw->lock >= 0)
181 printk("_write_lock(): %s/%d (nip %08lX) lock %d\n",
182 current->comm,current->pid,current->thread.regs->nip,
183 rw->lock);
184 wmb();
185 rw->lock = 0;
186}
187EXPORT_SYMBOL(_raw_write_unlock);
188
189#endif
diff --git a/arch/ppc/lib/string.S b/arch/ppc/lib/string.S
deleted file mode 100644
index 927253bfc826..000000000000
--- a/arch/ppc/lib/string.S
+++ /dev/null
@@ -1,732 +0,0 @@
1/*
2 * String handling functions for PowerPC.
3 *
4 * Copyright (C) 1996 Paul Mackerras.
5 *
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License
8 * as published by the Free Software Foundation; either version
9 * 2 of the License, or (at your option) any later version.
10 */
11#include <asm/processor.h>
12#include <asm/cache.h>
13#include <asm/errno.h>
14#include <asm/ppc_asm.h>
15
16#define COPY_16_BYTES \
17 lwz r7,4(r4); \
18 lwz r8,8(r4); \
19 lwz r9,12(r4); \
20 lwzu r10,16(r4); \
21 stw r7,4(r6); \
22 stw r8,8(r6); \
23 stw r9,12(r6); \
24 stwu r10,16(r6)
25
26#define COPY_16_BYTES_WITHEX(n) \
278 ## n ## 0: \
28 lwz r7,4(r4); \
298 ## n ## 1: \
30 lwz r8,8(r4); \
318 ## n ## 2: \
32 lwz r9,12(r4); \
338 ## n ## 3: \
34 lwzu r10,16(r4); \
358 ## n ## 4: \
36 stw r7,4(r6); \
378 ## n ## 5: \
38 stw r8,8(r6); \
398 ## n ## 6: \
40 stw r9,12(r6); \
418 ## n ## 7: \
42 stwu r10,16(r6)
43
44#define COPY_16_BYTES_EXCODE(n) \
459 ## n ## 0: \
46 addi r5,r5,-(16 * n); \
47 b 104f; \
489 ## n ## 1: \
49 addi r5,r5,-(16 * n); \
50 b 105f; \
51.section __ex_table,"a"; \
52 .align 2; \
53 .long 8 ## n ## 0b,9 ## n ## 0b; \
54 .long 8 ## n ## 1b,9 ## n ## 0b; \
55 .long 8 ## n ## 2b,9 ## n ## 0b; \
56 .long 8 ## n ## 3b,9 ## n ## 0b; \
57 .long 8 ## n ## 4b,9 ## n ## 1b; \
58 .long 8 ## n ## 5b,9 ## n ## 1b; \
59 .long 8 ## n ## 6b,9 ## n ## 1b; \
60 .long 8 ## n ## 7b,9 ## n ## 1b; \
61 .text
62
63 .text
64 .stabs "arch/ppc/lib/",N_SO,0,0,0f
65 .stabs "string.S",N_SO,0,0,0f
66
67CACHELINE_BYTES = L1_CACHE_BYTES
68LG_CACHELINE_BYTES = L1_CACHE_SHIFT
69CACHELINE_MASK = (L1_CACHE_BYTES-1)
70
71_GLOBAL(strcpy)
72 addi r5,r3,-1
73 addi r4,r4,-1
741: lbzu r0,1(r4)
75 cmpwi 0,r0,0
76 stbu r0,1(r5)
77 bne 1b
78 blr
79
80/* This clears out any unused part of the destination buffer,
81 just as the libc version does. -- paulus */
82_GLOBAL(strncpy)
83 cmpwi 0,r5,0
84 beqlr
85 mtctr r5
86 addi r6,r3,-1
87 addi r4,r4,-1
881: lbzu r0,1(r4)
89 cmpwi 0,r0,0
90 stbu r0,1(r6)
91 bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
92 bnelr /* if we didn't hit a null char, we're done */
93 mfctr r5
94 cmpwi 0,r5,0 /* any space left in destination buffer? */
95 beqlr /* we know r0 == 0 here */
962: stbu r0,1(r6) /* clear it out if so */
97 bdnz 2b
98 blr
99
100_GLOBAL(strcat)
101 addi r5,r3,-1
102 addi r4,r4,-1
1031: lbzu r0,1(r5)
104 cmpwi 0,r0,0
105 bne 1b
106 addi r5,r5,-1
1071: lbzu r0,1(r4)
108 cmpwi 0,r0,0
109 stbu r0,1(r5)
110 bne 1b
111 blr
112
113_GLOBAL(strcmp)
114 addi r5,r3,-1
115 addi r4,r4,-1
1161: lbzu r3,1(r5)
117 cmpwi 1,r3,0
118 lbzu r0,1(r4)
119 subf. r3,r0,r3
120 beqlr 1
121 beq 1b
122 blr
123
124_GLOBAL(strncmp)
125 PPC_LCMPI r5,0
126 beqlr
127 mtctr r5
128 addi r5,r3,-1
129 addi r4,r4,-1
1301: lbzu r3,1(r5)
131 cmpwi 1,r3,0
132 lbzu r0,1(r4)
133 subf. r3,r0,r3
134 beqlr 1
135 bdnzt eq,1b
136 blr
137
138_GLOBAL(strlen)
139 addi r4,r3,-1
1401: lbzu r0,1(r4)
141 cmpwi 0,r0,0
142 bne 1b
143 subf r3,r3,r4
144 blr
145
146/*
147 * Use dcbz on the complete cache lines in the destination
148 * to set them to zero. This requires that the destination
149 * area is cacheable. -- paulus
150 */
151_GLOBAL(cacheable_memzero)
152 mr r5,r4
153 li r4,0
154 addi r6,r3,-4
155 cmplwi 0,r5,4
156 blt 7f
157 stwu r4,4(r6)
158 beqlr
159 andi. r0,r6,3
160 add r5,r0,r5
161 subf r6,r0,r6
162 clrlwi r7,r6,32-LG_CACHELINE_BYTES
163 add r8,r7,r5
164 srwi r9,r8,LG_CACHELINE_BYTES
165 addic. r9,r9,-1 /* total number of complete cachelines */
166 ble 2f
167 xori r0,r7,CACHELINE_MASK & ~3
168 srwi. r0,r0,2
169 beq 3f
170 mtctr r0
1714: stwu r4,4(r6)
172 bdnz 4b
1733: mtctr r9
174 li r7,4
175#if !defined(CONFIG_8xx)
17610: dcbz r7,r6
177#else
17810: stw r4, 4(r6)
179 stw r4, 8(r6)
180 stw r4, 12(r6)
181 stw r4, 16(r6)
182#if CACHE_LINE_SIZE >= 32
183 stw r4, 20(r6)
184 stw r4, 24(r6)
185 stw r4, 28(r6)
186 stw r4, 32(r6)
187#endif /* CACHE_LINE_SIZE */
188#endif
189 addi r6,r6,CACHELINE_BYTES
190 bdnz 10b
191 clrlwi r5,r8,32-LG_CACHELINE_BYTES
192 addi r5,r5,4
1932: srwi r0,r5,2
194 mtctr r0
195 bdz 6f
1961: stwu r4,4(r6)
197 bdnz 1b
1986: andi. r5,r5,3
1997: cmpwi 0,r5,0
200 beqlr
201 mtctr r5
202 addi r6,r6,3
2038: stbu r4,1(r6)
204 bdnz 8b
205 blr
206
207_GLOBAL(memset)
208 rlwimi r4,r4,8,16,23
209 rlwimi r4,r4,16,0,15
210 addi r6,r3,-4
211 cmplwi 0,r5,4
212 blt 7f
213 stwu r4,4(r6)
214 beqlr
215 andi. r0,r6,3
216 add r5,r0,r5
217 subf r6,r0,r6
218 srwi r0,r5,2
219 mtctr r0
220 bdz 6f
2211: stwu r4,4(r6)
222 bdnz 1b
2236: andi. r5,r5,3
2247: cmpwi 0,r5,0
225 beqlr
226 mtctr r5
227 addi r6,r6,3
2288: stbu r4,1(r6)
229 bdnz 8b
230 blr
231
232/*
233 * This version uses dcbz on the complete cache lines in the
234 * destination area to reduce memory traffic. This requires that
235 * the destination area is cacheable.
236 * We only use this version if the source and dest don't overlap.
237 * -- paulus.
238 */
239_GLOBAL(cacheable_memcpy)
240 add r7,r3,r5 /* test if the src & dst overlap */
241 add r8,r4,r5
242 cmplw 0,r4,r7
243 cmplw 1,r3,r8
244 crand 0,0,4 /* cr0.lt &= cr1.lt */
245 blt memcpy /* if regions overlap */
246
247 addi r4,r4,-4
248 addi r6,r3,-4
249 neg r0,r3
250 andi. r0,r0,CACHELINE_MASK /* # bytes to start of cache line */
251 beq 58f
252
253 cmplw 0,r5,r0 /* is this more than total to do? */
254 blt 63f /* if not much to do */
255 andi. r8,r0,3 /* get it word-aligned first */
256 subf r5,r0,r5
257 mtctr r8
258 beq+ 61f
25970: lbz r9,4(r4) /* do some bytes */
260 stb r9,4(r6)
261 addi r4,r4,1
262 addi r6,r6,1
263 bdnz 70b
26461: srwi. r0,r0,2
265 mtctr r0
266 beq 58f
26772: lwzu r9,4(r4) /* do some words */
268 stwu r9,4(r6)
269 bdnz 72b
270
27158: srwi. r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
272 clrlwi r5,r5,32-LG_CACHELINE_BYTES
273 li r11,4
274 mtctr r0
275 beq 63f
27653:
277#if !defined(CONFIG_8xx)
278 dcbz r11,r6
279#endif
280 COPY_16_BYTES
281#if L1_CACHE_BYTES >= 32
282 COPY_16_BYTES
283#if L1_CACHE_BYTES >= 64
284 COPY_16_BYTES
285 COPY_16_BYTES
286#if L1_CACHE_BYTES >= 128
287 COPY_16_BYTES
288 COPY_16_BYTES
289 COPY_16_BYTES
290 COPY_16_BYTES
291#endif
292#endif
293#endif
294 bdnz 53b
295
29663: srwi. r0,r5,2
297 mtctr r0
298 beq 64f
29930: lwzu r0,4(r4)
300 stwu r0,4(r6)
301 bdnz 30b
302
30364: andi. r0,r5,3
304 mtctr r0
305 beq+ 65f
30640: lbz r0,4(r4)
307 stb r0,4(r6)
308 addi r4,r4,1
309 addi r6,r6,1
310 bdnz 40b
31165: blr
312
313_GLOBAL(memmove)
314 cmplw 0,r3,r4
315 bgt backwards_memcpy
316 /* fall through */
317
318_GLOBAL(memcpy)
319 srwi. r7,r5,3
320 addi r6,r3,-4
321 addi r4,r4,-4
322 beq 2f /* if less than 8 bytes to do */
323 andi. r0,r6,3 /* get dest word aligned */
324 mtctr r7
325 bne 5f
3261: lwz r7,4(r4)
327 lwzu r8,8(r4)
328 stw r7,4(r6)
329 stwu r8,8(r6)
330 bdnz 1b
331 andi. r5,r5,7
3322: cmplwi 0,r5,4
333 blt 3f
334 lwzu r0,4(r4)
335 addi r5,r5,-4
336 stwu r0,4(r6)
3373: cmpwi 0,r5,0
338 beqlr
339 mtctr r5
340 addi r4,r4,3
341 addi r6,r6,3
3424: lbzu r0,1(r4)
343 stbu r0,1(r6)
344 bdnz 4b
345 blr
3465: subfic r0,r0,4
347 mtctr r0
3486: lbz r7,4(r4)
349 addi r4,r4,1
350 stb r7,4(r6)
351 addi r6,r6,1
352 bdnz 6b
353 subf r5,r0,r5
354 rlwinm. r7,r5,32-3,3,31
355 beq 2b
356 mtctr r7
357 b 1b
358
359_GLOBAL(backwards_memcpy)
360 rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
361 add r6,r3,r5
362 add r4,r4,r5
363 beq 2f
364 andi. r0,r6,3
365 mtctr r7
366 bne 5f
3671: lwz r7,-4(r4)
368 lwzu r8,-8(r4)
369 stw r7,-4(r6)
370 stwu r8,-8(r6)
371 bdnz 1b
372 andi. r5,r5,7
3732: cmplwi 0,r5,4
374 blt 3f
375 lwzu r0,-4(r4)
376 subi r5,r5,4
377 stwu r0,-4(r6)
3783: cmpwi 0,r5,0
379 beqlr
380 mtctr r5
3814: lbzu r0,-1(r4)
382 stbu r0,-1(r6)
383 bdnz 4b
384 blr
3855: mtctr r0
3866: lbzu r7,-1(r4)
387 stbu r7,-1(r6)
388 bdnz 6b
389 subf r5,r0,r5
390 rlwinm. r7,r5,32-3,3,31
391 beq 2b
392 mtctr r7
393 b 1b
394
395_GLOBAL(memcmp)
396 cmpwi 0,r5,0
397 ble- 2f
398 mtctr r5
399 addi r6,r3,-1
400 addi r4,r4,-1
4011: lbzu r3,1(r6)
402 lbzu r0,1(r4)
403 subf. r3,r0,r3
404 bdnzt 2,1b
405 blr
4062: li r3,0
407 blr
408
409_GLOBAL(memchr)
410 cmpwi 0,r5,0
411 ble- 2f
412 mtctr r5
413 addi r3,r3,-1
4141: lbzu r0,1(r3)
415 cmpw 0,r0,r4
416 bdnzf 2,1b
417 beqlr
4182: li r3,0
419 blr
420
421_GLOBAL(__copy_tofrom_user)
422 addi r4,r4,-4
423 addi r6,r3,-4
424 neg r0,r3
425 andi. r0,r0,CACHELINE_MASK /* # bytes to start of cache line */
426 beq 58f
427
428 cmplw 0,r5,r0 /* is this more than total to do? */
429 blt 63f /* if not much to do */
430 andi. r8,r0,3 /* get it word-aligned first */
431 mtctr r8
432 beq+ 61f
43370: lbz r9,4(r4) /* do some bytes */
43471: stb r9,4(r6)
435 addi r4,r4,1
436 addi r6,r6,1
437 bdnz 70b
43861: subf r5,r0,r5
439 srwi. r0,r0,2
440 mtctr r0
441 beq 58f
44272: lwzu r9,4(r4) /* do some words */
44373: stwu r9,4(r6)
444 bdnz 72b
445
446 .section __ex_table,"a"
447 .align 2
448 .long 70b,100f
449 .long 71b,101f
450 .long 72b,102f
451 .long 73b,103f
452 .text
453
45458: srwi. r0,r5,LG_CACHELINE_BYTES /* # complete cachelines */
455 clrlwi r5,r5,32-LG_CACHELINE_BYTES
456 li r11,4
457 beq 63f
458
459#ifdef CONFIG_8xx
460 /* Don't use prefetch on 8xx */
461 mtctr r0
462 li r0,0
46353: COPY_16_BYTES_WITHEX(0)
464 bdnz 53b
465
466#else /* not CONFIG_8xx */
467 /* Here we decide how far ahead to prefetch the source */
468 li r3,4
469 cmpwi r0,1
470 li r7,0
471 ble 114f
472 li r7,1
473#if MAX_COPY_PREFETCH > 1
474 /* Heuristically, for large transfers we prefetch
475 MAX_COPY_PREFETCH cachelines ahead. For small transfers
476 we prefetch 1 cacheline ahead. */
477 cmpwi r0,MAX_COPY_PREFETCH
478 ble 112f
479 li r7,MAX_COPY_PREFETCH
480112: mtctr r7
481111: dcbt r3,r4
482 addi r3,r3,CACHELINE_BYTES
483 bdnz 111b
484#else
485 dcbt r3,r4
486 addi r3,r3,CACHELINE_BYTES
487#endif /* MAX_COPY_PREFETCH > 1 */
488
489114: subf r8,r7,r0
490 mr r0,r7
491 mtctr r8
492
49353: dcbt r3,r4
49454: dcbz r11,r6
495 .section __ex_table,"a"
496 .align 2
497 .long 54b,105f
498 .text
499/* the main body of the cacheline loop */
500 COPY_16_BYTES_WITHEX(0)
501#if L1_CACHE_BYTES >= 32
502 COPY_16_BYTES_WITHEX(1)
503#if L1_CACHE_BYTES >= 64
504 COPY_16_BYTES_WITHEX(2)
505 COPY_16_BYTES_WITHEX(3)
506#if L1_CACHE_BYTES >= 128
507 COPY_16_BYTES_WITHEX(4)
508 COPY_16_BYTES_WITHEX(5)
509 COPY_16_BYTES_WITHEX(6)
510 COPY_16_BYTES_WITHEX(7)
511#endif
512#endif
513#endif
514 bdnz 53b
515 cmpwi r0,0
516 li r3,4
517 li r7,0
518 bne 114b
519#endif /* CONFIG_8xx */
520
52163: srwi. r0,r5,2
522 mtctr r0
523 beq 64f
52430: lwzu r0,4(r4)
52531: stwu r0,4(r6)
526 bdnz 30b
527
52864: andi. r0,r5,3
529 mtctr r0
530 beq+ 65f
53140: lbz r0,4(r4)
53241: stb r0,4(r6)
533 addi r4,r4,1
534 addi r6,r6,1
535 bdnz 40b
53665: li r3,0
537 blr
538
539/* read fault, initial single-byte copy */
540100: li r9,0
541 b 90f
542/* write fault, initial single-byte copy */
543101: li r9,1
54490: subf r5,r8,r5
545 li r3,0
546 b 99f
547/* read fault, initial word copy */
548102: li r9,0
549 b 91f
550/* write fault, initial word copy */
551103: li r9,1
55291: li r3,2
553 b 99f
554
555/*
556 * this stuff handles faults in the cacheline loop and branches to either
557 * 104f (if in read part) or 105f (if in write part), after updating r5
558 */
559 COPY_16_BYTES_EXCODE(0)
560#if L1_CACHE_BYTES >= 32
561 COPY_16_BYTES_EXCODE(1)
562#if L1_CACHE_BYTES >= 64
563 COPY_16_BYTES_EXCODE(2)
564 COPY_16_BYTES_EXCODE(3)
565#if L1_CACHE_BYTES >= 128
566 COPY_16_BYTES_EXCODE(4)
567 COPY_16_BYTES_EXCODE(5)
568 COPY_16_BYTES_EXCODE(6)
569 COPY_16_BYTES_EXCODE(7)
570#endif
571#endif
572#endif
573
574/* read fault in cacheline loop */
575104: li r9,0
576 b 92f
577/* fault on dcbz (effectively a write fault) */
578/* or write fault in cacheline loop */
579105: li r9,1
58092: li r3,LG_CACHELINE_BYTES
581 mfctr r8
582 add r0,r0,r8
583 b 106f
584/* read fault in final word loop */
585108: li r9,0
586 b 93f
587/* write fault in final word loop */
588109: li r9,1
58993: andi. r5,r5,3
590 li r3,2
591 b 99f
592/* read fault in final byte loop */
593110: li r9,0
594 b 94f
595/* write fault in final byte loop */
596111: li r9,1
59794: li r5,0
598 li r3,0
599/*
600 * At this stage the number of bytes not copied is
601 * r5 + (ctr << r3), and r9 is 0 for read or 1 for write.
602 */
60399: mfctr r0
604106: slw r3,r0,r3
605 add. r3,r3,r5
606 beq 120f /* shouldn't happen */
607 cmpwi 0,r9,0
608 bne 120f
609/* for a read fault, first try to continue the copy one byte at a time */
610 mtctr r3
611130: lbz r0,4(r4)
612131: stb r0,4(r6)
613 addi r4,r4,1
614 addi r6,r6,1
615 bdnz 130b
616/* then clear out the destination: r3 bytes starting at 4(r6) */
617132: mfctr r3
618 srwi. r0,r3,2
619 li r9,0
620 mtctr r0
621 beq 113f
622112: stwu r9,4(r6)
623 bdnz 112b
624113: andi. r0,r3,3
625 mtctr r0
626 beq 120f
627114: stb r9,4(r6)
628 addi r6,r6,1
629 bdnz 114b
630120: blr
631
632 .section __ex_table,"a"
633 .align 2
634 .long 30b,108b
635 .long 31b,109b
636 .long 40b,110b
637 .long 41b,111b
638 .long 130b,132b
639 .long 131b,120b
640 .long 112b,120b
641 .long 114b,120b
642 .text
643
644_GLOBAL(__clear_user)
645 addi r6,r3,-4
646 li r3,0
647 li r5,0
648 cmplwi 0,r4,4
649 blt 7f
650 /* clear a single word */
65111: stwu r5,4(r6)
652 beqlr
653 /* clear word sized chunks */
654 andi. r0,r6,3
655 add r4,r0,r4
656 subf r6,r0,r6
657 srwi r0,r4,2
658 andi. r4,r4,3
659 mtctr r0
660 bdz 7f
6611: stwu r5,4(r6)
662 bdnz 1b
663 /* clear byte sized chunks */
6647: cmpwi 0,r4,0
665 beqlr
666 mtctr r4
667 addi r6,r6,3
6688: stbu r5,1(r6)
669 bdnz 8b
670 blr
67190: mr r3,r4
672 blr
67391: mfctr r3
674 slwi r3,r3,2
675 add r3,r3,r4
676 blr
67792: mfctr r3
678 blr
679
680 .section __ex_table,"a"
681 .align 2
682 .long 11b,90b
683 .long 1b,91b
684 .long 8b,92b
685 .text
686
687_GLOBAL(__strncpy_from_user)
688 addi r6,r3,-1
689 addi r4,r4,-1
690 cmpwi 0,r5,0
691 beq 2f
692 mtctr r5
6931: lbzu r0,1(r4)
694 cmpwi 0,r0,0
695 stbu r0,1(r6)
696 bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
697 beq 3f
6982: addi r6,r6,1
6993: subf r3,r3,r6
700 blr
70199: li r3,-EFAULT
702 blr
703
704 .section __ex_table,"a"
705 .align 2
706 .long 1b,99b
707 .text
708
709/* r3 = str, r4 = len (> 0), r5 = top (highest addr) */
710_GLOBAL(__strnlen_user)
711 addi r7,r3,-1
712 subf r6,r7,r5 /* top+1 - str */
713 cmplw 0,r4,r6
714 bge 0f
715 mr r6,r4
7160: mtctr r6 /* ctr = min(len, top - str) */
7171: lbzu r0,1(r7) /* get next byte */
718 cmpwi 0,r0,0
719 bdnzf 2,1b /* loop if --ctr != 0 && byte != 0 */
720 addi r7,r7,1
721 subf r3,r3,r7 /* number of bytes we have looked at */
722 beqlr /* return if we found a 0 byte */
723 cmpw 0,r3,r4 /* did we look at all len bytes? */
724 blt 99f /* if not, must have hit top */
725 addi r3,r4,1 /* return len + 1 to indicate no null found */
726 blr
72799: li r3,0 /* bad address, return 0 */
728 blr
729
730 .section __ex_table,"a"
731 .align 2
732 .long 1b,99b