URL
https://opencores.org/ocsvn/or1k/or1k/trunk
Subversion Repositories or1k
[/] [or1k/] [trunk/] [uclinux/] [uClinux-2.0.x/] [arch/] [i386/] [lib/] [checksum.c] - Rev 1767
Go to most recent revision | Compare with Previous | Blame | View Log
/* * INET An implementation of the TCP/IP protocol suite for the LINUX * operating system. INET is implemented using the BSD Socket * interface as the means of communication with the user level. * * IP/TCP/UDP checksumming routines * * Authors: Jorge Cwik, <jorge@laser.satlink.net> * Arnt Gulbrandsen, <agulbra@nvg.unit.no> * Tom May, <ftom@netcom.com> * Lots of code moved from tcp.c and ip.c; see those files * for more names. * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License * as published by the Free Software Foundation; either version * 2 of the License, or (at your option) any later version. */ #include <net/checksum.h> /* * computes a partial checksum, e.g. for TCP/UDP fragments */ unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) { /* * Experiments with ethernet and slip connections show that buff * is aligned on either a 2-byte or 4-byte boundary. We get at * least a 2x speedup on 486 and Pentium if it is 4-byte aligned. * Fortunately, it is easy to convert 2-byte alignment to 4-byte * alignment for the unrolled loop. */ __asm__(" testl $2, %%esi # Check alignment. jz 2f # Jump if alignment is ok. subl $2, %%ecx # Alignment uses up two bytes. jae 1f # Jump if we had at least two bytes. addl $2, %%ecx # ecx was < 2. Deal with it. jmp 4f 1: movw (%%esi), %%bx addl $2, %%esi addw %%bx, %%ax adcl $0, %%eax 2: movl %%ecx, %%edx shrl $5, %%ecx jz 2f testl %%esi, %%esi 1: movl (%%esi), %%ebx adcl %%ebx, %%eax movl 4(%%esi), %%ebx adcl %%ebx, %%eax movl 8(%%esi), %%ebx adcl %%ebx, %%eax movl 12(%%esi), %%ebx adcl %%ebx, %%eax movl 16(%%esi), %%ebx adcl %%ebx, %%eax movl 20(%%esi), %%ebx adcl %%ebx, %%eax movl 24(%%esi), %%ebx adcl %%ebx, %%eax movl 28(%%esi), %%ebx adcl %%ebx, %%eax lea 32(%%esi), %%esi dec %%ecx jne 1b adcl $0, %%eax 2: movl %%edx, %%ecx andl $0x1c, %%edx je 4f shrl $2, %%edx testl %%esi, %%esi 3: adcl (%%esi), %%eax lea 4(%%esi), %%esi dec %%edx jne 3b adcl $0, %%eax 4: andl $3, %%ecx jz 7f cmpl $2, %%ecx jb 5f movw (%%esi),%%cx leal 2(%%esi),%%esi je 6f shll $16,%%ecx 5: movb (%%esi),%%cl 6: addl %%ecx,%%eax adcl $0, %%eax 7: " : "=a"(sum) : "0"(sum), "c"(len), "S"(buff) : "bx", "cx", "dx", "si"); return(sum); } /* * copy from fs while checksumming, otherwise like csum_partial */ unsigned int csum_partial_copy_fromuser(const char *src, char *dst, int len, int sum) { __asm__(" testl $2, %%edi # Check alignment. jz 2f # Jump if alignment is ok. subl $2, %%ecx # Alignment uses up two bytes. jae 1f # Jump if we had at least two bytes. addl $2, %%ecx # ecx was < 2. Deal with it. jmp 4f 1: movw %%fs:(%%esi), %%bx addl $2, %%esi movw %%bx, (%%edi) addl $2, %%edi addw %%bx, %%ax adcl $0, %%eax 2: movl %%ecx, %%edx shrl $5, %%ecx jz 2f testl %%esi, %%esi 1: movl %%fs:(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, (%%edi) movl %%fs:4(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, 4(%%edi) movl %%fs:8(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, 8(%%edi) movl %%fs:12(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, 12(%%edi) movl %%fs:16(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, 16(%%edi) movl %%fs:20(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, 20(%%edi) movl %%fs:24(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, 24(%%edi) movl %%fs:28(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, 28(%%edi) lea 32(%%esi), %%esi lea 32(%%edi), %%edi dec %%ecx jne 1b adcl $0, %%eax 2: movl %%edx, %%ecx andl $28, %%edx je 4f shrl $2, %%edx testl %%esi, %%esi 3: movl %%fs:(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, (%%edi) lea 4(%%esi), %%esi lea 4(%%edi), %%edi dec %%edx jne 3b adcl $0, %%eax 4: andl $3, %%ecx jz 7f cmpl $2, %%ecx jb 5f movw %%fs:(%%esi), %%cx leal 2(%%esi), %%esi movw %%cx, (%%edi) leal 2(%%edi), %%edi je 6f shll $16,%%ecx 5: movb %%fs:(%%esi), %%cl movb %%cl, (%%edi) 6: addl %%ecx, %%eax adcl $0, %%eax 7: " : "=a" (sum) : "0"(sum), "c"(len), "S"(src), "D" (dst) : "bx", "cx", "dx", "si", "di" ); return(sum); } /* * copy from ds while checksumming, otherwise like csum_partial */ unsigned int csum_partial_copy(const char *src, char *dst, int len, int sum) { __asm__(" testl $2, %%edi # Check alignment. jz 2f # Jump if alignment is ok. subl $2, %%ecx # Alignment uses up two bytes. jae 1f # Jump if we had at least two bytes. addl $2, %%ecx # ecx was < 2. Deal with it. jmp 4f 1: movw (%%esi), %%bx addl $2, %%esi movw %%bx, (%%edi) addl $2, %%edi addw %%bx, %%ax adcl $0, %%eax 2: movl %%ecx, %%edx shrl $5, %%ecx jz 2f testl %%esi, %%esi 1: movl (%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, (%%edi) movl 4(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, 4(%%edi) movl 8(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, 8(%%edi) movl 12(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, 12(%%edi) movl 16(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, 16(%%edi) movl 20(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, 20(%%edi) movl 24(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, 24(%%edi) movl 28(%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, 28(%%edi) lea 32(%%esi), %%esi lea 32(%%edi), %%edi dec %%ecx jne 1b adcl $0, %%eax 2: movl %%edx, %%ecx andl $28, %%edx je 4f shrl $2, %%edx testl %%esi, %%esi 3: movl (%%esi), %%ebx adcl %%ebx, %%eax movl %%ebx, (%%edi) lea 4(%%esi), %%esi lea 4(%%edi), %%edi dec %%edx jne 3b adcl $0, %%eax 4: andl $3, %%ecx jz 7f cmpl $2, %%ecx jb 5f movw (%%esi), %%cx leal 2(%%esi), %%esi movw %%cx, (%%edi) leal 2(%%edi), %%edi je 6f shll $16,%%ecx 5: movb (%%esi), %%cl movb %%cl, (%%edi) 6: addl %%ecx, %%eax adcl $0, %%eax 7: " : "=a" (sum) : "0"(sum), "c"(len), "S"(src), "D" (dst) : "bx", "cx", "dx", "si", "di" ); return(sum); }
Go to most recent revision | Compare with Previous | Blame | View Log