Subversion Repositories Kolibri OS

Rev

Rev 6881 | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
6617 IgorA 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  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
	@@:
6639 IgorA 93
end if
6617 IgorA 94
	mov eax,crc_table
95
	ret
96
endp
97
 
98
; =========================================================================
6881 IgorA 99
;unsigned long (unsigned long crc, unsigned char *buf, uInt len)
6617 IgorA 100
align 4
101
proc calc_crc32 uses ecx esi, p1crc:dword, buf:dword, len:dword
102
	xor eax,eax
103
	mov esi,[buf]
6881 IgorA 104
 
6617 IgorA 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]
6881 IgorA 117
	push edx
6883 IgorA 118
	call crc_continue
6881 IgorA 119
	pop edx
6617 IgorA 120
.end_f:
121
	ret
122
endp
123
 
124
GF2_DIM equ 32 ;dimension of GF(2) vectors (length of CRC)
125
 
126
; =========================================================================
6881 IgorA 127
;unsigned long (unsigned long *mat, unsigned long vec)
6617 IgorA 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
; =========================================================================
6881 IgorA 144
;local void (unsigned long *square, unsigned long *mat)
6617 IgorA 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
; =========================================================================
6881 IgorA 155
;uLong (uLong crc1, uLong crc2, z_off64_t len2)
6617 IgorA 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
; =========================================================================
6881 IgorA 210
;uLong (uLong crc1, uLong crc2, z_off_t len2)
6617 IgorA 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
 
6881 IgorA 217
;uLong (uLong crc1, uLong crc2, z_off64_t len2)
6617 IgorA 218
align 4
219
proc crc32_combine64, crc1:dword, crc2:dword, len2:dword
220
	stdcall crc32_combine_, [crc1], [crc2], [len2]
221
	ret
222
endp