1/*	$OpenBSD: in_cksum.S,v 1.4 2023/01/04 14:58:04 jsg Exp $	*/
2/*	$NetBSD: in_cksum.S,v 1.2 2001/08/10 20:53:11 eeh Exp $ */
3
4/*
5 * Copyright (c) 2001 Eduardo Horvath
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 *    notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "assym.h"
29#include <machine/asm.h>
30
31/*
32 * int in_cksum(struct mbuf *m, int len)
33 * int in_cksum_internal(struct mbuf *m, int len, int offset, int sum)
34 *
35 * The only fields of the mbuf we really care about
36 * is m_next and m_len and m_data.
37 *
38 *
39 * Register usage:
40 *
41 *	%o0 -	mbuf
42 *	%o1 -	len
43 *	%o2 -	mlen
44 *	%o3 -	sum
45 *	%o4 -	temp
46 *	%o5 -	mdata
47 *	%g1 -	swapped
48 *	%g4 -	temp
49 *	%g5 -	temp
50 */
51
52#define	IALIGN	.align	32
53
54ENTRY(in_cksum)
55	clr	%o3		! sum = 0;
56	clr	%o2
57_ENTRY(in_cksum_internal)
58	brz	%o0, Lfinish	! for (; m && len > 0; m->m_next) {
59	 clr	%g1		! swapped = 0;
60	brlez	%o1, Lfinish
61	 mov	%o2, %o4	! Stash this elsewhere for a bit
62
63	lduw	[%o0 + M_LEN], %o2	! Code duplicated at Lloop
64	srlx	%o3, 32, %g4	! REDUCE bigtime
65	sethi	%hi(0xffff), %g5
66	ldx	[%o0 + M_DATA], %o5
67	srl	%o3, 0, %o3
68	or	%g5, %lo(0xffff), %g5
69
70	sub	%o2, %o4, %o2	! Correct for initial offset
71	ba,pt	%icc, 0f
72	 add	%o5, %o4, %o5
73
74	IALIGN
75Lloop:
76	lduw	[%o0 + M_LEN], %o2
77	srlx	%o3, 32, %g4	! REDUCE bigtime
78	sethi	%hi(0xffff), %g5
79	ldx	[%o0 + M_DATA], %o5
80	srl	%o3, 0, %o3
81	or	%g5, %lo(0xffff), %g5
820:
83	add	%o3, %g4, %o3
84	brz	%o2, Lnext	! if (m->m_len == 0) continue;
85
86	 cmp	%o1, %o2	! if (len < mlen)
87	movl	%icc, %o1, %o2	!	mlen = len;
88
89	btst	3, %o5		! if (!(*w & 3)) {
90	bz	Lint_aligned
91	 sub	%o1, %o2, %o1	! len -= mlen
92
93	srlx	%o3, 16, %o4	! REDUCE {sum = (sum & 0xffff) + (sum >> 16);}
94	and	%o3, %g5, %o3
95
96	add	%o3, %o4, %o3
97	btst	1, %o5		! if (!(*w & 3) &&
98	bz	Lshort_aligned
99	 nop
100
101	deccc	%o2
102	bl,a,pn	%icc, Lnext	! mlen >= 1) {
103	 inc	%o2
104	ldub	[%o5], %o4	! ADDBYTE {ROL; sum += *w; byte_swapped ^= 1;}
105	sllx	%o3, 8, %o3	! ROL { sum = sum << 8; }
106	inc	%o5		! }
107	add	%o3, %o4, %o3
108	xor	%g1, 1, %g1	! Flip byte_swapped
109
110Lshort_aligned:
111	btst	2, %o5		! if (!(*w & 3) &&
112	bz	Lint_aligned
113	 nop
114
115	deccc	2, %o2		! mlen >= 1) {
116	bl,a,pn	%icc, Lfinish_byte
117	 inc	2, %o2
118	lduh	[%o5], %o4	! ADDSHORT {sum += *(u_short *)w;}
119	inc	2, %o5		! }
120	add	%o3, %o4, %o3	! }
121Lint_aligned:
122	deccc	0xc, %o2	! while (mlen >= 12) {
123	ble,pn	%icc, Ltoofar
124	 clr	%g5
125	ba,pt	%icc, 0f
126	 clr	%g4
127	IALIGN
1280:
129	lduw	[%o5 + 0x00], %o4
130	add	%o3, %g4, %o3
131	deccc	0xc, %o2
132	lduw	[%o5 + 0x04], %g4
133	add	%o3, %g5, %o3
134	lduw	[%o5 + 0x08], %g5
135	inc	0xc, %o5	! ADVANCE(12) }
136	bg,pt	%icc, 0b
137	 add	%o3, %o4, %o3
138	add	%o3, %g4, %o3
139	add	%o3, %g5, %o3
140Ltoofar:
141	inc	0xc, %o2
142
143Ldo_int:
144	deccc	4, %o2
145	bl,pn	%icc, Lfinish_short
146	 nop
1470:
148	lduw	[%o5], %o4
149	inc	4, %o5
150	deccc	4, %o2
151	bge,pt	%icc, 0b
152	 add	%o3, %o4, %o3
153
154Lfinish_short:
155	btst	2, %o2
156	bz	Lfinish_byte
157	 nop
158	lduh	[%o5], %o4
159	inc	2, %o5
160	add	%o3, %o4, %o3
161
162Lfinish_byte:
163	btst	1, %o2
164	bz	Lnext
165	 nop
166	ldub	[%o5], %o4
167	sllx	%o3, 8, %o3	! ROL { sum = sum << 8; }
168	inc	%o5
169	xor	%g1, 1, %g1	! Flip byte_swapped
170	add	%o3, %o4, %o3
171
172Lnext:
173	ldx	[%o0 + M_NEXT], %o0
174Lfinish:
175	srlx	%o3, 32, %o4	! Reduce to 32-bits
176	srl	%o3, 0, %o3
177	brz,pt	%o0, 1f		! In general there is only one mbuf
178	 add	%o3, %o4, %o3
179	brgz,pt	%o1, Lloop	! But usually all need to be fully checksummed
180	 nop
1811:
182	sethi	%hi(0x0000ffff), %o5	! data ptr not needed any more
183
184	srlx	%o3, 16, %o4
185	or	%o5, %lo(0x0000ffff), %o5
186
187	and	%o3, %o5, %o3
188
189	add	%o3, %o4, %o3
190	brz,pt	%g1, 0f		! if (byte_swapped) {
191	 nop
192
193	sllx	%o3, 8, %o3	! ROL
194
195	srlx	%o3, 16, %o4	! REDUCE
196	and	%o3, %o5, %o3
197
198	add	%o3, %o4, %o3
1990:
200	subcc	%o3, %o5, %o4	! if (sum > 0xffff)
201	movg	%icc, %o4, %o3	! sum -= 0xffff;
202
203	clr	%g4		! In case we are using EMBEDANY (ick)
204	retl
205	 xor	%o3, %o5, %o0	! return (0xffff ^ sum);
206