aboutsummaryrefslogtreecommitdiffstats
path: root/arch/ppc64/lib
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
committerLinus Torvalds <torvalds@ppc970.osdl.org>2005-04-16 18:20:36 -0400
commit1da177e4c3f41524e886b7f1b8a0c1fc7321cac2 (patch)
tree0bba044c4ce775e45a88a51686b5d9f90697ea9d /arch/ppc64/lib
Linux-2.6.12-rc2v2.6.12-rc2
Initial git repository build. I'm not bothering with the full history, even though we have it. We can create a separate "historical" git archive of that later if we want to, and in the meantime it's about 3.2GB when imported into git - space that would just make the early git days unnecessarily complicated, when we don't have a lot of good infrastructure for it. Let it rip!
Diffstat (limited to 'arch/ppc64/lib')
-rw-r--r--arch/ppc64/lib/Makefile18
-rw-r--r--arch/ppc64/lib/checksum.S229
-rw-r--r--arch/ppc64/lib/copypage.S121
-rw-r--r--arch/ppc64/lib/copyuser.S576
-rw-r--r--arch/ppc64/lib/dec_and_lock.c55
-rw-r--r--arch/ppc64/lib/e2a.c108
-rw-r--r--arch/ppc64/lib/locks.c95
-rw-r--r--arch/ppc64/lib/memcpy.S172
-rw-r--r--arch/ppc64/lib/sstep.c141
-rw-r--r--arch/ppc64/lib/strcase.c31
-rw-r--r--arch/ppc64/lib/string.S285
-rw-r--r--arch/ppc64/lib/usercopy.c41
12 files changed, 1872 insertions, 0 deletions
diff --git a/arch/ppc64/lib/Makefile b/arch/ppc64/lib/Makefile
new file mode 100644
index 000000000000..bf7b5bbfc04e
--- /dev/null
+++ b/arch/ppc64/lib/Makefile
@@ -0,0 +1,18 @@
1#
2# Makefile for ppc64-specific library files..
3#
4
5lib-y := checksum.o dec_and_lock.o string.o strcase.o
6lib-y += copypage.o memcpy.o copyuser.o usercopy.o
7
8# Lock primitives are defined as no-ops in include/linux/spinlock.h
9# for non-SMP configs. Don't build the real versions.
10
11lib-$(CONFIG_SMP) += locks.o
12
13# e2a provides EBCDIC to ASCII conversions.
14ifdef CONFIG_PPC_ISERIES
15obj-$(CONFIG_PCI) += e2a.o
16endif
17
18lib-$(CONFIG_DEBUG_KERNEL) += sstep.o
diff --git a/arch/ppc64/lib/checksum.S b/arch/ppc64/lib/checksum.S
new file mode 100644
index 000000000000..ef96c6c58efc
--- /dev/null
+++ b/arch/ppc64/lib/checksum.S
@@ -0,0 +1,229 @@
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/*
21 * ip_fast_csum(r3=buf, r4=len) -- Optimized for IP header
22 * len is in words and is always >= 5.
23 *
24 * In practice len == 5, but this is not guaranteed. So this code does not
25 * attempt to use doubleword instructions.
26 */
27_GLOBAL(ip_fast_csum)
28 lwz r0,0(r3)
29 lwzu r5,4(r3)
30 addic. r4,r4,-2
31 addc r0,r0,r5
32 mtctr r4
33 blelr-
341: lwzu r4,4(r3)
35 adde r0,r0,r4
36 bdnz 1b
37 addze r0,r0 /* add in final carry */
38 rldicl r4,r0,32,0 /* fold two 32-bit halves together */
39 add r0,r0,r4
40 srdi r0,r0,32
41 rlwinm r3,r0,16,0,31 /* fold two halves together */
42 add r3,r0,r3
43 not r3,r3
44 srwi r3,r3,16
45 blr
46
47/*
48 * Compute checksum of TCP or UDP pseudo-header:
49 * csum_tcpudp_magic(r3=saddr, r4=daddr, r5=len, r6=proto, r7=sum)
50 * No real gain trying to do this specially for 64 bit, but
51 * the 32 bit addition may spill into the upper bits of
52 * the doubleword so we still must fold it down from 64.
53 */
54_GLOBAL(csum_tcpudp_magic)
55 rlwimi r5,r6,16,0,15 /* put proto in upper half of len */
56 addc r0,r3,r4 /* add 4 32-bit words together */
57 adde r0,r0,r5
58 adde r0,r0,r7
59 rldicl r4,r0,32,0 /* fold 64 bit value */
60 add r0,r4,r0
61 srdi r0,r0,32
62 rlwinm r3,r0,16,0,31 /* fold two halves together */
63 add r3,r0,r3
64 not r3,r3
65 srwi r3,r3,16
66 blr
67
68/*
69 * Computes the checksum of a memory block at buff, length len,
70 * and adds in "sum" (32-bit).
71 *
72 * This code assumes at least halfword alignment, though the length
73 * can be any number of bytes. The sum is accumulated in r5.
74 *
75 * csum_partial(r3=buff, r4=len, r5=sum)
76 */
77_GLOBAL(csum_partial)
78 subi r3,r3,8 /* we'll offset by 8 for the loads */
79 srdi. r6,r4,3 /* divide by 8 for doubleword count */
80 addic r5,r5,0 /* clear carry */
81 beq 3f /* if we're doing < 8 bytes */
82 andi. r0,r3,2 /* aligned on a word boundary already? */
83 beq+ 1f
84 lhz r6,8(r3) /* do 2 bytes to get aligned */
85 addi r3,r3,2
86 subi r4,r4,2
87 addc r5,r5,r6
88 srdi. r6,r4,3 /* recompute number of doublewords */
89 beq 3f /* any left? */
901: mtctr r6
912: ldu r6,8(r3) /* main sum loop */
92 adde r5,r5,r6
93 bdnz 2b
94 andi. r4,r4,7 /* compute bytes left to sum after doublewords */
953: cmpwi 0,r4,4 /* is at least a full word left? */
96 blt 4f
97 lwz r6,8(r3) /* sum this word */
98 addi r3,r3,4
99 subi r4,r4,4
100 adde r5,r5,r6
1014: cmpwi 0,r4,2 /* is at least a halfword left? */
102 blt+ 5f
103 lhz r6,8(r3) /* sum this halfword */
104 addi r3,r3,2
105 subi r4,r4,2
106 adde r5,r5,r6
1075: cmpwi 0,r4,1 /* is at least a byte left? */
108 bne+ 6f
109 lbz r6,8(r3) /* sum this byte */
110 slwi r6,r6,8 /* this byte is assumed to be the upper byte of a halfword */
111 adde r5,r5,r6
1126: addze r5,r5 /* add in final carry */
113 rldicl r4,r5,32,0 /* fold two 32-bit halves together */
114 add r3,r4,r5
115 srdi r3,r3,32
116 blr
117
118/*
119 * Computes the checksum of a memory block at src, length len,
120 * and adds in "sum" (32-bit), while copying the block to dst.
121 * If an access exception occurs on src or dst, it stores -EFAULT
122 * to *src_err or *dst_err respectively, and (for an error on
123 * src) zeroes the rest of dst.
124 *
125 * This code needs to be reworked to take advantage of 64 bit sum+copy.
126 * However, due to tokenring halfword alignment problems this will be very
127 * tricky. For now we'll leave it until we instrument it somehow.
128 *
129 * csum_partial_copy_generic(r3=src, r4=dst, r5=len, r6=sum, r7=src_err, r8=dst_err)
130 */
131_GLOBAL(csum_partial_copy_generic)
132 addic r0,r6,0
133 subi r3,r3,4
134 subi r4,r4,4
135 srwi. r6,r5,2
136 beq 3f /* if we're doing < 4 bytes */
137 andi. r9,r4,2 /* Align dst to longword boundary */
138 beq+ 1f
13981: lhz r6,4(r3) /* do 2 bytes to get aligned */
140 addi r3,r3,2
141 subi r5,r5,2
14291: sth r6,4(r4)
143 addi r4,r4,2
144 addc r0,r0,r6
145 srwi. r6,r5,2 /* # words to do */
146 beq 3f
1471: mtctr r6
14882: lwzu r6,4(r3) /* the bdnz has zero overhead, so it should */
14992: stwu r6,4(r4) /* be unnecessary to unroll this loop */
150 adde r0,r0,r6
151 bdnz 82b
152 andi. r5,r5,3
1533: cmpwi 0,r5,2
154 blt+ 4f
15583: lhz r6,4(r3)
156 addi r3,r3,2
157 subi r5,r5,2
15893: sth r6,4(r4)
159 addi r4,r4,2
160 adde r0,r0,r6
1614: cmpwi 0,r5,1
162 bne+ 5f
16384: lbz r6,4(r3)
16494: stb r6,4(r4)
165 slwi r6,r6,8 /* Upper byte of word */
166 adde r0,r0,r6
1675: addze r3,r0 /* add in final carry (unlikely with 64-bit regs) */
168 rldicl r4,r3,32,0 /* fold 64 bit value */
169 add r3,r4,r3
170 srdi r3,r3,32
171 blr
172
173/* These shouldn't go in the fixup section, since that would
174 cause the ex_table addresses to get out of order. */
175
176 .globl src_error_1
177src_error_1:
178 li r6,0
179 subi r5,r5,2
18095: sth r6,4(r4)
181 addi r4,r4,2
182 srwi. r6,r5,2
183 beq 3f
184 mtctr r6
185 .globl src_error_2
186src_error_2:
187 li r6,0
18896: stwu r6,4(r4)
189 bdnz 96b
1903: andi. r5,r5,3
191 beq src_error
192 .globl src_error_3
193src_error_3:
194 li r6,0
195 mtctr r5
196 addi r4,r4,3
19797: stbu r6,1(r4)
198 bdnz 97b
199 .globl src_error
200src_error:
201 cmpdi 0,r7,0
202 beq 1f
203 li r6,-EFAULT
204 stw r6,0(r7)
2051: addze r3,r0
206 blr
207
208 .globl dst_error
209dst_error:
210 cmpdi 0,r8,0
211 beq 1f
212 li r6,-EFAULT
213 stw r6,0(r8)
2141: addze r3,r0
215 blr
216
217.section __ex_table,"a"
218 .align 3
219 .llong 81b,src_error_1
220 .llong 91b,dst_error
221 .llong 82b,src_error_2
222 .llong 92b,dst_error
223 .llong 83b,src_error_3
224 .llong 93b,dst_error
225 .llong 84b,src_error_3
226 .llong 94b,dst_error
227 .llong 95b,dst_error
228 .llong 96b,dst_error
229 .llong 97b,dst_error
diff --git a/arch/ppc64/lib/copypage.S b/arch/ppc64/lib/copypage.S
new file mode 100644
index 000000000000..733d61618bbf
--- /dev/null
+++ b/arch/ppc64/lib/copypage.S
@@ -0,0 +1,121 @@
1/*
2 * arch/ppc64/lib/copypage.S
3 *
4 * Copyright (C) 2002 Paul Mackerras, IBM Corp.
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/ppc_asm.h>
13
14_GLOBAL(copy_page)
15 std r31,-8(1)
16 std r30,-16(1)
17 std r29,-24(1)
18 std r28,-32(1)
19 std r27,-40(1)
20 std r26,-48(1)
21 std r25,-56(1)
22 std r24,-64(1)
23 std r23,-72(1)
24 std r22,-80(1)
25 std r21,-88(1)
26 std r20,-96(1)
27 li r5,4096/32 - 1
28 addi r3,r3,-8
29 li r12,5
300: addi r5,r5,-24
31 mtctr r12
32 ld r22,640(4)
33 ld r21,512(4)
34 ld r20,384(4)
35 ld r11,256(4)
36 ld r9,128(4)
37 ld r7,0(4)
38 ld r25,648(4)
39 ld r24,520(4)
40 ld r23,392(4)
41 ld r10,264(4)
42 ld r8,136(4)
43 ldu r6,8(4)
44 cmpwi r5,24
451: std r22,648(3)
46 std r21,520(3)
47 std r20,392(3)
48 std r11,264(3)
49 std r9,136(3)
50 std r7,8(3)
51 ld r28,648(4)
52 ld r27,520(4)
53 ld r26,392(4)
54 ld r31,264(4)
55 ld r30,136(4)
56 ld r29,8(4)
57 std r25,656(3)
58 std r24,528(3)
59 std r23,400(3)
60 std r10,272(3)
61 std r8,144(3)
62 std r6,16(3)
63 ld r22,656(4)
64 ld r21,528(4)
65 ld r20,400(4)
66 ld r11,272(4)
67 ld r9,144(4)
68 ld r7,16(4)
69 std r28,664(3)
70 std r27,536(3)
71 std r26,408(3)
72 std r31,280(3)
73 std r30,152(3)
74 stdu r29,24(3)
75 ld r25,664(4)
76 ld r24,536(4)
77 ld r23,408(4)
78 ld r10,280(4)
79 ld r8,152(4)
80 ldu r6,24(4)
81 bdnz 1b
82 std r22,648(3)
83 std r21,520(3)
84 std r20,392(3)
85 std r11,264(3)
86 std r9,136(3)
87 std r7,8(3)
88 addi r4,r4,640
89 addi r3,r3,648
90 bge 0b
91 mtctr r5
92 ld r7,0(4)
93 ld r8,8(4)
94 ldu r9,16(4)
953: ld r10,8(4)
96 std r7,8(3)
97 ld r7,16(4)
98 std r8,16(3)
99 ld r8,24(4)
100 std r9,24(3)
101 ldu r9,32(4)
102 stdu r10,32(3)
103 bdnz 3b
1044: ld r10,8(4)
105 std r7,8(3)
106 std r8,16(3)
107 std r9,24(3)
108 std r10,32(3)
1099: ld r20,-96(1)
110 ld r21,-88(1)
111 ld r22,-80(1)
112 ld r23,-72(1)
113 ld r24,-64(1)
114 ld r25,-56(1)
115 ld r26,-48(1)
116 ld r27,-40(1)
117 ld r28,-32(1)
118 ld r29,-24(1)
119 ld r30,-16(1)
120 ld r31,-8(1)
121 blr
diff --git a/arch/ppc64/lib/copyuser.S b/arch/ppc64/lib/copyuser.S
new file mode 100644
index 000000000000..a0b3fbbd6fb1
--- /dev/null
+++ b/arch/ppc64/lib/copyuser.S
@@ -0,0 +1,576 @@
1/*
2 * arch/ppc64/lib/copyuser.S
3 *
4 * Copyright (C) 2002 Paul Mackerras, IBM Corp.
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/ppc_asm.h>
13
14 .align 7
15_GLOBAL(__copy_tofrom_user)
16 /* first check for a whole page copy on a page boundary */
17 cmpldi cr1,r5,16
18 cmpdi cr6,r5,4096
19 or r0,r3,r4
20 neg r6,r3 /* LS 3 bits = # bytes to 8-byte dest bdry */
21 andi. r0,r0,4095
22 std r3,-24(r1)
23 crand cr0*4+2,cr0*4+2,cr6*4+2
24 std r4,-16(r1)
25 std r5,-8(r1)
26 dcbt 0,r4
27 beq .Lcopy_page
28 andi. r6,r6,7
29 mtcrf 0x01,r5
30 blt cr1,.Lshort_copy
31 bne .Ldst_unaligned
32.Ldst_aligned:
33 andi. r0,r4,7
34 addi r3,r3,-16
35 bne .Lsrc_unaligned
36 srdi r7,r5,4
3720: ld r9,0(r4)
38 addi r4,r4,-8
39 mtctr r7
40 andi. r5,r5,7
41 bf cr7*4+0,22f
42 addi r3,r3,8
43 addi r4,r4,8
44 mr r8,r9
45 blt cr1,72f
4621: ld r9,8(r4)
4770: std r8,8(r3)
4822: ldu r8,16(r4)
4971: stdu r9,16(r3)
50 bdnz 21b
5172: std r8,8(r3)
52 beq+ 3f
53 addi r3,r3,16
5423: ld r9,8(r4)
55.Ldo_tail:
56 bf cr7*4+1,1f
57 rotldi r9,r9,32
5873: stw r9,0(r3)
59 addi r3,r3,4
601: bf cr7*4+2,2f
61 rotldi r9,r9,16
6274: sth r9,0(r3)
63 addi r3,r3,2
642: bf cr7*4+3,3f
65 rotldi r9,r9,8
6675: stb r9,0(r3)
673: li r3,0
68 blr
69
70.Lsrc_unaligned:
71 srdi r6,r5,3
72 addi r5,r5,-16
73 subf r4,r0,r4
74 srdi r7,r5,4
75 sldi r10,r0,3
76 cmpldi cr6,r6,3
77 andi. r5,r5,7
78 mtctr r7
79 subfic r11,r10,64
80 add r5,r5,r0
81 bt cr7*4+0,28f
82
8324: ld r9,0(r4) /* 3+2n loads, 2+2n stores */
8425: ld r0,8(r4)
85 sld r6,r9,r10
8626: ldu r9,16(r4)
87 srd r7,r0,r11
88 sld r8,r0,r10
89 or r7,r7,r6
90 blt cr6,79f
9127: ld r0,8(r4)
92 b 2f
93
9428: ld r0,0(r4) /* 4+2n loads, 3+2n stores */
9529: ldu r9,8(r4)
96 sld r8,r0,r10
97 addi r3,r3,-8
98 blt cr6,5f
9930: ld r0,8(r4)
100 srd r12,r9,r11
101 sld r6,r9,r10
10231: ldu r9,16(r4)
103 or r12,r8,r12
104 srd r7,r0,r11
105 sld r8,r0,r10
106 addi r3,r3,16
107 beq cr6,78f
108
1091: or r7,r7,r6
11032: ld r0,8(r4)
11176: std r12,8(r3)
1122: srd r12,r9,r11
113 sld r6,r9,r10
11433: ldu r9,16(r4)
115 or r12,r8,r12
11677: stdu r7,16(r3)
117 srd r7,r0,r11
118 sld r8,r0,r10
119 bdnz 1b
120
12178: std r12,8(r3)
122 or r7,r7,r6
12379: std r7,16(r3)
1245: srd r12,r9,r11
125 or r12,r8,r12
12680: std r12,24(r3)
127 bne 6f
128 li r3,0
129 blr
1306: cmpwi cr1,r5,8
131 addi r3,r3,32
132 sld r9,r9,r10
133 ble cr1,.Ldo_tail
13434: ld r0,8(r4)
135 srd r7,r0,r11
136 or r9,r7,r9
137 b .Ldo_tail
138
139.Ldst_unaligned:
140 mtcrf 0x01,r6 /* put #bytes to 8B bdry into cr7 */
141 subf r5,r6,r5
142 li r7,0
143 cmpldi r1,r5,16
144 bf cr7*4+3,1f
14535: lbz r0,0(r4)
14681: stb r0,0(r3)
147 addi r7,r7,1
1481: bf cr7*4+2,2f
14936: lhzx r0,r7,r4
15082: sthx r0,r7,r3
151 addi r7,r7,2
1522: bf cr7*4+1,3f
15337: lwzx r0,r7,r4
15483: stwx r0,r7,r3
1553: mtcrf 0x01,r5
156 add r4,r6,r4
157 add r3,r6,r3
158 b .Ldst_aligned
159
160.Lshort_copy:
161 bf cr7*4+0,1f
16238: lwz r0,0(r4)
16339: lwz r9,4(r4)
164 addi r4,r4,8
16584: stw r0,0(r3)
16685: stw r9,4(r3)
167 addi r3,r3,8
1681: bf cr7*4+1,2f
16940: lwz r0,0(r4)
170 addi r4,r4,4
17186: stw r0,0(r3)
172 addi r3,r3,4
1732: bf cr7*4+2,3f
17441: lhz r0,0(r4)
175 addi r4,r4,2
17687: sth r0,0(r3)
177 addi r3,r3,2
1783: bf cr7*4+3,4f
17942: lbz r0,0(r4)
18088: stb r0,0(r3)
1814: li r3,0
182 blr
183
184/*
185 * exception handlers follow
186 * we have to return the number of bytes not copied
187 * for an exception on a load, we set the rest of the destination to 0
188 */
189
190136:
191137:
192 add r3,r3,r7
193 b 1f
194130:
195131:
196 addi r3,r3,8
197120:
198122:
199124:
200125:
201126:
202127:
203128:
204129:
205133:
206 addi r3,r3,8
207121:
208132:
209 addi r3,r3,8
210123:
211134:
212135:
213138:
214139:
215140:
216141:
217142:
218
219/*
220 * here we have had a fault on a load and r3 points to the first
221 * unmodified byte of the destination
222 */
2231: ld r6,-24(r1)
224 ld r4,-16(r1)
225 ld r5,-8(r1)
226 subf r6,r6,r3
227 add r4,r4,r6
228 subf r5,r6,r5 /* #bytes left to go */
229
230/*
231 * first see if we can copy any more bytes before hitting another exception
232 */
233 mtctr r5
23443: lbz r0,0(r4)
235 addi r4,r4,1
23689: stb r0,0(r3)
237 addi r3,r3,1
238 bdnz 43b
239 li r3,0 /* huh? all copied successfully this time? */
240 blr
241
242/*
243 * here we have trapped again, need to clear ctr bytes starting at r3
244 */
245143: mfctr r5
246 li r0,0
247 mr r4,r3
248 mr r3,r5 /* return the number of bytes not copied */
2491: andi. r9,r4,7
250 beq 3f
25190: stb r0,0(r4)
252 addic. r5,r5,-1
253 addi r4,r4,1
254 bne 1b
255 blr
2563: cmpldi cr1,r5,8
257 srdi r9,r5,3
258 andi. r5,r5,7
259 blt cr1,93f
260 mtctr r9
26191: std r0,0(r4)
262 addi r4,r4,8
263 bdnz 91b
26493: beqlr
265 mtctr r5
26692: stb r0,0(r4)
267 addi r4,r4,1
268 bdnz 92b
269 blr
270
271/*
272 * exception handlers for stores: we just need to work
273 * out how many bytes weren't copied
274 */
275182:
276183:
277 add r3,r3,r7
278 b 1f
279180:
280 addi r3,r3,8
281171:
282177:
283 addi r3,r3,8
284170:
285172:
286176:
287178:
288 addi r3,r3,4
289185:
290 addi r3,r3,4
291173:
292174:
293175:
294179:
295181:
296184:
297186:
298187:
299188:
300189:
3011:
302 ld r6,-24(r1)
303 ld r5,-8(r1)
304 add r6,r6,r5
305 subf r3,r3,r6 /* #bytes not copied */
306190:
307191:
308192:
309 blr /* #bytes not copied in r3 */
310
311 .section __ex_table,"a"
312 .align 3
313 .llong 20b,120b
314 .llong 21b,121b
315 .llong 70b,170b
316 .llong 22b,122b
317 .llong 71b,171b
318 .llong 72b,172b
319 .llong 23b,123b
320 .llong 73b,173b
321 .llong 74b,174b
322 .llong 75b,175b
323 .llong 24b,124b
324 .llong 25b,125b
325 .llong 26b,126b
326 .llong 27b,127b
327 .llong 28b,128b
328 .llong 29b,129b
329 .llong 30b,130b
330 .llong 31b,131b
331 .llong 32b,132b
332 .llong 76b,176b
333 .llong 33b,133b
334 .llong 77b,177b
335 .llong 78b,178b
336 .llong 79b,179b
337 .llong 80b,180b
338 .llong 34b,134b
339 .llong 35b,135b
340 .llong 81b,181b
341 .llong 36b,136b
342 .llong 82b,182b
343 .llong 37b,137b
344 .llong 83b,183b
345 .llong 38b,138b
346 .llong 39b,139b
347 .llong 84b,184b
348 .llong 85b,185b
349 .llong 40b,140b
350 .llong 86b,186b
351 .llong 41b,141b
352 .llong 87b,187b
353 .llong 42b,142b
354 .llong 88b,188b
355 .llong 43b,143b
356 .llong 89b,189b
357 .llong 90b,190b
358 .llong 91b,191b
359 .llong 92b,192b
360
361 .text
362
363/*
364 * Routine to copy a whole page of data, optimized for POWER4.
365 * On POWER4 it is more than 50% faster than the simple loop
366 * above (following the .Ldst_aligned label) but it runs slightly
367 * slower on POWER3.
368 */
369.Lcopy_page:
370 std r31,-32(1)
371 std r30,-40(1)
372 std r29,-48(1)
373 std r28,-56(1)
374 std r27,-64(1)
375 std r26,-72(1)
376 std r25,-80(1)
377 std r24,-88(1)
378 std r23,-96(1)
379 std r22,-104(1)
380 std r21,-112(1)
381 std r20,-120(1)
382 li r5,4096/32 - 1
383 addi r3,r3,-8
384 li r0,5
3850: addi r5,r5,-24
386 mtctr r0
38720: ld r22,640(4)
38821: ld r21,512(4)
38922: ld r20,384(4)
39023: ld r11,256(4)
39124: ld r9,128(4)
39225: ld r7,0(4)
39326: ld r25,648(4)
39427: ld r24,520(4)
39528: ld r23,392(4)
39629: ld r10,264(4)
39730: ld r8,136(4)
39831: ldu r6,8(4)
399 cmpwi r5,24
4001:
40132: std r22,648(3)
40233: std r21,520(3)
40334: std r20,392(3)
40435: std r11,264(3)
40536: std r9,136(3)
40637: std r7,8(3)
40738: ld r28,648(4)
40839: ld r27,520(4)
40940: ld r26,392(4)
41041: ld r31,264(4)
41142: ld r30,136(4)
41243: ld r29,8(4)
41344: std r25,656(3)
41445: std r24,528(3)
41546: std r23,400(3)
41647: std r10,272(3)
41748: std r8,144(3)
41849: std r6,16(3)
41950: ld r22,656(4)
42051: ld r21,528(4)
42152: ld r20,400(4)
42253: ld r11,272(4)
42354: ld r9,144(4)
42455: ld r7,16(4)
42556: std r28,664(3)
42657: std r27,536(3)
42758: std r26,408(3)
42859: std r31,280(3)
42960: std r30,152(3)
43061: stdu r29,24(3)
43162: ld r25,664(4)
43263: ld r24,536(4)
43364: ld r23,408(4)
43465: ld r10,280(4)
43566: ld r8,152(4)
43667: ldu r6,24(4)
437 bdnz 1b
43868: std r22,648(3)
43969: std r21,520(3)
44070: std r20,392(3)
44171: std r11,264(3)
44272: std r9,136(3)
44373: std r7,8(3)
44474: addi r4,r4,640
44575: addi r3,r3,648
446 bge 0b
447 mtctr r5
44876: ld r7,0(4)
44977: ld r8,8(4)
45078: ldu r9,16(4)
4513:
45279: ld r10,8(4)
45380: std r7,8(3)
45481: ld r7,16(4)
45582: std r8,16(3)
45683: ld r8,24(4)
45784: std r9,24(3)
45885: ldu r9,32(4)
45986: stdu r10,32(3)
460 bdnz 3b
4614:
46287: ld r10,8(4)
46388: std r7,8(3)
46489: std r8,16(3)
46590: std r9,24(3)
46691: std r10,32(3)
4679: ld r20,-120(1)
468 ld r21,-112(1)
469 ld r22,-104(1)
470 ld r23,-96(1)
471 ld r24,-88(1)
472 ld r25,-80(1)
473 ld r26,-72(1)
474 ld r27,-64(1)
475 ld r28,-56(1)
476 ld r29,-48(1)
477 ld r30,-40(1)
478 ld r31,-32(1)
479 li r3,0
480 blr
481
482/*
483 * on an exception, reset to the beginning and jump back into the
484 * standard __copy_tofrom_user
485 */
486100: ld r20,-120(1)
487 ld r21,-112(1)
488 ld r22,-104(1)
489 ld r23,-96(1)
490 ld r24,-88(1)
491 ld r25,-80(1)
492 ld r26,-72(1)
493 ld r27,-64(1)
494 ld r28,-56(1)
495 ld r29,-48(1)
496 ld r30,-40(1)
497 ld r31,-32(1)
498 ld r3,-24(r1)
499 ld r4,-16(r1)
500 li r5,4096
501 b .Ldst_aligned
502
503 .section __ex_table,"a"
504 .align 3
505 .llong 20b,100b
506 .llong 21b,100b
507 .llong 22b,100b
508 .llong 23b,100b
509 .llong 24b,100b
510 .llong 25b,100b
511 .llong 26b,100b
512 .llong 27b,100b
513 .llong 28b,100b
514 .llong 29b,100b
515 .llong 30b,100b
516 .llong 31b,100b
517 .llong 32b,100b
518 .llong 33b,100b
519 .llong 34b,100b
520 .llong 35b,100b
521 .llong 36b,100b
522 .llong 37b,100b
523 .llong 38b,100b
524 .llong 39b,100b
525 .llong 40b,100b
526 .llong 41b,100b
527 .llong 42b,100b
528 .llong 43b,100b
529 .llong 44b,100b
530 .llong 45b,100b
531 .llong 46b,100b
532 .llong 47b,100b
533 .llong 48b,100b
534 .llong 49b,100b
535 .llong 50b,100b
536 .llong 51b,100b
537 .llong 52b,100b
538 .llong 53b,100b
539 .llong 54b,100b
540 .llong 55b,100b
541 .llong 56b,100b
542 .llong 57b,100b
543 .llong 58b,100b
544 .llong 59b,100b
545 .llong 60b,100b
546 .llong 61b,100b
547 .llong 62b,100b
548 .llong 63b,100b
549 .llong 64b,100b
550 .llong 65b,100b
551 .llong 66b,100b
552 .llong 67b,100b
553 .llong 68b,100b
554 .llong 69b,100b
555 .llong 70b,100b
556 .llong 71b,100b
557 .llong 72b,100b
558 .llong 73b,100b
559 .llong 74b,100b
560 .llong 75b,100b
561 .llong 76b,100b
562 .llong 77b,100b
563 .llong 78b,100b
564 .llong 79b,100b
565 .llong 80b,100b
566 .llong 81b,100b
567 .llong 82b,100b
568 .llong 83b,100b
569 .llong 84b,100b
570 .llong 85b,100b
571 .llong 86b,100b
572 .llong 87b,100b
573 .llong 88b,100b
574 .llong 89b,100b
575 .llong 90b,100b
576 .llong 91b,100b
diff --git a/arch/ppc64/lib/dec_and_lock.c b/arch/ppc64/lib/dec_and_lock.c
new file mode 100644
index 000000000000..6e8d8591708c
--- /dev/null
+++ b/arch/ppc64/lib/dec_and_lock.c
@@ -0,0 +1,55 @@
1/*
2 * ppc64 version of atomic_dec_and_lock() using cmpxchg
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9
10#include <linux/module.h>
11#include <linux/spinlock.h>
12#include <asm/atomic.h>
13#include <asm/system.h>
14
15/*
16 * This is an implementation of the notion of "decrement a
17 * reference count, and return locked if it decremented to zero".
18 *
19 * This implementation can be used on any architecture that
20 * has a cmpxchg, and where atomic->value is an int holding
21 * the value of the atomic (i.e. the high bits aren't used
22 * for a lock or anything like that).
23 *
24 * N.B. ATOMIC_DEC_AND_LOCK gets defined in include/linux/spinlock.h
25 * if spinlocks are empty and thus atomic_dec_and_lock is defined
26 * to be atomic_dec_and_test - in that case we don't need it
27 * defined here as well.
28 */
29
30#ifndef ATOMIC_DEC_AND_LOCK
31int _atomic_dec_and_lock(atomic_t *atomic, spinlock_t *lock)
32{
33 int counter;
34 int newcount;
35
36 for (;;) {
37 counter = atomic_read(atomic);
38 newcount = counter - 1;
39 if (!newcount)
40 break; /* do it the slow way */
41
42 newcount = cmpxchg(&atomic->counter, counter, newcount);
43 if (newcount == counter)
44 return 0;
45 }
46
47 spin_lock(lock);
48 if (atomic_dec_and_test(atomic))
49 return 1;
50 spin_unlock(lock);
51 return 0;
52}
53
54EXPORT_SYMBOL(_atomic_dec_and_lock);
55#endif /* ATOMIC_DEC_AND_LOCK */
diff --git a/arch/ppc64/lib/e2a.c b/arch/ppc64/lib/e2a.c
new file mode 100644
index 000000000000..d2b834887920
--- /dev/null
+++ b/arch/ppc64/lib/e2a.c
@@ -0,0 +1,108 @@
1/*
2 * arch/ppc64/lib/e2a.c
3 *
4 * EBCDIC to ASCII conversion
5 *
6 * This function moved here from arch/ppc64/kernel/viopath.c
7 *
8 * (C) Copyright 2000-2004 IBM Corporation
9 *
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) anyu later version.
14 *
15 * This program is distributed in the hope that it will be useful, but
16 * WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
18 * General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software Foundation,
22 * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 *
24 */
25
26#include <linux/module.h>
27
28unsigned char e2a(unsigned char x)
29{
30 switch (x) {
31 case 0xF0:
32 return '0';
33 case 0xF1:
34 return '1';
35 case 0xF2:
36 return '2';
37 case 0xF3:
38 return '3';
39 case 0xF4:
40 return '4';
41 case 0xF5:
42 return '5';
43 case 0xF6:
44 return '6';
45 case 0xF7:
46 return '7';
47 case 0xF8:
48 return '8';
49 case 0xF9:
50 return '9';
51 case 0xC1:
52 return 'A';
53 case 0xC2:
54 return 'B';
55 case 0xC3:
56 return 'C';
57 case 0xC4:
58 return 'D';
59 case 0xC5:
60 return 'E';
61 case 0xC6:
62 return 'F';
63 case 0xC7:
64 return 'G';
65 case 0xC8:
66 return 'H';
67 case 0xC9:
68 return 'I';
69 case 0xD1:
70 return 'J';
71 case 0xD2:
72 return 'K';
73 case 0xD3:
74 return 'L';
75 case 0xD4:
76 return 'M';
77 case 0xD5:
78 return 'N';
79 case 0xD6:
80 return 'O';
81 case 0xD7:
82 return 'P';
83 case 0xD8:
84 return 'Q';
85 case 0xD9:
86 return 'R';
87 case 0xE2:
88 return 'S';
89 case 0xE3:
90 return 'T';
91 case 0xE4:
92 return 'U';
93 case 0xE5:
94 return 'V';
95 case 0xE6:
96 return 'W';
97 case 0xE7:
98 return 'X';
99 case 0xE8:
100 return 'Y';
101 case 0xE9:
102 return 'Z';
103 }
104 return ' ';
105}
106EXPORT_SYMBOL(e2a);
107
108
diff --git a/arch/ppc64/lib/locks.c b/arch/ppc64/lib/locks.c
new file mode 100644
index 000000000000..ef70ef91abe2
--- /dev/null
+++ b/arch/ppc64/lib/locks.c
@@ -0,0 +1,95 @@
1/*
2 * Spin and read/write lock operations.
3 *
4 * Copyright (C) 2001-2004 Paul Mackerras <paulus@au.ibm.com>, IBM
5 * Copyright (C) 2001 Anton Blanchard <anton@au.ibm.com>, IBM
6 * Copyright (C) 2002 Dave Engebretsen <engebret@us.ibm.com>, IBM
7 * Rework to support virtual processors
8 *
9 * This program is free software; you can redistribute it and/or
10 * modify it under the terms of the GNU General Public License
11 * as published by the Free Software Foundation; either version
12 * 2 of the License, or (at your option) any later version.
13 */
14
15#include <linux/config.h>
16#include <linux/kernel.h>
17#include <linux/spinlock.h>
18#include <linux/module.h>
19#include <linux/stringify.h>
20#include <asm/hvcall.h>
21#include <asm/iSeries/HvCall.h>
22
23/* waiting for a spinlock... */
24#if defined(CONFIG_PPC_SPLPAR) || defined(CONFIG_PPC_ISERIES)
25
26void __spin_yield(spinlock_t *lock)
27{
28 unsigned int lock_value, holder_cpu, yield_count;
29 struct paca_struct *holder_paca;
30
31 lock_value = lock->lock;
32 if (lock_value == 0)
33 return;
34 holder_cpu = lock_value & 0xffff;
35 BUG_ON(holder_cpu >= NR_CPUS);
36 holder_paca = &paca[holder_cpu];
37 yield_count = holder_paca->lppaca.yield_count;
38 if ((yield_count & 1) == 0)
39 return; /* virtual cpu is currently running */
40 rmb();
41 if (lock->lock != lock_value)
42 return; /* something has changed */
43#ifdef CONFIG_PPC_ISERIES
44 HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
45 ((u64)holder_cpu << 32) | yield_count);
46#else
47 plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
48 yield_count);
49#endif
50}
51
52/*
53 * Waiting for a read lock or a write lock on a rwlock...
54 * This turns out to be the same for read and write locks, since
55 * we only know the holder if it is write-locked.
56 */
57void __rw_yield(rwlock_t *rw)
58{
59 int lock_value;
60 unsigned int holder_cpu, yield_count;
61 struct paca_struct *holder_paca;
62
63 lock_value = rw->lock;
64 if (lock_value >= 0)
65 return; /* no write lock at present */
66 holder_cpu = lock_value & 0xffff;
67 BUG_ON(holder_cpu >= NR_CPUS);
68 holder_paca = &paca[holder_cpu];
69 yield_count = holder_paca->lppaca.yield_count;
70 if ((yield_count & 1) == 0)
71 return; /* virtual cpu is currently running */
72 rmb();
73 if (rw->lock != lock_value)
74 return; /* something has changed */
75#ifdef CONFIG_PPC_ISERIES
76 HvCall2(HvCallBaseYieldProcessor, HvCall_YieldToProc,
77 ((u64)holder_cpu << 32) | yield_count);
78#else
79 plpar_hcall_norets(H_CONFER, get_hard_smp_processor_id(holder_cpu),
80 yield_count);
81#endif
82}
83#endif
84
85void spin_unlock_wait(spinlock_t *lock)
86{
87 while (lock->lock) {
88 HMT_low();
89 if (SHARED_PROCESSOR)
90 __spin_yield(lock);
91 }
92 HMT_medium();
93}
94
95EXPORT_SYMBOL(spin_unlock_wait);
diff --git a/arch/ppc64/lib/memcpy.S b/arch/ppc64/lib/memcpy.S
new file mode 100644
index 000000000000..9ccacdf5bcb9
--- /dev/null
+++ b/arch/ppc64/lib/memcpy.S
@@ -0,0 +1,172 @@
1/*
2 * arch/ppc64/lib/memcpy.S
3 *
4 * Copyright (C) 2002 Paul Mackerras, IBM Corp.
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/ppc_asm.h>
13
14 .align 7
15_GLOBAL(memcpy)
16 mtcrf 0x01,r5
17 cmpldi cr1,r5,16
18 neg r6,r3 # LS 3 bits = # bytes to 8-byte dest bdry
19 andi. r6,r6,7
20 dcbt 0,r4
21 blt cr1,.Lshort_copy
22 bne .Ldst_unaligned
23.Ldst_aligned:
24 andi. r0,r4,7
25 addi r3,r3,-16
26 bne .Lsrc_unaligned
27 srdi r7,r5,4
28 ld r9,0(r4)
29 addi r4,r4,-8
30 mtctr r7
31 andi. r5,r5,7
32 bf cr7*4+0,2f
33 addi r3,r3,8
34 addi r4,r4,8
35 mr r8,r9
36 blt cr1,3f
371: ld r9,8(r4)
38 std r8,8(r3)
392: ldu r8,16(r4)
40 stdu r9,16(r3)
41 bdnz 1b
423: std r8,8(r3)
43 beqlr
44 addi r3,r3,16
45 ld r9,8(r4)
46.Ldo_tail:
47 bf cr7*4+1,1f
48 rotldi r9,r9,32
49 stw r9,0(r3)
50 addi r3,r3,4
511: bf cr7*4+2,2f
52 rotldi r9,r9,16
53 sth r9,0(r3)
54 addi r3,r3,2
552: bf cr7*4+3,3f
56 rotldi r9,r9,8
57 stb r9,0(r3)
583: blr
59
60.Lsrc_unaligned:
61 srdi r6,r5,3
62 addi r5,r5,-16
63 subf r4,r0,r4
64 srdi r7,r5,4
65 sldi r10,r0,3
66 cmpdi cr6,r6,3
67 andi. r5,r5,7
68 mtctr r7
69 subfic r11,r10,64
70 add r5,r5,r0
71
72 bt cr7*4+0,0f
73
74 ld r9,0(r4) # 3+2n loads, 2+2n stores
75 ld r0,8(r4)
76 sld r6,r9,r10
77 ldu r9,16(r4)
78 srd r7,r0,r11
79 sld r8,r0,r10
80 or r7,r7,r6
81 blt cr6,4f
82 ld r0,8(r4)
83 # s1<< in r8, d0=(s0<<|s1>>) in r7, s3 in r0, s2 in r9, nix in r6 & r12
84 b 2f
85
860: ld r0,0(r4) # 4+2n loads, 3+2n stores
87 ldu r9,8(r4)
88 sld r8,r0,r10
89 addi r3,r3,-8
90 blt cr6,5f
91 ld r0,8(r4)
92 srd r12,r9,r11
93 sld r6,r9,r10
94 ldu r9,16(r4)
95 or r12,r8,r12
96 srd r7,r0,r11
97 sld r8,r0,r10
98 addi r3,r3,16
99 beq cr6,3f
100
101 # d0=(s0<<|s1>>) in r12, s1<< in r6, s2>> in r7, s2<< in r8, s3 in r9
1021: or r7,r7,r6
103 ld r0,8(r4)
104 std r12,8(r3)
1052: srd r12,r9,r11
106 sld r6,r9,r10
107 ldu r9,16(r4)
108 or r12,r8,r12
109 stdu r7,16(r3)
110 srd r7,r0,r11
111 sld r8,r0,r10
112 bdnz 1b
113
1143: std r12,8(r3)
115 or r7,r7,r6
1164: std r7,16(r3)
1175: srd r12,r9,r11
118 or r12,r8,r12
119 std r12,24(r3)
120 beqlr
121 cmpwi cr1,r5,8
122 addi r3,r3,32
123 sld r9,r9,r10
124 ble cr1,.Ldo_tail
125 ld r0,8(r4)
126 srd r7,r0,r11
127 or r9,r7,r9
128 b .Ldo_tail
129
130.Ldst_unaligned:
131 mtcrf 0x01,r6 # put #bytes to 8B bdry into cr7
132 subf r5,r6,r5
133 li r7,0
134 cmpldi r1,r5,16
135 bf cr7*4+3,1f
136 lbz r0,0(r4)
137 stb r0,0(r3)
138 addi r7,r7,1
1391: bf cr7*4+2,2f
140 lhzx r0,r7,r4
141 sthx r0,r7,r3
142 addi r7,r7,2
1432: bf cr7*4+1,3f
144 lwzx r0,r7,r4
145 stwx r0,r7,r3
1463: mtcrf 0x01,r5
147 add r4,r6,r4
148 add r3,r6,r3
149 b .Ldst_aligned
150
151.Lshort_copy:
152 bf cr7*4+0,1f
153 lwz r0,0(r4)
154 lwz r9,4(r4)
155 addi r4,r4,8
156 stw r0,0(r3)
157 stw r9,4(r3)
158 addi r3,r3,8
1591: bf cr7*4+1,2f
160 lwz r0,0(r4)
161 addi r4,r4,4
162 stw r0,0(r3)
163 addi r3,r3,4
1642: bf cr7*4+2,3f
165 lhz r0,0(r4)
166 addi r4,r4,2
167 sth r0,0(r3)
168 addi r3,r3,2
1693: bf cr7*4+3,4f
170 lbz r0,0(r4)
171 stb r0,0(r3)
1724: blr
diff --git a/arch/ppc64/lib/sstep.c b/arch/ppc64/lib/sstep.c
new file mode 100644
index 000000000000..e79123d1485c
--- /dev/null
+++ b/arch/ppc64/lib/sstep.c
@@ -0,0 +1,141 @@
1/*
2 * Single-step support.
3 *
4 * Copyright (C) 2004 Paul Mackerras <paulus@au.ibm.com>, IBM
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 <linux/kernel.h>
12#include <linux/ptrace.h>
13#include <asm/sstep.h>
14#include <asm/processor.h>
15
16extern char system_call_common[];
17
18/* Bits in SRR1 that are copied from MSR */
19#define MSR_MASK 0xffffffff87c0ffff
20
21/*
22 * Determine whether a conditional branch instruction would branch.
23 */
24static int branch_taken(unsigned int instr, struct pt_regs *regs)
25{
26 unsigned int bo = (instr >> 21) & 0x1f;
27 unsigned int bi;
28
29 if ((bo & 4) == 0) {
30 /* decrement counter */
31 --regs->ctr;
32 if (((bo >> 1) & 1) ^ (regs->ctr == 0))
33 return 0;
34 }
35 if ((bo & 0x10) == 0) {
36 /* check bit from CR */
37 bi = (instr >> 16) & 0x1f;
38 if (((regs->ccr >> (31 - bi)) & 1) != ((bo >> 3) & 1))
39 return 0;
40 }
41 return 1;
42}
43
44/*
45 * Emulate instructions that cause a transfer of control.
46 * Returns 1 if the step was emulated, 0 if not,
47 * or -1 if the instruction is one that should not be stepped,
48 * such as an rfid, or a mtmsrd that would clear MSR_RI.
49 */
50int emulate_step(struct pt_regs *regs, unsigned int instr)
51{
52 unsigned int opcode, rd;
53 unsigned long int imm;
54
55 opcode = instr >> 26;
56 switch (opcode) {
57 case 16: /* bc */
58 imm = (signed short)(instr & 0xfffc);
59 if ((instr & 2) == 0)
60 imm += regs->nip;
61 regs->nip += 4;
62 if ((regs->msr & MSR_SF) == 0)
63 regs->nip &= 0xffffffffUL;
64 if (instr & 1)
65 regs->link = regs->nip;
66 if (branch_taken(instr, regs))
67 regs->nip = imm;
68 return 1;
69 case 17: /* sc */
70 /*
71 * N.B. this uses knowledge about how the syscall
72 * entry code works. If that is changed, this will
73 * need to be changed also.
74 */
75 regs->gpr[9] = regs->gpr[13];
76 regs->gpr[11] = regs->nip + 4;
77 regs->gpr[12] = regs->msr & MSR_MASK;
78 regs->gpr[13] = (unsigned long) get_paca();
79 regs->nip = (unsigned long) &system_call_common;
80 regs->msr = MSR_KERNEL;
81 return 1;
82 case 18: /* b */
83 imm = instr & 0x03fffffc;
84 if (imm & 0x02000000)
85 imm -= 0x04000000;
86 if ((instr & 2) == 0)
87 imm += regs->nip;
88 if (instr & 1) {
89 regs->link = regs->nip + 4;
90 if ((regs->msr & MSR_SF) == 0)
91 regs->link &= 0xffffffffUL;
92 }
93 if ((regs->msr & MSR_SF) == 0)
94 imm &= 0xffffffffUL;
95 regs->nip = imm;
96 return 1;
97 case 19:
98 switch (instr & 0x7fe) {
99 case 0x20: /* bclr */
100 case 0x420: /* bcctr */
101 imm = (instr & 0x400)? regs->ctr: regs->link;
102 regs->nip += 4;
103 if ((regs->msr & MSR_SF) == 0) {
104 regs->nip &= 0xffffffffUL;
105 imm &= 0xffffffffUL;
106 }
107 if (instr & 1)
108 regs->link = regs->nip;
109 if (branch_taken(instr, regs))
110 regs->nip = imm;
111 return 1;
112 case 0x24: /* rfid, scary */
113 return -1;
114 }
115 case 31:
116 rd = (instr >> 21) & 0x1f;
117 switch (instr & 0x7fe) {
118 case 0xa6: /* mfmsr */
119 regs->gpr[rd] = regs->msr & MSR_MASK;
120 regs->nip += 4;
121 if ((regs->msr & MSR_SF) == 0)
122 regs->nip &= 0xffffffffUL;
123 return 1;
124 case 0x164: /* mtmsrd */
125 /* only MSR_EE and MSR_RI get changed if bit 15 set */
126 /* mtmsrd doesn't change MSR_HV and MSR_ME */
127 imm = (instr & 0x10000)? 0x8002: 0xefffffffffffefffUL;
128 imm = (regs->msr & MSR_MASK & ~imm)
129 | (regs->gpr[rd] & imm);
130 if ((imm & MSR_RI) == 0)
131 /* can't step mtmsrd that would clear MSR_RI */
132 return -1;
133 regs->msr = imm;
134 regs->nip += 4;
135 if ((imm & MSR_SF) == 0)
136 regs->nip &= 0xffffffffUL;
137 return 1;
138 }
139 }
140 return 0;
141}
diff --git a/arch/ppc64/lib/strcase.c b/arch/ppc64/lib/strcase.c
new file mode 100644
index 000000000000..e84f243368c0
--- /dev/null
+++ b/arch/ppc64/lib/strcase.c
@@ -0,0 +1,31 @@
1/*
2 * c 2001 PPC 64 Team, IBM Corp
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9#include <linux/ctype.h>
10
11int strcasecmp(const char *s1, const char *s2)
12{
13 int c1, c2;
14
15 do {
16 c1 = tolower(*s1++);
17 c2 = tolower(*s2++);
18 } while (c1 == c2 && c1 != 0);
19 return c1 - c2;
20}
21
22int strncasecmp(const char *s1, const char *s2, int n)
23{
24 int c1, c2;
25
26 do {
27 c1 = tolower(*s1++);
28 c2 = tolower(*s2++);
29 } while ((--n > 0) && c1 == c2 && c1 != 0);
30 return c1 - c2;
31}
diff --git a/arch/ppc64/lib/string.S b/arch/ppc64/lib/string.S
new file mode 100644
index 000000000000..813587e5c2ec
--- /dev/null
+++ b/arch/ppc64/lib/string.S
@@ -0,0 +1,285 @@
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/errno.h>
13#include <asm/ppc_asm.h>
14
15_GLOBAL(strcpy)
16 addi r5,r3,-1
17 addi r4,r4,-1
181: lbzu r0,1(r4)
19 cmpwi 0,r0,0
20 stbu r0,1(r5)
21 bne 1b
22 blr
23
24_GLOBAL(strncpy)
25 cmpwi 0,r5,0
26 beqlr
27 mtctr r5
28 addi r6,r3,-1
29 addi r4,r4,-1
301: lbzu r0,1(r4)
31 cmpwi 0,r0,0
32 stbu r0,1(r6)
33 bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
34 blr
35
36_GLOBAL(strcat)
37 addi r5,r3,-1
38 addi r4,r4,-1
391: lbzu r0,1(r5)
40 cmpwi 0,r0,0
41 bne 1b
42 addi r5,r5,-1
431: lbzu r0,1(r4)
44 cmpwi 0,r0,0
45 stbu r0,1(r5)
46 bne 1b
47 blr
48
49_GLOBAL(strcmp)
50 addi r5,r3,-1
51 addi r4,r4,-1
521: lbzu r3,1(r5)
53 cmpwi 1,r3,0
54 lbzu r0,1(r4)
55 subf. r3,r0,r3
56 beqlr 1
57 beq 1b
58 blr
59
60_GLOBAL(strlen)
61 addi r4,r3,-1
621: lbzu r0,1(r4)
63 cmpwi 0,r0,0
64 bne 1b
65 subf r3,r3,r4
66 blr
67
68_GLOBAL(memset)
69 neg r0,r3
70 rlwimi r4,r4,8,16,23
71 andi. r0,r0,7 /* # bytes to be 8-byte aligned */
72 rlwimi r4,r4,16,0,15
73 cmplw cr1,r5,r0 /* do we get that far? */
74 rldimi r4,r4,32,0
75 mtcrf 1,r0
76 mr r6,r3
77 blt cr1,8f
78 beq+ 3f /* if already 8-byte aligned */
79 subf r5,r0,r5
80 bf 31,1f
81 stb r4,0(r6)
82 addi r6,r6,1
831: bf 30,2f
84 sth r4,0(r6)
85 addi r6,r6,2
862: bf 29,3f
87 stw r4,0(r6)
88 addi r6,r6,4
893: srdi. r0,r5,6
90 clrldi r5,r5,58
91 mtctr r0
92 beq 5f
934: std r4,0(r6)
94 std r4,8(r6)
95 std r4,16(r6)
96 std r4,24(r6)
97 std r4,32(r6)
98 std r4,40(r6)
99 std r4,48(r6)
100 std r4,56(r6)
101 addi r6,r6,64
102 bdnz 4b
1035: srwi. r0,r5,3
104 clrlwi r5,r5,29
105 mtcrf 1,r0
106 beq 8f
107 bf 29,6f
108 std r4,0(r6)
109 std r4,8(r6)
110 std r4,16(r6)
111 std r4,24(r6)
112 addi r6,r6,32
1136: bf 30,7f
114 std r4,0(r6)
115 std r4,8(r6)
116 addi r6,r6,16
1177: bf 31,8f
118 std r4,0(r6)
119 addi r6,r6,8
1208: cmpwi r5,0
121 mtcrf 1,r5
122 beqlr+
123 bf 29,9f
124 stw r4,0(r6)
125 addi r6,r6,4
1269: bf 30,10f
127 sth r4,0(r6)
128 addi r6,r6,2
12910: bflr 31
130 stb r4,0(r6)
131 blr
132
133_GLOBAL(memmove)
134 cmplw 0,r3,r4
135 bgt .backwards_memcpy
136 b .memcpy
137
138_GLOBAL(backwards_memcpy)
139 rlwinm. r7,r5,32-3,3,31 /* r0 = r5 >> 3 */
140 add r6,r3,r5
141 add r4,r4,r5
142 beq 2f
143 andi. r0,r6,3
144 mtctr r7
145 bne 5f
1461: lwz r7,-4(r4)
147 lwzu r8,-8(r4)
148 stw r7,-4(r6)
149 stwu r8,-8(r6)
150 bdnz 1b
151 andi. r5,r5,7
1522: cmplwi 0,r5,4
153 blt 3f
154 lwzu r0,-4(r4)
155 subi r5,r5,4
156 stwu r0,-4(r6)
1573: cmpwi 0,r5,0
158 beqlr
159 mtctr r5
1604: lbzu r0,-1(r4)
161 stbu r0,-1(r6)
162 bdnz 4b
163 blr
1645: mtctr r0
1656: lbzu r7,-1(r4)
166 stbu r7,-1(r6)
167 bdnz 6b
168 subf r5,r0,r5
169 rlwinm. r7,r5,32-3,3,31
170 beq 2b
171 mtctr r7
172 b 1b
173
174_GLOBAL(memcmp)
175 cmpwi 0,r5,0
176 ble- 2f
177 mtctr r5
178 addi r6,r3,-1
179 addi r4,r4,-1
1801: lbzu r3,1(r6)
181 lbzu r0,1(r4)
182 subf. r3,r0,r3
183 bdnzt 2,1b
184 blr
1852: li r3,0
186 blr
187
188_GLOBAL(memchr)
189 cmpwi 0,r5,0
190 ble- 2f
191 mtctr r5
192 addi r3,r3,-1
1931: lbzu r0,1(r3)
194 cmpw 0,r0,r4
195 bdnzf 2,1b
196 beqlr
1972: li r3,0
198 blr
199
200_GLOBAL(__clear_user)
201 addi r6,r3,-4
202 li r3,0
203 li r5,0
204 cmplwi 0,r4,4
205 blt 7f
206 /* clear a single word */
20711: stwu r5,4(r6)
208 beqlr
209 /* clear word sized chunks */
210 andi. r0,r6,3
211 add r4,r0,r4
212 subf r6,r0,r6
213 srwi r0,r4,2
214 andi. r4,r4,3
215 mtctr r0
216 bdz 7f
2171: stwu r5,4(r6)
218 bdnz 1b
219 /* clear byte sized chunks */
2207: cmpwi 0,r4,0
221 beqlr
222 mtctr r4
223 addi r6,r6,3
2248: stbu r5,1(r6)
225 bdnz 8b
226 blr
22790: mr r3,r4
228 blr
22991: mfctr r3
230 slwi r3,r3,2
231 add r3,r3,r4
232 blr
23392: mfctr r3
234 blr
235
236 .section __ex_table,"a"
237 .align 3
238 .llong 11b,90b
239 .llong 1b,91b
240 .llong 8b,92b
241 .text
242
243/* r3 = dst, r4 = src, r5 = count */
244_GLOBAL(__strncpy_from_user)
245 addi r6,r3,-1
246 addi r4,r4,-1
247 cmpwi 0,r5,0
248 beq 2f
249 mtctr r5
2501: lbzu r0,1(r4)
251 cmpwi 0,r0,0
252 stbu r0,1(r6)
253 bdnzf 2,1b /* dec ctr, branch if ctr != 0 && !cr0.eq */
254 beq 3f
2552: addi r6,r6,1
2563: subf r3,r3,r6
257 blr
25899: li r3,-EFAULT
259 blr
260
261 .section __ex_table,"a"
262 .align 3
263 .llong 1b,99b
264 .text
265
266/* r3 = str, r4 = len (> 0) */
267_GLOBAL(__strnlen_user)
268 addi r7,r3,-1
269 mtctr r4 /* ctr = len */
2701: lbzu r0,1(r7) /* get next byte */
271 cmpwi 0,r0,0
272 bdnzf 2,1b /* loop if --ctr != 0 && byte != 0 */
273 addi r7,r7,1
274 subf r3,r3,r7 /* number of bytes we have looked at */
275 beqlr /* return if we found a 0 byte */
276 cmpw 0,r3,r4 /* did we look at all len bytes? */
277 blt 99f /* if not, must have hit top */
278 addi r3,r4,1 /* return len + 1 to indicate no null found */
279 blr
28099: li r3,0 /* bad address, return 0 */
281 blr
282
283 .section __ex_table,"a"
284 .align 3
285 .llong 1b,99b
diff --git a/arch/ppc64/lib/usercopy.c b/arch/ppc64/lib/usercopy.c
new file mode 100644
index 000000000000..5eea6f3c1e03
--- /dev/null
+++ b/arch/ppc64/lib/usercopy.c
@@ -0,0 +1,41 @@
1/*
2 * Functions which are too large to be inlined.
3 *
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation; either version
7 * 2 of the License, or (at your option) any later version.
8 */
9#include <linux/module.h>
10#include <asm/uaccess.h>
11
12unsigned long copy_from_user(void *to, const void __user *from, unsigned long n)
13{
14 if (likely(access_ok(VERIFY_READ, from, n)))
15 n = __copy_from_user(to, from, n);
16 else
17 memset(to, 0, n);
18 return n;
19}
20
21unsigned long copy_to_user(void __user *to, const void *from, unsigned long n)
22{
23 if (likely(access_ok(VERIFY_WRITE, to, n)))
24 n = __copy_to_user(to, from, n);
25 return n;
26}
27
28unsigned long copy_in_user(void __user *to, const void __user *from,
29 unsigned long n)
30{
31 might_sleep();
32 if (likely(access_ok(VERIFY_READ, from, n) &&
33 access_ok(VERIFY_WRITE, to, n)))
34 n =__copy_tofrom_user(to, from, n);
35 return n;
36}
37
38EXPORT_SYMBOL(copy_from_user);
39EXPORT_SYMBOL(copy_to_user);
40EXPORT_SYMBOL(copy_in_user);
41