xref: /linux/arch/parisc/include/asm/checksum.h (revision 5ea5880764cbb164afb17a62e76ca75dc371409d)
1 /* SPDX-License-Identifier: GPL-2.0 */
2 #ifndef _PARISC_CHECKSUM_H
3 #define _PARISC_CHECKSUM_H
4 
5 #include <linux/in6.h>
6 
7 #define csum_tcpudp_nofold csum_tcpudp_nofold
8 static inline __wsum csum_tcpudp_nofold(__be32 saddr, __be32 daddr,
9 					__u32 len, __u8 proto,
10 					__wsum sum)
11 {
12 	__asm__(
13 	"	add  %1, %0, %0\n"
14 	"	addc %2, %0, %0\n"
15 	"	addc %3, %0, %0\n"
16 	"	addc %%r0, %0, %0\n"
17 		: "=r" (sum)
18 		: "r" (daddr), "r"(saddr), "r"(proto+len), "0"(sum));
19 	return sum;
20 }
21 
22 #include <asm-generic/checksum.h>
23 
24 #define _HAVE_ARCH_IPV6_CSUM
25 static __inline__ __sum16 csum_ipv6_magic(const struct in6_addr *saddr,
26 					  const struct in6_addr *daddr,
27 					  __u32 len, __u8 proto,
28 					  __wsum sum)
29 {
30 	unsigned long t0, t1, t2, t3;
31 
32 	len += proto;	/* add 16-bit proto + len */
33 
34 	__asm__ __volatile__ (
35 
36 #if BITS_PER_LONG > 32
37 
38 	/*
39 	** We can execute two loads and two adds per cycle on PA 8000.
40 	** But add insn's get serialized waiting for the carry bit.
41 	** Try to keep 4 registers with "live" values ahead of the ALU.
42 	*/
43 
44 "	depdi		0, 31, 32, %0\n"/* clear upper half of incoming checksum */
45 "	ldd,ma		8(%1), %4\n"	/* get 1st saddr word */
46 "	ldd,ma		8(%2), %5\n"	/* get 1st daddr word */
47 "	add		%4, %0, %0\n"
48 "	ldd,ma		8(%1), %6\n"	/* 2nd saddr */
49 "	ldd,ma		8(%2), %7\n"	/* 2nd daddr */
50 "	add,dc		%5, %0, %0\n"
51 "	add,dc		%6, %0, %0\n"
52 "	add,dc		%7, %0, %0\n"
53 "	add,dc		%3, %0, %0\n"  /* fold in proto+len | carry bit */
54 "	extrd,u		%0, 31, 32, %4\n"/* copy upper half down */
55 "	depdi		0, 31, 32, %0\n"/* clear upper half */
56 "	add,dc		%4, %0, %0\n"	/* fold into 32-bits, plus carry */
57 "	addc		0, %0, %0\n"	/* add final carry */
58 
59 #else
60 
61 	/*
62 	** For PA 1.x, the insn order doesn't matter as much.
63 	** Insn stream is serialized on the carry bit here too.
64 	** result from the previous operation (eg r0 + x)
65 	*/
66 "	ldw,ma		4(%1), %4\n"	/* get 1st saddr word */
67 "	ldw,ma		4(%2), %5\n"	/* get 1st daddr word */
68 "	add		%4, %0, %0\n"
69 "	ldw,ma		4(%1), %6\n"	/* 2nd saddr */
70 "	addc		%5, %0, %0\n"
71 "	ldw,ma		4(%2), %7\n"	/* 2nd daddr */
72 "	addc		%6, %0, %0\n"
73 "	ldw,ma		4(%1), %4\n"	/* 3rd saddr */
74 "	addc		%7, %0, %0\n"
75 "	ldw,ma		4(%2), %5\n"	/* 3rd daddr */
76 "	addc		%4, %0, %0\n"
77 "	ldw,ma		4(%1), %6\n"	/* 4th saddr */
78 "	addc		%5, %0, %0\n"
79 "	ldw,ma		4(%2), %7\n"	/* 4th daddr */
80 "	addc		%6, %0, %0\n"
81 "	addc		%7, %0, %0\n"
82 "	addc		%3, %0, %0\n"	/* fold in proto+len */
83 "	addc		0, %0, %0\n"	/* add carry */
84 
85 #endif
86 	: "=r" (sum), "=r" (saddr), "=r" (daddr), "=r" (len),
87 	  "=r" (t0), "=r" (t1), "=r" (t2), "=r" (t3)
88 	: "0" (sum), "1" (saddr), "2" (daddr), "3" (len)
89 	: "memory");
90 	return csum_fold(sum);
91 }
92 
93 #endif
94 
95