aboutsummaryrefslogtreecommitdiffstats
path: root/arch/frv/lib
diff options
context:
space:
mode:
Diffstat (limited to 'arch/frv/lib')
-rw-r--r--arch/frv/lib/Makefile8
-rw-r--r--arch/frv/lib/__ashldi3.S40
-rw-r--r--arch/frv/lib/__ashrdi3.S41
-rw-r--r--arch/frv/lib/__lshrdi3.S40
-rw-r--r--arch/frv/lib/__muldi3.S32
-rw-r--r--arch/frv/lib/__negdi2.S28
-rw-r--r--arch/frv/lib/atomic-ops.S265
-rw-r--r--arch/frv/lib/cache.S98
-rw-r--r--arch/frv/lib/checksum.c148
-rw-r--r--arch/frv/lib/insl_ns.S52
-rw-r--r--arch/frv/lib/insl_sw.S40
-rw-r--r--arch/frv/lib/memcpy.S135
-rw-r--r--arch/frv/lib/memset.S182
-rw-r--r--arch/frv/lib/outsl_ns.S59
-rw-r--r--arch/frv/lib/outsl_sw.S45
15 files changed, 1213 insertions, 0 deletions
diff --git a/arch/frv/lib/Makefile b/arch/frv/lib/Makefile
new file mode 100644
index 000000000000..19be2626d5e6
--- /dev/null
+++ b/arch/frv/lib/Makefile
@@ -0,0 +1,8 @@
1#
2# Makefile for FRV-specific library files..
3#
4
5lib-y := \
6 __ashldi3.o __lshrdi3.o __muldi3.o __ashrdi3.o __negdi2.o \
7 checksum.o memcpy.o memset.o atomic-ops.o \
8 outsl_ns.o outsl_sw.o insl_ns.o insl_sw.o cache.o
diff --git a/arch/frv/lib/__ashldi3.S b/arch/frv/lib/__ashldi3.S
new file mode 100644
index 000000000000..db5b6dc37a11
--- /dev/null
+++ b/arch/frv/lib/__ashldi3.S
@@ -0,0 +1,40 @@
1/* __ashldi3.S: 64-bit arithmetic shift left
2 *
3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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
12 .text
13 .p2align 4
14
15###############################################################################
16#
17# unsigned long long __ashldi3(unsigned long long value [GR8:GR9], unsigned by [GR10])
18#
19###############################################################################
20 .globl __ashldi3
21 .type __ashldi3,@function
22__ashldi3:
23 andicc.p gr10,#63,gr10,icc0
24 setlos #32,gr5
25 andicc.p gr10,#32,gr0,icc1
26 beqlr icc0,#0
27 ckeq icc1,cc4 ; cc4 is true if 0<N<32
28
29 # deal with a shift in the range 1<=N<=31
30 csll.p gr8,gr10,gr8 ,cc4,#1 ; MSW <<= N
31 csub gr5,gr10,gr5 ,cc4,#1 ; M = 32 - N
32 csrl.p gr9,gr5,gr4 ,cc4,#1
33 csll gr9,gr10,gr9 ,cc4,#1 ; LSW <<= N
34 cor.p gr4,gr8,gr8 ,cc4,#1 ; MSW |= LSW >> M
35
36 # deal with a shift in the range 32<=N<=63
37 csll gr9,gr10,gr8 ,cc4,#0 ; MSW = LSW << (N & 31 [implicit AND])
38 cor.p gr0,gr0,gr9 ,cc4,#0 ; LSW = 0
39 bralr
40 .size __ashldi3, .-__ashldi3
diff --git a/arch/frv/lib/__ashrdi3.S b/arch/frv/lib/__ashrdi3.S
new file mode 100644
index 000000000000..5742665bfd29
--- /dev/null
+++ b/arch/frv/lib/__ashrdi3.S
@@ -0,0 +1,41 @@
1/* __ashrdi3.S: 64-bit arithmetic shift right
2 *
3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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
12 .text
13 .p2align 4
14
15###############################################################################
16#
17# signed long long __ashrdi3(signed long long value [GR8:GR9], unsigned by [GR10])
18#
19###############################################################################
20 .globl __ashrdi3
21 .type __ashrdi3,@function
22__ashrdi3:
23 andicc.p gr10,#63,gr10,icc0
24 setlos #32,gr5
25 andicc.p gr10,#32,gr0,icc1
26 beqlr icc0,#0
27 setlos.p #31,gr6
28 ckeq icc1,cc4 ; cc4 is true if 0<N<32
29
30 # deal with a shift in the range 1<=N<=31
31 csrl.p gr9,gr10,gr9 ,cc4,#1 ; LSW >>= N
32 csub gr5,gr10,gr5 ,cc4,#1 ; M = 32 - N
33 csll.p gr8,gr5,gr4 ,cc4,#1
34 csra gr8,gr10,gr8 ,cc4,#1 ; MSW >>= N
35 cor.p gr4,gr9,gr9 ,cc4,#1 ; LSW |= MSW << M
36
37 # deal with a shift in the range 32<=N<=63
38 csra gr8,gr10,gr9 ,cc4,#0 ; LSW = MSW >> (N & 31 [implicit AND])
39 csra.p gr8,gr6,gr8 ,cc4,#0 ; MSW >>= 31
40 bralr
41 .size __ashrdi3, .-__ashrdi3
diff --git a/arch/frv/lib/__lshrdi3.S b/arch/frv/lib/__lshrdi3.S
new file mode 100644
index 000000000000..7b41f6304f04
--- /dev/null
+++ b/arch/frv/lib/__lshrdi3.S
@@ -0,0 +1,40 @@
1/* __lshrdi3.S: 64-bit logical shift right
2 *
3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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
12 .text
13 .p2align 4
14
15###############################################################################
16#
17# unsigned long long __lshrdi3(unsigned long long value [GR8:GR9], unsigned by [GR10])
18#
19###############################################################################
20 .globl __lshrdi3
21 .type __lshrdi3,@function
22__lshrdi3:
23 andicc.p gr10,#63,gr10,icc0
24 setlos #32,gr5
25 andicc.p gr10,#32,gr0,icc1
26 beqlr icc0,#0
27 ckeq icc1,cc4 ; cc4 is true if 0<N<32
28
29 # deal with a shift in the range 1<=N<=31
30 csrl.p gr9,gr10,gr9 ,cc4,#1 ; LSW >>= N
31 csub gr5,gr10,gr5 ,cc4,#1 ; M = 32 - N
32 csll.p gr8,gr5,gr4 ,cc4,#1
33 csrl gr8,gr10,gr8 ,cc4,#1 ; MSW >>= N
34 cor.p gr4,gr9,gr9 ,cc4,#1 ; LSW |= MSW << M
35
36 # deal with a shift in the range 32<=N<=63
37 csrl gr8,gr10,gr9 ,cc4,#0 ; LSW = MSW >> (N & 31 [implicit AND])
38 cor.p gr0,gr0,gr8 ,cc4,#0 ; MSW = 0
39 bralr
40 .size __lshrdi3, .-__lshrdi3
diff --git a/arch/frv/lib/__muldi3.S b/arch/frv/lib/__muldi3.S
new file mode 100644
index 000000000000..2703d9b79361
--- /dev/null
+++ b/arch/frv/lib/__muldi3.S
@@ -0,0 +1,32 @@
1/* __muldi3.S: 64-bit multiply
2 *
3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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
12 .text
13 .p2align 4
14
15###############################################################################
16#
17# unsigned long long __muldi3(unsigned long long x [GR8:GR9],
18# unsigned long long y [GR10:GR11])
19#
20###############################################################################
21 .globl __muldi3, __mulll, __umulll
22 .type __muldi3,@function
23__muldi3:
24__mulll:
25__umulll:
26 umul gr8,gr11,gr4 ; GR4:GR5 = x.MSW * y.LSW
27 umul gr9,gr10,gr6 ; GR6:GR7 = x.LSW * y.MSW
28 umul.p gr9,gr11,gr8 ; GR8:GR9 = x.LSW * y.LSW
29 add gr5,gr7,gr5
30 add.p gr8,gr5,gr8 ; GR8 += GR5 + GR7
31 bralr
32 .size __muldi3, .-__muldi3
diff --git a/arch/frv/lib/__negdi2.S b/arch/frv/lib/__negdi2.S
new file mode 100644
index 000000000000..d1747bf24997
--- /dev/null
+++ b/arch/frv/lib/__negdi2.S
@@ -0,0 +1,28 @@
1/* __negdi2.S: 64-bit negate
2 *
3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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
12
13 .text
14 .p2align 4
15
16###############################################################################
17#
18# unsigned long long __negdi2(unsigned long long value [GR8:GR9])
19#
20###############################################################################
21 .globl __negdi2
22 .type __negdi2,@function
23__negdi2:
24 subcc gr0,gr9,gr9,icc0
25 subx gr0,gr8,gr8,icc0
26 bralr
27 .size __negdi2, .-__negdi2
28
diff --git a/arch/frv/lib/atomic-ops.S b/arch/frv/lib/atomic-ops.S
new file mode 100644
index 000000000000..b03d510a89e4
--- /dev/null
+++ b/arch/frv/lib/atomic-ops.S
@@ -0,0 +1,265 @@
1/* atomic-ops.S: kernel atomic operations
2 *
3 * For an explanation of how atomic ops work in this arch, see:
4 * Documentation/fujitsu/frv/atomic-ops.txt
5 *
6 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
7 * Written by David Howells (dhowells@redhat.com)
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 <asm/spr-regs.h>
16
17 .text
18 .balign 4
19
20###############################################################################
21#
22# unsigned long atomic_test_and_ANDNOT_mask(unsigned long mask, volatile unsigned long *v);
23#
24###############################################################################
25 .globl atomic_test_and_ANDNOT_mask
26 .type atomic_test_and_ANDNOT_mask,@function
27atomic_test_and_ANDNOT_mask:
28 not.p gr8,gr10
290:
30 orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
31 ckeq icc3,cc7
32 ld.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
33 orcr cc7,cc7,cc3 /* set CC3 to true */
34 and gr8,gr10,gr11
35 cst.p gr11,@(gr9,gr0) ,cc3,#1
36 corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
37 beq icc3,#0,0b
38 bralr
39
40 .size atomic_test_and_ANDNOT_mask, .-atomic_test_and_ANDNOT_mask
41
42###############################################################################
43#
44# unsigned long atomic_test_and_OR_mask(unsigned long mask, volatile unsigned long *v);
45#
46###############################################################################
47 .globl atomic_test_and_OR_mask
48 .type atomic_test_and_OR_mask,@function
49atomic_test_and_OR_mask:
50 or.p gr8,gr8,gr10
510:
52 orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
53 ckeq icc3,cc7
54 ld.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
55 orcr cc7,cc7,cc3 /* set CC3 to true */
56 or gr8,gr10,gr11
57 cst.p gr11,@(gr9,gr0) ,cc3,#1
58 corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
59 beq icc3,#0,0b
60 bralr
61
62 .size atomic_test_and_OR_mask, .-atomic_test_and_OR_mask
63
64###############################################################################
65#
66# unsigned long atomic_test_and_XOR_mask(unsigned long mask, volatile unsigned long *v);
67#
68###############################################################################
69 .globl atomic_test_and_XOR_mask
70 .type atomic_test_and_XOR_mask,@function
71atomic_test_and_XOR_mask:
72 or.p gr8,gr8,gr10
730:
74 orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
75 ckeq icc3,cc7
76 ld.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
77 orcr cc7,cc7,cc3 /* set CC3 to true */
78 xor gr8,gr10,gr11
79 cst.p gr11,@(gr9,gr0) ,cc3,#1
80 corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
81 beq icc3,#0,0b
82 bralr
83
84 .size atomic_test_and_XOR_mask, .-atomic_test_and_XOR_mask
85
86###############################################################################
87#
88# int atomic_add_return(int i, atomic_t *v)
89#
90###############################################################################
91 .globl atomic_add_return
92 .type atomic_add_return,@function
93atomic_add_return:
94 or.p gr8,gr8,gr10
950:
96 orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
97 ckeq icc3,cc7
98 ld.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
99 orcr cc7,cc7,cc3 /* set CC3 to true */
100 add gr8,gr10,gr8
101 cst.p gr8,@(gr9,gr0) ,cc3,#1
102 corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
103 beq icc3,#0,0b
104 bralr
105
106 .size atomic_add_return, .-atomic_add_return
107
108###############################################################################
109#
110# int atomic_sub_return(int i, atomic_t *v)
111#
112###############################################################################
113 .globl atomic_sub_return
114 .type atomic_sub_return,@function
115atomic_sub_return:
116 or.p gr8,gr8,gr10
1170:
118 orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
119 ckeq icc3,cc7
120 ld.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
121 orcr cc7,cc7,cc3 /* set CC3 to true */
122 sub gr8,gr10,gr8
123 cst.p gr8,@(gr9,gr0) ,cc3,#1
124 corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
125 beq icc3,#0,0b
126 bralr
127
128 .size atomic_sub_return, .-atomic_sub_return
129
130###############################################################################
131#
132# uint8_t __xchg_8(uint8_t i, uint8_t *v)
133#
134###############################################################################
135 .globl __xchg_8
136 .type __xchg_8,@function
137__xchg_8:
138 or.p gr8,gr8,gr10
1390:
140 orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
141 ckeq icc3,cc7
142 ldub.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
143 orcr cc7,cc7,cc3 /* set CC3 to true */
144 cstb.p gr10,@(gr9,gr0) ,cc3,#1
145 corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
146 beq icc3,#0,0b
147 bralr
148
149 .size __xchg_8, .-__xchg_8
150
151###############################################################################
152#
153# uint16_t __xchg_16(uint16_t i, uint16_t *v)
154#
155###############################################################################
156 .globl __xchg_16
157 .type __xchg_16,@function
158__xchg_16:
159 or.p gr8,gr8,gr10
1600:
161 orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
162 ckeq icc3,cc7
163 lduh.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
164 orcr cc7,cc7,cc3 /* set CC3 to true */
165 csth.p gr10,@(gr9,gr0) ,cc3,#1
166 corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
167 beq icc3,#0,0b
168 bralr
169
170 .size __xchg_16, .-__xchg_16
171
172###############################################################################
173#
174# uint32_t __xchg_32(uint32_t i, uint32_t *v)
175#
176###############################################################################
177 .globl __xchg_32
178 .type __xchg_32,@function
179__xchg_32:
180 or.p gr8,gr8,gr10
1810:
182 orcc gr0,gr0,gr0,icc3 /* set ICC3.Z */
183 ckeq icc3,cc7
184 ld.p @(gr9,gr0),gr8 /* LD.P/ORCR must be atomic */
185 orcr cc7,cc7,cc3 /* set CC3 to true */
186 cst.p gr10,@(gr9,gr0) ,cc3,#1
187 corcc gr29,gr29,gr0 ,cc3,#1 /* clear ICC3.Z if store happens */
188 beq icc3,#0,0b
189 bralr
190
191 .size __xchg_32, .-__xchg_32
192
193###############################################################################
194#
195# uint8_t __cmpxchg_8(uint8_t *v, uint8_t test, uint8_t new)
196#
197###############################################################################
198 .globl __cmpxchg_8
199 .type __cmpxchg_8,@function
200__cmpxchg_8:
201 or.p gr8,gr8,gr11
2020:
203 orcc gr0,gr0,gr0,icc3
204 ckeq icc3,cc7
205 ldub.p @(gr11,gr0),gr8
206 orcr cc7,cc7,cc3
207 sub gr8,gr9,gr7
208 sllicc gr7,#24,gr0,icc0
209 bne icc0,#0,1f
210 cstb.p gr10,@(gr11,gr0) ,cc3,#1
211 corcc gr29,gr29,gr0 ,cc3,#1
212 beq icc3,#0,0b
2131:
214 bralr
215
216 .size __cmpxchg_8, .-__cmpxchg_8
217
218###############################################################################
219#
220# uint16_t __cmpxchg_16(uint16_t *v, uint16_t test, uint16_t new)
221#
222###############################################################################
223 .globl __cmpxchg_16
224 .type __cmpxchg_16,@function
225__cmpxchg_16:
226 or.p gr8,gr8,gr11
2270:
228 orcc gr0,gr0,gr0,icc3
229 ckeq icc3,cc7
230 lduh.p @(gr11,gr0),gr8
231 orcr cc7,cc7,cc3
232 sub gr8,gr9,gr7
233 sllicc gr7,#16,gr0,icc0
234 bne icc0,#0,1f
235 csth.p gr10,@(gr11,gr0) ,cc3,#1
236 corcc gr29,gr29,gr0 ,cc3,#1
237 beq icc3,#0,0b
2381:
239 bralr
240
241 .size __cmpxchg_16, .-__cmpxchg_16
242
243###############################################################################
244#
245# uint32_t __cmpxchg_32(uint32_t *v, uint32_t test, uint32_t new)
246#
247###############################################################################
248 .globl __cmpxchg_32
249 .type __cmpxchg_32,@function
250__cmpxchg_32:
251 or.p gr8,gr8,gr11
2520:
253 orcc gr0,gr0,gr0,icc3
254 ckeq icc3,cc7
255 ld.p @(gr11,gr0),gr8
256 orcr cc7,cc7,cc3
257 subcc gr8,gr9,gr7,icc0
258 bne icc0,#0,1f
259 cst.p gr10,@(gr11,gr0) ,cc3,#1
260 corcc gr29,gr29,gr0 ,cc3,#1
261 beq icc3,#0,0b
2621:
263 bralr
264
265 .size __cmpxchg_32, .-__cmpxchg_32
diff --git a/arch/frv/lib/cache.S b/arch/frv/lib/cache.S
new file mode 100644
index 000000000000..0e10ad8dc462
--- /dev/null
+++ b/arch/frv/lib/cache.S
@@ -0,0 +1,98 @@
1/* cache.S: cache managment routines
2 *
3 * Copyright (C) 2004 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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
12#include <asm/spr-regs.h>
13#include <asm/cache.h>
14
15 .text
16 .p2align 4
17
18###############################################################################
19#
20# Write back a range of dcache
21# - void frv_dcache_writeback(unsigned long start [GR8], unsigned long size [GR9])
22#
23###############################################################################
24 .globl frv_dcache_writeback
25 .type frv_dcache_writeback,@function
26frv_dcache_writeback:
27 andi gr8,~(L1_CACHE_BYTES-1),gr8
28
292: dcf @(gr8,gr0)
30 addi gr8,#L1_CACHE_BYTES,gr8
31 cmp gr9,gr8,icc0
32 bhi icc0,#2,2b
33
34 membar
35 bralr
36 .size frv_dcache_writeback, .-frv_dcache_writeback
37
38##############################################################################
39#
40# Invalidate a range of dcache and icache
41# - void frv_cache_invalidate(unsigned long start [GR8], unsigned long end [GR9]);
42#
43###############################################################################
44 .globl frv_cache_invalidate
45 .type frv_cache_invalidate,@function
46frv_cache_invalidate:
47 andi gr8,~(L1_CACHE_BYTES-1),gr8
48
492: dci @(gr8,gr0)
50 ici @(gr8,gr0)
51 addi gr8,#L1_CACHE_BYTES,gr8
52 cmp gr9,gr8,icc0
53 bhi icc0,#2,2b
54
55 membar
56 bralr
57 .size frv_cache_invalidate, .-frv_cache_invalidate
58
59##############################################################################
60#
61# Invalidate a range of icache
62# - void frv_icache_invalidate(unsigned long start [GR8], unsigned long end [GR9]);
63#
64###############################################################################
65 .globl frv_icache_invalidate
66 .type frv_icache_invalidate,@function
67frv_icache_invalidate:
68 andi gr8,~(L1_CACHE_BYTES-1),gr8
69
702: ici @(gr8,gr0)
71 addi gr8,#L1_CACHE_BYTES,gr8
72 cmp gr9,gr8,icc0
73 bhi icc0,#2,2b
74
75 membar
76 bralr
77 .size frv_icache_invalidate, .-frv_icache_invalidate
78
79###############################################################################
80#
81# Write back and invalidate a range of dcache and icache
82# - void frv_cache_wback_inv(unsigned long start [GR8], unsigned long end [GR9])
83#
84###############################################################################
85 .globl frv_cache_wback_inv
86 .type frv_cache_wback_inv,@function
87frv_cache_wback_inv:
88 andi gr8,~(L1_CACHE_BYTES-1),gr8
89
902: dcf @(gr8,gr0)
91 ici @(gr8,gr0)
92 addi gr8,#L1_CACHE_BYTES,gr8
93 cmp gr9,gr8,icc0
94 bhi icc0,#2,2b
95
96 membar
97 bralr
98 .size frv_cache_wback_inv, .-frv_cache_wback_inv
diff --git a/arch/frv/lib/checksum.c b/arch/frv/lib/checksum.c
new file mode 100644
index 000000000000..7bf5bd6cac8a
--- /dev/null
+++ b/arch/frv/lib/checksum.c
@@ -0,0 +1,148 @@
1/*
2 * INET An implementation of the TCP/IP protocol suite for the LINUX
3 * operating system. INET is implemented using the BSD Socket
4 * interface as the means of communication with the user level.
5 *
6 * IP/TCP/UDP checksumming routines
7 *
8 * Authors: Jorge Cwik, <jorge@laser.satlink.net>
9 * Arnt Gulbrandsen, <agulbra@nvg.unit.no>
10 * Tom May, <ftom@netcom.com>
11 * Andreas Schwab, <schwab@issan.informatik.uni-dortmund.de>
12 * Lots of code moved from tcp.c and ip.c; see those files
13 * for more names.
14 *
15 * 03/02/96 Jes Sorensen, Andreas Schwab, Roman Hodek:
16 * Fixed some nasty bugs, causing some horrible crashes.
17 * A: At some points, the sum (%0) was used as
18 * length-counter instead of the length counter
19 * (%1). Thanks to Roman Hodek for pointing this out.
20 * B: GCC seems to mess up if one uses too many
21 * data-registers to hold input values and one tries to
22 * specify d0 and d1 as scratch registers. Letting gcc choose these
23 * registers itself solves the problem.
24 *
25 * This program is free software; you can redistribute it and/or
26 * modify it under the terms of the GNU General Public License
27 * as published by the Free Software Foundation; either version
28 * 2 of the License, or (at your option) any later version.
29 */
30
31/* Revised by Kenneth Albanowski for m68knommu. Basic problem: unaligned access kills, so most
32 of the assembly has to go. */
33
34#include <net/checksum.h>
35#include <asm/checksum.h>
36
37static inline unsigned short from32to16(unsigned long x)
38{
39 /* add up 16-bit and 16-bit for 16+c bit */
40 x = (x & 0xffff) + (x >> 16);
41 /* add up carry.. */
42 x = (x & 0xffff) + (x >> 16);
43 return x;
44}
45
46static unsigned long do_csum(const unsigned char * buff, int len)
47{
48 int odd, count;
49 unsigned long result = 0;
50
51 if (len <= 0)
52 goto out;
53 odd = 1 & (unsigned long) buff;
54 if (odd) {
55 result = *buff;
56 len--;
57 buff++;
58 }
59 count = len >> 1; /* nr of 16-bit words.. */
60 if (count) {
61 if (2 & (unsigned long) buff) {
62 result += *(unsigned short *) buff;
63 count--;
64 len -= 2;
65 buff += 2;
66 }
67 count >>= 1; /* nr of 32-bit words.. */
68 if (count) {
69 unsigned long carry = 0;
70 do {
71 unsigned long w = *(unsigned long *) buff;
72 count--;
73 buff += 4;
74 result += carry;
75 result += w;
76 carry = (w > result);
77 } while (count);
78 result += carry;
79 result = (result & 0xffff) + (result >> 16);
80 }
81 if (len & 2) {
82 result += *(unsigned short *) buff;
83 buff += 2;
84 }
85 }
86 if (len & 1)
87 result += (*buff << 8);
88 result = from32to16(result);
89 if (odd)
90 result = ((result >> 8) & 0xff) | ((result & 0xff) << 8);
91out:
92 return result;
93}
94
95/*
96 * computes the checksum of a memory block at buff, length len,
97 * and adds in "sum" (32-bit)
98 *
99 * returns a 32-bit number suitable for feeding into itself
100 * or csum_tcpudp_magic
101 *
102 * this function must be called with even lengths, except
103 * for the last fragment, which may be odd
104 *
105 * it's best to have buff aligned on a 32-bit boundary
106 */
107unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum)
108{
109 unsigned int result = do_csum(buff, len);
110
111 /* add in old sum, and carry.. */
112 result += sum;
113 if (sum > result)
114 result += 1;
115 return result;
116}
117
118/*
119 * this routine is used for miscellaneous IP-like checksums, mainly
120 * in icmp.c
121 */
122unsigned short ip_compute_csum(const unsigned char * buff, int len)
123{
124 return ~do_csum(buff,len);
125}
126
127/*
128 * copy from fs while checksumming, otherwise like csum_partial
129 */
130
131unsigned int
132csum_partial_copy_from_user(const char *src, char *dst, int len, int sum, int *csum_err)
133{
134 if (csum_err) *csum_err = 0;
135 memcpy(dst, src, len);
136 return csum_partial(dst, len, sum);
137}
138
139/*
140 * copy from ds while checksumming, otherwise like csum_partial
141 */
142
143unsigned int
144csum_partial_copy(const char *src, char *dst, int len, int sum)
145{
146 memcpy(dst, src, len);
147 return csum_partial(dst, len, sum);
148}
diff --git a/arch/frv/lib/insl_ns.S b/arch/frv/lib/insl_ns.S
new file mode 100644
index 000000000000..d1658425a9f7
--- /dev/null
+++ b/arch/frv/lib/insl_ns.S
@@ -0,0 +1,52 @@
1/* insl_ns.S: input array of 4b words from device port without byte swapping
2 *
3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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
12
13 .text
14 .p2align 4
15
16###############################################################################
17#
18# void __insl_ns(unsigned int port, void *buf, int n)
19#
20###############################################################################
21 .globl __insl_ns
22 .type __insl_ns,@function
23__insl_ns:
24 andicc.p gr9,#3,gr0,icc0
25 setlos #4,gr4
26 bne icc0,#0,__insl_ns_misaligned
27 subi gr9,#4,gr9
280:
29 ldi.p @(gr8,#0),gr5
30 subicc gr10,#1,gr10,icc0
31 stu.p gr5,@(gr9,gr4)
32 bhi icc0,#2,0b
33 bralr
34
35__insl_ns_misaligned:
36 subi.p gr9,#1,gr9
37 setlos #1,gr4
380:
39 ldi @(gr8,#0),gr5
40
41 srli gr5,#24,gr6
42 stbu.p gr6,@(gr9,gr4)
43 srli gr5,#16,gr6
44 stbu.p gr6,@(gr9,gr4)
45 srli gr5,#8,gr6
46 stbu.p gr6,@(gr9,gr4)
47 subicc gr10,#1,gr10,icc0
48 stbu.p gr5,@(gr9,gr4)
49 bhi icc0,#2,0b
50 bralr
51
52 .size __insl_ns, .-__insl_ns
diff --git a/arch/frv/lib/insl_sw.S b/arch/frv/lib/insl_sw.S
new file mode 100644
index 000000000000..9b5aa95d069b
--- /dev/null
+++ b/arch/frv/lib/insl_sw.S
@@ -0,0 +1,40 @@
1/* insl_sw.S: input array of 4b words from device port with byte swapping
2 *
3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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
12
13 .text
14 .p2align 4
15
16###############################################################################
17#
18# void __insl_sw(unsigned int port, void *buf, int n)
19#
20###############################################################################
21 .globl __insl_sw
22 .type __insl_sw,@function
23__insl_sw:
24 subi.p gr9,#1,gr9
25 setlos #1,gr4
260:
27 ldi.p @(gr8,#0),gr5 ; get 0xAABBCCDD
28 subicc gr10,#1,gr10,icc0
29
30 stbu.p gr5,@(gr9,gr4) ; write 0xDD
31 srli gr5,#8,gr5
32 stbu.p gr5,@(gr9,gr4) ; write 0xCC
33 srli gr5,#8,gr5
34 stbu.p gr5,@(gr9,gr4) ; write 0xBB
35 srli gr5,#8,gr5
36 stbu.p gr5,@(gr9,gr4) ; write 0xAA
37 bhi icc0,#2,0b
38 bralr
39
40 .size __insl_sw, .-__insl_sw
diff --git a/arch/frv/lib/memcpy.S b/arch/frv/lib/memcpy.S
new file mode 100644
index 000000000000..9c5965273428
--- /dev/null
+++ b/arch/frv/lib/memcpy.S
@@ -0,0 +1,135 @@
1/* memcpy.S: optimised assembly memcpy
2 *
3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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
12
13 .text
14 .p2align 4
15
16###############################################################################
17#
18# void *memcpy(void *to, const char *from, size_t count)
19#
20# - NOTE: must not use any stack. exception detection performs function return
21# to caller's fixup routine, aborting the remainder of the copy
22#
23###############################################################################
24 .globl memcpy,__memcpy_end
25 .type memcpy,@function
26memcpy:
27 or.p gr8,gr9,gr4
28 orcc gr10,gr0,gr0,icc3
29 or.p gr10,gr4,gr4
30 beqlr icc3,#0
31
32 # optimise based on best common alignment for to, from & count
33 andicc.p gr4,#0x0f,gr0,icc0
34 setlos #8,gr11
35 andicc.p gr4,#0x07,gr0,icc1
36 beq icc0,#0,memcpy_16
37 andicc.p gr4,#0x03,gr0,icc0
38 beq icc1,#0,memcpy_8
39 andicc.p gr4,#0x01,gr0,icc1
40 beq icc0,#0,memcpy_4
41 setlos.p #1,gr11
42 beq icc1,#0,memcpy_2
43
44 # do byte by byte copy
45 sub.p gr8,gr11,gr3
46 sub gr9,gr11,gr9
470: ldubu.p @(gr9,gr11),gr4
48 subicc gr10,#1,gr10,icc0
49 stbu.p gr4,@(gr3,gr11)
50 bne icc0,#2,0b
51 bralr
52
53 # do halfword by halfword copy
54memcpy_2:
55 setlos #2,gr11
56 sub.p gr8,gr11,gr3
57 sub gr9,gr11,gr9
580: lduhu.p @(gr9,gr11),gr4
59 subicc gr10,#2,gr10,icc0
60 sthu.p gr4,@(gr3,gr11)
61 bne icc0,#2,0b
62 bralr
63
64 # do word by word copy
65memcpy_4:
66 setlos #4,gr11
67 sub.p gr8,gr11,gr3
68 sub gr9,gr11,gr9
690: ldu.p @(gr9,gr11),gr4
70 subicc gr10,#4,gr10,icc0
71 stu.p gr4,@(gr3,gr11)
72 bne icc0,#2,0b
73 bralr
74
75 # do double-word by double-word copy
76memcpy_8:
77 sub.p gr8,gr11,gr3
78 sub gr9,gr11,gr9
790: lddu.p @(gr9,gr11),gr4
80 subicc gr10,#8,gr10,icc0
81 stdu.p gr4,@(gr3,gr11)
82 bne icc0,#2,0b
83 bralr
84
85 # do quad-word by quad-word copy
86memcpy_16:
87 sub.p gr8,gr11,gr3
88 sub gr9,gr11,gr9
890: lddu @(gr9,gr11),gr4
90 lddu.p @(gr9,gr11),gr6
91 subicc gr10,#16,gr10,icc0
92 stdu gr4,@(gr3,gr11)
93 stdu.p gr6,@(gr3,gr11)
94 bne icc0,#2,0b
95 bralr
96__memcpy_end:
97
98 .size memcpy, __memcpy_end-memcpy
99
100###############################################################################
101#
102# copy to/from userspace
103# - return the number of bytes that could not be copied (0 on complete success)
104#
105# long __memcpy_user(void *dst, const void *src, size_t count)
106#
107###############################################################################
108 .globl __memcpy_user, __memcpy_user_error_lr, __memcpy_user_error_handler
109 .type __memcpy_user,@function
110__memcpy_user:
111 movsg lr,gr7
112 subi.p sp,#8,sp
113 add gr8,gr10,gr6 ; calculate expected end address
114 stdi gr6,@(sp,#0)
115
116 # abuse memcpy to do the dirty work
117 call memcpy
118__memcpy_user_error_lr:
119 ldi.p @(sp,#4),gr7
120 setlos #0,gr8
121 jmpl.p @(gr7,gr0)
122 addi sp,#8,sp
123
124 # deal any exception generated by memcpy
125 # GR8 - memcpy's current dest address
126 # GR11 - memset's step value (index register for store insns)
127__memcpy_user_error_handler:
128 lddi.p @(sp,#0),gr4 ; load GR4 with dst+count, GR5 with ret addr
129 add gr11,gr3,gr7
130 sub.p gr4,gr7,gr8
131
132 addi sp,#8,sp
133 jmpl @(gr5,gr0)
134
135 .size __memcpy_user, .-__memcpy_user
diff --git a/arch/frv/lib/memset.S b/arch/frv/lib/memset.S
new file mode 100644
index 000000000000..55a35263cbe3
--- /dev/null
+++ b/arch/frv/lib/memset.S
@@ -0,0 +1,182 @@
1/* memset.S: optimised assembly memset
2 *
3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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
12
13 .text
14 .p2align 4
15
16###############################################################################
17#
18# void *memset(void *p, char ch, size_t count)
19#
20# - NOTE: must not use any stack. exception detection performs function return
21# to caller's fixup routine, aborting the remainder of the set
22# GR4, GR7, GR8, and GR11 must be managed
23#
24###############################################################################
25 .globl memset,__memset_end
26 .type memset,@function
27memset:
28 orcc.p gr10,gr0,gr5,icc3 ; GR5 = count
29 andi gr9,#0xff,gr9
30 or.p gr8,gr0,gr4 ; GR4 = address
31 beqlr icc3,#0
32
33 # conditionally write a byte to 2b-align the address
34 setlos.p #1,gr6
35 andicc gr4,#1,gr0,icc0
36 ckne icc0,cc7
37 cstb.p gr9,@(gr4,gr0) ,cc7,#1
38 csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3
39 cadd.p gr4,gr6,gr4 ,cc7,#1
40 beqlr icc3,#0
41
42 # conditionally write a word to 4b-align the address
43 andicc.p gr4,#2,gr0,icc0
44 subicc gr5,#2,gr0,icc1
45 setlos.p #2,gr6
46 ckne icc0,cc7
47 slli.p gr9,#8,gr12 ; need to double up the pattern
48 cknc icc1,cc5
49 or.p gr9,gr12,gr12
50 andcr cc7,cc5,cc7
51
52 csth.p gr12,@(gr4,gr0) ,cc7,#1
53 csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3
54 cadd.p gr4,gr6,gr4 ,cc7,#1
55 beqlr icc3,#0
56
57 # conditionally write a dword to 8b-align the address
58 andicc.p gr4,#4,gr0,icc0
59 subicc gr5,#4,gr0,icc1
60 setlos.p #4,gr6
61 ckne icc0,cc7
62 slli.p gr12,#16,gr13 ; need to quadruple-up the pattern
63 cknc icc1,cc5
64 or.p gr13,gr12,gr12
65 andcr cc7,cc5,cc7
66
67 cst.p gr12,@(gr4,gr0) ,cc7,#1
68 csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3
69 cadd.p gr4,gr6,gr4 ,cc7,#1
70 beqlr icc3,#0
71
72 or.p gr12,gr12,gr13 ; need to octuple-up the pattern
73
74 # the address is now 8b-aligned - loop around writing 64b chunks
75 setlos #8,gr7
76 subi.p gr4,#8,gr4 ; store with update index does weird stuff
77 setlos #64,gr6
78
79 subicc gr5,#64,gr0,icc0
800: cknc icc0,cc7
81 cstdu gr12,@(gr4,gr7) ,cc7,#1
82 cstdu gr12,@(gr4,gr7) ,cc7,#1
83 cstdu gr12,@(gr4,gr7) ,cc7,#1
84 cstdu gr12,@(gr4,gr7) ,cc7,#1
85 cstdu gr12,@(gr4,gr7) ,cc7,#1
86 cstdu.p gr12,@(gr4,gr7) ,cc7,#1
87 csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3
88 cstdu.p gr12,@(gr4,gr7) ,cc7,#1
89 subicc gr5,#64,gr0,icc0
90 cstdu.p gr12,@(gr4,gr7) ,cc7,#1
91 beqlr icc3,#0
92 bnc icc0,#2,0b
93
94 # now do 32-byte remnant
95 subicc.p gr5,#32,gr0,icc0
96 setlos #32,gr6
97 cknc icc0,cc7
98 cstdu.p gr12,@(gr4,gr7) ,cc7,#1
99 csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3
100 cstdu.p gr12,@(gr4,gr7) ,cc7,#1
101 setlos #16,gr6
102 cstdu.p gr12,@(gr4,gr7) ,cc7,#1
103 subicc gr5,#16,gr0,icc0
104 cstdu.p gr12,@(gr4,gr7) ,cc7,#1
105 beqlr icc3,#0
106
107 # now do 16-byte remnant
108 cknc icc0,cc7
109 cstdu.p gr12,@(gr4,gr7) ,cc7,#1
110 csubcc gr5,gr6,gr5 ,cc7,#1 ; also set ICC3
111 cstdu.p gr12,@(gr4,gr7) ,cc7,#1
112 beqlr icc3,#0
113
114 # now do 8-byte remnant
115 subicc gr5,#8,gr0,icc1
116 cknc icc1,cc7
117 cstdu.p gr12,@(gr4,gr7) ,cc7,#1
118 csubcc gr5,gr7,gr5 ,cc7,#1 ; also set ICC3
119 setlos.p #4,gr7
120 beqlr icc3,#0
121
122 # now do 4-byte remnant
123 subicc gr5,#4,gr0,icc0
124 addi.p gr4,#4,gr4
125 cknc icc0,cc7
126 cstu.p gr12,@(gr4,gr7) ,cc7,#1
127 csubcc gr5,gr7,gr5 ,cc7,#1 ; also set ICC3
128 subicc.p gr5,#2,gr0,icc1
129 beqlr icc3,#0
130
131 # now do 2-byte remnant
132 setlos #2,gr7
133 addi.p gr4,#2,gr4
134 cknc icc1,cc7
135 csthu.p gr12,@(gr4,gr7) ,cc7,#1
136 csubcc gr5,gr7,gr5 ,cc7,#1 ; also set ICC3
137 subicc.p gr5,#1,gr0,icc0
138 beqlr icc3,#0
139
140 # now do 1-byte remnant
141 setlos #0,gr7
142 addi.p gr4,#2,gr4
143 cknc icc0,cc7
144 cstb.p gr12,@(gr4,gr0) ,cc7,#1
145 bralr
146__memset_end:
147
148 .size memset, __memset_end-memset
149
150###############################################################################
151#
152# clear memory in userspace
153# - return the number of bytes that could not be cleared (0 on complete success)
154#
155# long __memset_user(void *p, size_t count)
156#
157###############################################################################
158 .globl __memset_user, __memset_user_error_lr, __memset_user_error_handler
159 .type __memset_user,@function
160__memset_user:
161 movsg lr,gr11
162
163 # abuse memset to do the dirty work
164 or.p gr9,gr9,gr10
165 setlos #0,gr9
166 call memset
167__memset_user_error_lr:
168 jmpl.p @(gr11,gr0)
169 setlos #0,gr8
170
171 # deal any exception generated by memset
172 # GR4 - memset's address tracking pointer
173 # GR7 - memset's step value (index register for store insns)
174 # GR8 - memset's original start address
175 # GR10 - memset's original count
176__memset_user_error_handler:
177 add.p gr4,gr7,gr4
178 add gr8,gr10,gr8
179 jmpl.p @(gr11,gr0)
180 sub gr8,gr4,gr8 ; we return the amount left uncleared
181
182 .size __memset_user, .-__memset_user
diff --git a/arch/frv/lib/outsl_ns.S b/arch/frv/lib/outsl_ns.S
new file mode 100644
index 000000000000..4cd4c46a6966
--- /dev/null
+++ b/arch/frv/lib/outsl_ns.S
@@ -0,0 +1,59 @@
1/* outsl_ns.S: output array of 4b words to device without byte swapping
2 *
3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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
12
13 .text
14 .p2align 4
15
16###############################################################################
17#
18# void __outsl_ns(unsigned int port, const void *buf, int n)
19#
20###############################################################################
21 .globl __outsl_ns
22 .type __outsl_ns,@function
23__outsl_ns:
24 andicc.p gr9,#3,gr0,icc0
25 setlos #4,gr4
26 bne icc0,#0,__outsl_ns_misaligned
27 subi gr9,#4,gr9
280:
29 ldu.p @(gr9,gr4),gr5
30 subicc gr10,#1,gr10,icc0
31 sti.p gr5,@(gr8,#0)
32 bhi icc0,#2,0b
33
34 membar
35 bralr
36
37__outsl_ns_misaligned:
38 subi.p gr9,#1,gr9
39 setlos #1,gr4
400:
41 ldubu @(gr9,gr4),gr5
42 ldubu.p @(gr9,gr4),gr6
43 slli gr5,#8,gr5
44 ldubu.p @(gr9,gr4),gr7
45 or gr5,gr6,gr5
46 ldubu.p @(gr9,gr4),gr6
47 slli gr5,#16,gr5
48 slli.p gr7,#8,gr7
49 or gr5,gr6,gr5
50 subicc.p gr10,#1,gr10,icc0
51 or gr5,gr7,gr5
52
53 sti.p gr5,@(gr8,#0)
54 bhi icc0,#2,0b
55
56 membar
57 bralr
58
59 .size __outsl_ns, .-__outsl_ns
diff --git a/arch/frv/lib/outsl_sw.S b/arch/frv/lib/outsl_sw.S
new file mode 100644
index 000000000000..7eb56d35a956
--- /dev/null
+++ b/arch/frv/lib/outsl_sw.S
@@ -0,0 +1,45 @@
1/* outsl_ns.S: output array of 4b words to device with byte swapping
2 *
3 * Copyright (C) 2003 Red Hat, Inc. All Rights Reserved.
4 * Written by David Howells (dhowells@redhat.com)
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
12
13 .text
14 .p2align 4
15
16###############################################################################
17#
18# void __outsl_sw(unsigned int port, const void *buf, int n)
19#
20###############################################################################
21 .globl __outsl_sw
22 .type __outsl_sw,@function
23__outsl_sw:
24 subi.p gr9,#1,gr9
25 setlos #1,gr4
260:
27 ldubu @(gr9,gr4),gr5
28 ldubu @(gr9,gr4),gr6
29 slli gr6,#8,gr6
30 ldubu.p @(gr9,gr4),gr7
31 or gr5,gr6,gr5
32 ldubu.p @(gr9,gr4),gr6
33 slli gr7,#16,gr7
34 slli.p gr6,#24,gr6
35 or gr5,gr7,gr5
36 subicc.p gr10,#1,gr10,icc0
37 or gr5,gr6,gr5
38
39 sti.p gr5,@(gr8,#0)
40 bhi icc0,#2,0b
41
42 membar
43 bralr
44
45 .size __outsl_sw, .-__outsl_sw