/src/ffmpeg/libavutil/x86/crc.h
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2025 Shreesh Adiga <16567adigashreesh@gmail.com> |
3 | | * |
4 | | * This file is part of FFmpeg. |
5 | | * |
6 | | * FFmpeg is free software; you can redistribute it and/or |
7 | | * modify it under the terms of the GNU Lesser General Public |
8 | | * License as published by the Free Software Foundation; either |
9 | | * version 2.1 of the License, or (at your option) any later version. |
10 | | * |
11 | | * FFmpeg is distributed in the hope that it will be useful, |
12 | | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
13 | | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU |
14 | | * Lesser General Public License for more details. |
15 | | * |
16 | | * You should have received a copy of the GNU Lesser General Public |
17 | | * License along with FFmpeg; if not, write to the Free Software |
18 | | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA |
19 | | */ |
20 | | |
21 | | #ifndef AVUTIL_X86_CRC_H |
22 | | #define AVUTIL_X86_CRC_H |
23 | | |
24 | | #include "config.h" |
25 | | #include "libavutil/attributes.h" |
26 | | #include "libavutil/attributes_internal.h" |
27 | | #include "libavutil/avassert.h" |
28 | | #include "libavutil/cpu.h" |
29 | | #include "libavutil/crc.h" |
30 | | #include "libavutil/intreadwrite.h" |
31 | | #include "libavutil/x86/cpu.h" |
32 | | |
33 | | #if HAVE_CLMUL_EXTERNAL |
34 | | #include "libavutil/crc_internal.h" |
35 | | |
36 | | FF_VISIBILITY_PUSH_HIDDEN |
37 | | uint32_t ff_crc_clmul(const AVCRC *ctx, uint32_t crc, |
38 | | const uint8_t *buffer, size_t length); |
39 | | uint32_t ff_crc_le_clmul(const AVCRC *ctx, uint32_t crc, |
40 | | const uint8_t *buffer, size_t length); |
41 | | FF_VISIBILITY_POP_HIDDEN |
42 | | |
43 | | enum { |
44 | | CRC_C = 0, |
45 | | CLMUL_BE, |
46 | | CLMUL_LE, |
47 | | }; |
48 | | |
49 | | static const AVCRC crc_table_clmul[AV_CRC_MAX][17] = { |
50 | | [AV_CRC_8_ATM] = { |
51 | | CLMUL_BE, |
52 | | 0x32000000, 0x0, 0xbc000000, 0x0, |
53 | | 0xc4000000, 0x0, 0x94000000, 0x0, |
54 | | 0x62000000, 0x0, 0x79000000, 0x0, |
55 | | 0x07156a16, 0x1, 0x07000000, 0x1, |
56 | | }, |
57 | | [AV_CRC_8_EBU] = { |
58 | | CLMUL_BE, |
59 | | 0xb5000000, 0x0, 0xf3000000, 0x0, |
60 | | 0xfc000000, 0x0, 0x0d000000, 0x0, |
61 | | 0x6a000000, 0x0, 0x65000000, 0x0, |
62 | | 0x1c4b8192, 0x1, 0x1d000000, 0x1, |
63 | | }, |
64 | | [AV_CRC_16_ANSI] = { |
65 | | CLMUL_BE, |
66 | | 0xf9e30000, 0x0, 0x807d0000, 0x0, |
67 | | 0xf9130000, 0x0, 0xff830000, 0x0, |
68 | | 0x807b0000, 0x0, 0x86630000, 0x0, |
69 | | 0xfffbffe7, 0x1, 0x80050000, 0x1, |
70 | | }, |
71 | | [AV_CRC_16_CCITT] = { |
72 | | CLMUL_BE, |
73 | | 0x60190000, 0x0, 0x59b00000, 0x0, |
74 | | 0xd5f60000, 0x0, 0x45630000, 0x0, |
75 | | 0xaa510000, 0x0, 0xeb230000, 0x0, |
76 | | 0x11303471, 0x1, 0x10210000, 0x1, |
77 | | }, |
78 | | [AV_CRC_24_IEEE] = { |
79 | | CLMUL_BE, |
80 | | 0x1f428700, 0x0, 0x467d2400, 0x0, |
81 | | 0x2c8c9d00, 0x0, 0x64e4d700, 0x0, |
82 | | 0xd9fe8c00, 0x0, 0xfd7e0c00, 0x0, |
83 | | 0xf845fe24, 0x1, 0x864cfb00, 0x1, |
84 | | }, |
85 | | [AV_CRC_32_IEEE] = { |
86 | | CLMUL_BE, |
87 | | 0x8833794c, 0x0, 0xe6228b11, 0x0, |
88 | | 0xc5b9cd4c, 0x0, 0xe8a45605, 0x0, |
89 | | 0x490d678d, 0x0, 0xf200aa66, 0x0, |
90 | | 0x04d101df, 0x1, 0x04c11db7, 0x1, |
91 | | }, |
92 | | [AV_CRC_32_IEEE_LE] = { |
93 | | CLMUL_LE, |
94 | | 0xc6e41596, 0x1, 0x54442bd4, 0x1, |
95 | | 0xccaa009e, 0x0, 0x751997d0, 0x1, |
96 | | 0xccaa009e, 0x0, 0x63cd6124, 0x1, |
97 | | 0xf7011640, 0x1, 0xdb710641, 0x1, |
98 | | }, |
99 | | [AV_CRC_16_ANSI_LE] = { |
100 | | CLMUL_LE, |
101 | | 0x0000bffa, 0x0, 0x1b0c2, 0x0, |
102 | | 0x00018cc2, 0x0, 0x1d0c2, 0x0, |
103 | | 0x00018cc2, 0x0, 0x1bc02, 0x0, |
104 | | 0xcfffbffe, 0x1, 0x14003, 0x0, |
105 | | }, |
106 | | }; |
107 | | |
108 | | static inline void crc_init_x86(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size) |
109 | 0 | { |
110 | 0 | uint64_t poly_; |
111 | 0 | if (le) { |
112 | | // convert the reversed representation to regular form |
113 | 0 | poly = reverse(poly, bits) >> 1; |
114 | 0 | } |
115 | | // convert to 32 degree polynomial |
116 | 0 | poly_ = ((uint64_t)poly) << (32 - bits); |
117 | |
|
118 | 0 | uint64_t div; |
119 | 0 | uint8_t *dst = (uint8_t*)(ctx + 1); |
120 | 0 | if (le) { |
121 | 0 | ctx[0] = CLMUL_LE; |
122 | 0 | AV_WN64(dst, xnmodp(4 * 128 - 32, poly_, 32, &div, le)); |
123 | 0 | AV_WN64(dst + 8, xnmodp(4 * 128 + 32, poly_, 32, &div, le)); |
124 | 0 | uint64_t tmp = xnmodp(128 - 32, poly_, 32, &div, le); |
125 | 0 | AV_WN64(dst + 16, tmp); |
126 | 0 | AV_WN64(dst + 24, xnmodp(128 + 32, poly_, 32, &div, le)); |
127 | 0 | AV_WN64(dst + 32, tmp); |
128 | 0 | AV_WN64(dst + 40, xnmodp(64, poly_, 32, &div, le)); |
129 | 0 | AV_WN64(dst + 48, div); |
130 | 0 | AV_WN64(dst + 56, reverse(poly_ | (1ULL << 32), 32)); |
131 | 0 | } else { |
132 | 0 | ctx[0] = CLMUL_BE; |
133 | 0 | AV_WN64(dst, xnmodp(4 * 128 + 64, poly_, 32, &div, le)); |
134 | 0 | AV_WN64(dst + 8, xnmodp(4 * 128, poly_, 32, &div, le)); |
135 | 0 | AV_WN64(dst + 16, xnmodp(128 + 64, poly_, 32, &div, le)); |
136 | 0 | AV_WN64(dst + 24, xnmodp(128, poly_, 32, &div, le)); |
137 | 0 | AV_WN64(dst + 32, xnmodp(64, poly_, 32, &div, le)); |
138 | 0 | AV_WN64(dst + 48, div); |
139 | 0 | AV_WN64(dst + 40, xnmodp(96, poly_, 32, &div, le)); |
140 | 0 | AV_WN64(dst + 56, poly_ | (1ULL << 32)); |
141 | 0 | } |
142 | 0 | } |
143 | | #endif |
144 | | |
145 | | static inline const AVCRC *ff_crc_get_table_x86(AVCRCId crc_id) |
146 | 0 | { |
147 | 0 | #if HAVE_CLMUL_EXTERNAL |
148 | 0 | int cpu_flags = av_get_cpu_flags(); |
149 | |
|
150 | 0 | if (EXTERNAL_CLMUL(cpu_flags)) { |
151 | 0 | return crc_table_clmul[crc_id]; |
152 | 0 | } |
153 | 0 | #endif |
154 | 0 | return NULL; |
155 | 0 | } |
156 | | |
157 | | static inline av_cold int ff_crc_init_x86(AVCRC *ctx, int le, int bits, uint32_t poly, int ctx_size) |
158 | 0 | { |
159 | 0 | #if HAVE_CLMUL_EXTERNAL |
160 | 0 | int cpu_flags = av_get_cpu_flags(); |
161 | |
|
162 | 0 | if (EXTERNAL_CLMUL(cpu_flags)) { |
163 | 0 | crc_init_x86(ctx, le, bits, poly, ctx_size); |
164 | 0 | return 1; |
165 | 0 | } |
166 | 0 | #endif |
167 | 0 | return 0; |
168 | 0 | } |
169 | | |
170 | | static inline uint32_t ff_crc_x86(const AVCRC *ctx, uint32_t crc, |
171 | | const uint8_t *buffer, size_t length) |
172 | 0 | { |
173 | 0 | switch (ctx[0]) { |
174 | 0 | #if HAVE_CLMUL_EXTERNAL |
175 | 0 | case CLMUL_BE: return ff_crc_clmul(ctx, crc, buffer, length); |
176 | 0 | case CLMUL_LE: return ff_crc_le_clmul(ctx, crc, buffer, length); |
177 | 0 | #endif |
178 | 0 | default: av_unreachable("x86 CRC only uses CLMUL_BE and CLMUL_LE"); |
179 | 0 | } |
180 | 0 | return 0; |
181 | 0 | } |
182 | | |
183 | | #endif /* AVUTIL_X86_CRC_H */ |