Subversion Repositories Kolibri OS

Rev

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