• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/* SPDX-License-Identifier: GPL-2.0 */
2/*
3 * A fast checksum routine using movem
4 * Copyright (c) 1998-2001 Axis Communications AB
5 *
6 * csum_partial(const unsigned char * buff, int len, unsigned int sum)
7 */
8
9	.globl	csum_partial
10csum_partial:
11
12	;; r10 - src
13	;; r11 - length
14	;; r12 - checksum
15
16	;; check for breakeven length between movem and normal word looping versions
17	;; we also do _NOT_ want to compute a checksum over more than the
18	;; actual length when length < 40
19
20	cmpu.w	80,$r11
21	blo	_word_loop
22	nop
23
24	;; need to save the registers we use below in the movem loop
25	;; this overhead is why we have a check above for breakeven length
26	;; only r0 - r8 have to be saved, the other ones are clobber-able
27	;; according to the ABI
28
29	subq	9*4,$sp
30	movem	$r8,[$sp]
31
32	;; do a movem checksum
33
34	subq	10*4,$r11	; update length for the first loop
35
36_mloop:	movem	[$r10+],$r9	; read 10 longwords
37
38	;; perform dword checksumming on the 10 longwords
39
40	add.d	$r0,$r12
41	ax
42	add.d	$r1,$r12
43	ax
44	add.d	$r2,$r12
45	ax
46	add.d	$r3,$r12
47	ax
48	add.d	$r4,$r12
49	ax
50	add.d	$r5,$r12
51	ax
52	add.d	$r6,$r12
53	ax
54	add.d	$r7,$r12
55	ax
56	add.d	$r8,$r12
57	ax
58	add.d	$r9,$r12
59
60	;; fold the carry into the checksum, to avoid having to loop the carry
61	;; back into the top
62
63	ax
64	addq	0,$r12
65
66	subq	10*4,$r11
67	bge	_mloop
68	nop
69
70	addq	10*4,$r11	; compensate for last loop underflowing length
71
72	movem	[$sp+],$r8	; restore regs
73
74_word_loop:
75	;; only fold if there is anything to fold.
76
77	cmpq	0,$r12
78	beq	_no_fold
79
80	;; fold 32-bit checksum into a 16-bit checksum, to avoid carries below.
81	;; r9 and r13 can be used as temporaries.
82
83	moveq	-1,$r9		; put 0xffff in r9, faster than move.d 0xffff,r9
84	lsrq	16,$r9
85
86	move.d	$r12,$r13
87	lsrq	16,$r13		; r13 = checksum >> 16
88	and.d	$r9,$r12		; checksum = checksum & 0xffff
89	add.d	$r13,$r12		; checksum += r13
90
91_no_fold:
92	cmpq	2,$r11
93	blt	_no_words
94	nop
95
96	;; checksum the rest of the words
97
98	subq	2,$r11
99
100_wloop:	subq	2,$r11
101	bge	_wloop
102	addu.w	[$r10+],$r12
103
104	addq	2,$r11
105
106_no_words:
107	;; see if we have one odd byte more
108	cmpq	1,$r11
109	beq	_do_byte
110	nop
111	ret
112	move.d	$r12, $r10
113
114_do_byte:
115	;; copy and checksum the last byte
116	addu.b	[$r10],$r12
117	ret
118	move.d	$r12, $r10
119
120