Subversion Repositories Kolibri OS

Rev

Rev 6639 | Go to most recent revision | Blame | Compare with Previous | Last modification | View Log | Download | RSS feed

  1. ; crc32.asm -- compute the CRC-32 of a data stream
  2. ; Copyright (C) 1995-2006, 2010, 2011, 2012 Mark Adler
  3. ; For conditions of distribution and use, see copyright notice in zlib.inc
  4.  
  5. ; Thanks to Rodney Brown <rbrown64@csc.com.au> for his contribution of faster
  6. ; CRC methods: exclusive-oring 32 bits of data at a time, and pre-computing
  7. ; tables for updating the shift register in one step with three exclusive-ors
  8. ; instead of four steps with four exclusive-ors.  This results in about a
  9. ; factor of two increase in speed on a Power PC G4 (PPC7455) using gcc -O3.
  10.  
  11.  
  12. ;  Note on the use of DYNAMIC_CRC_TABLE: there is no mutex or semaphore
  13. ;  protection on the static variables used to control the first-use generation
  14. ;  of the crc tables.  Therefore, if you #define DYNAMIC_CRC_TABLE, you should
  15. ;  first call get_crc_table() to initialize the tables before allowing more than
  16. ;  one thread to use crc32().
  17.  
  18. ; Definitions for doing the crc four data bytes at a time.
  19.  
  20. TBLS equ 1
  21.  
  22. if DYNAMIC_CRC_TABLE eq 1
  23.  
  24. align 4
  25. crc_table_empty dd 1
  26. ;align 4
  27. ;crc_table rd TBLS*256
  28.  
  29. ;  Generate tables for a byte-wise 32-bit CRC calculation on the polynomial:
  30. ;  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.
  31.  
  32. ;  Polynomials over GF(2) are represented in binary, one bit per coefficient,
  33. ;  with the lowest powers in the most significant bit.  Then adding polynomials
  34. ;  is just exclusive-or, and multiplying a polynomial by x is a right shift by
  35. ;  one.  If we call the above polynomial p, and represent a byte as the
  36. ;  polynomial q, also with the lowest power in the most significant bit (so the
  37. ;  byte 0xb1 is the polynomial x^7+x^3+x+1), then the CRC is (q*x^32) mod p,
  38. ;  where a mod b means the remainder after dividing a by b.
  39.  
  40. ;  This calculation is done using the shift-register method of multiplying and
  41. ;  taking the remainder.  The register is initialized to zero, and for each
  42. ;  incoming bit, x^32 is added mod p to the register if the bit is a one (where
  43. ;  x^32 mod p is p+x^32 = x^26+...+1), and the register is multiplied mod p by
  44. ;  x (which is shifting right by one and adding x^32 mod p if the bit shifted
  45. ;  out is a one).  We start with the highest power (least significant bit) of
  46. ;  q and repeat for all eight bits of q.
  47.  
  48. ;  The first table is simply the CRC of all possible eight bit values.  This is
  49. ;  all the information needed to generate CRCs on data a byte at a time for all
  50. ;  combinations of CRC register values and incoming bytes.  The remaining tables
  51. ;  allow for word-at-a-time CRC calculation for both big-endian and little-
  52. ;  endian machines, where a word is four bytes.
  53.  
  54. ;void ()
  55. align 4
  56. proc make_crc_table uses ecx edx edi
  57. zlib_debug 'make_crc_table'
  58.  
  59.         ; generate a crc for every 8-bit value
  60.         xor edx, edx
  61.         mov edi, crc_table
  62. .1:
  63.         mov ecx, 8
  64.         mov eax, edx
  65. .2:
  66.         shr eax, 1
  67.         jnc @f
  68.         xor eax, 0xEDB88320
  69. @@:
  70.         loop .2
  71.         stosd
  72.         inc dl
  73.         jnz .1
  74.  
  75.         mov dword[crc_table_empty],0
  76.         ret
  77. endp
  78.  
  79. else ;!DYNAMIC_CRC_TABLE
  80. ; ========================================================================
  81. ; Tables of CRC-32s of all single-byte values, made by make_crc_table().
  82.  
  83. ;include 'crc32.inc'
  84. end if ;DYNAMIC_CRC_TABLE
  85.  
  86. ; =========================================================================
  87. ; This function can be used by asm versions of crc32()
  88.  
  89. ;const z_crc_t* ()
  90. align 4
  91. proc get_crc_table
  92. if DYNAMIC_CRC_TABLE eq 1
  93.         cmp dword[crc_table_empty],0
  94.         je @f ;if (..)
  95.                 call make_crc_table
  96.         @@:
  97. end if
  98.         mov eax,crc_table
  99.         ret
  100. endp
  101.  
  102. ; =========================================================================
  103. ;unsigned long (crc, buf, len)
  104. ;    unsigned long crc
  105. ;    unsigned char *buf
  106. ;    uInt len
  107. align 4
  108. proc calc_crc32 uses ecx esi, p1crc:dword, buf:dword, len:dword
  109.         xor eax,eax
  110.         mov esi,[buf]
  111. zlib_debug 'calc_crc32 buf = %d',esi
  112.         cmp esi,Z_NULL
  113.         je .end_f ;if (..==0) return 0
  114.  
  115. if DYNAMIC_CRC_TABLE eq 1
  116.         cmp dword[crc_table_empty],0
  117.         je @f ;if (..)
  118.                 call make_crc_table
  119.         @@:
  120. end if
  121.  
  122.         mov eax,[p1crc]
  123.         mov ecx,[len]
  124.         call crc
  125. .end_f:
  126.         ret
  127. endp
  128.  
  129. GF2_DIM equ 32 ;dimension of GF(2) vectors (length of CRC)
  130.  
  131. ; =========================================================================
  132. ;unsigned long (mat, vec)
  133. ;    unsigned long *mat
  134. ;    unsigned long vec
  135. align 4
  136. proc gf2_matrix_times, mat:dword, vec:dword
  137. ;    unsigned long sum;
  138.  
  139. ;    sum = 0;
  140. ;    while (vec) {
  141. ;        if (vec & 1)
  142. ;            sum ^= *mat;
  143. ;        vec >>= 1;
  144. ;        mat++;
  145. ;    }
  146. ;    return sum;
  147.         ret
  148. endp
  149.  
  150. ; =========================================================================
  151. ;local void (square, mat)
  152. ;    unsigned long *square
  153. ;    unsigned long *mat
  154. align 4
  155. proc gf2_matrix_square, square:dword, mat:dword
  156. ;    int n;
  157.  
  158. ;    for (n = 0; n < GF2_DIM; n++)
  159. ;        square[n] = gf2_matrix_times(mat, mat[n]);
  160.         ret
  161. endp
  162.  
  163. ; =========================================================================
  164. ;uLong (crc1, crc2, len2)
  165. ;    uLong crc1
  166. ;    uLong crc2
  167. ;    z_off64_t len2
  168. align 4
  169. proc crc32_combine_, crc1:dword, crc2:dword, len2:dword
  170. ;    int n;
  171. ;    unsigned long row;
  172. ;    unsigned long even[GF2_DIM];    /* even-power-of-two zeros operator */
  173. ;    unsigned long odd[GF2_DIM];     /* odd-power-of-two zeros operator */
  174.  
  175.         ; degenerate case (also disallow negative lengths)
  176. ;    if (len2 <= 0)
  177. ;        return crc1;
  178.  
  179.         ; put operator for one zero bit in odd
  180. ;    odd[0] = 0xedb88320UL;          /* CRC-32 polynomial */
  181. ;    row = 1;
  182. ;    for (n = 1; n < GF2_DIM; n++) {
  183. ;        odd[n] = row;
  184. ;        row <<= 1;
  185. ;    }
  186.  
  187.         ; put operator for two zero bits in even
  188. ;    gf2_matrix_square(even, odd);
  189.  
  190.         ; put operator for four zero bits in odd
  191. ;    gf2_matrix_square(odd, even);
  192.  
  193.         ; apply len2 zeros to crc1 (first square will put the operator for one
  194.         ; zero byte, eight zero bits, in even)
  195. ;    do {
  196.                 ; apply zeros operator for this bit of len2
  197. ;        gf2_matrix_square(even, odd);
  198. ;        if (len2 & 1)
  199. ;            crc1 = gf2_matrix_times(even, crc1);
  200. ;        len2 >>= 1;
  201.  
  202.         ; if no more bits set, then done
  203. ;        if (len2 == 0)
  204. ;            break;
  205.  
  206.         ; another iteration of the loop with odd and even swapped
  207. ;        gf2_matrix_square(odd, even);
  208. ;        if (len2 & 1)
  209. ;            crc1 = gf2_matrix_times(odd, crc1);
  210. ;        len2 >>= 1;
  211.  
  212.         ; if no more bits set, then done
  213. ;    } while (len2 != 0);
  214.  
  215.         ; return combined crc
  216. ;    crc1 ^= crc2;
  217. ;    return crc1;
  218.         ret
  219. endp
  220.  
  221. ; =========================================================================
  222. ;uLong (crc1, crc2, len2)
  223. ;    uLong crc1
  224. ;    uLong crc2
  225. ;    z_off_t len2
  226. align 4
  227. proc crc32_combine, crc1:dword, crc2:dword, len2:dword
  228.         stdcall crc32_combine_, [crc1], [crc2], [len2]
  229.         ret
  230. endp
  231.  
  232. ;uLong (crc1, crc2, len2)
  233. ;    uLong crc1
  234. ;    uLong crc2
  235. ;    z_off64_t len2
  236. align 4
  237. proc crc32_combine64, crc1:dword, crc2:dword, len2:dword
  238.         stdcall crc32_combine_, [crc1], [crc2], [len2]
  239.         ret
  240. endp
  241.