1 /* csum_copy.S: Checksum+copy code for sparc64
3 * Copyright (C) 2005 David S. Miller <davem@davemloft.net>
6 #include <asm/export.h>
9 #define GLOBAL_SPARE %g7
11 #define GLOBAL_SPARE %g5
23 #define EX_RETVAL(x) x
27 #define LOAD(type,addr,dest) type [addr], dest
31 #define STORE(type,src,addr) type src, [addr]
35 #define FUNC_NAME csum_partial_copy_nocheck
38 .register %g2, #scratch
39 .register %g3, #scratch
44 /* We checked for zero length already, so there must be
49 EX_LD(LOAD(ldub, %o0 + 0x00, %o4))
52 EX_ST(STORE(stb, %o4, %o1 + 0x00))
54 1: andcc %o0, 0x2, %g0
59 EX_LD(LOAD(lduh, %o0 + 0x00, %o5))
62 EX_ST(STORE(sth, %o5, %o1 + 0x00))
68 .type FUNC_NAME,#function
69 EXPORT_SYMBOL(FUNC_NAME)
70 FUNC_NAME: /* %o0=src, %o1=dst, %o2=len, %o3=sum */
71 LOAD(prefetch, %o0 + 0x000, #n_reads)
76 LOAD(prefetch, %o0 + 0x040, #n_reads)
81 /* We "remember" whether the lowest bit in the address
82 * was set in GLOBAL_SPARE. Because if it is, we have to swap
83 * upper and lower 8 bit fields of the sum we calculate.
86 andcc %o0, 0x1, GLOBAL_SPARE
89 LOAD(prefetch, %o0 + 0x080, #n_reads)
92 LOAD(prefetch, %o0 + 0x0c0, #n_reads)
95 LOAD(prefetch, %o0 + 0x100, #n_reads)
97 /* So that we don't need to use the non-pairing
98 * add-with-carry instructions we accumulate 32-bit
99 * values into a 64-bit register. At the end of the
100 * loop we fold it down to 32-bits and so on.
103 LOAD(prefetch, %o0 + 0x140, #n_reads)
106 1: EX_LD(LOAD(lduw, %o0 + 0x00, %o5))
107 EX_LD(LOAD(lduw, %o0 + 0x04, %g1))
108 EX_LD(LOAD(lduw, %o0 + 0x08, %g2))
110 EX_ST(STORE(stw, %o5, %o1 + 0x00))
111 EX_LD(LOAD(lduw, %o0 + 0x0c, %o5))
113 EX_ST(STORE(stw, %g1, %o1 + 0x04))
114 EX_LD(LOAD(lduw, %o0 + 0x10, %g1))
116 EX_ST(STORE(stw, %g2, %o1 + 0x08))
117 EX_LD(LOAD(lduw, %o0 + 0x14, %g2))
119 EX_ST(STORE(stw, %o5, %o1 + 0x0c))
120 EX_LD(LOAD(lduw, %o0 + 0x18, %o5))
122 EX_ST(STORE(stw, %g1, %o1 + 0x10))
123 EX_LD(LOAD(lduw, %o0 + 0x1c, %g1))
125 EX_ST(STORE(stw, %g2, %o1 + 0x14))
126 EX_LD(LOAD(lduw, %o0 + 0x20, %g2))
128 EX_ST(STORE(stw, %o5, %o1 + 0x18))
129 EX_LD(LOAD(lduw, %o0 + 0x24, %o5))
131 EX_ST(STORE(stw, %g1, %o1 + 0x1c))
132 EX_LD(LOAD(lduw, %o0 + 0x28, %g1))
134 EX_ST(STORE(stw, %g2, %o1 + 0x20))
135 EX_LD(LOAD(lduw, %o0 + 0x2c, %g2))
137 EX_ST(STORE(stw, %o5, %o1 + 0x24))
138 EX_LD(LOAD(lduw, %o0 + 0x30, %o5))
140 EX_ST(STORE(stw, %g1, %o1 + 0x28))
141 EX_LD(LOAD(lduw, %o0 + 0x34, %g1))
143 EX_ST(STORE(stw, %g2, %o1 + 0x2c))
144 EX_LD(LOAD(lduw, %o0 + 0x38, %g2))
146 EX_ST(STORE(stw, %o5, %o1 + 0x30))
147 EX_LD(LOAD(lduw, %o0 + 0x3c, %o5))
149 EX_ST(STORE(stw, %g1, %o1 + 0x34))
150 LOAD(prefetch, %o0 + 0x180, #n_reads)
152 EX_ST(STORE(stw, %g2, %o1 + 0x38))
156 EX_ST(STORE(stw, %o5, %o1 + 0x3c))
160 2: and %o2, 0x3c, %g3
163 1: EX_LD(LOAD(lduw, %o0 + 0x00, %o5))
167 EX_ST(STORE(stw, %o5, %o1 + 0x00))
181 sethi %hi(0xffff0000), %g1
190 /* %o4 has the 16-bit sum we have calculated so-far. */
194 EX_LD(LOAD(lduh, %o0 + 0x00, %o5))
198 EX_ST(STORE(sth, %o5, %o1 + 0x00))
202 EX_LD(LOAD(ldub, %o0 + 0x00, %o5))
205 EX_ST(STORE(stb, %o5, %o1 + 0x00))
211 sethi %hi(0xffff0000), %g1
219 1: brz,pt GLOBAL_SPARE, 1f
222 /* We started with an odd byte, byte-swap the result. */
228 1: addcc %o3, %o4, %o3
235 95: mov 0, GLOBAL_SPARE
241 EX_LD(LOAD(ldub, %o0, GLOBAL_SPARE))
243 EX_ST(STORE(stb, GLOBAL_SPARE, %o1))
251 EX_LD(LOAD(lduh, %o0, %o4))
255 EX_ST(STORE(stb, %g2, %o1))
256 add %o4, GLOBAL_SPARE, GLOBAL_SPARE
257 EX_ST(STORE(stb, %o4, %o1 + 1))
263 EX_LD(LOAD(lduw, %o0, %o4))
266 EX_ST(STORE(stb, %g2, %o1))
268 EX_ST(STORE(stb, %g3, %o1 + 1))
270 EX_ST(STORE(stb, %g2, %o1 + 2))
271 addcc %o4, GLOBAL_SPARE, GLOBAL_SPARE
272 EX_ST(STORE(stb, %o4, %o1 + 3))
273 addc GLOBAL_SPARE, %g0, GLOBAL_SPARE
277 EX_LD(LOAD(lduw, %o0, %o4))
278 sll GLOBAL_SPARE, 16, %g2
279 srl GLOBAL_SPARE, 16, GLOBAL_SPARE
282 add %g2, GLOBAL_SPARE, GLOBAL_SPARE
285 EX_LD(LOAD(lduh, %o0, %o4))
289 EX_ST(STORE(stb, %g2, %o1))
290 add GLOBAL_SPARE, %o4, GLOBAL_SPARE
291 EX_ST(STORE(stb, %o4, %o1 + 1))
294 sll GLOBAL_SPARE, 16, %o4
295 EX_LD(LOAD(ldub, %o0, %g2))
297 EX_ST(STORE(stb, %g2, %o1))
298 add GLOBAL_SPARE, %o4, GLOBAL_SPARE
299 sll GLOBAL_SPARE, 16, %o4
300 1: addcc %o4, GLOBAL_SPARE, GLOBAL_SPARE
301 srl GLOBAL_SPARE, 16, %o4
302 addc %g0, %o4, GLOBAL_SPARE
304 srl GLOBAL_SPARE, 8, %o4
305 and GLOBAL_SPARE, 0xff, %g2
308 or %g2, %o4, GLOBAL_SPARE
309 4: addcc %o3, GLOBAL_SPARE, %o3
313 .size FUNC_NAME, .-FUNC_NAME