xref: /openbmc/linux/arch/sparc/lib/csum_copy.S (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
1b2441318SGreg Kroah-Hartman/* SPDX-License-Identifier: GPL-2.0 */
2478b8fecSSam Ravnborg/* csum_copy.S: Checksum+copy code for sparc64
3478b8fecSSam Ravnborg *
4478b8fecSSam Ravnborg * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
5478b8fecSSam Ravnborg */
6478b8fecSSam Ravnborg
7*4cdb71b6SMasahiro Yamada#include <linux/export.h>
8d3867f04SAl Viro
9478b8fecSSam Ravnborg#ifdef __KERNEL__
10478b8fecSSam Ravnborg#define GLOBAL_SPARE	%g7
11478b8fecSSam Ravnborg#else
12478b8fecSSam Ravnborg#define GLOBAL_SPARE	%g5
13478b8fecSSam Ravnborg#endif
14478b8fecSSam Ravnborg
15478b8fecSSam Ravnborg#ifndef EX_LD
16478b8fecSSam Ravnborg#define EX_LD(x)	x
17478b8fecSSam Ravnborg#endif
18478b8fecSSam Ravnborg
19478b8fecSSam Ravnborg#ifndef EX_ST
20478b8fecSSam Ravnborg#define EX_ST(x)	x
21478b8fecSSam Ravnborg#endif
22478b8fecSSam Ravnborg
23478b8fecSSam Ravnborg#ifndef EX_RETVAL
24478b8fecSSam Ravnborg#define EX_RETVAL(x)	x
25478b8fecSSam Ravnborg#endif
26478b8fecSSam Ravnborg
27478b8fecSSam Ravnborg#ifndef LOAD
28478b8fecSSam Ravnborg#define LOAD(type,addr,dest)	type [addr], dest
29478b8fecSSam Ravnborg#endif
30478b8fecSSam Ravnborg
31478b8fecSSam Ravnborg#ifndef STORE
32478b8fecSSam Ravnborg#define STORE(type,src,addr)	type src, [addr]
33478b8fecSSam Ravnborg#endif
34478b8fecSSam Ravnborg
35478b8fecSSam Ravnborg#ifndef FUNC_NAME
36fdf8bee9SAl Viro#define FUNC_NAME	csum_partial_copy_nocheck
37478b8fecSSam Ravnborg#endif
38478b8fecSSam Ravnborg
39478b8fecSSam Ravnborg	.register	%g2, #scratch
40478b8fecSSam Ravnborg	.register	%g3, #scratch
41478b8fecSSam Ravnborg
42478b8fecSSam Ravnborg	.text
43478b8fecSSam Ravnborg
44478b8fecSSam Ravnborg90:
45478b8fecSSam Ravnborg	/* We checked for zero length already, so there must be
46478b8fecSSam Ravnborg	 * at least one byte.
47478b8fecSSam Ravnborg	 */
48478b8fecSSam Ravnborg	be,pt		%icc, 1f
49478b8fecSSam Ravnborg	 nop
50478b8fecSSam Ravnborg	EX_LD(LOAD(ldub, %o0 + 0x00, %o4))
51478b8fecSSam Ravnborg	add		%o0, 1, %o0
52478b8fecSSam Ravnborg	sub		%o2, 1, %o2
53478b8fecSSam Ravnborg	EX_ST(STORE(stb, %o4, %o1 + 0x00))
54478b8fecSSam Ravnborg	add		%o1, 1, %o1
55478b8fecSSam Ravnborg1:	andcc		%o0, 0x2, %g0
56478b8fecSSam Ravnborg	be,pn		%icc, 80f
57478b8fecSSam Ravnborg	 cmp		%o2, 2
58478b8fecSSam Ravnborg	blu,pn		%icc, 60f
59478b8fecSSam Ravnborg	 nop
60478b8fecSSam Ravnborg	EX_LD(LOAD(lduh, %o0 + 0x00, %o5))
61478b8fecSSam Ravnborg	add		%o0, 2, %o0
62478b8fecSSam Ravnborg	sub		%o2, 2, %o2
63478b8fecSSam Ravnborg	EX_ST(STORE(sth, %o5, %o1 + 0x00))
64478b8fecSSam Ravnborg	add		%o1, 2, %o1
65478b8fecSSam Ravnborg	ba,pt		%xcc, 80f
66478b8fecSSam Ravnborg	 add		%o5, %o4, %o4
67478b8fecSSam Ravnborg
68478b8fecSSam Ravnborg	.globl		FUNC_NAME
69f5a651f1SNagarathnam Muthusamy	.type		FUNC_NAME,#function
70d3867f04SAl Viro	EXPORT_SYMBOL(FUNC_NAME)
71fdf8bee9SAl ViroFUNC_NAME:		/* %o0=src, %o1=dst, %o2=len */
72478b8fecSSam Ravnborg	LOAD(prefetch, %o0 + 0x000, #n_reads)
73478b8fecSSam Ravnborg	xor		%o0, %o1, %g1
746220e48dSAl Viro	mov		-1, %o3
75478b8fecSSam Ravnborg	clr		%o4
76478b8fecSSam Ravnborg	andcc		%g1, 0x3, %g0
77478b8fecSSam Ravnborg	bne,pn		%icc, 95f
78478b8fecSSam Ravnborg	 LOAD(prefetch, %o0 + 0x040, #n_reads)
79478b8fecSSam Ravnborg
80478b8fecSSam Ravnborg	brz,pn		%o2, 70f
81478b8fecSSam Ravnborg	 andcc		%o0, 0x3, %g0
82478b8fecSSam Ravnborg
83478b8fecSSam Ravnborg	/* We "remember" whether the lowest bit in the address
84478b8fecSSam Ravnborg	 * was set in GLOBAL_SPARE.  Because if it is, we have to swap
85478b8fecSSam Ravnborg	 * upper and lower 8 bit fields of the sum we calculate.
86478b8fecSSam Ravnborg	*/
87478b8fecSSam Ravnborg	bne,pn		%icc, 90b
88478b8fecSSam Ravnborg	 andcc		%o0, 0x1, GLOBAL_SPARE
89478b8fecSSam Ravnborg
90478b8fecSSam Ravnborg80:
91478b8fecSSam Ravnborg	LOAD(prefetch, %o0 + 0x080, #n_reads)
92478b8fecSSam Ravnborg	andncc		%o2, 0x3f, %g3
93478b8fecSSam Ravnborg
94478b8fecSSam Ravnborg	LOAD(prefetch, %o0 + 0x0c0, #n_reads)
95478b8fecSSam Ravnborg	sub		%o2, %g3, %o2
96478b8fecSSam Ravnborg	brz,pn		%g3, 2f
97478b8fecSSam Ravnborg	 LOAD(prefetch, %o0 + 0x100, #n_reads)
98478b8fecSSam Ravnborg
99478b8fecSSam Ravnborg	/* So that we don't need to use the non-pairing
100478b8fecSSam Ravnborg	 * add-with-carry instructions we accumulate 32-bit
101478b8fecSSam Ravnborg	 * values into a 64-bit register.  At the end of the
102478b8fecSSam Ravnborg	 * loop we fold it down to 32-bits and so on.
103478b8fecSSam Ravnborg	 */
104478b8fecSSam Ravnborg	ba,pt		%xcc, 1f
105478b8fecSSam Ravnborg	LOAD(prefetch, %o0 + 0x140, #n_reads)
106478b8fecSSam Ravnborg
107478b8fecSSam Ravnborg	.align		32
108478b8fecSSam Ravnborg1:	EX_LD(LOAD(lduw, %o0 + 0x00, %o5))
109478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x04, %g1))
110478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x08, %g2))
111478b8fecSSam Ravnborg	add		%o4, %o5, %o4
112478b8fecSSam Ravnborg	EX_ST(STORE(stw, %o5, %o1 + 0x00))
113478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x0c, %o5))
114478b8fecSSam Ravnborg	add		%o4, %g1, %o4
115478b8fecSSam Ravnborg	EX_ST(STORE(stw, %g1, %o1 + 0x04))
116478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x10, %g1))
117478b8fecSSam Ravnborg	add		%o4, %g2, %o4
118478b8fecSSam Ravnborg	EX_ST(STORE(stw, %g2, %o1 + 0x08))
119478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x14, %g2))
120478b8fecSSam Ravnborg	add		%o4, %o5, %o4
121478b8fecSSam Ravnborg	EX_ST(STORE(stw, %o5, %o1 + 0x0c))
122478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x18, %o5))
123478b8fecSSam Ravnborg	add		%o4, %g1, %o4
124478b8fecSSam Ravnborg	EX_ST(STORE(stw, %g1, %o1 + 0x10))
125478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x1c, %g1))
126478b8fecSSam Ravnborg	add		%o4, %g2, %o4
127478b8fecSSam Ravnborg	EX_ST(STORE(stw, %g2, %o1 + 0x14))
128478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x20, %g2))
129478b8fecSSam Ravnborg	add		%o4, %o5, %o4
130478b8fecSSam Ravnborg	EX_ST(STORE(stw, %o5, %o1 + 0x18))
131478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x24, %o5))
132478b8fecSSam Ravnborg	add		%o4, %g1, %o4
133478b8fecSSam Ravnborg	EX_ST(STORE(stw, %g1, %o1 + 0x1c))
134478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x28, %g1))
135478b8fecSSam Ravnborg	add		%o4, %g2, %o4
136478b8fecSSam Ravnborg	EX_ST(STORE(stw, %g2, %o1 + 0x20))
137478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x2c, %g2))
138478b8fecSSam Ravnborg	add		%o4, %o5, %o4
139478b8fecSSam Ravnborg	EX_ST(STORE(stw, %o5, %o1 + 0x24))
140478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x30, %o5))
141478b8fecSSam Ravnborg	add		%o4, %g1, %o4
142478b8fecSSam Ravnborg	EX_ST(STORE(stw, %g1, %o1 + 0x28))
143478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x34, %g1))
144478b8fecSSam Ravnborg	add		%o4, %g2, %o4
145478b8fecSSam Ravnborg	EX_ST(STORE(stw, %g2, %o1 + 0x2c))
146478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x38, %g2))
147478b8fecSSam Ravnborg	add		%o4, %o5, %o4
148478b8fecSSam Ravnborg	EX_ST(STORE(stw, %o5, %o1 + 0x30))
149478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0 + 0x3c, %o5))
150478b8fecSSam Ravnborg	add		%o4, %g1, %o4
151478b8fecSSam Ravnborg	EX_ST(STORE(stw, %g1, %o1 + 0x34))
152478b8fecSSam Ravnborg	LOAD(prefetch, %o0 + 0x180, #n_reads)
153478b8fecSSam Ravnborg	add		%o4, %g2, %o4
154478b8fecSSam Ravnborg	EX_ST(STORE(stw, %g2, %o1 + 0x38))
155478b8fecSSam Ravnborg	subcc		%g3, 0x40, %g3
156478b8fecSSam Ravnborg	add		%o0, 0x40, %o0
157478b8fecSSam Ravnborg	add		%o4, %o5, %o4
158478b8fecSSam Ravnborg	EX_ST(STORE(stw, %o5, %o1 + 0x3c))
159478b8fecSSam Ravnborg	bne,pt		%icc, 1b
160478b8fecSSam Ravnborg	 add		%o1, 0x40, %o1
161478b8fecSSam Ravnborg
162478b8fecSSam Ravnborg2:	and		%o2, 0x3c, %g3
163478b8fecSSam Ravnborg	brz,pn		%g3, 2f
164478b8fecSSam Ravnborg	 sub		%o2, %g3, %o2
165478b8fecSSam Ravnborg1:	EX_LD(LOAD(lduw, %o0 + 0x00, %o5))
166478b8fecSSam Ravnborg	subcc		%g3, 0x4, %g3
167478b8fecSSam Ravnborg	add		%o0, 0x4, %o0
168478b8fecSSam Ravnborg	add		%o4, %o5, %o4
169478b8fecSSam Ravnborg	EX_ST(STORE(stw, %o5, %o1 + 0x00))
170478b8fecSSam Ravnborg	bne,pt		%icc, 1b
171478b8fecSSam Ravnborg	 add		%o1, 0x4, %o1
172478b8fecSSam Ravnborg
173478b8fecSSam Ravnborg2:
174478b8fecSSam Ravnborg	/* fold 64-->32 */
175478b8fecSSam Ravnborg	srlx		%o4, 32, %o5
176478b8fecSSam Ravnborg	srl		%o4, 0, %o4
177478b8fecSSam Ravnborg	add		%o4, %o5, %o4
178478b8fecSSam Ravnborg	srlx		%o4, 32, %o5
179478b8fecSSam Ravnborg	srl		%o4, 0, %o4
180478b8fecSSam Ravnborg	add		%o4, %o5, %o4
181478b8fecSSam Ravnborg
182478b8fecSSam Ravnborg	/* fold 32-->16 */
183478b8fecSSam Ravnborg	sethi		%hi(0xffff0000), %g1
184478b8fecSSam Ravnborg	srl		%o4, 16, %o5
185478b8fecSSam Ravnborg	andn		%o4, %g1, %g2
186478b8fecSSam Ravnborg	add		%o5, %g2, %o4
187478b8fecSSam Ravnborg	srl		%o4, 16, %o5
188478b8fecSSam Ravnborg	andn		%o4, %g1, %g2
189478b8fecSSam Ravnborg	add		%o5, %g2, %o4
190478b8fecSSam Ravnborg
191478b8fecSSam Ravnborg60:
192478b8fecSSam Ravnborg	/* %o4 has the 16-bit sum we have calculated so-far.  */
193478b8fecSSam Ravnborg	cmp		%o2, 2
194478b8fecSSam Ravnborg	blu,pt		%icc, 1f
195478b8fecSSam Ravnborg	 nop
196478b8fecSSam Ravnborg	EX_LD(LOAD(lduh, %o0 + 0x00, %o5))
197478b8fecSSam Ravnborg	sub		%o2, 2, %o2
198478b8fecSSam Ravnborg	add		%o0, 2, %o0
199478b8fecSSam Ravnborg	add		%o4, %o5, %o4
200478b8fecSSam Ravnborg	EX_ST(STORE(sth, %o5, %o1 + 0x00))
201478b8fecSSam Ravnborg	add		%o1, 0x2, %o1
202478b8fecSSam Ravnborg1:	brz,pt		%o2, 1f
203478b8fecSSam Ravnborg	 nop
204478b8fecSSam Ravnborg	EX_LD(LOAD(ldub, %o0 + 0x00, %o5))
205478b8fecSSam Ravnborg	sub		%o2, 1, %o2
206478b8fecSSam Ravnborg	add		%o0, 1, %o0
207478b8fecSSam Ravnborg	EX_ST(STORE(stb, %o5, %o1 + 0x00))
208478b8fecSSam Ravnborg	sllx		%o5, 8, %o5
209478b8fecSSam Ravnborg	add		%o1, 1, %o1
210478b8fecSSam Ravnborg	add		%o4, %o5, %o4
211478b8fecSSam Ravnborg1:
212478b8fecSSam Ravnborg	/* fold 32-->16 */
213478b8fecSSam Ravnborg	sethi		%hi(0xffff0000), %g1
214478b8fecSSam Ravnborg	srl		%o4, 16, %o5
215478b8fecSSam Ravnborg	andn		%o4, %g1, %g2
216478b8fecSSam Ravnborg	add		%o5, %g2, %o4
217478b8fecSSam Ravnborg	srl		%o4, 16, %o5
218478b8fecSSam Ravnborg	andn		%o4, %g1, %g2
219478b8fecSSam Ravnborg	add		%o5, %g2, %o4
220478b8fecSSam Ravnborg
221478b8fecSSam Ravnborg1:	brz,pt		GLOBAL_SPARE, 1f
222478b8fecSSam Ravnborg	 nop
223478b8fecSSam Ravnborg
224478b8fecSSam Ravnborg	/* We started with an odd byte, byte-swap the result.  */
225478b8fecSSam Ravnborg	srl		%o4, 8, %o5
226478b8fecSSam Ravnborg	and		%o4, 0xff, %g1
227478b8fecSSam Ravnborg	sll		%g1, 8, %g1
228478b8fecSSam Ravnborg	or		%o5, %g1, %o4
229478b8fecSSam Ravnborg
230478b8fecSSam Ravnborg1:	addcc		%o3, %o4, %o3
231478b8fecSSam Ravnborg	addc		%g0, %o3, %o3
232478b8fecSSam Ravnborg
233478b8fecSSam Ravnborg70:
234478b8fecSSam Ravnborg	retl
235478b8fecSSam Ravnborg	 srl		%o3, 0, %o0
236478b8fecSSam Ravnborg
237478b8fecSSam Ravnborg95:	mov		0, GLOBAL_SPARE
238478b8fecSSam Ravnborg	brlez,pn	%o2, 4f
239478b8fecSSam Ravnborg	 andcc		%o0, 1, %o5
240478b8fecSSam Ravnborg	be,a,pt		%icc, 1f
241478b8fecSSam Ravnborg	 srl		%o2, 1, %g1
242478b8fecSSam Ravnborg	sub		%o2, 1, %o2
243478b8fecSSam Ravnborg	EX_LD(LOAD(ldub, %o0, GLOBAL_SPARE))
244478b8fecSSam Ravnborg	add		%o0, 1, %o0
245478b8fecSSam Ravnborg	EX_ST(STORE(stb, GLOBAL_SPARE, %o1))
246478b8fecSSam Ravnborg	srl		%o2, 1, %g1
247478b8fecSSam Ravnborg	add		%o1, 1, %o1
248478b8fecSSam Ravnborg1:	brz,a,pn	%g1, 3f
249478b8fecSSam Ravnborg	 andcc		%o2, 1, %g0
250478b8fecSSam Ravnborg	andcc		%o0, 2, %g0
251478b8fecSSam Ravnborg	be,a,pt		%icc, 1f
252478b8fecSSam Ravnborg	 srl		%g1, 1, %g1
253478b8fecSSam Ravnborg	EX_LD(LOAD(lduh, %o0, %o4))
254478b8fecSSam Ravnborg	sub		%o2, 2, %o2
255478b8fecSSam Ravnborg	srl		%o4, 8, %g2
256478b8fecSSam Ravnborg	sub		%g1, 1, %g1
257478b8fecSSam Ravnborg	EX_ST(STORE(stb, %g2, %o1))
258478b8fecSSam Ravnborg	add		%o4, GLOBAL_SPARE, GLOBAL_SPARE
259478b8fecSSam Ravnborg	EX_ST(STORE(stb, %o4, %o1 + 1))
260478b8fecSSam Ravnborg	add		%o0, 2, %o0
261478b8fecSSam Ravnborg	srl		%g1, 1, %g1
262478b8fecSSam Ravnborg	add		%o1, 2, %o1
263478b8fecSSam Ravnborg1:	brz,a,pn	%g1, 2f
264478b8fecSSam Ravnborg	 andcc		%o2, 2, %g0
265478b8fecSSam Ravnborg	EX_LD(LOAD(lduw, %o0, %o4))
266478b8fecSSam Ravnborg5:	srl		%o4, 24, %g2
267478b8fecSSam Ravnborg	srl		%o4, 16, %g3
268478b8fecSSam Ravnborg	EX_ST(STORE(stb, %g2, %o1))
269478b8fecSSam Ravnborg	srl		%o4, 8, %g2
270478b8fecSSam Ravnborg	EX_ST(STORE(stb, %g3, %o1 + 1))
271478b8fecSSam Ravnborg	add		%o0, 4, %o0
272478b8fecSSam Ravnborg	EX_ST(STORE(stb, %g2, %o1 + 2))
273478b8fecSSam Ravnborg	addcc		%o4, GLOBAL_SPARE, GLOBAL_SPARE
274478b8fecSSam Ravnborg	EX_ST(STORE(stb, %o4, %o1 + 3))
275478b8fecSSam Ravnborg	addc		GLOBAL_SPARE, %g0, GLOBAL_SPARE
276478b8fecSSam Ravnborg	add		%o1, 4, %o1
277478b8fecSSam Ravnborg	subcc		%g1, 1, %g1
278478b8fecSSam Ravnborg	bne,a,pt	%icc, 5b
279478b8fecSSam Ravnborg	 EX_LD(LOAD(lduw, %o0, %o4))
280478b8fecSSam Ravnborg	sll		GLOBAL_SPARE, 16, %g2
281478b8fecSSam Ravnborg	srl		GLOBAL_SPARE, 16, GLOBAL_SPARE
282478b8fecSSam Ravnborg	srl		%g2, 16, %g2
283478b8fecSSam Ravnborg	andcc		%o2, 2, %g0
284478b8fecSSam Ravnborg	add		%g2, GLOBAL_SPARE, GLOBAL_SPARE
285478b8fecSSam Ravnborg2:	be,a,pt		%icc, 3f
286478b8fecSSam Ravnborg	 andcc		%o2, 1, %g0
287478b8fecSSam Ravnborg	EX_LD(LOAD(lduh, %o0, %o4))
288478b8fecSSam Ravnborg	andcc		%o2, 1, %g0
289478b8fecSSam Ravnborg	srl		%o4, 8, %g2
290478b8fecSSam Ravnborg	add		%o0, 2, %o0
291478b8fecSSam Ravnborg	EX_ST(STORE(stb, %g2, %o1))
292478b8fecSSam Ravnborg	add		GLOBAL_SPARE, %o4, GLOBAL_SPARE
293478b8fecSSam Ravnborg	EX_ST(STORE(stb, %o4, %o1 + 1))
294478b8fecSSam Ravnborg	add		%o1, 2, %o1
295478b8fecSSam Ravnborg3:	be,a,pt		%icc, 1f
296478b8fecSSam Ravnborg	 sll		GLOBAL_SPARE, 16, %o4
297478b8fecSSam Ravnborg	EX_LD(LOAD(ldub, %o0, %g2))
298478b8fecSSam Ravnborg	sll		%g2, 8, %o4
299478b8fecSSam Ravnborg	EX_ST(STORE(stb, %g2, %o1))
300478b8fecSSam Ravnborg	add		GLOBAL_SPARE, %o4, GLOBAL_SPARE
301478b8fecSSam Ravnborg	sll		GLOBAL_SPARE, 16, %o4
302478b8fecSSam Ravnborg1:	addcc		%o4, GLOBAL_SPARE, GLOBAL_SPARE
303478b8fecSSam Ravnborg	srl		GLOBAL_SPARE, 16, %o4
304478b8fecSSam Ravnborg	addc		%g0, %o4, GLOBAL_SPARE
305478b8fecSSam Ravnborg	brz,pt		%o5, 4f
306478b8fecSSam Ravnborg	 srl		GLOBAL_SPARE, 8, %o4
307478b8fecSSam Ravnborg	and		GLOBAL_SPARE, 0xff, %g2
308478b8fecSSam Ravnborg	and		%o4, 0xff, %o4
309478b8fecSSam Ravnborg	sll		%g2, 8, %g2
310478b8fecSSam Ravnborg	or		%g2, %o4, GLOBAL_SPARE
311478b8fecSSam Ravnborg4:	addcc		%o3, GLOBAL_SPARE, %o3
312478b8fecSSam Ravnborg	addc		%g0, %o3, %o0
313478b8fecSSam Ravnborg	retl
314478b8fecSSam Ravnborg	 srl		%o0, 0, %o0
315478b8fecSSam Ravnborg	.size		FUNC_NAME, .-FUNC_NAME
316