I also and added some comments about non-obvious goings on in the
__asm__ stuff.
And relaxed some operand constraints to allow operands to be used from
memory, which avoids making gcc allocate a whole pile of registers for
an __asm__ when it doesn't have to.
And I rewrote csum_tcpudp_magic() and ip_compute_csum() in terms of
csum_fold(), which seems to have been added since the last time I
looked at checksum.h.
This patch is against 1.3.97. I've been running with it since April 8
using gcc-2.7.2.
--- linux/include/asm-i386/checksum.h.0 Tue Oct 3 02:45:59 1995
+++ linux/include/asm-i386/checksum.h Mon Apr 8 09:17:57 1996
@@ -65,14 +65,30 @@
notl %0
2:
"
- : "=&r" (sum), "=&r" (iph), "=&r" (ihl)
+ /* Since the input registers which are loaded with iph and ipl
+ are modified, we must also specify them as outputs, or gcc
+ will assume they contain their original values. */
+ : "=r" (sum), "=r" (iph), "=r" (ihl)
: "1" (iph), "2" (ihl));
return(sum);
}
+/*
+ * Fold a partial checksum
+ */
-
-
+static inline unsigned int csum_fold(unsigned int sum)
+{
+ __asm__("
+ addl %1, %0
+ adcl $0xffff, %0
+ "
+ : "=r" (sum)
+ : "r" (sum << 16), "0" (sum & 0xffff0000)
+ );
+ return (~sum) >> 16;
+}
+
/*
* computes the checksum of the TCP/UDP pseudo-header
* returns a 16-bit checksum, already complemented
@@ -85,55 +101,21 @@
unsigned int sum) {
__asm__("
addl %1, %0
- adcl %4, %0
- adcl %5, %0
- adcl $0, %0
- movl %0, %1
- shrl $16, %1
- addw %w1, %w0
+ adcl %2, %0
+ adcl %3, %0
adcl $0, %0
- notl %0
"
- : "=&r" (sum), "=&r" (saddr)
- : "0" (daddr), "1"(saddr), "r"((ntohs(len)<<16)+proto*256), "r"(sum));
- return((unsigned short)sum);
-}
-
-/*
- * Fold a partial checksum without adding pseudo headers
- */
-
-static inline unsigned int csum_fold(unsigned int sum)
-{
- __asm__("
- addl %1, %0
- adcl $0xffff, %0
- "
- : "=r" (sum)
- : "r" (sum << 16), "0" (sum & 0xffff0000)
- );
- return (~sum) >> 16;
+ : "=r" (sum)
+ : "g" (daddr), "g"(saddr), "g"((ntohs(len)<<16)+proto*256), "0"(sum));
+ return csum_fold(sum);
}
-
/*
* this routine is used for miscellaneous IP-like checksums, mainly
* in icmp.c
*/
static inline unsigned short ip_compute_csum(unsigned char * buff, int len) {
- unsigned int sum;
-
- unsigned int scratch;
- __asm__("
- movl %0, %1
- shrl $16, %1
- addw %w1, %w0
- adcl $0, %0
- notl %0
- "
- : "=a"(sum), "=r" (scratch)
- : "0" (csum_partial(buff, len, 0)));
- return(sum);
+ return csum_fold (csum_partial(buff, len, 0));
}
#endif
Tom.