diff options
Diffstat (limited to 'pfinet/linux-inet')
-rw-r--r-- | pfinet/linux-inet/tcp.c | 169 | ||||
-rw-r--r-- | pfinet/linux-inet/udp.c | 142 |
2 files changed, 156 insertions, 155 deletions
diff --git a/pfinet/linux-inet/tcp.c b/pfinet/linux-inet/tcp.c index e4b4005b..3005fbfd 100644 --- a/pfinet/linux-inet/tcp.c +++ b/pfinet/linux-inet/tcp.c @@ -1016,90 +1016,6 @@ int tcp_ioctl(struct sock *sk, int cmd, unsigned long arg) } #endif -/* - * This routine computes a TCP checksum. - */ - -unsigned short tcp_check(struct tcphdr *th, int len, - unsigned long saddr, unsigned long daddr) -{ - unsigned long sum; - - if (saddr == 0) saddr = ip_my_addr(); - -/* - * stupid, gcc complains when I use just one __asm__ block, - * something about too many reloads, but this is just two - * instructions longer than what I want - */ - __asm__(" - addl %%ecx, %%ebx - adcl %%edx, %%ebx - adcl $0, %%ebx - " - : "=b"(sum) - : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_TCP*256) - : "bx", "cx", "dx" ); - __asm__(" - movl %%ecx, %%edx - cld - cmpl $32, %%ecx - jb 2f - shrl $5, %%ecx - clc -1: lodsl - adcl %%eax, %%ebx - lodsl - adcl %%eax, %%ebx - lodsl - adcl %%eax, %%ebx - lodsl - adcl %%eax, %%ebx - lodsl - adcl %%eax, %%ebx - lodsl - adcl %%eax, %%ebx - lodsl - adcl %%eax, %%ebx - lodsl - adcl %%eax, %%ebx - loop 1b - adcl $0, %%ebx - movl %%edx, %%ecx -2: andl $28, %%ecx - je 4f - shrl $2, %%ecx - clc -3: lodsl - adcl %%eax, %%ebx - loop 3b - adcl $0, %%ebx -4: movl $0, %%eax - testw $2, %%dx - je 5f - lodsw - addl %%eax, %%ebx - adcl $0, %%ebx - movw $0, %%ax -5: test $1, %%edx - je 6f - lodsb - addl %%eax, %%ebx - adcl $0, %%ebx -6: movl %%ebx, %%eax - shrl $16, %%eax - addw %%ax, %%bx - adcw $0, %%bx - " - : "=b"(sum) - : "0"(sum), "c"(len), "S"(th) - : "ax", "bx", "cx", "dx", "si" ); - - /* We only want the bottom 16 bits, but we never cleared the top 16. */ - - return((~sum) & 0xffff); -} - void tcp_send_check(struct tcphdr *th, unsigned long saddr, @@ -5118,3 +5034,88 @@ struct proto tcp_prot = { "TCP", 0, 0 }; + +/* + * This routine computes a TCP checksum. + */ + +unsigned short tcp_check(struct tcphdr *th, int len, + unsigned long saddr, unsigned long daddr) +{ + unsigned long sum; + + if (saddr == 0) saddr = ip_my_addr(); + +/* + * stupid, gcc complains when I use just one __asm__ block, + * something about too many reloads, but this is just two + * instructions longer than what I want + */ + __asm__(" + addl %%ecx, %%ebx + adcl %%edx, %%ebx + adcl $0, %%ebx + " + : "=b"(sum) + : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_TCP*256) + : "bx", "cx", "dx" ); + __asm__(" + movl %%ecx, %%edx + cld + cmpl $32, %%ecx + jb 2f + shrl $5, %%ecx + clc +1: lodsl + adcl %%eax, %%ebx + lodsl + adcl %%eax, %%ebx + lodsl + adcl %%eax, %%ebx + lodsl + adcl %%eax, %%ebx + lodsl + adcl %%eax, %%ebx + lodsl + adcl %%eax, %%ebx + lodsl + adcl %%eax, %%ebx + lodsl + adcl %%eax, %%ebx + loop 1b + adcl $0, %%ebx + movl %%edx, %%ecx +2: andl $28, %%ecx + je 4f + shrl $2, %%ecx + clc +3: lodsl + adcl %%eax, %%ebx + loop 3b + adcl $0, %%ebx +4: movl $0, %%eax + testw $2, %%dx + je 5f + lodsw + addl %%eax, %%ebx + adcl $0, %%ebx + movw $0, %%ax +5: test $1, %%edx + je 6f + lodsb + addl %%eax, %%ebx + adcl $0, %%ebx +6: movl %%ebx, %%eax + shrl $16, %%eax + addw %%ax, %%bx + adcw $0, %%bx + " + : "=b"(sum) + : "0"(sum), "c"(len), "S"(th) + : "ax", "bx", "cx", "dx", "si" ); + + /* We only want the bottom 16 bits, but we never cleared the top 16. */ + + return((~sum) & 0xffff); +} + diff --git a/pfinet/linux-inet/udp.c b/pfinet/linux-inet/udp.c index be4cf928..420f24b3 100644 --- a/pfinet/linux-inet/udp.c +++ b/pfinet/linux-inet/udp.c @@ -152,77 +152,6 @@ void udp_err(int err, unsigned char *header, unsigned long daddr, } -static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr) -{ - unsigned long sum; - - __asm__( "\t addl %%ecx,%%ebx\n" - "\t adcl %%edx,%%ebx\n" - "\t adcl $0, %%ebx\n" - : "=b"(sum) - : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_UDP*256) - : "cx","bx","dx" ); - - if (len > 3) - { - __asm__("\tclc\n" - "1:\n" - "\t lodsl\n" - "\t adcl %%eax, %%ebx\n" - "\t loop 1b\n" - "\t adcl $0, %%ebx\n" - : "=b"(sum) , "=S"(uh) - : "0"(sum), "c"(len/4) ,"1"(uh) - : "ax", "cx", "bx", "si" ); - } - - /* - * Convert from 32 bits to 16 bits. - */ - - __asm__("\t movl %%ebx, %%ecx\n" - "\t shrl $16,%%ecx\n" - "\t addw %%cx, %%bx\n" - "\t adcw $0, %%bx\n" - : "=b"(sum) - : "0"(sum) - : "bx", "cx"); - - /* - * Check for an extra word. - */ - - if ((len & 2) != 0) - { - __asm__("\t lodsw\n" - "\t addw %%ax,%%bx\n" - "\t adcw $0, %%bx\n" - : "=b"(sum), "=S"(uh) - : "0"(sum) ,"1"(uh) - : "si", "ax", "bx"); - } - - /* - * Now check for the extra byte. - */ - - if ((len & 1) != 0) - { - __asm__("\t lodsb\n" - "\t movb $0,%%ah\n" - "\t addw %%ax,%%bx\n" - "\t adcw $0, %%bx\n" - : "=b"(sum) - : "0"(sum) ,"S"(uh) - : "si", "ax", "bx"); - } - - /* - * We only want the bottom 16 bits, but we never cleared the top 16. - */ - - return((~sum) & 0xffff); -} /* * Generate UDP checksums. These may be disabled, eg for fast NFS over ethernet @@ -738,3 +667,74 @@ struct proto udp_prot = { 0, 0 }; +static unsigned short udp_check(struct udphdr *uh, int len, unsigned long saddr, unsigned long daddr) +{ + unsigned long sum; + + __asm__( "\t addl %%ecx,%%ebx\n" + "\t adcl %%edx,%%ebx\n" + "\t adcl $0, %%ebx\n" + : "=b"(sum) + : "0"(daddr), "c"(saddr), "d"((ntohs(len) << 16) + IPPROTO_UDP*256) + : "cx","bx","dx" ); + + if (len > 3) + { + __asm__("\tclc\n" + "1:\n" + "\t lodsl\n" + "\t adcl %%eax, %%ebx\n" + "\t loop 1b\n" + "\t adcl $0, %%ebx\n" + : "=b"(sum) , "=S"(uh) + : "0"(sum), "c"(len/4) ,"1"(uh) + : "ax", "cx", "bx", "si" ); + } + + /* + * Convert from 32 bits to 16 bits. + */ + + __asm__("\t movl %%ebx, %%ecx\n" + "\t shrl $16,%%ecx\n" + "\t addw %%cx, %%bx\n" + "\t adcw $0, %%bx\n" + : "=b"(sum) + : "0"(sum) + : "bx", "cx"); + + /* + * Check for an extra word. + */ + + if ((len & 2) != 0) + { + __asm__("\t lodsw\n" + "\t addw %%ax,%%bx\n" + "\t adcw $0, %%bx\n" + : "=b"(sum), "=S"(uh) + : "0"(sum) ,"1"(uh) + : "si", "ax", "bx"); + } + + /* + * Now check for the extra byte. + */ + + if ((len & 1) != 0) + { + __asm__("\t lodsb\n" + "\t movb $0,%%ah\n" + "\t addw %%ax,%%bx\n" + "\t adcw $0, %%bx\n" + : "=b"(sum) + : "0"(sum) ,"S"(uh) + : "si", "ax", "bx"); + } + + /* + * We only want the bottom 16 bits, but we never cleared the top 16. + */ + + return((~sum) & 0xffff); +} |