/* SPDX-License-Identifier: GPL-2.0 */
/* csum_copy.S: Checksum+copy code for sparc64
*
* Copyright (C) 2005 David S. Miller <davem@davemloft.net>
*/
#include <linux/export.h>
#ifdef __KERNEL__
#define GLOBAL_SPARE %g7
#else
#define GLOBAL_SPARE %g5
#endif
#ifndef EX_LD
#define EX_LD(x) x
#endif
#ifndef EX_ST
#define EX_ST(x) x
#endif
#ifndef EX_RETVAL
#define EX_RETVAL(x) x
#endif
#ifndef LOAD
#define LOAD(type,addr,dest) type [addr], dest
#endif
#ifndef STORE
#define STORE(type,src,addr) type src, [addr]
#endif
#ifndef FUNC_NAME
#define FUNC_NAME csum_partial_copy_nocheck
#endif
.register %g2, #scratch
.register %g3, #scratch
.text
90 :
/* We checked for zero length already, so there must be
* at least one byte.
*/
be,pt %icc, 1 f
nop
EX_LD(LOAD(ldub, %o0 + 0 x00, %o4))
add %o0, 1 , %o0
sub %o2, 1 , %o2
EX_ST(STORE(stb, %o4, %o1 + 0 x00))
add %o1, 1 , %o1
1 : andcc %o0, 0 x2, %g0
be,pn %icc, 80 f
cmp %o2, 2
blu,pn %icc, 60 f
nop
EX_LD(LOAD(lduh, %o0 + 0 x00, %o5))
add %o0, 2 , %o0
sub %o2, 2 , %o2
EX_ST(STORE(sth, %o5, %o1 + 0 x00))
add %o1, 2 , %o1
ba,pt %xcc, 80 f
add %o5, %o4, %o4
.globl FUNC_NAME
.type FUNC_NAME,#function
EXPORT_SYMBOL(FUNC_NAME)
FUNC_NAME: /* %o0=src, %o1=dst, %o2=len */
LOAD(prefetch, %o0 + 0 x000, #n_reads)
xor %o0, %o1, %g1
mov -1 , %o3
clr %o4
andcc %g1, 0 x3, %g0
bne,pn %icc, 95 f
LOAD(prefetch, %o0 + 0 x040, #n_reads)
brz,pn %o2, 70 f
andcc %o0, 0 x3, %g0
/* We "remember" whether the lowest bit in the address
* was set in GLOBAL_SPARE. Because if it is, we have to swap
* upper and lower 8 bit fields of the sum we calculate.
*/
bne,pn %icc, 90 b
andcc %o0, 0 x1, GLOBAL_SPARE
80 :
LOAD(prefetch, %o0 + 0 x080, #n_reads)
andncc %o2, 0 x3f, %g3
LOAD(prefetch, %o0 + 0 x0c0, #n_reads)
sub %o2, %g3, %o2
brz,pn %g3, 2 f
LOAD(prefetch, %o0 + 0 x100, #n_reads)
/* So that we don't need to use the non-pairing
* add-with-carry instructions we accumulate 32-bit
* values into a 64-bit register. At the end of the
* loop we fold it down to 32-bits and so on.
*/
ba,pt %xcc, 1 f
LOAD(prefetch, %o0 + 0 x140, #n_reads)
.align 32
1 : EX_LD(LOAD(lduw, %o0 + 0 x00, %o5))
EX_LD(LOAD(lduw, %o0 + 0 x04, %g1))
EX_LD(LOAD(lduw, %o0 + 0 x08, %g2))
add %o4, %o5, %o4
EX_ST(STORE(stw, %o5, %o1 + 0 x00))
EX_LD(LOAD(lduw, %o0 + 0 x0c, %o5))
add %o4, %g1, %o4
EX_ST(STORE(stw, %g1, %o1 + 0 x04))
EX_LD(LOAD(lduw, %o0 + 0 x10, %g1))
add %o4, %g2, %o4
EX_ST(STORE(stw, %g2, %o1 + 0 x08))
EX_LD(LOAD(lduw, %o0 + 0 x14, %g2))
add %o4, %o5, %o4
EX_ST(STORE(stw, %o5, %o1 + 0 x0c))
EX_LD(LOAD(lduw, %o0 + 0 x18, %o5))
add %o4, %g1, %o4
EX_ST(STORE(stw, %g1, %o1 + 0 x10))
EX_LD(LOAD(lduw, %o0 + 0 x1c, %g1))
add %o4, %g2, %o4
EX_ST(STORE(stw, %g2, %o1 + 0 x14))
EX_LD(LOAD(lduw, %o0 + 0 x20, %g2))
add %o4, %o5, %o4
EX_ST(STORE(stw, %o5, %o1 + 0 x18))
EX_LD(LOAD(lduw, %o0 + 0 x24, %o5))
add %o4, %g1, %o4
EX_ST(STORE(stw, %g1, %o1 + 0 x1c))
EX_LD(LOAD(lduw, %o0 + 0 x28, %g1))
add %o4, %g2, %o4
EX_ST(STORE(stw, %g2, %o1 + 0 x20))
EX_LD(LOAD(lduw, %o0 + 0 x2c, %g2))
add %o4, %o5, %o4
EX_ST(STORE(stw, %o5, %o1 + 0 x24))
EX_LD(LOAD(lduw, %o0 + 0 x30, %o5))
add %o4, %g1, %o4
EX_ST(STORE(stw, %g1, %o1 + 0 x28))
EX_LD(LOAD(lduw, %o0 + 0 x34, %g1))
add %o4, %g2, %o4
EX_ST(STORE(stw, %g2, %o1 + 0 x2c))
EX_LD(LOAD(lduw, %o0 + 0 x38, %g2))
add %o4, %o5, %o4
EX_ST(STORE(stw, %o5, %o1 + 0 x30))
EX_LD(LOAD(lduw, %o0 + 0 x3c, %o5))
add %o4, %g1, %o4
EX_ST(STORE(stw, %g1, %o1 + 0 x34))
LOAD(prefetch, %o0 + 0 x180, #n_reads)
add %o4, %g2, %o4
EX_ST(STORE(stw, %g2, %o1 + 0 x38))
subcc %g3, 0 x40, %g3
add %o0, 0 x40, %o0
add %o4, %o5, %o4
EX_ST(STORE(stw, %o5, %o1 + 0 x3c))
bne,pt %icc, 1 b
add %o1, 0 x40, %o1
2 : and %o2, 0 x3c, %g3
brz,pn %g3, 2 f
sub %o2, %g3, %o2
1 : EX_LD(LOAD(lduw, %o0 + 0 x00, %o5))
subcc %g3, 0 x4, %g3
add %o0, 0 x4, %o0
add %o4, %o5, %o4
EX_ST(STORE(stw, %o5, %o1 + 0 x00))
bne,pt %icc, 1 b
add %o1, 0 x4, %o1
2 :
/* fold 64-->32 */
srlx %o4, 32 , %o5
srl %o4, 0 , %o4
add %o4, %o5, %o4
srlx %o4, 32 , %o5
srl %o4, 0 , %o4
add %o4, %o5, %o4
/* fold 32-->16 */
sethi %hi (0 xffff0000), %g1
srl %o4, 16 , %o5
andn %o4, %g1, %g2
add %o5, %g2, %o4
srl %o4, 16 , %o5
andn %o4, %g1, %g2
add %o5, %g2, %o4
60 :
/* %o4 has the 16-bit sum we have calculated so-far. */
cmp %o2, 2
blu,pt %icc, 1 f
nop
EX_LD(LOAD(lduh, %o0 + 0 x00, %o5))
sub %o2, 2 , %o2
add %o0, 2 , %o0
add %o4, %o5, %o4
EX_ST(STORE(sth, %o5, %o1 + 0 x00))
add %o1, 0 x2, %o1
1 : brz,pt %o2, 1 f
nop
EX_LD(LOAD(ldub, %o0 + 0 x00, %o5))
sub %o2, 1 , %o2
add %o0, 1 , %o0
EX_ST(STORE(stb, %o5, %o1 + 0 x00))
sllx %o5, 8 , %o5
add %o1, 1 , %o1
add %o4, %o5, %o4
1 :
/* fold 32-->16 */
sethi %hi (0 xffff0000), %g1
srl %o4, 16 , %o5
andn %o4, %g1, %g2
add %o5, %g2, %o4
srl %o4, 16 , %o5
andn %o4, %g1, %g2
add %o5, %g2, %o4
1 : brz,pt GLOBAL_SPARE, 1 f
nop
/* We started with an odd byte, byte-swap the result. */
srl %o4, 8 , %o5
and %o4, 0 xff, %g1
sll %g1, 8 , %g1
or %o5, %g1, %o4
1 : addcc %o3, %o4, %o3
addc %g0, %o3, %o3
70 :
retl
srl %o3, 0 , %o0
95 : mov 0 , GLOBAL_SPARE
brlez,pn %o2, 4 f
andcc %o0, 1 , %o5
be,a,pt %icc, 1 f
srl %o2, 1 , %g1
sub %o2, 1 , %o2
EX_LD(LOAD(ldub, %o0, GLOBAL_SPARE))
add %o0, 1 , %o0
EX_ST(STORE(stb, GLOBAL_SPARE, %o1))
srl %o2, 1 , %g1
add %o1, 1 , %o1
1 : brz,a,pn %g1, 3 f
andcc %o2, 1 , %g0
andcc %o0, 2 , %g0
be,a,pt %icc, 1 f
srl %g1, 1 , %g1
EX_LD(LOAD(lduh, %o0, %o4))
sub %o2, 2 , %o2
srl %o4, 8 , %g2
sub %g1, 1 , %g1
EX_ST(STORE(stb, %g2, %o1))
add %o4, GLOBAL_SPARE, GLOBAL_SPARE
EX_ST(STORE(stb, %o4, %o1 + 1 ))
add %o0, 2 , %o0
srl %g1, 1 , %g1
add %o1, 2 , %o1
1 : brz,a,pn %g1, 2 f
andcc %o2, 2 , %g0
EX_LD(LOAD(lduw, %o0, %o4))
5 : srl %o4, 24 , %g2
srl %o4, 16 , %g3
EX_ST(STORE(stb, %g2, %o1))
srl %o4, 8 , %g2
EX_ST(STORE(stb, %g3, %o1 + 1 ))
add %o0, 4 , %o0
EX_ST(STORE(stb, %g2, %o1 + 2 ))
addcc %o4, GLOBAL_SPARE, GLOBAL_SPARE
EX_ST(STORE(stb, %o4, %o1 + 3 ))
addc GLOBAL_SPARE, %g0, GLOBAL_SPARE
add %o1, 4 , %o1
subcc %g1, 1 , %g1
bne,a,pt %icc, 5 b
EX_LD(LOAD(lduw, %o0, %o4))
sll GLOBAL_SPARE, 16 , %g2
srl GLOBAL_SPARE, 16 , GLOBAL_SPARE
srl %g2, 16 , %g2
andcc %o2, 2 , %g0
add %g2, GLOBAL_SPARE, GLOBAL_SPARE
2 : be,a,pt %icc, 3 f
andcc %o2, 1 , %g0
EX_LD(LOAD(lduh, %o0, %o4))
andcc %o2, 1 , %g0
srl %o4, 8 , %g2
add %o0, 2 , %o0
EX_ST(STORE(stb, %g2, %o1))
add GLOBAL_SPARE, %o4, GLOBAL_SPARE
EX_ST(STORE(stb, %o4, %o1 + 1 ))
add %o1, 2 , %o1
3 : be,a,pt %icc, 1 f
sll GLOBAL_SPARE, 16 , %o4
EX_LD(LOAD(ldub, %o0, %g2))
sll %g2, 8 , %o4
EX_ST(STORE(stb, %g2, %o1))
add GLOBAL_SPARE, %o4, GLOBAL_SPARE
sll GLOBAL_SPARE, 16 , %o4
1 : addcc %o4, GLOBAL_SPARE, GLOBAL_SPARE
srl GLOBAL_SPARE, 16 , %o4
addc %g0, %o4, GLOBAL_SPARE
brz,pt %o5, 4 f
srl GLOBAL_SPARE, 8 , %o4
and GLOBAL_SPARE, 0 xff, %g2
and %o4, 0 xff, %o4
sll %g2, 8 , %g2
or %g2, %o4, GLOBAL_SPARE
4 : addcc %o3, GLOBAL_SPARE, %o3
addc %g0, %o3, %o0
retl
srl %o0, 0 , %o0
.size FUNC_NAME, .-FUNC_NAME
Messung V0.5 in Prozent C=96 H=92 G=93