xref: /freebsd/contrib/xz/src/liblzma/check/crc32_loongarch.h (revision 128836d304d93f2d00eb14069c27089ab46c38d4)
1 // SPDX-License-Identifier: 0BSD
2 
3 ///////////////////////////////////////////////////////////////////////////////
4 //
5 /// \file       crc32_loongarch.h
6 /// \brief      CRC32 calculation with LoongArch optimization
7 //
8 //  Authors:    Xi Ruoyao
9 //              Lasse Collin
10 //
11 ///////////////////////////////////////////////////////////////////////////////
12 
13 #ifndef LZMA_CRC32_LOONGARCH_H
14 #define LZMA_CRC32_LOONGARCH_H
15 
16 #include <larchintrin.h>
17 
18 
19 static uint32_t
crc32_arch_optimized(const uint8_t * buf,size_t size,uint32_t crc_unsigned)20 crc32_arch_optimized(const uint8_t *buf, size_t size, uint32_t crc_unsigned)
21 {
22 	int32_t crc = (int32_t)~crc_unsigned;
23 
24 	if (size >= 8) {
25 		const size_t align = (0 - (uintptr_t)buf) & 7;
26 
27 		if (align & 1)
28 			crc = __crc_w_b_w((int8_t)*buf++, crc);
29 
30 		if (align & 2) {
31 			crc = __crc_w_h_w((int16_t)aligned_read16le(buf), crc);
32 			buf += 2;
33 		}
34 
35 		if (align & 4) {
36 			crc = __crc_w_w_w((int32_t)aligned_read32le(buf), crc);
37 			buf += 4;
38 		}
39 
40 		size -= align;
41 
42 		for (const uint8_t *limit = buf + (size & ~(size_t)7);
43 				buf < limit; buf += 8)
44 			crc = __crc_w_d_w((int64_t)aligned_read64le(buf), crc);
45 
46 		size &= 7;
47 	}
48 
49 	if (size & 4) {
50 		crc = __crc_w_w_w((int32_t)aligned_read32le(buf), crc);
51 		buf += 4;
52 	}
53 
54 	if (size & 2) {
55 		crc = __crc_w_h_w((int16_t)aligned_read16le(buf), crc);
56 		buf += 2;
57 	}
58 
59 	if (size & 1)
60 		crc = __crc_w_b_w((int8_t)*buf, crc);
61 
62 	return (uint32_t)~crc;
63 }
64 
65 #endif // LZMA_CRC32_LOONGARCH_H
66