Subversion Repositories Kolibri OS

Rev

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

  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      ?
  533.