@@ -10,13 +10,15 @@ TUInt128 = record
1010 end ;
1111
1212 // PCLMULQDQ / VPCLMULQDQ CRC folding and Barrett reduction constants.
13- // Layout must match the assembly expectations in CRCFoldPclmul.inc
14- // and CRCFoldVpclmul.inc.
13+ // Layout must match the assembly expectations in the CRCFold*.inc files.
1514 TCRCFoldConstants = packed record
1615 Fold_4x128: array [0 .. 1 ] of UInt64; // offset 0: fold-by-4 constants (stride 512)
1716 Fold_1x128: array [0 .. 1 ] of UInt64; // offset 16: fold-by-1 constants (stride 128)
1817 Barrett: array [0 .. 1 ] of UInt64; // offset 32: Barrett reduction constants
1918 Fold_8x128: array [0 .. 1 ] of UInt64; // offset 48: fold-by-8 constants (stride 1024)
19+ BswapMask: array [0 .. 15 ] of Byte; // offset 64: byte-reverse mask for MSB-first CRCs
20+ CrcBits: UInt64; // offset 80: CRC width (8..64)
21+ BarrettShift: UInt64; // offset 88: = 64 - CrcBits (MSB psrlq alignment)
2022 end ;
2123
2224 TGF2 = class sealed
@@ -214,8 +216,8 @@ class function TGF2.BitReverse(AValue: UInt64; ANumBits: Int32): UInt64;
214216class procedure TGF2.GenerateFoldConstants (APoly: UInt64; ABits: Int32;
215217 AReflected: Boolean; out AConstants: TCRCFoldConstants);
216218var
217- LK, LPowOfX: Int32;
218- LConst0, LConst1, LBarrett0, LBarrett1, LGMinusXn: UInt64;
219+ LK, LPowOfX, I : Int32;
220+ LConst0, LConst1, LBarrett0, LGMinusXn: UInt64;
219221 LDiv128: TUInt128;
220222begin
221223 // Following the Linux kernel gen-crc-consts.py algorithm.
@@ -271,40 +273,61 @@ class procedure TGF2.GenerateFoldConstants(APoly: UInt64; ABits: Int32;
271273 end ;
272274
273275 // --- Barrett reduction constants ---
274- // barrett[0] = floor(x^(63+n) / G)
275- LDiv128.Lo := 0 ;
276- LDiv128.Hi := 0 ;
277- if (63 + ABits) < 64 then
278- LDiv128.Lo := UInt64(1 ) shl (63 + ABits)
279- else if (63 + ABits) = 64 then
280- LDiv128.Hi := 1
281- else
282- LDiv128.Hi := UInt64(1 ) shl ((63 + ABits) - 64 );
283- LBarrett0 := DivPoly(LDiv128, APoly, ABits);
284-
285- // barrett[1] = (G - x^n) * x^(64-n-1) for n < 64
286- // = ((G - x^n) - x^0) / x for n = 64
287276 LGMinusXn := APoly;
288- if ABits < 64 then
289- begin
290- LPowOfX := 64 - ABits - 1 ;
291- LBarrett1 := LGMinusXn shl LPowOfX;
292- end
293- else
294- begin
295- LBarrett1 := LGMinusXn shr 1 ;
296- end ;
297277
298278 if AReflected then
299279 begin
280+ // LSB-first: m = 63.
281+ // Barrett[0] = bitreflect(floor(x^(63+n) / G), 64)
282+ // Barrett[1] = bitreflect(G, n+1) (truncated: for n=64, x^0 removed)
283+ LDiv128.Lo := 0 ;
284+ LDiv128.Hi := 0 ;
285+ if (63 + ABits) < 64 then
286+ LDiv128.Lo := UInt64(1 ) shl (63 + ABits)
287+ else if (63 + ABits) = 64 then
288+ LDiv128.Hi := 1
289+ else
290+ LDiv128.Hi := UInt64(1 ) shl ((63 + ABits) - 64 );
291+ LBarrett0 := DivPoly(LDiv128, APoly, ABits);
292+
300293 AConstants.Barrett[0 ] := BitReverse(LBarrett0, 64 );
301- AConstants.Barrett[1 ] := BitReverse(LBarrett1, 64 );
294+ if ABits < 64 then
295+ begin
296+ LPowOfX := 64 - ABits - 1 ;
297+ AConstants.Barrett[1 ] := BitReverse(LGMinusXn shl LPowOfX, 64 );
298+ end
299+ else
300+ AConstants.Barrett[1 ] := BitReverse(LGMinusXn shr 1 , 64 );
302301 end
303302 else
304303 begin
305- AConstants.Barrett[0 ] := LBarrett1;
306- AConstants.Barrett[1 ] := LBarrett0;
304+ // MSB-first: m = 64. Two-round Barrett per Linux kernel.
305+ // Barrett[0] = floor(x^(64+n) / G) - x^64 (mu, low 64 bits)
306+ // Since floor(x^(64+n)/G) = x^64 + floor(APoly*x^64 / G),
307+ // we compute Barrett[0] = DivPoly(APoly*x^64, G) to avoid the x^64 overflow.
308+ // Barrett[1] = G (full generator polynomial; for n=64, x^64 term implicit)
309+ LDiv128.Hi := APoly;
310+ LDiv128.Lo := 0 ;
311+ AConstants.Barrett[0 ] := DivPoly(LDiv128, APoly, ABits);
312+ if ABits < 64 then
313+ AConstants.Barrett[1 ] := (UInt64(1 ) shl ABits) or APoly
314+ else
315+ AConstants.Barrett[1 ] := APoly;
307316 end ;
317+
318+ // --- Byte-swap mask for MSB-first CRCs ---
319+ if AReflected then
320+ FillChar(AConstants.BswapMask[0 ], 16 , 0 )
321+ else
322+ for I := 0 to 15 do
323+ AConstants.BswapMask[I] := Byte(15 - I);
324+
325+ // --- Metadata ---
326+ AConstants.CrcBits := UInt64(ABits);
327+ if ABits < 64 then
328+ AConstants.BarrettShift := UInt64(64 - ABits)
329+ else
330+ AConstants.BarrettShift := 0 ;
308331end ;
309332
310333end .
0 commit comments