gzcrcasm.pas 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. Unit GZCrcAsm;
  2. {
  3. crc32.c -- compute the CRC-32 of a data stream
  4. Copyright (C) 1995-1998 Mark Adler
  5. Pascal translation
  6. Copyright (C) 1998 by Jacques Nomssi Nzali
  7. For conditions of distribution and use, see copyright notice in readme.txt
  8. Assembler for FPC by Marco van de Voort, originating from a Modula-2 port
  9. which originated from either SWAG sources or the RA development kit. (not
  10. tracable anymore)
  11. }
  12. interface
  13. {$I zconf.inc}
  14. {$IFNDEF FPC}
  15. 'CRC32 assembler version specific for the Free Pascal compiler'
  16. {$ELSE}
  17. {-- $DEFINE TightLoop}
  18. {$ENDIF}
  19. uses
  20. zutil, zbase;
  21. function crc32(crc : uLong; buf : pBytef; len : uInt) : uLong;
  22. { Update a running crc with the bytes buf[0..len-1] and return the updated
  23. crc. If buf is NULL, this function returns the required initial value
  24. for the crc. Pre- and post-conditioning (one's complement) is performed
  25. within this function so it shouldn't be done by the application.
  26. Usage example:
  27. var
  28. crc : uLong;
  29. begin
  30. crc := crc32(0, Z_NULL, 0);
  31. while (read_buffer(buffer, length) <> EOF) do
  32. crc := crc32(crc, buffer, length);
  33. if (crc <> original_crc) then error();
  34. end;
  35. }
  36. function get_crc_table : puLong; { can be used by asm versions of crc32() }
  37. implementation
  38. {$IFDEF DYNAMIC_CRC_TABLE}
  39. {local}
  40. const
  41. crc_table_empty : boolean = TRUE;
  42. {local}
  43. var
  44. crc_table : array[0..256-1] of uLongf;
  45. {
  46. Generate a table for a byte-wise 32-bit CRC calculation on the polynomial:
  47. 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.
  48. Polynomials over GF(2) are represented in binary, one bit per coefficient,
  49. with the lowest powers in the most significant bit. Then adding polynomials
  50. is just exclusive-or, and multiplying a polynomial by x is a right shift by
  51. one. If we call the above polynomial p, and represent a byte as the
  52. polynomial q, also with the lowest power in the most significant bit (so the
  53. byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
  54. where a mod b means the remainder after dividing a by b.
  55. This calculation is done using the shift-register method of multiplying and
  56. taking the remainder. The register is initialized to zero, and for each
  57. incoming bit, x^32 is added mod p to the register if the bit is a one (where
  58. x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
  59. x (which is shifting right by one and adding x^32 mod p if the bit shifted
  60. out is a one). We start with the highest power (least significant bit) of
  61. q and repeat for all eight bits of q.
  62. The table is simply the CRC of all possible eight bit values. This is all
  63. the information needed to generate CRC's on data a byte at a time for all
  64. combinations of CRC register values and incoming bytes.
  65. }
  66. {local}
  67. procedure make_crc_table;
  68. var
  69. c : uLong;
  70. n,k : int;
  71. poly : uLong; { polynomial exclusive-or pattern }
  72. const
  73. { terms of polynomial defining this crc (except x^32): }
  74. p: array [0..13] of Byte = (0,1,2,4,5,7,8,10,11,12,16,22,23,26);
  75. begin
  76. { make exclusive-or pattern from polynomial ($EDB88320) }
  77. poly := Long(0);
  78. for n := 0 to (sizeof(p) div sizeof(Byte))-1 do
  79. poly := poly or (Long(1) shl (31 - p[n]));
  80. for n := 0 to 255 do
  81. begin
  82. c := uLong(n);
  83. for k := 0 to 7 do
  84. begin
  85. if (c and 1) <> 0 then
  86. c := poly xor (c shr 1)
  87. else
  88. c := (c shr 1);
  89. end;
  90. crc_table[n] := c;
  91. end;
  92. crc_table_empty := FALSE;
  93. end;
  94. {$ELSE}
  95. { ========================================================================
  96. Table of CRC-32's of all single-byte values (made by make_crc_table) }
  97. {local}
  98. const
  99. crc_table : array[0..256-1] of uLongf = (
  100. $00000000, $77073096, $ee0e612c, $990951ba, $076dc419,
  101. $706af48f, $e963a535, $9e6495a3, $0edb8832, $79dcb8a4,
  102. $e0d5e91e, $97d2d988, $09b64c2b, $7eb17cbd, $e7b82d07,
  103. $90bf1d91, $1db71064, $6ab020f2, $f3b97148, $84be41de,
  104. $1adad47d, $6ddde4eb, $f4d4b551, $83d385c7, $136c9856,
  105. $646ba8c0, $fd62f97a, $8a65c9ec, $14015c4f, $63066cd9,
  106. $fa0f3d63, $8d080df5, $3b6e20c8, $4c69105e, $d56041e4,
  107. $a2677172, $3c03e4d1, $4b04d447, $d20d85fd, $a50ab56b,
  108. $35b5a8fa, $42b2986c, $dbbbc9d6, $acbcf940, $32d86ce3,
  109. $45df5c75, $dcd60dcf, $abd13d59, $26d930ac, $51de003a,
  110. $c8d75180, $bfd06116, $21b4f4b5, $56b3c423, $cfba9599,
  111. $b8bda50f, $2802b89e, $5f058808, $c60cd9b2, $b10be924,
  112. $2f6f7c87, $58684c11, $c1611dab, $b6662d3d, $76dc4190,
  113. $01db7106, $98d220bc, $efd5102a, $71b18589, $06b6b51f,
  114. $9fbfe4a5, $e8b8d433, $7807c9a2, $0f00f934, $9609a88e,
  115. $e10e9818, $7f6a0dbb, $086d3d2d, $91646c97, $e6635c01,
  116. $6b6b51f4, $1c6c6162, $856530d8, $f262004e, $6c0695ed,
  117. $1b01a57b, $8208f4c1, $f50fc457, $65b0d9c6, $12b7e950,
  118. $8bbeb8ea, $fcb9887c, $62dd1ddf, $15da2d49, $8cd37cf3,
  119. $fbd44c65, $4db26158, $3ab551ce, $a3bc0074, $d4bb30e2,
  120. $4adfa541, $3dd895d7, $a4d1c46d, $d3d6f4fb, $4369e96a,
  121. $346ed9fc, $ad678846, $da60b8d0, $44042d73, $33031de5,
  122. $aa0a4c5f, $dd0d7cc9, $5005713c, $270241aa, $be0b1010,
  123. $c90c2086, $5768b525, $206f85b3, $b966d409, $ce61e49f,
  124. $5edef90e, $29d9c998, $b0d09822, $c7d7a8b4, $59b33d17,
  125. $2eb40d81, $b7bd5c3b, $c0ba6cad, $edb88320, $9abfb3b6,
  126. $03b6e20c, $74b1d29a, $ead54739, $9dd277af, $04db2615,
  127. $73dc1683, $e3630b12, $94643b84, $0d6d6a3e, $7a6a5aa8,
  128. $e40ecf0b, $9309ff9d, $0a00ae27, $7d079eb1, $f00f9344,
  129. $8708a3d2, $1e01f268, $6906c2fe, $f762575d, $806567cb,
  130. $196c3671, $6e6b06e7, $fed41b76, $89d32be0, $10da7a5a,
  131. $67dd4acc, $f9b9df6f, $8ebeeff9, $17b7be43, $60b08ed5,
  132. $d6d6a3e8, $a1d1937e, $38d8c2c4, $4fdff252, $d1bb67f1,
  133. $a6bc5767, $3fb506dd, $48b2364b, $d80d2bda, $af0a1b4c,
  134. $36034af6, $41047a60, $df60efc3, $a867df55, $316e8eef,
  135. $4669be79, $cb61b38c, $bc66831a, $256fd2a0, $5268e236,
  136. $cc0c7795, $bb0b4703, $220216b9, $5505262f, $c5ba3bbe,
  137. $b2bd0b28, $2bb45a92, $5cb36a04, $c2d7ffa7, $b5d0cf31,
  138. $2cd99e8b, $5bdeae1d, $9b64c2b0, $ec63f226, $756aa39c,
  139. $026d930a, $9c0906a9, $eb0e363f, $72076785, $05005713,
  140. $95bf4a82, $e2b87a14, $7bb12bae, $0cb61b38, $92d28e9b,
  141. $e5d5be0d, $7cdcefb7, $0bdbdf21, $86d3d2d4, $f1d4e242,
  142. $68ddb3f8, $1fda836e, $81be16cd, $f6b9265b, $6fb077e1,
  143. $18b74777, $88085ae6, $ff0f6a70, $66063bca, $11010b5c,
  144. $8f659eff, $f862ae69, $616bffd3, $166ccf45, $a00ae278,
  145. $d70dd2ee, $4e048354, $3903b3c2, $a7672661, $d06016f7,
  146. $4969474d, $3e6e77db, $aed16a4a, $d9d65adc, $40df0b66,
  147. $37d83bf0, $a9bcae53, $debb9ec5, $47b2cf7f, $30b5ffe9,
  148. $bdbdf21c, $cabac28a, $53b39330, $24b4a3a6, $bad03605,
  149. $cdd70693, $54de5729, $23d967bf, $b3667a2e, $c4614ab8,
  150. $5d681b02, $2a6f2b94, $b40bbe37, $c30c8ea1, $5a05df1b,
  151. $2d02ef8d);
  152. {$ENDIF}
  153. { =========================================================================
  154. This function can be used by asm versions of crc32() }
  155. function get_crc_table : {const} puLong;
  156. begin
  157. {$ifdef DYNAMIC_CRC_TABLE}
  158. if (crc_table_empty) then
  159. make_crc_table;
  160. {$endif}
  161. get_crc_table := {const} puLong(@crc_table);
  162. end;
  163. { ========================================================================= }
  164. function crc32 (crc : uLong; buf : pBytef; len : uInt): uLong; ASSEMBLER;
  165. // Original header, old procedure didn't normalize or check for NIL pointer
  166. // (since open array), and check for table-existance.
  167. //
  168. // FUNCTION Crc32( crc : CARDINAL;var Buffer;BufSize:CARDINAL):CARDINAL;ASSEMBLER;
  169. ASM
  170. mov buf,%esi // Load source address
  171. xor %ebx,%ebx
  172. test %esi,%esi
  173. je .LCalcAfterEndLoop // buf-pointer is NIL
  174. mov crc,%ebx // load previous CRC
  175. xor $-1,%ebx // normalize/invert CRC
  176. call get_crc_table
  177. mov %eax,%edi
  178. mov len,%ecx // Counter.
  179. {$IFNDEF TightLoop}
  180. .LTightTest: test $-8,%ecx // Test if at least 8 bytes left in buffer
  181. je .LCalcEndbigloop
  182. lodsb // Yes, loop optimalisation
  183. movzbl %bl,%edx
  184. shrl $8,%ebx
  185. xorb %al,%dl
  186. xorl (%edi,%edx,4),%ebx
  187. // the above base code is copied 7 times. So 7+1=8
  188. lodsb // 2
  189. movzbl %bl,%edx
  190. shrl $8,%ebx
  191. xorb %al,%dl
  192. xorl (%edi,%edx,4),%ebx
  193. lodsb // 3
  194. movzbl %bl,%edx
  195. shrl $8,%ebx
  196. xorb %al,%dl
  197. xorl (%edi,%edx,4),%ebx
  198. lodsb // 4
  199. movzbl %bl,%edx
  200. shrl $8,%ebx
  201. xorb %al,%dl
  202. xorl (%edi,%edx,4),%ebx
  203. lodsb // 5
  204. movzbl %bl,%edx
  205. shrl $8,%ebx
  206. xorb %al,%dl
  207. xorl (%edi,%edx,4),%ebx
  208. lodsb // 6
  209. movzbl %bl,%edx
  210. shrl $8,%ebx
  211. xorb %al,%dl
  212. xorl (%edi,%edx,4),%ebx
  213. lodsb // 7
  214. movzbl %bl,%edx
  215. shrl $8,%ebx
  216. xorb %al,%dl
  217. xorl (%edi,%edx,4),%ebx
  218. lodsb // 8
  219. movzbl %bl,%edx
  220. shrl $8,%ebx
  221. xorb %al,%dl
  222. xorl (%edi,%edx,4),%ebx
  223. subl $8,%ecx // 8 less to go
  224. jmp .LTightTest
  225. .LCalcEndbigloop: jecxz .LCalcNormalTerm
  226. {$ENDIF}
  227. .LCalcLoop: lodsb // Do (rest) buffer
  228. movzbl %bl,%edx
  229. shrl $8,%ebx
  230. xorb %al,%dl
  231. xorl (%edi,%edx,4),%ebx
  232. loop .LCalcLoop
  233. .LCalcNormalTerm: xor $-1,%ebx // normalize/invert CRC
  234. .LCalcAfterEndLoop: mov %ebx,%eax
  235. end['EAX','EBX','ECX','EDX','ESI','EDI'];
  236. end.