Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
4349 Serge 1
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
2
;;                                                              ;;
3
;; Copyright (C) KolibriOS team 2004-2007. All rights reserved. ;;
4
;; Distributed under terms of the GNU General Public License    ;;
5
;;                                                              ;;
6
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
7
 
8
 
9
format MS COFF
10
 
11
section '.text' code readable align 16
12
 
13
public _unpack@8
14
 
15
; void __stdcall unpack(void* packed_data, void* unpacked_data);
16
_unpack@8:
17
unpack:
18
        pushad
19
        mov     esi, [esp+32+4]
20
        mov     edi, [esp+32+8]
21
        mov     eax, [esi+8]
22
        and     al, 0xC0
23
        cmp     al, 0xC0
24
        jz      .failed
25
        mov     eax, [esi+8]
26
        push    eax
27
        add     esi, 12
28
        and     al, not 0xC0
29
        dec     eax
30
        jz      .lzma
31
.failed:
32
        pop     eax
33
        popad
34
        ret     8
35
.lzma:
36
        call    .lzma_unpack
37
.common:
38
        pop     eax
39
        test    al, 0x80
40
        jnz     .ctr1
41
        test    al, 0x40
42
        jz      .ok
43
        lodsd
44
        mov     ecx, eax
45
        jecxz   .ok
46
        mov     dl, [esi]
47
        mov     esi, [esp+32+8]
48
.c1:
49
        lodsb
50
        sub     al, 0E8h
51
        cmp     al, 1
52
        ja      .c1
53
        cmp     byte [esi], dl
54
        jnz     .c1
55
        lodsd
56
; "bswap eax" is not supported on i386
57
        shr     ax, 8
58
        ror     eax, 16
59
        xchg    al, ah
60
        sub     eax, esi
61
        add     eax, [esp+32+8]
62
        mov     [esi-4], eax
63
        loop    .c1
64
.ok:
65
        popad
66
        ret     8
67
.ctr1:
68
        lodsd
69
        mov     ecx, eax
70
        jecxz   .ok
71
        mov     dl, [esi]
72
        mov     esi, [esp+32+8]
73
.c2:
74
        lodsb
75
@@:
76
        cmp     al, 0xF
77
        jnz     .f
78
        lodsb
79
        cmp     al, 80h
80
        jb      @b
81
        cmp     al, 90h
82
        jb      @f
83
.f:
84
        sub     al, 0E8h
85
        cmp     al, 1
86
        ja      .c2
87
@@:
88
        cmp     byte [esi], dl
89
        jnz     .c2
90
        lodsd
91
        shr     ax, 8
92
        ror     eax, 16
93
        xchg    al, ah
94
        sub     eax, esi
95
        add     eax, [esp+32+8]
96
        mov     [esi-4], eax
97
        loop    .c2
98
        jmp     .ok
99
 
100
.lzma_unpack:
101
 
102
.pb	=	2	; pos state bits
103
.lp	=	0	; literal pos state bits
104
.lc	=	3	; literal context bits
105
.posStateMask	=	((1 shl .pb)-1)
106
.literalPosMask	=	((1 shl .lp)-1)
107
 
108
.kNumPosBitsMax	=	4
109
.kNumPosStatesMax =	(1 shl .kNumPosBitsMax)
110
 
111
.kLenNumLowBits         =       3
112
.kLenNumLowSymbols      =       (1 shl .kLenNumLowBits)
113
.kLenNumMidBits         =       3
114
.kLenNumMidSymbols      =       (1 shl .kLenNumMidBits)
115
.kLenNumHighBits        =       8
116
.kLenNumHighSymbols     =       (1 shl .kLenNumHighBits)
117
 
118
.LenChoice	=	0
119
.LenChoice2	=	1
120
.LenLow		=	2
121
.LenMid		=	(.LenLow + (.kNumPosStatesMax shl .kLenNumLowBits))
122
.LenHigh	=	(.LenMid + (.kNumPosStatesMax shl .kLenNumMidBits))
123
.kNumLenProbs	=	(.LenHigh + .kLenNumHighSymbols)
124
 
125
.kNumStates	=	12
126
.kNumLitStates	=	7
127
.kStartPosModelIndex =	4
128
.kEndPosModelIndex =	14
129
.kNumFullDistances =	(1 shl (.kEndPosModelIndex/2))
130
.kNumPosSlotBits =	6
131
.kNumLenToPosStates =	4
132
.kNumAlignBits	=	4
133
.kAlignTableSize =	(1 shl .kNumAlignBits)
134
.kMatchMinLen	=	2
135
 
136
.IsMatch	=	0
137
.IsRep		=	(.IsMatch + (.kNumStates shl .kNumPosBitsMax))
138
.IsRepG0	=	(.IsRep + .kNumStates)
139
.IsRepG1	=	(.IsRepG0 + .kNumStates)
140
.IsRepG2	=	(.IsRepG1 + .kNumStates)
141
.IsRep0Long	=	(.IsRepG2 + .kNumStates)
142
.PosSlot	=	(.IsRep0Long + (.kNumStates shl .kNumPosBitsMax))
143
.SpecPos	=	(.PosSlot + (.kNumLenToPosStates shl .kNumPosSlotBits))
144
.Align_		=	(.SpecPos + .kNumFullDistances - .kEndPosModelIndex)
145
.Lencoder	=	(.Align_ + .kAlignTableSize)
146
.RepLencoder	=	(.Lencoder + .kNumLenProbs)
147
.Literal	=	(.RepLencoder + .kNumLenProbs)
148
 
149
.LZMA_BASE_SIZE	=	1846	; must be ==Literal
150
.LZMA_LIT_SIZE	=	768
151
 
152
.kNumTopBits	=	24
153
.kTopValue	=	(1 shl .kNumTopBits)
154
 
155
.kNumBitModelTotalBits =	11
156
.kBitModelTotal	=	(1 shl .kNumBitModelTotalBits)
157
.kNumMoveBits	=	5
158
 
159
        push    edi
160
; int state=0;
161
	xor	ebx, ebx
162
	mov	[.previousByte], bl
163
; unsigned rep0=1,rep1=1,rep2=1,rep3=1;
164
	mov	eax, 1
165
	mov	edi, .rep0
166
	stosd
167
	stosd
168
	stosd
169
	stosd
170
; int len=0;
171
; result=0;
172
	mov	ecx, .Literal + (.LZMA_LIT_SIZE shl (.lc+.lp))
173
	mov	eax, .kBitModelTotal/2
174
        lea     edi, [.p]
175
	rep	stosd
176
; RangeDecoderInit
177
; rd->ExtraBytes = 0
178
; rd->Buffer = stream
179
; rd->BufferLim = stream+bufferSize
180
; rd->Range = 0xFFFFFFFF
181
        pop     edi
182
	mov	ebp, [esi-8]	; dest_length
183
	add	ebp, edi	; ebp = destination limit
184
	lodsd
185
; rd->code_ = eax
186
	mov	[.code_], eax
187
	or	[.range], -1
188
.main_loop:
189
	cmp	edi, ebp
190
	jae	.main_loop_done
191
	mov	edx, edi
192
	and	edx, .posStateMask
193
	mov	eax, ebx
194
	shl	eax, .kNumPosBitsMax+2
195
        lea     eax, [.p+.IsMatch*4 + eax + edx*4]
196
;       add     eax, [.p]
197
	call	.RangeDecoderBitDecode
198
	jc	.1
199
	movzx	eax, [.previousByte]
200
if .literalPosMask
201
	mov	ah, dl
202
	and	ah, .literalPosMask
203
end if
204
	shr	eax, 8-.lc
205
	imul	eax, .LZMA_LIT_SIZE*4
206
        add     eax, (.p+.Literal*4)
207
;       add     eax, [.p]
208
	cmp	ebx, .kNumLitStates
209
	jb	.literal
210
	xor	edx, edx
211
	sub	edx, [.rep0]
212
	mov	dl, [edi + edx]
213
	call	.LzmaLiteralDecodeMatch
214
	jmp	@f
215
.literal:
216
	call	.LzmaLiteralDecode
217
@@:
218
	mov	[.previousByte], al
219
	stosb
220
	mov	al, bl
221
	cmp	bl, 4
222
	jb	@f
223
	mov	al, 3
224
	cmp	bl, 10
225
	jb	@f
226
	mov	al, 6
227
@@:	sub	bl, al
228
	jmp	.main_loop
229
.1:
230
        lea     eax, [.p+.IsRep*4 + ebx*4]
231
;       add     eax, [.p]
232
	call	.RangeDecoderBitDecode
233
	jnc	.10
234
        lea     eax, [.p+.IsRepG0*4 + ebx*4]
235
;       add     eax, [.p]
236
	call	.RangeDecoderBitDecode
237
	jc	.111
238
	mov	eax, ebx
239
	shl	eax, .kNumPosBitsMax+2
240
        lea     eax, [.p+.IsRep0Long*4 + eax + edx*4]
241
;       add     eax, [.p]
242
	call	.RangeDecoderBitDecode
243
	jc	.1101
244
	cmp	bl, 7
245
	setae	bl
246
	lea	ebx, [9 + ebx + ebx]
247
	xor	edx, edx
248
	sub	edx, [.rep0]
249
	mov	al, [edi + edx]
250
	stosb
251
	mov	[.previousByte], al
252
	jmp	.main_loop
253
.111:
254
        lea     eax, [.p+.IsRepG1*4 + ebx*4]
255
;       add     eax, [.p]
256
	call	.RangeDecoderBitDecode
257
	mov	eax, [.rep1]
258
	jnc	.l3
259
.l1:
260
        lea     eax, [.p+.IsRepG2*4 + ebx*4]
261
;       add     eax, [.p]
262
	call	.RangeDecoderBitDecode
263
	mov	eax, [.rep2]
264
	jnc	.l2
265
	xchg	[.rep3], eax
266
.l2:
267
	push	[.rep1]
268
	pop	[.rep2]
269
.l3:
270
	xchg	eax, [.rep0]
271
	mov	[.rep1], eax
272
.1101:
273
        mov     eax, (.p+.RepLencoder*4)
274
;       add     eax, [.p]
275
	call	.LzmaLenDecode
276
	cmp	bl, 7
277
	setc	bl
278
	adc	bl, bl
279
	xor	bl, 3
280
	add	bl, 8
281
	jmp	.repmovsb
282
.10:
283
	mov	eax, [.rep0]
284
	xchg	eax, [.rep1]
285
	xchg	eax, [.rep2]
286
	xchg	eax, [.rep3]
287
	cmp	bl, 7
288
	setc	bl
289
	adc	bl, bl
290
	xor	bl, 3
291
	add	bl, 7
292
        mov     eax, (.p+.Lencoder*4)
293
;       add     eax, [.p]
294
	call	.LzmaLenDecode
295
	mov	eax, .kNumLenToPosStates-1
296
	cmp	eax, ecx
297
	jb	@f
298
	mov	eax, ecx
299
@@:
300
	push	ecx
301
	mov	ecx, .kNumPosSlotBits
302
	shl	eax, cl
303
	shl	eax, 2
304
        add     eax, (.p+.PosSlot*4)
305
;       add     eax, [.p]
306
	call	.RangeDecoderBitTreeDecode
307
	mov	[.rep0], ecx
308
	cmp	ecx, .kStartPosModelIndex
309
	jb	.l6
310
	push	ecx
311
	mov	eax, ecx
312
	and	eax, 1
313
	shr	ecx, 1
314
	or	eax, 2
315
	dec	ecx
316
	shl	eax, cl
317
	mov	[.rep0], eax
318
	pop	edx
319
	cmp	edx, .kEndPosModelIndex
320
	jae	.l5
321
	sub	eax, edx
322
	shl	eax, 2
323
        add     eax, (.p+(.SpecPos - 1)*4)
324
;       add     eax, [.p]
325
	call	.RangeDecoderReverseBitTreeDecode
326
	add	[.rep0], ecx
327
	jmp	.l6
328
.l5:
329
	sub	ecx, .kNumAlignBits
330
	call	.RangeDecoderDecodeDirectBits
331
	mov	ecx, .kNumAlignBits
332
	shl	eax, cl
333
	add	[.rep0], eax
334
        mov     eax, (.p+.Align_*4)
335
;       add     eax, [.p]
336
	call	.RangeDecoderReverseBitTreeDecode
337
	add	[.rep0], ecx
338
.l6:
339
	pop	ecx
340
	inc	[.rep0]
341
	jz	.main_loop_done
342
.repmovsb:
343
	add	ecx, .kMatchMinLen
344
	push	esi
345
	mov	esi, edi
346
	sub	esi, [.rep0]
347
	rep	movsb
348
	pop	esi
349
	mov	al, [edi-1]
350
	mov	[.previousByte], al
351
	jmp	.main_loop
352
.main_loop_done:
353
	ret
354
 
355
.RangeDecoderBitDecode:
356
; in: eax->prob
357
; out: CF=bit; destroys eax
358
	push	edx
359
	mov	edx, [.range]
360
	shr	edx, .kNumBitModelTotalBits
361
	imul	edx, [eax]
362
	cmp	[.code_], edx
363
	jae	.ae
364
	mov	[.range], edx
365
	mov	edx, .kBitModelTotal
366
	sub	edx, [eax]
367
	shr	edx, .kNumMoveBits
368
	add	[eax], edx
369
	clc
370
.n:
371
	lahf
372
	cmp	[.range], .kTopValue
373
	jae	@f
374
	shl	[.range], 8
375
	shl	[.code_], 8
376
	lodsb
377
	mov	byte [.code_], al
378
@@:
379
	sahf
380
	pop	edx
381
	ret
382
.ae:
383
	sub	[.range], edx
384
	sub	[.code_], edx
385
	mov	edx, [eax]
386
	shr	edx, .kNumMoveBits
387
	sub	[eax], edx
388
	stc
389
	jmp	.n
390
 
391
.RangeDecoderDecodeDirectBits:
392
; in: ecx=numTotalBits
393
; out: eax=result; destroys edx
394
	xor	eax, eax
395
.l:
396
	shr	[.range], 1
397
	shl	eax, 1
398
	mov	edx, [.code_]
399
	sub	edx, [.range]
400
	jb	@f
401
	mov	[.code_], edx
402
	or	eax, 1
403
@@:
404
	cmp	[.range], .kTopValue
405
	jae	@f
406
	shl	[.range], 8
407
	shl	[.code_], 8
408
	push	eax
409
	lodsb
410
	mov	byte [.code_], al
411
	pop	eax
412
@@:
413
	loop	.l
414
	ret
415
 
416
.LzmaLiteralDecode:
417
; in: eax->probs
418
; out: al=byte; destroys edx
419
	push	ecx
420
	mov	ecx, 1
421
@@:
422
	push	eax
423
	lea	eax, [eax+ecx*4]
424
	call	.RangeDecoderBitDecode
425
	pop	eax
426
	adc	cl, cl
427
	jnc	@b
428
.LzmaLiteralDecode.ret:
429
	mov	al, cl
430
	pop	ecx
431
	ret
432
.LzmaLiteralDecodeMatch:
433
; in: eax->probs, dl=matchByte
434
; out: al=byte; destroys edx
435
	push	ecx
436
	mov	ecx, 1
437
.LzmaLiteralDecodeMatch.1:
438
	add	dl, dl
439
	setc	ch
440
	push	eax
441
	lea	eax, [eax+ecx*4+0x100*4]
442
	call	.RangeDecoderBitDecode
443
	pop	eax
444
	adc	cl, cl
445
	jc	.LzmaLiteralDecode.ret
446
	xor	ch, cl
447
	test	ch, 1
448
	mov	ch, 0
449
	jnz	@b
450
	jmp	.LzmaLiteralDecodeMatch.1
451
 
452
.LzmaLenDecode:
453
; in: eax->prob, edx=posState
454
; out: ecx=len
455
	push	eax
456
	add	eax, .LenChoice*4
457
	call	.RangeDecoderBitDecode
458
	pop	eax
459
	jnc	.0
460
	push	eax
461
	add	eax, .LenChoice2*4
462
	call	.RangeDecoderBitDecode
463
	pop	eax
464
	jc	@f
465
	mov	ecx, .kLenNumMidBits
466
	shl	edx, cl
467
	lea	eax, [eax + .LenMid*4 + edx*4]
468
	call	.RangeDecoderBitTreeDecode
469
	add	ecx, .kLenNumLowSymbols
470
	ret
471
@@:
472
	add	eax, .LenHigh*4
473
	mov	ecx, .kLenNumHighBits
474
	call	.RangeDecoderBitTreeDecode
475
	add	ecx, .kLenNumLowSymbols + .kLenNumMidSymbols
476
	ret
477
.0:
478
	mov	ecx, .kLenNumLowBits
479
	shl	edx, cl
480
	lea	eax, [eax + .LenLow*4 + edx*4]
481
.RangeDecoderBitTreeDecode:
482
; in: eax->probs,ecx=numLevels
483
; out: ecx=length; destroys edx
484
	push	ebx
485
	mov	edx, 1
486
	mov	ebx, edx
487
@@:
488
	push	eax
489
	lea	eax, [eax+edx*4]
490
	call	.RangeDecoderBitDecode
491
	pop	eax
492
	adc	dl, dl
493
	add	bl, bl
494
	loop	@b
495
	sub	dl, bl
496
	pop	ebx
497
	mov	ecx, edx
498
	ret
499
.RangeDecoderReverseBitTreeDecode:
500
; in: eax->probs,ecx=numLevels
501
; out: ecx=length; destroys edx
502
	push	ebx ecx
503
	mov	edx, 1
504
	xor	ebx, ebx
505
@@:
506
	push	eax
507
	lea	eax, [eax+edx*4]
508
	call	.RangeDecoderBitDecode
509
	lahf
510
	adc	edx, edx
511
	sahf
512
	rcr	ebx, 1
513
	pop	eax
514
	loop	@b
515
	pop	ecx
516
	rol	ebx, cl
517
	mov	ecx, ebx
518
	pop	ebx
519
	ret
520
 
521
section ".bss" data readable writeable align 16
522
 
523
unpack.p        rd (unpack.LZMA_BASE_SIZE+(unpack.LZMA_LIT_SIZE shl (unpack.lc+unpack.lp)))*2
524
 
525
align 4
526
unpack.code_	dd	?
527
unpack.range	dd	?
528
unpack.rep0	dd	?
529
unpack.rep1	dd	?
530
unpack.rep2	dd	?
531
unpack.rep3	dd	?
532
unpack.previousByte db      ?