1 /* $NetBSD: in_cksum.c,v 1.1 2002/06/05 01:04:20 fredette Exp $ */ 2 3 /* $OpenBSD: in_cksum.c,v 1.1 2001/01/13 00:00:20 mickey Exp $ */ 4 5 /* 6 * Copyright (c) 2000 Michael Shalayeff 7 * All rights reserved. 8 * 9 * based on a sparc version of Zubin Dittia. 10 * Copyright (c) 1995 Zubin Dittia. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted provided that the following conditions 14 * are met: 15 * 1. Redistributions of source code must retain the above copyright 16 * notice, this list of conditions and the following disclaimer. 17 * 2. Redistributions in binary form must reproduce the above copyright 18 * notice, this list of conditions and the following disclaimer in the 19 * documentation and/or other materials provided with the distribution. 20 * 3. All advertising materials mentioning features or use of this software 21 * must display the following acknowledgement: 22 * This product includes software developed by Michael Shalayeff. 23 * 4. The name of the author may not be used to endorse or promote products 24 * derived from this software without specific prior written permission. 25 * 26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 27 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 28 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 29 * IN NO EVENT SHALL THE AUTHOR OR HIS RELATIVES BE LIABLE FOR ANY DIRECT, 30 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 31 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR 32 * SERVICES; LOSS OF MIND, USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 34 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 35 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 36 * THE POSSIBILITY OF SUCH DAMAGE. 37 */ 38 39 #include <sys/param.h> 40 #include <sys/systm.h> 41 #include <sys/mbuf.h> 42 #include <netinet/in.h> 43 44 /* 45 * Checksum routine for Internet Protocol family headers. 46 * 47 * This routine is very heavily used in the network 48 * code and should be modified for each CPU to be as fast as possible. 49 * 50 * HPPA version. 51 */ 52 53 #define ADD32 asm volatile( "ldw 0x00(%1), %%r19! ldw 0x04(%1), %%r20\n\t" \ 54 "add %0, %%r19, %0 ! addc %0, %%r20, %0\n\t" \ 55 "ldw 0x08(%1), %%r19! ldw 0x0c(%1), %%r20\n\t" \ 56 "addc %0, %%r19, %0 ! addc %0, %%r20, %0\n\t" \ 57 "ldw 0x10(%1), %%r19! ldw 0x14(%1), %%r20\n\t" \ 58 "addc %0, %%r19, %0 ! addc %0, %%r20, %0\n\t" \ 59 "ldw 0x18(%1), %%r19! ldw 0x1c(%1), %%r20\n\t" \ 60 "addc %0, %%r19, %0 ! addc %0, %%r20, %0\n\t" \ 61 "ldo 0x20(%1), %1 ! addc %0, %%r0 , %0" \ 62 : "+r" (sum), "+r" (w) :: "r20", "r19") 63 #define ADD16 asm volatile( "ldw 0x00(%1), %%r19! ldw 0x04(%1), %%r20\n\t" \ 64 "add %0, %%r19, %0! addc %0, %%r20, %0\n\t" \ 65 "ldw 0x08(%1), %%r19! ldw 0x0c(%1), %%r20\n\t" \ 66 "addc %0, %%r19, %0! addc %0, %%r20, %0\n\t" \ 67 "ldo 0x10(%1), %1 ! addc %0, %%r0 , %0" \ 68 : "+r" (sum), "+r" (w) :: "r20", "r19") 69 70 #define ADDCARRY {if (sum > 0xffff) sum -= 0xffff;} 71 #define REDUCE {sum = (sum & 0xffff) + (sum >> 16); ADDCARRY} 72 #define ROL asm volatile ("shd %0, %0, 8, %0" : "+r" (sum)) 73 #define ADDBYTE {ROL; sum += *w++; bins++; mlen--;} 74 #define ADDSHORT {sum += *((u_short *)w)++; mlen -= 2;} 75 #define ADDWORD asm volatile( "ldwm 4(%1), %%r19! add %0, %%r19, %0\n\t" \ 76 "ldo -4(%2), %2 ! addc %0, 0, %0" \ 77 : "+r" (sum), "+r" (w), "+r" (mlen) :: "r19") 78 79 int 80 in_cksum(m, len) 81 register struct mbuf *m; 82 register int len; 83 { 84 register u_int sum = 0; 85 register u_int bins = 0; 86 87 for (; m && len; m = m->m_next) { 88 register int mlen = m->m_len; 89 register u_char *w; 90 91 if (!mlen) 92 continue; 93 if (len < mlen) 94 mlen = len; 95 len -= mlen; 96 w = mtod(m, u_char *); 97 98 if (mlen > 16) { 99 /* 100 * If we are aligned on a doubleword boundary 101 * do 32 bit bundled operations 102 */ 103 if ((7 & (u_long)w) != 0) { 104 if ((1 & (u_long)w) != 0) 105 ADDBYTE; 106 if ((2 & (u_long)w) != 0) 107 ADDSHORT; 108 if ((4 & (u_long)w) != 0) 109 ADDWORD; 110 } 111 112 while ((mlen -= 32) >= 0) 113 ADD32; 114 115 mlen += 32; 116 if (mlen >= 16) { 117 ADD16; 118 mlen -= 16; 119 } 120 } 121 122 while (mlen > 0) 123 ADDBYTE; 124 } 125 if (bins & 1) 126 ROL; 127 REDUCE; 128 129 return (0xffff ^ sum); 130 } 131