wok-next view memtest/stuff/unlzma.S @ rev 13287

memtest: lzma compression
author Pascal Bellard <pascal.bellard@slitaz.org>
date Sun Aug 26 00:21:22 2012 +0200 (2012-08-26)
parents
children e76c37f7bfe6
line source
1 // #define RC_NORMALIZE if (Range < kTopValue) { Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
2 //
3 // #define IfBit0(p) RC_NORMALIZE; bound = (Range >> kNumBitModelTotalBits) * *(p); if (Code < bound)
4 // #define UpdateBit0(p) Range = bound; *(p) += (kBitModelTotal - *(p)) >> kNumMoveBits;
5 // #define UpdateBit1(p) Range -= bound; Code -= bound; *(p) -= (*(p)) >> kNumMoveBits;
6 //
7 //#define RC_GET_BIT2(p, mi, A0, A1) IfBit0(p) \
8 // { UpdateBit0(p); mi <<= 1; A0; } else \
9 // { UpdateBit1(p); mi = (mi + mi) + 1; A1; }
10 //
11 // #define RC_GET_BIT(p, mi) RC_GET_BIT2(p, mi, ; , ;)
12 //
13 // #define RangeDecoderBitTreeDecode(probs, numLevels, res) \
14 // { int i = numLevels; res = 1; \
15 // do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0); \
16 // res -= (1 << numLevels); }
17 /*
18 * Compression with : lzma e src dst -eos -pb2 -lp0 -lc3
19 */
21 #define PROP_PB 2
22 #define PROP_LP 0
23 #define PROP_LC 3
24 #define PROPS (PROP_LC+(PROP_LP*9)+(PROP_PB*45))
26 // static const Byte *Buffer;
27 // static UInt32 bound, Code, Range;
29 /*
30 * Buffer register DS:SI
31 * all var based ws=ss:bp
32 */
34 rep0 = -4 // long
35 rep1 = rep0-4 // long
36 rep2 = rep0-8 // long
37 rep3 = rep0-12 // long
38 state = -17 // byte, 0..11
39 posState = state-1 // byte, 0..15
40 posState2 = posState-1 // byte, 0..15
41 scratched = rep0-16 // byte = 1
42 Code = -24 // long
43 outStream = -28 // long
44 nowPos = outStream // long
45 Range = Code-8 // long
46 #define LOCALS 32
48 // int LzmaDecode(CLzmaDecoderState *vs,
49 // const unsigned char *inStream,
50 // unsigned char *outStream)
51 // {
52 // CProb *p = vs->Probs;
53 // SizeT nowPos = 0;
54 // #define posStateMask = (1 << (vs->Properties.pb)) - 1;
55 // #define literalPosMask = (1 << (vs->Properties.lp)) - 1;
56 // int lc = vs->Properties.lc, state = 0, len = 0;
57 // UInt32 rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
58 //
59 // {
60 // UInt32 i, numProbs = Literal /*1846*/
61 // + ((UInt32)LZMA_LIT_SIZE /*768*/ << (lc + vs->Properties.lp));
62 // for (i = 0; i < numProbs; i++) p[i] = kBitModelTotal /*2048*/ >> 1;
64 #define WS (1846+(768<<(PROP_LC+PROP_LP)))
65 #if (WS+WS+LOCALS) >= 65000
66 /* MAX WS = (1846+(768<<(8+4))) > 3MB! */
67 #error invalid (lc,lp,pb) : out of memory
68 #endif
70 ws1 = WS
71 ws2 = ws1*2
72 ws = ws2+LOCALS+15
74 #ifndef FLAT32
75 #define AX %ax
76 #define BX %bx
77 #define CX %cx
78 #define DX %dx
79 #define SI %si
80 #define DI %di
81 #define BP %bp
82 #define SP %sp
83 #define CWD cwd
84 #else
85 #define AX %eax
86 #define BX %ebx
87 #define CX %ecx
88 #define DX %edx
89 #define SI %esi
90 #define DI %edi
91 #define BP %ebp
92 #define SP %esp
93 #define CWD cdq
94 #endif
95 /*
96 * LzmaDecode:
97 #ifndef FLAT32
98 * input ds:si=inStream, es:di=outStream
99 * output outStream[], ds:si, es:di
100 .code 16
101 #else
102 * input esi=inStream, edi=outStream
103 * output outStream[], esi, edi
104 .code 32
105 #endif
106 */
108 mov $ws1, CX
109 lzd1:
110 pushw $2048/2
111 loop lzd1
112 mov SP, BP
113 movb $((LOCALS+3)/4)*2, %cl
114 initlocals:
115 pushl $1
116 loop initlocals
118 #ifndef FLAT32
119 movb $4, %cl
120 movw %es, %bx
121 shrw %cl, %bx
122 movw %es, %dx
123 shlw %cl, %dx
124 addw %dx, %di
125 movw %di, outStream(%bp)
126 adcb %bh, outStream+2(%bp)
127 incw %cx
128 #else
129 movb $5, %cl
130 movl %edi, outStream(%ebp)
131 #endif
133 // Byte previousByte = 0;
134 xor BX, BX
136 // #define RC_INIT(buffer)
137 // Buffer = buffer; Code = 0; Range = 0xFFFFFFFF;
138 // { int i; for(i=0; i<5; i++) { Code = (Code<<8) | RC_READ_BYTE; }}
139 // }
140 // RC_INIT(inStream);
142 add $13, SI // skip header
143 setrep:
144 call RC_LOAD_BYTE
145 decb Range(BP)
146 loop setrep
148 lzdmainlp:
149 // while(1) {
150 // CProb *prob;
151 // int posState = (int)((nowPos) & posStateMask);
152 //
153 // prob = p + IsMatch /*0*/ + (state << kNumPosBitsMax /*4*/) + posState;
154 // if (Bit0(prob)) { /* char */
156 xor DX, DX
157 call Bit1state // Bit1(dx + (state << kNumPosBitsMax /*4*/) + posState)
158 mov $state, DI
159 jc lzdstring
161 // prob = p + Literal /*1846*/ + (LZMA_LIT_SIZE /*768*/ *
162 // ((((nowPos) & literalPosMask) << lc) + (previousByte >> (8 - lc))));
164 #if PROP_LC != 0
165 shrb $8-PROP_LC, %bl
166 #endif
168 #if PROP_LP != 0
169 movb posState2(BP), %dl
170 shl $PROP_LC, DX
171 movb $0, %bh
172 add BX, DX
173 #endif
175 movb $3, %ah
176 mul BX // dx = 3*bh
177 add $1846, AX
179 // int symbol = 1;
181 CWD
182 inc DX // symbol = 1
183 xchg AX, CX // save prob
185 // if (state >= kNumLitStates /*7*/) { /* previous was string */
186 // if (state < 4) state = 0;
188 lzd6z:
189 subb $3, (BP, DI)
191 // if (state < 4) state = 0;
193 jnc lzd6
194 movb %dh, (BP, DI) // %dh = 0
196 lzd6:
197 // else if (state < 10) state -= 3;
199 cmpb $10-3, (BP, DI)
201 // else state -= 6;
203 jnb lzd6z
204 cmpb $7-3-1, (BP, DI)
205 jbe lzd3
207 // int matchByte = outStream[nowPos - rep0];
209 call DicoRep02ESDI // %bl = outStream[nowPos - rep0];
211 // do {
212 // int bit;
213 // CProb *probLit;
214 // matchByte <<= 1; bit = (matchByte & 0x100);
216 movb $1, %bh
217 lzd4:
218 shlb $1, %bl // matchByte <<= 1
219 sbb DI, DI // save bit=C
221 // probLit = prob + 0x100 + bit + symbol;
223 mov CX, AX // restore prob
224 adcb %bh, %ah // + bit + 0x100
226 // RC_GET_BIT2(probLit, symbol, if (bit) break, if (!bit) break)
228 call Bit1axdx // C,%ax = Bit1(prob+%ax)
229 rclb $1, %dl // symbol <<= 1; symbol |= C
230 jc lzd5 // if symbol >= 0x100
231 cmp DI, AX
232 jz lzd4 // if bit == Bit1(prob+%ax)
234 // } while (symbol < 0x100);
235 // }
236 lzd3:
237 // while (symbol < 0x100) {
238 // CProb *probLit = prob + symbol;
239 // RC_GET_BIT(probLit, symbol)
240 // }
242 xor BX, BX
243 jmp lzd4
244 lzd5:
246 // outStream[nowPos++] = previousByte = (Byte)symbol;
248 xchg AX, DX
249 call outchar // %bl = outStream[nowPos++] = %al;
250 jmp lzdmainlp
252 // }
254 lzdstring:
255 mov $1, CX
257 // else { /* string */
258 // prob = p + IsRep /*192*/ + state;
260 movb $192, %dl
261 addb (BP, DI), %dl
262 mov $rep0, DI
264 // if (Bit0(prob)) {
266 call Bit1dx // Bit1(prob)
267 jc lzd8
269 // rep3 = rep2; rep2 = rep1; rep1 = rep0;
270 // state = (state < kNumLitStates /*7*/) ? 0 : 3;
272 stc
274 // prob = p + LenCoder /*818*/;
276 mov $818, DX
278 // }
280 jmp lzd11a
282 // else {
283 lzd8:
284 // prob += kNumStates /*12*/;
285 // if (Bit0(prob)) {
286 call Bit1dx12 // prob += 12; Bit1(prob)
287 jc lzd11
288 // prob = p + IsRep0Long /*240*/ + (state << kNumPosBitsMax /*4*/)
289 // + posState;
290 movb $240, %dl // dh=0
292 // if (Bit0(prob)) {
294 call Bit1state // Bit1(dx + (state << kNumPosBitsMax /*4*/) + posState)
295 jc lzd12
297 // // if (nowPos == 0) return LZMA_RESULT_DATA_ERROR;
298 // state = (state < kNumLitStates /*7*/) ? 9 : 11;
300 movb $9, %dl
302 // len++; goto string;
303 jmp lzd13string // ax = 0
304 // }
305 // }
306 // else {
307 lzd11:
308 // UInt32 distance = rep1;
309 // prob += kNumStates /*12*/;
310 // if (!Bit0(prob)) {
312 call Bit1dx12 // prob += 12; Bit1(prob)
313 jnc lzd11z
315 // prob += kNumStates /*12*/;
316 // if (Bit0(prob)) distance = rep2;
318 call Bit1dx12 // prob += 12; Bit1(prob)
319 lzd11a:
320 adcb %cl, %cl
322 // else { distance = rep3; rep3 = rep2; }
323 // rep2 = rep1;
324 // }
325 // rep1 = rep0; rep0 = distance;
327 lzd11z:
328 shl $2, CX // 8->32 bits
329 sub CX, DI // &rep[cx]
330 movl (BP, DI), %eax
331 rotreplp:
332 movb 4(BP, DI), %bl
333 movb %bl, (BP, DI)
334 inc DI
335 loop rotreplp
336 testb %dh, %dh
337 jnz lzd10
338 movl %eax, (BP, DI)
340 // }
341 lzd12:
342 // state = (state < kNumLitStates /*7*/) ? 8 : 11;
344 movb $0x08, %cl
346 // prob = p + RepLenCoder /*1332*/;
348 mov $1332, DX
350 // }
351 lzd10:
352 push CX // CX = 0
354 // { /* get len */
355 // int numBits, offset;
356 // CProb *probLen = prob + LenChoice /*0*/;
357 // numBits = kLenNumLowBits /*3*/;
359 movb $8, %cl // numBits : 3,3,8
361 // if (Bit0(probLen)) {
363 call Bit1dx // Bit1(prob)
364 xchg AX, BX
365 inc DX
366 jnc lzd15 // bx=0
368 // probLen = prob + LenLow/*2*/ + (posState << kLenNumLowBits/*3*/);
369 // offset = 0;
370 // }
371 // else {
372 // probLen = prob + LenChoice2 /*1*/;
374 call Bit1dx // Bit1(prob)
375 add AX, BX
377 #if PROP_PB != 0
378 inc AX // ah=0
379 #endif
380 jc lzd16 // %ax=0, %bx=-2
381 lzd15:
382 #if PROP_PB != 0
383 movb $8, %al
384 mulb posState(BP)
385 #endif
387 // if (Bit0(probLen)) {
388 // probLen = prob + LenMid/*130*/ + (posState << kLenNumMidBits/*3*/);
390 movb $3, %cl // numBits : 3,3,8
391 lzd16:
392 #if PROP_PB != 0
393 add $2-128-1, AX // probLen : 2,130,258
394 #else
395 mov $2-128-1, AX // probLen : 2,130,258
396 #endif
397 add DX, AX
398 mov $-8+1, DX // offset : 0,8,16
399 lzdargslp:
400 add $8, DX
401 add $128, AX
402 inc BX
403 jle lzdargslp // leave with bx=1
405 // offset = kLenNumLowSymbols /*8*/;
406 // //numBits = kLenNumMidBits /*3*/;
407 // }
408 // else {
409 // probLen = prob + LenHigh /*258*/;
410 // offset = kLenNumLowSymbols /*8*/ + kLenNumMidSymbols /*8*/;
411 // numBits = kLenNumHighBits /*8*/;
412 // }
413 // }
414 // RangeDecoderBitTreeDecode(probLen, numBits, len); len += offset;
416 push DX
417 call RangeDecoder // %ax=probs, %cx=numLevels, %ax=res
418 pop DX
419 add DX, AX // offset
420 pop DX // 0
421 lzd13string:
422 push AX
424 // state = (state < kNumLitStates /*7*/) ? dl : dl|3;
426 movb $7, %cl
427 cmpb %cl, state(BP)
428 jb new_state
429 orb $3, %dl
430 new_state:
431 movb %dl, state(BP)
433 // } /* get len */
434 // if (state < 4) {
436 cmpb $4-1, %dl
437 ja lzd19
439 // int posSlot;
440 // state += kNumLitStates /*7*/;
442 addb %cl, state(BP)
444 // prob = p + PosSlot /*432*/ + (((len < kNumLenToPosStates /*4*/) ?
445 // len : kNumLenToPosStates - 1) << kNumPosSlotBits /*6*/);
447 cmp $4+1, AX
448 jb lzd21
449 mov $3+1, AX
450 //??movb $3+1, %al
452 lzd21:
454 dec CX // cx = 6
455 shl %cl, AX
456 add $432-64, AX
458 // RangeDecoderBitTreeDecode(prob, kNumPosSlotBits /*6*/, posSlot);
460 call RangeDecoder // %ax=probs, %cx=numLevels, %ax=res
462 // if (posSlot >= kStartPosModelIndex /*4*/) {
463 // int numDirectBits = ((posSlot >> 1) - 1);
465 #ifndef FLAT32
466 movw %cx, 2(%bp, %di) // %cx = 0
467 #endif
468 mov AX, (BP, DI)
469 mov AX, CX
470 shrw $1, CX
471 dec CX
472 cmpb $4, %al
473 jb lzd22
475 // rep0 = (2 | ((UInt32)posSlot & 1));
477 andb %bl, (BP, DI) // %bx=1
478 orb $2, (BP, DI)
480 // if (posSlot < kEndPosModelIndex /*14*/) {
482 cmpb $14, %al
483 jnb lzd23
485 // rep0 <<= numDirectBits;
487 neg AX
488 shll %cl, (BP, DI)
489 add (BP, DI), AX
491 // prob = p + SpecPos /*688*/ + rep0 - posSlot - 1;
493 add $687, AX
494 jmp lzd24
496 // }
497 // else {
498 lzd23:
499 // numDirectBits -= kNumAlignBits /*4*/;
500 // do {
501 // RC_NORMALIZE; Range >>= 1; rep0 <<= 1;
502 // if (Code >= Range) { Code -= Range; rep0 |= 1; }
504 lzd23z:
505 call RC_NORMALIZE
506 shrl $1, Range(BP)
507 movl Range(BP), %eax
508 cmpl Code(BP), %eax
509 ja lzd25
510 subl %eax, Code(BP)
511 stc
512 lzd25:
513 rcll $1, (BP, DI)
515 // } while (--numDirectBits != 0);
517 cmp $4+1, CX
518 loopne lzd23z
520 // prob = p + Align /* 802 */; numDirectBits = kNumAlignBits /*4*/;
521 // rep0 <<= numDirectBits;
523 shll %cl, (BP, DI)
524 mov $802, AX
525 // }
527 lzd24:
528 call RangeDecoder // %ax=probs, %cx=numLevels, %ax=res
530 // {
531 // int i = 1, mi = 1;
532 // do {
533 // CProb *prob3 = prob + mi;
534 // RC_GET_BIT2(prob3, mi, ; , rep0 |= i);
536 orb %dh, (BP, DI) // update rep0 with DirectBits
538 // i <<= 1;
539 // } while(--numDirectBits != 0);
540 // }
541 // } else rep0 = posSlot;
542 lzd22:
543 // if (++rep0 == (UInt32)(0)) break; /* EOF */
545 incl (BP, DI)
547 lzd19:
548 pop CX
549 jz lzdone
551 // }
552 // len += kMatchMinLen;/*2*/
554 inc CX
556 // string: // if (rep0 > nowPos) return LZMA_RESULT_DATA_ERROR;
557 // do {
558 lzd13z:
559 // previousByte = outStream[nowPos - rep0];
560 // outStream[nowPos++] = previousByte;
562 call outcharDico // %bl = outStream[nowPos++] = outStream[nowPos - rep0]
564 // } while(--len != 0);
566 loop lzd13z
568 // } /* char/string */
569 // }
571 jmp lzdmainlp
573 lzdone:
574 // //RC_NORMALIZE;
575 // //*inSizeProcessed = (SizeT)(Buffer - inStream); *outSizeProcessed = nowPos;
576 // return LZMA_RESULT_OK;
577 call Dico2ESDI // set es & di (rep0 = 0)
578 lea ws2(BP), SP // dealloc
579 ret
580 // }
582 // al = outStream[nowPos - rep0];
584 /*
585 * output es:di, al
586 * scratch bh, cl, flags
587 */
589 DicoRep02ESDI:
590 stc
592 // bl = outStream[nowPos];
594 /*
595 * output es:di, bl
596 * scratch bh, cl, flags
597 */
599 Dico2ESDI:
600 #ifndef FLAT32
601 movl nowPos(%bp), %ebx
602 jnc Dico2ESDIz
603 subl rep0(%bp), %ebx
604 Dico2ESDIz:
605 movw %bx, %di
606 xorw %bx, %bx
607 shrl $4, %ebx
608 movw %bx, %es
609 movb %es:(%di), %bl
610 #else
611 movl nowPos(%bp), %edi
612 jnc Dico2ESDIz
613 subl rep0(%bp), %edi
614 Dico2ESDIz:
615 movb (%edi), %bl
616 #endif
617 ret
619 outcharDico:
621 // bl = outStream[nowPos++] = outStream[nowPos - rep0]
623 /*
624 * output es:di, bl
625 * update nowPos
626 * scratch ax, dx, bh, cl, flags
627 */
629 call DicoRep02ESDI // %bl = outStream[nowPos - rep0]
630 xchg AX, BX
631 outchar:
633 // bl = outStream[nowPos++] = previousByte = al;
635 /*
636 * output bl
637 * update nowPos
638 * scratch ax, dx, bh, di, cl, flags
639 */
641 clc
642 call Dico2ESDI
643 stosb
644 xchg AX, BX // previous byte
646 // int posState = (int)((nowPos) & posStateMask);
648 #if PROP_PB != 0 && PROP_LP != 0
649 addw $0x0101, posState2(BP)
650 andb $(((1 << PROP_PB) -1)<<8)+((1 << PROP_LP) -1), posState2(BP)
651 #else
652 # if PROP_PB != 0
653 incb posState(BP)
654 andb $((1 << PROP_PB) -1), posState(BP)
655 # endif
656 # if PROP_LP != 0
657 incb posState2(BP)
658 andb $((1 << PROP_LP) -1), posState2(BP)
659 # endif
660 #endif
661 incl nowPos(BP)
662 ret
664 //
665 // #define RC_NORMALIZE if (Range < kTopValue)
666 // { Range <<= 8; Code = (Code << 8) | RC_READ_BYTE; }
668 /*
669 * update Range, Code, ds:si
670 * scratch flags
671 */
673 RC_NORMALIZE:
674 cmpb $0, Range+3(BP)
675 jne RC_NORMALIZE_1
676 RC_LOAD_BYTE:
677 push AX
678 shll $8, Range(BP)
679 shll $8, Code(BP)
680 #ifndef FLAT32
681 testw %si, %si
682 jns RC_READ_BYTE
683 movw %ds, %ax
684 incw %ax
685 movw %ax, %ds
686 addw $-16, %si
687 RC_READ_BYTE:
688 #endif
689 lodsb
690 movb %al, Code(BP)
691 pop AX
692 RC_NORMALIZE_1:
693 ret
695 // Bit1(dx + (state << kNumPosBitsMax /*4*/) + posState)
697 Bit1state:
698 movb $16, %al
699 mulb state(BP)
700 # if PROP_PB != 0
701 addb posState(BP), %al
702 # endif
703 Bit1axdx:
704 add DX, AX
705 jmp Bit1
707 // prob += 12; Bit1(prob)
709 Bit1dx12:
710 add $12, DX
711 Bit1dx:
712 mov DX, AX
714 // static int Bit1(CProb *p)
716 Bit1:
717 /*
718 * input ax=p
719 * output C, ax
720 * update bound, Range, Code, ds:si
721 * scratch flags
722 */
724 // {
725 // RC_NORMALIZE;
727 call RC_NORMALIZE // kill %ax, update %si
729 pushal // FIXME pushaw?
731 xchg AX, DI
732 add DI, DI // short *
735 // bound = (Range>>kNumBitModelTotalBits /*11*/) * *(p);
737 movl Range(BP), %eax
738 shrl $11, %eax
739 movzwl (BP, DI), %edx
740 mull %edx
742 // if (Code < bound) {
744 cmpl Code(BP), %eax
745 jbe Bit1_1
747 // Range = bound;
749 movl %eax, Range(BP)
751 // *(p) += (kBitModelTotal /*2048*/ - *(p)) >> kNumMoveBits /*5*/;
753 movw $2048, %ax
755 // return 0;
757 jmp Bit1_2
759 // }
760 // else {
762 Bit1_1:
764 // Range -= bound; Code -= bound;
766 subl %eax, Range(BP)
767 subl %eax, Code(BP)
769 // *(p) -= (*(p)) >> kNumMoveBits /*5*/;
771 movw $31, %ax
773 // return 1;
775 stc
776 Bit1_2:
777 pushf
778 subw (BP, DI), %ax
779 sarw $5, %ax
780 addw %ax, (BP, DI)
781 popf
782 popal // FIXME popaw?
783 sbb AX, AX
785 // }
786 // }
788 ret
790 RangeDecoder:
792 /*
793 * input ax=probs cx=numLevels (< 8) bx=1
794 * output ax=res (backward), dh (forward)
795 * update bound, Range, Code, ds:si
796 * scratch flags, cx=0, dl
797 */
799 push BX
801 // { int i = numLevels; res = 1;
802 mov BX, DX // res = 1
804 // do { CProb *p = probs + res; RC_GET_BIT(p, res) } while(--i != 0);
806 RangeDecoder_1:
807 push AX
808 call Bit1axdx // C,%ax = Bit1(prob+%ax)
809 rclb $1, %dl // res <<= 1; res |= C
810 andb %bl, %al // current bit
811 orb %al, %bh // store in bh
812 shlb $1, %bl // update max
813 pop AX
814 loop RangeDecoder_1
816 // res -= (1 << numLevels); }
818 xchg AX, BX // move bh to dh
819 xchg AX, DX // and dl to al
820 sub %dl, %al // sub max
821 pop BX
822 ret