root/arch/i386/lib/checksum.c

/* [previous][next][first][last][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. csum_partial
  2. csum_partial_copy_fromuser
  3. csum_partial_copy

   1 /*
   2  * INET         An implementation of the TCP/IP protocol suite for the LINUX
   3  *              operating system.  INET is implemented using the  BSD Socket
   4  *              interface as the means of communication with the user level.
   5  *
   6  *              IP/TCP/UDP checksumming routines
   7  *
   8  * Authors:     Jorge Cwik, <jorge@laser.satlink.net>
   9  *              Arnt Gulbrandsen, <agulbra@nvg.unit.no>
  10  *              Tom May, <ftom@netcom.com>
  11  *              Lots of code moved from tcp.c and ip.c; see those files
  12  *              for more names.
  13  *
  14  *              This program is free software; you can redistribute it and/or
  15  *              modify it under the terms of the GNU General Public License
  16  *              as published by the Free Software Foundation; either version
  17  *              2 of the License, or (at your option) any later version.
  18  */
  19 
  20 #include <net/checksum.h>
  21 
  22 /*
  23  * computes a partial checksum, e.g. for TCP/UDP fragments
  24  */
  25 
  26 unsigned int csum_partial(const unsigned char * buff, int len, unsigned int sum) {
     /* [previous][next][first][last][top][bottom][index][help] */
  27           /*
  28            * Experiments with ethernet and slip connections show that buff
  29            * is aligned on either a 2-byte or 4-byte boundary.  We get at
  30            * least a 2x speedup on 486 and Pentium if it is 4-byte aligned.
  31            * Fortunately, it is easy to convert 2-byte alignment to 4-byte
  32            * alignment for the unrolled loop.
  33            */
  34         __asm__("
  35             testl $2, %%esi             # Check alignment.
  36             jz 2f                       # Jump if alignment is ok.
  37             subl $2, %%ecx              # Alignment uses up two bytes.
  38             jae 1f                      # Jump if we had at least two bytes.
  39             addl $2, %%ecx              # ecx was < 2.  Deal with it.
  40             jmp 4f
  41 1:          movw (%%esi), %%bx
  42             addl $2, %%esi
  43             addw %%bx, %%ax
  44             adcl $0, %%eax
  45 2:
  46             movl %%ecx, %%edx
  47             shrl $5, %%ecx
  48             jz 2f
  49             testl %%esi, %%esi
  50 1:          movl (%%esi), %%ebx
  51             adcl %%ebx, %%eax
  52             movl 4(%%esi), %%ebx
  53             adcl %%ebx, %%eax
  54             movl 8(%%esi), %%ebx
  55             adcl %%ebx, %%eax
  56             movl 12(%%esi), %%ebx
  57             adcl %%ebx, %%eax
  58             movl 16(%%esi), %%ebx
  59             adcl %%ebx, %%eax
  60             movl 20(%%esi), %%ebx
  61             adcl %%ebx, %%eax
  62             movl 24(%%esi), %%ebx
  63             adcl %%ebx, %%eax
  64             movl 28(%%esi), %%ebx
  65             adcl %%ebx, %%eax
  66             lea 32(%%esi), %%esi
  67             dec %%ecx
  68             jne 1b
  69             adcl $0, %%eax
  70 2:          movl %%edx, %%ecx
  71             andl $0x1c, %%edx
  72             je 4f
  73             shrl $2, %%edx
  74             testl %%esi, %%esi
  75 3:          adcl (%%esi), %%eax
  76             lea 4(%%esi), %%esi
  77             dec %%edx
  78             jne 3b
  79             adcl $0, %%eax
  80 4:          andl $3, %%ecx
  81             jz 7f
  82             cmpl $2, %%ecx
  83             jb 5f
  84             movw (%%esi),%%cx
  85             leal 2(%%esi),%%esi
  86             je 6f
  87             shll $16,%%ecx
  88 5:          movb (%%esi),%%cl
  89 6:          addl %%ecx,%%eax
  90             adcl $0, %%eax
  91 7:          "
  92         : "=a"(sum)
  93         : "0"(sum), "c"(len), "S"(buff)
  94         : "bx", "cx", "dx", "si");
  95         return(sum);
  96 }
  97 
  98 
  99 
 100 /*
 101  * copy from fs while checksumming, otherwise like csum_partial
 102  */
 103 
 104 unsigned int csum_partial_copy_fromuser(const char *src, char *dst, 
     /* [previous][next][first][last][top][bottom][index][help] */
 105                                   int len, int sum) {
 106     __asm__("
 107         testl $2, %%edi         # Check alignment.
 108         jz 2f                   # Jump if alignment is ok.
 109         subl $2, %%ecx          # Alignment uses up two bytes.
 110         jae 1f                  # Jump if we had at least two bytes.
 111         addl $2, %%ecx          # ecx was < 2.  Deal with it.
 112         jmp 4f
 113 1:      movw %%fs:(%%esi), %%bx
 114         addl $2, %%esi
 115         movw %%bx, (%%edi)
 116         addl $2, %%edi
 117         addw %%bx, %%ax
 118         adcl $0, %%eax
 119 2:
 120         movl %%ecx, %%edx
 121         shrl $5, %%ecx
 122         jz 2f
 123         testl %%esi, %%esi
 124 1:      movl %%fs:(%%esi), %%ebx
 125         adcl %%ebx, %%eax
 126         movl %%ebx, (%%edi)
 127 
 128         movl %%fs:4(%%esi), %%ebx
 129         adcl %%ebx, %%eax
 130         movl %%ebx, 4(%%edi)
 131 
 132         movl %%fs:8(%%esi), %%ebx
 133         adcl %%ebx, %%eax
 134         movl %%ebx, 8(%%edi)
 135 
 136         movl %%fs:12(%%esi), %%ebx
 137         adcl %%ebx, %%eax
 138         movl %%ebx, 12(%%edi)
 139 
 140         movl %%fs:16(%%esi), %%ebx
 141         adcl %%ebx, %%eax
 142         movl %%ebx, 16(%%edi)
 143 
 144         movl %%fs:20(%%esi), %%ebx
 145         adcl %%ebx, %%eax
 146         movl %%ebx, 20(%%edi)
 147 
 148         movl %%fs:24(%%esi), %%ebx
 149         adcl %%ebx, %%eax
 150         movl %%ebx, 24(%%edi)
 151 
 152         movl %%fs:28(%%esi), %%ebx
 153         adcl %%ebx, %%eax
 154         movl %%ebx, 28(%%edi)
 155 
 156         lea 32(%%esi), %%esi
 157         lea 32(%%edi), %%edi
 158         dec %%ecx
 159         jne 1b
 160         adcl $0, %%eax
 161 2:      movl %%edx, %%ecx
 162         andl $28, %%edx
 163         je 4f
 164         shrl $2, %%edx
 165         testl %%esi, %%esi
 166 3:      movl %%fs:(%%esi), %%ebx
 167         adcl %%ebx, %%eax
 168         movl %%ebx, (%%edi)
 169         lea 4(%%esi), %%esi
 170         lea 4(%%edi), %%edi
 171         dec %%edx
 172         jne 3b
 173         adcl $0, %%eax
 174 4:      andl $3, %%ecx
 175         jz 7f
 176         cmpl $2, %%ecx
 177         jb 5f
 178         movw %%fs:(%%esi), %%cx
 179         leal 2(%%esi), %%esi
 180         movw %%cx, (%%edi)
 181         leal 2(%%edi), %%edi
 182         je 6f
 183         shll $16,%%ecx
 184 5:      movb %%fs:(%%esi), %%cl
 185         movb %%cl, (%%edi)
 186 6:      addl %%ecx, %%eax
 187         adcl $0, %%eax
 188 7:
 189         "
 190         : "=a" (sum)
 191         : "0"(sum), "c"(len), "S"(src), "D" (dst)
 192         : "bx", "cx", "dx", "si", "di" );
 193     return(sum);
 194 }
 195 /*
 196  * copy from ds while checksumming, otherwise like csum_partial
 197  */
 198 
 199 unsigned int csum_partial_copy(const char *src, char *dst, 
     /* [previous][next][first][last][top][bottom][index][help] */
 200                                   int len, int sum) {
 201     __asm__("
 202         testl $2, %%edi         # Check alignment.
 203         jz 2f                   # Jump if alignment is ok.
 204         subl $2, %%ecx          # Alignment uses up two bytes.
 205         jae 1f                  # Jump if we had at least two bytes.
 206         addl $2, %%ecx          # ecx was < 2.  Deal with it.
 207         jmp 4f
 208 1:      movw (%%esi), %%bx
 209         addl $2, %%esi
 210         movw %%bx, (%%edi)
 211         addl $2, %%edi
 212         addw %%bx, %%ax
 213         adcl $0, %%eax
 214 2:
 215         movl %%ecx, %%edx
 216         shrl $5, %%ecx
 217         jz 2f
 218         testl %%esi, %%esi
 219 1:      movl (%%esi), %%ebx
 220         adcl %%ebx, %%eax
 221         movl %%ebx, (%%edi)
 222 
 223         movl 4(%%esi), %%ebx
 224         adcl %%ebx, %%eax
 225         movl %%ebx, 4(%%edi)
 226 
 227         movl 8(%%esi), %%ebx
 228         adcl %%ebx, %%eax
 229         movl %%ebx, 8(%%edi)
 230 
 231         movl 12(%%esi), %%ebx
 232         adcl %%ebx, %%eax
 233         movl %%ebx, 12(%%edi)
 234 
 235         movl 16(%%esi), %%ebx
 236         adcl %%ebx, %%eax
 237         movl %%ebx, 16(%%edi)
 238 
 239         movl 20(%%esi), %%ebx
 240         adcl %%ebx, %%eax
 241         movl %%ebx, 20(%%edi)
 242 
 243         movl 24(%%esi), %%ebx
 244         adcl %%ebx, %%eax
 245         movl %%ebx, 24(%%edi)
 246 
 247         movl 28(%%esi), %%ebx
 248         adcl %%ebx, %%eax
 249         movl %%ebx, 28(%%edi)
 250 
 251         lea 32(%%esi), %%esi
 252         lea 32(%%edi), %%edi
 253         dec %%ecx
 254         jne 1b
 255         adcl $0, %%eax
 256 2:      movl %%edx, %%ecx
 257         andl $28, %%edx
 258         je 4f
 259         shrl $2, %%edx
 260         testl %%esi, %%esi
 261 3:      movl (%%esi), %%ebx
 262         adcl %%ebx, %%eax
 263         movl %%ebx, (%%edi)
 264         lea 4(%%esi), %%esi
 265         lea 4(%%edi), %%edi
 266         dec %%edx
 267         jne 3b
 268         adcl $0, %%eax
 269 4:      andl $3, %%ecx
 270         jz 7f
 271         cmpl $2, %%ecx
 272         jb 5f
 273         movw (%%esi), %%cx
 274         leal 2(%%esi), %%esi
 275         movw %%cx, (%%edi)
 276         leal 2(%%edi), %%edi
 277         je 6f
 278         shll $16,%%ecx
 279 5:      movb (%%esi), %%cl
 280         movb %%cl, (%%edi)
 281 6:      addl %%ecx, %%eax
 282         adcl $0, %%eax
 283 7:
 284         "
 285         : "=a" (sum)
 286         : "0"(sum), "c"(len), "S"(src), "D" (dst)
 287         : "bx", "cx", "dx", "si", "di" );
 288     return(sum);
 289 }

/* [previous][next][first][last][top][bottom][index][help] */