summaryrefslogtreecommitdiffstats
path: root/Documentation/crc32.txt
diff options
context:
space:
mode:
authorMauro Carvalho Chehab <mchehab@s-opensource.com>2017-05-14 08:56:02 -0400
committerJonathan Corbet <corbet@lwn.net>2017-07-14 15:51:30 -0400
commit2e4e6f30f7ff84632e893786fab5e8ff44ff3e03 (patch)
tree33e07f82369ecaec0605fbe7c59b961a7e390b56 /Documentation/crc32.txt
parente8cb6f1edc57e5c729ce4e37a54a5f84fac0c6a4 (diff)
crc32.txt: standardize document format
Each text file under Documentation follows a different format. Some doesn't even have titles! Change its representation to follow the adopted standard, using ReST markups for it to be parseable by Sphinx: - Add a title for the document; - Mark literal blocks. While here, replace a comma by a dot at the end of a paragraph. Signed-off-by: Mauro Carvalho Chehab <mchehab@s-opensource.com> Signed-off-by: Jonathan Corbet <corbet@lwn.net>
Diffstat (limited to 'Documentation/crc32.txt')
-rw-r--r--Documentation/crc32.txt75
1 files changed, 41 insertions, 34 deletions
diff --git a/Documentation/crc32.txt b/Documentation/crc32.txt
index a08a7dd9d625..8a6860f33b4e 100644
--- a/Documentation/crc32.txt
+++ b/Documentation/crc32.txt
@@ -1,4 +1,6 @@
1A brief CRC tutorial. 1=================================
2brief tutorial on CRC computation
3=================================
2 4
3A CRC is a long-division remainder. You add the CRC to the message, 5A CRC is a long-division remainder. You add the CRC to the message,
4and the whole thing (message+CRC) is a multiple of the given 6and the whole thing (message+CRC) is a multiple of the given
@@ -8,7 +10,8 @@ remainder computed on the message+CRC is 0. This latter approach
8is used by a lot of hardware implementations, and is why so many 10is used by a lot of hardware implementations, and is why so many
9protocols put the end-of-frame flag after the CRC. 11protocols put the end-of-frame flag after the CRC.
10 12
11It's actually the same long division you learned in school, except that 13It's actually the same long division you learned in school, except that:
14
12- We're working in binary, so the digits are only 0 and 1, and 15- We're working in binary, so the digits are only 0 and 1, and
13- When dividing polynomials, there are no carries. Rather than add and 16- When dividing polynomials, there are no carries. Rather than add and
14 subtract, we just xor. Thus, we tend to get a bit sloppy about 17 subtract, we just xor. Thus, we tend to get a bit sloppy about
@@ -40,11 +43,12 @@ throw the quotient bit away, but subtract the appropriate multiple of
40the polynomial from the remainder and we're back to where we started, 43the polynomial from the remainder and we're back to where we started,
41ready to process the next bit. 44ready to process the next bit.
42 45
43A big-endian CRC written this way would be coded like: 46A big-endian CRC written this way would be coded like::
44for (i = 0; i < input_bits; i++) { 47
45 multiple = remainder & 0x80000000 ? CRCPOLY : 0; 48 for (i = 0; i < input_bits; i++) {
46 remainder = (remainder << 1 | next_input_bit()) ^ multiple; 49 multiple = remainder & 0x80000000 ? CRCPOLY : 0;
47} 50 remainder = (remainder << 1 | next_input_bit()) ^ multiple;
51 }
48 52
49Notice how, to get at bit 32 of the shifted remainder, we look 53Notice how, to get at bit 32 of the shifted remainder, we look
50at bit 31 of the remainder *before* shifting it. 54at bit 31 of the remainder *before* shifting it.
@@ -54,25 +58,26 @@ the remainder don't actually affect any decision-making until
5432 bits later. Thus, the first 32 cycles of this are pretty boring. 5832 bits later. Thus, the first 32 cycles of this are pretty boring.
55Also, to add the CRC to a message, we need a 32-bit-long hole for it at 59Also, to add the CRC to a message, we need a 32-bit-long hole for it at
56the end, so we have to add 32 extra cycles shifting in zeros at the 60the end, so we have to add 32 extra cycles shifting in zeros at the
57end of every message, 61end of every message.
58 62
59These details lead to a standard trick: rearrange merging in the 63These details lead to a standard trick: rearrange merging in the
60next_input_bit() until the moment it's needed. Then the first 32 cycles 64next_input_bit() until the moment it's needed. Then the first 32 cycles
61can be precomputed, and merging in the final 32 zero bits to make room 65can be precomputed, and merging in the final 32 zero bits to make room
62for the CRC can be skipped entirely. This changes the code to: 66for the CRC can be skipped entirely. This changes the code to::
63 67
64for (i = 0; i < input_bits; i++) { 68 for (i = 0; i < input_bits; i++) {
65 remainder ^= next_input_bit() << 31; 69 remainder ^= next_input_bit() << 31;
66 multiple = (remainder & 0x80000000) ? CRCPOLY : 0; 70 multiple = (remainder & 0x80000000) ? CRCPOLY : 0;
67 remainder = (remainder << 1) ^ multiple; 71 remainder = (remainder << 1) ^ multiple;
68} 72 }
69 73
70With this optimization, the little-endian code is particularly simple: 74With this optimization, the little-endian code is particularly simple::
71for (i = 0; i < input_bits; i++) { 75
72 remainder ^= next_input_bit(); 76 for (i = 0; i < input_bits; i++) {
73 multiple = (remainder & 1) ? CRCPOLY : 0; 77 remainder ^= next_input_bit();
74 remainder = (remainder >> 1) ^ multiple; 78 multiple = (remainder & 1) ? CRCPOLY : 0;
75} 79 remainder = (remainder >> 1) ^ multiple;
80 }
76 81
77The most significant coefficient of the remainder polynomial is stored 82The most significant coefficient of the remainder polynomial is stored
78in the least significant bit of the binary "remainder" variable. 83in the least significant bit of the binary "remainder" variable.
@@ -81,23 +86,25 @@ be bit-reversed) and next_input_bit().
81 86
82As long as next_input_bit is returning the bits in a sensible order, we don't 87As long as next_input_bit is returning the bits in a sensible order, we don't
83*have* to wait until the last possible moment to merge in additional bits. 88*have* to wait until the last possible moment to merge in additional bits.
84We can do it 8 bits at a time rather than 1 bit at a time: 89We can do it 8 bits at a time rather than 1 bit at a time::
85for (i = 0; i < input_bytes; i++) { 90
86 remainder ^= next_input_byte() << 24; 91 for (i = 0; i < input_bytes; i++) {
87 for (j = 0; j < 8; j++) { 92 remainder ^= next_input_byte() << 24;
88 multiple = (remainder & 0x80000000) ? CRCPOLY : 0; 93 for (j = 0; j < 8; j++) {
89 remainder = (remainder << 1) ^ multiple; 94 multiple = (remainder & 0x80000000) ? CRCPOLY : 0;
95 remainder = (remainder << 1) ^ multiple;
96 }
90 } 97 }
91}
92 98
93Or in little-endian: 99Or in little-endian::
94for (i = 0; i < input_bytes; i++) { 100
95 remainder ^= next_input_byte(); 101 for (i = 0; i < input_bytes; i++) {
96 for (j = 0; j < 8; j++) { 102 remainder ^= next_input_byte();
97 multiple = (remainder & 1) ? CRCPOLY : 0; 103 for (j = 0; j < 8; j++) {
98 remainder = (remainder >> 1) ^ multiple; 104 multiple = (remainder & 1) ? CRCPOLY : 0;
105 remainder = (remainder >> 1) ^ multiple;
106 }
99 } 107 }
100}
101 108
102If the input is a multiple of 32 bits, you can even XOR in a 32-bit 109If the input is a multiple of 32 bits, you can even XOR in a 32-bit
103word at a time and increase the inner loop count to 32. 110word at a time and increase the inner loop count to 32.