xref: /linux/lib/gen_crc32table.c (revision e37f2f93)
1b2441318SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
21da177e4SLinus Torvalds #include <stdio.h>
31fb2e3f2SKrzysztof Kozlowski #include "../include/linux/crc32poly.h"
4324eb0f1SBob Pearson #include "../include/generated/autoconf.h"
51da177e4SLinus Torvalds #include "crc32defs.h"
61da177e4SLinus Torvalds #include <inttypes.h>
71da177e4SLinus Torvalds 
81da177e4SLinus Torvalds #define ENTRIES_PER_LINE 4
91da177e4SLinus Torvalds 
10324eb0f1SBob Pearson #if CRC_LE_BITS > 8
11324eb0f1SBob Pearson # define LE_TABLE_ROWS (CRC_LE_BITS/8)
129a1dbf6aSBob Pearson # define LE_TABLE_SIZE 256
139a1dbf6aSBob Pearson #else
14324eb0f1SBob Pearson # define LE_TABLE_ROWS 1
15324eb0f1SBob Pearson # define LE_TABLE_SIZE (1 << CRC_LE_BITS)
169a1dbf6aSBob Pearson #endif
171da177e4SLinus Torvalds 
18324eb0f1SBob Pearson #if CRC_BE_BITS > 8
19324eb0f1SBob Pearson # define BE_TABLE_ROWS (CRC_BE_BITS/8)
20324eb0f1SBob Pearson # define BE_TABLE_SIZE 256
21324eb0f1SBob Pearson #else
22324eb0f1SBob Pearson # define BE_TABLE_ROWS 1
23324eb0f1SBob Pearson # define BE_TABLE_SIZE (1 << CRC_BE_BITS)
24324eb0f1SBob Pearson #endif
25324eb0f1SBob Pearson 
26324eb0f1SBob Pearson static uint32_t crc32table_le[LE_TABLE_ROWS][256];
27324eb0f1SBob Pearson static uint32_t crc32table_be[BE_TABLE_ROWS][256];
2846c5801eSDarrick J. Wong static uint32_t crc32ctable_le[LE_TABLE_ROWS][256];
291da177e4SLinus Torvalds 
301da177e4SLinus Torvalds /**
311da177e4SLinus Torvalds  * crc32init_le() - allocate and initialize LE table data
321da177e4SLinus Torvalds  *
331da177e4SLinus Torvalds  * crc is the crc of the byte i; other entries are filled in based on the
341da177e4SLinus Torvalds  * fact that crctable[i^j] = crctable[i] ^ crctable[j].
351da177e4SLinus Torvalds  *
361da177e4SLinus Torvalds  */
crc32init_le_generic(const uint32_t polynomial,uint32_t (* tab)[256])3746c5801eSDarrick J. Wong static void crc32init_le_generic(const uint32_t polynomial,
3846c5801eSDarrick J. Wong 				 uint32_t (*tab)[256])
391da177e4SLinus Torvalds {
401da177e4SLinus Torvalds 	unsigned i, j;
411da177e4SLinus Torvalds 	uint32_t crc = 1;
421da177e4SLinus Torvalds 
4346c5801eSDarrick J. Wong 	tab[0][0] = 0;
441da177e4SLinus Torvalds 
459a1dbf6aSBob Pearson 	for (i = LE_TABLE_SIZE >> 1; i; i >>= 1) {
4646c5801eSDarrick J. Wong 		crc = (crc >> 1) ^ ((crc & 1) ? polynomial : 0);
471da177e4SLinus Torvalds 		for (j = 0; j < LE_TABLE_SIZE; j += 2 * i)
4846c5801eSDarrick J. Wong 			tab[0][i + j] = crc ^ tab[0][j];
49836e2af9SJoakim Tjernlund 	}
50836e2af9SJoakim Tjernlund 	for (i = 0; i < LE_TABLE_SIZE; i++) {
5146c5801eSDarrick J. Wong 		crc = tab[0][i];
52324eb0f1SBob Pearson 		for (j = 1; j < LE_TABLE_ROWS; j++) {
5346c5801eSDarrick J. Wong 			crc = tab[0][crc & 0xff] ^ (crc >> 8);
5446c5801eSDarrick J. Wong 			tab[j][i] = crc;
55836e2af9SJoakim Tjernlund 		}
561da177e4SLinus Torvalds 	}
571da177e4SLinus Torvalds }
581da177e4SLinus Torvalds 
crc32init_le(void)5946c5801eSDarrick J. Wong static void crc32init_le(void)
6046c5801eSDarrick J. Wong {
61*e37f2f93SKrzysztof Kozlowski 	crc32init_le_generic(CRC32_POLY_LE, crc32table_le);
6246c5801eSDarrick J. Wong }
6346c5801eSDarrick J. Wong 
crc32cinit_le(void)6446c5801eSDarrick J. Wong static void crc32cinit_le(void)
6546c5801eSDarrick J. Wong {
6646c5801eSDarrick J. Wong 	crc32init_le_generic(CRC32C_POLY_LE, crc32ctable_le);
6746c5801eSDarrick J. Wong }
6846c5801eSDarrick J. Wong 
691da177e4SLinus Torvalds /**
701da177e4SLinus Torvalds  * crc32init_be() - allocate and initialize BE table data
711da177e4SLinus Torvalds  */
crc32init_be(void)721da177e4SLinus Torvalds static void crc32init_be(void)
731da177e4SLinus Torvalds {
741da177e4SLinus Torvalds 	unsigned i, j;
751da177e4SLinus Torvalds 	uint32_t crc = 0x80000000;
761da177e4SLinus Torvalds 
77836e2af9SJoakim Tjernlund 	crc32table_be[0][0] = 0;
781da177e4SLinus Torvalds 
791da177e4SLinus Torvalds 	for (i = 1; i < BE_TABLE_SIZE; i <<= 1) {
80*e37f2f93SKrzysztof Kozlowski 		crc = (crc << 1) ^ ((crc & 0x80000000) ? CRC32_POLY_BE : 0);
811da177e4SLinus Torvalds 		for (j = 0; j < i; j++)
82836e2af9SJoakim Tjernlund 			crc32table_be[0][i + j] = crc ^ crc32table_be[0][j];
83836e2af9SJoakim Tjernlund 	}
84836e2af9SJoakim Tjernlund 	for (i = 0; i < BE_TABLE_SIZE; i++) {
85836e2af9SJoakim Tjernlund 		crc = crc32table_be[0][i];
86324eb0f1SBob Pearson 		for (j = 1; j < BE_TABLE_ROWS; j++) {
87836e2af9SJoakim Tjernlund 			crc = crc32table_be[0][(crc >> 24) & 0xff] ^ (crc << 8);
88836e2af9SJoakim Tjernlund 			crc32table_be[j][i] = crc;
89836e2af9SJoakim Tjernlund 		}
901da177e4SLinus Torvalds 	}
911da177e4SLinus Torvalds }
921da177e4SLinus Torvalds 
output_table(uint32_t (* table)[256],int rows,int len,char * trans)93324eb0f1SBob Pearson static void output_table(uint32_t (*table)[256], int rows, int len, char *trans)
941da177e4SLinus Torvalds {
95836e2af9SJoakim Tjernlund 	int i, j;
961da177e4SLinus Torvalds 
97324eb0f1SBob Pearson 	for (j = 0 ; j < rows; j++) {
98836e2af9SJoakim Tjernlund 		printf("{");
991da177e4SLinus Torvalds 		for (i = 0; i < len - 1; i++) {
1001da177e4SLinus Torvalds 			if (i % ENTRIES_PER_LINE == 0)
1011da177e4SLinus Torvalds 				printf("\n");
102836e2af9SJoakim Tjernlund 			printf("%s(0x%8.8xL), ", trans, table[j][i]);
1031da177e4SLinus Torvalds 		}
104836e2af9SJoakim Tjernlund 		printf("%s(0x%8.8xL)},\n", trans, table[j][len - 1]);
105836e2af9SJoakim Tjernlund 	}
1061da177e4SLinus Torvalds }
1071da177e4SLinus Torvalds 
main(int argc,char ** argv)1081da177e4SLinus Torvalds int main(int argc, char** argv)
1091da177e4SLinus Torvalds {
1101da177e4SLinus Torvalds 	printf("/* this file is generated - do not edit */\n\n");
1111da177e4SLinus Torvalds 
1121da177e4SLinus Torvalds 	if (CRC_LE_BITS > 1) {
1131da177e4SLinus Torvalds 		crc32init_le();
114f5e38b92SDaniel Borkmann 		printf("static const u32 ____cacheline_aligned "
115324eb0f1SBob Pearson 		       "crc32table_le[%d][%d] = {",
116324eb0f1SBob Pearson 		       LE_TABLE_ROWS, LE_TABLE_SIZE);
117324eb0f1SBob Pearson 		output_table(crc32table_le, LE_TABLE_ROWS,
118324eb0f1SBob Pearson 			     LE_TABLE_SIZE, "tole");
1191da177e4SLinus Torvalds 		printf("};\n");
1201da177e4SLinus Torvalds 	}
1211da177e4SLinus Torvalds 
1221da177e4SLinus Torvalds 	if (CRC_BE_BITS > 1) {
1231da177e4SLinus Torvalds 		crc32init_be();
124f5e38b92SDaniel Borkmann 		printf("static const u32 ____cacheline_aligned "
125324eb0f1SBob Pearson 		       "crc32table_be[%d][%d] = {",
126324eb0f1SBob Pearson 		       BE_TABLE_ROWS, BE_TABLE_SIZE);
127324eb0f1SBob Pearson 		output_table(crc32table_be, LE_TABLE_ROWS,
128324eb0f1SBob Pearson 			     BE_TABLE_SIZE, "tobe");
1291da177e4SLinus Torvalds 		printf("};\n");
1301da177e4SLinus Torvalds 	}
13146c5801eSDarrick J. Wong 	if (CRC_LE_BITS > 1) {
13246c5801eSDarrick J. Wong 		crc32cinit_le();
133f5e38b92SDaniel Borkmann 		printf("static const u32 ____cacheline_aligned "
13446c5801eSDarrick J. Wong 		       "crc32ctable_le[%d][%d] = {",
13546c5801eSDarrick J. Wong 		       LE_TABLE_ROWS, LE_TABLE_SIZE);
13646c5801eSDarrick J. Wong 		output_table(crc32ctable_le, LE_TABLE_ROWS,
13746c5801eSDarrick J. Wong 			     LE_TABLE_SIZE, "tole");
13846c5801eSDarrick J. Wong 		printf("};\n");
13946c5801eSDarrick J. Wong 	}
1401da177e4SLinus Torvalds 
1411da177e4SLinus Torvalds 	return 0;
1421da177e4SLinus Torvalds }
143