Messages in this thread Patch in this message | | | Date | Wed, 1 May 1996 19:27:51 -0700 | From | (Tom May) | Subject | Patch to make include/asm-i386/checksum.h nicer for gcc & people |
| |
A while back I asked on linux-gcc about a patch to system.h that added what looks like a gratuitous "&" to some __asm__ output operand constraints. I never got an authoritative answer about why that patch was made. It turns out that using "&" where it isn't really needed can result in some suboptimal code generation. So I went back and deleted some similar cruft in include/asm-i386/checksum.h (which I put there in the first place).
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.
| |