Schnelles CRC32 mit PCLMULQDQ
- NicTheQuick
- Ein Admin
- Beiträge: 8679
- Registriert: 29.08.2004 20:20
- Computerausstattung: Ryzen 7 5800X, 32 GB DDR4-3200
Ubuntu 22.04.3 LTS
GeForce RTX 3080 Ti - Wohnort: Saarbrücken
- Kontaktdaten:
Re: Schnelles CRC32 mit PCLMULQDQ
Aber was ist mit dem x86 Code?
Wenn Ich dort die 3 Zeilen mit dem Initialisierungswert ändere kommt ein falsches Ergebnis raus,
Wenn Ich dort die 3 Zeilen mit dem Initialisierungswert ändere kommt ein falsches Ergebnis raus,
PureBasic 5.46 LTS (Windows x86/x64) | windows 10 x64 Oktober failure
Re: Schnelles CRC32 mit PCLMULQDQ
Gerade getestet. Bei mir gibt es ausser einem Fehler kein Ergebnis.
X64 geht, X86 geht nicht
[22:36:23] Executable-Typ: Windows - x86 (32bit, Unicode)
[22:36:23] Executable gestartet.
[22:36:31] [ERROR] crc32.pbi (Zeile: 1)
[22:36:31] [ERROR] Ungültiger Speicherzugriff. (Lesefehler an der Adresse 4294967295)
[22:37:00] Das Programm wurde beendet.
Zeile 1 ist:
Oh Oh.
X64 geht, X86 geht nicht
[22:36:23] Executable-Typ: Windows - x86 (32bit, Unicode)
[22:36:23] Executable gestartet.
[22:36:31] [ERROR] crc32.pbi (Zeile: 1)
[22:36:31] [ERROR] Ungültiger Speicherzugriff. (Lesefehler an der Adresse 4294967295)
[22:37:00] Das Programm wurde beendet.
Zeile 1 ist:
Code: Alles auswählen
Procedure.l CRC32_CL(Mem, Laenge, Crc32.l)
Skylake QuadCore i7 6700K @4400MHz, MSI Z170A Gaming M5, 64 GB DDR4 @ 2133MHz, B: Ramdisk 32GB, C: Raid0 SATA SSD 1TB, D: Raid0 M2 SSD 1TB, E: Raid0 HDD 8TB, 28" 4K @ RTX2080, Win10 X64
Re: Schnelles CRC32 mit PCLMULQDQ
Natürlich muss dann auch die 32-Bit-Version umgemodelt werden. Wichtig ist das Alignment von *buffer! Muss mind. 16 sein! Bei 32-Bit muss nachgeholfen werden. Das Ganze sieht dann so aus:
Gruß
Helle
Code: Alles auswählen
Procedure.l CRC32_CL(Mem, Laenge, Crc32)
CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
!MOV r9,[p.v_Laenge]
!OR r9,r9 ;erstmal Test, ob Länge = 0
!JNZ Laenge_OK ;nicht 0
!MOV rax,r9
ProcedureReturn ;Rückgabewert = 0 für Länge = 0
!Laenge_OK:
;Test auf PCLMULQDQ
!MOV eax,1
!CPUID
!MOV eax,[p.v_Crc32] ;liest vom Stack, muss nicht rax sein
!NOT eax ;vlt. der einfachste Weg
;-----
!TEST ecx,2
!JNZ CL_OK ;kann losgehen! Auskommentieren für Test ohne PCLMULQDQ
!LEA r10,[CRC_Table] ;die CPU bringts nicht, also konventionell
!MOV r8,[p.v_Mem]
!@@:
!MOVZX rcx,byte[r8]
!XOR cl,al
!SHR rax,8
!XOR eax,dword[r10+rcx*4]
!INC r8
!DEC r9 ;Länge
!JNZ @b
!NOT eax ;wegen Polynomial Reversed
ProcedureReturn
!CL_OK:
!AND r9,0FFFFFFFFFFFFFFC0h ;Länge < 40?
!JZ less_64 ;ja, konventionell weiter
!MOVD xmm0,eax ;eax = Initialisierungswert für CRC32
!MOV r8,[p.v_Mem]
!MOVDQA xmm1,[r8]
!MOVDQA xmm2,[r8+10h]
!MOVDQA xmm3,[r8+20h]
!MOVDQA xmm4,[r8+30h]
!PXOR xmm1,xmm0
!SUB r9,40h
!ADD r8,40h
!MOVDQA xmm0,[Lconstant_R2R1]
!loop_64:
!PREFETCHNTA [r8+0c0h] ;Cache "vorfüllen"
!MOVDQA xmm5,xmm1
!MOVDQA xmm6,xmm2
!MOVDQA xmm7,xmm3
!MOVDQA xmm8,xmm4
!PCLMULQDQ xmm1,xmm0,00h
!PCLMULQDQ xmm2,xmm0,00h
!PCLMULQDQ xmm3,xmm0,00h
!PCLMULQDQ xmm4,xmm0,00h
!PCLMULQDQ xmm5,xmm0,11h
!PCLMULQDQ xmm6,xmm0,11h
!PCLMULQDQ xmm7,xmm0,11h
!PCLMULQDQ xmm8,xmm0,11h
!PXOR xmm1,xmm5
!PXOR xmm2,xmm6
!PXOR xmm3,xmm7
!PXOR xmm4,xmm8
!PXOR xmm1,[r8]
!PXOR xmm2,[r8+10h]
!PXOR xmm3,[r8+20h]
!PXOR xmm4,[r8+30h]
!SUB r9,40h
!ADD r8,40h
!CMP r9,40h
!JGE loop_64
!MOVDQA xmm0,[Lconstant_R4R3]
!PREFETCHNTA [r8]
!MOVDQA xmm5,xmm1
!PCLMULQDQ xmm1,xmm0,00h
!PCLMULQDQ xmm5,xmm0,11h
!PXOR xmm1,xmm5
!PXOR xmm1,xmm2
!MOVDQA xmm5,xmm1
!PCLMULQDQ xmm1,xmm0,00h
!PCLMULQDQ xmm5,xmm0,11h
!PXOR xmm1,xmm5
!PXOR xmm1,xmm3
!MOVDQA xmm5,xmm1
!PCLMULQDQ xmm1,xmm0,00h
!PCLMULQDQ xmm5,xmm0,11h
!PXOR xmm1,xmm5
!PXOR xmm1,xmm4
!PCLMULQDQ xmm0,xmm1,01h
!PSRLDQ xmm1,08h
!PXOR xmm1,xmm0
!MOVDQA xmm2,xmm1
!MOVDQA xmm0,[Lconstant_R5]
!MOVDQA xmm3,[Lconstant_mask32]
!PSRLDQ xmm2,04h
!PAND xmm1,xmm3
!PCLMULQDQ xmm1,xmm0,00h
!PXOR xmm1,xmm2
!MOVDQA xmm0,[Lconstant_RUpoly]
!MOVDQA xmm2,xmm1
!PAND xmm1,xmm3
!PCLMULQDQ xmm1,xmm0,10h
!PAND xmm1,xmm3
!PCLMULQDQ xmm1,xmm0,00h
!PXOR xmm1,xmm2
!PEXTRD eax,xmm1,01h ;eax ist CRC32 (bis hierher)
!less_64: ;Rest (max.63 Bytes)
!MOV r8,[p.v_Mem]
!MOV r9,[p.v_Laenge]
!ADD r8,r9
!AND r9,3fh ;möglicher Rest
!JZ NoRest ;kein Rest
!LEA r10,[CRC_Table] ;die restlichen Bytes mit Tabelle
!SUB r8,r9
!@@:
!MOVZX rcx,byte[r8]
!XOR cl,al
!SHR rax,8
!XOR eax,dword[r10+rcx*4]
!INC r8
!DEC r9
!JNZ @b
!NoRest:
!NOT eax ;wegen Polynomial Reversed
ProcedureReturn
CompilerElse
!MOV eax,[p.v_Laenge]
!OR eax,eax ;erstmal Test, ob Länge = 0
!JNZ Laenge_OK ;nicht 0
ProcedureReturn ;Rückgabewert = 0 für Länge = 0
!Laenge_OK:
;Test auf PCLMULQDQ
!MOV eax,1
!CPUID
!MOV eax,[p.v_Crc32] ;Initialisierungswert für CRC32
!NOT eax
!TEST ecx,2
!JNZ CL_OK ;kann losgehen! Auskommentieren für Test ohne PCLMULQDQ
!MOV edx,[p.v_Laenge] ;die CPU bringts nicht, also konventionell
!MOV ecx,[p.v_Mem]
!PUSH esi
!MOV esi,ecx
!PUSH ebx
!LEA ebx,[CRC_Table]
!@@:
!MOVZX ecx,byte[esi] ;Mem
!XOR cl,al
!SHR eax,8
!XOR eax,dword[ebx+ecx*4] ;Table
!INC esi
!DEC edx ;Länge
!JNZ @b
!POP esi
!POP ebx
!NOT eax ;wegen Polynomial Reversed
ProcedureReturn
!CL_OK:
!MOV edx,[p.v_Laenge]
!AND edx,0FFFFFFC0h ;Länge < 40h?
!JZ less_64 ;ja, konventionell weiter
!MOVD xmm5,eax ;eax = Initialisierungswert für CRC32
!MOV ecx,[p.v_Mem]
!MOVDQA xmm0,[ecx]
!MOVDQA xmm1,[ecx+10h]
!MOVDQA xmm2,[ecx+20h]
!MOVDQA xmm3,[ecx+30h]
!PXOR xmm0,xmm5
!SUB edx,40h
!ADD ecx,40h
!loop_64:
!PREFETCHNTA [ecx+0c0h] ;Cache "vorfüllen"
!MOVDQA xmm4,xmm0
!MOVDQA xmm5,xmm1
!MOVDQA xmm6,xmm2
!MOVDQA xmm7,xmm3
!PCLMULQDQ xmm0,[Lconstant_R2R1],00h
!PCLMULQDQ xmm1,[Lconstant_R2R1],00h
!PCLMULQDQ xmm2,[Lconstant_R2R1],00h
!PCLMULQDQ xmm3,[Lconstant_R2R1],00h
!PCLMULQDQ xmm4,[Lconstant_R2R1],11h
!PCLMULQDQ xmm5,[Lconstant_R2R1],11h
!PCLMULQDQ xmm6,[Lconstant_R2R1],11h
!PCLMULQDQ xmm7,[Lconstant_R2R1],11h
!PXOR xmm0,xmm4
!PXOR xmm1,xmm5
!PXOR xmm2,xmm6
!PXOR xmm3,xmm7
!PXOR xmm0,[ecx]
!PXOR xmm1,[ecx+10h]
!PXOR xmm2,[ecx+20h]
!PXOR xmm3,[ecx+30h]
!SUB edx,40h
!ADD ecx,40h
!CMP edx,40h
!JGE loop_64
!MOVDQA xmm6,[Lconstant_R4R3]
!PREFETCHNTA [ecx]
!MOVDQA xmm4,xmm0
!PCLMULQDQ xmm0,xmm6,00h
!PCLMULQDQ xmm4,xmm6,11h
!PXOR xmm0,xmm4
!PXOR xmm0,xmm1
!MOVDQA xmm4,xmm0
!PCLMULQDQ xmm0,xmm6,00h
!PCLMULQDQ xmm4,xmm6,11h
!PXOR xmm0,xmm4
!PXOR xmm0,xmm2
!MOVDQA xmm4,xmm0
!PCLMULQDQ xmm0,xmm6,00h
!PCLMULQDQ xmm4,xmm6,11h
!PXOR xmm0,xmm4
!PXOR xmm0,xmm3
!PCLMULQDQ xmm6,xmm0,01h
!PSRLDQ xmm0,08h
!PXOR xmm0,xmm6
!MOVDQA xmm1,xmm0
!MOVDQA xmm6,[Lconstant_R5]
!MOVDQA xmm2,[Lconstant_mask32]
!PSRLDQ xmm1,04h
!PAND xmm0,xmm2
!PCLMULQDQ xmm0,xmm6,00h
!PXOR xmm0,xmm1
!MOVDQA xmm6,[Lconstant_RUpoly]
!MOVDQA xmm1,xmm0
!PAND xmm0,xmm2
!PCLMULQDQ xmm0,xmm6,10h
!PAND xmm0,xmm2
!PCLMULQDQ xmm0,xmm6,00h
!PXOR xmm0,xmm1
!less_64: ;Rest (max.63 Bytes)
!LEA ecx,[CRC_Table] ;die restlichen Bytes mit Tabelle
!MOV eax,[p.v_Mem]
!MOV edx,[p.v_Laenge]
!PUSH ebx
!MOV ebx,ecx
!PUSH esi
!MOV esi,eax
!PEXTRD eax,xmm0,01h ;eax ist CRC32 (bis hierher)
!ADD esi,edx
!AND edx,3fh ;möglicher Rest
!JZ NoRest ;kein Rest
!SUB esi,edx
!@@:
!MOVZX ecx,byte[esi]
!XOR cl,al
!SHR eax,8
!XOR eax,dword[ebx+ecx*4]
!INC esi
!DEC edx
!JNZ @b
!NoRest:
!POP esi
!POP ebx
!NOT eax ;wegen Polynomial Reversed
ProcedureReturn
CompilerEndIf
;Konstanten
!Align 16
!Lconstant_R2R1:
!dq 0000000154442BD4h, 00000001C6E41596h
!Lconstant_R4R3:
!dq 00000001751997D0h, 00000000CCAA009Eh
!Lconstant_R5:
!dq 0000000163CD6124h, 0000000000000000h
!Lconstant_mask32:
!dq 00000000FFFFFFFFh, 0000000000000000h
!Lconstant_RUpoly:
!dq 00000001DB710641h, 00000001F7011641h
!CRC_Table:
!dd 0
!dd 077073096h, 0EE0E612Ch, 0990951BAh, 0076DC419h, 0706AF48Fh
!dd 0E963A535h, 09E6495A3h, 00EDB8832h, 079DCB8A4h, 0E0D5E91Eh
!dd 097D2D988h, 009B64C2Bh, 07EB17CBDh, 0E7B82D07h, 090BF1D91h
!dd 01DB71064h, 06AB020F2h, 0F3B97148h, 084BE41DEh, 01ADAD47Dh
!dd 06DDDE4EBh, 0F4D4B551h, 083D385C7h, 0136C9856h, 0646BA8C0h
!dd 0FD62F97Ah, 08A65C9ECh, 014015C4Fh, 063066CD9h, 0FA0F3D63h
!dd 08D080DF5h, 03B6E20C8h, 04C69105Eh, 0D56041E4h, 0A2677172h
!dd 03C03E4D1h, 04B04D447h, 0D20D85FDh, 0A50AB56Bh, 035B5A8FAh
!dd 042B2986Ch, 0DBBBC9D6h, 0ACBCF940h, 032D86CE3h, 045DF5C75h
!dd 0DCD60DCFh, 0ABD13D59h, 026D930ACh, 051DE003Ah, 0C8D75180h
!dd 0BFD06116h, 021B4F4B5h, 056B3C423h, 0CFBA9599h, 0B8BDA50Fh
!dd 02802B89Eh, 05F058808h, 0C60CD9B2h, 0B10BE924h, 02F6F7C87h
!dd 058684C11h, 0C1611DABh, 0B6662D3Dh, 076DC4190h, 001DB7106h
!dd 098D220BCh, 0EFD5102Ah, 071B18589h, 006B6B51Fh, 09FBFE4A5h
!dd 0E8B8D433h, 07807C9A2h, 00F00F934h, 09609A88Eh, 0E10E9818h
!dd 07F6A0DBBh, 0086D3D2Dh, 091646C97h, 0E6635C01h, 06B6B51F4h
!dd 01C6C6162h, 0856530D8h, 0F262004Eh, 06C0695EDh, 01B01A57Bh
!dd 08208F4C1h, 0F50FC457h, 065B0D9C6h, 012B7E950h, 08BBEB8EAh
!dd 0FCB9887Ch, 062DD1DDFh, 015DA2D49h, 08CD37CF3h, 0FBD44C65h
!dd 04DB26158h, 03AB551CEh, 0A3BC0074h, 0D4BB30E2h, 04ADFA541h
!dd 03DD895D7h, 0A4D1C46Dh, 0D3D6F4FBh, 04369E96Ah, 0346ED9FCh
!dd 0AD678846h, 0DA60B8D0h, 044042D73h, 033031DE5h, 0AA0A4C5Fh
!dd 0DD0D7CC9h, 05005713Ch, 0270241AAh, 0BE0B1010h, 0C90C2086h
!dd 05768B525h, 0206F85B3h, 0B966D409h, 0CE61E49Fh, 05EDEF90Eh
!dd 029D9C998h, 0B0D09822h, 0C7D7A8B4h, 059B33D17h, 02EB40D81h
!dd 0B7BD5C3Bh, 0C0BA6CADh, 0EDB88320h, 09ABFB3B6h, 003B6E20Ch
!dd 074B1D29Ah, 0EAD54739h, 09DD277AFh, 004DB2615h, 073DC1683h
!dd 0E3630B12h, 094643B84h, 00D6D6A3Eh, 07A6A5AA8h, 0E40ECF0Bh
!dd 09309FF9Dh, 00A00AE27h, 07D079EB1h, 0F00F9344h, 08708A3D2h
!dd 01E01F268h, 06906C2FEh, 0F762575Dh, 0806567CBh, 0196C3671h
!dd 06E6B06E7h, 0FED41B76h, 089D32BE0h, 010DA7A5Ah, 067DD4ACCh
!dd 0F9B9DF6Fh, 08EBEEFF9h, 017B7BE43h, 060B08ED5h, 0D6D6A3E8h
!dd 0A1D1937Eh, 038D8C2C4h, 04FDFF252h, 0D1BB67F1h, 0A6BC5767h
!dd 03FB506DDh, 048B2364Bh, 0D80D2BDAh, 0AF0A1B4Ch, 036034AF6h
!dd 041047A60h, 0DF60EFC3h, 0A867DF55h, 0316E8EEFh, 04669BE79h
!dd 0CB61B38Ch, 0BC66831Ah, 0256FD2A0h, 05268E236h, 0CC0C7795h
!dd 0BB0B4703h, 0220216B9h, 05505262Fh, 0C5BA3BBEh, 0B2BD0B28h
!dd 02BB45A92h, 05CB36A04h, 0C2D7FFA7h, 0B5D0CF31h, 02CD99E8Bh
!dd 05BDEAE1Dh, 09B64C2B0h, 0EC63F226h, 0756AA39Ch, 0026D930Ah
!dd 09C0906A9h, 0EB0E363Fh, 072076785h, 005005713h, 095BF4A82h
!dd 0E2B87A14h, 07BB12BAEh, 00CB61B38h, 092D28E9Bh, 0E5D5BE0Dh
!dd 07CDCEFB7h, 00BDBDF21h, 086D3D2D4h, 0F1D4E242h, 068DDB3F8h
!dd 01FDA836Eh, 081BE16CDh, 0F6B9265Bh, 06FB077E1h, 018B74777h
!dd 088085AE6h, 0FF0F6A70h, 066063BCAh, 011010B5Ch, 08F659EFFh
!dd 0F862AE69h, 0616BFFD3h, 0166CCF45h, 0A00AE278h, 0D70DD2EEh
!dd 04E048354h, 03903B3C2h, 0A7672661h, 0D06016F7h, 04969474Dh
!dd 03E6E77DBh, 0AED16A4Ah, 0D9D65ADCh, 040DF0B66h, 037D83BF0h
!dd 0A9BCAE53h, 0DEBB9EC5h, 047B2CF7Fh, 030B5FFE9h, 0BDBDF21Ch
!dd 0CABAC28Ah, 053B39330h, 024B4A3A6h, 0BAD03605h, 0CDD70693h
!dd 054DE5729h, 023D967BFh, 0B3667A2Eh, 0C4614AB8h, 05D681B02h
!dd 02A6F2B94h, 0B40BBE37h, 0C30C8EA1h, 05A05DF1Bh, 02D02EF8Dh
EndProcedure
Procedure.i FileCrc32(Filename.s)
Protected Anzahl.i, Crc32.i = 0, hFile.i = ReadFile(#PB_Any, Filename, #PB_File_SharedRead | #PB_File_SharedWrite)
If hFile
Protected *buffer = AllocateMemory($FFFF + 16) ;muss Alignment 16 sein!
BufferA = *buffer
If BufferA & $0F
BufferA = *buffer + 16 - (BufferA & $0F)
EndIf
If BufferA
While Not Eof(hFile)
Anzahl = ReadData(hFile, BufferA, $FFFF)
Crc32 = crc32_cl(BufferA, Anzahl, Crc32)
Wend
FreeMemory(*buffer)
EndIf
CloseFile(hFile)
EndIf
ProcedureReturn Crc32
EndProcedure
Helle
-
- Beiträge: 56
- Registriert: 12.11.2015 17:41
Re: Schnelles CRC32 mit PCLMULQDQ
Ich versteh nur asm ( synonym für ich versteh nur bahnhof )
Re: Schnelles CRC32 mit PCLMULQDQ
Perfekt, danke Helle
PureBasic 5.46 LTS (Windows x86/x64) | windows 10 x64 Oktober failure
Re: Schnelles CRC32 mit PCLMULQDQ
Hallo,
Ich habe eine 4.026.400.768 Bytes grosse Datei da kommt bei x86 $FFFFFFFF heraus?
Selbe Datei mit x64 ist OK.
Nehme ich eine andere Datei mit 5.291.225.668 Bytes geht x86 und x64 ohne Probleme.
Bin ich der einzige bei dem das so ist?
Gruß Rene
Ich habe eine 4.026.400.768 Bytes grosse Datei da kommt bei x86 $FFFFFFFF heraus?
Selbe Datei mit x64 ist OK.
Nehme ich eine andere Datei mit 5.291.225.668 Bytes geht x86 und x64 ohne Probleme.
Bin ich der einzige bei dem das so ist?
Gruß Rene
Skylake QuadCore i7 6700K @4400MHz, MSI Z170A Gaming M5, 64 GB DDR4 @ 2133MHz, B: Ramdisk 32GB, C: Raid0 SATA SSD 1TB, D: Raid0 M2 SSD 1TB, E: Raid0 HDD 8TB, 28" 4K @ RTX2080, Win10 X64
Re: Schnelles CRC32 mit PCLMULQDQ
Anbei mal der Code mit dem ich Teste. x64 geht immer, x86 nicht immer.
Gruß Rene
Code: Alles auswählen
EnableExplicit
UseCRC32Fingerprint()
Declare.l CRC32_CL(Mem, Laenge, Crc32)
RandomSeed(ElapsedMilliseconds())
Define *buffer = AllocateMemory($FFFF + 16) ;muss Alignment 16 sein!
Define *bufferA = *buffer
If *bufferA & $0F
*bufferA = *buffer + 16 - (*bufferA & $0F)
EndIf
If *bufferA
Define Loop.i
For Loop = 1 To 1000
Define Crc32.i = 0
Define Anzahl.i = Random($FFFF)
RandomData(*bufferA, Anzahl)
Crc32 = CRC32_CL(*bufferA, Anzahl, Crc32)
Debug UCase(RSet(Fingerprint(*bufferA, Anzahl, #PB_Cipher_CRC32), 8, "0")) + " " + UCase(RSet(Hex(Crc32), 8, "0"))
Next Loop
FreeMemory(*buffer)
EndIf
End
Procedure.l CRC32_CL(Mem, Laenge, Crc32)
CompilerIf #PB_Compiler_Processor=#PB_Processor_x64
!MOV r9,[p.v_Laenge]
!OR r9,r9 ;erstmal Test, ob Länge = 0
!JNZ Laenge_OK ;nicht 0
!MOV rax,r9
ProcedureReturn ;Rückgabewert = 0 für Länge = 0
!Laenge_OK:
;Test auf PCLMULQDQ
!MOV eax,1
!CPUID
!MOV eax,[p.v_Crc32] ;liest vom Stack, muss nicht rax sein
!NOT eax ;vlt. der einfachste Weg
;-----
!TEST ecx,2
!JNZ CL_OK ;kann losgehen! Auskommentieren für Test ohne PCLMULQDQ
!LEA r10,[CRC_Table] ;die CPU bringts nicht, also konventionell
!MOV r8,[p.v_Mem]
!@@:
!MOVZX rcx,byte[r8]
!XOR cl,al
!SHR rax,8
!XOR eax,dword[r10+rcx*4]
!INC r8
!DEC r9 ;Länge
!JNZ @b
!NOT eax ;wegen Polynomial Reversed
ProcedureReturn
!CL_OK:
!AND r9,0FFFFFFFFFFFFFFC0h ;Länge < 40?
!JZ less_64 ;ja, konventionell weiter
!MOVD xmm0,eax ;eax = Initialisierungswert für CRC32
!MOV r8,[p.v_Mem]
!MOVDQA xmm1,[r8]
!MOVDQA xmm2,[r8+10h]
!MOVDQA xmm3,[r8+20h]
!MOVDQA xmm4,[r8+30h]
!PXOR xmm1,xmm0
!SUB r9,40h
!ADD r8,40h
!MOVDQA xmm0,[Lconstant_R2R1]
!loop_64:
!PREFETCHNTA [r8+0c0h] ;Cache "vorfüllen"
!MOVDQA xmm5,xmm1
!MOVDQA xmm6,xmm2
!MOVDQA xmm7,xmm3
!MOVDQA xmm8,xmm4
!PCLMULQDQ xmm1,xmm0,00h
!PCLMULQDQ xmm2,xmm0,00h
!PCLMULQDQ xmm3,xmm0,00h
!PCLMULQDQ xmm4,xmm0,00h
!PCLMULQDQ xmm5,xmm0,11h
!PCLMULQDQ xmm6,xmm0,11h
!PCLMULQDQ xmm7,xmm0,11h
!PCLMULQDQ xmm8,xmm0,11h
!PXOR xmm1,xmm5
!PXOR xmm2,xmm6
!PXOR xmm3,xmm7
!PXOR xmm4,xmm8
!PXOR xmm1,[r8]
!PXOR xmm2,[r8+10h]
!PXOR xmm3,[r8+20h]
!PXOR xmm4,[r8+30h]
!SUB r9,40h
!ADD r8,40h
!CMP r9,40h
!JGE loop_64
!MOVDQA xmm0,[Lconstant_R4R3]
!PREFETCHNTA [r8]
!MOVDQA xmm5,xmm1
!PCLMULQDQ xmm1,xmm0,00h
!PCLMULQDQ xmm5,xmm0,11h
!PXOR xmm1,xmm5
!PXOR xmm1,xmm2
!MOVDQA xmm5,xmm1
!PCLMULQDQ xmm1,xmm0,00h
!PCLMULQDQ xmm5,xmm0,11h
!PXOR xmm1,xmm5
!PXOR xmm1,xmm3
!MOVDQA xmm5,xmm1
!PCLMULQDQ xmm1,xmm0,00h
!PCLMULQDQ xmm5,xmm0,11h
!PXOR xmm1,xmm5
!PXOR xmm1,xmm4
!PCLMULQDQ xmm0,xmm1,01h
!PSRLDQ xmm1,08h
!PXOR xmm1,xmm0
!MOVDQA xmm2,xmm1
!MOVDQA xmm0,[Lconstant_R5]
!MOVDQA xmm3,[Lconstant_mask32]
!PSRLDQ xmm2,04h
!PAND xmm1,xmm3
!PCLMULQDQ xmm1,xmm0,00h
!PXOR xmm1,xmm2
!MOVDQA xmm0,[Lconstant_RUpoly]
!MOVDQA xmm2,xmm1
!PAND xmm1,xmm3
!PCLMULQDQ xmm1,xmm0,10h
!PAND xmm1,xmm3
!PCLMULQDQ xmm1,xmm0,00h
!PXOR xmm1,xmm2
!PEXTRD eax,xmm1,01h ;eax ist CRC32 (bis hierher)
!less_64: ;Rest (max.63 Bytes)
!MOV r8,[p.v_Mem]
!MOV r9,[p.v_Laenge]
!ADD r8,r9
!AND r9,3fh ;möglicher Rest
!JZ NoRest ;kein Rest
!LEA r10,[CRC_Table] ;die restlichen Bytes mit Tabelle
!SUB r8,r9
!@@:
!MOVZX rcx,byte[r8]
!XOR cl,al
!SHR rax,8
!XOR eax,dword[r10+rcx*4]
!INC r8
!DEC r9
!JNZ @b
!NoRest:
!NOT eax ;wegen Polynomial Reversed
ProcedureReturn
CompilerElse
!MOV eax,[p.v_Laenge]
!OR eax,eax ;erstmal Test, ob Länge = 0
!JNZ Laenge_OK ;nicht 0
ProcedureReturn ;Rückgabewert = 0 für Länge = 0
!Laenge_OK:
;Test auf PCLMULQDQ
!MOV eax,1
!CPUID
!MOV eax,[p.v_Crc32] ;Initialisierungswert für CRC32
!NOT eax
!TEST ecx,2
!JNZ CL_OK ;kann losgehen! Auskommentieren für Test ohne PCLMULQDQ
!MOV edx,[p.v_Laenge] ;die CPU bringts nicht, also konventionell
!MOV ecx,[p.v_Mem]
!PUSH esi
!MOV esi,ecx
!PUSH ebx
!LEA ebx,[CRC_Table]
!@@:
!MOVZX ecx,byte[esi] ;Mem
!XOR cl,al
!SHR eax,8
!XOR eax,dword[ebx+ecx*4] ;Table
!INC esi
!DEC edx ;Länge
!JNZ @b
!POP esi
!POP ebx
!NOT eax ;wegen Polynomial Reversed
ProcedureReturn
!CL_OK:
!MOV edx,[p.v_Laenge]
!AND edx,0FFFFFFC0h ;Länge < 40h?
!JZ less_64 ;ja, konventionell weiter
!MOVD xmm5,eax ;eax = Initialisierungswert für CRC32
!MOV ecx,[p.v_Mem]
!MOVDQA xmm0,[ecx]
!MOVDQA xmm1,[ecx+10h]
!MOVDQA xmm2,[ecx+20h]
!MOVDQA xmm3,[ecx+30h]
!PXOR xmm0,xmm5
!SUB edx,40h
!ADD ecx,40h
!loop_64:
!PREFETCHNTA [ecx+0c0h] ;Cache "vorfüllen"
!MOVDQA xmm4,xmm0
!MOVDQA xmm5,xmm1
!MOVDQA xmm6,xmm2
!MOVDQA xmm7,xmm3
!PCLMULQDQ xmm0,[Lconstant_R2R1],00h
!PCLMULQDQ xmm1,[Lconstant_R2R1],00h
!PCLMULQDQ xmm2,[Lconstant_R2R1],00h
!PCLMULQDQ xmm3,[Lconstant_R2R1],00h
!PCLMULQDQ xmm4,[Lconstant_R2R1],11h
!PCLMULQDQ xmm5,[Lconstant_R2R1],11h
!PCLMULQDQ xmm6,[Lconstant_R2R1],11h
!PCLMULQDQ xmm7,[Lconstant_R2R1],11h
!PXOR xmm0,xmm4
!PXOR xmm1,xmm5
!PXOR xmm2,xmm6
!PXOR xmm3,xmm7
!PXOR xmm0,[ecx]
!PXOR xmm1,[ecx+10h]
!PXOR xmm2,[ecx+20h]
!PXOR xmm3,[ecx+30h]
!SUB edx,40h
!ADD ecx,40h
!CMP edx,40h
!JGE loop_64
!MOVDQA xmm6,[Lconstant_R4R3]
!PREFETCHNTA [ecx]
!MOVDQA xmm4,xmm0
!PCLMULQDQ xmm0,xmm6,00h
!PCLMULQDQ xmm4,xmm6,11h
!PXOR xmm0,xmm4
!PXOR xmm0,xmm1
!MOVDQA xmm4,xmm0
!PCLMULQDQ xmm0,xmm6,00h
!PCLMULQDQ xmm4,xmm6,11h
!PXOR xmm0,xmm4
!PXOR xmm0,xmm2
!MOVDQA xmm4,xmm0
!PCLMULQDQ xmm0,xmm6,00h
!PCLMULQDQ xmm4,xmm6,11h
!PXOR xmm0,xmm4
!PXOR xmm0,xmm3
!PCLMULQDQ xmm6,xmm0,01h
!PSRLDQ xmm0,08h
!PXOR xmm0,xmm6
!MOVDQA xmm1,xmm0
!MOVDQA xmm6,[Lconstant_R5]
!MOVDQA xmm2,[Lconstant_mask32]
!PSRLDQ xmm1,04h
!PAND xmm0,xmm2
!PCLMULQDQ xmm0,xmm6,00h
!PXOR xmm0,xmm1
!MOVDQA xmm6,[Lconstant_RUpoly]
!MOVDQA xmm1,xmm0
!PAND xmm0,xmm2
!PCLMULQDQ xmm0,xmm6,10h
!PAND xmm0,xmm2
!PCLMULQDQ xmm0,xmm6,00h
!PXOR xmm0,xmm1
!less_64: ;Rest (max.63 Bytes)
!LEA ecx,[CRC_Table] ;die restlichen Bytes mit Tabelle
!MOV eax,[p.v_Mem]
!MOV edx,[p.v_Laenge]
!PUSH ebx
!MOV ebx,ecx
!PUSH esi
!MOV esi,eax
!PEXTRD eax,xmm0,01h ;eax ist CRC32 (bis hierher)
!ADD esi,edx
!AND edx,3fh ;möglicher Rest
!JZ NoRest ;kein Rest
!SUB esi,edx
!@@:
!MOVZX ecx,byte[esi]
!XOR cl,al
!SHR eax,8
!XOR eax,dword[ebx+ecx*4]
!INC esi
!DEC edx
!JNZ @b
!NoRest:
!POP esi
!POP ebx
!NOT eax ;wegen Polynomial Reversed
ProcedureReturn
CompilerEndIf
;Konstanten
!Align 16
!Lconstant_R2R1:
!dq 0000000154442BD4h, 00000001C6E41596h
!Lconstant_R4R3:
!dq 00000001751997D0h, 00000000CCAA009Eh
!Lconstant_R5:
!dq 0000000163CD6124h, 0000000000000000h
!Lconstant_mask32:
!dq 00000000FFFFFFFFh, 0000000000000000h
!Lconstant_RUpoly:
!dq 00000001DB710641h, 00000001F7011641h
!CRC_Table:
!dd 0
!dd 077073096h, 0EE0E612Ch, 0990951BAh, 0076DC419h, 0706AF48Fh
!dd 0E963A535h, 09E6495A3h, 00EDB8832h, 079DCB8A4h, 0E0D5E91Eh
!dd 097D2D988h, 009B64C2Bh, 07EB17CBDh, 0E7B82D07h, 090BF1D91h
!dd 01DB71064h, 06AB020F2h, 0F3B97148h, 084BE41DEh, 01ADAD47Dh
!dd 06DDDE4EBh, 0F4D4B551h, 083D385C7h, 0136C9856h, 0646BA8C0h
!dd 0FD62F97Ah, 08A65C9ECh, 014015C4Fh, 063066CD9h, 0FA0F3D63h
!dd 08D080DF5h, 03B6E20C8h, 04C69105Eh, 0D56041E4h, 0A2677172h
!dd 03C03E4D1h, 04B04D447h, 0D20D85FDh, 0A50AB56Bh, 035B5A8FAh
!dd 042B2986Ch, 0DBBBC9D6h, 0ACBCF940h, 032D86CE3h, 045DF5C75h
!dd 0DCD60DCFh, 0ABD13D59h, 026D930ACh, 051DE003Ah, 0C8D75180h
!dd 0BFD06116h, 021B4F4B5h, 056B3C423h, 0CFBA9599h, 0B8BDA50Fh
!dd 02802B89Eh, 05F058808h, 0C60CD9B2h, 0B10BE924h, 02F6F7C87h
!dd 058684C11h, 0C1611DABh, 0B6662D3Dh, 076DC4190h, 001DB7106h
!dd 098D220BCh, 0EFD5102Ah, 071B18589h, 006B6B51Fh, 09FBFE4A5h
!dd 0E8B8D433h, 07807C9A2h, 00F00F934h, 09609A88Eh, 0E10E9818h
!dd 07F6A0DBBh, 0086D3D2Dh, 091646C97h, 0E6635C01h, 06B6B51F4h
!dd 01C6C6162h, 0856530D8h, 0F262004Eh, 06C0695EDh, 01B01A57Bh
!dd 08208F4C1h, 0F50FC457h, 065B0D9C6h, 012B7E950h, 08BBEB8EAh
!dd 0FCB9887Ch, 062DD1DDFh, 015DA2D49h, 08CD37CF3h, 0FBD44C65h
!dd 04DB26158h, 03AB551CEh, 0A3BC0074h, 0D4BB30E2h, 04ADFA541h
!dd 03DD895D7h, 0A4D1C46Dh, 0D3D6F4FBh, 04369E96Ah, 0346ED9FCh
!dd 0AD678846h, 0DA60B8D0h, 044042D73h, 033031DE5h, 0AA0A4C5Fh
!dd 0DD0D7CC9h, 05005713Ch, 0270241AAh, 0BE0B1010h, 0C90C2086h
!dd 05768B525h, 0206F85B3h, 0B966D409h, 0CE61E49Fh, 05EDEF90Eh
!dd 029D9C998h, 0B0D09822h, 0C7D7A8B4h, 059B33D17h, 02EB40D81h
!dd 0B7BD5C3Bh, 0C0BA6CADh, 0EDB88320h, 09ABFB3B6h, 003B6E20Ch
!dd 074B1D29Ah, 0EAD54739h, 09DD277AFh, 004DB2615h, 073DC1683h
!dd 0E3630B12h, 094643B84h, 00D6D6A3Eh, 07A6A5AA8h, 0E40ECF0Bh
!dd 09309FF9Dh, 00A00AE27h, 07D079EB1h, 0F00F9344h, 08708A3D2h
!dd 01E01F268h, 06906C2FEh, 0F762575Dh, 0806567CBh, 0196C3671h
!dd 06E6B06E7h, 0FED41B76h, 089D32BE0h, 010DA7A5Ah, 067DD4ACCh
!dd 0F9B9DF6Fh, 08EBEEFF9h, 017B7BE43h, 060B08ED5h, 0D6D6A3E8h
!dd 0A1D1937Eh, 038D8C2C4h, 04FDFF252h, 0D1BB67F1h, 0A6BC5767h
!dd 03FB506DDh, 048B2364Bh, 0D80D2BDAh, 0AF0A1B4Ch, 036034AF6h
!dd 041047A60h, 0DF60EFC3h, 0A867DF55h, 0316E8EEFh, 04669BE79h
!dd 0CB61B38Ch, 0BC66831Ah, 0256FD2A0h, 05268E236h, 0CC0C7795h
!dd 0BB0B4703h, 0220216B9h, 05505262Fh, 0C5BA3BBEh, 0B2BD0B28h
!dd 02BB45A92h, 05CB36A04h, 0C2D7FFA7h, 0B5D0CF31h, 02CD99E8Bh
!dd 05BDEAE1Dh, 09B64C2B0h, 0EC63F226h, 0756AA39Ch, 0026D930Ah
!dd 09C0906A9h, 0EB0E363Fh, 072076785h, 005005713h, 095BF4A82h
!dd 0E2B87A14h, 07BB12BAEh, 00CB61B38h, 092D28E9Bh, 0E5D5BE0Dh
!dd 07CDCEFB7h, 00BDBDF21h, 086D3D2D4h, 0F1D4E242h, 068DDB3F8h
!dd 01FDA836Eh, 081BE16CDh, 0F6B9265Bh, 06FB077E1h, 018B74777h
!dd 088085AE6h, 0FF0F6A70h, 066063BCAh, 011010B5Ch, 08F659EFFh
!dd 0F862AE69h, 0616BFFD3h, 0166CCF45h, 0A00AE278h, 0D70DD2EEh
!dd 04E048354h, 03903B3C2h, 0A7672661h, 0D06016F7h, 04969474Dh
!dd 03E6E77DBh, 0AED16A4Ah, 0D9D65ADCh, 040DF0B66h, 037D83BF0h
!dd 0A9BCAE53h, 0DEBB9EC5h, 047B2CF7Fh, 030B5FFE9h, 0BDBDF21Ch
!dd 0CABAC28Ah, 053B39330h, 024B4A3A6h, 0BAD03605h, 0CDD70693h
!dd 054DE5729h, 023D967BFh, 0B3667A2Eh, 0C4614AB8h, 05D681B02h
!dd 02A6F2B94h, 0B40BBE37h, 0C30C8EA1h, 05A05DF1Bh, 02D02EF8Dh
EndProcedure
Skylake QuadCore i7 6700K @4400MHz, MSI Z170A Gaming M5, 64 GB DDR4 @ 2133MHz, B: Ramdisk 32GB, C: Raid0 SATA SSD 1TB, D: Raid0 M2 SSD 1TB, E: Raid0 HDD 8TB, 28" 4K @ RTX2080, Win10 X64
Re: Schnelles CRC32 mit PCLMULQDQ
Mit
ist man bei Debug 32-Bit immer auf der sicheren Seite !
Also bitte die Ausgabe ändern!
Gruß
Helle
Ja, ja, 32-Bit...
Code: Alles auswählen
UCase(RSet(Hex(Crc32 & $FFFFFFFF), 8, "0"))
Also bitte die Ausgabe ändern!
Gruß
Helle
Ja, ja, 32-Bit...
Re: Schnelles CRC32 mit PCLMULQDQ
Thx, da muss man mal drauf kommen.
Skylake QuadCore i7 6700K @4400MHz, MSI Z170A Gaming M5, 64 GB DDR4 @ 2133MHz, B: Ramdisk 32GB, C: Raid0 SATA SSD 1TB, D: Raid0 M2 SSD 1TB, E: Raid0 HDD 8TB, 28" 4K @ RTX2080, Win10 X64