BSD 4_1c_2 development
authorCSRG <csrg@ucbvax.Berkeley.EDU>
Thu, 20 Jan 1983 09:48:46 +0000 (01:48 -0800)
committerCSRG <csrg@ucbvax.Berkeley.EDU>
Thu, 20 Jan 1983 09:48:46 +0000 (01:48 -0800)
Work on file a/sys/vax/in_cksum.c

Synthesized-from: CSRG/cd1/4.1c.2

a/sys/vax/in_cksum.c [new file with mode: 0644]

diff --git a/a/sys/vax/in_cksum.c b/a/sys/vax/in_cksum.c
new file mode 100644 (file)
index 0000000..2b53add
--- /dev/null
@@ -0,0 +1,127 @@
+/*     in_cksum.c      1.17    83/01/17        */
+
+#include "../h/types.h"
+#include "../h/mbuf.h"
+#include "../netinet/in.h"
+#include "../netinet/in_systm.h"
+
+/*
+ * Checksum routine for Internet Protocol family headers (VAX Version).
+ *
+ * This routine is very heavily used in the network
+ * code and should be modified for each CPU to be as fast as possible.
+ */
+
+in_cksum(m, len)
+       register struct mbuf *m;
+       register int len;
+{
+       register u_short *w;            /* on vax, known to be r9 */
+       register int sum = 0;           /* on vax, known to be r8 */
+       register int mlen = 0;
+
+       for (;;) {
+               /*
+                * Each trip around loop adds in
+                * word from one mbuf segment.
+                */
+               w = mtod(m, u_short *);
+               if (mlen == -1) {
+                       /*
+                        * There is a byte left from the last segment;
+                        * add it into the checksum.  Don't have to worry
+                        * about a carry-out here because we make sure
+                        * that high part of (32 bit) sum is small below.
+                        */
+                       sum += *(u_char *)w << 8;
+                       w = (u_short *)((char *)w + 1);
+                       mlen = m->m_len - 1;
+                       len--;
+               } else
+                       mlen = m->m_len;
+               m = m->m_next;
+               if (len < mlen)
+                       mlen = len;
+               len -= mlen;
+               /*
+                * Force to long boundary so we do longword aligned
+                * memory operations.  It is too hard to do byte
+                * adjustment, do only word adjustment.
+                */
+               if (((int)w&0x2) && mlen >= 2) {
+                       sum += *w++;
+                       mlen -= 2;
+               }
+               /*
+                * Do as much of the checksum as possible 32 bits at at time.
+                * In fact, this loop is unrolled to make overhead from
+                * branches &c small.
+                *
+                * We can do a 16 bit ones complement sum 32 bits at a time
+                * because the 32 bit register is acting as two 16 bit
+                * registers for adding, with carries from the low added
+                * into the high (by normal carry-chaining) and carries
+                * from the high carried into the low on the next word
+                * by use of the adwc instruction.  This lets us run
+                * this loop at almost memory speed.
+                *
+                * Here there is the danger of high order carry out, and
+                * we carefully use adwc.
+                */
+               while ((mlen -= 32) >= 0) {
+#undef ADD
+                       asm("clrl r0");         /* clears carry */
+#define ADD            asm("adwc (r9)+,r8;");
+                       ADD; ADD; ADD; ADD; ADD; ADD; ADD; ADD;
+                       asm("adwc $0,r8");
+               }
+               mlen += 32;
+               while ((mlen -= 8) >= 0) {
+                       asm("clrl r0");
+                       ADD; ADD;
+                       asm("adwc $0,r8");
+               }
+               mlen += 8;
+               /*
+                * Now eliminate the possibility of carry-out's by
+                * folding back to a 16 bit number (adding high and
+                * low parts together.)  Then mop up trailing words
+                * and maybe an odd byte.
+                */
+               { asm("ashl $-16,r8,r0; addw2 r0,r8");
+                 asm("adwc $0,r8; movzwl r8,r8"); }
+               while ((mlen -= 2) >= 0) {
+                       asm("movzwl (r9)+,r0; addl2 r0,r8");
+               }
+               if (mlen == -1) {
+                       sum += *(u_char *)w;
+               }
+               if (len == 0)
+                       break;
+               /*
+                * Locate the next block with some data.
+                * If there is a word split across a boundary we
+                * will wrap to the top with mlen == -1 and
+                * then add it in shifted appropriately.
+                */
+               for (;;) {
+                       if (m == 0) {
+                               printf("cksum: out of data\n");
+                               goto done;
+                       }
+                       if (m->m_len)
+                               break;
+                       m = m->m_next;
+               }
+       }
+done:
+       /*
+        * Add together high and low parts of sum
+        * and carry to get cksum.
+        * Have to be careful to not drop the last
+        * carry here.
+        */
+       { asm("ashl $-16,r8,r0; addw2 r0,r8; adwc $0,r8");
+         asm("mcoml r8,r8; movzwl r8,r8"); }
+       return (sum);
+}