1 |
52 |
dgisselq |
////////////////////////////////////////////////////////////////////////////////
|
2 |
|
|
//
|
3 |
|
|
// Filename: ipsum.c
|
4 |
|
|
//
|
5 |
|
|
// Project: OpenArty, an entirely open SoC based upon the Arty platform
|
6 |
|
|
//
|
7 |
|
|
// Purpose: To calculate (and return) an IP checksum on a section of data.
|
8 |
|
|
// The data must be contiguous in memory, and the checksum field
|
9 |
|
|
// (which is usually a part of it) must be blank when calling this
|
10 |
|
|
// function.
|
11 |
|
|
//
|
12 |
|
|
// Creator: Dan Gisselquist, Ph.D.
|
13 |
|
|
// Gisselquist Technology, LLC
|
14 |
|
|
//
|
15 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
16 |
|
|
//
|
17 |
|
|
// Copyright (C) 2015-2016, Gisselquist Technology, LLC
|
18 |
|
|
//
|
19 |
|
|
// This program is free software (firmware): you can redistribute it and/or
|
20 |
|
|
// modify it under the terms of the GNU General Public License as published
|
21 |
|
|
// by the Free Software Foundation, either version 3 of the License, or (at
|
22 |
|
|
// your option) any later version.
|
23 |
|
|
//
|
24 |
|
|
// This program is distributed in the hope that it will be useful, but WITHOUT
|
25 |
|
|
// ANY WARRANTY; without even the implied warranty of MERCHANTIBILITY or
|
26 |
|
|
// FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
|
27 |
|
|
// for more details.
|
28 |
|
|
//
|
29 |
|
|
// You should have received a copy of the GNU General Public License along
|
30 |
|
|
// with this program. (It's in the $(ROOT)/doc directory, run make with no
|
31 |
|
|
// target there if the PDF file isn't present.) If not, see
|
32 |
|
|
// <http://www.gnu.org/licenses/> for a copy.
|
33 |
|
|
//
|
34 |
|
|
// License: GPL, v3, as defined and found on www.gnu.org,
|
35 |
|
|
// http://www.gnu.org/licenses/gpl.html
|
36 |
|
|
//
|
37 |
|
|
//
|
38 |
|
|
////////////////////////////////////////////////////////////////////////////////
|
39 |
|
|
//
|
40 |
|
|
//
|
41 |
|
|
#include "zipcpu.h"
|
42 |
|
|
#include "ipcksum.h"
|
43 |
|
|
|
44 |
|
|
#define ASM
|
45 |
|
|
unsigned ipcksum(int len, unsigned *ptr) {
|
46 |
|
|
#ifndef ASM
|
47 |
|
|
unsigned checksum = 0;
|
48 |
|
|
|
49 |
|
|
for(int i=0; i<len; i++)
|
50 |
|
|
checksum = checksum + (ptr[i] & 0x0ffff) + (ptr[i] >> 16);
|
51 |
|
|
while(checksum & ~0x0ffff)
|
52 |
|
|
checksum = (checksum & 0x0ffff) + (checksum >> 16);
|
53 |
|
|
return checksum ^ 0x0ffff;
|
54 |
|
|
#else
|
55 |
|
|
asm(ASMFNSTR("ipcksum") // R1 = length (W), R2 = packet pointer
|
56 |
|
|
"\tMOV R1,R3\n" // R3 is now the remaining length
|
57 |
|
|
"\tCLR R1\n" // R1 will be our checksum accumulator
|
58 |
|
|
".Lloop:\n"
|
59 |
|
|
"\tLW (R2),R4\n"
|
60 |
|
|
"\tADD R4,R1\n"
|
61 |
|
|
"\tADD.C 1,R1\n"
|
62 |
|
|
"\tADD 4,R2\n"
|
63 |
|
|
"\tSUB 1,R3\n"
|
64 |
|
|
"\tBZ .Lexit\n"
|
65 |
|
|
"\tBRA .Lloop\n"
|
66 |
|
|
".Lexit:\n"
|
67 |
|
|
"\tMOV R1,R3\n"
|
68 |
|
|
"\tAND 0x0ffff,R1\n"
|
69 |
|
|
"\tLSR 16,R3\n"
|
70 |
|
|
"\tADD R3,R1\n"
|
71 |
|
|
"\tTEST 0xffff0000,R1\n" // The carry bit can only and will only
|
72 |
|
|
"\tADD.NZ 1,R1\n" // ever be a one here. Add it in.
|
73 |
|
|
"\tAND 0x0ffff,R1\n"
|
74 |
|
|
"\tXOR 0x0ffff,R1\n"
|
75 |
|
|
"\tRETN");
|
76 |
|
|
#endif
|
77 |
|
|
}
|
78 |
|
|
|