diff options
author | Ralf Baechle <ralf@linux-mips.org> | 1997-03-25 23:40:36 +0000 |
---|---|---|
committer | <ralf@linux-mips.org> | 1997-03-25 23:40:36 +0000 |
commit | 7206675c40394c78a90e74812bbdbf8cf3cca1be (patch) | |
tree | 251895cf5a0008e2b4ce438cb01ad4d55fb5b97b /arch/mips/lib/checksum.c | |
parent | beb116954b9b7f3bb56412b2494b562f02b864b1 (diff) |
Import of Linux/MIPS 2.1.14.2
Diffstat (limited to 'arch/mips/lib/checksum.c')
-rw-r--r-- | arch/mips/lib/checksum.c | 180 |
1 files changed, 65 insertions, 115 deletions
diff --git a/arch/mips/lib/checksum.c b/arch/mips/lib/checksum.c index 0e04ac5e8..dd1583892 100644 --- a/arch/mips/lib/checksum.c +++ b/arch/mips/lib/checksum.c @@ -17,124 +17,76 @@ #include <net/checksum.h> #include <asm/string.h> +static inline unsigned short from32to16(unsigned long x) +{ + /* 32 bits --> 16 bits + carry */ + x = (x & 0xffff) + (x >> 16); + /* 16 bits + carry --> 16 bits including carry */ + x = (x & 0xffff) + (x >> 16); + return x; +} + +static inline unsigned long do_csum(const unsigned char * buff, int len) +{ + int odd, count; + unsigned long result = 0; + + if (len <= 0) + goto out; + odd = 1 & (unsigned long) buff; + if (odd) { + result = *buff; + len--; + buff++; + } + count = len >> 1; /* nr of 16-bit words.. */ + if (count) { + if (2 & (unsigned long) buff) { + result += *(unsigned short *) buff; + count--; + len -= 2; + buff += 2; + } + count >>= 1; /* nr of 32-bit words.. */ + if (count) { + unsigned long carry = 0; + do { + unsigned long w = *(unsigned long *) buff; + count--; + buff += 4; + result += carry; + result += w; + carry = (w > result); + } while (count); + result += carry; + result = (result & 0xffff) + (result >> 16); + } + if (len & 2) { + result += *(unsigned short *) buff; + buff += 2; + } + } + if (len & 1) + result += (*buff << 8); + result = from32to16(result); + if (odd) + result = ((result >> 8) & 0xff) | ((result & 0xff) << 8); +out: + return result; +} + /* * computes a partial checksum, e.g. for TCP/UDP fragments */ unsigned int csum_partial(const unsigned char *buff, int len, unsigned int sum) { - unsigned long scratch1; - unsigned long scratch2; - - /* - * This is for 32-bit MIPS processors. - */ - __asm__(" - .set noreorder - .set noat - andi $1,%4,2 # Check alignment - beqz $1,2f # Branch if ok - nop # delay slot - subu $1,%3,2 # Alignment uses up two bytes - bgez $1,1f # Jump if we had at least two bytes - move %3,$1 # delay slot - j 4f - addiu %3,2 # delay slot; len was < 2. Deal with it - -1: lhu %2,(%4) - addiu %4,2 - addu %0,%2 - sltu $1,%0,%2 - addu %0,$1 - -2: srl %1,%3,5 - beqz %1,2f - sll %1,%1,5 # delay slot - - addu %1,%4 -1: lw %2,0(%4) - addu %4,32 - addu %0,%2 - sltu $1,%0,%2 + unsigned long result = do_csum(buff, len); - lw %2,-28(%4) - addu %0,$1 - addu %0,%2 - sltu $1,%0,%2 - - lw %2,-24(%4) - addu %0,$1 - addu %0,%2 - sltu $1,%0,%2 - - lw %2,-20(%4) - addu %0,$1 - addu %0,%2 - sltu $1,%0,%2 - - lw %2,-16(%4) - addu %0,$1 - addu %0,%2 - sltu $1,%0,%2 - - lw %2,-12(%4) - addu %0,$1 - addu %0,%2 - sltu $1,%0,%2 - - lw %2,-8(%4) - addu %0,$1 - addu %0,%2 - sltu $1,%0,%2 - - lw %2,-4(%4) - addu %0,$1 - addu %0,%2 - sltu $1,%0,%2 - - bne %4,%1,1b - addu %0,$1 # delay slot - -2: andi %1,%3,0x1c - beqz %1,4f - addu %1,%4 # delay slot -3: lw %2,0(%4) - addu %4,4 - addu %0,%2 - sltu $1,%0,%2 - bne %4,%1,3b - addu %0,$1 # delay slot - -4: andi $1,%3,3 - beqz $1,7f - andi $1,%3,2 # delay slot - beqz $1,5f - move %2,$0 # delay slot - lhu %2,(%4) - addiu %4,2 # delay slot - -5: andi $1,%3,1 - beqz $1,6f - nop # delay slot - lbu %1,(%4) - sll %2,16\n\t" -#ifdef __MIPSEB__ - "sll %1,8\n\t" -#endif - "or %2,%1 -6: addu %0,%2 - sltu $1,%0,%2 - addu %0,$1 -7: .set at - .set reorder" - : "=r"(sum), - "=&r" (scratch1), - "=&r" (scratch2), - "=r" (len), - "=r" (buff) - : "0"(sum), "3"(len), "4"(buff) - : "$1"); - - return sum; + /* add in old sum, and carry.. */ + result += sum; + if(sum > result) + result += 1; + return result; } /* @@ -144,12 +96,10 @@ unsigned int csum_partial_copy(const char *src, char *dst, int len, unsigned int sum) { /* - * It's 2:30 am and I don't feel like doing it right ... + * It's 2:30 am and I don't feel like doing it real ... * This is lots slower than the real thing (tm) * * XXX This may nuke the kernel for unaligned src addresses!!! - * (Due to software address error fixing no longer true, but - * seems to happen very rarely only anyway.) */ sum = csum_partial(src, len, sum); memcpy(dst, src, len); |