--- a/CRC32Stream.st Sun Mar 17 18:18:27 2019 +0100
+++ b/CRC32Stream.st Sun Mar 17 18:35:19 2019 +0100
@@ -31,32 +31,43 @@
!CRC32Stream primitiveDefinitions!
%{
+#if defined(__x86__) || defined(__x86_64__)
-/*
- * includes, defines, structure definitions
- * and typedefs come here.
- */
-#ifdef __LP64__
-inline uint64_t _mm_crc32_u64(uint64_t crc, uint64_t value) {
+# if defined(__GNUC__)
+# pragma GCC push_options
+# pragma GCC target ("arch=core-avx2")
+# define HAS_CRC
+# endif
+
+# if defined(__clang__)
+# define HAS_CRC
+# endif
+
+#ifdef HAS_CRC
+
+# ifdef __LP64__
+static inline uint64_t __crc32_u64(uint64_t crc, uint64_t value) {
asm("crc32q %[value], %[crc]\n" : [crc] "+r" (crc) : [value] "rm" (value));
return crc;
}
-#endif
+# endif
-inline uint32_t _mm_crc32_u32(uint32_t crc, uint32_t value) {
+static inline uint32_t __crc32_u32(uint32_t crc, uint32_t value) {
asm("crc32l %[value], %[crc]\n" : [crc] "+r" (crc) : [value] "rm" (value));
return crc;
}
-inline uint32_t _mm_crc32_u16(uint32_t crc, uint16_t value) {
+static inline uint32_t __crc32_u16(uint32_t crc, uint16_t value) {
asm("crc32w %[value], %[crc]\n" : [crc] "+r" (crc) : [value] "rm" (value));
return crc;
}
-inline uint32_t _mm_crc32_u8(uint32_t crc, uint8_t value) {
+static inline uint32_t __crc32_u8(uint32_t crc, uint8_t value) {
asm("crc32b %[value], %[crc]\n" : [crc] "+r" (crc) : [value] "rm" (value));
return crc;
}
+# endif // HAS_CRC
+#endif // x86 or x86_64
%}
! !
@@ -85,37 +96,37 @@
Standard CRC method as defined by ISO 3309 [ISO-3309] or ITU-T V.42 [ITU-T-V42].
The default CRC polynomial employed is
- x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
- (or 16r04C11DB7)
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
+ (or 16r04C11DB7)
- You can also create an instace performing the Castagnoli CRC-32C
+ You can also create an instace performing the Castagnoli CRC-32C
(used in iSCSI & SCTP [RFC3720], G.hn payload, SSE4.2):
- self newCrc32c
+ self newCrc32c
- poly: 16r1edc6f41
- = x32 + x28 + x27 + x26 + x25 + x23 + x22 + x20 + x19 + x18 + x14 + x13 + x11 + x10 + x9 + x8 + x6 + 1
+ poly: 16r1edc6f41
+ = x32 + x28 + x27 + x26 + x25 + x23 + x22 + x20 + x19 + x18 + x14 + x13 + x11 + x10 + x9 + x8 + x6 + 1
- Notice that this CRC is also used with PNG images;
+ Notice that this CRC is also used with PNG images;
therefore, its performance directly affects png image processing (png write speed).
throughput:
- 235 Mb/s on MacBook Pro (2.6Ghz I7)
- 157 Mb/s on a 2.5Ghz 64X2 Athlon 4800+ (64bit)
- 150 Mb/s on 2Ghz Duo
+ 235 Mb/s on MacBook Pro (2.6Ghz I7)
+ 157 Mb/s on a 2.5Ghz 64X2 Athlon 4800+ (64bit)
+ 150 Mb/s on 2Ghz Duo
new:
- 500 Mb/s for castagnoli on MacBook Pro (2.6Ghz I7)
+ 500 Mb/s for castagnoli on MacBook Pro (2.6Ghz I7)
[author:]
- Stefan Vogel (stefan@zwerg)
+ Stefan Vogel (stefan@zwerg)
[instance variables:]
[class variables:]
[see also:]
- SHA1Stream
- MD5Stream
+ SHA1Stream
+ MD5Stream
"
!
@@ -124,261 +135,111 @@
"
expect 60C1D0A0
- [exBegin]
+ [exBegin]
self information:(CRC32Stream hashValueOf:'resume') hexPrintString
- [exEnd]
+ [exEnd]
expect 16r60C1D0A0
- [exBegin]
+ [exBegin]
self information:(CRC32Stream new
- nextPut:$r;
- nextPut:$e;
- nextPut:$s;
- nextPut:$u;
- nextPut:$m;
- nextPut:$e;
- hashValue) hexPrintString
- [exEnd]
+ nextPut:$r;
+ nextPut:$e;
+ nextPut:$s;
+ nextPut:$u;
+ nextPut:$m;
+ nextPut:$e;
+ hashValue) hexPrintString
+ [exEnd]
expect 16r70E46888:
- [exBegin]
+ [exBegin]
self information:(CRC32Stream hashValueOf:#[1 2 3 4 5 6 7]) hexPrintString
- [exEnd]
+ [exEnd]
expect 16r8CD04C73:
- [exBegin]
+ [exBegin]
self information:((CRC32Stream hashValueOf:#[16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF
- 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF
- 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF
- 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF]) hexPrintString)
- [exEnd]
+ 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF
+ 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF
+ 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF 16rFF]) hexPrintString)
+ [exEnd]
timing throughput:
- 230Mb/s (on MacBook Pro 2012 / 2.6Ghz I7)
- [exBegin]
+ 230Mb/s (on MacBook Pro 2012 / 2.6Ghz I7)
+ [exBegin]
|hashStream n t|
hashStream := CRC32Stream new.
n := 2000000.
t := Time millisecondsToRun:[
- n timesRepeat:[
- hashStream nextPutAll:'12345678901234567890123456789012345678901234567890'.
- ].
- ].
+ n timesRepeat:[
+ hashStream nextPutAll:'12345678901234567890123456789012345678901234567890'.
+ ].
+ ].
t := (t / 1000) asFloat.
Transcript show:'crc32:'; showCR: hashStream hashValue hexPrintString.
Transcript show:t; show:' seconds for '; show:(50*n/1024) asFloat; showCR:' Kb'.
Transcript show:(n*50/1024 / t); showCR:' Kb/s'
- [exEnd]
+ [exEnd]
- 500Mb/s (on MacBook Pro 2012 / 2.6Ghz I7)
- [exBegin]
+ 500Mb/s (on MacBook Pro 2012 / 2.6Ghz I7)
+ [exBegin]
|hashStream n t|
hashStream := CRC32Stream newCastagnoli.
- n := 4000000.
+ n := 2000000.
t := Time millisecondsToRun:[
- n timesRepeat:[
- hashStream nextPutAll:'12345678901234567890123456789012345678901234567890'.
- ].
- ].
+ n timesRepeat:[
+ hashStream nextPutAll:'12345678901234567890123456789012345678901234567890'.
+ ].
+ ].
t := (t / 1000) asFloat.
Transcript show:'crc32:'; showCR: hashStream hashValue hexPrintString.
Transcript show:t; show:' seconds for '; show:(50*n/1024) asFloat; showCR:' Kb'.
Transcript show:(n*50/1024 / t); showCR:' Kb/s'
- [exEnd]
+ [exEnd]
test vectors from https://tools.ietf.org/html/rfc3720#page-217:
-
+
expect 0
- [exBegin]
+ [exBegin]
self information:(CRC32Stream newCrc32c hashValueOf:'') hexPrintString
- [exEnd]
+ [exEnd]
expect C1D04330
- [exBegin]
+ [exBegin]
self information:(CRC32Stream newCrc32c hashValueOf:'a') hexPrintString
- [exEnd]
+ [exEnd]
expect E3069283
- [exBegin]
+ [exBegin]
self information:(CRC32Stream newCrc32c hashValueOf:'123456789') hexPrintString
- [exEnd]
+ [exEnd]
expect 8A9136AA
- [exBegin]
+ [exBegin]
self information:(CRC32Stream newCrc32c hashValueOf:(ByteArray new:32 withAll:0)) hexPrintString
- [exEnd]
+ [exEnd]
expect 62a8ab43
- [exBegin]
+ [exBegin]
self information:(CRC32Stream newCrc32c hashValueOf:(ByteArray new:32 withAll:16rFF)) hexPrintString
- [exEnd]
+ [exEnd]
expect 46dd794e
- [exBegin]
+ [exBegin]
self information:(CRC32Stream newCrc32c hashValueOf:(0 to:31) asByteArray) hexPrintString
- [exEnd]
+ [exEnd]
"
! !
!CRC32Stream class methodsFor:'instance creation'!
-castagnoli_nextPutBytes:count from:anObject startingAt:start
- "add the hash of anObject to the computed hash so far.
- This uses an x86 crc instruction,
- and works only with the castagnoli polynom"
-
-%{
-#if defined(__x86__) || defined(__x86_64__)
-# if defined(__clang__) || defined(__GNUC__)
-# pragma GCC push_options
-# pragma GCC target ("arch=core-avx2")
-
- if (__bothSmallInteger(count, start)) {
- int len, offs;
- int objSize;
- unsigned char *extPtr;
-
- len = __intVal(count);
- offs = __intVal(start) - 1;
-
- if (__isExternalBytesLike(anObject)) {
- OBJ sz = __externalBytesSize(anObject);
-
- extPtr = (unsigned char *)__externalBytesAddress(anObject);
- if (__isSmallInteger(sz)) {
- objSize = __intVal(sz);
- } else {
- objSize = 0; /* unknown */
- }
- } else {
- int nInstVars, nInstBytes;
- OBJ oClass = __Class(anObject);
-
- switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
- case BYTEARRAY:
- case WORDARRAY:
- case LONGARRAY:
- case SWORDARRAY:
- case SLONGARRAY:
- case FLOATARRAY:
- case DOUBLEARRAY:
- break;
- default:
- goto bad;
- }
- nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
- nInstBytes = __OBJS2BYTES__(nInstVars);
- // nInstBytes is the number of bytes occupied by pointer instance variables
- // subtract from size and add to byte-pointer
- objSize = __qSize(anObject) - OHDR_SIZE - nInstBytes;
- extPtr = (unsigned char *)__byteArrayVal(anObject)+nInstBytes;
- }
-
- if ((offs >= 0) && (len >= 0) && (objSize >= (len + offs))) {
- unsigned int _crc;
- unsigned int *_crcTable = __integerArrayVal( __INST(crcTable) );
- unsigned char *cp = extPtr+offs;
- unsigned int n = len;
-
- if (__isSmallInteger(__INST(crc))) {
- _crc = (unsigned int) (__intVal( __INST(crc) ));
- } else {
- _crc = __unsignedLongIntVal( __INST(crc) );
- }
-
-#if 0
-# if __POINTER_SIZE__ == 8
- if (((unsigned INT)cp & 7) == 0) {
- // longword aligned
- for ( ; n >= 8 ; n -= 8, cp += 8) {
- unsigned INT lWord;
- unsigned char _idx;
-
- lWord = ((unsigned INT *)cp)[0];
- _idx = (_crc ^ lWord) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- _idx = (_crc ^ (lWord>>8)) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- _idx = (_crc ^ (lWord>>16)) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- _idx = (_crc ^ (lWord>>24)) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
-
- _idx = (_crc ^ (lWord>>32)) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- _idx = (_crc ^ (lWord>>40)) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- _idx = (_crc ^ (lWord>>48)) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- _idx = (_crc ^ (lWord>>56)) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- }
- }
-# endif // __POINTER_SIZE__ == 8
- if (((unsigned INT)cp & 3) == 0) {
- // word aligned
- for ( ; n >= 4 ; n -= 4, cp += 4) {
- unsigned int word;
- unsigned char _idx;
-
- word = ((unsigned int *)cp)[0];
- _idx = (_crc ^ word) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- _idx = (_crc ^ (word>>8)) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- _idx = (_crc ^ (word>>16)) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- _idx = (_crc ^ (word>>24)) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- }
- }
-#endif // 0
- for ( ; n >= 4 ; n -= 4, cp += 4) {
- unsigned char _idx;
-
- _idx = (_crc ^ cp[0]) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- _idx = (_crc ^ cp[1]) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- _idx = (_crc ^ cp[2]) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- _idx = (_crc ^ cp[3]) & 0xFF;
- _crc = _crcTable[_idx] ^ (_crc >> 8);
- }
- while (n-- > 0) {
- unsigned char ch = *cp++;
-
- _crc = __builtin_ia32_crc32qi(_crc, ch);
- }
-
- if ((__POINTER_SIZE__==8) || (_crc <= _MAX_INT)) {
- __INST(crc) = __MKSMALLINT(_crc);
- } else {
- // this code fails with gcc 4.7.2:
- // __INST(crc) = __MKUINT(_crc); __STORESELF(crc);
- OBJ temp = __MKUINT(_crc);
- __INST(crc) = temp; __STORESELF(crc);
- }
-
- RETURN (count);
- }
- }
-bad: ;
-# endif
-#endif
-%}.
- self primitiveFailed
-
- "Created: / 17-03-2019 / 15:36:45 / Claus Gittinger"
-!
-
generatorPolynomMSB:anInteger
"notice, in literature, the generator polynom is usually specified as an MSB number"
-
+
^ self generatorPolynom:(anInteger bitReversed32)
"
self assert:((self generatorPolynom:16r82F63B78)
- nextPut:'123456789';
- hashValue) = 16rE3069283
+ nextPut:'123456789';
+ hashValue) = 16rE3069283
"
"Created: / 16-03-2019 / 20:55:46 / Claus Gittinger"
@@ -386,7 +247,7 @@
generatorPolynomMSB:anInteger initValue:initValueArg
"notice, in literature, the generator polynom is usually specified as an MSB number"
-
+
^ self generatorPolynom:(anInteger bitReversed32) initValue:initValueArg
"Created: / 16-03-2019 / 21:11:31 / Claus Gittinger"
@@ -394,7 +255,7 @@
generatorPolynomMSB:anInteger initValue:initValueArg xorOut:xorOut
"notice, in literature, the generator polynom is usually specified as an MSB number"
-
+
^ self generatorPolynom:(anInteger bitReversed32) initValue:initValueArg xorOut:xorOut
"Created: / 16-03-2019 / 21:21:27 / Claus Gittinger"
@@ -412,11 +273,11 @@
newCCITT
"return an instance of the ITU-T CRC-32
- x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1"
+ x^32+x^26+x^23+x^22+x^16+x^12+x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1"
"/ 16r4C11DB7 bitReversed32 -> 16rEDB88320
- ^ self generatorPolynomMSB:16r4C11DB7
- initValue:16rFFFFFFFF xorOut:16rFFFFFFFF
+ ^ self generatorPolynomMSB:16r4C11DB7
+ initValue:16rFFFFFFFF xorOut:16rFFFFFFFF
"Created: / 16-03-2019 / 23:29:39 / Claus Gittinger"
"Modified: / 17-03-2019 / 14:07:36 / Claus Gittinger"
@@ -424,27 +285,27 @@
newCastagnoli
"return an instance of the Castagnoli CRC-32
- x32 + x28 + x27 + x26 + x25 + x23 + x22 + x20 + x19 + x18 + x14 + x13 + x11 + x10 + x9 + x8 + x6 + 1
+ x32 + x28 + x27 + x26 + x25 + x23 + x22 + x20 + x19 + x18 + x14 + x13 + x11 + x10 + x9 + x8 + x6 + 1
(used in iSCSI & SCTP, G.hn payload, SSE4.2)"
|impl|
-
+
impl := (self canUseFastCRC) ifTrue:[CRC32Stream_Castagnoli] ifFalse:[self].
-
+
"/ 16r1edc6f41 bitReversed32 -> 16r82F63B78
- ^ impl generatorPolynomMSB:16r1edc6f41
- initValue:16rFFFFFFFF xorOut:16rFFFFFFFF
+ ^ impl generatorPolynomMSB:16r1edc6f41
+ initValue:16rFFFFFFFF xorOut:16rFFFFFFFF
"
Castagnoli crc:
self assert:((self newCrc32c)
- nextPut:'123456789';
- hashValue) = 3808858755. '16rE3069283'
+ nextPut:'123456789';
+ hashValue) = 3808858755. '16rE3069283'
default crc:
self assert:((self new)
- nextPut:'123456789';
- hashValue) = 3421780262. '16rCBF43926'
+ nextPut:'123456789';
+ hashValue) = 3421780262. '16rCBF43926'
"
"Created: / 17-03-2019 / 14:33:54 / Claus Gittinger"
@@ -459,13 +320,13 @@
"
Castagnoli crc:
self assert:((self newCrc32c)
- nextPut:'123456789';
- hashValue) = 3808858755. '16rE3069283'
+ nextPut:'123456789';
+ hashValue) = 3808858755. '16rE3069283'
default crc:
self assert:((self new)
- nextPut:'123456789';
- hashValue) = 3421780262. '16rCBF43926'
+ nextPut:'123456789';
+ hashValue) = 3421780262. '16rCBF43926'
"
"Modified (comment): / 17-05-2012 / 12:48:53 / cg"
@@ -476,11 +337,13 @@
canUseFastCRC
%{ /* NOCONTEXT */
-#if defined(__x86__) || defined(__x86_64__)
-# if defined(__clang__) || defined(__GNUC__)
+#if defined(HAS_CRC)
+# if defined(__x86__) || defined(__x86_64__)
+# if defined(__clang__) || defined(__GNUC__)
extern unsigned char __cpu_hasSSE4_2;
-
+
RETURN (__cpu_hasSSE4_2 ? true : false);
+# endif
# endif
#endif
%}.
@@ -500,8 +363,8 @@
set start and xorOut to 16rFFFFFFFF.
Note: you have to set the bit-reversed value, so the LSB must be first"
- self generatorPolynom:anLSBInteger
- initValue:16rFFFFFFFF xorOut:16rFFFFFFFF.
+ self generatorPolynom:anLSBInteger
+ initValue:16rFFFFFFFF xorOut:16rFFFFFFFF.
"Modified: / 16-03-2019 / 21:23:25 / Claus Gittinger"
"Modified (format): / 17-03-2019 / 14:02:38 / Claus Gittinger"
@@ -512,8 +375,8 @@
set start to initValueArg and xorOut to 16rFFFFFFFF.
Note: you have to set the bit-reversed value, so the LSB must be first"
- self generatorPolynom:anLSBInteger
- initValue:initValueArg xorOut:16rFFFFFFFF
+ self generatorPolynom:anLSBInteger
+ initValue:initValueArg xorOut:16rFFFFFFFF
"Created: / 16-03-2019 / 21:06:16 / Claus Gittinger"
"Modified (format): / 17-03-2019 / 14:02:31 / Claus Gittinger"
@@ -526,7 +389,7 @@
redefined to use the CPU's CRC instruction
[author:]
- Claus Gittinger
+ Claus Gittinger
"
! !
@@ -538,142 +401,117 @@
and works only for the castagnoli polynom"
%{ /* NOCONTEXT */
-#if defined(__x86__) || defined(__x86_64__)
-# if defined(__clang__) || defined(__GNUC__)
-
- int len, offs;
-
- // fetch here, but catch non-SmallInt error later
- len = __intVal(count);
- offs = __intVal(start) - 1;
+#if defined(HAS_CRC)
if (__bothSmallInteger(count, start)) {
- int objSize;
- unsigned char *extPtr;
+ int len, offs;
+ int objSize;
+ unsigned char *extPtr;
- if (__isExternalBytesLike(anObject)) {
- OBJ sz = __externalBytesSize(anObject);
+ len = __intVal(count);
+ offs = __intVal(start) - 1;
+
+ if (__isExternalBytesLike(anObject)) {
+ OBJ sz = __externalBytesSize(anObject);
- extPtr = (unsigned char *)__externalBytesAddress(anObject);
- if (__isSmallInteger(sz)) {
- objSize = __intVal(sz);
- } else {
- objSize = 0; /* unknown */
- }
- } else {
- int nInstVars, nInstBytes;
- OBJ oClass = __Class(anObject);
+ extPtr = (unsigned char *)__externalBytesAddress(anObject);
+ if (__isSmallInteger(sz)) {
+ objSize = __intVal(sz);
+ } else {
+ objSize = 0; /* unknown */
+ }
+ } else {
+ int nInstVars, nInstBytes;
+ OBJ oClass = __Class(anObject);
- switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
- case BYTEARRAY:
- case WORDARRAY:
- case LONGARRAY:
- case SWORDARRAY:
- case SLONGARRAY:
- case FLOATARRAY:
- case DOUBLEARRAY:
- break;
- default:
- goto bad;
- }
- nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
- nInstBytes = __OBJS2BYTES__(nInstVars);
- // nInstBytes is the number of bytes occupied by pointer instance variables
- // subtract from size and add to byte-pointer
- objSize = __qSize(anObject) - OHDR_SIZE - nInstBytes;
- extPtr = (unsigned char *)__byteArrayVal(anObject)+nInstBytes;
- }
+ switch (__intVal(__ClassInstPtr(oClass)->c_flags) & ARRAYMASK) {
+ case BYTEARRAY:
+ case WORDARRAY:
+ case LONGARRAY:
+ case SWORDARRAY:
+ case SLONGARRAY:
+ case FLOATARRAY:
+ case DOUBLEARRAY:
+ break;
+ default:
+ goto bad;
+ }
+ nInstVars = __intVal(__ClassInstPtr(oClass)->c_ninstvars);
+ nInstBytes = __OBJS2BYTES__(nInstVars);
+ // nInstBytes is the number of bytes occupied by pointer instance variables
+ // subtract from size and add to byte-pointer
+ objSize = __qSize(anObject) - OHDR_SIZE - nInstBytes;
+ extPtr = (unsigned char *)__byteArrayVal(anObject)+nInstBytes;
+ }
- if ((offs >= 0) && (len >= 0) && (objSize >= (len + offs))) {
- unsigned int _crc;
- unsigned int *_crcTable = __integerArrayVal( __INST(crcTable) );
- unsigned char *cp = extPtr+offs;
- unsigned int n = len;
- OBJ crcInst = __INST(crc);
-
- // fetch here, but catch non-SmallInt error later
- _crc = (unsigned int) (__intVal( crcInst ));
- if (! __isSmallInteger(crcInst)) {
- _crc = __unsignedLongIntVal(crcInst);
- }
+ if ((offs >= 0) && (len >= 0) && (objSize >= (len + offs))) {
+ unsigned int _crc;
+ unsigned int *_crcTable = __integerArrayVal( __INST(crcTable) );
+ unsigned char *cp = extPtr+offs;
+ unsigned int n = len;
+
+ if (__isSmallInteger(__INST(crc))) {
+ _crc = (unsigned int) (__intVal( __INST(crc) ));
+ } else {
+ _crc = __unsignedLongIntVal( __INST(crc) );
+ }
# if __POINTER_SIZE__ == 8
- if (((unsigned INT)cp & 7) == 0) {
- // longword aligned
- for ( ; n >= 32 ; n -= 32, cp += 32) {
- unsigned INT w0, w1, w2, w3;
-
- w0 = ((unsigned INT *)cp)[0];
- w1 = ((unsigned INT *)cp)[1];
- w2 = ((unsigned INT *)cp)[2];
- w3 = ((unsigned INT *)cp)[3];
- _crc = _mm_crc32_u64(_crc, w0);
- _crc = _mm_crc32_u64(_crc, w1);
- _crc = _mm_crc32_u64(_crc, w2);
- _crc = _mm_crc32_u64(_crc, w3);
- }
- if (n >= 16) {
- _crc = _mm_crc32_u64(_crc, ((unsigned INT *)cp)[0]);
- _crc = _mm_crc32_u64(_crc, ((unsigned INT *)cp)[1]);
- n -= 16, cp += 16;
- }
- if (n >= 8) {
- _crc = _mm_crc32_u64(_crc, ((unsigned INT *)cp)[0]);
- n -= 8, cp += 8;
- }
- if (n >= 4) {
- _crc = _mm_crc32_u32(_crc, ((unsigned int *)cp)[0]);
- n -= 4, cp += 4;
- }
- if (n >= 2) {
- _crc = _mm_crc32_u16(_crc, ((unsigned short *)cp)[0]);
- n -= 2, cp += 2;
- }
- if (n >= 1) {
- _crc = _mm_crc32_u8(_crc, (cp)[0]);
- }
- __INST(crc) = __MKSMALLINT(_crc);
- RETURN (count);
- }
-# endif // __POINTER_SIZE__ == 8
- if (((unsigned INT)cp & 3) == 0) {
- // word aligned
- for ( ; n >= 4 ; n -= 4, cp += 4) {
- _crc = _mm_crc32_u32(_crc, ((unsigned int *)cp)[0]);
- }
- }
- for ( ; n >= 4 ; n -= 4, cp += 4) {
- _crc = _mm_crc32_u8(_crc, cp[0]);
- _crc = _mm_crc32_u8(_crc, cp[1]);
- _crc = _mm_crc32_u8(_crc, cp[2]);
- _crc = _mm_crc32_u8(_crc, cp[3]);
- }
- while (n-- > 0) {
- unsigned char ch = *cp++;
+ if (((unsigned INT)cp & 7) == 0) {
+ // longword aligned
+ for ( ; n >= 32 ; n -= 32, cp += 32) {
+ unsigned INT w0 = ((unsigned INT *)cp)[0];
+ unsigned INT w1, w2, w3;
- _crc = _mm_crc32_u8(_crc, ch);
- }
-done:
- if ((__POINTER_SIZE__==8) || (_crc <= _MAX_INT)) {
- __INST(crc) = __MKSMALLINT(_crc);
- } else {
- // this code fails with gcc 4.7.2:
- // __INST(crc) = __MKUINT(_crc); __STORESELF(crc);
- OBJ temp = __MKUINT(_crc);
- __INST(crc) = temp; __STORESELF(crc);
- }
+ _crc = __crc32_u64(_crc, w0);
+ w1 = ((unsigned INT *)cp)[1];
+ _crc = __crc32_u64(_crc, w1);
+ w2 = ((unsigned INT *)cp)[2];
+ _crc = __crc32_u64(_crc, w2);
+ w3 = ((unsigned INT *)cp)[3];
+ _crc = __crc32_u64(_crc, w3);
+ }
+ for ( ; n >= 8 ; n -= 8, cp += 8) {
+ _crc = __crc32_u64(_crc, ((unsigned INT *)cp)[0]);
+ }
+ }
+# endif // __POINTER_SIZE__ == 8
+ if (((unsigned INT)cp & 3) == 0) {
+ // word aligned
+ for ( ; n >= 4 ; n -= 4, cp += 4) {
+ _crc = __crc32_u32(_crc, ((unsigned int *)cp)[0]);
+ }
+ }
+ for ( ; n >= 4 ; n -= 4, cp += 4) {
+ _crc = __crc32_u8(_crc, cp[0]);
+ _crc = __crc32_u8(_crc, cp[1]);
+ _crc = __crc32_u8(_crc, cp[2]);
+ _crc = __crc32_u8(_crc, cp[3]);
+ }
+ while (n-- > 0) {
+ unsigned char ch = *cp++;
- RETURN (count);
- }
+ _crc = __crc32_u8(_crc, ch);
+ }
+
+ if ((__POINTER_SIZE__==8) || (_crc <= _MAX_INT)) {
+ __INST(crc) = __MKSMALLINT(_crc);
+ } else {
+ // this code fails with gcc 4.7.2:
+ // __INST(crc) = __MKUINT(_crc); __STORESELF(crc);
+ OBJ temp = __MKUINT(_crc);
+ __INST(crc) = temp; __STORESELF(crc);
+ }
+
+ RETURN (count);
+ }
}
bad: ;
-# endif
#endif
%}.
self primitiveFailed
"Created: / 17-03-2019 / 16:44:27 / Claus Gittinger"
- "Modified: / 17-03-2019 / 18:09:03 / Claus Gittinger"
! !
!CRC32Stream class methodsFor:'documentation'!
@@ -685,4 +523,3 @@
version_CVS
^ '$Header$'
! !
-